@parall/daemon 1.36.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/manifest.json +11 -11
- package/bundle/parall-browser-pod.js +384 -32
- package/bundle/parall-claude-agent.js +426 -51
- package/bundle/parall-codex-agent.js +425 -49
- package/bundle/parall-daemon.js +33336 -31520
- package/dist/browser-pod.d.ts +7 -0
- package/dist/browser-pod.d.ts.map +1 -1
- package/dist/browser-pod.js +73 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/clip-runtime/browser-daemon-env.d.ts +29 -0
- package/dist/clip-runtime/browser-daemon-env.d.ts.map +1 -0
- package/dist/clip-runtime/browser-daemon-env.js +70 -0
- package/dist/clip-runtime/browser-profile-manager.d.ts +34 -5
- package/dist/clip-runtime/browser-profile-manager.d.ts.map +1 -1
- package/dist/clip-runtime/browser-profile-manager.js +166 -24
- package/dist/clip-runtime/browser-profile-pool.d.ts +250 -0
- package/dist/clip-runtime/browser-profile-pool.d.ts.map +1 -0
- package/dist/clip-runtime/browser-profile-pool.js +581 -0
- package/dist/clip-runtime/index.d.ts +2 -1
- package/dist/clip-runtime/index.d.ts.map +1 -1
- package/dist/clip-runtime/index.js +2 -1
- package/dist/clip-runtime/process-manager.d.ts +5 -3
- package/dist/clip-runtime/process-manager.d.ts.map +1 -1
- package/dist/clip-runtime/subprocess.d.ts +14 -0
- package/dist/clip-runtime/subprocess.d.ts.map +1 -1
- package/dist/clip-runtime/subprocess.js +49 -0
- package/dist/config.d.ts +14 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -26
- package/dist/daemon-main.d.ts +8 -0
- package/dist/daemon-main.d.ts.map +1 -0
- package/dist/daemon-main.js +165 -0
- package/dist/daemon-paths.d.ts +14 -0
- package/dist/daemon-paths.d.ts.map +1 -0
- package/dist/daemon-paths.js +26 -0
- package/dist/daemon-update-mode.d.ts +8 -0
- package/dist/daemon-update-mode.d.ts.map +1 -0
- package/dist/daemon-update-mode.js +18 -0
- package/dist/index.js +41 -167
- package/dist/runtime-bin-resolver.d.ts +4 -0
- package/dist/runtime-bin-resolver.d.ts.map +1 -1
- package/dist/runtime-bin-resolver.js +40 -7
- package/dist/runtime-detector.d.ts +30 -0
- package/dist/runtime-detector.d.ts.map +1 -0
- package/dist/runtime-detector.js +100 -0
- package/dist/supervisor.d.ts +64 -2
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +629 -67
- package/dist/update-health-gate.d.ts +66 -0
- package/dist/update-health-gate.d.ts.map +1 -0
- package/dist/update-health-gate.js +93 -0
- package/dist/updater-manifest.d.ts +2 -1
- package/dist/updater-manifest.d.ts.map +1 -1
- package/dist/updater-manifest.js +38 -7
- package/dist/updater.d.ts +13 -2
- package/dist/updater.d.ts.map +1 -1
- package/dist/updater.js +126 -17
- package/package.json +6 -6
|
@@ -26647,6 +26647,17 @@ function buildEventBody(event) {
|
|
|
26647
26647
|
if (event.attachedUri)
|
|
26648
26648
|
lines.push(`[Attached: ${sanitizeMeta(event.attachedUri)}]`);
|
|
26649
26649
|
lines.push("", event.body);
|
|
26650
|
+
} else if (event.type === "channel_message") {
|
|
26651
|
+
lines.push(`[Event: channel.message]`);
|
|
26652
|
+
const providerLabel = sanitizeMeta(event.channelProvider ?? "external IM");
|
|
26653
|
+
const convLabel = event.channelExternalConversationId ? `${sanitizeMeta(event.channelExternalConversationId)} (${sanitizeMeta(event.channelConversationType ?? "conversation")})` : sanitizeMeta(event.channelConversationType ?? "conversation");
|
|
26654
|
+
lines.push(`[Channel: ${providerLabel} | conversation: ${convLabel}]`);
|
|
26655
|
+
lines.push(`[From: ${sanitizeMeta(event.senderName)} (external user, not a Parall member)]`);
|
|
26656
|
+
if (event.channelExternalMessageId) {
|
|
26657
|
+
lines.push(`[External message ID: ${sanitizeMeta(event.channelExternalMessageId)}]`);
|
|
26658
|
+
}
|
|
26659
|
+
lines.push(`[Audience: this conversation lives on ${providerLabel}, OUTSIDE Parall. Readers cannot open prll:// links, Parall cards, or internal attachments \u2014 never include them in replies. Write plain conversational text.]`);
|
|
26660
|
+
lines.push("", event.body);
|
|
26650
26661
|
} else if (event.type === "external_trigger") {
|
|
26651
26662
|
lines.push(`[Event: external.trigger]`);
|
|
26652
26663
|
lines.push(`[Trigger: prll://${event.targetId}]`);
|
|
@@ -26688,7 +26699,7 @@ function buildSendMessageHint(event) {
|
|
|
26688
26699
|
}
|
|
26689
26700
|
if (event.targetId.startsWith("cht_")) {
|
|
26690
26701
|
return `
|
|
26691
|
-
<system-reminder>To reply, run
|
|
26702
|
+
<system-reminder>To reply, run \`parall messages send prll://${event.targetId} --text-file - <<'EOF'\` \u2026 \`EOF\` \u2014 the quoted heredoc keeps \`$\`, backticks and apostrophes literal (plain \`--text "$1,000"\` sends \`,000\`). Your plain text output is not delivered to the chat.</system-reminder>`;
|
|
26692
26703
|
}
|
|
26693
26704
|
if (event.targetId.startsWith("tsk_")) {
|
|
26694
26705
|
return `
|
|
@@ -26697,6 +26708,14 @@ function buildSendMessageHint(event) {
|
|
|
26697
26708
|
if (event.targetId.startsWith("sch_")) {
|
|
26698
26709
|
return `
|
|
26699
26710
|
<system-reminder>To communicate, use the CLI: \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
26711
|
+
}
|
|
26712
|
+
if (event.type === "channel_message") {
|
|
26713
|
+
const clipLabel = event.channelProvider ? `the \`${event.channelProvider}\` clip's` : "your channel provider clip's";
|
|
26714
|
+
const apiLabel = event.channelProvider ?? "external platform";
|
|
26715
|
+
const target = event.channelExternalConversationId ? `{"chat_id": "${event.channelExternalConversationId}", "text": "..."}` : `{"chat_id": "<conversation id>", "text": "..."}`;
|
|
26716
|
+
const threadAlt = event.channelExternalMessageId ? ` To reply in-thread to this specific message, use {"message_id": "${event.channelExternalMessageId}", "text": "..."} instead.` : "";
|
|
26717
|
+
return `
|
|
26718
|
+
<system-reminder>To reply, invoke ${clipLabel} \`send_message\` command with ${target} \u2014 your plain text output is NOT delivered to the external conversation.${threadAlt} The same clip's \`call\` command reaches the wider ${apiLabel} API when needed.</system-reminder>`;
|
|
26700
26719
|
}
|
|
26701
26720
|
if (event.type === "external_trigger" || event.targetId.startsWith("xtr_")) {
|
|
26702
26721
|
return `
|
|
@@ -26904,6 +26923,8 @@ Or upload first and reuse across chats:
|
|
|
26904
26923
|
parall messages send prll://cht_aaa --attachment att_yyy --text "Report"
|
|
26905
26924
|
parall messages send prll://cht_bbb --attachment att_yyy --text "FYI"
|
|
26906
26925
|
|
|
26926
|
+
The \`--text\` captions above are safe short literals. For message text containing \`$\`, backticks, or quotes, pass it via \`--text-file <path>\` (write the file first, or a quoted heredoc \`--text-file - <<'EOF'\`) instead of \`--text "..."\` \u2014 inside double quotes the shell turns \`$1,000\` into \`,000\` and executes \`$(...)\`.
|
|
26927
|
+
|
|
26907
26928
|
### When to reference
|
|
26908
26929
|
|
|
26909
26930
|
- **Origin** \u2014 always link the message or task that triggered your work
|
|
@@ -26954,11 +26975,21 @@ To say something in a chat, you **must** invoke the Parall CLI via your shell/ex
|
|
|
26954
26975
|
|
|
26955
26976
|
All outbound interactions go through the \`parall\` CLI. Credentials are pre-injected as environment variables \u2014 no setup needed. If \`parall\` is not on PATH, use \`npx --yes @parall/cli@latest\` instead.
|
|
26956
26977
|
|
|
26957
|
-
- \`parall messages send prll://cht_xxx --text
|
|
26958
|
-
- \`parall dm prll://usr_xxx --text
|
|
26978
|
+
- \`parall messages send prll://cht_xxx --text-file -\` \u2014 reply into the triggering chat (pipe the body via a quoted heredoc; see Shell-safety below)
|
|
26979
|
+
- \`parall dm prll://usr_xxx --text-file - [--no-reply]\` \u2014 direct message another user
|
|
26959
26980
|
- \`parall tasks update prll://tsk_xxx --status in_progress\` \u2014 task state
|
|
26960
26981
|
- \`parall no-reply [--reason "..."]\` \u2014 explicitly declare this turn silent (audit signal; not required for silence, just clarifies intent)
|
|
26961
26982
|
|
|
26983
|
+
**Shell-safety \u2014 never wrap real message content in double quotes.** Your command runs in a shell, which expands \`$\`, backticks, and \`$(...)\` inside \`"..."\` before the CLI sees them: \`--text "That costs $1,000"\` sends \`That costs ,000\`, and \`--text "$(cmd)"\` executes \`cmd\`. Pass message bodies via \`--text-file <path>\` (write the file first \u2014 no shell touches it) or a quoted heredoc that disables expansion:
|
|
26984
|
+
|
|
26985
|
+
\`\`\`bash
|
|
26986
|
+
parall messages send prll://cht_xxx --text-file - <<'EOF'
|
|
26987
|
+
That costs $1,000, and $(whoami) stays literal. I'm on it.
|
|
26988
|
+
EOF
|
|
26989
|
+
\`\`\`
|
|
26990
|
+
|
|
26991
|
+
Keep \`--text "..."\` for short literals with no \`$\`, backtick, or apostrophe.
|
|
26992
|
+
|
|
26962
26993
|
The bridge injects Parall context via environment variables. The static credentials \`PRLL_API_URL\`, \`PRLL_API_KEY\`, and \`PRLL_ORG_ID\` are always set. \`PRLL_CONTEXT_FILE\` points to a per-session JSON file that the gateway updates each dispatch with \`session_id\`, \`chat_id\`, \`trigger_message_id\`, \`no_reply\`, and \`step_id\` (updated per tool call). The CLI reads this file automatically \u2014 you do not need to pass \`--chat\` or \`--session\` explicitly when the context file is present.
|
|
26963
26994
|
|
|
26964
26995
|
## Attachments
|
|
@@ -27003,7 +27034,7 @@ Messages may arrive with a \`[Thread: prll://msg_xxx]\` line in the event block,
|
|
|
27003
27034
|
|
|
27004
27035
|
### CLI usage
|
|
27005
27036
|
- The \`msg_xxx\` from the \`[Thread: prll://msg_xxx]\` line is the thread root ID \u2014 pass it as \`--thread-root-id\`
|
|
27006
|
-
- Reply in a thread: \`parall messages send <chatId> --text
|
|
27037
|
+
- Reply in a thread: \`parall messages send <chatId> --text-file /tmp/reply.md --thread-root-id <msgId>\`
|
|
27007
27038
|
- Read thread replies: \`parall messages list <chatId> --thread-root-id <msgId>\`
|
|
27008
27039
|
|
|
27009
27040
|
### Thread etiquette
|
|
@@ -27104,6 +27135,7 @@ var ENDPOINTS = {
|
|
|
27104
27135
|
// Org-scoped
|
|
27105
27136
|
ORG: (orgId) => `${API_BASE}/orgs/${orgId}`,
|
|
27106
27137
|
ORG_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/members`,
|
|
27138
|
+
ORG_MEMBERS_FORMER: (orgId) => `${API_BASE}/orgs/${orgId}/members/former`,
|
|
27107
27139
|
TEAMS: (orgId) => `${API_BASE}/orgs/${orgId}/teams`,
|
|
27108
27140
|
ORG_MEMBERS_ONLINE: (orgId) => `${API_BASE}/orgs/${orgId}/members/online`,
|
|
27109
27141
|
ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
|
|
@@ -27253,6 +27285,19 @@ var ENDPOINTS = {
|
|
|
27253
27285
|
EXTERNAL_TRIGGER: (orgId, triggerId) => `${API_BASE}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
27254
27286
|
EXTERNAL_TRIGGER_RUNS: (orgId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs`,
|
|
27255
27287
|
EXTERNAL_TRIGGER_RUN: (orgId, runId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs/${runId}`,
|
|
27288
|
+
// External IM channel (org-scoped, platform-mediated Feishu/Slack)
|
|
27289
|
+
CHANNEL_CONNECTIONS: (orgId) => `${API_BASE}/orgs/${orgId}/channel-connections`,
|
|
27290
|
+
CHANNEL_CONNECTION: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}`,
|
|
27291
|
+
CHANNEL_CONNECTION_CREDENTIALS: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/credentials`,
|
|
27292
|
+
CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/ingress-token/regenerate`,
|
|
27293
|
+
CHANNEL_CONNECTION_CONVERSATIONS: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/conversations`,
|
|
27294
|
+
CHANNEL_CONVERSATION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}`,
|
|
27295
|
+
CHANNEL_CONVERSATION_MESSAGES: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/messages`,
|
|
27296
|
+
CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
|
|
27297
|
+
CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
|
|
27298
|
+
CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
|
|
27299
|
+
CHANNEL_PROVISIONING_SESSION: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
|
|
27300
|
+
CHANNEL_PROVISIONING_CANCEL: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
|
|
27256
27301
|
// Invitations (org-scoped, admin)
|
|
27257
27302
|
ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
|
|
27258
27303
|
ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
|
|
@@ -27270,9 +27315,16 @@ var ENDPOINTS = {
|
|
|
27270
27315
|
INVITE_LINK_JOIN: `${API_BASE}/invite-link/join`,
|
|
27271
27316
|
// Wikis (org-scoped, served by wiki-service)
|
|
27272
27317
|
WIKIS: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis`,
|
|
27318
|
+
// Recycle bin — soft-deleted wikis (owner only). Must precede WIKI in the
|
|
27319
|
+
// backend router so `deleted` isn't captured as a {wikiId}; the SDK builder
|
|
27320
|
+
// is just a string.
|
|
27321
|
+
WIKIS_DELETED: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis/deleted`,
|
|
27322
|
+
// Detail URL — also reused for DELETE (soft-delete) and `${WIKI}/restore`.
|
|
27273
27323
|
WIKI: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
|
|
27324
|
+
WIKI_RESTORE: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restore`,
|
|
27274
27325
|
WIKI_TREE: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/tree`,
|
|
27275
27326
|
WIKI_BLOB: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/blob`,
|
|
27327
|
+
WIKI_COPY: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/copy`,
|
|
27276
27328
|
WIKI_NODE_SECTIONS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/node-sections`,
|
|
27277
27329
|
WIKI_SEARCH: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/search`,
|
|
27278
27330
|
WIKI_PAGE_INDEX: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/page-index`,
|
|
@@ -27334,6 +27386,7 @@ var ENDPOINTS = {
|
|
|
27334
27386
|
// References (org-scoped)
|
|
27335
27387
|
REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
|
|
27336
27388
|
REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
|
|
27389
|
+
REFS_GRAPH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/graph`,
|
|
27337
27390
|
REFS_CHECK: (orgId) => `${API_BASE}/orgs/${orgId}/refs/check`,
|
|
27338
27391
|
// Platform config (agent-scoped, not org-scoped)
|
|
27339
27392
|
PLATFORM_CONFIG: `${API_BASE}/agents/platform-config`,
|
|
@@ -27354,6 +27407,14 @@ var ENDPOINTS = {
|
|
|
27354
27407
|
BILLING_AUTO_RELOAD: (orgId) => `${API_BASE}/orgs/${orgId}/billing/auto-reload`,
|
|
27355
27408
|
BILLING_SETUP_INTENT: (orgId) => `${API_BASE}/orgs/${orgId}/billing/setup-intent`,
|
|
27356
27409
|
COMPUTE_PRICING: () => `${API_BASE}/billing/compute-pricing`,
|
|
27410
|
+
// Runtime capability table (public, no auth) — SSOT for the create/settings
|
|
27411
|
+
// interlock: per-runtime compute modes, native model family, cross-family
|
|
27412
|
+
// availability, and recommended model.
|
|
27413
|
+
RUNTIMES: () => `${API_BASE}/runtimes`,
|
|
27414
|
+
// Model catalog (public, no auth) — served from the server's DB-backed
|
|
27415
|
+
// snapshot. Optional include_model keeps an agent's pinned hidden legacy
|
|
27416
|
+
// model representable in settings pickers.
|
|
27417
|
+
MODELS: (includeModel) => includeModel ? `${API_BASE}/models?include_model=${encodeURIComponent(includeModel)}` : `${API_BASE}/models`,
|
|
27357
27418
|
// ADMIN_GRANTS intentionally NOT exported here — it sits under the
|
|
27358
27419
|
// unauthenticated `/internal/admin/*` surface and must not bleed into the
|
|
27359
27420
|
// public SDK. Admin dashboard hits the URL directly from its own client.
|
|
@@ -27366,6 +27427,7 @@ var ENDPOINTS = {
|
|
|
27366
27427
|
AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
|
|
27367
27428
|
CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
|
|
27368
27429
|
CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
|
|
27430
|
+
BROWSER_RUNTIME_STATUS: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-runtime/status`,
|
|
27369
27431
|
BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
|
|
27370
27432
|
BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
|
|
27371
27433
|
BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
|
|
@@ -27419,10 +27481,13 @@ var WS_EVENTS = {
|
|
|
27419
27481
|
INVITATION_REVOKED: "invitation.revoked",
|
|
27420
27482
|
ORG_JOIN_REQUEST_NEW: "org.join_request.new",
|
|
27421
27483
|
ORG_INVITE_LINK_JOINED: "org.invite_link.joined",
|
|
27484
|
+
ORG_MEMBER_REMOVED: "org.member.removed",
|
|
27422
27485
|
AGENT_CONFIG_UPDATE: "agent_config.update",
|
|
27423
27486
|
PRESENCE_UPDATE: "presence.update",
|
|
27424
27487
|
WIKI_CHANGESET_CREATED: "wiki.changeset.created",
|
|
27425
27488
|
WIKI_CHANGESET_UPDATED: "wiki.changeset.updated",
|
|
27489
|
+
WIKI_DELETED: "wiki.deleted",
|
|
27490
|
+
WIKI_RESTORED: "wiki.restored",
|
|
27426
27491
|
COMMENT_CREATED: "comment.created",
|
|
27427
27492
|
COMMENT_UPDATED: "comment.updated",
|
|
27428
27493
|
COMMENT_DELETED: "comment.deleted",
|
|
@@ -27450,6 +27515,7 @@ var WS_EVENTS = {
|
|
|
27450
27515
|
MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
|
|
27451
27516
|
MACHINE_UPDATE: "machine.update",
|
|
27452
27517
|
MACHINE_CONFIG_UPDATED: "machine.config.updated",
|
|
27518
|
+
MACHINE_AGENT_CONFIG_UPDATED: "machine.agent_config.updated",
|
|
27453
27519
|
MACHINE_CLIP_SYNC: "machine.clip.sync",
|
|
27454
27520
|
MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
|
|
27455
27521
|
MACHINE_BROWSER_PROFILE_VIEWER: "machine.browser_profile.viewer",
|
|
@@ -27789,6 +27855,13 @@ var ParallClient = class _ParallClient {
|
|
|
27789
27855
|
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS(orgId));
|
|
27790
27856
|
return res.data;
|
|
27791
27857
|
}
|
|
27858
|
+
/** User IDs of soft-removed (former) org members — for marking their avatar /
|
|
27859
|
+
* name as "left" where dormant relations still surface them (DMs, task
|
|
27860
|
+
* assignees, message history). */
|
|
27861
|
+
async getFormerMemberIds(orgId) {
|
|
27862
|
+
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_FORMER(orgId));
|
|
27863
|
+
return res.user_ids ?? [];
|
|
27864
|
+
}
|
|
27792
27865
|
async getTeams(orgId) {
|
|
27793
27866
|
const res = await this.request("GET", ENDPOINTS.TEAMS(orgId));
|
|
27794
27867
|
return res.data;
|
|
@@ -28270,26 +28343,32 @@ var ParallClient = class _ParallClient {
|
|
|
28270
28343
|
const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIPS);
|
|
28271
28344
|
return res.data;
|
|
28272
28345
|
}
|
|
28273
|
-
/** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine.
|
|
28346
|
+
/** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine.
|
|
28347
|
+
* Returns the daemon DTO (carries proxy_password for bb-browser replay). */
|
|
28274
28348
|
async listMachineBrowserProfiles() {
|
|
28275
28349
|
const res = await this.request("GET", ENDPOINTS.MACHINES_ME_BROWSER_PROFILES);
|
|
28276
28350
|
return res.data;
|
|
28277
28351
|
}
|
|
28278
28352
|
/** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
|
|
28279
|
-
async reportBrowserProfileStatus(profileId, status, errorMsg) {
|
|
28353
|
+
async reportBrowserProfileStatus(profileId, status, errorMsg, generation) {
|
|
28280
28354
|
await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
|
|
28281
28355
|
status,
|
|
28282
|
-
...errorMsg ? { error_msg: errorMsg } : {}
|
|
28356
|
+
...errorMsg ? { error_msg: errorMsg } : {},
|
|
28357
|
+
...generation !== void 0 ? { generation } : {}
|
|
28283
28358
|
});
|
|
28284
28359
|
}
|
|
28285
28360
|
/**
|
|
28286
28361
|
* `POST /machines/me/health` — bump the Machine's `updated_at` to now and
|
|
28287
|
-
* report daemon state. The daemon
|
|
28288
|
-
*
|
|
28362
|
+
* report daemon state. The daemon calls this on startup and again whenever
|
|
28363
|
+
* periodic runtime re-detection produces a CHANGED result (there is no
|
|
28364
|
+
* fixed-cadence keepalive loop today — steady state posts nothing). All
|
|
28289
28365
|
* fields are optional and only persisted when changed:
|
|
28290
28366
|
* - `daemonVersion` — the running bundle/launcher version.
|
|
28291
28367
|
* - `selfUpdateCapable` — whether the daemon can act on a machine.update
|
|
28292
28368
|
* signal (true under a service manager, false for bare `npx` foreground).
|
|
28369
|
+
* - `detectedRuntimes` — runtime CLIs found on the host. Omitted = no
|
|
28370
|
+
* report this beat (server keeps the stored value); [] = detection ran
|
|
28371
|
+
* and found nothing (server clears to empty).
|
|
28293
28372
|
*/
|
|
28294
28373
|
async postMachineHeartbeat(opts) {
|
|
28295
28374
|
const body = {};
|
|
@@ -28297,6 +28376,8 @@ var ParallClient = class _ParallClient {
|
|
|
28297
28376
|
body.daemon_version = opts.daemonVersion;
|
|
28298
28377
|
if (opts?.selfUpdateCapable !== void 0)
|
|
28299
28378
|
body.self_update_capable = opts.selfUpdateCapable;
|
|
28379
|
+
if (opts?.detectedRuntimes !== void 0)
|
|
28380
|
+
body.detected_runtimes = opts.detectedRuntimes;
|
|
28300
28381
|
return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
|
|
28301
28382
|
}
|
|
28302
28383
|
async reportAgentWorkspaceState(agentId, state) {
|
|
@@ -28615,6 +28696,59 @@ var ParallClient = class _ParallClient {
|
|
|
28615
28696
|
async deleteExternalConnection(orgId, connectionId) {
|
|
28616
28697
|
return this.request("DELETE", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
28617
28698
|
}
|
|
28699
|
+
// ---- External IM channel (org-scoped) ----
|
|
28700
|
+
async createChannelConnection(orgId, input) {
|
|
28701
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTIONS(orgId), input);
|
|
28702
|
+
}
|
|
28703
|
+
async listChannelConnections(orgId) {
|
|
28704
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTIONS(orgId));
|
|
28705
|
+
}
|
|
28706
|
+
async getChannelConnection(orgId, connectionId) {
|
|
28707
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
28708
|
+
}
|
|
28709
|
+
async updateChannelConnection(orgId, connectionId, patch) {
|
|
28710
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId), patch);
|
|
28711
|
+
}
|
|
28712
|
+
async archiveChannelConnection(orgId, connectionId) {
|
|
28713
|
+
return this.request("DELETE", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
28714
|
+
}
|
|
28715
|
+
async deliverChannelCredentials(orgId, connectionId, credentials) {
|
|
28716
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_CREDENTIALS(orgId, connectionId), credentials);
|
|
28717
|
+
}
|
|
28718
|
+
async regenerateChannelIngressToken(orgId, connectionId) {
|
|
28719
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId));
|
|
28720
|
+
}
|
|
28721
|
+
/** Start a Feishu one-click provisioning session (device flow QR). */
|
|
28722
|
+
async initiateChannelProvisioning(orgId, input) {
|
|
28723
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
|
|
28724
|
+
}
|
|
28725
|
+
/**
|
|
28726
|
+
* Lazy status poll — server-side this may forward one provider poll, so
|
|
28727
|
+
* call it at the session's `poll_interval_seconds` cadence, not faster.
|
|
28728
|
+
*/
|
|
28729
|
+
async getChannelProvisioningSession(orgId, sessionId) {
|
|
28730
|
+
return this.request("GET", ENDPOINTS.CHANNEL_PROVISIONING_SESSION(orgId, sessionId));
|
|
28731
|
+
}
|
|
28732
|
+
async cancelChannelProvisioning(orgId, sessionId) {
|
|
28733
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING_CANCEL(orgId, sessionId));
|
|
28734
|
+
}
|
|
28735
|
+
async listChannelConversations(orgId, connectionId) {
|
|
28736
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
|
|
28737
|
+
}
|
|
28738
|
+
async getChannelConversation(orgId, conversationId) {
|
|
28739
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION(orgId, conversationId));
|
|
28740
|
+
}
|
|
28741
|
+
async listChannelConversationMessages(orgId, conversationId, limit) {
|
|
28742
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION_MESSAGES(orgId, conversationId), void 0, { limit });
|
|
28743
|
+
}
|
|
28744
|
+
async setChannelConversationSession(orgId, conversationId, agentSessionId) {
|
|
28745
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONVERSATION_SESSION(orgId, conversationId), {
|
|
28746
|
+
agent_session_id: agentSessionId
|
|
28747
|
+
});
|
|
28748
|
+
}
|
|
28749
|
+
async getChannelMessage(orgId, messageId) {
|
|
28750
|
+
return this.request("GET", ENDPOINTS.CHANNEL_MESSAGE(orgId, messageId));
|
|
28751
|
+
}
|
|
28618
28752
|
async getExternalTriggerSchema(orgId, connectionId) {
|
|
28619
28753
|
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_SCHEMA(orgId, connectionId));
|
|
28620
28754
|
}
|
|
@@ -28656,6 +28790,23 @@ var ParallClient = class _ParallClient {
|
|
|
28656
28790
|
async getWiki(orgId, wikiId) {
|
|
28657
28791
|
return this.request("GET", ENDPOINTS.WIKI(orgId, wikiId));
|
|
28658
28792
|
}
|
|
28793
|
+
/** Soft-delete an entire wiki (org owner only; the default wiki is
|
|
28794
|
+
* protected → 403 WIKI_PROTECTED). Returns the deleted wiki. Recoverable
|
|
28795
|
+
* via restoreWiki within the retention window. */
|
|
28796
|
+
async deleteWiki(orgId, wikiId) {
|
|
28797
|
+
return this.request("DELETE", ENDPOINTS.WIKI(orgId, wikiId));
|
|
28798
|
+
}
|
|
28799
|
+
/** Restore a soft-deleted wiki (org owner only). 409 WIKI_PURGE_STARTED once
|
|
28800
|
+
* purge has been claimed (no longer restorable), or 404 once the row is gone.
|
|
28801
|
+
* Returns the restored wiki. */
|
|
28802
|
+
async restoreWiki(orgId, wikiId) {
|
|
28803
|
+
return this.request("POST", ENDPOINTS.WIKI_RESTORE(orgId, wikiId));
|
|
28804
|
+
}
|
|
28805
|
+
/** Recycle bin — list soft-deleted wikis for the org (owner only). */
|
|
28806
|
+
async getDeletedWikis(orgId) {
|
|
28807
|
+
const res = await this.request("GET", ENDPOINTS.WIKIS_DELETED(orgId));
|
|
28808
|
+
return res.data;
|
|
28809
|
+
}
|
|
28659
28810
|
async getWikiTree(orgId, wikiId, params) {
|
|
28660
28811
|
return this.request("GET", ENDPOINTS.WIKI_TREE(orgId, wikiId), void 0, params);
|
|
28661
28812
|
}
|
|
@@ -28689,6 +28840,15 @@ var ParallClient = class _ParallClient {
|
|
|
28689
28840
|
blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
28690
28841
|
return blob;
|
|
28691
28842
|
}
|
|
28843
|
+
/**
|
|
28844
|
+
* Copy one wiki file to another path as an independent snapshot (no sync).
|
|
28845
|
+
* Used to "share a private file out": copy a file from the caller's personal
|
|
28846
|
+
* namespace (`users/{userId}/…`) into the public wiki, leaving the original
|
|
28847
|
+
* untouched. 409 `FILE_EXISTS` if `dest_path` already exists.
|
|
28848
|
+
*/
|
|
28849
|
+
async copyWikiFile(orgId, wikiId, req) {
|
|
28850
|
+
return this.request("POST", ENDPOINTS.WIKI_COPY(orgId, wikiId), req);
|
|
28851
|
+
}
|
|
28692
28852
|
async getWikiNodeSections(orgId, wikiId, params) {
|
|
28693
28853
|
return this.request("GET", ENDPOINTS.WIKI_NODE_SECTIONS(orgId, wikiId), void 0, params);
|
|
28694
28854
|
}
|
|
@@ -28857,6 +29017,16 @@ var ParallClient = class _ParallClient {
|
|
|
28857
29017
|
async getBacklinks(orgId, params) {
|
|
28858
29018
|
return this.request("GET", ENDPOINTS.REFS_BACKLINKS(orgId), void 0, params);
|
|
28859
29019
|
}
|
|
29020
|
+
/**
|
|
29021
|
+
* Bounded multi-hop walk of the prll:// reference graph around `uri`. `uri`
|
|
29022
|
+
* must be an entity-level prll:// URI — a refined URI (path/query/fragment) is
|
|
29023
|
+
* rejected with 400 UNSUPPORTED_REFINED_URI. `depth` is clamped server-side to
|
|
29024
|
+
* [1, 4]; breadth (node/edge counts) is capped server-side and surfaced via
|
|
29025
|
+
* `truncated`. ACL is applied per hop (chat membership + wiki path scope).
|
|
29026
|
+
*/
|
|
29027
|
+
async getRefsGraph(orgId, params) {
|
|
29028
|
+
return this.request("GET", ENDPOINTS.REFS_GRAPH(orgId), void 0, params);
|
|
29029
|
+
}
|
|
28860
29030
|
async checkBrokenRefs(orgId) {
|
|
28861
29031
|
return this.request("GET", ENDPOINTS.REFS_CHECK(orgId));
|
|
28862
29032
|
}
|
|
@@ -28952,6 +29122,19 @@ var ParallClient = class _ParallClient {
|
|
|
28952
29122
|
const resp = await this.request("GET", ENDPOINTS.COMPUTE_PRICING());
|
|
28953
29123
|
return resp.data;
|
|
28954
29124
|
}
|
|
29125
|
+
/** Runtime capability table (public) — SSOT for the create/settings interlock. */
|
|
29126
|
+
async getRuntimes() {
|
|
29127
|
+
const resp = await this.request("GET", ENDPOINTS.RUNTIMES());
|
|
29128
|
+
return resp.data;
|
|
29129
|
+
}
|
|
29130
|
+
/**
|
|
29131
|
+
* Platform model catalog (public) — DB-backed, replaces the compile-time
|
|
29132
|
+
* PLATFORM_MODELS constant. Pass includeModel to keep an agent's pinned
|
|
29133
|
+
* hidden legacy model representable (settings picker).
|
|
29134
|
+
*/
|
|
29135
|
+
async getModels(includeModel) {
|
|
29136
|
+
return this.request("GET", ENDPOINTS.MODELS(includeModel));
|
|
29137
|
+
}
|
|
28955
29138
|
// ---- Clips ----
|
|
28956
29139
|
async listClips(orgId) {
|
|
28957
29140
|
const resp = await this.request("GET", ENDPOINTS.CLIPS(orgId));
|
|
@@ -28996,6 +29179,11 @@ var ParallClient = class _ParallClient {
|
|
|
28996
29179
|
const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
|
|
28997
29180
|
return resp.data;
|
|
28998
29181
|
}
|
|
29182
|
+
/** Deployment-wide hosted browser runtime availability — drives whether the
|
|
29183
|
+
* create UI offers the platform-hosted placement. Fail-closed server-side. */
|
|
29184
|
+
async getBrowserRuntimeStatus(orgId) {
|
|
29185
|
+
return this.request("GET", ENDPOINTS.BROWSER_RUNTIME_STATUS(orgId));
|
|
29186
|
+
}
|
|
28999
29187
|
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
29000
29188
|
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
29001
29189
|
* carrying a per-viewer `can_open` control hint. */
|
|
@@ -29655,6 +29843,9 @@ function resolveStepTarget(event) {
|
|
|
29655
29843
|
if (event.type === "external_trigger" || event.targetId.startsWith("xtr_")) {
|
|
29656
29844
|
return { target_type: "external_trigger", target_id: event.targetId };
|
|
29657
29845
|
}
|
|
29846
|
+
if (event.type === "channel_message" || event.targetId.startsWith("chv_")) {
|
|
29847
|
+
return { target_type: "channel_conversation", target_id: event.targetId };
|
|
29848
|
+
}
|
|
29658
29849
|
if (event.type === "wiki_comment") {
|
|
29659
29850
|
return { target_type: "wiki", target_id: event.targetId || void 0 };
|
|
29660
29851
|
}
|
|
@@ -29698,6 +29889,9 @@ var ParallAgentGateway = class {
|
|
|
29698
29889
|
opts;
|
|
29699
29890
|
chatInfoMap = /* @__PURE__ */ new Map();
|
|
29700
29891
|
dispatchedTasks = /* @__PURE__ */ new Set();
|
|
29892
|
+
// connection id → provider alias, for channel_message prompt labeling
|
|
29893
|
+
// (stable mapping; avoids one connection fetch per inbound message).
|
|
29894
|
+
channelConnectionProviders = /* @__PURE__ */ new Map();
|
|
29701
29895
|
dispatchedMessages = /* @__PURE__ */ new Set();
|
|
29702
29896
|
forkStates = /* @__PURE__ */ new Map();
|
|
29703
29897
|
dispatchState = {
|
|
@@ -29871,6 +30065,18 @@ var ParallAgentGateway = class {
|
|
|
29871
30065
|
} catch (err) {
|
|
29872
30066
|
this.opts.log?.error(`external trigger dispatch failed for ${data.source_id}: ${String(err)}`);
|
|
29873
30067
|
}
|
|
30068
|
+
} else if (data.event_type === "channel_message") {
|
|
30069
|
+
if (!data.source_id)
|
|
30070
|
+
return;
|
|
30071
|
+
try {
|
|
30072
|
+
const dispatched = await this.fetchAndHandleChannelMessage(data.source_id);
|
|
30073
|
+
if (dispatched) {
|
|
30074
|
+
this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {
|
|
30075
|
+
});
|
|
30076
|
+
}
|
|
30077
|
+
} catch (err) {
|
|
30078
|
+
this.opts.log?.error(`channel message dispatch failed for ${data.source_id}: ${String(err)}`);
|
|
30079
|
+
}
|
|
29874
30080
|
} else if (data.event_type === "approval_decided") {
|
|
29875
30081
|
if (!data.source_id)
|
|
29876
30082
|
return;
|
|
@@ -29949,12 +30155,17 @@ var ParallAgentGateway = class {
|
|
|
29949
30155
|
target_type: target.target_type,
|
|
29950
30156
|
target_id: target.target_id,
|
|
29951
30157
|
content: {
|
|
29952
|
-
trigger_type: event.type === "task" ? "task_assign" : event.type === "task_comment" ? "task_comment" : event.type === "wiki_comment" ? "wiki_comment" : event.type === "schedule" ? "schedule_fire" : event.type === "external_trigger" ? "external_trigger" : event.type === "approval" ? "approval_decided" : "mention",
|
|
30158
|
+
trigger_type: event.type === "task" ? "task_assign" : event.type === "task_comment" ? "task_comment" : event.type === "wiki_comment" ? "wiki_comment" : event.type === "schedule" ? "schedule_fire" : event.type === "external_trigger" ? "external_trigger" : event.type === "channel_message" ? "channel_message" : event.type === "approval" ? "approval_decided" : "mention",
|
|
29953
30159
|
trigger_ref: event.type === "task" ? { task_id: event.targetId } : event.type === "task_comment" ? { comment_id: event.messageId, task_id: event.targetId } : event.type === "wiki_comment" ? { comment_id: event.messageId, target_uri: event.replyTargetUri } : event.type === "schedule" ? { schedule_id: event.targetId, run_id: event.messageId } : event.type === "external_trigger" ? {
|
|
29954
30160
|
trigger_id: event.targetId,
|
|
29955
30161
|
run_id: event.messageId,
|
|
29956
30162
|
connection_id: event.externalConnectionId,
|
|
29957
30163
|
ingress_event_id: event.externalIngressEventId
|
|
30164
|
+
} : event.type === "channel_message" ? {
|
|
30165
|
+
conversation_id: event.targetId,
|
|
30166
|
+
channel_message_id: event.messageId,
|
|
30167
|
+
provider: event.channelProvider,
|
|
30168
|
+
external_conversation_id: event.channelExternalConversationId
|
|
29958
30169
|
} : event.type === "approval" ? { approval_id: event.messageId } : { message_id: event.messageId },
|
|
29959
30170
|
sender_id: event.senderId,
|
|
29960
30171
|
sender_name: event.senderName,
|
|
@@ -30205,7 +30416,15 @@ var ParallAgentGateway = class {
|
|
|
30205
30416
|
context: dispatchContext
|
|
30206
30417
|
})) {
|
|
30207
30418
|
if (runtimeEvent.type === "runtime_session") {
|
|
30419
|
+
const priorAgentSessionId = binding?.agentSessionId;
|
|
30208
30420
|
binding = await this.bindRuntimeSession(sessionKey, runtimeEvent, contextFilePath);
|
|
30421
|
+
if (event.targetType === "channel_conversation" && binding.agentSessionId !== priorAgentSessionId) {
|
|
30422
|
+
try {
|
|
30423
|
+
await this.opts.client.setChannelConversationSession(this.opts.config.org_id, event.targetId, binding.agentSessionId);
|
|
30424
|
+
} catch (err) {
|
|
30425
|
+
this.opts.log?.warn(`failed to record session mapping for channel conversation ${event.targetId}: ${String(err)}`);
|
|
30426
|
+
}
|
|
30427
|
+
}
|
|
30209
30428
|
if (!inputStepsCreated) {
|
|
30210
30429
|
if (earlierEvents.length > 0) {
|
|
30211
30430
|
await this.createInputStepsForEarlierEvents(binding.agentSessionId, earlierEvents);
|
|
@@ -31008,6 +31227,75 @@ var ParallAgentGateway = class {
|
|
|
31008
31227
|
return true;
|
|
31009
31228
|
return this.handleExternalTriggerRun(run);
|
|
31010
31229
|
}
|
|
31230
|
+
// fetchAndHandleChannelMessage resolves a channel_message dispatch to its
|
|
31231
|
+
// durable ChannelMessage + conversation and hands it to the inbound
|
|
31232
|
+
// pipeline. targetId = the ChannelConversation id, so per-conversation
|
|
31233
|
+
// multi-turn continuity rides the same per-target session mechanics as
|
|
31234
|
+
// chats. Design: docs/engineering-design/external-im-channel-design.md.
|
|
31235
|
+
async fetchAndHandleChannelMessage(messageId) {
|
|
31236
|
+
if (this.shuttingDown)
|
|
31237
|
+
return false;
|
|
31238
|
+
const claimKey = `channel_message:${messageId}`;
|
|
31239
|
+
if (!this.tryClaimMessage(claimKey))
|
|
31240
|
+
return false;
|
|
31241
|
+
let msg = null;
|
|
31242
|
+
let conv = null;
|
|
31243
|
+
try {
|
|
31244
|
+
msg = await this.opts.client.getChannelMessage(this.opts.config.org_id, messageId);
|
|
31245
|
+
conv = await this.opts.client.getChannelConversation(this.opts.config.org_id, msg.conversation_id);
|
|
31246
|
+
} catch (err) {
|
|
31247
|
+
const status = err?.status;
|
|
31248
|
+
if (status === 404) {
|
|
31249
|
+
this.opts.log?.warn(`channel message ${messageId} not accessible (404), acking stale dispatch`);
|
|
31250
|
+
return true;
|
|
31251
|
+
}
|
|
31252
|
+
this.dispatchedMessages.delete(claimKey);
|
|
31253
|
+
this.opts.log?.warn(`channel message fetch failed for ${messageId}, leaving pending: ${String(err)}`);
|
|
31254
|
+
return false;
|
|
31255
|
+
}
|
|
31256
|
+
if (!msg || !conv) {
|
|
31257
|
+
return true;
|
|
31258
|
+
}
|
|
31259
|
+
this.opts.log?.info(`channel message: ${msg.id} (conversation ${conv.id})`);
|
|
31260
|
+
let provider = this.channelConnectionProviders.get(conv.connection_id);
|
|
31261
|
+
if (!provider) {
|
|
31262
|
+
try {
|
|
31263
|
+
const connection = await this.opts.client.getChannelConnection(this.opts.config.org_id, conv.connection_id);
|
|
31264
|
+
provider = connection.provider;
|
|
31265
|
+
this.channelConnectionProviders.set(conv.connection_id, provider);
|
|
31266
|
+
} catch {
|
|
31267
|
+
provider = void 0;
|
|
31268
|
+
}
|
|
31269
|
+
}
|
|
31270
|
+
const event = {
|
|
31271
|
+
type: "channel_message",
|
|
31272
|
+
targetId: conv.id,
|
|
31273
|
+
targetName: conv.external_user_name || conv.external_conversation_id,
|
|
31274
|
+
targetType: "channel_conversation",
|
|
31275
|
+
senderId: msg.external_user_id || "external",
|
|
31276
|
+
senderName: msg.external_user_name || msg.external_user_id || "external user",
|
|
31277
|
+
messageId: msg.id,
|
|
31278
|
+
body: msg.text,
|
|
31279
|
+
sentAt: msg.received_at,
|
|
31280
|
+
channelProvider: provider,
|
|
31281
|
+
channelConversationType: conv.conversation_type || void 0,
|
|
31282
|
+
channelExternalConversationId: conv.external_conversation_id,
|
|
31283
|
+
channelExternalMessageId: msg.external_message_id,
|
|
31284
|
+
ackSourceType: "channel_message",
|
|
31285
|
+
ackSourceId: msg.id
|
|
31286
|
+
};
|
|
31287
|
+
let dispatched;
|
|
31288
|
+
try {
|
|
31289
|
+
dispatched = await this.handleInboundEvent(event);
|
|
31290
|
+
} catch (err) {
|
|
31291
|
+
this.dispatchedMessages.delete(claimKey);
|
|
31292
|
+
throw err;
|
|
31293
|
+
}
|
|
31294
|
+
if (!dispatched) {
|
|
31295
|
+
this.dispatchedMessages.delete(claimKey);
|
|
31296
|
+
}
|
|
31297
|
+
return dispatched;
|
|
31298
|
+
}
|
|
31011
31299
|
async handleExternalTriggerRun(run) {
|
|
31012
31300
|
if (this.shuttingDown)
|
|
31013
31301
|
return false;
|
|
@@ -31159,6 +31447,8 @@ var ParallAgentGateway = class {
|
|
|
31159
31447
|
dispatched = await this.fetchAndHandleScheduleFire(item.source_id, item.actor_id);
|
|
31160
31448
|
} else if (item.event_type === "external_trigger" && item.source_id) {
|
|
31161
31449
|
dispatched = await this.fetchAndHandleExternalTriggerRun(item.source_id);
|
|
31450
|
+
} else if (item.event_type === "channel_message" && item.source_id) {
|
|
31451
|
+
dispatched = await this.fetchAndHandleChannelMessage(item.source_id);
|
|
31162
31452
|
} else if (item.event_type === "approval_decided" && item.source_id) {
|
|
31163
31453
|
dispatched = await this.fetchAndHandleApprovalDecided(item.source_id, item.actor_id, item.chat_id ?? null);
|
|
31164
31454
|
} else if (item.event_type === "message" && item.source_id && item.chat_id) {
|
|
@@ -31356,6 +31646,9 @@ function resolveRuntimeModel(isOperatorOverride, platformModel, configModel) {
|
|
|
31356
31646
|
const operatorOverride = isOperatorOverride ? platformModel : null;
|
|
31357
31647
|
return operatorOverride ?? configModel ?? platformModel ?? void 0;
|
|
31358
31648
|
}
|
|
31649
|
+
function deriveModelIsPin(defaults, profile) {
|
|
31650
|
+
return defaults.modelIsPin !== void 0 ? defaults.modelIsPin : isPlatformModelOverride(profile);
|
|
31651
|
+
}
|
|
31359
31652
|
var CACHE_FILENAME = "parall-platform-config.json";
|
|
31360
31653
|
var SUPPORTED_SCHEMA_VERSION = 1;
|
|
31361
31654
|
function cachePath(stateDir) {
|
|
@@ -31373,6 +31666,7 @@ function saveCache(stateDir, response) {
|
|
|
31373
31666
|
const cached = {
|
|
31374
31667
|
version: response.version,
|
|
31375
31668
|
config: response.config,
|
|
31669
|
+
modelIsPin: response.model_is_pin,
|
|
31376
31670
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
31377
31671
|
};
|
|
31378
31672
|
const filePath = cachePath(stateDir);
|
|
@@ -31383,23 +31677,27 @@ function saveCache(stateDir, response) {
|
|
|
31383
31677
|
}
|
|
31384
31678
|
function runtimeModelName(canonicalModel, runtimeType, config) {
|
|
31385
31679
|
const runtime = runtimeType?.trim();
|
|
31386
|
-
if (!runtime || runtime === "openclaw")
|
|
31680
|
+
if (!runtime || runtime === "openclaw" || runtime === "hermes")
|
|
31387
31681
|
return canonicalModel;
|
|
31388
31682
|
const models = config.models ?? {};
|
|
31389
31683
|
const providers = models.providers ?? {};
|
|
31390
31684
|
const parall = providers.parall ?? {};
|
|
31391
31685
|
const catalog = Array.isArray(parall.models) ? parall.models : [];
|
|
31392
31686
|
const match = catalog.find((model) => model.id === canonicalModel);
|
|
31393
|
-
|
|
31687
|
+
if (!match)
|
|
31688
|
+
return null;
|
|
31689
|
+
const runtimeNames = match.runtime_names ?? {};
|
|
31394
31690
|
const runtimeName = runtimeNames[runtime];
|
|
31395
|
-
|
|
31691
|
+
if (typeof runtimeName === "string" && runtimeName)
|
|
31692
|
+
return runtimeName;
|
|
31693
|
+
return canonicalModel;
|
|
31396
31694
|
}
|
|
31397
31695
|
function extractDefaults(config, runtimeType) {
|
|
31398
31696
|
const agents = config.agents ?? {};
|
|
31399
31697
|
const defaults = agents.defaults ?? {};
|
|
31400
31698
|
let model = null;
|
|
31401
31699
|
if (typeof defaults.model === "string" && defaults.model) {
|
|
31402
|
-
const canonicalModel = defaults.model.replace(/^parall\//, "");
|
|
31700
|
+
const canonicalModel = defaults.model.replace(/^parall-anthropic\//, "").replace(/^parall\//, "");
|
|
31403
31701
|
model = runtimeModelName(canonicalModel, runtimeType, config);
|
|
31404
31702
|
}
|
|
31405
31703
|
let thinkingEffort = null;
|
|
@@ -31411,13 +31709,20 @@ function extractDefaults(config, runtimeType) {
|
|
|
31411
31709
|
function createPlatformConfigManager(opts) {
|
|
31412
31710
|
const { client, stateDir, runtimeType, log: log2 } = opts;
|
|
31413
31711
|
let cachedVersion;
|
|
31414
|
-
let currentDefaults = {
|
|
31712
|
+
let currentDefaults = {
|
|
31713
|
+
model: null,
|
|
31714
|
+
thinkingEffort: null,
|
|
31715
|
+
modelIsPin: void 0
|
|
31716
|
+
};
|
|
31415
31717
|
let currentRawConfig = null;
|
|
31416
31718
|
const cached = loadCache(stateDir);
|
|
31417
31719
|
if (cached) {
|
|
31418
|
-
cachedVersion = cached.version;
|
|
31720
|
+
cachedVersion = cached.modelIsPin === void 0 ? void 0 : cached.version;
|
|
31419
31721
|
currentRawConfig = cached.config;
|
|
31420
|
-
currentDefaults =
|
|
31722
|
+
currentDefaults = {
|
|
31723
|
+
...extractDefaults(cached.config, runtimeType),
|
|
31724
|
+
modelIsPin: cached.modelIsPin
|
|
31725
|
+
};
|
|
31421
31726
|
}
|
|
31422
31727
|
return {
|
|
31423
31728
|
async fetch() {
|
|
@@ -31443,7 +31748,10 @@ function createPlatformConfigManager(opts) {
|
|
|
31443
31748
|
saveCache(stateDir, fresh);
|
|
31444
31749
|
cachedVersion = fresh.version;
|
|
31445
31750
|
currentRawConfig = fresh.config;
|
|
31446
|
-
currentDefaults =
|
|
31751
|
+
currentDefaults = {
|
|
31752
|
+
...extractDefaults(fresh.config, runtimeType),
|
|
31753
|
+
modelIsPin: fresh.model_is_pin
|
|
31754
|
+
};
|
|
31447
31755
|
return currentDefaults;
|
|
31448
31756
|
},
|
|
31449
31757
|
current() {
|
|
@@ -31526,22 +31834,69 @@ parall machines logs prll://mch_xxx --lines 100
|
|
|
31526
31834
|
\`\`\`bash
|
|
31527
31835
|
parall chats list # List all chats
|
|
31528
31836
|
parall messages list prll://cht_xxx # Read chat message history
|
|
31837
|
+
parall messages list prll://cht_xxx --since 2026-01-01 # Only messages at/after a date (RFC3339 or YYYY-MM-DD)
|
|
31529
31838
|
\`\`\`
|
|
31530
31839
|
|
|
31840
|
+
## Org-Context Search
|
|
31841
|
+
|
|
31842
|
+
Before deciding or starting non-trivial work, search the org's real history \u2014
|
|
31843
|
+
past discussions, decisions, tasks, and wiki notes \u2014 so you don't re-litigate
|
|
31844
|
+
settled questions or repeat known mistakes. This searches live org data
|
|
31845
|
+
(semantic + keyword), not a local copy, and is permission-filtered to what you
|
|
31846
|
+
can see.
|
|
31847
|
+
|
|
31848
|
+
\`\`\`bash
|
|
31849
|
+
# Semantic + keyword search across messages, tasks, and wiki
|
|
31850
|
+
parall search "auth v5 upgrade"
|
|
31851
|
+
|
|
31852
|
+
# Restrict entity types (m=message, t=task, w=wiki). --channel narrows the
|
|
31853
|
+
# MESSAGE hits to one chat (tasks/wiki are unaffected by it).
|
|
31854
|
+
parall search "auth v5 upgrade" --types m,w --channel prll://cht_eng
|
|
31855
|
+
|
|
31856
|
+
# Time-box to recent activity (RFC3339 or YYYY-MM-DD). Narrows messages + tasks;
|
|
31857
|
+
# wiki is always matched by relevance (the index has no authored timestamp).
|
|
31858
|
+
parall search "auth v5 upgrade" --since 2026-01-01
|
|
31859
|
+
|
|
31860
|
+
# Narrow wiki hits to a frontmatter document type
|
|
31861
|
+
parall search "deploy steps" --types w --wiki-type Runbook
|
|
31862
|
+
\`\`\`
|
|
31863
|
+
|
|
31864
|
+
Even with zero curated notes, the raw message + task history is searchable \u2014 the
|
|
31865
|
+
original discussion and its approval/rejection IS the precedent.
|
|
31866
|
+
|
|
31531
31867
|
## Sending Messages
|
|
31532
31868
|
|
|
31533
31869
|
Each \`[Event: message.new]\` includes \`[Chat: ... (prll://cht_xxx)]\` \u2014 use that chat URI to reply.
|
|
31534
31870
|
|
|
31871
|
+
> **How you pass the message body matters \u2014 your command runs through a shell.**
|
|
31872
|
+
> Inside double quotes the shell expands \`$\`, backticks, and \`$(...)\` *before*
|
|
31873
|
+
> the CLI sees them: \`--text "That costs $1,000"\` sends \`That costs ,000\`, and
|
|
31874
|
+
> \`--text "$(cmd)"\` runs \`cmd\`. Single quotes instead break on apostrophes
|
|
31875
|
+
> (\`I'm\`, \`don't\`). So do **not** wrap real message content in quotes \u2014 pass it
|
|
31876
|
+
> through \`--text-file\` (a written file, or a quoted heredoc \`<<'EOF'\` that
|
|
31877
|
+
> disables all expansion). Reserve \`--text "..."\` for short literals with no
|
|
31878
|
+
> \`$\`, backtick, or apostrophe.
|
|
31879
|
+
|
|
31535
31880
|
\`\`\`bash
|
|
31536
|
-
#
|
|
31537
|
-
|
|
31881
|
+
# One-off reply \u2192 quoted heredoc into stdin. The quoted delimiter <<'EOF'
|
|
31882
|
+
# disables ALL shell expansion, so $, backticks and apostrophes pass verbatim.
|
|
31883
|
+
parall messages send prll://cht_xxx --text-file - <<'PARALL_EOF'
|
|
31884
|
+
Sure \u2014 that's $1,000, and $(whoami) stays literal. I'm on it.
|
|
31885
|
+
PARALL_EOF
|
|
31886
|
+
|
|
31887
|
+
# Longer / multi-line reply \u2192 write it with your file tool (no shell touches
|
|
31888
|
+
# the body), then point --text-file at the file.
|
|
31889
|
+
parall messages send prll://cht_xxx --text-file /tmp/reply.md
|
|
31890
|
+
|
|
31891
|
+
# Short literal with no $, backtick, or apostrophe \u2192 --text is fine.
|
|
31892
|
+
parall messages send prll://cht_xxx --text "On it"
|
|
31538
31893
|
|
|
31539
|
-
# Direct message by user URI or display name
|
|
31540
|
-
parall dm prll://usr_xxx --text
|
|
31894
|
+
# Direct message by user URI or display name (same --text-file / heredoc rules)
|
|
31895
|
+
parall dm prll://usr_xxx --text-file /tmp/reply.md
|
|
31541
31896
|
parall dm "Alice" --text "Hello"
|
|
31542
31897
|
|
|
31543
31898
|
# Thread reply
|
|
31544
|
-
parall messages send prll://cht_xxx --text
|
|
31899
|
+
parall messages send prll://cht_xxx --text-file /tmp/reply.md --thread-root-id 01JWC...
|
|
31545
31900
|
|
|
31546
31901
|
# FYI message (no response expected \u2014 the recipient sees \`[Hint: no_reply]\`)
|
|
31547
31902
|
parall messages send prll://cht_xxx --text "FYI: done" --no-reply
|
|
@@ -31573,7 +31928,9 @@ parall messages send prll://cht_xxx --attachment att_xxx --text "See attached"
|
|
|
31573
31928
|
parall dm "Alice" --file /tmp/report.pdf --text "Report attached"
|
|
31574
31929
|
\`\`\`
|
|
31575
31930
|
|
|
31576
|
-
\`--file\` and \`--attachment\` are mutually exclusive. \`--text\`
|
|
31931
|
+
\`--file\` and \`--attachment\` are mutually exclusive. A caption (\`--text\` for
|
|
31932
|
+
short literals, or \`--text-file\` for anything with \`$\`, backticks, or quotes)
|
|
31933
|
+
can be combined with either.
|
|
31577
31934
|
|
|
31578
31935
|
## Approvals
|
|
31579
31936
|
|
|
@@ -31629,6 +31986,28 @@ When a message or event references \`prll://sch_xxx\` or \`prll://srn_xxx\`, or
|
|
|
31629
31986
|
|
|
31630
31987
|
When a message or event references \`prll://xcn_xxx\`, \`prll://xin_xxx\`, \`prll://xtr_xxx\`, or \`prll://xrn_xxx\`, or when you receive \`[Event: external.trigger]\`, switch to the **parall-external-triggers** skill for the CLI commands (connections / triggers / events / runs).
|
|
31631
31988
|
|
|
31989
|
+
## References (relationship graph)
|
|
31990
|
+
|
|
31991
|
+
\`prll://\` references between entities form a graph \u2014 a message cites a task, a
|
|
31992
|
+
task cites a wiki page, and so on. Walk it to answer "what is this decision /
|
|
31993
|
+
entity connected to". All results are permission-filtered to what you can see.
|
|
31994
|
+
|
|
31995
|
+
\`\`\`bash
|
|
31996
|
+
# Resolve URIs to entity metadata (titles, status, previews)
|
|
31997
|
+
parall refs resolve prll://tsk_xxx prll://wik_xxx
|
|
31998
|
+
|
|
31999
|
+
# Single hop \u2014 who references X
|
|
32000
|
+
parall refs backlinks prll://tsk_xxx
|
|
32001
|
+
|
|
32002
|
+
# Multi-hop \u2014 the connected sub-graph around X (entity-level URI only \u2014 no
|
|
32003
|
+
# path/anchor; depth 1\u20134, default 2)
|
|
32004
|
+
parall refs graph prll://tsk_xxx --depth 2
|
|
32005
|
+
\`\`\`
|
|
32006
|
+
|
|
32007
|
+
\`refs graph\` traverses both directions (inbound + outbound) and returns \`nodes\`
|
|
32008
|
+
and \`edges\` with each node's hop \`depth\`. \`truncated: true\` means a size cap clipped
|
|
32009
|
+
the result \u2014 narrow it with a smaller \`--depth\`.
|
|
32010
|
+
|
|
31632
32011
|
CLI success output is JSON. Errors print a JSON line (\`{"error","status","code",...}\`) and, on a \`PERMISSION_DENIED\`, may add a plain-text \`Request approval:\` line \u2014 read both.
|
|
31633
32012
|
`;
|
|
31634
32013
|
|
|
@@ -34742,14 +35121,13 @@ async function main() {
|
|
|
34742
35121
|
log: agentLog
|
|
34743
35122
|
});
|
|
34744
35123
|
const platformDefaults = await configMgr.fetch();
|
|
34745
|
-
|
|
34746
|
-
let platformModelOverride = isPlatformModelOverride(me.agent_profile);
|
|
35124
|
+
const platformModelOverride = deriveModelIsPin(platformDefaults, me.agent_profile);
|
|
34747
35125
|
const resolvedModel = resolveRuntimeModel(platformModelOverride, platformDefaults.model, config.model);
|
|
34748
|
-
const resolvedEffort =
|
|
35126
|
+
const resolvedEffort = platformDefaults.thinkingEffort ?? config.reasoningEffort;
|
|
34749
35127
|
if (platformDefaults.model)
|
|
34750
|
-
agentLog.info(`platform config: model=${platformDefaults.model} \u2192 resolved=${resolvedModel ?? "cli-default"} (${platformModelOverride ? "
|
|
35128
|
+
agentLog.info(`platform config: model=${platformDefaults.model} \u2192 resolved=${resolvedModel ?? "cli-default"} (${platformModelOverride ? "pin/override" : "floor"})`);
|
|
34751
35129
|
if (platformDefaults.thinkingEffort)
|
|
34752
|
-
agentLog.info(`platform config: reasoning_effort=${platformDefaults.thinkingEffort}
|
|
35130
|
+
agentLog.info(`platform config: reasoning_effort=${platformDefaults.thinkingEffort}`);
|
|
34753
35131
|
const adapter = new CodexAppServerAdapter({
|
|
34754
35132
|
codexBin: config.codexBin,
|
|
34755
35133
|
codexHome: config.codexHome,
|
|
@@ -34763,6 +35141,22 @@ async function main() {
|
|
|
34763
35141
|
contextFilePath: mainContextFilePath,
|
|
34764
35142
|
useParallProvider
|
|
34765
35143
|
});
|
|
35144
|
+
const refreshPlatformConfig = async () => {
|
|
35145
|
+
const updated = await configMgr.fetch();
|
|
35146
|
+
let refreshedProfile;
|
|
35147
|
+
if (updated.modelIsPin === void 0) {
|
|
35148
|
+
try {
|
|
35149
|
+
refreshedProfile = (await getAgentMeWithLegacyFallback(client, config.orgId)).agent_profile;
|
|
35150
|
+
} catch (err) {
|
|
35151
|
+
agentLog.warn(`platform config refresh: legacy /agents/me fallback failed: ${String(err)}`);
|
|
35152
|
+
}
|
|
35153
|
+
}
|
|
35154
|
+
const isPin = deriveModelIsPin(updated, refreshedProfile);
|
|
35155
|
+
adapter.updateConfig({
|
|
35156
|
+
model: resolveRuntimeModel(isPin, updated.model, config.model) ?? null,
|
|
35157
|
+
reasoningEffort: updated.thinkingEffort ?? config.reasoningEffort ?? null
|
|
35158
|
+
});
|
|
35159
|
+
};
|
|
34766
35160
|
const gateway = new ParallAgentGateway({
|
|
34767
35161
|
accountId: agentUserId,
|
|
34768
35162
|
client,
|
|
@@ -34790,26 +35184,8 @@ async function main() {
|
|
|
34790
35184
|
dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
|
|
34791
35185
|
contextFilePathForSession: (sessionKey) => contextFilePathForSession(config.stateDir, sessionKey),
|
|
34792
35186
|
stepIdFilePathForSession: (sessionKey) => stepIdFilePathForSession(config.stateDir, sessionKey),
|
|
34793
|
-
onConfigUpdate:
|
|
34794
|
-
|
|
34795
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
34796
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
34797
|
-
const updated = await configMgr.fetch();
|
|
34798
|
-
adapter.updateConfig({
|
|
34799
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
34800
|
-
reasoningEffort: platformManaged ? updated.thinkingEffort ?? config.reasoningEffort : config.reasoningEffort ?? null
|
|
34801
|
-
});
|
|
34802
|
-
},
|
|
34803
|
-
onSessionReady: async () => {
|
|
34804
|
-
const refreshed = await getAgentMeWithLegacyFallback(client, config.orgId);
|
|
34805
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
34806
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
34807
|
-
const updated = await configMgr.fetch();
|
|
34808
|
-
adapter.updateConfig({
|
|
34809
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
34810
|
-
reasoningEffort: platformManaged ? updated.thinkingEffort ?? config.reasoningEffort : config.reasoningEffort ?? null
|
|
34811
|
-
});
|
|
34812
|
-
},
|
|
35187
|
+
onConfigUpdate: refreshPlatformConfig,
|
|
35188
|
+
onSessionReady: refreshPlatformConfig,
|
|
34813
35189
|
onNewSession: () => {
|
|
34814
35190
|
sessionManager.clearMainThread();
|
|
34815
35191
|
},
|