Skip to content

Session switch/fork/import

源码版本v0.73.1

AgentSessionRuntime is the outer wrapper around AgentSession, responsible for session replacement. Within a running process, the AgentSession instance can be swapped out multiple times: /new opens a new session, /resume switches to an old one, /fork branches off a message, /import brings in an external jsonl. Each replacement has to tear down the old session, create new services, rebind extensions, and restore event subscriptions. This file is the container for that replacement flow.

Responsibilities

  1. Hold the current session: the _session and _services fields store the live instances, exposed via session / services / cwd getters. See packages/coding-agent/src/core/agent-session-runtime.ts:67-97.
  2. new / switch / fork / import: four replacement methods. Each emits a before-event (extensions can cancel), then teardownCurrent, then apply of the new runtime. See packages/coding-agent/src/core/agent-session-runtime.ts:175-198, packages/coding-agent/src/core/agent-session-runtime.ts:200-232, packages/coding-agent/src/core/agent-session-runtime.ts:234-320, and packages/coding-agent/src/core/agent-session-runtime.ts:329-364.
  3. Event hooks: three extension events — session_before_switch / session_before_fork / session_shutdown — that extensions can cancel. See packages/coding-agent/src/core/agent-session-runtime.ts:115-147.
  4. Rebind callback: the host (InteractiveMode or rpc-mode) registers a setRebindSession callback that runs after session replacement to rebind extension UI and resubscribe to events. See packages/coding-agent/src/core/agent-session-runtime.ts:99-113 and packages/coding-agent/src/core/agent-session-runtime.ts:166-173.
  5. Factory reuse: the createRuntime closure is passed in when createAgentSessionRuntime runs and reused on every subsequent replacement, so cwd/agentDir/extension paths stay consistent. See packages/coding-agent/src/core/agent-session-runtime.ts:382-400.

Design Motivation

Why not just this.session = new AgentSession(...)? Because replacement involves three things: the old session has to emit a shutdown event so extensions can release resources; the new session has to load services from the same paths (settings, auth, resource loader); and the UI layer has to resubscribe to events and rebind extension command context. The order matters — extensions must receive shutdown before dispose, or they hold dangling references. The teardownCurrentapplyfinishSessionReplacement three-stage flow is a hard guarantee of that order.

The createRuntime factory reuse is also worth noting: re-resolving cwd, agentDir, and extension paths on every replacement is heavy and lets parameters drift. The closure captures the config parsed once at CLI time and reuses it, so extension paths don't suddenly go invalid after several /resumes.

Key Files

The three-stage replacement:

typescript
// packages/coding-agent/src/core/agent-session-runtime.ts:149-164
private async teardownCurrent(reason: SessionShutdownEvent["reason"], targetSessionFile?: string): Promise<void> {
	await emitSessionShutdownEvent(this.session.extensionRunner, {
		type: "session_shutdown",
		reason,
		targetSessionFile,
	});
	this.beforeSessionInvalidate?.();
	this.session.dispose();
}

private apply(result: CreateAgentSessionRuntimeResult): void {
	this._session = result.session;
	this._services = result.services;
	this._diagnostics = result.diagnostics;
	this._modelFallbackMessage = result.modelFallbackMessage;
}

When position: "at", fork takes the selected entry as the branch point; for before, it takes the parent entry and extracts the user message text to refill the editor:

typescript
// packages/coding-agent/src/core/agent-session-runtime.ts:251-258
if (position === "at") {
	targetLeafId = selectedEntry.id;
} else {
	if (selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
		throw new Error("Invalid entry ID for forking");
	}
	targetLeafId = selectedEntry.parentId;
	selectedText = extractUserMessageText(selectedEntry.message.content);
}

Data Flow

The unified flow for session replacement:

Edges and Failures

Summary

AgentSessionRuntime abstracts session replacement into a unified three-stage flow: teardown → apply → rebind. The four entry points (new/switch/fork/import) share the same teardown and factory closure; extensions can cancel via before-events. For the assembly factory internals, see createAgentSession Wiring; for the session being replaced, see AgentSession Orchestration Layer.