@parall/daemon 1.33.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.33.0",
3
- "built_at": "2026-06-08T13:37:00.737Z",
2
+ "version": "1.35.0",
3
+ "built_at": "2026-06-16T06:46:33.372Z",
4
4
  "min_node_version": "20.0.0",
5
5
  "files": {
6
6
  "bb-browser-daemon.js": {
@@ -16,21 +16,21 @@
16
16
  "size": 18
17
17
  },
18
18
  "parall-claude-agent.js": {
19
- "sha256": "fd2395bb9ba5bc2912175d42419c4073ae581bd9382be6447d9169ce177e915c",
20
- "size": 1544348
19
+ "sha256": "cfabbba287441175296257d3dfa3a4abd41aa5ff527e40b457d9b1487f8b8b6c",
20
+ "size": 1550833
21
21
  },
22
22
  "parall-codex-agent.js": {
23
- "sha256": "fa93fb3b2aab23b6f3ecd218a0c0124bbe323af11c0ced898c2d057ad293f03b",
24
- "size": 1575437
23
+ "sha256": "94515538d3451f141b831f5f4cab3e4fe341b8db69a5ce3d17a3e566d911da18",
24
+ "size": 1581843
25
25
  },
26
26
  "parall-daemon.js": {
27
- "sha256": "83d37677018aa1bf0a37df14baaade7738bec2f907fa5d1f66b4bcad77430535",
28
- "size": 1565851
27
+ "sha256": "21d8c5150255adaac150f4b680b22bed039780686d178f6a4fe27b24a4b699db",
28
+ "size": 1597026
29
29
  },
30
30
  "parall-openclaw-agent.js": {
31
31
  "sha256": "505433b4bf3a4b8dbb7b96978d8693d6c48079f4513282ff1ee59a6d13b3eddf",
32
32
  "size": 9801
33
33
  }
34
34
  },
35
- "signature": "z7sT/o8aV5gfuQpr9TYQ+IkY3+IfdC5EiKrFKoQ4kz3TO1zXBC1RQ4xh1M0cFdB9KCDbaGeti2smdYAAczoCAQ=="
35
+ "signature": "LxNippCuMT4fJRPgPRlVICMxw6H+ny4eWg4qEUYg2uX1VddGPyQTEv+S4U2D7c0/ssHV4T8lukamtWRXNVCsCw=="
36
36
  }
