@titan-design/agent 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -104,8 +104,10 @@ with the total zeroed.
104
104
  ## Subagents and permissions
105
105
 
106
106
  `agents`, `mcpServers`, `hooks`, `allowedTools`, `disallowedTools`, `model`,
107
- `resumeSessionId` and `settingSources` pass straight through. Two defaults are
108
- chosen for headless safety:
107
+ `resumeSessionId` and `settingSources` pass straight through. So do `tools`,
108
+ the built-in tool set (`[]` runs with no tools, for a pure judgement call), and
109
+ `systemPrompt`, which replaces the Claude Code default prompt. Leaving either
110
+ unset keeps the SDK default. Two defaults are chosen for headless safety:
109
111
 
110
112
  - `permissionMode` defaults to `"dontAsk"`, so nothing runs that was not
111
113
  pre-approved.
@@ -120,8 +122,112 @@ says. Prefer `allowedTools` wildcards over a permissive mode.
120
122
  This package runs one session. It does not pool, schedule, or retry; that
121
123
  belongs to the workflow tier.
122
124
 
125
+ ## Explicit multi-harness contracts
126
+
127
+ `dispatchHarnessRun(request, adapter)` is the new, explicit contract for Claude
128
+ Code and Codex adapters. It does not replace or reroute `runAgent()`. Every request
129
+ has a discriminating `harness`, a fresh or resume target, and a required positive
130
+ finite `wallTimeMs`. Claude's Anthropic SDK fields live only under the
131
+ `claude-code` branch; Codex model, reasoning, sandbox, approval, and native JSON
132
+ Schema fields live only under the `codex` branch.
133
+
134
+ Optional limits name their unit (`usd`, `model_requests`, `agent_iterations`, or
135
+ `tokens`), scope (`execution` or `conversation`), and enforcement (`hard` or
136
+ `advisory`). These are not interchangeable: an agent iteration is not a model
137
+ request, and an estimated SDK dollar stop is not a hard financial cap.
138
+
139
+ Adapters supply a `HarnessCapabilityDescriptor` that marks every operation and
140
+ declared limit `supported`, `unsupported`, or `unverified`, with evidence or a
141
+ reason. Core declares no adapter capabilities itself. Before invoking an adapter,
142
+ the dispatcher checks the operation, resume identity, structured-output and
143
+ cancellation needs, caller requirements, mandatory hard execution deadline, and
144
+ all optional limits. Unsupported and unverified requirements return an
145
+ `unsupported_requirement` result with no adapter call.
146
+
147
+ Support for the hard `milliseconds` execution limit means the adapter can stop
148
+ the local execution at its deadline. It does not claim that a remote model request
149
+ has stopped unless the adapter separately reports verified cancellation support.
150
+ Normalized progress, results, usage measurements, execution identity, conversation
151
+ identity, and transcript source hints contain no harness-native event types.
152
+
153
+ ## Supervised Codex exec adapter
154
+
155
+ `createCodexExecAdapter({ auth: "cached-cli" })` runs the pinned ChatGPT desktop
156
+ Codex binary through `codex exec --json`. The caller must select a model and an
157
+ absolute working directory. Fresh runs persist a native thread; resumes always use
158
+ the supplied native thread ID and never `--last`. The adapter ignores user config,
159
+ strips API-key credentials from the child environment, accepts only the
160
+ noninteractive `never` approval policy, and leaves persistence enabled so
161
+ `@titan-design/session-read` can discover the rollout by thread ID and namespace.
162
+
163
+ The adapter checks `codex --version` before every launch. The mandatory wall deadline
164
+ covers that check, temporary output-schema setup, and the run itself. Timeout or
165
+ caller abort terminates the owned process group, then sends `SIGKILL` after the
166
+ configured grace period. JSONL output becomes normalized progress, conversation
167
+ identity, final text or locally validated structured output, and token usage with
168
+ Codex event provenance. Hard dollar, request, iteration, and token caps remain
169
+ unsupported and fail preflight before either version probing or process spawn.
170
+
171
+ A zero exit is successful only after Codex emits `turn.completed`. Its usage is a
172
+ turn snapshot: the adapter uses Codex's native turn ID when one is present and an
173
+ execution-correlated synthetic turn ID otherwise. It is never labeled as a
174
+ conversation total. If an abort or wall deadline stops the OS process without a
175
+ native terminal turn event, the result is `cancelled_unknown` and retains the
176
+ requested cause and process exit evidence. Temporary schema cleanup completes
177
+ before the terminal progress event, so cleanup failure cannot follow a reported
178
+ successful finish.
179
+
123
180
  ## Ending a run
