@parall/daemon 1.55.0 → 1.55.2
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 +110 -5
- package/bundle/parall-claude-agent.js +247 -31
- package/bundle/parall-codex-agent.js +247 -27
- package/bundle/parall-daemon.js +128 -5
- package/package.json +6 -6
|
@@ -51863,6 +51863,13 @@ var ENDPOINTS = {
|
|
|
51863
51863
|
PROJECTS: (orgId) => `${API_BASE}/orgs/${orgId}/projects`,
|
|
51864
51864
|
PROJECT_TASK_SUMMARY: (orgId) => `${API_BASE}/orgs/${orgId}/projects/task-summary`,
|
|
51865
51865
|
PROJECT: (orgId, projectId) => `${API_BASE}/orgs/${orgId}/projects/${projectId}`,
|
|
51866
|
+
PROJECT_MEMBERS: (orgId, projectId) => `${API_BASE}/orgs/${orgId}/projects/${projectId}/members`,
|
|
51867
|
+
PROJECT_READERS: (orgId, projectId) => `${API_BASE}/orgs/${orgId}/projects/${projectId}/readers`,
|
|
51868
|
+
PROJECT_LIBRARY: (orgId) => `${API_BASE}/orgs/${orgId}/projects/library`,
|
|
51869
|
+
PROJECT_JOIN: (orgId, projectId) => `${API_BASE}/orgs/${orgId}/projects/${projectId}/join`,
|
|
51870
|
+
PROJECT_JOIN_REQUESTS: (orgId, projectId) => `${API_BASE}/orgs/${orgId}/projects/${projectId}/join-requests`,
|
|
51871
|
+
// subject is a bare user ID or a bare team ID; both are path-segment safe.
|
|
51872
|
+
PROJECT_MEMBER: (orgId, projectId, subject) => `${API_BASE}/orgs/${orgId}/projects/${projectId}/members/${subject}`,
|
|
51866
51873
|
// Schedules (org-scoped, platform time trigger primitive)
|
|
51867
51874
|
SCHEDULES: (orgId) => `${API_BASE}/orgs/${orgId}/schedules`,
|
|
51868
51875
|
SCHEDULE: (orgId, id) => `${API_BASE}/orgs/${orgId}/schedules/${id}`,
|
|
@@ -52080,6 +52087,9 @@ var ENDPOINTS = {
|
|
|
52080
52087
|
ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
|
|
52081
52088
|
// Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
|
|
52082
52089
|
ORG_EDGE_PROFILE_PROXY: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
|
|
52090
|
+
// Per-profile one-shot cookie seed (hosted Cloud Profiles; manager-only,
|
|
52091
|
+
// human-only, idle-only). Injected at the next cold start, then consumed.
|
|
52092
|
+
ORG_EDGE_PROFILE_COOKIES: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/cookies`,
|
|
52083
52093
|
ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
|
|
52084
52094
|
// Cloud Edge live viewer command (V1b) — api-server, gated on cap:edge-viewer.
|
|
52085
52095
|
// Same request/reply shape as the v2 browser-profile viewer, on the v3 edge
|
|
@@ -52121,6 +52131,7 @@ var WS_EVENTS = {
|
|
|
52121
52131
|
PONG: "pong",
|
|
52122
52132
|
WATCHING: "watching",
|
|
52123
52133
|
MESSAGE_NEW: "message.new",
|
|
52134
|
+
/** @deprecated `message.patch` is retired and never published; kept for compile compatibility. */
|
|
52124
52135
|
MESSAGE_PATCH: "message.patch",
|
|
52125
52136
|
MESSAGE_EDIT: "message.edit",
|
|
52126
52137
|
MESSAGE_DELETE: "message.delete",
|
|
@@ -52316,6 +52327,62 @@ var ProjectTaskClient = class {
|
|
|
52316
52327
|
async deleteProject(orgId, projectId) {
|
|
52317
52328
|
return this.request("DELETE", ENDPOINTS.PROJECT(orgId, projectId));
|
|
52318
52329
|
}
|
|
52330
|
+
/** Roster with display info; readable by anyone who can read the project. */
|
|
52331
|
+
async getProjectMembers(orgId, projectId) {
|
|
52332
|
+
const res = await this.request("GET", ENDPOINTS.PROJECT_MEMBERS(orgId, projectId));
|
|
52333
|
+
return res.data;
|
|
52334
|
+
}
|
|
52335
|
+
/**
|
|
52336
|
+
* User IDs who may read the project — the assignee-eligibility set. Every
|
|
52337
|
+
* tier answers the roster expansion (direct, team-reached, org
|
|
52338
|
+
* owners/admins); visibility only shapes admission, never reach.
|
|
52339
|
+
*/
|
|
52340
|
+
async getProjectReaders(orgId, projectId) {
|
|
52341
|
+
const res = await this.request("GET", ENDPOINTS.PROJECT_READERS(orgId, projectId));
|
|
52342
|
+
return res.data;
|
|
52343
|
+
}
|
|
52344
|
+
/** The join library: every discoverable project (public + restricted, plus
|
|
52345
|
+
* private for org owners/admins) with the caller's admission state. */
|
|
52346
|
+
async getProjectLibrary(orgId) {
|
|
52347
|
+
const res = await this.request("GET", ENDPOINTS.PROJECT_LIBRARY(orgId));
|
|
52348
|
+
return res.data;
|
|
52349
|
+
}
|
|
52350
|
+
/** Public-tier self-admission: writes the caller's own member row.
|
|
52351
|
+
* Other tiers answer `404 PROJECT_NOT_FOUND`; a duplicate answers
|
|
52352
|
+
* `409 MEMBER_EXISTS`. */
|
|
52353
|
+
async joinProject(orgId, projectId) {
|
|
52354
|
+
return this.request("POST", ENDPOINTS.PROJECT_JOIN(orgId, projectId));
|
|
52355
|
+
}
|
|
52356
|
+
/** Restricted-tier admission petition. A pending duplicate answers
|
|
52357
|
+
* `409 REQUEST_EXISTS`; membership answers `409 MEMBER_EXISTS`. */
|
|
52358
|
+
async createProjectJoinRequest(orgId, projectId) {
|
|
52359
|
+
return this.request("POST", ENDPOINTS.PROJECT_JOIN_REQUESTS(orgId, projectId));
|
|
52360
|
+
}
|
|
52361
|
+
/** Pending petitions for one project — manager standing required. */
|
|
52362
|
+
async listProjectJoinRequests(orgId, projectId) {
|
|
52363
|
+
const res = await this.request("GET", ENDPOINTS.PROJECT_JOIN_REQUESTS(orgId, projectId));
|
|
52364
|
+
return res.data;
|
|
52365
|
+
}
|
|
52366
|
+
/** Withdraws the caller's own pending petition. */
|
|
52367
|
+
async cancelProjectJoinRequest(orgId, projectId) {
|
|
52368
|
+
return this.request("DELETE", ENDPOINTS.PROJECT_JOIN_REQUESTS(orgId, projectId));
|
|
52369
|
+
}
|
|
52370
|
+
/**
|
|
52371
|
+
* Adds one subject (user ID or team ID) to the roster. Manager-only,
|
|
52372
|
+
* create-only: an existing row answers `409 MEMBER_EXISTS` — change roles
|
|
52373
|
+
* through updateProjectMember instead.
|
|
52374
|
+
*/
|
|
52375
|
+
async addProjectMember(orgId, projectId, req) {
|
|
52376
|
+
return this.request("POST", ENDPOINTS.PROJECT_MEMBERS(orgId, projectId), req);
|
|
52377
|
+
}
|
|
52378
|
+
/** Sets one roster entry's role. Demoting the last manager answers `400 LAST_MANAGER`. */
|
|
52379
|
+
async updateProjectMember(orgId, projectId, subject, req) {
|
|
52380
|
+
return this.request("PATCH", ENDPOINTS.PROJECT_MEMBER(orgId, projectId, subject), req);
|
|
52381
|
+
}
|
|
52382
|
+
/** Removes one roster entry. Removing the last manager answers `400 LAST_MANAGER`. */
|
|
52383
|
+
async removeProjectMember(orgId, projectId, subject) {
|
|
52384
|
+
return this.request("DELETE", ENDPOINTS.PROJECT_MEMBER(orgId, projectId, subject));
|
|
52385
|
+
}
|
|
52319
52386
|
};
|
|
52320
52387
|
|
|
52321
52388
|
// ts/sdk/dist/task-label-client.js
|
|
@@ -52708,8 +52775,9 @@ var ParallClient = class _ParallClient extends TaskLabelClient {
|
|
|
52708
52775
|
return this.request("POST", ENDPOINTS.TEAMS(orgId), req);
|
|
52709
52776
|
}
|
|
52710
52777
|
/**
|
|
52711
|
-
* Renames a team.
|
|
52712
|
-
*
|
|
52778
|
+
* Renames a team. Renaming is an ordinary edit: ACL rows reference teams by
|
|
52779
|
+
* ID. Names are org-unique (case-insensitive); a duplicate answers 409
|
|
52780
|
+
* NAME_TAKEN.
|
|
52713
52781
|
*/
|
|
52714
52782
|
async updateTeam(orgId, teamId, req) {
|
|
52715
52783
|
return this.request("PATCH", ENDPOINTS.TEAM(orgId, teamId), req);
|
|
@@ -54338,15 +54406,18 @@ var ParallClient = class _ParallClient extends TaskLabelClient {
|
|
|
54338
54406
|
/**
|
|
54339
54407
|
* Read a clip's per-org agent exec access. Org-member readable (agents
|
|
54340
54408
|
* included, so a denied agent can learn why exec answered
|
|
54341
|
-
* `CLIP_AGENT_NOT_ALLOWED`).
|
|
54409
|
+
* `CLIP_AGENT_NOT_ALLOWED` / `CLIP_AGENT_CONNECTION_NOT_ALLOWED`).
|
|
54342
54410
|
*/
|
|
54343
54411
|
async getClipAgentExecAccess(orgId, clipId) {
|
|
54344
54412
|
return this.request("GET", ENDPOINTS.ORG_CLIP_EXEC_ACCESS(orgId, clipId));
|
|
54345
54413
|
}
|
|
54346
54414
|
/**
|
|
54347
54415
|
* Replace a clip's per-org agent exec access. Human-only (agent principals
|
|
54348
|
-
* get 403); under `all_agents`
|
|
54349
|
-
*
|
|
54416
|
+
* get 403); under `all_agents` both lists must be empty; pass either
|
|
54417
|
+
* `agent_ids` (legacy flat form → every agent gets `connection_scope: 'all'`)
|
|
54418
|
+
* or `grants` (connection-scoped), never both. Every granted id must be an
|
|
54419
|
+
* active agent of this org, and every `connection_ids` entry a connection of
|
|
54420
|
+
* THIS clip in this org (else `400 INVALID_INPUT`).
|
|
54350
54421
|
*/
|
|
54351
54422
|
async putClipAgentExecAccess(orgId, clipId, access) {
|
|
54352
54423
|
return this.request("PUT", ENDPOINTS.ORG_CLIP_EXEC_ACCESS(orgId, clipId), access);
|
|
@@ -54432,6 +54503,41 @@ var ParallClient = class _ParallClient extends TaskLabelClient {
|
|
|
54432
54503
|
headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
|
|
54433
54504
|
});
|
|
54434
54505
|
}
|
|
54506
|
+
/**
|
|
54507
|
+
* Read a hosted Cloud Profile's one-shot cookie-seed status (manager-only:
|
|
54508
|
+
* hosted human maintainer or org admin). Sanitized — cookie VALUES never come
|
|
54509
|
+
* back, only `cookie_count` and the distinct target `domains`. `can_mutate` /
|
|
54510
|
+
* `lease_status` are the authoritative idle gate. Typed errors: `EDGE_NOT_HOSTED`
|
|
54511
|
+
* (BYOC device), `NOT_FOUND` (unknown profile).
|
|
54512
|
+
*/
|
|
54513
|
+
async getEdgeProfileCookieSeed(orgId, edgeId, profileName) {
|
|
54514
|
+
return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_COOKIES(orgId, edgeId, profileName));
|
|
54515
|
+
}
|
|
54516
|
+
/**
|
|
54517
|
+
* Set/replace the profile's one-shot cookie seed (the full normalized cookie
|
|
54518
|
+
* array every time) — IDLE ONLY: while the profile's hosted browser is running
|
|
54519
|
+
* the server answers 409 `EDGE_PROFILE_IN_USE`; close the viewer, wait for idle
|
|
54520
|
+
* scale-to-zero, and retry. The next cold start injects the cookies into the
|
|
54521
|
+
* profile partition and consumes the seed. Other typed errors:
|
|
54522
|
+
* `EDGE_COOKIE_SEED_STALE` (409 — expectedVersion lost a tab race, sent as the
|
|
54523
|
+
* `cookieseed-<version>` If-Match), `EDGE_DELETING` (409), and
|
|
54524
|
+
* `SECRETBOX_UNCONFIGURED` (503 — server cannot store cookies safely).
|
|
54525
|
+
*/
|
|
54526
|
+
async setEdgeProfileCookieSeed(orgId, edgeId, profileName, req, expectedVersion) {
|
|
54527
|
+
return this.request("PUT", ENDPOINTS.ORG_EDGE_PROFILE_COOKIES(orgId, edgeId, profileName), req, void 0, false, {
|
|
54528
|
+
headers: expectedVersion ? { "If-Match": `"cookieseed-${expectedVersion}"` } : void 0
|
|
54529
|
+
});
|
|
54530
|
+
}
|
|
54531
|
+
/**
|
|
54532
|
+
* Clear the pending cookie seed (does NOT sign the profile out — cookies
|
|
54533
|
+
* already injected into the partition stay). Idle-only like set — 409
|
|
54534
|
+
* `EDGE_PROFILE_IN_USE` while the browser is live.
|
|
54535
|
+
*/
|
|
54536
|
+
async clearEdgeProfileCookieSeed(orgId, edgeId, profileName, expectedVersion) {
|
|
54537
|
+
return this.request("DELETE", ENDPOINTS.ORG_EDGE_PROFILE_COOKIES(orgId, edgeId, profileName), void 0, void 0, false, {
|
|
54538
|
+
headers: expectedVersion ? { "If-Match": `"cookieseed-${expectedVersion}"` } : void 0
|
|
54539
|
+
});
|
|
54540
|
+
}
|
|
54435
54541
|
/**
|
|
54436
54542
|
* Execute a registry clip command on an Edge device.
|
|
54437
54543
|
*
|
|
@@ -55779,6 +55885,56 @@ async function consumeMessageWorkItem(host, item) {
|
|
|
55779
55885
|
}
|
|
55780
55886
|
}
|
|
55781
55887
|
|
|
55888
|
+
// ts/agent-core/dist/dispatch-inactivity-deadline.js
|
|
55889
|
+
var DispatchInactivityDeadline = class {
|
|
55890
|
+
timeoutMs;
|
|
55891
|
+
onExpire;
|
|
55892
|
+
onDispose;
|
|
55893
|
+
timer = null;
|
|
55894
|
+
expired = false;
|
|
55895
|
+
disposed = false;
|
|
55896
|
+
constructor(timeoutMs, onExpire, onDispose) {
|
|
55897
|
+
this.timeoutMs = timeoutMs;
|
|
55898
|
+
this.onExpire = onExpire;
|
|
55899
|
+
this.onDispose = onDispose;
|
|
55900
|
+
}
|
|
55901
|
+
touch = () => {
|
|
55902
|
+
if (this.timeoutMs <= 0 || this.expired || this.disposed)
|
|
55903
|
+
return;
|
|
55904
|
+
if (this.timer)
|
|
55905
|
+
clearTimeout(this.timer);
|
|
55906
|
+
this.timer = setTimeout(() => {
|
|
55907
|
+
this.timer = null;
|
|
55908
|
+
this.expired = true;
|
|
55909
|
+
this.onExpire();
|
|
55910
|
+
}, this.timeoutMs);
|
|
55911
|
+
};
|
|
55912
|
+
dispose() {
|
|
55913
|
+
if (this.disposed)
|
|
55914
|
+
return;
|
|
55915
|
+
this.disposed = true;
|
|
55916
|
+
if (this.timer)
|
|
55917
|
+
clearTimeout(this.timer);
|
|
55918
|
+
this.timer = null;
|
|
55919
|
+
this.onDispose();
|
|
55920
|
+
}
|
|
55921
|
+
};
|
|
55922
|
+
var DispatchInactivityDeadlines = class {
|
|
55923
|
+
active = /* @__PURE__ */ new Map();
|
|
55924
|
+
start(sessionKey, timeoutMs, onExpire) {
|
|
55925
|
+
const deadline = new DispatchInactivityDeadline(timeoutMs, onExpire, () => {
|
|
55926
|
+
if (this.active.get(sessionKey) === deadline)
|
|
55927
|
+
this.active.delete(sessionKey);
|
|
55928
|
+
});
|
|
55929
|
+
this.active.set(sessionKey, deadline);
|
|
55930
|
+
deadline.touch();
|
|
55931
|
+
return deadline;
|
|
55932
|
+
}
|
|
55933
|
+
touch(sessionKey) {
|
|
55934
|
+
this.active.get(sessionKey)?.touch();
|
|
55935
|
+
}
|
|
55936
|
+
};
|
|
55937
|
+
|
|
55782
55938
|
// ts/agent-core/dist/routing.js
|
|
55783
55939
|
var MAX_CONCURRENT_FORKS = 20;
|
|
55784
55940
|
var defaultRoutingStrategy = (event, state) => {
|
|
@@ -57324,6 +57480,7 @@ var ParallAgentGateway = class {
|
|
|
57324
57480
|
* an unrelated stalled fork's lane leased forever).
|
|
57325
57481
|
*/
|
|
57326
57482
|
sessionActiveLanes = /* @__PURE__ */ new Map();
|
|
57483
|
+
dispatchInactivityDeadlines = new DispatchInactivityDeadlines();
|
|
57327
57484
|
noteSessionLane(sessionKey, laneKey) {
|
|
57328
57485
|
if (laneKey == null)
|
|
57329
57486
|
this.sessionActiveLanes.delete(sessionKey);
|
|
@@ -57333,11 +57490,12 @@ var ParallAgentGateway = class {
|
|
|
57333
57490
|
/**
|
|
57334
57491
|
* External runtime-activity signal for adapters whose tool activity does
|
|
57335
57492
|
* not flow through the RuntimeEvent stream (openclaw hooks call this from
|
|
57336
|
-
* the tool-call lifecycle):
|
|
57337
|
-
*
|
|
57338
|
-
*
|
|
57493
|
+
* the tool-call lifecycle): refreshes the dispatch inactivity deadline and
|
|
57494
|
+
* renews the session's OWN active ledger lane, when present, so a long tool
|
|
57495
|
+
* call cannot time out or get dethroned mid-turn.
|
|
57339
57496
|
*/
|
|
57340
57497
|
touchRuntimeActivity(sessionKey) {
|
|
57498
|
+
this.dispatchInactivityDeadlines.touch(sessionKey);
|
|
57341
57499
|
if (this.ledgerDisabled)
|
|
57342
57500
|
return;
|
|
57343
57501
|
const laneKey = this.sessionActiveLanes.get(sessionKey);
|
|
@@ -57813,14 +57971,14 @@ var ParallAgentGateway = class {
|
|
|
57813
57971
|
this.writeContextFile(laneContextFilePath2, contextBody);
|
|
57814
57972
|
}
|
|
57815
57973
|
this.inFlightDispatches++;
|
|
57816
|
-
const
|
|
57817
|
-
this.opts.log?.warn(`dispatch deadline exceeded (${this.DISPATCH_DEADLINE_MS}ms) for ${event.messageId} on ${sessionKey}; aborting`);
|
|
57974
|
+
const dispatchDeadline = this.dispatchInactivityDeadlines.start(sessionKey, this.DISPATCH_DEADLINE_MS, () => {
|
|
57975
|
+
this.opts.log?.warn(`dispatch inactivity deadline exceeded (${this.DISPATCH_DEADLINE_MS}ms) for ${event.messageId} on ${sessionKey}; aborting`);
|
|
57818
57976
|
try {
|
|
57819
57977
|
this.opts.dispatchAdapter.abortDispatch?.(sessionKey);
|
|
57820
57978
|
} catch (err) {
|
|
57821
57979
|
this.opts.log?.warn(`abortDispatch threw for ${sessionKey}: ${String(err)}`);
|
|
57822
57980
|
}
|
|
57823
|
-
}
|
|
57981
|
+
});
|
|
57824
57982
|
let binding = this.sessionBindings.get(sessionKey);
|
|
57825
57983
|
let inputStepsCreated = false;
|
|
57826
57984
|
let turnHandle;
|
|
@@ -57841,8 +57999,10 @@ var ParallAgentGateway = class {
|
|
|
57841
57999
|
bodyForAgent,
|
|
57842
58000
|
sessionKey,
|
|
57843
58001
|
context: dispatchContext,
|
|
57844
|
-
inputLifecycle
|
|
58002
|
+
inputLifecycle,
|
|
58003
|
+
noteActivity: dispatchDeadline.touch
|
|
57845
58004
|
})) {
|
|
58005
|
+
dispatchDeadline.touch();
|
|
57846
58006
|
if (runtimeEvent.type === "runtime_session") {
|
|
57847
58007
|
const priorAgentSessionId = binding?.agentSessionId;
|
|
57848
58008
|
binding = await this.bindRuntimeSession(sessionKey, runtimeEvent, contextFilePath, laneContextFilePath2);
|
|
@@ -57979,8 +58139,7 @@ var ParallAgentGateway = class {
|
|
|
57979
58139
|
}
|
|
57980
58140
|
throw err;
|
|
57981
58141
|
} finally {
|
|
57982
|
-
|
|
57983
|
-
clearTimeout(deadlineTimer);
|
|
58142
|
+
dispatchDeadline.dispose();
|
|
57984
58143
|
const metricsSnapshot = getDispatchMetrics(sessionKey);
|
|
57985
58144
|
const durationMs = metricsSnapshot ? Date.now() - metricsSnapshot.started_at : 0;
|
|
57986
58145
|
const effectiveOutcome = turnOutcomeEvent?.outcome ?? (dispatchError || sawErrorEvent ? "runtime_crash" : "ok");
|
|
@@ -60516,6 +60675,7 @@ function parseTweets(data) { /* ... */ }
|
|
|
60516
60675
|
- \`tab.cookie(name)\` \xB7 \`tab.fetch(url, opts)\` (in-browser fetch, carries the session)
|
|
60517
60676
|
- \`tab.eval(expr)\` (escape hatch) \xB7 \`tab.click(sel)\` \xB7 \`tab.fill(sel, text)\` \xB7 \`tab.navigate(url)\`
|
|
60518
60677
|
- \`tab.waitForSelector(sel)\` \xB7 \`tab.getTitle()\` \xB7 \`tab.getURL()\` \xB7 \`tab.screenshot()\` \xB7 \`tab.close()\`
|
|
60678
|
+
- \`tab.setFileInput(sel, url, opts?)\` \u2014 upload a file into an \`<input type=file>\`
|
|
60519
60679
|
- \`fetch\` \u2014 runtime-side HTTP, does NOT go through the browser (no session)
|
|
60520
60680
|
- \`console\` \u2014 logs \xB7 \`args\` \u2014 the invocation input
|
|
60521
60681
|
|
|
@@ -60524,6 +60684,40 @@ returns structured data; eval is the last resort. Always \`tab.close()\` what yo
|
|
|
60524
60684
|
open, and do it in a \`finally\` \u2014 an early return or a thrown fetch is exactly
|
|
60525
60685
|
when the tab leaks.
|
|
60526
60686
|
|
|
60687
|
+
### Uploading a file
|
|
60688
|
+
|
|
60689
|
+
\`tab.setFileInput\` takes a URL, never a path, and the runtime \u2014 not the page \u2014
|
|
60690
|
+
fetches the bytes. That is what makes it work where an in-page \`fetch\` +
|
|
60691
|
+
\`DataTransfer\` cannot: upload targets ship a Content-Security-Policy that
|
|
60692
|
+
forbids the page from fetching an arbitrary file host (Instagram's \`default-src\`
|
|
60693
|
+
allows only its own domains), and you cannot change a header on their site. The
|
|
60694
|
+
runtime is not a page, so no CSP applies to it \u2014 and a large video never has to
|
|
60695
|
+
pass through the page's memory.
|
|
60696
|
+
|
|
60697
|
+
\`\`\`js
|
|
60698
|
+
await tab.setFileInput("input[type=file]", videoUrl, { filename: "clip.mp4" });
|
|
60699
|
+
await tab.click("button[type=submit]");
|
|
60700
|
+
await tab.waitForSelector(".upload-complete"); // \u2190 do not skip this
|
|
60701
|
+
\`\`\`
|
|
60702
|
+
|
|
60703
|
+
Four rules that decide whether your clip works:
|
|
60704
|
+
|
|
60705
|
+
1. **The URL must be fetchable with no credentials** \u2014 a public direct link or a
|
|
60706
|
+
signed temporary one. The runtime sends no cookies, so a Drive or Feishu link
|
|
60707
|
+
copied from the address bar will not work: those are HTML pages behind a
|
|
60708
|
+
login. If the file needs a session, use a logged-in tab to obtain a signed
|
|
60709
|
+
direct link first, then pass THAT here. An HTML answer is refused with
|
|
60710
|
+
\`EDGE_FILE_SOURCE_NOT_A_FILE\` rather than uploaded as if it were a file.
|
|
60711
|
+
2. **Finish the upload inside the same command.** The browser reads the file when
|
|
60712
|
+
the page submits, and the runtime deletes it when your command ends. Injecting
|
|
60713
|
+
and returning immediately uploads nothing \u2014 wait for the site to confirm.
|
|
60714
|
+
3. **Main-document inputs only.** An input inside an iframe or a shadow root is
|
|
60715
|
+
not addressable and returns \`EDGE_FILE_SELECTOR_MISS\`. If the page rebuilds
|
|
60716
|
+
the input after you inject (navigation, re-render), inject again.
|
|
60717
|
+
4. **\`opts.filename\` is what the page sees**, and many sites validate by
|
|
60718
|
+
extension \u2014 set it when the URL has none. \`opts.timeoutMs\` bounds the
|
|
60719
|
+
download. One file per call; there is no multi-file form yet.
|
|
60720
|
+
|
|
60527
60721
|
## Develop \u2192 publish \u2192 iterate
|
|
60528
60722
|
|
|
60529
60723
|
Use the platform \`parall clip\` subcommands \u2014 they reuse the credentials you
|
|
@@ -60630,18 +60824,30 @@ and the folder is just a manifest:
|
|
|
60630
60824
|
}
|
|
60631
60825
|
\`\`\`
|
|
60632
60826
|
|
|
60633
|
-
- The \`mcp\` block takes ONLY \`server_url
|
|
60634
|
-
"
|
|
60635
|
-
|
|
60636
|
-
definition.
|
|
60827
|
+
- The \`mcp\` block takes ONLY \`server_url\`, \`auth\` (\`"none" | "api_key" |
|
|
60828
|
+
"basic" | "oauth"\`, legacy \`"bearer"\` accepted) and \`auth_headers\`. Any
|
|
60829
|
+
other key is refused at publish \u2014 a credential belongs to the installing
|
|
60830
|
+
org's own configuration, NEVER to the clip definition.
|
|
60831
|
+
- \`auth\` is REQUIRED at publish: you know what your server speaks, and this
|
|
60832
|
+
one word decides what the install form asks for (\`none\` = zero input,
|
|
60833
|
+
\`api_key\` = key field(s), \`basic\` = username + password, \`oauth\` = a
|
|
60834
|
+
Connect button).
|
|
60835
|
+
- \`api_key\` delivers as a single \`X-API-Key\` header by default. When the
|
|
60836
|
+
server wants a different shape, declare \`auth_headers\` (max 4 slots, one
|
|
60837
|
+
admin-supplied value each): \`[{"name": "Authorization", "scheme":
|
|
60838
|
+
"Bearer"}]\` for Bearer tokens, \`[{"name": "api-key"}]\` for a custom
|
|
60839
|
+
header, or a pair like \`[{"name": "CF-Access-Client-Id"}, {"name":
|
|
60840
|
+
"CF-Access-Client-Secret"}]\`. Framing/platform headers (Host, Cookie,
|
|
60841
|
+
X-Prll-*, \u2026) are refused.
|
|
60637
60842
|
- \`server_url\` must be an absolute **https** URL with no embedded credentials,
|
|
60638
60843
|
query, or fragment. It is review material, frozen with the approved version.
|
|
60844
|
+
It stays OPTIONAL for self-hosted products where each org connects its own
|
|
60845
|
+
instance URL.
|
|
60639
60846
|
- Do NOT put the server in the top-level \`server\` / \`auth\` manifest keys \u2014
|
|
60640
60847
|
those are legacy Edge-manifest fields nothing reads. Only the \`mcp\` block
|
|
60641
60848
|
declares the server.
|
|
60642
|
-
-
|
|
60643
|
-
|
|
60644
|
-
republishing.
|
|
60849
|
+
- What you declare is LOCKED: the installing org's config must match it, and
|
|
60850
|
+
changing the URL, auth mode, or header shape means republishing.
|
|
60645
60851
|
- Entering the credential / completing OAuth is a HUMAN step in the Clip
|
|
60646
60852
|
Console (the config-write endpoints are session-only \u2014 an API key cannot
|
|
60647
60853
|
call them). An org can add SEVERAL connections to one MCP clip \u2014 one
|
|
@@ -60727,14 +60933,17 @@ ${lines.join("\n")}
|
|
|
60727
60933
|
}
|
|
60728
60934
|
|
|
60729
60935
|
// ts/agent-core/dist/platform-instructions.js
|
|
60730
|
-
function
|
|
60936
|
+
function buildPlatformInstructions(workspaceDir, runtimeAppendix, identity, capabilityFragments) {
|
|
60731
60937
|
return renderPlatformInstructions({
|
|
60732
60938
|
identity,
|
|
60733
|
-
runtimeAppendix
|
|
60939
|
+
runtimeAppendix,
|
|
60734
60940
|
capabilityFragments,
|
|
60735
60941
|
skillReferences: buildSkillReferences(workspaceDir)
|
|
60736
60942
|
});
|
|
60737
60943
|
}
|
|
60944
|
+
function buildBridgePlatformInstructions(workspaceDir, identity, capabilityFragments) {
|
|
60945
|
+
return buildPlatformInstructions(workspaceDir, PLATFORM_BRIDGE_WORKSPACE_INSTRUCTIONS, identity, capabilityFragments);
|
|
60946
|
+
}
|
|
60738
60947
|
|
|
60739
60948
|
// ts/agent-core/dist/prompt-fragments.js
|
|
60740
60949
|
function identityFromMe(me) {
|
|
@@ -61666,8 +61875,10 @@ async function* parseClaudeStreamJson(readable) {
|
|
|
61666
61875
|
yield { type: "assistant_error", message: message2 };
|
|
61667
61876
|
continue;
|
|
61668
61877
|
}
|
|
61669
|
-
if (asTrimmedString(eventRecord.parent_tool_use_id))
|
|
61878
|
+
if (asTrimmedString(eventRecord.parent_tool_use_id)) {
|
|
61879
|
+
yield { type: "runtime_activity" };
|
|
61670
61880
|
continue;
|
|
61881
|
+
}
|
|
61671
61882
|
const message = eventRecord.message;
|
|
61672
61883
|
const content = message && typeof message === "object" ? message.content : void 0;
|
|
61673
61884
|
if (!Array.isArray(content))
|
|
@@ -61712,8 +61923,10 @@ async function* parseClaudeStreamJson(readable) {
|
|
|
61712
61923
|
continue;
|
|
61713
61924
|
}
|
|
61714
61925
|
if (eventRecord.type === "user") {
|
|
61715
|
-
if (asTrimmedString(eventRecord.parent_tool_use_id))
|
|
61926
|
+
if (asTrimmedString(eventRecord.parent_tool_use_id)) {
|
|
61927
|
+
yield { type: "runtime_activity" };
|
|
61716
61928
|
continue;
|
|
61929
|
+
}
|
|
61717
61930
|
const message = eventRecord.message;
|
|
61718
61931
|
const content = message && typeof message === "object" ? message.content : void 0;
|
|
61719
61932
|
if (!Array.isArray(content))
|
|
@@ -62076,7 +62289,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62076
62289
|
return false;
|
|
62077
62290
|
return state.inputs.hasPendingInjections();
|
|
62078
62291
|
}
|
|
62079
|
-
async *dispatch({ event, bodyForAgent, sessionKey, context: context2, inputLifecycle }) {
|
|
62292
|
+
async *dispatch({ event, bodyForAgent, sessionKey, context: context2, inputLifecycle, noteActivity }) {
|
|
62080
62293
|
const deliveryKey = inputLifecycle?.deliveryKey ?? event.dispatchEventId ?? event.messageId;
|
|
62081
62294
|
const existingState = this.processes.get(sessionKey);
|
|
62082
62295
|
const injected = existingState?.inputs.getByKey(deliveryKey);
|
|
@@ -62087,7 +62300,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62087
62300
|
injected.drained = true;
|
|
62088
62301
|
context2.log?.info?.(`consuming steer input ${injected.commandUuid}`);
|
|
62089
62302
|
try {
|
|
62090
|
-
yield* this.consumeDelivery(sessionKey, existingState, injected, context2.log);
|
|
62303
|
+
yield* this.consumeDelivery(sessionKey, existingState, injected, context2.log, noteActivity);
|
|
62091
62304
|
} finally {
|
|
62092
62305
|
existingState.inputs.remove(injected);
|
|
62093
62306
|
}
|
|
@@ -62117,7 +62330,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62117
62330
|
context2.log?.warn?.(`failed to prepare local attachments: ${String(err)}`);
|
|
62118
62331
|
}
|
|
62119
62332
|
try {
|
|
62120
|
-
yield* this.runTurn(sessionKey, promptBody, deliveryKey, inputLifecycle, context2.log);
|
|
62333
|
+
yield* this.runTurn(sessionKey, promptBody, deliveryKey, inputLifecycle, context2.log, noteActivity);
|
|
62121
62334
|
} finally {
|
|
62122
62335
|
releasePreparedAttachments();
|
|
62123
62336
|
}
|
|
@@ -62158,7 +62371,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62158
62371
|
this.resetProcesses();
|
|
62159
62372
|
await this.opts.sessionManager.shutdownAll();
|
|
62160
62373
|
}
|
|
62161
|
-
async *runTurn(sessionKey, promptBody, deliveryKey, lifecycle, log2) {
|
|
62374
|
+
async *runTurn(sessionKey, promptBody, deliveryKey, lifecycle, log2, noteActivity) {
|
|
62162
62375
|
let state;
|
|
62163
62376
|
try {
|
|
62164
62377
|
await this.ensureRuntimeCapability(log2);
|
|
@@ -62183,7 +62396,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62183
62396
|
return;
|
|
62184
62397
|
}
|
|
62185
62398
|
try {
|
|
62186
|
-
yield* this.consumeDelivery(sessionKey, state, delivery, log2);
|
|
62399
|
+
yield* this.consumeDelivery(sessionKey, state, delivery, log2, noteActivity);
|
|
62187
62400
|
} finally {
|
|
62188
62401
|
state.inputs.remove(delivery);
|
|
62189
62402
|
}
|
|
@@ -62248,7 +62461,7 @@ var ClaudeCodeAdapter = class {
|
|
|
62248
62461
|
* finish while this drain is active; their callbacks advance independently
|
|
62249
62462
|
* and their later bookkeeping dispatch becomes a no-op.
|
|
62250
62463
|
*/
|
|
62251
|
-
async *consumeDelivery(sessionKey, state, target, log2) {
|
|
62464
|
+
async *consumeDelivery(sessionKey, state, target, log2, noteActivity) {
|
|
62252
62465
|
if (target.terminal)
|
|
62253
62466
|
return;
|
|
62254
62467
|
const groupKey = randomUUID3();
|
|
@@ -62279,6 +62492,9 @@ var ClaudeCodeAdapter = class {
|
|
|
62279
62492
|
return;
|
|
62280
62493
|
}
|
|
62281
62494
|
const parsed = next.value;
|
|
62495
|
+
noteActivity?.();
|
|
62496
|
+
if (parsed.type === "runtime_activity")
|
|
62497
|
+
continue;
|
|
62282
62498
|
if (parsed.type === "runtime_init") {
|
|
62283
62499
|
state.capabilities = new Set(parsed.capabilities);
|
|
62284
62500
|
if (parsed.sessionId) {
|