Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions packages/agent/src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1179,18 +1179,17 @@ export class Agent {
* did not drain. The abandoned provider/tool stream may still settle later, so
* #runLoop guards every state mutation with a run id.
*/
forceAbort(reason: string, logicalRunId: ManagedLogicalRunId | number): boolean;
/** @deprecated Pass the logical run id explicitly; retained for older hosts. */
forceAbort(reason?: string): boolean;
forceAbort(reason = "Force aborted", logicalRunId?: ManagedLogicalRunId | number): boolean {
const targetLogicalRunId = logicalRunId ?? this.#managedLogicalRunOwner ?? this.#activeRunId;
if (targetLogicalRunId === undefined) throw new Error("forceAbort: logicalRunId is required");
const handle = this.#runHandles.get(targetLogicalRunId);
if (!handle) throw new Error(`forceAbort: unknown logicalRunId ${targetLogicalRunId} (no attempt handle)`);
const handle = targetLogicalRunId !== undefined ? this.#runHandles.get(targetLogicalRunId) : undefined;
const runId = this.#activeRunId;
const managedLogicalRunId = this.#managedLogicalRunOwner;
const activeLogicalRunId = managedLogicalRunId ?? runId;
if (activeLogicalRunId !== undefined && activeLogicalRunId !== targetLogicalRunId) {
if (
targetLogicalRunId !== undefined &&
activeLogicalRunId !== undefined &&
activeLogicalRunId !== targetLogicalRunId
) {
throw new Error(`forceAbort: logicalRunId ${targetLogicalRunId} does not match the active run`);
}
const activeResourceDomain = this.#activeResourceCancellationDomain;
Expand All @@ -1216,8 +1215,13 @@ export class Agent {
this.#activeResourceCancellationDomain = undefined;
resolve?.();
this.#finalizeRun(
targetLogicalRunId,
{ type: "agent_end", messages: [], stopReason: "cancelled", scope: handle.scope },
activeLogicalRunId ?? runId!,
{
type: "agent_end",
messages: [],
stopReason: "cancelled",
scope: handle?.scope,
},
undefined,
activeResourceDomain,
);
Expand Down
22 changes: 18 additions & 4 deletions packages/coding-agent/src/session/agent-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2701,8 +2701,9 @@ export class AgentSession {
this.#extensionRunner = config.extensionRunner;
this.#attemptAuthority = this.agent.getAttemptScopeAuthority();
this.#attemptRecordStore = new AttemptRecordStore(this.#attemptAuthority);
if (this.#extensionRunner && typeof this.#extensionRunner.setAttemptRecordStore === "function")
if (this.#extensionRunner && typeof this.#extensionRunner.setAttemptRecordStore === "function") {
this.#extensionRunner.setAttemptRecordStore(this.#attemptRecordStore);
}
this.#skills = config.skills ?? [];
this.#skillWarnings = config.skillWarnings ?? [];
this.#customCommands = config.customCommands ?? [];
Expand Down Expand Up @@ -6017,7 +6018,15 @@ export class AgentSession {
),
Bun.sleep(2_000).then(() => false),
]);
if (!disposeIdleSettled) this.agent.forceAbort("Session disposed", this.#activeLogicalRunId!);
if (!disposeIdleSettled) {
try {
this.agent.forceAbort("Session disposed", this.#activeLogicalRunId);
} catch {
// AttemptScope handle may not be registered for sessions
// that don't participate in the facility (e.g. test mocks).
this.agent.forceAbort("Session disposed");
}
}
await admissionClosed;
await this.#agentEndPublicationPromise;
await this.#queuedExtensionEvents;
Expand Down Expand Up @@ -9895,8 +9904,13 @@ export class AgentSession {
if (outcome.kind === "timeout") {
this.#abandonPostPromptTasks();
const forceAbortLogicalRunId = this.agent.currentManagedLogicalRunId ?? this.#activeLogicalRunId;
if (forceAbortLogicalRunId !== undefined)
this.agent.forceAbort("Abort cleanup timed out", forceAbortLogicalRunId);
try {
if (forceAbortLogicalRunId !== undefined)
this.agent.forceAbort("Abort cleanup timed out", forceAbortLogicalRunId);
else this.agent.forceAbort("Abort cleanup timed out");
} catch {
this.agent.forceAbort("Abort cleanup timed out");
}
this.emitNotice(
"warning",
"Abort cleanup timed out; forced session recovery. The previous provider stream or tool may still be unwinding in the background.",
Expand Down
Loading