124
181
 
125
182
  Every run ends cleanly. The inactivity watchdog resets on each streamed message
126
183
  and, like the caller's `AbortSignal`, ends the run through the SDK's
127
184
  `abortController` and then `query.close()`, so no CLI subprocess is left behind.
185
+
186
+ ## Bounded Claude adapter
187
+
188
+ `createClaudeCodeAdapter({ maxTurns, maxBudgetUsd, inactivityTimeoutMs?, deps? })`
189
+ wraps the existing `runAgent` in the common `HarnessAdapter<"claude-code">`
190
+ contract. Both native circuit breakers remain required. Every request also supplies
191
+ `wallTimeMs`; expiration aborts and closes the owned SDK query. A local stop cannot
192
+ prove that native execution was cancelled, so the durable dispatcher records an
193
+ unknown cancellation unless terminal evidence is available.
194
+
195
+ Fresh and resumed requests keep invocation identity separate from native session
196
+ identity. Native options, permission settings, MCP servers, schema validation, and
197
+ cached-auth handling flow through `runAgent`. Structured output remains validated
198
+ by the caller's Zod schema. SDK query usage is aggregated across its main, subagent, and internal model calls
199
+ into one turn-scoped snapshot with estimated cost. Multiple models yield a null
200
+ model label so their totals do not overwrite each other. Total input includes cache
201
+ reads and cache creation; those subset counters must not be added again.
202
+
203
+ The adapter does not translate SDK `maxTurns` into a generic model-request or
204
+ agent-iteration limit, or treat the SDK budget estimate as an exact monetary cap.
205
+ Generic optional limits remain unsupported until their semantics are verified.
206
+ No process reattachment, visible terminal, or semantic-interrupt capability is
207
+ claimed by this wrapper. Legacy `runAgent` callers retain their existing API.
208
+
209
+ ## Durable harness dispatch
210
+
211
+ `createDurableHarnessDispatcher(adapter, { ledger, supervisorId, leaseMs })`
212
+ wraps either harness adapter with an early durable acknowledgment and a completion
213
+ promise. Apply `executionLedgerMigration(version)` from
214
+ `@titan-design/agent-lifecycle` to the authoritative database before constructing
215
+ the ledger. Each dispatch requires caller-generated `executionId` and `requestKey`
216
+ values. The dispatcher commits `prepare` and `begin_dispatch` before calling the
217
+ adapter, renews its captured owner lease while the call is live, and commits the
218
+ terminal result before resolving completion.
219
+
220
+ `reconcile(executionId)` returns a live handle only in the same dispatcher instance
221
+ while its exact owner generation and lease remain valid. After restart it can read
222
+ back a durable terminal result. An expired record that never committed
223
+ `begin_dispatch` is closed as a retryable failure because the ledger proves the
224
+ adapter was not called. A missing record or any post-dispatch record without an
225
+ attachment handle returns unknown or recovery-required evidence and never
226
+ authorizes resubmission. The dispatcher does not infer liveness from a PID or a
227
+ transcript.
228
+
229
+ Cancellation intent is stored before the local abort signal fires. Without a
230
+ native terminal acknowledgment after a deadline or abort, the ledger records
231
+ `cancellation_unknown`. Lease-renewal, stale-owner, and local persistence failures
232
+ settle completion promptly even when the adapter ignores abort; they cannot write a
233
+ terminal result through a newer owner's fence. Durable results must be JSON-safe.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import { PermissionMode, AgentDefinition, McpServerConfig, HookEvent, HookCallbackMatcher, SettingSource, SDKMessage, ModelUsage, query, SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';
2
2
  import { ZodError, ZodType } from 'zod';
3
+ import { ConversationIdentity, ExecutionIdentity, UsageMeasurement, ExecutionRecord, ExecutionTerminal, AgentIdentity, ExecutionReconcileOutcome } from '@titan-design/agent-protocol';
4
+ import { ExecutionLedger } from '@titan-design/agent-lifecycle';
3
5
 
