@bastani/atomic 0.9.39-alpha.2 → 0.9.40-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/dist/builtin/intercom/CHANGELOG.md +20 -0
- package/dist/builtin/intercom/broker/broker.ts +523 -72
- package/dist/builtin/intercom/broker/client.ts +136 -5
- package/dist/builtin/intercom/broker/database-wake-up-bus.ts +274 -0
- package/dist/builtin/intercom/broker/group-membership.ts +2 -2
- package/dist/builtin/intercom/broker/multinode-router.ts +1500 -0
- package/dist/builtin/intercom/broker/multinode-state-store.ts +569 -0
- package/dist/builtin/intercom/broker/open-broker-state.ts +160 -0
- package/dist/builtin/intercom/broker/paths.ts +6 -0
- package/dist/builtin/intercom/broker/pending-send-registry.ts +14 -0
- package/dist/builtin/intercom/broker/recipient-receipts.ts +93 -0
- package/dist/builtin/intercom/broker/restoring-recipients.ts +263 -0
- package/dist/builtin/intercom/broker/send-handler.ts +241 -25
- package/dist/builtin/intercom/broker/session-id-reclaim.ts +41 -0
- package/dist/builtin/intercom/broker/socket-writes.ts +47 -0
- package/dist/builtin/intercom/broker/spawn.ts +10 -2
- package/dist/builtin/intercom/broker/sql-held-send-store.ts +96 -0
- package/dist/builtin/intercom/broker/sql-known-session-store.ts +129 -0
- package/dist/builtin/intercom/broker/sql-lease-store.ts +194 -0
- package/dist/builtin/intercom/broker/sql-outbox-store.ts +249 -0
- package/dist/builtin/intercom/broker/sql-pending-ask-store.ts +105 -0
- package/dist/builtin/intercom/broker/sql-restoring-reservation-store.ts +295 -0
- package/dist/builtin/intercom/broker/sql-sent-message-authority.ts +126 -0
- package/dist/builtin/intercom/broker/supervisor-channel.ts +10 -0
- package/dist/builtin/intercom/broker/wake-up-bus.ts +60 -0
- package/dist/builtin/intercom/index.bundle.mjs +793 -91
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/retry-policy.ts +4 -0
- package/dist/builtin/intercom/session-target.ts +24 -0
- package/dist/builtin/intercom/types.ts +57 -3
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +37 -0
- package/dist/builtin/subagents/README.md +18 -12
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/skills/agent-browser/SKILL.md +1 -1
- package/dist/builtin/subagents/skills/cua-driver/BROWSER.md +55 -8
- package/dist/builtin/subagents/skills/cua-driver/EMBEDDING.md +7 -2
- package/dist/builtin/subagents/skills/cua-driver/LINUX.md +7 -1
- package/dist/builtin/subagents/skills/cua-driver/MACOS.md +151 -27
- package/dist/builtin/subagents/skills/cua-driver/RUNTIME.md +1 -1
- package/dist/builtin/subagents/skills/cua-driver/SKILL.md +33 -17
- package/dist/builtin/subagents/skills/cua-driver/WINDOWS.md +5 -0
- package/dist/builtin/subagents/skills/cua-driver/WORKFLOW.md +46 -8
- package/dist/builtin/subagents/skills/subagent/SKILL.md +18 -20
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +8032 -6034
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +32 -0
- package/dist/builtin/workflows/README.md +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +8 -8
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.native.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +4 -2
- package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/craft-floor.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +22 -9
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/distill.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/extract.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/harden.md +2 -4
- package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +4 -4
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +6 -6
- package/dist/builtin/workflows/skills/impeccable/reference/onboard.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +10 -0
- package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/VERSION +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable +6 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable.cmd +47 -22
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-dom.js +34 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-session.js +25 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +33 -8
- package/dist/builtin/workflows/src/durable/journal/resolution.d.ts +7 -7
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +22855 -22308
- package/dist/builtin/workflows/src/index.js +106 -35
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +16 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +2 -0
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +6 -6
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +6 -3
- 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 +7 -2
- package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
- package/dist/core/agent-session-persistent-custom-messages.js +29 -12
- package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
- package/dist/core/agent-session-recovery.d.ts +14 -0
- package/dist/core/agent-session-recovery.d.ts.map +1 -0
- package/dist/core/agent-session-recovery.js +83 -0
- package/dist/core/agent-session-recovery.js.map +1 -0
- package/dist/core/agent-session-tasks.d.ts.map +1 -1
- package/dist/core/agent-session-tasks.js +4 -6
- package/dist/core/agent-session-tasks.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +13 -0
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/api-types.d.ts +6 -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/event-results.d.ts +21 -0
- package/dist/core/extensions/event-results.d.ts.map +1 -1
- package/dist/core/extensions/event-results.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- 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.map +1 -1
- package/dist/core/extensions/loader-api.js +4 -0
- package/dist/core/extensions/loader-api.js.map +1 -1
- package/dist/core/extensions/runner-events.d.ts +9 -2
- package/dist/core/extensions/runner-events.d.ts.map +1 -1
- package/dist/core/extensions/runner-events.js +29 -0
- package/dist/core/extensions/runner-events.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +7 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +1 -0
- 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/session-events.d.ts +30 -2
- package/dist/core/extensions/session-events.d.ts.map +1 -1
- package/dist/core/extensions/session-events.js.map +1 -1
- package/dist/core/sdk-types.d.ts +3 -2
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +15 -9
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/storage/process-selection.d.ts +39 -0
- package/dist/core/storage/process-selection.d.ts.map +1 -0
- package/dist/core/storage/process-selection.js +154 -0
- package/dist/core/storage/process-selection.js.map +1 -0
- package/dist/core/storage/provider.d.ts +6 -1
- package/dist/core/storage/provider.d.ts.map +1 -1
- package/dist/core/storage/provider.js +3 -2
- package/dist/core/storage/provider.js.map +1 -1
- package/dist/core/storage/selection.d.ts +1 -1
- package/dist/core/storage/selection.d.ts.map +1 -1
- package/dist/core/storage/selection.js.map +1 -1
- package/dist/core/storage/session/jsonl-session-store.d.ts +2 -0
- package/dist/core/storage/session/jsonl-session-store.d.ts.map +1 -1
- package/dist/core/storage/session/jsonl-session-store.js +38 -2
- package/dist/core/storage/session/jsonl-session-store.js.map +1 -1
- package/dist/core/tasks/completion.d.ts +11 -2
- package/dist/core/tasks/completion.d.ts.map +1 -1
- package/dist/core/tasks/completion.js +40 -16
- package/dist/core/tasks/completion.js.map +1 -1
- package/dist/core/tasks/pause.d.ts +4 -1
- package/dist/core/tasks/pause.d.ts.map +1 -1
- package/dist/core/tasks/pause.js +8 -5
- package/dist/core/tasks/pause.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +7 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js +11 -1
- package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.d.ts +2 -0
- package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-state.js +2 -0
- package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +4 -0
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -1
- 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-render-chat.js +3 -0
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +2 -0
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.d.ts +2 -1
- package/dist/modes/interactive/interactive-session-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-session-runtime.js +29 -0
- package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +4 -1
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive-engine/engine-args.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-args.js +4 -0
- package/dist/modes/interactive-engine/engine-args.js.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.d.ts.map +1 -1
- package/dist/modes/interactive-engine/engine-render-service.js +4 -4
- package/dist/modes/interactive-engine/engine-render-service.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +4 -0
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js +1 -1
- package/dist/modes/interactive-engine/remote-renderer.js.map +1 -1
- package/dist/modes/rpc/rpc-client-api.d.ts +4 -1
- package/dist/modes/rpc/rpc-client-api.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client-api.js +4 -0
- package/dist/modes/rpc/rpc-client-api.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +3 -0
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-command-timeouts.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-timeouts.js +1 -0
- package/dist/modes/rpc/rpc-command-timeouts.js.map +1 -1
- package/dist/modes/rpc/rpc-input-scheduler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-scheduler.js +6 -1
- package/dist/modes/rpc/rpc-input-scheduler.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +12 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +44 -11
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/tools-manager.js +1 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/background-tasks.md +5 -3
- package/docs/computer-use.md +2 -2
- package/docs/environment-variables.md +4 -1
- package/docs/extensions/events.md +29 -2
- package/docs/getting-started/first-session.md +1 -1
- package/docs/guides/intercom.md +1 -1
- package/docs/intercom/operations.md +103 -1
- package/docs/intercom/reference.md +10 -3
- package/docs/intercom.md +8 -6
- package/docs/keybindings.md +1 -1
- package/docs/models.md +1 -1
- package/docs/providers.md +4 -2
- package/docs/reference/cli.md +5 -0
- package/docs/rpc/protocol.md +19 -0
- package/docs/rpc.md +3 -0
- package/docs/sdk/web-server.md +1 -1
- package/docs/sdk.md +5 -2
- package/docs/sessions.md +17 -1
- package/docs/settings.md +5 -3
- package/docs/skills.md +1 -1
- package/docs/storage.md +54 -3
- package/docs/subagents.md +49 -9
- package/docs/usage.md +1 -1
- package/docs/windows.md +14 -4
- package/docs/workflows/api-reference.md +1 -1
- package/docs/workflows/authoring.md +1 -1
- package/docs/workflows/operations.md +10 -6
- package/npm-shrinkwrap.json +37 -37
- package/package.json +4 -4
|
@@ -164,7 +164,7 @@ var init_recoverable_disconnect = __esm(() => {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
// dist/builtin/intercom/retry-policy.ts
|
|
167
|
-
var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS;
|
|
167
|
+
var ASK_REPLY_TIMEOUT_MS, RETRY_IDENTITY_RETRY_OPPORTUNITY_MS, RETRY_IDENTITY_TTL_MS, DELIVERED_MESSAGE_TTL_MS, RECONNECT_DELAYS_MS, SEND_RESPONSE_TIMEOUT_MS = 1e4;
|
|
168
168
|
var init_retry_policy = __esm(() => {
|
|
169
169
|
ASK_REPLY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
170
170
|
RETRY_IDENTITY_RETRY_OPPORTUNITY_MS = 60 * 1000;
|
|
@@ -182,6 +182,298 @@ var init_reconnect_backoff = __esm(() => {
|
|
|
182
182
|
BACKOFF_MS = [1000, 2000, 5000, 1e4, 30000];
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
+
// dist/builtin/intercom/session-recovery.ts
|
|
186
|
+
async function awaitRestoredIntercomPeers(events, ownerSessionId) {
|
|
187
|
+
const request = { ownerSessionId };
|
|
188
|
+
try {
|
|
189
|
+
events.emit(SUBAGENT_RESTORED_INTERCOM_PEERS_EVENT, request);
|
|
190
|
+
return request.completion ? await request.completion : [];
|
|
191
|
+
} catch {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function isReserveRestoringChildRequest(value) {
|
|
196
|
+
if (!value || typeof value !== "object")
|
|
197
|
+
return false;
|
|
198
|
+
const request = value;
|
|
199
|
+
return typeof request.capability === "string" && request.capability.length > 0 && (request.group === undefined || typeof request.group === "string") && (request.dormant === undefined || typeof request.dormant === "boolean") && Array.isArray(request.aliases) && request.aliases.every((alias) => typeof alias === "string");
|
|
200
|
+
}
|
|
201
|
+
function isReleaseRestoringChildRequest(value) {
|
|
202
|
+
if (!value || typeof value !== "object")
|
|
203
|
+
return false;
|
|
204
|
+
const request = value;
|
|
205
|
+
return typeof request.capability === "string" && request.capability.length > 0 && (request.gone === undefined || typeof request.gone === "string") && (request.refusal === undefined || typeof request.refusal === "string");
|
|
206
|
+
}
|
|
207
|
+
async function awaitSubagentChildRestoration(events, ownerSessionId, target) {
|
|
208
|
+
const request = { ownerSessionId, target, timeoutMs: CHILD_RESTORATION_WAIT_MS };
|
|
209
|
+
try {
|
|
210
|
+
events.emit(SUBAGENT_AWAIT_CHILD_RESTORATION_EVENT, request);
|
|
211
|
+
return request.completion ? await request.completion : undefined;
|
|
212
|
+
} catch {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function isAwaitIntercomPeerRequest(value) {
|
|
217
|
+
const request = value;
|
|
218
|
+
return typeof request.name === "string" && request.name.trim().length > 0 && typeof request.timeoutMs === "number" && (request.group === undefined || typeof request.group === "string");
|
|
219
|
+
}
|
|
220
|
+
function hasIntercomHistory(entries) {
|
|
221
|
+
return entries.some((entry) => entry.type === "custom_message" && entry.customType === "intercom_message" || entry.type === "custom" && entry.customType === "intercom_inbox" || entry.type === "custom" && entry.customType === "subagent-child" || entry.type === "message" && entry.message.role === "toolResult" && (entry.message.toolName === "intercom" || entry.message.toolName === "contact_supervisor"));
|
|
222
|
+
}
|
|
223
|
+
async function waitForIntercomPeer(client, request) {
|
|
224
|
+
const name = request.name.trim().toLowerCase();
|
|
225
|
+
const deadline = Date.now() + request.timeoutMs;
|
|
226
|
+
for (;; ) {
|
|
227
|
+
const sessions = await client.listSessions(request.group);
|
|
228
|
+
if (sessions.some((session) => session.name?.trim().toLowerCase() === name))
|
|
229
|
+
return true;
|
|
230
|
+
if (Date.now() + PEER_POLL_INTERVAL_MS > deadline)
|
|
231
|
+
return false;
|
|
232
|
+
await new Promise((resolve) => setTimeout(resolve, PEER_POLL_INTERVAL_MS));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function inboundEntry(delivery) {
|
|
236
|
+
if (delivery.customType !== "intercom_message")
|
|
237
|
+
return;
|
|
238
|
+
const details = delivery.details;
|
|
239
|
+
return typeof details?.from?.id === "string" && typeof details.message?.id === "string" ? details : undefined;
|
|
240
|
+
}
|
|
241
|
+
function peerLabel(from) {
|
|
242
|
+
return from.name ? `\`${from.name}\`` : `\`${from.id}\``;
|
|
243
|
+
}
|
|
244
|
+
function isLivePeer(from, peers) {
|
|
245
|
+
const name = from.name?.trim().toLowerCase();
|
|
246
|
+
return peers.some((peer) => peer.id === from.id || name !== undefined && peer.name?.trim().toLowerCase() === name);
|
|
247
|
+
}
|
|
248
|
+
function isRestoredPeer(from, restored) {
|
|
249
|
+
const name = from.name?.trim().toLowerCase();
|
|
250
|
+
return restored.some((peer) => peer.ids.includes(from.id) || name !== undefined && peer.name.trim().toLowerCase() === name);
|
|
251
|
+
}
|
|
252
|
+
function boundedBody(text) {
|
|
253
|
+
return text.length > RECOVERED_BODY_MAX_CHARS ? `${text.slice(0, RECOVERED_BODY_MAX_CHARS)}…` : text;
|
|
254
|
+
}
|
|
255
|
+
function planIntercomRecoveryReplay(pending, peers, restored = []) {
|
|
256
|
+
const decisions = [];
|
|
257
|
+
const gone = new Map;
|
|
258
|
+
const deferred = new Map;
|
|
259
|
+
const reconnecting = new Map;
|
|
260
|
+
const tally = (counts, key, from) => {
|
|
261
|
+
const sender = counts.get(key) ?? { from, count: 0 };
|
|
262
|
+
sender.count += 1;
|
|
263
|
+
counts.set(key, sender);
|
|
264
|
+
};
|
|
265
|
+
for (const delivery of pending) {
|
|
266
|
+
const entry = inboundEntry(delivery);
|
|
267
|
+
if (!entry || LOCAL_RELAY_SENDERS.has(entry.from.id))
|
|
268
|
+
continue;
|
|
269
|
+
const key = entry.from.name?.trim().toLowerCase() ?? entry.from.id;
|
|
270
|
+
if (peers === undefined) {
|
|
271
|
+
decisions.push({ entryId: delivery.entryId, action: "defer" });
|
|
272
|
+
tally(deferred, key, entry.from);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (isLivePeer(entry.from, peers)) {
|
|
276
|
+
decisions.push({ entryId: delivery.entryId, action: "replay" });
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (isRestoredPeer(entry.from, restored)) {
|
|
280
|
+
decisions.push({ entryId: delivery.entryId, action: "defer" });
|
|
281
|
+
tally(reconnecting, key, entry.from);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
decisions.push({ entryId: delivery.entryId, action: "drop" });
|
|
285
|
+
const group = gone.get(key) ?? { from: entry.from, entries: [] };
|
|
286
|
+
group.entries.push(entry);
|
|
287
|
+
gone.set(key, group);
|
|
288
|
+
}
|
|
289
|
+
const notices = [...gone.values()].map(({ from, entries }) => {
|
|
290
|
+
const history = entries.map((entry) => `- Sent ${new Date(entry.message.timestamp).toISOString()}: ${boundedBody(entry.bodyText)}`).join(`
|
|
291
|
+
`);
|
|
292
|
+
return `Intercom peer ${peerLabel(from)} is gone: it is no longer connected after the restart. ${entries.length} message(s) it sent before the restart were not replayed as new turns; they are shown here as history only. Do not reply to it or send it new messages; launch a fresh subagent if its work is still needed.
|
|
293
|
+
${history}`;
|
|
294
|
+
});
|
|
295
|
+
for (const { from, count } of reconnecting.values()) {
|
|
296
|
+
notices.push(`Intercom peer ${peerLabel(from)} was relaunched after the restart but has not reconnected to Intercom yet, so ${count === 1 ? "1 interrupted delivery" : `${count} interrupted deliveries`} from it ${count === 1 ? "was" : "were"} deferred: not replayed now and not discarded. It is not gone; treat it as unreachable until it reconnects. The next resume of this session tries them again.`);
|
|
297
|
+
}
|
|
298
|
+
if (deferred.size > 0) {
|
|
299
|
+
const count = [...deferred.values()].reduce((total, sender) => total + sender.count, 0);
|
|
300
|
+
const senders = [...deferred.values()].map(({ from }) => peerLabel(from)).join(", ");
|
|
301
|
+
notices.push(`Intercom could not be reached after the restart, so ${count === 1 ? "1 interrupted Intercom delivery" : `${count} interrupted Intercom deliveries`} from ${senders} ${count === 1 ? "was" : "were"} deferred: not replayed now and not discarded. Whether their senders are still connected is unknown. The next resume of this session tries them again.`);
|
|
302
|
+
}
|
|
303
|
+
return { decisions, ...notices.length > 0 ? { notices } : {} };
|
|
304
|
+
}
|
|
305
|
+
var SUBAGENT_AWAIT_INTERCOM_PEER_EVENT = "subagent:await-intercom-peer", SUBAGENT_AWAIT_CHILD_RESTORATION_EVENT = "subagent:await-child-restoration", CHILD_RESTORATION_WAIT_MS = 20000, SUBAGENT_RESERVE_RESTORING_CHILD_EVENT = "subagent:reserve-restoring-child", SUBAGENT_RELEASE_RESTORING_CHILD_EVENT = "subagent:release-restoring-child", SUBAGENT_RESTORED_INTERCOM_PEERS_EVENT = "subagent:restored-intercom-peers", INTERCOM_RECOVERY_PEERS_EVENT = "intercom:recovery-peers", PEER_POLL_INTERVAL_MS = 200, RECOVERED_BODY_MAX_CHARS = 2000, LOCAL_RELAY_SENDERS;
|
|
306
|
+
var init_session_recovery = __esm(() => {
|
|
307
|
+
LOCAL_RELAY_SENDERS = new Set(["subagent-control", "subagent-result"]);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// dist/builtin/intercom/broker/client-message-validation.ts
|
|
311
|
+
function isAttachment(value) {
|
|
312
|
+
if (typeof value !== "object" || value === null)
|
|
313
|
+
return false;
|
|
314
|
+
const attachment = value;
|
|
315
|
+
if (attachment.type !== "file" && attachment.type !== "snippet" && attachment.type !== "context")
|
|
316
|
+
return false;
|
|
317
|
+
if (typeof attachment.name !== "string" || typeof attachment.content !== "string")
|
|
318
|
+
return false;
|
|
319
|
+
return attachment.language === undefined || typeof attachment.language === "string";
|
|
320
|
+
}
|
|
321
|
+
function isMessageSource(value) {
|
|
322
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
323
|
+
return false;
|
|
324
|
+
const source = value;
|
|
325
|
+
return typeof source.subagentRunId === "string" && (source.subagentAgent === undefined || typeof source.subagentAgent === "string") && (source.subagentIndex === undefined || typeof source.subagentIndex === "number");
|
|
326
|
+
}
|
|
327
|
+
function isMessage(value) {
|
|
328
|
+
if (typeof value !== "object" || value === null)
|
|
329
|
+
return false;
|
|
330
|
+
const message = value;
|
|
331
|
+
if (typeof message.id !== "string" || typeof message.timestamp !== "number")
|
|
332
|
+
return false;
|
|
333
|
+
if (message.replyTo !== undefined && typeof message.replyTo !== "string")
|
|
334
|
+
return false;
|
|
335
|
+
if (message.expectsReply !== undefined && typeof message.expectsReply !== "boolean")
|
|
336
|
+
return false;
|
|
337
|
+
if (message.replyError !== undefined && typeof message.replyError !== "string")
|
|
338
|
+
return false;
|
|
339
|
+
if (message.source !== undefined && !isMessageSource(message.source))
|
|
340
|
+
return false;
|
|
341
|
+
if (typeof message.content !== "object" || message.content === null)
|
|
342
|
+
return false;
|
|
343
|
+
const content = message.content;
|
|
344
|
+
if (typeof content.text !== "string")
|
|
345
|
+
return false;
|
|
346
|
+
return content.attachments === undefined || Array.isArray(content.attachments) && content.attachments.every(isAttachment);
|
|
347
|
+
}
|
|
348
|
+
function isSessionInfo(value) {
|
|
349
|
+
if (typeof value !== "object" || value === null)
|
|
350
|
+
return false;
|
|
351
|
+
const session = value;
|
|
352
|
+
if (typeof session.id !== "string" || typeof session.cwd !== "string" || typeof session.model !== "string" || typeof session.pid !== "number" || typeof session.startedAt !== "number" || typeof session.lastActivity !== "number")
|
|
353
|
+
return false;
|
|
354
|
+
if (session.name !== undefined && typeof session.name !== "string")
|
|
355
|
+
return false;
|
|
356
|
+
if (session.group !== undefined && typeof session.group !== "string")
|
|
357
|
+
return false;
|
|
358
|
+
return session.status === undefined || typeof session.status === "string";
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// dist/builtin/intercom/durable-inbox.ts
|
|
362
|
+
function inboxRecord(entry) {
|
|
363
|
+
if (entry.type !== "custom" || entry.customType !== INTERCOM_INBOX_ENTRY)
|
|
364
|
+
return;
|
|
365
|
+
const data = entry.data;
|
|
366
|
+
if (!isMessage(data?.message) || !isSessionInfo(data.from) || typeof data.receivedAt !== "number")
|
|
367
|
+
return;
|
|
368
|
+
return {
|
|
369
|
+
message: data.message,
|
|
370
|
+
from: data.from,
|
|
371
|
+
receivedAt: data.receivedAt,
|
|
372
|
+
...data.channel === "supervisor" ? { channel: "supervisor" } : {}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function consumedIntercomMessageIds(entries) {
|
|
376
|
+
const ids = new Set;
|
|
377
|
+
for (const entry of entries) {
|
|
378
|
+
if (entry.type !== "custom_message" || entry.customType !== "intercom_message")
|
|
379
|
+
continue;
|
|
380
|
+
const id = entry.details?.message?.id;
|
|
381
|
+
if (typeof id === "string")
|
|
382
|
+
ids.add(id);
|
|
383
|
+
}
|
|
384
|
+
return ids;
|
|
385
|
+
}
|
|
386
|
+
function handledIntercomMessageIds(entries) {
|
|
387
|
+
const ids = new Set;
|
|
388
|
+
for (const entry of entries) {
|
|
389
|
+
if (entry.type !== "custom")
|
|
390
|
+
continue;
|
|
391
|
+
if (entry.customType !== "intercom_received" && entry.customType !== INTERCOM_INBOX_HANDLED_ENTRY)
|
|
392
|
+
continue;
|
|
393
|
+
const id = entry.data?.messageId;
|
|
394
|
+
if (typeof id === "string")
|
|
395
|
+
ids.add(id);
|
|
396
|
+
}
|
|
397
|
+
return ids;
|
|
398
|
+
}
|
|
399
|
+
function savedIntercomMessageIds(entries) {
|
|
400
|
+
const ids = new Set;
|
|
401
|
+
for (const entry of entries) {
|
|
402
|
+
const record = inboxRecord(entry);
|
|
403
|
+
if (record !== undefined)
|
|
404
|
+
ids.add(record.message.id);
|
|
405
|
+
}
|
|
406
|
+
return ids;
|
|
407
|
+
}
|
|
408
|
+
function unconsumedIntercomInbox(entries) {
|
|
409
|
+
const branch = [...entries];
|
|
410
|
+
const consumed = consumedIntercomMessageIds(branch);
|
|
411
|
+
for (const id of handledIntercomMessageIds(branch))
|
|
412
|
+
consumed.add(id);
|
|
413
|
+
const records = new Map;
|
|
414
|
+
for (const entry of branch) {
|
|
415
|
+
const record = inboxRecord(entry);
|
|
416
|
+
if (record === undefined || consumed.has(record.message.id) || records.has(record.message.id))
|
|
417
|
+
continue;
|
|
418
|
+
records.set(record.message.id, record);
|
|
419
|
+
}
|
|
420
|
+
return [...records.values()].sort((left, right) => left.receivedAt - right.receivedAt);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
class DurableInbox {
|
|
424
|
+
options;
|
|
425
|
+
saved = new Set;
|
|
426
|
+
tail = Promise.resolve();
|
|
427
|
+
constructor(options) {
|
|
428
|
+
this.options = options;
|
|
429
|
+
}
|
|
430
|
+
receive(from, message, channel, acknowledge) {
|
|
431
|
+
const arrival = this.tail.then(() => this.save(from, message, channel, acknowledge));
|
|
432
|
+
this.tail = arrival.then(() => {}, () => {});
|
|
433
|
+
return arrival;
|
|
434
|
+
}
|
|
435
|
+
async handledWithoutCard(messageId) {
|
|
436
|
+
if (!this.options.durable())
|
|
437
|
+
return;
|
|
438
|
+
if (!this.saved.has(messageId) && !savedIntercomMessageIds(this.options.entries()).has(messageId))
|
|
439
|
+
return;
|
|
440
|
+
try {
|
|
441
|
+
await this.options.appendHandled(messageId);
|
|
442
|
+
} catch {}
|
|
443
|
+
}
|
|
444
|
+
async save(from, message, channel, acknowledge) {
|
|
445
|
+
const confirm = () => {
|
|
446
|
+
try {
|
|
447
|
+
acknowledge();
|
|
448
|
+
} catch {}
|
|
449
|
+
};
|
|
450
|
+
if (!this.options.durable()) {
|
|
451
|
+
confirm();
|
|
452
|
+
return "fresh";
|
|
453
|
+
}
|
|
454
|
+
if (this.saved.has(message.id) || savedIntercomMessageIds(this.options.entries()).has(message.id)) {
|
|
455
|
+
this.saved.add(message.id);
|
|
456
|
+
confirm();
|
|
457
|
+
return "redelivered";
|
|
458
|
+
}
|
|
459
|
+
try {
|
|
460
|
+
await this.options.append({
|
|
461
|
+
message,
|
|
462
|
+
from,
|
|
463
|
+
receivedAt: this.options.now?.() ?? Date.now(),
|
|
464
|
+
...channel === undefined ? {} : { channel }
|
|
465
|
+
});
|
|
466
|
+
} catch {
|
|
467
|
+
return "unsaved";
|
|
468
|
+
}
|
|
469
|
+
this.saved.add(message.id);
|
|
470
|
+
confirm();
|
|
471
|
+
return "fresh";
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
var INTERCOM_INBOX_ENTRY = "intercom_inbox", INTERCOM_INBOX_HANDLED_ENTRY = "intercom_inbox_handled", INTERCOM_INBOX_REPLAY_EVENT = "intercom:inbox-replay";
|
|
475
|
+
var init_durable_inbox = () => {};
|
|
476
|
+
|
|
185
477
|
// dist/builtin/intercom/subagent-reply-capability.ts
|
|
186
478
|
function registerSubagentReplyCapability(pi, client) {
|
|
187
479
|
let signal;
|
|
@@ -213,6 +505,20 @@ function registerSubagentReplyCapability(pi, client) {
|
|
|
213
505
|
return capability;
|
|
214
506
|
}
|
|
215
507
|
|
|
508
|
+
// dist/builtin/intercom/session-identity.ts
|
|
509
|
+
function readIntercomSessionIdentity(entries, sessionId) {
|
|
510
|
+
for (let index = entries.length - 1;index >= 0; index -= 1) {
|
|
511
|
+
const entry = entries[index];
|
|
512
|
+
if (entry?.type !== "custom" || entry.customType !== INTERCOM_SESSION_IDENTITY_ENTRY)
|
|
513
|
+
continue;
|
|
514
|
+
const data = entry.data;
|
|
515
|
+
if (data?.sessionId === sessionId && typeof data.intercomSessionId === "string" && data.intercomSessionId)
|
|
516
|
+
return data.intercomSessionId;
|
|
517
|
+
}
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
var INTERCOM_SESSION_IDENTITY_ENTRY = "intercom_session_identity";
|
|
521
|
+
|
|
216
522
|
// dist/builtin/intercom/broker/framing.ts
|
|
217
523
|
function writeMessage(socket, msg, callback) {
|
|
218
524
|
const json = JSON.stringify(msg);
|
|
@@ -308,6 +614,7 @@ function getBrokerSocketPath(platform = process.platform, agentDir = getAgentDir
|
|
|
308
614
|
}
|
|
309
615
|
return join(getIntercomDirPath(agentDir), "broker.sock");
|
|
310
616
|
}
|
|
617
|
+
var BROKER_STORAGE_ENV = "ATOMIC_STORAGE";
|
|
311
618
|
var init_paths = () => {};
|
|
312
619
|
|
|
313
620
|
// dist/builtin/intercom/broker/send-signature.ts
|
|
@@ -415,6 +722,17 @@ class PendingSendRegistry {
|
|
|
415
722
|
attempt.resolve(result);
|
|
416
723
|
return true;
|
|
417
724
|
}
|
|
725
|
+
extend(messageId, attemptId, timeoutMs) {
|
|
726
|
+
const attempt = this.attempts.get(messageId);
|
|
727
|
+
if (!attempt || (attemptId === undefined ? !attempt.legacyEligible : attempt.attemptId !== attemptId))
|
|
728
|
+
return false;
|
|
729
|
+
if (attempt.timer)
|
|
730
|
+
clearTimeout(attempt.timer);
|
|
731
|
+
attempt.timer = setTimeout(() => {
|
|
732
|
+
this.reject(attempt, new Error("Send timeout"));
|
|
733
|
+
}, timeoutMs);
|
|
734
|
+
return true;
|
|
735
|
+
}
|
|
418
736
|
resolveLegacy(messageId, result) {
|
|
419
737
|
const attempt = this.attempts.get(messageId);
|
|
420
738
|
if (!attempt?.legacyEligible)
|
|
@@ -454,57 +772,6 @@ function readSubagentMessageSource(policy) {
|
|
|
454
772
|
};
|
|
455
773
|
}
|
|
456
774
|
|
|
457
|
-
// dist/builtin/intercom/broker/client-message-validation.ts
|
|
458
|
-
function isAttachment(value) {
|
|
459
|
-
if (typeof value !== "object" || value === null)
|
|
460
|
-
return false;
|
|
461
|
-
const attachment = value;
|
|
462
|
-
if (attachment.type !== "file" && attachment.type !== "snippet" && attachment.type !== "context")
|
|
463
|
-
return false;
|
|
464
|
-
if (typeof attachment.name !== "string" || typeof attachment.content !== "string")
|
|
465
|
-
return false;
|
|
466
|
-
return attachment.language === undefined || typeof attachment.language === "string";
|
|
467
|
-
}
|
|
468
|
-
function isMessageSource(value) {
|
|
469
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
470
|
-
return false;
|
|
471
|
-
const source = value;
|
|
472
|
-
return typeof source.subagentRunId === "string" && (source.subagentAgent === undefined || typeof source.subagentAgent === "string") && (source.subagentIndex === undefined || typeof source.subagentIndex === "number");
|
|
473
|
-
}
|
|
474
|
-
function isMessage(value) {
|
|
475
|
-
if (typeof value !== "object" || value === null)
|
|
476
|
-
return false;
|
|
477
|
-
const message = value;
|
|
478
|
-
if (typeof message.id !== "string" || typeof message.timestamp !== "number")
|
|
479
|
-
return false;
|
|
480
|
-
if (message.replyTo !== undefined && typeof message.replyTo !== "string")
|
|
481
|
-
return false;
|
|
482
|
-
if (message.expectsReply !== undefined && typeof message.expectsReply !== "boolean")
|
|
483
|
-
return false;
|
|
484
|
-
if (message.replyError !== undefined && typeof message.replyError !== "string")
|
|
485
|
-
return false;
|
|
486
|
-
if (message.source !== undefined && !isMessageSource(message.source))
|
|
487
|
-
return false;
|
|
488
|
-
if (typeof message.content !== "object" || message.content === null)
|
|
489
|
-
return false;
|
|
490
|
-
const content = message.content;
|
|
491
|
-
if (typeof content.text !== "string")
|
|
492
|
-
return false;
|
|
493
|
-
return content.attachments === undefined || Array.isArray(content.attachments) && content.attachments.every(isAttachment);
|
|
494
|
-
}
|
|
495
|
-
function isSessionInfo(value) {
|
|
496
|
-
if (typeof value !== "object" || value === null)
|
|
497
|
-
return false;
|
|
498
|
-
const session = value;
|
|
499
|
-
if (typeof session.id !== "string" || typeof session.cwd !== "string" || typeof session.model !== "string" || typeof session.pid !== "number" || typeof session.startedAt !== "number" || typeof session.lastActivity !== "number")
|
|
500
|
-
return false;
|
|
501
|
-
if (session.name !== undefined && typeof session.name !== "string")
|
|
502
|
-
return false;
|
|
503
|
-
if (session.group !== undefined && typeof session.group !== "string")
|
|
504
|
-
return false;
|
|
505
|
-
return session.status === undefined || typeof session.status === "string";
|
|
506
|
-
}
|
|
507
|
-
|
|
508
775
|
// dist/builtin/intercom/group.ts
|
|
509
776
|
function intercomGroupFromEnv() {
|
|
510
777
|
return process.env.ATOMIC_INTERCOM_GROUP ?? process.env.PI_INTERCOM_GROUP;
|
|
@@ -571,16 +838,20 @@ function isWorkflowFutureStageRosterEntries(value) {
|
|
|
571
838
|
function isWorkflowStageRosterEntries(value) {
|
|
572
839
|
return Array.isArray(value) && value.every((entry) => typeof entry === "object" && entry !== null && entry.kind === "workflow-stage" && typeof entry.runId === "string" && typeof entry.stageId === "string" && typeof entry.stageName === "string" && typeof entry.target === "string" && (entry.lifecycle === "pending" || entry.lifecycle === "running") && typeof entry.group === "string" && (entry.sessionId === undefined || typeof entry.sessionId === "string"));
|
|
573
840
|
}
|
|
574
|
-
var BROKER_SOCKET, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, IntercomClient;
|
|
841
|
+
var BROKER_SOCKET, GROUP_REQUEST_TIMEOUT_MS = 5000, PRESENCE_ACK_TIMEOUT_MS = 5000, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS = 5000, HELD_SEND_GRACE_MS = 5000, IntercomClient;
|
|
575
842
|
var init_client = __esm(() => {
|
|
576
843
|
init_paths();
|
|
577
844
|
init_pending_send_registry();
|
|
578
845
|
init_group();
|
|
579
846
|
init_recoverable_disconnect();
|
|
580
847
|
init_live_route_refusal();
|
|
848
|
+
init_retry_policy();
|
|
581
849
|
BROKER_SOCKET = getBrokerSocketPath();
|
|
582
850
|
IntercomClient = class IntercomClient extends EventEmitter {
|
|
583
851
|
returnAddress;
|
|
852
|
+
preferredSessionId;
|
|
853
|
+
acknowledgesReceipt;
|
|
854
|
+
brokerAcknowledgesReceipt = false;
|
|
584
855
|
socket = null;
|
|
585
856
|
_sessionId = null;
|
|
586
857
|
_supervisorSessionId = null;
|
|
@@ -594,13 +865,16 @@ var init_client = __esm(() => {
|
|
|
594
865
|
_groups = normalizeGroups();
|
|
595
866
|
pendingLiveWorkflowStageRoutes = new Map;
|
|
596
867
|
pendingSupervisorAuthorizations = new Map;
|
|
868
|
+
pendingRestoringRecipientRequests = new Map;
|
|
597
869
|
disconnecting = false;
|
|
598
870
|
disconnectError = null;
|
|
599
|
-
constructor(returnAddress = randomUUID2()) {
|
|
871
|
+
constructor(returnAddress = randomUUID2(), options = {}) {
|
|
600
872
|
super();
|
|
601
873
|
if (returnAddress.length === 0)
|
|
602
874
|
throw new Error("Intercom return address must not be empty");
|
|
603
875
|
this.returnAddress = returnAddress;
|
|
876
|
+
this.preferredSessionId = options.preferredSessionId;
|
|
877
|
+
this.acknowledgesReceipt = options.acknowledgesReceipt === true;
|
|
604
878
|
}
|
|
605
879
|
failPending(error) {
|
|
606
880
|
this.pendingSends.rejectAll(error);
|
|
@@ -610,6 +884,8 @@ var init_client = __esm(() => {
|
|
|
610
884
|
pending.reject(error);
|
|
611
885
|
for (const pending of this.pendingSupervisorAuthorizations.values())
|
|
612
886
|
pending.reject(error);
|
|
887
|
+
for (const pending of this.pendingRestoringRecipientRequests.values())
|
|
888
|
+
pending.reject(error);
|
|
613
889
|
for (const pending of this.pendingPresence.values())
|
|
614
890
|
pending.reject(error);
|
|
615
891
|
for (const pending of this.pendingMemberships.values())
|
|
@@ -619,6 +895,7 @@ var init_client = __esm(() => {
|
|
|
619
895
|
this.pendingLists.clear();
|
|
620
896
|
this.pendingGroupLists.clear();
|
|
621
897
|
this.pendingSupervisorAuthorizations.clear();
|
|
898
|
+
this.pendingRestoringRecipientRequests.clear();
|
|
622
899
|
this.pendingPresence.clear();
|
|
623
900
|
this.pendingMemberships.clear();
|
|
624
901
|
this.pendingLiveWorkflowStageRoutes.clear();
|
|
@@ -702,6 +979,7 @@ var init_client = __esm(() => {
|
|
|
702
979
|
}
|
|
703
980
|
this._sessionId = null;
|
|
704
981
|
this._supervisorSessionId = null;
|
|
982
|
+
this.brokerAcknowledgesReceipt = false;
|
|
705
983
|
this._messageSource = undefined;
|
|
706
984
|
this.disconnectError = null;
|
|
707
985
|
if (connectionEstablished && !wasDisconnecting) {
|
|
@@ -753,6 +1031,8 @@ var init_client = __esm(() => {
|
|
|
753
1031
|
session,
|
|
754
1032
|
...registrationGroup !== undefined ? { registrationGroup } : {},
|
|
755
1033
|
returnAddress: this.returnAddress,
|
|
1034
|
+
...this.preferredSessionId === undefined ? {} : { preferredSessionId: this.preferredSessionId },
|
|
1035
|
+
...this.acknowledgesReceipt ? { acknowledgesReceipt: true } : {},
|
|
756
1036
|
...supervisor ? { supervisor } : {},
|
|
757
1037
|
...supervisorOwnerToken ? { supervisorOwnerToken } : {}
|
|
758
1038
|
});
|
|
@@ -777,7 +1057,7 @@ var init_client = __esm(() => {
|
|
|
777
1057
|
}
|
|
778
1058
|
switch (brokerMessage.type) {
|
|
779
1059
|
case "registered": {
|
|
780
|
-
if (typeof brokerMessage.sessionId !== "string" || brokerMessage.supervisorSessionId !== undefined && typeof brokerMessage.supervisorSessionId !== "string") {
|
|
1060
|
+
if (typeof brokerMessage.sessionId !== "string" || brokerMessage.supervisorSessionId !== undefined && typeof brokerMessage.supervisorSessionId !== "string" || brokerMessage.acknowledgesReceipt !== undefined && brokerMessage.acknowledgesReceipt !== true) {
|
|
781
1061
|
throw new Error("Invalid registered message");
|
|
782
1062
|
}
|
|
783
1063
|
if (this._sessionId !== null) {
|
|
@@ -785,6 +1065,7 @@ var init_client = __esm(() => {
|
|
|
785
1065
|
}
|
|
786
1066
|
this._sessionId = brokerMessage.sessionId;
|
|
787
1067
|
this._supervisorSessionId = typeof brokerMessage.supervisorSessionId === "string" ? brokerMessage.supervisorSessionId : null;
|
|
1068
|
+
this.brokerAcknowledgesReceipt = this.acknowledgesReceipt && brokerMessage.acknowledgesReceipt === true;
|
|
788
1069
|
this.emit("_registered", { type: "registered", sessionId: brokerMessage.sessionId });
|
|
789
1070
|
break;
|
|
790
1071
|
}
|
|
@@ -901,6 +1182,13 @@ var init_client = __esm(() => {
|
|
|
901
1182
|
});
|
|
902
1183
|
break;
|
|
903
1184
|
}
|
|
1185
|
+
case "pending_stage_route_revoked": {
|
|
1186
|
+
const { runId } = brokerMessage;
|
|
1187
|
+
if (typeof runId !== "string")
|
|
1188
|
+
throw new Error("Invalid pending-stage route revocation");
|
|
1189
|
+
this.emit("pending_stage_route_revoked", { runId });
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
904
1192
|
case "live_workflow_stage_route_registered": {
|
|
905
1193
|
const { requestId } = brokerMessage;
|
|
906
1194
|
if (typeof requestId !== "string")
|
|
@@ -931,6 +1219,29 @@ var init_client = __esm(() => {
|
|
|
931
1219
|
this.pendingSends.resolve(messageId, attemptId, result);
|
|
932
1220
|
break;
|
|
933
1221
|
}
|
|
1222
|
+
case "send_held": {
|
|
1223
|
+
const { messageId, attemptId, timeoutMs } = brokerMessage;
|
|
1224
|
+
if (typeof messageId !== "string" || attemptId !== undefined && typeof attemptId !== "string" || typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
1225
|
+
throw new Error("Invalid send_held message");
|
|
1226
|
+
}
|
|
1227
|
+
this.pendingSends.extend(messageId, attemptId, timeoutMs + HELD_SEND_GRACE_MS);
|
|
1228
|
+
break;
|
|
1229
|
+
}
|
|
1230
|
+
case "restoring_recipient_ack": {
|
|
1231
|
+
const { requestId, error } = brokerMessage;
|
|
1232
|
+
if (typeof requestId !== "string" || error !== undefined && typeof error !== "string") {
|
|
1233
|
+
throw new Error("Invalid restoring_recipient_ack message");
|
|
1234
|
+
}
|
|
1235
|
+
const pending = this.pendingRestoringRecipientRequests.get(requestId);
|
|
1236
|
+
if (!pending)
|
|
1237
|
+
return;
|
|
1238
|
+
this.pendingRestoringRecipientRequests.delete(requestId);
|
|
1239
|
+
if (error === undefined)
|
|
1240
|
+
pending.resolve();
|
|
1241
|
+
else
|
|
1242
|
+
pending.reject(new Error(error));
|
|
1243
|
+
break;
|
|
1244
|
+
}
|
|
934
1245
|
case "delivered": {
|
|
935
1246
|
const { messageId, attemptId } = brokerMessage;
|
|
936
1247
|
if (typeof messageId !== "string" || attemptId !== undefined && typeof attemptId !== "string") {
|
|
@@ -1228,7 +1539,58 @@ var init_client = __esm(() => {
|
|
|
1228
1539
|
}
|
|
1229
1540
|
});
|
|
1230
1541
|
}
|
|
1231
|
-
|
|
1542
|
+
reserveRestoringRecipient(capability, options = {}) {
|
|
1543
|
+
return this.restoringRecipientRequest({
|
|
1544
|
+
type: "reserve_restoring_recipient",
|
|
1545
|
+
capability,
|
|
1546
|
+
...options.group === undefined ? {} : { group: options.group },
|
|
1547
|
+
...options.aliases === undefined ? {} : { aliases: [...options.aliases] },
|
|
1548
|
+
...options.dormant === true ? { dormant: true } : {}
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
releaseRestoringRecipient(capability, outcome) {
|
|
1552
|
+
const { gone, refusal } = typeof outcome === "string" ? { gone: outcome, refusal: undefined } : outcome ?? {};
|
|
1553
|
+
return this.restoringRecipientRequest({
|
|
1554
|
+
type: "release_restoring_recipient",
|
|
1555
|
+
capability,
|
|
1556
|
+
...gone === undefined ? {} : { gone },
|
|
1557
|
+
...refusal === undefined ? {} : { refusal }
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
restoringRecipientRequest(frame) {
|
|
1561
|
+
let socket;
|
|
1562
|
+
try {
|
|
1563
|
+
socket = this.requireActiveSocket();
|
|
1564
|
+
} catch (error) {
|
|
1565
|
+
return Promise.reject(toError(error));
|
|
1566
|
+
}
|
|
1567
|
+
const requestId = randomUUID2();
|
|
1568
|
+
return new Promise((resolve, reject) => {
|
|
1569
|
+
const timeout = setTimeout(() => {
|
|
1570
|
+
if (!this.pendingRestoringRecipientRequests.delete(requestId))
|
|
1571
|
+
return;
|
|
1572
|
+
reject(new Error("Restoring-recipient request timeout"));
|
|
1573
|
+
}, RESTORING_RECIPIENT_REQUEST_TIMEOUT_MS);
|
|
1574
|
+
this.pendingRestoringRecipientRequests.set(requestId, {
|
|
1575
|
+
resolve: () => {
|
|
1576
|
+
clearTimeout(timeout);
|
|
1577
|
+
resolve();
|
|
1578
|
+
},
|
|
1579
|
+
reject: (error) => {
|
|
1580
|
+
clearTimeout(timeout);
|
|
1581
|
+
reject(error);
|
|
1582
|
+
}
|
|
1583
|
+
});
|
|
1584
|
+
try {
|
|
1585
|
+
writeMessage(socket, { ...frame, requestId });
|
|
1586
|
+
} catch (error) {
|
|
1587
|
+
clearTimeout(timeout);
|
|
1588
|
+
this.pendingRestoringRecipientRequests.delete(requestId);
|
|
1589
|
+
reject(toError(error));
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
registerPendingStageRoute(runId, group, capability, stages, possibleStages, parent, dormant) {
|
|
1232
1594
|
writeMessage(this.requireActiveSocket(), {
|
|
1233
1595
|
type: "register_pending_stage_route",
|
|
1234
1596
|
runId,
|
|
@@ -1236,7 +1598,8 @@ var init_client = __esm(() => {
|
|
|
1236
1598
|
capability,
|
|
1237
1599
|
stages,
|
|
1238
1600
|
possibleStages,
|
|
1239
|
-
...parent === undefined ? {} : { parent }
|
|
1601
|
+
...parent === undefined ? {} : { parent },
|
|
1602
|
+
...dormant === true ? { dormant: true } : {}
|
|
1240
1603
|
});
|
|
1241
1604
|
}
|
|
1242
1605
|
registerLiveWorkflowStageRoute(runId, stageKeys, capability) {
|
|
@@ -1286,6 +1649,11 @@ var init_client = __esm(() => {
|
|
|
1286
1649
|
send(to, options) {
|
|
1287
1650
|
return this.sendFrame("send", to, options);
|
|
1288
1651
|
}
|
|
1652
|
+
acknowledgeReceived(messageId) {
|
|
1653
|
+
if (!this.brokerAcknowledgesReceipt)
|
|
1654
|
+
return;
|
|
1655
|
+
writeMessage(this.requireActiveSocket(), { type: "received", messageId });
|
|
1656
|
+
}
|
|
1289
1657
|
sendPendingStageNotification(runId, capability, to, senderRegistrationName, options, senderReturnAddress) {
|
|
1290
1658
|
return this.sendFrame("send_pending_stage_notification", to, options, {
|
|
1291
1659
|
runId,
|
|
@@ -1313,7 +1681,7 @@ var init_client = __esm(() => {
|
|
|
1313
1681
|
requirePendingReply: options.requirePendingReply ?? false,
|
|
1314
1682
|
...options.expectedRecipientId === undefined ? {} : { expectedRecipientId: options.expectedRecipientId }
|
|
1315
1683
|
});
|
|
1316
|
-
acquired = this.pendingSends.acquire(messageId, pendingSignature,
|
|
1684
|
+
acquired = this.pendingSends.acquire(messageId, pendingSignature, SEND_RESPONSE_TIMEOUT_MS);
|
|
1317
1685
|
} catch (error) {
|
|
1318
1686
|
return Promise.reject(toError(error));
|
|
1319
1687
|
}
|
|
@@ -1339,6 +1707,7 @@ var init_client = __esm(() => {
|
|
|
1339
1707
|
...options.requirePendingReply === undefined ? {} : { requirePendingReply: options.requirePendingReply },
|
|
1340
1708
|
...options.expectedRecipientId === undefined ? {} : { expectedRecipientId: options.expectedRecipientId },
|
|
1341
1709
|
...options.onReplyTarget === undefined ? {} : { resolveReplyTarget: true },
|
|
1710
|
+
...type === "send" ? { awaitRestoringRecipient: true } : {},
|
|
1342
1711
|
message,
|
|
1343
1712
|
attemptId: acquired.attempt.attemptId,
|
|
1344
1713
|
...extra
|
|
@@ -1443,7 +1812,7 @@ import { appendFileSync, chmodSync, closeSync, existsSync, mkdirSync, openSync,
|
|
|
1443
1812
|
import { join as join2, dirname } from "path";
|
|
1444
1813
|
import { fileURLToPath } from "url";
|
|
1445
1814
|
import { createRequire } from "module";
|
|
1446
|
-
import { createChildProcessEnvironment, isBunBinary } from "@bastani/atomic";
|
|
1815
|
+
import { createChildProcessEnvironment, isBunBinary, processSharedStorageSelection } from "@bastani/atomic";
|
|
1447
1816
|
function isIntercomPackageRoot(dir) {
|
|
1448
1817
|
return existsSync(join2(dir, "package.json")) && existsSync(join2(dir, "broker"));
|
|
1449
1818
|
}
|
|
@@ -1557,11 +1926,15 @@ function getBrokerLaunchSpec(brokerPath, brokerCommand, brokerArgs, extensionDir
|
|
|
1557
1926
|
};
|
|
1558
1927
|
}
|
|
1559
1928
|
function getBrokerSpawnOptions(extensionDir = EXTENSION_DIR, stderr = "ignore") {
|
|
1929
|
+
const storage = processSharedStorageSelection();
|
|
1560
1930
|
return {
|
|
1561
1931
|
detached: true,
|
|
1562
1932
|
stdio: ["ignore", "ignore", stderr],
|
|
1563
1933
|
cwd: extensionDir,
|
|
1564
|
-
env: createChildProcessEnvironment({
|
|
1934
|
+
env: createChildProcessEnvironment({
|
|
1935
|
+
NODE_NO_WARNINGS: "1",
|
|
1936
|
+
...storage === undefined ? {} : { [BROKER_STORAGE_ENV]: storage }
|
|
1937
|
+
}),
|
|
1565
1938
|
windowsHide: true
|
|
1566
1939
|
};
|
|
1567
1940
|
}
|
|
@@ -2081,6 +2454,9 @@ function sessionTargetFailureReason(target, resolution) {
|
|
|
2081
2454
|
if (resolution.kind === "ambiguous_id_prefix") {
|
|
2082
2455
|
return `Session ID prefix "${target}" is ambiguous; matches: ${resolution.matches.map((session) => `${session.name ?? "unnamed"} (${session.id})`).join(", ")}. Use the full UUID.`;
|
|
2083
2456
|
}
|
|
2457
|
+
if (resolution.kind === "ambiguous_session_id") {
|
|
2458
|
+
return `Session ID "${target}" is registered by more than one Intercom session: ${resolution.matches.map((session) => `${session.name ?? "unnamed"} (${session.id})`).join(", ")}. Use the Intercom session ID shown by intercom list.`;
|
|
2459
|
+
}
|
|
2084
2460
|
return "Session not found";
|
|
2085
2461
|
}
|
|
2086
2462
|
async function resolveSessionTargetId(client, nameOrId) {
|
|
@@ -2268,6 +2644,12 @@ var init_parent_ask_handoff = __esm(() => {
|
|
|
2268
2644
|
});
|
|
2269
2645
|
|
|
2270
2646
|
// dist/builtin/intercom/intercom-utils.ts
|
|
2647
|
+
function mayStartTurn(entry) {
|
|
2648
|
+
return entry.historyOnly !== true;
|
|
2649
|
+
}
|
|
2650
|
+
function maySupplyReplyContext(entry) {
|
|
2651
|
+
return entry.historyOnly !== true;
|
|
2652
|
+
}
|
|
2271
2653
|
function getErrorMessage(error) {
|
|
2272
2654
|
return error instanceof Error ? error.message : String(error);
|
|
2273
2655
|
}
|
|
@@ -3698,6 +4080,16 @@ ${message}${attachmentText}`);
|
|
|
3698
4080
|
replyTo,
|
|
3699
4081
|
expectsReply: false
|
|
3700
4082
|
}, retryToken);
|
|
4083
|
+
const goneChild = await awaitSubagentChildRestoration(pi.events, toolSessionId, to);
|
|
4084
|
+
if (goneChild !== undefined) {
|
|
4085
|
+
retryIdentities.release(retryIdentity);
|
|
4086
|
+
retryIdentity = undefined;
|
|
4087
|
+
return {
|
|
4088
|
+
content: [{ type: "text", text: goneChild }],
|
|
4089
|
+
isError: true,
|
|
4090
|
+
details: { error: true, delivered: false, reason: goneChild }
|
|
4091
|
+
};
|
|
4092
|
+
}
|
|
3701
4093
|
const sendTo = await resolveTarget(connectedClient, to) ?? to;
|
|
3702
4094
|
if (_signal?.aborted) {
|
|
3703
4095
|
const retained = retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
@@ -3861,7 +4253,18 @@ ${message}${attachmentText}`);
|
|
|
3861
4253
|
details: { yielded: true }
|
|
3862
4254
|
};
|
|
3863
4255
|
}
|
|
3864
|
-
const
|
|
4256
|
+
const goneChild = await awaitSubagentChildRestoration(pi.events, toolSessionId, to);
|
|
4257
|
+
if (goneChild !== undefined) {
|
|
4258
|
+
retryIdentities.release(retryIdentity);
|
|
4259
|
+
retryIdentity = undefined;
|
|
4260
|
+
return {
|
|
4261
|
+
content: [{ type: "text", text: goneChild }],
|
|
4262
|
+
isError: true,
|
|
4263
|
+
details: { error: true, delivered: false, reason: goneChild }
|
|
4264
|
+
};
|
|
4265
|
+
}
|
|
4266
|
+
const listedTarget = await resolveTarget(connectedClient, to);
|
|
4267
|
+
const sendTo = listedTarget ?? to;
|
|
3865
4268
|
if (_signal?.aborted) {
|
|
3866
4269
|
const retained = retryIdentity === undefined ? undefined : retainInconclusiveRetry(retryIdentities, retryIdentity);
|
|
3867
4270
|
retryIdentity = undefined;
|
|
@@ -3946,7 +4349,7 @@ ${message}${attachmentText}`);
|
|
|
3946
4349
|
attachments,
|
|
3947
4350
|
replyTo,
|
|
3948
4351
|
expectsReply: true,
|
|
3949
|
-
|
|
4352
|
+
onReplyTarget: wait.bindSender
|
|
3950
4353
|
});
|
|
3951
4354
|
if (sendResult.queued === true) {
|
|
3952
4355
|
retryIdentities.release(retryIdentity);
|
|
@@ -4308,6 +4711,7 @@ var init_intercom_tool = __esm(() => {
|
|
|
4308
4711
|
init_parent_ask_handoff();
|
|
4309
4712
|
init_result_renderers();
|
|
4310
4713
|
init_intercom_utils();
|
|
4714
|
+
init_session_recovery();
|
|
4311
4715
|
init_session_target();
|
|
4312
4716
|
init_group();
|
|
4313
4717
|
init_workflow_stage_target();
|
|
@@ -5919,11 +6323,12 @@ function routePeerDisconnect(waiters, notice) {
|
|
|
5919
6323
|
|
|
5920
6324
|
// dist/builtin/intercom/incoming-message-delivery.ts
|
|
5921
6325
|
function createIncomingMessageSender(input) {
|
|
5922
|
-
return (entry,
|
|
6326
|
+
return (entry, requested, generation = input.currentGeneration(), trackReplyContext = true, turnContext, stageAdmissionBarrier) => {
|
|
5923
6327
|
if (!input.canDeliver(generation)) {
|
|
5924
6328
|
return Promise.reject(new Error("Intercom session retired before inbound delivery"));
|
|
5925
6329
|
}
|
|
5926
|
-
|
|
6330
|
+
const delivery = (requested === "trigger" || requested === "interrupt") && !mayStartTurn(entry) ? "prelude" : requested;
|
|
6331
|
+
if ((delivery === "trigger" || delivery === "interrupt") && trackReplyContext && maySupplyReplyContext(entry)) {
|
|
5927
6332
|
input.queueTurnContext(turnContext ?? { from: entry.from, message: entry.message, receivedAt: Date.now() });
|
|
5928
6333
|
}
|
|
5929
6334
|
const baseOptions = {
|
|
@@ -5991,16 +6396,39 @@ ${entry.bodyText}`,
|
|
|
5991
6396
|
details: entry
|
|
5992
6397
|
};
|
|
5993
6398
|
}
|
|
6399
|
+
var init_incoming_message_delivery = __esm(() => {
|
|
6400
|
+
init_intercom_utils();
|
|
6401
|
+
});
|
|
5994
6402
|
|
|
5995
6403
|
// dist/builtin/intercom/inbound-idle-queue.ts
|
|
6404
|
+
function planIdleBatch(entries) {
|
|
6405
|
+
const starter = entries.findIndex(mayStartTurn);
|
|
6406
|
+
return {
|
|
6407
|
+
triggerTurn: starter >= 0,
|
|
6408
|
+
replyContext: starter >= 0 ? entries.find(maySupplyReplyContext) : undefined,
|
|
6409
|
+
sendOptions: entries.map((_, index) => starter < 0 || index < starter ? { triggerTurn: false } : index === starter ? { triggerTurn: true } : { deliverAs: "followUp" })
|
|
6410
|
+
};
|
|
6411
|
+
}
|
|
6412
|
+
|
|
5996
6413
|
class InboundIdleQueue {
|
|
6414
|
+
consumedIds;
|
|
5997
6415
|
entries = [];
|
|
5998
6416
|
generation = 0;
|
|
6417
|
+
constructor(consumedIds = () => NONE_CONSUMED) {
|
|
6418
|
+
this.consumedIds = consumedIds;
|
|
6419
|
+
}
|
|
6420
|
+
dropConsumed() {
|
|
6421
|
+
const consumed = this.consumedIds();
|
|
6422
|
+
this.entries = this.entries.filter((entry) => !consumed.has(entry.message.id));
|
|
6423
|
+
}
|
|
5999
6424
|
get size() {
|
|
6000
6425
|
return this.entries.length;
|
|
6001
6426
|
}
|
|
6002
6427
|
enqueue(entry) {
|
|
6428
|
+
if (this.consumedIds().has(entry.message.id) || this.entries.some((queued) => queued.message.id === entry.message.id))
|
|
6429
|
+
return false;
|
|
6003
6430
|
this.entries.push(entry);
|
|
6431
|
+
return true;
|
|
6004
6432
|
}
|
|
6005
6433
|
has(entry) {
|
|
6006
6434
|
return this.entries.includes(entry);
|
|
@@ -6010,14 +6438,16 @@ class InboundIdleQueue {
|
|
|
6010
6438
|
if (index < 0)
|
|
6011
6439
|
return false;
|
|
6012
6440
|
this.entries.splice(index, 1);
|
|
6013
|
-
return
|
|
6441
|
+
return !this.consumedIds().has(entry.message.id);
|
|
6014
6442
|
}
|
|
6015
6443
|
drain() {
|
|
6444
|
+
this.dropConsumed();
|
|
6016
6445
|
const entries = this.entries;
|
|
6017
6446
|
this.entries = [];
|
|
6018
6447
|
return entries;
|
|
6019
6448
|
}
|
|
6020
6449
|
claimOrdinarySourceTargets(runId, sourceSessionTargets, terminalAt = Number.POSITIVE_INFINITY) {
|
|
6450
|
+
this.dropConsumed();
|
|
6021
6451
|
const targets = new Set(sourceSessionTargets);
|
|
6022
6452
|
const generation = this.generation;
|
|
6023
6453
|
const original = this.entries;
|
|
@@ -6065,6 +6495,11 @@ class InboundIdleQueue {
|
|
|
6065
6495
|
this.entries = [];
|
|
6066
6496
|
}
|
|
6067
6497
|
}
|
|
6498
|
+
var NONE_CONSUMED;
|
|
6499
|
+
var init_inbound_idle_queue = __esm(() => {
|
|
6500
|
+
init_intercom_utils();
|
|
6501
|
+
NONE_CONSUMED = new Set;
|
|
6502
|
+
});
|
|
6068
6503
|
|
|
6069
6504
|
// dist/builtin/intercom/inbound-message-admission.ts
|
|
6070
6505
|
class InboundMessageAdmission {
|
|
@@ -6175,6 +6610,10 @@ function registerLateStageMessageRouter(pi, admission, getReplyTracker, getOwner
|
|
|
6175
6610
|
const entry = message.details;
|
|
6176
6611
|
if (!entry?.from || !entry.message)
|
|
6177
6612
|
continue;
|
|
6613
|
+
if (!maySupplyReplyContext(entry)) {
|
|
6614
|
+
accepted.push(message);
|
|
6615
|
+
continue;
|
|
6616
|
+
}
|
|
6178
6617
|
if (entry.channel !== "supervisor" && !isSubagentRelayHandoff(entry) && normalizeGroup(entry.from.group) !== normalizeGroup(getOwnerGroup()))
|
|
6179
6618
|
continue;
|
|
6180
6619
|
const result = admission.admit(entry.from, entry.message);
|
|
@@ -6193,11 +6632,18 @@ function registerLateStageMessageRouter(pi, admission, getReplyTracker, getOwner
|
|
|
6193
6632
|
accepted.push(message);
|
|
6194
6633
|
}
|
|
6195
6634
|
event.handled = true;
|
|
6196
|
-
const
|
|
6635
|
+
const delivery = accepted.some((message) => !isHistoryCard(message)) || event.options?.triggerTurn !== true ? event : { ...event, options: { ...event.options, triggerTurn: false } };
|
|
6636
|
+
const ownedCompletion = event.batch && typeof pi.sendMessages === "function" ? deliverAtomicBatch(pi, accepted, delivery, reservations, admission, tracker) : deliverSequentially(pi, accepted, delivery, reservations, admission, tracker);
|
|
6197
6637
|
event.completion = Promise.all([ownedCompletion, ...joined]).then(() => {});
|
|
6198
6638
|
return event.completion;
|
|
6199
6639
|
});
|
|
6200
6640
|
}
|
|
6641
|
+
function isHistoryCard(message) {
|
|
6642
|
+
if (message.customType !== "intercom_message")
|
|
6643
|
+
return false;
|
|
6644
|
+
const entry = message.details;
|
|
6645
|
+
return entry !== undefined && !mayStartTurn(entry);
|
|
6646
|
+
}
|
|
6201
6647
|
function isCompletedStageAskRoute(event) {
|
|
6202
6648
|
return typeof event.workflowRunId === "string" && typeof event.workflowStageId === "string" && event.messages?.length !== 0 && event.messages?.every((message) => {
|
|
6203
6649
|
if (message.customType !== "intercom_message")
|
|
@@ -6229,13 +6675,14 @@ function deliverAtomicBatch(pi, accepted, event, reservations, admission, tracke
|
|
|
6229
6675
|
}
|
|
6230
6676
|
async function deliverSequentially(pi, accepted, event, reservations, admission, tracker) {
|
|
6231
6677
|
const pending = new Map(reservations.map((owned) => [owned.message, owned]));
|
|
6678
|
+
const starter = accepted.findIndex((message) => !isHistoryCard(message));
|
|
6232
6679
|
for (let index = 0;index < accepted.length; index += 1) {
|
|
6233
6680
|
const message = accepted[index];
|
|
6234
6681
|
const owned = pending.get(message);
|
|
6235
6682
|
if (owned)
|
|
6236
6683
|
admission.beginDelivery(owned.reservation);
|
|
6237
6684
|
try {
|
|
6238
|
-
await pi.sendMessage(message, index === 0 ? event.options : { deliverAs: "followUp" });
|
|
6685
|
+
await pi.sendMessage(message, index === starter ? event.options : starter < 0 || index < starter ? { ...event.options, triggerTurn: false } : { deliverAs: "followUp" });
|
|
6239
6686
|
} catch (error) {
|
|
6240
6687
|
if (owned)
|
|
6241
6688
|
admission.endDelivery(owned.reservation);
|
|
@@ -6258,6 +6705,7 @@ function releaseReservations(reservations, admission, tracker, error) {
|
|
|
6258
6705
|
}
|
|
6259
6706
|
var LATE_STAGE_MESSAGE_EVENT = "atomic:workflow-stage-late-message";
|
|
6260
6707
|
var init_late_stage_message_router = __esm(() => {
|
|
6708
|
+
init_intercom_utils();
|
|
6261
6709
|
init_group();
|
|
6262
6710
|
});
|
|
6263
6711
|
|
|
@@ -6406,10 +6854,12 @@ async function settleOpenStageDeliveryFailure(input, error) {
|
|
|
6406
6854
|
}
|
|
6407
6855
|
|
|
6408
6856
|
// dist/builtin/intercom/closed-workflow-stage-message.ts
|
|
6409
|
-
function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deliver, currentClient, isCurrent, ownsSubagentRun) {
|
|
6857
|
+
function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deliver, currentClient, isCurrent, ownsSubagentRun, handledWithoutCard = () => {}) {
|
|
6410
6858
|
const sourceRunId = entry.message.source?.subagentRunId;
|
|
6411
|
-
if (sourceRunId !== undefined && ownsSubagentRun(sourceRunId))
|
|
6859
|
+
if (sourceRunId !== undefined && ownsSubagentRun(sourceRunId)) {
|
|
6860
|
+
handledWithoutCard();
|
|
6412
6861
|
return;
|
|
6862
|
+
}
|
|
6413
6863
|
if (entry.message.expectsReply !== true && !isDeliveryFeedback(entry.message)) {
|
|
6414
6864
|
retryStableDelivery({ deliver, isCurrent }).catch(() => {});
|
|
6415
6865
|
return;
|
|
@@ -6438,6 +6888,7 @@ function routeClosedWorkflowStageMessage(entry, admission, tracker, waiter, deli
|
|
|
6438
6888
|
const failure = error instanceof Error ? error : new Error(String(error));
|
|
6439
6889
|
tracker.forgetIncomingMessage(replyContext);
|
|
6440
6890
|
if (entry.message.expectsReply === true && await sendWorkflowStageDeliveryFailure(entry, failure, tracker, currentClient, isCurrent, "Completed workflow stage could not process intercom ask")) {
|
|
6891
|
+
handledWithoutCard();
|
|
6441
6892
|
admission.commit(admitted.reservation);
|
|
6442
6893
|
return;
|
|
6443
6894
|
}
|
|
@@ -6451,7 +6902,9 @@ function invoke(deliver) {
|
|
|
6451
6902
|
return Promise.reject(error);
|
|
6452
6903
|
}
|
|
6453
6904
|
}
|
|
6454
|
-
var init_closed_workflow_stage_message = () => {
|
|
6905
|
+
var init_closed_workflow_stage_message = __esm(() => {
|
|
6906
|
+
init_incoming_message_delivery();
|
|
6907
|
+
});
|
|
6455
6908
|
|
|
6456
6909
|
// dist/builtin/intercom/runtime-group.ts
|
|
6457
6910
|
import { runtimeIntercomGroupEnvKey } from "@bastani/atomic";
|
|
@@ -6731,7 +7184,26 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6731
7184
|
let replyTracker = new ReplyTracker;
|
|
6732
7185
|
const replyWaiters = new ReplyWaiterRegistry(DEFAULT_REPLY_TIMEOUT_MS, config.maxPendingAsks);
|
|
6733
7186
|
const foregroundDetachHandoff = new ForegroundDetachHandoff(pi);
|
|
6734
|
-
|
|
7187
|
+
function sessionBranch() {
|
|
7188
|
+
try {
|
|
7189
|
+
return runtimeContext?.sessionManager.getBranch() ?? [];
|
|
7190
|
+
} catch {
|
|
7191
|
+
return [];
|
|
7192
|
+
}
|
|
7193
|
+
}
|
|
7194
|
+
const pendingIdleMessages = new InboundIdleQueue(() => consumedIntercomMessageIds(sessionBranch()));
|
|
7195
|
+
const durableInbox = new DurableInbox({
|
|
7196
|
+
durable: () => {
|
|
7197
|
+
try {
|
|
7198
|
+
return runtimeContext?.sessionManager.getSessionStore?.().descriptor.adapter !== "memory";
|
|
7199
|
+
} catch {
|
|
7200
|
+
return true;
|
|
7201
|
+
}
|
|
7202
|
+
},
|
|
7203
|
+
entries: sessionBranch,
|
|
7204
|
+
append: (record) => pi.appendEntry(INTERCOM_INBOX_ENTRY, record),
|
|
7205
|
+
appendHandled: (messageId) => pi.appendEntry(INTERCOM_INBOX_HANDLED_ENTRY, { messageId })
|
|
7206
|
+
});
|
|
6735
7207
|
const inboundDeliveries = new InboundMessageAdmission;
|
|
6736
7208
|
const pendingStageRoutes = new Map;
|
|
6737
7209
|
const pendingStageRouteClients = new Map;
|
|
@@ -6912,16 +7384,79 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6912
7384
|
return;
|
|
6913
7385
|
}
|
|
6914
7386
|
const entries = pendingIdleMessages.drain();
|
|
6915
|
-
const
|
|
6916
|
-
if (
|
|
6917
|
-
replyTracker.queueTurnContext({ from:
|
|
7387
|
+
const batch = planIdleBatch(entries);
|
|
7388
|
+
if (batch.replyContext)
|
|
7389
|
+
replyTracker.queueTurnContext({ from: batch.replyContext.from, message: batch.replyContext.message, receivedAt: Date.now() });
|
|
6918
7390
|
const messages = entries.map(buildIncomingCustomMessage);
|
|
6919
7391
|
retryStableDelivery({
|
|
6920
|
-
deliver: () => typeof pi.sendMessages === "function" ? Promise.resolve(pi.sendMessages(messages, { triggerTurn:
|
|
7392
|
+
deliver: () => typeof pi.sendMessages === "function" ? Promise.resolve(pi.sendMessages(messages, { triggerTurn: batch.triggerTurn })) : Promise.all(messages.map((message, index) => pi.sendMessage(message, batch.sendOptions[index]))).then(() => {}),
|
|
6921
7393
|
isCurrent: () => Boolean(getLiveContext(ctx, generation))
|
|
6922
7394
|
}).catch(() => {});
|
|
6923
7395
|
}
|
|
6924
7396
|
testOverrides.captureInboundHandler?.(handleIncomingMessage);
|
|
7397
|
+
function buildInboundEntry(from, message, channel) {
|
|
7398
|
+
const attachmentText = message.content.attachments?.length ? formatAttachments(message.content.attachments) : "";
|
|
7399
|
+
const bodyText = `${message.content.text}${attachmentText}`;
|
|
7400
|
+
const replyCommand = config.replyHint && message.expectsReply ? `intercom({ action: "reply", message: "..." })` : undefined;
|
|
7401
|
+
const rawEntry = { from, message, replyCommand, bodyText, ...channel ? { channel } : {} };
|
|
7402
|
+
return isDeliveryFeedback(message) ? frameDeliveryFeedback(rawEntry) : frameHistoricalSupervisorUpdate(rawEntry);
|
|
7403
|
+
}
|
|
7404
|
+
function receiveIncomingMessage(receiver, from, message, channel) {
|
|
7405
|
+
const generation = runtimeGeneration;
|
|
7406
|
+
durableInbox.receive(from, message, channel, () => receiver.acknowledgeReceived(message.id)).then((arrival) => {
|
|
7407
|
+
if (arrival !== "fresh")
|
|
7408
|
+
return;
|
|
7409
|
+
const liveContext = getLiveContext(runtimeContext, generation);
|
|
7410
|
+
if (liveContext)
|
|
7411
|
+
handleIncomingMessage(liveContext, from, message, channel);
|
|
7412
|
+
});
|
|
7413
|
+
}
|
|
7414
|
+
async function replayDurableInbox(request) {
|
|
7415
|
+
const liveContext = getLiveContext();
|
|
7416
|
+
if (!liveContext)
|
|
7417
|
+
return [];
|
|
7418
|
+
replyTracker = bindWorkflowReplyTracker(liveContext, replyTracker);
|
|
7419
|
+
const records = unconsumedIntercomInbox(sessionBranch()).map((record) => ({
|
|
7420
|
+
record,
|
|
7421
|
+
entry: buildInboundEntry(record.from, record.message, record.channel)
|
|
7422
|
+
}));
|
|
7423
|
+
const plan = planIntercomRecoveryReplay(records.map(({ record, entry }) => ({
|
|
7424
|
+
entryId: record.message.id,
|
|
7425
|
+
customType: "intercom_message",
|
|
7426
|
+
content: entry.bodyText,
|
|
7427
|
+
details: entry,
|
|
7428
|
+
timestamp: new Date(record.receivedAt).toISOString(),
|
|
7429
|
+
delivery: "followUp"
|
|
7430
|
+
})), request.peers, request.restored);
|
|
7431
|
+
const actions = new Map((plan.decisions ?? []).map((decision) => [decision.entryId, decision.action]));
|
|
7432
|
+
let queued = 0;
|
|
7433
|
+
for (const { record, entry } of records) {
|
|
7434
|
+
const action = actions.get(record.message.id) ?? "replay";
|
|
7435
|
+
if (action === "defer")
|
|
7436
|
+
continue;
|
|
7437
|
+
if (action === "drop") {
|
|
7438
|
+
const historyEntry = { ...entry, replyCommand: undefined, historyOnly: true };
|
|
7439
|
+
if (queued > 0) {
|
|
7440
|
+
pendingIdleMessages.enqueue(historyEntry);
|
|
7441
|
+
continue;
|
|
7442
|
+
}
|
|
7443
|
+
try {
|
|
7444
|
+
await pi.sendMessage(buildIncomingCustomMessage(historyEntry), { triggerTurn: false });
|
|
7445
|
+
} catch {}
|
|
7446
|
+
continue;
|
|
7447
|
+
}
|
|
7448
|
+
const admission = inboundDeliveries.admit(record.from, record.message);
|
|
7449
|
+
if (admission.kind !== "reserved")
|
|
7450
|
+
continue;
|
|
7451
|
+
replyTracker.recordIncomingMessage(record.from, record.message);
|
|
7452
|
+
if (pendingIdleMessages.enqueue(entry))
|
|
7453
|
+
queued += 1;
|
|
7454
|
+
inboundDeliveries.commit(admission.reservation);
|
|
7455
|
+
}
|
|
7456
|
+
if (queued > 0)
|
|
7457
|
+
scheduleInboundFlush();
|
|
7458
|
+
return plan.notices ?? [];
|
|
7459
|
+
}
|
|
6925
7460
|
function handleIncomingMessage(ctx, from, message, channel, receivedBeforeStageStart = false) {
|
|
6926
7461
|
const messageGeneration = runtimeGeneration;
|
|
6927
7462
|
const liveContext = getLiveContext(ctx, messageGeneration);
|
|
@@ -6931,11 +7466,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6931
7466
|
return;
|
|
6932
7467
|
}
|
|
6933
7468
|
replyTracker = bindWorkflowReplyTracker(liveContext, replyTracker);
|
|
6934
|
-
const
|
|
6935
|
-
const bodyText = `${message.content.text}${attachmentText}`;
|
|
6936
|
-
const replyCommand = config.replyHint && message.expectsReply ? `intercom({ action: "reply", message: "..." })` : undefined;
|
|
6937
|
-
const rawEntry = { from, message, replyCommand, bodyText, ...channel ? { channel } : {} };
|
|
6938
|
-
const framedEntry = isDeliveryFeedback(message) ? frameDeliveryFeedback(rawEntry) : frameHistoricalSupervisorUpdate(rawEntry);
|
|
7469
|
+
const framedEntry = buildInboundEntry(from, message, channel);
|
|
6939
7470
|
const entry = receivedBeforeStageStart ? framePreStartPendingStageMessage(framedEntry) : framedEntry;
|
|
6940
7471
|
if (receivedBeforeStageStart) {
|
|
6941
7472
|
return sendIncomingMessage(entry, "prelude", messageGeneration, false);
|
|
@@ -6948,7 +7479,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6948
7479
|
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.");
|
|
6949
7480
|
}
|
|
6950
7481
|
return sendIncomingMessage(entry, isDeliveryFeedback(message) ? "prelude" : "trigger", messageGeneration, false);
|
|
6951
|
-
}, () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId));
|
|
7482
|
+
}, () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId), () => durableInbox.handledWithoutCard(message.id));
|
|
6952
7483
|
return;
|
|
6953
7484
|
}
|
|
6954
7485
|
const admission = inboundDeliveries.admit(from, message);
|
|
@@ -6976,7 +7507,10 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6976
7507
|
tracker: replyTracker,
|
|
6977
7508
|
replyContext,
|
|
6978
7509
|
currentClient: () => client,
|
|
6979
|
-
commit
|
|
7510
|
+
commit: () => {
|
|
7511
|
+
durableInbox.handledWithoutCard(message.id);
|
|
7512
|
+
commit();
|
|
7513
|
+
},
|
|
6980
7514
|
failurePrefix: liveContext.subagentPolicy?.executionEnded === undefined ? undefined : "Subagent could not admit intercom ask"
|
|
6981
7515
|
});
|
|
6982
7516
|
const activeDelivery = admitActiveSessionInbound(liveContext, (admissionBarrier) => {
|
|
@@ -7013,6 +7547,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7013
7547
|
}
|
|
7014
7548
|
} catch {}
|
|
7015
7549
|
}
|
|
7550
|
+
await durableInbox.handledWithoutCard(message.id);
|
|
7016
7551
|
commit();
|
|
7017
7552
|
return;
|
|
7018
7553
|
}
|
|
@@ -7164,11 +7699,10 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7164
7699
|
}
|
|
7165
7700
|
function attachClientHandlers(nextClient) {
|
|
7166
7701
|
nextClient.on("message", (from, message, channel) => {
|
|
7167
|
-
|
|
7168
|
-
if (client !== nextClient || !liveContext) {
|
|
7702
|
+
if (client !== nextClient || !getLiveContext()) {
|
|
7169
7703
|
return;
|
|
7170
7704
|
}
|
|
7171
|
-
|
|
7705
|
+
receiveIncomingMessage(nextClient, from, message, channel);
|
|
7172
7706
|
});
|
|
7173
7707
|
nextClient.on("pending_stage_message", (request) => {
|
|
7174
7708
|
handlePendingStageMessage(nextClient, request, () => client === nextClient);
|
|
@@ -7249,6 +7783,20 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7249
7783
|
if (state.client === nextClient)
|
|
7250
7784
|
relayStickyLiveDelivered(notice);
|
|
7251
7785
|
});
|
|
7786
|
+
nextClient.on("pending_stage_route_revoked", (notice) => {
|
|
7787
|
+
if (notice.runId !== runId || state.client !== nextClient)
|
|
7788
|
+
return;
|
|
7789
|
+
state.client = null;
|
|
7790
|
+
if (state.reconnectTimer)
|
|
7791
|
+
clearTimeout(state.reconnectTimer);
|
|
7792
|
+
state.reconnectTimer = null;
|
|
7793
|
+
if (pendingStageRouteClients.get(runId) === state)
|
|
7794
|
+
pendingStageRouteClients.delete(runId);
|
|
7795
|
+
if (samePendingStageRoute(pendingStageRoutes.get(runId), state.route))
|
|
7796
|
+
pendingStageRoutes.delete(runId);
|
|
7797
|
+
nextClient.disconnect().catch(() => {});
|
|
7798
|
+
pi.events.emit(PENDING_STAGE_ROUTE_REVOKED_EVENT, { runId, capability: state.route.capability });
|
|
7799
|
+
});
|
|
7252
7800
|
}
|
|
7253
7801
|
async function ensurePendingStageRouteClient(runId, route) {
|
|
7254
7802
|
const contextAtStart = getLiveContext();
|
|
@@ -7281,7 +7829,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7281
7829
|
pendingStageRouteClients.set(runId, state);
|
|
7282
7830
|
if (state.client?.isConnected()) {
|
|
7283
7831
|
state.route = route;
|
|
7284
|
-
state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
|
|
7832
|
+
state.client.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true);
|
|
7285
7833
|
await state.client.listSessions();
|
|
7286
7834
|
return;
|
|
7287
7835
|
}
|
|
@@ -7299,7 +7847,7 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7299
7847
|
await nextClient.disconnect();
|
|
7300
7848
|
throw new Error("Intercom runtime no longer active");
|
|
7301
7849
|
}
|
|
7302
|
-
nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent);
|
|
7850
|
+
nextClient.registerPendingStageRoute(runId, normalizeGroup(route.group), route.capability, route.stages, route.possibleStages, route.parent, route.dormant === true);
|
|
7303
7851
|
await nextClient.listSessions();
|
|
7304
7852
|
if (!pendingStageRouteClientIsCurrent(runId, state, contextAtStart, generationAtStart)) {
|
|
7305
7853
|
await nextClient.disconnect();
|
|
@@ -7346,13 +7894,28 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7346
7894
|
}
|
|
7347
7895
|
async function registerPendingStageRoute(activeClient, runId, route) {
|
|
7348
7896
|
const routeGroup = normalizeGroup(route.group);
|
|
7349
|
-
if (clientRegistrationGroup === routeGroup) {
|
|
7897
|
+
if (clientRegistrationGroup === routeGroup && route.dormant !== true) {
|
|
7350
7898
|
activeClient.registerPendingStageRoute(runId, routeGroup, route.capability, route.stages, route.possibleStages, route.parent);
|
|
7351
7899
|
await activeClient.listSessions();
|
|
7352
7900
|
return;
|
|
7353
7901
|
}
|
|
7354
7902
|
await ensurePendingStageRouteClient(runId, { ...route, group: routeGroup });
|
|
7355
7903
|
}
|
|
7904
|
+
function persistedIntercomSessionId(ctx, sessionId) {
|
|
7905
|
+
try {
|
|
7906
|
+
return readIntercomSessionIdentity(ctx.sessionManager.getEntries(), sessionId);
|
|
7907
|
+
} catch {
|
|
7908
|
+
return;
|
|
7909
|
+
}
|
|
7910
|
+
}
|
|
7911
|
+
async function recordIntercomSessionIdentity(sessionId, intercomSessionId) {
|
|
7912
|
+
try {
|
|
7913
|
+
await pi.appendEntry(INTERCOM_SESSION_IDENTITY_ENTRY, {
|
|
7914
|
+
sessionId,
|
|
7915
|
+
intercomSessionId
|
|
7916
|
+
});
|
|
7917
|
+
} catch {}
|
|
7918
|
+
}
|
|
7356
7919
|
async function ensureConnected(reason) {
|
|
7357
7920
|
if (disposed || shuttingDown) {
|
|
7358
7921
|
throw new Error("Intercom shutting down");
|
|
@@ -7370,10 +7933,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7370
7933
|
return reconnectPromise;
|
|
7371
7934
|
}
|
|
7372
7935
|
const ownershipRecorded = Promise.withResolvers();
|
|
7936
|
+
const sessionIdAtStart = currentSessionId;
|
|
7937
|
+
const preferredSessionId = persistedIntercomSessionId(contextAtStart, sessionIdAtStart);
|
|
7373
7938
|
const nextReconnectPromise = (async () => {
|
|
7374
7939
|
let connectFailed = false;
|
|
7375
7940
|
await ownershipRecorded.promise;
|
|
7376
|
-
const nextClient = new IntercomClient(
|
|
7941
|
+
const nextClient = new IntercomClient(sessionIdAtStart, { preferredSessionId, acknowledgesReceipt: true });
|
|
7377
7942
|
client = nextClient;
|
|
7378
7943
|
attachClientHandlers(nextClient);
|
|
7379
7944
|
try {
|
|
@@ -7404,6 +7969,9 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7404
7969
|
process.env[INTERCOM_SESSION_ID_ENV] = nextClient.sessionId;
|
|
7405
7970
|
}
|
|
7406
7971
|
reconnectAttempt = 0;
|
|
7972
|
+
if (nextClient.sessionId && nextClient.sessionId !== preferredSessionId) {
|
|
7973
|
+
await recordIntercomSessionIdentity(sessionIdAtStart, nextClient.sessionId);
|
|
7974
|
+
}
|
|
7407
7975
|
return nextClient;
|
|
7408
7976
|
} catch (error) {
|
|
7409
7977
|
if (client === nextClient) {
|
|
@@ -7438,7 +8006,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7438
8006
|
capability: payload.capability,
|
|
7439
8007
|
...payload.stages === undefined ? {} : { stages: payload.stages },
|
|
7440
8008
|
...payload.possibleStages === undefined ? {} : { possibleStages: payload.possibleStages },
|
|
7441
|
-
...payload.parent === undefined ? {} : { parent: payload.parent }
|
|
8009
|
+
...payload.parent === undefined ? {} : { parent: payload.parent },
|
|
8010
|
+
...payload.dormant === true ? { dormant: true } : {}
|
|
7442
8011
|
});
|
|
7443
8012
|
const completion = ensureConnected("background").then((activeClient) => registerPendingStageRoute(activeClient, payload.runId, payload));
|
|
7444
8013
|
payload.completion = completion;
|
|
@@ -7508,6 +8077,48 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7508
8077
|
resolveSessionTarget: resolveSessionTargetId,
|
|
7509
8078
|
homeGroup: currentIntercomGroup
|
|
7510
8079
|
});
|
|
8080
|
+
pi.events.on(SUBAGENT_AWAIT_INTERCOM_PEER_EVENT, (payload) => {
|
|
8081
|
+
if (!payload || typeof payload !== "object" || !isAwaitIntercomPeerRequest(payload) || payload.completion)
|
|
8082
|
+
return;
|
|
8083
|
+
const request = payload;
|
|
8084
|
+
request.completion = ensureConnected("background").then((activeClient) => waitForIntercomPeer(activeClient, request));
|
|
8085
|
+
});
|
|
8086
|
+
pi.events.on(INTERCOM_INBOX_REPLAY_EVENT, (payload) => {
|
|
8087
|
+
if (!payload || typeof payload !== "object")
|
|
8088
|
+
return;
|
|
8089
|
+
const request = payload;
|
|
8090
|
+
if (request.completion || !Array.isArray(request.restored))
|
|
8091
|
+
return;
|
|
8092
|
+
request.completion = replayDurableInbox(request);
|
|
8093
|
+
});
|
|
8094
|
+
pi.events.on(INTERCOM_RECOVERY_PEERS_EVENT, (payload) => {
|
|
8095
|
+
if (!payload || typeof payload !== "object")
|
|
8096
|
+
return;
|
|
8097
|
+
const request = payload;
|
|
8098
|
+
if (request.completion)
|
|
8099
|
+
return;
|
|
8100
|
+
request.completion = ensureConnected("background").then((activeClient) => activeClient.listSessions());
|
|
8101
|
+
});
|
|
8102
|
+
pi.events.on(SUBAGENT_RESERVE_RESTORING_CHILD_EVENT, (payload) => {
|
|
8103
|
+
if (!isReserveRestoringChildRequest(payload) || payload.completion)
|
|
8104
|
+
return;
|
|
8105
|
+
const request = payload;
|
|
8106
|
+
request.completion = ensureConnected("background").then((activeClient) => activeClient.reserveRestoringRecipient(request.capability, {
|
|
8107
|
+
...request.group === undefined ? {} : { group: request.group },
|
|
8108
|
+
aliases: request.aliases,
|
|
8109
|
+
...request.dormant === true ? { dormant: true } : {}
|
|
8110
|
+
}));
|
|
8111
|
+
});
|
|
8112
|
+
pi.events.on(SUBAGENT_RELEASE_RESTORING_CHILD_EVENT, (payload) => {
|
|
8113
|
+
if (!isReleaseRestoringChildRequest(payload) || payload.completion)
|
|
8114
|
+
return;
|
|
8115
|
+
const request = payload;
|
|
8116
|
+
const activeClient = client;
|
|
8117
|
+
request.completion = activeClient?.isConnected() ? activeClient.releaseRestoringRecipient(request.capability, {
|
|
8118
|
+
...request.gone === undefined ? {} : { gone: request.gone },
|
|
8119
|
+
...request.refusal === undefined ? {} : { refusal: request.refusal }
|
|
8120
|
+
}) : Promise.resolve();
|
|
8121
|
+
});
|
|
7511
8122
|
pi.on("session_shutdown", (event) => {
|
|
7512
8123
|
if (event.reason !== "reload" && currentSessionId)
|
|
7513
8124
|
sessionMemberships.delete(currentSessionId);
|
|
@@ -7635,8 +8246,9 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
7635
8246
|
syncPresenceIdentity
|
|
7636
8247
|
});
|
|
7637
8248
|
}
|
|
7638
|
-
var INTERCOM_SESSION_ID_ENV, PENDING_STAGE_ROUTE_EVENT = "atomic:workflow-pending-stage-route", PENDING_STAGE_MESSAGE_EVENT = "atomic:workflow-pending-stage-message", PENDING_STAGE_UNDELIVERABLE_EVENT = "atomic:workflow-pending-stage-undeliverable", STICKY_LIVE_DELIVERED_EVENT = "atomic:workflow-sticky-live-delivered";
|
|
8249
|
+
var INTERCOM_SESSION_ID_ENV, PENDING_STAGE_ROUTE_EVENT = "atomic:workflow-pending-stage-route", PENDING_STAGE_MESSAGE_EVENT = "atomic:workflow-pending-stage-message", PENDING_STAGE_UNDELIVERABLE_EVENT = "atomic:workflow-pending-stage-undeliverable", STICKY_LIVE_DELIVERED_EVENT = "atomic:workflow-sticky-live-delivered", PENDING_STAGE_ROUTE_REVOKED_EVENT = "atomic:workflow-pending-stage-route-revoked";
|
|
7639
8250
|
var init_index_heavy = __esm(() => {
|
|
8251
|
+
init_session_recovery();
|
|
7640
8252
|
init_client();
|
|
7641
8253
|
init_spawn();
|
|
7642
8254
|
init_inline_message();
|
|
@@ -7650,6 +8262,9 @@ var init_index_heavy = __esm(() => {
|
|
|
7650
8262
|
init_subagent_relay();
|
|
7651
8263
|
init_foreground_detach_handoff();
|
|
7652
8264
|
init_intercom_utils();
|
|
8265
|
+
init_incoming_message_delivery();
|
|
8266
|
+
init_inbound_idle_queue();
|
|
8267
|
+
init_durable_inbox();
|
|
7653
8268
|
init_terminal_ordering_barrier();
|
|
7654
8269
|
init_session_target();
|
|
7655
8270
|
init_inbound_message_admission();
|
|
@@ -7818,6 +8433,8 @@ class IntercomWarmUpExhaustedError extends Error {
|
|
|
7818
8433
|
|
|
7819
8434
|
// dist/builtin/intercom/index.ts
|
|
7820
8435
|
init_reconnect_backoff();
|
|
8436
|
+
init_session_recovery();
|
|
8437
|
+
init_durable_inbox();
|
|
7821
8438
|
|
|
7822
8439
|
// dist/builtin/intercom/lazy-heavy-proxy.ts
|
|
7823
8440
|
var LIVE_EVENT_SUBSCRIPTIONS = new Set(["pi-intercom:detach-response"]);
|
|
@@ -8404,6 +9021,91 @@ function intercom(pi, options = {}) {
|
|
|
8404
9021
|
throw error;
|
|
8405
9022
|
});
|
|
8406
9023
|
});
|
|
9024
|
+
pi.events.on(SUBAGENT_AWAIT_INTERCOM_PEER_EVENT, (payload) => {
|
|
9025
|
+
if (!payload || typeof payload !== "object" || !isAwaitIntercomPeerRequest(payload) || payload.completion)
|
|
9026
|
+
return;
|
|
9027
|
+
const forwarded = {
|
|
9028
|
+
name: payload.name,
|
|
9029
|
+
timeoutMs: payload.timeoutMs,
|
|
9030
|
+
...payload.group === undefined ? {} : { group: payload.group }
|
|
9031
|
+
};
|
|
9032
|
+
payload.completion = loadHeavy(latestLifecycleContext()).then(async (handle) => {
|
|
9033
|
+
handle.assertCurrent();
|
|
9034
|
+
await dispatchEventHandlers(handle.heavy, SUBAGENT_AWAIT_INTERCOM_PEER_EVENT, forwarded);
|
|
9035
|
+
return forwarded.completion ? await forwarded.completion : false;
|
|
9036
|
+
}).catch(() => false);
|
|
9037
|
+
});
|
|
9038
|
+
pi.events.on(SUBAGENT_RESERVE_RESTORING_CHILD_EVENT, (payload) => {
|
|
9039
|
+
if (!isReserveRestoringChildRequest(payload) || payload.completion)
|
|
9040
|
+
return;
|
|
9041
|
+
const forwarded = {
|
|
9042
|
+
capability: payload.capability,
|
|
9043
|
+
aliases: [...payload.aliases],
|
|
9044
|
+
...payload.group === undefined ? {} : { group: payload.group },
|
|
9045
|
+
...payload.dormant === true ? { dormant: true } : {}
|
|
9046
|
+
};
|
|
9047
|
+
payload.completion = loadHeavy(latestLifecycleContext()).then(async (handle) => {
|
|
9048
|
+
handle.assertCurrent();
|
|
9049
|
+
await dispatchEventHandlers(handle.heavy, SUBAGENT_RESERVE_RESTORING_CHILD_EVENT, forwarded);
|
|
9050
|
+
if (!forwarded.completion)
|
|
9051
|
+
throw new Error("Intercom cannot hold sends for a restoring subagent");
|
|
9052
|
+
await forwarded.completion;
|
|
9053
|
+
});
|
|
9054
|
+
});
|
|
9055
|
+
pi.events.on(SUBAGENT_RELEASE_RESTORING_CHILD_EVENT, (payload) => {
|
|
9056
|
+
if (!isReleaseRestoringChildRequest(payload) || payload.completion)
|
|
9057
|
+
return;
|
|
9058
|
+
const forwarded = {
|
|
9059
|
+
capability: payload.capability,
|
|
9060
|
+
...payload.gone === undefined ? {} : { gone: payload.gone },
|
|
9061
|
+
...payload.refusal === undefined ? {} : { refusal: payload.refusal }
|
|
9062
|
+
};
|
|
9063
|
+
const handle = loadedHeavy;
|
|
9064
|
+
payload.completion = !handle ? Promise.resolve() : (async () => {
|
|
9065
|
+
try {
|
|
9066
|
+
handle.assertCurrent();
|
|
9067
|
+
await dispatchEventHandlers(handle.heavy, SUBAGENT_RELEASE_RESTORING_CHILD_EVENT, forwarded);
|
|
9068
|
+
await forwarded.completion;
|
|
9069
|
+
} catch {}
|
|
9070
|
+
})();
|
|
9071
|
+
});
|
|
9072
|
+
async function recoveryPeers(ctx) {
|
|
9073
|
+
try {
|
|
9074
|
+
const handle = await loadHeavy(ctx);
|
|
9075
|
+
handle.assertCurrent();
|
|
9076
|
+
const forwarded = {};
|
|
9077
|
+
await dispatchEventHandlers(handle.heavy, INTERCOM_RECOVERY_PEERS_EVENT, forwarded);
|
|
9078
|
+
return forwarded.completion ? await forwarded.completion : undefined;
|
|
9079
|
+
} catch {
|
|
9080
|
+
return;
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
9083
|
+
async function replayIntercomInbox(ctx, peers) {
|
|
9084
|
+
try {
|
|
9085
|
+
const restored = await awaitRestoredIntercomPeers(pi.events, ctx.sessionManager.getSessionId());
|
|
9086
|
+
const handle = await loadHeavy(ctx);
|
|
9087
|
+
handle.assertCurrent();
|
|
9088
|
+
const forwarded = { peers, restored };
|
|
9089
|
+
await dispatchEventHandlers(handle.heavy, INTERCOM_INBOX_REPLAY_EVENT, forwarded);
|
|
9090
|
+
return await forwarded.completion ?? [];
|
|
9091
|
+
} catch {
|
|
9092
|
+
return [];
|
|
9093
|
+
}
|
|
9094
|
+
}
|
|
9095
|
+
pi.on("session_recovery_restore", async (_event, ctx) => {
|
|
9096
|
+
const peers = hasIntercomHistory(ctx.sessionManager.getEntries()) ? await recoveryPeers(ctx) : undefined;
|
|
9097
|
+
if (unconsumedIntercomInbox(ctx.sessionManager.getBranch()).length === 0)
|
|
9098
|
+
return;
|
|
9099
|
+
const notices = await replayIntercomInbox(ctx, peers);
|
|
9100
|
+
return notices.length > 0 ? { notices: [...notices] } : undefined;
|
|
9101
|
+
});
|
|
9102
|
+
pi.on("session_recovery_replay", async (event, ctx) => {
|
|
9103
|
+
if (!event.pending.some((delivery) => delivery.customType === "intercom_message"))
|
|
9104
|
+
return;
|
|
9105
|
+
const peers = await recoveryPeers(ctx);
|
|
9106
|
+
const restored = await awaitRestoredIntercomPeers(pi.events, ctx.sessionManager.getSessionId());
|
|
9107
|
+
return planIntercomRecoveryReplay(event.pending, peers, restored);
|
|
9108
|
+
});
|
|
8407
9109
|
pi.events.on(PENDING_STAGE_UNDELIVERABLE_EVENT2, (payload) => {
|
|
8408
9110
|
if (!isPendingStageUndeliverableRelay(payload) || payload.handled === true)
|
|
8409
9111
|
return;
|