@gajae-code/coding-agent 0.10.2 → 0.11.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 +50 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/cli/args.d.ts +4 -5
- package/dist/types/cli/daemon-cli.d.ts +12 -1
- package/dist/types/cli/notify-cli.d.ts +21 -1
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/notify.d.ts +28 -1
- package/dist/types/commands/sdk.d.ts +33 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
- package/dist/types/config/model-profile-activation.d.ts +35 -15
- package/dist/types/config/model-profiles.d.ts +11 -5
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/model-resolver.d.ts +39 -6
- package/dist/types/config/model-selector-value.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +10 -6
- package/dist/types/config/settings-schema.d.ts +133 -6
- package/dist/types/config/settings.d.ts +63 -35
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
- package/dist/types/coordinator-mcp/server.d.ts +6 -49
- package/dist/types/daemon/builtin.d.ts +6 -5
- package/dist/types/daemon/control-types.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +12 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
- package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +10 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -3
- package/dist/types/extensibility/extensions/types.d.ts +141 -16
- package/dist/types/extensibility/hooks/types.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
- package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
- package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
- package/dist/types/harness-control-plane/operate.d.ts +5 -5
- package/dist/types/harness-control-plane/owner.d.ts +18 -4
- package/dist/types/harness-control-plane/receipts.d.ts +0 -1
- package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
- package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
- package/dist/types/harness-control-plane/types.d.ts +3 -4
- package/dist/types/lsp/index.d.ts +1 -1
- package/dist/types/main.d.ts +32 -38
- package/dist/types/modes/acp/acp-agent.d.ts +224 -53
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
- package/dist/types/modes/acp/acp-mode.d.ts +6 -15
- package/dist/types/modes/acp/permission-mode.d.ts +4 -0
- package/dist/types/modes/acp/startup-options.d.ts +6 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -4
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
- package/dist/types/modes/index.d.ts +0 -4
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/runtime-init.d.ts +2 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
- package/dist/types/modes/types.d.ts +5 -0
- package/dist/types/runtime-mcp/client.d.ts +2 -0
- package/dist/types/runtime-mcp/config.d.ts +5 -1
- package/dist/types/runtime-mcp/manager.d.ts +8 -1
- package/dist/types/runtime-mcp/types.d.ts +4 -0
- package/dist/types/sdk/acp/adapter.d.ts +67 -0
- package/dist/types/sdk/acp/index.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +53 -0
- package/dist/types/sdk/broker/discovery.d.ts +30 -0
- package/dist/types/sdk/broker/ensure.d.ts +33 -0
- package/dist/types/sdk/broker/identity.d.ts +3 -0
- package/dist/types/sdk/broker/index.d.ts +8 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
- package/dist/types/sdk/broker/runtime.d.ts +33 -0
- package/dist/types/sdk/broker/session-index.d.ts +57 -0
- package/dist/types/sdk/broker/state-version.d.ts +8 -0
- package/dist/types/sdk/broker/transport.d.ts +9 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
- package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
- package/dist/types/sdk/bus/config.d.ts +274 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
- package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
- package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
- package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
- package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
- package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
- package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
- package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
- package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
- package/dist/types/sdk/bus/session-control.d.ts +83 -0
- package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
- package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
- package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
- package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/session-cli.d.ts +19 -0
- package/dist/types/sdk/client/client.d.ts +1 -0
- package/dist/types/sdk/client/discovery.d.ts +27 -0
- package/dist/types/sdk/client/index.d.ts +2 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
- package/dist/types/sdk/host/control/index.d.ts +2 -0
- package/dist/types/sdk/host/control/operations.d.ts +65 -0
- package/dist/types/sdk/host/events.d.ts +35 -0
- package/dist/types/sdk/host/host.d.ts +35 -0
- package/dist/types/sdk/host/index.d.ts +4 -0
- package/dist/types/sdk/host/query/cursor.d.ts +62 -0
- package/dist/types/sdk/host/query/handlers.d.ts +70 -0
- package/dist/types/sdk/host/query/index.d.ts +3 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
- package/dist/types/sdk/host/types.d.ts +32 -0
- package/dist/types/sdk/index.d.ts +6 -0
- package/dist/types/sdk/lifecycle-session.d.ts +14 -0
- package/dist/types/sdk/mcp/index.d.ts +1 -0
- package/dist/types/sdk/mcp/server.d.ts +37 -0
- package/dist/types/sdk/models.d.ts +44 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
- package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
- package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
- package/dist/types/sdk/startup-capability.d.ts +50 -0
- package/dist/types/session/agent-session.d.ts +114 -21
- package/dist/types/session/default-model-selection.d.ts +25 -0
- package/dist/types/session/fallback-chain-controller.d.ts +52 -0
- package/dist/types/session/session-manager.d.ts +58 -1
- package/dist/types/setup/credential-auto-import.d.ts +36 -6
- package/dist/types/tools/ask-answer-registry.d.ts +1 -1
- package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
- package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
- package/dist/types/tools/browser/launch.d.ts +22 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
- package/dist/types/tools/browser/profile-posture.d.ts +37 -0
- package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
- package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
- package/dist/types/tools/browser/registry.d.ts +19 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +8 -8
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +94 -0
- package/scripts/capture-notifications-settings-showcase.ts +435 -0
- package/scripts/compile-args.ts +4 -2
- package/scripts/g005-daemon-smoke.ts +4 -5
- package/scripts/g011-daemon-path-smoke.ts +5 -5
- package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
- package/scripts/generate-sdk-operation-inventory.ts +867 -0
- package/scripts/generate-telegram-baseline-manifest.ts +128 -0
- package/scripts/manifest-schema.ts +124 -0
- package/scripts/run-test-manifest.ts +153 -0
- package/scripts/run-threat-model-check.ts +157 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
- package/scripts/verify-gjc-sdk-rename.ts +90 -0
- package/src/append-only-mode.ts +1 -1
- package/src/cli/args.ts +43 -12
- package/src/cli/auth-gateway-cli.ts +2 -2
- package/src/cli/config-cli.ts +2 -1
- package/src/cli/daemon-cli.ts +63 -14
- package/src/cli/list-models.ts +1 -1
- package/src/cli/notify-cli.ts +288 -286
- package/src/cli.ts +21 -2
- package/src/commands/daemon.ts +50 -6
- package/src/commands/harness.ts +93 -36
- package/src/commands/launch.ts +5 -2
- package/src/commands/mcp-serve.ts +19 -12
- package/src/commands/notify.ts +36 -3
- package/src/commands/sdk.ts +426 -0
- package/src/commit/agentic/agent.ts +1 -0
- package/src/config/atomic-yaml-patch.ts +423 -0
- package/src/config/model-profile-activation.ts +240 -89
- package/src/config/model-profiles.ts +18 -15
- package/src/config/model-registry.ts +51 -26
- package/src/config/model-resolver.ts +138 -51
- package/src/config/model-selector-value.ts +50 -0
- package/src/config/models-config-schema.ts +14 -21
- package/src/config/settings-schema.ts +128 -10
- package/src/config/settings.ts +1120 -158
- package/src/coordinator-mcp/model-preset.ts +74 -20
- package/src/coordinator-mcp/server.ts +1597 -3052
- package/src/daemon/builtin.ts +8 -5
- package/src/daemon/control-types.ts +1 -1
- package/src/defaults/gjc/skills/team/SKILL.md +4 -4
- package/src/discovery/mcp-json.ts +327 -20
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/compact-handler.ts +3 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -2
- package/src/extensibility/extensions/loader.ts +69 -5
- package/src/extensibility/extensions/runner.ts +112 -4
- package/src/extensibility/extensions/types.ts +176 -17
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/gjc-runtime/launch-tmux.ts +170 -86
- package/src/gjc-runtime/psmux-detect.ts +82 -4
- package/src/gjc-runtime/session-state-sidecar.ts +41 -31
- package/src/gjc-runtime/team-runtime.ts +54 -35
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
- package/src/gjc-runtime/tmux-sessions.ts +19 -13
- package/src/gjc-runtime/ultragoal-guard.ts +53 -6
- package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
- package/src/gjc-runtime/windows-powershell-command.ts +58 -0
- package/src/harness-control-plane/operate.ts +9 -9
- package/src/harness-control-plane/owner.ts +283 -39
- package/src/harness-control-plane/receipts.ts +0 -1
- package/src/harness-control-plane/sdk-transport.ts +395 -0
- package/src/harness-control-plane/session-transport.ts +94 -0
- package/src/harness-control-plane/types.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +34 -35
- package/src/lsp/client.ts +42 -6
- package/src/lsp/index.ts +2 -2
- package/src/main.ts +299 -204
- package/src/modes/DESIGN.md +258 -0
- package/src/modes/acp/acp-agent.ts +1228 -2612
- package/src/modes/acp/acp-client-bridge.ts +2 -20
- package/src/modes/acp/acp-event-mapper.ts +18 -2
- package/src/modes/acp/acp-mode.ts +8 -36
- package/src/modes/acp/permission-mode.ts +25 -0
- package/src/modes/acp/startup-options.ts +6 -0
- package/src/modes/components/agent-dashboard.ts +37 -17
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/settings-selector.ts +60 -11
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +1 -2
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +348 -4
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +59 -20
- package/src/modes/runtime-init.ts +298 -6
- package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
- package/src/modes/shared/agent-wire/event-contract.ts +7 -8
- package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
- package/src/modes/shared/agent-wire/event-observation.ts +16 -7
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
- package/src/modes/types.ts +5 -0
- package/src/runtime-mcp/client.ts +94 -19
- package/src/runtime-mcp/config.ts +27 -15
- package/src/runtime-mcp/manager.ts +343 -105
- package/src/runtime-mcp/oauth-flow.ts +42 -12
- package/src/runtime-mcp/transports/http.ts +49 -19
- package/src/runtime-mcp/transports/stdio.ts +47 -28
- package/src/runtime-mcp/types.ts +10 -0
- package/src/sdk/acp/adapter.ts +418 -0
- package/src/sdk/acp/index.ts +2 -0
- package/src/sdk/broker/broker.ts +642 -0
- package/src/sdk/broker/discovery.ts +94 -0
- package/src/sdk/broker/ensure.ts +249 -0
- package/src/sdk/broker/identity.ts +42 -0
- package/src/sdk/broker/index.ts +8 -0
- package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
- package/src/sdk/broker/internal-source.bunfig.toml +1 -0
- package/src/sdk/broker/lifecycle-ledger.ts +286 -0
- package/src/sdk/broker/lifecycle.ts +2157 -0
- package/src/sdk/broker/process-incarnation.ts +159 -0
- package/src/sdk/broker/runtime.ts +164 -0
- package/src/sdk/broker/session-index.ts +318 -0
- package/src/sdk/broker/state-version.ts +23 -0
- package/src/sdk/broker/transport.ts +125 -0
- package/src/sdk/bus/chat-command-policy.ts +107 -0
- package/src/sdk/bus/chat-daemon-cli.ts +214 -0
- package/src/sdk/bus/chat-daemon-control.ts +713 -0
- package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
- package/src/sdk/bus/chat-effect-journal.ts +353 -0
- package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
- package/src/sdk/bus/config.ts +433 -0
- package/src/sdk/bus/conversation-store.ts +391 -0
- package/src/sdk/bus/discord-conversation.ts +85 -0
- package/src/sdk/bus/discord-daemon.ts +2275 -0
- package/src/sdk/bus/discord-live-provider.ts +521 -0
- package/src/sdk/bus/discord-provider.ts +56 -0
- package/src/{notifications → sdk/bus}/html-format.ts +2 -2
- package/src/sdk/bus/index.ts +3943 -0
- package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
- package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
- package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
- package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
- package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
- package/src/sdk/bus/natives-augment.d.ts +38 -0
- package/src/sdk/bus/notification-orchestration.ts +535 -0
- package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
- package/src/sdk/bus/session-control.ts +333 -0
- package/src/sdk/bus/slack-conversation.ts +74 -0
- package/src/sdk/bus/slack-daemon.ts +2144 -0
- package/src/sdk/bus/slack-live-provider.ts +380 -0
- package/src/sdk/bus/slack-provider.ts +76 -0
- package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
- package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
- package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
- package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
- package/src/sdk/bus/telegram-setup.ts +663 -0
- package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/session-cli.ts +275 -0
- package/src/sdk/client/client.ts +1 -0
- package/src/sdk/client/discovery.ts +108 -0
- package/src/sdk/client/index.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +367 -0
- package/src/sdk/host/control/index.ts +10 -0
- package/src/sdk/host/control/operations.ts +63 -0
- package/src/sdk/host/events.ts +91 -0
- package/src/sdk/host/host.ts +296 -0
- package/src/sdk/host/index.ts +4 -0
- package/src/sdk/host/query/cursor.ts +189 -0
- package/src/sdk/host/query/handlers.ts +533 -0
- package/src/sdk/host/query/index.ts +3 -0
- package/src/sdk/host/query/revision-store.ts +1126 -0
- package/src/sdk/host/reverse-leases.ts +325 -0
- package/src/sdk/host/types.ts +29 -0
- package/src/sdk/index.ts +13 -0
- package/src/sdk/lifecycle-session.ts +39 -0
- package/src/sdk/mcp/index.ts +1 -0
- package/src/sdk/mcp/server.ts +332 -0
- package/src/sdk/models.ts +168 -0
- package/src/sdk/protocol/adapter-validation.ts +48 -0
- package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
- package/src/sdk/protocol/operation-registry.ts +312 -0
- package/src/{sdk.ts → sdk/session.ts} +339 -212
- package/src/sdk/startup-capability.ts +189 -0
- package/src/session/agent-session.ts +2453 -894
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +438 -11
- package/src/session/session-storage.ts +8 -1
- package/src/setup/credential-auto-import.ts +290 -35
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/executor.ts +62 -13
- package/src/tools/ask-answer-registry.ts +1 -1
- package/src/tools/ask.ts +13 -8
- package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
- package/src/tools/browser/benchmark/detector-report.ts +157 -0
- package/src/tools/browser/benchmark/run-suite.ts +39 -0
- package/src/tools/browser/launch.ts +124 -19
- package/src/tools/browser/profile-discovery.ts +63 -0
- package/src/tools/browser/profile-posture.ts +59 -0
- package/src/tools/browser/profile-reuse.ts +102 -0
- package/src/tools/browser/profile-warmup.ts +109 -0
- package/src/tools/browser/registry.ts +87 -11
- package/src/tools/browser/tab-protocol.ts +1 -0
- package/src/tools/browser/tab-supervisor.ts +1 -0
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +6 -0
- package/src/tools/index.ts +8 -8
- package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
- package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
- package/src/tools/telegram-send.ts +2 -2
- package/vendor/insane-search/MANIFEST.json +2 -1
- package/vendor/insane-search/engine/bias_check.py +4 -1
- package/vendor/insane-search/engine/phase0.py +26 -1
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
- package/dist/types/modes/bridge/auth.d.ts +0 -12
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
- package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
- package/dist/types/modes/bridge/event-stream.d.ts +0 -8
- package/dist/types/modes/rpc/host-tools.d.ts +0 -1
- package/dist/types/modes/rpc/host-uris.d.ts +0 -1
- package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
- package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
- package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
- package/dist/types/notifications/config.d.ts +0 -132
- package/src/harness-control-plane/rpc-adapter.ts +0 -290
- package/src/modes/bridge/auth.ts +0 -41
- package/src/modes/bridge/bridge-client-bridge.ts +0 -47
- package/src/modes/bridge/bridge-mode.ts +0 -675
- package/src/modes/bridge/bridge-ui-context.ts +0 -200
- package/src/modes/bridge/event-stream.ts +0 -70
- package/src/modes/rpc/host-tools.ts +0 -1
- package/src/modes/rpc/host-uris.ts +0 -1
- package/src/modes/rpc/rpc-client.ts +0 -1166
- package/src/modes/rpc/rpc-mode.ts +0 -1029
- package/src/modes/rpc/rpc-socket-security.ts +0 -115
- package/src/modes/rpc/rpc-types.ts +0 -637
- package/src/modes/shared/agent-wire/command-contract.ts +0 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
- package/src/modes/shared/agent-wire/command-validation.ts +0 -181
- package/src/modes/shared/agent-wire/handshake.ts +0 -157
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
- package/src/modes/shared/agent-wire/protocol.ts +0 -46
- package/src/modes/shared/agent-wire/responses.ts +0 -17
- package/src/modes/shared/agent-wire/scopes.ts +0 -94
- package/src/modes/shared/agent-wire/session-registry.ts +0 -109
- package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
- package/src/modes/shared/agent-wire/ui-result.ts +0 -48
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
- package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
- package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
- package/src/notifications/config.ts +0 -219
- package/src/notifications/index.ts +0 -1835
- package/src/notifications/telegram-daemon-cli.ts +0 -243
- package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
- /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
- /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
- /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
- /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
- /package/src/{notifications → sdk/bus}/engine.ts +0 -0
- /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
- /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
- /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
- /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
- /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import * as fs from "node:fs/promises";
|
|
2
3
|
import * as path from "node:path";
|
|
3
4
|
import type {
|
|
@@ -7,8 +8,8 @@ import type {
|
|
|
7
8
|
AuthStorage,
|
|
8
9
|
} from "@gajae-code/ai";
|
|
9
10
|
import { getAgentDir, logger, VERSION } from "@gajae-code/utils";
|
|
11
|
+
import { withFileLock } from "../config/file-lock";
|
|
10
12
|
import type { ModelRegistry } from "../config/model-registry";
|
|
11
|
-
|
|
12
13
|
import {
|
|
13
14
|
type CredentialDiscoveryResult,
|
|
14
15
|
type CredentialOrigin,
|
|
@@ -23,42 +24,206 @@ import {
|
|
|
23
24
|
|
|
24
25
|
export const CREDENTIAL_AUTO_IMPORT_ROTATION_WARNING =
|
|
25
26
|
"Refreshing in gjc may log out the Claude/Codex CLI because OAuth refresh tokens can rotate.";
|
|
27
|
+
export const CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING =
|
|
28
|
+
"Credential import preference could not be saved; external credentials may be offered again.";
|
|
29
|
+
export const CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING =
|
|
30
|
+
"Imported credentials were saved, but provider availability could not be refreshed.";
|
|
31
|
+
export const CREDENTIAL_AUTO_IMPORT_DISCOVERY_WARNING =
|
|
32
|
+
"External credential discovery could not be completed. Use /provider to import credentials manually.";
|
|
33
|
+
export const CREDENTIAL_AUTO_IMPORT_RETRY_WARNING =
|
|
34
|
+
"Some external credentials could not be imported. Use /provider to retry.";
|
|
35
|
+
|
|
36
|
+
export const CREDENTIAL_AUTO_IMPORT_STATE_UNREADABLE_WARNING =
|
|
37
|
+
"Credential import preference could not be read. External credential discovery was skipped; use /provider to import credentials manually.";
|
|
26
38
|
|
|
27
39
|
export type CredentialAutoImportSourceLabel = "claude-code-file" | "claude-code-keychain" | "codex-file";
|
|
28
40
|
export type CredentialAutoImportTrigger = "startup" | "bare-login" | "setup-cli";
|
|
41
|
+
export type InitialImportResolution = "accepted" | "declined";
|
|
42
|
+
export type CredentialAutoImportStateProblem =
|
|
43
|
+
| "invalid-initial-import-resolution"
|
|
44
|
+
| "invalid-last-import-version"
|
|
45
|
+
| "malformed-json"
|
|
46
|
+
| "malformed-root";
|
|
29
47
|
|
|
30
48
|
const CREDENTIAL_AUTO_IMPORT_STATE_FILENAME = "credential-auto-import-state.json";
|
|
49
|
+
const VERSION_MARKER_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
50
|
+
|
|
51
|
+
export interface CredentialAutoImportStateFile {
|
|
52
|
+
lastImportVersion?: string;
|
|
53
|
+
initialImportResolution?: InitialImportResolution;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface CredentialAutoImportStateReadResult {
|
|
57
|
+
state: CredentialAutoImportStateFile;
|
|
58
|
+
problems: CredentialAutoImportStateProblem[];
|
|
59
|
+
unreadable: boolean;
|
|
60
|
+
}
|
|
31
61
|
|
|
32
|
-
interface
|
|
33
|
-
lastImportVersion?:
|
|
62
|
+
export interface CredentialAutoImportStateMutation {
|
|
63
|
+
lastImportVersion?: string;
|
|
64
|
+
initialImportResolution?: InitialImportResolution;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface CredentialAutoImportStateStore {
|
|
68
|
+
read: () => Promise<CredentialAutoImportStateReadResult>;
|
|
69
|
+
write: (mutation: CredentialAutoImportStateMutation) => Promise<boolean>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface CredentialAutoImportStateStoreDependencies {
|
|
73
|
+
withFileLock?: <T>(filePath: string, transaction: () => Promise<T>) => Promise<T>;
|
|
74
|
+
rename?: (oldPath: string, newPath: string) => Promise<void>;
|
|
34
75
|
}
|
|
35
76
|
|
|
36
77
|
export function getCredentialAutoImportStatePath(agentDir: string = getAgentDir()): string {
|
|
37
78
|
return path.join(agentDir, CREDENTIAL_AUTO_IMPORT_STATE_FILENAME);
|
|
38
79
|
}
|
|
39
80
|
|
|
40
|
-
|
|
81
|
+
function isEnoent(error: unknown): boolean {
|
|
82
|
+
return (error as NodeJS.ErrnoException | undefined)?.code === "ENOENT";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isValidVersionMarker(value: unknown): value is string {
|
|
86
|
+
return (
|
|
87
|
+
typeof value === "string" &&
|
|
88
|
+
value.length > 0 &&
|
|
89
|
+
value.trim() === value &&
|
|
90
|
+
value.length <= 128 &&
|
|
91
|
+
VERSION_MARKER_PATTERN.test(value)
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function isInitialImportResolution(value: unknown): value is InitialImportResolution {
|
|
96
|
+
return value === "accepted" || value === "declined";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function projectCredentialAutoImportState(value: unknown): CredentialAutoImportStateReadResult {
|
|
100
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
101
|
+
return { state: {}, problems: ["malformed-root"], unreadable: false };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const record = value as Record<string, unknown>;
|
|
105
|
+
const state: CredentialAutoImportStateFile = {};
|
|
106
|
+
const problems: CredentialAutoImportStateProblem[] = [];
|
|
107
|
+
if (Object.hasOwn(record, "initialImportResolution")) {
|
|
108
|
+
if (isInitialImportResolution(record.initialImportResolution)) {
|
|
109
|
+
state.initialImportResolution = record.initialImportResolution;
|
|
110
|
+
} else {
|
|
111
|
+
problems.push("invalid-initial-import-resolution");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (Object.hasOwn(record, "lastImportVersion")) {
|
|
115
|
+
if (isValidVersionMarker(record.lastImportVersion)) {
|
|
116
|
+
state.lastImportVersion = record.lastImportVersion;
|
|
117
|
+
} else {
|
|
118
|
+
problems.push("invalid-last-import-version");
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { state, problems, unreadable: false };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function readCredentialAutoImportStateAtPath(statePath: string): Promise<CredentialAutoImportStateReadResult> {
|
|
41
125
|
try {
|
|
42
|
-
const raw = await fs.readFile(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
126
|
+
const raw = await fs.readFile(statePath, "utf-8");
|
|
127
|
+
try {
|
|
128
|
+
return projectCredentialAutoImportState(JSON.parse(raw) as unknown);
|
|
129
|
+
} catch {
|
|
130
|
+
return { state: {}, problems: ["malformed-json"], unreadable: false };
|
|
131
|
+
}
|
|
132
|
+
} catch (error: unknown) {
|
|
133
|
+
if (isEnoent(error)) return { state: {}, problems: [], unreadable: false };
|
|
134
|
+
return { state: {}, problems: [], unreadable: true };
|
|
47
135
|
}
|
|
48
136
|
}
|
|
49
137
|
|
|
50
|
-
|
|
138
|
+
function serializeCredentialAutoImportState(state: CredentialAutoImportStateFile): string {
|
|
139
|
+
const serialized: CredentialAutoImportStateFile = {};
|
|
140
|
+
if (isValidVersionMarker(state.lastImportVersion)) serialized.lastImportVersion = state.lastImportVersion;
|
|
141
|
+
if (isInitialImportResolution(state.initialImportResolution)) {
|
|
142
|
+
serialized.initialImportResolution = state.initialImportResolution;
|
|
143
|
+
}
|
|
144
|
+
return `${JSON.stringify(serialized)}\n`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function writeCredentialAutoImportStateAtomic(
|
|
148
|
+
statePath: string,
|
|
149
|
+
state: CredentialAutoImportStateFile,
|
|
150
|
+
rename: (oldPath: string, newPath: string) => Promise<void> = fs.rename,
|
|
151
|
+
): Promise<void> {
|
|
152
|
+
const temporaryPath = `${statePath}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
|
|
51
153
|
try {
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
154
|
+
const handle = await fs.open(temporaryPath, "wx", 0o600);
|
|
155
|
+
try {
|
|
156
|
+
await handle.writeFile(serializeCredentialAutoImportState(state));
|
|
157
|
+
} finally {
|
|
158
|
+
await handle.close();
|
|
159
|
+
}
|
|
160
|
+
await rename(temporaryPath, statePath);
|
|
56
161
|
} catch (error: unknown) {
|
|
57
|
-
|
|
58
|
-
|
|
162
|
+
await fs.rm(temporaryPath, { force: true }).catch(() => {});
|
|
163
|
+
throw error;
|
|
59
164
|
}
|
|
60
165
|
}
|
|
61
166
|
|
|
167
|
+
export function createCredentialAutoImportStateStore(
|
|
168
|
+
agentDir: string = getAgentDir(),
|
|
169
|
+
dependencies: CredentialAutoImportStateStoreDependencies = {},
|
|
170
|
+
): CredentialAutoImportStateStore {
|
|
171
|
+
const statePath = getCredentialAutoImportStatePath(agentDir);
|
|
172
|
+
const lock = dependencies.withFileLock ?? withFileLock;
|
|
173
|
+
const rename = dependencies.rename ?? fs.rename;
|
|
174
|
+
return {
|
|
175
|
+
read: () => readCredentialAutoImportStateAtPath(statePath),
|
|
176
|
+
write: async mutation => {
|
|
177
|
+
if (
|
|
178
|
+
(mutation.lastImportVersion !== undefined && !isValidVersionMarker(mutation.lastImportVersion)) ||
|
|
179
|
+
(mutation.initialImportResolution !== undefined &&
|
|
180
|
+
!isInitialImportResolution(mutation.initialImportResolution))
|
|
181
|
+
) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
try {
|
|
185
|
+
await fs.mkdir(path.dirname(statePath), { recursive: true, mode: 0o700 });
|
|
186
|
+
await lock(statePath, async () => {
|
|
187
|
+
const current = await readCredentialAutoImportStateAtPath(statePath);
|
|
188
|
+
if (current.unreadable) throw new Error("Credential auto-import state became unreadable");
|
|
189
|
+
const next: CredentialAutoImportStateFile = { ...current.state };
|
|
190
|
+
if (mutation.lastImportVersion !== undefined) next.lastImportVersion = mutation.lastImportVersion;
|
|
191
|
+
if (next.initialImportResolution === undefined && mutation.initialImportResolution !== undefined) {
|
|
192
|
+
next.initialImportResolution = mutation.initialImportResolution;
|
|
193
|
+
}
|
|
194
|
+
await writeCredentialAutoImportStateAtomic(statePath, next, rename);
|
|
195
|
+
});
|
|
196
|
+
return true;
|
|
197
|
+
} catch {
|
|
198
|
+
logger.warn("Credential auto-import state persistence failed", { classification: "state-write-failed" });
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export async function readCredentialAutoImportState(agentDir?: string): Promise<CredentialAutoImportStateReadResult> {
|
|
206
|
+
return createCredentialAutoImportStateStore(agentDir).read();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function isCredentialAutoImportStateResolvedForVersion(
|
|
210
|
+
state: CredentialAutoImportStateFile,
|
|
211
|
+
version: string,
|
|
212
|
+
): boolean {
|
|
213
|
+
return (
|
|
214
|
+
state.initialImportResolution !== undefined ||
|
|
215
|
+
(state.lastImportVersion !== undefined && state.lastImportVersion === version)
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export async function readCredentialImportMarker(agentDir?: string): Promise<string | undefined> {
|
|
220
|
+
return (await readCredentialAutoImportState(agentDir)).state.lastImportVersion;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export async function writeCredentialImportMarker(version: string, agentDir?: string): Promise<boolean> {
|
|
224
|
+
return createCredentialAutoImportStateStore(agentDir).write({ lastImportVersion: version });
|
|
225
|
+
}
|
|
226
|
+
|
|
62
227
|
export enum CredentialAutoImportFailureClass {
|
|
63
228
|
DiscoveryUnavailable = "discovery-unavailable",
|
|
64
229
|
SourceUnreadable = "source-unreadable",
|
|
@@ -93,6 +258,63 @@ export interface CredentialAutoImportResult {
|
|
|
93
258
|
globalDiscoveryFailure?: CredentialAutoImportFailure;
|
|
94
259
|
}
|
|
95
260
|
|
|
261
|
+
const CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS: readonly ExternalProvider[] = ["anthropic", "openai-codex"];
|
|
262
|
+
const CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS: readonly CredentialOrigin[] = [
|
|
263
|
+
"claude-code-file",
|
|
264
|
+
"claude-code-keychain",
|
|
265
|
+
"codex-file",
|
|
266
|
+
];
|
|
267
|
+
const CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS: Record<CredentialOrigin, string> = {
|
|
268
|
+
"claude-code-file": "Claude Code file",
|
|
269
|
+
"claude-code-keychain": "Claude Code Keychain",
|
|
270
|
+
"codex-file": "Codex CLI file",
|
|
271
|
+
};
|
|
272
|
+
const CREDENTIAL_AUTO_IMPORT_FAILURE_CLASSES = new Set(Object.values(CredentialAutoImportFailureClass));
|
|
273
|
+
|
|
274
|
+
export function formatCredentialAutoImportCandidateLabel(
|
|
275
|
+
candidate: Pick<ImportableCredential, "provider" | "origin">,
|
|
276
|
+
): string {
|
|
277
|
+
const provider = CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS.includes(candidate.provider)
|
|
278
|
+
? EXTERNAL_PROVIDER_LABELS[candidate.provider]
|
|
279
|
+
: undefined;
|
|
280
|
+
const origin = CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS.includes(candidate.origin)
|
|
281
|
+
? CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS[candidate.origin]
|
|
282
|
+
: undefined;
|
|
283
|
+
return provider && origin ? `${provider} · ${origin}` : "External OAuth credential";
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export function formatCredentialAutoImportPrompt(
|
|
287
|
+
candidates: readonly Pick<ImportableCredential, "provider" | "origin">[],
|
|
288
|
+
): string {
|
|
289
|
+
const lines: string[] = [];
|
|
290
|
+
for (const provider of CREDENTIAL_AUTO_IMPORT_PROMPT_PROVIDERS) {
|
|
291
|
+
for (const origin of CREDENTIAL_AUTO_IMPORT_PROMPT_ORIGINS) {
|
|
292
|
+
const count = candidates.filter(
|
|
293
|
+
candidate => candidate.provider === provider && candidate.origin === origin,
|
|
294
|
+
).length;
|
|
295
|
+
if (count > 0)
|
|
296
|
+
lines.push(
|
|
297
|
+
`${EXTERNAL_PROVIDER_LABELS[provider]} · ${CREDENTIAL_AUTO_IMPORT_ORIGIN_LABELS[origin]}: ${count}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return `External OAuth credentials found: ${candidates.length}\n${lines.join("\n")}`;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function logCredentialAutoImportFailures(
|
|
305
|
+
trigger: CredentialAutoImportTrigger,
|
|
306
|
+
failures: readonly Pick<CredentialAutoImportFailure, "failureClass">[],
|
|
307
|
+
): void {
|
|
308
|
+
const failureCounts: Partial<Record<CredentialAutoImportFailureClass, number>> = {};
|
|
309
|
+
for (const failure of failures) {
|
|
310
|
+
if (!CREDENTIAL_AUTO_IMPORT_FAILURE_CLASSES.has(failure.failureClass)) continue;
|
|
311
|
+
failureCounts[failure.failureClass] = (failureCounts[failure.failureClass] ?? 0) + 1;
|
|
312
|
+
}
|
|
313
|
+
if (Object.keys(failureCounts).length > 0) {
|
|
314
|
+
logger.warn("Credential auto-import completed with failures", { trigger, failureCounts });
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
96
318
|
export type CredentialAutoImportAuthStorage = Pick<AuthStorage, "importCredentialIfAbsent">;
|
|
97
319
|
|
|
98
320
|
export interface CredentialAutoImportOptions {
|
|
@@ -204,18 +426,38 @@ export function formatCredentialAutoImportResult(result: CredentialAutoImportRes
|
|
|
204
426
|
return lines;
|
|
205
427
|
}
|
|
206
428
|
|
|
207
|
-
export interface CredentialImportMarkerStore {
|
|
208
|
-
read: () => Promise<string | undefined> | string | undefined;
|
|
209
|
-
write: (version: string) => Promise<boolean> | boolean;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
429
|
export interface StartupCredentialAutoImportOptions {
|
|
213
430
|
authStorage: CredentialAutoImportOptions["authStorage"];
|
|
214
431
|
modelRegistry: Pick<ModelRegistry, "refresh">;
|
|
215
432
|
discover?: CredentialAutoImportOptions["discover"];
|
|
216
433
|
version?: string;
|
|
217
434
|
agentDir?: string;
|
|
218
|
-
|
|
435
|
+
stateStore?: CredentialAutoImportStateStore;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function appendNoticeLine(notice: string | undefined, line: string): string {
|
|
439
|
+
return notice ? `${notice}\n${line}` : line;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async function readStateSafely(store: CredentialAutoImportStateStore): Promise<CredentialAutoImportStateReadResult> {
|
|
443
|
+
try {
|
|
444
|
+
return await store.read();
|
|
445
|
+
} catch {
|
|
446
|
+
logger.warn("Credential auto-import state read failed", { classification: "state-read-failed" });
|
|
447
|
+
return { state: {}, problems: [], unreadable: true };
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async function writeStateSafely(
|
|
452
|
+
store: CredentialAutoImportStateStore,
|
|
453
|
+
mutation: CredentialAutoImportStateMutation,
|
|
454
|
+
): Promise<boolean> {
|
|
455
|
+
try {
|
|
456
|
+
return await store.write(mutation);
|
|
457
|
+
} catch {
|
|
458
|
+
logger.warn("Credential auto-import state persistence failed", { classification: "state-write-failed" });
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
219
461
|
}
|
|
220
462
|
|
|
221
463
|
export async function runStartupCredentialAutoImportIfNeeded({
|
|
@@ -224,17 +466,15 @@ export async function runStartupCredentialAutoImportIfNeeded({
|
|
|
224
466
|
discover,
|
|
225
467
|
version = VERSION,
|
|
226
468
|
agentDir,
|
|
227
|
-
|
|
469
|
+
stateStore,
|
|
228
470
|
}: StartupCredentialAutoImportOptions): Promise<string | undefined> {
|
|
229
|
-
const store =
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const lastVersion = await store.read();
|
|
234
|
-
if (lastVersion === version) {
|
|
235
|
-
// Steady state: user already completed this version's auto-import gate. Skip all file/Keychain reads.
|
|
471
|
+
const store = stateStore ?? createCredentialAutoImportStateStore(agentDir);
|
|
472
|
+
const stateRead = await readStateSafely(store);
|
|
473
|
+
if (stateRead.unreadable) {
|
|
474
|
+
logger.warn("Credential auto-import state unavailable", { classification: "state-unreadable" });
|
|
236
475
|
return undefined;
|
|
237
476
|
}
|
|
477
|
+
if (isCredentialAutoImportStateResolvedForVersion(stateRead.state, version)) return undefined;
|
|
238
478
|
|
|
239
479
|
const result = await runExternalCredentialAutoImport({
|
|
240
480
|
authStorage: activeAuthStorage,
|
|
@@ -242,17 +482,32 @@ export async function runStartupCredentialAutoImportIfNeeded({
|
|
|
242
482
|
trigger: "startup",
|
|
243
483
|
});
|
|
244
484
|
if (!result.discovered) {
|
|
485
|
+
logCredentialAutoImportFailures("startup", result.failures);
|
|
245
486
|
return undefined;
|
|
246
487
|
}
|
|
247
488
|
|
|
248
489
|
const candidates = filterAutoImportOAuthCredentials(result.discovery?.importable ?? []);
|
|
249
|
-
|
|
250
|
-
|
|
490
|
+
const handledCandidates = result.imported.length + result.skipped.length > 0;
|
|
491
|
+
if (result.failures.length > 0) logCredentialAutoImportFailures("startup", result.failures);
|
|
492
|
+
let persisted = true;
|
|
493
|
+
if (handledCandidates) {
|
|
494
|
+
persisted = await writeStateSafely(store, {
|
|
495
|
+
lastImportVersion: version,
|
|
496
|
+
initialImportResolution: "accepted",
|
|
497
|
+
});
|
|
498
|
+
} else if (candidates.length === 0 && result.failures.length === 0) {
|
|
499
|
+
persisted = await writeStateSafely(store, { lastImportVersion: version });
|
|
251
500
|
}
|
|
252
|
-
await store.write(version);
|
|
253
501
|
|
|
502
|
+
let notice = buildCredentialAutoImportNotice(result);
|
|
503
|
+
if (!persisted) notice = appendNoticeLine(notice, CREDENTIAL_AUTO_IMPORT_PERSISTENCE_WARNING);
|
|
254
504
|
if (result.imported.length > 0) {
|
|
255
|
-
|
|
505
|
+
try {
|
|
506
|
+
await activeModelRegistry.refresh("offline");
|
|
507
|
+
} catch {
|
|
508
|
+
logger.warn("Credential auto-import refresh failed", { classification: "refresh-failed" });
|
|
509
|
+
notice = appendNoticeLine(notice, CREDENTIAL_AUTO_IMPORT_REFRESH_WARNING);
|
|
510
|
+
}
|
|
256
511
|
}
|
|
257
|
-
return
|
|
512
|
+
return notice;
|
|
258
513
|
}
|
|
@@ -13,7 +13,7 @@ These instructions teach a Hermes-style coordinator how to operate GJC through t
|
|
|
13
13
|
If a second task is needed while one turn is active, pass `queue: true`; the next queued turn is promoted after the active turn is reported terminal.
|
|
14
14
|
5. If GJC asks a structured question, use `{{TOOL_PREFIX}}_list_questions` and answer with `{{TOOL_PREFIX}}_submit_question_answer`.
|
|
15
15
|
6. Use `{{TOOL_PREFIX}}_report_status` for coordinator-visible status and final reports.
|
|
16
|
-
7. Use `{{TOOL_PREFIX}}_read_tail` only
|
|
16
|
+
7. Use `{{TOOL_PREFIX}}_read_tail` only to inspect the latest assistant response through the SDK when structured turn state is insufficient; it never reads terminal output.
|
|
17
17
|
|
|
18
18
|
## Prefer high-level delegation
|
|
19
19
|
|
|
@@ -39,11 +39,9 @@ The Hermes bridge does not choose a model/provider. Generated setup configures `
|
|
|
39
39
|
|
|
40
40
|
Provider-specific commands are examples only, never product defaults.
|
|
41
41
|
|
|
42
|
-
##
|
|
42
|
+
## Human-visible TUI boundary
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Use that pattern only when the router must watch tmux output, send stale-session alerts, or inject follow-up prompts into the same visible pane. The short version is: prepare a dedicated worktree, register a stable tmux session through the host router, start interactive `gjc`, wait for TUI readiness, inject the task prompt separately, and verify actual tool/work activity before reporting acceptance.
|
|
44
|
+
A human may choose to run the local TUI in tmux for terminal visibility. That terminal is not a controller API: Hermes/OpenClaw/Clawhip-style operators must not inject prompts into, scrape, or route machine decisions through a tmux pane. Use the Coordinator MCP tools above for every external control and viewing operation.
|
|
47
45
|
|
|
48
46
|
Do not put private channel ids, mention targets, socket names, tokens, or local routing policy into portable setup output. Keep those in the host/operator deployment.
|
|
49
47
|
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
formatNotificationTestResult,
|
|
34
34
|
recoverNotifications,
|
|
35
35
|
sendNotificationTest,
|
|
36
|
-
} from "../
|
|
36
|
+
} from "../sdk/bus/notification-service";
|
|
37
37
|
import { computeCacheMissCostSummary, formatCacheMissSummaryLines } from "../session/cache-economics";
|
|
38
38
|
import { formatModelOnboardingGuidance } from "../setup/model-onboarding-guidance";
|
|
39
39
|
import {
|
|
@@ -697,6 +697,7 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
|
|
|
697
697
|
await runtime.session.setModel(selection.model, "default", {
|
|
698
698
|
selector: selection.selector,
|
|
699
699
|
thinkingLevel: existingDefaultThinkingLevel,
|
|
700
|
+
cause: "user-selection",
|
|
700
701
|
});
|
|
701
702
|
if (existingDefaultThinkingLevel) {
|
|
702
703
|
runtime.session.setThinkingLevel(existingDefaultThinkingLevel);
|
package/src/task/executor.ts
CHANGED
|
@@ -914,19 +914,24 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
914
914
|
progress.recentOutput = [];
|
|
915
915
|
};
|
|
916
916
|
|
|
917
|
+
const forwardSubagentEvent = (
|
|
918
|
+
event: AgentEvent | Extract<AgentSessionEvent, { type: "model_fallback_switched" }>,
|
|
919
|
+
) => {
|
|
920
|
+
if (!options.eventBus) return;
|
|
921
|
+
options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
|
|
922
|
+
index,
|
|
923
|
+
agent: agent.name,
|
|
924
|
+
agentSource: agent.source,
|
|
925
|
+
task,
|
|
926
|
+
assignment,
|
|
927
|
+
event,
|
|
928
|
+
});
|
|
929
|
+
};
|
|
930
|
+
|
|
917
931
|
const processEvent = (event: AgentEvent) => {
|
|
918
932
|
if (resolved) return;
|
|
919
933
|
|
|
920
|
-
|
|
921
|
-
options.eventBus.emit(TASK_SUBAGENT_EVENT_CHANNEL, {
|
|
922
|
-
index,
|
|
923
|
-
agent: agent.name,
|
|
924
|
-
agentSource: agent.source,
|
|
925
|
-
task,
|
|
926
|
-
assignment,
|
|
927
|
-
event,
|
|
928
|
-
});
|
|
929
|
-
}
|
|
934
|
+
forwardSubagentEvent(event);
|
|
930
935
|
|
|
931
936
|
const now = Date.now();
|
|
932
937
|
let flushProgress = false;
|
|
@@ -1234,6 +1239,9 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1234
1239
|
authFallbackUsed,
|
|
1235
1240
|
requestedModel,
|
|
1236
1241
|
fallbackReason,
|
|
1242
|
+
activeIndex,
|
|
1243
|
+
parentFallbackSelector,
|
|
1244
|
+
skips,
|
|
1237
1245
|
} = await awaitAbortable(
|
|
1238
1246
|
resolveModelOverrideWithAuthFallback(
|
|
1239
1247
|
modelPatterns,
|
|
@@ -1241,6 +1249,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1241
1249
|
modelRegistry,
|
|
1242
1250
|
settings,
|
|
1243
1251
|
options.parentSessionId,
|
|
1252
|
+
{ managedFallback: true },
|
|
1244
1253
|
),
|
|
1245
1254
|
);
|
|
1246
1255
|
if (model) {
|
|
@@ -1431,6 +1440,21 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1431
1440
|
);
|
|
1432
1441
|
|
|
1433
1442
|
activeSession = session;
|
|
1443
|
+
// Each subagent invocation owns a fresh controller; its configured chain
|
|
1444
|
+
// is scoped to this child session and never shares parent sticky state.
|
|
1445
|
+
// Auth-aware resolution can substitute the parent model only after every
|
|
1446
|
+
// override entry was unavailable. Rebase the controller to that concrete
|
|
1447
|
+
// parent selector so its request is never charged to override index zero.
|
|
1448
|
+
session.setConfiguredModelChain(
|
|
1449
|
+
"default",
|
|
1450
|
+
parentFallbackSelector ? [parentFallbackSelector] : modelPatterns,
|
|
1451
|
+
"subagent",
|
|
1452
|
+
agent.name,
|
|
1453
|
+
true,
|
|
1454
|
+
);
|
|
1455
|
+
if (activeIndex !== undefined && !parentFallbackSelector) {
|
|
1456
|
+
session.seedDefaultFallbackResolution(activeIndex, skips);
|
|
1457
|
+
}
|
|
1434
1458
|
const liveSubagentId = options.subagentId ?? id;
|
|
1435
1459
|
const manager = AsyncJobManager.instance();
|
|
1436
1460
|
if (manager) {
|
|
@@ -1508,12 +1532,14 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1508
1532
|
pendingExtensionMessages.push(sendPromise);
|
|
1509
1533
|
},
|
|
1510
1534
|
sendUserMessage: (content, options) => {
|
|
1511
|
-
const
|
|
1535
|
+
const send = session.sendUserMessage(content, options);
|
|
1536
|
+
const observedSend = send.catch(e => {
|
|
1512
1537
|
logger.error("Extension sendUserMessage failed", {
|
|
1513
1538
|
error: e instanceof Error ? e.message : String(e),
|
|
1514
1539
|
});
|
|
1515
1540
|
});
|
|
1516
|
-
pendingExtensionMessages.push(
|
|
1541
|
+
pendingExtensionMessages.push(observedSend);
|
|
1542
|
+
return send;
|
|
1517
1543
|
},
|
|
1518
1544
|
appendEntry: (customType, data) => {
|
|
1519
1545
|
session.sessionManager.appendCustomEntry(customType, data);
|
|
@@ -1528,7 +1554,17 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1528
1554
|
getCommands: () => getSessionSlashCommands(session),
|
|
1529
1555
|
setModel: model => runExtensionSetModel(session, model),
|
|
1530
1556
|
getThinkingLevel: () => session.thinkingLevel,
|
|
1531
|
-
setThinkingLevel: level => session.setThinkingLevel(level),
|
|
1557
|
+
setThinkingLevel: (level, persist) => session.setThinkingLevel(level, persist),
|
|
1558
|
+
getThinkingVisibility: () => session.getThinkingVisibility(),
|
|
1559
|
+
setThinkingVisibility: (visibility, persist) => session.setThinkingVisibility(visibility, persist),
|
|
1560
|
+
cycleThinkingLevel: () => session.cycleThinkingLevel(),
|
|
1561
|
+
setThinkingLevelForControl: (level, persist) => session.setThinkingLevelForControl(level, persist),
|
|
1562
|
+
setThinkingVisibilityForControl: (visibility, persist) =>
|
|
1563
|
+
session.setThinkingVisibilityForControl(visibility, persist),
|
|
1564
|
+
setModelTemporaryForControl: (model, expectedSessionId) =>
|
|
1565
|
+
session.setModelTemporaryForControl(model, expectedSessionId),
|
|
1566
|
+
fetchUsageReportsForControl: () => session.fetchUsageReportsForControl(),
|
|
1567
|
+
getThinkingScopeForControl: () => session.getThinkingScopeForControl(),
|
|
1532
1568
|
getSessionName: () => session.sessionManager.getSessionName(),
|
|
1533
1569
|
setSessionName: async name => {
|
|
1534
1570
|
await session.sessionManager.setSessionName(name, "user");
|
|
@@ -1539,10 +1575,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1539
1575
|
isIdle: () => !session.isStreaming,
|
|
1540
1576
|
abort: () => session.abort(),
|
|
1541
1577
|
hasPendingMessages: () => session.queuedMessageCount > 0,
|
|
1578
|
+
getPendingMessageCounts: () => session.pendingMessageCounts,
|
|
1579
|
+
getTranscript: () => session.getTranscript(),
|
|
1580
|
+
getTranscriptBody: entryId => session.getTranscriptBody(entryId),
|
|
1581
|
+
getGoalState: () => session.getGoalModeState(),
|
|
1582
|
+
getTodoState: () => session.getTodoPhases(),
|
|
1583
|
+
getQueuedMessages: () => session.getQueuedMessageEntries(),
|
|
1584
|
+
getActiveTools: () => session.getActiveToolNames(),
|
|
1585
|
+
getAllTools: () => session.getAllToolNames(),
|
|
1542
1586
|
shutdown: () => {},
|
|
1543
1587
|
getContextUsage: () => session.getContextUsage(),
|
|
1544
1588
|
getSystemPrompt: () => session.systemPrompt,
|
|
1545
1589
|
compact: instructionsOrOptions => runExtensionCompact(session, instructionsOrOptions),
|
|
1590
|
+
clearContext: () => session.clearContext(),
|
|
1546
1591
|
},
|
|
1547
1592
|
);
|
|
1548
1593
|
extensionRunner.onError(err => {
|
|
@@ -1581,6 +1626,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1581
1626
|
scheduleProgress(true);
|
|
1582
1627
|
return;
|
|
1583
1628
|
}
|
|
1629
|
+
if (event.type === "model_fallback_switched") {
|
|
1630
|
+
forwardSubagentEvent(event);
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1584
1633
|
if (isAgentEvent(event)) {
|
|
1585
1634
|
try {
|
|
1586
1635
|
processEvent(event);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* source; registering returns a disposer.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/
|
|
10
|
+
import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/workflow-gate-broker";
|
|
11
11
|
import type { AskAnswerSource } from "./index";
|
|
12
12
|
|
|
13
13
|
const sources = new Map<string, AskAnswerSource>();
|
package/src/tools/ask.ts
CHANGED
|
@@ -758,9 +758,14 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
758
758
|
if (receipt) await receipt.settle(settlement);
|
|
759
759
|
};
|
|
760
760
|
const gateEmitter = this.session.getWorkflowGateEmitter?.();
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
//
|
|
761
|
+
// A durable workflow-gate emitter now exists for every session, and its
|
|
762
|
+
// isUnattended() is always true, so it can no longer signal "no local UI".
|
|
763
|
+
// The workflow gate is only the headless (non-TUI) answer path: when a real
|
|
764
|
+
// interactive UI is present, prefer it — otherwise attended TUI asks would
|
|
765
|
+
// route to emitGate() and hang forever waiting on a remote responder.
|
|
766
|
+
const hasInteractiveUi = context?.hasUI === true && !!context.ui;
|
|
767
|
+
const canUseWorkflowGate = !hasInteractiveUi && gateEmitter?.isUnattended() === true;
|
|
768
|
+
// Headless fallback: SDK workflow gates are the non-TUI answer path.
|
|
764
769
|
if (!canUseWorkflowGate && (!context?.hasUI || !context.ui)) {
|
|
765
770
|
context?.abort();
|
|
766
771
|
throw new ToolAbortError("Ask tool requires interactive mode");
|
|
@@ -772,9 +777,9 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
772
777
|
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
773
778
|
const source = this.session.getAskAnswerSource?.();
|
|
774
779
|
if (!source) return extensionUi.select(prompt, options, dialogOptions);
|
|
775
|
-
// Race the local UI against a remote answer (e.g.
|
|
776
|
-
//
|
|
777
|
-
//
|
|
780
|
+
// Race the local UI against a remote answer (e.g. an SDK reply) so asks
|
|
781
|
+
// can be answered without local UI interaction. The first valid answer
|
|
782
|
+
// wins; the loser is aborted so neither side is left hanging:
|
|
778
783
|
// - local wins -> abort the remote source (marks the action resolved-locally)
|
|
779
784
|
// - remote wins -> abort the local selector so the TUI dialog actually closes
|
|
780
785
|
const remoteController = new AbortController();
|
|
@@ -975,8 +980,8 @@ export class AskTool implements AgentTool<typeof askSchema, AskToolDetails> {
|
|
|
975
980
|
) => {
|
|
976
981
|
const rawOptionLabels = q.options.map(o => o.label);
|
|
977
982
|
const questionIndex = params.questions.indexOf(q);
|
|
978
|
-
//
|
|
979
|
-
//
|
|
983
|
+
// Route headless asks through the SDK workflow-gate emitter; a connected
|
|
984
|
+
// SDK responder supplies the durable answer instead of an interactive UI.
|
|
980
985
|
if (gateEmitter && canUseWorkflowGate) {
|
|
981
986
|
const gateQuestion: AskGateQuestion = {
|
|
982
987
|
id: q.id,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Stealth Third-Party Notices
|
|
2
|
+
|
|
3
|
+
Per the approved plan, anti-detection evasions are **reimplemented/adapted** as
|
|
4
|
+
first-party code (no vendored source tree, no runtime dependency). This file
|
|
5
|
+
records provenance for evasion techniques whose semantics were informed by the
|
|
6
|
+
following open-source projects. Each individual reimplemented script also
|
|
7
|
+
carries an attributing header comment.
|
|
8
|
+
|
|
9
|
+
| Source project | License | Techniques referenced |
|
|
10
|
+
|----------------|---------|-----------------------|
|
|
11
|
+
| rebrowser-patches | MIT | CDP `Runtime.enable` leak mitigation (data-driven; landed only if the offline baseline shows a runtime/CDP leak signal) |
|
|
12
|
+
| puppeteer-extra-plugin-stealth | MIT | Fingerprint evasion signal set (navigator/webgl/plugins/permissions/webrtc surfaces) overlapping and complementing the existing injection scripts |
|
|
13
|
+
| fingerprint-suite (fingerprint-injector / generator) | Apache-2.0 | Coherent fingerprint attribute generation ideas |
|
|
14
|
+
|
|
15
|
+
No source files from these projects are copied into this repository. Only the
|
|
16
|
+
observable behaviors/signal semantics were reimplemented against `puppeteer-core`
|
|
17
|
+
after being confirmed by the offline benchmark suite
|
|
18
|
+
(`test/fixtures/stealth-detectors/`, `src/tools/browser/benchmark/`).
|
|
19
|
+
|
|
20
|
+
## Detector fixtures
|
|
21
|
+
|
|
22
|
+
The offline detector fixtures under `test/fixtures/stealth-detectors/` are
|
|
23
|
+
first-party probes modeled on the public boolean signal sets used by
|
|
24
|
+
`bot.sannysoft.com` and CreepJS. They are self-contained (inline JS, zero
|
|
25
|
+
network) and are not verbatim copies of those sites. See that directory's
|
|
26
|
+
`MANIFEST.json` for the refresh procedure.
|