{"version":3,"file":"external-runs.d.ts","sourceRoot":"","sources":["../../../src/api/external-runs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,yBAAyB,kCAAkC,CAAC;AAMzE,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC9E,MAAM,MAAM,2BAA2B,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEtH,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,IAAI,SAAS,WAAW,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAsB,SAAQ,WAAW;IACzD,QAAQ,EAAE,MAAM,CAAC;CACjB;AAuHD,uGAAuG;AACvG,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAkBrF;AAED,4GAA4G;AAC5G,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,qBAAqB,EAAE,CAwBxF","sourcesContent":["export const EXTERNAL_RUN_REGISTRY_VERSION = 1;\nexport const EXTERNAL_RUN_REGISTRY_KEY = \"pi-subagents.external-runs.v1\";\n\nconst MAX_PROVIDERS = 100;\nconst MAX_RUNS_PER_PROVIDER = 10_000;\nconst MAX_TEXT_LENGTH = 4_096;\n\nexport type ExternalRunState = \"running\" | \"completed\" | \"failed\" | \"stopped\";\nexport type ExternalRunCompletionReason = \"exit\" | \"timeout\" | \"user-kill\" | \"auto-close-quiet\" | \"crash\" | \"unknown\";\n\n/** An observational record for work owned by another runtime. */\nexport interface ExternalRun {\n\tid: string;\n\tsessionId: string;\n\tsource: string;\n\tstate: ExternalRunState;\n\tcommand?: string;\n\tcwd?: string;\n\tisolationPath?: string;\n\towner?: string;\n\tcompletionReason?: ExternalRunCompletionReason;\n\treportPath?: string;\n\tstartedAt?: number;\n\tcompletedAt?: number;\n\texitCode?: number | null;\n\tresidualRisks?: string[];\n}\n\nexport interface ExternalRunProvider {\n\tname: string;\n\tlistExternalRuns(): readonly ExternalRun[];\n}\n\nexport interface RegisteredExternalRun extends ExternalRun {\n\tprovider: string;\n}\n\ninterface ExternalRunRegistry {\n\tversion: typeof EXTERNAL_RUN_REGISTRY_VERSION;\n\tproviders: Map<string, ExternalRunProvider>;\n}\n\nfunction registry(): ExternalRunRegistry {\n\tconst key = Symbol.for(EXTERNAL_RUN_REGISTRY_KEY);\n\tconst target = globalThis as Record<PropertyKey, unknown>;\n\tconst existing = target[key];\n\tif (existing === undefined) {\n\t\tconst created: ExternalRunRegistry = { version: EXTERNAL_RUN_REGISTRY_VERSION, providers: new Map() };\n\t\ttarget[key] = created;\n\t\treturn created;\n\t}\n\tif (!existing || typeof existing !== \"object\" || Array.isArray(existing))\n\t\tthrow new Error(`Malformed external-run registry at Symbol.for(\"${EXTERNAL_RUN_REGISTRY_KEY}\").`);\n\tconst candidate = existing as Partial<ExternalRunRegistry>;\n\tif (candidate.version !== EXTERNAL_RUN_REGISTRY_VERSION || !(candidate.providers instanceof Map))\n\t\tthrow new Error(`Unsupported external-run registry at Symbol.for(\"${EXTERNAL_RUN_REGISTRY_KEY}\").`);\n\treturn candidate as ExternalRunRegistry;\n}\n\nfunction text(value: unknown, field: string, required = false): string | undefined {\n\tif (value === undefined && !required) return undefined;\n\tif (typeof value !== \"string\" || value.length === 0 || value.trim() !== value || value.includes(\"\\0\"))\n\t\tthrow new Error(`${field} must be a non-empty trimmed string without NUL characters.`);\n\tif (value.length > MAX_TEXT_LENGTH) throw new Error(`${field} must be at most ${MAX_TEXT_LENGTH} characters.`);\n\treturn value;\n}\n\nfunction timestamp(value: unknown, field: string): number | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0)\n\t\tthrow new Error(`${field} must be a non-negative finite number.`);\n\treturn value;\n}\n\nfunction validateRun(value: unknown, provider: string, index: number): ExternalRun {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} must be an object.`);\n\tconst run = value as Record<string, unknown>;\n\tconst fields = new Set([\n\t\t\"id\",\n\t\t\"sessionId\",\n\t\t\"source\",\n\t\t\"state\",\n\t\t\"command\",\n\t\t\"cwd\",\n\t\t\"isolationPath\",\n\t\t\"owner\",\n\t\t\"completionReason\",\n\t\t\"reportPath\",\n\t\t\"startedAt\",\n\t\t\"completedAt\",\n\t\t\"exitCode\",\n\t\t\"residualRisks\",\n\t]);\n\tconst unknown = Object.keys(run).filter((key) => !fields.has(key));\n\tif (unknown.length)\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} has unknown fields: ${unknown.join(\", \")}.`);\n\tif (![\"running\", \"completed\", \"failed\", \"stopped\"].includes(run.state as string))\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} state is invalid.`);\n\tif (\n\t\trun.completionReason !== undefined &&\n\t\t![\"exit\", \"timeout\", \"user-kill\", \"auto-close-quiet\", \"crash\", \"unknown\"].includes(run.completionReason as string)\n\t)\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} completionReason is invalid.`);\n\tif (\n\t\trun.exitCode !== undefined &&\n\t\trun.exitCode !== null &&\n\t\t(!Number.isInteger(run.exitCode) || !Number.isFinite(run.exitCode))\n\t)\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} exitCode must be an integer or null.`);\n\tif (\n\t\trun.residualRisks !== undefined &&\n\t\t(!Array.isArray(run.residualRisks) ||\n\t\t\trun.residualRisks.some(\n\t\t\t\t(risk, riskIndex) =>\n\t\t\t\t\ttext(risk, `External-run provider '${provider}' item ${index} residualRisks[${riskIndex}]`, true) ===\n\t\t\t\t\tundefined,\n\t\t\t))\n\t)\n\t\tthrow new Error(`External-run provider '${provider}' item ${index} residualRisks must be an array of strings.`);\n\treturn {\n\t\tid: text(run.id, `External-run provider '${provider}' item ${index} id`, true)!,\n\t\tsessionId: text(run.sessionId, `External-run provider '${provider}' item ${index} sessionId`, true)!,\n\t\tsource: text(run.source, `External-run provider '${provider}' item ${index} source`, true)!,\n\t\tstate: run.state as ExternalRunState,\n\t\t...(text(run.command, `External-run provider '${provider}' item ${index} command`) !== undefined\n\t\t\t? { command: text(run.command, `External-run provider '${provider}' item ${index} command`) }\n\t\t\t: {}),\n\t\t...(text(run.cwd, `External-run provider '${provider}' item ${index} cwd`) !== undefined\n\t\t\t? { cwd: text(run.cwd, `External-run provider '${provider}' item ${index} cwd`) }\n\t\t\t: {}),\n\t\t...(text(run.isolationPath, `External-run provider '${provider}' item ${index} isolationPath`) !== undefined\n\t\t\t? { isolationPath: text(run.isolationPath, `External-run provider '${provider}' item ${index} isolationPath`) }\n\t\t\t: {}),\n\t\t...(text(run.owner, `External-run provider '${provider}' item ${index} owner`) !== undefined\n\t\t\t? { owner: text(run.owner, `External-run provider '${provider}' item ${index} owner`) }\n\t\t\t: {}),\n\t\t...(run.completionReason !== undefined\n\t\t\t? { completionReason: run.completionReason as ExternalRunCompletionReason }\n\t\t\t: {}),\n\t\t...(text(run.reportPath, `External-run provider '${provider}' item ${index} reportPath`) !== undefined\n\t\t\t? { reportPath: text(run.reportPath, `External-run provider '${provider}' item ${index} reportPath`) }\n\t\t\t: {}),\n\t\t...(timestamp(run.startedAt, `External-run provider '${provider}' item ${index} startedAt`) !== undefined\n\t\t\t? { startedAt: timestamp(run.startedAt, `External-run provider '${provider}' item ${index} startedAt`) }\n\t\t\t: {}),\n\t\t...(timestamp(run.completedAt, `External-run provider '${provider}' item ${index} completedAt`) !== undefined\n\t\t\t? { completedAt: timestamp(run.completedAt, `External-run provider '${provider}' item ${index} completedAt`) }\n\t\t\t: {}),\n\t\t...(run.exitCode !== undefined ? { exitCode: run.exitCode as number | null } : {}),\n\t\t...(run.residualRisks !== undefined ? { residualRisks: [...run.residualRisks] as string[] } : {}),\n\t};\n}\n\n/** Register an observational provider. pi-subagents never starts, stops, or steers these processes. */\nexport function registerExternalRunProvider(provider: ExternalRunProvider): () => void {\n\tif (\n\t\t!provider ||\n\t\ttypeof provider !== \"object\" ||\n\t\tArray.isArray(provider) ||\n\t\tObject.keys(provider).some((key) => key !== \"name\" && key !== \"listExternalRuns\")\n\t)\n\t\tthrow new Error(\"External-run provider must contain only name and listExternalRuns.\");\n\tconst name = text(provider.name, \"External-run provider name\", true)!;\n\tif (typeof provider.listExternalRuns !== \"function\")\n\t\tthrow new Error(`External-run provider '${name}' must expose listExternalRuns().`);\n\tconst current = registry();\n\tif (!current.providers.has(name) && current.providers.size >= MAX_PROVIDERS)\n\t\tthrow new Error(`External-run registry supports at most ${MAX_PROVIDERS} providers.`);\n\tcurrent.providers.set(name, provider);\n\treturn () => {\n\t\tif (current.providers.get(name) === provider) current.providers.delete(name);\n\t};\n}\n\n/** Snapshot records for one Pi session. Records are read-only observations of foreign process ownership. */\nexport function snapshotExternalRuns(sessionId: string): readonly RegisteredExternalRun[] {\n\ttext(sessionId, \"External-run snapshot sessionId\", true);\n\tconst records: RegisteredExternalRun[] = [];\n\tconst identities = new Set<string>();\n\tfor (const [name, provider] of registry().providers) {\n\t\tif (provider.name !== name)\n\t\t\tthrow new Error(`External-run registry key '${name}' does not match provider name '${provider.name}'.`);\n\t\tconst runs = provider.listExternalRuns();\n\t\tif (!Array.isArray(runs))\n\t\t\tthrow new Error(`External-run provider '${name}' listExternalRuns() must return an array.`);\n\t\tif (runs.length > MAX_RUNS_PER_PROVIDER)\n\t\t\tthrow new Error(`External-run provider '${name}' returned more than ${MAX_RUNS_PER_PROVIDER} runs.`);\n\t\truns.forEach((value, index) => {\n\t\t\tconst run = validateRun(value, name, index);\n\t\t\tconst identity = `${name}\\0${run.sessionId}\\0${run.id}`;\n\t\t\tif (identities.has(identity))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`External-run provider '${name}' returned duplicate run '${run.id}' for session '${run.sessionId}'.`,\n\t\t\t\t);\n\t\t\tidentities.add(identity);\n\t\t\tif (run.sessionId === sessionId) records.push({ provider: name, ...run });\n\t\t});\n\t}\n\treturn records;\n}\n"]}