{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/shared-inference/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Local Subagent Runtime (3.0.0 foundation).\n *\n * Maintains MANY logical agents independently of physical inference capacity. A\n * logical agent is a durable semantic execution context reusing existing Jensen\n * identities (child session / mission / assignment / execution). This runtime\n * is a control/read model; it does NOT implement automatic fan-out, does NOT\n * own the Mission state machine, and never owns an OS process.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { LogicalAgentStore } from \"./logical-agent.js\";\nimport { createLogicalAgentRecord } from \"./logical-agent.js\";\nimport type { LogicalAgentActivity, LogicalAgentRecord } from \"./types.js\";\n\nexport interface LocalSubagentRuntimeOptions {\n\tstore: LogicalAgentStore;\n\tnow?: () => number;\n\tidFactory?: () => string;\n}\n\nexport interface RegisterLogicalAgentInput {\n\tlogicalAgentId?: string;\n\tparentAgentId?: string;\n\tmissionId?: string;\n\tassignmentId?: string;\n\tattemptId?: string;\n\texecutionId?: string;\n\tworkerId?: string;\n\texecutorId?: string;\n\tmodelPolicy?: { provider: string; model: string };\n\tsessionId: string;\n\tsessionDir?: string;\n\tevidenceRefs?: string[];\n\tactivity?: LogicalAgentActivity;\n\tpriority?: number;\n}\n\nexport interface ActivityCounts {\n\trunningInference: number;\n\twaitingInference: number;\n\ttooling: number;\n\tparked: number;\n\trunnable: number;\n\ttotal: number;\n}\n\nexport class LocalSubagentRuntime {\n\tprivate readonly _store: LogicalAgentStore;\n\tprivate readonly _now: () => number;\n\tprivate readonly _idFactory: () => string;\n\tconstructor(options: LocalSubagentRuntimeOptions) {\n\t\tthis._store = options.store;\n\t\tthis._now = options.now ?? (() => Date.now());\n\t\tthis._idFactory = options.idFactory ?? (() => `agent_${randomUUID()}`);\n\t}\n\n\tget store(): LogicalAgentStore {\n\t\treturn this._store;\n\t}\n\n\t/** Register a logical agent (idempotent by logicalAgentId). Never creates a duplicate identity. */\n\tasync register(input: RegisterLogicalAgentInput): Promise<LogicalAgentRecord> {\n\t\tconst logicalAgentId = input.logicalAgentId ?? this._idFactory();\n\t\tconst existing = await this._store.load(logicalAgentId);\n\t\tif (existing.status === \"ok\") return existing.record;\n\t\tif (existing.status === \"corrupt\") {\n\t\t\tthrow new Error(`Cannot register logical agent ${logicalAgentId}: corrupt record (${existing.diagnostic})`);\n\t\t}\n\t\tconst record = createLogicalAgentRecord({\n\t\t\tlogicalAgentId,\n\t\t\tparentAgentId: input.parentAgentId,\n\t\t\tmissionId: input.missionId,\n\t\t\tassignmentId: input.assignmentId,\n\t\t\tattemptId: input.attemptId,\n\t\t\texecutionId: input.executionId,\n\t\t\tworkerId: input.workerId,\n\t\t\texecutorId: input.executorId,\n\t\t\tmodelPolicy: input.modelPolicy,\n\t\t\tsessionId: input.sessionId,\n\t\t\tsessionDir: input.sessionDir,\n\t\t\tevidenceRefs: input.evidenceRefs,\n\t\t\tactivity: input.activity ?? \"RUNNABLE\",\n\t\t\tpriority: input.priority,\n\t\t\tnow: this._now(),\n\t\t});\n\t\tconst saved = await this._store.save(record);\n\t\tif (saved.status === \"saved\") return saved.record;\n\t\tthrow new Error(`Failed to register logical agent ${logicalAgentId}: stale revision`);\n\t}\n\n\tasync inspect(logicalAgentId: string): Promise<LogicalAgentRecord | undefined> {\n\t\tconst loaded = await this._store.load(logicalAgentId);\n\t\tif (loaded.status === \"ok\") return loaded.record;\n\t\tif (loaded.status === \"missing\") return undefined;\n\t\tthrow new Error(`Corrupt logical agent ${logicalAgentId}: ${loaded.diagnostic}`);\n\t}\n\n\tasync list(): Promise<LogicalAgentRecord[]> {\n\t\tconst ids = await this._store.list();\n\t\tconst records: LogicalAgentRecord[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst loaded = await this._store.load(id);\n\t\t\tif (loaded.status === \"ok\") records.push(loaded.record);\n\t\t}\n\t\treturn records.sort((a, b) => a.createdAtMs - b.createdAtMs || (a.logicalAgentId < b.logicalAgentId ? -1 : 1));\n\t}\n\n\t/** Transition activity with a waiting reason. Optimistic revision guarded. */\n\tasync transition(\n\t\tlogicalAgentId: string,\n\t\tactivity: LogicalAgentActivity,\n\t\toptions: {\n\t\t\twaitingReason?: string;\n\t\t\tpendingInferenceRequestId?: string;\n\t\t\texecutionId?: string;\n\t\t\tattemptId?: string;\n\t\t\tassignmentId?: string;\n\t\t} = {},\n\t): Promise<LogicalAgentRecord> {\n\t\t// Control planes may race (e.g. a fire-and-forget release handler and an\n\t\t// explicit operator transition). Retry a bounded number of times on stale\n\t\t// revision; the last load wins deterministically.\n\t\tfor (let attempt = 0; attempt < 5; attempt++) {\n\t\t\tlet loaded = await this._store.load(logicalAgentId);\n\t\t\tif (loaded.status === \"missing\") {\n\t\t\t\t// A logical agent may begin inference before an explicit register\n\t\t\t\t// call. Auto-register a minimal durable record (idempotent) so the\n\t\t\t\t// read/control model is self-sufficient.\n\t\t\t\tawait this.register({ logicalAgentId, sessionId: logicalAgentId });\n\t\t\t\tloaded = await this._store.load(logicalAgentId);\n\t\t\t}\n\t\t\tif (loaded.status !== \"ok\") throw new Error(`Logical agent ${logicalAgentId} not found`);\n\t\t\tconst current = loaded.record;\n\t\t\tconst next: LogicalAgentRecord = {\n\t\t\t\t...current,\n\t\t\t\tactivity,\n\t\t\t\twaitingReason: options.waitingReason,\n\t\t\t\tpendingInferenceRequestId: Object.hasOwn(options, \"pendingInferenceRequestId\")\n\t\t\t\t\t? options.pendingInferenceRequestId\n\t\t\t\t\t: current.pendingInferenceRequestId,\n\t\t\t\texecutionId: Object.hasOwn(options, \"executionId\") ? options.executionId : current.executionId,\n\t\t\t\tattemptId: Object.hasOwn(options, \"attemptId\") ? options.attemptId : current.attemptId,\n\t\t\t\tassignmentId: Object.hasOwn(options, \"assignmentId\") ? options.assignmentId : current.assignmentId,\n\t\t\t\tupdatedAtMs: this._now(),\n\t\t\t};\n\t\t\tconst saved = await this._store.save(next, { expectedRevision: current.revision });\n\t\t\tif (saved.status === \"saved\") return saved.record;\n\t\t}\n\t\tthrow new Error(`Logical agent ${logicalAgentId} transition conflicted after retries (stale revision)`);\n\t}\n\n\t/** Park a logical agent (durable identity + reason preserved; no hot KV reservation). */\n\tasync park(logicalAgentId: string, reason: string): Promise<LogicalAgentRecord> {\n\t\treturn this.transition(logicalAgentId, \"PARKED\", {\n\t\t\twaitingReason: reason,\n\t\t\tpendingInferenceRequestId: undefined,\n\t\t});\n\t}\n\n\t/** Resume a parked/waiting agent back to RUNNABLE. */\n\tasync resume(logicalAgentId: string): Promise<LogicalAgentRecord> {\n\t\treturn this.transition(logicalAgentId, \"RUNNABLE\", {\n\t\t\twaitingReason: undefined,\n\t\t\tpendingInferenceRequestId: undefined,\n\t\t});\n\t}\n\n\tasync cancel(logicalAgentId: string, reason?: string): Promise<LogicalAgentRecord> {\n\t\treturn this.transition(logicalAgentId, \"CANCELLED\", { waitingReason: reason });\n\t}\n\n\tasync complete(logicalAgentId: string, state: \"COMPLETED\" | \"FAILED\" = \"COMPLETED\"): Promise<LogicalAgentRecord> {\n\t\treturn this.transition(logicalAgentId, state, { waitingReason: undefined, pendingInferenceRequestId: undefined });\n\t}\n\n\t/** Deterministic activity counts (used to enrich scheduler status). */\n\tasync activityCounts(): Promise<ActivityCounts> {\n\t\tconst records = await this.list();\n\t\tconst counts: ActivityCounts = {\n\t\t\trunningInference: 0,\n\t\t\twaitingInference: 0,\n\t\t\ttooling: 0,\n\t\t\tparked: 0,\n\t\t\trunnable: 0,\n\t\t\ttotal: records.length,\n\t\t};\n\t\tfor (const record of records) {\n\t\t\tswitch (record.activity) {\n\t\t\t\tcase \"RUNNING_INFERENCE\":\n\t\t\t\t\tcounts.runningInference += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"WAITING_INFERENCE\":\n\t\t\t\t\tcounts.waitingInference += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"RUNNING_TOOL\":\n\t\t\t\tcase \"WAITING_TOOL\":\n\t\t\t\tcase \"VERIFYING\":\n\t\t\t\t\tcounts.tooling += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"PARKED\":\n\t\t\t\t\tcounts.parked += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"RUNNABLE\":\n\t\t\t\t\tcounts.runnable += 1;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn counts;\n\t}\n}\n"]}