@prestyj/cli 5.11.0 → 5.13.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/README.md +46 -36
- package/assets/skills/bulletproof/SKILL.md +158 -0
- package/assets/skills/bulletproof/references/agent-surface.md +82 -0
- package/assets/skills/bulletproof/references/audit-protocol.md +147 -0
- package/assets/skills/bulletproof/references/platform-playbooks.md +176 -0
- package/assets/skills/bulletproof/references/provenance.md +45 -0
- package/assets/skills/bulletproof/references/secure-defaults.md +108 -0
- package/assets/skills/bulletproof/references/supply-chain.md +76 -0
- package/assets/skills/bulletproof/references/threat-landscape.md +74 -0
- package/assets/skills/bulletproof/references/verification.md +65 -0
- package/assets/skills/compliance-guard/SKILL.md +251 -0
- package/assets/skills/compliance-guard/references/artifacts.md +186 -0
- package/assets/skills/compliance-guard/references/eu-uk.md +151 -0
- package/assets/skills/compliance-guard/references/exposure-triage.md +161 -0
- package/assets/skills/compliance-guard/references/lawsuit-vectors.md +141 -0
- package/assets/skills/compliance-guard/references/provenance.md +42 -0
- package/assets/skills/compliance-guard/references/sector-gates.md +173 -0
- package/assets/skills/compliance-guard/references/security-baseline.md +130 -0
- package/assets/skills/compliance-guard/references/trigger-map.md +163 -0
- package/assets/skills/compliance-guard/references/us.md +164 -0
- package/assets/skills/durable/SKILL.md +111 -0
- package/assets/skills/durable/references/backups-and-runtime.md +86 -0
- package/assets/skills/durable/references/migrations-and-schema.md +79 -0
- package/assets/skills/lean/SKILL.md +110 -0
- package/assets/skills/lean/references/memory-and-processes.md +98 -0
- package/assets/skills/lean/references/playbooks.md +107 -0
- package/dist/app-sidecar-auth-broadcast.test.js +111 -10
- package/dist/app-sidecar-auth-broadcast.test.js.map +1 -1
- package/dist/app-sidecar-sessions.test.js +1 -1
- package/dist/app-sidecar.js +210 -72
- package/dist/app-sidecar.js.map +1 -1
- package/dist/chat-agents/jiwa.test.js +1 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +33 -36
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/mcp.js +30 -10
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +28 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +50 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +56 -13
- package/dist/config.test.js.map +1 -1
- package/dist/core/agent-session-checkpoint-flush.test.js +2 -2
- package/dist/core/agent-session-compaction.test.js +60 -0
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-crash-durability.test.js +3 -3
- package/dist/core/agent-session-model-switch.test.js +1 -1
- package/dist/core/agent-session-process-gate.test.js +7 -1
- package/dist/core/agent-session-process-gate.test.js.map +1 -1
- package/dist/core/agent-session-review-coverage.test.js +52 -1
- package/dist/core/agent-session-review-coverage.test.js.map +1 -1
- package/dist/core/agent-session-tool-tiers.test.d.ts +2 -0
- package/dist/core/agent-session-tool-tiers.test.d.ts.map +1 -0
- package/dist/core/agent-session-tool-tiers.test.js +138 -0
- package/dist/core/agent-session-tool-tiers.test.js.map +1 -0
- package/dist/core/agent-session-verification-gate.test.d.ts +2 -0
- package/dist/core/agent-session-verification-gate.test.d.ts.map +1 -0
- package/dist/core/agent-session-verification-gate.test.js +135 -0
- package/dist/core/agent-session-verification-gate.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +77 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +268 -33
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/agents.d.ts +29 -1
- package/dist/core/agents.d.ts.map +1 -1
- package/dist/core/agents.js +47 -97
- package/dist/core/agents.js.map +1 -1
- package/dist/core/agents.test.js +87 -7
- package/dist/core/agents.test.js.map +1 -1
- package/dist/core/api-benchmark.d.ts +3 -3
- package/dist/core/api-benchmark.js +7 -7
- package/dist/core/auth-providers.d.ts +37 -1
- package/dist/core/auth-providers.d.ts.map +1 -1
- package/dist/core/auth-providers.js +84 -4
- package/dist/core/auth-providers.js.map +1 -1
- package/dist/core/auto-update.test.js +1 -1
- package/dist/core/autopilot-gate.d.ts +2 -2
- package/dist/core/autopilot-gate.js +1 -1
- package/dist/core/autopilot-gate.test.js +7 -4
- package/dist/core/autopilot-gate.test.js.map +1 -1
- package/dist/core/bash-spawn-benchmark.js +6 -6
- package/dist/core/bundled-agents.d.ts +3 -0
- package/dist/core/bundled-agents.d.ts.map +1 -0
- package/dist/core/bundled-agents.js +255 -0
- package/dist/core/bundled-agents.js.map +1 -0
- package/dist/core/cache-warm-benchmark.d.ts +2 -2
- package/dist/core/cache-warm-benchmark.js +5 -5
- package/dist/core/code-retrieval-chunkers.d.ts +27 -0
- package/dist/core/code-retrieval-chunkers.d.ts.map +1 -0
- package/dist/core/code-retrieval-chunkers.js +264 -0
- package/dist/core/code-retrieval-chunkers.js.map +1 -0
- package/dist/core/code-retrieval-chunkers.test.d.ts +2 -0
- package/dist/core/code-retrieval-chunkers.test.d.ts.map +1 -0
- package/dist/core/code-retrieval-chunkers.test.js +203 -0
- package/dist/core/code-retrieval-chunkers.test.js.map +1 -0
- package/dist/core/code-retrieval.d.ts +6 -0
- package/dist/core/code-retrieval.d.ts.map +1 -1
- package/dist/core/code-retrieval.js +38 -1
- package/dist/core/code-retrieval.js.map +1 -1
- package/dist/core/compaction/token-estimator.test.js +1 -1
- package/dist/core/encode-cwd.test.js +1 -1
- package/dist/core/event-bus.d.ts +11 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +1 -0
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/event-bus.test.d.ts +2 -0
- package/dist/core/event-bus.test.d.ts.map +1 -0
- package/dist/core/event-bus.test.js +33 -0
- package/dist/core/event-bus.test.js.map +1 -0
- package/dist/core/extensions/plugin-bundles.js +2 -2
- package/dist/core/extensions/plugin-bundles.js.map +1 -1
- package/dist/core/extensions/plugin-bundles.test.js +2 -2
- package/dist/core/extensions/plugin-bundles.test.js.map +1 -1
- package/dist/core/fast-apply-benchmark.d.ts +2 -2
- package/dist/core/fast-apply-benchmark.js +6 -6
- package/dist/core/foreign-session-import.test.js +1 -1
- package/dist/core/goal-lifecycle-smoke.test.js +2 -2
- package/dist/core/goal-store.js +1 -1
- package/dist/core/goal-store.test.js +2 -2
- package/dist/core/goal-verifier.test.js +2 -2
- package/dist/core/goal-worker-dev-server-lifecycle.test.js +1 -1
- package/dist/core/goal-worker.test.js +2 -2
- package/dist/core/hashline-edit-benchmark.d.ts +2 -2
- package/dist/core/hashline-edit-benchmark.js +7 -7
- package/dist/core/local-endpoint-store.test.js +1 -1
- package/dist/core/logger.d.ts +1 -1
- package/dist/core/logger.js +2 -2
- package/dist/core/logger.js.map +1 -1
- package/dist/core/lsp/client-navigation.test.d.ts +2 -0
- package/dist/core/lsp/client-navigation.test.d.ts.map +1 -0
- package/dist/core/lsp/client-navigation.test.js +135 -0
- package/dist/core/lsp/client-navigation.test.js.map +1 -0
- package/dist/core/lsp/client.d.ts +69 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +151 -2
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/lsp/integration.test.js +2 -2
- package/dist/core/lsp/manager-navigation.test.d.ts +2 -0
- package/dist/core/lsp/manager-navigation.test.d.ts.map +1 -0
- package/dist/core/lsp/manager-navigation.test.js +121 -0
- package/dist/core/lsp/manager-navigation.test.js.map +1 -0
- package/dist/core/lsp/manager.d.ts +35 -1
- package/dist/core/lsp/manager.d.ts.map +1 -1
- package/dist/core/lsp/manager.js +92 -0
- package/dist/core/lsp/manager.js.map +1 -1
- package/dist/core/lsp/servers.test.js +1 -1
- package/dist/core/lsp/windows.test.js +4 -4
- package/dist/core/mcp/catalog-cache.test.js +1 -1
- package/dist/core/mcp/client-session-recovery.test.js +1 -1
- package/dist/core/mcp/client.d.ts.map +1 -1
- package/dist/core/mcp/client.js +2 -10
- package/dist/core/mcp/client.js.map +1 -1
- package/dist/core/mcp/content.d.ts +19 -0
- package/dist/core/mcp/content.d.ts.map +1 -0
- package/dist/core/mcp/content.js +172 -0
- package/dist/core/mcp/content.js.map +1 -0
- package/dist/core/mcp/content.test.d.ts +2 -0
- package/dist/core/mcp/content.test.d.ts.map +1 -0
- package/dist/core/mcp/content.test.js +135 -0
- package/dist/core/mcp/content.test.js.map +1 -0
- package/dist/core/mcp/defaults.d.ts +3 -1
- package/dist/core/mcp/defaults.d.ts.map +1 -1
- package/dist/core/mcp/defaults.js +9 -2
- package/dist/core/mcp/defaults.js.map +1 -1
- package/dist/core/mcp/defaults.test.d.ts +2 -0
- package/dist/core/mcp/defaults.test.d.ts.map +1 -0
- package/dist/core/mcp/defaults.test.js +60 -0
- package/dist/core/mcp/defaults.test.js.map +1 -0
- package/dist/core/mcp/deferred-catalog.d.ts +1 -1
- package/dist/core/mcp/deferred-catalog.js +1 -1
- package/dist/core/mcp/elicitation.test.js +1 -1
- package/dist/core/mcp/legacy-negotiation.test.js +2 -2
- package/dist/core/mcp/oauth-store.test.js +2 -2
- package/dist/core/mcp/resolve-stdio.test.js +5 -5
- package/dist/core/mcp/shared-pool.test.js +5 -5
- package/dist/core/mcp/store.test.js +5 -5
- package/dist/core/mcp/when-connected.test.js +2 -2
- package/dist/core/nolan-model.test.js +1 -1
- package/dist/core/nolan-prompt.js +5 -5
- package/dist/core/oauth/xai.d.ts +2 -0
- package/dist/core/oauth/xai.d.ts.map +1 -0
- package/dist/core/oauth/xai.js +4 -0
- package/dist/core/oauth/xai.js.map +1 -0
- package/dist/core/persistent-shell.js +1 -1
- package/dist/core/persistent-shell.test.js +6 -6
- package/dist/core/process-manager-dev-server-repro.test.js +51 -12
- package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
- package/dist/core/process-manager-notifications.test.js +24 -14
- package/dist/core/process-manager-notifications.test.js.map +1 -1
- package/dist/core/process-manager-wake.test.d.ts +2 -0
- package/dist/core/process-manager-wake.test.d.ts.map +1 -0
- package/dist/core/process-manager-wake.test.js +96 -0
- package/dist/core/process-manager-wake.test.js.map +1 -0
- package/dist/core/process-manager.d.ts +61 -1
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +204 -4
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/progress/git-xp.test.js +2 -2
- package/dist/core/progress/ranks.d.ts +14 -3
- package/dist/core/progress/ranks.d.ts.map +1 -1
- package/dist/core/progress/ranks.js +181 -12
- package/dist/core/progress/ranks.js.map +1 -1
- package/dist/core/progress/ranks.test.js +48 -7
- package/dist/core/progress/ranks.test.js.map +1 -1
- package/dist/core/progress/rebuild.test.js +1 -1
- package/dist/core/progress/store.test.js +1 -1
- package/dist/core/progress/types.d.ts +2 -1
- package/dist/core/progress/types.d.ts.map +1 -1
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +62 -48
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.js +10 -10
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +3 -3
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/provider-cache.e2e.test.d.ts +2 -0
- package/dist/core/provider-cache.e2e.test.d.ts.map +1 -0
- package/dist/core/provider-cache.e2e.test.js +125 -0
- package/dist/core/provider-cache.e2e.test.js.map +1 -0
- package/dist/core/radio.d.ts +1 -1
- package/dist/core/radio.d.ts.map +1 -1
- package/dist/core/radio.js +90 -6
- package/dist/core/radio.js.map +1 -1
- package/dist/core/radio.test.js +15 -2
- package/dist/core/radio.test.js.map +1 -1
- package/dist/core/run-journal.test.js +2 -2
- package/dist/core/sandbox.test.js +6 -6
- package/dist/core/semantic-search-benchmark.d.ts +2 -2
- package/dist/core/semantic-search-benchmark.js +5 -5
- package/dist/core/session-compaction.test.js +1 -1
- package/dist/core/session-injections.test.d.ts +2 -0
- package/dist/core/session-injections.test.d.ts.map +1 -0
- package/dist/core/session-injections.test.js +117 -0
- package/dist/core/session-injections.test.js.map +1 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +83 -67
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +7 -7
- package/dist/core/session-reconstructability.test.d.ts +2 -0
- package/dist/core/session-reconstructability.test.d.ts.map +1 -0
- package/dist/core/session-reconstructability.test.js +105 -0
- package/dist/core/session-reconstructability.test.js.map +1 -0
- package/dist/core/session-storage-fd-leak.test.d.ts +2 -0
- package/dist/core/session-storage-fd-leak.test.d.ts.map +1 -0
- package/dist/core/session-storage-fd-leak.test.js +116 -0
- package/dist/core/session-storage-fd-leak.test.js.map +1 -0
- package/dist/core/session-storage.d.ts +22 -2
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +33 -6
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/session-storage.test.js +2 -2
- package/dist/core/settings-manager.d.ts +12 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +46 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/shell-path.js +1 -1
- package/dist/core/shell.d.ts +1 -1
- package/dist/core/shell.js +2 -2
- package/dist/core/shell.test.js +2 -2
- package/dist/core/shutdown.d.ts +71 -0
- package/dist/core/shutdown.d.ts.map +1 -0
- package/dist/core/shutdown.js +144 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/core/shutdown.test.d.ts +2 -0
- package/dist/core/shutdown.test.d.ts.map +1 -0
- package/dist/core/shutdown.test.js +160 -0
- package/dist/core/shutdown.test.js.map +1 -0
- package/dist/core/sidecar-error-reporter.js +1 -1
- package/dist/core/sidecar-error-reporter.test.js +2 -2
- package/dist/core/skills-routing.test.js +142 -0
- package/dist/core/skills-routing.test.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +4 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/subagent-manager.d.ts +9 -0
- package/dist/core/subagent-manager.d.ts.map +1 -1
- package/dist/core/subagent-manager.js +45 -12
- package/dist/core/subagent-manager.js.map +1 -1
- package/dist/core/subagent-manager.test.js +14 -8
- package/dist/core/subagent-manager.test.js.map +1 -1
- package/dist/core/subagent-store.test.js +3 -3
- package/dist/core/task-store.js +1 -1
- package/dist/core/verification-gate.d.ts +55 -0
- package/dist/core/verification-gate.d.ts.map +1 -0
- package/dist/core/verification-gate.js +188 -0
- package/dist/core/verification-gate.js.map +1 -0
- package/dist/core/verification-gate.test.d.ts +2 -0
- package/dist/core/verification-gate.test.d.ts.map +1 -0
- package/dist/core/verification-gate.test.js +102 -0
- package/dist/core/verification-gate.test.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/acp-mode.js +2 -2
- package/dist/modes/acp-mode.test.js +10 -8
- package/dist/modes/acp-mode.test.js.map +1 -1
- package/dist/modes/agent-home-mode.d.ts.map +1 -1
- package/dist/modes/agent-home-mode.js +15 -11
- package/dist/modes/agent-home-mode.js.map +1 -1
- package/dist/modes/json-mode.d.ts +9 -1
- package/dist/modes/json-mode.d.ts.map +1 -1
- package/dist/modes/json-mode.js +3 -1
- package/dist/modes/json-mode.js.map +1 -1
- package/dist/modes/serve-mode.d.ts +1 -1
- package/dist/modes/serve-mode.d.ts.map +1 -1
- package/dist/modes/serve-mode.js +14 -9
- package/dist/modes/serve-mode.js.map +1 -1
- package/dist/modes/subagent-worker-mode.d.ts +5 -0
- package/dist/modes/subagent-worker-mode.d.ts.map +1 -1
- package/dist/modes/subagent-worker-mode.js.map +1 -1
- package/dist/session.test.js +1 -1
- package/dist/system-prompt.d.ts +37 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +170 -12
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +170 -11
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/system-prompt.tiering.test.d.ts +2 -0
- package/dist/system-prompt.tiering.test.d.ts.map +1 -0
- package/dist/system-prompt.tiering.test.js +108 -0
- package/dist/system-prompt.tiering.test.js.map +1 -0
- package/dist/tools/bash.d.ts +4 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +57 -3
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/bash.test.js +37 -0
- package/dist/tools/bash.test.js.map +1 -1
- package/dist/tools/code-nav.d.ts +30 -0
- package/dist/tools/code-nav.d.ts.map +1 -0
- package/dist/tools/code-nav.js +320 -0
- package/dist/tools/code-nav.js.map +1 -0
- package/dist/tools/code-nav.test.d.ts +2 -0
- package/dist/tools/code-nav.test.d.ts.map +1 -0
- package/dist/tools/code-nav.test.js +136 -0
- package/dist/tools/code-nav.test.js.map +1 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +37 -4
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +45 -1
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/generate-image.d.ts +1 -1
- package/dist/tools/goals.d.ts +2 -2
- package/dist/tools/goals.test.js +2 -2
- package/dist/tools/grep-parity.test.d.ts +2 -0
- package/dist/tools/grep-parity.test.d.ts.map +1 -0
- package/dist/tools/grep-parity.test.js +92 -0
- package/dist/tools/grep-parity.test.js.map +1 -0
- package/dist/tools/grep-recall.test.d.ts +2 -0
- package/dist/tools/grep-recall.test.d.ts.map +1 -0
- package/dist/tools/grep-recall.test.js +114 -0
- package/dist/tools/grep-recall.test.js.map +1 -0
- package/dist/tools/grep-spawn.test.d.ts +2 -0
- package/dist/tools/grep-spawn.test.d.ts.map +1 -0
- package/dist/tools/grep-spawn.test.js +66 -0
- package/dist/tools/grep-spawn.test.js.map +1 -0
- package/dist/tools/grep.d.ts +13 -3
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +340 -40
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/grep.test.js +17 -14
- package/dist/tools/grep.test.js.map +1 -1
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +8 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-mode.test.js +1 -1
- package/dist/tools/prompt-hints.d.ts +9 -0
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +62 -8
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/read-only-bash.d.ts +6 -0
- package/dist/tools/read-only-bash.d.ts.map +1 -1
- package/dist/tools/read-only-bash.js +168 -9
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/read-only-bash.test.js +49 -0
- package/dist/tools/read-only-bash.test.js.map +1 -1
- package/dist/tools/safe-env.js +1 -1
- package/dist/tools/search-code.d.ts.map +1 -1
- package/dist/tools/search-code.js +7 -6
- package/dist/tools/search-code.js.map +1 -1
- package/dist/tools/search-code.test.js +8 -2
- package/dist/tools/search-code.test.js.map +1 -1
- package/dist/tools/skill.js +3 -1
- package/dist/tools/skill.js.map +1 -1
- package/dist/tools/subagent-control.d.ts.map +1 -1
- package/dist/tools/subagent-control.js +20 -5
- package/dist/tools/subagent-control.js.map +1 -1
- package/dist/tools/subagent-control.test.js +34 -1
- package/dist/tools/subagent-control.test.js.map +1 -1
- package/dist/tools/subagent-shared.d.ts +20 -1
- package/dist/tools/subagent-shared.d.ts.map +1 -1
- package/dist/tools/subagent-shared.js +34 -7
- package/dist/tools/subagent-shared.js.map +1 -1
- package/dist/tools/subagent-shared.test.js +43 -9
- package/dist/tools/subagent-shared.test.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +11 -8
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/subagent.test.js +3 -0
- package/dist/tools/subagent.test.js.map +1 -1
- package/dist/tools/task-send.test.js +19 -10
- package/dist/tools/task-send.test.js.map +1 -1
- package/dist/tools/tool-catalog.test.d.ts +2 -0
- package/dist/tools/tool-catalog.test.d.ts.map +1 -0
- package/dist/tools/tool-catalog.test.js +124 -0
- package/dist/tools/tool-catalog.test.js.map +1 -0
- package/dist/tools/tool-search.d.ts.map +1 -1
- package/dist/tools/tool-search.js +2 -1
- package/dist/tools/tool-search.js.map +1 -1
- package/dist/tools/tool-tiers.d.ts +42 -0
- package/dist/tools/tool-tiers.d.ts.map +1 -0
- package/dist/tools/tool-tiers.js +78 -0
- package/dist/tools/tool-tiers.js.map +1 -0
- package/dist/tools/tool-tiers.test.d.ts +2 -0
- package/dist/tools/tool-tiers.test.d.ts.map +1 -0
- package/dist/tools/tool-tiers.test.js +48 -0
- package/dist/tools/tool-tiers.test.js.map +1 -0
- package/dist/tools/write.test.js +1 -1
- package/dist/ui/App.d.ts +3 -0
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +39 -3
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/app-items.d.ts +2 -0
- package/dist/ui/app-items.d.ts.map +1 -1
- package/dist/ui/app-items.js +2 -0
- package/dist/ui/app-items.js.map +1 -1
- package/dist/ui/components/Banner.d.ts.map +1 -1
- package/dist/ui/components/Banner.js +24 -16
- package/dist/ui/components/Banner.js.map +1 -1
- package/dist/ui/components/ToolExecution.js +42 -34
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/components/force-color.d.ts +2 -0
- package/dist/ui/components/force-color.d.ts.map +1 -0
- package/dist/ui/components/force-color.js +11 -0
- package/dist/ui/components/force-color.js.map +1 -0
- package/dist/ui/components/themed-output.test.d.ts +2 -0
- package/dist/ui/components/themed-output.test.d.ts.map +1 -0
- package/dist/ui/components/themed-output.test.js +111 -0
- package/dist/ui/components/themed-output.test.js.map +1 -0
- package/dist/ui/error-item.d.ts +1 -1
- package/dist/ui/error-item.js +3 -3
- package/dist/ui/error-item.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +4 -1
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +27 -2
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/login.js +2 -2
- package/dist/ui/login.js.map +1 -1
- package/dist/ui/render.d.ts +1 -1
- package/dist/ui/render.js +6 -6
- package/dist/ui/theme/dark-ansi.json +6 -0
- package/dist/ui/theme/dark-daltonized.json +6 -0
- package/dist/ui/theme/dark.json +6 -0
- package/dist/ui/theme/light-ansi.json +6 -0
- package/dist/ui/theme/light-daltonized.json +6 -0
- package/dist/ui/theme/light.json +6 -0
- package/dist/ui/theme/theme.d.ts +6 -0
- package/dist/ui/theme/theme.d.ts.map +1 -1
- package/dist/ui/tui-terminal-recorder.test.js +1 -1
- package/dist/utils/git.test.js +3 -3
- package/dist/utils/image.d.ts.map +1 -1
- package/dist/utils/image.js.map +1 -1
- package/package.json +7 -7
package/dist/app-sidecar.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* POST /prompt → { text } ; runs AgentSession.prompt(text)
|
|
9
9
|
* POST /cancel → aborts the in-flight run
|
|
10
10
|
*
|
|
11
|
-
* The agent spine (
|
|
11
|
+
* The agent spine (@prestyj/ai → @prestyj/agent → @prestyj/core) and every tool are reused
|
|
12
12
|
* unchanged via AgentSession — this file is only a network seam.
|
|
13
13
|
*/
|
|
14
14
|
import http from "node:http";
|
|
@@ -39,14 +39,15 @@ import { sessionToMarkdown, defaultExportFilename, } from "./core/session-export
|
|
|
39
39
|
import { AuthStorage } from "./core/auth-storage.js";
|
|
40
40
|
import { cleanupToolOutputs } from "./tools/overflow.js";
|
|
41
41
|
import { readCappedBody } from "./utils/http-body.js";
|
|
42
|
-
import { fetchSubscriptionUsage,
|
|
42
|
+
import { fetchSubscriptionUsage, SubscriptionUsageError, XIAOMI_CREDITS_KEY, dualAuthProvider, oauthStorageKey, discoverLocalModels, findProbedModel, formatLocalModelId, parseLocalModelId, probeEndpoint, toModelInfo as localModelInfo, } from "@prestyj/core";
|
|
43
43
|
import { LocalEndpointError, addCustomEndpoint, listAllEndpoints, removeCustomEndpoint, syncEndpointCredentials, } from "./core/local-endpoint-store.js";
|
|
44
44
|
import { loginAnthropic } from "./core/oauth/anthropic.js";
|
|
45
45
|
import { loginOpenAI } from "./core/oauth/openai.js";
|
|
46
46
|
import { loginGemini } from "./core/oauth/gemini.js";
|
|
47
47
|
import { loginKimi } from "./core/oauth/kimi.js";
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
48
|
+
import { loginXai } from "./core/oauth/xai.js";
|
|
49
|
+
import { AUTH_PROVIDERS, authPriorityNote, describeAuthMethods, } from "./core/auth-providers.js";
|
|
50
|
+
import { ensureAppDirs, loadSavedSettings, projectScopeAllowed } from "./config.js";
|
|
50
51
|
import { SettingsManager } from "./core/settings-manager.js";
|
|
51
52
|
import { installPlugin, listInstalledPlugins, removePlugin, } from "./core/extensions/plugin-bundles.js";
|
|
52
53
|
import { getModel, getDefaultThinkingLevel, getContextWindow, getAllModels, clearRuntimeModels, registerRuntimeModels, } from "./core/model-registry.js";
|
|
@@ -61,6 +62,7 @@ import { discoverProjects } from "./core/project-discovery.js";
|
|
|
61
62
|
import { listSidecarSessions } from "./app-sidecar-sessions.js";
|
|
62
63
|
import { loadTasksSync, saveTasksSync, pruneDoneTasksSync, getNextPendingTask, markTaskInProgress, } from "./core/task-store.js";
|
|
63
64
|
import { initLogger, log } from "./core/logger.js";
|
|
65
|
+
import { installTerminationHandlers } from "./core/shutdown.js";
|
|
64
66
|
import { RADIO_STATIONS, getCurrentStation, getRadioVolume, playRadio, setRadioVolume, stopRadio, } from "./core/radio.js";
|
|
65
67
|
import { enrichProcessPath } from "./core/shell-path.js";
|
|
66
68
|
import { downscaleForPreview, shrinkToFit, validateVisionImage } from "./utils/image.js";
|
|
@@ -386,27 +388,49 @@ function mcpRowSummary(config) {
|
|
|
386
388
|
}
|
|
387
389
|
/** Load + connect every server, returning one wire row per server. Mirrors the
|
|
388
390
|
* CLI dashboard's buildRows (connectAllDetailed, then dispose). Empty list
|
|
389
|
-
* short-circuits before spawning any stdio process / opening any HTTP conn.
|
|
390
|
-
|
|
391
|
+
* short-circuits before spawning any stdio process / opening any HTTP conn.
|
|
392
|
+
* Project-scope servers run repo-controlled commands, so unless the user
|
|
393
|
+
* trusts them (trustProjectMcpServers) they are reported blocked WITHOUT
|
|
394
|
+
* being connected — even a status probe would spawn the process. */
|
|
395
|
+
async function buildMcpRows(cwd, settingsFile) {
|
|
391
396
|
const scoped = await loadServers(cwd);
|
|
392
397
|
if (scoped.length === 0)
|
|
393
398
|
return [];
|
|
399
|
+
const settings = loadSavedSettings(settingsFile);
|
|
400
|
+
const allowProject = projectScopeAllowed(settings.trustProjectMcpServers, settings.trustedProjects, cwd);
|
|
401
|
+
const connectable = scoped.filter((s) => allowProject || s.scope !== "project");
|
|
402
|
+
const blocked = scoped.filter((s) => !allowProject && s.scope === "project");
|
|
394
403
|
const manager = new MCPClientManager();
|
|
395
404
|
try {
|
|
396
|
-
const results =
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
405
|
+
const results = connectable.length > 0
|
|
406
|
+
? await manager.connectAllDetailed(connectable.map((s) => s.config))
|
|
407
|
+
: [];
|
|
408
|
+
return [
|
|
409
|
+
...connectable.map((s) => {
|
|
410
|
+
const result = results.find((r) => r.name === s.config.name);
|
|
411
|
+
return {
|
|
412
|
+
name: s.config.name,
|
|
413
|
+
scope: s.scope,
|
|
414
|
+
ok: result?.ok ?? false,
|
|
415
|
+
toolCount: result?.toolCount ?? 0,
|
|
416
|
+
error: result?.error,
|
|
417
|
+
kind: s.config.url ? "http" : "stdio",
|
|
418
|
+
summary: mcpRowSummary(s.config),
|
|
419
|
+
requiresAuth: result?.requiresAuth,
|
|
420
|
+
};
|
|
421
|
+
}),
|
|
422
|
+
...blocked.map((s) => ({
|
|
400
423
|
name: s.config.name,
|
|
401
424
|
scope: s.scope,
|
|
402
|
-
ok:
|
|
403
|
-
toolCount:
|
|
404
|
-
error:
|
|
405
|
-
|
|
425
|
+
ok: false,
|
|
426
|
+
toolCount: 0,
|
|
427
|
+
error: "Project-scope server not connected — this repo's .ezcoder/mcp.json runs " +
|
|
428
|
+
"repo-controlled commands. Add or re-add a server in this project via " +
|
|
429
|
+
"the MCP modal to trust it.",
|
|
430
|
+
kind: (s.config.url ? "http" : "stdio"),
|
|
406
431
|
summary: mcpRowSummary(s.config),
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
});
|
|
432
|
+
})),
|
|
433
|
+
];
|
|
410
434
|
}
|
|
411
435
|
finally {
|
|
412
436
|
await manager.dispose();
|
|
@@ -450,6 +474,8 @@ async function runJsonModeIfRequested() {
|
|
|
450
474
|
model: { type: "string" },
|
|
451
475
|
"max-turns": { type: "string" },
|
|
452
476
|
"system-prompt": { type: "string" },
|
|
477
|
+
"agent-prompt": { type: "string" },
|
|
478
|
+
"agent-context": { type: "string" },
|
|
453
479
|
tools: { type: "string" },
|
|
454
480
|
"mcp-servers": { type: "string" },
|
|
455
481
|
"prompt-cache-key": { type: "string" },
|
|
@@ -483,6 +509,8 @@ async function runJsonModeIfRequested() {
|
|
|
483
509
|
model: values.model ?? "claude-opus-5",
|
|
484
510
|
cwd: process.cwd(),
|
|
485
511
|
systemPrompt: values["system-prompt"],
|
|
512
|
+
agentPrompt: values["agent-prompt"],
|
|
513
|
+
agentContext: values["agent-context"] === "none" ? "none" : undefined,
|
|
486
514
|
maxTurns: maxTurnsRaw ? parseInt(maxTurnsRaw, 10) : undefined,
|
|
487
515
|
allowedTools,
|
|
488
516
|
allowedMcpServers,
|
|
@@ -504,9 +532,10 @@ function daemonReadBody(req, res) {
|
|
|
504
532
|
return readCappedBody(req, res);
|
|
505
533
|
}
|
|
506
534
|
function daemonJson(res, status, body) {
|
|
535
|
+
// No CORS headers: only the Rust proxy (no Origin) should call this daemon.
|
|
536
|
+
// Granting origins would let any web page read responses from loopback.
|
|
507
537
|
res.writeHead(status, {
|
|
508
538
|
"content-type": "application/json",
|
|
509
|
-
"access-control-allow-origin": "*",
|
|
510
539
|
});
|
|
511
540
|
res.end(JSON.stringify(body));
|
|
512
541
|
}
|
|
@@ -524,6 +553,13 @@ async function main() {
|
|
|
524
553
|
// GG_APP_LISTENING handshake and consumed by the shell.
|
|
525
554
|
const port = Number(process.env.GG_APP_PORT ?? 0);
|
|
526
555
|
const host = "127.0.0.1";
|
|
556
|
+
// Per-launch bearer token. The Rust shell generates one and passes it via
|
|
557
|
+
// GG_APP_TOKEN; spawned any other way (dev, tests, smoke) we mint our own
|
|
558
|
+
// and report it on the GG_APP_LISTENING line. Every request must carry it
|
|
559
|
+
// as x-ez-token: this daemon creates sessions for arbitrary cwds, runs
|
|
560
|
+
// prompts, and installs plugins, so an unauthenticated loopback port lets
|
|
561
|
+
// any local process drive the agent as the user.
|
|
562
|
+
const authToken = process.env.GG_APP_TOKEN ?? randomUUID();
|
|
527
563
|
const paths = await ensureAppDirs();
|
|
528
564
|
// Own log file so the app sidecar never clobbers the interactive CLI's
|
|
529
565
|
// ~/.ezcoder/debug.log (initLogger truncates on each start).
|
|
@@ -586,7 +622,7 @@ async function main() {
|
|
|
586
622
|
await auth.load();
|
|
587
623
|
// Every window's session lives here as an in-process object, keyed by the id
|
|
588
624
|
// the daemon hands back from POST /session. The Rust shell routes each proxy
|
|
589
|
-
// request to its window's session via the `x-
|
|
625
|
+
// request to its window's session via the `x-ez-session` header (and the
|
|
590
626
|
// `?session=` query for the SSE /events stream).
|
|
591
627
|
const sessions = new Map();
|
|
592
628
|
/**
|
|
@@ -645,7 +681,7 @@ async function main() {
|
|
|
645
681
|
const displayName = provider === "anthropic" ? "Anthropic" : provider === "openai" ? "Codex" : "Kimi";
|
|
646
682
|
// Kimi plan usage is tracked on the OAuth credential specifically — the
|
|
647
683
|
// Moonshot platform API key is metered per-token, not per plan window.
|
|
648
|
-
const authKey = provider
|
|
684
|
+
const authKey = oauthStorageKey(provider) ?? provider;
|
|
649
685
|
if (!(await auth.hasProviderAuth(authKey))) {
|
|
650
686
|
// Logged out: drop the replay cache so a later login on a DIFFERENT
|
|
651
687
|
// account can never inherit the previous one's numbers.
|
|
@@ -666,7 +702,14 @@ async function main() {
|
|
|
666
702
|
// A provider can revoke an access token before its stored expiry. Refresh
|
|
667
703
|
// once on 401, matching inference auth recovery, then retry the usage call.
|
|
668
704
|
if (error instanceof SubscriptionUsageError && error.status === 401) {
|
|
669
|
-
|
|
705
|
+
// Name the rejected token. This poller runs on a timer alongside live
|
|
706
|
+
// agent runs, so an unconditional refresh here would invalidate the
|
|
707
|
+
// token those runs are holding and fail them mid-turn — a background
|
|
708
|
+
// status check must never be able to log out the foreground.
|
|
709
|
+
credentials = await auth.resolveCredentials(authKey, {
|
|
710
|
+
forceRefresh: true,
|
|
711
|
+
rejectedToken: credentials.accessToken,
|
|
712
|
+
});
|
|
670
713
|
const snapshot = {
|
|
671
714
|
...(await fetchSubscriptionUsage(provider, credentials)),
|
|
672
715
|
connected: true,
|
|
@@ -751,10 +794,10 @@ async function main() {
|
|
|
751
794
|
usageRequests.delete(provider);
|
|
752
795
|
}
|
|
753
796
|
}
|
|
754
|
-
/** Resolve the target session id: the `x-
|
|
797
|
+
/** Resolve the target session id: the `x-ez-session` header, else a
|
|
755
798
|
* `?session=` query param (used by the SSE /events connection). */
|
|
756
799
|
function sessionIdFromReq(req, url) {
|
|
757
|
-
const header = req.headers["x-
|
|
800
|
+
const header = req.headers["x-ez-session"];
|
|
758
801
|
if (typeof header === "string" && header.length > 0)
|
|
759
802
|
return header;
|
|
760
803
|
try {
|
|
@@ -767,16 +810,26 @@ async function main() {
|
|
|
767
810
|
const server = http.createServer(wrapSidecarHandler((req, res) => {
|
|
768
811
|
const url = req.url ?? "/";
|
|
769
812
|
const method = req.method ?? "GET";
|
|
770
|
-
//
|
|
813
|
+
// Answer preflights with a bare 204 but grant NO origins — the webview
|
|
814
|
+
// reaches the daemon through the Rust proxy, never cross-origin, so any
|
|
815
|
+
// browser page's preflight must fail here.
|
|
771
816
|
if (method === "OPTIONS") {
|
|
772
|
-
res.writeHead(204
|
|
773
|
-
"access-control-allow-origin": "*",
|
|
774
|
-
"access-control-allow-methods": "GET, POST, DELETE, OPTIONS",
|
|
775
|
-
"access-control-allow-headers": "content-type, x-gg-session",
|
|
776
|
-
});
|
|
817
|
+
res.writeHead(204);
|
|
777
818
|
res.end();
|
|
778
819
|
return;
|
|
779
820
|
}
|
|
821
|
+
// Host allowlist. The daemon binds 127.0.0.1 only; rejecting any other
|
|
822
|
+
// Host blocks DNS rebinding, where a web page's request arrives with
|
|
823
|
+
// the attacker's hostname (browsers cannot spoof Host).
|
|
824
|
+
const reqHost = req.headers.host ?? "";
|
|
825
|
+
if (!/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i.test(reqHost)) {
|
|
826
|
+
daemonJson(res, 403, { error: "forbidden host" });
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (req.headers["x-ez-token"] !== authToken) {
|
|
830
|
+
daemonJson(res, 401, { error: "unauthorized" });
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
780
833
|
// ── Daemon-level routes (session lifecycle) ──────────────────────────
|
|
781
834
|
// Create a session for a window: { mode?, cwd, sessionPath? } → { sessionId }.
|
|
782
835
|
if (method === "POST" && url === "/session") {
|
|
@@ -874,28 +927,34 @@ async function main() {
|
|
|
874
927
|
}, "app-sidecar.http"));
|
|
875
928
|
server.listen(port, host, () => {
|
|
876
929
|
const addr = server.address();
|
|
877
|
-
// The Rust shell reads this line to learn the daemon port
|
|
878
|
-
|
|
930
|
+
// The Rust shell reads this line to learn the daemon port (it already
|
|
931
|
+
// knows the token — it set GG_APP_TOKEN; the field serves other spawners).
|
|
932
|
+
process.stdout.write(`GG_APP_LISTENING ${addr.port} ${authToken}\n`);
|
|
879
933
|
log("INFO", "app-sidecar", "daemon listening", { port: String(addr.port), host });
|
|
880
934
|
});
|
|
881
935
|
const shellPid = process.ppid;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
936
|
+
// Session teardown awaits MCP servers, LSP servers and third-party extension
|
|
937
|
+
// `deactivate()` hooks. Any can hang, so a deadline guarantees process exit.
|
|
938
|
+
const shutdown = installTerminationHandlers({
|
|
939
|
+
scope: "app-sidecar",
|
|
940
|
+
teardown: async () => {
|
|
941
|
+
clearInterval(parentWatch);
|
|
942
|
+
// Radio playback is app-wide (one stream across all windows).
|
|
943
|
+
stopRadio();
|
|
944
|
+
// Close the ~/.ezcoder progress fs.watch handle.
|
|
945
|
+
progress.dispose();
|
|
946
|
+
await Promise.all([...sessions.values()].map((c) => c.dispose().catch(() => { })));
|
|
947
|
+
server.close();
|
|
948
|
+
},
|
|
949
|
+
onTimeout: (timeoutMs) => {
|
|
950
|
+
// Radio is audible, so it must stop even when the rest is wedged.
|
|
951
|
+
stopRadio();
|
|
952
|
+
log("WARN", "app-sidecar", "daemon teardown hung; exiting on deadline", {
|
|
953
|
+
timeoutMs: String(timeoutMs),
|
|
954
|
+
sessions: String(sessions.size),
|
|
955
|
+
});
|
|
956
|
+
},
|
|
957
|
+
});
|
|
899
958
|
process.once("exit", stopRadio);
|
|
900
959
|
// Tauri can disappear without delivering a signal (force-quit, dev runner
|
|
901
960
|
// teardown, crash). Detect reparenting or a dead shell so the daemon and its
|
|
@@ -911,7 +970,7 @@ async function main() {
|
|
|
911
970
|
}
|
|
912
971
|
}
|
|
913
972
|
if (!parentAlive)
|
|
914
|
-
|
|
973
|
+
shutdown();
|
|
915
974
|
}, 1_000);
|
|
916
975
|
parentWatch.unref?.();
|
|
917
976
|
}
|
|
@@ -1177,7 +1236,7 @@ async function createSession(deps, opts) {
|
|
|
1177
1236
|
"Start it again and retry, or pick another model.");
|
|
1178
1237
|
}
|
|
1179
1238
|
// Turn any thrown value into the same clear headline/message/guidance shape
|
|
1180
|
-
// the TUI shows (see
|
|
1239
|
+
// the TUI shows (see @prestyj/ai's formatError) instead of a bare `err.message`, log
|
|
1181
1240
|
// the full detail, and broadcast it under `type` ("error" or "nolan_error").
|
|
1182
1241
|
// Without this the webview only ever saw a raw provider string like
|
|
1183
1242
|
// `400 {"code":"400",...}` with no "is this me or them / when does it reset"
|
|
@@ -1587,6 +1646,12 @@ async function createSession(deps, opts) {
|
|
|
1587
1646
|
durationMs: String(d.durationMs),
|
|
1588
1647
|
isError: String(d.isError),
|
|
1589
1648
|
...(d.isError ? { result: d.result.slice(0, 500) } : {}),
|
|
1649
|
+
// Consecutive-failure count for schema rejections. Attempt 1 followed by
|
|
1650
|
+
// a success means the model self-corrected; reaching 3 means it looped
|
|
1651
|
+
// and the turn was ended. Grep this to tell the two apart.
|
|
1652
|
+
...(d.invalidArgAttempt === undefined
|
|
1653
|
+
? {}
|
|
1654
|
+
: { invalidArgAttempt: String(d.invalidArgAttempt) }),
|
|
1590
1655
|
});
|
|
1591
1656
|
broadcast("tool_call_end", d);
|
|
1592
1657
|
// The agent can add/done/remove project tasks via the `tasks` tool during a
|
|
@@ -1610,12 +1675,25 @@ async function createSession(deps, opts) {
|
|
|
1610
1675
|
session.eventBus.on("agent_done", (d) => broadcast("agent_done", d));
|
|
1611
1676
|
// Non-clean stop (max_tokens/refusal/provider error) — info-style frame so
|
|
1612
1677
|
// the webview can warn instead of presenting truncated output as complete.
|
|
1613
|
-
|
|
1678
|
+
// empty_response is a hard failure (no output at all): route it through
|
|
1679
|
+
// broadcastError so the app renders an error row — the webview does not
|
|
1680
|
+
// render bare "truncated" frames.
|
|
1681
|
+
session.eventBus.on("truncated", (d) => {
|
|
1682
|
+
if (d.reason === "empty_response") {
|
|
1683
|
+
broadcastError("error", "empty response", new Error("The model returned an empty response after retries — try sending again."));
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
broadcast("truncated", d);
|
|
1687
|
+
});
|
|
1614
1688
|
session.eventBus.on("error", (d) => {
|
|
1615
1689
|
broadcastError("error", "agent error", d.error);
|
|
1616
1690
|
});
|
|
1617
1691
|
session.eventBus.on("model_change", (d) => broadcast("model_change", d));
|
|
1618
1692
|
session.eventBus.on("hook", (d) => broadcast("hook", d));
|
|
1693
|
+
// Fires BEFORE the candidate final answer streams. The webview holds assistant
|
|
1694
|
+
// text back while armed, so an Ideal review supersedes a draft that was never
|
|
1695
|
+
// painted instead of deleting one the user already started reading.
|
|
1696
|
+
session.eventBus.on("hook_armed", (d) => broadcast("hook_armed", d));
|
|
1619
1697
|
session.eventBus.on("subagent_state", (d) => broadcast("subagent_state", d));
|
|
1620
1698
|
session.eventBus.on("compaction_start", (d) => broadcast("compaction_start", d));
|
|
1621
1699
|
session.eventBus.on("compaction_end", (d) => broadcast("compaction_end", d));
|
|
@@ -2372,10 +2450,52 @@ async function createSession(deps, opts) {
|
|
|
2372
2450
|
// Native (Rust) writes to auth.json bypass this daemon's cache; re-read so
|
|
2373
2451
|
// the reported connection state matches what's actually on disk.
|
|
2374
2452
|
await auth.reload();
|
|
2375
|
-
const providers = await Promise.all(AUTH_PROVIDERS.map(async (p) =>
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2453
|
+
const providers = await Promise.all(AUTH_PROVIDERS.map(async (p) => {
|
|
2454
|
+
const dual = dualAuthProvider(p.value);
|
|
2455
|
+
// Which methods hold a credential right now. Dual-auth providers can hold
|
|
2456
|
+
// both at once, and the app needs them separately: one "connected" bit
|
|
2457
|
+
// cannot express "OAuth signed in, key also on file as backup", nor offer
|
|
2458
|
+
// a per-method disconnect.
|
|
2459
|
+
const oauthKey = dual?.oauthKey;
|
|
2460
|
+
const hasOAuth = oauthKey ? await auth.hasCredentials(oauthKey) : false;
|
|
2461
|
+
const apiKeyKeys = p.apiKeyVariants?.map((v) => v.key) ?? [p.value];
|
|
2462
|
+
const hasApiKey = p.methods.includes("apikey")
|
|
2463
|
+
? (await Promise.all(apiKeyKeys.map((k) => auth.hasCredentials(k)))).some(Boolean)
|
|
2464
|
+
: false;
|
|
2465
|
+
const connectedMethods = [];
|
|
2466
|
+
// OAuth-only providers (Anthropic/OpenAI/Gemini) store under the provider
|
|
2467
|
+
// id itself, so `hasProviderAuth` is what proves their OAuth connection.
|
|
2468
|
+
if (p.methods.includes("oauth") &&
|
|
2469
|
+
(hasOAuth || (!dual && (await auth.hasCredentials(p.value)))))
|
|
2470
|
+
connectedMethods.push("oauth");
|
|
2471
|
+
if (hasApiKey)
|
|
2472
|
+
connectedMethods.push("apikey");
|
|
2473
|
+
// Which one a request would actually use, mirroring AuthStorage's
|
|
2474
|
+
// resolution: OAuth wins unless its usage window is exhausted AND a key
|
|
2475
|
+
// is configured to cover it.
|
|
2476
|
+
const exhaustedUntil = oauthKey
|
|
2477
|
+
? ((await auth.getCredentials(oauthKey))?.usageExhaustedUntil ?? 0)
|
|
2478
|
+
: 0;
|
|
2479
|
+
const oauthSidelined = hasOAuth && Date.now() < exhaustedUntil && hasApiKey;
|
|
2480
|
+
const activeMethod = connectedMethods.includes("oauth")
|
|
2481
|
+
? oauthSidelined
|
|
2482
|
+
? "apikey"
|
|
2483
|
+
: "oauth"
|
|
2484
|
+
: connectedMethods[0];
|
|
2485
|
+
// `methodDetails` is the server-side lookup table behind
|
|
2486
|
+
// `methodGuidance` — shipping both would duplicate every string on the
|
|
2487
|
+
// wire for no consumer.
|
|
2488
|
+
const { methodDetails: _table, ...wireMeta } = p;
|
|
2489
|
+
return {
|
|
2490
|
+
...wireMeta,
|
|
2491
|
+
connected: await auth.hasProviderAuth(p.value),
|
|
2492
|
+
connectedMethods,
|
|
2493
|
+
...(activeMethod ? { activeMethod } : {}),
|
|
2494
|
+
...(oauthSidelined ? { oauthExhaustedUntil: exhaustedUntil } : {}),
|
|
2495
|
+
...(authPriorityNote(p.value) ? { priorityNote: authPriorityNote(p.value) } : {}),
|
|
2496
|
+
methodGuidance: describeAuthMethods(p.value),
|
|
2497
|
+
};
|
|
2498
|
+
}));
|
|
2379
2499
|
return { providers };
|
|
2380
2500
|
}
|
|
2381
2501
|
// Background tasks have no event source (the bash tool just spawns them), so
|
|
@@ -2448,7 +2568,6 @@ async function createSession(deps, opts) {
|
|
|
2448
2568
|
const payload = JSON.stringify(redactValue(body, { secrets: environmentSecrets(process.env) }));
|
|
2449
2569
|
res.writeHead(status, {
|
|
2450
2570
|
"content-type": "application/json",
|
|
2451
|
-
"access-control-allow-origin": "*",
|
|
2452
2571
|
});
|
|
2453
2572
|
res.end(payload);
|
|
2454
2573
|
}
|
|
@@ -2533,7 +2652,6 @@ async function createSession(deps, opts) {
|
|
|
2533
2652
|
"content-type": "text/event-stream",
|
|
2534
2653
|
"cache-control": "no-cache",
|
|
2535
2654
|
connection: "keep-alive",
|
|
2536
|
-
"access-control-allow-origin": "*",
|
|
2537
2655
|
});
|
|
2538
2656
|
res.write(`retry: 1000\n\n`);
|
|
2539
2657
|
const client = { id: ++clientSeq, res };
|
|
@@ -3299,7 +3417,7 @@ async function createSession(deps, opts) {
|
|
|
3299
3417
|
});
|
|
3300
3418
|
// After the user's run settles, kick off Nolan's auto-review loop — but
|
|
3301
3419
|
// only when the turn is actually reviewable (shouldStartAutopilotCycle):
|
|
3302
|
-
// workflow commands (/compare, /
|
|
3420
|
+
// workflow commands (/compare, /expand, …) end with reports or
|
|
3303
3421
|
// A/B/C choices reserved for the USER; registry commands (/help) and
|
|
3304
3422
|
// failed runs add no assistant work to judge; a turn that ended in plan
|
|
3305
3423
|
// mode has a pending Accept/Reject modal Nolan must not preempt. This is
|
|
@@ -4163,9 +4281,11 @@ async function createSession(deps, opts) {
|
|
|
4163
4281
|
creds = await loginOpenAI(cb);
|
|
4164
4282
|
else if (provider === "gemini")
|
|
4165
4283
|
creds = await loginGemini(cb);
|
|
4166
|
-
else if (provider === "moonshot") {
|
|
4167
|
-
|
|
4168
|
-
|
|
4284
|
+
else if (provider === "moonshot" || provider === "xai") {
|
|
4285
|
+
// Subscription OAuth (Kimi plan / SuperGrok-X Premium) stores under
|
|
4286
|
+
// a distinct key so it can coexist with the provider's API key.
|
|
4287
|
+
creds = provider === "moonshot" ? await loginKimi(cb) : await loginXai(cb);
|
|
4288
|
+
storageKey = dualAuthProvider(provider).oauthKey;
|
|
4169
4289
|
}
|
|
4170
4290
|
else {
|
|
4171
4291
|
throw new Error(`OAuth not implemented for ${provider}`);
|
|
@@ -4258,22 +4378,34 @@ async function createSession(deps, opts) {
|
|
|
4258
4378
|
if (raw === null)
|
|
4259
4379
|
return;
|
|
4260
4380
|
let provider;
|
|
4381
|
+
let logoutMethod;
|
|
4261
4382
|
try {
|
|
4262
|
-
|
|
4383
|
+
const body = JSON.parse(raw);
|
|
4384
|
+
provider = body.provider ?? "";
|
|
4385
|
+
logoutMethod =
|
|
4386
|
+
body.method === "oauth" || body.method === "apikey" ? body.method : undefined;
|
|
4263
4387
|
}
|
|
4264
4388
|
catch {
|
|
4265
4389
|
json(res, 400, { error: "invalid JSON body" });
|
|
4266
4390
|
return;
|
|
4267
4391
|
}
|
|
4268
|
-
|
|
4269
|
-
//
|
|
4270
|
-
//
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4392
|
+
const dual = dualAuthProvider(provider);
|
|
4393
|
+
// A dual-auth provider can be disconnected one method at a time: dropping
|
|
4394
|
+
// a spent API key should not sign the user out of their subscription, and
|
|
4395
|
+
// vice versa. Omitting `method` still clears everything (the plain
|
|
4396
|
+
// "Disconnect" action).
|
|
4397
|
+
if (logoutMethod !== "apikey") {
|
|
4398
|
+
await auth.clearCredentials(dual ? dual.oauthKey : provider);
|
|
4399
|
+
}
|
|
4400
|
+
if (logoutMethod !== "oauth") {
|
|
4401
|
+
// Non-dual providers store their only credential under the provider id,
|
|
4402
|
+
// so this covers both them and a dual provider's API key.
|
|
4403
|
+
await auth.clearCredentials(provider);
|
|
4404
|
+
// Xiaomi's API Credits credential lives under a distinct key — clear it
|
|
4405
|
+
// too so "disconnect" fully removes both the Token Plan and Credits keys.
|
|
4406
|
+
if (provider === "xiaomi")
|
|
4407
|
+
await auth.clearCredentials(XIAOMI_CREDITS_KEY);
|
|
4408
|
+
}
|
|
4277
4409
|
broadcast("auth_done", { provider });
|
|
4278
4410
|
json(res, 200, { ok: true });
|
|
4279
4411
|
});
|
|
@@ -4467,7 +4599,7 @@ async function createSession(deps, opts) {
|
|
|
4467
4599
|
// scope ignores it (always ~/.ezcoder/mcp.json).
|
|
4468
4600
|
if (method === "GET" && (url === "/mcp" || url.startsWith("/mcp?"))) {
|
|
4469
4601
|
const targetCwd = new URL(url, `http://${host}`).searchParams.get("cwd") ?? cwd;
|
|
4470
|
-
void buildMcpRows(targetCwd)
|
|
4602
|
+
void buildMcpRows(targetCwd, paths.settingsFile)
|
|
4471
4603
|
.then((servers) => json(res, 200, { servers }))
|
|
4472
4604
|
.catch((err) => {
|
|
4473
4605
|
captureSidecarError(err, "app-sidecar.mcp.list");
|
|
@@ -4519,6 +4651,12 @@ async function createSession(deps, opts) {
|
|
|
4519
4651
|
json(res, 400, { error: saved.error });
|
|
4520
4652
|
return;
|
|
4521
4653
|
}
|
|
4654
|
+
// Adding a project-scope server is an explicit trust signal — the
|
|
4655
|
+
// user chose to put a server in this repo's .ezcoder/mcp.json. Auto-trust
|
|
4656
|
+
// the project so all project-scope servers connect on next load.
|
|
4657
|
+
if (scope === "project") {
|
|
4658
|
+
await session.trustProject(targetCwd);
|
|
4659
|
+
}
|
|
4522
4660
|
json(res, 200, {
|
|
4523
4661
|
ok: true,
|
|
4524
4662
|
name: config.name,
|