@ai-devkit/agent-manager 0.32.0 → 0.33.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/AgentManager.d.ts +3 -3
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +80 -79
- package/dist/AgentManager.js.map +1 -1
- package/dist/__tests__/AgentManager.test.js +413 -388
- package/dist/__tests__/AgentManager.test.js.map +1 -1
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +642 -642
- package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/CodexAdapter.test.js +322 -2321
- package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/CopilotAdapter.test.js +254 -248
- package/dist/__tests__/adapters/CopilotAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/GeminiCliAdapter.test.js +564 -558
- package/dist/__tests__/adapters/GeminiCliAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/GrokCliAdapter.test.js +114 -114
- package/dist/__tests__/adapters/GrokCliAdapter.test.js.map +1 -1
- package/dist/__tests__/adapters/OpenCodeAdapter.test.js +169 -169
- package/dist/__tests__/adapters/OpenCodeAdapter.test.js.map +1 -1
- package/dist/__tests__/capacity/codex.test.js +93 -93
- package/dist/__tests__/capacity/codex.test.js.map +1 -1
- package/dist/__tests__/capacity/index.test.js +17 -17
- package/dist/__tests__/capacity/index.test.js.map +1 -1
- package/dist/__tests__/durable/CodexCliProbe.test.js +60 -60
- package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -1
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +28 -28
- package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -1
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +30 -30
- package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/durable/CodexPrintAgentService.test.js +71 -71
- package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -1
- package/dist/__tests__/durable/CodexPrintRunner.test.js +125 -125
- package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -1
- package/dist/__tests__/print/ClaudeCliProbe.test.js +20 -20
- package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +20 -20
- package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintAgentService.test.js +58 -58
- package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
- package/dist/__tests__/print/ClaudePrintRunner.test.js +55 -55
- package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
- package/dist/__tests__/print/DurableAgent.test.js +9 -9
- package/dist/__tests__/print/DurableAgent.test.js.map +1 -1
- package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js +40 -40
- package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js.map +1 -1
- package/dist/__tests__/print/DurableAgentRepository.test.js +66 -66
- package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -1
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +34 -34
- package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -1
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +132 -132
- package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -1
- package/dist/__tests__/providers/codex/CodexSessionLocator.test.js +194 -0
- package/dist/__tests__/providers/codex/CodexSessionLocator.test.js.map +1 -0
- package/dist/__tests__/providers/codex/CodexSessionMapping.test.js +86 -0
- package/dist/__tests__/providers/codex/CodexSessionMapping.test.js.map +1 -0
- package/dist/__tests__/providers/codex/CodexSessionParser.test.js +254 -0
- package/dist/__tests__/providers/codex/CodexSessionParser.test.js.map +1 -0
- package/dist/__tests__/providers/pi/PiAdapter.test.js +337 -0
- package/dist/__tests__/providers/pi/PiAdapter.test.js.map +1 -0
- package/dist/__tests__/providers/pi/PiSessionParser.test.js +246 -0
- package/dist/__tests__/providers/pi/PiSessionParser.test.js.map +1 -0
- package/dist/__tests__/providers/pi/PiSessionTracker.test.js +108 -0
- package/dist/__tests__/providers/pi/PiSessionTracker.test.js.map +1 -0
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +33 -33
- package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -1
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +16 -16
- package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -1
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +52 -52
- package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -1
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +44 -44
- package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -1
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +126 -126
- package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -1
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +14 -14
- package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -1
- package/dist/__tests__/readiness/AgentReadiness.test.js +134 -134
- package/dist/__tests__/readiness/AgentReadiness.test.js.map +1 -1
- package/dist/__tests__/runtime/AgentRuntime.test.js +13 -0
- package/dist/__tests__/runtime/AgentRuntime.test.js.map +1 -0
- package/dist/__tests__/runtime/HerdrAgentRuntime.test.js +452 -0
- package/dist/__tests__/runtime/HerdrAgentRuntime.test.js.map +1 -0
- package/dist/__tests__/runtime/ManagedAgentRuntime.test.js +588 -0
- package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -0
- package/dist/__tests__/terminal/TerminalFocusManager.test.js +100 -100
- package/dist/__tests__/terminal/TerminalFocusManager.test.js.map +1 -1
- package/dist/__tests__/terminal/TmuxManager.test.js +101 -101
- package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
- package/dist/__tests__/terminal/TtyWriter.test.js +185 -185
- package/dist/__tests__/terminal/TtyWriter.test.js.map +1 -1
- package/dist/__tests__/utils/AgentRegistry.test.js +335 -217
- package/dist/__tests__/utils/AgentRegistry.test.js.map +1 -1
- package/dist/__tests__/utils/ClaudeSessionParser.test.js +103 -101
- package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +1 -1
- package/dist/__tests__/utils/agent-requests.test.js +43 -43
- package/dist/__tests__/utils/agent-requests.test.js.map +1 -1
- package/dist/__tests__/utils/agents.test.js +17 -17
- package/dist/__tests__/utils/agents.test.js.map +1 -1
- package/dist/__tests__/utils/matching.test.js +92 -92
- package/dist/__tests__/utils/matching.test.js.map +1 -1
- package/dist/__tests__/utils/process.test.js +108 -108
- package/dist/__tests__/utils/process.test.js.map +1 -1
- package/dist/__tests__/utils/session.test.js +53 -53
- package/dist/__tests__/utils/session.test.js.map +1 -1
- package/dist/adapters/AgentAdapter.d.ts +2 -2
- package/dist/adapters/AgentAdapter.d.ts.map +1 -1
- package/dist/adapters/AgentAdapter.js +1 -1
- package/dist/adapters/AgentAdapter.js.map +1 -1
- package/dist/adapters/CopilotAdapter.d.ts +2 -2
- package/dist/adapters/CopilotAdapter.d.ts.map +1 -1
- package/dist/adapters/CopilotAdapter.js +51 -51
- package/dist/adapters/CopilotAdapter.js.map +1 -1
- package/dist/adapters/GeminiCliAdapter.d.ts +2 -2
- package/dist/adapters/GeminiCliAdapter.d.ts.map +1 -1
- package/dist/adapters/GeminiCliAdapter.js +86 -86
- package/dist/adapters/GeminiCliAdapter.js.map +1 -1
- package/dist/adapters/GrokCliAdapter.d.ts +1 -1
- package/dist/adapters/GrokCliAdapter.d.ts.map +1 -1
- package/dist/adapters/GrokCliAdapter.js +80 -80
- package/dist/adapters/GrokCliAdapter.js.map +1 -1
- package/dist/adapters/OpenCodeAdapter.d.ts +1 -1
- package/dist/adapters/OpenCodeAdapter.d.ts.map +1 -1
- package/dist/adapters/OpenCodeAdapter.js +37 -36
- package/dist/adapters/OpenCodeAdapter.js.map +1 -1
- package/dist/adapters/index.d.ts +9 -9
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +8 -8
- package/dist/adapters/index.js.map +1 -1
- package/dist/capacity/codex.d.ts +3 -3
- package/dist/capacity/codex.d.ts.map +1 -1
- package/dist/capacity/codex.js +57 -57
- package/dist/capacity/codex.js.map +1 -1
- package/dist/capacity/index.d.ts +3 -3
- package/dist/capacity/index.d.ts.map +1 -1
- package/dist/capacity/index.js +8 -8
- package/dist/capacity/index.js.map +1 -1
- package/dist/capacity/types.d.ts +1 -1
- package/dist/capacity/types.js.map +1 -1
- package/dist/database/connection.d.ts +1 -1
- package/dist/database/connection.d.ts.map +1 -1
- package/dist/database/connection.js +15 -15
- package/dist/database/connection.js.map +1 -1
- package/dist/database/index.d.ts +3 -3
- package/dist/database/index.d.ts.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/database/migrations/005_agent_runtime.sql +2 -0
- package/dist/database/schema.d.ts +1 -1
- package/dist/database/schema.d.ts.map +1 -1
- package/dist/database/schema.js +7 -7
- package/dist/database/schema.js.map +1 -1
- package/dist/durable/DurableAgent.d.ts +9 -9
- package/dist/durable/DurableAgent.d.ts.map +1 -1
- package/dist/durable/DurableAgent.js +16 -16
- package/dist/durable/DurableAgent.js.map +1 -1
- package/dist/durable/DurableAgentRepository.d.ts +4 -4
- package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
- package/dist/durable/DurableAgentRepository.js +49 -48
- package/dist/durable/DurableAgentRepository.js.map +1 -1
- package/dist/durable/process.d.ts +1 -1
- package/dist/durable/process.d.ts.map +1 -1
- package/dist/durable/process.js +14 -14
- package/dist/durable/process.js.map +1 -1
- package/dist/durable/run.d.ts +2 -2
- package/dist/durable/run.d.ts.map +1 -1
- package/dist/durable/run.js +6 -6
- package/dist/durable/run.js.map +1 -1
- package/dist/durable/utils.d.ts +1 -1
- package/dist/durable/utils.d.ts.map +1 -1
- package/dist/durable/utils.js +4 -4
- package/dist/durable/utils.js.map +1 -1
- package/dist/index.d.ts +46 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -26
- package/dist/index.js.map +1 -1
- package/dist/providers/claude/ClaudeAgentMapper.d.ts +4 -4
- package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeAgentMapper.js +10 -10
- package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeCodeAdapter.js +14 -14
- package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.d.ts +4 -4
- package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeSessionLocator.js +79 -79
- package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -1
- package/dist/providers/claude/ClaudeSessionParser.d.ts +2 -2
- package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -1
- package/dist/providers/claude/ClaudeSessionParser.js +99 -99
- package/dist/providers/claude/ClaudeSessionParser.js.map +1 -1
- package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -1
- package/dist/providers/claude/durable/ClaudeCliProbe.js +16 -16
- package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -1
- package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts +5 -5
- package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -1
- package/dist/providers/claude/durable/ClaudePrintAgentService.js +10 -10
- package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -1
- package/dist/providers/claude/durable/ClaudePrintRunner.d.ts +4 -4
- package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -1
- package/dist/providers/claude/durable/ClaudePrintRunner.js +18 -18
- package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -1
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +2 -2
- package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -1
- package/dist/providers/claude/durable/ClaudeStreamParser.js +17 -17
- package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -1
- package/dist/providers/codex/CodexAdapter.d.ts +27 -0
- package/dist/providers/codex/CodexAdapter.d.ts.map +1 -0
- package/dist/providers/codex/CodexAdapter.js +162 -0
- package/dist/providers/codex/CodexAdapter.js.map +1 -0
- package/dist/providers/codex/CodexAgentMapper.d.ts +9 -0
- package/dist/providers/codex/CodexAgentMapper.d.ts.map +1 -0
- package/dist/providers/codex/CodexAgentMapper.js +35 -0
- package/dist/providers/codex/CodexAgentMapper.js.map +1 -0
- package/dist/providers/codex/CodexSessionLocator.d.ts +44 -0
- package/dist/providers/codex/CodexSessionLocator.d.ts.map +1 -0
- package/dist/providers/codex/CodexSessionLocator.js +207 -0
- package/dist/providers/codex/CodexSessionLocator.js.map +1 -0
- package/dist/providers/codex/CodexSessionMapping.d.ts +23 -0
- package/dist/providers/codex/CodexSessionMapping.d.ts.map +1 -0
- package/dist/providers/codex/CodexSessionMapping.js +68 -0
- package/dist/providers/codex/CodexSessionMapping.js.map +1 -0
- package/dist/providers/codex/CodexSessionParser.d.ts +58 -0
- package/dist/providers/codex/CodexSessionParser.d.ts.map +1 -0
- package/dist/providers/codex/CodexSessionParser.js +262 -0
- package/dist/providers/codex/CodexSessionParser.js.map +1 -0
- package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -1
- package/dist/providers/codex/durable/CodexCliProbe.js +22 -22
- package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -1
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +6 -6
- package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -1
- package/dist/providers/codex/durable/CodexPrintAgentService.js +10 -10
- package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -1
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts +4 -4
- package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -1
- package/dist/providers/codex/durable/CodexPrintRunner.js +20 -20
- package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -1
- package/dist/providers/codex/durable/CodexStreamParser.d.ts +2 -2
- package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -1
- package/dist/providers/codex/durable/CodexStreamParser.js +21 -21
- package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -1
- package/dist/providers/pi/PiAdapter.d.ts +28 -0
- package/dist/providers/pi/PiAdapter.d.ts.map +1 -0
- package/dist/providers/pi/PiAdapter.js +153 -0
- package/dist/providers/pi/PiAdapter.js.map +1 -0
- package/dist/providers/pi/PiAgentMapper.d.ts +9 -0
- package/dist/providers/pi/PiAgentMapper.d.ts.map +1 -0
- package/dist/providers/pi/PiAgentMapper.js +37 -0
- package/dist/providers/pi/PiAgentMapper.js.map +1 -0
- package/dist/providers/pi/PiSessionLocator.d.ts +23 -0
- package/dist/providers/pi/PiSessionLocator.d.ts.map +1 -0
- package/dist/providers/pi/PiSessionLocator.js +79 -0
- package/dist/providers/pi/PiSessionLocator.js.map +1 -0
- package/dist/providers/pi/PiSessionParser.d.ts +36 -0
- package/dist/providers/pi/PiSessionParser.d.ts.map +1 -0
- package/dist/providers/pi/PiSessionParser.js +191 -0
- package/dist/providers/pi/PiSessionParser.js.map +1 -0
- package/dist/providers/pi/PiSessionTracker.d.ts +23 -0
- package/dist/providers/pi/PiSessionTracker.d.ts.map +1 -0
- package/dist/providers/pi/PiSessionTracker.js +69 -0
- package/dist/providers/pi/PiSessionTracker.js.map +1 -0
- package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -1
- package/dist/providers/pi/durable/PiCliProbe.js +15 -15
- package/dist/providers/pi/durable/PiCliProbe.js.map +1 -1
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts +6 -6
- package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -1
- package/dist/providers/pi/durable/PiPrintAgentService.js +10 -10
- package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -1
- package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -1
- package/dist/providers/pi/durable/PiPrintProtocol.js +18 -18
- package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -1
- package/dist/providers/pi/durable/PiPrintRunner.d.ts +4 -4
- package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -1
- package/dist/providers/pi/durable/PiPrintRunner.js +15 -15
- package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -1
- package/dist/providers/pi/durable/PiStreamParser.d.ts +1 -1
- package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -1
- package/dist/providers/pi/durable/PiStreamParser.js +16 -16
- package/dist/providers/pi/durable/PiStreamParser.js.map +1 -1
- package/dist/readiness/AgentReadiness.d.ts +6 -6
- package/dist/readiness/AgentReadiness.d.ts.map +1 -1
- package/dist/readiness/AgentReadiness.js +130 -130
- package/dist/readiness/AgentReadiness.js.map +1 -1
- package/dist/runtime/ManagedAgentRuntime.d.ts +69 -0
- package/dist/runtime/ManagedAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/ManagedAgentRuntime.js +156 -0
- package/dist/runtime/ManagedAgentRuntime.js.map +1 -0
- package/dist/runtime/RuntimeFactory.d.ts +4 -0
- package/dist/runtime/RuntimeFactory.d.ts.map +1 -0
- package/dist/runtime/RuntimeFactory.js +11 -0
- package/dist/runtime/RuntimeFactory.js.map +1 -0
- package/dist/runtime/errors.d.ts +27 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/errors.js +42 -0
- package/dist/runtime/errors.js.map +1 -0
- package/dist/runtime/herdr/HerdrAgentRuntime.d.ts +31 -0
- package/dist/runtime/herdr/HerdrAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/herdr/HerdrAgentRuntime.js +184 -0
- package/dist/runtime/herdr/HerdrAgentRuntime.js.map +1 -0
- package/dist/runtime/herdr/HerdrCliClient.d.ts +13 -0
- package/dist/runtime/herdr/HerdrCliClient.d.ts.map +1 -0
- package/dist/runtime/herdr/HerdrCliClient.js +60 -0
- package/dist/runtime/herdr/HerdrCliClient.js.map +1 -0
- package/dist/runtime/herdr/HerdrErrors.d.ts +7 -0
- package/dist/runtime/herdr/HerdrErrors.d.ts.map +1 -0
- package/dist/runtime/herdr/HerdrErrors.js +10 -0
- package/dist/runtime/herdr/HerdrErrors.js.map +1 -0
- package/dist/runtime/herdr/HerdrResponseParsers.d.ts +14 -0
- package/dist/runtime/herdr/HerdrResponseParsers.d.ts.map +1 -0
- package/dist/runtime/herdr/HerdrResponseParsers.js +96 -0
- package/dist/runtime/herdr/HerdrResponseParsers.js.map +1 -0
- package/dist/runtime/herdr/HerdrRuntimeRef.d.ts +9 -0
- package/dist/runtime/herdr/HerdrRuntimeRef.d.ts.map +1 -0
- package/dist/runtime/herdr/HerdrRuntimeRef.js +33 -0
- package/dist/runtime/herdr/HerdrRuntimeRef.js.map +1 -0
- package/dist/runtime/tmux/PidPolling.d.ts +5 -0
- package/dist/runtime/tmux/PidPolling.d.ts.map +1 -0
- package/dist/runtime/tmux/PidPolling.js +24 -0
- package/dist/runtime/tmux/PidPolling.js.map +1 -0
- package/dist/runtime/tmux/TmuxAgentRuntime.d.ts +17 -0
- package/dist/runtime/tmux/TmuxAgentRuntime.d.ts.map +1 -0
- package/dist/runtime/tmux/TmuxAgentRuntime.js +80 -0
- package/dist/runtime/tmux/TmuxAgentRuntime.js.map +1 -0
- package/dist/runtime/tmux/TmuxRuntimeRef.d.ts +5 -0
- package/dist/runtime/tmux/TmuxRuntimeRef.d.ts.map +1 -0
- package/dist/runtime/tmux/TmuxRuntimeRef.js +9 -0
- package/dist/runtime/tmux/TmuxRuntimeRef.js.map +1 -0
- package/dist/runtime/types.d.ts +54 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +3 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
- package/dist/terminal/TerminalFocusManager.js +50 -50
- package/dist/terminal/TerminalFocusManager.js.map +1 -1
- package/dist/terminal/TmuxManager.d.ts.map +1 -1
- package/dist/terminal/TmuxManager.js +47 -47
- package/dist/terminal/TmuxManager.js.map +1 -1
- package/dist/terminal/TtyWriter.d.ts +1 -1
- package/dist/terminal/TtyWriter.d.ts.map +1 -1
- package/dist/terminal/TtyWriter.js +89 -89
- package/dist/terminal/TtyWriter.js.map +1 -1
- package/dist/terminal/index.d.ts +4 -4
- package/dist/terminal/index.js +3 -3
- package/dist/terminal/index.js.map +1 -1
- package/dist/utils/AgentRegistry.d.ts +10 -2
- package/dist/utils/AgentRegistry.d.ts.map +1 -1
- package/dist/utils/AgentRegistry.js +57 -24
- package/dist/utils/AgentRegistry.js.map +1 -1
- package/dist/utils/agent-requests.d.ts.map +1 -1
- package/dist/utils/agent-requests.js +5 -5
- package/dist/utils/agent-requests.js.map +1 -1
- package/dist/utils/agents.d.ts +2 -2
- package/dist/utils/agents.d.ts.map +1 -1
- package/dist/utils/agents.js +15 -15
- package/dist/utils/agents.js.map +1 -1
- package/dist/utils/applescript.js +1 -1
- package/dist/utils/applescript.js.map +1 -1
- package/dist/utils/index.d.ts +6 -6
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/matching.d.ts +2 -2
- package/dist/utils/matching.d.ts.map +1 -1
- package/dist/utils/matching.js +4 -4
- package/dist/utils/matching.js.map +1 -1
- package/dist/utils/process.d.ts +1 -1
- package/dist/utils/process.d.ts.map +1 -1
- package/dist/utils/process.js +74 -74
- package/dist/utils/process.js.map +1 -1
- package/dist/utils/session.d.ts +1 -1
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +7 -7
- package/dist/utils/session.js.map +1 -1
- package/dist/utils/sortAgents.d.ts +2 -2
- package/dist/utils/sortAgents.d.ts.map +1 -1
- package/dist/utils/sortAgents.js +5 -5
- package/dist/utils/sortAgents.js.map +1 -1
- package/package.json +18 -19
- package/src/AgentManager.ts +283 -281
- package/src/__tests__/AgentManager.test.ts +917 -907
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1657 -1368
- package/src/__tests__/adapters/CodexAdapter.test.ts +365 -1698
- package/src/__tests__/adapters/CopilotAdapter.test.ts +576 -481
- package/src/__tests__/adapters/GeminiCliAdapter.test.ts +1189 -1157
- package/src/__tests__/adapters/GrokCliAdapter.test.ts +325 -272
- package/src/__tests__/adapters/OpenCodeAdapter.test.ts +510 -455
- package/src/__tests__/capacity/codex.test.ts +178 -91
- package/src/__tests__/capacity/index.test.ts +27 -18
- package/src/__tests__/durable/CodexCliProbe.test.ts +75 -53
- package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +51 -40
- package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +89 -64
- package/src/__tests__/durable/CodexPrintAgentService.test.ts +196 -118
- package/src/__tests__/durable/CodexPrintRunner.test.ts +282 -162
- package/src/__tests__/fixtures/fake-claude.cjs +20 -13
- package/src/__tests__/fixtures/fake-codex.cjs +41 -30
- package/src/__tests__/print/ClaudeCliProbe.test.ts +27 -21
- package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +48 -40
- package/src/__tests__/print/ClaudePrintAgentService.test.ts +118 -67
- package/src/__tests__/print/ClaudePrintRunner.test.ts +136 -83
- package/src/__tests__/print/DurableAgent.test.ts +19 -16
- package/src/__tests__/print/DurableAgentRepository.sqlite.test.ts +109 -86
- package/src/__tests__/print/DurableAgentRepository.test.ts +170 -137
- package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +65 -65
- package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +400 -377
- package/src/__tests__/providers/codex/CodexSessionLocator.test.ts +182 -0
- package/src/__tests__/providers/codex/CodexSessionMapping.test.ts +63 -0
- package/src/__tests__/providers/codex/CodexSessionParser.test.ts +192 -0
- package/src/__tests__/providers/pi/PiAdapter.test.ts +310 -0
- package/src/__tests__/providers/pi/PiSessionParser.test.ts +190 -0
- package/src/__tests__/providers/pi/PiSessionTracker.test.ts +79 -0
- package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +48 -32
- package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +24 -23
- package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +131 -59
- package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +66 -28
- package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +236 -90
- package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +20 -18
- package/src/__tests__/readiness/AgentReadiness.test.ts +217 -169
- package/src/__tests__/runtime/AgentRuntime.test.ts +8 -0
- package/src/__tests__/runtime/HerdrAgentRuntime.test.ts +358 -0
- package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +555 -0
- package/src/__tests__/terminal/TerminalFocusManager.test.ts +254 -253
- package/src/__tests__/terminal/TmuxManager.test.ts +157 -157
- package/src/__tests__/terminal/TtyWriter.test.ts +423 -419
- package/src/__tests__/utils/AgentRegistry.test.ts +506 -402
- package/src/__tests__/utils/ClaudeSessionParser.test.ts +276 -242
- package/src/__tests__/utils/agent-requests.test.ts +76 -56
- package/src/__tests__/utils/agents.test.ts +20 -20
- package/src/__tests__/utils/matching.test.ts +206 -171
- package/src/__tests__/utils/process.test.ts +276 -262
- package/src/__tests__/utils/session.test.ts +133 -139
- package/src/adapters/AgentAdapter.ts +134 -126
- package/src/adapters/CopilotAdapter.ts +405 -395
- package/src/adapters/GeminiCliAdapter.ts +598 -600
- package/src/adapters/GrokCliAdapter.ts +353 -342
- package/src/adapters/OpenCodeAdapter.ts +285 -259
- package/src/adapters/index.ts +15 -9
- package/src/capacity/codex.ts +137 -84
- package/src/capacity/index.ts +18 -13
- package/src/capacity/types.ts +1 -1
- package/src/database/connection.ts +73 -68
- package/src/database/index.ts +6 -6
- package/src/database/migrations/005_agent_runtime.sql +2 -0
- package/src/database/schema.ts +40 -38
- package/src/durable/DurableAgent.ts +85 -85
- package/src/durable/DurableAgentRepository.ts +409 -260
- package/src/durable/process.ts +22 -21
- package/src/durable/run.ts +61 -51
- package/src/durable/utils.ts +46 -41
- package/src/index.ts +144 -103
- package/src/providers/claude/ClaudeAgentMapper.ts +51 -50
- package/src/providers/claude/ClaudeCodeAdapter.ts +144 -136
- package/src/providers/claude/ClaudeSessionLocator.ts +291 -293
- package/src/providers/claude/ClaudeSessionParser.ts +322 -338
- package/src/providers/claude/durable/ClaudeCliProbe.ts +42 -37
- package/src/providers/claude/durable/ClaudePrintAgentService.ts +63 -50
- package/src/providers/claude/durable/ClaudePrintRunner.ts +79 -69
- package/src/providers/claude/durable/ClaudeStreamParser.ts +91 -62
- package/src/providers/codex/CodexAdapter.ts +205 -0
- package/src/providers/codex/CodexAgentMapper.ts +35 -0
- package/src/providers/codex/CodexSessionLocator.ts +279 -0
- package/src/providers/codex/CodexSessionMapping.ts +89 -0
- package/src/providers/codex/CodexSessionParser.ts +385 -0
- package/src/providers/codex/durable/CodexCliProbe.ts +50 -42
- package/src/providers/codex/durable/CodexPrintAgentService.ts +63 -49
- package/src/providers/codex/durable/CodexPrintRunner.ts +79 -69
- package/src/providers/codex/durable/CodexStreamParser.ts +97 -84
- package/src/providers/pi/PiAdapter.ts +183 -0
- package/src/providers/pi/PiAgentMapper.ts +36 -0
- package/src/providers/pi/PiSessionLocator.ts +95 -0
- package/src/providers/pi/PiSessionParser.ts +284 -0
- package/src/providers/pi/PiSessionTracker.ts +87 -0
- package/src/providers/pi/durable/PiCliProbe.ts +42 -34
- package/src/providers/pi/durable/PiPrintAgentService.ts +61 -53
- package/src/providers/pi/durable/PiPrintProtocol.ts +31 -29
- package/src/providers/pi/durable/PiPrintRunner.ts +75 -68
- package/src/providers/pi/durable/PiStreamParser.ts +82 -72
- package/src/readiness/AgentReadiness.ts +585 -513
- package/src/runtime/ManagedAgentRuntime.ts +266 -0
- package/src/runtime/RuntimeFactory.ts +13 -0
- package/src/runtime/errors.ts +50 -0
- package/src/runtime/herdr/HerdrAgentRuntime.ts +190 -0
- package/src/runtime/herdr/HerdrCliClient.ts +78 -0
- package/src/runtime/herdr/HerdrErrors.ts +9 -0
- package/src/runtime/herdr/HerdrResponseParsers.ts +76 -0
- package/src/runtime/herdr/HerdrRuntimeRef.ts +41 -0
- package/src/runtime/tmux/PidPolling.ts +34 -0
- package/src/runtime/tmux/TmuxAgentRuntime.ts +113 -0
- package/src/runtime/tmux/TmuxRuntimeRef.ts +9 -0
- package/src/runtime/types.ts +56 -0
- package/src/terminal/TerminalFocusManager.ts +215 -212
- package/src/terminal/TmuxManager.ts +99 -92
- package/src/terminal/TtyWriter.ts +203 -194
- package/src/terminal/index.ts +4 -4
- package/src/utils/AgentRegistry.ts +299 -238
- package/src/utils/agent-requests.ts +16 -16
- package/src/utils/agents.ts +41 -38
- package/src/utils/applescript.ts +4 -4
- package/src/utils/index.ts +12 -6
- package/src/utils/matching.ts +43 -43
- package/src/utils/process.ts +261 -258
- package/src/utils/session.ts +66 -66
- package/src/utils/sortAgents.ts +35 -33
- package/tsconfig.json +2 -8
- package/vitest.config.ts +16 -16
- package/.eslintrc.json +0 -31
- package/dist/__tests__/adapters/PiAdapter.test.js +0 -618
- package/dist/__tests__/adapters/PiAdapter.test.js.map +0 -1
- package/dist/__tests__/database/DurableAgentsDatabase.test.js +0 -128
- package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +0 -1
- package/dist/adapters/CodexAdapter.d.ts +0 -109
- package/dist/adapters/CodexAdapter.d.ts.map +0 -1
- package/dist/adapters/CodexAdapter.js +0 -710
- package/dist/adapters/CodexAdapter.js.map +0 -1
- package/dist/adapters/PiAdapter.d.ts +0 -63
- package/dist/adapters/PiAdapter.d.ts.map +0 -1
- package/dist/adapters/PiAdapter.js +0 -453
- package/dist/adapters/PiAdapter.js.map +0 -1
- package/src/__tests__/adapters/PiAdapter.test.ts +0 -458
- package/src/__tests__/database/DurableAgentsDatabase.test.ts +0 -102
- package/src/adapters/CodexAdapter.ts +0 -923
- package/src/adapters/PiAdapter.ts +0 -598
package/dist/capacity/codex.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { spawn } from
|
|
2
|
-
import { readFile } from
|
|
3
|
-
import { join } from
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
4
|
export const CODEX_APP_SERVER_ARGS = [
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
"-s",
|
|
6
|
+
"read-only",
|
|
7
|
+
"-a",
|
|
8
|
+
"untrusted",
|
|
9
|
+
"app-server"
|
|
10
10
|
];
|
|
11
11
|
function record(value) {
|
|
12
|
-
return value !== null && typeof value ===
|
|
12
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
13
13
|
}
|
|
14
14
|
function finiteNumber(value) {
|
|
15
|
-
return typeof value ===
|
|
15
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
16
16
|
}
|
|
17
17
|
function nonEmptyText(value) {
|
|
18
|
-
return typeof value ===
|
|
18
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
19
19
|
}
|
|
20
20
|
function resetTime(value) {
|
|
21
21
|
const seconds = finiteNumber(value);
|
|
22
22
|
if (seconds !== null) return new Date(seconds * 1000).toISOString();
|
|
23
|
-
if (typeof value ===
|
|
23
|
+
if (typeof value === "string" && !Number.isNaN(Date.parse(value))) return new Date(value).toISOString();
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
26
|
function safeIdentifier(value) {
|
|
@@ -30,8 +30,8 @@ function safeIdentifier(value) {
|
|
|
30
30
|
return candidate;
|
|
31
31
|
}
|
|
32
32
|
export function resolveCodexAuthPath(env = process.env) {
|
|
33
|
-
const root = env.CODEX_HOME || join(env.HOME ||
|
|
34
|
-
return join(root,
|
|
33
|
+
const root = env.CODEX_HOME || join(env.HOME || "", ".codex");
|
|
34
|
+
return join(root, "auth.json");
|
|
35
35
|
}
|
|
36
36
|
export function toRateWindow(value, id, label) {
|
|
37
37
|
const input = record(value);
|
|
@@ -65,8 +65,8 @@ export function parseUsage(raw, source) {
|
|
|
65
65
|
const credits = record(response.credits) ?? {};
|
|
66
66
|
return {
|
|
67
67
|
windows: [
|
|
68
|
-
toRateWindow(limits.primary_window,
|
|
69
|
-
toRateWindow(limits.secondary_window,
|
|
68
|
+
toRateWindow(limits.primary_window, "session", "Session"),
|
|
69
|
+
toRateWindow(limits.secondary_window, "weekly", "Weekly"),
|
|
70
70
|
...extraWindows(response.additional_rate_limits)
|
|
71
71
|
].filter((window)=>window !== null),
|
|
72
72
|
creditsRemaining: finiteNumber(credits.balance),
|
|
@@ -87,7 +87,7 @@ function cliWindow(value, id, label) {
|
|
|
87
87
|
function cliSnapshotWindows(value, fallbackId) {
|
|
88
88
|
const snapshot = record(value);
|
|
89
89
|
if (!snapshot) return [];
|
|
90
|
-
const scope = safeIdentifier(snapshot.limitId) ?? safeIdentifier(fallbackId) ??
|
|
90
|
+
const scope = safeIdentifier(snapshot.limitId) ?? safeIdentifier(fallbackId) ?? "codex";
|
|
91
91
|
return [
|
|
92
92
|
cliWindow(snapshot.primary, `${scope}:primary`, `${scope} primary`),
|
|
93
93
|
cliWindow(snapshot.secondary, `${scope}:secondary`, `${scope} secondary`)
|
|
@@ -96,7 +96,7 @@ function cliSnapshotWindows(value, fallbackId) {
|
|
|
96
96
|
export function parseCliUsage(raw) {
|
|
97
97
|
const response = record(raw) ?? {};
|
|
98
98
|
const primary = record(response.rateLimits);
|
|
99
|
-
const windows = primary ? cliSnapshotWindows(primary,
|
|
99
|
+
const windows = primary ? cliSnapshotWindows(primary, "codex") : [];
|
|
100
100
|
const buckets = record(response.rateLimitsByLimitId);
|
|
101
101
|
if (buckets) {
|
|
102
102
|
for (const [id, snapshot] of Object.entries(buckets))windows.push(...cliSnapshotWindows(snapshot, id));
|
|
@@ -110,7 +110,7 @@ export function parseCliUsage(raw) {
|
|
|
110
110
|
return {
|
|
111
111
|
windows: unique,
|
|
112
112
|
creditsRemaining: null,
|
|
113
|
-
source:
|
|
113
|
+
source: "cli"
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
function capacityFromSnapshot(snapshot, context, raw) {
|
|
@@ -119,19 +119,19 @@ function capacityFromSnapshot(snapshot, context, raw) {
|
|
|
119
119
|
const reached = nonEmptyText(rateLimits?.rateLimitReachedType);
|
|
120
120
|
const resetCredits = record(record(raw)?.rateLimitResetCredits) ?? record(record(raw)?.usageLimitResetCredits);
|
|
121
121
|
return {
|
|
122
|
-
provider:
|
|
122
|
+
provider: "codex",
|
|
123
123
|
generatedAt: context.checkedAt,
|
|
124
124
|
authenticated: true,
|
|
125
|
-
available: reached ?
|
|
125
|
+
available: reached ? "no" : hasUsage ? "yes" : "unknown",
|
|
126
126
|
windows: snapshot.windows,
|
|
127
127
|
creditsRemaining: snapshot.creditsRemaining ?? finiteNumber(resetCredits?.availableCount)
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
function jwtExpiry(token) {
|
|
131
|
-
const part = token.split(
|
|
131
|
+
const part = token.split(".")[1];
|
|
132
132
|
if (!part) return null;
|
|
133
133
|
try {
|
|
134
|
-
return finiteNumber(record(JSON.parse(Buffer.from(part,
|
|
134
|
+
return finiteNumber(record(JSON.parse(Buffer.from(part, "base64url").toString("utf8")))?.exp);
|
|
135
135
|
} catch {
|
|
136
136
|
return null;
|
|
137
137
|
}
|
|
@@ -139,7 +139,7 @@ function jwtExpiry(token) {
|
|
|
139
139
|
function staleOAuth(tokens, token, now) {
|
|
140
140
|
const metadata = tokens.expires_at ?? tokens.expiresAt ?? tokens.expiry;
|
|
141
141
|
let expiry = finiteNumber(metadata);
|
|
142
|
-
if (typeof metadata ===
|
|
142
|
+
if (typeof metadata === "string") {
|
|
143
143
|
const parsed = Date.parse(metadata);
|
|
144
144
|
expiry = Number.isNaN(parsed) ? null : parsed / 1000;
|
|
145
145
|
}
|
|
@@ -154,7 +154,7 @@ async function fetchJson(fetcher, url, init, timeoutMs) {
|
|
|
154
154
|
...init,
|
|
155
155
|
signal: controller.signal
|
|
156
156
|
});
|
|
157
|
-
if (!response.ok) throw new Error(response.status === 401 ?
|
|
157
|
+
if (!response.ok) throw new Error(response.status === 401 ? "unauthorized" : "request failed");
|
|
158
158
|
return await response.json();
|
|
159
159
|
} finally{
|
|
160
160
|
clearTimeout(timer);
|
|
@@ -162,25 +162,25 @@ async function fetchJson(fetcher, url, init, timeoutMs) {
|
|
|
162
162
|
}
|
|
163
163
|
async function apiSnapshot(token, accountId, source, options) {
|
|
164
164
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
165
|
-
const raw = await fetchJson(fetcher,
|
|
165
|
+
const raw = await fetchJson(fetcher, "https://chatgpt.com/backend-api/wham/usage", {
|
|
166
166
|
headers: {
|
|
167
167
|
Authorization: `Bearer ${token}`,
|
|
168
|
-
|
|
168
|
+
"ChatGPT-Account-Id": accountId
|
|
169
169
|
}
|
|
170
170
|
}, options.timeoutMs ?? 5000);
|
|
171
171
|
return parseUsage(raw, source);
|
|
172
172
|
}
|
|
173
173
|
function appServerRpc(messages, timeoutMs = 5000) {
|
|
174
174
|
return new Promise((resolve, reject)=>{
|
|
175
|
-
const child = spawn(
|
|
175
|
+
const child = spawn("codex", CODEX_APP_SERVER_ARGS, {
|
|
176
176
|
stdio: [
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
"pipe",
|
|
178
|
+
"pipe",
|
|
179
|
+
"ignore"
|
|
180
180
|
]
|
|
181
181
|
});
|
|
182
182
|
const results = {};
|
|
183
|
-
let buffer =
|
|
183
|
+
let buffer = "";
|
|
184
184
|
let settled = false;
|
|
185
185
|
const finish = (error)=>{
|
|
186
186
|
if (settled) return;
|
|
@@ -190,16 +190,16 @@ function appServerRpc(messages, timeoutMs = 5000) {
|
|
|
190
190
|
if (error) reject(error);
|
|
191
191
|
else resolve(results);
|
|
192
192
|
};
|
|
193
|
-
const timer = setTimeout(()=>finish(new Error(
|
|
194
|
-
child.once(
|
|
195
|
-
child.once(
|
|
196
|
-
if (!settled) finish(new Error(
|
|
193
|
+
const timer = setTimeout(()=>finish(new Error("codex probe timed out")), timeoutMs);
|
|
194
|
+
child.once("error", ()=>finish(new Error("codex app-server unavailable")));
|
|
195
|
+
child.once("exit", ()=>{
|
|
196
|
+
if (!settled) finish(new Error("codex app-server exited"));
|
|
197
197
|
});
|
|
198
|
-
child.stdout.setEncoding(
|
|
199
|
-
child.stdout.on(
|
|
198
|
+
child.stdout.setEncoding("utf8");
|
|
199
|
+
child.stdout.on("data", (chunk)=>{
|
|
200
200
|
buffer += chunk;
|
|
201
201
|
for(;;){
|
|
202
|
-
const newline = buffer.indexOf(
|
|
202
|
+
const newline = buffer.indexOf("\n");
|
|
203
203
|
if (newline < 0) break;
|
|
204
204
|
const line = buffer.slice(0, newline).trim();
|
|
205
205
|
buffer = buffer.slice(newline + 1);
|
|
@@ -213,13 +213,13 @@ function appServerRpc(messages, timeoutMs = 5000) {
|
|
|
213
213
|
if (message.id === 1) {
|
|
214
214
|
for (const request of messages.slice(1))child.stdin.write(`${JSON.stringify(request)}\n`);
|
|
215
215
|
} else if (message.id === 2) {
|
|
216
|
-
if (message.error) finish(new Error(
|
|
216
|
+
if (message.error) finish(new Error("codex rate-limit method failed"));
|
|
217
217
|
else results.rateLimits = message.result;
|
|
218
218
|
} else if (message.id === 3) {
|
|
219
|
-
if (message.error) finish(new Error(
|
|
219
|
+
if (message.error) finish(new Error("codex account method failed"));
|
|
220
220
|
else results.account = message.result;
|
|
221
221
|
}
|
|
222
|
-
if (
|
|
222
|
+
if ("rateLimits" in results && "account" in results) finish();
|
|
223
223
|
}
|
|
224
224
|
});
|
|
225
225
|
child.stdin.write(`${JSON.stringify(messages[0])}\n`);
|
|
@@ -227,10 +227,10 @@ function appServerRpc(messages, timeoutMs = 5000) {
|
|
|
227
227
|
}
|
|
228
228
|
function unavailable(options) {
|
|
229
229
|
return {
|
|
230
|
-
provider:
|
|
230
|
+
provider: "codex",
|
|
231
231
|
generatedAt: options.checkedAt,
|
|
232
232
|
authenticated: null,
|
|
233
|
-
available:
|
|
233
|
+
available: "unknown",
|
|
234
234
|
windows: [],
|
|
235
235
|
creditsRemaining: null
|
|
236
236
|
};
|
|
@@ -240,26 +240,26 @@ async function cliFallback(options) {
|
|
|
240
240
|
const messages = [
|
|
241
241
|
{
|
|
242
242
|
id: 1,
|
|
243
|
-
method:
|
|
243
|
+
method: "initialize",
|
|
244
244
|
params: {
|
|
245
245
|
clientInfo: {
|
|
246
|
-
name:
|
|
246
|
+
name: "ai-devkit",
|
|
247
247
|
title: null,
|
|
248
|
-
version:
|
|
248
|
+
version: "1"
|
|
249
249
|
},
|
|
250
250
|
capabilities: null
|
|
251
251
|
}
|
|
252
252
|
},
|
|
253
253
|
{
|
|
254
|
-
method:
|
|
254
|
+
method: "initialized"
|
|
255
255
|
},
|
|
256
256
|
{
|
|
257
257
|
id: 2,
|
|
258
|
-
method:
|
|
258
|
+
method: "account/rateLimits/read"
|
|
259
259
|
},
|
|
260
260
|
{
|
|
261
261
|
id: 3,
|
|
262
|
-
method:
|
|
262
|
+
method: "account/read"
|
|
263
263
|
}
|
|
264
264
|
];
|
|
265
265
|
try {
|
|
@@ -267,9 +267,9 @@ async function cliFallback(options) {
|
|
|
267
267
|
const response = await rpc(messages);
|
|
268
268
|
const result = capacityFromSnapshot(parseCliUsage(response.rateLimits), options, response.rateLimits);
|
|
269
269
|
const accountEnvelope = record(response.account);
|
|
270
|
-
if (accountEnvelope && Object.hasOwn(accountEnvelope,
|
|
270
|
+
if (accountEnvelope && Object.hasOwn(accountEnvelope, "account") && !record(accountEnvelope.account)) {
|
|
271
271
|
result.authenticated = false;
|
|
272
|
-
result.available =
|
|
272
|
+
result.available = "unknown";
|
|
273
273
|
}
|
|
274
274
|
return result;
|
|
275
275
|
} catch {
|
|
@@ -279,7 +279,7 @@ async function cliFallback(options) {
|
|
|
279
279
|
export async function probeCodexCapacity(options) {
|
|
280
280
|
let parsed = null;
|
|
281
281
|
try {
|
|
282
|
-
const contents = await (options.readFile ?? readFile)(resolveCodexAuthPath(options.env),
|
|
282
|
+
const contents = await (options.readFile ?? readFile)(resolveCodexAuthPath(options.env), "utf8");
|
|
283
283
|
parsed = record(JSON.parse(contents));
|
|
284
284
|
} catch {
|
|
285
285
|
return cliFallback(options);
|
|
@@ -289,14 +289,14 @@ export async function probeCodexCapacity(options) {
|
|
|
289
289
|
if (pat) {
|
|
290
290
|
try {
|
|
291
291
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
292
|
-
const whoami = record(await fetchJson(fetcher,
|
|
292
|
+
const whoami = record(await fetchJson(fetcher, "https://auth.openai.com/api/accounts/v1/user-auth-credential/whoami", {
|
|
293
293
|
headers: {
|
|
294
294
|
Authorization: `Bearer ${pat}`
|
|
295
295
|
}
|
|
296
296
|
}, options.timeoutMs ?? 5000));
|
|
297
297
|
const accountId = nonEmptyText(whoami?.chatgpt_account_id);
|
|
298
|
-
if (!accountId) throw new Error(
|
|
299
|
-
return capacityFromSnapshot(await apiSnapshot(pat, accountId,
|
|
298
|
+
if (!accountId) throw new Error("account unavailable");
|
|
299
|
+
return capacityFromSnapshot(await apiSnapshot(pat, accountId, "pat", options), options);
|
|
300
300
|
} catch {
|
|
301
301
|
// Continue to a separately available OAuth credential before using the CLI.
|
|
302
302
|
}
|
|
@@ -306,7 +306,7 @@ export async function probeCodexCapacity(options) {
|
|
|
306
306
|
const accountId = nonEmptyText(tokens?.account_id);
|
|
307
307
|
if (tokens && accessToken && accountId && !staleOAuth(tokens, accessToken, (options.now ?? (()=>new Date()))())) {
|
|
308
308
|
try {
|
|
309
|
-
return capacityFromSnapshot(await apiSnapshot(accessToken, accountId,
|
|
309
|
+
return capacityFromSnapshot(await apiSnapshot(accessToken, accountId, "oauth", options), options);
|
|
310
310
|
} catch {
|
|
311
311
|
return cliFallback(options);
|
|
312
312
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/capacity/codex.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { CapacityReport, CapacityWindow } from './types.js';\n\ntype CodexUsageSource = 'pat' | 'oauth' | 'cli';\ntype UsageSnapshot = { windows: CapacityWindow[]; creditsRemaining: number | null; source: CodexUsageSource };\n\ntype UnknownRecord = Record<string, unknown>;\ntype RpcMessage = { id?: number; method: string; params?: UnknownRecord };\ntype CliResponses = { rateLimits: unknown; account: unknown };\ntype CodexRpc = (messages: RpcMessage[]) => Promise<CliResponses>;\n\nexport const CODEX_APP_SERVER_ARGS = ['-s', 'read-only', '-a', 'untrusted', 'app-server'] as const;\n\ntype CodexProbeOptions = {\n installed: boolean;\n checkedAt: string;\n readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;\n fetch?: typeof globalThis.fetch;\n rpc?: CodexRpc;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n now?: () => Date;\n};\n\nfunction record(value: unknown): UnknownRecord | null {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? value as UnknownRecord\n : null;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction resetTime(value: unknown): string | null {\n const seconds = finiteNumber(value);\n if (seconds !== null) return new Date(seconds * 1000).toISOString();\n if (typeof value === 'string' && !Number.isNaN(Date.parse(value))) return new Date(value).toISOString();\n return null;\n}\n\nfunction safeIdentifier(value: unknown): string | null {\n const candidate = nonEmptyText(value);\n if (!candidate || !/^[a-z][a-z0-9_-]{0,63}$/i.test(candidate)) return null;\n if (/(?:account|token|secret|key)[_-]?\\d{6,}/i.test(candidate)) return null;\n return candidate;\n}\n\nexport function resolveCodexAuthPath(env: NodeJS.ProcessEnv = process.env): string {\n const root = env.CODEX_HOME || join(env.HOME || '', '.codex');\n return join(root, 'auth.json');\n}\n\nexport function toRateWindow(\n value: unknown,\n id: string,\n label: string\n): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n const used = finiteNumber(input.used_percent);\n const seconds = finiteNumber(input.limit_window_seconds);\n return {\n id,\n label,\n durationMinutes: seconds === null ? null : seconds / 60,\n usedPercent: used,\n resetsAt: resetTime(input.reset_at)\n };\n}\n\nfunction extraWindows(value: unknown): CapacityWindow[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry, index) => {\n const limit = record(entry);\n if (!limit) return [];\n const scope = safeIdentifier(limit.limit_name) ?? `extra-${index + 1}`;\n const windows = record(limit.rate_limit) ?? limit;\n return [\n toRateWindow(windows.primary_window, `${scope}:primary`, `${scope} primary`),\n toRateWindow(windows.secondary_window, `${scope}:secondary`, `${scope} secondary`)\n ].filter((window): window is CapacityWindow => window !== null);\n });\n}\n\nexport function parseUsage(raw: unknown, source: 'pat' | 'oauth'): UsageSnapshot {\n const response = record(raw) ?? {};\n const limits = record(response.rate_limit) ?? {};\n const credits = record(response.credits) ?? {};\n return {\n windows: [\n toRateWindow(limits.primary_window, 'session', 'Session'),\n toRateWindow(limits.secondary_window, 'weekly', 'Weekly'),\n ...extraWindows(response.additional_rate_limits)\n ].filter((window): window is CapacityWindow => window !== null),\n creditsRemaining: finiteNumber(credits.balance),\n source\n };\n}\n\nfunction cliWindow(value: unknown, id: string, label: string): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n return {\n id,\n label,\n durationMinutes: finiteNumber(input.windowDurationMins),\n usedPercent: finiteNumber(input.usedPercent),\n resetsAt: resetTime(input.resetsAt)\n };\n}\n\nfunction cliSnapshotWindows(value: unknown, fallbackId: string): CapacityWindow[] {\n const snapshot = record(value);\n if (!snapshot) return [];\n const scope = safeIdentifier(snapshot.limitId) ?? safeIdentifier(fallbackId) ?? 'codex';\n return [\n cliWindow(snapshot.primary, `${scope}:primary`, `${scope} primary`),\n cliWindow(snapshot.secondary, `${scope}:secondary`, `${scope} secondary`)\n ].filter((item): item is CapacityWindow => item !== null);\n}\n\nexport function parseCliUsage(raw: unknown): UsageSnapshot {\n const response = record(raw) ?? {};\n const primary = record(response.rateLimits);\n const windows = primary ? cliSnapshotWindows(primary, 'codex') : [];\n const buckets = record(response.rateLimitsByLimitId);\n if (buckets) {\n for (const [id, snapshot] of Object.entries(buckets)) windows.push(...cliSnapshotWindows(snapshot, id));\n }\n const unique = [...new Map(windows.map(window => [window.id, window])).values()];\n return { windows: unique, creditsRemaining: null, source: 'cli' };\n}\n\nfunction capacityFromSnapshot(snapshot: UsageSnapshot, context: CodexProbeOptions, raw?: unknown): CapacityReport {\n const hasUsage = snapshot.windows.some(window => window.usedPercent !== null);\n const rateLimits = record(record(raw)?.rateLimits);\n const reached = nonEmptyText(rateLimits?.rateLimitReachedType);\n const resetCredits = record(record(raw)?.rateLimitResetCredits) ?? record(record(raw)?.usageLimitResetCredits);\n return {\n provider: 'codex',\n generatedAt: context.checkedAt,\n authenticated: true,\n available: reached ? 'no' : hasUsage ? 'yes' : 'unknown',\n windows: snapshot.windows,\n creditsRemaining: snapshot.creditsRemaining ?? finiteNumber(resetCredits?.availableCount)\n };\n}\n\nfunction jwtExpiry(token: string): number | null {\n const part = token.split('.')[1];\n if (!part) return null;\n try {\n return finiteNumber(record(JSON.parse(Buffer.from(part, 'base64url').toString('utf8')))?.exp);\n } catch {\n return null;\n }\n}\n\nfunction staleOAuth(tokens: UnknownRecord, token: string, now: Date): boolean {\n const metadata = tokens.expires_at ?? tokens.expiresAt ?? tokens.expiry;\n let expiry: number | null = finiteNumber(metadata);\n if (typeof metadata === 'string') {\n const parsed = Date.parse(metadata);\n expiry = Number.isNaN(parsed) ? null : parsed / 1000;\n }\n expiry ??= jwtExpiry(token);\n return expiry !== null && expiry <= now.getTime() / 1000;\n}\n\nasync function fetchJson(fetcher: typeof globalThis.fetch, url: string, init: RequestInit, timeoutMs: number): Promise<unknown> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetcher(url, { ...init, signal: controller.signal });\n if (!response.ok) throw new Error(response.status === 401 ? 'unauthorized' : 'request failed');\n return await response.json();\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function apiSnapshot(\n token: string,\n accountId: string,\n source: 'pat' | 'oauth',\n options: CodexProbeOptions\n): Promise<UsageSnapshot> {\n const fetcher = options.fetch ?? globalThis.fetch;\n const raw = await fetchJson(fetcher, 'https://chatgpt.com/backend-api/wham/usage', {\n headers: { Authorization: `Bearer ${token}`, 'ChatGPT-Account-Id': accountId }\n }, options.timeoutMs ?? 5000);\n return parseUsage(raw, source);\n}\n\nfunction appServerRpc(messages: RpcMessage[], timeoutMs = 5000): Promise<CliResponses> {\n return new Promise((resolve, reject) => {\n const child = spawn('codex', CODEX_APP_SERVER_ARGS, {\n stdio: ['pipe', 'pipe', 'ignore']\n });\n const results: Partial<CliResponses> = {};\n let buffer = '';\n let settled = false;\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n child.kill();\n if (error) reject(error);\n else resolve(results as CliResponses);\n };\n const timer = setTimeout(() => finish(new Error('codex probe timed out')), timeoutMs);\n child.once('error', () => finish(new Error('codex app-server unavailable')));\n child.once('exit', () => { if (!settled) finish(new Error('codex app-server exited')); });\n child.stdout.setEncoding('utf8');\n child.stdout.on('data', (chunk: string) => {\n buffer += chunk;\n for (;;) {\n const newline = buffer.indexOf('\\n');\n if (newline < 0) break;\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (!line) continue;\n let message: UnknownRecord;\n try { message = JSON.parse(line) as UnknownRecord; } catch { continue; }\n if (message.id === 1) {\n for (const request of messages.slice(1)) child.stdin.write(`${JSON.stringify(request)}\\n`);\n } else if (message.id === 2) {\n if (message.error) finish(new Error('codex rate-limit method failed'));\n else results.rateLimits = message.result;\n } else if (message.id === 3) {\n if (message.error) finish(new Error('codex account method failed'));\n else results.account = message.result;\n }\n if ('rateLimits' in results && 'account' in results) finish();\n }\n });\n child.stdin.write(`${JSON.stringify(messages[0])}\\n`);\n });\n}\n\nfunction unavailable(options: CodexProbeOptions): CapacityReport {\n return {\n provider: 'codex',\n generatedAt: options.checkedAt,\n authenticated: null,\n available: 'unknown',\n windows: [],\n creditsRemaining: null\n };\n}\n\nasync function cliFallback(options: CodexProbeOptions): Promise<CapacityReport> {\n if (!options.installed) return unavailable(options);\n const messages: RpcMessage[] = [\n { id: 1, method: 'initialize', params: {\n clientInfo: { name: 'ai-devkit', title: null, version: '1' }, capabilities: null\n } },\n { method: 'initialized' },\n { id: 2, method: 'account/rateLimits/read' },\n { id: 3, method: 'account/read' }\n ];\n try {\n const rpc = options.rpc ?? (requests => appServerRpc(requests, options.timeoutMs));\n const response = await rpc(messages);\n const result = capacityFromSnapshot(parseCliUsage(response.rateLimits), options, response.rateLimits);\n const accountEnvelope = record(response.account);\n if (accountEnvelope && Object.hasOwn(accountEnvelope, 'account') && !record(accountEnvelope.account)) {\n result.authenticated = false;\n result.available = 'unknown';\n }\n return result;\n } catch {\n return unavailable(options);\n }\n}\n\nexport async function probeCodexCapacity(options: CodexProbeOptions): Promise<CapacityReport> {\n let parsed: UnknownRecord | null = null;\n try {\n const contents = await (options.readFile ?? readFile)(resolveCodexAuthPath(options.env), 'utf8');\n parsed = record(JSON.parse(contents));\n } catch {\n return cliFallback(options);\n }\n\n const auth = parsed ?? {};\n const pat = nonEmptyText(auth.personal_access_token);\n if (pat) {\n try {\n const fetcher = options.fetch ?? globalThis.fetch;\n const whoami = record(await fetchJson(fetcher,\n 'https://auth.openai.com/api/accounts/v1/user-auth-credential/whoami',\n { headers: { Authorization: `Bearer ${pat}` } }, options.timeoutMs ?? 5000));\n const accountId = nonEmptyText(whoami?.chatgpt_account_id);\n if (!accountId) throw new Error('account unavailable');\n return capacityFromSnapshot(await apiSnapshot(pat, accountId, 'pat', options), options);\n } catch {\n // Continue to a separately available OAuth credential before using the CLI.\n }\n }\n\n const tokens = record(auth.tokens);\n const accessToken = nonEmptyText(tokens?.access_token);\n const accountId = nonEmptyText(tokens?.account_id);\n if (tokens && accessToken && accountId && !staleOAuth(tokens, accessToken, (options.now ?? (() => new Date()))())) {\n try {\n return capacityFromSnapshot(await apiSnapshot(accessToken, accountId, 'oauth', options), options);\n } catch {\n return cliFallback(options);\n }\n }\n return cliFallback(options);\n}\n"],"names":["spawn","readFile","join","CODEX_APP_SERVER_ARGS","record","value","Array","isArray","finiteNumber","Number","isFinite","nonEmptyText","length","resetTime","seconds","Date","toISOString","isNaN","parse","safeIdentifier","candidate","test","resolveCodexAuthPath","env","process","root","CODEX_HOME","HOME","toRateWindow","id","label","input","used","used_percent","limit_window_seconds","durationMinutes","usedPercent","resetsAt","reset_at","extraWindows","flatMap","entry","index","limit","scope","limit_name","windows","rate_limit","primary_window","secondary_window","filter","window","parseUsage","raw","source","response","limits","credits","additional_rate_limits","creditsRemaining","balance","cliWindow","windowDurationMins","cliSnapshotWindows","fallbackId","snapshot","limitId","primary","secondary","item","parseCliUsage","rateLimits","buckets","rateLimitsByLimitId","Object","entries","push","unique","Map","map","values","capacityFromSnapshot","context","hasUsage","some","reached","rateLimitReachedType","resetCredits","rateLimitResetCredits","usageLimitResetCredits","provider","generatedAt","checkedAt","authenticated","available","availableCount","jwtExpiry","token","part","split","JSON","Buffer","from","toString","exp","staleOAuth","tokens","now","metadata","expires_at","expiresAt","expiry","parsed","getTime","fetchJson","fetcher","url","init","timeoutMs","controller","AbortController","timer","setTimeout","abort","signal","ok","Error","status","json","clearTimeout","apiSnapshot","accountId","options","fetch","globalThis","headers","Authorization","appServerRpc","messages","Promise","resolve","reject","child","stdio","results","buffer","settled","finish","error","kill","once","stdout","setEncoding","on","chunk","newline","indexOf","line","slice","trim","message","request","stdin","write","stringify","result","account","unavailable","cliFallback","installed","method","params","clientInfo","name","title","version","capabilities","rpc","requests","accountEnvelope","hasOwn","probeCodexCapacity","contents","auth","pat","personal_access_token","whoami","chatgpt_account_id","accessToken","access_token","account_id"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/capacity/codex.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { CapacityReport, CapacityWindow } from \"./types.js\";\n\ntype CodexUsageSource = \"pat\" | \"oauth\" | \"cli\";\ntype UsageSnapshot = {\n windows: CapacityWindow[];\n creditsRemaining: number | null;\n source: CodexUsageSource;\n};\n\ntype UnknownRecord = Record<string, unknown>;\ntype RpcMessage = { id?: number; method: string; params?: UnknownRecord };\ntype CliResponses = { rateLimits: unknown; account: unknown };\ntype CodexRpc = (messages: RpcMessage[]) => Promise<CliResponses>;\n\nexport const CODEX_APP_SERVER_ARGS = [\"-s\", \"read-only\", \"-a\", \"untrusted\", \"app-server\"] as const;\n\ntype CodexProbeOptions = {\n installed: boolean;\n checkedAt: string;\n readFile?: (path: string, encoding: BufferEncoding) => Promise<string>;\n fetch?: typeof globalThis.fetch;\n rpc?: CodexRpc;\n timeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n now?: () => Date;\n};\n\nfunction record(value: unknown): UnknownRecord | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as UnknownRecord)\n : null;\n}\n\nfunction finiteNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction nonEmptyText(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction resetTime(value: unknown): string | null {\n const seconds = finiteNumber(value);\n if (seconds !== null) return new Date(seconds * 1000).toISOString();\n if (typeof value === \"string\" && !Number.isNaN(Date.parse(value)))\n return new Date(value).toISOString();\n return null;\n}\n\nfunction safeIdentifier(value: unknown): string | null {\n const candidate = nonEmptyText(value);\n if (!candidate || !/^[a-z][a-z0-9_-]{0,63}$/i.test(candidate)) return null;\n if (/(?:account|token|secret|key)[_-]?\\d{6,}/i.test(candidate)) return null;\n return candidate;\n}\n\nexport function resolveCodexAuthPath(env: NodeJS.ProcessEnv = process.env): string {\n const root = env.CODEX_HOME || join(env.HOME || \"\", \".codex\");\n return join(root, \"auth.json\");\n}\n\nexport function toRateWindow(value: unknown, id: string, label: string): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n const used = finiteNumber(input.used_percent);\n const seconds = finiteNumber(input.limit_window_seconds);\n return {\n id,\n label,\n durationMinutes: seconds === null ? null : seconds / 60,\n usedPercent: used,\n resetsAt: resetTime(input.reset_at),\n };\n}\n\nfunction extraWindows(value: unknown): CapacityWindow[] {\n if (!Array.isArray(value)) return [];\n return value.flatMap((entry, index) => {\n const limit = record(entry);\n if (!limit) return [];\n const scope = safeIdentifier(limit.limit_name) ?? `extra-${index + 1}`;\n const windows = record(limit.rate_limit) ?? limit;\n return [\n toRateWindow(windows.primary_window, `${scope}:primary`, `${scope} primary`),\n toRateWindow(windows.secondary_window, `${scope}:secondary`, `${scope} secondary`),\n ].filter((window): window is CapacityWindow => window !== null);\n });\n}\n\nexport function parseUsage(raw: unknown, source: \"pat\" | \"oauth\"): UsageSnapshot {\n const response = record(raw) ?? {};\n const limits = record(response.rate_limit) ?? {};\n const credits = record(response.credits) ?? {};\n return {\n windows: [\n toRateWindow(limits.primary_window, \"session\", \"Session\"),\n toRateWindow(limits.secondary_window, \"weekly\", \"Weekly\"),\n ...extraWindows(response.additional_rate_limits),\n ].filter((window): window is CapacityWindow => window !== null),\n creditsRemaining: finiteNumber(credits.balance),\n source,\n };\n}\n\nfunction cliWindow(value: unknown, id: string, label: string): CapacityWindow | null {\n const input = record(value);\n if (!input) return null;\n return {\n id,\n label,\n durationMinutes: finiteNumber(input.windowDurationMins),\n usedPercent: finiteNumber(input.usedPercent),\n resetsAt: resetTime(input.resetsAt),\n };\n}\n\nfunction cliSnapshotWindows(value: unknown, fallbackId: string): CapacityWindow[] {\n const snapshot = record(value);\n if (!snapshot) return [];\n const scope = safeIdentifier(snapshot.limitId) ?? safeIdentifier(fallbackId) ?? \"codex\";\n return [\n cliWindow(snapshot.primary, `${scope}:primary`, `${scope} primary`),\n cliWindow(snapshot.secondary, `${scope}:secondary`, `${scope} secondary`),\n ].filter((item): item is CapacityWindow => item !== null);\n}\n\nexport function parseCliUsage(raw: unknown): UsageSnapshot {\n const response = record(raw) ?? {};\n const primary = record(response.rateLimits);\n const windows = primary ? cliSnapshotWindows(primary, \"codex\") : [];\n const buckets = record(response.rateLimitsByLimitId);\n if (buckets) {\n for (const [id, snapshot] of Object.entries(buckets))\n windows.push(...cliSnapshotWindows(snapshot, id));\n }\n const unique = [...new Map(windows.map((window) => [window.id, window])).values()];\n return { windows: unique, creditsRemaining: null, source: \"cli\" };\n}\n\nfunction capacityFromSnapshot(\n snapshot: UsageSnapshot,\n context: CodexProbeOptions,\n raw?: unknown,\n): CapacityReport {\n const hasUsage = snapshot.windows.some((window) => window.usedPercent !== null);\n const rateLimits = record(record(raw)?.rateLimits);\n const reached = nonEmptyText(rateLimits?.rateLimitReachedType);\n const resetCredits =\n record(record(raw)?.rateLimitResetCredits) ?? record(record(raw)?.usageLimitResetCredits);\n return {\n provider: \"codex\",\n generatedAt: context.checkedAt,\n authenticated: true,\n available: reached ? \"no\" : hasUsage ? \"yes\" : \"unknown\",\n windows: snapshot.windows,\n creditsRemaining: snapshot.creditsRemaining ?? finiteNumber(resetCredits?.availableCount),\n };\n}\n\nfunction jwtExpiry(token: string): number | null {\n const part = token.split(\".\")[1];\n if (!part) return null;\n try {\n return finiteNumber(record(JSON.parse(Buffer.from(part, \"base64url\").toString(\"utf8\")))?.exp);\n } catch {\n return null;\n }\n}\n\nfunction staleOAuth(tokens: UnknownRecord, token: string, now: Date): boolean {\n const metadata = tokens.expires_at ?? tokens.expiresAt ?? tokens.expiry;\n let expiry: number | null = finiteNumber(metadata);\n if (typeof metadata === \"string\") {\n const parsed = Date.parse(metadata);\n expiry = Number.isNaN(parsed) ? null : parsed / 1000;\n }\n expiry ??= jwtExpiry(token);\n return expiry !== null && expiry <= now.getTime() / 1000;\n}\n\nasync function fetchJson(\n fetcher: typeof globalThis.fetch,\n url: string,\n init: RequestInit,\n timeoutMs: number,\n): Promise<unknown> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetcher(url, { ...init, signal: controller.signal });\n if (!response.ok) throw new Error(response.status === 401 ? \"unauthorized\" : \"request failed\");\n return await response.json();\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function apiSnapshot(\n token: string,\n accountId: string,\n source: \"pat\" | \"oauth\",\n options: CodexProbeOptions,\n): Promise<UsageSnapshot> {\n const fetcher = options.fetch ?? globalThis.fetch;\n const raw = await fetchJson(\n fetcher,\n \"https://chatgpt.com/backend-api/wham/usage\",\n {\n headers: { Authorization: `Bearer ${token}`, \"ChatGPT-Account-Id\": accountId },\n },\n options.timeoutMs ?? 5000,\n );\n return parseUsage(raw, source);\n}\n\nfunction appServerRpc(messages: RpcMessage[], timeoutMs = 5000): Promise<CliResponses> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"codex\", CODEX_APP_SERVER_ARGS, {\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const results: Partial<CliResponses> = {};\n let buffer = \"\";\n let settled = false;\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n child.kill();\n if (error) reject(error);\n else resolve(results as CliResponses);\n };\n const timer = setTimeout(() => finish(new Error(\"codex probe timed out\")), timeoutMs);\n child.once(\"error\", () => finish(new Error(\"codex app-server unavailable\")));\n child.once(\"exit\", () => {\n if (!settled) finish(new Error(\"codex app-server exited\"));\n });\n child.stdout.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n buffer += chunk;\n for (;;) {\n const newline = buffer.indexOf(\"\\n\");\n if (newline < 0) break;\n const line = buffer.slice(0, newline).trim();\n buffer = buffer.slice(newline + 1);\n if (!line) continue;\n let message: UnknownRecord;\n try {\n message = JSON.parse(line) as UnknownRecord;\n } catch {\n continue;\n }\n if (message.id === 1) {\n for (const request of messages.slice(1))\n child.stdin.write(`${JSON.stringify(request)}\\n`);\n } else if (message.id === 2) {\n if (message.error) finish(new Error(\"codex rate-limit method failed\"));\n else results.rateLimits = message.result;\n } else if (message.id === 3) {\n if (message.error) finish(new Error(\"codex account method failed\"));\n else results.account = message.result;\n }\n if (\"rateLimits\" in results && \"account\" in results) finish();\n }\n });\n child.stdin.write(`${JSON.stringify(messages[0])}\\n`);\n });\n}\n\nfunction unavailable(options: CodexProbeOptions): CapacityReport {\n return {\n provider: \"codex\",\n generatedAt: options.checkedAt,\n authenticated: null,\n available: \"unknown\",\n windows: [],\n creditsRemaining: null,\n };\n}\n\nasync function cliFallback(options: CodexProbeOptions): Promise<CapacityReport> {\n if (!options.installed) return unavailable(options);\n const messages: RpcMessage[] = [\n {\n id: 1,\n method: \"initialize\",\n params: {\n clientInfo: { name: \"ai-devkit\", title: null, version: \"1\" },\n capabilities: null,\n },\n },\n { method: \"initialized\" },\n { id: 2, method: \"account/rateLimits/read\" },\n { id: 3, method: \"account/read\" },\n ];\n try {\n const rpc = options.rpc ?? ((requests) => appServerRpc(requests, options.timeoutMs));\n const response = await rpc(messages);\n const result = capacityFromSnapshot(\n parseCliUsage(response.rateLimits),\n options,\n response.rateLimits,\n );\n const accountEnvelope = record(response.account);\n if (\n accountEnvelope &&\n Object.hasOwn(accountEnvelope, \"account\") &&\n !record(accountEnvelope.account)\n ) {\n result.authenticated = false;\n result.available = \"unknown\";\n }\n return result;\n } catch {\n return unavailable(options);\n }\n}\n\nexport async function probeCodexCapacity(options: CodexProbeOptions): Promise<CapacityReport> {\n let parsed: UnknownRecord | null = null;\n try {\n const contents = await (options.readFile ?? readFile)(\n resolveCodexAuthPath(options.env),\n \"utf8\",\n );\n parsed = record(JSON.parse(contents));\n } catch {\n return cliFallback(options);\n }\n\n const auth = parsed ?? {};\n const pat = nonEmptyText(auth.personal_access_token);\n if (pat) {\n try {\n const fetcher = options.fetch ?? globalThis.fetch;\n const whoami = record(\n await fetchJson(\n fetcher,\n \"https://auth.openai.com/api/accounts/v1/user-auth-credential/whoami\",\n { headers: { Authorization: `Bearer ${pat}` } },\n options.timeoutMs ?? 5000,\n ),\n );\n const accountId = nonEmptyText(whoami?.chatgpt_account_id);\n if (!accountId) throw new Error(\"account unavailable\");\n return capacityFromSnapshot(await apiSnapshot(pat, accountId, \"pat\", options), options);\n } catch {\n // Continue to a separately available OAuth credential before using the CLI.\n }\n }\n\n const tokens = record(auth.tokens);\n const accessToken = nonEmptyText(tokens?.access_token);\n const accountId = nonEmptyText(tokens?.account_id);\n if (\n tokens &&\n accessToken &&\n accountId &&\n !staleOAuth(tokens, accessToken, (options.now ?? (() => new Date()))())\n ) {\n try {\n return capacityFromSnapshot(\n await apiSnapshot(accessToken, accountId, \"oauth\", options),\n options,\n );\n } catch {\n return cliFallback(options);\n }\n }\n return cliFallback(options);\n}\n"],"names":["spawn","readFile","join","CODEX_APP_SERVER_ARGS","record","value","Array","isArray","finiteNumber","Number","isFinite","nonEmptyText","length","resetTime","seconds","Date","toISOString","isNaN","parse","safeIdentifier","candidate","test","resolveCodexAuthPath","env","process","root","CODEX_HOME","HOME","toRateWindow","id","label","input","used","used_percent","limit_window_seconds","durationMinutes","usedPercent","resetsAt","reset_at","extraWindows","flatMap","entry","index","limit","scope","limit_name","windows","rate_limit","primary_window","secondary_window","filter","window","parseUsage","raw","source","response","limits","credits","additional_rate_limits","creditsRemaining","balance","cliWindow","windowDurationMins","cliSnapshotWindows","fallbackId","snapshot","limitId","primary","secondary","item","parseCliUsage","rateLimits","buckets","rateLimitsByLimitId","Object","entries","push","unique","Map","map","values","capacityFromSnapshot","context","hasUsage","some","reached","rateLimitReachedType","resetCredits","rateLimitResetCredits","usageLimitResetCredits","provider","generatedAt","checkedAt","authenticated","available","availableCount","jwtExpiry","token","part","split","JSON","Buffer","from","toString","exp","staleOAuth","tokens","now","metadata","expires_at","expiresAt","expiry","parsed","getTime","fetchJson","fetcher","url","init","timeoutMs","controller","AbortController","timer","setTimeout","abort","signal","ok","Error","status","json","clearTimeout","apiSnapshot","accountId","options","fetch","globalThis","headers","Authorization","appServerRpc","messages","Promise","resolve","reject","child","stdio","results","buffer","settled","finish","error","kill","once","stdout","setEncoding","on","chunk","newline","indexOf","line","slice","trim","message","request","stdin","write","stringify","result","account","unavailable","cliFallback","installed","method","params","clientInfo","name","title","version","capabilities","rpc","requests","accountEnvelope","hasOwn","probeCodexCapacity","contents","auth","pat","personal_access_token","whoami","chatgpt_account_id","accessToken","access_token","account_id"],"mappings":"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"}
|
package/dist/capacity/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { probeCodexCapacity } from
|
|
2
|
-
import type { CapacityReport } from
|
|
3
|
-
export type { CapacityReport, CapacityWindow } from
|
|
1
|
+
import { probeCodexCapacity } from "./codex.js";
|
|
2
|
+
import type { CapacityReport } from "./types.js";
|
|
3
|
+
export type { CapacityReport, CapacityWindow } from "./types.js";
|
|
4
4
|
export type CapacityProbeOptions = {
|
|
5
5
|
now?: () => Date;
|
|
6
6
|
path?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capacity/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,kBAAkB,CAAC;CACnC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capacity/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,OAAO,kBAAkB,CAAC;CACnC,CAAC;AA+BF,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,cAAc,CAAC,CAezB"}
|
package/dist/capacity/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { constants } from
|
|
2
|
-
import { access as fsAccess } from
|
|
3
|
-
import path from
|
|
4
|
-
import { probeCodexCapacity } from
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access as fsAccess } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { probeCodexCapacity } from "./codex.js";
|
|
5
5
|
async function canAccess(target, mode) {
|
|
6
6
|
try {
|
|
7
7
|
await fsAccess(target, mode);
|
|
@@ -13,7 +13,7 @@ async function canAccess(target, mode) {
|
|
|
13
13
|
async function isCodexInstalled(pathValue, checkAccess) {
|
|
14
14
|
const directories = pathValue.split(path.delimiter).filter(Boolean);
|
|
15
15
|
for (const directory of directories){
|
|
16
|
-
const executable = path.join(directory,
|
|
16
|
+
const executable = path.join(directory, "codex");
|
|
17
17
|
if (checkAccess) {
|
|
18
18
|
try {
|
|
19
19
|
await checkAccess(executable);
|
|
@@ -28,7 +28,7 @@ async function isCodexInstalled(pathValue, checkAccess) {
|
|
|
28
28
|
}
|
|
29
29
|
export async function getCodexCapacityReport(options = {}) {
|
|
30
30
|
const generatedAt = (options.now?.() ?? new Date()).toISOString();
|
|
31
|
-
const installed = await isCodexInstalled(options.path ?? process.env.PATH ??
|
|
31
|
+
const installed = await isCodexInstalled(options.path ?? process.env.PATH ?? "", options.access);
|
|
32
32
|
try {
|
|
33
33
|
return await (options.probe ?? probeCodexCapacity)({
|
|
34
34
|
installed,
|
|
@@ -36,10 +36,10 @@ export async function getCodexCapacityReport(options = {}) {
|
|
|
36
36
|
});
|
|
37
37
|
} catch {
|
|
38
38
|
return {
|
|
39
|
-
provider:
|
|
39
|
+
provider: "codex",
|
|
40
40
|
generatedAt,
|
|
41
41
|
authenticated: null,
|
|
42
|
-
available:
|
|
42
|
+
available: "unknown",
|
|
43
43
|
windows: [],
|
|
44
44
|
creditsRemaining: null
|
|
45
45
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/capacity/index.ts"],"sourcesContent":["import { constants } from
|
|
1
|
+
{"version":3,"sources":["../../src/capacity/index.ts"],"sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { probeCodexCapacity } from \"./codex.js\";\nimport type { CapacityReport } from \"./types.js\";\n\nexport type { CapacityReport, CapacityWindow } from \"./types.js\";\n\nexport type CapacityProbeOptions = {\n now?: () => Date;\n path?: string;\n access?: (target: string) => Promise<void>;\n probe?: typeof probeCodexCapacity;\n};\n\nasync function canAccess(target: string, mode: number): Promise<boolean> {\n try {\n await fsAccess(target, mode);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isCodexInstalled(\n pathValue: string,\n checkAccess?: (target: string) => Promise<void>,\n): Promise<boolean> {\n const directories = pathValue.split(path.delimiter).filter(Boolean);\n for (const directory of directories) {\n const executable = path.join(directory, \"codex\");\n if (checkAccess) {\n try {\n await checkAccess(executable);\n return true;\n } catch {\n continue;\n }\n }\n if (await canAccess(executable, constants.X_OK)) return true;\n }\n return false;\n}\n\nexport async function getCodexCapacityReport(\n options: CapacityProbeOptions = {},\n): Promise<CapacityReport> {\n const generatedAt = (options.now?.() ?? new Date()).toISOString();\n const installed = await isCodexInstalled(options.path ?? process.env.PATH ?? \"\", options.access);\n try {\n return await (options.probe ?? probeCodexCapacity)({ installed, checkedAt: generatedAt });\n } catch {\n return {\n provider: \"codex\",\n generatedAt,\n authenticated: null,\n available: \"unknown\",\n windows: [],\n creditsRemaining: null,\n };\n }\n}\n"],"names":["constants","access","fsAccess","path","probeCodexCapacity","canAccess","target","mode","isCodexInstalled","pathValue","checkAccess","directories","split","delimiter","filter","Boolean","directory","executable","join","X_OK","getCodexCapacityReport","options","generatedAt","now","Date","toISOString","installed","process","env","PATH","probe","checkedAt","provider","authenticated","available","windows","creditsRemaining"],"mappings":"AAAA,SAASA,SAAS,QAAQ,UAAU;AACpC,SAASC,UAAUC,QAAQ,QAAQ,mBAAmB;AACtD,OAAOC,UAAU,YAAY;AAC7B,SAASC,kBAAkB,QAAQ,aAAa;AAYhD,eAAeC,UAAUC,MAAc,EAAEC,IAAY;IACnD,IAAI;QACF,MAAML,SAASI,QAAQC;QACvB,OAAO;IACT,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAEA,eAAeC,iBACbC,SAAiB,EACjBC,WAA+C;IAE/C,MAAMC,cAAcF,UAAUG,KAAK,CAACT,KAAKU,SAAS,EAAEC,MAAM,CAACC;IAC3D,KAAK,MAAMC,aAAaL,YAAa;QACnC,MAAMM,aAAad,KAAKe,IAAI,CAACF,WAAW;QACxC,IAAIN,aAAa;YACf,IAAI;gBACF,MAAMA,YAAYO;gBAClB,OAAO;YACT,EAAE,OAAM;gBACN;YACF;QACF;QACA,IAAI,MAAMZ,UAAUY,YAAYjB,UAAUmB,IAAI,GAAG,OAAO;IAC1D;IACA,OAAO;AACT;AAEA,OAAO,eAAeC,uBACpBC,UAAgC,CAAC,CAAC;IAElC,MAAMC,cAAc,AAACD,CAAAA,QAAQE,GAAG,QAAQ,IAAIC,MAAK,EAAGC,WAAW;IAC/D,MAAMC,YAAY,MAAMlB,iBAAiBa,QAAQlB,IAAI,IAAIwB,QAAQC,GAAG,CAACC,IAAI,IAAI,IAAIR,QAAQpB,MAAM;IAC/F,IAAI;QACF,OAAO,MAAM,AAACoB,CAAAA,QAAQS,KAAK,IAAI1B,kBAAiB,EAAG;YAAEsB;YAAWK,WAAWT;QAAY;IACzF,EAAE,OAAM;QACN,OAAO;YACLU,UAAU;YACVV;YACAW,eAAe;YACfC,WAAW;YACXC,SAAS,EAAE;YACXC,kBAAkB;QACpB;IACF;AACF"}
|
package/dist/capacity/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/capacity/types.ts"],"sourcesContent":["export type Availability =
|
|
1
|
+
{"version":3,"sources":["../../src/capacity/types.ts"],"sourcesContent":["export type Availability = \"yes\" | \"no\" | \"unknown\";\n\nexport interface CapacityWindow {\n id: string;\n label: string;\n durationMinutes: number | null;\n usedPercent: number | null;\n resetsAt: string | null;\n}\n\nexport interface CapacityReport {\n provider: string;\n generatedAt: string;\n authenticated: boolean | null;\n available: Availability;\n windows: CapacityWindow[];\n creditsRemaining: number | null;\n}\n"],"names":[],"mappings":"AAUA,WAOC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/database/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAMtC,eAAO,MAAM,8BAA8B,QAA6C,CAAC;AAEzF,MAAM,WAAW,eAAe;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/database/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAMtC,eAAO,MAAM,8BAA8B,QAA6C,CAAC;AAEzF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGpE;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;gBAEvB,OAAO,GAAE,eAAoB;IAiCzC,OAAO,CAAC,SAAS;IASjB,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAEhC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,CAAC,EAAE;IAIlD,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,CAAC,GAAG,SAAS;IAI/D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,QAAQ,CAAC,SAAS;IAIhE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAI9B,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import Database from
|
|
2
|
-
import { existsSync, mkdirSync } from
|
|
3
|
-
import { dirname, join } from
|
|
4
|
-
import { homedir } from
|
|
5
|
-
import { initializeSchema } from
|
|
6
|
-
export const DEFAULT_AGENT_REGISTRY_DB_PATH = join(homedir(),
|
|
1
|
+
import Database from "better-sqlite3";
|
|
2
|
+
import { existsSync, mkdirSync } from "fs";
|
|
3
|
+
import { dirname, join } from "path";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { initializeSchema } from "./schema.js";
|
|
6
|
+
export const DEFAULT_AGENT_REGISTRY_DB_PATH = join(homedir(), ".ai-devkit", "agents.db");
|
|
7
7
|
export function resolveAgentRegistryDbPath(filePath) {
|
|
8
8
|
if (!filePath) return DEFAULT_AGENT_REGISTRY_DB_PATH;
|
|
9
|
-
return filePath.endsWith(
|
|
9
|
+
return filePath.endsWith(".json") ? filePath.replace(/\.json$/, ".db") : filePath;
|
|
10
10
|
}
|
|
11
11
|
export class DatabaseConnection {
|
|
12
12
|
db;
|
|
@@ -24,10 +24,10 @@ export class DatabaseConnection {
|
|
|
24
24
|
this.db = new Database(this.dbPath, {
|
|
25
25
|
readonly: this.readonly,
|
|
26
26
|
timeout: 5000,
|
|
27
|
-
verbose: typeof options.verbose ===
|
|
27
|
+
verbose: typeof options.verbose === "function" ? options.verbose : options.verbose ? console.log : undefined
|
|
28
28
|
});
|
|
29
29
|
if (this.readonly) {
|
|
30
|
-
const version = this.db.pragma(
|
|
30
|
+
const version = this.db.pragma("user_version", {
|
|
31
31
|
simple: true
|
|
32
32
|
});
|
|
33
33
|
if (version < 3) {
|
|
@@ -40,14 +40,14 @@ export class DatabaseConnection {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
configure() {
|
|
43
|
-
const journalMode = this.db.pragma(
|
|
43
|
+
const journalMode = this.db.pragma("journal_mode", {
|
|
44
44
|
simple: true
|
|
45
45
|
});
|
|
46
|
-
if (journalMode.toLowerCase() !==
|
|
47
|
-
this.db.pragma(
|
|
48
|
-
this.db.pragma(
|
|
49
|
-
this.db.pragma(
|
|
50
|
-
this.db.pragma(
|
|
46
|
+
if (journalMode.toLowerCase() !== "wal") this.db.pragma("journal_mode = WAL");
|
|
47
|
+
this.db.pragma("foreign_keys = ON");
|
|
48
|
+
this.db.pragma("synchronous = NORMAL");
|
|
49
|
+
this.db.pragma("busy_timeout = 5000");
|
|
50
|
+
this.db.pragma("mmap_size = 268435456");
|
|
51
51
|
}
|
|
52
52
|
get instance() {
|
|
53
53
|
return this.db;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/database/connection.ts"],"sourcesContent":["import Database from
|
|
1
|
+
{"version":3,"sources":["../../src/database/connection.ts"],"sourcesContent":["import Database from \"better-sqlite3\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { homedir } from \"os\";\nimport { initializeSchema } from \"./schema.js\";\n\nexport const DEFAULT_AGENT_REGISTRY_DB_PATH = join(homedir(), \".ai-devkit\", \"agents.db\");\n\nexport interface DatabaseOptions {\n dbPath?: string;\n verbose?: boolean | ((message: string) => void);\n readonly?: boolean;\n}\n\nexport function resolveAgentRegistryDbPath(filePath?: string): string {\n if (!filePath) return DEFAULT_AGENT_REGISTRY_DB_PATH;\n return filePath.endsWith(\".json\") ? filePath.replace(/\\.json$/, \".db\") : filePath;\n}\n\nexport class DatabaseConnection {\n private db: Database.Database;\n private readonly dbPath: string;\n private readonly readonly: boolean;\n\n constructor(options: DatabaseOptions = {}) {\n this.dbPath = options.dbPath ?? DEFAULT_AGENT_REGISTRY_DB_PATH;\n this.readonly = options.readonly ?? false;\n if (this.readonly && !existsSync(this.dbPath)) {\n throw new Error(\n `Cannot open readonly agent database because it does not exist: ${this.dbPath}`,\n );\n }\n if (!this.readonly) mkdirSync(dirname(this.dbPath), { recursive: true });\n\n this.db = new Database(this.dbPath, {\n readonly: this.readonly,\n timeout: 5000,\n verbose:\n typeof options.verbose === \"function\"\n ? options.verbose\n : options.verbose\n ? console.log\n : undefined,\n });\n\n if (this.readonly) {\n const version = this.db.pragma(\"user_version\", { simple: true }) as number;\n if (version < 3) {\n this.db.close();\n throw new Error(`Readonly agent database requires schema version 3 (found ${version}).`);\n }\n } else {\n this.configure();\n initializeSchema(this);\n }\n }\n\n private configure(): void {\n const journalMode = this.db.pragma(\"journal_mode\", { simple: true }) as string;\n if (journalMode.toLowerCase() !== \"wal\") this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"foreign_keys = ON\");\n this.db.pragma(\"synchronous = NORMAL\");\n this.db.pragma(\"busy_timeout = 5000\");\n this.db.pragma(\"mmap_size = 268435456\");\n }\n\n get instance(): Database.Database {\n return this.db;\n }\n\n get path(): string {\n return this.dbPath;\n }\n\n query<T>(sql: string, params: unknown[] = []): T[] {\n return this.db.prepare(sql).all(...params) as T[];\n }\n\n queryOne<T>(sql: string, params: unknown[] = []): T | undefined {\n return this.db.prepare(sql).get(...params) as T | undefined;\n }\n\n execute(sql: string, params: unknown[] = []): Database.RunResult {\n return this.db.prepare(sql).run(...params);\n }\n\n transaction<T>(fn: () => T): T {\n return this.db.transaction(fn)();\n }\n\n close(): void {\n if (this.db.open) {\n this.db.close();\n }\n }\n}\n"],"names":["Database","existsSync","mkdirSync","dirname","join","homedir","initializeSchema","DEFAULT_AGENT_REGISTRY_DB_PATH","resolveAgentRegistryDbPath","filePath","endsWith","replace","DatabaseConnection","db","dbPath","readonly","options","Error","recursive","timeout","verbose","console","log","undefined","version","pragma","simple","close","configure","journalMode","toLowerCase","instance","path","query","sql","params","prepare","all","queryOne","get","execute","run","transaction","fn","open"],"mappings":"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"}
|