@ponythewhite/base-context 1.0.13 → 1.0.14
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/CHANGELOG.md +9 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +3 -3
- package/dist/bundle/{anthropic-BJVPUMPB.js → anthropic-AXUXEET7.js} +1 -1
- package/dist/bundle/{azure-openai-responses-ERRMAXK6.js → azure-openai-responses-J3NTJKEO.js} +2 -2
- package/dist/bundle/{bundled-modules-URKVA3UB.js → bundled-modules-UODO7ZR7.js} +5 -5
- package/dist/bundle/{chunk-FOGKLC7V.js → chunk-72LSQYUV.js} +1 -1
- package/dist/bundle/{chunk-MUFZODP5.js → chunk-EGFIZABJ.js} +1 -1
- package/dist/bundle/{chunk-AEMRBMI2.js → chunk-IEM74GZ5.js} +9 -9
- package/dist/bundle/{chunk-25VYRAC6.js → chunk-JKKXN6JE.js} +72 -0
- package/dist/bundle/{chunk-TXVF6Q5H.js → chunk-NLRWERWA.js} +37 -32
- package/dist/bundle/{chunk-TKOBEJ5E.js → chunk-SX7CAXWU.js} +22 -4
- package/dist/bundle/{chunk-Q6UAHLII.js → chunk-V6LOBH6X.js} +2 -2
- package/dist/bundle/{cli-main-ZTJM5EEH.js → cli-main-6GXXIMQQ.js} +4 -4
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-4GA4YMUX.js → google-QLKV2ZLC.js} +2 -2
- package/dist/bundle/{google-vertex-7AMALD7D.js → google-vertex-UGLUZV6B.js} +2 -2
- package/dist/bundle/{main-53I74INO.js → main-HF64B4HM.js} +5 -5
- package/dist/bundle/{mistral-74BXMNRM.js → mistral-2ITSLHYF.js} +1 -1
- package/dist/bundle/{openai-codex-responses-COXNC4IH.js → openai-codex-responses-FRREQXS3.js} +5 -4
- package/dist/bundle/{openai-completions-BCSA5Q6S.js → openai-completions-HF6UPPLW.js} +1 -1
- package/dist/bundle/{openai-responses-ONCIZSJS.js → openai-responses-LRTMBDFW.js} +2 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomous.d.ts +2 -0
- package/dist/core/autonomous.d.ts.map +1 -1
- package/dist/core/autonomous.js +4 -0
- package/dist/core/autonomous.js.map +1 -1
- package/dist/core/canonical-context.d.ts.map +1 -1
- package/dist/core/canonical-context.js +7 -0
- package/dist/core/canonical-context.js.map +1 -1
- package/dist/core/public-context.d.ts.map +1 -1
- package/dist/core/public-context.js +2 -0
- package/dist/core/public-context.js.map +1 -1
- package/dist/core/view-units.d.ts.map +1 -1
- package/dist/core/view-units.js +3 -0
- package/dist/core/view-units.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +4 -3
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +11 -5
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts +3 -0
- package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.js +2 -0
- package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +24 -21
- package/dist/modes/print-mode.js.map +1 -1
- package/docs/json.md +14 -1
- package/docs/long-running-agents.md +23 -2
- package/docs/providers.md +17 -0
- package/package.json +4 -4
|
@@ -9,6 +9,7 @@ export declare const DAEMON_WORKER_INSTANCE_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEM
|
|
|
9
9
|
export declare const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID";
|
|
10
10
|
export declare const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET";
|
|
11
11
|
export declare const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL";
|
|
12
|
+
export declare const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR";
|
|
12
13
|
export declare const DAEMON_WORKER_STARTUP_GATE_FD_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD";
|
|
13
14
|
export declare const DAEMON_WORKER_STARTUP_GATE_COMMIT = "start\n";
|
|
14
15
|
export type DaemonWorkerLifecycle = "starting" | "ready" | "recovering" | "stopping" | "failed";
|
|
@@ -179,6 +180,8 @@ export interface DaemonWorkerDescriptor {
|
|
|
179
180
|
rootSessionId?: string;
|
|
180
181
|
sessionFile?: string;
|
|
181
182
|
sessionDir?: string;
|
|
183
|
+
/** Supervisor-assigned journal scope, independent of transcript storage. */
|
|
184
|
+
rlmLedgerSessionDir?: string;
|
|
182
185
|
createdAt: string;
|
|
183
186
|
updatedAt: string;
|
|
184
187
|
lifecycle: DaemonWorkerLifecycle;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-worker-protocol.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"daemon-worker-protocol.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\t/** Supervisor-assigned journal scope, independent of transcript storage. */\n\trlmLedgerSessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\t...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
@@ -6,6 +6,7 @@ export const DAEMON_WORKER_INSTANCE_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKE
|
|
|
6
6
|
export const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID";
|
|
7
7
|
export const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET";
|
|
8
8
|
export const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL";
|
|
9
|
+
export const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR";
|
|
9
10
|
export const DAEMON_WORKER_STARTUP_GATE_FD_ENV = "BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD";
|
|
10
11
|
export const DAEMON_WORKER_STARTUP_GATE_COMMIT = "start\n";
|
|
11
12
|
/** Advertised by new workers in the worker_auth response; absent on legacy workers. */
|
|
@@ -64,6 +65,7 @@ export function durableDaemonWorkerDescriptor(descriptor) {
|
|
|
64
65
|
...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),
|
|
65
66
|
...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),
|
|
66
67
|
...(sessionDir !== undefined ? { sessionDir } : {}),
|
|
68
|
+
...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),
|
|
67
69
|
createdAt: descriptor.createdAt,
|
|
68
70
|
updatedAt: descriptor.updatedAt,
|
|
69
71
|
lifecycle: descriptor.lifecycle,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-worker-protocol.js","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"daemon-worker-protocol.js","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-worker-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { closeSync, readFileSync } from \"node:fs\";\nimport type { AgentSessionMessageDeliveryMode, AgentSessionMessageSender } from \"../../core/agent-messages.js\";\nimport type { IdleEvictionMinutes } from \"../../core/session-action-store.js\";\n\nexport { SESSION_LEASE_OWNER_ID_ENV, SESSION_LEASES_ENABLED_ENV } from \"../../core/session-lease.js\";\n\nimport type { WorkerRosterEntry } from \"./agent-roster.js\";\nimport type { DaemonClientCapability, DaemonCommand, DaemonOutbound } from \"./daemon-protocol.js\";\n\nexport const DAEMON_WORKER_ROLE_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER\";\nexport const DAEMON_WORKER_TOKEN_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_TOKEN\";\nexport const DAEMON_WORKER_INSTANCE_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_INSTANCE_ID\";\nexport const DAEMON_WORKER_ACTIVE_SESSION_ID_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_ACTIVE_SESSION_ID\";\nexport const DAEMON_WORKER_SUPERVISOR_SOCKET_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_SUPERVISOR_SOCKET\";\nexport const DAEMON_WORKER_RECOVERY_JOURNAL_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RECOVERY_JOURNAL\";\nexport const DAEMON_WORKER_RLM_LEDGER_SESSION_DIR_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_RLM_LEDGER_SESSION_DIR\";\nexport const DAEMON_WORKER_STARTUP_GATE_FD_ENV = \"BASE_CONTEXT_INTERNAL_DAEMON_WORKER_STARTUP_GATE_FD\";\nexport const DAEMON_WORKER_STARTUP_GATE_COMMIT = \"start\\n\";\nexport type DaemonWorkerLifecycle = \"starting\" | \"ready\" | \"recovering\" | \"stopping\" | \"failed\";\n\n// Worker->supervisor roster frames live outside the client-facing DaemonOutbound schema.\nexport type DaemonWorkerRosterOutbound =\n\t| {\n\t\t\ttype: \"roster_delta\";\n\t\t\tentries: WorkerRosterEntry[];\n\t\t\tremovedAgentIds?: string[];\n\t\t\tsnapshot?: true;\n\t }\n\t| { type: \"roster_heartbeat\" };\n\n/** Advertised by new workers in the worker_auth response; absent on legacy workers. */\nexport const DAEMON_WORKER_ROSTER_CAPABILITY = \"agent_roster\";\n\n/** Advertised in the worker_auth response by workers that accept peer transport grants. */\nexport const DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY = \"peer_transport\";\n\n/** Idle keepalive cadence for worker->supervisor roster frames; the supervisor staleness threshold derives from it. */\nexport const ROSTER_HEARTBEAT_INTERVAL_MS = 15_000;\n\nexport type DaemonWorkerFrameHeader =\n\t| {\n\t\t\tkind: \"command\";\n\t\t\trequestId: string;\n\t\t\tcommandType: string;\n\t }\n\t| {\n\t\t\tkind: \"outbound\";\n\t\t\trequestId?: string;\n\t\t\toutboundType: DaemonOutbound[\"type\"] | DaemonWorkerRosterOutbound[\"type\"];\n\t\t\tactiveSessionId?: string;\n\t\t\tsnapshotId?: string;\n\t\t\tsessionEventType?: string;\n\t\t\tpayloadEncoding?: \"jsonl\" | \"assistant-delta\";\n\t\t\tsnapshotPurpose?: \"attach\" | \"replacement\" | \"catchup\";\n\t };\n\nexport interface DaemonRlmCapacityOrigin {\n\tsessionFile?: string;\n\tsessionId: string;\n}\n\nexport type DaemonRlmCapacityOperation =\n\t| (DaemonRlmCapacityOrigin & { op: \"status\" })\n\t| (DaemonRlmCapacityOrigin & { op: \"set\"; maxSubagents: number })\n\t| (DaemonRlmCapacityOrigin & { op: \"reserve\"; reservationId: string; residentRoot?: true })\n\t| { op: \"release\"; reservationId: string };\n\nexport interface DaemonRlmCapacityReservation extends DaemonRlmCapacityOrigin {\n\treservationId: string;\n\tresidentRoot?: true;\n}\n\nexport interface DaemonRlmCapacitySnapshot {\n\treservations: DaemonRlmCapacityReservation[];\n}\n\nexport function isDaemonRlmCapacitySnapshot(value: unknown): value is DaemonRlmCapacitySnapshot {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"reservations\" in value &&\n\t\tArray.isArray(value.reservations) &&\n\t\tvalue.reservations.every(\n\t\t\t(entry: unknown) =>\n\t\t\t\ttypeof entry === \"object\" &&\n\t\t\t\tentry !== null &&\n\t\t\t\t\"reservationId\" in entry &&\n\t\t\t\ttypeof entry.reservationId === \"string\" &&\n\t\t\t\tentry.reservationId.length > 0 &&\n\t\t\t\t\"sessionId\" in entry &&\n\t\t\t\ttypeof entry.sessionId === \"string\" &&\n\t\t\t\tentry.sessionId.length > 0 &&\n\t\t\t\t(!(\"sessionFile\" in entry) || entry.sessionFile === undefined || typeof entry.sessionFile === \"string\") &&\n\t\t\t\t(!(\"residentRoot\" in entry) || entry.residentRoot === undefined || entry.residentRoot === true),\n\t\t)\n\t);\n}\n\nexport type DaemonCreateCommand = Extract<DaemonCommand, { type: \"create\" }>;\n\nexport interface DurableDaemonCreateCommand {\n\ttype: \"create\";\n\tsessionPath?: string;\n\tnoSession?: boolean;\n}\n\nexport function durableDaemonCreateCommand(command: DaemonCreateCommand): DurableDaemonCreateCommand {\n\treturn {\n\t\ttype: \"create\",\n\t\t...(command.sessionPath !== undefined ? { sessionPath: command.sessionPath } : {}),\n\t\t...(command.noSession !== undefined ? { noSession: command.noSession } : {}),\n\t};\n}\n\n/**\n * A single-use, worker-memory-only admission for one direct peer, scoped to one active-session\n * slot (stable across switch_session/new_session/fork) of one worker incarnation. The session pin\n * is a routing/accident guard, not a privilege boundary: ticket holders already hold supervisor\n * access, which can attach to, switch, or kill any session.\n */\nexport interface DaemonWorkerPeerGrant {\n\tgrantId: string;\n\ttoken: string;\n\texpiresAt: string;\n\tpurpose: \"session_client\";\n\tworkerInstanceId: string;\n\tactiveSessionId: string;\n\tissuerGeneration: string;\n}\n\n/** Commands a direct peer may send before it holds an authenticated session role. */\nexport type DaemonPeerCommand = {\n\tid?: string;\n\ttype: \"peer_auth\";\n\tgrantId: string;\n\ttoken: string;\n\tworkerInstanceId: string;\n\tpurpose: \"session_client\";\n};\n\nexport type DaemonPeerCommandBody = Omit<DaemonPeerCommand, \"id\">;\n\nexport type DaemonWorkerCommand =\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_auth\";\n\t\t\ttoken: string;\n\t\t\tworkerInstanceId?: string;\n\t\t\tsupervisorGeneration: string;\n\t\t\tsupervisorPid: number;\n\t\t\tsupervisorProcessStartId?: string;\n\t\t\tsupervisorSocketPath: string;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_subscribe\";\n\t\t\tactiveSessionId: string;\n\t\t\tcapabilities?: readonly DaemonClientCapability[];\n\t\t\tsupportsExtensionUi?: boolean;\n\t }\n\t| { id?: string; type: \"worker_unsubscribe\"; activeSessionId: string }\n\t| { id?: string; type: \"worker_register_peer_transport\"; grant: DaemonWorkerPeerGrant }\n\t| { id?: string; type: \"worker_archive_and_shutdown\" }\n\t| { id?: string; type: \"worker_get_rlm_capacity\" }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_passivate_idle_children\";\n\t\t\tidleEvictionMinutes: IdleEvictionMinutes;\n\t\t\tnow: number;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_message\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tmessage: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| {\n\t\t\tid?: string;\n\t\t\ttype: \"worker_deliver_result\";\n\t\t\ttargetActiveSessionId: string;\n\t\t\tsummary: string;\n\t\t\tfindings: string;\n\t\t\tsender: AgentSessionMessageSender;\n\t\t\tdeliveryMode?: AgentSessionMessageDeliveryMode;\n\t }\n\t| { id?: string; type: \"worker_prepare_update\" }\n\t| { id?: string; type: \"worker_commit_update\" }\n\t| { id?: string; type: \"worker_cancel_update\" };\n\nexport type DaemonWorkerCommandBody = DaemonWorkerCommand extends infer TCommand\n\t? TCommand extends { id?: string }\n\t\t? Omit<TCommand, \"id\">\n\t\t: never\n\t: never;\n\nexport interface DaemonWorkerDescriptor {\n\tversion: 1 | 2;\n\tworkerId: string;\n\tpid: number;\n\tprocessStartId?: string;\n\tsocketPath: string;\n\trecoveryJournalPath: string;\n\torphanProcessJournalPath?: string;\n\tsupervisorSocketPath: string;\n\tauthenticationToken: string;\n\tworkerInstanceId?: string;\n\trootActiveSessionId: string;\n\t/** Stable protocol client that owns this worker. Omitted for resident sessions. */\n\townerClientId?: string;\n\trootSessionId?: string;\n\tsessionFile?: string;\n\tsessionDir?: string;\n\t/** Supervisor-assigned journal scope, independent of transcript storage. */\n\trlmLedgerSessionDir?: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlifecycle: DaemonWorkerLifecycle;\n\tcreateCommand: DurableDaemonCreateCommand;\n\tconsecutiveFailures: number;\n\t/** Durable intent written before root termination so replacement supervisors never recover it. */\n\tstopRequestedAt?: string;\n\t/** Complete the root's archived lifecycle state after its process has stopped. */\n\tarchiveOnStop?: boolean;\n\tlastFailureAt?: string;\n\tlastError?: string;\n}\n\nexport function durableDaemonWorkerDescriptor(descriptor: DaemonWorkerDescriptor): DaemonWorkerDescriptor {\n\tconst versionOneCreateCommand = descriptor.createCommand as unknown as { config?: unknown };\n\tconst versionOneConfig =\n\t\tdescriptor.version === 1 &&\n\t\ttypeof versionOneCreateCommand.config === \"object\" &&\n\t\tversionOneCreateCommand.config !== null\n\t\t\t? (versionOneCreateCommand.config as Record<string, unknown>)\n\t\t\t: undefined;\n\tconst sessionDir =\n\t\tdescriptor.sessionDir ??\n\t\t(typeof versionOneConfig?.sessionDir === \"string\" ? versionOneConfig.sessionDir : undefined);\n\treturn {\n\t\tversion: 2,\n\t\tworkerId: descriptor.workerId,\n\t\tpid: descriptor.pid,\n\t\t...(descriptor.processStartId !== undefined ? { processStartId: descriptor.processStartId } : {}),\n\t\tsocketPath: descriptor.socketPath,\n\t\trecoveryJournalPath: descriptor.recoveryJournalPath,\n\t\t...(descriptor.orphanProcessJournalPath !== undefined\n\t\t\t? { orphanProcessJournalPath: descriptor.orphanProcessJournalPath }\n\t\t\t: {}),\n\t\tsupervisorSocketPath: descriptor.supervisorSocketPath,\n\t\tauthenticationToken: descriptor.authenticationToken,\n\t\t...(descriptor.workerInstanceId !== undefined ? { workerInstanceId: descriptor.workerInstanceId } : {}),\n\t\trootActiveSessionId: descriptor.rootActiveSessionId,\n\t\t...(descriptor.ownerClientId !== undefined ? { ownerClientId: descriptor.ownerClientId } : {}),\n\t\t...(descriptor.rootSessionId !== undefined ? { rootSessionId: descriptor.rootSessionId } : {}),\n\t\t...(descriptor.sessionFile !== undefined ? { sessionFile: descriptor.sessionFile } : {}),\n\t\t...(sessionDir !== undefined ? { sessionDir } : {}),\n\t\t...(descriptor.rlmLedgerSessionDir !== undefined ? { rlmLedgerSessionDir: descriptor.rlmLedgerSessionDir } : {}),\n\t\tcreatedAt: descriptor.createdAt,\n\t\tupdatedAt: descriptor.updatedAt,\n\t\tlifecycle: descriptor.lifecycle,\n\t\tcreateCommand: durableDaemonCreateCommand(descriptor.createCommand),\n\t\tconsecutiveFailures: descriptor.consecutiveFailures,\n\t\t...(descriptor.stopRequestedAt !== undefined ? { stopRequestedAt: descriptor.stopRequestedAt } : {}),\n\t\t...(descriptor.archiveOnStop !== undefined ? { archiveOnStop: descriptor.archiveOnStop } : {}),\n\t\t...(descriptor.lastFailureAt !== undefined ? { lastFailureAt: descriptor.lastFailureAt } : {}),\n\t\t...(descriptor.lifecycle === \"failed\" ? { lastError: \"Waiting for a client with fresh runtime context\" } : {}),\n\t};\n}\n\nexport function isDaemonWorkerProcess(environment: NodeJS.ProcessEnv = process.env): boolean {\n\treturn environment[DAEMON_WORKER_ROLE_ENV] === \"1\";\n}\n\nexport function waitForDaemonWorkerStartupGate(environment: NodeJS.ProcessEnv = process.env): void {\n\tconst rawFd = environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tif (rawFd === undefined) {\n\t\treturn;\n\t}\n\tdelete environment[DAEMON_WORKER_STARTUP_GATE_FD_ENV];\n\tconst fd = Number(rawFd);\n\tif (!Number.isInteger(fd) || fd < 3) {\n\t\tthrow new Error(\"Daemon session worker has an invalid startup gate\");\n\t}\n\tlet marker: string;\n\ttry {\n\t\tmarker = readFileSync(fd, \"utf8\");\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tif (marker !== DAEMON_WORKER_STARTUP_GATE_COMMIT) {\n\t\tthrow new Error(\"Daemon session worker startup was cancelled\");\n\t}\n}\n\nexport function daemonWorkerInstanceId(environment: NodeJS.ProcessEnv = process.env): string | undefined {\n\treturn environment[DAEMON_WORKER_INSTANCE_ID_ENV] || undefined;\n}\n\nexport function requireDaemonWorkerAuthenticationToken(environment: NodeJS.ProcessEnv = process.env): string {\n\tconst token = environment[DAEMON_WORKER_TOKEN_ENV];\n\tif (!token) {\n\t\tthrow new Error(\"Daemon session worker is missing its authentication token\");\n\t}\n\treturn token;\n}\n\nexport function isDaemonWorkerFrameHeader(value: unknown): value is DaemonWorkerFrameHeader {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as Record<string, unknown>;\n\tif (candidate.kind === \"command\") {\n\t\treturn typeof candidate.requestId === \"string\" && typeof candidate.commandType === \"string\";\n\t}\n\treturn (\n\t\tcandidate.kind === \"outbound\" &&\n\t\ttypeof candidate.outboundType === \"string\" &&\n\t\t(candidate.requestId === undefined || typeof candidate.requestId === \"string\") &&\n\t\t(candidate.activeSessionId === undefined || typeof candidate.activeSessionId === \"string\") &&\n\t\t(candidate.snapshotId === undefined || typeof candidate.snapshotId === \"string\") &&\n\t\t(candidate.sessionEventType === undefined || typeof candidate.sessionEventType === \"string\") &&\n\t\t(candidate.snapshotPurpose === undefined ||\n\t\t\tcandidate.snapshotPurpose === \"attach\" ||\n\t\t\tcandidate.snapshotPurpose === \"replacement\" ||\n\t\t\tcandidate.snapshotPurpose === \"catchup\") &&\n\t\t(candidate.payloadEncoding === undefined ||\n\t\t\tcandidate.payloadEncoding === \"jsonl\" ||\n\t\t\tcandidate.payloadEncoding === \"assistant-delta\")\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAgBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/G;AAED,wBAAsB,0BAA0B,CAC/C,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\
|
|
1
|
+
{"version":3,"file":"print-mode.d.ts","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAK5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,yEAAyE;IACzE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;CAC/B;AAgBD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/G;AAED,wBAAsB,0BAA0B,CAC/C,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\tif (primary?.role === \"assistant\") {\n\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\texitCode = 1;\n\t\t\t} else if (mode === \"text\") {\n\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (primary) {\n\t\t\tif (mode === \"text\") writeRawStdout(`${primary.content}\\n`);\n\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t}\n\t\tfor (const outcome of compactionOutcomes) {\n\t\t\tif (mode === \"text\" || outcome.details.outcome === \"failed\") console.error(outcome.content);\n\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (\n\t\t\tautonomousStatus.enabled &&\n\t\t\tautonomousLimit &&\n\t\t\t(autonomousStatus.gates.commands.length === 0 ||\n\t\t\t\tautonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))\n\t\t) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -85,31 +85,31 @@ async function runPrintModeWithConnectionInternal(connection, options, bindHeadl
|
|
|
85
85
|
await connection.promptAndWait(message);
|
|
86
86
|
}
|
|
87
87
|
const autonomousStatus = await connection.waitForHeadlessCompletion();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (primary
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
writeRawStdout(`${content.text}\n`);
|
|
99
|
-
}
|
|
88
|
+
const { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());
|
|
89
|
+
if (primary?.role === "assistant") {
|
|
90
|
+
if (primary.stopReason === "error" || primary.stopReason === "aborted") {
|
|
91
|
+
console.error(primary.errorMessage || `Request ${primary.stopReason}`);
|
|
92
|
+
exitCode = 1;
|
|
93
|
+
}
|
|
94
|
+
else if (mode === "text") {
|
|
95
|
+
for (const content of primary.content) {
|
|
96
|
+
if (content.type === "text") {
|
|
97
|
+
writeRawStdout(`${content.text}\n`);
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
|
-
|
|
101
|
+
}
|
|
102
|
+
else if (primary) {
|
|
103
|
+
if (mode === "text")
|
|
104
104
|
writeRawStdout(`${primary.content}\n`);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
if (!primary.details.success || primary.details.severity === "error")
|
|
106
|
+
exitCode = 1;
|
|
107
|
+
}
|
|
108
|
+
for (const outcome of compactionOutcomes) {
|
|
109
|
+
if (mode === "text" || outcome.details.outcome === "failed")
|
|
109
110
|
console.error(outcome.content);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
111
|
+
if (outcome.details.outcome === "failed")
|
|
112
|
+
exitCode = 1;
|
|
113
113
|
}
|
|
114
114
|
const autonomousLimit = autonomousLimitReason(autonomousStatus);
|
|
115
115
|
if (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {
|
|
@@ -119,7 +119,10 @@ async function runPrintModeWithConnectionInternal(connection, options, bindHeadl
|
|
|
119
119
|
console.error(`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`);
|
|
120
120
|
exitCode = 1;
|
|
121
121
|
}
|
|
122
|
-
else if (autonomousStatus.enabled &&
|
|
122
|
+
else if (autonomousStatus.enabled &&
|
|
123
|
+
autonomousLimit &&
|
|
124
|
+
(autonomousStatus.gates.commands.length === 0 ||
|
|
125
|
+
autonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))) {
|
|
123
126
|
console.error(`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`);
|
|
124
127
|
exitCode = 1;
|
|
125
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tif (mode === \"text\") {\n\t\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\t\tif (primary?.role === \"assistant\") {\n\t\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\t\texitCode = 1;\n\t\t\t\t} else {\n\t\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (primary) {\n\t\t\t\twriteRawStdout(`${primary.content}\\n`);\n\t\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t\t}\n\t\t\tfor (const outcome of compactionOutcomes) {\n\t\t\t\tconsole.error(outcome.content);\n\t\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t\t}\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (autonomousStatus.enabled && autonomousStatus.gates.commands.length === 0 && autonomousLimit) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"print-mode.js","sourceRoot":"","sources":["../../src/modes/print-mode.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Print mode (single-shot): Send prompts, output result, exit.\n *\n * Used for:\n * - `pi -p \"prompt\"` - text output\n * - `pi --mode json \"prompt\"` - JSON event stream\n */\n\nimport type { ImageContent } from \"@ponythewhite/base-context-ai\";\nimport type { AgentSessionRuntime } from \"../core/agent-session-runtime.js\";\nimport { type AgentAutonomousStatus, type AutonomousLimitReason, autonomousLimitReason } from \"../core/autonomous.js\";\nimport { flushRawStdout, writeRawStdout } from \"../core/output-guard.js\";\nimport { killTrackedDetachedChildren } from \"../utils/shell.js\";\nimport { InProcessAgentConnection } from \"./agent-connection/in-process-agent-connection.js\";\nimport type { AgentConnection } from \"./agent-connection/types.js\";\nimport { latestAutonomousGateAttempt, selectHeadlessTerminalResult } from \"./headless-completion.js\";\n\n/**\n * Options for print mode.\n */\nexport interface PrintModeOptions {\n\t/** Output mode: \"text\" for final response only, \"json\" for all events */\n\tmode: \"text\" | \"json\";\n\t/** Array of additional prompts to send after initialMessage */\n\tmessages?: string[];\n\t/** First message to send (may contain @file content) */\n\tinitialMessage?: string;\n\t/** Images to attach to the initial message */\n\tinitialImages?: ImageContent[];\n}\n\nfunction describeAutonomousLimit(status: AgentAutonomousStatus, reason: AutonomousLimitReason): string {\n\tif (reason === \"maxContinuations\") {\n\t\treturn `maxContinuations reached (${status.continuationsUsed}/${status.limits.maxContinuations})`;\n\t}\n\tif (reason === \"maxTurns\") {\n\t\treturn `maxTurns reached (${status.turnsUsed}/${status.limits.maxTurns})`;\n\t}\n\tif (reason === \"maxTokens\") {\n\t\treturn `maxTokens reached (${status.tokensUsed}/${status.limits.maxTokens})`;\n\t}\n\tconst elapsed = status.startedAt === undefined ? 0 : Math.max(0, Date.now() - status.startedAt);\n\treturn `timeoutMs reached (${elapsed}/${status.limits.timeoutMs})`;\n}\n\n/**\n * Run in print (single-shot) mode.\n * Sends prompts to the agent and outputs the result.\n */\nexport async function runPrintMode(runtimeHost: AgentSessionRuntime, options: PrintModeOptions): Promise<number> {\n\tconst connection = new InProcessAgentConnection(runtimeHost);\n\treturn runPrintModeWithConnectionInternal(connection, options, () => connection.bindHeadlessExtensions());\n}\n\nexport async function runPrintModeWithConnection(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n): Promise<number> {\n\treturn runPrintModeWithConnectionInternal(connection, options);\n}\n\nasync function runPrintModeWithConnectionInternal(\n\tconnection: AgentConnection,\n\toptions: PrintModeOptions,\n\tbindHeadlessExtensions?: () => Promise<void>,\n): Promise<number> {\n\tconst { mode, messages = [], initialMessage, initialImages } = options;\n\tlet exitCode = 0;\n\tlet disposed = false;\n\tlet unsubscribe: (() => void) | undefined;\n\tconst signalCleanupHandlers: Array<() => void> = [];\n\n\tconst disposeConnection = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tunsubscribe?.();\n\t\tawait connection.dispose();\n\t};\n\n\tfor (const signal of [\n\t\t\"SIGINT\",\n\t\t\"SIGTERM\",\n\t\t...(process.platform === \"win32\" ? [] : [\"SIGHUP\"]),\n\t] as NodeJS.Signals[]) {\n\t\tconst handler = () => {\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid disposeConnection().finally(() => {\n\t\t\t\tconst exitCode = signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143;\n\t\t\t\tprocess.exit(exitCode);\n\t\t\t});\n\t\t};\n\t\tprocess.on(signal, handler);\n\t\tsignalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\ttry {\n\t\tif (mode === \"json\") {\n\t\t\tconst header = await connection.getSessionHeader();\n\t\t\tif (header) {\n\t\t\t\twriteRawStdout(`${JSON.stringify(header)}\\n`);\n\t\t\t}\n\t\t}\n\n\t\tunsubscribe = connection.subscribe((event) => {\n\t\t\tif (mode === \"json\" && event.type === \"session_event\") {\n\t\t\t\twriteRawStdout(`${JSON.stringify(event.event)}\\n`);\n\t\t\t}\n\t\t\tif (event.type === \"extension_error\") {\n\t\t\t\tconsole.error(`Extension error (${event.extensionPath}): ${event.error}`);\n\t\t\t}\n\t\t});\n\t\tawait bindHeadlessExtensions?.();\n\n\t\tif (initialMessage) {\n\t\t\tawait connection.promptAndWait(initialMessage, { images: initialImages });\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tawait connection.promptAndWait(message);\n\t\t}\n\n\t\tconst autonomousStatus = await connection.waitForHeadlessCompletion();\n\t\tconst { primary, compactionOutcomes } = selectHeadlessTerminalResult(await connection.getMessages());\n\t\tif (primary?.role === \"assistant\") {\n\t\t\tif (primary.stopReason === \"error\" || primary.stopReason === \"aborted\") {\n\t\t\t\tconsole.error(primary.errorMessage || `Request ${primary.stopReason}`);\n\t\t\t\texitCode = 1;\n\t\t\t} else if (mode === \"text\") {\n\t\t\t\tfor (const content of primary.content) {\n\t\t\t\t\tif (content.type === \"text\") {\n\t\t\t\t\t\twriteRawStdout(`${content.text}\\n`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (primary) {\n\t\t\tif (mode === \"text\") writeRawStdout(`${primary.content}\\n`);\n\t\t\tif (!primary.details.success || primary.details.severity === \"error\") exitCode = 1;\n\t\t}\n\t\tfor (const outcome of compactionOutcomes) {\n\t\t\tif (mode === \"text\" || outcome.details.outcome === \"failed\") console.error(outcome.content);\n\t\t\tif (outcome.details.outcome === \"failed\") exitCode = 1;\n\t\t}\n\n\t\tconst autonomousLimit = autonomousLimitReason(autonomousStatus);\n\t\tif (autonomousStatus.enabled && autonomousStatus.gates.commands.length > 0 && autonomousStatus.lastGateFailure) {\n\t\t\tconst limitText = autonomousLimit\n\t\t\t\t? `; autonomous limit reached: ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`\n\t\t\t\t: \"\";\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous quality gate still failing after attempt ${latestAutonomousGateAttempt(autonomousStatus)}/${autonomousStatus.gates.maxRetries}: ${autonomousStatus.lastGateFailure.exitText}${limitText}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t} else if (\n\t\t\tautonomousStatus.enabled &&\n\t\t\tautonomousLimit &&\n\t\t\t(autonomousStatus.gates.commands.length === 0 ||\n\t\t\t\tautonomousStatus.gates.commands.some((command) => autonomousStatus.gateAttempts[command] !== 0))\n\t\t) {\n\t\t\tconsole.error(\n\t\t\t\t`Autonomous run stopped before terminal evidence; ${describeAutonomousLimit(autonomousStatus, autonomousLimit)}`,\n\t\t\t);\n\t\t\texitCode = 1;\n\t\t}\n\n\t\treturn exitCode;\n\t} catch (error: unknown) {\n\t\tconsole.error(error instanceof Error ? error.message : String(error));\n\t\treturn 1;\n\t} finally {\n\t\tfor (const cleanup of signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tawait disposeConnection();\n\t\tawait flushRawStdout();\n\t}\n}\n"]}
|
package/docs/json.md
CHANGED
|
@@ -75,8 +75,21 @@ Followed by events as they occur:
|
|
|
75
75
|
{"type":"agent_end","messages":[...]}
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
## Completion and Errors
|
|
79
|
+
|
|
80
|
+
JSON mode has the same exit-status rules as text print mode. Terminal assistant errors or aborts, failed session commands, failed compaction, and unfinished autonomous runs stopped by a limit return a nonzero exit status. A configured gate that has not run is not a passed gate. Error diagnostics go to stderr; stdout remains a JSON event stream. Recovered intermediate errors do not by themselves make the final result fail.
|
|
81
|
+
|
|
82
|
+
An unknown explicit `--model` fails startup instead of falling back to the saved model. Startup failures can occur before the session header is emitted.
|
|
83
|
+
|
|
84
|
+
Keep stderr and check the process exit status. An `agent_end` event means the agent loop ended, not that the task succeeded: inspect the terminal assistant's `stopReason` and `errorMessage`, and any gate or compaction failure. Codex error diagnostics retain supplied flat or nested error messages and codes; an empty provider error cannot reveal a cause the provider did not send.
|
|
85
|
+
|
|
86
|
+
Record the first session header's `id` when launching a run. Use that session ID with lifecycle commands; neither cwd nor an operating-system process title uniquely identifies a session. See [Long-Running Agents](long-running-agents.md#daemon-backed-sessions) for client-owned versus resident lifetimes.
|
|
87
|
+
|
|
78
88
|
## Example
|
|
79
89
|
|
|
90
|
+
Use `pipefail` so the filter does not hide a failing CLI exit status:
|
|
91
|
+
|
|
80
92
|
```bash
|
|
81
|
-
|
|
93
|
+
set -o pipefail
|
|
94
|
+
base-context --mode json "List files" 2>run.err | jq -c 'select(.type == "message_end")'
|
|
82
95
|
```
|
|
@@ -46,7 +46,9 @@ The client can detach at any point. The resident worker continues to own the que
|
|
|
46
46
|
|
|
47
47
|
Normal interactive sessions run in resident worker processes managed by a local supervisor. The worker owns the root session, its Python kernel, scheduled jobs, and RLM descendants.
|
|
48
48
|
|
|
49
|
-
Closing the terminal UI detaches the client; it does not stop the worker.
|
|
49
|
+
Closing the terminal UI detaches the client; it does not stop the resident worker. Print/JSON and RPC sessions are client-owned instead: losing their client connection triggers worker cleanup. ACP sessions are resident unless `--no-session` is used. A separate launcher or monitoring process can fail while its CLI child remains connected; that is not a client disconnect.
|
|
50
|
+
|
|
51
|
+
List and reconnect to active agents with:
|
|
50
52
|
|
|
51
53
|
```bash
|
|
52
54
|
base-context list
|
|
@@ -64,12 +66,16 @@ base-context doctor [--fix] # Diagnose or repair service state
|
|
|
64
66
|
base-context shutdown [--force] # Stop all agents and services
|
|
65
67
|
```
|
|
66
68
|
|
|
69
|
+
Use the session ID from the JSON stream header or the IDs in `base-context list --json` to track a run. Several sessions can share one cwd. The process title `base-context` identifies the program, not an individual session. `stop` reports an error for an unknown or ambiguous target; do not suppress all stop failures or infer worker death from a separate launcher's exit.
|
|
70
|
+
|
|
67
71
|
Workers persist native-framed journals and use derived indexes. The default flat paths are `~/.base-context/sessions/<session-id>.jsonl` and `~/.base-context/session-artifacts/<session-id>/`. `BASE_CONTEXT_HOME` selects the product root; `BASE_CONTEXT_SESSION_DIR` can select a different absolute sessions directory, with artifacts under its parent's `session-artifacts/` directory.
|
|
68
72
|
|
|
69
73
|
The `.jsonl` extension does not make a native journal an editable transcript. Use the asynchronous, bounded SessionManager APIs described in [Sessions](sessions.md#session-format), not `jq`, manual appends or text edits. Recovery uses the native owners and supported artifacts. Copying a journal alone does not restore a worker, Python process, live children or pending dispatch authority.
|
|
70
74
|
|
|
71
75
|
Daemon workers are process-isolated for lifecycle and failure containment, not security-sandboxed. They normally run with the same operating-system permissions as the client.
|
|
72
76
|
|
|
77
|
+
If a run must not create subagents, use the existing `/agents 0` control or the `rlmMaxSubagents: 0` setting. This blocks new admissions; it does not stop existing children. A prompt instruction alone is not a capability limit. Parent `message_end` usage describes parent responses, not all delegated work; inspect child usage separately. See [RLM](rlm.md) and [Settings](settings.md).
|
|
78
|
+
|
|
73
79
|
## Agent-to-Agent Communication
|
|
74
80
|
|
|
75
81
|
The daemon routes direct messages between active sessions and retained daemon-backed subagents. From a shell:
|
|
@@ -228,6 +234,15 @@ await goal.complete()
|
|
|
228
234
|
|
|
229
235
|
Goal state records token usage, elapsed time, continuation count, and an optional explicit token budget. The harness keeps prompting an active goal after ordinary assistant turns; only `goal.complete()` marks successful completion. Creating a persistent goal is an explicit user or host action, not something the agent should infer from every task. Imported historical goal entries remain retained data; importing them does not reactivate the goal.
|
|
230
236
|
|
|
237
|
+
Goal objectives are limited to 4,000 characters because they remain part of the ongoing task context. Keep the objective short and pass a longer brief as prompt input, for example:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
base-context -p --goal "Complete the change described in BRIEF.md" \
|
|
241
|
+
--goal-token-budget 200000 @BRIEF.md
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`--goal-token-budget` accompanies `--goal`; resuming a session alone restores the saved goal budget and usage. `/goal resume` does not reset an exhausted budget. To authorize more work after exhaustion, explicitly start a new goal with a new budget. Goal token usage counts `input + output`, not cached reads.
|
|
245
|
+
|
|
231
246
|
## Autonomous Mode
|
|
232
247
|
|
|
233
248
|
Autonomous mode is a bounded host policy for runs where no human input is expected. Base Context adds follow-up continuations until configured quality gates pass or a continuation, turn, token, or wall-clock limit is reached.
|
|
@@ -250,7 +265,13 @@ base-context \
|
|
|
250
265
|
"Implement and verify the requested change"
|
|
251
266
|
```
|
|
252
267
|
|
|
253
|
-
Autonomous mode supports limits for continuations, assistant turns, tokens, and wall-clock duration.
|
|
268
|
+
Autonomous mode supports limits for continuations, assistant turns, tokens, and wall-clock duration. Defaults are 3 continuations, 12 turns, 80,000 tokens, and 30 minutes. Set explicit limits for longer jobs rather than relying on unbounded execution.
|
|
269
|
+
|
|
270
|
+
The autonomous token counter is `input + output + cacheWrite`. It excludes `cacheRead`; provider `totalTokens` includes cached reads and is not the same budget or a monetary cost. An external launcher that sums `totalTokens` therefore applies a different limit.
|
|
271
|
+
|
|
272
|
+
Turn, token, and time limits are checked at completed native tool-turn boundaries before another main-loop request. A running response or tool is allowed to finish, so usage or elapsed time can exceed the exact cap by that work. These limits are not process-kill timers and do not cancel every auxiliary lifecycle operation. `maxContinuations` counts host-injected prompts separately; the final permitted prompt can still execute its tool turns.
|
|
273
|
+
|
|
274
|
+
Gate commands run before successful autonomous completion; a failed gate returns its bounded output to the agent for another attempt. Base Context avoids rerunning the same failed gate when the workspace has not changed. A work limit can stop a run before its gates execute. Headless mode returns nonzero in that case, rather than treating an unrun gate as success.
|
|
254
275
|
|
|
255
276
|
Goals and autonomous mode are complementary but different:
|
|
256
277
|
|
package/docs/providers.md
CHANGED
|
@@ -35,6 +35,23 @@ An OpenAI API key belongs to the separate `openai` provider; it is not required
|
|
|
35
35
|
|
|
36
36
|
The SDK also offers an optional, explicitly injected read-only Codex backend for existing credentials. Only that mode disables login, refresh, credential writes, and API-key fallback. It does not restrict normal interactive subscription login. See [SDK authentication](sdk.md#api-keys-and-oauth).
|
|
37
37
|
|
|
38
|
+
### GPT-6 Sol and Luna
|
|
39
|
+
|
|
40
|
+
Both `gpt-6-sol` and `gpt-6-luna` are listed under these separate providers:
|
|
41
|
+
|
|
42
|
+
| Provider | Authentication | Route | Catalog context capacity |
|
|
43
|
+
|----------|----------------|-------|--------------------------|
|
|
44
|
+
| `openai` | OpenAI API key | `openai-responses`, `https://api.openai.com/v1/responses` | 1,050,000 tokens |
|
|
45
|
+
| `openai-codex` | ChatGPT/Codex subscription OAuth | `openai-codex-responses`, `https://chatgpt.com/backend-api/codex/responses` | 872,000 tokens |
|
|
46
|
+
|
|
47
|
+
The official Codex catalog specifies a 272,000-token **client default** and an 872,000-token **maximum configuration override** for both models. Base Context uses that documented maximum as catalog capacity, without importing Codex's compaction percentages. The API model cards specify 1,050,000 context tokens, 922,000 maximum input tokens, and 128,000 maximum output tokens. All four catalog entries use the nominal 128,000 output ceiling; a separate Codex account/backend output limit has not been verified. Both accept text and images and produce text.
|
|
48
|
+
|
|
49
|
+
API reasoning levels are `off` (sent as `none`), `low`, `medium`, `high`, `xhigh`, and `max`. The Codex entries expose `low` through `max`, without `off` or `minimal`. Codex's Ultra option is client-side task delegation, not an additional Base Context reasoning level.
|
|
50
|
+
|
|
51
|
+
Catalog costs are flat Standard API-rate estimates. Long-context and service-tier premiums are not modeled by these entries. Codex costs are API-equivalent estimates, not subscription charges or invoices. Model availability depends on account, workspace, client, and rollout; live account access has not been verified.
|
|
52
|
+
|
|
53
|
+
Official sources: [Sol model card](https://developers.openai.com/api/docs/models/gpt-6-sol), [Luna model card](https://developers.openai.com/api/docs/models/gpt-6-luna), [API pricing](https://developers.openai.com/api/docs/pricing), [Codex models](https://developers.openai.com/codex/models), [Codex catalog](https://github.com/openai/codex/blob/main/codex-rs/models-manager/models.json), and [context-field definitions](https://github.com/openai/codex/blob/main/codex-rs/protocol/src/openai_models.rs).
|
|
54
|
+
|
|
38
55
|
## API Keys
|
|
39
56
|
|
|
40
57
|
### Environment Variables or Auth File
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ponythewhite/base-context",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Synerise base-context: a coding and research agent with durable context and a persistent Python REPL",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
45
|
-
"@ponythewhite/base-context-agent": "1.0.
|
|
46
|
-
"@ponythewhite/base-context-ai": "1.0.
|
|
47
|
-
"@ponythewhite/base-context-tui": "1.0.
|
|
45
|
+
"@ponythewhite/base-context-agent": "1.0.14",
|
|
46
|
+
"@ponythewhite/base-context-ai": "1.0.14",
|
|
47
|
+
"@ponythewhite/base-context-tui": "1.0.14",
|
|
48
48
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
49
49
|
"chalk": "^5.5.0",
|
|
50
50
|
"cli-highlight": "^2.1.11",
|