@gajae-code/coding-agent 0.10.1 → 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 +70 -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/gajae-pet-widget.d.ts +1 -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/pet-capability.d.ts +37 -0
- package/dist/types/modes/components/pet-selector.d.ts +1 -1
- package/dist/types/modes/components/settings-selector.d.ts +15 -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 +5 -1
- 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 +16 -1
- 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 +37 -34
- 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/extensibility/slash-commands.ts +3 -3
- 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 +5 -2
- 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 +36 -37
- 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/custom-editor.ts +1 -0
- package/src/modes/components/gajae-pet-widget.ts +169 -20
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/pet-capability.ts +115 -0
- package/src/modes/components/pet-selector.ts +4 -6
- package/src/modes/components/settings-selector.ts +86 -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 +357 -12
- package/src/modes/controllers/input-controller.ts +43 -13
- package/src/modes/controllers/selector-controller.ts +671 -44
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +108 -24
- 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 +16 -1
- 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 +2470 -866
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +447 -13
- 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 +33 -30
- 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
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.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline stealth-detector benchmark model.
|
|
3
|
+
*
|
|
4
|
+
* Pure, deterministic logic for the anti-detection benchmark suite: it converts
|
|
5
|
+
* a browser-collected fingerprint probe into a normalized per-detector verdict,
|
|
6
|
+
* implements the falsifiable CI gate (see plan Phase 1 / R-T3), and renders a
|
|
7
|
+
* before/after report. No browser or network access lives here so it can be
|
|
8
|
+
* unit-tested deterministically; the harness that drives the real browser tool
|
|
9
|
+
* against vendored detector fixtures feeds its output into these functions.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type SignalStatus = "pass" | "fail";
|
|
13
|
+
|
|
14
|
+
/** A single boolean fingerprint signal, e.g. "navigator.webdriver is undefined". */
|
|
15
|
+
export interface DetectorSignal {
|
|
16
|
+
/** Stable identifier, used to diff across runs. */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Human-readable label for the report. */
|
|
19
|
+
label: string;
|
|
20
|
+
/** `pass` means the signal looks human; `fail` means it leaks automation. */
|
|
21
|
+
status: SignalStatus;
|
|
22
|
+
/** Optional observed value for debugging. */
|
|
23
|
+
detail?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type AutomatedVerdict = "human" | "bot" | "unknown";
|
|
27
|
+
|
|
28
|
+
/** Normalized result for one detector (e.g. bot.sannysoft, CreepJS). */
|
|
29
|
+
export interface DetectorResult {
|
|
30
|
+
detector: string;
|
|
31
|
+
signals: DetectorSignal[];
|
|
32
|
+
/** Overall automated/not classification when the detector exposes one. */
|
|
33
|
+
automatedVerdict: AutomatedVerdict;
|
|
34
|
+
/** Absolute trust score (observability-only, never a hard gate). */
|
|
35
|
+
trustScore: number | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Shape emitted by the offline probe fixture on `window.__stealthProbe`. */
|
|
39
|
+
export interface RawProbe {
|
|
40
|
+
detector: string;
|
|
41
|
+
signals: Array<{ id: string; label: string; pass: boolean; detail?: string }>;
|
|
42
|
+
automatedVerdict?: AutomatedVerdict;
|
|
43
|
+
trustScore?: number | null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Convert a raw browser-collected probe into a normalized {@link DetectorResult}. */
|
|
47
|
+
export function parseProbe(raw: RawProbe): DetectorResult {
|
|
48
|
+
if (!raw || typeof raw.detector !== "string" || !Array.isArray(raw.signals)) {
|
|
49
|
+
throw new Error("invalid stealth probe payload");
|
|
50
|
+
}
|
|
51
|
+
const signals: DetectorSignal[] = raw.signals.map(s => ({
|
|
52
|
+
id: s.id,
|
|
53
|
+
label: s.label,
|
|
54
|
+
status: s.pass ? "pass" : "fail",
|
|
55
|
+
...(s.detail !== undefined ? { detail: s.detail } : {}),
|
|
56
|
+
}));
|
|
57
|
+
return {
|
|
58
|
+
detector: raw.detector,
|
|
59
|
+
signals,
|
|
60
|
+
automatedVerdict: raw.automatedVerdict ?? "unknown",
|
|
61
|
+
trustScore: raw.trustScore ?? null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function passCount(result: DetectorResult): number {
|
|
66
|
+
return result.signals.filter(s => s.status === "pass").length;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function failingSignalIds(result: DetectorResult): Set<string> {
|
|
70
|
+
return new Set(result.signals.filter(s => s.status === "fail").map(s => s.id));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface GateOutcome {
|
|
74
|
+
pass: boolean;
|
|
75
|
+
reasons: string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Falsifiable CI gate (plan Phase 1 / R-T3, R-C1, R-C2):
|
|
80
|
+
* (a) zero failing signals in the current run, AND
|
|
81
|
+
* current pass-count >= baseline pass-count (no silent regression), AND
|
|
82
|
+
* (b) either at least one signal that failed at baseline now passes,
|
|
83
|
+
* OR the baseline was already all-green (empty-gap regression lock).
|
|
84
|
+
* The absolute `trustScore` is never consulted here; it is observability-only.
|
|
85
|
+
*/
|
|
86
|
+
export function evaluateGate(baseline: DetectorResult, current: DetectorResult): GateOutcome {
|
|
87
|
+
const reasons: string[] = [];
|
|
88
|
+
const currentFail = failingSignalIds(current);
|
|
89
|
+
if (currentFail.size > 0) {
|
|
90
|
+
reasons.push(
|
|
91
|
+
`${current.detector}: ${currentFail.size} signal(s) still leak automation: ${[...currentFail].join(", ")}`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const baselinePass = passCount(baseline);
|
|
96
|
+
const currentPass = passCount(current);
|
|
97
|
+
if (currentPass < baselinePass) {
|
|
98
|
+
reasons.push(`${current.detector}: pass-count regressed (${currentPass} < baseline ${baselinePass})`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const baselineFail = failingSignalIds(baseline);
|
|
102
|
+
const currentPassIds = new Set(current.signals.filter(s => s.status === "pass").map(s => s.id));
|
|
103
|
+
const newlyPassing = [...baselineFail].filter(id => currentPassIds.has(id));
|
|
104
|
+
const baselineAllGreen = baselineFail.size === 0;
|
|
105
|
+
if (!baselineAllGreen && newlyPassing.length === 0) {
|
|
106
|
+
reasons.push(`${current.detector}: no baseline-failing signal was fixed (improvement required)`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return { pass: reasons.length === 0, reasons };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Aggregate gate across every detector; passes only when all detectors pass. */
|
|
113
|
+
export function evaluateSuiteGate(
|
|
114
|
+
baseline: readonly DetectorResult[],
|
|
115
|
+
current: readonly DetectorResult[],
|
|
116
|
+
): GateOutcome {
|
|
117
|
+
const reasons: string[] = [];
|
|
118
|
+
const currentByName = new Map(current.map(r => [r.detector, r]));
|
|
119
|
+
for (const base of baseline) {
|
|
120
|
+
const now = currentByName.get(base.detector);
|
|
121
|
+
if (!now) {
|
|
122
|
+
reasons.push(`${base.detector}: missing from current run`);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
reasons.push(...evaluateGate(base, now).reasons);
|
|
126
|
+
}
|
|
127
|
+
return { pass: reasons.length === 0, reasons };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Render a deterministic before/after markdown report for one run. */
|
|
131
|
+
export function renderReport(baseline: readonly DetectorResult[], current: readonly DetectorResult[]): string {
|
|
132
|
+
const lines: string[] = ["# Stealth Benchmark Report", ""];
|
|
133
|
+
const gate = evaluateSuiteGate(baseline, current);
|
|
134
|
+
lines.push(`Gate: ${gate.pass ? "PASS" : "FAIL"}`, "");
|
|
135
|
+
const currentByName = new Map(current.map(r => [r.detector, r]));
|
|
136
|
+
for (const base of baseline) {
|
|
137
|
+
const now = currentByName.get(base.detector);
|
|
138
|
+
lines.push(`## ${base.detector}`);
|
|
139
|
+
lines.push(
|
|
140
|
+
`- Automated verdict: ${base.automatedVerdict} -> ${now?.automatedVerdict ?? "n/a"}`,
|
|
141
|
+
`- Trust score (observability): ${base.trustScore ?? "n/a"} -> ${now?.trustScore ?? "n/a"}`,
|
|
142
|
+
`- Passing signals: ${passCount(base)} -> ${now ? passCount(now) : "n/a"} of ${base.signals.length}`,
|
|
143
|
+
"",
|
|
144
|
+
"| Signal | Baseline | Current |",
|
|
145
|
+
"|--------|----------|---------|",
|
|
146
|
+
);
|
|
147
|
+
for (const sig of base.signals) {
|
|
148
|
+
const nowSig = now?.signals.find(s => s.id === sig.id);
|
|
149
|
+
lines.push(`| ${sig.label} | ${sig.status} | ${nowSig?.status ?? "n/a"} |`);
|
|
150
|
+
}
|
|
151
|
+
lines.push("");
|
|
152
|
+
}
|
|
153
|
+
if (!gate.pass) {
|
|
154
|
+
lines.push("## Blocking reasons", ...gate.reasons.map(r => `- ${r}`), "");
|
|
155
|
+
}
|
|
156
|
+
return lines.join("\n");
|
|
157
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Offline stealth benchmark harness (plan Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* Drives a puppeteer Page (already stealth-patched by the browser tool) against
|
|
5
|
+
* self-contained offline detector fixtures and collects normalized results. The
|
|
6
|
+
* navigation/evaluation is injected so this stays unit-testable without a real
|
|
7
|
+
* browser; the integration test wires a live puppeteer Page.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Page } from "puppeteer-core";
|
|
11
|
+
import type { DetectorResult, RawProbe } from "./detector-report";
|
|
12
|
+
import { parseProbe } from "./detector-report";
|
|
13
|
+
|
|
14
|
+
/** Minimal surface of a puppeteer Page that the harness needs. */
|
|
15
|
+
export type SuitePage = Pick<Page, "goto" | "evaluate">;
|
|
16
|
+
|
|
17
|
+
export interface SuiteFixture {
|
|
18
|
+
/** file:// (or http://) URL of the offline detector fixture. */
|
|
19
|
+
url: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Read the probe the fixture placed on `window.__stealthProbe`. */
|
|
23
|
+
function readProbe(): RawProbe {
|
|
24
|
+
// Runs in the browser context.
|
|
25
|
+
const probe = (globalThis as unknown as { __stealthProbe?: RawProbe }).__stealthProbe;
|
|
26
|
+
if (!probe) throw new Error("fixture did not expose window.__stealthProbe");
|
|
27
|
+
return probe;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Navigate to each fixture and collect a normalized DetectorResult per fixture. */
|
|
31
|
+
export async function runOfflineSuite(page: SuitePage, fixtures: readonly SuiteFixture[]): Promise<DetectorResult[]> {
|
|
32
|
+
const results: DetectorResult[] = [];
|
|
33
|
+
for (const fixture of fixtures) {
|
|
34
|
+
await page.goto(fixture.url, { waitUntil: "load" });
|
|
35
|
+
const raw = await page.evaluate(readProbe);
|
|
36
|
+
results.push(parseProbe(raw));
|
|
37
|
+
}
|
|
38
|
+
return results;
|
|
39
|
+
}
|