@bastani/atomic 0.9.19-alpha.2 → 0.9.19-alpha.3
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 +14 -0
- package/dist/builtin/intercom/CHANGELOG.md +7 -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 +44 -4
- 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 +6 -0
- package/dist/builtin/subagents/README.md +2 -2
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +2 -2
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +13 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +56 -33
- package/dist/builtin/workflows/src/index.js +14 -4
- package/dist/core/agent-session-message-queue.d.ts.map +1 -1
- package/dist/core/agent-session-message-queue.js +2 -2
- package/dist/core/agent-session-message-queue.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +3 -0
- 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-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/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/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/settings-manager-basic-accessors.d.ts +1 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +2 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/tasks/agent-adapter.d.ts +9 -0
- package/dist/core/tasks/agent-adapter.d.ts.map +1 -1
- package/dist/core/tasks/agent-adapter.js +36 -2
- package/dist/core/tasks/agent-adapter.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.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/core/tools/powershell.js +1 -0
- 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/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/docs/background-tasks.md +7 -1
- package/docs/development.md +23 -74
- package/docs/extensions.md +4 -0
- package/docs/herdr.md +25 -78
- package/docs/intercom.md +4 -0
- package/docs/models/evals.md +2 -0
- package/docs/models/model-selection.md +10 -7
- package/docs/settings.md +4 -0
- package/docs/subagents.md +3 -1
- package/docs/tools.md +4 -0
- package/docs/workflows/api-reference.md +1 -1
- package/docs/workflows/operations.md +8 -3
- package/npm-shrinkwrap.json +59 -59
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.19-alpha.3] - 2026-09-09
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- 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.
|
|
10
|
+
- 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.
|
|
11
|
+
- 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.
|
|
12
|
+
- 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)).
|
|
13
|
+
- 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)).
|
|
14
|
+
- 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.
|
|
15
|
+
- 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.
|
|
16
|
+
- 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.
|
|
17
|
+
- 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.
|
|
18
|
+
|
|
5
19
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
6
20
|
|
|
7
21
|
### Added
|
|
@@ -4,6 +4,13 @@ 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.3] - 2026-09-09
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- 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.
|
|
12
|
+
- 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.
|
|
13
|
+
|
|
7
14
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
8
15
|
|
|
9
16
|
### 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;
|
|
@@ -523,6 +523,7 @@ var init_client = __esm(() => {
|
|
|
523
523
|
_supervisorSessionId = null;
|
|
524
524
|
_messageSource;
|
|
525
525
|
pendingSends = new PendingSendRegistry;
|
|
526
|
+
pendingReplyTargets = new Map;
|
|
526
527
|
pendingGroupLists = new Map;
|
|
527
528
|
pendingLists = new Map;
|
|
528
529
|
pendingPresence = new Map;
|
|
@@ -730,6 +731,16 @@ var init_client = __esm(() => {
|
|
|
730
731
|
this.emit("_registration_failed", new Error(brokerMessage.reason));
|
|
731
732
|
break;
|
|
732
733
|
}
|
|
734
|
+
case "question_target": {
|
|
735
|
+
const { messageId, attemptId, sessionId } = brokerMessage;
|
|
736
|
+
if (typeof messageId !== "string" || typeof attemptId !== "string" || typeof sessionId !== "string") {
|
|
737
|
+
throw new Error("Invalid question_target message");
|
|
738
|
+
}
|
|
739
|
+
const pending = this.pendingReplyTargets.get(attemptId);
|
|
740
|
+
if (pending?.messageId === messageId)
|
|
741
|
+
pending.bind(sessionId);
|
|
742
|
+
break;
|
|
743
|
+
}
|
|
733
744
|
case "sessions": {
|
|
734
745
|
const { requestId, sessions, workflowStages, workflowFutureStages } = brokerMessage;
|
|
735
746
|
if (typeof requestId !== "string" || !Array.isArray(sessions) || !sessions.every(isSessionInfo) || workflowStages !== undefined && !isWorkflowStageRosterEntries(workflowStages) || workflowFutureStages !== undefined && !isWorkflowFutureStageRosterEntries(workflowFutureStages)) {
|
|
@@ -1246,12 +1257,16 @@ var init_client = __esm(() => {
|
|
|
1246
1257
|
source: this._messageSource,
|
|
1247
1258
|
content: { text: options.text, attachments: options.attachments }
|
|
1248
1259
|
};
|
|
1260
|
+
if (options.onReplyTarget !== undefined) {
|
|
1261
|
+
this.pendingReplyTargets.set(acquired.attempt.attemptId, { messageId, bind: options.onReplyTarget });
|
|
1262
|
+
}
|
|
1249
1263
|
try {
|
|
1250
1264
|
writeMessage(socket, {
|
|
1251
1265
|
type,
|
|
1252
1266
|
to,
|
|
1253
1267
|
...options.logicalTarget === undefined ? {} : { logicalTarget: options.logicalTarget },
|
|
1254
1268
|
...options.requirePendingReply === undefined ? {} : { requirePendingReply: options.requirePendingReply },
|
|
1269
|
+
...options.onReplyTarget === undefined ? {} : { resolveReplyTarget: true },
|
|
1255
1270
|
message,
|
|
1256
1271
|
attemptId: acquired.attempt.attemptId,
|
|
1257
1272
|
...extra
|
|
@@ -1259,6 +1274,10 @@ var init_client = __esm(() => {
|
|
|
1259
1274
|
} catch (error) {
|
|
1260
1275
|
this.pendingSends.reject(acquired.attempt, toError(error));
|
|
1261
1276
|
}
|
|
1277
|
+
const clearReplyTarget = () => {
|
|
1278
|
+
this.pendingReplyTargets.delete(acquired.attempt.attemptId);
|
|
1279
|
+
};
|
|
1280
|
+
acquired.attempt.promise.then(clearReplyTarget, clearReplyTarget);
|
|
1262
1281
|
return acquired.attempt.promise;
|
|
1263
1282
|
}
|
|
1264
1283
|
updatePresence(updates) {
|
|
@@ -1799,6 +1818,10 @@ class ReplyWaiterRegistry {
|
|
|
1799
1818
|
ok: true,
|
|
1800
1819
|
wait: {
|
|
1801
1820
|
promise,
|
|
1821
|
+
bindSender: (sender) => {
|
|
1822
|
+
if (this.waiters.get(replyTo) === record)
|
|
1823
|
+
record.from = sender;
|
|
1824
|
+
},
|
|
1802
1825
|
cancel: (error) => record.reject(error)
|
|
1803
1826
|
}
|
|
1804
1827
|
};
|
|
@@ -2414,7 +2437,8 @@ function formatSessionListRow(session, currentCwd, isSelf) {
|
|
|
2414
2437
|
const name = session.name || "Unnamed session";
|
|
2415
2438
|
const normalizedGroup = normalizeGroup(session.group);
|
|
2416
2439
|
const groupTag = normalizedGroup !== DEFAULT_GROUP ? `group: ${normalizedGroup}` : undefined;
|
|
2417
|
-
const
|
|
2440
|
+
const capabilityTag = session.replyCapability === undefined ? undefined : `replyCapability: ${session.replyCapability}`;
|
|
2441
|
+
const tags = [isSelf ? "self" : session.cwd === currentCwd ? "same cwd" : undefined, session.status, capabilityTag, groupTag].filter((tag) => Boolean(tag));
|
|
2418
2442
|
const suffix = tags.length ? ` [${tags.join(", ")}]` : "";
|
|
2419
2443
|
return `• ${name} (${session.id}) — ${session.cwd} (${session.model})${suffix}`;
|
|
2420
2444
|
}
|
|
@@ -3755,7 +3779,8 @@ ${message}${attachmentText}`);
|
|
|
3755
3779
|
text: message ?? "",
|
|
3756
3780
|
attachments,
|
|
3757
3781
|
replyTo,
|
|
3758
|
-
expectsReply: true
|
|
3782
|
+
expectsReply: true,
|
|
3783
|
+
...parseWorkflowStageTarget(to)?.kind === "path" ? { onReplyTarget: wait.bindSender } : {}
|
|
3759
3784
|
});
|
|
3760
3785
|
if (sendResult.queued === true) {
|
|
3761
3786
|
retryIdentities.release(retryIdentity);
|
|
@@ -4487,7 +4512,10 @@ var init_overlay = __esm(() => {
|
|
|
4487
4512
|
function registerIntercomLifecycle(pi, deps) {
|
|
4488
4513
|
const activeReplyTracker = () => typeof deps.replyTracker === "function" ? deps.replyTracker() : deps.replyTracker;
|
|
4489
4514
|
let hasActiveSession = false;
|
|
4515
|
+
let unbindStageClose;
|
|
4490
4516
|
async function cleanupRuntime(reason) {
|
|
4517
|
+
unbindStageClose?.();
|
|
4518
|
+
unbindStageClose = undefined;
|
|
4491
4519
|
deps.setRuntimeStarted(false);
|
|
4492
4520
|
deps.setShuttingDown(true);
|
|
4493
4521
|
deps.setDisposed(true);
|
|
@@ -4538,6 +4566,12 @@ function registerIntercomLifecycle(pi, deps) {
|
|
|
4538
4566
|
deps.setSessionStartedAt(Date.now());
|
|
4539
4567
|
deps.setAgentRunning(false);
|
|
4540
4568
|
deps.activeTools.clear();
|
|
4569
|
+
const stage = ctx.orchestrationContext;
|
|
4570
|
+
const closeSignal = stage?.kind === "workflow-stage" ? stage.messageAdmission?.boundary?.closeSignal : undefined;
|
|
4571
|
+
closeSignal?.addEventListener("abort", deps.syncPresenceStatus, { once: true });
|
|
4572
|
+
unbindStageClose = () => closeSignal?.removeEventListener("abort", deps.syncPresenceStatus);
|
|
4573
|
+
if (closeSignal?.aborted)
|
|
4574
|
+
deps.syncPresenceStatus();
|
|
4541
4575
|
});
|
|
4542
4576
|
pi.on("session_shutdown", async () => {
|
|
4543
4577
|
if (!hasActiveSession)
|
|
@@ -6263,7 +6297,8 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6263
6297
|
}
|
|
6264
6298
|
function currentStatus() {
|
|
6265
6299
|
const activeToolName = activeTools.values().next().value;
|
|
6266
|
-
const
|
|
6300
|
+
const stage = getLiveContext()?.orchestrationContext;
|
|
6301
|
+
const lifecycleStatus = stage?.kind === "workflow-stage" && stage.messageAdmission?.isOpen() === false ? `closed · reply: ${stage.lateMessageRouter === undefined ? "unavailable" : "post-mortem only"}` : activeToolName ? `tool:${activeToolName}` : agentRunning ? "thinking" : "idle";
|
|
6267
6302
|
return config.status ? `${lifecycleStatus} · ${config.status}` : lifecycleStatus;
|
|
6268
6303
|
}
|
|
6269
6304
|
function resolveSessionHomeGroup() {
|
|
@@ -6411,7 +6446,12 @@ function piIntercomExtension(pi, testOverrides = {}) {
|
|
|
6411
6446
|
const stageAdmission = liveContext.orchestrationContext?.kind === "workflow-stage" ? liveContext.orchestrationContext.messageAdmission : undefined;
|
|
6412
6447
|
const stageClosed = stageAdmission?.isOpen() === false;
|
|
6413
6448
|
if (stageClosed) {
|
|
6414
|
-
routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () =>
|
|
6449
|
+
routeClosedWorkflowStageMessage(entry, inboundDeliveries, replyTracker, replyWaiters.pending(), () => {
|
|
6450
|
+
if (message.expectsReply === true && liveContext.orchestrationContext?.lateMessageRouter === undefined) {
|
|
6451
|
+
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.");
|
|
6452
|
+
}
|
|
6453
|
+
return sendIncomingMessage(entry, isDeliveryFeedback(message) ? "prelude" : "trigger", messageGeneration, false);
|
|
6454
|
+
}, () => client, () => Boolean(getLiveContext(liveContext, messageGeneration)), (runId) => stageAdmission.boundary.ownsSubagentRun(runId));
|
|
6415
6455
|
return;
|
|
6416
6456
|
}
|
|
6417
6457
|
const admission = inboundDeliveries.admit(from, message);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -124,7 +124,7 @@ export type ClientMessage =
|
|
|
124
124
|
| { type: "join_group"; requestId: string; group: string }
|
|
125
125
|
| { type: "leave_group"; requestId: string; group?: string }
|
|
126
126
|
| { type: "authorize_supervisor"; requestId: string; childName: string; capability?: string }
|
|
127
|
-
| { type: "send" | "supervisor_send"; to: string; logicalTarget?: string; requirePendingReply?: true; message: Message; attemptId?: string }
|
|
127
|
+
| { type: "send" | "supervisor_send"; to: string; logicalTarget?: string; requirePendingReply?: true; resolveReplyTarget?: true; message: Message; attemptId?: string }
|
|
128
128
|
| {
|
|
129
129
|
type: "send_pending_stage_notification";
|
|
130
130
|
runId: string;
|
|
@@ -168,6 +168,7 @@ export type ClientMessage =
|
|
|
168
168
|
export type BrokerMessage =
|
|
169
169
|
| { type: "registered"; sessionId: string; supervisorSessionId?: string }
|
|
170
170
|
| { type: "registration_failed"; reason: string }
|
|
171
|
+
| { type: "question_target"; messageId: string; attemptId: string; sessionId: string }
|
|
171
172
|
| { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[] }
|
|
172
173
|
| { type: "groups"; requestId: string; groups: GroupSummary[] }
|
|
173
174
|
| { type: "membership_ack"; requestId: string; groups: string[] }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
|
|
6
6
|
"contributors": [
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.19-alpha.3] - 2026-09-09
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Reduced default top-level parallel subagent concurrency from 4 to 3. Explicit configuration and per-call overrides remain honored; the separate per-parent native turn cap remains 4.
|
|
10
|
+
|
|
5
11
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
6
12
|
|
|
7
13
|
### Added
|
|
@@ -536,7 +536,7 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
536
536
|
| `skill` | `string \| string[] \| false` | agent default | Override skills or disable all. |
|
|
537
537
|
| `model` | string | agent default | Override model. |
|
|
538
538
|
| `tasks` | array | - | Top-level parallel tasks. Supports `agent`, `task`, `cwd`, `count`, `output`, `outputMode`, `reads`, `progress`, `skill`, and `model`. |
|
|
539
|
-
| `concurrency` | number | config or `
|
|
539
|
+
| `concurrency` | number | config or `3` | Top-level parallel concurrency. |
|
|
540
540
|
| `worktree` | boolean | false | Create isolated git worktrees for parallel tasks. |
|
|
541
541
|
| `context` | `fresh \| fork` | agent default or `fresh` | `fork` creates real branched sessions from the parent leaf. Packaged `worker` defaults to `fork`; every other builtin runs fresh. |
|
|
542
542
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
@@ -603,7 +603,7 @@ Subagent configuration controls discovery, parallel limits, session storage, con
|
|
|
603
603
|
}
|
|
604
604
|
```
|
|
605
605
|
|
|
606
|
-
`maxTasks` defaults to `50`; `concurrency` defaults to `
|
|
606
|
+
`maxTasks` defaults to `50`; `concurrency` defaults to `3`. `maxTasks` can set a lower per-call task limit but cannot exceed the hard maximum of `50`. Per-call `concurrency` takes precedence.
|
|
607
607
|
|
|
608
608
|
### `defaultSessionDir`
|
|
609
609
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -8495,7 +8495,7 @@ function resolveTempScopeId(options) {
|
|
|
8495
8495
|
return "shared";
|
|
8496
8496
|
}
|
|
8497
8497
|
var MAX_PARALLEL_TASKS = 50;
|
|
8498
|
-
var MAX_CONCURRENCY =
|
|
8498
|
+
var MAX_CONCURRENCY = 3;
|
|
8499
8499
|
var TEMP_ROOT_DIR = path6.join(os4.tmpdir(), `${APP_NAME2}-subagents-${resolveTempScopeId()}`);
|
|
8500
8500
|
var TEMP_ARTIFACTS_DIR = path6.join(TEMP_ROOT_DIR, "artifacts");
|
|
8501
8501
|
var SLASH_RESULT_TYPE = "subagent-slash-result";
|
|
@@ -17175,7 +17175,7 @@ var SubagentParams = Type.Object({
|
|
|
17175
17175
|
})),
|
|
17176
17176
|
concurrency: Type.Optional(Type.Integer({
|
|
17177
17177
|
minimum: 1,
|
|
17178
|
-
description: "Top-level PARALLEL mode only: max concurrent tasks. Defaults to config.parallel.concurrency or
|
|
17178
|
+
description: "Top-level PARALLEL mode only: max concurrent tasks. Defaults to config.parallel.concurrency or 3."
|
|
17179
17179
|
})),
|
|
17180
17180
|
group: Type.Optional(GroupSchema),
|
|
17181
17181
|
worktree: Type.Optional(Type.Boolean({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.9.19-alpha.
|
|
3
|
+
"version": "0.9.19-alpha.3",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.9.19-alpha.3] - 2026-09-09
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Local `workflow stages` now uses the same expanded nested graph as exact stage/transcript lookup, matching retained durable inspection instead of listing hidden import boundaries.
|
|
14
|
+
- Runner-created workflow sessions retain their pending-delivery context while receiving the host late-message route, so completed-stage Intercom asks can reopen the exact retained conversation without re-running the workflow.
|
|
15
|
+
- Stage pause now cancels owned active and admitted queued agents and commands before acknowledging completion, including shells admitted during already-in-flight setup. It waits for cleanup without permanently closing message admission; resume releases queued user and Intercom messages and permits fresh work, without reviving cancelled executions or affecting sibling stages.
|
|
16
|
+
- Fixed the `BACKGROUND` workflow list's stage count and `single`/`chain` label to include recursively nested stages as they appear, without double-counting expanded workflow boundaries. Completed, failed, and skipped stages retain their existing progress semantics. Recursive counts share run lookup preparation across cards within each refresh.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Reduced default workflow stage and authored parallel concurrency from 4 to 3, preserving explicit configuration and per-call overrides.
|
|
21
|
+
|
|
9
22
|
## [0.9.19-alpha.2] - 2026-09-08
|
|
10
23
|
|
|
11
24
|
### Added
|