@gajae-code/coding-agent 0.10.2 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -2
- package/dist/types/append-only-mode.d.ts +1 -1
- package/dist/types/async/job-manager.d.ts +46 -7
- package/dist/types/cli/args.d.ts +4 -5
- package/dist/types/cli/daemon-cli.d.ts +12 -1
- package/dist/types/cli/notify-cli.d.ts +21 -1
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/notify.d.ts +28 -1
- package/dist/types/commands/sdk.d.ts +33 -0
- package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
- package/dist/types/config/model-profile-activation.d.ts +35 -15
- package/dist/types/config/model-profiles.d.ts +11 -5
- package/dist/types/config/model-registry.d.ts +3 -3
- package/dist/types/config/model-resolver.d.ts +39 -6
- package/dist/types/config/model-selector-value.d.ts +17 -0
- package/dist/types/config/models-config-schema.d.ts +10 -6
- package/dist/types/config/settings-schema.d.ts +133 -6
- package/dist/types/config/settings.d.ts +63 -35
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
- package/dist/types/coordinator-mcp/server.d.ts +6 -49
- package/dist/types/daemon/builtin.d.ts +6 -5
- package/dist/types/daemon/control-types.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +12 -1
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
- package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
- package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
- package/dist/types/extensibility/extensions/loader.d.ts +10 -1
- package/dist/types/extensibility/extensions/runner.d.ts +3 -3
- package/dist/types/extensibility/extensions/types.d.ts +141 -16
- package/dist/types/extensibility/hooks/types.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
- package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
- package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
- package/dist/types/harness-control-plane/operate.d.ts +5 -5
- package/dist/types/harness-control-plane/owner.d.ts +18 -4
- package/dist/types/harness-control-plane/receipts.d.ts +0 -1
- package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
- package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
- package/dist/types/harness-control-plane/types.d.ts +3 -4
- package/dist/types/lsp/index.d.ts +1 -1
- package/dist/types/main.d.ts +32 -38
- package/dist/types/modes/acp/acp-agent.d.ts +224 -53
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
- package/dist/types/modes/acp/acp-mode.d.ts +6 -15
- package/dist/types/modes/acp/permission-mode.d.ts +4 -0
- package/dist/types/modes/acp/startup-options.d.ts +6 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
- package/dist/types/modes/components/model-selector.d.ts +1 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
- package/dist/types/modes/components/settings-selector.d.ts +6 -4
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
- package/dist/types/modes/index.d.ts +0 -4
- package/dist/types/modes/interactive-mode.d.ts +5 -2
- package/dist/types/modes/runtime-init.d.ts +2 -2
- package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
- package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
- package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
- package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
- package/dist/types/modes/types.d.ts +7 -2
- package/dist/types/runtime-mcp/client.d.ts +2 -0
- package/dist/types/runtime-mcp/config.d.ts +5 -1
- package/dist/types/runtime-mcp/manager.d.ts +8 -1
- package/dist/types/runtime-mcp/types.d.ts +4 -0
- package/dist/types/sdk/acp/adapter.d.ts +67 -0
- package/dist/types/sdk/acp/index.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +53 -0
- package/dist/types/sdk/broker/discovery.d.ts +30 -0
- package/dist/types/sdk/broker/ensure.d.ts +42 -0
- package/dist/types/sdk/broker/identity.d.ts +3 -0
- package/dist/types/sdk/broker/index.d.ts +8 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
- package/dist/types/sdk/broker/runtime.d.ts +33 -0
- package/dist/types/sdk/broker/session-index.d.ts +57 -0
- package/dist/types/sdk/broker/state-version.d.ts +8 -0
- package/dist/types/sdk/broker/transport.d.ts +9 -0
- package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
- package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
- package/dist/types/sdk/bus/config.d.ts +274 -0
- package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
- package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
- package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
- package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
- package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
- package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
- package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
- package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
- package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
- package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
- package/dist/types/sdk/bus/session-control.d.ts +83 -0
- package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
- package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
- package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
- package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
- package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
- package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
- package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
- package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
- package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
- package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/session-cli.d.ts +19 -0
- package/dist/types/sdk/client/client.d.ts +1 -0
- package/dist/types/sdk/client/discovery.d.ts +27 -0
- package/dist/types/sdk/client/index.d.ts +2 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
- package/dist/types/sdk/host/control/index.d.ts +2 -0
- package/dist/types/sdk/host/control/operations.d.ts +65 -0
- package/dist/types/sdk/host/events.d.ts +35 -0
- package/dist/types/sdk/host/host.d.ts +35 -0
- package/dist/types/sdk/host/index.d.ts +4 -0
- package/dist/types/sdk/host/query/cursor.d.ts +62 -0
- package/dist/types/sdk/host/query/handlers.d.ts +70 -0
- package/dist/types/sdk/host/query/index.d.ts +3 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
- package/dist/types/sdk/host/types.d.ts +32 -0
- package/dist/types/sdk/index.d.ts +6 -0
- package/dist/types/sdk/lifecycle-session.d.ts +14 -0
- package/dist/types/sdk/mcp/index.d.ts +1 -0
- package/dist/types/sdk/mcp/server.d.ts +37 -0
- package/dist/types/sdk/models.d.ts +44 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
- package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
- package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
- package/dist/types/sdk/startup-capability.d.ts +50 -0
- package/dist/types/session/agent-session.d.ts +114 -21
- package/dist/types/session/default-model-selection.d.ts +25 -0
- package/dist/types/session/fallback-chain-controller.d.ts +52 -0
- package/dist/types/session/session-manager.d.ts +58 -1
- package/dist/types/setup/credential-auto-import.d.ts +36 -6
- package/dist/types/tools/ask-answer-registry.d.ts +1 -1
- package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
- package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
- package/dist/types/tools/browser/launch.d.ts +22 -0
- package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
- package/dist/types/tools/browser/profile-posture.d.ts +37 -0
- package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
- package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
- package/dist/types/tools/browser/registry.d.ts +19 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/index.d.ts +8 -8
- package/dist/types/tools/subagent-render.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +6 -1
- package/package.json +34 -13
- package/scripts/build-sdk-package-smoke.ts +99 -0
- package/scripts/capture-notifications-settings-showcase.ts +435 -0
- package/scripts/compile-args.ts +4 -2
- package/scripts/g005-daemon-smoke.ts +4 -5
- package/scripts/g011-daemon-path-smoke.ts +5 -5
- package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
- package/scripts/generate-sdk-operation-inventory.ts +867 -0
- package/scripts/generate-telegram-baseline-manifest.ts +128 -0
- package/scripts/manifest-schema.ts +124 -0
- package/scripts/run-test-manifest.ts +153 -0
- package/scripts/run-threat-model-check.ts +157 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
- package/scripts/verify-gjc-sdk-rename.ts +90 -0
- package/src/append-only-mode.ts +1 -1
- package/src/async/job-manager.ts +406 -63
- package/src/cli/args.ts +43 -12
- package/src/cli/auth-gateway-cli.ts +2 -2
- package/src/cli/config-cli.ts +2 -1
- package/src/cli/daemon-cli.ts +63 -14
- package/src/cli/list-models.ts +1 -1
- package/src/cli/notify-cli.ts +288 -286
- package/src/cli.ts +21 -2
- package/src/commands/daemon.ts +50 -6
- package/src/commands/harness.ts +93 -36
- package/src/commands/launch.ts +5 -2
- package/src/commands/mcp-serve.ts +19 -12
- package/src/commands/notify.ts +36 -3
- package/src/commands/sdk.ts +426 -0
- package/src/commit/agentic/agent.ts +1 -0
- package/src/config/atomic-yaml-patch.ts +423 -0
- package/src/config/model-profile-activation.ts +240 -89
- package/src/config/model-profiles.ts +18 -15
- package/src/config/model-registry.ts +51 -26
- package/src/config/model-resolver.ts +138 -51
- package/src/config/model-selector-value.ts +50 -0
- package/src/config/models-config-schema.ts +14 -21
- package/src/config/settings-schema.ts +128 -10
- package/src/config/settings.ts +1120 -158
- package/src/coordinator-mcp/model-preset.ts +74 -20
- package/src/coordinator-mcp/server.ts +1597 -3052
- package/src/daemon/builtin.ts +8 -5
- package/src/daemon/control-types.ts +1 -1
- package/src/defaults/gjc/skills/team/SKILL.md +4 -4
- package/src/discovery/mcp-json.ts +327 -20
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/compact-handler.ts +3 -3
- package/src/extensibility/extensions/get-commands-handler.ts +2 -2
- package/src/extensibility/extensions/loader.ts +69 -5
- package/src/extensibility/extensions/runner.ts +112 -4
- package/src/extensibility/extensions/types.ts +176 -17
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/gjc-runtime/launch-tmux.ts +170 -86
- package/src/gjc-runtime/psmux-detect.ts +82 -4
- package/src/gjc-runtime/session-state-sidecar.ts +41 -31
- package/src/gjc-runtime/team-runtime.ts +54 -35
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
- package/src/gjc-runtime/tmux-sessions.ts +19 -13
- package/src/gjc-runtime/ultragoal-guard.ts +108 -14
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
- package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
- package/src/gjc-runtime/windows-powershell-command.ts +58 -0
- package/src/harness-control-plane/operate.ts +9 -9
- package/src/harness-control-plane/owner.ts +283 -39
- package/src/harness-control-plane/receipts.ts +0 -1
- package/src/harness-control-plane/sdk-transport.ts +395 -0
- package/src/harness-control-plane/session-transport.ts +94 -0
- package/src/harness-control-plane/types.ts +1 -1
- package/src/internal-urls/docs-index.generated.ts +34 -35
- package/src/lsp/client.ts +42 -6
- package/src/lsp/index.ts +2 -2
- package/src/main.ts +299 -204
- package/src/modes/DESIGN.md +258 -0
- package/src/modes/acp/acp-agent.ts +1228 -2612
- package/src/modes/acp/acp-client-bridge.ts +2 -20
- package/src/modes/acp/acp-event-mapper.ts +18 -2
- package/src/modes/acp/acp-mode.ts +8 -36
- package/src/modes/acp/permission-mode.ts +25 -0
- package/src/modes/acp/startup-options.ts +6 -0
- package/src/modes/components/agent-dashboard.ts +37 -17
- package/src/modes/components/model-selector.ts +93 -35
- package/src/modes/components/notifications-settings-editor.ts +1379 -0
- package/src/modes/components/settings-selector.ts +60 -11
- package/src/modes/components/welcome.ts +4 -4
- package/src/modes/controllers/command-controller.ts +10 -17
- package/src/modes/controllers/event-controller.ts +11 -16
- package/src/modes/controllers/extension-ui-controller.ts +396 -28
- package/src/modes/controllers/selector-controller.ts +674 -36
- package/src/modes/index.ts +0 -22
- package/src/modes/interactive-mode.ts +87 -36
- package/src/modes/runtime-init.ts +298 -6
- package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
- package/src/modes/shared/agent-wire/event-contract.ts +7 -8
- package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
- package/src/modes/shared/agent-wire/event-observation.ts +16 -7
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
- package/src/modes/types.ts +7 -2
- package/src/runtime-mcp/client.ts +94 -19
- package/src/runtime-mcp/config.ts +27 -15
- package/src/runtime-mcp/manager.ts +343 -105
- package/src/runtime-mcp/oauth-flow.ts +42 -12
- package/src/runtime-mcp/transports/http.ts +49 -19
- package/src/runtime-mcp/transports/stdio.ts +47 -28
- package/src/runtime-mcp/types.ts +10 -0
- package/src/sdk/acp/adapter.ts +418 -0
- package/src/sdk/acp/index.ts +2 -0
- package/src/sdk/broker/broker.ts +642 -0
- package/src/sdk/broker/discovery.ts +113 -0
- package/src/sdk/broker/ensure.ts +307 -0
- package/src/sdk/broker/identity.ts +42 -0
- package/src/sdk/broker/index.ts +8 -0
- package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
- package/src/sdk/broker/internal-source.bunfig.toml +1 -0
- package/src/sdk/broker/lifecycle-ledger.ts +286 -0
- package/src/sdk/broker/lifecycle.ts +2157 -0
- package/src/sdk/broker/process-incarnation.ts +159 -0
- package/src/sdk/broker/runtime.ts +164 -0
- package/src/sdk/broker/session-index.ts +318 -0
- package/src/sdk/broker/state-version.ts +23 -0
- package/src/sdk/broker/transport.ts +125 -0
- package/src/sdk/bus/chat-command-policy.ts +107 -0
- package/src/sdk/bus/chat-daemon-cli.ts +214 -0
- package/src/sdk/bus/chat-daemon-control.ts +713 -0
- package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
- package/src/sdk/bus/chat-effect-journal.ts +355 -0
- package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
- package/src/sdk/bus/config.ts +433 -0
- package/src/sdk/bus/conversation-store.ts +391 -0
- package/src/sdk/bus/discord-conversation.ts +85 -0
- package/src/sdk/bus/discord-daemon.ts +2292 -0
- package/src/sdk/bus/discord-live-provider.ts +521 -0
- package/src/sdk/bus/discord-provider.ts +56 -0
- package/src/{notifications → sdk/bus}/html-format.ts +2 -2
- package/src/sdk/bus/index.ts +3979 -0
- package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
- package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
- package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
- package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
- package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
- package/src/sdk/bus/natives-augment.d.ts +38 -0
- package/src/sdk/bus/notification-orchestration.ts +535 -0
- package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
- package/src/sdk/bus/session-control.ts +333 -0
- package/src/sdk/bus/slack-conversation.ts +74 -0
- package/src/sdk/bus/slack-daemon.ts +2144 -0
- package/src/sdk/bus/slack-live-provider.ts +380 -0
- package/src/sdk/bus/slack-provider.ts +76 -0
- package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
- package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
- package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
- package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
- package/src/sdk/bus/telegram-setup.ts +663 -0
- package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/session-cli.ts +275 -0
- package/src/sdk/client/client.ts +1 -0
- package/src/sdk/client/discovery.ts +108 -0
- package/src/sdk/client/index.ts +2 -0
- package/src/sdk/host/control/dispatch.ts +367 -0
- package/src/sdk/host/control/index.ts +10 -0
- package/src/sdk/host/control/operations.ts +63 -0
- package/src/sdk/host/events.ts +91 -0
- package/src/sdk/host/host.ts +296 -0
- package/src/sdk/host/index.ts +4 -0
- package/src/sdk/host/query/cursor.ts +189 -0
- package/src/sdk/host/query/handlers.ts +533 -0
- package/src/sdk/host/query/index.ts +3 -0
- package/src/sdk/host/query/revision-store.ts +1126 -0
- package/src/sdk/host/reverse-leases.ts +325 -0
- package/src/sdk/host/types.ts +29 -0
- package/src/sdk/index.ts +13 -0
- package/src/sdk/lifecycle-session.ts +39 -0
- package/src/sdk/mcp/index.ts +1 -0
- package/src/sdk/mcp/server.ts +332 -0
- package/src/sdk/models.ts +168 -0
- package/src/sdk/protocol/adapter-validation.ts +48 -0
- package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
- package/src/sdk/protocol/operation-registry.ts +312 -0
- package/src/{sdk.ts → sdk/session.ts} +339 -212
- package/src/sdk/startup-capability.ts +189 -0
- package/src/session/agent-session.ts +2650 -944
- package/src/session/default-model-selection.ts +93 -0
- package/src/session/fallback-chain-controller.ts +136 -0
- package/src/session/session-manager.ts +438 -11
- package/src/session/session-storage.ts +8 -1
- package/src/setup/credential-auto-import.ts +290 -35
- package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
- package/src/slash-commands/builtin-registry.ts +2 -1
- package/src/task/executor.ts +62 -13
- package/src/task/index.ts +26 -16
- package/src/tools/ask-answer-registry.ts +1 -1
- package/src/tools/ask.ts +13 -8
- package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
- package/src/tools/browser/benchmark/detector-report.ts +157 -0
- package/src/tools/browser/benchmark/run-suite.ts +39 -0
- package/src/tools/browser/launch.ts +124 -19
- package/src/tools/browser/profile-discovery.ts +63 -0
- package/src/tools/browser/profile-posture.ts +59 -0
- package/src/tools/browser/profile-reuse.ts +102 -0
- package/src/tools/browser/profile-warmup.ts +109 -0
- package/src/tools/browser/registry.ts +87 -11
- package/src/tools/browser/tab-protocol.ts +1 -0
- package/src/tools/browser/tab-supervisor.ts +1 -0
- package/src/tools/browser/tab-worker.ts +1 -1
- package/src/tools/browser.ts +6 -0
- package/src/tools/index.ts +8 -8
- package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
- package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
- package/src/tools/subagent-render.ts +19 -8
- package/src/tools/subagent.ts +84 -32
- package/src/tools/telegram-send.ts +2 -2
- package/vendor/insane-search/MANIFEST.json +2 -1
- package/vendor/insane-search/engine/bias_check.py +4 -1
- package/vendor/insane-search/engine/phase0.py +26 -1
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
- package/dist/types/modes/bridge/auth.d.ts +0 -12
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
- package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
- package/dist/types/modes/bridge/event-stream.d.ts +0 -8
- package/dist/types/modes/rpc/host-tools.d.ts +0 -1
- package/dist/types/modes/rpc/host-uris.d.ts +0 -1
- package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
- package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
- package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
- package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
- package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
- package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
- package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
- package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
- package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
- package/dist/types/notifications/config.d.ts +0 -132
- package/src/harness-control-plane/rpc-adapter.ts +0 -290
- package/src/modes/bridge/auth.ts +0 -41
- package/src/modes/bridge/bridge-client-bridge.ts +0 -47
- package/src/modes/bridge/bridge-mode.ts +0 -675
- package/src/modes/bridge/bridge-ui-context.ts +0 -200
- package/src/modes/bridge/event-stream.ts +0 -70
- package/src/modes/rpc/host-tools.ts +0 -1
- package/src/modes/rpc/host-uris.ts +0 -1
- package/src/modes/rpc/rpc-client.ts +0 -1166
- package/src/modes/rpc/rpc-mode.ts +0 -1029
- package/src/modes/rpc/rpc-socket-security.ts +0 -115
- package/src/modes/rpc/rpc-types.ts +0 -637
- package/src/modes/shared/agent-wire/command-contract.ts +0 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
- package/src/modes/shared/agent-wire/command-validation.ts +0 -181
- package/src/modes/shared/agent-wire/handshake.ts +0 -157
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
- package/src/modes/shared/agent-wire/protocol.ts +0 -46
- package/src/modes/shared/agent-wire/responses.ts +0 -17
- package/src/modes/shared/agent-wire/scopes.ts +0 -94
- package/src/modes/shared/agent-wire/session-registry.ts +0 -109
- package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
- package/src/modes/shared/agent-wire/ui-result.ts +0 -48
- package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
- package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
- package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
- package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
- package/src/notifications/config.ts +0 -219
- package/src/notifications/index.ts +0 -1835
- package/src/notifications/telegram-daemon-cli.ts +0 -243
- package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
- /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
- /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
- /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
- /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
- /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
- /package/src/{notifications → sdk/bus}/engine.ts +0 -0
- /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
- /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
- /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
- /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
- /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
- /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
- /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
package/src/async/job-manager.ts
CHANGED
|
@@ -75,6 +75,47 @@ export type SubagentRunOutcome = { kind: "completed"; text: string } | { kind: "
|
|
|
75
75
|
/** Canonical lifecycle of a subagent across pause/resume cycles. */
|
|
76
76
|
export type SubagentLifecycle = "running" | "paused" | "queued" | "completed" | "failed" | "cancelled";
|
|
77
77
|
|
|
78
|
+
/** Maximum time allowed to prove owned subagents have stopped before replacement. */
|
|
79
|
+
export const OWNER_SUBAGENT_SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
80
|
+
|
|
81
|
+
export class OwnerSubagentShutdownError extends Error {
|
|
82
|
+
readonly code = "owner_shutdown_in_progress";
|
|
83
|
+
|
|
84
|
+
constructor() {
|
|
85
|
+
super("Cannot start subagent while owner shutdown is in progress.");
|
|
86
|
+
this.name = "OwnerSubagentShutdownError";
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface OwnerSubagentShutdownTarget {
|
|
91
|
+
subagentId: string;
|
|
92
|
+
jobId: string | null;
|
|
93
|
+
source: "record" | "metadata_job";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface OwnerSubagentShutdownLease {
|
|
97
|
+
ownerId: string;
|
|
98
|
+
id: string;
|
|
99
|
+
targets: readonly OwnerSubagentShutdownTarget[];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface OwnerSubagentShutdownProof {
|
|
103
|
+
ownerId: string;
|
|
104
|
+
leaseId: string;
|
|
105
|
+
confirmed: boolean;
|
|
106
|
+
reason: "confirmed" | "deadline_exceeded" | "missing_terminal_evidence" | "lease_lost";
|
|
107
|
+
targets: readonly OwnerSubagentShutdownTarget[];
|
|
108
|
+
terminalIds: readonly string[];
|
|
109
|
+
unresolvedIds: readonly string[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface OwnerSubagentShutdownLeaseState {
|
|
113
|
+
lease: OwnerSubagentShutdownLease;
|
|
114
|
+
backingJobIds: ReadonlyMap<string, readonly string[]>;
|
|
115
|
+
phase: "active" | "proving" | "proved";
|
|
116
|
+
proof?: OwnerSubagentShutdownProof;
|
|
117
|
+
}
|
|
118
|
+
|
|
78
119
|
/**
|
|
79
120
|
* Live, executor-owned control handle for a RUNNING subagent. Registered when a
|
|
80
121
|
* subagent run starts and removed on pause/terminal so a paused subagent retains
|
|
@@ -122,6 +163,12 @@ export interface ResumeDescriptor {
|
|
|
122
163
|
data: unknown;
|
|
123
164
|
}
|
|
124
165
|
|
|
166
|
+
/**
|
|
167
|
+
* In-memory resume runner bound to the session that originally launched a
|
|
168
|
+
* subagent. Never serialized: process restart drops it so resume fails closed.
|
|
169
|
+
*/
|
|
170
|
+
export type ResumeRunner = (subagentId: string, message?: string, descriptor?: ResumeDescriptor) => string | undefined;
|
|
171
|
+
|
|
125
172
|
function sessionFileFromResumeDescriptorData(data: unknown): string | null {
|
|
126
173
|
if (typeof data !== "object" || data === null) return null;
|
|
127
174
|
const sessionFile = (data as { sessionFile?: unknown }).sessionFile;
|
|
@@ -324,9 +371,19 @@ export class AsyncJobManager {
|
|
|
324
371
|
readonly #subagentProgress = new Map<string, AgentProgress>();
|
|
325
372
|
readonly #resumeQueue: ResumeQueueEntry[] = [];
|
|
326
373
|
#resumeSeq = 0;
|
|
327
|
-
#resumeRunner?:
|
|
374
|
+
#resumeRunner?: ResumeRunner;
|
|
328
375
|
readonly #resumeDescriptors = new Map<string, ResumeDescriptor>();
|
|
376
|
+
/**
|
|
377
|
+
* Per-descriptor in-memory resume runners, keyed by subagentId, captured at
|
|
378
|
+
* registerResumeDescriptor time so each resume executes under the authority of
|
|
379
|
+
* the session that originally launched that subagent. Fixes #2303's global
|
|
380
|
+
* last-writer-wins slot. In-memory only: a process restart drops these and
|
|
381
|
+
* resume fails closed with reason "no_runner".
|
|
382
|
+
*/
|
|
383
|
+
readonly #descriptorResumeRunners = new Map<string, ResumeRunner>();
|
|
329
384
|
readonly #deadLetteredDeliveries = new Map<string, AsyncJobDelivery>();
|
|
385
|
+
readonly #ownerSubagentShutdownLeases = new Map<string, OwnerSubagentShutdownLeaseState>();
|
|
386
|
+
#ownerSubagentShutdownSeq = 0;
|
|
330
387
|
#lastDisposeDiagnostics: AsyncJobDisposeDiagnostics = { stuckJobIds: [], deliveriesDrained: true };
|
|
331
388
|
/**
|
|
332
389
|
* Change listeners notified on any mutation that can alter the live job set
|
|
@@ -387,6 +444,9 @@ export class AsyncJobManager {
|
|
|
387
444
|
if (this.#disposed) {
|
|
388
445
|
throw new Error("Async job manager is disposed");
|
|
389
446
|
}
|
|
447
|
+
if (options?.ownerId && this.#isOwnerSubagentShutdownFenced(options.ownerId)) {
|
|
448
|
+
throw new OwnerSubagentShutdownError();
|
|
449
|
+
}
|
|
390
450
|
const runningCount = this.getRunningJobs().length;
|
|
391
451
|
if (runningCount >= this.#maxRunningJobs) {
|
|
392
452
|
throw new Error(
|
|
@@ -687,14 +747,23 @@ export class AsyncJobManager {
|
|
|
687
747
|
}
|
|
688
748
|
|
|
689
749
|
/** Install the TaskTool-owned resume runner. Returns the new job id, or undefined on failure. */
|
|
690
|
-
setResumeRunner(
|
|
691
|
-
runner: (subagentId: string, message?: string, descriptor?: ResumeDescriptor) => string | undefined,
|
|
692
|
-
): void {
|
|
750
|
+
setResumeRunner(runner: ResumeRunner): void {
|
|
693
751
|
this.#resumeRunner = runner;
|
|
694
752
|
}
|
|
695
753
|
|
|
696
|
-
registerResumeDescriptor(descriptor: ResumeDescriptor): void {
|
|
754
|
+
registerResumeDescriptor(descriptor: ResumeDescriptor, runner?: ResumeRunner): void {
|
|
697
755
|
this.#resumeDescriptors.set(descriptor.subagentId, descriptor);
|
|
756
|
+
if (runner) this.#descriptorResumeRunners.set(descriptor.subagentId, runner);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Resolve the resume runner for a subagent: prefer the per-descriptor runner
|
|
761
|
+
* captured at registration time (the originating parent's execution authority),
|
|
762
|
+
* falling back to the process-global runner only for descriptors registered
|
|
763
|
+
* without one.
|
|
764
|
+
*/
|
|
765
|
+
#resolveResumeRunner(subagentId: string): ResumeRunner | undefined {
|
|
766
|
+
return this.#descriptorResumeRunners.get(subagentId) ?? this.#resumeRunner;
|
|
698
767
|
}
|
|
699
768
|
|
|
700
769
|
getResumeDescriptor(subagentId: string, filter?: AsyncJobFilter): ResumeDescriptor | undefined {
|
|
@@ -704,6 +773,224 @@ export class AsyncJobManager {
|
|
|
704
773
|
return descriptor;
|
|
705
774
|
}
|
|
706
775
|
|
|
776
|
+
#isOwnerSubagentShutdownFenced(ownerId: string | undefined): boolean {
|
|
777
|
+
return ownerId !== undefined && this.#ownerSubagentShutdownLeases.has(ownerId);
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
#isTerminalSubagentStatus(status: SubagentLifecycle): boolean {
|
|
781
|
+
return status === "completed" || status === "failed" || status === "cancelled";
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
beginOwnerSubagentShutdown(ownerId: string): OwnerSubagentShutdownLease | undefined {
|
|
785
|
+
if (!ownerId || this.#ownerSubagentShutdownLeases.has(ownerId)) return undefined;
|
|
786
|
+
const targets = new Map<string, OwnerSubagentShutdownTarget>();
|
|
787
|
+
const backingJobIds = new Map<string, Set<string>>();
|
|
788
|
+
const addBackingJob = (subagentId: string, jobId: string | null): void => {
|
|
789
|
+
if (!jobId) return;
|
|
790
|
+
const ids = backingJobIds.get(subagentId) ?? new Set<string>();
|
|
791
|
+
ids.add(jobId);
|
|
792
|
+
backingJobIds.set(subagentId, ids);
|
|
793
|
+
};
|
|
794
|
+
for (const record of this.#subagentRecords.values()) {
|
|
795
|
+
if (record.ownerId !== ownerId || this.#isTerminalSubagentStatus(record.status)) continue;
|
|
796
|
+
targets.set(record.subagentId, {
|
|
797
|
+
subagentId: record.subagentId,
|
|
798
|
+
jobId: record.status === "queued" ? null : record.currentJobId,
|
|
799
|
+
source: "record",
|
|
800
|
+
});
|
|
801
|
+
if (record.status !== "queued") addBackingJob(record.subagentId, record.currentJobId);
|
|
802
|
+
}
|
|
803
|
+
for (const job of this.#jobs.values()) {
|
|
804
|
+
const subagentId = job.metadata?.subagent?.id;
|
|
805
|
+
if (
|
|
806
|
+
job.ownerId !== ownerId ||
|
|
807
|
+
!subagentId ||
|
|
808
|
+
(job.status !== "running" && job.status !== "paused" && job.status !== "cancelled")
|
|
809
|
+
) {
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
if (!targets.has(subagentId)) {
|
|
813
|
+
targets.set(subagentId, { subagentId, jobId: job.id, source: "metadata_job" });
|
|
814
|
+
}
|
|
815
|
+
addBackingJob(subagentId, job.id);
|
|
816
|
+
}
|
|
817
|
+
const lease: OwnerSubagentShutdownLease = {
|
|
818
|
+
ownerId,
|
|
819
|
+
id: `owner_shutdown_${++this.#ownerSubagentShutdownSeq}`,
|
|
820
|
+
targets: Array.from(targets.values()),
|
|
821
|
+
};
|
|
822
|
+
this.#ownerSubagentShutdownLeases.set(ownerId, {
|
|
823
|
+
lease,
|
|
824
|
+
backingJobIds: new Map<string, readonly string[]>(
|
|
825
|
+
Array.from(backingJobIds, ([subagentId, jobIds]): [string, readonly string[]] => [
|
|
826
|
+
subagentId,
|
|
827
|
+
Array.from(jobIds),
|
|
828
|
+
]),
|
|
829
|
+
),
|
|
830
|
+
phase: "active",
|
|
831
|
+
});
|
|
832
|
+
return lease;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
runOwnerProducerCleanups(filter?: AsyncJobFilter): void {
|
|
836
|
+
this.#runOwnerProducerCleanups(filter, false);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
runOwnerProducerCleanupsStrict(filter?: AsyncJobFilter): void {
|
|
840
|
+
this.#runOwnerProducerCleanups(filter, true);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
#runOwnerProducerCleanups(filter: AsyncJobFilter | undefined, strict: boolean): void {
|
|
844
|
+
const ownerId = filter?.ownerId;
|
|
845
|
+
const targets: Array<[string, Set<() => void>]> = [];
|
|
846
|
+
if (ownerId) {
|
|
847
|
+
const bag = this.#ownerCleanups.get(ownerId);
|
|
848
|
+
if (bag) targets.push([ownerId, bag]);
|
|
849
|
+
} else {
|
|
850
|
+
for (const entry of this.#ownerCleanups.entries()) targets.push(entry);
|
|
851
|
+
}
|
|
852
|
+
const errors: unknown[] = [];
|
|
853
|
+
for (const [id, bag] of targets) {
|
|
854
|
+
const callbacks = Array.from(bag);
|
|
855
|
+
bag.clear();
|
|
856
|
+
this.#ownerCleanups.delete(id);
|
|
857
|
+
for (const cleanup of callbacks) {
|
|
858
|
+
try {
|
|
859
|
+
cleanup();
|
|
860
|
+
} catch (error) {
|
|
861
|
+
errors.push(error);
|
|
862
|
+
if (strict) {
|
|
863
|
+
let retryBag = this.#ownerCleanups.get(id);
|
|
864
|
+
if (!retryBag) {
|
|
865
|
+
retryBag = new Set();
|
|
866
|
+
this.#ownerCleanups.set(id, retryBag);
|
|
867
|
+
}
|
|
868
|
+
retryBag.add(cleanup);
|
|
869
|
+
}
|
|
870
|
+
logger.warn("Async job owner cleanup failed", {
|
|
871
|
+
ownerId: id,
|
|
872
|
+
error: error instanceof Error ? error.message : String(error),
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (strict && errors.length > 0) throw new AggregateError(errors, "Async job owner cleanup failed");
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
async cancelAndProveOwnerSubagents(
|
|
881
|
+
lease: OwnerSubagentShutdownLease,
|
|
882
|
+
options?: { timeoutMs?: number },
|
|
883
|
+
): Promise<OwnerSubagentShutdownProof> {
|
|
884
|
+
const state = this.#ownerSubagentShutdownLeases.get(lease.ownerId);
|
|
885
|
+
if (!state || state.lease.id !== lease.id) {
|
|
886
|
+
return this.#ownerSubagentShutdownProof(
|
|
887
|
+
lease,
|
|
888
|
+
"lease_lost",
|
|
889
|
+
lease.targets.map(target => target.subagentId),
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
if (state.phase === "proved" && state.proof) return state.proof;
|
|
893
|
+
state.phase = "proving";
|
|
894
|
+
const settled = new Set<string>();
|
|
895
|
+
const promises: Promise<void>[] = [];
|
|
896
|
+
for (const target of lease.targets) {
|
|
897
|
+
const backingJobs = (state.backingJobIds.get(target.subagentId) ?? []).map(jobId => ({
|
|
898
|
+
jobId,
|
|
899
|
+
job: this.#jobs.get(jobId),
|
|
900
|
+
}));
|
|
901
|
+
if (target.source === "record") this.cancelSubagent(target.subagentId, { ownerId: lease.ownerId });
|
|
902
|
+
for (const { jobId, job } of backingJobs) {
|
|
903
|
+
this.cancel(jobId, { ownerId: lease.ownerId });
|
|
904
|
+
if (!job || job.ownerId !== lease.ownerId) continue;
|
|
905
|
+
promises.push(
|
|
906
|
+
job.promise.then(
|
|
907
|
+
() => {
|
|
908
|
+
settled.add(jobId);
|
|
909
|
+
},
|
|
910
|
+
() => {
|
|
911
|
+
settled.add(jobId);
|
|
912
|
+
},
|
|
913
|
+
),
|
|
914
|
+
);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
const timeoutMs = Math.max(0, options?.timeoutMs ?? OWNER_SUBAGENT_SHUTDOWN_TIMEOUT_MS);
|
|
918
|
+
let deadlineExceeded = false;
|
|
919
|
+
await Promise.race([
|
|
920
|
+
Promise.allSettled(promises),
|
|
921
|
+
Bun.sleep(timeoutMs).then(() => {
|
|
922
|
+
deadlineExceeded = true;
|
|
923
|
+
}),
|
|
924
|
+
]);
|
|
925
|
+
const current = this.#ownerSubagentShutdownLeases.get(lease.ownerId);
|
|
926
|
+
if (!current || current.lease.id !== lease.id || current.phase !== "proving") {
|
|
927
|
+
return this.#ownerSubagentShutdownProof(
|
|
928
|
+
lease,
|
|
929
|
+
"lease_lost",
|
|
930
|
+
lease.targets.map(target => target.subagentId),
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
const unresolvedIds = lease.targets
|
|
934
|
+
.filter(target => !this.#hasTerminalShutdownEvidence(target, lease.ownerId, current.backingJobIds, settled))
|
|
935
|
+
.map(target => target.subagentId);
|
|
936
|
+
const reason =
|
|
937
|
+
unresolvedIds.length === 0
|
|
938
|
+
? "confirmed"
|
|
939
|
+
: deadlineExceeded
|
|
940
|
+
? "deadline_exceeded"
|
|
941
|
+
: "missing_terminal_evidence";
|
|
942
|
+
const proof = this.#ownerSubagentShutdownProof(lease, reason, unresolvedIds);
|
|
943
|
+
current.phase = "proved";
|
|
944
|
+
current.proof = proof;
|
|
945
|
+
return proof;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
#hasTerminalShutdownEvidence(
|
|
949
|
+
target: OwnerSubagentShutdownTarget,
|
|
950
|
+
ownerId: string,
|
|
951
|
+
backingJobIds: ReadonlyMap<string, readonly string[]>,
|
|
952
|
+
settled: ReadonlySet<string>,
|
|
953
|
+
): boolean {
|
|
954
|
+
const record = this.#subagentRecords.get(target.subagentId);
|
|
955
|
+
if (!record || record.ownerId !== ownerId || !this.#isTerminalSubagentStatus(record.status)) return false;
|
|
956
|
+
return (backingJobIds.get(target.subagentId) ?? []).every(jobId => {
|
|
957
|
+
if (!settled.has(jobId)) return false;
|
|
958
|
+
const job = this.#jobs.get(jobId);
|
|
959
|
+
return job === undefined || job.ownerId === ownerId;
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
#ownerSubagentShutdownProof(
|
|
964
|
+
lease: OwnerSubagentShutdownLease,
|
|
965
|
+
reason: OwnerSubagentShutdownProof["reason"],
|
|
966
|
+
unresolvedIds: readonly string[],
|
|
967
|
+
): OwnerSubagentShutdownProof {
|
|
968
|
+
const unresolved = new Set(unresolvedIds);
|
|
969
|
+
return {
|
|
970
|
+
ownerId: lease.ownerId,
|
|
971
|
+
leaseId: lease.id,
|
|
972
|
+
confirmed: reason === "confirmed",
|
|
973
|
+
reason,
|
|
974
|
+
targets: lease.targets,
|
|
975
|
+
terminalIds: lease.targets
|
|
976
|
+
.filter(target => !unresolved.has(target.subagentId))
|
|
977
|
+
.map(target => target.subagentId),
|
|
978
|
+
unresolvedIds: [...unresolvedIds],
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
finishOwnerSubagentShutdown(lease: OwnerSubagentShutdownLease, outcome: "commit" | "release"): void {
|
|
983
|
+
const state = this.#ownerSubagentShutdownLeases.get(lease.ownerId);
|
|
984
|
+
if (!state || state.lease.id !== lease.id) return;
|
|
985
|
+
if (outcome === "commit" && state.proof?.confirmed) {
|
|
986
|
+
const pendingJobIds = this.getDeliveryState({ ownerId: lease.ownerId }).pendingJobIds;
|
|
987
|
+
this.acknowledgeDeliveries(pendingJobIds);
|
|
988
|
+
this.#purgeOwnerSubagentState(lease.ownerId);
|
|
989
|
+
}
|
|
990
|
+
this.#ownerSubagentShutdownLeases.delete(lease.ownerId);
|
|
991
|
+
if (outcome === "release") this.#ensureDeliveryLoop();
|
|
992
|
+
}
|
|
993
|
+
|
|
707
994
|
#recordByJobId(jobId: string): SubagentRecord | undefined {
|
|
708
995
|
for (const rec of this.#subagentRecords.values()) {
|
|
709
996
|
if (rec.currentJobId === jobId) return rec;
|
|
@@ -758,6 +1045,9 @@ export class AsyncJobManager {
|
|
|
758
1045
|
): { ok: boolean; status?: SubagentLifecycle; jobId?: string; queued?: boolean; reason?: string } {
|
|
759
1046
|
const rec = this.getSubagentRecord(subagentId, filter);
|
|
760
1047
|
if (!rec) return { ok: false, reason: "not_found" };
|
|
1048
|
+
if (this.#isOwnerSubagentShutdownFenced(rec.ownerId)) {
|
|
1049
|
+
return { ok: false, status: rec.status, reason: "owner_shutdown_in_progress" };
|
|
1050
|
+
}
|
|
761
1051
|
if (rec.status === "running") return { ok: false, status: "running", reason: "already_running" };
|
|
762
1052
|
if (rec.status === "queued") {
|
|
763
1053
|
if (message !== undefined && rec.queued) {
|
|
@@ -769,7 +1059,7 @@ export class AsyncJobManager {
|
|
|
769
1059
|
return { ok: false, status: "queued", reason: "already_queued" };
|
|
770
1060
|
}
|
|
771
1061
|
if (!rec.resumable || !rec.sessionFile) return { ok: false, reason: "context_unavailable" };
|
|
772
|
-
if (!this.#
|
|
1062
|
+
if (!this.#resolveResumeRunner(rec.subagentId)) return { ok: false, reason: "no_runner" };
|
|
773
1063
|
if (this.getRunningJobs().length >= this.#maxRunningJobs) {
|
|
774
1064
|
const seq = ++this.#resumeSeq;
|
|
775
1065
|
rec.status = "queued";
|
|
@@ -790,11 +1080,15 @@ export class AsyncJobManager {
|
|
|
790
1080
|
rec: SubagentRecord,
|
|
791
1081
|
message?: string,
|
|
792
1082
|
): { ok: boolean; status?: SubagentLifecycle; jobId?: string; reason?: string } {
|
|
1083
|
+
if (this.#isOwnerSubagentShutdownFenced(rec.ownerId)) {
|
|
1084
|
+
return { ok: false, status: rec.status, reason: "owner_shutdown_in_progress" };
|
|
1085
|
+
}
|
|
793
1086
|
const prevJobId = rec.currentJobId;
|
|
794
1087
|
// Clear any retained progress from the previous run so a resumed subagent
|
|
795
1088
|
// never renders the prior run's tool/output as live before it emits again.
|
|
796
1089
|
this.#subagentProgress.delete(rec.subagentId);
|
|
797
|
-
const
|
|
1090
|
+
const runner = this.#resolveResumeRunner(rec.subagentId);
|
|
1091
|
+
const newJobId = runner?.(rec.subagentId, message, this.#resumeDescriptors.get(rec.subagentId));
|
|
798
1092
|
if (!newJobId) return { ok: false, reason: "resume_failed" };
|
|
799
1093
|
if (prevJobId && prevJobId !== newJobId) rec.historicalJobIds.push(prevJobId);
|
|
800
1094
|
rec.currentJobId = newJobId;
|
|
@@ -803,16 +1097,36 @@ export class AsyncJobManager {
|
|
|
803
1097
|
return { ok: true, status: rec.status, jobId: newJobId };
|
|
804
1098
|
}
|
|
805
1099
|
|
|
806
|
-
/** Drain queued resumes
|
|
1100
|
+
/** Drain queued resumes while preserving fenced owners and allowing foreign progress. */
|
|
807
1101
|
#drainResumeQueue(): void {
|
|
808
1102
|
if (this.#resumeQueue.length === 0) return;
|
|
809
1103
|
this.#resumeQueue.sort((a, b) => a.seq - b.seq);
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
1104
|
+
let index = 0;
|
|
1105
|
+
while (index < this.#resumeQueue.length && this.getRunningJobs().length < this.#maxRunningJobs) {
|
|
1106
|
+
const entry = this.#resumeQueue[index];
|
|
813
1107
|
const rec = this.#subagentRecords.get(entry.subagentId);
|
|
814
|
-
if (rec?.status !== "queued")
|
|
815
|
-
|
|
1108
|
+
if (rec?.status !== "queued") {
|
|
1109
|
+
this.#resumeQueue.splice(index, 1);
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
if (this.#isOwnerSubagentShutdownFenced(entry.ownerId)) {
|
|
1113
|
+
index += 1;
|
|
1114
|
+
continue;
|
|
1115
|
+
}
|
|
1116
|
+
try {
|
|
1117
|
+
const result = this.#startResume(rec, entry.message);
|
|
1118
|
+
if (result.reason === "owner_shutdown_in_progress") {
|
|
1119
|
+
index += 1;
|
|
1120
|
+
continue;
|
|
1121
|
+
}
|
|
1122
|
+
this.#resumeQueue.splice(index, 1);
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
if (error instanceof OwnerSubagentShutdownError) {
|
|
1125
|
+
index += 1;
|
|
1126
|
+
continue;
|
|
1127
|
+
}
|
|
1128
|
+
throw error;
|
|
1129
|
+
}
|
|
816
1130
|
}
|
|
817
1131
|
}
|
|
818
1132
|
|
|
@@ -854,6 +1168,7 @@ export class AsyncJobManager {
|
|
|
854
1168
|
if (!ownerId || rec.ownerId === ownerId) {
|
|
855
1169
|
this.#liveHandles.delete(sid);
|
|
856
1170
|
this.#resumeDescriptors.delete(sid);
|
|
1171
|
+
this.#descriptorResumeRunners.delete(sid);
|
|
857
1172
|
this.#subagentRecords.delete(sid);
|
|
858
1173
|
this.#subagentProgress.delete(sid);
|
|
859
1174
|
}
|
|
@@ -1011,36 +1326,10 @@ export class AsyncJobManager {
|
|
|
1011
1326
|
};
|
|
1012
1327
|
}
|
|
1013
1328
|
|
|
1014
|
-
/**
|
|
1015
|
-
* Run and clear every registered cleanup for the given filter. Idempotent
|
|
1016
|
-
* and error-isolated: a throwing cleanup does not prevent siblings from
|
|
1017
|
-
* running and never escalates to the caller.
|
|
1018
|
-
*/
|
|
1329
|
+
/** Run producer cleanups, then perform the legacy destructive subagent purge. */
|
|
1019
1330
|
runOwnerCleanups(filter?: AsyncJobFilter): void {
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
if (ownerId) {
|
|
1023
|
-
const bag = this.#ownerCleanups.get(ownerId);
|
|
1024
|
-
if (bag) targets.push([ownerId, bag]);
|
|
1025
|
-
} else {
|
|
1026
|
-
for (const entry of this.#ownerCleanups.entries()) targets.push(entry);
|
|
1027
|
-
}
|
|
1028
|
-
for (const [id, bag] of targets) {
|
|
1029
|
-
const callbacks = Array.from(bag);
|
|
1030
|
-
bag.clear();
|
|
1031
|
-
this.#ownerCleanups.delete(id);
|
|
1032
|
-
for (const cleanup of callbacks) {
|
|
1033
|
-
try {
|
|
1034
|
-
cleanup();
|
|
1035
|
-
} catch (error) {
|
|
1036
|
-
logger.warn("Async job owner cleanup failed", {
|
|
1037
|
-
ownerId: id,
|
|
1038
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
this.#purgeOwnerSubagentState(ownerId);
|
|
1331
|
+
this.runOwnerProducerCleanups(filter);
|
|
1332
|
+
this.#purgeOwnerSubagentState(filter?.ownerId);
|
|
1044
1333
|
}
|
|
1045
1334
|
|
|
1046
1335
|
getDeliveryState(filter?: AsyncJobFilter): AsyncJobDeliveryState {
|
|
@@ -1084,6 +1373,7 @@ export class AsyncJobManager {
|
|
|
1084
1373
|
removed += 1;
|
|
1085
1374
|
}
|
|
1086
1375
|
}
|
|
1376
|
+
if (removed > 0) this.#ensureDeliveryLoop();
|
|
1087
1377
|
return removed;
|
|
1088
1378
|
}
|
|
1089
1379
|
|
|
@@ -1099,7 +1389,7 @@ export class AsyncJobManager {
|
|
|
1099
1389
|
this.#deliveries.splice(
|
|
1100
1390
|
0,
|
|
1101
1391
|
this.#deliveries.length,
|
|
1102
|
-
...this.#deliveries.filter(delivery => !this
|
|
1392
|
+
...this.#deliveries.filter(delivery => !this.#isDeliveryAcknowledged(delivery.jobId)),
|
|
1103
1393
|
);
|
|
1104
1394
|
return before - this.#deliveries.length;
|
|
1105
1395
|
}
|
|
@@ -1119,6 +1409,48 @@ export class AsyncJobManager {
|
|
|
1119
1409
|
}
|
|
1120
1410
|
}
|
|
1121
1411
|
|
|
1412
|
+
async waitForOwnerInFlightDeliveries(ownerId: string, options?: { timeoutMs?: number }): Promise<boolean> {
|
|
1413
|
+
const inFlight = this.#inFlightDeliveries
|
|
1414
|
+
.filter(delivery => delivery.ownerId === ownerId)
|
|
1415
|
+
.map(delivery => delivery.promise)
|
|
1416
|
+
.filter((promise): promise is Promise<void> => promise !== undefined);
|
|
1417
|
+
if (inFlight.length === 0) return true;
|
|
1418
|
+
const timeoutMs = Math.max(0, options?.timeoutMs ?? OWNER_SUBAGENT_SHUTDOWN_TIMEOUT_MS);
|
|
1419
|
+
let timedOut = false;
|
|
1420
|
+
await Promise.race([
|
|
1421
|
+
Promise.allSettled(inFlight),
|
|
1422
|
+
Bun.sleep(timeoutMs).then(() => {
|
|
1423
|
+
timedOut = true;
|
|
1424
|
+
}),
|
|
1425
|
+
]);
|
|
1426
|
+
return !timedOut;
|
|
1427
|
+
}
|
|
1428
|
+
async cancelAndSettleOwnerJobs(ownerId: string, options?: { timeoutMs?: number }): Promise<boolean> {
|
|
1429
|
+
const jobs = this.getAllJobs({ ownerId });
|
|
1430
|
+
for (const job of jobs) this.cancel(job.id, { ownerId });
|
|
1431
|
+
const timeoutMs = Math.max(0, options?.timeoutMs ?? OWNER_SUBAGENT_SHUTDOWN_TIMEOUT_MS);
|
|
1432
|
+
let timedOut = false;
|
|
1433
|
+
await Promise.race([
|
|
1434
|
+
Promise.allSettled(jobs.map(job => job.promise)),
|
|
1435
|
+
Bun.sleep(timeoutMs).then(() => {
|
|
1436
|
+
timedOut = true;
|
|
1437
|
+
}),
|
|
1438
|
+
]);
|
|
1439
|
+
const inFlight = this.#inFlightDeliveries
|
|
1440
|
+
.filter(delivery => delivery.ownerId === ownerId)
|
|
1441
|
+
.map(delivery => delivery.promise)
|
|
1442
|
+
.filter((promise): promise is Promise<void> => promise !== undefined);
|
|
1443
|
+
if (inFlight.length === 0) return !timedOut;
|
|
1444
|
+
let deliveryTimedOut = false;
|
|
1445
|
+
await Promise.race([
|
|
1446
|
+
Promise.allSettled(inFlight),
|
|
1447
|
+
Bun.sleep(timeoutMs).then(() => {
|
|
1448
|
+
deliveryTimedOut = true;
|
|
1449
|
+
}),
|
|
1450
|
+
]);
|
|
1451
|
+
return !timedOut && !deliveryTimedOut;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1122
1454
|
getLastDisposeDiagnostics(): AsyncJobDisposeDiagnostics {
|
|
1123
1455
|
return { ...this.#lastDisposeDiagnostics, stuckJobIds: [...this.#lastDisposeDiagnostics.stuckJobIds] };
|
|
1124
1456
|
}
|
|
@@ -1229,7 +1561,9 @@ export class AsyncJobManager {
|
|
|
1229
1561
|
this.#liveHandles.clear();
|
|
1230
1562
|
this.#subagentProgress.clear();
|
|
1231
1563
|
this.#resumeDescriptors.clear();
|
|
1564
|
+
this.#descriptorResumeRunners.clear();
|
|
1232
1565
|
this.#resumeQueue.length = 0;
|
|
1566
|
+
this.#ownerSubagentShutdownLeases.clear();
|
|
1233
1567
|
this.#notifyChange();
|
|
1234
1568
|
this.#changeListeners.clear();
|
|
1235
1569
|
return drained && waitResult.completed;
|
|
@@ -1315,12 +1649,22 @@ export class AsyncJobManager {
|
|
|
1315
1649
|
);
|
|
1316
1650
|
}
|
|
1317
1651
|
|
|
1652
|
+
#isDeliveryFenced(delivery: AsyncJobDelivery): boolean {
|
|
1653
|
+
return Boolean(delivery.ownerId && this.#isOwnerSubagentShutdownFenced(delivery.ownerId));
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
#hasDeliverable(): boolean {
|
|
1657
|
+
return this.#deliveries.some(
|
|
1658
|
+
delivery => !this.isDeliverySuppressed(delivery.jobId) && !this.#isDeliveryFenced(delivery),
|
|
1659
|
+
);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1318
1662
|
async #deliverNextFiltered(filter: AsyncJobFilter, deadline: number): Promise<boolean> {
|
|
1319
1663
|
while (true) {
|
|
1320
1664
|
let selected: AsyncJobDelivery | undefined;
|
|
1321
1665
|
for (const delivery of this.#deliveries) {
|
|
1322
1666
|
if (delivery.ownerId !== filter.ownerId) continue;
|
|
1323
|
-
if (this.isDeliverySuppressed(delivery.jobId)) continue;
|
|
1667
|
+
if (this.isDeliverySuppressed(delivery.jobId) || this.#isDeliveryFenced(delivery)) continue;
|
|
1324
1668
|
if (!selected || delivery.nextAttemptAt < selected.nextAttemptAt) {
|
|
1325
1669
|
selected = delivery;
|
|
1326
1670
|
}
|
|
@@ -1328,7 +1672,7 @@ export class AsyncJobManager {
|
|
|
1328
1672
|
|
|
1329
1673
|
if (!selected) {
|
|
1330
1674
|
const inFlight = this.#filterInFlightDeliveries(filter);
|
|
1331
|
-
if (inFlight.length === 0) return
|
|
1675
|
+
if (inFlight.length === 0) return this.#filterDeliveries(filter).length === 0;
|
|
1332
1676
|
return this.#waitForDeliveryPromise(inFlight[0]?.promise, deadline);
|
|
1333
1677
|
}
|
|
1334
1678
|
|
|
@@ -1348,13 +1692,17 @@ export class AsyncJobManager {
|
|
|
1348
1692
|
}
|
|
1349
1693
|
}
|
|
1350
1694
|
|
|
1695
|
+
#isDeliveryAcknowledged(jobId: string): boolean {
|
|
1696
|
+
return this.#suppressedDeliveries.has(jobId);
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1351
1699
|
isDeliverySuppressed(jobId: string): boolean {
|
|
1352
|
-
return this.#
|
|
1700
|
+
return this.#isDeliveryAcknowledged(jobId) || this.#watchedJobs.has(jobId);
|
|
1353
1701
|
}
|
|
1354
1702
|
|
|
1355
1703
|
#enqueueDelivery(jobId: string, text: string): void {
|
|
1356
1704
|
// Skip delivery if already acknowledged
|
|
1357
|
-
if (this
|
|
1705
|
+
if (this.#isDeliveryAcknowledged(jobId)) {
|
|
1358
1706
|
return;
|
|
1359
1707
|
}
|
|
1360
1708
|
const deliveryText = this.#boundedDeliveryText(text);
|
|
@@ -1399,7 +1747,7 @@ export class AsyncJobManager {
|
|
|
1399
1747
|
})
|
|
1400
1748
|
.finally(() => {
|
|
1401
1749
|
this.#deliveryLoop = undefined;
|
|
1402
|
-
if (!this.#disposed && this.#
|
|
1750
|
+
if (!this.#disposed && this.#hasDeliverable()) {
|
|
1403
1751
|
this.#ensureDeliveryLoop();
|
|
1404
1752
|
}
|
|
1405
1753
|
});
|
|
@@ -1407,24 +1755,19 @@ export class AsyncJobManager {
|
|
|
1407
1755
|
|
|
1408
1756
|
async #runDeliveryLoop(): Promise<void> {
|
|
1409
1757
|
while (this.#deliveries.length > 0) {
|
|
1410
|
-
const delivery = this.#deliveries
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
}
|
|
1758
|
+
const delivery = this.#deliveries.find(
|
|
1759
|
+
candidate => !this.isDeliverySuppressed(candidate.jobId) && !this.#isDeliveryFenced(candidate),
|
|
1760
|
+
);
|
|
1761
|
+
if (!delivery) return;
|
|
1415
1762
|
const waitMs = delivery.nextAttemptAt - Date.now();
|
|
1416
1763
|
if (waitMs > 0) {
|
|
1417
1764
|
await Bun.sleep(waitMs);
|
|
1418
1765
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
if (this.isDeliverySuppressed(delivery.jobId)) {
|
|
1423
|
-
this.#deliveries.shift();
|
|
1424
|
-
continue;
|
|
1425
|
-
}
|
|
1766
|
+
const index = this.#deliveries.indexOf(delivery);
|
|
1767
|
+
if (index === -1) continue;
|
|
1768
|
+
if (this.isDeliverySuppressed(delivery.jobId) || this.#isDeliveryFenced(delivery)) continue;
|
|
1426
1769
|
|
|
1427
|
-
this.#deliveries.
|
|
1770
|
+
this.#deliveries.splice(index, 1);
|
|
1428
1771
|
await this.#deliverDelivery(delivery);
|
|
1429
1772
|
}
|
|
1430
1773
|
}
|
|
@@ -1446,7 +1789,7 @@ export class AsyncJobManager {
|
|
|
1446
1789
|
});
|
|
1447
1790
|
} else {
|
|
1448
1791
|
delivery.nextAttemptAt = Date.now() + this.#getRetryDelay(delivery.attempt);
|
|
1449
|
-
if (!this
|
|
1792
|
+
if (!this.#isDeliveryAcknowledged(delivery.jobId)) {
|
|
1450
1793
|
this.#deliveries.push(delivery);
|
|
1451
1794
|
}
|
|
1452
1795
|
logger.warn("Async job completion delivery failed", {
|
|
@@ -1459,7 +1802,7 @@ export class AsyncJobManager {
|
|
|
1459
1802
|
} finally {
|
|
1460
1803
|
const index = this.#inFlightDeliveries.indexOf(delivery);
|
|
1461
1804
|
if (index !== -1) this.#inFlightDeliveries.splice(index, 1);
|
|
1462
|
-
if (!this.#disposed && this.#
|
|
1805
|
+
if (!this.#disposed && this.#hasDeliverable()) this.#ensureDeliveryLoop();
|
|
1463
1806
|
}
|
|
1464
1807
|
})();
|
|
1465
1808
|
delivery.promise = promise;
|