@parall/parel-channel 1.57.1 → 1.58.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/channel-prompt.d.ts +5 -1
- package/dist/channel-prompt.d.ts.map +1 -1
- package/dist/channel-prompt.js +37 -8
- package/dist/typed-dispatch.js +10 -1
- package/package.json +1 -1
- package/src/channel-prompt.ts +45 -8
- package/src/typed-dispatch.ts +11 -1
package/dist/channel-prompt.d.ts
CHANGED
|
@@ -36,8 +36,12 @@ export interface ChatPromptArgs {
|
|
|
36
36
|
chatId: string;
|
|
37
37
|
/** Display name of the chat; undefined when unresolved (best-effort). */
|
|
38
38
|
chatName?: string;
|
|
39
|
-
/** Sender user id (usr_)
|
|
39
|
+
/** Sender user id (usr_). */
|
|
40
40
|
senderId?: string;
|
|
41
|
+
/** Sender display name; rendered before the id when resolved (best-effort). */
|
|
42
|
+
senderName?: string;
|
|
43
|
+
/** Chat shape (direct/group); the type segment is omitted when unresolved. */
|
|
44
|
+
chatType?: string;
|
|
41
45
|
/**
|
|
42
46
|
* The inbound message id (msg_); anchors the forwarded-message hint's
|
|
43
47
|
* explicit --from so coalesced turns don't lean on the single trigger id.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-prompt.d.ts","sourceRoot":"","sources":["../src/channel-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA+BH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"channel-prompt.d.ts","sourceRoot":"","sources":["../src/channel-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA+BH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,8FAA8F;IAC9F,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,CAwC5D;AAgBD,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CA2BlE"}
|
package/dist/channel-prompt.js
CHANGED
|
@@ -73,16 +73,31 @@ function attachmentLines(attachments) {
|
|
|
73
73
|
* not re-created here.
|
|
74
74
|
*/
|
|
75
75
|
export function buildChatPrompt(args) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
// agent-core's event-format.ts message branch is the SSOT for this frame:
|
|
77
|
+
// same lines, same order, same send-hint. The only sanctioned deltas are
|
|
78
|
+
// absent-field fallbacks (no chat name → bare URI, no sender name → bare
|
|
79
|
+
// id, no chat type → segment omitted) — agent-core's host always has them.
|
|
80
|
+
const lines = [`[Event: message.new]`];
|
|
81
|
+
const chatUri = `prll://${args.chatId}`;
|
|
82
|
+
const chatLabel = args.chatName ? `"${sanitizeMeta(args.chatName)}" (${chatUri})` : chatUri;
|
|
83
|
+
const typeSeg = args.chatType ? ` | type: ${sanitizeMeta(args.chatType)}` : '';
|
|
84
|
+
lines.push(`[Chat: ${chatLabel}${typeSeg}]`);
|
|
85
|
+
if (args.senderId) {
|
|
86
|
+
lines.push(args.senderName
|
|
87
|
+
? `[From: ${sanitizeMeta(args.senderName)} (prll://${args.senderId})]`
|
|
88
|
+
: `[From: prll://${args.senderId}]`);
|
|
89
|
+
}
|
|
90
|
+
if (args.messageId)
|
|
91
|
+
lines.push(`[Message ID: prll://${args.messageId}]`);
|
|
82
92
|
if (args.threadRootId)
|
|
83
|
-
lines.push(`[Thread:
|
|
93
|
+
lines.push(`[Thread: prll://${sanitizeMeta(args.threadRootId)}]`);
|
|
84
94
|
if (args.deliveryReason)
|
|
85
95
|
lines.push(`[Delivery: ${sanitizeMeta(args.deliveryReason)}]`);
|
|
96
|
+
if (args.deliveryReason === 'watcher' && args.threadRootId) {
|
|
97
|
+
// agent-core's threadWatcherHint, verbatim — the cooperative nudge under
|
|
98
|
+
// the server's agent-loop ceiling (agent-dm-loop-prevention.md Layer 4).
|
|
99
|
+
lines.push(`[Hint: watcher — you were not addressed in this reply. Reply only if you add something new; otherwise run \`parall no-reply\`. If this thread is not relevant to you, or you have nothing more to contribute, run \`parall messages unwatch prll://${sanitizeMeta(args.threadRootId)}\` so later replies stop waking you.]`);
|
|
100
|
+
}
|
|
86
101
|
if (args.noReply)
|
|
87
102
|
lines.push(`[Hint: no_reply]`);
|
|
88
103
|
if (isForwardedMessageBody(args.text)) {
|
|
@@ -94,7 +109,21 @@ export function buildChatPrompt(args) {
|
|
|
94
109
|
}
|
|
95
110
|
lines.push(...attachmentLines(args.attachments));
|
|
96
111
|
lines.push('', args.text);
|
|
97
|
-
return lines.join('\n');
|
|
112
|
+
return lines.join('\n') + chatSendHint(args);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* agent-core's buildSendMessageHint chat branch, verbatim: every chat event
|
|
116
|
+
* ends with the concrete send command. The standing system prompt teaches the
|
|
117
|
+
* CLI-only reply contract too, but a per-event reminder is what the standard
|
|
118
|
+
* runtimes ship — and weak models demonstrably drop the send step without it.
|
|
119
|
+
*/
|
|
120
|
+
function chatSendHint(args) {
|
|
121
|
+
if (args.noReply)
|
|
122
|
+
return '';
|
|
123
|
+
if (args.threadRootId) {
|
|
124
|
+
return `\n<system-reminder>To reply in this thread, run \`parall messages send prll://${args.chatId} --thread-root-id ${sanitizeMeta(args.threadRootId)} --text-file - <<'EOF'\` … \`EOF\` — the quoted heredoc keeps \`$\`, backticks and apostrophes literal (plain \`--text "$1,000"\` sends \`,000\`). Your plain text output is not delivered to the chat.</system-reminder>`;
|
|
125
|
+
}
|
|
126
|
+
return `\n<system-reminder>To reply, run \`parall messages send prll://${args.chatId} --text-file - <<'EOF'\` … \`EOF\` — the quoted heredoc keeps \`$\`, backticks and apostrophes literal (plain \`--text "$1,000"\` sends \`,000\`). Your plain text output is not delivered to the chat.</system-reminder>`;
|
|
98
127
|
}
|
|
99
128
|
export function buildChannelPrompt(args) {
|
|
100
129
|
const providerLabel = sanitizeMeta(args.provider ?? 'external IM');
|
package/dist/typed-dispatch.js
CHANGED
|
@@ -342,7 +342,16 @@ async function planApprovalDecided(ctx, approvalId, chatId, actor) {
|
|
|
342
342
|
if (!approval?.id)
|
|
343
343
|
return STALE;
|
|
344
344
|
const statusLabel = approval.status === 'approved' ? 'Approved' : 'Rejected';
|
|
345
|
-
|
|
345
|
+
// A failed execution names its cause on the same line — the agent must not
|
|
346
|
+
// need a second read to tell a version conflict from anything else.
|
|
347
|
+
// agent-core's formatApprovalExecution and the server's Go materializer
|
|
348
|
+
// render the identical suffix; keep the three in sync.
|
|
349
|
+
const execError = approval.execution_error
|
|
350
|
+
? ` | error: ${sanitizeMeta(approval.execution_error)}`
|
|
351
|
+
: '';
|
|
352
|
+
const execInfo = approval.execution_status
|
|
353
|
+
? ` | execution: ${approval.execution_status}${execError}`
|
|
354
|
+
: '';
|
|
346
355
|
const resolvedChat = chatId ?? approval.chat_id;
|
|
347
356
|
const lines = [`[Event: approval.decided]`];
|
|
348
357
|
lines.push(`[Approval: prll://${approval.id}]`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parel-channel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.58.0",
|
|
4
4
|
"description": "Parall channel plugin for the parel runtime — lets a parel agent treat Parall as a managed_ws channel (receive dispatches, reply via the Parall API)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/src/channel-prompt.ts
CHANGED
|
@@ -67,8 +67,12 @@ export interface ChatPromptArgs {
|
|
|
67
67
|
chatId: string;
|
|
68
68
|
/** Display name of the chat; undefined when unresolved (best-effort). */
|
|
69
69
|
chatName?: string;
|
|
70
|
-
/** Sender user id (usr_)
|
|
70
|
+
/** Sender user id (usr_). */
|
|
71
71
|
senderId?: string;
|
|
72
|
+
/** Sender display name; rendered before the id when resolved (best-effort). */
|
|
73
|
+
senderName?: string;
|
|
74
|
+
/** Chat shape (direct/group); the type segment is omitted when unresolved. */
|
|
75
|
+
chatType?: string;
|
|
72
76
|
/**
|
|
73
77
|
* The inbound message id (msg_); anchors the forwarded-message hint's
|
|
74
78
|
* explicit --from so coalesced turns don't lean on the single trigger id.
|
|
@@ -113,13 +117,32 @@ function attachmentLines(attachments: PromptAttachment[] | undefined): string[]
|
|
|
113
117
|
* not re-created here.
|
|
114
118
|
*/
|
|
115
119
|
export function buildChatPrompt(args: ChatPromptArgs): string {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
// agent-core's event-format.ts message branch is the SSOT for this frame:
|
|
121
|
+
// same lines, same order, same send-hint. The only sanctioned deltas are
|
|
122
|
+
// absent-field fallbacks (no chat name → bare URI, no sender name → bare
|
|
123
|
+
// id, no chat type → segment omitted) — agent-core's host always has them.
|
|
124
|
+
const lines = [`[Event: message.new]`];
|
|
125
|
+
const chatUri = `prll://${args.chatId}`;
|
|
126
|
+
const chatLabel = args.chatName ? `"${sanitizeMeta(args.chatName)}" (${chatUri})` : chatUri;
|
|
127
|
+
const typeSeg = args.chatType ? ` | type: ${sanitizeMeta(args.chatType)}` : '';
|
|
128
|
+
lines.push(`[Chat: ${chatLabel}${typeSeg}]`);
|
|
129
|
+
if (args.senderId) {
|
|
130
|
+
lines.push(
|
|
131
|
+
args.senderName
|
|
132
|
+
? `[From: ${sanitizeMeta(args.senderName)} (prll://${args.senderId})]`
|
|
133
|
+
: `[From: prll://${args.senderId}]`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
if (args.messageId) lines.push(`[Message ID: prll://${args.messageId}]`);
|
|
137
|
+
if (args.threadRootId) lines.push(`[Thread: prll://${sanitizeMeta(args.threadRootId)}]`);
|
|
122
138
|
if (args.deliveryReason) lines.push(`[Delivery: ${sanitizeMeta(args.deliveryReason)}]`);
|
|
139
|
+
if (args.deliveryReason === 'watcher' && args.threadRootId) {
|
|
140
|
+
// agent-core's threadWatcherHint, verbatim — the cooperative nudge under
|
|
141
|
+
// the server's agent-loop ceiling (agent-dm-loop-prevention.md Layer 4).
|
|
142
|
+
lines.push(
|
|
143
|
+
`[Hint: watcher — you were not addressed in this reply. Reply only if you add something new; otherwise run \`parall no-reply\`. If this thread is not relevant to you, or you have nothing more to contribute, run \`parall messages unwatch prll://${sanitizeMeta(args.threadRootId)}\` so later replies stop waking you.]`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
123
146
|
if (args.noReply) lines.push(`[Hint: no_reply]`);
|
|
124
147
|
if (isForwardedMessageBody(args.text)) {
|
|
125
148
|
// Embed the concrete --from anchor: parel snapshots one invocation
|
|
@@ -132,7 +155,21 @@ export function buildChatPrompt(args: ChatPromptArgs): string {
|
|
|
132
155
|
}
|
|
133
156
|
lines.push(...attachmentLines(args.attachments));
|
|
134
157
|
lines.push('', args.text);
|
|
135
|
-
return lines.join('\n');
|
|
158
|
+
return lines.join('\n') + chatSendHint(args);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* agent-core's buildSendMessageHint chat branch, verbatim: every chat event
|
|
163
|
+
* ends with the concrete send command. The standing system prompt teaches the
|
|
164
|
+
* CLI-only reply contract too, but a per-event reminder is what the standard
|
|
165
|
+
* runtimes ship — and weak models demonstrably drop the send step without it.
|
|
166
|
+
*/
|
|
167
|
+
function chatSendHint(args: ChatPromptArgs): string {
|
|
168
|
+
if (args.noReply) return '';
|
|
169
|
+
if (args.threadRootId) {
|
|
170
|
+
return `\n<system-reminder>To reply in this thread, run \`parall messages send prll://${args.chatId} --thread-root-id ${sanitizeMeta(args.threadRootId)} --text-file - <<'EOF'\` … \`EOF\` — the quoted heredoc keeps \`$\`, backticks and apostrophes literal (plain \`--text "$1,000"\` sends \`,000\`). Your plain text output is not delivered to the chat.</system-reminder>`;
|
|
171
|
+
}
|
|
172
|
+
return `\n<system-reminder>To reply, run \`parall messages send prll://${args.chatId} --text-file - <<'EOF'\` … \`EOF\` — the quoted heredoc keeps \`$\`, backticks and apostrophes literal (plain \`--text "$1,000"\` sends \`,000\`). Your plain text output is not delivered to the chat.</system-reminder>`;
|
|
136
173
|
}
|
|
137
174
|
|
|
138
175
|
export interface ChannelPromptArgs {
|
package/src/typed-dispatch.ts
CHANGED
|
@@ -508,6 +508,7 @@ interface ApprovalRow {
|
|
|
508
508
|
title?: string;
|
|
509
509
|
status?: string;
|
|
510
510
|
execution_status?: string;
|
|
511
|
+
execution_error?: string | null;
|
|
511
512
|
chat_id?: string;
|
|
512
513
|
decided_by?: string;
|
|
513
514
|
decision_reason?: string | null;
|
|
@@ -532,7 +533,16 @@ async function planApprovalDecided(
|
|
|
532
533
|
if (!approval?.id) return STALE;
|
|
533
534
|
|
|
534
535
|
const statusLabel = approval.status === 'approved' ? 'Approved' : 'Rejected';
|
|
535
|
-
|
|
536
|
+
// A failed execution names its cause on the same line — the agent must not
|
|
537
|
+
// need a second read to tell a version conflict from anything else.
|
|
538
|
+
// agent-core's formatApprovalExecution and the server's Go materializer
|
|
539
|
+
// render the identical suffix; keep the three in sync.
|
|
540
|
+
const execError = approval.execution_error
|
|
541
|
+
? ` | error: ${sanitizeMeta(approval.execution_error)}`
|
|
542
|
+
: '';
|
|
543
|
+
const execInfo = approval.execution_status
|
|
544
|
+
? ` | execution: ${approval.execution_status}${execError}`
|
|
545
|
+
: '';
|
|
536
546
|
const resolvedChat = chatId ?? approval.chat_id;
|
|
537
547
|
|
|
538
548
|
const lines = [`[Event: approval.decided]`];
|