@@ -27081,6 +27081,7 @@ var ENDPOINTS = {
27081
27081
  // Org-scoped
27082
27082
  ORG: (orgId) => `${API_BASE}/orgs/${orgId}`,
27083
27083
  ORG_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/members`,
27084
+ TEAMS: (orgId) => `${API_BASE}/orgs/${orgId}/teams`,
27084
27085
  ORG_MEMBERS_ONLINE: (orgId) => `${API_BASE}/orgs/${orgId}/members/online`,
27085
27086
  ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
27086
27087
  ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
@@ -27125,6 +27126,7 @@ var ENDPOINTS = {
27125
27126
  AGENT: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}`,
27126
27127
  AGENT_API_KEYS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys`,
27127
27128
  AGENT_API_KEY: (orgId, agentId, key) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys/${key}`,
27129
+ AGENT_API_KEY_REGENERATE: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/api-keys/regenerate`,
27128
27130
  AGENT_AVATAR: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/avatar`,
27129
27131
  AGENT_ACTIVITY: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/activity`,
27130
27132
  AGENT_MONITOR: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/monitor`,
@@ -27164,6 +27166,7 @@ var ENDPOINTS = {
27164
27166
  MACHINE_AGENT_WORKSPACE_SETUP: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
27165
27167
  MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
27166
27168
  MACHINE_PROVIDER_ENABLED: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/provider-enabled`,
27169
+ MACHINE_CAPABILITIES: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/capabilities`,
27167
27170
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
27168
27171
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
27169
27172
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
@@ -27184,6 +27187,12 @@ var ENDPOINTS = {
27184
27187
  MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
27185
27188
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
27186
27189
  MACHINES_ME_BROWSE_RESPONSE: (requestId) => `${API_BASE}/machines/me/browse-response/${requestId}`,
27190
+ // Hosted browser live-viewer control plane (api-server, NOT clip-service):
27191
+ // the web client drives WebRTC signaling + tab nav through VIEWER_COMMAND;
27192
+ // api-server brokers each command to the host daemon via the machine:{id}
27193
+ // request/reply bridge (mirrors filesystem browse), and the daemon replies on
27194
+ // VIEWER_RESPONSE. See docs/engineering-design/hosted-browser-provider-design.md.
27195
+ MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE: (requestId) => `${API_BASE}/machines/me/browser-profiles/viewer-response/${requestId}`,
27187
27196
  // Tasks (org-scoped)
27188
27197
  TASKS: (orgId) => `${API_BASE}/orgs/${orgId}/tasks`,
27189
27198
  TASK: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}`,
@@ -27249,6 +27258,9 @@ var ENDPOINTS = {
27249
27258
  // Wiki Path Scopes (AFCS ACL)
27250
27259
  WIKI_PATH_SCOPES: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes`,
27251
27260
  WIKI_PATH_SCOPE: (orgId, wikiId, scopeId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/path-scopes/${scopeId}`,
27261
+ // Wiki Path Restrictions (AFCS narrowing ACL — private subtrees)
27262
+ WIKI_RESTRICTIONS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions`,
27263
+ WIKI_RESTRICTION: (orgId, wikiId, restrictionId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions/${restrictionId}`,
27252
27264
  WIKI_ACCESS_STATUS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-status`,
27253
27265
  WIKI_ACCESS_REQUESTS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-requests`,
27254
27266
  // Wiki History (commits, file commits, blame)
@@ -27297,6 +27309,8 @@ var ENDPOINTS = {
27297
27309
  PUSH_VAPID_KEY: `${API_BASE}/push/vapid-key`,
27298
27310
  // Notification preferences
27299
27311
  NOTIFICATION_PREFERENCES: `${API_BASE}/notification-preferences`,
27312
+ // Unified search (messages + tasks + wiki, org-scoped)
27313
+ SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/search`,
27300
27314
  // Feature flags (org-scoped, server-evaluated)
27301
27315
  FEATURE_FLAGS: (orgId) => `${API_BASE}/orgs/${orgId}/feature-flags`,
27302
27316
  // Billing & Credits (org-scoped)
@@ -27312,6 +27326,7 @@ var ENDPOINTS = {
27312
27326
  // Clips (org-scoped, served by clip-service)
27313
27327
  CLIPS: (orgId) => `${CLIP_BASE}/orgs/${orgId}/clips`,
27314
27328
  CLIP: (orgId, clipId) => `${CLIP_BASE}/orgs/${orgId}/clips/${clipId}`,
27329
+ CLIPS_BULK_METADATA: (orgId) => `${CLIP_BASE}/orgs/${orgId}/clips/bulk-metadata`,
27315
27330
  CLIP_AGENTS: (orgId, clipId) => `${CLIP_BASE}/orgs/${orgId}/clips/${clipId}/agents`,
27316
27331
  AGENT_CLIPS: (orgId, agentId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips`,
27317
27332
  AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
@@ -27324,6 +27339,9 @@ var ENDPOINTS = {
27324
27339
  BROWSER_PROFILE_RESET: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/reset`,
27325
27340
  BROWSER_PROFILE_CONSENTS: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
27326
27341
  BROWSER_PROFILE_CONSENT: (orgId, profileId, clipId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
27342
+ // Live viewer command — on api-server (API_BASE), not clip-service: it rides
27343
+ // the machine control-plane request/reply bridge that lives in api-server.
27344
+ BROWSER_PROFILE_VIEWER_COMMAND: (orgId, profileId) => `${API_BASE}/orgs/${orgId}/browser-profiles/${profileId}/viewer/command`,
27327
27345
  // Clip registry (global, served by clip-service → Pinix Hub proxy)
27328
27346
  CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`
27329
27347
  };
@@ -27400,6 +27418,7 @@ var WS_EVENTS = {
27400
27418
  MACHINE_CONFIG_UPDATED: "machine.config.updated",
27401
27419
  MACHINE_CLIP_SYNC: "machine.clip.sync",
27402
27420
  MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
27421
+ MACHINE_BROWSER_PROFILE_VIEWER: "machine.browser_profile.viewer",
27403
27422
  AGENT_NEW_SESSION: "agent.new_session",
27404
27423
  CLIP_CREATED: "clip.created",
27405
27424
  CLIP_REMOVED: "clip.removed",
@@ -27430,8 +27449,13 @@ var ParallClient = class _ParallClient {
27430
27449
  /** Proactive refresh when token expires within this window (seconds). */
27431
27450
  static REFRESH_THRESHOLD_S = 5 * 60;
27432
27451
  static normalizeFetchError(err) {
27433
- if (typeof DOMException !== "undefined" && err instanceof DOMException && (err.name === "TimeoutError" || err.name === "AbortError")) {
27434
- return new ApiError(0, "Request timed out", "REQUEST_TIMEOUT");
27452
+ if (typeof DOMException !== "undefined" && err instanceof DOMException) {
27453
+ if (err.name === "TimeoutError") {
27454
+ return new ApiError(0, "Request timed out", "REQUEST_TIMEOUT");
27455
+ }
27456
+ if (err.name === "AbortError") {
27457
+ return new ApiError(0, "Request aborted", "REQUEST_ABORTED");
27458
+ }
27435
27459
  }
27436
27460
  const apiError = new ApiError(0, "Network request failed", "NETWORK_ERROR");
27437
27461
  if (err instanceof Error && err.message && err.message !== "Failed to fetch") {
@@ -27538,13 +27562,18 @@ var ParallClient = class _ParallClient {
27538
27562
  url += `?${qs}`;
27539
27563
  }
27540
27564
  const headers = this.buildHeaders();
27565
+ const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
27566
+ const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
27541
27567
  let res;
27542
27568
  try {
27543
27569
  res = await fetch(url, {
27544
27570
  method,
27545
27571
  headers,
27546
27572
  body: body ? JSON.stringify(body) : void 0,
27547
- signal: AbortSignal.timeout(opts?.timeoutMs ?? 15e3)
27573
+ signal,
27574
+ // keepalive lets a request fired during page unload (e.g. the browser
27575
+ // viewer's stream.close on pagehide) outlive the document.
27576
+ keepalive: opts?.keepalive
27548
27577
  });
27549
27578
  } catch (err) {
27550
27579
  throw _ParallClient.normalizeFetchError(err);
@@ -27715,6 +27744,10 @@ var ParallClient = class _ParallClient {
27715
27744
  const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS(orgId));
27716
27745
  return res.data;
27717
27746
  }
27747
+ async getTeams(orgId) {
27748
+ const res = await this.request("GET", ENDPOINTS.TEAMS(orgId));
27749
+ return res.data;
27750
+ }
27718
27751
  async getOnlineMembers(orgId) {
27719
27752
  const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_ONLINE(orgId));
27720
27753
  return res.user_ids ?? [];
@@ -27953,6 +27986,10 @@ var ParallClient = class _ParallClient {
27953
27986
  async createAgentApiKey(orgId, agentId) {
27954
27987
  return this.request("POST", ENDPOINTS.AGENT_API_KEYS(orgId, agentId));
27955
27988
  }
27989
+ /** Revokes all of the agent's active API keys and mints a replacement. */
27990
+ async regenerateAgentApiKey(orgId, agentId) {
27991
+ return this.request("POST", ENDPOINTS.AGENT_API_KEY_REGENERATE(orgId, agentId));
27992
+ }
27956
27993
  async revokeAgentApiKey(orgId, agentId, key) {
27957
27994
  return this.request("DELETE", ENDPOINTS.AGENT_API_KEY(orgId, agentId, key));
27958
27995
  }
@@ -28124,6 +28161,17 @@ var ParallClient = class _ParallClient {
28124
28161
  provider_enabled: providerEnabled
28125
28162
  });
28126
28163
  }
28164
+ /**
28165
+ * Replace the machine's capability set (admin). Primary use: healing a
28166
+ * machine that registered without `browser_provider` during the capability
28167
+ * migration's rolling-deploy window. Removing `agent_host` is rejected by the
28168
+ * server while agents are attached (409 AGENTS_STILL_ATTACHED).
28169
+ */
28170
+ async patchMachineCapabilities(orgId, machineId, capabilities) {
28171
+ return this.request("PATCH", ENDPOINTS.MACHINE_CAPABILITIES(orgId, machineId), {
28172
+ capabilities
28173
+ });
28174
+ }
28127
28175
  /** Get machine-level runtime auth state. */
28128
28176
  async getMachineRuntimeAuth(orgId, machineId) {
28129
28177
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
@@ -28214,6 +28262,22 @@ var ParallClient = class _ParallClient {
28214
28262
  async postBrowseResponse(requestId, response) {
28215
28263
  return this.request("POST", ENDPOINTS.MACHINES_ME_BROWSE_RESPONSE(requestId), response);
28216
28264
  }
28265
+ /**
28266
+ * `POST /machines/me/browser-profiles/viewer-response/{requestId}` — daemon
28267
+ * reply to a `machine.browser_profile.viewer` control command. Wakes the
28268
+ * api-server request/reply bridge (mirrors {@link postBrowseResponse}).
28269
+ */
28270
+ async postBrowserProfileViewerResponse(requestId, response) {
28271
+ return this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE(requestId), response);
28272
+ }
28273
+ /**
28274
+ * `POST /orgs/{orgId}/browser-profiles/{profileId}/viewer/command` — drive the
28275
+ * hosted browser live viewer (WebRTC signaling + tab nav). Authz: profile
28276
+ * owner or org admin. api-server brokers the command to the host daemon.
28277
+ */
28278
+ async browserViewerCommand(orgId, profileId, req, opts) {
28279
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, opts);
28280
+ }
28217
28281
  async resizeMachine(orgId, machineId, spec) {
28218
28282
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
28219
28283
  }
@@ -28492,6 +28556,9 @@ var ParallClient = class _ParallClient {
28492
28556
  async getWikiNodeSections(orgId, wikiId, params) {
28493
28557
  return this.request("GET", ENDPOINTS.WIKI_NODE_SECTIONS(orgId, wikiId), void 0, params);
28494
28558
  }
28559
+ async search(orgId, params, opts) {
28560
+ return this.request("GET", ENDPOINTS.SEARCH(orgId), void 0, params, false, opts);
28561
+ }
28495
28562
  async searchWiki(orgId, wikiId, params) {
28496
28563
  return this.request("GET", ENDPOINTS.WIKI_SEARCH(orgId, wikiId), void 0, params);
28497
28564
  }
@@ -28587,6 +28654,17 @@ var ParallClient = class _ParallClient {
28587
28654
  async deleteWikiPathScope(orgId, wikiId, scopeId) {
28588
28655
  await this.request("DELETE", ENDPOINTS.WIKI_PATH_SCOPE(orgId, wikiId, scopeId));
28589
28656
  }
28657
+ // ---- Wiki Path Restrictions (narrowing ACL — private subtrees) ----
28658
+ async getWikiRestrictions(orgId, wikiId) {
28659
+ const res = await this.request("GET", ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId));
28660
+ return res.data;
28661
+ }
28662
+ async createWikiRestriction(orgId, wikiId, data) {
28663
+ return this.request("POST", ENDPOINTS.WIKI_RESTRICTIONS(orgId, wikiId), data);
28664
+ }
28665
+ async deleteWikiRestriction(orgId, wikiId, restrictionId) {
28666
+ await this.request("DELETE", ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
28667
+ }
28590
28668
  async getWikiAccessStatus(orgId, wikiId, path9) {
28591
28669
  return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path9 ? { path: path9 } : void 0);
28592
28670
  }
@@ -28749,6 +28827,10 @@ var ParallClient = class _ParallClient {
28749
28827
  async updateClip(orgId, clipId, req) {
28750
28828
  return this.request("PATCH", ENDPOINTS.CLIP(orgId, clipId), req);
28751
28829
  }
28830
+ /** Atomically set display_name and/or description on multiple clip instances (application metadata). */
28831
+ async bulkUpdateClipMetadata(orgId, req) {
28832
+ return this.request("POST", ENDPOINTS.CLIPS_BULK_METADATA(orgId), req);
28833
+ }
28752
28834
  async deleteClip(orgId, clipId) {
28753
28835
  await this.request("DELETE", ENDPOINTS.CLIP(orgId, clipId));
28754
28836
  }
@@ -30280,7 +30362,7 @@ var ParallAgentGateway = class {
30280
30362
  this.dispatchState.mainDispatching = true;
30281
30363
  void this.drainMainBuffer();
30282
30364
  }
30283
- }, 5e3);
30365
+ }, 5e3).unref();
30284
30366
  }
30285
30367
  }
30286
30368
  }
@@ -31396,132 +31478,131 @@ var PARALL_WIKI_SKILL = `# Parall Wiki
31396
31478
 
31397
31479
  Manage organization wikis via the Parall CLI. Auth is pre-configured.
31398
31480
 
31399
- ## Browsing (no local state needed)
31481
+ ## Mental model
31482
+
31483
+ Wiki editing works on a **local workspace**: \`parall wiki sync\` downloads the
31484
+ wiki into a directory on disk, you edit those files with your normal file
31485
+ tools, then \`parall wiki changeset create\` uploads the result as a proposal.
31486
+ There is no git in the workspace \u2014 your edits are detected by diffing against
31487
+ the synced baseline.
31488
+
31489
+ Key facts the commands won't tell you:
31490
+
31491
+ - **Workspace location is fixed.** Sync output and \`parall wiki status\` print
31492
+ the absolute workspace path (\`synced \u2192 /path/to/<slug>\` / \`Mount: ...\`).
31493
+ Always address wiki files by that absolute path \u2014 your shell cwd is usually
31494
+ NOT inside the workspace.
31495
+ - **Text files only.** Changesets reject binary content. Don't put images or
31496
+ archives in the workspace; binary uploads go through the web UI.
31497
+ - **\`cat\`, \`search\`, \`query\`, \`outline\`, and \`section\` read your local
31498
+ workspace copy when it exists** \u2014 including your own unproposed edits. Add
31499
+ \`--remote\` to \`cat\` to read the server version instead.
31500
+ - **\`search\`/\`query\` are keyword (lexical) matching**, not semantic search.
31501
+ \`query\` additionally ranks whole documents \u2014 better for multi-word
31502
+ questions; \`search\` for a single identifier.
31503
+ - The \`<wiki>\` argument is the slug or ID from \`parall wiki list\`; with a
31504
+ single wiki in the org it can be omitted.
31505
+
31506
+ ## Core workflow
31400
31507
 
31401
31508
  \`\`\`bash
31402
- parall wiki list # List all wikis
31403
- parall wiki tree <slug> # List files and directories
31404
- parall wiki tree <slug> --path docs/ # List a subdirectory
31509
+ parall wiki sync # 1. get/update files (prints workspace path)
31510
+ # 2. read + edit files under the workspace path with standard file tools
31511
+ parall wiki diff <wiki> # 3. review exactly what you'll propose
31512
+ parall wiki changeset create <wiki> --title "..." # 4. submit
31405
31513
  \`\`\`
31406
31514
 
31407
- ## Editing
31408
-
31409
- Wiki editing works on a **local workspace** \u2014 a directory on disk where wiki
31410
- files are synced. You sync from the server, edit files locally, then propose
31411
- a changeset.
31412
-
31413
- ### Step 1: Sync
31414
-
31415
- \`\`\`bash
31416
- parall wiki sync <slug>
31417
- \`\`\`
31515
+ Always sync before starting and always check \`diff\` before proposing \u2014 the
31516
+ changeset uploads the full content of every changed file.
31418
31517
 
31419
- This downloads wiki files to a local directory. The output includes the
31420
- **absolute mount path** for each wiki (e.g. \`synced \u2192 /path/to/workspace/kb\`).
31518
+ Unprotected paths auto-merge immediately (\`auto_merged: true\`); protected
31519
+ paths stay open for human review. Follow the returned \`next_action\` either way.
31421
31520
 
31422
- ### Step 2: Find the mount path
31521
+ ## Stale base (server moved since your sync)
31423
31522
 
31424
- The sync output JSON contains \`synced[].path\` \u2014 the absolute path where files
31425
- live. You can also check it anytime with:
31523
+ If files changed on the server after your last sync, \`changeset create\` is
31524
+ rejected \u2014 both by a CLI precheck and by the server (409 \`STALE_BASE\`) \u2014 so
31525
+ you can't silently overwrite someone's concurrent edit. Recovery:
31426
31526
 
31427
31527
  \`\`\`bash
31428
- parall wiki status <slug>
31528
+ parall wiki sync # pull latest; your local edits are preserved
31529
+ # if a file conflicts, resolve it (see next section)
31530
+ parall wiki changeset create <wiki> --title "..."
31429
31531
  \`\`\`
31430
31532
 
31431
- The output includes \`Mount: /absolute/path/to/<slug>\`.
31533
+ ## Sync conflicts
31432
31534
 
31433
- Use this path with \`read\`, \`write\`, and \`edit\` tools. For example, if the mount
31434
- is \`/data/.openclaw/workspace/kb\`, then \`README.md\` is at
31435
- \`/data/.openclaw/workspace/kb/README.md\`.
31535
+ \`sync\` three-way merges. When both you and the server changed the same file,
31536
+ your file is left intact and the upstream copy lands under
31537
+ \`<workspace>/.parall-wiki/conflicts/\`:
31436
31538
 
31437
- ### Step 3: Edit files
31438
-
31439
- Use standard file tools (\`read\`, \`write\`, \`edit\`) on files under the mount path.
31539
+ | Marker | Meaning |
31540
+ |--------|---------|
31541
+ | \`conflicts/<path>.remote\` | Server has different content for \`<path>\` |
31542
+ | \`conflicts/<path>.remote-deleted\` | Server deleted \`<path>\`; you still have edits |
31440
31543
 
31441
- ### Step 4: Review changes
31544
+ All paths below are relative to the workspace root. Pick one:
31442
31545
 
31443
31546
  \`\`\`bash
31444
- parall wiki diff <slug> # Shows unified diff of all local changes
31445
- parall wiki status <slug> # Shows which files changed with +/- line counts
31446
- \`\`\`
31547
+ # Accept upstream (drop your edit):
31548
+ cp <workspace>/.parall-wiki/conflicts/<path>.remote <workspace>/<path>
31447
31549
 
31448
- Always review before proposing.
31550
+ # Keep yours / hand-merge: edit <workspace>/<path> to final content, then
31551
+ parall wiki changeset create <wiki> --title "Reconcile <path>"
31449
31552
 
31450
- ### Step 5: Propose changeset
31451
-
31452
- \`\`\`bash
31453
- parall wiki changeset create <slug> --title "Description of changes"
31553
+ # Accept server delete (.remote-deleted only):
31554
+ rm <workspace>/<path>
31454
31555
  \`\`\`
31455
31556
 
31456
- This uploads your local changes. Unprotected paths auto-merge immediately; the
31457
- CLI prints \`auto_merged: true\` and refreshes the local manifest. Protected
31458
- paths remain as a changeset for review; follow the returned \`next_action\`.
31557
+ Then re-run \`parall wiki sync\` and delete the used marker file. Conflicts
31558
+ exit 0 (they need your decision); \`failed[]\` entries (download error,
31559
+ shape-conflict) exit 1 and retry on the next sync.
31459
31560
 
31460
- ## Changeset Management
31561
+ ## Changesets
31461
31562
 
31462
31563
  \`\`\`bash
31463
- parall wiki changeset list <slug> # List all changesets
31464
- parall wiki changeset show <changesetId> <slug> # Show detail + feedback
31465
- parall wiki changeset diff <changesetId> <slug> # Show changeset diff
31564
+ parall wiki changeset list <wiki>
31565
+ parall wiki changeset show <changesetId> <wiki> # status + feedback
31566
+ parall wiki changeset diff <changesetId> <wiki>
31567
+ parall wiki changeset create <wiki> --update <id> # re-propose after rejection (title inherited)
31466
31568
  \`\`\`
31467
31569
 
31468
- If a changeset is rejected, fix the files locally and re-propose:
31570
+ Rejected: read the feedback (\`show\` / \`status\`), fix the files, re-propose
31571
+ with \`--update <id>\`. Conflict status: \`sync\`, resolve, then \`--update <id>\`.
31469
31572
 
31470
- \`\`\`bash
31471
- parall wiki changeset create <slug> --update <changesetId>
31472
- \`\`\`
31473
-
31474
- The title is inherited from the original changeset \u2014 no need to repeat it.
31475
-
31476
- ## Handling sync conflicts
31573
+ Re-propose REPLACES the changeset's previous contents with your current
31574
+ workspace diff \u2014 to withdraw a file from the proposal, revert it locally
31575
+ (restore the synced content) and re-propose; it drops out of the changeset.
31477
31576
 
31478
- \`wiki sync\` runs a three-way merge. When both you and the server changed the
31479
- same file, sync **does not overwrite your work**. It leaves your file intact
31480
- and drops the upstream version under \`.parall-wiki/conflicts/\`:
31481
-
31482
- | Marker | Meaning |
31483
- |--------|---------|
31484
- | \`.parall-wiki/conflicts/<path>.remote\` | Server has different content (concurrent edit, new file collision, or server changed a file you deleted) |
31485
- | \`.parall-wiki/conflicts/<path>.remote-deleted\` | Server deleted the file; you still have edits |
31577
+ ## Discovery & history
31486
31578
 
31487
- stderr prints one line per conflict. Recovery:
31488
-
31489
- **Accept upstream** (drop your edit):
31490
- \`\`\`bash
31491
- cp .parall-wiki/conflicts/<path>.remote <path>
31492
- parall wiki sync
31493
- \`\`\`
31494
-
31495
- **Keep yours** (or hand-merge, then propose):
31496
- \`\`\`bash
31497
- # edit <path> to final content
31498
- parall wiki diff <slug>
31499
- parall wiki changeset create <slug> --title "Reconcile <path>"
31500
- parall wiki sync # fast-forwards after server merges
31501
- \`\`\`
31502
-
31503
- **Accept server delete** (\`.remote-deleted\` only):
31504
31579
  \`\`\`bash
31505
- rm <path>
31506
- parall wiki sync
31580
+ parall wiki query "how is auth configured" <wiki> # multi-word lookup (query FIRST, wiki second)
31581
+ parall wiki search "JWT" <wiki> # single keyword (query FIRST, wiki second)
31582
+ parall wiki outline <wiki> --path docs/ # heading structure
31583
+ parall wiki cat docs/auth.md <wiki> # print a file (--remote for server version)
31584
+ parall wiki tree <wiki> # list files
31585
+ parall wiki log <wiki> # recent operations
31586
+ parall wiki log <wiki> docs/auth.md # per-file commit history
31507
31587
  \`\`\`
31508
31588
 
31509
- Sync failures (\`download\`, \`shape-conflict\`) set exit code 1 and retry on
31510
- next sync. Conflicts exit 0 \u2014 they need your decision, not a retry.
31511
-
31512
- ## Discarding local changes
31589
+ ## Permissions
31513
31590
 
31514
- \`\`\`bash
31515
- parall wiki reset <slug> # Restore all files to last synced state
31516
- \`\`\`
31591
+ Reads and writes are ACL-checked server-side per path. \`parall wiki access
31592
+ <path>\` shows your level for a path. On a \`PERMISSION_DENIED\`, errors include
31593
+ a \`Request approval:\` hint \u2014 use \`parall wiki request-access <path> --reason
31594
+ "..."\` to file an approval card for a maintainer, then re-sync after approval.
31517
31595
 
31518
- ## History
31596
+ ## Recovery
31519
31597
 
31520
31598
  \`\`\`bash
31521
- parall wiki log <slug> # Recent wiki operations
31599
+ parall wiki reset <wiki> # discard ALL local edits, restore last-synced state
31600
+ parall wiki status <wiki> # local changes + your changesets, anytime
31522
31601
  \`\`\`
31523
31602
 
31524
- CLI success output is JSON; errors may add a plain-text \`Request approval:\` line on a \`PERMISSION_DENIED\` \u2014 read both. Run \`parall wiki --help\` for full options.
31603
+ CLI success output is JSON on stdout (human summary on stderr); errors state
31604
+ the reason and the next step \u2014 follow them. \`parall wiki --help\` for the
31605
+ full command list.
31525
31606
  `;
31526
31607
 
31527
31608
  // ts/agent-core/dist/skills/parall-schedules.js
@@ -32562,6 +32643,9 @@ function buildSpawnEnv(parentEnv, claudeHome, context2, opts) {
32562
32643
  PRLL_CONTEXT_FILE: context2.contextFilePath ?? "",
32563
32644
  PRLL_STEP_ID_FILE: context2.stepIdFilePath ?? ""
32564
32645
  };
32646
+ if (!result.PRLL_WIKI_MOUNT_ROOT?.trim() && opts.wikiMountRoot) {
32647
+ result.PRLL_WIKI_MOUNT_ROOT = opts.wikiMountRoot;
32648
+ }
32565
32649
  if (opts.effortLevel) {
32566
32650
  result.CLAUDE_CODE_EFFORT_LEVEL = opts.effortLevel;
32567
32651
  }
@@ -32868,7 +32952,11 @@ var ClaudeCodeAdapter = class {
32868
32952
  }
32869
32953
  spawnProcess(sessionKey, log2) {
32870
32954
  const args = this.buildArgs(sessionKey);
32871
- const env = buildSpawnEnv(process.env, this.opts.claudeHome, this.buildPlaceholderContext(sessionKey), { allowApiKey: this.opts.allowApiKey, effortLevel: this._effortLevel });
32955
+ const env = buildSpawnEnv(process.env, this.opts.claudeHome, this.buildPlaceholderContext(sessionKey), {
32956
+ allowApiKey: this.opts.allowApiKey,
32957
+ effortLevel: this._effortLevel,
32958
+ wikiMountRoot: this.opts.workspaceDir
32959
+ });
32872
32960
  log2?.info(`spawn long-lived ${this.opts.claudeBin} (session ${sessionKey}, model=${this._model || "default"}, effort=${this._effortLevel || "default"}, mode=${this.opts.permissionMode})`);
32873
32961
  const proc = spawn(IS_WIN32 ? quoteWin32Arg(this.opts.claudeBin) : this.opts.claudeBin, IS_WIN32 ? args.map(quoteWin32Arg) : args, {
32874
32962
  cwd: this.opts.workspaceDir,