sandbox-agent/research/acp/missing-features-spec/07-session-termination.md
2026-02-11 07:57:02 -08:00

123 lines
3.8 KiB
Markdown

# Feature 7: Session Termination
**Implementation approach:** ACP extension, referencing existing ACP RFD
## Summary
v1 had explicit session termination (`POST /v1/sessions/{id}/terminate`). v1 only has `session/cancel` (turn cancellation, not session kill) and `DELETE /v1/rpc` (connection close, not session termination). Need explicit session destroy/terminate semantics.
## Current v1 State
- `session/cancel` — cancels an in-flight prompt turn only
- `DELETE /v1/rpc` — closes the HTTP connection, does **not** terminate the session
- `_sandboxagent/session/detach` — detaches a session from a connection (multi-client visibility)
- No session termination/deletion exists
- `rfds-vs-extensions.md`: "Session Termination: Not covered by ACP. Only implement if product explicitly requires termination semantics beyond session/cancel"
- `extensibility-status.md`: Documents `_sandboxagent/session/terminate` as proposed but not implemented
## v1 Implementation
### HTTP Endpoint
```
POST /v1/sessions/{id}/terminate
```
### Handler (from `router.rs`)
The terminate handler:
1. Looked up the session by ID
2. Killed the agent subprocess (SIGTERM then SIGKILL after grace period)
3. Emitted a `session.ended` event with `reason: Terminated, terminated_by: Daemon`
4. Cleaned up session state
### v1 Types
```rust
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
pub struct SessionEndedData {
pub reason: SessionEndReason,
pub terminated_by: TerminatedBy,
pub message: Option<String>,
pub exit_code: Option<i32>,
pub stderr: Option<StderrOutput>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum SessionEndReason {
Completed,
Error,
Terminated,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum TerminatedBy {
Agent,
Daemon,
}
```
## ACP RFD Reference
Per `~/misc/acp-docs/`, session termination is listed as an RFD topic. The existing ACP spec does not define a `session/terminate` or `session/delete` method.
## Implementation Plan
### ACP Extension Method
```
_sandboxagent/session/terminate
```
Client -> Runtime request:
```json
{
"jsonrpc": "2.0",
"id": "t-1",
"method": "_sandboxagent/session/terminate",
"params": {
"sessionId": "session-uuid"
}
}
```
Response:
```json
{
"jsonrpc": "2.0",
"id": "t-1",
"result": {
"terminated": true,
"reason": "terminated",
"terminatedBy": "daemon"
}
}
```
### Behavior
1. Client sends `_sandboxagent/session/terminate` request
2. Runtime identifies the session and its owning agent process
3. For shared-process agents (Codex, OpenCode): send a cancel/terminate signal to the agent process for that specific session
4. For per-turn subprocess agents (Claude, Amp): kill the subprocess if running, mark session as terminated
5. Emit `_sandboxagent/session/ended` to all connected clients watching that session
6. Method is idempotent: repeated calls on an already-ended session return success without side effects
### Files to Modify
| File | Change |
|------|--------|
| `server/packages/sandbox-agent/src/acp_runtime/mod.rs` | Add `_sandboxagent/session/terminate` handler; add session removal from registry; add process kill logic |
| `server/packages/sandbox-agent/src/acp_runtime/mock.rs` | Add mock terminate support |
| `sdks/typescript/src/client.ts` | Add `terminateSession(sessionId)` method |
| `server/packages/sandbox-agent/tests/v1_api.rs` | Add session termination test |
### Docs to Update
| Doc | Change |
|-----|--------|
| `docs/sdks/typescript.mdx` | Document `terminateSession` method |
| `research/acp/spec.md` | Add `_sandboxagent/session/terminate` to extension methods list |
| `research/acp/rfds-vs-extensions.md` | Update session termination row |