@parall/agent-core 1.30.0 → 1.32.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.
Files changed (58) hide show
  1. package/dist/bridge-workspace.js +12 -12
  2. package/dist/dispatch-adapter.d.ts +15 -8
  3. package/dist/dispatch-adapter.d.ts.map +1 -1
  4. package/dist/event-format.d.ts +1 -1
  5. package/dist/event-format.d.ts.map +1 -1
  6. package/dist/event-format.js +68 -25
  7. package/dist/gateway-base.d.ts +15 -13
  8. package/dist/gateway-base.d.ts.map +1 -1
  9. package/dist/gateway-base.js +662 -312
  10. package/dist/index.d.ts +15 -12
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +13 -11
  13. package/dist/internal/attachment-input.d.ts +3 -3
  14. package/dist/internal/attachment-input.d.ts.map +1 -1
  15. package/dist/internal/attachment-input.js +61 -58
  16. package/dist/logger.d.ts +1 -1
  17. package/dist/platform-config.d.ts +28 -2
  18. package/dist/platform-config.d.ts.map +1 -1
  19. package/dist/platform-config.js +42 -11
  20. package/dist/prompt-fragments.d.ts +1 -1
  21. package/dist/prompt-fragments.d.ts.map +1 -1
  22. package/dist/prompt-fragments.js +28 -10
  23. package/dist/provider-config.d.ts +20 -0
  24. package/dist/provider-config.d.ts.map +1 -0
  25. package/dist/provider-config.js +41 -0
  26. package/dist/routing.d.ts +5 -5
  27. package/dist/routing.js +6 -6
  28. package/dist/session-state.d.ts +16 -0
  29. package/dist/session-state.d.ts.map +1 -1
  30. package/dist/session-state.js +45 -0
  31. package/dist/skills/index.d.ts +5 -4
  32. package/dist/skills/index.d.ts.map +1 -1
  33. package/dist/skills/index.js +28 -21
  34. package/dist/skills/parall-clips.d.ts +2 -0
  35. package/dist/skills/parall-clips.d.ts.map +1 -0
  36. package/dist/skills/parall-clips.js +44 -0
  37. package/dist/telemetry.d.ts +27 -0
  38. package/dist/telemetry.d.ts.map +1 -0
  39. package/dist/telemetry.js +205 -0
  40. package/dist/types.d.ts +18 -2
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +11 -2
  43. package/src/bridge-workspace.ts +12 -12
  44. package/src/dispatch-adapter.ts +31 -8
  45. package/src/event-format.ts +80 -30
  46. package/src/gateway-base.ts +998 -442
  47. package/src/index.ts +23 -12
  48. package/src/internal/attachment-input.ts +127 -100
  49. package/src/logger.ts +1 -1
  50. package/src/platform-config.ts +61 -16
  51. package/src/prompt-fragments.ts +28 -10
  52. package/src/provider-config.ts +51 -0
  53. package/src/routing.ts +11 -11
  54. package/src/session-state.ts +62 -0
  55. package/src/skills/index.ts +34 -23
  56. package/src/skills/parall-clips.ts +44 -0
  57. package/src/telemetry.ts +252 -0
  58. package/src/types.ts +18 -2
