@ai-devkit/agent-manager 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +1 -342
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/database/DurableAgentsDatabase.test.js +31 -3
- package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +1 -1
- package/dist/__tests__/durable/CodexCliProbe.test.js +129 -0
- package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -0
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +84 -0
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +126 -0
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintAgentService.test.js +271 -0
- package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -0
- package/dist/__tests__/durable/CodexPrintRunner.test.js +393 -0
- package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -0
- package/dist/__tests__/print/ClaudeCliProbe.test.js +3 -7
- package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +25 -28
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgentService.test.js +65 -0
- package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintRunner.test.js +4 -10
- package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +79 -0
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -0
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +436 -0
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +76 -0
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +43 -0
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +202 -0
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +119 -0
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +386 -0
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +34 -0
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -0
- package/dist/__tests__/utils/ClaudeSessionParser.test.js +2 -2
- package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/database/migrations/004_codex_durable_sessions.sql +1 -0
- package/dist/durable/DurableAgent.d.ts +23 -3
- package/dist/durable/DurableAgent.d.ts.map +1 -1
- package/dist/durable/DurableAgent.js +12 -0
- package/dist/durable/DurableAgent.js.map +1 -1
- package/dist/durable/DurableAgentRepository.d.ts +6 -7
- package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
- package/dist/durable/DurableAgentRepository.js +73 -42
- package/dist/durable/DurableAgentRepository.js.map +1 -1
- package/dist/durable/process.d.ts +8 -0
- package/dist/durable/process.d.ts.map +1 -0
- package/dist/durable/process.js +40 -0
- package/dist/durable/process.js.map +1 -0
- package/dist/durable/run.d.ts +32 -0
- package/dist/durable/run.d.ts.map +1 -0
- package/dist/durable/run.js +46 -0
- package/dist/durable/run.js.map +1 -0
- package/dist/durable/utils.d.ts +19 -0
- package/dist/durable/utils.d.ts.map +1 -0
- package/dist/durable/utils.js +52 -0
- package/dist/durable/utils.js.map +1 -0
- package/dist/index.d.ts +17 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/dist/providers/claude/ClaudeAgentMapper.d.ts +21 -0
- package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -0
- package/dist/providers/claude/ClaudeAgentMapper.js +42 -0
- package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts +29 -0
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -0
- package/dist/providers/claude/ClaudeCodeAdapter.js +129 -0
- package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -0
- package/dist/{adapters/ClaudeCodeAdapter.d.ts → providers/claude/ClaudeSessionLocator.d.ts} +68 -52
- package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -0
- package/dist/{adapters/ClaudeCodeAdapter.js → providers/claude/ClaudeSessionLocator.js} +71 -189
- package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -0
- package/dist/{utils → providers/claude}/ClaudeSessionParser.d.ts +2 -2
- package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -0
- package/dist/{utils → providers/claude}/ClaudeSessionParser.js +1 -1
- package/dist/providers/claude/ClaudeSessionParser.js.map +1 -0
- package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.js +4 -9
- package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudePrintAgentService.d.ts +4 -9
- package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudePrintAgentService.js +45 -0
- package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -0
- package/dist/{durable → providers/claude/durable}/ClaudePrintRunner.d.ts +3 -3
- package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudePrintRunner.js +75 -0
- package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +17 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.js +69 -0
- package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -0
- package/dist/providers/codex/durable/CodexCliProbe.d.ts +20 -0
- package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexCliProbe.js +61 -0
- package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +40 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.js +50 -0
- package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -0
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts +34 -0
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexPrintRunner.js +78 -0
- package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -0
- package/dist/providers/codex/durable/CodexStreamParser.d.ts +21 -0
- package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -0
- package/dist/providers/codex/durable/CodexStreamParser.js +86 -0
- package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -0
- package/dist/providers/pi/durable/PiCliProbe.d.ts +20 -0
- package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiCliProbe.js +51 -0
- package/dist/providers/pi/durable/PiCliProbe.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts +39 -0
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintAgentService.js +47 -0
- package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintProtocol.d.ts +4 -0
- package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintProtocol.js +44 -0
- package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -0
- package/dist/providers/pi/durable/PiPrintRunner.d.ts +32 -0
- package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiPrintRunner.js +61 -0
- package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -0
- package/dist/providers/pi/durable/PiStreamParser.d.ts +21 -0
- package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -0
- package/dist/providers/pi/durable/PiStreamParser.js +71 -0
- package/dist/providers/pi/durable/PiStreamParser.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1 -307
- package/src/__tests__/database/DurableAgentsDatabase.test.ts +28 -3
- package/src/__tests__/durable/CodexCliProbe.test.ts +63 -0
- package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +54 -0
- package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +79 -0
- package/src/__tests__/durable/CodexPrintAgentService.test.ts +139 -0
- package/src/__tests__/durable/CodexPrintRunner.test.ts +189 -0
- package/src/__tests__/fixtures/fake-codex.cjs +45 -0
- package/src/__tests__/print/ClaudeCliProbe.test.ts +3 -7
- package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +11 -21
- package/src/__tests__/print/ClaudePrintAgentService.test.ts +33 -1
- package/src/__tests__/print/ClaudePrintRunner.test.ts +4 -10
- package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +84 -0
- package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +411 -0
- package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +38 -0
- package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +32 -0
- package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +69 -0
- package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +33 -0
- package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +107 -0
- package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +24 -0
- package/src/__tests__/utils/ClaudeSessionParser.test.ts +2 -2
- package/src/adapters/index.ts +1 -1
- package/src/database/migrations/004_codex_durable_sessions.sql +1 -0
- package/src/durable/DurableAgent.ts +51 -3
- package/src/durable/DurableAgentRepository.ts +60 -31
- package/src/durable/process.ts +28 -0
- package/src/durable/run.ts +74 -0
- package/src/durable/utils.ts +61 -0
- package/src/index.ts +31 -15
- package/src/providers/claude/ClaudeAgentMapper.ts +62 -0
- package/src/providers/claude/ClaudeCodeAdapter.ts +160 -0
- package/src/{adapters/ClaudeCodeAdapter.ts → providers/claude/ClaudeSessionLocator.ts} +97 -239
- package/src/{utils → providers/claude}/ClaudeSessionParser.ts +2 -2
- package/src/{durable → providers/claude/durable}/ClaudeCliProbe.ts +4 -10
- package/src/providers/claude/durable/ClaudePrintAgentService.ts +66 -0
- package/src/providers/claude/durable/ClaudePrintRunner.ts +92 -0
- package/src/providers/claude/durable/ClaudeStreamParser.ts +79 -0
- package/src/providers/codex/durable/CodexCliProbe.ts +60 -0
- package/src/providers/codex/durable/CodexPrintAgentService.ts +65 -0
- package/src/providers/codex/durable/CodexPrintRunner.ts +94 -0
- package/src/providers/codex/durable/CodexStreamParser.ts +104 -0
- package/src/providers/pi/durable/PiCliProbe.ts +48 -0
- package/src/providers/pi/durable/PiPrintAgentService.ts +69 -0
- package/src/providers/pi/durable/PiPrintProtocol.ts +39 -0
- package/src/providers/pi/durable/PiPrintRunner.ts +88 -0
- package/src/providers/pi/durable/PiStreamParser.ts +84 -0
- package/dist/adapters/ClaudeCodeAdapter.d.ts.map +0 -1
- package/dist/adapters/ClaudeCodeAdapter.js.map +0 -1
- package/dist/durable/ClaudeCliProbe.d.ts.map +0 -1
- package/dist/durable/ClaudeCliProbe.js.map +0 -1
- package/dist/durable/ClaudePrintAgentService.d.ts.map +0 -1
- package/dist/durable/ClaudePrintAgentService.js +0 -66
- package/dist/durable/ClaudePrintAgentService.js.map +0 -1
- package/dist/durable/ClaudePrintRunner.d.ts.map +0 -1
- package/dist/durable/ClaudePrintRunner.js +0 -128
- package/dist/durable/ClaudePrintRunner.js.map +0 -1
- package/dist/utils/ClaudeSessionParser.d.ts.map +0 -1
- package/dist/utils/ClaudeSessionParser.js.map +0 -1
- package/src/durable/ClaudePrintAgentService.ts +0 -94
- package/src/durable/ClaudePrintRunner.ts +0 -139
- /package/dist/{durable → providers/claude/durable}/ClaudeCliProbe.d.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DurableAgent.d.ts","sourceRoot":"","sources":["../../src/durable/DurableAgent.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AACjE,MAAM,MAAM,oBAAoB,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AACxF,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"DurableAgent.d.ts","sourceRoot":"","sources":["../../src/durable/DurableAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,5 +42,17 @@ export class ClaudePrintError extends DurableAgentError {
|
|
|
42
42
|
this.name = 'ClaudePrintError';
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
export class CodexPrintError extends DurableAgentError {
|
|
46
|
+
constructor(message, code){
|
|
47
|
+
super(message, code);
|
|
48
|
+
this.name = 'CodexPrintError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export class PiPrintError extends DurableAgentError {
|
|
52
|
+
constructor(message, code = 'PI_PROCESS'){
|
|
53
|
+
super(message, code);
|
|
54
|
+
this.name = 'PiPrintError';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
|
|
46
58
|
//# sourceMappingURL=DurableAgent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/durable/DurableAgent.ts"],"sourcesContent":["export type DurableAgentState = 'ready' | 'running' | 'degraded';\nexport type DurableSessionHealth = 'uninitialized' | 'healthy' | 'unknown' | 'mismatch';\nexport type DurableRunStatus = 'succeeded' | 'failed' | 'interrupted';\n\nexport const AGENT_MODES = {\n INTERACTIVE: 'interactive',\n DURABLE: 'durable',\n} as const;\n\nexport interface ProcessIdentity {\n pid: number;\n startedAt: string;\n}\n\nexport interface DurableActiveRun {\n token: string;\n owner: ProcessIdentity;\n provider: ProcessIdentity | null;\n startedAt: string;\n}\n\nexport interface DurableLastResult {\n status: DurableRunStatus;\n completedAt: string;\n exitCode: number | null;\n summary: string;\n}\n\nexport interface
|
|
1
|
+
{"version":3,"sources":["../../src/durable/DurableAgent.ts"],"sourcesContent":["export type DurableAgentState = 'ready' | 'running' | 'degraded';\nexport type DurableSessionHealth = 'uninitialized' | 'healthy' | 'unknown' | 'mismatch';\nexport type DurableRunStatus = 'succeeded' | 'failed' | 'interrupted';\nexport type PiPrintErrorCode =\n | 'PI_CLI_UNAVAILABLE'\n | 'PI_CLI_UNSUPPORTED'\n | 'PI_PROCESS'\n | 'PI_PROTOCOL'\n | 'PI_RESULT_MISSING'\n | 'PI_SESSION_MISMATCH'\n | 'PI_UNSUPPORTED';\n\nexport const AGENT_MODES = {\n INTERACTIVE: 'interactive',\n DURABLE: 'durable',\n} as const;\n\nexport interface ProcessIdentity {\n pid: number;\n startedAt: string;\n}\n\nexport interface DurableActiveRun {\n token: string;\n owner: ProcessIdentity;\n provider: ProcessIdentity | null;\n startedAt: string;\n}\n\nexport interface DurableLastResult {\n status: DurableRunStatus;\n completedAt: string;\n exitCode: number | null;\n summary: string;\n}\n\nexport type DurableProvider = 'claude' | 'codex' | 'pi';\n\nexport interface DurableAgentBase {\n id: string;\n name: string;\n mode: typeof AGENT_MODES.DURABLE;\n cwd: string;\n state: DurableAgentState;\n sessionHealth: DurableSessionHealth;\n createdAt: string;\n updatedAt: string;\n lastActiveAt: string | null;\n lastResult: DurableLastResult | null;\n activeRun: DurableActiveRun | null;\n}\n\nexport interface ClaudeDurableAgent extends DurableAgentBase {\n provider: 'claude';\n providerSessionId: string;\n}\n\nexport interface CodexDurableAgent extends DurableAgentBase {\n provider: 'codex';\n providerSessionId: string | null;\n}\n\nexport interface PiDurableAgent extends DurableAgentBase {\n provider: 'pi';\n providerSessionId: string;\n}\n\nexport type DurableAgent = ClaudeDurableAgent | CodexDurableAgent | PiDurableAgent;\n\nexport class DurableAgentError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = 'DurableAgentError';\n }\n}\n\nexport class DurableAgentBusyError extends DurableAgentError {\n constructor(\n public readonly agentId: string,\n agentName: string,\n ) {\n super(`Durable agent \"${agentName}\" is busy.`, 'DURABLE_AGENT_BUSY');\n this.name = 'DurableAgentBusyError';\n }\n}\n\nexport class DurableAgentNotFoundError extends DurableAgentError {\n constructor(public readonly reference: string) {\n super(`Durable agent \"${reference}\" was not found.`, 'DURABLE_AGENT_NOT_FOUND');\n this.name = 'DurableAgentNotFoundError';\n }\n}\n\nexport class DurableAgentRepositoryError extends DurableAgentError {\n constructor(message: string) {\n super(message, 'DURABLE_AGENT_REPOSITORY');\n this.name = 'DurableAgentRepositoryError';\n }\n}\n\nexport class DurableAgentNameConflictError extends DurableAgentError {\n constructor(public readonly agentName: string) {\n super(`Durable agent name \"${agentName}\" is already in use.`, 'DURABLE_AGENT_NAME_CONFLICT');\n this.name = 'DurableAgentNameConflictError';\n }\n}\n\nexport class ClaudePrintError extends DurableAgentError {\n constructor(message: string, code = 'CLAUDE_PRINT_FAILED') {\n super(message, code);\n this.name = 'ClaudePrintError';\n }\n}\n\nexport type CodexPrintErrorCode =\n | 'CODEX_PROTOCOL'\n | 'CODEX_PROCESS'\n | 'CODEX_SESSION_MISMATCH'\n | 'CODEX_UNSUPPORTED'\n | 'CODEX_RESULT_MISSING'\n | 'CODEX_CLI_UNSUPPORTED'\n | 'CODEX_CLI_UNAVAILABLE';\n\nexport class CodexPrintError extends DurableAgentError {\n constructor(message: string, code: CodexPrintErrorCode) {\n super(message, code);\n this.name = 'CodexPrintError';\n }\n}\n\nexport class PiPrintError extends DurableAgentError {\n constructor(message: string, code: PiPrintErrorCode = 'PI_PROCESS') {\n super(message, code);\n this.name = 'PiPrintError';\n }\n}\n"],"names":["AGENT_MODES","INTERACTIVE","DURABLE","DurableAgentError","Error","message","code","name","DurableAgentBusyError","agentId","agentName","DurableAgentNotFoundError","reference","DurableAgentRepositoryError","DurableAgentNameConflictError","ClaudePrintError","CodexPrintError","PiPrintError"],"mappings":"AAYA,OAAO,MAAMA,cAAc;IACvBC,aAAa;IACbC,SAAS;AACb,EAAW;AAsDX,OAAO,MAAMC,0BAA0BC;;IACnC,YACIC,OAAe,EACf,AAAgBC,IAAY,CAC9B;QACE,KAAK,CAACD,eAFUC,OAAAA;QAGhB,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMC,8BAA8BL;;IACvC,YACI,AAAgBM,OAAe,EAC/BC,SAAiB,CACnB;QACE,KAAK,CAAC,CAAC,eAAe,EAAEA,UAAU,UAAU,CAAC,EAAE,4BAH/BD,UAAAA;QAIhB,IAAI,CAACF,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMI,kCAAkCR;;IAC3C,YAAY,AAAgBS,SAAiB,CAAE;QAC3C,KAAK,CAAC,CAAC,eAAe,EAAEA,UAAU,gBAAgB,CAAC,EAAE,iCAD7BA,YAAAA;QAExB,IAAI,CAACL,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMM,oCAAoCV;IAC7C,YAAYE,OAAe,CAAE;QACzB,KAAK,CAACA,SAAS;QACf,IAAI,CAACE,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMO,sCAAsCX;;IAC/C,YAAY,AAAgBO,SAAiB,CAAE;QAC3C,KAAK,CAAC,CAAC,oBAAoB,EAAEA,UAAU,oBAAoB,CAAC,EAAE,qCADtCA,YAAAA;QAExB,IAAI,CAACH,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMQ,yBAAyBZ;IAClC,YAAYE,OAAe,EAAEC,OAAO,qBAAqB,CAAE;QACvD,KAAK,CAACD,SAASC;QACf,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ;AAWA,OAAO,MAAMS,wBAAwBb;IACjC,YAAYE,OAAe,EAAEC,IAAyB,CAAE;QACpD,KAAK,CAACD,SAASC;QACf,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ;AAEA,OAAO,MAAMU,qBAAqBd;IAC9B,YAAYE,OAAe,EAAEC,OAAyB,YAAY,CAAE;QAChE,KAAK,CAACD,SAASC;QACf,IAAI,CAACC,IAAI,GAAG;IAChB;AACJ"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { type DurableAgent, type ProcessIdentity, type DurableRunStatus, type DurableSessionHealth } from './DurableAgent.js';
|
|
1
|
+
import { type DurableAgent, type DurableProvider, type ProcessIdentity, type DurableRunStatus, type DurableSessionHealth } from './DurableAgent.js';
|
|
2
|
+
import { type ProcessInspector } from './process.js';
|
|
2
3
|
export interface CreateDurableAgentInput {
|
|
3
4
|
name: string;
|
|
4
5
|
cwd: string;
|
|
6
|
+
provider?: DurableProvider;
|
|
5
7
|
}
|
|
6
8
|
export interface DurableAgentRepositoryOptions {
|
|
7
9
|
dbPath?: string;
|
|
@@ -15,9 +17,8 @@ export interface DurableAgentRepositoryOptions {
|
|
|
15
17
|
/** @deprecated SQLite transactions replace mutation lock directories. */
|
|
16
18
|
mutationLockStaleMs?: number;
|
|
17
19
|
}
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
}
|
|
20
|
+
export { LocalProcessInspector } from './process.js';
|
|
21
|
+
export type { ProcessInspector } from './process.js';
|
|
21
22
|
export interface DurableRunCompletion {
|
|
22
23
|
status: DurableRunStatus;
|
|
23
24
|
exitCode: number | null;
|
|
@@ -40,6 +41,7 @@ export declare class DurableAgentRepository {
|
|
|
40
41
|
token: string;
|
|
41
42
|
}>;
|
|
42
43
|
recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void>;
|
|
44
|
+
bindProviderSession(id: string, token: string, providerSessionId: string): Promise<DurableAgent>;
|
|
43
45
|
completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent>;
|
|
44
46
|
reconcile(): Promise<void>;
|
|
45
47
|
private immediate;
|
|
@@ -54,7 +56,4 @@ export declare class DurableAgentRepository {
|
|
|
54
56
|
private assertWritable;
|
|
55
57
|
private storageError;
|
|
56
58
|
}
|
|
57
|
-
export declare class LocalProcessInspector implements ProcessInspector {
|
|
58
|
-
getIdentity(pid: number): ProcessIdentity | null;
|
|
59
|
-
}
|
|
60
59
|
//# sourceMappingURL=DurableAgentRepository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DurableAgentRepository.d.ts","sourceRoot":"","sources":["../../src/durable/DurableAgentRepository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DurableAgentRepository.d.ts","sourceRoot":"","sources":["../../src/durable/DurableAgentRepository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuD,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzM,OAAO,EAAyB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAkB5E,MAAM,WAAW,uBAAuB;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,CAAA;CAAE;AAElG,MAAM,WAAW,6BAA6B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,4DAA4D;IAC5D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,oBAAoB,CAAC;CAC3G;AAED,qBAAa,sBAAsB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAqB;gBAE5B,OAAO,GAAE,6BAAkC;IAajD,MAAM,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB7D,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAK/B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAKjD,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IAQzE,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAkDvE,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1F,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAoChG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC;IAgB3F,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBhC,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,OAAO;IAUf,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,OAAO;IAgCf,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;CAIvB"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { randomUUID } from 'crypto';
|
|
3
|
-
import { execFileSync } from 'child_process';
|
|
4
3
|
import { DatabaseConnection, DEFAULT_AGENT_REGISTRY_DB_PATH } from '../database/index.js';
|
|
5
|
-
import { AGENT_MODES } from './DurableAgent.js';
|
|
4
|
+
import { AGENT_MODES, CodexPrintError } from './DurableAgent.js';
|
|
5
|
+
import { LocalProcessInspector } from './process.js';
|
|
6
|
+
import { isUuid } from './utils.js';
|
|
6
7
|
import { DurableAgentBusyError, DurableAgentNameConflictError, DurableAgentNotFoundError, DurableAgentRepositoryError } from './DurableAgent.js';
|
|
8
|
+
export { LocalProcessInspector } from './process.js';
|
|
7
9
|
export class DurableAgentRepository {
|
|
8
10
|
dbPath;
|
|
9
11
|
now;
|
|
@@ -30,14 +32,16 @@ export class DurableAgentRepository {
|
|
|
30
32
|
const cwd = this.canonicalDirectory(input.cwd);
|
|
31
33
|
const timestamp = this.now().toISOString();
|
|
32
34
|
const id = randomUUID();
|
|
33
|
-
|
|
35
|
+
const provider = input.provider ?? 'claude';
|
|
36
|
+
let providerSessionId = provider === 'codex' ? null : randomUUID();
|
|
34
37
|
while(providerSessionId === id)providerSessionId = randomUUID();
|
|
35
38
|
try {
|
|
36
39
|
this.db.execute(`INSERT INTO durable_agents (
|
|
37
40
|
id, name, provider, mode, cwd, provider_session_id, state, session_health, created_at, updated_at
|
|
38
|
-
) VALUES (?, ?,
|
|
41
|
+
) VALUES (?, ?, ?, ?, ?, ?, 'ready', 'uninitialized', ?, ?)`, [
|
|
39
42
|
id,
|
|
40
43
|
input.name,
|
|
44
|
+
provider,
|
|
41
45
|
AGENT_MODES.DURABLE,
|
|
42
46
|
cwd,
|
|
43
47
|
providerSessionId,
|
|
@@ -142,6 +146,44 @@ export class DurableAgentRepository {
|
|
|
142
146
|
]);
|
|
143
147
|
if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');
|
|
144
148
|
}
|
|
149
|
+
async bindProviderSession(id, token, providerSessionId) {
|
|
150
|
+
this.assertWritable();
|
|
151
|
+
if (!isUuid(providerSessionId)) {
|
|
152
|
+
throw new DurableAgentRepositoryError('Invalid provider session id.');
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
this.immediate(()=>{
|
|
156
|
+
const agent = this.findById(id);
|
|
157
|
+
if (!agent) throw new DurableAgentNotFoundError(id);
|
|
158
|
+
if (agent.provider !== 'codex') {
|
|
159
|
+
throw new DurableAgentRepositoryError('Only Codex durable sessions can be bound after creation.');
|
|
160
|
+
}
|
|
161
|
+
if (agent.activeRun?.token !== token) {
|
|
162
|
+
throw new DurableAgentRepositoryError('Print run ownership changed.');
|
|
163
|
+
}
|
|
164
|
+
if (agent.providerSessionId !== null && agent.providerSessionId !== providerSessionId) {
|
|
165
|
+
throw new CodexPrintError('Durable agent provider session identity does not match.', 'CODEX_SESSION_MISMATCH');
|
|
166
|
+
}
|
|
167
|
+
if (agent.providerSessionId === providerSessionId) return;
|
|
168
|
+
const changed = this.db.execute(`UPDATE durable_agents SET provider_session_id = ?, updated_at = ?
|
|
169
|
+
WHERE id = ? AND provider = 'codex' AND state = 'running' AND active_run_token = ?
|
|
170
|
+
AND provider_session_id IS NULL`, [
|
|
171
|
+
providerSessionId,
|
|
172
|
+
this.now().toISOString(),
|
|
173
|
+
id,
|
|
174
|
+
token
|
|
175
|
+
]);
|
|
176
|
+
if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');
|
|
177
|
+
});
|
|
178
|
+
} catch (error) {
|
|
179
|
+
if (error instanceof DurableAgentRepositoryError || error instanceof DurableAgentNotFoundError || error instanceof CodexPrintError) throw error;
|
|
180
|
+
if (/UNIQUE constraint failed: durable_agents\.provider_session_id/i.test(error.message)) {
|
|
181
|
+
throw new CodexPrintError('Provider session is already bound to another durable agent.', 'CODEX_SESSION_MISMATCH');
|
|
182
|
+
}
|
|
183
|
+
throw this.storageError('Failed to bind durable-agent provider session', error);
|
|
184
|
+
}
|
|
185
|
+
return this.requireById(id);
|
|
186
|
+
}
|
|
145
187
|
async completeRun(id, token, result) {
|
|
146
188
|
this.assertWritable();
|
|
147
189
|
const completedAt = this.now().toISOString();
|
|
@@ -221,6 +263,13 @@ export class DurableAgentRepository {
|
|
|
221
263
|
return agent;
|
|
222
264
|
}
|
|
223
265
|
fromRow(row) {
|
|
266
|
+
if (![
|
|
267
|
+
'claude',
|
|
268
|
+
'codex',
|
|
269
|
+
'pi'
|
|
270
|
+
].includes(row.provider) || row.provider !== 'codex' && row.provider_session_id === null) {
|
|
271
|
+
throw new DurableAgentRepositoryError(`Invalid durable-agent provider record: ${row.id}`);
|
|
272
|
+
}
|
|
224
273
|
const activeRun = row.active_run_token === null ? null : {
|
|
225
274
|
token: row.active_run_token,
|
|
226
275
|
owner: {
|
|
@@ -233,13 +282,12 @@ export class DurableAgentRepository {
|
|
|
233
282
|
},
|
|
234
283
|
startedAt: row.active_run_started_at
|
|
235
284
|
};
|
|
236
|
-
|
|
285
|
+
const base = {
|
|
237
286
|
id: row.id,
|
|
238
287
|
name: row.name,
|
|
239
288
|
provider: row.provider,
|
|
240
289
|
mode: row.mode,
|
|
241
290
|
cwd: row.cwd,
|
|
242
|
-
providerSessionId: row.provider_session_id,
|
|
243
291
|
state: row.state,
|
|
244
292
|
sessionHealth: row.session_health,
|
|
245
293
|
createdAt: row.created_at,
|
|
@@ -253,6 +301,25 @@ export class DurableAgentRepository {
|
|
|
253
301
|
},
|
|
254
302
|
activeRun
|
|
255
303
|
};
|
|
304
|
+
if (row.provider === 'claude') {
|
|
305
|
+
return {
|
|
306
|
+
...base,
|
|
307
|
+
provider: 'claude',
|
|
308
|
+
providerSessionId: row.provider_session_id
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (row.provider === 'pi') {
|
|
312
|
+
return {
|
|
313
|
+
...base,
|
|
314
|
+
provider: 'pi',
|
|
315
|
+
providerSessionId: row.provider_session_id
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
...base,
|
|
320
|
+
provider: 'codex',
|
|
321
|
+
providerSessionId: row.provider_session_id
|
|
322
|
+
};
|
|
256
323
|
}
|
|
257
324
|
canonicalDirectory(input) {
|
|
258
325
|
try {
|
|
@@ -285,41 +352,5 @@ export class DurableAgentRepository {
|
|
|
285
352
|
return error instanceof DurableAgentRepositoryError ? error : new DurableAgentRepositoryError(`${prefix}: ${error.message}`);
|
|
286
353
|
}
|
|
287
354
|
}
|
|
288
|
-
export class LocalProcessInspector {
|
|
289
|
-
getIdentity(pid) {
|
|
290
|
-
if (!Number.isInteger(pid) || pid <= 0) return null;
|
|
291
|
-
try {
|
|
292
|
-
if (process.platform === 'linux') {
|
|
293
|
-
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
294
|
-
const close = stat.lastIndexOf(')');
|
|
295
|
-
const fields = stat.slice(close + 2).split(' ');
|
|
296
|
-
const startTicks = fields[19];
|
|
297
|
-
return startTicks ? {
|
|
298
|
-
pid,
|
|
299
|
-
startedAt: `linux:${startTicks}`
|
|
300
|
-
} : null;
|
|
301
|
-
}
|
|
302
|
-
const startedAt = execFileSync('ps', [
|
|
303
|
-
'-o',
|
|
304
|
-
'lstart=',
|
|
305
|
-
'-p',
|
|
306
|
-
String(pid)
|
|
307
|
-
], {
|
|
308
|
-
encoding: 'utf8',
|
|
309
|
-
stdio: [
|
|
310
|
-
'ignore',
|
|
311
|
-
'pipe',
|
|
312
|
-
'ignore'
|
|
313
|
-
]
|
|
314
|
-
}).trim();
|
|
315
|
-
return startedAt ? {
|
|
316
|
-
pid,
|
|
317
|
-
startedAt
|
|
318
|
-
} : null;
|
|
319
|
-
} catch {
|
|
320
|
-
return null;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
355
|
|
|
325
356
|
//# sourceMappingURL=DurableAgentRepository.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/durable/DurableAgentRepository.ts"],"sourcesContent":["import fs from 'fs';\nimport { randomUUID } from 'crypto';\nimport { execFileSync } from 'child_process';\nimport { DatabaseConnection, DEFAULT_AGENT_REGISTRY_DB_PATH } from '../database/index.js';\nimport { AGENT_MODES, type DurableActiveRun, type DurableAgent, type ProcessIdentity, type DurableRunStatus, type DurableSessionHealth } from './DurableAgent.js';\nimport {\n DurableAgentBusyError,\n DurableAgentNameConflictError,\n DurableAgentNotFoundError,\n DurableAgentRepositoryError,\n} from './DurableAgent.js';\n\ninterface DurableAgentRow {\n id: string; name: string; provider: 'claude'; mode: typeof AGENT_MODES.DURABLE; cwd: string; provider_session_id: string;\n state: DurableAgent['state']; session_health: DurableSessionHealth; created_at: string; updated_at: string;\n last_active_at: string | null; last_result_status: DurableRunStatus | null;\n last_result_completed_at: string | null; last_result_exit_code: number | null; last_result_summary: string | null;\n active_run_token: string | null; active_owner_pid: number | null; active_owner_started_at: string | null;\n active_provider_pid: number | null; active_provider_started_at: string | null; active_run_started_at: string | null;\n}\n\nexport interface CreateDurableAgentInput { name: string; cwd: string }\n\nexport interface DurableAgentRepositoryOptions {\n dbPath?: string;\n readonly?: boolean;\n /** @deprecated SQLite busy_timeout replaces filesystem lock polling. */\n lockTimeoutMs?: number;\n now?: () => Date;\n processInspector?: ProcessInspector;\n /** @deprecated Active ownership is committed atomically. */\n incompleteLockGraceMs?: number;\n /** @deprecated SQLite transactions replace mutation lock directories. */\n mutationLockStaleMs?: number;\n}\n\nexport interface ProcessInspector { getIdentity(pid: number): ProcessIdentity | null }\nexport interface DurableRunCompletion {\n status: DurableRunStatus; exitCode: number | null; summary: string; sessionHealth: DurableSessionHealth;\n}\n\nexport class DurableAgentRepository {\n readonly dbPath: string;\n private readonly now: () => Date;\n private readonly processInspector: ProcessInspector;\n private readonly readonly: boolean;\n private readonly db: DatabaseConnection;\n\n constructor(options: DurableAgentRepositoryOptions = {}) {\n this.dbPath = options.dbPath ?? DEFAULT_AGENT_REGISTRY_DB_PATH;\n this.now = options.now ?? (() => new Date());\n this.processInspector = options.processInspector ?? new LocalProcessInspector();\n this.readonly = options.readonly ?? false;\n try {\n this.db = new DatabaseConnection({ dbPath: this.dbPath, readonly: this.readonly });\n } catch (error) {\n if (error instanceof DurableAgentRepositoryError) throw error;\n throw new DurableAgentRepositoryError(`Cannot open durable-agent database: ${(error as Error).message}`);\n }\n }\n\n async create(input: CreateDurableAgentInput): Promise<DurableAgent> {\n this.assertWritable();\n const cwd = this.canonicalDirectory(input.cwd);\n const timestamp = this.now().toISOString();\n const id = randomUUID();\n let providerSessionId = randomUUID();\n while (providerSessionId === id) providerSessionId = randomUUID();\n try {\n this.db.execute(`INSERT INTO durable_agents (\n id, name, provider, mode, cwd, provider_session_id, state, session_health, created_at, updated_at\n ) VALUES (?, ?, 'claude', ?, ?, ?, 'ready', 'uninitialized', ?, ?)`,\n [id, input.name, AGENT_MODES.DURABLE, cwd, providerSessionId, timestamp, timestamp]);\n } catch (error) {\n if (/UNIQUE constraint failed: durable_agents\\.name/i.test((error as Error).message)) {\n throw new DurableAgentNameConflictError(input.name);\n }\n throw this.storageError('Failed to create durable agent', error);\n }\n return this.requireById(id);\n }\n\n async list(): Promise<DurableAgent[]> {\n if (!this.readonly) await this.reconcile();\n return this.listRaw();\n }\n\n async getById(id: string): Promise<DurableAgent | null> {\n if (!this.readonly) await this.reconcile();\n return this.findById(id);\n }\n\n async resolve(reference: string): Promise<DurableAgent | DurableAgent[] | null> {\n const agents = await this.list();\n const byId = agents.find((agent) => agent.id === reference);\n if (byId) return byId;\n const matches = agents.filter((agent) => agent.name.toLowerCase() === reference.toLowerCase());\n return matches.length === 0 ? null : matches.length === 1 ? matches[0]! : matches;\n }\n\n async acquireRun(id: string): Promise<{ agent: DurableAgent; token: string }> {\n this.assertWritable();\n const snapshot = this.findById(id);\n if (!snapshot) throw new DurableAgentNotFoundError(id);\n this.validateBoundCwd(snapshot.cwd);\n const observed = snapshot.activeRun;\n const observedLive = observed ? this.isActive(observed) : false;\n if (observedLive) throw new DurableAgentBusyError(id, snapshot.name);\n const owner = this.processInspector.getIdentity(process.pid);\n if (!owner) throw new DurableAgentRepositoryError('Cannot determine the current process identity.');\n const token = randomUUID();\n const startedAt = this.now().toISOString();\n let recovered = false;\n try {\n this.immediate(() => {\n const current = this.findById(id);\n if (!current) throw new DurableAgentNotFoundError(id);\n if (current.state === 'running') {\n if (!observed || current.activeRun?.token !== observed.token || observedLive) {\n throw new DurableAgentBusyError(id, current.name);\n }\n recovered = true;\n }\n const changed = this.db.execute(`UPDATE durable_agents SET\n state = 'running', active_run_token = ?, active_owner_pid = ?, active_owner_started_at = ?,\n active_provider_pid = NULL, active_provider_started_at = NULL, active_run_started_at = ?, updated_at = ?,\n session_health = CASE WHEN state = 'running' THEN 'unknown' ELSE session_health END,\n last_result_status = CASE WHEN state = 'running' THEN 'interrupted' ELSE last_result_status END,\n last_result_completed_at = CASE WHEN state = 'running' THEN ? ELSE last_result_completed_at END,\n last_result_exit_code = CASE WHEN state = 'running' THEN NULL ELSE last_result_exit_code END,\n last_result_summary = CASE WHEN state = 'running' THEN 'Previous print run was interrupted.' ELSE last_result_summary END\n WHERE id = ? AND (state <> 'running' OR (\n active_run_token = ? AND active_owner_started_at = ? AND active_run_started_at = ?\n ))\n `, [token, owner.pid, owner.startedAt, startedAt, startedAt, startedAt, id,\n observed?.token ?? null, observed?.owner.startedAt ?? null, observed?.startedAt ?? null]);\n if (changed.changes !== 1) throw new DurableAgentBusyError(id, current.name);\n });\n } catch (error) {\n if (error instanceof DurableAgentBusyError || error instanceof DurableAgentNotFoundError) throw error;\n if (/busy|locked/i.test((error as Error).message)) throw new DurableAgentBusyError(id, snapshot.name);\n throw this.storageError('Failed to acquire durable-agent run', error);\n }\n const agent = this.requireById(id);\n if (recovered && agent.lastResult?.status !== 'interrupted') {\n throw new DurableAgentRepositoryError('Failed to record interrupted print run.');\n }\n return { agent, token };\n }\n\n async recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void> {\n this.assertWritable();\n const changed = this.db.execute(`UPDATE durable_agents SET\n active_provider_pid = ?, active_provider_started_at = ?, updated_at = ?\n WHERE id = ? AND state = 'running' AND active_run_token = ?`,\n [identity.pid, identity.startedAt, this.now().toISOString(), id, token]);\n if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');\n }\n\n async completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent> {\n this.assertWritable();\n const completedAt = this.now().toISOString();\n const changed = this.db.execute(`UPDATE durable_agents SET\n state = ?, session_health = ?, active_run_token = NULL, active_owner_pid = NULL,\n active_owner_started_at = NULL, active_provider_pid = NULL, active_provider_started_at = NULL,\n active_run_started_at = NULL, last_active_at = ?, updated_at = ?, last_result_status = ?,\n last_result_completed_at = ?, last_result_exit_code = ?, last_result_summary = ?\n WHERE id = ? AND state = 'running' AND active_run_token = ?`, [\n result.status === 'succeeded' ? 'ready' : 'degraded', result.sessionHealth, completedAt, completedAt,\n result.status, completedAt, result.exitCode, result.summary.slice(0, 4096), id, token,\n ]);\n if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');\n return this.requireById(id);\n }\n\n async reconcile(): Promise<void> {\n this.assertWritable();\n const running = this.listRaw().filter((agent) => agent.state === 'running' && agent.activeRun);\n for (const snapshot of running) {\n if (this.isActive(snapshot.activeRun!)) continue;\n const completedAt = this.now().toISOString();\n this.db.execute(`UPDATE durable_agents SET\n state = 'degraded', session_health = 'unknown', active_run_token = NULL,\n active_owner_pid = NULL, active_owner_started_at = NULL, active_provider_pid = NULL,\n active_provider_started_at = NULL, active_run_started_at = NULL, updated_at = ?, last_active_at = ?,\n last_result_status = 'interrupted', last_result_completed_at = ?, last_result_exit_code = NULL,\n last_result_summary = 'Previous print run was interrupted.'\n WHERE id = ? AND state = 'running' AND active_run_token = ?\n AND active_owner_started_at = ? AND active_run_started_at = ?`, [\n completedAt, completedAt, completedAt, snapshot.id, snapshot.activeRun!.token,\n snapshot.activeRun!.owner.startedAt, snapshot.activeRun!.startedAt,\n ]);\n }\n }\n\n private immediate<T>(operation: () => T): T {\n this.db.instance.exec('BEGIN IMMEDIATE');\n try {\n const result = operation();\n this.db.instance.exec('COMMIT');\n return result;\n } catch (error) {\n try { this.db.instance.exec('ROLLBACK'); } catch { /* retain original failure */ }\n throw error;\n }\n }\n\n private listRaw(): DurableAgent[] {\n try {\n return this.db.query<DurableAgentRow>(\n 'SELECT * FROM durable_agents ORDER BY updated_at DESC, name COLLATE NOCASE',\n ).map((row) => this.fromRow(row));\n } catch (error) {\n throw this.storageError('Failed to read durable-agent database', error);\n }\n }\n\n private findById(id: string): DurableAgent | null {\n const row = this.db.queryOne<DurableAgentRow>('SELECT * FROM durable_agents WHERE id = ?', [id]);\n return row ? this.fromRow(row) : null;\n }\n\n private requireById(id: string): DurableAgent {\n const agent = this.findById(id);\n if (!agent) throw new DurableAgentNotFoundError(id);\n return agent;\n }\n\n private fromRow(row: DurableAgentRow): DurableAgent {\n const activeRun: DurableActiveRun | null = row.active_run_token === null ? null : {\n token: row.active_run_token,\n owner: { pid: row.active_owner_pid!, startedAt: row.active_owner_started_at! },\n provider: row.active_provider_pid === null ? null : {\n pid: row.active_provider_pid, startedAt: row.active_provider_started_at!,\n },\n startedAt: row.active_run_started_at!,\n };\n return {\n id: row.id, name: row.name, provider: row.provider, mode: row.mode, cwd: row.cwd,\n providerSessionId: row.provider_session_id, state: row.state, sessionHealth: row.session_health,\n createdAt: row.created_at, updatedAt: row.updated_at, lastActiveAt: row.last_active_at,\n lastResult: row.last_result_status === null ? null : {\n status: row.last_result_status, completedAt: row.last_result_completed_at!,\n exitCode: row.last_result_exit_code, summary: row.last_result_summary ?? '',\n },\n activeRun,\n };\n }\n\n private canonicalDirectory(input: string): string {\n try {\n const resolved = fs.realpathSync(input);\n if (!fs.statSync(resolved).isDirectory()) throw new Error('not a directory');\n return resolved;\n } catch {\n throw new DurableAgentRepositoryError(`Durable agent cwd is not an existing directory: ${input}`);\n }\n }\n\n private validateBoundCwd(bound: string): void {\n try {\n const stat = fs.lstatSync(bound);\n if (!stat.isDirectory() || stat.isSymbolicLink() || fs.realpathSync(bound) !== bound) throw new Error('binding changed');\n } catch {\n throw new DurableAgentRepositoryError(`Durable agent cwd binding is no longer safe: ${bound}`);\n }\n }\n\n private isActive(metadata: DurableActiveRun): boolean {\n return this.sameProcess(metadata.owner) || (metadata.provider !== null && this.sameProcess(metadata.provider));\n }\n\n private sameProcess(expected: ProcessIdentity): boolean {\n const actual = this.processInspector.getIdentity(expected.pid);\n return actual !== null && actual.startedAt === expected.startedAt;\n }\n\n private assertWritable(): void {\n if (this.readonly) throw new DurableAgentRepositoryError('Durable-agent repository is readonly.');\n }\n\n private storageError(prefix: string, error: unknown): DurableAgentRepositoryError {\n return error instanceof DurableAgentRepositoryError ? error\n : new DurableAgentRepositoryError(`${prefix}: ${(error as Error).message}`);\n }\n}\n\nexport class LocalProcessInspector implements ProcessInspector {\n getIdentity(pid: number): ProcessIdentity | null {\n if (!Number.isInteger(pid) || pid <= 0) return null;\n try {\n if (process.platform === 'linux') {\n const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');\n const close = stat.lastIndexOf(')');\n const fields = stat.slice(close + 2).split(' ');\n const startTicks = fields[19];\n return startTicks ? { pid, startedAt: `linux:${startTicks}` } : null;\n }\n const startedAt = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n return startedAt ? { pid, startedAt } : null;\n } catch {\n return null;\n }\n }\n}\n"],"names":["fs","randomUUID","execFileSync","DatabaseConnection","DEFAULT_AGENT_REGISTRY_DB_PATH","AGENT_MODES","DurableAgentBusyError","DurableAgentNameConflictError","DurableAgentNotFoundError","DurableAgentRepositoryError","DurableAgentRepository","dbPath","now","processInspector","readonly","db","options","Date","LocalProcessInspector","error","message","create","input","assertWritable","cwd","canonicalDirectory","timestamp","toISOString","id","providerSessionId","execute","name","DURABLE","test","storageError","requireById","list","reconcile","listRaw","getById","findById","resolve","reference","agents","byId","find","agent","matches","filter","toLowerCase","length","acquireRun","snapshot","validateBoundCwd","observed","activeRun","observedLive","isActive","owner","getIdentity","process","pid","token","startedAt","recovered","immediate","current","state","changed","changes","lastResult","status","recordProviderProcess","identity","completeRun","result","completedAt","sessionHealth","exitCode","summary","slice","running","operation","instance","exec","query","map","row","fromRow","queryOne","active_run_token","active_owner_pid","active_owner_started_at","provider","active_provider_pid","active_provider_started_at","active_run_started_at","mode","provider_session_id","session_health","createdAt","created_at","updatedAt","updated_at","lastActiveAt","last_active_at","last_result_status","last_result_completed_at","last_result_exit_code","last_result_summary","resolved","realpathSync","statSync","isDirectory","Error","bound","stat","lstatSync","isSymbolicLink","metadata","sameProcess","expected","actual","prefix","Number","isInteger","platform","readFileSync","close","lastIndexOf","fields","split","startTicks","String","encoding","stdio","trim"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/durable/DurableAgentRepository.ts"],"sourcesContent":["import fs from 'fs';\nimport { randomUUID } from 'crypto';\nimport { DatabaseConnection, DEFAULT_AGENT_REGISTRY_DB_PATH } from '../database/index.js';\nimport { AGENT_MODES, CodexPrintError, type DurableActiveRun, type DurableAgent, type DurableProvider, type ProcessIdentity, type DurableRunStatus, type DurableSessionHealth } from './DurableAgent.js';\nimport { LocalProcessInspector, type ProcessInspector } from './process.js';\nimport { isUuid } from './utils.js';\nimport {\n DurableAgentBusyError,\n DurableAgentNameConflictError,\n DurableAgentNotFoundError,\n DurableAgentRepositoryError,\n} from './DurableAgent.js';\n\ninterface DurableAgentRow {\n id: string; name: string; provider: DurableProvider; mode: typeof AGENT_MODES.DURABLE; cwd: string; provider_session_id: string | null;\n state: DurableAgent['state']; session_health: DurableSessionHealth; created_at: string; updated_at: string;\n last_active_at: string | null; last_result_status: DurableRunStatus | null;\n last_result_completed_at: string | null; last_result_exit_code: number | null; last_result_summary: string | null;\n active_run_token: string | null; active_owner_pid: number | null; active_owner_started_at: string | null;\n active_provider_pid: number | null; active_provider_started_at: string | null; active_run_started_at: string | null;\n}\n\nexport interface CreateDurableAgentInput { name: string; cwd: string; provider?: DurableProvider }\n\nexport interface DurableAgentRepositoryOptions {\n dbPath?: string;\n readonly?: boolean;\n /** @deprecated SQLite busy_timeout replaces filesystem lock polling. */\n lockTimeoutMs?: number;\n now?: () => Date;\n processInspector?: ProcessInspector;\n /** @deprecated Active ownership is committed atomically. */\n incompleteLockGraceMs?: number;\n /** @deprecated SQLite transactions replace mutation lock directories. */\n mutationLockStaleMs?: number;\n}\n\nexport { LocalProcessInspector } from './process.js';\nexport type { ProcessInspector } from './process.js';\nexport interface DurableRunCompletion {\n status: DurableRunStatus; exitCode: number | null; summary: string; sessionHealth: DurableSessionHealth;\n}\n\nexport class DurableAgentRepository {\n readonly dbPath: string;\n private readonly now: () => Date;\n private readonly processInspector: ProcessInspector;\n private readonly readonly: boolean;\n private readonly db: DatabaseConnection;\n\n constructor(options: DurableAgentRepositoryOptions = {}) {\n this.dbPath = options.dbPath ?? DEFAULT_AGENT_REGISTRY_DB_PATH;\n this.now = options.now ?? (() => new Date());\n this.processInspector = options.processInspector ?? new LocalProcessInspector();\n this.readonly = options.readonly ?? false;\n try {\n this.db = new DatabaseConnection({ dbPath: this.dbPath, readonly: this.readonly });\n } catch (error) {\n if (error instanceof DurableAgentRepositoryError) throw error;\n throw new DurableAgentRepositoryError(`Cannot open durable-agent database: ${(error as Error).message}`);\n }\n }\n\n async create(input: CreateDurableAgentInput): Promise<DurableAgent> {\n this.assertWritable();\n const cwd = this.canonicalDirectory(input.cwd);\n const timestamp = this.now().toISOString();\n const id = randomUUID();\n const provider = input.provider ?? 'claude';\n let providerSessionId = provider === 'codex' ? null : randomUUID();\n while (providerSessionId === id) providerSessionId = randomUUID();\n try {\n this.db.execute(`INSERT INTO durable_agents (\n id, name, provider, mode, cwd, provider_session_id, state, session_health, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, 'ready', 'uninitialized', ?, ?)`,\n [id, input.name, provider, AGENT_MODES.DURABLE, cwd, providerSessionId, timestamp, timestamp]);\n } catch (error) {\n if (/UNIQUE constraint failed: durable_agents\\.name/i.test((error as Error).message)) {\n throw new DurableAgentNameConflictError(input.name);\n }\n throw this.storageError('Failed to create durable agent', error);\n }\n return this.requireById(id);\n }\n\n async list(): Promise<DurableAgent[]> {\n if (!this.readonly) await this.reconcile();\n return this.listRaw();\n }\n\n async getById(id: string): Promise<DurableAgent | null> {\n if (!this.readonly) await this.reconcile();\n return this.findById(id);\n }\n\n async resolve(reference: string): Promise<DurableAgent | DurableAgent[] | null> {\n const agents = await this.list();\n const byId = agents.find((agent) => agent.id === reference);\n if (byId) return byId;\n const matches = agents.filter((agent) => agent.name.toLowerCase() === reference.toLowerCase());\n return matches.length === 0 ? null : matches.length === 1 ? matches[0]! : matches;\n }\n\n async acquireRun(id: string): Promise<{ agent: DurableAgent; token: string }> {\n this.assertWritable();\n const snapshot = this.findById(id);\n if (!snapshot) throw new DurableAgentNotFoundError(id);\n this.validateBoundCwd(snapshot.cwd);\n const observed = snapshot.activeRun;\n const observedLive = observed ? this.isActive(observed) : false;\n if (observedLive) throw new DurableAgentBusyError(id, snapshot.name);\n const owner = this.processInspector.getIdentity(process.pid);\n if (!owner) throw new DurableAgentRepositoryError('Cannot determine the current process identity.');\n const token = randomUUID();\n const startedAt = this.now().toISOString();\n let recovered = false;\n try {\n this.immediate(() => {\n const current = this.findById(id);\n if (!current) throw new DurableAgentNotFoundError(id);\n if (current.state === 'running') {\n if (!observed || current.activeRun?.token !== observed.token || observedLive) {\n throw new DurableAgentBusyError(id, current.name);\n }\n recovered = true;\n }\n const changed = this.db.execute(`UPDATE durable_agents SET\n state = 'running', active_run_token = ?, active_owner_pid = ?, active_owner_started_at = ?,\n active_provider_pid = NULL, active_provider_started_at = NULL, active_run_started_at = ?, updated_at = ?,\n session_health = CASE WHEN state = 'running' THEN 'unknown' ELSE session_health END,\n last_result_status = CASE WHEN state = 'running' THEN 'interrupted' ELSE last_result_status END,\n last_result_completed_at = CASE WHEN state = 'running' THEN ? ELSE last_result_completed_at END,\n last_result_exit_code = CASE WHEN state = 'running' THEN NULL ELSE last_result_exit_code END,\n last_result_summary = CASE WHEN state = 'running' THEN 'Previous print run was interrupted.' ELSE last_result_summary END\n WHERE id = ? AND (state <> 'running' OR (\n active_run_token = ? AND active_owner_started_at = ? AND active_run_started_at = ?\n ))\n `, [token, owner.pid, owner.startedAt, startedAt, startedAt, startedAt, id,\n observed?.token ?? null, observed?.owner.startedAt ?? null, observed?.startedAt ?? null]);\n if (changed.changes !== 1) throw new DurableAgentBusyError(id, current.name);\n });\n } catch (error) {\n if (error instanceof DurableAgentBusyError || error instanceof DurableAgentNotFoundError) throw error;\n if (/busy|locked/i.test((error as Error).message)) throw new DurableAgentBusyError(id, snapshot.name);\n throw this.storageError('Failed to acquire durable-agent run', error);\n }\n const agent = this.requireById(id);\n if (recovered && agent.lastResult?.status !== 'interrupted') {\n throw new DurableAgentRepositoryError('Failed to record interrupted print run.');\n }\n return { agent, token };\n }\n\n async recordProviderProcess(id: string, token: string, identity: ProcessIdentity): Promise<void> {\n this.assertWritable();\n const changed = this.db.execute(`UPDATE durable_agents SET\n active_provider_pid = ?, active_provider_started_at = ?, updated_at = ?\n WHERE id = ? AND state = 'running' AND active_run_token = ?`,\n [identity.pid, identity.startedAt, this.now().toISOString(), id, token]);\n if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');\n }\n\n async bindProviderSession(id: string, token: string, providerSessionId: string): Promise<DurableAgent> {\n this.assertWritable();\n if (!isUuid(providerSessionId)) {\n throw new DurableAgentRepositoryError('Invalid provider session id.');\n }\n try {\n this.immediate(() => {\n const agent = this.findById(id);\n if (!agent) throw new DurableAgentNotFoundError(id);\n if (agent.provider !== 'codex') {\n throw new DurableAgentRepositoryError('Only Codex durable sessions can be bound after creation.');\n }\n if (agent.activeRun?.token !== token) {\n throw new DurableAgentRepositoryError('Print run ownership changed.');\n }\n if (agent.providerSessionId !== null && agent.providerSessionId !== providerSessionId) {\n throw new CodexPrintError('Durable agent provider session identity does not match.', 'CODEX_SESSION_MISMATCH');\n }\n if (agent.providerSessionId === providerSessionId) return;\n const changed = this.db.execute(`UPDATE durable_agents SET provider_session_id = ?, updated_at = ?\n WHERE id = ? AND provider = 'codex' AND state = 'running' AND active_run_token = ?\n AND provider_session_id IS NULL`,\n [providerSessionId, this.now().toISOString(), id, token]);\n if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');\n });\n } catch (error) {\n if (error instanceof DurableAgentRepositoryError || error instanceof DurableAgentNotFoundError\n || error instanceof CodexPrintError) throw error;\n if (/UNIQUE constraint failed: durable_agents\\.provider_session_id/i.test((error as Error).message)) {\n throw new CodexPrintError('Provider session is already bound to another durable agent.', 'CODEX_SESSION_MISMATCH');\n }\n throw this.storageError('Failed to bind durable-agent provider session', error);\n }\n return this.requireById(id);\n }\n\n async completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent> {\n this.assertWritable();\n const completedAt = this.now().toISOString();\n const changed = this.db.execute(`UPDATE durable_agents SET\n state = ?, session_health = ?, active_run_token = NULL, active_owner_pid = NULL,\n active_owner_started_at = NULL, active_provider_pid = NULL, active_provider_started_at = NULL,\n active_run_started_at = NULL, last_active_at = ?, updated_at = ?, last_result_status = ?,\n last_result_completed_at = ?, last_result_exit_code = ?, last_result_summary = ?\n WHERE id = ? AND state = 'running' AND active_run_token = ?`, [\n result.status === 'succeeded' ? 'ready' : 'degraded', result.sessionHealth, completedAt, completedAt,\n result.status, completedAt, result.exitCode, result.summary.slice(0, 4096), id, token,\n ]);\n if (changed.changes !== 1) throw new DurableAgentRepositoryError('Print run ownership changed.');\n return this.requireById(id);\n }\n\n async reconcile(): Promise<void> {\n this.assertWritable();\n const running = this.listRaw().filter((agent) => agent.state === 'running' && agent.activeRun);\n for (const snapshot of running) {\n if (this.isActive(snapshot.activeRun!)) continue;\n const completedAt = this.now().toISOString();\n this.db.execute(`UPDATE durable_agents SET\n state = 'degraded', session_health = 'unknown', active_run_token = NULL,\n active_owner_pid = NULL, active_owner_started_at = NULL, active_provider_pid = NULL,\n active_provider_started_at = NULL, active_run_started_at = NULL, updated_at = ?, last_active_at = ?,\n last_result_status = 'interrupted', last_result_completed_at = ?, last_result_exit_code = NULL,\n last_result_summary = 'Previous print run was interrupted.'\n WHERE id = ? AND state = 'running' AND active_run_token = ?\n AND active_owner_started_at = ? AND active_run_started_at = ?`, [\n completedAt, completedAt, completedAt, snapshot.id, snapshot.activeRun!.token,\n snapshot.activeRun!.owner.startedAt, snapshot.activeRun!.startedAt,\n ]);\n }\n }\n\n private immediate<T>(operation: () => T): T {\n this.db.instance.exec('BEGIN IMMEDIATE');\n try {\n const result = operation();\n this.db.instance.exec('COMMIT');\n return result;\n } catch (error) {\n try { this.db.instance.exec('ROLLBACK'); } catch { /* retain original failure */ }\n throw error;\n }\n }\n\n private listRaw(): DurableAgent[] {\n try {\n return this.db.query<DurableAgentRow>(\n 'SELECT * FROM durable_agents ORDER BY updated_at DESC, name COLLATE NOCASE',\n ).map((row) => this.fromRow(row));\n } catch (error) {\n throw this.storageError('Failed to read durable-agent database', error);\n }\n }\n\n private findById(id: string): DurableAgent | null {\n const row = this.db.queryOne<DurableAgentRow>('SELECT * FROM durable_agents WHERE id = ?', [id]);\n return row ? this.fromRow(row) : null;\n }\n\n private requireById(id: string): DurableAgent {\n const agent = this.findById(id);\n if (!agent) throw new DurableAgentNotFoundError(id);\n return agent;\n }\n\n private fromRow(row: DurableAgentRow): DurableAgent {\n if (!['claude', 'codex', 'pi'].includes(row.provider)\n || (row.provider !== 'codex' && row.provider_session_id === null)) {\n throw new DurableAgentRepositoryError(`Invalid durable-agent provider record: ${row.id}`);\n }\n const activeRun: DurableActiveRun | null = row.active_run_token === null ? null : {\n token: row.active_run_token,\n owner: { pid: row.active_owner_pid!, startedAt: row.active_owner_started_at! },\n provider: row.active_provider_pid === null ? null : {\n pid: row.active_provider_pid, startedAt: row.active_provider_started_at!,\n },\n startedAt: row.active_run_started_at!,\n };\n const base = {\n id: row.id, name: row.name, provider: row.provider, mode: row.mode, cwd: row.cwd,\n state: row.state, sessionHealth: row.session_health,\n createdAt: row.created_at, updatedAt: row.updated_at, lastActiveAt: row.last_active_at,\n lastResult: row.last_result_status === null ? null : {\n status: row.last_result_status, completedAt: row.last_result_completed_at!,\n exitCode: row.last_result_exit_code, summary: row.last_result_summary ?? '',\n },\n activeRun,\n };\n if (row.provider === 'claude') {\n return { ...base, provider: 'claude', providerSessionId: row.provider_session_id! };\n }\n if (row.provider === 'pi') {\n return { ...base, provider: 'pi', providerSessionId: row.provider_session_id! };\n }\n return { ...base, provider: 'codex', providerSessionId: row.provider_session_id };\n }\n\n private canonicalDirectory(input: string): string {\n try {\n const resolved = fs.realpathSync(input);\n if (!fs.statSync(resolved).isDirectory()) throw new Error('not a directory');\n return resolved;\n } catch {\n throw new DurableAgentRepositoryError(`Durable agent cwd is not an existing directory: ${input}`);\n }\n }\n\n private validateBoundCwd(bound: string): void {\n try {\n const stat = fs.lstatSync(bound);\n if (!stat.isDirectory() || stat.isSymbolicLink() || fs.realpathSync(bound) !== bound) throw new Error('binding changed');\n } catch {\n throw new DurableAgentRepositoryError(`Durable agent cwd binding is no longer safe: ${bound}`);\n }\n }\n\n private isActive(metadata: DurableActiveRun): boolean {\n return this.sameProcess(metadata.owner) || (metadata.provider !== null && this.sameProcess(metadata.provider));\n }\n\n private sameProcess(expected: ProcessIdentity): boolean {\n const actual = this.processInspector.getIdentity(expected.pid);\n return actual !== null && actual.startedAt === expected.startedAt;\n }\n\n private assertWritable(): void {\n if (this.readonly) throw new DurableAgentRepositoryError('Durable-agent repository is readonly.');\n }\n\n private storageError(prefix: string, error: unknown): DurableAgentRepositoryError {\n return error instanceof DurableAgentRepositoryError ? error\n : new DurableAgentRepositoryError(`${prefix}: ${(error as Error).message}`);\n }\n}\n"],"names":["fs","randomUUID","DatabaseConnection","DEFAULT_AGENT_REGISTRY_DB_PATH","AGENT_MODES","CodexPrintError","LocalProcessInspector","isUuid","DurableAgentBusyError","DurableAgentNameConflictError","DurableAgentNotFoundError","DurableAgentRepositoryError","DurableAgentRepository","dbPath","now","processInspector","readonly","db","options","Date","error","message","create","input","assertWritable","cwd","canonicalDirectory","timestamp","toISOString","id","provider","providerSessionId","execute","name","DURABLE","test","storageError","requireById","list","reconcile","listRaw","getById","findById","resolve","reference","agents","byId","find","agent","matches","filter","toLowerCase","length","acquireRun","snapshot","validateBoundCwd","observed","activeRun","observedLive","isActive","owner","getIdentity","process","pid","token","startedAt","recovered","immediate","current","state","changed","changes","lastResult","status","recordProviderProcess","identity","bindProviderSession","completeRun","result","completedAt","sessionHealth","exitCode","summary","slice","running","operation","instance","exec","query","map","row","fromRow","queryOne","includes","provider_session_id","active_run_token","active_owner_pid","active_owner_started_at","active_provider_pid","active_provider_started_at","active_run_started_at","base","mode","session_health","createdAt","created_at","updatedAt","updated_at","lastActiveAt","last_active_at","last_result_status","last_result_completed_at","last_result_exit_code","last_result_summary","resolved","realpathSync","statSync","isDirectory","Error","bound","stat","lstatSync","isSymbolicLink","metadata","sameProcess","expected","actual","prefix"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ProcessIdentity } from './DurableAgent.js';
|
|
2
|
+
export interface ProcessInspector {
|
|
3
|
+
getIdentity(pid: number): ProcessIdentity | null;
|
|
4
|
+
}
|
|
5
|
+
export declare class LocalProcessInspector implements ProcessInspector {
|
|
6
|
+
getIdentity(pid: number): ProcessIdentity | null;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/durable/process.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC7B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAAC;CACpD;AAED,qBAAa,qBAAsB,YAAW,gBAAgB;IAC1D,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CAkBnD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { execFileSync } from 'child_process';
|
|
3
|
+
export class LocalProcessInspector {
|
|
4
|
+
getIdentity(pid) {
|
|
5
|
+
if (!Number.isInteger(pid) || pid <= 0) return null;
|
|
6
|
+
try {
|
|
7
|
+
if (process.platform === 'linux') {
|
|
8
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
9
|
+
const close = stat.lastIndexOf(')');
|
|
10
|
+
const fields = stat.slice(close + 2).split(' ');
|
|
11
|
+
const startTicks = fields[19];
|
|
12
|
+
return startTicks ? {
|
|
13
|
+
pid,
|
|
14
|
+
startedAt: `linux:${startTicks}`
|
|
15
|
+
} : null;
|
|
16
|
+
}
|
|
17
|
+
const startedAt = execFileSync('ps', [
|
|
18
|
+
'-o',
|
|
19
|
+
'lstart=',
|
|
20
|
+
'-p',
|
|
21
|
+
String(pid)
|
|
22
|
+
], {
|
|
23
|
+
encoding: 'utf8',
|
|
24
|
+
stdio: [
|
|
25
|
+
'ignore',
|
|
26
|
+
'pipe',
|
|
27
|
+
'ignore'
|
|
28
|
+
]
|
|
29
|
+
}).trim();
|
|
30
|
+
return startedAt ? {
|
|
31
|
+
pid,
|
|
32
|
+
startedAt
|
|
33
|
+
} : null;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/durable/process.ts"],"sourcesContent":["import fs from 'fs';\nimport { execFileSync } from 'child_process';\nimport type { ProcessIdentity } from './DurableAgent.js';\n\nexport interface ProcessInspector {\n getIdentity(pid: number): ProcessIdentity | null;\n}\n\nexport class LocalProcessInspector implements ProcessInspector {\n getIdentity(pid: number): ProcessIdentity | null {\n if (!Number.isInteger(pid) || pid <= 0) return null;\n try {\n if (process.platform === 'linux') {\n const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');\n const close = stat.lastIndexOf(')');\n const fields = stat.slice(close + 2).split(' ');\n const startTicks = fields[19];\n return startTicks ? { pid, startedAt: `linux:${startTicks}` } : null;\n }\n const startedAt = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {\n encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n return startedAt ? { pid, startedAt } : null;\n } catch {\n return null;\n }\n }\n}\n"],"names":["fs","execFileSync","LocalProcessInspector","getIdentity","pid","Number","isInteger","process","platform","stat","readFileSync","close","lastIndexOf","fields","slice","split","startTicks","startedAt","String","encoding","stdio","trim"],"mappings":"AAAA,OAAOA,QAAQ,KAAK;AACpB,SAASC,YAAY,QAAQ,gBAAgB;AAO7C,OAAO,MAAMC;IACTC,YAAYC,GAAW,EAA0B;QAC7C,IAAI,CAACC,OAAOC,SAAS,CAACF,QAAQA,OAAO,GAAG,OAAO;QAC/C,IAAI;YACA,IAAIG,QAAQC,QAAQ,KAAK,SAAS;gBAC9B,MAAMC,OAAOT,GAAGU,YAAY,CAAC,CAAC,MAAM,EAAEN,IAAI,KAAK,CAAC,EAAE;gBAClD,MAAMO,QAAQF,KAAKG,WAAW,CAAC;gBAC/B,MAAMC,SAASJ,KAAKK,KAAK,CAACH,QAAQ,GAAGI,KAAK,CAAC;gBAC3C,MAAMC,aAAaH,MAAM,CAAC,GAAG;gBAC7B,OAAOG,aAAa;oBAAEZ;oBAAKa,WAAW,CAAC,MAAM,EAAED,YAAY;gBAAC,IAAI;YACpE;YACA,MAAMC,YAAYhB,aAAa,MAAM;gBAAC;gBAAM;gBAAW;gBAAMiB,OAAOd;aAAK,EAAE;gBACvEe,UAAU;gBAAQC,OAAO;oBAAC;oBAAU;oBAAQ;iBAAS;YACzD,GAAGC,IAAI;YACP,OAAOJ,YAAY;gBAAEb;gBAAKa;YAAU,IAAI;QAC5C,EAAE,OAAM;YACJ,OAAO;QACX;IACJ;AACJ"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DurableAgent, DurableProvider } from './DurableAgent.js';
|
|
2
|
+
import type { DurableRunCompletion } from './DurableAgentRepository.js';
|
|
3
|
+
export interface DurableRunRepository {
|
|
4
|
+
resolve(reference: string): Promise<DurableAgent | DurableAgent[] | null>;
|
|
5
|
+
acquireRun(id: string): Promise<{
|
|
6
|
+
agent: DurableAgent;
|
|
7
|
+
token: string;
|
|
8
|
+
}>;
|
|
9
|
+
completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent>;
|
|
10
|
+
}
|
|
11
|
+
type ProviderAgent<Provider extends DurableProvider> = Extract<DurableAgent, {
|
|
12
|
+
provider: Provider;
|
|
13
|
+
}>;
|
|
14
|
+
interface DurableRunResult {
|
|
15
|
+
result: string;
|
|
16
|
+
exitCode: number;
|
|
17
|
+
}
|
|
18
|
+
interface DurableRunOptions<Provider extends DurableProvider, Result extends DurableRunResult> {
|
|
19
|
+
reference: string;
|
|
20
|
+
provider: Provider;
|
|
21
|
+
repository: DurableRunRepository;
|
|
22
|
+
ambiguousError(): Error;
|
|
23
|
+
providerError(): Error;
|
|
24
|
+
execute(agent: ProviderAgent<Provider>, token: string): Promise<Result>;
|
|
25
|
+
isSessionMismatch(error: unknown): boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function runDurableAgent<Provider extends DurableProvider, Result extends DurableRunResult>(options: DurableRunOptions<Provider, Result>): Promise<{
|
|
28
|
+
agent: ProviderAgent<Provider>;
|
|
29
|
+
result: Result;
|
|
30
|
+
}>;
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/durable/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAKxE,MAAM,WAAW,oBAAoB;IACjC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1E,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/F;AAED,KAAK,aAAa,CAAC,QAAQ,SAAS,eAAe,IAAI,OAAO,CAAC,YAAY,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAErG,UAAU,gBAAgB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,iBAAiB,CAAC,QAAQ,SAAS,eAAe,EAAE,MAAM,SAAS,gBAAgB;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,oBAAoB,CAAC;IACjC,cAAc,IAAI,KAAK,CAAC;IACxB,aAAa,IAAI,KAAK,CAAC;IACvB,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CAC9C;AAED,wBAAsB,eAAe,CAAC,QAAQ,SAAS,eAAe,EAAE,MAAM,SAAS,gBAAgB,EACnG,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,GAC7C,OAAO,CAAC;IAAE,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB7D"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DurableAgentNotFoundError } from './DurableAgent.js';
|
|
2
|
+
import { sanitizeText } from './utils.js';
|
|
3
|
+
const MAX_RESULT_SUMMARY_LENGTH = 4096;
|
|
4
|
+
export async function runDurableAgent(options) {
|
|
5
|
+
const resolved = await options.repository.resolve(options.reference);
|
|
6
|
+
if (!resolved) throw new DurableAgentNotFoundError(options.reference);
|
|
7
|
+
if (Array.isArray(resolved)) throw options.ambiguousError();
|
|
8
|
+
if (resolved.provider !== options.provider) throw options.providerError();
|
|
9
|
+
const target = resolved;
|
|
10
|
+
const acquired = await options.repository.acquireRun(target.id);
|
|
11
|
+
let result;
|
|
12
|
+
try {
|
|
13
|
+
result = await options.execute(acquired.agent, acquired.token);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
await options.repository.completeRun(target.id, acquired.token, createFailedCompletion(error, options.isSessionMismatch(error)));
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
await options.repository.completeRun(target.id, acquired.token, createSucceededCompletion(result));
|
|
19
|
+
return {
|
|
20
|
+
agent: target,
|
|
21
|
+
result
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createSucceededCompletion(result) {
|
|
25
|
+
return {
|
|
26
|
+
status: 'succeeded',
|
|
27
|
+
exitCode: result.exitCode,
|
|
28
|
+
summary: sanitizeText(result.result, MAX_RESULT_SUMMARY_LENGTH, {
|
|
29
|
+
preserveFormatting: true
|
|
30
|
+
}),
|
|
31
|
+
sessionHealth: 'healthy'
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function createFailedCompletion(error, sessionMismatch) {
|
|
35
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36
|
+
return {
|
|
37
|
+
status: 'failed',
|
|
38
|
+
exitCode: null,
|
|
39
|
+
summary: sanitizeText(message, MAX_RESULT_SUMMARY_LENGTH, {
|
|
40
|
+
preserveFormatting: true
|
|
41
|
+
}),
|
|
42
|
+
sessionHealth: sessionMismatch ? 'mismatch' : 'unknown'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/durable/run.ts"],"sourcesContent":["import type { DurableAgent, DurableProvider } from './DurableAgent.js';\nimport { DurableAgentNotFoundError } from './DurableAgent.js';\nimport type { DurableRunCompletion } from './DurableAgentRepository.js';\nimport { sanitizeText } from './utils.js';\n\nconst MAX_RESULT_SUMMARY_LENGTH = 4096;\n\nexport interface DurableRunRepository {\n resolve(reference: string): Promise<DurableAgent | DurableAgent[] | null>;\n acquireRun(id: string): Promise<{ agent: DurableAgent; token: string }>;\n completeRun(id: string, token: string, result: DurableRunCompletion): Promise<DurableAgent>;\n}\n\ntype ProviderAgent<Provider extends DurableProvider> = Extract<DurableAgent, { provider: Provider }>;\n\ninterface DurableRunResult {\n result: string;\n exitCode: number;\n}\n\ninterface DurableRunOptions<Provider extends DurableProvider, Result extends DurableRunResult> {\n reference: string;\n provider: Provider;\n repository: DurableRunRepository;\n ambiguousError(): Error;\n providerError(): Error;\n execute(agent: ProviderAgent<Provider>, token: string): Promise<Result>;\n isSessionMismatch(error: unknown): boolean;\n}\n\nexport async function runDurableAgent<Provider extends DurableProvider, Result extends DurableRunResult>(\n options: DurableRunOptions<Provider, Result>,\n): Promise<{ agent: ProviderAgent<Provider>; result: Result }> {\n const resolved = await options.repository.resolve(options.reference);\n if (!resolved) throw new DurableAgentNotFoundError(options.reference);\n if (Array.isArray(resolved)) throw options.ambiguousError();\n if (resolved.provider !== options.provider) throw options.providerError();\n\n const target = resolved as ProviderAgent<Provider>;\n const acquired = await options.repository.acquireRun(target.id);\n let result: Result;\n try {\n result = await options.execute(acquired.agent as ProviderAgent<Provider>, acquired.token);\n } catch (error) {\n await options.repository.completeRun(\n target.id,\n acquired.token,\n createFailedCompletion(error, options.isSessionMismatch(error)),\n );\n throw error;\n }\n\n await options.repository.completeRun(target.id, acquired.token, createSucceededCompletion(result));\n return { agent: target, result };\n}\n\nfunction createSucceededCompletion(result: DurableRunResult): DurableRunCompletion {\n return {\n status: 'succeeded',\n exitCode: result.exitCode,\n summary: sanitizeText(result.result, MAX_RESULT_SUMMARY_LENGTH, { preserveFormatting: true }),\n sessionHealth: 'healthy',\n };\n}\n\nfunction createFailedCompletion(error: unknown, sessionMismatch: boolean): DurableRunCompletion {\n const message = error instanceof Error ? error.message : String(error);\n return {\n status: 'failed',\n exitCode: null,\n summary: sanitizeText(message, MAX_RESULT_SUMMARY_LENGTH, { preserveFormatting: true }),\n sessionHealth: sessionMismatch ? 'mismatch' : 'unknown',\n };\n}\n"],"names":["DurableAgentNotFoundError","sanitizeText","MAX_RESULT_SUMMARY_LENGTH","runDurableAgent","options","resolved","repository","resolve","reference","Array","isArray","ambiguousError","provider","providerError","target","acquired","acquireRun","id","result","execute","agent","token","error","completeRun","createFailedCompletion","isSessionMismatch","createSucceededCompletion","status","exitCode","summary","preserveFormatting","sessionHealth","sessionMismatch","message","Error","String"],"mappings":"AACA,SAASA,yBAAyB,QAAQ,oBAAoB;AAE9D,SAASC,YAAY,QAAQ,aAAa;AAE1C,MAAMC,4BAA4B;AAyBlC,OAAO,eAAeC,gBAClBC,OAA4C;IAE5C,MAAMC,WAAW,MAAMD,QAAQE,UAAU,CAACC,OAAO,CAACH,QAAQI,SAAS;IACnE,IAAI,CAACH,UAAU,MAAM,IAAIL,0BAA0BI,QAAQI,SAAS;IACpE,IAAIC,MAAMC,OAAO,CAACL,WAAW,MAAMD,QAAQO,cAAc;IACzD,IAAIN,SAASO,QAAQ,KAAKR,QAAQQ,QAAQ,EAAE,MAAMR,QAAQS,aAAa;IAEvE,MAAMC,SAAST;IACf,MAAMU,WAAW,MAAMX,QAAQE,UAAU,CAACU,UAAU,CAACF,OAAOG,EAAE;IAC9D,IAAIC;IACJ,IAAI;QACAA,SAAS,MAAMd,QAAQe,OAAO,CAACJ,SAASK,KAAK,EAA6BL,SAASM,KAAK;IAC5F,EAAE,OAAOC,OAAO;QACZ,MAAMlB,QAAQE,UAAU,CAACiB,WAAW,CAChCT,OAAOG,EAAE,EACTF,SAASM,KAAK,EACdG,uBAAuBF,OAAOlB,QAAQqB,iBAAiB,CAACH;QAE5D,MAAMA;IACV;IAEA,MAAMlB,QAAQE,UAAU,CAACiB,WAAW,CAACT,OAAOG,EAAE,EAAEF,SAASM,KAAK,EAAEK,0BAA0BR;IAC1F,OAAO;QAAEE,OAAON;QAAQI;IAAO;AACnC;AAEA,SAASQ,0BAA0BR,MAAwB;IACvD,OAAO;QACHS,QAAQ;QACRC,UAAUV,OAAOU,QAAQ;QACzBC,SAAS5B,aAAaiB,OAAOA,MAAM,EAAEhB,2BAA2B;YAAE4B,oBAAoB;QAAK;QAC3FC,eAAe;IACnB;AACJ;AAEA,SAASP,uBAAuBF,KAAc,EAAEU,eAAwB;IACpE,MAAMC,UAAUX,iBAAiBY,QAAQZ,MAAMW,OAAO,GAAGE,OAAOb;IAChE,OAAO;QACHK,QAAQ;QACRC,UAAU;QACVC,SAAS5B,aAAagC,SAAS/B,2BAA2B;YAAE4B,oBAAoB;QAAK;QACrFC,eAAeC,kBAAkB,aAAa;IAClD;AACJ"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ChildProcessWithoutNullStreams } from 'child_process';
|
|
2
|
+
export interface ChildCloseResult {
|
|
3
|
+
code: number | null;
|
|
4
|
+
signal: NodeJS.Signals | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function waitForChildClose(child: ChildProcessWithoutNullStreams): Promise<ChildCloseResult>;
|
|
7
|
+
export declare function sanitizeText(value: string, max: number, options?: {
|
|
8
|
+
preserveFormatting?: boolean;
|
|
9
|
+
}): string;
|
|
10
|
+
export declare function isUuid(value: string): boolean;
|
|
11
|
+
export declare class LineBuffer {
|
|
12
|
+
private readonly maxLineBytes;
|
|
13
|
+
private readonly createOversizedLineError;
|
|
14
|
+
private buffer;
|
|
15
|
+
constructor(maxLineBytes: number, createOversizedLineError: () => Error);
|
|
16
|
+
accept(chunk: Buffer | string): Buffer[];
|
|
17
|
+
assertComplete(createIncompleteLineError: () => Error): void;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/durable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,8BAA8B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAKlG;AAED,wBAAgB,YAAY,CACxB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,MAAM,CAMR;AAID,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,qBAAa,UAAU;IAIf,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IAJ7C,OAAO,CAAC,MAAM,CAAmB;gBAGZ,YAAY,EAAE,MAAM,EACpB,wBAAwB,EAAE,MAAM,KAAK;IAG1D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE;IAiBxC,cAAc,CAAC,yBAAyB,EAAE,MAAM,KAAK,GAAG,IAAI;CAG/D"}
|