@clawos-dev/clawd 0.2.498 → 0.2.500

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.
package/dist/cli.cjs CHANGED
@@ -10935,7 +10935,7 @@ var require_atomic_sleep = __commonJS({
10935
10935
  var require_sonic_boom = __commonJS({
10936
10936
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
10937
10937
  "use strict";
10938
- var fs87 = require("fs");
10938
+ var fs88 = require("fs");
10939
10939
  var EventEmitter3 = require("events");
10940
10940
  var inherits = require("util").inherits;
10941
10941
  var path98 = require("path");
@@ -10992,20 +10992,20 @@ var require_sonic_boom = __commonJS({
10992
10992
  const mode = sonic.mode;
10993
10993
  if (sonic.sync) {
10994
10994
  try {
10995
- if (sonic.mkdir) fs87.mkdirSync(path98.dirname(file), { recursive: true });
10996
- const fd = fs87.openSync(file, flags, mode);
10995
+ if (sonic.mkdir) fs88.mkdirSync(path98.dirname(file), { recursive: true });
10996
+ const fd = fs88.openSync(file, flags, mode);
10997
10997
  fileOpened(null, fd);
10998
10998
  } catch (err) {
10999
10999
  fileOpened(err);
11000
11000
  throw err;
11001
11001
  }
11002
11002
  } else if (sonic.mkdir) {
11003
- fs87.mkdir(path98.dirname(file), { recursive: true }, (err) => {
11003
+ fs88.mkdir(path98.dirname(file), { recursive: true }, (err) => {
11004
11004
  if (err) return fileOpened(err);
11005
- fs87.open(file, flags, mode, fileOpened);
11005
+ fs88.open(file, flags, mode, fileOpened);
11006
11006
  });
11007
11007
  } else {
11008
- fs87.open(file, flags, mode, fileOpened);
11008
+ fs88.open(file, flags, mode, fileOpened);
11009
11009
  }
11010
11010
  }
11011
11011
  function SonicBoom(opts) {
@@ -11046,8 +11046,8 @@ var require_sonic_boom = __commonJS({
11046
11046
  this.flush = flushBuffer;
11047
11047
  this.flushSync = flushBufferSync;
11048
11048
  this._actualWrite = actualWriteBuffer;
11049
- fsWriteSync = () => fs87.writeSync(this.fd, this._writingBuf);
11050
- fsWrite = () => fs87.write(this.fd, this._writingBuf, this.release);
11049
+ fsWriteSync = () => fs88.writeSync(this.fd, this._writingBuf);
11050
+ fsWrite = () => fs88.write(this.fd, this._writingBuf, this.release);
11051
11051
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
11052
11052
  this._writingBuf = "";
11053
11053
  this.write = write;
@@ -11056,15 +11056,15 @@ var require_sonic_boom = __commonJS({
11056
11056
  this._actualWrite = actualWrite;
11057
11057
  fsWriteSync = () => {
11058
11058
  if (Buffer.isBuffer(this._writingBuf)) {
11059
- return fs87.writeSync(this.fd, this._writingBuf);
11059
+ return fs88.writeSync(this.fd, this._writingBuf);
11060
11060
  }
11061
- return fs87.writeSync(this.fd, this._writingBuf, "utf8");
11061
+ return fs88.writeSync(this.fd, this._writingBuf, "utf8");
11062
11062
  };
11063
11063
  fsWrite = () => {
11064
11064
  if (Buffer.isBuffer(this._writingBuf)) {
11065
- return fs87.write(this.fd, this._writingBuf, this.release);
11065
+ return fs88.write(this.fd, this._writingBuf, this.release);
11066
11066
  }
11067
- return fs87.write(this.fd, this._writingBuf, "utf8", this.release);
11067
+ return fs88.write(this.fd, this._writingBuf, "utf8", this.release);
11068
11068
  };
11069
11069
  } else {
11070
11070
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -11121,7 +11121,7 @@ var require_sonic_boom = __commonJS({
11121
11121
  }
11122
11122
  }
11123
11123
  if (this._fsync) {
11124
- fs87.fsyncSync(this.fd);
11124
+ fs88.fsyncSync(this.fd);
11125
11125
  }
11126
11126
  const len = this._len;
11127
11127
  if (this._reopening) {
@@ -11235,7 +11235,7 @@ var require_sonic_boom = __commonJS({
11235
11235
  const onDrain = () => {
11236
11236
  if (!this._fsync) {
11237
11237
  try {
11238
- fs87.fsync(this.fd, (err) => {
11238
+ fs88.fsync(this.fd, (err) => {
11239
11239
  this._flushPending = false;
11240
11240
  cb(err);
11241
11241
  });
@@ -11337,7 +11337,7 @@ var require_sonic_boom = __commonJS({
11337
11337
  const fd = this.fd;
11338
11338
  this.once("ready", () => {
11339
11339
  if (fd !== this.fd) {
11340
- fs87.close(fd, (err) => {
11340
+ fs88.close(fd, (err) => {
11341
11341
  if (err) {
11342
11342
  return this.emit("error", err);
11343
11343
  }
@@ -11386,7 +11386,7 @@ var require_sonic_boom = __commonJS({
11386
11386
  buf = this._bufs[0];
11387
11387
  }
11388
11388
  try {
11389
- const n = Buffer.isBuffer(buf) ? fs87.writeSync(this.fd, buf) : fs87.writeSync(this.fd, buf, "utf8");
11389
+ const n = Buffer.isBuffer(buf) ? fs88.writeSync(this.fd, buf) : fs88.writeSync(this.fd, buf, "utf8");
11390
11390
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
11391
11391
  buf = releasedBufObj.writingBuf;
11392
11392
  this._len = releasedBufObj.len;
@@ -11402,7 +11402,7 @@ var require_sonic_boom = __commonJS({
11402
11402
  }
11403
11403
  }
11404
11404
  try {
11405
- fs87.fsyncSync(this.fd);
11405
+ fs88.fsyncSync(this.fd);
11406
11406
  } catch {
11407
11407
  }
11408
11408
  }
@@ -11423,7 +11423,7 @@ var require_sonic_boom = __commonJS({
11423
11423
  buf = mergeBuf(this._bufs[0], this._lens[0]);
11424
11424
  }
11425
11425
  try {
11426
- const n = fs87.writeSync(this.fd, buf);
11426
+ const n = fs88.writeSync(this.fd, buf);
11427
11427
  buf = buf.subarray(n);
11428
11428
  this._len = Math.max(this._len - n, 0);
11429
11429
  if (buf.length <= 0) {
@@ -11451,13 +11451,13 @@ var require_sonic_boom = __commonJS({
11451
11451
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
11452
11452
  if (this.sync) {
11453
11453
  try {
11454
- const written = Buffer.isBuffer(this._writingBuf) ? fs87.writeSync(this.fd, this._writingBuf) : fs87.writeSync(this.fd, this._writingBuf, "utf8");
11454
+ const written = Buffer.isBuffer(this._writingBuf) ? fs88.writeSync(this.fd, this._writingBuf) : fs88.writeSync(this.fd, this._writingBuf, "utf8");
11455
11455
  release2(null, written);
11456
11456
  } catch (err) {
11457
11457
  release2(err);
11458
11458
  }
11459
11459
  } else {
11460
- fs87.write(this.fd, this._writingBuf, release2);
11460
+ fs88.write(this.fd, this._writingBuf, release2);
11461
11461
  }
11462
11462
  }
11463
11463
  function actualWriteBuffer() {
@@ -11466,7 +11466,7 @@ var require_sonic_boom = __commonJS({
11466
11466
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
11467
11467
  if (this.sync) {
11468
11468
  try {
11469
- const written = fs87.writeSync(this.fd, this._writingBuf);
11469
+ const written = fs88.writeSync(this.fd, this._writingBuf);
11470
11470
  release2(null, written);
11471
11471
  } catch (err) {
11472
11472
  release2(err);
@@ -11475,7 +11475,7 @@ var require_sonic_boom = __commonJS({
11475
11475
  if (kCopyBuffer) {
11476
11476
  this._writingBuf = Buffer.from(this._writingBuf);
11477
11477
  }
11478
- fs87.write(this.fd, this._writingBuf, release2);
11478
+ fs88.write(this.fd, this._writingBuf, release2);
11479
11479
  }
11480
11480
  }
11481
11481
  function actualClose(sonic) {
@@ -11491,12 +11491,12 @@ var require_sonic_boom = __commonJS({
11491
11491
  sonic._lens = [];
11492
11492
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
11493
11493
  try {
11494
- fs87.fsync(sonic.fd, closeWrapped);
11494
+ fs88.fsync(sonic.fd, closeWrapped);
11495
11495
  } catch {
11496
11496
  }
11497
11497
  function closeWrapped() {
11498
11498
  if (sonic.fd !== 1 && sonic.fd !== 2) {
11499
- fs87.close(sonic.fd, done);
11499
+ fs88.close(sonic.fd, done);
11500
11500
  } else {
11501
11501
  done();
11502
11502
  }
@@ -43954,8 +43954,8 @@ function startRunCaseRecorder(opts) {
43954
43954
  });
43955
43955
  const ensureStream = () => {
43956
43956
  if (stream) return stream;
43957
- import_node_fs59.default.mkdirSync(dir, { recursive: true });
43958
- stream = import_node_fs59.default.createWriteStream(opts.recordPath, { flags: "a" });
43957
+ import_node_fs60.default.mkdirSync(dir, { recursive: true });
43958
+ stream = import_node_fs60.default.createWriteStream(opts.recordPath, { flags: "a" });
43959
43959
  stream.on("close", () => closedResolve());
43960
43960
  return stream;
43961
43961
  };
@@ -43980,11 +43980,11 @@ function startRunCaseRecorder(opts) {
43980
43980
  };
43981
43981
  return { tap, close, closed };
43982
43982
  }
43983
- var import_node_fs59, import_node_path80;
43983
+ var import_node_fs60, import_node_path80;
43984
43984
  var init_recorder = __esm({
43985
43985
  "src/run-case/recorder.ts"() {
43986
43986
  "use strict";
43987
- import_node_fs59 = __toESM(require("fs"), 1);
43987
+ import_node_fs60 = __toESM(require("fs"), 1);
43988
43988
  import_node_path80 = __toESM(require("path"), 1);
43989
43989
  }
43990
43990
  });
@@ -44028,7 +44028,7 @@ var init_wire = __esm({
44028
44028
  // src/run-case/controller.ts
44029
44029
  async function runController(opts) {
44030
44030
  const now = opts.now ?? Date.now;
44031
- const cwd = opts.cwd ?? (0, import_node_fs60.mkdtempSync)(import_node_path81.default.join(import_node_os28.default.tmpdir(), "clawd-runcase-"));
44031
+ const cwd = opts.cwd ?? (0, import_node_fs61.mkdtempSync)(import_node_path81.default.join(import_node_os28.default.tmpdir(), "clawd-runcase-"));
44032
44032
  const ownsCwd = opts.cwd === void 0;
44033
44033
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
44034
44034
  const spawnCtx = { cwd };
@@ -44189,17 +44189,17 @@ async function runController(opts) {
44189
44189
  if (sigintHandler) process.off("SIGINT", sigintHandler);
44190
44190
  if (ownsCwd) {
44191
44191
  try {
44192
- (0, import_node_fs60.rmSync)(cwd, { recursive: true, force: true });
44192
+ (0, import_node_fs61.rmSync)(cwd, { recursive: true, force: true });
44193
44193
  } catch {
44194
44194
  }
44195
44195
  }
44196
44196
  return exitCode ?? 0;
44197
44197
  }
44198
- var import_node_fs60, import_node_os28, import_node_path81;
44198
+ var import_node_fs61, import_node_os28, import_node_path81;
44199
44199
  var init_controller = __esm({
44200
44200
  "src/run-case/controller.ts"() {
44201
44201
  "use strict";
44202
- import_node_fs60 = require("fs");
44202
+ import_node_fs61 = require("fs");
44203
44203
  import_node_os28 = __toESM(require("os"), 1);
44204
44204
  import_node_path81 = __toESM(require("path"), 1);
44205
44205
  init_claude();
@@ -44477,7 +44477,7 @@ Env (advanced):
44477
44477
 
44478
44478
  // src/index.ts
44479
44479
  var import_node_path79 = __toESM(require("path"), 1);
44480
- var import_node_fs58 = __toESM(require("fs"), 1);
44480
+ var import_node_fs59 = __toESM(require("fs"), 1);
44481
44481
  var import_node_os27 = __toESM(require("os"), 1);
44482
44482
  var import_node_crypto22 = require("crypto");
44483
44483
  var import_node_url5 = require("url");
@@ -51298,7 +51298,7 @@ var import_node_fs20 = __toESM(require("fs"), 1);
51298
51298
 
51299
51299
  // src/tools/codex-session.ts
51300
51300
  var import_node_child_process4 = require("child_process");
51301
- var import_node_path17 = __toESM(require("path"), 1);
51301
+ var import_node_path18 = __toESM(require("path"), 1);
51302
51302
 
51303
51303
  // src/tools/codex-app-server-client.ts
51304
51304
  var import_node_readline = require("readline");
@@ -51787,7 +51787,7 @@ function threadStartParams(ctx) {
51787
51787
  }
51788
51788
  var ATTACHMENT_RE2 = /\[attachment:(image|file):([^\]]+)\]/g;
51789
51789
  var SKILL_RE = /\[skill:(.+?):(\/[^\]]+)\]/g;
51790
- function turnStartInput(text) {
51790
+ function turnStartInput(text, resolveImage) {
51791
51791
  const items = [];
51792
51792
  let leftover = text;
51793
51793
  for (const m2 of text.matchAll(SKILL_RE)) {
@@ -51797,8 +51797,10 @@ function turnStartInput(text) {
51797
51797
  }
51798
51798
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
51799
51799
  const [marker, kind, url] = m2;
51800
- if (kind === "image") {
51801
- items.push({ type: "image", url });
51800
+ if (kind !== "image") continue;
51801
+ const item = url.startsWith("data:") ? { type: "image", url } : resolveImage?.(url) ?? null;
51802
+ if (item) {
51803
+ items.push(item);
51802
51804
  leftover = leftover.replace(marker, "");
51803
51805
  }
51804
51806
  }
@@ -51889,11 +51891,17 @@ function driveCodexThread(opts) {
51889
51891
  if (threadId)
51890
51892
  void client.request("turn/start", {
51891
51893
  threadId,
51892
- input: turnStartInput(text),
51894
+ input: turnStartInput(text, opts.imageInput),
51893
51895
  // TurnStartParams 字段是 `effort`(不是 `reasoningEffort`,0.138 改名)——传错名字
51894
51896
  // codex 静默忽略, reasoning effort 改了不生效。"override for this turn and subsequent turns"。
51895
51897
  ...effort ? { effort } : {}
51896
- }).catch((e) => sink.onError(`turn/start failed: ${e.message}`));
51898
+ }).catch((e) => {
51899
+ if (exited) return;
51900
+ sink.pushEvents([
51901
+ { kind: "error", message: `turn/start failed: ${e.message}` },
51902
+ { kind: "turn_end" }
51903
+ ]);
51904
+ });
51897
51905
  });
51898
51906
  },
51899
51907
  respondPermission(requestId, allow) {
@@ -52047,6 +52055,200 @@ function warmCodexFeatureCache() {
52047
52055
  );
52048
52056
  }
52049
52057
 
52058
+ // src/attachment/sign-url.ts
52059
+ var import_node_crypto5 = __toESM(require("crypto"), 1);
52060
+ var HMAC_ALGO = "sha256";
52061
+ function base64urlEncode(buf) {
52062
+ const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
52063
+ return b2.toString("base64url");
52064
+ }
52065
+ function base64urlDecodeBuf(s) {
52066
+ return Buffer.from(s, "base64url");
52067
+ }
52068
+ function encodeAbsPathForUrl(absPath) {
52069
+ return absPath.split("/").map(encodeURIComponent).join("/");
52070
+ }
52071
+ function decodeAbsPathFromUrl(encoded) {
52072
+ return encoded.split("/").map(decodeURIComponent).join("/");
52073
+ }
52074
+ var DOMAIN_PREFIX2 = "clawd-attach-v1|";
52075
+ function computeSig(secret, absPath, e) {
52076
+ const msg = e === null ? `${DOMAIN_PREFIX2}${absPath}` : `${DOMAIN_PREFIX2}${absPath}|${e}`;
52077
+ return import_node_crypto5.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
52078
+ }
52079
+ function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
52080
+ const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
52081
+ const s = base64urlEncode(computeSig(secret, absPath, e));
52082
+ return { absPath, e, s };
52083
+ }
52084
+ function buildSignedFileUrl(httpBaseUrl, parts, prefix = "/files") {
52085
+ const encodedPath = encodeAbsPathForUrl(parts.absPath);
52086
+ const query = parts.e === null ? `s=${encodeURIComponent(parts.s)}` : `e=${parts.e}&s=${encodeURIComponent(parts.s)}`;
52087
+ const base = httpBaseUrl.endsWith("/") ? httpBaseUrl.slice(0, -1) : httpBaseUrl;
52088
+ return `${base}${prefix}${encodedPath}?${query}`;
52089
+ }
52090
+ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
52091
+ let e;
52092
+ if (eRaw === null || eRaw === void 0 || eRaw === "") {
52093
+ e = null;
52094
+ } else {
52095
+ const parsed = Number.parseInt(eRaw, 10);
52096
+ if (!Number.isFinite(parsed) || parsed < 0) {
52097
+ return { ok: false, code: "MALFORMED" };
52098
+ }
52099
+ e = parsed;
52100
+ }
52101
+ if (!absPath || !s) return { ok: false, code: "MALFORMED" };
52102
+ const expected = computeSig(secret, absPath, e);
52103
+ let provided;
52104
+ try {
52105
+ provided = base64urlDecodeBuf(s);
52106
+ } catch {
52107
+ return { ok: false, code: "MALFORMED" };
52108
+ }
52109
+ if (provided.length !== expected.length) {
52110
+ return { ok: false, code: "BAD_SIG" };
52111
+ }
52112
+ if (!import_node_crypto5.default.timingSafeEqual(provided, expected)) {
52113
+ return { ok: false, code: "BAD_SIG" };
52114
+ }
52115
+ if (e !== null && now() / 1e3 > e) {
52116
+ return { ok: false, code: "EXPIRED" };
52117
+ }
52118
+ return { ok: true, absPath };
52119
+ }
52120
+ function resolveSignedFileUrl(secret, url, now = Date.now) {
52121
+ let u;
52122
+ try {
52123
+ u = new URL(url);
52124
+ } catch {
52125
+ return null;
52126
+ }
52127
+ if (!u.pathname.startsWith("/files/")) return null;
52128
+ let absPath;
52129
+ try {
52130
+ absPath = decodeAbsPathFromUrl(u.pathname.slice("/files".length));
52131
+ } catch {
52132
+ return null;
52133
+ }
52134
+ const r = verifySignedUrl(secret, absPath, u.searchParams.get("e"), u.searchParams.get("s") ?? "", now);
52135
+ return r.ok ? r.absPath : null;
52136
+ }
52137
+
52138
+ // src/attachment/mime.ts
52139
+ var import_node_path17 = __toESM(require("path"), 1);
52140
+ var TEXT_PLAIN = "text/plain; charset=utf-8";
52141
+ var EXT_TO_NATIVE_MIME = {
52142
+ // 图片
52143
+ ".png": "image/png",
52144
+ ".jpg": "image/jpeg",
52145
+ ".jpeg": "image/jpeg",
52146
+ ".gif": "image/gif",
52147
+ ".webp": "image/webp",
52148
+ ".svg": "image/svg+xml",
52149
+ ".bmp": "image/bmp",
52150
+ ".ico": "image/x-icon",
52151
+ ".avif": "image/avif",
52152
+ // 文档 / 富文本
52153
+ ".pdf": "application/pdf",
52154
+ ".html": "text/html; charset=utf-8",
52155
+ ".htm": "text/html; charset=utf-8",
52156
+ // 视频 / 音频
52157
+ ".mp4": "video/mp4",
52158
+ ".webm": "video/webm",
52159
+ ".mov": "video/quicktime",
52160
+ ".mp3": "audio/mpeg",
52161
+ ".wav": "audio/wav",
52162
+ ".ogg": "audio/ogg",
52163
+ ".flac": "audio/flac",
52164
+ // 真二进制(让浏览器下载而不是错把它当文本明文)
52165
+ ".zip": "application/zip",
52166
+ ".gz": "application/gzip",
52167
+ ".tar": "application/x-tar",
52168
+ ".7z": "application/x-7z-compressed",
52169
+ ".rar": "application/x-rar-compressed"
52170
+ };
52171
+ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
52172
+ // 文档
52173
+ ".md",
52174
+ ".markdown",
52175
+ ".rst",
52176
+ ".adoc",
52177
+ ".txt",
52178
+ ".log",
52179
+ // 通用结构化
52180
+ ".json",
52181
+ ".jsonc",
52182
+ ".json5",
52183
+ ".yaml",
52184
+ ".yml",
52185
+ ".toml",
52186
+ ".xml",
52187
+ ".csv",
52188
+ ".tsv",
52189
+ ".ini",
52190
+ ".conf",
52191
+ ".cfg",
52192
+ ".env",
52193
+ // 前端
52194
+ ".js",
52195
+ ".jsx",
52196
+ ".mjs",
52197
+ ".cjs",
52198
+ ".ts",
52199
+ ".tsx",
52200
+ ".css",
52201
+ ".scss",
52202
+ ".sass",
52203
+ ".less",
52204
+ ".vue",
52205
+ ".svelte",
52206
+ ".graphql",
52207
+ ".gql",
52208
+ // 后端 / 各语言
52209
+ ".py",
52210
+ ".rb",
52211
+ ".go",
52212
+ ".rs",
52213
+ ".java",
52214
+ ".kt",
52215
+ ".kts",
52216
+ ".scala",
52217
+ ".c",
52218
+ ".h",
52219
+ ".cpp",
52220
+ ".hpp",
52221
+ ".cc",
52222
+ ".hh",
52223
+ ".cs",
52224
+ ".php",
52225
+ ".swift",
52226
+ ".m",
52227
+ ".mm",
52228
+ ".dart",
52229
+ ".lua",
52230
+ ".pl",
52231
+ ".r",
52232
+ ".sh",
52233
+ ".bash",
52234
+ ".zsh",
52235
+ ".fish",
52236
+ // 其他
52237
+ ".sql",
52238
+ ".proto",
52239
+ ".dockerfile",
52240
+ ".diff",
52241
+ ".patch",
52242
+ ".makefile",
52243
+ ".mk"
52244
+ ]);
52245
+ function lookupMime(filePathOrName) {
52246
+ const ext = import_node_path17.default.extname(filePathOrName).toLowerCase();
52247
+ if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
52248
+ if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
52249
+ return "application/octet-stream";
52250
+ }
52251
+
52050
52252
  // src/tools/codex-session.ts
52051
52253
  function createCodexSession(ctx, sink, deps = {}) {
52052
52254
  const cmd = process.env.CODEX_BIN ?? "codex";
@@ -52089,7 +52291,15 @@ function createCodexSession(ctx, sink, deps = {}) {
52089
52291
  threadParams: threadStartParams(ctx),
52090
52292
  // persona 惯例装在 <cwd>/.claude/skills/,经 extraRoots 注入 discovery
52091
52293
  // (skills:list RPC 侧 codex-skills.ts 同款注入,两处保持一致)。
52092
- skillsExtraRoots: [import_node_path17.default.join(ctx.cwd, ".claude", "skills")],
52294
+ skillsExtraRoots: [import_node_path18.default.join(ctx.cwd, ".claude", "skills")],
52295
+ // 附件图片:验签认出本机 absPath → localImage,codex 自己读文件(TUI 拖图 / SDK local_image 同一条路)。
52296
+ // 0.145 起 http(s) URL 在 turn/start 入口被拒,不能再按 url 传(codex-app-server-params.ts 头注释)。
52297
+ // 与云上 cloudImageInput 同一道 mime 门:非图片(签过的 .md 之类)留文本,别让 codex 读到一半才炸。
52298
+ imageInput: (url) => {
52299
+ const secret = deps.getSignSecret?.();
52300
+ const p2 = secret ? resolveSignedFileUrl(secret, url) : null;
52301
+ return p2 && lookupMime(p2).startsWith("image/") ? { type: "localImage", path: p2 } : null;
52302
+ },
52093
52303
  kill: (signal) => {
52094
52304
  if (alive()) proc.kill(signal);
52095
52305
  },
@@ -52236,14 +52446,14 @@ function mergeProviderModels(native, provider) {
52236
52446
  // src/tools/codex-provider-models.ts
52237
52447
  var import_node_fs19 = __toESM(require("fs"), 1);
52238
52448
  var import_node_os8 = __toESM(require("os"), 1);
52239
- var import_node_path18 = __toESM(require("path"), 1);
52449
+ var import_node_path19 = __toESM(require("path"), 1);
52240
52450
  var PROVIDER_FETCH_TIMEOUT_MS = 3e3;
52241
52451
  function asRecord(v2) {
52242
52452
  return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : null;
52243
52453
  }
52244
52454
  function readAuthKey(codexHome) {
52245
52455
  try {
52246
- const raw = JSON.parse(import_node_fs19.default.readFileSync(import_node_path18.default.join(codexHome, "auth.json"), "utf8"));
52456
+ const raw = JSON.parse(import_node_fs19.default.readFileSync(import_node_path19.default.join(codexHome, "auth.json"), "utf8"));
52247
52457
  const key = asRecord(raw)?.OPENAI_API_KEY;
52248
52458
  return typeof key === "string" && key ? key : void 0;
52249
52459
  } catch {
@@ -52260,7 +52470,7 @@ function resolveProviderEndpoint(rawConfig, deps = {}) {
52260
52470
  const baseUrl = entry.base_url;
52261
52471
  if (typeof baseUrl !== "string" || !baseUrl) return null;
52262
52472
  const env = deps.env ?? process.env;
52263
- const codexHome = deps.codexHome ?? env.CODEX_HOME ?? import_node_path18.default.join(import_node_os8.default.homedir(), ".codex");
52473
+ const codexHome = deps.codexHome ?? env.CODEX_HOME ?? import_node_path19.default.join(import_node_os8.default.homedir(), ".codex");
52264
52474
  const envKey = typeof entry.env_key === "string" && entry.env_key ? entry.env_key : null;
52265
52475
  const token = envKey ? env[envKey] : readAuthKey(codexHome);
52266
52476
  if (!token) {
@@ -52393,6 +52603,7 @@ var CodexAdapter = class {
52393
52603
  fetchImpl;
52394
52604
  /** CODEX_HOME 归属解析(spec 2026-08-18-codex-project-alignment §3.1),由 index.ts 注入 */
52395
52605
  codexHomeFor;
52606
+ getSignSecret;
52396
52607
  // capabilities 的进程级 memo。**回落结果同样被缓存**——否则 codex 没装时每次开弹窗都
52397
52608
  // spawn 一次必然失败的子进程。代价是装好 codex 后要重启 daemon 才恢复,与「codex 升级后
52398
52609
  // 要重启才更新模型表」是同一条语义。
@@ -52405,6 +52616,7 @@ var CodexAdapter = class {
52405
52616
  this.configQueryOverride = opts.configQueryOverride;
52406
52617
  this.fetchImpl = opts.fetchImpl;
52407
52618
  this.codexHomeFor = opts.codexHomeFor;
52619
+ this.getSignSecret = opts.getSignSecret;
52408
52620
  }
52409
52621
  async probe() {
52410
52622
  if (this.probeCache) return this.probeCache;
@@ -52467,7 +52679,8 @@ var CodexAdapter = class {
52467
52679
  createSession(ctx, sink) {
52468
52680
  return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, {
52469
52681
  logger: this.logger,
52470
- codexHomeFor: this.codexHomeFor
52682
+ codexHomeFor: this.codexHomeFor,
52683
+ getSignSecret: this.getSignSecret
52471
52684
  });
52472
52685
  }
52473
52686
  spawn(_ctx) {
@@ -52484,10 +52697,10 @@ var CodexAdapter = class {
52484
52697
  };
52485
52698
 
52486
52699
  // src/tools/claude-tui.ts
52487
- var import_node_crypto5 = require("crypto");
52700
+ var import_node_crypto6 = require("crypto");
52488
52701
  var import_node_fs21 = __toESM(require("fs"), 1);
52489
52702
  var import_node_os9 = __toESM(require("os"), 1);
52490
- var import_node_path19 = __toESM(require("path"), 1);
52703
+ var import_node_path20 = __toESM(require("path"), 1);
52491
52704
  var import_headless = __toESM(require_xterm_headless(), 1);
52492
52705
 
52493
52706
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -53372,7 +53585,7 @@ function observeScreenIdle(surface, opts) {
53372
53585
  };
53373
53586
  }
53374
53587
  function shortHash(s) {
53375
- return (0, import_node_crypto5.createHash)("sha1").update(s).digest("hex").slice(0, 8);
53588
+ return (0, import_node_crypto6.createHash)("sha1").update(s).digest("hex").slice(0, 8);
53376
53589
  }
53377
53590
  function firstLineDiff(prev, next) {
53378
53591
  const p2 = prev.split("\n");
@@ -53713,7 +53926,7 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
53713
53926
  function jsonlExistsForCtx(ctx) {
53714
53927
  if (!ctx.toolSessionId) return false;
53715
53928
  const home = import_node_os9.default.homedir();
53716
- const file = import_node_path19.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
53929
+ const file = import_node_path20.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
53717
53930
  try {
53718
53931
  return import_node_fs21.default.statSync(file).isFile();
53719
53932
  } catch {
@@ -53800,7 +54013,7 @@ var PersonaDispatchManager = class {
53800
54013
 
53801
54014
  // src/dispatch/store.ts
53802
54015
  var import_promises = __toESM(require("fs/promises"), 1);
53803
- var import_node_path20 = __toESM(require("path"), 1);
54016
+ var import_node_path21 = __toESM(require("path"), 1);
53804
54017
 
53805
54018
  // src/shift/constants.ts
53806
54019
  var MAX_RUNS_PER_SHIFT = 30;
@@ -53838,7 +54051,7 @@ function createDispatchStore(deps) {
53838
54051
  flushTimer = null;
53839
54052
  }
53840
54053
  const content = { version: 1, records };
53841
- await import_promises.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
54054
+ await import_promises.default.mkdir(import_node_path21.default.dirname(deps.filePath), { recursive: true });
53842
54055
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53843
54056
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53844
54057
  await import_promises.default.rename(tmp, deps.filePath);
@@ -53907,7 +54120,7 @@ function createDispatchStore(deps) {
53907
54120
 
53908
54121
  // src/channel/json-store.ts
53909
54122
  var import_promises2 = __toESM(require("fs/promises"), 1);
53910
- var import_node_path21 = __toESM(require("path"), 1);
54123
+ var import_node_path22 = __toESM(require("path"), 1);
53911
54124
  function createJsonStore(deps) {
53912
54125
  let items = [];
53913
54126
  let flushTimer = null;
@@ -53918,7 +54131,7 @@ function createJsonStore(deps) {
53918
54131
  flushTimer = null;
53919
54132
  }
53920
54133
  const content = { version: version2, [deps.key]: items };
53921
- await import_promises2.default.mkdir(import_node_path21.default.dirname(deps.filePath), { recursive: true });
54134
+ await import_promises2.default.mkdir(import_node_path22.default.dirname(deps.filePath), { recursive: true });
53922
54135
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53923
54136
  await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53924
54137
  await import_promises2.default.rename(tmp, deps.filePath);
@@ -54211,9 +54424,9 @@ function createTopicStore(deps) {
54211
54424
 
54212
54425
  // src/dispatch/mcp-config.ts
54213
54426
  var import_node_fs22 = __toESM(require("fs"), 1);
54214
- var import_node_path22 = __toESM(require("path"), 1);
54427
+ var import_node_path23 = __toESM(require("path"), 1);
54215
54428
  function dispatchMcpConfigPath(dataDir) {
54216
- return import_node_path22.default.join(dataDir, "dispatch.mcp.json");
54429
+ return import_node_path23.default.join(dataDir, "dispatch.mcp.json");
54217
54430
  }
54218
54431
  function writeDispatchMcpConfig(args) {
54219
54432
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -54239,9 +54452,9 @@ function writeDispatchMcpConfig(args) {
54239
54452
 
54240
54453
  // src/ticket/mcp-config.ts
54241
54454
  var import_node_fs23 = __toESM(require("fs"), 1);
54242
- var import_node_path23 = __toESM(require("path"), 1);
54455
+ var import_node_path24 = __toESM(require("path"), 1);
54243
54456
  function ticketMcpConfigPath(dataDir) {
54244
- return import_node_path23.default.join(dataDir, "ticket.mcp.json");
54457
+ return import_node_path24.default.join(dataDir, "ticket.mcp.json");
54245
54458
  }
54246
54459
  function writeTicketMcpConfig(args) {
54247
54460
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -54270,9 +54483,9 @@ function writeTicketMcpConfig(args) {
54270
54483
 
54271
54484
  // src/shift/mcp-config.ts
54272
54485
  var import_node_fs24 = __toESM(require("fs"), 1);
54273
- var import_node_path24 = __toESM(require("path"), 1);
54486
+ var import_node_path25 = __toESM(require("path"), 1);
54274
54487
  function shiftMcpConfigPath(dataDir) {
54275
- return import_node_path24.default.join(dataDir, "shift.mcp.json");
54488
+ return import_node_path25.default.join(dataDir, "shift.mcp.json");
54276
54489
  }
54277
54490
  async function writeShiftMcpConfig(args) {
54278
54491
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -54298,9 +54511,9 @@ async function writeShiftMcpConfig(args) {
54298
54511
 
54299
54512
  // src/inbox/mcp-config.ts
54300
54513
  var import_node_fs25 = __toESM(require("fs"), 1);
54301
- var import_node_path25 = __toESM(require("path"), 1);
54514
+ var import_node_path26 = __toESM(require("path"), 1);
54302
54515
  function inboxMcpConfigPath(dataDir) {
54303
- return import_node_path25.default.join(dataDir, "inbox.mcp.json");
54516
+ return import_node_path26.default.join(dataDir, "inbox.mcp.json");
54304
54517
  }
54305
54518
  async function writeInboxMcpConfig(args) {
54306
54519
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -54326,9 +54539,9 @@ async function writeInboxMcpConfig(args) {
54326
54539
 
54327
54540
  // src/peer-ops/mcp-config.ts
54328
54541
  var import_node_fs26 = __toESM(require("fs"), 1);
54329
- var import_node_path26 = __toESM(require("path"), 1);
54542
+ var import_node_path27 = __toESM(require("path"), 1);
54330
54543
  function peerOpsMcpConfigPath(dataDir) {
54331
- return import_node_path26.default.join(dataDir, "peer-ops.mcp.json");
54544
+ return import_node_path27.default.join(dataDir, "peer-ops.mcp.json");
54332
54545
  }
54333
54546
  function writePeerOpsMcpConfig(args) {
54334
54547
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -54352,9 +54565,9 @@ function writePeerOpsMcpConfig(args) {
54352
54565
 
54353
54566
  // src/rpc-tool/mcp-config.ts
54354
54567
  var import_node_fs27 = __toESM(require("fs"), 1);
54355
- var import_node_path27 = __toESM(require("path"), 1);
54568
+ var import_node_path28 = __toESM(require("path"), 1);
54356
54569
  function rpcToolMcpConfigPath(dataDir) {
54357
- return import_node_path27.default.join(dataDir, "rpc-tool.mcp.json");
54570
+ return import_node_path28.default.join(dataDir, "rpc-tool.mcp.json");
54358
54571
  }
54359
54572
  function writeRpcToolMcpConfig(args) {
54360
54573
  const cfgPath = rpcToolMcpConfigPath(args.dataDir);
@@ -54380,15 +54593,15 @@ function writeRpcToolMcpConfig(args) {
54380
54593
 
54381
54594
  // src/deploy/secret-table.ts
54382
54595
  var import_node_fs28 = __toESM(require("fs"), 1);
54383
- var import_node_path28 = __toESM(require("path"), 1);
54596
+ var import_node_path29 = __toESM(require("path"), 1);
54384
54597
  var import_node_url4 = require("url");
54385
54598
  var import_meta4 = {};
54386
54599
  var LOCAL_SECRETS_DIRNAME = "secrets";
54387
54600
  function findSecretsBundleRoot(logger) {
54388
54601
  const candidates = [];
54389
54602
  try {
54390
- const here = import_node_path28.default.dirname((0, import_node_url4.fileURLToPath)(import_meta4.url));
54391
- candidates.push(import_node_path28.default.resolve(here, "..", "secrets"));
54603
+ const here = import_node_path29.default.dirname((0, import_node_url4.fileURLToPath)(import_meta4.url));
54604
+ candidates.push(import_node_path29.default.resolve(here, "..", "secrets"));
54392
54605
  } catch {
54393
54606
  }
54394
54607
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "secrets");
@@ -54429,9 +54642,9 @@ function readDir(dir, logger) {
54429
54642
  }
54430
54643
  for (const f of files) {
54431
54644
  try {
54432
- Object.assign(out, parseEnvFile(import_node_fs28.default.readFileSync(import_node_path28.default.join(dir, f), "utf8")));
54645
+ Object.assign(out, parseEnvFile(import_node_fs28.default.readFileSync(import_node_path29.default.join(dir, f), "utf8")));
54433
54646
  } catch (e) {
54434
- logger?.warn("secrets.file-unreadable", { file: import_node_path28.default.join(dir, f), error: e.message });
54647
+ logger?.warn("secrets.file-unreadable", { file: import_node_path29.default.join(dir, f), error: e.message });
54435
54648
  }
54436
54649
  }
54437
54650
  return out;
@@ -54457,14 +54670,14 @@ function collectKitPlaceholders(kitDir) {
54457
54670
  }
54458
54671
  return entries.flatMap((e) => {
54459
54672
  if (e.name === "node_modules") return [];
54460
- const p2 = import_node_path28.default.join(dir, e.name);
54673
+ const p2 = import_node_path29.default.join(dir, e.name);
54461
54674
  return e.isDirectory() ? walk2(p2, depth + 1) : [p2];
54462
54675
  });
54463
54676
  };
54464
- for (const f of walk2(import_node_path28.default.join(kitDir, "contract"), 0)) {
54677
+ for (const f of walk2(import_node_path29.default.join(kitDir, "contract"), 0)) {
54465
54678
  if (f.endsWith(".tmpl")) scan(f, /__([A-Z0-9_]+)__/g);
54466
54679
  }
54467
- for (const f of walk2(import_node_path28.default.join(kitDir, "examples"), 0)) {
54680
+ for (const f of walk2(import_node_path29.default.join(kitDir, "examples"), 0)) {
54468
54681
  if (f.endsWith(".env.example")) scan(f, /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g);
54469
54682
  }
54470
54683
  return out;
@@ -54482,12 +54695,12 @@ function readSecretTable(args) {
54482
54695
  }
54483
54696
 
54484
54697
  // src/dispatch/source-transcript.ts
54485
- var import_node_path29 = __toESM(require("path"), 1);
54698
+ var import_node_path30 = __toESM(require("path"), 1);
54486
54699
  init_claude_history();
54487
54700
  var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
54488
54701
  function resolveSourceJsonlPath(sourceFile, home) {
54489
54702
  if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
54490
- return import_node_path29.default.join(
54703
+ return import_node_path30.default.join(
54491
54704
  home,
54492
54705
  ".claude",
54493
54706
  "projects",
@@ -54498,8 +54711,8 @@ function resolveSourceJsonlPath(sourceFile, home) {
54498
54711
 
54499
54712
  // src/shift/store.ts
54500
54713
  var import_promises3 = __toESM(require("fs/promises"), 1);
54501
- var import_node_path30 = __toESM(require("path"), 1);
54502
- var import_node_crypto6 = require("crypto");
54714
+ var import_node_path31 = __toESM(require("path"), 1);
54715
+ var import_node_crypto7 = require("crypto");
54503
54716
 
54504
54717
  // src/shift/schedule.ts
54505
54718
  var import_cron_parser = __toESM(require_dist(), 1);
@@ -54573,7 +54786,7 @@ function createShiftStore(deps) {
54573
54786
  flushTimer = null;
54574
54787
  }
54575
54788
  const content = { version: 1, shifts };
54576
- await import_promises3.default.mkdir(import_node_path30.default.dirname(deps.filePath), { recursive: true });
54789
+ await import_promises3.default.mkdir(import_node_path31.default.dirname(deps.filePath), { recursive: true });
54577
54790
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
54578
54791
  await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
54579
54792
  await import_promises3.default.rename(tmp, deps.filePath);
@@ -54603,7 +54816,7 @@ function createShiftStore(deps) {
54603
54816
  const shift = {
54604
54817
  ...input,
54605
54818
  schedule,
54606
- id: (0, import_node_crypto6.randomUUID)(),
54819
+ id: (0, import_node_crypto7.randomUUID)(),
54607
54820
  createdAtMs: now,
54608
54821
  updatedAtMs: now,
54609
54822
  state: { nextRunAtMs },
@@ -55021,10 +55234,10 @@ function redactEvidence(evidence) {
55021
55234
 
55022
55235
  // src/deploy/deploy-file.ts
55023
55236
  var import_promises4 = __toESM(require("fs/promises"), 1);
55024
- var import_node_path31 = __toESM(require("path"), 1);
55237
+ var import_node_path32 = __toESM(require("path"), 1);
55025
55238
  init_protocol();
55026
- var DEPLOY_FILE = import_node_path31.default.join(".clawd", "deploy.json");
55027
- var SCAN_FILE = import_node_path31.default.join(".clawd", "deploy-scan.json");
55239
+ var DEPLOY_FILE = import_node_path32.default.join(".clawd", "deploy.json");
55240
+ var SCAN_FILE = import_node_path32.default.join(".clawd", "deploy-scan.json");
55028
55241
  async function readJson(file) {
55029
55242
  let raw;
55030
55243
  try {
@@ -55040,14 +55253,14 @@ async function readJson(file) {
55040
55253
  }
55041
55254
  }
55042
55255
  async function writeJson(file, value) {
55043
- await import_promises4.default.mkdir(import_node_path31.default.dirname(file), { recursive: true });
55256
+ await import_promises4.default.mkdir(import_node_path32.default.dirname(file), { recursive: true });
55044
55257
  const tmp = `${file}.tmp-${process.pid}`;
55045
55258
  await import_promises4.default.writeFile(tmp, `${JSON.stringify(value, null, 2)}
55046
55259
  `);
55047
55260
  await import_promises4.default.rename(tmp, file);
55048
55261
  }
55049
55262
  async function readDeployFile(dir) {
55050
- const raw = await readJson(import_node_path31.default.join(dir, DEPLOY_FILE));
55263
+ const raw = await readJson(import_node_path32.default.join(dir, DEPLOY_FILE));
55051
55264
  if (raw === void 0) return void 0;
55052
55265
  const parsed = DeployFileSchema.safeParse(raw);
55053
55266
  if (!parsed.success) {
@@ -55057,10 +55270,10 @@ async function readDeployFile(dir) {
55057
55270
  return parsed.data;
55058
55271
  }
55059
55272
  async function writeDeployFile(dir, file) {
55060
- await writeJson(import_node_path31.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
55273
+ await writeJson(import_node_path32.default.join(dir, DEPLOY_FILE), DeployFileSchema.parse(file));
55061
55274
  }
55062
55275
  async function readScan(dir) {
55063
- const raw = await readJson(import_node_path31.default.join(dir, SCAN_FILE));
55276
+ const raw = await readJson(import_node_path32.default.join(dir, SCAN_FILE));
55064
55277
  if (raw === void 0) return void 0;
55065
55278
  const parsed = DeployScanSchema.safeParse(raw);
55066
55279
  if (!parsed.success) {
@@ -55070,7 +55283,7 @@ async function readScan(dir) {
55070
55283
  return parsed.data;
55071
55284
  }
55072
55285
  async function writeScan(dir, scan) {
55073
- await writeJson(import_node_path31.default.join(dir, SCAN_FILE), DeployScanSchema.parse(scan));
55286
+ await writeJson(import_node_path32.default.join(dir, SCAN_FILE), DeployScanSchema.parse(scan));
55074
55287
  }
55075
55288
  function emptyDeployFile() {
55076
55289
  return { version: 1, manifest: { version: 1, clis: [], secrets: [], assets: [], connectors: [] } };
@@ -55110,7 +55323,7 @@ function requiredEnvNames(file) {
55110
55323
  // src/deploy/repo.ts
55111
55324
  var import_node_child_process8 = require("child_process");
55112
55325
  var import_promises5 = __toESM(require("fs/promises"), 1);
55113
- var import_node_path32 = __toESM(require("path"), 1);
55326
+ var import_node_path33 = __toESM(require("path"), 1);
55114
55327
  init_protocol();
55115
55328
 
55116
55329
  // src/deploy/templates.ts
@@ -55344,7 +55557,7 @@ var L = [
55344
55557
  var WORKFLOW_TEMPLATE = L.join("\n");
55345
55558
 
55346
55559
  // src/deploy/repo.ts
55347
- var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path32.default.sep).join("/");
55560
+ var DEPLOY_FILE_REL = DEPLOY_FILE.split(import_node_path33.default.sep).join("/");
55348
55561
  var DEFAULT_TIMEOUT_MS3 = 6e4;
55349
55562
  var runCommand = (cmd, args, opts = {}) => new Promise((resolve9) => {
55350
55563
  const child = (0, import_node_child_process8.spawn)(cmd, args, {
@@ -55411,7 +55624,7 @@ async function samePath(a, b2) {
55411
55624
  try {
55412
55625
  return await import_promises5.default.realpath(x);
55413
55626
  } catch {
55414
- return import_node_path32.default.resolve(x);
55627
+ return import_node_path33.default.resolve(x);
55415
55628
  }
55416
55629
  };
55417
55630
  return await real(a) === await real(b2);
@@ -55437,7 +55650,7 @@ async function identityArgs(exec, dir) {
55437
55650
  return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
55438
55651
  }
55439
55652
  async function writeTemplates(dir) {
55440
- const gi = import_node_path32.default.join(dir, ".gitignore");
55653
+ const gi = import_node_path33.default.join(dir, ".gitignore");
55441
55654
  let existing;
55442
55655
  try {
55443
55656
  existing = await import_promises5.default.readFile(gi, "utf8");
@@ -55445,8 +55658,8 @@ async function writeTemplates(dir) {
55445
55658
  existing = void 0;
55446
55659
  }
55447
55660
  await import_promises5.default.writeFile(gi, mergeGitignore(existing));
55448
- const wf = import_node_path32.default.join(dir, WORKFLOW_PATH);
55449
- await import_promises5.default.mkdir(import_node_path32.default.dirname(wf), { recursive: true });
55661
+ const wf = import_node_path33.default.join(dir, WORKFLOW_PATH);
55662
+ await import_promises5.default.mkdir(import_node_path33.default.dirname(wf), { recursive: true });
55450
55663
  await import_promises5.default.writeFile(wf, WORKFLOW_TEMPLATE);
55451
55664
  }
55452
55665
  async function ensureRepo(exec, args) {
@@ -55636,12 +55849,12 @@ async function rerunJob(exec, slug, runId, jobId) {
55636
55849
  }
55637
55850
 
55638
55851
  // src/deploy/scan-task.ts
55639
- var import_node_path33 = __toESM(require("path"), 1);
55852
+ var import_node_path34 = __toESM(require("path"), 1);
55640
55853
  var BUTLER_PERSONA_ID = "persona-clawd-butler";
55641
55854
  var SCANNABLE_ASSETS = [
55642
55855
  {
55643
55856
  name: "deploy-kit",
55644
- path: (dataDir) => import_node_path33.default.join(dataDir, "deploy-kit"),
55857
+ path: (dataDir) => import_node_path34.default.join(dataDir, "deploy-kit"),
55645
55858
  what: "FC \u90E8\u7F72\u80FD\u529B\uFF08publish.sh / new-extension.sh / \u5DE5\u5177\u94FE / \u51ED\u8BC1\u76EE\u5F55\uFF09\u3002persona \u7528\u7EDD\u5BF9\u8DEF\u5F84\u53BB\u8C03\u8FD9\u91CC\u7684\u811A\u672C\u65F6\uFF0C\u5C31\u8BE5\u62A5\u4E00\u6761 asset\u3002"
55646
55859
  },
55647
55860
  {
@@ -56375,9 +56588,9 @@ async function refreshTunnelUrlOnStartup(deps) {
56375
56588
 
56376
56589
  // src/lark-bot-connector/binding-store.ts
56377
56590
  var import_node_fs29 = __toESM(require("fs"), 1);
56378
- var import_node_path34 = __toESM(require("path"), 1);
56591
+ var import_node_path35 = __toESM(require("path"), 1);
56379
56592
  function createLarkBotBindingStore(personaRoot) {
56380
- const filePath = (personaId2) => import_node_path34.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56593
+ const filePath = (personaId2) => import_node_path35.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
56381
56594
  const read = (personaId2) => {
56382
56595
  const file = filePath(personaId2);
56383
56596
  if (!import_node_fs29.default.existsSync(file)) return null;
@@ -56391,7 +56604,7 @@ function createLarkBotBindingStore(personaRoot) {
56391
56604
  };
56392
56605
  const write = (personaId2, meta) => {
56393
56606
  const file = filePath(personaId2);
56394
- import_node_fs29.default.mkdirSync(import_node_path34.default.dirname(file), { recursive: true });
56607
+ import_node_fs29.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
56395
56608
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
56396
56609
  import_node_fs29.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
56397
56610
  import_node_fs29.default.renameSync(tmp, file);
@@ -56559,7 +56772,7 @@ function createLarkBotCloudClient(opts) {
56559
56772
 
56560
56773
  // src/lark-bot-connector/chat-router.ts
56561
56774
  var import_node_fs30 = __toESM(require("fs"), 1);
56562
- var import_node_path35 = __toESM(require("path"), 1);
56775
+ var import_node_path36 = __toESM(require("path"), 1);
56563
56776
  init_protocol();
56564
56777
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
56565
56778
  var LOCAL_TURN_RETRIES = 2;
@@ -56638,7 +56851,7 @@ function createLarkChatRouter(deps) {
56638
56851
  }
56639
56852
  const dir = deps.mediaRootFor(env.chatId);
56640
56853
  import_node_fs30.default.mkdirSync(dir, { recursive: true });
56641
- const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56854
+ const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
56642
56855
  import_node_fs30.default.writeFileSync(p2, r.data);
56643
56856
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56644
56857
  } catch (err) {
@@ -56661,7 +56874,7 @@ function createLarkChatRouter(deps) {
56661
56874
  }
56662
56875
  const dir = deps.mediaRootFor(env.chatId);
56663
56876
  import_node_fs30.default.mkdirSync(dir, { recursive: true });
56664
- const p2 = import_node_path35.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56877
+ const p2 = import_node_path36.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
56665
56878
  import_node_fs30.default.writeFileSync(p2, r.data);
56666
56879
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56667
56880
  } catch (err) {
@@ -56876,7 +57089,7 @@ ${formatLarkSpeakerReminder(speaker)}`
56876
57089
  }
56877
57090
 
56878
57091
  // src/lark-bot-connector/envelope.ts
56879
- var import_node_crypto7 = require("crypto");
57092
+ var import_node_crypto8 = require("crypto");
56880
57093
  var LARK_ENVELOPE_PREFIX = "clawdlbe1";
56881
57094
  function verifyLarkEventEnvelope(args) {
56882
57095
  const { token, publicKeyPem } = args;
@@ -56895,7 +57108,7 @@ function verifyLarkEventEnvelope(args) {
56895
57108
  const data = Buffer.from(`${prefix}.${payloadB64}`, "utf8");
56896
57109
  let sigOk = false;
56897
57110
  try {
56898
- sigOk = (0, import_node_crypto7.verify)(null, data, publicKeyPem, Buffer.from(sigB64, "base64url"));
57111
+ sigOk = (0, import_node_crypto8.verify)(null, data, publicKeyPem, Buffer.from(sigB64, "base64url"));
56899
57112
  } catch {
56900
57113
  sigOk = false;
56901
57114
  }
@@ -57488,11 +57701,11 @@ async function forwardPeerExecToPeer(args) {
57488
57701
 
57489
57702
  // src/tools/codex-history.ts
57490
57703
  var import_node_fs32 = __toESM(require("fs"), 1);
57491
- var import_node_path37 = __toESM(require("path"), 1);
57704
+ var import_node_path38 = __toESM(require("path"), 1);
57492
57705
 
57493
57706
  // src/tools/transcript-search.ts
57494
57707
  var import_node_fs31 = __toESM(require("fs"), 1);
57495
- var import_node_path36 = __toESM(require("path"), 1);
57708
+ var import_node_path37 = __toESM(require("path"), 1);
57496
57709
  var SNIPPET_PAD = 60;
57497
57710
  var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
57498
57711
  var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
@@ -57585,7 +57798,7 @@ function createCodexRolloutLocator(roots) {
57585
57798
  return;
57586
57799
  }
57587
57800
  for (const entry of entries) {
57588
- const full = import_node_path36.default.join(dir, entry.name);
57801
+ const full = import_node_path37.default.join(dir, entry.name);
57589
57802
  if (entry.isDirectory()) {
57590
57803
  walk2(full, into);
57591
57804
  continue;
@@ -57865,7 +58078,7 @@ function readThreadNames(sharedHome) {
57865
58078
  if (!sharedHome) return names;
57866
58079
  let raw;
57867
58080
  try {
57868
- raw = import_node_fs32.default.readFileSync(import_node_path37.default.join(sharedHome, "session_index.jsonl"), "utf8");
58081
+ raw = import_node_fs32.default.readFileSync(import_node_path38.default.join(sharedHome, "session_index.jsonl"), "utf8");
57869
58082
  } catch {
57870
58083
  return names;
57871
58084
  }
@@ -57890,7 +58103,7 @@ function walkRollouts(dir, visit) {
57890
58103
  }
57891
58104
  entries.sort((a, b2) => a.name < b2.name ? 1 : a.name > b2.name ? -1 : 0);
57892
58105
  for (const entry of entries) {
57893
- const full = import_node_path37.default.join(dir, entry.name);
58106
+ const full = import_node_path38.default.join(dir, entry.name);
57894
58107
  if (entry.isDirectory()) {
57895
58108
  if (!walkRollouts(full, visit)) return false;
57896
58109
  } else if (ROLLOUT_NAME_RE.test(entry.name)) {
@@ -57958,7 +58171,7 @@ var CodexHistoryReader = class {
57958
58171
  return [];
57959
58172
  }
57960
58173
  async listSessions(args) {
57961
- const want = import_node_path37.default.resolve(args.projectPath);
58174
+ const want = import_node_path38.default.resolve(args.projectPath);
57962
58175
  const names = readThreadNames(this.deps.sharedHome);
57963
58176
  const found = [];
57964
58177
  let scanned = 0;
@@ -57967,7 +58180,7 @@ var CodexHistoryReader = class {
57967
58180
  if (++scanned > CODEX_LIST_SESSIONS_SCAN_CAP) return false;
57968
58181
  const head = readHead(file, PEEK_BYTES);
57969
58182
  const cwd = head === null ? null : peekSessionCwd(head);
57970
- if (!cwd || import_node_path37.default.resolve(cwd) !== want) return;
58183
+ if (!cwd || import_node_path38.default.resolve(cwd) !== want) return;
57971
58184
  const first = readFirstLine(file);
57972
58185
  const meta = first === null ? null : parseCodexRolloutMeta(first);
57973
58186
  if (!meta) return;
@@ -58444,6 +58657,9 @@ function openHttpLineStream(opts) {
58444
58657
  // src/tools/codex-cloud.ts
58445
58658
  init_protocol();
58446
58659
 
58660
+ // src/tools/codex-cloud-session.ts
58661
+ var import_node_fs33 = __toESM(require("fs"), 1);
58662
+
58447
58663
  // src/tools/codex-cloud-history.ts
58448
58664
  function personaIdFromCloudCwd(cwd) {
58449
58665
  const m2 = /\/p\/([^/?#]+)(?:[/?#]|$)/.exec(cwd);
@@ -58558,6 +58774,22 @@ function deferredLineStream() {
58558
58774
  }
58559
58775
  };
58560
58776
  }
58777
+ function cloudImageInput(deps) {
58778
+ return (url) => {
58779
+ const secret = deps.getSignSecret?.();
58780
+ const p2 = secret ? resolveSignedFileUrl(secret, url) : null;
58781
+ if (!p2) return null;
58782
+ const mime = lookupMime(p2);
58783
+ if (!mime.startsWith("image/")) return null;
58784
+ try {
58785
+ const bytes = (deps.readFile ?? import_node_fs33.default.readFileSync)(p2);
58786
+ return { type: "image", url: `data:${mime};base64,${bytes.toString("base64")}` };
58787
+ } catch (e) {
58788
+ deps.logger?.warn("cloud image attachment unreadable", { path: p2, message: e.message });
58789
+ return null;
58790
+ }
58791
+ };
58792
+ }
58561
58793
  function createCloudCodexSession(ctx, sink, deps) {
58562
58794
  const personaId2 = personaIdFromCloudCwd(ctx.cwd);
58563
58795
  const stream = deferredLineStream();
@@ -58567,6 +58799,7 @@ function createCloudCodexSession(ctx, sink, deps) {
58567
58799
  stream,
58568
58800
  logger: deps.logger,
58569
58801
  threadParams: cloudThreadParams(ctx),
58802
+ imageInput: cloudImageInput(deps),
58570
58803
  // skills 在 Pod 里由 persona 目录自带,本机路径对它没意义
58571
58804
  // 「让对端走人」= 断开下行流,gateway 收到就删 Job;信号对 Pod 没有意义
58572
58805
  kill: () => stream.close()
@@ -58623,9 +58856,11 @@ var CloudCodexAdapter = class {
58623
58856
  historyReader;
58624
58857
  client;
58625
58858
  logger;
58859
+ getSignSecret;
58626
58860
  constructor(opts) {
58627
58861
  this.client = opts.client;
58628
58862
  this.logger = opts.logger;
58863
+ this.getSignSecret = opts.getSignSecret;
58629
58864
  this.historyReader = new CloudCodexHistoryReader(opts.client, opts.logger);
58630
58865
  }
58631
58866
  /** 可用 = 能拿到凭据(登了飞书、生成过 key、中心配了 gateway),与本机装没装 codex 无关 */
@@ -58645,7 +58880,7 @@ var CloudCodexAdapter = class {
58645
58880
  return CODEX_CONTEXT_WINDOW;
58646
58881
  }
58647
58882
  createSession(ctx, sink) {
58648
- return createCloudCodexSession(ctx, sink, { client: this.client, logger: this.logger });
58883
+ return createCloudCodexSession(ctx, sink, { client: this.client, logger: this.logger, getSignSecret: this.getSignSecret });
58649
58884
  }
58650
58885
  spawn(_ctx) {
58651
58886
  throw new Error("CloudCodexAdapter uses createSession, not spawn");
@@ -58662,7 +58897,7 @@ var CloudCodexAdapter = class {
58662
58897
  init_protocol();
58663
58898
 
58664
58899
  // src/tools/codex-skills.ts
58665
- var import_node_path38 = __toESM(require("path"), 1);
58900
+ var import_node_path39 = __toESM(require("path"), 1);
58666
58901
  function str3(v2) {
58667
58902
  return typeof v2 === "string" ? v2 : void 0;
58668
58903
  }
@@ -58699,7 +58934,7 @@ async function listCodexSkills(cwd, deps = {}) {
58699
58934
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
58700
58935
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
58701
58936
  beforeRequest: (client) => {
58702
- void client.request("skills/extraRoots/set", { extraRoots: [import_node_path38.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
58937
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path39.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
58703
58938
  }
58704
58939
  });
58705
58940
  return mapSkillsListResponse(res);
@@ -58773,23 +59008,23 @@ function rec3(v2) {
58773
59008
  }
58774
59009
 
58775
59010
  // src/workspace/browser.ts
58776
- var import_node_fs33 = __toESM(require("fs"), 1);
59011
+ var import_node_fs34 = __toESM(require("fs"), 1);
58777
59012
  var import_node_os10 = __toESM(require("os"), 1);
58778
- var import_node_path39 = __toESM(require("path"), 1);
59013
+ var import_node_path40 = __toESM(require("path"), 1);
58779
59014
  init_protocol();
58780
59015
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
58781
59016
  function resolveInsideCwd(cwd, subpath) {
58782
- const absCwd = import_node_path39.default.resolve(cwd);
58783
- const joined = import_node_path39.default.resolve(absCwd, subpath ?? ".");
58784
- const rel = import_node_path39.default.relative(absCwd, joined);
58785
- if (rel.startsWith("..") || import_node_path39.default.isAbsolute(rel)) {
59017
+ const absCwd = import_node_path40.default.resolve(cwd);
59018
+ const joined = import_node_path40.default.resolve(absCwd, subpath ?? ".");
59019
+ const rel = import_node_path40.default.relative(absCwd, joined);
59020
+ if (rel.startsWith("..") || import_node_path40.default.isAbsolute(rel)) {
58786
59021
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
58787
59022
  }
58788
59023
  return joined;
58789
59024
  }
58790
59025
  function ensureCwd(cwd) {
58791
59026
  try {
58792
- const stat = import_node_fs33.default.statSync(cwd);
59027
+ const stat = import_node_fs34.default.statSync(cwd);
58793
59028
  if (!stat.isDirectory()) {
58794
59029
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
58795
59030
  }
@@ -58803,7 +59038,7 @@ var WorkspaceBrowser = class {
58803
59038
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os10.default.homedir();
58804
59039
  ensureCwd(cwd);
58805
59040
  const full = resolveInsideCwd(cwd, args.path);
58806
- const dirents = import_node_fs33.default.readdirSync(full, { withFileTypes: true });
59041
+ const dirents = import_node_fs34.default.readdirSync(full, { withFileTypes: true });
58807
59042
  const entries = [];
58808
59043
  for (const d of dirents) {
58809
59044
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -58813,7 +59048,7 @@ var WorkspaceBrowser = class {
58813
59048
  mtime: ""
58814
59049
  };
58815
59050
  try {
58816
- const st = import_node_fs33.default.statSync(import_node_path39.default.join(full, d.name));
59051
+ const st = import_node_fs34.default.statSync(import_node_path40.default.join(full, d.name));
58817
59052
  entry.mtime = new Date(st.mtimeMs).toISOString();
58818
59053
  if (d.isFile()) entry.size = st.size;
58819
59054
  } catch {
@@ -58829,14 +59064,14 @@ var WorkspaceBrowser = class {
58829
59064
  read(args) {
58830
59065
  ensureCwd(args.cwd);
58831
59066
  const full = resolveInsideCwd(args.cwd, args.path);
58832
- const st = import_node_fs33.default.statSync(full);
59067
+ const st = import_node_fs34.default.statSync(full);
58833
59068
  if (!st.isFile()) {
58834
59069
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
58835
59070
  }
58836
59071
  if (st.size > MAX_FILE_BYTES2) {
58837
59072
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
58838
59073
  }
58839
- const buf = import_node_fs33.default.readFileSync(full);
59074
+ const buf = import_node_fs34.default.readFileSync(full);
58840
59075
  const isBinary = buf.includes(0);
58841
59076
  if (isBinary) {
58842
59077
  return {
@@ -58858,20 +59093,20 @@ var WorkspaceBrowser = class {
58858
59093
  };
58859
59094
 
58860
59095
  // src/skills/agents-scanner.ts
58861
- var import_node_fs34 = __toESM(require("fs"), 1);
59096
+ var import_node_fs35 = __toESM(require("fs"), 1);
58862
59097
  var import_node_os11 = __toESM(require("os"), 1);
58863
- var import_node_path40 = __toESM(require("path"), 1);
59098
+ var import_node_path41 = __toESM(require("path"), 1);
58864
59099
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
58865
59100
  function isDirLikeSync2(p2) {
58866
59101
  try {
58867
- return import_node_fs34.default.statSync(p2).isDirectory();
59102
+ return import_node_fs35.default.statSync(p2).isDirectory();
58868
59103
  } catch {
58869
59104
  return false;
58870
59105
  }
58871
59106
  }
58872
59107
  function fileExistsSync(p2) {
58873
59108
  try {
58874
- return import_node_fs34.default.statSync(p2).isFile();
59109
+ return import_node_fs35.default.statSync(p2).isFile();
58875
59110
  } catch {
58876
59111
  return false;
58877
59112
  }
@@ -58879,7 +59114,7 @@ function fileExistsSync(p2) {
58879
59114
  function parseAgentFile(filePath) {
58880
59115
  let content;
58881
59116
  try {
58882
- content = import_node_fs34.default.readFileSync(filePath, "utf8");
59117
+ content = import_node_fs35.default.readFileSync(filePath, "utf8");
58883
59118
  } catch {
58884
59119
  return {};
58885
59120
  }
@@ -58892,16 +59127,16 @@ function parseAgentFile(filePath) {
58892
59127
  function scanAgentsDir(dir, source, seen, out) {
58893
59128
  let entries;
58894
59129
  try {
58895
- entries = import_node_fs34.default.readdirSync(dir, { withFileTypes: true });
59130
+ entries = import_node_fs35.default.readdirSync(dir, { withFileTypes: true });
58896
59131
  } catch {
58897
59132
  return;
58898
59133
  }
58899
59134
  for (const ent of entries) {
58900
59135
  if (!ent.name.endsWith(".md")) continue;
58901
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path40.default.join(dir, ent.name)))) {
59136
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path41.default.join(dir, ent.name)))) {
58902
59137
  continue;
58903
59138
  }
58904
- const filePath = import_node_path40.default.join(dir, ent.name);
59139
+ const filePath = import_node_path41.default.join(dir, ent.name);
58905
59140
  const baseName = ent.name.replace(/\.md$/, "");
58906
59141
  if (seen.has(baseName)) continue;
58907
59142
  seen.add(baseName);
@@ -58919,12 +59154,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58919
59154
  function walk2(dir, namespaces) {
58920
59155
  let entries;
58921
59156
  try {
58922
- entries = import_node_fs34.default.readdirSync(dir, { withFileTypes: true });
59157
+ entries = import_node_fs35.default.readdirSync(dir, { withFileTypes: true });
58923
59158
  } catch {
58924
59159
  return;
58925
59160
  }
58926
59161
  for (const ent of entries) {
58927
- const childPath = import_node_path40.default.join(dir, ent.name);
59162
+ const childPath = import_node_path41.default.join(dir, ent.name);
58928
59163
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
58929
59164
  walk2(childPath, [...namespaces, ent.name]);
58930
59165
  continue;
@@ -58949,13 +59184,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58949
59184
  walk2(root, []);
58950
59185
  }
58951
59186
  function readInstalledPlugins2(home) {
58952
- const pluginsDir = import_node_path40.default.join(home, ".claude", "plugins");
58953
- const v2 = import_node_path40.default.join(pluginsDir, "installed_plugins_v2.json");
58954
- const v1 = import_node_path40.default.join(pluginsDir, "installed_plugins.json");
59187
+ const pluginsDir = import_node_path41.default.join(home, ".claude", "plugins");
59188
+ const v2 = import_node_path41.default.join(pluginsDir, "installed_plugins_v2.json");
59189
+ const v1 = import_node_path41.default.join(pluginsDir, "installed_plugins.json");
58955
59190
  let raw = null;
58956
59191
  for (const candidate of [v2, v1]) {
58957
59192
  try {
58958
- raw = import_node_fs34.default.readFileSync(candidate, "utf8");
59193
+ raw = import_node_fs35.default.readFileSync(candidate, "utf8");
58959
59194
  break;
58960
59195
  } catch {
58961
59196
  }
@@ -58980,19 +59215,19 @@ function readInstalledPlugins2(home) {
58980
59215
  return out;
58981
59216
  }
58982
59217
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
58983
- let cur = import_node_path40.default.resolve(startCwd);
58984
- const fsRoot = import_node_path40.default.parse(cur).root;
59218
+ let cur = import_node_path41.default.resolve(startCwd);
59219
+ const fsRoot = import_node_path41.default.parse(cur).root;
58985
59220
  while (true) {
58986
- scanAgentsDir(import_node_path40.default.join(cur, ".claude", "agents"), "project", seen, out);
59221
+ scanAgentsDir(import_node_path41.default.join(cur, ".claude", "agents"), "project", seen, out);
58987
59222
  let hasGit = false;
58988
59223
  try {
58989
- hasGit = import_node_fs34.default.existsSync(import_node_path40.default.join(cur, ".git"));
59224
+ hasGit = import_node_fs35.default.existsSync(import_node_path41.default.join(cur, ".git"));
58990
59225
  } catch {
58991
59226
  }
58992
59227
  if (hasGit) return;
58993
59228
  if (cur === home) return;
58994
59229
  if (cur === fsRoot) return;
58995
- const parent = import_node_path40.default.dirname(cur);
59230
+ const parent = import_node_path41.default.dirname(cur);
58996
59231
  if (parent === cur) return;
58997
59232
  cur = parent;
58998
59233
  }
@@ -59027,7 +59262,7 @@ var AgentsScanner = class {
59027
59262
  }
59028
59263
  const fsBlock = [];
59029
59264
  scanAgentsDir(
59030
- import_node_path40.default.join(this.home, ".claude", "agents"),
59265
+ import_node_path41.default.join(this.home, ".claude", "agents"),
59031
59266
  "global",
59032
59267
  seen,
59033
59268
  fsBlock
@@ -59041,7 +59276,7 @@ var AgentsScanner = class {
59041
59276
  ...this.extraPluginRoots
59042
59277
  ];
59043
59278
  for (const { name, root } of plugins) {
59044
- const agentsRoot = import_node_path40.default.join(root, "agents");
59279
+ const agentsRoot = import_node_path41.default.join(root, "agents");
59045
59280
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
59046
59281
  }
59047
59282
  return [...builtinBlock, ...fsBlock];
@@ -59049,15 +59284,15 @@ var AgentsScanner = class {
59049
59284
  };
59050
59285
 
59051
59286
  // src/observer/session-observer.ts
59052
- var import_node_fs36 = __toESM(require("fs"), 1);
59287
+ var import_node_fs37 = __toESM(require("fs"), 1);
59053
59288
  var import_node_os13 = __toESM(require("os"), 1);
59054
- var import_node_path42 = __toESM(require("path"), 1);
59289
+ var import_node_path43 = __toESM(require("path"), 1);
59055
59290
  init_claude_history();
59056
59291
 
59057
59292
  // src/observer/subagent-meta-observer.ts
59058
- var import_node_fs35 = __toESM(require("fs"), 1);
59293
+ var import_node_fs36 = __toESM(require("fs"), 1);
59059
59294
  var import_node_os12 = __toESM(require("os"), 1);
59060
- var import_node_path41 = __toESM(require("path"), 1);
59295
+ var import_node_path42 = __toESM(require("path"), 1);
59061
59296
  init_claude_history();
59062
59297
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
59063
59298
  var SubagentMetaObserver = class {
@@ -59070,7 +59305,7 @@ var SubagentMetaObserver = class {
59070
59305
  watches = /* @__PURE__ */ new Map();
59071
59306
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
59072
59307
  resolveSubagentDir(cwd, toolSessionId) {
59073
- return import_node_path41.default.join(
59308
+ return import_node_path42.default.join(
59074
59309
  this.home,
59075
59310
  ".claude",
59076
59311
  "projects",
@@ -59100,7 +59335,7 @@ var SubagentMetaObserver = class {
59100
59335
  attachWatcher(w2) {
59101
59336
  if (w2.watcher) return;
59102
59337
  try {
59103
- w2.watcher = import_node_fs35.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
59338
+ w2.watcher = import_node_fs36.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
59104
59339
  if (!name) return;
59105
59340
  const m2 = META_RE.exec(String(name));
59106
59341
  if (!m2) return;
@@ -59112,7 +59347,7 @@ var SubagentMetaObserver = class {
59112
59347
  scan(w2) {
59113
59348
  let entries;
59114
59349
  try {
59115
- entries = import_node_fs35.default.readdirSync(w2.dirPath);
59350
+ entries = import_node_fs36.default.readdirSync(w2.dirPath);
59116
59351
  } catch {
59117
59352
  return;
59118
59353
  }
@@ -59126,10 +59361,10 @@ var SubagentMetaObserver = class {
59126
59361
  if (!m2) return;
59127
59362
  const agentId = m2[1];
59128
59363
  if (w2.emitted.has(agentId)) return;
59129
- const file = import_node_path41.default.join(w2.dirPath, name);
59364
+ const file = import_node_path42.default.join(w2.dirPath, name);
59130
59365
  let raw;
59131
59366
  try {
59132
- raw = import_node_fs35.default.readFileSync(file, "utf8");
59367
+ raw = import_node_fs36.default.readFileSync(file, "utf8");
59133
59368
  } catch {
59134
59369
  return;
59135
59370
  }
@@ -59186,14 +59421,14 @@ var SessionObserver = class {
59186
59421
  metaObserver;
59187
59422
  resolveJsonlPath(cwd, toolSessionId, override) {
59188
59423
  if (override) return override;
59189
- return import_node_path42.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
59424
+ return import_node_path43.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
59190
59425
  }
59191
59426
  start(args) {
59192
59427
  this.stop(args.sessionId);
59193
59428
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
59194
59429
  let size = 0;
59195
59430
  try {
59196
- size = import_node_fs36.default.statSync(filePath).size;
59431
+ size = import_node_fs37.default.statSync(filePath).size;
59197
59432
  } catch {
59198
59433
  }
59199
59434
  const w2 = {
@@ -59206,16 +59441,16 @@ var SessionObserver = class {
59206
59441
  adapter: args.adapter,
59207
59442
  prevIsRejectSentinel: false,
59208
59443
  toolSessionId: args.toolSessionId,
59209
- sawFile: import_node_fs36.default.existsSync(filePath),
59444
+ sawFile: import_node_fs37.default.existsSync(filePath),
59210
59445
  lastRelocateScanMs: 0,
59211
59446
  pendingCwdDerive: false,
59212
59447
  lastDeriveMs: 0
59213
59448
  };
59214
59449
  try {
59215
- import_node_fs36.default.mkdirSync(import_node_path42.default.dirname(filePath), { recursive: true });
59450
+ import_node_fs37.default.mkdirSync(import_node_path43.default.dirname(filePath), { recursive: true });
59216
59451
  } catch {
59217
59452
  }
59218
- w2.watcher = import_node_fs36.default.watch(import_node_path42.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
59453
+ w2.watcher = import_node_fs37.default.watch(import_node_path43.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
59219
59454
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
59220
59455
  this.poll(w2);
59221
59456
  });
@@ -59238,7 +59473,7 @@ var SessionObserver = class {
59238
59473
  // 异常静默吞,不阻塞 watcher 启动
59239
59474
  hydrateMetaTail(w2, maxLines = 200) {
59240
59475
  try {
59241
- const raw = import_node_fs36.default.readFileSync(w2.filePath, "utf8");
59476
+ const raw = import_node_fs37.default.readFileSync(w2.filePath, "utf8");
59242
59477
  if (!raw) return;
59243
59478
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
59244
59479
  if (allLines.length === 0) return;
@@ -59262,7 +59497,7 @@ var SessionObserver = class {
59262
59497
  poll(w2) {
59263
59498
  let size = 0;
59264
59499
  try {
59265
- size = import_node_fs36.default.statSync(w2.filePath).size;
59500
+ size = import_node_fs37.default.statSync(w2.filePath).size;
59266
59501
  } catch {
59267
59502
  if (w2.sawFile) this.maybeRelocate(w2);
59268
59503
  return;
@@ -59273,11 +59508,11 @@ var SessionObserver = class {
59273
59508
  w2.buf = "";
59274
59509
  }
59275
59510
  if (size === w2.lastSize) return;
59276
- const fd = import_node_fs36.default.openSync(w2.filePath, "r");
59511
+ const fd = import_node_fs37.default.openSync(w2.filePath, "r");
59277
59512
  try {
59278
59513
  const len = size - w2.lastSize;
59279
59514
  const buf = Buffer.alloc(len);
59280
- import_node_fs36.default.readSync(fd, buf, 0, len, w2.lastSize);
59515
+ import_node_fs37.default.readSync(fd, buf, 0, len, w2.lastSize);
59281
59516
  w2.lastSize = size;
59282
59517
  w2.buf += buf.toString("utf8");
59283
59518
  let newlineIndex;
@@ -59300,7 +59535,7 @@ var SessionObserver = class {
59300
59535
  }
59301
59536
  }
59302
59537
  } finally {
59303
- import_node_fs36.default.closeSync(fd);
59538
+ import_node_fs37.default.closeSync(fd);
59304
59539
  }
59305
59540
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
59306
59541
  }
@@ -59312,7 +59547,7 @@ var SessionObserver = class {
59312
59547
  const now = Date.now();
59313
59548
  if (now - w2.lastRelocateScanMs < 1e3) return;
59314
59549
  w2.lastRelocateScanMs = now;
59315
- const projectsRoot = import_node_path42.default.join(this.home, ".claude", "projects");
59550
+ const projectsRoot = import_node_path43.default.join(this.home, ".claude", "projects");
59316
59551
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
59317
59552
  if (!found || found === w2.filePath) return;
59318
59553
  try {
@@ -59321,7 +59556,7 @@ var SessionObserver = class {
59321
59556
  }
59322
59557
  w2.filePath = found;
59323
59558
  try {
59324
- w2.watcher = import_node_fs36.default.watch(import_node_path42.default.dirname(found), { persistent: false }, (_event, changedName) => {
59559
+ w2.watcher = import_node_fs37.default.watch(import_node_path43.default.dirname(found), { persistent: false }, (_event, changedName) => {
59325
59560
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
59326
59561
  this.poll(w2);
59327
59562
  });
@@ -59443,9 +59678,9 @@ function listRegistered() {
59443
59678
  // src/tools/title-generator.ts
59444
59679
  var import_node_child_process9 = require("child_process");
59445
59680
  init_protocol();
59446
- var import_node_fs37 = __toESM(require("fs"), 1);
59681
+ var import_node_fs38 = __toESM(require("fs"), 1);
59447
59682
  var import_node_os14 = __toESM(require("os"), 1);
59448
- var import_node_path43 = __toESM(require("path"), 1);
59683
+ var import_node_path44 = __toESM(require("path"), 1);
59449
59684
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
59450
59685
  var TITLE_MODEL_BY_TOOL = {
59451
59686
  claude: "haiku",
@@ -59516,21 +59751,21 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
59516
59751
  if (!text) return null;
59517
59752
  let workDir;
59518
59753
  try {
59519
- workDir = import_node_fs37.default.mkdtempSync(import_node_path43.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
59754
+ workDir = import_node_fs38.default.mkdtempSync(import_node_path44.default.join(import_node_os14.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
59520
59755
  } catch {
59521
59756
  return null;
59522
59757
  }
59523
59758
  const cleanupWorkDir = () => {
59524
59759
  try {
59525
- import_node_fs37.default.rmSync(workDir, { recursive: true, force: true });
59760
+ import_node_fs38.default.rmSync(workDir, { recursive: true, force: true });
59526
59761
  } catch {
59527
59762
  }
59528
59763
  };
59529
- const outFile = import_node_path43.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
59530
- const schemaFile = import_node_path43.default.join(workDir, "title-schema.json");
59764
+ const outFile = import_node_path44.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
59765
+ const schemaFile = import_node_path44.default.join(workDir, "title-schema.json");
59531
59766
  if (isCodexFamily(tool)) {
59532
59767
  try {
59533
- import_node_fs37.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
59768
+ import_node_fs38.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
59534
59769
  } catch {
59535
59770
  cleanupWorkDir();
59536
59771
  return null;
@@ -59580,7 +59815,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
59580
59815
  if (tool === "claude") return finish(parseTitleJson(stdout));
59581
59816
  let fileText = "";
59582
59817
  try {
59583
- fileText = import_node_fs37.default.readFileSync(outFile, "utf8");
59818
+ fileText = import_node_fs38.default.readFileSync(outFile, "utf8");
59584
59819
  } catch {
59585
59820
  return finish(null);
59586
59821
  }
@@ -59602,7 +59837,7 @@ var wrapper_default = import_websocket.default;
59602
59837
 
59603
59838
  // src/transport/local-ws-server.ts
59604
59839
  var import_node_http2 = __toESM(require("http"), 1);
59605
- var import_node_crypto8 = require("crypto");
59840
+ var import_node_crypto9 = require("crypto");
59606
59841
 
59607
59842
  // src/transport/preview-proxy.ts
59608
59843
  var import_node_http = __toESM(require("http"), 1);
@@ -59886,7 +60121,7 @@ var LocalWsServer = class {
59886
60121
  }
59887
60122
  }
59888
60123
  onConnection(socket, remoteAddress) {
59889
- const id = (0, import_node_crypto8.randomUUID)();
60124
+ const id = (0, import_node_crypto9.randomUUID)();
59890
60125
  const subscribedSessions = /* @__PURE__ */ new Map();
59891
60126
  const handle = {
59892
60127
  id,
@@ -60292,8 +60527,8 @@ async function authenticate(token, deps) {
60292
60527
  }
60293
60528
 
60294
60529
  // src/legacy-cleanup.ts
60295
- var fs48 = __toESM(require("fs/promises"), 1);
60296
- var path51 = __toESM(require("path"), 1);
60530
+ var fs49 = __toESM(require("fs/promises"), 1);
60531
+ var path52 = __toESM(require("path"), 1);
60297
60532
  var LEGACY_FILES = [
60298
60533
  "personal-capability.json",
60299
60534
  "received-capabilities.json",
@@ -60302,9 +60537,9 @@ var LEGACY_FILES = [
60302
60537
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
60303
60538
  const removed = [];
60304
60539
  for (const name of LEGACY_FILES) {
60305
- const p2 = path51.join(dataDir, name);
60540
+ const p2 = path52.join(dataDir, name);
60306
60541
  try {
60307
- await fs48.unlink(p2);
60542
+ await fs49.unlink(p2);
60308
60543
  removed.push(name);
60309
60544
  logger.debug("legacy capability file removed", { file: name });
60310
60545
  } catch (err) {
@@ -60316,13 +60551,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
60316
60551
  }
60317
60552
 
60318
60553
  // src/inbox/inbox-store.ts
60319
- var fs49 = __toESM(require("fs"), 1);
60320
- var path52 = __toESM(require("path"), 1);
60554
+ var fs50 = __toESM(require("fs"), 1);
60555
+ var path53 = __toESM(require("path"), 1);
60321
60556
  var INBOX_SUBDIR = "inbox";
60322
60557
  var InboxStore = class {
60323
60558
  constructor(dataDir) {
60324
60559
  this.dataDir = dataDir;
60325
- fs49.mkdirSync(this.dirPath(), { recursive: true });
60560
+ fs50.mkdirSync(this.dirPath(), { recursive: true });
60326
60561
  }
60327
60562
  dataDir;
60328
60563
  /**
@@ -60334,7 +60569,7 @@ var InboxStore = class {
60334
60569
  const file = this.filePath(peerDeviceId);
60335
60570
  let raw;
60336
60571
  try {
60337
- raw = fs49.readFileSync(file, "utf8");
60572
+ raw = fs50.readFileSync(file, "utf8");
60338
60573
  } catch (err) {
60339
60574
  if (err?.code === "ENOENT") return [];
60340
60575
  return [];
@@ -60350,7 +60585,7 @@ var InboxStore = class {
60350
60585
  const dir = this.dirPath();
60351
60586
  let entries;
60352
60587
  try {
60353
- entries = fs49.readdirSync(dir);
60588
+ entries = fs50.readdirSync(dir);
60354
60589
  } catch (err) {
60355
60590
  if (err?.code === "ENOENT") return [];
60356
60591
  return [];
@@ -60366,9 +60601,9 @@ var InboxStore = class {
60366
60601
  if (existing.some((m2) => m2.id === message.id)) return;
60367
60602
  const file = this.filePath(message.peerDeviceId);
60368
60603
  const line = JSON.stringify(message) + "\n";
60369
- fs49.appendFileSync(file, line, { mode: 384 });
60604
+ fs50.appendFileSync(file, line, { mode: 384 });
60370
60605
  try {
60371
- fs49.chmodSync(file, 384);
60606
+ fs50.chmodSync(file, 384);
60372
60607
  } catch {
60373
60608
  }
60374
60609
  }
@@ -60398,7 +60633,7 @@ var InboxStore = class {
60398
60633
  removeByPeerDeviceId(peerDeviceId) {
60399
60634
  const file = this.filePath(peerDeviceId);
60400
60635
  try {
60401
- fs49.unlinkSync(file);
60636
+ fs50.unlinkSync(file);
60402
60637
  } catch (err) {
60403
60638
  if (err?.code === "ENOENT") return;
60404
60639
  }
@@ -60407,18 +60642,18 @@ var InboxStore = class {
60407
60642
  const file = this.filePath(peerDeviceId);
60408
60643
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
60409
60644
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
60410
- fs49.writeFileSync(tmp, content, { mode: 384 });
60411
- fs49.renameSync(tmp, file);
60645
+ fs50.writeFileSync(tmp, content, { mode: 384 });
60646
+ fs50.renameSync(tmp, file);
60412
60647
  try {
60413
- fs49.chmodSync(file, 384);
60648
+ fs50.chmodSync(file, 384);
60414
60649
  } catch {
60415
60650
  }
60416
60651
  }
60417
60652
  dirPath() {
60418
- return path52.join(this.dataDir, INBOX_SUBDIR);
60653
+ return path53.join(this.dataDir, INBOX_SUBDIR);
60419
60654
  }
60420
60655
  filePath(peerDeviceId) {
60421
- return path52.join(this.dirPath(), `${peerDeviceId}.jsonl`);
60656
+ return path53.join(this.dirPath(), `${peerDeviceId}.jsonl`);
60422
60657
  }
60423
60658
  };
60424
60659
  function parseAllLines(raw) {
@@ -60506,8 +60741,8 @@ var InboxManager = class {
60506
60741
  };
60507
60742
 
60508
60743
  // src/state/contact-store.ts
60509
- var fs50 = __toESM(require("fs"), 1);
60510
- var path53 = __toESM(require("path"), 1);
60744
+ var fs51 = __toESM(require("fs"), 1);
60745
+ var path54 = __toESM(require("path"), 1);
60511
60746
  var FILE_NAME = "contacts.json";
60512
60747
  var ContactStore = class {
60513
60748
  constructor(dataDir) {
@@ -60517,10 +60752,10 @@ var ContactStore = class {
60517
60752
  contacts = /* @__PURE__ */ new Map();
60518
60753
  load() {
60519
60754
  this.contacts.clear();
60520
- const file = path53.join(this.dataDir, FILE_NAME);
60755
+ const file = path54.join(this.dataDir, FILE_NAME);
60521
60756
  let raw;
60522
60757
  try {
60523
- raw = fs50.readFileSync(file, "utf8");
60758
+ raw = fs51.readFileSync(file, "utf8");
60524
60759
  } catch (err) {
60525
60760
  if (err?.code !== "ENOENT") this.renameBak(file);
60526
60761
  return;
@@ -60601,27 +60836,27 @@ var ContactStore = class {
60601
60836
  return true;
60602
60837
  }
60603
60838
  flush() {
60604
- const file = path53.join(this.dataDir, FILE_NAME);
60839
+ const file = path54.join(this.dataDir, FILE_NAME);
60605
60840
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
60606
60841
  const content = JSON.stringify(
60607
60842
  { contacts: Array.from(this.contacts.values()) },
60608
60843
  null,
60609
60844
  2
60610
60845
  );
60611
- fs50.mkdirSync(this.dataDir, { recursive: true });
60612
- fs50.writeFileSync(tmp, content, { mode: 384 });
60613
- fs50.renameSync(tmp, file);
60846
+ fs51.mkdirSync(this.dataDir, { recursive: true });
60847
+ fs51.writeFileSync(tmp, content, { mode: 384 });
60848
+ fs51.renameSync(tmp, file);
60614
60849
  }
60615
60850
  renameBak(file) {
60616
60851
  try {
60617
- fs50.renameSync(file, `${file}.bak`);
60852
+ fs51.renameSync(file, `${file}.bak`);
60618
60853
  } catch {
60619
60854
  }
60620
60855
  }
60621
60856
  };
60622
60857
 
60623
60858
  // src/contact/connect-remote.ts
60624
- var crypto3 = __toESM(require("crypto"), 1);
60859
+ var crypto4 = __toESM(require("crypto"), 1);
60625
60860
  init_protocol();
60626
60861
  var HANDSHAKE_TIMEOUT_MS = 5e3;
60627
60862
  var RPC_TIMEOUT_MS = 5e3;
@@ -60676,7 +60911,7 @@ async function connectRemote(args) {
60676
60911
  ws.once("close", onClose);
60677
60912
  });
60678
60913
  function call(method, payload) {
60679
- const requestId = crypto3.randomUUID();
60914
+ const requestId = crypto4.randomUUID();
60680
60915
  return new Promise((resolve9, reject) => {
60681
60916
  const onMessage = (raw) => {
60682
60917
  let f;
@@ -60722,61 +60957,61 @@ async function connectRemote(args) {
60722
60957
  }
60723
60958
 
60724
60959
  // src/migrations/2026-05-20-flatten-sessions.ts
60725
- var fs51 = __toESM(require("fs"), 1);
60726
- var path54 = __toESM(require("path"), 1);
60960
+ var fs52 = __toESM(require("fs"), 1);
60961
+ var path55 = __toESM(require("path"), 1);
60727
60962
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
60728
60963
  function migrateFlattenSessions(opts) {
60729
60964
  const dataDir = opts.dataDir;
60730
60965
  const now = opts.now ?? Date.now;
60731
- const sessionsDir = path54.join(dataDir, "sessions");
60732
- const flagPath = path54.join(sessionsDir, MIGRATION_FLAG_NAME);
60966
+ const sessionsDir = path55.join(dataDir, "sessions");
60967
+ const flagPath = path55.join(sessionsDir, MIGRATION_FLAG_NAME);
60733
60968
  if (existsSync3(flagPath)) {
60734
60969
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
60735
60970
  }
60736
60971
  let movedBare = 0;
60737
60972
  let movedVmOwner = 0;
60738
60973
  let archivedListener = 0;
60739
- const defaultDir = path54.join(sessionsDir, "default");
60974
+ const defaultDir = path55.join(sessionsDir, "default");
60740
60975
  if (existsSync3(defaultDir)) {
60741
60976
  for (const entry of readdirSafe(defaultDir)) {
60742
60977
  if (!entry.endsWith(".json")) continue;
60743
- const src = path54.join(defaultDir, entry);
60744
- const dst = path54.join(sessionsDir, entry);
60745
- fs51.renameSync(src, dst);
60978
+ const src = path55.join(defaultDir, entry);
60979
+ const dst = path55.join(sessionsDir, entry);
60980
+ fs52.renameSync(src, dst);
60746
60981
  movedBare += 1;
60747
60982
  }
60748
60983
  rmdirIfEmpty(defaultDir);
60749
60984
  }
60750
60985
  for (const pid of readdirSafe(sessionsDir)) {
60751
- const personaDir = path54.join(sessionsDir, pid);
60986
+ const personaDir = path55.join(sessionsDir, pid);
60752
60987
  if (!isDir(personaDir)) continue;
60753
60988
  if (pid === "default") continue;
60754
- const ownerSrc = path54.join(personaDir, "owner");
60989
+ const ownerSrc = path55.join(personaDir, "owner");
60755
60990
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
60756
- const ownerDst = path54.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
60757
- fs51.mkdirSync(ownerDst, { recursive: true });
60991
+ const ownerDst = path55.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
60992
+ fs52.mkdirSync(ownerDst, { recursive: true });
60758
60993
  for (const file of readdirSafe(ownerSrc)) {
60759
60994
  if (!file.endsWith(".json")) continue;
60760
- fs51.renameSync(path54.join(ownerSrc, file), path54.join(ownerDst, file));
60995
+ fs52.renameSync(path55.join(ownerSrc, file), path55.join(ownerDst, file));
60761
60996
  movedVmOwner += 1;
60762
60997
  }
60763
60998
  rmdirIfEmpty(ownerSrc);
60764
60999
  }
60765
- const listenerSrc = path54.join(personaDir, "listener");
61000
+ const listenerSrc = path55.join(personaDir, "listener");
60766
61001
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
60767
- const archiveDst = path54.join(dataDir, ".legacy", `listener-${pid}`);
60768
- fs51.mkdirSync(archiveDst, { recursive: true });
61002
+ const archiveDst = path55.join(dataDir, ".legacy", `listener-${pid}`);
61003
+ fs52.mkdirSync(archiveDst, { recursive: true });
60769
61004
  for (const file of readdirSafe(listenerSrc)) {
60770
61005
  if (!file.endsWith(".json")) continue;
60771
- fs51.renameSync(path54.join(listenerSrc, file), path54.join(archiveDst, file));
61006
+ fs52.renameSync(path55.join(listenerSrc, file), path55.join(archiveDst, file));
60772
61007
  archivedListener += 1;
60773
61008
  }
60774
61009
  rmdirIfEmpty(listenerSrc);
60775
61010
  }
60776
61011
  rmdirIfEmpty(personaDir);
60777
61012
  }
60778
- fs51.mkdirSync(sessionsDir, { recursive: true });
60779
- fs51.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
61013
+ fs52.mkdirSync(sessionsDir, { recursive: true });
61014
+ fs52.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
60780
61015
  return {
60781
61016
  skipped: false,
60782
61017
  flagWritten: true,
@@ -60787,7 +61022,7 @@ function migrateFlattenSessions(opts) {
60787
61022
  }
60788
61023
  function existsSync3(p2) {
60789
61024
  try {
60790
- fs51.statSync(p2);
61025
+ fs52.statSync(p2);
60791
61026
  return true;
60792
61027
  } catch {
60793
61028
  return false;
@@ -60795,238 +61030,61 @@ function existsSync3(p2) {
60795
61030
  }
60796
61031
  function isDir(p2) {
60797
61032
  try {
60798
- return fs51.statSync(p2).isDirectory();
61033
+ return fs52.statSync(p2).isDirectory();
60799
61034
  } catch {
60800
61035
  return false;
60801
61036
  }
60802
61037
  }
60803
61038
  function readdirSafe(p2) {
60804
61039
  try {
60805
- return fs51.readdirSync(p2);
61040
+ return fs52.readdirSync(p2);
60806
61041
  } catch {
60807
61042
  return [];
60808
61043
  }
60809
61044
  }
60810
61045
  function rmdirIfEmpty(p2) {
60811
61046
  try {
60812
- fs51.rmdirSync(p2);
61047
+ fs52.rmdirSync(p2);
60813
61048
  } catch {
60814
61049
  }
60815
61050
  }
60816
61051
 
60817
61052
  // src/migrations/2026-08-18-drop-seeded-projects.ts
60818
- var fs52 = __toESM(require("fs"), 1);
60819
- var path55 = __toESM(require("path"), 1);
61053
+ var fs53 = __toESM(require("fs"), 1);
61054
+ var path56 = __toESM(require("path"), 1);
60820
61055
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
60821
61056
  function dropSeededProjects(opts) {
60822
- fs52.mkdirSync(opts.dataDir, { recursive: true });
60823
- const flag = path55.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
60824
- if (fs52.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
60825
- const file = path55.join(opts.dataDir, "projects.json");
61057
+ fs53.mkdirSync(opts.dataDir, { recursive: true });
61058
+ const flag = path56.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
61059
+ if (fs53.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
61060
+ const file = path56.join(opts.dataDir, "projects.json");
60826
61061
  let raw = null;
60827
61062
  let dropped = 0;
60828
61063
  try {
60829
- raw = fs52.readFileSync(file, "utf8");
61064
+ raw = fs53.readFileSync(file, "utf8");
60830
61065
  dropped = JSON.parse(raw).projects?.length ?? 0;
60831
61066
  } catch {
60832
61067
  }
60833
61068
  let backup = null;
60834
61069
  if (raw != null && dropped > 0) {
60835
- const dir = path55.join(opts.dataDir, "backups");
60836
- fs52.mkdirSync(dir, { recursive: true });
60837
- backup = path55.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
60838
- fs52.writeFileSync(backup, raw);
61070
+ const dir = path56.join(opts.dataDir, "backups");
61071
+ fs53.mkdirSync(dir, { recursive: true });
61072
+ backup = path56.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
61073
+ fs53.writeFileSync(backup, raw);
60839
61074
  }
60840
61075
  if (raw != null || dropped > 0) {
60841
- fs52.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
61076
+ fs53.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
60842
61077
  }
60843
- fs52.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
61078
+ fs53.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
60844
61079
  return { skipped: false, dropped, backup };
60845
61080
  }
60846
61081
 
60847
61082
  // src/transport/http-router.ts
60848
- var import_node_fs39 = __toESM(require("fs"), 1);
61083
+ var import_node_fs40 = __toESM(require("fs"), 1);
60849
61084
  var import_node_path47 = __toESM(require("path"), 1);
60850
61085
 
60851
- // src/attachment/mime.ts
60852
- var import_node_path44 = __toESM(require("path"), 1);
60853
- var TEXT_PLAIN = "text/plain; charset=utf-8";
60854
- var EXT_TO_NATIVE_MIME = {
60855
- // 图片
60856
- ".png": "image/png",
60857
- ".jpg": "image/jpeg",
60858
- ".jpeg": "image/jpeg",
60859
- ".gif": "image/gif",
60860
- ".webp": "image/webp",
60861
- ".svg": "image/svg+xml",
60862
- ".bmp": "image/bmp",
60863
- ".ico": "image/x-icon",
60864
- ".avif": "image/avif",
60865
- // 文档 / 富文本
60866
- ".pdf": "application/pdf",
60867
- ".html": "text/html; charset=utf-8",
60868
- ".htm": "text/html; charset=utf-8",
60869
- // 视频 / 音频
60870
- ".mp4": "video/mp4",
60871
- ".webm": "video/webm",
60872
- ".mov": "video/quicktime",
60873
- ".mp3": "audio/mpeg",
60874
- ".wav": "audio/wav",
60875
- ".ogg": "audio/ogg",
60876
- ".flac": "audio/flac",
60877
- // 真二进制(让浏览器下载而不是错把它当文本明文)
60878
- ".zip": "application/zip",
60879
- ".gz": "application/gzip",
60880
- ".tar": "application/x-tar",
60881
- ".7z": "application/x-7z-compressed",
60882
- ".rar": "application/x-rar-compressed"
60883
- };
60884
- var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
60885
- // 文档
60886
- ".md",
60887
- ".markdown",
60888
- ".rst",
60889
- ".adoc",
60890
- ".txt",
60891
- ".log",
60892
- // 通用结构化
60893
- ".json",
60894
- ".jsonc",
60895
- ".json5",
60896
- ".yaml",
60897
- ".yml",
60898
- ".toml",
60899
- ".xml",
60900
- ".csv",
60901
- ".tsv",
60902
- ".ini",
60903
- ".conf",
60904
- ".cfg",
60905
- ".env",
60906
- // 前端
60907
- ".js",
60908
- ".jsx",
60909
- ".mjs",
60910
- ".cjs",
60911
- ".ts",
60912
- ".tsx",
60913
- ".css",
60914
- ".scss",
60915
- ".sass",
60916
- ".less",
60917
- ".vue",
60918
- ".svelte",
60919
- ".graphql",
60920
- ".gql",
60921
- // 后端 / 各语言
60922
- ".py",
60923
- ".rb",
60924
- ".go",
60925
- ".rs",
60926
- ".java",
60927
- ".kt",
60928
- ".kts",
60929
- ".scala",
60930
- ".c",
60931
- ".h",
60932
- ".cpp",
60933
- ".hpp",
60934
- ".cc",
60935
- ".hh",
60936
- ".cs",
60937
- ".php",
60938
- ".swift",
60939
- ".m",
60940
- ".mm",
60941
- ".dart",
60942
- ".lua",
60943
- ".pl",
60944
- ".r",
60945
- ".sh",
60946
- ".bash",
60947
- ".zsh",
60948
- ".fish",
60949
- // 其他
60950
- ".sql",
60951
- ".proto",
60952
- ".dockerfile",
60953
- ".diff",
60954
- ".patch",
60955
- ".makefile",
60956
- ".mk"
60957
- ]);
60958
- function lookupMime(filePathOrName) {
60959
- const ext = import_node_path44.default.extname(filePathOrName).toLowerCase();
60960
- if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
60961
- if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
60962
- return "application/octet-stream";
60963
- }
60964
-
60965
- // src/attachment/sign-url.ts
60966
- var import_node_crypto9 = __toESM(require("crypto"), 1);
60967
- var HMAC_ALGO = "sha256";
60968
- function base64urlEncode(buf) {
60969
- const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
60970
- return b2.toString("base64url");
60971
- }
60972
- function base64urlDecodeBuf(s) {
60973
- return Buffer.from(s, "base64url");
60974
- }
60975
- function encodeAbsPathForUrl(absPath) {
60976
- return absPath.split("/").map(encodeURIComponent).join("/");
60977
- }
60978
- function decodeAbsPathFromUrl(encoded) {
60979
- return encoded.split("/").map(decodeURIComponent).join("/");
60980
- }
60981
- var DOMAIN_PREFIX2 = "clawd-attach-v1|";
60982
- function computeSig(secret, absPath, e) {
60983
- const msg = e === null ? `${DOMAIN_PREFIX2}${absPath}` : `${DOMAIN_PREFIX2}${absPath}|${e}`;
60984
- return import_node_crypto9.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
60985
- }
60986
- function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
60987
- const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
60988
- const s = base64urlEncode(computeSig(secret, absPath, e));
60989
- return { absPath, e, s };
60990
- }
60991
- function buildSignedFileUrl(httpBaseUrl, parts, prefix = "/files") {
60992
- const encodedPath = encodeAbsPathForUrl(parts.absPath);
60993
- const query = parts.e === null ? `s=${encodeURIComponent(parts.s)}` : `e=${parts.e}&s=${encodeURIComponent(parts.s)}`;
60994
- const base = httpBaseUrl.endsWith("/") ? httpBaseUrl.slice(0, -1) : httpBaseUrl;
60995
- return `${base}${prefix}${encodedPath}?${query}`;
60996
- }
60997
- function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
60998
- let e;
60999
- if (eRaw === null || eRaw === void 0 || eRaw === "") {
61000
- e = null;
61001
- } else {
61002
- const parsed = Number.parseInt(eRaw, 10);
61003
- if (!Number.isFinite(parsed) || parsed < 0) {
61004
- return { ok: false, code: "MALFORMED" };
61005
- }
61006
- e = parsed;
61007
- }
61008
- if (!absPath || !s) return { ok: false, code: "MALFORMED" };
61009
- const expected = computeSig(secret, absPath, e);
61010
- let provided;
61011
- try {
61012
- provided = base64urlDecodeBuf(s);
61013
- } catch {
61014
- return { ok: false, code: "MALFORMED" };
61015
- }
61016
- if (provided.length !== expected.length) {
61017
- return { ok: false, code: "BAD_SIG" };
61018
- }
61019
- if (!import_node_crypto9.default.timingSafeEqual(provided, expected)) {
61020
- return { ok: false, code: "BAD_SIG" };
61021
- }
61022
- if (e !== null && now() / 1e3 > e) {
61023
- return { ok: false, code: "EXPIRED" };
61024
- }
61025
- return { ok: true, absPath };
61026
- }
61027
-
61028
61086
  // src/attachment/upload.ts
61029
- var import_node_fs38 = __toESM(require("fs"), 1);
61087
+ var import_node_fs39 = __toESM(require("fs"), 1);
61030
61088
  var import_node_path45 = __toESM(require("path"), 1);
61031
61089
  var import_node_crypto10 = __toESM(require("crypto"), 1);
61032
61090
  var import_promises7 = require("stream/promises");
@@ -61048,7 +61106,7 @@ async function writeUploadedAttachment(args) {
61048
61106
  assertValidFileName(args.fileName);
61049
61107
  const attachmentsRoot = import_node_path45.default.join(args.baseDir, ".attachments");
61050
61108
  try {
61051
- import_node_fs38.default.mkdirSync(attachmentsRoot, { recursive: true });
61109
+ import_node_fs39.default.mkdirSync(attachmentsRoot, { recursive: true });
61052
61110
  } catch (err) {
61053
61111
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
61054
61112
  }
@@ -61069,18 +61127,18 @@ async function writeUploadedAttachment(args) {
61069
61127
  yield buf;
61070
61128
  }
61071
61129
  },
61072
- import_node_fs38.default.createWriteStream(tmpPath, { mode: 384 })
61130
+ import_node_fs39.default.createWriteStream(tmpPath, { mode: 384 })
61073
61131
  );
61074
61132
  } catch (err) {
61075
61133
  try {
61076
- import_node_fs38.default.unlinkSync(tmpPath);
61134
+ import_node_fs39.default.unlinkSync(tmpPath);
61077
61135
  } catch {
61078
61136
  }
61079
61137
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
61080
61138
  }
61081
61139
  if (actualSize !== args.contentLength) {
61082
61140
  try {
61083
- import_node_fs38.default.unlinkSync(tmpPath);
61141
+ import_node_fs39.default.unlinkSync(tmpPath);
61084
61142
  } catch {
61085
61143
  }
61086
61144
  throw new UploadError(
@@ -61093,24 +61151,24 @@ async function writeUploadedAttachment(args) {
61093
61151
  let finalFileName;
61094
61152
  let hashDirExists = false;
61095
61153
  try {
61096
- hashDirExists = import_node_fs38.default.statSync(hashDir).isDirectory();
61154
+ hashDirExists = import_node_fs39.default.statSync(hashDir).isDirectory();
61097
61155
  } catch {
61098
61156
  }
61099
61157
  if (hashDirExists) {
61100
- const existing = import_node_fs38.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
61158
+ const existing = import_node_fs39.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
61101
61159
  finalFileName = existing[0] ?? args.fileName;
61102
61160
  try {
61103
- import_node_fs38.default.unlinkSync(tmpPath);
61161
+ import_node_fs39.default.unlinkSync(tmpPath);
61104
61162
  } catch {
61105
61163
  }
61106
61164
  } else {
61107
61165
  try {
61108
- import_node_fs38.default.mkdirSync(hashDir, { recursive: true });
61166
+ import_node_fs39.default.mkdirSync(hashDir, { recursive: true });
61109
61167
  finalFileName = args.fileName;
61110
- import_node_fs38.default.renameSync(tmpPath, import_node_path45.default.join(hashDir, finalFileName));
61168
+ import_node_fs39.default.renameSync(tmpPath, import_node_path45.default.join(hashDir, finalFileName));
61111
61169
  } catch (err) {
61112
61170
  try {
61113
- import_node_fs38.default.unlinkSync(tmpPath);
61171
+ import_node_fs39.default.unlinkSync(tmpPath);
61114
61172
  } catch {
61115
61173
  }
61116
61174
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
@@ -61417,7 +61475,7 @@ function createHttpRouter(deps) {
61417
61475
  }
61418
61476
  let buf;
61419
61477
  try {
61420
- buf = await import_node_fs39.default.promises.readFile(abs);
61478
+ buf = await import_node_fs40.default.promises.readFile(abs);
61421
61479
  } catch {
61422
61480
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
61423
61481
  return true;
@@ -61781,7 +61839,7 @@ function withCtx(ctx, body) {
61781
61839
  function streamFile(res, absPath, logger) {
61782
61840
  let stat;
61783
61841
  try {
61784
- stat = import_node_fs39.default.statSync(absPath);
61842
+ stat = import_node_fs40.default.statSync(absPath);
61785
61843
  } catch (err) {
61786
61844
  const code = err?.code;
61787
61845
  if (code === "ENOENT") {
@@ -61804,7 +61862,7 @@ function streamFile(res, absPath, logger) {
61804
61862
  // 防止浏览器把任意 mime 当 html 渲染
61805
61863
  "X-Content-Type-Options": "nosniff"
61806
61864
  });
61807
- const stream = import_node_fs39.default.createReadStream(absPath);
61865
+ const stream = import_node_fs40.default.createReadStream(absPath);
61808
61866
  stream.on("error", (err) => {
61809
61867
  logger?.warn("streamFile read error", { absPath, err: err.message });
61810
61868
  res.destroy();
@@ -61813,7 +61871,7 @@ function streamFile(res, absPath, logger) {
61813
61871
  }
61814
61872
 
61815
61873
  // src/attachment/gc.ts
61816
- var import_node_fs40 = __toESM(require("fs"), 1);
61874
+ var import_node_fs41 = __toESM(require("fs"), 1);
61817
61875
  var import_node_path48 = __toESM(require("path"), 1);
61818
61876
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
61819
61877
  function runAttachmentGc(args) {
@@ -61844,7 +61902,7 @@ function runAttachmentGc(args) {
61844
61902
  const attRoot = import_node_path48.default.join(rootDir, ".attachments");
61845
61903
  let hashDirs;
61846
61904
  try {
61847
- hashDirs = import_node_fs40.default.readdirSync(attRoot);
61905
+ hashDirs = import_node_fs41.default.readdirSync(attRoot);
61848
61906
  } catch (err) {
61849
61907
  if (err.code === "ENOENT") continue;
61850
61908
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
@@ -61854,7 +61912,7 @@ function runAttachmentGc(args) {
61854
61912
  const hashDirAbs = import_node_path48.default.join(attRoot, hashDir);
61855
61913
  let files;
61856
61914
  try {
61857
- files = import_node_fs40.default.readdirSync(hashDirAbs);
61915
+ files = import_node_fs41.default.readdirSync(hashDirAbs);
61858
61916
  } catch {
61859
61917
  continue;
61860
61918
  }
@@ -61862,7 +61920,7 @@ function runAttachmentGc(args) {
61862
61920
  const file = import_node_path48.default.join(hashDirAbs, name);
61863
61921
  let stat;
61864
61922
  try {
61865
- stat = import_node_fs40.default.statSync(file);
61923
+ stat = import_node_fs41.default.statSync(file);
61866
61924
  } catch {
61867
61925
  continue;
61868
61926
  }
@@ -61871,18 +61929,18 @@ function runAttachmentGc(args) {
61871
61929
  if (age < ttlMs) continue;
61872
61930
  if (liveAbs.has(file)) continue;
61873
61931
  try {
61874
- import_node_fs40.default.unlinkSync(file);
61932
+ import_node_fs41.default.unlinkSync(file);
61875
61933
  } catch (err) {
61876
61934
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
61877
61935
  }
61878
61936
  }
61879
61937
  try {
61880
- if (import_node_fs40.default.readdirSync(hashDirAbs).length === 0) import_node_fs40.default.rmdirSync(hashDirAbs);
61938
+ if (import_node_fs41.default.readdirSync(hashDirAbs).length === 0) import_node_fs41.default.rmdirSync(hashDirAbs);
61881
61939
  } catch {
61882
61940
  }
61883
61941
  }
61884
61942
  try {
61885
- if (import_node_fs40.default.readdirSync(attRoot).length === 0) import_node_fs40.default.rmdirSync(attRoot);
61943
+ if (import_node_fs41.default.readdirSync(attRoot).length === 0) import_node_fs41.default.rmdirSync(attRoot);
61886
61944
  } catch {
61887
61945
  }
61888
61946
  }
@@ -61890,7 +61948,7 @@ function runAttachmentGc(args) {
61890
61948
  }
61891
61949
 
61892
61950
  // src/attachment/group.ts
61893
- var import_node_fs41 = __toESM(require("fs"), 1);
61951
+ var import_node_fs42 = __toESM(require("fs"), 1);
61894
61952
  var import_node_path49 = __toESM(require("path"), 1);
61895
61953
  var import_node_crypto11 = __toESM(require("crypto"), 1);
61896
61954
  init_protocol();
@@ -61916,7 +61974,7 @@ var GroupFileStore = class {
61916
61974
  readFile(scope, sessionId) {
61917
61975
  const file = this.filePath(scope, sessionId);
61918
61976
  try {
61919
- const raw = import_node_fs41.default.readFileSync(file, "utf8");
61977
+ const raw = import_node_fs42.default.readFileSync(file, "utf8");
61920
61978
  const parsed = JSON.parse(raw);
61921
61979
  if (!Array.isArray(parsed)) {
61922
61980
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -61942,10 +62000,10 @@ var GroupFileStore = class {
61942
62000
  }
61943
62001
  writeFile(scope, sessionId, entries) {
61944
62002
  const file = this.filePath(scope, sessionId);
61945
- import_node_fs41.default.mkdirSync(import_node_path49.default.dirname(file), { recursive: true });
62003
+ import_node_fs42.default.mkdirSync(import_node_path49.default.dirname(file), { recursive: true });
61946
62004
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
61947
- import_node_fs41.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
61948
- import_node_fs41.default.renameSync(tmp, file);
62005
+ import_node_fs42.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
62006
+ import_node_fs42.default.renameSync(tmp, file);
61949
62007
  }
61950
62008
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
61951
62009
  list(scope, sessionId) {
@@ -62031,7 +62089,7 @@ var GroupFileStore = class {
62031
62089
  };
62032
62090
 
62033
62091
  // src/discovery/state-file.ts
62034
- var import_node_fs42 = __toESM(require("fs"), 1);
62092
+ var import_node_fs43 = __toESM(require("fs"), 1);
62035
62093
  var import_node_path50 = __toESM(require("path"), 1);
62036
62094
  function defaultStateFilePath(dataDir) {
62037
62095
  return import_node_path50.default.join(dataDir, "state.json");
@@ -62056,7 +62114,7 @@ var StateFileManager = class {
62056
62114
  }
62057
62115
  read() {
62058
62116
  try {
62059
- const raw = import_node_fs42.default.readFileSync(this.file, "utf8");
62117
+ const raw = import_node_fs43.default.readFileSync(this.file, "utf8");
62060
62118
  const parsed = JSON.parse(raw);
62061
62119
  return parsed;
62062
62120
  } catch {
@@ -62070,20 +62128,20 @@ var StateFileManager = class {
62070
62128
  return { status: "stale", existing };
62071
62129
  }
62072
62130
  write(state) {
62073
- import_node_fs42.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
62131
+ import_node_fs43.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
62074
62132
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
62075
- import_node_fs42.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
62076
- import_node_fs42.default.renameSync(tmp, this.file);
62133
+ import_node_fs43.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
62134
+ import_node_fs43.default.renameSync(tmp, this.file);
62077
62135
  if (process.platform !== "win32") {
62078
62136
  try {
62079
- import_node_fs42.default.chmodSync(this.file, 384);
62137
+ import_node_fs43.default.chmodSync(this.file, 384);
62080
62138
  } catch {
62081
62139
  }
62082
62140
  }
62083
62141
  }
62084
62142
  delete() {
62085
62143
  try {
62086
- import_node_fs42.default.unlinkSync(this.file);
62144
+ import_node_fs43.default.unlinkSync(this.file);
62087
62145
  } catch {
62088
62146
  }
62089
62147
  }
@@ -62097,13 +62155,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
62097
62155
  }
62098
62156
 
62099
62157
  // src/tunnel/tunnel-manager.ts
62100
- var import_node_fs46 = __toESM(require("fs"), 1);
62158
+ var import_node_fs47 = __toESM(require("fs"), 1);
62101
62159
  var import_node_path54 = __toESM(require("path"), 1);
62102
62160
  var import_node_crypto12 = __toESM(require("crypto"), 1);
62103
62161
  var import_node_child_process12 = require("child_process");
62104
62162
 
62105
62163
  // src/tunnel/tunnel-store.ts
62106
- var import_node_fs43 = __toESM(require("fs"), 1);
62164
+ var import_node_fs44 = __toESM(require("fs"), 1);
62107
62165
  var import_node_path51 = __toESM(require("path"), 1);
62108
62166
  var TunnelStore = class {
62109
62167
  constructor(filePath) {
@@ -62112,7 +62170,7 @@ var TunnelStore = class {
62112
62170
  filePath;
62113
62171
  async get() {
62114
62172
  try {
62115
- const raw = await import_node_fs43.default.promises.readFile(this.filePath, "utf8");
62173
+ const raw = await import_node_fs44.default.promises.readFile(this.filePath, "utf8");
62116
62174
  const obj = JSON.parse(raw);
62117
62175
  if (!isPersistedTunnel(obj)) return null;
62118
62176
  return obj;
@@ -62124,21 +62182,21 @@ var TunnelStore = class {
62124
62182
  }
62125
62183
  async set(v2) {
62126
62184
  const dir = import_node_path51.default.dirname(this.filePath);
62127
- await import_node_fs43.default.promises.mkdir(dir, { recursive: true });
62185
+ await import_node_fs44.default.promises.mkdir(dir, { recursive: true });
62128
62186
  const data = JSON.stringify(v2, null, 2);
62129
62187
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
62130
- await import_node_fs43.default.promises.writeFile(tmp, data, { mode: 384 });
62188
+ await import_node_fs44.default.promises.writeFile(tmp, data, { mode: 384 });
62131
62189
  if (process.platform !== "win32") {
62132
62190
  try {
62133
- await import_node_fs43.default.promises.chmod(tmp, 384);
62191
+ await import_node_fs44.default.promises.chmod(tmp, 384);
62134
62192
  } catch {
62135
62193
  }
62136
62194
  }
62137
- await import_node_fs43.default.promises.rename(tmp, this.filePath);
62195
+ await import_node_fs44.default.promises.rename(tmp, this.filePath);
62138
62196
  }
62139
62197
  async clear() {
62140
62198
  try {
62141
- await import_node_fs43.default.promises.unlink(this.filePath);
62199
+ await import_node_fs44.default.promises.unlink(this.filePath);
62142
62200
  } catch (err) {
62143
62201
  const code = err?.code;
62144
62202
  if (code !== "ENOENT") throw err;
@@ -62233,7 +62291,7 @@ function escape(v2) {
62233
62291
  }
62234
62292
 
62235
62293
  // src/tunnel/frpc-binary.ts
62236
- var import_node_fs44 = __toESM(require("fs"), 1);
62294
+ var import_node_fs45 = __toESM(require("fs"), 1);
62237
62295
  var import_node_os16 = __toESM(require("os"), 1);
62238
62296
  var import_node_path52 = __toESM(require("path"), 1);
62239
62297
  var import_node_child_process10 = require("child_process");
@@ -62267,7 +62325,7 @@ function frpcDownloadUrl(version2, p2) {
62267
62325
  }
62268
62326
  async function ensureFrpcBinary(opts) {
62269
62327
  if (opts.override) {
62270
- if (!import_node_fs44.default.existsSync(opts.override)) {
62328
+ if (!import_node_fs45.default.existsSync(opts.override)) {
62271
62329
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
62272
62330
  }
62273
62331
  return opts.override;
@@ -62275,10 +62333,10 @@ async function ensureFrpcBinary(opts) {
62275
62333
  const version2 = opts.version ?? FRPC_VERSION;
62276
62334
  const platform = opts.platform ?? detectPlatform();
62277
62335
  const binDir = import_node_path52.default.join(opts.dataDir, "bin");
62278
- import_node_fs44.default.mkdirSync(binDir, { recursive: true });
62336
+ import_node_fs45.default.mkdirSync(binDir, { recursive: true });
62279
62337
  cleanupStaleArtifacts(binDir);
62280
62338
  const stableBin = import_node_path52.default.join(binDir, "frpc");
62281
- if (import_node_fs44.default.existsSync(stableBin)) return stableBin;
62339
+ if (import_node_fs45.default.existsSync(stableBin)) return stableBin;
62282
62340
  const partialBin = `${stableBin}.partial`;
62283
62341
  const tarballPath = import_node_path52.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
62284
62342
  try {
@@ -62289,8 +62347,8 @@ async function ensureFrpcBinary(opts) {
62289
62347
  } else {
62290
62348
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
62291
62349
  }
62292
- import_node_fs44.default.chmodSync(partialBin, 493);
62293
- import_node_fs44.default.renameSync(partialBin, stableBin);
62350
+ import_node_fs45.default.chmodSync(partialBin, 493);
62351
+ import_node_fs45.default.renameSync(partialBin, stableBin);
62294
62352
  } finally {
62295
62353
  safeUnlink(tarballPath);
62296
62354
  safeUnlink(partialBin);
@@ -62300,7 +62358,7 @@ async function ensureFrpcBinary(opts) {
62300
62358
  function cleanupStaleArtifacts(binDir) {
62301
62359
  let entries;
62302
62360
  try {
62303
- entries = import_node_fs44.default.readdirSync(binDir);
62361
+ entries = import_node_fs45.default.readdirSync(binDir);
62304
62362
  } catch {
62305
62363
  return;
62306
62364
  }
@@ -62308,7 +62366,7 @@ function cleanupStaleArtifacts(binDir) {
62308
62366
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
62309
62367
  const full = import_node_path52.default.join(binDir, name);
62310
62368
  try {
62311
- import_node_fs44.default.rmSync(full, { recursive: true, force: true });
62369
+ import_node_fs45.default.rmSync(full, { recursive: true, force: true });
62312
62370
  } catch {
62313
62371
  }
62314
62372
  }
@@ -62316,7 +62374,7 @@ function cleanupStaleArtifacts(binDir) {
62316
62374
  }
62317
62375
  function safeUnlink(p2) {
62318
62376
  try {
62319
- import_node_fs44.default.unlinkSync(p2);
62377
+ import_node_fs45.default.unlinkSync(p2);
62320
62378
  } catch {
62321
62379
  }
62322
62380
  }
@@ -62327,13 +62385,13 @@ async function downloadToFile(url, dest, fetchImpl) {
62327
62385
  if (!res.ok || !res.body) {
62328
62386
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
62329
62387
  }
62330
- const out = import_node_fs44.default.createWriteStream(dest);
62388
+ const out = import_node_fs45.default.createWriteStream(dest);
62331
62389
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
62332
62390
  await (0, import_promises9.pipeline)(nodeStream, out);
62333
62391
  }
62334
62392
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
62335
62393
  const work = import_node_path52.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
62336
- import_node_fs44.default.mkdirSync(work, { recursive: true });
62394
+ import_node_fs45.default.mkdirSync(work, { recursive: true });
62337
62395
  try {
62338
62396
  await new Promise((resolve9, reject) => {
62339
62397
  const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -62342,17 +62400,17 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
62342
62400
  });
62343
62401
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
62344
62402
  const src = import_node_path52.default.join(work, dirName, "frpc");
62345
- if (!import_node_fs44.default.existsSync(src)) {
62403
+ if (!import_node_fs45.default.existsSync(src)) {
62346
62404
  throw new Error(`frpc not found inside tarball at ${src}`);
62347
62405
  }
62348
- import_node_fs44.default.copyFileSync(src, destBin);
62406
+ import_node_fs45.default.copyFileSync(src, destBin);
62349
62407
  } finally {
62350
- import_node_fs44.default.rmSync(work, { recursive: true, force: true });
62408
+ import_node_fs45.default.rmSync(work, { recursive: true, force: true });
62351
62409
  }
62352
62410
  }
62353
62411
 
62354
62412
  // src/tunnel/frpc-process.ts
62355
- var import_node_fs45 = __toESM(require("fs"), 1);
62413
+ var import_node_fs46 = __toESM(require("fs"), 1);
62356
62414
  var import_node_path53 = __toESM(require("path"), 1);
62357
62415
  var import_node_child_process11 = require("child_process");
62358
62416
  function frpcPidFilePath(dataDir) {
@@ -62360,13 +62418,13 @@ function frpcPidFilePath(dataDir) {
62360
62418
  }
62361
62419
  function writeFrpcPid(dataDir, pid) {
62362
62420
  try {
62363
- import_node_fs45.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
62421
+ import_node_fs46.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
62364
62422
  } catch {
62365
62423
  }
62366
62424
  }
62367
62425
  function clearFrpcPid(dataDir) {
62368
62426
  try {
62369
- import_node_fs45.default.unlinkSync(frpcPidFilePath(dataDir));
62427
+ import_node_fs46.default.unlinkSync(frpcPidFilePath(dataDir));
62370
62428
  } catch {
62371
62429
  }
62372
62430
  }
@@ -62382,7 +62440,7 @@ function defaultIsPidAlive(pid) {
62382
62440
  }
62383
62441
  function defaultReadPidFile(file) {
62384
62442
  try {
62385
- return import_node_fs45.default.readFileSync(file, "utf8");
62443
+ return import_node_fs46.default.readFileSync(file, "utf8");
62386
62444
  } catch {
62387
62445
  return null;
62388
62446
  }
@@ -62422,7 +62480,7 @@ async function killStaleFrpc(deps) {
62422
62480
  }
62423
62481
  if (victims.size === 0) {
62424
62482
  try {
62425
- import_node_fs45.default.unlinkSync(pidFile);
62483
+ import_node_fs46.default.unlinkSync(pidFile);
62426
62484
  } catch {
62427
62485
  }
62428
62486
  return;
@@ -62433,7 +62491,7 @@ async function killStaleFrpc(deps) {
62433
62491
  }
62434
62492
  await sleep2(deps.reapWaitMs ?? 300);
62435
62493
  try {
62436
- import_node_fs45.default.unlinkSync(pidFile);
62494
+ import_node_fs46.default.unlinkSync(pidFile);
62437
62495
  } catch {
62438
62496
  }
62439
62497
  }
@@ -62608,14 +62666,14 @@ var TunnelManager = class {
62608
62666
  localPort,
62609
62667
  logLevel: "info"
62610
62668
  });
62611
- await import_node_fs46.default.promises.writeFile(tomlPath, toml, { mode: 384 });
62669
+ await import_node_fs47.default.promises.writeFile(tomlPath, toml, { mode: 384 });
62612
62670
  const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
62613
62671
  stdio: ["ignore", "pipe", "pipe"]
62614
62672
  });
62615
62673
  const logDir = import_node_path54.default.join(this.deps.dataDir, "log");
62616
- import_node_fs46.default.mkdirSync(logDir, { recursive: true });
62674
+ import_node_fs47.default.mkdirSync(logDir, { recursive: true });
62617
62675
  const logFilePath = import_node_path54.default.join(logDir, "frpc.log");
62618
- const logStream = import_node_fs46.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
62676
+ const logStream = import_node_fs47.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
62619
62677
  logStream.on("error", () => {
62620
62678
  });
62621
62679
  const tee = (chunk) => {
@@ -62713,7 +62771,7 @@ function deriveStableDeviceKey(opts = {}) {
62713
62771
  }
62714
62772
 
62715
62773
  // src/auth-store.ts
62716
- var import_node_fs47 = __toESM(require("fs"), 1);
62774
+ var import_node_fs48 = __toESM(require("fs"), 1);
62717
62775
  var import_node_path56 = __toESM(require("path"), 1);
62718
62776
  var import_node_crypto14 = __toESM(require("crypto"), 1);
62719
62777
  var AUTH_FILE_NAME = "auth.json";
@@ -62750,7 +62808,7 @@ function defaultGenerateOwnerPrincipalId() {
62750
62808
  }
62751
62809
  function readAuthFile(file) {
62752
62810
  try {
62753
- const raw = import_node_fs47.default.readFileSync(file, "utf8");
62811
+ const raw = import_node_fs48.default.readFileSync(file, "utf8");
62754
62812
  const parsed = JSON.parse(raw);
62755
62813
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
62756
62814
  return null;
@@ -62770,16 +62828,16 @@ function readAuthFile(file) {
62770
62828
  }
62771
62829
  }
62772
62830
  function writeAuthFile(file, content) {
62773
- import_node_fs47.default.mkdirSync(import_node_path56.default.dirname(file), { recursive: true });
62774
- import_node_fs47.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
62831
+ import_node_fs48.default.mkdirSync(import_node_path56.default.dirname(file), { recursive: true });
62832
+ import_node_fs48.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
62775
62833
  try {
62776
- import_node_fs47.default.chmodSync(file, 384);
62834
+ import_node_fs48.default.chmodSync(file, 384);
62777
62835
  } catch {
62778
62836
  }
62779
62837
  }
62780
62838
 
62781
62839
  // src/owner-profile.ts
62782
- var import_node_fs48 = __toESM(require("fs"), 1);
62840
+ var import_node_fs49 = __toESM(require("fs"), 1);
62783
62841
  var import_node_os18 = __toESM(require("os"), 1);
62784
62842
  var import_node_path57 = __toESM(require("path"), 1);
62785
62843
  var PROFILE_FILENAME = "profile.json";
@@ -62789,7 +62847,7 @@ function profilePath(dataDir) {
62789
62847
  function loadOwnerProfile(dataDir) {
62790
62848
  let raw;
62791
62849
  try {
62792
- raw = import_node_fs48.default.readFileSync(profilePath(dataDir), "utf8");
62850
+ raw = import_node_fs49.default.readFileSync(profilePath(dataDir), "utf8");
62793
62851
  } catch {
62794
62852
  return {};
62795
62853
  }
@@ -62805,7 +62863,7 @@ function loadOwnerProfile(dataDir) {
62805
62863
  }
62806
62864
  function patchOwnerProfile(dataDir, patch) {
62807
62865
  const merged = { ...loadOwnerProfile(dataDir), ...patch };
62808
- import_node_fs48.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
62866
+ import_node_fs49.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
62809
62867
  return merged;
62810
62868
  }
62811
62869
  function loadOwnerDisplayName(dataDir) {
@@ -62821,7 +62879,7 @@ function loadOwnerDisplayName(dataDir) {
62821
62879
  }
62822
62880
 
62823
62881
  // src/feishu-auth/owner-identity-store.ts
62824
- var import_node_fs49 = __toESM(require("fs"), 1);
62882
+ var import_node_fs50 = __toESM(require("fs"), 1);
62825
62883
  var import_node_path58 = __toESM(require("path"), 1);
62826
62884
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
62827
62885
  var OwnerIdentityStore = class {
@@ -62832,7 +62890,7 @@ var OwnerIdentityStore = class {
62832
62890
  read() {
62833
62891
  let raw;
62834
62892
  try {
62835
- raw = import_node_fs49.default.readFileSync(this.file, "utf8");
62893
+ raw = import_node_fs50.default.readFileSync(this.file, "utf8");
62836
62894
  } catch {
62837
62895
  return null;
62838
62896
  }
@@ -62860,16 +62918,16 @@ var OwnerIdentityStore = class {
62860
62918
  };
62861
62919
  }
62862
62920
  write(record3) {
62863
- import_node_fs49.default.mkdirSync(import_node_path58.default.dirname(this.file), { recursive: true });
62864
- import_node_fs49.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
62921
+ import_node_fs50.default.mkdirSync(import_node_path58.default.dirname(this.file), { recursive: true });
62922
+ import_node_fs50.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
62865
62923
  try {
62866
- import_node_fs49.default.chmodSync(this.file, 384);
62924
+ import_node_fs50.default.chmodSync(this.file, 384);
62867
62925
  } catch {
62868
62926
  }
62869
62927
  }
62870
62928
  clear() {
62871
62929
  try {
62872
- import_node_fs49.default.unlinkSync(this.file);
62930
+ import_node_fs50.default.unlinkSync(this.file);
62873
62931
  } catch (err) {
62874
62932
  const code = err?.code;
62875
62933
  if (code !== "ENOENT") throw err;
@@ -63330,7 +63388,7 @@ function verifyConnectToken(args) {
63330
63388
  }
63331
63389
 
63332
63390
  // src/feishu-auth/server-key.ts
63333
- var fs66 = __toESM(require("fs"), 1);
63391
+ var fs67 = __toESM(require("fs"), 1);
63334
63392
  var path71 = __toESM(require("path"), 1);
63335
63393
  var FILE_NAME2 = "server-signing-key.json";
63336
63394
  var ServerKeyStore = class {
@@ -63344,7 +63402,7 @@ var ServerKeyStore = class {
63344
63402
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
63345
63403
  read() {
63346
63404
  try {
63347
- const raw = fs66.readFileSync(this.filePath(), "utf8");
63405
+ const raw = fs67.readFileSync(this.filePath(), "utf8");
63348
63406
  const parsed = JSON.parse(raw);
63349
63407
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
63350
63408
  return parsed.publicKeyPem;
@@ -63359,12 +63417,12 @@ var ServerKeyStore = class {
63359
63417
  publicKeyPem,
63360
63418
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
63361
63419
  };
63362
- fs66.mkdirSync(this.dataDir, { recursive: true });
63363
- fs66.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
63420
+ fs67.mkdirSync(this.dataDir, { recursive: true });
63421
+ fs67.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
63364
63422
  }
63365
63423
  clear() {
63366
63424
  try {
63367
- fs66.unlinkSync(this.filePath());
63425
+ fs67.unlinkSync(this.filePath());
63368
63426
  } catch {
63369
63427
  }
63370
63428
  }
@@ -63380,13 +63438,13 @@ var import_node_path72 = __toESM(require("path"), 1);
63380
63438
  init_protocol();
63381
63439
 
63382
63440
  // src/session/fork.ts
63383
- var import_node_fs50 = __toESM(require("fs"), 1);
63441
+ var import_node_fs51 = __toESM(require("fs"), 1);
63384
63442
  var import_node_os19 = __toESM(require("os"), 1);
63385
63443
  var import_node_path59 = __toESM(require("path"), 1);
63386
63444
  var import_node_crypto16 = require("crypto");
63387
63445
  init_claude_history();
63388
63446
  function readJsonlEntries(file) {
63389
- const raw = import_node_fs50.default.readFileSync(file, "utf8");
63447
+ const raw = import_node_fs51.default.readFileSync(file, "utf8");
63390
63448
  const out = [];
63391
63449
  for (const line of raw.split("\n")) {
63392
63450
  const t = line.trim();
@@ -63402,7 +63460,7 @@ function forkSession(input) {
63402
63460
  const baseDir = input.baseDir ?? import_node_path59.default.join(import_node_os19.default.homedir(), ".claude");
63403
63461
  let projectDir = import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
63404
63462
  let sourceFile = import_node_path59.default.join(projectDir, `${input.toolSessionId}.jsonl`);
63405
- if (!import_node_fs50.default.existsSync(sourceFile)) {
63463
+ if (!import_node_fs51.default.existsSync(sourceFile)) {
63406
63464
  const found = findTranscriptByToolSessionId(
63407
63465
  import_node_path59.default.join(baseDir, "projects"),
63408
63466
  input.toolSessionId
@@ -63442,13 +63500,13 @@ function forkSession(input) {
63442
63500
  }
63443
63501
  const outDir = input.targetCwd ? import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
63444
63502
  const forkedFilePath = import_node_path59.default.join(outDir, `${forkedToolSessionId}.jsonl`);
63445
- import_node_fs50.default.mkdirSync(outDir, { recursive: true });
63446
- import_node_fs50.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
63503
+ import_node_fs51.default.mkdirSync(outDir, { recursive: true });
63504
+ import_node_fs51.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
63447
63505
  return { forkedToolSessionId, forkedFilePath };
63448
63506
  }
63449
63507
 
63450
63508
  // src/session/external-scan.ts
63451
- var import_node_fs51 = __toESM(require("fs"), 1);
63509
+ var import_node_fs52 = __toESM(require("fs"), 1);
63452
63510
  var import_promises10 = __toESM(require("fs/promises"), 1);
63453
63511
  var import_node_os20 = __toESM(require("os"), 1);
63454
63512
  var import_node_path60 = __toESM(require("path"), 1);
@@ -63511,7 +63569,7 @@ function userText(msg) {
63511
63569
  }
63512
63570
  function isDir2(p2) {
63513
63571
  try {
63514
- return import_node_fs51.default.statSync(p2).isDirectory();
63572
+ return import_node_fs52.default.statSync(p2).isDirectory();
63515
63573
  } catch {
63516
63574
  return false;
63517
63575
  }
@@ -63520,7 +63578,7 @@ async function scanClaude(roots) {
63520
63578
  const out = [];
63521
63579
  let dirs;
63522
63580
  try {
63523
- dirs = import_node_fs51.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
63581
+ dirs = import_node_fs52.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
63524
63582
  } catch {
63525
63583
  return out;
63526
63584
  }
@@ -63528,7 +63586,7 @@ async function scanClaude(roots) {
63528
63586
  if (!d.isDirectory()) continue;
63529
63587
  let files;
63530
63588
  try {
63531
- files = import_node_fs51.default.readdirSync(import_node_path60.default.join(roots.claudeProjectsDir, d.name));
63589
+ files = import_node_fs52.default.readdirSync(import_node_path60.default.join(roots.claudeProjectsDir, d.name));
63532
63590
  } catch {
63533
63591
  continue;
63534
63592
  }
@@ -63537,7 +63595,7 @@ async function scanClaude(roots) {
63537
63595
  const file = import_node_path60.default.join(roots.claudeProjectsDir, d.name, name);
63538
63596
  let st;
63539
63597
  try {
63540
- st = import_node_fs51.default.statSync(file);
63598
+ st = import_node_fs52.default.statSync(file);
63541
63599
  } catch {
63542
63600
  continue;
63543
63601
  }
@@ -63590,7 +63648,7 @@ async function scanClaude(roots) {
63590
63648
  return out;
63591
63649
  }
63592
63650
  async function countCodexTurns(rolloutPath) {
63593
- if (!rolloutPath || !import_node_fs51.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
63651
+ if (!rolloutPath || !import_node_fs52.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
63594
63652
  let turns = 0;
63595
63653
  let first = "";
63596
63654
  for await (const rec4 of jsonLines(rolloutPath)) {
@@ -63664,7 +63722,7 @@ async function codexFromRows(rows) {
63664
63722
  async function scanCodex(roots) {
63665
63723
  let dbs = [];
63666
63724
  try {
63667
- dbs = import_node_fs51.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path60.default.join(roots.codexDir, n));
63725
+ dbs = import_node_fs52.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path60.default.join(roots.codexDir, n));
63668
63726
  } catch {
63669
63727
  }
63670
63728
  if (!dbs.length) return [];
@@ -63697,13 +63755,13 @@ async function scanExternalSessions(rootsIn) {
63697
63755
  }
63698
63756
 
63699
63757
  // src/session/import-ledger.ts
63700
- var import_node_fs52 = __toESM(require("fs"), 1);
63758
+ var import_node_fs53 = __toESM(require("fs"), 1);
63701
63759
  var import_node_path61 = __toESM(require("path"), 1);
63702
63760
  var LEDGER_FILENAME = "session-import-ledger.json";
63703
63761
  function readImportLedger(dataDir) {
63704
63762
  try {
63705
63763
  const parsed = JSON.parse(
63706
- import_node_fs52.default.readFileSync(import_node_path61.default.join(dataDir, LEDGER_FILENAME), "utf8")
63764
+ import_node_fs53.default.readFileSync(import_node_path61.default.join(dataDir, LEDGER_FILENAME), "utf8")
63707
63765
  );
63708
63766
  return Array.isArray(parsed) ? parsed : [];
63709
63767
  } catch {
@@ -63714,7 +63772,7 @@ function appendImportLedger(dataDir, entry) {
63714
63772
  const file = import_node_path61.default.join(dataDir, LEDGER_FILENAME);
63715
63773
  const entries = readImportLedger(dataDir);
63716
63774
  entries.push(entry);
63717
- import_node_fs52.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
63775
+ import_node_fs53.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
63718
63776
  }
63719
63777
 
63720
63778
  // src/handlers/session.ts
@@ -64483,7 +64541,7 @@ function buildHistoryHandlers(deps) {
64483
64541
  }
64484
64542
 
64485
64543
  // src/handlers/projects.ts
64486
- var fs70 = __toESM(require("fs"), 1);
64544
+ var fs71 = __toESM(require("fs"), 1);
64487
64545
  var os22 = __toESM(require("os"), 1);
64488
64546
  var path77 = __toESM(require("path"), 1);
64489
64547
  var import_node_child_process14 = require("child_process");
@@ -64492,7 +64550,7 @@ var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
64492
64550
  function allocateDir(root, name) {
64493
64551
  let candidate = path77.join(root, name);
64494
64552
  let n = 2;
64495
- while (fs70.existsSync(candidate)) {
64553
+ while (fs71.existsSync(candidate)) {
64496
64554
  candidate = path77.join(root, `${name} ${n}`);
64497
64555
  n += 1;
64498
64556
  }
@@ -64521,7 +64579,7 @@ function buildProjectHandlers(deps) {
64521
64579
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
64522
64580
  }
64523
64581
  try {
64524
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
64582
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
64525
64583
  } catch {
64526
64584
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
64527
64585
  }
@@ -64537,7 +64595,7 @@ function buildProjectHandlers(deps) {
64537
64595
  let target;
64538
64596
  if (args.path) {
64539
64597
  try {
64540
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
64598
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
64541
64599
  } catch {
64542
64600
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
64543
64601
  }
@@ -64545,15 +64603,15 @@ function buildProjectHandlers(deps) {
64545
64603
  } else {
64546
64604
  const name = args.name;
64547
64605
  try {
64548
- fs70.mkdirSync(root, { recursive: true });
64606
+ fs71.mkdirSync(root, { recursive: true });
64549
64607
  target = allocateDir(root, name);
64550
- fs70.mkdirSync(target);
64608
+ fs71.mkdirSync(target);
64551
64609
  } catch (err) {
64552
64610
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
64553
64611
  }
64554
64612
  const git2 = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
64555
64613
  if (git2.status !== 0) {
64556
- fs70.rmSync(target, { recursive: true, force: true });
64614
+ fs71.rmSync(target, { recursive: true, force: true });
64557
64615
  throw new ClawdError(
64558
64616
  ERROR_CODES.INVALID_CWD,
64559
64617
  `git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
@@ -64676,14 +64734,14 @@ init_protocol();
64676
64734
 
64677
64735
  // src/workspace/git.ts
64678
64736
  var import_node_child_process15 = require("child_process");
64679
- var import_node_fs53 = __toESM(require("fs"), 1);
64737
+ var import_node_fs54 = __toESM(require("fs"), 1);
64680
64738
  var import_node_path62 = __toESM(require("path"), 1);
64681
64739
  var import_node_util = require("util");
64682
64740
  var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
64683
64741
  function normalizePath(p2) {
64684
64742
  const resolved = import_node_path62.default.resolve(p2);
64685
64743
  try {
64686
- return import_node_fs53.default.realpathSync(resolved);
64744
+ return import_node_fs54.default.realpathSync(resolved);
64687
64745
  } catch {
64688
64746
  return resolved;
64689
64747
  }
@@ -65643,10 +65701,10 @@ function computeMethodAccess(args) {
65643
65701
  }
65644
65702
 
65645
65703
  // src/version.ts
65646
- var version = "0.2.498".length > 0 ? "0.2.498" : "dev";
65704
+ var version = "0.2.500".length > 0 ? "0.2.500" : "dev";
65647
65705
 
65648
65706
  // src/cli-probe/probe.ts
65649
- var fs72 = __toESM(require("fs"), 1);
65707
+ var fs73 = __toESM(require("fs"), 1);
65650
65708
  var path81 = __toESM(require("path"), 1);
65651
65709
  var PKG_NAME = "@clawos-dev/clawd";
65652
65710
  var BIN_NAME = "clawd";
@@ -65657,7 +65715,7 @@ function probeGlobalCli(pathEnv) {
65657
65715
  if (!dir) continue;
65658
65716
  let real;
65659
65717
  try {
65660
- real = fs72.realpathSync(path81.join(dir, BIN_NAME));
65718
+ real = fs73.realpathSync(path81.join(dir, BIN_NAME));
65661
65719
  } catch {
65662
65720
  continue;
65663
65721
  }
@@ -65670,7 +65728,7 @@ function readOwnPackageVersion(entryPath) {
65670
65728
  let dir = path81.dirname(entryPath);
65671
65729
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
65672
65730
  try {
65673
- const raw = fs72.readFileSync(path81.join(dir, "package.json"), "utf8");
65731
+ const raw = fs73.readFileSync(path81.join(dir, "package.json"), "utf8");
65674
65732
  const pkg = JSON.parse(raw);
65675
65733
  if (pkg.name !== PKG_NAME) return null;
65676
65734
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
@@ -66745,7 +66803,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
66745
66803
  // src/handlers/app-builder.ts
66746
66804
  init_protocol();
66747
66805
  var import_node_path69 = require("path");
66748
- var import_node_fs54 = require("fs");
66806
+ var import_node_fs55 = require("fs");
66749
66807
  var DEFAULT_TEMPLATE = "nestjs-react";
66750
66808
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
66751
66809
  function buildAppBuilderHandlers(deps) {
@@ -66818,7 +66876,7 @@ function buildAppBuilderHandlers(deps) {
66818
66876
  async function listAllUsersProjects() {
66819
66877
  if (!deps.usersRoot || !deps.getStore) return [];
66820
66878
  const getStore = deps.getStore;
66821
- const userIds = await import_node_fs54.promises.readdir(deps.usersRoot).catch(() => []);
66879
+ const userIds = await import_node_fs55.promises.readdir(deps.usersRoot).catch(() => []);
66822
66880
  const perUser = await Promise.all(
66823
66881
  userIds.map((uid) => getStore(uid).list().catch(() => []))
66824
66882
  );
@@ -68329,7 +68387,7 @@ function buildOnboardingHandlers(deps) {
68329
68387
  }
68330
68388
 
68331
68389
  // src/app-builder-plugin/project-store.ts
68332
- var import_node_fs55 = require("fs");
68390
+ var import_node_fs56 = require("fs");
68333
68391
  var import_node_child_process20 = require("child_process");
68334
68392
  var import_node_path73 = require("path");
68335
68393
  init_protocol();
@@ -68373,7 +68431,7 @@ var ProjectStore = class {
68373
68431
  async list() {
68374
68432
  let entries;
68375
68433
  try {
68376
- entries = await import_node_fs55.promises.readdir(this.projectsRoot());
68434
+ entries = await import_node_fs56.promises.readdir(this.projectsRoot());
68377
68435
  } catch (err) {
68378
68436
  if (err.code === "ENOENT") return [];
68379
68437
  throw err;
@@ -68381,7 +68439,7 @@ var ProjectStore = class {
68381
68439
  const out = [];
68382
68440
  for (const name of entries) {
68383
68441
  try {
68384
- const raw = await import_node_fs55.promises.readFile(this.metaPath(name), "utf8");
68442
+ const raw = await import_node_fs56.promises.readFile(this.metaPath(name), "utf8");
68385
68443
  const json = JSON.parse(raw);
68386
68444
  let migrated = false;
68387
68445
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -68392,7 +68450,7 @@ var ProjectStore = class {
68392
68450
  if (parsed.success) {
68393
68451
  out.push(parsed.data);
68394
68452
  if (migrated) {
68395
- void import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
68453
+ void import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
68396
68454
  });
68397
68455
  }
68398
68456
  }
@@ -68436,8 +68494,8 @@ var ProjectStore = class {
68436
68494
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
68437
68495
  }
68438
68496
  const dir = this.projectDir(name);
68439
- await import_node_fs55.promises.mkdir(dir, { recursive: true });
68440
- await import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
68497
+ await import_node_fs56.promises.mkdir(dir, { recursive: true });
68498
+ await import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
68441
68499
  return meta;
68442
68500
  }
68443
68501
  /**
@@ -68482,7 +68540,7 @@ var ProjectStore = class {
68482
68540
  }
68483
68541
  async delete(name) {
68484
68542
  const dir = this.projectDir(name);
68485
- await import_node_fs55.promises.rm(dir, { recursive: true, force: true });
68543
+ await import_node_fs56.promises.rm(dir, { recursive: true, force: true });
68486
68544
  }
68487
68545
  async updatePort(name, newPort) {
68488
68546
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -68499,7 +68557,7 @@ var ProjectStore = class {
68499
68557
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
68500
68558
  }
68501
68559
  const updated = { ...target, port: newPort };
68502
- await import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
68560
+ await import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
68503
68561
  return updated;
68504
68562
  });
68505
68563
  }
@@ -68518,7 +68576,7 @@ var ProjectStore = class {
68518
68576
  if (!validated.success) {
68519
68577
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
68520
68578
  }
68521
- await import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68579
+ await import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68522
68580
  return validated.data;
68523
68581
  });
68524
68582
  }
@@ -68541,7 +68599,7 @@ var ProjectStore = class {
68541
68599
  if (!validated.success) {
68542
68600
  throw new Error(`invalid publishJob: ${validated.error.message}`);
68543
68601
  }
68544
- await import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68602
+ await import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68545
68603
  return validated.data;
68546
68604
  });
68547
68605
  }
@@ -68558,7 +68616,7 @@ var ProjectStore = class {
68558
68616
  if (!validated.success) {
68559
68617
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
68560
68618
  }
68561
- await import_node_fs55.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68619
+ await import_node_fs56.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
68562
68620
  return validated.data;
68563
68621
  });
68564
68622
  }
@@ -68873,7 +68931,7 @@ var PublishJobRegistry = class {
68873
68931
 
68874
68932
  // src/app-builder-plugin/publish-job-runner.ts
68875
68933
  var import_node_child_process22 = require("child_process");
68876
- var import_node_fs56 = require("fs");
68934
+ var import_node_fs57 = require("fs");
68877
68935
  var import_node_path74 = require("path");
68878
68936
 
68879
68937
  // src/app-builder-plugin/publish-stage-parser.ts
@@ -68909,7 +68967,7 @@ async function startPublishJob(deps, args) {
68909
68967
  const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
68910
68968
  let logStream = null;
68911
68969
  try {
68912
- logStream = (0, import_node_fs56.createWriteStream)(logPath, { flags: "w" });
68970
+ logStream = (0, import_node_fs57.createWriteStream)(logPath, { flags: "w" });
68913
68971
  } catch {
68914
68972
  logStream = null;
68915
68973
  }
@@ -69252,7 +69310,7 @@ async function recoverInterruptedPublishJobs(store, logger) {
69252
69310
  }
69253
69311
 
69254
69312
  // src/app-builder-plugin/mcp-config.ts
69255
- var import_node_fs57 = __toESM(require("fs"), 1);
69313
+ var import_node_fs58 = __toESM(require("fs"), 1);
69256
69314
  var import_node_path75 = __toESM(require("path"), 1);
69257
69315
  function appBuilderMcpConfigPath(dataDir) {
69258
69316
  return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
@@ -69276,8 +69334,8 @@ function writeAppBuilderMcpConfig(args) {
69276
69334
  }
69277
69335
  }
69278
69336
  };
69279
- import_node_fs57.default.mkdirSync(args.dataDir, { recursive: true });
69280
- import_node_fs57.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
69337
+ import_node_fs58.default.mkdirSync(args.dataDir, { recursive: true });
69338
+ import_node_fs58.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf8");
69281
69339
  return cfgPath;
69282
69340
  }
69283
69341
 
@@ -69694,7 +69752,7 @@ async function startDaemon(config) {
69694
69752
  homeDir: import_node_os27.default.homedir()
69695
69753
  });
69696
69754
  const logDir = import_node_path79.default.join(config.dataDir, "log");
69697
- import_node_fs58.default.mkdirSync(logDir, { recursive: true });
69755
+ import_node_fs59.default.mkdirSync(logDir, { recursive: true });
69698
69756
  const logger = createLogger({
69699
69757
  level: config.logLevel,
69700
69758
  file: import_node_path79.default.join(logDir, "clawd.log"),
@@ -69921,7 +69979,7 @@ async function startDaemon(config) {
69921
69979
  import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
69922
69980
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
69923
69981
  ];
69924
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
69982
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69925
69983
  if (dispatchServerScriptPath) {
69926
69984
  const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
69927
69985
  const dispatchCfgPath = writeDispatchMcpConfig({
@@ -69946,7 +70004,7 @@ async function startDaemon(config) {
69946
70004
  import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
69947
70005
  import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69948
70006
  ];
69949
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70007
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69950
70008
  if (ticketServerScriptPath) {
69951
70009
  const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
69952
70010
  const ticketCfgPath = writeTicketMcpConfig({
@@ -69973,7 +70031,7 @@ async function startDaemon(config) {
69973
70031
  import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
69974
70032
  import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69975
70033
  ];
69976
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70034
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69977
70035
  if (shiftServerScriptPath) {
69978
70036
  const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
69979
70037
  const shiftCfgPath = await writeShiftMcpConfig({
@@ -69999,7 +70057,7 @@ async function startDaemon(config) {
69999
70057
  import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
70000
70058
  import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
70001
70059
  ];
70002
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70060
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70003
70061
  if (inboxServerScriptPath) {
70004
70062
  const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
70005
70063
  const inboxCfgPath = await writeInboxMcpConfig({
@@ -70025,7 +70083,7 @@ async function startDaemon(config) {
70025
70083
  import_node_path79.default.join(here, "peer-ops", "mcp-server.cjs"),
70026
70084
  import_node_path79.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
70027
70085
  ];
70028
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70086
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70029
70087
  if (peerOpsServerScriptPath) {
70030
70088
  const peerOpsCfgPath = writePeerOpsMcpConfig({
70031
70089
  dataDir: config.dataDir,
@@ -70048,7 +70106,7 @@ async function startDaemon(config) {
70048
70106
  import_node_path79.default.join(here, "rpc-tool", "mcp-server.cjs"),
70049
70107
  import_node_path79.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
70050
70108
  ];
70051
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70109
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70052
70110
  if (rpcToolServerScriptPath) {
70053
70111
  const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
70054
70112
  const rpcToolCfgPath = writeRpcToolMcpConfig({
@@ -70074,7 +70132,7 @@ async function startDaemon(config) {
70074
70132
  import_node_path79.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
70075
70133
  import_node_path79.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
70076
70134
  ];
70077
- const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70135
+ const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70078
70136
  if (appBuilderServerScriptPath) {
70079
70137
  const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
70080
70138
  const appBuilderCfgPath = writeAppBuilderMcpConfig({
@@ -70180,7 +70238,7 @@ async function startDaemon(config) {
70180
70238
  const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
70181
70239
  let size = 0;
70182
70240
  try {
70183
- size = import_node_fs58.default.statSync(absPath).size;
70241
+ size = import_node_fs59.default.statSync(absPath).size;
70184
70242
  } catch (err) {
70185
70243
  logger.warn("attachment.onFileEdit stat failed", {
70186
70244
  sessionId: input.sessionId,
@@ -70282,11 +70340,11 @@ async function startDaemon(config) {
70282
70340
  registerAdapter("claude", claudeAdapter);
70283
70341
  const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
70284
70342
  try {
70285
- import_node_fs58.default.mkdirSync(codexIsolatedHome, { recursive: true });
70343
+ import_node_fs59.default.mkdirSync(codexIsolatedHome, { recursive: true });
70286
70344
  for (const f of ["auth.json", "config.toml"]) {
70287
70345
  const link = import_node_path79.default.join(codexIsolatedHome, f);
70288
70346
  const target = import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", f);
70289
- if (!import_node_fs58.default.existsSync(link) && import_node_fs58.default.existsSync(target)) import_node_fs58.default.symlinkSync(target, link);
70347
+ if (!import_node_fs59.default.existsSync(link) && import_node_fs59.default.existsSync(target)) import_node_fs59.default.symlinkSync(target, link);
70290
70348
  }
70291
70349
  } catch (err) {
70292
70350
  logger.warn("codex isolated home setup failed", { err: String(err) });
@@ -70309,10 +70367,12 @@ async function startDaemon(config) {
70309
70367
  projectPaths: projectsStore.listMerged().map((x) => x.path),
70310
70368
  sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
70311
70369
  isolatedHome: codexIsolatedHome
70312
- })
70370
+ }),
70371
+ // 附件图片验签:与 http-router /files 路由同一把 secret
70372
+ getSignSecret: () => authFile.token
70313
70373
  })
70314
70374
  );
70315
- registerAdapter(CODEX_CLOUD_TOOL_ID, new CloudCodexAdapter({ client: cloudGateway, logger }));
70375
+ registerAdapter(CODEX_CLOUD_TOOL_ID, new CloudCodexAdapter({ client: cloudGateway, logger, getSignSecret: () => authFile.token }));
70316
70376
  warmCodexFeatureCache();
70317
70377
  const personaRegistry = new PersonaRegistry(personaStore);
70318
70378
  const refreshCloudPersonas = async () => {
@@ -71254,7 +71314,7 @@ ${bar}
71254
71314
  `);
71255
71315
  try {
71256
71316
  const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
71257
- import_node_fs58.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
71317
+ import_node_fs59.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
71258
71318
  } catch {
71259
71319
  }
71260
71320
  } catch (err) {
@@ -71343,7 +71403,7 @@ ${bar}
71343
71403
  function migrateDropPersonsDir(dataDir) {
71344
71404
  const dir = import_node_path79.default.join(dataDir, "persons");
71345
71405
  try {
71346
- import_node_fs58.default.rmSync(dir, { recursive: true, force: true });
71406
+ import_node_fs59.default.rmSync(dir, { recursive: true, force: true });
71347
71407
  } catch {
71348
71408
  }
71349
71409
  }