@clawos-dev/clawd 0.2.439 → 0.2.441

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: path89, errorMaps, issueData } = params;
454
- const fullPath = [...path89, ...issueData.path || []];
453
+ const { data, path: path91, errorMaps, issueData } = params;
454
+ const fullPath = [...path91, ...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, path89, key) {
765
+ constructor(parent, value, path91, key) {
766
766
  this._cachedPath = [];
767
767
  this.parent = parent;
768
768
  this.data = value;
769
- this._path = path89;
769
+ this._path = path91;
770
770
  this._key = key;
771
771
  }
772
772
  get path() {
@@ -7089,10 +7089,9 @@ var init_persona_schemas = __esm({
7089
7089
  writableRoots: external_exports.array(external_exports.string()).optional(),
7090
7090
  // 禁读 glob(相对 workspace root 或绝对),如 ".secrets/**"、"**/*.env"。
7091
7091
  denyRead: external_exports.array(external_exports.string()).optional(),
7092
- // true → 网络全放(*);false → 断网。**缺省等于联网**:daemon 写入的默认值是 network:true
7093
- // (对齐 claude guest 一贯的域名全放,见 spec 2026-09-01-codex-guest-network §1.3),
7094
- // 且 manager / UI 读到 undefined 时都回落 true —— 两侧必须同向,否则出现
7095
- // 「卡片显示开、实际断网」的幽灵态。
7092
+ // true → 网络全放(*);false / 缺省 → 断网(fail-closed)。**「新建默认联网」不靠这里的缺省**,
7093
+ // 靠 persona 创建时就把 CODEX_SANDBOX_DEFAULT 物化进文件(见 PersonaManager.create)——
7094
+ // 缺省只在文件损坏这种异常路径上出现,那时断网是更安全的一侧。
7096
7095
  network: external_exports.boolean().optional()
7097
7096
  }).strict();
7098
7097
  PersonaSandboxSettingsSchema = external_exports.object({
@@ -7285,7 +7284,7 @@ var init_principal = __esm({
7285
7284
  });
7286
7285
 
7287
7286
  // ../protocol/src/schemas.ts
7288
- var SessionStatusSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, SelectOptionSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, TURN_END_REASONS, ParsedEventSchema, SessionCreateArgs, ProjectEntry, ProjectPatchArgs, ProjectRevealArgs, ProjectCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, QueuedMessage, SessionSendArgs, SessionDequeueArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, SessionArchiveArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
7287
+ var SessionStatusSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, SelectOptionSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, TURN_END_REASONS, ParsedEventSchema, SessionCreateArgs, ProjectEntry, ProjectPatchArgs, ProjectRevealArgs, ProjectCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, QueuedMessage, SessionSendArgs, SessionDequeueArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, SessionArchiveArgs, SessionSearchContentArgs, SessionSearchMatchSchema, SessionSearchContentResponseSchema, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
7289
7288
  var init_schemas = __esm({
7290
7289
  "../protocol/src/schemas.ts"() {
7291
7290
  "use strict";
@@ -8029,6 +8028,22 @@ var init_schemas = __esm({
8029
8028
  sessionId: external_exports.string().min(1),
8030
8029
  archived: external_exports.boolean()
8031
8030
  });
8031
+ SessionSearchContentArgs = external_exports.object({
8032
+ query: external_exports.string().min(1),
8033
+ // 扫描顺序 = 数组顺序(调用方按 updatedAt 倒序传),攒够 limit 即停
8034
+ sessionIds: external_exports.array(external_exports.string().min(1)),
8035
+ limit: external_exports.number().int().positive().max(50).optional()
8036
+ });
8037
+ SessionSearchMatchSchema = external_exports.object({
8038
+ sessionId: external_exports.string().min(1),
8039
+ // 命中处上下文片段,已单行化。**不回高亮 offset**:调用方手里有 query,
8040
+ // 自己在 snippet 里 indexOf 就能高亮,wire 上少一组坐标少一处漂
8041
+ snippet: external_exports.string()
8042
+ });
8043
+ SessionSearchContentResponseSchema = external_exports.object({
8044
+ type: external_exports.literal("session:searchContent"),
8045
+ matches: external_exports.array(SessionSearchMatchSchema)
8046
+ });
8032
8047
  PeerSessionUpsertArgs = SessionFileSchema;
8033
8048
  PeerSessionUpsertResponseSchema = external_exports.object({
8034
8049
  type: external_exports.literal("peerSession:upsert:ok")
@@ -8515,6 +8530,10 @@ var init_methods = __esm({
8515
8530
  summary: "\u5F52\u6863 / \u53D6\u6D88\u5F52\u6863\u4F1A\u8BDD\uFF08\u5F52\u6863 = \u5168\u5C40\u6536\u7EB3\u6001\uFF1A\u9000\u51FA sidebar\u3001\u539F\u5B50\u6E05 pinnedAt\uFF09",
8516
8531
  args: SessionArchiveArgs
8517
8532
  },
8533
+ "session:searchContent": {
8534
+ summary: '\u5728 sessionIds \u7ED9\u5B9A\u7684\u8FD9\u6279\u4F1A\u8BDD\u91CC\u641C\u6B63\u6587\u5185\u5BB9\uFF08user / assistant \u7684\u6587\u672C\u6D88\u606F\uFF1B\u5DE5\u5177\u5165\u53C2\u51FA\u53C2\u4E0E\u7CFB\u7EDF\u6CE8\u5165\u4E0D\u7B97\uFF09\uFF0C\u547D\u4E2D\u8FD4\u56DE\u4E0A\u4E0B\u6587\u7247\u6BB5\u3002**\u626B\u63CF\u987A\u5E8F = sessionIds \u6570\u7EC4\u987A\u5E8F\uFF0C\u6512\u591F limit \u5C31\u505C**\uFF08\u8C03\u7528\u65B9\u6309 updatedAt \u5012\u5E8F\u4F20 \u2192 \u65E9\u505C\u7ED3\u679C\u5373"\u6700\u8FD1 N \u6761"\uFF09\uFF1Blimit \u7F3A\u7701 9\u3002\u5019\u9009\u7531\u8C03\u7528\u65B9\u7ED9\u5B9A\uFF0Cdaemon \u4E0D\u81EA\u5DF1\u6309 archivedAt \u7B5B\uFF08\u8BDD\u9898\u5F52\u6863\u53EA\u6253\u5728 Master \u4F1A\u8BDD\u4E0A\uFF0Cworker \u4F1A\u8BDD\u6CA1\u6807\u8BB0\uFF09\uFF1B\u65E0\u6743\u8BFB / \u5B9A\u4F4D\u4E0D\u5230 transcript / transcript \u5DF2\u88AB CC \u6E05\u7406\u7684\u4F1A\u8BDD\u9759\u9ED8\u8DF3\u8FC7\uFF0C\u4E0D\u62A5\u9519',
8535
+ args: SessionSearchContentArgs
8536
+ },
8518
8537
  "session:markRead": {
8519
8538
  summary: "\u6E05\u6389\u4F1A\u8BDD\u7684\u5171\u4EAB\u672A\u8BFB\u6807\u8BB0\u5E76\u5E7F\u64AD session:info\uFF1B\u5E42\u7B49",
8520
8539
  args: SessionIdArgs
@@ -9574,8 +9593,8 @@ var require_req = __commonJS({
9574
9593
  if (req.originalUrl) {
9575
9594
  _req.url = req.originalUrl;
9576
9595
  } else {
9577
- const path89 = req.path;
9578
- _req.url = typeof path89 === "string" ? path89 : req.url ? req.url.path || req.url : void 0;
9596
+ const path91 = req.path;
9597
+ _req.url = typeof path91 === "string" ? path91 : req.url ? req.url.path || req.url : void 0;
9579
9598
  }
9580
9599
  if (req.query) {
9581
9600
  _req.query = req.query;
@@ -9740,14 +9759,14 @@ var require_redact = __commonJS({
9740
9759
  }
9741
9760
  return obj;
9742
9761
  }
9743
- function parsePath(path89) {
9762
+ function parsePath(path91) {
9744
9763
  const parts = [];
9745
9764
  let current = "";
9746
9765
  let inBrackets = false;
9747
9766
  let inQuotes = false;
9748
9767
  let quoteChar = "";
9749
- for (let i = 0; i < path89.length; i++) {
9750
- const char = path89[i];
9768
+ for (let i = 0; i < path91.length; i++) {
9769
+ const char = path91[i];
9751
9770
  if (!inBrackets && char === ".") {
9752
9771
  if (current) {
9753
9772
  parts.push(current);
@@ -9878,10 +9897,10 @@ var require_redact = __commonJS({
9878
9897
  return current;
9879
9898
  }
9880
9899
  function redactPaths(obj, paths, censor, remove = false) {
9881
- for (const path89 of paths) {
9882
- const parts = parsePath(path89);
9900
+ for (const path91 of paths) {
9901
+ const parts = parsePath(path91);
9883
9902
  if (parts.includes("*")) {
9884
- redactWildcardPath(obj, parts, censor, path89, remove);
9903
+ redactWildcardPath(obj, parts, censor, path91, remove);
9885
9904
  } else {
9886
9905
  if (remove) {
9887
9906
  removeKey(obj, parts);
@@ -9966,8 +9985,8 @@ var require_redact = __commonJS({
9966
9985
  }
9967
9986
  } else {
9968
9987
  if (afterWildcard.includes("*")) {
9969
- const wrappedCensor = typeof censor === "function" ? (value, path89) => {
9970
- const fullPath = [...pathArray.slice(0, pathLength), ...path89];
9988
+ const wrappedCensor = typeof censor === "function" ? (value, path91) => {
9989
+ const fullPath = [...pathArray.slice(0, pathLength), ...path91];
9971
9990
  return censor(value, fullPath);
9972
9991
  } : censor;
9973
9992
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -10002,8 +10021,8 @@ var require_redact = __commonJS({
10002
10021
  return null;
10003
10022
  }
10004
10023
  const pathStructure = /* @__PURE__ */ new Map();
10005
- for (const path89 of pathsToClone) {
10006
- const parts = parsePath(path89);
10024
+ for (const path91 of pathsToClone) {
10025
+ const parts = parsePath(path91);
10007
10026
  let current = pathStructure;
10008
10027
  for (let i = 0; i < parts.length; i++) {
10009
10028
  const part = parts[i];
@@ -10055,24 +10074,24 @@ var require_redact = __commonJS({
10055
10074
  }
10056
10075
  return cloneSelectively(obj, pathStructure);
10057
10076
  }
10058
- function validatePath(path89) {
10059
- if (typeof path89 !== "string") {
10077
+ function validatePath(path91) {
10078
+ if (typeof path91 !== "string") {
10060
10079
  throw new Error("Paths must be (non-empty) strings");
10061
10080
  }
10062
- if (path89 === "") {
10081
+ if (path91 === "") {
10063
10082
  throw new Error("Invalid redaction path ()");
10064
10083
  }
10065
- if (path89.includes("..")) {
10066
- throw new Error(`Invalid redaction path (${path89})`);
10084
+ if (path91.includes("..")) {
10085
+ throw new Error(`Invalid redaction path (${path91})`);
10067
10086
  }
10068
- if (path89.includes(",")) {
10069
- throw new Error(`Invalid redaction path (${path89})`);
10087
+ if (path91.includes(",")) {
10088
+ throw new Error(`Invalid redaction path (${path91})`);
10070
10089
  }
10071
10090
  let bracketCount = 0;
10072
10091
  let inQuotes = false;
10073
10092
  let quoteChar = "";
10074
- for (let i = 0; i < path89.length; i++) {
10075
- const char = path89[i];
10093
+ for (let i = 0; i < path91.length; i++) {
10094
+ const char = path91[i];
10076
10095
  if ((char === '"' || char === "'") && bracketCount > 0) {
10077
10096
  if (!inQuotes) {
10078
10097
  inQuotes = true;
@@ -10086,20 +10105,20 @@ var require_redact = __commonJS({
10086
10105
  } else if (char === "]" && !inQuotes) {
10087
10106
  bracketCount--;
10088
10107
  if (bracketCount < 0) {
10089
- throw new Error(`Invalid redaction path (${path89})`);
10108
+ throw new Error(`Invalid redaction path (${path91})`);
10090
10109
  }
10091
10110
  }
10092
10111
  }
10093
10112
  if (bracketCount !== 0) {
10094
- throw new Error(`Invalid redaction path (${path89})`);
10113
+ throw new Error(`Invalid redaction path (${path91})`);
10095
10114
  }
10096
10115
  }
10097
10116
  function validatePaths(paths) {
10098
10117
  if (!Array.isArray(paths)) {
10099
10118
  throw new TypeError("paths must be an array");
10100
10119
  }
10101
- for (const path89 of paths) {
10102
- validatePath(path89);
10120
+ for (const path91 of paths) {
10121
+ validatePath(path91);
10103
10122
  }
10104
10123
  }
10105
10124
  function slowRedact(options = {}) {
@@ -10267,8 +10286,8 @@ var require_redaction = __commonJS({
10267
10286
  if (shape[k2] === null) {
10268
10287
  o[k2] = (value) => topCensor(value, [k2]);
10269
10288
  } else {
10270
- const wrappedCensor = typeof censor === "function" ? (value, path89) => {
10271
- return censor(value, [k2, ...path89]);
10289
+ const wrappedCensor = typeof censor === "function" ? (value, path91) => {
10290
+ return censor(value, [k2, ...path91]);
10272
10291
  } : censor;
10273
10292
  o[k2] = Redact({
10274
10293
  paths: shape[k2],
@@ -10486,10 +10505,10 @@ var require_atomic_sleep = __commonJS({
10486
10505
  var require_sonic_boom = __commonJS({
10487
10506
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
10488
10507
  "use strict";
10489
- var fs79 = require("fs");
10508
+ var fs80 = require("fs");
10490
10509
  var EventEmitter3 = require("events");
10491
10510
  var inherits = require("util").inherits;
10492
- var path89 = require("path");
10511
+ var path91 = require("path");
10493
10512
  var sleep2 = require_atomic_sleep();
10494
10513
  var assert = require("assert");
10495
10514
  var BUSY_WRITE_TIMEOUT = 100;
@@ -10543,20 +10562,20 @@ var require_sonic_boom = __commonJS({
10543
10562
  const mode = sonic.mode;
10544
10563
  if (sonic.sync) {
10545
10564
  try {
10546
- if (sonic.mkdir) fs79.mkdirSync(path89.dirname(file), { recursive: true });
10547
- const fd = fs79.openSync(file, flags, mode);
10565
+ if (sonic.mkdir) fs80.mkdirSync(path91.dirname(file), { recursive: true });
10566
+ const fd = fs80.openSync(file, flags, mode);
10548
10567
  fileOpened(null, fd);
10549
10568
  } catch (err) {
10550
10569
  fileOpened(err);
10551
10570
  throw err;
10552
10571
  }
10553
10572
  } else if (sonic.mkdir) {
10554
- fs79.mkdir(path89.dirname(file), { recursive: true }, (err) => {
10573
+ fs80.mkdir(path91.dirname(file), { recursive: true }, (err) => {
10555
10574
  if (err) return fileOpened(err);
10556
- fs79.open(file, flags, mode, fileOpened);
10575
+ fs80.open(file, flags, mode, fileOpened);
10557
10576
  });
10558
10577
  } else {
10559
- fs79.open(file, flags, mode, fileOpened);
10578
+ fs80.open(file, flags, mode, fileOpened);
10560
10579
  }
10561
10580
  }
10562
10581
  function SonicBoom(opts) {
@@ -10597,8 +10616,8 @@ var require_sonic_boom = __commonJS({
10597
10616
  this.flush = flushBuffer;
10598
10617
  this.flushSync = flushBufferSync;
10599
10618
  this._actualWrite = actualWriteBuffer;
10600
- fsWriteSync = () => fs79.writeSync(this.fd, this._writingBuf);
10601
- fsWrite = () => fs79.write(this.fd, this._writingBuf, this.release);
10619
+ fsWriteSync = () => fs80.writeSync(this.fd, this._writingBuf);
10620
+ fsWrite = () => fs80.write(this.fd, this._writingBuf, this.release);
10602
10621
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
10603
10622
  this._writingBuf = "";
10604
10623
  this.write = write;
@@ -10607,15 +10626,15 @@ var require_sonic_boom = __commonJS({
10607
10626
  this._actualWrite = actualWrite;
10608
10627
  fsWriteSync = () => {
10609
10628
  if (Buffer.isBuffer(this._writingBuf)) {
10610
- return fs79.writeSync(this.fd, this._writingBuf);
10629
+ return fs80.writeSync(this.fd, this._writingBuf);
10611
10630
  }
10612
- return fs79.writeSync(this.fd, this._writingBuf, "utf8");
10631
+ return fs80.writeSync(this.fd, this._writingBuf, "utf8");
10613
10632
  };
10614
10633
  fsWrite = () => {
10615
10634
  if (Buffer.isBuffer(this._writingBuf)) {
10616
- return fs79.write(this.fd, this._writingBuf, this.release);
10635
+ return fs80.write(this.fd, this._writingBuf, this.release);
10617
10636
  }
10618
- return fs79.write(this.fd, this._writingBuf, "utf8", this.release);
10637
+ return fs80.write(this.fd, this._writingBuf, "utf8", this.release);
10619
10638
  };
10620
10639
  } else {
10621
10640
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -10672,7 +10691,7 @@ var require_sonic_boom = __commonJS({
10672
10691
  }
10673
10692
  }
10674
10693
  if (this._fsync) {
10675
- fs79.fsyncSync(this.fd);
10694
+ fs80.fsyncSync(this.fd);
10676
10695
  }
10677
10696
  const len = this._len;
10678
10697
  if (this._reopening) {
@@ -10786,7 +10805,7 @@ var require_sonic_boom = __commonJS({
10786
10805
  const onDrain = () => {
10787
10806
  if (!this._fsync) {
10788
10807
  try {
10789
- fs79.fsync(this.fd, (err) => {
10808
+ fs80.fsync(this.fd, (err) => {
10790
10809
  this._flushPending = false;
10791
10810
  cb(err);
10792
10811
  });
@@ -10888,7 +10907,7 @@ var require_sonic_boom = __commonJS({
10888
10907
  const fd = this.fd;
10889
10908
  this.once("ready", () => {
10890
10909
  if (fd !== this.fd) {
10891
- fs79.close(fd, (err) => {
10910
+ fs80.close(fd, (err) => {
10892
10911
  if (err) {
10893
10912
  return this.emit("error", err);
10894
10913
  }
@@ -10937,7 +10956,7 @@ var require_sonic_boom = __commonJS({
10937
10956
  buf = this._bufs[0];
10938
10957
  }
10939
10958
  try {
10940
- const n = Buffer.isBuffer(buf) ? fs79.writeSync(this.fd, buf) : fs79.writeSync(this.fd, buf, "utf8");
10959
+ const n = Buffer.isBuffer(buf) ? fs80.writeSync(this.fd, buf) : fs80.writeSync(this.fd, buf, "utf8");
10941
10960
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
10942
10961
  buf = releasedBufObj.writingBuf;
10943
10962
  this._len = releasedBufObj.len;
@@ -10953,7 +10972,7 @@ var require_sonic_boom = __commonJS({
10953
10972
  }
10954
10973
  }
10955
10974
  try {
10956
- fs79.fsyncSync(this.fd);
10975
+ fs80.fsyncSync(this.fd);
10957
10976
  } catch {
10958
10977
  }
10959
10978
  }
@@ -10974,7 +10993,7 @@ var require_sonic_boom = __commonJS({
10974
10993
  buf = mergeBuf(this._bufs[0], this._lens[0]);
10975
10994
  }
10976
10995
  try {
10977
- const n = fs79.writeSync(this.fd, buf);
10996
+ const n = fs80.writeSync(this.fd, buf);
10978
10997
  buf = buf.subarray(n);
10979
10998
  this._len = Math.max(this._len - n, 0);
10980
10999
  if (buf.length <= 0) {
@@ -11002,13 +11021,13 @@ var require_sonic_boom = __commonJS({
11002
11021
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
11003
11022
  if (this.sync) {
11004
11023
  try {
11005
- const written = Buffer.isBuffer(this._writingBuf) ? fs79.writeSync(this.fd, this._writingBuf) : fs79.writeSync(this.fd, this._writingBuf, "utf8");
11024
+ const written = Buffer.isBuffer(this._writingBuf) ? fs80.writeSync(this.fd, this._writingBuf) : fs80.writeSync(this.fd, this._writingBuf, "utf8");
11006
11025
  release(null, written);
11007
11026
  } catch (err) {
11008
11027
  release(err);
11009
11028
  }
11010
11029
  } else {
11011
- fs79.write(this.fd, this._writingBuf, release);
11030
+ fs80.write(this.fd, this._writingBuf, release);
11012
11031
  }
11013
11032
  }
11014
11033
  function actualWriteBuffer() {
@@ -11017,7 +11036,7 @@ var require_sonic_boom = __commonJS({
11017
11036
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
11018
11037
  if (this.sync) {
11019
11038
  try {
11020
- const written = fs79.writeSync(this.fd, this._writingBuf);
11039
+ const written = fs80.writeSync(this.fd, this._writingBuf);
11021
11040
  release(null, written);
11022
11041
  } catch (err) {
11023
11042
  release(err);
@@ -11026,7 +11045,7 @@ var require_sonic_boom = __commonJS({
11026
11045
  if (kCopyBuffer) {
11027
11046
  this._writingBuf = Buffer.from(this._writingBuf);
11028
11047
  }
11029
- fs79.write(this.fd, this._writingBuf, release);
11048
+ fs80.write(this.fd, this._writingBuf, release);
11030
11049
  }
11031
11050
  }
11032
11051
  function actualClose(sonic) {
@@ -11042,12 +11061,12 @@ var require_sonic_boom = __commonJS({
11042
11061
  sonic._lens = [];
11043
11062
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
11044
11063
  try {
11045
- fs79.fsync(sonic.fd, closeWrapped);
11064
+ fs80.fsync(sonic.fd, closeWrapped);
11046
11065
  } catch {
11047
11066
  }
11048
11067
  function closeWrapped() {
11049
11068
  if (sonic.fd !== 1 && sonic.fd !== 2) {
11050
- fs79.close(sonic.fd, done);
11069
+ fs80.close(sonic.fd, done);
11051
11070
  } else {
11052
11071
  done();
11053
11072
  }
@@ -13411,7 +13430,7 @@ var require_multistream = __commonJS({
13411
13430
  var require_pino = __commonJS({
13412
13431
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
13413
13432
  "use strict";
13414
- var os30 = require("os");
13433
+ var os31 = require("os");
13415
13434
  var stdSerializers = require_pino_std_serializers();
13416
13435
  var caller = require_caller();
13417
13436
  var redaction = require_redaction();
@@ -13458,7 +13477,7 @@ var require_pino = __commonJS({
13458
13477
  } = symbols;
13459
13478
  var { epochTime, nullTime } = time;
13460
13479
  var { pid } = process;
13461
- var hostname = os30.hostname();
13480
+ var hostname = os31.hostname();
13462
13481
  var defaultErrorSerializer = stdSerializers.err;
13463
13482
  var defaultOptions2 = {
13464
13483
  level: "info",
@@ -14182,11 +14201,11 @@ var init_lib = __esm({
14182
14201
  }
14183
14202
  }
14184
14203
  },
14185
- addToPath: function addToPath(path89, added, removed, oldPosInc, options) {
14186
- var last = path89.lastComponent;
14204
+ addToPath: function addToPath(path91, added, removed, oldPosInc, options) {
14205
+ var last = path91.lastComponent;
14187
14206
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14188
14207
  return {
14189
- oldPos: path89.oldPos + oldPosInc,
14208
+ oldPos: path91.oldPos + oldPosInc,
14190
14209
  lastComponent: {
14191
14210
  count: last.count + 1,
14192
14211
  added,
@@ -14196,7 +14215,7 @@ var init_lib = __esm({
14196
14215
  };
14197
14216
  } else {
14198
14217
  return {
14199
- oldPos: path89.oldPos + oldPosInc,
14218
+ oldPos: path91.oldPos + oldPosInc,
14200
14219
  lastComponent: {
14201
14220
  count: 1,
14202
14221
  added,
@@ -14778,10 +14797,10 @@ function attachmentToHistoryMessage(o, ts) {
14778
14797
  const memories = raw.map((m2) => {
14779
14798
  if (!m2 || typeof m2 !== "object") return null;
14780
14799
  const rec4 = m2;
14781
- const path89 = typeof rec4.path === "string" ? rec4.path : null;
14800
+ const path91 = typeof rec4.path === "string" ? rec4.path : null;
14782
14801
  const content = typeof rec4.content === "string" ? rec4.content : null;
14783
- if (!path89 || content == null) return null;
14784
- const entry = { path: path89, content };
14802
+ if (!path91 || content == null) return null;
14803
+ const entry = { path: path91, content };
14785
14804
  if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
14786
14805
  return entry;
14787
14806
  }).filter((m2) => m2 !== null);
@@ -15647,10 +15666,10 @@ function parseAttachment(obj) {
15647
15666
  const memories = raw.map((m2) => {
15648
15667
  if (!m2 || typeof m2 !== "object") return null;
15649
15668
  const rec4 = m2;
15650
- const path89 = typeof rec4.path === "string" ? rec4.path : null;
15669
+ const path91 = typeof rec4.path === "string" ? rec4.path : null;
15651
15670
  const content = typeof rec4.content === "string" ? rec4.content : null;
15652
- if (!path89 || content == null) return null;
15653
- const out = { path: path89, content };
15671
+ if (!path91 || content == null) return null;
15672
+ const out = { path: path91, content };
15654
15673
  if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
15655
15674
  return out;
15656
15675
  }).filter((m2) => m2 !== null);
@@ -36624,8 +36643,8 @@ var require_utils = __commonJS({
36624
36643
  var result = transform[inputType][outputType](input);
36625
36644
  return result;
36626
36645
  };
36627
- exports2.resolve = function(path89) {
36628
- var parts = path89.split("/");
36646
+ exports2.resolve = function(path91) {
36647
+ var parts = path91.split("/");
36629
36648
  var result = [];
36630
36649
  for (var index = 0; index < parts.length; index++) {
36631
36650
  var part = parts[index];
@@ -42478,18 +42497,18 @@ var require_object = __commonJS({
42478
42497
  var object = new ZipObject(name, zipObjectContent, o);
42479
42498
  this.files[name] = object;
42480
42499
  };
42481
- var parentFolder = function(path89) {
42482
- if (path89.slice(-1) === "/") {
42483
- path89 = path89.substring(0, path89.length - 1);
42500
+ var parentFolder = function(path91) {
42501
+ if (path91.slice(-1) === "/") {
42502
+ path91 = path91.substring(0, path91.length - 1);
42484
42503
  }
42485
- var lastSlash = path89.lastIndexOf("/");
42486
- return lastSlash > 0 ? path89.substring(0, lastSlash) : "";
42504
+ var lastSlash = path91.lastIndexOf("/");
42505
+ return lastSlash > 0 ? path91.substring(0, lastSlash) : "";
42487
42506
  };
42488
- var forceTrailingSlash = function(path89) {
42489
- if (path89.slice(-1) !== "/") {
42490
- path89 += "/";
42507
+ var forceTrailingSlash = function(path91) {
42508
+ if (path91.slice(-1) !== "/") {
42509
+ path91 += "/";
42491
42510
  }
42492
- return path89;
42511
+ return path91;
42493
42512
  };
42494
42513
  var folderAdd = function(name, createFolders) {
42495
42514
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -43491,7 +43510,7 @@ var require_lib3 = __commonJS({
43491
43510
  // src/run-case/recorder.ts
43492
43511
  function startRunCaseRecorder(opts) {
43493
43512
  const now = opts.now ?? Date.now;
43494
- const dir = import_node_path71.default.dirname(opts.recordPath);
43513
+ const dir = import_node_path73.default.dirname(opts.recordPath);
43495
43514
  let stream = null;
43496
43515
  let closing = false;
43497
43516
  let closedSettled = false;
@@ -43505,8 +43524,8 @@ function startRunCaseRecorder(opts) {
43505
43524
  });
43506
43525
  const ensureStream = () => {
43507
43526
  if (stream) return stream;
43508
- import_node_fs53.default.mkdirSync(dir, { recursive: true });
43509
- stream = import_node_fs53.default.createWriteStream(opts.recordPath, { flags: "a" });
43527
+ import_node_fs54.default.mkdirSync(dir, { recursive: true });
43528
+ stream = import_node_fs54.default.createWriteStream(opts.recordPath, { flags: "a" });
43510
43529
  stream.on("close", () => closedResolve());
43511
43530
  return stream;
43512
43531
  };
@@ -43531,12 +43550,12 @@ function startRunCaseRecorder(opts) {
43531
43550
  };
43532
43551
  return { tap, close, closed };
43533
43552
  }
43534
- var import_node_fs53, import_node_path71;
43553
+ var import_node_fs54, import_node_path73;
43535
43554
  var init_recorder = __esm({
43536
43555
  "src/run-case/recorder.ts"() {
43537
43556
  "use strict";
43538
- import_node_fs53 = __toESM(require("fs"), 1);
43539
- import_node_path71 = __toESM(require("path"), 1);
43557
+ import_node_fs54 = __toESM(require("fs"), 1);
43558
+ import_node_path73 = __toESM(require("path"), 1);
43540
43559
  }
43541
43560
  });
43542
43561
 
@@ -43579,7 +43598,7 @@ var init_wire = __esm({
43579
43598
  // src/run-case/controller.ts
43580
43599
  async function runController(opts) {
43581
43600
  const now = opts.now ?? Date.now;
43582
- const cwd = opts.cwd ?? (0, import_node_fs54.mkdtempSync)(import_node_path72.default.join(import_node_os26.default.tmpdir(), "clawd-runcase-"));
43601
+ const cwd = opts.cwd ?? (0, import_node_fs55.mkdtempSync)(import_node_path74.default.join(import_node_os27.default.tmpdir(), "clawd-runcase-"));
43583
43602
  const ownsCwd = opts.cwd === void 0;
43584
43603
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
43585
43604
  const spawnCtx = { cwd };
@@ -43740,19 +43759,19 @@ async function runController(opts) {
43740
43759
  if (sigintHandler) process.off("SIGINT", sigintHandler);
43741
43760
  if (ownsCwd) {
43742
43761
  try {
43743
- (0, import_node_fs54.rmSync)(cwd, { recursive: true, force: true });
43762
+ (0, import_node_fs55.rmSync)(cwd, { recursive: true, force: true });
43744
43763
  } catch {
43745
43764
  }
43746
43765
  }
43747
43766
  return exitCode ?? 0;
43748
43767
  }
43749
- var import_node_fs54, import_node_os26, import_node_path72;
43768
+ var import_node_fs55, import_node_os27, import_node_path74;
43750
43769
  var init_controller = __esm({
43751
43770
  "src/run-case/controller.ts"() {
43752
43771
  "use strict";
43753
- import_node_fs54 = require("fs");
43754
- import_node_os26 = __toESM(require("os"), 1);
43755
- import_node_path72 = __toESM(require("path"), 1);
43772
+ import_node_fs55 = require("fs");
43773
+ import_node_os27 = __toESM(require("os"), 1);
43774
+ import_node_path74 = __toESM(require("path"), 1);
43756
43775
  init_claude();
43757
43776
  init_stdout_splitter();
43758
43777
  init_permission_stdio();
@@ -44027,9 +44046,9 @@ Env (advanced):
44027
44046
  `;
44028
44047
 
44029
44048
  // src/index.ts
44030
- var import_node_path70 = __toESM(require("path"), 1);
44031
- var import_node_fs52 = __toESM(require("fs"), 1);
44032
- var import_node_os25 = __toESM(require("os"), 1);
44049
+ var import_node_path72 = __toESM(require("path"), 1);
44050
+ var import_node_fs53 = __toESM(require("fs"), 1);
44051
+ var import_node_os26 = __toESM(require("os"), 1);
44033
44052
  var import_node_crypto22 = require("crypto");
44034
44053
  var import_node_url4 = require("url");
44035
44054
 
@@ -47069,7 +47088,7 @@ var SessionManager = class {
47069
47088
  subSessionMeta.codexSandbox = {
47070
47089
  writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
47071
47090
  denyRead: codexCfg?.denyRead ?? [],
47072
- network: codexCfg?.network ?? true
47091
+ network: codexCfg?.network ?? false
47073
47092
  };
47074
47093
  }
47075
47094
  if (subSessionMeta?.personaMode === "owner" && file.projectPath) {
@@ -49446,408 +49465,20 @@ var PersonaRegistry = class {
49446
49465
  }
49447
49466
  };
49448
49467
 
49449
- // src/skills/scanner.ts
49450
- var import_node_fs9 = __toESM(require("fs"), 1);
49451
- var import_node_os6 = __toESM(require("os"), 1);
49452
- var import_node_path9 = __toESM(require("path"), 1);
49453
-
49454
- // src/skills/frontmatter.ts
49455
- var STRIP_QUOTES = /^["']|["']$/g;
49456
- function strip(s) {
49457
- return s.trim().replace(STRIP_QUOTES, "");
49458
- }
49459
- function parseFrontmatter(content, keys) {
49460
- const out = {};
49461
- if (!content.startsWith("---")) return out;
49462
- const end = content.indexOf("---", 3);
49463
- if (end === -1) return out;
49464
- const lines = content.slice(3, end).split("\n");
49465
- for (let i = 0; i < lines.length; i++) {
49466
- const trimmed = lines[i].trim();
49467
- for (const key of keys) {
49468
- const prefix = `${key}:`;
49469
- if (!trimmed.startsWith(prefix)) continue;
49470
- const rest = trimmed.slice(prefix.length).trim();
49471
- if (rest === "|" || rest === ">" || rest === "|-" || rest === ">-") {
49472
- const parts = [];
49473
- for (let j = i + 1; j < lines.length; j++) {
49474
- const next = lines[j];
49475
- if (next.length === 0) {
49476
- parts.push("");
49477
- continue;
49478
- }
49479
- if (!/^\s/.test(next)) break;
49480
- parts.push(next.replace(/^\s+/, ""));
49481
- }
49482
- const value = parts.filter(Boolean).join(" ").trim();
49483
- if (value) out[key] = value;
49484
- } else {
49485
- const value = strip(rest);
49486
- if (value) out[key] = value;
49487
- }
49488
- break;
49489
- }
49490
- }
49491
- return out;
49492
- }
49493
-
49494
- // src/skills/builtin-cc-resources.ts
49495
- var BUILTIN_SKILLS = [
49496
- { name: "update-config", source: "builtin", description: "Update Claude Code configuration." },
49497
- { name: "keybindings-help", source: "builtin", description: "Show available keybindings." },
49498
- { name: "verify", source: "builtin", description: "Verify the implementation." },
49499
- { name: "debug", source: "builtin", description: "Debug current issue." },
49500
- { name: "lorem-ipsum", source: "builtin", description: "Generate lorem ipsum placeholder text." },
49501
- { name: "skillify", source: "builtin", description: "Convert a process into a reusable skill." },
49502
- { name: "remember", source: "builtin", description: "Remember context for later use." },
49503
- { name: "simplify", source: "builtin", description: "Simplify the code or message." },
49504
- { name: "batch", source: "builtin", description: "Run a batch of similar operations." },
49505
- { name: "stuck", source: "builtin", description: "Help unstick a stalled task." },
49506
- { name: "loop", source: "builtin", description: "Loop a task until a condition is met." },
49507
- { name: "cron-list", source: "builtin", description: "List scheduled cron tasks." },
49508
- { name: "cron-delete", source: "builtin", description: "Delete a scheduled cron task." },
49509
- { name: "dream", source: "builtin", description: "Brainstorm freely without constraints." },
49510
- { name: "hunter", source: "builtin", description: "Hunt down a bug or root cause." },
49511
- { name: "schedule", source: "builtin", description: "Schedule a task to run later." },
49512
- { name: "claude-api", source: "builtin", description: "Use the Claude API directly." },
49513
- { name: "claude-in-chrome", source: "builtin", description: "Drive Claude inside Chrome via the Chrome extension." }
49514
- ];
49515
- var BUILTIN_AGENTS = [
49516
- {
49517
- name: "general-purpose",
49518
- source: "builtin",
49519
- description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
49520
- whenToUse: "When you are searching for a keyword or file and are not confident you will find the right match in the first few tries."
49521
- },
49522
- {
49523
- name: "statusline-setup",
49524
- source: "builtin",
49525
- description: "Configure the user's Claude Code status line setting.",
49526
- whenToUse: "When the user is setting up or changing their status line configuration."
49527
- },
49528
- {
49529
- name: "Explore",
49530
- source: "builtin",
49531
- description: "Explore the codebase to gather context.",
49532
- whenToUse: "Before making changes that require understanding the surrounding code."
49533
- },
49534
- {
49535
- name: "Plan",
49536
- source: "builtin",
49537
- description: "Produce an implementation plan before writing code.",
49538
- whenToUse: "When the task is non-trivial and would benefit from an explicit plan."
49539
- },
49540
- {
49541
- name: "claude-code-guide",
49542
- source: "builtin",
49543
- description: "Guide the user through Claude Code features.",
49544
- whenToUse: "When the user needs help understanding what Claude Code can do."
49545
- },
49546
- {
49547
- name: "verification",
49548
- source: "builtin",
49549
- description: "Verify that a change works as intended.",
49550
- whenToUse: "After implementing a change, before declaring it done."
49551
- }
49552
- ];
49553
-
49554
- // src/skills/scanner.ts
49555
- function parseDescription(content) {
49556
- const fields = parseFrontmatter(content, ["description"]);
49557
- return { description: fields.description ?? "" };
49558
- }
49559
- function isDirLikeSync(p2) {
49560
- try {
49561
- return import_node_fs9.default.statSync(p2).isDirectory();
49562
- } catch {
49563
- return false;
49564
- }
49565
- }
49566
- function scanSkillDir(dir, source, seen, out, pluginName) {
49567
- let entries;
49568
- try {
49569
- entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
49570
- } catch {
49571
- return;
49572
- }
49573
- for (const ent of entries) {
49574
- const entryPath = import_node_path9.default.join(dir, ent.name);
49575
- if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
49576
- let content;
49577
- try {
49578
- content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
49579
- } catch {
49580
- try {
49581
- content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
49582
- } catch {
49583
- continue;
49584
- }
49585
- }
49586
- const { description } = parseDescription(content);
49587
- const baseName = ent.name;
49588
- const name = pluginName ? `${pluginName}:${baseName}` : baseName;
49589
- if (seen.has(name)) continue;
49590
- seen.add(name);
49591
- const info = { name, source, path: entryPath, description: description || void 0 };
49592
- if (pluginName) info.plugin = pluginName;
49593
- out.push(info);
49594
- }
49595
- }
49596
- function listSkillsForDir(dir, source) {
49597
- const seen = /* @__PURE__ */ new Set();
49598
- const out = [];
49599
- scanSkillDir(dir, source, seen, out);
49600
- return out;
49601
- }
49602
- function scanCommandDir(dir, source, seen, out, pluginName) {
49603
- let entries;
49604
- try {
49605
- entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
49606
- } catch {
49607
- return;
49608
- }
49609
- for (const ent of entries) {
49610
- const entryPath = import_node_path9.default.join(dir, ent.name);
49611
- if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
49612
- const ns = ent.name;
49613
- let subEntries;
49614
- try {
49615
- subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
49616
- } catch {
49617
- continue;
49618
- }
49619
- for (const se of subEntries) {
49620
- if (!se.name.endsWith(".md")) continue;
49621
- const sePath = import_node_path9.default.join(entryPath, se.name);
49622
- let content;
49623
- try {
49624
- content = import_node_fs9.default.readFileSync(sePath, "utf8");
49625
- } catch {
49626
- continue;
49627
- }
49628
- const cmd = se.name.replace(/\.md$/, "");
49629
- const { description } = parseDescription(content);
49630
- const qualified = `${ns}:${cmd}`;
49631
- const name = pluginName ? `${pluginName}:${qualified}` : qualified;
49632
- if (seen.has(name)) continue;
49633
- seen.add(name);
49634
- const info = { name, source, path: sePath, description: description || void 0 };
49635
- if (pluginName) info.plugin = pluginName;
49636
- out.push(info);
49637
- }
49638
- } else if (ent.name.endsWith(".md")) {
49639
- let content;
49640
- try {
49641
- content = import_node_fs9.default.readFileSync(entryPath, "utf8");
49642
- } catch {
49643
- continue;
49644
- }
49645
- const cmd = ent.name.replace(/\.md$/, "");
49646
- const { description } = parseDescription(content);
49647
- const name = pluginName ? `${pluginName}:${cmd}` : cmd;
49648
- if (seen.has(name)) continue;
49649
- seen.add(name);
49650
- const info = { name, source, path: entryPath, description: description || void 0 };
49651
- if (pluginName) info.plugin = pluginName;
49652
- out.push(info);
49653
- }
49654
- }
49655
- }
49656
- function readInstalledPlugins(home) {
49657
- const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
49658
- let raw;
49659
- try {
49660
- raw = import_node_fs9.default.readFileSync(file, "utf8");
49661
- } catch {
49662
- return [];
49663
- }
49664
- let parsed;
49665
- try {
49666
- parsed = JSON.parse(raw);
49667
- } catch {
49668
- return [];
49669
- }
49670
- const out = [];
49671
- for (const [key, entries] of Object.entries(parsed.plugins ?? {})) {
49672
- if (!Array.isArray(entries) || entries.length === 0) continue;
49673
- const entry = entries[0];
49674
- if (!entry?.installPath) continue;
49675
- const pluginName = key.includes("@") ? key.slice(0, key.indexOf("@")) : key;
49676
- if (!pluginName) continue;
49677
- out.push({ name: pluginName, root: entry.installPath });
49678
- }
49679
- return out;
49680
- }
49681
- var SkillsScanner = class {
49682
- home;
49683
- extraPluginRoots;
49684
- constructor(opts = {}) {
49685
- this.home = opts.home ?? import_node_os6.default.homedir();
49686
- this.extraPluginRoots = opts.extraPluginRoots ?? [];
49687
- }
49688
- /**
49689
- * 对齐 cc-direct(openclaw-plugin-clawos/src/claude-code/skills-scanner.ts):
49690
- * 1. global: ~/.claude/skills + ~/.claude/commands
49691
- * 2. project: <cwd>/.claude/skills + <cwd>/.claude/commands
49692
- * 3. plugin: installed_plugins.json 里每个 plugin 的 skills + commands
49693
- * 顺序 global → project → plugin,同名去重(先到先得)
49694
- */
49695
- list(args) {
49696
- const seen = /* @__PURE__ */ new Set();
49697
- const builtinBlock = [];
49698
- for (const b2 of BUILTIN_SKILLS) {
49699
- if (seen.has(b2.name)) continue;
49700
- seen.add(b2.name);
49701
- builtinBlock.push({
49702
- name: b2.name,
49703
- source: "builtin",
49704
- description: b2.description
49705
- });
49706
- }
49707
- const fsBlock = [];
49708
- scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
49709
- scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
49710
- scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
49711
- scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
49712
- const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
49713
- for (const { name, root } of plugins) {
49714
- scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
49715
- scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
49716
- }
49717
- fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
49718
- return [...builtinBlock, ...fsBlock];
49719
- }
49720
- };
49721
-
49722
- // src/persona/manager.ts
49723
- var PersonaManager = class {
49724
- constructor(deps) {
49725
- this.deps = deps;
49726
- }
49727
- deps;
49728
- /**
49729
- * slug 是 persona 的身份,label 只是显示名——两者刻意分开:id 落进文件路径 /
49730
- * 分享链接且创建后不可改,label 可中文、可随时改。此前 id 从 label 推导,
49731
- * 非 ascii 被剥空后一律 fallback 成 `persona-persona`。
49732
- *
49733
- * 撞名直接抛错而非改名:id 由调用方显式指定,静默换成带后缀的 id 等于把
49734
- * 用户的选择偷偷改掉。字符集校验在 PersonaCreateArgsSchema(路径穿越边界)。
49735
- */
49736
- create(args) {
49737
- const personaId2 = `persona-${args.slug}`;
49738
- if (this.deps.store.has(personaId2)) {
49739
- throw new Error(`personaId already exists: ${personaId2}`);
49740
- }
49741
- const now = Date.now();
49742
- const persona = {
49743
- personaId: personaId2,
49744
- label: args.label,
49745
- model: args.model,
49746
- // effort 兜底 high:persona 一律持有具体档位(spec 2026-08-12),UI 会带界面上高亮的
49747
- // 那一档,但 persona:create 也可能来自 butler 的 persona-authoring skill 这类不带该
49748
- // 字段的调用方——不兜的话要等下次 daemon 启动 backfill 才补上,中间建的 session 就漏了。
49749
- // 取值理由与 backfillPersonaSessionDefaults 一致(见那里的注释)。
49750
- effort: args.effort ?? "high",
49751
- tool: args.tool,
49752
- public: args.public ?? false,
49753
- iconKey: args.iconKey,
49754
- createdAt: now,
49755
- updatedAt: now
49756
- };
49757
- this.deps.store.write(persona, args.personality);
49758
- this.deps.registry.set(persona);
49759
- return persona;
49760
- }
49761
- update(personaId2, patch, texts) {
49762
- const existing = this.deps.registry.get(personaId2);
49763
- if (!existing) throw new Error(`persona not found: ${personaId2}`);
49764
- const { iconKey: iconKeyPatch, ...restPatch } = patch;
49765
- const updated = {
49766
- ...existing,
49767
- ...restPatch,
49768
- updatedAt: Date.now()
49769
- };
49770
- const toolChanged = patch.tool !== void 0 && (patch.tool ?? "claude") !== (existing.tool ?? "claude");
49771
- if (toolChanged) {
49772
- if (patch.model === void 0) delete updated.model;
49773
- if (patch.effort === void 0) delete updated.effort;
49774
- }
49775
- if (iconKeyPatch === null) {
49776
- delete updated.iconKey;
49777
- } else if (iconKeyPatch !== void 0) {
49778
- updated.iconKey = iconKeyPatch;
49779
- }
49780
- if (texts?.personality !== void 0) {
49781
- this.deps.store.writePersonality(personaId2, texts.personality);
49782
- }
49783
- if (texts?.personalityLocal !== void 0) {
49784
- this.deps.store.writePersonalityLocal(personaId2, texts.personalityLocal);
49785
- }
49786
- this.deps.store.writeMeta(updated);
49787
- this.deps.registry.set(updated);
49788
- return updated;
49789
- }
49790
- /** 读取 CLAUDE.md 内容;persona 目录或文件不存在时返回 null。透传给 handler 拼响应。 */
49791
- readPersonality(personaId2) {
49792
- return this.deps.store.readPersonality(personaId2);
49793
- }
49794
- /** 读人格补充层(`.clawd/personality.local.md`);没写过返回 null。供 persona:get 拼响应。 */
49795
- readPersonalityLocal(personaId2) {
49796
- return this.deps.store.readPersonalityLocal(personaId2);
49797
- }
49798
- /** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
49799
- listSkills(personaId2) {
49800
- return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
49801
- }
49802
- /**
49803
- * 读取 persona `.claude/settings.json` 中已启用的插件列表(value === true 的 key)。
49804
- * 文件不存在 / 解析失败 / 字段缺失 → 空数组。供 persona:get handler 拼响应。
49805
- */
49806
- listEnabledPlugins(personaId2) {
49807
- return this.deps.store.readEnabledPlugins(personaId2);
49808
- }
49809
- /** 读 sandbox-settings.json;不存在 / 损坏返回 null。供 persona:get handler 拼响应。 */
49810
- /** 读 codex guest 沙箱配置(`.clawd/codex-sandbox.json`);缺失 / 坏 → null。透传给 handler 拼响应。 */
49811
- readCodexSandboxSettings(personaId2) {
49812
- return this.deps.store.readCodexSandboxSettings(personaId2);
49813
- }
49814
- /**
49815
- * 局部合并写 codex guest 沙箱配置,返回合并后的全量。
49816
- *
49817
- * **必须是合并不是覆盖**:UI 的「访客联网」开关只发 `{network}`,整体覆盖会静默抹掉 owner
49818
- * 手配的 writableRoots / denyRead(丢的是安全边界,且用户不会立刻发现)。
49819
- * 不走 PersonaManager.update 是因为它管的是 PersonaFile meta + 人格两层文本,
49820
- * 而这份配置是另一个文件、另一套 schema。
49821
- */
49822
- mergeCodexSandbox(personaId2, patch) {
49823
- if (!this.deps.registry.get(personaId2)) throw new Error(`persona not found: ${personaId2}`);
49824
- const merged = { ...this.deps.store.readCodexSandboxSettings(personaId2) ?? {}, ...patch };
49825
- this.deps.store.writeCodexSandboxSettings(personaId2, merged);
49826
- return merged;
49827
- }
49828
- readSandboxSettings(personaId2) {
49829
- return this.deps.store.readSandboxSettings(personaId2);
49830
- }
49831
- /**
49832
- * 删除 persona。
49833
- * PersonaStore.remove(personaId) 级联删整个 <personaRoot>/<personaId>/ 目录
49834
- * (含 .clawd/sessions/owner/ 和 .clawd/sessions/guests/<capId>/),rmSync
49835
- * recursive force 一锅清。
49836
- */
49837
- delete(personaId2) {
49838
- this.deps.store.remove(personaId2);
49839
- this.deps.registry.remove(personaId2);
49840
- }
49841
- };
49842
-
49843
49468
  // src/persona/seed.ts
49844
- var fs13 = __toESM(require("fs"), 1);
49845
- var path16 = __toESM(require("path"), 1);
49469
+ var fs12 = __toESM(require("fs"), 1);
49470
+ var path15 = __toESM(require("path"), 1);
49846
49471
  var import_node_url = require("url");
49847
49472
  var import_meta = {};
49848
49473
  var DEFAULT_BYPASS_PROFILE = {
49849
49474
  permissions: { defaultMode: "bypassPermissions" }
49850
49475
  };
49476
+ var PKG_CACHE_ROOTS = ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"];
49477
+ var CODEX_SANDBOX_DEFAULT = {
49478
+ writableRoots: [...PKG_CACHE_ROOTS],
49479
+ denyRead: [".secrets/**"],
49480
+ network: true
49481
+ };
49851
49482
  var DEFAULT_PERSONAS = [
49852
49483
  {
49853
49484
  personaId: "persona-researcher",
@@ -49932,7 +49563,7 @@ var DEFAULT_PERSONAS = [
49932
49563
  }
49933
49564
  },
49934
49565
  codexSandbox: {
49935
- writableRoots: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
49566
+ writableRoots: [...PKG_CACHE_ROOTS],
49936
49567
  denyRead: [".secrets/**"],
49937
49568
  network: true
49938
49569
  }
@@ -49966,7 +49597,7 @@ var DEFAULT_PERSONAS = [
49966
49597
  }
49967
49598
  },
49968
49599
  codexSandbox: {
49969
- writableRoots: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
49600
+ writableRoots: [...PKG_CACHE_ROOTS],
49970
49601
  denyRead: [".secrets/**"],
49971
49602
  network: true
49972
49603
  }
@@ -50008,7 +49639,7 @@ var DEFAULT_PERSONAS = [
50008
49639
  }
50009
49640
  },
50010
49641
  codexSandbox: {
50011
- writableRoots: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
49642
+ writableRoots: [...PKG_CACHE_ROOTS],
50012
49643
  denyRead: [".secrets/**"],
50013
49644
  network: true
50014
49645
  }
@@ -50033,24 +49664,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
50033
49664
  if (!argv1) return null;
50034
49665
  let real = argv1;
50035
49666
  try {
50036
- real = fs13.realpathSync(argv1);
49667
+ real = fs12.realpathSync(argv1);
50037
49668
  } catch {
50038
49669
  }
50039
- return path16.resolve(path16.dirname(real), sibling);
49670
+ return path15.resolve(path15.dirname(real), sibling);
50040
49671
  }
50041
49672
  function findDefaultsRoot(logger) {
50042
49673
  const candidates = [];
50043
49674
  try {
50044
- const here = path16.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
50045
- candidates.push(path16.resolve(here, "defaults"));
50046
- candidates.push(path16.resolve(here, "persona-defaults"));
49675
+ const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
49676
+ candidates.push(path15.resolve(here, "defaults"));
49677
+ candidates.push(path15.resolve(here, "persona-defaults"));
50047
49678
  } catch {
50048
49679
  }
50049
49680
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
50050
49681
  if (fromArgv) candidates.push(fromArgv);
50051
49682
  for (const c of candidates) {
50052
49683
  try {
50053
- if (fs13.statSync(c).isDirectory()) {
49684
+ if (fs12.statSync(c).isDirectory()) {
50054
49685
  logger?.info("persona.defaults-root.resolved", { root: c });
50055
49686
  return c;
50056
49687
  }
@@ -50067,8 +49698,8 @@ function seedDefaultPersonas(args) {
50067
49698
  args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
50068
49699
  continue;
50069
49700
  }
50070
- const bundleDir = path16.join(args.defaultsRoot, entry.personaId);
50071
- if (!fs13.existsSync(bundleDir)) {
49701
+ const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
49702
+ if (!fs12.existsSync(bundleDir)) {
50072
49703
  args.logger.warn("persona.seed.skip", {
50073
49704
  personaId: entry.personaId,
50074
49705
  reason: "bundle-missing",
@@ -50076,8 +49707,8 @@ function seedDefaultPersonas(args) {
50076
49707
  });
50077
49708
  continue;
50078
49709
  }
50079
- const claudeMdPath = path16.join(bundleDir, "CLAUDE.md");
50080
- if (!fs13.existsSync(claudeMdPath)) {
49710
+ const claudeMdPath = path15.join(bundleDir, "CLAUDE.md");
49711
+ if (!fs12.existsSync(claudeMdPath)) {
50081
49712
  args.logger.warn("persona.seed.skip", {
50082
49713
  personaId: entry.personaId,
50083
49714
  reason: "no-CLAUDE.md",
@@ -50085,7 +49716,7 @@ function seedDefaultPersonas(args) {
50085
49716
  });
50086
49717
  continue;
50087
49718
  }
50088
- const personality = fs13.readFileSync(claudeMdPath, "utf8");
49719
+ const personality = fs12.readFileSync(claudeMdPath, "utf8");
50089
49720
  const now = Date.now();
50090
49721
  const persona = {
50091
49722
  personaId: entry.personaId,
@@ -50112,51 +49743,51 @@ function seedDefaultPersonas(args) {
50112
49743
  }
50113
49744
  }
50114
49745
  function skipNodeModulesUnder(srcRoot) {
50115
- return (src) => !path16.relative(srcRoot, src).split(path16.sep).includes("node_modules");
49746
+ return (src) => !path15.relative(srcRoot, src).split(path15.sep).includes("node_modules");
50116
49747
  }
50117
49748
  function copyBundleExtras(srcDir, dstDir) {
50118
- for (const entry of fs13.readdirSync(srcDir, { withFileTypes: true })) {
49749
+ for (const entry of fs12.readdirSync(srcDir, { withFileTypes: true })) {
50119
49750
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
50120
- const srcPath = path16.join(srcDir, entry.name);
50121
- const dstPath = path16.join(dstDir, entry.name);
49751
+ const srcPath = path15.join(srcDir, entry.name);
49752
+ const dstPath = path15.join(dstDir, entry.name);
50122
49753
  if (entry.isDirectory()) {
50123
- fs13.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
49754
+ fs12.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
50124
49755
  } else if (entry.isFile()) {
50125
- fs13.copyFileSync(srcPath, dstPath);
49756
+ fs12.copyFileSync(srcPath, dstPath);
50126
49757
  }
50127
49758
  }
50128
49759
  }
50129
49760
  var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills", ".claude/agents"];
50130
49761
  function replaceManagedPath(src, dst) {
50131
- if (!fs13.statSync(src).isDirectory()) {
50132
- fs13.mkdirSync(path16.dirname(dst), { recursive: true });
50133
- fs13.rmSync(dst, { recursive: true, force: true });
50134
- fs13.cpSync(src, dst, { dereference: true });
49762
+ if (!fs12.statSync(src).isDirectory()) {
49763
+ fs12.mkdirSync(path15.dirname(dst), { recursive: true });
49764
+ fs12.rmSync(dst, { recursive: true, force: true });
49765
+ fs12.cpSync(src, dst, { dereference: true });
50135
49766
  return;
50136
49767
  }
50137
- fs13.mkdirSync(dst, { recursive: true });
50138
- for (const e of fs13.readdirSync(src, { withFileTypes: true })) {
49768
+ fs12.mkdirSync(dst, { recursive: true });
49769
+ for (const e of fs12.readdirSync(src, { withFileTypes: true })) {
50139
49770
  if (e.name === "node_modules") continue;
50140
- const child = path16.join(dst, e.name);
50141
- fs13.rmSync(child, { recursive: true, force: true });
50142
- fs13.cpSync(path16.join(src, e.name), child, { recursive: true, dereference: true });
49771
+ const child = path15.join(dst, e.name);
49772
+ fs12.rmSync(child, { recursive: true, force: true });
49773
+ fs12.cpSync(path15.join(src, e.name), child, { recursive: true, dereference: true });
50143
49774
  }
50144
49775
  }
50145
49776
  function refreshDaemonManagedDirs(args) {
50146
49777
  const entries = args.entries ?? DEFAULT_PERSONAS;
50147
49778
  for (const entry of entries) {
50148
- const bundleDir = path16.join(args.defaultsRoot, entry.personaId);
50149
- if (!fs13.existsSync(bundleDir)) continue;
49779
+ const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
49780
+ if (!fs12.existsSync(bundleDir)) continue;
50150
49781
  const personaDir = args.store.personaDirPath(entry.personaId);
50151
- if (!fs13.existsSync(personaDir)) continue;
49782
+ if (!fs12.existsSync(personaDir)) continue;
50152
49783
  for (const relPath of DAEMON_MANAGED_PATHS) {
50153
- const srcPath = path16.join(bundleDir, relPath);
50154
- if (!fs13.existsSync(srcPath)) continue;
50155
- const dstPath = path16.join(personaDir, relPath);
49784
+ const srcPath = path15.join(bundleDir, relPath);
49785
+ if (!fs12.existsSync(srcPath)) continue;
49786
+ const dstPath = path15.join(personaDir, relPath);
50156
49787
  try {
50157
49788
  replaceManagedPath(srcPath, dstPath);
50158
49789
  if (relPath === "CLAUDE.md") {
50159
- replaceManagedPath(srcPath, path16.join(personaDir, "AGENTS.md"));
49790
+ replaceManagedPath(srcPath, path15.join(personaDir, "AGENTS.md"));
50160
49791
  }
50161
49792
  args.logger.info("persona.refresh.synced", {
50162
49793
  personaId: entry.personaId,
@@ -50180,12 +49811,12 @@ function migratePersonalityOverlay(args) {
50180
49811
  for (const entry of entries) {
50181
49812
  const personaId2 = entry.personaId;
50182
49813
  try {
50183
- if (fs13.existsSync(args.store.personalityLocalPath(personaId2))) continue;
50184
- const bundleClaudeMd = path16.join(args.defaultsRoot, personaId2, "CLAUDE.md");
50185
- if (!fs13.existsSync(bundleClaudeMd)) continue;
49814
+ if (fs12.existsSync(args.store.personalityLocalPath(personaId2))) continue;
49815
+ const bundleClaudeMd = path15.join(args.defaultsRoot, personaId2, "CLAUDE.md");
49816
+ if (!fs12.existsSync(bundleClaudeMd)) continue;
50186
49817
  const current = args.store.readPersonality(personaId2);
50187
49818
  if (current === null) continue;
50188
- const bundle = fs13.readFileSync(bundleClaudeMd, "utf8");
49819
+ const bundle = fs12.readFileSync(bundleClaudeMd, "utf8");
50189
49820
  if (current === bundle) continue;
50190
49821
  if (!current.startsWith(bundle)) continue;
50191
49822
  const tail = current.slice(bundle.length).trim();
@@ -50226,8 +49857,6 @@ function migrateAgentsMirror(args) {
50226
49857
  }
50227
49858
  if (mirrored > 0) args.logger.info("persona.agents-mirror.done", { mirrored });
50228
49859
  }
50229
- var PKG_CACHE_ROOTS = ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"];
50230
- var CODEX_SANDBOX_DEFAULT = { writableRoots: [...PKG_CACHE_ROOTS], denyRead: [], network: true };
50231
49860
  function migrateCodexSandbox(args) {
50232
49861
  const entries = args.entries ?? DEFAULT_PERSONAS;
50233
49862
  let n = 0;
@@ -50286,7 +49915,7 @@ function migrateSandboxAllowRead(args) {
50286
49915
  for (const personaId2 of args.store.list()) {
50287
49916
  try {
50288
49917
  const readPath = tildePath(args.store.personaDirPath(personaId2));
50289
- if (!fs13.existsSync(args.store.sandboxSettingsPath(personaId2))) {
49918
+ if (!fs12.existsSync(args.store.sandboxSettingsPath(personaId2))) {
50290
49919
  args.store.writeSandboxSettings(personaId2, buildGuestSettingsV1());
50291
49920
  n++;
50292
49921
  continue;
@@ -50329,13 +49958,13 @@ var PERSONA_BUILDER_TOMBSTONE = `${PERSONA_BUILDER_TOMBSTONE_MARKER}
50329
49958
  function containsAnyFile(dir) {
50330
49959
  let entries;
50331
49960
  try {
50332
- entries = fs13.readdirSync(dir, { withFileTypes: true });
49961
+ entries = fs12.readdirSync(dir, { withFileTypes: true });
50333
49962
  } catch {
50334
49963
  return false;
50335
49964
  }
50336
49965
  for (const e of entries) {
50337
49966
  if (e.isDirectory()) {
50338
- if (containsAnyFile(path16.join(dir, e.name))) return true;
49967
+ if (containsAnyFile(path15.join(dir, e.name))) return true;
50339
49968
  } else {
50340
49969
  return true;
50341
49970
  }
@@ -50344,9 +49973,9 @@ function containsAnyFile(dir) {
50344
49973
  }
50345
49974
  function retirePersonaBuilder(args) {
50346
49975
  const dir = args.store.personaDirPath(PERSONA_BUILDER_ID);
50347
- if (!fs13.existsSync(dir)) return;
49976
+ if (!fs12.existsSync(dir)) return;
50348
49977
  try {
50349
- const used = containsAnyFile(path16.join(dir, ".clawd", "sessions")) || containsAnyFile(path16.join(dir, ".claude", "skills")) || containsAnyFile(path16.join(dir, "projects"));
49978
+ const used = containsAnyFile(path15.join(dir, ".clawd", "sessions")) || containsAnyFile(path15.join(dir, ".claude", "skills")) || containsAnyFile(path15.join(dir, "projects"));
50350
49979
  if (!used) {
50351
49980
  args.store.remove(PERSONA_BUILDER_ID);
50352
49981
  args.logger.info("persona.retire-builder.removed", { personaId: PERSONA_BUILDER_ID });
@@ -50354,10 +49983,10 @@ function retirePersonaBuilder(args) {
50354
49983
  }
50355
49984
  let wrote = false;
50356
49985
  for (const name of ["CLAUDE.md", "AGENTS.md"]) {
50357
- const p2 = path16.join(dir, name);
50358
- const cur = fs13.existsSync(p2) ? fs13.readFileSync(p2, "utf8") : null;
49986
+ const p2 = path15.join(dir, name);
49987
+ const cur = fs12.existsSync(p2) ? fs12.readFileSync(p2, "utf8") : null;
50359
49988
  if (cur?.startsWith(PERSONA_BUILDER_TOMBSTONE_MARKER)) continue;
50360
- fs13.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
49989
+ fs12.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
50361
49990
  wrote = true;
50362
49991
  }
50363
49992
  if (wrote) args.logger.info("persona.retire-builder.tombstoned", { personaId: PERSONA_BUILDER_ID });
@@ -50371,15 +50000,15 @@ function retirePersonaBuilder(args) {
50371
50000
  function findDeployKitRoot(logger) {
50372
50001
  const candidates = [];
50373
50002
  try {
50374
- const here = path16.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
50375
- candidates.push(path16.resolve(here, "..", "deploy-kit"));
50003
+ const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
50004
+ candidates.push(path15.resolve(here, "..", "deploy-kit"));
50376
50005
  } catch {
50377
50006
  }
50378
50007
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
50379
50008
  if (fromArgv) candidates.push(fromArgv);
50380
50009
  for (const c of candidates) {
50381
50010
  try {
50382
- if (fs13.statSync(c).isDirectory()) {
50011
+ if (fs12.statSync(c).isDirectory()) {
50383
50012
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
50384
50013
  return c;
50385
50014
  }
@@ -50390,8 +50019,8 @@ function findDeployKitRoot(logger) {
50390
50019
  return null;
50391
50020
  }
50392
50021
  function seedDeployKit(args) {
50393
- const dst = path16.join(args.dataDir, "deploy-kit");
50394
- fs13.cpSync(args.deployKitBundleRoot, dst, {
50022
+ const dst = path15.join(args.dataDir, "deploy-kit");
50023
+ fs12.cpSync(args.deployKitBundleRoot, dst, {
50395
50024
  recursive: true,
50396
50025
  dereference: true,
50397
50026
  force: false,
@@ -50400,28 +50029,434 @@ function seedDeployKit(args) {
50400
50029
  args.logger.info("deploy-kit.seed.done", { dst });
50401
50030
  }
50402
50031
  function refreshDeployKit(args) {
50403
- const dst = path16.join(args.dataDir, "deploy-kit");
50404
- if (!fs13.existsSync(dst)) {
50032
+ const dst = path15.join(args.dataDir, "deploy-kit");
50033
+ if (!fs12.existsSync(dst)) {
50405
50034
  seedDeployKit(args);
50406
50035
  return;
50407
50036
  }
50408
50037
  for (const sub of ["scripts", "contract"]) {
50409
- const s = path16.join(args.deployKitBundleRoot, sub);
50410
- if (fs13.existsSync(s)) {
50411
- fs13.cpSync(s, path16.join(dst, sub), { recursive: true, force: true, dereference: true });
50038
+ const s = path15.join(args.deployKitBundleRoot, sub);
50039
+ if (fs12.existsSync(s)) {
50040
+ fs12.cpSync(s, path15.join(dst, sub), { recursive: true, force: true, dereference: true });
50412
50041
  }
50413
50042
  }
50414
- const secretsSrc = path16.join(args.deployKitBundleRoot, ".secrets");
50415
- if (fs13.existsSync(secretsSrc)) {
50416
- fs13.mkdirSync(path16.join(dst, ".secrets"), { recursive: true });
50417
- for (const f of fs13.readdirSync(secretsSrc)) {
50043
+ const secretsSrc = path15.join(args.deployKitBundleRoot, ".secrets");
50044
+ if (fs12.existsSync(secretsSrc)) {
50045
+ fs12.mkdirSync(path15.join(dst, ".secrets"), { recursive: true });
50046
+ for (const f of fs12.readdirSync(secretsSrc)) {
50418
50047
  if (f.endsWith(".local")) continue;
50419
- fs13.copyFileSync(path16.join(secretsSrc, f), path16.join(dst, ".secrets", f));
50048
+ fs12.copyFileSync(path15.join(secretsSrc, f), path15.join(dst, ".secrets", f));
50420
50049
  }
50421
50050
  }
50422
50051
  args.logger.info("deploy-kit.refresh.done", { dst });
50423
50052
  }
50424
50053
 
50054
+ // src/skills/scanner.ts
50055
+ var import_node_fs9 = __toESM(require("fs"), 1);
50056
+ var import_node_os6 = __toESM(require("os"), 1);
50057
+ var import_node_path9 = __toESM(require("path"), 1);
50058
+
50059
+ // src/skills/frontmatter.ts
50060
+ var STRIP_QUOTES = /^["']|["']$/g;
50061
+ function strip(s) {
50062
+ return s.trim().replace(STRIP_QUOTES, "");
50063
+ }
50064
+ function parseFrontmatter(content, keys) {
50065
+ const out = {};
50066
+ if (!content.startsWith("---")) return out;
50067
+ const end = content.indexOf("---", 3);
50068
+ if (end === -1) return out;
50069
+ const lines = content.slice(3, end).split("\n");
50070
+ for (let i = 0; i < lines.length; i++) {
50071
+ const trimmed = lines[i].trim();
50072
+ for (const key of keys) {
50073
+ const prefix = `${key}:`;
50074
+ if (!trimmed.startsWith(prefix)) continue;
50075
+ const rest = trimmed.slice(prefix.length).trim();
50076
+ if (rest === "|" || rest === ">" || rest === "|-" || rest === ">-") {
50077
+ const parts = [];
50078
+ for (let j = i + 1; j < lines.length; j++) {
50079
+ const next = lines[j];
50080
+ if (next.length === 0) {
50081
+ parts.push("");
50082
+ continue;
50083
+ }
50084
+ if (!/^\s/.test(next)) break;
50085
+ parts.push(next.replace(/^\s+/, ""));
50086
+ }
50087
+ const value = parts.filter(Boolean).join(" ").trim();
50088
+ if (value) out[key] = value;
50089
+ } else {
50090
+ const value = strip(rest);
50091
+ if (value) out[key] = value;
50092
+ }
50093
+ break;
50094
+ }
50095
+ }
50096
+ return out;
50097
+ }
50098
+
50099
+ // src/skills/builtin-cc-resources.ts
50100
+ var BUILTIN_SKILLS = [
50101
+ { name: "update-config", source: "builtin", description: "Update Claude Code configuration." },
50102
+ { name: "keybindings-help", source: "builtin", description: "Show available keybindings." },
50103
+ { name: "verify", source: "builtin", description: "Verify the implementation." },
50104
+ { name: "debug", source: "builtin", description: "Debug current issue." },
50105
+ { name: "lorem-ipsum", source: "builtin", description: "Generate lorem ipsum placeholder text." },
50106
+ { name: "skillify", source: "builtin", description: "Convert a process into a reusable skill." },
50107
+ { name: "remember", source: "builtin", description: "Remember context for later use." },
50108
+ { name: "simplify", source: "builtin", description: "Simplify the code or message." },
50109
+ { name: "batch", source: "builtin", description: "Run a batch of similar operations." },
50110
+ { name: "stuck", source: "builtin", description: "Help unstick a stalled task." },
50111
+ { name: "loop", source: "builtin", description: "Loop a task until a condition is met." },
50112
+ { name: "cron-list", source: "builtin", description: "List scheduled cron tasks." },
50113
+ { name: "cron-delete", source: "builtin", description: "Delete a scheduled cron task." },
50114
+ { name: "dream", source: "builtin", description: "Brainstorm freely without constraints." },
50115
+ { name: "hunter", source: "builtin", description: "Hunt down a bug or root cause." },
50116
+ { name: "schedule", source: "builtin", description: "Schedule a task to run later." },
50117
+ { name: "claude-api", source: "builtin", description: "Use the Claude API directly." },
50118
+ { name: "claude-in-chrome", source: "builtin", description: "Drive Claude inside Chrome via the Chrome extension." }
50119
+ ];
50120
+ var BUILTIN_AGENTS = [
50121
+ {
50122
+ name: "general-purpose",
50123
+ source: "builtin",
50124
+ description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
50125
+ whenToUse: "When you are searching for a keyword or file and are not confident you will find the right match in the first few tries."
50126
+ },
50127
+ {
50128
+ name: "statusline-setup",
50129
+ source: "builtin",
50130
+ description: "Configure the user's Claude Code status line setting.",
50131
+ whenToUse: "When the user is setting up or changing their status line configuration."
50132
+ },
50133
+ {
50134
+ name: "Explore",
50135
+ source: "builtin",
50136
+ description: "Explore the codebase to gather context.",
50137
+ whenToUse: "Before making changes that require understanding the surrounding code."
50138
+ },
50139
+ {
50140
+ name: "Plan",
50141
+ source: "builtin",
50142
+ description: "Produce an implementation plan before writing code.",
50143
+ whenToUse: "When the task is non-trivial and would benefit from an explicit plan."
50144
+ },
50145
+ {
50146
+ name: "claude-code-guide",
50147
+ source: "builtin",
50148
+ description: "Guide the user through Claude Code features.",
50149
+ whenToUse: "When the user needs help understanding what Claude Code can do."
50150
+ },
50151
+ {
50152
+ name: "verification",
50153
+ source: "builtin",
50154
+ description: "Verify that a change works as intended.",
50155
+ whenToUse: "After implementing a change, before declaring it done."
50156
+ }
50157
+ ];
50158
+
50159
+ // src/skills/scanner.ts
50160
+ function parseDescription(content) {
50161
+ const fields = parseFrontmatter(content, ["description"]);
50162
+ return { description: fields.description ?? "" };
50163
+ }
50164
+ function isDirLikeSync(p2) {
50165
+ try {
50166
+ return import_node_fs9.default.statSync(p2).isDirectory();
50167
+ } catch {
50168
+ return false;
50169
+ }
50170
+ }
50171
+ function scanSkillDir(dir, source, seen, out, pluginName) {
50172
+ let entries;
50173
+ try {
50174
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
50175
+ } catch {
50176
+ return;
50177
+ }
50178
+ for (const ent of entries) {
50179
+ const entryPath = import_node_path9.default.join(dir, ent.name);
50180
+ if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
50181
+ let content;
50182
+ try {
50183
+ content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
50184
+ } catch {
50185
+ try {
50186
+ content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
50187
+ } catch {
50188
+ continue;
50189
+ }
50190
+ }
50191
+ const { description } = parseDescription(content);
50192
+ const baseName = ent.name;
50193
+ const name = pluginName ? `${pluginName}:${baseName}` : baseName;
50194
+ if (seen.has(name)) continue;
50195
+ seen.add(name);
50196
+ const info = { name, source, path: entryPath, description: description || void 0 };
50197
+ if (pluginName) info.plugin = pluginName;
50198
+ out.push(info);
50199
+ }
50200
+ }
50201
+ function listSkillsForDir(dir, source) {
50202
+ const seen = /* @__PURE__ */ new Set();
50203
+ const out = [];
50204
+ scanSkillDir(dir, source, seen, out);
50205
+ return out;
50206
+ }
50207
+ function scanCommandDir(dir, source, seen, out, pluginName) {
50208
+ let entries;
50209
+ try {
50210
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
50211
+ } catch {
50212
+ return;
50213
+ }
50214
+ for (const ent of entries) {
50215
+ const entryPath = import_node_path9.default.join(dir, ent.name);
50216
+ if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
50217
+ const ns = ent.name;
50218
+ let subEntries;
50219
+ try {
50220
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
50221
+ } catch {
50222
+ continue;
50223
+ }
50224
+ for (const se of subEntries) {
50225
+ if (!se.name.endsWith(".md")) continue;
50226
+ const sePath = import_node_path9.default.join(entryPath, se.name);
50227
+ let content;
50228
+ try {
50229
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
50230
+ } catch {
50231
+ continue;
50232
+ }
50233
+ const cmd = se.name.replace(/\.md$/, "");
50234
+ const { description } = parseDescription(content);
50235
+ const qualified = `${ns}:${cmd}`;
50236
+ const name = pluginName ? `${pluginName}:${qualified}` : qualified;
50237
+ if (seen.has(name)) continue;
50238
+ seen.add(name);
50239
+ const info = { name, source, path: sePath, description: description || void 0 };
50240
+ if (pluginName) info.plugin = pluginName;
50241
+ out.push(info);
50242
+ }
50243
+ } else if (ent.name.endsWith(".md")) {
50244
+ let content;
50245
+ try {
50246
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
50247
+ } catch {
50248
+ continue;
50249
+ }
50250
+ const cmd = ent.name.replace(/\.md$/, "");
50251
+ const { description } = parseDescription(content);
50252
+ const name = pluginName ? `${pluginName}:${cmd}` : cmd;
50253
+ if (seen.has(name)) continue;
50254
+ seen.add(name);
50255
+ const info = { name, source, path: entryPath, description: description || void 0 };
50256
+ if (pluginName) info.plugin = pluginName;
50257
+ out.push(info);
50258
+ }
50259
+ }
50260
+ }
50261
+ function readInstalledPlugins(home) {
50262
+ const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
50263
+ let raw;
50264
+ try {
50265
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
50266
+ } catch {
50267
+ return [];
50268
+ }
50269
+ let parsed;
50270
+ try {
50271
+ parsed = JSON.parse(raw);
50272
+ } catch {
50273
+ return [];
50274
+ }
50275
+ const out = [];
50276
+ for (const [key, entries] of Object.entries(parsed.plugins ?? {})) {
50277
+ if (!Array.isArray(entries) || entries.length === 0) continue;
50278
+ const entry = entries[0];
50279
+ if (!entry?.installPath) continue;
50280
+ const pluginName = key.includes("@") ? key.slice(0, key.indexOf("@")) : key;
50281
+ if (!pluginName) continue;
50282
+ out.push({ name: pluginName, root: entry.installPath });
50283
+ }
50284
+ return out;
50285
+ }
50286
+ var SkillsScanner = class {
50287
+ home;
50288
+ extraPluginRoots;
50289
+ constructor(opts = {}) {
50290
+ this.home = opts.home ?? import_node_os6.default.homedir();
50291
+ this.extraPluginRoots = opts.extraPluginRoots ?? [];
50292
+ }
50293
+ /**
50294
+ * 对齐 cc-direct(openclaw-plugin-clawos/src/claude-code/skills-scanner.ts):
50295
+ * 1. global: ~/.claude/skills + ~/.claude/commands
50296
+ * 2. project: <cwd>/.claude/skills + <cwd>/.claude/commands
50297
+ * 3. plugin: installed_plugins.json 里每个 plugin 的 skills + commands
50298
+ * 顺序 global → project → plugin,同名去重(先到先得)
50299
+ */
50300
+ list(args) {
50301
+ const seen = /* @__PURE__ */ new Set();
50302
+ const builtinBlock = [];
50303
+ for (const b2 of BUILTIN_SKILLS) {
50304
+ if (seen.has(b2.name)) continue;
50305
+ seen.add(b2.name);
50306
+ builtinBlock.push({
50307
+ name: b2.name,
50308
+ source: "builtin",
50309
+ description: b2.description
50310
+ });
50311
+ }
50312
+ const fsBlock = [];
50313
+ scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
50314
+ scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
50315
+ scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
50316
+ scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
50317
+ const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
50318
+ for (const { name, root } of plugins) {
50319
+ scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
50320
+ scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
50321
+ }
50322
+ fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
50323
+ return [...builtinBlock, ...fsBlock];
50324
+ }
50325
+ };
50326
+
50327
+ // src/persona/manager.ts
50328
+ var PersonaManager = class {
50329
+ constructor(deps) {
50330
+ this.deps = deps;
50331
+ }
50332
+ deps;
50333
+ /**
50334
+ * slug 是 persona 的身份,label 只是显示名——两者刻意分开:id 落进文件路径 /
50335
+ * 分享链接且创建后不可改,label 可中文、可随时改。此前 id 从 label 推导,
50336
+ * 非 ascii 被剥空后一律 fallback 成 `persona-persona`。
50337
+ *
50338
+ * 撞名直接抛错而非改名:id 由调用方显式指定,静默换成带后缀的 id 等于把
50339
+ * 用户的选择偷偷改掉。字符集校验在 PersonaCreateArgsSchema(路径穿越边界)。
50340
+ */
50341
+ create(args) {
50342
+ const personaId2 = `persona-${args.slug}`;
50343
+ if (this.deps.store.has(personaId2)) {
50344
+ throw new Error(`personaId already exists: ${personaId2}`);
50345
+ }
50346
+ const now = Date.now();
50347
+ const persona = {
50348
+ personaId: personaId2,
50349
+ label: args.label,
50350
+ model: args.model,
50351
+ // effort 兜底 high:persona 一律持有具体档位(spec 2026-08-12),UI 会带界面上高亮的
50352
+ // 那一档,但 persona:create 也可能来自 butler 的 persona-authoring skill 这类不带该
50353
+ // 字段的调用方——不兜的话要等下次 daemon 启动 backfill 才补上,中间建的 session 就漏了。
50354
+ // 取值理由与 backfillPersonaSessionDefaults 一致(见那里的注释)。
50355
+ effort: args.effort ?? "high",
50356
+ tool: args.tool,
50357
+ public: args.public ?? false,
50358
+ iconKey: args.iconKey,
50359
+ createdAt: now,
50360
+ updatedAt: now
50361
+ };
50362
+ this.deps.store.write(persona, args.personality);
50363
+ this.deps.store.writeCodexSandboxSettings(personaId2, CODEX_SANDBOX_DEFAULT);
50364
+ this.deps.registry.set(persona);
50365
+ return persona;
50366
+ }
50367
+ update(personaId2, patch, texts) {
50368
+ const existing = this.deps.registry.get(personaId2);
50369
+ if (!existing) throw new Error(`persona not found: ${personaId2}`);
50370
+ const { iconKey: iconKeyPatch, ...restPatch } = patch;
50371
+ const updated = {
50372
+ ...existing,
50373
+ ...restPatch,
50374
+ updatedAt: Date.now()
50375
+ };
50376
+ const toolChanged = patch.tool !== void 0 && (patch.tool ?? "claude") !== (existing.tool ?? "claude");
50377
+ if (toolChanged) {
50378
+ if (patch.model === void 0) delete updated.model;
50379
+ if (patch.effort === void 0) delete updated.effort;
50380
+ }
50381
+ if (iconKeyPatch === null) {
50382
+ delete updated.iconKey;
50383
+ } else if (iconKeyPatch !== void 0) {
50384
+ updated.iconKey = iconKeyPatch;
50385
+ }
50386
+ if (texts?.personality !== void 0) {
50387
+ this.deps.store.writePersonality(personaId2, texts.personality);
50388
+ }
50389
+ if (texts?.personalityLocal !== void 0) {
50390
+ this.deps.store.writePersonalityLocal(personaId2, texts.personalityLocal);
50391
+ }
50392
+ this.deps.store.writeMeta(updated);
50393
+ this.deps.registry.set(updated);
50394
+ return updated;
50395
+ }
50396
+ /** 读取 CLAUDE.md 内容;persona 目录或文件不存在时返回 null。透传给 handler 拼响应。 */
50397
+ readPersonality(personaId2) {
50398
+ return this.deps.store.readPersonality(personaId2);
50399
+ }
50400
+ /** 读人格补充层(`.clawd/personality.local.md`);没写过返回 null。供 persona:get 拼响应。 */
50401
+ readPersonalityLocal(personaId2) {
50402
+ return this.deps.store.readPersonalityLocal(personaId2);
50403
+ }
50404
+ /** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
50405
+ listSkills(personaId2) {
50406
+ return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
50407
+ }
50408
+ /**
50409
+ * 读取 persona `.claude/settings.json` 中已启用的插件列表(value === true 的 key)。
50410
+ * 文件不存在 / 解析失败 / 字段缺失 → 空数组。供 persona:get handler 拼响应。
50411
+ */
50412
+ listEnabledPlugins(personaId2) {
50413
+ return this.deps.store.readEnabledPlugins(personaId2);
50414
+ }
50415
+ /** 读 codex guest 沙箱配置(`.clawd/codex-sandbox.json`);缺失 / 坏 → null。透传给 handler 拼响应。 */
50416
+ readCodexSandboxSettings(personaId2) {
50417
+ return this.deps.store.readCodexSandboxSettings(personaId2);
50418
+ }
50419
+ /**
50420
+ * 局部合并写 codex guest 沙箱配置,返回合并后的全量。
50421
+ *
50422
+ * **必须是合并不是覆盖**:UI 的「访客联网」开关只发 `{network}`,整体覆盖会静默抹掉 owner
50423
+ * 手配的 writableRoots / denyRead(丢的是安全边界,且用户不会立刻发现)。
50424
+ * 不走 PersonaManager.update 是因为它管的是 PersonaFile meta + 人格两层文本,
50425
+ * 而这份配置是另一个文件、另一套 schema。
50426
+ *
50427
+ * **读不到时 base 用 CODEX_SANDBOX_DEFAULT 而不是 `{}`**:`{}` 会让这次「合并」实际写出一份
50428
+ * 只有 patch 字段的残缺配置(例如只有 `{network:true}`,没有包管理器缓存目录 → `npm install`
50429
+ * EPERM),而且从此 migrateCodexSandbox 见文件已存在就跳过,UI 上再也补不回来。
50430
+ * 正常路径下文件在 create 时就已物化,这条兜底只在文件被删 / 被改坏时触发。
50431
+ *
50432
+ * ⚠️ 已知限制:`CodexSandboxSettingsSchema` 是 `.strict()` 的,owner 手编时多写一个键
50433
+ * (注释键 / 历史字段)会让整份文件读成 null,于是这次合并把它替换成默认值 ⊕ patch。
50434
+ * 已有测试锁定该 strict 语义(store.spec「schema 校验失败 → 返回 null」),本次不动它——
50435
+ * 至少残缺配置不会再被写出去。要放宽得单独评估。
50436
+ */
50437
+ mergeCodexSandbox(personaId2, patch) {
50438
+ if (!this.deps.registry.get(personaId2)) throw new Error(`persona not found: ${personaId2}`);
50439
+ const base = this.deps.store.readCodexSandboxSettings(personaId2) ?? CODEX_SANDBOX_DEFAULT;
50440
+ const merged = { ...base, ...patch };
50441
+ this.deps.store.writeCodexSandboxSettings(personaId2, merged);
50442
+ return merged;
50443
+ }
50444
+ /** 读 sandbox-settings.json;不存在 / 损坏返回 null。供 persona:get handler 拼响应。 */
50445
+ readSandboxSettings(personaId2) {
50446
+ return this.deps.store.readSandboxSettings(personaId2);
50447
+ }
50448
+ /**
50449
+ * 删除 persona。
50450
+ * PersonaStore.remove(personaId) 级联删整个 <personaRoot>/<personaId>/ 目录
50451
+ * (含 .clawd/sessions/owner/ 和 .clawd/sessions/guests/<capId>/),rmSync
50452
+ * recursive force 一锅清。
50453
+ */
50454
+ delete(personaId2) {
50455
+ this.deps.store.remove(personaId2);
50456
+ this.deps.registry.remove(personaId2);
50457
+ }
50458
+ };
50459
+
50425
50460
  // src/share-md-viewer/load.ts
50426
50461
  var import_node_fs11 = __toESM(require("fs"), 1);
50427
50462
  var import_node_path10 = __toESM(require("path"), 1);
@@ -51154,8 +51189,8 @@ function turnStartInput(text) {
51154
51189
  const items = [];
51155
51190
  let leftover = text;
51156
51191
  for (const m2 of text.matchAll(SKILL_RE)) {
51157
- const [marker, name, path89] = m2;
51158
- items.push({ type: "skill", name, path: path89 });
51192
+ const [marker, name, path91] = m2;
51193
+ items.push({ type: "skill", name, path: path91 });
51159
51194
  leftover = leftover.replace(marker, "");
51160
51195
  }
51161
51196
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -55842,13 +55877,13 @@ function mapSkillsListResponse(res) {
55842
55877
  const r = s ?? {};
55843
55878
  const name = str3(r.name);
55844
55879
  if (!name) continue;
55845
- const path89 = str3(r.path);
55880
+ const path91 = str3(r.path);
55846
55881
  const description = str3(r.description);
55847
55882
  const isPlugin = name.includes(":");
55848
55883
  out.push({
55849
55884
  name,
55850
55885
  source: isPlugin ? "plugin" : "project",
55851
- ...path89 ? { path: path89 } : {},
55886
+ ...path91 ? { path: path91 } : {},
55852
55887
  ...description ? { description } : {},
55853
55888
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
55854
55889
  });
@@ -60170,9 +60205,9 @@ var CentralClientError = class extends Error {
60170
60205
  code;
60171
60206
  cause;
60172
60207
  };
60173
- async function centralRequest(opts, path89, init) {
60208
+ async function centralRequest(opts, path91, init) {
60174
60209
  const f = opts.fetchImpl ?? globalThis.fetch;
60175
- const url = `${opts.api.replace(/\/+$/, "")}${path89}`;
60210
+ const url = `${opts.api.replace(/\/+$/, "")}${path91}`;
60176
60211
  const ctrl = new AbortController();
60177
60212
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
60178
60213
  let res;
@@ -60653,7 +60688,7 @@ var ServerKeyStore = class {
60653
60688
  init_protocol();
60654
60689
 
60655
60690
  // src/handlers/index.ts
60656
- var import_node_path66 = __toESM(require("path"), 1);
60691
+ var import_node_path68 = __toESM(require("path"), 1);
60657
60692
 
60658
60693
  // src/handlers/session.ts
60659
60694
  init_protocol();
@@ -60996,8 +61031,133 @@ function appendImportLedger(dataDir, entry) {
60996
61031
  import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
60997
61032
  }
60998
61033
 
61034
+ // src/tools/transcript-search.ts
61035
+ var import_node_fs48 = __toESM(require("fs"), 1);
61036
+ var import_node_path54 = __toESM(require("path"), 1);
61037
+ var SNIPPET_PAD = 60;
61038
+ var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
61039
+ var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
61040
+ function asRecord(v2) {
61041
+ return typeof v2 === "object" && v2 !== null ? v2 : null;
61042
+ }
61043
+ function textOfBlocks(content, types) {
61044
+ if (!Array.isArray(content)) return null;
61045
+ const parts = [];
61046
+ for (const block of content) {
61047
+ const b2 = asRecord(block);
61048
+ if (!b2 || typeof b2.type !== "string" || !types.includes(b2.type)) continue;
61049
+ const text = b2.text;
61050
+ if (typeof text === "string" && text !== "") parts.push(text);
61051
+ }
61052
+ return parts.length > 0 ? parts.join("\n") : null;
61053
+ }
61054
+ function lineToSearchableText(raw) {
61055
+ const line = asRecord(raw);
61056
+ if (!line) return null;
61057
+ if (line.type === "response_item") {
61058
+ const payload = asRecord(line.payload);
61059
+ if (!payload || payload.type !== "message") return null;
61060
+ const role = payload.role;
61061
+ if (role !== "user" && role !== "assistant") return null;
61062
+ const text2 = textOfBlocks(payload.content, ["input_text", "output_text"]);
61063
+ if (text2 === null) return null;
61064
+ if (role !== "user") return text2;
61065
+ const stripped = text2.replace(CODEX_WRAPPER_RE, "").trim();
61066
+ if (stripped === "") return null;
61067
+ return INJECTED_ENVELOPE_RE.test(stripped) ? null : stripped;
61068
+ }
61069
+ if (line.type !== "user" && line.type !== "assistant") return null;
61070
+ const message = asRecord(line.message);
61071
+ if (!message) return null;
61072
+ const content = message.content;
61073
+ const text = typeof content === "string" && content !== "" ? content : textOfBlocks(content, ["text"]);
61074
+ if (text === null) return null;
61075
+ if (line.type === "user" && (line.isMeta === true || line.isSynthetic === true)) return null;
61076
+ if (line.type === "user" && INJECTED_ENVELOPE_RE.test(text.trimStart())) return null;
61077
+ return text;
61078
+ }
61079
+ function escapeRegExp(s) {
61080
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
61081
+ }
61082
+ function makeSnippet(text, at, needleLength) {
61083
+ const from = Math.max(0, at - SNIPPET_PAD);
61084
+ const to = Math.min(text.length, at + needleLength + SNIPPET_PAD);
61085
+ const body = text.slice(from, to).replace(/\s+/g, " ").trim();
61086
+ return `${from > 0 ? "\u2026 " : ""}${body}${to < text.length ? " \u2026" : ""}`;
61087
+ }
61088
+ function searchTranscriptFile(file, query) {
61089
+ let buf;
61090
+ try {
61091
+ buf = import_node_fs48.default.readFileSync(file);
61092
+ } catch {
61093
+ return null;
61094
+ }
61095
+ const haystack = buf.toString("latin1");
61096
+ const needle = Buffer.from(query, "utf8").toString("latin1");
61097
+ const re = new RegExp(escapeRegExp(needle), "gi");
61098
+ let m2;
61099
+ while ((m2 = re.exec(haystack)) !== null) {
61100
+ const lineStart = haystack.lastIndexOf("\n", m2.index) + 1;
61101
+ let lineEnd = haystack.indexOf("\n", m2.index);
61102
+ if (lineEnd < 0) lineEnd = haystack.length;
61103
+ re.lastIndex = lineEnd + 1;
61104
+ let parsed;
61105
+ try {
61106
+ parsed = JSON.parse(Buffer.from(haystack.slice(lineStart, lineEnd), "latin1").toString("utf8"));
61107
+ } catch {
61108
+ continue;
61109
+ }
61110
+ const text = lineToSearchableText(parsed);
61111
+ if (text === null) continue;
61112
+ const at = text.toLowerCase().indexOf(query.toLowerCase());
61113
+ if (at < 0) continue;
61114
+ return makeSnippet(text, at, query.length);
61115
+ }
61116
+ return null;
61117
+ }
61118
+ var ROLLOUT_NAME_RE = /-([0-9a-fA-F-]{36})\.jsonl$/;
61119
+ function createCodexRolloutLocator(roots) {
61120
+ let index = null;
61121
+ const walk2 = (dir, into) => {
61122
+ let entries;
61123
+ try {
61124
+ entries = import_node_fs48.default.readdirSync(dir, { withFileTypes: true });
61125
+ } catch {
61126
+ return;
61127
+ }
61128
+ for (const entry of entries) {
61129
+ const full = import_node_path54.default.join(dir, entry.name);
61130
+ if (entry.isDirectory()) {
61131
+ walk2(full, into);
61132
+ continue;
61133
+ }
61134
+ const matched = ROLLOUT_NAME_RE.exec(entry.name);
61135
+ if (matched) into.set(matched[1].toLowerCase(), full);
61136
+ }
61137
+ };
61138
+ return (toolSessionId) => {
61139
+ if (index === null) {
61140
+ index = /* @__PURE__ */ new Map();
61141
+ for (const root of roots) walk2(root, index);
61142
+ }
61143
+ return index.get(toolSessionId.toLowerCase()) ?? null;
61144
+ };
61145
+ }
61146
+
60999
61147
  // src/handlers/session.ts
61000
61148
  init_protocol();
61149
+ var import_node_os19 = __toESM(require("os"), 1);
61150
+ var import_node_path55 = __toESM(require("path"), 1);
61151
+ function canReadSearchHit(ctx, file) {
61152
+ if (!ctx || ctx.principal.kind === "owner") return true;
61153
+ return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
61154
+ }
61155
+ var DEFAULT_SEARCH_LIMIT = 9;
61156
+ function codexRolloutRoots(dataDir) {
61157
+ const roots = [import_node_path55.default.join(import_node_os19.default.homedir(), ".codex", "sessions")];
61158
+ if (dataDir) roots.push(import_node_path55.default.join(dataDir, "codex-home", "sessions"));
61159
+ return roots;
61160
+ }
61001
61161
  function buildSessionHandlers(deps) {
61002
61162
  const { manager, observer, getAdapter: getAdapter2, store, ownerPrincipalId } = deps;
61003
61163
  const ensureSessionAccess = (ctx, sessionId, action) => {
@@ -61373,6 +61533,23 @@ ${attribution}` } : args;
61373
61533
  const { response, broadcast } = manager.markRead(args);
61374
61534
  return { response: { type: "session:info", ...response }, broadcast };
61375
61535
  };
61536
+ const searchContent = async (frame, _client, ctx) => {
61537
+ const args = SessionSearchContentArgs.parse(frame);
61538
+ const limit = args.limit ?? DEFAULT_SEARCH_LIMIT;
61539
+ const locateCodexRollout = createCodexRolloutLocator(codexRolloutRoots(deps.dataDir));
61540
+ const matches = [];
61541
+ for (const sessionId of args.sessionIds) {
61542
+ if (matches.length >= limit) break;
61543
+ const file = manager.findOwnedSession(sessionId);
61544
+ if (!file?.toolSessionId) continue;
61545
+ if (!canReadSearchHit(ctx, file)) continue;
61546
+ const transcript = file.tool === "codex" ? locateCodexRollout(file.toolSessionId) : deps.history?.resolveTranscriptFile(file.cwd, file.toolSessionId) ?? null;
61547
+ if (!transcript) continue;
61548
+ const snippet = searchTranscriptFile(transcript, args.query);
61549
+ if (snippet !== null) matches.push({ sessionId, snippet });
61550
+ }
61551
+ return { response: { type: "session:searchContent", matches } };
61552
+ };
61376
61553
  const reorderPins = async (frame) => {
61377
61554
  const args = SessionReorderPinsArgs.parse(frame);
61378
61555
  const { response, broadcast } = manager.reorderPins(args);
@@ -61493,6 +61670,7 @@ ${attribution}` } : args;
61493
61670
  "session:pin": pin,
61494
61671
  "session:archive": archive,
61495
61672
  "session:markRead": markRead,
61673
+ "session:searchContent": searchContent,
61496
61674
  "session:reorderPins": reorderPins,
61497
61675
  "session:answerQuestion": answerQuestion,
61498
61676
  "session:cancelQuestion": cancelQuestion,
@@ -61519,7 +61697,7 @@ function buildPermissionHandlers(deps) {
61519
61697
  }
61520
61698
 
61521
61699
  // src/handlers/history.ts
61522
- var path68 = __toESM(require("path"), 1);
61700
+ var path70 = __toESM(require("path"), 1);
61523
61701
  init_protocol();
61524
61702
 
61525
61703
  // src/session/recent-dirs.ts
@@ -61537,7 +61715,7 @@ function listRecentDirs(store, limit = 50) {
61537
61715
  }
61538
61716
 
61539
61717
  // src/permission/persona-paths.ts
61540
- var path67 = __toESM(require("path"), 1);
61718
+ var path69 = __toESM(require("path"), 1);
61541
61719
  function getAllowedPersonaIds(grants, action) {
61542
61720
  const ids = /* @__PURE__ */ new Set();
61543
61721
  for (const g2 of grants) {
@@ -61550,42 +61728,42 @@ function getAllowedPersonaIds(grants, action) {
61550
61728
  return ids;
61551
61729
  }
61552
61730
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
61553
- const target = path67.resolve(absPath);
61731
+ const target = path69.resolve(absPath);
61554
61732
  if (userWorkDir) {
61555
- const u = path67.resolve(userWorkDir);
61556
- const usep = u.endsWith(path67.sep) ? "" : path67.sep;
61733
+ const u = path69.resolve(userWorkDir);
61734
+ const usep = u.endsWith(path69.sep) ? "" : path69.sep;
61557
61735
  if (target === u || target.startsWith(u + usep)) return true;
61558
61736
  }
61559
- const root = path67.resolve(personaRoot);
61560
- const sep4 = root.endsWith(path67.sep) ? "" : path67.sep;
61737
+ const root = path69.resolve(personaRoot);
61738
+ const sep4 = root.endsWith(path69.sep) ? "" : path69.sep;
61561
61739
  if (!target.startsWith(root + sep4)) return false;
61562
- const rel = path67.relative(root, target);
61740
+ const rel = path69.relative(root, target);
61563
61741
  if (!rel || rel.startsWith("..")) return false;
61564
- const personaId2 = rel.split(path67.sep)[0];
61742
+ const personaId2 = rel.split(path69.sep)[0];
61565
61743
  if (!personaId2) return false;
61566
61744
  const allowed = getAllowedPersonaIds(grants, action);
61567
61745
  if (allowed === "*") return true;
61568
61746
  return allowed.has(personaId2);
61569
61747
  }
61570
61748
  function personaIdFromPath(absPath, personaRoot) {
61571
- const root = path67.resolve(personaRoot);
61572
- const target = path67.resolve(absPath);
61573
- const sep4 = root.endsWith(path67.sep) ? "" : path67.sep;
61749
+ const root = path69.resolve(personaRoot);
61750
+ const target = path69.resolve(absPath);
61751
+ const sep4 = root.endsWith(path69.sep) ? "" : path69.sep;
61574
61752
  if (!target.startsWith(root + sep4)) return null;
61575
- const rel = path67.relative(root, target);
61753
+ const rel = path69.relative(root, target);
61576
61754
  if (!rel || rel.startsWith("..")) return null;
61577
- const id = rel.split(path67.sep)[0];
61755
+ const id = rel.split(path69.sep)[0];
61578
61756
  return id || null;
61579
61757
  }
61580
61758
  function isPathWithin(dir, absPath) {
61581
- const d = path67.resolve(dir);
61582
- const t = path67.resolve(absPath);
61583
- const sep4 = d.endsWith(path67.sep) ? "" : path67.sep;
61759
+ const d = path69.resolve(dir);
61760
+ const t = path69.resolve(absPath);
61761
+ const sep4 = d.endsWith(path69.sep) ? "" : path69.sep;
61584
61762
  return t === d || t.startsWith(d + sep4);
61585
61763
  }
61586
61764
  function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
61587
61765
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
61588
- return personaIdFromPath(path67.resolve(absPath), personaRoot) === personaId2;
61766
+ return personaIdFromPath(path69.resolve(absPath), personaRoot) === personaId2;
61589
61767
  }
61590
61768
 
61591
61769
  // src/handlers/history.ts
@@ -61638,7 +61816,7 @@ function buildHistoryHandlers(deps) {
61638
61816
  if (!pid) return false;
61639
61817
  return isGuestPathAllowed(
61640
61818
  ctx.grants,
61641
- path68.join(personaRoot, pid),
61819
+ path70.join(personaRoot, pid),
61642
61820
  personaRoot,
61643
61821
  "read",
61644
61822
  userWorkDir
@@ -61650,7 +61828,7 @@ function buildHistoryHandlers(deps) {
61650
61828
  };
61651
61829
  const list = async (frame, _client, ctx) => {
61652
61830
  const args = HistoryListArgs.parse(frame);
61653
- assertGuestPath(ctx, path68.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
61831
+ assertGuestPath(ctx, path70.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
61654
61832
  const sessions = await history.listSessions(args);
61655
61833
  return { response: { type: "history:list", sessions } };
61656
61834
  };
@@ -61698,14 +61876,14 @@ function buildHistoryHandlers(deps) {
61698
61876
  };
61699
61877
  const subagents = async (frame, _client, ctx) => {
61700
61878
  const args = HistorySubagentsArgs.parse(frame);
61701
- assertGuestPath(ctx, path68.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
61879
+ assertGuestPath(ctx, path70.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
61702
61880
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
61703
61881
  const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
61704
61882
  return { response: { type: "history:subagents", subagents: subs } };
61705
61883
  };
61706
61884
  const subagentRead = async (frame, _client, ctx) => {
61707
61885
  const args = HistorySubagentReadArgs.parse(frame);
61708
- assertGuestPath(ctx, path68.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
61886
+ assertGuestPath(ctx, path70.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
61709
61887
  assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
61710
61888
  const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
61711
61889
  return { response: { type: "history:subagent-read", ...res } };
@@ -61715,7 +61893,7 @@ function buildHistoryHandlers(deps) {
61715
61893
  if (ctx?.principal.kind === "guest" && personaRoot) {
61716
61894
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
61717
61895
  const filtered = dirs.filter(
61718
- (d) => isGuestPathAllowed(ctx.grants, path68.resolve(d.cwd), personaRoot, "read", userWorkDir)
61896
+ (d) => isGuestPathAllowed(ctx.grants, path70.resolve(d.cwd), personaRoot, "read", userWorkDir)
61719
61897
  );
61720
61898
  return { response: { type: "history:recentDirs", dirs: filtered } };
61721
61899
  }
@@ -61732,17 +61910,17 @@ function buildHistoryHandlers(deps) {
61732
61910
  }
61733
61911
 
61734
61912
  // src/handlers/projects.ts
61735
- var fs63 = __toESM(require("fs"), 1);
61736
- var os20 = __toESM(require("os"), 1);
61737
- var path69 = __toESM(require("path"), 1);
61913
+ var fs64 = __toESM(require("fs"), 1);
61914
+ var os21 = __toESM(require("os"), 1);
61915
+ var path71 = __toESM(require("path"), 1);
61738
61916
  var import_node_child_process13 = require("child_process");
61739
61917
  init_protocol();
61740
- var DEFAULT_PROJECTS_ROOT = path69.join(os20.homedir(), "Documents", "ChatGPT");
61918
+ var DEFAULT_PROJECTS_ROOT = path71.join(os21.homedir(), "Documents", "ChatGPT");
61741
61919
  function allocateDir(root, name) {
61742
- let candidate = path69.join(root, name);
61920
+ let candidate = path71.join(root, name);
61743
61921
  let n = 2;
61744
- while (fs63.existsSync(candidate)) {
61745
- candidate = path69.join(root, `${name} ${n}`);
61922
+ while (fs64.existsSync(candidate)) {
61923
+ candidate = path71.join(root, `${name} ${n}`);
61746
61924
  n += 1;
61747
61925
  }
61748
61926
  return candidate;
@@ -61770,7 +61948,7 @@ function buildProjectHandlers(deps) {
61770
61948
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
61771
61949
  }
61772
61950
  try {
61773
- if (!fs63.statSync(args.path).isDirectory()) throw new Error("not dir");
61951
+ if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
61774
61952
  } catch {
61775
61953
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
61776
61954
  }
@@ -61786,7 +61964,7 @@ function buildProjectHandlers(deps) {
61786
61964
  let target;
61787
61965
  if (args.path) {
61788
61966
  try {
61789
- if (!fs63.statSync(args.path).isDirectory()) throw new Error("not dir");
61967
+ if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
61790
61968
  } catch {
61791
61969
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
61792
61970
  }
@@ -61794,15 +61972,15 @@ function buildProjectHandlers(deps) {
61794
61972
  } else {
61795
61973
  const name = args.name;
61796
61974
  try {
61797
- fs63.mkdirSync(root, { recursive: true });
61975
+ fs64.mkdirSync(root, { recursive: true });
61798
61976
  target = allocateDir(root, name);
61799
- fs63.mkdirSync(target);
61977
+ fs64.mkdirSync(target);
61800
61978
  } catch (err) {
61801
61979
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
61802
61980
  }
61803
61981
  const git = (0, import_node_child_process13.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
61804
61982
  if (git.status !== 0) {
61805
- fs63.rmSync(target, { recursive: true, force: true });
61983
+ fs64.rmSync(target, { recursive: true, force: true });
61806
61984
  throw new ClawdError(
61807
61985
  ERROR_CODES.INVALID_CWD,
61808
61986
  `git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
@@ -61827,8 +62005,8 @@ function buildProjectHandlers(deps) {
61827
62005
  }
61828
62006
 
61829
62007
  // src/handlers/workspace.ts
61830
- var path70 = __toESM(require("path"), 1);
61831
- var os21 = __toESM(require("os"), 1);
62008
+ var path72 = __toESM(require("path"), 1);
62009
+ var os22 = __toESM(require("os"), 1);
61832
62010
  init_protocol();
61833
62011
  init_protocol();
61834
62012
  function buildEnabledPluginNames(personaManager, personaId2) {
@@ -61868,23 +62046,23 @@ function buildWorkspaceHandlers(deps) {
61868
62046
  const list = async (frame, _client, ctx) => {
61869
62047
  const args = WorkspaceListArgs.parse(frame);
61870
62048
  const isGuest = ctx?.principal.kind === "guest";
61871
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os21.homedir();
61872
- const resolvedCwd = path70.resolve(args.cwd ?? fallbackCwd);
61873
- const target = args.path ? path70.resolve(resolvedCwd, args.path) : resolvedCwd;
62049
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os22.homedir();
62050
+ const resolvedCwd = path72.resolve(args.cwd ?? fallbackCwd);
62051
+ const target = args.path ? path72.resolve(resolvedCwd, args.path) : resolvedCwd;
61874
62052
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
61875
62053
  const res = workspace.list({ ...args, cwd: resolvedCwd });
61876
62054
  return { response: { type: "workspace:list", ...res } };
61877
62055
  };
61878
62056
  const read = async (frame, _client, ctx) => {
61879
62057
  const args = WorkspaceReadArgs.parse(frame);
61880
- const target = path70.isAbsolute(args.path) ? path70.resolve(args.path) : path70.resolve(args.cwd, args.path);
62058
+ const target = path72.isAbsolute(args.path) ? path72.resolve(args.path) : path72.resolve(args.cwd, args.path);
61881
62059
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
61882
62060
  const res = workspace.read(args);
61883
62061
  return { response: { type: "workspace:read", ...res } };
61884
62062
  };
61885
62063
  const skillsList = async (frame, _client, ctx) => {
61886
62064
  const args = SkillsListArgs.parse(frame);
61887
- const cwdAbs = path70.resolve(args.cwd);
62065
+ const cwdAbs = path72.resolve(args.cwd);
61888
62066
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
61889
62067
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
61890
62068
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -61896,7 +62074,7 @@ function buildWorkspaceHandlers(deps) {
61896
62074
  };
61897
62075
  const agentsList = async (frame, _client, ctx) => {
61898
62076
  const args = AgentsListArgs.parse(frame);
61899
- const cwdAbs = path70.resolve(args.cwd);
62077
+ const cwdAbs = path72.resolve(args.cwd);
61900
62078
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
61901
62079
  if (args.tool === "codex") {
61902
62080
  return { response: { type: "agents:list", agents: [] } };
@@ -61918,20 +62096,20 @@ function buildWorkspaceHandlers(deps) {
61918
62096
  }
61919
62097
 
61920
62098
  // src/handlers/git.ts
61921
- var path72 = __toESM(require("path"), 1);
62099
+ var path74 = __toESM(require("path"), 1);
61922
62100
  init_protocol();
61923
62101
  init_protocol();
61924
62102
 
61925
62103
  // src/workspace/git.ts
61926
62104
  var import_node_child_process14 = require("child_process");
61927
- var import_node_fs48 = __toESM(require("fs"), 1);
61928
- var import_node_path54 = __toESM(require("path"), 1);
62105
+ var import_node_fs49 = __toESM(require("fs"), 1);
62106
+ var import_node_path56 = __toESM(require("path"), 1);
61929
62107
  var import_node_util = require("util");
61930
62108
  var pexec = (0, import_node_util.promisify)(import_node_child_process14.execFile);
61931
62109
  function normalizePath(p2) {
61932
- const resolved = import_node_path54.default.resolve(p2);
62110
+ const resolved = import_node_path56.default.resolve(p2);
61933
62111
  try {
61934
- return import_node_fs48.default.realpathSync(resolved);
62112
+ return import_node_fs49.default.realpathSync(resolved);
61935
62113
  } catch {
61936
62114
  return resolved;
61937
62115
  }
@@ -62005,7 +62183,7 @@ async function listGitBranches(cwd) {
62005
62183
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
62006
62184
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
62007
62185
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
62008
- if (!isGuestPathAllowed(ctx.grants, path72.resolve(cwd), personaRoot, "read", userWorkDir)) {
62186
+ if (!isGuestPathAllowed(ctx.grants, path74.resolve(cwd), personaRoot, "read", userWorkDir)) {
62009
62187
  throw new ClawdError(
62010
62188
  ERROR_CODES.UNAUTHORIZED,
62011
62189
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -62550,7 +62728,7 @@ function buildFeishuAuthHandlers(deps) {
62550
62728
  }
62551
62729
 
62552
62730
  // src/handlers/meta.ts
62553
- var import_node_os19 = __toESM(require("os"), 1);
62731
+ var import_node_os20 = __toESM(require("os"), 1);
62554
62732
  init_protocol();
62555
62733
 
62556
62734
  // src/handlers/method-grants.ts
@@ -62626,6 +62804,9 @@ var METHOD_GRANT_MAP = {
62626
62804
  "session:pin": CAPABILITY_SCOPED,
62627
62805
  "session:archive": CAPABILITY_SCOPED,
62628
62806
  "session:markRead": CAPABILITY_SCOPED,
62807
+ // 全局搜索扫 transcript 正文。与 history:read 同档:guest 进 persona VM 后要能搜自己的会话,
62808
+ // handler 内仍逐条 ensureSessionAccess,可见面不因 sessionIds 由客户端给定而放大
62809
+ "session:searchContent": CAPABILITY_SCOPED,
62629
62810
  "session:reorderPins": ADMIN_ANY,
62630
62811
  // owner 全局操作,无 personaId 维度
62631
62812
  // mirror peer sessions (2026-05-26):owner-only — guest 不应能写/删本机 mirror SessionFile
@@ -62837,21 +63018,21 @@ function computeMethodAccess(args) {
62837
63018
  }
62838
63019
 
62839
63020
  // src/version.ts
62840
- var version = "0.2.439".length > 0 ? "0.2.439" : "dev";
63021
+ var version = "0.2.441".length > 0 ? "0.2.441" : "dev";
62841
63022
 
62842
63023
  // src/cli-probe/probe.ts
62843
- var fs65 = __toESM(require("fs"), 1);
62844
- var path73 = __toESM(require("path"), 1);
63024
+ var fs66 = __toESM(require("fs"), 1);
63025
+ var path75 = __toESM(require("path"), 1);
62845
63026
  var PKG_NAME = "@clawos-dev/clawd";
62846
63027
  var BIN_NAME = "clawd";
62847
63028
  var MAX_PARENT_HOPS = 5;
62848
63029
  function probeGlobalCli(pathEnv) {
62849
63030
  if (!pathEnv) return null;
62850
- for (const dir of pathEnv.split(path73.delimiter)) {
63031
+ for (const dir of pathEnv.split(path75.delimiter)) {
62851
63032
  if (!dir) continue;
62852
63033
  let real;
62853
63034
  try {
62854
- real = fs65.realpathSync(path73.join(dir, BIN_NAME));
63035
+ real = fs66.realpathSync(path75.join(dir, BIN_NAME));
62855
63036
  } catch {
62856
63037
  continue;
62857
63038
  }
@@ -62861,15 +63042,15 @@ function probeGlobalCli(pathEnv) {
62861
63042
  return null;
62862
63043
  }
62863
63044
  function readOwnPackageVersion(entryPath) {
62864
- let dir = path73.dirname(entryPath);
63045
+ let dir = path75.dirname(entryPath);
62865
63046
  for (let i = 0; i < MAX_PARENT_HOPS; i++) {
62866
63047
  try {
62867
- const raw = fs65.readFileSync(path73.join(dir, "package.json"), "utf8");
63048
+ const raw = fs66.readFileSync(path75.join(dir, "package.json"), "utf8");
62868
63049
  const pkg = JSON.parse(raw);
62869
63050
  if (pkg.name !== PKG_NAME) return null;
62870
63051
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
62871
63052
  } catch {
62872
- const parent = path73.dirname(dir);
63053
+ const parent = path75.dirname(dir);
62873
63054
  if (parent === dir) return null;
62874
63055
  dir = parent;
62875
63056
  }
@@ -62905,7 +63086,7 @@ function buildReadyFrame(deps, client) {
62905
63086
  return {
62906
63087
  version,
62907
63088
  protocolVersion: PROTOCOL_VERSION,
62908
- hostname: import_node_os19.default.hostname(),
63089
+ hostname: import_node_os20.default.hostname(),
62909
63090
  os: process.platform,
62910
63091
  tools,
62911
63092
  runningSessions: info.runningSessions,
@@ -63021,16 +63202,8 @@ function buildPersonaHandlers(deps) {
63021
63202
  const args = parseArgs2(PersonaUpdateArgsSchema, frame, "persona:update");
63022
63203
  const { personality, personalityLocal, codexSandbox, ...metaPatch } = args.patch;
63023
63204
  const persona = personaManager.update(args.personaId, metaPatch, { personality, personalityLocal });
63024
- const mergedCodexSandbox = codexSandbox ? personaManager.mergeCodexSandbox(args.personaId, codexSandbox) : void 0;
63025
- return {
63026
- response: {
63027
- type: "persona:info",
63028
- ...persona,
63029
- // 只在本次确实动过时回带,让调用方拿到合并后的真值而不用再 get 一次;
63030
- // 没动就不带(与 personality 等分层字段同口径:persona:update 的响应是 meta 视图)。
63031
- ...mergedCodexSandbox ? { codexSandbox: mergedCodexSandbox } : {}
63032
- }
63033
- };
63205
+ if (codexSandbox) personaManager.mergeCodexSandbox(args.personaId, codexSandbox);
63206
+ return { response: { type: "persona:info", ...persona } };
63034
63207
  };
63035
63208
  const del = async (frame) => {
63036
63209
  const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:delete");
@@ -63049,7 +63222,7 @@ function buildPersonaHandlers(deps) {
63049
63222
  }
63050
63223
 
63051
63224
  // src/handlers/attachment.ts
63052
- var import_node_path55 = __toESM(require("path"), 1);
63225
+ var import_node_path57 = __toESM(require("path"), 1);
63053
63226
  init_protocol();
63054
63227
  init_protocol();
63055
63228
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -63129,12 +63302,12 @@ function buildAttachmentHandlers(deps) {
63129
63302
  `session ${args.sessionId} scope unresolved`
63130
63303
  );
63131
63304
  }
63132
- const cwdAbs = import_node_path55.default.resolve(sessionFile.cwd);
63133
- const candidateAbs = import_node_path55.default.isAbsolute(args.relPath) ? import_node_path55.default.resolve(args.relPath) : import_node_path55.default.resolve(cwdAbs, args.relPath);
63305
+ const cwdAbs = import_node_path57.default.resolve(sessionFile.cwd);
63306
+ const candidateAbs = import_node_path57.default.isAbsolute(args.relPath) ? import_node_path57.default.resolve(args.relPath) : import_node_path57.default.resolve(cwdAbs, args.relPath);
63134
63307
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
63135
63308
  const entries = deps.groupFileStore.list(scope, args.sessionId);
63136
63309
  const entry = entries.find((e) => {
63137
- const storedAbs = import_node_path55.default.isAbsolute(e.relPath) ? import_node_path55.default.resolve(e.relPath) : import_node_path55.default.resolve(cwdAbs, e.relPath);
63310
+ const storedAbs = import_node_path57.default.isAbsolute(e.relPath) ? import_node_path57.default.resolve(e.relPath) : import_node_path57.default.resolve(cwdAbs, e.relPath);
63138
63311
  return storedAbs === candidateAbs && !e.stale;
63139
63312
  });
63140
63313
  if (!entry) {
@@ -63159,7 +63332,7 @@ function buildAttachmentHandlers(deps) {
63159
63332
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
63160
63333
  const f = deps.sessionStore.read(sessionId);
63161
63334
  if (!f) return;
63162
- assertGuestAttachmentPath(ctx, import_node_path55.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
63335
+ assertGuestAttachmentPath(ctx, import_node_path57.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
63163
63336
  }
63164
63337
  const groupAdd = async (frame, _client, ctx) => {
63165
63338
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -63174,8 +63347,8 @@ function buildAttachmentHandlers(deps) {
63174
63347
  if (!scope) {
63175
63348
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
63176
63349
  }
63177
- const cwdAbs = import_node_path55.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
63178
- const candidateAbs = import_node_path55.default.isAbsolute(args.relPath) ? import_node_path55.default.resolve(args.relPath) : import_node_path55.default.resolve(cwdAbs, args.relPath);
63350
+ const cwdAbs = import_node_path57.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
63351
+ const candidateAbs = import_node_path57.default.isAbsolute(args.relPath) ? import_node_path57.default.resolve(args.relPath) : import_node_path57.default.resolve(cwdAbs, args.relPath);
63179
63352
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
63180
63353
  const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
63181
63354
  const size = 0;
@@ -63234,19 +63407,19 @@ function buildAttachmentHandlers(deps) {
63234
63407
 
63235
63408
  // src/handlers/extension.ts
63236
63409
  var import_promises12 = __toESM(require("fs/promises"), 1);
63237
- var import_node_path60 = __toESM(require("path"), 1);
63410
+ var import_node_path62 = __toESM(require("path"), 1);
63238
63411
  init_protocol();
63239
63412
 
63240
63413
  // src/extension/bundle-zip.ts
63241
63414
  var import_promises9 = __toESM(require("fs/promises"), 1);
63242
- var import_node_path56 = __toESM(require("path"), 1);
63415
+ var import_node_path58 = __toESM(require("path"), 1);
63243
63416
  var import_node_crypto17 = __toESM(require("crypto"), 1);
63244
63417
  var import_jszip2 = __toESM(require_lib3(), 1);
63245
63418
  async function bundleExtensionDir(dir) {
63246
63419
  const entries = await listFilesSorted(dir);
63247
63420
  const zip = new import_jszip2.default();
63248
63421
  for (const rel of entries) {
63249
- const abs = import_node_path56.default.join(dir, rel);
63422
+ const abs = import_node_path58.default.join(dir, rel);
63250
63423
  const content = await import_promises9.default.readFile(abs);
63251
63424
  zip.file(rel, content, { date: FIXED_DATE });
63252
63425
  }
@@ -63267,7 +63440,7 @@ async function listFilesSorted(rootDir) {
63267
63440
  return out;
63268
63441
  }
63269
63442
  async function walk(absRoot, relPrefix, out) {
63270
- const dirAbs = import_node_path56.default.join(absRoot, relPrefix);
63443
+ const dirAbs = import_node_path58.default.join(absRoot, relPrefix);
63271
63444
  const entries = await import_promises9.default.readdir(dirAbs, { withFileTypes: true });
63272
63445
  for (const e of entries) {
63273
63446
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -63321,25 +63494,25 @@ function computePublishCheck(args) {
63321
63494
 
63322
63495
  // src/extension/install-flow.ts
63323
63496
  var import_promises10 = __toESM(require("fs/promises"), 1);
63324
- var import_node_path58 = __toESM(require("path"), 1);
63325
- var import_node_os21 = __toESM(require("os"), 1);
63497
+ var import_node_path60 = __toESM(require("path"), 1);
63498
+ var import_node_os22 = __toESM(require("os"), 1);
63326
63499
  var import_node_crypto18 = __toESM(require("crypto"), 1);
63327
63500
  var import_jszip3 = __toESM(require_lib3(), 1);
63328
63501
 
63329
63502
  // src/extension/paths.ts
63330
- var import_node_os20 = __toESM(require("os"), 1);
63331
- var import_node_path57 = __toESM(require("path"), 1);
63503
+ var import_node_os21 = __toESM(require("os"), 1);
63504
+ var import_node_path59 = __toESM(require("path"), 1);
63332
63505
  function clawdHomeRoot(override) {
63333
- return override ?? process.env.CLAWD_HOME ?? import_node_path57.default.join(import_node_os20.default.homedir(), ".clawd");
63506
+ return override ?? process.env.CLAWD_HOME ?? import_node_path59.default.join(import_node_os21.default.homedir(), ".clawd");
63334
63507
  }
63335
63508
  function extensionsRoot(override) {
63336
- return import_node_path57.default.join(clawdHomeRoot(override), "extensions");
63509
+ return import_node_path59.default.join(clawdHomeRoot(override), "extensions");
63337
63510
  }
63338
63511
  function publishedChannelsFile(override) {
63339
- return import_node_path57.default.join(clawdHomeRoot(override), "extensions-published.json");
63512
+ return import_node_path59.default.join(clawdHomeRoot(override), "extensions-published.json");
63340
63513
  }
63341
63514
  function bundleCacheRoot(override) {
63342
- return import_node_path57.default.join(clawdHomeRoot(override), "extension-bundles");
63515
+ return import_node_path59.default.join(clawdHomeRoot(override), "extension-bundles");
63343
63516
  }
63344
63517
 
63345
63518
  // src/extension/install-flow.ts
@@ -63366,7 +63539,7 @@ async function installFromChannel(args, deps) {
63366
63539
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
63367
63540
  }
63368
63541
  for (const name of Object.keys(zip.files)) {
63369
- if (name.includes("..") || name.startsWith("/") || import_node_path58.default.isAbsolute(name)) {
63542
+ if (name.includes("..") || name.startsWith("/") || import_node_path60.default.isAbsolute(name)) {
63370
63543
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
63371
63544
  }
63372
63545
  }
@@ -63398,7 +63571,7 @@ async function installFromChannel(args, deps) {
63398
63571
  );
63399
63572
  }
63400
63573
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
63401
- const destDir = import_node_path58.default.join(deps.extensionsRoot, localExtId);
63574
+ const destDir = import_node_path60.default.join(deps.extensionsRoot, localExtId);
63402
63575
  let destExists = false;
63403
63576
  try {
63404
63577
  await import_promises10.default.access(destDir);
@@ -63412,16 +63585,16 @@ async function installFromChannel(args, deps) {
63412
63585
  );
63413
63586
  }
63414
63587
  const stage = await import_promises10.default.mkdtemp(
63415
- import_node_path58.default.join(import_node_os21.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
63588
+ import_node_path60.default.join(import_node_os22.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
63416
63589
  );
63417
63590
  try {
63418
63591
  for (const [name, entry] of Object.entries(zip.files)) {
63419
- const dest = import_node_path58.default.join(stage, name);
63592
+ const dest = import_node_path60.default.join(stage, name);
63420
63593
  if (entry.dir) {
63421
63594
  await import_promises10.default.mkdir(dest, { recursive: true });
63422
63595
  continue;
63423
63596
  }
63424
- await import_promises10.default.mkdir(import_node_path58.default.dirname(dest), { recursive: true });
63597
+ await import_promises10.default.mkdir(import_node_path60.default.dirname(dest), { recursive: true });
63425
63598
  if (name === "manifest.json") {
63426
63599
  const rewritten = { ...parsed.data, id: localExtId };
63427
63600
  await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -63442,8 +63615,8 @@ async function installFromChannel(args, deps) {
63442
63615
 
63443
63616
  // src/extension/update-flow.ts
63444
63617
  var import_promises11 = __toESM(require("fs/promises"), 1);
63445
- var import_node_path59 = __toESM(require("path"), 1);
63446
- var import_node_os22 = __toESM(require("os"), 1);
63618
+ var import_node_path61 = __toESM(require("path"), 1);
63619
+ var import_node_os23 = __toESM(require("os"), 1);
63447
63620
  var import_node_crypto19 = __toESM(require("crypto"), 1);
63448
63621
  var import_jszip4 = __toESM(require_lib3(), 1);
63449
63622
  var UpdateError = class extends Error {
@@ -63459,11 +63632,11 @@ async function updateFromChannel(args, deps) {
63459
63632
  channelRef.extId,
63460
63633
  channelRef.ownerPrincipalId
63461
63634
  );
63462
- const liveDir = import_node_path59.default.join(deps.extensionsRoot, localExtId);
63635
+ const liveDir = import_node_path61.default.join(deps.extensionsRoot, localExtId);
63463
63636
  const prevDir = `${liveDir}.prev`;
63464
63637
  let existingVersion;
63465
63638
  try {
63466
- const raw = await import_promises11.default.readFile(import_node_path59.default.join(liveDir, "manifest.json"), "utf8");
63639
+ const raw = await import_promises11.default.readFile(import_node_path61.default.join(liveDir, "manifest.json"), "utf8");
63467
63640
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
63468
63641
  if (!parsed2.success) {
63469
63642
  throw new UpdateError(
@@ -63496,7 +63669,7 @@ async function updateFromChannel(args, deps) {
63496
63669
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
63497
63670
  }
63498
63671
  for (const name of Object.keys(zip.files)) {
63499
- if (name.includes("..") || name.startsWith("/") || import_node_path59.default.isAbsolute(name)) {
63672
+ if (name.includes("..") || name.startsWith("/") || import_node_path61.default.isAbsolute(name)) {
63500
63673
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
63501
63674
  }
63502
63675
  }
@@ -63531,16 +63704,16 @@ async function updateFromChannel(args, deps) {
63531
63704
  await import_promises11.default.rm(prevDir, { recursive: true, force: true });
63532
63705
  await import_promises11.default.rename(liveDir, prevDir);
63533
63706
  const stage = await import_promises11.default.mkdtemp(
63534
- import_node_path59.default.join(import_node_os22.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
63707
+ import_node_path61.default.join(import_node_os23.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
63535
63708
  );
63536
63709
  try {
63537
63710
  for (const [name, entry] of Object.entries(zip.files)) {
63538
- const dest = import_node_path59.default.join(stage, name);
63711
+ const dest = import_node_path61.default.join(stage, name);
63539
63712
  if (entry.dir) {
63540
63713
  await import_promises11.default.mkdir(dest, { recursive: true });
63541
63714
  continue;
63542
63715
  }
63543
- await import_promises11.default.mkdir(import_node_path59.default.dirname(dest), { recursive: true });
63716
+ await import_promises11.default.mkdir(import_node_path61.default.dirname(dest), { recursive: true });
63544
63717
  if (name === "manifest.json") {
63545
63718
  const rewritten = { ...parsed.data, id: localExtId };
63546
63719
  await import_promises11.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -63607,7 +63780,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
63607
63780
  );
63608
63781
  }
63609
63782
  }
63610
- const manifestPath = import_node_path60.default.join(root, extId, "manifest.json");
63783
+ const manifestPath = import_node_path62.default.join(root, extId, "manifest.json");
63611
63784
  const manifest = await readManifest(root, extId);
63612
63785
  const next = { ...manifest, version: newVersion };
63613
63786
  const tmp = `${manifestPath}.tmp`;
@@ -63615,7 +63788,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
63615
63788
  await import_promises12.default.rename(tmp, manifestPath);
63616
63789
  }
63617
63790
  async function readManifest(root, extId) {
63618
- const file = import_node_path60.default.join(root, extId, "manifest.json");
63791
+ const file = import_node_path62.default.join(root, extId, "manifest.json");
63619
63792
  let raw;
63620
63793
  try {
63621
63794
  raw = await import_promises12.default.readFile(file, "utf8");
@@ -63699,7 +63872,7 @@ function buildExtensionHandlers(deps) {
63699
63872
  };
63700
63873
  async function buildSnapshotMeta(extId) {
63701
63874
  const manifest = await readManifest(deps.root, extId);
63702
- const { sha256, buffer } = await bundleExtensionDir(import_node_path60.default.join(deps.root, extId));
63875
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path62.default.join(deps.root, extId));
63703
63876
  return { manifest, contentHash: sha256, buffer };
63704
63877
  }
63705
63878
  const publish = async (frame, _client, ctx) => {
@@ -63874,9 +64047,9 @@ function buildExtensionHandlers(deps) {
63874
64047
  }
63875
64048
 
63876
64049
  // src/app-builder/project-store.ts
63877
- var import_node_fs49 = require("fs");
64050
+ var import_node_fs50 = require("fs");
63878
64051
  var import_node_child_process15 = require("child_process");
63879
- var import_node_path61 = require("path");
64052
+ var import_node_path63 = require("path");
63880
64053
  init_protocol();
63881
64054
  var PROJECTS_DIR = "projects";
63882
64055
  var META_FILE = ".clawd-project.json";
@@ -63890,19 +64063,19 @@ var ProjectStore = class {
63890
64063
  root;
63891
64064
  /** projects/<name>/.clawd-project.json 路径 */
63892
64065
  metaPath(name) {
63893
- return (0, import_node_path61.join)(this.projectsRoot(), name, META_FILE);
64066
+ return (0, import_node_path63.join)(this.projectsRoot(), name, META_FILE);
63894
64067
  }
63895
64068
  /** projects/<name>/ 目录路径(cwd 用) */
63896
64069
  projectDir(name) {
63897
- return (0, import_node_path61.join)(this.projectsRoot(), name);
64070
+ return (0, import_node_path63.join)(this.projectsRoot(), name);
63898
64071
  }
63899
64072
  projectsRoot() {
63900
- return (0, import_node_path61.join)(this.root, PROJECTS_DIR);
64073
+ return (0, import_node_path63.join)(this.root, PROJECTS_DIR);
63901
64074
  }
63902
64075
  async list() {
63903
64076
  let entries;
63904
64077
  try {
63905
- entries = await import_node_fs49.promises.readdir(this.projectsRoot());
64078
+ entries = await import_node_fs50.promises.readdir(this.projectsRoot());
63906
64079
  } catch (err) {
63907
64080
  if (err.code === "ENOENT") return [];
63908
64081
  throw err;
@@ -63910,7 +64083,7 @@ var ProjectStore = class {
63910
64083
  const out = [];
63911
64084
  for (const name of entries) {
63912
64085
  try {
63913
- const raw = await import_node_fs49.promises.readFile(this.metaPath(name), "utf8");
64086
+ const raw = await import_node_fs50.promises.readFile(this.metaPath(name), "utf8");
63914
64087
  const json = JSON.parse(raw);
63915
64088
  let migrated = false;
63916
64089
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -63921,7 +64094,7 @@ var ProjectStore = class {
63921
64094
  if (parsed.success) {
63922
64095
  out.push(parsed.data);
63923
64096
  if (migrated) {
63924
- void import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
64097
+ void import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
63925
64098
  });
63926
64099
  }
63927
64100
  }
@@ -63965,8 +64138,8 @@ var ProjectStore = class {
63965
64138
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
63966
64139
  }
63967
64140
  const dir = this.projectDir(name);
63968
- await import_node_fs49.promises.mkdir(dir, { recursive: true });
63969
- await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
64141
+ await import_node_fs50.promises.mkdir(dir, { recursive: true });
64142
+ await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
63970
64143
  return meta;
63971
64144
  }
63972
64145
  /**
@@ -64009,7 +64182,7 @@ var ProjectStore = class {
64009
64182
  }
64010
64183
  async delete(name) {
64011
64184
  const dir = this.projectDir(name);
64012
- await import_node_fs49.promises.rm(dir, { recursive: true, force: true });
64185
+ await import_node_fs50.promises.rm(dir, { recursive: true, force: true });
64013
64186
  }
64014
64187
  async updatePort(name, newPort) {
64015
64188
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -64025,7 +64198,7 @@ var ProjectStore = class {
64025
64198
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
64026
64199
  }
64027
64200
  const updated = { ...target, port: newPort };
64028
- await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
64201
+ await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
64029
64202
  return updated;
64030
64203
  }
64031
64204
  /**
@@ -64042,7 +64215,7 @@ var ProjectStore = class {
64042
64215
  if (!validated.success) {
64043
64216
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
64044
64217
  }
64045
- await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64218
+ await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64046
64219
  return validated.data;
64047
64220
  }
64048
64221
  /**
@@ -64063,7 +64236,7 @@ var ProjectStore = class {
64063
64236
  if (!validated.success) {
64064
64237
  throw new Error(`invalid publishJob: ${validated.error.message}`);
64065
64238
  }
64066
- await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64239
+ await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64067
64240
  return validated.data;
64068
64241
  }
64069
64242
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -64078,7 +64251,7 @@ var ProjectStore = class {
64078
64251
  if (!validated.success) {
64079
64252
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
64080
64253
  }
64081
- await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64254
+ await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
64082
64255
  return validated.data;
64083
64256
  }
64084
64257
  };
@@ -64199,8 +64372,8 @@ var PublishJobRegistry = class {
64199
64372
 
64200
64373
  // src/app-builder/publish-job-runner.ts
64201
64374
  var import_node_child_process17 = require("child_process");
64202
- var import_node_fs50 = require("fs");
64203
- var import_node_path62 = require("path");
64375
+ var import_node_fs51 = require("fs");
64376
+ var import_node_path64 = require("path");
64204
64377
 
64205
64378
  // src/app-builder/publish-stage-parser.ts
64206
64379
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -64232,10 +64405,10 @@ async function startPublishJob(deps, args) {
64232
64405
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
64233
64406
  }
64234
64407
  const projDir = projectDir(args.name);
64235
- const logPath = (0, import_node_path62.join)(projDir, ".publish.log");
64408
+ const logPath = (0, import_node_path64.join)(projDir, ".publish.log");
64236
64409
  let logStream = null;
64237
64410
  try {
64238
- logStream = (0, import_node_fs50.createWriteStream)(logPath, { flags: "w" });
64411
+ logStream = (0, import_node_fs51.createWriteStream)(logPath, { flags: "w" });
64239
64412
  } catch {
64240
64413
  logStream = null;
64241
64414
  }
@@ -64492,8 +64665,8 @@ async function recoverInterruptedJobs(deps) {
64492
64665
 
64493
64666
  // src/handlers/app-builder.ts
64494
64667
  init_protocol();
64495
- var import_node_path63 = require("path");
64496
- var import_node_fs51 = require("fs");
64668
+ var import_node_path65 = require("path");
64669
+ var import_node_fs52 = require("fs");
64497
64670
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
64498
64671
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
64499
64672
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -64574,7 +64747,7 @@ function buildAppBuilderHandlers(deps) {
64574
64747
  async function listAllUsersProjects() {
64575
64748
  if (!deps.usersRoot || !deps.getStore) return [];
64576
64749
  const getStore = deps.getStore;
64577
- const userIds = await import_node_fs51.promises.readdir(deps.usersRoot).catch(() => []);
64750
+ const userIds = await import_node_fs52.promises.readdir(deps.usersRoot).catch(() => []);
64578
64751
  const perUser = await Promise.all(
64579
64752
  userIds.map((uid) => getStore(uid).list().catch(() => []))
64580
64753
  );
@@ -64643,8 +64816,8 @@ function buildAppBuilderHandlers(deps) {
64643
64816
  const project = await userStore.create(f.name, reservedPorts);
64644
64817
  try {
64645
64818
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
64646
- const templateSrcDir = (0, import_node_path63.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
64647
- const scaffoldScript = (0, import_node_path63.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
64819
+ const templateSrcDir = (0, import_node_path65.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
64820
+ const scaffoldScript = (0, import_node_path65.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
64648
64821
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
64649
64822
  deps.logger?.info("app-builder.scaffold.done", {
64650
64823
  name: project.name,
@@ -64848,7 +65021,7 @@ function buildAppBuilderHandlers(deps) {
64848
65021
  await userStore.clearPublishJob(args.name);
64849
65022
  }
64850
65023
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
64851
- const scriptPath = (0, import_node_path63.join)(deps.deployKitRoot, "scripts", "publish.sh");
65024
+ const scriptPath = (0, import_node_path65.join)(deps.deployKitRoot, "scripts", "publish.sh");
64852
65025
  deps.logger?.info("app-builder.publish.start", {
64853
65026
  name: args.name,
64854
65027
  sessionId: boundSession.sessionId,
@@ -65404,20 +65577,20 @@ function mapPrState(state, isDraft) {
65404
65577
  if (state === "CLOSED") return "closed";
65405
65578
  return isDraft === true ? "draft" : "open";
65406
65579
  }
65407
- function asRecord(v2) {
65580
+ function asRecord2(v2) {
65408
65581
  return typeof v2 === "object" && v2 !== null ? v2 : {};
65409
65582
  }
65410
65583
  function lastCommitRollup(node) {
65411
- const first = asRecord(node.commits).nodes?.[0];
65412
- return asRecord(asRecord(first).commit).statusCheckRollup;
65584
+ const first = asRecord2(node.commits).nodes?.[0];
65585
+ return asRecord2(asRecord2(first).commit).statusCheckRollup;
65413
65586
  }
65414
65587
  function parsePrListResponse(json) {
65415
- const nodes = asRecord(asRecord(asRecord(json).data).search).nodes ?? [];
65588
+ const nodes = asRecord2(asRecord2(asRecord2(json).data).search).nodes ?? [];
65416
65589
  const items = [];
65417
65590
  for (const raw of nodes) {
65418
- const n = asRecord(raw);
65591
+ const n = asRecord2(raw);
65419
65592
  if (typeof n.number !== "number") continue;
65420
- const nameWithOwner = String(asRecord(n.repository).nameWithOwner ?? "");
65593
+ const nameWithOwner = String(asRecord2(n.repository).nameWithOwner ?? "");
65421
65594
  const slash = nameWithOwner.indexOf("/");
65422
65595
  if (slash <= 0) continue;
65423
65596
  const rollup = lastCommitRollup(n);
@@ -65431,27 +65604,27 @@ function parsePrListResponse(json) {
65431
65604
  additions: typeof n.additions === "number" ? n.additions : 0,
65432
65605
  deletions: typeof n.deletions === "number" ? n.deletions : 0,
65433
65606
  updatedAt: String(n.updatedAt ?? ""),
65434
- author: String(asRecord(n.author).login ?? ""),
65435
- checksRollup: rollup == null ? "none" : mapRollupState(asRecord(rollup).state)
65607
+ author: String(asRecord2(n.author).login ?? ""),
65608
+ checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state)
65436
65609
  });
65437
65610
  }
65438
65611
  return items;
65439
65612
  }
65440
65613
  function parsePrDetailResponse(json, repoRef) {
65441
- const pr = asRecord(asRecord(asRecord(json).data).repository).pullRequest;
65614
+ const pr = asRecord2(asRecord2(asRecord2(json).data).repository).pullRequest;
65442
65615
  if (pr == null || typeof pr !== "object") return null;
65443
- const n = asRecord(pr);
65616
+ const n = asRecord2(pr);
65444
65617
  const rollup = lastCommitRollup(n);
65445
- const contextNodes = asRecord(asRecord(rollup).contexts).nodes ?? [];
65618
+ const contextNodes = asRecord2(asRecord2(rollup).contexts).nodes ?? [];
65446
65619
  const checks = [];
65447
65620
  for (const c of contextNodes) {
65448
- const mapped = mapCheckNode(asRecord(c));
65621
+ const mapped = mapCheckNode(asRecord2(c));
65449
65622
  if (mapped) checks.push(mapped);
65450
65623
  }
65451
- const reviewerNodes = asRecord(n.reviewRequests).nodes ?? [];
65452
- const reviewers = reviewerNodes.map((r) => String(asRecord(asRecord(r).requestedReviewer).login ?? "")).filter((s) => s !== "");
65624
+ const reviewerNodes = asRecord2(n.reviewRequests).nodes ?? [];
65625
+ const reviewers = reviewerNodes.map((r) => String(asRecord2(asRecord2(r).requestedReviewer).login ?? "")).filter((s) => s !== "");
65453
65626
  const mergeable = n.mergeable === "MERGEABLE" ? "mergeable" : n.mergeable === "CONFLICTING" ? "conflicting" : "unknown";
65454
- const commentCountRaw = asRecord(n.comments).totalCount;
65627
+ const commentCountRaw = asRecord2(n.comments).totalCount;
65455
65628
  return {
65456
65629
  owner: repoRef.owner,
65457
65630
  repo: repoRef.repo,
@@ -65459,7 +65632,7 @@ function parsePrDetailResponse(json, repoRef) {
65459
65632
  title: String(n.title ?? ""),
65460
65633
  body: String(n.body ?? ""),
65461
65634
  state: mapPrState(n.state, n.isDraft),
65462
- author: String(asRecord(n.author).login ?? ""),
65635
+ author: String(asRecord2(n.author).login ?? ""),
65463
65636
  updatedAt: String(n.updatedAt ?? ""),
65464
65637
  headRef: String(n.headRefName ?? ""),
65465
65638
  baseRef: String(n.baseRefName ?? ""),
@@ -65469,7 +65642,7 @@ function parsePrDetailResponse(json, repoRef) {
65469
65642
  mergeable,
65470
65643
  reviewers,
65471
65644
  commentCount: typeof commentCountRaw === "number" ? commentCountRaw : 0,
65472
- checksRollup: rollup == null ? "none" : mapRollupState(asRecord(rollup).state),
65645
+ checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state),
65473
65646
  checks
65474
65647
  };
65475
65648
  }
@@ -65607,7 +65780,7 @@ function buildVisitorHandlers(deps) {
65607
65780
 
65608
65781
  // src/extension/registry.ts
65609
65782
  var import_promises14 = __toESM(require("fs/promises"), 1);
65610
- var import_node_path64 = __toESM(require("path"), 1);
65783
+ var import_node_path66 = __toESM(require("path"), 1);
65611
65784
  async function loadAll(root) {
65612
65785
  let entries;
65613
65786
  try {
@@ -65620,13 +65793,13 @@ async function loadAll(root) {
65620
65793
  for (const ent of entries) {
65621
65794
  if (!ent.isDirectory()) continue;
65622
65795
  if (ent.name.startsWith(".")) continue;
65623
- records.push(await loadOne(import_node_path64.default.join(root, ent.name), ent.name));
65796
+ records.push(await loadOne(import_node_path66.default.join(root, ent.name), ent.name));
65624
65797
  }
65625
65798
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
65626
65799
  return records;
65627
65800
  }
65628
65801
  async function loadOne(dir, dirName) {
65629
- const manifestPath = import_node_path64.default.join(dir, "manifest.json");
65802
+ const manifestPath = import_node_path66.default.join(dir, "manifest.json");
65630
65803
  let raw;
65631
65804
  try {
65632
65805
  raw = await import_promises14.default.readFile(manifestPath, "utf8");
@@ -65671,7 +65844,7 @@ async function loadOne(dir, dirName) {
65671
65844
 
65672
65845
  // src/extension/uninstall.ts
65673
65846
  var import_promises15 = __toESM(require("fs/promises"), 1);
65674
- var import_node_path65 = __toESM(require("path"), 1);
65847
+ var import_node_path67 = __toESM(require("path"), 1);
65675
65848
  var UninstallError = class extends Error {
65676
65849
  constructor(code, message) {
65677
65850
  super(message);
@@ -65680,7 +65853,7 @@ var UninstallError = class extends Error {
65680
65853
  code;
65681
65854
  };
65682
65855
  async function uninstall(deps) {
65683
- const dir = import_node_path65.default.join(deps.root, deps.extId);
65856
+ const dir = import_node_path67.default.join(deps.root, deps.extId);
65684
65857
  try {
65685
65858
  await import_promises15.default.access(dir);
65686
65859
  } catch {
@@ -65698,14 +65871,14 @@ init_protocol();
65698
65871
 
65699
65872
  // src/peer-ops/run-command.ts
65700
65873
  var import_node_child_process18 = require("child_process");
65701
- var import_node_os23 = __toESM(require("os"), 1);
65874
+ var import_node_os24 = __toESM(require("os"), 1);
65702
65875
  var DEFAULT_TIMEOUT_MS5 = 3e4;
65703
65876
  var MAX_TIMEOUT_MS = 3e5;
65704
65877
  var MAX_OUTPUT_BYTES = 1048576;
65705
65878
  function runCommand(command, opts = {}) {
65706
65879
  const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
65707
65880
  return new Promise((resolve9) => {
65708
- const child = (0, import_node_child_process18.spawn)("bash", ["-c", command], { cwd: import_node_os23.default.homedir() });
65881
+ const child = (0, import_node_child_process18.spawn)("bash", ["-c", command], { cwd: import_node_os24.default.homedir() });
65709
65882
  const out = [];
65710
65883
  const err = [];
65711
65884
  let outBytes = 0;
@@ -65913,7 +66086,7 @@ function buildMethodHandlers(deps) {
65913
66086
  broadcast: deps.broadcastToOwners
65914
66087
  }),
65915
66088
  ...buildMasterHandlers({
65916
- authorityTablePath: import_node_path66.default.join(deps.masterDataDir, "master-authority.json")
66089
+ authorityTablePath: import_node_path68.default.join(deps.masterDataDir, "master-authority.json")
65917
66090
  }),
65918
66091
  ...buildTopicHandlers({
65919
66092
  topicStore: deps.topicStore,
@@ -65949,18 +66122,18 @@ init_claude();
65949
66122
 
65950
66123
  // src/tools/shell-path.ts
65951
66124
  var import_node_child_process19 = require("child_process");
65952
- var import_node_os24 = __toESM(require("os"), 1);
66125
+ var import_node_os25 = __toESM(require("os"), 1);
65953
66126
  function refreshPathFromLoginShell() {
65954
66127
  if (process.platform === "win32") return;
65955
- const shell = process.env.SHELL ?? import_node_os24.default.userInfo().shell ?? "/bin/zsh";
66128
+ const shell = process.env.SHELL ?? import_node_os25.default.userInfo().shell ?? "/bin/zsh";
65956
66129
  try {
65957
66130
  const out = (0, import_node_child_process19.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
65958
66131
  encoding: "utf8",
65959
66132
  timeout: 3e3,
65960
66133
  stdio: ["ignore", "pipe", "ignore"]
65961
66134
  });
65962
- const path89 = out.trim();
65963
- if (path89) process.env.PATH = path89;
66135
+ const path91 = out.trim();
66136
+ if (path91) process.env.PATH = path91;
65964
66137
  } catch {
65965
66138
  }
65966
66139
  }
@@ -66374,7 +66547,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
66374
66547
 
66375
66548
  // src/extension/runtime.ts
66376
66549
  var import_node_child_process22 = require("child_process");
66377
- var import_node_path67 = __toESM(require("path"), 1);
66550
+ var import_node_path69 = __toESM(require("path"), 1);
66378
66551
  var import_promises16 = require("timers/promises");
66379
66552
 
66380
66553
  // src/extension/port-allocator.ts
@@ -66475,7 +66648,7 @@ var Runtime = class {
66475
66648
  /\$CLAWOS_EXT_PORT/g,
66476
66649
  String(port)
66477
66650
  );
66478
- const dir = import_node_path67.default.join(this.root, extId);
66651
+ const dir = import_node_path69.default.join(this.root, extId);
66479
66652
  const env = {
66480
66653
  ...process.env,
66481
66654
  CLAWOS_EXT_PORT: String(port),
@@ -66587,7 +66760,7 @@ ${handle.stderrTail}`
66587
66760
 
66588
66761
  // src/extension/published-channels.ts
66589
66762
  var import_promises17 = __toESM(require("fs/promises"), 1);
66590
- var import_node_path68 = __toESM(require("path"), 1);
66763
+ var import_node_path70 = __toESM(require("path"), 1);
66591
66764
  init_zod();
66592
66765
  var PublishedChannelsError = class extends Error {
66593
66766
  constructor(code, message) {
@@ -66686,7 +66859,7 @@ var PublishedChannelStore = class {
66686
66859
  )
66687
66860
  };
66688
66861
  const tmp = `${this.filePath}.tmp`;
66689
- await import_promises17.default.mkdir(import_node_path68.default.dirname(this.filePath), { recursive: true });
66862
+ await import_promises17.default.mkdir(import_node_path70.default.dirname(this.filePath), { recursive: true });
66690
66863
  await import_promises17.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
66691
66864
  await import_promises17.default.rename(tmp, this.filePath);
66692
66865
  }
@@ -66694,7 +66867,7 @@ var PublishedChannelStore = class {
66694
66867
 
66695
66868
  // src/extension/bundle-cache.ts
66696
66869
  var import_promises18 = __toESM(require("fs/promises"), 1);
66697
- var import_node_path69 = __toESM(require("path"), 1);
66870
+ var import_node_path71 = __toESM(require("path"), 1);
66698
66871
  var BundleCache = class {
66699
66872
  constructor(rootDir) {
66700
66873
  this.rootDir = rootDir;
@@ -66703,14 +66876,14 @@ var BundleCache = class {
66703
66876
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
66704
66877
  async write(snapshotHash, buffer) {
66705
66878
  await import_promises18.default.mkdir(this.rootDir, { recursive: true });
66706
- const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
66879
+ const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
66707
66880
  const tmp = `${file}.tmp`;
66708
66881
  await import_promises18.default.writeFile(tmp, buffer, { mode: 384 });
66709
66882
  await import_promises18.default.rename(tmp, file);
66710
66883
  }
66711
66884
  /** Returns the bundle bytes, or null when the file doesn't exist. */
66712
66885
  async read(snapshotHash) {
66713
- const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
66886
+ const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
66714
66887
  try {
66715
66888
  return await import_promises18.default.readFile(file);
66716
66889
  } catch (e) {
@@ -66720,7 +66893,7 @@ var BundleCache = class {
66720
66893
  }
66721
66894
  /** Idempotent — missing file is not an error. */
66722
66895
  async delete(snapshotHash) {
66723
- const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
66896
+ const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
66724
66897
  await import_promises18.default.rm(file, { force: true });
66725
66898
  }
66726
66899
  };
@@ -66741,26 +66914,26 @@ async function startDaemon(config) {
66741
66914
  },
66742
66915
  source: "daemon",
66743
66916
  sampling: logShippingCfg.sampling,
66744
- homeDir: import_node_os25.default.homedir()
66917
+ homeDir: import_node_os26.default.homedir()
66745
66918
  });
66746
- const logDir = import_node_path70.default.join(config.dataDir, "log");
66747
- import_node_fs52.default.mkdirSync(logDir, { recursive: true });
66919
+ const logDir = import_node_path72.default.join(config.dataDir, "log");
66920
+ import_node_fs53.default.mkdirSync(logDir, { recursive: true });
66748
66921
  const logger = createLogger({
66749
66922
  level: config.logLevel,
66750
- file: import_node_path70.default.join(logDir, "clawd.log"),
66923
+ file: import_node_path72.default.join(logDir, "clawd.log"),
66751
66924
  logClient
66752
66925
  });
66753
66926
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
66754
66927
  const screenIdleProbeLogger = createFileOnlyLogger({
66755
- file: import_node_path70.default.join(logDir, "screen-idle-probe.log"),
66928
+ file: import_node_path72.default.join(logDir, "screen-idle-probe.log"),
66756
66929
  level: "debug"
66757
66930
  });
66758
66931
  logger.info("screen-idle probe logger enabled", {
66759
- file: import_node_path70.default.join(logDir, "screen-idle-probe.log")
66932
+ file: import_node_path72.default.join(logDir, "screen-idle-probe.log")
66760
66933
  });
66761
66934
  const CAP_TARGETS = [
66762
- import_node_path70.default.join(logDir, "clawd.log"),
66763
- import_node_path70.default.join(logDir, "screen-idle-probe.log")
66935
+ import_node_path72.default.join(logDir, "clawd.log"),
66936
+ import_node_path72.default.join(logDir, "screen-idle-probe.log")
66764
66937
  ];
66765
66938
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
66766
66939
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -66882,8 +67055,8 @@ async function startDaemon(config) {
66882
67055
  const agents = new AgentsScanner();
66883
67056
  const history = new ClaudeHistoryReader();
66884
67057
  let transport = null;
66885
- const personaStore = new PersonaStore(import_node_path70.default.join(config.dataDir, "personas"));
66886
- const usersRoot = import_node_path70.default.join(config.dataDir, "users");
67058
+ const personaStore = new PersonaStore(import_node_path72.default.join(config.dataDir, "personas"));
67059
+ const usersRoot = import_node_path72.default.join(config.dataDir, "users");
66887
67060
  const defaultsRoot = findDefaultsRoot(logger);
66888
67061
  if (defaultsRoot) {
66889
67062
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -66907,7 +67080,7 @@ async function startDaemon(config) {
66907
67080
  retirePersonaBuilder({ store: personaStore, logger });
66908
67081
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
66909
67082
  const dispatchStore = createDispatchStore({
66910
- filePath: import_node_path70.default.join(config.dataDir, "dispatch.json"),
67083
+ filePath: import_node_path72.default.join(config.dataDir, "dispatch.json"),
66911
67084
  now: () => Date.now(),
66912
67085
  onFlushError: (err) => logger.error("dispatch store flush failed", {
66913
67086
  reason: err instanceof Error ? err.message : String(err)
@@ -66916,7 +67089,7 @@ async function startDaemon(config) {
66916
67089
  await dispatchStore.load();
66917
67090
  dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
66918
67091
  const channelStore = createChannelStore({
66919
- filePath: import_node_path70.default.join(config.dataDir, "channels.json"),
67092
+ filePath: import_node_path72.default.join(config.dataDir, "channels.json"),
66920
67093
  now: () => Date.now(),
66921
67094
  genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
66922
67095
  onFlushError: (err) => logger.error("channel store flush failed", {
@@ -66925,7 +67098,7 @@ async function startDaemon(config) {
66925
67098
  });
66926
67099
  await channelStore.load();
66927
67100
  const topicStore = createTopicStore({
66928
- filePath: import_node_path70.default.join(config.dataDir, "topics.json"),
67101
+ filePath: import_node_path72.default.join(config.dataDir, "topics.json"),
66929
67102
  now: () => Date.now(),
66930
67103
  genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
66931
67104
  onFlushError: (err) => logger.error("topic store flush failed", {
@@ -66952,18 +67125,18 @@ async function startDaemon(config) {
66952
67125
  });
66953
67126
  }
66954
67127
  });
66955
- const here = typeof __dirname === "string" ? __dirname : import_node_path70.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
67128
+ const here = typeof __dirname === "string" ? __dirname : import_node_path72.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
66956
67129
  const mcpConfigs = [];
66957
67130
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
66958
67131
  const dispatchServerCandidates = [
66959
- import_node_path70.default.join(here, "dispatch", "mcp-server.cjs"),
67132
+ import_node_path72.default.join(here, "dispatch", "mcp-server.cjs"),
66960
67133
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
66961
- import_node_path70.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
67134
+ import_node_path72.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
66962
67135
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
66963
67136
  ];
66964
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67137
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
66965
67138
  if (dispatchServerScriptPath) {
66966
- const dispatchLogPath = import_node_path70.default.join(logDir, "dispatch-mcp-server.log");
67139
+ const dispatchLogPath = import_node_path72.default.join(logDir, "dispatch-mcp-server.log");
66967
67140
  const dispatchCfgPath = writeDispatchMcpConfig({
66968
67141
  dataDir: config.dataDir,
66969
67142
  serverScriptPath: dispatchServerScriptPath,
@@ -66983,12 +67156,12 @@ async function startDaemon(config) {
66983
67156
  });
66984
67157
  }
66985
67158
  const ticketServerCandidates = [
66986
- import_node_path70.default.join(here, "ticket", "mcp-server.cjs"),
66987
- import_node_path70.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
67159
+ import_node_path72.default.join(here, "ticket", "mcp-server.cjs"),
67160
+ import_node_path72.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
66988
67161
  ];
66989
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67162
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
66990
67163
  if (ticketServerScriptPath) {
66991
- const ticketLogPath = import_node_path70.default.join(logDir, "ticket-mcp-server.log");
67164
+ const ticketLogPath = import_node_path72.default.join(logDir, "ticket-mcp-server.log");
66992
67165
  const ticketCfgPath = writeTicketMcpConfig({
66993
67166
  dataDir: config.dataDir,
66994
67167
  serverScriptPath: ticketServerScriptPath,
@@ -67010,12 +67183,12 @@ async function startDaemon(config) {
67010
67183
  });
67011
67184
  }
67012
67185
  const shiftServerCandidates = [
67013
- import_node_path70.default.join(here, "shift", "mcp-server.cjs"),
67014
- import_node_path70.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
67186
+ import_node_path72.default.join(here, "shift", "mcp-server.cjs"),
67187
+ import_node_path72.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
67015
67188
  ];
67016
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67189
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
67017
67190
  if (shiftServerScriptPath) {
67018
- const shiftLogPath = import_node_path70.default.join(logDir, "shift-mcp-server.log");
67191
+ const shiftLogPath = import_node_path72.default.join(logDir, "shift-mcp-server.log");
67019
67192
  const shiftCfgPath = await writeShiftMcpConfig({
67020
67193
  dataDir: config.dataDir,
67021
67194
  serverScriptPath: shiftServerScriptPath,
@@ -67036,12 +67209,12 @@ async function startDaemon(config) {
67036
67209
  );
67037
67210
  }
67038
67211
  const inboxServerCandidates = [
67039
- import_node_path70.default.join(here, "inbox", "mcp-server.cjs"),
67040
- import_node_path70.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
67212
+ import_node_path72.default.join(here, "inbox", "mcp-server.cjs"),
67213
+ import_node_path72.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
67041
67214
  ];
67042
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67215
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
67043
67216
  if (inboxServerScriptPath) {
67044
- const inboxLogPath = import_node_path70.default.join(logDir, "inbox-mcp-server.log");
67217
+ const inboxLogPath = import_node_path72.default.join(logDir, "inbox-mcp-server.log");
67045
67218
  const inboxCfgPath = await writeInboxMcpConfig({
67046
67219
  dataDir: config.dataDir,
67047
67220
  serverScriptPath: inboxServerScriptPath,
@@ -67062,10 +67235,10 @@ async function startDaemon(config) {
67062
67235
  );
67063
67236
  }
67064
67237
  const peerOpsServerCandidates = [
67065
- import_node_path70.default.join(here, "peer-ops", "mcp-server.cjs"),
67066
- import_node_path70.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
67238
+ import_node_path72.default.join(here, "peer-ops", "mcp-server.cjs"),
67239
+ import_node_path72.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
67067
67240
  ];
67068
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67241
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
67069
67242
  if (peerOpsServerScriptPath) {
67070
67243
  const peerOpsCfgPath = writePeerOpsMcpConfig({
67071
67244
  dataDir: config.dataDir,
@@ -67085,12 +67258,12 @@ async function startDaemon(config) {
67085
67258
  );
67086
67259
  }
67087
67260
  const rpcToolServerCandidates = [
67088
- import_node_path70.default.join(here, "rpc-tool", "mcp-server.cjs"),
67089
- import_node_path70.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
67261
+ import_node_path72.default.join(here, "rpc-tool", "mcp-server.cjs"),
67262
+ import_node_path72.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
67090
67263
  ];
67091
- const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
67264
+ const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
67092
67265
  if (rpcToolServerScriptPath) {
67093
- const rpcToolLogPath = import_node_path70.default.join(logDir, "rpc-tool-mcp-server.log");
67266
+ const rpcToolLogPath = import_node_path72.default.join(logDir, "rpc-tool-mcp-server.log");
67094
67267
  const rpcToolCfgPath = writeRpcToolMcpConfig({
67095
67268
  dataDir: config.dataDir,
67096
67269
  serverScriptPath: rpcToolServerScriptPath,
@@ -67111,7 +67284,7 @@ async function startDaemon(config) {
67111
67284
  );
67112
67285
  }
67113
67286
  const shiftStore = createShiftStore({
67114
- filePath: import_node_path70.default.join(config.dataDir, "shift.json"),
67287
+ filePath: import_node_path72.default.join(config.dataDir, "shift.json"),
67115
67288
  ownerIdProvider: () => ownerPrincipalId,
67116
67289
  now: () => Date.now()
67117
67290
  });
@@ -67133,7 +67306,7 @@ async function startDaemon(config) {
67133
67306
  getAdapter,
67134
67307
  historyReader: history,
67135
67308
  dataDir: config.dataDir,
67136
- personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
67309
+ personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
67137
67310
  // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
67138
67311
  // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
67139
67312
  getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
@@ -67187,10 +67360,10 @@ async function startDaemon(config) {
67187
67360
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
67188
67361
  attachmentGroup: {
67189
67362
  onFileEdit: (input) => {
67190
- const absPath = import_node_path70.default.isAbsolute(input.relPath) ? input.relPath : import_node_path70.default.join(input.cwd, input.relPath);
67363
+ const absPath = import_node_path72.default.isAbsolute(input.relPath) ? input.relPath : import_node_path72.default.join(input.cwd, input.relPath);
67191
67364
  let size = 0;
67192
67365
  try {
67193
- size = import_node_fs52.default.statSync(absPath).size;
67366
+ size = import_node_fs53.default.statSync(absPath).size;
67194
67367
  } catch (err) {
67195
67368
  logger.warn("attachment.onFileEdit stat failed", {
67196
67369
  sessionId: input.sessionId,
@@ -67220,9 +67393,9 @@ async function startDaemon(config) {
67220
67393
  logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
67221
67394
  }
67222
67395
  const projectsStore = new ProjectsStore({
67223
- file: import_node_path70.default.join(config.dataDir, "projects.json"),
67396
+ file: import_node_path72.default.join(config.dataDir, "projects.json"),
67224
67397
  clawdDir: config.dataDir,
67225
- codexStateFile: import_node_path70.default.join(import_node_os25.default.homedir(), ".codex", ".codex-global-state.json"),
67398
+ codexStateFile: import_node_path72.default.join(import_node_os26.default.homedir(), ".codex", ".codex-global-state.json"),
67226
67399
  logger
67227
67400
  });
67228
67401
  const observer = new SessionObserver({
@@ -67282,13 +67455,13 @@ async function startDaemon(config) {
67282
67455
  screenIdleProbeLogger
67283
67456
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
67284
67457
  registerAdapter("claude", claudeAdapter);
67285
- const codexIsolatedHome = import_node_path70.default.join(config.dataDir, "codex-home");
67458
+ const codexIsolatedHome = import_node_path72.default.join(config.dataDir, "codex-home");
67286
67459
  try {
67287
- import_node_fs52.default.mkdirSync(codexIsolatedHome, { recursive: true });
67460
+ import_node_fs53.default.mkdirSync(codexIsolatedHome, { recursive: true });
67288
67461
  for (const f of ["auth.json", "config.toml"]) {
67289
- const link = import_node_path70.default.join(codexIsolatedHome, f);
67290
- const target = import_node_path70.default.join(import_node_os25.default.homedir(), ".codex", f);
67291
- if (!import_node_fs52.default.existsSync(link) && import_node_fs52.default.existsSync(target)) import_node_fs52.default.symlinkSync(target, link);
67462
+ const link = import_node_path72.default.join(codexIsolatedHome, f);
67463
+ const target = import_node_path72.default.join(import_node_os26.default.homedir(), ".codex", f);
67464
+ if (!import_node_fs53.default.existsSync(link) && import_node_fs53.default.existsSync(target)) import_node_fs53.default.symlinkSync(target, link);
67292
67465
  }
67293
67466
  } catch (err) {
67294
67467
  logger.warn("codex isolated home setup failed", { err: String(err) });
@@ -67301,11 +67474,11 @@ async function startDaemon(config) {
67301
67474
  // projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
67302
67475
  codexHomeFor: (cwd) => resolveCodexHome({
67303
67476
  cwd,
67304
- personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
67477
+ personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
67305
67478
  // 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
67306
67479
  // Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
67307
67480
  projectPaths: projectsStore.listMerged().map((x) => x.path),
67308
- sharedHome: import_node_path70.default.join(import_node_os25.default.homedir(), ".codex"),
67481
+ sharedHome: import_node_path72.default.join(import_node_os26.default.homedir(), ".codex"),
67309
67482
  isolatedHome: codexIsolatedHome
67310
67483
  })
67311
67484
  })
@@ -67589,11 +67762,11 @@ async function startDaemon(config) {
67589
67762
  // 'persona/<pid>/owner',default 走 'default'。
67590
67763
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
67591
67764
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
67592
- personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
67765
+ personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
67593
67766
  usersRoot
67594
67767
  },
67595
67768
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
67596
- personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
67769
+ personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
67597
67770
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
67598
67771
  usersRoot,
67599
67772
  // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
@@ -67692,11 +67865,11 @@ async function startDaemon(config) {
67692
67865
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
67693
67866
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
67694
67867
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
67695
- appBuilderPersonaRoot: import_node_path70.default.join(config.dataDir, "personas", "persona-app-builder"),
67868
+ appBuilderPersonaRoot: import_node_path72.default.join(config.dataDir, "personas", "persona-app-builder"),
67696
67869
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
67697
- deployKitRoot: import_node_path70.default.join(config.dataDir, "deploy-kit"),
67870
+ deployKitRoot: import_node_path72.default.join(config.dataDir, "deploy-kit"),
67698
67871
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
67699
- resolvePersonaRoot: (personaId2) => import_node_path70.default.join(config.dataDir, "personas", personaId2),
67872
+ resolvePersonaRoot: (personaId2) => import_node_path72.default.join(config.dataDir, "personas", personaId2),
67700
67873
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
67701
67874
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
67702
67875
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -67751,7 +67924,7 @@ async function startDaemon(config) {
67751
67924
  sourceSessionId: args.sourceSessionId
67752
67925
  });
67753
67926
  const sourceFile = manager.findOwnedSession(args.sourceSessionId);
67754
- const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os25.default.homedir());
67927
+ const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os26.default.homedir());
67755
67928
  logger.info("dispatch.spawnB.source-resolved", {
67756
67929
  dispatchId: args.dispatchId,
67757
67930
  sourceJsonlPath,
@@ -67817,7 +67990,7 @@ async function startDaemon(config) {
67817
67990
  });
67818
67991
  shiftScheduler.start();
67819
67992
  logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
67820
- const larkBotStore = createLarkBotBindingStore(import_node_path70.default.join(config.dataDir, "personas"));
67993
+ const larkBotStore = createLarkBotBindingStore(import_node_path72.default.join(config.dataDir, "personas"));
67821
67994
  const larkBotCloud = createLarkBotCloudClient({
67822
67995
  api: config.clawosApi ?? DEFAULT_CLAWOS_API,
67823
67996
  apiKey: resolveClawdTicketsApiKey(),
@@ -67831,7 +68004,7 @@ async function startDaemon(config) {
67831
68004
  store: larkBotStore,
67832
68005
  fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
67833
68006
  // 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
67834
- mediaRootFor: (chatId) => import_node_path70.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
68007
+ mediaRootFor: (chatId) => import_node_path72.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
67835
68008
  isShuttingDown: () => larkDraining,
67836
68009
  logger: {
67837
68010
  warn: (msg) => logger.warn(msg),
@@ -68136,8 +68309,8 @@ async function startDaemon(config) {
68136
68309
  const lines = [
68137
68310
  `Tunnel: ${r.url}`,
68138
68311
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
68139
- `Frpc config: ${import_node_path70.default.join(config.dataDir, "frpc.toml")}`,
68140
- `Frpc log: ${import_node_path70.default.join(logDir, "frpc.log")}`
68312
+ `Frpc config: ${import_node_path72.default.join(config.dataDir, "frpc.toml")}`,
68313
+ `Frpc log: ${import_node_path72.default.join(logDir, "frpc.log")}`
68141
68314
  ];
68142
68315
  const width2 = Math.max(...lines.map((l) => l.length));
68143
68316
  const bar = "\u2550".repeat(width2 + 4);
@@ -68150,8 +68323,8 @@ ${bar}
68150
68323
 
68151
68324
  `);
68152
68325
  try {
68153
- const connectPath = import_node_path70.default.join(config.dataDir, "connect.txt");
68154
- import_node_fs52.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
68326
+ const connectPath = import_node_path72.default.join(config.dataDir, "connect.txt");
68327
+ import_node_fs53.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
68155
68328
  } catch {
68156
68329
  }
68157
68330
  } catch (err) {
@@ -68238,9 +68411,9 @@ ${bar}
68238
68411
  };
68239
68412
  }
68240
68413
  function migrateDropPersonsDir(dataDir) {
68241
- const dir = import_node_path70.default.join(dataDir, "persons");
68414
+ const dir = import_node_path72.default.join(dataDir, "persons");
68242
68415
  try {
68243
- import_node_fs52.default.rmSync(dir, { recursive: true, force: true });
68416
+ import_node_fs53.default.rmSync(dir, { recursive: true, force: true });
68244
68417
  } catch {
68245
68418
  }
68246
68419
  }