@gajae-code/coding-agent 0.10.2 → 0.11.1
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/CHANGELOG.md +58 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/async/job-manager.d.ts +46 -7
- package/dist/types/cli/args.d.ts +4 -5
- package/dist/types/cli/daemon-cli.d.ts +12 -1
- package/dist/types/cli/notify-cli.d.ts +21 -1
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/notify.d.ts +28 -1
- package/dist/types/commands/sdk.d.ts +33 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
- package/dist/types/config/model-profile-activation.d.ts +35 -15
- package/dist/types/config/model-profiles.d.ts +11 -5
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/model-resolver.d.ts +39 -6
- package/dist/types/config/model-selector-value.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +10 -6
- package/dist/types/config/settings-schema.d.ts +133 -6
- package/dist/types/config/settings.d.ts +63 -35
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
- package/dist/types/coordinator-mcp/server.d.ts +6 -49
- package/dist/types/daemon/builtin.d.ts +6 -5
- package/dist/types/daemon/control-types.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +12 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
- package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +10 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -3
- package/dist/types/extensibility/extensions/types.d.ts +141 -16
- package/dist/types/extensibility/hooks/types.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
- package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
- package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
- package/dist/types/harness-control-plane/operate.d.ts +5 -5
- package/dist/types/harness-control-plane/owner.d.ts +18 -4
- package/dist/types/harness-control-plane/receipts.d.ts +0 -1
- package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
- package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
- package/dist/types/harness-control-plane/types.d.ts +3 -4
- package/dist/types/lsp/index.d.ts +1 -1
- package/dist/types/main.d.ts +32 -38
- package/dist/types/modes/acp/acp-agent.d.ts +224 -53
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
- package/dist/types/modes/acp/acp-mode.d.ts +6 -15
- package/dist/types/modes/acp/permission-mode.d.ts +4 -0
- package/dist/types/modes/acp/startup-options.d.ts +6 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -4
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
- package/dist/types/modes/index.d.ts +0 -4
- package/dist/types/modes/interactive-mode.d.ts +5 -2
- package/dist/types/modes/runtime-init.d.ts +2 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
- package/dist/types/modes/types.d.ts +7 -2
- package/dist/types/runtime-mcp/client.d.ts +2 -0
- package/dist/types/runtime-mcp/config.d.ts +5 -1
- package/dist/types/runtime-mcp/manager.d.ts +8 -1
- package/dist/types/runtime-mcp/types.d.ts +4 -0
- package/dist/types/sdk/acp/adapter.d.ts +67 -0
- package/dist/types/sdk/acp/index.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +53 -0
- package/dist/types/sdk/broker/discovery.d.ts +30 -0
- package/dist/types/sdk/broker/ensure.d.ts +42 -0
- package/dist/types/sdk/broker/identity.d.ts +3 -0
- package/dist/types/sdk/broker/index.d.ts +8 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
- package/dist/types/sdk/broker/runtime.d.ts +33 -0
- package/dist/types/sdk/broker/session-index.d.ts +57 -0
- package/dist/types/sdk/broker/state-version.d.ts +8 -0
- package/dist/types/sdk/broker/transport.d.ts +9 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
- package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
- package/dist/types/sdk/bus/config.d.ts +274 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
- package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
- package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
- package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
- package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
- package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
- package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
- package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
- package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
- package/dist/types/sdk/bus/session-control.d.ts +83 -0
- package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
- package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
- package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
- package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/session-cli.d.ts +19 -0
- package/dist/types/sdk/client/client.d.ts +1 -0
- package/dist/types/sdk/client/discovery.d.ts +27 -0
- package/dist/types/sdk/client/index.d.ts +2 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
- package/dist/types/sdk/host/control/index.d.ts +2 -0
- package/dist/types/sdk/host/control/operations.d.ts +65 -0
- package/dist/types/sdk/host/events.d.ts +35 -0
- package/dist/types/sdk/host/host.d.ts +35 -0
- package/dist/types/sdk/host/index.d.ts +4 -0
- package/dist/types/sdk/host/query/cursor.d.ts +62 -0
- package/dist/types/sdk/host/query/handlers.d.ts +70 -0
- package/dist/types/sdk/host/query/index.d.ts +3 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
- package/dist/types/sdk/host/types.d.ts +32 -0
- package/dist/types/sdk/index.d.ts +6 -0
- package/dist/types/sdk/lifecycle-session.d.ts +14 -0
- package/dist/types/sdk/mcp/index.d.ts +1 -0
- package/dist/types/sdk/mcp/server.d.ts +37 -0
- package/dist/types/sdk/models.d.ts +44 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
- package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
- package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
- package/dist/types/sdk/startup-capability.d.ts +50 -0
- package/dist/types/session/agent-session.d.ts +114 -21
- package/dist/types/session/default-model-selection.d.ts +25 -0
- package/dist/types/session/fallback-chain-controller.d.ts +52 -0
- package/dist/types/session/session-manager.d.ts +58 -1
- package/dist/types/setup/credential-auto-import.d.ts +36 -6
- package/dist/types/tools/ask-answer-registry.d.ts +1 -1
- package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
- package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
- package/dist/types/tools/browser/launch.d.ts +22 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
- package/dist/types/tools/browser/profile-posture.d.ts +37 -0
- package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
- package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
- package/dist/types/tools/browser/registry.d.ts +19 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +8 -8
- package/dist/types/tools/subagent-render.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +6 -1
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +99 -0
- package/scripts/capture-notifications-settings-showcase.ts +435 -0
- package/scripts/compile-args.ts +4 -2
- package/scripts/g005-daemon-smoke.ts +4 -5
- package/scripts/g011-daemon-path-smoke.ts +5 -5
- package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
- package/scripts/generate-sdk-operation-inventory.ts +867 -0
- package/scripts/generate-telegram-baseline-manifest.ts +128 -0
- package/scripts/manifest-schema.ts +124 -0
- package/scripts/run-test-manifest.ts +153 -0
- package/scripts/run-threat-model-check.ts +157 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
- package/scripts/verify-gjc-sdk-rename.ts +90 -0
- package/src/append-only-mode.ts +1 -1
- package/src/async/job-manager.ts +406 -63
- package/src/cli/args.ts +43 -12
- package/src/cli/auth-gateway-cli.ts +2 -2
- package/src/cli/config-cli.ts +2 -1
- package/src/cli/daemon-cli.ts +63 -14
- package/src/cli/list-models.ts +1 -1
- package/src/cli/notify-cli.ts +288 -286
- package/src/cli.ts +21 -2
- package/src/commands/daemon.ts +50 -6
- package/src/commands/harness.ts +93 -36
- package/src/commands/launch.ts +5 -2
- package/src/commands/mcp-serve.ts +19 -12
- package/src/commands/notify.ts +36 -3
- package/src/commands/sdk.ts +426 -0
- package/src/commit/agentic/agent.ts +1 -0
- package/src/config/atomic-yaml-patch.ts +423 -0
- package/src/config/model-profile-activation.ts +240 -89
- package/src/config/model-profiles.ts +18 -15
- package/src/config/model-registry.ts +51 -26
- package/src/config/model-resolver.ts +138 -51
- package/src/config/model-selector-value.ts +50 -0
- package/src/config/models-config-schema.ts +14 -21
- package/src/config/settings-schema.ts +128 -10
- package/src/config/settings.ts +1120 -158
- package/src/coordinator-mcp/model-preset.ts +74 -20
- package/src/coordinator-mcp/server.ts +1597 -3052
- package/src/daemon/builtin.ts +8 -5
- package/src/daemon/control-types.ts +1 -1
- package/src/defaults/gjc/skills/team/SKILL.md +4 -4
- package/src/discovery/mcp-json.ts +327 -20
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/compact-handler.ts +3 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -2
- package/src/extensibility/extensions/loader.ts +69 -5
- package/src/extensibility/extensions/runner.ts +112 -4
- package/src/extensibility/extensions/types.ts +176 -17
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/gjc-runtime/launch-tmux.ts +170 -86
- package/src/gjc-runtime/psmux-detect.ts +82 -4
- package/src/gjc-runtime/session-state-sidecar.ts +41 -31
- package/src/gjc-runtime/team-runtime.ts +54 -35
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
- package/src/gjc-runtime/tmux-sessions.ts +19 -13
- package/src/gjc-runtime/ultragoal-guard.ts +108 -14
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
- package/src/gjc-runtime/windows-powershell-command.ts +58 -0
- package/src/harness-control-plane/operate.ts +9 -9
- package/src/harness-control-plane/owner.ts +283 -39
- package/src/harness-control-plane/receipts.ts +0 -1
- package/src/harness-control-plane/sdk-transport.ts +395 -0
- package/src/harness-control-plane/session-transport.ts +94 -0
- package/src/harness-control-plane/types.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +34 -35
- package/src/lsp/client.ts +42 -6
- package/src/lsp/index.ts +2 -2
- package/src/main.ts +299 -204
- package/src/modes/DESIGN.md +258 -0
- package/src/modes/acp/acp-agent.ts +1228 -2612
- package/src/modes/acp/acp-client-bridge.ts +2 -20
- package/src/modes/acp/acp-event-mapper.ts +18 -2
- package/src/modes/acp/acp-mode.ts +8 -36
- package/src/modes/acp/permission-mode.ts +25 -0
- package/src/modes/acp/startup-options.ts +6 -0
- package/src/modes/components/agent-dashboard.ts +37 -17
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/settings-selector.ts +60 -11
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +10 -17
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +396 -28
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +87 -36
- package/src/modes/runtime-init.ts +298 -6
- package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
- package/src/modes/shared/agent-wire/event-contract.ts +7 -8
- package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
- package/src/modes/shared/agent-wire/event-observation.ts +16 -7
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
- package/src/modes/types.ts +7 -2
- package/src/runtime-mcp/client.ts +94 -19
- package/src/runtime-mcp/config.ts +27 -15
- package/src/runtime-mcp/manager.ts +343 -105
- package/src/runtime-mcp/oauth-flow.ts +42 -12
- package/src/runtime-mcp/transports/http.ts +49 -19
- package/src/runtime-mcp/transports/stdio.ts +47 -28
- package/src/runtime-mcp/types.ts +10 -0
- package/src/sdk/acp/adapter.ts +418 -0
- package/src/sdk/acp/index.ts +2 -0
- package/src/sdk/broker/broker.ts +642 -0
- package/src/sdk/broker/discovery.ts +113 -0
- package/src/sdk/broker/ensure.ts +307 -0
- package/src/sdk/broker/identity.ts +42 -0
- package/src/sdk/broker/index.ts +8 -0
- package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
- package/src/sdk/broker/internal-source.bunfig.toml +1 -0
- package/src/sdk/broker/lifecycle-ledger.ts +286 -0
- package/src/sdk/broker/lifecycle.ts +2157 -0
- package/src/sdk/broker/process-incarnation.ts +159 -0
- package/src/sdk/broker/runtime.ts +164 -0
- package/src/sdk/broker/session-index.ts +318 -0
- package/src/sdk/broker/state-version.ts +23 -0
- package/src/sdk/broker/transport.ts +125 -0
- package/src/sdk/bus/chat-command-policy.ts +107 -0
- package/src/sdk/bus/chat-daemon-cli.ts +214 -0
- package/src/sdk/bus/chat-daemon-control.ts +713 -0
- package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
- package/src/sdk/bus/chat-effect-journal.ts +355 -0
- package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
- package/src/sdk/bus/config.ts +433 -0
- package/src/sdk/bus/conversation-store.ts +391 -0
- package/src/sdk/bus/discord-conversation.ts +85 -0
- package/src/sdk/bus/discord-daemon.ts +2292 -0
- package/src/sdk/bus/discord-live-provider.ts +521 -0
- package/src/sdk/bus/discord-provider.ts +56 -0
- package/src/{notifications → sdk/bus}/html-format.ts +2 -2
- package/src/sdk/bus/index.ts +3979 -0
- package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
- package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
- package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
- package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
- package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
- package/src/sdk/bus/natives-augment.d.ts +38 -0
- package/src/sdk/bus/notification-orchestration.ts +535 -0
- package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
- package/src/sdk/bus/session-control.ts +333 -0
- package/src/sdk/bus/slack-conversation.ts +74 -0
- package/src/sdk/bus/slack-daemon.ts +2144 -0
- package/src/sdk/bus/slack-live-provider.ts +380 -0
- package/src/sdk/bus/slack-provider.ts +76 -0
- package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
- package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
- package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
- package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
- package/src/sdk/bus/telegram-setup.ts +663 -0
- package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/session-cli.ts +275 -0
- package/src/sdk/client/client.ts +1 -0
- package/src/sdk/client/discovery.ts +108 -0
- package/src/sdk/client/index.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +367 -0
- package/src/sdk/host/control/index.ts +10 -0
- package/src/sdk/host/control/operations.ts +63 -0
- package/src/sdk/host/events.ts +91 -0
- package/src/sdk/host/host.ts +296 -0
- package/src/sdk/host/index.ts +4 -0
- package/src/sdk/host/query/cursor.ts +189 -0
- package/src/sdk/host/query/handlers.ts +533 -0
- package/src/sdk/host/query/index.ts +3 -0
- package/src/sdk/host/query/revision-store.ts +1126 -0
- package/src/sdk/host/reverse-leases.ts +325 -0
- package/src/sdk/host/types.ts +29 -0
- package/src/sdk/index.ts +13 -0
- package/src/sdk/lifecycle-session.ts +39 -0
- package/src/sdk/mcp/index.ts +1 -0
- package/src/sdk/mcp/server.ts +332 -0
- package/src/sdk/models.ts +168 -0
- package/src/sdk/protocol/adapter-validation.ts +48 -0
- package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
- package/src/sdk/protocol/operation-registry.ts +312 -0
- package/src/{sdk.ts → sdk/session.ts} +339 -212
- package/src/sdk/startup-capability.ts +189 -0
- package/src/session/agent-session.ts +2650 -944
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +438 -11
- package/src/session/session-storage.ts +8 -1
- package/src/setup/credential-auto-import.ts +290 -35
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/executor.ts +62 -13
- package/src/task/index.ts +26 -16
- package/src/tools/ask-answer-registry.ts +1 -1
- package/src/tools/ask.ts +13 -8
- package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
- package/src/tools/browser/benchmark/detector-report.ts +157 -0
- package/src/tools/browser/benchmark/run-suite.ts +39 -0
- package/src/tools/browser/launch.ts +124 -19
- package/src/tools/browser/profile-discovery.ts +63 -0
- package/src/tools/browser/profile-posture.ts +59 -0
- package/src/tools/browser/profile-reuse.ts +102 -0
- package/src/tools/browser/profile-warmup.ts +109 -0
- package/src/tools/browser/registry.ts +87 -11
- package/src/tools/browser/tab-protocol.ts +1 -0
- package/src/tools/browser/tab-supervisor.ts +1 -0
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +6 -0
- package/src/tools/index.ts +8 -8
- package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
- package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
- package/src/tools/subagent-render.ts +19 -8
- package/src/tools/subagent.ts +84 -32
- package/src/tools/telegram-send.ts +2 -2
- package/vendor/insane-search/MANIFEST.json +2 -1
- package/vendor/insane-search/engine/bias_check.py +4 -1
- package/vendor/insane-search/engine/phase0.py +26 -1
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
- package/dist/types/modes/bridge/auth.d.ts +0 -12
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
- package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
- package/dist/types/modes/bridge/event-stream.d.ts +0 -8
- package/dist/types/modes/rpc/host-tools.d.ts +0 -1
- package/dist/types/modes/rpc/host-uris.d.ts +0 -1
- package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
- package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
- package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
- package/dist/types/notifications/config.d.ts +0 -132
- package/src/harness-control-plane/rpc-adapter.ts +0 -290
- package/src/modes/bridge/auth.ts +0 -41
- package/src/modes/bridge/bridge-client-bridge.ts +0 -47
- package/src/modes/bridge/bridge-mode.ts +0 -675
- package/src/modes/bridge/bridge-ui-context.ts +0 -200
- package/src/modes/bridge/event-stream.ts +0 -70
- package/src/modes/rpc/host-tools.ts +0 -1
- package/src/modes/rpc/host-uris.ts +0 -1
- package/src/modes/rpc/rpc-client.ts +0 -1166
- package/src/modes/rpc/rpc-mode.ts +0 -1029
- package/src/modes/rpc/rpc-socket-security.ts +0 -115
- package/src/modes/rpc/rpc-types.ts +0 -637
- package/src/modes/shared/agent-wire/command-contract.ts +0 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
- package/src/modes/shared/agent-wire/command-validation.ts +0 -181
- package/src/modes/shared/agent-wire/handshake.ts +0 -157
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
- package/src/modes/shared/agent-wire/protocol.ts +0 -46
- package/src/modes/shared/agent-wire/responses.ts +0 -17
- package/src/modes/shared/agent-wire/scopes.ts +0 -94
- package/src/modes/shared/agent-wire/session-registry.ts +0 -109
- package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
- package/src/modes/shared/agent-wire/ui-result.ts +0 -48
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
- package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
- package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
- package/src/notifications/config.ts +0 -219
- package/src/notifications/index.ts +0 -1835
- package/src/notifications/telegram-daemon-cli.ts +0 -243
- package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
- /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
- /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
- /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
- /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
- /package/src/{notifications → sdk/bus}/engine.ts +0 -0
- /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
- /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
- /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
- /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
- /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
1
2
|
import { ThinkingLevel } from "@gajae-code/agent-core";
|
|
2
3
|
import { getOAuthProviders } from "@gajae-code/ai/utils/oauth";
|
|
3
4
|
import type { OAuthProvider } from "@gajae-code/ai/utils/oauth/types";
|
|
4
5
|
import type { Component, OverlayHandle } from "@gajae-code/tui";
|
|
5
6
|
import { Input, isPetMode, Loader, Spacer, Text } from "@gajae-code/tui";
|
|
6
|
-
import { getAgentDbPath, getProjectDir } from "@gajae-code/utils";
|
|
7
|
+
import { getAgentDbPath, getProjectDir, logger, VERSION } from "@gajae-code/utils";
|
|
7
8
|
import {
|
|
8
9
|
activateModelProfile,
|
|
9
10
|
type MaterializeModelProfileForDeletionResult,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
import { formatModelProfileDisplayLabel, recommendModelProfileForProvider } from "../../config/model-profiles";
|
|
16
17
|
import { GJC_MODEL_ASSIGNMENT_TARGETS, type GjcModelAssignmentTargetId } from "../../config/model-registry";
|
|
17
18
|
import { formatModelSelectorValue } from "../../config/model-resolver";
|
|
19
|
+
import { selectorHead } from "../../config/model-selector-value";
|
|
18
20
|
import type { ModelProfileConfig } from "../../config/models-config-schema";
|
|
19
21
|
import { type Settings, settings } from "../../config/settings";
|
|
20
22
|
import { DebugSelectorComponent } from "../../debug";
|
|
@@ -40,10 +42,48 @@ import {
|
|
|
40
42
|
theme,
|
|
41
43
|
} from "../../modes/theme/theme";
|
|
42
44
|
import type { InteractiveModeContext, OAuthSelectorOptions } from "../../modes/types";
|
|
45
|
+
import { getNotificationConfig, maskToken } from "../../sdk/bus/config";
|
|
46
|
+
import {
|
|
47
|
+
clearTelegramActivationMarker,
|
|
48
|
+
createTelegramActivationMarker,
|
|
49
|
+
observedTelegramActivationMarker,
|
|
50
|
+
persistTelegramActivationMarker,
|
|
51
|
+
proposedTelegramIdentity,
|
|
52
|
+
reconcileCommittedTelegramConfiguration,
|
|
53
|
+
removeTelegramConfiguration,
|
|
54
|
+
saveTelegramInactive,
|
|
55
|
+
} from "../../sdk/bus/notification-orchestration";
|
|
56
|
+
import {
|
|
57
|
+
buildNotificationStatusReport,
|
|
58
|
+
checkNotificationHealth,
|
|
59
|
+
recoverNotifications,
|
|
60
|
+
sanitizeDiagnostic,
|
|
61
|
+
sendNotificationTest,
|
|
62
|
+
} from "../../sdk/bus/notification-service";
|
|
63
|
+
import type { NotificationSessionStatus } from "../../sdk/bus/session-control";
|
|
64
|
+
import {
|
|
65
|
+
ensureTelegramDaemonRunningDetailed,
|
|
66
|
+
readDaemonState,
|
|
67
|
+
unregisterNotificationRoot,
|
|
68
|
+
} from "../../sdk/bus/telegram-daemon";
|
|
69
|
+
import { TelegramDaemonController } from "../../sdk/bus/telegram-daemon-control";
|
|
70
|
+
import { runTelegramSetup, type TelegramSetupPreflight } from "../../sdk/bus/telegram-setup";
|
|
43
71
|
import { type SessionInfo, SessionManager } from "../../session/session-manager";
|
|
44
72
|
import { FileSessionStorage } from "../../session/session-storage";
|
|
45
73
|
import {
|
|
74
|
+
CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING,
|
|
75
|
+
CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING,
|
|
76
|
+
CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING,
|
|
77
|
+
CREDENTIAL_AUTO_IMPORT_RETRY_WARNING,
|
|
46
78
|
CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING,
|
|
79
|
+
CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING,
|
|
80
|
+
type CredentialAutoImportStateReadResult,
|
|
81
|
+
type CredentialAutoImportStateStore,
|
|
82
|
+
createCredentialAutoImportStateStore,
|
|
83
|
+
formatCredentialAutoImportCandidateLabel,
|
|
84
|
+
formatCredentialAutoImportPrompt,
|
|
85
|
+
isCredentialAutoImportStateResolvedForVersion,
|
|
86
|
+
logCredentialAutoImportFailures,
|
|
47
87
|
runExternalCredentialAutoImport,
|
|
48
88
|
} from "../../setup/credential-auto-import";
|
|
49
89
|
import {
|
|
@@ -78,6 +118,10 @@ import type { PetMode } from "../components/gajae-pet-widget";
|
|
|
78
118
|
import { HistorySearchComponent } from "../components/history-search";
|
|
79
119
|
import { JobsOverlayComponent } from "../components/jobs-overlay";
|
|
80
120
|
import { ModelSelectorComponent } from "../components/model-selector";
|
|
121
|
+
import type {
|
|
122
|
+
NotificationsEditorOperations,
|
|
123
|
+
PreparedTelegramConfiguration,
|
|
124
|
+
} from "../components/notifications-settings-editor";
|
|
81
125
|
import { OAuthSelectorComponent } from "../components/oauth-selector";
|
|
82
126
|
import { isPetAvailable } from "../components/pet-capability";
|
|
83
127
|
import { PetSelectorComponent } from "../components/pet-selector";
|
|
@@ -142,8 +186,512 @@ function formatProviderOnboardingCommandGuide(): string {
|
|
|
142
186
|
].join("\n");
|
|
143
187
|
}
|
|
144
188
|
|
|
189
|
+
export interface NotificationsEditorAdapterContext {
|
|
190
|
+
settings: Settings;
|
|
191
|
+
session: Pick<InteractiveModeContext["session"], "notificationSessionController">;
|
|
192
|
+
sessionManager: Pick<InteractiveModeContext["sessionManager"], "getCwd" | "getSessionId">;
|
|
193
|
+
notifyConfigChanged?: () => Promise<void> | void;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface NotificationsEditorOperationDependencies {
|
|
197
|
+
getNotificationConfig: typeof getNotificationConfig;
|
|
198
|
+
maskToken: typeof maskToken;
|
|
199
|
+
buildNotificationStatusReport: typeof buildNotificationStatusReport;
|
|
200
|
+
checkNotificationHealth: typeof checkNotificationHealth;
|
|
201
|
+
sendNotificationTest: typeof sendNotificationTest;
|
|
202
|
+
recoverNotifications: typeof recoverNotifications;
|
|
203
|
+
sanitizeDiagnostic: typeof sanitizeDiagnostic;
|
|
204
|
+
ensureTelegramDaemonRunningDetailed: typeof ensureTelegramDaemonRunningDetailed;
|
|
205
|
+
runTelegramSetup: typeof runTelegramSetup;
|
|
206
|
+
proposedTelegramIdentity: typeof proposedTelegramIdentity;
|
|
207
|
+
reconcileCommittedTelegramConfiguration: typeof reconcileCommittedTelegramConfiguration;
|
|
208
|
+
saveTelegramInactive: typeof saveTelegramInactive;
|
|
209
|
+
removeTelegramConfiguration: typeof removeTelegramConfiguration;
|
|
210
|
+
unregisterNotificationRoot: typeof unregisterNotificationRoot;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const notificationEditorOperationDependencies: NotificationsEditorOperationDependencies = {
|
|
214
|
+
getNotificationConfig,
|
|
215
|
+
maskToken,
|
|
216
|
+
buildNotificationStatusReport,
|
|
217
|
+
checkNotificationHealth,
|
|
218
|
+
sendNotificationTest,
|
|
219
|
+
recoverNotifications,
|
|
220
|
+
sanitizeDiagnostic,
|
|
221
|
+
ensureTelegramDaemonRunningDetailed,
|
|
222
|
+
runTelegramSetup,
|
|
223
|
+
proposedTelegramIdentity,
|
|
224
|
+
reconcileCommittedTelegramConfiguration,
|
|
225
|
+
saveTelegramInactive,
|
|
226
|
+
removeTelegramConfiguration,
|
|
227
|
+
unregisterNotificationRoot,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
function unavailableNotificationSessionStatus(): NotificationSessionStatus {
|
|
231
|
+
return {
|
|
232
|
+
eligible: false,
|
|
233
|
+
locallyEnabled: true,
|
|
234
|
+
effectiveEnabled: false,
|
|
235
|
+
running: false,
|
|
236
|
+
environment: "off",
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function unavailableNotificationSessionResult() {
|
|
241
|
+
return { outcome: "disabled" as const, status: unavailableNotificationSessionStatus() };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function notificationOperationError(
|
|
245
|
+
services: NotificationsEditorOperationDependencies,
|
|
246
|
+
error: unknown,
|
|
247
|
+
token?: string,
|
|
248
|
+
): Error {
|
|
249
|
+
return new Error(
|
|
250
|
+
services.sanitizeDiagnostic(error instanceof Error ? error.message : "Notification operation failed.", token),
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Concrete service adapter for the direct Notifications settings tab. Secrets remain in this closure's
|
|
256
|
+
* WeakMap and are never exposed through the editor's safe draft contract.
|
|
257
|
+
*/
|
|
258
|
+
export function createNotificationsEditorOperations(
|
|
259
|
+
ctx: NotificationsEditorAdapterContext,
|
|
260
|
+
overrides: Partial<NotificationsEditorOperationDependencies> = {},
|
|
261
|
+
): NotificationsEditorOperations {
|
|
262
|
+
const services = { ...notificationEditorOperationDependencies, ...overrides };
|
|
263
|
+
const drafts = new WeakMap<PreparedTelegramConfiguration, string>();
|
|
264
|
+
const sessionContext = () => ({ sessionManager: ctx.sessionManager });
|
|
265
|
+
const notifyAfterDurableCommit = async (): Promise<void> => {
|
|
266
|
+
await ctx.notifyConfigChanged?.();
|
|
267
|
+
};
|
|
268
|
+
const reconnect = async () =>
|
|
269
|
+
await services.ensureTelegramDaemonRunningDetailed({
|
|
270
|
+
settings: ctx.settings,
|
|
271
|
+
cwd: ctx.sessionManager.getCwd(),
|
|
272
|
+
sessionId: ctx.sessionManager.getSessionId(),
|
|
273
|
+
});
|
|
274
|
+
const telegramSetupPreflight = async (): Promise<TelegramSetupPreflight> => {
|
|
275
|
+
const storedChatId = services.getNotificationConfig(ctx.settings).chatId;
|
|
276
|
+
try {
|
|
277
|
+
const state = await readDaemonState(ctx.settings);
|
|
278
|
+
const validPid = Number.isSafeInteger(state?.pid) && (state?.pid ?? 0) > 0;
|
|
279
|
+
if (!state || !validPid) return { storedChatId };
|
|
280
|
+
let live = false;
|
|
281
|
+
try {
|
|
282
|
+
process.kill(state.pid, 0);
|
|
283
|
+
live = true;
|
|
284
|
+
} catch (error) {
|
|
285
|
+
live = (error as NodeJS.ErrnoException).code === "EPERM";
|
|
286
|
+
}
|
|
287
|
+
return live
|
|
288
|
+
? {
|
|
289
|
+
storedChatId,
|
|
290
|
+
daemon: {
|
|
291
|
+
live,
|
|
292
|
+
tokenFingerprint: typeof state.tokenFingerprint === "string" ? state.tokenFingerprint : undefined,
|
|
293
|
+
chatId: typeof state.chatId === "string" && state.chatId.trim() ? state.chatId.trim() : undefined,
|
|
294
|
+
},
|
|
295
|
+
}
|
|
296
|
+
: { storedChatId };
|
|
297
|
+
} catch {
|
|
298
|
+
return { storedChatId };
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
return {
|
|
303
|
+
loadState: async () => {
|
|
304
|
+
const config = services.getNotificationConfig(ctx.settings);
|
|
305
|
+
return {
|
|
306
|
+
status: services.buildNotificationStatusReport(ctx.settings),
|
|
307
|
+
session:
|
|
308
|
+
ctx.session.notificationSessionController?.query(sessionContext()) ??
|
|
309
|
+
unavailableNotificationSessionStatus(),
|
|
310
|
+
preferences: {
|
|
311
|
+
redact: config.redact,
|
|
312
|
+
verbosity: config.verbosity,
|
|
313
|
+
sessionScope: config.sessionScope,
|
|
314
|
+
richEnabled: config.rich.enabled,
|
|
315
|
+
richDraftEnabled: config.richDraft.enabled,
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
refreshHealth: async ({ probe, signal }) => {
|
|
321
|
+
if (signal?.aborted) throw new Error("Notification health refresh cancelled.");
|
|
322
|
+
try {
|
|
323
|
+
const input: Parameters<typeof checkNotificationHealth>[0] & { signal?: AbortSignal } = {
|
|
324
|
+
settings: ctx.settings,
|
|
325
|
+
stateRoot: path.join(ctx.sessionManager.getCwd(), ".gjc", "state"),
|
|
326
|
+
probe,
|
|
327
|
+
signal,
|
|
328
|
+
};
|
|
329
|
+
const report = await services.checkNotificationHealth(input);
|
|
330
|
+
if (signal?.aborted) throw new Error("Notification health refresh cancelled.");
|
|
331
|
+
const token = services.getNotificationConfig(ctx.settings).botToken;
|
|
332
|
+
return {
|
|
333
|
+
...report,
|
|
334
|
+
checks: report.checks.map(check => ({
|
|
335
|
+
...check,
|
|
336
|
+
detail: services.sanitizeDiagnostic(check.detail, token),
|
|
337
|
+
})),
|
|
338
|
+
reachability: {
|
|
339
|
+
...report.reachability,
|
|
340
|
+
detail: services.sanitizeDiagnostic(report.reachability.detail, token),
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
} catch (error) {
|
|
344
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
sendTest: async () => {
|
|
349
|
+
try {
|
|
350
|
+
const result = await services.sendNotificationTest({ settings: ctx.settings });
|
|
351
|
+
return {
|
|
352
|
+
...result,
|
|
353
|
+
detail: services.sanitizeDiagnostic(
|
|
354
|
+
result.detail,
|
|
355
|
+
services.getNotificationConfig(ctx.settings).botToken,
|
|
356
|
+
),
|
|
357
|
+
};
|
|
358
|
+
} catch (error) {
|
|
359
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
recover: async () => {
|
|
364
|
+
try {
|
|
365
|
+
const result = await services.recoverNotifications({
|
|
366
|
+
settings: ctx.settings,
|
|
367
|
+
stateRoot: path.join(ctx.sessionManager.getCwd(), ".gjc", "state"),
|
|
368
|
+
});
|
|
369
|
+
return {
|
|
370
|
+
...result,
|
|
371
|
+
daemon: {
|
|
372
|
+
...result.daemon,
|
|
373
|
+
detail: services.sanitizeDiagnostic(
|
|
374
|
+
result.daemon.detail,
|
|
375
|
+
services.getNotificationConfig(ctx.settings).botToken,
|
|
376
|
+
),
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
} catch (error) {
|
|
380
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
reconnect: async () => {
|
|
385
|
+
try {
|
|
386
|
+
const result = await reconnect();
|
|
387
|
+
const controller = ctx.session.notificationSessionController;
|
|
388
|
+
if (result === "blocked_identity") {
|
|
389
|
+
await controller?.enterBlockedRuntime(sessionContext());
|
|
390
|
+
} else if (result === "spawned" || result === "reloaded" || result === "attached") {
|
|
391
|
+
await controller?.clearBlockedRuntime(sessionContext());
|
|
392
|
+
await controller?.reconcileCurrentSession(sessionContext());
|
|
393
|
+
}
|
|
394
|
+
return result;
|
|
395
|
+
} catch (error) {
|
|
396
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
|
|
400
|
+
preflightProposedIdentity: async (input, signal) => {
|
|
401
|
+
const token = input.token.consume();
|
|
402
|
+
const unknownIdentity = { status: "unknown" as const };
|
|
403
|
+
if (!token.trim()) {
|
|
404
|
+
return {
|
|
405
|
+
status: "error",
|
|
406
|
+
identity: unknownIdentity,
|
|
407
|
+
message: "Telegram bot token is required.",
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
const setup = await services.runTelegramSetup({
|
|
412
|
+
token,
|
|
413
|
+
chatId: input.chatId,
|
|
414
|
+
preflight: await telegramSetupPreflight(),
|
|
415
|
+
revalidatePreflight: async () => await telegramSetupPreflight(),
|
|
416
|
+
interactive: false,
|
|
417
|
+
signal,
|
|
418
|
+
deps: { fetchImpl: globalThis.fetch },
|
|
419
|
+
});
|
|
420
|
+
if (!setup.ok) {
|
|
421
|
+
return {
|
|
422
|
+
status: setup.status === "aborted" ? "aborted" : setup.status === "cancelled" ? "cancelled" : "error",
|
|
423
|
+
identity: unknownIdentity,
|
|
424
|
+
message: services.sanitizeDiagnostic(setup.detail, token),
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (signal.aborted) {
|
|
428
|
+
return {
|
|
429
|
+
status: "aborted",
|
|
430
|
+
identity: unknownIdentity,
|
|
431
|
+
message: "Telegram setup cancelled.",
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
const identity = await services.proposedTelegramIdentity({
|
|
435
|
+
settings: ctx.settings,
|
|
436
|
+
botToken: token,
|
|
437
|
+
chatId: setup.chatId,
|
|
438
|
+
chatDisplay: setup.chatId,
|
|
439
|
+
});
|
|
440
|
+
if (signal.aborted) {
|
|
441
|
+
return {
|
|
442
|
+
status: "aborted",
|
|
443
|
+
identity,
|
|
444
|
+
message: "Telegram setup cancelled.",
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
const draft: PreparedTelegramConfiguration = {
|
|
448
|
+
chatId: setup.chatId,
|
|
449
|
+
tokenMask: services.maskToken(token),
|
|
450
|
+
tokenFingerprint: setup.tokenFingerprint,
|
|
451
|
+
richEnabled: input.richEnabled,
|
|
452
|
+
richDraftEnabled: input.richDraftEnabled,
|
|
453
|
+
};
|
|
454
|
+
drafts.set(draft, token);
|
|
455
|
+
const pairingMessage =
|
|
456
|
+
setup.pairingSource === "discovered"
|
|
457
|
+
? "Telegram private chat discovered and validated."
|
|
458
|
+
: setup.pairingSource === "reused"
|
|
459
|
+
? "Stored Telegram private chat validated without polling."
|
|
460
|
+
: "Supplied Telegram private chat validated.";
|
|
461
|
+
return {
|
|
462
|
+
status: "ready",
|
|
463
|
+
identity,
|
|
464
|
+
draft,
|
|
465
|
+
pairingSource: setup.pairingSource,
|
|
466
|
+
message:
|
|
467
|
+
identity.status === "foreign" || identity.status === "unknown"
|
|
468
|
+
? `${pairingMessage} Activation is blocked by the current daemon identity.`
|
|
469
|
+
: pairingMessage,
|
|
470
|
+
};
|
|
471
|
+
} catch (error) {
|
|
472
|
+
return {
|
|
473
|
+
status: signal.aborted ? "aborted" : "error",
|
|
474
|
+
identity: unknownIdentity,
|
|
475
|
+
message: signal.aborted
|
|
476
|
+
? "Telegram setup cancelled."
|
|
477
|
+
: services.sanitizeDiagnostic(
|
|
478
|
+
error instanceof Error ? error.message : "Telegram setup failed.",
|
|
479
|
+
token,
|
|
480
|
+
),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
|
|
485
|
+
commitConfigure: async draft => {
|
|
486
|
+
const token = drafts.get(draft);
|
|
487
|
+
if (!token) throw new Error("The Telegram setup draft expired. Re-enter the masked bot token.");
|
|
488
|
+
try {
|
|
489
|
+
const inactiveMarkerToClear = observedTelegramActivationMarker(ctx.settings, token, draft.chatId);
|
|
490
|
+
const receipt = await ctx.settings.commitAtomicBatch([
|
|
491
|
+
{ path: "notifications.enabled", op: "set", value: true },
|
|
492
|
+
{ path: "notifications.telegram.botToken", op: "set", value: token },
|
|
493
|
+
{ path: "notifications.telegram.chatId", op: "set", value: draft.chatId },
|
|
494
|
+
{ path: "notifications.telegram.rich.enabled", op: "set", value: draft.richEnabled },
|
|
495
|
+
{ path: "notifications.telegram.richDraft.enabled", op: "set", value: draft.richDraftEnabled },
|
|
496
|
+
]);
|
|
497
|
+
drafts.delete(draft);
|
|
498
|
+
const activationMarker = createTelegramActivationMarker({
|
|
499
|
+
botToken: token,
|
|
500
|
+
chatId: draft.chatId,
|
|
501
|
+
state: "blocked",
|
|
502
|
+
reason: "identity_mismatch",
|
|
503
|
+
});
|
|
504
|
+
const controller = ctx.session.notificationSessionController;
|
|
505
|
+
const activation = await services.reconcileCommittedTelegramConfiguration({
|
|
506
|
+
receipt,
|
|
507
|
+
inactiveMarkerToClear,
|
|
508
|
+
activation: {
|
|
509
|
+
controller: controller
|
|
510
|
+
? {
|
|
511
|
+
enterBlockedRuntime: async () => await controller.enterBlockedRuntime(sessionContext()),
|
|
512
|
+
clearBlockedRuntime: async () => await controller.clearBlockedRuntime(sessionContext()),
|
|
513
|
+
reconcileCurrentSession: async () =>
|
|
514
|
+
await controller.reconcileCurrentSession(sessionContext()),
|
|
515
|
+
}
|
|
516
|
+
: {
|
|
517
|
+
enterBlockedRuntime: async () => undefined,
|
|
518
|
+
clearBlockedRuntime: async () => undefined,
|
|
519
|
+
reconcileCurrentSession: async () => undefined,
|
|
520
|
+
},
|
|
521
|
+
reconnect,
|
|
522
|
+
persistInactive: async marker => await persistTelegramActivationMarker(ctx.settings, marker),
|
|
523
|
+
clearInactive: async marker => await clearTelegramActivationMarker(ctx.settings, marker),
|
|
524
|
+
marker: activationMarker,
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
await notifyAfterDurableCommit();
|
|
528
|
+
if (activation.status === "blocked_identity") {
|
|
529
|
+
return {
|
|
530
|
+
status: "blocked_identity" as const,
|
|
531
|
+
receipt,
|
|
532
|
+
message: services.sanitizeDiagnostic(activation.message, token),
|
|
533
|
+
restore: async () => {
|
|
534
|
+
const restored = await activation.restore();
|
|
535
|
+
if (restored.status === "restored" || restored.status === "still_blocked") {
|
|
536
|
+
await notifyAfterDurableCommit();
|
|
537
|
+
}
|
|
538
|
+
return restored;
|
|
539
|
+
},
|
|
540
|
+
retainCommitted: () => activation.retainCommitted(),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
return {
|
|
544
|
+
status: "saved" as const,
|
|
545
|
+
receipt,
|
|
546
|
+
message: services.sanitizeDiagnostic("Telegram configuration saved and reconciled.", token),
|
|
547
|
+
};
|
|
548
|
+
} catch (error) {
|
|
549
|
+
throw notificationOperationError(services, error, token);
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
|
|
553
|
+
saveInactive: async draft => {
|
|
554
|
+
const token = drafts.get(draft);
|
|
555
|
+
if (!token) throw new Error("The Telegram setup draft expired. Re-enter the masked bot token.");
|
|
556
|
+
try {
|
|
557
|
+
const result = await services.saveTelegramInactive({
|
|
558
|
+
settings: ctx.settings,
|
|
559
|
+
botToken: token,
|
|
560
|
+
chatId: draft.chatId,
|
|
561
|
+
});
|
|
562
|
+
drafts.delete(draft);
|
|
563
|
+
await notifyAfterDurableCommit();
|
|
564
|
+
return {
|
|
565
|
+
status: "saved_inactive" as const,
|
|
566
|
+
receipt: result.receipt,
|
|
567
|
+
message: "Telegram configuration saved inactive; no runtime activation was requested.",
|
|
568
|
+
};
|
|
569
|
+
} catch (error) {
|
|
570
|
+
throw notificationOperationError(services, error, token);
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
|
|
574
|
+
discardConfigureDraft: draft => {
|
|
575
|
+
drafts.delete(draft);
|
|
576
|
+
},
|
|
577
|
+
|
|
578
|
+
enableGlobally: async () => {
|
|
579
|
+
try {
|
|
580
|
+
const receipt = await ctx.settings.commitAtomicBatch([
|
|
581
|
+
{ path: "notifications.enabled", op: "set", value: true },
|
|
582
|
+
]);
|
|
583
|
+
await notifyAfterDurableCommit();
|
|
584
|
+
return { receipt, message: "Global notifications enabled using stored configuration." };
|
|
585
|
+
} catch (error) {
|
|
586
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
disableGlobally: async () => {
|
|
591
|
+
try {
|
|
592
|
+
const receipt = await ctx.settings.commitAtomicBatch([
|
|
593
|
+
{ path: "notifications.enabled", op: "set", value: false },
|
|
594
|
+
]);
|
|
595
|
+
await notifyAfterDurableCommit();
|
|
596
|
+
return { receipt, message: "Global notifications disabled." };
|
|
597
|
+
} catch (error) {
|
|
598
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
removeTelegram: async () => {
|
|
603
|
+
const controller = ctx.session.notificationSessionController;
|
|
604
|
+
let runtimePrepared = false;
|
|
605
|
+
try {
|
|
606
|
+
const result = await services.removeTelegramConfiguration({
|
|
607
|
+
settings: ctx.settings,
|
|
608
|
+
removal: {
|
|
609
|
+
stopAndUnregister: async () => {
|
|
610
|
+
if (controller) await controller.enterBlockedRuntime(sessionContext());
|
|
611
|
+
runtimePrepared = true;
|
|
612
|
+
const unregistered = await services.unregisterNotificationRoot({
|
|
613
|
+
settings: ctx.settings,
|
|
614
|
+
cwd: ctx.sessionManager.getCwd(),
|
|
615
|
+
sessionId: ctx.sessionManager.getSessionId(),
|
|
616
|
+
});
|
|
617
|
+
if (unregistered.remainingRoots === 0) {
|
|
618
|
+
const stopped = await new TelegramDaemonController(ctx.settings).stop();
|
|
619
|
+
if (!stopped.ok) throw new Error(stopped.message);
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
});
|
|
624
|
+
if (runtimePrepared && controller) {
|
|
625
|
+
await controller.clearBlockedRuntime(sessionContext());
|
|
626
|
+
await controller.reconcileCurrentSession(sessionContext());
|
|
627
|
+
}
|
|
628
|
+
await notifyAfterDurableCommit();
|
|
629
|
+
return {
|
|
630
|
+
receipt: result.receipt,
|
|
631
|
+
globallyDisabled: result.globallyDisabled,
|
|
632
|
+
message: result.globallyDisabled
|
|
633
|
+
? "Telegram configuration removed and global notifications disabled."
|
|
634
|
+
: "Telegram configuration removed; Discord or Slack configuration was preserved.",
|
|
635
|
+
};
|
|
636
|
+
} catch (error) {
|
|
637
|
+
if (runtimePrepared) {
|
|
638
|
+
const restored = await reconnect();
|
|
639
|
+
if (restored !== "blocked_identity" && controller) {
|
|
640
|
+
await controller.clearBlockedRuntime(sessionContext());
|
|
641
|
+
await controller.reconcileCurrentSession(sessionContext());
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
|
|
648
|
+
setSessionLocal: async enabled => {
|
|
649
|
+
const controller = ctx.session.notificationSessionController;
|
|
650
|
+
if (!controller) return unavailableNotificationSessionResult();
|
|
651
|
+
try {
|
|
652
|
+
return await controller.setLocalEnabled(sessionContext(), enabled);
|
|
653
|
+
} catch (error) {
|
|
654
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
commitPreferences: async preferences => {
|
|
659
|
+
try {
|
|
660
|
+
const receipt = await ctx.settings.commitAtomicBatch([
|
|
661
|
+
{ path: "notifications.redact", op: "set", value: preferences.redact },
|
|
662
|
+
{ path: "notifications.verbosity", op: "set", value: preferences.verbosity },
|
|
663
|
+
{ path: "notifications.sessionScope", op: "set", value: preferences.sessionScope },
|
|
664
|
+
{ path: "notifications.telegram.rich.enabled", op: "set", value: preferences.richEnabled },
|
|
665
|
+
{ path: "notifications.telegram.richDraft.enabled", op: "set", value: preferences.richDraftEnabled },
|
|
666
|
+
]);
|
|
667
|
+
await notifyAfterDurableCommit();
|
|
668
|
+
return { receipt, message: "Notification preferences saved atomically." };
|
|
669
|
+
} catch (error) {
|
|
670
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
|
|
674
|
+
reconcileCurrentSession: async () => {
|
|
675
|
+
const controller = ctx.session.notificationSessionController;
|
|
676
|
+
if (!controller) return unavailableNotificationSessionResult();
|
|
677
|
+
try {
|
|
678
|
+
return await controller.reconcileCurrentSession(sessionContext());
|
|
679
|
+
} catch (error) {
|
|
680
|
+
throw notificationOperationError(services, error, services.getNotificationConfig(ctx.settings).botToken);
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
145
686
|
export class SelectorController {
|
|
146
|
-
|
|
687
|
+
#credentialAutoImportStateStore?: CredentialAutoImportStateStore;
|
|
688
|
+
|
|
689
|
+
constructor(
|
|
690
|
+
private ctx: InteractiveModeContext,
|
|
691
|
+
credentialAutoImportStateStore?: CredentialAutoImportStateStore,
|
|
692
|
+
) {
|
|
693
|
+
this.#credentialAutoImportStateStore = credentialAutoImportStateStore;
|
|
694
|
+
}
|
|
147
695
|
|
|
148
696
|
async #refreshOAuthProviderAuthState(): Promise<void> {
|
|
149
697
|
const oauthProviders = getOAuthProviders();
|
|
@@ -486,6 +1034,8 @@ export class SelectorController {
|
|
|
486
1034
|
showSettingsSelector(): void {
|
|
487
1035
|
getAvailableThemes().then(availableThemes => {
|
|
488
1036
|
this.showSelector(done => {
|
|
1037
|
+
const notificationsOperations = createNotificationsEditorOperations(this.ctx);
|
|
1038
|
+
|
|
489
1039
|
const selector = new SettingsSelectorComponent(
|
|
490
1040
|
{
|
|
491
1041
|
availableThinkingLevels: [...this.ctx.session.getAvailableThinkingLevels()],
|
|
@@ -493,7 +1043,6 @@ export class SelectorController {
|
|
|
493
1043
|
availableThemes,
|
|
494
1044
|
availableModelProfiles: [...this.ctx.session.modelRegistry.getModelProfiles().keys()],
|
|
495
1045
|
cwd: getProjectDir(),
|
|
496
|
-
petAvailable: isPetAvailable(),
|
|
497
1046
|
},
|
|
498
1047
|
{
|
|
499
1048
|
onChange: (id, value) => this.handleSettingChange(id, value),
|
|
@@ -516,7 +1065,6 @@ export class SelectorController {
|
|
|
516
1065
|
onPetPreview: mode => {
|
|
517
1066
|
this.ctx.previewPetMode(mode as PetMode);
|
|
518
1067
|
},
|
|
519
|
-
onPetCommit: mode => this.ctx.commitPetPreviewMode(mode as PetMode),
|
|
520
1068
|
onStatusLinePreview: previewSettings => {
|
|
521
1069
|
// Update status line with preview settings
|
|
522
1070
|
this.ctx.statusLine.updateSettings({
|
|
@@ -543,6 +1091,7 @@ export class SelectorController {
|
|
|
543
1091
|
this.ctx.ui.requestRender();
|
|
544
1092
|
},
|
|
545
1093
|
},
|
|
1094
|
+
notificationsOperations,
|
|
546
1095
|
);
|
|
547
1096
|
return { component: selector, focus: selector };
|
|
548
1097
|
});
|
|
@@ -594,7 +1143,6 @@ export class SelectorController {
|
|
|
594
1143
|
showPetSelector(): void {
|
|
595
1144
|
const stored = settings.get("pet.mode");
|
|
596
1145
|
const initial: PetMode = isPetMode(stored) ? stored : "off";
|
|
597
|
-
const available = isPetAvailable();
|
|
598
1146
|
this.showSelector(done => {
|
|
599
1147
|
// Live-preview via previewMode (no editor re-mount, so the overlay stays);
|
|
600
1148
|
// Enter commits + persists, Esc restores the initial skin.
|
|
@@ -611,7 +1159,7 @@ export class SelectorController {
|
|
|
611
1159
|
mode => {
|
|
612
1160
|
this.ctx.previewPetMode(mode);
|
|
613
1161
|
},
|
|
614
|
-
|
|
1162
|
+
isPetAvailable(),
|
|
615
1163
|
);
|
|
616
1164
|
return { component: selector, focus: selector.getSelectList() };
|
|
617
1165
|
});
|
|
@@ -665,7 +1213,7 @@ export class SelectorController {
|
|
|
665
1213
|
const dashboard = await AgentDashboard.create(getProjectDir(), this.ctx.settings, this.ctx.ui.terminal.rows, {
|
|
666
1214
|
modelRegistry: this.ctx.session.modelRegistry,
|
|
667
1215
|
activeModelPattern,
|
|
668
|
-
defaultModelPattern,
|
|
1216
|
+
defaultModelPattern: selectorHead(defaultModelPattern),
|
|
669
1217
|
});
|
|
670
1218
|
this.showSelector(done => {
|
|
671
1219
|
dashboard.onClose = () => {
|
|
@@ -767,6 +1315,12 @@ export class SelectorController {
|
|
|
767
1315
|
});
|
|
768
1316
|
break;
|
|
769
1317
|
}
|
|
1318
|
+
case "pet.mode":
|
|
1319
|
+
// The settings submenu already persisted the value; apply it to the live
|
|
1320
|
+
// widget via previewMode (the settings overlay is still open, so a full
|
|
1321
|
+
// re-mount would tear it down — restoreComposer re-mounts on close).
|
|
1322
|
+
this.ctx.previewPetMode(value as PetMode);
|
|
1323
|
+
break;
|
|
770
1324
|
case "symbolPreset": {
|
|
771
1325
|
setSymbolPreset(value as "unicode" | "nerd" | "ascii").then(() => {
|
|
772
1326
|
this.ctx.statusLine.invalidate();
|
|
@@ -941,7 +1495,13 @@ export class SelectorController {
|
|
|
941
1495
|
const { model, role, thinkingLevel, selector: selectedSelector } = selection;
|
|
942
1496
|
if (role === null) {
|
|
943
1497
|
// Temporary: update agent state but don't persist to settings
|
|
944
|
-
await this.ctx.session.setModelTemporary(model, thinkingLevel
|
|
1498
|
+
await this.ctx.session.setModelTemporary(model, thinkingLevel, {
|
|
1499
|
+
cause: "temporary-operation",
|
|
1500
|
+
reason: "other",
|
|
1501
|
+
});
|
|
1502
|
+
this.ctx.session.setDefaultFallbackRuntimeModel(
|
|
1503
|
+
selectedSelector ?? formatModelSelectorValue(`${model.provider}/${model.id}`, thinkingLevel),
|
|
1504
|
+
);
|
|
945
1505
|
this.ctx.statusLine.invalidate();
|
|
946
1506
|
this.ctx.updateEditorBorderColor();
|
|
947
1507
|
this.ctx.showStatus(`Temporary model: ${selectedSelector ?? model.id}`);
|
|
@@ -973,6 +1533,7 @@ export class SelectorController {
|
|
|
973
1533
|
await this.ctx.session.setModel(model, "default", {
|
|
974
1534
|
selector: defaultSelector,
|
|
975
1535
|
thinkingLevel,
|
|
1536
|
+
cause: "user-selection",
|
|
976
1537
|
});
|
|
977
1538
|
if (thinkingLevel && thinkingLevel !== ThinkingLevel.Inherit) {
|
|
978
1539
|
this.ctx.session.setThinkingLevel(thinkingLevel);
|
|
@@ -1018,6 +1579,7 @@ export class SelectorController {
|
|
|
1018
1579
|
await this.ctx.session.setModel(model, role, {
|
|
1019
1580
|
selector: selectedSelector,
|
|
1020
1581
|
thinkingLevel,
|
|
1582
|
+
cause: "user-selection",
|
|
1021
1583
|
});
|
|
1022
1584
|
const value = formatModelSelectorValue(
|
|
1023
1585
|
selectedSelector ?? `${model.provider}/${model.id}`,
|
|
@@ -1643,34 +2205,110 @@ export class SelectorController {
|
|
|
1643
2205
|
options?.allowExternalCredentialDiscovery === true &&
|
|
1644
2206
|
options.trigger === "bare-login"
|
|
1645
2207
|
) {
|
|
1646
|
-
const
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
},
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
2208
|
+
const stateStore =
|
|
2209
|
+
this.#credentialAutoImportStateStore ??
|
|
2210
|
+
createCredentialAutoImportStateStore(this.ctx.settings.getAgentDir());
|
|
2211
|
+
let stateRead: CredentialAutoImportStateReadResult | undefined;
|
|
2212
|
+
try {
|
|
2213
|
+
stateRead = await stateStore.read();
|
|
2214
|
+
} catch {
|
|
2215
|
+
logger.warn("Credential auto-import state read failed", { classification: "state-read-failed" });
|
|
2216
|
+
stateRead = { state: {}, problems: [], unreadable: true };
|
|
2217
|
+
}
|
|
2218
|
+
if (stateRead?.unreadable === true) {
|
|
2219
|
+
logger.warn("Credential auto-import state unavailable", { classification: "state-unreadable" });
|
|
2220
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING);
|
|
2221
|
+
} else if (stateRead && !isCredentialAutoImportStateResolvedForVersion(stateRead.state, VERSION)) {
|
|
2222
|
+
const preview = await runExternalCredentialAutoImport({
|
|
2223
|
+
authStorage: {
|
|
2224
|
+
importCredentialIfAbsent: async () => ({
|
|
2225
|
+
inserted: false,
|
|
2226
|
+
reason: "skipped-existing",
|
|
2227
|
+
provider: "",
|
|
2228
|
+
entries: [],
|
|
2229
|
+
}),
|
|
2230
|
+
},
|
|
2231
|
+
trigger: "bare-login",
|
|
2232
|
+
discover: options.externalCredentialDiscover,
|
|
2233
|
+
});
|
|
2234
|
+
if (!preview.discovered) {
|
|
2235
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
|
|
2236
|
+
} else {
|
|
2237
|
+
const result = preview.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
2238
|
+
const candidates = filterAutoImportOAuthCredentials(result.importable);
|
|
2239
|
+
const previewSourceFailures = preview.failures.filter(failure => failure.credential === undefined);
|
|
2240
|
+
if (candidates.length === 0 && previewSourceFailures.length > 0) {
|
|
2241
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
|
|
2242
|
+
} else if (candidates.length > 0) {
|
|
2243
|
+
const confirmed = await this.ctx.showHookConfirm(
|
|
2244
|
+
`Import ${candidates.length} external credential(s)?`,
|
|
2245
|
+
`${formatCredentialAutoImportPrompt(candidates)}\n\n${CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING}`,
|
|
2246
|
+
);
|
|
2247
|
+
if (!confirmed) {
|
|
2248
|
+
let persisted = false;
|
|
2249
|
+
try {
|
|
2250
|
+
persisted = await stateStore.write({ initialImportResolution: "declined" });
|
|
2251
|
+
} catch {
|
|
2252
|
+
logger.warn("Credential auto-import state persistence failed", {
|
|
2253
|
+
classification: "state-write-failed",
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2256
|
+
if (!persisted) this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
|
|
2257
|
+
} else {
|
|
2258
|
+
const summary = await runExternalCredentialAutoImport({
|
|
2259
|
+
authStorage: this.ctx.session.modelRegistry.authStorage,
|
|
2260
|
+
trigger: "bare-login",
|
|
2261
|
+
discover: options.externalCredentialDiscover,
|
|
2262
|
+
});
|
|
2263
|
+
if (!summary.discovered) {
|
|
2264
|
+
logCredentialAutoImportFailures("bare-login", summary.failures);
|
|
2265
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
|
|
2266
|
+
} else {
|
|
2267
|
+
const secondResult = summary.discovery ?? { importable: [], skipped: [], environment: [] };
|
|
2268
|
+
const secondCandidates = filterAutoImportOAuthCredentials(secondResult.importable);
|
|
2269
|
+
const secondSourceFailures = summary.failures.filter(
|
|
2270
|
+
failure => failure.credential === undefined,
|
|
2271
|
+
);
|
|
2272
|
+
const handledCandidates = summary.imported.length + summary.skipped.length > 0;
|
|
2273
|
+
if (handledCandidates || (secondCandidates.length === 0 && secondSourceFailures.length === 0)) {
|
|
2274
|
+
let persisted = false;
|
|
2275
|
+
try {
|
|
2276
|
+
persisted = await stateStore.write({ initialImportResolution: "accepted" });
|
|
2277
|
+
} catch {
|
|
2278
|
+
logger.warn("Credential auto-import state persistence failed", {
|
|
2279
|
+
classification: "state-write-failed",
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
if (!persisted) this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
|
|
2283
|
+
externalCredentialCandidates = summary.imported.map(credential => ({
|
|
2284
|
+
...credential,
|
|
2285
|
+
source: formatCredentialAutoImportCandidateLabel(credential),
|
|
2286
|
+
}));
|
|
2287
|
+
if (!handledCandidates) {
|
|
2288
|
+
this.ctx.showStatus("External credentials were no longer available to import.");
|
|
2289
|
+
}
|
|
2290
|
+
if (summary.imported.length > 0) {
|
|
2291
|
+
try {
|
|
2292
|
+
await this.ctx.session.modelRegistry.refresh("offline");
|
|
2293
|
+
} catch {
|
|
2294
|
+
logger.warn("Credential auto-import refresh failed", {
|
|
2295
|
+
classification: "refresh-failed",
|
|
2296
|
+
});
|
|
2297
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING);
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
if (handledCandidates && summary.failures.length > 0) {
|
|
2301
|
+
logCredentialAutoImportFailures("bare-login", summary.failures);
|
|
2302
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
|
|
2303
|
+
}
|
|
2304
|
+
} else if (secondCandidates.length > 0 && summary.failures.length > 0) {
|
|
2305
|
+
logCredentialAutoImportFailures("bare-login", summary.failures);
|
|
2306
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_RETRY_WARNING);
|
|
2307
|
+
} else {
|
|
2308
|
+
this.ctx.showWarning(CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
1674
2312
|
}
|
|
1675
2313
|
}
|
|
1676
2314
|
}
|