@parall/daemon 1.35.0 → 1.36.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/bundle/manifest.json +13 -9
- package/bundle/parall-browser-pod.js +40737 -0
- package/bundle/parall-claude-agent.js +472 -13
- package/bundle/parall-codex-agent.js +472 -13
- package/bundle/parall-daemon.js +351 -32
- package/dist/browser-pod.d.ts +301 -0
- package/dist/browser-pod.d.ts.map +1 -0
- package/dist/browser-pod.js +835 -0
- package/dist/clip-runtime/browser-profile-manager.d.ts +16 -0
- package/dist/clip-runtime/browser-profile-manager.d.ts.map +1 -1
- package/dist/clip-runtime/browser-profile-manager.js +17 -0
- package/dist/clip-runtime/browser-state-store.d.ts +157 -0
- package/dist/clip-runtime/browser-state-store.d.ts.map +1 -0
- package/dist/clip-runtime/browser-state-store.js +370 -0
- package/dist/clip-runtime/browser-viewer-streamer.d.ts +35 -1
- package/dist/clip-runtime/browser-viewer-streamer.d.ts.map +1 -1
- package/dist/clip-runtime/browser-viewer-streamer.js +97 -1
- package/dist/clip-runtime/clip-provider.d.ts +56 -0
- package/dist/clip-runtime/clip-provider.d.ts.map +1 -1
- package/dist/clip-runtime/clip-provider.js +141 -17
- package/dist/clip-runtime/index.d.ts +1 -0
- package/dist/clip-runtime/index.d.ts.map +1 -1
- package/dist/supervisor.d.ts +11 -1
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +38 -13
- package/package.json +11 -8
|
@@ -26647,6 +26647,25 @@ 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 === "external_trigger") {
|
|
26651
|
+
lines.push(`[Event: external.trigger]`);
|
|
26652
|
+
lines.push(`[Trigger: prll://${event.targetId}]`);
|
|
26653
|
+
lines.push(`[Run: prll://${event.messageId}]`);
|
|
26654
|
+
if (event.externalConnectionId) {
|
|
26655
|
+
const label = event.externalConnectionDisplayName ? `${sanitizeMeta(event.externalConnectionDisplayName)} (prll://${event.externalConnectionId})` : `prll://${event.externalConnectionId}`;
|
|
26656
|
+
lines.push(`[Connection: ${label}]`);
|
|
26657
|
+
}
|
|
26658
|
+
if (event.externalIngressEventId)
|
|
26659
|
+
lines.push(`[Ingress: prll://${event.externalIngressEventId}]`);
|
|
26660
|
+
if (event.attachedUri)
|
|
26661
|
+
lines.push(`[Attached: ${sanitizeMeta(event.attachedUri)}]`);
|
|
26662
|
+
if (event.externalConnectionSourceType) {
|
|
26663
|
+
lines.push(`[Source: ${sanitizeMeta(event.externalConnectionSourceType)}]`);
|
|
26664
|
+
}
|
|
26665
|
+
if (event.externalIngressEventType) {
|
|
26666
|
+
lines.push(`[External event: ${sanitizeMeta(event.externalIngressEventType)}]`);
|
|
26667
|
+
}
|
|
26668
|
+
lines.push("", event.body);
|
|
26650
26669
|
} else {
|
|
26651
26670
|
lines.push(`[Event: task.assigned]`);
|
|
26652
26671
|
const taskLabel = event.targetName ? `${event.targetName} (prll://${event.targetId})` : `prll://${event.targetId}`;
|
|
@@ -26678,6 +26697,10 @@ function buildSendMessageHint(event) {
|
|
|
26678
26697
|
if (event.targetId.startsWith("sch_")) {
|
|
26679
26698
|
return `
|
|
26680
26699
|
<system-reminder>To communicate, use the CLI: \`parall messages send\` / \`parall dm\`. Your plain text output is not delivered.</system-reminder>`;
|
|
26700
|
+
}
|
|
26701
|
+
if (event.type === "external_trigger" || event.targetId.startsWith("xtr_")) {
|
|
26702
|
+
return `
|
|
26703
|
+
<system-reminder>This external trigger is incoming-only. Your plain text output is not sent back to the external provider. To communicate in Parall, use \`parall messages send\` / \`parall dm\`; provider-specific outbound actions require a separate capability.</system-reminder>`;
|
|
26681
26704
|
}
|
|
26682
26705
|
return "";
|
|
26683
26706
|
}
|
|
@@ -27219,6 +27242,17 @@ var ENDPOINTS = {
|
|
|
27219
27242
|
SCHEDULE_CANCEL: (orgId, id) => `${API_BASE}/orgs/${orgId}/schedules/${id}/cancel`,
|
|
27220
27243
|
SCHEDULE_RUNS: (orgId, id) => `${API_BASE}/orgs/${orgId}/schedules/${id}/runs`,
|
|
27221
27244
|
SCHEDULE_RUN: (orgId, runId) => `${API_BASE}/orgs/${orgId}/schedule_runs/${runId}`,
|
|
27245
|
+
// External triggers (org-scoped incoming integration primitive)
|
|
27246
|
+
EXTERNAL_CONNECTIONS: (orgId) => `${API_BASE}/orgs/${orgId}/external-connections`,
|
|
27247
|
+
EXTERNAL_CONNECTION: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/external-connections/${connectionId}`,
|
|
27248
|
+
EXTERNAL_CONNECTION_INGRESS_TOKEN_REGENERATE: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/external-connections/${connectionId}/ingress-token/regenerate`,
|
|
27249
|
+
EXTERNAL_TRIGGER_SCHEMA: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/external-connections/${connectionId}/trigger-schema`,
|
|
27250
|
+
EXTERNAL_INGRESS_EVENTS: (orgId) => `${API_BASE}/orgs/${orgId}/external-ingress-events`,
|
|
27251
|
+
EXTERNAL_INGRESS_EVENT: (orgId, eventId) => `${API_BASE}/orgs/${orgId}/external-ingress-events/${eventId}`,
|
|
27252
|
+
EXTERNAL_TRIGGERS: (orgId) => `${API_BASE}/orgs/${orgId}/external-triggers`,
|
|
27253
|
+
EXTERNAL_TRIGGER: (orgId, triggerId) => `${API_BASE}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
27254
|
+
EXTERNAL_TRIGGER_RUNS: (orgId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs`,
|
|
27255
|
+
EXTERNAL_TRIGGER_RUN: (orgId, runId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs/${runId}`,
|
|
27222
27256
|
// Invitations (org-scoped, admin)
|
|
27223
27257
|
ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
|
|
27224
27258
|
ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
|
|
@@ -27300,6 +27334,7 @@ var ENDPOINTS = {
|
|
|
27300
27334
|
// References (org-scoped)
|
|
27301
27335
|
REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
|
|
27302
27336
|
REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
|
|
27337
|
+
REFS_GRAPH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/graph`,
|
|
27303
27338
|
REFS_CHECK: (orgId) => `${API_BASE}/orgs/${orgId}/refs/check`,
|
|
27304
27339
|
// Platform config (agent-scoped, not org-scoped)
|
|
27305
27340
|
PLATFORM_CONFIG: `${API_BASE}/agents/platform-config`,
|
|
@@ -27428,6 +27463,7 @@ var WS_EVENTS = {
|
|
|
27428
27463
|
// ts/sdk/dist/client.js
|
|
27429
27464
|
var ParallClient = class _ParallClient {
|
|
27430
27465
|
baseUrl;
|
|
27466
|
+
wikiBaseUrl;
|
|
27431
27467
|
token;
|
|
27432
27468
|
onTokenExpired;
|
|
27433
27469
|
getRefreshToken;
|
|
@@ -27479,12 +27515,22 @@ var ParallClient = class _ParallClient {
|
|
|
27479
27515
|
}
|
|
27480
27516
|
constructor(options = {}) {
|
|
27481
27517
|
this.baseUrl = options.baseUrl ?? "";
|
|
27518
|
+
this.wikiBaseUrl = options.wikiBaseUrl ?? this.baseUrl;
|
|
27482
27519
|
this.token = options.token ?? null;
|
|
27483
27520
|
this.onTokenExpired = options.onTokenExpired;
|
|
27484
27521
|
this.getRefreshToken = options.getRefreshToken;
|
|
27485
27522
|
this.setTokens = options.setTokens;
|
|
27486
27523
|
this.swimlaneName = options.swimlaneName;
|
|
27487
27524
|
}
|
|
27525
|
+
/**
|
|
27526
|
+
* Pick the origin for a request path: wiki-service base for `/wiki/v1`
|
|
27527
|
+
* endpoints, api base for everything else. The path itself (from ENDPOINTS)
|
|
27528
|
+
* is authoritative, so wiki vs api routing can't drift from how a caller
|
|
27529
|
+
* happens to invoke the client.
|
|
27530
|
+
*/
|
|
27531
|
+
baseUrlFor(path9) {
|
|
27532
|
+
return path9.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
|
|
27533
|
+
}
|
|
27488
27534
|
setToken(token) {
|
|
27489
27535
|
this.token = token;
|
|
27490
27536
|
}
|
|
@@ -27549,7 +27595,7 @@ var ParallClient = class _ParallClient {
|
|
|
27549
27595
|
if (!retried) {
|
|
27550
27596
|
await this.ensureFreshToken(path9);
|
|
27551
27597
|
}
|
|
27552
|
-
let url = `${this.
|
|
27598
|
+
let url = `${this.baseUrlFor(path9)}${path9}`;
|
|
27553
27599
|
if (query) {
|
|
27554
27600
|
const params = new URLSearchParams();
|
|
27555
27601
|
for (const [key, value] of Object.entries(query)) {
|
|
@@ -27621,7 +27667,7 @@ var ParallClient = class _ParallClient {
|
|
|
27621
27667
|
void _drop;
|
|
27622
27668
|
let res;
|
|
27623
27669
|
try {
|
|
27624
|
-
res = await fetch(`${this.
|
|
27670
|
+
res = await fetch(`${this.baseUrlFor(path9)}${path9}`, {
|
|
27625
27671
|
method,
|
|
27626
27672
|
headers,
|
|
27627
27673
|
body,
|
|
@@ -27781,6 +27827,21 @@ var ParallClient = class _ParallClient {
|
|
|
27781
27827
|
q.limit = String(params.limit);
|
|
27782
27828
|
return this.request("GET", ENDPOINTS.ORG_MEMBER_TASKS(orgId, memberId), void 0, q);
|
|
27783
27829
|
}
|
|
27830
|
+
// Auto-paginated variant of getMemberTasks: fetches ALL pending tasks
|
|
27831
|
+
// (todo + in_progress) assigned to a member, including subtasks (the
|
|
27832
|
+
// endpoint does not filter parent_id). Powers the CLI `tasks assigned`
|
|
27833
|
+
// command so an agent answering "what's on X's plate" sees the full
|
|
27834
|
+
// backlog, not just the first page.
|
|
27835
|
+
async getMemberTasksAll(orgId, memberId) {
|
|
27836
|
+
const all = [];
|
|
27837
|
+
let cursor;
|
|
27838
|
+
do {
|
|
27839
|
+
const res = await this.getMemberTasks(orgId, memberId, { cursor, limit: 100 });
|
|
27840
|
+
all.push(...res.data);
|
|
27841
|
+
cursor = res.has_more ? res.next_cursor : void 0;
|
|
27842
|
+
} while (cursor);
|
|
27843
|
+
return all;
|
|
27844
|
+
}
|
|
27784
27845
|
// ---- Invitations ----
|
|
27785
27846
|
async createInvitation(orgId, email, role) {
|
|
27786
27847
|
return this.request("POST", ENDPOINTS.ORG_INVITATIONS(orgId), { email, role });
|
|
@@ -28210,7 +28271,8 @@ var ParallClient = class _ParallClient {
|
|
|
28210
28271
|
const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIPS);
|
|
28211
28272
|
return res.data;
|
|
28212
28273
|
}
|
|
28213
|
-
/** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine.
|
|
28274
|
+
/** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine.
|
|
28275
|
+
* Returns the daemon DTO (carries proxy_password for bb-browser replay). */
|
|
28214
28276
|
async listMachineBrowserProfiles() {
|
|
28215
28277
|
const res = await this.request("GET", ENDPOINTS.MACHINES_ME_BROWSER_PROFILES);
|
|
28216
28278
|
return res.data;
|
|
@@ -28370,7 +28432,7 @@ var ParallClient = class _ParallClient {
|
|
|
28370
28432
|
* Returns null when the server responds with 304 (config unchanged).
|
|
28371
28433
|
*/
|
|
28372
28434
|
async getPlatformConfig(currentVersion) {
|
|
28373
|
-
const url = `${this.
|
|
28435
|
+
const url = `${this.baseUrlFor(ENDPOINTS.PLATFORM_CONFIG)}${ENDPOINTS.PLATFORM_CONFIG}`;
|
|
28374
28436
|
const extra = {};
|
|
28375
28437
|
if (currentVersion !== void 0) {
|
|
28376
28438
|
extra["If-None-Match"] = currentVersion;
|
|
@@ -28536,6 +28598,55 @@ var ParallClient = class _ParallClient {
|
|
|
28536
28598
|
async getScheduleRun(orgId, runId) {
|
|
28537
28599
|
return this.request("GET", ENDPOINTS.SCHEDULE_RUN(orgId, runId));
|
|
28538
28600
|
}
|
|
28601
|
+
// ---- External triggers (org-scoped) ----
|
|
28602
|
+
async createExternalConnection(orgId, input) {
|
|
28603
|
+
return this.request("POST", ENDPOINTS.EXTERNAL_CONNECTIONS(orgId), input);
|
|
28604
|
+
}
|
|
28605
|
+
async listExternalConnections(orgId, filters) {
|
|
28606
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_CONNECTIONS(orgId), void 0, filters);
|
|
28607
|
+
}
|
|
28608
|
+
async getExternalConnection(orgId, connectionId) {
|
|
28609
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
28610
|
+
}
|
|
28611
|
+
async updateExternalConnection(orgId, connectionId, patch) {
|
|
28612
|
+
return this.request("PATCH", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId), patch);
|
|
28613
|
+
}
|
|
28614
|
+
async regenerateExternalConnectionIngressToken(orgId, connectionId) {
|
|
28615
|
+
return this.request("POST", ENDPOINTS.EXTERNAL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId));
|
|
28616
|
+
}
|
|
28617
|
+
async deleteExternalConnection(orgId, connectionId) {
|
|
28618
|
+
return this.request("DELETE", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
28619
|
+
}
|
|
28620
|
+
async getExternalTriggerSchema(orgId, connectionId) {
|
|
28621
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_SCHEMA(orgId, connectionId));
|
|
28622
|
+
}
|
|
28623
|
+
async listExternalIngressEvents(orgId, filters) {
|
|
28624
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_INGRESS_EVENTS(orgId), void 0, filters);
|
|
28625
|
+
}
|
|
28626
|
+
async getExternalIngressEvent(orgId, eventId) {
|
|
28627
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_INGRESS_EVENT(orgId, eventId));
|
|
28628
|
+
}
|
|
28629
|
+
async createExternalTrigger(orgId, input) {
|
|
28630
|
+
return this.request("POST", ENDPOINTS.EXTERNAL_TRIGGERS(orgId), input);
|
|
28631
|
+
}
|
|
28632
|
+
async listExternalTriggers(orgId, filters) {
|
|
28633
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGERS(orgId), void 0, filters);
|
|
28634
|
+
}
|
|
28635
|
+
async getExternalTrigger(orgId, triggerId) {
|
|
28636
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId));
|
|
28637
|
+
}
|
|
28638
|
+
async updateExternalTrigger(orgId, triggerId, patch) {
|
|
28639
|
+
return this.request("PATCH", ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId), patch);
|
|
28640
|
+
}
|
|
28641
|
+
async deleteExternalTrigger(orgId, triggerId) {
|
|
28642
|
+
return this.request("DELETE", ENDPOINTS.EXTERNAL_TRIGGER(orgId, triggerId));
|
|
28643
|
+
}
|
|
28644
|
+
async listExternalTriggerRuns(orgId, filters) {
|
|
28645
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_RUNS(orgId), void 0, filters);
|
|
28646
|
+
}
|
|
28647
|
+
async getExternalTriggerRun(orgId, runId) {
|
|
28648
|
+
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_RUN(orgId, runId));
|
|
28649
|
+
}
|
|
28539
28650
|
// ---- Wikis (org-scoped) ----
|
|
28540
28651
|
async createWiki(orgId, data) {
|
|
28541
28652
|
return this.request("POST", ENDPOINTS.WIKIS(orgId), data);
|
|
@@ -28550,8 +28661,35 @@ var ParallClient = class _ParallClient {
|
|
|
28550
28661
|
async getWikiTree(orgId, wikiId, params) {
|
|
28551
28662
|
return this.request("GET", ENDPOINTS.WIKI_TREE(orgId, wikiId), void 0, params);
|
|
28552
28663
|
}
|
|
28664
|
+
/**
|
|
28665
|
+
* Resolve a server-returned, host-relative media URL (a wiki `signed_url`
|
|
28666
|
+
* like `/wiki/v1/signed/files?token=...`) against this client's base origin,
|
|
28667
|
+
* so it can be dropped straight into a browser `<img>`/`<video>`/`<iframe>`
|
|
28668
|
+
* `src`.
|
|
28669
|
+
*
|
|
28670
|
+
* wiki-service returns these relative on purpose — it doesn't know its own
|
|
28671
|
+
* public origin. A relative `src` resolves against the *page* origin, which
|
|
28672
|
+
* only works when the page and wiki-service share an origin (local dev:
|
|
28673
|
+
* same-origin + Next.js `/wiki/*` proxy). In deployed envs the app
|
|
28674
|
+
* (app.parall.com) and wiki-service (api.parall.com) are different origins,
|
|
28675
|
+
* so `app.parall.com/wiki/v1/signed/files` hits the SPA's own `/wiki/[...]`
|
|
28676
|
+
* catch-all route — an `<iframe>` then recursively renders the whole app
|
|
28677
|
+
* instead of the file. Prefixing with the wiki base (the exact origin every
|
|
28678
|
+
* wiki API request already uses — `baseUrlFor` resolves `/wiki/v1` paths to
|
|
28679
|
+
* `wikiBaseUrl`) makes the URL absolute against the origin that actually
|
|
28680
|
+
* serves the bytes. An empty base (local dev, same-origin proxy) leaves it
|
|
28681
|
+
* relative, preserving the proxy path.
|
|
28682
|
+
*/
|
|
28683
|
+
absoluteMediaUrl(url) {
|
|
28684
|
+
if (/^https?:\/\//i.test(url))
|
|
28685
|
+
return url;
|
|
28686
|
+
return `${this.baseUrlFor(url)}${url}`;
|
|
28687
|
+
}
|
|
28553
28688
|
async getWikiBlob(orgId, wikiId, params) {
|
|
28554
|
-
|
|
28689
|
+
const blob = await this.request("GET", ENDPOINTS.WIKI_BLOB(orgId, wikiId), void 0, params);
|
|
28690
|
+
if (blob.signed_url)
|
|
28691
|
+
blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
28692
|
+
return blob;
|
|
28555
28693
|
}
|
|
28556
28694
|
async getWikiNodeSections(orgId, wikiId, params) {
|
|
28557
28695
|
return this.request("GET", ENDPOINTS.WIKI_NODE_SECTIONS(orgId, wikiId), void 0, params);
|
|
@@ -28641,7 +28779,10 @@ var ParallClient = class _ParallClient {
|
|
|
28641
28779
|
* token — don't leak it.
|
|
28642
28780
|
*/
|
|
28643
28781
|
async getWikiFilePreviewUrl(orgId, wikiId, params) {
|
|
28644
|
-
|
|
28782
|
+
const res = await this.request("POST", ENDPOINTS.WIKI_FILE_PREVIEW_URL(orgId, wikiId), params);
|
|
28783
|
+
if (res.url)
|
|
28784
|
+
res.url = this.absoluteMediaUrl(res.url);
|
|
28785
|
+
return res;
|
|
28645
28786
|
}
|
|
28646
28787
|
// ---- Wiki Path Scopes (AFCS ACL) ----
|
|
28647
28788
|
async getWikiPathScopes(orgId, wikiId) {
|
|
@@ -28718,6 +28859,16 @@ var ParallClient = class _ParallClient {
|
|
|
28718
28859
|
async getBacklinks(orgId, params) {
|
|
28719
28860
|
return this.request("GET", ENDPOINTS.REFS_BACKLINKS(orgId), void 0, params);
|
|
28720
28861
|
}
|
|
28862
|
+
/**
|
|
28863
|
+
* Bounded multi-hop walk of the prll:// reference graph around `uri`. `uri`
|
|
28864
|
+
* must be an entity-level prll:// URI — a refined URI (path/query/fragment) is
|
|
28865
|
+
* rejected with 400 UNSUPPORTED_REFINED_URI. `depth` is clamped server-side to
|
|
28866
|
+
* [1, 4]; breadth (node/edge counts) is capped server-side and surfaced via
|
|
28867
|
+
* `truncated`. ACL is applied per hop (chat membership + wiki path scope).
|
|
28868
|
+
*/
|
|
28869
|
+
async getRefsGraph(orgId, params) {
|
|
28870
|
+
return this.request("GET", ENDPOINTS.REFS_GRAPH(orgId), void 0, params);
|
|
28871
|
+
}
|
|
28721
28872
|
async checkBrokenRefs(orgId) {
|
|
28722
28873
|
return this.request("GET", ENDPOINTS.REFS_CHECK(orgId));
|
|
28723
28874
|
}
|
|
@@ -28857,6 +29008,9 @@ var ParallClient = class _ParallClient {
|
|
|
28857
29008
|
const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
|
|
28858
29009
|
return resp.data;
|
|
28859
29010
|
}
|
|
29011
|
+
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
29012
|
+
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
29013
|
+
* carrying a per-viewer `can_open` control hint. */
|
|
28860
29014
|
async listBrowserProfiles(orgId) {
|
|
28861
29015
|
const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILES(orgId));
|
|
28862
29016
|
return resp.data;
|
|
@@ -29510,6 +29664,9 @@ function resolveStepTarget(event) {
|
|
|
29510
29664
|
if (event.type === "schedule" || event.targetId.startsWith("sch_")) {
|
|
29511
29665
|
return { target_type: "schedule", target_id: event.targetId };
|
|
29512
29666
|
}
|
|
29667
|
+
if (event.type === "external_trigger" || event.targetId.startsWith("xtr_")) {
|
|
29668
|
+
return { target_type: "external_trigger", target_id: event.targetId };
|
|
29669
|
+
}
|
|
29513
29670
|
if (event.type === "wiki_comment") {
|
|
29514
29671
|
return { target_type: "wiki", target_id: event.targetId || void 0 };
|
|
29515
29672
|
}
|
|
@@ -29714,6 +29871,18 @@ var ParallAgentGateway = class {
|
|
|
29714
29871
|
} catch (err) {
|
|
29715
29872
|
this.opts.log?.error(`schedule fire dispatch failed for ${data.source_id}: ${String(err)}`);
|
|
29716
29873
|
}
|
|
29874
|
+
} else if (data.event_type === "external_trigger") {
|
|
29875
|
+
if (!data.source_id)
|
|
29876
|
+
return;
|
|
29877
|
+
try {
|
|
29878
|
+
const dispatched = await this.fetchAndHandleExternalTriggerRun(data.source_id);
|
|
29879
|
+
if (dispatched) {
|
|
29880
|
+
this.opts.client.ackDispatchByID(this.opts.config.org_id, data.id).catch(() => {
|
|
29881
|
+
});
|
|
29882
|
+
}
|
|
29883
|
+
} catch (err) {
|
|
29884
|
+
this.opts.log?.error(`external trigger dispatch failed for ${data.source_id}: ${String(err)}`);
|
|
29885
|
+
}
|
|
29717
29886
|
} else if (data.event_type === "approval_decided") {
|
|
29718
29887
|
if (!data.source_id)
|
|
29719
29888
|
return;
|
|
@@ -29792,8 +29961,13 @@ var ParallAgentGateway = class {
|
|
|
29792
29961
|
target_type: target.target_type,
|
|
29793
29962
|
target_id: target.target_id,
|
|
29794
29963
|
content: {
|
|
29795
|
-
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 === "approval" ? "approval_decided" : "mention",
|
|
29796
|
-
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 === "
|
|
29964
|
+
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",
|
|
29965
|
+
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" ? {
|
|
29966
|
+
trigger_id: event.targetId,
|
|
29967
|
+
run_id: event.messageId,
|
|
29968
|
+
connection_id: event.externalConnectionId,
|
|
29969
|
+
ingress_event_id: event.externalIngressEventId
|
|
29970
|
+
} : event.type === "approval" ? { approval_id: event.messageId } : { message_id: event.messageId },
|
|
29797
29971
|
sender_id: event.senderId,
|
|
29798
29972
|
sender_name: event.senderName,
|
|
29799
29973
|
summary: event.body.substring(0, 200),
|
|
@@ -30829,6 +31003,62 @@ var ParallAgentGateway = class {
|
|
|
30829
31003
|
}
|
|
30830
31004
|
return dispatched;
|
|
30831
31005
|
}
|
|
31006
|
+
async fetchAndHandleExternalTriggerRun(runId) {
|
|
31007
|
+
let run = null;
|
|
31008
|
+
try {
|
|
31009
|
+
run = await this.opts.client.getExternalTriggerRun(this.opts.config.org_id, runId);
|
|
31010
|
+
} catch (err) {
|
|
31011
|
+
const status = err?.status;
|
|
31012
|
+
if (status === 404) {
|
|
31013
|
+
this.opts.log?.warn(`external trigger run ${runId} not accessible (404), acking stale dispatch`);
|
|
31014
|
+
return true;
|
|
31015
|
+
}
|
|
31016
|
+
this.opts.log?.warn(`external trigger run fetch failed for ${runId}, leaving pending: ${String(err)}`);
|
|
31017
|
+
return false;
|
|
31018
|
+
}
|
|
31019
|
+
if (!run)
|
|
31020
|
+
return true;
|
|
31021
|
+
return this.handleExternalTriggerRun(run);
|
|
31022
|
+
}
|
|
31023
|
+
async handleExternalTriggerRun(run) {
|
|
31024
|
+
if (this.shuttingDown)
|
|
31025
|
+
return false;
|
|
31026
|
+
const dedupeKey = `external_trigger_run:${run.id}`;
|
|
31027
|
+
if (this.dispatchedTasks.has(dedupeKey))
|
|
31028
|
+
return false;
|
|
31029
|
+
this.dispatchedTasks.add(dedupeKey);
|
|
31030
|
+
this.opts.log?.info(`external trigger fired: ${run.id} (trigger ${run.trigger_id})`);
|
|
31031
|
+
const attachedUri = typeof run.trigger_snapshot?.attached_to_uri === "string" ? run.trigger_snapshot.attached_to_uri : void 0;
|
|
31032
|
+
const event = {
|
|
31033
|
+
type: "external_trigger",
|
|
31034
|
+
targetId: run.trigger_id,
|
|
31035
|
+
targetName: run.trigger_name || void 0,
|
|
31036
|
+
targetType: "external_trigger",
|
|
31037
|
+
senderId: "system",
|
|
31038
|
+
senderName: "external",
|
|
31039
|
+
messageId: run.id,
|
|
31040
|
+
body: run.agent_input_body ?? "",
|
|
31041
|
+
externalConnectionId: run.connection_id,
|
|
31042
|
+
externalConnectionSourceType: run.connection_source_type || void 0,
|
|
31043
|
+
externalConnectionDisplayName: run.connection_display_name || void 0,
|
|
31044
|
+
externalIngressEventId: run.ingress_event_id,
|
|
31045
|
+
externalIngressEventType: run.ingress_event_type || void 0,
|
|
31046
|
+
attachedUri,
|
|
31047
|
+
ackSourceType: "external_trigger_run",
|
|
31048
|
+
ackSourceId: run.id
|
|
31049
|
+
};
|
|
31050
|
+
let dispatched;
|
|
31051
|
+
try {
|
|
31052
|
+
dispatched = await this.handleInboundEvent(event);
|
|
31053
|
+
} catch (err) {
|
|
31054
|
+
this.dispatchedTasks.delete(dedupeKey);
|
|
31055
|
+
throw err;
|
|
31056
|
+
}
|
|
31057
|
+
if (!dispatched) {
|
|
31058
|
+
this.dispatchedTasks.delete(dedupeKey);
|
|
31059
|
+
}
|
|
31060
|
+
return dispatched;
|
|
31061
|
+
}
|
|
30832
31062
|
async fetchAndHandleApprovalDecided(approvalId, actorId, chatId) {
|
|
30833
31063
|
let approval = null;
|
|
30834
31064
|
try {
|
|
@@ -30939,6 +31169,8 @@ var ParallAgentGateway = class {
|
|
|
30939
31169
|
dispatched = await this.handleWikiComment(item.source_id, item.actor_id, item.delivery_reason);
|
|
30940
31170
|
} else if (item.event_type === "schedule.fire" && item.source_id) {
|
|
30941
31171
|
dispatched = await this.fetchAndHandleScheduleFire(item.source_id, item.actor_id);
|
|
31172
|
+
} else if (item.event_type === "external_trigger" && item.source_id) {
|
|
31173
|
+
dispatched = await this.fetchAndHandleExternalTriggerRun(item.source_id);
|
|
30942
31174
|
} else if (item.event_type === "approval_decided" && item.source_id) {
|
|
30943
31175
|
dispatched = await this.fetchAndHandleApprovalDecided(item.source_id, item.actor_id, item.chat_id ?? null);
|
|
30944
31176
|
} else if (item.event_type === "message" && item.source_id && item.chat_id) {
|
|
@@ -31306,8 +31538,36 @@ parall machines logs prll://mch_xxx --lines 100
|
|
|
31306
31538
|
\`\`\`bash
|
|
31307
31539
|
parall chats list # List all chats
|
|
31308
31540
|
parall messages list prll://cht_xxx # Read chat message history
|
|
31541
|
+
parall messages list prll://cht_xxx --since 2026-01-01 # Only messages at/after a date (RFC3339 or YYYY-MM-DD)
|
|
31542
|
+
\`\`\`
|
|
31543
|
+
|
|
31544
|
+
## Org-Context Search
|
|
31545
|
+
|
|
31546
|
+
Before deciding or starting non-trivial work, search the org's real history \u2014
|
|
31547
|
+
past discussions, decisions, tasks, and wiki notes \u2014 so you don't re-litigate
|
|
31548
|
+
settled questions or repeat known mistakes. This searches live org data
|
|
31549
|
+
(semantic + keyword), not a local copy, and is permission-filtered to what you
|
|
31550
|
+
can see.
|
|
31551
|
+
|
|
31552
|
+
\`\`\`bash
|
|
31553
|
+
# Semantic + keyword search across messages, tasks, and wiki
|
|
31554
|
+
parall search "auth v5 upgrade"
|
|
31555
|
+
|
|
31556
|
+
# Restrict entity types (m=message, t=task, w=wiki). --channel narrows the
|
|
31557
|
+
# MESSAGE hits to one chat (tasks/wiki are unaffected by it).
|
|
31558
|
+
parall search "auth v5 upgrade" --types m,w --channel prll://cht_eng
|
|
31559
|
+
|
|
31560
|
+
# Time-box to recent activity (RFC3339 or YYYY-MM-DD). Narrows messages + tasks;
|
|
31561
|
+
# wiki is always matched by relevance (the index has no authored timestamp).
|
|
31562
|
+
parall search "auth v5 upgrade" --since 2026-01-01
|
|
31563
|
+
|
|
31564
|
+
# Narrow wiki hits to a frontmatter document type
|
|
31565
|
+
parall search "deploy steps" --types w --wiki-type Runbook
|
|
31309
31566
|
\`\`\`
|
|
31310
31567
|
|
|
31568
|
+
Even with zero curated notes, the raw message + task history is searchable \u2014 the
|
|
31569
|
+
original discussion and its approval/rejection IS the precedent.
|
|
31570
|
+
|
|
31311
31571
|
## Sending Messages
|
|
31312
31572
|
|
|
31313
31573
|
Each \`[Event: message.new]\` includes \`[Chat: ... (prll://cht_xxx)]\` \u2014 use that chat URI to reply.
|
|
@@ -31398,11 +31658,39 @@ Every entity is addressable with a \`prll://\` URI. Common prefixes you'll see i
|
|
|
31398
31658
|
| \`prll://prj_\` | Project | parall-tasks |
|
|
31399
31659
|
| \`prll://sch_\` | Schedule (time trigger) | parall-schedules |
|
|
31400
31660
|
| \`prll://srn_\` | Schedule run (single fire audit record; carries fire-time snapshot) | parall-schedules |
|
|
31661
|
+
| \`prll://xcn_\` | External Trigger Connection (incoming endpoint) | parall-external-triggers |
|
|
31662
|
+
| \`prll://xin_\` | External Trigger Event (single incoming event audit record) | parall-external-triggers |
|
|
31663
|
+
| \`prll://xtr_\` | External Trigger (incoming trigger configuration) | parall-external-triggers |
|
|
31664
|
+
| \`prll://xrn_\` | External Trigger run (single matched dispatch audit record) | parall-external-triggers |
|
|
31401
31665
|
| \`prll://wik_\` | Wiki | parall-wiki |
|
|
31402
31666
|
| \`prll://att_\` | Attachment | parall-platform (files) |
|
|
31403
31667
|
|
|
31404
31668
|
When a message or event references \`prll://sch_xxx\` or \`prll://srn_xxx\`, or when you receive \`[Event: schedule.fired]\`, switch to the **parall-schedules** skill for the CLI commands (create / list / pause / resume / cancel / runs).
|
|
31405
31669
|
|
|
31670
|
+
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).
|
|
31671
|
+
|
|
31672
|
+
## References (relationship graph)
|
|
31673
|
+
|
|
31674
|
+
\`prll://\` references between entities form a graph \u2014 a message cites a task, a
|
|
31675
|
+
task cites a wiki page, and so on. Walk it to answer "what is this decision /
|
|
31676
|
+
entity connected to". All results are permission-filtered to what you can see.
|
|
31677
|
+
|
|
31678
|
+
\`\`\`bash
|
|
31679
|
+
# Resolve URIs to entity metadata (titles, status, previews)
|
|
31680
|
+
parall refs resolve prll://tsk_xxx prll://wik_xxx
|
|
31681
|
+
|
|
31682
|
+
# Single hop \u2014 who references X
|
|
31683
|
+
parall refs backlinks prll://tsk_xxx
|
|
31684
|
+
|
|
31685
|
+
# Multi-hop \u2014 the connected sub-graph around X (entity-level URI only \u2014 no
|
|
31686
|
+
# path/anchor; depth 1\u20134, default 2)
|
|
31687
|
+
parall refs graph prll://tsk_xxx --depth 2
|
|
31688
|
+
\`\`\`
|
|
31689
|
+
|
|
31690
|
+
\`refs graph\` traverses both directions (inbound + outbound) and returns \`nodes\`
|
|
31691
|
+
and \`edges\` with each node's hop \`depth\`. \`truncated: true\` means a size cap clipped
|
|
31692
|
+
the result \u2014 narrow it with a smaller \`--depth\`.
|
|
31693
|
+
|
|
31406
31694
|
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.
|
|
31407
31695
|
`;
|
|
31408
31696
|
|
|
@@ -31411,16 +31699,39 @@ var PARALL_TASKS_SKILL = `# Parall Tasks
|
|
|
31411
31699
|
|
|
31412
31700
|
Manage tasks and projects via the Parall CLI. Auth and runtime context are pre-configured.
|
|
31413
31701
|
|
|
31702
|
+
## Finding What's on Someone's Plate (incl. subtasks)
|
|
31703
|
+
|
|
31704
|
+
To answer "what do I still have to do", "what's <person> working on", or any
|
|
31705
|
+
"open work assigned to X" question, use \`tasks assigned\`:
|
|
31706
|
+
|
|
31707
|
+
\`\`\`bash
|
|
31708
|
+
# Pending tasks (todo + in_progress) assigned to a member \u2014 INCLUDES subtasks.
|
|
31709
|
+
parall tasks assigned prll://usr_xxx # a specific person (e.g. the human who asked)
|
|
31710
|
+
parall tasks assigned # yourself (defaults to the authenticated user)
|
|
31711
|
+
\`\`\`
|
|
31712
|
+
|
|
31713
|
+
This is the authoritative "open work for a person" query. It returns every
|
|
31714
|
+
pending task assigned to that member **including subtasks** \u2014 even when the
|
|
31715
|
+
subtask's parent task belongs to someone else. Decomposed work usually lives in
|
|
31716
|
+
subtasks, so do NOT answer this kind of question from \`tasks list\` alone:
|
|
31717
|
+
that is org-wide, page-capped, and not scoped to a person, so a person's
|
|
31718
|
+
subtasks are easily missed.
|
|
31719
|
+
|
|
31720
|
+
Resolve a person's \`prll://usr_\` id from the message context, the members
|
|
31721
|
+
list, or ref search; your own id comes from \`parall whoami\`.
|
|
31722
|
+
|
|
31414
31723
|
## Task Commands
|
|
31415
31724
|
|
|
31416
31725
|
\`\`\`bash
|
|
31417
|
-
# List tasks (
|
|
31726
|
+
# List tasks (org-wide; filter by status, assignee, or parent)
|
|
31418
31727
|
parall tasks list
|
|
31419
31728
|
parall tasks list --status todo
|
|
31420
31729
|
parall tasks list --status in_progress
|
|
31730
|
+
parall tasks list --assignee-id prll://usr_xxx # first page only (default 20) \u2014 for a person's FULL backlog use 'tasks assigned' above
|
|
31731
|
+
parall tasks subtasks prll://tsk_xxx # children of a single parent task
|
|
31421
31732
|
|
|
31422
|
-
# Create a task
|
|
31423
|
-
parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--project-id prll://prj_xxx]
|
|
31733
|
+
# Create a task (add --parent-id to make it a SUBTASK of another task)
|
|
31734
|
+
parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--parent-id prll://tsk_xxx] [--project-id prll://prj_xxx]
|
|
31424
31735
|
|
|
31425
31736
|
# Update task status
|
|
31426
31737
|
parall tasks update prll://tsk_xxx --status in_progress
|
|
@@ -31430,6 +31741,12 @@ parall tasks update prll://tsk_xxx --status done
|
|
|
31430
31741
|
parall tasks comments add prll://tsk_xxx --body "Progress update..."
|
|
31431
31742
|
\`\`\`
|
|
31432
31743
|
|
|
31744
|
+
Subtasks are just tasks with a parent: create one with \`tasks create --parent-id\`,
|
|
31745
|
+
re-parent with \`tasks update --parent-id\`, list a parent's children with
|
|
31746
|
+
\`tasks subtasks\`. \`tasks list\` without \`--parent-id\` already returns both
|
|
31747
|
+
top-level tasks and subtasks; per-person open work is best fetched with
|
|
31748
|
+
\`tasks assigned\` (above).
|
|
31749
|
+
|
|
31433
31750
|
## Project Commands
|
|
31434
31751
|
|
|
31435
31752
|
\`\`\`bash
|
|
@@ -31492,8 +31809,11 @@ Key facts the commands won't tell you:
|
|
|
31492
31809
|
the absolute workspace path (\`synced \u2192 /path/to/<slug>\` / \`Mount: ...\`).
|
|
31493
31810
|
Always address wiki files by that absolute path \u2014 your shell cwd is usually
|
|
31494
31811
|
NOT inside the workspace.
|
|
31495
|
-
- **Text
|
|
31496
|
-
|
|
31812
|
+
- **Text and binary are two paths.** The workspace + changeset flow is for
|
|
31813
|
+
text (markdown, code, config). Binary assets (images, PDFs, archives) are
|
|
31814
|
+
diff-less \u2014 they don't go in the workspace; use \`parall wiki file\` (see
|
|
31815
|
+
**Binary files** below). Dropping a binary into the workspace just gets it
|
|
31816
|
+
rejected on propose.
|
|
31497
31817
|
- **\`cat\`, \`search\`, \`query\`, \`outline\`, and \`section\` read your local
|
|
31498
31818
|
workspace copy when it exists** \u2014 including your own unproposed edits. Add
|
|
31499
31819
|
\`--remote\` to \`cat\` to read the server version instead.
|
|
@@ -31574,6 +31894,50 @@ Re-propose REPLACES the changeset's previous contents with your current
|
|
|
31574
31894
|
workspace diff \u2014 to withdraw a file from the proposal, revert it locally
|
|
31575
31895
|
(restore the synced content) and re-propose; it drops out of the changeset.
|
|
31576
31896
|
|
|
31897
|
+
## Binary files
|
|
31898
|
+
|
|
31899
|
+
Images, PDFs, archives \u2014 anything that can't be diffed \u2014 bypass the workspace
|
|
31900
|
+
and changeset-text flow entirely. They never belong in the synced workspace
|
|
31901
|
+
(propose rejects them); use \`parall wiki file\` instead. \`cat\` is text-only \u2014
|
|
31902
|
+
to read a binary's real bytes use \`file get\` (a plain \`sync\` only leaves a
|
|
31903
|
+
few-line Git-LFS pointer on disk, since the runtime has no git-lfs).
|
|
31904
|
+
|
|
31905
|
+
\`\`\`bash
|
|
31906
|
+
# Maintainer: direct-commit a binary to the default branch (no review)
|
|
31907
|
+
parall wiki file upload ./diagram.png docs/assets/diagram.png
|
|
31908
|
+
|
|
31909
|
+
# Read a binary's real bytes (LFS pointers resolved server-side) to a file.
|
|
31910
|
+
# Always use --output for binaries \u2014 without it the bytes stream to stdout and
|
|
31911
|
+
# would flood your context.
|
|
31912
|
+
parall wiki file get docs/assets/diagram.png --output ./diagram.png
|
|
31913
|
+
parall wiki file get docs/assets/diagram.png --ref <commit-or-branch> --output ./diagram.png # a specific revision
|
|
31914
|
+
|
|
31915
|
+
# Remove a binary from the default branch (git history still has it)
|
|
31916
|
+
parall wiki file delete docs/assets/diagram.png
|
|
31917
|
+
\`\`\`
|
|
31918
|
+
|
|
31919
|
+
\`upload\` needs **maintain**; it routes by size automatically (\u22641 MiB inline,
|
|
31920
|
+
larger \u2192 LFS). A text file sent to \`upload\` is rejected \u2014 that's the changeset
|
|
31921
|
+
flow's job.
|
|
31922
|
+
|
|
31923
|
+
### Reader: propose markdown that embeds an image
|
|
31924
|
+
|
|
31925
|
+
Without maintain you can still propose a doc with images \u2014 upload the binary
|
|
31926
|
+
into your **changeset's** branch (read + author), not the default branch:
|
|
31927
|
+
|
|
31928
|
+
\`\`\`bash
|
|
31929
|
+
parall wiki sync
|
|
31930
|
+
# edit a .md in the workspace to add 
|
|
31931
|
+
parall wiki changeset create <wiki> --title "Add foo diagram" # creates the changeset (note its id)
|
|
31932
|
+
parall wiki file upload ./foo.png assets/foo.png <wiki> --changeset <changesetId>
|
|
31933
|
+
# leave it for a maintainer to merge \u2014 both the markdown and the image squash in together
|
|
31934
|
+
\`\`\`
|
|
31935
|
+
|
|
31936
|
+
Do the markdown \`changeset create\` first so the changeset exists, then attach
|
|
31937
|
+
the image to it. Don't re-propose (\`--update\`) after attaching a binary \u2014
|
|
31938
|
+
re-propose replays only the text workspace and the server rejects dropping the
|
|
31939
|
+
attached binary (422 \`REPLACE_HAS_BINARY\`).
|
|
31940
|
+
|
|
31577
31941
|
## Discovery & history
|
|
31578
31942
|
|
|
31579
31943
|
\`\`\`bash
|
|
@@ -31687,6 +32051,96 @@ Do not treat schedule fires as "tasks assigned to you" \u2014 there's no status
|
|
|
31687
32051
|
CLI command results are JSON on stdout; mutation commands may emit auxiliary hints on stderr (for example, \`Created: prll://sch_xxx\`).
|
|
31688
32052
|
`;
|
|
31689
32053
|
|
|
32054
|
+
// ts/agent-core/dist/skills/parall-external-triggers.js
|
|
32055
|
+
var PARALL_EXTERNAL_TRIGGERS_SKILL = `# Parall External Triggers
|
|
32056
|
+
|
|
32057
|
+
An **External Trigger** is an incoming platform trigger. External systems send events to an External Trigger Connection, Parall matches active triggers with CEL, renders a Liquid template into an agent input body, and dispatches that input to the configured target agents.
|
|
32058
|
+
|
|
32059
|
+
Use External Triggers for incoming events such as GitHub callbacks, Slack/Feishu notifications, generic webhooks, or emails once the platform has a connection for them. The runtime behavior is incoming-only: receiving a trigger does not imply that you can call the external system back unless another explicit Parall capability is available.
|
|
32060
|
+
|
|
32061
|
+
## Prerequisite
|
|
32062
|
+
|
|
32063
|
+
External Trigger CLI commands are gated by the org-level \`external-triggers\` feature flag. If a command reports that the feature is unavailable, ask a human org admin to enable the flag before trying again. Public ingress delivery may still be live even when the management CLI is hidden behind the rollout flag.
|
|
32064
|
+
|
|
32065
|
+
## Creating a trigger
|
|
32066
|
+
|
|
32067
|
+
\`\`\`bash
|
|
32068
|
+
# 1. Create a connection. The ingress token is shown once; prefer writing it
|
|
32069
|
+
# to a local file so it does not land in shell history or logs.
|
|
32070
|
+
parall external-triggers create-connection --name "GitHub CI" --token-file ./github-ci-webhook-token.txt
|
|
32071
|
+
|
|
32072
|
+
# 2. Create a trigger that targets one or more agents.
|
|
32073
|
+
parall external-triggers create \\
|
|
32074
|
+
--connection prll://xcn_xxx \\
|
|
32075
|
+
--name "Failed checks" \\
|
|
32076
|
+
--target-ids prll://usr_agent_xxx \\
|
|
32077
|
+
--filter "body.json.check_run.conclusion == 'failure'" \\
|
|
32078
|
+
--template-file ./github-check-failed.md \\
|
|
32079
|
+
--attached-to-uri prll://tsk_xxx
|
|
32080
|
+
\`\`\`
|
|
32081
|
+
|
|
32082
|
+
\`--filter\` is CEL. Omit it to match all incoming events (\`true\`). Keep filters small and deterministic; do not model provider-specific branching in agent code when the CEL expression can select the relevant events first.
|
|
32083
|
+
|
|
32084
|
+
\`--template\` / \`--template-file\` is Liquid with the safe Parall profile. It can read event data, body data, safe request metadata, trigger fields, run fields, and connection fields. It cannot call HTTP, read databases, evaluate arbitrary code, access platform secrets, or read arbitrary request headers/query parameters.
|
|
32085
|
+
|
|
32086
|
+
Example template:
|
|
32087
|
+
|
|
32088
|
+
\`\`\`liquid
|
|
32089
|
+
GitHub check failed.
|
|
32090
|
+
|
|
32091
|
+
Event: {{ request.headers.x_github_event | default: "unknown" }}
|
|
32092
|
+
Repo: {{ body.json.repository.full_name }}
|
|
32093
|
+
PR: {{ body.json.pull_request.number }} {{ body.json.pull_request.title }}
|
|
32094
|
+
Check: {{ body.json.check_run.name }}
|
|
32095
|
+
Conclusion: {{ body.json.check_run.conclusion }}
|
|
32096
|
+
|
|
32097
|
+
Run: {{ body.json.check_run.html_url }}
|
|
32098
|
+
\`\`\`
|
|
32099
|
+
|
|
32100
|
+
Do not render access tokens, signing secrets, cookies, or private credentials into agent input. Request snapshots and bodies may contain third-party data; treat them as user-provided input.
|
|
32101
|
+
|
|
32102
|
+
## Inspecting and lifecycle
|
|
32103
|
+
|
|
32104
|
+
\`\`\`bash
|
|
32105
|
+
parall external-triggers connections
|
|
32106
|
+
parall external-triggers connection prll://xcn_xxx
|
|
32107
|
+
parall external-triggers schema prll://xcn_xxx
|
|
32108
|
+
|
|
32109
|
+
parall external-triggers list
|
|
32110
|
+
parall external-triggers list --connection prll://xcn_xxx
|
|
32111
|
+
parall external-triggers get prll://xtr_xxx
|
|
32112
|
+
parall external-triggers update prll://xtr_xxx --filter "event.type == 'check_run'"
|
|
32113
|
+
parall external-triggers pause prll://xtr_xxx
|
|
32114
|
+
parall external-triggers resume prll://xtr_xxx
|
|
32115
|
+
parall external-triggers delete prll://xtr_xxx
|
|
32116
|
+
|
|
32117
|
+
parall external-triggers runs prll://xtr_xxx
|
|
32118
|
+
parall external-triggers run prll://xrn_xxx
|
|
32119
|
+
parall external-triggers events --connection prll://xcn_xxx
|
|
32120
|
+
parall external-triggers event prll://xin_xxx
|
|
32121
|
+
\`\`\`
|
|
32122
|
+
|
|
32123
|
+
## Responding to external trigger dispatches
|
|
32124
|
+
|
|
32125
|
+
When you receive \`[Event: external.trigger]\`, Parall has already matched a trigger and rendered its template. The prompt includes headers such as:
|
|
32126
|
+
|
|
32127
|
+
- \`[Trigger: prll://xtr_xxx]\`
|
|
32128
|
+
- \`[Run: prll://xrn_xxx]\`
|
|
32129
|
+
- \`[Connection: ... (prll://xcn_xxx)]\`
|
|
32130
|
+
- \`[Ingress: prll://xin_xxx]\`
|
|
32131
|
+
- Optional \`[Attached: prll://...]\`
|
|
32132
|
+
|
|
32133
|
+
The rendered agent input body follows those headers. You usually do not need to fetch the run before acting. Fetch the run only for audit/debugging:
|
|
32134
|
+
|
|
32135
|
+
\`\`\`bash
|
|
32136
|
+
parall external-triggers run prll://xrn_xxx
|
|
32137
|
+
\`\`\`
|
|
32138
|
+
|
|
32139
|
+
Act on the rendered input the same way you would act on a user message: send a message, create or update tasks, edit wiki pages, or use available clips. If no visible response is needed, use \`parall no-reply --reason "handled external trigger"\` before sending any message.
|
|
32140
|
+
|
|
32141
|
+
CLI command results are JSON on stdout; mutation commands may emit auxiliary hints on stderr, for example \`Created: prll://xtr_xxx\`.
|
|
32142
|
+
`;
|
|
32143
|
+
|
|
31690
32144
|
// ts/agent-core/dist/skills/parall-clips.js
|
|
31691
32145
|
var PARALL_CLIPS_SKILL = `# Parall Clips
|
|
31692
32146
|
|
|
@@ -31755,6 +32209,11 @@ var SKILLS = [
|
|
|
31755
32209
|
description: "Parall schedule operations: create / pause / resume / cancel recurring or one-shot time triggers; respond to schedule fire events. Use when: user asks to set up a recurring reminder, schedule a delayed prompt, run cron-like work, or when the agent receives an `[Event: schedule.fired]` dispatch.",
|
|
31756
32210
|
content: PARALL_SCHEDULES_SKILL
|
|
31757
32211
|
},
|
|
32212
|
+
{
|
|
32213
|
+
name: "parall-external-triggers",
|
|
32214
|
+
description: "Parall External Trigger operations: create incoming connections, configure CEL/Liquid triggers, inspect incoming events and runs, and respond to `[Event: external.trigger]` dispatches. Use when: user asks to connect an external system to an agent, set up incoming callbacks/notifications, or when the agent receives an external trigger event.",
|
|
32215
|
+
content: PARALL_EXTERNAL_TRIGGERS_SKILL
|
|
32216
|
+
},
|
|
31758
32217
|
{
|
|
31759
32218
|
name: "parall-clips",
|
|
31760
32219
|
description: "Parall clip operations: list installed clips, invoke clip commands, inspect clip details. Use when: the task requires external capabilities (GitHub, web search, etc.), user asks about available tools/clips, or you need to call a clip command.",
|