@clawos-dev/clawd 0.2.85-beta.158.934b6ca → 0.2.85-beta.160.958069f

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 +442 -400
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -65,14 +65,6 @@ var init_methods = __esm({
65
65
  "session:unsubscribe",
66
66
  "session:pin",
67
67
  "session:reorderPins",
68
- // mirror peer sessions (2026-05-26): owner-only RPC,写/删本机 mirror SessionFile —
69
- // mirror 是「**我**在朋友 daemon 上自己创建的 session」的本机持久化副本(不是朋友的会话),
70
- // 方便 sidebar 跨设备聚合。daemon dumb 写删,**不广播任何 push 帧** (不发 session:info /
71
- // session:deleted);UI 是写入唯一源,双写完成后通过 cache.setData('sessions', ...) 同步
72
- // 本地 sidebar state。native session:* handler 完全不感知 mirror (UI 操作 mirror 不复用
73
- // native 路径)。
74
- "peerSession:upsert",
75
- "peerSession:remove",
76
68
  "permission:respond",
77
69
  // AskUserQuestion 表单回写:UI 答完所有 question 后调用,daemon 把答案合并进 updated_input
78
70
  // 写一条 control_response 到 CC stdin(详见 events.ts session:question JSDoc)
@@ -651,8 +643,8 @@ var init_parseUtil = __esm({
651
643
  init_errors2();
652
644
  init_en();
653
645
  makeIssue = (params) => {
654
- const { data, path: path43, errorMaps, issueData } = params;
655
- const fullPath = [...path43, ...issueData.path || []];
646
+ const { data, path: path44, errorMaps, issueData } = params;
647
+ const fullPath = [...path44, ...issueData.path || []];
656
648
  const fullIssue = {
657
649
  ...issueData,
658
650
  path: fullPath
@@ -963,11 +955,11 @@ var init_types = __esm({
963
955
  init_parseUtil();
964
956
  init_util();
965
957
  ParseInputLazyPath = class {
966
- constructor(parent, value, path43, key) {
958
+ constructor(parent, value, path44, key) {
967
959
  this._cachedPath = [];
968
960
  this.parent = parent;
969
961
  this.data = value;
970
- this._path = path43;
962
+ this._path = path44;
971
963
  this._key = key;
972
964
  }
973
965
  get path() {
@@ -4491,7 +4483,7 @@ var init_persona_schemas = __esm({
4491
4483
  });
4492
4484
 
4493
4485
  // ../protocol/src/schemas.ts
4494
- var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema;
4486
+ var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionSubscribeArgs, SessionPinArgs, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema;
4495
4487
  var init_schemas = __esm({
4496
4488
  "../protocol/src/schemas.ts"() {
4497
4489
  "use strict";
@@ -4619,35 +4611,6 @@ var init_schemas = __esm({
4619
4611
  * 当前为 caller 自报,daemon 不密码学验证真伪;强身份验签是独立工作(B 方案)。
4620
4612
  */
4621
4613
  creatorOwnerPrincipalId: external_exports.string().min(1).optional(),
4622
- /**
4623
- * Mirror peer sessions (2026-05-26): mirror 标识。**我在朋友 daemon 上以 guest ctx
4624
- * 创建的 session**,远端是 source of truth,本机是该 session 的持久化副本,方便
4625
- * sidebar 跨设备聚合。字段值是远端 daemon 的 ownerPrincipalId(即我接入的那位朋友)。
4626
- *
4627
- * 语义关键澄清:mirror **不是朋友创建给我的会话**——它是我自己的会话,只是在朋友
4628
- * 的机器上跑。sidebar chip 显示 `@<朋友>` 暗示「位置」,不是「来源」。
4629
- *
4630
- * - undefined / 缺省 → 本机 native session(在我自己机器上跑)
4631
- * - 非空 → 我的会话在该 ownerPrincipalId 朋友的 daemon 上跑,本机为持久化副本
4632
- *
4633
- * 与 `creatorPrincipalId` / `creatorOwnerPrincipalId` 在四类 session 下取值矩阵:
4634
- * | 形态 | creatorPrincipalId | creatorOwnerPrincipalId | originOwnerPrincipalId |
4635
- * |-------------------------------------|--------------------------|-------------------------|------------------------|
4636
- * | 本机 owner 自创 | 本机 ownerPrincipalId | 本机 ownerPrincipalId | undefined |
4637
- * | 本机被别人通过 personal token 接入创建 | 远端接入者 cap.id | 远端接入者 ownerPrincipalId | undefined |
4638
- * | 我在朋友 daemon 上以 guest ctx 创建(mirror 回本机) | 朋友 daemon personal cap.id | 我自己 ownerPrincipalId | 朋友 ownerPrincipalId |
4639
- *
4640
- * UI 用法:
4641
- * - sidebar Active/Pinned/Recents 过滤:`origin 非空 → 一律视作 self`(绕过 #739 隔离)
4642
- * - 行内显示 `@<朋友>` chip 暗示位置
4643
- * - 进 ChatPanel 时按 origin 路由到 `pool.ensureRemoteForOwner(origin)` 走远端
4644
- *
4645
- * daemon 用法:
4646
- * - `peerSession:upsert` / `peerSession:remove` 一族 RPC 专管 mirror 写删;
4647
- * daemon dumb write/delete,**不广播任何 push 帧**,UI 是写入唯一源
4648
- * - native `session:*` handler 完全不感知 mirror(UI 操作 mirror 不走 native 路径)
4649
- */
4650
- originOwnerPrincipalId: external_exports.string().min(1).optional(),
4651
4614
  createdAt: external_exports.string().min(1),
4652
4615
  updatedAt: external_exports.string().min(1)
4653
4616
  });
@@ -5003,14 +4966,6 @@ var init_schemas = __esm({
5003
4966
  sessionId: external_exports.string().min(1),
5004
4967
  pinned: external_exports.boolean()
5005
4968
  });
5006
- PeerSessionUpsertArgs = SessionFileSchema;
5007
- PeerSessionUpsertResponseSchema = external_exports.object({
5008
- type: external_exports.literal("peerSession:upsert:ok")
5009
- });
5010
- PeerSessionRemoveArgs = external_exports.object({ sessionId: external_exports.string().min(1) });
5011
- PeerSessionRemoveResponseSchema = external_exports.object({
5012
- type: external_exports.literal("peerSession:remove:ok")
5013
- });
5014
4969
  SessionReorderPinsArgs = external_exports.object({
5015
4970
  orderedIds: external_exports.array(external_exports.string().min(1)).min(1)
5016
4971
  });
@@ -5625,8 +5580,8 @@ var require_req = __commonJS({
5625
5580
  if (req.originalUrl) {
5626
5581
  _req.url = req.originalUrl;
5627
5582
  } else {
5628
- const path43 = req.path;
5629
- _req.url = typeof path43 === "string" ? path43 : req.url ? req.url.path || req.url : void 0;
5583
+ const path44 = req.path;
5584
+ _req.url = typeof path44 === "string" ? path44 : req.url ? req.url.path || req.url : void 0;
5630
5585
  }
5631
5586
  if (req.query) {
5632
5587
  _req.query = req.query;
@@ -5791,14 +5746,14 @@ var require_redact = __commonJS({
5791
5746
  }
5792
5747
  return obj;
5793
5748
  }
5794
- function parsePath(path43) {
5749
+ function parsePath(path44) {
5795
5750
  const parts = [];
5796
5751
  let current = "";
5797
5752
  let inBrackets = false;
5798
5753
  let inQuotes = false;
5799
5754
  let quoteChar = "";
5800
- for (let i = 0; i < path43.length; i++) {
5801
- const char = path43[i];
5755
+ for (let i = 0; i < path44.length; i++) {
5756
+ const char = path44[i];
5802
5757
  if (!inBrackets && char === ".") {
5803
5758
  if (current) {
5804
5759
  parts.push(current);
@@ -5929,10 +5884,10 @@ var require_redact = __commonJS({
5929
5884
  return current;
5930
5885
  }
5931
5886
  function redactPaths(obj, paths, censor, remove = false) {
5932
- for (const path43 of paths) {
5933
- const parts = parsePath(path43);
5887
+ for (const path44 of paths) {
5888
+ const parts = parsePath(path44);
5934
5889
  if (parts.includes("*")) {
5935
- redactWildcardPath(obj, parts, censor, path43, remove);
5890
+ redactWildcardPath(obj, parts, censor, path44, remove);
5936
5891
  } else {
5937
5892
  if (remove) {
5938
5893
  removeKey(obj, parts);
@@ -6017,8 +5972,8 @@ var require_redact = __commonJS({
6017
5972
  }
6018
5973
  } else {
6019
5974
  if (afterWildcard.includes("*")) {
6020
- const wrappedCensor = typeof censor === "function" ? (value, path43) => {
6021
- const fullPath = [...pathArray.slice(0, pathLength), ...path43];
5975
+ const wrappedCensor = typeof censor === "function" ? (value, path44) => {
5976
+ const fullPath = [...pathArray.slice(0, pathLength), ...path44];
6022
5977
  return censor(value, fullPath);
6023
5978
  } : censor;
6024
5979
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6053,8 +6008,8 @@ var require_redact = __commonJS({
6053
6008
  return null;
6054
6009
  }
6055
6010
  const pathStructure = /* @__PURE__ */ new Map();
6056
- for (const path43 of pathsToClone) {
6057
- const parts = parsePath(path43);
6011
+ for (const path44 of pathsToClone) {
6012
+ const parts = parsePath(path44);
6058
6013
  let current = pathStructure;
6059
6014
  for (let i = 0; i < parts.length; i++) {
6060
6015
  const part = parts[i];
@@ -6106,24 +6061,24 @@ var require_redact = __commonJS({
6106
6061
  }
6107
6062
  return cloneSelectively(obj, pathStructure);
6108
6063
  }
6109
- function validatePath(path43) {
6110
- if (typeof path43 !== "string") {
6064
+ function validatePath(path44) {
6065
+ if (typeof path44 !== "string") {
6111
6066
  throw new Error("Paths must be (non-empty) strings");
6112
6067
  }
6113
- if (path43 === "") {
6068
+ if (path44 === "") {
6114
6069
  throw new Error("Invalid redaction path ()");
6115
6070
  }
6116
- if (path43.includes("..")) {
6117
- throw new Error(`Invalid redaction path (${path43})`);
6071
+ if (path44.includes("..")) {
6072
+ throw new Error(`Invalid redaction path (${path44})`);
6118
6073
  }
6119
- if (path43.includes(",")) {
6120
- throw new Error(`Invalid redaction path (${path43})`);
6074
+ if (path44.includes(",")) {
6075
+ throw new Error(`Invalid redaction path (${path44})`);
6121
6076
  }
6122
6077
  let bracketCount = 0;
6123
6078
  let inQuotes = false;
6124
6079
  let quoteChar = "";
6125
- for (let i = 0; i < path43.length; i++) {
6126
- const char = path43[i];
6080
+ for (let i = 0; i < path44.length; i++) {
6081
+ const char = path44[i];
6127
6082
  if ((char === '"' || char === "'") && bracketCount > 0) {
6128
6083
  if (!inQuotes) {
6129
6084
  inQuotes = true;
@@ -6137,20 +6092,20 @@ var require_redact = __commonJS({
6137
6092
  } else if (char === "]" && !inQuotes) {
6138
6093
  bracketCount--;
6139
6094
  if (bracketCount < 0) {
6140
- throw new Error(`Invalid redaction path (${path43})`);
6095
+ throw new Error(`Invalid redaction path (${path44})`);
6141
6096
  }
6142
6097
  }
6143
6098
  }
6144
6099
  if (bracketCount !== 0) {
6145
- throw new Error(`Invalid redaction path (${path43})`);
6100
+ throw new Error(`Invalid redaction path (${path44})`);
6146
6101
  }
6147
6102
  }
6148
6103
  function validatePaths(paths) {
6149
6104
  if (!Array.isArray(paths)) {
6150
6105
  throw new TypeError("paths must be an array");
6151
6106
  }
6152
- for (const path43 of paths) {
6153
- validatePath(path43);
6107
+ for (const path44 of paths) {
6108
+ validatePath(path44);
6154
6109
  }
6155
6110
  }
6156
6111
  function slowRedact(options = {}) {
@@ -6318,8 +6273,8 @@ var require_redaction = __commonJS({
6318
6273
  if (shape[k2] === null) {
6319
6274
  o[k2] = (value) => topCensor(value, [k2]);
6320
6275
  } else {
6321
- const wrappedCensor = typeof censor === "function" ? (value, path43) => {
6322
- return censor(value, [k2, ...path43]);
6276
+ const wrappedCensor = typeof censor === "function" ? (value, path44) => {
6277
+ return censor(value, [k2, ...path44]);
6323
6278
  } : censor;
6324
6279
  o[k2] = Redact({
6325
6280
  paths: shape[k2],
@@ -6537,10 +6492,10 @@ var require_atomic_sleep = __commonJS({
6537
6492
  var require_sonic_boom = __commonJS({
6538
6493
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6539
6494
  "use strict";
6540
- var fs34 = require("fs");
6495
+ var fs35 = require("fs");
6541
6496
  var EventEmitter2 = require("events");
6542
6497
  var inherits = require("util").inherits;
6543
- var path43 = require("path");
6498
+ var path44 = require("path");
6544
6499
  var sleep = require_atomic_sleep();
6545
6500
  var assert = require("assert");
6546
6501
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6594,20 +6549,20 @@ var require_sonic_boom = __commonJS({
6594
6549
  const mode = sonic.mode;
6595
6550
  if (sonic.sync) {
6596
6551
  try {
6597
- if (sonic.mkdir) fs34.mkdirSync(path43.dirname(file), { recursive: true });
6598
- const fd = fs34.openSync(file, flags, mode);
6552
+ if (sonic.mkdir) fs35.mkdirSync(path44.dirname(file), { recursive: true });
6553
+ const fd = fs35.openSync(file, flags, mode);
6599
6554
  fileOpened(null, fd);
6600
6555
  } catch (err) {
6601
6556
  fileOpened(err);
6602
6557
  throw err;
6603
6558
  }
6604
6559
  } else if (sonic.mkdir) {
6605
- fs34.mkdir(path43.dirname(file), { recursive: true }, (err) => {
6560
+ fs35.mkdir(path44.dirname(file), { recursive: true }, (err) => {
6606
6561
  if (err) return fileOpened(err);
6607
- fs34.open(file, flags, mode, fileOpened);
6562
+ fs35.open(file, flags, mode, fileOpened);
6608
6563
  });
6609
6564
  } else {
6610
- fs34.open(file, flags, mode, fileOpened);
6565
+ fs35.open(file, flags, mode, fileOpened);
6611
6566
  }
6612
6567
  }
6613
6568
  function SonicBoom(opts) {
@@ -6648,8 +6603,8 @@ var require_sonic_boom = __commonJS({
6648
6603
  this.flush = flushBuffer;
6649
6604
  this.flushSync = flushBufferSync;
6650
6605
  this._actualWrite = actualWriteBuffer;
6651
- fsWriteSync = () => fs34.writeSync(this.fd, this._writingBuf);
6652
- fsWrite = () => fs34.write(this.fd, this._writingBuf, this.release);
6606
+ fsWriteSync = () => fs35.writeSync(this.fd, this._writingBuf);
6607
+ fsWrite = () => fs35.write(this.fd, this._writingBuf, this.release);
6653
6608
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6654
6609
  this._writingBuf = "";
6655
6610
  this.write = write;
@@ -6658,15 +6613,15 @@ var require_sonic_boom = __commonJS({
6658
6613
  this._actualWrite = actualWrite;
6659
6614
  fsWriteSync = () => {
6660
6615
  if (Buffer.isBuffer(this._writingBuf)) {
6661
- return fs34.writeSync(this.fd, this._writingBuf);
6616
+ return fs35.writeSync(this.fd, this._writingBuf);
6662
6617
  }
6663
- return fs34.writeSync(this.fd, this._writingBuf, "utf8");
6618
+ return fs35.writeSync(this.fd, this._writingBuf, "utf8");
6664
6619
  };
6665
6620
  fsWrite = () => {
6666
6621
  if (Buffer.isBuffer(this._writingBuf)) {
6667
- return fs34.write(this.fd, this._writingBuf, this.release);
6622
+ return fs35.write(this.fd, this._writingBuf, this.release);
6668
6623
  }
6669
- return fs34.write(this.fd, this._writingBuf, "utf8", this.release);
6624
+ return fs35.write(this.fd, this._writingBuf, "utf8", this.release);
6670
6625
  };
6671
6626
  } else {
6672
6627
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6723,7 +6678,7 @@ var require_sonic_boom = __commonJS({
6723
6678
  }
6724
6679
  }
6725
6680
  if (this._fsync) {
6726
- fs34.fsyncSync(this.fd);
6681
+ fs35.fsyncSync(this.fd);
6727
6682
  }
6728
6683
  const len = this._len;
6729
6684
  if (this._reopening) {
@@ -6837,7 +6792,7 @@ var require_sonic_boom = __commonJS({
6837
6792
  const onDrain = () => {
6838
6793
  if (!this._fsync) {
6839
6794
  try {
6840
- fs34.fsync(this.fd, (err) => {
6795
+ fs35.fsync(this.fd, (err) => {
6841
6796
  this._flushPending = false;
6842
6797
  cb(err);
6843
6798
  });
@@ -6939,7 +6894,7 @@ var require_sonic_boom = __commonJS({
6939
6894
  const fd = this.fd;
6940
6895
  this.once("ready", () => {
6941
6896
  if (fd !== this.fd) {
6942
- fs34.close(fd, (err) => {
6897
+ fs35.close(fd, (err) => {
6943
6898
  if (err) {
6944
6899
  return this.emit("error", err);
6945
6900
  }
@@ -6988,7 +6943,7 @@ var require_sonic_boom = __commonJS({
6988
6943
  buf = this._bufs[0];
6989
6944
  }
6990
6945
  try {
6991
- const n = Buffer.isBuffer(buf) ? fs34.writeSync(this.fd, buf) : fs34.writeSync(this.fd, buf, "utf8");
6946
+ const n = Buffer.isBuffer(buf) ? fs35.writeSync(this.fd, buf) : fs35.writeSync(this.fd, buf, "utf8");
6992
6947
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6993
6948
  buf = releasedBufObj.writingBuf;
6994
6949
  this._len = releasedBufObj.len;
@@ -7004,7 +6959,7 @@ var require_sonic_boom = __commonJS({
7004
6959
  }
7005
6960
  }
7006
6961
  try {
7007
- fs34.fsyncSync(this.fd);
6962
+ fs35.fsyncSync(this.fd);
7008
6963
  } catch {
7009
6964
  }
7010
6965
  }
@@ -7025,7 +6980,7 @@ var require_sonic_boom = __commonJS({
7025
6980
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7026
6981
  }
7027
6982
  try {
7028
- const n = fs34.writeSync(this.fd, buf);
6983
+ const n = fs35.writeSync(this.fd, buf);
7029
6984
  buf = buf.subarray(n);
7030
6985
  this._len = Math.max(this._len - n, 0);
7031
6986
  if (buf.length <= 0) {
@@ -7053,13 +7008,13 @@ var require_sonic_boom = __commonJS({
7053
7008
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7054
7009
  if (this.sync) {
7055
7010
  try {
7056
- const written = Buffer.isBuffer(this._writingBuf) ? fs34.writeSync(this.fd, this._writingBuf) : fs34.writeSync(this.fd, this._writingBuf, "utf8");
7011
+ const written = Buffer.isBuffer(this._writingBuf) ? fs35.writeSync(this.fd, this._writingBuf) : fs35.writeSync(this.fd, this._writingBuf, "utf8");
7057
7012
  release(null, written);
7058
7013
  } catch (err) {
7059
7014
  release(err);
7060
7015
  }
7061
7016
  } else {
7062
- fs34.write(this.fd, this._writingBuf, release);
7017
+ fs35.write(this.fd, this._writingBuf, release);
7063
7018
  }
7064
7019
  }
7065
7020
  function actualWriteBuffer() {
@@ -7068,7 +7023,7 @@ var require_sonic_boom = __commonJS({
7068
7023
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7069
7024
  if (this.sync) {
7070
7025
  try {
7071
- const written = fs34.writeSync(this.fd, this._writingBuf);
7026
+ const written = fs35.writeSync(this.fd, this._writingBuf);
7072
7027
  release(null, written);
7073
7028
  } catch (err) {
7074
7029
  release(err);
@@ -7077,7 +7032,7 @@ var require_sonic_boom = __commonJS({
7077
7032
  if (kCopyBuffer) {
7078
7033
  this._writingBuf = Buffer.from(this._writingBuf);
7079
7034
  }
7080
- fs34.write(this.fd, this._writingBuf, release);
7035
+ fs35.write(this.fd, this._writingBuf, release);
7081
7036
  }
7082
7037
  }
7083
7038
  function actualClose(sonic) {
@@ -7093,12 +7048,12 @@ var require_sonic_boom = __commonJS({
7093
7048
  sonic._lens = [];
7094
7049
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7095
7050
  try {
7096
- fs34.fsync(sonic.fd, closeWrapped);
7051
+ fs35.fsync(sonic.fd, closeWrapped);
7097
7052
  } catch {
7098
7053
  }
7099
7054
  function closeWrapped() {
7100
7055
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7101
- fs34.close(sonic.fd, done);
7056
+ fs35.close(sonic.fd, done);
7102
7057
  } else {
7103
7058
  done();
7104
7059
  }
@@ -9462,7 +9417,7 @@ var require_multistream = __commonJS({
9462
9417
  var require_pino = __commonJS({
9463
9418
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
9464
9419
  "use strict";
9465
- var os16 = require("os");
9420
+ var os17 = require("os");
9466
9421
  var stdSerializers = require_pino_std_serializers();
9467
9422
  var caller = require_caller();
9468
9423
  var redaction = require_redaction();
@@ -9509,7 +9464,7 @@ var require_pino = __commonJS({
9509
9464
  } = symbols;
9510
9465
  var { epochTime, nullTime } = time;
9511
9466
  var { pid } = process;
9512
- var hostname = os16.hostname();
9467
+ var hostname = os17.hostname();
9513
9468
  var defaultErrorSerializer = stdSerializers.err;
9514
9469
  var defaultOptions = {
9515
9470
  level: "info",
@@ -10233,11 +10188,11 @@ var init_lib = __esm({
10233
10188
  }
10234
10189
  }
10235
10190
  },
10236
- addToPath: function addToPath(path43, added, removed, oldPosInc, options) {
10237
- var last = path43.lastComponent;
10191
+ addToPath: function addToPath(path44, added, removed, oldPosInc, options) {
10192
+ var last = path44.lastComponent;
10238
10193
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10239
10194
  return {
10240
- oldPos: path43.oldPos + oldPosInc,
10195
+ oldPos: path44.oldPos + oldPosInc,
10241
10196
  lastComponent: {
10242
10197
  count: last.count + 1,
10243
10198
  added,
@@ -10247,7 +10202,7 @@ var init_lib = __esm({
10247
10202
  };
10248
10203
  } else {
10249
10204
  return {
10250
- oldPos: path43.oldPos + oldPosInc,
10205
+ oldPos: path44.oldPos + oldPosInc,
10251
10206
  lastComponent: {
10252
10207
  count: 1,
10253
10208
  added,
@@ -10678,10 +10633,10 @@ function attachmentToHistoryMessage(o, ts) {
10678
10633
  const memories = raw.map((m2) => {
10679
10634
  if (!m2 || typeof m2 !== "object") return null;
10680
10635
  const rec = m2;
10681
- const path43 = typeof rec.path === "string" ? rec.path : null;
10636
+ const path44 = typeof rec.path === "string" ? rec.path : null;
10682
10637
  const content = typeof rec.content === "string" ? rec.content : null;
10683
- if (!path43 || content == null) return null;
10684
- const entry = { path: path43, content };
10638
+ if (!path44 || content == null) return null;
10639
+ const entry = { path: path44, content };
10685
10640
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10686
10641
  return entry;
10687
10642
  }).filter((m2) => m2 !== null);
@@ -11507,10 +11462,10 @@ function parseAttachment(obj) {
11507
11462
  const memories = raw.map((m2) => {
11508
11463
  if (!m2 || typeof m2 !== "object") return null;
11509
11464
  const rec = m2;
11510
- const path43 = typeof rec.path === "string" ? rec.path : null;
11465
+ const path44 = typeof rec.path === "string" ? rec.path : null;
11511
11466
  const content = typeof rec.content === "string" ? rec.content : null;
11512
- if (!path43 || content == null) return null;
11513
- const out = { path: path43, content };
11467
+ if (!path44 || content == null) return null;
11468
+ const out = { path: path44, content };
11514
11469
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11515
11470
  return out;
11516
11471
  }).filter((m2) => m2 !== null);
@@ -20425,7 +20380,7 @@ var require_websocket_server = __commonJS({
20425
20380
  // src/run-case/recorder.ts
20426
20381
  function startRunCaseRecorder(opts) {
20427
20382
  const now = opts.now ?? Date.now;
20428
- const dir = import_node_path29.default.dirname(opts.recordPath);
20383
+ const dir = import_node_path30.default.dirname(opts.recordPath);
20429
20384
  let stream = null;
20430
20385
  let closing = false;
20431
20386
  let closedSettled = false;
@@ -20439,8 +20394,8 @@ function startRunCaseRecorder(opts) {
20439
20394
  });
20440
20395
  const ensureStream = () => {
20441
20396
  if (stream) return stream;
20442
- import_node_fs26.default.mkdirSync(dir, { recursive: true });
20443
- stream = import_node_fs26.default.createWriteStream(opts.recordPath, { flags: "a" });
20397
+ import_node_fs27.default.mkdirSync(dir, { recursive: true });
20398
+ stream = import_node_fs27.default.createWriteStream(opts.recordPath, { flags: "a" });
20444
20399
  stream.on("close", () => closedResolve());
20445
20400
  return stream;
20446
20401
  };
@@ -20465,12 +20420,12 @@ function startRunCaseRecorder(opts) {
20465
20420
  };
20466
20421
  return { tap, close, closed };
20467
20422
  }
20468
- var import_node_fs26, import_node_path29;
20423
+ var import_node_fs27, import_node_path30;
20469
20424
  var init_recorder = __esm({
20470
20425
  "src/run-case/recorder.ts"() {
20471
20426
  "use strict";
20472
- import_node_fs26 = __toESM(require("fs"), 1);
20473
- import_node_path29 = __toESM(require("path"), 1);
20427
+ import_node_fs27 = __toESM(require("fs"), 1);
20428
+ import_node_path30 = __toESM(require("path"), 1);
20474
20429
  }
20475
20430
  });
20476
20431
 
@@ -20513,7 +20468,7 @@ var init_wire = __esm({
20513
20468
  // src/run-case/controller.ts
20514
20469
  async function runController(opts) {
20515
20470
  const now = opts.now ?? Date.now;
20516
- const cwd = opts.cwd ?? (0, import_node_fs27.mkdtempSync)(import_node_path30.default.join(import_node_os14.default.tmpdir(), "clawd-runcase-"));
20471
+ const cwd = opts.cwd ?? (0, import_node_fs28.mkdtempSync)(import_node_path31.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
20517
20472
  const ownsCwd = opts.cwd === void 0;
20518
20473
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
20519
20474
  const spawnCtx = { cwd };
@@ -20674,19 +20629,19 @@ async function runController(opts) {
20674
20629
  if (sigintHandler) process.off("SIGINT", sigintHandler);
20675
20630
  if (ownsCwd) {
20676
20631
  try {
20677
- (0, import_node_fs27.rmSync)(cwd, { recursive: true, force: true });
20632
+ (0, import_node_fs28.rmSync)(cwd, { recursive: true, force: true });
20678
20633
  } catch {
20679
20634
  }
20680
20635
  }
20681
20636
  return exitCode ?? 0;
20682
20637
  }
20683
- var import_node_fs27, import_node_os14, import_node_path30;
20638
+ var import_node_fs28, import_node_os15, import_node_path31;
20684
20639
  var init_controller = __esm({
20685
20640
  "src/run-case/controller.ts"() {
20686
20641
  "use strict";
20687
- import_node_fs27 = require("fs");
20688
- import_node_os14 = __toESM(require("os"), 1);
20689
- import_node_path30 = __toESM(require("path"), 1);
20642
+ import_node_fs28 = require("fs");
20643
+ import_node_os15 = __toESM(require("os"), 1);
20644
+ import_node_path31 = __toESM(require("path"), 1);
20690
20645
  init_claude();
20691
20646
  init_stdout_splitter();
20692
20647
  init_permission_stdio();
@@ -20918,8 +20873,8 @@ Env (advanced):
20918
20873
  `;
20919
20874
 
20920
20875
  // src/index.ts
20921
- var import_node_path28 = __toESM(require("path"), 1);
20922
- var import_node_fs25 = __toESM(require("fs"), 1);
20876
+ var import_node_path29 = __toESM(require("path"), 1);
20877
+ var import_node_fs26 = __toESM(require("fs"), 1);
20923
20878
 
20924
20879
  // src/logger.ts
20925
20880
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -22907,25 +22862,6 @@ var SessionManager = class {
22907
22862
  const file = this.getFile(args.sessionId);
22908
22863
  return { response: file, broadcast: [] };
22909
22864
  }
22910
- // mirror peer sessions (2026-05-26):把来自朋友 daemon 的 SessionFile(originOwnerPrincipalId
22911
- // 非空)持久化到本机 default store。dumb write,**不广播 push 帧**——UI 是写入唯一源,
22912
- // 双写完成后通过 cache.setData 同步 sidebar 本地 state。
22913
- //
22914
- // 强制走 deps.store(即 default scope),不走 scopeForFile:即使 mirror SessionFile 带
22915
- // 远端 ownerPersonaId(远端 persona session),本机也落 default,不创建本机 persona 目录。
22916
- // 远端 creator / origin 字段原值保留(不被本机 ctx 派生覆写)。
22917
- //
22918
- // 与 manager.create / manager.update 区别:
22919
- // - 不走 newRunner / attachObserver / cwd 校验(mirror 是纯 metadata 层)
22920
- // - 不发 session:info 帧(manager.create / .update 通过 reducer/wireCollector 发 push)
22921
- mirrorUpsert(file) {
22922
- return this.deps.store.write(file);
22923
- }
22924
- // mirror peer sessions:删本机 mirror SessionFile。强制 default store。
22925
- // idempotent:找不到不 throw(UI 反复点删容错)。**不广播 session:deleted**。
22926
- mirrorRemove(sessionId) {
22927
- this.deps.store.delete(sessionId);
22928
- }
22929
22865
  // observer 上报"jsonl 写入了一条 user 行"时调用:在 buffer 里找到与之对应的、
22930
22866
  // 还没建立映射的最早一条 synth user_text,记下 synth → real 映射。
22931
22867
  // 找不到匹配的 synth(runner 不存在 / buffer 已被 /clear 清空 / 真 uuid 来自纯 history
@@ -25573,11 +25509,18 @@ var AgentsScanner = class {
25573
25509
  };
25574
25510
 
25575
25511
  // src/observer/session-observer.ts
25512
+ var import_node_fs13 = __toESM(require("fs"), 1);
25513
+ var import_node_os9 = __toESM(require("os"), 1);
25514
+ var import_node_path14 = __toESM(require("path"), 1);
25515
+ init_claude_history();
25516
+
25517
+ // src/observer/subagent-meta-observer.ts
25576
25518
  var import_node_fs12 = __toESM(require("fs"), 1);
25577
25519
  var import_node_os8 = __toESM(require("os"), 1);
25578
25520
  var import_node_path13 = __toESM(require("path"), 1);
25579
25521
  init_claude_history();
25580
- var SessionObserver = class {
25522
+ var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
25523
+ var SubagentMetaObserver = class {
25581
25524
  constructor(opts) {
25582
25525
  this.opts = opts;
25583
25526
  this.home = opts.home ?? import_node_os8.default.homedir();
@@ -25585,16 +25528,132 @@ var SessionObserver = class {
25585
25528
  opts;
25586
25529
  home;
25587
25530
  watches = /* @__PURE__ */ new Map();
25531
+ // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
25532
+ resolveSubagentDir(cwd, toolSessionId) {
25533
+ return import_node_path13.default.join(
25534
+ this.home,
25535
+ ".claude",
25536
+ "projects",
25537
+ cwdToHashDir(cwd),
25538
+ toolSessionId,
25539
+ "subagents"
25540
+ );
25541
+ }
25542
+ start(args) {
25543
+ this.stop(args.sessionId);
25544
+ const dirPath = this.resolveSubagentDir(args.cwd, args.toolSessionId);
25545
+ const w2 = {
25546
+ sessionId: args.sessionId,
25547
+ dirPath,
25548
+ watcher: null,
25549
+ pollTimer: null,
25550
+ emitted: /* @__PURE__ */ new Set()
25551
+ };
25552
+ this.watches.set(args.sessionId, w2);
25553
+ this.scan(w2);
25554
+ this.attachWatcher(w2);
25555
+ w2.pollTimer = setInterval(() => this.scan(w2), 200);
25556
+ return { dirPath };
25557
+ }
25558
+ // fs.watch 必须在目录存在后调用;首次启动时 subagents/ 通常不存在 —— attachWatcher
25559
+ // 失败就交给 pollTimer 200ms 兜底,目录一出现就被下次 poll 捡起来,那时也尝试 attach
25560
+ attachWatcher(w2) {
25561
+ if (w2.watcher) return;
25562
+ try {
25563
+ w2.watcher = import_node_fs12.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
25564
+ if (!name) return;
25565
+ const m2 = META_RE.exec(String(name));
25566
+ if (!m2) return;
25567
+ this.scanOne(w2, String(name));
25568
+ });
25569
+ } catch {
25570
+ }
25571
+ }
25572
+ scan(w2) {
25573
+ let entries;
25574
+ try {
25575
+ entries = import_node_fs12.default.readdirSync(w2.dirPath);
25576
+ } catch {
25577
+ return;
25578
+ }
25579
+ if (!w2.watcher) this.attachWatcher(w2);
25580
+ for (const name of entries) {
25581
+ this.scanOne(w2, name);
25582
+ }
25583
+ }
25584
+ scanOne(w2, name) {
25585
+ const m2 = META_RE.exec(name);
25586
+ if (!m2) return;
25587
+ const agentId = m2[1];
25588
+ if (w2.emitted.has(agentId)) return;
25589
+ const file = import_node_path13.default.join(w2.dirPath, name);
25590
+ let raw;
25591
+ try {
25592
+ raw = import_node_fs12.default.readFileSync(file, "utf8");
25593
+ } catch {
25594
+ return;
25595
+ }
25596
+ let obj;
25597
+ try {
25598
+ obj = JSON.parse(raw);
25599
+ } catch {
25600
+ return;
25601
+ }
25602
+ const toolUseId = typeof obj.toolUseId === "string" ? obj.toolUseId : "";
25603
+ if (!toolUseId) return;
25604
+ w2.emitted.add(agentId);
25605
+ const ev = {
25606
+ kind: "subagent_progress",
25607
+ toolUseId,
25608
+ agentId,
25609
+ status: "started"
25610
+ };
25611
+ if (typeof obj.description === "string" && obj.description) ev.description = obj.description;
25612
+ this.opts.onEvent({ sessionId: w2.sessionId, events: [ev] });
25613
+ }
25614
+ isObserving(sessionId) {
25615
+ return this.watches.has(sessionId);
25616
+ }
25617
+ stop(sessionId) {
25618
+ const w2 = this.watches.get(sessionId);
25619
+ if (!w2) return false;
25620
+ try {
25621
+ w2.watcher?.close();
25622
+ } catch {
25623
+ }
25624
+ if (w2.pollTimer) clearInterval(w2.pollTimer);
25625
+ this.watches.delete(sessionId);
25626
+ return true;
25627
+ }
25628
+ stopAll() {
25629
+ for (const id of [...this.watches.keys()]) this.stop(id);
25630
+ }
25631
+ };
25632
+
25633
+ // src/observer/session-observer.ts
25634
+ var SessionObserver = class {
25635
+ constructor(opts) {
25636
+ this.opts = opts;
25637
+ this.home = opts.home ?? import_node_os9.default.homedir();
25638
+ this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
25639
+ }
25640
+ opts;
25641
+ home;
25642
+ watches = /* @__PURE__ */ new Map();
25643
+ // 子 observer:监听 <projectsRoot>/<hashDir>/<toolSessionId>/subagents/ 目录的 meta.json,
25644
+ // 仅 TUI 模式启用——SDK 模式靠 `system.task_started` 帧(claude.ts:466)emit subagent_progress
25645
+ // 已经能解锁 AgentCallLine 抽屉入口,再跑 meta watcher 会让 ring buffer 留双帧
25646
+ metaObserver;
25588
25647
  resolveJsonlPath(cwd, toolSessionId, override) {
25589
25648
  if (override) return override;
25590
- return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
25649
+ return import_node_path14.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
25591
25650
  }
25592
25651
  start(args) {
25593
25652
  this.stop(args.sessionId);
25594
25653
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
25595
25654
  let size = 0;
25596
25655
  try {
25597
- size = import_node_fs12.default.statSync(filePath).size;
25656
+ size = import_node_fs13.default.statSync(filePath).size;
25598
25657
  } catch {
25599
25658
  }
25600
25659
  const w2 = {
@@ -25607,10 +25666,10 @@ var SessionObserver = class {
25607
25666
  adapter: args.adapter
25608
25667
  };
25609
25668
  try {
25610
- import_node_fs12.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
25669
+ import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
25611
25670
  } catch {
25612
25671
  }
25613
- w2.watcher = import_node_fs12.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
25672
+ w2.watcher = import_node_fs13.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
25614
25673
  if (!changedName || !filePath.endsWith(changedName)) return;
25615
25674
  this.poll(w2);
25616
25675
  });
@@ -25619,6 +25678,11 @@ var SessionObserver = class {
25619
25678
  this.opts.onStatus?.(args.sessionId, "observing");
25620
25679
  this.hydrateMetaTail(w2);
25621
25680
  this.poll(w2);
25681
+ this.metaObserver?.start({
25682
+ sessionId: args.sessionId,
25683
+ cwd: args.cwd,
25684
+ toolSessionId: args.toolSessionId
25685
+ });
25622
25686
  return { filePath };
25623
25687
  }
25624
25688
  // 读 JSONL 文件尾部 N 行,把每行的 meta_update 字段**合并成一个 patch** 喂给 reducer。
@@ -25628,7 +25692,7 @@ var SessionObserver = class {
25628
25692
  // 异常静默吞,不阻塞 watcher 启动
25629
25693
  hydrateMetaTail(w2, maxLines = 200) {
25630
25694
  try {
25631
- const raw = import_node_fs12.default.readFileSync(w2.filePath, "utf8");
25695
+ const raw = import_node_fs13.default.readFileSync(w2.filePath, "utf8");
25632
25696
  if (!raw) return;
25633
25697
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
25634
25698
  if (allLines.length === 0) return;
@@ -25652,7 +25716,7 @@ var SessionObserver = class {
25652
25716
  poll(w2) {
25653
25717
  let size = 0;
25654
25718
  try {
25655
- size = import_node_fs12.default.statSync(w2.filePath).size;
25719
+ size = import_node_fs13.default.statSync(w2.filePath).size;
25656
25720
  } catch {
25657
25721
  return;
25658
25722
  }
@@ -25661,11 +25725,11 @@ var SessionObserver = class {
25661
25725
  w2.buf = "";
25662
25726
  }
25663
25727
  if (size === w2.lastSize) return;
25664
- const fd = import_node_fs12.default.openSync(w2.filePath, "r");
25728
+ const fd = import_node_fs13.default.openSync(w2.filePath, "r");
25665
25729
  try {
25666
25730
  const len = size - w2.lastSize;
25667
25731
  const buf = Buffer.alloc(len);
25668
- import_node_fs12.default.readSync(fd, buf, 0, len, w2.lastSize);
25732
+ import_node_fs13.default.readSync(fd, buf, 0, len, w2.lastSize);
25669
25733
  w2.lastSize = size;
25670
25734
  w2.buf += buf.toString("utf8");
25671
25735
  let newlineIndex;
@@ -25679,7 +25743,7 @@ var SessionObserver = class {
25679
25743
  }
25680
25744
  }
25681
25745
  } finally {
25682
- import_node_fs12.default.closeSync(fd);
25746
+ import_node_fs13.default.closeSync(fd);
25683
25747
  }
25684
25748
  }
25685
25749
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -25732,11 +25796,13 @@ var SessionObserver = class {
25732
25796
  }
25733
25797
  if (w2.pollTimer) clearInterval(w2.pollTimer);
25734
25798
  this.watches.delete(sessionId);
25799
+ this.metaObserver?.stop(sessionId);
25735
25800
  this.opts.onStatus?.(sessionId, "stopped");
25736
25801
  return true;
25737
25802
  }
25738
25803
  stopAll() {
25739
25804
  for (const id of [...this.watches.keys()]) this.stop(id);
25805
+ this.metaObserver?.stopAll();
25740
25806
  }
25741
25807
  };
25742
25808
 
@@ -26337,14 +26403,14 @@ function authenticate(token, deps) {
26337
26403
  }
26338
26404
 
26339
26405
  // src/permission/capability-store.ts
26340
- var fs15 = __toESM(require("fs"), 1);
26341
- var path18 = __toESM(require("path"), 1);
26406
+ var fs16 = __toESM(require("fs"), 1);
26407
+ var path19 = __toESM(require("path"), 1);
26342
26408
  var CAPABILITIES_FILE_NAME = "capabilities.json";
26343
26409
  var FILE_VERSION = 1;
26344
26410
  var CapabilityStore = class {
26345
26411
  constructor(dataDir) {
26346
26412
  this.dataDir = dataDir;
26347
- fs15.mkdirSync(dataDir, { recursive: true });
26413
+ fs16.mkdirSync(dataDir, { recursive: true });
26348
26414
  this.cache = this.readFromDisk();
26349
26415
  }
26350
26416
  dataDir;
@@ -26368,13 +26434,13 @@ var CapabilityStore = class {
26368
26434
  this.flush();
26369
26435
  }
26370
26436
  filePath() {
26371
- return path18.join(this.dataDir, CAPABILITIES_FILE_NAME);
26437
+ return path19.join(this.dataDir, CAPABILITIES_FILE_NAME);
26372
26438
  }
26373
26439
  readFromDisk() {
26374
26440
  const file = this.filePath();
26375
26441
  let raw;
26376
26442
  try {
26377
- raw = fs15.readFileSync(file, "utf8");
26443
+ raw = fs16.readFileSync(file, "utf8");
26378
26444
  } catch (err) {
26379
26445
  if (err?.code === "ENOENT") return [];
26380
26446
  return [];
@@ -26402,10 +26468,10 @@ var CapabilityStore = class {
26402
26468
  }
26403
26469
  atomicWrite(file, content) {
26404
26470
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26405
- fs15.writeFileSync(tmp, content, { mode: 384 });
26406
- fs15.renameSync(tmp, file);
26471
+ fs16.writeFileSync(tmp, content, { mode: 384 });
26472
+ fs16.renameSync(tmp, file);
26407
26473
  try {
26408
- fs15.chmodSync(file, 384);
26474
+ fs16.chmodSync(file, 384);
26409
26475
  } catch {
26410
26476
  }
26411
26477
  }
@@ -26498,14 +26564,14 @@ var CapabilityManager = class {
26498
26564
  };
26499
26565
 
26500
26566
  // src/permission/cleanup.ts
26501
- var fs16 = __toESM(require("fs"), 1);
26567
+ var fs17 = __toESM(require("fs"), 1);
26502
26568
  function cleanupGuestSessionsForCapability(cap, factory) {
26503
26569
  const removed = [];
26504
26570
  for (const g2 of cap.grants) {
26505
26571
  if (g2.resource.type !== "persona") continue;
26506
26572
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
26507
26573
  try {
26508
- fs16.rmSync(dir, { recursive: true, force: true });
26574
+ fs17.rmSync(dir, { recursive: true, force: true });
26509
26575
  removed.push(dir);
26510
26576
  } catch {
26511
26577
  }
@@ -26514,13 +26580,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
26514
26580
  }
26515
26581
 
26516
26582
  // src/permission/personal-capability.ts
26517
- var import_node_fs13 = __toESM(require("fs"), 1);
26518
- var import_node_path14 = __toESM(require("path"), 1);
26583
+ var import_node_fs14 = __toESM(require("fs"), 1);
26584
+ var import_node_path15 = __toESM(require("path"), 1);
26519
26585
  var import_node_crypto4 = __toESM(require("crypto"), 1);
26520
26586
  var PERSONAL_CAP_FILE_NAME = "personal-capability.json";
26521
26587
  var PERSONAL_CAP_DISPLAY_NAME = "personal";
26522
26588
  function personalCapFilePath(dataDir) {
26523
- return import_node_path14.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
26589
+ return import_node_path15.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
26524
26590
  }
26525
26591
  function loadOrCreatePersonalCapability(opts) {
26526
26592
  const file = personalCapFilePath(opts.dataDir);
@@ -26550,7 +26616,7 @@ function loadOrCreatePersonalCapability(opts) {
26550
26616
  function readFile(file) {
26551
26617
  let raw;
26552
26618
  try {
26553
- raw = import_node_fs13.default.readFileSync(file, "utf8");
26619
+ raw = import_node_fs14.default.readFileSync(file, "utf8");
26554
26620
  } catch (err) {
26555
26621
  const code = err?.code;
26556
26622
  if (code === "ENOENT") return null;
@@ -26571,10 +26637,10 @@ function readFile(file) {
26571
26637
  return { token: obj.token, capability: capParsed.data };
26572
26638
  }
26573
26639
  function writeFile(file, content) {
26574
- import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
26575
- import_node_fs13.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
26640
+ import_node_fs14.default.mkdirSync(import_node_path15.default.dirname(file), { recursive: true });
26641
+ import_node_fs14.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
26576
26642
  try {
26577
- import_node_fs13.default.chmodSync(file, 384);
26643
+ import_node_fs14.default.chmodSync(file, 384);
26578
26644
  } catch {
26579
26645
  }
26580
26646
  }
@@ -26589,13 +26655,13 @@ function sha256Hex2(s) {
26589
26655
  }
26590
26656
 
26591
26657
  // src/inbox/inbox-store.ts
26592
- var fs18 = __toESM(require("fs"), 1);
26593
- var path20 = __toESM(require("path"), 1);
26658
+ var fs19 = __toESM(require("fs"), 1);
26659
+ var path21 = __toESM(require("path"), 1);
26594
26660
  var INBOX_SUBDIR = "inbox";
26595
26661
  var InboxStore = class {
26596
26662
  constructor(dataDir) {
26597
26663
  this.dataDir = dataDir;
26598
- fs18.mkdirSync(this.dirPath(), { recursive: true });
26664
+ fs19.mkdirSync(this.dirPath(), { recursive: true });
26599
26665
  }
26600
26666
  dataDir;
26601
26667
  /**
@@ -26607,7 +26673,7 @@ var InboxStore = class {
26607
26673
  const file = this.filePath(peerOwnerId);
26608
26674
  let raw;
26609
26675
  try {
26610
- raw = fs18.readFileSync(file, "utf8");
26676
+ raw = fs19.readFileSync(file, "utf8");
26611
26677
  } catch (err) {
26612
26678
  if (err?.code === "ENOENT") return [];
26613
26679
  return [];
@@ -26623,7 +26689,7 @@ var InboxStore = class {
26623
26689
  const dir = this.dirPath();
26624
26690
  let entries;
26625
26691
  try {
26626
- entries = fs18.readdirSync(dir);
26692
+ entries = fs19.readdirSync(dir);
26627
26693
  } catch (err) {
26628
26694
  if (err?.code === "ENOENT") return [];
26629
26695
  return [];
@@ -26639,9 +26705,9 @@ var InboxStore = class {
26639
26705
  if (existing.some((m2) => m2.id === message.id)) return;
26640
26706
  const file = this.filePath(message.peerOwnerId);
26641
26707
  const line = JSON.stringify(message) + "\n";
26642
- fs18.appendFileSync(file, line, { mode: 384 });
26708
+ fs19.appendFileSync(file, line, { mode: 384 });
26643
26709
  try {
26644
- fs18.chmodSync(file, 384);
26710
+ fs19.chmodSync(file, 384);
26645
26711
  } catch {
26646
26712
  }
26647
26713
  }
@@ -26671,7 +26737,7 @@ var InboxStore = class {
26671
26737
  removeByPeerOwnerId(peerOwnerId) {
26672
26738
  const file = this.filePath(peerOwnerId);
26673
26739
  try {
26674
- fs18.unlinkSync(file);
26740
+ fs19.unlinkSync(file);
26675
26741
  } catch (err) {
26676
26742
  if (err?.code === "ENOENT") return;
26677
26743
  }
@@ -26680,18 +26746,18 @@ var InboxStore = class {
26680
26746
  const file = this.filePath(peerOwnerId);
26681
26747
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26682
26748
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
26683
- fs18.writeFileSync(tmp, content, { mode: 384 });
26684
- fs18.renameSync(tmp, file);
26749
+ fs19.writeFileSync(tmp, content, { mode: 384 });
26750
+ fs19.renameSync(tmp, file);
26685
26751
  try {
26686
- fs18.chmodSync(file, 384);
26752
+ fs19.chmodSync(file, 384);
26687
26753
  } catch {
26688
26754
  }
26689
26755
  }
26690
26756
  dirPath() {
26691
- return path20.join(this.dataDir, INBOX_SUBDIR);
26757
+ return path21.join(this.dataDir, INBOX_SUBDIR);
26692
26758
  }
26693
26759
  filePath(peerOwnerId) {
26694
- return path20.join(this.dirPath(), `${peerOwnerId}.jsonl`);
26760
+ return path21.join(this.dirPath(), `${peerOwnerId}.jsonl`);
26695
26761
  }
26696
26762
  };
26697
26763
  function parseAllLines(raw) {
@@ -26778,8 +26844,8 @@ var InboxManager = class {
26778
26844
  };
26779
26845
 
26780
26846
  // src/state/received-capability-store.ts
26781
- var fs19 = __toESM(require("fs"), 1);
26782
- var path21 = __toESM(require("path"), 1);
26847
+ var fs20 = __toESM(require("fs"), 1);
26848
+ var path22 = __toESM(require("path"), 1);
26783
26849
  var FILE_NAME = "received-capabilities.json";
26784
26850
  var ReceivedCapabilityStore = class {
26785
26851
  constructor(dataDir) {
@@ -26789,10 +26855,10 @@ var ReceivedCapabilityStore = class {
26789
26855
  caps = /* @__PURE__ */ new Map();
26790
26856
  load() {
26791
26857
  this.caps.clear();
26792
- const file = path21.join(this.dataDir, FILE_NAME);
26858
+ const file = path22.join(this.dataDir, FILE_NAME);
26793
26859
  let raw;
26794
26860
  try {
26795
- raw = fs19.readFileSync(file, "utf8");
26861
+ raw = fs20.readFileSync(file, "utf8");
26796
26862
  } catch (err) {
26797
26863
  if (err?.code !== "ENOENT") this.renameBak(file);
26798
26864
  return;
@@ -26829,20 +26895,20 @@ var ReceivedCapabilityStore = class {
26829
26895
  this.flush();
26830
26896
  }
26831
26897
  flush() {
26832
- const file = path21.join(this.dataDir, FILE_NAME);
26898
+ const file = path22.join(this.dataDir, FILE_NAME);
26833
26899
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
26834
26900
  const content = JSON.stringify(
26835
26901
  { receivedCaps: Array.from(this.caps.values()) },
26836
26902
  null,
26837
26903
  2
26838
26904
  );
26839
- fs19.mkdirSync(this.dataDir, { recursive: true });
26840
- fs19.writeFileSync(tmp, content, { mode: 384 });
26841
- fs19.renameSync(tmp, file);
26905
+ fs20.mkdirSync(this.dataDir, { recursive: true });
26906
+ fs20.writeFileSync(tmp, content, { mode: 384 });
26907
+ fs20.renameSync(tmp, file);
26842
26908
  }
26843
26909
  renameBak(file) {
26844
26910
  try {
26845
- fs19.renameSync(file, `${file}.bak`);
26911
+ fs20.renameSync(file, `${file}.bak`);
26846
26912
  } catch {
26847
26913
  }
26848
26914
  }
@@ -26940,61 +27006,61 @@ async function connectRemote(args) {
26940
27006
  }
26941
27007
 
26942
27008
  // src/migrations/2026-05-20-flatten-sessions.ts
26943
- var fs20 = __toESM(require("fs"), 1);
26944
- var path22 = __toESM(require("path"), 1);
27009
+ var fs21 = __toESM(require("fs"), 1);
27010
+ var path23 = __toESM(require("path"), 1);
26945
27011
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
26946
27012
  function migrateFlattenSessions(opts) {
26947
27013
  const dataDir = opts.dataDir;
26948
27014
  const now = opts.now ?? Date.now;
26949
- const sessionsDir = path22.join(dataDir, "sessions");
26950
- const flagPath = path22.join(sessionsDir, MIGRATION_FLAG_NAME);
27015
+ const sessionsDir = path23.join(dataDir, "sessions");
27016
+ const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
26951
27017
  if (existsSync3(flagPath)) {
26952
27018
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
26953
27019
  }
26954
27020
  let movedBare = 0;
26955
27021
  let movedVmOwner = 0;
26956
27022
  let archivedListener = 0;
26957
- const defaultDir = path22.join(sessionsDir, "default");
27023
+ const defaultDir = path23.join(sessionsDir, "default");
26958
27024
  if (existsSync3(defaultDir)) {
26959
27025
  for (const entry of readdirSafe(defaultDir)) {
26960
27026
  if (!entry.endsWith(".json")) continue;
26961
- const src = path22.join(defaultDir, entry);
26962
- const dst = path22.join(sessionsDir, entry);
26963
- fs20.renameSync(src, dst);
27027
+ const src = path23.join(defaultDir, entry);
27028
+ const dst = path23.join(sessionsDir, entry);
27029
+ fs21.renameSync(src, dst);
26964
27030
  movedBare += 1;
26965
27031
  }
26966
27032
  rmdirIfEmpty(defaultDir);
26967
27033
  }
26968
27034
  for (const pid of readdirSafe(sessionsDir)) {
26969
- const personaDir = path22.join(sessionsDir, pid);
27035
+ const personaDir = path23.join(sessionsDir, pid);
26970
27036
  if (!isDir(personaDir)) continue;
26971
27037
  if (pid === "default") continue;
26972
- const ownerSrc = path22.join(personaDir, "owner");
27038
+ const ownerSrc = path23.join(personaDir, "owner");
26973
27039
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
26974
- const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26975
- fs20.mkdirSync(ownerDst, { recursive: true });
27040
+ const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
27041
+ fs21.mkdirSync(ownerDst, { recursive: true });
26976
27042
  for (const file of readdirSafe(ownerSrc)) {
26977
27043
  if (!file.endsWith(".json")) continue;
26978
- fs20.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
27044
+ fs21.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
26979
27045
  movedVmOwner += 1;
26980
27046
  }
26981
27047
  rmdirIfEmpty(ownerSrc);
26982
27048
  }
26983
- const listenerSrc = path22.join(personaDir, "listener");
27049
+ const listenerSrc = path23.join(personaDir, "listener");
26984
27050
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
26985
- const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
26986
- fs20.mkdirSync(archiveDst, { recursive: true });
27051
+ const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
27052
+ fs21.mkdirSync(archiveDst, { recursive: true });
26987
27053
  for (const file of readdirSafe(listenerSrc)) {
26988
27054
  if (!file.endsWith(".json")) continue;
26989
- fs20.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
27055
+ fs21.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
26990
27056
  archivedListener += 1;
26991
27057
  }
26992
27058
  rmdirIfEmpty(listenerSrc);
26993
27059
  }
26994
27060
  rmdirIfEmpty(personaDir);
26995
27061
  }
26996
- fs20.mkdirSync(sessionsDir, { recursive: true });
26997
- fs20.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
27062
+ fs21.mkdirSync(sessionsDir, { recursive: true });
27063
+ fs21.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26998
27064
  return {
26999
27065
  skipped: false,
27000
27066
  flagWritten: true,
@@ -27005,7 +27071,7 @@ function migrateFlattenSessions(opts) {
27005
27071
  }
27006
27072
  function existsSync3(p2) {
27007
27073
  try {
27008
- fs20.statSync(p2);
27074
+ fs21.statSync(p2);
27009
27075
  return true;
27010
27076
  } catch {
27011
27077
  return false;
@@ -27013,31 +27079,31 @@ function existsSync3(p2) {
27013
27079
  }
27014
27080
  function isDir(p2) {
27015
27081
  try {
27016
- return fs20.statSync(p2).isDirectory();
27082
+ return fs21.statSync(p2).isDirectory();
27017
27083
  } catch {
27018
27084
  return false;
27019
27085
  }
27020
27086
  }
27021
27087
  function readdirSafe(p2) {
27022
27088
  try {
27023
- return fs20.readdirSync(p2);
27089
+ return fs21.readdirSync(p2);
27024
27090
  } catch {
27025
27091
  return [];
27026
27092
  }
27027
27093
  }
27028
27094
  function rmdirIfEmpty(p2) {
27029
27095
  try {
27030
- fs20.rmdirSync(p2);
27096
+ fs21.rmdirSync(p2);
27031
27097
  } catch {
27032
27098
  }
27033
27099
  }
27034
27100
 
27035
27101
  // src/transport/http-router.ts
27036
- var import_node_fs14 = __toESM(require("fs"), 1);
27037
- var import_node_path16 = __toESM(require("path"), 1);
27102
+ var import_node_fs15 = __toESM(require("fs"), 1);
27103
+ var import_node_path17 = __toESM(require("path"), 1);
27038
27104
 
27039
27105
  // src/attachment/mime.ts
27040
- var import_node_path15 = __toESM(require("path"), 1);
27106
+ var import_node_path16 = __toESM(require("path"), 1);
27041
27107
  var TEXT_PLAIN = "text/plain; charset=utf-8";
27042
27108
  var EXT_TO_NATIVE_MIME = {
27043
27109
  // 图片
@@ -27144,7 +27210,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
27144
27210
  ".mk"
27145
27211
  ]);
27146
27212
  function lookupMime(filePathOrName) {
27147
- const ext = import_node_path15.default.extname(filePathOrName).toLowerCase();
27213
+ const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
27148
27214
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
27149
27215
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
27150
27216
  return "application/octet-stream";
@@ -27275,7 +27341,7 @@ function createHttpRouter(deps) {
27275
27341
  return true;
27276
27342
  }
27277
27343
  let absPath;
27278
- if (import_node_path16.default.isAbsolute(pathParam)) {
27344
+ if (import_node_path17.default.isAbsolute(pathParam)) {
27279
27345
  absPath = pathParam;
27280
27346
  } else if (deps.sessionStore) {
27281
27347
  const file = deps.sessionStore.read(sid);
@@ -27283,7 +27349,7 @@ function createHttpRouter(deps) {
27283
27349
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
27284
27350
  return true;
27285
27351
  }
27286
- absPath = import_node_path16.default.join(file.cwd, pathParam);
27352
+ absPath = import_node_path17.default.join(file.cwd, pathParam);
27287
27353
  } else {
27288
27354
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
27289
27355
  return true;
@@ -27316,7 +27382,7 @@ function withCtx(ctx, body) {
27316
27382
  function streamFile(res, absPath, logger) {
27317
27383
  let stat;
27318
27384
  try {
27319
- stat = import_node_fs14.default.statSync(absPath);
27385
+ stat = import_node_fs15.default.statSync(absPath);
27320
27386
  } catch (err) {
27321
27387
  const code = err?.code;
27322
27388
  if (code === "ENOENT") {
@@ -27331,7 +27397,7 @@ function streamFile(res, absPath, logger) {
27331
27397
  return;
27332
27398
  }
27333
27399
  const mime = lookupMime(absPath);
27334
- const basename = import_node_path16.default.basename(absPath);
27400
+ const basename = import_node_path17.default.basename(absPath);
27335
27401
  res.writeHead(200, {
27336
27402
  "Content-Type": mime,
27337
27403
  "Content-Length": String(stat.size),
@@ -27339,7 +27405,7 @@ function streamFile(res, absPath, logger) {
27339
27405
  // 防止浏览器把任意 mime 当 html 渲染
27340
27406
  "X-Content-Type-Options": "nosniff"
27341
27407
  });
27342
- const stream = import_node_fs14.default.createReadStream(absPath);
27408
+ const stream = import_node_fs15.default.createReadStream(absPath);
27343
27409
  stream.on("error", (err) => {
27344
27410
  logger?.warn("streamFile read error", { absPath, err: err.message });
27345
27411
  res.destroy();
@@ -27348,8 +27414,8 @@ function streamFile(res, absPath, logger) {
27348
27414
  }
27349
27415
 
27350
27416
  // src/attachment/group.ts
27351
- var import_node_fs15 = __toESM(require("fs"), 1);
27352
- var import_node_path17 = __toESM(require("path"), 1);
27417
+ var import_node_fs16 = __toESM(require("fs"), 1);
27418
+ var import_node_path18 = __toESM(require("path"), 1);
27353
27419
  var import_node_crypto6 = __toESM(require("crypto"), 1);
27354
27420
  init_protocol();
27355
27421
  var GroupFileStore = class {
@@ -27361,11 +27427,11 @@ var GroupFileStore = class {
27361
27427
  this.logger = opts.logger;
27362
27428
  }
27363
27429
  rootForScope(scope) {
27364
- return import_node_path17.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
27430
+ return import_node_path18.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
27365
27431
  }
27366
27432
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
27367
27433
  filePath(scope, sessionId) {
27368
- return import_node_path17.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
27434
+ return import_node_path18.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
27369
27435
  }
27370
27436
  cacheKey(scope, sessionId) {
27371
27437
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -27374,7 +27440,7 @@ var GroupFileStore = class {
27374
27440
  readFile(scope, sessionId) {
27375
27441
  const file = this.filePath(scope, sessionId);
27376
27442
  try {
27377
- const raw = import_node_fs15.default.readFileSync(file, "utf8");
27443
+ const raw = import_node_fs16.default.readFileSync(file, "utf8");
27378
27444
  const parsed = JSON.parse(raw);
27379
27445
  if (!Array.isArray(parsed)) {
27380
27446
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -27400,10 +27466,10 @@ var GroupFileStore = class {
27400
27466
  }
27401
27467
  writeFile(scope, sessionId, entries) {
27402
27468
  const file = this.filePath(scope, sessionId);
27403
- import_node_fs15.default.mkdirSync(import_node_path17.default.dirname(file), { recursive: true });
27469
+ import_node_fs16.default.mkdirSync(import_node_path18.default.dirname(file), { recursive: true });
27404
27470
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
27405
- import_node_fs15.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
27406
- import_node_fs15.default.renameSync(tmp, file);
27471
+ import_node_fs16.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
27472
+ import_node_fs16.default.renameSync(tmp, file);
27407
27473
  }
27408
27474
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
27409
27475
  list(scope, sessionId) {
@@ -27489,10 +27555,10 @@ var GroupFileStore = class {
27489
27555
  };
27490
27556
 
27491
27557
  // src/discovery/state-file.ts
27492
- var import_node_fs16 = __toESM(require("fs"), 1);
27493
- var import_node_path18 = __toESM(require("path"), 1);
27558
+ var import_node_fs17 = __toESM(require("fs"), 1);
27559
+ var import_node_path19 = __toESM(require("path"), 1);
27494
27560
  function defaultStateFilePath(dataDir) {
27495
- return import_node_path18.default.join(dataDir, "state.json");
27561
+ return import_node_path19.default.join(dataDir, "state.json");
27496
27562
  }
27497
27563
  function isPidAlive(pid) {
27498
27564
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -27514,7 +27580,7 @@ var StateFileManager = class {
27514
27580
  }
27515
27581
  read() {
27516
27582
  try {
27517
- const raw = import_node_fs16.default.readFileSync(this.file, "utf8");
27583
+ const raw = import_node_fs17.default.readFileSync(this.file, "utf8");
27518
27584
  const parsed = JSON.parse(raw);
27519
27585
  return parsed;
27520
27586
  } catch {
@@ -27528,34 +27594,34 @@ var StateFileManager = class {
27528
27594
  return { status: "stale", existing };
27529
27595
  }
27530
27596
  write(state) {
27531
- import_node_fs16.default.mkdirSync(import_node_path18.default.dirname(this.file), { recursive: true });
27597
+ import_node_fs17.default.mkdirSync(import_node_path19.default.dirname(this.file), { recursive: true });
27532
27598
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
27533
- import_node_fs16.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27534
- import_node_fs16.default.renameSync(tmp, this.file);
27599
+ import_node_fs17.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27600
+ import_node_fs17.default.renameSync(tmp, this.file);
27535
27601
  if (process.platform !== "win32") {
27536
27602
  try {
27537
- import_node_fs16.default.chmodSync(this.file, 384);
27603
+ import_node_fs17.default.chmodSync(this.file, 384);
27538
27604
  } catch {
27539
27605
  }
27540
27606
  }
27541
27607
  }
27542
27608
  delete() {
27543
27609
  try {
27544
- import_node_fs16.default.unlinkSync(this.file);
27610
+ import_node_fs17.default.unlinkSync(this.file);
27545
27611
  } catch {
27546
27612
  }
27547
27613
  }
27548
27614
  };
27549
27615
 
27550
27616
  // src/tunnel/tunnel-manager.ts
27551
- var import_node_fs20 = __toESM(require("fs"), 1);
27552
- var import_node_path22 = __toESM(require("path"), 1);
27617
+ var import_node_fs21 = __toESM(require("fs"), 1);
27618
+ var import_node_path23 = __toESM(require("path"), 1);
27553
27619
  var import_node_crypto7 = __toESM(require("crypto"), 1);
27554
27620
  var import_node_child_process5 = require("child_process");
27555
27621
 
27556
27622
  // src/tunnel/tunnel-store.ts
27557
- var import_node_fs17 = __toESM(require("fs"), 1);
27558
- var import_node_path19 = __toESM(require("path"), 1);
27623
+ var import_node_fs18 = __toESM(require("fs"), 1);
27624
+ var import_node_path20 = __toESM(require("path"), 1);
27559
27625
  var TunnelStore = class {
27560
27626
  constructor(filePath) {
27561
27627
  this.filePath = filePath;
@@ -27563,7 +27629,7 @@ var TunnelStore = class {
27563
27629
  filePath;
27564
27630
  async get() {
27565
27631
  try {
27566
- const raw = await import_node_fs17.default.promises.readFile(this.filePath, "utf8");
27632
+ const raw = await import_node_fs18.default.promises.readFile(this.filePath, "utf8");
27567
27633
  const obj = JSON.parse(raw);
27568
27634
  if (!isPersistedTunnel(obj)) return null;
27569
27635
  return obj;
@@ -27574,22 +27640,22 @@ var TunnelStore = class {
27574
27640
  }
27575
27641
  }
27576
27642
  async set(v2) {
27577
- const dir = import_node_path19.default.dirname(this.filePath);
27578
- await import_node_fs17.default.promises.mkdir(dir, { recursive: true });
27643
+ const dir = import_node_path20.default.dirname(this.filePath);
27644
+ await import_node_fs18.default.promises.mkdir(dir, { recursive: true });
27579
27645
  const data = JSON.stringify(v2, null, 2);
27580
27646
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
27581
- await import_node_fs17.default.promises.writeFile(tmp, data, { mode: 384 });
27647
+ await import_node_fs18.default.promises.writeFile(tmp, data, { mode: 384 });
27582
27648
  if (process.platform !== "win32") {
27583
27649
  try {
27584
- await import_node_fs17.default.promises.chmod(tmp, 384);
27650
+ await import_node_fs18.default.promises.chmod(tmp, 384);
27585
27651
  } catch {
27586
27652
  }
27587
27653
  }
27588
- await import_node_fs17.default.promises.rename(tmp, this.filePath);
27654
+ await import_node_fs18.default.promises.rename(tmp, this.filePath);
27589
27655
  }
27590
27656
  async clear() {
27591
27657
  try {
27592
- await import_node_fs17.default.promises.unlink(this.filePath);
27658
+ await import_node_fs18.default.promises.unlink(this.filePath);
27593
27659
  } catch (err) {
27594
27660
  const code = err?.code;
27595
27661
  if (code !== "ENOENT") throw err;
@@ -27684,9 +27750,9 @@ function escape(v2) {
27684
27750
  }
27685
27751
 
27686
27752
  // src/tunnel/frpc-binary.ts
27687
- var import_node_fs18 = __toESM(require("fs"), 1);
27688
- var import_node_os9 = __toESM(require("os"), 1);
27689
- var import_node_path20 = __toESM(require("path"), 1);
27753
+ var import_node_fs19 = __toESM(require("fs"), 1);
27754
+ var import_node_os10 = __toESM(require("os"), 1);
27755
+ var import_node_path21 = __toESM(require("path"), 1);
27690
27756
  var import_node_child_process3 = require("child_process");
27691
27757
  var import_node_stream2 = require("stream");
27692
27758
  var import_promises = require("stream/promises");
@@ -27718,20 +27784,20 @@ function frpcDownloadUrl(version2, p2) {
27718
27784
  }
27719
27785
  async function ensureFrpcBinary(opts) {
27720
27786
  if (opts.override) {
27721
- if (!import_node_fs18.default.existsSync(opts.override)) {
27787
+ if (!import_node_fs19.default.existsSync(opts.override)) {
27722
27788
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
27723
27789
  }
27724
27790
  return opts.override;
27725
27791
  }
27726
27792
  const version2 = opts.version ?? FRPC_VERSION;
27727
27793
  const platform = opts.platform ?? detectPlatform();
27728
- const binDir = import_node_path20.default.join(opts.dataDir, "bin");
27729
- import_node_fs18.default.mkdirSync(binDir, { recursive: true });
27794
+ const binDir = import_node_path21.default.join(opts.dataDir, "bin");
27795
+ import_node_fs19.default.mkdirSync(binDir, { recursive: true });
27730
27796
  cleanupStaleArtifacts(binDir);
27731
- const stableBin = import_node_path20.default.join(binDir, "frpc");
27732
- if (import_node_fs18.default.existsSync(stableBin)) return stableBin;
27797
+ const stableBin = import_node_path21.default.join(binDir, "frpc");
27798
+ if (import_node_fs19.default.existsSync(stableBin)) return stableBin;
27733
27799
  const partialBin = `${stableBin}.partial`;
27734
- const tarballPath = import_node_path20.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
27800
+ const tarballPath = import_node_path21.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
27735
27801
  try {
27736
27802
  const url = frpcDownloadUrl(version2, platform);
27737
27803
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -27740,8 +27806,8 @@ async function ensureFrpcBinary(opts) {
27740
27806
  } else {
27741
27807
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
27742
27808
  }
27743
- import_node_fs18.default.chmodSync(partialBin, 493);
27744
- import_node_fs18.default.renameSync(partialBin, stableBin);
27809
+ import_node_fs19.default.chmodSync(partialBin, 493);
27810
+ import_node_fs19.default.renameSync(partialBin, stableBin);
27745
27811
  } finally {
27746
27812
  safeUnlink(tarballPath);
27747
27813
  safeUnlink(partialBin);
@@ -27751,15 +27817,15 @@ async function ensureFrpcBinary(opts) {
27751
27817
  function cleanupStaleArtifacts(binDir) {
27752
27818
  let entries;
27753
27819
  try {
27754
- entries = import_node_fs18.default.readdirSync(binDir);
27820
+ entries = import_node_fs19.default.readdirSync(binDir);
27755
27821
  } catch {
27756
27822
  return;
27757
27823
  }
27758
27824
  for (const name of entries) {
27759
27825
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
27760
- const full = import_node_path20.default.join(binDir, name);
27826
+ const full = import_node_path21.default.join(binDir, name);
27761
27827
  try {
27762
- import_node_fs18.default.rmSync(full, { recursive: true, force: true });
27828
+ import_node_fs19.default.rmSync(full, { recursive: true, force: true });
27763
27829
  } catch {
27764
27830
  }
27765
27831
  }
@@ -27767,7 +27833,7 @@ function cleanupStaleArtifacts(binDir) {
27767
27833
  }
27768
27834
  function safeUnlink(p2) {
27769
27835
  try {
27770
- import_node_fs18.default.unlinkSync(p2);
27836
+ import_node_fs19.default.unlinkSync(p2);
27771
27837
  } catch {
27772
27838
  }
27773
27839
  }
@@ -27778,13 +27844,13 @@ async function downloadToFile(url, dest, fetchImpl) {
27778
27844
  if (!res.ok || !res.body) {
27779
27845
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
27780
27846
  }
27781
- const out = import_node_fs18.default.createWriteStream(dest);
27847
+ const out = import_node_fs19.default.createWriteStream(dest);
27782
27848
  const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
27783
27849
  await (0, import_promises.pipeline)(nodeStream, out);
27784
27850
  }
27785
27851
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
27786
- const work = import_node_path20.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
27787
- import_node_fs18.default.mkdirSync(work, { recursive: true });
27852
+ const work = import_node_path21.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
27853
+ import_node_fs19.default.mkdirSync(work, { recursive: true });
27788
27854
  try {
27789
27855
  await new Promise((resolve6, reject) => {
27790
27856
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -27792,32 +27858,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
27792
27858
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
27793
27859
  });
27794
27860
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
27795
- const src = import_node_path20.default.join(work, dirName, "frpc");
27796
- if (!import_node_fs18.default.existsSync(src)) {
27861
+ const src = import_node_path21.default.join(work, dirName, "frpc");
27862
+ if (!import_node_fs19.default.existsSync(src)) {
27797
27863
  throw new Error(`frpc not found inside tarball at ${src}`);
27798
27864
  }
27799
- import_node_fs18.default.copyFileSync(src, destBin);
27865
+ import_node_fs19.default.copyFileSync(src, destBin);
27800
27866
  } finally {
27801
- import_node_fs18.default.rmSync(work, { recursive: true, force: true });
27867
+ import_node_fs19.default.rmSync(work, { recursive: true, force: true });
27802
27868
  }
27803
27869
  }
27804
27870
 
27805
27871
  // src/tunnel/frpc-process.ts
27806
- var import_node_fs19 = __toESM(require("fs"), 1);
27807
- var import_node_path21 = __toESM(require("path"), 1);
27872
+ var import_node_fs20 = __toESM(require("fs"), 1);
27873
+ var import_node_path22 = __toESM(require("path"), 1);
27808
27874
  var import_node_child_process4 = require("child_process");
27809
27875
  function frpcPidFilePath(dataDir) {
27810
- return import_node_path21.default.join(dataDir, "frpc.pid");
27876
+ return import_node_path22.default.join(dataDir, "frpc.pid");
27811
27877
  }
27812
27878
  function writeFrpcPid(dataDir, pid) {
27813
27879
  try {
27814
- import_node_fs19.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
27880
+ import_node_fs20.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
27815
27881
  } catch {
27816
27882
  }
27817
27883
  }
27818
27884
  function clearFrpcPid(dataDir) {
27819
27885
  try {
27820
- import_node_fs19.default.unlinkSync(frpcPidFilePath(dataDir));
27886
+ import_node_fs20.default.unlinkSync(frpcPidFilePath(dataDir));
27821
27887
  } catch {
27822
27888
  }
27823
27889
  }
@@ -27833,7 +27899,7 @@ function defaultIsPidAlive(pid) {
27833
27899
  }
27834
27900
  function defaultReadPidFile(file) {
27835
27901
  try {
27836
- return import_node_fs19.default.readFileSync(file, "utf8");
27902
+ return import_node_fs20.default.readFileSync(file, "utf8");
27837
27903
  } catch {
27838
27904
  return null;
27839
27905
  }
@@ -27849,7 +27915,7 @@ function defaultSleep(ms) {
27849
27915
  }
27850
27916
  async function killStaleFrpc(deps) {
27851
27917
  const pidFile = frpcPidFilePath(deps.dataDir);
27852
- const tomlPath = import_node_path21.default.join(deps.dataDir, "frpc.toml");
27918
+ const tomlPath = import_node_path22.default.join(deps.dataDir, "frpc.toml");
27853
27919
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
27854
27920
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
27855
27921
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -27873,7 +27939,7 @@ async function killStaleFrpc(deps) {
27873
27939
  }
27874
27940
  if (victims.size === 0) {
27875
27941
  try {
27876
- import_node_fs19.default.unlinkSync(pidFile);
27942
+ import_node_fs20.default.unlinkSync(pidFile);
27877
27943
  } catch {
27878
27944
  }
27879
27945
  return;
@@ -27884,7 +27950,7 @@ async function killStaleFrpc(deps) {
27884
27950
  }
27885
27951
  await sleep(deps.reapWaitMs ?? 300);
27886
27952
  try {
27887
- import_node_fs19.default.unlinkSync(pidFile);
27953
+ import_node_fs20.default.unlinkSync(pidFile);
27888
27954
  } catch {
27889
27955
  }
27890
27956
  }
@@ -27921,7 +27987,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
27921
27987
  var TunnelManager = class {
27922
27988
  constructor(deps) {
27923
27989
  this.deps = deps;
27924
- this.store = deps.store ?? new TunnelStore(import_node_path22.default.join(deps.dataDir, "tunnel.json"));
27990
+ this.store = deps.store ?? new TunnelStore(import_node_path23.default.join(deps.dataDir, "tunnel.json"));
27925
27991
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
27926
27992
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
27927
27993
  }
@@ -28048,7 +28114,7 @@ var TunnelManager = class {
28048
28114
  dataDir: this.deps.dataDir,
28049
28115
  override: this.deps.frpcBinaryOverride ?? void 0
28050
28116
  });
28051
- const tomlPath = import_node_path22.default.join(this.deps.dataDir, "frpc.toml");
28117
+ const tomlPath = import_node_path23.default.join(this.deps.dataDir, "frpc.toml");
28052
28118
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
28053
28119
  const toml = buildFrpcToml({
28054
28120
  serverAddr: t.frpsHost,
@@ -28059,12 +28125,12 @@ var TunnelManager = class {
28059
28125
  localPort,
28060
28126
  logLevel: "info"
28061
28127
  });
28062
- await import_node_fs20.default.promises.writeFile(tomlPath, toml, { mode: 384 });
28128
+ await import_node_fs21.default.promises.writeFile(tomlPath, toml, { mode: 384 });
28063
28129
  const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
28064
28130
  stdio: ["ignore", "pipe", "pipe"]
28065
28131
  });
28066
- const logFilePath = import_node_path22.default.join(this.deps.dataDir, "frpc.log");
28067
- const logStream = import_node_fs20.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
28132
+ const logFilePath = import_node_path23.default.join(this.deps.dataDir, "frpc.log");
28133
+ const logStream = import_node_fs21.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
28068
28134
  logStream.on("error", () => {
28069
28135
  });
28070
28136
  const tee = (chunk) => {
@@ -28146,23 +28212,23 @@ async function waitForFrpcReady(proc, timeoutMs) {
28146
28212
  }
28147
28213
 
28148
28214
  // src/tunnel/device-key.ts
28149
- var import_node_os10 = __toESM(require("os"), 1);
28215
+ var import_node_os11 = __toESM(require("os"), 1);
28150
28216
  var import_node_crypto8 = __toESM(require("crypto"), 1);
28151
28217
  var DERIVE_SALT = "clawd-tunnel-device-v1";
28152
28218
  function deriveStableDeviceKey(opts = {}) {
28153
- const hostname = opts.hostname ?? import_node_os10.default.hostname();
28154
- const uid = opts.uid ?? (typeof import_node_os10.default.userInfo === "function" ? import_node_os10.default.userInfo().uid : 0);
28219
+ const hostname = opts.hostname ?? import_node_os11.default.hostname();
28220
+ const uid = opts.uid ?? (typeof import_node_os11.default.userInfo === "function" ? import_node_os11.default.userInfo().uid : 0);
28155
28221
  const input = `${hostname}::${uid}`;
28156
28222
  return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
28157
28223
  }
28158
28224
 
28159
28225
  // src/auth-store.ts
28160
- var import_node_fs21 = __toESM(require("fs"), 1);
28161
- var import_node_path23 = __toESM(require("path"), 1);
28226
+ var import_node_fs22 = __toESM(require("fs"), 1);
28227
+ var import_node_path24 = __toESM(require("path"), 1);
28162
28228
  var import_node_crypto9 = __toESM(require("crypto"), 1);
28163
28229
  var AUTH_FILE_NAME = "auth.json";
28164
28230
  function authFilePath(dataDir) {
28165
- return import_node_path23.default.join(dataDir, AUTH_FILE_NAME);
28231
+ return import_node_path24.default.join(dataDir, AUTH_FILE_NAME);
28166
28232
  }
28167
28233
  function loadOrCreateAuthFile(opts) {
28168
28234
  const file = authFilePath(opts.dataDir);
@@ -28194,7 +28260,7 @@ function defaultGenerateOwnerPrincipalId() {
28194
28260
  }
28195
28261
  function readAuthFile(file) {
28196
28262
  try {
28197
- const raw = import_node_fs21.default.readFileSync(file, "utf8");
28263
+ const raw = import_node_fs22.default.readFileSync(file, "utf8");
28198
28264
  const parsed = JSON.parse(raw);
28199
28265
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
28200
28266
  return null;
@@ -28212,25 +28278,25 @@ function readAuthFile(file) {
28212
28278
  }
28213
28279
  }
28214
28280
  function writeAuthFile(file, content) {
28215
- import_node_fs21.default.mkdirSync(import_node_path23.default.dirname(file), { recursive: true });
28216
- import_node_fs21.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
28281
+ import_node_fs22.default.mkdirSync(import_node_path24.default.dirname(file), { recursive: true });
28282
+ import_node_fs22.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
28217
28283
  try {
28218
- import_node_fs21.default.chmodSync(file, 384);
28284
+ import_node_fs22.default.chmodSync(file, 384);
28219
28285
  } catch {
28220
28286
  }
28221
28287
  }
28222
28288
 
28223
28289
  // src/owner-profile.ts
28224
- var import_node_fs22 = __toESM(require("fs"), 1);
28225
- var import_node_os11 = __toESM(require("os"), 1);
28226
- var import_node_path24 = __toESM(require("path"), 1);
28290
+ var import_node_fs23 = __toESM(require("fs"), 1);
28291
+ var import_node_os12 = __toESM(require("os"), 1);
28292
+ var import_node_path25 = __toESM(require("path"), 1);
28227
28293
  var PROFILE_FILENAME = "profile.json";
28228
28294
  function loadOwnerDisplayName(dataDir) {
28229
- const fallback = import_node_os11.default.userInfo().username;
28230
- const profilePath = import_node_path24.default.join(dataDir, PROFILE_FILENAME);
28295
+ const fallback = import_node_os12.default.userInfo().username;
28296
+ const profilePath = import_node_path25.default.join(dataDir, PROFILE_FILENAME);
28231
28297
  let raw;
28232
28298
  try {
28233
- raw = import_node_fs22.default.readFileSync(profilePath, "utf8");
28299
+ raw = import_node_fs23.default.readFileSync(profilePath, "utf8");
28234
28300
  } catch {
28235
28301
  return fallback;
28236
28302
  }
@@ -28259,12 +28325,12 @@ init_protocol();
28259
28325
  init_protocol();
28260
28326
 
28261
28327
  // src/session/fork.ts
28262
- var import_node_fs23 = __toESM(require("fs"), 1);
28263
- var import_node_os12 = __toESM(require("os"), 1);
28264
- var import_node_path25 = __toESM(require("path"), 1);
28328
+ var import_node_fs24 = __toESM(require("fs"), 1);
28329
+ var import_node_os13 = __toESM(require("os"), 1);
28330
+ var import_node_path26 = __toESM(require("path"), 1);
28265
28331
  init_claude_history();
28266
28332
  function readJsonlEntries(file) {
28267
- const raw = import_node_fs23.default.readFileSync(file, "utf8");
28333
+ const raw = import_node_fs24.default.readFileSync(file, "utf8");
28268
28334
  const out = [];
28269
28335
  for (const line of raw.split("\n")) {
28270
28336
  const t = line.trim();
@@ -28277,10 +28343,10 @@ function readJsonlEntries(file) {
28277
28343
  return out;
28278
28344
  }
28279
28345
  function forkSession(input) {
28280
- const baseDir = input.baseDir ?? import_node_path25.default.join(import_node_os12.default.homedir(), ".claude");
28281
- const projectDir = import_node_path25.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
28282
- const sourceFile = import_node_path25.default.join(projectDir, `${input.toolSessionId}.jsonl`);
28283
- if (!import_node_fs23.default.existsSync(sourceFile)) {
28346
+ const baseDir = input.baseDir ?? import_node_path26.default.join(import_node_os13.default.homedir(), ".claude");
28347
+ const projectDir = import_node_path26.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
28348
+ const sourceFile = import_node_path26.default.join(projectDir, `${input.toolSessionId}.jsonl`);
28349
+ if (!import_node_fs24.default.existsSync(sourceFile)) {
28284
28350
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
28285
28351
  }
28286
28352
  const entries = readJsonlEntries(sourceFile);
@@ -28310,9 +28376,9 @@ function forkSession(input) {
28310
28376
  }
28311
28377
  forkedLines.push(JSON.stringify(forked));
28312
28378
  }
28313
- const forkedFilePath = import_node_path25.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
28314
- import_node_fs23.default.mkdirSync(projectDir, { recursive: true });
28315
- import_node_fs23.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
28379
+ const forkedFilePath = import_node_path26.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
28380
+ import_node_fs24.default.mkdirSync(projectDir, { recursive: true });
28381
+ import_node_fs24.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
28316
28382
  return { forkedToolSessionId, forkedFilePath };
28317
28383
  }
28318
28384
 
@@ -28600,28 +28666,6 @@ function buildSessionHandlers(deps) {
28600
28666
  }
28601
28667
  };
28602
28668
  };
28603
- const peerSessionUpsert = async (frame, _client, ctx) => {
28604
- if (ctx && ctx.principal.kind !== "owner") {
28605
- throw new ClawdError(
28606
- ERROR_CODES.UNAUTHORIZED,
28607
- `principal ${ctx.principal.kind}:${ctx.principal.id} cannot peerSession:upsert`
28608
- );
28609
- }
28610
- const file = PeerSessionUpsertArgs.parse(frame);
28611
- manager.mirrorUpsert(file);
28612
- return { response: { type: "peerSession:upsert:ok" }, broadcast: [] };
28613
- };
28614
- const peerSessionRemove = async (frame, _client, ctx) => {
28615
- if (ctx && ctx.principal.kind !== "owner") {
28616
- throw new ClawdError(
28617
- ERROR_CODES.UNAUTHORIZED,
28618
- `principal ${ctx.principal.kind}:${ctx.principal.id} cannot peerSession:remove`
28619
- );
28620
- }
28621
- const args = PeerSessionRemoveArgs.parse(frame);
28622
- manager.mirrorRemove(args.sessionId);
28623
- return { response: { type: "peerSession:remove:ok" }, broadcast: [] };
28624
- };
28625
28669
  return {
28626
28670
  "session:create": create,
28627
28671
  "session:list": list,
@@ -28647,9 +28691,7 @@ function buildSessionHandlers(deps) {
28647
28691
  "session:cancelQuestion": cancelQuestion,
28648
28692
  "session:pty:input": ptyInput,
28649
28693
  "session:pty:resize": ptyResize,
28650
- "session:pty:snapshot": ptySnapshot,
28651
- "peerSession:upsert": peerSessionUpsert,
28652
- "peerSession:remove": peerSessionRemove
28694
+ "session:pty:snapshot": ptySnapshot
28653
28695
  };
28654
28696
  }
28655
28697
 
@@ -28668,7 +28710,7 @@ function buildPermissionHandlers(deps) {
28668
28710
  }
28669
28711
 
28670
28712
  // src/handlers/history.ts
28671
- var path35 = __toESM(require("path"), 1);
28713
+ var path36 = __toESM(require("path"), 1);
28672
28714
  init_protocol();
28673
28715
 
28674
28716
  // src/session/recent-dirs.ts
@@ -28686,7 +28728,7 @@ function listRecentDirs(store, limit = 50) {
28686
28728
  }
28687
28729
 
28688
28730
  // src/permission/persona-paths.ts
28689
- var path34 = __toESM(require("path"), 1);
28731
+ var path35 = __toESM(require("path"), 1);
28690
28732
  function getAllowedPersonaIds(grants, action) {
28691
28733
  const ids = /* @__PURE__ */ new Set();
28692
28734
  for (const g2 of grants) {
@@ -28699,26 +28741,26 @@ function getAllowedPersonaIds(grants, action) {
28699
28741
  return ids;
28700
28742
  }
28701
28743
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read") {
28702
- const root = path34.resolve(personaRoot);
28703
- const target = path34.resolve(absPath);
28704
- const sep3 = root.endsWith(path34.sep) ? "" : path34.sep;
28744
+ const root = path35.resolve(personaRoot);
28745
+ const target = path35.resolve(absPath);
28746
+ const sep3 = root.endsWith(path35.sep) ? "" : path35.sep;
28705
28747
  if (!target.startsWith(root + sep3)) return false;
28706
- const rel = path34.relative(root, target);
28748
+ const rel = path35.relative(root, target);
28707
28749
  if (!rel || rel.startsWith("..")) return false;
28708
- const personaId = rel.split(path34.sep)[0];
28750
+ const personaId = rel.split(path35.sep)[0];
28709
28751
  if (!personaId) return false;
28710
28752
  const allowed = getAllowedPersonaIds(grants, action);
28711
28753
  if (allowed === "*") return true;
28712
28754
  return allowed.has(personaId);
28713
28755
  }
28714
28756
  function personaIdFromPath(absPath, personaRoot) {
28715
- const root = path34.resolve(personaRoot);
28716
- const target = path34.resolve(absPath);
28717
- const sep3 = root.endsWith(path34.sep) ? "" : path34.sep;
28757
+ const root = path35.resolve(personaRoot);
28758
+ const target = path35.resolve(absPath);
28759
+ const sep3 = root.endsWith(path35.sep) ? "" : path35.sep;
28718
28760
  if (!target.startsWith(root + sep3)) return null;
28719
- const rel = path34.relative(root, target);
28761
+ const rel = path35.relative(root, target);
28720
28762
  if (!rel || rel.startsWith("..")) return null;
28721
- const id = rel.split(path34.sep)[0];
28763
+ const id = rel.split(path35.sep)[0];
28722
28764
  return id || null;
28723
28765
  }
28724
28766
 
@@ -28743,7 +28785,7 @@ function buildHistoryHandlers(deps) {
28743
28785
  if (!pid) return false;
28744
28786
  return isGuestPathAllowed(
28745
28787
  ctx.grants,
28746
- path35.join(personaRoot, pid),
28788
+ path36.join(personaRoot, pid),
28747
28789
  personaRoot,
28748
28790
  "read"
28749
28791
  );
@@ -28754,7 +28796,7 @@ function buildHistoryHandlers(deps) {
28754
28796
  };
28755
28797
  const list = async (frame, _client, ctx) => {
28756
28798
  const args = HistoryListArgs.parse(frame);
28757
- assertGuestPath(ctx, path35.resolve(args.projectPath), personaRoot, "history:list");
28799
+ assertGuestPath(ctx, path36.resolve(args.projectPath), personaRoot, "history:list");
28758
28800
  const sessions = await history.listSessions(args);
28759
28801
  return { response: { type: "history:list", sessions } };
28760
28802
  };
@@ -28786,13 +28828,13 @@ function buildHistoryHandlers(deps) {
28786
28828
  };
28787
28829
  const subagents = async (frame, _client, ctx) => {
28788
28830
  const args = HistorySubagentsArgs.parse(frame);
28789
- assertGuestPath(ctx, path35.resolve(args.cwd), personaRoot, "history:subagents");
28831
+ assertGuestPath(ctx, path36.resolve(args.cwd), personaRoot, "history:subagents");
28790
28832
  const subs = await history.listSubagents(args);
28791
28833
  return { response: { type: "history:subagents", subagents: subs } };
28792
28834
  };
28793
28835
  const subagentRead = async (frame, _client, ctx) => {
28794
28836
  const args = HistorySubagentReadArgs.parse(frame);
28795
- assertGuestPath(ctx, path35.resolve(args.cwd), personaRoot, "history:subagent-read");
28837
+ assertGuestPath(ctx, path36.resolve(args.cwd), personaRoot, "history:subagent-read");
28796
28838
  const res = await history.readSubagent(args);
28797
28839
  return { response: { type: "history:subagent-read", ...res } };
28798
28840
  };
@@ -28800,7 +28842,7 @@ function buildHistoryHandlers(deps) {
28800
28842
  const dirs = listRecentDirs(store);
28801
28843
  if (ctx?.principal.kind === "guest" && personaRoot) {
28802
28844
  const filtered = dirs.filter(
28803
- (d) => isGuestPathAllowed(ctx.grants, path35.resolve(d.cwd), personaRoot, "read")
28845
+ (d) => isGuestPathAllowed(ctx.grants, path36.resolve(d.cwd), personaRoot, "read")
28804
28846
  );
28805
28847
  return { response: { type: "history:recentDirs", dirs: filtered } };
28806
28848
  }
@@ -28817,8 +28859,8 @@ function buildHistoryHandlers(deps) {
28817
28859
  }
28818
28860
 
28819
28861
  // src/handlers/workspace.ts
28820
- var path36 = __toESM(require("path"), 1);
28821
- var os13 = __toESM(require("os"), 1);
28862
+ var path37 = __toESM(require("path"), 1);
28863
+ var os14 = __toESM(require("os"), 1);
28822
28864
  init_protocol();
28823
28865
  init_protocol();
28824
28866
  function buildEnabledPluginNames(personaManager, personaId) {
@@ -28857,23 +28899,23 @@ function buildWorkspaceHandlers(deps) {
28857
28899
  const list = async (frame, _client, ctx) => {
28858
28900
  const args = WorkspaceListArgs.parse(frame);
28859
28901
  const isGuest = ctx?.principal.kind === "guest";
28860
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os13.homedir();
28861
- const resolvedCwd = path36.resolve(args.cwd ?? fallbackCwd);
28862
- const target = args.path ? path36.resolve(resolvedCwd, args.path) : resolvedCwd;
28902
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os14.homedir();
28903
+ const resolvedCwd = path37.resolve(args.cwd ?? fallbackCwd);
28904
+ const target = args.path ? path37.resolve(resolvedCwd, args.path) : resolvedCwd;
28863
28905
  assertGuestPath2(ctx, target, personaRoot, "workspace:list");
28864
28906
  const res = workspace.list({ ...args, cwd: resolvedCwd });
28865
28907
  return { response: { type: "workspace:list", ...res } };
28866
28908
  };
28867
28909
  const read = async (frame, _client, ctx) => {
28868
28910
  const args = WorkspaceReadArgs.parse(frame);
28869
- const target = path36.isAbsolute(args.path) ? path36.resolve(args.path) : path36.resolve(args.cwd, args.path);
28911
+ const target = path37.isAbsolute(args.path) ? path37.resolve(args.path) : path37.resolve(args.cwd, args.path);
28870
28912
  assertGuestPath2(ctx, target, personaRoot, "workspace:read");
28871
28913
  const res = workspace.read(args);
28872
28914
  return { response: { type: "workspace:read", ...res } };
28873
28915
  };
28874
28916
  const skillsList = async (frame, _client, ctx) => {
28875
28917
  const args = SkillsListArgs.parse(frame);
28876
- const cwdAbs = path36.resolve(args.cwd);
28918
+ const cwdAbs = path37.resolve(args.cwd);
28877
28919
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list");
28878
28920
  const list2 = skills.list(args);
28879
28921
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -28885,7 +28927,7 @@ function buildWorkspaceHandlers(deps) {
28885
28927
  };
28886
28928
  const agentsList = async (frame, _client, ctx) => {
28887
28929
  const args = AgentsListArgs.parse(frame);
28888
- const cwdAbs = path36.resolve(args.cwd);
28930
+ const cwdAbs = path37.resolve(args.cwd);
28889
28931
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list");
28890
28932
  const list2 = agents.list(args);
28891
28933
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -28904,20 +28946,20 @@ function buildWorkspaceHandlers(deps) {
28904
28946
  }
28905
28947
 
28906
28948
  // src/handlers/git.ts
28907
- var path38 = __toESM(require("path"), 1);
28949
+ var path39 = __toESM(require("path"), 1);
28908
28950
  init_protocol();
28909
28951
  init_protocol();
28910
28952
 
28911
28953
  // src/workspace/git.ts
28912
28954
  var import_node_child_process6 = require("child_process");
28913
- var import_node_fs24 = __toESM(require("fs"), 1);
28914
- var import_node_path26 = __toESM(require("path"), 1);
28955
+ var import_node_fs25 = __toESM(require("fs"), 1);
28956
+ var import_node_path27 = __toESM(require("path"), 1);
28915
28957
  var import_node_util = require("util");
28916
28958
  var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
28917
28959
  function normalizePath(p2) {
28918
- const resolved = import_node_path26.default.resolve(p2);
28960
+ const resolved = import_node_path27.default.resolve(p2);
28919
28961
  try {
28920
- return import_node_fs24.default.realpathSync(resolved);
28962
+ return import_node_fs25.default.realpathSync(resolved);
28921
28963
  } catch {
28922
28964
  return resolved;
28923
28965
  }
@@ -28990,7 +29032,7 @@ async function listGitBranches(cwd) {
28990
29032
  // src/handlers/git.ts
28991
29033
  function assertGuestCwd(ctx, cwd, personaRoot, method) {
28992
29034
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
28993
- if (!isGuestPathAllowed(ctx.grants, path38.resolve(cwd), personaRoot, "read")) {
29035
+ if (!isGuestPathAllowed(ctx.grants, path39.resolve(cwd), personaRoot, "read")) {
28994
29036
  throw new ClawdError(
28995
29037
  ERROR_CODES.UNAUTHORIZED,
28996
29038
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -29353,7 +29395,7 @@ function buildWhoamiHandler(deps) {
29353
29395
  }
29354
29396
 
29355
29397
  // src/handlers/meta.ts
29356
- var import_node_os13 = __toESM(require("os"), 1);
29398
+ var import_node_os14 = __toESM(require("os"), 1);
29357
29399
  init_protocol();
29358
29400
 
29359
29401
  // src/version.ts
@@ -29383,7 +29425,7 @@ function buildReadyFrame(deps, client) {
29383
29425
  return {
29384
29426
  version,
29385
29427
  protocolVersion: PROTOCOL_VERSION,
29386
- hostname: import_node_os13.default.hostname(),
29428
+ hostname: import_node_os14.default.hostname(),
29387
29429
  os: process.platform,
29388
29430
  tools,
29389
29431
  runningSessions: info.runningSessions,
@@ -29477,7 +29519,7 @@ function buildPersonaHandlers(deps) {
29477
29519
  }
29478
29520
 
29479
29521
  // src/handlers/attachment.ts
29480
- var import_node_path27 = __toESM(require("path"), 1);
29522
+ var import_node_path28 = __toESM(require("path"), 1);
29481
29523
  init_protocol();
29482
29524
  init_protocol();
29483
29525
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -29531,12 +29573,12 @@ function buildAttachmentHandlers(deps) {
29531
29573
  `session ${args.sessionId} scope unresolved`
29532
29574
  );
29533
29575
  }
29534
- const cwdAbs = import_node_path27.default.resolve(sessionFile.cwd);
29535
- const candidateAbs = import_node_path27.default.isAbsolute(args.relPath) ? import_node_path27.default.resolve(args.relPath) : import_node_path27.default.resolve(cwdAbs, args.relPath);
29576
+ const cwdAbs = import_node_path28.default.resolve(sessionFile.cwd);
29577
+ const candidateAbs = import_node_path28.default.isAbsolute(args.relPath) ? import_node_path28.default.resolve(args.relPath) : import_node_path28.default.resolve(cwdAbs, args.relPath);
29536
29578
  assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
29537
29579
  const entries = deps.groupFileStore.list(scope, args.sessionId);
29538
29580
  const entry = entries.find((e) => {
29539
- const storedAbs = import_node_path27.default.isAbsolute(e.relPath) ? import_node_path27.default.resolve(e.relPath) : import_node_path27.default.resolve(cwdAbs, e.relPath);
29581
+ const storedAbs = import_node_path28.default.isAbsolute(e.relPath) ? import_node_path28.default.resolve(e.relPath) : import_node_path28.default.resolve(cwdAbs, e.relPath);
29540
29582
  return storedAbs === candidateAbs && !e.stale;
29541
29583
  });
29542
29584
  if (!entry) {
@@ -29560,7 +29602,7 @@ function buildAttachmentHandlers(deps) {
29560
29602
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
29561
29603
  const f = deps.sessionStore.read(sessionId);
29562
29604
  if (!f) return;
29563
- assertGuestAttachmentPath(ctx, import_node_path27.default.resolve(f.cwd), deps.personaRoot, method);
29605
+ assertGuestAttachmentPath(ctx, import_node_path28.default.resolve(f.cwd), deps.personaRoot, method);
29564
29606
  }
29565
29607
  const groupAdd = async (frame, _client, ctx) => {
29566
29608
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -29727,11 +29769,6 @@ var METHOD_GRANT_MAP = {
29727
29769
  "session:pin": CAPABILITY_SCOPED,
29728
29770
  "session:reorderPins": ADMIN_ANY,
29729
29771
  // owner 全局操作,无 personaId 维度
29730
- // mirror peer sessions (2026-05-26):owner-only — guest 不应能写/删本机 mirror SessionFile
29731
- // (会绕过 #739 隔离规则把伪造身份的 SessionFile 写进 default store)。handler 端内部 ctx
29732
- // 校验,dispatcher 层一刀切 admin 也兜底。
29733
- "peerSession:upsert": ADMIN_ANY,
29734
- "peerSession:remove": ADMIN_ANY,
29735
29772
  "permission:respond": CAPABILITY_SCOPED,
29736
29773
  "session:answerQuestion": CAPABILITY_SCOPED,
29737
29774
  "session:cancelQuestion": CAPABILITY_SCOPED,
@@ -29802,7 +29839,7 @@ function computeGrantForFrame(method, frame) {
29802
29839
  async function startDaemon(config) {
29803
29840
  const logger = createLogger({
29804
29841
  level: config.logLevel,
29805
- file: import_node_path28.default.join(config.dataDir, "clawd.log")
29842
+ file: import_node_path29.default.join(config.dataDir, "clawd.log")
29806
29843
  });
29807
29844
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
29808
29845
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -29889,7 +29926,7 @@ async function startDaemon(config) {
29889
29926
  const agents = new AgentsScanner();
29890
29927
  const history = new ClaudeHistoryReader();
29891
29928
  let transport = null;
29892
- const personaStore = new PersonaStore(import_node_path28.default.join(config.dataDir, "personas"));
29929
+ const personaStore = new PersonaStore(import_node_path29.default.join(config.dataDir, "personas"));
29893
29930
  const defaultsRoot = findDefaultsRoot();
29894
29931
  if (defaultsRoot) {
29895
29932
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -29906,7 +29943,7 @@ async function startDaemon(config) {
29906
29943
  getAdapter,
29907
29944
  historyReader: history,
29908
29945
  dataDir: config.dataDir,
29909
- personaRoot: import_node_path28.default.join(config.dataDir, "personas"),
29946
+ personaRoot: import_node_path29.default.join(config.dataDir, "personas"),
29910
29947
  personaStore,
29911
29948
  ownerDisplayName,
29912
29949
  ownerPrincipalId,
@@ -29930,10 +29967,10 @@ async function startDaemon(config) {
29930
29967
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
29931
29968
  attachmentGroup: {
29932
29969
  onFileEdit: (input) => {
29933
- const absPath = import_node_path28.default.isAbsolute(input.relPath) ? input.relPath : import_node_path28.default.join(input.cwd, input.relPath);
29970
+ const absPath = import_node_path29.default.isAbsolute(input.relPath) ? input.relPath : import_node_path29.default.join(input.cwd, input.relPath);
29934
29971
  let size = 0;
29935
29972
  try {
29936
- size = import_node_fs25.default.statSync(absPath).size;
29973
+ size = import_node_fs26.default.statSync(absPath).size;
29937
29974
  } catch (err) {
29938
29975
  logger.warn("attachment.onFileEdit stat failed", {
29939
29976
  sessionId: input.sessionId,
@@ -29959,6 +29996,11 @@ async function startDaemon(config) {
29959
29996
  }
29960
29997
  });
29961
29998
  const observer = new SessionObserver({
29999
+ // TUI 模式 pty 跑 CC 不发 SDK system.task_started 帧 → UI pending 期 progress.agentId
30000
+ // 永远 undefined,子 agent 调用过程没有抽屉入口。开 meta observer 后从 subagents 目录
30001
+ // 新出现的 agent-*.meta.json 派生 subagent_progress(started) 补这块缺口。SDK 模式仍走
30002
+ // task_started 路径,避免双 emit 让 ring buffer 双帧。
30003
+ enableSubagentMetaObserver: config.mode === "tui",
29962
30004
  onEvent: ({ sessionId, events }) => {
29963
30005
  manager.feedObserverEvents(sessionId, events);
29964
30006
  },
@@ -30046,10 +30088,10 @@ async function startDaemon(config) {
30046
30088
  // 'persona/<pid>/owner',default 走 'default'。
30047
30089
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
30048
30090
  // guest path guard:candidate 必须在 personaRoot 子树下
30049
- personaRoot: import_node_path28.default.join(config.dataDir, "personas")
30091
+ personaRoot: import_node_path29.default.join(config.dataDir, "personas")
30050
30092
  },
30051
30093
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
30052
- personaRoot: import_node_path28.default.join(config.dataDir, "personas"),
30094
+ personaRoot: import_node_path29.default.join(config.dataDir, "personas"),
30053
30095
  // capability:list / delete handler 依赖
30054
30096
  capabilityManager,
30055
30097
  // personal-cap:get 返回的 shareBaseUrl 用此 base URL:
@@ -30250,8 +30292,8 @@ async function startDaemon(config) {
30250
30292
  const lines = [
30251
30293
  `Tunnel: ${r.url}`,
30252
30294
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
30253
- `Frpc config: ${import_node_path28.default.join(config.dataDir, "frpc.toml")}`,
30254
- `Frpc log: ${import_node_path28.default.join(config.dataDir, "frpc.log")}`
30295
+ `Frpc config: ${import_node_path29.default.join(config.dataDir, "frpc.toml")}`,
30296
+ `Frpc log: ${import_node_path29.default.join(config.dataDir, "frpc.log")}`
30255
30297
  ];
30256
30298
  const width = Math.max(...lines.map((l) => l.length));
30257
30299
  const bar = "\u2550".repeat(width + 4);
@@ -30264,8 +30306,8 @@ ${bar}
30264
30306
 
30265
30307
  `);
30266
30308
  try {
30267
- const connectPath = import_node_path28.default.join(config.dataDir, "connect.txt");
30268
- import_node_fs25.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
30309
+ const connectPath = import_node_path29.default.join(config.dataDir, "connect.txt");
30310
+ import_node_fs26.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
30269
30311
  } catch {
30270
30312
  }
30271
30313
  } catch (err) {
@@ -30309,9 +30351,9 @@ ${bar}
30309
30351
  };
30310
30352
  }
30311
30353
  function migrateDropPersonsDir(dataDir) {
30312
- const dir = import_node_path28.default.join(dataDir, "persons");
30354
+ const dir = import_node_path29.default.join(dataDir, "persons");
30313
30355
  try {
30314
- import_node_fs25.default.rmSync(dir, { recursive: true, force: true });
30356
+ import_node_fs26.default.rmSync(dir, { recursive: true, force: true });
30315
30357
  } catch {
30316
30358
  }
30317
30359
  }