@jait/gateway 0.1.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/bin/jait.mjs +144 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +73 -0
- package/dist/config.js.map +1 -0
- package/dist/db/connection.d.ts +37 -0
- package/dist/db/connection.d.ts.map +1 -0
- package/dist/db/connection.js +85 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/index.d.ts +4 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +4 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +24 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +312 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/schema.d.ts +2253 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +195 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/foundation.d.ts +26 -0
- package/dist/foundation.d.ts.map +1 -0
- package/dist/foundation.js +15 -0
- package/dist/foundation.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +413 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/uuidv7.d.ts +10 -0
- package/dist/lib/uuidv7.d.ts.map +1 -0
- package/dist/lib/uuidv7.js +33 -0
- package/dist/lib/uuidv7.js.map +1 -0
- package/dist/memory/contracts.d.ts +42 -0
- package/dist/memory/contracts.d.ts.map +1 -0
- package/dist/memory/contracts.js +2 -0
- package/dist/memory/contracts.js.map +1 -0
- package/dist/memory/embeddings.d.ts +4 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +26 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/service.d.ts +17 -0
- package/dist/memory/service.d.ts.map +1 -0
- package/dist/memory/service.js +82 -0
- package/dist/memory/service.js.map +1 -0
- package/dist/memory/sqlite-backend.d.ts +11 -0
- package/dist/memory/sqlite-backend.d.ts.map +1 -0
- package/dist/memory/sqlite-backend.js +68 -0
- package/dist/memory/sqlite-backend.js.map +1 -0
- package/dist/plugins/contracts.d.ts +11 -0
- package/dist/plugins/contracts.d.ts.map +1 -0
- package/dist/plugins/contracts.js +2 -0
- package/dist/plugins/contracts.js.map +1 -0
- package/dist/providers/claude-code-provider.d.ts +39 -0
- package/dist/providers/claude-code-provider.d.ts.map +1 -0
- package/dist/providers/claude-code-provider.js +322 -0
- package/dist/providers/claude-code-provider.js.map +1 -0
- package/dist/providers/codex-provider.d.ts +51 -0
- package/dist/providers/codex-provider.d.ts.map +1 -0
- package/dist/providers/codex-provider.js +826 -0
- package/dist/providers/codex-provider.js.map +1 -0
- package/dist/providers/contracts.d.ts +167 -0
- package/dist/providers/contracts.d.ts.map +1 -0
- package/dist/providers/contracts.js +13 -0
- package/dist/providers/contracts.js.map +1 -0
- package/dist/providers/index.d.ts +6 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +5 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/jait-provider.d.ts +23 -0
- package/dist/providers/jait-provider.d.ts.map +1 -0
- package/dist/providers/jait-provider.js +67 -0
- package/dist/providers/jait-provider.js.map +1 -0
- package/dist/providers/registry.d.ts +39 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +64 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/pty-broker-client.d.ts +46 -0
- package/dist/pty-broker-client.d.ts.map +1 -0
- package/dist/pty-broker-client.js +142 -0
- package/dist/pty-broker-client.js.map +1 -0
- package/dist/routes/auth.d.ts +6 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +236 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/chat.d.ts +32 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +1503 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/consent.d.ts +10 -0
- package/dist/routes/consent.d.ts.map +1 -0
- package/dist/routes/consent.js +127 -0
- package/dist/routes/consent.js.map +1 -0
- package/dist/routes/filesystem.d.ts +14 -0
- package/dist/routes/filesystem.d.ts.map +1 -0
- package/dist/routes/filesystem.js +152 -0
- package/dist/routes/filesystem.js.map +1 -0
- package/dist/routes/git.d.ts +17 -0
- package/dist/routes/git.d.ts.map +1 -0
- package/dist/routes/git.js +213 -0
- package/dist/routes/git.js.map +1 -0
- package/dist/routes/health.d.ts +7 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +21 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/hooks.d.ts +9 -0
- package/dist/routes/hooks.d.ts.map +1 -0
- package/dist/routes/hooks.js +22 -0
- package/dist/routes/hooks.js.map +1 -0
- package/dist/routes/jobs.d.ts +5 -0
- package/dist/routes/jobs.d.ts.map +1 -0
- package/dist/routes/jobs.js +333 -0
- package/dist/routes/jobs.js.map +1 -0
- package/dist/routes/mcp-server.d.ts +23 -0
- package/dist/routes/mcp-server.d.ts.map +1 -0
- package/dist/routes/mcp-server.js +177 -0
- package/dist/routes/mcp-server.js.map +1 -0
- package/dist/routes/mobile.d.ts +12 -0
- package/dist/routes/mobile.d.ts.map +1 -0
- package/dist/routes/mobile.js +64 -0
- package/dist/routes/mobile.js.map +1 -0
- package/dist/routes/network.d.ts +3 -0
- package/dist/routes/network.d.ts.map +1 -0
- package/dist/routes/network.js +367 -0
- package/dist/routes/network.js.map +1 -0
- package/dist/routes/repositories.d.ts +18 -0
- package/dist/routes/repositories.d.ts.map +1 -0
- package/dist/routes/repositories.js +90 -0
- package/dist/routes/repositories.js.map +1 -0
- package/dist/routes/screen-share.d.ts +17 -0
- package/dist/routes/screen-share.d.ts.map +1 -0
- package/dist/routes/screen-share.js +92 -0
- package/dist/routes/screen-share.js.map +1 -0
- package/dist/routes/sessions.d.ts +18 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +169 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/terminals.d.ts +15 -0
- package/dist/routes/terminals.d.ts.map +1 -0
- package/dist/routes/terminals.js +326 -0
- package/dist/routes/terminals.js.map +1 -0
- package/dist/routes/threads.d.ts +38 -0
- package/dist/routes/threads.d.ts.map +1 -0
- package/dist/routes/threads.js +488 -0
- package/dist/routes/threads.js.map +1 -0
- package/dist/routes/trust.d.ts +9 -0
- package/dist/routes/trust.d.ts.map +1 -0
- package/dist/routes/trust.js +25 -0
- package/dist/routes/trust.js.map +1 -0
- package/dist/routes/voice.d.ts +5 -0
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +37 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/routes/workspace.d.ts +13 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +275 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/scheduler/contracts.d.ts +15 -0
- package/dist/scheduler/contracts.d.ts.map +1 -0
- package/dist/scheduler/contracts.js +2 -0
- package/dist/scheduler/contracts.js.map +1 -0
- package/dist/scheduler/hooks.d.ts +20 -0
- package/dist/scheduler/hooks.d.ts.map +1 -0
- package/dist/scheduler/hooks.js +78 -0
- package/dist/scheduler/hooks.js.map +1 -0
- package/dist/scheduler/service.d.ts +65 -0
- package/dist/scheduler/service.d.ts.map +1 -0
- package/dist/scheduler/service.js +188 -0
- package/dist/scheduler/service.js.map +1 -0
- package/dist/security/consent-executor.d.ts +48 -0
- package/dist/security/consent-executor.d.ts.map +1 -0
- package/dist/security/consent-executor.js +158 -0
- package/dist/security/consent-executor.js.map +1 -0
- package/dist/security/consent-manager.d.ts +105 -0
- package/dist/security/consent-manager.d.ts.map +1 -0
- package/dist/security/consent-manager.js +227 -0
- package/dist/security/consent-manager.js.map +1 -0
- package/dist/security/contracts.d.ts +31 -0
- package/dist/security/contracts.d.ts.map +1 -0
- package/dist/security/contracts.js +2 -0
- package/dist/security/contracts.js.map +1 -0
- package/dist/security/http-auth.d.ts +10 -0
- package/dist/security/http-auth.d.ts.map +1 -0
- package/dist/security/http-auth.js +48 -0
- package/dist/security/http-auth.js.map +1 -0
- package/dist/security/index.d.ts +10 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +9 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/path-guard.d.ts +40 -0
- package/dist/security/path-guard.d.ts.map +1 -0
- package/dist/security/path-guard.js +125 -0
- package/dist/security/path-guard.js.map +1 -0
- package/dist/security/sandbox-manager.d.ts +43 -0
- package/dist/security/sandbox-manager.d.ts.map +1 -0
- package/dist/security/sandbox-manager.js +110 -0
- package/dist/security/sandbox-manager.js.map +1 -0
- package/dist/security/ssrf-guard.d.ts +11 -0
- package/dist/security/ssrf-guard.d.ts.map +1 -0
- package/dist/security/ssrf-guard.js +59 -0
- package/dist/security/ssrf-guard.js.map +1 -0
- package/dist/security/tool-permissions.d.ts +61 -0
- package/dist/security/tool-permissions.d.ts.map +1 -0
- package/dist/security/tool-permissions.js +105 -0
- package/dist/security/tool-permissions.js.map +1 -0
- package/dist/security/tool-profiles.d.ts +23 -0
- package/dist/security/tool-profiles.d.ts.map +1 -0
- package/dist/security/tool-profiles.js +106 -0
- package/dist/security/tool-profiles.js.map +1 -0
- package/dist/security/trust-engine.d.ts +61 -0
- package/dist/security/trust-engine.d.ts.map +1 -0
- package/dist/security/trust-engine.js +192 -0
- package/dist/security/trust-engine.js.map +1 -0
- package/dist/server.d.ts +54 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +188 -0
- package/dist/server.js.map +1 -0
- package/dist/services/audit.d.ts +60 -0
- package/dist/services/audit.d.ts.map +1 -0
- package/dist/services/audit.js +58 -0
- package/dist/services/audit.js.map +1 -0
- package/dist/services/device-registry.d.ts +15 -0
- package/dist/services/device-registry.d.ts.map +1 -0
- package/dist/services/device-registry.js +32 -0
- package/dist/services/device-registry.js.map +1 -0
- package/dist/services/git.d.ts +168 -0
- package/dist/services/git.d.ts.map +1 -0
- package/dist/services/git.js +957 -0
- package/dist/services/git.js.map +1 -0
- package/dist/services/repositories.d.ts +32 -0
- package/dist/services/repositories.d.ts.map +1 -0
- package/dist/services/repositories.js +70 -0
- package/dist/services/repositories.js.map +1 -0
- package/dist/services/session-state.d.ts +20 -0
- package/dist/services/session-state.d.ts.map +1 -0
- package/dist/services/session-state.js +89 -0
- package/dist/services/session-state.js.map +1 -0
- package/dist/services/sessions.d.ts +68 -0
- package/dist/services/sessions.d.ts.map +1 -0
- package/dist/services/sessions.js +136 -0
- package/dist/services/sessions.js.map +1 -0
- package/dist/services/thread-title.d.ts +23 -0
- package/dist/services/thread-title.d.ts.map +1 -0
- package/dist/services/thread-title.js +141 -0
- package/dist/services/thread-title.js.map +1 -0
- package/dist/services/threads.d.ts +64 -0
- package/dist/services/threads.d.ts.map +1 -0
- package/dist/services/threads.js +202 -0
- package/dist/services/threads.js.map +1 -0
- package/dist/services/users.d.ts +39 -0
- package/dist/services/users.d.ts.map +1 -0
- package/dist/services/users.js +203 -0
- package/dist/services/users.js.map +1 -0
- package/dist/sessions/contracts.d.ts +14 -0
- package/dist/sessions/contracts.d.ts.map +1 -0
- package/dist/sessions/contracts.js +2 -0
- package/dist/sessions/contracts.js.map +1 -0
- package/dist/surfaces/browser.d.ts +65 -0
- package/dist/surfaces/browser.d.ts.map +1 -0
- package/dist/surfaces/browser.js +615 -0
- package/dist/surfaces/browser.js.map +1 -0
- package/dist/surfaces/contracts.d.ts +34 -0
- package/dist/surfaces/contracts.d.ts.map +1 -0
- package/dist/surfaces/contracts.js +2 -0
- package/dist/surfaces/contracts.js.map +1 -0
- package/dist/surfaces/filesystem.d.ts +76 -0
- package/dist/surfaces/filesystem.d.ts.map +1 -0
- package/dist/surfaces/filesystem.js +245 -0
- package/dist/surfaces/filesystem.js.map +1 -0
- package/dist/surfaces/index.d.ts +6 -0
- package/dist/surfaces/index.d.ts.map +1 -0
- package/dist/surfaces/index.js +5 -0
- package/dist/surfaces/index.js.map +1 -0
- package/dist/surfaces/registry.d.ts +24 -0
- package/dist/surfaces/registry.d.ts.map +1 -0
- package/dist/surfaces/registry.js +59 -0
- package/dist/surfaces/registry.js.map +1 -0
- package/dist/surfaces/terminal.d.ts +76 -0
- package/dist/surfaces/terminal.d.ts.map +1 -0
- package/dist/surfaces/terminal.js +271 -0
- package/dist/surfaces/terminal.js.map +1 -0
- package/dist/tools/agent-loop.d.ts +302 -0
- package/dist/tools/agent-loop.d.ts.map +1 -0
- package/dist/tools/agent-loop.js +918 -0
- package/dist/tools/agent-loop.js.map +1 -0
- package/dist/tools/agent-tools.d.ts +39 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +263 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/browser-tools.d.ts +38 -0
- package/dist/tools/browser-tools.d.ts.map +1 -0
- package/dist/tools/browser-tools.js +725 -0
- package/dist/tools/browser-tools.js.map +1 -0
- package/dist/tools/chat-modes.d.ts +75 -0
- package/dist/tools/chat-modes.d.ts.map +1 -0
- package/dist/tools/chat-modes.js +228 -0
- package/dist/tools/chat-modes.js.map +1 -0
- package/dist/tools/contracts.d.ts +69 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +2 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/core/agent.d.ts +31 -0
- package/dist/tools/core/agent.d.ts.map +1 -0
- package/dist/tools/core/agent.js +65 -0
- package/dist/tools/core/agent.js.map +1 -0
- package/dist/tools/core/edit.d.ts +30 -0
- package/dist/tools/core/edit.d.ts.map +1 -0
- package/dist/tools/core/edit.js +109 -0
- package/dist/tools/core/edit.js.map +1 -0
- package/dist/tools/core/execute.d.ts +36 -0
- package/dist/tools/core/execute.d.ts.map +1 -0
- package/dist/tools/core/execute.js +81 -0
- package/dist/tools/core/execute.js.map +1 -0
- package/dist/tools/core/get-fs.d.ts +32 -0
- package/dist/tools/core/get-fs.d.ts.map +1 -0
- package/dist/tools/core/get-fs.js +143 -0
- package/dist/tools/core/get-fs.js.map +1 -0
- package/dist/tools/core/index.d.ts +26 -0
- package/dist/tools/core/index.d.ts.map +1 -0
- package/dist/tools/core/index.js +26 -0
- package/dist/tools/core/index.js.map +1 -0
- package/dist/tools/core/jait.d.ts +60 -0
- package/dist/tools/core/jait.d.ts.map +1 -0
- package/dist/tools/core/jait.js +256 -0
- package/dist/tools/core/jait.js.map +1 -0
- package/dist/tools/core/read.d.ts +26 -0
- package/dist/tools/core/read.d.ts.map +1 -0
- package/dist/tools/core/read.js +118 -0
- package/dist/tools/core/read.js.map +1 -0
- package/dist/tools/core/search.d.ts +34 -0
- package/dist/tools/core/search.d.ts.map +1 -0
- package/dist/tools/core/search.js +187 -0
- package/dist/tools/core/search.js.map +1 -0
- package/dist/tools/core/todo.d.ts +38 -0
- package/dist/tools/core/todo.d.ts.map +1 -0
- package/dist/tools/core/todo.js +116 -0
- package/dist/tools/core/todo.js.map +1 -0
- package/dist/tools/core/web.d.ts +34 -0
- package/dist/tools/core/web.d.ts.map +1 -0
- package/dist/tools/core/web.js +120 -0
- package/dist/tools/core/web.js.map +1 -0
- package/dist/tools/cron-tools.d.ts +7 -0
- package/dist/tools/cron-tools.d.ts.map +1 -0
- package/dist/tools/cron-tools.js +116 -0
- package/dist/tools/cron-tools.js.map +1 -0
- package/dist/tools/file-tools.d.ts +32 -0
- package/dist/tools/file-tools.d.ts.map +1 -0
- package/dist/tools/file-tools.js +178 -0
- package/dist/tools/file-tools.js.map +1 -0
- package/dist/tools/gateway-tools.d.ts +15 -0
- package/dist/tools/gateway-tools.d.ts.map +1 -0
- package/dist/tools/gateway-tools.js +39 -0
- package/dist/tools/gateway-tools.js.map +1 -0
- package/dist/tools/index.d.ts +57 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +170 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/mcp-bridge.d.ts +111 -0
- package/dist/tools/mcp-bridge.d.ts.map +1 -0
- package/dist/tools/mcp-bridge.js +166 -0
- package/dist/tools/mcp-bridge.js.map +1 -0
- package/dist/tools/memory-tools.d.ts +19 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js +78 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/meta-tools.d.ts +25 -0
- package/dist/tools/meta-tools.d.ts.map +1 -0
- package/dist/tools/meta-tools.js +125 -0
- package/dist/tools/meta-tools.js.map +1 -0
- package/dist/tools/network-tools.d.ts +21 -0
- package/dist/tools/network-tools.d.ts.map +1 -0
- package/dist/tools/network-tools.js +189 -0
- package/dist/tools/network-tools.js.map +1 -0
- package/dist/tools/os-tools.d.ts +18 -0
- package/dist/tools/os-tools.d.ts.map +1 -0
- package/dist/tools/os-tools.js +210 -0
- package/dist/tools/os-tools.js.map +1 -0
- package/dist/tools/prompts/claude-prompt.d.ts +8 -0
- package/dist/tools/prompts/claude-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/claude-prompt.js +228 -0
- package/dist/tools/prompts/claude-prompt.js.map +1 -0
- package/dist/tools/prompts/default-openai-prompt.d.ts +8 -0
- package/dist/tools/prompts/default-openai-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/default-openai-prompt.js +67 -0
- package/dist/tools/prompts/default-openai-prompt.js.map +1 -0
- package/dist/tools/prompts/default-prompt.d.ts +7 -0
- package/dist/tools/prompts/default-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/default-prompt.js +50 -0
- package/dist/tools/prompts/default-prompt.js.map +1 -0
- package/dist/tools/prompts/gemini-prompt.d.ts +8 -0
- package/dist/tools/prompts/gemini-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/gemini-prompt.js +118 -0
- package/dist/tools/prompts/gemini-prompt.js.map +1 -0
- package/dist/tools/prompts/gpt5-codex-prompt.d.ts +8 -0
- package/dist/tools/prompts/gpt5-codex-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/gpt5-codex-prompt.js +72 -0
- package/dist/tools/prompts/gpt5-codex-prompt.js.map +1 -0
- package/dist/tools/prompts/gpt5-prompt.d.ts +8 -0
- package/dist/tools/prompts/gpt5-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/gpt5-prompt.js +177 -0
- package/dist/tools/prompts/gpt5-prompt.js.map +1 -0
- package/dist/tools/prompts/gpt51-prompt.d.ts +8 -0
- package/dist/tools/prompts/gpt51-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/gpt51-prompt.js +178 -0
- package/dist/tools/prompts/gpt51-prompt.js.map +1 -0
- package/dist/tools/prompts/gpt52-prompt.d.ts +8 -0
- package/dist/tools/prompts/gpt52-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/gpt52-prompt.js +198 -0
- package/dist/tools/prompts/gpt52-prompt.js.map +1 -0
- package/dist/tools/prompts/index.d.ts +22 -0
- package/dist/tools/prompts/index.d.ts.map +1 -0
- package/dist/tools/prompts/index.js +23 -0
- package/dist/tools/prompts/index.js.map +1 -0
- package/dist/tools/prompts/prompt-registry.d.ts +44 -0
- package/dist/tools/prompts/prompt-registry.d.ts.map +1 -0
- package/dist/tools/prompts/prompt-registry.js +60 -0
- package/dist/tools/prompts/prompt-registry.js.map +1 -0
- package/dist/tools/prompts/shared-sections.d.ts +28 -0
- package/dist/tools/prompts/shared-sections.d.ts.map +1 -0
- package/dist/tools/prompts/shared-sections.js +111 -0
- package/dist/tools/prompts/shared-sections.js.map +1 -0
- package/dist/tools/prompts/xai-prompt.d.ts +8 -0
- package/dist/tools/prompts/xai-prompt.d.ts.map +1 -0
- package/dist/tools/prompts/xai-prompt.js +68 -0
- package/dist/tools/prompts/xai-prompt.js.map +1 -0
- package/dist/tools/redeploy-tools.d.ts +30 -0
- package/dist/tools/redeploy-tools.d.ts.map +1 -0
- package/dist/tools/redeploy-tools.js +191 -0
- package/dist/tools/redeploy-tools.js.map +1 -0
- package/dist/tools/registry.d.ts +51 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +148 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/screen-share-tools.d.ts +31 -0
- package/dist/tools/screen-share-tools.d.ts.map +1 -0
- package/dist/tools/screen-share-tools.js +183 -0
- package/dist/tools/screen-share-tools.js.map +1 -0
- package/dist/tools/surface-tools.d.ts +23 -0
- package/dist/tools/surface-tools.d.ts.map +1 -0
- package/dist/tools/surface-tools.js +99 -0
- package/dist/tools/surface-tools.js.map +1 -0
- package/dist/tools/terminal-tools.d.ts +37 -0
- package/dist/tools/terminal-tools.d.ts.map +1 -0
- package/dist/tools/terminal-tools.js +448 -0
- package/dist/tools/terminal-tools.js.map +1 -0
- package/dist/tools/thread-tools.d.ts +61 -0
- package/dist/tools/thread-tools.d.ts.map +1 -0
- package/dist/tools/thread-tools.js +484 -0
- package/dist/tools/thread-tools.js.map +1 -0
- package/dist/tools/token-estimator.d.ts +55 -0
- package/dist/tools/token-estimator.d.ts.map +1 -0
- package/dist/tools/token-estimator.js +82 -0
- package/dist/tools/token-estimator.js.map +1 -0
- package/dist/tools/tool-names.d.ts +64 -0
- package/dist/tools/tool-names.d.ts.map +1 -0
- package/dist/tools/tool-names.js +76 -0
- package/dist/tools/tool-names.js.map +1 -0
- package/dist/tools/validate.d.ts +27 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +99 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/tools/voice-tools.d.ts +8 -0
- package/dist/tools/voice-tools.d.ts.map +1 -0
- package/dist/tools/voice-tools.js +32 -0
- package/dist/tools/voice-tools.js.map +1 -0
- package/dist/voice/service.d.ts +42 -0
- package/dist/voice/service.d.ts.map +1 -0
- package/dist/voice/service.js +75 -0
- package/dist/voice/service.js.map +1 -0
- package/dist/ws.d.ts +90 -0
- package/dist/ws.d.ts.map +1 -0
- package/dist/ws.js +562 -0
- package/dist/ws.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,826 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI Provider — wraps OpenAI Codex CLI as a Jait provider.
|
|
3
|
+
*
|
|
4
|
+
* Spawns `codex app-server` as a child process and communicates
|
|
5
|
+
* via JSON-RPC 2.0 over NDJSON on stdin/stdout.
|
|
6
|
+
*
|
|
7
|
+
* Protocol (codex-cli ≥ 0.111.0):
|
|
8
|
+
* 1. spawn `codex app-server` with piped stdio
|
|
9
|
+
* 2. send `initialize` request → get response
|
|
10
|
+
* 3. send `initialized` notification (no response)
|
|
11
|
+
* 4. send `thread/start` request → get threadId
|
|
12
|
+
* 5. send `turn/start` request per user message
|
|
13
|
+
* 6. listen for notifications: item/agentMessage/delta, turn/completed, etc.
|
|
14
|
+
*/
|
|
15
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
16
|
+
import { EventEmitter } from "node:events";
|
|
17
|
+
import readline from "node:readline";
|
|
18
|
+
import { uuidv7 } from "../lib/uuidv7.js";
|
|
19
|
+
// ── Provider implementation ──────────────────────────────────────────
|
|
20
|
+
export class CodexProvider {
|
|
21
|
+
id = "codex";
|
|
22
|
+
info = {
|
|
23
|
+
id: "codex",
|
|
24
|
+
name: "OpenAI Codex",
|
|
25
|
+
description: "OpenAI Codex CLI agent with sandboxed execution and MCP support",
|
|
26
|
+
available: false,
|
|
27
|
+
modes: ["full-access", "supervised"],
|
|
28
|
+
};
|
|
29
|
+
sessions = new Map();
|
|
30
|
+
emitter = new EventEmitter();
|
|
31
|
+
codexPath = null;
|
|
32
|
+
async checkAvailability() {
|
|
33
|
+
try {
|
|
34
|
+
const paths = ["codex", "npx codex"];
|
|
35
|
+
for (const cmd of paths) {
|
|
36
|
+
const available = await this.testCommand(cmd);
|
|
37
|
+
if (available) {
|
|
38
|
+
this.codexPath = cmd;
|
|
39
|
+
this.info.available = true;
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
this.info.available = false;
|
|
44
|
+
this.info.unavailableReason = "Codex CLI not found. Install with: npm install -g @openai/codex";
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
this.info.available = false;
|
|
49
|
+
this.info.unavailableReason = "Failed to check Codex CLI availability";
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* List available models by spawning a short-lived `codex app-server`,
|
|
55
|
+
* performing the initialize handshake, then calling `model/list`.
|
|
56
|
+
*/
|
|
57
|
+
async listModels() {
|
|
58
|
+
const cmd = this.codexPath ?? "codex";
|
|
59
|
+
const child = spawn(cmd, ["app-server"], {
|
|
60
|
+
cwd: process.cwd(),
|
|
61
|
+
env: process.env,
|
|
62
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
63
|
+
shell: true,
|
|
64
|
+
});
|
|
65
|
+
const rl = readline.createInterface({ input: child.stdout });
|
|
66
|
+
const pending = new Map();
|
|
67
|
+
let nextId = 1;
|
|
68
|
+
const writeMsg = (msg) => {
|
|
69
|
+
if (child.stdin?.writable)
|
|
70
|
+
child.stdin.write(JSON.stringify(msg) + "\n");
|
|
71
|
+
};
|
|
72
|
+
const sendReq = (method, params, timeoutMs = 15_000) => {
|
|
73
|
+
const id = nextId++;
|
|
74
|
+
return new Promise((resolve, reject) => {
|
|
75
|
+
const timeout = setTimeout(() => {
|
|
76
|
+
pending.delete(String(id));
|
|
77
|
+
reject(new Error(`Timed out waiting for ${method}`));
|
|
78
|
+
}, timeoutMs);
|
|
79
|
+
pending.set(String(id), { method, timeout, resolve, reject });
|
|
80
|
+
writeMsg({ method, id, params });
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
// Listen for JSON-RPC responses
|
|
84
|
+
rl.on("line", (line) => {
|
|
85
|
+
try {
|
|
86
|
+
const msg = JSON.parse(line);
|
|
87
|
+
if (msg.id != null) {
|
|
88
|
+
const p = pending.get(String(msg.id));
|
|
89
|
+
if (p) {
|
|
90
|
+
pending.delete(String(msg.id));
|
|
91
|
+
clearTimeout(p.timeout);
|
|
92
|
+
if (msg.error) {
|
|
93
|
+
p.reject(new Error(msg.error.message ?? "RPC error"));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
p.resolve(msg.result);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch { /* ignore non-JSON lines */ }
|
|
102
|
+
});
|
|
103
|
+
try {
|
|
104
|
+
// Handshake
|
|
105
|
+
await sendReq("initialize", {
|
|
106
|
+
clientInfo: { name: "jait", title: "Jait Gateway", version: "1.0.0" },
|
|
107
|
+
capabilities: { experimentalApi: true },
|
|
108
|
+
});
|
|
109
|
+
writeMsg({ method: "initialized" });
|
|
110
|
+
// Fetch model list — response shape: { data: [{id, model, displayName, description, isDefault, ...}], nextCursor }
|
|
111
|
+
const result = await sendReq("model/list", {});
|
|
112
|
+
const models = [];
|
|
113
|
+
const items = result?.data ?? result?.models;
|
|
114
|
+
if (Array.isArray(items)) {
|
|
115
|
+
for (const m of items) {
|
|
116
|
+
const id = String(m.id ?? m.model ?? m.name ?? "");
|
|
117
|
+
const name = String(m.displayName ?? m.name ?? m.id ?? "");
|
|
118
|
+
if (!id)
|
|
119
|
+
continue;
|
|
120
|
+
models.push({
|
|
121
|
+
id,
|
|
122
|
+
name,
|
|
123
|
+
...(m.description ? { description: String(m.description) } : {}),
|
|
124
|
+
...(m.isDefault ? { isDefault: true } : {}),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return models;
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error("[codex] model/list failed:", err);
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
// Clean up
|
|
136
|
+
for (const p of pending.values()) {
|
|
137
|
+
clearTimeout(p.timeout);
|
|
138
|
+
p.reject(new Error("Session closed"));
|
|
139
|
+
}
|
|
140
|
+
pending.clear();
|
|
141
|
+
rl.close();
|
|
142
|
+
child.kill("SIGTERM");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async startSession(options) {
|
|
146
|
+
const sessionId = uuidv7();
|
|
147
|
+
const cmd = this.codexPath ?? "codex";
|
|
148
|
+
const child = spawn(cmd, ["app-server"], {
|
|
149
|
+
cwd: options.workingDirectory,
|
|
150
|
+
env: {
|
|
151
|
+
...process.env,
|
|
152
|
+
...options.env,
|
|
153
|
+
},
|
|
154
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
155
|
+
shell: true,
|
|
156
|
+
});
|
|
157
|
+
const rl = readline.createInterface({ input: child.stdout });
|
|
158
|
+
const session = {
|
|
159
|
+
id: sessionId,
|
|
160
|
+
providerId: "codex",
|
|
161
|
+
threadId: options.threadId,
|
|
162
|
+
status: "starting",
|
|
163
|
+
runtimeMode: options.mode,
|
|
164
|
+
startedAt: new Date().toISOString(),
|
|
165
|
+
};
|
|
166
|
+
const state = {
|
|
167
|
+
session,
|
|
168
|
+
child,
|
|
169
|
+
rl,
|
|
170
|
+
pending: new Map(),
|
|
171
|
+
nextId: 1,
|
|
172
|
+
providerThreadId: null,
|
|
173
|
+
stopping: false,
|
|
174
|
+
};
|
|
175
|
+
this.sessions.set(sessionId, state);
|
|
176
|
+
this.attachListeners(state);
|
|
177
|
+
try {
|
|
178
|
+
// ── Step 1: initialize handshake ──
|
|
179
|
+
await this.sendRequest(state, "initialize", {
|
|
180
|
+
clientInfo: { name: "jait", title: "Jait Gateway", version: "1.0.0" },
|
|
181
|
+
capabilities: { experimentalApi: true },
|
|
182
|
+
});
|
|
183
|
+
// ── Step 2: initialized notification (no response expected) ──
|
|
184
|
+
this.writeMessage(state, { method: "initialized" });
|
|
185
|
+
// ── Step 3: thread/start ──
|
|
186
|
+
const { approvalPolicy, sandbox } = mapRuntimeMode(options.mode);
|
|
187
|
+
const threadResponse = await this.sendRequest(state, "thread/start", {
|
|
188
|
+
model: options.model ?? null,
|
|
189
|
+
cwd: options.workingDirectory,
|
|
190
|
+
approvalPolicy,
|
|
191
|
+
sandbox,
|
|
192
|
+
experimentalRawEvents: false,
|
|
193
|
+
});
|
|
194
|
+
const providerThreadId = threadResponse?.thread?.id ?? threadResponse?.threadId;
|
|
195
|
+
if (!providerThreadId) {
|
|
196
|
+
throw new Error("thread/start response did not include a thread id");
|
|
197
|
+
}
|
|
198
|
+
state.providerThreadId = providerThreadId;
|
|
199
|
+
state.session.status = "running";
|
|
200
|
+
this.emit({ type: "session.started", sessionId });
|
|
201
|
+
return session;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
state.session.status = "error";
|
|
205
|
+
state.session.error = error instanceof Error ? error.message : "Failed to start Codex session";
|
|
206
|
+
this.emit({ type: "session.error", sessionId, error: state.session.error });
|
|
207
|
+
this.stopSession(sessionId);
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async sendTurn(sessionId, message, _attachments) {
|
|
212
|
+
const state = this.getState(sessionId);
|
|
213
|
+
if (!state.providerThreadId) {
|
|
214
|
+
throw new Error("Session has no active thread");
|
|
215
|
+
}
|
|
216
|
+
await this.sendRequest(state, "turn/start", {
|
|
217
|
+
threadId: state.providerThreadId,
|
|
218
|
+
input: [{ type: "text", text: message, text_elements: [] }],
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
async interruptTurn(sessionId) {
|
|
222
|
+
const state = this.sessions.get(sessionId);
|
|
223
|
+
if (!state?.providerThreadId)
|
|
224
|
+
return;
|
|
225
|
+
try {
|
|
226
|
+
await this.sendRequest(state, "turn/interrupt", {
|
|
227
|
+
threadId: state.providerThreadId,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// best effort
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async respondToApproval(sessionId, requestId, approved) {
|
|
235
|
+
const state = this.getState(sessionId);
|
|
236
|
+
// Respond to the server request with a JSON-RPC response using the original request id
|
|
237
|
+
this.writeMessage(state, {
|
|
238
|
+
id: requestId,
|
|
239
|
+
result: { decision: approved ? "approve" : "deny" },
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async stopSession(sessionId) {
|
|
243
|
+
const state = this.sessions.get(sessionId);
|
|
244
|
+
if (!state)
|
|
245
|
+
return;
|
|
246
|
+
state.stopping = true;
|
|
247
|
+
// Clear pending requests
|
|
248
|
+
for (const [, pending] of state.pending) {
|
|
249
|
+
clearTimeout(pending.timeout);
|
|
250
|
+
pending.reject(new Error("Session stopped"));
|
|
251
|
+
}
|
|
252
|
+
state.pending.clear();
|
|
253
|
+
// Close readline interface
|
|
254
|
+
state.rl.close();
|
|
255
|
+
// Kill the process tree
|
|
256
|
+
if (!state.child.killed) {
|
|
257
|
+
killChildTree(state.child);
|
|
258
|
+
}
|
|
259
|
+
this.sessions.delete(sessionId);
|
|
260
|
+
// Emit session.completed so the onEvent handler in /start can unsubscribe
|
|
261
|
+
this.emit({ type: "session.completed", sessionId });
|
|
262
|
+
}
|
|
263
|
+
onEvent(handler) {
|
|
264
|
+
this.emitter.on("event", handler);
|
|
265
|
+
return () => this.emitter.off("event", handler);
|
|
266
|
+
}
|
|
267
|
+
// ── Private helpers ────────────────────────────────────────────────
|
|
268
|
+
emit(event) {
|
|
269
|
+
this.emitter.emit("event", event);
|
|
270
|
+
}
|
|
271
|
+
getState(sessionId) {
|
|
272
|
+
const state = this.sessions.get(sessionId);
|
|
273
|
+
if (!state)
|
|
274
|
+
throw new Error(`No Codex session found: ${sessionId}`);
|
|
275
|
+
return state;
|
|
276
|
+
}
|
|
277
|
+
attachListeners(state) {
|
|
278
|
+
state.rl.on("line", (line) => {
|
|
279
|
+
this.handleStdoutLine(state, line);
|
|
280
|
+
});
|
|
281
|
+
state.child.stderr?.on("data", (data) => {
|
|
282
|
+
const text = data.toString().trim();
|
|
283
|
+
if (text) {
|
|
284
|
+
// Filter out noisy info/debug/trace log lines from codex
|
|
285
|
+
const isLogLine = /^\d{4}-\d{2}-\d{2}T\S+\s+(TRACE|DEBUG|INFO|WARN)\s+/.test(text);
|
|
286
|
+
if (!isLogLine) {
|
|
287
|
+
console.error(`[codex:${state.session.id}] stderr: ${text}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
state.child.on("error", (err) => {
|
|
292
|
+
state.session.status = "error";
|
|
293
|
+
state.session.error = err.message;
|
|
294
|
+
this.emit({ type: "session.error", sessionId: state.session.id, error: err.message });
|
|
295
|
+
});
|
|
296
|
+
state.child.on("exit", (code, signal) => {
|
|
297
|
+
if (state.stopping)
|
|
298
|
+
return;
|
|
299
|
+
const message = `codex app-server exited (code=${code}, signal=${signal})`;
|
|
300
|
+
state.session.status = code === 0 ? "completed" : "error";
|
|
301
|
+
state.session.completedAt = new Date().toISOString();
|
|
302
|
+
if (code !== 0) {
|
|
303
|
+
state.session.error = message;
|
|
304
|
+
}
|
|
305
|
+
this.emit({ type: "session.completed", sessionId: state.session.id });
|
|
306
|
+
// Reject pending requests
|
|
307
|
+
for (const [, pending] of state.pending) {
|
|
308
|
+
clearTimeout(pending.timeout);
|
|
309
|
+
pending.reject(new Error("Codex process exited"));
|
|
310
|
+
}
|
|
311
|
+
state.pending.clear();
|
|
312
|
+
this.sessions.delete(state.session.id);
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
handleStdoutLine(state, line) {
|
|
316
|
+
let parsed;
|
|
317
|
+
try {
|
|
318
|
+
parsed = JSON.parse(line);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (!parsed || typeof parsed !== "object")
|
|
324
|
+
return;
|
|
325
|
+
if (this.isResponse(parsed)) {
|
|
326
|
+
this.handleResponse(state, parsed);
|
|
327
|
+
}
|
|
328
|
+
else if (this.isServerRequest(parsed)) {
|
|
329
|
+
this.handleServerRequest(state, parsed);
|
|
330
|
+
}
|
|
331
|
+
else if (this.isServerNotification(parsed)) {
|
|
332
|
+
this.handleServerNotification(state, parsed);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** Response: has id, no method */
|
|
336
|
+
isResponse(value) {
|
|
337
|
+
const obj = value;
|
|
338
|
+
const hasId = typeof obj.id === "string" || typeof obj.id === "number";
|
|
339
|
+
const hasMethod = typeof obj.method === "string";
|
|
340
|
+
return hasId && !hasMethod;
|
|
341
|
+
}
|
|
342
|
+
/** Server request: has both method and id */
|
|
343
|
+
isServerRequest(value) {
|
|
344
|
+
const obj = value;
|
|
345
|
+
return (typeof obj.method === "string" &&
|
|
346
|
+
(typeof obj.id === "string" || typeof obj.id === "number"));
|
|
347
|
+
}
|
|
348
|
+
/** Server notification: has method, no id */
|
|
349
|
+
isServerNotification(value) {
|
|
350
|
+
const obj = value;
|
|
351
|
+
return typeof obj.method === "string" && !("id" in obj);
|
|
352
|
+
}
|
|
353
|
+
handleResponse(state, response) {
|
|
354
|
+
const key = String(response.id);
|
|
355
|
+
const pending = state.pending.get(key);
|
|
356
|
+
if (!pending)
|
|
357
|
+
return;
|
|
358
|
+
clearTimeout(pending.timeout);
|
|
359
|
+
state.pending.delete(key);
|
|
360
|
+
if (response.error?.message) {
|
|
361
|
+
pending.reject(new Error(`${pending.method} failed: ${response.error.message}`));
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
pending.resolve(response.result);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
handleServerRequest(state, request) {
|
|
368
|
+
const params = (request.params ?? {});
|
|
369
|
+
// Approval requests from codex
|
|
370
|
+
if (request.method === "item/commandExecution/requestApproval" ||
|
|
371
|
+
request.method === "item/fileChange/requestApproval" ||
|
|
372
|
+
request.method === "item/fileRead/requestApproval") {
|
|
373
|
+
const tool = String(params.command ?? params.tool ?? request.method);
|
|
374
|
+
this.emit({
|
|
375
|
+
type: "tool.approval-required",
|
|
376
|
+
sessionId: state.session.id,
|
|
377
|
+
tool,
|
|
378
|
+
args: params,
|
|
379
|
+
requestId: String(request.id),
|
|
380
|
+
});
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
// Unknown server request — respond with error
|
|
384
|
+
this.writeMessage(state, {
|
|
385
|
+
id: request.id,
|
|
386
|
+
error: { code: -32601, message: `Unsupported server request: ${request.method}` },
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
handleServerNotification(state, notification) {
|
|
390
|
+
const params = (notification.params ?? {});
|
|
391
|
+
const sessionId = state.session.id;
|
|
392
|
+
switch (notification.method) {
|
|
393
|
+
// ── Streaming text tokens ──
|
|
394
|
+
case "item/agentMessage/delta":
|
|
395
|
+
case "codex/event/agent_message_content_delta": {
|
|
396
|
+
const delta = typeof params.delta === "string" ? params.delta
|
|
397
|
+
: typeof params.text === "string" ? params.text
|
|
398
|
+
: "";
|
|
399
|
+
if (delta) {
|
|
400
|
+
this.emit({ type: "token", sessionId, content: delta });
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
// ── Reasoning / chain-of-thought tokens ──
|
|
405
|
+
case "item/reasoning/textDelta":
|
|
406
|
+
case "item/reasoning/summaryTextDelta":
|
|
407
|
+
// Handled in the noisy-events skip block below; these tokens
|
|
408
|
+
// are too granular to persist as individual activities.
|
|
409
|
+
break;
|
|
410
|
+
// ── Tool/command output deltas ──
|
|
411
|
+
case "item/commandExecution/outputDelta":
|
|
412
|
+
case "item/fileChange/outputDelta": {
|
|
413
|
+
const delta = typeof params.delta === "string" ? params.delta : "";
|
|
414
|
+
if (delta) {
|
|
415
|
+
const itemId = extractItemId(params);
|
|
416
|
+
if (itemId) {
|
|
417
|
+
this.emit({ type: "tool.output", sessionId, callId: itemId, content: delta });
|
|
418
|
+
}
|
|
419
|
+
// Don't emit a redundant generic activity — the tool.output event
|
|
420
|
+
// is already logged by logProviderEvent.
|
|
421
|
+
}
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
// ── Item lifecycle for tool calls ──
|
|
425
|
+
case "item/started": {
|
|
426
|
+
const item = (params.item ?? params);
|
|
427
|
+
const itemId = extractItemId(params);
|
|
428
|
+
const itemType = normalizeItemType(typeof item.type === "string" ? item.type : "");
|
|
429
|
+
if (isToolItemType(itemType)) {
|
|
430
|
+
const category = mapItemTypeToCategory(itemType);
|
|
431
|
+
this.emit({ type: "tool.start", sessionId, tool: category, args: buildToolArgs(item, category), callId: itemId });
|
|
432
|
+
}
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
case "item/completed": {
|
|
436
|
+
const item = (params.item ?? params);
|
|
437
|
+
const itemId = extractItemId(params);
|
|
438
|
+
const itemType = normalizeItemType(typeof item.type === "string" ? item.type : "");
|
|
439
|
+
if (isToolItemType(itemType)) {
|
|
440
|
+
const category = mapItemTypeToCategory(itemType);
|
|
441
|
+
const status = typeof item.status === "string" ? item.status : "completed";
|
|
442
|
+
const output = typeof item.output === "string" ? item.output
|
|
443
|
+
: typeof item.summary === "string" ? item.summary
|
|
444
|
+
: "";
|
|
445
|
+
this.emit({
|
|
446
|
+
type: "tool.result",
|
|
447
|
+
sessionId,
|
|
448
|
+
tool: category,
|
|
449
|
+
ok: status !== "error" && status !== "failed",
|
|
450
|
+
message: output,
|
|
451
|
+
callId: itemId,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
// Non-tool item completed (e.g. agent message) — extract text content
|
|
456
|
+
// Skip user items (already persisted by the route handler)
|
|
457
|
+
const itemRole = typeof item.role === "string" ? item.role : "";
|
|
458
|
+
const rawType = typeof item.type === "string" ? item.type : "";
|
|
459
|
+
const isUserItem = itemRole === "user" || /user/i.test(rawType);
|
|
460
|
+
if (!isUserItem) {
|
|
461
|
+
const text = extractTextContent(item);
|
|
462
|
+
if (text) {
|
|
463
|
+
this.emit({ type: "message", sessionId, role: "assistant", content: text });
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
case "item/mcpToolCall/progress": {
|
|
470
|
+
const itemId = extractItemId(params);
|
|
471
|
+
const toolName = typeof params.name === "string"
|
|
472
|
+
? params.name
|
|
473
|
+
: typeof params.toolName === "string"
|
|
474
|
+
? params.toolName
|
|
475
|
+
: "mcp-tool";
|
|
476
|
+
this.emit({
|
|
477
|
+
type: "tool.start",
|
|
478
|
+
sessionId,
|
|
479
|
+
tool: toolName,
|
|
480
|
+
args: params.arguments ?? params.args ?? {},
|
|
481
|
+
callId: itemId,
|
|
482
|
+
});
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
// ── codex/event item lifecycle (codex 0.111.0+ envelope format) ──
|
|
486
|
+
case "codex/event/item_started": {
|
|
487
|
+
const msg = (params.msg ?? params);
|
|
488
|
+
const itemId = extractCodexEventItemId(params);
|
|
489
|
+
const itemType = normalizeItemType(typeof msg.type === "string" ? msg.type
|
|
490
|
+
: typeof msg.kind === "string" ? msg.kind
|
|
491
|
+
: "");
|
|
492
|
+
if (isToolItemType(itemType)) {
|
|
493
|
+
const category = mapItemTypeToCategory(itemType);
|
|
494
|
+
this.emit({ type: "tool.start", sessionId, tool: category, args: buildToolArgs(msg, category), callId: itemId });
|
|
495
|
+
}
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
case "codex/event/item_completed": {
|
|
499
|
+
const msg = (params.msg ?? params);
|
|
500
|
+
const itemId = extractCodexEventItemId(params);
|
|
501
|
+
const itemType = normalizeItemType(typeof msg.type === "string" ? msg.type
|
|
502
|
+
: typeof msg.kind === "string" ? msg.kind
|
|
503
|
+
: "");
|
|
504
|
+
if (isToolItemType(itemType)) {
|
|
505
|
+
const category = mapItemTypeToCategory(itemType);
|
|
506
|
+
const status = typeof msg.status === "string" ? msg.status : "completed";
|
|
507
|
+
const output = typeof msg.output === "string" ? msg.output
|
|
508
|
+
: typeof msg.summary === "string" ? msg.summary
|
|
509
|
+
: typeof msg.last_agent_message === "string" ? msg.last_agent_message
|
|
510
|
+
: "";
|
|
511
|
+
this.emit({
|
|
512
|
+
type: "tool.result",
|
|
513
|
+
sessionId,
|
|
514
|
+
tool: category,
|
|
515
|
+
ok: status !== "error" && status !== "failed",
|
|
516
|
+
message: output,
|
|
517
|
+
callId: itemId,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
// Non-tool item completed (e.g. agent message) — extract text content
|
|
522
|
+
// Skip user items (already persisted by the route handler)
|
|
523
|
+
const msgRole = typeof msg.role === "string" ? msg.role : "";
|
|
524
|
+
const rawType = typeof msg.type === "string" ? msg.type : "";
|
|
525
|
+
const isUserItem = msgRole === "user" || /user/i.test(rawType);
|
|
526
|
+
if (!isUserItem) {
|
|
527
|
+
const text = extractTextContent(msg);
|
|
528
|
+
if (text) {
|
|
529
|
+
this.emit({ type: "message", sessionId, role: "assistant", content: text });
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
break;
|
|
534
|
+
}
|
|
535
|
+
// ── Turn lifecycle ──
|
|
536
|
+
case "turn/started": {
|
|
537
|
+
state.session.status = "running";
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
case "turn/completed": {
|
|
541
|
+
// Mark as idle (ready for next turn) — the Codex app-server session is
|
|
542
|
+
// still alive and maintains the full conversation history. We must NOT
|
|
543
|
+
// emit session.completed here because that would tear down the event
|
|
544
|
+
// listener and mark the DB thread as "completed", causing the frontend
|
|
545
|
+
// to call /start (which creates a brand-new session with no context)
|
|
546
|
+
// instead of /send.
|
|
547
|
+
state.session.status = "idle";
|
|
548
|
+
const turn = params.turn;
|
|
549
|
+
const status = typeof turn?.status === "string" ? turn.status : "";
|
|
550
|
+
const errorObj = turn?.error;
|
|
551
|
+
if (status === "failed" && errorObj?.message) {
|
|
552
|
+
state.session.error = String(errorObj.message);
|
|
553
|
+
this.emit({ type: "session.error", sessionId, error: state.session.error });
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
this.emit({ type: "turn.completed", sessionId });
|
|
557
|
+
}
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
// ── Errors ──
|
|
561
|
+
case "error": {
|
|
562
|
+
const errorObj = params.error;
|
|
563
|
+
const message = typeof errorObj?.message === "string" ? errorObj.message : "Codex error";
|
|
564
|
+
this.emit({ type: "session.error", sessionId, error: message });
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
// ── Agent / user complete messages → emit as proper message events ──
|
|
568
|
+
case "codex/event/agent_message": {
|
|
569
|
+
const text = typeof params.content === "string" ? params.content
|
|
570
|
+
: typeof params.text === "string" ? params.text
|
|
571
|
+
: typeof params.message === "string" ? params.message
|
|
572
|
+
: typeof params.delta === "string" ? params.delta
|
|
573
|
+
: "";
|
|
574
|
+
if (text) {
|
|
575
|
+
this.emit({ type: "message", sessionId, role: "assistant", content: text });
|
|
576
|
+
}
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
case "codex/event/user_message": {
|
|
580
|
+
// User messages are already persisted by the route handler (/start, /send).
|
|
581
|
+
// Ignore the echo from Codex to avoid duplicates.
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
// ── Noisy / redundant events — skip logging to DB ──
|
|
585
|
+
case "item/plan/delta":
|
|
586
|
+
case "turn/plan/updated":
|
|
587
|
+
case "turn/diff/updated":
|
|
588
|
+
case "thread/tokenUsage/updated":
|
|
589
|
+
case "codex/event/token_count":
|
|
590
|
+
case "codex/event/agent_message_delta":
|
|
591
|
+
// Already handled as token events or too noisy to persist
|
|
592
|
+
break;
|
|
593
|
+
// ── Known lifecycle / status notifications → emit as activity ──
|
|
594
|
+
case "thread/started":
|
|
595
|
+
case "thread/status/changed":
|
|
596
|
+
case "thread/name/updated":
|
|
597
|
+
case "model/rerouted":
|
|
598
|
+
case "configWarning":
|
|
599
|
+
case "deprecationNotice":
|
|
600
|
+
case "account/updated":
|
|
601
|
+
case "skills/changed":
|
|
602
|
+
case "codex/event/mcp_startup_complete":
|
|
603
|
+
case "codex/event/skills_update_available":
|
|
604
|
+
case "codex/event/task_started":
|
|
605
|
+
case "codex/event/task_complete":
|
|
606
|
+
case "codex/event/agent_reasoning": {
|
|
607
|
+
this.emit({
|
|
608
|
+
type: "activity",
|
|
609
|
+
sessionId,
|
|
610
|
+
kind: notification.method,
|
|
611
|
+
summary: `Codex: ${notification.method}`,
|
|
612
|
+
payload: params,
|
|
613
|
+
});
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
default:
|
|
617
|
+
this.emit({
|
|
618
|
+
type: "activity",
|
|
619
|
+
sessionId,
|
|
620
|
+
kind: notification.method,
|
|
621
|
+
summary: `Codex: ${notification.method}`,
|
|
622
|
+
payload: params,
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
sendRequest(state, method, params, timeoutMs = 20_000) {
|
|
627
|
+
const id = state.nextId++;
|
|
628
|
+
return new Promise((resolve, reject) => {
|
|
629
|
+
const timeout = setTimeout(() => {
|
|
630
|
+
state.pending.delete(String(id));
|
|
631
|
+
reject(new Error(`Timed out waiting for ${method}`));
|
|
632
|
+
}, timeoutMs);
|
|
633
|
+
state.pending.set(String(id), { method, timeout, resolve, reject });
|
|
634
|
+
this.writeMessage(state, { method, id, params });
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
writeMessage(state, message) {
|
|
638
|
+
if (!state.child.stdin?.writable) {
|
|
639
|
+
throw new Error("Cannot write to codex app-server stdin");
|
|
640
|
+
}
|
|
641
|
+
state.child.stdin.write(JSON.stringify(message) + "\n");
|
|
642
|
+
}
|
|
643
|
+
testCommand(cmd) {
|
|
644
|
+
return new Promise((resolve) => {
|
|
645
|
+
const parts = cmd.split(" ");
|
|
646
|
+
const bin = parts[0];
|
|
647
|
+
if (!bin) {
|
|
648
|
+
resolve(false);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
const child = spawn(bin, [...parts.slice(1), "--version"], {
|
|
652
|
+
stdio: "pipe",
|
|
653
|
+
shell: true,
|
|
654
|
+
});
|
|
655
|
+
const timer = setTimeout(() => {
|
|
656
|
+
child.kill();
|
|
657
|
+
resolve(false);
|
|
658
|
+
}, 5000);
|
|
659
|
+
child.on("exit", (code) => {
|
|
660
|
+
clearTimeout(timer);
|
|
661
|
+
resolve(code === 0);
|
|
662
|
+
});
|
|
663
|
+
child.on("error", () => {
|
|
664
|
+
clearTimeout(timer);
|
|
665
|
+
resolve(false);
|
|
666
|
+
});
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
671
|
+
function mapRuntimeMode(mode) {
|
|
672
|
+
if (mode === "supervised") {
|
|
673
|
+
return { approvalPolicy: "on-request", sandbox: "workspace-write" };
|
|
674
|
+
}
|
|
675
|
+
return { approvalPolicy: "never", sandbox: "danger-full-access" };
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* On Windows with `shell: true`, `child.kill()` only terminates the cmd.exe
|
|
679
|
+
* wrapper, leaving the actual process running. Use `taskkill /T` to kill
|
|
680
|
+
* the entire process tree.
|
|
681
|
+
*/
|
|
682
|
+
function killChildTree(child) {
|
|
683
|
+
if (process.platform === "win32" && child.pid !== undefined) {
|
|
684
|
+
try {
|
|
685
|
+
spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore" });
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
catch {
|
|
689
|
+
// fallback
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
child.kill();
|
|
693
|
+
}
|
|
694
|
+
// ── Item ID extraction ───────────────────────────────────────────────
|
|
695
|
+
let _nextFallbackId = 1;
|
|
696
|
+
/** Extract item ID from standard item/* notification params */
|
|
697
|
+
function extractItemId(params) {
|
|
698
|
+
const item = params.item;
|
|
699
|
+
return (asString(params.itemId) ??
|
|
700
|
+
asString(item?.id) ??
|
|
701
|
+
asString(params.id) ??
|
|
702
|
+
`codex-item-${_nextFallbackId++}`);
|
|
703
|
+
}
|
|
704
|
+
/** Extract item ID from codex/event/* notification params (msg envelope) */
|
|
705
|
+
function extractCodexEventItemId(params) {
|
|
706
|
+
const msg = params.msg;
|
|
707
|
+
return (asString(msg?.item_id) ??
|
|
708
|
+
asString(msg?.itemId) ??
|
|
709
|
+
asString(params.id) ??
|
|
710
|
+
asString(msg?.id) ??
|
|
711
|
+
`codex-evt-${_nextFallbackId++}`);
|
|
712
|
+
}
|
|
713
|
+
/** Safely read a string */
|
|
714
|
+
function asString(v) {
|
|
715
|
+
return typeof v === "string" && v.trim() ? v : undefined;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Extract text content from a non-tool item (e.g. agent message item).
|
|
719
|
+
* Codex sends completed message items with various content field names.
|
|
720
|
+
*/
|
|
721
|
+
function extractTextContent(item) {
|
|
722
|
+
// Direct text fields
|
|
723
|
+
if (typeof item.content === "string" && item.content.trim())
|
|
724
|
+
return item.content;
|
|
725
|
+
if (typeof item.text === "string" && item.text.trim())
|
|
726
|
+
return item.text;
|
|
727
|
+
if (typeof item.message === "string" && item.message.trim())
|
|
728
|
+
return item.message;
|
|
729
|
+
if (typeof item.output === "string" && item.output.trim())
|
|
730
|
+
return item.output;
|
|
731
|
+
if (typeof item.last_agent_message === "string" && item.last_agent_message.trim())
|
|
732
|
+
return item.last_agent_message;
|
|
733
|
+
// Content may be an array of parts (OpenAI message format)
|
|
734
|
+
if (Array.isArray(item.content)) {
|
|
735
|
+
const texts = item.content
|
|
736
|
+
.filter((p) => p.type === "text" || p.type === "output_text")
|
|
737
|
+
.map((p) => (typeof p.text === "string" ? p.text : ""))
|
|
738
|
+
.filter(Boolean);
|
|
739
|
+
if (texts.length > 0)
|
|
740
|
+
return texts.join("\n");
|
|
741
|
+
}
|
|
742
|
+
return "";
|
|
743
|
+
}
|
|
744
|
+
// ── Item type classification ─────────────────────────────────────────
|
|
745
|
+
/** Normalize a raw item type to lowercase words for matching */
|
|
746
|
+
function normalizeItemType(raw) {
|
|
747
|
+
// camelCase → words, then lowercase
|
|
748
|
+
return raw
|
|
749
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
750
|
+
.replace(/[_\-/]+/g, " ")
|
|
751
|
+
.toLowerCase()
|
|
752
|
+
.trim();
|
|
753
|
+
}
|
|
754
|
+
/** Does this item type represent a tool / command / file operation? */
|
|
755
|
+
function isToolItemType(normalized) {
|
|
756
|
+
return (normalized.includes("command") ||
|
|
757
|
+
normalized.includes("tool") ||
|
|
758
|
+
normalized.includes("function") ||
|
|
759
|
+
normalized.includes("file change") ||
|
|
760
|
+
normalized.includes("file_change") ||
|
|
761
|
+
normalized.includes("patch") ||
|
|
762
|
+
normalized.includes("edit") ||
|
|
763
|
+
normalized.includes("mcp") ||
|
|
764
|
+
normalized.includes("web search"));
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Map a normalized item type to a frontend-compatible tool category.
|
|
768
|
+
* These categories must match entries in the frontend's toolMeta dictionary
|
|
769
|
+
* (e.g. 'execute', 'edit', 'read', 'search', 'web').
|
|
770
|
+
*/
|
|
771
|
+
function mapItemTypeToCategory(normalizedType) {
|
|
772
|
+
if (normalizedType.includes("command"))
|
|
773
|
+
return "execute";
|
|
774
|
+
if (normalizedType.includes("file change") || normalizedType.includes("file_change") ||
|
|
775
|
+
normalizedType.includes("patch") || normalizedType.includes("edit"))
|
|
776
|
+
return "edit";
|
|
777
|
+
if (normalizedType.includes("file read") || normalizedType.includes("file_read"))
|
|
778
|
+
return "read";
|
|
779
|
+
if (normalizedType.includes("web search") || normalizedType.includes("web_search"))
|
|
780
|
+
return "web";
|
|
781
|
+
if (normalizedType.includes("mcp"))
|
|
782
|
+
return "mcp-tool";
|
|
783
|
+
if (normalizedType.includes("function") || normalizedType.includes("tool"))
|
|
784
|
+
return "execute";
|
|
785
|
+
return normalizedType || "tool";
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Build args that the frontend's getCallSummary can render nicely.
|
|
789
|
+
* For 'execute' → { command: "...", ...rest }
|
|
790
|
+
* For 'edit' → { path: "...", ...rest }
|
|
791
|
+
* For 'read' → { path: "...", ...rest }
|
|
792
|
+
* For 'web' → { query: "...", ...rest }
|
|
793
|
+
*/
|
|
794
|
+
function buildToolArgs(item, category) {
|
|
795
|
+
switch (category) {
|
|
796
|
+
case "execute": {
|
|
797
|
+
const cmd = asString(item.command) ??
|
|
798
|
+
(Array.isArray(item.command)
|
|
799
|
+
? item.command.join(" ")
|
|
800
|
+
: undefined) ??
|
|
801
|
+
asString(item.name) ??
|
|
802
|
+
asString(item.title) ??
|
|
803
|
+
"";
|
|
804
|
+
return { command: cmd, ...item };
|
|
805
|
+
}
|
|
806
|
+
case "edit":
|
|
807
|
+
case "read": {
|
|
808
|
+
const path = asString(item.name) ??
|
|
809
|
+
asString(item.path) ??
|
|
810
|
+
asString(item.file) ??
|
|
811
|
+
asString(item.title) ??
|
|
812
|
+
"";
|
|
813
|
+
return { path, ...item };
|
|
814
|
+
}
|
|
815
|
+
case "web": {
|
|
816
|
+
const query = asString(item.query) ??
|
|
817
|
+
asString(item.name) ??
|
|
818
|
+
asString(item.url) ??
|
|
819
|
+
"";
|
|
820
|
+
return { query, ...item };
|
|
821
|
+
}
|
|
822
|
+
default:
|
|
823
|
+
return { ...item };
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
//# sourceMappingURL=codex-provider.js.map
|