@gajae-code/coding-agent 0.13.2 → 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 +215 -8
- 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 +10 -1
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +73 -9
- 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 +2 -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/dynamic-theme-text.d.ts +9 -0
- package/dist/types/modes/components/gajae-pet-widget.d.ts +6 -28
- 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 +7 -21
- package/dist/types/modes/components/settings-selector.d.ts +5 -0
- 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/theme/defaults/index.d.ts +118 -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 +47 -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 +10 -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 +23 -2
- package/src/config/model-profiles.ts +88 -21
- package/src/config/model-registry.ts +147 -21
- package/src/config/models-config-schema.ts +1 -1
- package/src/config/settings-schema.ts +77 -7
- 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/extensions/grok-cli-vendor/src/models/catalog.ts +31 -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 +41 -32
- package/src/main.ts +36 -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/chrome.ts +4 -3
- 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/dynamic-theme-text.ts +22 -0
- package/src/modes/components/gajae-pet-widget.ts +607 -193
- package/src/modes/components/irc-sidebar.ts +11 -0
- package/src/modes/components/iterm-pet-transport.ts +585 -0
- package/src/modes/components/model-selector.ts +1 -6
- package/src/modes/components/oauth-selector.ts +277 -86
- package/src/modes/components/pet-capability.ts +35 -31
- package/src/modes/components/settings-selector.ts +29 -5
- package/src/modes/components/status-line/gh.ts +45 -1
- package/src/modes/components/status-line/segments.ts +19 -4
- 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 +238 -77
- 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/theme/defaults/index.ts +2 -0
- package/src/modes/theme/defaults/ouroboros.json +118 -0
- 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 +2873 -559
- 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 +199 -31
- package/src/session/messages.ts +1 -1
- package/src/session/secure-token-file.ts +80 -0
- package/src/session/session-manager.ts +757 -57
- 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 +117 -19
- 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 +349 -142
- 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/todo-contract.ts +55 -3
- package/src/tools/todo-write.ts +4 -3
- 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
package/src/tools/bash.ts
CHANGED
|
@@ -30,6 +30,11 @@ import {
|
|
|
30
30
|
truncateHeadBytes,
|
|
31
31
|
truncateTailBytes,
|
|
32
32
|
} from "../session/streaming-output";
|
|
33
|
+
import {
|
|
34
|
+
lookupOwnedRegistration,
|
|
35
|
+
registerOwnedIfLineaged,
|
|
36
|
+
unregisterOwnedRegistration,
|
|
37
|
+
} from "../session/terminal-abort";
|
|
33
38
|
|
|
34
39
|
import { renderStatusLine } from "../tui";
|
|
35
40
|
import { CachedOutputBlock, getOutputBlockContentWidth } from "../tui/output-block";
|
|
@@ -42,6 +47,7 @@ import { type BashInteractiveResult, runInteractiveBashPty } from "./bash-intera
|
|
|
42
47
|
import { checkBashInterception } from "./bash-interceptor";
|
|
43
48
|
import { canUseInteractiveBashPty } from "./bash-pty-selection";
|
|
44
49
|
import { expandInternalUrls, type InternalUrlExpansionOptions } from "./bash-skill-urls";
|
|
50
|
+
import { longSleepAdvisory } from "./bash-sleep-advisory";
|
|
45
51
|
import { checkComposerBashPolicy } from "./composer-bash-policy";
|
|
46
52
|
import {
|
|
47
53
|
formatArtifactReference,
|
|
@@ -598,6 +604,23 @@ function formatTimeoutClampNotice(requestedTimeoutSec: number, effectiveTimeoutS
|
|
|
598
604
|
*
|
|
599
605
|
* Executes bash commands with optional timeout and working directory.
|
|
600
606
|
*/
|
|
607
|
+
/** Remove the owned registration of a FOREGROUND bash job whose delivery was
|
|
608
|
+
* synchronously acknowledged: the tuple is settled and must not occupy the
|
|
609
|
+
* registry, otherwise old retained policies are treated as occupied and the
|
|
610
|
+
* tombstone FIFO fallback can evict a genuinely live work's policy (review
|
|
611
|
+
* thread P2). */
|
|
612
|
+
function unregisterForegroundOwnedBash(
|
|
613
|
+
manager: { getJob?(id: string): { generation?: string } | undefined },
|
|
614
|
+
jobId: string,
|
|
615
|
+
endpointId?: string,
|
|
616
|
+
): void {
|
|
617
|
+
const generation = manager.getJob?.(jobId)?.generation;
|
|
618
|
+
if (!generation) return;
|
|
619
|
+
// The endpoint disambiguates concurrent sessions' same job ids (review P1).
|
|
620
|
+
const registration = lookupOwnedRegistration(jobId, generation, endpointId);
|
|
621
|
+
if (registration) unregisterOwnedRegistration(registration);
|
|
622
|
+
}
|
|
623
|
+
|
|
601
624
|
export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
602
625
|
readonly name = "bash";
|
|
603
626
|
readonly label = "Bash";
|
|
@@ -751,8 +774,10 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
751
774
|
resolvedEnv?: Record<string, string>;
|
|
752
775
|
onUpdate?: AgentToolUpdateCallback<BashToolDetails>;
|
|
753
776
|
startBackgrounded: boolean;
|
|
777
|
+
/** Immutable attempt-scoped tool call id, when executed via a tool call. */
|
|
778
|
+
toolCallId?: string;
|
|
754
779
|
}): ManagedBashJobHandle {
|
|
755
|
-
const manager =
|
|
780
|
+
const manager = this.#resolveOwnedJobManager();
|
|
756
781
|
if (!manager) {
|
|
757
782
|
throw new ToolError("Background job manager unavailable for this session.");
|
|
758
783
|
}
|
|
@@ -840,6 +865,7 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
840
865
|
},
|
|
841
866
|
},
|
|
842
867
|
);
|
|
868
|
+
registerOwnedIfLineaged(manager, options.toolCallId, jobId, this.session.getSessionId?.() ?? undefined);
|
|
843
869
|
|
|
844
870
|
return {
|
|
845
871
|
jobId,
|
|
@@ -852,6 +878,24 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
852
878
|
};
|
|
853
879
|
}
|
|
854
880
|
|
|
881
|
+
/**
|
|
882
|
+
* The session's ENDPOINT-owned AsyncJobManager, falling back to the
|
|
883
|
+
* process-global instance. Concurrent top-level sessions each register
|
|
884
|
+
* their manager under their endpoint (sdk/session.ts), so a job created
|
|
885
|
+
* by THIS session must be stored in THIS session's manager — otherwise a
|
|
886
|
+
* Bash launched by session A lands in the last-created session B's
|
|
887
|
+
* manager while registering as A-owned, an A scope:"owned" abort then
|
|
888
|
+
* consults A's endpoint manager and cannot cancel the actual job, and a
|
|
889
|
+
* later missing-job settlement can retire the tuple while the job keeps
|
|
890
|
+
* running (review thread P1).
|
|
891
|
+
*/
|
|
892
|
+
#resolveOwnedJobManager(): AsyncJobManager | undefined {
|
|
893
|
+
const endpointId = this.session.getSessionId?.() ?? undefined;
|
|
894
|
+
return (
|
|
895
|
+
this.session.getAsyncJobManager?.() ?? AsyncJobManager.forEndpoint(endpointId) ?? AsyncJobManager.instance()
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
|
|
855
899
|
async #waitForManagedBashJob(
|
|
856
900
|
job: ManagedBashJobHandle,
|
|
857
901
|
thresholdMs: number,
|
|
@@ -1024,12 +1068,28 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1024
1068
|
),
|
|
1025
1069
|
)
|
|
1026
1070
|
: undefined;
|
|
1071
|
+
// Spawned workflow commands must resolve the SESSION's agent
|
|
1072
|
+
// profile: the child's getAgentDir() reads GJC_CODING_AGENT_DIR at
|
|
1073
|
+
// module load. Injected per-command (session-scoped), never
|
|
1074
|
+
// mutating the host process; an explicit tool-call env wins. The
|
|
1075
|
+
// session's REQUESTED directory (getSessionAgentDir) takes
|
|
1076
|
+
// precedence over the global Settings singleton, which may belong
|
|
1077
|
+
// to an earlier session.
|
|
1078
|
+
const sessionAgentDir = this.session.getSessionAgentDir?.() ?? this.session.settings?.getAgentDir?.();
|
|
1079
|
+
// An EXPLICIT tool-call env that supplies either supported spelling of
|
|
1080
|
+
// the agent-directory override wins over the session injection: the
|
|
1081
|
+
// child's getAgentDir() prefers GJC_CODING_AGENT_DIR, so injecting it
|
|
1082
|
+
// while the caller only set the legacy PI_CODING_AGENT_DIR alias would
|
|
1083
|
+
// silently ignore the caller's override.
|
|
1084
|
+
const explicitAgentDirOverride =
|
|
1085
|
+
expandedEnv?.GJC_CODING_AGENT_DIR !== undefined || expandedEnv?.PI_CODING_AGENT_DIR !== undefined;
|
|
1027
1086
|
const resolvedEnv = {
|
|
1028
1087
|
...buildGjcRuntimeSessionEnv({
|
|
1029
1088
|
sessionFile: null,
|
|
1030
1089
|
sessionId: this.session.getSessionId?.(),
|
|
1031
1090
|
cwd: this.session.cwd,
|
|
1032
1091
|
}),
|
|
1092
|
+
...(sessionAgentDir && !explicitAgentDirOverride ? { GJC_CODING_AGENT_DIR: sessionAgentDir } : {}),
|
|
1033
1093
|
...expandedEnv,
|
|
1034
1094
|
...(this.session.bashRestrictionProfile === "read-only" ? READ_ONLY_BASH_ENV : {}),
|
|
1035
1095
|
...(allowedPrefixes && allowedPrefixes.length > 0 ? { [GJC_RESTRICTED_ROLE_AGENT_BASH_ENV]: "1" } : {}),
|
|
@@ -1059,6 +1119,8 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1059
1119
|
const notices: string[] = [];
|
|
1060
1120
|
const timeoutClampNotice = formatTimeoutClampNotice(requestedTimeoutSec, timeoutSec);
|
|
1061
1121
|
if (timeoutClampNotice) notices.push(timeoutClampNotice);
|
|
1122
|
+
const sleepAdvisory = longSleepAdvisory(command, timeoutSec);
|
|
1123
|
+
if (sleepAdvisory) notices.push(sleepAdvisory);
|
|
1062
1124
|
|
|
1063
1125
|
return { command, commandCwd, resolvedEnv, requestedTimeoutSec, timeoutSec, timeoutMs, notices };
|
|
1064
1126
|
}
|
|
@@ -1078,12 +1140,13 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1078
1140
|
ownerId?: string;
|
|
1079
1141
|
label?: string;
|
|
1080
1142
|
ctx?: AgentToolContext;
|
|
1143
|
+
toolCallId?: string;
|
|
1081
1144
|
onRawLine?: (line: string, jobId: string) => void;
|
|
1082
1145
|
shouldAcceptRawLine?: (jobId: string) => boolean;
|
|
1083
1146
|
lifecycle?: import("../async").AsyncJobLifecycleCleanup;
|
|
1084
1147
|
} = {},
|
|
1085
1148
|
): Promise<{ jobId: string; label: string; commandCwd: string }> {
|
|
1086
|
-
const manager =
|
|
1149
|
+
const manager = this.#resolveOwnedJobManager();
|
|
1087
1150
|
if (!manager) {
|
|
1088
1151
|
throw new ToolError("Async job manager unavailable for this session.");
|
|
1089
1152
|
}
|
|
@@ -1181,12 +1244,16 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1181
1244
|
},
|
|
1182
1245
|
{ ownerId, metadata: { monitor: true }, lifecycle: opts.lifecycle },
|
|
1183
1246
|
);
|
|
1247
|
+
// Monitor jobs are exact owned background work of the turn that started
|
|
1248
|
+
// them: register the five-tuple so scope:"owned" terminal abort stops the
|
|
1249
|
+
// monitor too (review thread P2).
|
|
1250
|
+
registerOwnedIfLineaged(manager, opts.toolCallId, jobId, this.session.getSessionId?.() ?? undefined);
|
|
1184
1251
|
currentJobId = jobId;
|
|
1185
1252
|
return { jobId, label, commandCwd: prepared.commandCwd };
|
|
1186
1253
|
}
|
|
1187
1254
|
|
|
1188
1255
|
async execute(
|
|
1189
|
-
|
|
1256
|
+
toolCallId: string,
|
|
1190
1257
|
{
|
|
1191
1258
|
command: rawCommand,
|
|
1192
1259
|
env: rawEnv,
|
|
@@ -1222,7 +1289,11 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1222
1289
|
} = prepared;
|
|
1223
1290
|
|
|
1224
1291
|
if (asyncRequested) {
|
|
1225
|
-
|
|
1292
|
+
// Availability is endpoint-first: a concurrent top-level session
|
|
1293
|
+
// that was the process-global instance may have been disposed,
|
|
1294
|
+
// clearing instance() while THIS session's manager stays
|
|
1295
|
+
// registered by endpoint (review thread P1).
|
|
1296
|
+
if (!this.#resolveOwnedJobManager()) {
|
|
1226
1297
|
throw new ToolError("Async job manager unavailable for this session.");
|
|
1227
1298
|
}
|
|
1228
1299
|
const job = this.#startManagedBashJob({
|
|
@@ -1236,6 +1307,7 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1236
1307
|
resolvedEnv,
|
|
1237
1308
|
onUpdate,
|
|
1238
1309
|
startBackgrounded: true,
|
|
1310
|
+
toolCallId,
|
|
1239
1311
|
});
|
|
1240
1312
|
return this.#buildBackgroundStartResult(job.jobId, job.label, "", timeoutSec, {
|
|
1241
1313
|
requestedTimeoutSec,
|
|
@@ -1249,11 +1321,15 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1249
1321
|
this.session.bashRestrictionProfile === "read-only" ? undefined : this.session.getClientBridge?.();
|
|
1250
1322
|
const clientTerminalActive = Boolean(clientBridge?.capabilities.terminal && clientBridge.createTerminal && !pty);
|
|
1251
1323
|
|
|
1252
|
-
const autoBgManager = AsyncJobManager.instance();
|
|
1253
1324
|
// Run non-PTY bash through the managed job path so Ctrl+B-twice fold-on-demand works
|
|
1254
1325
|
// even when auto-background is disabled. When a client terminal will handle the
|
|
1255
1326
|
// command, keep the existing bridge path unless auto-background is enabled.
|
|
1256
|
-
|
|
1327
|
+
// The manager is resolved ONCE from the session's endpoint (same instance the
|
|
1328
|
+
// job was created in) and reused for creation, acknowledgement, cancellation,
|
|
1329
|
+
// and unregistering — the process-global instance may belong to a different
|
|
1330
|
+
// concurrent top-level session (review thread P1).
|
|
1331
|
+
const ownedManager = this.#resolveOwnedJobManager();
|
|
1332
|
+
if (!pty && ownedManager && (this.#autoBackgroundEnabled || !clientTerminalActive)) {
|
|
1257
1333
|
// With auto-background off, wait past the command's own timeout so the job only
|
|
1258
1334
|
// leaves the foreground on an explicit Ctrl+B fold, never on an auto-background timer.
|
|
1259
1335
|
const autoBackgroundWaitMs = this.#autoBackgroundEnabled
|
|
@@ -1271,6 +1347,7 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1271
1347
|
resolvedEnv,
|
|
1272
1348
|
onUpdate,
|
|
1273
1349
|
startBackgrounded,
|
|
1350
|
+
toolCallId,
|
|
1274
1351
|
});
|
|
1275
1352
|
if (startBackgrounded) {
|
|
1276
1353
|
return this.#buildBackgroundStartResult(job.jobId, job.label, "", timeoutSec, {
|
|
@@ -1295,17 +1372,20 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1295
1372
|
unregisterBackgroundRequest?.();
|
|
1296
1373
|
}
|
|
1297
1374
|
if (waitResult.kind === "completed") {
|
|
1298
|
-
|
|
1375
|
+
ownedManager.acknowledgeDeliveries([job.jobId]);
|
|
1376
|
+
unregisterForegroundOwnedBash(ownedManager, job.jobId, this.session.getSessionId?.() ?? "local");
|
|
1299
1377
|
return waitResult.result;
|
|
1300
1378
|
}
|
|
1301
1379
|
if (waitResult.kind === "failed") {
|
|
1302
|
-
|
|
1380
|
+
ownedManager.acknowledgeDeliveries([job.jobId]);
|
|
1381
|
+
unregisterForegroundOwnedBash(ownedManager, job.jobId, this.session.getSessionId?.() ?? "local");
|
|
1303
1382
|
throw waitResult.error;
|
|
1304
1383
|
}
|
|
1305
1384
|
if (waitResult.kind === "aborted") {
|
|
1306
|
-
|
|
1385
|
+
ownedManager.cancel(job.jobId);
|
|
1307
1386
|
const terminal = await job.completion;
|
|
1308
|
-
|
|
1387
|
+
ownedManager.acknowledgeDeliveries([job.jobId]);
|
|
1388
|
+
unregisterForegroundOwnedBash(ownedManager, job.jobId, this.session.getSessionId?.() ?? "local");
|
|
1309
1389
|
if (terminal.kind === "failed") {
|
|
1310
1390
|
throw new ToolAbortError(
|
|
1311
1391
|
formatManagedAbortFailure(terminal.error, terminal.result, job.getLatestText()),
|
|
@@ -1585,20 +1665,20 @@ export class BashTool implements AgentTool<BashToolSchema, BashToolDetails> {
|
|
|
1585
1665
|
disableShellSnapshot: this.session.bashRestrictionProfile === "read-only",
|
|
1586
1666
|
});
|
|
1587
1667
|
if (result.cancelled) {
|
|
1588
|
-
const
|
|
1589
|
-
|
|
1590
|
-
normalizeResultOutput(result) || "Command aborted",
|
|
1591
|
-
signal?.aborted ? "Command aborted" : undefined,
|
|
1592
|
-
);
|
|
1668
|
+
const noticeSuffix = pendingNotices.length > 0 ? `\n\n${pendingNotices.join("\n")}` : "";
|
|
1669
|
+
const baseCancelledText = normalizeResultOutput(result) || "Command aborted";
|
|
1593
1670
|
if (signal?.aborted) {
|
|
1594
|
-
throw new ToolAbortError(
|
|
1671
|
+
throw new ToolAbortError(formatBashFailureMessage(result, baseCancelledText, "Command aborted"));
|
|
1595
1672
|
}
|
|
1596
|
-
|
|
1673
|
+
const failureText = `${baseCancelledText}${noticeSuffix}`;
|
|
1674
|
+
throw new ToolError(formatBashFailureMessage(result, failureText));
|
|
1597
1675
|
}
|
|
1598
1676
|
if (isInteractiveResult(result) && result.timedOut) {
|
|
1599
1677
|
const timeoutMessage = `Command timed out after ${timeoutSec} seconds`;
|
|
1600
1678
|
const output = normalizeResultOutput(result);
|
|
1601
|
-
const
|
|
1679
|
+
const noticeSuffix = pendingNotices.length > 0 ? `\n\n${pendingNotices.join("\n")}` : "";
|
|
1680
|
+
const baseText = output ? `${output}\n\n${timeoutMessage}` : timeoutMessage;
|
|
1681
|
+
const failureText = `${baseText}${noticeSuffix}`;
|
|
1602
1682
|
throw new ToolError(formatBashFailureMessage(result, failureText, timeoutMessage));
|
|
1603
1683
|
}
|
|
1604
1684
|
return this.#buildCompletedResult(result, timeoutSec, {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
1
2
|
import * as net from "node:net";
|
|
2
3
|
import * as path from "node:path";
|
|
3
4
|
import { nativeProcessBindings } from "@gajae-code/utils/native-process";
|
|
4
5
|
import type { Browser, Page } from "puppeteer-core";
|
|
5
6
|
import { ToolError, throwIfAborted } from "../tool-errors";
|
|
7
|
+
import { isChromeProfileExecutable } from "./launch";
|
|
6
8
|
|
|
7
9
|
const ATTACH_TARGET_SKIP_PATTERN =
|
|
8
10
|
/request[\s_-]?handler|devtools|background[\s_-]?(?:page|host)|service[\s_-]?worker/i;
|
|
@@ -133,8 +135,10 @@ async function probeCdpAt(port: number, signal?: AbortSignal): Promise<boolean>
|
|
|
133
135
|
try {
|
|
134
136
|
const res = await fetch(`http://127.0.0.1:${port}/json/version`, { signal: probeSignal });
|
|
135
137
|
await res.body?.cancel();
|
|
138
|
+
throwIfAborted(signal);
|
|
136
139
|
return res.ok;
|
|
137
140
|
} catch {
|
|
141
|
+
throwIfAborted(signal);
|
|
138
142
|
return false;
|
|
139
143
|
}
|
|
140
144
|
}
|
|
@@ -181,6 +185,7 @@ export async function findReusableCdp(
|
|
|
181
185
|
if (await probeCdpAt(port, signal)) {
|
|
182
186
|
return { cdpUrl: `http://127.0.0.1:${port}`, pid: proc.pid };
|
|
183
187
|
}
|
|
188
|
+
throwIfAborted(signal);
|
|
184
189
|
}
|
|
185
190
|
return null;
|
|
186
191
|
}
|
|
@@ -196,10 +201,64 @@ export async function findRunningChromeProfile(
|
|
|
196
201
|
profile: { userDataDir: string; profileDirectory: string },
|
|
197
202
|
signal?: AbortSignal,
|
|
198
203
|
): Promise<RunningChromeProfile | null> {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
return findRunningChromeProfileWithOptions(exe, profile, signal, {});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface ProfileProcessScanOptions {
|
|
208
|
+
platform?: NodeJS.Platform;
|
|
209
|
+
linuxPids?: readonly number[];
|
|
210
|
+
linuxExecutablePaths?: ReadonlyMap<number, string>;
|
|
211
|
+
signal?: AbortSignal;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function liveLinuxPids(): Promise<number[]> {
|
|
215
|
+
try {
|
|
216
|
+
const entries = await fs.readdir("/proc", { withFileTypes: true });
|
|
217
|
+
return entries
|
|
218
|
+
.filter(entry => entry.isDirectory() && /^\d+$/.test(entry.name))
|
|
219
|
+
.map(entry => Number.parseInt(entry.name, 10));
|
|
220
|
+
} catch {
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function linuxExecutablePath(pid: number, options: ProfileProcessScanOptions): Promise<string | null> {
|
|
226
|
+
const injected = options.linuxExecutablePaths?.get(pid);
|
|
227
|
+
if (injected) return injected;
|
|
228
|
+
try {
|
|
229
|
+
return await fs.readlink(`/proc/${pid}/exe`);
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function findRunningChromeProfileWithOptions(
|
|
236
|
+
exe: string,
|
|
237
|
+
profile: { userDataDir: string; profileDirectory: string },
|
|
238
|
+
signal: AbortSignal | undefined,
|
|
239
|
+
options: ProfileProcessScanOptions,
|
|
240
|
+
): Promise<RunningChromeProfile | null> {
|
|
241
|
+
const bindings = nativeProcessBindings();
|
|
242
|
+
const candidates = bindings.Process.fromPath(exe).filter(p => p.status() === bindings.ProcessStatus.Running);
|
|
243
|
+
const seenPids = new Set(candidates.map(candidate => candidate.pid));
|
|
244
|
+
if ((options.platform ?? process.platform) === "linux" && candidates.length === 0) {
|
|
245
|
+
throwIfAborted(signal);
|
|
246
|
+
const linuxPids = options.linuxPids ?? (await liveLinuxPids());
|
|
247
|
+
throwIfAborted(signal);
|
|
248
|
+
for (const pid of linuxPids) {
|
|
249
|
+
throwIfAborted(signal);
|
|
250
|
+
if (seenPids.has(pid)) continue;
|
|
251
|
+
const candidate = bindings.Process.fromPid(pid);
|
|
252
|
+
if (!candidate || candidate.status() !== bindings.ProcessStatus.Running) continue;
|
|
253
|
+
const executablePath = await linuxExecutablePath(pid, options);
|
|
254
|
+
throwIfAborted(signal);
|
|
255
|
+
if (!executablePath || !isChromeProfileExecutable(executablePath)) continue;
|
|
256
|
+
seenPids.add(pid);
|
|
257
|
+
candidates.push(candidate);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
202
260
|
for (const proc of candidates) {
|
|
261
|
+
throwIfAborted(signal);
|
|
203
262
|
let args: string[];
|
|
204
263
|
try {
|
|
205
264
|
args = proc.args();
|
|
@@ -216,12 +275,21 @@ export async function findRunningChromeProfile(
|
|
|
216
275
|
if (await probeCdpAt(port, signal)) {
|
|
217
276
|
return { pid: proc.pid, cdpUrl: `http://127.0.0.1:${port}` };
|
|
218
277
|
}
|
|
278
|
+
throwIfAborted(signal);
|
|
219
279
|
}
|
|
220
280
|
return { pid: proc.pid, cdpUrl: null };
|
|
221
281
|
}
|
|
222
282
|
return null;
|
|
223
283
|
}
|
|
224
284
|
|
|
285
|
+
export function findRunningChromeProfileForTest(
|
|
286
|
+
exe: string,
|
|
287
|
+
profile: { userDataDir: string; profileDirectory: string },
|
|
288
|
+
options: ProfileProcessScanOptions,
|
|
289
|
+
): Promise<RunningChromeProfile | null> {
|
|
290
|
+
return findRunningChromeProfileWithOptions(exe, profile, options.signal, options);
|
|
291
|
+
}
|
|
292
|
+
|
|
225
293
|
/**
|
|
226
294
|
* Pick the best page target on an attached browser. Without a matcher, prefer
|
|
227
295
|
* a page that doesn't look like a helper window (devtools, request handler,
|
|
@@ -108,12 +108,18 @@ export function resolveBrowserEnvOverridesForTest(): {
|
|
|
108
108
|
proxy: string | undefined;
|
|
109
109
|
proxyBypassLoopback: boolean;
|
|
110
110
|
ignoreCertErrors: boolean;
|
|
111
|
+
programFiles: string | undefined;
|
|
112
|
+
programFilesX86: string | undefined;
|
|
113
|
+
localAppData: string | undefined;
|
|
111
114
|
} {
|
|
112
115
|
return {
|
|
113
116
|
executablePath: trustedBrowserEnv("PUPPETEER_EXECUTABLE_PATH"),
|
|
114
117
|
proxy: trustedBrowserEnv("PUPPETEER_PROXY"),
|
|
115
118
|
proxyBypassLoopback: browserLaunchFlagEnabled("PUPPETEER_PROXY_BYPASS_LOOPBACK"),
|
|
116
119
|
ignoreCertErrors: browserLaunchFlagEnabled("PUPPETEER_PROXY_IGNORE_CERT_ERRORS"),
|
|
120
|
+
programFiles: trustedBrowserEnv("ProgramFiles"),
|
|
121
|
+
programFilesX86: trustedBrowserEnv("ProgramFiles(x86)"),
|
|
122
|
+
localAppData: trustedBrowserEnv("LOCALAPPDATA"),
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
|
|
@@ -208,7 +214,16 @@ function systemChromiumCandidates(): string[] {
|
|
|
208
214
|
break;
|
|
209
215
|
}
|
|
210
216
|
case "linux": {
|
|
211
|
-
const names = [
|
|
217
|
+
const names = [
|
|
218
|
+
"google-chrome-stable",
|
|
219
|
+
"google-chrome",
|
|
220
|
+
"google-chrome-beta",
|
|
221
|
+
"google-chrome-unstable",
|
|
222
|
+
"google-chrome-canary",
|
|
223
|
+
"chromium",
|
|
224
|
+
"chromium-browser",
|
|
225
|
+
"chrome",
|
|
226
|
+
];
|
|
212
227
|
for (const name of names) {
|
|
213
228
|
const found = $which(name);
|
|
214
229
|
if (found) candidates.push(found);
|
|
@@ -216,6 +231,9 @@ function systemChromiumCandidates(): string[] {
|
|
|
216
231
|
candidates.push(
|
|
217
232
|
"/usr/bin/google-chrome-stable",
|
|
218
233
|
"/usr/bin/google-chrome",
|
|
234
|
+
"/usr/bin/google-chrome-beta",
|
|
235
|
+
"/usr/bin/google-chrome-unstable",
|
|
236
|
+
"/usr/bin/google-chrome-canary",
|
|
219
237
|
"/usr/bin/chromium",
|
|
220
238
|
"/usr/bin/chromium-browser",
|
|
221
239
|
"/snap/bin/chromium",
|
|
@@ -232,13 +250,20 @@ function systemChromiumCandidates(): string[] {
|
|
|
232
250
|
break;
|
|
233
251
|
}
|
|
234
252
|
case "win32": {
|
|
235
|
-
const programFiles =
|
|
236
|
-
const programFilesX86 =
|
|
237
|
-
const localAppData =
|
|
253
|
+
const programFiles = trustedBrowserEnv("ProgramFiles") ?? "C:\\Program Files";
|
|
254
|
+
const programFilesX86 = trustedBrowserEnv("ProgramFiles(x86)") ?? "C:\\Program Files (x86)";
|
|
255
|
+
const localAppData = trustedBrowserEnv("LOCALAPPDATA") ?? path.join(home, "AppData\\Local");
|
|
238
256
|
candidates.push(
|
|
239
257
|
path.join(programFiles, "Google\\Chrome\\Application\\chrome.exe"),
|
|
240
258
|
path.join(programFilesX86, "Google\\Chrome\\Application\\chrome.exe"),
|
|
241
259
|
path.join(localAppData, "Google\\Chrome\\Application\\chrome.exe"),
|
|
260
|
+
path.join(programFiles, "Google\\Chrome Beta\\Application\\chrome.exe"),
|
|
261
|
+
path.join(programFilesX86, "Google\\Chrome Beta\\Application\\chrome.exe"),
|
|
262
|
+
path.join(localAppData, "Google\\Chrome Beta\\Application\\chrome.exe"),
|
|
263
|
+
path.join(programFiles, "Google\\Chrome Dev\\Application\\chrome.exe"),
|
|
264
|
+
path.join(programFilesX86, "Google\\Chrome Dev\\Application\\chrome.exe"),
|
|
265
|
+
path.join(localAppData, "Google\\Chrome Dev\\Application\\chrome.exe"),
|
|
266
|
+
path.join(localAppData, "Google\\Chrome SxS\\Application\\chrome.exe"),
|
|
242
267
|
path.join(programFiles, "Chromium\\Application\\chrome.exe"),
|
|
243
268
|
path.join(localAppData, "Chromium\\Application\\chrome.exe"),
|
|
244
269
|
path.join(programFiles, "Microsoft\\Edge\\Application\\msedge.exe"),
|
|
@@ -250,22 +275,70 @@ function systemChromiumCandidates(): string[] {
|
|
|
250
275
|
return candidates;
|
|
251
276
|
}
|
|
252
277
|
|
|
253
|
-
function
|
|
254
|
-
if (resolvedChromium !== undefined) return resolvedChromium ?? undefined;
|
|
278
|
+
function firstExecutableCandidate(candidates: string[], accept: (candidate: string) => boolean): string | undefined {
|
|
255
279
|
const seen = new Set<string>();
|
|
256
|
-
for (const candidate of
|
|
280
|
+
for (const candidate of candidates) {
|
|
257
281
|
if (!candidate || seen.has(candidate)) continue;
|
|
258
282
|
seen.add(candidate);
|
|
259
|
-
if (isExecutableFile(candidate))
|
|
260
|
-
resolvedChromium = candidate;
|
|
261
|
-
logger.debug("Using system Chrome/Chromium", { path: candidate });
|
|
262
|
-
return candidate;
|
|
263
|
-
}
|
|
283
|
+
if (accept(candidate) && isExecutableFile(candidate)) return candidate;
|
|
264
284
|
}
|
|
265
|
-
resolvedChromium = null;
|
|
266
285
|
return undefined;
|
|
267
286
|
}
|
|
268
287
|
|
|
288
|
+
function resolveSystemChromium(): string | undefined {
|
|
289
|
+
if (resolvedChromium !== undefined) return resolvedChromium ?? undefined;
|
|
290
|
+
const found = firstExecutableCandidate(systemChromiumCandidates(), () => true);
|
|
291
|
+
resolvedChromium = found ?? null;
|
|
292
|
+
if (found) logger.debug("Using system Chrome/Chromium", { path: found });
|
|
293
|
+
return found;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Edge is Chromium-based but keeps its own profile format under its own user data root. */
|
|
297
|
+
const EDGE_EXECUTABLE_PATTERN =
|
|
298
|
+
/(?:^|[/\\])(?:msedge(?:\.exe)?|microsoft-edge(?:-(?:stable|beta|dev|canary))?|com\.microsoft\.Edge|Microsoft Edge(?: Beta| Dev| Canary)?)$/i;
|
|
299
|
+
|
|
300
|
+
/** True for a Microsoft Edge executable path (excluded from Chrome profile mode). */
|
|
301
|
+
export function isEdgeExecutable(candidate: string): boolean {
|
|
302
|
+
return EDGE_EXECUTABLE_PATTERN.test(candidate);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const CHROME_PROFILE_EXECUTABLE_PATTERN =
|
|
306
|
+
/(?:^|[/\\])(?:google-chrome(?:-(?:stable|beta|unstable|canary))?|chromium(?:-browser)?|chrome(?:\.exe)?|Google Chrome(?: Beta| Dev| Canary)?|Chromium|com\.google\.Chrome|org\.chromium\.Chromium)$/i;
|
|
307
|
+
|
|
308
|
+
/** True only for executable names owned by Google Chrome or Chromium. */
|
|
309
|
+
export function isChromeProfileExecutable(candidate: string): boolean {
|
|
310
|
+
return CHROME_PROFILE_EXECUTABLE_PATTERN.test(candidate);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Validate the executable identity used for profile mode. Most symlinks are
|
|
315
|
+
* judged by their resolved target so a renamed cross-brand browser cannot pass
|
|
316
|
+
* by alias. Snap's canonical `/snap/bin/chromium` launcher is the exception:
|
|
317
|
+
* it resolves to the generic `/usr/bin/snap` dispatcher by design.
|
|
318
|
+
*/
|
|
319
|
+
export function isChromeProfileExecutableForLaunch(candidate: string, resolvedCandidate: string): boolean {
|
|
320
|
+
return (
|
|
321
|
+
(path.posix.normalize(candidate) === "/snap/bin/chromium" &&
|
|
322
|
+
path.posix.normalize(resolvedCandidate) === "/usr/bin/snap") ||
|
|
323
|
+
isChromeProfileExecutable(resolvedCandidate)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
let resolvedProfileChrome: string | null | undefined; // undefined = unchecked; null = not found
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Installed Chrome/Chromium executable for saved-profile mode, or undefined when
|
|
331
|
+
* none is present. Edge is excluded on purpose: a discovered Chrome user data
|
|
332
|
+
* directory must never be opened by a different browser brand.
|
|
333
|
+
*/
|
|
334
|
+
export function resolveSystemChromeForProfile(): string | undefined {
|
|
335
|
+
if (resolvedProfileChrome !== undefined) return resolvedProfileChrome ?? undefined;
|
|
336
|
+
const found = firstExecutableCandidate(systemChromiumCandidates(), isChromeProfileExecutable);
|
|
337
|
+
resolvedProfileChrome = found ?? null;
|
|
338
|
+
if (found) logger.debug("Using system Chrome/Chromium for profile mode", { path: found });
|
|
339
|
+
return found;
|
|
340
|
+
}
|
|
341
|
+
|
|
269
342
|
export interface LaunchHeadlessOptions {
|
|
270
343
|
headless: boolean;
|
|
271
344
|
viewport?: { width: number; height: number; deviceScaleFactor?: number };
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import * as os from "node:os";
|
|
12
12
|
import * as path from "node:path";
|
|
13
|
+
import { $credentialEnv } from "@gajae-code/utils/env";
|
|
13
14
|
|
|
14
15
|
export interface DiscoveryEnv {
|
|
15
16
|
platform: NodeJS.Platform;
|
|
@@ -18,19 +19,55 @@ export interface DiscoveryEnv {
|
|
|
18
19
|
exists: (p: string) => boolean;
|
|
19
20
|
/** Windows LOCALAPPDATA override (tests / non-default installs). */
|
|
20
21
|
localAppData?: string;
|
|
22
|
+
/** Linux Chrome-specific default user-data override. */
|
|
23
|
+
chromeUserDataDir?: string;
|
|
24
|
+
/** Linux Chrome config-home override (takes precedence over XDG_CONFIG_HOME). */
|
|
25
|
+
chromeConfigHome?: string;
|
|
26
|
+
/** Linux XDG config-home override. */
|
|
27
|
+
xdgConfigHome?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function discoveryPath(env: DiscoveryEnv): typeof path.posix {
|
|
31
|
+
return env.platform === "win32" ? path.win32 : path.posix;
|
|
21
32
|
}
|
|
22
33
|
|
|
23
34
|
/** Candidate Chrome user-data roots for the platform (most common first). */
|
|
24
35
|
export function chromeUserDataRoots(env: DiscoveryEnv): string[] {
|
|
36
|
+
const platformPath = discoveryPath(env);
|
|
25
37
|
switch (env.platform) {
|
|
26
38
|
case "darwin":
|
|
27
|
-
return [
|
|
39
|
+
return [
|
|
40
|
+
platformPath.join(env.home, "Library", "Application Support", "Google", "Chrome"),
|
|
41
|
+
platformPath.join(env.home, "Library", "Application Support", "Google", "Chrome Beta"),
|
|
42
|
+
platformPath.join(env.home, "Library", "Application Support", "Google", "Chrome Dev"),
|
|
43
|
+
platformPath.join(env.home, "Library", "Application Support", "Google", "Chrome Canary"),
|
|
44
|
+
platformPath.join(env.home, "Library", "Application Support", "Chromium"),
|
|
45
|
+
];
|
|
28
46
|
case "win32": {
|
|
29
|
-
const localAppData = env.localAppData ??
|
|
30
|
-
return [
|
|
47
|
+
const localAppData = env.localAppData ?? platformPath.join(env.home, "AppData", "Local");
|
|
48
|
+
return [
|
|
49
|
+
platformPath.join(localAppData, "Google", "Chrome", "User Data"),
|
|
50
|
+
platformPath.join(localAppData, "Google", "Chrome Beta", "User Data"),
|
|
51
|
+
platformPath.join(localAppData, "Google", "Chrome Dev", "User Data"),
|
|
52
|
+
platformPath.join(localAppData, "Google", "Chrome SxS", "User Data"),
|
|
53
|
+
platformPath.join(localAppData, "Chromium", "User Data"),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
default: {
|
|
57
|
+
const configHome = env.chromeConfigHome ?? env.xdgConfigHome ?? platformPath.join(env.home, ".config");
|
|
58
|
+
return [
|
|
59
|
+
...(env.chromeUserDataDir ? [env.chromeUserDataDir] : []),
|
|
60
|
+
platformPath.join(configHome, "google-chrome"),
|
|
61
|
+
platformPath.join(configHome, "google-chrome-beta"),
|
|
62
|
+
platformPath.join(configHome, "google-chrome-unstable"),
|
|
63
|
+
platformPath.join(configHome, "google-chrome-canary"),
|
|
64
|
+
platformPath.join(configHome, "chromium"),
|
|
65
|
+
platformPath.join(env.home, ".var", "app", "com.google.Chrome", "config", "google-chrome"),
|
|
66
|
+
platformPath.join(env.home, ".var", "app", "org.chromium.Chromium", "config", "chromium"),
|
|
67
|
+
platformPath.join(env.home, "snap", "chromium", "common", "chromium"),
|
|
68
|
+
platformPath.join(env.home, "snap", "chromium", "current", ".config", "chromium"),
|
|
69
|
+
];
|
|
31
70
|
}
|
|
32
|
-
default:
|
|
33
|
-
return [path.join(env.home, ".config", "google-chrome"), path.join(env.home, ".config", "chromium")];
|
|
34
71
|
}
|
|
35
72
|
}
|
|
36
73
|
|
|
@@ -48,8 +85,9 @@ export function discoverDefaultChromeProfile(
|
|
|
48
85
|
env: DiscoveryEnv,
|
|
49
86
|
profileDirectory = "Default",
|
|
50
87
|
): DiscoveredProfile | null {
|
|
88
|
+
const platformPath = discoveryPath(env);
|
|
51
89
|
for (const userDataDir of chromeUserDataRoots(env)) {
|
|
52
|
-
const profileDir =
|
|
90
|
+
const profileDir = platformPath.join(userDataDir, profileDirectory);
|
|
53
91
|
if (env.exists(profileDir)) {
|
|
54
92
|
return { userDataDir, profileDirectory, profileDir };
|
|
55
93
|
}
|
|
@@ -59,5 +97,17 @@ export function discoverDefaultChromeProfile(
|
|
|
59
97
|
|
|
60
98
|
/** Convenience wrapper using the live OS environment + fs. */
|
|
61
99
|
export function defaultDiscoveryEnv(exists: (p: string) => boolean): DiscoveryEnv {
|
|
62
|
-
|
|
100
|
+
const localAppData = $credentialEnv("LOCALAPPDATA");
|
|
101
|
+
const chromeUserDataDir = $credentialEnv("CHROME_USER_DATA_DIR");
|
|
102
|
+
const chromeConfigHome = $credentialEnv("CHROME_CONFIG_HOME");
|
|
103
|
+
const xdgConfigHome = $credentialEnv("XDG_CONFIG_HOME");
|
|
104
|
+
return {
|
|
105
|
+
platform: process.platform,
|
|
106
|
+
home: os.homedir(),
|
|
107
|
+
exists,
|
|
108
|
+
...(localAppData ? { localAppData } : {}),
|
|
109
|
+
...(chromeUserDataDir ? { chromeUserDataDir } : {}),
|
|
110
|
+
...(chromeConfigHome ? { chromeConfigHome } : {}),
|
|
111
|
+
...(xdgConfigHome ? { xdgConfigHome } : {}),
|
|
112
|
+
};
|
|
63
113
|
}
|
|
@@ -42,7 +42,7 @@ interface BrowserRenderContext {
|
|
|
42
42
|
|
|
43
43
|
function describeBrowser(args: BrowserRenderArgs, details: BrowserToolDetails | undefined): string | undefined {
|
|
44
44
|
if (args.app?.cdp_url) return `connected ${args.app.cdp_url}`;
|
|
45
|
-
if (args.app?.browser === "chrome") return `Chrome profile ${args.app.profile_directory ?? "
|
|
45
|
+
if (args.app?.browser === "chrome") return `Chrome profile ${args.app.profile_directory ?? "Default"}`;
|
|
46
46
|
if (args.app?.path) return `spawned ${shortenPath(args.app.path)}`;
|
|
47
47
|
switch (details?.browser) {
|
|
48
48
|
case "headless":
|
|
@@ -56,6 +56,13 @@ function describeBrowser(args: BrowserRenderArgs, details: BrowserToolDetails |
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
export function describeBrowserForTest(
|
|
60
|
+
args: BrowserRenderArgs,
|
|
61
|
+
details: BrowserToolDetails | undefined,
|
|
62
|
+
): string | undefined {
|
|
63
|
+
return describeBrowser(args, details);
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
function tabLabel(args: BrowserRenderArgs, details: BrowserToolDetails | undefined): string {
|
|
60
67
|
const name = details?.name ?? args.name ?? "main";
|
|
61
68
|
return `tab ${JSON.stringify(name)}`;
|