@bastani/atomic 0.9.19-alpha.2 → 0.9.19-alpha.4
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 +42 -0
- package/dist/builtin/intercom/CHANGELOG.md +15 -0
- package/dist/builtin/intercom/broker/broker.ts +8 -0
- package/dist/builtin/intercom/broker/client.ts +18 -0
- package/dist/builtin/intercom/broker/send-handler.ts +9 -0
- package/dist/builtin/intercom/index.bundle.mjs +161 -30
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/types.ts +2 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +18 -0
- package/dist/builtin/subagents/README.md +14 -14
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/subagent/SKILL.md +14 -14
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +142 -60
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +33 -0
- package/dist/builtin/workflows/README.md +14 -15
- package/dist/builtin/workflows/builtin/{chunk-mygmtz6e.js → chunk-9k3ywfgd.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-r9qq7xfj.js → chunk-ahbntmx2.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-zggjyg5z.js → chunk-n8zysf1t.js} +1 -1
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +3 -3
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/package.json +5 -5
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +171 -207
- package/dist/builtin/workflows/src/index.js +33 -6
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +2 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -1
- package/dist/core/agent-session-auto-compaction.js +1 -1
- package/dist/core/agent-session-auto-compaction.js.map +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.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-message-queue.d.ts +1 -1
- 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 +7 -1
- 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.map +1 -1
- package/dist/core/agent-session-prompt.js +83 -0
- 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-tasks.d.ts +5 -0
- package/dist/core/agent-session-tasks.d.ts.map +1 -1
- package/dist/core/agent-session-tasks.js +8 -1
- package/dist/core/agent-session-tasks.js.map +1 -1
- 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.map +1 -1
- package/dist/core/agent-session-tool-registry.js +12 -0
- 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-types.d.ts +2 -0
- 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 +4 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +22 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +6 -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/loader-api.d.ts.map +1 -1
- package/dist/core/extensions/loader-api.js +3 -0
- package/dist/core/extensions/loader-api.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 +2 -1
- package/dist/core/extensions/loader-host-modules.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +4 -1
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +1 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +9 -3
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.js +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/workflow-events.d.ts +1 -1
- package/dist/core/extensions/workflow-events.d.ts.map +1 -1
- package/dist/core/extensions/workflow-events.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 +1 -1
- 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/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.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-types.d.ts +6 -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 +4 -5
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tasks/agent-adapter.d.ts +14 -2
- package/dist/core/tasks/agent-adapter.d.ts.map +1 -1
- package/dist/core/tasks/agent-adapter.js +45 -4
- package/dist/core/tasks/agent-adapter.js.map +1 -1
- package/dist/core/tasks/completion.d.ts.map +1 -1
- package/dist/core/tasks/completion.js +5 -1
- package/dist/core/tasks/completion.js.map +1 -1
- 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 +3 -1
- package/dist/core/tasks/supervisor.d.ts.map +1 -1
- package/dist/core/tasks/supervisor.js +48 -22
- package/dist/core/tasks/supervisor.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts +16 -2
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +82 -0
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts +15 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +49 -4
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +4 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +12 -0
- 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/powershell.d.ts +84 -28
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/core/tools/powershell.js +11 -3
- package/dist/core/tools/powershell.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 +7 -4
- package/dist/core/tools/resource-selectors.js.map +1 -1
- package/dist/core/workflow-stage-admission.d.ts +14 -0
- package/dist/core/workflow-stage-admission.d.ts.map +1 -1
- package/dist/core/workflow-stage-admission.js +63 -3
- package/dist/core/workflow-stage-admission.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +3 -2
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-row.js +8 -1
- package/dist/modes/interactive/components/task-row.js.map +1 -1
- package/docs/background-tasks.md +31 -2
- package/docs/compaction.md +20 -0
- package/docs/computer-use.md +390 -0
- package/docs/development.md +23 -74
- package/docs/docs.json +1 -0
- package/docs/extensions.md +15 -1
- package/docs/herdr.md +26 -77
- package/docs/index.md +1 -0
- package/docs/intercom.md +14 -2
- package/docs/models/evals.md +2 -0
- package/docs/models/model-selection.md +10 -7
- package/docs/quickstart.md +1 -1
- package/docs/sdk.md +11 -1
- package/docs/settings.md +24 -0
- package/docs/subagents.md +10 -6
- package/docs/tmux.md +2 -0
- package/docs/tools.md +11 -1
- package/docs/usage.md +1 -1
- package/docs/workflows/api-reference.md +5 -4
- package/docs/workflows/authoring.md +3 -3
- package/docs/workflows/operations.md +44 -33
- package/docs/workflows/reliable-design.md +3 -3
- package/docs/workflows/verification.md +99 -40
- package/docs/workflows.md +4 -2
- package/npm-shrinkwrap.json +59 -59
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.19-alpha.4] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- Workflow controls, completion, help, and status hints use `/workflow pause`, `/workflow quit`, and `/workflow resume`. The workflow tool supports run, stage, and individual durable-tool pause targets; `/workflow pause [run-id|--all]` controls runs. Workflow lifecycle control events report `action: "pause"` for pause requests.
|
|
10
|
+
- Renamed the bundled subagent `interrupt` action to `kill`. Migrate `subagent({ action: "interrupt", id })` to `subagent({ action: "kill", id })`, including calls using `runId`. The old action is no longer accepted. Kill terminally stops the child and cannot be resumed; follow-up work requires a fresh launch. Workflow controls use `/workflow pause`; parent cancellation behavior is unchanged.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Added a model row to the `/workflow connect` graph node cards showing each stage's effective model and thinking level, including canonical fast model identity, with model-name truncation preserving the suffixes. Cards retain duration, status and dependencies in a six-row layout, reflect live fallbacks, and restore identity through durable resume ([#1859](https://github.com/bastani-inc/atomic/pull/1859) by [@sina85](https://github.com/sina85)).
|
|
15
|
+
- Added `{ action: "wait", id, budgetMs }` to Bash and PowerShell for observing existing asynchronous tasks without rerunning commands. The observation budget is optional. Waits retain output and terminal metadata, follow owner observation policy, and release on cancellation or incoming messages without stopping execution or extending task lifetime.
|
|
16
|
+
- Added the agent-callable `kill({ id })` tool for owned background bash and PowerShell tasks in main and workflow-stage chat. It cancels by task ID, preserves retained output and original outcomes, reports current cleanup state, and rejects other owners' tasks and subagents.
|
|
17
|
+
- Added exact per-model overrides through `compaction.modelOverrides` for `compaction.reserveTokens` and Atomic's `compaction.preserve_recent` message count. Each field falls back to ordinary settings and then built-in defaults, with non-negative safe-integer validation. Manual, automatic, and post-tool compaction use the active model's budgets while retaining verbatim line compaction.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- First-loaded TypeScript extensions share the live host's classes and singletons when native import falls back to transformation, avoiding duplicate host evaluation and slow startup.
|
|
22
|
+
- Fixed repeated yielded shell waits replaying the first output page instead of progressing through retained output while the task is still running ([#2972](https://github.com/bastani-inc/atomic/pull/2972)).
|
|
23
|
+
- Preserved an explicit subagent kill when parent cancellation arrives during execution-capacity waiting, and kept grouped Intercom cancellation status consistent when a killed child has parent-cancelled siblings.
|
|
24
|
+
- Embedded Postgres now starts on Windows administrative accounts. PostgreSQL refuses to run for a member of the Administrators or Power Users groups, so Atomic launches the retained server process with the same restricted access token `pg_ctl` uses, keeping exact-process shutdown semantics; non-administrative Windows accounts are unchanged. Postgres processes that exit during startup (including that administrator refusal on older builds) now fail fast with the actual server log instead of a readiness timeout.
|
|
25
|
+
- Preserved embedded Postgres startup logs on regular Windows accounts, honored Unicode environment overrides on administrative launches, and prevented Windows handle leaks across repeated launches.
|
|
26
|
+
- Preserved `PATH` lookup and relative executable paths for administrative Windows Postgres launches. Invalid launch inputs containing embedded NUL characters now fail before starting a process rather than using truncated paths, arguments, or environment values.
|
|
27
|
+
- Fixed custom Windows Postgres `.cmd` and `.bat` launchers failing with arguments on administrative accounts, including launcher paths containing spaces. Batch arguments retain their existing quoting and line-break rejection.
|
|
28
|
+
- Fixed explicit `cmd.exe` Postgres launchers and safe verbatim working directories on Windows administrative accounts. Concurrent Postgres launches no longer keep one another's log files open or expose them to unrelated commands starting at the same time.
|
|
29
|
+
- Incoming Intercom send and ask messages now act as a priority interrupt queue for working subagents and live workflow stages: the receiver's current model call or cancellable tool is cancelled immediately and the message is processed within the same task, session, and stage generation. Admission survives consumed preflight input and overlapping SDK interrupt turns. Completed tool side effects are never replayed, the original task prompt is not repeated, multiple arrivals stay in arrival order with duplicate suppression, and exact ask/reply correlation survives the cancelled turn. Explicit user abort, host stop, and terminal/closed receivers still win: late input never restarts finished work.
|
|
30
|
+
- Fixed a deadlock where an extension event hook awaiting an ordinary context-only message could wait behind an inbound Intercom delivery that was itself waiting for that event hook.
|
|
31
|
+
- Inbound delivery retries after a transient persistence failure keep their original arrival position and remain part of both child and workflow-stage settlement, and a card appended before a failed flush is completed on retry instead of being appended a second time.
|
|
32
|
+
|
|
33
|
+
## [0.9.19-alpha.3] - 2026-09-09
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Fixed `Failed to initialize class constructor` when npm-installed Node sessions create multiple task supervisors, preventing shell commands and subagent launches from failing during task-host initialization.
|
|
38
|
+
- Fixed foreground subagent launches and explicit waits blocking parent user steering and incoming Intercom asks/sends. Admitted messages now release the waiting parent's observations in main and workflow-stage chat without cancelling children or affecting other owners.
|
|
39
|
+
- Fixed PowerShell internal-URL path quoting so apostrophes and smart single quotes in resolved paths remain literal instead of allowing injected commands. Bash quoting, deliberate shell commands, and balanced command prefixes are unchanged.
|
|
40
|
+
- Capped agent retry backoff with `retry.maxAgentDelayMs` (60 seconds by default), preserving independent provider retry limits ([#8826](https://github.com/earendil-works/pi/issues/8826)).
|
|
41
|
+
- Rejected extension tools with missing or non-object parameter schema containers during registration instead of breaking provider requests ([#9300](https://github.com/earendil-works/pi/issues/9300)).
|
|
42
|
+
- Workflow-stage pause now blocks new task launches, cancels active and admitted queued agents and commands, and waits for in-flight command admission and resource cleanup. Main-chat and sibling tasks stay unaffected; queued user and Intercom messages survive, and resume permits fresh work without restarting cancelled executions.
|
|
43
|
+
- Fixed npm-installed Node startup failing with a missing upstream AI package after the retry-policy update. Core retry imports now use Atomic's declared AI dependency.
|
|
44
|
+
- Fixed an unhandled rejection when session cancellation interrupts an in-flight stage-chat pause, while preserving pause error reporting and rejection for callers awaiting completion.
|
|
45
|
+
- Fixed Windows extension reloads re-evaluating Atomic's host modules, avoiding duplicate host classes and long reload delays while preserving edits to extension dependencies. The supported `@earendil-works/pi-coding-agent` import also shares host identity with `@bastani/atomic` after reload.
|
|
46
|
+
|
|
5
47
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
6
48
|
|
|
7
49
|
### Added
|
|
@@ -4,6 +4,21 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.19-alpha.4] - 2026-09-10
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Route lazy initialization, event-relay, and rejected-candidate cleanup diagnostics through the owning interactive session's notifications, including during shutdown, instead of leaking console output and stacks. Retryable initialization uses warning color; non-interactive console diagnostics (including RPC), original failures, acknowledgements, and retry behavior are preserved even when an error cannot be rendered.
|
|
12
|
+
- `send` and `ask` to a working subagent or live workflow stage are delivered as a priority interrupt: the recipient's active model call or cancellable tool is cancelled immediately and the message is processed in the same task instead of waiting for the next natural turn or being refused as busy. Completed side effects are not undone or replayed. Arrival order holds across persistence retries for both receiver kinds; duplicate suppression, exact reply correlation, terminal-child and closed-stage rejection, unrelated headless protection, and group restrictions are unchanged.
|
|
13
|
+
- A cancelled turn that produced no reply no longer consumes the pending ask's reply context, so replies to consecutive asks stay correlated with the right sender and message.
|
|
14
|
+
|
|
15
|
+
## [0.9.19-alpha.3] - 2026-09-09
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Session listings display host-provided live/terminal reply capability separately from idle activity. Closed workflow generations publish `closed` with post-mortem-only or unavailable reply routing rather than remaining misleadingly idle; group isolation and ask rejection rules are unchanged.
|
|
20
|
+
- Canonical workflow-path asks correlate replies from connected retained stages even after their active roster rows disappear. Closed stages without post-mortem routing reject asks with lifecycle guidance rather than attempting a model turn.
|
|
21
|
+
|
|
7
22
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
8
23
|
|
|
9
24
|
### Breaking Changes
|
|
@@ -86,6 +86,7 @@ interface PendingStageAcknowledgment {
|
|
|
86
86
|
readonly message: Message;
|
|
87
87
|
readonly liveTargetId?: string;
|
|
88
88
|
readonly signature?: string;
|
|
89
|
+
readonly resolveReplyTarget?: true;
|
|
89
90
|
readonly timeout: NodeJS.Timeout;
|
|
90
91
|
}
|
|
91
92
|
|
|
@@ -681,6 +682,7 @@ class IntercomBroker {
|
|
|
681
682
|
message: route.message,
|
|
682
683
|
...(route.liveTargetId === undefined ? {} : { liveTargetId: route.liveTargetId }),
|
|
683
684
|
...(route.signature === undefined ? {} : { signature: route.signature }),
|
|
685
|
+
...(route.resolveReplyTarget === true ? { resolveReplyTarget: true } : {}),
|
|
684
686
|
timeout,
|
|
685
687
|
});
|
|
686
688
|
if (
|
|
@@ -828,6 +830,8 @@ class IntercomBroker {
|
|
|
828
830
|
return;
|
|
829
831
|
}
|
|
830
832
|
this.pendingQuestions.record(from.info.id, target.info.id, pending.messageId);
|
|
833
|
+
if (pending.resolveReplyTarget === true && pending.attemptId !== undefined)
|
|
834
|
+
writeMessageIfOpen(pending.senderSocket, { type: "question_target", messageId: pending.messageId, attemptId: pending.attemptId, sessionId: target.info.id });
|
|
831
835
|
}
|
|
832
836
|
writeMessageIfOpen(pending.senderSocket, {
|
|
833
837
|
type: "delivered",
|
|
@@ -880,6 +884,8 @@ class IntercomBroker {
|
|
|
880
884
|
return;
|
|
881
885
|
}
|
|
882
886
|
this.pendingQuestions.record(from.info.id, target.info.id, pending.messageId);
|
|
887
|
+
if (pending.resolveReplyTarget === true && pending.attemptId !== undefined)
|
|
888
|
+
writeMessageIfOpen(pending.senderSocket, { type: "question_target", messageId: pending.messageId, attemptId: pending.attemptId, sessionId: target.info.id });
|
|
883
889
|
}
|
|
884
890
|
writeMessageIfOpen(pending.senderSocket, {
|
|
885
891
|
type: "delivered",
|
|
@@ -903,6 +909,8 @@ class IntercomBroker {
|
|
|
903
909
|
});
|
|
904
910
|
return;
|
|
905
911
|
}
|
|
912
|
+
if (pending.message.expectsReply === true && pending.resolveReplyTarget === true && pending.attemptId !== undefined)
|
|
913
|
+
writeMessageIfOpen(pending.senderSocket, { type: "question_target", messageId: pending.messageId, attemptId: pending.attemptId, sessionId: target.info.id });
|
|
906
914
|
if (!writeMessageIfOpen(target.socket, { type: "message", from: pending.sender, message: pending.message })) {
|
|
907
915
|
this.deliveredMessages.forget(pending.messageId, pending.signature);
|
|
908
916
|
writeMessageIfOpen(pending.senderSocket, {
|
|
@@ -38,6 +38,8 @@ export interface SendOptions {
|
|
|
38
38
|
logicalTarget?: string;
|
|
39
39
|
/** Public reply must use the broker's exact pending reverse question route. */
|
|
40
40
|
requirePendingReply?: true;
|
|
41
|
+
/** Broker-authorized identity for a canonical-path ask, delivered before its recipient can reply. */
|
|
42
|
+
onReplyTarget?: (sessionId: string) => void;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export interface SendResult {
|
|
@@ -153,6 +155,7 @@ export class IntercomClient extends EventEmitter {
|
|
|
153
155
|
/** Source identity is captured once at connect, never read from env per message. */
|
|
154
156
|
private _messageSource: Message["source"] | undefined;
|
|
155
157
|
private pendingSends = new PendingSendRegistry();
|
|
158
|
+
private pendingReplyTargets = new Map<string, { messageId: string; bind(sessionId: string): void }>();
|
|
156
159
|
private pendingGroupLists = new Map<string, { resolve: (groups: GroupSummary[]) => void; reject: (error: Error) => void }>();
|
|
157
160
|
private pendingLists = new Map<string, { resolve: (directory: SessionDirectory) => void; reject: (e: Error) => void }>();
|
|
158
161
|
private pendingPresence = new Map<string, {
|
|
@@ -415,6 +418,15 @@ export class IntercomClient extends EventEmitter {
|
|
|
415
418
|
this.emit("_registration_failed", new Error(brokerMessage.reason));
|
|
416
419
|
break;
|
|
417
420
|
}
|
|
421
|
+
case "question_target": {
|
|
422
|
+
const { messageId, attemptId, sessionId } = brokerMessage;
|
|
423
|
+
if (typeof messageId !== "string" || typeof attemptId !== "string" || typeof sessionId !== "string") {
|
|
424
|
+
throw new Error("Invalid question_target message");
|
|
425
|
+
}
|
|
426
|
+
const pending = this.pendingReplyTargets.get(attemptId);
|
|
427
|
+
if (pending?.messageId === messageId) pending.bind(sessionId);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
418
430
|
case "sessions": {
|
|
419
431
|
const { requestId, sessions, workflowStages, workflowFutureStages } = brokerMessage;
|
|
420
432
|
if (
|
|
@@ -989,12 +1001,16 @@ export class IntercomClient extends EventEmitter {
|
|
|
989
1001
|
source: this._messageSource,
|
|
990
1002
|
content: { text: options.text, attachments: options.attachments },
|
|
991
1003
|
};
|
|
1004
|
+
if (options.onReplyTarget !== undefined) {
|
|
1005
|
+
this.pendingReplyTargets.set(acquired.attempt.attemptId, { messageId, bind: options.onReplyTarget });
|
|
1006
|
+
}
|
|
992
1007
|
try {
|
|
993
1008
|
writeMessage(socket, {
|
|
994
1009
|
type,
|
|
995
1010
|
to,
|
|
996
1011
|
...(options.logicalTarget === undefined ? {} : { logicalTarget: options.logicalTarget }),
|
|
997
1012
|
...(options.requirePendingReply === undefined ? {} : { requirePendingReply: options.requirePendingReply }),
|
|
1013
|
+
...(options.onReplyTarget === undefined ? {} : { resolveReplyTarget: true as const }),
|
|
998
1014
|
message,
|
|
999
1015
|
attemptId: acquired.attempt.attemptId,
|
|
1000
1016
|
...extra,
|
|
@@ -1002,6 +1018,8 @@ export class IntercomClient extends EventEmitter {
|
|
|
1002
1018
|
} catch (error) {
|
|
1003
1019
|
this.pendingSends.reject(acquired.attempt, toError(error));
|
|
1004
1020
|
}
|
|
1021
|
+
const clearReplyTarget = () => { this.pendingReplyTargets.delete(acquired.attempt.attemptId); };
|
|
1022
|
+
void acquired.attempt.promise.then(clearReplyTarget, clearReplyTarget);
|
|
1005
1023
|
return acquired.attempt.promise;
|
|
1006
1024
|
}
|
|
1007
1025
|
updatePresence(updates: PresenceUpdates): boolean {
|
|
@@ -59,6 +59,7 @@ export interface PendingStageRoute {
|
|
|
59
59
|
readonly attemptId?: string;
|
|
60
60
|
readonly liveTargetId?: string;
|
|
61
61
|
readonly signature?: string;
|
|
62
|
+
readonly resolveReplyTarget?: true;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
export type PendingStageRouter = (route: PendingStageRoute) => boolean;
|
|
@@ -326,6 +327,8 @@ export function handleBrokerSend(
|
|
|
326
327
|
return;
|
|
327
328
|
}
|
|
328
329
|
pendingQuestions.record(fromSession.info.id, target.info.id, message.id);
|
|
330
|
+
if (clientMessage.resolveReplyTarget === true && attemptId !== undefined)
|
|
331
|
+
write(socket, { type: "question_target", messageId: message.id, attemptId, sessionId: target.info.id });
|
|
329
332
|
}
|
|
330
333
|
write(socket, { type: "delivered", messageId: message.id, attemptId });
|
|
331
334
|
return;
|
|
@@ -369,6 +372,7 @@ export function handleBrokerSend(
|
|
|
369
372
|
...(attemptId ? { attemptId } : {}),
|
|
370
373
|
liveTargetId: target.info.id,
|
|
371
374
|
signature,
|
|
375
|
+
...(clientMessage.resolveReplyTarget === true ? { resolveReplyTarget: true } : {}),
|
|
372
376
|
})
|
|
373
377
|
) {
|
|
374
378
|
return;
|
|
@@ -416,6 +420,8 @@ export function handleBrokerSend(
|
|
|
416
420
|
return;
|
|
417
421
|
}
|
|
418
422
|
if (message.expectsReply === true) pendingQuestions.record(fromSession.info.id, target.info.id, message.id);
|
|
423
|
+
if (message.expectsReply === true && clientMessage.resolveReplyTarget === true && attemptId !== undefined)
|
|
424
|
+
write(socket, { type: "question_target", messageId: message.id, attemptId, sessionId: target.info.id });
|
|
419
425
|
write(socket, { type: "delivered", messageId: message.id, attemptId });
|
|
420
426
|
return;
|
|
421
427
|
}
|
|
@@ -433,6 +439,8 @@ export function handleBrokerSend(
|
|
|
433
439
|
});
|
|
434
440
|
return;
|
|
435
441
|
}
|
|
442
|
+
if (message.expectsReply === true && clientMessage.resolveReplyTarget === true && attemptId !== undefined)
|
|
443
|
+
write(socket, { type: "question_target", messageId: message.id, attemptId, sessionId: target.info.id });
|
|
436
444
|
const finishDelivery = (): void => {
|
|
437
445
|
let accepted: ReturnType<DeliveredMessageCache["accept"]>;
|
|
438
446
|
try {
|
|
@@ -508,6 +516,7 @@ export function handleBrokerSend(
|
|
|
508
516
|
message,
|
|
509
517
|
...(attemptId ? { attemptId } : {}),
|
|
510
518
|
signature,
|
|
519
|
+
...(clientMessage.resolveReplyTarget === true ? { resolveReplyTarget: true } : {}),
|
|
511
520
|
})
|
|
512
521
|
) {
|
|
513
522
|
return;
|