@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.
@@ -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. The slug cannot be changed — wiki ACL rows reference it as
52712
- * `@slug`, so the server answers 400 SLUG_IMMUTABLE if one is sent.
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` the `agent_ids` must be empty. Every granted
54349
- * id must be an active agent of this org (else `400 INVALID_INPUT`).
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): renews the session's OWN active ledger lane so
57337
- * a long tool call cannot outlive the lease and get dethroned mid-turn.
57338
- * No-op without an active ledger lane for the session.
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 deadlineTimer = this.DISPATCH_DEADLINE_MS > 0 ? setTimeout(() => {
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
- }, this.DISPATCH_DEADLINE_MS) : null;
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
- if (deadlineTimer)
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");
@@ -59501,6 +59660,9 @@ function createPlatformConfigManager(opts) {
59501
59660
  };
59502
59661
  }
59503
59662
 
59663
+ // ts/agent-core/dist/generated/codex-message-delivery.js
59664
+ var PLATFORM_CODEX_MESSAGE_DELIVERY_INSTRUCTIONS = "### Codex message delivery\n\nCodex's native `commentary` and `final` prose is not a Parall message. The\nbridge records that prose only as a suppressed session step; nobody in the chat\nsees it. Tool calls made from `commentary` still execute, so use the shell/exec\ntool there to run the Parall CLI.\n\nThroughout these Parall instructions, \u201Creply\u201D, \u201Csay\u201D, \u201Cask\u201D, \u201Creport\u201D,\n\u201Cupdate\u201D, and \u201Ccommunicate\u201D mean creating a collaborator-visible Parall\nartifact through the CLI, never emitting runtime-native assistant prose.\n\nWhen the current event warrants a visible response, deliver acknowledgements,\nmeaningful progress, blockers or questions, requested status, and final results\nwith `parall messages send` or `parall dm`. Native `commentary` or `final` prose\ndoes not satisfy that communication requirement. A reply is delivered only\nafter the CLI command succeeds.\n\nDo not mirror every routine runtime commentary heartbeat into the chat. After a\nsuccessful send, native `final` output is only an audit record and does not need\nto duplicate the collaborator-visible message.";
59665
+
59504
59666
  // ts/agent-core/dist/skills/index.js
59505
59667
  import * as fs5 from "node:fs";
59506
59668
  import * as path5 from "node:path";
@@ -60516,6 +60678,7 @@ function parseTweets(data) { /* ... */ }
60516
60678
  - \`tab.cookie(name)\` \xB7 \`tab.fetch(url, opts)\` (in-browser fetch, carries the session)
60517
60679
  - \`tab.eval(expr)\` (escape hatch) \xB7 \`tab.click(sel)\` \xB7 \`tab.fill(sel, text)\` \xB7 \`tab.navigate(url)\`
60518
60680
  - \`tab.waitForSelector(sel)\` \xB7 \`tab.getTitle()\` \xB7 \`tab.getURL()\` \xB7 \`tab.screenshot()\` \xB7 \`tab.close()\`
60681
+ - \`tab.setFileInput(sel, url, opts?)\` \u2014 upload a file into an \`<input type=file>\`
60519
60682
  - \`fetch\` \u2014 runtime-side HTTP, does NOT go through the browser (no session)
60520
60683
  - \`console\` \u2014 logs \xB7 \`args\` \u2014 the invocation input
60521
60684
 
@@ -60524,6 +60687,40 @@ returns structured data; eval is the last resort. Always \`tab.close()\` what yo
60524
60687
  open, and do it in a \`finally\` \u2014 an early return or a thrown fetch is exactly
60525
60688
  when the tab leaks.
60526
60689
 
60690
+ ### Uploading a file
60691
+
60692
+ \`tab.setFileInput\` takes a URL, never a path, and the runtime \u2014 not the page \u2014
60693
+ fetches the bytes. That is what makes it work where an in-page \`fetch\` +
60694
+ \`DataTransfer\` cannot: upload targets ship a Content-Security-Policy that
60695
+ forbids the page from fetching an arbitrary file host (Instagram's \`default-src\`
60696
+ allows only its own domains), and you cannot change a header on their site. The
60697
+ runtime is not a page, so no CSP applies to it \u2014 and a large video never has to
60698
+ pass through the page's memory.
60699
+
60700
+ \`\`\`js
60701
+ await tab.setFileInput("input[type=file]", videoUrl, { filename: "clip.mp4" });
60702
+ await tab.click("button[type=submit]");
60703
+ await tab.waitForSelector(".upload-complete"); // \u2190 do not skip this
60704
+ \`\`\`
60705
+
60706
+ Four rules that decide whether your clip works:
60707
+
60708
+ 1. **The URL must be fetchable with no credentials** \u2014 a public direct link or a
60709
+ signed temporary one. The runtime sends no cookies, so a Drive or Feishu link
60710
+ copied from the address bar will not work: those are HTML pages behind a
60711
+ login. If the file needs a session, use a logged-in tab to obtain a signed
60712
+ direct link first, then pass THAT here. An HTML answer is refused with
60713
+ \`EDGE_FILE_SOURCE_NOT_A_FILE\` rather than uploaded as if it were a file.
60714
+ 2. **Finish the upload inside the same command.** The browser reads the file when
60715
+ the page submits, and the runtime deletes it when your command ends. Injecting
60716
+ and returning immediately uploads nothing \u2014 wait for the site to confirm.
60717
+ 3. **Main-document inputs only.** An input inside an iframe or a shadow root is
60718
+ not addressable and returns \`EDGE_FILE_SELECTOR_MISS\`. If the page rebuilds
60719
+ the input after you inject (navigation, re-render), inject again.
60720
+ 4. **\`opts.filename\` is what the page sees**, and many sites validate by
60721
+ extension \u2014 set it when the URL has none. \`opts.timeoutMs\` bounds the
60722
+ download. One file per call; there is no multi-file form yet.
60723
+
60527
60724
  ## Develop \u2192 publish \u2192 iterate
60528
60725
 
60529
60726
  Use the platform \`parall clip\` subcommands \u2014 they reuse the credentials you
@@ -60630,18 +60827,30 @@ and the folder is just a manifest:
60630
60827
  }
60631
60828
  \`\`\`
60632
60829
 
60633
- - The \`mcp\` block takes ONLY \`server_url\` and \`auth\` (\`"none" | "bearer" |
60634
- "api_key" | "oauth"\`). Any other key is refused at publish \u2014 a credential
60635
- belongs to the installing org's own configuration, NEVER to the clip
60636
- definition.
60830
+ - The \`mcp\` block takes ONLY \`server_url\`, \`auth\` (\`"none" | "api_key" |
60831
+ "basic" | "oauth"\`, legacy \`"bearer"\` accepted) and \`auth_headers\`. Any
60832
+ other key is refused at publish \u2014 a credential belongs to the installing
60833
+ org's own configuration, NEVER to the clip definition.
60834
+ - \`auth\` is REQUIRED at publish: you know what your server speaks, and this
60835
+ one word decides what the install form asks for (\`none\` = zero input,
60836
+ \`api_key\` = key field(s), \`basic\` = username + password, \`oauth\` = a
60837
+ Connect button).
60838
+ - \`api_key\` delivers as a single \`X-API-Key\` header by default. When the
60839
+ server wants a different shape, declare \`auth_headers\` (max 4 slots, one
60840
+ admin-supplied value each): \`[{"name": "Authorization", "scheme":
60841
+ "Bearer"}]\` for Bearer tokens, \`[{"name": "api-key"}]\` for a custom
60842
+ header, or a pair like \`[{"name": "CF-Access-Client-Id"}, {"name":
60843
+ "CF-Access-Client-Secret"}]\`. Framing/platform headers (Host, Cookie,
60844
+ X-Prll-*, \u2026) are refused.
60637
60845
  - \`server_url\` must be an absolute **https** URL with no embedded credentials,
60638
60846
  query, or fragment. It is review material, frozen with the approved version.
60847
+ It stays OPTIONAL for self-hosted products where each org connects its own
60848
+ instance URL.
60639
60849
  - Do NOT put the server in the top-level \`server\` / \`auth\` manifest keys \u2014
60640
60850
  those are legacy Edge-manifest fields nothing reads. Only the \`mcp\` block
60641
60851
  declares the server.
60642
- - Both fields are optional, but what you declare is LOCKED: the installing
60643
- org's config must match it, and changing the URL or auth mode means
60644
- republishing.
60852
+ - What you declare is LOCKED: the installing org's config must match it, and
60853
+ changing the URL, auth mode, or header shape means republishing.
60645
60854
  - Entering the credential / completing OAuth is a HUMAN step in the Clip
60646
60855
  Console (the config-write endpoints are session-only \u2014 an API key cannot
60647
60856
  call them). An org can add SEVERAL connections to one MCP clip \u2014 one
@@ -60727,14 +60936,17 @@ ${lines.join("\n")}
60727
60936
  }
60728
60937
 
60729
60938
  // ts/agent-core/dist/platform-instructions.js
60730
- function buildBridgePlatformInstructions(workspaceDir, identity, capabilityFragments) {
60939
+ function buildPlatformInstructions(workspaceDir, runtimeAppendix, identity, capabilityFragments) {
60731
60940
  return renderPlatformInstructions({
60732
60941
  identity,
60733
- runtimeAppendix: PLATFORM_BRIDGE_WORKSPACE_INSTRUCTIONS,
60942
+ runtimeAppendix,
60734
60943
  capabilityFragments,
60735
60944
  skillReferences: buildSkillReferences(workspaceDir)
60736
60945
  });
60737
60946
  }
60947
+ function buildCodexPlatformInstructions(workspaceDir, identity, capabilityFragments) {
60948
+ return buildPlatformInstructions(workspaceDir, [PLATFORM_BRIDGE_WORKSPACE_INSTRUCTIONS, PLATFORM_CODEX_MESSAGE_DELIVERY_INSTRUCTIONS].join("\n\n"), identity, capabilityFragments);
60949
+ }
60738
60950
 
60739
60951
  // ts/agent-core/dist/prompt-fragments.js
60740
60952
  function identityFromMe(me) {
@@ -62298,10 +62510,17 @@ function formatCommand(command) {
62298
62510
 
62299
62511
  // ts/codex-agent/dist/turn-sink.js
62300
62512
  var TurnSink = class {
62513
+ noteActivity;
62301
62514
  mapper = new EventMapper();
62302
62515
  queue = [];
62303
62516
  resolver = null;
62304
62517
  closed = false;
62518
+ constructor(noteActivity) {
62519
+ this.noteActivity = noteActivity;
62520
+ }
62521
+ touchActivity() {
62522
+ this.noteActivity?.();
62523
+ }
62305
62524
  push(envelope) {
62306
62525
  if (this.closed)
62307
62526
  return;
@@ -62452,13 +62671,13 @@ var CodexAppServerAdapter = class {
62452
62671
  if (turnId && this.client && !this.client.isDisposed()) {
62453
62672
  this.client.sendRequest("turn/interrupt", { threadId, turnId }).catch((err) => this.opts.log?.warn?.(`turn/interrupt failed: ${errToString2(err)}`));
62454
62673
  }
62455
- sink.push({ kind: "error", message: "dispatch deadline exceeded" });
62674
+ sink.push({ kind: "error", message: "dispatch inactivity deadline exceeded" });
62456
62675
  sink.close();
62457
62676
  }
62458
62677
  hasPendingInjections(sessionKey) {
62459
62678
  return (this.pendingInjections.get(sessionKey) ?? 0) > 0;
62460
62679
  }
62461
- async *dispatch({ event, bodyForAgent, sessionKey, context: context2 }) {
62680
+ async *dispatch({ event, bodyForAgent, sessionKey, context: context2, noteActivity }) {
62462
62681
  const pending = this.pendingInjections.get(sessionKey) ?? 0;
62463
62682
  if (pending > 0) {
62464
62683
  this.pendingInjections.delete(sessionKey);
@@ -62524,7 +62743,7 @@ var CodexAppServerAdapter = class {
62524
62743
  }
62525
62744
  break;
62526
62745
  }
62527
- const sink = new TurnSink();
62746
+ const sink = new TurnSink(noteActivity);
62528
62747
  this.setActiveTurn(threadId, sink, log2);
62529
62748
  const groupKey = randomUUID2();
62530
62749
  let sawTurnEnd = false;
@@ -63038,6 +63257,7 @@ var CodexAppServerAdapter = class {
63038
63257
  }
63039
63258
  return;
63040
63259
  }
63260
+ sink.touchActivity();
63041
63261
  for (const event of sink.mapper.map(method, params)) {
63042
63262
  sink.push({ kind: "runtime", event });
63043
63263
  }
@@ -63591,7 +63811,7 @@ function systemPromptCopyPath(workspaceDir) {
63591
63811
  return path11.join(workspaceDir, ".parall", "system-prompt.md");
63592
63812
  }
63593
63813
  function writeCodexSystemPrompt(workspaceDir, agentIdentity, capabilityFragments) {
63594
- const systemPrompt = buildBridgePlatformInstructions(workspaceDir, agentIdentity, capabilityFragments);
63814
+ const systemPrompt = buildCodexPlatformInstructions(workspaceDir, agentIdentity, capabilityFragments);
63595
63815
  fs10.mkdirSync(path11.join(workspaceDir, ".parall"), { recursive: true });
63596
63816
  fs10.writeFileSync(systemPromptCopyPath(workspaceDir), systemPrompt, "utf8");
63597
63817
  return systemPrompt;