@bastani/atomic 0.9.19-alpha.1 → 0.9.19-alpha.11
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 +206 -0
- package/README.md +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +51 -0
- package/dist/builtin/intercom/README.md +28 -18
- package/dist/builtin/intercom/broker/broker.ts +81 -9
- package/dist/builtin/intercom/broker/client.ts +45 -1
- package/dist/builtin/intercom/broker/framing.ts +5 -2
- package/dist/builtin/intercom/broker/group-membership.ts +4 -2
- package/dist/builtin/intercom/broker/presence-handler.ts +14 -0
- package/dist/builtin/intercom/broker/send-handler.ts +61 -6
- package/dist/builtin/intercom/broker/terminal-questions.ts +29 -0
- package/dist/builtin/intercom/index.bundle.mjs +1120 -783
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/intercom/recipient-purpose.ts +9 -0
- package/dist/builtin/intercom/recoverable-disconnect.ts +2 -3
- package/dist/builtin/intercom/retry-policy.ts +4 -2
- package/dist/builtin/intercom/skills/intercom/SKILL.md +8 -7
- package/dist/builtin/intercom/types.ts +18 -3
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/README.md +2 -0
- package/dist/builtin/mcp/index.bundle.mjs +2201 -12000
- package/dist/builtin/mcp/package.json +2 -2
- package/dist/builtin/subagents/CHANGELOG.md +57 -0
- package/dist/builtin/subagents/README.md +46 -23
- package/dist/builtin/subagents/agents/code-simplifier.md +1 -1
- package/dist/builtin/subagents/agents/codebase-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
- package/dist/builtin/subagents/agents/codebase-online-researcher.md +8 -8
- package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
- package/dist/builtin/subagents/agents/codebase-research-analyzer.md +1 -1
- package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
- package/dist/builtin/subagents/agents/debugger.md +2 -2
- package/dist/builtin/subagents/agents/worker.md +1 -1
- package/dist/builtin/subagents/package.json +2 -2
- package/dist/builtin/subagents/skills/herdr/LICENSE +201 -0
- package/dist/builtin/subagents/skills/herdr/SKILL.md +202 -0
- package/dist/builtin/subagents/skills/subagent/SKILL.md +41 -35
- package/dist/builtin/subagents/skills/tmux/SKILL.md +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +1414 -656
- package/dist/builtin/web-access/CHANGELOG.md +19 -0
- package/dist/builtin/web-access/README.md +31 -24
- package/dist/builtin/web-access/index.bundle.mjs +42723 -26674
- package/dist/builtin/web-access/package.json +3 -2
- package/dist/builtin/workflows/CHANGELOG.md +127 -0
- package/dist/builtin/workflows/README.md +15 -16
- package/dist/builtin/workflows/builtin/adversarial-verification.js +5 -7
- package/dist/builtin/workflows/builtin/{chunk-hqpe2cyx.js → chunk-1jth021m.js} +85 -85
- package/dist/builtin/workflows/builtin/{chunk-7430zyas.js → chunk-2377r57g.js} +5 -3
- package/dist/builtin/workflows/builtin/{chunk-79fjkcvh.js → chunk-31j2gs7h.js} +18 -18
- package/dist/builtin/workflows/builtin/{chunk-wgccch41.js → chunk-6w6cvk6b.js} +16 -16
- package/dist/builtin/workflows/builtin/{chunk-zbekjqew.js → chunk-a2kdsqn8.js} +4 -4
- package/dist/builtin/workflows/builtin/{chunk-ze5x3d1r.js → chunk-fg9esgkj.js} +7 -7
- package/dist/builtin/workflows/builtin/{chunk-n8h4yyew.js → chunk-g0csgs7w.js} +11 -11
- package/dist/builtin/workflows/builtin/{chunk-b0v2xab1.js → chunk-ngkqkzej.js} +221 -23
- package/dist/builtin/workflows/builtin/{chunk-ed4jfn5t.js → chunk-nkrafh9s.js} +61 -61
- package/dist/builtin/workflows/builtin/{chunk-reqr3sr3.js → chunk-wf741bv3.js} +22 -22
- package/dist/builtin/workflows/builtin/{chunk-42s7sw0b.js → chunk-yeee2jrc.js} +19 -19
- package/dist/builtin/workflows/builtin/{chunk-6fqs7c01.js → chunk-z0d03ktm.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-k3w87x8y.js → chunk-z29qbehr.js} +10 -10
- package/dist/builtin/workflows/builtin/classify-and-act.js +5 -6
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +3 -4
- package/dist/builtin/workflows/builtin/generate-and-filter.js +5 -6
- package/dist/builtin/workflows/builtin/goal.js +7 -8
- package/dist/builtin/workflows/builtin/index.js +20 -22
- package/dist/builtin/workflows/builtin/loop-until-done.js +5 -6
- package/dist/builtin/workflows/builtin/open-claude-design.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +7 -8
- package/dist/builtin/workflows/builtin/steering-context.js +3 -3
- package/dist/builtin/workflows/builtin/tournament.js +5 -7
- package/dist/builtin/workflows/package.json +6 -6
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +27782 -26348
- package/dist/builtin/workflows/src/index.js +1103 -515
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +4 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +6 -5
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +5 -1
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts +1 -1
- package/dist/core/agent-session-compaction.js +1 -1
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-custom-message-commit.d.ts +1 -1
- package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
- package/dist/core/agent-session-custom-message-commit.js +33 -2
- package/dist/core/agent-session-custom-message-commit.js.map +1 -1
- package/dist/core/agent-session-delivery-forwarding.d.ts +1 -1
- package/dist/core/agent-session-delivery-forwarding.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +5 -0
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-export.d.ts +1 -1
- package/dist/core/agent-session-export.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +8 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +45 -3
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-message-queue.d.ts +2 -2
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +22 -8
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +21 -8
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.d.ts +1 -1
- package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.js +13 -3
- package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
- package/dist/core/agent-session-post-tool-compaction.js +1 -1
- package/dist/core/agent-session-post-tool-compaction.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts +2 -2
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +105 -18
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-queue-pause.d.ts.map +1 -1
- package/dist/core/agent-session-queue-pause.js +11 -0
- package/dist/core/agent-session-queue-pause.js.map +1 -1
- package/dist/core/agent-session-runtime-auth.d.ts +1 -1
- package/dist/core/agent-session-runtime-auth.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +13 -4
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +27 -4
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +5 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +44 -34
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-state.d.ts +1 -1
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tasks.d.ts +14 -0
- package/dist/core/agent-session-tasks.d.ts.map +1 -0
- package/dist/core/agent-session-tasks.js +120 -0
- package/dist/core/agent-session-tasks.js.map +1 -0
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +2 -0
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts +1 -0
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +52 -5
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-transfer.d.ts.map +1 -1
- package/dist/core/agent-session-transfer.js +7 -0
- package/dist/core/agent-session-transfer.js.map +1 -1
- package/dist/core/agent-session-tree.d.ts.map +1 -1
- package/dist/core/agent-session-tree.js +3 -0
- package/dist/core/agent-session-tree.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +4 -2
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js +2 -0
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +8 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +29 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extension-session-state.js.map +1 -1
- package/dist/core/extensions/agent-events.d.ts +4 -4
- package/dist/core/extensions/agent-events.d.ts.map +1 -1
- package/dist/core/extensions/agent-events.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +10 -2
- package/dist/core/extensions/api-types.d.ts.map +1 -1
- package/dist/core/extensions/api-types.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +15 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/event-results.d.ts +1 -1
- package/dist/core/extensions/event-results.js.map +1 -1
- package/dist/core/extensions/event-types.d.ts +2 -1
- package/dist/core/extensions/event-types.d.ts.map +1 -1
- package/dist/core/extensions/event-types.js.map +1 -1
- package/dist/core/extensions/index.d.ts +3 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader-api.d.ts +1 -1
- package/dist/core/extensions/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js +10 -0
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/loader-core.d.ts +1 -1
- package/dist/core/extensions/loader-core.js.map +1 -1
- package/dist/core/extensions/loader-discovery.d.ts +1 -1
- package/dist/core/extensions/loader-discovery.js.map +1 -1
- package/dist/core/extensions/loader-host-modules.d.ts +1 -1
- package/dist/core/extensions/loader-host-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-host-modules.js +5 -2
- package/dist/core/extensions/loader-host-modules.js.map +1 -1
- package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
- package/dist/core/extensions/loader-runtime.js +3 -0
- package/dist/core/extensions/loader-runtime.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +6 -1
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/message-types.d.ts +1 -1
- package/dist/core/extensions/message-types.js.map +1 -1
- package/dist/core/extensions/reactive-widget.d.ts +6 -0
- package/dist/core/extensions/reactive-widget.d.ts.map +1 -1
- package/dist/core/extensions/reactive-widget.js +7 -1
- package/dist/core/extensions/reactive-widget.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +12 -2
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +49 -4
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner-events.d.ts +1 -1
- package/dist/core/extensions/runner-events.d.ts.map +1 -1
- package/dist/core/extensions/runner-events.js +17 -2
- package/dist/core/extensions/runner-events.js.map +1 -1
- package/dist/core/extensions/runner-shortcuts.d.ts.map +1 -1
- package/dist/core/extensions/runner-shortcuts.js +32 -3
- package/dist/core/extensions/runner-shortcuts.js.map +1 -1
- package/dist/core/extensions/runner-ui.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +17 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +69 -19
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +8 -1
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/tool-types.d.ts +1 -1
- package/dist/core/extensions/tool-types.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/ui-types.d.ts +25 -1
- package/dist/core/extensions/ui-types.d.ts.map +1 -1
- package/dist/core/extensions/ui-types.js.map +1 -1
- package/dist/core/extensions/workflow-activity-hub.d.ts +25 -0
- package/dist/core/extensions/workflow-activity-hub.d.ts.map +1 -0
- package/dist/core/extensions/workflow-activity-hub.js +183 -0
- package/dist/core/extensions/workflow-activity-hub.js.map +1 -0
- package/dist/core/extensions/workflow-events.d.ts +118 -0
- package/dist/core/extensions/workflow-events.d.ts.map +1 -0
- package/dist/core/extensions/workflow-events.js +2 -0
- package/dist/core/extensions/workflow-events.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +8 -4
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +97 -11
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybinding-identity.d.ts +4 -0
- package/dist/core/keybinding-identity.d.ts.map +1 -0
- package/dist/core/keybinding-identity.js +10 -0
- package/dist/core/keybinding-identity.js.map +1 -0
- package/dist/core/keybindings.d.ts +37 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +9 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/mandatory-runtime-tools.d.ts +1 -1
- package/dist/core/mandatory-runtime-tools.js.map +1 -1
- package/dist/core/model-fallback-failures.js +2 -2
- package/dist/core/model-fallback-failures.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/resource-loader-assets.js.map +1 -1
- package/dist/core/resource-loader-core.d.ts +1 -1
- package/dist/core/resource-loader-core.js.map +1 -1
- package/dist/core/resource-loader-internals.d.ts +2 -2
- package/dist/core/resource-loader-internals.js.map +1 -1
- package/dist/core/resource-loader-reload.d.ts +2 -0
- package/dist/core/resource-loader-reload.d.ts.map +1 -1
- package/dist/core/resource-loader-reload.js +231 -191
- package/dist/core/resource-loader-reload.js.map +1 -1
- package/dist/core/resource-loader-types.d.ts +4 -2
- package/dist/core/resource-loader-types.d.ts.map +1 -1
- package/dist/core/resource-loader-types.js.map +1 -1
- package/dist/core/retry-policy.d.ts +1 -0
- package/dist/core/retry-policy.d.ts.map +1 -1
- package/dist/core/retry-policy.js +2 -1
- package/dist/core/retry-policy.js.map +1 -1
- package/dist/core/sdk-exports.d.ts +3 -3
- package/dist/core/sdk-exports.d.ts.map +1 -1
- package/dist/core/sdk-exports.js +1 -1
- package/dist/core/sdk-exports.js.map +1 -1
- package/dist/core/sdk-types.d.ts +2 -2
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +6 -3
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +25 -8
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-manager-core.d.ts.map +1 -1
- package/dist/core/settings-manager-core.js +10 -4
- package/dist/core/settings-manager-core.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-storage.d.ts +1 -0
- package/dist/core/settings-storage.d.ts.map +1 -1
- package/dist/core/settings-storage.js +18 -0
- package/dist/core/settings-storage.js.map +1 -1
- package/dist/core/settings-types.d.ts +17 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +6 -5
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +5 -6
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/agent-adapter.d.ts +44 -0
- package/dist/core/tasks/agent-adapter.d.ts.map +1 -0
- package/dist/core/tasks/agent-adapter.js +112 -0
- package/dist/core/tasks/agent-adapter.js.map +1 -0
- package/dist/core/tasks/command-output.d.ts +15 -0
- package/dist/core/tasks/command-output.d.ts.map +1 -0
- package/dist/core/tasks/command-output.js +29 -0
- package/dist/core/tasks/command-output.js.map +1 -0
- package/dist/core/tasks/completion-ordering.d.ts +11 -0
- package/dist/core/tasks/completion-ordering.d.ts.map +1 -0
- package/dist/core/tasks/completion-ordering.js +19 -0
- package/dist/core/tasks/completion-ordering.js.map +1 -0
- package/dist/core/tasks/completion.d.ts +36 -0
- package/dist/core/tasks/completion.d.ts.map +1 -0
- package/dist/core/tasks/completion.js +119 -0
- package/dist/core/tasks/completion.js.map +1 -0
- package/dist/core/tasks/contracts.d.ts +404 -0
- package/dist/core/tasks/contracts.d.ts.map +1 -0
- package/dist/core/tasks/contracts.js +2 -0
- package/dist/core/tasks/contracts.js.map +1 -0
- package/dist/core/tasks/execution-scope.d.ts +10 -0
- package/dist/core/tasks/execution-scope.d.ts.map +1 -0
- package/dist/core/tasks/execution-scope.js +27 -0
- package/dist/core/tasks/execution-scope.js.map +1 -0
- package/dist/core/tasks/owner-store.d.ts +53 -0
- package/dist/core/tasks/owner-store.d.ts.map +1 -0
- package/dist/core/tasks/owner-store.js +155 -0
- package/dist/core/tasks/owner-store.js.map +1 -0
- package/dist/core/tasks/pause.d.ts +4 -0
- package/dist/core/tasks/pause.d.ts.map +1 -0
- package/dist/core/tasks/pause.js +49 -0
- package/dist/core/tasks/pause.js.map +1 -0
- package/dist/core/tasks/supervisor.d.ts +123 -0
- package/dist/core/tasks/supervisor.d.ts.map +1 -0
- package/dist/core/tasks/supervisor.js +942 -0
- package/dist/core/tasks/supervisor.js.map +1 -0
- package/dist/core/tasks/transcript.d.ts +23 -0
- package/dist/core/tasks/transcript.d.ts.map +1 -0
- package/dist/core/tasks/transcript.js +74 -0
- package/dist/core/tasks/transcript.js.map +1 -0
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts +2 -2
- package/dist/core/tools/ask-user-question/ask-user-question.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/ask-user-question.js +8 -4
- package/dist/core/tools/ask-user-question/ask-user-question.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/build-questionnaire.d.ts +1 -1
- package/dist/core/tools/ask-user-question/state/build-questionnaire.js.map +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts +1 -1
- package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/components/multi-select-view.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/components/preview/markdown-content-cache.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/components/preview/preview-block-renderer.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/submit-picker.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/components/submit-picker.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/components/tab-bar.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/components/tab-bar.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/dialog-builder.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/dialog-builder.js.map +1 -1
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.d.ts +1 -1
- package/dist/core/tools/ask-user-question/view/tab-content-strategy.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts +32 -3
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +198 -1
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts +25 -5
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +100 -10
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +3 -0
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +92 -14
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-coordinator.d.ts +255 -0
- package/dist/core/tools/file-mutation-coordinator.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-coordinator.js +300 -0
- package/dist/core/tools/file-mutation-coordinator.js.map +1 -0
- package/dist/core/tools/file-mutation-queue.d.ts +14 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +15 -3
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/hashline.d.ts +9 -0
- package/dist/core/tools/hashline.d.ts.map +1 -1
- package/dist/core/tools/hashline.js +12 -1
- package/dist/core/tools/hashline.js.map +1 -1
- package/dist/core/tools/index.d.ts +15 -4
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +79 -12
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/kill.d.ts +17 -0
- package/dist/core/tools/kill.d.ts.map +1 -0
- package/dist/core/tools/kill.js +49 -0
- package/dist/core/tools/kill.js.map +1 -0
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/non-minting-snapshot-store.d.ts +49 -0
- package/dist/core/tools/non-minting-snapshot-store.d.ts.map +1 -0
- package/dist/core/tools/non-minting-snapshot-store.js +64 -0
- package/dist/core/tools/non-minting-snapshot-store.js.map +1 -0
- package/dist/core/tools/powershell.d.ts +100 -34
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/core/tools/powershell.js +41 -11
- package/dist/core/tools/powershell.js.map +1 -1
- package/dist/core/tools/read-document-extract.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/resource-selectors.d.ts +1 -1
- package/dist/core/tools/resource-selectors.d.ts.map +1 -1
- package/dist/core/tools/resource-selectors.js +21 -10
- package/dist/core/tools/resource-selectors.js.map +1 -1
- package/dist/core/tools/search.js.map +1 -1
- package/dist/core/tools/todos-render.d.ts +1 -1
- package/dist/core/tools/todos-render.js.map +1 -1
- package/dist/core/tools/write.d.ts +30 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +98 -10
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/workflow-stage-admission.d.ts +24 -0
- package/dist/core/workflow-stage-admission.d.ts.map +1 -1
- package/dist/core/workflow-stage-admission.js +87 -3
- package/dist/core/workflow-stage-admission.js.map +1 -1
- package/dist/extensions/herdr/activity.d.ts +15 -0
- package/dist/extensions/herdr/activity.d.ts.map +1 -0
- package/dist/extensions/herdr/activity.js +24 -0
- package/dist/extensions/herdr/activity.js.map +1 -0
- package/dist/extensions/herdr/environment.d.ts +7 -0
- package/dist/extensions/herdr/environment.d.ts.map +1 -0
- package/dist/extensions/herdr/environment.js +6 -0
- package/dist/extensions/herdr/environment.js.map +1 -0
- package/dist/extensions/herdr/index.d.ts +9 -0
- package/dist/extensions/herdr/index.d.ts.map +1 -0
- package/dist/extensions/herdr/index.js +225 -0
- package/dist/extensions/herdr/index.js.map +1 -0
- package/dist/extensions/herdr/pane-owner.d.ts +30 -0
- package/dist/extensions/herdr/pane-owner.d.ts.map +1 -0
- package/dist/extensions/herdr/pane-owner.js +111 -0
- package/dist/extensions/herdr/pane-owner.js.map +1 -0
- package/dist/extensions/herdr/transport.d.ts +8 -0
- package/dist/extensions/herdr/transport.d.ts.map +1 -0
- package/dist/extensions/herdr/transport.js +28 -0
- package/dist/extensions/herdr/transport.js.map +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +2 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/llama/huggingface-ui.d.ts +1 -1
- package/dist/extensions/llama/huggingface-ui.js.map +1 -1
- package/dist/extensions/llama/ui.js.map +1 -1
- package/dist/index-extensions.d.ts +3 -2
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +14 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +149 -69
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/atomic-banner.d.ts +1 -1
- package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
- package/dist/modes/interactive/components/atomic-working-status.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.d.ts +12 -0
- package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-message-renderer.js +44 -0
- package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.d.ts +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.js +43 -8
- package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-editor.d.ts +1 -1
- package/dist/modes/interactive/components/chat-session-host-editor.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts +2 -2
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts +2 -2
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js +12 -3
- package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +4 -5
- package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-runtime.js +8 -6
- package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.d.ts +7 -2
- package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.js +1 -0
- package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.d.ts +1 -1
- package/dist/modes/interactive/components/chat-session-host-terminal-cleanup.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-types.d.ts +8 -3
- package/dist/modes/interactive/components/chat-session-host-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-types.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.d.ts +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-utils.js +2 -0
- package/dist/modes/interactive/components/chat-session-host-utils.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts +17 -2
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +100 -3
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/chat-transcript.d.ts +1 -0
- package/dist/modes/interactive/components/chat-transcript.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-transcript.js +1 -1
- package/dist/modes/interactive/components/chat-transcript.js.map +1 -1
- package/dist/modes/interactive/components/compaction-boundary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +12 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +7 -6
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +27 -9
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/host-input-form-mount.js.map +1 -1
- package/dist/modes/interactive/components/host-input-form.d.ts +1 -1
- package/dist/modes/interactive/components/host-input-form.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +2 -2
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts +1 -1
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/reserved-bottom-overlay.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/scroll-widget.d.ts +23 -0
- package/dist/modes/interactive/components/scroll-widget.d.ts.map +1 -0
- package/dist/modes/interactive/components/scroll-widget.js +61 -0
- package/dist/modes/interactive/components/scroll-widget.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-header.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-submenus.d.ts +1 -1
- package/dist/modes/interactive/components/settings-selector-submenus.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/task-completion-message.d.ts +13 -0
- package/dist/modes/interactive/components/task-completion-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-completion-message.js +65 -0
- package/dist/modes/interactive/components/task-completion-message.js.map +1 -0
- package/dist/modes/interactive/components/task-detail.d.ts +27 -0
- package/dist/modes/interactive/components/task-detail.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-detail.js +107 -0
- package/dist/modes/interactive/components/task-detail.js.map +1 -0
- package/dist/modes/interactive/components/task-inspector.d.ts +50 -0
- package/dist/modes/interactive/components/task-inspector.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-inspector.js +599 -0
- package/dist/modes/interactive/components/task-inspector.js.map +1 -0
- package/dist/modes/interactive/components/task-list.d.ts +18 -0
- package/dist/modes/interactive/components/task-list.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-list.js +59 -0
- package/dist/modes/interactive/components/task-list.js.map +1 -0
- package/dist/modes/interactive/components/task-live-transcript.d.ts +17 -0
- package/dist/modes/interactive/components/task-live-transcript.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-live-transcript.js +41 -0
- package/dist/modes/interactive/components/task-live-transcript.js.map +1 -0
- package/dist/modes/interactive/components/task-navigation.d.ts +38 -0
- package/dist/modes/interactive/components/task-navigation.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-navigation.js +93 -0
- package/dist/modes/interactive/components/task-navigation.js.map +1 -0
- package/dist/modes/interactive/components/task-row.d.ts +34 -0
- package/dist/modes/interactive/components/task-row.d.ts.map +1 -0
- package/dist/modes/interactive/components/task-row.js +165 -0
- package/dist/modes/interactive/components/task-row.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/transcript-follow-indicator.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-component.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-help.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-label-input.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector-list.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/working-status.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +8 -2
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.js +3 -1
- package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +9 -30
- package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +2 -1
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-context.js +14 -4
- package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-custom-ui.js +52 -4
- package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-runtime.js +11 -3
- package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-widgets.js +9 -1
- package/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +19 -0
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +7 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +10 -4
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +6 -6
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +3 -2
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +3 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js +4 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +30 -4
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +33 -23
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +1 -0
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +3 -0
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-summarization-retry-events.js +2 -2
- package/dist/modes/interactive/interactive-summarization-retry-events.js.map +1 -1
- package/dist/modes/interactive/interactive-task-projection.d.ts +13 -0
- package/dist/modes/interactive/interactive-task-projection.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-task-projection.js +72 -0
- package/dist/modes/interactive/interactive-task-projection.js.map +1 -0
- package/dist/modes/interactive/interactive-tui.js.map +1 -1
- package/dist/modes/interactive/interactive-windows-subshell.d.ts +17 -0
- package/dist/modes/interactive/interactive-windows-subshell.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-windows-subshell.js +92 -0
- package/dist/modes/interactive/interactive-windows-subshell.js.map +1 -0
- package/dist/modes/interactive/skill-command-autocomplete.d.ts +12 -0
- package/dist/modes/interactive/skill-command-autocomplete.d.ts.map +1 -0
- package/dist/modes/interactive/skill-command-autocomplete.js +69 -0
- package/dist/modes/interactive/skill-command-autocomplete.js.map +1 -0
- package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-class.js +4 -1
- package/dist/modes/interactive/theme/theme-class.js.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive-engine/activity-watchdog.d.ts +2 -2
- package/dist/modes/interactive-engine/activity-watchdog.d.ts.map +1 -1
- package/dist/modes/interactive-engine/activity-watchdog.js.map +1 -1
- package/dist/modes/interactive-engine/create-isolated-runtime.d.ts +1 -1
- package/dist/modes/interactive-engine/create-isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts +9 -10
- package/dist/modes/interactive-engine/engine-custom-ui.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-custom-ui.js +29 -12
- package/dist/modes/interactive-engine/engine-custom-ui.js.map +1 -1
- package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts +3 -1
- package/dist/modes/interactive-engine/engine-diagnostic-view.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-diagnostic-view.js +11 -0
- package/dist/modes/interactive-engine/engine-diagnostic-view.js.map +1 -1
- package/dist/modes/interactive-engine/engine-dialog-host.d.ts +2 -2
- package/dist/modes/interactive-engine/engine-dialog-host.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-dialog-host.js +4 -1
- package/dist/modes/interactive-engine/engine-dialog-host.js.map +1 -1
- package/dist/modes/interactive-engine/engine-project-trust.d.ts +10 -0
- package/dist/modes/interactive-engine/engine-project-trust.d.ts.map +1 -0
- package/dist/modes/interactive-engine/engine-project-trust.js +28 -0
- package/dist/modes/interactive-engine/engine-project-trust.js.map +1 -0
- package/dist/modes/interactive-engine/engine-render-service.d.ts +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.d.ts +3 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.d.ts.map +1 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.js +7 -1
- package/dist/modes/interactive-engine/extension-ui-bridge.js.map +1 -1
- package/dist/modes/interactive-engine/input-form-host.d.ts +2 -2
- package/dist/modes/interactive-engine/input-form-host.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-auth.d.ts +1 -1
- package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts +5 -2
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +42 -4
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/protocol.d.ts +21 -1
- package/dist/modes/interactive-engine/protocol.d.ts.map +1 -1
- package/dist/modes/interactive-engine/protocol.js +53 -2
- package/dist/modes/interactive-engine/protocol.js.map +1 -1
- package/dist/modes/interactive-engine/remote-component.d.ts +2 -2
- package/dist/modes/interactive-engine/remote-component.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-component.js +19 -8
- package/dist/modes/interactive-engine/remote-component.js.map +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.d.ts +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.d.ts +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
- package/dist/modes/interactive-engine/session-picker-host.d.ts +2 -2
- package/dist/modes/interactive-engine/session-picker-host.js.map +1 -1
- package/dist/modes/json-event.d.ts +1 -1
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-bash-request-owners.d.ts +2 -2
- package/dist/modes/rpc/rpc-bash-request-owners.js.map +1 -1
- package/dist/modes/rpc/rpc-client-api.d.ts +2 -2
- package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client-api.js +2 -2
- package/dist/modes/rpc/rpc-client-api.js.map +1 -1
- package/dist/modes/rpc/rpc-client-process.d.ts +2 -0
- package/dist/modes/rpc/rpc-client-process.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client-process.js +23 -1
- package/dist/modes/rpc/rpc-client-process.js.map +1 -1
- package/dist/modes/rpc/rpc-client-waits.d.ts +1 -1
- package/dist/modes/rpc/rpc-client-waits.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +40 -3
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts +4 -2
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +12 -4
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-extension-ui.d.ts +1 -1
- package/dist/modes/rpc/rpc-extension-ui.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-extension-ui.js +2 -1
- package/dist/modes/rpc/rpc-extension-ui.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +12 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-provider-auth.d.ts +1 -1
- package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
- package/dist/modes/rpc/rpc-session-binding.d.ts +4 -1
- package/dist/modes/rpc/rpc-session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-session-binding.js +35 -1
- package/dist/modes/rpc/rpc-session-binding.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +17 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/task-ui-bridge.d.ts +9 -0
- package/dist/modes/rpc/task-ui-bridge.d.ts.map +1 -0
- package/dist/modes/rpc/task-ui-bridge.js +146 -0
- package/dist/modes/rpc/task-ui-bridge.js.map +1 -0
- package/dist/self-update-plan.js.map +1 -1
- package/dist/utils/markit.d.ts +2 -0
- package/dist/utils/markit.d.ts.map +1 -1
- package/dist/utils/markit.js +65 -5
- package/dist/utils/markit.js.map +1 -1
- package/docs/background-tasks.md +232 -0
- package/docs/build.md +51 -0
- package/docs/changelog.mdx +8 -8
- package/docs/compaction/reference.md +267 -0
- package/docs/compaction.md +39 -200
- package/docs/computer-use.md +425 -0
- package/docs/containerization.md +9 -5
- package/docs/custom-provider/api-reference.md +145 -0
- package/docs/custom-provider/oauth.md +131 -0
- package/docs/custom-provider/override.md +34 -0
- package/docs/custom-provider/registration.md +163 -0
- package/docs/custom-provider/streaming.md +214 -0
- package/docs/custom-provider.md +43 -607
- package/docs/development.md +68 -30
- package/docs/docs.json +199 -73
- package/docs/environment-variables.md +2 -2
- package/docs/extensions/api-reference.md +1003 -0
- package/docs/extensions/authoring.md +676 -0
- package/docs/extensions/events.md +793 -0
- package/docs/extensions/examples.md +94 -0
- package/docs/extensions/ui.md +470 -0
- package/docs/extensions.md +241 -2623
- package/docs/getting-started/authentication.md +55 -0
- package/docs/getting-started/first-session.md +172 -0
- package/docs/getting-started/installation.md +154 -0
- package/docs/getting-started/project-instructions.md +43 -0
- package/docs/guides/configuration.md +65 -0
- package/docs/guides/intercom.md +24 -0
- package/docs/guides/non-interactive.md +33 -0
- package/docs/guides/subagents.md +24 -0
- package/docs/guides/workflows.md +27 -0
- package/docs/guides.md +41 -0
- package/docs/herdr.md +55 -0
- package/docs/index.md +13 -44
- package/docs/intercom/operations.md +178 -0
- package/docs/intercom/reference.md +150 -0
- package/docs/intercom.md +61 -251
- package/docs/json.md +17 -0
- package/docs/keybindings.md +36 -2
- package/docs/llama-cpp.md +5 -0
- package/docs/models/artificial-analysis-index.md +89 -0
- package/docs/models/evals.md +225 -148
- package/docs/models/model-selection.md +30 -21
- package/docs/models/pareto-efficiency.md +4 -4
- package/docs/models/reference.md +601 -0
- package/docs/models.md +45 -550
- package/docs/packages/authoring.md +88 -0
- package/docs/packages/reference.md +43 -0
- package/docs/packages.md +28 -107
- package/docs/programmatic.md +29 -0
- package/docs/prompt-templates.md +11 -0
- package/docs/providers/reference.md +23 -0
- package/docs/providers.md +59 -62
- package/docs/quickstart.md +45 -239
- package/docs/reference/cli.md +252 -0
- package/docs/reference.md +52 -0
- package/docs/rpc/examples.md +64 -0
- package/docs/rpc/extension-ui.md +198 -0
- package/docs/rpc/protocol.md +1341 -0
- package/docs/rpc.md +109 -1346
- package/docs/sdk/reference.md +1090 -0
- package/docs/sdk.md +64 -756
- package/docs/session-format.md +2 -0
- package/docs/sessions.md +6 -10
- package/docs/settings.md +45 -48
- package/docs/skills/authoring.md +95 -0
- package/docs/skills/reference.md +60 -0
- package/docs/skills.md +37 -117
- package/docs/subagents/authoring.md +37 -0
- package/docs/subagents/reference.md +60 -0
- package/docs/subagents.md +90 -78
- package/docs/terminal-setup.md +1 -1
- package/docs/themes/reference.md +176 -0
- package/docs/themes.md +25 -135
- package/docs/tmux.md +7 -0
- package/docs/tools/edit.md +5 -0
- package/docs/tools.md +67 -1
- package/docs/tui/reference.md +343 -0
- package/docs/tui.md +83 -285
- package/docs/usage.md +31 -210
- package/docs/web-access.md +50 -0
- package/docs/windows.md +6 -5
- package/docs/workflows/api-reference.md +31 -12
- package/docs/workflows/authoring.md +7 -5
- package/docs/workflows/builtins.md +11 -8
- package/docs/workflows/operations.md +103 -38
- package/docs/workflows/reliable-design.md +59 -10
- package/docs/workflows/verification.md +116 -32
- package/docs/workflows.md +7 -3
- package/examples/extensions/gondolin/index.ts +116 -148
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/ssh.ts +56 -34
- package/npm-shrinkwrap.json +798 -678
- package/package.json +11 -11
- /package/dist/builtin/workflows/builtin/{chunk-cg9tmks0.js → chunk-n1910xc4.js} +0 -0
- /package/dist/builtin/workflows/builtin/{chunk-wpckd35c.js → chunk-rc5ec5xx.js} +0 -0
- /package/dist/builtin/workflows/builtin/{chunk-7at6dnkr.js → chunk-tgt0s5e5.js} +0 -0
- /package/dist/builtin/workflows/builtin/{chunk-bfkmzv9h.js → chunk-xtxcq5tj.js} +0 -0
|
@@ -12,7 +12,17 @@ var __export = (target, all) => {
|
|
|
12
12
|
set: __exportSetter.bind(all, name)
|
|
13
13
|
});
|
|
14
14
|
};
|
|
15
|
-
var __esm = (fn, res) => () =>
|
|
15
|
+
var __esm = (fn, res, err) => () => {
|
|
16
|
+
if (fn)
|
|
17
|
+
try {
|
|
18
|
+
res = fn(fn = 0);
|
|
19
|
+
} catch (e) {
|
|
20
|
+
err = [e];
|
|
21
|
+
}
|
|
22
|
+
if (err)
|
|
23
|
+
throw err[0];
|
|
24
|
+
return res;
|
|
25
|
+
};
|
|
16
26
|
|
|
17
27
|
// dist/builtin/intercom/result-renderers.ts
|
|
18
28
|
import { Text } from "@earendil-works/pi-tui";
|
|
@@ -80,7 +90,7 @@ function isRecoverableIntercomDisconnect(error) {
|
|
|
80
90
|
}
|
|
81
91
|
return false;
|
|
82
92
|
}
|
|
83
|
-
var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected
|
|
93
|
+
var RECOVERABLE_DISCONNECT_MESSAGE = "Client disconnected", MAX_CAUSE_DEPTH = 8, IntercomClientDisconnectedError;
|
|
84
94
|
var init_recoverable_disconnect = __esm(() => {
|
|
85
95
|
IntercomClientDisconnectedError = class IntercomClientDisconnectedError extends Error {
|
|
86
96
|
intercomRecoverableDisconnect = true;
|
|
@@ -91,6 +101,16 @@ var init_recoverable_disconnect = __esm(() => {
|
|
|
91
101
|
};
|
|
92
102
|
});
|
|
93
103
|
|
|
104
|
+
// dist/builtin/intercom/retry-policy.ts
|
|
105
|
+
var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS;
|
|
106
|
+
var init_retry_policy = __esm(() => {
|
|
107
|
+
ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
108
|
+
RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
|
|
109
|
+
RETRY_IDENTITY_TTL_MS = ASK_REPLY_TIMEOUT_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
|
|
110
|
+
DELIVERED_MESSAGE_TTL_MS = RETRY_IDENTITY_TTL_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
|
|
111
|
+
RECONNECT_DELAYS_MS = [1000, 2000, 5000];
|
|
112
|
+
});
|
|
113
|
+
|
|
94
114
|
// dist/builtin/intercom/reconnect-backoff.ts
|
|
95
115
|
function reconnectDelayMs(attempt) {
|
|
96
116
|
return BACKOFF_MS[Math.min(attempt, BACKOFF_MS.length - 1)];
|
|
@@ -100,6 +120,37 @@ var init_reconnect_backoff = __esm(() => {
|
|
|
100
120
|
BACKOFF_MS = [1000, 2000, 5000, 1e4, 30000];
|
|
101
121
|
});
|
|
102
122
|
|
|
123
|
+
// dist/builtin/intercom/subagent-reply-capability.ts
|
|
124
|
+
function registerSubagentReplyCapability(pi, client) {
|
|
125
|
+
let signal;
|
|
126
|
+
let unbind;
|
|
127
|
+
const capability = () => {
|
|
128
|
+
if (!signal)
|
|
129
|
+
return;
|
|
130
|
+
return signal.aborted ? "terminal" : "live";
|
|
131
|
+
};
|
|
132
|
+
pi.on("session_start", (_event, ctx) => {
|
|
133
|
+
unbind?.();
|
|
134
|
+
signal = ctx.subagentPolicy?.executionEnded;
|
|
135
|
+
const current = signal;
|
|
136
|
+
const terminal = () => {
|
|
137
|
+
if (signal !== current)
|
|
138
|
+
return;
|
|
139
|
+
client()?.updatePresence({ replyCapability: "terminal" });
|
|
140
|
+
};
|
|
141
|
+
current?.addEventListener("abort", terminal, { once: true });
|
|
142
|
+
unbind = () => current?.removeEventListener("abort", terminal);
|
|
143
|
+
if (current?.aborted)
|
|
144
|
+
terminal();
|
|
145
|
+
});
|
|
146
|
+
pi.on("session_shutdown", () => {
|
|
147
|
+
unbind?.();
|
|
148
|
+
unbind = undefined;
|
|
149
|
+
signal = undefined;
|
|
150
|
+
});
|
|
151
|
+
return capability;
|
|
152
|
+
}
|
|
153
|
+
|
|
103
154
|
// dist/builtin/intercom/broker/framing.ts
|
|
104
155
|
function writeMessage(socket, msg, callback) {
|
|
105
156
|
const json = JSON.stringify(msg);
|
|
@@ -472,6 +523,7 @@ var init_client = __esm(() => {
|
|
|
472
523
|
_supervisorSessionId = null;
|
|
473
524
|
_messageSource;
|
|
474
525
|
pendingSends = new PendingSendRegistry;
|
|
526
|
+
pendingReplyTargets = new Map;
|
|
475
527
|
pendingGroupLists = new Map;
|
|
476
528
|
pendingLists = new Map;
|
|
477
529
|
pendingPresence = new Map;
|
|
@@ -676,7 +728,24 @@ var init_client = __esm(() => {
|
|
|
676
728
|
case "registration_failed": {
|
|
677
729
|
if (typeof brokerMessage.reason !== "string")
|
|
678
730
|
throw new Error("Invalid registration_failed message");
|
|
679
|
-
|
|
731
|
+
const refusal = new Error(brokerMessage.reason);
|
|
732
|
+
if (this._sessionId === null) {
|
|
733
|
+
this.emit("_registration_failed", refusal);
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
this.disconnectError ??= refusal;
|
|
737
|
+
this.failPending(this.disconnectError);
|
|
738
|
+
this.socket?.destroy();
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
case "question_target": {
|
|
742
|
+
const { messageId, attemptId, sessionId } = brokerMessage;
|
|
743
|
+
if (typeof messageId !== "string" || typeof attemptId !== "string" || typeof sessionId !== "string") {
|
|
744
|
+
throw new Error("Invalid question_target message");
|
|
745
|
+
}
|
|
746
|
+
const pending = this.pendingReplyTargets.get(attemptId);
|
|
747
|
+
if (pending?.messageId === messageId)
|
|
748
|
+
pending.bind(sessionId);
|
|
680
749
|
break;
|
|
681
750
|
}
|
|
682
751
|
case "sessions": {
|
|
@@ -1096,14 +1165,15 @@ var init_client = __esm(() => {
|
|
|
1096
1165
|
}
|
|
1097
1166
|
});
|
|
1098
1167
|
}
|
|
1099
|
-
registerPendingStageRoute(runId, group, capability, stages, possibleStages) {
|
|
1168
|
+
registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent) {
|
|
1100
1169
|
writeMessage(this.requireActiveSocket(), {
|
|
1101
1170
|
type: "register_pending_stage_route",
|
|
1102
1171
|
runId,
|
|
1103
1172
|
group,
|
|
1104
1173
|
capability,
|
|
1105
1174
|
stages,
|
|
1106
|
-
possibleStages
|
|
1175
|
+
possibleStages,
|
|
1176
|
+
...parent === undefined ? {} : { parent }
|
|
1107
1177
|
});
|
|
1108
1178
|
}
|
|
1109
1179
|
registerLiveWorkflowStageRoute(runId, stageKeys, capability) {
|
|
@@ -1177,7 +1247,8 @@ var init_client = __esm(() => {
|
|
|
1177
1247
|
const pendingSignature = JSON.stringify({
|
|
1178
1248
|
transportTarget: to,
|
|
1179
1249
|
logicalSignature: buildSendSignature(options.logicalTarget ?? to, options),
|
|
1180
|
-
requirePendingReply: options.requirePendingReply ?? false
|
|
1250
|
+
requirePendingReply: options.requirePendingReply ?? false,
|
|
1251
|
+
...options.expectedRecipientId === undefined ? {} : { expectedRecipientId: options.expectedRecipientId }
|
|
1181
1252
|
});
|
|
1182
1253
|
acquired = this.pendingSends.acquire(messageId, pendingSignature, 1e4);
|
|
1183
1254
|
} catch (error) {
|
|
@@ -1194,12 +1265,17 @@ var init_client = __esm(() => {
|
|
|
1194
1265
|
source: this._messageSource,
|
|
1195
1266
|
content: { text: options.text, attachments: options.attachments }
|
|
1196
1267
|
};
|
|
1268
|
+
if (options.onReplyTarget !== undefined) {
|
|
1269
|
+
this.pendingReplyTargets.set(acquired.attempt.attemptId, { messageId, bind: options.onReplyTarget });
|
|
1270
|
+
}
|
|
1197
1271
|
try {
|
|
1198
1272
|
writeMessage(socket, {
|
|
1199
1273
|
type,
|
|
1200
1274
|
to,
|
|
1201
1275
|
...options.logicalTarget === undefined ? {} : { logicalTarget: options.logicalTarget },
|
|
1202
1276
|
...options.requirePendingReply === undefined ? {} : { requirePendingReply: options.requirePendingReply },
|
|
1277
|
+
...options.expectedRecipientId === undefined ? {} : { expectedRecipientId: options.expectedRecipientId },
|
|
1278
|
+
...options.onReplyTarget === undefined ? {} : { resolveReplyTarget: true },
|
|
1203
1279
|
message,
|
|
1204
1280
|
attemptId: acquired.attempt.attemptId,
|
|
1205
1281
|
...extra
|
|
@@ -1207,6 +1283,10 @@ var init_client = __esm(() => {
|
|
|
1207
1283
|
} catch (error) {
|
|
1208
1284
|
this.pendingSends.reject(acquired.attempt, toError(error));
|
|
1209
1285
|
}
|
|
1286
|
+
const clearReplyTarget = () => {
|
|
1287
|
+
this.pendingReplyTargets.delete(acquired.attempt.attemptId);
|
|
1288
|
+
};
|
|
1289
|
+
acquired.attempt.promise.then(clearReplyTarget, clearReplyTarget);
|
|
1210
1290
|
return acquired.attempt.promise;
|
|
1211
1291
|
}
|
|
1212
1292
|
updatePresence(updates) {
|
|
@@ -1676,15 +1756,6 @@ class InlineMessageComponent {
|
|
|
1676
1756
|
}
|
|
1677
1757
|
var init_inline_message = () => {};
|
|
1678
1758
|
|
|
1679
|
-
// dist/builtin/intercom/retry-policy.ts
|
|
1680
|
-
var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS;
|
|
1681
|
-
var init_retry_policy = __esm(() => {
|
|
1682
|
-
ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
1683
|
-
RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
|
|
1684
|
-
RETRY_IDENTITY_TTL_MS = ASK_REPLY_TIMEOUT_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
|
|
1685
|
-
DELIVERED_MESSAGE_TTL_MS = RETRY_IDENTITY_TTL_MS + RETRY_IDENTITY_RETRY_OPPORTUNITY_MS;
|
|
1686
|
-
});
|
|
1687
|
-
|
|
1688
1759
|
// dist/builtin/intercom/reply-waiter.ts
|
|
1689
1760
|
class ReplyWaiterRegistry {
|
|
1690
1761
|
timeoutMs;
|
|
@@ -1756,6 +1827,10 @@ class ReplyWaiterRegistry {
|
|
|
1756
1827
|
ok: true,
|
|
1757
1828
|
wait: {
|
|
1758
1829
|
promise,
|
|
1830
|
+
bindSender: (sender) => {
|
|
1831
|
+
if (this.waiters.get(replyTo) === record)
|
|
1832
|
+
record.from = sender;
|
|
1833
|
+
},
|
|
1759
1834
|
cancel: (error) => record.reject(error)
|
|
1760
1835
|
}
|
|
1761
1836
|
};
|
|
@@ -1923,6 +1998,11 @@ class ReplyTracker {
|
|
|
1923
1998
|
endTurn() {
|
|
1924
1999
|
this.currentTurnContext = null;
|
|
1925
2000
|
}
|
|
2001
|
+
restoreTurnContext() {
|
|
2002
|
+
if (this.currentTurnContext)
|
|
2003
|
+
this.pendingTurnContexts.unshift(this.currentTurnContext);
|
|
2004
|
+
this.currentTurnContext = null;
|
|
2005
|
+
}
|
|
1926
2006
|
reset() {
|
|
1927
2007
|
this.pendingAsks.clear();
|
|
1928
2008
|
this.pendingTurnContexts.length = 0;
|
|
@@ -1930,22 +2010,22 @@ class ReplyTracker {
|
|
|
1930
2010
|
}
|
|
1931
2011
|
resolveReplyTarget(options, now = Date.now()) {
|
|
1932
2012
|
this.pruneExpired(now);
|
|
1933
|
-
if (options.replyTo) {
|
|
1934
|
-
const exact = this.pendingAsks.get(options.replyTo);
|
|
1935
|
-
if (exact)
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
return exact;
|
|
2013
|
+
if (options.replyTo !== undefined) {
|
|
2014
|
+
const exact = this.pendingAsks.get(options.replyTo) ?? (this.currentTurnContext?.message.id === options.replyTo && !this.currentTurnContext.message.expectsReply ? this.currentTurnContext : undefined);
|
|
2015
|
+
if (!exact)
|
|
2016
|
+
throw new Error(`No reply context for "${options.replyTo}"`);
|
|
2017
|
+
if (options.to !== undefined) {
|
|
2018
|
+
const resolution = resolveSessionTarget([exact.from], options.to);
|
|
2019
|
+
if (resolution.kind !== "resolved")
|
|
2020
|
+
throw new Error(`Reply context "${options.replyTo}" is not from "${options.to}"`);
|
|
1942
2021
|
}
|
|
2022
|
+
return exact;
|
|
1943
2023
|
}
|
|
1944
|
-
if (this.currentTurnContext) {
|
|
2024
|
+
if (options.to === undefined && this.currentTurnContext) {
|
|
1945
2025
|
return this.currentTurnContext;
|
|
1946
2026
|
}
|
|
1947
2027
|
const pending = Array.from(this.pendingAsks.values());
|
|
1948
|
-
if (options.to) {
|
|
2028
|
+
if (options.to !== undefined) {
|
|
1949
2029
|
const senders = [...new Map(pending.map((context) => [context.from.id, context.from])).values()];
|
|
1950
2030
|
const resolution = resolveSessionTarget(senders, options.to);
|
|
1951
2031
|
if (resolution.kind !== "resolved") {
|
|
@@ -2264,32 +2344,32 @@ function validateSupervisorInterviewReply(value, interview) {
|
|
|
2264
2344
|
if (!Object.hasOwn(raw, "value")) {
|
|
2265
2345
|
throw new Error(`responses[${index}].value is required`);
|
|
2266
2346
|
}
|
|
2267
|
-
const
|
|
2347
|
+
const value = raw.value;
|
|
2268
2348
|
if (question.type === "single") {
|
|
2269
|
-
if (typeof
|
|
2349
|
+
if (typeof value !== "string")
|
|
2270
2350
|
throw new Error(`responses[${index}].value must be a string for single questions`);
|
|
2271
2351
|
const optionLabels = new Set(question.options?.map(interviewOptionLabel));
|
|
2272
|
-
if (!optionLabels.has(
|
|
2352
|
+
if (!optionLabels.has(value.trim()))
|
|
2273
2353
|
throw new Error(`responses[${index}].value must match one of the question options`);
|
|
2274
|
-
responses.push({ id, value:
|
|
2354
|
+
responses.push({ id, value: value.trim() });
|
|
2275
2355
|
continue;
|
|
2276
2356
|
}
|
|
2277
2357
|
if (question.type === "multi") {
|
|
2278
|
-
if (!Array.isArray(
|
|
2358
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
2279
2359
|
throw new Error(`responses[${index}].value must be an array of strings for multi questions`);
|
|
2280
2360
|
}
|
|
2281
2361
|
const optionLabels = new Set(question.options?.map(interviewOptionLabel));
|
|
2282
|
-
const selected =
|
|
2362
|
+
const selected = value.map((item) => item.trim());
|
|
2283
2363
|
const invalid = selected.find((item) => !optionLabels.has(item));
|
|
2284
2364
|
if (invalid)
|
|
2285
2365
|
throw new Error(`responses[${index}].value contains an option that is not in the question options: ${invalid}`);
|
|
2286
2366
|
responses.push({ id, value: selected });
|
|
2287
2367
|
continue;
|
|
2288
2368
|
}
|
|
2289
|
-
if (typeof
|
|
2369
|
+
if (typeof value !== "string") {
|
|
2290
2370
|
throw new Error(`responses[${index}].value must be a string for ${question.type} questions`);
|
|
2291
2371
|
}
|
|
2292
|
-
responses.push({ id, value
|
|
2372
|
+
responses.push({ id, value });
|
|
2293
2373
|
}
|
|
2294
2374
|
return { responses };
|
|
2295
2375
|
}
|
|
@@ -2368,12 +2448,13 @@ function formatSessionLabel(session, duplicates) {
|
|
|
2368
2448
|
return duplicates.has(session.name.toLowerCase()) ? `${session.name} (${session.id})` : session.name;
|
|
2369
2449
|
}
|
|
2370
2450
|
function formatSessionListRow(session, currentCwd, isSelf) {
|
|
2371
|
-
const name = session.name
|
|
2451
|
+
const name = session.name && session.name !== session.id && session.name !== resolveIntercomPresenceName(undefined, session.id) ? ` name: ${session.name}` : "";
|
|
2372
2452
|
const normalizedGroup = normalizeGroup(session.group);
|
|
2373
2453
|
const groupTag = normalizedGroup !== DEFAULT_GROUP ? `group: ${normalizedGroup}` : undefined;
|
|
2374
|
-
const
|
|
2454
|
+
const capabilityTag = session.replyCapability === undefined ? undefined : `replyCapability: ${session.replyCapability}`;
|
|
2455
|
+
const tags = [isSelf ? "self" : session.cwd === currentCwd ? "same cwd" : undefined, session.status, capabilityTag, groupTag].filter((tag) => Boolean(tag));
|
|
2375
2456
|
const suffix = tags.length ? ` [${tags.join(", ")}]` : "";
|
|
2376
|
-
return
|
|
2457
|
+
return `- \`${session.id}\`${suffix} ${session.cwd} (${session.model})${name}`;
|
|
2377
2458
|
}
|
|
2378
2459
|
function previewText(value, maxLength = 72) {
|
|
2379
2460
|
if (typeof value !== "string") {
|
|
@@ -2395,7 +2476,7 @@ import { randomUUID as randomUUID3 } from "crypto";
|
|
|
2395
2476
|
import { Type } from "typebox";
|
|
2396
2477
|
import { Text as Text2 } from "@earendil-works/pi-tui";
|
|
2397
2478
|
function registerContactSupervisorTool(pi, deps) {
|
|
2398
|
-
const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, resolveSessionTarget
|
|
2479
|
+
const { childOrchestratorMetadata, ensureConnected, syncPresenceIdentity, resolveSessionTarget, beginReplyWait } = deps;
|
|
2399
2480
|
const getMetadata = typeof childOrchestratorMetadata === "function" ? childOrchestratorMetadata : () => childOrchestratorMetadata;
|
|
2400
2481
|
let supervisorWaitActive = false;
|
|
2401
2482
|
let supervisorHandoffClaimed = false;
|
|
@@ -2508,13 +2589,6 @@ function registerContactSupervisorTool(pi, deps) {
|
|
|
2508
2589
|
details: { yielded: true }
|
|
2509
2590
|
};
|
|
2510
2591
|
}
|
|
2511
|
-
if (reason === "need_decision" && typeof params.message !== "string") {
|
|
2512
|
-
return {
|
|
2513
|
-
content: [{ type: "text", text: `Missing 'message' parameter for reason '${reason}'.` }],
|
|
2514
|
-
isError: true,
|
|
2515
|
-
details: { error: true }
|
|
2516
|
-
};
|
|
2517
|
-
}
|
|
2518
2592
|
let connectedClient;
|
|
2519
2593
|
try {
|
|
2520
2594
|
connectedClient = await ensureConnected("tool");
|
|
@@ -2538,7 +2612,7 @@ function registerContactSupervisorTool(pi, deps) {
|
|
|
2538
2612
|
sendTo = connectedClient.supervisorSessionId ?? metadata.supervisor.supervisorSessionId;
|
|
2539
2613
|
} else {
|
|
2540
2614
|
try {
|
|
2541
|
-
sendTo = await
|
|
2615
|
+
sendTo = await resolveSessionTarget(connectedClient, metadata.orchestratorTarget) ?? metadata.orchestratorTarget;
|
|
2542
2616
|
} catch (error) {
|
|
2543
2617
|
return {
|
|
2544
2618
|
content: [{ type: "text", text: `Failed to resolve supervisor target: ${getErrorMessage(error)}` }],
|
|
@@ -2607,7 +2681,7 @@ function registerContactSupervisorTool(pi, deps) {
|
|
|
2607
2681
|
};
|
|
2608
2682
|
}
|
|
2609
2683
|
wait = admission.wait;
|
|
2610
|
-
const requestText = reason === "interview_request" ? formatChildOrchestratorMessage("interview", metadata, formatSupervisorInterviewRequest(supervisorInterview, typeof params.message === "string" ? params.message : undefined)) : formatChildOrchestratorMessage("ask", metadata, params.message);
|
|
2684
|
+
const requestText = reason === "interview_request" ? formatChildOrchestratorMessage("interview", metadata, formatSupervisorInterviewRequest(supervisorInterview, typeof params.message === "string" ? params.message : undefined)) : formatChildOrchestratorMessage("ask", metadata, typeof params.message === "string" ? params.message : "");
|
|
2611
2685
|
const sendResult = await connectedClient.sendToSupervisor(sendTo, {
|
|
2612
2686
|
messageId: questionId,
|
|
2613
2687
|
text: requestText,
|
|
@@ -2808,6 +2882,11 @@ class RetryIdentityReservations {
|
|
|
2808
2882
|
}
|
|
2809
2883
|
this.finishRetained(reservation, "settled");
|
|
2810
2884
|
}
|
|
2885
|
+
discard(retryToken) {
|
|
2886
|
+
const reservation = this.tokenReservations.get(retryToken);
|
|
2887
|
+
if (reservation !== undefined)
|
|
2888
|
+
this.expire(reservation);
|
|
2889
|
+
}
|
|
2811
2890
|
remainingRetries(attempt) {
|
|
2812
2891
|
const reservation = this.currentReservation(attempt);
|
|
2813
2892
|
return reservation === undefined ? 0 : Math.max(0, this.maxReuses - reservation.reuseCount);
|
|
@@ -2961,14 +3040,73 @@ var init_retry_identity = __esm(() => {
|
|
|
2961
3040
|
};
|
|
2962
3041
|
});
|
|
2963
3042
|
|
|
3043
|
+
// dist/builtin/intercom/tool-retry.ts
|
|
3044
|
+
import { setTimeout as delay2 } from "node:timers/promises";
|
|
3045
|
+
async function runIntercomOperation(attempt, release, signal) {
|
|
3046
|
+
const deadline = new AbortController;
|
|
3047
|
+
const timer = setTimeout(() => deadline.abort(), RETRY_IDENTITY_TTL_MS);
|
|
3048
|
+
const operationSignal = signal === undefined ? deadline.signal : AbortSignal.any([signal, deadline.signal]);
|
|
3049
|
+
let token;
|
|
3050
|
+
let recovering = false;
|
|
3051
|
+
let retries = 0;
|
|
3052
|
+
let last = {
|
|
3053
|
+
content: [{ type: "text", text: "Cancelled" }],
|
|
3054
|
+
isError: true,
|
|
3055
|
+
details: { error: true }
|
|
3056
|
+
};
|
|
3057
|
+
try {
|
|
3058
|
+
for (;; ) {
|
|
3059
|
+
if (operationSignal.aborted)
|
|
3060
|
+
break;
|
|
3061
|
+
last = await attempt(token, operationSignal);
|
|
3062
|
+
const { retryToken, retryable, deliveryUncertain, ...details } = last.details;
|
|
3063
|
+
last = { ...last, details };
|
|
3064
|
+
if (!last.isError)
|
|
3065
|
+
return last;
|
|
3066
|
+
recovering ||= deliveryUncertain === true || retryable === true;
|
|
3067
|
+
const nextToken = typeof retryToken === "string" ? retryToken : undefined;
|
|
3068
|
+
const canRetry = nextToken !== undefined || token === undefined && retryable === true;
|
|
3069
|
+
token = nextToken ?? token;
|
|
3070
|
+
if (!canRetry) {
|
|
3071
|
+
if (!recovering && retryable !== true)
|
|
3072
|
+
return last;
|
|
3073
|
+
break;
|
|
3074
|
+
}
|
|
3075
|
+
recovering = true;
|
|
3076
|
+
if (retries >= RETRY_IDENTITY_MAX_REUSES || operationSignal.aborted)
|
|
3077
|
+
break;
|
|
3078
|
+
try {
|
|
3079
|
+
await delay2(RECONNECT_DELAYS_MS[retries], undefined, { signal: operationSignal });
|
|
3080
|
+
} catch {
|
|
3081
|
+
break;
|
|
3082
|
+
}
|
|
3083
|
+
retries += 1;
|
|
3084
|
+
}
|
|
3085
|
+
const reason = operationSignal.aborted ? "Cancelled" : last.content.map(({ text }) => text).join(`
|
|
3086
|
+
`);
|
|
3087
|
+
return {
|
|
3088
|
+
content: [{
|
|
3089
|
+
type: "text",
|
|
3090
|
+
text: recovering ? `${reason}
|
|
3091
|
+
Intercom recovery stopped after ${retries} automatic retries. Delivery may already have occurred. Do not repeat this operation automatically; check with the recipient before intentionally sending a new message.` : reason
|
|
3092
|
+
}],
|
|
3093
|
+
isError: true,
|
|
3094
|
+
details: { error: true, terminal: true, automaticRetries: retries, ...recovering ? { outcome: "unknown" } : {} }
|
|
3095
|
+
};
|
|
3096
|
+
} finally {
|
|
3097
|
+
clearTimeout(timer);
|
|
3098
|
+
if (token !== undefined)
|
|
3099
|
+
release(token);
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
var init_tool_retry = __esm(() => {
|
|
3103
|
+
init_retry_identity();
|
|
3104
|
+
init_retry_policy();
|
|
3105
|
+
});
|
|
3106
|
+
|
|
2964
3107
|
// dist/builtin/intercom/intercom-tool.ts
|
|
2965
3108
|
import { Type as Type2 } from "typebox";
|
|
2966
3109
|
import { Text as Text3 } from "@earendil-works/pi-tui";
|
|
2967
|
-
function retryTokenGuidance(retryToken, remainingRetries) {
|
|
2968
|
-
if (retryToken === undefined)
|
|
2969
|
-
return "";
|
|
2970
|
-
return ` Retry this exact operation with retryToken \`${retryToken}\` (${remainingRetries} claimed ${remainingRetries === 1 ? "attempt" : "attempts"} remain; the original deadline is unchanged).`;
|
|
2971
|
-
}
|
|
2972
3110
|
function retryErrorDetails(retryToken) {
|
|
2973
3111
|
return retryToken === undefined ? { error: true } : { error: true, retryToken };
|
|
2974
3112
|
}
|
|
@@ -3056,10 +3194,10 @@ async function resolveReplySender(client, logicalTarget, sendTarget) {
|
|
|
3056
3194
|
return { kind: "unresolved" };
|
|
3057
3195
|
}
|
|
3058
3196
|
function formatWorkflowStageRow(stage) {
|
|
3059
|
-
return `-
|
|
3197
|
+
return `- \`${stage.target}\` [${stage.lifecycle.toUpperCase()}] workflow stage: ${stage.stageName}${stage.sessionId === undefined ? "" : ` session: \`${stage.sessionId}\``}`;
|
|
3060
3198
|
}
|
|
3061
3199
|
function formatWorkflowFutureStageRow(stage) {
|
|
3062
|
-
return `-
|
|
3200
|
+
return `- \`${stage.target}\` [future] ${stage.queuedCount} queued message${stage.queuedCount === 1 ? "" : "s"}`;
|
|
3063
3201
|
}
|
|
3064
3202
|
function registerIntercomTool(pi, deps) {
|
|
3065
3203
|
const retryIdentities = new RetryIdentityReservations({ maxEntries: deps.retryIdentityMaxEntries });
|
|
@@ -3086,7 +3224,7 @@ A valid target outside the known set queues speculatively with a \`notInKnownSet
|
|
|
3086
3224
|
undeliverable at terminal only if never delivered. Use \`ask\` only for a live, reply-capable target.
|
|
3087
3225
|
Stage paths win over same-named owned subgroups for send/ask; \`list\` with \`group\` continues to
|
|
3088
3226
|
select the group.
|
|
3089
|
-
|
|
3227
|
+
For send/ask/reply, Intercom retries recoverable disconnects internally up to three times with the same operation identity. Each new tool call is a new operation. If recovery ends with an unknown delivery outcome, do not repeat it automatically.
|
|
3090
3228
|
|
|
3091
3229
|
Usage:
|
|
3092
3230
|
intercom({ action: "list" }) → List sessions visible through your groups
|
|
@@ -3098,14 +3236,13 @@ Usage:
|
|
|
3098
3236
|
intercom({ action: "send", to: "session-name", message: "..." }) → Send message (shared group only)
|
|
3099
3237
|
intercom({ action: "ask", to: "session-name", message: "..." }) → Ask and wait for reply
|
|
3100
3238
|
intercom({ action: "reply", message: "..." }) → Reply to the active or exact pending ask
|
|
3101
|
-
intercom({ action: "send", to: "session-name", message: "...", retryToken: "..." }) → Claim the exact retry returned by a retryable failure
|
|
3102
3239
|
intercom({ action: "pending" }) → List unresolved inbound asks
|
|
3103
3240
|
intercom({ action: "status" }) → Show connection status and all your groups
|
|
3104
3241
|
|
|
3105
3242
|
The "join" action is additive. "default" is the shared default group; "true" and
|
|
3106
3243
|
"auto" are reserved for subagent auto-groups. Ordinary delivery requires at least
|
|
3107
3244
|
one shared membership; contact_supervisor remains the only cross-group path.`,
|
|
3108
|
-
promptSnippet: "Use to coordinate with other local agent sessions that share an intercom group.
|
|
3245
|
+
promptSnippet: "Use to coordinate with other local agent sessions that share an intercom group. Send/ask/reply retry reconnects internally; do not automatically repeat an unknown delivery outcome.",
|
|
3109
3246
|
parameters: Type2.Object({
|
|
3110
3247
|
action: Type2.String({
|
|
3111
3248
|
description: "Action: 'list', 'groups', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'"
|
|
@@ -3125,78 +3262,25 @@ one shared membership; contact_supervisor remains the only cross-group path.`,
|
|
|
3125
3262
|
replyTo: Type2.Optional(Type2.String({
|
|
3126
3263
|
description: "Exact pending-ask message ID; disambiguates concurrent asks, including asks from one sender"
|
|
3127
3264
|
})),
|
|
3128
|
-
retryToken: Type2.Optional(Type2.String({
|
|
3129
|
-
minLength: 1,
|
|
3130
|
-
maxLength: 128,
|
|
3131
|
-
description: "Opaque token returned after a retryable send/ask/reply failure. Repeat the exact same action and arguments with this token; omit it for every fresh operation."
|
|
3132
|
-
})),
|
|
3133
3265
|
group: Type2.Optional(Type2.String({
|
|
3134
3266
|
description: "Group name for 'join' or optional targeted 'leave'; read-only group filter for 'list'/'status'. 'send'/'ask' use shared memberships."
|
|
3135
3267
|
}))
|
|
3136
3268
|
}),
|
|
3137
|
-
async execute(_toolCallId, params,
|
|
3138
|
-
|
|
3139
|
-
const { action, to, message, attachments, replyTo, retryToken, group } = params;
|
|
3140
|
-
let retryPreflightRemaining;
|
|
3141
|
-
if (retryToken !== undefined) {
|
|
3142
|
-
if (action !== "send" && action !== "ask" && action !== "reply") {
|
|
3143
|
-
const error = new RetryTokenError("mismatch");
|
|
3144
|
-
return {
|
|
3145
|
-
content: [{ type: "text", text: getErrorMessage(error) }],
|
|
3146
|
-
isError: true,
|
|
3147
|
-
details: { error: true }
|
|
3148
|
-
};
|
|
3149
|
-
}
|
|
3150
|
-
try {
|
|
3151
|
-
retryPreflightRemaining = retryIdentities.validateRetryToken(retryToken, toolSessionId, action);
|
|
3152
|
-
} catch (error) {
|
|
3153
|
-
return {
|
|
3154
|
-
content: [{ type: "text", text: getErrorMessage(error) }],
|
|
3155
|
-
isError: true,
|
|
3156
|
-
details: { error: true }
|
|
3157
|
-
};
|
|
3158
|
-
}
|
|
3159
|
-
}
|
|
3160
|
-
let connectedClient;
|
|
3161
|
-
try {
|
|
3162
|
-
connectedClient = await ensureConnected("tool");
|
|
3163
|
-
} catch (error) {
|
|
3164
|
-
const retainedToken = retryToken !== undefined && isRecoverableIntercomDisconnect(error) ? retryToken : undefined;
|
|
3269
|
+
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
3270
|
+
if ("retryToken" in params) {
|
|
3165
3271
|
return {
|
|
3166
|
-
content: [{
|
|
3167
|
-
type: "text",
|
|
3168
|
-
text: `Intercom not connected: ${getErrorMessage(error)}${retryTokenGuidance(retainedToken, retryPreflightRemaining ?? 0)}`
|
|
3169
|
-
}],
|
|
3272
|
+
content: [{ type: "text", text: "Intercom manages retries internally. Caller-supplied retry tokens are not supported; this call was not sent." }],
|
|
3170
3273
|
isError: true,
|
|
3171
|
-
details:
|
|
3274
|
+
details: { error: true }
|
|
3172
3275
|
};
|
|
3173
3276
|
}
|
|
3174
|
-
|
|
3175
|
-
const
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
};
|
|
3182
|
-
const isOnlyOwnGroup = (candidate, ownGroups) => candidate !== undefined && ownGroups.length === 1 && ownGroups[0] === candidate;
|
|
3183
|
-
const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
|
|
3184
|
-
if ((action === "send" || action === "ask") && requestedGroup) {
|
|
3185
|
-
const ownGroups = resolveOwnGroups();
|
|
3186
|
-
if (!ownGroups.includes(requestedGroup)) {
|
|
3187
|
-
return {
|
|
3188
|
-
content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your groups (${ownGroups.join(", ")}); it cannot target group "${requestedGroup}".` }],
|
|
3189
|
-
isError: true,
|
|
3190
|
-
details: { error: true }
|
|
3191
|
-
};
|
|
3192
|
-
}
|
|
3193
|
-
}
|
|
3194
|
-
switch (action) {
|
|
3195
|
-
case "join": {
|
|
3196
|
-
let targetGroup;
|
|
3197
|
-
try {
|
|
3198
|
-
targetGroup = validateRuntimeGroup(group);
|
|
3199
|
-
} catch (error) {
|
|
3277
|
+
const toolSessionId = ctx.sessionManager.getSessionId();
|
|
3278
|
+
const { action, to, message, replyTo, group } = params;
|
|
3279
|
+
const attachments = params.attachments?.map((attachment) => ({ ...attachment }));
|
|
3280
|
+
const executeAttempt = async (retryToken, _signal) => {
|
|
3281
|
+
if (retryToken !== undefined) {
|
|
3282
|
+
if (action !== "send" && action !== "ask" && action !== "reply") {
|
|
3283
|
+
const error = new RetryTokenError("mismatch");
|
|
3200
3284
|
return {
|
|
3201
3285
|
content: [{ type: "text", text: getErrorMessage(error) }],
|
|
3202
3286
|
isError: true,
|
|
@@ -3204,174 +3288,256 @@ one shared membership; contact_supervisor remains the only cross-group path.`,
|
|
|
3204
3288
|
};
|
|
3205
3289
|
}
|
|
3206
3290
|
try {
|
|
3207
|
-
|
|
3208
|
-
deps.setJoinedGroups(groups);
|
|
3209
|
-
return {
|
|
3210
|
-
content: [{ type: "text", text: `Joined intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.` }],
|
|
3211
|
-
isError: false,
|
|
3212
|
-
details: { group: targetGroup, groups }
|
|
3213
|
-
};
|
|
3291
|
+
retryIdentities.validateRetryToken(retryToken, toolSessionId, action);
|
|
3214
3292
|
} catch (error) {
|
|
3215
3293
|
return {
|
|
3216
|
-
content: [{ type: "text", text:
|
|
3294
|
+
content: [{ type: "text", text: getErrorMessage(error) }],
|
|
3217
3295
|
isError: true,
|
|
3218
3296
|
details: { error: true }
|
|
3219
3297
|
};
|
|
3220
3298
|
}
|
|
3221
3299
|
}
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3300
|
+
let connectedClient;
|
|
3301
|
+
try {
|
|
3302
|
+
connectedClient = await ensureConnected("tool");
|
|
3303
|
+
} catch (error) {
|
|
3304
|
+
const retainedToken = retryToken !== undefined && isRecoverableIntercomDisconnect(error) ? retryToken : undefined;
|
|
3305
|
+
return {
|
|
3306
|
+
content: [{
|
|
3307
|
+
type: "text",
|
|
3308
|
+
text: `Intercom not connected: ${getErrorMessage(error)}`
|
|
3309
|
+
}],
|
|
3310
|
+
isError: true,
|
|
3311
|
+
details: { ...retryErrorDetails(retainedToken), retryable: isRecoverableIntercomDisconnect(error) }
|
|
3312
|
+
};
|
|
3313
|
+
}
|
|
3314
|
+
syncPresenceIdentity(toolSessionId);
|
|
3315
|
+
const resolveOwnGroups = (sessions) => {
|
|
3316
|
+
if (Array.isArray(connectedClient.groups)) {
|
|
3317
|
+
return connectedClient.groups.map((membership) => normalizeGroup(membership));
|
|
3318
|
+
}
|
|
3319
|
+
const self = sessions?.find((session) => session.id === connectedClient.sessionId);
|
|
3320
|
+
return [...normalizeGroups(self?.groups, self?.group)];
|
|
3321
|
+
};
|
|
3322
|
+
const isOnlyOwnGroup = (candidate, ownGroups) => candidate !== undefined && ownGroups.length === 1 && ownGroups[0] === candidate;
|
|
3323
|
+
const requestedGroup = typeof group === "string" && group.trim() ? normalizeGroup(group) : undefined;
|
|
3324
|
+
if ((action === "send" || action === "ask") && requestedGroup) {
|
|
3325
|
+
const ownGroups = resolveOwnGroups();
|
|
3326
|
+
if (!ownGroups.includes(requestedGroup)) {
|
|
3230
3327
|
return {
|
|
3231
|
-
content: [{ type: "text", text: `
|
|
3328
|
+
content: [{ type: "text", text: `The 'group' parameter is read-only for 'list'/'status'. '${action}' is always locked to your groups (${ownGroups.join(", ")}); it cannot target group "${requestedGroup}".` }],
|
|
3232
3329
|
isError: true,
|
|
3233
3330
|
details: { error: true }
|
|
3234
3331
|
};
|
|
3235
3332
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3333
|
+
}
|
|
3334
|
+
switch (action) {
|
|
3335
|
+
case "join": {
|
|
3336
|
+
let targetGroup;
|
|
3337
|
+
try {
|
|
3338
|
+
targetGroup = validateRuntimeGroup(group);
|
|
3339
|
+
} catch (error) {
|
|
3340
|
+
return {
|
|
3341
|
+
content: [{ type: "text", text: getErrorMessage(error) }],
|
|
3342
|
+
isError: true,
|
|
3343
|
+
details: { error: true }
|
|
3344
|
+
};
|
|
3345
|
+
}
|
|
3346
|
+
try {
|
|
3347
|
+
const groups = await connectedClient.joinGroup(targetGroup);
|
|
3246
3348
|
deps.setJoinedGroups(groups);
|
|
3349
|
+
return {
|
|
3350
|
+
content: [{ type: "text", text: `Joined intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.` }],
|
|
3351
|
+
isError: false,
|
|
3352
|
+
details: { group: targetGroup, groups }
|
|
3353
|
+
};
|
|
3354
|
+
} catch (error) {
|
|
3355
|
+
return {
|
|
3356
|
+
content: [{ type: "text", text: `Failed to join group: ${getErrorMessage(error)}` }],
|
|
3357
|
+
isError: true,
|
|
3358
|
+
details: { error: true }
|
|
3359
|
+
};
|
|
3247
3360
|
}
|
|
3248
|
-
const text = targetGroup === undefined ? `Returned to home intercom membership. Memberships: ${groups.join(", ")}.` : `Left intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.`;
|
|
3249
|
-
return {
|
|
3250
|
-
content: [{ type: "text", text }],
|
|
3251
|
-
isError: false,
|
|
3252
|
-
details: targetGroup === undefined ? { group: homeGroup, groups } : { groups }
|
|
3253
|
-
};
|
|
3254
|
-
} catch (error) {
|
|
3255
|
-
return {
|
|
3256
|
-
content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
|
|
3257
|
-
isError: true,
|
|
3258
|
-
details: { error: true }
|
|
3259
|
-
};
|
|
3260
3361
|
}
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3362
|
+
case "leave": {
|
|
3363
|
+
let targetGroup;
|
|
3364
|
+
let homeGroup;
|
|
3365
|
+
try {
|
|
3366
|
+
targetGroup = typeof group === "string" && group.trim().length > 0 ? validateRuntimeGroup(group) : undefined;
|
|
3367
|
+
if (targetGroup === undefined)
|
|
3368
|
+
homeGroup = validateRuntimeGroup(deps.homeGroup());
|
|
3369
|
+
} catch (error) {
|
|
3370
|
+
return {
|
|
3371
|
+
content: [{ type: "text", text: `Cannot leave intercom group: ${getErrorMessage(error)}` }],
|
|
3372
|
+
isError: true,
|
|
3373
|
+
details: { error: true }
|
|
3374
|
+
};
|
|
3375
|
+
}
|
|
3376
|
+
try {
|
|
3377
|
+
let groups;
|
|
3378
|
+
if (targetGroup === undefined) {
|
|
3379
|
+
if (homeGroup === undefined)
|
|
3380
|
+
throw new Error("Intercom home group is unavailable");
|
|
3381
|
+
await connectedClient.updatePresenceAcked({ groups: [homeGroup] });
|
|
3382
|
+
groups = connectedClient.groups;
|
|
3383
|
+
deps.clearJoinedGroups();
|
|
3384
|
+
} else {
|
|
3385
|
+
groups = await connectedClient.leaveGroup(targetGroup);
|
|
3386
|
+
deps.setJoinedGroups(groups);
|
|
3387
|
+
}
|
|
3388
|
+
const text = targetGroup === undefined ? `Returned to home intercom membership. Memberships: ${groups.join(", ")}.` : `Left intercom group "${targetGroup}". Memberships: ${groups.join(", ")}.`;
|
|
3389
|
+
return {
|
|
3390
|
+
content: [{ type: "text", text }],
|
|
3391
|
+
isError: false,
|
|
3392
|
+
details: targetGroup === undefined ? { group: homeGroup, groups } : { groups }
|
|
3393
|
+
};
|
|
3394
|
+
} catch (error) {
|
|
3395
|
+
return {
|
|
3396
|
+
content: [{ type: "text", text: `Failed to leave group: ${getErrorMessage(error)}` }],
|
|
3397
|
+
isError: true,
|
|
3398
|
+
details: { error: true }
|
|
3399
|
+
};
|
|
3400
|
+
}
|
|
3401
|
+
}
|
|
3402
|
+
case "groups": {
|
|
3403
|
+
try {
|
|
3404
|
+
const groups = await connectedClient.listGroups();
|
|
3405
|
+
const lines = groups.map(({ group: groupName, sessionCount, member }) => `- ${groupName} — ${sessionCount} session${sessionCount === 1 ? "" : "s"}${member ? " [member]" : ""}`);
|
|
3406
|
+
return {
|
|
3407
|
+
content: [{ type: "text", text: `**Intercom groups:**
|
|
3268
3408
|
${lines.join(`
|
|
3269
3409
|
`)}` }],
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
return {
|
|
3275
|
-
content: [{ type: "text", text: `Failed to list groups: ${getErrorMessage(error)}` }],
|
|
3276
|
-
isError: true,
|
|
3277
|
-
details: { error: true }
|
|
3278
|
-
};
|
|
3279
|
-
}
|
|
3280
|
-
}
|
|
3281
|
-
case "list": {
|
|
3282
|
-
try {
|
|
3283
|
-
const mySessionId = connectedClient.sessionId;
|
|
3284
|
-
const ownDirectory = await listDirectory(connectedClient);
|
|
3285
|
-
const ownSessions = ownDirectory.sessions;
|
|
3286
|
-
const currentSession = ownSessions.find((session) => session.id === mySessionId);
|
|
3287
|
-
if (!currentSession) {
|
|
3410
|
+
isError: false,
|
|
3411
|
+
details: { groups }
|
|
3412
|
+
};
|
|
3413
|
+
} catch (error) {
|
|
3288
3414
|
return {
|
|
3289
|
-
content: [{ type: "text", text:
|
|
3415
|
+
content: [{ type: "text", text: `Failed to list groups: ${getErrorMessage(error)}` }],
|
|
3290
3416
|
isError: true,
|
|
3291
3417
|
details: { error: true }
|
|
3292
3418
|
};
|
|
3293
3419
|
}
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
const
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3420
|
+
}
|
|
3421
|
+
case "list": {
|
|
3422
|
+
try {
|
|
3423
|
+
const mySessionId = connectedClient.sessionId;
|
|
3424
|
+
const ownDirectory = await listDirectory(connectedClient);
|
|
3425
|
+
const ownSessions = ownDirectory.sessions;
|
|
3426
|
+
const currentSession = ownSessions.find((session) => session.id === mySessionId);
|
|
3427
|
+
if (!currentSession) {
|
|
3428
|
+
return {
|
|
3429
|
+
content: [{ type: "text", text: "Current session is missing from intercom session list." }],
|
|
3430
|
+
isError: true,
|
|
3431
|
+
details: { error: true }
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
3434
|
+
const ownGroups = resolveOwnGroups(ownSessions);
|
|
3435
|
+
if (requestedGroup && !isOnlyOwnGroup(requestedGroup, ownGroups)) {
|
|
3436
|
+
const peeked = await listDirectory(connectedClient, requestedGroup);
|
|
3437
|
+
const rows = [
|
|
3438
|
+
...peeked.sessions.map((session) => formatSessionListRow(session, currentSession.cwd, session.id === mySessionId)),
|
|
3439
|
+
...peeked.workflowStages.map(formatWorkflowStageRow),
|
|
3440
|
+
...(peeked.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
|
|
3441
|
+
];
|
|
3442
|
+
const section = rows.length === 0 ? `**Group [${requestedGroup}] (read-only peek):**
|
|
3303
3443
|
No sessions or workflow stages in this group.` : `**Group [${requestedGroup}] (read-only peek):**
|
|
3304
3444
|
${rows.join(`
|
|
3305
3445
|
`)}`;
|
|
3306
|
-
|
|
3307
|
-
|
|
3446
|
+
return {
|
|
3447
|
+
content: [{ type: "text", text: `Your groups: ${ownGroups.join(", ")}
|
|
3308
3448
|
|
|
3309
3449
|
${section}` }],
|
|
3450
|
+
isError: false,
|
|
3451
|
+
details: {
|
|
3452
|
+
group: ownGroups.at(-1),
|
|
3453
|
+
groups: ownGroups,
|
|
3454
|
+
peekGroup: requestedGroup,
|
|
3455
|
+
workflowStages: peeked.workflowStages,
|
|
3456
|
+
...(peeked.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: peeked.workflowFutureStages }
|
|
3457
|
+
}
|
|
3458
|
+
};
|
|
3459
|
+
}
|
|
3460
|
+
const otherSessions = ownSessions.filter((session) => session.id !== mySessionId);
|
|
3461
|
+
const currentSection = `**Current session** (groups: ${ownGroups.join(", ")}):
|
|
3462
|
+
${formatSessionListRow(currentSession, currentSession.cwd, true)}`;
|
|
3463
|
+
const visibleRows = [
|
|
3464
|
+
...otherSessions.map((session) => formatSessionListRow(session, currentSession.cwd, false)),
|
|
3465
|
+
...ownDirectory.workflowStages.map(formatWorkflowStageRow),
|
|
3466
|
+
...(ownDirectory.workflowFutureStages ?? []).map(formatWorkflowFutureStageRow)
|
|
3467
|
+
];
|
|
3468
|
+
const otherSection = visibleRows.length === 0 ? `**Other sessions and workflow stages:**
|
|
3469
|
+
No other sessions or workflow stages share any of your groups.` : `**Other visible sessions and workflow stages:**
|
|
3470
|
+
${visibleRows.join(`
|
|
3471
|
+
`)}`;
|
|
3472
|
+
return {
|
|
3473
|
+
content: [{ type: "text", text: `${currentSection}
|
|
3474
|
+
|
|
3475
|
+
${otherSection}` }],
|
|
3310
3476
|
isError: false,
|
|
3311
3477
|
details: {
|
|
3312
3478
|
group: ownGroups.at(-1),
|
|
3313
3479
|
groups: ownGroups,
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
...(peeked.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: peeked.workflowFutureStages }
|
|
3480
|
+
...ownDirectory.workflowStages.length === 0 ? {} : { workflowStages: ownDirectory.workflowStages },
|
|
3481
|
+
...(ownDirectory.workflowFutureStages?.length ?? 0) === 0 ? {} : { workflowFutureStages: ownDirectory.workflowFutureStages }
|
|
3317
3482
|
}
|
|
3318
3483
|
};
|
|
3484
|
+
} catch (error) {
|
|
3485
|
+
return {
|
|
3486
|
+
content: [{ type: "text", text: `Failed to list sessions: ${getErrorMessage(error)}` }],
|
|
3487
|
+
isError: true,
|
|
3488
|
+
details: { error: true }
|
|
3489
|
+
};
|
|
3319
3490
|
}
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3491
|
+
}
|
|
3492
|
+
case "send": {
|
|
3493
|
+
if (!to || !message) {
|
|
3494
|
+
const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3495
|
+
return {
|
|
3496
|
+
content: [{ type: "text", text: errorText }],
|
|
3497
|
+
isError: true,
|
|
3498
|
+
details: { error: true }
|
|
3499
|
+
};
|
|
3500
|
+
}
|
|
3501
|
+
if (_signal?.aborted) {
|
|
3502
|
+
return {
|
|
3503
|
+
content: [{
|
|
3504
|
+
type: "text",
|
|
3505
|
+
text: "Cancelled"
|
|
3506
|
+
}],
|
|
3507
|
+
isError: true,
|
|
3508
|
+
details: retryErrorDetails(retryToken)
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3511
|
+
let retryIdentity;
|
|
3512
|
+
try {
|
|
3513
|
+
if (retryToken === undefined) {
|
|
3514
|
+
retryIdentity = retryIdentities.begin({
|
|
3515
|
+
sessionId: toolSessionId,
|
|
3516
|
+
action: "send",
|
|
3517
|
+
target: to,
|
|
3518
|
+
text: message,
|
|
3519
|
+
attachments,
|
|
3520
|
+
replyTo,
|
|
3521
|
+
expectsReply: false
|
|
3522
|
+
});
|
|
3523
|
+
}
|
|
3524
|
+
if (retryToken === undefined && !replyTo && deps.confirmSend && ctx.hasUI) {
|
|
3525
|
+
const attachmentText = attachments?.length ? formatAttachments(attachments) : "";
|
|
3526
|
+
const confirmed = await ctx.ui.confirm("Send Message", `Send to "${to}":
|
|
3334
3527
|
|
|
3335
|
-
${
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3528
|
+
${message}${attachmentText}`);
|
|
3529
|
+
if (!confirmed) {
|
|
3530
|
+
if (retryIdentity !== undefined)
|
|
3531
|
+
retryIdentities.release(retryIdentity);
|
|
3532
|
+
retryIdentity = undefined;
|
|
3533
|
+
return {
|
|
3534
|
+
content: [{ type: "text", text: "Message cancelled by user" }],
|
|
3535
|
+
isError: false,
|
|
3536
|
+
details: {}
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3342
3539
|
}
|
|
3343
|
-
|
|
3344
|
-
} catch (error) {
|
|
3345
|
-
return {
|
|
3346
|
-
content: [{ type: "text", text: `Failed to list sessions: ${getErrorMessage(error)}` }],
|
|
3347
|
-
isError: true,
|
|
3348
|
-
details: { error: true }
|
|
3349
|
-
};
|
|
3350
|
-
}
|
|
3351
|
-
}
|
|
3352
|
-
case "send": {
|
|
3353
|
-
if (!to || !message) {
|
|
3354
|
-
const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3355
|
-
return {
|
|
3356
|
-
content: [{ type: "text", text: errorText }],
|
|
3357
|
-
isError: true,
|
|
3358
|
-
details: { error: true }
|
|
3359
|
-
};
|
|
3360
|
-
}
|
|
3361
|
-
if (_signal?.aborted) {
|
|
3362
|
-
return {
|
|
3363
|
-
content: [{
|
|
3364
|
-
type: "text",
|
|
3365
|
-
text: `Cancelled${retryTokenGuidance(retryToken, retryPreflightRemaining ?? 0)}`
|
|
3366
|
-
}],
|
|
3367
|
-
isError: true,
|
|
3368
|
-
details: retryErrorDetails(retryToken)
|
|
3369
|
-
};
|
|
3370
|
-
}
|
|
3371
|
-
let retryIdentity;
|
|
3372
|
-
try {
|
|
3373
|
-
if (retryToken === undefined) {
|
|
3374
|
-
retryIdentity = retryIdentities.begin({
|
|
3540
|
+
retryIdentity ??= retryIdentities.begin({
|
|
3375
3541
|
sessionId: toolSessionId,
|
|
3376
3542
|
action: "send",
|
|
3377
3543
|
target: to,
|
|
@@ -3379,63 +3545,79 @@ ${otherSection}` }],
|
|
|
3379
3545
|
attachments,
|
|
3380
3546
|
replyTo,
|
|
3381
3547
|
expectsReply: false
|
|
3548
|
+
}, retryToken);
|
|
3549
|
+
const sendTo = await resolveTarget(connectedClient, to) ?? to;
|
|
3550
|
+
if (_signal?.aborted) {
|
|
3551
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3552
|
+
retryIdentity = undefined;
|
|
3553
|
+
return {
|
|
3554
|
+
content: [{ type: "text", text: "Cancelled" }],
|
|
3555
|
+
isError: true,
|
|
3556
|
+
details: retryErrorDetails(retained.retryToken)
|
|
3557
|
+
};
|
|
3558
|
+
}
|
|
3559
|
+
if (sendTo === connectedClient.sessionId) {
|
|
3560
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3561
|
+
retryIdentity = undefined;
|
|
3562
|
+
return {
|
|
3563
|
+
content: [{
|
|
3564
|
+
type: "text",
|
|
3565
|
+
text: "Cannot message the current session"
|
|
3566
|
+
}],
|
|
3567
|
+
isError: true,
|
|
3568
|
+
details: retryErrorDetails(retained.retryToken)
|
|
3569
|
+
};
|
|
3570
|
+
}
|
|
3571
|
+
const result = await connectedClient.send(sendTo, {
|
|
3572
|
+
messageId: retryIdentity.messageId,
|
|
3573
|
+
logicalTarget: to,
|
|
3574
|
+
text: message,
|
|
3575
|
+
attachments,
|
|
3576
|
+
replyTo
|
|
3382
3577
|
});
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
const attachmentText = attachments?.length ? formatAttachments(attachments) : "";
|
|
3386
|
-
const confirmed = await ctx.ui.confirm("Send Message", `Send to "${to}":
|
|
3387
|
-
|
|
3388
|
-
${message}${attachmentText}`);
|
|
3389
|
-
if (!confirmed) {
|
|
3390
|
-
if (retryIdentity !== undefined)
|
|
3391
|
-
retryIdentities.release(retryIdentity);
|
|
3578
|
+
if (result.queued === true) {
|
|
3579
|
+
retryIdentities.release(retryIdentity);
|
|
3392
3580
|
retryIdentity = undefined;
|
|
3581
|
+
pi.appendEntry("intercom_sent", {
|
|
3582
|
+
to,
|
|
3583
|
+
message: { text: message, attachments, replyTo },
|
|
3584
|
+
messageId: result.id,
|
|
3585
|
+
timestamp: Date.now()
|
|
3586
|
+
});
|
|
3587
|
+
const notInKnownSet = result.notInKnownSet === true;
|
|
3393
3588
|
return {
|
|
3394
|
-
content: [{
|
|
3589
|
+
content: [{
|
|
3590
|
+
type: "text",
|
|
3591
|
+
text: notInKnownSet ? `Message queued for ${to} (not in the workflow's known stage set; it will be delivered to every matching stage that starts before the run terminates)` : `Message queued for ${to}`
|
|
3592
|
+
}],
|
|
3395
3593
|
isError: false,
|
|
3396
|
-
details: {
|
|
3594
|
+
details: {
|
|
3595
|
+
messageId: result.id,
|
|
3596
|
+
delivered: false,
|
|
3597
|
+
queued: true,
|
|
3598
|
+
target: result.target,
|
|
3599
|
+
position: result.position,
|
|
3600
|
+
...notInKnownSet ? { notInKnownSet: true } : {}
|
|
3601
|
+
}
|
|
3602
|
+
};
|
|
3603
|
+
}
|
|
3604
|
+
if (!result.delivered) {
|
|
3605
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3606
|
+
retryIdentity = undefined;
|
|
3607
|
+
const errorText = result.reason ?? "Session may not exist or has disconnected.";
|
|
3608
|
+
return {
|
|
3609
|
+
content: [{
|
|
3610
|
+
type: "text",
|
|
3611
|
+
text: `Message to "${to}" was not delivered: ${errorText}`
|
|
3612
|
+
}],
|
|
3613
|
+
isError: true,
|
|
3614
|
+
details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
|
|
3615
|
+
delivered: false,
|
|
3616
|
+
reason: result.reason,
|
|
3617
|
+
...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
|
|
3618
|
+
}
|
|
3397
3619
|
};
|
|
3398
3620
|
}
|
|
3399
|
-
}
|
|
3400
|
-
retryIdentity ??= retryIdentities.begin({
|
|
3401
|
-
sessionId: toolSessionId,
|
|
3402
|
-
action: "send",
|
|
3403
|
-
target: to,
|
|
3404
|
-
text: message,
|
|
3405
|
-
attachments,
|
|
3406
|
-
replyTo,
|
|
3407
|
-
expectsReply: false
|
|
3408
|
-
}, retryToken);
|
|
3409
|
-
const sendTo = await resolveTarget(connectedClient, to) ?? to;
|
|
3410
|
-
if (_signal?.aborted) {
|
|
3411
|
-
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3412
|
-
retryIdentity = undefined;
|
|
3413
|
-
return {
|
|
3414
|
-
content: [{ type: "text", text: `Cancelled${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}` }],
|
|
3415
|
-
isError: true,
|
|
3416
|
-
details: retryErrorDetails(retained.retryToken)
|
|
3417
|
-
};
|
|
3418
|
-
}
|
|
3419
|
-
if (sendTo === connectedClient.sessionId) {
|
|
3420
|
-
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3421
|
-
retryIdentity = undefined;
|
|
3422
|
-
return {
|
|
3423
|
-
content: [{
|
|
3424
|
-
type: "text",
|
|
3425
|
-
text: `Cannot message the current session${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
|
|
3426
|
-
}],
|
|
3427
|
-
isError: true,
|
|
3428
|
-
details: retryErrorDetails(retained.retryToken)
|
|
3429
|
-
};
|
|
3430
|
-
}
|
|
3431
|
-
const result = await connectedClient.send(sendTo, {
|
|
3432
|
-
messageId: retryIdentity.messageId,
|
|
3433
|
-
logicalTarget: to,
|
|
3434
|
-
text: message,
|
|
3435
|
-
attachments,
|
|
3436
|
-
replyTo
|
|
3437
|
-
});
|
|
3438
|
-
if (result.queued === true) {
|
|
3439
3621
|
retryIdentities.release(retryIdentity);
|
|
3440
3622
|
retryIdentity = undefined;
|
|
3441
3623
|
pi.appendEntry("intercom_sent", {
|
|
@@ -3444,160 +3626,81 @@ ${message}${attachmentText}`);
|
|
|
3444
3626
|
messageId: result.id,
|
|
3445
3627
|
timestamp: Date.now()
|
|
3446
3628
|
});
|
|
3447
|
-
|
|
3629
|
+
if (replyTo)
|
|
3630
|
+
activeReplyTracker().markReplied(replyTo);
|
|
3448
3631
|
return {
|
|
3449
|
-
content: [{
|
|
3450
|
-
type: "text",
|
|
3451
|
-
text: notInKnownSet ? `Message queued for ${to} (not in the workflow's known stage set; it will be delivered to every matching stage that starts before the run terminates)` : `Message queued for ${to}`
|
|
3452
|
-
}],
|
|
3632
|
+
content: [{ type: "text", text: `Message sent to ${to}` }],
|
|
3453
3633
|
isError: false,
|
|
3454
|
-
details: {
|
|
3455
|
-
messageId: result.id,
|
|
3456
|
-
delivered: false,
|
|
3457
|
-
queued: true,
|
|
3458
|
-
target: result.target,
|
|
3459
|
-
position: result.position,
|
|
3460
|
-
...notInKnownSet ? { notInKnownSet: true } : {}
|
|
3461
|
-
}
|
|
3634
|
+
details: { messageId: result.id, delivered: true }
|
|
3462
3635
|
};
|
|
3463
|
-
}
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
retryIdentity
|
|
3467
|
-
|
|
3636
|
+
} catch (error) {
|
|
3637
|
+
let failure = error;
|
|
3638
|
+
let retained;
|
|
3639
|
+
if (retryIdentity !== undefined) {
|
|
3640
|
+
if (isRecoverableIntercomDisconnect(error)) {
|
|
3641
|
+
try {
|
|
3642
|
+
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
3643
|
+
} catch (retentionError) {
|
|
3644
|
+
failure = retentionError;
|
|
3645
|
+
}
|
|
3646
|
+
} else {
|
|
3647
|
+
retryIdentities.release(retryIdentity);
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3468
3650
|
return {
|
|
3469
3651
|
content: [{
|
|
3470
3652
|
type: "text",
|
|
3471
|
-
text: `
|
|
3653
|
+
text: `Failed to send: ${getErrorMessage(failure)}`
|
|
3472
3654
|
}],
|
|
3473
3655
|
isError: true,
|
|
3474
|
-
details:
|
|
3475
|
-
delivered: false,
|
|
3476
|
-
reason: result.reason,
|
|
3477
|
-
...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
|
|
3478
|
-
}
|
|
3656
|
+
details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error) }
|
|
3479
3657
|
};
|
|
3480
3658
|
}
|
|
3481
|
-
retryIdentities.release(retryIdentity);
|
|
3482
|
-
retryIdentity = undefined;
|
|
3483
|
-
pi.appendEntry("intercom_sent", {
|
|
3484
|
-
to,
|
|
3485
|
-
message: { text: message, attachments, replyTo },
|
|
3486
|
-
messageId: result.id,
|
|
3487
|
-
timestamp: Date.now()
|
|
3488
|
-
});
|
|
3489
|
-
if (replyTo)
|
|
3490
|
-
activeReplyTracker().markReplied(replyTo);
|
|
3491
|
-
return {
|
|
3492
|
-
content: [{ type: "text", text: `Message sent to ${to}` }],
|
|
3493
|
-
isError: false,
|
|
3494
|
-
details: { messageId: result.id, delivered: true }
|
|
3495
|
-
};
|
|
3496
|
-
} catch (error) {
|
|
3497
|
-
let failure = error;
|
|
3498
|
-
let retained;
|
|
3499
|
-
if (retryIdentity !== undefined) {
|
|
3500
|
-
if (isRecoverableIntercomDisconnect(error)) {
|
|
3501
|
-
try {
|
|
3502
|
-
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
3503
|
-
} catch (retentionError) {
|
|
3504
|
-
failure = retentionError;
|
|
3505
|
-
}
|
|
3506
|
-
} else {
|
|
3507
|
-
retryIdentities.release(retryIdentity);
|
|
3508
|
-
}
|
|
3509
|
-
}
|
|
3510
|
-
return {
|
|
3511
|
-
content: [{
|
|
3512
|
-
type: "text",
|
|
3513
|
-
text: `Failed to send: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
|
|
3514
|
-
}],
|
|
3515
|
-
isError: true,
|
|
3516
|
-
details: retryErrorDetails(retained?.retryToken)
|
|
3517
|
-
};
|
|
3518
|
-
}
|
|
3519
|
-
}
|
|
3520
|
-
case "ask": {
|
|
3521
|
-
if (!to) {
|
|
3522
|
-
const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3523
|
-
return {
|
|
3524
|
-
content: [{ type: "text", text: errorText }],
|
|
3525
|
-
isError: true,
|
|
3526
|
-
details: { error: true }
|
|
3527
|
-
};
|
|
3528
|
-
}
|
|
3529
|
-
if (_signal?.aborted) {
|
|
3530
|
-
return {
|
|
3531
|
-
content: [{
|
|
3532
|
-
type: "text",
|
|
3533
|
-
text: `Cancelled${retryTokenGuidance(retryToken, retryPreflightRemaining ?? 0)}`
|
|
3534
|
-
}],
|
|
3535
|
-
isError: true,
|
|
3536
|
-
details: retryErrorDetails(retryToken)
|
|
3537
|
-
};
|
|
3538
3659
|
}
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
if (retryToken !== undefined && !message)
|
|
3543
|
-
throw new RetryTokenError("mismatch");
|
|
3544
|
-
retryIdentity = retryIdentities.begin({
|
|
3545
|
-
sessionId: toolSessionId,
|
|
3546
|
-
action: "ask",
|
|
3547
|
-
target: to,
|
|
3548
|
-
text: message ?? "",
|
|
3549
|
-
attachments,
|
|
3550
|
-
replyTo,
|
|
3551
|
-
expectsReply: true
|
|
3552
|
-
}, retryToken);
|
|
3553
|
-
const metadata = getMetadata();
|
|
3554
|
-
const currentSupervisorId = connectedClient.supervisorSessionId ?? undefined;
|
|
3555
|
-
const metadataSupervisorId = metadata?.supervisor?.supervisorSessionId;
|
|
3556
|
-
const directParentTarget = Boolean(metadata && (to === metadata.orchestratorTarget || to === currentSupervisorId || to === metadataSupervisorId));
|
|
3557
|
-
const claimParentAsk = (resolvedTargetId) => Boolean(metadata && requestParentAskHandoff(pi.events, metadata, {
|
|
3558
|
-
kind: "intercom",
|
|
3559
|
-
question: typeof message === "string" ? message : "",
|
|
3560
|
-
attachments,
|
|
3561
|
-
resolvedTargetId
|
|
3562
|
-
}));
|
|
3563
|
-
if (retryToken === undefined && directParentTarget && claimParentAsk(currentSupervisorId ?? metadataSupervisorId ?? to)) {
|
|
3564
|
-
retryIdentities.release(retryIdentity);
|
|
3565
|
-
retryIdentity = undefined;
|
|
3660
|
+
case "ask": {
|
|
3661
|
+
if (!to) {
|
|
3662
|
+
const errorText = retryToken === undefined ? "Missing 'to' or 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3566
3663
|
return {
|
|
3567
|
-
content: [{ type: "text", text:
|
|
3568
|
-
isError: false,
|
|
3569
|
-
details: { yielded: true }
|
|
3570
|
-
};
|
|
3571
|
-
}
|
|
3572
|
-
const sendTo = await resolveTarget(connectedClient, to) ?? to;
|
|
3573
|
-
if (_signal?.aborted) {
|
|
3574
|
-
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3575
|
-
retryIdentity = undefined;
|
|
3576
|
-
return {
|
|
3577
|
-
content: [{
|
|
3578
|
-
type: "text",
|
|
3579
|
-
text: `Cancelled${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
|
|
3580
|
-
}],
|
|
3664
|
+
content: [{ type: "text", text: errorText }],
|
|
3581
3665
|
isError: true,
|
|
3582
|
-
details:
|
|
3666
|
+
details: { error: true }
|
|
3583
3667
|
};
|
|
3584
3668
|
}
|
|
3585
|
-
if (
|
|
3586
|
-
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3587
|
-
retryIdentity = undefined;
|
|
3669
|
+
if (_signal?.aborted) {
|
|
3588
3670
|
return {
|
|
3589
3671
|
content: [{
|
|
3590
3672
|
type: "text",
|
|
3591
|
-
text:
|
|
3673
|
+
text: "Cancelled"
|
|
3592
3674
|
}],
|
|
3593
3675
|
isError: true,
|
|
3594
|
-
details: retryErrorDetails(
|
|
3676
|
+
details: retryErrorDetails(retryToken)
|
|
3595
3677
|
};
|
|
3596
3678
|
}
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3679
|
+
let wait = null;
|
|
3680
|
+
let retryIdentity;
|
|
3681
|
+
let askDelivered = false;
|
|
3682
|
+
try {
|
|
3683
|
+
retryIdentity = retryIdentities.begin({
|
|
3684
|
+
sessionId: toolSessionId,
|
|
3685
|
+
action: "ask",
|
|
3686
|
+
target: to,
|
|
3687
|
+
text: message ?? "",
|
|
3688
|
+
attachments,
|
|
3689
|
+
replyTo,
|
|
3690
|
+
expectsReply: true
|
|
3691
|
+
}, retryToken);
|
|
3692
|
+
const metadata = getMetadata();
|
|
3693
|
+
const currentSupervisorId = connectedClient.supervisorSessionId ?? undefined;
|
|
3694
|
+
const metadataSupervisorId = metadata?.supervisor?.supervisorSessionId;
|
|
3695
|
+
const directParentTarget = Boolean(metadata && (to === metadata.orchestratorTarget || to === currentSupervisorId || to === metadataSupervisorId));
|
|
3696
|
+
let parentTarget = directParentTarget;
|
|
3697
|
+
const claimParentAsk = (resolvedTargetId) => Boolean(metadata && requestParentAskHandoff(pi.events, metadata, {
|
|
3698
|
+
kind: "intercom",
|
|
3699
|
+
question: typeof message === "string" ? message : "",
|
|
3700
|
+
attachments: params.attachments,
|
|
3701
|
+
resolvedTargetId
|
|
3702
|
+
}));
|
|
3703
|
+
if (retryToken === undefined && directParentTarget && claimParentAsk(currentSupervisorId ?? metadataSupervisorId ?? to)) {
|
|
3601
3704
|
retryIdentities.release(retryIdentity);
|
|
3602
3705
|
retryIdentity = undefined;
|
|
3603
3706
|
return {
|
|
@@ -3606,214 +3709,297 @@ ${message}${attachmentText}`);
|
|
|
3606
3709
|
details: { yielded: true }
|
|
3607
3710
|
};
|
|
3608
3711
|
}
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3712
|
+
const sendTo = await resolveTarget(connectedClient, to) ?? to;
|
|
3713
|
+
if (_signal?.aborted) {
|
|
3714
|
+
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3715
|
+
retryIdentity = undefined;
|
|
3716
|
+
return {
|
|
3717
|
+
content: [{
|
|
3718
|
+
type: "text",
|
|
3719
|
+
text: "Cancelled"
|
|
3720
|
+
}],
|
|
3721
|
+
isError: true,
|
|
3722
|
+
details: retryErrorDetails(retained?.retryToken)
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
if (sendTo === connectedClient.sessionId) {
|
|
3726
|
+
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3727
|
+
retryIdentity = undefined;
|
|
3728
|
+
return {
|
|
3729
|
+
content: [{
|
|
3730
|
+
type: "text",
|
|
3731
|
+
text: "Cannot message the current session"
|
|
3732
|
+
}],
|
|
3733
|
+
isError: true,
|
|
3734
|
+
details: retryErrorDetails(retained?.retryToken)
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
if (metadata && !directParentTarget) {
|
|
3738
|
+
const authoritativeParent = [currentSupervisorId, metadataSupervisorId].find((candidate) => candidate === sendTo);
|
|
3739
|
+
const resolvedParent = authoritativeParent ?? await resolveTarget(connectedClient, metadata.orchestratorTarget);
|
|
3740
|
+
parentTarget = resolvedParent !== null && resolvedParent === sendTo;
|
|
3741
|
+
if (retryToken === undefined && parentTarget && claimParentAsk(sendTo)) {
|
|
3742
|
+
retryIdentities.release(retryIdentity);
|
|
3743
|
+
retryIdentity = undefined;
|
|
3744
|
+
return {
|
|
3745
|
+
content: [{ type: "text", text: "Parent ask claimed; this child is ending for a fresh subagent start." }],
|
|
3746
|
+
isError: false,
|
|
3747
|
+
details: { yielded: true }
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
if (!message && !parentTarget) {
|
|
3752
|
+
retryIdentities.release(retryIdentity);
|
|
3753
|
+
retryIdentity = undefined;
|
|
3754
|
+
return {
|
|
3755
|
+
content: [{ type: "text", text: "Missing 'to' or 'message' parameter" }],
|
|
3756
|
+
isError: true,
|
|
3757
|
+
details: { error: true }
|
|
3758
|
+
};
|
|
3759
|
+
}
|
|
3760
|
+
const replySender = await resolveReplySender(connectedClient, to, sendTo);
|
|
3761
|
+
if (replySender.kind === "ambiguous") {
|
|
3762
|
+
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3763
|
+
retryIdentity = undefined;
|
|
3764
|
+
return {
|
|
3765
|
+
content: [{
|
|
3766
|
+
type: "text",
|
|
3767
|
+
text: `Message to "${to}" is ambiguous: ${replySender.reason}. Use the exact target shown by intercom list.`
|
|
3768
|
+
}],
|
|
3769
|
+
isError: true,
|
|
3770
|
+
details: retryErrorDetails(retained?.retryToken)
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3773
|
+
const questionId = retryIdentity.messageId;
|
|
3774
|
+
const replyFrom = replySender.kind === "resolved" ? replySender.sessionId : sendTo;
|
|
3775
|
+
const admission = beginReplyWait(replyFrom, questionId, _signal);
|
|
3776
|
+
if (!admission.ok) {
|
|
3777
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3778
|
+
retryIdentity = undefined;
|
|
3779
|
+
const text = admission.reason === "busy" ? `Too many pending asks (${admission.limit}); reply-wait slots are full` : "Cancelled";
|
|
3780
|
+
return {
|
|
3781
|
+
content: [{
|
|
3782
|
+
type: "text",
|
|
3783
|
+
text
|
|
3784
|
+
}],
|
|
3785
|
+
isError: true,
|
|
3786
|
+
details: retryErrorDetails(retained.retryToken)
|
|
3787
|
+
};
|
|
3788
|
+
}
|
|
3789
|
+
wait = admission.wait;
|
|
3790
|
+
const sendResult = await connectedClient.send(sendTo, {
|
|
3791
|
+
messageId: questionId,
|
|
3792
|
+
logicalTarget: to,
|
|
3793
|
+
text: message ?? "",
|
|
3794
|
+
attachments,
|
|
3795
|
+
replyTo,
|
|
3796
|
+
expectsReply: true,
|
|
3797
|
+
...parseWorkflowStageTarget(to)?.kind === "path" ? { onReplyTarget: wait.bindSender } : {}
|
|
3798
|
+
});
|
|
3799
|
+
if (sendResult.queued === true) {
|
|
3800
|
+
retryIdentities.release(retryIdentity);
|
|
3801
|
+
retryIdentity = undefined;
|
|
3802
|
+
wait.cancel(new Error(`Message queued for ${to}`));
|
|
3803
|
+
pi.appendEntry("intercom_sent", {
|
|
3804
|
+
to,
|
|
3805
|
+
message: { text: message, attachments, replyTo },
|
|
3806
|
+
messageId: sendResult.id,
|
|
3807
|
+
timestamp: Date.now()
|
|
3808
|
+
});
|
|
3809
|
+
return {
|
|
3810
|
+
content: [{ type: "text", text: `Message queued for ${to}` }],
|
|
3811
|
+
isError: false,
|
|
3812
|
+
details: {
|
|
3813
|
+
messageId: sendResult.id,
|
|
3814
|
+
delivered: false,
|
|
3815
|
+
queued: true,
|
|
3816
|
+
target: sendResult.target,
|
|
3817
|
+
position: sendResult.position
|
|
3818
|
+
}
|
|
3819
|
+
};
|
|
3820
|
+
}
|
|
3821
|
+
if (!sendResult.delivered) {
|
|
3822
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3823
|
+
retryIdentity = undefined;
|
|
3824
|
+
const errorText = sendResult.reason ?? "Session may not exist or has disconnected.";
|
|
3825
|
+
wait.cancel(new Error(`Message to "${to}" was not delivered: ${errorText}`));
|
|
3826
|
+
const pendingStageAskRefusal = errorText.startsWith("Cannot ask a workflow stage whose session has not initialized.");
|
|
3827
|
+
return {
|
|
3828
|
+
content: [{
|
|
3829
|
+
type: "text",
|
|
3830
|
+
text: `Message to "${to}" was not delivered: ${errorText}`
|
|
3831
|
+
}],
|
|
3832
|
+
isError: true,
|
|
3833
|
+
details: {
|
|
3834
|
+
...pendingStageAskRefusal ? {
|
|
3835
|
+
refusal: "pending_stage_ask_unsupported",
|
|
3836
|
+
recommendedAction: "send",
|
|
3837
|
+
reason: errorText
|
|
3838
|
+
} : {},
|
|
3839
|
+
...retryErrorDetails(retained.retryToken)
|
|
3840
|
+
}
|
|
3841
|
+
};
|
|
3842
|
+
}
|
|
3843
|
+
askDelivered = true;
|
|
3661
3844
|
pi.appendEntry("intercom_sent", {
|
|
3662
3845
|
to,
|
|
3663
3846
|
message: { text: message, attachments, replyTo },
|
|
3664
3847
|
messageId: sendResult.id,
|
|
3665
3848
|
timestamp: Date.now()
|
|
3666
3849
|
});
|
|
3850
|
+
const replyMessage = await wait.promise;
|
|
3851
|
+
retryIdentities.release(retryIdentity);
|
|
3852
|
+
retryIdentity = undefined;
|
|
3853
|
+
const replyText = replyMessage.content.text;
|
|
3854
|
+
const replyAttachments = replyMessage.content.attachments?.length ? formatAttachments(replyMessage.content.attachments) : "";
|
|
3855
|
+
pi.appendEntry("intercom_received", {
|
|
3856
|
+
from: to,
|
|
3857
|
+
message: { text: replyText, attachments: replyMessage.content.attachments },
|
|
3858
|
+
messageId: replyMessage.id,
|
|
3859
|
+
timestamp: replyMessage.timestamp
|
|
3860
|
+
});
|
|
3861
|
+
if (replyMessage.replyError !== undefined) {
|
|
3862
|
+
return {
|
|
3863
|
+
content: [{ type: "text", text: `Failed: ${replyMessage.replyError}` }],
|
|
3864
|
+
isError: true,
|
|
3865
|
+
details: { error: true, replyTo: replyMessage.replyTo }
|
|
3866
|
+
};
|
|
3867
|
+
}
|
|
3667
3868
|
return {
|
|
3668
|
-
content: [{ type: "text", text:
|
|
3869
|
+
content: [{ type: "text", text: `**Reply from ${to}:**
|
|
3870
|
+
${replyText}${replyAttachments}` }],
|
|
3669
3871
|
isError: false,
|
|
3670
|
-
details: {
|
|
3671
|
-
messageId: sendResult.id,
|
|
3672
|
-
delivered: false,
|
|
3673
|
-
queued: true,
|
|
3674
|
-
target: sendResult.target,
|
|
3675
|
-
position: sendResult.position
|
|
3676
|
-
}
|
|
3872
|
+
details: {}
|
|
3677
3873
|
};
|
|
3678
|
-
}
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3874
|
+
} catch (error) {
|
|
3875
|
+
wait?.cancel(toError3(error));
|
|
3876
|
+
let failure = error;
|
|
3877
|
+
let retained;
|
|
3878
|
+
if (retryIdentity !== undefined) {
|
|
3879
|
+
if (isRecoverableIntercomDisconnect(error)) {
|
|
3880
|
+
try {
|
|
3881
|
+
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
3882
|
+
} catch (retentionError) {
|
|
3883
|
+
failure = retentionError;
|
|
3884
|
+
}
|
|
3885
|
+
} else {
|
|
3886
|
+
retryIdentities.release(retryIdentity);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3685
3889
|
return {
|
|
3686
3890
|
content: [{
|
|
3687
3891
|
type: "text",
|
|
3688
|
-
text: `
|
|
3892
|
+
text: `Failed: ${getErrorMessage(failure)}`
|
|
3689
3893
|
}],
|
|
3690
3894
|
isError: true,
|
|
3691
|
-
details: {
|
|
3692
|
-
...pendingStageAskRefusal ? {
|
|
3693
|
-
refusal: "pending_stage_ask_unsupported",
|
|
3694
|
-
recommendedAction: "send",
|
|
3695
|
-
reason: errorText
|
|
3696
|
-
} : {},
|
|
3697
|
-
...retryErrorDetails(retained.retryToken)
|
|
3698
|
-
}
|
|
3699
|
-
};
|
|
3700
|
-
}
|
|
3701
|
-
pi.appendEntry("intercom_sent", {
|
|
3702
|
-
to,
|
|
3703
|
-
message: { text: message, attachments, replyTo },
|
|
3704
|
-
messageId: sendResult.id,
|
|
3705
|
-
timestamp: Date.now()
|
|
3706
|
-
});
|
|
3707
|
-
const replyMessage = await wait.promise;
|
|
3708
|
-
retryIdentities.release(retryIdentity);
|
|
3709
|
-
retryIdentity = undefined;
|
|
3710
|
-
const replyText = replyMessage.content.text;
|
|
3711
|
-
const replyAttachments = replyMessage.content.attachments?.length ? formatAttachments(replyMessage.content.attachments) : "";
|
|
3712
|
-
pi.appendEntry("intercom_received", {
|
|
3713
|
-
from: to,
|
|
3714
|
-
message: { text: replyText, attachments: replyMessage.content.attachments },
|
|
3715
|
-
messageId: replyMessage.id,
|
|
3716
|
-
timestamp: replyMessage.timestamp
|
|
3717
|
-
});
|
|
3718
|
-
if (replyMessage.replyError !== undefined) {
|
|
3719
|
-
return {
|
|
3720
|
-
content: [{ type: "text", text: `Failed: ${replyMessage.replyError}` }],
|
|
3721
|
-
isError: true,
|
|
3722
|
-
details: { error: true, replyTo: replyMessage.replyTo }
|
|
3895
|
+
details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error), deliveryUncertain: askDelivered }
|
|
3723
3896
|
};
|
|
3724
3897
|
}
|
|
3725
|
-
return {
|
|
3726
|
-
content: [{ type: "text", text: `**Reply from ${to}:**
|
|
3727
|
-
${replyText}${replyAttachments}` }],
|
|
3728
|
-
isError: false,
|
|
3729
|
-
details: {}
|
|
3730
|
-
};
|
|
3731
|
-
} catch (error) {
|
|
3732
|
-
wait?.cancel(toError3(error));
|
|
3733
|
-
let failure = error;
|
|
3734
|
-
let retained;
|
|
3735
|
-
if (retryIdentity !== undefined) {
|
|
3736
|
-
if (isRecoverableIntercomDisconnect(error)) {
|
|
3737
|
-
try {
|
|
3738
|
-
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
3739
|
-
} catch (retentionError) {
|
|
3740
|
-
failure = retentionError;
|
|
3741
|
-
}
|
|
3742
|
-
} else {
|
|
3743
|
-
retryIdentities.release(retryIdentity);
|
|
3744
|
-
}
|
|
3745
|
-
}
|
|
3746
|
-
return {
|
|
3747
|
-
content: [{
|
|
3748
|
-
type: "text",
|
|
3749
|
-
text: `Failed: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
|
|
3750
|
-
}],
|
|
3751
|
-
isError: true,
|
|
3752
|
-
details: retryErrorDetails(retained?.retryToken)
|
|
3753
|
-
};
|
|
3754
|
-
}
|
|
3755
|
-
}
|
|
3756
|
-
case "reply": {
|
|
3757
|
-
if (!message) {
|
|
3758
|
-
const errorText = retryToken === undefined ? "Missing 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3759
|
-
return {
|
|
3760
|
-
content: [{ type: "text", text: errorText }],
|
|
3761
|
-
isError: true,
|
|
3762
|
-
details: { error: true }
|
|
3763
|
-
};
|
|
3764
3898
|
}
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
sessionId: toolSessionId,
|
|
3769
|
-
action: "reply",
|
|
3770
|
-
target: to,
|
|
3771
|
-
text: message,
|
|
3772
|
-
attachments,
|
|
3773
|
-
replyTo,
|
|
3774
|
-
expectsReply: false
|
|
3775
|
-
}, retryToken);
|
|
3776
|
-
if (retryToken === undefined) {
|
|
3777
|
-
const target = activeReplyTracker().resolveReplyTarget({ to, replyTo });
|
|
3778
|
-
retryIdentities.bindReplyRoute(retryIdentity, {
|
|
3779
|
-
senderId: target.from.id,
|
|
3780
|
-
...target.from.name === undefined ? {} : { senderName: target.from.name },
|
|
3781
|
-
messageId: target.message.id,
|
|
3782
|
-
expectsReply: target.message.expectsReply === true
|
|
3783
|
-
});
|
|
3784
|
-
}
|
|
3785
|
-
const route = retryIdentities.replyRoute(retryIdentity);
|
|
3786
|
-
if (route === undefined)
|
|
3787
|
-
throw new RetryTokenError("invalid");
|
|
3788
|
-
const replySendTo = to ?? route.senderId;
|
|
3789
|
-
const replyLogicalTarget = to ?? route.senderId;
|
|
3790
|
-
const displayTarget = route.senderName || route.senderId;
|
|
3791
|
-
if (route.senderId === connectedClient.sessionId) {
|
|
3792
|
-
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3793
|
-
retryIdentity = undefined;
|
|
3899
|
+
case "reply": {
|
|
3900
|
+
if (!message) {
|
|
3901
|
+
const errorText = retryToken === undefined ? "Missing 'message' parameter" : getErrorMessage(new RetryTokenError("mismatch"));
|
|
3794
3902
|
return {
|
|
3795
|
-
content: [{
|
|
3796
|
-
type: "text",
|
|
3797
|
-
text: `Cannot message the current session${retryTokenGuidance(retained.retryToken, retained.remainingRetries)}`
|
|
3798
|
-
}],
|
|
3903
|
+
content: [{ type: "text", text: errorText }],
|
|
3799
3904
|
isError: true,
|
|
3800
|
-
details:
|
|
3905
|
+
details: { error: true }
|
|
3801
3906
|
};
|
|
3802
3907
|
}
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
messageId: replyMessageId,
|
|
3806
|
-
logicalTarget: replyLogicalTarget,
|
|
3807
|
-
...route.expectsReply ? { requirePendingReply: true } : {},
|
|
3808
|
-
text: message,
|
|
3809
|
-
attachments,
|
|
3810
|
-
replyTo: route.messageId
|
|
3811
|
-
});
|
|
3812
|
-
let result = await sendReply(replySendTo);
|
|
3813
|
-
if (to === undefined && result.delivered === false && result.reasonCode === "session_not_found" && route.senderName !== undefined) {
|
|
3814
|
-
result = await sendReply(route.senderName);
|
|
3908
|
+
if (_signal?.aborted) {
|
|
3909
|
+
return { content: [{ type: "text", text: "Cancelled" }], isError: true, details: retryErrorDetails(retryToken) };
|
|
3815
3910
|
}
|
|
3816
|
-
|
|
3911
|
+
let retryIdentity;
|
|
3912
|
+
try {
|
|
3913
|
+
retryIdentity = retryIdentities.begin({
|
|
3914
|
+
sessionId: toolSessionId,
|
|
3915
|
+
action: "reply",
|
|
3916
|
+
target: to,
|
|
3917
|
+
text: message,
|
|
3918
|
+
attachments,
|
|
3919
|
+
replyTo,
|
|
3920
|
+
expectsReply: false
|
|
3921
|
+
}, retryToken);
|
|
3922
|
+
if (retryToken === undefined) {
|
|
3923
|
+
const target = activeReplyTracker().resolveReplyTarget({ to, replyTo });
|
|
3924
|
+
retryIdentities.bindReplyRoute(retryIdentity, {
|
|
3925
|
+
senderId: target.from.id,
|
|
3926
|
+
...target.from.name === undefined ? {} : { senderName: target.from.name },
|
|
3927
|
+
messageId: target.message.id,
|
|
3928
|
+
expectsReply: target.message.expectsReply === true
|
|
3929
|
+
});
|
|
3930
|
+
}
|
|
3931
|
+
const route = retryIdentities.replyRoute(retryIdentity);
|
|
3932
|
+
if (route === undefined)
|
|
3933
|
+
throw new RetryTokenError("invalid");
|
|
3934
|
+
const replySendTo = to ?? route.senderId;
|
|
3935
|
+
const replyLogicalTarget = to ?? route.senderId;
|
|
3936
|
+
const displayTarget = route.senderName || route.senderId;
|
|
3937
|
+
if (route.senderId === connectedClient.sessionId) {
|
|
3938
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3939
|
+
retryIdentity = undefined;
|
|
3940
|
+
return {
|
|
3941
|
+
content: [{
|
|
3942
|
+
type: "text",
|
|
3943
|
+
text: "Cannot message the current session"
|
|
3944
|
+
}],
|
|
3945
|
+
isError: true,
|
|
3946
|
+
details: retryErrorDetails(retained.retryToken)
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3949
|
+
const replyMessageId = retryIdentity.messageId;
|
|
3950
|
+
const sendReply = (targetId) => connectedClient.send(targetId, {
|
|
3951
|
+
messageId: replyMessageId,
|
|
3952
|
+
logicalTarget: replyLogicalTarget,
|
|
3953
|
+
...route.expectsReply ? { requirePendingReply: true } : {},
|
|
3954
|
+
...to === undefined && replyTo === undefined ? {} : { expectedRecipientId: route.senderId },
|
|
3955
|
+
text: message,
|
|
3956
|
+
attachments,
|
|
3957
|
+
replyTo: route.messageId
|
|
3958
|
+
});
|
|
3959
|
+
let result = await sendReply(replySendTo);
|
|
3960
|
+
if (to === undefined && replyTo === undefined && result.delivered === false && result.reasonCode === "session_not_found" && route.senderName !== undefined) {
|
|
3961
|
+
result = await sendReply(route.senderName);
|
|
3962
|
+
}
|
|
3963
|
+
if (result.queued === true) {
|
|
3964
|
+
retryIdentities.release(retryIdentity);
|
|
3965
|
+
retryIdentity = undefined;
|
|
3966
|
+
activeReplyTracker().markReplied(route.messageId);
|
|
3967
|
+
pi.appendEntry("intercom_sent", {
|
|
3968
|
+
to: displayTarget,
|
|
3969
|
+
message: { text: message, attachments, replyTo: route.messageId },
|
|
3970
|
+
messageId: result.id,
|
|
3971
|
+
timestamp: Date.now()
|
|
3972
|
+
});
|
|
3973
|
+
return {
|
|
3974
|
+
content: [{ type: "text", text: `Reply queued for ${displayTarget}` }],
|
|
3975
|
+
isError: false,
|
|
3976
|
+
details: {
|
|
3977
|
+
messageId: result.id,
|
|
3978
|
+
delivered: false,
|
|
3979
|
+
queued: true,
|
|
3980
|
+
replyTo: route.messageId,
|
|
3981
|
+
target: result.target,
|
|
3982
|
+
position: result.position
|
|
3983
|
+
}
|
|
3984
|
+
};
|
|
3985
|
+
}
|
|
3986
|
+
if (!result.delivered) {
|
|
3987
|
+
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3988
|
+
retryIdentity = undefined;
|
|
3989
|
+
const errorText = result.reason ?? "Session may not exist or has disconnected.";
|
|
3990
|
+
return {
|
|
3991
|
+
content: [{
|
|
3992
|
+
type: "text",
|
|
3993
|
+
text: `Reply to "${displayTarget}" was not delivered: ${errorText}`
|
|
3994
|
+
}],
|
|
3995
|
+
isError: true,
|
|
3996
|
+
details: retryToken === undefined ? { messageId: result.id, delivered: false, reason: result.reason } : {
|
|
3997
|
+
delivered: false,
|
|
3998
|
+
reason: result.reason,
|
|
3999
|
+
...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
|
|
4000
|
+
}
|
|
4001
|
+
};
|
|
4002
|
+
}
|
|
3817
4003
|
retryIdentities.release(retryIdentity);
|
|
3818
4004
|
retryIdentity = undefined;
|
|
3819
4005
|
activeReplyTracker().markReplied(route.messageId);
|
|
@@ -3824,136 +4010,101 @@ ${replyText}${replyAttachments}` }],
|
|
|
3824
4010
|
timestamp: Date.now()
|
|
3825
4011
|
});
|
|
3826
4012
|
return {
|
|
3827
|
-
content: [{ type: "text", text: `Reply
|
|
4013
|
+
content: [{ type: "text", text: `Reply sent to ${displayTarget}` }],
|
|
3828
4014
|
isError: false,
|
|
3829
|
-
details: {
|
|
3830
|
-
messageId: result.id,
|
|
3831
|
-
delivered: false,
|
|
3832
|
-
queued: true,
|
|
3833
|
-
replyTo: route.messageId,
|
|
3834
|
-
target: result.target,
|
|
3835
|
-
position: result.position
|
|
3836
|
-
}
|
|
4015
|
+
details: { messageId: result.id, delivered: true, replyTo: route.messageId }
|
|
3837
4016
|
};
|
|
3838
|
-
}
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
retryIdentity
|
|
3842
|
-
|
|
4017
|
+
} catch (error) {
|
|
4018
|
+
let failure = error;
|
|
4019
|
+
let retained;
|
|
4020
|
+
if (retryIdentity !== undefined) {
|
|
4021
|
+
if (isRecoverableIntercomDisconnect(error)) {
|
|
4022
|
+
try {
|
|
4023
|
+
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
4024
|
+
} catch (retentionError) {
|
|
4025
|
+
failure = retentionError;
|
|
4026
|
+
}
|
|
4027
|
+
} else {
|
|
4028
|
+
retryIdentities.release(retryIdentity);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
3843
4031
|
return {
|
|
3844
4032
|
content: [{
|
|
3845
4033
|
type: "text",
|
|
3846
|
-
text: `
|
|
4034
|
+
text: `Failed to reply: ${getErrorMessage(failure)}`
|
|
3847
4035
|
}],
|
|
3848
4036
|
isError: true,
|
|
3849
|
-
details:
|
|
3850
|
-
delivered: false,
|
|
3851
|
-
reason: result.reason,
|
|
3852
|
-
...retained.retryToken === undefined ? {} : { retryToken: retained.retryToken }
|
|
3853
|
-
}
|
|
4037
|
+
details: { ...retryErrorDetails(retained?.retryToken), retryable: isRecoverableIntercomDisconnect(error) }
|
|
3854
4038
|
};
|
|
3855
4039
|
}
|
|
3856
|
-
retryIdentities.release(retryIdentity);
|
|
3857
|
-
retryIdentity = undefined;
|
|
3858
|
-
activeReplyTracker().markReplied(route.messageId);
|
|
3859
|
-
pi.appendEntry("intercom_sent", {
|
|
3860
|
-
to: displayTarget,
|
|
3861
|
-
message: { text: message, attachments, replyTo: route.messageId },
|
|
3862
|
-
messageId: result.id,
|
|
3863
|
-
timestamp: Date.now()
|
|
3864
|
-
});
|
|
3865
|
-
return {
|
|
3866
|
-
content: [{ type: "text", text: `Reply sent to ${displayTarget}` }],
|
|
3867
|
-
isError: false,
|
|
3868
|
-
details: { messageId: result.id, delivered: true, replyTo: route.messageId }
|
|
3869
|
-
};
|
|
3870
|
-
} catch (error) {
|
|
3871
|
-
let failure = error;
|
|
3872
|
-
let retained;
|
|
3873
|
-
if (retryIdentity !== undefined) {
|
|
3874
|
-
if (isRecoverableIntercomDisconnect(error)) {
|
|
3875
|
-
try {
|
|
3876
|
-
retained = retainRecoverableRetry(retryIdentities, retryIdentity);
|
|
3877
|
-
} catch (retentionError) {
|
|
3878
|
-
failure = retentionError;
|
|
3879
|
-
}
|
|
3880
|
-
} else {
|
|
3881
|
-
retryIdentities.release(retryIdentity);
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
return {
|
|
3885
|
-
content: [{
|
|
3886
|
-
type: "text",
|
|
3887
|
-
text: `Failed to reply: ${getErrorMessage(failure)}${retryTokenGuidance(retained?.retryToken, retained?.remainingRetries ?? 0)}`
|
|
3888
|
-
}],
|
|
3889
|
-
isError: true,
|
|
3890
|
-
details: retryErrorDetails(retained?.retryToken)
|
|
3891
|
-
};
|
|
3892
4040
|
}
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
4041
|
+
case "pending": {
|
|
4042
|
+
const pendingAsks = activeReplyTracker().listPending();
|
|
4043
|
+
if (pendingAsks.length === 0) {
|
|
4044
|
+
return {
|
|
4045
|
+
content: [{ type: "text", text: "No unresolved inbound asks." }],
|
|
4046
|
+
isError: false,
|
|
4047
|
+
details: {}
|
|
4048
|
+
};
|
|
4049
|
+
}
|
|
4050
|
+
const now = Date.now();
|
|
4051
|
+
const lines = pendingAsks.map(({ from, message, receivedAt }) => {
|
|
4052
|
+
const preview = message.content.text.replace(/\s+/g, " ").slice(0, 80);
|
|
4053
|
+
const elapsedSeconds = Math.max(0, Math.floor((now - receivedAt) / 1000));
|
|
4054
|
+
return `- ${from.name || from.id} · ${message.id} · ${elapsedSeconds}s ago · ${preview}`;
|
|
4055
|
+
});
|
|
3897
4056
|
return {
|
|
3898
|
-
content: [{ type: "text", text:
|
|
4057
|
+
content: [{ type: "text", text: `**Pending asks:**
|
|
4058
|
+
${lines.join(`
|
|
4059
|
+
`)}` }],
|
|
3899
4060
|
isError: false,
|
|
3900
4061
|
details: {}
|
|
3901
4062
|
};
|
|
3902
4063
|
}
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
${lines.join(`
|
|
3912
|
-
`)}` }],
|
|
3913
|
-
isError: false,
|
|
3914
|
-
details: {}
|
|
3915
|
-
};
|
|
3916
|
-
}
|
|
3917
|
-
case "status": {
|
|
3918
|
-
try {
|
|
3919
|
-
const mySessionId = connectedClient.sessionId;
|
|
3920
|
-
const sessions = await connectedClient.listSessions();
|
|
3921
|
-
const ownGroups = resolveOwnGroups(sessions);
|
|
3922
|
-
const selectedGroup = isOnlyOwnGroup(requestedGroup, ownGroups) ? undefined : requestedGroup;
|
|
3923
|
-
const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
|
|
3924
|
-
const selectedSection = selectedGroupSessions === undefined ? "" : `
|
|
4064
|
+
case "status": {
|
|
4065
|
+
try {
|
|
4066
|
+
const mySessionId = connectedClient.sessionId;
|
|
4067
|
+
const sessions = await connectedClient.listSessions();
|
|
4068
|
+
const ownGroups = resolveOwnGroups(sessions);
|
|
4069
|
+
const selectedGroup = isOnlyOwnGroup(requestedGroup, ownGroups) ? undefined : requestedGroup;
|
|
4070
|
+
const selectedGroupSessions = selectedGroup === undefined ? undefined : await connectedClient.listSessions(selectedGroup);
|
|
4071
|
+
const selectedSection = selectedGroupSessions === undefined ? "" : `
|
|
3925
4072
|
Selected group [${selectedGroup}]: ${selectedGroupSessions.length} session(s)`;
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
4073
|
+
return {
|
|
4074
|
+
content: [{
|
|
4075
|
+
type: "text",
|
|
4076
|
+
text: `**Intercom Status:**
|
|
3930
4077
|
Connected: Yes
|
|
3931
4078
|
Session ID: ${mySessionId}
|
|
3932
4079
|
Groups: ${ownGroups.join(", ")}
|
|
3933
4080
|
Active visible sessions: ${sessions.length}${selectedSection}`
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
4081
|
+
}],
|
|
4082
|
+
isError: false,
|
|
4083
|
+
details: {
|
|
4084
|
+
group: ownGroups.at(-1),
|
|
4085
|
+
groups: ownGroups,
|
|
4086
|
+
...selectedGroup === undefined ? {} : { selectedGroup, selectedGroupSessionCount: selectedGroupSessions?.length ?? 0 }
|
|
4087
|
+
}
|
|
4088
|
+
};
|
|
4089
|
+
} catch (error) {
|
|
4090
|
+
return {
|
|
4091
|
+
content: [{ type: "text", text: `Failed to get status: ${getErrorMessage(error)}` }],
|
|
4092
|
+
isError: true,
|
|
4093
|
+
details: { error: true }
|
|
4094
|
+
};
|
|
4095
|
+
}
|
|
4096
|
+
}
|
|
4097
|
+
default:
|
|
3943
4098
|
return {
|
|
3944
|
-
content: [{ type: "text", text: `
|
|
4099
|
+
content: [{ type: "text", text: `Unknown action: ${action}` }],
|
|
3945
4100
|
isError: true,
|
|
3946
4101
|
details: { error: true }
|
|
3947
4102
|
};
|
|
3948
|
-
}
|
|
3949
4103
|
}
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
details: { error: true }
|
|
3955
|
-
};
|
|
3956
|
-
}
|
|
4104
|
+
};
|
|
4105
|
+
if (action !== "send" && action !== "ask" && action !== "reply")
|
|
4106
|
+
return executeAttempt(undefined, signal);
|
|
4107
|
+
return runIntercomOperation(executeAttempt, (token) => retryIdentities.discard(token), signal);
|
|
3957
4108
|
},
|
|
3958
4109
|
renderCall(args, theme) {
|
|
3959
4110
|
const action = typeof args.action === "string" ? args.action : "intercom";
|
|
@@ -3985,6 +4136,7 @@ var init_intercom_tool = __esm(() => {
|
|
|
3985
4136
|
init_workflow_stage_target();
|
|
3986
4137
|
init_recoverable_disconnect();
|
|
3987
4138
|
init_retry_identity();
|
|
4139
|
+
init_tool_retry();
|
|
3988
4140
|
});
|
|
3989
4141
|
|
|
3990
4142
|
// dist/builtin/intercom/ui/compose.ts
|
|
@@ -4375,7 +4527,10 @@ var init_overlay = __esm(() => {
|
|
|
4375
4527
|
function registerIntercomLifecycle(pi, deps) {
|
|
4376
4528
|
const activeReplyTracker = () => typeof deps.replyTracker === "function" ? deps.replyTracker() : deps.replyTracker;
|
|
4377
4529
|
let hasActiveSession = false;
|
|
4530
|
+
let unbindStageClose;
|
|
4378
4531
|
async function cleanupRuntime(reason) {
|
|
4532
|
+
unbindStageClose?.();
|
|
4533
|
+
unbindStageClose = undefined;
|
|
4379
4534
|
deps.setRuntimeStarted(false);
|
|
4380
4535
|
deps.setShuttingDown(true);
|
|
4381
4536
|
deps.setDisposed(true);
|
|
@@ -4426,6 +4581,12 @@ function registerIntercomLifecycle(pi, deps) {
|
|
|
4426
4581
|
deps.setSessionStartedAt(Date.now());
|
|
4427
4582
|
deps.setAgentRunning(false);
|
|
4428
4583
|
deps.activeTools.clear();
|
|
4584
|
+
const stage = ctx.orchestrationContext;
|
|
4585
|
+
const closeSignal = stage?.kind === "workflow-stage" ? stage.messageAdmission?.boundary?.closeSignal : undefined;
|
|
4586
|
+
closeSignal?.addEventListener("abort", deps.syncPresenceStatus, { once: true });
|
|
4587
|
+
unbindStageClose = () => closeSignal?.removeEventListener("abort", deps.syncPresenceStatus);
|
|
4588
|
+
if (closeSignal?.aborted)
|
|
4589
|
+
deps.syncPresenceStatus();
|
|
4429
4590
|
});
|
|
4430
4591
|
pi.on("session_shutdown", async () => {
|
|
4431
4592
|
if (!hasActiveSession)
|
|
@@ -4433,10 +4594,15 @@ function registerIntercomLifecycle(pi, deps) {
|
|
|
4433
4594
|
hasActiveSession = false;
|
|
4434
4595
|
await cleanupRuntime("Session shutting down");
|
|
4435
4596
|
});
|
|
4436
|
-
pi.on("turn_end", () => {
|
|
4597
|
+
pi.on("turn_end", (event) => {
|
|
4437
4598
|
if (!deps.getLiveContext())
|
|
4438
4599
|
return;
|
|
4439
|
-
|
|
4600
|
+
const message = event.message;
|
|
4601
|
+
const cancelledBeforeReply = message?.role === "assistant" && message.stopReason === "aborted" && message.content?.length === 0;
|
|
4602
|
+
if (cancelledBeforeReply)
|
|
4603
|
+
activeReplyTracker().restoreTurnContext();
|
|
4604
|
+
else
|
|
4605
|
+
activeReplyTracker().endTurn();
|
|
4440
4606
|
deps.scheduleInboundFlush();
|
|
4441
4607
|
});
|
|
4442
4608
|
pi.on("agent_start", () => {
|
|
@@ -4564,12 +4730,12 @@ function prepareDurableAuthority(storagePath) {
|
|
|
4564
4730
|
if (databaseExists !== keyExists)
|
|
4565
4731
|
return;
|
|
4566
4732
|
if (!databaseExists) {
|
|
4567
|
-
const
|
|
4568
|
-
writeFileSync2(keyPath,
|
|
4733
|
+
const key = randomBytes(AUTHORITY_KEY_BYTES);
|
|
4734
|
+
writeFileSync2(keyPath, key, { flag: "wx", mode: 384 });
|
|
4569
4735
|
const databaseDescriptor = openSync2(storagePath, "wx", 384);
|
|
4570
4736
|
closeSync2(databaseDescriptor);
|
|
4571
4737
|
restrictExistingAuthorityArtifacts(storagePath, keyPath);
|
|
4572
|
-
return
|
|
4738
|
+
return key;
|
|
4573
4739
|
}
|
|
4574
4740
|
const key = readFileSync3(keyPath);
|
|
4575
4741
|
if (key.length !== AUTHORITY_KEY_BYTES)
|
|
@@ -4878,7 +5044,7 @@ function parseBarrier(value) {
|
|
|
4878
5044
|
return null;
|
|
4879
5045
|
if (typeof record.terminalAt !== "number" || !Number.isFinite(record.terminalAt))
|
|
4880
5046
|
return null;
|
|
4881
|
-
if (record.source !== "detached-notify" && record.source !== "result-relay")
|
|
5047
|
+
if (record.source !== "detached-notify" && record.source !== "result-relay" && record.source !== "owner-task")
|
|
4882
5048
|
return null;
|
|
4883
5049
|
if (!Array.isArray(record.sourceSessionTargets))
|
|
4884
5050
|
return null;
|
|
@@ -4954,11 +5120,17 @@ function registerTerminalOrderingBarrier(pi, options) {
|
|
|
4954
5120
|
envelope.completion = currentOwner;
|
|
4955
5121
|
return;
|
|
4956
5122
|
}
|
|
4957
|
-
const drainedTargets = drainedTargetsByTerminal.get(terminalKey) ?? new Set;
|
|
5123
|
+
const drainedTargets = barrier.source === "owner-task" ? new Set : drainedTargetsByTerminal.get(terminalKey) ?? new Set;
|
|
4958
5124
|
const pendingTargets = barrier.sourceSessionTargets.filter((target) => !drainedTargets.has(target));
|
|
4959
5125
|
if (pendingTargets.length === 0)
|
|
4960
5126
|
return;
|
|
4961
5127
|
const claim = options.queue.claimOrdinarySourceTargets(barrier.runId, pendingTargets, barrier.terminalAt);
|
|
5128
|
+
const deliverPrelude = (entry) => {
|
|
5129
|
+
if (!claim.isCurrent() || options.isCurrent?.() === false) {
|
|
5130
|
+
throw new Error("Intercom terminal delivery owner retired");
|
|
5131
|
+
}
|
|
5132
|
+
return options.deliver(entry, "prelude");
|
|
5133
|
+
};
|
|
4962
5134
|
const ownership = Promise.withResolvers();
|
|
4963
5135
|
ownership.promise.catch(() => {});
|
|
4964
5136
|
inFlightByTerminal.set(terminalKey, ownership.promise);
|
|
@@ -4968,7 +5140,7 @@ function registerTerminalOrderingBarrier(pi, options) {
|
|
|
4968
5140
|
ownership.reject(error);
|
|
4969
5141
|
};
|
|
4970
5142
|
const finish = () => {
|
|
4971
|
-
if (barrier.dispatch && options.toMessage || claim.entries.length > 0) {
|
|
5143
|
+
if (barrier.source !== "owner-task" && (barrier.dispatch && options.toMessage || claim.entries.length > 0)) {
|
|
4972
5144
|
for (const target of pendingTargets)
|
|
4973
5145
|
drainedTargets.add(target);
|
|
4974
5146
|
drainedTargetsByTerminal.set(terminalKey, drainedTargets);
|
|
@@ -5019,7 +5191,7 @@ function registerTerminalOrderingBarrier(pi, options) {
|
|
|
5019
5191
|
let delivered;
|
|
5020
5192
|
let deliveredAsync;
|
|
5021
5193
|
try {
|
|
5022
|
-
delivered =
|
|
5194
|
+
delivered = deliverPrelude(claim.entries[index]);
|
|
5023
5195
|
deliveredAsync = isPromiseLike(delivered);
|
|
5024
5196
|
} catch (error) {
|
|
5025
5197
|
if (barrier.owner)
|
|
@@ -5035,7 +5207,7 @@ function registerTerminalOrderingBarrier(pi, options) {
|
|
|
5035
5207
|
try {
|
|
5036
5208
|
await delivered;
|
|
5037
5209
|
for (current = index + 1;current < claim.entries.length; current++) {
|
|
5038
|
-
await
|
|
5210
|
+
await deliverPrelude(claim.entries[current]);
|
|
5039
5211
|
}
|
|
5040
5212
|
finish();
|
|
5041
5213
|
} catch (error) {
|
|
@@ -5111,7 +5283,7 @@ async function dispatchRelayFallback(pi, prefix, terminalMessage, stageAdmission
|
|
|
5111
5283
|
}
|
|
5112
5284
|
}
|
|
5113
5285
|
function registerSubagentRelay(pi, deps) {
|
|
5114
|
-
const { getLiveContext, currentSessionTargetMatches, sendIncomingMessage, ensureConnected, resolveSessionTarget
|
|
5286
|
+
const { getLiveContext, currentSessionTargetMatches, sendIncomingMessage, ensureConnected, resolveSessionTarget } = deps;
|
|
5115
5287
|
const localDeliveries = deps.localDeliveryAuthority ?? new DeliveredMessageCache;
|
|
5116
5288
|
function deliverLocalSubagentRelayMessage(sender, status, messageText, terminalBarrier, requestId) {
|
|
5117
5289
|
const now = Date.now();
|
|
@@ -5268,7 +5440,7 @@ ${messageText}`,
|
|
|
5268
5440
|
let target;
|
|
5269
5441
|
try {
|
|
5270
5442
|
activeClient = await ensureConnected("background");
|
|
5271
|
-
target = await
|
|
5443
|
+
target = await resolveSessionTarget(activeClient, parsed.to) ?? parsed.to;
|
|
5272
5444
|
} catch (error) {
|
|
5273
5445
|
if (!relayStillLive()) {
|
|
5274
5446
|
acknowledgeResult(options, parsed.requestId, false, error);
|
|
@@ -5522,7 +5694,7 @@ function createIncomingMessageSender(input) {
|
|
|
5522
5694
|
if (!input.canDeliver(generation)) {
|
|
5523
5695
|
return Promise.reject(new Error("Intercom session retired before inbound delivery"));
|
|
5524
5696
|
}
|
|
5525
|
-
if (delivery === "trigger" && trackReplyContext) {
|
|
5697
|
+
if ((delivery === "trigger" || delivery === "interrupt") && trackReplyContext) {
|
|
5526
5698
|
input.queueTurnContext(turnContext ?? { from: entry.from, message: entry.message, receivedAt: Date.now() });
|
|
5527
5699
|
}
|
|
5528
5700
|
const baseOptions = {
|
|
@@ -5530,7 +5702,7 @@ function createIncomingMessageSender(input) {
|
|
|
5530
5702
|
persistWhenStreaming: true,
|
|
5531
5703
|
...stageAdmissionBarrier ? { stageAdmissionBarrier } : {}
|
|
5532
5704
|
};
|
|
5533
|
-
const options = delivery === "trigger" ? { ...baseOptions, triggerTurn: true } : delivery === "followUp" ? { ...baseOptions, deliverAs: "followUp" } : baseOptions;
|
|
5705
|
+
const options = delivery === "interrupt" ? { ...baseOptions, triggerTurn: true, deliverAs: "interrupt" } : delivery === "trigger" ? { ...baseOptions, triggerTurn: true } : delivery === "followUp" ? { ...baseOptions, deliverAs: "followUp" } : baseOptions;
|
|
5534
5706
|
return Promise.resolve(input.pi.sendMessage(buildIncomingCustomMessage(entry), options));
|
|
5535
5707
|
};
|
|
5536
5708
|
}
|
|
@@ -5545,6 +5717,20 @@ function framePreStartPendingStageMessage(entry) {
|
|
|
5545
5717
|
|
|
5546
5718
|
Sent: ${framePendingStageTimestamp(entry.message.timestamp)}
|
|
5547
5719
|
|
|
5720
|
+
${entry.bodyText}`
|
|
5721
|
+
};
|
|
5722
|
+
}
|
|
5723
|
+
function isDeliveryFeedback(message) {
|
|
5724
|
+
return Boolean(message.replyTo) && message.replyError !== undefined;
|
|
5725
|
+
}
|
|
5726
|
+
function frameDeliveryFeedback(entry) {
|
|
5727
|
+
return {
|
|
5728
|
+
...entry,
|
|
5729
|
+
replyCommand: undefined,
|
|
5730
|
+
bodyText: `**Intercom delivery failed**
|
|
5731
|
+
|
|
5732
|
+
Sent: ${framePendingStageTimestamp(entry.message.timestamp)}
|
|
5733
|
+
|
|
5548
5734
|
${entry.bodyText}`
|
|
5549
5735
|
};
|
|
5550
5736
|
}
|
|
@@ -5566,6 +5752,7 @@ ${entry.bodyText}`,
|
|
|
5566
5752
|
// dist/builtin/intercom/inbound-idle-queue.ts
|
|
5567
5753
|
class InboundIdleQueue {
|
|
5568
5754
|
entries = [];
|
|
5755
|
+
generation = 0;
|
|
5569
5756
|
get size() {
|
|
5570
5757
|
return this.entries.length;
|
|
5571
5758
|
}
|
|
@@ -5589,6 +5776,7 @@ class InboundIdleQueue {
|
|
|
5589
5776
|
}
|
|
5590
5777
|
claimOrdinarySourceTargets(runId, sourceSessionTargets, terminalAt = Number.POSITIVE_INFINITY) {
|
|
5591
5778
|
const targets = new Set(sourceSessionTargets);
|
|
5779
|
+
const generation = this.generation;
|
|
5592
5780
|
const original = this.entries;
|
|
5593
5781
|
const legacyIdsByName = new Map;
|
|
5594
5782
|
for (const entry of original) {
|
|
@@ -5618,8 +5806,9 @@ class InboundIdleQueue {
|
|
|
5618
5806
|
let settled = false;
|
|
5619
5807
|
return {
|
|
5620
5808
|
entries: selected,
|
|
5809
|
+
isCurrent: () => generation === this.generation,
|
|
5621
5810
|
rollbackFrom: (index) => {
|
|
5622
|
-
if (settled)
|
|
5811
|
+
if (settled || generation !== this.generation)
|
|
5623
5812
|
return;
|
|
5624
5813
|
settled = true;
|
|
5625
5814
|
const undelivered = new Set(selected.slice(index));
|
|
@@ -5629,6 +5818,7 @@ class InboundIdleQueue {
|
|
|
5629
5818
|
};
|
|
5630
5819
|
}
|
|
5631
5820
|
clear() {
|
|
5821
|
+
this.generation++;
|
|
5632
5822
|
this.entries = [];
|
|
5633
5823
|
}
|
|
5634
5824
|
}
|
|
@@ -5864,13 +6054,15 @@ function retryStableDelivery(options) {
|
|
|
5864
6054
|
function admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailure) {
|
|
5865
6055
|
if (ctx.orchestrationContext?.kind !== "workflow-stage")
|
|
5866
6056
|
return false;
|
|
6057
|
+
const boundary = ctx.orchestrationContext.messageAdmission?.boundary;
|
|
6058
|
+
const run = (barrier) => boundary?.runMessageDelivery(() => deliver(barrier), () => deliver(), true) ?? Promise.resolve(deliver(barrier));
|
|
5867
6059
|
try {
|
|
5868
6060
|
let busy = false;
|
|
5869
6061
|
try {
|
|
5870
6062
|
busy = ctx.isIdle?.() === false;
|
|
5871
6063
|
} catch {}
|
|
5872
6064
|
if (!busy || !firstRefusal)
|
|
5873
|
-
return
|
|
6065
|
+
return run();
|
|
5874
6066
|
let firstRefusalPromise;
|
|
5875
6067
|
const admissionBarrier = () => {
|
|
5876
6068
|
firstRefusalPromise ??= (async () => {
|
|
@@ -5883,12 +6075,29 @@ function admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailur
|
|
|
5883
6075
|
})();
|
|
5884
6076
|
return firstRefusalPromise;
|
|
5885
6077
|
};
|
|
5886
|
-
return
|
|
6078
|
+
return run(admissionBarrier);
|
|
5887
6079
|
} catch (error) {
|
|
5888
6080
|
return Promise.reject(error);
|
|
5889
6081
|
}
|
|
5890
6082
|
}
|
|
5891
6083
|
|
|
6084
|
+
// dist/builtin/intercom/active-session-admission.ts
|
|
6085
|
+
function admitActiveSessionInbound(ctx, deliver, firstRefusal, onAdmissionFailure) {
|
|
6086
|
+
const executionEnded = ctx.subagentPolicy?.executionEnded;
|
|
6087
|
+
if (executionEnded !== undefined) {
|
|
6088
|
+
if (executionEnded.aborted || ctx.subagentPolicy?.messageAdmission?.isOpen() === false) {
|
|
6089
|
+
return Promise.reject(new Error("Subagent execution is terminal and cannot accept messages"));
|
|
6090
|
+
}
|
|
6091
|
+
try {
|
|
6092
|
+
return ctx.subagentPolicy?.messageAdmission?.run(deliver) ?? Promise.resolve(deliver());
|
|
6093
|
+
} catch (error) {
|
|
6094
|
+
return Promise.reject(error);
|
|
6095
|
+
}
|
|
6096
|
+
}
|
|
6097
|
+
return admitWorkflowStageInbound(ctx, deliver, firstRefusal, onAdmissionFailure);
|
|
6098
|
+
}
|
|
6099
|
+
var init_active_session_admission = () => {};
|
|
6100
|
+
|
|
5892
6101
|
// dist/builtin/intercom/workflow-reply-tracker.ts
|
|
5893
6102
|
function bindWorkflowReplyTracker(ctx, current) {
|
|
5894
6103
|
const state = ctx.orchestrationContext?.messageAdmission?.extensionState;
|
|
@@ -5942,7 +6151,7 @@ async function settleOpenStageDeliveryFailure(input, error) {
|
|
|
5942
6151
|
input.admission.release(input.reservation, failure);
|
|
5943
6152
|
return;
|
|
5944
6153
|
}
|
|
5945
|
-
const delivered = await sendWorkflowStageDeliveryFailure(input.entry, failure, input.tracker, input.currentClient, () => input.currentClient()?.isConnected() === true, "Running workflow stage could not admit intercom ask");
|
|
6154
|
+
const delivered = await sendWorkflowStageDeliveryFailure(input.entry, failure, input.tracker, input.currentClient, () => input.currentClient()?.isConnected() === true, input.failurePrefix ?? "Running workflow stage could not admit intercom ask");
|
|
5946
6155
|
if (delivered)
|
|
5947
6156
|
input.commit();
|
|
5948
6157
|
else
|
|
@@ -5954,7 +6163,7 @@ function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deli
|
|
|
5954
6163
|
const sourceRunId = entry.message.source?.subagentRunId;
|
|
5955
6164
|
if (sourceRunId !== undefined && ownsSubagentRun(sourceRunId))
|
|
5956
6165
|
return;
|
|
5957
|
-
if (entry.message.expectsReply !== true) {
|
|
6166
|
+
if (entry.message.expectsReply !== true && !isDeliveryFeedback(entry.message)) {
|
|
5958
6167
|
retryStableDelivery({ deliver, isCurrent }).catch(() => {});
|
|
5959
6168
|
return;
|
|
5960
6169
|
}
|
|
@@ -5965,6 +6174,14 @@ function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deli
|
|
|
5965
6174
|
admission.commit(admitted.reservation);
|
|
5966
6175
|
return;
|
|
5967
6176
|
}
|
|
6177
|
+
if (isDeliveryFeedback(entry.message)) {
|
|
6178
|
+
retryStableDelivery({ deliver, isCurrent }).then(() => {
|
|
6179
|
+
admission.commit(admitted.reservation);
|
|
6180
|
+
}, (error) => {
|
|
6181
|
+
admission.release(admitted.reservation, error instanceof Error ? error : new Error(String(error)));
|
|
6182
|
+
});
|
|
6183
|
+
return;
|
|
6184
|
+
}
|
|
5968
6185
|
const replyContext = tracker.recordIncomingMessage(entry.from, entry.message);
|
|
5969
6186
|
tracker.queueTurnContext(replyContext);
|
|
5970
6187
|
const delivery = invoke(deliver);
|
|
@@ -6050,6 +6267,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6050
6267
|
};
|
|
6051
6268
|
let client = null;
|
|
6052
6269
|
let clientRegistrationGroup = null;
|
|
6270
|
+
const replyCapability = registerSubagentReplyCapability(pi, () => client);
|
|
6053
6271
|
const config = loadConfig();
|
|
6054
6272
|
const legacyChildOrchestratorMetadata = readChildOrchestratorMetadata();
|
|
6055
6273
|
let runtimeContext = null;
|
|
@@ -6118,7 +6336,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6118
6336
|
}
|
|
6119
6337
|
function currentStatus() {
|
|
6120
6338
|
const activeToolName = activeTools.values().next().value;
|
|
6121
|
-
const
|
|
6339
|
+
const stage = getLiveContext()?.orchestrationContext;
|
|
6340
|
+
const lifecycleStatus = stage?.kind === "workflow-stage" && stage.messageAdmission?.isOpen() === false ? `closed · reply: ${stage.lateMessageRouter === undefined ? "unavailable" : "post-mortem only"}` : activeToolName ? `tool:${activeToolName}` : agentRunning ? "thinking" : "idle";
|
|
6122
6341
|
return config.status ? `${lifecycleStatus} · ${config.status}` : lifecycleStatus;
|
|
6123
6342
|
}
|
|
6124
6343
|
function resolveSessionHomeGroup() {
|
|
@@ -6156,6 +6375,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6156
6375
|
startedAt: sessionStartedAt,
|
|
6157
6376
|
lastActivity: Date.now(),
|
|
6158
6377
|
status: currentStatus(),
|
|
6378
|
+
replyCapability: replyCapability(),
|
|
6159
6379
|
groups: [...currentIntercomGroups()],
|
|
6160
6380
|
group: currentIntercomGroup()
|
|
6161
6381
|
};
|
|
@@ -6257,14 +6477,20 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6257
6477
|
const bodyText = `${message.content.text}${attachmentText}`;
|
|
6258
6478
|
const replyCommand = config.replyHint && message.expectsReply ? `intercom({ action: "reply", message: "..." })` : undefined;
|
|
6259
6479
|
const rawEntry = { from, message, replyCommand, bodyText, ...channel ? { channel } : {} };
|
|
6260
|
-
const
|
|
6480
|
+
const framedEntry = isDeliveryFeedback(message) ? frameDeliveryFeedback(rawEntry) : rawEntry;
|
|
6481
|
+
const entry = receivedBeforeStageStart ? framePreStartPendingStageMessage(framedEntry) : framedEntry;
|
|
6261
6482
|
if (receivedBeforeStageStart) {
|
|
6262
6483
|
return sendIncomingMessage(entry, "prelude", messageGeneration, false);
|
|
6263
6484
|
}
|
|
6264
6485
|
const stageAdmission = liveContext.orchestrationContext?.kind === "workflow-stage" ? liveContext.orchestrationContext.messageAdmission : undefined;
|
|
6265
6486
|
const stageClosed = stageAdmission?.isOpen() === false;
|
|
6266
6487
|
if (stageClosed) {
|
|
6267
|
-
routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () =>
|
|
6488
|
+
routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () => {
|
|
6489
|
+
if (message.expectsReply === true && liveContext.orchestrationContext?.lateMessageRouter === undefined) {
|
|
6490
|
+
throw new Error("Workflow stage is closed and cannot reply because post-mortem routing is unavailable. Contact a live stage or start new work with explicit context.");
|
|
6491
|
+
}
|
|
6492
|
+
return sendIncomingMessage(entry, isDeliveryFeedback(message) ? "prelude" : "trigger", messageGeneration, false);
|
|
6493
|
+
}, () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId));
|
|
6268
6494
|
return;
|
|
6269
6495
|
}
|
|
6270
6496
|
const admission = inboundDeliveries.admit(from, message);
|
|
@@ -6275,6 +6501,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6275
6501
|
inboundDeliveries.commit(reservation);
|
|
6276
6502
|
return;
|
|
6277
6503
|
}
|
|
6504
|
+
if (isDeliveryFeedback(message)) {
|
|
6505
|
+
return retryStableDelivery({
|
|
6506
|
+
deliver: () => sendIncomingMessage(entry, "prelude", messageGeneration, false),
|
|
6507
|
+
isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration))
|
|
6508
|
+
}).then(() => inboundDeliveries.commit(reservation), (error) => inboundDeliveries.release(reservation, toError3(error)));
|
|
6509
|
+
}
|
|
6278
6510
|
const replyContext = replyTracker.recordIncomingMessage(from, message);
|
|
6279
6511
|
const commit = () => {
|
|
6280
6512
|
inboundDeliveries.commit(reservation);
|
|
@@ -6286,17 +6518,18 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6286
6518
|
tracker: replyTracker,
|
|
6287
6519
|
replyContext,
|
|
6288
6520
|
currentClient: () => client,
|
|
6289
|
-
commit
|
|
6521
|
+
commit,
|
|
6522
|
+
failurePrefix: liveContext.subagentPolicy?.executionEnded === undefined ? undefined : "Subagent could not admit intercom ask"
|
|
6290
6523
|
});
|
|
6291
|
-
const
|
|
6524
|
+
const activeDelivery = admitActiveSessionInbound(liveContext, (admissionBarrier) => {
|
|
6292
6525
|
replyTracker.queueTurnContext(replyContext);
|
|
6293
6526
|
return retryStableDelivery({
|
|
6294
|
-
deliver: () => sendIncomingMessage(entry, "
|
|
6295
|
-
isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration))
|
|
6527
|
+
deliver: () => sendIncomingMessage(entry, "interrupt", messageGeneration, false, undefined, admissionBarrier),
|
|
6528
|
+
isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration)) && liveContext.subagentPolicy?.executionEnded?.aborted !== true && liveContext.subagentPolicy?.messageAdmission?.isOpen() !== false
|
|
6296
6529
|
});
|
|
6297
6530
|
}, () => foregroundDetachHandoff.claim(from, message, messageGeneration, () => Boolean(getLiveContext(liveContext, messageGeneration))), release);
|
|
6298
|
-
if (
|
|
6299
|
-
|
|
6531
|
+
if (activeDelivery !== false) {
|
|
6532
|
+
activeDelivery.then(commit, release);
|
|
6300
6533
|
return;
|
|
6301
6534
|
}
|
|
6302
6535
|
return (async () => {
|
|
@@ -6306,14 +6539,16 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6306
6539
|
release(new Error("Intercom session retired before inbound delivery"));
|
|
6307
6540
|
return;
|
|
6308
6541
|
}
|
|
6309
|
-
if (!activeContext.isIdle()) {
|
|
6542
|
+
if (!activeContext.isIdle() && !activeContext.getAgentTaskHost?.().hasActiveTaskWaits) {
|
|
6310
6543
|
if (!activeContext.hasUI) {
|
|
6311
6544
|
const activeClient = client;
|
|
6312
6545
|
if (!message.replyTo && activeClient?.isConnected()) {
|
|
6313
6546
|
try {
|
|
6547
|
+
const refusal = "Message not accepted: recipient was busy in non-interactive mode. Its task was not interrupted.";
|
|
6314
6548
|
const result = await activeClient.send(from.id, {
|
|
6315
|
-
text:
|
|
6316
|
-
replyTo: message.id
|
|
6549
|
+
text: refusal,
|
|
6550
|
+
replyTo: message.id,
|
|
6551
|
+
replyError: refusal
|
|
6317
6552
|
});
|
|
6318
6553
|
if (result.delivered && getLiveContext(liveContext, messageGeneration)) {
|
|
6319
6554
|
replyTracker.markReplied(message.id);
|
|
@@ -6347,6 +6582,13 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6347
6582
|
});
|
|
6348
6583
|
return;
|
|
6349
6584
|
}
|
|
6585
|
+
if (!activeContext.isIdle()) {
|
|
6586
|
+
const disposition = await foregroundDetachHandoff.claim(from, message, messageGeneration, () => Boolean(getLiveContext(liveContext, messageGeneration)));
|
|
6587
|
+
if (disposition === "abandoned") {
|
|
6588
|
+
release(new Error("Intercom session retired during foreground-owner admission"));
|
|
6589
|
+
return;
|
|
6590
|
+
}
|
|
6591
|
+
}
|
|
6350
6592
|
replyTracker.queueTurnContext(replyContext);
|
|
6351
6593
|
await retryStableDelivery({ deliver: () => sendIncomingMessage(entry, "trigger", messageGeneration, false), isCurrent: () => Boolean(getLiveContext(liveContext, messageGeneration)) });
|
|
6352
6594
|
commit();
|
|
@@ -6581,7 +6823,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6581
6823
|
pendingStageRouteClients.set(runId, state);
|
|
6582
6824
|
if (state.client?.isConnected()) {
|
|
6583
6825
|
state.route = route;
|
|
6584
|
-
state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages);
|
|
6826
|
+
state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
|
|
6827
|
+
await state.client.listSessions();
|
|
6585
6828
|
return;
|
|
6586
6829
|
}
|
|
6587
6830
|
if (state.promise) {
|
|
@@ -6593,12 +6836,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6593
6836
|
const nextClient = new IntercomClient(`${currentSessionId}:pending-stage-route:${runId}`);
|
|
6594
6837
|
state.client = nextClient;
|
|
6595
6838
|
attachPendingStageRouteClientHandlers(runId, state, nextClient);
|
|
6596
|
-
await nextClient.connect({ ...buildRegistration(), name: undefined, groups: [normalizeGroup(route.group)], group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
|
|
6839
|
+
await nextClient.connect({ ...buildRegistration(), recipientPurpose: "control", name: undefined, groups: [normalizeGroup(route.group)], group: normalizeGroup(route.group) }, undefined, undefined, readSubagentMessageSource(runtimeContext?.subagentPolicy));
|
|
6597
6840
|
if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
|
|
6598
6841
|
await nextClient.disconnect();
|
|
6599
6842
|
throw new Error("Intercom runtime no longer active");
|
|
6600
6843
|
}
|
|
6601
|
-
nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages);
|
|
6844
|
+
nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
|
|
6602
6845
|
await nextClient.listSessions();
|
|
6603
6846
|
if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
|
|
6604
6847
|
await nextClient.disconnect();
|
|
@@ -6646,7 +6889,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6646
6889
|
async function registerPendingStageRoute(activeClient, runId, route) {
|
|
6647
6890
|
const routeGroup = normalizeGroup(route.group);
|
|
6648
6891
|
if (clientRegistrationGroup === routeGroup) {
|
|
6649
|
-
activeClient.registerPendingStageRoute(runId, routeGroup, route.capability, route.stages, route.possibleStages);
|
|
6892
|
+
activeClient.registerPendingStageRoute(runId, routeGroup, route.capability, route.stages, route.possibleStages, route.parent);
|
|
6893
|
+
await activeClient.listSessions();
|
|
6650
6894
|
return;
|
|
6651
6895
|
}
|
|
6652
6896
|
await ensurePendingStageRouteClient(runId, { ...route, group: routeGroup });
|
|
@@ -6672,15 +6916,16 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6672
6916
|
let connectFailed = false;
|
|
6673
6917
|
await ownershipRecorded.promise;
|
|
6674
6918
|
const nextClient = new IntercomClient(currentSessionId);
|
|
6675
|
-
const registration = buildRegistration();
|
|
6676
6919
|
client = nextClient;
|
|
6677
6920
|
attachClientHandlers(nextClient);
|
|
6678
6921
|
try {
|
|
6679
6922
|
await testOverrides.beforeConnectAttempt?.(reason);
|
|
6680
6923
|
await spawnBrokerIfNeeded(config.brokerCommand, config.brokerArgs);
|
|
6681
6924
|
const childMetadata = currentChildOrchestratorMetadata();
|
|
6682
|
-
await nextClient.connect(
|
|
6925
|
+
await nextClient.connect(buildRegistration(), childMetadata?.supervisor, supervisorAuthorizations.ownerToken, readSubagentMessageSource(runtimeContext?.subagentPolicy), resolveSessionHomeGroup());
|
|
6683
6926
|
clientRegistrationGroup = resolveSessionHomeGroup();
|
|
6927
|
+
if (replyCapability() === "terminal")
|
|
6928
|
+
nextClient.updatePresence({ replyCapability: "terminal" });
|
|
6684
6929
|
await supervisorAuthorizations.restore(nextClient);
|
|
6685
6930
|
for (const [runId, route] of pendingStageRoutes) {
|
|
6686
6931
|
await registerPendingStageRoute(nextClient, runId, route);
|
|
@@ -6734,7 +6979,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6734
6979
|
group: payload.group,
|
|
6735
6980
|
capability: payload.capability,
|
|
6736
6981
|
...payload.stages === undefined ? {} : { stages: payload.stages },
|
|
6737
|
-
...payload.possibleStages === undefined ? {} : { possibleStages: payload.possibleStages }
|
|
6982
|
+
...payload.possibleStages === undefined ? {} : { possibleStages: payload.possibleStages },
|
|
6983
|
+
...payload.parent === undefined ? {} : { parent: payload.parent }
|
|
6738
6984
|
});
|
|
6739
6985
|
const completion = ensureConnected("background").then((activeClient) => registerPendingStageRoute(activeClient, payload.runId, payload));
|
|
6740
6986
|
payload.completion = completion;
|
|
@@ -6919,6 +7165,7 @@ var init_index_heavy = __esm(() => {
|
|
|
6919
7165
|
init_terminal_ordering_barrier();
|
|
6920
7166
|
init_inbound_message_admission();
|
|
6921
7167
|
init_late_stage_message_router();
|
|
7168
|
+
init_active_session_admission();
|
|
6922
7169
|
init_workflow_reply_tracker();
|
|
6923
7170
|
init_closed_workflow_stage_message();
|
|
6924
7171
|
init_group();
|
|
@@ -6936,14 +7183,49 @@ var init_index_heavy = __esm(() => {
|
|
|
6936
7183
|
});
|
|
6937
7184
|
|
|
6938
7185
|
// dist/builtin/intercom/index.ts
|
|
6939
|
-
init_result_renderers();
|
|
6940
7186
|
import { APP_NAME as APP_NAME2, getEnvValue } from "@bastani/atomic";
|
|
6941
7187
|
import { Text as Text4 } from "@earendil-works/pi-tui";
|
|
6942
7188
|
import { Type as Type3 } from "typebox";
|
|
6943
7189
|
|
|
7190
|
+
// dist/builtin/intercom/context-owner.ts
|
|
7191
|
+
var CONTEXT_OWNERS_KEY = Symbol.for("atomic-coding-agent/extension-context-owners@1");
|
|
7192
|
+
function getExtensionContextOwner(context) {
|
|
7193
|
+
const owners = globalThis[CONTEXT_OWNERS_KEY];
|
|
7194
|
+
return owners?.get(context) ?? context;
|
|
7195
|
+
}
|
|
7196
|
+
|
|
7197
|
+
// dist/builtin/intercom/index.ts
|
|
7198
|
+
init_result_renderers();
|
|
7199
|
+
|
|
6944
7200
|
// dist/builtin/intercom/lazy-tool-execution.ts
|
|
7201
|
+
init_recoverable_disconnect();
|
|
7202
|
+
init_retry_policy();
|
|
7203
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
6945
7204
|
async function executeHeavyTool(loadHeavy, name, args) {
|
|
6946
|
-
const
|
|
7205
|
+
const params = args[1];
|
|
7206
|
+
const recoverInitialization = name === "intercom" && ["send", "ask", "reply"].includes(params.action ?? "");
|
|
7207
|
+
let handle;
|
|
7208
|
+
let retries = 0;
|
|
7209
|
+
for (;; ) {
|
|
7210
|
+
if (recoverInitialization && args[2]?.aborted)
|
|
7211
|
+
return initializationFailure("Cancelled", retries);
|
|
7212
|
+
try {
|
|
7213
|
+
handle = await loadHeavy(args[4]);
|
|
7214
|
+
break;
|
|
7215
|
+
} catch (error) {
|
|
7216
|
+
if (!recoverInitialization || !isRecoverableIntercomDisconnect(error))
|
|
7217
|
+
throw error;
|
|
7218
|
+
const delayMs = RECONNECT_DELAYS_MS[retries];
|
|
7219
|
+
if (delayMs === undefined)
|
|
7220
|
+
return initializationFailure("Client disconnected", retries);
|
|
7221
|
+
try {
|
|
7222
|
+
await delay(delayMs, undefined, { signal: args[2] });
|
|
7223
|
+
} catch {
|
|
7224
|
+
return initializationFailure("Cancelled", retries);
|
|
7225
|
+
}
|
|
7226
|
+
retries += 1;
|
|
7227
|
+
}
|
|
7228
|
+
}
|
|
6947
7229
|
handle.assertCurrent();
|
|
6948
7230
|
const tool = handle.heavy.tools.get(name);
|
|
6949
7231
|
if (!tool?.execute)
|
|
@@ -6952,6 +7234,13 @@ async function executeHeavyTool(loadHeavy, name, args) {
|
|
|
6952
7234
|
handle.assertCurrent();
|
|
6953
7235
|
return result;
|
|
6954
7236
|
}
|
|
7237
|
+
function initializationFailure(reason, retries) {
|
|
7238
|
+
return {
|
|
7239
|
+
content: [{ type: "text", text: `${reason}. Intercom initialization stopped after ${retries} automatic retries. This operation was not sent.` }],
|
|
7240
|
+
isError: true,
|
|
7241
|
+
details: { error: true, terminal: true, automaticRetries: retries, outcome: "not_sent" }
|
|
7242
|
+
};
|
|
7243
|
+
}
|
|
6955
7244
|
async function runHeavyCommand(loadHeavy, args, ctx) {
|
|
6956
7245
|
const handle = await loadHeavy(ctx);
|
|
6957
7246
|
handle.assertCurrent();
|
|
@@ -7169,10 +7458,37 @@ function renderHeavyToolResult(loadedHeavy, name, args) {
|
|
|
7169
7458
|
return renderer(...args);
|
|
7170
7459
|
return renderIntercomToolResult(name, args);
|
|
7171
7460
|
}
|
|
7172
|
-
function
|
|
7461
|
+
function diagnosticDetail(error) {
|
|
7462
|
+
try {
|
|
7463
|
+
return String(error instanceof Error ? error.message : error);
|
|
7464
|
+
} catch {
|
|
7465
|
+
return "Unprintable error";
|
|
7466
|
+
}
|
|
7467
|
+
}
|
|
7468
|
+
function captureDiagnosticRoute(ctx) {
|
|
7469
|
+
try {
|
|
7470
|
+
return ctx?.hasUI && ctx.mode === "tui" ? ctx : "console";
|
|
7471
|
+
} catch {
|
|
7472
|
+
return "silent";
|
|
7473
|
+
}
|
|
7474
|
+
}
|
|
7475
|
+
function reportDiagnostic(route, message, error, level, consoleMessage = message) {
|
|
7476
|
+
if (route === "console") {
|
|
7477
|
+
console.error(consoleMessage, error);
|
|
7478
|
+
return;
|
|
7479
|
+
}
|
|
7480
|
+
if (route === "silent")
|
|
7481
|
+
return;
|
|
7482
|
+
try {
|
|
7483
|
+
route.ui.notify(message, level);
|
|
7484
|
+
} catch {}
|
|
7485
|
+
}
|
|
7486
|
+
function reportRelayFailure(route, eventName, error) {
|
|
7173
7487
|
if (isRecoverableIntercomDisconnect(error))
|
|
7174
7488
|
return;
|
|
7175
|
-
|
|
7489
|
+
const prefix = `Intercom event relay failed (${eventName}):`;
|
|
7490
|
+
const detail = diagnosticDetail(error);
|
|
7491
|
+
reportDiagnostic(route, `${prefix} ${detail}`, error, "error", prefix);
|
|
7176
7492
|
}
|
|
7177
7493
|
var WARM_UP_RETRY_ATTEMPTS = 5;
|
|
7178
7494
|
function intercom(pi, options = {}) {
|
|
@@ -7180,6 +7496,7 @@ function intercom(pi, options = {}) {
|
|
|
7180
7496
|
let heavyAttempt = null;
|
|
7181
7497
|
let loadedHeavy = null;
|
|
7182
7498
|
let sessionSnapshot = null;
|
|
7499
|
+
let shutdownDiagnosticRoute;
|
|
7183
7500
|
let lifecycleGeneration = 0;
|
|
7184
7501
|
let nextLeaseId = 1;
|
|
7185
7502
|
let activeLease = createLifecycleLease(nextLeaseId++);
|
|
@@ -7263,6 +7580,8 @@ function intercom(pi, options = {}) {
|
|
|
7263
7580
|
await promise;
|
|
7264
7581
|
}
|
|
7265
7582
|
async function loadHeavy(ctx) {
|
|
7583
|
+
let diagnosticRoute = captureDiagnosticRoute(ctx);
|
|
7584
|
+
let diagnosticOwner = ctx && getExtensionContextOwner(ctx);
|
|
7266
7585
|
const lease = activeLease;
|
|
7267
7586
|
if (lease.retired)
|
|
7268
7587
|
throw new Error("Intercom initialization unavailable: no active session");
|
|
@@ -7279,6 +7598,7 @@ function intercom(pi, options = {}) {
|
|
|
7279
7598
|
return handle;
|
|
7280
7599
|
}
|
|
7281
7600
|
let promise;
|
|
7601
|
+
let replayCtx = null;
|
|
7282
7602
|
promise = (async () => {
|
|
7283
7603
|
const captured = {
|
|
7284
7604
|
tools: new Map,
|
|
@@ -7287,7 +7607,6 @@ function intercom(pi, options = {}) {
|
|
|
7287
7607
|
shortcuts: new Map,
|
|
7288
7608
|
eventHandlers: new Map
|
|
7289
7609
|
};
|
|
7290
|
-
let replayCtx = null;
|
|
7291
7610
|
let cleaned = false;
|
|
7292
7611
|
const cleanupCandidate = async () => {
|
|
7293
7612
|
const shutdown = lease.shutdown;
|
|
@@ -7299,7 +7618,9 @@ function intercom(pi, options = {}) {
|
|
|
7299
7618
|
try {
|
|
7300
7619
|
await dispatchHandlers(captured, "session_shutdown", event, cleanupCtx);
|
|
7301
7620
|
} catch (cleanupError) {
|
|
7302
|
-
|
|
7621
|
+
const prefix = "Intercom failed to clean rejected lazy candidate:";
|
|
7622
|
+
const detail = diagnosticDetail(cleanupError);
|
|
7623
|
+
reportDiagnostic(shutdown?.diagnosticRoute ?? diagnosticRoute, `${prefix} ${detail}`, cleanupError, "error", prefix);
|
|
7303
7624
|
}
|
|
7304
7625
|
};
|
|
7305
7626
|
try {
|
|
@@ -7311,6 +7632,11 @@ function intercom(pi, options = {}) {
|
|
|
7311
7632
|
sessionSnapshot = { event: createSyntheticSessionStartEvent(), ctx, generation: ++lifecycleGeneration, lease };
|
|
7312
7633
|
}
|
|
7313
7634
|
await ensureSessionStartReplayed(captured, lease, (replayContext) => {
|
|
7635
|
+
const owner = getExtensionContextOwner(replayContext);
|
|
7636
|
+
if (owner !== diagnosticOwner) {
|
|
7637
|
+
diagnosticRoute = captureDiagnosticRoute(replayContext);
|
|
7638
|
+
diagnosticOwner = owner;
|
|
7639
|
+
}
|
|
7314
7640
|
replayCtx = replayContext;
|
|
7315
7641
|
});
|
|
7316
7642
|
assertLease(lease);
|
|
@@ -7329,8 +7655,8 @@ function intercom(pi, options = {}) {
|
|
|
7329
7655
|
if (heavyAttempt?.promise === promise)
|
|
7330
7656
|
heavyAttempt = null;
|
|
7331
7657
|
if (!isRecoverableIntercomDisconnect(error)) {
|
|
7332
|
-
const message =
|
|
7333
|
-
|
|
7658
|
+
const message = diagnosticDetail(error);
|
|
7659
|
+
reportDiagnostic(diagnosticRoute, `Intercom heavy initialization failed; a later call will retry: ${message}`, error, "warning");
|
|
7334
7660
|
}
|
|
7335
7661
|
});
|
|
7336
7662
|
return promise;
|
|
@@ -7441,6 +7767,7 @@ function intercom(pi, options = {}) {
|
|
|
7441
7767
|
}
|
|
7442
7768
|
const generation = ++lifecycleGeneration;
|
|
7443
7769
|
sessionSnapshot = { event, ctx, generation, lease };
|
|
7770
|
+
shutdownDiagnosticRoute = undefined;
|
|
7444
7771
|
cancelWarmUpRetry();
|
|
7445
7772
|
if (ctx.orchestrationContext?.kind === "workflow-stage" && ctx.orchestrationContext.pendingStageDelivery !== undefined) {
|
|
7446
7773
|
const pendingStageDelivery = ctx.orchestrationContext.pendingStageDelivery;
|
|
@@ -7458,7 +7785,9 @@ function intercom(pi, options = {}) {
|
|
|
7458
7785
|
pi.on("session_shutdown", async (event, ctx) => {
|
|
7459
7786
|
const lease = activeLease;
|
|
7460
7787
|
const generation = ++lifecycleGeneration;
|
|
7461
|
-
|
|
7788
|
+
const diagnosticRoute = captureDiagnosticRoute(ctx);
|
|
7789
|
+
retireLifecycleLease(lease, { event, ctx, generation, diagnosticRoute });
|
|
7790
|
+
shutdownDiagnosticRoute = diagnosticRoute;
|
|
7462
7791
|
cancelWarmUpRetry();
|
|
7463
7792
|
const retiredHeavy = loadedHeavy?.heavy ?? null;
|
|
7464
7793
|
const retiredAttempt = heavyAttempt?.lease === lease ? heavyAttempt.promise : null;
|
|
@@ -7579,13 +7908,15 @@ function intercom(pi, options = {}) {
|
|
|
7579
7908
|
return;
|
|
7580
7909
|
payload.handled = true;
|
|
7581
7910
|
const forwarded = { ...payload, handled: false, completion: undefined };
|
|
7582
|
-
|
|
7911
|
+
const ctx = latestLifecycleContext();
|
|
7912
|
+
const diagnosticRoute = ctx ? captureDiagnosticRoute(ctx) : shutdownDiagnosticRoute ?? "console";
|
|
7913
|
+
payload.completion = loadHeavy(ctx).then(async (handle) => {
|
|
7583
7914
|
handle.assertCurrent();
|
|
7584
7915
|
await dispatchEventHandlers(handle.heavy, PENDING_STAGE_UNDELIVERABLE_EVENT2, forwarded);
|
|
7585
7916
|
handle.assertCurrent();
|
|
7586
7917
|
return forwarded.handled === true && forwarded.completion !== undefined ? await forwarded.completion : false;
|
|
7587
7918
|
}).catch((error) => {
|
|
7588
|
-
reportRelayFailure(PENDING_STAGE_UNDELIVERABLE_EVENT2, error);
|
|
7919
|
+
reportRelayFailure(diagnosticRoute, PENDING_STAGE_UNDELIVERABLE_EVENT2, error);
|
|
7589
7920
|
return false;
|
|
7590
7921
|
});
|
|
7591
7922
|
});
|
|
@@ -7595,7 +7926,9 @@ function intercom(pi, options = {}) {
|
|
|
7595
7926
|
PENDING_STAGE_ROUTE_EVENT2
|
|
7596
7927
|
]) {
|
|
7597
7928
|
pi.events.on(eventName, (payload) => {
|
|
7598
|
-
const
|
|
7929
|
+
const ctx = latestLifecycleContext();
|
|
7930
|
+
const diagnosticRoute = ctx ? captureDiagnosticRoute(ctx) : shutdownDiagnosticRoute ?? "console";
|
|
7931
|
+
const completion = loadHeavy(ctx).then(async (handle) => {
|
|
7599
7932
|
handle.assertCurrent();
|
|
7600
7933
|
await dispatchEventHandlers(handle.heavy, eventName, payload);
|
|
7601
7934
|
handle.assertCurrent();
|
|
@@ -7610,7 +7943,7 @@ function intercom(pi, options = {}) {
|
|
|
7610
7943
|
}
|
|
7611
7944
|
completion.catch((error) => {
|
|
7612
7945
|
rejectLazyResultRelay(pi, eventName, payload, error);
|
|
7613
|
-
reportRelayFailure(eventName, error);
|
|
7946
|
+
reportRelayFailure(diagnosticRoute, eventName, error);
|
|
7614
7947
|
});
|
|
7615
7948
|
});
|
|
7616
7949
|
}
|
|
@@ -7634,7 +7967,7 @@ function intercom(pi, options = {}) {
|
|
|
7634
7967
|
Use this to communicate findings, request help, or coordinate work with other sessions.
|
|
7635
7968
|
Sessions belong to an intercom group and can ONLY message sessions in the same group; cross-group sends are rejected by the broker. Ungrouped sessions share the "default" group.
|
|
7636
7969
|
For send, live session names and exact full session IDs remain supported. Workflow-stage targets use \`workflow:<rootRunId>/<segment>[/<segment>...]\`; \`*\` matches one segment and \`**\` any depth. Use \`intercom list\` inside the invocation group to see live, pending, and possible future targets with queued counts. \`workflow:<rootRunId>/**\` reaches live stages now and remains sticky for every future stage until root termination; valid targets outside the known set queue with a \`notInKnownSet\` warning and settle undeliverable at terminal only if never delivered. Use \`ask\` only on live targets.
|
|
7637
|
-
|
|
7970
|
+
For send/ask/reply, Intercom retries recoverable disconnects internally up to three times with the same operation identity. Each new tool call is a new operation. If recovery ends with an unknown delivery outcome, do not repeat it automatically.
|
|
7638
7971
|
Usage:
|
|
7639
7972
|
intercom({ action: "list" }) → List sessions in your group
|
|
7640
7973
|
intercom({ action: "list", group: "name" }) → Read-only peek at another group's sessions
|
|
@@ -7643,12 +7976,11 @@ Usage:
|
|
|
7643
7976
|
intercom({ action: "send", to: "session-name", message: "..." }) → Send message (own group only)
|
|
7644
7977
|
intercom({ action: "ask", to: "session-name", message: "..." }) → Ask and wait for reply
|
|
7645
7978
|
intercom({ action: "reply", message: "..." }) → Reply to the active or exact pending ask
|
|
7646
|
-
intercom({ action: "send", to: "session-name", message: "...", retryToken: "..." }) → Claim the exact retry returned by a retryable failure
|
|
7647
7979
|
intercom({ action: "pending" }) → List unresolved inbound asks
|
|
7648
7980
|
intercom({ action: "status" }) → Show connection status and your group
|
|
7649
7981
|
|
|
7650
7982
|
"default" is the shared group; "true" and "auto" are reserved for subagent auto-groups. Joining does not grant cross-group access; contact_supervisor remains the only cross-group path.`,
|
|
7651
|
-
promptSnippet: "Use to coordinate with other local agent sessions in your intercom group.
|
|
7983
|
+
promptSnippet: "Use to coordinate with other local agent sessions in your intercom group. Send/ask/reply retry reconnects internally; do not automatically repeat an unknown delivery outcome.",
|
|
7652
7984
|
parameters: Type3.Object({
|
|
7653
7985
|
action: Type3.String({ description: "Action: 'list', 'join', 'leave', 'send', 'ask', 'reply', 'pending', or 'status'" }),
|
|
7654
7986
|
to: Type3.Optional(Type3.String({ description: "Live session name, exact full session ID, or `workflow:<rootRunId>/<segment>[/<segment>...]` path; `*` matches one segment and `**` any depth. Send queues sticky pending/future delivery and `workflow:<rootRunId>/**` broadcasts to live and future stages; use `ask` only on live targets (for 'send', 'ask', or targeted 'reply')" })),
|
|
@@ -7660,10 +7992,15 @@ Usage:
|
|
|
7660
7992
|
language: Type3.Optional(Type3.String())
|
|
7661
7993
|
}))),
|
|
7662
7994
|
replyTo: Type3.Optional(Type3.String({ description: "Exact pending-ask message ID; disambiguates concurrent asks, including asks from one sender" })),
|
|
7663
|
-
retryToken: Type3.Optional(Type3.String({ minLength: 1, maxLength: 128, description: "Opaque token returned after a retryable send/ask/reply failure. Repeat the exact same action and arguments with it; omit it for fresh operations." })),
|
|
7664
7995
|
group: Type3.Optional(Type3.String({ description: "Group name for 'join'; read-only group filter for 'list'/'status'. 'send'/'ask' are locked to your own group." }))
|
|
7665
7996
|
}),
|
|
7666
|
-
execute: (...args) =>
|
|
7997
|
+
execute: (...args) => {
|
|
7998
|
+
const invocationLease = activeLease;
|
|
7999
|
+
return executeHeavyTool((ctx) => {
|
|
8000
|
+
assertLease(invocationLease);
|
|
8001
|
+
return loadHeavy(ctx);
|
|
8002
|
+
}, "intercom", args);
|
|
8003
|
+
},
|
|
7667
8004
|
renderResult: (...args) => renderHeavyToolResult(loadedHeavy?.heavy ?? null, "intercom", args),
|
|
7668
8005
|
renderCall(args, theme) {
|
|
7669
8006
|
const input = args;
|