* Shared setup for `session/load` and `session/resume`: gates auth, * checks the connection, resolves MCP servers, asks the harness to * resume the on-disk session, computes the current model/thinking * projection (with a resume-state fallback), constructs the * AcpSession, regis
(params: {
cwd: string;
sessionId: string;
mcpServers?: ReadonlyArray<McpServer>;
mode: 'load' | 'resume';
})
| 425 | * structured JSON-RPC failure rather than a generic internal error. |
| 426 | */ |
| 427 | private async setupSessionFromExisting(params: { |
| 428 | cwd: string; |
| 429 | sessionId: string; |
| 430 | mcpServers?: ReadonlyArray<McpServer>; |
| 431 | mode: 'load' | 'resume'; |
| 432 | }): Promise<{ |
| 433 | session: Session; |
| 434 | acpSession: AcpSession; |
| 435 | configOptions: SessionConfigOption[]; |
| 436 | }> { |
| 437 | if (!(await harnessIsAuthed(this.harness))) { |
| 438 | throw RequestError.authRequired(); |
| 439 | } |
| 440 | if (!this.conn) { |
| 441 | throw RequestError.internalError(undefined, 'AcpServer is missing its AgentSideConnection'); |
| 442 | } |
| 443 | // ACP `cwd` → SDK `workDir` for parity with `newSession`. The |
| 444 | // harness's `resumeSession` only takes `{ id }` today; the cwd |
| 445 | // arrives on the request for future validation but is not enforced |
| 446 | // here (the on-disk session already has its own workDir). Phase |
| 447 | // 10.1 also forwards `mcpServers` so a resumed session can pick up |
| 448 | // ACP-supplied MCP servers (matching `newSession` behaviour). Same |
| 449 | // `@ts-expect-error` boundary as `newSession` — the SDK's |
| 450 | // `resumeSession` spreads `input` so unknown fields ride to the |
| 451 | // kernel. |
| 452 | const mcpServers = acpMcpServersToConfigs(params.mcpServers); |
| 453 | const acpKaos = await this.maybeBuildAcpKaos(params.sessionId); |
| 454 | const persistenceKaos = acpKaos === undefined ? undefined : await this.ensureInnerKaos(); |
| 455 | let session: Session; |
| 456 | try { |
| 457 | session = await this.harness.resumeSession({ |
| 458 | id: params.sessionId, |
| 459 | kaos: acpKaos, |
| 460 | persistenceKaos, |
| 461 | sessionStartedProperties: { mode: params.mode }, |
| 462 | // @ts-expect-error — see block comment above; mcpServers is a |
| 463 | // kernel-only field that the SDK forwards via spread. |
| 464 | mcpServers, |
| 465 | }); |
| 466 | } catch (err) { |
| 467 | // Surface unknown-session as invalid_params so the JSON-RPC layer |
| 468 | // returns a structured failure rather than a generic internal |
| 469 | // error. Other errors propagate as-is. |
| 470 | const code = (err as { code?: string } | undefined)?.code; |
| 471 | if (code === 'session.not_found') { |
| 472 | throw RequestError.invalidParams( |
| 473 | { sessionId: params.sessionId }, |
| 474 | `Unknown sessionId: ${params.sessionId}`, |
| 475 | ); |
| 476 | } |
| 477 | throw err; |
| 478 | } |
| 479 | // Phase 14 (PLAN D11) — same `configOptions:` advertisement as |
| 480 | // `newSession`. `currentModeId` is `default` on every load (mode |
| 481 | // is session-scoped per PLAN D9); `currentModelId` is read from |
| 482 | // the resumed session's main-agent config when available so the |
| 483 | // dropdown's highlight matches the model the resumed turn will |
| 484 | // actually use — falling back to the harness-level default |
no test coverage detected