@clawos-dev/clawd 0.2.617 → 0.2.619

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
450
450
  init_errors();
451
451
  init_en();
452
452
  makeIssue = (params) => {
453
- const { data, path: path106, errorMaps, issueData } = params;
454
- const fullPath = [...path106, ...issueData.path || []];
453
+ const { data, path: path107, errorMaps, issueData } = params;
454
+ const fullPath = [...path107, ...issueData.path || []];
455
455
  const fullIssue = {
456
456
  ...issueData,
457
457
  path: fullPath
@@ -762,11 +762,11 @@ var init_types = __esm({
762
762
  init_parseUtil();
763
763
  init_util();
764
764
  ParseInputLazyPath = class {
765
- constructor(parent, value, path106, key) {
765
+ constructor(parent, value, path107, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path106;
769
+ this._path = path107;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -7835,7 +7835,8 @@ var init_persona_schemas = __esm({
7835
7835
  size: external_exports.string().optional(),
7836
7836
  /**
7837
7837
  * 云上 task 运行模式下一个 task Pod 同时跑几个 task(design 2026-09-19-cloud-task-mode §3.6),没写按 4。
7838
- * 同 size:只有发布上云的流水线读它(cloud-host/pipeline/deploy-file.mjs 校验正整数、不合格拒发);本机跑不看;没有设置页,作者直接改 persona.json
7838
+ * 只有发布上云的流水线读它(cloud-host/pipeline/deploy-file.mjs 校验正整数、不合格拒发);本机跑不看。
7839
+ * 发布页的资源预估卡通过 persona:update 保存,下次发布生效。
7839
7840
  */
7840
7841
  taskConcurrency: external_exports.number().int().positive().optional(),
7841
7842
  createdAt: external_exports.number(),
@@ -7951,6 +7952,7 @@ var init_persona_schemas = __esm({
7951
7952
  tool: external_exports.string().optional(),
7952
7953
  // 云上任务 Pod 的规格档:只收四档之一(PersonaFile 层是 string,边界在这里收窄)
7953
7954
  size: PersonaSizeSchema.optional(),
7955
+ taskConcurrency: PersonaFileSchema.shape.taskConcurrency,
7954
7956
  personality: external_exports.string().optional(),
7955
7957
  // 人格补充层正文(见 PersonaInfoResponseSchema.personalityLocal)。与 personality 各写
7956
7958
  // 各层、互不影响;'' = 清空补充层。预装 persona 的编辑入口写的就是这个字段。
@@ -10356,8 +10358,8 @@ var require_req = __commonJS({
10356
10358
  if (req.originalUrl) {
10357
10359
  _req.url = req.originalUrl;
10358
10360
  } else {
10359
- const path106 = req.path;
10360
- _req.url = typeof path106 === "string" ? path106 : req.url ? req.url.path || req.url : void 0;
10361
+ const path107 = req.path;
10362
+ _req.url = typeof path107 === "string" ? path107 : req.url ? req.url.path || req.url : void 0;
10361
10363
  }
10362
10364
  if (req.query) {
10363
10365
  _req.query = req.query;
@@ -10522,14 +10524,14 @@ var require_redact = __commonJS({
10522
10524
  }
10523
10525
  return obj;
10524
10526
  }
10525
- function parsePath(path106) {
10527
+ function parsePath(path107) {
10526
10528
  const parts = [];
10527
10529
  let current = "";
10528
10530
  let inBrackets = false;
10529
10531
  let inQuotes = false;
10530
10532
  let quoteChar = "";
10531
- for (let i2 = 0; i2 < path106.length; i2++) {
10532
- const char = path106[i2];
10533
+ for (let i2 = 0; i2 < path107.length; i2++) {
10534
+ const char = path107[i2];
10533
10535
  if (!inBrackets && char === ".") {
10534
10536
  if (current) {
10535
10537
  parts.push(current);
@@ -10660,10 +10662,10 @@ var require_redact = __commonJS({
10660
10662
  return current;
10661
10663
  }
10662
10664
  function redactPaths(obj, paths, censor, remove = false) {
10663
- for (const path106 of paths) {
10664
- const parts = parsePath(path106);
10665
+ for (const path107 of paths) {
10666
+ const parts = parsePath(path107);
10665
10667
  if (parts.includes("*")) {
10666
- redactWildcardPath(obj, parts, censor, path106, remove);
10668
+ redactWildcardPath(obj, parts, censor, path107, remove);
10667
10669
  } else {
10668
10670
  if (remove) {
10669
10671
  removeKey(obj, parts);
@@ -10748,8 +10750,8 @@ var require_redact = __commonJS({
10748
10750
  }
10749
10751
  } else {
10750
10752
  if (afterWildcard.includes("*")) {
10751
- const wrappedCensor = typeof censor === "function" ? (value, path106) => {
10752
- const fullPath = [...pathArray.slice(0, pathLength), ...path106];
10753
+ const wrappedCensor = typeof censor === "function" ? (value, path107) => {
10754
+ const fullPath = [...pathArray.slice(0, pathLength), ...path107];
10753
10755
  return censor(value, fullPath);
10754
10756
  } : censor;
10755
10757
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -10784,8 +10786,8 @@ var require_redact = __commonJS({
10784
10786
  return null;
10785
10787
  }
10786
10788
  const pathStructure = /* @__PURE__ */ new Map();
10787
- for (const path106 of pathsToClone) {
10788
- const parts = parsePath(path106);
10789
+ for (const path107 of pathsToClone) {
10790
+ const parts = parsePath(path107);
10789
10791
  let current = pathStructure;
10790
10792
  for (let i2 = 0; i2 < parts.length; i2++) {
10791
10793
  const part = parts[i2];
@@ -10837,24 +10839,24 @@ var require_redact = __commonJS({
10837
10839
  }
10838
10840
  return cloneSelectively(obj, pathStructure);
10839
10841
  }
10840
- function validatePath(path106) {
10841
- if (typeof path106 !== "string") {
10842
+ function validatePath(path107) {
10843
+ if (typeof path107 !== "string") {
10842
10844
  throw new Error("Paths must be (non-empty) strings");
10843
10845
  }
10844
- if (path106 === "") {
10846
+ if (path107 === "") {
10845
10847
  throw new Error("Invalid redaction path ()");
10846
10848
  }
10847
- if (path106.includes("..")) {
10848
- throw new Error(`Invalid redaction path (${path106})`);
10849
+ if (path107.includes("..")) {
10850
+ throw new Error(`Invalid redaction path (${path107})`);
10849
10851
  }
10850
- if (path106.includes(",")) {
10851
- throw new Error(`Invalid redaction path (${path106})`);
10852
+ if (path107.includes(",")) {
10853
+ throw new Error(`Invalid redaction path (${path107})`);
10852
10854
  }
10853
10855
  let bracketCount = 0;
10854
10856
  let inQuotes = false;
10855
10857
  let quoteChar = "";
10856
- for (let i2 = 0; i2 < path106.length; i2++) {
10857
- const char = path106[i2];
10858
+ for (let i2 = 0; i2 < path107.length; i2++) {
10859
+ const char = path107[i2];
10858
10860
  if ((char === '"' || char === "'") && bracketCount > 0) {
10859
10861
  if (!inQuotes) {
10860
10862
  inQuotes = true;
@@ -10868,20 +10870,20 @@ var require_redact = __commonJS({
10868
10870
  } else if (char === "]" && !inQuotes) {
10869
10871
  bracketCount--;
10870
10872
  if (bracketCount < 0) {
10871
- throw new Error(`Invalid redaction path (${path106})`);
10873
+ throw new Error(`Invalid redaction path (${path107})`);
10872
10874
  }
10873
10875
  }
10874
10876
  }
10875
10877
  if (bracketCount !== 0) {
10876
- throw new Error(`Invalid redaction path (${path106})`);
10878
+ throw new Error(`Invalid redaction path (${path107})`);
10877
10879
  }
10878
10880
  }
10879
10881
  function validatePaths(paths) {
10880
10882
  if (!Array.isArray(paths)) {
10881
10883
  throw new TypeError("paths must be an array");
10882
10884
  }
10883
- for (const path106 of paths) {
10884
- validatePath(path106);
10885
+ for (const path107 of paths) {
10886
+ validatePath(path107);
10885
10887
  }
10886
10888
  }
10887
10889
  function slowRedact(options = {}) {
@@ -11049,8 +11051,8 @@ var require_redaction = __commonJS({
11049
11051
  if (shape[k3] === null) {
11050
11052
  o2[k3] = (value) => topCensor(value, [k3]);
11051
11053
  } else {
11052
- const wrappedCensor = typeof censor === "function" ? (value, path106) => {
11053
- return censor(value, [k3, ...path106]);
11054
+ const wrappedCensor = typeof censor === "function" ? (value, path107) => {
11055
+ return censor(value, [k3, ...path107]);
11054
11056
  } : censor;
11055
11057
  o2[k3] = Redact({
11056
11058
  paths: shape[k3],
@@ -11268,10 +11270,10 @@ var require_atomic_sleep = __commonJS({
11268
11270
  var require_sonic_boom = __commonJS({
11269
11271
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
11270
11272
  "use strict";
11271
- var fs95 = require("fs");
11273
+ var fs96 = require("fs");
11272
11274
  var EventEmitter2 = require("events");
11273
11275
  var inherits = require("util").inherits;
11274
- var path106 = require("path");
11276
+ var path107 = require("path");
11275
11277
  var sleep2 = require_atomic_sleep();
11276
11278
  var assert = require("assert");
11277
11279
  var BUSY_WRITE_TIMEOUT = 100;
@@ -11325,20 +11327,20 @@ var require_sonic_boom = __commonJS({
11325
11327
  const mode = sonic.mode;
11326
11328
  if (sonic.sync) {
11327
11329
  try {
11328
- if (sonic.mkdir) fs95.mkdirSync(path106.dirname(file), { recursive: true });
11329
- const fd = fs95.openSync(file, flags, mode);
11330
+ if (sonic.mkdir) fs96.mkdirSync(path107.dirname(file), { recursive: true });
11331
+ const fd = fs96.openSync(file, flags, mode);
11330
11332
  fileOpened(null, fd);
11331
11333
  } catch (err) {
11332
11334
  fileOpened(err);
11333
11335
  throw err;
11334
11336
  }
11335
11337
  } else if (sonic.mkdir) {
11336
- fs95.mkdir(path106.dirname(file), { recursive: true }, (err) => {
11338
+ fs96.mkdir(path107.dirname(file), { recursive: true }, (err) => {
11337
11339
  if (err) return fileOpened(err);
11338
- fs95.open(file, flags, mode, fileOpened);
11340
+ fs96.open(file, flags, mode, fileOpened);
11339
11341
  });
11340
11342
  } else {
11341
- fs95.open(file, flags, mode, fileOpened);
11343
+ fs96.open(file, flags, mode, fileOpened);
11342
11344
  }
11343
11345
  }
11344
11346
  function SonicBoom(opts) {
@@ -11379,8 +11381,8 @@ var require_sonic_boom = __commonJS({
11379
11381
  this.flush = flushBuffer;
11380
11382
  this.flushSync = flushBufferSync;
11381
11383
  this._actualWrite = actualWriteBuffer;
11382
- fsWriteSync = () => fs95.writeSync(this.fd, this._writingBuf);
11383
- fsWrite = () => fs95.write(this.fd, this._writingBuf, this.release);
11384
+ fsWriteSync = () => fs96.writeSync(this.fd, this._writingBuf);
11385
+ fsWrite = () => fs96.write(this.fd, this._writingBuf, this.release);
11384
11386
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
11385
11387
  this._writingBuf = "";
11386
11388
  this.write = write;
@@ -11389,15 +11391,15 @@ var require_sonic_boom = __commonJS({
11389
11391
  this._actualWrite = actualWrite;
11390
11392
  fsWriteSync = () => {
11391
11393
  if (Buffer.isBuffer(this._writingBuf)) {
11392
- return fs95.writeSync(this.fd, this._writingBuf);
11394
+ return fs96.writeSync(this.fd, this._writingBuf);
11393
11395
  }
11394
- return fs95.writeSync(this.fd, this._writingBuf, "utf8");
11396
+ return fs96.writeSync(this.fd, this._writingBuf, "utf8");
11395
11397
  };
11396
11398
  fsWrite = () => {
11397
11399
  if (Buffer.isBuffer(this._writingBuf)) {
11398
- return fs95.write(this.fd, this._writingBuf, this.release);
11400
+ return fs96.write(this.fd, this._writingBuf, this.release);
11399
11401
  }
11400
- return fs95.write(this.fd, this._writingBuf, "utf8", this.release);
11402
+ return fs96.write(this.fd, this._writingBuf, "utf8", this.release);
11401
11403
  };
11402
11404
  } else {
11403
11405
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -11454,7 +11456,7 @@ var require_sonic_boom = __commonJS({
11454
11456
  }
11455
11457
  }
11456
11458
  if (this._fsync) {
11457
- fs95.fsyncSync(this.fd);
11459
+ fs96.fsyncSync(this.fd);
11458
11460
  }
11459
11461
  const len = this._len;
11460
11462
  if (this._reopening) {
@@ -11568,7 +11570,7 @@ var require_sonic_boom = __commonJS({
11568
11570
  const onDrain = () => {
11569
11571
  if (!this._fsync) {
11570
11572
  try {
11571
- fs95.fsync(this.fd, (err) => {
11573
+ fs96.fsync(this.fd, (err) => {
11572
11574
  this._flushPending = false;
11573
11575
  cb(err);
11574
11576
  });
@@ -11670,7 +11672,7 @@ var require_sonic_boom = __commonJS({
11670
11672
  const fd = this.fd;
11671
11673
  this.once("ready", () => {
11672
11674
  if (fd !== this.fd) {
11673
- fs95.close(fd, (err) => {
11675
+ fs96.close(fd, (err) => {
11674
11676
  if (err) {
11675
11677
  return this.emit("error", err);
11676
11678
  }
@@ -11719,7 +11721,7 @@ var require_sonic_boom = __commonJS({
11719
11721
  buf = this._bufs[0];
11720
11722
  }
11721
11723
  try {
11722
- const n2 = Buffer.isBuffer(buf) ? fs95.writeSync(this.fd, buf) : fs95.writeSync(this.fd, buf, "utf8");
11724
+ const n2 = Buffer.isBuffer(buf) ? fs96.writeSync(this.fd, buf) : fs96.writeSync(this.fd, buf, "utf8");
11723
11725
  const releasedBufObj = releaseWritingBuf(buf, this._len, n2);
11724
11726
  buf = releasedBufObj.writingBuf;
11725
11727
  this._len = releasedBufObj.len;
@@ -11735,7 +11737,7 @@ var require_sonic_boom = __commonJS({
11735
11737
  }
11736
11738
  }
11737
11739
  try {
11738
- fs95.fsyncSync(this.fd);
11740
+ fs96.fsyncSync(this.fd);
11739
11741
  } catch {
11740
11742
  }
11741
11743
  }
@@ -11756,7 +11758,7 @@ var require_sonic_boom = __commonJS({
11756
11758
  buf = mergeBuf(this._bufs[0], this._lens[0]);
11757
11759
  }
11758
11760
  try {
11759
- const n2 = fs95.writeSync(this.fd, buf);
11761
+ const n2 = fs96.writeSync(this.fd, buf);
11760
11762
  buf = buf.subarray(n2);
11761
11763
  this._len = Math.max(this._len - n2, 0);
11762
11764
  if (buf.length <= 0) {
@@ -11784,13 +11786,13 @@ var require_sonic_boom = __commonJS({
11784
11786
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
11785
11787
  if (this.sync) {
11786
11788
  try {
11787
- const written = Buffer.isBuffer(this._writingBuf) ? fs95.writeSync(this.fd, this._writingBuf) : fs95.writeSync(this.fd, this._writingBuf, "utf8");
11789
+ const written = Buffer.isBuffer(this._writingBuf) ? fs96.writeSync(this.fd, this._writingBuf) : fs96.writeSync(this.fd, this._writingBuf, "utf8");
11788
11790
  release2(null, written);
11789
11791
  } catch (err) {
11790
11792
  release2(err);
11791
11793
  }
11792
11794
  } else {
11793
- fs95.write(this.fd, this._writingBuf, release2);
11795
+ fs96.write(this.fd, this._writingBuf, release2);
11794
11796
  }
11795
11797
  }
11796
11798
  function actualWriteBuffer() {
@@ -11799,7 +11801,7 @@ var require_sonic_boom = __commonJS({
11799
11801
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
11800
11802
  if (this.sync) {
11801
11803
  try {
11802
- const written = fs95.writeSync(this.fd, this._writingBuf);
11804
+ const written = fs96.writeSync(this.fd, this._writingBuf);
11803
11805
  release2(null, written);
11804
11806
  } catch (err) {
11805
11807
  release2(err);
@@ -11808,7 +11810,7 @@ var require_sonic_boom = __commonJS({
11808
11810
  if (kCopyBuffer) {
11809
11811
  this._writingBuf = Buffer.from(this._writingBuf);
11810
11812
  }
11811
- fs95.write(this.fd, this._writingBuf, release2);
11813
+ fs96.write(this.fd, this._writingBuf, release2);
11812
11814
  }
11813
11815
  }
11814
11816
  function actualClose(sonic) {
@@ -11824,12 +11826,12 @@ var require_sonic_boom = __commonJS({
11824
11826
  sonic._lens = [];
11825
11827
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
11826
11828
  try {
11827
- fs95.fsync(sonic.fd, closeWrapped);
11829
+ fs96.fsync(sonic.fd, closeWrapped);
11828
11830
  } catch {
11829
11831
  }
11830
11832
  function closeWrapped() {
11831
11833
  if (sonic.fd !== 1 && sonic.fd !== 2) {
11832
- fs95.close(sonic.fd, done);
11834
+ fs96.close(sonic.fd, done);
11833
11835
  } else {
11834
11836
  done();
11835
11837
  }
@@ -14964,11 +14966,11 @@ var init_lib = __esm({
14964
14966
  }
14965
14967
  }
14966
14968
  },
14967
- addToPath: function addToPath(path106, added, removed, oldPosInc, options) {
14968
- var last = path106.lastComponent;
14969
+ addToPath: function addToPath(path107, added, removed, oldPosInc, options) {
14970
+ var last = path107.lastComponent;
14969
14971
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14970
14972
  return {
14971
- oldPos: path106.oldPos + oldPosInc,
14973
+ oldPos: path107.oldPos + oldPosInc,
14972
14974
  lastComponent: {
14973
14975
  count: last.count + 1,
14974
14976
  added,
@@ -14978,7 +14980,7 @@ var init_lib = __esm({
14978
14980
  };
14979
14981
  } else {
14980
14982
  return {
14981
- oldPos: path106.oldPos + oldPosInc,
14983
+ oldPos: path107.oldPos + oldPosInc,
14982
14984
  lastComponent: {
14983
14985
  count: 1,
14984
14986
  added,
@@ -15560,10 +15562,10 @@ function attachmentToHistoryMessage(o2, ts) {
15560
15562
  const memories = raw.map((m3) => {
15561
15563
  if (!m3 || typeof m3 !== "object") return null;
15562
15564
  const rec6 = m3;
15563
- const path106 = typeof rec6.path === "string" ? rec6.path : null;
15565
+ const path107 = typeof rec6.path === "string" ? rec6.path : null;
15564
15566
  const content = typeof rec6.content === "string" ? rec6.content : null;
15565
- if (!path106 || content == null) return null;
15566
- const entry = { path: path106, content };
15567
+ if (!path107 || content == null) return null;
15568
+ const entry = { path: path107, content };
15567
15569
  if (typeof rec6.mtimeMs === "number") entry.mtimeMs = rec6.mtimeMs;
15568
15570
  return entry;
15569
15571
  }).filter((m3) => m3 !== null);
@@ -16429,10 +16431,10 @@ function parseAttachment(obj) {
16429
16431
  const memories = raw.map((m3) => {
16430
16432
  if (!m3 || typeof m3 !== "object") return null;
16431
16433
  const rec6 = m3;
16432
- const path106 = typeof rec6.path === "string" ? rec6.path : null;
16434
+ const path107 = typeof rec6.path === "string" ? rec6.path : null;
16433
16435
  const content = typeof rec6.content === "string" ? rec6.content : null;
16434
- if (!path106 || content == null) return null;
16435
- const out = { path: path106, content };
16436
+ if (!path107 || content == null) return null;
16437
+ const out = { path: path107, content };
16436
16438
  if (typeof rec6.mtimeMs === "number") out.mtimeMs = rec6.mtimeMs;
16437
16439
  return out;
16438
16440
  }).filter((m3) => m3 !== null);
@@ -37406,8 +37408,8 @@ var require_utils = __commonJS({
37406
37408
  var result = transform[inputType][outputType](input);
37407
37409
  return result;
37408
37410
  };
37409
- exports2.resolve = function(path106) {
37410
- var parts = path106.split("/");
37411
+ exports2.resolve = function(path107) {
37412
+ var parts = path107.split("/");
37411
37413
  var result = [];
37412
37414
  for (var index = 0; index < parts.length; index++) {
37413
37415
  var part = parts[index];
@@ -43260,18 +43262,18 @@ var require_object = __commonJS({
43260
43262
  var object = new ZipObject(name, zipObjectContent, o2);
43261
43263
  this.files[name] = object;
43262
43264
  };
43263
- var parentFolder = function(path106) {
43264
- if (path106.slice(-1) === "/") {
43265
- path106 = path106.substring(0, path106.length - 1);
43265
+ var parentFolder = function(path107) {
43266
+ if (path107.slice(-1) === "/") {
43267
+ path107 = path107.substring(0, path107.length - 1);
43266
43268
  }
43267
- var lastSlash = path106.lastIndexOf("/");
43268
- return lastSlash > 0 ? path106.substring(0, lastSlash) : "";
43269
+ var lastSlash = path107.lastIndexOf("/");
43270
+ return lastSlash > 0 ? path107.substring(0, lastSlash) : "";
43269
43271
  };
43270
- var forceTrailingSlash = function(path106) {
43271
- if (path106.slice(-1) !== "/") {
43272
- path106 += "/";
43272
+ var forceTrailingSlash = function(path107) {
43273
+ if (path107.slice(-1) !== "/") {
43274
+ path107 += "/";
43273
43275
  }
43274
- return path106;
43276
+ return path107;
43275
43277
  };
43276
43278
  var folderAdd = function(name, createFolders) {
43277
43279
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -44273,7 +44275,7 @@ var require_lib3 = __commonJS({
44273
44275
  // src/run-case/recorder.ts
44274
44276
  function startRunCaseRecorder(opts) {
44275
44277
  const now = opts.now ?? Date.now;
44276
- const dir = import_node_path85.default.dirname(opts.recordPath);
44278
+ const dir = import_node_path86.default.dirname(opts.recordPath);
44277
44279
  let stream = null;
44278
44280
  let closing = false;
44279
44281
  let closedSettled = false;
@@ -44287,8 +44289,8 @@ function startRunCaseRecorder(opts) {
44287
44289
  });
44288
44290
  const ensureStream = () => {
44289
44291
  if (stream) return stream;
44290
- import_node_fs66.default.mkdirSync(dir, { recursive: true });
44291
- stream = import_node_fs66.default.createWriteStream(opts.recordPath, { flags: "a" });
44292
+ import_node_fs67.default.mkdirSync(dir, { recursive: true });
44293
+ stream = import_node_fs67.default.createWriteStream(opts.recordPath, { flags: "a" });
44292
44294
  stream.on("close", () => closedResolve());
44293
44295
  return stream;
44294
44296
  };
@@ -44313,12 +44315,12 @@ function startRunCaseRecorder(opts) {
44313
44315
  };
44314
44316
  return { tap, close, closed };
44315
44317
  }
44316
- var import_node_fs66, import_node_path85;
44318
+ var import_node_fs67, import_node_path86;
44317
44319
  var init_recorder = __esm({
44318
44320
  "src/run-case/recorder.ts"() {
44319
44321
  "use strict";
44320
- import_node_fs66 = __toESM(require("fs"), 1);
44321
- import_node_path85 = __toESM(require("path"), 1);
44322
+ import_node_fs67 = __toESM(require("fs"), 1);
44323
+ import_node_path86 = __toESM(require("path"), 1);
44322
44324
  }
44323
44325
  });
44324
44326
 
@@ -44361,7 +44363,7 @@ var init_wire = __esm({
44361
44363
  // src/run-case/controller.ts
44362
44364
  async function runController(opts) {
44363
44365
  const now = opts.now ?? Date.now;
44364
- const cwd = opts.cwd ?? (0, import_node_fs67.mkdtempSync)(import_node_path86.default.join(import_node_os32.default.tmpdir(), "clawd-runcase-"));
44366
+ const cwd = opts.cwd ?? (0, import_node_fs68.mkdtempSync)(import_node_path87.default.join(import_node_os32.default.tmpdir(), "clawd-runcase-"));
44365
44367
  const ownsCwd = opts.cwd === void 0;
44366
44368
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
44367
44369
  const spawnCtx = { cwd };
@@ -44522,19 +44524,19 @@ async function runController(opts) {
44522
44524
  if (sigintHandler) process.off("SIGINT", sigintHandler);
44523
44525
  if (ownsCwd) {
44524
44526
  try {
44525
- (0, import_node_fs67.rmSync)(cwd, { recursive: true, force: true });
44527
+ (0, import_node_fs68.rmSync)(cwd, { recursive: true, force: true });
44526
44528
  } catch {
44527
44529
  }
44528
44530
  }
44529
44531
  return exitCode ?? 0;
44530
44532
  }
44531
- var import_node_fs67, import_node_os32, import_node_path86;
44533
+ var import_node_fs68, import_node_os32, import_node_path87;
44532
44534
  var init_controller = __esm({
44533
44535
  "src/run-case/controller.ts"() {
44534
44536
  "use strict";
44535
- import_node_fs67 = require("fs");
44537
+ import_node_fs68 = require("fs");
44536
44538
  import_node_os32 = __toESM(require("os"), 1);
44537
- import_node_path86 = __toESM(require("path"), 1);
44539
+ import_node_path87 = __toESM(require("path"), 1);
44538
44540
  init_claude();
44539
44541
  init_stdout_splitter();
44540
44542
  init_permission_stdio();
@@ -44806,8 +44808,8 @@ Env (advanced):
44806
44808
  `;
44807
44809
 
44808
44810
  // src/index.ts
44809
- var import_node_path84 = __toESM(require("path"), 1);
44810
- var import_node_fs65 = __toESM(require("fs"), 1);
44811
+ var import_node_path85 = __toESM(require("path"), 1);
44812
+ var import_node_fs66 = __toESM(require("fs"), 1);
44811
44813
  var import_node_os31 = __toESM(require("os"), 1);
44812
44814
  var import_node_crypto27 = require("crypto");
44813
44815
  var import_node_url6 = require("url");
@@ -52906,9 +52908,9 @@ var CentralClientError = class extends Error {
52906
52908
  cause;
52907
52909
  status;
52908
52910
  };
52909
- async function centralRequest(opts, path106, init) {
52911
+ async function centralRequest(opts, path107, init) {
52910
52912
  const f2 = opts.fetchImpl ?? globalThis.fetch;
52911
- const url = `${opts.api.replace(/\/+$/, "")}${path106}`;
52913
+ const url = `${opts.api.replace(/\/+$/, "")}${path107}`;
52912
52914
  const ctrl = new AbortController();
52913
52915
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
52914
52916
  let res;
@@ -53944,8 +53946,8 @@ function turnStartInput(text, resolveImage) {
53944
53946
  const items = [];
53945
53947
  let leftover = text;
53946
53948
  for (const m3 of text.matchAll(SKILL_RE)) {
53947
- const [marker, name, path106] = m3;
53948
- items.push({ type: "skill", name, path: path106 });
53949
+ const [marker, name, path107] = m3;
53950
+ items.push({ type: "skill", name, path: path107 });
53949
53951
  leftover = leftover.replace(marker, "");
53950
53952
  }
53951
53953
  for (const m3 of text.matchAll(ATTACHMENT_RE2)) {
@@ -61320,10 +61322,10 @@ function createGithubApi(args) {
61320
61322
  const doFetch = args.fetch ?? fetch;
61321
61323
  const seal = args.seal ?? sealWithSodium;
61322
61324
  const timeoutMs = args.timeoutMs ?? TIMEOUT_MS;
61323
- async function request(method, path106, body) {
61325
+ async function request(method, path107, body) {
61324
61326
  let res;
61325
61327
  try {
61326
- res = await doFetch(`${API}${path106}`, {
61328
+ res = await doFetch(`${API}${path107}`, {
61327
61329
  method,
61328
61330
  headers: {
61329
61331
  Authorization: `Bearer ${args.token}`,
@@ -61348,8 +61350,8 @@ function createGithubApi(args) {
61348
61350
  }
61349
61351
  return { status: res.status, json };
61350
61352
  }
61351
- async function must(method, path106, what, body) {
61352
- const r2 = await request(method, path106, body);
61353
+ async function must(method, path107, what, body) {
61354
+ const r2 = await request(method, path107, body);
61353
61355
  if (r2.status < 200 || r2.status >= 300) throw new GithubApiError(r2.status, explain(r2.status, what, r2.json));
61354
61356
  return r2.json;
61355
61357
  }
@@ -61394,9 +61396,9 @@ function createGithubApi(args) {
61394
61396
  return { env: x2.name, ...Number.isFinite(at3) ? { setAt: at3 } : {} };
61395
61397
  });
61396
61398
  },
61397
- async getJson(path106) {
61399
+ async getJson(path107) {
61398
61400
  try {
61399
- const r2 = await request("GET", path106);
61401
+ const r2 = await request("GET", path107);
61400
61402
  return r2.status >= 200 && r2.status < 300 ? r2.json : void 0;
61401
61403
  } catch {
61402
61404
  return void 0;
@@ -62654,16 +62656,364 @@ function buildDeployHandlers(deps) {
62654
62656
  }
62655
62657
 
62656
62658
  // src/tools/subscription-channels-store.ts
62659
+ var import_node_fs36 = __toESM(require("fs"), 1);
62660
+ var import_node_os13 = __toESM(require("os"), 1);
62661
+ var import_node_path41 = __toESM(require("path"), 1);
62662
+
62663
+ // src/tools/subscription-channels-apply.ts
62657
62664
  var import_node_fs35 = __toESM(require("fs"), 1);
62658
62665
  var import_node_os12 = __toESM(require("os"), 1);
62659
62666
  var import_node_path40 = __toESM(require("path"), 1);
62667
+
62668
+ // src/tools/codex-config-toml.ts
62669
+ function parseKey(src, start) {
62670
+ const parts = [];
62671
+ let i2 = start;
62672
+ for (; ; ) {
62673
+ while (src[i2] === " " || src[i2] === " ") i2++;
62674
+ let part;
62675
+ if (src[i2] === '"') {
62676
+ let j2 = i2 + 1;
62677
+ while (j2 < src.length && src[j2] !== '"') j2 += src[j2] === "\\" ? 2 : 1;
62678
+ if (j2 >= src.length) return null;
62679
+ try {
62680
+ part = JSON.parse(src.slice(i2, j2 + 1));
62681
+ } catch {
62682
+ part = src.slice(i2 + 1, j2);
62683
+ }
62684
+ i2 = j2 + 1;
62685
+ } else if (src[i2] === "'") {
62686
+ const j2 = src.indexOf("'", i2 + 1);
62687
+ if (j2 < 0) return null;
62688
+ part = src.slice(i2 + 1, j2);
62689
+ i2 = j2 + 1;
62690
+ } else {
62691
+ const bare = /^[A-Za-z0-9_-]+/.exec(src.slice(i2));
62692
+ if (!bare) return null;
62693
+ part = bare[0];
62694
+ i2 += part.length;
62695
+ }
62696
+ parts.push(part);
62697
+ while (src[i2] === " " || src[i2] === " ") i2++;
62698
+ if (src[i2] !== ".") return { parts, end: i2 };
62699
+ i2++;
62700
+ }
62701
+ }
62702
+ function tableHeader(line) {
62703
+ const open = /^\s*(\[\[?)/.exec(line);
62704
+ if (!open) return null;
62705
+ const key = parseKey(line, open[0].length);
62706
+ if (!key) return null;
62707
+ const close = open[1] === "[[" ? "]]" : "]";
62708
+ if (!line.startsWith(close, key.end)) return null;
62709
+ return /^\s*(?:#.*)?$/.test(line.slice(key.end + close.length)) ? key.parts : null;
62710
+ }
62711
+ function keyLine(line) {
62712
+ const lead = /^\s*/.exec(line)[0].length;
62713
+ if (line[lead] === "[" || line[lead] === "#") return null;
62714
+ const key = parseKey(line, lead);
62715
+ return key && line[key.end] === "=" ? { parts: key.parts, valueStart: key.end + 1 } : null;
62716
+ }
62717
+ function scanValue(s2, start, st2) {
62718
+ let i2 = start;
62719
+ while (i2 < s2.length) {
62720
+ if (st2.ml) {
62721
+ if (st2.ml === '"""' && s2[i2] === "\\") {
62722
+ i2 += 2;
62723
+ continue;
62724
+ }
62725
+ if (s2.startsWith(st2.ml, i2)) {
62726
+ let j2 = i2 + 3;
62727
+ while (j2 < s2.length && j2 < i2 + 5 && s2[j2] === st2.ml[0]) j2++;
62728
+ st2.ml = null;
62729
+ i2 = j2;
62730
+ continue;
62731
+ }
62732
+ i2++;
62733
+ continue;
62734
+ }
62735
+ const c2 = s2[i2];
62736
+ if (c2 === "#") return;
62737
+ if (s2.startsWith('"""', i2) || s2.startsWith("'''", i2)) {
62738
+ st2.ml = s2.slice(i2, i2 + 3);
62739
+ i2 += 3;
62740
+ continue;
62741
+ }
62742
+ if (c2 === '"') {
62743
+ i2++;
62744
+ while (i2 < s2.length && s2[i2] !== '"') i2 += s2[i2] === "\\" ? 2 : 1;
62745
+ i2++;
62746
+ continue;
62747
+ }
62748
+ if (c2 === "'") {
62749
+ const j2 = s2.indexOf("'", i2 + 1);
62750
+ i2 = j2 < 0 ? s2.length : j2 + 1;
62751
+ continue;
62752
+ }
62753
+ if (c2 === "[" || c2 === "{") st2.depth++;
62754
+ else if ((c2 === "]" || c2 === "}") && st2.depth > 0) st2.depth--;
62755
+ i2++;
62756
+ }
62757
+ }
62758
+ function scanToml(text) {
62759
+ const out = [];
62760
+ const st2 = { ml: null, depth: 0 };
62761
+ let table = [];
62762
+ for (const line of text.split("\n")) {
62763
+ if (st2.ml || st2.depth > 0) {
62764
+ scanValue(line, 0, st2);
62765
+ out.push({ text: line, kind: "continuation", table });
62766
+ continue;
62767
+ }
62768
+ const header = tableHeader(line);
62769
+ if (header) {
62770
+ table = header;
62771
+ out.push({ text: line, kind: "header", table, key: header });
62772
+ continue;
62773
+ }
62774
+ const key = keyLine(line);
62775
+ if (key) {
62776
+ scanValue(line, key.valueStart, st2);
62777
+ out.push({ text: line, kind: "key", table, key: key.parts, value: line.slice(key.valueStart) });
62778
+ continue;
62779
+ }
62780
+ out.push({ text: line, kind: "other", table });
62781
+ }
62782
+ return out;
62783
+ }
62784
+ var UNREADABLE = /* @__PURE__ */ Symbol("unreadable TOML value");
62785
+ function parseTomlValue(raw) {
62786
+ const parsed = parseValueAt(raw, 0);
62787
+ if (!parsed) return void 0;
62788
+ return /^\s*(?:#[^\n]*)?\s*$/.test(raw.slice(parsed.end)) ? parsed.value : void 0;
62789
+ }
62790
+ function skipSeparators(s2, start) {
62791
+ let i2 = start;
62792
+ for (; ; ) {
62793
+ while (i2 < s2.length && " \r\n,".includes(s2[i2])) i2++;
62794
+ if (s2[i2] !== "#") return i2;
62795
+ const newline = s2.indexOf("\n", i2);
62796
+ i2 = newline < 0 ? s2.length : newline;
62797
+ }
62798
+ }
62799
+ function parseValueAt(s2, start) {
62800
+ let i2 = start;
62801
+ while (s2[i2] === " " || s2[i2] === " ") i2++;
62802
+ const c2 = s2[i2];
62803
+ if (c2 === '"') {
62804
+ if (s2.startsWith('"""', i2)) return null;
62805
+ let j2 = i2 + 1;
62806
+ while (j2 < s2.length && s2[j2] !== '"') j2 += s2[j2] === "\\" ? 2 : 1;
62807
+ if (j2 >= s2.length) return null;
62808
+ try {
62809
+ return { value: JSON.parse(s2.slice(i2, j2 + 1)), end: j2 + 1 };
62810
+ } catch {
62811
+ return null;
62812
+ }
62813
+ }
62814
+ if (c2 === "'") {
62815
+ if (s2.startsWith("'''", i2)) return null;
62816
+ const j2 = s2.indexOf("'", i2 + 1);
62817
+ return j2 < 0 ? null : { value: s2.slice(i2 + 1, j2), end: j2 + 1 };
62818
+ }
62819
+ if (c2 === "[") {
62820
+ const items = [];
62821
+ i2++;
62822
+ for (; ; ) {
62823
+ i2 = skipSeparators(s2, i2);
62824
+ if (s2[i2] === "]") return { value: items, end: i2 + 1 };
62825
+ const item = parseValueAt(s2, i2);
62826
+ if (!item) return null;
62827
+ items.push(item.value);
62828
+ i2 = item.end;
62829
+ }
62830
+ }
62831
+ if (c2 === "{") {
62832
+ const table = {};
62833
+ i2++;
62834
+ for (; ; ) {
62835
+ i2 = skipSeparators(s2, i2);
62836
+ if (s2[i2] === "}") return { value: table, end: i2 + 1 };
62837
+ const key = parseKey(s2, i2);
62838
+ if (!key || s2[key.end] !== "=") return null;
62839
+ const item = parseValueAt(s2, key.end + 1);
62840
+ if (!item) return null;
62841
+ setPath(table, key.parts, item.value);
62842
+ i2 = item.end;
62843
+ }
62844
+ }
62845
+ const bare = /^[^\s,\]}#]+/.exec(s2.slice(i2));
62846
+ return bare ? { value: bare[0], end: i2 + bare[0].length } : null;
62847
+ }
62848
+ function setPath(target, path107, value) {
62849
+ let node = target;
62850
+ for (const part of path107.slice(0, -1)) {
62851
+ const next = node[part];
62852
+ if (!next || typeof next !== "object" || Array.isArray(next)) node[part] = {};
62853
+ node = node[part];
62854
+ }
62855
+ const last = path107[path107.length - 1];
62856
+ const existing = node[last];
62857
+ if (existing && typeof existing === "object" && !Array.isArray(existing) && value && typeof value === "object" && !Array.isArray(value)) {
62858
+ Object.assign(existing, value);
62859
+ } else node[last] = value;
62860
+ }
62861
+ function readTomlTable(text, path107) {
62862
+ const result = {};
62863
+ let found = false;
62864
+ const within = (full) => full.length >= path107.length && path107.every((part, i2) => full[i2] === part);
62865
+ const lines = scanToml(text);
62866
+ for (let index = 0; index < lines.length; index++) {
62867
+ const line = lines[index];
62868
+ if (line.kind === "header" && within(line.key)) {
62869
+ found = true;
62870
+ if (line.key.length > path107.length) setPath(result, line.key.slice(path107.length), {});
62871
+ continue;
62872
+ }
62873
+ if (line.kind !== "key") continue;
62874
+ const full = [...line.table, ...line.key];
62875
+ if (!within(full)) continue;
62876
+ let raw = line.value;
62877
+ while (lines[index + 1]?.kind === "continuation") raw += `
62878
+ ${lines[++index].text}`;
62879
+ const parsed = parseTomlValue(raw);
62880
+ const value = parsed === void 0 ? UNREADABLE : parsed;
62881
+ found = true;
62882
+ if (full.length === path107.length) {
62883
+ if (value && typeof value === "object" && !Array.isArray(value)) Object.assign(result, value);
62884
+ } else setPath(result, full.slice(path107.length), value);
62885
+ }
62886
+ return found ? result : null;
62887
+ }
62888
+
62889
+ // src/tools/subscription-channels-apply.ts
62890
+ var PROVIDER_ID = "cliproxyapi";
62891
+ var isOwnProvider = (path107) => path107[0] === "model_providers" && path107[1] === PROVIDER_ID;
62892
+ function stripCodexProvider(text) {
62893
+ const out = [];
62894
+ let dropping = false;
62895
+ let droppingValue = false;
62896
+ for (const line of scanToml(text)) {
62897
+ if (line.kind === "header") {
62898
+ dropping = isOwnProvider(line.key);
62899
+ droppingValue = false;
62900
+ if (!dropping) out.push(line.text);
62901
+ continue;
62902
+ }
62903
+ if (line.kind === "continuation") {
62904
+ if (!dropping && !droppingValue) out.push(line.text);
62905
+ continue;
62906
+ }
62907
+ if (dropping) continue;
62908
+ if (line.kind === "key") {
62909
+ const full = [...line.table, ...line.key];
62910
+ droppingValue = full.length === 1 && full[0] === "model_provider" || isOwnProvider(full);
62911
+ if (!droppingValue) out.push(line.text);
62912
+ continue;
62913
+ }
62914
+ out.push(line.text);
62915
+ }
62916
+ return out.join("\n").trim();
62917
+ }
62918
+ function writeFileAtomic(file, data) {
62919
+ const target = import_node_fs35.default.existsSync(file) && import_node_fs35.default.lstatSync(file).isSymbolicLink() ? import_node_fs35.default.realpathSync(file) : file;
62920
+ const tmp = `${target}.tmp.${process.pid}.${Date.now()}`;
62921
+ import_node_fs35.default.writeFileSync(tmp, data, { mode: 384 });
62922
+ import_node_fs35.default.renameSync(tmp, target);
62923
+ }
62924
+ function snapshotFile(file) {
62925
+ const original = import_node_fs35.default.existsSync(file) ? import_node_fs35.default.readFileSync(file) : null;
62926
+ return () => {
62927
+ const current = import_node_fs35.default.existsSync(file) ? import_node_fs35.default.readFileSync(file) : null;
62928
+ if (original === null) {
62929
+ if (current !== null) import_node_fs35.default.rmSync(file, { force: true });
62930
+ return;
62931
+ }
62932
+ if (current !== null && current.equals(original)) return;
62933
+ writeFileAtomic(file, original);
62934
+ };
62935
+ }
62936
+ var resolveCodexHome2 = (codexHome) => codexHome || process.env.CODEX_HOME || import_node_path40.default.join(import_node_os12.default.homedir(), ".codex");
62937
+ var resolvePiAgentDir = (agentDir) => agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path40.default.join(import_node_os12.default.homedir(), ".pi", "agent");
62938
+ var PI_SUBSCRIPTION_FILE = "cliproxyapi.json";
62939
+ function applyCodexSubscriptionChannel(opts) {
62940
+ const codexHome = resolveCodexHome2(opts.codexHome);
62941
+ import_node_fs35.default.mkdirSync(codexHome, { recursive: true });
62942
+ const configFile = import_node_path40.default.join(codexHome, "config.toml");
62943
+ const original = import_node_fs35.default.existsSync(configFile) ? import_node_fs35.default.readFileSync(configFile, "utf8") : "";
62944
+ const rest = stripCodexProvider(original);
62945
+ let content;
62946
+ if (opts.channel) {
62947
+ const ch = opts.channel;
62948
+ content = [
62949
+ `model_provider = "${PROVIDER_ID}"`,
62950
+ ...rest ? ["", rest] : [],
62951
+ "",
62952
+ `[model_providers.${PROVIDER_ID}]`,
62953
+ `name = "${PROVIDER_ID}"`,
62954
+ `base_url = ${JSON.stringify(ch.baseUrl)}`,
62955
+ 'wire_api = "responses"',
62956
+ `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
62957
+ ""
62958
+ ].join("\n");
62959
+ } else {
62960
+ content = [
62961
+ 'model_provider = "openai"',
62962
+ ...rest ? ["", rest] : [],
62963
+ ""
62964
+ ].join("\n");
62965
+ }
62966
+ writeFileAtomic(configFile, content);
62967
+ }
62968
+ function applyPiSubscriptionChannel(opts) {
62969
+ const agentDir = resolvePiAgentDir(opts.agentDir);
62970
+ if (!import_node_fs35.default.existsSync(agentDir)) return false;
62971
+ const configFile = import_node_path40.default.join(agentDir, PI_SUBSCRIPTION_FILE);
62972
+ if (opts.channel) {
62973
+ const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
62974
+ writeFileAtomic(configFile, JSON.stringify(data, null, 2) + "\n");
62975
+ return true;
62976
+ }
62977
+ return false;
62978
+ }
62979
+
62980
+ // src/tools/subscription-channels-store.ts
62660
62981
  var CHANNELS_FILE_NAME = "subscription-channels.json";
62982
+ function providerKey(provider, codexHome) {
62983
+ if ([provider.env_key, provider.experimental_bearer_token, provider.auth].includes(UNREADABLE)) return null;
62984
+ const envKey = typeof provider.env_key === "string" && provider.env_key ? provider.env_key : null;
62985
+ if (envKey) return process.env[envKey] || null;
62986
+ const inline = provider.experimental_bearer_token;
62987
+ if (typeof inline === "string" && inline) return inline;
62988
+ if (provider.auth !== void 0) {
62989
+ const auth = provider.auth;
62990
+ const args = auth?.args;
62991
+ if (auth?.command !== "echo" || !Array.isArray(args) || args.length !== 1) return null;
62992
+ const [arg] = args;
62993
+ if (typeof arg !== "string" || /^-[neE]+$/.test(arg)) return null;
62994
+ return arg.trim() || null;
62995
+ }
62996
+ return readAuthKey2(codexHome);
62997
+ }
62998
+ function readAuthKey2(codexHome) {
62999
+ try {
63000
+ const key = JSON.parse(import_node_fs36.default.readFileSync(import_node_path41.default.join(codexHome, "auth.json"), "utf8")).OPENAI_API_KEY;
63001
+ return typeof key === "string" && key ? key : null;
63002
+ } catch {
63003
+ return null;
63004
+ }
63005
+ }
62661
63006
  var SubscriptionChannelStore = class {
62662
63007
  filePath;
62663
63008
  codexHome;
62664
63009
  constructor(options) {
62665
- this.filePath = import_node_path40.default.join(options.dataDir, CHANNELS_FILE_NAME);
62666
- this.codexHome = options.codexHome || process.env.CODEX_HOME || import_node_path40.default.join(import_node_os12.default.homedir(), ".codex");
63010
+ this.filePath = import_node_path41.default.join(options.dataDir, CHANNELS_FILE_NAME);
63011
+ this.codexHome = options.codexHome || process.env.CODEX_HOME || import_node_path41.default.join(import_node_os13.default.homedir(), ".codex");
63012
+ }
63013
+ /** 存储文件的快照(首次初始化 / 迁移先落盘);返回的函数把它恢复成此刻的样子,通道切换失败时回滚用 */
63014
+ snapshot() {
63015
+ this.readOrCreate();
63016
+ return snapshotFile(this.filePath);
62667
63017
  }
62668
63018
  /** 获取列表与激活通道 ID(Key 经脱敏掩码) */
62669
63019
  list() {
@@ -62758,9 +63108,9 @@ var SubscriptionChannelStore = class {
62758
63108
  return target;
62759
63109
  }
62760
63110
  readOrCreate() {
62761
- if (import_node_fs35.default.existsSync(this.filePath)) {
63111
+ if (import_node_fs36.default.existsSync(this.filePath)) {
62762
63112
  try {
62763
- const raw = JSON.parse(import_node_fs35.default.readFileSync(this.filePath, "utf8"));
63113
+ const raw = JSON.parse(import_node_fs36.default.readFileSync(this.filePath, "utf8"));
62764
63114
  if (raw && Array.isArray(raw.channels)) {
62765
63115
  return {
62766
63116
  activeChannelId: typeof raw.activeChannelId === "string" ? raw.activeChannelId : null,
@@ -62780,19 +63130,21 @@ var SubscriptionChannelStore = class {
62780
63130
  }
62781
63131
  tryMigrateFromCodexConfig() {
62782
63132
  try {
62783
- const configPath = import_node_path40.default.join(this.codexHome, "config.toml");
62784
- if (!import_node_fs35.default.existsSync(configPath)) return null;
62785
- const content = import_node_fs35.default.readFileSync(configPath, "utf8");
62786
- if (!content.includes('model_provider = "cliproxyapi"')) return null;
62787
- const urlMatch = /base_url\s*=\s*["']([^"']+)["']/.exec(content);
62788
- const keyMatch = /args\s*=\s*\[\s*["']([^"']+)["']\s*\]/.exec(content) || /experimental_bearer_token\s*=\s*["']([^"']+)["']/.exec(content);
62789
- if (urlMatch && keyMatch) {
63133
+ const configPath = import_node_path41.default.join(this.codexHome, "config.toml");
63134
+ if (!import_node_fs36.default.existsSync(configPath)) return null;
63135
+ const content = import_node_fs36.default.readFileSync(configPath, "utf8");
63136
+ if (readTomlTable(content, [])?.model_provider !== "cliproxyapi") return null;
63137
+ const provider = readTomlTable(content, ["model_providers", "cliproxyapi"]);
63138
+ if (!provider) return null;
63139
+ const baseUrl = typeof provider.base_url === "string" && provider.base_url ? provider.base_url : null;
63140
+ const key = providerKey(provider, this.codexHome);
63141
+ if (baseUrl && key) {
62790
63142
  const id = "default-pool";
62791
63143
  const channel = {
62792
63144
  id,
62793
63145
  name: "\u9ED8\u8BA4\u56E2\u961F\u53F7\u6C60",
62794
- baseUrl: normalizeEngineBaseUrl(urlMatch[1]),
62795
- apiKey: keyMatch[1],
63146
+ baseUrl: normalizeEngineBaseUrl(baseUrl),
63147
+ apiKey: key,
62796
63148
  remark: "\u4ECE\u672C\u673A\u5DF2\u63A5\u5165\u7684\u53F7\u6C60\u914D\u7F6E\u81EA\u52A8\u8FC1\u79FB",
62797
63149
  createdAt: Date.now(),
62798
63150
  updatedAt: Date.now()
@@ -62807,89 +63159,12 @@ var SubscriptionChannelStore = class {
62807
63159
  return null;
62808
63160
  }
62809
63161
  write(data) {
62810
- const dir = import_node_path40.default.dirname(this.filePath);
62811
- import_node_fs35.default.mkdirSync(dir, { recursive: true });
62812
- const tmp = `${this.filePath}.tmp.${Date.now()}`;
62813
- import_node_fs35.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
62814
- import_node_fs35.default.renameSync(tmp, this.filePath);
63162
+ const dir = import_node_path41.default.dirname(this.filePath);
63163
+ import_node_fs36.default.mkdirSync(dir, { recursive: true });
63164
+ writeFileAtomic(this.filePath, JSON.stringify(data, null, 2) + "\n");
62815
63165
  }
62816
63166
  };
62817
63167
 
62818
- // src/tools/subscription-channels-apply.ts
62819
- var import_node_fs36 = __toESM(require("fs"), 1);
62820
- var import_node_os13 = __toESM(require("os"), 1);
62821
- var import_node_path41 = __toESM(require("path"), 1);
62822
- var TABLE_HEADER = /^\s*\[\[?\s*([A-Za-z0-9_.-]+)\s*\]\]?\s*(?:#.*)?$/;
62823
- var KEY_LINE = /^\s*([A-Za-z0-9_.-]+)\s*=/;
62824
- function stripCodexProvider(text) {
62825
- const out = [];
62826
- let inProviderSection = false;
62827
- for (const line of text.split("\n")) {
62828
- const headerMatch = TABLE_HEADER.exec(line);
62829
- if (headerMatch) {
62830
- const section = headerMatch[1].trim();
62831
- inProviderSection = section === "model_providers" || section.startsWith("model_providers.");
62832
- if (inProviderSection) continue;
62833
- out.push(line);
62834
- continue;
62835
- }
62836
- if (inProviderSection) continue;
62837
- const keyMatch = KEY_LINE.exec(line);
62838
- if (keyMatch) {
62839
- const key = keyMatch[1].trim();
62840
- if (key === "model_provider" || key.startsWith("model_providers.")) {
62841
- continue;
62842
- }
62843
- }
62844
- out.push(line);
62845
- }
62846
- return out.join("\n").trim();
62847
- }
62848
- function applyCodexSubscriptionChannel(opts) {
62849
- const codexHome = opts.codexHome || process.env.CODEX_HOME || import_node_path41.default.join(import_node_os13.default.homedir(), ".codex");
62850
- import_node_fs36.default.mkdirSync(codexHome, { recursive: true });
62851
- const configFile = import_node_path41.default.join(codexHome, "config.toml");
62852
- const original = import_node_fs36.default.existsSync(configFile) ? import_node_fs36.default.readFileSync(configFile, "utf8") : "";
62853
- const rest = stripCodexProvider(original);
62854
- let content;
62855
- if (opts.channel) {
62856
- const ch = opts.channel;
62857
- content = [
62858
- 'model_provider = "cliproxyapi"',
62859
- ...rest ? ["", rest] : [],
62860
- "",
62861
- "[model_providers.cliproxyapi]",
62862
- 'name = "cliproxyapi"',
62863
- `base_url = ${JSON.stringify(ch.baseUrl)}`,
62864
- 'wire_api = "responses"',
62865
- `auth = { command = "echo", args = [${JSON.stringify(ch.apiKey)}] }`,
62866
- ""
62867
- ].join("\n");
62868
- } else {
62869
- content = [
62870
- 'model_provider = "openai"',
62871
- ...rest ? ["", rest] : [],
62872
- ""
62873
- ].join("\n");
62874
- }
62875
- const tmpFile = `${configFile}.tmp.${Date.now()}`;
62876
- import_node_fs36.default.writeFileSync(tmpFile, content, { mode: 384 });
62877
- import_node_fs36.default.renameSync(tmpFile, configFile);
62878
- }
62879
- function applyPiSubscriptionChannel(opts) {
62880
- const agentDir = opts.agentDir || process.env.PI_CODING_AGENT_DIR || import_node_path41.default.join(import_node_os13.default.homedir(), ".pi", "agent");
62881
- if (!import_node_fs36.default.existsSync(agentDir)) return false;
62882
- const configFile = import_node_path41.default.join(agentDir, "cliproxyapi.json");
62883
- if (opts.channel) {
62884
- const data = { baseUrl: opts.channel.baseUrl, apiKey: opts.channel.apiKey };
62885
- const tmp = `${configFile}.tmp.${Date.now()}`;
62886
- import_node_fs36.default.writeFileSync(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
62887
- import_node_fs36.default.renameSync(tmp, configFile);
62888
- return true;
62889
- }
62890
- return false;
62891
- }
62892
-
62893
63168
  // src/deploy/local-probe.ts
62894
63169
  function pickVersion(s2) {
62895
63170
  return /(\d+)\.(\d+)(?:\.(\d+))?/.exec(s2)?.[0];
@@ -62948,8 +63223,8 @@ function refreshPathFromLoginShell() {
62948
63223
  timeout: 3e3,
62949
63224
  stdio: ["ignore", "pipe", "ignore"]
62950
63225
  });
62951
- const path106 = out.trim();
62952
- if (path106) process.env.PATH = path106;
63226
+ const path107 = out.trim();
63227
+ if (path107) process.env.PATH = path107;
62953
63228
  } catch {
62954
63229
  }
62955
63230
  }
@@ -63751,10 +64026,10 @@ function createCloudPersonaBotClient(opts) {
63751
64026
  const f2 = opts.fetchImpl ?? fetch;
63752
64027
  const base = opts.api.replace(/\/+$/, "");
63753
64028
  const route = (personaId2) => `/api/lark-bot/cloud/${encodeURIComponent(personaId2)}`;
63754
- async function request(method, path106, body) {
64029
+ async function request(method, path107, body) {
63755
64030
  const pass = opts.getLoginPass();
63756
64031
  if (!pass) throw new LarkBotCloudError("\u98DE\u4E66\u767B\u5F55\u540E\u624D\u80FD\u7BA1\u7406\u4E91 Persona \u7684 Bot", 401);
63757
- const response = await f2(base + path106, {
64032
+ const response = await f2(base + path107, {
63758
64033
  method,
63759
64034
  headers: { authorization: `Bearer ${pass}`, "content-type": "application/json" },
63760
64035
  ...body ? { body: JSON.stringify(body) } : {},
@@ -63763,7 +64038,7 @@ function createCloudPersonaBotClient(opts) {
63763
64038
  const json = await response.json().catch(() => ({}));
63764
64039
  if (!response.ok) {
63765
64040
  const detail = typeof json.message === "string" ? json.message : `HTTP ${response.status}`;
63766
- throw new LarkBotCloudError(`cloud bot ${method} ${path106}: ${detail}`, response.status);
64041
+ throw new LarkBotCloudError(`cloud bot ${method} ${path107}: ${detail}`, response.status);
63767
64042
  }
63768
64043
  return json;
63769
64044
  }
@@ -65159,15 +65434,28 @@ function createCloudTurnSession(args) {
65159
65434
  const accepted = new Promise((resolve9) => {
65160
65435
  resolveAccepted = resolve9;
65161
65436
  });
65162
- stream.onEvents((events) => sink.pushEvents(events));
65163
- stream.onHistoryGap(() => sink.onHistoryGap?.(false));
65437
+ let turnOpen = true;
65438
+ let gap = false;
65439
+ stream.onEvents((events) => {
65440
+ for (const event of events) {
65441
+ if (event.kind === "turn_end") turnOpen = false;
65442
+ else if (event.kind !== "subagent_progress" && event.kind !== "session_init") turnOpen = true;
65443
+ }
65444
+ sink.pushEvents(events);
65445
+ });
65446
+ stream.onHistoryGap(() => {
65447
+ gap = true;
65448
+ sink.onHistoryGap?.(false);
65449
+ });
65164
65450
  stream.onState((state) => {
65165
65451
  resolveAccepted();
65166
65452
  if (state.status === "inqueue") sink.pushEvents([{ kind: "meta-text", text: "\u5DF2\u6392\u961F\uFF0C\u4E0A\u4E00\u8F6E\u7ED3\u675F\u540E\u6267\u884C" }]);
65167
65453
  if (state.status === "completed" || state.status === "failed" || state.status === "cancelled") {
65168
65454
  live.delete(commandId);
65169
65455
  streams.delete(commandId);
65456
+ if (state.status === "completed" && turnOpen) sink.pushEvents([{ kind: "turn_end", reason: "completed" }]);
65170
65457
  if (state.status === "completed" && state.threadId) sink.pushEvents([{ kind: "session_init", toolSessionId: state.threadId }]);
65458
+ if (state.status === "completed" && gap) sink.onHistoryGap?.(true);
65171
65459
  if (state.status === "failed") sink.pushEvents([{ kind: "error", message: `\u4E91\u4E0A\u6267\u884C\u5931\u8D25\uFF1A${state.errorCode ?? "TURN_FAILED"}` }]);
65172
65460
  if (state.status === "failed" || state.status === "cancelled") sink.pushEvents([{ kind: "turn_end", reason: "interrupted" }]);
65173
65461
  sink.onCloudTurnTerminal?.(commandId);
@@ -65565,6 +65853,7 @@ function drivePiSession(opts) {
65565
65853
  let turnOpen = false;
65566
65854
  const firstByte = createFirstByteClock(opts.now);
65567
65855
  let handshakeFailed = false;
65856
+ let interrupts = 0;
65568
65857
  let exited = false;
65569
65858
  const finish = (code) => {
65570
65859
  if (exited) return;
@@ -65639,12 +65928,20 @@ function drivePiSession(opts) {
65639
65928
  const session = {
65640
65929
  startTurn(text) {
65641
65930
  let opened = false;
65931
+ const askedAt = interrupts;
65642
65932
  void ready.then(async () => {
65643
65933
  if (handshakeFailed) {
65644
65934
  fail("pi session not ready (get_state failed)", false);
65645
65935
  return;
65646
65936
  }
65647
65937
  const input = await piPromptInput(text, { fetchImage: opts.fetchImage });
65938
+ if (interrupts !== askedAt) {
65939
+ if (!turnOpen) {
65940
+ sink.pushEvents([{ kind: "turn_end", reason: "interrupted" }]);
65941
+ opts.onTurnCompleted?.("interrupted");
65942
+ }
65943
+ return;
65944
+ }
65648
65945
  opened = !turnOpen;
65649
65946
  if (opened) {
65650
65947
  turnOpen = true;
@@ -65664,6 +65961,7 @@ function drivePiSession(opts) {
65664
65961
  logger?.warn("pi respondPermission ignored: pi has no approvals", { requestId });
65665
65962
  },
65666
65963
  interrupt() {
65964
+ interrupts++;
65667
65965
  st2.aborted = true;
65668
65966
  void client.request({ type: "abort" }).catch(() => {
65669
65967
  });
@@ -66070,13 +66368,13 @@ function mapSkillsListResponse(res) {
66070
66368
  const r2 = s2 ?? {};
66071
66369
  const name = str4(r2.name);
66072
66370
  if (!name) continue;
66073
- const path106 = str4(r2.path);
66371
+ const path107 = str4(r2.path);
66074
66372
  const description = str4(r2.description);
66075
66373
  const isPlugin = name.includes(":");
66076
66374
  out.push({
66077
66375
  name,
66078
66376
  source: isPlugin ? "plugin" : "project",
66079
- ...path106 ? { path: path106 } : {},
66377
+ ...path107 ? { path: path107 } : {},
66080
66378
  ...description ? { description } : {},
66081
66379
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
66082
66380
  });
@@ -70686,7 +70984,7 @@ var ServerKeyStore = class {
70686
70984
  init_protocol();
70687
70985
 
70688
70986
  // src/handlers/index.ts
70689
- var import_node_path80 = __toESM(require("path"), 1);
70987
+ var import_node_path81 = __toESM(require("path"), 1);
70690
70988
 
70691
70989
  // src/handlers/session.ts
70692
70990
  init_protocol();
@@ -72513,45 +72811,65 @@ function buildEngineHandlers(deps, overrides = {}) {
72513
72811
  }
72514
72812
 
72515
72813
  // src/handlers/channels.ts
72814
+ var import_node_fs65 = __toESM(require("fs"), 1);
72815
+ var import_node_path72 = __toESM(require("path"), 1);
72516
72816
  function buildChannelsHandlers(deps) {
72817
+ let queue = Promise.resolve();
72818
+ const serialized = (fn) => (frame, context) => {
72819
+ const run = queue.then(() => fn(frame, context));
72820
+ queue = run.then(() => {
72821
+ }, () => {
72822
+ });
72823
+ return run;
72824
+ };
72825
+ async function transact(mutate) {
72826
+ const codexHome = resolveCodexHome2(deps.codexHome);
72827
+ const agentDir = resolvePiAgentDir(deps.agentDir);
72828
+ const restoreStore = deps.store.snapshot();
72829
+ const restoreCodex = snapshotFile(import_node_path72.default.join(codexHome, "config.toml"));
72830
+ const restorePi = import_node_fs65.default.existsSync(agentDir) ? snapshotFile(import_node_path72.default.join(agentDir, PI_SUBSCRIPTION_FILE)) : null;
72831
+ let next;
72832
+ try {
72833
+ next = mutate();
72834
+ if (next === void 0) return;
72835
+ applyCodexSubscriptionChannel({ codexHome, channel: next });
72836
+ applyPiSubscriptionChannel({ agentDir, channel: next });
72837
+ if (next) await deps.manager.getCapabilities("codex", { refresh: true });
72838
+ } catch (err) {
72839
+ restoreStore();
72840
+ restoreCodex();
72841
+ restorePi?.();
72842
+ if (next?.id === "default-pool" && err instanceof Error && /HTTP 401/.test(err.message)) {
72843
+ throw new Error("\u9ED8\u8BA4\u53F7\u6C60\u8BA4\u8BC1\u5931\u8D25\uFF08HTTP 401\uFF09\uFF1A\u8BF7\u7F16\u8F91\u300C\u9ED8\u8BA4\u56E2\u961F\u53F7\u6C60\u300D\u5E76\u91CD\u65B0\u586B\u5199\u53F7\u6C60 API Key\uFF0C\u518D\u8BBE\u4E3A\u5F53\u524D\u3002");
72844
+ }
72845
+ throw err;
72846
+ }
72847
+ }
72517
72848
  const get = async () => {
72518
72849
  return { response: deps.store.list() };
72519
72850
  };
72520
- const save = async (frame) => {
72851
+ const save = serialized(async (frame) => {
72521
72852
  const args = parseArgs2(SubscriptionChannelSaveArgsSchema, frame, "subscriptionChannel:save");
72522
- const channel = deps.store.save(args);
72523
- const state = deps.store.list();
72524
- if (state.activeChannelId === channel.id) {
72525
- applyCodexSubscriptionChannel({ codexHome: deps.codexHome, channel });
72526
- applyPiSubscriptionChannel({ agentDir: deps.agentDir, channel });
72527
- await deps.manager.getCapabilities("codex", { refresh: true });
72528
- }
72853
+ await transact(() => {
72854
+ const channel = deps.store.save(args);
72855
+ return deps.store.list().activeChannelId === channel.id ? channel : void 0;
72856
+ });
72529
72857
  return { response: deps.store.list() };
72530
- };
72531
- const del = async (frame) => {
72858
+ });
72859
+ const del = serialized(async (frame) => {
72532
72860
  const args = parseArgs2(SubscriptionChannelDeleteArgsSchema, frame, "subscriptionChannel:delete");
72533
- const wasActive = deps.store.list().activeChannelId === args.id;
72534
- deps.store.delete(args.id);
72535
- if (wasActive) {
72536
- const newActive = deps.store.getActive();
72537
- applyCodexSubscriptionChannel({ codexHome: deps.codexHome, channel: newActive });
72538
- applyPiSubscriptionChannel({ agentDir: deps.agentDir, channel: newActive });
72539
- if (newActive) {
72540
- await deps.manager.getCapabilities("codex", { refresh: true });
72541
- }
72542
- }
72861
+ await transact(() => {
72862
+ const wasActive = deps.store.list().activeChannelId === args.id;
72863
+ deps.store.delete(args.id);
72864
+ return wasActive ? deps.store.getActive() : void 0;
72865
+ });
72543
72866
  return { response: { ok: true } };
72544
- };
72545
- const activate = async (frame) => {
72867
+ });
72868
+ const activate = serialized(async (frame) => {
72546
72869
  const args = parseArgs2(SubscriptionChannelActivateArgsSchema, frame, "subscriptionChannel:activate");
72547
- const channel = deps.store.setActive(args.id);
72548
- applyCodexSubscriptionChannel({ codexHome: deps.codexHome, channel });
72549
- applyPiSubscriptionChannel({ agentDir: deps.agentDir, channel });
72550
- if (channel) {
72551
- await deps.manager.getCapabilities("codex", { refresh: true });
72552
- }
72870
+ await transact(() => deps.store.setActive(args.id));
72553
72871
  return { response: { ok: true } };
72554
- };
72872
+ });
72555
72873
  return {
72556
72874
  "subscriptionChannel:get": get,
72557
72875
  "subscriptionChannel:save": save,
@@ -73520,21 +73838,21 @@ function computeMethodAccess(args) {
73520
73838
  }
73521
73839
 
73522
73840
  // src/version.ts
73523
- var version = "0.2.617".length > 0 ? "0.2.617" : "dev";
73841
+ var version = "0.2.619".length > 0 ? "0.2.619" : "dev";
73524
73842
 
73525
73843
  // src/cli-probe/probe.ts
73526
- var fs83 = __toESM(require("fs"), 1);
73527
- var path90 = __toESM(require("path"), 1);
73844
+ var fs84 = __toESM(require("fs"), 1);
73845
+ var path91 = __toESM(require("path"), 1);
73528
73846
  var PKG_NAME = "@clawos-dev/clawd";
73529
73847
  var BIN_NAME = "clawd";
73530
73848
  var MAX_PARENT_HOPS = 5;
73531
73849
  function probeGlobalCli(pathEnv) {
73532
73850
  if (!pathEnv) return null;
73533
- for (const dir of pathEnv.split(path90.delimiter)) {
73851
+ for (const dir of pathEnv.split(path91.delimiter)) {
73534
73852
  if (!dir) continue;
73535
73853
  let real;
73536
73854
  try {
73537
- real = fs83.realpathSync(path90.join(dir, BIN_NAME));
73855
+ real = fs84.realpathSync(path91.join(dir, BIN_NAME));
73538
73856
  } catch {
73539
73857
  continue;
73540
73858
  }
@@ -73544,15 +73862,15 @@ function probeGlobalCli(pathEnv) {
73544
73862
  return null;
73545
73863
  }
73546
73864
  function readOwnPackageVersion(entryPath) {
73547
- let dir = path90.dirname(entryPath);
73865
+ let dir = path91.dirname(entryPath);
73548
73866
  for (let i2 = 0; i2 < MAX_PARENT_HOPS; i2++) {
73549
73867
  try {
73550
- const raw = fs83.readFileSync(path90.join(dir, "package.json"), "utf8");
73868
+ const raw = fs84.readFileSync(path91.join(dir, "package.json"), "utf8");
73551
73869
  const pkg = JSON.parse(raw);
73552
73870
  if (pkg.name !== PKG_NAME) return null;
73553
73871
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
73554
73872
  } catch {
73555
- const parent = path90.dirname(dir);
73873
+ const parent = path91.dirname(dir);
73556
73874
  if (parent === dir) return null;
73557
73875
  dir = parent;
73558
73876
  }
@@ -73728,7 +74046,7 @@ function buildPersonaHandlers(deps) {
73728
74046
  }
73729
74047
 
73730
74048
  // src/handlers/attachment.ts
73731
- var import_node_path72 = __toESM(require("path"), 1);
74049
+ var import_node_path73 = __toESM(require("path"), 1);
73732
74050
  init_protocol();
73733
74051
  init_protocol();
73734
74052
  function assertGuestAttachmentPath(ctx, absPath, personaRoot, method, usersRoot) {
@@ -73807,12 +74125,12 @@ function buildAttachmentHandlers(deps) {
73807
74125
  `session ${args.sessionId} scope unresolved`
73808
74126
  );
73809
74127
  }
73810
- const cwdAbs = import_node_path72.default.resolve(sessionFile.cwd);
73811
- const candidateAbs = import_node_path72.default.isAbsolute(args.relPath) ? import_node_path72.default.resolve(args.relPath) : import_node_path72.default.resolve(cwdAbs, args.relPath);
74128
+ const cwdAbs = import_node_path73.default.resolve(sessionFile.cwd);
74129
+ const candidateAbs = import_node_path73.default.isAbsolute(args.relPath) ? import_node_path73.default.resolve(args.relPath) : import_node_path73.default.resolve(cwdAbs, args.relPath);
73812
74130
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
73813
74131
  const entries = deps.groupFileStore.list(scope, args.sessionId);
73814
74132
  const entry = entries.find((e) => {
73815
- const storedAbs = import_node_path72.default.isAbsolute(e.relPath) ? import_node_path72.default.resolve(e.relPath) : import_node_path72.default.resolve(cwdAbs, e.relPath);
74133
+ const storedAbs = import_node_path73.default.isAbsolute(e.relPath) ? import_node_path73.default.resolve(e.relPath) : import_node_path73.default.resolve(cwdAbs, e.relPath);
73816
74134
  return storedAbs === candidateAbs && !e.stale;
73817
74135
  });
73818
74136
  if (!entry) {
@@ -73836,7 +74154,7 @@ function buildAttachmentHandlers(deps) {
73836
74154
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
73837
74155
  const f2 = deps.sessionStore.read(sessionId);
73838
74156
  if (!f2) return;
73839
- assertGuestAttachmentPath(ctx, import_node_path72.default.resolve(f2.cwd), deps.personaRoot, method, deps.usersRoot);
74157
+ assertGuestAttachmentPath(ctx, import_node_path73.default.resolve(f2.cwd), deps.personaRoot, method, deps.usersRoot);
73840
74158
  }
73841
74159
  const groupAdd = async (frame, _client, ctx) => {
73842
74160
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -73851,8 +74169,8 @@ function buildAttachmentHandlers(deps) {
73851
74169
  if (!scope) {
73852
74170
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
73853
74171
  }
73854
- const cwdAbs = import_node_path72.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
73855
- const candidateAbs = import_node_path72.default.isAbsolute(args.relPath) ? import_node_path72.default.resolve(args.relPath) : import_node_path72.default.resolve(cwdAbs, args.relPath);
74172
+ const cwdAbs = import_node_path73.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
74173
+ const candidateAbs = import_node_path73.default.isAbsolute(args.relPath) ? import_node_path73.default.resolve(args.relPath) : import_node_path73.default.resolve(cwdAbs, args.relPath);
73856
74174
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
73857
74175
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
73858
74176
  const size = 0;
@@ -73911,19 +74229,19 @@ function buildAttachmentHandlers(deps) {
73911
74229
 
73912
74230
  // src/handlers/extension.ts
73913
74231
  var import_promises15 = __toESM(require("fs/promises"), 1);
73914
- var import_node_path77 = __toESM(require("path"), 1);
74232
+ var import_node_path78 = __toESM(require("path"), 1);
73915
74233
  init_protocol();
73916
74234
 
73917
74235
  // src/extension/bundle-zip.ts
73918
74236
  var import_promises12 = __toESM(require("fs/promises"), 1);
73919
- var import_node_path73 = __toESM(require("path"), 1);
74237
+ var import_node_path74 = __toESM(require("path"), 1);
73920
74238
  var import_node_crypto23 = __toESM(require("crypto"), 1);
73921
74239
  var import_jszip2 = __toESM(require_lib3(), 1);
73922
74240
  async function bundleExtensionDir(dir) {
73923
74241
  const entries = await listFilesSorted(dir);
73924
74242
  const zip = new import_jszip2.default();
73925
74243
  for (const rel of entries) {
73926
- const abs = import_node_path73.default.join(dir, rel);
74244
+ const abs = import_node_path74.default.join(dir, rel);
73927
74245
  const content = await import_promises12.default.readFile(abs);
73928
74246
  zip.file(rel, content, { date: FIXED_DATE });
73929
74247
  }
@@ -73944,7 +74262,7 @@ async function listFilesSorted(rootDir) {
73944
74262
  return out;
73945
74263
  }
73946
74264
  async function walk(absRoot, relPrefix, out) {
73947
- const dirAbs = import_node_path73.default.join(absRoot, relPrefix);
74265
+ const dirAbs = import_node_path74.default.join(absRoot, relPrefix);
73948
74266
  const entries = await import_promises12.default.readdir(dirAbs, { withFileTypes: true });
73949
74267
  for (const e of entries) {
73950
74268
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -73998,25 +74316,25 @@ function computePublishCheck(args) {
73998
74316
 
73999
74317
  // src/extension/install-flow.ts
74000
74318
  var import_promises13 = __toESM(require("fs/promises"), 1);
74001
- var import_node_path75 = __toESM(require("path"), 1);
74319
+ var import_node_path76 = __toESM(require("path"), 1);
74002
74320
  var import_node_os28 = __toESM(require("os"), 1);
74003
74321
  var import_node_crypto24 = __toESM(require("crypto"), 1);
74004
74322
  var import_jszip3 = __toESM(require_lib3(), 1);
74005
74323
 
74006
74324
  // src/extension/paths.ts
74007
74325
  var import_node_os27 = __toESM(require("os"), 1);
74008
- var import_node_path74 = __toESM(require("path"), 1);
74326
+ var import_node_path75 = __toESM(require("path"), 1);
74009
74327
  function clawdHomeRoot(override) {
74010
- return override ?? process.env.CLAWD_HOME ?? import_node_path74.default.join(import_node_os27.default.homedir(), ".clawd");
74328
+ return override ?? process.env.CLAWD_HOME ?? import_node_path75.default.join(import_node_os27.default.homedir(), ".clawd");
74011
74329
  }
74012
74330
  function extensionsRoot(override) {
74013
- return import_node_path74.default.join(clawdHomeRoot(override), "extensions");
74331
+ return import_node_path75.default.join(clawdHomeRoot(override), "extensions");
74014
74332
  }
74015
74333
  function publishedChannelsFile(override) {
74016
- return import_node_path74.default.join(clawdHomeRoot(override), "extensions-published.json");
74334
+ return import_node_path75.default.join(clawdHomeRoot(override), "extensions-published.json");
74017
74335
  }
74018
74336
  function bundleCacheRoot(override) {
74019
- return import_node_path74.default.join(clawdHomeRoot(override), "extension-bundles");
74337
+ return import_node_path75.default.join(clawdHomeRoot(override), "extension-bundles");
74020
74338
  }
74021
74339
 
74022
74340
  // src/extension/install-flow.ts
@@ -74043,7 +74361,7 @@ async function installFromChannel(args, deps) {
74043
74361
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
74044
74362
  }
74045
74363
  for (const name of Object.keys(zip.files)) {
74046
- if (name.includes("..") || name.startsWith("/") || import_node_path75.default.isAbsolute(name)) {
74364
+ if (name.includes("..") || name.startsWith("/") || import_node_path76.default.isAbsolute(name)) {
74047
74365
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
74048
74366
  }
74049
74367
  }
@@ -74075,7 +74393,7 @@ async function installFromChannel(args, deps) {
74075
74393
  );
74076
74394
  }
74077
74395
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
74078
- const destDir = import_node_path75.default.join(deps.extensionsRoot, localExtId);
74396
+ const destDir = import_node_path76.default.join(deps.extensionsRoot, localExtId);
74079
74397
  let destExists = false;
74080
74398
  try {
74081
74399
  await import_promises13.default.access(destDir);
@@ -74089,16 +74407,16 @@ async function installFromChannel(args, deps) {
74089
74407
  );
74090
74408
  }
74091
74409
  const stage = await import_promises13.default.mkdtemp(
74092
- import_node_path75.default.join(import_node_os28.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
74410
+ import_node_path76.default.join(import_node_os28.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
74093
74411
  );
74094
74412
  try {
74095
74413
  for (const [name, entry] of Object.entries(zip.files)) {
74096
- const dest = import_node_path75.default.join(stage, name);
74414
+ const dest = import_node_path76.default.join(stage, name);
74097
74415
  if (entry.dir) {
74098
74416
  await import_promises13.default.mkdir(dest, { recursive: true });
74099
74417
  continue;
74100
74418
  }
74101
- await import_promises13.default.mkdir(import_node_path75.default.dirname(dest), { recursive: true });
74419
+ await import_promises13.default.mkdir(import_node_path76.default.dirname(dest), { recursive: true });
74102
74420
  if (name === "manifest.json") {
74103
74421
  const rewritten = { ...parsed.data, id: localExtId };
74104
74422
  await import_promises13.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -74119,7 +74437,7 @@ async function installFromChannel(args, deps) {
74119
74437
 
74120
74438
  // src/extension/update-flow.ts
74121
74439
  var import_promises14 = __toESM(require("fs/promises"), 1);
74122
- var import_node_path76 = __toESM(require("path"), 1);
74440
+ var import_node_path77 = __toESM(require("path"), 1);
74123
74441
  var import_node_os29 = __toESM(require("os"), 1);
74124
74442
  var import_node_crypto25 = __toESM(require("crypto"), 1);
74125
74443
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -74136,11 +74454,11 @@ async function updateFromChannel(args, deps) {
74136
74454
  channelRef.extId,
74137
74455
  channelRef.ownerPrincipalId
74138
74456
  );
74139
- const liveDir = import_node_path76.default.join(deps.extensionsRoot, localExtId);
74457
+ const liveDir = import_node_path77.default.join(deps.extensionsRoot, localExtId);
74140
74458
  const prevDir = `${liveDir}.prev`;
74141
74459
  let existingVersion;
74142
74460
  try {
74143
- const raw = await import_promises14.default.readFile(import_node_path76.default.join(liveDir, "manifest.json"), "utf8");
74461
+ const raw = await import_promises14.default.readFile(import_node_path77.default.join(liveDir, "manifest.json"), "utf8");
74144
74462
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
74145
74463
  if (!parsed2.success) {
74146
74464
  throw new UpdateError(
@@ -74173,7 +74491,7 @@ async function updateFromChannel(args, deps) {
74173
74491
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
74174
74492
  }
74175
74493
  for (const name of Object.keys(zip.files)) {
74176
- if (name.includes("..") || name.startsWith("/") || import_node_path76.default.isAbsolute(name)) {
74494
+ if (name.includes("..") || name.startsWith("/") || import_node_path77.default.isAbsolute(name)) {
74177
74495
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
74178
74496
  }
74179
74497
  }
@@ -74208,16 +74526,16 @@ async function updateFromChannel(args, deps) {
74208
74526
  await import_promises14.default.rm(prevDir, { recursive: true, force: true });
74209
74527
  await import_promises14.default.rename(liveDir, prevDir);
74210
74528
  const stage = await import_promises14.default.mkdtemp(
74211
- import_node_path76.default.join(import_node_os29.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
74529
+ import_node_path77.default.join(import_node_os29.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
74212
74530
  );
74213
74531
  try {
74214
74532
  for (const [name, entry] of Object.entries(zip.files)) {
74215
- const dest = import_node_path76.default.join(stage, name);
74533
+ const dest = import_node_path77.default.join(stage, name);
74216
74534
  if (entry.dir) {
74217
74535
  await import_promises14.default.mkdir(dest, { recursive: true });
74218
74536
  continue;
74219
74537
  }
74220
- await import_promises14.default.mkdir(import_node_path76.default.dirname(dest), { recursive: true });
74538
+ await import_promises14.default.mkdir(import_node_path77.default.dirname(dest), { recursive: true });
74221
74539
  if (name === "manifest.json") {
74222
74540
  const rewritten = { ...parsed.data, id: localExtId };
74223
74541
  await import_promises14.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -74284,7 +74602,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
74284
74602
  );
74285
74603
  }
74286
74604
  }
74287
- const manifestPath = import_node_path77.default.join(root, extId, "manifest.json");
74605
+ const manifestPath = import_node_path78.default.join(root, extId, "manifest.json");
74288
74606
  const manifest = await readManifest(root, extId);
74289
74607
  const next = { ...manifest, version: newVersion };
74290
74608
  const tmp = `${manifestPath}.tmp`;
@@ -74292,7 +74610,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
74292
74610
  await import_promises15.default.rename(tmp, manifestPath);
74293
74611
  }
74294
74612
  async function readManifest(root, extId) {
74295
- const file = import_node_path77.default.join(root, extId, "manifest.json");
74613
+ const file = import_node_path78.default.join(root, extId, "manifest.json");
74296
74614
  let raw;
74297
74615
  try {
74298
74616
  raw = await import_promises15.default.readFile(file, "utf8");
@@ -74376,7 +74694,7 @@ function buildExtensionHandlers(deps) {
74376
74694
  };
74377
74695
  async function buildSnapshotMeta(extId) {
74378
74696
  const manifest = await readManifest(deps.root, extId);
74379
- const { sha256, buffer } = await bundleExtensionDir(import_node_path77.default.join(deps.root, extId));
74697
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path78.default.join(deps.root, extId));
74380
74698
  return { manifest, contentHash: sha256, buffer };
74381
74699
  }
74382
74700
  const publish = async (frame, _client, ctx) => {
@@ -75204,7 +75522,7 @@ function buildVisitorHandlers(deps) {
75204
75522
 
75205
75523
  // src/extension/registry.ts
75206
75524
  var import_promises17 = __toESM(require("fs/promises"), 1);
75207
- var import_node_path78 = __toESM(require("path"), 1);
75525
+ var import_node_path79 = __toESM(require("path"), 1);
75208
75526
  async function loadAll(root) {
75209
75527
  let entries;
75210
75528
  try {
@@ -75217,13 +75535,13 @@ async function loadAll(root) {
75217
75535
  for (const ent of entries) {
75218
75536
  if (!ent.isDirectory()) continue;
75219
75537
  if (ent.name.startsWith(".")) continue;
75220
- records.push(await loadOne(import_node_path78.default.join(root, ent.name), ent.name));
75538
+ records.push(await loadOne(import_node_path79.default.join(root, ent.name), ent.name));
75221
75539
  }
75222
75540
  records.sort((a2, b3) => a2.extId < b3.extId ? -1 : a2.extId > b3.extId ? 1 : 0);
75223
75541
  return records;
75224
75542
  }
75225
75543
  async function loadOne(dir, dirName) {
75226
- const manifestPath = import_node_path78.default.join(dir, "manifest.json");
75544
+ const manifestPath = import_node_path79.default.join(dir, "manifest.json");
75227
75545
  let raw;
75228
75546
  try {
75229
75547
  raw = await import_promises17.default.readFile(manifestPath, "utf8");
@@ -75268,7 +75586,7 @@ async function loadOne(dir, dirName) {
75268
75586
 
75269
75587
  // src/extension/uninstall.ts
75270
75588
  var import_promises18 = __toESM(require("fs/promises"), 1);
75271
- var import_node_path79 = __toESM(require("path"), 1);
75589
+ var import_node_path80 = __toESM(require("path"), 1);
75272
75590
  var UninstallError = class extends Error {
75273
75591
  constructor(code, message) {
75274
75592
  super(message);
@@ -75277,7 +75595,7 @@ var UninstallError = class extends Error {
75277
75595
  code;
75278
75596
  };
75279
75597
  async function uninstall(deps) {
75280
- const dir = import_node_path79.default.join(deps.root, deps.extId);
75598
+ const dir = import_node_path80.default.join(deps.root, deps.extId);
75281
75599
  try {
75282
75600
  await import_promises18.default.access(dir);
75283
75601
  } catch {
@@ -75495,7 +75813,7 @@ function buildMethodHandlers(deps) {
75495
75813
  broadcast: deps.broadcastToOwners
75496
75814
  }),
75497
75815
  ...buildMasterHandlers({
75498
- authorityTablePath: import_node_path80.default.join(deps.masterDataDir, "master-authority.json")
75816
+ authorityTablePath: import_node_path81.default.join(deps.masterDataDir, "master-authority.json")
75499
75817
  }),
75500
75818
  ...buildTopicHandlers({
75501
75819
  topicStore: deps.topicStore,
@@ -75638,7 +75956,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
75638
75956
 
75639
75957
  // src/extension/runtime.ts
75640
75958
  var import_node_child_process25 = require("child_process");
75641
- var import_node_path81 = __toESM(require("path"), 1);
75959
+ var import_node_path82 = __toESM(require("path"), 1);
75642
75960
  var import_promises19 = require("timers/promises");
75643
75961
 
75644
75962
  // src/extension/port-allocator.ts
@@ -75739,7 +76057,7 @@ var Runtime = class {
75739
76057
  /\$CLAWOS_EXT_PORT/g,
75740
76058
  String(port)
75741
76059
  );
75742
- const dir = import_node_path81.default.join(this.root, extId);
76060
+ const dir = import_node_path82.default.join(this.root, extId);
75743
76061
  const env = {
75744
76062
  ...process.env,
75745
76063
  CLAWOS_EXT_PORT: String(port),
@@ -75851,7 +76169,7 @@ ${handle.stderrTail}`
75851
76169
 
75852
76170
  // src/extension/published-channels.ts
75853
76171
  var import_promises20 = __toESM(require("fs/promises"), 1);
75854
- var import_node_path82 = __toESM(require("path"), 1);
76172
+ var import_node_path83 = __toESM(require("path"), 1);
75855
76173
  init_zod();
75856
76174
  var PublishedChannelsError = class extends Error {
75857
76175
  constructor(code, message) {
@@ -75950,7 +76268,7 @@ var PublishedChannelStore = class {
75950
76268
  )
75951
76269
  };
75952
76270
  const tmp = `${this.filePath}.tmp`;
75953
- await import_promises20.default.mkdir(import_node_path82.default.dirname(this.filePath), { recursive: true });
76271
+ await import_promises20.default.mkdir(import_node_path83.default.dirname(this.filePath), { recursive: true });
75954
76272
  await import_promises20.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
75955
76273
  await import_promises20.default.rename(tmp, this.filePath);
75956
76274
  }
@@ -75958,7 +76276,7 @@ var PublishedChannelStore = class {
75958
76276
 
75959
76277
  // src/extension/bundle-cache.ts
75960
76278
  var import_promises21 = __toESM(require("fs/promises"), 1);
75961
- var import_node_path83 = __toESM(require("path"), 1);
76279
+ var import_node_path84 = __toESM(require("path"), 1);
75962
76280
  var BundleCache = class {
75963
76281
  constructor(rootDir) {
75964
76282
  this.rootDir = rootDir;
@@ -75967,14 +76285,14 @@ var BundleCache = class {
75967
76285
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
75968
76286
  async write(snapshotHash, buffer) {
75969
76287
  await import_promises21.default.mkdir(this.rootDir, { recursive: true });
75970
- const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
76288
+ const file = import_node_path84.default.join(this.rootDir, `${snapshotHash}.zip`);
75971
76289
  const tmp = `${file}.tmp`;
75972
76290
  await import_promises21.default.writeFile(tmp, buffer, { mode: 384 });
75973
76291
  await import_promises21.default.rename(tmp, file);
75974
76292
  }
75975
76293
  /** Returns the bundle bytes, or null when the file doesn't exist. */
75976
76294
  async read(snapshotHash) {
75977
- const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
76295
+ const file = import_node_path84.default.join(this.rootDir, `${snapshotHash}.zip`);
75978
76296
  try {
75979
76297
  return await import_promises21.default.readFile(file);
75980
76298
  } catch (e) {
@@ -75984,7 +76302,7 @@ var BundleCache = class {
75984
76302
  }
75985
76303
  /** Idempotent — missing file is not an error. */
75986
76304
  async delete(snapshotHash) {
75987
- const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
76305
+ const file = import_node_path84.default.join(this.rootDir, `${snapshotHash}.zip`);
75988
76306
  await import_promises21.default.rm(file, { force: true });
75989
76307
  }
75990
76308
  };
@@ -76007,24 +76325,24 @@ async function startDaemon(config) {
76007
76325
  sampling: logShippingCfg.sampling,
76008
76326
  homeDir: import_node_os31.default.homedir()
76009
76327
  });
76010
- const logDir = import_node_path84.default.join(config.dataDir, "log");
76011
- import_node_fs65.default.mkdirSync(logDir, { recursive: true });
76328
+ const logDir = import_node_path85.default.join(config.dataDir, "log");
76329
+ import_node_fs66.default.mkdirSync(logDir, { recursive: true });
76012
76330
  const logger = createLogger({
76013
76331
  level: config.logLevel,
76014
- file: import_node_path84.default.join(logDir, "clawd.log"),
76332
+ file: import_node_path85.default.join(logDir, "clawd.log"),
76015
76333
  logClient
76016
76334
  });
76017
76335
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
76018
76336
  const screenIdleProbeLogger = createFileOnlyLogger({
76019
- file: import_node_path84.default.join(logDir, "screen-idle-probe.log"),
76337
+ file: import_node_path85.default.join(logDir, "screen-idle-probe.log"),
76020
76338
  level: "debug"
76021
76339
  });
76022
76340
  logger.info("screen-idle probe logger enabled", {
76023
- file: import_node_path84.default.join(logDir, "screen-idle-probe.log")
76341
+ file: import_node_path85.default.join(logDir, "screen-idle-probe.log")
76024
76342
  });
76025
76343
  const CAP_TARGETS = [
76026
- import_node_path84.default.join(logDir, "clawd.log"),
76027
- import_node_path84.default.join(logDir, "screen-idle-probe.log")
76344
+ import_node_path85.default.join(logDir, "clawd.log"),
76345
+ import_node_path85.default.join(logDir, "screen-idle-probe.log")
76028
76346
  ];
76029
76347
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
76030
76348
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -76146,11 +76464,11 @@ async function startDaemon(config) {
76146
76464
  const agents = new AgentsScanner();
76147
76465
  const history = new ClaudeHistoryReader();
76148
76466
  let transport = null;
76149
- const personaStore = new PersonaStore(import_node_path84.default.join(config.dataDir, "personas"));
76467
+ const personaStore = new PersonaStore(import_node_path85.default.join(config.dataDir, "personas"));
76150
76468
  const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
76151
76469
  const activeSubscriptionChannel = subscriptionChannelStore.getActive();
76152
76470
  if (activeSubscriptionChannel) applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
76153
- const usersRoot = import_node_path84.default.join(config.dataDir, "users");
76471
+ const usersRoot = import_node_path85.default.join(config.dataDir, "users");
76154
76472
  const defaultsRoot = findDefaultsRoot(logger);
76155
76473
  if (defaultsRoot) {
76156
76474
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -76167,7 +76485,7 @@ async function startDaemon(config) {
76167
76485
  retirePersonaBuilder({ store: personaStore, logger });
76168
76486
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
76169
76487
  const dispatchStore = createDispatchStore({
76170
- filePath: import_node_path84.default.join(config.dataDir, "dispatch.json"),
76488
+ filePath: import_node_path85.default.join(config.dataDir, "dispatch.json"),
76171
76489
  now: () => Date.now(),
76172
76490
  onFlushError: (err) => logger.error("dispatch store flush failed", {
76173
76491
  reason: err instanceof Error ? err.message : String(err)
@@ -76176,7 +76494,7 @@ async function startDaemon(config) {
76176
76494
  await dispatchStore.load();
76177
76495
  dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
76178
76496
  const channelStore = createChannelStore({
76179
- filePath: import_node_path84.default.join(config.dataDir, "channels.json"),
76497
+ filePath: import_node_path85.default.join(config.dataDir, "channels.json"),
76180
76498
  now: () => Date.now(),
76181
76499
  genId: () => `ch-${(0, import_node_crypto27.randomUUID)().slice(0, 8)}`,
76182
76500
  onFlushError: (err) => logger.error("channel store flush failed", {
@@ -76185,7 +76503,7 @@ async function startDaemon(config) {
76185
76503
  });
76186
76504
  await channelStore.load();
76187
76505
  const topicStore = createTopicStore({
76188
- filePath: import_node_path84.default.join(config.dataDir, "topics.json"),
76506
+ filePath: import_node_path85.default.join(config.dataDir, "topics.json"),
76189
76507
  now: () => Date.now(),
76190
76508
  genId: () => `tp-${(0, import_node_crypto27.randomUUID)().slice(0, 8)}`,
76191
76509
  onFlushError: (err) => logger.error("topic store flush failed", {
@@ -76212,12 +76530,12 @@ async function startDaemon(config) {
76212
76530
  });
76213
76531
  }
76214
76532
  });
76215
- const here = typeof __dirname === "string" ? __dirname : import_node_path84.default.dirname((0, import_node_url6.fileURLToPath)(import_meta10.url));
76533
+ const here = typeof __dirname === "string" ? __dirname : import_node_path85.default.dirname((0, import_node_url6.fileURLToPath)(import_meta10.url));
76216
76534
  const mcpConfigs = [];
76217
76535
  const secretsBundleRoot = findSecretsBundleRoot(logger);
76218
- const localSecretsDir = import_node_path84.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
76536
+ const localSecretsDir = import_node_path85.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
76219
76537
  const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
76220
- const githubTokenFile = import_node_path84.default.join(localSecretsDir, GITHUB_TOKEN_FILE);
76538
+ const githubTokenFile = import_node_path85.default.join(localSecretsDir, GITHUB_TOKEN_FILE);
76221
76539
  const githubIdentity = createGithubIdentity({
76222
76540
  resolve: () => resolveGithubAuth({ exec: runCommand, fileToken: () => readEnvFileVar(githubTokenFile, GITHUB_TOKEN_VAR) }),
76223
76541
  store: (token) => storeGithubAuth({
@@ -76255,22 +76573,22 @@ async function startDaemon(config) {
76255
76573
  void githubIdentity.refresh();
76256
76574
  return renderPersonaMcpSecrets({
76257
76575
  personaId: personaId2,
76258
- personaDir: import_node_path84.default.join(config.dataDir, "personas", personaId2),
76576
+ personaDir: import_node_path85.default.join(config.dataDir, "personas", personaId2),
76259
76577
  secrets,
76260
- outDir: import_node_path84.default.join(config.dataDir, "persona-mcp"),
76578
+ outDir: import_node_path85.default.join(config.dataDir, "persona-mcp"),
76261
76579
  logger
76262
76580
  });
76263
76581
  };
76264
76582
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
76265
76583
  const dispatchServerCandidates = [
76266
- import_node_path84.default.join(here, "dispatch", "mcp-server.cjs"),
76584
+ import_node_path85.default.join(here, "dispatch", "mcp-server.cjs"),
76267
76585
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
76268
- import_node_path84.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
76586
+ import_node_path85.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
76269
76587
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
76270
76588
  ];
76271
- const dispatchServerScriptPath = dispatchServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76589
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76272
76590
  if (dispatchServerScriptPath) {
76273
- const dispatchLogPath = import_node_path84.default.join(logDir, "dispatch-mcp-server.log");
76591
+ const dispatchLogPath = import_node_path85.default.join(logDir, "dispatch-mcp-server.log");
76274
76592
  const dispatchCfgPath = writeDispatchMcpConfig({
76275
76593
  dataDir: config.dataDir,
76276
76594
  serverScriptPath: dispatchServerScriptPath,
@@ -76290,12 +76608,12 @@ async function startDaemon(config) {
76290
76608
  });
76291
76609
  }
76292
76610
  const ticketServerCandidates = [
76293
- import_node_path84.default.join(here, "ticket", "mcp-server.cjs"),
76294
- import_node_path84.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
76611
+ import_node_path85.default.join(here, "ticket", "mcp-server.cjs"),
76612
+ import_node_path85.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
76295
76613
  ];
76296
- const ticketServerScriptPath = ticketServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76614
+ const ticketServerScriptPath = ticketServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76297
76615
  if (ticketServerScriptPath) {
76298
- const ticketLogPath = import_node_path84.default.join(logDir, "ticket-mcp-server.log");
76616
+ const ticketLogPath = import_node_path85.default.join(logDir, "ticket-mcp-server.log");
76299
76617
  const ticketCfgPath = writeTicketMcpConfig({
76300
76618
  dataDir: config.dataDir,
76301
76619
  serverScriptPath: ticketServerScriptPath,
@@ -76317,12 +76635,12 @@ async function startDaemon(config) {
76317
76635
  });
76318
76636
  }
76319
76637
  const shiftServerCandidates = [
76320
- import_node_path84.default.join(here, "shift", "mcp-server.cjs"),
76321
- import_node_path84.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
76638
+ import_node_path85.default.join(here, "shift", "mcp-server.cjs"),
76639
+ import_node_path85.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
76322
76640
  ];
76323
- const shiftServerScriptPath = shiftServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76641
+ const shiftServerScriptPath = shiftServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76324
76642
  if (shiftServerScriptPath) {
76325
- const shiftLogPath = import_node_path84.default.join(logDir, "shift-mcp-server.log");
76643
+ const shiftLogPath = import_node_path85.default.join(logDir, "shift-mcp-server.log");
76326
76644
  const shiftCfgPath = await writeShiftMcpConfig({
76327
76645
  dataDir: config.dataDir,
76328
76646
  serverScriptPath: shiftServerScriptPath,
@@ -76343,12 +76661,12 @@ async function startDaemon(config) {
76343
76661
  );
76344
76662
  }
76345
76663
  const inboxServerCandidates = [
76346
- import_node_path84.default.join(here, "inbox", "mcp-server.cjs"),
76347
- import_node_path84.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
76664
+ import_node_path85.default.join(here, "inbox", "mcp-server.cjs"),
76665
+ import_node_path85.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
76348
76666
  ];
76349
- const inboxServerScriptPath = inboxServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76667
+ const inboxServerScriptPath = inboxServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76350
76668
  if (inboxServerScriptPath) {
76351
- const inboxLogPath = import_node_path84.default.join(logDir, "inbox-mcp-server.log");
76669
+ const inboxLogPath = import_node_path85.default.join(logDir, "inbox-mcp-server.log");
76352
76670
  const inboxCfgPath = await writeInboxMcpConfig({
76353
76671
  dataDir: config.dataDir,
76354
76672
  serverScriptPath: inboxServerScriptPath,
@@ -76369,10 +76687,10 @@ async function startDaemon(config) {
76369
76687
  );
76370
76688
  }
76371
76689
  const peerOpsServerCandidates = [
76372
- import_node_path84.default.join(here, "peer-ops", "mcp-server.cjs"),
76373
- import_node_path84.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
76690
+ import_node_path85.default.join(here, "peer-ops", "mcp-server.cjs"),
76691
+ import_node_path85.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
76374
76692
  ];
76375
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76693
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76376
76694
  if (peerOpsServerScriptPath) {
76377
76695
  const peerOpsCfgPath = writePeerOpsMcpConfig({
76378
76696
  dataDir: config.dataDir,
@@ -76392,12 +76710,12 @@ async function startDaemon(config) {
76392
76710
  );
76393
76711
  }
76394
76712
  const rpcToolServerCandidates = [
76395
- import_node_path84.default.join(here, "rpc-tool", "mcp-server.cjs"),
76396
- import_node_path84.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
76713
+ import_node_path85.default.join(here, "rpc-tool", "mcp-server.cjs"),
76714
+ import_node_path85.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
76397
76715
  ];
76398
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76716
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76399
76717
  if (rpcToolServerScriptPath) {
76400
- const rpcToolLogPath = import_node_path84.default.join(logDir, "rpc-tool-mcp-server.log");
76718
+ const rpcToolLogPath = import_node_path85.default.join(logDir, "rpc-tool-mcp-server.log");
76401
76719
  const rpcToolCfgPath = writeRpcToolMcpConfig({
76402
76720
  dataDir: config.dataDir,
76403
76721
  serverScriptPath: rpcToolServerScriptPath,
@@ -76418,7 +76736,7 @@ async function startDaemon(config) {
76418
76736
  );
76419
76737
  }
76420
76738
  const shiftStore = createShiftStore({
76421
- filePath: import_node_path84.default.join(config.dataDir, "shift.json"),
76739
+ filePath: import_node_path85.default.join(config.dataDir, "shift.json"),
76422
76740
  ownerIdProvider: () => ownerPrincipalId,
76423
76741
  now: () => Date.now()
76424
76742
  });
@@ -76440,7 +76758,7 @@ async function startDaemon(config) {
76440
76758
  getAdapter,
76441
76759
  historyReader: history,
76442
76760
  dataDir: config.dataDir,
76443
- personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
76761
+ personaRoot: import_node_path85.default.join(config.dataDir, "personas"),
76444
76762
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
76445
76763
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
76446
76764
  getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
@@ -76501,10 +76819,10 @@ async function startDaemon(config) {
76501
76819
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
76502
76820
  attachmentGroup: {
76503
76821
  onFileEdit: (input) => {
76504
- const absPath = import_node_path84.default.isAbsolute(input.relPath) ? input.relPath : import_node_path84.default.join(input.cwd, input.relPath);
76822
+ const absPath = import_node_path85.default.isAbsolute(input.relPath) ? input.relPath : import_node_path85.default.join(input.cwd, input.relPath);
76505
76823
  let size = 0;
76506
76824
  try {
76507
- size = import_node_fs65.default.statSync(absPath).size;
76825
+ size = import_node_fs66.default.statSync(absPath).size;
76508
76826
  } catch (err) {
76509
76827
  logger.warn("attachment.onFileEdit stat failed", {
76510
76828
  sessionId: input.sessionId,
@@ -76545,9 +76863,9 @@ async function startDaemon(config) {
76545
76863
  logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
76546
76864
  }
76547
76865
  const projectsStore = new ProjectsStore({
76548
- file: import_node_path84.default.join(config.dataDir, "projects.json"),
76866
+ file: import_node_path85.default.join(config.dataDir, "projects.json"),
76549
76867
  clawdDir: config.dataDir,
76550
- codexStateFile: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex", ".codex-global-state.json"),
76868
+ codexStateFile: import_node_path85.default.join(import_node_os31.default.homedir(), ".codex", ".codex-global-state.json"),
76551
76869
  logger
76552
76870
  });
76553
76871
  const observer = new SessionObserver({
@@ -76622,13 +76940,13 @@ async function startDaemon(config) {
76622
76940
  runner?.confirmCloudCancelled();
76623
76941
  });
76624
76942
  registerAdapter("claude", claudeAdapter);
76625
- const codexIsolatedHome = import_node_path84.default.join(config.dataDir, "codex-home");
76943
+ const codexIsolatedHome = import_node_path85.default.join(config.dataDir, "codex-home");
76626
76944
  try {
76627
- import_node_fs65.default.mkdirSync(codexIsolatedHome, { recursive: true });
76945
+ import_node_fs66.default.mkdirSync(codexIsolatedHome, { recursive: true });
76628
76946
  for (const f2 of ["auth.json", "config.toml"]) {
76629
- const link = import_node_path84.default.join(codexIsolatedHome, f2);
76630
- const target = import_node_path84.default.join(import_node_os31.default.homedir(), ".codex", f2);
76631
- if (!import_node_fs65.default.existsSync(link) && import_node_fs65.default.existsSync(target)) import_node_fs65.default.symlinkSync(target, link);
76947
+ const link = import_node_path85.default.join(codexIsolatedHome, f2);
76948
+ const target = import_node_path85.default.join(import_node_os31.default.homedir(), ".codex", f2);
76949
+ if (!import_node_fs66.default.existsSync(link) && import_node_fs66.default.existsSync(target)) import_node_fs66.default.symlinkSync(target, link);
76632
76950
  }
76633
76951
  } catch (err) {
76634
76952
  logger.warn("codex isolated home setup failed", { err: String(err) });
@@ -76639,17 +76957,17 @@ async function startDaemon(config) {
76639
76957
  logger,
76640
76958
  historyReader: new CodexHistoryReader({
76641
76959
  roots: codexRolloutRoots(config.dataDir),
76642
- sharedHome: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex"),
76960
+ sharedHome: import_node_path85.default.join(import_node_os31.default.homedir(), ".codex"),
76643
76961
  logger
76644
76962
  }),
76645
76963
  // projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
76646
76964
  codexHomeFor: (cwd) => resolveCodexHome({
76647
76965
  cwd,
76648
- personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
76966
+ personaRoot: import_node_path85.default.join(config.dataDir, "personas"),
76649
76967
  // 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
76650
76968
  // Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
76651
76969
  projectPaths: projectsStore.listMerged().map((x2) => x2.path),
76652
- sharedHome: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex"),
76970
+ sharedHome: import_node_path85.default.join(import_node_os31.default.homedir(), ".codex"),
76653
76971
  isolatedHome: codexIsolatedHome
76654
76972
  }),
76655
76973
  codexHomeForThread: (threadId) => locateCodexThread(codexRolloutRoots(config.dataDir), threadId)?.home,
@@ -76675,10 +76993,10 @@ async function startDaemon(config) {
76675
76993
  );
76676
76994
  registerAdapter(PI_CLOUD_TOOL_ID, new CloudPiAdapter({ client: cloudGateway, history: cloudHistorySource, logger }));
76677
76995
  const piMcpBridgeCandidates = [
76678
- import_node_path84.default.join(here, "pi-mcp-bridge", "extension.cjs"),
76679
- import_node_path84.default.join(here, "..", "dist", "pi-mcp-bridge", "extension.cjs")
76996
+ import_node_path85.default.join(here, "pi-mcp-bridge", "extension.cjs"),
76997
+ import_node_path85.default.join(here, "..", "dist", "pi-mcp-bridge", "extension.cjs")
76680
76998
  ];
76681
- const piMcpBridgePath = piMcpBridgeCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
76999
+ const piMcpBridgePath = piMcpBridgeCandidates.find((p3) => import_node_fs66.default.existsSync(p3));
76682
77000
  if (piMcpBridgePath) {
76683
77001
  logger.info("pi-mcp-bridge extension resolved", { path: piMcpBridgePath });
76684
77002
  } else {
@@ -76984,11 +77302,11 @@ async function startDaemon(config) {
76984
77302
  // 'persona/<pid>/owner',default 走 'default'。
76985
77303
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
76986
77304
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
76987
- personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
77305
+ personaRoot: import_node_path85.default.join(config.dataDir, "personas"),
76988
77306
  usersRoot
76989
77307
  },
76990
77308
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
76991
- personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
77309
+ personaRoot: import_node_path85.default.join(config.dataDir, "personas"),
76992
77310
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
76993
77311
  usersRoot,
76994
77312
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -77294,7 +77612,7 @@ async function startDaemon(config) {
77294
77612
  });
77295
77613
  shiftScheduler.start();
77296
77614
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
77297
- const larkBotStore = createLarkBotBindingStore(import_node_path84.default.join(config.dataDir, "personas"));
77615
+ const larkBotStore = createLarkBotBindingStore(import_node_path85.default.join(config.dataDir, "personas"));
77298
77616
  const larkBotCloud = createLarkBotCloudClient({
77299
77617
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
77300
77618
  getLoginPass: () => ownerIdentityStore.read()?.loginPass ?? null
@@ -77306,7 +77624,7 @@ async function startDaemon(config) {
77306
77624
  store: larkBotStore,
77307
77625
  fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
77308
77626
  // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
77309
- mediaRootFor: (chatId) => import_node_path84.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
77627
+ mediaRootFor: (chatId) => import_node_path85.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
77310
77628
  isShuttingDown: () => larkDraining,
77311
77629
  logger: {
77312
77630
  warn: (msg) => logger.warn(msg),
@@ -77619,8 +77937,8 @@ async function startDaemon(config) {
77619
77937
  const lines = [
77620
77938
  `Tunnel: ${r2.url}`,
77621
77939
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
77622
- `Frpc config: ${import_node_path84.default.join(config.dataDir, "frpc.toml")}`,
77623
- `Frpc log: ${import_node_path84.default.join(logDir, "frpc.log")}`
77940
+ `Frpc config: ${import_node_path85.default.join(config.dataDir, "frpc.toml")}`,
77941
+ `Frpc log: ${import_node_path85.default.join(logDir, "frpc.log")}`
77624
77942
  ];
77625
77943
  const width2 = Math.max(...lines.map((l2) => l2.length));
77626
77944
  const bar = "\u2550".repeat(width2 + 4);
@@ -77633,8 +77951,8 @@ ${bar}
77633
77951
 
77634
77952
  `);
77635
77953
  try {
77636
- const connectPath = import_node_path84.default.join(config.dataDir, "connect.txt");
77637
- import_node_fs65.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
77954
+ const connectPath = import_node_path85.default.join(config.dataDir, "connect.txt");
77955
+ import_node_fs66.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
77638
77956
  } catch {
77639
77957
  }
77640
77958
  } catch (err) {
@@ -77733,9 +78051,9 @@ ${bar}
77733
78051
  };
77734
78052
  }
77735
78053
  function migrateDropPersonsDir(dataDir) {
77736
- const dir = import_node_path84.default.join(dataDir, "persons");
78054
+ const dir = import_node_path85.default.join(dataDir, "persons");
77737
78055
  try {
77738
- import_node_fs65.default.rmSync(dir, { recursive: true, force: true });
78056
+ import_node_fs66.default.rmSync(dir, { recursive: true, force: true });
77739
78057
  } catch {
77740
78058
  }
77741
78059
  }