package/dist/index.d.ts CHANGED
@@ -1,13 +1,16 @@
1
- export * from "./types.js";
2
- export * from "./session-state.js";
3
- export * from "./routing.js";
4
- export * from "./event-format.js";
5
- export * from "./prompt-fragments.js";
6
- export * from "./bridge-workspace.js";
7
- export * from "./dispatch-adapter.js";
8
- export { createLogger, childLogger } from "./logger.js";
9
- export * from "./gateway-base.js";
10
- export * from "./platform-config.js";
11
- export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
12
- export type { SkillMeta } from "./skills/index.js";
1
+ export * from './provider-config.js';
2
+ export * from './types.js';
3
+ export * from './session-state.js';
4
+ export * from './routing.js';
5
+ export * from './event-format.js';
6
+ export * from './prompt-fragments.js';
7
+ export * from './bridge-workspace.js';
8
+ export * from './dispatch-adapter.js';
9
+ export { createLogger, childLogger } from './logger.js';
10
+ export * from './gateway-base.js';
11
+ export * from './platform-config.js';
12
+ export { writeSkillFiles, buildSkillReferences, SKILLS } from './skills/index.js';
13
+ export type { SkillMeta } from './skills/index.js';
14
+ export { initAgentTelemetry, createOtelLogger, runWithSessionKey, startDispatchSpan, endDispatchSpan, recordDispatchMetric, recordMissingReply, } from './telemetry.js';
15
+ export type { TelemetryHandle } from './telemetry.js';
13
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
- export * from "./types.js";
2
- export * from "./session-state.js";
3
- export * from "./routing.js";
4
- export * from "./event-format.js";
5
- export * from "./prompt-fragments.js";
6
- export * from "./bridge-workspace.js";
7
- export * from "./dispatch-adapter.js";
8
- export { createLogger, childLogger } from "./logger.js";
9
- export * from "./gateway-base.js";
10
- export * from "./platform-config.js";
11
- export { writeSkillFiles, buildSkillReferences, SKILLS } from "./skills/index.js";
1
+ export * from './provider-config.js';
2
+ export * from './types.js';
3
+ export * from './session-state.js';
4
+ export * from './routing.js';
5
+ export * from './event-format.js';
6
+ export * from './prompt-fragments.js';
7
+ export * from './bridge-workspace.js';
8
+ export * from './dispatch-adapter.js';
9
+ export { createLogger, childLogger } from './logger.js';
10
+ export * from './gateway-base.js';
11
+ export * from './platform-config.js';
12
+ export { writeSkillFiles, buildSkillReferences, SKILLS } from './skills/index.js';
13
+ export { initAgentTelemetry, createOtelLogger, runWithSessionKey, startDispatchSpan, endDispatchSpan, recordDispatchMetric, recordMissingReply, } from './telemetry.js';
@@ -1,6 +1,6 @@
1
- import type { DispatchContext, GatewayLogger } from "../dispatch-adapter.js";
2
- import type { LocalAttachmentResult, PreparedLocalImage } from "../prompt-fragments.js";
3
- import type { ParallEvent } from "../types.js";
1
+ import type { DispatchContext, GatewayLogger } from '../dispatch-adapter.js';
2
+ import type { LocalAttachmentResult, PreparedLocalImage } from '../prompt-fragments.js';
3
+ import type { ParallEvent } from '../types.js';
4
4
  export type { LocalAttachmentResult, PreparedLocalImage };
