@clawos-dev/clawd 0.2.499 → 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.
Files changed (2) hide show
  1. package/dist/cli.cjs +619 -564
  2. package/package.json +1 -1
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,16 +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(
51897
- (e) => sink.pushEvents([
51898
+ }).catch((e) => {
51899
+ if (exited) return;
51900
+ sink.pushEvents([
51898
51901
  { kind: "error", message: `turn/start failed: ${e.message}` },
51899
51902
  { kind: "turn_end" }
51900
- ])
51901
- );
51903
+ ]);
51904
+ });
51902
51905
  });
51903
51906
  },
51904
51907
  respondPermission(requestId, allow) {
@@ -52052,6 +52055,200 @@ function warmCodexFeatureCache() {
52052
52055
  );
52053
52056
  }
52054
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
+
52055
52252
  // src/tools/codex-session.ts
52056
52253
  function createCodexSession(ctx, sink, deps = {}) {
52057
52254
  const cmd = process.env.CODEX_BIN ?? "codex";
@@ -52094,7 +52291,15 @@ function createCodexSession(ctx, sink, deps = {}) {
52094
52291
  threadParams: threadStartParams(ctx),
52095
52292
  // persona 惯例装在 <cwd>/.claude/skills/,经 extraRoots 注入 discovery
52096
52293
  // (skills:list RPC 侧 codex-skills.ts 同款注入,两处保持一致)。
52097
- 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
+ },
52098
52303
  kill: (signal) => {
52099
52304
  if (alive()) proc.kill(signal);
52100
52305
  },
@@ -52241,14 +52446,14 @@ function mergeProviderModels(native, provider) {
52241
52446
  // src/tools/codex-provider-models.ts
52242
52447
  var import_node_fs19 = __toESM(require("fs"), 1);
52243
52448
  var import_node_os8 = __toESM(require("os"), 1);
52244
- var import_node_path18 = __toESM(require("path"), 1);
52449
+ var import_node_path19 = __toESM(require("path"), 1);
52245
52450
  var PROVIDER_FETCH_TIMEOUT_MS = 3e3;
52246
52451
  function asRecord(v2) {
52247
52452
  return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : null;
52248
52453
  }
52249
52454
  function readAuthKey(codexHome) {
52250
52455
  try {
52251
- 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"));
52252
52457
  const key = asRecord(raw)?.OPENAI_API_KEY;
52253
52458
  return typeof key === "string" && key ? key : void 0;
52254
52459
  } catch {
@@ -52265,7 +52470,7 @@ function resolveProviderEndpoint(rawConfig, deps = {}) {
52265
52470
  const baseUrl = entry.base_url;
52266
52471
  if (typeof baseUrl !== "string" || !baseUrl) return null;
52267
52472
  const env = deps.env ?? process.env;
52268
- 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");
52269
52474
  const envKey = typeof entry.env_key === "string" && entry.env_key ? entry.env_key : null;
52270
52475
  const token = envKey ? env[envKey] : readAuthKey(codexHome);
52271
52476
  if (!token) {
@@ -52398,6 +52603,7 @@ var CodexAdapter = class {
52398
52603
  fetchImpl;
52399
52604
  /** CODEX_HOME 归属解析(spec 2026-08-18-codex-project-alignment §3.1),由 index.ts 注入 */
52400
52605
  codexHomeFor;
52606
+ getSignSecret;
52401
52607
  // capabilities 的进程级 memo。**回落结果同样被缓存**——否则 codex 没装时每次开弹窗都
52402
52608
  // spawn 一次必然失败的子进程。代价是装好 codex 后要重启 daemon 才恢复,与「codex 升级后
52403
52609
  // 要重启才更新模型表」是同一条语义。
@@ -52410,6 +52616,7 @@ var CodexAdapter = class {
52410
52616
  this.configQueryOverride = opts.configQueryOverride;
52411
52617
  this.fetchImpl = opts.fetchImpl;
52412
52618
  this.codexHomeFor = opts.codexHomeFor;
52619
+ this.getSignSecret = opts.getSignSecret;
52413
52620
  }
52414
52621
  async probe() {
52415
52622
  if (this.probeCache) return this.probeCache;
@@ -52472,7 +52679,8 @@ var CodexAdapter = class {
52472
52679
  createSession(ctx, sink) {
52473
52680
  return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, {
52474
52681
  logger: this.logger,
52475
- codexHomeFor: this.codexHomeFor
52682
+ codexHomeFor: this.codexHomeFor,
52683
+ getSignSecret: this.getSignSecret
52476
52684
  });
52477
52685
  }
52478
52686
  spawn(_ctx) {
@@ -52489,10 +52697,10 @@ var CodexAdapter = class {
52489
52697
  };
52490
52698
 
52491
52699
  // src/tools/claude-tui.ts
52492
- var import_node_crypto5 = require("crypto");
52700
+ var import_node_crypto6 = require("crypto");
52493
52701
  var import_node_fs21 = __toESM(require("fs"), 1);
52494
52702
  var import_node_os9 = __toESM(require("os"), 1);
52495
- var import_node_path19 = __toESM(require("path"), 1);
52703
+ var import_node_path20 = __toESM(require("path"), 1);
52496
52704
  var import_headless = __toESM(require_xterm_headless(), 1);
52497
52705
 
52498
52706
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -53377,7 +53585,7 @@ function observeScreenIdle(surface, opts) {
53377
53585
  };
53378
53586
  }
53379
53587
  function shortHash(s) {
53380
- 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);
53381
53589
  }
53382
53590
  function firstLineDiff(prev, next) {
53383
53591
  const p2 = prev.split("\n");
@@ -53718,7 +53926,7 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
53718
53926
  function jsonlExistsForCtx(ctx) {
53719
53927
  if (!ctx.toolSessionId) return false;
53720
53928
  const home = import_node_os9.default.homedir();
53721
- 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`);
53722
53930
  try {
53723
53931
  return import_node_fs21.default.statSync(file).isFile();
53724
53932
  } catch {
@@ -53805,7 +54013,7 @@ var PersonaDispatchManager = class {
53805
54013
 
53806
54014
  // src/dispatch/store.ts
53807
54015
  var import_promises = __toESM(require("fs/promises"), 1);
53808
- var import_node_path20 = __toESM(require("path"), 1);
54016
+ var import_node_path21 = __toESM(require("path"), 1);
53809
54017
 
53810
54018
  // src/shift/constants.ts
53811
54019
  var MAX_RUNS_PER_SHIFT = 30;
@@ -53843,7 +54051,7 @@ function createDispatchStore(deps) {
53843
54051
  flushTimer = null;
53844
54052
  }
53845
54053
  const content = { version: 1, records };
53846
- 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 });
53847
54055
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53848
54056
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53849
54057
  await import_promises.default.rename(tmp, deps.filePath);
@@ -53912,7 +54120,7 @@ function createDispatchStore(deps) {
53912
54120
 
53913
54121
  // src/channel/json-store.ts
53914
54122
  var import_promises2 = __toESM(require("fs/promises"), 1);
53915
- var import_node_path21 = __toESM(require("path"), 1);
54123
+ var import_node_path22 = __toESM(require("path"), 1);
53916
54124
  function createJsonStore(deps) {
53917
54125
  let items = [];
53918
54126
  let flushTimer = null;
@@ -53923,7 +54131,7 @@ function createJsonStore(deps) {
53923
54131
  flushTimer = null;
53924
54132
  }
53925
54133
  const content = { version: version2, [deps.key]: items };
53926
- 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 });
53927
54135
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
53928
54136
  await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
53929
54137
  await import_promises2.default.rename(tmp, deps.filePath);
@@ -54216,9 +54424,9 @@ function createTopicStore(deps) {
54216
54424
 
54217
54425
  // src/dispatch/mcp-config.ts
54218
54426
  var import_node_fs22 = __toESM(require("fs"), 1);
54219
- var import_node_path22 = __toESM(require("path"), 1);
54427
+ var import_node_path23 = __toESM(require("path"), 1);
54220
54428
  function dispatchMcpConfigPath(dataDir) {
54221
- return import_node_path22.default.join(dataDir, "dispatch.mcp.json");
54429
+ return import_node_path23.default.join(dataDir, "dispatch.mcp.json");
54222
54430
  }
54223
54431
  function writeDispatchMcpConfig(args) {
54224
54432
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -54244,9 +54452,9 @@ function writeDispatchMcpConfig(args) {
54244
54452
 
54245
54453
  // src/ticket/mcp-config.ts
54246
54454
  var import_node_fs23 = __toESM(require("fs"), 1);
54247
- var import_node_path23 = __toESM(require("path"), 1);
54455
+ var import_node_path24 = __toESM(require("path"), 1);
54248
54456
  function ticketMcpConfigPath(dataDir) {
54249
- return import_node_path23.default.join(dataDir, "ticket.mcp.json");
54457
+ return import_node_path24.default.join(dataDir, "ticket.mcp.json");
54250
54458
  }
54251
54459
  function writeTicketMcpConfig(args) {
54252
54460
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -54275,9 +54483,9 @@ function writeTicketMcpConfig(args) {
54275
54483
 
54276
54484
  // src/shift/mcp-config.ts
54277
54485
  var import_node_fs24 = __toESM(require("fs"), 1);
54278
- var import_node_path24 = __toESM(require("path"), 1);
54486
+ var import_node_path25 = __toESM(require("path"), 1);
54279
54487
  function shiftMcpConfigPath(dataDir) {
54280
- return import_node_path24.default.join(dataDir, "shift.mcp.json");
54488
+ return import_node_path25.default.join(dataDir, "shift.mcp.json");
54281
54489
  }
54282
54490
  async function writeShiftMcpConfig(args) {
54283
54491
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -54303,9 +54511,9 @@ async function writeShiftMcpConfig(args) {
54303
54511
 
54304
54512
  // src/inbox/mcp-config.ts
54305
54513
  var import_node_fs25 = __toESM(require("fs"), 1);
54306
- var import_node_path25 = __toESM(require("path"), 1);
54514
+ var import_node_path26 = __toESM(require("path"), 1);
54307
54515
  function inboxMcpConfigPath(dataDir) {
54308
- return import_node_path25.default.join(dataDir, "inbox.mcp.json");
54516
+ return import_node_path26.default.join(dataDir, "inbox.mcp.json");
54309
54517
  }
54310
54518
  async function writeInboxMcpConfig(args) {
54311
54519
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -54331,9 +54539,9 @@ async function writeInboxMcpConfig(args) {
54331
54539
 
54332
54540
  // src/peer-ops/mcp-config.ts
54333
54541
  var import_node_fs26 = __toESM(require("fs"), 1);
54334
- var import_node_path26 = __toESM(require("path"), 1);
54542
+ var import_node_path27 = __toESM(require("path"), 1);
54335
54543
  function peerOpsMcpConfigPath(dataDir) {
54336
- return import_node_path26.default.join(dataDir, "peer-ops.mcp.json");
54544
+ return import_node_path27.default.join(dataDir, "peer-ops.mcp.json");
54337
54545
  }
54338
54546
  function writePeerOpsMcpConfig(args) {
54339
54547
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -54357,9 +54565,9 @@ function writePeerOpsMcpConfig(args) {
54357
54565
 
54358
54566
  // src/rpc-tool/mcp-config.ts
54359
54567
  var import_node_fs27 = __toESM(require("fs"), 1);
54360
- var import_node_path27 = __toESM(require("path"), 1);
54568
+ var import_node_path28 = __toESM(require("path"), 1);
54361
54569
  function rpcToolMcpConfigPath(dataDir) {
54362
- return import_node_path27.default.join(dataDir, "rpc-tool.mcp.json");
54570
+ return import_node_path28.default.join(dataDir, "rpc-tool.mcp.json");
54363
54571
  }
54364
54572
  function writeRpcToolMcpConfig(args) {
54365
54573
  const cfgPath = rpcToolMcpConfigPath(args.dataDir);
@@ -54385,15 +54593,15 @@ function writeRpcToolMcpConfig(args) {
54385
54593
 
54386
54594
  // src/deploy/secret-table.ts
54387
54595
  var import_node_fs28 = __toESM(require("fs"), 1);
54388
- var import_node_path28 = __toESM(require("path"), 1);
54596
+ var import_node_path29 = __toESM(require("path"), 1);
54389
54597
  var import_node_url4 = require("url");
54390
54598
  var import_meta4 = {};
54391
54599
  var LOCAL_SECRETS_DIRNAME = "secrets";
54392
54600
  function findSecretsBundleRoot(logger) {
54393
54601
  const candidates = [];
54394
54602
  try {
54395
- const here = import_node_path28.default.dirname((0, import_node_url4.fileURLToPath)(import_meta4.url));
54396
- 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"));
54397
54605
  } catch {
54398
54606
  }
54399
54607
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "secrets");
@@ -54434,9 +54642,9 @@ function readDir(dir, logger) {
54434
54642
  }
54435
54643
  for (const f of files) {
54436
54644
  try {
54437
- 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")));
54438
54646
  } catch (e) {
54439
- 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 });
54440
54648
  }
54441
54649
  }
54442
54650
  return out;
@@ -54462,14 +54670,14 @@ function collectKitPlaceholders(kitDir) {
54462
54670
  }
54463
54671
  return entries.flatMap((e) => {
54464
54672
  if (e.name === "node_modules") return [];
54465
- const p2 = import_node_path28.default.join(dir, e.name);
54673
+ const p2 = import_node_path29.default.join(dir, e.name);
54466
54674
  return e.isDirectory() ? walk2(p2, depth + 1) : [p2];
54467
54675
  });
54468
54676
  };
54469
- 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)) {
54470
54678
  if (f.endsWith(".tmpl")) scan(f, /__([A-Z0-9_]+)__/g);
54471
54679
  }
54472
- 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)) {
54473
54681
  if (f.endsWith(".env.example")) scan(f, /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g);
54474
54682
  }
54475
54683
  return out;
@@ -54487,12 +54695,12 @@ function readSecretTable(args) {
54487
54695
  }
54488
54696
 
54489
54697
  // src/dispatch/source-transcript.ts
54490
- var import_node_path29 = __toESM(require("path"), 1);
54698
+ var import_node_path30 = __toESM(require("path"), 1);
54491
54699
  init_claude_history();
54492
54700
  var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
54493
54701
  function resolveSourceJsonlPath(sourceFile, home) {
54494
54702
  if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
54495
- return import_node_path29.default.join(
54703
+ return import_node_path30.default.join(
54496
54704
  home,
54497
54705
  ".claude",
54498
54706
  "projects",
@@ -54503,8 +54711,8 @@ function resolveSourceJsonlPath(sourceFile, home) {
54503
54711
 
54504
54712
  // src/shift/store.ts
54505
54713
  var import_promises3 = __toESM(require("fs/promises"), 1);
54506
- var import_node_path30 = __toESM(require("path"), 1);
54507
- var import_node_crypto6 = require("crypto");
54714
+ var import_node_path31 = __toESM(require("path"), 1);
54715
+ var import_node_crypto7 = require("crypto");
54508
54716
 
54509
54717
  // src/shift/schedule.ts
54510
54718
  var import_cron_parser = __toESM(require_dist(), 1);
@@ -54578,7 +54786,7 @@ function createShiftStore(deps) {
54578
54786
  flushTimer = null;
54579
54787
  }
54580
54788
  const content = { version: 1, shifts };
54581
- 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 });
54582
54790
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
54583
54791
  await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
54584
54792
  await import_promises3.default.rename(tmp, deps.filePath);
@@ -54608,7 +54816,7 @@ function createShiftStore(deps) {
54608
54816
  const shift = {
54609
54817
  ...input,
54610
54818
  schedule,
54611
- id: (0, import_node_crypto6.randomUUID)(),
54819
+ id: (0, import_node_crypto7.randomUUID)(),
54612
54820
  createdAtMs: now,
54613
54821
  updatedAtMs: now,
54614
54822
  state: { nextRunAtMs },
@@ -55026,10 +55234,10 @@ function redactEvidence(evidence) {
55026
55234
 
55027
55235
  // src/deploy/deploy-file.ts
55028
55236
  var import_promises4 = __toESM(require("fs/promises"), 1);
55029
- var import_node_path31 = __toESM(require("path"), 1);
55237
+ var import_node_path32 = __toESM(require("path"), 1);
55030
55238
  init_protocol();
55031
- var DEPLOY_FILE = import_node_path31.default.join(".clawd", "deploy.json");
55032
- 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");
55033
55241
  async function readJson(file) {
55034
55242
  let raw;
55035
55243
  try {
@@ -55045,14 +55253,14 @@ async function readJson(file) {
55045
55253
  }
55046
55254
  }
55047
55255
  async function writeJson(file, value) {
55048
- 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 });
55049
55257
  const tmp = `${file}.tmp-${process.pid}`;
55050
55258
  await import_promises4.default.writeFile(tmp, `${JSON.stringify(value, null, 2)}
55051
55259
  `);
55052
55260
  await import_promises4.default.rename(tmp, file);
55053
55261
  }
55054
55262
  async function readDeployFile(dir) {
55055
- 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));
55056
55264
  if (raw === void 0) return void 0;
55057
55265
  const parsed = DeployFileSchema.safeParse(raw);
55058
55266
  if (!parsed.success) {
@@ -55062,10 +55270,10 @@ async function readDeployFile(dir) {
55062
55270
  return parsed.data;
55063
55271
  }
55064
55272
  async function writeDeployFile(dir, file) {
55065
- 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));
55066
55274
  }
55067
55275
  async function readScan(dir) {
55068
- 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));
55069
55277
  if (raw === void 0) return void 0;
55070
55278
  const parsed = DeployScanSchema.safeParse(raw);
55071
55279
  if (!parsed.success) {
@@ -55075,7 +55283,7 @@ async function readScan(dir) {
55075
55283
  return parsed.data;
55076
55284
  }
55077
55285
  async function writeScan(dir, scan) {
55078
- 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));
55079
55287
  }
55080
55288
  function emptyDeployFile() {
55081
55289
  return { version: 1, manifest: { version: 1, clis: [], secrets: [], assets: [], connectors: [] } };
@@ -55115,7 +55323,7 @@ function requiredEnvNames(file) {
55115
55323
  // src/deploy/repo.ts
55116
55324
  var import_node_child_process8 = require("child_process");
55117
55325
  var import_promises5 = __toESM(require("fs/promises"), 1);
55118
- var import_node_path32 = __toESM(require("path"), 1);
55326
+ var import_node_path33 = __toESM(require("path"), 1);
55119
55327
  init_protocol();
55120
55328
 
55121
55329
  // src/deploy/templates.ts
@@ -55349,7 +55557,7 @@ var L = [
55349
55557
  var WORKFLOW_TEMPLATE = L.join("\n");
55350
55558
 
55351
55559
  // src/deploy/repo.ts
55352
- 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("/");
55353
55561
  var DEFAULT_TIMEOUT_MS3 = 6e4;
55354
55562
  var runCommand = (cmd, args, opts = {}) => new Promise((resolve9) => {
55355
55563
  const child = (0, import_node_child_process8.spawn)(cmd, args, {
@@ -55416,7 +55624,7 @@ async function samePath(a, b2) {
55416
55624
  try {
55417
55625
  return await import_promises5.default.realpath(x);
55418
55626
  } catch {
55419
- return import_node_path32.default.resolve(x);
55627
+ return import_node_path33.default.resolve(x);
55420
55628
  }
55421
55629
  };
55422
55630
  return await real(a) === await real(b2);
@@ -55442,7 +55650,7 @@ async function identityArgs(exec, dir) {
55442
55650
  return ["-c", "user.name=clawd", "-c", "user.email=clawd@clawos.local"];
55443
55651
  }
55444
55652
  async function writeTemplates(dir) {
55445
- const gi = import_node_path32.default.join(dir, ".gitignore");
55653
+ const gi = import_node_path33.default.join(dir, ".gitignore");
55446
55654
  let existing;
55447
55655
  try {
55448
55656
  existing = await import_promises5.default.readFile(gi, "utf8");
@@ -55450,8 +55658,8 @@ async function writeTemplates(dir) {
55450
55658
  existing = void 0;
55451
55659
  }
55452
55660
  await import_promises5.default.writeFile(gi, mergeGitignore(existing));
55453
- const wf = import_node_path32.default.join(dir, WORKFLOW_PATH);
55454
- 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 });
55455
55663
  await import_promises5.default.writeFile(wf, WORKFLOW_TEMPLATE);
55456
55664
  }
55457
55665
  async function ensureRepo(exec, args) {
@@ -55641,12 +55849,12 @@ async function rerunJob(exec, slug, runId, jobId) {
55641
55849
  }
55642
55850
 
55643
55851
  // src/deploy/scan-task.ts
55644
- var import_node_path33 = __toESM(require("path"), 1);
55852
+ var import_node_path34 = __toESM(require("path"), 1);
55645
55853
  var BUTLER_PERSONA_ID = "persona-clawd-butler";
55646
55854
  var SCANNABLE_ASSETS = [
55647
55855
  {
55648
55856
  name: "deploy-kit",
55649
- path: (dataDir) => import_node_path33.default.join(dataDir, "deploy-kit"),
55857
+ path: (dataDir) => import_node_path34.default.join(dataDir, "deploy-kit"),
55650
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"
55651
55859
  },
55652
55860
  {
@@ -56380,9 +56588,9 @@ async function refreshTunnelUrlOnStartup(deps) {
56380
56588
 
56381
56589
  // src/lark-bot-connector/binding-store.ts
56382
56590
  var import_node_fs29 = __toESM(require("fs"), 1);
56383
- var import_node_path34 = __toESM(require("path"), 1);
56591
+ var import_node_path35 = __toESM(require("path"), 1);
56384
56592
  function createLarkBotBindingStore(personaRoot) {
56385
- 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");
56386
56594
  const read = (personaId2) => {
56387
56595
  const file = filePath(personaId2);
56388
56596
  if (!import_node_fs29.default.existsSync(file)) return null;
@@ -56396,7 +56604,7 @@ function createLarkBotBindingStore(personaRoot) {
56396
56604
  };
56397
56605
  const write = (personaId2, meta) => {
56398
56606
  const file = filePath(personaId2);
56399
- 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 });
56400
56608
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
56401
56609
  import_node_fs29.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
56402
56610
  import_node_fs29.default.renameSync(tmp, file);
@@ -56564,7 +56772,7 @@ function createLarkBotCloudClient(opts) {
56564
56772
 
56565
56773
  // src/lark-bot-connector/chat-router.ts
56566
56774
  var import_node_fs30 = __toESM(require("fs"), 1);
56567
- var import_node_path35 = __toESM(require("path"), 1);
56775
+ var import_node_path36 = __toESM(require("path"), 1);
56568
56776
  init_protocol();
56569
56777
  var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
56570
56778
  var LOCAL_TURN_RETRIES = 2;
@@ -56643,7 +56851,7 @@ function createLarkChatRouter(deps) {
56643
56851
  }
56644
56852
  const dir = deps.mediaRootFor(env.chatId);
56645
56853
  import_node_fs30.default.mkdirSync(dir, { recursive: true });
56646
- 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}`);
56647
56855
  import_node_fs30.default.writeFileSync(p2, r.data);
56648
56856
  lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56649
56857
  } catch (err) {
@@ -56666,7 +56874,7 @@ function createLarkChatRouter(deps) {
56666
56874
  }
56667
56875
  const dir = deps.mediaRootFor(env.chatId);
56668
56876
  import_node_fs30.default.mkdirSync(dir, { recursive: true });
56669
- 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)}`);
56670
56878
  import_node_fs30.default.writeFileSync(p2, r.data);
56671
56879
  lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
56672
56880
  } catch (err) {
@@ -56881,7 +57089,7 @@ ${formatLarkSpeakerReminder(speaker)}`
56881
57089
  }
56882
57090
 
56883
57091
  // src/lark-bot-connector/envelope.ts
56884
- var import_node_crypto7 = require("crypto");
57092
+ var import_node_crypto8 = require("crypto");
56885
57093
  var LARK_ENVELOPE_PREFIX = "clawdlbe1";
56886
57094
  function verifyLarkEventEnvelope(args) {
56887
57095
  const { token, publicKeyPem } = args;
@@ -56900,7 +57108,7 @@ function verifyLarkEventEnvelope(args) {
56900
57108
  const data = Buffer.from(`${prefix}.${payloadB64}`, "utf8");
56901
57109
  let sigOk = false;
56902
57110
  try {
56903
- 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"));
56904
57112
  } catch {
56905
57113
  sigOk = false;
56906
57114
  }
@@ -57493,11 +57701,11 @@ async function forwardPeerExecToPeer(args) {
57493
57701
 
57494
57702
  // src/tools/codex-history.ts
57495
57703
  var import_node_fs32 = __toESM(require("fs"), 1);
57496
- var import_node_path37 = __toESM(require("path"), 1);
57704
+ var import_node_path38 = __toESM(require("path"), 1);
57497
57705
 
57498
57706
  // src/tools/transcript-search.ts
57499
57707
  var import_node_fs31 = __toESM(require("fs"), 1);
57500
- var import_node_path36 = __toESM(require("path"), 1);
57708
+ var import_node_path37 = __toESM(require("path"), 1);
57501
57709
  var SNIPPET_PAD = 60;
57502
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/;
57503
57711
  var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
@@ -57590,7 +57798,7 @@ function createCodexRolloutLocator(roots) {
57590
57798
  return;
57591
57799
  }
57592
57800
  for (const entry of entries) {
57593
- const full = import_node_path36.default.join(dir, entry.name);
57801
+ const full = import_node_path37.default.join(dir, entry.name);
57594
57802
  if (entry.isDirectory()) {
57595
57803
  walk2(full, into);
57596
57804
  continue;
@@ -57870,7 +58078,7 @@ function readThreadNames(sharedHome) {
57870
58078
  if (!sharedHome) return names;
57871
58079
  let raw;
57872
58080
  try {
57873
- 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");
57874
58082
  } catch {
57875
58083
  return names;
57876
58084
  }
@@ -57895,7 +58103,7 @@ function walkRollouts(dir, visit) {
57895
58103
  }
57896
58104
  entries.sort((a, b2) => a.name < b2.name ? 1 : a.name > b2.name ? -1 : 0);
57897
58105
  for (const entry of entries) {
57898
- const full = import_node_path37.default.join(dir, entry.name);
58106
+ const full = import_node_path38.default.join(dir, entry.name);
57899
58107
  if (entry.isDirectory()) {
57900
58108
  if (!walkRollouts(full, visit)) return false;
57901
58109
  } else if (ROLLOUT_NAME_RE.test(entry.name)) {
@@ -57963,7 +58171,7 @@ var CodexHistoryReader = class {
57963
58171
  return [];
57964
58172
  }
57965
58173
  async listSessions(args) {
57966
- const want = import_node_path37.default.resolve(args.projectPath);
58174
+ const want = import_node_path38.default.resolve(args.projectPath);
57967
58175
  const names = readThreadNames(this.deps.sharedHome);
57968
58176
  const found = [];
57969
58177
  let scanned = 0;
@@ -57972,7 +58180,7 @@ var CodexHistoryReader = class {
57972
58180
  if (++scanned > CODEX_LIST_SESSIONS_SCAN_CAP) return false;
57973
58181
  const head = readHead(file, PEEK_BYTES);
57974
58182
  const cwd = head === null ? null : peekSessionCwd(head);
57975
- if (!cwd || import_node_path37.default.resolve(cwd) !== want) return;
58183
+ if (!cwd || import_node_path38.default.resolve(cwd) !== want) return;
57976
58184
  const first = readFirstLine(file);
57977
58185
  const meta = first === null ? null : parseCodexRolloutMeta(first);
57978
58186
  if (!meta) return;
@@ -58449,6 +58657,9 @@ function openHttpLineStream(opts) {
58449
58657
  // src/tools/codex-cloud.ts
58450
58658
  init_protocol();
58451
58659
 
58660
+ // src/tools/codex-cloud-session.ts
58661
+ var import_node_fs33 = __toESM(require("fs"), 1);
58662
+
58452
58663
  // src/tools/codex-cloud-history.ts
58453
58664
  function personaIdFromCloudCwd(cwd) {
58454
58665
  const m2 = /\/p\/([^/?#]+)(?:[/?#]|$)/.exec(cwd);
@@ -58563,6 +58774,22 @@ function deferredLineStream() {
58563
58774
  }
58564
58775
  };
58565
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
+ }
58566
58793
  function createCloudCodexSession(ctx, sink, deps) {
58567
58794
  const personaId2 = personaIdFromCloudCwd(ctx.cwd);
58568
58795
  const stream = deferredLineStream();
@@ -58572,6 +58799,7 @@ function createCloudCodexSession(ctx, sink, deps) {
58572
58799
  stream,
58573
58800
  logger: deps.logger,
58574
58801
  threadParams: cloudThreadParams(ctx),
58802
+ imageInput: cloudImageInput(deps),
58575
58803
  // skills 在 Pod 里由 persona 目录自带,本机路径对它没意义
58576
58804
  // 「让对端走人」= 断开下行流,gateway 收到就删 Job;信号对 Pod 没有意义
58577
58805
  kill: () => stream.close()
@@ -58628,9 +58856,11 @@ var CloudCodexAdapter = class {
58628
58856
  historyReader;
58629
58857
  client;
58630
58858
  logger;
58859
+ getSignSecret;
58631
58860
  constructor(opts) {
58632
58861
  this.client = opts.client;
58633
58862
  this.logger = opts.logger;
58863
+ this.getSignSecret = opts.getSignSecret;
58634
58864
  this.historyReader = new CloudCodexHistoryReader(opts.client, opts.logger);
58635
58865
  }
58636
58866
  /** 可用 = 能拿到凭据(登了飞书、生成过 key、中心配了 gateway),与本机装没装 codex 无关 */
@@ -58650,7 +58880,7 @@ var CloudCodexAdapter = class {
58650
58880
  return CODEX_CONTEXT_WINDOW;
58651
58881
  }
58652
58882
  createSession(ctx, sink) {
58653
- return createCloudCodexSession(ctx, sink, { client: this.client, logger: this.logger });
58883
+ return createCloudCodexSession(ctx, sink, { client: this.client, logger: this.logger, getSignSecret: this.getSignSecret });
58654
58884
  }
58655
58885
  spawn(_ctx) {
58656
58886
  throw new Error("CloudCodexAdapter uses createSession, not spawn");
@@ -58667,7 +58897,7 @@ var CloudCodexAdapter = class {
58667
58897
  init_protocol();
58668
58898
 
58669
58899
  // src/tools/codex-skills.ts
58670
- var import_node_path38 = __toESM(require("path"), 1);
58900
+ var import_node_path39 = __toESM(require("path"), 1);
58671
58901
  function str3(v2) {
58672
58902
  return typeof v2 === "string" ? v2 : void 0;
58673
58903
  }
@@ -58704,7 +58934,7 @@ async function listCodexSkills(cwd, deps = {}) {
58704
58934
  // 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
58705
58935
  // codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
58706
58936
  beforeRequest: (client) => {
58707
- 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);
58708
58938
  }
58709
58939
  });
58710
58940
  return mapSkillsListResponse(res);
@@ -58778,23 +59008,23 @@ function rec3(v2) {
58778
59008
  }
58779
59009
 
58780
59010
  // src/workspace/browser.ts
58781
- var import_node_fs33 = __toESM(require("fs"), 1);
59011
+ var import_node_fs34 = __toESM(require("fs"), 1);
58782
59012
  var import_node_os10 = __toESM(require("os"), 1);
58783
- var import_node_path39 = __toESM(require("path"), 1);
59013
+ var import_node_path40 = __toESM(require("path"), 1);
58784
59014
  init_protocol();
58785
59015
  var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
58786
59016
  function resolveInsideCwd(cwd, subpath) {
58787
- const absCwd = import_node_path39.default.resolve(cwd);
58788
- const joined = import_node_path39.default.resolve(absCwd, subpath ?? ".");
58789
- const rel = import_node_path39.default.relative(absCwd, joined);
58790
- 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)) {
58791
59021
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
58792
59022
  }
58793
59023
  return joined;
58794
59024
  }
58795
59025
  function ensureCwd(cwd) {
58796
59026
  try {
58797
- const stat = import_node_fs33.default.statSync(cwd);
59027
+ const stat = import_node_fs34.default.statSync(cwd);
58798
59028
  if (!stat.isDirectory()) {
58799
59029
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
58800
59030
  }
@@ -58808,7 +59038,7 @@ var WorkspaceBrowser = class {
58808
59038
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os10.default.homedir();
58809
59039
  ensureCwd(cwd);
58810
59040
  const full = resolveInsideCwd(cwd, args.path);
58811
- const dirents = import_node_fs33.default.readdirSync(full, { withFileTypes: true });
59041
+ const dirents = import_node_fs34.default.readdirSync(full, { withFileTypes: true });
58812
59042
  const entries = [];
58813
59043
  for (const d of dirents) {
58814
59044
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -58818,7 +59048,7 @@ var WorkspaceBrowser = class {
58818
59048
  mtime: ""
58819
59049
  };
58820
59050
  try {
58821
- 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));
58822
59052
  entry.mtime = new Date(st.mtimeMs).toISOString();
58823
59053
  if (d.isFile()) entry.size = st.size;
58824
59054
  } catch {
@@ -58834,14 +59064,14 @@ var WorkspaceBrowser = class {
58834
59064
  read(args) {
58835
59065
  ensureCwd(args.cwd);
58836
59066
  const full = resolveInsideCwd(args.cwd, args.path);
58837
- const st = import_node_fs33.default.statSync(full);
59067
+ const st = import_node_fs34.default.statSync(full);
58838
59068
  if (!st.isFile()) {
58839
59069
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
58840
59070
  }
58841
59071
  if (st.size > MAX_FILE_BYTES2) {
58842
59072
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
58843
59073
  }
58844
- const buf = import_node_fs33.default.readFileSync(full);
59074
+ const buf = import_node_fs34.default.readFileSync(full);
58845
59075
  const isBinary = buf.includes(0);
58846
59076
  if (isBinary) {
58847
59077
  return {
@@ -58863,20 +59093,20 @@ var WorkspaceBrowser = class {
58863
59093
  };
58864
59094
 
58865
59095
  // src/skills/agents-scanner.ts
58866
- var import_node_fs34 = __toESM(require("fs"), 1);
59096
+ var import_node_fs35 = __toESM(require("fs"), 1);
58867
59097
  var import_node_os11 = __toESM(require("os"), 1);
58868
- var import_node_path40 = __toESM(require("path"), 1);
59098
+ var import_node_path41 = __toESM(require("path"), 1);
58869
59099
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
58870
59100
  function isDirLikeSync2(p2) {
58871
59101
  try {
58872
- return import_node_fs34.default.statSync(p2).isDirectory();
59102
+ return import_node_fs35.default.statSync(p2).isDirectory();
58873
59103
  } catch {
58874
59104
  return false;
58875
59105
  }
58876
59106
  }
58877
59107
  function fileExistsSync(p2) {
58878
59108
  try {
58879
- return import_node_fs34.default.statSync(p2).isFile();
59109
+ return import_node_fs35.default.statSync(p2).isFile();
58880
59110
  } catch {
58881
59111
  return false;
58882
59112
  }
@@ -58884,7 +59114,7 @@ function fileExistsSync(p2) {
58884
59114
  function parseAgentFile(filePath) {
58885
59115
  let content;
58886
59116
  try {
58887
- content = import_node_fs34.default.readFileSync(filePath, "utf8");
59117
+ content = import_node_fs35.default.readFileSync(filePath, "utf8");
58888
59118
  } catch {
58889
59119
  return {};
58890
59120
  }
@@ -58897,16 +59127,16 @@ function parseAgentFile(filePath) {
58897
59127
  function scanAgentsDir(dir, source, seen, out) {
58898
59128
  let entries;
58899
59129
  try {
58900
- entries = import_node_fs34.default.readdirSync(dir, { withFileTypes: true });
59130
+ entries = import_node_fs35.default.readdirSync(dir, { withFileTypes: true });
58901
59131
  } catch {
58902
59132
  return;
58903
59133
  }
58904
59134
  for (const ent of entries) {
58905
59135
  if (!ent.name.endsWith(".md")) continue;
58906
- 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)))) {
58907
59137
  continue;
58908
59138
  }
58909
- const filePath = import_node_path40.default.join(dir, ent.name);
59139
+ const filePath = import_node_path41.default.join(dir, ent.name);
58910
59140
  const baseName = ent.name.replace(/\.md$/, "");
58911
59141
  if (seen.has(baseName)) continue;
58912
59142
  seen.add(baseName);
@@ -58924,12 +59154,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58924
59154
  function walk2(dir, namespaces) {
58925
59155
  let entries;
58926
59156
  try {
58927
- entries = import_node_fs34.default.readdirSync(dir, { withFileTypes: true });
59157
+ entries = import_node_fs35.default.readdirSync(dir, { withFileTypes: true });
58928
59158
  } catch {
58929
59159
  return;
58930
59160
  }
58931
59161
  for (const ent of entries) {
58932
- const childPath = import_node_path40.default.join(dir, ent.name);
59162
+ const childPath = import_node_path41.default.join(dir, ent.name);
58933
59163
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
58934
59164
  walk2(childPath, [...namespaces, ent.name]);
58935
59165
  continue;
@@ -58954,13 +59184,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
58954
59184
  walk2(root, []);
58955
59185
  }
58956
59186
  function readInstalledPlugins2(home) {
58957
- const pluginsDir = import_node_path40.default.join(home, ".claude", "plugins");
58958
- const v2 = import_node_path40.default.join(pluginsDir, "installed_plugins_v2.json");
58959
- 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");
58960
59190
  let raw = null;
58961
59191
  for (const candidate of [v2, v1]) {
58962
59192
  try {
58963
- raw = import_node_fs34.default.readFileSync(candidate, "utf8");
59193
+ raw = import_node_fs35.default.readFileSync(candidate, "utf8");
58964
59194
  break;
58965
59195
  } catch {
58966
59196
  }
@@ -58985,19 +59215,19 @@ function readInstalledPlugins2(home) {
58985
59215
  return out;
58986
59216
  }
58987
59217
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
58988
- let cur = import_node_path40.default.resolve(startCwd);
58989
- 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;
58990
59220
  while (true) {
58991
- 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);
58992
59222
  let hasGit = false;
58993
59223
  try {
58994
- 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"));
58995
59225
  } catch {
58996
59226
  }
58997
59227
  if (hasGit) return;
58998
59228
  if (cur === home) return;
58999
59229
  if (cur === fsRoot) return;
59000
- const parent = import_node_path40.default.dirname(cur);
59230
+ const parent = import_node_path41.default.dirname(cur);
59001
59231
  if (parent === cur) return;
59002
59232
  cur = parent;
59003
59233
  }
@@ -59032,7 +59262,7 @@ var AgentsScanner = class {
59032
59262
  }
59033
59263
  const fsBlock = [];
59034
59264
  scanAgentsDir(
59035
- import_node_path40.default.join(this.home, ".claude", "agents"),
59265
+ import_node_path41.default.join(this.home, ".claude", "agents"),
59036
59266
  "global",
59037
59267
  seen,
59038
59268
  fsBlock
@@ -59046,7 +59276,7 @@ var AgentsScanner = class {
59046
59276
  ...this.extraPluginRoots
59047
59277
  ];
59048
59278
  for (const { name, root } of plugins) {
59049
- const agentsRoot = import_node_path40.default.join(root, "agents");
59279
+ const agentsRoot = import_node_path41.default.join(root, "agents");
59050
59280
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
59051
59281
  }
59052
59282
  return [...builtinBlock, ...fsBlock];
@@ -59054,15 +59284,15 @@ var AgentsScanner = class {
59054
59284
  };
59055
59285
 
59056
59286
  // src/observer/session-observer.ts
59057
- var import_node_fs36 = __toESM(require("fs"), 1);
59287
+ var import_node_fs37 = __toESM(require("fs"), 1);
59058
59288
  var import_node_os13 = __toESM(require("os"), 1);
59059
- var import_node_path42 = __toESM(require("path"), 1);
59289
+ var import_node_path43 = __toESM(require("path"), 1);
59060
59290
  init_claude_history();
59061
59291
 
59062
59292
  // src/observer/subagent-meta-observer.ts
59063
- var import_node_fs35 = __toESM(require("fs"), 1);
59293
+ var import_node_fs36 = __toESM(require("fs"), 1);
59064
59294
  var import_node_os12 = __toESM(require("os"), 1);
59065
- var import_node_path41 = __toESM(require("path"), 1);
59295
+ var import_node_path42 = __toESM(require("path"), 1);
59066
59296
  init_claude_history();
59067
59297
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
59068
59298
  var SubagentMetaObserver = class {
@@ -59075,7 +59305,7 @@ var SubagentMetaObserver = class {
59075
59305
  watches = /* @__PURE__ */ new Map();
59076
59306
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
59077
59307
  resolveSubagentDir(cwd, toolSessionId) {
59078
- return import_node_path41.default.join(
59308
+ return import_node_path42.default.join(
59079
59309
  this.home,
59080
59310
  ".claude",
59081
59311
  "projects",
@@ -59105,7 +59335,7 @@ var SubagentMetaObserver = class {
59105
59335
  attachWatcher(w2) {
59106
59336
  if (w2.watcher) return;
59107
59337
  try {
59108
- 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) => {
59109
59339
  if (!name) return;
59110
59340
  const m2 = META_RE.exec(String(name));
59111
59341
  if (!m2) return;
@@ -59117,7 +59347,7 @@ var SubagentMetaObserver = class {
59117
59347
  scan(w2) {
59118
59348
  let entries;
59119
59349
  try {
59120
- entries = import_node_fs35.default.readdirSync(w2.dirPath);
59350
+ entries = import_node_fs36.default.readdirSync(w2.dirPath);
59121
59351
  } catch {
59122
59352
  return;
59123
59353
  }
@@ -59131,10 +59361,10 @@ var SubagentMetaObserver = class {
59131
59361
  if (!m2) return;
59132
59362
  const agentId = m2[1];
59133
59363
  if (w2.emitted.has(agentId)) return;
59134
- const file = import_node_path41.default.join(w2.dirPath, name);
59364
+ const file = import_node_path42.default.join(w2.dirPath, name);
59135
59365
  let raw;
59136
59366
  try {
59137
- raw = import_node_fs35.default.readFileSync(file, "utf8");
59367
+ raw = import_node_fs36.default.readFileSync(file, "utf8");
59138
59368
  } catch {
59139
59369
  return;
59140
59370
  }
@@ -59191,14 +59421,14 @@ var SessionObserver = class {
59191
59421
  metaObserver;
59192
59422
  resolveJsonlPath(cwd, toolSessionId, override) {
59193
59423
  if (override) return override;
59194
- 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`);
59195
59425
  }
59196
59426
  start(args) {
59197
59427
  this.stop(args.sessionId);
59198
59428
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
59199
59429
  let size = 0;
59200
59430
  try {
59201
- size = import_node_fs36.default.statSync(filePath).size;
59431
+ size = import_node_fs37.default.statSync(filePath).size;
59202
59432
  } catch {
59203
59433
  }
59204
59434
  const w2 = {
@@ -59211,16 +59441,16 @@ var SessionObserver = class {
59211
59441
  adapter: args.adapter,
59212
59442
  prevIsRejectSentinel: false,
59213
59443
  toolSessionId: args.toolSessionId,
59214
- sawFile: import_node_fs36.default.existsSync(filePath),
59444
+ sawFile: import_node_fs37.default.existsSync(filePath),
59215
59445
  lastRelocateScanMs: 0,
59216
59446
  pendingCwdDerive: false,
59217
59447
  lastDeriveMs: 0
59218
59448
  };
59219
59449
  try {
59220
- 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 });
59221
59451
  } catch {
59222
59452
  }
59223
- 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) => {
59224
59454
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
59225
59455
  this.poll(w2);
59226
59456
  });
@@ -59243,7 +59473,7 @@ var SessionObserver = class {
59243
59473
  // 异常静默吞,不阻塞 watcher 启动
59244
59474
  hydrateMetaTail(w2, maxLines = 200) {
59245
59475
  try {
59246
- const raw = import_node_fs36.default.readFileSync(w2.filePath, "utf8");
59476
+ const raw = import_node_fs37.default.readFileSync(w2.filePath, "utf8");
59247
59477
  if (!raw) return;
59248
59478
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
59249
59479
  if (allLines.length === 0) return;
@@ -59267,7 +59497,7 @@ var SessionObserver = class {
59267
59497
  poll(w2) {
59268
59498
  let size = 0;
59269
59499
  try {
59270
- size = import_node_fs36.default.statSync(w2.filePath).size;
59500
+ size = import_node_fs37.default.statSync(w2.filePath).size;
59271
59501
  } catch {
59272
59502
  if (w2.sawFile) this.maybeRelocate(w2);
59273
59503
  return;
@@ -59278,11 +59508,11 @@ var SessionObserver = class {
59278
59508
  w2.buf = "";
59279
59509
  }
59280
59510
  if (size === w2.lastSize) return;
59281
- const fd = import_node_fs36.default.openSync(w2.filePath, "r");
59511
+ const fd = import_node_fs37.default.openSync(w2.filePath, "r");
59282
59512
  try {
59283
59513
  const len = size - w2.lastSize;
59284
59514
  const buf = Buffer.alloc(len);
59285
- import_node_fs36.default.readSync(fd, buf, 0, len, w2.lastSize);
59515
+ import_node_fs37.default.readSync(fd, buf, 0, len, w2.lastSize);
59286
59516
  w2.lastSize = size;
59287
59517
  w2.buf += buf.toString("utf8");
59288
59518
  let newlineIndex;
@@ -59305,7 +59535,7 @@ var SessionObserver = class {
59305
59535
  }
59306
59536
  }
59307
59537
  } finally {
59308
- import_node_fs36.default.closeSync(fd);
59538
+ import_node_fs37.default.closeSync(fd);
59309
59539
  }
59310
59540
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
59311
59541
  }
@@ -59317,7 +59547,7 @@ var SessionObserver = class {
59317
59547
  const now = Date.now();
59318
59548
  if (now - w2.lastRelocateScanMs < 1e3) return;
59319
59549
  w2.lastRelocateScanMs = now;
59320
- const projectsRoot = import_node_path42.default.join(this.home, ".claude", "projects");
59550
+ const projectsRoot = import_node_path43.default.join(this.home, ".claude", "projects");
59321
59551
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
59322
59552
  if (!found || found === w2.filePath) return;
59323
59553
  try {
@@ -59326,7 +59556,7 @@ var SessionObserver = class {
59326
59556
  }
59327
59557
  w2.filePath = found;
59328
59558
  try {
59329
- 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) => {
59330
59560
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
59331
59561
  this.poll(w2);
59332
59562
  });
@@ -59448,9 +59678,9 @@ function listRegistered() {
59448
59678
  // src/tools/title-generator.ts
59449
59679
  var import_node_child_process9 = require("child_process");
59450
59680
  init_protocol();
59451
- var import_node_fs37 = __toESM(require("fs"), 1);
59681
+ var import_node_fs38 = __toESM(require("fs"), 1);
59452
59682
  var import_node_os14 = __toESM(require("os"), 1);
59453
- var import_node_path43 = __toESM(require("path"), 1);
59683
+ var import_node_path44 = __toESM(require("path"), 1);
59454
59684
  var TITLE_GEN_DIR_PREFIX = "clawd-title-";
59455
59685
  var TITLE_MODEL_BY_TOOL = {
59456
59686
  claude: "haiku",
@@ -59521,21 +59751,21 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
59521
59751
  if (!text) return null;
59522
59752
  let workDir;
59523
59753
  try {
59524
- 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));
59525
59755
  } catch {
59526
59756
  return null;
59527
59757
  }
59528
59758
  const cleanupWorkDir = () => {
59529
59759
  try {
59530
- import_node_fs37.default.rmSync(workDir, { recursive: true, force: true });
59760
+ import_node_fs38.default.rmSync(workDir, { recursive: true, force: true });
59531
59761
  } catch {
59532
59762
  }
59533
59763
  };
59534
- const outFile = import_node_path43.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
59535
- 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");
59536
59766
  if (isCodexFamily(tool)) {
59537
59767
  try {
59538
- import_node_fs37.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
59768
+ import_node_fs38.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
59539
59769
  } catch {
59540
59770
  cleanupWorkDir();
59541
59771
  return null;
@@ -59585,7 +59815,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
59585
59815
  if (tool === "claude") return finish(parseTitleJson(stdout));
59586
59816
  let fileText = "";
59587
59817
  try {
59588
- fileText = import_node_fs37.default.readFileSync(outFile, "utf8");
59818
+ fileText = import_node_fs38.default.readFileSync(outFile, "utf8");
59589
59819
  } catch {
59590
59820
  return finish(null);
59591
59821
  }
@@ -59607,7 +59837,7 @@ var wrapper_default = import_websocket.default;
59607
59837
 
59608
59838
  // src/transport/local-ws-server.ts
59609
59839
  var import_node_http2 = __toESM(require("http"), 1);
59610
- var import_node_crypto8 = require("crypto");
59840
+ var import_node_crypto9 = require("crypto");
59611
59841
 
59612
59842
  // src/transport/preview-proxy.ts
59613
59843
  var import_node_http = __toESM(require("http"), 1);
@@ -59891,7 +60121,7 @@ var LocalWsServer = class {
59891
60121
  }
59892
60122
  }
59893
60123
  onConnection(socket, remoteAddress) {
59894
- const id = (0, import_node_crypto8.randomUUID)();
60124
+ const id = (0, import_node_crypto9.randomUUID)();
59895
60125
  const subscribedSessions = /* @__PURE__ */ new Map();
59896
60126
  const handle = {
59897
60127
  id,
@@ -60297,8 +60527,8 @@ async function authenticate(token, deps) {
60297
60527
  }
60298
60528
 
60299
60529
  // src/legacy-cleanup.ts
60300
- var fs48 = __toESM(require("fs/promises"), 1);
60301
- var path51 = __toESM(require("path"), 1);
60530
+ var fs49 = __toESM(require("fs/promises"), 1);
60531
+ var path52 = __toESM(require("path"), 1);
60302
60532
  var LEGACY_FILES = [
60303
60533
  "personal-capability.json",
60304
60534
  "received-capabilities.json",
@@ -60307,9 +60537,9 @@ var LEGACY_FILES = [
60307
60537
  async function cleanupLegacyCapabilityFiles(dataDir, logger) {
60308
60538
  const removed = [];
60309
60539
  for (const name of LEGACY_FILES) {
60310
- const p2 = path51.join(dataDir, name);
60540
+ const p2 = path52.join(dataDir, name);
60311
60541
  try {
60312
- await fs48.unlink(p2);
60542
+ await fs49.unlink(p2);
60313
60543
  removed.push(name);
60314
60544
  logger.debug("legacy capability file removed", { file: name });
60315
60545
  } catch (err) {
@@ -60321,13 +60551,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
60321
60551
  }
60322
60552
 
60323
60553
  // src/inbox/inbox-store.ts
60324
- var fs49 = __toESM(require("fs"), 1);
60325
- var path52 = __toESM(require("path"), 1);
60554
+ var fs50 = __toESM(require("fs"), 1);
60555
+ var path53 = __toESM(require("path"), 1);
60326
60556
  var INBOX_SUBDIR = "inbox";
60327
60557
  var InboxStore = class {
60328
60558
  constructor(dataDir) {
60329
60559
  this.dataDir = dataDir;
60330
- fs49.mkdirSync(this.dirPath(), { recursive: true });
60560
+ fs50.mkdirSync(this.dirPath(), { recursive: true });
60331
60561
  }
60332
60562
  dataDir;
60333
60563
  /**
@@ -60339,7 +60569,7 @@ var InboxStore = class {
60339
60569
  const file = this.filePath(peerDeviceId);
60340
60570
  let raw;
60341
60571
  try {
60342
- raw = fs49.readFileSync(file, "utf8");
60572
+ raw = fs50.readFileSync(file, "utf8");
60343
60573
  } catch (err) {
60344
60574
  if (err?.code === "ENOENT") return [];
60345
60575
  return [];
@@ -60355,7 +60585,7 @@ var InboxStore = class {
60355
60585
  const dir = this.dirPath();
60356
60586
  let entries;
60357
60587
  try {
60358
- entries = fs49.readdirSync(dir);
60588
+ entries = fs50.readdirSync(dir);
60359
60589
  } catch (err) {
60360
60590
  if (err?.code === "ENOENT") return [];
60361
60591
  return [];
@@ -60371,9 +60601,9 @@ var InboxStore = class {
60371
60601
  if (existing.some((m2) => m2.id === message.id)) return;
60372
60602
  const file = this.filePath(message.peerDeviceId);
60373
60603
  const line = JSON.stringify(message) + "\n";
60374
- fs49.appendFileSync(file, line, { mode: 384 });
60604
+ fs50.appendFileSync(file, line, { mode: 384 });
60375
60605
  try {
60376
- fs49.chmodSync(file, 384);
60606
+ fs50.chmodSync(file, 384);
60377
60607
  } catch {
60378
60608
  }
60379
60609
  }
@@ -60403,7 +60633,7 @@ var InboxStore = class {
60403
60633
  removeByPeerDeviceId(peerDeviceId) {
60404
60634
  const file = this.filePath(peerDeviceId);
60405
60635
  try {
60406
- fs49.unlinkSync(file);
60636
+ fs50.unlinkSync(file);
60407
60637
  } catch (err) {
60408
60638
  if (err?.code === "ENOENT") return;
60409
60639
  }
@@ -60412,18 +60642,18 @@ var InboxStore = class {
60412
60642
  const file = this.filePath(peerDeviceId);
60413
60643
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
60414
60644
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
60415
- fs49.writeFileSync(tmp, content, { mode: 384 });
60416
- fs49.renameSync(tmp, file);
60645
+ fs50.writeFileSync(tmp, content, { mode: 384 });
60646
+ fs50.renameSync(tmp, file);
60417
60647
  try {
60418
- fs49.chmodSync(file, 384);
60648
+ fs50.chmodSync(file, 384);
60419
60649
  } catch {
60420
60650
  }
60421
60651
  }
60422
60652
  dirPath() {
60423
- return path52.join(this.dataDir, INBOX_SUBDIR);
60653
+ return path53.join(this.dataDir, INBOX_SUBDIR);
60424
60654
  }
60425
60655
  filePath(peerDeviceId) {
60426
- return path52.join(this.dirPath(), `${peerDeviceId}.jsonl`);
60656
+ return path53.join(this.dirPath(), `${peerDeviceId}.jsonl`);
60427
60657
  }
60428
60658
  };
60429
60659
  function parseAllLines(raw) {
@@ -60511,8 +60741,8 @@ var InboxManager = class {
60511
60741
  };
60512
60742
 
60513
60743
  // src/state/contact-store.ts
60514
- var fs50 = __toESM(require("fs"), 1);
60515
- var path53 = __toESM(require("path"), 1);
60744
+ var fs51 = __toESM(require("fs"), 1);
60745
+ var path54 = __toESM(require("path"), 1);
60516
60746
  var FILE_NAME = "contacts.json";
60517
60747
  var ContactStore = class {
60518
60748
  constructor(dataDir) {
@@ -60522,10 +60752,10 @@ var ContactStore = class {
60522
60752
  contacts = /* @__PURE__ */ new Map();
60523
60753
  load() {
60524
60754
  this.contacts.clear();
60525
- const file = path53.join(this.dataDir, FILE_NAME);
60755
+ const file = path54.join(this.dataDir, FILE_NAME);
60526
60756
  let raw;
60527
60757
  try {
60528
- raw = fs50.readFileSync(file, "utf8");
60758
+ raw = fs51.readFileSync(file, "utf8");
60529
60759
  } catch (err) {
60530
60760
  if (err?.code !== "ENOENT") this.renameBak(file);
60531
60761
  return;
@@ -60606,27 +60836,27 @@ var ContactStore = class {
60606
60836
  return true;
60607
60837
  }
60608
60838
  flush() {
60609
- const file = path53.join(this.dataDir, FILE_NAME);
60839
+ const file = path54.join(this.dataDir, FILE_NAME);
60610
60840
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
60611
60841
  const content = JSON.stringify(
60612
60842
  { contacts: Array.from(this.contacts.values()) },
60613
60843
  null,
60614
60844
  2
60615
60845
  );
60616
- fs50.mkdirSync(this.dataDir, { recursive: true });
60617
- fs50.writeFileSync(tmp, content, { mode: 384 });
60618
- fs50.renameSync(tmp, file);
60846
+ fs51.mkdirSync(this.dataDir, { recursive: true });
60847
+ fs51.writeFileSync(tmp, content, { mode: 384 });
60848
+ fs51.renameSync(tmp, file);
60619
60849
  }
60620
60850
  renameBak(file) {
60621
60851
  try {
60622
- fs50.renameSync(file, `${file}.bak`);
60852
+ fs51.renameSync(file, `${file}.bak`);
60623
60853
  } catch {
60624
60854
  }
60625
60855
  }
60626
60856
  };
60627
60857
 
60628
60858
  // src/contact/connect-remote.ts
60629
- var crypto3 = __toESM(require("crypto"), 1);
60859
+ var crypto4 = __toESM(require("crypto"), 1);
60630
60860
  init_protocol();
60631
60861
  var HANDSHAKE_TIMEOUT_MS = 5e3;
60632
60862
  var RPC_TIMEOUT_MS = 5e3;
@@ -60681,7 +60911,7 @@ async function connectRemote(args) {
60681
60911
  ws.once("close", onClose);
60682
60912
  });
60683
60913
  function call(method, payload) {
60684
- const requestId = crypto3.randomUUID();
60914
+ const requestId = crypto4.randomUUID();
60685
60915
  return new Promise((resolve9, reject) => {
60686
60916
  const onMessage = (raw) => {
60687
60917
  let f;
@@ -60727,61 +60957,61 @@ async function connectRemote(args) {
60727
60957
  }
60728
60958
 
60729
60959
  // src/migrations/2026-05-20-flatten-sessions.ts
60730
- var fs51 = __toESM(require("fs"), 1);
60731
- var path54 = __toESM(require("path"), 1);
60960
+ var fs52 = __toESM(require("fs"), 1);
60961
+ var path55 = __toESM(require("path"), 1);
60732
60962
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
60733
60963
  function migrateFlattenSessions(opts) {
60734
60964
  const dataDir = opts.dataDir;
60735
60965
  const now = opts.now ?? Date.now;
60736
- const sessionsDir = path54.join(dataDir, "sessions");
60737
- const flagPath = path54.join(sessionsDir, MIGRATION_FLAG_NAME);
60966
+ const sessionsDir = path55.join(dataDir, "sessions");
60967
+ const flagPath = path55.join(sessionsDir, MIGRATION_FLAG_NAME);
60738
60968
  if (existsSync3(flagPath)) {
60739
60969
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
60740
60970
  }
60741
60971
  let movedBare = 0;
60742
60972
  let movedVmOwner = 0;
60743
60973
  let archivedListener = 0;
60744
- const defaultDir = path54.join(sessionsDir, "default");
60974
+ const defaultDir = path55.join(sessionsDir, "default");
60745
60975
  if (existsSync3(defaultDir)) {
60746
60976
  for (const entry of readdirSafe(defaultDir)) {
60747
60977
  if (!entry.endsWith(".json")) continue;
60748
- const src = path54.join(defaultDir, entry);
60749
- const dst = path54.join(sessionsDir, entry);
60750
- fs51.renameSync(src, dst);
60978
+ const src = path55.join(defaultDir, entry);
60979
+ const dst = path55.join(sessionsDir, entry);
60980
+ fs52.renameSync(src, dst);
60751
60981
  movedBare += 1;
60752
60982
  }
60753
60983
  rmdirIfEmpty(defaultDir);
60754
60984
  }
60755
60985
  for (const pid of readdirSafe(sessionsDir)) {
60756
- const personaDir = path54.join(sessionsDir, pid);
60986
+ const personaDir = path55.join(sessionsDir, pid);
60757
60987
  if (!isDir(personaDir)) continue;
60758
60988
  if (pid === "default") continue;
60759
- const ownerSrc = path54.join(personaDir, "owner");
60989
+ const ownerSrc = path55.join(personaDir, "owner");
60760
60990
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
60761
- const ownerDst = path54.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
60762
- fs51.mkdirSync(ownerDst, { recursive: true });
60991
+ const ownerDst = path55.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
60992
+ fs52.mkdirSync(ownerDst, { recursive: true });
60763
60993
  for (const file of readdirSafe(ownerSrc)) {
60764
60994
  if (!file.endsWith(".json")) continue;
60765
- fs51.renameSync(path54.join(ownerSrc, file), path54.join(ownerDst, file));
60995
+ fs52.renameSync(path55.join(ownerSrc, file), path55.join(ownerDst, file));
60766
60996
  movedVmOwner += 1;
60767
60997
  }
60768
60998
  rmdirIfEmpty(ownerSrc);
60769
60999
  }
60770
- const listenerSrc = path54.join(personaDir, "listener");
61000
+ const listenerSrc = path55.join(personaDir, "listener");
60771
61001
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
60772
- const archiveDst = path54.join(dataDir, ".legacy", `listener-${pid}`);
60773
- fs51.mkdirSync(archiveDst, { recursive: true });
61002
+ const archiveDst = path55.join(dataDir, ".legacy", `listener-${pid}`);
61003
+ fs52.mkdirSync(archiveDst, { recursive: true });
60774
61004
  for (const file of readdirSafe(listenerSrc)) {
60775
61005
  if (!file.endsWith(".json")) continue;
60776
- fs51.renameSync(path54.join(listenerSrc, file), path54.join(archiveDst, file));
61006
+ fs52.renameSync(path55.join(listenerSrc, file), path55.join(archiveDst, file));
60777
61007
  archivedListener += 1;
60778
61008
  }
60779
61009
  rmdirIfEmpty(listenerSrc);
60780
61010
  }
60781
61011
  rmdirIfEmpty(personaDir);
60782
61012
  }
60783
- fs51.mkdirSync(sessionsDir, { recursive: true });
60784
- 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));
60785
61015
  return {
60786
61016
  skipped: false,
60787
61017
  flagWritten: true,
@@ -60792,7 +61022,7 @@ function migrateFlattenSessions(opts) {
60792
61022
  }
60793
61023
  function existsSync3(p2) {
60794
61024
  try {
60795
- fs51.statSync(p2);
61025
+ fs52.statSync(p2);
60796
61026
  return true;
60797
61027
  } catch {
60798
61028
  return false;
@@ -60800,238 +61030,61 @@ function existsSync3(p2) {
60800
61030
  }
60801
61031
  function isDir(p2) {
60802
61032
  try {
60803
- return fs51.statSync(p2).isDirectory();
61033
+ return fs52.statSync(p2).isDirectory();
60804
61034
  } catch {
60805
61035
  return false;
60806
61036
  }
60807
61037
  }
60808
61038
  function readdirSafe(p2) {
60809
61039
  try {
60810
- return fs51.readdirSync(p2);
61040
+ return fs52.readdirSync(p2);
60811
61041
  } catch {
60812
61042
  return [];
60813
61043
  }
60814
61044
  }
60815
61045
  function rmdirIfEmpty(p2) {
60816
61046
  try {
60817
- fs51.rmdirSync(p2);
61047
+ fs52.rmdirSync(p2);
60818
61048
  } catch {
60819
61049
  }
60820
61050
  }
60821
61051
 
60822
61052
  // src/migrations/2026-08-18-drop-seeded-projects.ts
60823
- var fs52 = __toESM(require("fs"), 1);
60824
- var path55 = __toESM(require("path"), 1);
61053
+ var fs53 = __toESM(require("fs"), 1);
61054
+ var path56 = __toESM(require("path"), 1);
60825
61055
  var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
60826
61056
  function dropSeededProjects(opts) {
60827
- fs52.mkdirSync(opts.dataDir, { recursive: true });
60828
- const flag = path55.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
60829
- if (fs52.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
60830
- 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");
60831
61061
  let raw = null;
60832
61062
  let dropped = 0;
60833
61063
  try {
60834
- raw = fs52.readFileSync(file, "utf8");
61064
+ raw = fs53.readFileSync(file, "utf8");
60835
61065
  dropped = JSON.parse(raw).projects?.length ?? 0;
60836
61066
  } catch {
60837
61067
  }
60838
61068
  let backup = null;
60839
61069
  if (raw != null && dropped > 0) {
60840
- const dir = path55.join(opts.dataDir, "backups");
60841
- fs52.mkdirSync(dir, { recursive: true });
60842
- backup = path55.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
60843
- 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);
60844
61074
  }
60845
61075
  if (raw != null || dropped > 0) {
60846
- fs52.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
61076
+ fs53.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
60847
61077
  }
60848
- fs52.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
61078
+ fs53.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
60849
61079
  return { skipped: false, dropped, backup };
60850
61080
  }
60851
61081
 
60852
61082
  // src/transport/http-router.ts
60853
- var import_node_fs39 = __toESM(require("fs"), 1);
61083
+ var import_node_fs40 = __toESM(require("fs"), 1);
60854
61084
  var import_node_path47 = __toESM(require("path"), 1);
60855
61085
 
60856
- // src/attachment/mime.ts
60857
- var import_node_path44 = __toESM(require("path"), 1);
60858
- var TEXT_PLAIN = "text/plain; charset=utf-8";
60859
- var EXT_TO_NATIVE_MIME = {
60860
- // 图片
60861
- ".png": "image/png",
60862
- ".jpg": "image/jpeg",
60863
- ".jpeg": "image/jpeg",
60864
- ".gif": "image/gif",
60865
- ".webp": "image/webp",
60866
- ".svg": "image/svg+xml",
60867
- ".bmp": "image/bmp",
60868
- ".ico": "image/x-icon",
60869
- ".avif": "image/avif",
60870
- // 文档 / 富文本
60871
- ".pdf": "application/pdf",
60872
- ".html": "text/html; charset=utf-8",
60873
- ".htm": "text/html; charset=utf-8",
60874
- // 视频 / 音频
60875
- ".mp4": "video/mp4",
60876
- ".webm": "video/webm",
60877
- ".mov": "video/quicktime",
60878
- ".mp3": "audio/mpeg",
60879
- ".wav": "audio/wav",
60880
- ".ogg": "audio/ogg",
60881
- ".flac": "audio/flac",
60882
- // 真二进制(让浏览器下载而不是错把它当文本明文)
60883
- ".zip": "application/zip",
60884
- ".gz": "application/gzip",
60885
- ".tar": "application/x-tar",
60886
- ".7z": "application/x-7z-compressed",
60887
- ".rar": "application/x-rar-compressed"
60888
- };
60889
- var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
60890
- // 文档
60891
- ".md",
60892
- ".markdown",
60893
- ".rst",
60894
- ".adoc",
60895
- ".txt",
60896
- ".log",
60897
- // 通用结构化
60898
- ".json",
60899
- ".jsonc",
60900
- ".json5",
60901
- ".yaml",
60902
- ".yml",
60903
- ".toml",
60904
- ".xml",
60905
- ".csv",
60906
- ".tsv",
60907
- ".ini",
60908
- ".conf",
60909
- ".cfg",
60910
- ".env",
60911
- // 前端
60912
- ".js",
60913
- ".jsx",
60914
- ".mjs",
60915
- ".cjs",
60916
- ".ts",
60917
- ".tsx",
60918
- ".css",
60919
- ".scss",
60920
- ".sass",
60921
- ".less",
60922
- ".vue",
60923
- ".svelte",
60924
- ".graphql",
60925
- ".gql",
60926
- // 后端 / 各语言
60927
- ".py",
60928
- ".rb",
60929
- ".go",
60930
- ".rs",
60931
- ".java",
60932
- ".kt",
60933
- ".kts",
60934
- ".scala",
60935
- ".c",
60936
- ".h",
60937
- ".cpp",
60938
- ".hpp",
60939
- ".cc",
60940
- ".hh",
60941
- ".cs",
60942
- ".php",
60943
- ".swift",
60944
- ".m",
60945
- ".mm",
60946
- ".dart",
60947
- ".lua",
60948
- ".pl",
60949
- ".r",
60950
- ".sh",
60951
- ".bash",
60952
- ".zsh",
60953
- ".fish",
60954
- // 其他
60955
- ".sql",
60956
- ".proto",
60957
- ".dockerfile",
60958
- ".diff",
60959
- ".patch",
60960
- ".makefile",
60961
- ".mk"
60962
- ]);
60963
- function lookupMime(filePathOrName) {
60964
- const ext = import_node_path44.default.extname(filePathOrName).toLowerCase();
60965
- if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
60966
- if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
60967
- return "application/octet-stream";
60968
- }
60969
-
60970
- // src/attachment/sign-url.ts
60971
- var import_node_crypto9 = __toESM(require("crypto"), 1);
60972
- var HMAC_ALGO = "sha256";
60973
- function base64urlEncode(buf) {
60974
- const b2 = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
60975
- return b2.toString("base64url");
60976
- }
60977
- function base64urlDecodeBuf(s) {
60978
- return Buffer.from(s, "base64url");
60979
- }
60980
- function encodeAbsPathForUrl(absPath) {
60981
- return absPath.split("/").map(encodeURIComponent).join("/");
60982
- }
60983
- function decodeAbsPathFromUrl(encoded) {
60984
- return encoded.split("/").map(decodeURIComponent).join("/");
60985
- }
60986
- var DOMAIN_PREFIX2 = "clawd-attach-v1|";
60987
- function computeSig(secret, absPath, e) {
60988
- const msg = e === null ? `${DOMAIN_PREFIX2}${absPath}` : `${DOMAIN_PREFIX2}${absPath}|${e}`;
60989
- return import_node_crypto9.default.createHmac(HMAC_ALGO, secret).update(msg).digest();
60990
- }
60991
- function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
60992
- const e = ttlSeconds === null ? null : Math.floor(now() / 1e3) + ttlSeconds;
60993
- const s = base64urlEncode(computeSig(secret, absPath, e));
60994
- return { absPath, e, s };
60995
- }
60996
- function buildSignedFileUrl(httpBaseUrl, parts, prefix = "/files") {
60997
- const encodedPath = encodeAbsPathForUrl(parts.absPath);
60998
- const query = parts.e === null ? `s=${encodeURIComponent(parts.s)}` : `e=${parts.e}&s=${encodeURIComponent(parts.s)}`;
60999
- const base = httpBaseUrl.endsWith("/") ? httpBaseUrl.slice(0, -1) : httpBaseUrl;
61000
- return `${base}${prefix}${encodedPath}?${query}`;
61001
- }
61002
- function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
61003
- let e;
61004
- if (eRaw === null || eRaw === void 0 || eRaw === "") {
61005
- e = null;
61006
- } else {
61007
- const parsed = Number.parseInt(eRaw, 10);
61008
- if (!Number.isFinite(parsed) || parsed < 0) {
61009
- return { ok: false, code: "MALFORMED" };
61010
- }
61011
- e = parsed;
61012
- }
61013
- if (!absPath || !s) return { ok: false, code: "MALFORMED" };
61014
- const expected = computeSig(secret, absPath, e);
61015
- let provided;
61016
- try {
61017
- provided = base64urlDecodeBuf(s);
61018
- } catch {
61019
- return { ok: false, code: "MALFORMED" };
61020
- }
61021
- if (provided.length !== expected.length) {
61022
- return { ok: false, code: "BAD_SIG" };
61023
- }
61024
- if (!import_node_crypto9.default.timingSafeEqual(provided, expected)) {
61025
- return { ok: false, code: "BAD_SIG" };
61026
- }
61027
- if (e !== null && now() / 1e3 > e) {
61028
- return { ok: false, code: "EXPIRED" };
61029
- }
61030
- return { ok: true, absPath };
61031
- }
61032
-
61033
61086
  // src/attachment/upload.ts
61034
- var import_node_fs38 = __toESM(require("fs"), 1);
61087
+ var import_node_fs39 = __toESM(require("fs"), 1);
61035
61088
  var import_node_path45 = __toESM(require("path"), 1);
61036
61089
  var import_node_crypto10 = __toESM(require("crypto"), 1);
61037
61090
  var import_promises7 = require("stream/promises");
@@ -61053,7 +61106,7 @@ async function writeUploadedAttachment(args) {
61053
61106
  assertValidFileName(args.fileName);
61054
61107
  const attachmentsRoot = import_node_path45.default.join(args.baseDir, ".attachments");
61055
61108
  try {
61056
- import_node_fs38.default.mkdirSync(attachmentsRoot, { recursive: true });
61109
+ import_node_fs39.default.mkdirSync(attachmentsRoot, { recursive: true });
61057
61110
  } catch (err) {
61058
61111
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
61059
61112
  }
@@ -61074,18 +61127,18 @@ async function writeUploadedAttachment(args) {
61074
61127
  yield buf;
61075
61128
  }
61076
61129
  },
61077
- import_node_fs38.default.createWriteStream(tmpPath, { mode: 384 })
61130
+ import_node_fs39.default.createWriteStream(tmpPath, { mode: 384 })
61078
61131
  );
61079
61132
  } catch (err) {
61080
61133
  try {
61081
- import_node_fs38.default.unlinkSync(tmpPath);
61134
+ import_node_fs39.default.unlinkSync(tmpPath);
61082
61135
  } catch {
61083
61136
  }
61084
61137
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
61085
61138
  }
61086
61139
  if (actualSize !== args.contentLength) {
61087
61140
  try {
61088
- import_node_fs38.default.unlinkSync(tmpPath);
61141
+ import_node_fs39.default.unlinkSync(tmpPath);
61089
61142
  } catch {
61090
61143
  }
61091
61144
  throw new UploadError(
@@ -61098,24 +61151,24 @@ async function writeUploadedAttachment(args) {
61098
61151
  let finalFileName;
61099
61152
  let hashDirExists = false;
61100
61153
  try {
61101
- hashDirExists = import_node_fs38.default.statSync(hashDir).isDirectory();
61154
+ hashDirExists = import_node_fs39.default.statSync(hashDir).isDirectory();
61102
61155
  } catch {
61103
61156
  }
61104
61157
  if (hashDirExists) {
61105
- 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("."));
61106
61159
  finalFileName = existing[0] ?? args.fileName;
61107
61160
  try {
61108
- import_node_fs38.default.unlinkSync(tmpPath);
61161
+ import_node_fs39.default.unlinkSync(tmpPath);
61109
61162
  } catch {
61110
61163
  }
61111
61164
  } else {
61112
61165
  try {
61113
- import_node_fs38.default.mkdirSync(hashDir, { recursive: true });
61166
+ import_node_fs39.default.mkdirSync(hashDir, { recursive: true });
61114
61167
  finalFileName = args.fileName;
61115
- 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));
61116
61169
  } catch (err) {
61117
61170
  try {
61118
- import_node_fs38.default.unlinkSync(tmpPath);
61171
+ import_node_fs39.default.unlinkSync(tmpPath);
61119
61172
  } catch {
61120
61173
  }
61121
61174
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
@@ -61422,7 +61475,7 @@ function createHttpRouter(deps) {
61422
61475
  }
61423
61476
  let buf;
61424
61477
  try {
61425
- buf = await import_node_fs39.default.promises.readFile(abs);
61478
+ buf = await import_node_fs40.default.promises.readFile(abs);
61426
61479
  } catch {
61427
61480
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
61428
61481
  return true;
@@ -61786,7 +61839,7 @@ function withCtx(ctx, body) {
61786
61839
  function streamFile(res, absPath, logger) {
61787
61840
  let stat;
61788
61841
  try {
61789
- stat = import_node_fs39.default.statSync(absPath);
61842
+ stat = import_node_fs40.default.statSync(absPath);
61790
61843
  } catch (err) {
61791
61844
  const code = err?.code;
61792
61845
  if (code === "ENOENT") {
@@ -61809,7 +61862,7 @@ function streamFile(res, absPath, logger) {
61809
61862
  // 防止浏览器把任意 mime 当 html 渲染
61810
61863
  "X-Content-Type-Options": "nosniff"
61811
61864
  });
61812
- const stream = import_node_fs39.default.createReadStream(absPath);
61865
+ const stream = import_node_fs40.default.createReadStream(absPath);
61813
61866
  stream.on("error", (err) => {
61814
61867
  logger?.warn("streamFile read error", { absPath, err: err.message });
61815
61868
  res.destroy();
@@ -61818,7 +61871,7 @@ function streamFile(res, absPath, logger) {
61818
61871
  }
61819
61872
 
61820
61873
  // src/attachment/gc.ts
61821
- var import_node_fs40 = __toESM(require("fs"), 1);
61874
+ var import_node_fs41 = __toESM(require("fs"), 1);
61822
61875
  var import_node_path48 = __toESM(require("path"), 1);
61823
61876
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
61824
61877
  function runAttachmentGc(args) {
@@ -61849,7 +61902,7 @@ function runAttachmentGc(args) {
61849
61902
  const attRoot = import_node_path48.default.join(rootDir, ".attachments");
61850
61903
  let hashDirs;
61851
61904
  try {
61852
- hashDirs = import_node_fs40.default.readdirSync(attRoot);
61905
+ hashDirs = import_node_fs41.default.readdirSync(attRoot);
61853
61906
  } catch (err) {
61854
61907
  if (err.code === "ENOENT") continue;
61855
61908
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
@@ -61859,7 +61912,7 @@ function runAttachmentGc(args) {
61859
61912
  const hashDirAbs = import_node_path48.default.join(attRoot, hashDir);
61860
61913
  let files;
61861
61914
  try {
61862
- files = import_node_fs40.default.readdirSync(hashDirAbs);
61915
+ files = import_node_fs41.default.readdirSync(hashDirAbs);
61863
61916
  } catch {
61864
61917
  continue;
61865
61918
  }
@@ -61867,7 +61920,7 @@ function runAttachmentGc(args) {
61867
61920
  const file = import_node_path48.default.join(hashDirAbs, name);
61868
61921
  let stat;
61869
61922
  try {
61870
- stat = import_node_fs40.default.statSync(file);
61923
+ stat = import_node_fs41.default.statSync(file);
61871
61924
  } catch {
61872
61925
  continue;
61873
61926
  }
@@ -61876,18 +61929,18 @@ function runAttachmentGc(args) {
61876
61929
  if (age < ttlMs) continue;
61877
61930
  if (liveAbs.has(file)) continue;
61878
61931
  try {
61879
- import_node_fs40.default.unlinkSync(file);
61932
+ import_node_fs41.default.unlinkSync(file);
61880
61933
  } catch (err) {
61881
61934
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
61882
61935
  }
61883
61936
  }
61884
61937
  try {
61885
- 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);
61886
61939
  } catch {
61887
61940
  }
61888
61941
  }
61889
61942
  try {
61890
- 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);
61891
61944
  } catch {
61892
61945
  }
61893
61946
  }
@@ -61895,7 +61948,7 @@ function runAttachmentGc(args) {
61895
61948
  }
61896
61949
 
61897
61950
  // src/attachment/group.ts
61898
- var import_node_fs41 = __toESM(require("fs"), 1);
61951
+ var import_node_fs42 = __toESM(require("fs"), 1);
61899
61952
  var import_node_path49 = __toESM(require("path"), 1);
61900
61953
  var import_node_crypto11 = __toESM(require("crypto"), 1);
61901
61954
  init_protocol();
@@ -61921,7 +61974,7 @@ var GroupFileStore = class {
61921
61974
  readFile(scope, sessionId) {
61922
61975
  const file = this.filePath(scope, sessionId);
61923
61976
  try {
61924
- const raw = import_node_fs41.default.readFileSync(file, "utf8");
61977
+ const raw = import_node_fs42.default.readFileSync(file, "utf8");
61925
61978
  const parsed = JSON.parse(raw);
61926
61979
  if (!Array.isArray(parsed)) {
61927
61980
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -61947,10 +62000,10 @@ var GroupFileStore = class {
61947
62000
  }
61948
62001
  writeFile(scope, sessionId, entries) {
61949
62002
  const file = this.filePath(scope, sessionId);
61950
- 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 });
61951
62004
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
61952
- import_node_fs41.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
61953
- 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);
61954
62007
  }
61955
62008
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
61956
62009
  list(scope, sessionId) {
@@ -62036,7 +62089,7 @@ var GroupFileStore = class {
62036
62089
  };
62037
62090
 
62038
62091
  // src/discovery/state-file.ts
62039
- var import_node_fs42 = __toESM(require("fs"), 1);
62092
+ var import_node_fs43 = __toESM(require("fs"), 1);
62040
62093
  var import_node_path50 = __toESM(require("path"), 1);
62041
62094
  function defaultStateFilePath(dataDir) {
62042
62095
  return import_node_path50.default.join(dataDir, "state.json");
@@ -62061,7 +62114,7 @@ var StateFileManager = class {
62061
62114
  }
62062
62115
  read() {
62063
62116
  try {
62064
- const raw = import_node_fs42.default.readFileSync(this.file, "utf8");
62117
+ const raw = import_node_fs43.default.readFileSync(this.file, "utf8");
62065
62118
  const parsed = JSON.parse(raw);
62066
62119
  return parsed;
62067
62120
  } catch {
@@ -62075,20 +62128,20 @@ var StateFileManager = class {
62075
62128
  return { status: "stale", existing };
62076
62129
  }
62077
62130
  write(state) {
62078
- 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 });
62079
62132
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
62080
- import_node_fs42.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
62081
- 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);
62082
62135
  if (process.platform !== "win32") {
62083
62136
  try {
62084
- import_node_fs42.default.chmodSync(this.file, 384);
62137
+ import_node_fs43.default.chmodSync(this.file, 384);
62085
62138
  } catch {
62086
62139
  }
62087
62140
  }
62088
62141
  }
62089
62142
  delete() {
62090
62143
  try {
62091
- import_node_fs42.default.unlinkSync(this.file);
62144
+ import_node_fs43.default.unlinkSync(this.file);
62092
62145
  } catch {
62093
62146
  }
62094
62147
  }
@@ -62102,13 +62155,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
62102
62155
  }
62103
62156
 
62104
62157
  // src/tunnel/tunnel-manager.ts
62105
- var import_node_fs46 = __toESM(require("fs"), 1);
62158
+ var import_node_fs47 = __toESM(require("fs"), 1);
62106
62159
  var import_node_path54 = __toESM(require("path"), 1);
62107
62160
  var import_node_crypto12 = __toESM(require("crypto"), 1);
62108
62161
  var import_node_child_process12 = require("child_process");
62109
62162
 
62110
62163
  // src/tunnel/tunnel-store.ts
62111
- var import_node_fs43 = __toESM(require("fs"), 1);
62164
+ var import_node_fs44 = __toESM(require("fs"), 1);
62112
62165
  var import_node_path51 = __toESM(require("path"), 1);
62113
62166
  var TunnelStore = class {
62114
62167
  constructor(filePath) {
@@ -62117,7 +62170,7 @@ var TunnelStore = class {
62117
62170
  filePath;
62118
62171
  async get() {
62119
62172
  try {
62120
- 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");
62121
62174
  const obj = JSON.parse(raw);
62122
62175
  if (!isPersistedTunnel(obj)) return null;
62123
62176
  return obj;
@@ -62129,21 +62182,21 @@ var TunnelStore = class {
62129
62182
  }
62130
62183
  async set(v2) {
62131
62184
  const dir = import_node_path51.default.dirname(this.filePath);
62132
- await import_node_fs43.default.promises.mkdir(dir, { recursive: true });
62185
+ await import_node_fs44.default.promises.mkdir(dir, { recursive: true });
62133
62186
  const data = JSON.stringify(v2, null, 2);
62134
62187
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
62135
- await import_node_fs43.default.promises.writeFile(tmp, data, { mode: 384 });
62188
+ await import_node_fs44.default.promises.writeFile(tmp, data, { mode: 384 });
62136
62189
  if (process.platform !== "win32") {
62137
62190
  try {
62138
- await import_node_fs43.default.promises.chmod(tmp, 384);
62191
+ await import_node_fs44.default.promises.chmod(tmp, 384);
62139
62192
  } catch {
62140
62193
  }
62141
62194
  }
62142
- await import_node_fs43.default.promises.rename(tmp, this.filePath);
62195
+ await import_node_fs44.default.promises.rename(tmp, this.filePath);
62143
62196
  }
62144
62197
  async clear() {
62145
62198
  try {
62146
- await import_node_fs43.default.promises.unlink(this.filePath);
62199
+ await import_node_fs44.default.promises.unlink(this.filePath);
62147
62200
  } catch (err) {
62148
62201
  const code = err?.code;
62149
62202
  if (code !== "ENOENT") throw err;
@@ -62238,7 +62291,7 @@ function escape(v2) {
62238
62291
  }
62239
62292
 
62240
62293
  // src/tunnel/frpc-binary.ts
62241
- var import_node_fs44 = __toESM(require("fs"), 1);
62294
+ var import_node_fs45 = __toESM(require("fs"), 1);
62242
62295
  var import_node_os16 = __toESM(require("os"), 1);
62243
62296
  var import_node_path52 = __toESM(require("path"), 1);
62244
62297
  var import_node_child_process10 = require("child_process");
@@ -62272,7 +62325,7 @@ function frpcDownloadUrl(version2, p2) {
62272
62325
  }
62273
62326
  async function ensureFrpcBinary(opts) {
62274
62327
  if (opts.override) {
62275
- if (!import_node_fs44.default.existsSync(opts.override)) {
62328
+ if (!import_node_fs45.default.existsSync(opts.override)) {
62276
62329
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
62277
62330
  }
62278
62331
  return opts.override;
@@ -62280,10 +62333,10 @@ async function ensureFrpcBinary(opts) {
62280
62333
  const version2 = opts.version ?? FRPC_VERSION;
62281
62334
  const platform = opts.platform ?? detectPlatform();
62282
62335
  const binDir = import_node_path52.default.join(opts.dataDir, "bin");
62283
- import_node_fs44.default.mkdirSync(binDir, { recursive: true });
62336
+ import_node_fs45.default.mkdirSync(binDir, { recursive: true });
62284
62337
  cleanupStaleArtifacts(binDir);
62285
62338
  const stableBin = import_node_path52.default.join(binDir, "frpc");
62286
- if (import_node_fs44.default.existsSync(stableBin)) return stableBin;
62339
+ if (import_node_fs45.default.existsSync(stableBin)) return stableBin;
62287
62340
  const partialBin = `${stableBin}.partial`;
62288
62341
  const tarballPath = import_node_path52.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
62289
62342
  try {
@@ -62294,8 +62347,8 @@ async function ensureFrpcBinary(opts) {
62294
62347
  } else {
62295
62348
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
62296
62349
  }
62297
- import_node_fs44.default.chmodSync(partialBin, 493);
62298
- import_node_fs44.default.renameSync(partialBin, stableBin);
62350
+ import_node_fs45.default.chmodSync(partialBin, 493);
62351
+ import_node_fs45.default.renameSync(partialBin, stableBin);
62299
62352
  } finally {
62300
62353
  safeUnlink(tarballPath);
62301
62354
  safeUnlink(partialBin);
@@ -62305,7 +62358,7 @@ async function ensureFrpcBinary(opts) {
62305
62358
  function cleanupStaleArtifacts(binDir) {
62306
62359
  let entries;
62307
62360
  try {
62308
- entries = import_node_fs44.default.readdirSync(binDir);
62361
+ entries = import_node_fs45.default.readdirSync(binDir);
62309
62362
  } catch {
62310
62363
  return;
62311
62364
  }
@@ -62313,7 +62366,7 @@ function cleanupStaleArtifacts(binDir) {
62313
62366
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
62314
62367
  const full = import_node_path52.default.join(binDir, name);
62315
62368
  try {
62316
- import_node_fs44.default.rmSync(full, { recursive: true, force: true });
62369
+ import_node_fs45.default.rmSync(full, { recursive: true, force: true });
62317
62370
  } catch {
62318
62371
  }
62319
62372
  }
@@ -62321,7 +62374,7 @@ function cleanupStaleArtifacts(binDir) {
62321
62374
  }
62322
62375
  function safeUnlink(p2) {
62323
62376
  try {
62324
- import_node_fs44.default.unlinkSync(p2);
62377
+ import_node_fs45.default.unlinkSync(p2);
62325
62378
  } catch {
62326
62379
  }
62327
62380
  }
@@ -62332,13 +62385,13 @@ async function downloadToFile(url, dest, fetchImpl) {
62332
62385
  if (!res.ok || !res.body) {
62333
62386
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
62334
62387
  }
62335
- const out = import_node_fs44.default.createWriteStream(dest);
62388
+ const out = import_node_fs45.default.createWriteStream(dest);
62336
62389
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
62337
62390
  await (0, import_promises9.pipeline)(nodeStream, out);
62338
62391
  }
62339
62392
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
62340
62393
  const work = import_node_path52.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
62341
- import_node_fs44.default.mkdirSync(work, { recursive: true });
62394
+ import_node_fs45.default.mkdirSync(work, { recursive: true });
62342
62395
  try {
62343
62396
  await new Promise((resolve9, reject) => {
62344
62397
  const proc = (0, import_node_child_process10.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -62347,17 +62400,17 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
62347
62400
  });
62348
62401
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
62349
62402
  const src = import_node_path52.default.join(work, dirName, "frpc");
62350
- if (!import_node_fs44.default.existsSync(src)) {
62403
+ if (!import_node_fs45.default.existsSync(src)) {
62351
62404
  throw new Error(`frpc not found inside tarball at ${src}`);
62352
62405
  }
62353
- import_node_fs44.default.copyFileSync(src, destBin);
62406
+ import_node_fs45.default.copyFileSync(src, destBin);
62354
62407
  } finally {
62355
- import_node_fs44.default.rmSync(work, { recursive: true, force: true });
62408
+ import_node_fs45.default.rmSync(work, { recursive: true, force: true });
62356
62409
  }
62357
62410
  }
62358
62411
 
62359
62412
  // src/tunnel/frpc-process.ts
62360
- var import_node_fs45 = __toESM(require("fs"), 1);
62413
+ var import_node_fs46 = __toESM(require("fs"), 1);
62361
62414
  var import_node_path53 = __toESM(require("path"), 1);
62362
62415
  var import_node_child_process11 = require("child_process");
62363
62416
  function frpcPidFilePath(dataDir) {
@@ -62365,13 +62418,13 @@ function frpcPidFilePath(dataDir) {
62365
62418
  }
62366
62419
  function writeFrpcPid(dataDir, pid) {
62367
62420
  try {
62368
- import_node_fs45.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
62421
+ import_node_fs46.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
62369
62422
  } catch {
62370
62423
  }
62371
62424
  }
62372
62425
  function clearFrpcPid(dataDir) {
62373
62426
  try {
62374
- import_node_fs45.default.unlinkSync(frpcPidFilePath(dataDir));
62427
+ import_node_fs46.default.unlinkSync(frpcPidFilePath(dataDir));
62375
62428
  } catch {
62376
62429
  }
62377
62430
  }
@@ -62387,7 +62440,7 @@ function defaultIsPidAlive(pid) {
62387
62440
  }
62388
62441
  function defaultReadPidFile(file) {
62389
62442
  try {
62390
- return import_node_fs45.default.readFileSync(file, "utf8");
62443
+ return import_node_fs46.default.readFileSync(file, "utf8");
62391
62444
  } catch {
62392
62445
  return null;
62393
62446
  }
@@ -62427,7 +62480,7 @@ async function killStaleFrpc(deps) {
62427
62480
  }
62428
62481
  if (victims.size === 0) {
62429
62482
  try {
62430
- import_node_fs45.default.unlinkSync(pidFile);
62483
+ import_node_fs46.default.unlinkSync(pidFile);
62431
62484
  } catch {
62432
62485
  }
62433
62486
  return;
@@ -62438,7 +62491,7 @@ async function killStaleFrpc(deps) {
62438
62491
  }
62439
62492
  await sleep2(deps.reapWaitMs ?? 300);
62440
62493
  try {
62441
- import_node_fs45.default.unlinkSync(pidFile);
62494
+ import_node_fs46.default.unlinkSync(pidFile);
62442
62495
  } catch {
62443
62496
  }
62444
62497
  }
@@ -62613,14 +62666,14 @@ var TunnelManager = class {
62613
62666
  localPort,
62614
62667
  logLevel: "info"
62615
62668
  });
62616
- await import_node_fs46.default.promises.writeFile(tomlPath, toml, { mode: 384 });
62669
+ await import_node_fs47.default.promises.writeFile(tomlPath, toml, { mode: 384 });
62617
62670
  const proc = (this.deps.spawnImpl ?? import_node_child_process12.spawn)(frpcBin, ["-c", tomlPath], {
62618
62671
  stdio: ["ignore", "pipe", "pipe"]
62619
62672
  });
62620
62673
  const logDir = import_node_path54.default.join(this.deps.dataDir, "log");
62621
- import_node_fs46.default.mkdirSync(logDir, { recursive: true });
62674
+ import_node_fs47.default.mkdirSync(logDir, { recursive: true });
62622
62675
  const logFilePath = import_node_path54.default.join(logDir, "frpc.log");
62623
- 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 });
62624
62677
  logStream.on("error", () => {
62625
62678
  });
62626
62679
  const tee = (chunk) => {
@@ -62718,7 +62771,7 @@ function deriveStableDeviceKey(opts = {}) {
62718
62771
  }
62719
62772
 
62720
62773
  // src/auth-store.ts
62721
- var import_node_fs47 = __toESM(require("fs"), 1);
62774
+ var import_node_fs48 = __toESM(require("fs"), 1);
62722
62775
  var import_node_path56 = __toESM(require("path"), 1);
62723
62776
  var import_node_crypto14 = __toESM(require("crypto"), 1);
62724
62777
  var AUTH_FILE_NAME = "auth.json";
@@ -62755,7 +62808,7 @@ function defaultGenerateOwnerPrincipalId() {
62755
62808
  }
62756
62809
  function readAuthFile(file) {
62757
62810
  try {
62758
- const raw = import_node_fs47.default.readFileSync(file, "utf8");
62811
+ const raw = import_node_fs48.default.readFileSync(file, "utf8");
62759
62812
  const parsed = JSON.parse(raw);
62760
62813
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
62761
62814
  return null;
@@ -62775,16 +62828,16 @@ function readAuthFile(file) {
62775
62828
  }
62776
62829
  }
62777
62830
  function writeAuthFile(file, content) {
62778
- import_node_fs47.default.mkdirSync(import_node_path56.default.dirname(file), { recursive: true });
62779
- 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 });
62780
62833
  try {
62781
- import_node_fs47.default.chmodSync(file, 384);
62834
+ import_node_fs48.default.chmodSync(file, 384);
62782
62835
  } catch {
62783
62836
  }
62784
62837
  }
62785
62838
 
62786
62839
  // src/owner-profile.ts
62787
- var import_node_fs48 = __toESM(require("fs"), 1);
62840
+ var import_node_fs49 = __toESM(require("fs"), 1);
62788
62841
  var import_node_os18 = __toESM(require("os"), 1);
62789
62842
  var import_node_path57 = __toESM(require("path"), 1);
62790
62843
  var PROFILE_FILENAME = "profile.json";
@@ -62794,7 +62847,7 @@ function profilePath(dataDir) {
62794
62847
  function loadOwnerProfile(dataDir) {
62795
62848
  let raw;
62796
62849
  try {
62797
- raw = import_node_fs48.default.readFileSync(profilePath(dataDir), "utf8");
62850
+ raw = import_node_fs49.default.readFileSync(profilePath(dataDir), "utf8");
62798
62851
  } catch {
62799
62852
  return {};
62800
62853
  }
@@ -62810,7 +62863,7 @@ function loadOwnerProfile(dataDir) {
62810
62863
  }
62811
62864
  function patchOwnerProfile(dataDir, patch) {
62812
62865
  const merged = { ...loadOwnerProfile(dataDir), ...patch };
62813
- 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 });
62814
62867
  return merged;
62815
62868
  }
62816
62869
  function loadOwnerDisplayName(dataDir) {
@@ -62826,7 +62879,7 @@ function loadOwnerDisplayName(dataDir) {
62826
62879
  }
62827
62880
 
62828
62881
  // src/feishu-auth/owner-identity-store.ts
62829
- var import_node_fs49 = __toESM(require("fs"), 1);
62882
+ var import_node_fs50 = __toESM(require("fs"), 1);
62830
62883
  var import_node_path58 = __toESM(require("path"), 1);
62831
62884
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
62832
62885
  var OwnerIdentityStore = class {
@@ -62837,7 +62890,7 @@ var OwnerIdentityStore = class {
62837
62890
  read() {
62838
62891
  let raw;
62839
62892
  try {
62840
- raw = import_node_fs49.default.readFileSync(this.file, "utf8");
62893
+ raw = import_node_fs50.default.readFileSync(this.file, "utf8");
62841
62894
  } catch {
62842
62895
  return null;
62843
62896
  }
@@ -62865,16 +62918,16 @@ var OwnerIdentityStore = class {
62865
62918
  };
62866
62919
  }
62867
62920
  write(record3) {
62868
- import_node_fs49.default.mkdirSync(import_node_path58.default.dirname(this.file), { recursive: true });
62869
- 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 });
62870
62923
  try {
62871
- import_node_fs49.default.chmodSync(this.file, 384);
62924
+ import_node_fs50.default.chmodSync(this.file, 384);
62872
62925
  } catch {
62873
62926
  }
62874
62927
  }
62875
62928
  clear() {
62876
62929
  try {
62877
- import_node_fs49.default.unlinkSync(this.file);
62930
+ import_node_fs50.default.unlinkSync(this.file);
62878
62931
  } catch (err) {
62879
62932
  const code = err?.code;
62880
62933
  if (code !== "ENOENT") throw err;
@@ -63335,7 +63388,7 @@ function verifyConnectToken(args) {
63335
63388
  }
63336
63389
 
63337
63390
  // src/feishu-auth/server-key.ts
63338
- var fs66 = __toESM(require("fs"), 1);
63391
+ var fs67 = __toESM(require("fs"), 1);
63339
63392
  var path71 = __toESM(require("path"), 1);
63340
63393
  var FILE_NAME2 = "server-signing-key.json";
63341
63394
  var ServerKeyStore = class {
@@ -63349,7 +63402,7 @@ var ServerKeyStore = class {
63349
63402
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
63350
63403
  read() {
63351
63404
  try {
63352
- const raw = fs66.readFileSync(this.filePath(), "utf8");
63405
+ const raw = fs67.readFileSync(this.filePath(), "utf8");
63353
63406
  const parsed = JSON.parse(raw);
63354
63407
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
63355
63408
  return parsed.publicKeyPem;
@@ -63364,12 +63417,12 @@ var ServerKeyStore = class {
63364
63417
  publicKeyPem,
63365
63418
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
63366
63419
  };
63367
- fs66.mkdirSync(this.dataDir, { recursive: true });
63368
- 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 });
63369
63422
  }
63370
63423
  clear() {
63371
63424
  try {
63372
- fs66.unlinkSync(this.filePath());
63425
+ fs67.unlinkSync(this.filePath());
63373
63426
  } catch {
63374
63427
  }
63375
63428
  }
@@ -63385,13 +63438,13 @@ var import_node_path72 = __toESM(require("path"), 1);
63385
63438
  init_protocol();
63386
63439
 
63387
63440
  // src/session/fork.ts
63388
- var import_node_fs50 = __toESM(require("fs"), 1);
63441
+ var import_node_fs51 = __toESM(require("fs"), 1);
63389
63442
  var import_node_os19 = __toESM(require("os"), 1);
63390
63443
  var import_node_path59 = __toESM(require("path"), 1);
63391
63444
  var import_node_crypto16 = require("crypto");
63392
63445
  init_claude_history();
63393
63446
  function readJsonlEntries(file) {
63394
- const raw = import_node_fs50.default.readFileSync(file, "utf8");
63447
+ const raw = import_node_fs51.default.readFileSync(file, "utf8");
63395
63448
  const out = [];
63396
63449
  for (const line of raw.split("\n")) {
63397
63450
  const t = line.trim();
@@ -63407,7 +63460,7 @@ function forkSession(input) {
63407
63460
  const baseDir = input.baseDir ?? import_node_path59.default.join(import_node_os19.default.homedir(), ".claude");
63408
63461
  let projectDir = import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
63409
63462
  let sourceFile = import_node_path59.default.join(projectDir, `${input.toolSessionId}.jsonl`);
63410
- if (!import_node_fs50.default.existsSync(sourceFile)) {
63463
+ if (!import_node_fs51.default.existsSync(sourceFile)) {
63411
63464
  const found = findTranscriptByToolSessionId(
63412
63465
  import_node_path59.default.join(baseDir, "projects"),
63413
63466
  input.toolSessionId
@@ -63447,13 +63500,13 @@ function forkSession(input) {
63447
63500
  }
63448
63501
  const outDir = input.targetCwd ? import_node_path59.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
63449
63502
  const forkedFilePath = import_node_path59.default.join(outDir, `${forkedToolSessionId}.jsonl`);
63450
- import_node_fs50.default.mkdirSync(outDir, { recursive: true });
63451
- 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 });
63452
63505
  return { forkedToolSessionId, forkedFilePath };
63453
63506
  }
63454
63507
 
63455
63508
  // src/session/external-scan.ts
63456
- var import_node_fs51 = __toESM(require("fs"), 1);
63509
+ var import_node_fs52 = __toESM(require("fs"), 1);
63457
63510
  var import_promises10 = __toESM(require("fs/promises"), 1);
63458
63511
  var import_node_os20 = __toESM(require("os"), 1);
63459
63512
  var import_node_path60 = __toESM(require("path"), 1);
@@ -63516,7 +63569,7 @@ function userText(msg) {
63516
63569
  }
63517
63570
  function isDir2(p2) {
63518
63571
  try {
63519
- return import_node_fs51.default.statSync(p2).isDirectory();
63572
+ return import_node_fs52.default.statSync(p2).isDirectory();
63520
63573
  } catch {
63521
63574
  return false;
63522
63575
  }
@@ -63525,7 +63578,7 @@ async function scanClaude(roots) {
63525
63578
  const out = [];
63526
63579
  let dirs;
63527
63580
  try {
63528
- dirs = import_node_fs51.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
63581
+ dirs = import_node_fs52.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
63529
63582
  } catch {
63530
63583
  return out;
63531
63584
  }
@@ -63533,7 +63586,7 @@ async function scanClaude(roots) {
63533
63586
  if (!d.isDirectory()) continue;
63534
63587
  let files;
63535
63588
  try {
63536
- 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));
63537
63590
  } catch {
63538
63591
  continue;
63539
63592
  }
@@ -63542,7 +63595,7 @@ async function scanClaude(roots) {
63542
63595
  const file = import_node_path60.default.join(roots.claudeProjectsDir, d.name, name);
63543
63596
  let st;
63544
63597
  try {
63545
- st = import_node_fs51.default.statSync(file);
63598
+ st = import_node_fs52.default.statSync(file);
63546
63599
  } catch {
63547
63600
  continue;
63548
63601
  }
@@ -63595,7 +63648,7 @@ async function scanClaude(roots) {
63595
63648
  return out;
63596
63649
  }
63597
63650
  async function countCodexTurns(rolloutPath) {
63598
- 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: "" };
63599
63652
  let turns = 0;
63600
63653
  let first = "";
63601
63654
  for await (const rec4 of jsonLines(rolloutPath)) {
@@ -63669,7 +63722,7 @@ async function codexFromRows(rows) {
63669
63722
  async function scanCodex(roots) {
63670
63723
  let dbs = [];
63671
63724
  try {
63672
- 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));
63673
63726
  } catch {
63674
63727
  }
63675
63728
  if (!dbs.length) return [];
@@ -63702,13 +63755,13 @@ async function scanExternalSessions(rootsIn) {
63702
63755
  }
63703
63756
 
63704
63757
  // src/session/import-ledger.ts
63705
- var import_node_fs52 = __toESM(require("fs"), 1);
63758
+ var import_node_fs53 = __toESM(require("fs"), 1);
63706
63759
  var import_node_path61 = __toESM(require("path"), 1);
63707
63760
  var LEDGER_FILENAME = "session-import-ledger.json";
63708
63761
  function readImportLedger(dataDir) {
63709
63762
  try {
63710
63763
  const parsed = JSON.parse(
63711
- 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")
63712
63765
  );
63713
63766
  return Array.isArray(parsed) ? parsed : [];
63714
63767
  } catch {
@@ -63719,7 +63772,7 @@ function appendImportLedger(dataDir, entry) {
63719
63772
  const file = import_node_path61.default.join(dataDir, LEDGER_FILENAME);
63720
63773
  const entries = readImportLedger(dataDir);
63721
63774
  entries.push(entry);
63722
- 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 });
63723
63776
  }
63724
63777
 
63725
63778
  // src/handlers/session.ts
@@ -64488,7 +64541,7 @@ function buildHistoryHandlers(deps) {
64488
64541
  }
64489
64542
 
64490
64543
  // src/handlers/projects.ts
64491
- var fs70 = __toESM(require("fs"), 1);
64544
+ var fs71 = __toESM(require("fs"), 1);
64492
64545
  var os22 = __toESM(require("os"), 1);
64493
64546
  var path77 = __toESM(require("path"), 1);
64494
64547
  var import_node_child_process14 = require("child_process");
@@ -64497,7 +64550,7 @@ var DEFAULT_PROJECTS_ROOT = path77.join(os22.homedir(), "Documents", "ChatGPT");
64497
64550
  function allocateDir(root, name) {
64498
64551
  let candidate = path77.join(root, name);
64499
64552
  let n = 2;
64500
- while (fs70.existsSync(candidate)) {
64553
+ while (fs71.existsSync(candidate)) {
64501
64554
  candidate = path77.join(root, `${name} ${n}`);
64502
64555
  n += 1;
64503
64556
  }
@@ -64526,7 +64579,7 @@ function buildProjectHandlers(deps) {
64526
64579
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
64527
64580
  }
64528
64581
  try {
64529
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
64582
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
64530
64583
  } catch {
64531
64584
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
64532
64585
  }
@@ -64542,7 +64595,7 @@ function buildProjectHandlers(deps) {
64542
64595
  let target;
64543
64596
  if (args.path) {
64544
64597
  try {
64545
- if (!fs70.statSync(args.path).isDirectory()) throw new Error("not dir");
64598
+ if (!fs71.statSync(args.path).isDirectory()) throw new Error("not dir");
64546
64599
  } catch {
64547
64600
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
64548
64601
  }
@@ -64550,15 +64603,15 @@ function buildProjectHandlers(deps) {
64550
64603
  } else {
64551
64604
  const name = args.name;
64552
64605
  try {
64553
- fs70.mkdirSync(root, { recursive: true });
64606
+ fs71.mkdirSync(root, { recursive: true });
64554
64607
  target = allocateDir(root, name);
64555
- fs70.mkdirSync(target);
64608
+ fs71.mkdirSync(target);
64556
64609
  } catch (err) {
64557
64610
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
64558
64611
  }
64559
64612
  const git2 = (0, import_node_child_process14.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
64560
64613
  if (git2.status !== 0) {
64561
- fs70.rmSync(target, { recursive: true, force: true });
64614
+ fs71.rmSync(target, { recursive: true, force: true });
64562
64615
  throw new ClawdError(
64563
64616
  ERROR_CODES.INVALID_CWD,
64564
64617
  `git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
@@ -64681,14 +64734,14 @@ init_protocol();
64681
64734
 
64682
64735
  // src/workspace/git.ts
64683
64736
  var import_node_child_process15 = require("child_process");
64684
- var import_node_fs53 = __toESM(require("fs"), 1);
64737
+ var import_node_fs54 = __toESM(require("fs"), 1);
64685
64738
  var import_node_path62 = __toESM(require("path"), 1);
64686
64739
  var import_node_util = require("util");
64687
64740
  var pexec = (0, import_node_util.promisify)(import_node_child_process15.execFile);
64688
64741
  function normalizePath(p2) {
64689
64742
  const resolved = import_node_path62.default.resolve(p2);
64690
64743
  try {
64691
- return import_node_fs53.default.realpathSync(resolved);
64744
+ return import_node_fs54.default.realpathSync(resolved);
64692
64745
  } catch {
64693
64746
  return resolved;
64694
64747
  }
@@ -65648,10 +65701,10 @@ function computeMethodAccess(args) {
65648
65701
  }
65649
65702
 
65650
65703
  // src/version.ts
65651
- var version = "0.2.499".length > 0 ? "0.2.499" : "dev";
65704
+ var version = "0.2.500".length > 0 ? "0.2.500" : "dev";
65652
65705
 
65653
65706
  // src/cli-probe/probe.ts
65654
- var fs72 = __toESM(require("fs"), 1);
65707
+ var fs73 = __toESM(require("fs"), 1);
65655
65708
  var path81 = __toESM(require("path"), 1);
65656
65709
  var PKG_NAME = "@clawos-dev/clawd";
65657
65710
  var BIN_NAME = "clawd";
@@ -65662,7 +65715,7 @@ function probeGlobalCli(pathEnv) {
65662
65715
  if (!dir) continue;
65663
65716
  let real;
65664
65717
  try {
65665
- real = fs72.realpathSync(path81.join(dir, BIN_NAME));
65718
+ real = fs73.realpathSync(path81.join(dir, BIN_NAME));
65666
65719
  } catch {
65667
65720
  continue;
65668
65721
  }
@@ -65675,7 +65728,7 @@ function readOwnPackageVersion(entryPath) {
65675
65728
  let dir = path81.dirname(entryPath);
65676
65729
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
65677
65730
  try {
65678
- const raw = fs72.readFileSync(path81.join(dir, "package.json"), "utf8");
65731
+ const raw = fs73.readFileSync(path81.join(dir, "package.json"), "utf8");
65679
65732
  const pkg = JSON.parse(raw);
65680
65733
  if (pkg.name !== PKG_NAME) return null;
65681
65734
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
@@ -66750,7 +66803,7 @@ var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
66750
66803
  // src/handlers/app-builder.ts
66751
66804
  init_protocol();
66752
66805
  var import_node_path69 = require("path");
66753
- var import_node_fs54 = require("fs");
66806
+ var import_node_fs55 = require("fs");
66754
66807
  var DEFAULT_TEMPLATE = "nestjs-react";
66755
66808
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
66756
66809
  function buildAppBuilderHandlers(deps) {
@@ -66823,7 +66876,7 @@ function buildAppBuilderHandlers(deps) {
66823
66876
  async function listAllUsersProjects() {
66824
66877
  if (!deps.usersRoot || !deps.getStore) return [];
66825
66878
  const getStore = deps.getStore;
66826
- const userIds = await import_node_fs54.promises.readdir(deps.usersRoot).catch(() => []);
66879
+ const userIds = await import_node_fs55.promises.readdir(deps.usersRoot).catch(() => []);
66827
66880
  const perUser = await Promise.all(
66828
66881
  userIds.map((uid) => getStore(uid).list().catch(() => []))
66829
66882
  );
@@ -68334,7 +68387,7 @@ function buildOnboardingHandlers(deps) {
68334
68387
  }
68335
68388
 
68336
68389
  // src/app-builder-plugin/project-store.ts
68337
- var import_node_fs55 = require("fs");
68390
+ var import_node_fs56 = require("fs");
68338
68391
  var import_node_child_process20 = require("child_process");
68339
68392
  var import_node_path73 = require("path");
68340
68393
  init_protocol();
@@ -68378,7 +68431,7 @@ var ProjectStore = class {
68378
68431
  async list() {
68379
68432
  let entries;
68380
68433
  try {
68381
- entries = await import_node_fs55.promises.readdir(this.projectsRoot());
68434
+ entries = await import_node_fs56.promises.readdir(this.projectsRoot());
68382
68435
  } catch (err) {
68383
68436
  if (err.code === "ENOENT") return [];
68384
68437
  throw err;
@@ -68386,7 +68439,7 @@ var ProjectStore = class {
68386
68439
  const out = [];
68387
68440
  for (const name of entries) {
68388
68441
  try {
68389
- 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");
68390
68443
  const json = JSON.parse(raw);
68391
68444
  let migrated = false;
68392
68445
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -68397,7 +68450,7 @@ var ProjectStore = class {
68397
68450
  if (parsed.success) {
68398
68451
  out.push(parsed.data);
68399
68452
  if (migrated) {
68400
- 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(() => {
68401
68454
  });
68402
68455
  }
68403
68456
  }
@@ -68441,8 +68494,8 @@ var ProjectStore = class {
68441
68494
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
68442
68495
  }
68443
68496
  const dir = this.projectDir(name);
68444
- await import_node_fs55.promises.mkdir(dir, { recursive: true });
68445
- 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");
68446
68499
  return meta;
68447
68500
  }
68448
68501
  /**
@@ -68487,7 +68540,7 @@ var ProjectStore = class {
68487
68540
  }
68488
68541
  async delete(name) {
68489
68542
  const dir = this.projectDir(name);
68490
- await import_node_fs55.promises.rm(dir, { recursive: true, force: true });
68543
+ await import_node_fs56.promises.rm(dir, { recursive: true, force: true });
68491
68544
  }
68492
68545
  async updatePort(name, newPort) {
68493
68546
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -68504,7 +68557,7 @@ var ProjectStore = class {
68504
68557
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
68505
68558
  }
68506
68559
  const updated = { ...target, port: newPort };
68507
- 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");
68508
68561
  return updated;
68509
68562
  });
68510
68563
  }
@@ -68523,7 +68576,7 @@ var ProjectStore = class {
68523
68576
  if (!validated.success) {
68524
68577
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
68525
68578
  }
68526
- 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");
68527
68580
  return validated.data;
68528
68581
  });
68529
68582
  }
@@ -68546,7 +68599,7 @@ var ProjectStore = class {
68546
68599
  if (!validated.success) {
68547
68600
  throw new Error(`invalid publishJob: ${validated.error.message}`);
68548
68601
  }
68549
- 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");
68550
68603
  return validated.data;
68551
68604
  });
68552
68605
  }
@@ -68563,7 +68616,7 @@ var ProjectStore = class {
68563
68616
  if (!validated.success) {
68564
68617
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
68565
68618
  }
68566
- 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");
68567
68620
  return validated.data;
68568
68621
  });
68569
68622
  }
@@ -68878,7 +68931,7 @@ var PublishJobRegistry = class {
68878
68931
 
68879
68932
  // src/app-builder-plugin/publish-job-runner.ts
68880
68933
  var import_node_child_process22 = require("child_process");
68881
- var import_node_fs56 = require("fs");
68934
+ var import_node_fs57 = require("fs");
68882
68935
  var import_node_path74 = require("path");
68883
68936
 
68884
68937
  // src/app-builder-plugin/publish-stage-parser.ts
@@ -68914,7 +68967,7 @@ async function startPublishJob(deps, args) {
68914
68967
  const logPath = (0, import_node_path74.join)(projDir, ".publish.log");
68915
68968
  let logStream = null;
68916
68969
  try {
68917
- logStream = (0, import_node_fs56.createWriteStream)(logPath, { flags: "w" });
68970
+ logStream = (0, import_node_fs57.createWriteStream)(logPath, { flags: "w" });
68918
68971
  } catch {
68919
68972
  logStream = null;
68920
68973
  }
@@ -69257,7 +69310,7 @@ async function recoverInterruptedPublishJobs(store, logger) {
69257
69310
  }
69258
69311
 
69259
69312
  // src/app-builder-plugin/mcp-config.ts
69260
- var import_node_fs57 = __toESM(require("fs"), 1);
69313
+ var import_node_fs58 = __toESM(require("fs"), 1);
69261
69314
  var import_node_path75 = __toESM(require("path"), 1);
69262
69315
  function appBuilderMcpConfigPath(dataDir) {
69263
69316
  return import_node_path75.default.join(dataDir, "app-builder.mcp.json");
@@ -69281,8 +69334,8 @@ function writeAppBuilderMcpConfig(args) {
69281
69334
  }
69282
69335
  }
69283
69336
  };
69284
- import_node_fs57.default.mkdirSync(args.dataDir, { recursive: true });
69285
- 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");
69286
69339
  return cfgPath;
69287
69340
  }
69288
69341
 
@@ -69699,7 +69752,7 @@ async function startDaemon(config) {
69699
69752
  homeDir: import_node_os27.default.homedir()
69700
69753
  });
69701
69754
  const logDir = import_node_path79.default.join(config.dataDir, "log");
69702
- import_node_fs58.default.mkdirSync(logDir, { recursive: true });
69755
+ import_node_fs59.default.mkdirSync(logDir, { recursive: true });
69703
69756
  const logger = createLogger({
69704
69757
  level: config.logLevel,
69705
69758
  file: import_node_path79.default.join(logDir, "clawd.log"),
@@ -69926,7 +69979,7 @@ async function startDaemon(config) {
69926
69979
  import_node_path79.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
69927
69980
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
69928
69981
  ];
69929
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
69982
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69930
69983
  if (dispatchServerScriptPath) {
69931
69984
  const dispatchLogPath = import_node_path79.default.join(logDir, "dispatch-mcp-server.log");
69932
69985
  const dispatchCfgPath = writeDispatchMcpConfig({
@@ -69951,7 +70004,7 @@ async function startDaemon(config) {
69951
70004
  import_node_path79.default.join(here, "ticket", "mcp-server.cjs"),
69952
70005
  import_node_path79.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
69953
70006
  ];
69954
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70007
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69955
70008
  if (ticketServerScriptPath) {
69956
70009
  const ticketLogPath = import_node_path79.default.join(logDir, "ticket-mcp-server.log");
69957
70010
  const ticketCfgPath = writeTicketMcpConfig({
@@ -69978,7 +70031,7 @@ async function startDaemon(config) {
69978
70031
  import_node_path79.default.join(here, "shift", "mcp-server.cjs"),
69979
70032
  import_node_path79.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
69980
70033
  ];
69981
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70034
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
69982
70035
  if (shiftServerScriptPath) {
69983
70036
  const shiftLogPath = import_node_path79.default.join(logDir, "shift-mcp-server.log");
69984
70037
  const shiftCfgPath = await writeShiftMcpConfig({
@@ -70004,7 +70057,7 @@ async function startDaemon(config) {
70004
70057
  import_node_path79.default.join(here, "inbox", "mcp-server.cjs"),
70005
70058
  import_node_path79.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
70006
70059
  ];
70007
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70060
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70008
70061
  if (inboxServerScriptPath) {
70009
70062
  const inboxLogPath = import_node_path79.default.join(logDir, "inbox-mcp-server.log");
70010
70063
  const inboxCfgPath = await writeInboxMcpConfig({
@@ -70030,7 +70083,7 @@ async function startDaemon(config) {
70030
70083
  import_node_path79.default.join(here, "peer-ops", "mcp-server.cjs"),
70031
70084
  import_node_path79.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
70032
70085
  ];
70033
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70086
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70034
70087
  if (peerOpsServerScriptPath) {
70035
70088
  const peerOpsCfgPath = writePeerOpsMcpConfig({
70036
70089
  dataDir: config.dataDir,
@@ -70053,7 +70106,7 @@ async function startDaemon(config) {
70053
70106
  import_node_path79.default.join(here, "rpc-tool", "mcp-server.cjs"),
70054
70107
  import_node_path79.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
70055
70108
  ];
70056
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70109
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70057
70110
  if (rpcToolServerScriptPath) {
70058
70111
  const rpcToolLogPath = import_node_path79.default.join(logDir, "rpc-tool-mcp-server.log");
70059
70112
  const rpcToolCfgPath = writeRpcToolMcpConfig({
@@ -70079,7 +70132,7 @@ async function startDaemon(config) {
70079
70132
  import_node_path79.default.join(here, "app-builder-plugin", "mcp-server.cjs"),
70080
70133
  import_node_path79.default.join(here, "..", "dist", "app-builder-plugin", "mcp-server.cjs")
70081
70134
  ];
70082
- const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs58.default.existsSync(p2));
70135
+ const appBuilderServerScriptPath = appBuilderServerCandidates.find((p2) => import_node_fs59.default.existsSync(p2));
70083
70136
  if (appBuilderServerScriptPath) {
70084
70137
  const appBuilderLogPath = import_node_path79.default.join(logDir, "app-builder-mcp-server.log");
70085
70138
  const appBuilderCfgPath = writeAppBuilderMcpConfig({
@@ -70185,7 +70238,7 @@ async function startDaemon(config) {
70185
70238
  const absPath = import_node_path79.default.isAbsolute(input.relPath) ? input.relPath : import_node_path79.default.join(input.cwd, input.relPath);
70186
70239
  let size = 0;
70187
70240
  try {
70188
- size = import_node_fs58.default.statSync(absPath).size;
70241
+ size = import_node_fs59.default.statSync(absPath).size;
70189
70242
  } catch (err) {
70190
70243
  logger.warn("attachment.onFileEdit stat failed", {
70191
70244
  sessionId: input.sessionId,
@@ -70287,11 +70340,11 @@ async function startDaemon(config) {
70287
70340
  registerAdapter("claude", claudeAdapter);
70288
70341
  const codexIsolatedHome = import_node_path79.default.join(config.dataDir, "codex-home");
70289
70342
  try {
70290
- import_node_fs58.default.mkdirSync(codexIsolatedHome, { recursive: true });
70343
+ import_node_fs59.default.mkdirSync(codexIsolatedHome, { recursive: true });
70291
70344
  for (const f of ["auth.json", "config.toml"]) {
70292
70345
  const link = import_node_path79.default.join(codexIsolatedHome, f);
70293
70346
  const target = import_node_path79.default.join(import_node_os27.default.homedir(), ".codex", f);
70294
- 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);
70295
70348
  }
70296
70349
  } catch (err) {
70297
70350
  logger.warn("codex isolated home setup failed", { err: String(err) });
@@ -70314,10 +70367,12 @@ async function startDaemon(config) {
70314
70367
  projectPaths: projectsStore.listMerged().map((x) => x.path),
70315
70368
  sharedHome: import_node_path79.default.join(import_node_os27.default.homedir(), ".codex"),
70316
70369
  isolatedHome: codexIsolatedHome
70317
- })
70370
+ }),
70371
+ // 附件图片验签:与 http-router /files 路由同一把 secret
70372
+ getSignSecret: () => authFile.token
70318
70373
  })
70319
70374
  );
70320
- registerAdapter(CODEX_CLOUD_TOOL_ID, new CloudCodexAdapter({ client: cloudGateway, logger }));
70375
+ registerAdapter(CODEX_CLOUD_TOOL_ID, new CloudCodexAdapter({ client: cloudGateway, logger, getSignSecret: () => authFile.token }));
70321
70376
  warmCodexFeatureCache();
70322
70377
  const personaRegistry = new PersonaRegistry(personaStore);
70323
70378
  const refreshCloudPersonas = async () => {
@@ -71259,7 +71314,7 @@ ${bar}
71259
71314
  `);
71260
71315
  try {
71261
71316
  const connectPath = import_node_path79.default.join(config.dataDir, "connect.txt");
71262
- 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 });
71263
71318
  } catch {
71264
71319
  }
71265
71320
  } catch (err) {
@@ -71348,7 +71403,7 @@ ${bar}
71348
71403
  function migrateDropPersonsDir(dataDir) {
71349
71404
  const dir = import_node_path79.default.join(dataDir, "persons");
71350
71405
  try {
71351
- import_node_fs58.default.rmSync(dir, { recursive: true, force: true });
71406
+ import_node_fs59.default.rmSync(dir, { recursive: true, force: true });
71352
71407
  } catch {
71353
71408
  }
71354
71409
  }