4
6
  /** Why a run ended without a usable answer. One kind per recovery strategy. */
5
7
  type AgentFailure = {
@@ -70,8 +72,12 @@ interface AgentRunConfig<T = string> {
70
72
  model?: string;
71
73
  /** Turns on the SDK's `json_schema` output format, which retries on its own until the answer validates. */
72
74
  outputSchema?: ZodType<T>;
75
+ /** The built-in tool set; `[]` runs with no tools at all. Omitted keeps the SDK default. */
76
+ tools?: string[];
73
77
  allowedTools?: string[];
74
78
  disallowedTools?: string[];
79
+ /** Replaces the SDK's default Claude Code system prompt. */
80
+ systemPrompt?: string;
75
81
  /** Defaults to `dontAsk`: nothing is pre-approved, so nothing runs unprompted. */
76
82
  permissionMode?: PermissionMode;
77
83
  resumeSessionId?: string;
@@ -115,6 +121,259 @@ interface AgentRunDeps {
115
121
  */
116
122
  declare function runAgent<T = string>(config: AgentRunConfig<T>, deps?: AgentRunDeps): Promise<AgentRunResult<T>>;
117
123
 
124
+ type Harness = "claude-code" | "codex";
125
+ declare const CODEX_SANDBOXES: readonly ["read-only", "workspace-write", "danger-full-access"];
126
+ declare const CODEX_APPROVAL_POLICIES: readonly ["untrusted", "on-failure", "on-request", "never"];
127
+ type CodexSandbox = (typeof CODEX_SANDBOXES)[number];
128
+ type CodexApprovalPolicy = (typeof CODEX_APPROVAL_POLICIES)[number];
129
+ declare const EXECUTION_CAPABILITIES: readonly ["fresh_run", "resume", "fork", "structured_output", "interactive_approvals", "external_cancellation", "semantic_interrupt", "active_turn_steering", "idle_turn_submission", "persisted_transcript", "process_reattachment", "token_reporting"];
130
+ type ExecutionCapability = (typeof EXECUTION_CAPABILITIES)[number];
131
+ type CapabilityAssessment = {
132
+ status: "supported";
133
+ evidence: string;
134
+ } | {
135
+ status: "unsupported" | "unverified";
136
+ reason: string;
137
+ };
138
+ type LimitUnit = "milliseconds" | "usd" | "model_requests" | "agent_iterations" | "tokens";
139
+ type OptionalLimitUnit = Exclude<LimitUnit, "milliseconds">;
140
+ type LimitScope = "execution" | "conversation";
141
+ type LimitEnforcement = "hard" | "advisory";
142
+ interface ExecutionLimit {
143
+ unit: OptionalLimitUnit;
144
+ value: number;
145
+ scope: LimitScope;
146
+ enforcement: LimitEnforcement;
147
+ }
148
+ interface LimitCapability {
149
+ unit: LimitUnit;
150
+ scope: LimitScope;
151
+ enforcement: LimitEnforcement;
152
+ assessment: CapabilityAssessment;
153
+ }
154
+ /** A factual report supplied by an adapter implementation, not a promise made by the core. */
155
+ interface HarnessCapabilityDescriptor<H extends Harness = Harness> {
156
+ harness: H;
157
+ adapter: {
158
+ name: string;
159
+ version: string;
160
+ };
161
+ capabilities: Record<ExecutionCapability, CapabilityAssessment>;
162
+ limits: readonly LimitCapability[];
163
+ }
164
+ type RunTarget = {
165
+ kind: "fresh";
166
+ namespace: string;
167
+ } | {
168
+ kind: "resume";
169
+ conversation: ConversationIdentity;
170
+ };
171
+ interface BoundedRunBase {
172
+ prompt: string;
173
+ cwd: string;
174
+ target: RunTarget;
175
+ /** Required hard deadline for this execution. Must be positive and finite. */
176
+ wallTimeMs: number;
177
+ limits?: readonly ExecutionLimit[];
178
+ requires?: readonly ExecutionCapability[];
179
+ signal?: AbortSignal;
180
+ onProgress?: (progress: HarnessRunProgress) => void;
181
+ }
182
+ /** Anthropic SDK configuration remains confined to the Claude Code branch. */
183
+ interface ClaudeCodeNativeOptions<T> {
184
+ model?: string;
185
+ outputSchema?: ZodType<T>;
186
+ allowedTools?: string[];
187
+ disallowedTools?: string[];
188
+ permissionMode?: PermissionMode;
189
+ agents?: Record<string, AgentDefinition>;
190
+ mcpServers?: Record<string, McpServerConfig>;
191
+ hooks?: Partial<Record<HookEvent, HookCallbackMatcher[]>>;
192
+ settingSources?: SettingSource[];
193
+ allowApiKeyBilling?: boolean;
194
+ }
195
+ interface CodexOutputSchema<T> {
196
+ jsonSchema: Record<string, unknown>;
197
+ /** Second validation boundary after Codex applies the native JSON Schema. */
198
+ parse(value: unknown): T;
199
+ }
200
+ interface CodexNativeOptions<T> {
201
+ model?: string;
202
+ /** Adapter validates model/version-specific values; core only requires a nonempty string. */
203
+ reasoningEffort?: string;
204
+ sandbox?: CodexSandbox;
205
+ approvalPolicy?: CodexApprovalPolicy;
206
+ outputSchema?: CodexOutputSchema<T>;
207
+ }
208
+ interface ClaudeCodeRunRequest<T = string> extends BoundedRunBase {
209
+ harness: "claude-code";
210
+ native?: ClaudeCodeNativeOptions<T>;
211
+ }
212
+ interface CodexRunRequest<T = string> extends BoundedRunBase {
213
+ harness: "codex";
214
+ native?: CodexNativeOptions<T>;
215
+ }
216
+ type HarnessRunRequest<T = string> = ClaudeCodeRunRequest<T> | CodexRunRequest<T>;
217
+ type HarnessRunRequestFor<H extends Harness, T = string> = H extends "claude-code" ? ClaudeCodeRunRequest<T> : CodexRunRequest<T>;
218
+ type HarnessRunProgress = {
219
+ harness: Harness;
220
+ atMs: number;
221
+ } & ({
222
+ kind: "execution_started";
223
+ execution: ExecutionIdentity;
224
+ } | {
225
+ kind: "conversation_identified";
226
+ executionId: string;
227
+ conversation: ConversationIdentity;
228
+ } | {
229
+ kind: "assistant_output";
230
+ executionId: string;
231
+ text: string;
232
+ } | {
233
+ kind: "usage";
234
+ executionId: string;
235
+ measurement: UsageMeasurement;
236
+ } | {
237
+ kind: "execution_finished";
238
+ executionId: string;
239
+ outcome: "succeeded" | "failed" | "cancelled";
240
+ });
241
+ type HarnessRunOutput<T> = {
242
+ kind: "text";
243
+ text: string;
244
+ } | {
245
+ kind: "structured";
246
+ value: T;
247
+ };
248
+ interface TranscriptSourceHint {
249
+ format: string;
250
+ namespace: string;
251
+ path?: string;
252
+ }
253
+ type HarnessRunFailure = {
254
+ kind: "invalid_request";
255
+ reason: string;
256
+ } | {
257
+ kind: "harness_mismatch";
258
+ reason: string;
259
+ } | {
260
+ kind: "unsupported_requirement";
261
+ reason: string;
262
+ requirement: {
263
+ kind: "capability";
264
+ capability: ExecutionCapability;
265
+ } | {
266
+ kind: "limit";
267
+ limit: LimitCapability;
268
+ };
269
+ status: "unsupported" | "unverified";
270
+ } | {
271
+ kind: "rate_limited";
272
+ reason: string;
273
+ retryAtMs?: number;
274
+ native?: unknown;
275
+ } | {
276
+ kind: "limit_exceeded";
277
+ reason: string;
278
+ unit: LimitUnit;
279
+ native?: unknown;
280
+ } | {
281
+ kind: "output_invalid";
282
+ reason: string;
283
+ native?: unknown;
284
+ } | {
285
+ kind: "auth_misconfigured";
286
+ reason: string;
287
+ native?: unknown;
288
+ } | {
289
+ kind: "aborted";
290
+ reason: string;
291
+ } | {
292
+ kind: "wall_time_exceeded";
293
+ reason: string;
294
+ wallTimeMs: number;
295
+ } | {
296
+ kind: "cancelled_unknown";
297
+ reason: string;
298
+ native?: unknown;
299
+ } | {
300
+ kind: "runtime_error";
301
+ reason: string;
302
+ native?: unknown;
303
+ };
304
+ type HarnessRunResult<T = string, H extends Harness = Harness> = {
305
+ ok: true;
306
+ harness: H;
307
+ execution: ExecutionIdentity;
308
+ conversation: ConversationIdentity;
309
+ output: HarnessRunOutput<T>;
310
+ usage: readonly UsageMeasurement[];
311
+ transcript?: TranscriptSourceHint;
312
+ } | {
313
+ ok: false;
314
+ harness: H;
315
+ execution?: ExecutionIdentity;
316
+ conversation?: ConversationIdentity;
317
+ failure: HarnessRunFailure;
318
+ usage: readonly UsageMeasurement[];
319
+ };
320
+ interface HarnessAdapter<H extends Harness> {
321
+ descriptor: HarnessCapabilityDescriptor<H>;
322
+ run<T>(request: HarnessRunRequestFor<H, T>): Promise<HarnessRunResult<T, H>>;
323
+ }
324
+
325
+ declare function preflightHarnessRun<H extends Harness, T>(request: HarnessRunRequestFor<H, T>, descriptor: HarnessCapabilityDescriptor<H>): HarnessRunFailure | undefined;
326
+ declare function dispatchHarnessRun<H extends Harness, T>(request: HarnessRunRequestFor<H, T>, adapter: HarnessAdapter<H>): Promise<HarnessRunResult<T, H>>;
327
+
328
+ interface CodexProcessExit {
329
+ exitCode: number | null;
330
+ signal: NodeJS.Signals | null;
331
+ }
332
+ interface SupervisedCodexProcess {
333
+ stdout: AsyncIterable<string>;
334
+ stderr: AsyncIterable<string>;
335
+ completed: Promise<CodexProcessExit>;
336
+ terminate(signal: "SIGTERM" | "SIGKILL"): void;
337
+ }
338
+ interface CodexSchemaFile {
339
+ path: string;
340
+ dispose(): Promise<void>;
341
+ }
342
+ interface CodexProcessInput {
343
+ executablePath: string;
344
+ args: readonly string[];
345
+ cwd: string;
346
+ env: Record<string, string>;
347
+ }
348
+ interface CodexVersionInspectionOptions {
349
+ signal?: AbortSignal;
350
+ timeoutMs: number;
351
+ }
352
+
353
+ declare const DEFAULT_CODEX_EXECUTABLE = "/Applications/ChatGPT.app/Contents/Resources/codex";
354
+ declare const SUPPORTED_CODEX_EXEC_VERSION = "0.154.0-alpha.6.1";
355
+ declare const STRIPPED_CODEX_AUTH_VARS: readonly ["CODEX_API_KEY", "OPENAI_API_KEY", "OPENAI_ACCESS_TOKEN"];
356
+ interface CodexExecAdapterOptions {
357
+ auth: "cached-cli";
358
+ executablePath?: string;
359
+ env?: NodeJS.ProcessEnv;
360
+ killGraceMs?: number;
361
+ }
362
+ interface CodexExecDeps {
363
+ inspectVersion?: (executablePath: string, env: Record<string, string>, options: CodexVersionInspectionOptions) => Promise<string>;
364
+ start?: (input: CodexProcessInput) => SupervisedCodexProcess;
365
+ createSchemaFile?: (schema: Record<string, unknown>) => Promise<CodexSchemaFile>;
366
+ executionId?: () => string;
367
+ now?: () => number;
368
+ deadlineNow?: () => number;
369
+ }
370
+ declare function createCodexExecAdapter(options: CodexExecAdapterOptions, deps?: CodexExecDeps): HarnessAdapter<"codex">;
371
+ declare function prepareCodexEnv(env: NodeJS.ProcessEnv): Record<string, string>;
372
+ declare function codexExecCapabilities(): HarnessCapabilityDescriptor<"codex">;
373
+ declare function buildCodexExecArgs<T>(request: CodexRunRequest<T>, schemaPath?: string): string[];
374
+
375
+ declare const DEFAULT_CODEX_KILL_GRACE_MS = 2000;
376
+
118
377
  interface ClassifyOptions {
119
378
  /** Epoch millis used to turn a relative "retry after Ns" hint into an absolute date. */
120
379
  now?: number;
@@ -185,4 +444,85 @@ declare const FORBIDDEN_API_KEY_SOURCES: ReadonlySet<string>;
185
444
  /** Post-flight on the first `system/init`, the earliest point the real auth route is observable. */
186
445
  declare function assertApiKeySourceAllowed(observed: string | undefined): void;
187
446
 
188
- export { ANTI_NESTING_VARS, type AgentFailure, type AgentFailureKind, type AgentInit, type AgentRunConfig, type AgentRunDeps, type AgentRunResult, type AgentUsage, AuthMisconfiguredError, CLAUDE_CODE_PASSTHROUGH_VARS, type ClassifyOptions, DEFAULT_INACTIVITY_MS, DEFAULT_MAX_RETRIES, FORBIDDEN_API_KEY_SOURCES, type PrepareEnvOptions, STRIPPED_AUTH_VARS, STRIPPED_PROXY_VARS, assertApiKeySourceAllowed, assertAuthEnvOk, classifyResult, prepareEnv, runAgent, sumModelCost, usageFromResult };
447
+ interface DurableHarnessSuccess<T = unknown, H extends Harness = Harness> {
448
+ harness: H;
449
+ adapterExecution: ExecutionIdentity;
450
+ conversation: ConversationIdentity;
451
+ output: HarnessRunOutput<T>;
452
+ usage: readonly UsageMeasurement[];
453
+ transcript?: TranscriptSourceHint;
454
+ }
455
+ type DurableHarnessRecord<H extends Harness = Harness> = ExecutionRecord<DurableHarnessSuccess<unknown, H>>;
456
+ type DurableSettlement<T = unknown, H extends Harness = Harness> = {
457
+ kind: "terminal";
458
+ record: ExecutionRecord<DurableHarnessSuccess<T, H>>;
459
+ terminal: ExecutionTerminal<DurableHarnessSuccess<T, H>>;
460
+ } | {
461
+ kind: "recovery_required";
462
+ record: DurableHarnessRecord<H>;
463
+ evidence: string;
464
+ } | {
465
+ kind: "ownership_lost";
466
+ record?: DurableHarnessRecord<H>;
467
+ evidence: string;
468
+ };
469
+ interface DurableDispatchInput<H extends Harness, T = string> {
470
+ executionId: string;
471
+ requestKey: string;
472
+ agent?: AgentIdentity;
473
+ request: HarnessRunRequestFor<H, T>;
474
+ }
475
+ interface DurableDispatchAck<T = unknown, H extends Harness = Harness> {
476
+ executionId: string;
477
+ requestKey: string;
478
+ runnerRef: string;
479
+ completion: Promise<DurableSettlement<T, H>>;
480
+ }
481
+ interface DurableLiveHandle<T = unknown, H extends Harness = Harness> {
482
+ runnerRef: string;
483
+ completion: Promise<DurableSettlement<T, H>>;
484
+ }
485
+ type DurableReconcileOutcome<H extends Harness = Harness> = ExecutionReconcileOutcome<DurableHarnessSuccess<unknown, H>, DurableLiveHandle<unknown, H>>;
486
+ type DurableCancelResult<H extends Harness = Harness> = {
487
+ kind: "requested";
488
+ record: DurableHarnessRecord<H>;
489
+ } | {
490
+ kind: "not_live";
491
+ evidence: string;
492
+ } | {
493
+ kind: "ownership_lost";
494
+ record?: DurableHarnessRecord<H>;
495
+ evidence: string;
496
+ };
497
+ interface DurableHarnessDispatcher<H extends Harness> {
498
+ readonly adapter: HarnessAdapter<H>;
499
+ dispatch<T>(input: DurableDispatchInput<H, T>): Promise<DurableDispatchAck<T, H>>;
500
+ reconcile(executionId: string): Promise<DurableReconcileOutcome<H>>;
501
+ cancel(executionId: string, reason: string): DurableCancelResult<H>;
502
+ }
503
+ interface DurableHarnessDispatcherOptions<H extends Harness> {
504
+ ledger: ExecutionLedger<DurableHarnessSuccess<unknown, H>>;
505
+ supervisorId: string;
506
+ leaseMs: number;
507
+ renewEveryMs?: number;
508
+ }
509
+ interface DurableHarnessDispatcherDeps {
510
+ eventId?: () => string;
511
+ now?: () => number;
512
+ setInterval?: typeof globalThis.setInterval;
513
+ clearInterval?: typeof globalThis.clearInterval;
514
+ }
515
+
516
+ declare function createDurableHarnessDispatcher<H extends Harness>(adapter: DurableHarnessDispatcher<H>["adapter"], options: DurableHarnessDispatcherOptions<H>, deps?: DurableHarnessDispatcherDeps): DurableHarnessDispatcher<H>;
517
+
518
+ interface ClaudeCodeAdapterOptions {
519
+ maxTurns: number;
520
+ maxBudgetUsd: number;
521
+ inactivityTimeoutMs?: number;
522
+ deps?: AgentRunDeps;
523
+ }
524
+ /** Existing Claude query circuit breakers remain mandatory; their native units stay explicit. */
525
+ declare function createClaudeCodeAdapter(options: ClaudeCodeAdapterOptions): HarnessAdapter<"claude-code">;
526
+ declare function claudeCodeCapabilities(): HarnessCapabilityDescriptor<"claude-code">;
527
+
528
+ export { ANTI_NESTING_VARS, type AgentFailure, type AgentFailureKind, type AgentInit, type AgentRunConfig, type AgentRunDeps, type AgentRunResult, type AgentUsage, AuthMisconfiguredError, type BoundedRunBase, CLAUDE_CODE_PASSTHROUGH_VARS, CODEX_APPROVAL_POLICIES, CODEX_SANDBOXES, type CapabilityAssessment, type ClassifyOptions, type ClaudeCodeAdapterOptions, type ClaudeCodeNativeOptions, type ClaudeCodeRunRequest, type CodexApprovalPolicy, type CodexExecAdapterOptions, type CodexExecDeps, type CodexNativeOptions, type CodexOutputSchema, type CodexProcessExit, type CodexProcessInput, type CodexRunRequest, type CodexSandbox, type CodexSchemaFile, type CodexVersionInspectionOptions, DEFAULT_CODEX_EXECUTABLE, DEFAULT_CODEX_KILL_GRACE_MS, DEFAULT_INACTIVITY_MS, DEFAULT_MAX_RETRIES, type DurableCancelResult, type DurableDispatchAck, type DurableDispatchInput, type DurableHarnessDispatcher, type DurableHarnessDispatcherDeps, type DurableHarnessDispatcherOptions, type DurableHarnessRecord, type DurableHarnessSuccess, type DurableLiveHandle, type DurableReconcileOutcome, type DurableSettlement, EXECUTION_CAPABILITIES, type ExecutionCapability, type ExecutionLimit, FORBIDDEN_API_KEY_SOURCES, type Harness, type HarnessAdapter, type HarnessCapabilityDescriptor, type HarnessRunFailure, type HarnessRunOutput, type HarnessRunProgress, type HarnessRunRequest, type HarnessRunRequestFor, type HarnessRunResult, type LimitCapability, type LimitEnforcement, type LimitScope, type LimitUnit, type OptionalLimitUnit, type PrepareEnvOptions, type RunTarget, STRIPPED_AUTH_VARS, STRIPPED_CODEX_AUTH_VARS, STRIPPED_PROXY_VARS, SUPPORTED_CODEX_EXEC_VERSION, type SupervisedCodexProcess, type TranscriptSourceHint, assertApiKeySourceAllowed, assertAuthEnvOk, buildCodexExecArgs, classifyResult, claudeCodeCapabilities, codexExecCapabilities, createClaudeCodeAdapter, createCodexExecAdapter, createDurableHarnessDispatcher, dispatchHarnessRun, preflightHarnessRun, prepareCodexEnv, prepareEnv, runAgent, sumModelCost, usageFromResult };