5
5
  export type LocalAttachmentOptions = {
6
6
  workspaceDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-input.d.ts","sourceRoot":"","sources":["../../src/internal/attachment-input.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;AAE1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAC9D;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,QAAoB,CAAC;AACpE,eAAO,MAAM,sCAAsC,QAAS,CAAC;AAC7D,eAAO,MAAM,yBAAyB,QAAsB,CAAC;AAC7D,eAAO,MAAM,+BAA+B,QAAY,CAAC;AAmBzD,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CA2HhC;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,qBAAqB,GAC5B,MAAM,CAGR;AAED,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,CAG/D;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,IAAI,CAchF;AAMD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAgB9E"}
1
+ {"version":3,"file":"attachment-input.d.ts","sourceRoot":"","sources":["../../src/internal/attachment-input.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE7E,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,YAAY,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;AAE1D,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAC9D;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,QAAoB,CAAC;AACpE,eAAO,MAAM,sCAAsC,QAAS,CAAC;AAC7D,eAAO,MAAM,yBAAyB,QAAsB,CAAC;AAC7D,eAAO,MAAM,+BAA+B,QAAY,CAAC;AAmBzD,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CAmIhC;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAG7F;AAED,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAA;CAAE,CAAC,CAG/D;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,IAAI,CAchF;AAMD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAgB9E"}
@@ -1,9 +1,9 @@
1
- import { execSync } from "node:child_process";
2
- import { constants } from "node:fs";
3
- import * as fsSync from "node:fs";
4
- import * as fs from "node:fs/promises";
5
- import * as path from "node:path";
6
- import { formatBytes, renderLocalAttachmentSection } from "../prompt-fragments.js";
1
+ import { execSync } from 'node:child_process';
2
+ import { constants } from 'node:fs';
3
+ import * as fsSync from 'node:fs';
4
+ import * as fs from 'node:fs/promises';
5
+ import * as path from 'node:path';
6
+ import { formatBytes, renderLocalAttachmentSection } from '../prompt-fragments.js';
7
7
  /**
8
8
  * Per-dispatch cap on image bytes a runtime turn receives. Counts declared
9
9
  * attachment sizes plus fresh download bytes; cache hits are NOT recharged
@@ -23,11 +23,11 @@ export const DEFAULT_ATTACHMENT_DOWNLOAD_TIMEOUT_MS = 30_000;
23
23
  export const DEFAULT_ATTACHMENT_TTL_MS = 24 * 60 * 60 * 1000;
24
24
  export const DEFAULT_MAINTENANCE_COOLDOWN_MS = 60 * 1000;
25
25
  const SUPPORTED_IMAGE_MIME_TYPES = new Set([
26
- "image/png",
27
- "image/jpeg",
28
- "image/jpg",
29
- "image/webp",
30
- "image/gif",
26
+ 'image/png',
27
+ 'image/jpeg',
28
+ 'image/jpg',
29
+ 'image/webp',
30
+ 'image/gif',
31
31
  ]);
32
32
  // Process-global state — correct under the current "one gateway per agent"
33
33
  // architecture (each runtime bridge is a single-tenant subprocess, so all
@@ -165,7 +165,7 @@ export function pinLocalAttachmentPaths(images) {
165
165
  };
166
166
  }
167
167
  function attachmentRootDir(workspaceDir) {
168
- return path.join(path.resolve(workspaceDir), ".parall", "attachments");
168
+ return path.join(path.resolve(workspaceDir), '.parall', 'attachments');
169
169
  }
170
170
  /**
171
171
  * Append `.parall/` to the workspace's git info/exclude. Best-effort — a
@@ -175,18 +175,18 @@ function attachmentRootDir(workspaceDir) {
175
175
  */
176
176
  export function ensureLocalAttachmentGitExclude(workingDirectory) {
177
177
  try {
178
- const rel = execSync("git rev-parse --git-path info/exclude", {
178
+ const rel = execSync('git rev-parse --git-path info/exclude', {
179
179
  cwd: workingDirectory,
180
- encoding: "utf8",
181
- stdio: ["ignore", "pipe", "ignore"],
180
+ encoding: 'utf8',
181
+ stdio: ['ignore', 'pipe', 'ignore'],
182
182
  }).trim();
183
183
  const excludePath = path.isAbsolute(rel) ? rel : path.join(workingDirectory, rel);
184
184
  fsSync.mkdirSync(path.dirname(excludePath), { recursive: true });
185
- const existing = fsSync.existsSync(excludePath) ? fsSync.readFileSync(excludePath, "utf8") : "";
186
- if (existing.split(/\r?\n/).some((line) => line.trim() === ".parall/"))
185
+ const existing = fsSync.existsSync(excludePath) ? fsSync.readFileSync(excludePath, 'utf8') : '';
186
+ if (existing.split(/\r?\n/).some((line) => line.trim() === '.parall/'))
187
187
  return;
188
- const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
189
- fsSync.appendFileSync(excludePath, `${prefix}.parall/\n`, "utf8");
188
+ const prefix = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
189
+ fsSync.appendFileSync(excludePath, `${prefix}.parall/\n`, 'utf8');
190
190
  }
191
191
  catch {
192
192
  // Best-effort only. A missing exclude entry should not block dispatch.
@@ -232,7 +232,7 @@ function scheduleAttachmentMaintenance(rootDir, opts) {
232
232
  }
233
233
  async function ensureAttachmentRootDir(workspaceDir) {
234
234
  const workspaceRoot = path.resolve(workspaceDir);
235
- const parallDir = path.join(workspaceRoot, ".parall");
235
+ const parallDir = path.join(workspaceRoot, '.parall');
236
236
  const rootDir = attachmentRootDir(workspaceRoot);
237
237
  await fs.mkdir(workspaceRoot, { recursive: true });
238
238
  await ensurePathIsNotSymlink(parallDir);
@@ -256,14 +256,14 @@ async function ensurePathIsNotSymlink(filePath) {
256
256
  }
257
257
  }
258
258
  catch (err) {
259
- if (err?.code === "ENOENT")
259
+ if (err?.code === 'ENOENT')
260
260
  return;
261
261
  throw err;
262
262
  }
263
263
  }
264
264
  function isPathInside(childPath, parentPath) {
265
265
  const rel = path.relative(parentPath, childPath);
266
- return rel === "" || (!!rel && !rel.startsWith("..") && !path.isAbsolute(rel));
266
+ return rel === '' || (!!rel && !rel.startsWith('..') && !path.isAbsolute(rel));
267
267
  }
268
268
  async function existingUsableFile(filePath, expectedSize, rootDir) {
269
269
  try {
@@ -498,7 +498,7 @@ async function downloadAttachmentToFile(url, filePath, maxBytes, timeoutMs, root
498
498
  catch {
499
499
  throw new Error(`invalid attachment URL`);
500
500
  }
501
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
501
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
502
502
  throw new Error(`refusing attachment URL with scheme ${parsed.protocol}`);
503
503
  }
504
504
  const controller = new AbortController();
@@ -512,7 +512,7 @@ async function downloadAttachmentToFile(url, filePath, maxBytes, timeoutMs, root
512
512
  throw new Error(`${res.status} ${res.statusText}`);
513
513
  }
514
514
  // Content-Length is only an early-exit hint; the stream byte counter below is authoritative.
515
- const contentLength = parseContentLength(res.headers.get("content-length"));
515
+ const contentLength = parseContentLength(res.headers.get('content-length'));
516
516
  if (contentLength !== undefined && contentLength > maxBytes) {
517
517
  throw new Error(`download would exceed ${formatBytes(maxBytes)} remaining turn limit`);
518
518
  }
@@ -548,7 +548,7 @@ async function withTimeout(promise, timeoutMs, message) {
548
548
  }
549
549
  async function writeResponseToFileWithLimit(res, filePath, maxBytes, rootDir) {
550
550
  if (maxBytes <= 0) {
551
- throw new Error("download would exceed turn limit");
551
+ throw new Error('download would exceed turn limit');
552
552
  }
553
553
  const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
554
554
  const { file, openedStat } = await openLocalTempFileInsideRoot(tmpPath, rootDir);
@@ -615,22 +615,22 @@ function localFileName(attachmentId, fileName, mimeType) {
615
615
  }
616
616
  function extensionForMime(mimeType) {
617
617
  switch (mimeType.toLowerCase()) {
618
- case "image/jpeg":
619
- case "image/jpg":
620
- return ".jpg";
621
- case "image/webp":
622
- return ".webp";
623
- case "image/gif":
624
- return ".gif";
625
- case "image/png":
618
+ case 'image/jpeg':
619
+ case 'image/jpg':
620
+ return '.jpg';
621
+ case 'image/webp':
622
+ return '.webp';
623
+ case 'image/gif':
624
+ return '.gif';
625
+ case 'image/png':
626
626
  default:
627
- return ".png";
627
+ return '.png';
628
628
  }
629
629
  }
630
630
  function sanitizePathSegment(value) {
631
- const safe = value.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
631
+ const safe = value.replace(/[^A-Za-z0-9._-]+/g, '_').replace(/^_+|_+$/g, '');
632
632
  if (!safe || /^\.+$/.test(safe))
633
- return "attachment";
633
+ return 'attachment';
634
634
  return safe;
635
635
  }
636
636
  async function downloadedFileMatchesImageMime(filePath, mimeType, rootDir) {
@@ -646,36 +646,39 @@ async function downloadedFileMatchesImageMime(filePath, mimeType, rootDir) {
646
646
  }
647
647
  function imageHeaderMatches(bytes, mimeType) {
648
648
  switch (mimeType.toLowerCase()) {
649
- case "image/png":
650
- return bytes.length >= 8
651
- && bytes[0] === 0x89
652
- && bytes[1] === 0x50
653
- && bytes[2] === 0x4e
654
- && bytes[3] === 0x47
655
- && bytes[4] === 0x0d
656
- && bytes[5] === 0x0a
657
- && bytes[6] === 0x1a
658
- && bytes[7] === 0x0a;
659
- case "image/jpeg":
660
- case "image/jpg":
649
+ case 'image/png':
650
+ return (bytes.length >= 8 &&
651
+ bytes[0] === 0x89 &&
652
+ bytes[1] === 0x50 &&
653
+ bytes[2] === 0x4e &&
654
+ bytes[3] === 0x47 &&
655
+ bytes[4] === 0x0d &&
656
+ bytes[5] === 0x0a &&
657
+ bytes[6] === 0x1a &&
658
+ bytes[7] === 0x0a);
659
+ case 'image/jpeg':
660
+ case 'image/jpg':
661
661
  return bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff;
662
- case "image/gif":
663
- return bytes.length >= 6
664
- && (bytes.subarray(0, 6).toString("ascii") === "GIF87a"
665
- || bytes.subarray(0, 6).toString("ascii") === "GIF89a");
666
- case "image/webp":
667
- return bytes.length >= 12
668
- && bytes.subarray(0, 4).toString("ascii") === "RIFF"
669
- && bytes.subarray(8, 12).toString("ascii") === "WEBP";
662
+ case 'image/gif':
663
+ return (bytes.length >= 6 &&
664
+ (bytes.subarray(0, 6).toString('ascii') === 'GIF87a' ||
665
+ bytes.subarray(0, 6).toString('ascii') === 'GIF89a'));
666
+ case 'image/webp':
667
+ return (bytes.length >= 12 &&
668
+ bytes.subarray(0, 4).toString('ascii') === 'RIFF' &&
669
+ bytes.subarray(8, 12).toString('ascii') === 'WEBP');
670
670
  default:
671
671
  return false;
672
672
  }
673
673
  }
674
674
  function isAbortError(err) {
675
- return err instanceof DOMException && err.name === "AbortError";
675
+ return err instanceof DOMException && err.name === 'AbortError';
676
676
  }
677
677
  function sanitizeMeta(value) {
678
- return value.replace(/[\r\n]+/g, " ").replace(/[[\]|]/g, " ").trim();
678
+ return value
679
+ .replace(/[\r\n]+/g, ' ')
680
+ .replace(/[[\]|]/g, ' ')
681
+ .trim();
679
682
  }
680
683
  function parseContentLength(value) {
681
684
  if (!value)
package/dist/logger.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { GatewayLogger } from "./dispatch-adapter.js";
1
+ import type { GatewayLogger } from './dispatch-adapter.js';
2
2
  export declare function createLogger(prefix: string): GatewayLogger;
3
3
  export declare function childLogger(logger: GatewayLogger, sub: string): GatewayLogger;
4
4
  //# sourceMappingURL=logger.d.ts.map
@@ -1,5 +1,5 @@
1
- import type { ParallClient } from "@parall/sdk";
2
- import type { GatewayLogger } from "./dispatch-adapter.js";
1
+ import type { ParallClient } from '@parall/sdk';
2
+ import type { GatewayLogger } from './dispatch-adapter.js';
3
3
  export interface PlatformDefaults {
4
4
  model: string | null;
5
5
  thinkingEffort: string | null;
@@ -14,6 +14,32 @@ export interface PlatformManagementProfile {
14
14
  model_management?: string | null;
15
15
  }
16
16
  export declare function isPlatformManagedProfile(profile: PlatformManagementProfile | null | undefined): boolean;
17
+ /**
18
+ * Whether the platform-delivered model should be treated as an operator
19
+ * OVERRIDE (beats env) rather than a FLOOR (loses to env). True only when the
20
+ * profile is platform-managed AND not explicitly self-managed: legacy hosted
21
+ * profiles (model_management=null, resolved to platform server-side) are
22
+ * overrides; local self agents — whose delivered model is a catalog floor —
23
+ * are not. Pass the result as `resolveRuntimeModel`'s first argument. Keeping
24
+ * this derivation in one place avoids drift across the bridges' (re)config
25
+ * sites where the subtle null-hosted-vs-explicit-self distinction matters.
26
+ */
27
+ export declare function isPlatformModelOverride(profile: PlatformManagementProfile | null | undefined): boolean;
28
+ /**
29
+ * Resolve the model a runtime should launch with. Precedence:
30
+ * 1. platform operator override (only when the agent is platform-managed)
31
+ * 2. env/runtime config (PRLL_CLAUDE_MODEL / PRLL_CODEX_MODEL)
32
+ * 3. server-delivered model floor (applies even when model_management=self)
33
+ *
34
+ * The floor (3) is what makes self-hosted + Parall-proxy agents work: the
35
+ * server now delivers `agents.defaults.model` whenever the route is the
36
+ * catalog-gated Parall proxy, so the CLI never falls back to its built-in
37
+ * default (which can outrun the catalog and get rejected). Returns null when
38
+ * no model is resolved, so the bridge omits `--model` and lets the CLI / own
39
+ * login pick — the correct behavior for runtime_auth / custom routes, where
40
+ * the server delivers no floor.
41
+ */
42
+ export declare function resolveRuntimeModel(isOperatorOverride: boolean, platformModel: string | null, configModel: string | null | undefined): string | undefined;
17
43
  export declare function createPlatformConfigManager(opts: {
18
44
  client: ParallClient;
19
45
  stateDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"platform-config.d.ts","sourceRoot":"","sources":["../src/platform-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,OAAO,IAAI,gBAAgB,CAAC;IAC5B,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEvG;AA8ED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,GAAG,qBAAqB,CAoDxB"}
1
+ {"version":3,"file":"platform-config.d.ts","sourceRoot":"","sources":["../src/platform-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnC,OAAO,IAAI,gBAAgB,CAAC;IAC5B,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,GAAG,IAAI,GAAG,SAAS,GACpD,OAAO,CAET;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,yBAAyB,GAAG,IAAI,GAAG,SAAS,GACpD,OAAO,CAET;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,kBAAkB,EAAE,OAAO,EAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACrC,MAAM,GAAG,SAAS,CAGpB;AA8ED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,aAAa,CAAC;CACrB,GAAG,qBAAqB,CAwDxB"}
@@ -1,16 +1,47 @@
1
- import * as fs from "node:fs";
2
- import * as path from "node:path";
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
3
  export function isPlatformManagedProfile(profile) {
4
- return profile?.machine_id != null || profile?.model_management === "platform";
4
+ return profile?.machine_id != null || profile?.model_management === 'platform';
5
5
  }
6
- const CACHE_FILENAME = "parall-platform-config.json";
6
+ /**
7
+ * Whether the platform-delivered model should be treated as an operator
8
+ * OVERRIDE (beats env) rather than a FLOOR (loses to env). True only when the
9
+ * profile is platform-managed AND not explicitly self-managed: legacy hosted
10
+ * profiles (model_management=null, resolved to platform server-side) are
11
+ * overrides; local self agents — whose delivered model is a catalog floor —
12
+ * are not. Pass the result as `resolveRuntimeModel`'s first argument. Keeping
13
+ * this derivation in one place avoids drift across the bridges' (re)config
14
+ * sites where the subtle null-hosted-vs-explicit-self distinction matters.
15
+ */
16
+ export function isPlatformModelOverride(profile) {
17
+ return isPlatformManagedProfile(profile) && profile?.model_management !== 'self';
18
+ }
19
+ /**
20
+ * Resolve the model a runtime should launch with. Precedence:
21
+ * 1. platform operator override (only when the agent is platform-managed)
22
+ * 2. env/runtime config (PRLL_CLAUDE_MODEL / PRLL_CODEX_MODEL)
23
+ * 3. server-delivered model floor (applies even when model_management=self)
24
+ *
25
+ * The floor (3) is what makes self-hosted + Parall-proxy agents work: the
26
+ * server now delivers `agents.defaults.model` whenever the route is the
27
+ * catalog-gated Parall proxy, so the CLI never falls back to its built-in
28
+ * default (which can outrun the catalog and get rejected). Returns null when
29
+ * no model is resolved, so the bridge omits `--model` and lets the CLI / own
30
+ * login pick — the correct behavior for runtime_auth / custom routes, where
31
+ * the server delivers no floor.
32
+ */
33
+ export function resolveRuntimeModel(isOperatorOverride, platformModel, configModel) {
34
+ const operatorOverride = isOperatorOverride ? platformModel : null;
35
+ return operatorOverride ?? configModel ?? platformModel ?? undefined;
36
+ }
37
+ const CACHE_FILENAME = 'parall-platform-config.json';
7
38
  const SUPPORTED_SCHEMA_VERSION = 1;
8
39
  function cachePath(stateDir) {
9
40
  return path.join(stateDir, CACHE_FILENAME);
10
41
  }
11
42
  function loadCache(stateDir) {
12
43
  try {
13
- const raw = fs.readFileSync(cachePath(stateDir), "utf-8");
44
+ const raw = fs.readFileSync(cachePath(stateDir), 'utf-8');
14
45
  return JSON.parse(raw);
15
46
  }
16
47
  catch {
@@ -26,12 +57,12 @@ function saveCache(stateDir, response) {
26
57
  const filePath = cachePath(stateDir);
27
58
  const tmpPath = `${filePath}.tmp`;
28
59
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
29
- fs.writeFileSync(tmpPath, JSON.stringify(cached, null, 2), "utf-8");
60
+ fs.writeFileSync(tmpPath, JSON.stringify(cached, null, 2), 'utf-8');
30
61
  fs.renameSync(tmpPath, filePath);
31
62
  }
32
63
  function runtimeModelName(canonicalModel, runtimeType, config) {
33
64
  const runtime = runtimeType?.trim();
34
- if (!runtime || runtime === "openclaw")
65
+ if (!runtime || runtime === 'openclaw')
35
66
  return canonicalModel;
36
67
  const models = (config.models ?? {});
37
68
  const providers = (models.providers ?? {});
@@ -40,18 +71,18 @@ function runtimeModelName(canonicalModel, runtimeType, config) {
40
71
  const match = catalog.find((model) => model.id === canonicalModel);
41
72
  const runtimeNames = (match?.runtime_names ?? {});
42
73
  const runtimeName = runtimeNames[runtime];
43
- return typeof runtimeName === "string" && runtimeName ? runtimeName : null;
74
+ return typeof runtimeName === 'string' && runtimeName ? runtimeName : null;
44
75
  }
45
76
  function extractDefaults(config, runtimeType) {
46
77
  const agents = (config.agents ?? {});
47
78
  const defaults = (agents.defaults ?? {});
48
79
  let model = null;
49
- if (typeof defaults.model === "string" && defaults.model) {
50
- const canonicalModel = defaults.model.replace(/^parall\//, "");
80
+ if (typeof defaults.model === 'string' && defaults.model) {
81
+ const canonicalModel = defaults.model.replace(/^parall\//, '');
51
82
  model = runtimeModelName(canonicalModel, runtimeType, config);
52
83
  }
53
84
  let thinkingEffort = null;
54
- if (typeof defaults.thinking_effort === "string" && defaults.thinking_effort) {
85
+ if (typeof defaults.thinking_effort === 'string' && defaults.thinking_effort) {
55
86
  thinkingEffort = defaults.thinking_effort;
56
87
  }
57
88
  return { model, thinkingEffort };
@@ -18,7 +18,7 @@ export declare function buildIdentity(agent?: AgentIdentity): string;
18
18
  /** @deprecated Use buildIdentity() instead. Kept for backward compat during migration. */
19
19
  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.";
20
20
  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### Permissions and approvals\nYou have real permissions based on your roles (chat member/admin, org member).\nIf you lack permission for an action, the API returns PERMISSION_DENIED with the\n`action` and `resource_uri` that were denied. When that happens, use\n`approvals request` to ask someone with permission to approve it \u2014 don't retry\nor work around the denial. Only request approval after an actual denial, never\npreemptively.\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.";
21
- 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 prll://sch_xxx schedule\n prll://srn_xxx schedule run\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### Reading context on demand\n\nAn event only carries the single triggering message. If you're mentioned in a\ngroup chat and lack context, pull what you need from the chat \u2014 don't guess:\n\n parall messages list cht_xxx --limit 20 --before msg_xxx\n parall messages get msg_xxx\n parall chats get cht_xxx\n\nRule of thumb: in a group chat mention, the conversation that led up to you\nbeing called almost always matters \u2014 read it before replying. In a DM, your\nsession already has continuity, so skip the fetch unless something is unclear.\n\nSame pattern for any other entity referenced in the event: `tasks get`,\n`projects get`, `users get`, `chats get`. Follow the reflink, don't ask.\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 parall files download att_xxx --output /tmp/screenshot.png\n\nTo send a file:\n\n parall messages send prll://cht_xxx --file /tmp/output.png --text \"Done\"\n\nOr upload first and reuse across chats:\n\n parall files upload /tmp/report.pdf\n parall messages send prll://cht_aaa --attachment att_yyy --text \"Report\"\n parall 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.";
21
+ 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 prll://sch_xxx schedule\n prll://srn_xxx schedule run\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### Unread context\n\nWhen dispatched to a chat, you may see `[Unread: N messages | since: prll://msg_xxx]`.\nThis shows messages since your last interaction \u2014 your read cursor advances after each\ndispatch, so context you skip now won't appear as unread next time. Use\n`parall messages list <chat> --limit 20` to fetch recent context. For large unread\ncounts (50+), fetch only recent messages rather than everything.\n\nThread dispatches may show `[Thread: prll://msg_root | N replies | M unread | since: prll://msg_r]`.\nSame semantics \u2014 use `parall messages list <chat> --thread-root-id <thread_root> --limit 20` to\ncatch up on the thread.\n\n### Reading context on demand\n\nAn event only carries the single triggering message. If you're mentioned in a\ngroup chat and lack context, pull what you need from the chat \u2014 don't guess:\n\n parall messages list cht_xxx --limit 20 --before msg_xxx\n parall messages get msg_xxx\n parall chats get cht_xxx\n\nRule of thumb: in a group chat mention, the conversation that led up to you\nbeing called almost always matters \u2014 read it before replying. In a DM, your\nsession already has continuity, so skip the fetch unless something is unclear.\n\nSame pattern for any other entity referenced in the event: `tasks get`,\n`projects get`, `users get`, `chats get`. Follow the reflink, don't ask.\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 parall files download att_xxx --output /tmp/screenshot.png\n\nTo send a file:\n\n parall messages send prll://cht_xxx --file /tmp/output.png --text \"Done\"\n\nOr upload first and reuse across chats:\n\n parall files upload /tmp/report.pdf\n parall messages send prll://cht_aaa --attachment att_yyy --text \"Report\"\n parall 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.";
22
22
  export type PreparedLocalImage = {
23
23
  attachmentId: string;
24
24
  fileName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-fragments.d.ts","sourceRoot":"","sources":["../src/prompt-fragments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoBD,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,MAAM,CAgB3D;AAED,0FAA0F;AAC1F,eAAO,MAAM,aAAa,mcAAqB,CAAC;AAEhD,eAAO,MAAM,aAAa,ynEA0CmC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,wuHA2FkD,CAAC;AAEpF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAmBnF;AAMD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
1
+ {"version":3,"file":"prompt-fragments.d.ts","sourceRoot":"","sources":["../src/prompt-fragments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAuBD,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,MAAM,CAgB3D;AAED,0FAA0F;AAC1F,eAAO,MAAM,aAAa,mcAAqB,CAAC;AAEhD,eAAO,MAAM,aAAa,ynEA0CmC,CAAC;AAE9D,eAAO,MAAM,oBAAoB,23IAuGkD,CAAC;AAEpF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAmBnF;AASD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
@@ -19,25 +19,28 @@ The people and agents around you are collaborators, not users to serve. Be hones
19
19
  be direct, and care about the outcome of the work — not just the request in front
20
20
  of you.`;
21
21
  function sanitizeProfileField(value) {
22
- return value.replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim();
22
+ return value
23
+ .replace(/[\r\n]+/g, ' ')
24
+ .replace(/`/g, "'")
25
+ .trim();
23
26
  }
24
27
  function sanitizeProfileBlock(value) {
25
- return value.replace(/\r\n?/g, "\n").trim();
28
+ return value.replace(/\r\n?/g, '\n').trim();
26
29
  }
27
30
  export function buildIdentity(agent) {
28
31
  if (!agent)
29
32
  return PRLL_IDENTITY_BASE;
30
33
  const name = sanitizeProfileField(agent.displayName);
31
- const lines = [PRLL_IDENTITY_BASE, "", "### Your Parall Identity", ""];
34
+ const lines = [PRLL_IDENTITY_BASE, '', '### Your Parall Identity', ''];
32
35
  lines.push(`You are **${name}** (\`prll://${agent.userId}\`).`);
33
36
  if (agent.description) {
34
37
  const description = sanitizeProfileBlock(agent.description);
35
38
  if (description) {
36
- lines.push("", "### Your Agent Profile", "", description);
39
+ lines.push('', '### Your Agent Profile', '', description);
37
40
  }
38
41
  }
39
- lines.push("", `When you see \`${agent.userId}\` or \`prll://${agent.userId}\` in messages, mentions, or events — that's you.`);
40
- return lines.join("\n");
42
+ lines.push('', `When you see \`${agent.userId}\` or \`prll://${agent.userId}\` in messages, mentions, or events — that's you.`);
43
+ return lines.join('\n');
41
44
  }
42
45
  /** @deprecated Use buildIdentity() instead. Kept for backward compat during migration. */
43
46
  export const PRLL_IDENTITY = PRLL_IDENTITY_BASE;
@@ -128,6 +131,18 @@ resolves and renders the entity title automatically.
128
131
 
129
132
  prll://tsk_xxx/description#Implementation heading within task description
130
133
 
134
+ ### Unread context
135
+
136
+ When dispatched to a chat, you may see \`[Unread: N messages | since: prll://msg_xxx]\`.
137
+ This shows messages since your last interaction — your read cursor advances after each
138
+ dispatch, so context you skip now won't appear as unread next time. Use
139
+ \`parall messages list <chat> --limit 20\` to fetch recent context. For large unread
140
+ counts (50+), fetch only recent messages rather than everything.
141
+
142
+ Thread dispatches may show \`[Thread: prll://msg_root | N replies | M unread | since: prll://msg_r]\`.
143
+ Same semantics — use \`parall messages list <chat> --thread-root-id <thread_root> --limit 20\` to
144
+ catch up on the thread.
145
+
131
146
  ### Reading context on demand
132
147
 
133
148
  An event only carries the single triggering message. If you're mentioned in a
@@ -178,7 +193,7 @@ Other agents and humans read your output. References build a navigable context g
178
193
  in multi-agent workflows, your references are the map that the next agent follows.`;
179
194
  export function renderLocalAttachmentSection(section) {
180
195
  if (section.images.length === 0 && section.notes.length === 0)
181
- return "";
196
+ return '';
182
197
  // Each image renders as a metadata header line plus the absolute path on
183
198
  // its own line. The path stands alone (no quoting / escaping) so file-
184
199
  // reading tools can consume it verbatim — paths inside the attachment root
@@ -186,15 +201,18 @@ export function renderLocalAttachmentSection(section) {
186
201
  // the bridge operator. A pathological workspace dir with embedded newlines
187
202
  // would split across lines; that's exotic enough not to warrant scrubbing
188
203
  // every consumer's path through escape rules.
189
- const lines = ["[Local attachment files]"];
204
+ const lines = ['[Local attachment files]'];
190
205
  for (const image of section.images) {
191
206
  lines.push(`- prll://${image.attachmentId} (${sanitizePromptMeta(image.mimeType)}, ${formatBytes(image.fileSize)}, ${sanitizePromptMeta(image.fileName)})`, ` ${image.localPath}`);
192
207
  }
193
208
  lines.push(...section.notes);
194
- return lines.join("\n");
209
+ return lines.join('\n');
195
210
  }
196
211
  function sanitizePromptMeta(value) {
197
- return value.replace(/[\r\n]+/g, " ").replace(/[()]/g, " ").trim();
212
+ return value
213
+ .replace(/[\r\n]+/g, ' ')
214
+ .replace(/[()]/g, ' ')
215
+ .trim();
198
216
  }
199
217
  export function formatBytes(bytes) {
200
218
  if (bytes >= 1048576)
@@ -0,0 +1,20 @@
1
+ export interface ProviderConfig {
2
+ llm_source?: string;
3
+ openai_api_key?: string;
4
+ openai_base_url?: string;
5
+ anthropic_auth_token?: string;
6
+ anthropic_base_url?: string;
7
+ }
8
+ export declare function llmSource(pc?: ProviderConfig): string;
9
+ /**
10
+ * Returns the explicitly-configured LLM source — the llm_source value when
11
+ * set, or "custom" when BYO provider credentials are present — or "" when the
12
+ * provider_config carries no source signal at all (e.g. the empty `{}` default
13
+ * that self-hosted agents always have). The daemon supervisor uses the empty
14
+ * case to defer to the machine-level llm_source instead of letting `{}` shadow
15
+ * it as "parall". Mirrors the Go `ProviderConfig.EffectiveLLMSourceExplicit`.
16
+ */
17
+ export declare function effectiveLLMSourceExplicit(pc?: ProviderConfig): string;
18
+ export declare function clearAllProviderCreds(env: NodeJS.ProcessEnv): void;
19
+ export declare function parseProviderConfig(env: NodeJS.ProcessEnv): ProviderConfig | undefined;
20
+ //# sourceMappingURL=provider-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-config.d.ts","sourceRoot":"","sources":["../src/provider-config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAErD;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAWtE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAOlE;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,cAAc,GAAG,SAAS,CAQtF"}