@parall/agent-core 1.28.1 → 1.29.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/dist/dispatch-adapter.d.ts +9 -8
- package/dist/dispatch-adapter.d.ts.map +1 -1
- package/dist/event-format.d.ts +1 -0
- package/dist/event-format.d.ts.map +1 -1
- package/dist/event-format.js +11 -6
- package/dist/gateway-base.d.ts +5 -0
- package/dist/gateway-base.d.ts.map +1 -1
- package/dist/gateway-base.js +58 -44
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +7 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/dispatch-adapter.ts +9 -8
- package/src/event-format.ts +12 -5
- package/src/gateway-base.ts +73 -41
- package/src/index.ts +1 -0
- package/src/logger.ts +9 -0
- package/src/types.ts +5 -0
|
@@ -80,19 +80,20 @@ export interface DispatchAdapter {
|
|
|
80
80
|
/** Dispatch a Parall event to the runtime and emit normalized runtime events. */
|
|
81
81
|
dispatch(opts: DispatchOpts): AsyncIterable<RuntimeEvent>;
|
|
82
82
|
/**
|
|
83
|
-
* Inject a user message into the running
|
|
84
|
-
*
|
|
85
|
-
* waiting for the current turn to complete.
|
|
83
|
+
* Inject a user message into the running runtime mid-turn so it steers
|
|
84
|
+
* immediately, rather than waiting for the current turn to complete.
|
|
86
85
|
*
|
|
87
|
-
* Returns true if the
|
|
88
|
-
*
|
|
86
|
+
* Returns true if the injection succeeded; false if no live process/session
|
|
87
|
+
* exists (caller falls back to mainBuffer next-turn path). May return a
|
|
88
|
+
* Promise when the injection requires an async round-trip (e.g. Codex
|
|
89
|
+
* turn/steer JSON-RPC) — the gateway awaits it.
|
|
89
90
|
*
|
|
90
91
|
* The gateway still pushes the event to mainBuffer after a successful
|
|
91
92
|
* injection — drainMainBuffer will call dispatch() for it, and dispatch()
|
|
92
|
-
* must detect the pending injection (skip the
|
|
93
|
-
*
|
|
93
|
+
* must detect the pending injection (skip the duplicate input) and only
|
|
94
|
+
* consume output produced in response.
|
|
94
95
|
*/
|
|
95
|
-
enqueueDuringDispatch?(sessionKey: string, body: string): boolean
|
|
96
|
+
enqueueDuringDispatch?(sessionKey: string, body: string): boolean | Promise<boolean>;
|
|
96
97
|
/** True if enqueueDuringDispatch was called and the injections have not yet been consumed by dispatch(). */
|
|
97
98
|
hasPendingInjections?(sessionKey: string): boolean;
|
|
98
99
|
/** Fork the current runtime session for concurrent handling. Return null to buffer on main. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch-adapter.d.ts","sourceRoot":"","sources":["../src/dispatch-adapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dispatch-adapter.d.ts","sourceRoot":"","sources":["../src/dispatch-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,iBAAiB,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9G;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACjI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,aAAa,CAAC,EAAE,WAAW,EAAE,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;IAE1D;;;;;;;;;;;;;OAaG;IACH,qBAAqB,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErF,4GAA4G;IAC5G,oBAAoB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAEnD,+FAA+F;IAC/F,WAAW,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,iBAAiB,GAAG,IAAI,CAAC;IAE3F,wDAAwD;IACxD,WAAW,CAAC,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAE1D,6FAA6F;IAC7F,cAAc,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAExD,yFAAyF;IACzF,qBAAqB,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAChE"}
|
package/dist/event-format.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ForkResult, ParallEvent } from "./types.js";
|
|
2
2
|
export declare function buildEventBody(event: ParallEvent): string;
|
|
3
|
+
export declare function buildEventBodyForForkResult(event: ParallEvent): string;
|
|
3
4
|
export declare function buildForkScopePrefix(event: ParallEvent): string;
|
|
4
5
|
export declare function buildForkResultPrefix(results: ForkResult[]): string;
|
|
5
6
|
//# sourceMappingURL=event-format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-format.d.ts","sourceRoot":"","sources":["../src/event-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM1D,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAsDzD;AAoBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAK/D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"event-format.d.ts","sourceRoot":"","sources":["../src/event-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM1D,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAsDzD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEtE;AAoBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAK/D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAcnE"}
|
package/dist/event-format.js
CHANGED
|
@@ -65,6 +65,9 @@ export function buildEventBody(event) {
|
|
|
65
65
|
}
|
|
66
66
|
return lines.join("\n") + buildSendMessageHint(event);
|
|
67
67
|
}
|
|
68
|
+
export function buildEventBodyForForkResult(event) {
|
|
69
|
+
return buildEventBody(event).replace(/\n<system-reminder>[\s\S]*<\/system-reminder>$/, "");
|
|
70
|
+
}
|
|
68
71
|
function buildSendMessageHint(event) {
|
|
69
72
|
if (event.noReply)
|
|
70
73
|
return "";
|
|
@@ -89,14 +92,16 @@ export function buildForkResultPrefix(results) {
|
|
|
89
92
|
if (!results.length)
|
|
90
93
|
return "";
|
|
91
94
|
const blocks = results.map((result) => {
|
|
92
|
-
const lines = [
|
|
93
|
-
|
|
95
|
+
const lines = [];
|
|
96
|
+
for (const body of result.eventBodies) {
|
|
97
|
+
lines.push(body);
|
|
98
|
+
}
|
|
99
|
+
lines.push(`[This event was handled by a parallel fork session. Do NOT re-handle, re-reply, or duplicate work for it.]`);
|
|
100
|
+
lines.push(`[Fork summary: ${result.agentSummary ? sanitizeMeta(result.agentSummary) : "No fork summary available — the fork completed without producing a text summary. Check the target chat/task for any actions the fork already took before acting."}]`);
|
|
94
101
|
if (result.actions.length)
|
|
95
|
-
lines.push(`[
|
|
96
|
-
if (result.agentSummary)
|
|
97
|
-
lines.push(`[Summary: ${sanitizeMeta(result.agentSummary)}]`);
|
|
102
|
+
lines.push(`[Fork actions: ${result.actions.join("; ")}]`);
|
|
98
103
|
if (result.historyPath)
|
|
99
|
-
lines.push(`[
|
|
104
|
+
lines.push(`[Fork history: ${result.historyPath}]`);
|
|
100
105
|
return lines.join("\n");
|
|
101
106
|
});
|
|
102
107
|
return blocks.join("\n\n") + "\n\n---\n\n";
|
package/dist/gateway-base.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export declare class ParallAgentGateway {
|
|
|
41
41
|
private readonly opts;
|
|
42
42
|
private readonly chatInfoMap;
|
|
43
43
|
private readonly activeDispatches;
|
|
44
|
+
private readonly injectedTypingCounts;
|
|
44
45
|
private readonly dispatchedTasks;
|
|
45
46
|
private readonly dispatchedMessages;
|
|
46
47
|
private readonly forkStates;
|
|
@@ -63,6 +64,10 @@ export declare class ParallAgentGateway {
|
|
|
63
64
|
private tryClaimMessage;
|
|
64
65
|
private startTyping;
|
|
65
66
|
private stopTyping;
|
|
67
|
+
private shouldShowTyping;
|
|
68
|
+
private startInjectedTyping;
|
|
69
|
+
private takeInjectedTypingCount;
|
|
70
|
+
private runDispatchWithTyping;
|
|
66
71
|
private buildDispatchContext;
|
|
67
72
|
private createInputStep;
|
|
68
73
|
private createRuntimeStep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway-base.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as os from "node:os";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
5
4
|
import { MENTION_ALL_USER_ID } from "@parall/sdk";
|
|
6
|
-
import { buildEventBody, buildForkResultPrefix, buildForkScopePrefix } from "./event-format.js";
|
|
5
|
+
import { buildEventBody, buildEventBodyForForkResult, buildForkResultPrefix, buildForkScopePrefix } from "./event-format.js";
|
|
7
6
|
import { routeTrigger } from "./routing.js";
|
|
8
7
|
import { clearDispatchMessageId, clearDispatchNoReply, clearSessionMessageId, setDispatchMessageId, setDispatchNoReply, setSessionChatId, setSessionMessageId, } from "./session-state.js";
|
|
9
8
|
// Parse PRLL_SHUTDOWN_DEADLINE_MS (or any string env value) into a positive
|
|
@@ -55,6 +54,7 @@ export class ParallAgentGateway {
|
|
|
55
54
|
opts;
|
|
56
55
|
chatInfoMap = new Map();
|
|
57
56
|
activeDispatches = new Map();
|
|
57
|
+
injectedTypingCounts = new Map();
|
|
58
58
|
dispatchedTasks = new Set();
|
|
59
59
|
dispatchedMessages = new Set();
|
|
60
60
|
forkStates = new Map();
|
|
@@ -266,6 +266,35 @@ export class ParallAgentGateway {
|
|
|
266
266
|
if (this.opts.ws.state === "connected")
|
|
267
267
|
this.opts.ws.sendTyping(chatId, "stop");
|
|
268
268
|
}
|
|
269
|
+
shouldShowTyping(event) {
|
|
270
|
+
return event.type === "message" && event.targetId.startsWith("cht_") && !event.noReply;
|
|
271
|
+
}
|
|
272
|
+
startInjectedTyping(event) {
|
|
273
|
+
if (!this.shouldShowTyping(event))
|
|
274
|
+
return;
|
|
275
|
+
this.startTyping(event.targetId);
|
|
276
|
+
this.injectedTypingCounts.set(event.targetId, (this.injectedTypingCounts.get(event.targetId) ?? 0) + 1);
|
|
277
|
+
}
|
|
278
|
+
takeInjectedTypingCount(chatId) {
|
|
279
|
+
const count = this.injectedTypingCounts.get(chatId) ?? 0;
|
|
280
|
+
this.injectedTypingCounts.delete(chatId);
|
|
281
|
+
return count;
|
|
282
|
+
}
|
|
283
|
+
async runDispatchWithTyping(event, sessionKey, bodyForAgent, earlierEvents = [], captureText, opts = {}) {
|
|
284
|
+
const showTyping = !opts.suppressStart && (this.shouldShowTyping(event) || earlierEvents.some(e => this.shouldShowTyping(e)));
|
|
285
|
+
if (showTyping)
|
|
286
|
+
this.startTyping(event.targetId);
|
|
287
|
+
try {
|
|
288
|
+
return await this.runDispatch(event, sessionKey, bodyForAgent, earlierEvents, captureText);
|
|
289
|
+
}
|
|
290
|
+
finally {
|
|
291
|
+
if (showTyping)
|
|
292
|
+
this.stopTyping(event.targetId);
|
|
293
|
+
for (let i = 0; i < (opts.injectedTypingCount ?? 0); i++) {
|
|
294
|
+
this.stopTyping(event.targetId);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
269
298
|
buildDispatchContext(event, sessionKey) {
|
|
270
299
|
const binding = this.sessionBindings.get(sessionKey);
|
|
271
300
|
return {
|
|
@@ -307,6 +336,7 @@ export class ParallAgentGateway {
|
|
|
307
336
|
sender_id: event.senderId,
|
|
308
337
|
sender_name: event.senderName,
|
|
309
338
|
summary: event.body.substring(0, 200),
|
|
339
|
+
...(event.sentAt ? { sent_at: event.sentAt } : {}),
|
|
310
340
|
},
|
|
311
341
|
});
|
|
312
342
|
}
|
|
@@ -554,7 +584,8 @@ export class ParallAgentGateway {
|
|
|
554
584
|
continue;
|
|
555
585
|
}
|
|
556
586
|
if (!binding) {
|
|
557
|
-
|
|
587
|
+
const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
|
|
588
|
+
throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
|
|
558
589
|
}
|
|
559
590
|
if (!triggerMessageSet) {
|
|
560
591
|
triggerMessageSet = true;
|
|
@@ -637,7 +668,7 @@ export class ParallAgentGateway {
|
|
|
637
668
|
const earlier = events.slice(0, -1);
|
|
638
669
|
try {
|
|
639
670
|
const batchText = [];
|
|
640
|
-
const dispatched = await this.
|
|
671
|
+
const dispatched = await this.runDispatchWithTyping(last, fork.fork.sessionKey, buildForkScopePrefix(last) + buildEventBody(last), earlier, batchText);
|
|
641
672
|
if (!dispatched) {
|
|
642
673
|
// Shutdown short-circuit — resolve un-acked so the server requeues
|
|
643
674
|
// for the replacement pod and stop draining further items.
|
|
@@ -685,6 +716,7 @@ export class ParallAgentGateway {
|
|
|
685
716
|
? `${first.type} from ${first.senderName} in ${first.targetName ?? fork.targetId}`
|
|
686
717
|
: `${fork.processedEvents.length} events in ${first.targetName ?? fork.targetId}`,
|
|
687
718
|
},
|
|
719
|
+
eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
|
|
688
720
|
actions: [],
|
|
689
721
|
agentSummary,
|
|
690
722
|
historyPath,
|
|
@@ -723,7 +755,7 @@ export class ParallAgentGateway {
|
|
|
723
755
|
return;
|
|
724
756
|
this.draining = true;
|
|
725
757
|
try {
|
|
726
|
-
while (this.dispatchState.mainBuffer.length > 0
|
|
758
|
+
while (this.dispatchState.mainBuffer.length > 0) {
|
|
727
759
|
// Early shutdown guard — same reasoning as runForkDrainLoop: stop
|
|
728
760
|
// before any input AgentSteps are persisted, leaving the buffer +
|
|
729
761
|
// pendingForkResults intact so dispatch catch-up on the replacement
|
|
@@ -732,31 +764,6 @@ export class ParallAgentGateway {
|
|
|
732
764
|
this.opts.log?.info(`parall[${this.opts.accountId}]: drainMainBuffer halted (shutting down) — ${this.dispatchState.mainBuffer.length} buffered, ${this.dispatchState.pendingForkResults.length} pending fork results left for catch-up`);
|
|
733
765
|
break;
|
|
734
766
|
}
|
|
735
|
-
if (this.dispatchState.mainBuffer.length === 0 && this.dispatchState.pendingForkResults.length > 0) {
|
|
736
|
-
const pending = this.dispatchState.pendingForkResults.splice(0);
|
|
737
|
-
const forkPrefix = buildForkResultPrefix(pending);
|
|
738
|
-
const syntheticEvent = {
|
|
739
|
-
type: "message",
|
|
740
|
-
targetId: "_orchestrator",
|
|
741
|
-
targetType: "system",
|
|
742
|
-
senderId: "system",
|
|
743
|
-
senderName: "system",
|
|
744
|
-
messageId: `synthetic-${this.opts.accountId}-${randomUUID()}`,
|
|
745
|
-
body: "[Orchestrator: fork session(s) completed — review results above]",
|
|
746
|
-
};
|
|
747
|
-
this.dispatchState.mainCurrentTargetId = undefined;
|
|
748
|
-
this.dispatchState.mainPreDispatchBranchPoint =
|
|
749
|
-
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
750
|
-
const dispatched = await this.runDispatch(syntheticEvent, this.opts.runtimeKey, forkPrefix + buildEventBody(syntheticEvent));
|
|
751
|
-
if (!dispatched) {
|
|
752
|
-
// Shutdown: put the fork results back at the head so the synthetic
|
|
753
|
-
// event is regenerated on the replacement pod. Synthetic events are
|
|
754
|
-
// not ack'd, so this is the only state we need to preserve.
|
|
755
|
-
this.dispatchState.pendingForkResults.unshift(...pending);
|
|
756
|
-
break;
|
|
757
|
-
}
|
|
758
|
-
continue;
|
|
759
|
-
}
|
|
760
767
|
const targetId = this.dispatchState.mainBuffer[0].targetId;
|
|
761
768
|
const events = [];
|
|
762
769
|
while (this.dispatchState.mainBuffer[0]?.targetId === targetId) {
|
|
@@ -764,13 +771,14 @@ export class ParallAgentGateway {
|
|
|
764
771
|
}
|
|
765
772
|
const event = events[events.length - 1];
|
|
766
773
|
const earlier = events.slice(0, -1);
|
|
767
|
-
const
|
|
768
|
-
const
|
|
774
|
+
const hasPendingInjections = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
|
|
775
|
+
const injectedTypingCount = hasPendingInjections ? this.takeInjectedTypingCount(event.targetId) : 0;
|
|
776
|
+
const pendingFork = hasPendingInjections ? [] : this.dispatchState.pendingForkResults.splice(0);
|
|
769
777
|
const forkPrefix = buildForkResultPrefix(pendingFork);
|
|
770
778
|
this.dispatchState.mainCurrentTargetId = event.targetId;
|
|
771
779
|
this.dispatchState.mainPreDispatchBranchPoint =
|
|
772
780
|
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
773
|
-
const dispatched = await this.
|
|
781
|
+
const dispatched = await this.runDispatchWithTyping(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event), earlier, undefined, { suppressStart: injectedTypingCount > 0, injectedTypingCount });
|
|
774
782
|
if (!dispatched) {
|
|
775
783
|
// Shutdown: skip the ack so the server redelivers these buffered
|
|
776
784
|
// events to the replacement pod via dispatch catch-up. Put both the
|
|
@@ -811,7 +819,7 @@ export class ParallAgentGateway {
|
|
|
811
819
|
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
812
820
|
let dispatched = false;
|
|
813
821
|
try {
|
|
814
|
-
dispatched = await this.
|
|
822
|
+
dispatched = await this.runDispatchWithTyping(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event));
|
|
815
823
|
if (!dispatched) {
|
|
816
824
|
// Shutdown short-circuit — restore the fork results so a future
|
|
817
825
|
// pod can replay them, and return false so handleMessage skips ack.
|
|
@@ -827,11 +835,22 @@ export class ParallAgentGateway {
|
|
|
827
835
|
if (this.shuttingDown) {
|
|
828
836
|
return false;
|
|
829
837
|
}
|
|
838
|
+
// Push synchronously BEFORE the (possibly async) steer attempt so
|
|
839
|
+
// arrival order is preserved and the event cannot be orphaned in a
|
|
840
|
+
// gap between the steer await and the push.
|
|
841
|
+
this.dispatchState.mainBuffer.push(event);
|
|
830
842
|
if (this.dispatchState.mainCurrentTargetId === event.targetId &&
|
|
831
|
-
this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
|
|
832
|
-
this.
|
|
843
|
+
await this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
|
|
844
|
+
this.startInjectedTyping(event);
|
|
845
|
+
this.opts.log?.info(`parall[${this.opts.accountId}]: steer injected for ${event.messageId} (will drain for bookkeeping)`);
|
|
846
|
+
}
|
|
847
|
+
// If the main dispatch cycle ended while we awaited the steer RPC,
|
|
848
|
+
// our event is buffered but no drain is in flight. Re-enter the
|
|
849
|
+
// drain to process it. The draining guard prevents re-entry.
|
|
850
|
+
if (!this.dispatchState.mainDispatching && !this.draining && this.dispatchState.mainBuffer.length > 0) {
|
|
851
|
+
this.dispatchState.mainDispatching = true;
|
|
852
|
+
void this.drainMainBuffer();
|
|
833
853
|
}
|
|
834
|
-
this.dispatchState.mainBuffer.push(event);
|
|
835
854
|
return false;
|
|
836
855
|
}
|
|
837
856
|
case "buffer-fork": {
|
|
@@ -934,6 +953,7 @@ export class ParallAgentGateway {
|
|
|
934
953
|
threadRootId: message.thread_root_id ?? undefined,
|
|
935
954
|
noReply: message.hints?.no_reply ?? false,
|
|
936
955
|
attachments: attachments.length > 0 ? attachments : undefined,
|
|
956
|
+
sentAt: message.created_at,
|
|
937
957
|
ackSourceType: "message",
|
|
938
958
|
ackSourceId: message.id,
|
|
939
959
|
},
|
|
@@ -955,9 +975,6 @@ export class ParallAgentGateway {
|
|
|
955
975
|
return;
|
|
956
976
|
}
|
|
957
977
|
const event = decision.event;
|
|
958
|
-
const willDispatch = !this.dispatchState.mainDispatching || this.dispatchState.mainCurrentTargetId !== chatId;
|
|
959
|
-
if (willDispatch)
|
|
960
|
-
this.startTyping(chatId);
|
|
961
978
|
try {
|
|
962
979
|
const dispatched = await this.handleInboundEvent(event);
|
|
963
980
|
if (dispatched) {
|
|
@@ -971,10 +988,6 @@ export class ParallAgentGateway {
|
|
|
971
988
|
this.opts.log?.error(`parall[${this.opts.accountId}]: event dispatch failed for ${data.id}: ${String(err)}`);
|
|
972
989
|
this.dispatchedMessages.delete(data.id);
|
|
973
990
|
}
|
|
974
|
-
finally {
|
|
975
|
-
if (willDispatch)
|
|
976
|
-
this.stopTyping(chatId);
|
|
977
|
-
}
|
|
978
991
|
}
|
|
979
992
|
async handleTaskAssignment(task, ackSourceId) {
|
|
980
993
|
if (this.shuttingDown)
|
|
@@ -1003,6 +1016,7 @@ export class ParallAgentGateway {
|
|
|
1003
1016
|
senderName: "system",
|
|
1004
1017
|
messageId: task.id,
|
|
1005
1018
|
body: parts.join("\n"),
|
|
1019
|
+
sentAt: task.updated_at ?? task.created_at,
|
|
1006
1020
|
ackSourceType: "task_activity",
|
|
1007
1021
|
ackSourceId,
|
|
1008
1022
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./event-format.js";
|
|
|
5
5
|
export * from "./prompt-fragments.js";
|
|
6
6
|
export * from "./bridge-workspace.js";
|
|
7
7
|
export * from "./dispatch-adapter.js";
|
|
8
|
+
export { createLogger } from "./logger.js";
|
|
8
9
|
export * from "./gateway-base.js";
|
|
9
10
|
export * from "./platform-config.js";
|
|
10
11
|
export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./event-format.js";
|
|
|
5
5
|
export * from "./prompt-fragments.js";
|
|
6
6
|
export * from "./bridge-workspace.js";
|
|
7
7
|
export * from "./dispatch-adapter.js";
|
|
8
|
+
export { createLogger } from "./logger.js";
|
|
8
9
|
export * from "./gateway-base.js";
|
|
9
10
|
export * from "./platform-config.js";
|
|
10
11
|
export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAM1D"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function createLogger(prefix) {
|
|
2
|
+
return {
|
|
3
|
+
info: (msg) => console.log(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
4
|
+
warn: (msg) => console.warn(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
5
|
+
error: (msg) => console.error(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
6
|
+
};
|
|
7
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type ForkResult = {
|
|
|
6
6
|
targetId: string;
|
|
7
7
|
summary: string;
|
|
8
8
|
};
|
|
9
|
+
/** Original event bodies that the fork processed, built via `buildEventBody()`. */
|
|
10
|
+
eventBodies: string[];
|
|
9
11
|
actions: string[];
|
|
10
12
|
/** Agent's own summary of what it did (captured from the fork's last text output). */
|
|
11
13
|
agentSummary?: string;
|
|
@@ -45,6 +47,9 @@ export type ParallEvent = {
|
|
|
45
47
|
scheduledFireAt?: string;
|
|
46
48
|
/** Fire-time attached_to_uri snapshot, used for schedule events. */
|
|
47
49
|
attachedUri?: string;
|
|
50
|
+
/** Original event timestamp (e.g., message.created_at). When present,
|
|
51
|
+
* input steps use this instead of server insertion time for ordering. */
|
|
52
|
+
sentAt?: string;
|
|
48
53
|
ackSourceType?: "message" | "task_activity" | "comment" | "schedule_run";
|
|
49
54
|
ackSourceId?: string;
|
|
50
55
|
};
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,MAAM,UAAU,GAAG;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GAAG;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kBAAkB,EAAE,UAAU,EAAE,CAAC;IACjC,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,oFAAoF;IACpF,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,CAAC;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,MAAM,UAAU,GAAG;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,mFAAmF;IACnF,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GAAG;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,kBAAkB,EAAE,UAAU,EAAE,CAAC;IACjC,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,oFAAoF;IACpF,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,CAAC;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,8DAA8D;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;8EAC0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/agent-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.1",
|
|
4
4
|
"description": "Shared agent runtime orchestration helpers for Parall",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"src"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@parall/sdk": "1.
|
|
29
|
+
"@parall/sdk": "1.29.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.0.0",
|
package/src/dispatch-adapter.ts
CHANGED
|
@@ -68,19 +68,20 @@ export interface DispatchAdapter {
|
|
|
68
68
|
dispatch(opts: DispatchOpts): AsyncIterable<RuntimeEvent>;
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Inject a user message into the running
|
|
72
|
-
*
|
|
73
|
-
* waiting for the current turn to complete.
|
|
71
|
+
* Inject a user message into the running runtime mid-turn so it steers
|
|
72
|
+
* immediately, rather than waiting for the current turn to complete.
|
|
74
73
|
*
|
|
75
|
-
* Returns true if the
|
|
76
|
-
*
|
|
74
|
+
* Returns true if the injection succeeded; false if no live process/session
|
|
75
|
+
* exists (caller falls back to mainBuffer next-turn path). May return a
|
|
76
|
+
* Promise when the injection requires an async round-trip (e.g. Codex
|
|
77
|
+
* turn/steer JSON-RPC) — the gateway awaits it.
|
|
77
78
|
*
|
|
78
79
|
* The gateway still pushes the event to mainBuffer after a successful
|
|
79
80
|
* injection — drainMainBuffer will call dispatch() for it, and dispatch()
|
|
80
|
-
* must detect the pending injection (skip the
|
|
81
|
-
*
|
|
81
|
+
* must detect the pending injection (skip the duplicate input) and only
|
|
82
|
+
* consume output produced in response.
|
|
82
83
|
*/
|
|
83
|
-
enqueueDuringDispatch?(sessionKey: string, body: string): boolean
|
|
84
|
+
enqueueDuringDispatch?(sessionKey: string, body: string): boolean | Promise<boolean>;
|
|
84
85
|
|
|
85
86
|
/** True if enqueueDuringDispatch was called and the injections have not yet been consumed by dispatch(). */
|
|
86
87
|
hasPendingInjections?(sessionKey: string): boolean;
|
package/src/event-format.ts
CHANGED
|
@@ -60,6 +60,10 @@ export function buildEventBody(event: ParallEvent): string {
|
|
|
60
60
|
return lines.join("\n") + buildSendMessageHint(event);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export function buildEventBodyForForkResult(event: ParallEvent): string {
|
|
64
|
+
return buildEventBody(event).replace(/\n<system-reminder>[\s\S]*<\/system-reminder>$/, "");
|
|
65
|
+
}
|
|
66
|
+
|
|
63
67
|
function buildSendMessageHint(event: ParallEvent): string {
|
|
64
68
|
if (event.noReply) return "";
|
|
65
69
|
|
|
@@ -88,11 +92,14 @@ export function buildForkScopePrefix(event: ParallEvent): string {
|
|
|
88
92
|
export function buildForkResultPrefix(results: ForkResult[]): string {
|
|
89
93
|
if (!results.length) return "";
|
|
90
94
|
const blocks = results.map((result) => {
|
|
91
|
-
const lines = [
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
const lines: string[] = [];
|
|
96
|
+
for (const body of result.eventBodies) {
|
|
97
|
+
lines.push(body);
|
|
98
|
+
}
|
|
99
|
+
lines.push(`[This event was handled by a parallel fork session. Do NOT re-handle, re-reply, or duplicate work for it.]`);
|
|
100
|
+
lines.push(`[Fork summary: ${result.agentSummary ? sanitizeMeta(result.agentSummary) : "No fork summary available — the fork completed without producing a text summary. Check the target chat/task for any actions the fork already took before acting."}]`);
|
|
101
|
+
if (result.actions.length) lines.push(`[Fork actions: ${result.actions.join("; ")}]`);
|
|
102
|
+
if (result.historyPath) lines.push(`[Fork history: ${result.historyPath}]`);
|
|
96
103
|
return lines.join("\n");
|
|
97
104
|
});
|
|
98
105
|
return blocks.join("\n\n") + "\n\n---\n\n";
|
package/src/gateway-base.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as os from "node:os";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
5
4
|
import { MENTION_ALL_USER_ID, ParallClient, ParallWs } from "@parall/sdk";
|
|
6
5
|
import type {
|
|
7
6
|
AgentConfigUpdateData,
|
|
@@ -19,7 +18,7 @@ import type {
|
|
|
19
18
|
TaskAssignedData,
|
|
20
19
|
TextContent,
|
|
21
20
|
} from "@parall/sdk";
|
|
22
|
-
import { buildEventBody, buildForkResultPrefix, buildForkScopePrefix } from "./event-format.js";
|
|
21
|
+
import { buildEventBody, buildEventBodyForForkResult, buildForkResultPrefix, buildForkScopePrefix } from "./event-format.js";
|
|
23
22
|
import type {
|
|
24
23
|
CleanupForkOpts,
|
|
25
24
|
DispatchAdapter,
|
|
@@ -72,6 +71,7 @@ type DispatchableMessage = {
|
|
|
72
71
|
thread_root_id?: string | null;
|
|
73
72
|
hints?: { no_reply?: boolean } | null;
|
|
74
73
|
attachments?: Array<{ id: string; file_name: string; file_size: number; mime_type: string }>;
|
|
74
|
+
created_at?: string;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
type MessageDispatchDecision =
|
|
@@ -170,6 +170,7 @@ async function fetchAllChats(
|
|
|
170
170
|
export class ParallAgentGateway {
|
|
171
171
|
private readonly chatInfoMap = new Map<string, ChatInfo>();
|
|
172
172
|
private readonly activeDispatches = new Map<string, ActiveDispatch>();
|
|
173
|
+
private readonly injectedTypingCounts = new Map<string, number>();
|
|
173
174
|
private readonly dispatchedTasks = new Set<string>();
|
|
174
175
|
private readonly dispatchedMessages = new Set<string>();
|
|
175
176
|
private readonly forkStates = new Map<string, ActiveForkState>();
|
|
@@ -377,6 +378,42 @@ export class ParallAgentGateway {
|
|
|
377
378
|
if (this.opts.ws.state === "connected") this.opts.ws.sendTyping(chatId, "stop");
|
|
378
379
|
}
|
|
379
380
|
|
|
381
|
+
private shouldShowTyping(event: ParallEvent): boolean {
|
|
382
|
+
return event.type === "message" && event.targetId.startsWith("cht_") && !event.noReply;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private startInjectedTyping(event: ParallEvent) {
|
|
386
|
+
if (!this.shouldShowTyping(event)) return;
|
|
387
|
+
this.startTyping(event.targetId);
|
|
388
|
+
this.injectedTypingCounts.set(event.targetId, (this.injectedTypingCounts.get(event.targetId) ?? 0) + 1);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
private takeInjectedTypingCount(chatId: string): number {
|
|
392
|
+
const count = this.injectedTypingCounts.get(chatId) ?? 0;
|
|
393
|
+
this.injectedTypingCounts.delete(chatId);
|
|
394
|
+
return count;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private async runDispatchWithTyping(
|
|
398
|
+
event: ParallEvent,
|
|
399
|
+
sessionKey: string,
|
|
400
|
+
bodyForAgent: string,
|
|
401
|
+
earlierEvents: ParallEvent[] = [],
|
|
402
|
+
captureText?: string[],
|
|
403
|
+
opts: { suppressStart?: boolean; injectedTypingCount?: number } = {},
|
|
404
|
+
): Promise<boolean> {
|
|
405
|
+
const showTyping = !opts.suppressStart && (this.shouldShowTyping(event) || earlierEvents.some(e => this.shouldShowTyping(e)));
|
|
406
|
+
if (showTyping) this.startTyping(event.targetId);
|
|
407
|
+
try {
|
|
408
|
+
return await this.runDispatch(event, sessionKey, bodyForAgent, earlierEvents, captureText);
|
|
409
|
+
} finally {
|
|
410
|
+
if (showTyping) this.stopTyping(event.targetId);
|
|
411
|
+
for (let i = 0; i < (opts.injectedTypingCount ?? 0); i++) {
|
|
412
|
+
this.stopTyping(event.targetId);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
380
417
|
private buildDispatchContext(event: ParallEvent, sessionKey: string): DispatchContext {
|
|
381
418
|
const binding = this.sessionBindings.get(sessionKey);
|
|
382
419
|
return {
|
|
@@ -421,6 +458,7 @@ export class ParallAgentGateway {
|
|
|
421
458
|
sender_id: event.senderId,
|
|
422
459
|
sender_name: event.senderName,
|
|
423
460
|
summary: event.body.substring(0, 200),
|
|
461
|
+
...(event.sentAt ? { sent_at: event.sentAt } : {}),
|
|
424
462
|
},
|
|
425
463
|
});
|
|
426
464
|
} catch (err) {
|
|
@@ -693,7 +731,8 @@ export class ParallAgentGateway {
|
|
|
693
731
|
}
|
|
694
732
|
|
|
695
733
|
if (!binding) {
|
|
696
|
-
|
|
734
|
+
const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
|
|
735
|
+
throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
|
|
697
736
|
}
|
|
698
737
|
if (!triggerMessageSet) {
|
|
699
738
|
triggerMessageSet = true;
|
|
@@ -778,7 +817,7 @@ export class ParallAgentGateway {
|
|
|
778
817
|
const earlier = events.slice(0, -1);
|
|
779
818
|
try {
|
|
780
819
|
const batchText: string[] = [];
|
|
781
|
-
const dispatched = await this.
|
|
820
|
+
const dispatched = await this.runDispatchWithTyping(last, fork.fork.sessionKey, buildForkScopePrefix(last) + buildEventBody(last), earlier, batchText);
|
|
782
821
|
if (!dispatched) {
|
|
783
822
|
// Shutdown short-circuit — resolve un-acked so the server requeues
|
|
784
823
|
// for the replacement pod and stop draining further items.
|
|
@@ -823,6 +862,7 @@ export class ParallAgentGateway {
|
|
|
823
862
|
? `${first.type} from ${first.senderName} in ${first.targetName ?? fork.targetId}`
|
|
824
863
|
: `${fork.processedEvents.length} events in ${first.targetName ?? fork.targetId}`,
|
|
825
864
|
},
|
|
865
|
+
eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
|
|
826
866
|
actions: [],
|
|
827
867
|
agentSummary,
|
|
828
868
|
historyPath,
|
|
@@ -864,7 +904,7 @@ export class ParallAgentGateway {
|
|
|
864
904
|
if (this.draining) return;
|
|
865
905
|
this.draining = true;
|
|
866
906
|
try {
|
|
867
|
-
while (this.dispatchState.mainBuffer.length > 0
|
|
907
|
+
while (this.dispatchState.mainBuffer.length > 0) {
|
|
868
908
|
// Early shutdown guard — same reasoning as runForkDrainLoop: stop
|
|
869
909
|
// before any input AgentSteps are persisted, leaving the buffer +
|
|
870
910
|
// pendingForkResults intact so dispatch catch-up on the replacement
|
|
@@ -875,31 +915,6 @@ export class ParallAgentGateway {
|
|
|
875
915
|
);
|
|
876
916
|
break;
|
|
877
917
|
}
|
|
878
|
-
if (this.dispatchState.mainBuffer.length === 0 && this.dispatchState.pendingForkResults.length > 0) {
|
|
879
|
-
const pending = this.dispatchState.pendingForkResults.splice(0);
|
|
880
|
-
const forkPrefix = buildForkResultPrefix(pending);
|
|
881
|
-
const syntheticEvent: ParallEvent = {
|
|
882
|
-
type: "message",
|
|
883
|
-
targetId: "_orchestrator",
|
|
884
|
-
targetType: "system",
|
|
885
|
-
senderId: "system",
|
|
886
|
-
senderName: "system",
|
|
887
|
-
messageId: `synthetic-${this.opts.accountId}-${randomUUID()}`,
|
|
888
|
-
body: "[Orchestrator: fork session(s) completed — review results above]",
|
|
889
|
-
};
|
|
890
|
-
this.dispatchState.mainCurrentTargetId = undefined;
|
|
891
|
-
this.dispatchState.mainPreDispatchBranchPoint =
|
|
892
|
-
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
893
|
-
const dispatched = await this.runDispatch(syntheticEvent, this.opts.runtimeKey, forkPrefix + buildEventBody(syntheticEvent));
|
|
894
|
-
if (!dispatched) {
|
|
895
|
-
// Shutdown: put the fork results back at the head so the synthetic
|
|
896
|
-
// event is regenerated on the replacement pod. Synthetic events are
|
|
897
|
-
// not ack'd, so this is the only state we need to preserve.
|
|
898
|
-
this.dispatchState.pendingForkResults.unshift(...pending);
|
|
899
|
-
break;
|
|
900
|
-
}
|
|
901
|
-
continue;
|
|
902
|
-
}
|
|
903
918
|
|
|
904
919
|
const targetId = this.dispatchState.mainBuffer[0].targetId;
|
|
905
920
|
const events: ParallEvent[] = [];
|
|
@@ -909,13 +924,21 @@ export class ParallAgentGateway {
|
|
|
909
924
|
|
|
910
925
|
const event = events[events.length - 1];
|
|
911
926
|
const earlier = events.slice(0, -1);
|
|
912
|
-
const
|
|
913
|
-
const
|
|
927
|
+
const hasPendingInjections = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
|
|
928
|
+
const injectedTypingCount = hasPendingInjections ? this.takeInjectedTypingCount(event.targetId) : 0;
|
|
929
|
+
const pendingFork = hasPendingInjections ? [] : this.dispatchState.pendingForkResults.splice(0);
|
|
914
930
|
const forkPrefix = buildForkResultPrefix(pendingFork);
|
|
915
931
|
this.dispatchState.mainCurrentTargetId = event.targetId;
|
|
916
932
|
this.dispatchState.mainPreDispatchBranchPoint =
|
|
917
933
|
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
918
|
-
const dispatched = await this.
|
|
934
|
+
const dispatched = await this.runDispatchWithTyping(
|
|
935
|
+
event,
|
|
936
|
+
this.opts.runtimeKey,
|
|
937
|
+
forkPrefix + buildEventBody(event),
|
|
938
|
+
earlier,
|
|
939
|
+
undefined,
|
|
940
|
+
{ suppressStart: injectedTypingCount > 0, injectedTypingCount },
|
|
941
|
+
);
|
|
919
942
|
if (!dispatched) {
|
|
920
943
|
// Shutdown: skip the ack so the server redelivers these buffered
|
|
921
944
|
// events to the replacement pod via dispatch catch-up. Put both the
|
|
@@ -957,7 +980,7 @@ export class ParallAgentGateway {
|
|
|
957
980
|
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
958
981
|
let dispatched = false;
|
|
959
982
|
try {
|
|
960
|
-
dispatched = await this.
|
|
983
|
+
dispatched = await this.runDispatchWithTyping(event, this.opts.runtimeKey, forkPrefix + buildEventBody(event));
|
|
961
984
|
if (!dispatched) {
|
|
962
985
|
// Shutdown short-circuit — restore the fork results so a future
|
|
963
986
|
// pod can replay them, and return false so handleMessage skips ack.
|
|
@@ -973,15 +996,26 @@ export class ParallAgentGateway {
|
|
|
973
996
|
if (this.shuttingDown) {
|
|
974
997
|
return false;
|
|
975
998
|
}
|
|
999
|
+
// Push synchronously BEFORE the (possibly async) steer attempt so
|
|
1000
|
+
// arrival order is preserved and the event cannot be orphaned in a
|
|
1001
|
+
// gap between the steer await and the push.
|
|
1002
|
+
this.dispatchState.mainBuffer.push(event);
|
|
976
1003
|
if (
|
|
977
1004
|
this.dispatchState.mainCurrentTargetId === event.targetId &&
|
|
978
|
-
this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))
|
|
1005
|
+
await this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))
|
|
979
1006
|
) {
|
|
1007
|
+
this.startInjectedTyping(event);
|
|
980
1008
|
this.opts.log?.info(
|
|
981
|
-
`parall[${this.opts.accountId}]: steer injected
|
|
1009
|
+
`parall[${this.opts.accountId}]: steer injected for ${event.messageId} (will drain for bookkeeping)`,
|
|
982
1010
|
);
|
|
983
1011
|
}
|
|
984
|
-
|
|
1012
|
+
// If the main dispatch cycle ended while we awaited the steer RPC,
|
|
1013
|
+
// our event is buffered but no drain is in flight. Re-enter the
|
|
1014
|
+
// drain to process it. The draining guard prevents re-entry.
|
|
1015
|
+
if (!this.dispatchState.mainDispatching && !this.draining && this.dispatchState.mainBuffer.length > 0) {
|
|
1016
|
+
this.dispatchState.mainDispatching = true;
|
|
1017
|
+
void this.drainMainBuffer();
|
|
1018
|
+
}
|
|
985
1019
|
return false;
|
|
986
1020
|
}
|
|
987
1021
|
|
|
@@ -1098,6 +1132,7 @@ export class ParallAgentGateway {
|
|
|
1098
1132
|
threadRootId: message.thread_root_id ?? undefined,
|
|
1099
1133
|
noReply: message.hints?.no_reply ?? false,
|
|
1100
1134
|
attachments: attachments.length > 0 ? attachments : undefined,
|
|
1135
|
+
sentAt: message.created_at,
|
|
1101
1136
|
ackSourceType: "message",
|
|
1102
1137
|
ackSourceId: message.id,
|
|
1103
1138
|
},
|
|
@@ -1118,8 +1153,6 @@ export class ParallAgentGateway {
|
|
|
1118
1153
|
}
|
|
1119
1154
|
const event = decision.event;
|
|
1120
1155
|
|
|
1121
|
-
const willDispatch = !this.dispatchState.mainDispatching || this.dispatchState.mainCurrentTargetId !== chatId;
|
|
1122
|
-
if (willDispatch) this.startTyping(chatId);
|
|
1123
1156
|
try {
|
|
1124
1157
|
const dispatched = await this.handleInboundEvent(event);
|
|
1125
1158
|
if (dispatched) {
|
|
@@ -1130,8 +1163,6 @@ export class ParallAgentGateway {
|
|
|
1130
1163
|
} catch (err) {
|
|
1131
1164
|
this.opts.log?.error(`parall[${this.opts.accountId}]: event dispatch failed for ${data.id}: ${String(err)}`);
|
|
1132
1165
|
this.dispatchedMessages.delete(data.id);
|
|
1133
|
-
} finally {
|
|
1134
|
-
if (willDispatch) this.stopTyping(chatId);
|
|
1135
1166
|
}
|
|
1136
1167
|
}
|
|
1137
1168
|
|
|
@@ -1160,6 +1191,7 @@ export class ParallAgentGateway {
|
|
|
1160
1191
|
senderName: "system",
|
|
1161
1192
|
messageId: task.id,
|
|
1162
1193
|
body: parts.join("\n"),
|
|
1194
|
+
sentAt: task.updated_at ?? task.created_at,
|
|
1163
1195
|
ackSourceType: "task_activity",
|
|
1164
1196
|
ackSourceId,
|
|
1165
1197
|
};
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./event-format.js";
|
|
|
5
5
|
export * from "./prompt-fragments.js";
|
|
6
6
|
export * from "./bridge-workspace.js";
|
|
7
7
|
export * from "./dispatch-adapter.js";
|
|
8
|
+
export { createLogger } from "./logger.js";
|
|
8
9
|
export * from "./gateway-base.js";
|
|
9
10
|
export * from "./platform-config.js";
|
|
10
11
|
export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GatewayLogger } from "./dispatch-adapter.js";
|
|
2
|
+
|
|
3
|
+
export function createLogger(prefix: string): GatewayLogger {
|
|
4
|
+
return {
|
|
5
|
+
info: (msg: string) => console.log(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
6
|
+
warn: (msg: string) => console.warn(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
7
|
+
error: (msg: string) => console.error(`${new Date().toISOString()} [${prefix}] ${msg}`),
|
|
8
|
+
};
|
|
9
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
export type ForkResult = {
|
|
3
3
|
forkSessionKey: string;
|
|
4
4
|
sourceEvent: { type: string; targetId: string; summary: string };
|
|
5
|
+
/** Original event bodies that the fork processed, built via `buildEventBody()`. */
|
|
6
|
+
eventBodies: string[];
|
|
5
7
|
actions: string[];
|
|
6
8
|
/** Agent's own summary of what it did (captured from the fork's last text output). */
|
|
7
9
|
agentSummary?: string;
|
|
@@ -43,6 +45,9 @@ export type ParallEvent = {
|
|
|
43
45
|
scheduledFireAt?: string;
|
|
44
46
|
/** Fire-time attached_to_uri snapshot, used for schedule events. */
|
|
45
47
|
attachedUri?: string;
|
|
48
|
+
/** Original event timestamp (e.g., message.created_at). When present,
|
|
49
|
+
* input steps use this instead of server insertion time for ordering. */
|
|
50
|
+
sentAt?: string;
|
|
46
51
|
ackSourceType?: "message" | "task_activity" | "comment" | "schedule_run";
|
|
47
52
|
ackSourceId?: string;
|
|
48
53
|
};
|