@parall/agent-core 1.31.0 → 1.32.1
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/bridge-workspace.d.ts +1 -1
- package/dist/bridge-workspace.d.ts.map +1 -1
- package/dist/bridge-workspace.js +13 -13
- package/dist/dispatch-adapter.d.ts +15 -8
- package/dist/dispatch-adapter.d.ts.map +1 -1
- package/dist/event-format.d.ts +1 -1
- package/dist/event-format.d.ts.map +1 -1
- package/dist/event-format.js +68 -25
- package/dist/gateway-base.d.ts +14 -13
- package/dist/gateway-base.d.ts.map +1 -1
- package/dist/gateway-base.js +650 -313
- package/dist/index.d.ts +15 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -12
- package/dist/internal/attachment-input.d.ts +3 -3
- package/dist/internal/attachment-input.d.ts.map +1 -1
- package/dist/internal/attachment-input.js +61 -58
- package/dist/logger.d.ts +1 -1
- package/dist/platform-config.d.ts +28 -2
- package/dist/platform-config.d.ts.map +1 -1
- package/dist/platform-config.js +42 -11
- package/dist/prompt-fragments.d.ts +2 -2
- package/dist/prompt-fragments.d.ts.map +1 -1
- package/dist/prompt-fragments.js +37 -14
- package/dist/provider-config.d.ts +9 -0
- package/dist/provider-config.d.ts.map +1 -1
- package/dist/provider-config.js +13 -2
- package/dist/routing.d.ts +5 -5
- package/dist/routing.js +6 -6
- package/dist/session-state.d.ts +16 -0
- package/dist/session-state.d.ts.map +1 -1
- package/dist/session-state.js +45 -0
- package/dist/skills/index.d.ts +5 -4
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +28 -21
- package/dist/skills/parall-clips.d.ts +2 -0
- package/dist/skills/parall-clips.d.ts.map +1 -0
- package/dist/skills/parall-clips.js +44 -0
- package/dist/skills/parall-platform.d.ts +1 -1
- package/dist/skills/parall-platform.d.ts.map +1 -1
- package/dist/skills/parall-platform.js +6 -2
- package/dist/skills/parall-tasks.d.ts +1 -1
- package/dist/skills/parall-tasks.d.ts.map +1 -1
- package/dist/skills/parall-tasks.js +1 -1
- package/dist/skills/parall-wiki.d.ts +1 -1
- package/dist/skills/parall-wiki.d.ts.map +1 -1
- package/dist/skills/parall-wiki.js +1 -1
- package/dist/telemetry.d.ts +27 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +205 -0
- package/dist/types.d.ts +18 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -2
- package/src/bridge-workspace.ts +13 -13
- package/src/dispatch-adapter.ts +31 -8
- package/src/event-format.ts +80 -30
- package/src/gateway-base.ts +988 -445
- package/src/index.ts +23 -13
- package/src/internal/attachment-input.ts +127 -100
- package/src/logger.ts +1 -1
- package/src/platform-config.ts +61 -16
- package/src/prompt-fragments.ts +37 -14
- package/src/provider-config.ts +14 -2
- package/src/routing.ts +11 -11
- package/src/session-state.ts +62 -0
- package/src/skills/index.ts +34 -23
- package/src/skills/parall-clips.ts +44 -0
- package/src/skills/parall-platform.ts +6 -2
- package/src/skills/parall-tasks.ts +1 -1
- package/src/skills/parall-wiki.ts +1 -1
- package/src/telemetry.ts +252 -0
- package/src/types.ts +18 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export { createLogger, childLogger } from
|
|
10
|
-
export * from
|
|
11
|
-
export * from
|
|
12
|
-
export { writeSkillFiles, buildSkillReferences, SKILLS } from
|
|
13
|
-
export type { SkillMeta } from
|
|
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';
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"}
|
|
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,12 +1,13 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export { createLogger, childLogger } from
|
|
10
|
-
export * from
|
|
11
|
-
export * from
|
|
12
|
-
export { writeSkillFiles, buildSkillReferences, SKILLS } from
|
|
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
|
|
2
|
-
import type { LocalAttachmentResult, PreparedLocalImage } from
|
|
3
|
-
import type { ParallEvent } from
|
|
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,
|
|
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
|
|
2
|
-
import { constants } from
|
|
3
|
-
import * as fsSync from
|
|
4
|
-
import * as fs from
|
|
5
|
-
import * as path from
|
|
6
|
-
import { formatBytes, renderLocalAttachmentSection } from
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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),
|
|
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(
|
|
178
|
+
const rel = execSync('git rev-parse --git-path info/exclude', {
|
|
179
179
|
cwd: workingDirectory,
|
|
180
|
-
encoding:
|
|
181
|
-
stdio: [
|
|
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,
|
|
186
|
-
if (existing.split(/\r?\n/).some((line) => line.trim() ===
|
|
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(
|
|
189
|
-
fsSync.appendFileSync(excludePath, `${prefix}.parall/\n`,
|
|
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,
|
|
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 ===
|
|
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 ===
|
|
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 !==
|
|
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(
|
|
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(
|
|
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
|
|
619
|
-
case
|
|
620
|
-
return
|
|
621
|
-
case
|
|
622
|
-
return
|
|
623
|
-
case
|
|
624
|
-
return
|
|
625
|
-
case
|
|
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
|
|
627
|
+
return '.png';
|
|
628
628
|
}
|
|
629
629
|
}
|
|
630
630
|
function sanitizePathSegment(value) {
|
|
631
|
-
const safe = value.replace(/[^A-Za-z0-9._-]+/g,
|
|
631
|
+
const safe = value.replace(/[^A-Za-z0-9._-]+/g, '_').replace(/^_+|_+$/g, '');
|
|
632
632
|
if (!safe || /^\.+$/.test(safe))
|
|
633
|
-
return
|
|
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
|
|
650
|
-
return bytes.length >= 8
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
case
|
|
660
|
-
case
|
|
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
|
|
663
|
-
return bytes.length >= 6
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
case
|
|
667
|
-
return bytes.length >= 12
|
|
668
|
-
|
|
669
|
-
|
|
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 ===
|
|
675
|
+
return err instanceof DOMException && err.name === 'AbortError';
|
|
676
676
|
}
|
|
677
677
|
function sanitizeMeta(value) {
|
|
678
|
-
return value
|
|
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
|
|
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
|
|
2
|
-
import type { GatewayLogger } from
|
|
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,
|
|
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"}
|
package/dist/platform-config.js
CHANGED
|
@@ -1,16 +1,47 @@
|
|
|
1
|
-
import * as fs from
|
|
2
|
-
import * as path from
|
|
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 ===
|
|
4
|
+
return profile?.machine_id != null || profile?.model_management === 'platform';
|
|
5
5
|
}
|
|
6
|
-
|
|
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),
|
|
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),
|
|
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 ===
|
|
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 ===
|
|
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 ===
|
|
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 ===
|
|
85
|
+
if (typeof defaults.thinking_effort === 'string' && defaults.thinking_effort) {
|
|
55
86
|
thinkingEffort = defaults.thinking_effort;
|
|
56
87
|
}
|
|
57
88
|
return { model, thinkingEffort };
|
|
@@ -17,8 +17,8 @@ export interface AgentIdentity {
|
|
|
17
17
|
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
|
-
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.
|
|
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.";
|
|
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. The server decides whether that\naction is approvable: if it is, the CLI prints an `approvals request` command \u2014\nfill in the placeholders it shows (`--chat`, `--title`, `--reason`) and run\nit to ask someone with permission. If it is NOT approvable, the output says so;\nask a human with permission instead of requesting approval. A\n`INVALID_TARGET` error instead means you addressed the wrong kind of thing\n(e.g. a `usr_` id where a chat is expected) \u2014 follow the message (e.g. use\n`dm` for a user). Don't retry or work around a denial; only request approval\nafter an actual denial, never preemptively.\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### 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;
|
|
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,yhFA+CmC,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"}
|
package/dist/prompt-fragments.js
CHANGED
|
@@ -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
|
|
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,
|
|
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,
|
|
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(
|
|
39
|
+
lines.push('', '### Your Agent Profile', '', description);
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
|
-
lines.push(
|
|
40
|
-
return lines.join(
|
|
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;
|
|
@@ -76,10 +79,15 @@ Other agents share this workspace. Before starting work, check whether someone
|
|
|
76
79
|
### Permissions and approvals
|
|
77
80
|
You have real permissions based on your roles (chat member/admin, org member).
|
|
78
81
|
If you lack permission for an action, the API returns PERMISSION_DENIED with the
|
|
79
|
-
\`action\` and \`resource_uri\` that were denied.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
\`action\` and \`resource_uri\` that were denied. The server decides whether that
|
|
83
|
+
action is approvable: if it is, the CLI prints an \`approvals request\` command —
|
|
84
|
+
fill in the placeholders it shows (\`--chat\`, \`--title\`, \`--reason\`) and run
|
|
85
|
+
it to ask someone with permission. If it is NOT approvable, the output says so;
|
|
86
|
+
ask a human with permission instead of requesting approval. A
|
|
87
|
+
\`INVALID_TARGET\` error instead means you addressed the wrong kind of thing
|
|
88
|
+
(e.g. a \`usr_\` id where a chat is expected) — follow the message (e.g. use
|
|
89
|
+
\`dm\` for a user). Don't retry or work around a denial; only request approval
|
|
90
|
+
after an actual denial, never preemptively.
|
|
83
91
|
|
|
84
92
|
### When in doubt
|
|
85
93
|
Prefer asking over guessing. Prefer "I don't know" over fabricating. Your
|
|
@@ -128,6 +136,18 @@ resolves and renders the entity title automatically.
|
|
|
128
136
|
|
|
129
137
|
prll://tsk_xxx/description#Implementation heading within task description
|
|
130
138
|
|
|
139
|
+
### Unread context
|
|
140
|
+
|
|
141
|
+
When dispatched to a chat, you may see \`[Unread: N messages | since: prll://msg_xxx]\`.
|
|
142
|
+
This shows messages since your last interaction — your read cursor advances after each
|
|
143
|
+
dispatch, so context you skip now won't appear as unread next time. Use
|
|
144
|
+
\`parall messages list <chat> --limit 20\` to fetch recent context. For large unread
|
|
145
|
+
counts (50+), fetch only recent messages rather than everything.
|
|
146
|
+
|
|
147
|
+
Thread dispatches may show \`[Thread: prll://msg_root | N replies | M unread | since: prll://msg_r]\`.
|
|
148
|
+
Same semantics — use \`parall messages list <chat> --thread-root-id <thread_root> --limit 20\` to
|
|
149
|
+
catch up on the thread.
|
|
150
|
+
|
|
131
151
|
### Reading context on demand
|
|
132
152
|
|
|
133
153
|
An event only carries the single triggering message. If you're mentioned in a
|
|
@@ -178,7 +198,7 @@ Other agents and humans read your output. References build a navigable context g
|
|
|
178
198
|
in multi-agent workflows, your references are the map that the next agent follows.`;
|
|
179
199
|
export function renderLocalAttachmentSection(section) {
|
|
180
200
|
if (section.images.length === 0 && section.notes.length === 0)
|
|
181
|
-
return
|
|
201
|
+
return '';
|
|
182
202
|
// Each image renders as a metadata header line plus the absolute path on
|
|
183
203
|
// its own line. The path stands alone (no quoting / escaping) so file-
|
|
184
204
|
// reading tools can consume it verbatim — paths inside the attachment root
|
|
@@ -186,15 +206,18 @@ export function renderLocalAttachmentSection(section) {
|
|
|
186
206
|
// the bridge operator. A pathological workspace dir with embedded newlines
|
|
187
207
|
// would split across lines; that's exotic enough not to warrant scrubbing
|
|
188
208
|
// every consumer's path through escape rules.
|
|
189
|
-
const lines = [
|
|
209
|
+
const lines = ['[Local attachment files]'];
|
|
190
210
|
for (const image of section.images) {
|
|
191
211
|
lines.push(`- prll://${image.attachmentId} (${sanitizePromptMeta(image.mimeType)}, ${formatBytes(image.fileSize)}, ${sanitizePromptMeta(image.fileName)})`, ` ${image.localPath}`);
|
|
192
212
|
}
|
|
193
213
|
lines.push(...section.notes);
|
|
194
|
-
return lines.join(
|
|
214
|
+
return lines.join('\n');
|
|
195
215
|
}
|
|
196
216
|
function sanitizePromptMeta(value) {
|
|
197
|
-
return value
|
|
217
|
+
return value
|
|
218
|
+
.replace(/[\r\n]+/g, ' ')
|
|
219
|
+
.replace(/[()]/g, ' ')
|
|
220
|
+
.trim();
|
|
198
221
|
}
|
|
199
222
|
export function formatBytes(bytes) {
|
|
200
223
|
if (bytes >= 1048576)
|
|
@@ -6,6 +6,15 @@ export interface ProviderConfig {
|
|
|
6
6
|
anthropic_base_url?: string;
|
|
7
7
|
}
|
|
8
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;
|
|
9
18
|
export declare function clearAllProviderCreds(env: NodeJS.ProcessEnv): void;
|
|
10
19
|
export declare function parseProviderConfig(env: NodeJS.ProcessEnv): ProviderConfig | undefined;
|
|
11
20
|
//# sourceMappingURL=provider-config.d.ts.map
|