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
13 changes: 13 additions & 0 deletions packages/adapter-cli/src/generated/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,17 @@ export class CliAdapter implements EngineAdapter {
this.getVersion = this.getVersion.bind(this);
}

private withEngineTimeout(options: DispatchOptions): DispatchOptions {
// Honor the engine's declared timeout (slow coding-plan engines like zai set timeout=300) over a lower generic command default (orchestration uses 120s), so a slow engine isn't cut off mid-answer and lose its slot. Returns a NEW options object — never mutates the caller's, since callers may reuse/retry the same DispatchOptions.
const declared = Number((options.engine as any)?.timeout ?? 0);
if (declared > Number(options.timeout ?? 0)) {
return { ...options, timeout: declared };
}
return options;
}

async dispatch(options: DispatchOptions): Promise<DispatchResult> {
options = this.withEngineTimeout(options);
// Prefer CLI binary when available — API is fallback for binary-less engines
const binaryPath = options.engine.binary ? this.registry.findBinary(options.engine) : null;
if (!binaryPath) {
Expand Down Expand Up @@ -119,6 +129,7 @@ export class CliAdapter implements EngineAdapter {
}

async *dispatchStream(options: DispatchOptions): AsyncGenerator<string, DispatchResult, void> {
options = this.withEngineTimeout(options);
// workspace-pure isolation, resolved once for every dispatch path below.
const iso = computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd });
// Subscription pty path for claude — yields response deltas, returns final result.
Expand Down Expand Up @@ -215,6 +226,7 @@ export class CliAdapter implements EngineAdapter {
}

async dispatchAgent(options: DispatchOptions): Promise<AgentDispatchResult> {
options = this.withEngineTimeout(options);
// workspace-pure isolation, resolved once for every agent dispatch path below.
const iso = computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd });
// Subscription pty path for claude (agent mode: tools + bypassed perms).
Expand Down Expand Up @@ -371,6 +383,7 @@ export class CliAdapter implements EngineAdapter {
}

async *dispatchAgentStream(options: DispatchOptions): AsyncGenerator<string, AgentDispatchResult, void> {
options = this.withEngineTimeout(options);
// workspace-pure isolation, resolved once for every agent-stream path below.
const iso = computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd });
// Subscription pty path for claude (agent mode). Same diff capture as dispatchAgent.
Expand Down
12 changes: 12 additions & 0 deletions packages/adapter-cli/src/kern/adapter.kern
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,17 @@ service name=CliAdapter implements=EngineAdapter
assign target="this.isAvailable" value="this.isAvailable.bind(this)"
assign target="this.getVersion" value="this.getVersion.bind(this)"

method name=withEngineTimeout params="options:DispatchOptions" returns="DispatchOptions" private=true
handler lang="kern"
comment raw="// Honor the engine's declared timeout (slow coding-plan engines like zai set timeout=300) over a lower generic command default (orchestration uses 120s), so a slow engine isn't cut off mid-answer and lose its slot. Returns a NEW options object — never mutates the caller's, since callers may reuse/retry the same DispatchOptions."
let name=declared value="Number((options.engine as any)?.timeout ?? 0)"
if cond="declared > Number(options.timeout ?? 0)"
return value="{ ...options, timeout: declared }"
return value="options"

method name=dispatch params="options:DispatchOptions" returns="Promise<DispatchResult>" async=true
handler lang="kern"
assign target="options" value="this.withEngineTimeout(options)"
comment raw="// Prefer CLI binary when available — API is fallback for binary-less engines"
let name=binaryPath value="options.engine.binary ? this.registry.findBinary(options.engine) : null"
if cond="!binaryPath"
Expand Down Expand Up @@ -101,6 +110,7 @@ service name=CliAdapter implements=EngineAdapter

method name=dispatchStream params="options:DispatchOptions" returns="string, DispatchResult, void" async=true stream=true
handler <<<
options = this.withEngineTimeout(options);
// workspace-pure isolation, resolved once for every dispatch path below.
const iso = computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd });
// Subscription pty path for claude — yields response deltas, returns final result.
Expand Down Expand Up @@ -198,6 +208,7 @@ service name=CliAdapter implements=EngineAdapter

method name=dispatchAgent params="options:DispatchOptions" returns="Promise<AgentDispatchResult>" async=true
handler lang="kern"
assign target="options" value="this.withEngineTimeout(options)"
comment raw="// workspace-pure isolation, resolved once for every agent dispatch path below."
let name=iso value="computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd })"
comment raw="// Subscription pty path for claude (agent mode: tools + bypassed perms)."
Expand Down Expand Up @@ -333,6 +344,7 @@ service name=CliAdapter implements=EngineAdapter

method name=dispatchAgentStream params="options:DispatchOptions" returns="string, AgentDispatchResult, void" async=true stream=true
handler <<<
options = this.withEngineTimeout(options);
// workspace-pure isolation, resolved once for every agent-stream path below.
const iso = computeEngineIsolation(options.engine, { isolation: options.isolation, cwd: options.cwd });
// Subscription pty path for claude (agent mode). Same diff capture as dispatchAgent.
Expand Down