@gajae-code/coding-agent 0.13.3 → 0.14.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/CHANGELOG.md +184 -2
- package/README.md +2 -0
- package/bin/gajaessi.js +4 -0
- package/dist/types/async/job-manager.d.ts +55 -2
- package/dist/types/async/support.d.ts +14 -0
- package/dist/types/capability/mcp.d.ts +6 -0
- package/dist/types/capability/types.d.ts +6 -0
- package/dist/types/cli/accounts-cli.d.ts +19 -0
- package/dist/types/cli/args.d.ts +3 -0
- package/dist/types/cli/config-cli.d.ts +6 -0
- package/dist/types/cli/crash-cli.d.ts +10 -0
- package/dist/types/cli/customize-doctor.d.ts +145 -0
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/mcp-cli.d.ts +11 -0
- package/dist/types/cli/notify-cli.d.ts +1 -1
- package/dist/types/cli/root-flags.d.ts +12 -0
- package/dist/types/cli/setup-cli.d.ts +3 -1
- package/dist/types/cli/skills-cli.d.ts +2 -1
- package/dist/types/cli/update-cli.d.ts +19 -1
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/commands/accounts.d.ts +40 -0
- package/dist/types/commands/crash.d.ts +24 -0
- package/dist/types/commands/customize.d.ts +22 -0
- package/dist/types/commands/daemon.d.ts +1 -1
- package/dist/types/commands/launch.d.ts +6 -0
- package/dist/types/commands/setup.d.ts +6 -0
- package/dist/types/commands/skills.d.ts +6 -1
- package/dist/types/commands/update.d.ts +7 -0
- package/dist/types/config/atomic-yaml-patch-worker.d.ts +25 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +62 -2
- package/dist/types/config/config-schema-version.d.ts +10 -0
- package/dist/types/config/file-lock.d.ts +18 -0
- package/dist/types/config/model-profile-activation.d.ts +3 -1
- package/dist/types/config/model-registry.d.ts +9 -1
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +70 -6
- package/dist/types/config/settings.d.ts +63 -0
- package/dist/types/config/skill-settings-defaults.d.ts +26 -0
- package/dist/types/config/task-delegation.d.ts +39 -0
- package/dist/types/config/update-channel.d.ts +10 -0
- package/dist/types/coordinator-mcp/server.d.ts +5 -1
- package/dist/types/crash/index-store.d.ts +87 -0
- package/dist/types/crash/nudge.d.ts +50 -0
- package/dist/types/crash/record-loader.d.ts +17 -0
- package/dist/types/crash/report.d.ts +134 -0
- package/dist/types/crash/sanitize.d.ts +25 -0
- package/dist/types/cursor.d.ts +13 -2
- package/dist/types/customization/import.d.ts +37 -0
- package/dist/types/customization/index.d.ts +4 -0
- package/dist/types/customization/inventory.d.ts +25 -0
- package/dist/types/customization/mutations.d.ts +32 -0
- package/dist/types/customization/types.d.ts +115 -0
- package/dist/types/daemon/control-types.d.ts +8 -1
- package/dist/types/daemon/operator-contract.d.ts +4 -4
- package/dist/types/discovery/claude.d.ts +39 -1
- package/dist/types/discovery/codex.d.ts +39 -1
- package/dist/types/discovery/index.d.ts +2 -0
- package/dist/types/discovery/mcp-compat.d.ts +30 -0
- package/dist/types/edit/renderer.d.ts +23 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -0
- package/dist/types/extensibility/extensions/types.d.ts +21 -4
- package/dist/types/extensibility/gjc-plugins/observability.d.ts +6 -1
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +8 -1
- package/dist/types/extensibility/hooks/loader.d.ts +19 -5
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +22 -1
- package/dist/types/extensibility/skill-management.d.ts +107 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +3 -1
- package/dist/types/gjc-runtime/launch-worktree.d.ts +8 -0
- package/dist/types/gjc-runtime/linux-proc.d.ts +3 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +10 -6
- package/dist/types/gjc-runtime/session-state-lock.d.ts +104 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +120 -2
- package/dist/types/gjc-runtime/state-writer.d.ts +10 -1
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +4 -2
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -6
- package/dist/types/gjc-runtime/workflow-settings.d.ts +109 -0
- package/dist/types/hooks/events.d.ts +60 -0
- package/dist/types/hooks/normalize.d.ts +83 -0
- package/dist/types/hooks/skill-state.d.ts +9 -2
- package/dist/types/main.d.ts +1 -1
- package/dist/types/modes/acp/abort-scope.d.ts +13 -0
- package/dist/types/modes/acp/acp-agent.d.ts +7 -4
- package/dist/types/modes/components/customization/customization-dashboard.d.ts +44 -0
- package/dist/types/modes/components/customization/import-wizard.d.ts +21 -0
- package/dist/types/modes/components/customization/index.d.ts +1 -0
- package/dist/types/modes/components/gajae-pet-widget.d.ts +8 -30
- package/dist/types/modes/components/irc-sidebar.d.ts +1 -0
- package/dist/types/modes/components/iterm-pet-transport.d.ts +122 -0
- package/dist/types/modes/components/oauth-selector.d.ts +10 -4
- package/dist/types/modes/components/pet-capability.d.ts +11 -25
- package/dist/types/modes/components/status-line/gh.d.ts +6 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +7 -8
- package/dist/types/modes/controllers/stt-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -0
- package/dist/types/modes/utils/injected-user-submission.d.ts +10 -0
- package/dist/types/runtime-mcp/config.d.ts +9 -0
- package/dist/types/runtime-mcp/manager.d.ts +26 -1
- package/dist/types/runtime-mcp/oauth-discovery.d.ts +4 -0
- package/dist/types/runtime-mcp/oauth-flow.d.ts +24 -1
- package/dist/types/runtime-mcp/pool-key.d.ts +2 -0
- package/dist/types/runtime-mcp/protocol.d.ts +278 -0
- package/dist/types/runtime-mcp/scope-config.d.ts +29 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +15 -13
- package/dist/types/runtime-mcp/transports/http.d.ts +9 -0
- package/dist/types/runtime-mcp/types.d.ts +102 -10
- package/dist/types/sdk/acp/adapter.d.ts +26 -5
- package/dist/types/sdk/broker/broker.d.ts +3 -55
- package/dist/types/sdk/broker/lifecycle.d.ts +18 -12
- package/dist/types/sdk/broker/session-index.d.ts +14 -5
- package/dist/types/sdk/broker/startup-failure.d.ts +16 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +51 -1
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -41
- package/dist/types/sdk/bus/config.d.ts +11 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +0 -1
- package/dist/types/sdk/bus/daemon-paths.d.ts +6 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +2 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +17 -12
- package/dist/types/sdk/bus/existing-thread-readiness.d.ts +4 -34
- package/dist/types/sdk/bus/inbound-reaction-ordering.d.ts +61 -0
- package/dist/types/sdk/bus/index.d.ts +85 -99
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +29 -7
- package/dist/types/sdk/bus/managed-daemon.d.ts +2 -32
- package/dist/types/sdk/bus/notification-service.d.ts +52 -0
- package/dist/types/sdk/bus/operator-runtime.d.ts +1 -1
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +16 -5
- package/dist/types/sdk/bus/reconciliation-store.d.ts +113 -5
- package/dist/types/sdk/bus/session-control.d.ts +25 -1
- package/dist/types/sdk/bus/slack-conversation.d.ts +4 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +9 -17
- package/dist/types/sdk/bus/slack-live-provider.d.ts +3 -1
- package/dist/types/sdk/bus/slack-provider.d.ts +4 -0
- package/dist/types/sdk/bus/slack-thread-binding.d.ts +6 -40
- package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +30 -104
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +262 -19
- package/dist/types/sdk/bus/telegram-daemon-orphan-reap.d.ts +125 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +22 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +119 -310
- package/dist/types/sdk/bus/telegram-reference.d.ts +1 -47
- package/dist/types/sdk/bus/threaded-render.d.ts +1 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +33 -17
- package/dist/types/sdk/cli/rows.d.ts +2 -11
- package/dist/types/sdk/cli/session-cli.d.ts +15 -25
- package/dist/types/sdk/client/client.d.ts +97 -1
- package/dist/types/sdk/host/control/dispatch.d.ts +0 -7
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +18 -5
- package/dist/types/sdk/host/control/runtime-gate.d.ts +19 -0
- package/dist/types/sdk/host/host.d.ts +15 -1
- package/dist/types/sdk/host/query/handlers.d.ts +5 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
- package/dist/types/sdk/host/session-runtime.d.ts +127 -7
- package/dist/types/sdk/host/types.d.ts +1 -1
- package/dist/types/sdk/host/websocket-transport.d.ts +1 -1
- package/dist/types/sdk/index.d.ts +2 -1
- package/dist/types/sdk/lifecycle/broker-client.d.ts +8 -0
- package/dist/types/sdk/lifecycle/client.d.ts +59 -0
- package/dist/types/sdk/lifecycle/index.d.ts +3 -0
- package/dist/types/sdk/lifecycle/service.d.ts +232 -0
- package/dist/types/sdk/mcp/server.d.ts +9 -6
- package/dist/types/sdk/prompt-deadline-lease.d.ts +43 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +28 -0
- package/dist/types/sdk/prompt-status.d.ts +10 -3
- package/dist/types/sdk/protocol/operation-registry.d.ts +5 -0
- package/dist/types/sdk/receipt-state.d.ts +17 -0
- package/dist/types/sdk/reconciliation-extensions.d.ts +2 -0
- package/dist/types/sdk/router/index.d.ts +1 -0
- package/dist/types/sdk/router/session-router.d.ts +152 -0
- package/dist/types/sdk/session-list.d.ts +22 -0
- package/dist/types/sdk/session-reconnect.d.ts +43 -1
- package/dist/types/sdk/session.d.ts +34 -1
- package/dist/types/sdk/transport/serve-cli.d.ts +1 -4
- package/dist/types/session/account-inventory.d.ts +86 -0
- package/dist/types/session/agent-session.d.ts +145 -6
- package/dist/types/session/agent-storage.d.ts +10 -0
- package/dist/types/session/coordinator-tool-label.d.ts +28 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +23 -4
- package/dist/types/session/messages.d.ts +1 -1
- package/dist/types/session/secure-token-file.d.ts +3 -0
- package/dist/types/session/session-manager.d.ts +40 -1
- package/dist/types/session/startup-auth-config.d.ts +44 -0
- package/dist/types/session/terminal-abort.d.ts +378 -0
- package/dist/types/session/yield-queue.d.ts +7 -0
- package/dist/types/session-import/claude.d.ts +26 -0
- package/dist/types/session-import/codex.d.ts +88 -0
- package/dist/types/session-import/command.d.ts +35 -0
- package/dist/types/session-import/detect.d.ts +22 -0
- package/dist/types/session-import/index.d.ts +7 -0
- package/dist/types/session-import/provider-codex.d.ts +22 -0
- package/dist/types/session-import/provider-service.d.ts +38 -0
- package/dist/types/session-import/redact.d.ts +23 -0
- package/dist/types/session-import/service.d.ts +47 -0
- package/dist/types/session-import/types.d.ts +120 -0
- package/dist/types/setup/paseo/check.d.ts +16 -0
- package/dist/types/setup/paseo/install-saga.d.ts +115 -0
- package/dist/types/setup/paseo/json-publisher.d.ts +76 -0
- package/dist/types/setup/paseo/orchestration-preferences.d.ts +24 -0
- package/dist/types/setup/paseo/paseo-ownership.d.ts +87 -0
- package/dist/types/setup/paseo/paseo-setup.d.ts +29 -0
- package/dist/types/setup/paseo/provider-config.d.ts +35 -0
- package/dist/types/setup/paseo/remove.d.ts +14 -0
- package/dist/types/setup/paseo/result-types.d.ts +59 -0
- package/dist/types/setup/paseo/setup-deps.d.ts +73 -0
- package/dist/types/setup/paseo/skills-bridge.d.ts +44 -0
- package/dist/types/skill-state/active-state.d.ts +5 -1
- package/dist/types/slash-commands/acp-builtins.d.ts +5 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +2 -0
- package/dist/types/slash-commands/helpers/credential-switch.d.ts +12 -0
- package/dist/types/slash-commands/helpers/usage-report.d.ts +5 -6
- package/dist/types/slash-commands/types.d.ts +7 -1
- package/dist/types/task/executor.d.ts +10 -0
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/tools/ask-answer-registry.d.ts +6 -3
- package/dist/types/tools/bash-sleep-advisory.d.ts +14 -0
- package/dist/types/tools/bash.d.ts +2 -6
- package/dist/types/tools/browser/attach.d.ts +11 -0
- package/dist/types/tools/browser/launch.d.ts +20 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +6 -0
- package/dist/types/tools/browser/render.d.ts +1 -0
- package/dist/types/tools/browser.d.ts +3 -1
- package/dist/types/tools/image-gen.d.ts +9 -2
- package/dist/types/tools/index.d.ts +8 -0
- package/dist/types/tools/monitor.d.ts +1 -1
- package/dist/types/tools/skill-discovery.d.ts +8 -1
- package/dist/types/tools/subagent.d.ts +2 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +2 -2
- package/dist/types/utils/herdr-pane.d.ts +76 -0
- package/package.json +19 -9
- package/scripts/build-binary.ts +2 -1
- package/scripts/build-sdk-package-smoke.ts +2 -13
- package/scripts/capture-sticky-viewport-showcase.ts +0 -1
- package/scripts/compile-args.ts +2 -0
- package/scripts/generate-sdk-adapter-parity-manifest.ts +31 -16
- package/scripts/generate-sdk-operation-inventory.ts +28 -0
- package/scripts/generate-telegram-baseline-manifest.ts +1 -0
- package/scripts/generate-tool-catalog.ts +6 -4
- package/scripts/verify-gjc-sdk-canonicalization.ts +5 -39
- package/src/async/job-manager.ts +352 -17
- package/src/async/support.ts +25 -0
- package/src/autoresearch/dashboard.ts +28 -13
- package/src/capability/index.ts +3 -1
- package/src/capability/mcp.ts +6 -0
- package/src/capability/types.ts +6 -0
- package/src/cli/accounts-cli.ts +395 -0
- package/src/cli/args.ts +23 -0
- package/src/cli/auth-broker-cli.ts +136 -66
- package/src/cli/auth-gateway-cli.ts +94 -70
- package/src/cli/config-cli.ts +27 -2
- package/src/cli/crash-cli.ts +78 -0
- package/src/cli/customize-doctor.ts +1605 -0
- package/src/cli/daemon-cli.ts +12 -3
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/mcp-cli.ts +128 -60
- package/src/cli/notify-cli.ts +8 -14
- package/src/cli/root-flags.ts +8 -0
- package/src/cli/setup-cli.ts +145 -0
- package/src/cli/skills-cli.ts +38 -2
- package/src/cli/update-cli.ts +167 -12
- package/src/cli.ts +4 -0
- package/src/commands/accounts.ts +71 -0
- package/src/commands/crash.ts +35 -0
- package/src/commands/customize.ts +84 -0
- package/src/commands/daemon.ts +2 -2
- package/src/commands/deep-interview.ts +2 -0
- package/src/commands/launch.ts +1 -0
- package/src/commands/mcp.ts +12 -7
- package/src/commands/ralplan.ts +2 -0
- package/src/commands/sdk.ts +65 -32
- package/src/commands/setup.ts +5 -0
- package/src/commands/skills.ts +14 -4
- package/src/commands/ultragoal.ts +10 -1
- package/src/commands/update.ts +26 -15
- package/src/config/atomic-yaml-patch-worker.ts +57 -0
- package/src/config/atomic-yaml-patch.ts +769 -29
- package/src/config/config-schema-version.ts +10 -0
- package/src/config/file-lock.ts +70 -1
- package/src/config/mcp-schema.json +52 -14
- package/src/config/model-profile-activation.ts +20 -1
- package/src/config/model-profiles.ts +29 -19
- package/src/config/model-registry.ts +132 -21
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +76 -6
- package/src/config/settings.ts +4038 -199
- package/src/config/skill-settings-defaults.ts +41 -3
- package/src/config/task-delegation.ts +87 -0
- package/src/config/update-channel.ts +23 -0
- package/src/coordinator-mcp/server.ts +377 -308
- package/src/crash/index-store.ts +723 -0
- package/src/crash/nudge.ts +89 -0
- package/src/crash/record-loader.ts +149 -0
- package/src/crash/report.ts +551 -0
- package/src/crash/sanitize.ts +129 -0
- package/src/cursor.ts +36 -10
- package/src/customization/import.ts +946 -0
- package/src/customization/index.ts +4 -0
- package/src/customization/inventory.ts +335 -0
- package/src/customization/mutations.ts +141 -0
- package/src/customization/types.ts +223 -0
- package/src/daemon/control-types.ts +8 -1
- package/src/daemon/operator-contract.ts +6 -6
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +11 -22
- package/src/defaults/gjc/skills/ralplan/SKILL.md +36 -23
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +16 -0
- package/src/discovery/claude-hooks.ts +38 -0
- package/src/discovery/claude.ts +142 -209
- package/src/discovery/codex-hooks.ts +38 -0
- package/src/discovery/codex.ts +132 -198
- package/src/discovery/helpers.ts +8 -1
- package/src/discovery/index.ts +2 -0
- package/src/discovery/mcp-compat.ts +234 -0
- package/src/discovery/mcp-json.ts +6 -0
- package/src/edit/renderer.ts +40 -0
- package/src/edit/streaming.ts +4 -2
- package/src/exec/bash-executor.ts +24 -20
- package/src/export/html/index.ts +51 -2
- package/src/extensibility/extensions/loader.ts +9 -1
- package/src/extensibility/extensions/runner.ts +17 -4
- package/src/extensibility/extensions/types.ts +31 -6
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +33 -0
- package/src/extensibility/gjc-plugins/installer.ts +9 -5
- package/src/extensibility/gjc-plugins/observability.ts +8 -2
- package/src/extensibility/gjc-plugins/registry.ts +13 -2
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +3 -1
- package/src/extensibility/gjc-plugins/schema.ts +222 -39
- package/src/extensibility/hooks/loader.ts +154 -10
- package/src/extensibility/runtime-skill-discovery.ts +257 -60
- package/src/extensibility/skill-management.ts +368 -0
- package/src/extensibility/skills.ts +52 -16
- package/src/gjc-runtime/deep-interview-runtime.ts +45 -61
- package/src/gjc-runtime/launch-worktree.ts +56 -2
- package/src/gjc-runtime/linux-proc.ts +7 -1
- package/src/gjc-runtime/ralplan-runtime.ts +100 -164
- package/src/gjc-runtime/session-state-lock.ts +992 -0
- package/src/gjc-runtime/session-state-sidecar.ts +644 -142
- package/src/gjc-runtime/state-writer.ts +39 -14
- package/src/gjc-runtime/tmux-owner-isolation.ts +5 -4
- package/src/gjc-runtime/ultragoal-guard.ts +11 -4
- package/src/gjc-runtime/ultragoal-runtime.ts +44 -41
- package/src/gjc-runtime/workflow-settings.ts +596 -0
- package/src/goals/tools/goal-tool.ts +6 -1
- package/src/hooks/events.ts +291 -0
- package/src/hooks/native-skill-hook.ts +4 -0
- package/src/hooks/normalize.ts +369 -0
- package/src/hooks/skill-state.ts +165 -46
- package/src/internal-urls/docs-index.generated.ts +40 -32
- package/src/main.ts +32 -5
- package/src/migrate/mcp-mapper.ts +25 -2
- package/src/modes/acp/abort-scope.ts +29 -0
- package/src/modes/acp/acp-agent.ts +423 -98
- package/src/modes/components/assistant-message.ts +6 -1
- package/src/modes/components/customization/customization-dashboard.ts +443 -0
- package/src/modes/components/customization/import-wizard.ts +372 -0
- package/src/modes/components/customization/index.ts +1 -0
- package/src/modes/components/gajae-pet-widget.ts +539 -213
- package/src/modes/components/irc-sidebar.ts +11 -0
- package/src/modes/components/iterm-pet-transport.ts +585 -0
- package/src/modes/components/oauth-selector.ts +277 -86
- package/src/modes/components/pet-capability.ts +39 -40
- package/src/modes/components/settings-selector.ts +9 -0
- package/src/modes/components/status-line/gh.ts +45 -1
- package/src/modes/components/status-line/segments.ts +16 -1
- package/src/modes/components/tool-status-header.ts +13 -3
- package/src/modes/controllers/command-controller.ts +20 -8
- package/src/modes/controllers/extension-ui-controller.ts +56 -257
- package/src/modes/controllers/input-controller.ts +10 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +16 -3
- package/src/modes/controllers/selector-controller.ts +177 -72
- package/src/modes/controllers/stt-controller.ts +3 -3
- package/src/modes/interactive-mode.ts +88 -16
- package/src/modes/print-mode.ts +35 -6
- package/src/modes/runtime-init.ts +21 -68
- package/src/modes/types.ts +1 -0
- package/src/modes/utils/injected-user-submission.ts +25 -0
- package/src/modes/utils/terminal-bell.ts +15 -1
- package/src/prompts/agent-fragments/ralplan-persistence.md +1 -1
- package/src/prompts/agent-fragments/restricted-bash.md +1 -1
- package/src/prompts/agents/critic.md +1 -1
- package/src/prompts/system/rlm-research.md +1 -1
- package/src/prompts/system/system-prompt.md +0 -2
- package/src/prompts/tools/bash.md +7 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/cron.md +6 -6
- package/src/prompts/tools/read.md +0 -2
- package/src/prompts/tools/skill-discovery.md +4 -2
- package/src/runtime-mcp/client.ts +427 -23
- package/src/runtime-mcp/config.ts +37 -5
- package/src/runtime-mcp/manager-pool.test.ts +56 -0
- package/src/runtime-mcp/manager.ts +52 -2
- package/src/runtime-mcp/oauth-discovery.ts +13 -0
- package/src/runtime-mcp/oauth-flow.ts +46 -1
- package/src/runtime-mcp/pool-key.ts +5 -1
- package/src/runtime-mcp/pool.test.ts +9 -0
- package/src/runtime-mcp/protocol.test.ts +353 -0
- package/src/runtime-mcp/protocol.ts +624 -0
- package/src/runtime-mcp/scope-config.ts +78 -0
- package/src/runtime-mcp/tool-bridge.ts +44 -10
- package/src/runtime-mcp/transports/http.ts +84 -13
- package/src/runtime-mcp/types.ts +123 -12
- package/src/sdk/acp/adapter.ts +328 -97
- package/src/sdk/broker/broker.ts +160 -741
- package/src/sdk/broker/ensure.ts +9 -1
- package/src/sdk/broker/lifecycle.ts +510 -116
- package/src/sdk/broker/operation-receipt-ledger.ts +11 -2
- package/src/sdk/broker/process-incarnation.ts +19 -0
- package/src/sdk/broker/session-index.ts +516 -117
- package/src/sdk/broker/startup-failure.ts +28 -5
- package/src/sdk/broker/transport.ts +1 -13
- package/src/sdk/bus/chat-daemon-cli.ts +4 -2
- package/src/sdk/bus/chat-daemon-control.ts +67 -6
- package/src/sdk/bus/chat-daemon-runtime.ts +183 -859
- package/src/sdk/bus/config.ts +13 -0
- package/src/sdk/bus/conversation-store.ts +59 -171
- package/src/sdk/bus/daemon-paths.ts +20 -0
- package/src/sdk/bus/discord-conversation.ts +2 -0
- package/src/sdk/bus/discord-daemon.ts +524 -126
- package/src/sdk/bus/discord-live-provider.ts +206 -79
- package/src/sdk/bus/existing-thread-readiness.ts +4 -97
- package/src/sdk/bus/inbound-reaction-ordering.ts +122 -0
- package/src/sdk/bus/index.ts +2480 -456
- package/src/sdk/bus/kind-aware-reconciliation.ts +204 -34
- package/src/sdk/bus/lifecycle-commands.ts +2 -2
- package/src/sdk/bus/managed-daemon.ts +2 -145
- package/src/sdk/bus/notification-service.ts +196 -0
- package/src/sdk/bus/operator-runtime.ts +1 -1
- package/src/sdk/bus/prompt-reconciliation.ts +24 -15
- package/src/sdk/bus/reconciliation-store.ts +553 -24
- package/src/sdk/bus/session-control.ts +49 -3
- package/src/sdk/bus/slack-conversation.ts +4 -0
- package/src/sdk/bus/slack-daemon.ts +733 -134
- package/src/sdk/bus/slack-live-provider.ts +65 -15
- package/src/sdk/bus/slack-provider.ts +4 -0
- package/src/sdk/bus/slack-thread-binding.ts +9 -104
- package/src/sdk/bus/telegram-adoption-intent.ts +299 -209
- package/src/sdk/bus/telegram-daemon-cli.ts +194 -7
- package/src/sdk/bus/telegram-daemon-contract.ts +265 -19
- package/src/sdk/bus/telegram-daemon-control.ts +3 -13
- package/src/sdk/bus/telegram-daemon-orphan-reap.ts +498 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +176 -0
- package/src/sdk/bus/telegram-daemon.ts +2552 -2280
- package/src/sdk/bus/telegram-reference.ts +1 -226
- package/src/sdk/bus/telegram-setup.ts +2 -2
- package/src/sdk/bus/threaded-render.ts +1 -0
- package/src/sdk/bus/topic-registry.ts +279 -146
- package/src/sdk/cli/rows.ts +2 -35
- package/src/sdk/cli/session-cli.ts +776 -700
- package/src/sdk/client/client.ts +892 -1
- package/src/sdk/host/control/dispatch.ts +93 -58
- package/src/sdk/host/control/index.ts +1 -1
- package/src/sdk/host/control/operations.ts +18 -10
- package/src/sdk/host/control/runtime-gate.ts +40 -0
- package/src/sdk/host/host.ts +63 -12
- package/src/sdk/host/query/handlers.ts +66 -7
- package/src/sdk/host/reverse-leases.ts +2 -2
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -1
- package/src/sdk/host/session-runtime.test.ts +2787 -34
- package/src/sdk/host/session-runtime.ts +1489 -101
- package/src/sdk/host/surface-policy.ts +12 -8
- package/src/sdk/host/types.ts +1 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +31 -59
- package/src/sdk/host/websocket-transport.ts +85 -50
- package/src/sdk/index.ts +2 -1
- package/src/sdk/lifecycle/broker-client.ts +53 -0
- package/src/sdk/lifecycle/client.ts +234 -0
- package/src/sdk/lifecycle/index.ts +3 -0
- package/src/sdk/{bus/recent-activity.ts → lifecycle/recent-sessions.ts} +5 -2
- package/src/sdk/lifecycle/service.ts +720 -0
- package/src/sdk/mcp/server.ts +226 -188
- package/src/sdk/prompt-deadline-lease.ts +55 -0
- package/src/sdk/prompt-deadline-manager.ts +148 -0
- package/src/sdk/prompt-status.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +272 -129
- package/src/sdk/protocol/operation-registry.ts +71 -8
- package/src/sdk/receipt-state.ts +43 -0
- package/src/sdk/reconciliation-extensions.ts +14 -0
- package/src/sdk/router/index.ts +1 -0
- package/src/sdk/router/session-router.ts +1658 -0
- package/src/sdk/session-list.ts +93 -0
- package/src/sdk/session-reconnect.ts +45 -1
- package/src/sdk/session.ts +716 -120
- package/src/sdk/transport/serve-cli.ts +18 -34
- package/src/session/account-inventory.ts +603 -0
- package/src/session/agent-session.ts +2857 -582
- package/src/session/agent-storage.ts +35 -0
- package/src/session/blob-store.ts +32 -1
- package/src/session/coordinator-tool-label.ts +40 -0
- package/src/session/internal/managed-session-scope.ts +4 -0
- package/src/session/internal/managed-session-storage.ts +173 -12
- package/src/session/messages.ts +1 -1
- package/src/session/secure-token-file.ts +80 -0
- package/src/session/session-manager.ts +730 -58
- package/src/session/session-storage.ts +25 -16
- package/src/session/startup-auth-config.ts +297 -0
- package/src/session/terminal-abort.ts +1253 -0
- package/src/session/yield-queue.ts +57 -15
- package/src/session-import/claude.ts +334 -0
- package/src/session-import/codex.ts +1033 -0
- package/src/session-import/command.ts +77 -0
- package/src/session-import/detect.ts +133 -0
- package/src/session-import/index.ts +7 -0
- package/src/session-import/provider-codex.ts +327 -0
- package/src/session-import/provider-service.ts +457 -0
- package/src/session-import/redact.ts +128 -0
- package/src/session-import/service.ts +1264 -0
- package/src/session-import/types.ts +148 -0
- package/src/setup/paseo/check.ts +213 -0
- package/src/setup/paseo/install-saga.ts +293 -0
- package/src/setup/paseo/json-publisher.ts +263 -0
- package/src/setup/paseo/orchestration-preferences.ts +86 -0
- package/src/setup/paseo/paseo-ownership.ts +224 -0
- package/src/setup/paseo/paseo-setup.ts +253 -0
- package/src/setup/paseo/provider-config.ts +139 -0
- package/src/setup/paseo/remove.ts +183 -0
- package/src/setup/paseo/result-types.ts +79 -0
- package/src/setup/paseo/setup-deps.ts +175 -0
- package/src/setup/paseo/skills-bridge.ts +260 -0
- package/src/skill-state/active-state.ts +21 -11
- package/src/slash-commands/acp-builtins.ts +9 -1
- package/src/slash-commands/builtin-registry.ts +98 -16
- package/src/slash-commands/helpers/credential-switch.ts +143 -0
- package/src/slash-commands/helpers/mcp.ts +9 -3
- package/src/slash-commands/helpers/usage-report.ts +61 -56
- package/src/slash-commands/types.ts +7 -2
- package/src/task/executor.ts +30 -11
- package/src/task/index.ts +66 -7
- package/src/task/render.ts +23 -9
- package/src/tools/ask-answer-registry.ts +23 -7
- package/src/tools/ask.ts +8 -4
- package/src/tools/bash-sleep-advisory.ts +115 -0
- package/src/tools/bash.ts +98 -18
- package/src/tools/browser/attach.ts +71 -3
- package/src/tools/browser/launch.ts +86 -13
- package/src/tools/browser/profile-discovery.ts +57 -7
- package/src/tools/browser/render.ts +8 -1
- package/src/tools/browser.ts +130 -21
- package/src/tools/computer.enforcement.test.ts +1 -1
- package/src/tools/computer.ts +3 -2
- package/src/tools/cron.ts +12 -1
- package/src/tools/image-gen.ts +27 -16
- package/src/tools/index.ts +8 -0
- package/src/tools/job.ts +33 -6
- package/src/tools/monitor.ts +41 -2
- package/src/tools/skill-discovery.ts +21 -29
- package/src/tools/subagent.ts +142 -24
- package/src/tools/tool-catalog.generated.ts +6 -6
- package/src/tools/ultragoal-ask-guard.ts +10 -3
- package/src/utils/herdr-pane.ts +345 -0
- package/src/utils/title-generator.ts +2 -0
- package/src/web/scrapers/index.ts +6 -4
- package/dist/types/cli/malloc-env-guard.test.d.ts +0 -1
- package/dist/types/defaults/gjc-defaults.test.d.ts +0 -1
- package/dist/types/memory-backend/lazy-loading.test.d.ts +0 -1
- package/dist/types/runtime/boot-ordering.test.d.ts +0 -1
- package/dist/types/runtime/lazy-service.test.d.ts +0 -1
- package/dist/types/runtime/network-prewarm-service.test.d.ts +0 -1
- package/dist/types/runtime/workspace-tree-service.test.d.ts +0 -1
- package/dist/types/runtime-mcp/config.test.d.ts +0 -1
- package/dist/types/runtime-mcp/http.test.d.ts +0 -1
- package/dist/types/runtime-mcp/manager-pool.test.d.ts +0 -1
- package/dist/types/runtime-mcp/pool-key.test.d.ts +0 -1
- package/dist/types/runtime-mcp/pool.test.d.ts +0 -1
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +0 -117
- package/dist/types/sdk/bus/lifecycle-orchestrator.d.ts +0 -141
- package/dist/types/sdk/bus/telegram-cli.d.ts +0 -31
- package/dist/types/sdk/elevation/allowlist.d.ts +0 -20
- package/dist/types/sdk/elevation/audit.d.ts +0 -93
- package/dist/types/sdk/elevation/capability.d.ts +0 -3
- package/dist/types/sdk/elevation/digest.d.ts +0 -72
- package/dist/types/sdk/elevation/dispatch-receipt.d.ts +0 -85
- package/dist/types/sdk/elevation/grant-ledger.d.ts +0 -163
- package/dist/types/sdk/elevation/owner.d.ts +0 -48
- package/dist/types/sdk/host/import-graph.test.d.ts +0 -1
- package/dist/types/sdk/host/sdk-surface-parity.test.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.test.d.ts +0 -1
- package/dist/types/sdk/host/websocket-transport.lifecycle.test.d.ts +0 -1
- package/dist/types/session/auth-broker-config.d.ts +0 -13
- package/dist/types/session/heap-eviction-artifacts.test.d.ts +0 -1
- package/dist/types/skills/skills.test.d.ts +0 -1
- package/dist/types/slash-commands/notify-command.test.d.ts +0 -1
- package/dist/types/task/token-log.test.d.ts +0 -1
- package/dist/types/tools/computer.enforcement.test.d.ts +0 -1
- package/dist/types/tools/descriptors.test.d.ts +0 -1
- package/scripts/g005-daemon-smoke.ts +0 -180
- package/scripts/g011-daemon-path-smoke.ts +0 -153
- package/src/sdk/bus/lifecycle-control-runtime.ts +0 -1733
- package/src/sdk/bus/lifecycle-orchestrator.ts +0 -489
- package/src/sdk/bus/telegram-cli.ts +0 -212
- package/src/sdk/elevation/allowlist.ts +0 -54
- package/src/sdk/elevation/audit.ts +0 -208
- package/src/sdk/elevation/capability.ts +0 -41
- package/src/sdk/elevation/digest.ts +0 -129
- package/src/sdk/elevation/dispatch-receipt.ts +0 -184
- package/src/sdk/elevation/grant-ledger.ts +0 -1142
- package/src/sdk/elevation/owner.ts +0 -109
- package/src/session/auth-broker-config.ts +0 -109
- /package/dist/types/{ai-core-import-gate.test.d.ts → discovery/claude-hooks.d.ts} +0 -0
- /package/dist/types/{cli/fixture-report.test.d.ts → discovery/codex-hooks.d.ts} +0 -0
- /package/dist/types/sdk/{bus/recent-activity.d.ts → lifecycle/recent-sessions.d.ts} +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { getAgentDir } from "@gajae-code/utils";
|
|
2
2
|
import { CliParseError } from "@gajae-code/utils/cli";
|
|
3
3
|
import { readSdkBrokerDiscovery, SdkClient, SdkClientError } from "../client";
|
|
4
|
+
import { SessionListTraversalError, sessionListPageFromResponse, traverseSessionList } from "../session-list";
|
|
4
5
|
import { DEFAULT_PENDING_CEILING_BYTES, MIN_PENDING_CEILING_BYTES, startSocketServe, startStdioServe } from "./index";
|
|
5
6
|
|
|
6
|
-
const MAX_SESSION_LIST_PAGES = 10_000;
|
|
7
|
-
|
|
8
7
|
type ServeMode = { kind: "stdio" } | { kind: "socket"; socketPath: string };
|
|
9
8
|
|
|
10
9
|
interface ServeArguments {
|
|
@@ -85,32 +84,29 @@ function brokerResult(value: unknown): Record<string, unknown> {
|
|
|
85
84
|
return isRecord(value) && isRecord(value.result) ? value.result : {};
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
function brokerSessionRows(
|
|
89
|
-
|
|
90
|
-
return value.sessions.flatMap(item => {
|
|
87
|
+
function brokerSessionRows(sessions: readonly unknown[]): BrokerSessionRow[] {
|
|
88
|
+
return sessions.flatMap(item => {
|
|
91
89
|
if (!isRecord(item) || typeof item.sessionId !== "string" || !item.sessionId) return [];
|
|
92
90
|
return [{ sessionId: item.sessionId, live: item.live === true, ambiguous: item.ambiguous === true }];
|
|
93
91
|
});
|
|
94
92
|
}
|
|
95
93
|
|
|
96
|
-
/**
|
|
97
|
-
* Exhausts broker `session.list` cursor pagination (default page limit 100) to
|
|
98
|
-
* one full snapshot; exported for tests.
|
|
99
|
-
*/
|
|
94
|
+
/** Exhausts strict broker `session.list` pages into one full session snapshot. */
|
|
100
95
|
export async function listBrokerSessions(broker: SdkClient): Promise<BrokerSessionRow[]> {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
96
|
+
try {
|
|
97
|
+
const pages = await traverseSessionList(
|
|
98
|
+
{},
|
|
99
|
+
async input => await broker.global("session.list", input),
|
|
100
|
+
response => {
|
|
101
|
+
brokerResult(response);
|
|
102
|
+
return sessionListPageFromResponse(response);
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
return pages.flatMap(page => brokerSessionRows(page.sessions));
|
|
106
|
+
} catch (error) {
|
|
107
|
+
if (error instanceof SessionListTraversalError) throw new SdkClientError("protocol_error", error.message);
|
|
108
|
+
throw error;
|
|
112
109
|
}
|
|
113
|
-
throw new SdkClientError("protocol_error", "session.list exceeded the page budget.");
|
|
114
110
|
}
|
|
115
111
|
|
|
116
112
|
/** Selects the session to serve through broker `session.list` truth (C10); exported for tests. */
|
|
@@ -156,19 +152,7 @@ export async function runSdkServe(argv: string[]): Promise<void> {
|
|
|
156
152
|
const url = typeof endpoint.url === "string" && endpoint.url ? endpoint.url : undefined;
|
|
157
153
|
const token = typeof endpoint.token === "string" ? endpoint.token : "";
|
|
158
154
|
if (!url) throw new Error("unavailable: broker returned an invalid endpoint record");
|
|
159
|
-
const options = {
|
|
160
|
-
url,
|
|
161
|
-
token,
|
|
162
|
-
pendingCeilingBytes,
|
|
163
|
-
validateDownstreamFrame: (source: string): boolean => {
|
|
164
|
-
try {
|
|
165
|
-
const frame = JSON.parse(source) as { type?: unknown; elevationRequestId?: unknown };
|
|
166
|
-
return frame.type !== "control_request" || frame.elevationRequestId === undefined;
|
|
167
|
-
} catch {
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
};
|
|
155
|
+
const options = { url, token, pendingCeilingBytes };
|
|
172
156
|
const handle =
|
|
173
157
|
parsed.mode.kind === "stdio"
|
|
174
158
|
? await startStdioServe(options)
|
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AuthStorage,
|
|
3
|
+
type CachedCredentialHealth,
|
|
4
|
+
type CachedUsageReport,
|
|
5
|
+
type CredentialHealthResult,
|
|
6
|
+
type CredentialInventoryRecord,
|
|
7
|
+
getEnvApiKey,
|
|
8
|
+
listProvidersWithEnvKey,
|
|
9
|
+
type Provider,
|
|
10
|
+
type UsageLimit,
|
|
11
|
+
type UsageStatus,
|
|
12
|
+
type UsageUnit,
|
|
13
|
+
type UsageWindow,
|
|
14
|
+
} from "@gajae-code/ai/core";
|
|
15
|
+
import type { RawSettings, Settings, SettingsAtomicPatch } from "../config/settings";
|
|
16
|
+
import { parsePersistedCredentialSelector } from "./startup-auth-config";
|
|
17
|
+
|
|
18
|
+
/** A redacted usage observation attached to an account row. */
|
|
19
|
+
export interface AccountUsageCache extends CachedUsageReport {}
|
|
20
|
+
|
|
21
|
+
/** Safe account health state used by presentation surfaces. */
|
|
22
|
+
export interface AccountHealthCache extends CachedCredentialHealth {}
|
|
23
|
+
|
|
24
|
+
export type AccountInventorySource = "stored" | "env" | "config" | "runtime";
|
|
25
|
+
|
|
26
|
+
/** Fixed presentation classification for a persisted disabled credential. */
|
|
27
|
+
export type AccountInventoryDisabledCause = "auth_failure" | "user_removed" | "duplicate" | "replaced" | "unknown";
|
|
28
|
+
|
|
29
|
+
export interface AccountInventoryCapabilities {
|
|
30
|
+
canCheck: boolean;
|
|
31
|
+
canPin: boolean;
|
|
32
|
+
canRemove: boolean;
|
|
33
|
+
hasCachedUsage: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface AccountInventoryRouting {
|
|
37
|
+
/** True when this row is the session's last recorded stored credential. */
|
|
38
|
+
active: boolean;
|
|
39
|
+
/** True when this source is the effective source for the provider/session. */
|
|
40
|
+
selected: boolean;
|
|
41
|
+
marker: "active" | "selected" | "available";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Payload-free account row for renderers. This type deliberately has no
|
|
46
|
+
* AuthCredential, API-key bytes, access token, refresh token, or raw usage.
|
|
47
|
+
*/
|
|
48
|
+
export interface AccountInventoryRow {
|
|
49
|
+
/** Stable, non-secret presentation id. */
|
|
50
|
+
id: string;
|
|
51
|
+
/** Numeric storage id when this is a persisted row. */
|
|
52
|
+
credentialId?: number;
|
|
53
|
+
provider: string;
|
|
54
|
+
credentialKind: "oauth" | "api_key";
|
|
55
|
+
source: AccountInventorySource;
|
|
56
|
+
sourceLabel: string;
|
|
57
|
+
identityLabel: string | null;
|
|
58
|
+
/** OAuth identity is intentionally limited to safe labels from inventory. */
|
|
59
|
+
oauthIdentity?: { label: string };
|
|
60
|
+
disabled: boolean;
|
|
61
|
+
disabledCause: AccountInventoryDisabledCause | null;
|
|
62
|
+
health: AccountHealthCache;
|
|
63
|
+
usage?: AccountUsageCache;
|
|
64
|
+
capabilities: AccountInventoryCapabilities;
|
|
65
|
+
routing: AccountInventoryRouting;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface AccountInventorySnapshot {
|
|
69
|
+
generatedAt: number;
|
|
70
|
+
generation: number;
|
|
71
|
+
rows: AccountInventoryRow[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface AccountInventoryInput {
|
|
75
|
+
authStorage: AuthStorage;
|
|
76
|
+
modelRegistry?: {
|
|
77
|
+
getAvailable?: () => Array<{ provider: string }>;
|
|
78
|
+
getProviderBaseUrl?: (provider: string) => string | undefined;
|
|
79
|
+
};
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
provider?: string;
|
|
82
|
+
nowMs?: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
type SyntheticAccountSource = Exclude<AccountInventorySource, "stored">;
|
|
86
|
+
|
|
87
|
+
/** Source-scoped cache hooks supplied by AuthStorage. */
|
|
88
|
+
interface SourceHealthStorage {
|
|
89
|
+
peekCachedCredentialHealthForSource: (provider: string, source: SyntheticAccountSource) => CachedCredentialHealth;
|
|
90
|
+
recordCredentialHealthForSource: (
|
|
91
|
+
provider: string,
|
|
92
|
+
source: SyntheticAccountSource,
|
|
93
|
+
health: CachedCredentialHealth,
|
|
94
|
+
) => void;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface AccountInventoryCheckResult {
|
|
98
|
+
rowId: string;
|
|
99
|
+
provider: string;
|
|
100
|
+
credentialId?: number;
|
|
101
|
+
ok: boolean | null;
|
|
102
|
+
reason?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function asSafeLabel(value: unknown): string | null {
|
|
106
|
+
if (typeof value !== "string") return null;
|
|
107
|
+
const normalized = value
|
|
108
|
+
.replace(/\u001b\][^\u0007]*(?:\u0007|\u001b\\)/g, " ")
|
|
109
|
+
.replace(/\u001b\[[0-?]*[ -/]*[@-~]/g, " ")
|
|
110
|
+
.replace(/bearer\s+[^\s,;]+/gi, "Bearer [redacted]")
|
|
111
|
+
.replace(/(api[_-]?key|token|secret|authorization)[=:]\s*[^\s,;]+/gi, "$1=[redacted]")
|
|
112
|
+
.replace(/https?:\/\/[^\s?#]+(?:\?[^\s#]*)?/gi, value => value.split("?")[0] ?? "[redacted URL]")
|
|
113
|
+
.replace(/[\u0000-\u001f\u007f-\u009f]/g, " ")
|
|
114
|
+
.replace(/[\u061c\u200e\u200f\u200b-\u200d\u2060\u202a-\u202e\u2066-\u2069\ufeff]/g, "")
|
|
115
|
+
.replace(/\s+/g, " ")
|
|
116
|
+
.trim();
|
|
117
|
+
return normalized.length > 0 ? normalized.slice(0, 160) : null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function safeProvider(value: unknown): string {
|
|
121
|
+
return asSafeLabel(value) ?? "unknown-provider";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function optionalSafeLabel(value: unknown): string | undefined {
|
|
125
|
+
return asSafeLabel(value) ?? undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
129
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
130
|
+
? (value as Record<string, unknown>)
|
|
131
|
+
: undefined;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function finiteNumber(value: unknown): number | undefined {
|
|
135
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function classifyDisabledCause(value: unknown, disabled: boolean): AccountInventoryDisabledCause | null {
|
|
139
|
+
if (!disabled) return null;
|
|
140
|
+
if (typeof value !== "string") return "unknown";
|
|
141
|
+
const cause = value.trim();
|
|
142
|
+
if (/^(?:deleted|logged out) by user(?:$|\b)/i.test(cause) || /^disabled via auth-broker$/i.test(cause)) {
|
|
143
|
+
return "user_removed";
|
|
144
|
+
}
|
|
145
|
+
if (/^deduplicated duplicate credential$/i.test(cause)) return "duplicate";
|
|
146
|
+
if (/^replaced by newer credential$/i.test(cause)) return "replaced";
|
|
147
|
+
if (
|
|
148
|
+
/^(?:oauth|auth-broker) refresh failed:/i.test(cause) ||
|
|
149
|
+
/invalid_grant|grant is invalid|invalid_token|revoked|unauthorized|expired.*refresh|refresh.*expired/i.test(
|
|
150
|
+
cause,
|
|
151
|
+
) ||
|
|
152
|
+
(/\b(401|403)\b/.test(cause) && !/timeout|network|fetch failed|ECONNREFUSED/i.test(cause))
|
|
153
|
+
) {
|
|
154
|
+
return "auth_failure";
|
|
155
|
+
}
|
|
156
|
+
return "unknown";
|
|
157
|
+
}
|
|
158
|
+
function sourceId(provider: string, source: AccountInventorySource, credentialId?: number): string {
|
|
159
|
+
const safe = safeProvider(provider);
|
|
160
|
+
return credentialId === undefined ? `${safe}:${source}` : `${safe}:stored:${credentialId}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function sourceLabel(source: AccountInventorySource): string {
|
|
164
|
+
switch (source) {
|
|
165
|
+
case "stored":
|
|
166
|
+
return "stored credential";
|
|
167
|
+
case "env":
|
|
168
|
+
return "environment API key";
|
|
169
|
+
case "config":
|
|
170
|
+
return "config API key";
|
|
171
|
+
case "runtime":
|
|
172
|
+
return "runtime API key";
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function providerSet(input: AccountInventoryInput, inventory: CredentialInventoryRecord[]): Set<string> {
|
|
177
|
+
const providers = new Set(inventory.flatMap(row => (typeof row.provider === "string" ? [row.provider] : [])));
|
|
178
|
+
for (const provider of input.modelRegistry?.getAvailable?.() ?? []) {
|
|
179
|
+
if (typeof provider?.provider === "string") providers.add(provider.provider);
|
|
180
|
+
}
|
|
181
|
+
// This only asks whether a known env-backed provider is present. The key value
|
|
182
|
+
// never enters the snapshot or any renderer.
|
|
183
|
+
for (const provider of listProvidersWithEnvKey()) {
|
|
184
|
+
if (getEnvApiKey(provider)) providers.add(provider);
|
|
185
|
+
}
|
|
186
|
+
return providers;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function storedHealth(authStorage: AuthStorage, row: CredentialInventoryRecord): AccountHealthCache {
|
|
190
|
+
const cached = asRecord(authStorage.getCachedCredentialHealth(row.id));
|
|
191
|
+
if (row.disabled) return { status: "failed", reason: null };
|
|
192
|
+
const status: AccountHealthCache["status"] =
|
|
193
|
+
cached?.status === "ok" ||
|
|
194
|
+
cached?.status === "failed" ||
|
|
195
|
+
cached?.status === "unverifiable" ||
|
|
196
|
+
cached?.status === "unknown"
|
|
197
|
+
? cached.status
|
|
198
|
+
: "unknown";
|
|
199
|
+
return {
|
|
200
|
+
status,
|
|
201
|
+
reason: asSafeLabel(cached?.reason),
|
|
202
|
+
...(finiteNumber(cached?.checkedAt) !== undefined ? { checkedAt: finiteNumber(cached?.checkedAt) } : {}),
|
|
203
|
+
...(finiteNumber(cached?.retainUntil) !== undefined ? { retainUntil: finiteNumber(cached?.retainUntil) } : {}),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function storedUsage(authStorage: AuthStorage, row: CredentialInventoryRecord): AccountUsageCache | undefined {
|
|
208
|
+
return authStorage.getCachedUsageReport(row.provider as Provider, row.id);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function safeUsageUnit(value: unknown): UsageUnit {
|
|
212
|
+
return value === "percent" ||
|
|
213
|
+
value === "tokens" ||
|
|
214
|
+
value === "requests" ||
|
|
215
|
+
value === "usd" ||
|
|
216
|
+
value === "minutes" ||
|
|
217
|
+
value === "bytes" ||
|
|
218
|
+
value === "unknown"
|
|
219
|
+
? value
|
|
220
|
+
: "unknown";
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function safeUsageStatus(value: unknown): UsageStatus | undefined {
|
|
224
|
+
return value === "ok" || value === "warning" || value === "exhausted" || value === "unknown" ? value : undefined;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function redactUsageWindow(value: unknown): UsageWindow | undefined {
|
|
228
|
+
const window = asRecord(value);
|
|
229
|
+
if (!window) return undefined;
|
|
230
|
+
return {
|
|
231
|
+
id: asSafeLabel(window.id) ?? "usage-window",
|
|
232
|
+
label: asSafeLabel(window.label) ?? "usage window",
|
|
233
|
+
...(finiteNumber(window.durationMs) !== undefined ? { durationMs: finiteNumber(window.durationMs) } : {}),
|
|
234
|
+
...(finiteNumber(window.resetsAt) !== undefined ? { resetsAt: finiteNumber(window.resetsAt) } : {}),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function redactUsageLimit(value: unknown, reportProvider: string): UsageLimit {
|
|
239
|
+
const limit = asRecord(value);
|
|
240
|
+
const scope = asRecord(limit?.scope);
|
|
241
|
+
const amount = asRecord(limit?.amount);
|
|
242
|
+
const used = finiteNumber(amount?.used);
|
|
243
|
+
const amountLimit = finiteNumber(amount?.limit);
|
|
244
|
+
const remaining = finiteNumber(amount?.remaining);
|
|
245
|
+
const usedFraction = finiteNumber(amount?.usedFraction);
|
|
246
|
+
const remainingFraction = finiteNumber(amount?.remainingFraction);
|
|
247
|
+
const notes = Array.isArray(limit?.notes)
|
|
248
|
+
? limit.notes.map(note => asSafeLabel(note)).filter((note): note is string => note !== null)
|
|
249
|
+
: undefined;
|
|
250
|
+
const status = safeUsageStatus(limit?.status);
|
|
251
|
+
const window = redactUsageWindow(limit?.window);
|
|
252
|
+
return {
|
|
253
|
+
id: asSafeLabel(limit?.id) ?? "usage-limit",
|
|
254
|
+
label: asSafeLabel(limit?.label) ?? "usage limit",
|
|
255
|
+
scope: {
|
|
256
|
+
provider: safeProvider(scope?.provider ?? reportProvider),
|
|
257
|
+
...(optionalSafeLabel(scope?.accountId) ? { accountId: optionalSafeLabel(scope?.accountId) } : {}),
|
|
258
|
+
...(optionalSafeLabel(scope?.projectId) ? { projectId: optionalSafeLabel(scope?.projectId) } : {}),
|
|
259
|
+
...(optionalSafeLabel(scope?.orgId) ? { orgId: optionalSafeLabel(scope?.orgId) } : {}),
|
|
260
|
+
...(optionalSafeLabel(scope?.modelId) ? { modelId: optionalSafeLabel(scope?.modelId) } : {}),
|
|
261
|
+
...(optionalSafeLabel(scope?.tier) ? { tier: optionalSafeLabel(scope?.tier) } : {}),
|
|
262
|
+
...(optionalSafeLabel(scope?.windowId) ? { windowId: optionalSafeLabel(scope?.windowId) } : {}),
|
|
263
|
+
...(typeof scope?.shared === "boolean" ? { shared: scope.shared } : {}),
|
|
264
|
+
},
|
|
265
|
+
...(window ? { window } : {}),
|
|
266
|
+
amount: {
|
|
267
|
+
...(used !== undefined ? { used } : {}),
|
|
268
|
+
...(amountLimit !== undefined ? { limit: amountLimit } : {}),
|
|
269
|
+
...(remaining !== undefined ? { remaining } : {}),
|
|
270
|
+
...(usedFraction !== undefined ? { usedFraction } : {}),
|
|
271
|
+
...(remainingFraction !== undefined ? { remainingFraction } : {}),
|
|
272
|
+
unit: safeUsageUnit(amount?.unit),
|
|
273
|
+
},
|
|
274
|
+
...(status !== undefined ? { status } : {}),
|
|
275
|
+
...(notes !== undefined ? { notes } : {}),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function redactUsageReport(report: CachedUsageReport["report"]): CachedUsageReport["report"] {
|
|
280
|
+
const value = asRecord(report);
|
|
281
|
+
const provider = safeProvider(value?.provider);
|
|
282
|
+
const metadata = asRecord(value?.metadata);
|
|
283
|
+
const safeMetadata = metadata
|
|
284
|
+
? Object.fromEntries(
|
|
285
|
+
["email", "accountId", "account", "user", "projectId", "orgId"].flatMap(key => {
|
|
286
|
+
const safe = asSafeLabel(metadata[key]);
|
|
287
|
+
return safe ? [[key, safe]] : [];
|
|
288
|
+
}),
|
|
289
|
+
)
|
|
290
|
+
: undefined;
|
|
291
|
+
const limits = Array.isArray(value?.limits) ? value.limits.map(limit => redactUsageLimit(limit, provider)) : [];
|
|
292
|
+
return {
|
|
293
|
+
provider,
|
|
294
|
+
fetchedAt: finiteNumber(value?.fetchedAt) ?? 0,
|
|
295
|
+
limits,
|
|
296
|
+
...(safeMetadata && Object.keys(safeMetadata).length > 0 ? { metadata: safeMetadata } : {}),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function redactUsageCache(usage: CachedUsageReport | undefined): AccountUsageCache | undefined {
|
|
301
|
+
if (!usage || !asRecord(usage.report)) return undefined;
|
|
302
|
+
return {
|
|
303
|
+
report: redactUsageReport(usage.report),
|
|
304
|
+
fetchedAt: finiteNumber(usage.fetchedAt) ?? 0,
|
|
305
|
+
freshUntil: finiteNumber(usage.freshUntil) ?? 0,
|
|
306
|
+
retainUntil: finiteNumber(usage.retainUntil) ?? 0,
|
|
307
|
+
freshness: usage.freshness === "fresh" ? "fresh" : "stale-last-good",
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function canPinStoredOAuth(authStorage: AuthStorage, provider: string): boolean {
|
|
312
|
+
if (authStorage.hasRuntimeApiKey(provider) || authStorage.hasConfigApiKey(provider)) return false;
|
|
313
|
+
return !getEnvApiKey(provider);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function sourceHealth(authStorage: AuthStorage, provider: string, source: SyntheticAccountSource): AccountHealthCache {
|
|
317
|
+
const getter = (authStorage as AuthStorage & SourceHealthStorage).peekCachedCredentialHealthForSource;
|
|
318
|
+
const cached = getter.call(authStorage, provider, source);
|
|
319
|
+
return {
|
|
320
|
+
status:
|
|
321
|
+
cached.status === "ok" ||
|
|
322
|
+
cached.status === "failed" ||
|
|
323
|
+
cached.status === "unverifiable" ||
|
|
324
|
+
cached.status === "unknown"
|
|
325
|
+
? cached.status
|
|
326
|
+
: "unknown",
|
|
327
|
+
reason: asSafeLabel(cached.reason),
|
|
328
|
+
...(finiteNumber(cached.checkedAt) !== undefined ? { checkedAt: finiteNumber(cached.checkedAt) } : {}),
|
|
329
|
+
...(finiteNumber(cached.retainUntil) !== undefined ? { retainUntil: finiteNumber(cached.retainUntil) } : {}),
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function recordSourceHealth(
|
|
334
|
+
authStorage: AuthStorage,
|
|
335
|
+
provider: string,
|
|
336
|
+
source: SyntheticAccountSource,
|
|
337
|
+
ok: boolean | null,
|
|
338
|
+
reason: unknown,
|
|
339
|
+
): void {
|
|
340
|
+
const recorder = (authStorage as AuthStorage & SourceHealthStorage).recordCredentialHealthForSource;
|
|
341
|
+
const now = Date.now();
|
|
342
|
+
recorder.call(authStorage, provider, source, {
|
|
343
|
+
status: ok === true ? "ok" : ok === false ? "failed" : "unverifiable",
|
|
344
|
+
reason: asSafeLabel(reason),
|
|
345
|
+
checkedAt: now,
|
|
346
|
+
retainUntil: now + 24 * 60 * 60_000,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function addStoredRows(
|
|
351
|
+
rows: AccountInventoryRow[],
|
|
352
|
+
authStorage: AuthStorage,
|
|
353
|
+
inventory: CredentialInventoryRecord[],
|
|
354
|
+
sessionId: string | undefined,
|
|
355
|
+
): void {
|
|
356
|
+
const removalTargetIds = new Set(
|
|
357
|
+
(typeof authStorage.listCredentialRemovalTargets === "function"
|
|
358
|
+
? authStorage.listCredentialRemovalTargets()
|
|
359
|
+
: []
|
|
360
|
+
).map(target => target.id),
|
|
361
|
+
);
|
|
362
|
+
for (const record of inventory) {
|
|
363
|
+
const identityLabel = asSafeLabel(record.identityLabel);
|
|
364
|
+
const safeUsage = redactUsageCache(storedUsage(authStorage, record));
|
|
365
|
+
const active =
|
|
366
|
+
typeof record.provider === "string" &&
|
|
367
|
+
authStorage.getSessionCredentialRowId(record.provider, sessionId) === record.id;
|
|
368
|
+
const canPin =
|
|
369
|
+
record.credentialKind === "oauth" && !record.disabled && canPinStoredOAuth(authStorage, record.provider);
|
|
370
|
+
const canRemove = record.credentialKind === "oauth" && removalTargetIds.has(record.id);
|
|
371
|
+
rows.push({
|
|
372
|
+
id: sourceId(record.provider, "stored", record.id),
|
|
373
|
+
credentialId: record.id,
|
|
374
|
+
provider: safeProvider(record.provider),
|
|
375
|
+
credentialKind: record.credentialKind,
|
|
376
|
+
source: "stored",
|
|
377
|
+
sourceLabel: sourceLabel("stored"),
|
|
378
|
+
identityLabel,
|
|
379
|
+
...(record.credentialKind === "oauth" && identityLabel ? { oauthIdentity: { label: identityLabel } } : {}),
|
|
380
|
+
disabled: record.disabled,
|
|
381
|
+
disabledCause: classifyDisabledCause(record.disabledCause, record.disabled),
|
|
382
|
+
health: storedHealth(authStorage, record),
|
|
383
|
+
...(safeUsage ? { usage: safeUsage } : {}),
|
|
384
|
+
capabilities: {
|
|
385
|
+
canCheck: true,
|
|
386
|
+
canPin,
|
|
387
|
+
canRemove,
|
|
388
|
+
hasCachedUsage: safeUsage !== undefined,
|
|
389
|
+
},
|
|
390
|
+
routing: {
|
|
391
|
+
active,
|
|
392
|
+
selected: active,
|
|
393
|
+
marker: active ? "active" : "available",
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function addSyntheticRows(
|
|
400
|
+
rows: AccountInventoryRow[],
|
|
401
|
+
authStorage: AuthStorage,
|
|
402
|
+
providers: Set<string>,
|
|
403
|
+
sessionId: string | undefined,
|
|
404
|
+
): void {
|
|
405
|
+
for (const provider of [...providers].sort((a, b) => a.localeCompare(b))) {
|
|
406
|
+
const runtime = authStorage.hasRuntimeApiKey(provider);
|
|
407
|
+
const config = authStorage.hasConfigApiKey(provider);
|
|
408
|
+
const env = Boolean(getEnvApiKey(provider));
|
|
409
|
+
const effectiveType = authStorage.getEffectiveCredentialType(provider, sessionId);
|
|
410
|
+
|
|
411
|
+
const add = (source: AccountInventorySource): void => {
|
|
412
|
+
const selected =
|
|
413
|
+
source === "runtime"
|
|
414
|
+
? runtime && effectiveType === "api_key"
|
|
415
|
+
: source === "config"
|
|
416
|
+
? config && effectiveType === "api_key" && !runtime
|
|
417
|
+
: env && effectiveType === "api_key" && !runtime && !config;
|
|
418
|
+
const id = sourceId(provider, source);
|
|
419
|
+
rows.push({
|
|
420
|
+
id,
|
|
421
|
+
provider: safeProvider(provider),
|
|
422
|
+
credentialKind: "api_key",
|
|
423
|
+
source,
|
|
424
|
+
sourceLabel: sourceLabel(source),
|
|
425
|
+
identityLabel: null,
|
|
426
|
+
disabled: false,
|
|
427
|
+
disabledCause: null,
|
|
428
|
+
health: sourceHealth(authStorage, provider, source as SyntheticAccountSource),
|
|
429
|
+
capabilities: {
|
|
430
|
+
canCheck: true,
|
|
431
|
+
canPin: false,
|
|
432
|
+
canRemove: false,
|
|
433
|
+
hasCachedUsage: false,
|
|
434
|
+
},
|
|
435
|
+
routing: {
|
|
436
|
+
active: false,
|
|
437
|
+
selected,
|
|
438
|
+
marker: selected ? "selected" : "available",
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
// Keep synthetic rows even when a stored row exists: they represent
|
|
444
|
+
// explicit sources that can shadow stored credentials.
|
|
445
|
+
if (runtime) add("runtime");
|
|
446
|
+
if (config) add("config");
|
|
447
|
+
if (env) add("env");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** Build a redacted, cache-only account snapshot. This function never probes. */
|
|
452
|
+
export function buildAccountInventorySnapshot(input: AccountInventoryInput): AccountInventorySnapshot {
|
|
453
|
+
const nowMs = input.nowMs ?? Date.now();
|
|
454
|
+
const inventory = input.authStorage.listCredentialInventory();
|
|
455
|
+
const rows: AccountInventoryRow[] = [];
|
|
456
|
+
addStoredRows(rows, input.authStorage, inventory, input.sessionId);
|
|
457
|
+
addSyntheticRows(rows, input.authStorage, providerSet(input, inventory), input.sessionId);
|
|
458
|
+
rows.sort((left, right) => left.id.localeCompare(right.id));
|
|
459
|
+
return { generatedAt: nowMs, generation: input.authStorage.getGeneration(), rows };
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** Short alias used by command/report callers. */
|
|
463
|
+
export const buildAccountInventory = buildAccountInventorySnapshot;
|
|
464
|
+
|
|
465
|
+
function applyStoredCheck(
|
|
466
|
+
rows: AccountInventoryRow[],
|
|
467
|
+
authStorage: AuthStorage,
|
|
468
|
+
results: CredentialHealthResult[],
|
|
469
|
+
): AccountInventoryCheckResult[] {
|
|
470
|
+
const byId = new Map(rows.filter(row => row.credentialId !== undefined).map(row => [row.credentialId!, row]));
|
|
471
|
+
const checked: AccountInventoryCheckResult[] = [];
|
|
472
|
+
for (const result of results) {
|
|
473
|
+
const row = byId.get(result.id);
|
|
474
|
+
if (!row) continue;
|
|
475
|
+
row.health = {
|
|
476
|
+
status: result.ok === true ? "ok" : result.ok === false ? "failed" : "unverifiable",
|
|
477
|
+
reason: asSafeLabel(result.reason),
|
|
478
|
+
};
|
|
479
|
+
if (result.report) {
|
|
480
|
+
const cached =
|
|
481
|
+
row.credentialId === undefined
|
|
482
|
+
? undefined
|
|
483
|
+
: authStorage.getCachedUsageReport(row.provider as Provider, row.credentialId);
|
|
484
|
+
if (cached) {
|
|
485
|
+
row.usage = redactUsageCache(cached);
|
|
486
|
+
row.capabilities.hasCachedUsage = true;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
checked.push({
|
|
490
|
+
rowId: row.id,
|
|
491
|
+
provider: row.provider,
|
|
492
|
+
credentialId: row.credentialId,
|
|
493
|
+
ok: result.ok,
|
|
494
|
+
reason: asSafeLabel(result.reason) ?? undefined,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
return checked;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Run the explicit sequential checker and return a fresh redacted snapshot.
|
|
502
|
+
* AuthStorage.checkCredentials performs stored-row probes sequentially; the
|
|
503
|
+
* synthetic API-key probes below are also intentionally sequential.
|
|
504
|
+
*/
|
|
505
|
+
export async function checkAccountInventory(input: AccountInventoryInput): Promise<AccountInventorySnapshot> {
|
|
506
|
+
const fullSnapshot = buildAccountInventorySnapshot(input);
|
|
507
|
+
const rows = input.provider ? fullSnapshot.rows.filter(row => row.provider === input.provider) : fullSnapshot.rows;
|
|
508
|
+
const snapshot: AccountInventorySnapshot = { ...fullSnapshot, rows };
|
|
509
|
+
const authStorage = input.authStorage;
|
|
510
|
+
applyStoredCheck(
|
|
511
|
+
rows,
|
|
512
|
+
authStorage,
|
|
513
|
+
await authStorage.checkCredentials({
|
|
514
|
+
provider: input.provider,
|
|
515
|
+
baseUrlResolver: provider => input.modelRegistry?.getProviderBaseUrl?.(provider),
|
|
516
|
+
}),
|
|
517
|
+
);
|
|
518
|
+
const syntheticRows = rows.filter(row => row.source !== "stored");
|
|
519
|
+
for (const row of syntheticRows) {
|
|
520
|
+
let key: string | undefined;
|
|
521
|
+
if (row.source === "env") key = getEnvApiKey(row.provider);
|
|
522
|
+
else if (row.source === "runtime" && authStorage.hasRuntimeApiKey(row.provider))
|
|
523
|
+
key = await authStorage.peekApiKey(row.provider);
|
|
524
|
+
else if (
|
|
525
|
+
row.source === "config" &&
|
|
526
|
+
authStorage.hasConfigApiKey(row.provider) &&
|
|
527
|
+
!authStorage.hasRuntimeApiKey(row.provider)
|
|
528
|
+
) {
|
|
529
|
+
key = await authStorage.peekApiKey(row.provider);
|
|
530
|
+
}
|
|
531
|
+
const result = key
|
|
532
|
+
? await authStorage.checkApiKeyCredential(row.provider as Provider, key, {
|
|
533
|
+
baseUrl: input.modelRegistry?.getProviderBaseUrl?.(row.provider),
|
|
534
|
+
})
|
|
535
|
+
: { provider: row.provider, type: "api_key" as const, ok: null, reason: "API-key source is unavailable" };
|
|
536
|
+
row.health = {
|
|
537
|
+
status: result.ok === true ? "ok" : result.ok === false ? "failed" : "unverifiable",
|
|
538
|
+
reason: asSafeLabel(result.reason),
|
|
539
|
+
};
|
|
540
|
+
recordSourceHealth(authStorage, row.provider, row.source as SyntheticAccountSource, result.ok, result.reason);
|
|
541
|
+
if (result.report) {
|
|
542
|
+
row.usage = {
|
|
543
|
+
report: redactUsageReport(result.report),
|
|
544
|
+
fetchedAt: finiteNumber(result.report.fetchedAt) ?? 0,
|
|
545
|
+
freshUntil: Date.now() + 15 * 60_000,
|
|
546
|
+
retainUntil: Date.now() + 24 * 60 * 60_000,
|
|
547
|
+
freshness: "fresh",
|
|
548
|
+
};
|
|
549
|
+
row.capabilities.hasCachedUsage = true;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return snapshot;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export const checkAccountInventorySnapshot = checkAccountInventory;
|
|
556
|
+
|
|
557
|
+
function selectorMatchesRemovedRow(
|
|
558
|
+
selector: string,
|
|
559
|
+
provider: string,
|
|
560
|
+
inventory: readonly CredentialInventoryRecord[],
|
|
561
|
+
removedIds: ReadonlySet<number>,
|
|
562
|
+
): boolean {
|
|
563
|
+
const parsed = parsePersistedCredentialSelector(selector);
|
|
564
|
+
if (!parsed) return false;
|
|
565
|
+
if (parsed.kind === "id") return removedIds.has(Number(parsed.value));
|
|
566
|
+
return inventory.some(
|
|
567
|
+
row =>
|
|
568
|
+
row.provider === provider &&
|
|
569
|
+
removedIds.has(row.id) &&
|
|
570
|
+
(parsed.kind === "email"
|
|
571
|
+
? row.email?.trim().toLowerCase() === parsed.value.trim().toLowerCase()
|
|
572
|
+
: parsed.kind === "account"
|
|
573
|
+
? row.accountId === parsed.value
|
|
574
|
+
: row.projectId === parsed.value),
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/** Clear a global persistent pin only after its selected credential was removed. */
|
|
579
|
+
export async function clearPersistentPinForRemovedRows(
|
|
580
|
+
settings: Pick<Settings, "commitAtomicBatchWithCurrent">,
|
|
581
|
+
provider: string,
|
|
582
|
+
inventory: readonly CredentialInventoryRecord[],
|
|
583
|
+
removedIds: readonly number[],
|
|
584
|
+
): Promise<boolean> {
|
|
585
|
+
const removed = new Set(removedIds);
|
|
586
|
+
if (removed.size === 0) return false;
|
|
587
|
+
let cleared = false;
|
|
588
|
+
await settings.commitAtomicBatchWithCurrent(current => {
|
|
589
|
+
const auth = asRecord((current as RawSettings).auth);
|
|
590
|
+
const pins = asRecord(auth?.credentialPins);
|
|
591
|
+
const selector = pins?.[provider];
|
|
592
|
+
if (typeof selector !== "string" || !selectorMatchesRemovedRow(selector, provider, inventory, removed)) return [];
|
|
593
|
+
const nextPins = { ...pins };
|
|
594
|
+
delete nextPins[provider];
|
|
595
|
+
cleared = true;
|
|
596
|
+
const patches: SettingsAtomicPatch[] = [{ path: "auth.credentialPins", op: "set", value: nextPins }];
|
|
597
|
+
if (!Object.values(nextPins).some(value => typeof value === "string" && value.startsWith("id:"))) {
|
|
598
|
+
patches.push({ path: "auth.credentialPinStoreIdentity", op: "unset" });
|
|
599
|
+
}
|
|
600
|
+
return patches;
|
|
601
|
+
});
|
|
602
|
+
return cleared;
|
|
603
|
+
}
|