@parall/agent-core 1.15.0 → 1.16.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/event-format.d.ts.map +1 -1
- package/dist/event-format.js +10 -2
- package/dist/gateway-base.d.ts.map +1 -1
- package/dist/gateway-base.js +20 -33
- package/dist/prompt-fragments.d.ts +8 -6
- package/dist/prompt-fragments.d.ts.map +1 -1
- package/dist/prompt-fragments.js +70 -5
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/event-format.ts +11 -2
- package/src/gateway-base.ts +22 -33
- package/src/prompt-fragments.ts +72 -5
- package/src/types.ts +6 -1
|
@@ -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;
|
|
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,CA+BzD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CASnE"}
|
package/dist/event-format.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
function sanitizeMeta(value) {
|
|
2
|
+
return value.replace(/[\r\n]+/g, " ").replace(/[[\]|]/g, " ").trim();
|
|
3
|
+
}
|
|
1
4
|
export function buildEventBody(event) {
|
|
2
5
|
const lines = [];
|
|
3
6
|
if (event.type === "message") {
|
|
@@ -12,8 +15,13 @@ export function buildEventBody(event) {
|
|
|
12
15
|
lines.push(`[Thread: prll://${event.threadRootId}]`);
|
|
13
16
|
if (event.noReply)
|
|
14
17
|
lines.push(`[Hint: no_reply]`);
|
|
15
|
-
if (event.
|
|
16
|
-
|
|
18
|
+
if (event.attachments?.length) {
|
|
19
|
+
for (const att of event.attachments) {
|
|
20
|
+
const sizeStr = att.fileSize >= 1048576
|
|
21
|
+
? `${(att.fileSize / 1048576).toFixed(1)}MB`
|
|
22
|
+
: `${Math.round(att.fileSize / 1024)}KB`;
|
|
23
|
+
lines.push(`[Attachment: prll://${att.id} | ${sanitizeMeta(att.mimeType)} | ${sizeStr} | ${sanitizeMeta(att.fileName)}]`);
|
|
24
|
+
}
|
|
17
25
|
}
|
|
18
26
|
lines.push("", event.body);
|
|
19
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EACV,qBAAqB,
|
|
1
|
+
{"version":3,"file":"gateway-base.d.ts","sourceRoot":"","sources":["../src/gateway-base.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,KAAK,EACV,qBAAqB,EAQtB,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAEV,eAAe,EAGf,aAAa,EAEd,MAAM,uBAAuB,CAAC;AAmD/B,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE;QACN,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,EAAE,eAAe,CAAC;IACjC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,QAAQ,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACjH,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACjD,CAAC;AAkCF,qBAAa,kBAAkB;IAuBjB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAtBjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqC;IACtE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsC;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAK5B;IAEF,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAQ;IAChD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAEjB,IAAI,EAAE,oBAAoB;IAIjD,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA8ElD,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,oBAAoB;YAmBd,eAAe;YAqBf,iBAAiB;IAsF/B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;YAQT,gCAAgC;YAMhC,WAAW;YAyDX,gBAAgB;YAmEhB,eAAe;YAmDf,kBAAkB;YAoElB,kBAAkB;YAkBlB,4BAA4B;YAoD5B,aAAa;YA8Bb,oBAAoB;YAmCpB,mBAAmB;YAoGnB,WAAW;YA0DX,QAAQ;CAsBvB"}
|
package/dist/gateway-base.js
CHANGED
|
@@ -324,7 +324,7 @@ export class ParallAgentGateway {
|
|
|
324
324
|
try {
|
|
325
325
|
if (this.activeSessionId) {
|
|
326
326
|
try {
|
|
327
|
-
await this.opts.client.updateAgentSession(this.opts.config.org_id, this.opts.agentUserId, this.activeSessionId, { status: "active" });
|
|
327
|
+
await this.opts.client.updateAgentSession(this.opts.config.org_id, this.opts.agentUserId, this.activeSessionId, { status: "active", trigger_message_id: event.messageId });
|
|
328
328
|
}
|
|
329
329
|
catch (err) {
|
|
330
330
|
this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to set session active: ${String(err)}`);
|
|
@@ -562,42 +562,29 @@ export class ParallAgentGateway {
|
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
async buildMessageDispatchDecision(chatId, message) {
|
|
565
|
-
if (message.message_type !== "text"
|
|
565
|
+
if (message.message_type !== "text") {
|
|
566
566
|
return { action: "skip" };
|
|
567
567
|
}
|
|
568
568
|
const chatInfo = await this.getOrFetchChatInfo(chatId);
|
|
569
569
|
if (!chatInfo)
|
|
570
570
|
return { action: "retry" };
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const isMentioned = mentions.some((mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID);
|
|
581
|
-
if (!isMentioned)
|
|
582
|
-
return { action: "skip" };
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
else {
|
|
586
|
-
const content = message.content;
|
|
587
|
-
if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
|
|
571
|
+
const content = message.content;
|
|
572
|
+
const body = content.text?.trim() ?? "";
|
|
573
|
+
const hasAttachments = message.attachments?.length;
|
|
574
|
+
if (!body && !hasAttachments)
|
|
575
|
+
return { action: "skip" };
|
|
576
|
+
if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
|
|
577
|
+
const mentions = content.mentions ?? [];
|
|
578
|
+
const isMentioned = mentions.some((mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID);
|
|
579
|
+
if (!isMentioned)
|
|
588
580
|
return { action: "skip" };
|
|
589
|
-
}
|
|
590
|
-
body = content.caption?.trim() || `[file: ${content.file_name || "attachment"}]`;
|
|
591
|
-
if (content.attachment_id) {
|
|
592
|
-
try {
|
|
593
|
-
const fileRes = await this.opts.client.getFileUrl(content.attachment_id);
|
|
594
|
-
mediaFields = { MediaUrl: fileRes.url, MediaType: content.mime_type };
|
|
595
|
-
}
|
|
596
|
-
catch (err) {
|
|
597
|
-
this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to get file URL for ${content.attachment_id}: ${String(err)}`);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
581
|
}
|
|
582
|
+
const attachments = (message.attachments ?? []).map((a) => ({
|
|
583
|
+
id: a.id,
|
|
584
|
+
fileName: a.file_name,
|
|
585
|
+
fileSize: a.file_size,
|
|
586
|
+
mimeType: a.mime_type,
|
|
587
|
+
}));
|
|
601
588
|
return {
|
|
602
589
|
action: "dispatch",
|
|
603
590
|
event: {
|
|
@@ -608,10 +595,10 @@ export class ParallAgentGateway {
|
|
|
608
595
|
senderId: message.sender_id,
|
|
609
596
|
senderName: message.sender?.display_name ?? message.sender_id,
|
|
610
597
|
messageId: message.id,
|
|
611
|
-
body,
|
|
598
|
+
body: body || "[attachment]",
|
|
612
599
|
threadRootId: message.thread_root_id ?? undefined,
|
|
613
600
|
noReply: message.hints?.no_reply ?? false,
|
|
614
|
-
|
|
601
|
+
attachments: attachments.length > 0 ? attachments : undefined,
|
|
615
602
|
ackSourceType: "message",
|
|
616
603
|
ackSourceId: message.id,
|
|
617
604
|
},
|
|
@@ -621,7 +608,7 @@ export class ParallAgentGateway {
|
|
|
621
608
|
const chatId = data.chat_id;
|
|
622
609
|
if (data.sender_id === this.opts.agentUserId)
|
|
623
610
|
return;
|
|
624
|
-
if (data.message_type !== "text"
|
|
611
|
+
if (data.message_type !== "text")
|
|
625
612
|
return;
|
|
626
613
|
if (!this.tryClaimMessage(data.id))
|
|
627
614
|
return;
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
* Each runtime adapter imports these and injects them via its own mechanism
|
|
4
4
|
* (OpenClaw: appendSystemContext, Claude Code: workspace file, etc.).
|
|
5
5
|
*
|
|
6
|
-
* This is the agent-facing SSOT for prll:// URI
|
|
7
|
-
* architectural spec (BNF, canonicalization, data
|
|
8
|
-
* docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
-
* no duplication — this teaches agents HOW to
|
|
10
|
-
*
|
|
6
|
+
* This is the agent-facing SSOT for Parall identity, behavior, and prll:// URI
|
|
7
|
+
* usage. The developer-facing architectural spec (BNF, canonicalization, data
|
|
8
|
+
* model) lives in docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
+
* audiences, no duplication — this teaches agents HOW to work on Parall, the
|
|
10
|
+
* design docs explain WHY the system works the way it does.
|
|
11
11
|
*/
|
|
12
|
-
export declare const
|
|
12
|
+
export declare const PRLL_IDENTITY = "## You on Parall\n\nParall is a shared workspace where humans and agents work side by side as equals.\nYou are a participant here, not a service. You hold tasks, own decisions, and are\naccountable for the work you take on \u2014 the same way a human teammate is.\n\nThe people and agents around you are collaborators, not users to serve. Be honest,\nbe direct, and care about the outcome of the work \u2014 not just the request in front\nof you.";
|
|
13
|
+
export declare const PRLL_BEHAVIOR = "## How to work here\n\n### Move work forward\nDon't wait for instructions. If you see the next step, take it. If something is\nambiguous, clarify once and proceed. If you're blocked, say what's blocking you\n\u2014 don't go silent. Initiative is expected.\n\n### Work in the open\nNothing you do exists until the system can see it. Your progress, decisions,\nblockers, and results need to live in tasks, comments, messages, or wiki pages\n\u2014 otherwise the organization is blind to your work, and so is the next agent\nwho picks up where you left off. Leave traces as you go, not at the end.\n\nFor non-trivial work: create or claim a task, mark it `in_progress`, comment\nwhen status materially changes, close it when done, and link the origin that\ntriggered it. Details: load the `parall-tasks` skill.\n\n### Communicate like a teammate\nMatch the conversation \u2014 concise in chat, thorough in docs, plain language over\njargon. Say what matters; stop when you're done. Don't narrate every tool call\nor pad replies to seem thorough.\n\n### Respect what's shared\nYou have broad latitude inside your own work. But actions that are visible to\nothers, hard to reverse, or touch shared state \u2014 sending DMs, editing shared\nwiki, reassigning others' tasks, deleting content \u2014 pause and confirm before\nacting, unless you've been explicitly authorized.\n\n### Shared workspace\nOther agents share this workspace. Before starting work, check whether someone\n\u2014 human or agent \u2014 has already picked it up. Coordination beats racing.\n\n### When in doubt\nPrefer asking over guessing. Prefer \"I don't know\" over fabricating. Your\ncredibility is what you bring to the workspace \u2014 protect it.";
|
|
14
|
+
export declare const PRLL_REFERENCE_GUIDE = "## Parall References\n\nEvery entity on Parall has a `prll://` URI. Use these URIs to link related\nentities when you create or update tasks, comments, messages, and wiki files.\n\nAll three forms work \u2014 pick whichever fits:\n\n prll://tsk_abc bare URI (auto-linked)\n [](prll://tsk_abc) empty context (renders resolved title)\n [relevant context](prll://tsk_abc) with author annotation\n\nBare URIs and empty-context refs are preferred in most cases \u2014 the platform\nresolves and renders the entity title automatically.\n\n### URI format\n\n`prll://` follows standard URI structure: `scheme://authority/path?query#fragment`.\n\n**Entities** \u2014 the entity ID is the authority:\n\n prll://usr_xxx user prll://prj_xxx project\n prll://tsk_xxx task prll://wik_xxx wiki\n prll://msg_xxx message prll://tcm_xxx task comment\n prll://cht_xxx chat prll://ase_xxx agent session\n prll://att_xxx attachment\n\n**Wiki** \u2014 path is file path, fragment is a typed anchor:\n\n prll://wik_xxx/docs/guide.md file\n prll://wik_xxx/docs/guide.md#h=Auth::OAuth heading (:: = hierarchy)\n prll://wik_xxx/src/auth.go?rev=<sha>#l=42-58 line range (revision-pinned)\n\n Anchor types: `h=` heading, `l=` line/range, `s=` symbol.\n Line anchors in persistent content require `?rev=<full-40-char-sha>`.\n\n**Chat message range**:\n\n prll://cht_xxx#range=msg_01HA,msg_01HZ\n\n**Field access** \u2014 path selects a field (omit to reference the entity itself):\n\n prll://tsk_xxx/description#Implementation heading within task description\n\n### File attachments\n\nMessages may include attachments. They appear in events as:\n\n [Attachment: prll://att_xxx | image/png | 1.2MB | screenshot.png]\n\nTo download an attachment, use the CLI:\n\n npx @parall/cli@latest files download att_xxx --output /tmp/screenshot.png\n\nTo send a file:\n\n npx @parall/cli@latest messages send prll://cht_xxx --file /tmp/output.png --text \"Done\"\n\nOr upload first and reuse across chats:\n\n npx @parall/cli@latest files upload /tmp/report.pdf\n npx @parall/cli@latest messages send prll://cht_aaa --attachment att_yyy --text \"Report\"\n npx @parall/cli@latest messages send prll://cht_bbb --attachment att_yyy --text \"FYI\"\n\n### When to reference\n\n- **Origin** \u2014 always link the message or task that triggered your work\n- **Design docs / wiki** \u2014 link specs and guides relevant to the work\n- **Related tasks** \u2014 link parent, sibling, or blocking tasks\n- **People** \u2014 link assignees or stakeholders when mentioning them\n- **Conversations** \u2014 link a chat or message range as context\n\n### Why this matters\n\nOther agents and humans read your output. References build a navigable context graph \u2014\nin multi-agent workflows, your references are the map that the next agent follows.";
|
|
13
15
|
//# sourceMappingURL=prompt-fragments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-fragments.d.ts","sourceRoot":"","sources":["../src/prompt-fragments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"prompt-fragments.d.ts","sourceRoot":"","sources":["../src/prompt-fragments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,aAAa,mcAQlB,CAAC;AAET,eAAO,MAAM,aAAa,4rDAkCmC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,0/FA0EkD,CAAC"}
|
package/dist/prompt-fragments.js
CHANGED
|
@@ -3,12 +3,56 @@
|
|
|
3
3
|
* Each runtime adapter imports these and injects them via its own mechanism
|
|
4
4
|
* (OpenClaw: appendSystemContext, Claude Code: workspace file, etc.).
|
|
5
5
|
*
|
|
6
|
-
* This is the agent-facing SSOT for prll:// URI
|
|
7
|
-
* architectural spec (BNF, canonicalization, data
|
|
8
|
-
* docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
-
* no duplication — this teaches agents HOW to
|
|
10
|
-
*
|
|
6
|
+
* This is the agent-facing SSOT for Parall identity, behavior, and prll:// URI
|
|
7
|
+
* usage. The developer-facing architectural spec (BNF, canonicalization, data
|
|
8
|
+
* model) lives in docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
+
* audiences, no duplication — this teaches agents HOW to work on Parall, the
|
|
10
|
+
* design docs explain WHY the system works the way it does.
|
|
11
11
|
*/
|
|
12
|
+
export const PRLL_IDENTITY = `## You on Parall
|
|
13
|
+
|
|
14
|
+
Parall is a shared workspace where humans and agents work side by side as equals.
|
|
15
|
+
You are a participant here, not a service. You hold tasks, own decisions, and are
|
|
16
|
+
accountable for the work you take on — the same way a human teammate is.
|
|
17
|
+
|
|
18
|
+
The people and agents around you are collaborators, not users to serve. Be honest,
|
|
19
|
+
be direct, and care about the outcome of the work — not just the request in front
|
|
20
|
+
of you.`;
|
|
21
|
+
export const PRLL_BEHAVIOR = `## How to work here
|
|
22
|
+
|
|
23
|
+
### Move work forward
|
|
24
|
+
Don't wait for instructions. If you see the next step, take it. If something is
|
|
25
|
+
ambiguous, clarify once and proceed. If you're blocked, say what's blocking you
|
|
26
|
+
— don't go silent. Initiative is expected.
|
|
27
|
+
|
|
28
|
+
### Work in the open
|
|
29
|
+
Nothing you do exists until the system can see it. Your progress, decisions,
|
|
30
|
+
blockers, and results need to live in tasks, comments, messages, or wiki pages
|
|
31
|
+
— otherwise the organization is blind to your work, and so is the next agent
|
|
32
|
+
who picks up where you left off. Leave traces as you go, not at the end.
|
|
33
|
+
|
|
34
|
+
For non-trivial work: create or claim a task, mark it \`in_progress\`, comment
|
|
35
|
+
when status materially changes, close it when done, and link the origin that
|
|
36
|
+
triggered it. Details: load the \`parall-tasks\` skill.
|
|
37
|
+
|
|
38
|
+
### Communicate like a teammate
|
|
39
|
+
Match the conversation — concise in chat, thorough in docs, plain language over
|
|
40
|
+
jargon. Say what matters; stop when you're done. Don't narrate every tool call
|
|
41
|
+
or pad replies to seem thorough.
|
|
42
|
+
|
|
43
|
+
### Respect what's shared
|
|
44
|
+
You have broad latitude inside your own work. But actions that are visible to
|
|
45
|
+
others, hard to reverse, or touch shared state — sending DMs, editing shared
|
|
46
|
+
wiki, reassigning others' tasks, deleting content — pause and confirm before
|
|
47
|
+
acting, unless you've been explicitly authorized.
|
|
48
|
+
|
|
49
|
+
### Shared workspace
|
|
50
|
+
Other agents share this workspace. Before starting work, check whether someone
|
|
51
|
+
— human or agent — has already picked it up. Coordination beats racing.
|
|
52
|
+
|
|
53
|
+
### When in doubt
|
|
54
|
+
Prefer asking over guessing. Prefer "I don't know" over fabricating. Your
|
|
55
|
+
credibility is what you bring to the workspace — protect it.`;
|
|
12
56
|
export const PRLL_REFERENCE_GUIDE = `## Parall References
|
|
13
57
|
|
|
14
58
|
Every entity on Parall has a \`prll://\` URI. Use these URIs to link related
|
|
@@ -33,6 +77,7 @@ resolves and renders the entity title automatically.
|
|
|
33
77
|
prll://tsk_xxx task prll://wik_xxx wiki
|
|
34
78
|
prll://msg_xxx message prll://tcm_xxx task comment
|
|
35
79
|
prll://cht_xxx chat prll://ase_xxx agent session
|
|
80
|
+
prll://att_xxx attachment
|
|
36
81
|
|
|
37
82
|
**Wiki** — path is file path, fragment is a typed anchor:
|
|
38
83
|
|
|
@@ -51,6 +96,26 @@ resolves and renders the entity title automatically.
|
|
|
51
96
|
|
|
52
97
|
prll://tsk_xxx/description#Implementation heading within task description
|
|
53
98
|
|
|
99
|
+
### File attachments
|
|
100
|
+
|
|
101
|
+
Messages may include attachments. They appear in events as:
|
|
102
|
+
|
|
103
|
+
[Attachment: prll://att_xxx | image/png | 1.2MB | screenshot.png]
|
|
104
|
+
|
|
105
|
+
To download an attachment, use the CLI:
|
|
106
|
+
|
|
107
|
+
npx @parall/cli@latest files download att_xxx --output /tmp/screenshot.png
|
|
108
|
+
|
|
109
|
+
To send a file:
|
|
110
|
+
|
|
111
|
+
npx @parall/cli@latest messages send prll://cht_xxx --file /tmp/output.png --text "Done"
|
|
112
|
+
|
|
113
|
+
Or upload first and reuse across chats:
|
|
114
|
+
|
|
115
|
+
npx @parall/cli@latest files upload /tmp/report.pdf
|
|
116
|
+
npx @parall/cli@latest messages send prll://cht_aaa --attachment att_yyy --text "Report"
|
|
117
|
+
npx @parall/cli@latest messages send prll://cht_bbb --attachment att_yyy --text "FYI"
|
|
118
|
+
|
|
54
119
|
### When to reference
|
|
55
120
|
|
|
56
121
|
- **Origin** — always link the message or task that triggered your work
|
package/dist/types.d.ts
CHANGED
|
@@ -28,7 +28,12 @@ export type ParallEvent = {
|
|
|
28
28
|
body: string;
|
|
29
29
|
threadRootId?: string;
|
|
30
30
|
noReply?: boolean;
|
|
31
|
-
|
|
31
|
+
attachments?: Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
fileName: string;
|
|
34
|
+
fileSize: number;
|
|
35
|
+
mimeType: string;
|
|
36
|
+
}>;
|
|
32
37
|
ackSourceType?: "message" | "task_activity";
|
|
33
38
|
ackSourceId?: string;
|
|
34
39
|
};
|
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;CACnB,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;CAC3B,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,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,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
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;CACnB,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;CAC3B,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,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,aAAa,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC;IAC5C,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.16.0",
|
|
4
4
|
"description": "Shared agent runtime orchestration helpers for Parall",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"src"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@parall/sdk": "1.
|
|
25
|
+
"@parall/sdk": "1.16.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.0.0",
|
package/src/event-format.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ForkResult, ParallEvent } from "./types.js";
|
|
2
2
|
|
|
3
|
+
function sanitizeMeta(value: string): string {
|
|
4
|
+
return value.replace(/[\r\n]+/g, " ").replace(/[[\]|]/g, " ").trim();
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
export function buildEventBody(event: ParallEvent): string {
|
|
4
8
|
const lines: string[] = [];
|
|
5
9
|
if (event.type === "message") {
|
|
@@ -12,8 +16,13 @@ export function buildEventBody(event: ParallEvent): string {
|
|
|
12
16
|
lines.push(`[Message ID: prll://${event.messageId}]`);
|
|
13
17
|
if (event.threadRootId) lines.push(`[Thread: prll://${event.threadRootId}]`);
|
|
14
18
|
if (event.noReply) lines.push(`[Hint: no_reply]`);
|
|
15
|
-
if (event.
|
|
16
|
-
|
|
19
|
+
if (event.attachments?.length) {
|
|
20
|
+
for (const att of event.attachments) {
|
|
21
|
+
const sizeStr = att.fileSize >= 1048576
|
|
22
|
+
? `${(att.fileSize / 1048576).toFixed(1)}MB`
|
|
23
|
+
: `${Math.round(att.fileSize / 1024)}KB`;
|
|
24
|
+
lines.push(`[Attachment: prll://${att.id} | ${sanitizeMeta(att.mimeType)} | ${sizeStr} | ${sanitizeMeta(att.fileName)}]`);
|
|
25
|
+
}
|
|
17
26
|
}
|
|
18
27
|
lines.push("", event.body);
|
|
19
28
|
} else {
|
package/src/gateway-base.ts
CHANGED
|
@@ -8,7 +8,6 @@ import type {
|
|
|
8
8
|
Chat,
|
|
9
9
|
ChatUpdateData,
|
|
10
10
|
HelloData,
|
|
11
|
-
MediaContent,
|
|
12
11
|
MessageNewData,
|
|
13
12
|
Task,
|
|
14
13
|
TaskAssignedData,
|
|
@@ -437,7 +436,7 @@ export class ParallAgentGateway {
|
|
|
437
436
|
try {
|
|
438
437
|
if (this.activeSessionId) {
|
|
439
438
|
try {
|
|
440
|
-
await this.opts.client.updateAgentSession(this.opts.config.org_id, this.opts.agentUserId, this.activeSessionId, { status: "active" });
|
|
439
|
+
await this.opts.client.updateAgentSession(this.opts.config.org_id, this.opts.agentUserId, this.activeSessionId, { status: "active", trigger_message_id: event.messageId });
|
|
441
440
|
} catch (err) {
|
|
442
441
|
this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to set session active: ${String(err)}`);
|
|
443
442
|
}
|
|
@@ -685,44 +684,34 @@ export class ParallAgentGateway {
|
|
|
685
684
|
chatId: string,
|
|
686
685
|
message: DispatchableMessage,
|
|
687
686
|
): Promise<MessageDispatchDecision> {
|
|
688
|
-
if (message.message_type !== "text"
|
|
687
|
+
if (message.message_type !== "text") {
|
|
689
688
|
return { action: "skip" };
|
|
690
689
|
}
|
|
691
690
|
|
|
692
691
|
const chatInfo = await this.getOrFetchChatInfo(chatId);
|
|
693
692
|
if (!chatInfo) return { action: "retry" };
|
|
694
693
|
|
|
695
|
-
|
|
696
|
-
|
|
694
|
+
const content = message.content as TextContent;
|
|
695
|
+
const body = content.text?.trim() ?? "";
|
|
696
|
+
const hasAttachments = (message as { attachments?: unknown[] }).attachments?.length;
|
|
697
697
|
|
|
698
|
-
if (
|
|
699
|
-
const content = message.content as TextContent;
|
|
700
|
-
body = content.text?.trim() ?? "";
|
|
701
|
-
if (!body) return { action: "skip" };
|
|
698
|
+
if (!body && !hasAttachments) return { action: "skip" };
|
|
702
699
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
710
|
-
} else {
|
|
711
|
-
const content = message.content as MediaContent;
|
|
712
|
-
if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
|
|
713
|
-
return { action: "skip" };
|
|
714
|
-
}
|
|
715
|
-
body = content.caption?.trim() || `[file: ${content.file_name || "attachment"}]`;
|
|
716
|
-
if (content.attachment_id) {
|
|
717
|
-
try {
|
|
718
|
-
const fileRes = await this.opts.client.getFileUrl(content.attachment_id);
|
|
719
|
-
mediaFields = { MediaUrl: fileRes.url, MediaType: content.mime_type };
|
|
720
|
-
} catch (err) {
|
|
721
|
-
this.opts.log?.warn(`parall[${this.opts.accountId}]: failed to get file URL for ${content.attachment_id}: ${String(err)}`);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
700
|
+
if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
|
|
701
|
+
const mentions = content.mentions ?? [];
|
|
702
|
+
const isMentioned = mentions.some(
|
|
703
|
+
(mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID,
|
|
704
|
+
);
|
|
705
|
+
if (!isMentioned) return { action: "skip" };
|
|
724
706
|
}
|
|
725
707
|
|
|
708
|
+
const attachments = ((message as { attachments?: Array<{ id: string; file_name: string; file_size: number; mime_type: string }> }).attachments ?? []).map((a) => ({
|
|
709
|
+
id: a.id,
|
|
710
|
+
fileName: a.file_name,
|
|
711
|
+
fileSize: a.file_size,
|
|
712
|
+
mimeType: a.mime_type,
|
|
713
|
+
}));
|
|
714
|
+
|
|
726
715
|
return {
|
|
727
716
|
action: "dispatch",
|
|
728
717
|
event: {
|
|
@@ -733,10 +722,10 @@ export class ParallAgentGateway {
|
|
|
733
722
|
senderId: message.sender_id,
|
|
734
723
|
senderName: message.sender?.display_name ?? message.sender_id,
|
|
735
724
|
messageId: message.id,
|
|
736
|
-
body,
|
|
725
|
+
body: body || "[attachment]",
|
|
737
726
|
threadRootId: message.thread_root_id ?? undefined,
|
|
738
727
|
noReply: message.hints?.no_reply ?? false,
|
|
739
|
-
|
|
728
|
+
attachments: attachments.length > 0 ? attachments : undefined,
|
|
740
729
|
ackSourceType: "message",
|
|
741
730
|
ackSourceId: message.id,
|
|
742
731
|
},
|
|
@@ -746,7 +735,7 @@ export class ParallAgentGateway {
|
|
|
746
735
|
private async handleMessage(data: MessageNewData) {
|
|
747
736
|
const chatId = data.chat_id;
|
|
748
737
|
if (data.sender_id === this.opts.agentUserId) return;
|
|
749
|
-
if (data.message_type !== "text"
|
|
738
|
+
if (data.message_type !== "text") return;
|
|
750
739
|
if (!this.tryClaimMessage(data.id)) return;
|
|
751
740
|
|
|
752
741
|
const decision = await this.buildMessageDispatchDecision(chatId, data);
|
package/src/prompt-fragments.ts
CHANGED
|
@@ -3,13 +3,59 @@
|
|
|
3
3
|
* Each runtime adapter imports these and injects them via its own mechanism
|
|
4
4
|
* (OpenClaw: appendSystemContext, Claude Code: workspace file, etc.).
|
|
5
5
|
*
|
|
6
|
-
* This is the agent-facing SSOT for prll:// URI
|
|
7
|
-
* architectural spec (BNF, canonicalization, data
|
|
8
|
-
* docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
-
* no duplication — this teaches agents HOW to
|
|
10
|
-
*
|
|
6
|
+
* This is the agent-facing SSOT for Parall identity, behavior, and prll:// URI
|
|
7
|
+
* usage. The developer-facing architectural spec (BNF, canonicalization, data
|
|
8
|
+
* model) lives in docs/engineering-design/reference-schema-design.md. Different
|
|
9
|
+
* audiences, no duplication — this teaches agents HOW to work on Parall, the
|
|
10
|
+
* design docs explain WHY the system works the way it does.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
export const PRLL_IDENTITY = `## You on Parall
|
|
14
|
+
|
|
15
|
+
Parall is a shared workspace where humans and agents work side by side as equals.
|
|
16
|
+
You are a participant here, not a service. You hold tasks, own decisions, and are
|
|
17
|
+
accountable for the work you take on — the same way a human teammate is.
|
|
18
|
+
|
|
19
|
+
The people and agents around you are collaborators, not users to serve. Be honest,
|
|
20
|
+
be direct, and care about the outcome of the work — not just the request in front
|
|
21
|
+
of you.`;
|
|
22
|
+
|
|
23
|
+
export const PRLL_BEHAVIOR = `## How to work here
|
|
24
|
+
|
|
25
|
+
### Move work forward
|
|
26
|
+
Don't wait for instructions. If you see the next step, take it. If something is
|
|
27
|
+
ambiguous, clarify once and proceed. If you're blocked, say what's blocking you
|
|
28
|
+
— don't go silent. Initiative is expected.
|
|
29
|
+
|
|
30
|
+
### Work in the open
|
|
31
|
+
Nothing you do exists until the system can see it. Your progress, decisions,
|
|
32
|
+
blockers, and results need to live in tasks, comments, messages, or wiki pages
|
|
33
|
+
— otherwise the organization is blind to your work, and so is the next agent
|
|
34
|
+
who picks up where you left off. Leave traces as you go, not at the end.
|
|
35
|
+
|
|
36
|
+
For non-trivial work: create or claim a task, mark it \`in_progress\`, comment
|
|
37
|
+
when status materially changes, close it when done, and link the origin that
|
|
38
|
+
triggered it. Details: load the \`parall-tasks\` skill.
|
|
39
|
+
|
|
40
|
+
### Communicate like a teammate
|
|
41
|
+
Match the conversation — concise in chat, thorough in docs, plain language over
|
|
42
|
+
jargon. Say what matters; stop when you're done. Don't narrate every tool call
|
|
43
|
+
or pad replies to seem thorough.
|
|
44
|
+
|
|
45
|
+
### Respect what's shared
|
|
46
|
+
You have broad latitude inside your own work. But actions that are visible to
|
|
47
|
+
others, hard to reverse, or touch shared state — sending DMs, editing shared
|
|
48
|
+
wiki, reassigning others' tasks, deleting content — pause and confirm before
|
|
49
|
+
acting, unless you've been explicitly authorized.
|
|
50
|
+
|
|
51
|
+
### Shared workspace
|
|
52
|
+
Other agents share this workspace. Before starting work, check whether someone
|
|
53
|
+
— human or agent — has already picked it up. Coordination beats racing.
|
|
54
|
+
|
|
55
|
+
### When in doubt
|
|
56
|
+
Prefer asking over guessing. Prefer "I don't know" over fabricating. Your
|
|
57
|
+
credibility is what you bring to the workspace — protect it.`;
|
|
58
|
+
|
|
13
59
|
export const PRLL_REFERENCE_GUIDE = `## Parall References
|
|
14
60
|
|
|
15
61
|
Every entity on Parall has a \`prll://\` URI. Use these URIs to link related
|
|
@@ -34,6 +80,7 @@ resolves and renders the entity title automatically.
|
|
|
34
80
|
prll://tsk_xxx task prll://wik_xxx wiki
|
|
35
81
|
prll://msg_xxx message prll://tcm_xxx task comment
|
|
36
82
|
prll://cht_xxx chat prll://ase_xxx agent session
|
|
83
|
+
prll://att_xxx attachment
|
|
37
84
|
|
|
38
85
|
**Wiki** — path is file path, fragment is a typed anchor:
|
|
39
86
|
|
|
@@ -52,6 +99,26 @@ resolves and renders the entity title automatically.
|
|
|
52
99
|
|
|
53
100
|
prll://tsk_xxx/description#Implementation heading within task description
|
|
54
101
|
|
|
102
|
+
### File attachments
|
|
103
|
+
|
|
104
|
+
Messages may include attachments. They appear in events as:
|
|
105
|
+
|
|
106
|
+
[Attachment: prll://att_xxx | image/png | 1.2MB | screenshot.png]
|
|
107
|
+
|
|
108
|
+
To download an attachment, use the CLI:
|
|
109
|
+
|
|
110
|
+
npx @parall/cli@latest files download att_xxx --output /tmp/screenshot.png
|
|
111
|
+
|
|
112
|
+
To send a file:
|
|
113
|
+
|
|
114
|
+
npx @parall/cli@latest messages send prll://cht_xxx --file /tmp/output.png --text "Done"
|
|
115
|
+
|
|
116
|
+
Or upload first and reuse across chats:
|
|
117
|
+
|
|
118
|
+
npx @parall/cli@latest files upload /tmp/report.pdf
|
|
119
|
+
npx @parall/cli@latest messages send prll://cht_aaa --attachment att_yyy --text "Report"
|
|
120
|
+
npx @parall/cli@latest messages send prll://cht_bbb --attachment att_yyy --text "FYI"
|
|
121
|
+
|
|
55
122
|
### When to reference
|
|
56
123
|
|
|
57
124
|
- **Origin** — always link the message or task that triggered your work
|
package/src/types.ts
CHANGED
|
@@ -26,7 +26,12 @@ export type ParallEvent = {
|
|
|
26
26
|
body: string;
|
|
27
27
|
threadRootId?: string;
|
|
28
28
|
noReply?: boolean;
|
|
29
|
-
|
|
29
|
+
attachments?: Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
fileName: string;
|
|
32
|
+
fileSize: number;
|
|
33
|
+
mimeType: string;
|
|
34
|
+
}>;
|
|
30
35
|
ackSourceType?: "message" | "task_activity";
|
|
31
36
|
ackSourceId?: string;
|
|
32
37
|
};
|