@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.
@@ -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;AAE1D,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CA0BzD;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CASnE"}
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"}
@@ -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.mediaFields?.MediaUrl) {
16
- lines.push(`[Attachment: ${event.mediaFields.MediaType ?? "file"} ${event.mediaFields.MediaUrl}]`);
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,EAStB,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;YA8D5B,aAAa;YA8Bb,oBAAoB;YAmCpB,mBAAmB;YAoGnB,WAAW;YA0DX,QAAQ;CAsBvB"}
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"}
@@ -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" && message.message_type !== "file") {
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
- let body = "";
572
- let mediaFields = {};
573
- if (message.message_type === "text") {
574
- const content = message.content;
575
- body = content.text?.trim() ?? "";
576
- if (!body)
577
- return { action: "skip" };
578
- if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
579
- const mentions = content.mentions ?? [];
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
- mediaFields: Object.keys(mediaFields).length > 0 ? mediaFields : undefined,
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" && data.message_type !== "file")
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 usage. The developer-facing
7
- * architectural spec (BNF, canonicalization, data model) lives in
8
- * docs/engineering-design/reference-schema-design.md. Different audiences,
9
- * no duplication — this teaches agents HOW to use refs, the design doc
10
- * explains WHY the system works the way it does.
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 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\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### 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.";
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,6xEAqDkD,CAAC"}
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"}
@@ -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 usage. The developer-facing
7
- * architectural spec (BNF, canonicalization, data model) lives in
8
- * docs/engineering-design/reference-schema-design.md. Different audiences,
9
- * no duplication — this teaches agents HOW to use refs, the design doc
10
- * explains WHY the system works the way it does.
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
- mediaFields?: Record<string, string | undefined>;
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
  };
@@ -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,GAAG,SAAS,CAAC,CAAC;IACjD,aAAa,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC;IAC5C,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,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.15.0",
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.15.0"
25
+ "@parall/sdk": "1.16.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.0.0",
@@ -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.mediaFields?.MediaUrl) {
16
- lines.push(`[Attachment: ${event.mediaFields.MediaType ?? "file"} ${event.mediaFields.MediaUrl}]`);
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 {
@@ -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" && message.message_type !== "file") {
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
- let body = "";
696
- let mediaFields: Record<string, string | undefined> = {};
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 (message.message_type === "text") {
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
- if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
704
- const mentions = content.mentions ?? [];
705
- const isMentioned = mentions.some(
706
- (mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID,
707
- );
708
- if (!isMentioned) return { action: "skip" };
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
- mediaFields: Object.keys(mediaFields).length > 0 ? mediaFields : undefined,
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" && data.message_type !== "file") return;
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);
@@ -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 usage. The developer-facing
7
- * architectural spec (BNF, canonicalization, data model) lives in
8
- * docs/engineering-design/reference-schema-design.md. Different audiences,
9
- * no duplication — this teaches agents HOW to use refs, the design doc
10
- * explains WHY the system works the way it does.
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
- mediaFields?: Record<string, string | undefined>;
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
  };