@parall/daemon 1.42.0 → 1.43.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.
@@ -83,6 +83,9 @@ var init_daemon_update_mode = __esm({
83
83
  });
84
84
 
85
85
  // ts/agent-core/dist/provider-config.js
86
+ function llmSource(pc) {
87
+ return effectiveLLMSourceExplicit(pc) || "parall";
88
+ }
86
89
  function effectiveLLMSourceExplicit(pc) {
87
90
  if (pc?.llm_source)
88
91
  return pc.llm_source;
@@ -119,63 +122,6 @@ var init_lane_key = __esm({
119
122
  }
120
123
  });
121
124
 
122
- // ts/agent-core/dist/session-state.js
123
- var init_session_state = __esm({
124
- "ts/agent-core/dist/session-state.js"() {
125
- "use strict";
126
- }
127
- });
128
-
129
- // ts/agent-core/dist/routing.js
130
- var init_routing = __esm({
131
- "ts/agent-core/dist/routing.js"() {
132
- "use strict";
133
- }
134
- });
135
-
136
- // ts/agent-core/dist/event-format.js
137
- var init_event_format = __esm({
138
- "ts/agent-core/dist/event-format.js"() {
139
- "use strict";
140
- }
141
- });
142
-
143
- // ts/agent-core/dist/prompt-fragments.js
144
- var init_prompt_fragments = __esm({
145
- "ts/agent-core/dist/prompt-fragments.js"() {
146
- "use strict";
147
- }
148
- });
149
-
150
- // ts/agent-core/dist/bridge-workspace.js
151
- var init_bridge_workspace = __esm({
152
- "ts/agent-core/dist/bridge-workspace.js"() {
153
- "use strict";
154
- }
155
- });
156
-
157
- // ts/agent-core/dist/dispatch-adapter.js
158
- var init_dispatch_adapter = __esm({
159
- "ts/agent-core/dist/dispatch-adapter.js"() {
160
- "use strict";
161
- }
162
- });
163
-
164
- // ts/agent-core/dist/logger.js
165
- function createLogger(prefix) {
166
- return {
167
- info: (msg) => console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
168
- warn: (msg) => console.warn(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
169
- error: (msg) => console.error(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
170
- child: (sub) => createLogger(`${prefix}:${sub}`)
171
- };
172
- }
173
- var init_logger = __esm({
174
- "ts/agent-core/dist/logger.js"() {
175
- "use strict";
176
- }
177
- });
178
-
179
125
  // ts/sdk/dist/types.js
180
126
  var init_types2 = __esm({
181
127
  "ts/sdk/dist/types.js"() {
@@ -669,6 +615,7 @@ var init_client = __esm({
669
615
  setTokens;
670
616
  refreshPromise = null;
671
617
  swimlaneName;
618
+ getFeatureFlagOverrides;
672
619
  /** Auth endpoints excluded from automatic 401 refresh to prevent recursion. */
673
620
  static AUTH_PATHS = /* @__PURE__ */ new Set([
674
621
  "/auth/login",
@@ -699,7 +646,7 @@ var init_client = __esm({
699
646
  return apiError;
700
647
  }
701
648
  /** Build headers common to all requests (auth, swimlane). */
702
- buildHeaders(extra) {
649
+ buildHeaders(path19, extra) {
703
650
  const headers = {
704
651
  "Content-Type": "application/json",
705
652
  ...extra
@@ -710,6 +657,11 @@ var init_client = __esm({
710
657
  if (this.swimlaneName) {
711
658
  headers["X-Prll-Swimlane"] = this.swimlaneName;
712
659
  }
660
+ if (path19.startsWith(API_BASE)) {
661
+ const overrides = this.getFeatureFlagOverrides?.();
662
+ if (overrides)
663
+ headers["X-Prll-FF-Override"] = overrides;
664
+ }
713
665
  return headers;
714
666
  }
715
667
  constructor(options = {}) {
@@ -720,6 +672,7 @@ var init_client = __esm({
720
672
  this.getRefreshToken = options.getRefreshToken;
721
673
  this.setTokens = options.setTokens;
722
674
  this.swimlaneName = options.swimlaneName;
675
+ this.getFeatureFlagOverrides = options.getFeatureFlagOverrides;
723
676
  }
724
677
  /**
725
678
  * Pick the origin for a request path: wiki-service base for `/wiki/v1`
@@ -727,8 +680,8 @@ var init_client = __esm({
727
680
  * is authoritative, so wiki vs api routing can't drift from how a caller
728
681
  * happens to invoke the client.
729
682
  */
730
- baseUrlFor(path18) {
731
- return path18.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
683
+ baseUrlFor(path19) {
684
+ return path19.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
732
685
  }
733
686
  setToken(token) {
734
687
  this.token = token;
@@ -755,10 +708,10 @@ var init_client = __esm({
755
708
  * REFRESH_THRESHOLD_S, refresh it **before** sending the request.
756
709
  * No-op when the token is still fresh, missing, or un-parseable.
757
710
  */
758
- async ensureFreshToken(path18) {
711
+ async ensureFreshToken(path19) {
759
712
  if (!this.token || !this.getRefreshToken)
760
713
  return;
761
- const pathSuffix = path18.replace(/^\/api\/v1/, "");
714
+ const pathSuffix = path19.replace(/^\/api\/v1/, "");
762
715
  if (_ParallClient.AUTH_PATHS.has(pathSuffix))
763
716
  return;
764
717
  const exp = _ParallClient.decodeJwtExp(this.token);
@@ -790,11 +743,11 @@ var init_client = __esm({
790
743
  this.refreshPromise = null;
791
744
  }
792
745
  }
793
- async request(method, path18, body, query, retried = false, opts) {
746
+ async request(method, path19, body, query, retried = false, opts) {
794
747
  if (!retried) {
795
- await this.ensureFreshToken(path18);
748
+ await this.ensureFreshToken(path19);
796
749
  }
797
- let url = `${this.baseUrlFor(path18)}${path18}`;
750
+ let url = `${this.baseUrlFor(path19)}${path19}`;
798
751
  if (query) {
799
752
  const params = new URLSearchParams();
800
753
  for (const [key, value] of Object.entries(query)) {
@@ -806,7 +759,7 @@ var init_client = __esm({
806
759
  if (qs)
807
760
  url += `?${qs}`;
808
761
  }
809
- const headers = this.buildHeaders();
762
+ const headers = this.buildHeaders(path19);
810
763
  const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
811
764
  const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
812
765
  let res;
@@ -824,12 +777,12 @@ var init_client = __esm({
824
777
  throw _ParallClient.normalizeFetchError(err);
825
778
  }
826
779
  if (res.status === 401) {
827
- const pathSuffix = path18.replace(/^\/api\/v1/, "");
780
+ const pathSuffix = path19.replace(/^\/api\/v1/, "");
828
781
  const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
829
782
  if (!retried && !isAuthPath && this.getRefreshToken) {
830
783
  const refreshed = await this.tryRefresh();
831
784
  if (refreshed) {
832
- return this.request(method, path18, body, query, true, opts);
785
+ return this.request(method, path19, body, query, true, opts);
833
786
  }
834
787
  }
835
788
  if (this.onTokenExpired && !isAuthPath) {
@@ -859,15 +812,15 @@ var init_client = __esm({
859
812
  * hit the 100 MiB cap, so a longer 5-minute timeout is used so a
860
813
  * 50 MiB blob on a slow connection doesn't get chopped at 15 s.
861
814
  */
862
- async multipartRequest(method, path18, body, retried = false) {
815
+ async multipartRequest(method, path19, body, retried = false) {
863
816
  if (!retried) {
864
- await this.ensureFreshToken(path18);
817
+ await this.ensureFreshToken(path19);
865
818
  }
866
- const { "Content-Type": _drop, ...headers } = this.buildHeaders();
819
+ const { "Content-Type": _drop, ...headers } = this.buildHeaders(path19);
867
820
  void _drop;
868
821
  let res;
869
822
  try {
870
- res = await fetch(`${this.baseUrlFor(path18)}${path18}`, {
823
+ res = await fetch(`${this.baseUrlFor(path19)}${path19}`, {
871
824
  method,
872
825
  headers,
873
826
  body,
@@ -877,12 +830,12 @@ var init_client = __esm({
877
830
  throw _ParallClient.normalizeFetchError(err);
878
831
  }
879
832
  if (res.status === 401) {
880
- const pathSuffix = path18.replace(/^\/api\/v1/, "");
833
+ const pathSuffix = path19.replace(/^\/api\/v1/, "");
881
834
  const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
882
835
  if (!retried && !isAuthPath && this.getRefreshToken) {
883
836
  const refreshed = await this.tryRefresh();
884
837
  if (refreshed) {
885
- return this.multipartRequest(method, path18, body, true);
838
+ return this.multipartRequest(method, path19, body, true);
886
839
  }
887
840
  }
888
841
  if (this.onTokenExpired && !isAuthPath) {
@@ -1439,9 +1392,9 @@ var init_client = __esm({
1439
1392
  async retryAgentWorkspaceSetup(orgId, machineId, agentId) {
1440
1393
  return this.request("POST", ENDPOINTS.MACHINE_AGENT_WORKSPACE_SETUP(orgId, machineId, agentId));
1441
1394
  }
1442
- async patchMachineLLMSource(orgId, machineId, llmSource) {
1395
+ async patchMachineLLMSource(orgId, machineId, llmSource2) {
1443
1396
  return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), {
1444
- llm_source: llmSource
1397
+ llm_source: llmSource2
1445
1398
  });
1446
1399
  }
1447
1400
  /**
@@ -1586,8 +1539,8 @@ var init_client = __esm({
1586
1539
  async requestMachineUpdate(orgId, machineId, mandatory = false) {
1587
1540
  await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
1588
1541
  }
1589
- async browseMachineFilesystem(orgId, machineId, path18) {
1590
- return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path18 }, void 0, false, { timeoutMs: 15e3 });
1542
+ async browseMachineFilesystem(orgId, machineId, path19) {
1543
+ return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path19 }, void 0, false, { timeoutMs: 15e3 });
1591
1544
  }
1592
1545
  /** Create a new machine key. Returns the raw key string (shown once) + metadata. */
1593
1546
  async createMachineKey(orgId, machineId, name) {
@@ -1668,7 +1621,7 @@ var init_client = __esm({
1668
1621
  async claimDispatch(orgId, req) {
1669
1622
  return this.request("POST", ENDPOINTS.DISPATCH_CLAIM(orgId), req);
1670
1623
  }
1671
- /** Fold a pending same-target WorkItem into a live lane (409 STALE_LANE when dethroned). */
1624
+ /** Fold into a live lane: 409 STALE_LANE when dethroned; 409 INELIGIBLE_REF for a bad ref. */
1672
1625
  async steerDispatch(orgId, req) {
1673
1626
  return this.request("POST", ENDPOINTS.DISPATCH_STEER(orgId), req);
1674
1627
  }
@@ -1708,7 +1661,7 @@ var init_client = __esm({
1708
1661
  if (currentVersion !== void 0) {
1709
1662
  extra["If-None-Match"] = currentVersion;
1710
1663
  }
1711
- const headers = this.buildHeaders(extra);
1664
+ const headers = this.buildHeaders(ENDPOINTS.PLATFORM_CONFIG, extra);
1712
1665
  let res;
1713
1666
  try {
1714
1667
  res = await fetch(url, {
@@ -2156,8 +2109,8 @@ var init_client = __esm({
2156
2109
  async deleteWikiRestriction(orgId, wikiId, restrictionId) {
2157
2110
  await this.request("DELETE", ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
2158
2111
  }
2159
- async getWikiAccessStatus(orgId, wikiId, path18) {
2160
- return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path18 ? { path: path18 } : void 0);
2112
+ async getWikiAccessStatus(orgId, wikiId, path19) {
2113
+ return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path19 ? { path: path19 } : void 0);
2161
2114
  }
2162
2115
  async createWikiAccessRequest(orgId, wikiId, data) {
2163
2116
  await this.request("POST", ENDPOINTS.WIKI_ACCESS_REQUESTS(orgId, wikiId), data);
@@ -2166,14 +2119,14 @@ var init_client = __esm({
2166
2119
  async getWikiCommits(orgId, wikiId, params) {
2167
2120
  return this.request("GET", ENDPOINTS.WIKI_COMMITS(orgId, wikiId), void 0, params);
2168
2121
  }
2169
- async getWikiFileCommits(orgId, wikiId, path18, params) {
2122
+ async getWikiFileCommits(orgId, wikiId, path19, params) {
2170
2123
  return this.request("GET", ENDPOINTS.WIKI_FILE_COMMITS(orgId, wikiId), void 0, {
2171
- path: path18,
2124
+ path: path19,
2172
2125
  ...params
2173
2126
  });
2174
2127
  }
2175
- async getWikiBlame(orgId, wikiId, path18, ref) {
2176
- return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path: path18, ref });
2128
+ async getWikiBlame(orgId, wikiId, path19, ref) {
2129
+ return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path: path19, ref });
2177
2130
  }
2178
2131
  // ---- Wiki Operations (audit log) ----
2179
2132
  async getWikiOperations(orgId, wikiId, params) {
@@ -2821,10 +2774,69 @@ var init_lane_ledger = __esm({
2821
2774
  });
2822
2775
 
2823
2776
  // ts/agent-core/dist/gateway-lane-flow.js
2777
+ var TYPED_BACKOFF_CAP_MS;
2824
2778
  var init_gateway_lane_flow = __esm({
2825
2779
  "ts/agent-core/dist/gateway-lane-flow.js"() {
2826
2780
  "use strict";
2827
2781
  init_lane_ledger();
2782
+ TYPED_BACKOFF_CAP_MS = 5 * 6e4;
2783
+ }
2784
+ });
2785
+
2786
+ // ts/agent-core/dist/session-state.js
2787
+ var init_session_state = __esm({
2788
+ "ts/agent-core/dist/session-state.js"() {
2789
+ "use strict";
2790
+ }
2791
+ });
2792
+
2793
+ // ts/agent-core/dist/routing.js
2794
+ var init_routing = __esm({
2795
+ "ts/agent-core/dist/routing.js"() {
2796
+ "use strict";
2797
+ }
2798
+ });
2799
+
2800
+ // ts/agent-core/dist/event-format.js
2801
+ var init_event_format = __esm({
2802
+ "ts/agent-core/dist/event-format.js"() {
2803
+ "use strict";
2804
+ }
2805
+ });
2806
+
2807
+ // ts/agent-core/dist/prompt-fragments.js
2808
+ var init_prompt_fragments = __esm({
2809
+ "ts/agent-core/dist/prompt-fragments.js"() {
2810
+ "use strict";
2811
+ }
2812
+ });
2813
+
2814
+ // ts/agent-core/dist/bridge-workspace.js
2815
+ var init_bridge_workspace = __esm({
2816
+ "ts/agent-core/dist/bridge-workspace.js"() {
2817
+ "use strict";
2818
+ }
2819
+ });
2820
+
2821
+ // ts/agent-core/dist/dispatch-adapter.js
2822
+ var init_dispatch_adapter = __esm({
2823
+ "ts/agent-core/dist/dispatch-adapter.js"() {
2824
+ "use strict";
2825
+ }
2826
+ });
2827
+
2828
+ // ts/agent-core/dist/logger.js
2829
+ function createLogger(prefix) {
2830
+ return {
2831
+ info: (msg) => console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
2832
+ warn: (msg) => console.warn(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
2833
+ error: (msg) => console.error(`${(/* @__PURE__ */ new Date()).toISOString()} [${prefix}] ${msg}`),
2834
+ child: (sub) => createLogger(`${prefix}:${sub}`)
2835
+ };
2836
+ }
2837
+ var init_logger = __esm({
2838
+ "ts/agent-core/dist/logger.js"() {
2839
+ "use strict";
2828
2840
  }
2829
2841
  });
2830
2842
 
@@ -20507,9 +20519,9 @@ var require_getMachineId_linux = __commonJS({
20507
20519
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
20508
20520
  async function getMachineId() {
20509
20521
  const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
20510
- for (const path18 of paths) {
20522
+ for (const path19 of paths) {
20511
20523
  try {
20512
- const result = await fs_1.promises.readFile(path18, { encoding: "utf8" });
20524
+ const result = await fs_1.promises.readFile(path19, { encoding: "utf8" });
20513
20525
  return result.trim();
20514
20526
  } catch (e) {
20515
20527
  api_1.diag.debug(`error reading machine id: ${e}`);
@@ -20719,7 +20731,7 @@ var require_ProcessDetectorSync = __commonJS({
20719
20731
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
20720
20732
  var semantic_conventions_1 = (init_esm2(), __toCommonJS(esm_exports2));
20721
20733
  var Resource_1 = require_Resource();
20722
- var os6 = __require("os");
20734
+ var os8 = __require("os");
20723
20735
  var ProcessDetectorSync = class {
20724
20736
  detect(_config) {
20725
20737
  const attributes = {
@@ -20739,7 +20751,7 @@ var require_ProcessDetectorSync = __commonJS({
20739
20751
  attributes[semantic_conventions_1.SEMRESATTRS_PROCESS_COMMAND] = process.argv[1];
20740
20752
  }
20741
20753
  try {
20742
- const userInfo = os6.userInfo();
20754
+ const userInfo = os8.userInfo();
20743
20755
  attributes[semantic_conventions_1.SEMRESATTRS_PROCESS_OWNER] = userInfo.username;
20744
20756
  } catch (e) {
20745
20757
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -23912,7 +23924,7 @@ function appendRootPathToUrlIfNeeded(url) {
23912
23924
  return void 0;
23913
23925
  }
23914
23926
  }
23915
- function appendResourcePathToUrl(url, path18) {
23927
+ function appendResourcePathToUrl(url, path19) {
23916
23928
  try {
23917
23929
  new URL(url);
23918
23930
  } catch (_a) {
@@ -23922,11 +23934,11 @@ function appendResourcePathToUrl(url, path18) {
23922
23934
  if (!url.endsWith("/")) {
23923
23935
  url = url + "/";
23924
23936
  }
23925
- url += path18;
23937
+ url += path19;
23926
23938
  try {
23927
23939
  new URL(url);
23928
23940
  } catch (_b) {
23929
- diag2.warn("Configuration: Provided URL appended with '" + path18 + "' is not a valid URL, using 'undefined' instead of '" + url + "'");
23941
+ diag2.warn("Configuration: Provided URL appended with '" + path19 + "' is not a valid URL, using 'undefined' instead of '" + url + "'");
23930
23942
  return void 0;
23931
23943
  }
23932
23944
  return url;
@@ -29387,6 +29399,20 @@ var init_platform_config = __esm({
29387
29399
  }
29388
29400
  });
29389
29401
 
29402
+ // ts/agent-core/dist/channel-capability.js
29403
+ var init_channel_capability = __esm({
29404
+ "ts/agent-core/dist/channel-capability.js"() {
29405
+ "use strict";
29406
+ }
29407
+ });
29408
+
29409
+ // ts/agent-core/dist/channel-token.js
29410
+ var init_channel_token = __esm({
29411
+ "ts/agent-core/dist/channel-token.js"() {
29412
+ "use strict";
29413
+ }
29414
+ });
29415
+
29390
29416
  // ts/agent-core/dist/skills/parall-platform.js
29391
29417
  var init_parall_platform = __esm({
29392
29418
  "ts/agent-core/dist/skills/parall-platform.js"() {
@@ -29455,6 +29481,7 @@ var init_dist2 = __esm({
29455
29481
  init_provider_config();
29456
29482
  init_types();
29457
29483
  init_lane_key();
29484
+ init_gateway_lane_flow();
29458
29485
  init_session_state();
29459
29486
  init_routing();
29460
29487
  init_event_format();
@@ -29464,6 +29491,8 @@ var init_dist2 = __esm({
29464
29491
  init_logger();
29465
29492
  init_gateway_base();
29466
29493
  init_platform_config();
29494
+ init_channel_capability();
29495
+ init_channel_token();
29467
29496
  init_skills();
29468
29497
  init_telemetry();
29469
29498
  }
@@ -29474,6 +29503,7 @@ var config_exports = {};
29474
29503
  __export(config_exports, {
29475
29504
  agentClaudeCredentialsFileFor: () => agentClaudeCredentialsFileFor,
29476
29505
  agentClaudeHomeFor: () => agentClaudeHomeFor,
29506
+ agentHomeDirFor: () => agentHomeDirFor,
29477
29507
  agentStateDirFor: () => agentStateDirFor,
29478
29508
  agentWorkspaceDirFor: () => agentWorkspaceDirFor,
29479
29509
  daemonConfigDir: () => daemonConfigDir,
@@ -29560,7 +29590,8 @@ function resolveClaudeDaemonConfig(env = process.env) {
29560
29590
  updateCdnUrl: env.PRLL_DAEMON_UPDATE_CDN_URL?.trim() || ((env.PRLL_DAEMON_UPDATE_CHANNEL?.trim() ?? "production") === "staging" ? "https://releases.staging.prll.sh/daemon/staging" : "https://releases.parall.com/daemon/production"),
29561
29591
  updateIntervalMs: parseMsAllowZero(env.PRLL_DAEMON_UPDATE_INTERVAL_MS, 6 * 60 * 6e4),
29562
29592
  updateDisabled: env.PRLL_DAEMON_UPDATE_DISABLED === "true" || !!env.KUBERNETES_SERVICE_HOST,
29563
- updateConfirmDelayMs: parseMsAllowZero(env.PRLL_DAEMON_UPDATE_CONFIRM_DELAY_MS?.trim() || void 0, 6e4)
29593
+ updateConfirmDelayMs: parseMsAllowZero(env.PRLL_DAEMON_UPDATE_CONFIRM_DELAY_MS?.trim() || void 0, 6e4),
29594
+ homeIsolationDisabled: env.PRLL_DAEMON_HOME_ISOLATION?.trim() === "0"
29564
29595
  };
29565
29596
  }
29566
29597
  function assertSafeAgentId(agentId) {
@@ -29584,6 +29615,9 @@ function agentClaudeCredentialsFileFor(agentClaudeHome) {
29584
29615
  function agentWorkspaceDirFor(rootStateDir, agentId) {
29585
29616
  return path3.join(rootStateDir, "agents", assertSafeAgentId(agentId), "workspace");
29586
29617
  }
29618
+ function agentHomeDirFor(rootStateDir, agentId) {
29619
+ return path3.join(rootStateDir, "agents", assertSafeAgentId(agentId), "home");
29620
+ }
29587
29621
  function resolveUpdateSigningEnabled(env = process.env) {
29588
29622
  return env.PRLL_DAEMON_SIGNING_DISABLED !== "1";
29589
29623
  }
@@ -31098,6 +31132,7 @@ var init_manifest = __esm({
31098
31132
 
31099
31133
  // ts/daemon/dist/runtimes.js
31100
31134
  import * as fs7 from "node:fs";
31135
+ import * as os4 from "node:os";
31101
31136
  import * as path9 from "node:path";
31102
31137
  function buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
31103
31138
  const env = { ...baseEnv };
@@ -31110,6 +31145,8 @@ function buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
31110
31145
  env.PRLL_WORKSPACE_DIR = dirs.workspaceDir;
31111
31146
  if (pc)
31112
31147
  env.PRLL_PROVIDER_CONFIG = JSON.stringify(pc);
31148
+ if (dirs.homeDir)
31149
+ env.HOME = dirs.homeDir;
31113
31150
  delete env.PRLL_DAEMON_MODE;
31114
31151
  return env;
31115
31152
  }
@@ -31153,7 +31190,11 @@ var init_runtimes = __esm({
31153
31190
  args: [],
31154
31191
  buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
31155
31192
  const env = buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc);
31156
- env.PRLL_CODEX_HOME = path9.join(dirs.stateDir, ".codex");
31193
+ if (baseEnv.KUBERNETES_SERVICE_HOST || llmSource(pc) !== "runtime_auth") {
31194
+ env.PRLL_CODEX_HOME = path9.join(dirs.stateDir, ".codex");
31195
+ } else if (dirs.homeDir && !env.CODEX_HOME) {
31196
+ env.CODEX_HOME = path9.join(baseEnv.HOME || os4.homedir(), ".codex");
31197
+ }
31157
31198
  return env;
31158
31199
  }
31159
31200
  };
@@ -32403,7 +32444,7 @@ var init_process_manager = __esm({
32403
32444
  * (GetBindings), then forward the invoke through the hub (Invoke) to the bound
32404
32445
  * BrowserProfile's host. No local shortcut, no fallback — unbound is rejected.
32405
32446
  * The execution daemon never verifies clip_token; the hub does.
32406
- * See docs/engineering-design/browser-profile-clip-integration.md §11.3.
32447
+ * See docs/archive/engineering-design/browser-profile-clip-integration.md §11.3.
32407
32448
  */
32408
32449
  async invokeDependency(clipName, command, input, context2) {
32409
32450
  if (!isBrowserDependencyName(clipName)) {
@@ -32436,7 +32477,7 @@ var init_process_manager = __esm({
32436
32477
  * synthetic "browser" clip). The hub forwards clip_token as the PLAINTEXT
32437
32478
  * browser_profile_id, which the host daemon uses directly as the bb-browser
32438
32479
  * account. Only daemons that host BrowserProfiles register this capability.
32439
- * See docs/engineering-design/browser-profile-clip-integration.md §11.2.
32480
+ * See docs/archive/engineering-design/browser-profile-clip-integration.md §11.2.
32440
32481
  */
32441
32482
  async invokeBrowserCapability(clipToken, command, input) {
32442
32483
  if (!this.browserProfileManager) {
@@ -34791,7 +34832,7 @@ var init_clip_runtime = __esm({
34791
34832
  // ts/daemon/dist/filesystem.js
34792
34833
  import * as fs9 from "fs";
34793
34834
  import * as path13 from "path";
34794
- import * as os4 from "os";
34835
+ import * as os5 from "os";
34795
34836
  function browseDenyReason(value) {
34796
34837
  const normalized = path13.resolve(value).split(path13.sep).join("/");
34797
34838
  if (normalized === "/")
@@ -34811,8 +34852,8 @@ function browseDenyReason(value) {
34811
34852
  }
34812
34853
  function syntheticRoots() {
34813
34854
  const roots = [];
34814
- const platform2 = os4.platform();
34815
- const candidates = platform2 === "darwin" ? ["/Users", os4.homedir()] : ["/home", os4.homedir()];
34855
+ const platform2 = os5.platform();
34856
+ const candidates = platform2 === "darwin" ? ["/Users", os5.homedir()] : ["/home", os5.homedir()];
34816
34857
  for (const dir of [...new Set(candidates)]) {
34817
34858
  try {
34818
34859
  fs9.accessSync(dir, fs9.constants.R_OK);
@@ -34908,11 +34949,108 @@ var init_filesystem = __esm({
34908
34949
  }
34909
34950
  });
34910
34951
 
34911
- // ts/daemon/dist/runtime-bin-resolver.js
34912
- import { execFileSync as execFileSync3 } from "node:child_process";
34952
+ // ts/daemon/dist/home-isolation.js
34913
34953
  import * as fs10 from "node:fs";
34914
- import * as os5 from "node:os";
34915
34954
  import * as path14 from "node:path";
34955
+ function ensureIsolatedHome(spec, agentId, log2, platform2 = process.platform) {
34956
+ fs10.mkdirSync(spec.homeDir, { recursive: true });
34957
+ const failures = [];
34958
+ const attempt = (label, fn) => {
34959
+ try {
34960
+ fn();
34961
+ } catch (err) {
34962
+ failures.push(`${label}: ${String(err)}`);
34963
+ }
34964
+ };
34965
+ attempt(".claude link", () => {
34966
+ fs10.mkdirSync(path14.join(spec.claudeStateRoot, ".claude"), { recursive: true });
34967
+ ensureLink(path14.join(spec.homeDir, ".claude"), path14.join(spec.claudeStateRoot, ".claude"), agentId, log2);
34968
+ });
34969
+ attempt(".claude.json link", () => ensureLink(path14.join(spec.homeDir, ".claude.json"), path14.join(spec.claudeStateRoot, ".claude.json"), agentId, log2));
34970
+ if (platform2 === "darwin") {
34971
+ attempt("Library/Keychains link", () => {
34972
+ fs10.mkdirSync(path14.join(spec.homeDir, "Library"), { recursive: true });
34973
+ ensureLink(path14.join(spec.homeDir, "Library", "Keychains"), path14.join(spec.systemHome, "Library", "Keychains"), agentId, log2);
34974
+ });
34975
+ }
34976
+ attempt(".gitconfig", () => {
34977
+ const gitconfig = path14.join(spec.homeDir, ".gitconfig");
34978
+ if (!fs10.existsSync(gitconfig)) {
34979
+ fs10.writeFileSync(gitconfig, `[user]
34980
+ name = ${gitConfigValue(spec.gitUserName)}
34981
+ email = ${gitConfigValue(spec.gitUserEmail)}
34982
+ `, { mode: 420 });
34983
+ log2.info(`agent ${agentId}: wrote per-agent .gitconfig (${spec.gitUserName})`);
34984
+ }
34985
+ });
34986
+ return failures;
34987
+ }
34988
+ function gitConfigValue(value) {
34989
+ const flat = value.replace(/[\r\n\t]+/g, " ").trim();
34990
+ return `"${flat.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
34991
+ }
34992
+ function ensureLink(linkPath, target, agentId, log2) {
34993
+ let existing;
34994
+ try {
34995
+ existing = fs10.lstatSync(linkPath);
34996
+ } catch (err) {
34997
+ if (err.code !== "ENOENT")
34998
+ throw err;
34999
+ }
35000
+ if (existing) {
35001
+ if (existing.isSymbolicLink()) {
35002
+ const current = fs10.readlinkSync(linkPath);
35003
+ if (path14.resolve(path14.dirname(linkPath), current) === path14.resolve(target))
35004
+ return;
35005
+ fs10.unlinkSync(linkPath);
35006
+ log2.info(`agent ${agentId}: relinking ${linkPath} \u2192 ${target}`);
35007
+ } else {
35008
+ const preserved = `${linkPath}.pre-isolation.${Date.now()}`;
35009
+ fs10.renameSync(linkPath, preserved);
35010
+ log2.warn(`agent ${agentId}: ${linkPath} was a real ${existing.isDirectory() ? "directory" : "file"}, not the expected passthrough symlink \u2014 preserved at ${preserved} and relinked`);
35011
+ }
35012
+ }
35013
+ fs10.symlinkSync(target, linkPath);
35014
+ }
35015
+ function ensureSharedCredentialLink(rootClaudeHome, agentClaudeHome, agentId, log2) {
35016
+ const sharedCredentials = path14.resolve(sharedClaudeCredentialsFileFor(rootClaudeHome));
35017
+ const agentCredentials = agentClaudeCredentialsFileFor(agentClaudeHome);
35018
+ const agentCredentialsDir = path14.dirname(agentCredentials);
35019
+ fs10.mkdirSync(path14.dirname(sharedCredentials), { recursive: true });
35020
+ fs10.mkdirSync(agentCredentialsDir, { recursive: true });
35021
+ try {
35022
+ const existing = fs10.lstatSync(agentCredentials);
35023
+ if (existing.isSymbolicLink()) {
35024
+ const currentTarget = fs10.readlinkSync(agentCredentials);
35025
+ if (path14.resolve(agentCredentialsDir, currentTarget) === sharedCredentials) {
35026
+ return;
35027
+ }
35028
+ fs10.unlinkSync(agentCredentials);
35029
+ } else if (existing.isDirectory()) {
35030
+ log2.warn(`agent ${agentId}: credential path is a directory, cannot link ${agentCredentials}`);
35031
+ return;
35032
+ } else {
35033
+ fs10.unlinkSync(agentCredentials);
35034
+ }
35035
+ } catch (err) {
35036
+ if (err.code !== "ENOENT") {
35037
+ throw err;
35038
+ }
35039
+ }
35040
+ fs10.symlinkSync(sharedCredentials, agentCredentials);
35041
+ }
35042
+ var init_home_isolation = __esm({
35043
+ "ts/daemon/dist/home-isolation.js"() {
35044
+ "use strict";
35045
+ init_config();
35046
+ }
35047
+ });
35048
+
35049
+ // ts/daemon/dist/runtime-bin-resolver.js
35050
+ import { execFileSync as execFileSync3 } from "node:child_process";
35051
+ import * as fs11 from "node:fs";
35052
+ import * as os6 from "node:os";
35053
+ import * as path15 from "node:path";
34916
35054
  function runtimeBinaryEnvVar(runtimeType) {
34917
35055
  return RUNTIME_BINARIES[runtimeType]?.envVar;
34918
35056
  }
@@ -34989,16 +35127,16 @@ function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbac
34989
35127
  function resolveDirectPath(command) {
34990
35128
  if (!command.includes("/") && !command.includes("\\"))
34991
35129
  return null;
34992
- const abs = path14.isAbsolute(command) ? command : path14.resolve(process.cwd(), command);
35130
+ const abs = path15.isAbsolute(command) ? command : path15.resolve(process.cwd(), command);
34993
35131
  return isExecutable(abs) ? abs : null;
34994
35132
  }
34995
35133
  function resolveFromPath(command, pathValue, env) {
34996
35134
  if (!pathValue || command.includes("/") || command.includes("\\"))
34997
35135
  return null;
34998
- const dirs = pathValue.split(path14.delimiter).filter(Boolean);
35136
+ const dirs = pathValue.split(path15.delimiter).filter(Boolean);
34999
35137
  for (const dir of dirs) {
35000
35138
  for (const file of commandCandidates(command, env)) {
35001
- const candidate = path14.join(dir, file);
35139
+ const candidate = path15.join(dir, file);
35002
35140
  if (isExecutable(candidate))
35003
35141
  return { binaryPath: candidate, pathValue };
35004
35142
  }
@@ -35037,7 +35175,7 @@ __PRLL_PATH__%s
35037
35175
  if (line.startsWith("__PRLL_PATH__"))
35038
35176
  pathValue = line.slice("__PRLL_PATH__".length);
35039
35177
  }
35040
- if (path14.isAbsolute(binaryPath) && isExecutable(binaryPath)) {
35178
+ if (path15.isAbsolute(binaryPath) && isExecutable(binaryPath)) {
35041
35179
  return { binaryPath, pathValue: pathValue || void 0 };
35042
35180
  }
35043
35181
  } catch {
@@ -35055,25 +35193,25 @@ function cachedCandidatePathPlan(env) {
35055
35193
  return value;
35056
35194
  }
35057
35195
  function candidatePathPlan(env) {
35058
- const home = env.HOME || os5.homedir();
35196
+ const home = env.HOME || os6.homedir();
35059
35197
  const primaryDirs = [
35060
35198
  ...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
35061
35199
  ...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
35062
- path14.dirname(process.execPath),
35063
- path14.join(path14.dirname(process.execPath), "bin"),
35064
- path14.resolve(path14.dirname(process.execPath), "..", "Resources", "bin"),
35065
- path14.join(home, ".local", "bin"),
35066
- path14.join(home, "bin"),
35067
- path14.join(home, ".npm-global", "bin"),
35068
- path14.join(home, "Library", "pnpm"),
35069
- path14.join(home, ".local", "share", "pnpm"),
35070
- path14.join(home, ".volta", "bin"),
35071
- path14.join(home, ".bun", "bin"),
35072
- path14.join(home, ".asdf", "shims"),
35073
- path14.join(home, ".local", "share", "mise", "shims"),
35074
- path14.join(home, ".mise", "shims"),
35075
- path14.join(home, ".fnm", "aliases", "default", "bin"),
35076
- path14.join(home, "Library", "Application Support", "fnm", "aliases", "default", "bin"),
35200
+ path15.dirname(process.execPath),
35201
+ path15.join(path15.dirname(process.execPath), "bin"),
35202
+ path15.resolve(path15.dirname(process.execPath), "..", "Resources", "bin"),
35203
+ path15.join(home, ".local", "bin"),
35204
+ path15.join(home, "bin"),
35205
+ path15.join(home, ".npm-global", "bin"),
35206
+ path15.join(home, "Library", "pnpm"),
35207
+ path15.join(home, ".local", "share", "pnpm"),
35208
+ path15.join(home, ".volta", "bin"),
35209
+ path15.join(home, ".bun", "bin"),
35210
+ path15.join(home, ".asdf", "shims"),
35211
+ path15.join(home, ".local", "share", "mise", "shims"),
35212
+ path15.join(home, ".mise", "shims"),
35213
+ path15.join(home, ".fnm", "aliases", "default", "bin"),
35214
+ path15.join(home, "Library", "Application Support", "fnm", "aliases", "default", "bin"),
35077
35215
  "/opt/homebrew/bin",
35078
35216
  "/usr/local/bin",
35079
35217
  "/usr/bin",
@@ -35092,29 +35230,29 @@ function candidatePathPlan(env) {
35092
35230
  };
35093
35231
  }
35094
35232
  function nvmVersionBinDirs(home) {
35095
- const root = path14.join(home, ".nvm", "versions", "node");
35233
+ const root = path15.join(home, ".nvm", "versions", "node");
35096
35234
  let versions;
35097
35235
  try {
35098
- versions = fs10.readdirSync(root);
35236
+ versions = fs11.readdirSync(root);
35099
35237
  } catch {
35100
35238
  return [];
35101
35239
  }
35102
- return sortVersionNamesDesc(versions).map((version) => path14.join(root, version, "bin"));
35240
+ return sortVersionNamesDesc(versions).map((version) => path15.join(root, version, "bin"));
35103
35241
  }
35104
35242
  function fnmVersionBinDirs(home) {
35105
35243
  const roots = [
35106
- path14.join(home, ".fnm", "node-versions"),
35107
- path14.join(home, "Library", "Application Support", "fnm", "node-versions")
35244
+ path15.join(home, ".fnm", "node-versions"),
35245
+ path15.join(home, "Library", "Application Support", "fnm", "node-versions")
35108
35246
  ];
35109
35247
  const dirs = [];
35110
35248
  for (const root of roots) {
35111
35249
  let versions;
35112
35250
  try {
35113
- versions = fs10.readdirSync(root);
35251
+ versions = fs11.readdirSync(root);
35114
35252
  } catch {
35115
35253
  continue;
35116
35254
  }
35117
- dirs.push(...sortVersionNamesDesc(versions).map((version) => path14.join(root, version, "installation", "bin")));
35255
+ dirs.push(...sortVersionNamesDesc(versions).map((version) => path15.join(root, version, "installation", "bin")));
35118
35256
  }
35119
35257
  return dirs;
35120
35258
  }
@@ -35136,13 +35274,13 @@ function parseVersionName(value) {
35136
35274
  return value.replace(/^v/i, "").split(".").map((part) => Number.parseInt(part, 10)).filter((part) => Number.isFinite(part));
35137
35275
  }
35138
35276
  function splitPath(value) {
35139
- return value?.split(path14.delimiter).filter(Boolean) ?? [];
35277
+ return value?.split(path15.delimiter).filter(Boolean) ?? [];
35140
35278
  }
35141
35279
  function mergePath(prependDirs, existing) {
35142
- return unique([...prependDirs, ...splitPath(existing)]).join(path14.delimiter);
35280
+ return unique([...prependDirs, ...splitPath(existing)]).join(path15.delimiter);
35143
35281
  }
35144
35282
  function anchorResolvedPath(pathValue, resolution) {
35145
- return mergePath([path14.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
35283
+ return mergePath([path15.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
35146
35284
  }
35147
35285
  function commandCandidates(command, env) {
35148
35286
  if (process.platform !== "win32")
@@ -35168,10 +35306,10 @@ function setCachedResolution(cacheKey, value) {
35168
35306
  }
35169
35307
  function isExecutable(file) {
35170
35308
  try {
35171
- const stat = fs10.statSync(file);
35309
+ const stat = fs11.statSync(file);
35172
35310
  if (!stat.isFile())
35173
35311
  return false;
35174
- fs10.accessSync(file, fs10.constants.X_OK);
35312
+ fs11.accessSync(file, fs11.constants.X_OK);
35175
35313
  return true;
35176
35314
  } catch {
35177
35315
  return false;
@@ -35179,7 +35317,7 @@ function isExecutable(file) {
35179
35317
  }
35180
35318
  function isDirectory(dir) {
35181
35319
  try {
35182
- return fs10.statSync(dir).isDirectory();
35320
+ return fs11.statSync(dir).isDirectory();
35183
35321
  } catch {
35184
35322
  return false;
35185
35323
  }
@@ -35296,8 +35434,8 @@ var init_runtime_detector = __esm({
35296
35434
  // ts/daemon/dist/workspace.js
35297
35435
  import { spawn as spawn5 } from "node:child_process";
35298
35436
  import { createHash as createHash3 } from "node:crypto";
35299
- import * as fs11 from "node:fs";
35300
- import * as path15 from "node:path";
35437
+ import * as fs12 from "node:fs";
35438
+ import * as path16 from "node:path";
35301
35439
  async function prepareWorkspace(opts) {
35302
35440
  const prior = opts.attached.workspace_state;
35303
35441
  const plan = buildWorkspacePlan(opts.attached.daemon_config, opts.defaultWorkspaceDir, prior?.config_hash);
@@ -35412,7 +35550,7 @@ function resolveWorkspaceDir(workspace, defaultWorkspaceDir) {
35412
35550
  async function ensureWorkspace(plan, log2) {
35413
35551
  const ws = plan.workspace;
35414
35552
  if (ws.mode === "default") {
35415
- fs11.mkdirSync(plan.workspaceDir, { recursive: true });
35553
+ fs12.mkdirSync(plan.workspaceDir, { recursive: true });
35416
35554
  assertWritableWorkspaceDir(plan.workspaceDir);
35417
35555
  return;
35418
35556
  }
@@ -35420,7 +35558,7 @@ async function ensureWorkspace(plan, log2) {
35420
35558
  assertSafeCustomWorkspacePath(plan);
35421
35559
  let st;
35422
35560
  try {
35423
- st = fs11.statSync(plan.workspaceDir);
35561
+ st = fs12.statSync(plan.workspaceDir);
35424
35562
  } catch (err) {
35425
35563
  if (isNodeError(err) && err.code === "ENOENT") {
35426
35564
  throw new Error(`workspace path does not exist: ${plan.workspaceDir}`);
@@ -35430,7 +35568,7 @@ async function ensureWorkspace(plan, log2) {
35430
35568
  if (!st.isDirectory()) {
35431
35569
  throw new Error(`workspace path is not a directory: ${plan.workspaceDir}`);
35432
35570
  }
35433
- assertSafeCustomWorkspacePath(plan, fs11.realpathSync(plan.workspaceDir));
35571
+ assertSafeCustomWorkspacePath(plan, fs12.realpathSync(plan.workspaceDir));
35434
35572
  assertWritableWorkspaceDir(plan.workspaceDir);
35435
35573
  return;
35436
35574
  }
@@ -35441,17 +35579,17 @@ async function ensureWorkspace(plan, log2) {
35441
35579
  if (plan.customWorkspaceField) {
35442
35580
  assertSafeCustomWorkspacePath(plan);
35443
35581
  }
35444
- if (!fs11.existsSync(plan.workspaceDir)) {
35445
- fs11.mkdirSync(path15.dirname(plan.workspaceDir), { recursive: true });
35446
- assertWritableWorkspaceDir(path15.dirname(plan.workspaceDir));
35582
+ if (!fs12.existsSync(plan.workspaceDir)) {
35583
+ fs12.mkdirSync(path16.dirname(plan.workspaceDir), { recursive: true });
35584
+ assertWritableWorkspaceDir(path16.dirname(plan.workspaceDir));
35447
35585
  await runCommand("git", ["clone", remote, plan.workspaceDir], process.cwd());
35448
35586
  } else {
35449
- const st = fs11.statSync(plan.workspaceDir);
35587
+ const st = fs12.statSync(plan.workspaceDir);
35450
35588
  if (!st.isDirectory()) {
35451
35589
  throw new Error(`workspace path is not a directory: ${plan.workspaceDir}`);
35452
35590
  }
35453
35591
  if (plan.customWorkspaceField) {
35454
- assertSafeCustomWorkspacePath(plan, fs11.realpathSync(plan.workspaceDir));
35592
+ assertSafeCustomWorkspacePath(plan, fs12.realpathSync(plan.workspaceDir));
35455
35593
  }
35456
35594
  assertWritableWorkspaceDir(plan.workspaceDir);
35457
35595
  await ensureGitWorktree(plan.workspaceDir);
@@ -35475,13 +35613,13 @@ async function verifyExistingWorkspace(plan, log2) {
35475
35613
  if (plan.customWorkspaceField) {
35476
35614
  assertSafeCustomWorkspacePath(plan);
35477
35615
  }
35478
- const st = fs11.statSync(plan.workspaceDir);
35616
+ const st = fs12.statSync(plan.workspaceDir);
35479
35617
  if (!st.isDirectory()) {
35480
35618
  log2.warn(`workspace ready state ignored: path is not a directory: ${plan.workspaceDir}`);
35481
35619
  return false;
35482
35620
  }
35483
35621
  if (plan.customWorkspaceField) {
35484
- assertSafeCustomWorkspacePath(plan, fs11.realpathSync(plan.workspaceDir));
35622
+ assertSafeCustomWorkspacePath(plan, fs12.realpathSync(plan.workspaceDir));
35485
35623
  }
35486
35624
  assertWritableWorkspaceDir(plan.workspaceDir);
35487
35625
  if (plan.workspace.mode === "git") {
@@ -35625,10 +35763,10 @@ ${tail}`)));
35625
35763
  });
35626
35764
  }
35627
35765
  function requireAbsolute(value, field) {
35628
- if (!value || !path15.isAbsolute(value)) {
35766
+ if (!value || !path16.isAbsolute(value)) {
35629
35767
  throw new Error(`${field} must be an absolute path`);
35630
35768
  }
35631
- return path15.resolve(value);
35769
+ return path16.resolve(value);
35632
35770
  }
35633
35771
  function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
35634
35772
  if (!plan.customWorkspaceField)
@@ -35638,17 +35776,17 @@ function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
35638
35776
  if (reason) {
35639
35777
  throw new Error(`${plan.customWorkspaceField} must point to a project folder, not ${reason}: ${normalized}`);
35640
35778
  }
35641
- const defaultWorkspace = path15.resolve(plan.defaultWorkspaceDir);
35779
+ const defaultWorkspace = path16.resolve(plan.defaultWorkspaceDir);
35642
35780
  if (isAncestorPath(normalized, defaultWorkspace) || normalized === defaultWorkspace) {
35643
35781
  throw new Error(`${plan.customWorkspaceField} must not point at daemon state directories: ${normalized}`);
35644
35782
  }
35645
35783
  }
35646
35784
  function assertWritableWorkspaceDir(dir) {
35647
- fs11.accessSync(dir, fs11.constants.R_OK | fs11.constants.W_OK | fs11.constants.X_OK);
35648
- const probe = path15.join(dir, `.parall-workspace-check-${process.pid}-${Date.now()}`);
35649
- const fd = fs11.openSync(probe, "wx", 384);
35650
- fs11.closeSync(fd);
35651
- fs11.unlinkSync(probe);
35785
+ fs12.accessSync(dir, fs12.constants.R_OK | fs12.constants.W_OK | fs12.constants.X_OK);
35786
+ const probe = path16.join(dir, `.parall-workspace-check-${process.pid}-${Date.now()}`);
35787
+ const fd = fs12.openSync(probe, "wx", 384);
35788
+ fs12.closeSync(fd);
35789
+ fs12.unlinkSync(probe);
35652
35790
  }
35653
35791
  function workspacePathDenyReason(value) {
35654
35792
  if (value === "/")
@@ -35709,11 +35847,11 @@ function workspacePathDenyReason(value) {
35709
35847
  return "";
35710
35848
  }
35711
35849
  function isAncestorPath(parent, child) {
35712
- const relative2 = path15.relative(parent, child);
35713
- return relative2 !== "" && !relative2.startsWith("..") && !path15.isAbsolute(relative2);
35850
+ const relative2 = path16.relative(parent, child);
35851
+ return relative2 !== "" && !relative2.startsWith("..") && !path16.isAbsolute(relative2);
35714
35852
  }
35715
35853
  function toPolicyPath(value) {
35716
- return path15.resolve(value).split(path15.sep).join("/");
35854
+ return path16.resolve(value).split(path16.sep).join("/");
35717
35855
  }
35718
35856
  function isNodeError(err) {
35719
35857
  return err instanceof Error && "code" in err;
@@ -35730,8 +35868,9 @@ var init_workspace = __esm({
35730
35868
 
35731
35869
  // ts/daemon/dist/supervisor.js
35732
35870
  import { spawn as spawn6 } from "node:child_process";
35733
- import * as fs12 from "node:fs";
35734
- import * as path16 from "node:path";
35871
+ import * as fs13 from "node:fs";
35872
+ import * as os7 from "node:os";
35873
+ import * as path17 from "node:path";
35735
35874
  function sleepCancellable(ms, signal) {
35736
35875
  if (signal.aborted)
35737
35876
  return Promise.resolve(false);
@@ -35758,6 +35897,7 @@ var init_supervisor = __esm({
35758
35897
  init_clip_runtime();
35759
35898
  init_config();
35760
35899
  init_filesystem();
35900
+ init_home_isolation();
35761
35901
  init_runtimes();
35762
35902
  init_runtime_bin_resolver();
35763
35903
  init_runtime_detector();
@@ -35881,7 +36021,7 @@ var init_supervisor = __esm({
35881
36021
  this.migrateFlatLayout();
35882
36022
  if (process.env.PRLL_CLIP_RUNTIME_ENABLED === "true") {
35883
36023
  this.browserProfilePool = new BrowserProfilePool({
35884
- baseHomeDir: path16.join(this.config.rootStateDir, "bb-browser"),
36024
+ baseHomeDir: path17.join(this.config.rootStateDir, "bb-browser"),
35885
36025
  log: this.log,
35886
36026
  reportStatus: (profileId, status, errorMsg, generation) => {
35887
36027
  this.client.reportBrowserProfileStatus(profileId, status, errorMsg, generation).catch((err) => this.log.warn(`browser profile status report failed: ${String(err)}`));
@@ -35889,8 +36029,8 @@ var init_supervisor = __esm({
35889
36029
  resolveProxy: (profileId) => this.resolveBrowserProfileProxy(profileId)
35890
36030
  });
35891
36031
  this.clipManager = new ClipProcessManager({
35892
- clipsDir: path16.join(this.config.rootStateDir, "clips"),
35893
- dataDir: path16.join(this.config.rootStateDir, "clip-data"),
36032
+ clipsDir: path17.join(this.config.rootStateDir, "clips"),
36033
+ dataDir: path17.join(this.config.rootStateDir, "clip-data"),
35894
36034
  browserProfileManager: this.browserProfilePool,
35895
36035
  // Execution side: nested browser dependency invokes resolve their
35896
36036
  // binding and route through the hub (no local shortcut).
@@ -36119,6 +36259,22 @@ var init_supervisor = __esm({
36119
36259
  }
36120
36260
  await this.spawnAgent(userId, orgId, a);
36121
36261
  } else {
36262
+ const isolationChanged = !existing.shuttingDown && !!existing.homeIsolation !== !!this.buildHomeIsolationSpec(a, userId);
36263
+ if (isolationChanged) {
36264
+ this.log.info(`agent ${userId}: home isolation changed while disconnected \u2014 rebuilding child`);
36265
+ existing.shuttingDown = true;
36266
+ if (existing.restartTimer) {
36267
+ clearTimeout(existing.restartTimer);
36268
+ existing.restartTimer = null;
36269
+ }
36270
+ await this.terminateChild(existing);
36271
+ this.children.delete(userId);
36272
+ const orgId = this.machineOrgId;
36273
+ if (orgId) {
36274
+ await this.spawnAgent(userId, orgId, a);
36275
+ }
36276
+ continue;
36277
+ }
36122
36278
  const configChanged = JSON.stringify(existing.providerConfig ?? null) !== JSON.stringify(a.provider_config ?? null);
36123
36279
  existing.providerConfig = a.provider_config;
36124
36280
  if (!existing.child && !existing.restartTimer && !existing.shuttingDown) {
@@ -36279,15 +36435,15 @@ var init_supervisor = __esm({
36279
36435
  */
36280
36436
  migrateFlatLayout() {
36281
36437
  const root = this.config.rootStateDir;
36282
- const agentsDir = path16.join(root, "agents");
36283
- const flatWorkspace = path16.join(root, "workspace");
36284
- if (!fs12.existsSync(flatWorkspace) || fs12.existsSync(agentsDir))
36438
+ const agentsDir = path17.join(root, "agents");
36439
+ const flatWorkspace = path17.join(root, "workspace");
36440
+ if (!fs13.existsSync(flatWorkspace) || fs13.existsSync(agentsDir))
36285
36441
  return;
36286
36442
  let ownerAgentId;
36287
- const sessionsDir = path16.join(root, "sessions");
36288
- if (fs12.existsSync(sessionsDir)) {
36443
+ const sessionsDir = path17.join(root, "sessions");
36444
+ if (fs13.existsSync(sessionsDir)) {
36289
36445
  try {
36290
- for (const file of fs12.readdirSync(sessionsDir)) {
36446
+ for (const file of fs13.readdirSync(sessionsDir)) {
36291
36447
  if (!file.endsWith(".json"))
36292
36448
  continue;
36293
36449
  const decoded = Buffer.from(file.replace(".json", ""), "base64url").toString();
@@ -36301,13 +36457,13 @@ var init_supervisor = __esm({
36301
36457
  }
36302
36458
  }
36303
36459
  const targetId = ownerAgentId ?? "_orphan";
36304
- const targetDir = path16.join(agentsDir, targetId);
36460
+ const targetDir = path17.join(agentsDir, targetId);
36305
36461
  try {
36306
- fs12.mkdirSync(targetDir, { recursive: true });
36462
+ fs13.mkdirSync(targetDir, { recursive: true });
36307
36463
  for (const sub of ["workspace", "sessions", "dispatch-context"]) {
36308
- const src = path16.join(root, sub);
36309
- if (fs12.existsSync(src)) {
36310
- fs12.renameSync(src, path16.join(targetDir, sub));
36464
+ const src = path17.join(root, sub);
36465
+ if (fs13.existsSync(src)) {
36466
+ fs13.renameSync(src, path17.join(targetDir, sub));
36311
36467
  }
36312
36468
  }
36313
36469
  this.log.info(`migrated legacy flat state \u2192 agents/${targetId}/`);
@@ -36598,7 +36754,7 @@ var init_supervisor = __esm({
36598
36754
  return this.runtimeDetectInFlight;
36599
36755
  }
36600
36756
  machineClipToConfig(clip) {
36601
- const clipPath = path16.join(this.config.rootStateDir, "clips", clip.alias);
36757
+ const clipPath = path17.join(this.config.rootStateDir, "clips", clip.alias);
36602
36758
  return {
36603
36759
  clipId: clip.clip_id,
36604
36760
  name: clip.alias,
@@ -36664,7 +36820,7 @@ var init_supervisor = __esm({
36664
36820
  if (!sourceRef) {
36665
36821
  throw new Error(`registry clip "${config.name}" is missing source_ref`);
36666
36822
  }
36667
- const expectedPath = path16.join(this.config.rootStateDir, "clips", config.name);
36823
+ const expectedPath = path17.join(this.config.rootStateDir, "clips", config.name);
36668
36824
  const localVersion = this.readInstalledClipVersion(expectedPath);
36669
36825
  if (localVersion && (!config.version || localVersion === config.version)) {
36670
36826
  return { ...config, path: expectedPath, source: expectedPath };
@@ -36682,7 +36838,7 @@ var init_supervisor = __esm({
36682
36838
  const result = await installClip({
36683
36839
  source,
36684
36840
  alias: config.name,
36685
- clipsDir: path16.join(this.config.rootStateDir, "clips"),
36841
+ clipsDir: path17.join(this.config.rootStateDir, "clips"),
36686
36842
  registryUrl: process.env.PRLL_PINIX_REGISTRY_URL?.trim() || void 0
36687
36843
  });
36688
36844
  this.log.info(`clip ensured: ${result.alias} v${result.version} at ${result.path}`);
@@ -36697,7 +36853,7 @@ var init_supervisor = __esm({
36697
36853
  readInstalledClipVersion(dir) {
36698
36854
  for (const file of ["clip.json", "package.json"]) {
36699
36855
  try {
36700
- const raw = fs12.readFileSync(path16.join(dir, file), "utf-8");
36856
+ const raw = fs13.readFileSync(path17.join(dir, file), "utf-8");
36701
36857
  const parsed = JSON.parse(raw);
36702
36858
  if (typeof parsed.version === "string" && parsed.version.trim()) {
36703
36859
  return parsed.version.trim();
@@ -37007,6 +37163,28 @@ var init_supervisor = __esm({
37007
37163
  });
37008
37164
  }
37009
37165
  }
37166
+ /**
37167
+ * Local credential isolation (home-isolation.ts): per-agent opt-in via
37168
+ * daemon_config.home_isolation (unset = legacy shared HOME for existing
37169
+ * agents), machine-level kill switch PRLL_DAEMON_HOME_ISOLATION=0. K8s
37170
+ * pods never take this path — they keep the isolated claude-home +
37171
+ * shared-credential-link branch in spawnAgentOnce.
37172
+ */
37173
+ buildHomeIsolationSpec(attached, agentId) {
37174
+ if (process.env.KUBERNETES_SERVICE_HOST)
37175
+ return void 0;
37176
+ if (this.config.homeIsolationDisabled)
37177
+ return void 0;
37178
+ if (attached.daemon_config?.home_isolation !== true)
37179
+ return void 0;
37180
+ return {
37181
+ homeDir: agentHomeDirFor(this.config.rootStateDir, agentId),
37182
+ claudeStateRoot: this.config.rootClaudeHome,
37183
+ systemHome: os7.homedir(),
37184
+ gitUserName: attached.user?.display_name?.trim() || agentId,
37185
+ gitUserEmail: `${agentId}@noreply.parall.com`
37186
+ };
37187
+ }
37010
37188
  async spawnAgentOnce(agentId, orgId, attached) {
37011
37189
  let credential;
37012
37190
  try {
@@ -37018,12 +37196,13 @@ var init_supervisor = __esm({
37018
37196
  const stateDir = agentStateDirFor(this.config.rootStateDir, agentId);
37019
37197
  const defaultWorkspaceDir = agentWorkspaceDirFor(this.config.rootStateDir, agentId);
37020
37198
  const isK8s = !!process.env.KUBERNETES_SERVICE_HOST;
37021
- const claudeHome = isK8s ? agentClaudeHomeFor(this.config.rootClaudeHome, agentId) : this.config.rootClaudeHome;
37199
+ const homeIsolation = this.buildHomeIsolationSpec(attached, agentId);
37200
+ const claudeHome = isK8s ? agentClaudeHomeFor(this.config.rootClaudeHome, agentId) : homeIsolation?.homeDir ?? this.config.rootClaudeHome;
37022
37201
  try {
37023
- fs12.mkdirSync(stateDir, { recursive: true });
37202
+ fs13.mkdirSync(stateDir, { recursive: true });
37024
37203
  if (isK8s) {
37025
- fs12.mkdirSync(claudeHome, { recursive: true });
37026
- this.ensureSharedCredentialLink(claudeHome, agentId);
37204
+ fs13.mkdirSync(claudeHome, { recursive: true });
37205
+ ensureSharedCredentialLink(this.config.rootClaudeHome, claudeHome, agentId, this.log);
37027
37206
  }
37028
37207
  } catch (err) {
37029
37208
  this.log.warn(`mkdir agent dirs (${agentId}) failed: ${String(err)}`);
@@ -37056,6 +37235,7 @@ var init_supervisor = __esm({
37056
37235
  // resolved at startChild time (see resolveProviderConfig) so a respawn
37057
37236
  // after a machine llm_source change picks up the new source.
37058
37237
  providerConfig: attached.provider_config,
37238
+ homeIsolation,
37059
37239
  child: null,
37060
37240
  credential,
37061
37241
  restartAttempts: 0,
@@ -37075,17 +37255,38 @@ var init_supervisor = __esm({
37075
37255
  return;
37076
37256
  }
37077
37257
  assertAgentKey(state.credential.api_key);
37258
+ const effectiveProviderConfig = effectiveLLMSourceExplicit(state.providerConfig) ? state.providerConfig : { llm_source: this.machineLlmSource };
37259
+ let isolation = state.homeIsolation;
37260
+ if (isolation) {
37261
+ try {
37262
+ const failures = ensureIsolatedHome(isolation, state.agentId, this.log);
37263
+ if (failures.length > 0) {
37264
+ const needsPassthrough = state.runtimeType === "claude-code" && llmSource(effectiveProviderConfig) === "runtime_auth";
37265
+ if (needsPassthrough) {
37266
+ this.log.warn(`agent ${state.agentId}: home isolation passthrough failed (${failures.join("; ")}) \u2014 falling back to the shared HOME for this spawn so the runtime keeps its login`);
37267
+ isolation = void 0;
37268
+ } else {
37269
+ this.log.warn(`agent ${state.agentId}: home isolation passthrough incomplete (${failures.join("; ")}) \u2014 keeping the fake HOME (this runtime/source does not need the shared-login links)`);
37270
+ }
37271
+ }
37272
+ } catch (err) {
37273
+ this.log.warn(`agent ${state.agentId}: home isolation setup failed \u2014 falling back to the shared HOME for this spawn: ${String(err)}`);
37274
+ isolation = void 0;
37275
+ }
37276
+ }
37078
37277
  const adapter = getRuntimeAdapter(state.runtimeType);
37079
37278
  const dirs = {
37080
37279
  stateDir: agentStateDirFor(this.config.rootStateDir, state.agentId),
37081
37280
  workspaceDir: state.workspacePath,
37082
- claudeHome: state.claudeHome
37281
+ // Only the isolation-fallback case replaces claudeHome: K8s (isolation
37282
+ // never set) and legacy-shared children keep their state.claudeHome.
37283
+ claudeHome: state.homeIsolation && !isolation ? this.config.rootClaudeHome : state.claudeHome,
37284
+ homeDir: isolation?.homeDir
37083
37285
  };
37084
37286
  let baseEnv = { ...process.env, PRLL_API_URL: this.config.apiUrl };
37085
37287
  if (this.machineId)
37086
37288
  baseEnv.PRLL_MACHINE_ID = this.machineId;
37087
37289
  baseEnv = applyRuntimeBinaryEnv(state.runtimeType, baseEnv, this.log);
37088
- const effectiveProviderConfig = effectiveLLMSourceExplicit(state.providerConfig) ? state.providerConfig : { llm_source: this.machineLlmSource };
37089
37290
  const env = adapter.buildEnv(baseEnv, state.agentId, state.orgId, state.credential.api_key, dirs, effectiveProviderConfig);
37090
37291
  const spawnCmd = adapter.args.length > 0 ? `${adapter.bin} ${adapter.args.join(" ")}` : adapter.bin;
37091
37292
  this.log.info(`spawning agent ${state.agentId} runtime=${state.runtimeType} cmd=${spawnCmd} (attempt ${state.restartAttempts + 1})`);
@@ -37168,33 +37369,6 @@ var init_supervisor = __esm({
37168
37369
  child.once("exit", () => clearTimeout(hardKill));
37169
37370
  });
37170
37371
  }
37171
- ensureSharedCredentialLink(agentClaudeHome, agentId) {
37172
- const sharedCredentials = path16.resolve(sharedClaudeCredentialsFileFor(this.config.rootClaudeHome));
37173
- const agentCredentials = agentClaudeCredentialsFileFor(agentClaudeHome);
37174
- const agentCredentialsDir = path16.dirname(agentCredentials);
37175
- fs12.mkdirSync(path16.dirname(sharedCredentials), { recursive: true });
37176
- fs12.mkdirSync(agentCredentialsDir, { recursive: true });
37177
- try {
37178
- const existing = fs12.lstatSync(agentCredentials);
37179
- if (existing.isSymbolicLink()) {
37180
- const currentTarget = fs12.readlinkSync(agentCredentials);
37181
- if (path16.resolve(agentCredentialsDir, currentTarget) === sharedCredentials) {
37182
- return;
37183
- }
37184
- fs12.unlinkSync(agentCredentials);
37185
- } else if (existing.isDirectory()) {
37186
- this.log.warn(`agent ${agentId}: credential path is a directory, cannot link ${agentCredentials}`);
37187
- return;
37188
- } else {
37189
- fs12.unlinkSync(agentCredentials);
37190
- }
37191
- } catch (err) {
37192
- if (err.code !== "ENOENT") {
37193
- throw err;
37194
- }
37195
- }
37196
- fs12.symlinkSync(sharedCredentials, agentCredentials);
37197
- }
37198
37372
  };
37199
37373
  }
37200
37374
  });
@@ -37400,8 +37574,8 @@ var init_daemon_main = __esm({
37400
37574
  // ts/daemon/dist/index.js
37401
37575
  init_daemon_paths();
37402
37576
  init_daemon_update_mode();
37403
- import * as fs13 from "node:fs";
37404
- import * as path17 from "node:path";
37577
+ import * as fs14 from "node:fs";
37578
+ import * as path18 from "node:path";
37405
37579
  var UPDATE_EXIT_CODE2 = 42;
37406
37580
  function formatError2(reason) {
37407
37581
  if (reason instanceof Error) {
@@ -37417,7 +37591,7 @@ function errnoCode(err) {
37417
37591
  }
37418
37592
  function clearRunningMarker(markerPath) {
37419
37593
  try {
37420
- fs13.unlinkSync(markerPath);
37594
+ fs14.unlinkSync(markerPath);
37421
37595
  } catch (err) {
37422
37596
  if (errnoCode(err) === "ENOENT")
37423
37597
  return;
@@ -37426,15 +37600,15 @@ function clearRunningMarker(markerPath) {
37426
37600
  }
37427
37601
  function prepareDaemonBootstrap(env = process.env, args = process.argv.slice(2)) {
37428
37602
  const bundleDir = resolveBundleDir(env);
37429
- const runningMarker = path17.join(bundleDir, "daemon-running");
37603
+ const runningMarker = path18.join(bundleDir, "daemon-running");
37430
37604
  const lifecycleMarkerEnabled = args.length === 0 && !isSelfUpdateDisabledByEnv(env) && isSelfUpdateManaged(bundleDir, env);
37431
37605
  if (!lifecycleMarkerEnabled) {
37432
37606
  return { lifecycleMarkerEnabled: false, runningMarker, uncleanPrevExit: false };
37433
37607
  }
37434
- const uncleanPrevExit = fs13.existsSync(runningMarker);
37608
+ const uncleanPrevExit = fs14.existsSync(runningMarker);
37435
37609
  try {
37436
- fs13.mkdirSync(bundleDir, { recursive: true });
37437
- fs13.writeFileSync(runningMarker, String(process.pid));
37610
+ fs14.mkdirSync(bundleDir, { recursive: true });
37611
+ fs14.writeFileSync(runningMarker, String(process.pid));
37438
37612
  } catch (err) {
37439
37613
  console.warn(`failed to write daemon running marker: ${formatError2(err)}`);
37440
37614
  }