@clawos-dev/clawd 0.2.602 → 0.2.604

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +781 -607
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -62563,6 +62563,81 @@ var SubscriptionChannelStore = class {
62563
62563
  }
62564
62564
  };
62565
62565
 
62566
+ // src/tools/subscription-channels-apply.ts
62567
+ var import_node_fs36 = __toESM(require("fs"), 1);
62568
+ var import_node_os13 = __toESM(require("os"), 1);
62569
+ var import_node_path41 = __toESM(require("path"), 1);
62570
+ var TABLE_HEADER = /^\s*\[\[?\s*([A-Za-z0-9_.-]+)\s*\]\]?\s*(?:#.*)?$/;
62571
+ var KEY_LINE = /^\s*([A-Za-z0-9_.-]+)\s*=/;
62572
+ function stripCodexProvider(text) {
62573
+ const out = [];
62574
+ let inProviderSection = false;
62575
+ for (const line of text.split("\n")) {
62576
+ const headerMatch = TABLE_HEADER.exec(line);
62577
+ if (headerMatch) {
62578
+ const section = headerMatch[1].trim();
62579
+ inProviderSection = section === "model_providers" || section.startsWith("model_providers.");
62580
+ if (inProviderSection) continue;
62581
+ out.push(line);
62582
+ continue;
62583
+ }
62584
+ if (inProviderSection) continue;
62585
+ const keyMatch = KEY_LINE.exec(line);
62586
+ if (keyMatch) {
62587
+ const key = keyMatch[1].trim();
62588
+ if (key === "model_provider" || key.startsWith("model_providers.")) {
62589
+ continue;
62590
+ }
62591
+ }
62592
+ out.push(line);
62593
+ }
62594
+ return out.join("\n").trim();
62595
+ }
62596
+ function applyCodexSubscriptionChannel(opts) {
62597
+ const codexHome = opts.codexHome || process.env.CODEX_HOME || import_node_path41.default.join(import_node_os13.default.homedir(), ".codex");
62598
+ import_node_fs36.default.mkdirSync(codexHome, { recursive: true });
62599
+ const configFile = import_node_path41.default.join(codexHome, "config.toml");
62600
+ const original = import_node_fs36.default.existsSync(configFile) ? import_node_fs36.default.readFileSync(configFile, "utf8") : "";
62601
+ const rest = stripCodexProvider(original);
62602
+ let content;
62603
+ if (opts.channel) {
62604
+ const ch = opts.channel;
62605
+ content = [
62606
+ 'model_provider = "cliproxyapi"',
62607
+ ...rest ? ["", rest] : [],
62608
+ "",
62609
+ "[model_providers.cliproxyapi]",
62610
+ 'name = "cliproxyapi"',
62611
+ `base_url = ${JSON.stringify(ch.baseUrl)}`,
62612
+ 'wire_api = "responses"',
62613
+ `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
62614
+ ""
62615
+ ].join("\n");
62616
+ } else {
62617
+ content = [
62618
+ 'model_provider = "openai"',
62619
+ ...rest ? ["", rest] : [],
62620
+ ""
62621
+ ].join("\n");
62622
+ }
62623
+ const tmpFile = `${configFile}.tmp.${Date.now()}`;
62624
+ import_node_fs36.default.writeFileSync(tmpFile, content, { mode: 384 });
62625
+ import_node_fs36.default.renameSync(tmpFile, configFile);
62626
+ }
62627
+ function applyPiSubscriptionChannel(opts) {
62628
+ const agentDir = opts.agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path41.default.join(import_node_os13.default.homedir(), ".pi", "agent");
62629
+ if (!import_node_fs36.default.existsSync(agentDir)) return false;
62630
+ const configFile = import_node_path41.default.join(agentDir, "cliproxyapi.json");
62631
+ if (opts.channel) {
62632
+ const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
62633
+ const tmp = `${configFile}.tmp.${Date.now()}`;
62634
+ import_node_fs36.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
62635
+ import_node_fs36.default.renameSync(tmp, configFile);
62636
+ return true;
62637
+ }
62638
+ return false;
62639
+ }
62640
+
62566
62641
  // src/deploy/local-probe.ts
62567
62642
  function pickVersion(s2) {
62568
62643
  return /(\d+)\.(\d+)(?:\.(\d+))?/.exec(s2)?.[0];
@@ -62611,10 +62686,10 @@ async function probeLocalVersion(exec, pkg) {
62611
62686
 
62612
62687
  // src/tools/shell-path.ts
62613
62688
  var import_node_child_process10 = require("child_process");
62614
- var import_node_os13 = __toESM(require("os"), 1);
62689
+ var import_node_os14 = __toESM(require("os"), 1);
62615
62690
  function refreshPathFromLoginShell() {
62616
62691
  if (process.platform === "win32") return;
62617
- const shell = process.env.SHELL ?? import_node_os13.default.userInfo().shell ?? "/bin/zsh";
62692
+ const shell = process.env.SHELL ?? import_node_os14.default.userInfo().shell ?? "/bin/zsh";
62618
62693
  try {
62619
62694
  const out = (0, import_node_child_process10.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
62620
62695
  encoding: "utf8",
@@ -63160,15 +63235,15 @@ async function refreshTunnelUrlOnStartup(deps) {
63160
63235
  }
63161
63236
 
63162
63237
  // src/lark-bot-connector/binding-store.ts
63163
- var import_node_fs36 = __toESM(require("fs"), 1);
63164
- var import_node_path41 = __toESM(require("path"), 1);
63238
+ var import_node_fs37 = __toESM(require("fs"), 1);
63239
+ var import_node_path42 = __toESM(require("path"), 1);
63165
63240
  function createLarkBotBindingStore(personaRoot) {
63166
- const filePath = (personaId2) => import_node_path41.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
63241
+ const filePath = (personaId2) => import_node_path42.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
63167
63242
  const read = (personaId2) => {
63168
63243
  const file = filePath(personaId2);
63169
- if (!import_node_fs36.default.existsSync(file)) return null;
63244
+ if (!import_node_fs37.default.existsSync(file)) return null;
63170
63245
  try {
63171
- const raw = JSON.parse(import_node_fs36.default.readFileSync(file, "utf8"));
63246
+ const raw = JSON.parse(import_node_fs37.default.readFileSync(file, "utf8"));
63172
63247
  if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
63173
63248
  return raw;
63174
63249
  } catch {
@@ -63177,16 +63252,16 @@ function createLarkBotBindingStore(personaRoot) {
63177
63252
  };
63178
63253
  const write = (personaId2, meta) => {
63179
63254
  const file = filePath(personaId2);
63180
- import_node_fs36.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
63255
+ import_node_fs37.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
63181
63256
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
63182
- import_node_fs36.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
63183
- import_node_fs36.default.renameSync(tmp, file);
63257
+ import_node_fs37.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
63258
+ import_node_fs37.default.renameSync(tmp, file);
63184
63259
  };
63185
63260
  return {
63186
63261
  read,
63187
63262
  write,
63188
63263
  remove(personaId2) {
63189
- import_node_fs36.default.rmSync(filePath(personaId2), { force: true });
63264
+ import_node_fs37.default.rmSync(filePath(personaId2), { force: true });
63190
63265
  },
63191
63266
  addRemovedChat(personaId2, chatId) {
63192
63267
  const meta = read(personaId2);
@@ -63338,8 +63413,8 @@ function createLarkBotCloudClient(opts) {
63338
63413
  }
63339
63414
 
63340
63415
  // src/lark-bot-connector/chat-router.ts
63341
- var import_node_fs37 = __toESM(require("fs"), 1);
63342
- var import_node_path42 = __toESM(require("path"), 1);
63416
+ var import_node_fs38 = __toESM(require("fs"), 1);
63417
+ var import_node_path43 = __toESM(require("path"), 1);
63343
63418
  init_protocol();
63344
63419
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
63345
63420
  var LOCAL_TURN_RETRIES = 2;
@@ -63417,9 +63492,9 @@ function createLarkChatRouter(deps) {
63417
63492
  continue;
63418
63493
  }
63419
63494
  const dir = deps.mediaRootFor(env.chatId);
63420
- import_node_fs37.default.mkdirSync(dir, { recursive: true });
63421
- const p3 = import_node_path42.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}.${ext}`);
63422
- import_node_fs37.default.writeFileSync(p3, r2.data);
63495
+ import_node_fs38.default.mkdirSync(dir, { recursive: true });
63496
+ const p3 = import_node_path43.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}.${ext}`);
63497
+ import_node_fs38.default.writeFileSync(p3, r2.data);
63423
63498
  lines.push(`[\u56FE\u7247: ${p3}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
63424
63499
  } catch (err) {
63425
63500
  deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
@@ -63440,9 +63515,9 @@ function createLarkChatRouter(deps) {
63440
63515
  continue;
63441
63516
  }
63442
63517
  const dir = deps.mediaRootFor(env.chatId);
63443
- import_node_fs37.default.mkdirSync(dir, { recursive: true });
63444
- const p3 = import_node_path42.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}-${safeAttachmentName(f2.name)}`);
63445
- import_node_fs37.default.writeFileSync(p3, r2.data);
63518
+ import_node_fs38.default.mkdirSync(dir, { recursive: true });
63519
+ const p3 = import_node_path43.default.join(dir, `${safeMediaName(ownerMessageId)}-${i2}-${safeAttachmentName(f2.name)}`);
63520
+ import_node_fs38.default.writeFileSync(p3, r2.data);
63446
63521
  lines.push(`[\u6587\u4EF6: ${p3}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
63447
63522
  } catch (err) {
63448
63523
  deps.logger?.warn(`larkBot file fetch failed ${f2.key}: ${err.message}`);
@@ -64276,6 +64351,8 @@ var GATEWAY_ROUTES = {
64276
64351
  session: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session`,
64277
64352
  sessionSend: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/${encodeURIComponent(sessionId)}`,
64278
64353
  sessionMirror: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/${encodeURIComponent(sessionId)}/mirror`,
64354
+ eventSession: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session/events`,
64355
+ eventSend: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/events/${encodeURIComponent(sessionId)}`,
64279
64356
  // 调用方自己那块盘的用量(design 2026-09-19-cloud-volume-usage §3.3):同样按人、不挂 persona
64280
64357
  volume: () => "/me/volume",
64281
64358
  // 云 persona 运行看板的数据(design 2026-09-23-cloud-persona-metrics §3.6):只给发布者与管理员(gateway 问中心,design 2026-09-24-cloud-persona-conversations §3.2)
@@ -64396,6 +64473,22 @@ var CloudGatewayClient = class {
64396
64473
  logger: this.deps.logger
64397
64474
  });
64398
64475
  }
64476
+ async openEventSession(personaId2, opts) {
64477
+ const { apiKey, gatewayUrl } = await this.credentials();
64478
+ return openHttpEventSession({
64479
+ fetchImpl: this.fetchImpl,
64480
+ gatewayUrl,
64481
+ apiKey,
64482
+ personaId: personaId2,
64483
+ engineSessionId: opts.toolSessionId,
64484
+ instructions: opts.instructions,
64485
+ purpose: opts.purpose,
64486
+ expectedEngine: opts.expectedEngine,
64487
+ effort: opts.effort,
64488
+ personaMode: opts.personaMode,
64489
+ logger: this.deps.logger
64490
+ });
64491
+ }
64399
64492
  /**
64400
64493
  * 看板数据(design 2026-09-23-cloud-persona-metrics §3.8):GET /metrics/<persona>?window&entry,**原样回**状态码与 body——
64401
64494
  * 形状真源在 gateway 的 cloud-persona-metrics,daemon 只是替浏览器拿本机 api key 转一跳。拿不到 key / 连不上 / 超时 → 抛(路由折成 502)。
@@ -64433,6 +64526,149 @@ var CloudGatewayClient = class {
64433
64526
  return CloudVolumeUsageSchema.parse(body.volume);
64434
64527
  }
64435
64528
  };
64529
+ function openHttpEventSession(opts) {
64530
+ const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, instructions, purpose, effort, personaMode, expectedEngine, logger } = opts;
64531
+ const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
64532
+ const abort = new AbortController();
64533
+ const eventCbs = [];
64534
+ const controlCbs = [];
64535
+ const closeCbs = [];
64536
+ const earlyEvents = [];
64537
+ const earlyControls = [];
64538
+ let closed = false;
64539
+ let readyControl = null;
64540
+ let errorControl = null;
64541
+ let sessionId = null;
64542
+ let resolveReady;
64543
+ let rejectReady;
64544
+ const ready = new Promise((resolve9, reject) => {
64545
+ resolveReady = resolve9;
64546
+ rejectReady = reject;
64547
+ });
64548
+ void ready.catch(() => {
64549
+ });
64550
+ let sendChain = Promise.resolve();
64551
+ const emitControl = (control) => {
64552
+ if (control.kind === "ready") readyControl = control;
64553
+ if (control.kind === "error") errorControl = control;
64554
+ if (!controlCbs.length) earlyControls.push(control);
64555
+ for (const cb of controlCbs) cb(control);
64556
+ };
64557
+ const finish = (message) => {
64558
+ if (closed) return;
64559
+ if (message) emitControl({ kind: "error", message });
64560
+ closed = true;
64561
+ rejectReady(new Error(message ?? "event session closed"));
64562
+ abort.abort();
64563
+ for (const cb of closeCbs) cb();
64564
+ };
64565
+ void (async () => {
64566
+ try {
64567
+ const res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventSession(personaId2), {
64568
+ method: "POST",
64569
+ headers,
64570
+ body: JSON.stringify({ expectedEngine, ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {}, ...purpose ? { purpose } : {}, ...effort ? { effort } : {}, ...personaMode ? { personaMode } : {} }),
64571
+ signal: abort.signal
64572
+ });
64573
+ if (!res.ok || !res.body) {
64574
+ let message = `gateway \u56DE ${res.status}`;
64575
+ try {
64576
+ const body = await res.json();
64577
+ if (typeof body.message === "string") message = body.message;
64578
+ if (body.error === "SESSION_VERSION_EXPIRED" && !message.includes("SESSION_VERSION_EXPIRED")) message = `SESSION_VERSION_EXPIRED: ${message}`;
64579
+ } catch {
64580
+ }
64581
+ finish(message);
64582
+ return;
64583
+ }
64584
+ const reader = res.body.getReader();
64585
+ const decoder = new TextDecoder();
64586
+ let pending = "";
64587
+ for (; ; ) {
64588
+ const { value, done } = await reader.read();
64589
+ if (done) break;
64590
+ pending += decoder.decode(value, { stream: true });
64591
+ const lines = pending.split("\n");
64592
+ pending = lines.pop() ?? "";
64593
+ for (const line of lines) {
64594
+ if (!line.trim()) continue;
64595
+ const data = JSON.parse(line);
64596
+ if (data.clawd === "events") {
64597
+ const events = ParsedEventSchema.array().parse(data.events);
64598
+ if (!eventCbs.length) earlyEvents.push(events);
64599
+ for (const cb of eventCbs) cb(events);
64600
+ continue;
64601
+ }
64602
+ const control = parseControlLine(line);
64603
+ if (!control) throw new Error("gateway event stream contains an unknown line");
64604
+ if (control.kind === "ready") {
64605
+ if (!control.session) throw new Error("gateway ready line has no session id");
64606
+ if (control.engine !== expectedEngine) {
64607
+ finish(control.engine ? `SESSION_VERSION_EXPIRED: \u5F53\u524D Pod \u662F ${control.engine}\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u9700\u8981 ${expectedEngine}` : "gateway \u7684 ready \u63A7\u5236\u884C\u6CA1\u5E26 engine\uFF0Cgateway \u592A\u8001\uFF0C\u5148\u5347 gateway");
64608
+ return;
64609
+ }
64610
+ sessionId = control.session;
64611
+ resolveReady();
64612
+ }
64613
+ emitControl(control);
64614
+ if (control.kind === "error") {
64615
+ finish();
64616
+ return;
64617
+ }
64618
+ }
64619
+ }
64620
+ finish();
64621
+ } catch (e) {
64622
+ if (!closed) {
64623
+ logger?.warn("cloud event stream failed", { message: e.message });
64624
+ finish(`\u4E91\u4E0A\u4E8B\u4EF6\u901A\u9053\u51FA\u9519\uFF1A${e.message}`);
64625
+ }
64626
+ }
64627
+ })();
64628
+ return {
64629
+ send(command) {
64630
+ const next = sendChain.then(async () => {
64631
+ await ready;
64632
+ if (closed || !sessionId) throw new Error("event session closed");
64633
+ const res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventSend(personaId2, sessionId), { method: "POST", headers, body: JSON.stringify(command) });
64634
+ if (!res.ok) {
64635
+ let message = `gateway \u56DE ${res.status}`;
64636
+ try {
64637
+ const body = await res.json();
64638
+ if (typeof body.message === "string") message = body.message;
64639
+ } catch {
64640
+ }
64641
+ finish(message);
64642
+ throw new Error(message);
64643
+ }
64644
+ });
64645
+ sendChain = next.catch(() => {
64646
+ });
64647
+ return next;
64648
+ },
64649
+ onEvents(cb) {
64650
+ const first = !eventCbs.length;
64651
+ eventCbs.push(cb);
64652
+ if (first) for (const events of earlyEvents.splice(0)) cb(events);
64653
+ },
64654
+ onControl(cb) {
64655
+ const first = !controlCbs.length;
64656
+ controlCbs.push(cb);
64657
+ if (first) for (const control of earlyControls.splice(0)) cb(control);
64658
+ else {
64659
+ if (readyControl) cb(readyControl);
64660
+ if (errorControl) cb(errorControl);
64661
+ }
64662
+ },
64663
+ onClose(cb) {
64664
+ closeCbs.push(cb);
64665
+ if (closed) cb();
64666
+ },
64667
+ close() {
64668
+ finish();
64669
+ }
64670
+ };
64671
+ }
64436
64672
  function parseControlLine(line) {
64437
64673
  let o2;
64438
64674
  try {
@@ -64652,55 +64888,27 @@ function openHttpLineStream(opts) {
64652
64888
  init_protocol();
64653
64889
 
64654
64890
  // src/tools/codex-cloud-session.ts
64655
- var import_node_fs38 = __toESM(require("fs"), 1);
64656
- function cloudThreadParams(ctx, paths) {
64657
- const { model: _model, ...base } = threadStartParams(ctx);
64658
- const developerInstructions = ctx.titleOnly ? "\u53EA\u6839\u636E\u7528\u6237\u6D88\u606F\u8FD4\u56DE\u7B80\u77ED\u6807\u9898\u3002\u4E0D\u8981\u8C03\u7528\u5DE5\u5177\u3001\u8BFB\u53D6\u6587\u4EF6\u3001\u8BBF\u95EE\u7F51\u7EDC\u6216\u4FEE\u6539\u4EFB\u4F55\u5185\u5BB9\u3002" : [ctx.extraSystemPrompt, workDirPrompt(paths.workDir, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
64659
- return { ...base, ...paths.model ? { model: paths.model } : {}, cwd: paths.personaDir, approvalPolicy: "never", sandbox: ctx.titleOnly ? "read-only" : "danger-full-access", developerInstructions };
64660
- }
64661
- function deferredLineStream() {
64662
- let target = null;
64663
- let closed = false;
64664
- const pending = [];
64665
- const lineCbs = [];
64666
- const closeCbs = [];
64667
- const finish = () => {
64668
- if (closed) return;
64669
- closed = true;
64670
- for (const cb of closeCbs) cb();
64671
- };
64672
- return {
64673
- attach(t2) {
64674
- if (closed) {
64675
- t2.close();
64676
- return;
64677
- }
64678
- target = t2;
64679
- t2.onLine((l2) => {
64680
- for (const cb of lineCbs) cb(l2);
64681
- });
64682
- t2.onClose(finish);
64683
- for (const line of pending.splice(0)) t2.write(line);
64684
- },
64685
- write(line) {
64686
- if (closed) return;
64687
- if (target) target.write(line);
64688
- else pending.push(line);
64689
- },
64690
- onLine(cb) {
64691
- lineCbs.push(cb);
64692
- },
64693
- onClose(cb) {
64694
- closeCbs.push(cb);
64695
- if (closed) cb();
64696
- },
64697
- close() {
64698
- if (closed) return;
64699
- target?.close();
64700
- finish();
64701
- }
64702
- };
64891
+ var import_node_fs39 = __toESM(require("fs"), 1);
64892
+
64893
+ // src/tools/cloud-portable-input.ts
64894
+ async function portableCloudInput(text, resolvers) {
64895
+ const markers = [...text.matchAll(/\[attachment:image:(https?:\/\/[^\]]+)\]/g)];
64896
+ let result = text;
64897
+ for (const match of markers) {
64898
+ const url = match[1];
64899
+ let dataUrl;
64900
+ const codex = resolvers.resolveCodexImage?.(url);
64901
+ if (codex?.type === "image" && codex.url.startsWith("data:")) dataUrl = codex.url;
64902
+ if (!dataUrl && resolvers.fetchPiImage) {
64903
+ const pi = await resolvers.fetchPiImage(url).catch(() => null);
64904
+ if (pi) dataUrl = `data:${pi.mimeType};base64,${pi.data}`;
64905
+ }
64906
+ if (dataUrl) result = result.replace(match[0], `[attachment:image:${dataUrl}]`);
64907
+ }
64908
+ return result;
64703
64909
  }
64910
+
64911
+ // src/tools/codex-cloud-session.ts
64704
64912
  function cloudImageInput(deps) {
64705
64913
  return (url) => {
64706
64914
  const secret = deps.getSignSecret?.();
@@ -64709,7 +64917,7 @@ function cloudImageInput(deps) {
64709
64917
  const mime = lookupMime(p3);
64710
64918
  if (!mime.startsWith("image/")) return null;
64711
64919
  try {
64712
- const bytes = (deps.readFile ?? import_node_fs38.default.readFileSync)(p3);
64920
+ const bytes = (deps.readFile ?? import_node_fs39.default.readFileSync)(p3);
64713
64921
  return { type: "image", url: `data:${mime};base64,${bytes.toString("base64")}` };
64714
64922
  } catch (e) {
64715
64923
  deps.logger?.warn("cloud image attachment unreadable", { path: p3, message: e.message });
@@ -64719,73 +64927,84 @@ function cloudImageInput(deps) {
64719
64927
  }
64720
64928
  function createCloudCodexSession(ctx, sink, deps) {
64721
64929
  const personaId2 = personaIdFromCloudCwd(ctx.cwd);
64722
- const stream = deferredLineStream();
64723
- let resolvePaths;
64724
- let rejectPaths;
64725
- const paths = new Promise((resolve9, reject) => {
64726
- resolvePaths = resolve9;
64727
- rejectPaths = reject;
64728
- });
64729
- paths.catch(() => {
64730
- });
64731
- stream.onClose(() => rejectPaths(new Error("\u4E91\u4E0A\u901A\u9053\u5728 ready \u4E4B\u524D\u5173\u4E86\uFF0C\u62FF\u4E0D\u5230 Pod \u8DEF\u5F84")));
64732
64930
  let channel = null;
64733
- const driver = driveCodexThread({
64734
- ctx,
64735
- sink,
64736
- stream,
64737
- logger: deps.logger,
64738
- threadParams: async (client) => {
64739
- const p3 = await paths;
64740
- const params = cloudThreadParams(ctx, p3);
64741
- if (!ctx.toolSessionId || p3.model) return params;
64742
- const config = await client.request("config/read", {});
64743
- if (config?.config?.model) return { ...params, model: config.config.model };
64744
- const list = await client.request("model/list", {});
64745
- const selected = list?.data?.find((m3) => m3.isDefault);
64746
- const current = selected?.id || selected?.model;
64747
- if (!current) throw new Error("\u65E0\u6CD5\u786E\u5B9A\u5F53\u524D Codex \u9ED8\u8BA4\u6A21\u578B\uFF0C\u62D2\u7EDD\u6CBF\u7528\u65E7\u4F1A\u8BDD\u6A21\u578B");
64748
- return { ...params, model: current };
64749
- },
64750
- imageInput: cloudImageInput(deps),
64751
- // skills 在 Pod 里由 persona 目录自带,本机路径对它没意义
64752
- // 「让对端走人」= 断开下行流,gateway 收到就删 Job;信号对 Pod 没有意义
64753
- kill: () => stream.close(),
64754
- // 云 persona 运行看板(design 2026-09-23-cloud-persona-metrics §3.7):提问那一行带「一轮开始」头,轮末镜像顺带报这一轮的结果
64755
- onTurnStarting: () => channel?.markNextLineTurnStart(),
64756
- // 轮末镜像带上这一轮的结果与首字节(design 2026-09-23-cloud-persona-metrics §3.7)
64757
- onTurnCompleted: (outcome, afterFirstByteMs) => {
64758
- if (!ctx.titleOnly) void channel?.mirror({ outcome, ...afterFirstByteMs !== void 0 ? { afterFirstByteMs } : {} });
64759
- },
64760
- now: deps.now
64761
- });
64931
+ let closed = false;
64932
+ let exited = false;
64933
+ const exit = () => {
64934
+ if (!exited) {
64935
+ exited = true;
64936
+ sink.onExit(null);
64937
+ }
64938
+ };
64762
64939
  if (!personaId2) {
64763
64940
  queueMicrotask(() => {
64764
64941
  sink.onError(`cloud session has no persona id (cwd=${ctx.cwd})`);
64765
- stream.close();
64942
+ exit();
64766
64943
  });
64767
- return driver.session;
64768
- }
64769
- void deps.client.openSession(personaId2, { expectedEngine: "codex", ...ctx.titleOnly ? { purpose: "title" } : {} }).then(
64770
- (opened) => {
64771
- channel = opened;
64944
+ return { startTurn() {
64945
+ }, respondPermission() {
64946
+ }, interrupt() {
64947
+ }, async stop() {
64948
+ } };
64949
+ }
64950
+ const opened = deps.client.openEventSession(personaId2, {
64951
+ expectedEngine: "codex",
64952
+ ...ctx.toolSessionId ? { toolSessionId: ctx.toolSessionId } : {},
64953
+ ...ctx.extraSystemPrompt ? { instructions: ctx.extraSystemPrompt } : {},
64954
+ ...ctx.effort ? { effort: ctx.effort } : {},
64955
+ ...ctx.personaMode ? { personaMode: ctx.personaMode } : {},
64956
+ ...ctx.titleOnly ? { purpose: "title" } : {}
64957
+ }).then(
64958
+ (opened2) => {
64959
+ channel = opened2;
64960
+ channel.onEvents((events) => sink.pushEvents(events));
64772
64961
  channel.onControl((c2) => {
64773
- if (c2.kind === "ready") {
64774
- resolvePaths({ personaDir: c2.personaDir, workDir: c2.workDir, model: c2.model });
64775
- } else if (c2.kind === "queued") {
64962
+ if (c2.kind === "queued") {
64776
64963
  sink.pushEvents([{ kind: "meta-text", text: `\u4E91\u4E0A\u673A\u5668\u6709 ${c2.running} \u4E2A\u4EFB\u52A1\u5728\u8DD1\uFF0C\u7B49\u4E00\u4E2A\u7ED3\u675F\u5C31\u8F6E\u5230\u4F60` }]);
64777
64964
  } else if (c2.kind === "error") {
64778
64965
  sink.onError(`\u4E91\u4E0A persona \u8D77\u4E0D\u6765\uFF1A${c2.message}`);
64779
64966
  }
64780
64967
  });
64781
- stream.attach(channel);
64968
+ channel.onClose(exit);
64969
+ if (closed) channel.close();
64970
+ return channel;
64782
64971
  },
64783
64972
  (e) => {
64784
64973
  sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
64785
- stream.close();
64974
+ exit();
64975
+ throw e;
64786
64976
  }
64787
64977
  );
64788
- return driver.session;
64978
+ void opened.catch(() => {
64979
+ });
64980
+ let sendChain = Promise.resolve();
64981
+ const send2 = (command) => {
64982
+ sendChain = sendChain.then(command).catch((e) => {
64983
+ if (!closed && !exited) sink.onError(`\u4E91\u4E0A\u4F1A\u8BDD\u4E0A\u884C\u5931\u8D25\uFF1A${e.message}`);
64984
+ });
64985
+ };
64986
+ return {
64987
+ startTurn(text) {
64988
+ send2(async () => {
64989
+ const ch = await opened;
64990
+ if (closed) return;
64991
+ const portable = await portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) });
64992
+ await ch.send({ command: "turn", text: portable });
64993
+ });
64994
+ },
64995
+ respondPermission(requestId, allow) {
64996
+ send2(async () => (await opened).send({ command: "permission", requestId, allow }));
64997
+ },
64998
+ interrupt() {
64999
+ send2(async () => (await opened).send({ command: "interrupt" }));
65000
+ },
65001
+ async stop() {
65002
+ closed = true;
65003
+ const ch = await opened.catch(() => null);
65004
+ ch?.close();
65005
+ exit();
65006
+ }
65007
+ };
64789
65008
  }
64790
65009
 
64791
65010
  // src/tools/codex-cloud.ts
@@ -64856,7 +65075,7 @@ init_protocol();
64856
65075
 
64857
65076
  // src/tools/pi.ts
64858
65077
  var import_node_child_process12 = require("child_process");
64859
- var import_node_fs40 = __toESM(require("fs"), 1);
65078
+ var import_node_fs41 = __toESM(require("fs"), 1);
64860
65079
  init_protocol();
64861
65080
 
64862
65081
  // src/tools/pi-rpc-client.ts
@@ -64957,8 +65176,8 @@ var PiRpcClient = class {
64957
65176
  // src/tools/pi-session.ts
64958
65177
  var import_node_child_process11 = require("child_process");
64959
65178
  var import_node_crypto12 = require("crypto");
64960
- var import_node_fs39 = __toESM(require("fs"), 1);
64961
- var import_node_path43 = __toESM(require("path"), 1);
65179
+ var import_node_fs40 = __toESM(require("fs"), 1);
65180
+ var import_node_path44 = __toESM(require("path"), 1);
64962
65181
 
64963
65182
  // src/tools/pi-events.ts
64964
65183
  init_protocol();
@@ -65230,8 +65449,8 @@ ${dirs.map((d2) => `- ${d2}`).join("\n")}`;
65230
65449
  function createPiSession(ctx, sink, deps = {}) {
65231
65450
  const cmd = process.env.PI_BIN ?? "pi";
65232
65451
  const sessionId = ctx.toolSessionId ?? (0, import_node_crypto12.randomUUID)();
65233
- const skillsDir = import_node_path43.default.join(ctx.cwd, ".claude", "skills");
65234
- const exists = deps.skillsDirExists ?? ((d2) => import_node_fs39.default.existsSync(d2));
65452
+ const skillsDir = import_node_path44.default.join(ctx.cwd, ".claude", "skills");
65453
+ const exists = deps.skillsDirExists ?? ((d2) => import_node_fs40.default.existsSync(d2));
65235
65454
  const args = buildPiArgs(ctx, {
65236
65455
  sessionId,
65237
65456
  skillsDir: exists(skillsDir) ? skillsDir : void 0,
@@ -65293,10 +65512,10 @@ var PI_DEFAULT_MODEL_ENTRY = {
65293
65512
  };
65294
65513
  var PI_FULL_ACCESS = { id: "never", label: "Full Access", description: "pi \u65E0\u5BA1\u6279\uFF1A\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" };
65295
65514
  async function probePi(env = process.env) {
65296
- if (env.PI_BIN && import_node_fs40.default.existsSync(env.PI_BIN)) return { available: true, path: env.PI_BIN };
65515
+ if (env.PI_BIN && import_node_fs41.default.existsSync(env.PI_BIN)) return { available: true, path: env.PI_BIN };
65297
65516
  try {
65298
65517
  const out = (0, import_node_child_process12.execFileSync)("which", ["pi"], { encoding: "utf8" }).trim();
65299
- if (out && import_node_fs40.default.existsSync(out)) return { available: true, path: out };
65518
+ if (out && import_node_fs41.default.existsSync(out)) return { available: true, path: out };
65300
65519
  } catch {
65301
65520
  }
65302
65521
  return { available: false };
@@ -65473,34 +65692,30 @@ function cloudPiInstructions(ctx) {
65473
65692
  function createCloudPiSession(ctx, sink, deps) {
65474
65693
  const personaId2 = personaIdFromCloudCwd(ctx.cwd);
65475
65694
  const sessionId = ctx.toolSessionId ?? (0, import_node_crypto13.randomUUID)();
65476
- const stream = deferredLineStream();
65477
65695
  let channel = null;
65478
- const driver = drivePiSession({
65479
- sink,
65480
- stream,
65481
- sessionId,
65482
- logger: deps.logger,
65483
- fetchImage: deps.fetchImage ?? makeImageFetcher(),
65484
- // 「让对端走人」= 断开下行流,gateway 收到就删 Pod;信号对 Pod 没有意义
65485
- kill: () => stream.close(),
65486
- // 云 persona 运行看板(design 2026-09-23-cloud-persona-metrics §3.7):提问那一行带「一轮开始」头,轮末镜像顺带报这一轮的结果
65487
- onTurnStarting: () => channel?.markNextLineTurnStart(),
65488
- // 轮末镜像带上这一轮的结果与首字节(design 2026-09-23-cloud-persona-metrics §3.7)
65489
- onTurnCompleted: (outcome, afterFirstByteMs) => {
65490
- if (!ctx.titleOnly) void channel?.mirror({ outcome, ...afterFirstByteMs !== void 0 ? { afterFirstByteMs } : {} });
65491
- },
65492
- now: deps.now
65493
- });
65696
+ let closed = false;
65697
+ let exited = false;
65698
+ const exit = () => {
65699
+ if (!exited) {
65700
+ exited = true;
65701
+ sink.onExit(null);
65702
+ }
65703
+ };
65494
65704
  if (!personaId2) {
65495
65705
  queueMicrotask(() => {
65496
65706
  sink.onError(`cloud session has no persona id (cwd=${ctx.cwd})`);
65497
- stream.close();
65707
+ exit();
65498
65708
  });
65499
- return driver.session;
65500
- }
65501
- void deps.client.openSession(personaId2, { toolSessionId: sessionId, instructions: ctx.titleOnly ? "" : cloudPiInstructions(ctx), expectedEngine: "pi", ...ctx.titleOnly ? { purpose: "title" } : {} }).then(
65502
- (opened) => {
65503
- channel = opened;
65709
+ return { startTurn() {
65710
+ }, respondPermission() {
65711
+ }, interrupt() {
65712
+ }, async stop() {
65713
+ } };
65714
+ }
65715
+ const opened = deps.client.openEventSession(personaId2, { expectedEngine: "pi", toolSessionId: sessionId, instructions: ctx.titleOnly ? "" : cloudPiInstructions(ctx), ...ctx.titleOnly ? { purpose: "title" } : {} }).then(
65716
+ (opened2) => {
65717
+ channel = opened2;
65718
+ channel.onEvents((events) => sink.pushEvents(events));
65504
65719
  channel.onControl((c2) => {
65505
65720
  if (c2.kind === "queued") {
65506
65721
  sink.pushEvents([{ kind: "meta-text", text: `\u4E91\u4E0A\u673A\u5668\u6709 ${c2.running} \u4E2A\u4EFB\u52A1\u5728\u8DD1\uFF0C\u7B49\u4E00\u4E2A\u7ED3\u675F\u5C31\u8F6E\u5230\u4F60` }]);
@@ -65508,14 +65723,46 @@ function createCloudPiSession(ctx, sink, deps) {
65508
65723
  sink.onError(`\u4E91\u4E0A persona \u8D77\u4E0D\u6765\uFF1A${c2.message}`);
65509
65724
  }
65510
65725
  });
65511
- stream.attach(channel);
65726
+ channel.onClose(exit);
65727
+ if (closed) channel.close();
65728
+ return channel;
65512
65729
  },
65513
65730
  (e) => {
65514
65731
  sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
65515
- stream.close();
65732
+ exit();
65733
+ throw e;
65516
65734
  }
65517
65735
  );
65518
- return driver.session;
65736
+ void opened.catch(() => {
65737
+ });
65738
+ let sendChain = Promise.resolve();
65739
+ const send2 = (command) => {
65740
+ sendChain = sendChain.then(command).catch((e) => {
65741
+ if (!closed && !exited) sink.onError(`\u4E91\u4E0A\u4F1A\u8BDD\u4E0A\u884C\u5931\u8D25\uFF1A${e.message}`);
65742
+ });
65743
+ };
65744
+ return {
65745
+ startTurn(text) {
65746
+ send2(async () => {
65747
+ const ch = await opened;
65748
+ if (closed) return;
65749
+ const portable = await portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() });
65750
+ await ch.send({ command: "turn", text: portable });
65751
+ });
65752
+ },
65753
+ respondPermission(requestId, allow) {
65754
+ send2(async () => (await opened).send({ command: "permission", requestId, allow }));
65755
+ },
65756
+ interrupt() {
65757
+ send2(async () => (await opened).send({ command: "interrupt" }));
65758
+ },
65759
+ async stop() {
65760
+ closed = true;
65761
+ const ch = await opened.catch(() => null);
65762
+ ch?.close();
65763
+ exit();
65764
+ }
65765
+ };
65519
65766
  }
65520
65767
 
65521
65768
  // src/tools/pi-cloud.ts
@@ -65585,7 +65832,7 @@ var CloudPiAdapter = class {
65585
65832
  init_protocol();
65586
65833
 
65587
65834
  // src/tools/codex-skills.ts
65588
- var import_node_path44 = __toESM(require("path"), 1);
65835
+ var import_node_path45 = __toESM(require("path"), 1);
65589
65836
  function str4(v3) {
65590
65837
  return typeof v3 === "string" ? v3 : void 0;
65591
65838
  }
@@ -65622,7 +65869,7 @@ async function listCodexSkills(cwd, deps = {}) {
65622
65869
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
65623
65870
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
65624
65871
  beforeRequest: (client) => {
65625
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path44.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
65872
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path45.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
65626
65873
  }
65627
65874
  });
65628
65875
  return mapSkillsListResponse(res);
@@ -65696,23 +65943,23 @@ function rec4(v3) {
65696
65943
  }
65697
65944
 
65698
65945
  // src/workspace/browser.ts
65699
- var import_node_fs41 = __toESM(require("fs"), 1);
65700
- var import_node_os14 = __toESM(require("os"), 1);
65701
- var import_node_path45 = __toESM(require("path"), 1);
65946
+ var import_node_fs42 = __toESM(require("fs"), 1);
65947
+ var import_node_os15 = __toESM(require("os"), 1);
65948
+ var import_node_path46 = __toESM(require("path"), 1);
65702
65949
  init_protocol();
65703
65950
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
65704
65951
  function resolveInsideCwd(cwd, subpath) {
65705
- const absCwd = import_node_path45.default.resolve(cwd);
65706
- const joined = import_node_path45.default.resolve(absCwd, subpath ?? ".");
65707
- const rel = import_node_path45.default.relative(absCwd, joined);
65708
- if (rel.startsWith("..") || import_node_path45.default.isAbsolute(rel)) {
65952
+ const absCwd = import_node_path46.default.resolve(cwd);
65953
+ const joined = import_node_path46.default.resolve(absCwd, subpath ?? ".");
65954
+ const rel = import_node_path46.default.relative(absCwd, joined);
65955
+ if (rel.startsWith("..") || import_node_path46.default.isAbsolute(rel)) {
65709
65956
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
65710
65957
  }
65711
65958
  return joined;
65712
65959
  }
65713
65960
  function ensureCwd(cwd) {
65714
65961
  try {
65715
- const stat = import_node_fs41.default.statSync(cwd);
65962
+ const stat = import_node_fs42.default.statSync(cwd);
65716
65963
  if (!stat.isDirectory()) {
65717
65964
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
65718
65965
  }
@@ -65723,10 +65970,10 @@ function ensureCwd(cwd) {
65723
65970
  }
65724
65971
  var WorkspaceBrowser = class {
65725
65972
  list(args) {
65726
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os14.default.homedir();
65973
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os15.default.homedir();
65727
65974
  ensureCwd(cwd);
65728
65975
  const full = resolveInsideCwd(cwd, args.path);
65729
- const dirents = import_node_fs41.default.readdirSync(full, { withFileTypes: true });
65976
+ const dirents = import_node_fs42.default.readdirSync(full, { withFileTypes: true });
65730
65977
  const entries = [];
65731
65978
  for (const d2 of dirents) {
65732
65979
  if (!args.showHidden && d2.name.startsWith(".")) continue;
@@ -65736,7 +65983,7 @@ var WorkspaceBrowser = class {
65736
65983
  mtime: ""
65737
65984
  };
65738
65985
  try {
65739
- const st2 = import_node_fs41.default.statSync(import_node_path45.default.join(full, d2.name));
65986
+ const st2 = import_node_fs42.default.statSync(import_node_path46.default.join(full, d2.name));
65740
65987
  entry.mtime = new Date(st2.mtimeMs).toISOString();
65741
65988
  if (d2.isFile()) entry.size = st2.size;
65742
65989
  } catch {
@@ -65752,14 +65999,14 @@ var WorkspaceBrowser = class {
65752
65999
  read(args) {
65753
66000
  ensureCwd(args.cwd);
65754
66001
  const full = resolveInsideCwd(args.cwd, args.path);
65755
- const st2 = import_node_fs41.default.statSync(full);
66002
+ const st2 = import_node_fs42.default.statSync(full);
65756
66003
  if (!st2.isFile()) {
65757
66004
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
65758
66005
  }
65759
66006
  if (st2.size > MAX_FILE_BYTES2) {
65760
66007
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
65761
66008
  }
65762
- const buf = import_node_fs41.default.readFileSync(full);
66009
+ const buf = import_node_fs42.default.readFileSync(full);
65763
66010
  const isBinary = buf.includes(0);
65764
66011
  if (isBinary) {
65765
66012
  return {
@@ -65781,20 +66028,20 @@ var WorkspaceBrowser = class {
65781
66028
  };
65782
66029
 
65783
66030
  // src/skills/agents-scanner.ts
65784
- var import_node_fs42 = __toESM(require("fs"), 1);
65785
- var import_node_os15 = __toESM(require("os"), 1);
65786
- var import_node_path46 = __toESM(require("path"), 1);
66031
+ var import_node_fs43 = __toESM(require("fs"), 1);
66032
+ var import_node_os16 = __toESM(require("os"), 1);
66033
+ var import_node_path47 = __toESM(require("path"), 1);
65787
66034
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
65788
66035
  function isDirLikeSync2(p3) {
65789
66036
  try {
65790
- return import_node_fs42.default.statSync(p3).isDirectory();
66037
+ return import_node_fs43.default.statSync(p3).isDirectory();
65791
66038
  } catch {
65792
66039
  return false;
65793
66040
  }
65794
66041
  }
65795
66042
  function fileExistsSync(p3) {
65796
66043
  try {
65797
- return import_node_fs42.default.statSync(p3).isFile();
66044
+ return import_node_fs43.default.statSync(p3).isFile();
65798
66045
  } catch {
65799
66046
  return false;
65800
66047
  }
@@ -65802,7 +66049,7 @@ function fileExistsSync(p3) {
65802
66049
  function parseAgentFile(filePath) {
65803
66050
  let content;
65804
66051
  try {
65805
- content = import_node_fs42.default.readFileSync(filePath, "utf8");
66052
+ content = import_node_fs43.default.readFileSync(filePath, "utf8");
65806
66053
  } catch {
65807
66054
  return {};
65808
66055
  }
@@ -65815,16 +66062,16 @@ function parseAgentFile(filePath) {
65815
66062
  function scanAgentsDir(dir, source, seen, out) {
65816
66063
  let entries;
65817
66064
  try {
65818
- entries = import_node_fs42.default.readdirSync(dir, { withFileTypes: true });
66065
+ entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
65819
66066
  } catch {
65820
66067
  return;
65821
66068
  }
65822
66069
  for (const ent of entries) {
65823
66070
  if (!ent.name.endsWith(".md")) continue;
65824
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path46.default.join(dir, ent.name)))) {
66071
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path47.default.join(dir, ent.name)))) {
65825
66072
  continue;
65826
66073
  }
65827
- const filePath = import_node_path46.default.join(dir, ent.name);
66074
+ const filePath = import_node_path47.default.join(dir, ent.name);
65828
66075
  const baseName = ent.name.replace(/\.md$/, "");
65829
66076
  if (seen.has(baseName)) continue;
65830
66077
  seen.add(baseName);
@@ -65842,12 +66089,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
65842
66089
  function walk2(dir, namespaces) {
65843
66090
  let entries;
65844
66091
  try {
65845
- entries = import_node_fs42.default.readdirSync(dir, { withFileTypes: true });
66092
+ entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
65846
66093
  } catch {
65847
66094
  return;
65848
66095
  }
65849
66096
  for (const ent of entries) {
65850
- const childPath = import_node_path46.default.join(dir, ent.name);
66097
+ const childPath = import_node_path47.default.join(dir, ent.name);
65851
66098
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
65852
66099
  walk2(childPath, [...namespaces, ent.name]);
65853
66100
  continue;
@@ -65872,13 +66119,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
65872
66119
  walk2(root, []);
65873
66120
  }
65874
66121
  function readInstalledPlugins2(home) {
65875
- const pluginsDir = import_node_path46.default.join(home, ".claude", "plugins");
65876
- const v22 = import_node_path46.default.join(pluginsDir, "installed_plugins_v2.json");
65877
- const v1 = import_node_path46.default.join(pluginsDir, "installed_plugins.json");
66122
+ const pluginsDir = import_node_path47.default.join(home, ".claude", "plugins");
66123
+ const v22 = import_node_path47.default.join(pluginsDir, "installed_plugins_v2.json");
66124
+ const v1 = import_node_path47.default.join(pluginsDir, "installed_plugins.json");
65878
66125
  let raw = null;
65879
66126
  for (const candidate of [v22, v1]) {
65880
66127
  try {
65881
- raw = import_node_fs42.default.readFileSync(candidate, "utf8");
66128
+ raw = import_node_fs43.default.readFileSync(candidate, "utf8");
65882
66129
  break;
65883
66130
  } catch {
65884
66131
  }
@@ -65903,19 +66150,19 @@ function readInstalledPlugins2(home) {
65903
66150
  return out;
65904
66151
  }
65905
66152
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
65906
- let cur = import_node_path46.default.resolve(startCwd);
65907
- const fsRoot = import_node_path46.default.parse(cur).root;
66153
+ let cur = import_node_path47.default.resolve(startCwd);
66154
+ const fsRoot = import_node_path47.default.parse(cur).root;
65908
66155
  while (true) {
65909
- scanAgentsDir(import_node_path46.default.join(cur, ".claude", "agents"), "project", seen, out);
66156
+ scanAgentsDir(import_node_path47.default.join(cur, ".claude", "agents"), "project", seen, out);
65910
66157
  let hasGit = false;
65911
66158
  try {
65912
- hasGit = import_node_fs42.default.existsSync(import_node_path46.default.join(cur, ".git"));
66159
+ hasGit = import_node_fs43.default.existsSync(import_node_path47.default.join(cur, ".git"));
65913
66160
  } catch {
65914
66161
  }
65915
66162
  if (hasGit) return;
65916
66163
  if (cur === home) return;
65917
66164
  if (cur === fsRoot) return;
65918
- const parent = import_node_path46.default.dirname(cur);
66165
+ const parent = import_node_path47.default.dirname(cur);
65919
66166
  if (parent === cur) return;
65920
66167
  cur = parent;
65921
66168
  }
@@ -65925,7 +66172,7 @@ var AgentsScanner = class {
65925
66172
  extraPluginRoots;
65926
66173
  policyDir;
65927
66174
  constructor(opts = {}) {
65928
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os15.default.homedir();
66175
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os16.default.homedir();
65929
66176
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
65930
66177
  if (opts.policyDir !== void 0) {
65931
66178
  this.policyDir = opts.policyDir;
@@ -65950,7 +66197,7 @@ var AgentsScanner = class {
65950
66197
  }
65951
66198
  const fsBlock = [];
65952
66199
  scanAgentsDir(
65953
- import_node_path46.default.join(this.home, ".claude", "agents"),
66200
+ import_node_path47.default.join(this.home, ".claude", "agents"),
65954
66201
  "global",
65955
66202
  seen,
65956
66203
  fsBlock
@@ -65964,7 +66211,7 @@ var AgentsScanner = class {
65964
66211
  ...this.extraPluginRoots
65965
66212
  ];
65966
66213
  for (const { name, root } of plugins) {
65967
- const agentsRoot = import_node_path46.default.join(root, "agents");
66214
+ const agentsRoot = import_node_path47.default.join(root, "agents");
65968
66215
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
65969
66216
  }
65970
66217
  return [...builtinBlock, ...fsBlock];
@@ -65972,28 +66219,28 @@ var AgentsScanner = class {
65972
66219
  };
65973
66220
 
65974
66221
  // src/observer/session-observer.ts
65975
- var import_node_fs44 = __toESM(require("fs"), 1);
65976
- var import_node_os17 = __toESM(require("os"), 1);
65977
- var import_node_path48 = __toESM(require("path"), 1);
66222
+ var import_node_fs45 = __toESM(require("fs"), 1);
66223
+ var import_node_os18 = __toESM(require("os"), 1);
66224
+ var import_node_path49 = __toESM(require("path"), 1);
65978
66225
  init_claude_history();
65979
66226
 
65980
66227
  // src/observer/subagent-meta-observer.ts
65981
- var import_node_fs43 = __toESM(require("fs"), 1);
65982
- var import_node_os16 = __toESM(require("os"), 1);
65983
- var import_node_path47 = __toESM(require("path"), 1);
66228
+ var import_node_fs44 = __toESM(require("fs"), 1);
66229
+ var import_node_os17 = __toESM(require("os"), 1);
66230
+ var import_node_path48 = __toESM(require("path"), 1);
65984
66231
  init_claude_history();
65985
66232
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
65986
66233
  var SubagentMetaObserver = class {
65987
66234
  constructor(opts) {
65988
66235
  this.opts = opts;
65989
- this.home = opts.home ?? import_node_os16.default.homedir();
66236
+ this.home = opts.home ?? import_node_os17.default.homedir();
65990
66237
  }
65991
66238
  opts;
65992
66239
  home;
65993
66240
  watches = /* @__PURE__ */ new Map();
65994
66241
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
65995
66242
  resolveSubagentDir(cwd, toolSessionId) {
65996
- return import_node_path47.default.join(
66243
+ return import_node_path48.default.join(
65997
66244
  this.home,
65998
66245
  ".claude",
65999
66246
  "projects",
@@ -66023,7 +66270,7 @@ var SubagentMetaObserver = class {
66023
66270
  attachWatcher(w3) {
66024
66271
  if (w3.watcher) return;
66025
66272
  try {
66026
- w3.watcher = import_node_fs43.default.watch(w3.dirPath, { persistent: false }, (_evt, name) => {
66273
+ w3.watcher = import_node_fs44.default.watch(w3.dirPath, { persistent: false }, (_evt, name) => {
66027
66274
  if (!name) return;
66028
66275
  const m3 = META_RE.exec(String(name));
66029
66276
  if (!m3) return;
@@ -66035,7 +66282,7 @@ var SubagentMetaObserver = class {
66035
66282
  scan(w3) {
66036
66283
  let entries;
66037
66284
  try {
66038
- entries = import_node_fs43.default.readdirSync(w3.dirPath);
66285
+ entries = import_node_fs44.default.readdirSync(w3.dirPath);
66039
66286
  } catch {
66040
66287
  return;
66041
66288
  }
@@ -66049,10 +66296,10 @@ var SubagentMetaObserver = class {
66049
66296
  if (!m3) return;
66050
66297
  const agentId = m3[1];
66051
66298
  if (w3.emitted.has(agentId)) return;
66052
- const file = import_node_path47.default.join(w3.dirPath, name);
66299
+ const file = import_node_path48.default.join(w3.dirPath, name);
66053
66300
  let raw;
66054
66301
  try {
66055
- raw = import_node_fs43.default.readFileSync(file, "utf8");
66302
+ raw = import_node_fs44.default.readFileSync(file, "utf8");
66056
66303
  } catch {
66057
66304
  return;
66058
66305
  }
@@ -66097,7 +66344,7 @@ var SubagentMetaObserver = class {
66097
66344
  var SessionObserver = class {
66098
66345
  constructor(opts) {
66099
66346
  this.opts = opts;
66100
- this.home = opts.home ?? import_node_os17.default.homedir();
66347
+ this.home = opts.home ?? import_node_os18.default.homedir();
66101
66348
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
66102
66349
  }
66103
66350
  opts;
@@ -66109,14 +66356,14 @@ var SessionObserver = class {
66109
66356
  metaObserver;
66110
66357
  resolveJsonlPath(cwd, toolSessionId, override) {
66111
66358
  if (override) return override;
66112
- return import_node_path48.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
66359
+ return import_node_path49.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
66113
66360
  }
66114
66361
  start(args) {
66115
66362
  this.stop(args.sessionId);
66116
66363
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
66117
66364
  let size = 0;
66118
66365
  try {
66119
- size = import_node_fs44.default.statSync(filePath).size;
66366
+ size = import_node_fs45.default.statSync(filePath).size;
66120
66367
  } catch {
66121
66368
  }
66122
66369
  const w3 = {
@@ -66129,16 +66376,16 @@ var SessionObserver = class {
66129
66376
  adapter: args.adapter,
66130
66377
  prevIsRejectSentinel: false,
66131
66378
  toolSessionId: args.toolSessionId,
66132
- sawFile: import_node_fs44.default.existsSync(filePath),
66379
+ sawFile: import_node_fs45.default.existsSync(filePath),
66133
66380
  lastRelocateScanMs: 0,
66134
66381
  pendingCwdDerive: false,
66135
66382
  lastDeriveMs: 0
66136
66383
  };
66137
66384
  try {
66138
- import_node_fs44.default.mkdirSync(import_node_path48.default.dirname(filePath), { recursive: true });
66385
+ import_node_fs45.default.mkdirSync(import_node_path49.default.dirname(filePath), { recursive: true });
66139
66386
  } catch {
66140
66387
  }
66141
- w3.watcher = import_node_fs44.default.watch(import_node_path48.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
66388
+ w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
66142
66389
  if (!changedName || !w3.filePath.endsWith(changedName)) return;
66143
66390
  this.poll(w3);
66144
66391
  });
@@ -66161,7 +66408,7 @@ var SessionObserver = class {
66161
66408
  // 异常静默吞,不阻塞 watcher 启动
66162
66409
  hydrateMetaTail(w3, maxLines = 200) {
66163
66410
  try {
66164
- const raw = import_node_fs44.default.readFileSync(w3.filePath, "utf8");
66411
+ const raw = import_node_fs45.default.readFileSync(w3.filePath, "utf8");
66165
66412
  if (!raw) return;
66166
66413
  const allLines = raw.split("\n").filter((l2) => l2.trim().length > 0);
66167
66414
  if (allLines.length === 0) return;
@@ -66185,7 +66432,7 @@ var SessionObserver = class {
66185
66432
  poll(w3) {
66186
66433
  let size = 0;
66187
66434
  try {
66188
- size = import_node_fs44.default.statSync(w3.filePath).size;
66435
+ size = import_node_fs45.default.statSync(w3.filePath).size;
66189
66436
  } catch {
66190
66437
  if (w3.sawFile) this.maybeRelocate(w3);
66191
66438
  return;
@@ -66196,11 +66443,11 @@ var SessionObserver = class {
66196
66443
  w3.buf = "";
66197
66444
  }
66198
66445
  if (size === w3.lastSize) return;
66199
- const fd = import_node_fs44.default.openSync(w3.filePath, "r");
66446
+ const fd = import_node_fs45.default.openSync(w3.filePath, "r");
66200
66447
  try {
66201
66448
  const len = size - w3.lastSize;
66202
66449
  const buf = Buffer.alloc(len);
66203
- import_node_fs44.default.readSync(fd, buf, 0, len, w3.lastSize);
66450
+ import_node_fs45.default.readSync(fd, buf, 0, len, w3.lastSize);
66204
66451
  w3.lastSize = size;
66205
66452
  w3.buf += buf.toString("utf8");
66206
66453
  let newlineIndex;
@@ -66223,7 +66470,7 @@ var SessionObserver = class {
66223
66470
  }
66224
66471
  }
66225
66472
  } finally {
66226
- import_node_fs44.default.closeSync(fd);
66473
+ import_node_fs45.default.closeSync(fd);
66227
66474
  }
66228
66475
  if (w3.pendingCwdDerive) this.maybeDeriveCwd(w3);
66229
66476
  }
@@ -66235,7 +66482,7 @@ var SessionObserver = class {
66235
66482
  const now = Date.now();
66236
66483
  if (now - w3.lastRelocateScanMs < 1e3) return;
66237
66484
  w3.lastRelocateScanMs = now;
66238
- const projectsRoot = import_node_path48.default.join(this.home, ".claude", "projects");
66485
+ const projectsRoot = import_node_path49.default.join(this.home, ".claude", "projects");
66239
66486
  const found = findTranscriptByToolSessionId(projectsRoot, w3.toolSessionId);
66240
66487
  if (!found || found === w3.filePath) return;
66241
66488
  try {
@@ -66244,7 +66491,7 @@ var SessionObserver = class {
66244
66491
  }
66245
66492
  w3.filePath = found;
66246
66493
  try {
66247
- w3.watcher = import_node_fs44.default.watch(import_node_path48.default.dirname(found), { persistent: false }, (_event, changedName) => {
66494
+ w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(found), { persistent: false }, (_event, changedName) => {
66248
66495
  if (!changedName || !w3.filePath.endsWith(changedName)) return;
66249
66496
  this.poll(w3);
66250
66497
  });
@@ -66366,9 +66613,9 @@ function listRegistered() {
66366
66613
  // src/tools/title-generator.ts
66367
66614
  var import_node_child_process13 = require("child_process");
66368
66615
  init_protocol();
66369
- var import_node_fs45 = __toESM(require("fs"), 1);
66370
- var import_node_os18 = __toESM(require("os"), 1);
66371
- var import_node_path49 = __toESM(require("path"), 1);
66616
+ var import_node_fs46 = __toESM(require("fs"), 1);
66617
+ var import_node_os19 = __toESM(require("os"), 1);
66618
+ var import_node_path50 = __toESM(require("path"), 1);
66372
66619
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
66373
66620
  var TITLE_INPUT_MAX_CHARS = 400;
66374
66621
  var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
@@ -66459,21 +66706,21 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
66459
66706
  }
66460
66707
  let workDir;
66461
66708
  try {
66462
- workDir = import_node_fs45.default.mkdtempSync(import_node_path49.default.join(import_node_os18.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
66709
+ workDir = import_node_fs46.default.mkdtempSync(import_node_path50.default.join(import_node_os19.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
66463
66710
  } catch {
66464
66711
  return null;
66465
66712
  }
66466
66713
  const cleanupWorkDir = () => {
66467
66714
  try {
66468
- import_node_fs45.default.rmSync(workDir, { recursive: true, force: true });
66715
+ import_node_fs46.default.rmSync(workDir, { recursive: true, force: true });
66469
66716
  } catch {
66470
66717
  }
66471
66718
  };
66472
- const outFile = import_node_path49.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
66473
- const schemaFile = import_node_path49.default.join(workDir, "title-schema.json");
66719
+ const outFile = import_node_path50.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
66720
+ const schemaFile = import_node_path50.default.join(workDir, "title-schema.json");
66474
66721
  if (tool === "codex") {
66475
66722
  try {
66476
- import_node_fs45.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
66723
+ import_node_fs46.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
66477
66724
  } catch {
66478
66725
  cleanupWorkDir();
66479
66726
  return null;
@@ -66528,7 +66775,7 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
66528
66775
  if (tool === "claude" || tool === "pi") return finish(parseTitleJson(stdout));
66529
66776
  let fileText = "";
66530
66777
  try {
66531
- fileText = import_node_fs45.default.readFileSync(outFile, "utf8");
66778
+ fileText = import_node_fs46.default.readFileSync(outFile, "utf8");
66532
66779
  } catch {
66533
66780
  return finish(null);
66534
66781
  }
@@ -67224,8 +67471,8 @@ async function authenticate(token, deps) {
67224
67471
  }
67225
67472
 
67226
67473
  // src/legacy-cleanup.ts
67227
- var fs56 = __toESM(require("fs/promises"), 1);
67228
- var path57 = __toESM(require("path"), 1);
67474
+ var fs57 = __toESM(require("fs/promises"), 1);
67475
+ var path58 = __toESM(require("path"), 1);
67229
67476
  var LEGACY_FILES = [
67230
67477
  "personal-capability.json",
67231
67478
  "received-capabilities.json",
@@ -67234,9 +67481,9 @@ var LEGACY_FILES = [
67234
67481
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
67235
67482
  const removed = [];
67236
67483
  for (const name of LEGACY_FILES) {
67237
- const p3 = path57.join(dataDir, name);
67484
+ const p3 = path58.join(dataDir, name);
67238
67485
  try {
67239
- await fs56.unlink(p3);
67486
+ await fs57.unlink(p3);
67240
67487
  removed.push(name);
67241
67488
  logger.debug("legacy capability file removed", { file: name });
67242
67489
  } catch (err) {
@@ -67248,13 +67495,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
67248
67495
  }
67249
67496
 
67250
67497
  // src/inbox/inbox-store.ts
67251
- var fs57 = __toESM(require("fs"), 1);
67252
- var path58 = __toESM(require("path"), 1);
67498
+ var fs58 = __toESM(require("fs"), 1);
67499
+ var path59 = __toESM(require("path"), 1);
67253
67500
  var INBOX_SUBDIR = "inbox";
67254
67501
  var InboxStore = class {
67255
67502
  constructor(dataDir) {
67256
67503
  this.dataDir = dataDir;
67257
- fs57.mkdirSync(this.dirPath(), { recursive: true });
67504
+ fs58.mkdirSync(this.dirPath(), { recursive: true });
67258
67505
  }
67259
67506
  dataDir;
67260
67507
  /**
@@ -67266,7 +67513,7 @@ var InboxStore = class {
67266
67513
  const file = this.filePath(peerDeviceId);
67267
67514
  let raw;
67268
67515
  try {
67269
- raw = fs57.readFileSync(file, "utf8");
67516
+ raw = fs58.readFileSync(file, "utf8");
67270
67517
  } catch (err) {
67271
67518
  if (err?.code === "ENOENT") return [];
67272
67519
  return [];
@@ -67282,7 +67529,7 @@ var InboxStore = class {
67282
67529
  const dir = this.dirPath();
67283
67530
  let entries;
67284
67531
  try {
67285
- entries = fs57.readdirSync(dir);
67532
+ entries = fs58.readdirSync(dir);
67286
67533
  } catch (err) {
67287
67534
  if (err?.code === "ENOENT") return [];
67288
67535
  return [];
@@ -67298,9 +67545,9 @@ var InboxStore = class {
67298
67545
  if (existing.some((m3) => m3.id === message.id)) return;
67299
67546
  const file = this.filePath(message.peerDeviceId);
67300
67547
  const line = JSON.stringify(message) + "\n";
67301
- fs57.appendFileSync(file, line, { mode: 384 });
67548
+ fs58.appendFileSync(file, line, { mode: 384 });
67302
67549
  try {
67303
- fs57.chmodSync(file, 384);
67550
+ fs58.chmodSync(file, 384);
67304
67551
  } catch {
67305
67552
  }
67306
67553
  }
@@ -67330,7 +67577,7 @@ var InboxStore = class {
67330
67577
  removeByPeerDeviceId(peerDeviceId) {
67331
67578
  const file = this.filePath(peerDeviceId);
67332
67579
  try {
67333
- fs57.unlinkSync(file);
67580
+ fs58.unlinkSync(file);
67334
67581
  } catch (err) {
67335
67582
  if (err?.code === "ENOENT") return;
67336
67583
  }
@@ -67339,18 +67586,18 @@ var InboxStore = class {
67339
67586
  const file = this.filePath(peerDeviceId);
67340
67587
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
67341
67588
  const content = messages.map((m3) => JSON.stringify(m3)).join("\n") + (messages.length > 0 ? "\n" : "");
67342
- fs57.writeFileSync(tmp, content, { mode: 384 });
67343
- fs57.renameSync(tmp, file);
67589
+ fs58.writeFileSync(tmp, content, { mode: 384 });
67590
+ fs58.renameSync(tmp, file);
67344
67591
  try {
67345
- fs57.chmodSync(file, 384);
67592
+ fs58.chmodSync(file, 384);
67346
67593
  } catch {
67347
67594
  }
67348
67595
  }
67349
67596
  dirPath() {
67350
- return path58.join(this.dataDir, INBOX_SUBDIR);
67597
+ return path59.join(this.dataDir, INBOX_SUBDIR);
67351
67598
  }
67352
67599
  filePath(peerDeviceId) {
67353
- return path58.join(this.dirPath(), `${peerDeviceId}.jsonl`);
67600
+ return path59.join(this.dirPath(), `${peerDeviceId}.jsonl`);
67354
67601
  }
67355
67602
  };
67356
67603
  function parseAllLines(raw) {
@@ -67438,8 +67685,8 @@ var InboxManager = class {
67438
67685
  };
67439
67686
 
67440
67687
  // src/state/contact-store.ts
67441
- var fs58 = __toESM(require("fs"), 1);
67442
- var path59 = __toESM(require("path"), 1);
67688
+ var fs59 = __toESM(require("fs"), 1);
67689
+ var path60 = __toESM(require("path"), 1);
67443
67690
  var FILE_NAME = "contacts.json";
67444
67691
  var ContactStore = class {
67445
67692
  constructor(dataDir) {
@@ -67449,10 +67696,10 @@ var ContactStore = class {
67449
67696
  contacts = /* @__PURE__ */ new Map();
67450
67697
  load() {
67451
67698
  this.contacts.clear();
67452
- const file = path59.join(this.dataDir, FILE_NAME);
67699
+ const file = path60.join(this.dataDir, FILE_NAME);
67453
67700
  let raw;
67454
67701
  try {
67455
- raw = fs58.readFileSync(file, "utf8");
67702
+ raw = fs59.readFileSync(file, "utf8");
67456
67703
  } catch (err) {
67457
67704
  if (err?.code !== "ENOENT") this.renameBak(file);
67458
67705
  return;
@@ -67533,20 +67780,20 @@ var ContactStore = class {
67533
67780
  return true;
67534
67781
  }
67535
67782
  flush() {
67536
- const file = path59.join(this.dataDir, FILE_NAME);
67783
+ const file = path60.join(this.dataDir, FILE_NAME);
67537
67784
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
67538
67785
  const content = JSON.stringify(
67539
67786
  { contacts: Array.from(this.contacts.values()) },
67540
67787
  null,
67541
67788
  2
67542
67789
  );
67543
- fs58.mkdirSync(this.dataDir, { recursive: true });
67544
- fs58.writeFileSync(tmp, content, { mode: 384 });
67545
- fs58.renameSync(tmp, file);
67790
+ fs59.mkdirSync(this.dataDir, { recursive: true });
67791
+ fs59.writeFileSync(tmp, content, { mode: 384 });
67792
+ fs59.renameSync(tmp, file);
67546
67793
  }
67547
67794
  renameBak(file) {
67548
67795
  try {
67549
- fs58.renameSync(file, `${file}.bak`);
67796
+ fs59.renameSync(file, `${file}.bak`);
67550
67797
  } catch {
67551
67798
  }
67552
67799
  }
@@ -67654,61 +67901,61 @@ async function connectRemote(args) {
67654
67901
  }
67655
67902
 
67656
67903
  // src/migrations/2026-05-20-flatten-sessions.ts
67657
- var fs59 = __toESM(require("fs"), 1);
67658
- var path60 = __toESM(require("path"), 1);
67904
+ var fs60 = __toESM(require("fs"), 1);
67905
+ var path61 = __toESM(require("path"), 1);
67659
67906
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
67660
67907
  function migrateFlattenSessions(opts) {
67661
67908
  const dataDir = opts.dataDir;
67662
67909
  const now = opts.now ?? Date.now;
67663
- const sessionsDir = path60.join(dataDir, "sessions");
67664
- const flagPath = path60.join(sessionsDir, MIGRATION_FLAG_NAME);
67910
+ const sessionsDir = path61.join(dataDir, "sessions");
67911
+ const flagPath = path61.join(sessionsDir, MIGRATION_FLAG_NAME);
67665
67912
  if (existsSync3(flagPath)) {
67666
67913
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
67667
67914
  }
67668
67915
  let movedBare = 0;
67669
67916
  let movedVmOwner = 0;
67670
67917
  let archivedListener = 0;
67671
- const defaultDir = path60.join(sessionsDir, "default");
67918
+ const defaultDir = path61.join(sessionsDir, "default");
67672
67919
  if (existsSync3(defaultDir)) {
67673
67920
  for (const entry of readdirSafe(defaultDir)) {
67674
67921
  if (!entry.endsWith(".json")) continue;
67675
- const src = path60.join(defaultDir, entry);
67676
- const dst = path60.join(sessionsDir, entry);
67677
- fs59.renameSync(src, dst);
67922
+ const src = path61.join(defaultDir, entry);
67923
+ const dst = path61.join(sessionsDir, entry);
67924
+ fs60.renameSync(src, dst);
67678
67925
  movedBare += 1;
67679
67926
  }
67680
67927
  rmdirIfEmpty(defaultDir);
67681
67928
  }
67682
67929
  for (const pid of readdirSafe(sessionsDir)) {
67683
- const personaDir = path60.join(sessionsDir, pid);
67930
+ const personaDir = path61.join(sessionsDir, pid);
67684
67931
  if (!isDir(personaDir)) continue;
67685
67932
  if (pid === "default") continue;
67686
- const ownerSrc = path60.join(personaDir, "owner");
67933
+ const ownerSrc = path61.join(personaDir, "owner");
67687
67934
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
67688
- const ownerDst = path60.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
67689
- fs59.mkdirSync(ownerDst, { recursive: true });
67935
+ const ownerDst = path61.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
67936
+ fs60.mkdirSync(ownerDst, { recursive: true });
67690
67937
  for (const file of readdirSafe(ownerSrc)) {
67691
67938
  if (!file.endsWith(".json")) continue;
67692
- fs59.renameSync(path60.join(ownerSrc, file), path60.join(ownerDst, file));
67939
+ fs60.renameSync(path61.join(ownerSrc, file), path61.join(ownerDst, file));
67693
67940
  movedVmOwner += 1;
67694
67941
  }
67695
67942
  rmdirIfEmpty(ownerSrc);
67696
67943
  }
67697
- const listenerSrc = path60.join(personaDir, "listener");
67944
+ const listenerSrc = path61.join(personaDir, "listener");
67698
67945
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
67699
- const archiveDst = path60.join(dataDir, ".legacy", `listener-${pid}`);
67700
- fs59.mkdirSync(archiveDst, { recursive: true });
67946
+ const archiveDst = path61.join(dataDir, ".legacy", `listener-${pid}`);
67947
+ fs60.mkdirSync(archiveDst, { recursive: true });
67701
67948
  for (const file of readdirSafe(listenerSrc)) {
67702
67949
  if (!file.endsWith(".json")) continue;
67703
- fs59.renameSync(path60.join(listenerSrc, file), path60.join(archiveDst, file));
67950
+ fs60.renameSync(path61.join(listenerSrc, file), path61.join(archiveDst, file));
67704
67951
  archivedListener += 1;
67705
67952
  }
67706
67953
  rmdirIfEmpty(listenerSrc);
67707
67954
  }
67708
67955
  rmdirIfEmpty(personaDir);
67709
67956
  }
67710
- fs59.mkdirSync(sessionsDir, { recursive: true });
67711
- fs59.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
67957
+ fs60.mkdirSync(sessionsDir, { recursive: true });
67958
+ fs60.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
67712
67959
  return {
67713
67960
  skipped: false,
67714
67961
  flagWritten: true,
@@ -67719,7 +67966,7 @@ function migrateFlattenSessions(opts) {
67719
67966
  }
67720
67967
  function existsSync3(p3) {
67721
67968
  try {
67722
- fs59.statSync(p3);
67969
+ fs60.statSync(p3);
67723
67970
  return true;
67724
67971
  } catch {
67725
67972
  return false;
@@ -67727,62 +67974,62 @@ function existsSync3(p3) {
67727
67974
  }
67728
67975
  function isDir(p3) {
67729
67976
  try {
67730
- return fs59.statSync(p3).isDirectory();
67977
+ return fs60.statSync(p3).isDirectory();
67731
67978
  } catch {
67732
67979
  return false;
67733
67980
  }
67734
67981
  }
67735
67982
  function readdirSafe(p3) {
67736
67983
  try {
67737
- return fs59.readdirSync(p3);
67984
+ return fs60.readdirSync(p3);
67738
67985
  } catch {
67739
67986
  return [];
67740
67987
  }
67741
67988
  }
67742
67989
  function rmdirIfEmpty(p3) {
67743
67990
  try {
67744
- fs59.rmdirSync(p3);
67991
+ fs60.rmdirSync(p3);
67745
67992
  } catch {
67746
67993
  }
67747
67994
  }
67748
67995
 
67749
67996
  // src/migrations/2026-08-18-drop-seeded-projects.ts
67750
- var fs60 = __toESM(require("fs"), 1);
67751
- var path61 = __toESM(require("path"), 1);
67997
+ var fs61 = __toESM(require("fs"), 1);
67998
+ var path62 = __toESM(require("path"), 1);
67752
67999
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
67753
68000
  function dropSeededProjects(opts) {
67754
- fs60.mkdirSync(opts.dataDir, { recursive: true });
67755
- const flag = path61.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
67756
- if (fs60.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
67757
- const file = path61.join(opts.dataDir, "projects.json");
68001
+ fs61.mkdirSync(opts.dataDir, { recursive: true });
68002
+ const flag = path62.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
68003
+ if (fs61.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
68004
+ const file = path62.join(opts.dataDir, "projects.json");
67758
68005
  let raw = null;
67759
68006
  let dropped = 0;
67760
68007
  try {
67761
- raw = fs60.readFileSync(file, "utf8");
68008
+ raw = fs61.readFileSync(file, "utf8");
67762
68009
  dropped = JSON.parse(raw).projects?.length ?? 0;
67763
68010
  } catch {
67764
68011
  }
67765
68012
  let backup = null;
67766
68013
  if (raw != null && dropped > 0) {
67767
- const dir = path61.join(opts.dataDir, "backups");
67768
- fs60.mkdirSync(dir, { recursive: true });
67769
- backup = path61.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
67770
- fs60.writeFileSync(backup, raw);
68014
+ const dir = path62.join(opts.dataDir, "backups");
68015
+ fs61.mkdirSync(dir, { recursive: true });
68016
+ backup = path62.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
68017
+ fs61.writeFileSync(backup, raw);
67771
68018
  }
67772
68019
  if (raw != null || dropped > 0) {
67773
- fs60.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
68020
+ fs61.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
67774
68021
  }
67775
- fs60.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
68022
+ fs61.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
67776
68023
  return { skipped: false, dropped, backup };
67777
68024
  }
67778
68025
 
67779
68026
  // src/transport/http-router.ts
67780
- var import_node_fs47 = __toESM(require("fs"), 1);
67781
- var import_node_path52 = __toESM(require("path"), 1);
68027
+ var import_node_fs48 = __toESM(require("fs"), 1);
68028
+ var import_node_path53 = __toESM(require("path"), 1);
67782
68029
 
67783
68030
  // src/attachment/upload.ts
67784
- var import_node_fs46 = __toESM(require("fs"), 1);
67785
- var import_node_path50 = __toESM(require("path"), 1);
68031
+ var import_node_fs47 = __toESM(require("fs"), 1);
68032
+ var import_node_path51 = __toESM(require("path"), 1);
67786
68033
  var import_node_crypto15 = __toESM(require("crypto"), 1);
67787
68034
  var import_promises8 = require("stream/promises");
67788
68035
  var UploadError = class extends Error {
@@ -67794,22 +68041,22 @@ var UploadError = class extends Error {
67794
68041
  code;
67795
68042
  };
67796
68043
  function assertValidFileName(fileName) {
67797
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path50.default.basename(fileName)) {
68044
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path51.default.basename(fileName)) {
67798
68045
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
67799
68046
  }
67800
68047
  }
67801
68048
  var HASH_PREFIX_LEN = 16;
67802
68049
  async function writeUploadedAttachment(args) {
67803
68050
  assertValidFileName(args.fileName);
67804
- const attachmentsRoot = import_node_path50.default.join(args.baseDir, ".attachments");
68051
+ const attachmentsRoot = import_node_path51.default.join(args.baseDir, ".attachments");
67805
68052
  try {
67806
- import_node_fs46.default.mkdirSync(attachmentsRoot, { recursive: true });
68053
+ import_node_fs47.default.mkdirSync(attachmentsRoot, { recursive: true });
67807
68054
  } catch (err) {
67808
68055
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
67809
68056
  }
67810
68057
  const hasher = import_node_crypto15.default.createHash("sha256");
67811
68058
  let actualSize = 0;
67812
- const tmpPath = import_node_path50.default.join(
68059
+ const tmpPath = import_node_path51.default.join(
67813
68060
  attachmentsRoot,
67814
68061
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto15.default.randomBytes(4).toString("hex")}`
67815
68062
  );
@@ -67824,18 +68071,18 @@ async function writeUploadedAttachment(args) {
67824
68071
  yield buf;
67825
68072
  }
67826
68073
  },
67827
- import_node_fs46.default.createWriteStream(tmpPath, { mode: 384 })
68074
+ import_node_fs47.default.createWriteStream(tmpPath, { mode: 384 })
67828
68075
  );
67829
68076
  } catch (err) {
67830
68077
  try {
67831
- import_node_fs46.default.unlinkSync(tmpPath);
68078
+ import_node_fs47.default.unlinkSync(tmpPath);
67832
68079
  } catch {
67833
68080
  }
67834
68081
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
67835
68082
  }
67836
68083
  if (actualSize !== args.contentLength) {
67837
68084
  try {
67838
- import_node_fs46.default.unlinkSync(tmpPath);
68085
+ import_node_fs47.default.unlinkSync(tmpPath);
67839
68086
  } catch {
67840
68087
  }
67841
68088
  throw new UploadError(
@@ -67844,34 +68091,34 @@ async function writeUploadedAttachment(args) {
67844
68091
  );
67845
68092
  }
67846
68093
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
67847
- const hashDir = import_node_path50.default.join(attachmentsRoot, attachmentId);
68094
+ const hashDir = import_node_path51.default.join(attachmentsRoot, attachmentId);
67848
68095
  let finalFileName;
67849
68096
  let hashDirExists = false;
67850
68097
  try {
67851
- hashDirExists = import_node_fs46.default.statSync(hashDir).isDirectory();
68098
+ hashDirExists = import_node_fs47.default.statSync(hashDir).isDirectory();
67852
68099
  } catch {
67853
68100
  }
67854
68101
  if (hashDirExists) {
67855
- const existing = import_node_fs46.default.readdirSync(hashDir).filter((n2) => !n2.startsWith("."));
68102
+ const existing = import_node_fs47.default.readdirSync(hashDir).filter((n2) => !n2.startsWith("."));
67856
68103
  finalFileName = existing[0] ?? args.fileName;
67857
68104
  try {
67858
- import_node_fs46.default.unlinkSync(tmpPath);
68105
+ import_node_fs47.default.unlinkSync(tmpPath);
67859
68106
  } catch {
67860
68107
  }
67861
68108
  } else {
67862
68109
  try {
67863
- import_node_fs46.default.mkdirSync(hashDir, { recursive: true });
68110
+ import_node_fs47.default.mkdirSync(hashDir, { recursive: true });
67864
68111
  finalFileName = args.fileName;
67865
- import_node_fs46.default.renameSync(tmpPath, import_node_path50.default.join(hashDir, finalFileName));
68112
+ import_node_fs47.default.renameSync(tmpPath, import_node_path51.default.join(hashDir, finalFileName));
67866
68113
  } catch (err) {
67867
68114
  try {
67868
- import_node_fs46.default.unlinkSync(tmpPath);
68115
+ import_node_fs47.default.unlinkSync(tmpPath);
67869
68116
  } catch {
67870
68117
  }
67871
68118
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
67872
68119
  }
67873
68120
  }
67874
- const absPath = import_node_path50.default.join(hashDir, finalFileName);
68121
+ const absPath = import_node_path51.default.join(hashDir, finalFileName);
67875
68122
  const relPath = absPath;
67876
68123
  args.groupFileStore.upsert(args.scope, args.sessionId, {
67877
68124
  relPath: absPath,
@@ -67886,8 +68133,8 @@ async function writeUploadedAttachment(args) {
67886
68133
 
67887
68134
  // src/extension/import.ts
67888
68135
  var import_promises9 = __toESM(require("fs/promises"), 1);
67889
- var import_node_path51 = __toESM(require("path"), 1);
67890
- var import_node_os19 = __toESM(require("os"), 1);
68136
+ var import_node_path52 = __toESM(require("path"), 1);
68137
+ var import_node_os20 = __toESM(require("os"), 1);
67891
68138
  var import_jszip = __toESM(require_lib3(), 1);
67892
68139
  var ImportError = class extends Error {
67893
68140
  constructor(code, message) {
@@ -67904,7 +68151,7 @@ async function importZip(buf, root) {
67904
68151
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
67905
68152
  }
67906
68153
  for (const name of Object.keys(zip.files)) {
67907
- if (name.includes("..") || name.startsWith("/") || import_node_path51.default.isAbsolute(name)) {
68154
+ if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
67908
68155
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
67909
68156
  }
67910
68157
  }
@@ -67937,7 +68184,7 @@ async function importZip(buf, root) {
67937
68184
  );
67938
68185
  }
67939
68186
  }
67940
- const destDir = import_node_path51.default.join(root, manifest.id);
68187
+ const destDir = import_node_path52.default.join(root, manifest.id);
67941
68188
  let destExists = false;
67942
68189
  try {
67943
68190
  await import_promises9.default.access(destDir);
@@ -67947,15 +68194,15 @@ async function importZip(buf, root) {
67947
68194
  if (destExists) {
67948
68195
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
67949
68196
  }
67950
- const stage = await import_promises9.default.mkdtemp(import_node_path51.default.join(import_node_os19.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
68197
+ const stage = await import_promises9.default.mkdtemp(import_node_path52.default.join(import_node_os20.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
67951
68198
  try {
67952
68199
  for (const [name, entry] of Object.entries(zip.files)) {
67953
- const dest = import_node_path51.default.join(stage, name);
68200
+ const dest = import_node_path52.default.join(stage, name);
67954
68201
  if (entry.dir) {
67955
68202
  await import_promises9.default.mkdir(dest, { recursive: true });
67956
68203
  continue;
67957
68204
  }
67958
- await import_promises9.default.mkdir(import_node_path51.default.dirname(dest), { recursive: true });
68205
+ await import_promises9.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
67959
68206
  const content = await entry.async("nodebuffer");
67960
68207
  await import_promises9.default.writeFile(dest, content);
67961
68208
  }
@@ -68009,7 +68256,7 @@ var SHARE_UI_ASSET_MIME = {
68009
68256
  ".wasm": "application/wasm"
68010
68257
  };
68011
68258
  function shareUiAssetMime(filePath) {
68012
- const ext = import_node_path52.default.extname(filePath).toLowerCase();
68259
+ const ext = import_node_path53.default.extname(filePath).toLowerCase();
68013
68260
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
68014
68261
  }
68015
68262
  var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
@@ -68108,7 +68355,7 @@ function isValidUploadFileName(fileName) {
68108
68355
  if (fileName === "." || fileName === "..") return false;
68109
68356
  if (fileName.startsWith(".")) return false;
68110
68357
  if (fileName.includes("/") || fileName.includes("\\")) return false;
68111
- return fileName === import_node_path52.default.basename(fileName);
68358
+ return fileName === import_node_path53.default.basename(fileName);
68112
68359
  }
68113
68360
  function createHttpRouter(deps) {
68114
68361
  return async (req, res) => {
@@ -68192,7 +68439,7 @@ function createHttpRouter(deps) {
68192
68439
  }
68193
68440
  let buf;
68194
68441
  try {
68195
- buf = await import_node_fs47.default.promises.readFile(abs);
68442
+ buf = await import_node_fs48.default.promises.readFile(abs);
68196
68443
  } catch {
68197
68444
  sendJson2(res, 404, { code: "NOT_FOUND", message: "asset not found" });
68198
68445
  return true;
@@ -68338,7 +68585,7 @@ function createHttpRouter(deps) {
68338
68585
  sendHtml(res, statusByCode[r2.code], loader.renderErrorHtml(r2.code, msgByCode[r2.code]));
68339
68586
  return true;
68340
68587
  }
68341
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path52.default.basename(r2.absPath)));
68588
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path53.default.basename(r2.absPath)));
68342
68589
  return true;
68343
68590
  }
68344
68591
  const ctx = deps.authResolver.resolveFromHeader(
@@ -68459,7 +68706,7 @@ function createHttpRouter(deps) {
68459
68706
  return true;
68460
68707
  }
68461
68708
  let absPath;
68462
- if (import_node_path52.default.isAbsolute(pathParam)) {
68709
+ if (import_node_path53.default.isAbsolute(pathParam)) {
68463
68710
  absPath = pathParam;
68464
68711
  } else if (deps.sessionStore) {
68465
68712
  const file = deps.sessionStore.read(sid);
@@ -68467,7 +68714,7 @@ function createHttpRouter(deps) {
68467
68714
  sendJson2(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
68468
68715
  return true;
68469
68716
  }
68470
- absPath = import_node_path52.default.join(file.cwd, pathParam);
68717
+ absPath = import_node_path53.default.join(file.cwd, pathParam);
68471
68718
  } else {
68472
68719
  sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
68473
68720
  return true;
@@ -68551,7 +68798,7 @@ function withCtx(ctx, body) {
68551
68798
  function streamFile(res, absPath, logger) {
68552
68799
  let stat;
68553
68800
  try {
68554
- stat = import_node_fs47.default.statSync(absPath);
68801
+ stat = import_node_fs48.default.statSync(absPath);
68555
68802
  } catch (err) {
68556
68803
  const code = err?.code;
68557
68804
  if (code === "ENOENT") {
@@ -68566,7 +68813,7 @@ function streamFile(res, absPath, logger) {
68566
68813
  return;
68567
68814
  }
68568
68815
  const mime = lookupMime(absPath);
68569
- const basename2 = import_node_path52.default.basename(absPath);
68816
+ const basename2 = import_node_path53.default.basename(absPath);
68570
68817
  res.writeHead(200, {
68571
68818
  "Content-Type": mime,
68572
68819
  "Content-Length": String(stat.size),
@@ -68574,7 +68821,7 @@ function streamFile(res, absPath, logger) {
68574
68821
  // 防止浏览器把任意 mime 当 html 渲染
68575
68822
  "X-Content-Type-Options": "nosniff"
68576
68823
  });
68577
- const stream = import_node_fs47.default.createReadStream(absPath);
68824
+ const stream = import_node_fs48.default.createReadStream(absPath);
68578
68825
  stream.on("error", (err) => {
68579
68826
  logger?.warn("streamFile read error", { absPath, err: err.message });
68580
68827
  res.destroy();
@@ -68583,8 +68830,8 @@ function streamFile(res, absPath, logger) {
68583
68830
  }
68584
68831
 
68585
68832
  // src/attachment/gc.ts
68586
- var import_node_fs48 = __toESM(require("fs"), 1);
68587
- var import_node_path53 = __toESM(require("path"), 1);
68833
+ var import_node_fs49 = __toESM(require("fs"), 1);
68834
+ var import_node_path54 = __toESM(require("path"), 1);
68588
68835
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
68589
68836
  function runAttachmentGc(args) {
68590
68837
  const now = (args.now ?? Date.now)();
@@ -68593,12 +68840,12 @@ function runAttachmentGc(args) {
68593
68840
  for (const { scope, sessionId } of args.sessionScopes) {
68594
68841
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
68595
68842
  if (entry.stale) continue;
68596
- if (import_node_path53.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
68843
+ if (import_node_path54.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
68597
68844
  }
68598
68845
  }
68599
68846
  const visited = /* @__PURE__ */ new Set();
68600
68847
  for (const { scope, sessionId } of args.sessionScopes) {
68601
- const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path53.default.join(
68848
+ const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path54.default.join(
68602
68849
  args.dataDir,
68603
68850
  "sessions",
68604
68851
  ...scopeSubPath(scope).map(safeFileName),
@@ -68611,28 +68858,28 @@ function runAttachmentGc(args) {
68611
68858
  return true;
68612
68859
  });
68613
68860
  for (const rootDir of roots) {
68614
- const attRoot = import_node_path53.default.join(rootDir, ".attachments");
68861
+ const attRoot = import_node_path54.default.join(rootDir, ".attachments");
68615
68862
  let hashDirs;
68616
68863
  try {
68617
- hashDirs = import_node_fs48.default.readdirSync(attRoot);
68864
+ hashDirs = import_node_fs49.default.readdirSync(attRoot);
68618
68865
  } catch (err) {
68619
68866
  if (err.code === "ENOENT") continue;
68620
68867
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
68621
68868
  continue;
68622
68869
  }
68623
68870
  for (const hashDir of hashDirs) {
68624
- const hashDirAbs = import_node_path53.default.join(attRoot, hashDir);
68871
+ const hashDirAbs = import_node_path54.default.join(attRoot, hashDir);
68625
68872
  let files;
68626
68873
  try {
68627
- files = import_node_fs48.default.readdirSync(hashDirAbs);
68874
+ files = import_node_fs49.default.readdirSync(hashDirAbs);
68628
68875
  } catch {
68629
68876
  continue;
68630
68877
  }
68631
68878
  for (const name of files) {
68632
- const file = import_node_path53.default.join(hashDirAbs, name);
68879
+ const file = import_node_path54.default.join(hashDirAbs, name);
68633
68880
  let stat;
68634
68881
  try {
68635
- stat = import_node_fs48.default.statSync(file);
68882
+ stat = import_node_fs49.default.statSync(file);
68636
68883
  } catch {
68637
68884
  continue;
68638
68885
  }
@@ -68641,18 +68888,18 @@ function runAttachmentGc(args) {
68641
68888
  if (age < ttlMs) continue;
68642
68889
  if (liveAbs.has(file)) continue;
68643
68890
  try {
68644
- import_node_fs48.default.unlinkSync(file);
68891
+ import_node_fs49.default.unlinkSync(file);
68645
68892
  } catch (err) {
68646
68893
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
68647
68894
  }
68648
68895
  }
68649
68896
  try {
68650
- if (import_node_fs48.default.readdirSync(hashDirAbs).length === 0) import_node_fs48.default.rmdirSync(hashDirAbs);
68897
+ if (import_node_fs49.default.readdirSync(hashDirAbs).length === 0) import_node_fs49.default.rmdirSync(hashDirAbs);
68651
68898
  } catch {
68652
68899
  }
68653
68900
  }
68654
68901
  try {
68655
- if (import_node_fs48.default.readdirSync(attRoot).length === 0) import_node_fs48.default.rmdirSync(attRoot);
68902
+ if (import_node_fs49.default.readdirSync(attRoot).length === 0) import_node_fs49.default.rmdirSync(attRoot);
68656
68903
  } catch {
68657
68904
  }
68658
68905
  }
@@ -68660,8 +68907,8 @@ function runAttachmentGc(args) {
68660
68907
  }
68661
68908
 
68662
68909
  // src/attachment/group.ts
68663
- var import_node_fs49 = __toESM(require("fs"), 1);
68664
- var import_node_path54 = __toESM(require("path"), 1);
68910
+ var import_node_fs50 = __toESM(require("fs"), 1);
68911
+ var import_node_path55 = __toESM(require("path"), 1);
68665
68912
  var import_node_crypto16 = __toESM(require("crypto"), 1);
68666
68913
  init_protocol();
68667
68914
  var GroupFileStore = class {
@@ -68673,11 +68920,11 @@ var GroupFileStore = class {
68673
68920
  this.logger = opts.logger;
68674
68921
  }
68675
68922
  rootForScope(scope) {
68676
- return import_node_path54.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
68923
+ return import_node_path55.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
68677
68924
  }
68678
68925
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
68679
68926
  filePath(scope, sessionId) {
68680
- return import_node_path54.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
68927
+ return import_node_path55.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
68681
68928
  }
68682
68929
  cacheKey(scope, sessionId) {
68683
68930
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -68686,7 +68933,7 @@ var GroupFileStore = class {
68686
68933
  readFile(scope, sessionId) {
68687
68934
  const file = this.filePath(scope, sessionId);
68688
68935
  try {
68689
- const raw = import_node_fs49.default.readFileSync(file, "utf8");
68936
+ const raw = import_node_fs50.default.readFileSync(file, "utf8");
68690
68937
  const parsed = JSON.parse(raw);
68691
68938
  if (!Array.isArray(parsed)) {
68692
68939
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -68712,10 +68959,10 @@ var GroupFileStore = class {
68712
68959
  }
68713
68960
  writeFile(scope, sessionId, entries) {
68714
68961
  const file = this.filePath(scope, sessionId);
68715
- import_node_fs49.default.mkdirSync(import_node_path54.default.dirname(file), { recursive: true });
68962
+ import_node_fs50.default.mkdirSync(import_node_path55.default.dirname(file), { recursive: true });
68716
68963
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
68717
- import_node_fs49.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
68718
- import_node_fs49.default.renameSync(tmp, file);
68964
+ import_node_fs50.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
68965
+ import_node_fs50.default.renameSync(tmp, file);
68719
68966
  }
68720
68967
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
68721
68968
  list(scope, sessionId) {
@@ -68807,7 +69054,7 @@ var GroupFileStore = class {
68807
69054
  */
68808
69055
  deleteSession(scope, sessionId) {
68809
69056
  try {
68810
- import_node_fs49.default.unlinkSync(this.filePath(scope, sessionId));
69057
+ import_node_fs50.default.unlinkSync(this.filePath(scope, sessionId));
68811
69058
  } catch (err) {
68812
69059
  if (err?.code !== "ENOENT") throw err;
68813
69060
  }
@@ -68820,7 +69067,7 @@ var GroupFileStore = class {
68820
69067
  * 不在 persona 目录里(见文件头的路径约定)。没树的 persona 是 noop。
68821
69068
  */
68822
69069
  deletePersona(personaId2) {
68823
- import_node_fs49.default.rmSync(import_node_path54.default.join(this.dataDir, "sessions", safeFileName(personaId2)), { recursive: true, force: true });
69070
+ import_node_fs50.default.rmSync(import_node_path55.default.join(this.dataDir, "sessions", safeFileName(personaId2)), { recursive: true, force: true });
68824
69071
  const prefix = `persona:${personaId2}:`;
68825
69072
  for (const key of this.cache.keys()) {
68826
69073
  if (key.startsWith(prefix)) this.cache.delete(key);
@@ -68829,10 +69076,10 @@ var GroupFileStore = class {
68829
69076
  };
68830
69077
 
68831
69078
  // src/discovery/state-file.ts
68832
- var import_node_fs50 = __toESM(require("fs"), 1);
68833
- var import_node_path55 = __toESM(require("path"), 1);
69079
+ var import_node_fs51 = __toESM(require("fs"), 1);
69080
+ var import_node_path56 = __toESM(require("path"), 1);
68834
69081
  function defaultStateFilePath(dataDir) {
68835
- return import_node_path55.default.join(dataDir, "state.json");
69082
+ return import_node_path56.default.join(dataDir, "state.json");
68836
69083
  }
68837
69084
  function isPidAlive(pid) {
68838
69085
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -68854,7 +69101,7 @@ var StateFileManager = class {
68854
69101
  }
68855
69102
  read() {
68856
69103
  try {
68857
- const raw = import_node_fs50.default.readFileSync(this.file, "utf8");
69104
+ const raw = import_node_fs51.default.readFileSync(this.file, "utf8");
68858
69105
  const parsed = JSON.parse(raw);
68859
69106
  return parsed;
68860
69107
  } catch {
@@ -68868,20 +69115,20 @@ var StateFileManager = class {
68868
69115
  return { status: "stale", existing };
68869
69116
  }
68870
69117
  write(state) {
68871
- import_node_fs50.default.mkdirSync(import_node_path55.default.dirname(this.file), { recursive: true });
69118
+ import_node_fs51.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
68872
69119
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
68873
- import_node_fs50.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
68874
- import_node_fs50.default.renameSync(tmp, this.file);
69120
+ import_node_fs51.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
69121
+ import_node_fs51.default.renameSync(tmp, this.file);
68875
69122
  if (process.platform !== "win32") {
68876
69123
  try {
68877
- import_node_fs50.default.chmodSync(this.file, 384);
69124
+ import_node_fs51.default.chmodSync(this.file, 384);
68878
69125
  } catch {
68879
69126
  }
68880
69127
  }
68881
69128
  }
68882
69129
  delete() {
68883
69130
  try {
68884
- import_node_fs50.default.unlinkSync(this.file);
69131
+ import_node_fs51.default.unlinkSync(this.file);
68885
69132
  } catch {
68886
69133
  }
68887
69134
  }
@@ -68895,14 +69142,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
68895
69142
  }
68896
69143
 
68897
69144
  // src/tunnel/tunnel-manager.ts
68898
- var import_node_fs54 = __toESM(require("fs"), 1);
68899
- var import_node_path59 = __toESM(require("path"), 1);
69145
+ var import_node_fs55 = __toESM(require("fs"), 1);
69146
+ var import_node_path60 = __toESM(require("path"), 1);
68900
69147
  var import_node_crypto17 = __toESM(require("crypto"), 1);
68901
69148
  var import_node_child_process16 = require("child_process");
68902
69149
 
68903
69150
  // src/tunnel/tunnel-store.ts
68904
- var import_node_fs51 = __toESM(require("fs"), 1);
68905
- var import_node_path56 = __toESM(require("path"), 1);
69151
+ var import_node_fs52 = __toESM(require("fs"), 1);
69152
+ var import_node_path57 = __toESM(require("path"), 1);
68906
69153
  var TunnelStore = class {
68907
69154
  constructor(filePath) {
68908
69155
  this.filePath = filePath;
@@ -68910,7 +69157,7 @@ var TunnelStore = class {
68910
69157
  filePath;
68911
69158
  async get() {
68912
69159
  try {
68913
- const raw = await import_node_fs51.default.promises.readFile(this.filePath, "utf8");
69160
+ const raw = await import_node_fs52.default.promises.readFile(this.filePath, "utf8");
68914
69161
  const obj = JSON.parse(raw);
68915
69162
  if (!isPersistedTunnel(obj)) return null;
68916
69163
  return obj;
@@ -68921,22 +69168,22 @@ var TunnelStore = class {
68921
69168
  }
68922
69169
  }
68923
69170
  async set(v3) {
68924
- const dir = import_node_path56.default.dirname(this.filePath);
68925
- await import_node_fs51.default.promises.mkdir(dir, { recursive: true });
69171
+ const dir = import_node_path57.default.dirname(this.filePath);
69172
+ await import_node_fs52.default.promises.mkdir(dir, { recursive: true });
68926
69173
  const data = JSON.stringify(v3, null, 2);
68927
69174
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
68928
- await import_node_fs51.default.promises.writeFile(tmp, data, { mode: 384 });
69175
+ await import_node_fs52.default.promises.writeFile(tmp, data, { mode: 384 });
68929
69176
  if (process.platform !== "win32") {
68930
69177
  try {
68931
- await import_node_fs51.default.promises.chmod(tmp, 384);
69178
+ await import_node_fs52.default.promises.chmod(tmp, 384);
68932
69179
  } catch {
68933
69180
  }
68934
69181
  }
68935
- await import_node_fs51.default.promises.rename(tmp, this.filePath);
69182
+ await import_node_fs52.default.promises.rename(tmp, this.filePath);
68936
69183
  }
68937
69184
  async clear() {
68938
69185
  try {
68939
- await import_node_fs51.default.promises.unlink(this.filePath);
69186
+ await import_node_fs52.default.promises.unlink(this.filePath);
68940
69187
  } catch (err) {
68941
69188
  const code = err?.code;
68942
69189
  if (code !== "ENOENT") throw err;
@@ -69031,9 +69278,9 @@ function escape2(v3) {
69031
69278
  }
69032
69279
 
69033
69280
  // src/tunnel/frpc-binary.ts
69034
- var import_node_fs52 = __toESM(require("fs"), 1);
69035
- var import_node_os20 = __toESM(require("os"), 1);
69036
- var import_node_path57 = __toESM(require("path"), 1);
69281
+ var import_node_fs53 = __toESM(require("fs"), 1);
69282
+ var import_node_os21 = __toESM(require("os"), 1);
69283
+ var import_node_path58 = __toESM(require("path"), 1);
69037
69284
  var import_node_child_process14 = require("child_process");
69038
69285
  var import_node_stream4 = require("stream");
69039
69286
  var import_promises10 = require("stream/promises");
@@ -69065,20 +69312,20 @@ function frpcDownloadUrl(version2, p3) {
69065
69312
  }
69066
69313
  async function ensureFrpcBinary(opts) {
69067
69314
  if (opts.override) {
69068
- if (!import_node_fs52.default.existsSync(opts.override)) {
69315
+ if (!import_node_fs53.default.existsSync(opts.override)) {
69069
69316
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
69070
69317
  }
69071
69318
  return opts.override;
69072
69319
  }
69073
69320
  const version2 = opts.version ?? FRPC_VERSION;
69074
69321
  const platform = opts.platform ?? detectPlatform();
69075
- const binDir = import_node_path57.default.join(opts.dataDir, "bin");
69076
- import_node_fs52.default.mkdirSync(binDir, { recursive: true });
69322
+ const binDir = import_node_path58.default.join(opts.dataDir, "bin");
69323
+ import_node_fs53.default.mkdirSync(binDir, { recursive: true });
69077
69324
  cleanupStaleArtifacts(binDir);
69078
- const stableBin = import_node_path57.default.join(binDir, "frpc");
69079
- if (import_node_fs52.default.existsSync(stableBin)) return stableBin;
69325
+ const stableBin = import_node_path58.default.join(binDir, "frpc");
69326
+ if (import_node_fs53.default.existsSync(stableBin)) return stableBin;
69080
69327
  const partialBin = `${stableBin}.partial`;
69081
- const tarballPath = import_node_path57.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
69328
+ const tarballPath = import_node_path58.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
69082
69329
  try {
69083
69330
  const url = frpcDownloadUrl(version2, platform);
69084
69331
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -69087,8 +69334,8 @@ async function ensureFrpcBinary(opts) {
69087
69334
  } else {
69088
69335
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
69089
69336
  }
69090
- import_node_fs52.default.chmodSync(partialBin, 493);
69091
- import_node_fs52.default.renameSync(partialBin, stableBin);
69337
+ import_node_fs53.default.chmodSync(partialBin, 493);
69338
+ import_node_fs53.default.renameSync(partialBin, stableBin);
69092
69339
  } finally {
69093
69340
  safeUnlink(tarballPath);
69094
69341
  safeUnlink(partialBin);
@@ -69098,15 +69345,15 @@ async function ensureFrpcBinary(opts) {
69098
69345
  function cleanupStaleArtifacts(binDir) {
69099
69346
  let entries;
69100
69347
  try {
69101
- entries = import_node_fs52.default.readdirSync(binDir);
69348
+ entries = import_node_fs53.default.readdirSync(binDir);
69102
69349
  } catch {
69103
69350
  return;
69104
69351
  }
69105
69352
  for (const name of entries) {
69106
69353
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
69107
- const full = import_node_path57.default.join(binDir, name);
69354
+ const full = import_node_path58.default.join(binDir, name);
69108
69355
  try {
69109
- import_node_fs52.default.rmSync(full, { recursive: true, force: true });
69356
+ import_node_fs53.default.rmSync(full, { recursive: true, force: true });
69110
69357
  } catch {
69111
69358
  }
69112
69359
  }
@@ -69114,7 +69361,7 @@ function cleanupStaleArtifacts(binDir) {
69114
69361
  }
69115
69362
  function safeUnlink(p3) {
69116
69363
  try {
69117
- import_node_fs52.default.unlinkSync(p3);
69364
+ import_node_fs53.default.unlinkSync(p3);
69118
69365
  } catch {
69119
69366
  }
69120
69367
  }
@@ -69125,13 +69372,13 @@ async function downloadToFile(url, dest, fetchImpl) {
69125
69372
  if (!res.ok || !res.body) {
69126
69373
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
69127
69374
  }
69128
- const out = import_node_fs52.default.createWriteStream(dest);
69375
+ const out = import_node_fs53.default.createWriteStream(dest);
69129
69376
  const nodeStream = import_node_stream4.Readable.fromWeb(res.body);
69130
69377
  await (0, import_promises10.pipeline)(nodeStream, out);
69131
69378
  }
69132
69379
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
69133
- const work = import_node_path57.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
69134
- import_node_fs52.default.mkdirSync(work, { recursive: true });
69380
+ const work = import_node_path58.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
69381
+ import_node_fs53.default.mkdirSync(work, { recursive: true });
69135
69382
  try {
69136
69383
  await new Promise((resolve9, reject) => {
69137
69384
  const proc = (0, import_node_child_process14.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -69139,32 +69386,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
69139
69386
  proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
69140
69387
  });
69141
69388
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
69142
- const src = import_node_path57.default.join(work, dirName, "frpc");
69143
- if (!import_node_fs52.default.existsSync(src)) {
69389
+ const src = import_node_path58.default.join(work, dirName, "frpc");
69390
+ if (!import_node_fs53.default.existsSync(src)) {
69144
69391
  throw new Error(`frpc not found inside tarball at ${src}`);
69145
69392
  }
69146
- import_node_fs52.default.copyFileSync(src, destBin);
69393
+ import_node_fs53.default.copyFileSync(src, destBin);
69147
69394
  } finally {
69148
- import_node_fs52.default.rmSync(work, { recursive: true, force: true });
69395
+ import_node_fs53.default.rmSync(work, { recursive: true, force: true });
69149
69396
  }
69150
69397
  }
69151
69398
 
69152
69399
  // src/tunnel/frpc-process.ts
69153
- var import_node_fs53 = __toESM(require("fs"), 1);
69154
- var import_node_path58 = __toESM(require("path"), 1);
69400
+ var import_node_fs54 = __toESM(require("fs"), 1);
69401
+ var import_node_path59 = __toESM(require("path"), 1);
69155
69402
  var import_node_child_process15 = require("child_process");
69156
69403
  function frpcPidFilePath(dataDir) {
69157
- return import_node_path58.default.join(dataDir, "frpc.pid");
69404
+ return import_node_path59.default.join(dataDir, "frpc.pid");
69158
69405
  }
69159
69406
  function writeFrpcPid(dataDir, pid) {
69160
69407
  try {
69161
- import_node_fs53.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
69408
+ import_node_fs54.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
69162
69409
  } catch {
69163
69410
  }
69164
69411
  }
69165
69412
  function clearFrpcPid(dataDir) {
69166
69413
  try {
69167
- import_node_fs53.default.unlinkSync(frpcPidFilePath(dataDir));
69414
+ import_node_fs54.default.unlinkSync(frpcPidFilePath(dataDir));
69168
69415
  } catch {
69169
69416
  }
69170
69417
  }
@@ -69180,7 +69427,7 @@ function defaultIsPidAlive(pid) {
69180
69427
  }
69181
69428
  function defaultReadPidFile(file) {
69182
69429
  try {
69183
- return import_node_fs53.default.readFileSync(file, "utf8");
69430
+ return import_node_fs54.default.readFileSync(file, "utf8");
69184
69431
  } catch {
69185
69432
  return null;
69186
69433
  }
@@ -69196,7 +69443,7 @@ function defaultSleep2(ms) {
69196
69443
  }
69197
69444
  async function killStaleFrpc(deps) {
69198
69445
  const pidFile = frpcPidFilePath(deps.dataDir);
69199
- const tomlPath = import_node_path58.default.join(deps.dataDir, "frpc.toml");
69446
+ const tomlPath = import_node_path59.default.join(deps.dataDir, "frpc.toml");
69200
69447
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
69201
69448
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
69202
69449
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -69220,7 +69467,7 @@ async function killStaleFrpc(deps) {
69220
69467
  }
69221
69468
  if (victims.size === 0) {
69222
69469
  try {
69223
- import_node_fs53.default.unlinkSync(pidFile);
69470
+ import_node_fs54.default.unlinkSync(pidFile);
69224
69471
  } catch {
69225
69472
  }
69226
69473
  return;
@@ -69231,7 +69478,7 @@ async function killStaleFrpc(deps) {
69231
69478
  }
69232
69479
  await sleep2(deps.reapWaitMs ?? 300);
69233
69480
  try {
69234
- import_node_fs53.default.unlinkSync(pidFile);
69481
+ import_node_fs54.default.unlinkSync(pidFile);
69235
69482
  } catch {
69236
69483
  }
69237
69484
  }
@@ -69268,7 +69515,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
69268
69515
  var TunnelManager = class {
69269
69516
  constructor(deps) {
69270
69517
  this.deps = deps;
69271
- this.store = deps.store ?? new TunnelStore(import_node_path59.default.join(deps.dataDir, "tunnel.json"));
69518
+ this.store = deps.store ?? new TunnelStore(import_node_path60.default.join(deps.dataDir, "tunnel.json"));
69272
69519
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
69273
69520
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
69274
69521
  }
@@ -69395,7 +69642,7 @@ var TunnelManager = class {
69395
69642
  dataDir: this.deps.dataDir,
69396
69643
  override: this.deps.frpcBinaryOverride ?? void 0
69397
69644
  });
69398
- const tomlPath = import_node_path59.default.join(this.deps.dataDir, "frpc.toml");
69645
+ const tomlPath = import_node_path60.default.join(this.deps.dataDir, "frpc.toml");
69399
69646
  const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto17.default.randomBytes(3).toString("hex")}`;
69400
69647
  const toml = buildFrpcToml({
69401
69648
  serverAddr: t2.frpsHost,
@@ -69406,14 +69653,14 @@ var TunnelManager = class {
69406
69653
  localPort,
69407
69654
  logLevel: "info"
69408
69655
  });
69409
- await import_node_fs54.default.promises.writeFile(tomlPath, toml, { mode: 384 });
69656
+ await import_node_fs55.default.promises.writeFile(tomlPath, toml, { mode: 384 });
69410
69657
  const proc = (this.deps.spawnImpl ?? import_node_child_process16.spawn)(frpcBin, ["-c", tomlPath], {
69411
69658
  stdio: ["ignore", "pipe", "pipe"]
69412
69659
  });
69413
- const logDir = import_node_path59.default.join(this.deps.dataDir, "log");
69414
- import_node_fs54.default.mkdirSync(logDir, { recursive: true });
69415
- const logFilePath = import_node_path59.default.join(logDir, "frpc.log");
69416
- const logStream = import_node_fs54.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
69660
+ const logDir = import_node_path60.default.join(this.deps.dataDir, "log");
69661
+ import_node_fs55.default.mkdirSync(logDir, { recursive: true });
69662
+ const logFilePath = import_node_path60.default.join(logDir, "frpc.log");
69663
+ const logStream = import_node_fs55.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
69417
69664
  logStream.on("error", () => {
69418
69665
  });
69419
69666
  const tee = (chunk) => {
@@ -69495,28 +69742,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
69495
69742
  }
69496
69743
 
69497
69744
  // src/tunnel/device-key.ts
69498
- var import_node_os21 = __toESM(require("os"), 1);
69499
- var import_node_path60 = __toESM(require("path"), 1);
69745
+ var import_node_os22 = __toESM(require("os"), 1);
69746
+ var import_node_path61 = __toESM(require("path"), 1);
69500
69747
  var import_node_crypto18 = __toESM(require("crypto"), 1);
69501
69748
  var DERIVE_SALT = "clawd-tunnel-device-v1";
69502
69749
  function deriveStableDeviceKey(opts = {}) {
69503
- const hostname = opts.hostname ?? import_node_os21.default.hostname();
69504
- const uid = opts.uid ?? (typeof import_node_os21.default.userInfo === "function" ? import_node_os21.default.userInfo().uid : 0);
69505
- const home = opts.home ?? import_node_os21.default.homedir();
69506
- const defaultDataDir = import_node_path60.default.resolve(import_node_path60.default.join(home, ".clawd"));
69507
- const normalizedDataDir = opts.dataDir ? import_node_path60.default.resolve(opts.dataDir) : null;
69750
+ const hostname = opts.hostname ?? import_node_os22.default.hostname();
69751
+ const uid = opts.uid ?? (typeof import_node_os22.default.userInfo === "function" ? import_node_os22.default.userInfo().uid : 0);
69752
+ const home = opts.home ?? import_node_os22.default.homedir();
69753
+ const defaultDataDir = import_node_path61.default.resolve(import_node_path61.default.join(home, ".clawd"));
69754
+ const normalizedDataDir = opts.dataDir ? import_node_path61.default.resolve(opts.dataDir) : null;
69508
69755
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
69509
69756
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
69510
69757
  return import_node_crypto18.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
69511
69758
  }
69512
69759
 
69513
69760
  // src/auth-store.ts
69514
- var import_node_fs55 = __toESM(require("fs"), 1);
69515
- var import_node_path61 = __toESM(require("path"), 1);
69761
+ var import_node_fs56 = __toESM(require("fs"), 1);
69762
+ var import_node_path62 = __toESM(require("path"), 1);
69516
69763
  var import_node_crypto19 = __toESM(require("crypto"), 1);
69517
69764
  var AUTH_FILE_NAME = "auth.json";
69518
69765
  function authFilePath(dataDir) {
69519
- return import_node_path61.default.join(dataDir, AUTH_FILE_NAME);
69766
+ return import_node_path62.default.join(dataDir, AUTH_FILE_NAME);
69520
69767
  }
69521
69768
  function loadOrCreateAuthFile(opts) {
69522
69769
  const file = authFilePath(opts.dataDir);
@@ -69557,7 +69804,7 @@ function defaultGenerateOwnerPrincipalId() {
69557
69804
  }
69558
69805
  function readAuthFile(file) {
69559
69806
  try {
69560
- const raw = import_node_fs55.default.readFileSync(file, "utf8");
69807
+ const raw = import_node_fs56.default.readFileSync(file, "utf8");
69561
69808
  const parsed = JSON.parse(raw);
69562
69809
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
69563
69810
  return null;
@@ -69578,26 +69825,26 @@ function readAuthFile(file) {
69578
69825
  }
69579
69826
  }
69580
69827
  function writeAuthFile(file, content) {
69581
- import_node_fs55.default.mkdirSync(import_node_path61.default.dirname(file), { recursive: true });
69582
- import_node_fs55.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
69828
+ import_node_fs56.default.mkdirSync(import_node_path62.default.dirname(file), { recursive: true });
69829
+ import_node_fs56.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
69583
69830
  try {
69584
- import_node_fs55.default.chmodSync(file, 384);
69831
+ import_node_fs56.default.chmodSync(file, 384);
69585
69832
  } catch {
69586
69833
  }
69587
69834
  }
69588
69835
 
69589
69836
  // src/owner-profile.ts
69590
- var import_node_fs56 = __toESM(require("fs"), 1);
69591
- var import_node_os22 = __toESM(require("os"), 1);
69592
- var import_node_path62 = __toESM(require("path"), 1);
69837
+ var import_node_fs57 = __toESM(require("fs"), 1);
69838
+ var import_node_os23 = __toESM(require("os"), 1);
69839
+ var import_node_path63 = __toESM(require("path"), 1);
69593
69840
  var PROFILE_FILENAME = "profile.json";
69594
69841
  function profilePath(dataDir) {
69595
- return import_node_path62.default.join(dataDir, PROFILE_FILENAME);
69842
+ return import_node_path63.default.join(dataDir, PROFILE_FILENAME);
69596
69843
  }
69597
69844
  function loadOwnerProfile(dataDir) {
69598
69845
  let raw;
69599
69846
  try {
69600
- raw = import_node_fs56.default.readFileSync(profilePath(dataDir), "utf8");
69847
+ raw = import_node_fs57.default.readFileSync(profilePath(dataDir), "utf8");
69601
69848
  } catch {
69602
69849
  return {};
69603
69850
  }
@@ -69613,11 +69860,11 @@ function loadOwnerProfile(dataDir) {
69613
69860
  }
69614
69861
  function patchOwnerProfile(dataDir, patch) {
69615
69862
  const merged = { ...loadOwnerProfile(dataDir), ...patch };
69616
- import_node_fs56.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
69863
+ import_node_fs57.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
69617
69864
  return merged;
69618
69865
  }
69619
69866
  function loadOwnerDisplayName(dataDir) {
69620
- const fallback = import_node_os22.default.userInfo().username;
69867
+ const fallback = import_node_os23.default.userInfo().username;
69621
69868
  const displayName = loadOwnerProfile(dataDir).displayName;
69622
69869
  if (typeof displayName !== "string" || displayName.length === 0) {
69623
69870
  if (displayName !== void 0) {
@@ -69629,18 +69876,18 @@ function loadOwnerDisplayName(dataDir) {
69629
69876
  }
69630
69877
 
69631
69878
  // src/feishu-auth/owner-identity-store.ts
69632
- var import_node_fs57 = __toESM(require("fs"), 1);
69633
- var import_node_path63 = __toESM(require("path"), 1);
69879
+ var import_node_fs58 = __toESM(require("fs"), 1);
69880
+ var import_node_path64 = __toESM(require("path"), 1);
69634
69881
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
69635
69882
  var OwnerIdentityStore = class {
69636
69883
  file;
69637
69884
  constructor(dataDir) {
69638
- this.file = import_node_path63.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
69885
+ this.file = import_node_path64.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
69639
69886
  }
69640
69887
  read() {
69641
69888
  let raw;
69642
69889
  try {
69643
- raw = import_node_fs57.default.readFileSync(this.file, "utf8");
69890
+ raw = import_node_fs58.default.readFileSync(this.file, "utf8");
69644
69891
  } catch {
69645
69892
  return null;
69646
69893
  }
@@ -69667,16 +69914,16 @@ var OwnerIdentityStore = class {
69667
69914
  };
69668
69915
  }
69669
69916
  write(record4) {
69670
- import_node_fs57.default.mkdirSync(import_node_path63.default.dirname(this.file), { recursive: true });
69671
- import_node_fs57.default.writeFileSync(this.file, JSON.stringify(record4, null, 2), { mode: 384 });
69917
+ import_node_fs58.default.mkdirSync(import_node_path64.default.dirname(this.file), { recursive: true });
69918
+ import_node_fs58.default.writeFileSync(this.file, JSON.stringify(record4, null, 2), { mode: 384 });
69672
69919
  try {
69673
- import_node_fs57.default.chmodSync(this.file, 384);
69920
+ import_node_fs58.default.chmodSync(this.file, 384);
69674
69921
  } catch {
69675
69922
  }
69676
69923
  }
69677
69924
  clear() {
69678
69925
  try {
69679
- import_node_fs57.default.unlinkSync(this.file);
69926
+ import_node_fs58.default.unlinkSync(this.file);
69680
69927
  } catch (err) {
69681
69928
  const code = err?.code;
69682
69929
  if (code !== "ENOENT") throw err;
@@ -70172,8 +70419,8 @@ function verifyConnectToken(args) {
70172
70419
  }
70173
70420
 
70174
70421
  // src/feishu-auth/server-key.ts
70175
- var fs74 = __toESM(require("fs"), 1);
70176
- var path76 = __toESM(require("path"), 1);
70422
+ var fs75 = __toESM(require("fs"), 1);
70423
+ var path77 = __toESM(require("path"), 1);
70177
70424
  var FILE_NAME2 = "server-signing-key.json";
70178
70425
  var ServerKeyStore = class {
70179
70426
  constructor(dataDir) {
@@ -70181,12 +70428,12 @@ var ServerKeyStore = class {
70181
70428
  }
70182
70429
  dataDir;
70183
70430
  filePath() {
70184
- return path76.join(this.dataDir, FILE_NAME2);
70431
+ return path77.join(this.dataDir, FILE_NAME2);
70185
70432
  }
70186
70433
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
70187
70434
  read() {
70188
70435
  try {
70189
- const raw = fs74.readFileSync(this.filePath(), "utf8");
70436
+ const raw = fs75.readFileSync(this.filePath(), "utf8");
70190
70437
  const parsed = JSON.parse(raw);
70191
70438
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
70192
70439
  return parsed.publicKeyPem;
@@ -70201,12 +70448,12 @@ var ServerKeyStore = class {
70201
70448
  publicKeyPem,
70202
70449
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
70203
70450
  };
70204
- fs74.mkdirSync(this.dataDir, { recursive: true });
70205
- fs74.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
70451
+ fs75.mkdirSync(this.dataDir, { recursive: true });
70452
+ fs75.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
70206
70453
  }
70207
70454
  clear() {
70208
70455
  try {
70209
- fs74.unlinkSync(this.filePath());
70456
+ fs75.unlinkSync(this.filePath());
70210
70457
  } catch {
70211
70458
  }
70212
70459
  }
@@ -70222,13 +70469,13 @@ var import_node_path80 = __toESM(require("path"), 1);
70222
70469
  init_protocol();
70223
70470
 
70224
70471
  // src/session/fork.ts
70225
- var import_node_fs58 = __toESM(require("fs"), 1);
70226
- var import_node_os23 = __toESM(require("os"), 1);
70227
- var import_node_path64 = __toESM(require("path"), 1);
70472
+ var import_node_fs59 = __toESM(require("fs"), 1);
70473
+ var import_node_os24 = __toESM(require("os"), 1);
70474
+ var import_node_path65 = __toESM(require("path"), 1);
70228
70475
  var import_node_crypto21 = require("crypto");
70229
70476
  init_claude_history();
70230
70477
  function readJsonlEntries(file) {
70231
- const raw = import_node_fs58.default.readFileSync(file, "utf8");
70478
+ const raw = import_node_fs59.default.readFileSync(file, "utf8");
70232
70479
  const out = [];
70233
70480
  for (const line of raw.split("\n")) {
70234
70481
  const t2 = line.trim();
@@ -70241,19 +70488,19 @@ function readJsonlEntries(file) {
70241
70488
  return out;
70242
70489
  }
70243
70490
  function forkSession(input) {
70244
- const baseDir = input.baseDir ?? import_node_path64.default.join(import_node_os23.default.homedir(), ".claude");
70245
- let projectDir = import_node_path64.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
70246
- let sourceFile = import_node_path64.default.join(projectDir, `${input.toolSessionId}.jsonl`);
70247
- if (!import_node_fs58.default.existsSync(sourceFile)) {
70491
+ const baseDir = input.baseDir ?? import_node_path65.default.join(import_node_os24.default.homedir(), ".claude");
70492
+ let projectDir = import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
70493
+ let sourceFile = import_node_path65.default.join(projectDir, `${input.toolSessionId}.jsonl`);
70494
+ if (!import_node_fs59.default.existsSync(sourceFile)) {
70248
70495
  const found = findTranscriptByToolSessionId(
70249
- import_node_path64.default.join(baseDir, "projects"),
70496
+ import_node_path65.default.join(baseDir, "projects"),
70250
70497
  input.toolSessionId
70251
70498
  );
70252
70499
  if (!found) {
70253
70500
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
70254
70501
  }
70255
70502
  sourceFile = found;
70256
- projectDir = import_node_path64.default.dirname(found);
70503
+ projectDir = import_node_path65.default.dirname(found);
70257
70504
  }
70258
70505
  const entries = readJsonlEntries(sourceFile);
70259
70506
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -70282,17 +70529,17 @@ function forkSession(input) {
70282
70529
  }
70283
70530
  forkedLines.push(JSON.stringify(forked));
70284
70531
  }
70285
- const outDir = input.targetCwd ? import_node_path64.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
70286
- const forkedFilePath = import_node_path64.default.join(outDir, `${forkedToolSessionId}.jsonl`);
70287
- import_node_fs58.default.mkdirSync(outDir, { recursive: true });
70288
- import_node_fs58.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
70532
+ const outDir = input.targetCwd ? import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
70533
+ const forkedFilePath = import_node_path65.default.join(outDir, `${forkedToolSessionId}.jsonl`);
70534
+ import_node_fs59.default.mkdirSync(outDir, { recursive: true });
70535
+ import_node_fs59.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
70289
70536
  return { forkedToolSessionId, forkedFilePath };
70290
70537
  }
70291
70538
 
70292
70539
  // src/tools/codex-fork.ts
70293
70540
  var import_node_child_process17 = require("child_process");
70294
- var import_node_fs59 = __toESM(require("fs"), 1);
70295
- var import_node_path65 = __toESM(require("path"), 1);
70541
+ var import_node_fs60 = __toESM(require("fs"), 1);
70542
+ var import_node_path66 = __toESM(require("path"), 1);
70296
70543
  function openCodexAppServer(home, cwd) {
70297
70544
  const proc = (0, import_node_child_process17.spawn)(process.env.CODEX_BIN ?? "codex", ["app-server", "--listen", "stdio://"], {
70298
70545
  cwd,
@@ -70312,7 +70559,7 @@ function openCodexAppServer(home, cwd) {
70312
70559
  async function forkCodexThread(input, deps = {}) {
70313
70560
  const source = locateCodexThread(input.roots, input.sourceThreadId);
70314
70561
  if (!source) throw new Error(`codex fork: source thread not found: ${input.sourceThreadId}`);
70315
- const rollout = parseCodexRollout(import_node_fs59.default.readFileSync(source.file, "utf8"));
70562
+ const rollout = parseCodexRollout(import_node_fs60.default.readFileSync(source.file, "utf8"));
70316
70563
  if (rollout.meta?.threadId.toLowerCase() !== input.sourceThreadId.toLowerCase()) {
70317
70564
  throw new Error(`codex fork: source thread metadata does not match ${input.sourceThreadId}`);
70318
70565
  }
@@ -70342,7 +70589,7 @@ async function forkCodexThread(input, deps = {}) {
70342
70589
  if (typeof forkedToolSessionId !== "string" || !forkedToolSessionId) {
70343
70590
  throw new Error("codex fork: app-server returned no thread id");
70344
70591
  }
70345
- const forked = locateCodexThread([import_node_path65.default.join(source.home, "sessions")], forkedToolSessionId);
70592
+ const forked = locateCodexThread([import_node_path66.default.join(source.home, "sessions")], forkedToolSessionId);
70346
70593
  if (!forked) throw new Error(`codex fork: rollout not found for forked thread ${forkedToolSessionId}`);
70347
70594
  return { forkedToolSessionId, forkedFilePath: forked.file };
70348
70595
  })()]);
@@ -70353,19 +70600,19 @@ async function forkCodexThread(input, deps = {}) {
70353
70600
  }
70354
70601
 
70355
70602
  // src/session/external-scan.ts
70356
- var import_node_fs60 = __toESM(require("fs"), 1);
70603
+ var import_node_fs61 = __toESM(require("fs"), 1);
70357
70604
  var import_promises11 = __toESM(require("fs/promises"), 1);
70358
- var import_node_os24 = __toESM(require("os"), 1);
70359
- var import_node_path66 = __toESM(require("path"), 1);
70605
+ var import_node_os25 = __toESM(require("os"), 1);
70606
+ var import_node_path67 = __toESM(require("path"), 1);
70360
70607
  var import_node_module = require("module");
70361
70608
  var import_node_child_process18 = require("child_process");
70362
70609
  var import_meta7 = {};
70363
70610
  function defaultRoots() {
70364
- const home = import_node_os24.default.homedir();
70611
+ const home = import_node_os25.default.homedir();
70365
70612
  return {
70366
- claudeProjectsDir: import_node_path66.default.join(home, ".claude", "projects"),
70367
- codexDir: import_node_path66.default.join(home, ".codex"),
70368
- clawdDir: import_node_path66.default.join(home, ".clawd")
70613
+ claudeProjectsDir: import_node_path67.default.join(home, ".claude", "projects"),
70614
+ codexDir: import_node_path67.default.join(home, ".codex"),
70615
+ clawdDir: import_node_path67.default.join(home, ".clawd")
70369
70616
  };
70370
70617
  }
70371
70618
  function width(s2) {
@@ -70416,7 +70663,7 @@ function userText(msg) {
70416
70663
  }
70417
70664
  function isDir2(p3) {
70418
70665
  try {
70419
- return import_node_fs60.default.statSync(p3).isDirectory();
70666
+ return import_node_fs61.default.statSync(p3).isDirectory();
70420
70667
  } catch {
70421
70668
  return false;
70422
70669
  }
@@ -70425,7 +70672,7 @@ async function scanClaude(roots) {
70425
70672
  const out = [];
70426
70673
  let dirs;
70427
70674
  try {
70428
- dirs = import_node_fs60.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
70675
+ dirs = import_node_fs61.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
70429
70676
  } catch {
70430
70677
  return out;
70431
70678
  }
@@ -70433,16 +70680,16 @@ async function scanClaude(roots) {
70433
70680
  if (!d2.isDirectory()) continue;
70434
70681
  let files;
70435
70682
  try {
70436
- files = import_node_fs60.default.readdirSync(import_node_path66.default.join(roots.claudeProjectsDir, d2.name));
70683
+ files = import_node_fs61.default.readdirSync(import_node_path67.default.join(roots.claudeProjectsDir, d2.name));
70437
70684
  } catch {
70438
70685
  continue;
70439
70686
  }
70440
70687
  for (const name of files) {
70441
70688
  if (!name.endsWith(".jsonl")) continue;
70442
- const file = import_node_path66.default.join(roots.claudeProjectsDir, d2.name, name);
70689
+ const file = import_node_path67.default.join(roots.claudeProjectsDir, d2.name, name);
70443
70690
  let st2;
70444
70691
  try {
70445
- st2 = import_node_fs60.default.statSync(file);
70692
+ st2 = import_node_fs61.default.statSync(file);
70446
70693
  } catch {
70447
70694
  continue;
70448
70695
  }
@@ -70495,7 +70742,7 @@ async function scanClaude(roots) {
70495
70742
  return out;
70496
70743
  }
70497
70744
  async function countCodexTurns(rolloutPath) {
70498
- if (!rolloutPath || !import_node_fs60.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
70745
+ if (!rolloutPath || !import_node_fs61.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
70499
70746
  let turns = 0;
70500
70747
  let first = "";
70501
70748
  for await (const rec6 of jsonLines(rolloutPath)) {
@@ -70569,7 +70816,7 @@ async function codexFromRows(rows) {
70569
70816
  async function scanCodex(roots) {
70570
70817
  let dbs = [];
70571
70818
  try {
70572
- dbs = import_node_fs60.default.readdirSync(roots.codexDir).filter((n2) => /^state_.*\.sqlite$/.test(n2)).sort().map((n2) => import_node_path66.default.join(roots.codexDir, n2));
70819
+ dbs = import_node_fs61.default.readdirSync(roots.codexDir).filter((n2) => /^state_.*\.sqlite$/.test(n2)).sort().map((n2) => import_node_path67.default.join(roots.codexDir, n2));
70573
70820
  } catch {
70574
70821
  }
70575
70822
  if (!dbs.length) return [];
@@ -70578,14 +70825,14 @@ async function scanCodex(roots) {
70578
70825
  }
70579
70826
  async function scanExternalSessions(rootsIn) {
70580
70827
  const roots = { ...defaultRoots(), ...rootsIn };
70581
- const personaRoot = import_node_path66.default.join(roots.clawdDir, "personas");
70828
+ const personaRoot = import_node_path67.default.join(roots.clawdDir, "personas");
70582
70829
  const all = [...await scanClaude(roots), ...await scanCodex(roots)];
70583
70830
  const out = [];
70584
70831
  for (const c2 of all) {
70585
70832
  if (c2.skip) continue;
70586
70833
  if (c2.turns < 1) continue;
70587
70834
  if (!c2.cwd || !isDir2(c2.cwd)) continue;
70588
- if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot + import_node_path66.default.sep) || c2.cwd.startsWith(roots.clawdDir + import_node_path66.default.sep)) {
70835
+ if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot + import_node_path67.default.sep) || c2.cwd.startsWith(roots.clawdDir + import_node_path67.default.sep)) {
70589
70836
  continue;
70590
70837
  }
70591
70838
  out.push({
@@ -70602,13 +70849,13 @@ async function scanExternalSessions(rootsIn) {
70602
70849
  }
70603
70850
 
70604
70851
  // src/session/import-ledger.ts
70605
- var import_node_fs61 = __toESM(require("fs"), 1);
70606
- var import_node_path67 = __toESM(require("path"), 1);
70852
+ var import_node_fs62 = __toESM(require("fs"), 1);
70853
+ var import_node_path68 = __toESM(require("path"), 1);
70607
70854
  var LEDGER_FILENAME = "session-import-ledger.json";
70608
70855
  function readImportLedger(dataDir) {
70609
70856
  try {
70610
70857
  const parsed = JSON.parse(
70611
- import_node_fs61.default.readFileSync(import_node_path67.default.join(dataDir, LEDGER_FILENAME), "utf8")
70858
+ import_node_fs62.default.readFileSync(import_node_path68.default.join(dataDir, LEDGER_FILENAME), "utf8")
70612
70859
  );
70613
70860
  return Array.isArray(parsed) ? parsed : [];
70614
70861
  } catch {
@@ -70616,15 +70863,15 @@ function readImportLedger(dataDir) {
70616
70863
  }
70617
70864
  }
70618
70865
  function appendImportLedger(dataDir, entry) {
70619
- const file = import_node_path67.default.join(dataDir, LEDGER_FILENAME);
70866
+ const file = import_node_path68.default.join(dataDir, LEDGER_FILENAME);
70620
70867
  const entries = readImportLedger(dataDir);
70621
70868
  entries.push(entry);
70622
- import_node_fs61.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
70869
+ import_node_fs62.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
70623
70870
  }
70624
70871
 
70625
70872
  // src/handlers/session.ts
70626
70873
  init_protocol();
70627
- var import_node_path68 = __toESM(require("path"), 1);
70874
+ var import_node_path69 = __toESM(require("path"), 1);
70628
70875
  function canReadSearchHit(ctx, file) {
70629
70876
  if (!ctx || ctx.principal.kind === "owner") return true;
70630
70877
  return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
@@ -70905,7 +71152,7 @@ ${attribution}` } : args;
70905
71152
  `principal guest:${ctx.principal.id} cannot fork tool session ${args.toolSessionId}`
70906
71153
  );
70907
71154
  }
70908
- if (source?.tool === "codex" && args.targetCwd && import_node_path68.default.resolve(args.targetCwd) !== import_node_path68.default.resolve(source.cwd)) {
71155
+ if (source?.tool === "codex" && args.targetCwd && import_node_path69.default.resolve(args.targetCwd) !== import_node_path69.default.resolve(source.cwd)) {
70909
71156
  throw new ClawdError(ERROR_CODES.FORBIDDEN, "fork: guest targetCwd must match source cwd");
70910
71157
  }
70911
71158
  }
@@ -71182,7 +71429,7 @@ function buildPermissionHandlers(deps) {
71182
71429
  }
71183
71430
 
71184
71431
  // src/handlers/history.ts
71185
- var path83 = __toESM(require("path"), 1);
71432
+ var path84 = __toESM(require("path"), 1);
71186
71433
  init_protocol();
71187
71434
 
71188
71435
  // src/session/recent-dirs.ts
@@ -71200,7 +71447,7 @@ function listRecentDirs(store, limit = 50) {
71200
71447
  }
71201
71448
 
71202
71449
  // src/permission/persona-paths.ts
71203
- var path82 = __toESM(require("path"), 1);
71450
+ var path83 = __toESM(require("path"), 1);
71204
71451
  function getAllowedPersonaIds(grants, action) {
71205
71452
  const ids = /* @__PURE__ */ new Set();
71206
71453
  for (const g3 of grants) {
@@ -71213,42 +71460,42 @@ function getAllowedPersonaIds(grants, action) {
71213
71460
  return ids;
71214
71461
  }
71215
71462
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
71216
- const target = path82.resolve(absPath);
71463
+ const target = path83.resolve(absPath);
71217
71464
  if (userWorkDir) {
71218
- const u2 = path82.resolve(userWorkDir);
71219
- const usep = u2.endsWith(path82.sep) ? "" : path82.sep;
71465
+ const u2 = path83.resolve(userWorkDir);
71466
+ const usep = u2.endsWith(path83.sep) ? "" : path83.sep;
71220
71467
  if (target === u2 || target.startsWith(u2 + usep)) return true;
71221
71468
  }
71222
- const root = path82.resolve(personaRoot);
71223
- const sep4 = root.endsWith(path82.sep) ? "" : path82.sep;
71469
+ const root = path83.resolve(personaRoot);
71470
+ const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
71224
71471
  if (!target.startsWith(root + sep4)) return false;
71225
- const rel = path82.relative(root, target);
71472
+ const rel = path83.relative(root, target);
71226
71473
  if (!rel || rel.startsWith("..")) return false;
71227
- const personaId2 = rel.split(path82.sep)[0];
71474
+ const personaId2 = rel.split(path83.sep)[0];
71228
71475
  if (!personaId2) return false;
71229
71476
  const allowed = getAllowedPersonaIds(grants, action);
71230
71477
  if (allowed === "*") return true;
71231
71478
  return allowed.has(personaId2);
71232
71479
  }
71233
71480
  function personaIdFromPath(absPath, personaRoot) {
71234
- const root = path82.resolve(personaRoot);
71235
- const target = path82.resolve(absPath);
71236
- const sep4 = root.endsWith(path82.sep) ? "" : path82.sep;
71481
+ const root = path83.resolve(personaRoot);
71482
+ const target = path83.resolve(absPath);
71483
+ const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
71237
71484
  if (!target.startsWith(root + sep4)) return null;
71238
- const rel = path82.relative(root, target);
71485
+ const rel = path83.relative(root, target);
71239
71486
  if (!rel || rel.startsWith("..")) return null;
71240
- const id = rel.split(path82.sep)[0];
71487
+ const id = rel.split(path83.sep)[0];
71241
71488
  return id || null;
71242
71489
  }
71243
71490
  function isPathWithin(dir, absPath) {
71244
- const d2 = path82.resolve(dir);
71245
- const t2 = path82.resolve(absPath);
71246
- const sep4 = d2.endsWith(path82.sep) ? "" : path82.sep;
71491
+ const d2 = path83.resolve(dir);
71492
+ const t2 = path83.resolve(absPath);
71493
+ const sep4 = d2.endsWith(path83.sep) ? "" : path83.sep;
71247
71494
  return t2 === d2 || t2.startsWith(d2 + sep4);
71248
71495
  }
71249
71496
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
71250
71497
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
71251
- return personaIdFromPath(path82.resolve(absPath), personaRoot) === personaId2;
71498
+ return personaIdFromPath(path83.resolve(absPath), personaRoot) === personaId2;
71252
71499
  }
71253
71500
 
71254
71501
  // src/handlers/history.ts
@@ -71302,7 +71549,7 @@ function buildHistoryHandlers(deps) {
71302
71549
  if (!pid) return false;
71303
71550
  return isGuestPathAllowed(
71304
71551
  ctx.grants,
71305
- path83.join(personaRoot, pid),
71552
+ path84.join(personaRoot, pid),
71306
71553
  personaRoot,
71307
71554
  "read",
71308
71555
  userWorkDir
@@ -71314,7 +71561,7 @@ function buildHistoryHandlers(deps) {
71314
71561
  };
71315
71562
  const list = async (frame, _client, ctx) => {
71316
71563
  const args = HistoryListArgs.parse(frame);
71317
- assertGuestPath(ctx, path83.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
71564
+ assertGuestPath(ctx, path84.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
71318
71565
  const sessions = await history.listSessions(args);
71319
71566
  return { response: { type: "history:list", sessions } };
71320
71567
  };
@@ -71362,14 +71609,14 @@ function buildHistoryHandlers(deps) {
71362
71609
  };
71363
71610
  const subagents = async (frame, _client, ctx) => {
71364
71611
  const args = HistorySubagentsArgs.parse(frame);
71365
- assertGuestPath(ctx, path83.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
71612
+ assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
71366
71613
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
71367
71614
  const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
71368
71615
  return { response: { type: "history:subagents", subagents: subs } };
71369
71616
  };
71370
71617
  const subagentRead = async (frame, _client, ctx) => {
71371
71618
  const args = HistorySubagentReadArgs.parse(frame);
71372
- assertGuestPath(ctx, path83.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
71619
+ assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
71373
71620
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
71374
71621
  const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
71375
71622
  return { response: { type: "history:subagent-read", ...res } };
@@ -71379,7 +71626,7 @@ function buildHistoryHandlers(deps) {
71379
71626
  if (ctx?.principal.kind === "guest" && personaRoot) {
71380
71627
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
71381
71628
  const filtered = dirs.filter(
71382
- (d2) => isGuestPathAllowed(ctx.grants, path83.resolve(d2.cwd), personaRoot, "read", userWorkDir)
71629
+ (d2) => isGuestPathAllowed(ctx.grants, path84.resolve(d2.cwd), personaRoot, "read", userWorkDir)
71383
71630
  );
71384
71631
  return { response: { type: "history:recentDirs", dirs: filtered } };
71385
71632
  }
@@ -71396,17 +71643,17 @@ function buildHistoryHandlers(deps) {
71396
71643
  }
71397
71644
 
71398
71645
  // src/handlers/projects.ts
71399
- var fs79 = __toESM(require("fs"), 1);
71400
- var os26 = __toESM(require("os"), 1);
71401
- var path84 = __toESM(require("path"), 1);
71646
+ var fs80 = __toESM(require("fs"), 1);
71647
+ var os27 = __toESM(require("os"), 1);
71648
+ var path85 = __toESM(require("path"), 1);
71402
71649
  var import_node_child_process19 = require("child_process");
71403
71650
  init_protocol();
71404
- var DEFAULT_PROJECTS_ROOT = path84.join(os26.homedir(), "Documents", "ChatGPT");
71651
+ var DEFAULT_PROJECTS_ROOT = path85.join(os27.homedir(), "Documents", "ChatGPT");
71405
71652
  function allocateDir(root, name) {
71406
- let candidate = path84.join(root, name);
71653
+ let candidate = path85.join(root, name);
71407
71654
  let n2 = 2;
71408
- while (fs79.existsSync(candidate)) {
71409
- candidate = path84.join(root, `${name} ${n2}`);
71655
+ while (fs80.existsSync(candidate)) {
71656
+ candidate = path85.join(root, `${name} ${n2}`);
71410
71657
  n2 += 1;
71411
71658
  }
71412
71659
  return candidate;
@@ -71434,7 +71681,7 @@ function buildProjectHandlers(deps) {
71434
71681
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
71435
71682
  }
71436
71683
  try {
71437
- if (!fs79.statSync(args.path).isDirectory()) throw new Error("not dir");
71684
+ if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
71438
71685
  } catch {
71439
71686
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
71440
71687
  }
@@ -71450,7 +71697,7 @@ function buildProjectHandlers(deps) {
71450
71697
  let target;
71451
71698
  if (args.path) {
71452
71699
  try {
71453
- if (!fs79.statSync(args.path).isDirectory()) throw new Error("not dir");
71700
+ if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
71454
71701
  } catch {
71455
71702
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
71456
71703
  }
@@ -71458,15 +71705,15 @@ function buildProjectHandlers(deps) {
71458
71705
  } else {
71459
71706
  const name = args.name;
71460
71707
  try {
71461
- fs79.mkdirSync(root, { recursive: true });
71708
+ fs80.mkdirSync(root, { recursive: true });
71462
71709
  target = allocateDir(root, name);
71463
- fs79.mkdirSync(target);
71710
+ fs80.mkdirSync(target);
71464
71711
  } catch (err) {
71465
71712
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
71466
71713
  }
71467
71714
  const git2 = (0, import_node_child_process19.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
71468
71715
  if (git2.status !== 0) {
71469
- fs79.rmSync(target, { recursive: true, force: true });
71716
+ fs80.rmSync(target, { recursive: true, force: true });
71470
71717
  throw new ClawdError(
71471
71718
  ERROR_CODES.INVALID_CWD,
71472
71719
  `git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
@@ -71491,9 +71738,9 @@ function buildProjectHandlers(deps) {
71491
71738
  }
71492
71739
 
71493
71740
  // src/handlers/workspace.ts
71494
- var path85 = __toESM(require("path"), 1);
71741
+ var path86 = __toESM(require("path"), 1);
71495
71742
  init_protocol();
71496
- var os27 = __toESM(require("os"), 1);
71743
+ var os28 = __toESM(require("os"), 1);
71497
71744
  init_protocol();
71498
71745
  init_protocol();
71499
71746
  function buildEnabledPluginNames(personaManager, personaId2) {
@@ -71533,23 +71780,23 @@ function buildWorkspaceHandlers(deps) {
71533
71780
  const list = async (frame, _client, ctx) => {
71534
71781
  const args = WorkspaceListArgs.parse(frame);
71535
71782
  const isGuest = ctx?.principal.kind === "guest";
71536
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os27.homedir();
71537
- const resolvedCwd = path85.resolve(args.cwd ?? fallbackCwd);
71538
- const target = args.path ? path85.resolve(resolvedCwd, args.path) : resolvedCwd;
71783
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os28.homedir();
71784
+ const resolvedCwd = path86.resolve(args.cwd ?? fallbackCwd);
71785
+ const target = args.path ? path86.resolve(resolvedCwd, args.path) : resolvedCwd;
71539
71786
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
71540
71787
  const res = workspace.list({ ...args, cwd: resolvedCwd });
71541
71788
  return { response: { type: "workspace:list", ...res } };
71542
71789
  };
71543
71790
  const read = async (frame, _client, ctx) => {
71544
71791
  const args = WorkspaceReadArgs.parse(frame);
71545
- const target = path85.isAbsolute(args.path) ? path85.resolve(args.path) : path85.resolve(args.cwd, args.path);
71792
+ const target = path86.isAbsolute(args.path) ? path86.resolve(args.path) : path86.resolve(args.cwd, args.path);
71546
71793
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
71547
71794
  const res = workspace.read(args);
71548
71795
  return { response: { type: "workspace:read", ...res } };
71549
71796
  };
71550
71797
  const skillsList = async (frame, _client, ctx) => {
71551
71798
  const args = SkillsListArgs.parse(frame);
71552
- const cwdAbs = path85.resolve(args.cwd);
71799
+ const cwdAbs = path86.resolve(args.cwd);
71553
71800
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
71554
71801
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
71555
71802
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -71561,7 +71808,7 @@ function buildWorkspaceHandlers(deps) {
71561
71808
  };
71562
71809
  const agentsList = async (frame, _client, ctx) => {
71563
71810
  const args = AgentsListArgs.parse(frame);
71564
- const cwdAbs = path85.resolve(args.cwd);
71811
+ const cwdAbs = path86.resolve(args.cwd);
71565
71812
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
71566
71813
  if (isCodexFamily(args.tool) || isPiFamily(args.tool)) {
71567
71814
  return { response: { type: "agents:list", agents: [] } };
@@ -71583,20 +71830,20 @@ function buildWorkspaceHandlers(deps) {
71583
71830
  }
71584
71831
 
71585
71832
  // src/handlers/git.ts
71586
- var path87 = __toESM(require("path"), 1);
71833
+ var path88 = __toESM(require("path"), 1);
71587
71834
  init_protocol();
71588
71835
  init_protocol();
71589
71836
 
71590
71837
  // src/workspace/git.ts
71591
71838
  var import_node_child_process20 = require("child_process");
71592
- var import_node_fs62 = __toESM(require("fs"), 1);
71593
- var import_node_path69 = __toESM(require("path"), 1);
71839
+ var import_node_fs63 = __toESM(require("fs"), 1);
71840
+ var import_node_path70 = __toESM(require("path"), 1);
71594
71841
  var import_node_util2 = require("util");
71595
71842
  var pexec = (0, import_node_util2.promisify)(import_node_child_process20.execFile);
71596
71843
  function normalizePath(p3) {
71597
- const resolved = import_node_path69.default.resolve(p3);
71844
+ const resolved = import_node_path70.default.resolve(p3);
71598
71845
  try {
71599
- return import_node_fs62.default.realpathSync(resolved);
71846
+ return import_node_fs63.default.realpathSync(resolved);
71600
71847
  } catch {
71601
71848
  return resolved;
71602
71849
  }
@@ -71670,7 +71917,7 @@ async function listGitBranches(cwd) {
71670
71917
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
71671
71918
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
71672
71919
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
71673
- if (!isGuestPathAllowed(ctx.grants, path87.resolve(cwd), personaRoot, "read", userWorkDir)) {
71920
+ if (!isGuestPathAllowed(ctx.grants, path88.resolve(cwd), personaRoot, "read", userWorkDir)) {
71674
71921
  throw new ClawdError(
71675
71922
  ERROR_CODES.UNAUTHORIZED,
71676
71923
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -71927,12 +72174,12 @@ async function queryCodexAccount(deps = {}) {
71927
72174
  }
71928
72175
 
71929
72176
  // src/tools/pi-account.ts
71930
- var import_node_fs63 = __toESM(require("fs"), 1);
71931
- var import_node_path70 = __toESM(require("path"), 1);
72177
+ var import_node_fs64 = __toESM(require("fs"), 1);
72178
+ var import_node_path71 = __toESM(require("path"), 1);
71932
72179
  function readPiCredentials(agentDir) {
71933
72180
  let raw;
71934
72181
  try {
71935
- raw = JSON.parse(import_node_fs63.default.readFileSync(import_node_path70.default.join(agentDir, "auth.json"), "utf8"));
72182
+ raw = JSON.parse(import_node_fs64.default.readFileSync(import_node_path71.default.join(agentDir, "auth.json"), "utf8"));
71936
72183
  } catch {
71937
72184
  return {};
71938
72185
  }
@@ -72015,81 +72262,6 @@ function buildEngineHandlers(deps, overrides = {}) {
72015
72262
  return { "engine:status": status, "engine:connectPool": connectPool };
72016
72263
  }
72017
72264
 
72018
- // src/tools/subscription-channels-apply.ts
72019
- var import_node_fs64 = __toESM(require("fs"), 1);
72020
- var import_node_os25 = __toESM(require("os"), 1);
72021
- var import_node_path71 = __toESM(require("path"), 1);
72022
- var TABLE_HEADER = /^\s*\[\[?\s*([A-Za-z0-9_.-]+)\s*\]\]?\s*(?:#.*)?$/;
72023
- var KEY_LINE = /^\s*([A-Za-z0-9_.-]+)\s*=/;
72024
- function stripCodexProvider(text) {
72025
- const out = [];
72026
- let inProviderSection = false;
72027
- for (const line of text.split("\n")) {
72028
- const headerMatch = TABLE_HEADER.exec(line);
72029
- if (headerMatch) {
72030
- const section = headerMatch[1].trim();
72031
- inProviderSection = section === "model_providers" || section.startsWith("model_providers.");
72032
- if (inProviderSection) continue;
72033
- out.push(line);
72034
- continue;
72035
- }
72036
- if (inProviderSection) continue;
72037
- const keyMatch = KEY_LINE.exec(line);
72038
- if (keyMatch) {
72039
- const key = keyMatch[1].trim();
72040
- if (key === "model_provider" || key.startsWith("model_providers.")) {
72041
- continue;
72042
- }
72043
- }
72044
- out.push(line);
72045
- }
72046
- return out.join("\n").trim();
72047
- }
72048
- function applyCodexSubscriptionChannel(opts) {
72049
- const codexHome = opts.codexHome || process.env.CODEX_HOME || import_node_path71.default.join(import_node_os25.default.homedir(), ".codex");
72050
- import_node_fs64.default.mkdirSync(codexHome, { recursive: true });
72051
- const configFile = import_node_path71.default.join(codexHome, "config.toml");
72052
- const original = import_node_fs64.default.existsSync(configFile) ? import_node_fs64.default.readFileSync(configFile, "utf8") : "";
72053
- const rest = stripCodexProvider(original);
72054
- let content;
72055
- if (opts.channel) {
72056
- const ch = opts.channel;
72057
- content = [
72058
- 'model_provider = "cliproxyapi"',
72059
- ...rest ? ["", rest] : [],
72060
- "",
72061
- "[model_providers.cliproxyapi]",
72062
- 'name = "cliproxyapi"',
72063
- `base_url = ${JSON.stringify(ch.baseUrl)}`,
72064
- 'wire_api = "responses"',
72065
- `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
72066
- ""
72067
- ].join("\n");
72068
- } else {
72069
- content = [
72070
- 'model_provider = "openai"',
72071
- ...rest ? ["", rest] : [],
72072
- ""
72073
- ].join("\n");
72074
- }
72075
- const tmpFile = `${configFile}.tmp.${Date.now()}`;
72076
- import_node_fs64.default.writeFileSync(tmpFile, content, { mode: 384 });
72077
- import_node_fs64.default.renameSync(tmpFile, configFile);
72078
- }
72079
- function applyPiSubscriptionChannel(opts) {
72080
- const agentDir = opts.agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path71.default.join(import_node_os25.default.homedir(), ".pi", "agent");
72081
- if (!import_node_fs64.default.existsSync(agentDir)) return false;
72082
- const configFile = import_node_path71.default.join(agentDir, "cliproxyapi.json");
72083
- if (opts.channel) {
72084
- const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
72085
- const tmp = `${configFile}.tmp.${Date.now()}`;
72086
- import_node_fs64.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
72087
- import_node_fs64.default.renameSync(tmp, configFile);
72088
- return true;
72089
- }
72090
- return false;
72091
- }
72092
-
72093
72265
  // src/handlers/channels.ts
72094
72266
  function buildChannelsHandlers(deps) {
72095
72267
  const get = async () => {
@@ -73092,7 +73264,7 @@ function computeMethodAccess(args) {
73092
73264
  }
73093
73265
 
73094
73266
  // src/version.ts
73095
- var version = "0.2.602".length > 0 ? "0.2.602" : "dev";
73267
+ var version = "0.2.604".length > 0 ? "0.2.604" : "dev";
73096
73268
 
73097
73269
  // src/cli-probe/probe.ts
73098
73270
  var fs83 = __toESM(require("fs"), 1);
@@ -75720,6 +75892,8 @@ async function startDaemon(config) {
75720
75892
  let transport = null;
75721
75893
  const personaStore = new PersonaStore(import_node_path84.default.join(config.dataDir, "personas"));
75722
75894
  const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
75895
+ const activeSubscriptionChannel = subscriptionChannelStore.getActive();
75896
+ if (activeSubscriptionChannel) applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
75723
75897
  const usersRoot = import_node_path84.default.join(config.dataDir, "users");
75724
75898
  const defaultsRoot = findDefaultsRoot(logger);
75725
75899
  if (defaultsRoot) {