@parall/agent-core 1.28.0 → 1.29.0
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/bridge-workspace.d.ts +1 -1
- package/dist/bridge-workspace.d.ts.map +1 -1
- package/dist/bridge-workspace.js +23 -0
- package/dist/dispatch-adapter.d.ts +16 -0
- 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 +26 -7
- package/dist/gateway-base.d.ts.map +1 -1
- package/dist/gateway-base.js +20 -30
- 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 +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/bridge-workspace.ts +23 -0
- package/src/dispatch-adapter.ts +18 -0
- package/src/event-format.ts +31 -6
- package/src/gateway-base.ts +24 -30
- package/src/index.ts +1 -0
- package/src/logger.ts +9 -0
- package/src/types.ts +2 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* `@parall/agent-core` stays runtime-neutral and exports only text + pure
|
|
8
8
|
* helpers here.
|
|
9
9
|
*/
|
|
10
|
-
export declare const BRIDGE_WORKSPACE_INSTRUCTIONS = "# Agent workspace\n\nYou are an agent in Parall IM. You participate in chats, handle tasks, and interact exclusively through the Parall CLI.\n\n## Message Model\n\nIncoming events are rendered as structured `[Event: ...]` blocks.\nEach event includes `[Chat: ... (prll://cht_xxx)]` \u2014 use that chat ID (or full URI) when replying.\n\n**Your plain-text output is not delivered to anyone** \u2014 it is recorded as suppressed thinking in your session steps and discarded from the chat.\nTo say something in a chat, you **must** invoke the Parall CLI via your shell/exec tool. To stay silent, simply do not invoke it.\n\n## Parall CLI\n\nAll outbound interactions go through the `parall` CLI. Credentials are pre-injected as environment variables \u2014 no setup needed. If `parall` is not on PATH, use `npx --yes @parall/cli@latest` instead.\n\n- `parall messages send prll://cht_xxx --text \"...\"` \u2014 reply into the triggering chat\n- `parall dm prll://usr_xxx --text \"...\" [--no-reply]` \u2014 direct message another user\n- `parall tasks update prll://tsk_xxx --status in_progress` \u2014 task state\n- `parall no-reply [--reason \"...\"]` \u2014 explicitly declare this turn silent (audit signal; not required for silence, just clarifies intent)\n\nThe bridge injects Parall context via environment variables. The static credentials `PRLL_API_URL`, `PRLL_API_KEY`, and `PRLL_ORG_ID` are always set. `PRLL_CONTEXT_FILE` points to a per-session JSON file that the gateway updates each dispatch with `session_id`, `chat_id`, `trigger_message_id`, `no_reply`, and `step_id` (updated per tool call). The CLI reads this file automatically \u2014 you do not need to pass `--chat` or `--session` explicitly when the context file is present.\n\n## Attachments\n\nImage attachments are pre-downloaded under `.parall/attachments/<messageId>/`. Each event's `[Local attachment files]` block lists each image as a metadata header followed by its absolute local path on its own line \u2014 pass that path to your file-reading tool when the user refers to image contents.\n\nSupported image types: PNG, JPEG, WebP, GIF. Other attachment types (PDFs, archives, etc.) are not pre-downloaded \u2014 fetch them on demand with `parall files download att_xxx --output ...`.\n\n## Guardrails\n\n- A dispatch may coalesce multiple events. Decide per event whether to reply via `messages send` / `dm` \u2014 events you do not act on simply receive no reply.\n- If an event carries `[Hint: no_reply]`, do not send anything for that event. `no-reply` is optional and only useful as an explicit intent marker.\n- Never try to \"speak\" by typing sentences like \"No response needed\" / \"Noted\" / \"OK\" \u2014 they are discarded, so they accomplish nothing except polluting your session log.\n- Keep CLI replies concise and task-focused.\n\nSee `docs/engineering-design/agent-dm-loop-prevention.md` \u00A7 Layer 0 for why plain text is never auto-projected.\n\n## Approval Flow\n\nWhen you try an action (e.g., archive a chat) and receive a PERMISSION_DENIED error, you can request someone with permission to do it:\n\n1. The error includes a `PERMISSION_DENIED` code. For commonly approvable actions (archive, delete, restore), a `Tip:` line with an approval-request template is printed \u2014 copy it and fill in the remaining placeholders (`--chat`, `--title`, `--reason`)\n2. Request approval: `parall approvals request --action chat.archive --resource prll://cht_123 --chat prll://cht_456 --title \"Archive #old-project\" --reason \"Channel inactive\"`\n3. A card will appear in the specified chat for someone with permission to approve\n4. Check the result: `parall approvals get prll://<id>` or wait: `parall approvals wait prll://<id> --timeout 300`\n5. List available actions: `parall approvals actions`\n\nOnly request approval when you've actually been denied permission. Don't request approval preemptively.\n";
|
|
10
|
+
export declare const BRIDGE_WORKSPACE_INSTRUCTIONS = "# Agent workspace\n\nYou are an agent in Parall IM. You participate in chats, handle tasks, and interact exclusively through the Parall CLI.\n\n## Message Model\n\nIncoming events are rendered as structured `[Event: ...]` blocks.\nEach event includes `[Chat: ... (prll://cht_xxx)]` \u2014 use that chat ID (or full URI) when replying.\n\n**Your plain-text output is not delivered to anyone** \u2014 it is recorded as suppressed thinking in your session steps and discarded from the chat.\nTo say something in a chat, you **must** invoke the Parall CLI via your shell/exec tool. To stay silent, simply do not invoke it.\n\n## Parall CLI\n\nAll outbound interactions go through the `parall` CLI. Credentials are pre-injected as environment variables \u2014 no setup needed. If `parall` is not on PATH, use `npx --yes @parall/cli@latest` instead.\n\n- `parall messages send prll://cht_xxx --text \"...\"` \u2014 reply into the triggering chat\n- `parall dm prll://usr_xxx --text \"...\" [--no-reply]` \u2014 direct message another user\n- `parall tasks update prll://tsk_xxx --status in_progress` \u2014 task state\n- `parall no-reply [--reason \"...\"]` \u2014 explicitly declare this turn silent (audit signal; not required for silence, just clarifies intent)\n\nThe bridge injects Parall context via environment variables. The static credentials `PRLL_API_URL`, `PRLL_API_KEY`, and `PRLL_ORG_ID` are always set. `PRLL_CONTEXT_FILE` points to a per-session JSON file that the gateway updates each dispatch with `session_id`, `chat_id`, `trigger_message_id`, `no_reply`, and `step_id` (updated per tool call). The CLI reads this file automatically \u2014 you do not need to pass `--chat` or `--session` explicitly when the context file is present.\n\n## Attachments\n\nImage attachments are pre-downloaded under `.parall/attachments/<messageId>/`. Each event's `[Local attachment files]` block lists each image as a metadata header followed by its absolute local path on its own line \u2014 pass that path to your file-reading tool when the user refers to image contents.\n\nSupported image types: PNG, JPEG, WebP, GIF. Other attachment types (PDFs, archives, etc.) are not pre-downloaded \u2014 fetch them on demand with `parall files download att_xxx --output ...`.\n\n## Guardrails\n\n- A dispatch may coalesce multiple events. Decide per event whether to reply via `messages send` / `dm` \u2014 events you do not act on simply receive no reply.\n- If an event carries `[Hint: no_reply]`, do not send anything for that event. `no-reply` is optional and only useful as an explicit intent marker.\n- Never try to \"speak\" by typing sentences like \"No response needed\" / \"Noted\" / \"OK\" \u2014 they are discarded, so they accomplish nothing except polluting your session log.\n- Keep CLI replies concise and task-focused.\n\nSee `docs/engineering-design/agent-dm-loop-prevention.md` \u00A7 Layer 0 for why plain text is never auto-projected.\n\n## Approval Flow\n\nWhen you try an action (e.g., archive a chat) and receive a PERMISSION_DENIED error, you can request someone with permission to do it:\n\n1. The error includes a `PERMISSION_DENIED` code. For commonly approvable actions (archive, delete, restore), a `Tip:` line with an approval-request template is printed \u2014 copy it and fill in the remaining placeholders (`--chat`, `--title`, `--reason`)\n2. Request approval: `parall approvals request --action chat.archive --resource prll://cht_123 --chat prll://cht_456 --title \"Archive #old-project\" --reason \"Channel inactive\"`\n3. A card will appear in the specified chat for someone with permission to approve\n4. Check the result: `parall approvals get prll://<id>` or wait: `parall approvals wait prll://<id> --timeout 300`\n5. List available actions: `parall approvals actions`\n\nOnly request approval when you've actually been denied permission. Don't request approval preemptively.\n\n## Threads\n\nMessages may arrive with a `[Thread: prll://msg_xxx]` line in the event block, indicating the message is a reply inside a thread rooted at `msg_xxx`.\n\n### When to use threads\n- Replying to a specific message or continuing a focused sub-conversation\n- Keeping detailed discussion (logs, debugging, follow-ups) out of the main channel flow\n- When someone starts a thread with you, reply in the same thread\n\n### When NOT to use threads\n- Broadcasting status updates or announcements \u2014 use top-level messages\n- Starting a new topic \u2014 post at top level, let others thread if needed\n\n### CLI usage\n- The `msg_xxx` from the `[Thread: prll://msg_xxx]` line is the thread root ID \u2014 pass it as `--thread-root-id`\n- Reply in a thread: `parall messages send <chatId> --text \"...\" --thread-root-id <msgId>`\n- Read thread replies: `parall messages list <chatId> --thread-root-id <msgId>`\n\n### Thread etiquette\n- If your trigger message is in a thread, reply in that thread by default\n- Don't duplicate thread content to the channel unless explicitly asked\n- Keep thread replies focused on the original topic\n";
|
|
11
11
|
/** Extracts the `command` string from a shell/bash tool call's input payload. */
|
|
12
12
|
export declare function extractShellCommand(input: unknown): string | undefined;
|
|
13
13
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-workspace.d.ts","sourceRoot":"","sources":["../src/bridge-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"bridge-workspace.d.ts","sourceRoot":"","sources":["../src/bridge-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,6BAA6B,q8JAwEzC,CAAC;AAEF,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAItE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAmBzE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAKxE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAI3E"}
|
package/dist/bridge-workspace.js
CHANGED
|
@@ -56,6 +56,29 @@ When you try an action (e.g., archive a chat) and receive a PERMISSION_DENIED er
|
|
|
56
56
|
5. List available actions: \`parall approvals actions\`
|
|
57
57
|
|
|
58
58
|
Only request approval when you've actually been denied permission. Don't request approval preemptively.
|
|
59
|
+
|
|
60
|
+
## Threads
|
|
61
|
+
|
|
62
|
+
Messages may arrive with a \`[Thread: prll://msg_xxx]\` line in the event block, indicating the message is a reply inside a thread rooted at \`msg_xxx\`.
|
|
63
|
+
|
|
64
|
+
### When to use threads
|
|
65
|
+
- Replying to a specific message or continuing a focused sub-conversation
|
|
66
|
+
- Keeping detailed discussion (logs, debugging, follow-ups) out of the main channel flow
|
|
67
|
+
- When someone starts a thread with you, reply in the same thread
|
|
68
|
+
|
|
69
|
+
### When NOT to use threads
|
|
70
|
+
- Broadcasting status updates or announcements — use top-level messages
|
|
71
|
+
- Starting a new topic — post at top level, let others thread if needed
|
|
72
|
+
|
|
73
|
+
### CLI usage
|
|
74
|
+
- The \`msg_xxx\` from the \`[Thread: prll://msg_xxx]\` line is the thread root ID — pass it as \`--thread-root-id\`
|
|
75
|
+
- Reply in a thread: \`parall messages send <chatId> --text "..." --thread-root-id <msgId>\`
|
|
76
|
+
- Read thread replies: \`parall messages list <chatId> --thread-root-id <msgId>\`
|
|
77
|
+
|
|
78
|
+
### Thread etiquette
|
|
79
|
+
- If your trigger message is in a thread, reply in that thread by default
|
|
80
|
+
- Don't duplicate thread content to the channel unless explicitly asked
|
|
81
|
+
- Keep thread replies focused on the original topic
|
|
59
82
|
`;
|
|
60
83
|
/** Extracts the `command` string from a shell/bash tool call's input payload. */
|
|
61
84
|
export function extractShellCommand(input) {
|
|
@@ -79,6 +79,22 @@ export type CleanupForkOpts = {
|
|
|
79
79
|
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
|
+
/**
|
|
83
|
+
* Inject a user message into the running subprocess's stdin mid-turn so the
|
|
84
|
+
* runtime reads it between tool calls and steers immediately, rather than
|
|
85
|
+
* waiting for the current turn to complete.
|
|
86
|
+
*
|
|
87
|
+
* Returns true if the message was successfully written to stdin; false if no
|
|
88
|
+
* live process exists for the session (caller should fall back to mainBuffer).
|
|
89
|
+
*
|
|
90
|
+
* The gateway still pushes the event to mainBuffer after a successful
|
|
91
|
+
* injection — drainMainBuffer will call dispatch() for it, and dispatch()
|
|
92
|
+
* must detect the pending injection (skip the stdin write) and only consume
|
|
93
|
+
* the parser output that Claude produced in response.
|
|
94
|
+
*/
|
|
95
|
+
enqueueDuringDispatch?(sessionKey: string, body: string): boolean;
|
|
96
|
+
/** True if enqueueDuringDispatch was called and the injections have not yet been consumed by dispatch(). */
|
|
97
|
+
hasPendingInjections?(sessionKey: string): boolean;
|
|
82
98
|
/** Fork the current runtime session for concurrent handling. Return null to buffer on main. */
|
|
83
99
|
forkSession?(opts: ForkOpts): Promise<ForkSessionHandle | null> | ForkSessionHandle | null;
|
|
84
100
|
/** Clean up a fork session created by forkSession(). */
|
|
@@ -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":"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"}
|
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;AAED,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
|
@@ -63,7 +63,24 @@ export function buildEventBody(event) {
|
|
|
63
63
|
lines.push(`[Assigned by: ${event.senderName} (prll://${event.senderId})]`);
|
|
64
64
|
lines.push("", event.body);
|
|
65
65
|
}
|
|
66
|
-
return lines.join("\n");
|
|
66
|
+
return lines.join("\n") + buildSendMessageHint(event);
|
|
67
|
+
}
|
|
68
|
+
export function buildEventBodyForForkResult(event) {
|
|
69
|
+
return buildEventBody(event).replace(/\n<system-reminder>[\s\S]*<\/system-reminder>$/, "");
|
|
70
|
+
}
|
|
71
|
+
function buildSendMessageHint(event) {
|
|
72
|
+
if (event.noReply)
|
|
73
|
+
return "";
|
|
74
|
+
if (event.targetId.startsWith("cht_")) {
|
|
75
|
+
return `\n<system-reminder>To reply, run: \`parall messages send prll://${event.targetId} --text "..."\` — your plain text output is not delivered to the chat.</system-reminder>`;
|
|
76
|
+
}
|
|
77
|
+
if (event.targetId.startsWith("tsk_")) {
|
|
78
|
+
return `\n<system-reminder>To respond, use the CLI: \`parall tasks update\` / \`parall tasks comments add\`. To message someone, use \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
79
|
+
}
|
|
80
|
+
if (event.targetId.startsWith("sch_")) {
|
|
81
|
+
return `\n<system-reminder>To communicate, use the CLI: \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
82
|
+
}
|
|
83
|
+
return "";
|
|
67
84
|
}
|
|
68
85
|
export function buildForkScopePrefix(event) {
|
|
69
86
|
const targetLabel = event.targetName
|
|
@@ -75,14 +92,16 @@ export function buildForkResultPrefix(results) {
|
|
|
75
92
|
if (!results.length)
|
|
76
93
|
return "";
|
|
77
94
|
const blocks = results.map((result) => {
|
|
78
|
-
const lines = [
|
|
79
|
-
|
|
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."}]`);
|
|
80
101
|
if (result.actions.length)
|
|
81
|
-
lines.push(`[
|
|
82
|
-
if (result.agentSummary)
|
|
83
|
-
lines.push(`[Summary: ${sanitizeMeta(result.agentSummary)}]`);
|
|
102
|
+
lines.push(`[Fork actions: ${result.actions.join("; ")}]`);
|
|
84
103
|
if (result.historyPath)
|
|
85
|
-
lines.push(`[
|
|
104
|
+
lines.push(`[Fork history: ${result.historyPath}]`);
|
|
86
105
|
return lines.join("\n");
|
|
87
106
|
});
|
|
88
107
|
return blocks.join("\n\n") + "\n\n---\n\n";
|
|
@@ -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
|
|
@@ -554,7 +553,8 @@ export class ParallAgentGateway {
|
|
|
554
553
|
continue;
|
|
555
554
|
}
|
|
556
555
|
if (!binding) {
|
|
557
|
-
|
|
556
|
+
const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
|
|
557
|
+
throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
|
|
558
558
|
}
|
|
559
559
|
if (!triggerMessageSet) {
|
|
560
560
|
triggerMessageSet = true;
|
|
@@ -572,9 +572,18 @@ export class ParallAgentGateway {
|
|
|
572
572
|
}
|
|
573
573
|
await this.createRuntimeStep(binding.agentSessionId, event, runtimeEvent, stepIdFilePath, contextFilePath);
|
|
574
574
|
}
|
|
575
|
+
if (!binding) {
|
|
576
|
+
binding = this.sessionBindings.get(sessionKey);
|
|
577
|
+
}
|
|
575
578
|
if (!binding) {
|
|
576
579
|
throw new Error("runtime completed without runtime_session");
|
|
577
580
|
}
|
|
581
|
+
if (!inputStepsCreated) {
|
|
582
|
+
if (earlierEvents.length > 0) {
|
|
583
|
+
await this.createInputStepsForEarlierEvents(binding.agentSessionId, earlierEvents);
|
|
584
|
+
}
|
|
585
|
+
await this.createInputStep(binding.agentSessionId, event);
|
|
586
|
+
}
|
|
578
587
|
}
|
|
579
588
|
catch (err) {
|
|
580
589
|
if (binding) {
|
|
@@ -676,6 +685,7 @@ export class ParallAgentGateway {
|
|
|
676
685
|
? `${first.type} from ${first.senderName} in ${first.targetName ?? fork.targetId}`
|
|
677
686
|
: `${fork.processedEvents.length} events in ${first.targetName ?? fork.targetId}`,
|
|
678
687
|
},
|
|
688
|
+
eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
|
|
679
689
|
actions: [],
|
|
680
690
|
agentSummary,
|
|
681
691
|
historyPath,
|
|
@@ -714,7 +724,7 @@ export class ParallAgentGateway {
|
|
|
714
724
|
return;
|
|
715
725
|
this.draining = true;
|
|
716
726
|
try {
|
|
717
|
-
while (this.dispatchState.mainBuffer.length > 0
|
|
727
|
+
while (this.dispatchState.mainBuffer.length > 0) {
|
|
718
728
|
// Early shutdown guard — same reasoning as runForkDrainLoop: stop
|
|
719
729
|
// before any input AgentSteps are persisted, leaving the buffer +
|
|
720
730
|
// pendingForkResults intact so dispatch catch-up on the replacement
|
|
@@ -723,31 +733,6 @@ export class ParallAgentGateway {
|
|
|
723
733
|
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`);
|
|
724
734
|
break;
|
|
725
735
|
}
|
|
726
|
-
if (this.dispatchState.mainBuffer.length === 0 && this.dispatchState.pendingForkResults.length > 0) {
|
|
727
|
-
const pending = this.dispatchState.pendingForkResults.splice(0);
|
|
728
|
-
const forkPrefix = buildForkResultPrefix(pending);
|
|
729
|
-
const syntheticEvent = {
|
|
730
|
-
type: "message",
|
|
731
|
-
targetId: "_orchestrator",
|
|
732
|
-
targetType: "system",
|
|
733
|
-
senderId: "system",
|
|
734
|
-
senderName: "system",
|
|
735
|
-
messageId: `synthetic-${this.opts.accountId}-${randomUUID()}`,
|
|
736
|
-
body: "[Orchestrator: fork session(s) completed — review results above]",
|
|
737
|
-
};
|
|
738
|
-
this.dispatchState.mainCurrentTargetId = undefined;
|
|
739
|
-
this.dispatchState.mainPreDispatchBranchPoint =
|
|
740
|
-
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
741
|
-
const dispatched = await this.runDispatch(syntheticEvent, this.opts.runtimeKey, forkPrefix + buildEventBody(syntheticEvent));
|
|
742
|
-
if (!dispatched) {
|
|
743
|
-
// Shutdown: put the fork results back at the head so the synthetic
|
|
744
|
-
// event is regenerated on the replacement pod. Synthetic events are
|
|
745
|
-
// not ack'd, so this is the only state we need to preserve.
|
|
746
|
-
this.dispatchState.pendingForkResults.unshift(...pending);
|
|
747
|
-
break;
|
|
748
|
-
}
|
|
749
|
-
continue;
|
|
750
|
-
}
|
|
751
736
|
const targetId = this.dispatchState.mainBuffer[0].targetId;
|
|
752
737
|
const events = [];
|
|
753
738
|
while (this.dispatchState.mainBuffer[0]?.targetId === targetId) {
|
|
@@ -755,7 +740,8 @@ export class ParallAgentGateway {
|
|
|
755
740
|
}
|
|
756
741
|
const event = events[events.length - 1];
|
|
757
742
|
const earlier = events.slice(0, -1);
|
|
758
|
-
const
|
|
743
|
+
const skipForkSplice = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
|
|
744
|
+
const pendingFork = skipForkSplice ? [] : this.dispatchState.pendingForkResults.splice(0);
|
|
759
745
|
const forkPrefix = buildForkResultPrefix(pendingFork);
|
|
760
746
|
this.dispatchState.mainCurrentTargetId = event.targetId;
|
|
761
747
|
this.dispatchState.mainPreDispatchBranchPoint =
|
|
@@ -817,6 +803,10 @@ export class ParallAgentGateway {
|
|
|
817
803
|
if (this.shuttingDown) {
|
|
818
804
|
return false;
|
|
819
805
|
}
|
|
806
|
+
if (this.dispatchState.mainCurrentTargetId === event.targetId &&
|
|
807
|
+
this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))) {
|
|
808
|
+
this.opts.log?.info(`parall[${this.opts.accountId}]: steer injected to stdin for ${event.messageId} (will drain for bookkeeping)`);
|
|
809
|
+
}
|
|
820
810
|
this.dispatchState.mainBuffer.push(event);
|
|
821
811
|
return false;
|
|
822
812
|
}
|
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;
|
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,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.0",
|
|
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.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.0.0",
|
package/src/bridge-workspace.ts
CHANGED
|
@@ -57,6 +57,29 @@ When you try an action (e.g., archive a chat) and receive a PERMISSION_DENIED er
|
|
|
57
57
|
5. List available actions: \`parall approvals actions\`
|
|
58
58
|
|
|
59
59
|
Only request approval when you've actually been denied permission. Don't request approval preemptively.
|
|
60
|
+
|
|
61
|
+
## Threads
|
|
62
|
+
|
|
63
|
+
Messages may arrive with a \`[Thread: prll://msg_xxx]\` line in the event block, indicating the message is a reply inside a thread rooted at \`msg_xxx\`.
|
|
64
|
+
|
|
65
|
+
### When to use threads
|
|
66
|
+
- Replying to a specific message or continuing a focused sub-conversation
|
|
67
|
+
- Keeping detailed discussion (logs, debugging, follow-ups) out of the main channel flow
|
|
68
|
+
- When someone starts a thread with you, reply in the same thread
|
|
69
|
+
|
|
70
|
+
### When NOT to use threads
|
|
71
|
+
- Broadcasting status updates or announcements — use top-level messages
|
|
72
|
+
- Starting a new topic — post at top level, let others thread if needed
|
|
73
|
+
|
|
74
|
+
### CLI usage
|
|
75
|
+
- The \`msg_xxx\` from the \`[Thread: prll://msg_xxx]\` line is the thread root ID — pass it as \`--thread-root-id\`
|
|
76
|
+
- Reply in a thread: \`parall messages send <chatId> --text "..." --thread-root-id <msgId>\`
|
|
77
|
+
- Read thread replies: \`parall messages list <chatId> --thread-root-id <msgId>\`
|
|
78
|
+
|
|
79
|
+
### Thread etiquette
|
|
80
|
+
- If your trigger message is in a thread, reply in that thread by default
|
|
81
|
+
- Don't duplicate thread content to the channel unless explicitly asked
|
|
82
|
+
- Keep thread replies focused on the original topic
|
|
60
83
|
`;
|
|
61
84
|
|
|
62
85
|
/** Extracts the `command` string from a shell/bash tool call's input payload. */
|
package/src/dispatch-adapter.ts
CHANGED
|
@@ -67,6 +67,24 @@ export interface DispatchAdapter {
|
|
|
67
67
|
/** Dispatch a Parall event to the runtime and emit normalized runtime events. */
|
|
68
68
|
dispatch(opts: DispatchOpts): AsyncIterable<RuntimeEvent>;
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Inject a user message into the running subprocess's stdin mid-turn so the
|
|
72
|
+
* runtime reads it between tool calls and steers immediately, rather than
|
|
73
|
+
* waiting for the current turn to complete.
|
|
74
|
+
*
|
|
75
|
+
* Returns true if the message was successfully written to stdin; false if no
|
|
76
|
+
* live process exists for the session (caller should fall back to mainBuffer).
|
|
77
|
+
*
|
|
78
|
+
* The gateway still pushes the event to mainBuffer after a successful
|
|
79
|
+
* injection — drainMainBuffer will call dispatch() for it, and dispatch()
|
|
80
|
+
* must detect the pending injection (skip the stdin write) and only consume
|
|
81
|
+
* the parser output that Claude produced in response.
|
|
82
|
+
*/
|
|
83
|
+
enqueueDuringDispatch?(sessionKey: string, body: string): boolean;
|
|
84
|
+
|
|
85
|
+
/** True if enqueueDuringDispatch was called and the injections have not yet been consumed by dispatch(). */
|
|
86
|
+
hasPendingInjections?(sessionKey: string): boolean;
|
|
87
|
+
|
|
70
88
|
/** Fork the current runtime session for concurrent handling. Return null to buffer on main. */
|
|
71
89
|
forkSession?(opts: ForkOpts): Promise<ForkSessionHandle | null> | ForkSessionHandle | null;
|
|
72
90
|
|
package/src/event-format.ts
CHANGED
|
@@ -57,7 +57,29 @@ export function buildEventBody(event: ParallEvent): string {
|
|
|
57
57
|
lines.push(`[Assigned by: ${event.senderName} (prll://${event.senderId})]`);
|
|
58
58
|
lines.push("", event.body);
|
|
59
59
|
}
|
|
60
|
-
return lines.join("\n");
|
|
60
|
+
return lines.join("\n") + buildSendMessageHint(event);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function buildEventBodyForForkResult(event: ParallEvent): string {
|
|
64
|
+
return buildEventBody(event).replace(/\n<system-reminder>[\s\S]*<\/system-reminder>$/, "");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function buildSendMessageHint(event: ParallEvent): string {
|
|
68
|
+
if (event.noReply) return "";
|
|
69
|
+
|
|
70
|
+
if (event.targetId.startsWith("cht_")) {
|
|
71
|
+
return `\n<system-reminder>To reply, run: \`parall messages send prll://${event.targetId} --text "..."\` — your plain text output is not delivered to the chat.</system-reminder>`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (event.targetId.startsWith("tsk_")) {
|
|
75
|
+
return `\n<system-reminder>To respond, use the CLI: \`parall tasks update\` / \`parall tasks comments add\`. To message someone, use \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (event.targetId.startsWith("sch_")) {
|
|
79
|
+
return `\n<system-reminder>To communicate, use the CLI: \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return "";
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
export function buildForkScopePrefix(event: ParallEvent): string {
|
|
@@ -70,11 +92,14 @@ export function buildForkScopePrefix(event: ParallEvent): string {
|
|
|
70
92
|
export function buildForkResultPrefix(results: ForkResult[]): string {
|
|
71
93
|
if (!results.length) return "";
|
|
72
94
|
const blocks = results.map((result) => {
|
|
73
|
-
const lines = [
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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}]`);
|
|
78
103
|
return lines.join("\n");
|
|
79
104
|
});
|
|
80
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,
|
|
@@ -693,7 +692,8 @@ export class ParallAgentGateway {
|
|
|
693
692
|
}
|
|
694
693
|
|
|
695
694
|
if (!binding) {
|
|
696
|
-
|
|
695
|
+
const detail = runtimeEvent.type === "error" ? `: ${runtimeEvent.message}` : "";
|
|
696
|
+
throw new Error(`runtime emitted ${runtimeEvent.type} before runtime_session${detail}`);
|
|
697
697
|
}
|
|
698
698
|
if (!triggerMessageSet) {
|
|
699
699
|
triggerMessageSet = true;
|
|
@@ -714,9 +714,18 @@ export class ParallAgentGateway {
|
|
|
714
714
|
}
|
|
715
715
|
await this.createRuntimeStep(binding.agentSessionId, event, runtimeEvent, stepIdFilePath, contextFilePath);
|
|
716
716
|
}
|
|
717
|
+
if (!binding) {
|
|
718
|
+
binding = this.sessionBindings.get(sessionKey);
|
|
719
|
+
}
|
|
717
720
|
if (!binding) {
|
|
718
721
|
throw new Error("runtime completed without runtime_session");
|
|
719
722
|
}
|
|
723
|
+
if (!inputStepsCreated) {
|
|
724
|
+
if (earlierEvents.length > 0) {
|
|
725
|
+
await this.createInputStepsForEarlierEvents(binding.agentSessionId, earlierEvents);
|
|
726
|
+
}
|
|
727
|
+
await this.createInputStep(binding.agentSessionId, event);
|
|
728
|
+
}
|
|
720
729
|
} catch (err) {
|
|
721
730
|
if (binding) {
|
|
722
731
|
await this.createRuntimeStep(binding.agentSessionId, event, {
|
|
@@ -814,6 +823,7 @@ export class ParallAgentGateway {
|
|
|
814
823
|
? `${first.type} from ${first.senderName} in ${first.targetName ?? fork.targetId}`
|
|
815
824
|
: `${fork.processedEvents.length} events in ${first.targetName ?? fork.targetId}`,
|
|
816
825
|
},
|
|
826
|
+
eventBodies: fork.processedEvents.map((e) => buildEventBodyForForkResult(e)),
|
|
817
827
|
actions: [],
|
|
818
828
|
agentSummary,
|
|
819
829
|
historyPath,
|
|
@@ -855,7 +865,7 @@ export class ParallAgentGateway {
|
|
|
855
865
|
if (this.draining) return;
|
|
856
866
|
this.draining = true;
|
|
857
867
|
try {
|
|
858
|
-
while (this.dispatchState.mainBuffer.length > 0
|
|
868
|
+
while (this.dispatchState.mainBuffer.length > 0) {
|
|
859
869
|
// Early shutdown guard — same reasoning as runForkDrainLoop: stop
|
|
860
870
|
// before any input AgentSteps are persisted, leaving the buffer +
|
|
861
871
|
// pendingForkResults intact so dispatch catch-up on the replacement
|
|
@@ -866,31 +876,6 @@ export class ParallAgentGateway {
|
|
|
866
876
|
);
|
|
867
877
|
break;
|
|
868
878
|
}
|
|
869
|
-
if (this.dispatchState.mainBuffer.length === 0 && this.dispatchState.pendingForkResults.length > 0) {
|
|
870
|
-
const pending = this.dispatchState.pendingForkResults.splice(0);
|
|
871
|
-
const forkPrefix = buildForkResultPrefix(pending);
|
|
872
|
-
const syntheticEvent: ParallEvent = {
|
|
873
|
-
type: "message",
|
|
874
|
-
targetId: "_orchestrator",
|
|
875
|
-
targetType: "system",
|
|
876
|
-
senderId: "system",
|
|
877
|
-
senderName: "system",
|
|
878
|
-
messageId: `synthetic-${this.opts.accountId}-${randomUUID()}`,
|
|
879
|
-
body: "[Orchestrator: fork session(s) completed — review results above]",
|
|
880
|
-
};
|
|
881
|
-
this.dispatchState.mainCurrentTargetId = undefined;
|
|
882
|
-
this.dispatchState.mainPreDispatchBranchPoint =
|
|
883
|
-
this.opts.dispatchAdapter.getBranchPoint?.(this.opts.runtimeKey);
|
|
884
|
-
const dispatched = await this.runDispatch(syntheticEvent, this.opts.runtimeKey, forkPrefix + buildEventBody(syntheticEvent));
|
|
885
|
-
if (!dispatched) {
|
|
886
|
-
// Shutdown: put the fork results back at the head so the synthetic
|
|
887
|
-
// event is regenerated on the replacement pod. Synthetic events are
|
|
888
|
-
// not ack'd, so this is the only state we need to preserve.
|
|
889
|
-
this.dispatchState.pendingForkResults.unshift(...pending);
|
|
890
|
-
break;
|
|
891
|
-
}
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
879
|
|
|
895
880
|
const targetId = this.dispatchState.mainBuffer[0].targetId;
|
|
896
881
|
const events: ParallEvent[] = [];
|
|
@@ -900,7 +885,8 @@ export class ParallAgentGateway {
|
|
|
900
885
|
|
|
901
886
|
const event = events[events.length - 1];
|
|
902
887
|
const earlier = events.slice(0, -1);
|
|
903
|
-
const
|
|
888
|
+
const skipForkSplice = this.opts.dispatchAdapter.hasPendingInjections?.(this.opts.runtimeKey) ?? false;
|
|
889
|
+
const pendingFork = skipForkSplice ? [] : this.dispatchState.pendingForkResults.splice(0);
|
|
904
890
|
const forkPrefix = buildForkResultPrefix(pendingFork);
|
|
905
891
|
this.dispatchState.mainCurrentTargetId = event.targetId;
|
|
906
892
|
this.dispatchState.mainPreDispatchBranchPoint =
|
|
@@ -963,6 +949,14 @@ export class ParallAgentGateway {
|
|
|
963
949
|
if (this.shuttingDown) {
|
|
964
950
|
return false;
|
|
965
951
|
}
|
|
952
|
+
if (
|
|
953
|
+
this.dispatchState.mainCurrentTargetId === event.targetId &&
|
|
954
|
+
this.opts.dispatchAdapter.enqueueDuringDispatch?.(this.opts.runtimeKey, buildEventBody(event))
|
|
955
|
+
) {
|
|
956
|
+
this.opts.log?.info(
|
|
957
|
+
`parall[${this.opts.accountId}]: steer injected to stdin for ${event.messageId} (will drain for bookkeeping)`,
|
|
958
|
+
);
|
|
959
|
+
}
|
|
966
960
|
this.dispatchState.mainBuffer.push(event);
|
|
967
961
|
return false;
|
|
968
962
|
}
|
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;
|