@parall/agent-core 1.23.0 → 1.25.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.
@@ -30,13 +30,20 @@ function sanitizeProfileField(value: string): string {
30
30
  return value.replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim();
31
31
  }
32
32
 
33
+ function sanitizeProfileBlock(value: string): string {
34
+ return value.replace(/\r\n?/g, "\n").trim();
35
+ }
36
+
33
37
  export function buildIdentity(agent?: AgentIdentity): string {
34
38
  if (!agent) return PRLL_IDENTITY_BASE;
35
39
  const name = sanitizeProfileField(agent.displayName);
36
40
  const lines = [PRLL_IDENTITY_BASE, "", "### Your Parall Identity", ""];
37
41
  lines.push(`You are **${name}** (\`prll://${agent.userId}\`).`);
38
42
  if (agent.description) {
39
- lines.push(`Description: ${sanitizeProfileField(agent.description)}`);
43
+ const description = sanitizeProfileBlock(agent.description);
44
+ if (description) {
45
+ lines.push("", "### Your Agent Profile", "", description);
46
+ }
40
47
  }
41
48
  lines.push(
42
49
  "",
@@ -80,6 +87,14 @@ acting, unless you've been explicitly authorized.
80
87
  Other agents share this workspace. Before starting work, check whether someone
81
88
  — human or agent — has already picked it up. Coordination beats racing.
82
89
 
90
+ ### Permissions and approvals
91
+ You have real permissions based on your roles (chat member/admin, org member).
92
+ If you lack permission for an action, the API returns PERMISSION_DENIED with the
93
+ \`action\` and \`resource_uri\` that were denied. When that happens, use
94
+ \`approvals request\` to ask someone with permission to approve it — don't retry
95
+ or work around the denial. Only request approval after an actual denial, never
96
+ preemptively.
97
+
83
98
  ### When in doubt
84
99
  Prefer asking over guessing. Prefer "I don't know" over fabricating. Your
85
100
  credibility is what you bring to the workspace — protect it.`;
@@ -133,9 +148,9 @@ resolves and renders the entity title automatically.
133
148
  An event only carries the single triggering message. If you're mentioned in a
134
149
  group chat and lack context, pull what you need from the chat — don't guess:
135
150
 
136
- npx --yes @parall/cli@latest messages list cht_xxx --limit 20 --before msg_xxx
137
- npx --yes @parall/cli@latest messages get msg_xxx
138
- npx --yes @parall/cli@latest chats get cht_xxx
151
+ parall messages list cht_xxx --limit 20 --before msg_xxx
152
+ parall messages get msg_xxx
153
+ parall chats get cht_xxx
139
154
 
140
155
  Rule of thumb: in a group chat mention, the conversation that led up to you
141
156
  being called almost always matters — read it before replying. In a DM, your
@@ -152,17 +167,17 @@ Messages may include attachments. They appear in events as:
152
167
 
153
168
  To download an attachment, use the CLI:
154
169
 
155
- npx @parall/cli@latest files download att_xxx --output /tmp/screenshot.png
170
+ parall files download att_xxx --output /tmp/screenshot.png
156
171
 
157
172
  To send a file:
158
173
 
159
- npx @parall/cli@latest messages send prll://cht_xxx --file /tmp/output.png --text "Done"
174
+ parall messages send prll://cht_xxx --file /tmp/output.png --text "Done"
160
175
 
161
176
  Or upload first and reuse across chats:
162
177
 
163
- npx @parall/cli@latest files upload /tmp/report.pdf
164
- npx @parall/cli@latest messages send prll://cht_aaa --attachment att_yyy --text "Report"
165
- npx @parall/cli@latest messages send prll://cht_bbb --attachment att_yyy --text "FYI"
178
+ parall files upload /tmp/report.pdf
179
+ parall messages send prll://cht_aaa --attachment att_yyy --text "Report"
180
+ parall messages send prll://cht_bbb --attachment att_yyy --text "FYI"
166
181
 
167
182
  ### When to reference
168
183
 
@@ -176,3 +191,47 @@ Or upload first and reuse across chats:
176
191
 
177
192
  Other agents and humans read your output. References build a navigable context graph —
178
193
  in multi-agent workflows, your references are the map that the next agent follows.`;
194
+
195
+ export type PreparedLocalImage = {
196
+ attachmentId: string;
197
+ fileName: string;
198
+ mimeType: string;
199
+ fileSize: number;
200
+ localPath: string;
201
+ };
202
+
203
+ export type LocalAttachmentResult = {
204
+ images: PreparedLocalImage[];
205
+ notes: string[];
206
+ };
207
+
208
+ export function renderLocalAttachmentSection(section: LocalAttachmentResult): string {
209
+ if (section.images.length === 0 && section.notes.length === 0) return "";
210
+
211
+ // Each image renders as a metadata header line plus the absolute path on
212
+ // its own line. The path stands alone (no quoting / escaping) so file-
213
+ // reading tools can consume it verbatim — paths inside the attachment root
214
+ // are sanitized to ASCII-safe segments, and the workspace dir comes from
215
+ // the bridge operator. A pathological workspace dir with embedded newlines
216
+ // would split across lines; that's exotic enough not to warrant scrubbing
217
+ // every consumer's path through escape rules.
218
+ const lines = ["[Local attachment files]"];
219
+ for (const image of section.images) {
220
+ lines.push(
221
+ `- prll://${image.attachmentId} (${sanitizePromptMeta(image.mimeType)}, ${formatBytes(image.fileSize)}, ${sanitizePromptMeta(image.fileName)})`,
222
+ ` ${image.localPath}`,
223
+ );
224
+ }
225
+ lines.push(...section.notes);
226
+ return lines.join("\n");
227
+ }
228
+
229
+ function sanitizePromptMeta(value: string): string {
230
+ return value.replace(/[\r\n]+/g, " ").replace(/[()]/g, " ").trim();
231
+ }
232
+
233
+ export function formatBytes(bytes: number): string {
234
+ if (bytes >= 1048576) return `${(bytes / 1048576).toFixed(1)}MB`;
235
+ if (bytes >= 1024) return `${Math.round(bytes / 1024)}KB`;
236
+ return `${bytes}B`;
237
+ }
package/src/types.ts CHANGED
@@ -20,6 +20,7 @@ export type ParallEvent = {
20
20
  targetId: string;
21
21
  targetName?: string;
22
22
  targetType?: string;
23
+ deliveryReason?: string;
23
24
  senderId: string;
24
25
  senderName: string;
25
26
  messageId: string;