@clawos-dev/clawd 0.2.134 → 0.2.135-beta.280.568890f

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
@@ -4508,6 +4508,9 @@ var init_persona_schemas = __esm({
4508
4508
  // 8-key set defined UI-side in `lib/session-icons.ts`; protocol stays plain string
4509
4509
  // for forward compatibility, consumer fallbacks to default when key not found.
4510
4510
  iconKey: external_exports.string().optional(),
4511
+ // 绑定的 agent tool('claude' / 'codex');缺省消费侧按 'claude' 兜底。
4512
+ // 与 model 平行:persona 新建 session 的默认 tool,可平滑切换。
4513
+ tool: external_exports.string().optional(),
4511
4514
  createdAt: external_exports.number(),
4512
4515
  updatedAt: external_exports.number()
4513
4516
  }).strict();
@@ -4558,6 +4561,7 @@ var init_persona_schemas = __esm({
4558
4561
  label: external_exports.string().min(1),
4559
4562
  personality: external_exports.string(),
4560
4563
  model: external_exports.string().optional(),
4564
+ tool: external_exports.string().optional(),
4561
4565
  public: external_exports.boolean().optional(),
4562
4566
  iconKey: external_exports.string().optional()
4563
4567
  }).strict();
@@ -4569,6 +4573,7 @@ var init_persona_schemas = __esm({
4569
4573
  patch: external_exports.object({
4570
4574
  label: external_exports.string().min(1).optional(),
4571
4575
  model: external_exports.string().optional(),
4576
+ tool: external_exports.string().optional(),
4572
4577
  personality: external_exports.string().optional(),
4573
4578
  public: external_exports.boolean().optional(),
4574
4579
  // pass `null` to clear; daemon strips the field from PersonaFile on null
@@ -4579,7 +4584,7 @@ var init_persona_schemas = __esm({
4579
4584
  });
4580
4585
 
4581
4586
  // ../protocol/src/schemas.ts
4582
- var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, 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;
4587
+ var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionSubscribeArgs, SessionPinArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, 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;
4583
4588
  var init_schemas = __esm({
4584
4589
  "../protocol/src/schemas.ts"() {
4585
4590
  "use strict";
@@ -4637,12 +4642,23 @@ var init_schemas = __esm({
4637
4642
  CapabilitiesGetArgs = external_exports.object({
4638
4643
  tool: external_exports.string().min(1)
4639
4644
  });
4645
+ ToolFeaturesSchema = external_exports.object({
4646
+ rewind: external_exports.boolean(),
4647
+ subagents: external_exports.boolean(),
4648
+ tui: external_exports.boolean(),
4649
+ observe: external_exports.boolean(),
4650
+ fileSharing: external_exports.boolean(),
4651
+ // fork:session:fork 走 forkSession(claude jsonl 专用,派生新 jsonl)。codex 无 claude jsonl
4652
+ // → fork 不可用。UI 据此 gate assistant 消息上的 fork 按钮(codex 一轮多条消息会刷出一堆按钮且点了报错)。
4653
+ fork: external_exports.boolean()
4654
+ });
4640
4655
  CapabilitiesResponseSchema = external_exports.object({
4641
4656
  tool: external_exports.string().min(1),
4642
4657
  toolSessionIdLabel: external_exports.string().optional(),
4643
4658
  models: external_exports.array(ModelInfoSchema),
4644
4659
  permissionModes: external_exports.array(ModeInfoSchema),
4645
- configSchema: external_exports.array(ConfigFieldSchemaSchema)
4660
+ configSchema: external_exports.array(ConfigFieldSchemaSchema),
4661
+ features: ToolFeaturesSchema
4646
4662
  });
4647
4663
  AllowRuleSchema = external_exports.object({
4648
4664
  tool: external_exports.string().min(1),
@@ -5034,7 +5050,11 @@ var init_schemas = __esm({
5034
5050
  });
5035
5051
  PermissionRespondArgs = external_exports.object({
5036
5052
  sessionId: external_exports.string().min(1),
5037
- requestId: external_exports.string().min(1),
5053
+ // 权限请求 id 用 `permissionRequestId`,**不能**叫 `requestId`:WS 传输层用帧顶层的
5054
+ // `requestId` 做 RPC 请求/响应关联(daemon-client 发帧时 `{...args, type, requestId}`,
5055
+ // 传输 id 在最后会覆盖 args 同名字段)。若沿用 `requestId`,权限 id 会被传输 id(如 "r61")
5056
+ // 覆盖,daemon 查 pendingPermissions 永远 miss → 点了允许一直卡住。
5057
+ permissionRequestId: external_exports.string().min(1),
5038
5058
  allow: external_exports.boolean(),
5039
5059
  permanent: external_exports.boolean().optional(),
5040
5060
  pattern: external_exports.string().optional()
@@ -5065,7 +5085,7 @@ var init_schemas = __esm({
5065
5085
  cwd: external_exports.string().min(1),
5066
5086
  path: external_exports.string().min(1)
5067
5087
  });
5068
- SkillsListArgs = external_exports.object({ cwd: external_exports.string().min(1) });
5088
+ SkillsListArgs = external_exports.object({ cwd: external_exports.string().min(1), tool: external_exports.string().optional() });
5069
5089
  SkillEntrySchema = external_exports.object({
5070
5090
  name: external_exports.string().min(1),
5071
5091
  source: external_exports.enum(SKILL_SOURCE_VALUES),
@@ -5081,7 +5101,7 @@ var init_schemas = __esm({
5081
5101
  whenToUse: external_exports.string().optional(),
5082
5102
  plugin: external_exports.string().optional()
5083
5103
  });
5084
- AgentsListArgs = external_exports.object({ cwd: external_exports.string().min(1) });
5104
+ AgentsListArgs = external_exports.object({ cwd: external_exports.string().min(1), tool: external_exports.string().optional() });
5085
5105
  AgentsListResponseSchema = external_exports.object({
5086
5106
  agents: external_exports.array(AgentEntrySchema)
5087
5107
  });
@@ -6842,10 +6862,10 @@ var require_redaction = __commonJS({
6842
6862
  var strict = false;
6843
6863
  function redaction(opts, serialize) {
6844
6864
  const { paths, censor, remove } = handle(opts);
6845
- const shape = paths.reduce((o, str) => {
6865
+ const shape = paths.reduce((o, str4) => {
6846
6866
  rx.lastIndex = 0;
6847
- const first = rx.exec(str);
6848
- const next = rx.exec(str);
6867
+ const first = rx.exec(str4);
6868
+ const next = rx.exec(str4);
6849
6869
  let ns = first[1] !== void 0 ? first[1].replace(/^(?:"|'|`)(.*)(?:"|'|`)$/, "$1") : first[0];
6850
6870
  if (ns === "*") {
6851
6871
  ns = wildcardFirstSym;
@@ -6858,7 +6878,7 @@ var require_redaction = __commonJS({
6858
6878
  return o;
6859
6879
  }
6860
6880
  const { index } = next;
6861
- const nextPath = `${str.substr(index, str.length - 1)}`;
6881
+ const nextPath = `${str4.substr(index, str4.length - 1)}`;
6862
6882
  o[ns] = o[ns] || [];
6863
6883
  if (ns !== wildcardFirstSym && o[ns].length === 0) {
6864
6884
  o[ns].push(...o[wildcardFirstSym] || []);
@@ -6974,7 +6994,7 @@ var require_quick_format_unescaped = __commonJS({
6974
6994
  }
6975
6995
  var argLen = args.length;
6976
6996
  if (argLen === 0) return f;
6977
- var str = "";
6997
+ var str4 = "";
6978
6998
  var a = 1 - offset;
6979
6999
  var lastPos = -1;
6980
7000
  var flen = f && f.length || 0;
@@ -6989,8 +7009,8 @@ var require_quick_format_unescaped = __commonJS({
6989
7009
  break;
6990
7010
  if (args[a] == null) break;
6991
7011
  if (lastPos < i)
6992
- str += f.slice(lastPos, i);
6993
- str += Number(args[a]);
7012
+ str4 += f.slice(lastPos, i);
7013
+ str4 += Number(args[a]);
6994
7014
  lastPos = i + 2;
6995
7015
  i++;
6996
7016
  break;
@@ -6999,8 +7019,8 @@ var require_quick_format_unescaped = __commonJS({
6999
7019
  break;
7000
7020
  if (args[a] == null) break;
7001
7021
  if (lastPos < i)
7002
- str += f.slice(lastPos, i);
7003
- str += Math.floor(Number(args[a]));
7022
+ str4 += f.slice(lastPos, i);
7023
+ str4 += Math.floor(Number(args[a]));
7004
7024
  lastPos = i + 2;
7005
7025
  i++;
7006
7026
  break;
@@ -7013,21 +7033,21 @@ var require_quick_format_unescaped = __commonJS({
7013
7033
  break;
7014
7034
  if (args[a] === void 0) break;
7015
7035
  if (lastPos < i)
7016
- str += f.slice(lastPos, i);
7036
+ str4 += f.slice(lastPos, i);
7017
7037
  var type = typeof args[a];
7018
7038
  if (type === "string") {
7019
- str += "'" + args[a] + "'";
7039
+ str4 += "'" + args[a] + "'";
7020
7040
  lastPos = i + 2;
7021
7041
  i++;
7022
7042
  break;
7023
7043
  }
7024
7044
  if (type === "function") {
7025
- str += args[a].name || "<anonymous>";
7045
+ str4 += args[a].name || "<anonymous>";
7026
7046
  lastPos = i + 2;
7027
7047
  i++;
7028
7048
  break;
7029
7049
  }
7030
- str += ss(args[a]);
7050
+ str4 += ss(args[a]);
7031
7051
  lastPos = i + 2;
7032
7052
  i++;
7033
7053
  break;
@@ -7035,15 +7055,15 @@ var require_quick_format_unescaped = __commonJS({
7035
7055
  if (a >= argLen)
7036
7056
  break;
7037
7057
  if (lastPos < i)
7038
- str += f.slice(lastPos, i);
7039
- str += String(args[a]);
7058
+ str4 += f.slice(lastPos, i);
7059
+ str4 += String(args[a]);
7040
7060
  lastPos = i + 2;
7041
7061
  i++;
7042
7062
  break;
7043
7063
  case 37:
7044
7064
  if (lastPos < i)
7045
- str += f.slice(lastPos, i);
7046
- str += "%";
7065
+ str4 += f.slice(lastPos, i);
7066
+ str4 += "%";
7047
7067
  lastPos = i + 2;
7048
7068
  i++;
7049
7069
  a--;
@@ -7056,9 +7076,9 @@ var require_quick_format_unescaped = __commonJS({
7056
7076
  if (lastPos === -1)
7057
7077
  return f;
7058
7078
  else if (lastPos < flen) {
7059
- str += f.slice(lastPos);
7079
+ str4 += f.slice(lastPos);
7060
7080
  }
7061
- return str;
7081
+ return str4;
7062
7082
  }
7063
7083
  }
7064
7084
  });
@@ -7102,7 +7122,7 @@ var require_atomic_sleep = __commonJS({
7102
7122
  var require_sonic_boom = __commonJS({
7103
7123
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7104
7124
  "use strict";
7105
- var fs50 = require("fs");
7125
+ var fs51 = require("fs");
7106
7126
  var EventEmitter3 = require("events");
7107
7127
  var inherits = require("util").inherits;
7108
7128
  var path59 = require("path");
@@ -7159,20 +7179,20 @@ var require_sonic_boom = __commonJS({
7159
7179
  const mode = sonic.mode;
7160
7180
  if (sonic.sync) {
7161
7181
  try {
7162
- if (sonic.mkdir) fs50.mkdirSync(path59.dirname(file), { recursive: true });
7163
- const fd = fs50.openSync(file, flags, mode);
7182
+ if (sonic.mkdir) fs51.mkdirSync(path59.dirname(file), { recursive: true });
7183
+ const fd = fs51.openSync(file, flags, mode);
7164
7184
  fileOpened(null, fd);
7165
7185
  } catch (err) {
7166
7186
  fileOpened(err);
7167
7187
  throw err;
7168
7188
  }
7169
7189
  } else if (sonic.mkdir) {
7170
- fs50.mkdir(path59.dirname(file), { recursive: true }, (err) => {
7190
+ fs51.mkdir(path59.dirname(file), { recursive: true }, (err) => {
7171
7191
  if (err) return fileOpened(err);
7172
- fs50.open(file, flags, mode, fileOpened);
7192
+ fs51.open(file, flags, mode, fileOpened);
7173
7193
  });
7174
7194
  } else {
7175
- fs50.open(file, flags, mode, fileOpened);
7195
+ fs51.open(file, flags, mode, fileOpened);
7176
7196
  }
7177
7197
  }
7178
7198
  function SonicBoom(opts) {
@@ -7213,8 +7233,8 @@ var require_sonic_boom = __commonJS({
7213
7233
  this.flush = flushBuffer;
7214
7234
  this.flushSync = flushBufferSync;
7215
7235
  this._actualWrite = actualWriteBuffer;
7216
- fsWriteSync = () => fs50.writeSync(this.fd, this._writingBuf);
7217
- fsWrite = () => fs50.write(this.fd, this._writingBuf, this.release);
7236
+ fsWriteSync = () => fs51.writeSync(this.fd, this._writingBuf);
7237
+ fsWrite = () => fs51.write(this.fd, this._writingBuf, this.release);
7218
7238
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7219
7239
  this._writingBuf = "";
7220
7240
  this.write = write;
@@ -7223,15 +7243,15 @@ var require_sonic_boom = __commonJS({
7223
7243
  this._actualWrite = actualWrite;
7224
7244
  fsWriteSync = () => {
7225
7245
  if (Buffer.isBuffer(this._writingBuf)) {
7226
- return fs50.writeSync(this.fd, this._writingBuf);
7246
+ return fs51.writeSync(this.fd, this._writingBuf);
7227
7247
  }
7228
- return fs50.writeSync(this.fd, this._writingBuf, "utf8");
7248
+ return fs51.writeSync(this.fd, this._writingBuf, "utf8");
7229
7249
  };
7230
7250
  fsWrite = () => {
7231
7251
  if (Buffer.isBuffer(this._writingBuf)) {
7232
- return fs50.write(this.fd, this._writingBuf, this.release);
7252
+ return fs51.write(this.fd, this._writingBuf, this.release);
7233
7253
  }
7234
- return fs50.write(this.fd, this._writingBuf, "utf8", this.release);
7254
+ return fs51.write(this.fd, this._writingBuf, "utf8", this.release);
7235
7255
  };
7236
7256
  } else {
7237
7257
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7288,7 +7308,7 @@ var require_sonic_boom = __commonJS({
7288
7308
  }
7289
7309
  }
7290
7310
  if (this._fsync) {
7291
- fs50.fsyncSync(this.fd);
7311
+ fs51.fsyncSync(this.fd);
7292
7312
  }
7293
7313
  const len = this._len;
7294
7314
  if (this._reopening) {
@@ -7402,7 +7422,7 @@ var require_sonic_boom = __commonJS({
7402
7422
  const onDrain = () => {
7403
7423
  if (!this._fsync) {
7404
7424
  try {
7405
- fs50.fsync(this.fd, (err) => {
7425
+ fs51.fsync(this.fd, (err) => {
7406
7426
  this._flushPending = false;
7407
7427
  cb(err);
7408
7428
  });
@@ -7504,7 +7524,7 @@ var require_sonic_boom = __commonJS({
7504
7524
  const fd = this.fd;
7505
7525
  this.once("ready", () => {
7506
7526
  if (fd !== this.fd) {
7507
- fs50.close(fd, (err) => {
7527
+ fs51.close(fd, (err) => {
7508
7528
  if (err) {
7509
7529
  return this.emit("error", err);
7510
7530
  }
@@ -7553,7 +7573,7 @@ var require_sonic_boom = __commonJS({
7553
7573
  buf = this._bufs[0];
7554
7574
  }
7555
7575
  try {
7556
- const n = Buffer.isBuffer(buf) ? fs50.writeSync(this.fd, buf) : fs50.writeSync(this.fd, buf, "utf8");
7576
+ const n = Buffer.isBuffer(buf) ? fs51.writeSync(this.fd, buf) : fs51.writeSync(this.fd, buf, "utf8");
7557
7577
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7558
7578
  buf = releasedBufObj.writingBuf;
7559
7579
  this._len = releasedBufObj.len;
@@ -7569,7 +7589,7 @@ var require_sonic_boom = __commonJS({
7569
7589
  }
7570
7590
  }
7571
7591
  try {
7572
- fs50.fsyncSync(this.fd);
7592
+ fs51.fsyncSync(this.fd);
7573
7593
  } catch {
7574
7594
  }
7575
7595
  }
@@ -7590,7 +7610,7 @@ var require_sonic_boom = __commonJS({
7590
7610
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7591
7611
  }
7592
7612
  try {
7593
- const n = fs50.writeSync(this.fd, buf);
7613
+ const n = fs51.writeSync(this.fd, buf);
7594
7614
  buf = buf.subarray(n);
7595
7615
  this._len = Math.max(this._len - n, 0);
7596
7616
  if (buf.length <= 0) {
@@ -7618,13 +7638,13 @@ var require_sonic_boom = __commonJS({
7618
7638
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7619
7639
  if (this.sync) {
7620
7640
  try {
7621
- const written = Buffer.isBuffer(this._writingBuf) ? fs50.writeSync(this.fd, this._writingBuf) : fs50.writeSync(this.fd, this._writingBuf, "utf8");
7641
+ const written = Buffer.isBuffer(this._writingBuf) ? fs51.writeSync(this.fd, this._writingBuf) : fs51.writeSync(this.fd, this._writingBuf, "utf8");
7622
7642
  release(null, written);
7623
7643
  } catch (err) {
7624
7644
  release(err);
7625
7645
  }
7626
7646
  } else {
7627
- fs50.write(this.fd, this._writingBuf, release);
7647
+ fs51.write(this.fd, this._writingBuf, release);
7628
7648
  }
7629
7649
  }
7630
7650
  function actualWriteBuffer() {
@@ -7633,7 +7653,7 @@ var require_sonic_boom = __commonJS({
7633
7653
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7634
7654
  if (this.sync) {
7635
7655
  try {
7636
- const written = fs50.writeSync(this.fd, this._writingBuf);
7656
+ const written = fs51.writeSync(this.fd, this._writingBuf);
7637
7657
  release(null, written);
7638
7658
  } catch (err) {
7639
7659
  release(err);
@@ -7642,7 +7662,7 @@ var require_sonic_boom = __commonJS({
7642
7662
  if (kCopyBuffer) {
7643
7663
  this._writingBuf = Buffer.from(this._writingBuf);
7644
7664
  }
7645
- fs50.write(this.fd, this._writingBuf, release);
7665
+ fs51.write(this.fd, this._writingBuf, release);
7646
7666
  }
7647
7667
  }
7648
7668
  function actualClose(sonic) {
@@ -7658,12 +7678,12 @@ var require_sonic_boom = __commonJS({
7658
7678
  sonic._lens = [];
7659
7679
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7660
7680
  try {
7661
- fs50.fsync(sonic.fd, closeWrapped);
7681
+ fs51.fsync(sonic.fd, closeWrapped);
7662
7682
  } catch {
7663
7683
  }
7664
7684
  function closeWrapped() {
7665
7685
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7666
- fs50.close(sonic.fd, done);
7686
+ fs51.close(sonic.fd, done);
7667
7687
  } else {
7668
7688
  done();
7669
7689
  }
@@ -8544,38 +8564,38 @@ var require_tools = __commonJS({
8544
8564
  }
8545
8565
  }
8546
8566
  }
8547
- function asString(str) {
8567
+ function asString(str4) {
8548
8568
  let result = "";
8549
8569
  let last = 0;
8550
8570
  let found = false;
8551
8571
  let point = 255;
8552
- const l = str.length;
8572
+ const l = str4.length;
8553
8573
  if (l > 100) {
8554
- return JSON.stringify(str);
8574
+ return JSON.stringify(str4);
8555
8575
  }
8556
8576
  for (var i = 0; i < l && point >= 32; i++) {
8557
- point = str.charCodeAt(i);
8577
+ point = str4.charCodeAt(i);
8558
8578
  if (point === 34 || point === 92) {
8559
- result += str.slice(last, i) + "\\";
8579
+ result += str4.slice(last, i) + "\\";
8560
8580
  last = i;
8561
8581
  found = true;
8562
8582
  }
8563
8583
  }
8564
8584
  if (!found) {
8565
- result = str;
8585
+ result = str4;
8566
8586
  } else {
8567
- result += str.slice(last);
8587
+ result += str4.slice(last);
8568
8588
  }
8569
- return point < 32 ? JSON.stringify(str) : '"' + result + '"';
8589
+ return point < 32 ? JSON.stringify(str4) : '"' + result + '"';
8570
8590
  }
8571
- function asJson(obj, msg, num, time) {
8591
+ function asJson(obj, msg, num3, time) {
8572
8592
  if (asJsonChan.hasSubscribers === false) {
8573
- return _asJson.call(this, obj, msg, num, time);
8593
+ return _asJson.call(this, obj, msg, num3, time);
8574
8594
  }
8575
8595
  const store = { instance: this, arguments };
8576
- return asJsonChan.traceSync(_asJson, store, this, obj, msg, num, time);
8596
+ return asJsonChan.traceSync(_asJson, store, this, obj, msg, num3, time);
8577
8597
  }
8578
- function _asJson(obj, msg, num, time) {
8598
+ function _asJson(obj, msg, num3, time) {
8579
8599
  const stringify2 = this[stringifySym];
8580
8600
  const stringifySafe = this[stringifySafeSym];
8581
8601
  const stringifiers = this[stringifiersSym];
@@ -8585,7 +8605,7 @@ var require_tools = __commonJS({
8585
8605
  const formatters = this[formattersSym];
8586
8606
  const messageKey = this[messageKeySym];
8587
8607
  const errorKey = this[errorKeySym];
8588
- let data = this[lsCacheSym][num] + time;
8608
+ let data = this[lsCacheSym][num3] + time;
8589
8609
  data = data + chindings;
8590
8610
  let value;
8591
8611
  if (formatters.log) {
@@ -9212,7 +9232,7 @@ var require_proto = __commonJS({
9212
9232
  function defaultMixinMergeStrategy(mergeObject, mixinObject) {
9213
9233
  return Object.assign(mixinObject, mergeObject);
9214
9234
  }
9215
- function write(_obj, msg, num) {
9235
+ function write(_obj, msg, num3) {
9216
9236
  const t = this[timeSym]();
9217
9237
  const mixin = this[mixinSym];
9218
9238
  const errorKey = this[errorKeySym];
@@ -9234,12 +9254,12 @@ var require_proto = __commonJS({
9234
9254
  }
9235
9255
  }
9236
9256
  if (mixin) {
9237
- obj = mixinMergeStrategy(obj, mixin(obj, num, this));
9257
+ obj = mixinMergeStrategy(obj, mixin(obj, num3, this));
9238
9258
  }
9239
- const s = this[asJsonSym](obj, msg, num, t);
9259
+ const s = this[asJsonSym](obj, msg, num3, t);
9240
9260
  const stream = this[streamSym];
9241
9261
  if (stream[needsMetadataGsym] === true) {
9242
- stream.lastLevel = num;
9262
+ stream.lastLevel = num3;
9243
9263
  stream.lastObj = obj;
9244
9264
  stream.lastMsg = msg;
9245
9265
  stream.lastTime = t.slice(this[timeSliceIndexSym]);
@@ -9272,11 +9292,11 @@ var require_safe_stable_stringify = __commonJS({
9272
9292
  exports2.configure = configure;
9273
9293
  module2.exports = stringify;
9274
9294
  var strEscapeSequencesRegExp = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/;
9275
- function strEscape(str) {
9276
- if (str.length < 5e3 && !strEscapeSequencesRegExp.test(str)) {
9277
- return `"${str}"`;
9295
+ function strEscape(str4) {
9296
+ if (str4.length < 5e3 && !strEscapeSequencesRegExp.test(str4)) {
9297
+ return `"${str4}"`;
9278
9298
  }
9279
- return JSON.stringify(str);
9299
+ return JSON.stringify(str4);
9280
9300
  }
9281
9301
  function sort(array, comparator) {
9282
9302
  if (array.length > 200 || comparator) {
@@ -10233,6 +10253,23 @@ var require_pino = __commonJS({
10233
10253
  }
10234
10254
  });
10235
10255
 
10256
+ // src/session/stdout-splitter.ts
10257
+ function splitStdoutChunk(buf, chunk) {
10258
+ let next = buf + (typeof chunk === "string" ? chunk : chunk.toString("utf8"));
10259
+ const lines = [];
10260
+ let idx;
10261
+ while ((idx = next.indexOf("\n")) >= 0) {
10262
+ lines.push(next.slice(0, idx));
10263
+ next = next.slice(idx + 1);
10264
+ }
10265
+ return { newBuf: next, lines };
10266
+ }
10267
+ var init_stdout_splitter = __esm({
10268
+ "src/session/stdout-splitter.ts"() {
10269
+ "use strict";
10270
+ }
10271
+ });
10272
+
10236
10273
  // src/session/permission-stdio.ts
10237
10274
  function encodePermissionResponse(requestId, approved, input, message) {
10238
10275
  const innerResponse = approved ? {
@@ -10255,23 +10292,6 @@ var init_permission_stdio = __esm({
10255
10292
  }
10256
10293
  });
10257
10294
 
10258
- // src/session/stdout-splitter.ts
10259
- function splitStdoutChunk(buf, chunk) {
10260
- let next = buf + (typeof chunk === "string" ? chunk : chunk.toString("utf8"));
10261
- const lines = [];
10262
- let idx;
10263
- while ((idx = next.indexOf("\n")) >= 0) {
10264
- lines.push(next.slice(0, idx));
10265
- next = next.slice(idx + 1);
10266
- }
10267
- return { newBuf: next, lines };
10268
- }
10269
- var init_stdout_splitter = __esm({
10270
- "src/session/stdout-splitter.ts"() {
10271
- "use strict";
10272
- }
10273
- });
10274
-
10275
10295
  // ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
10276
10296
  function Diff() {
10277
10297
  }
@@ -10310,22 +10330,22 @@ function buildValues(diff2, lastComponent, newString, oldString, useLongestToken
10310
10330
  }
10311
10331
  return components;
10312
10332
  }
10313
- function longestCommonPrefix(str1, str2) {
10333
+ function longestCommonPrefix(str1, str22) {
10314
10334
  var i;
10315
- for (i = 0; i < str1.length && i < str2.length; i++) {
10316
- if (str1[i] != str2[i]) {
10335
+ for (i = 0; i < str1.length && i < str22.length; i++) {
10336
+ if (str1[i] != str22[i]) {
10317
10337
  return str1.slice(0, i);
10318
10338
  }
10319
10339
  }
10320
10340
  return str1.slice(0, i);
10321
10341
  }
10322
- function longestCommonSuffix(str1, str2) {
10342
+ function longestCommonSuffix(str1, str22) {
10323
10343
  var i;
10324
- if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) {
10344
+ if (!str1 || !str22 || str1[str1.length - 1] != str22[str22.length - 1]) {
10325
10345
  return "";
10326
10346
  }
10327
- for (i = 0; i < str1.length && i < str2.length; i++) {
10328
- if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) {
10347
+ for (i = 0; i < str1.length && i < str22.length; i++) {
10348
+ if (str1[str1.length - (i + 1)] != str22[str22.length - (i + 1)]) {
10329
10349
  return str1.slice(-i);
10330
10350
  }
10331
10351
  }
@@ -11257,12 +11277,12 @@ function attachmentToHistoryMessage(o, ts) {
11257
11277
  const raw = Array.isArray(a.memories) ? a.memories : [];
11258
11278
  const memories = raw.map((m2) => {
11259
11279
  if (!m2 || typeof m2 !== "object") return null;
11260
- const rec = m2;
11261
- const path59 = typeof rec.path === "string" ? rec.path : null;
11262
- const content = typeof rec.content === "string" ? rec.content : null;
11280
+ const rec3 = m2;
11281
+ const path59 = typeof rec3.path === "string" ? rec3.path : null;
11282
+ const content = typeof rec3.content === "string" ? rec3.content : null;
11263
11283
  if (!path59 || content == null) return null;
11264
11284
  const entry = { path: path59, content };
11265
- if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
11285
+ if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11266
11286
  return entry;
11267
11287
  }).filter((m2) => m2 !== null);
11268
11288
  if (memories.length === 0) return null;
@@ -12072,12 +12092,12 @@ function parseAttachment(obj) {
12072
12092
  const raw = Array.isArray(a.memories) ? a.memories : [];
12073
12093
  const memories = raw.map((m2) => {
12074
12094
  if (!m2 || typeof m2 !== "object") return null;
12075
- const rec = m2;
12076
- const path59 = typeof rec.path === "string" ? rec.path : null;
12077
- const content = typeof rec.content === "string" ? rec.content : null;
12095
+ const rec3 = m2;
12096
+ const path59 = typeof rec3.path === "string" ? rec3.path : null;
12097
+ const content = typeof rec3.content === "string" ? rec3.content : null;
12078
12098
  if (!path59 || content == null) return null;
12079
12099
  const out = { path: path59, content };
12080
- if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
12100
+ if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12081
12101
  return out;
12082
12102
  }).filter((m2) => m2 !== null);
12083
12103
  if (memories.length === 0) return null;
@@ -12224,6 +12244,7 @@ var init_claude = __esm({
12224
12244
  toolSessionIdLabel: "Claude Session ID",
12225
12245
  models: CLAUDE_MODELS,
12226
12246
  permissionModes: CLAUDE_PERMISSION_MODES,
12247
+ features: { rewind: true, subagents: true, tui: true, observe: true, fileSharing: true, fork: true },
12227
12248
  configSchema: [
12228
12249
  {
12229
12250
  name: "model",
@@ -17712,26 +17733,26 @@ var require_permessage_deflate = __commonJS({
17712
17733
  value = value[0];
17713
17734
  if (key === "client_max_window_bits") {
17714
17735
  if (value !== true) {
17715
- const num = +value;
17716
- if (!Number.isInteger(num) || num < 8 || num > 15) {
17736
+ const num3 = +value;
17737
+ if (!Number.isInteger(num3) || num3 < 8 || num3 > 15) {
17717
17738
  throw new TypeError(
17718
17739
  `Invalid value for parameter "${key}": ${value}`
17719
17740
  );
17720
17741
  }
17721
- value = num;
17742
+ value = num3;
17722
17743
  } else if (!this._isServer) {
17723
17744
  throw new TypeError(
17724
17745
  `Invalid value for parameter "${key}": ${value}`
17725
17746
  );
17726
17747
  }
17727
17748
  } else if (key === "server_max_window_bits") {
17728
- const num = +value;
17729
- if (!Number.isInteger(num) || num < 8 || num > 15) {
17749
+ const num3 = +value;
17750
+ if (!Number.isInteger(num3) || num3 < 8 || num3 > 15) {
17730
17751
  throw new TypeError(
17731
17752
  `Invalid value for parameter "${key}": ${value}`
17732
17753
  );
17733
17754
  }
17734
- value = num;
17755
+ value = num3;
17735
17756
  } else if (key === "client_no_context_takeover" || key === "server_no_context_takeover") {
17736
17757
  if (value !== true) {
17737
17758
  throw new TypeError(
@@ -18426,8 +18447,8 @@ var require_receiver = __commonJS({
18426
18447
  return;
18427
18448
  }
18428
18449
  const buf = this.consume(8);
18429
- const num = buf.readUInt32BE(0);
18430
- if (num > Math.pow(2, 53 - 32) - 1) {
18450
+ const num3 = buf.readUInt32BE(0);
18451
+ if (num3 > Math.pow(2, 53 - 32) - 1) {
18431
18452
  const error = this.createError(
18432
18453
  RangeError,
18433
18454
  "Unsupported WebSocket frame: payload length > 2^53 - 1",
@@ -18438,7 +18459,7 @@ var require_receiver = __commonJS({
18438
18459
  cb(error);
18439
18460
  return;
18440
18461
  }
18441
- this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
18462
+ this._payloadLength = num3 * Math.pow(2, 32) + buf.readUInt32BE(4);
18442
18463
  this.haveLength(cb);
18443
18464
  }
18444
18465
  /**
@@ -22752,19 +22773,19 @@ var require_stream_readable = __commonJS({
22752
22773
  var ret = p2.data;
22753
22774
  n -= ret.length;
22754
22775
  while (p2 = p2.next) {
22755
- var str = p2.data;
22756
- var nb = n > str.length ? str.length : n;
22757
- if (nb === str.length) ret += str;
22758
- else ret += str.slice(0, n);
22776
+ var str4 = p2.data;
22777
+ var nb = n > str4.length ? str4.length : n;
22778
+ if (nb === str4.length) ret += str4;
22779
+ else ret += str4.slice(0, n);
22759
22780
  n -= nb;
22760
22781
  if (n === 0) {
22761
- if (nb === str.length) {
22782
+ if (nb === str4.length) {
22762
22783
  ++c;
22763
22784
  if (p2.next) list.head = p2.next;
22764
22785
  else list.head = list.tail = null;
22765
22786
  } else {
22766
22787
  list.head = p2;
22767
- p2.data = str.slice(nb);
22788
+ p2.data = str4.slice(nb);
22768
22789
  }
22769
22790
  break;
22770
22791
  }
@@ -23660,14 +23681,14 @@ var require_utils = __commonJS({
23660
23681
  var nodejsUtils = require_nodejsUtils();
23661
23682
  var external = require_external();
23662
23683
  require_setImmediate();
23663
- function string2binary(str) {
23684
+ function string2binary(str4) {
23664
23685
  var result = null;
23665
23686
  if (support.uint8array) {
23666
- result = new Uint8Array(str.length);
23687
+ result = new Uint8Array(str4.length);
23667
23688
  } else {
23668
- result = new Array(str.length);
23689
+ result = new Array(str4.length);
23669
23690
  }
23670
- return stringToArrayLike(str, result);
23691
+ return stringToArrayLike(str4, result);
23671
23692
  }
23672
23693
  exports2.newBlob = function(part, type) {
23673
23694
  exports2.checkSupport("blob");
@@ -23689,9 +23710,9 @@ var require_utils = __commonJS({
23689
23710
  function identity(input) {
23690
23711
  return input;
23691
23712
  }
23692
- function stringToArrayLike(str, array) {
23693
- for (var i = 0; i < str.length; ++i) {
23694
- array[i] = str.charCodeAt(i) & 255;
23713
+ function stringToArrayLike(str4, array) {
23714
+ for (var i = 0; i < str4.length; ++i) {
23715
+ array[i] = str4.charCodeAt(i) & 255;
23695
23716
  }
23696
23717
  return array;
23697
23718
  }
@@ -23904,10 +23925,10 @@ var require_utils = __commonJS({
23904
23925
  };
23905
23926
  exports2.MAX_VALUE_16BITS = 65535;
23906
23927
  exports2.MAX_VALUE_32BITS = -1;
23907
- exports2.pretty = function(str) {
23928
+ exports2.pretty = function(str4) {
23908
23929
  var res = "", code, i;
23909
- for (i = 0; i < (str || "").length; i++) {
23910
- code = str.charCodeAt(i);
23930
+ for (i = 0; i < (str4 || "").length; i++) {
23931
+ code = str4.charCodeAt(i);
23911
23932
  res += "\\x" + (code < 16 ? "0" : "") + code.toString(16).toUpperCase();
23912
23933
  }
23913
23934
  return res;
@@ -24217,12 +24238,12 @@ var require_utf8 = __commonJS({
24217
24238
  }
24218
24239
  var i;
24219
24240
  _utf8len[254] = _utf8len[254] = 1;
24220
- var string2buf = function(str) {
24221
- var buf, c, c2, m_pos, i2, str_len = str.length, buf_len = 0;
24241
+ var string2buf = function(str4) {
24242
+ var buf, c, c2, m_pos, i2, str_len = str4.length, buf_len = 0;
24222
24243
  for (m_pos = 0; m_pos < str_len; m_pos++) {
24223
- c = str.charCodeAt(m_pos);
24244
+ c = str4.charCodeAt(m_pos);
24224
24245
  if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
24225
- c2 = str.charCodeAt(m_pos + 1);
24246
+ c2 = str4.charCodeAt(m_pos + 1);
24226
24247
  if ((c2 & 64512) === 56320) {
24227
24248
  c = 65536 + (c - 55296 << 10) + (c2 - 56320);
24228
24249
  m_pos++;
@@ -24236,9 +24257,9 @@ var require_utf8 = __commonJS({
24236
24257
  buf = new Array(buf_len);
24237
24258
  }
24238
24259
  for (i2 = 0, m_pos = 0; i2 < buf_len; m_pos++) {
24239
- c = str.charCodeAt(m_pos);
24260
+ c = str4.charCodeAt(m_pos);
24240
24261
  if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
24241
- c2 = str.charCodeAt(m_pos + 1);
24262
+ c2 = str4.charCodeAt(m_pos + 1);
24242
24263
  if ((c2 & 64512) === 56320) {
24243
24264
  c = 65536 + (c - 55296 << 10) + (c2 - 56320);
24244
24265
  m_pos++;
@@ -24322,11 +24343,11 @@ var require_utf8 = __commonJS({
24322
24343
  }
24323
24344
  return utils.applyFromCharCode(utf16buf);
24324
24345
  };
24325
- exports2.utf8encode = function utf8encode(str) {
24346
+ exports2.utf8encode = function utf8encode(str4) {
24326
24347
  if (support.nodebuffer) {
24327
- return nodejsUtils.newBufferFrom(str, "utf-8");
24348
+ return nodejsUtils.newBufferFrom(str4, "utf-8");
24328
24349
  }
24329
- return string2buf(str);
24350
+ return string2buf(str4);
24330
24351
  };
24331
24352
  exports2.utf8decode = function utf8decode(buf) {
24332
24353
  if (support.nodebuffer) {
@@ -24735,11 +24756,11 @@ var require_crc32 = __commonJS({
24735
24756
  }
24736
24757
  return crc ^ -1;
24737
24758
  }
24738
- function crc32str(crc, str, len, pos) {
24759
+ function crc32str(crc, str4, len, pos) {
24739
24760
  var t = crcTable, end = pos + len;
24740
24761
  crc = crc ^ -1;
24741
24762
  for (var i = pos; i < end; i++) {
24742
- crc = crc >>> 8 ^ t[(crc ^ str.charCodeAt(i)) & 255];
24763
+ crc = crc >>> 8 ^ t[(crc ^ str4.charCodeAt(i)) & 255];
24743
24764
  }
24744
24765
  return crc ^ -1;
24745
24766
  }
@@ -25936,7 +25957,7 @@ var require_deflate = __commonJS({
25936
25957
  }
25937
25958
  function fill_window(s) {
25938
25959
  var _w_size = s.w_size;
25939
- var p2, n, m2, more, str;
25960
+ var p2, n, m2, more, str4;
25940
25961
  do {
25941
25962
  more = s.window_size - s.lookahead - s.strstart;
25942
25963
  if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) {
@@ -25964,14 +25985,14 @@ var require_deflate = __commonJS({
25964
25985
  n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more);
25965
25986
  s.lookahead += n;
25966
25987
  if (s.lookahead + s.insert >= MIN_MATCH) {
25967
- str = s.strstart - s.insert;
25968
- s.ins_h = s.window[str];
25969
- s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + 1]) & s.hash_mask;
25988
+ str4 = s.strstart - s.insert;
25989
+ s.ins_h = s.window[str4];
25990
+ s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str4 + 1]) & s.hash_mask;
25970
25991
  while (s.insert) {
25971
- s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
25972
- s.prev[str & s.w_mask] = s.head[s.ins_h];
25973
- s.head[s.ins_h] = str;
25974
- str++;
25992
+ s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str4 + MIN_MATCH - 1]) & s.hash_mask;
25993
+ s.prev[str4 & s.w_mask] = s.head[s.ins_h];
25994
+ s.head[s.ins_h] = str4;
25995
+ str4++;
25975
25996
  s.insert--;
25976
25997
  if (s.lookahead + s.insert < MIN_MATCH) {
25977
25998
  break;
@@ -26747,7 +26768,7 @@ var require_deflate = __commonJS({
26747
26768
  function deflateSetDictionary(strm, dictionary) {
26748
26769
  var dictLength = dictionary.length;
26749
26770
  var s;
26750
- var str, n;
26771
+ var str4, n;
26751
26772
  var wrap2;
26752
26773
  var avail;
26753
26774
  var next;
@@ -26785,15 +26806,15 @@ var require_deflate = __commonJS({
26785
26806
  strm.input = dictionary;
26786
26807
  fill_window(s);
26787
26808
  while (s.lookahead >= MIN_MATCH) {
26788
- str = s.strstart;
26809
+ str4 = s.strstart;
26789
26810
  n = s.lookahead - (MIN_MATCH - 1);
26790
26811
  do {
26791
- s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask;
26792
- s.prev[str & s.w_mask] = s.head[s.ins_h];
26793
- s.head[s.ins_h] = str;
26794
- str++;
26812
+ s.ins_h = (s.ins_h << s.hash_shift ^ s.window[str4 + MIN_MATCH - 1]) & s.hash_mask;
26813
+ s.prev[str4 & s.w_mask] = s.head[s.ins_h];
26814
+ s.head[s.ins_h] = str4;
26815
+ str4++;
26795
26816
  } while (--n);
26796
- s.strstart = str;
26817
+ s.strstart = str4;
26797
26818
  s.lookahead = MIN_MATCH - 1;
26798
26819
  fill_window(s);
26799
26820
  }
@@ -26844,12 +26865,12 @@ var require_strings = __commonJS({
26844
26865
  }
26845
26866
  var q;
26846
26867
  _utf8len[254] = _utf8len[254] = 1;
26847
- exports2.string2buf = function(str) {
26848
- var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
26868
+ exports2.string2buf = function(str4) {
26869
+ var buf, c, c2, m_pos, i, str_len = str4.length, buf_len = 0;
26849
26870
  for (m_pos = 0; m_pos < str_len; m_pos++) {
26850
- c = str.charCodeAt(m_pos);
26871
+ c = str4.charCodeAt(m_pos);
26851
26872
  if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
26852
- c2 = str.charCodeAt(m_pos + 1);
26873
+ c2 = str4.charCodeAt(m_pos + 1);
26853
26874
  if ((c2 & 64512) === 56320) {
26854
26875
  c = 65536 + (c - 55296 << 10) + (c2 - 56320);
26855
26876
  m_pos++;
@@ -26859,9 +26880,9 @@ var require_strings = __commonJS({
26859
26880
  }
26860
26881
  buf = new utils.Buf8(buf_len);
26861
26882
  for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
26862
- c = str.charCodeAt(m_pos);
26883
+ c = str4.charCodeAt(m_pos);
26863
26884
  if ((c & 64512) === 55296 && m_pos + 1 < str_len) {
26864
- c2 = str.charCodeAt(m_pos + 1);
26885
+ c2 = str4.charCodeAt(m_pos + 1);
26865
26886
  if ((c2 & 64512) === 56320) {
26866
26887
  c = 65536 + (c - 55296 << 10) + (c2 - 56320);
26867
26888
  m_pos++;
@@ -26900,10 +26921,10 @@ var require_strings = __commonJS({
26900
26921
  exports2.buf2binstring = function(buf) {
26901
26922
  return buf2binstring(buf, buf.length);
26902
26923
  };
26903
- exports2.binstring2buf = function(str) {
26904
- var buf = new utils.Buf8(str.length);
26924
+ exports2.binstring2buf = function(str4) {
26925
+ var buf = new utils.Buf8(str4.length);
26905
26926
  for (var i = 0, len = buf.length; i < len; i++) {
26906
- buf[i] = str.charCodeAt(i);
26927
+ buf[i] = str4.charCodeAt(i);
26907
26928
  }
26908
26929
  return buf;
26909
26930
  };
@@ -30745,8 +30766,8 @@ function startRunCaseRecorder(opts) {
30745
30766
  });
30746
30767
  const ensureStream = () => {
30747
30768
  if (stream) return stream;
30748
- import_node_fs33.default.mkdirSync(dir, { recursive: true });
30749
- stream = import_node_fs33.default.createWriteStream(opts.recordPath, { flags: "a" });
30769
+ import_node_fs34.default.mkdirSync(dir, { recursive: true });
30770
+ stream = import_node_fs34.default.createWriteStream(opts.recordPath, { flags: "a" });
30750
30771
  stream.on("close", () => closedResolve());
30751
30772
  return stream;
30752
30773
  };
@@ -30771,11 +30792,11 @@ function startRunCaseRecorder(opts) {
30771
30792
  };
30772
30793
  return { tap, close, closed };
30773
30794
  }
30774
- var import_node_fs33, import_node_path47;
30795
+ var import_node_fs34, import_node_path47;
30775
30796
  var init_recorder = __esm({
30776
30797
  "src/run-case/recorder.ts"() {
30777
30798
  "use strict";
30778
- import_node_fs33 = __toESM(require("fs"), 1);
30799
+ import_node_fs34 = __toESM(require("fs"), 1);
30779
30800
  import_node_path47 = __toESM(require("path"), 1);
30780
30801
  }
30781
30802
  });
@@ -30819,7 +30840,7 @@ var init_wire = __esm({
30819
30840
  // src/run-case/controller.ts
30820
30841
  async function runController(opts) {
30821
30842
  const now = opts.now ?? Date.now;
30822
- const cwd = opts.cwd ?? (0, import_node_fs34.mkdtempSync)(import_node_path48.default.join(import_node_os19.default.tmpdir(), "clawd-runcase-"));
30843
+ const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(import_node_path48.default.join(import_node_os19.default.tmpdir(), "clawd-runcase-"));
30823
30844
  const ownsCwd = opts.cwd === void 0;
30824
30845
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
30825
30846
  const spawnCtx = { cwd };
@@ -30980,17 +31001,17 @@ async function runController(opts) {
30980
31001
  if (sigintHandler) process.off("SIGINT", sigintHandler);
30981
31002
  if (ownsCwd) {
30982
31003
  try {
30983
- (0, import_node_fs34.rmSync)(cwd, { recursive: true, force: true });
31004
+ (0, import_node_fs35.rmSync)(cwd, { recursive: true, force: true });
30984
31005
  } catch {
30985
31006
  }
30986
31007
  }
30987
31008
  return exitCode ?? 0;
30988
31009
  }
30989
- var import_node_fs34, import_node_os19, import_node_path48;
31010
+ var import_node_fs35, import_node_os19, import_node_path48;
30990
31011
  var init_controller = __esm({
30991
31012
  "src/run-case/controller.ts"() {
30992
31013
  "use strict";
30993
- import_node_fs34 = require("fs");
31014
+ import_node_fs35 = require("fs");
30994
31015
  import_node_os19 = __toESM(require("os"), 1);
30995
31016
  import_node_path48 = __toESM(require("path"), 1);
30996
31017
  init_claude();
@@ -31228,7 +31249,7 @@ Env (advanced):
31228
31249
 
31229
31250
  // src/index.ts
31230
31251
  var import_node_path46 = __toESM(require("path"), 1);
31231
- var import_node_fs32 = __toESM(require("fs"), 1);
31252
+ var import_node_fs33 = __toESM(require("fs"), 1);
31232
31253
 
31233
31254
  // src/logger.ts
31234
31255
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -31625,9 +31646,6 @@ function buildRule(tool, input) {
31625
31646
  return { tool, pattern, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
31626
31647
  }
31627
31648
 
31628
- // src/session/reducer.ts
31629
- init_permission_stdio();
31630
-
31631
31649
  // src/persona/connection-prompt.ts
31632
31650
  var OWNER_TEMPLATE = `# \u8FDE\u63A5\u4E0A\u4E0B\u6587
31633
31651
  \u4F60\u73B0\u5728\u4EE5 Owner \u8EAB\u4EFD\u88AB\u8FDE\u63A5\uFF0C\u5BF9\u65B9\u5C31\u662F owner \u672C\u4EBA\uFF08{ownerLabel}\uFF09\u3002
@@ -31749,6 +31767,9 @@ function buildSpawnContext(state, deps) {
31749
31767
  if (meta?.addDirs && meta.addDirs.length > 0) {
31750
31768
  ctx.addDirs = meta.addDirs;
31751
31769
  }
31770
+ if (meta?.networkAccess !== void 0) {
31771
+ ctx.networkAccess = meta.networkAccess;
31772
+ }
31752
31773
  return ctx;
31753
31774
  }
31754
31775
  function sessionInfoFrame(file) {
@@ -31814,10 +31835,7 @@ function applyParsedEvent(state, event, deps) {
31814
31835
  effects.push(...pushed2.effects);
31815
31836
  const hit = matchesAnyRule(next.file.permissionRules, tool, input);
31816
31837
  if (hit) {
31817
- effects.push({
31818
- kind: "write-stdin",
31819
- payload: encodePermissionResponse(requestId, true, input)
31820
- });
31838
+ effects.push({ kind: "respond-permission", requestId, allow: true, input });
31821
31839
  } else {
31822
31840
  const pending = {
31823
31841
  tool,
@@ -32210,13 +32228,11 @@ function reduceSession(state, input, deps) {
32210
32228
  next.pendingPermissions = nextPending;
32211
32229
  const effects = [
32212
32230
  {
32213
- kind: "write-stdin",
32214
- payload: encodePermissionResponse(
32215
- input.requestId,
32216
- input.allow,
32217
- pending.input,
32218
- input.message
32219
- )
32231
+ kind: "respond-permission",
32232
+ requestId: input.requestId,
32233
+ allow: input.allow,
32234
+ input: pending.input,
32235
+ message: input.message
32220
32236
  }
32221
32237
  ];
32222
32238
  if (input.allow && input.permanent) {
@@ -32356,6 +32372,7 @@ function reduceSession(state, input, deps) {
32356
32372
 
32357
32373
  // src/session/runner.ts
32358
32374
  init_stdout_splitter();
32375
+ init_permission_stdio();
32359
32376
 
32360
32377
  // src/ipc-recorder.ts
32361
32378
  var import_node_fs4 = __toESM(require("fs"), 1);
@@ -32463,6 +32480,9 @@ var SessionRunner = class {
32463
32480
  hooks;
32464
32481
  state;
32465
32482
  proc = null;
32483
+ // JSON-RPC 类 agent(codex app-server) 的 per-session 驱动器;非 null 时 runner 不用 spawn()/ChildProcess,
32484
+ // effect 路由到 session 一等方法(startTurn/respondPermission/answerQuestion/interrupt/stop)。claude 恒 null。
32485
+ session = null;
32466
32486
  stdoutBuf = "";
32467
32487
  // 未决 control_request 表;key = request_id
32468
32488
  pendingControlRequests = /* @__PURE__ */ new Map();
@@ -32571,6 +32591,15 @@ var SessionRunner = class {
32571
32591
  if (this.hooks.onFileEdit) this.observeForFileEdit(events);
32572
32592
  this.input({ kind: "inject-events", events });
32573
32593
  }
32594
+ // session:interrupt 的 SDK 通道分流:codex → AgentSession.interrupt();claude → control_request('interrupt')。
32595
+ // TUI(pty) 路径在 manager.dispatchInterrupt 里先于此处理,不进这里。
32596
+ async interrupt() {
32597
+ if (this.session) {
32598
+ this.session.interrupt();
32599
+ return;
32600
+ }
32601
+ await this.sendControlRequest("interrupt");
32602
+ }
32574
32603
  /**
32575
32604
  * file-sharing tool_use ↔ tool_result 配对(spec §6 PR 3)。
32576
32605
  *
@@ -32695,9 +32724,17 @@ var SessionRunner = class {
32695
32724
  this.doSpawn(effect.ctx);
32696
32725
  break;
32697
32726
  case "kill":
32727
+ if (this.session) {
32728
+ void this.session.stop(effect.signal);
32729
+ break;
32730
+ }
32698
32731
  this.doKill(effect.signal);
32699
32732
  break;
32700
32733
  case "write-stdin":
32734
+ if (this.session) {
32735
+ this.session.startTurn(effect.payload);
32736
+ break;
32737
+ }
32701
32738
  this.hooks.logger?.debug("[RG] write-stdin", {
32702
32739
  procAlive: !!this.proc,
32703
32740
  stdinWritable: !!this.proc?.stdin,
@@ -32707,6 +32744,16 @@ var SessionRunner = class {
32707
32744
  this.proc?.stdin?.write(effect.payload);
32708
32745
  this.recorder?.tapStdinWrite(effect.payload);
32709
32746
  break;
32747
+ case "respond-permission": {
32748
+ if (this.session) {
32749
+ this.session.respondPermission(effect.requestId, effect.allow);
32750
+ break;
32751
+ }
32752
+ const payload = encodePermissionResponse(effect.requestId, effect.allow, effect.input, effect.message);
32753
+ this.proc?.stdin?.write(payload);
32754
+ this.recorder?.tapStdinWrite(payload);
32755
+ break;
32756
+ }
32710
32757
  case "send-control-response-allow-with-input": {
32711
32758
  const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
32712
32759
  this.proc?.stdin?.write(payload);
@@ -32764,6 +32811,22 @@ var SessionRunner = class {
32764
32811
  }
32765
32812
  // 启动子进程,绑定 stdout line buffer → 回灌 reducer
32766
32813
  doSpawn(ctx) {
32814
+ if (this.hooks.adapter.createSession) {
32815
+ this.session = this.hooks.adapter.createSession(ctx, {
32816
+ pushEvents: (events) => {
32817
+ if (events.length === 0) return;
32818
+ const uuid = (this.hooks.genUuid ?? v4_default)();
32819
+ this.input({ kind: "inject-events", events: events.map((e) => e.uuid ? e : { ...e, uuid }) });
32820
+ },
32821
+ onExit: (code) => {
32822
+ this.session = null;
32823
+ this.clearIdleKillTimers();
32824
+ this.input({ kind: "proc-exit", code });
32825
+ },
32826
+ onError: (message) => this.input({ kind: "proc-error", message })
32827
+ });
32828
+ return;
32829
+ }
32767
32830
  const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
32768
32831
  this.proc = proc;
32769
32832
  this.stdoutBuf = "";
@@ -33203,6 +33266,8 @@ var SessionManager = class {
33203
33266
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
33204
33267
  const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
33205
33268
  subSessionMeta.extraSettings = JSON.stringify(settings);
33269
+ const domains = settings.sandbox?.network?.allowedDomains;
33270
+ subSessionMeta.networkAccess = Array.isArray(domains) && domains.length > 0;
33206
33271
  }
33207
33272
  const attachmentGroup = this.deps.attachmentGroup;
33208
33273
  const runner = new SessionRunner(makeInitialState(file, subSessionMeta), {
@@ -33634,7 +33699,7 @@ var SessionManager = class {
33634
33699
  tsid,
33635
33700
  mode: this.deps.mode
33636
33701
  });
33637
- await runner.sendControlRequest("interrupt");
33702
+ await runner.interrupt();
33638
33703
  }
33639
33704
  // 批量版本:UI 打开 session 时一次性拿到"磁盘和快照有差异"的 user message id 集合,
33640
33705
  // 用来在消息流里精准控制 rewind 按钮的显示。session 没 toolSessionId 时返回空
@@ -34192,17 +34257,17 @@ var SessionManager = class {
34192
34257
  if (!runner) {
34193
34258
  throw new ClawdError(
34194
34259
  ERROR_CODES.PERMISSION_REQUEST_STALE,
34195
- `no pending permission request: ${args.requestId}`
34260
+ `no pending permission request: ${args.permissionRequestId}`
34196
34261
  );
34197
34262
  }
34198
- const pending = runner.getState().pendingPermissions[args.requestId];
34263
+ const pending = runner.getState().pendingPermissions[args.permissionRequestId];
34199
34264
  if (!pending) {
34200
34265
  return { response: { ok: true }, broadcast: [] };
34201
34266
  }
34202
34267
  const { broadcast } = this.withCollector(() => {
34203
34268
  runner.input({
34204
34269
  kind: "permission-decision",
34205
- requestId: args.requestId,
34270
+ requestId: args.permissionRequestId,
34206
34271
  allow: args.allow,
34207
34272
  permanent: args.permanent,
34208
34273
  pattern: args.pattern,
@@ -34417,6 +34482,11 @@ var PersonaStore = class {
34417
34482
  claudeMdPath(personaId) {
34418
34483
  return path9.join(this.personaDir(personaId), "CLAUDE.md");
34419
34484
  }
34485
+ // codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
34486
+ // 两份内容恒一致,persona 切 tool 零迁移。
34487
+ agentsMdPath(personaId) {
34488
+ return path9.join(this.personaDir(personaId), "AGENTS.md");
34489
+ }
34420
34490
  /**
34421
34491
  * persona 级 sandbox 模板落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
34422
34492
  * source 自动发现扫不到(owner `--setting-sources user,project,local` 不会顺手带进来)。
@@ -34430,6 +34500,7 @@ var PersonaStore = class {
34430
34500
  const dir = this.personaDir(persona.personaId);
34431
34501
  fs7.mkdirSync(path9.join(dir, ".clawd"), { recursive: true });
34432
34502
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
34503
+ this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
34433
34504
  this.atomicWrite(
34434
34505
  this.sandboxSettingsPath(persona.personaId),
34435
34506
  JSON.stringify(buildGuestSettingsV1(), null, 2)
@@ -34438,6 +34509,7 @@ var PersonaStore = class {
34438
34509
  }
34439
34510
  writePersonality(personaId, personality) {
34440
34511
  this.atomicWrite(this.claudeMdPath(personaId), personality);
34512
+ this.atomicWrite(this.agentsMdPath(personaId), personality);
34441
34513
  }
34442
34514
  /**
34443
34515
  * 覆盖式写 persona 级 sandbox 配置(seed 给有 profile 的 persona 写 base⊕profile;owner 之后可手编)。
@@ -34467,9 +34539,11 @@ var PersonaStore = class {
34467
34539
  return fs7.existsSync(this.metaPath(personaId));
34468
34540
  }
34469
34541
  readPersonality(personaId) {
34470
- const p2 = this.claudeMdPath(personaId);
34471
- if (!fs7.existsSync(p2)) return null;
34472
- return fs7.readFileSync(p2, "utf8");
34542
+ const claudeMd = this.claudeMdPath(personaId);
34543
+ if (fs7.existsSync(claudeMd)) return fs7.readFileSync(claudeMd, "utf8");
34544
+ const agentsMd = this.agentsMdPath(personaId);
34545
+ if (fs7.existsSync(agentsMd)) return fs7.readFileSync(agentsMd, "utf8");
34546
+ return null;
34473
34547
  }
34474
34548
  /**
34475
34549
  * 读 sandbox-settings.json 当前内容;文件不存在 / JSON 解析失败均返回 null。
@@ -34871,6 +34945,7 @@ var PersonaManager = class {
34871
34945
  personaId,
34872
34946
  label: args.label,
34873
34947
  model: args.model,
34948
+ tool: args.tool,
34874
34949
  public: args.public ?? false,
34875
34950
  iconKey: args.iconKey,
34876
34951
  createdAt: now,
@@ -35154,8 +35229,454 @@ function refreshDaemonManagedDirs(args) {
35154
35229
  // src/index.ts
35155
35230
  init_claude();
35156
35231
 
35157
- // src/tools/claude-tui.ts
35232
+ // src/tools/codex.ts
35233
+ var import_node_child_process4 = require("child_process");
35158
35234
  var import_node_fs10 = __toESM(require("fs"), 1);
35235
+
35236
+ // src/tools/codex-session.ts
35237
+ var import_node_child_process3 = require("child_process");
35238
+
35239
+ // src/tools/codex-app-server-client.ts
35240
+ var import_node_readline = require("readline");
35241
+ var CodexAppServerClient = class {
35242
+ constructor(proc, opts = {}) {
35243
+ this.proc = proc;
35244
+ this.opts = opts;
35245
+ const rl = (0, import_node_readline.createInterface)({ input: proc.stdout, crlfDelay: Infinity });
35246
+ rl.on("line", (l) => this.onLine(l));
35247
+ rl.on("close", () => {
35248
+ for (const p2 of this.pending.values()) p2.reject(new Error("app-server connection closed"));
35249
+ this.pending.clear();
35250
+ this.opts.onClose?.();
35251
+ });
35252
+ }
35253
+ proc;
35254
+ opts;
35255
+ nextId = 1;
35256
+ pending = /* @__PURE__ */ new Map();
35257
+ request(method, params) {
35258
+ const id = this.nextId++;
35259
+ return new Promise((resolve6, reject) => {
35260
+ this.pending.set(id, { resolve: resolve6, reject });
35261
+ this.write({ jsonrpc: "2.0", method, id, params });
35262
+ });
35263
+ }
35264
+ notify(method, params) {
35265
+ this.write({ jsonrpc: "2.0", method, params });
35266
+ }
35267
+ // server-request 的响应也必须带 jsonrpc:'2.0',否则 codex app-server 忽略它 → 审批/问答永远卡住。
35268
+ respond(id, result) {
35269
+ this.write({ jsonrpc: "2.0", id, result });
35270
+ }
35271
+ onLine(line) {
35272
+ const t = line.trim();
35273
+ if (!t) return;
35274
+ let m2;
35275
+ try {
35276
+ m2 = JSON.parse(t);
35277
+ } catch {
35278
+ return;
35279
+ }
35280
+ if (!isRecord(m2)) return;
35281
+ const hasId = typeof m2.id === "number", hasMethod = typeof m2.method === "string";
35282
+ if (hasId && !hasMethod) {
35283
+ const p2 = this.pending.get(m2.id);
35284
+ if (!p2) return;
35285
+ this.pending.delete(m2.id);
35286
+ if (m2.error) {
35287
+ const e = isRecord(m2.error) ? m2.error : {};
35288
+ p2.reject(new Error(typeof e.message === "string" ? e.message : "app-server error"));
35289
+ } else p2.resolve(m2.result);
35290
+ return;
35291
+ }
35292
+ if (hasId && hasMethod) {
35293
+ this.opts.onServerRequest?.(m2.id, m2.method, m2.params);
35294
+ return;
35295
+ }
35296
+ if (hasMethod) this.opts.onNotification?.(m2.method, m2.params);
35297
+ }
35298
+ write(o) {
35299
+ this.proc.stdin.write(JSON.stringify(o) + "\n");
35300
+ }
35301
+ };
35302
+ function isRecord(v2) {
35303
+ return typeof v2 === "object" && v2 !== null;
35304
+ }
35305
+
35306
+ // src/tools/codex-app-server-events.ts
35307
+ function translateNotification(method, params) {
35308
+ const p2 = rec(params);
35309
+ switch (method) {
35310
+ case "thread/started": {
35311
+ const id = str(rec(p2?.thread)?.id);
35312
+ return id ? [{ kind: "session_init", toolSessionId: id }] : [];
35313
+ }
35314
+ case "item/agentMessage/delta": {
35315
+ const text = str(p2?.delta);
35316
+ const id = str(p2?.itemId);
35317
+ return text ? [{ kind: "text", text, ...id ? { partialId: id } : {} }] : [];
35318
+ }
35319
+ case "item/reasoning/textDelta":
35320
+ case "item/reasoning/summaryTextDelta": {
35321
+ const text = str(p2?.delta);
35322
+ const id = str(p2?.itemId);
35323
+ return text ? [{ kind: "thinking", text, ...id ? { partialId: id } : {} }] : [];
35324
+ }
35325
+ case "item/commandExecution/outputDelta":
35326
+ return [];
35327
+ // 命令输出增量 v1 不逐字(完成时整段给)
35328
+ case "item/started":
35329
+ return itemStarted(rec(p2?.item));
35330
+ case "item/completed":
35331
+ return itemCompleted(rec(p2?.item));
35332
+ case "thread/tokenUsage/updated":
35333
+ return tokenUsage(rec(rec(p2?.tokenUsage)));
35334
+ case "turn/completed":
35335
+ return turnCompleted(rec(p2?.turn));
35336
+ default:
35337
+ return [];
35338
+ }
35339
+ }
35340
+ function itemStarted(item) {
35341
+ if (!item) return [];
35342
+ const id = str(item.id);
35343
+ if (!id) return [];
35344
+ if (item.type === "commandExecution") {
35345
+ return [{ kind: "tool_call", toolUseId: id, tool: "commandExecution", toolKind: "codex", input: { command: str(item.command) ?? "" } }];
35346
+ }
35347
+ if (item.type === "fileChange") {
35348
+ return [{ kind: "tool_call", toolUseId: id, tool: "fileChange", toolKind: "codex", input: { changes: Array.isArray(item.changes) ? item.changes : [] } }];
35349
+ }
35350
+ return [];
35351
+ }
35352
+ function itemCompleted(item) {
35353
+ if (!item) return [];
35354
+ switch (item.type) {
35355
+ case "userMessage":
35356
+ return [];
35357
+ // 用户输入回显, clawd 自己 synthesize user_text
35358
+ case "agentMessage": {
35359
+ const text = str(item.text);
35360
+ return text ? [{ kind: "text", text }] : [];
35361
+ }
35362
+ case "reasoning": {
35363
+ const text = str(item.text);
35364
+ return text ? [{ kind: "thinking", text }] : [];
35365
+ }
35366
+ case "commandExecution": {
35367
+ const id = str(item.id);
35368
+ if (!id) return [];
35369
+ const exit = num(item.exitCode);
35370
+ const ev = { kind: "tool_result", toolUseId: id, output: str(item.aggregatedOutput ?? item.output) ?? "" };
35371
+ if (exit !== void 0 && exit !== 0) ev.error = `exit ${exit}`;
35372
+ return [ev];
35373
+ }
35374
+ case "fileChange": {
35375
+ const id = str(item.id);
35376
+ if (!id) return [];
35377
+ const changes = Array.isArray(item.changes) ? item.changes : [];
35378
+ const output = changes.map((c) => str(c.diff) ?? "").filter(Boolean).join("\n");
35379
+ const ev = { kind: "tool_result", toolUseId: id, output };
35380
+ const status = str(item.status);
35381
+ if (status === "failed" || status === "declined") ev.error = `patch ${status}`;
35382
+ return [ev];
35383
+ }
35384
+ default:
35385
+ return [];
35386
+ }
35387
+ }
35388
+ function tokenUsage(usage) {
35389
+ if (!usage) return [];
35390
+ const last = rec(usage.last);
35391
+ if (!last) return [];
35392
+ const i = num(last.inputTokens), o = num(last.outputTokens);
35393
+ const patch = {};
35394
+ if (i !== void 0 && o !== void 0) patch.contextUsage = { inputTokens: i, outputTokens: o };
35395
+ const w2 = num(usage.modelContextWindow);
35396
+ if (w2 !== void 0) patch.contextWindowSize = w2;
35397
+ return Object.keys(patch).length ? [{ kind: "meta_update", patch }] : [];
35398
+ }
35399
+ function turnCompleted(turn) {
35400
+ if (turn?.status === "failed") return [{ kind: "error", message: str(rec(turn.error)?.message) ?? "codex turn failed" }, { kind: "turn_end" }];
35401
+ return [{ kind: "turn_end" }];
35402
+ }
35403
+ function rec(v2) {
35404
+ return typeof v2 === "object" && v2 !== null ? v2 : void 0;
35405
+ }
35406
+ function str(v2) {
35407
+ return typeof v2 === "string" ? v2 : void 0;
35408
+ }
35409
+ function num(v2) {
35410
+ return typeof v2 === "number" ? v2 : void 0;
35411
+ }
35412
+
35413
+ // src/tools/codex-app-server-params.ts
35414
+ function resolveSandbox(ctx) {
35415
+ if (ctx.personaMode === "guest") return "workspace-write";
35416
+ return "danger-full-access";
35417
+ }
35418
+ function resolveApprovalPolicy(ctx) {
35419
+ if (ctx.personaMode === "owner" || ctx.personaMode === "guest") return "never";
35420
+ const m2 = ctx.permissionMode ?? "";
35421
+ if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
35422
+ return "on-request";
35423
+ }
35424
+ function threadStartParams(ctx) {
35425
+ const params = {
35426
+ cwd: ctx.cwd,
35427
+ sandbox: resolveSandbox(ctx),
35428
+ approvalPolicy: resolveApprovalPolicy(ctx),
35429
+ approvalsReviewer: "user",
35430
+ ...ctx.model ? { model: ctx.model } : {}
35431
+ };
35432
+ if (ctx.personaMode === "guest") {
35433
+ params.config = {
35434
+ sandbox_workspace_write: { writable_roots: ctx.addDirs ?? [], network_access: ctx.networkAccess ?? false }
35435
+ };
35436
+ }
35437
+ return params;
35438
+ }
35439
+ var ATTACHMENT_RE2 = /\[attachment:(image|file):([^\]]+)\]/g;
35440
+ var SKILL_RE = /\[skill:(.+?):(\/[^\]]+)\]/g;
35441
+ function turnStartInput(text) {
35442
+ const items = [];
35443
+ let leftover = text;
35444
+ for (const m2 of text.matchAll(SKILL_RE)) {
35445
+ const [marker, name, path59] = m2;
35446
+ items.push({ type: "skill", name, path: path59 });
35447
+ leftover = leftover.replace(marker, "");
35448
+ }
35449
+ for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
35450
+ const [marker, kind, url] = m2;
35451
+ if (kind === "image") {
35452
+ items.push({ type: "image", url });
35453
+ leftover = leftover.replace(marker, "");
35454
+ }
35455
+ }
35456
+ const trimmed = leftover.trim();
35457
+ if (trimmed || items.length === 0) items.push({ type: "text", text: trimmed, text_elements: [] });
35458
+ return items;
35459
+ }
35460
+
35461
+ // src/tools/codex-session.ts
35462
+ function createCodexSession(ctx, sink, deps = {}) {
35463
+ const cmd = process.env.CODEX_BIN ?? "codex";
35464
+ const args = ["app-server", "--listen", "stdio://"];
35465
+ const env = { ...process.env, ...ctx.env };
35466
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process3.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
35467
+ let threadId = ctx.toolSessionId;
35468
+ let turnId;
35469
+ const approvalIds = /* @__PURE__ */ new Map();
35470
+ let pendingSystemPrompt = ctx.toolSessionId ? void 0 : ctx.extraSystemPrompt;
35471
+ const effort = ctx.effort;
35472
+ let exited = false;
35473
+ const finish = (code) => {
35474
+ if (exited) return;
35475
+ exited = true;
35476
+ sink.onExit(code);
35477
+ };
35478
+ const client = new CodexAppServerClient(proc, {
35479
+ onNotification: (method, params) => {
35480
+ if (method === "turn/started") {
35481
+ const id = params?.turn?.id;
35482
+ if (id) turnId = id;
35483
+ }
35484
+ const events = translateNotification(method, params);
35485
+ if (events.length) sink.pushEvents(events);
35486
+ },
35487
+ onServerRequest: (id, method, params) => {
35488
+ const p2 = params ?? {};
35489
+ if (method === "item/commandExecution/requestApproval" || method === "item/fileChange/requestApproval") {
35490
+ const reqId = String(id);
35491
+ approvalIds.set(reqId, id);
35492
+ sink.pushEvents([
35493
+ {
35494
+ kind: "permission_request",
35495
+ requestId: reqId,
35496
+ tool: method.includes("fileChange") ? "fileChange" : "commandExecution",
35497
+ input: p2,
35498
+ ...typeof p2.itemId === "string" ? { toolUseId: p2.itemId } : {}
35499
+ }
35500
+ ]);
35501
+ return;
35502
+ }
35503
+ client.respond(id, "cancel");
35504
+ },
35505
+ onClose: () => finish(proc.exitCode)
35506
+ });
35507
+ proc.stderr?.on(
35508
+ "data",
35509
+ (c) => deps.logger?.warn("codex app-server stderr", { line: c.toString().slice(0, 500) })
35510
+ );
35511
+ proc.on("error", (err) => {
35512
+ const message = err.message;
35513
+ deps.logger?.error("codex app-server spawn failed", { message });
35514
+ sink.onError(`codex app-server spawn failed: ${message}`);
35515
+ });
35516
+ proc.on("exit", (code) => finish(code));
35517
+ const ready = (async () => {
35518
+ await client.request("initialize", {
35519
+ clientInfo: { name: "clawd", title: "clawd", version: "0" },
35520
+ capabilities: null
35521
+ });
35522
+ client.notify("initialized", {});
35523
+ if (threadId) {
35524
+ await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
35525
+ } else {
35526
+ const res = await client.request("thread/start", threadStartParams(ctx));
35527
+ threadId = res?.thread?.id;
35528
+ if (threadId) sink.pushEvents([{ kind: "session_init", toolSessionId: threadId }]);
35529
+ }
35530
+ })().catch((e) => sink.onError(`codex app-server init failed: ${e.message}`));
35531
+ return {
35532
+ startTurn(text) {
35533
+ const body = pendingSystemPrompt ? `${pendingSystemPrompt}
35534
+
35535
+ ${text}` : text;
35536
+ pendingSystemPrompt = void 0;
35537
+ void ready.then(() => {
35538
+ if (threadId)
35539
+ void client.request("turn/start", {
35540
+ threadId,
35541
+ input: turnStartInput(body),
35542
+ // TurnStartParams 字段是 `effort`(不是 `reasoningEffort`,0.138 改名)——传错名字
35543
+ // codex 静默忽略, reasoning effort 改了不生效。"override for this turn and subsequent turns"。
35544
+ ...effort ? { effort } : {}
35545
+ }).catch((e) => sink.onError(`turn/start failed: ${e.message}`));
35546
+ });
35547
+ },
35548
+ respondPermission(requestId, allow) {
35549
+ const id = approvalIds.get(requestId);
35550
+ if (id === void 0) return;
35551
+ approvalIds.delete(requestId);
35552
+ client.respond(id, { decision: allow ? "accept" : "decline" });
35553
+ },
35554
+ interrupt() {
35555
+ if (threadId && turnId) {
35556
+ void client.request("turn/interrupt", { threadId, turnId }).catch(() => {
35557
+ });
35558
+ return;
35559
+ }
35560
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
35561
+ },
35562
+ // signal 由 runner 透传 reducer 的 kill effect(runtime-patch / stop 恒 SIGKILL),与 claude doKill 语义统一:
35563
+ // SIGTERM 兜底会在 app-server 卡死收不到时泄漏进程,故尊重 SIGKILL 强杀。
35564
+ async stop(signal = "SIGTERM") {
35565
+ if (threadId && turnId) void client.request("turn/interrupt", { threadId, turnId }).catch(() => {
35566
+ });
35567
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill(signal);
35568
+ }
35569
+ };
35570
+ }
35571
+
35572
+ // src/tools/codex.ts
35573
+ var CODEX_MODELS = [
35574
+ { id: "", label: "Default", description: "codex config.toml \u9ED8\u8BA4", contextWindowSize: 258400, default: true },
35575
+ { id: "gpt-5.5", label: "GPT-5.5", description: "Frontier model for complex coding", contextWindowSize: 258400 },
35576
+ { id: "gpt-5.4", label: "GPT-5.4", contextWindowSize: 258400 },
35577
+ { id: "gpt-5.4-mini", label: "GPT-5.4-Mini", contextWindowSize: 258400 }
35578
+ ];
35579
+ var CODEX_EFFORTS = [
35580
+ { value: "low", label: "Low", description: "Fast responses with lighter reasoning" },
35581
+ { value: "medium", label: "Medium", description: "Balances speed and reasoning depth for everyday tasks" },
35582
+ { value: "high", label: "High", description: "Greater reasoning depth for complex problems" },
35583
+ { value: "xhigh", label: "Extra high", description: "Extra high reasoning depth for complex problems" }
35584
+ ];
35585
+ var CODEX_APPROVAL_PRESETS = [
35586
+ { id: "untrusted", label: "Ask for approval", description: "\u51E0\u4E4E\u6BCF\u6761\u547D\u4EE4\u90FD\u95EE\u4F60\uFF08\u6700\u8C28\u614E\uFF09" },
35587
+ { id: "on-request", label: "Approve for me", description: "\u6A21\u578B\u81EA\u5DF1\u5224\u65AD\uFF0C\u53EA\u5BF9\u9AD8\u98CE\u9669\u64CD\u4F5C\u95EE\u4F60\uFF08\u9ED8\u8BA4\uFF09" },
35588
+ { id: "never", label: "Full Access", description: "\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" }
35589
+ ];
35590
+ var CODEX_CAPABILITIES = {
35591
+ tool: "codex",
35592
+ toolSessionIdLabel: "Codex Thread ID",
35593
+ models: CODEX_MODELS,
35594
+ permissionModes: CODEX_APPROVAL_PRESETS,
35595
+ // codex 不支持这些 clawd 功能(rewind 无 file-snapshot / 无子 agent / 无 TUI pty /
35596
+ // 无 observe 推送 / 无文件分享 / fork 是 claude jsonl 专用);UI 据此 gate 入口。
35597
+ features: { rewind: false, subagents: false, tui: false, observe: false, fileSharing: false, fork: false },
35598
+ configSchema: [
35599
+ {
35600
+ name: "model",
35601
+ type: "select",
35602
+ label: "Model",
35603
+ scope: "core",
35604
+ options: CODEX_MODELS.map((m2) => ({ value: m2.id, label: m2.label, description: m2.description })),
35605
+ default: ""
35606
+ },
35607
+ {
35608
+ name: "permissionMode",
35609
+ type: "select",
35610
+ label: "Approval",
35611
+ scope: "core",
35612
+ options: CODEX_APPROVAL_PRESETS.map((m2) => ({ value: m2.id, label: m2.label, description: m2.description })),
35613
+ default: "on-request"
35614
+ },
35615
+ {
35616
+ name: "effort",
35617
+ type: "select",
35618
+ label: "Reasoning effort",
35619
+ scope: "tool-specific",
35620
+ // 渲染在 Advanced 区(与 claude effort 一致)
35621
+ options: CODEX_EFFORTS,
35622
+ default: "medium"
35623
+ }
35624
+ ]
35625
+ };
35626
+ function sanitizeCodexModel(model) {
35627
+ if (model === void 0) return void 0;
35628
+ return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
35629
+ }
35630
+ async function probeCodex(env = process.env) {
35631
+ if (env.CODEX_BIN && import_node_fs10.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
35632
+ try {
35633
+ const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
35634
+ if (out && import_node_fs10.default.existsSync(out)) return { available: true, path: out };
35635
+ } catch {
35636
+ }
35637
+ return { available: false };
35638
+ }
35639
+ var CodexAdapter = class {
35640
+ id = "codex";
35641
+ // 历史读取器:history:read 按 session.tool 路由到这里(thread/read)。
35642
+ historyReader;
35643
+ probeCache = null;
35644
+ logger;
35645
+ probeOverride;
35646
+ constructor(opts = {}) {
35647
+ this.logger = opts.logger;
35648
+ this.probeOverride = opts.probeOverride;
35649
+ this.historyReader = opts.historyReader;
35650
+ }
35651
+ async probe() {
35652
+ if (this.probeCache) return this.probeCache;
35653
+ this.probeCache = this.probeOverride ? await this.probeOverride() : await probeCodex();
35654
+ return this.probeCache;
35655
+ }
35656
+ async capabilities() {
35657
+ return CODEX_CAPABILITIES;
35658
+ }
35659
+ resolveContextWindow(modelId) {
35660
+ return (CODEX_MODELS.find((m2) => m2.id === (modelId ?? "")) ?? CODEX_MODELS[0]).contextWindowSize;
35661
+ }
35662
+ createSession(ctx, sink) {
35663
+ return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, { logger: this.logger });
35664
+ }
35665
+ spawn(_ctx) {
35666
+ throw new Error("CodexAdapter uses createSession, not spawn");
35667
+ }
35668
+ parseLine(_line) {
35669
+ return [];
35670
+ }
35671
+ // 原样返回带 marker 的文本;附件 marker → codex image 多模态由 turnStartInput 解析
35672
+ // (codex-app-server-params.ts, PR1)。encodeStdin 不动 markers。
35673
+ encodeStdin(text, _ctx) {
35674
+ return text;
35675
+ }
35676
+ };
35677
+
35678
+ // src/tools/claude-tui.ts
35679
+ var import_node_fs11 = __toESM(require("fs"), 1);
35159
35680
  var import_node_os5 = __toESM(require("os"), 1);
35160
35681
  var import_node_path10 = __toESM(require("path"), 1);
35161
35682
  var import_headless = __toESM(require_xterm_headless(), 1);
@@ -36139,7 +36660,7 @@ function jsonlExistsForCtx(ctx) {
36139
36660
  const home = import_node_os5.default.homedir();
36140
36661
  const file = import_node_path10.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
36141
36662
  try {
36142
- return import_node_fs10.default.statSync(file).isFile();
36663
+ return import_node_fs11.default.statSync(file).isFile();
36143
36664
  } catch {
36144
36665
  return false;
36145
36666
  }
@@ -36148,8 +36669,238 @@ function jsonlExistsForCtx(ctx) {
36148
36669
  // src/index.ts
36149
36670
  init_claude_history();
36150
36671
 
36672
+ // src/tools/codex-history.ts
36673
+ var import_node_child_process5 = require("child_process");
36674
+ var DEFAULT_TIMEOUT_MS = 8e3;
36675
+ function rec2(v2) {
36676
+ return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
36677
+ }
36678
+ function str2(v2) {
36679
+ return typeof v2 === "string" ? v2 : void 0;
36680
+ }
36681
+ function num2(v2) {
36682
+ return typeof v2 === "number" && Number.isFinite(v2) ? v2 : void 0;
36683
+ }
36684
+ function userInputText(content) {
36685
+ if (!Array.isArray(content)) return "";
36686
+ return content.map((c) => {
36687
+ const r = rec2(c);
36688
+ return r && r.type === "text" ? str2(r.text) ?? "" : "";
36689
+ }).filter(Boolean).join("");
36690
+ }
36691
+ function threadItemToHistoryMessages(item) {
36692
+ const it = rec2(item);
36693
+ if (!it) return [];
36694
+ switch (it.type) {
36695
+ case "userMessage": {
36696
+ const text = userInputText(it.content);
36697
+ return text ? [{ kind: "user-text", text, raw: item }] : [];
36698
+ }
36699
+ case "agentMessage": {
36700
+ const text = str2(it.text);
36701
+ return text ? [{ kind: "assistant-text", text, raw: item }] : [];
36702
+ }
36703
+ case "commandExecution": {
36704
+ const id = str2(it.id);
36705
+ if (!id) return [];
36706
+ const msgs = [
36707
+ {
36708
+ kind: "tool_call",
36709
+ tool: "commandExecution",
36710
+ toolUseId: id,
36711
+ input: { command: str2(it.command) ?? "" },
36712
+ raw: item
36713
+ }
36714
+ ];
36715
+ if (it.status === "completed" || it.aggregatedOutput != null || it.exitCode != null) {
36716
+ const exit = num2(it.exitCode);
36717
+ const result = {
36718
+ kind: "tool_result",
36719
+ toolUseId: id,
36720
+ output: str2(it.aggregatedOutput) ?? "",
36721
+ raw: item
36722
+ };
36723
+ if (exit !== void 0 && exit !== 0) result.output = `${result.output ?? ""}
36724
+ (exit ${exit})`;
36725
+ msgs.push(result);
36726
+ }
36727
+ return msgs;
36728
+ }
36729
+ default:
36730
+ return [];
36731
+ }
36732
+ }
36733
+ async function queryCodexAppServer(cwd, method, params, deps) {
36734
+ const cmd = process.env.CODEX_BIN ?? "codex";
36735
+ const args = ["app-server", "--listen", "stdio://"];
36736
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process5.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
36737
+ const client = new CodexAppServerClient(proc, {});
36738
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS;
36739
+ let timer;
36740
+ const timeout = new Promise((_2, reject) => {
36741
+ timer = setTimeout(() => reject(new Error(`codex app-server ${method} timed out after ${timeoutMs}ms`)), timeoutMs);
36742
+ proc.on("error", (err) => reject(new Error(`codex app-server spawn failed: ${err.message}`)));
36743
+ });
36744
+ try {
36745
+ await Promise.race([
36746
+ (async () => {
36747
+ await client.request("initialize", {
36748
+ clientInfo: { name: "clawd", title: "clawd", version: "0" },
36749
+ capabilities: null
36750
+ });
36751
+ client.notify("initialized", {});
36752
+ })(),
36753
+ timeout
36754
+ ]);
36755
+ return await Promise.race([client.request(method, params), timeout]);
36756
+ } finally {
36757
+ if (timer) clearTimeout(timer);
36758
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
36759
+ }
36760
+ }
36761
+ var CodexHistoryReader = class {
36762
+ deps;
36763
+ constructor(deps = {}) {
36764
+ this.deps = deps;
36765
+ }
36766
+ // v1 先返回 []:projects/list 非 session-scoped、不知 tool,跨-tool 项目浏览器合并排后续。
36767
+ // codex 旧会话仍能经 clawd 活跃列表(session:list, tool-agnostic) + read 打开。
36768
+ async listProjects() {
36769
+ return [];
36770
+ }
36771
+ async listSessions(args) {
36772
+ const res = rec2(
36773
+ await queryCodexAppServer(
36774
+ args.projectPath,
36775
+ "thread/list",
36776
+ {
36777
+ limit: 100,
36778
+ sortKey: "updated_at",
36779
+ sortDirection: "desc",
36780
+ archived: false,
36781
+ cwd: args.projectPath,
36782
+ useStateDbOnly: true
36783
+ },
36784
+ this.deps
36785
+ )
36786
+ );
36787
+ const data = res && Array.isArray(res.data) ? res.data : [];
36788
+ const out = [];
36789
+ for (const entry of data) {
36790
+ const e = rec2(entry);
36791
+ const id = e && str2(e.id);
36792
+ if (!e || !id) continue;
36793
+ const updatedAtMs = Math.round((num2(e.updatedAt) ?? 0) * 1e3);
36794
+ out.push({
36795
+ toolSessionId: id,
36796
+ summary: str2(e.preview) || "(\u7A7A\u4F1A\u8BDD)",
36797
+ messageCount: 0,
36798
+ // thread/list 不提供条数;活跃/read 时才知
36799
+ updatedAt: new Date(updatedAtMs).toISOString()
36800
+ });
36801
+ }
36802
+ return out;
36803
+ }
36804
+ async read(args) {
36805
+ const res = rec2(
36806
+ await queryCodexAppServer(
36807
+ args.cwd,
36808
+ "thread/read",
36809
+ { threadId: args.toolSessionId, includeTurns: true },
36810
+ this.deps
36811
+ )
36812
+ );
36813
+ const thread = res && rec2(res.thread);
36814
+ const turns = thread && Array.isArray(thread.turns) ? thread.turns : [];
36815
+ const messages = [];
36816
+ for (const turn of turns) {
36817
+ const t = rec2(turn);
36818
+ const items = t && Array.isArray(t.items) ? t.items : [];
36819
+ for (const item of items) messages.push(...threadItemToHistoryMessages(item));
36820
+ }
36821
+ const total = messages.length;
36822
+ const limit = args.limit ?? total;
36823
+ const offset = typeof args.offset === "number" ? Math.min(Math.max(0, args.offset), total) : Math.max(0, total - limit);
36824
+ return { messages: messages.slice(offset, offset + limit), total, offset };
36825
+ }
36826
+ // codex 无 sidechain 子 agent / file-history-snapshot → 全 stub 空(对齐 claude-history 同方法空返回)
36827
+ async listSubagents() {
36828
+ return [];
36829
+ }
36830
+ async readSubagent() {
36831
+ return { messages: [] };
36832
+ }
36833
+ computeRewindDiff() {
36834
+ return { canRewind: false, files: [], totalInsertions: 0, totalDeletions: 0 };
36835
+ }
36836
+ listRewindableUserMessageIds() {
36837
+ return [];
36838
+ }
36839
+ };
36840
+
36841
+ // src/tools/codex-skills.ts
36842
+ var import_node_child_process6 = require("child_process");
36843
+ var DEFAULT_TIMEOUT_MS2 = 8e3;
36844
+ function str3(v2) {
36845
+ return typeof v2 === "string" ? v2 : void 0;
36846
+ }
36847
+ function mapSkillsListResponse(res) {
36848
+ const data = res?.data;
36849
+ if (!Array.isArray(data)) return [];
36850
+ const out = [];
36851
+ for (const entry of data) {
36852
+ const skills = entry?.skills;
36853
+ if (!Array.isArray(skills)) continue;
36854
+ for (const s of skills) {
36855
+ const r = s ?? {};
36856
+ const name = str3(r.name);
36857
+ if (!name) continue;
36858
+ const path59 = str3(r.path);
36859
+ const description = str3(r.description);
36860
+ const isPlugin = name.includes(":");
36861
+ out.push({
36862
+ name,
36863
+ source: isPlugin ? "plugin" : "project",
36864
+ ...path59 ? { path: path59 } : {},
36865
+ ...description ? { description } : {},
36866
+ ...isPlugin ? { plugin: name.split(":")[0] } : {}
36867
+ });
36868
+ }
36869
+ }
36870
+ return out;
36871
+ }
36872
+ async function listCodexSkills(cwd, deps = {}) {
36873
+ const cmd = process.env.CODEX_BIN ?? "codex";
36874
+ const args = ["app-server", "--listen", "stdio://"];
36875
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
36876
+ const client = new CodexAppServerClient(proc, {});
36877
+ const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
36878
+ let timer;
36879
+ const timeout = new Promise((_2, reject) => {
36880
+ timer = setTimeout(() => reject(new Error(`codex app-server skills/list timed out after ${timeoutMs}ms`)), timeoutMs);
36881
+ proc.on("error", (err) => reject(new Error(`codex app-server spawn failed: ${err.message}`)));
36882
+ });
36883
+ try {
36884
+ await Promise.race([
36885
+ (async () => {
36886
+ await client.request("initialize", {
36887
+ clientInfo: { name: "clawd", title: "clawd", version: "0" },
36888
+ capabilities: null
36889
+ });
36890
+ client.notify("initialized", {});
36891
+ })(),
36892
+ timeout
36893
+ ]);
36894
+ const res = await Promise.race([client.request("skills/list", { cwds: [cwd] }), timeout]);
36895
+ return mapSkillsListResponse(res);
36896
+ } finally {
36897
+ if (timer) clearTimeout(timer);
36898
+ if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGTERM");
36899
+ }
36900
+ }
36901
+
36151
36902
  // src/workspace/browser.ts
36152
- var import_node_fs11 = __toESM(require("fs"), 1);
36903
+ var import_node_fs12 = __toESM(require("fs"), 1);
36153
36904
  var import_node_os6 = __toESM(require("os"), 1);
36154
36905
  var import_node_path11 = __toESM(require("path"), 1);
36155
36906
  init_protocol();
@@ -36165,7 +36916,7 @@ function resolveInsideCwd(cwd, subpath) {
36165
36916
  }
36166
36917
  function ensureCwd(cwd) {
36167
36918
  try {
36168
- const stat = import_node_fs11.default.statSync(cwd);
36919
+ const stat = import_node_fs12.default.statSync(cwd);
36169
36920
  if (!stat.isDirectory()) {
36170
36921
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
36171
36922
  }
@@ -36179,7 +36930,7 @@ var WorkspaceBrowser = class {
36179
36930
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
36180
36931
  ensureCwd(cwd);
36181
36932
  const full = resolveInsideCwd(cwd, args.path);
36182
- const dirents = import_node_fs11.default.readdirSync(full, { withFileTypes: true });
36933
+ const dirents = import_node_fs12.default.readdirSync(full, { withFileTypes: true });
36183
36934
  const entries = [];
36184
36935
  for (const d of dirents) {
36185
36936
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -36189,7 +36940,7 @@ var WorkspaceBrowser = class {
36189
36940
  mtime: ""
36190
36941
  };
36191
36942
  try {
36192
- const st = import_node_fs11.default.statSync(import_node_path11.default.join(full, d.name));
36943
+ const st = import_node_fs12.default.statSync(import_node_path11.default.join(full, d.name));
36193
36944
  entry.mtime = new Date(st.mtimeMs).toISOString();
36194
36945
  if (d.isFile()) entry.size = st.size;
36195
36946
  } catch {
@@ -36205,14 +36956,14 @@ var WorkspaceBrowser = class {
36205
36956
  read(args) {
36206
36957
  ensureCwd(args.cwd);
36207
36958
  const full = resolveInsideCwd(args.cwd, args.path);
36208
- const st = import_node_fs11.default.statSync(full);
36959
+ const st = import_node_fs12.default.statSync(full);
36209
36960
  if (!st.isFile()) {
36210
36961
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
36211
36962
  }
36212
36963
  if (st.size > MAX_FILE_BYTES) {
36213
36964
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
36214
36965
  }
36215
- const buf = import_node_fs11.default.readFileSync(full);
36966
+ const buf = import_node_fs12.default.readFileSync(full);
36216
36967
  const isBinary = buf.includes(0);
36217
36968
  if (isBinary) {
36218
36969
  return {
@@ -36234,20 +36985,20 @@ var WorkspaceBrowser = class {
36234
36985
  };
36235
36986
 
36236
36987
  // src/skills/agents-scanner.ts
36237
- var import_node_fs12 = __toESM(require("fs"), 1);
36988
+ var import_node_fs13 = __toESM(require("fs"), 1);
36238
36989
  var import_node_os7 = __toESM(require("os"), 1);
36239
36990
  var import_node_path12 = __toESM(require("path"), 1);
36240
36991
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
36241
36992
  function isDirLikeSync2(p2) {
36242
36993
  try {
36243
- return import_node_fs12.default.statSync(p2).isDirectory();
36994
+ return import_node_fs13.default.statSync(p2).isDirectory();
36244
36995
  } catch {
36245
36996
  return false;
36246
36997
  }
36247
36998
  }
36248
36999
  function fileExistsSync(p2) {
36249
37000
  try {
36250
- return import_node_fs12.default.statSync(p2).isFile();
37001
+ return import_node_fs13.default.statSync(p2).isFile();
36251
37002
  } catch {
36252
37003
  return false;
36253
37004
  }
@@ -36255,7 +37006,7 @@ function fileExistsSync(p2) {
36255
37006
  function parseAgentFile(filePath) {
36256
37007
  let content;
36257
37008
  try {
36258
- content = import_node_fs12.default.readFileSync(filePath, "utf8");
37009
+ content = import_node_fs13.default.readFileSync(filePath, "utf8");
36259
37010
  } catch {
36260
37011
  return {};
36261
37012
  }
@@ -36268,7 +37019,7 @@ function parseAgentFile(filePath) {
36268
37019
  function scanAgentsDir(dir, source, seen, out) {
36269
37020
  let entries;
36270
37021
  try {
36271
- entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
37022
+ entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
36272
37023
  } catch {
36273
37024
  return;
36274
37025
  }
@@ -36295,7 +37046,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
36295
37046
  function walk2(dir, namespaces) {
36296
37047
  let entries;
36297
37048
  try {
36298
- entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
37049
+ entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
36299
37050
  } catch {
36300
37051
  return;
36301
37052
  }
@@ -36331,7 +37082,7 @@ function readInstalledPlugins2(home) {
36331
37082
  let raw = null;
36332
37083
  for (const candidate of [v2, v1]) {
36333
37084
  try {
36334
- raw = import_node_fs12.default.readFileSync(candidate, "utf8");
37085
+ raw = import_node_fs13.default.readFileSync(candidate, "utf8");
36335
37086
  break;
36336
37087
  } catch {
36337
37088
  }
@@ -36362,7 +37113,7 @@ function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
36362
37113
  scanAgentsDir(import_node_path12.default.join(cur, ".claude", "agents"), "project", seen, out);
36363
37114
  let hasGit = false;
36364
37115
  try {
36365
- hasGit = import_node_fs12.default.existsSync(import_node_path12.default.join(cur, ".git"));
37116
+ hasGit = import_node_fs13.default.existsSync(import_node_path12.default.join(cur, ".git"));
36366
37117
  } catch {
36367
37118
  }
36368
37119
  if (hasGit) return;
@@ -36425,13 +37176,13 @@ var AgentsScanner = class {
36425
37176
  };
36426
37177
 
36427
37178
  // src/observer/session-observer.ts
36428
- var import_node_fs14 = __toESM(require("fs"), 1);
37179
+ var import_node_fs15 = __toESM(require("fs"), 1);
36429
37180
  var import_node_os9 = __toESM(require("os"), 1);
36430
37181
  var import_node_path14 = __toESM(require("path"), 1);
36431
37182
  init_claude_history();
36432
37183
 
36433
37184
  // src/observer/subagent-meta-observer.ts
36434
- var import_node_fs13 = __toESM(require("fs"), 1);
37185
+ var import_node_fs14 = __toESM(require("fs"), 1);
36435
37186
  var import_node_os8 = __toESM(require("os"), 1);
36436
37187
  var import_node_path13 = __toESM(require("path"), 1);
36437
37188
  init_claude_history();
@@ -36476,7 +37227,7 @@ var SubagentMetaObserver = class {
36476
37227
  attachWatcher(w2) {
36477
37228
  if (w2.watcher) return;
36478
37229
  try {
36479
- w2.watcher = import_node_fs13.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
37230
+ w2.watcher = import_node_fs14.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
36480
37231
  if (!name) return;
36481
37232
  const m2 = META_RE.exec(String(name));
36482
37233
  if (!m2) return;
@@ -36488,7 +37239,7 @@ var SubagentMetaObserver = class {
36488
37239
  scan(w2) {
36489
37240
  let entries;
36490
37241
  try {
36491
- entries = import_node_fs13.default.readdirSync(w2.dirPath);
37242
+ entries = import_node_fs14.default.readdirSync(w2.dirPath);
36492
37243
  } catch {
36493
37244
  return;
36494
37245
  }
@@ -36505,7 +37256,7 @@ var SubagentMetaObserver = class {
36505
37256
  const file = import_node_path13.default.join(w2.dirPath, name);
36506
37257
  let raw;
36507
37258
  try {
36508
- raw = import_node_fs13.default.readFileSync(file, "utf8");
37259
+ raw = import_node_fs14.default.readFileSync(file, "utf8");
36509
37260
  } catch {
36510
37261
  return;
36511
37262
  }
@@ -36569,7 +37320,7 @@ var SessionObserver = class {
36569
37320
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
36570
37321
  let size = 0;
36571
37322
  try {
36572
- size = import_node_fs14.default.statSync(filePath).size;
37323
+ size = import_node_fs15.default.statSync(filePath).size;
36573
37324
  } catch {
36574
37325
  }
36575
37326
  const w2 = {
@@ -36583,10 +37334,10 @@ var SessionObserver = class {
36583
37334
  prevIsRejectSentinel: false
36584
37335
  };
36585
37336
  try {
36586
- import_node_fs14.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
37337
+ import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
36587
37338
  } catch {
36588
37339
  }
36589
- w2.watcher = import_node_fs14.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
37340
+ w2.watcher = import_node_fs15.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
36590
37341
  if (!changedName || !filePath.endsWith(changedName)) return;
36591
37342
  this.poll(w2);
36592
37343
  });
@@ -36609,7 +37360,7 @@ var SessionObserver = class {
36609
37360
  // 异常静默吞,不阻塞 watcher 启动
36610
37361
  hydrateMetaTail(w2, maxLines = 200) {
36611
37362
  try {
36612
- const raw = import_node_fs14.default.readFileSync(w2.filePath, "utf8");
37363
+ const raw = import_node_fs15.default.readFileSync(w2.filePath, "utf8");
36613
37364
  if (!raw) return;
36614
37365
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
36615
37366
  if (allLines.length === 0) return;
@@ -36633,7 +37384,7 @@ var SessionObserver = class {
36633
37384
  poll(w2) {
36634
37385
  let size = 0;
36635
37386
  try {
36636
- size = import_node_fs14.default.statSync(w2.filePath).size;
37387
+ size = import_node_fs15.default.statSync(w2.filePath).size;
36637
37388
  } catch {
36638
37389
  return;
36639
37390
  }
@@ -36642,11 +37393,11 @@ var SessionObserver = class {
36642
37393
  w2.buf = "";
36643
37394
  }
36644
37395
  if (size === w2.lastSize) return;
36645
- const fd = import_node_fs14.default.openSync(w2.filePath, "r");
37396
+ const fd = import_node_fs15.default.openSync(w2.filePath, "r");
36646
37397
  try {
36647
37398
  const len = size - w2.lastSize;
36648
37399
  const buf = Buffer.alloc(len);
36649
- import_node_fs14.default.readSync(fd, buf, 0, len, w2.lastSize);
37400
+ import_node_fs15.default.readSync(fd, buf, 0, len, w2.lastSize);
36650
37401
  w2.lastSize = size;
36651
37402
  w2.buf += buf.toString("utf8");
36652
37403
  let newlineIndex;
@@ -36669,7 +37420,7 @@ var SessionObserver = class {
36669
37420
  }
36670
37421
  }
36671
37422
  } finally {
36672
- import_node_fs14.default.closeSync(fd);
37423
+ import_node_fs15.default.closeSync(fd);
36673
37424
  }
36674
37425
  }
36675
37426
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -37392,14 +38143,14 @@ async function authenticate(token, deps) {
37392
38143
  }
37393
38144
 
37394
38145
  // src/permission/capability-store.ts
37395
- var fs17 = __toESM(require("fs"), 1);
38146
+ var fs18 = __toESM(require("fs"), 1);
37396
38147
  var path19 = __toESM(require("path"), 1);
37397
38148
  var CAPABILITIES_FILE_NAME = "capabilities.json";
37398
38149
  var FILE_VERSION = 1;
37399
38150
  var CapabilityStore = class {
37400
38151
  constructor(dataDir) {
37401
38152
  this.dataDir = dataDir;
37402
- fs17.mkdirSync(dataDir, { recursive: true });
38153
+ fs18.mkdirSync(dataDir, { recursive: true });
37403
38154
  this.cache = this.readFromDisk();
37404
38155
  }
37405
38156
  dataDir;
@@ -37429,7 +38180,7 @@ var CapabilityStore = class {
37429
38180
  const file = this.filePath();
37430
38181
  let raw;
37431
38182
  try {
37432
- raw = fs17.readFileSync(file, "utf8");
38183
+ raw = fs18.readFileSync(file, "utf8");
37433
38184
  } catch (err) {
37434
38185
  if (err?.code === "ENOENT") return [];
37435
38186
  return [];
@@ -37457,10 +38208,10 @@ var CapabilityStore = class {
37457
38208
  }
37458
38209
  atomicWrite(file, content) {
37459
38210
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
37460
- fs17.writeFileSync(tmp, content, { mode: 384 });
37461
- fs17.renameSync(tmp, file);
38211
+ fs18.writeFileSync(tmp, content, { mode: 384 });
38212
+ fs18.renameSync(tmp, file);
37462
38213
  try {
37463
- fs17.chmodSync(file, 384);
38214
+ fs18.chmodSync(file, 384);
37464
38215
  } catch {
37465
38216
  }
37466
38217
  }
@@ -37553,14 +38304,14 @@ var CapabilityManager = class {
37553
38304
  };
37554
38305
 
37555
38306
  // src/permission/cleanup.ts
37556
- var fs18 = __toESM(require("fs"), 1);
38307
+ var fs19 = __toESM(require("fs"), 1);
37557
38308
  function cleanupGuestSessionsForCapability(cap, factory) {
37558
38309
  const removed = [];
37559
38310
  for (const g2 of cap.grants) {
37560
38311
  if (g2.resource.type !== "persona") continue;
37561
38312
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
37562
38313
  try {
37563
- fs18.rmSync(dir, { recursive: true, force: true });
38314
+ fs19.rmSync(dir, { recursive: true, force: true });
37564
38315
  removed.push(dir);
37565
38316
  } catch {
37566
38317
  }
@@ -37569,13 +38320,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
37569
38320
  }
37570
38321
 
37571
38322
  // src/inbox/inbox-store.ts
37572
- var fs19 = __toESM(require("fs"), 1);
38323
+ var fs20 = __toESM(require("fs"), 1);
37573
38324
  var path20 = __toESM(require("path"), 1);
37574
38325
  var INBOX_SUBDIR = "inbox";
37575
38326
  var InboxStore = class {
37576
38327
  constructor(dataDir) {
37577
38328
  this.dataDir = dataDir;
37578
- fs19.mkdirSync(this.dirPath(), { recursive: true });
38329
+ fs20.mkdirSync(this.dirPath(), { recursive: true });
37579
38330
  }
37580
38331
  dataDir;
37581
38332
  /**
@@ -37587,7 +38338,7 @@ var InboxStore = class {
37587
38338
  const file = this.filePath(peerDeviceId);
37588
38339
  let raw;
37589
38340
  try {
37590
- raw = fs19.readFileSync(file, "utf8");
38341
+ raw = fs20.readFileSync(file, "utf8");
37591
38342
  } catch (err) {
37592
38343
  if (err?.code === "ENOENT") return [];
37593
38344
  return [];
@@ -37603,7 +38354,7 @@ var InboxStore = class {
37603
38354
  const dir = this.dirPath();
37604
38355
  let entries;
37605
38356
  try {
37606
- entries = fs19.readdirSync(dir);
38357
+ entries = fs20.readdirSync(dir);
37607
38358
  } catch (err) {
37608
38359
  if (err?.code === "ENOENT") return [];
37609
38360
  return [];
@@ -37619,9 +38370,9 @@ var InboxStore = class {
37619
38370
  if (existing.some((m2) => m2.id === message.id)) return;
37620
38371
  const file = this.filePath(message.peerDeviceId);
37621
38372
  const line = JSON.stringify(message) + "\n";
37622
- fs19.appendFileSync(file, line, { mode: 384 });
38373
+ fs20.appendFileSync(file, line, { mode: 384 });
37623
38374
  try {
37624
- fs19.chmodSync(file, 384);
38375
+ fs20.chmodSync(file, 384);
37625
38376
  } catch {
37626
38377
  }
37627
38378
  }
@@ -37651,7 +38402,7 @@ var InboxStore = class {
37651
38402
  removeByPeerDeviceId(peerDeviceId) {
37652
38403
  const file = this.filePath(peerDeviceId);
37653
38404
  try {
37654
- fs19.unlinkSync(file);
38405
+ fs20.unlinkSync(file);
37655
38406
  } catch (err) {
37656
38407
  if (err?.code === "ENOENT") return;
37657
38408
  }
@@ -37660,10 +38411,10 @@ var InboxStore = class {
37660
38411
  const file = this.filePath(peerDeviceId);
37661
38412
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
37662
38413
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
37663
- fs19.writeFileSync(tmp, content, { mode: 384 });
37664
- fs19.renameSync(tmp, file);
38414
+ fs20.writeFileSync(tmp, content, { mode: 384 });
38415
+ fs20.renameSync(tmp, file);
37665
38416
  try {
37666
- fs19.chmodSync(file, 384);
38417
+ fs20.chmodSync(file, 384);
37667
38418
  } catch {
37668
38419
  }
37669
38420
  }
@@ -37758,7 +38509,7 @@ var InboxManager = class {
37758
38509
  };
37759
38510
 
37760
38511
  // src/state/contact-store.ts
37761
- var fs20 = __toESM(require("fs"), 1);
38512
+ var fs21 = __toESM(require("fs"), 1);
37762
38513
  var path21 = __toESM(require("path"), 1);
37763
38514
  var FILE_NAME = "contacts.json";
37764
38515
  var ContactStore = class {
@@ -37772,7 +38523,7 @@ var ContactStore = class {
37772
38523
  const file = path21.join(this.dataDir, FILE_NAME);
37773
38524
  let raw;
37774
38525
  try {
37775
- raw = fs20.readFileSync(file, "utf8");
38526
+ raw = fs21.readFileSync(file, "utf8");
37776
38527
  } catch (err) {
37777
38528
  if (err?.code !== "ENOENT") this.renameBak(file);
37778
38529
  return;
@@ -37822,13 +38573,13 @@ var ContactStore = class {
37822
38573
  null,
37823
38574
  2
37824
38575
  );
37825
- fs20.mkdirSync(this.dataDir, { recursive: true });
37826
- fs20.writeFileSync(tmp, content, { mode: 384 });
37827
- fs20.renameSync(tmp, file);
38576
+ fs21.mkdirSync(this.dataDir, { recursive: true });
38577
+ fs21.writeFileSync(tmp, content, { mode: 384 });
38578
+ fs21.renameSync(tmp, file);
37828
38579
  }
37829
38580
  renameBak(file) {
37830
38581
  try {
37831
- fs20.renameSync(file, `${file}.bak`);
38582
+ fs21.renameSync(file, `${file}.bak`);
37832
38583
  } catch {
37833
38584
  }
37834
38585
  }
@@ -37963,7 +38714,7 @@ async function autoReverseContact(args) {
37963
38714
  }
37964
38715
 
37965
38716
  // src/migrations/2026-05-20-flatten-sessions.ts
37966
- var fs21 = __toESM(require("fs"), 1);
38717
+ var fs22 = __toESM(require("fs"), 1);
37967
38718
  var path22 = __toESM(require("path"), 1);
37968
38719
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
37969
38720
  function migrateFlattenSessions(opts) {
@@ -37983,7 +38734,7 @@ function migrateFlattenSessions(opts) {
37983
38734
  if (!entry.endsWith(".json")) continue;
37984
38735
  const src = path22.join(defaultDir, entry);
37985
38736
  const dst = path22.join(sessionsDir, entry);
37986
- fs21.renameSync(src, dst);
38737
+ fs22.renameSync(src, dst);
37987
38738
  movedBare += 1;
37988
38739
  }
37989
38740
  rmdirIfEmpty(defaultDir);
@@ -37995,10 +38746,10 @@ function migrateFlattenSessions(opts) {
37995
38746
  const ownerSrc = path22.join(personaDir, "owner");
37996
38747
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
37997
38748
  const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
37998
- fs21.mkdirSync(ownerDst, { recursive: true });
38749
+ fs22.mkdirSync(ownerDst, { recursive: true });
37999
38750
  for (const file of readdirSafe(ownerSrc)) {
38000
38751
  if (!file.endsWith(".json")) continue;
38001
- fs21.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
38752
+ fs22.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
38002
38753
  movedVmOwner += 1;
38003
38754
  }
38004
38755
  rmdirIfEmpty(ownerSrc);
@@ -38006,18 +38757,18 @@ function migrateFlattenSessions(opts) {
38006
38757
  const listenerSrc = path22.join(personaDir, "listener");
38007
38758
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
38008
38759
  const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
38009
- fs21.mkdirSync(archiveDst, { recursive: true });
38760
+ fs22.mkdirSync(archiveDst, { recursive: true });
38010
38761
  for (const file of readdirSafe(listenerSrc)) {
38011
38762
  if (!file.endsWith(".json")) continue;
38012
- fs21.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
38763
+ fs22.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
38013
38764
  archivedListener += 1;
38014
38765
  }
38015
38766
  rmdirIfEmpty(listenerSrc);
38016
38767
  }
38017
38768
  rmdirIfEmpty(personaDir);
38018
38769
  }
38019
- fs21.mkdirSync(sessionsDir, { recursive: true });
38020
- fs21.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
38770
+ fs22.mkdirSync(sessionsDir, { recursive: true });
38771
+ fs22.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
38021
38772
  return {
38022
38773
  skipped: false,
38023
38774
  flagWritten: true,
@@ -38028,7 +38779,7 @@ function migrateFlattenSessions(opts) {
38028
38779
  }
38029
38780
  function existsSync3(p2) {
38030
38781
  try {
38031
- fs21.statSync(p2);
38782
+ fs22.statSync(p2);
38032
38783
  return true;
38033
38784
  } catch {
38034
38785
  return false;
@@ -38036,27 +38787,27 @@ function existsSync3(p2) {
38036
38787
  }
38037
38788
  function isDir(p2) {
38038
38789
  try {
38039
- return fs21.statSync(p2).isDirectory();
38790
+ return fs22.statSync(p2).isDirectory();
38040
38791
  } catch {
38041
38792
  return false;
38042
38793
  }
38043
38794
  }
38044
38795
  function readdirSafe(p2) {
38045
38796
  try {
38046
- return fs21.readdirSync(p2);
38797
+ return fs22.readdirSync(p2);
38047
38798
  } catch {
38048
38799
  return [];
38049
38800
  }
38050
38801
  }
38051
38802
  function rmdirIfEmpty(p2) {
38052
38803
  try {
38053
- fs21.rmdirSync(p2);
38804
+ fs22.rmdirSync(p2);
38054
38805
  } catch {
38055
38806
  }
38056
38807
  }
38057
38808
 
38058
38809
  // src/transport/http-router.ts
38059
- var import_node_fs16 = __toESM(require("fs"), 1);
38810
+ var import_node_fs17 = __toESM(require("fs"), 1);
38060
38811
  var import_node_path18 = __toESM(require("path"), 1);
38061
38812
 
38062
38813
  // src/attachment/mime.ts
@@ -38236,7 +38987,7 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
38236
38987
  }
38237
38988
 
38238
38989
  // src/attachment/upload.ts
38239
- var import_node_fs15 = __toESM(require("fs"), 1);
38990
+ var import_node_fs16 = __toESM(require("fs"), 1);
38240
38991
  var import_node_path16 = __toESM(require("path"), 1);
38241
38992
  var import_node_crypto5 = __toESM(require("crypto"), 1);
38242
38993
  var import_promises = require("stream/promises");
@@ -38258,7 +39009,7 @@ async function writeUploadedAttachment(args) {
38258
39009
  assertValidFileName(args.fileName);
38259
39010
  const attachmentsRoot = import_node_path16.default.join(args.sessionDir, ".attachments");
38260
39011
  try {
38261
- import_node_fs15.default.mkdirSync(attachmentsRoot, { recursive: true });
39012
+ import_node_fs16.default.mkdirSync(attachmentsRoot, { recursive: true });
38262
39013
  } catch (err) {
38263
39014
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
38264
39015
  }
@@ -38279,18 +39030,18 @@ async function writeUploadedAttachment(args) {
38279
39030
  yield buf;
38280
39031
  }
38281
39032
  },
38282
- import_node_fs15.default.createWriteStream(tmpPath, { mode: 384 })
39033
+ import_node_fs16.default.createWriteStream(tmpPath, { mode: 384 })
38283
39034
  );
38284
39035
  } catch (err) {
38285
39036
  try {
38286
- import_node_fs15.default.unlinkSync(tmpPath);
39037
+ import_node_fs16.default.unlinkSync(tmpPath);
38287
39038
  } catch {
38288
39039
  }
38289
39040
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
38290
39041
  }
38291
39042
  if (actualSize !== args.contentLength) {
38292
39043
  try {
38293
- import_node_fs15.default.unlinkSync(tmpPath);
39044
+ import_node_fs16.default.unlinkSync(tmpPath);
38294
39045
  } catch {
38295
39046
  }
38296
39047
  throw new UploadError(
@@ -38303,24 +39054,24 @@ async function writeUploadedAttachment(args) {
38303
39054
  let finalFileName;
38304
39055
  let hashDirExists = false;
38305
39056
  try {
38306
- hashDirExists = import_node_fs15.default.statSync(hashDir).isDirectory();
39057
+ hashDirExists = import_node_fs16.default.statSync(hashDir).isDirectory();
38307
39058
  } catch {
38308
39059
  }
38309
39060
  if (hashDirExists) {
38310
- const existing = import_node_fs15.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
39061
+ const existing = import_node_fs16.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
38311
39062
  finalFileName = existing[0] ?? args.fileName;
38312
39063
  try {
38313
- import_node_fs15.default.unlinkSync(tmpPath);
39064
+ import_node_fs16.default.unlinkSync(tmpPath);
38314
39065
  } catch {
38315
39066
  }
38316
39067
  } else {
38317
39068
  try {
38318
- import_node_fs15.default.mkdirSync(hashDir, { recursive: true });
39069
+ import_node_fs16.default.mkdirSync(hashDir, { recursive: true });
38319
39070
  finalFileName = args.fileName;
38320
- import_node_fs15.default.renameSync(tmpPath, import_node_path16.default.join(hashDir, finalFileName));
39071
+ import_node_fs16.default.renameSync(tmpPath, import_node_path16.default.join(hashDir, finalFileName));
38321
39072
  } catch (err) {
38322
39073
  try {
38323
- import_node_fs15.default.unlinkSync(tmpPath);
39074
+ import_node_fs16.default.unlinkSync(tmpPath);
38324
39075
  } catch {
38325
39076
  }
38326
39077
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
@@ -38844,7 +39595,7 @@ function withCtx(ctx, body) {
38844
39595
  function streamFile(res, absPath, logger) {
38845
39596
  let stat;
38846
39597
  try {
38847
- stat = import_node_fs16.default.statSync(absPath);
39598
+ stat = import_node_fs17.default.statSync(absPath);
38848
39599
  } catch (err) {
38849
39600
  const code = err?.code;
38850
39601
  if (code === "ENOENT") {
@@ -38867,7 +39618,7 @@ function streamFile(res, absPath, logger) {
38867
39618
  // 防止浏览器把任意 mime 当 html 渲染
38868
39619
  "X-Content-Type-Options": "nosniff"
38869
39620
  });
38870
- const stream = import_node_fs16.default.createReadStream(absPath);
39621
+ const stream = import_node_fs17.default.createReadStream(absPath);
38871
39622
  stream.on("error", (err) => {
38872
39623
  logger?.warn("streamFile read error", { absPath, err: err.message });
38873
39624
  res.destroy();
@@ -38876,7 +39627,7 @@ function streamFile(res, absPath, logger) {
38876
39627
  }
38877
39628
 
38878
39629
  // src/attachment/gc.ts
38879
- var import_node_fs17 = __toESM(require("fs"), 1);
39630
+ var import_node_fs18 = __toESM(require("fs"), 1);
38880
39631
  var import_node_path19 = __toESM(require("path"), 1);
38881
39632
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
38882
39633
  function runAttachmentGc(args) {
@@ -38899,7 +39650,7 @@ function runAttachmentGc(args) {
38899
39650
  const attRoot = import_node_path19.default.join(sessionDir, ".attachments");
38900
39651
  let hashDirs;
38901
39652
  try {
38902
- hashDirs = import_node_fs17.default.readdirSync(attRoot);
39653
+ hashDirs = import_node_fs18.default.readdirSync(attRoot);
38903
39654
  } catch (err) {
38904
39655
  if (err.code === "ENOENT") continue;
38905
39656
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
@@ -38909,7 +39660,7 @@ function runAttachmentGc(args) {
38909
39660
  const hashDirAbs = import_node_path19.default.join(attRoot, hashDir);
38910
39661
  let files;
38911
39662
  try {
38912
- files = import_node_fs17.default.readdirSync(hashDirAbs);
39663
+ files = import_node_fs18.default.readdirSync(hashDirAbs);
38913
39664
  } catch {
38914
39665
  continue;
38915
39666
  }
@@ -38917,7 +39668,7 @@ function runAttachmentGc(args) {
38917
39668
  const file = import_node_path19.default.join(hashDirAbs, name);
38918
39669
  let stat;
38919
39670
  try {
38920
- stat = import_node_fs17.default.statSync(file);
39671
+ stat = import_node_fs18.default.statSync(file);
38921
39672
  } catch {
38922
39673
  continue;
38923
39674
  }
@@ -38926,25 +39677,25 @@ function runAttachmentGc(args) {
38926
39677
  if (age < ttlMs) continue;
38927
39678
  if (liveAbs.has(file)) continue;
38928
39679
  try {
38929
- import_node_fs17.default.unlinkSync(file);
39680
+ import_node_fs18.default.unlinkSync(file);
38930
39681
  } catch (err) {
38931
39682
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
38932
39683
  }
38933
39684
  }
38934
39685
  try {
38935
- if (import_node_fs17.default.readdirSync(hashDirAbs).length === 0) import_node_fs17.default.rmdirSync(hashDirAbs);
39686
+ if (import_node_fs18.default.readdirSync(hashDirAbs).length === 0) import_node_fs18.default.rmdirSync(hashDirAbs);
38936
39687
  } catch {
38937
39688
  }
38938
39689
  }
38939
39690
  try {
38940
- if (import_node_fs17.default.readdirSync(attRoot).length === 0) import_node_fs17.default.rmdirSync(attRoot);
39691
+ if (import_node_fs18.default.readdirSync(attRoot).length === 0) import_node_fs18.default.rmdirSync(attRoot);
38941
39692
  } catch {
38942
39693
  }
38943
39694
  }
38944
39695
  }
38945
39696
 
38946
39697
  // src/attachment/group.ts
38947
- var import_node_fs18 = __toESM(require("fs"), 1);
39698
+ var import_node_fs19 = __toESM(require("fs"), 1);
38948
39699
  var import_node_path20 = __toESM(require("path"), 1);
38949
39700
  var import_node_crypto6 = __toESM(require("crypto"), 1);
38950
39701
  init_protocol();
@@ -38970,7 +39721,7 @@ var GroupFileStore = class {
38970
39721
  readFile(scope, sessionId) {
38971
39722
  const file = this.filePath(scope, sessionId);
38972
39723
  try {
38973
- const raw = import_node_fs18.default.readFileSync(file, "utf8");
39724
+ const raw = import_node_fs19.default.readFileSync(file, "utf8");
38974
39725
  const parsed = JSON.parse(raw);
38975
39726
  if (!Array.isArray(parsed)) {
38976
39727
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -38996,10 +39747,10 @@ var GroupFileStore = class {
38996
39747
  }
38997
39748
  writeFile(scope, sessionId, entries) {
38998
39749
  const file = this.filePath(scope, sessionId);
38999
- import_node_fs18.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
39750
+ import_node_fs19.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
39000
39751
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
39001
- import_node_fs18.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
39002
- import_node_fs18.default.renameSync(tmp, file);
39752
+ import_node_fs19.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
39753
+ import_node_fs19.default.renameSync(tmp, file);
39003
39754
  }
39004
39755
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
39005
39756
  list(scope, sessionId) {
@@ -39085,7 +39836,7 @@ var GroupFileStore = class {
39085
39836
  };
39086
39837
 
39087
39838
  // src/discovery/state-file.ts
39088
- var import_node_fs19 = __toESM(require("fs"), 1);
39839
+ var import_node_fs20 = __toESM(require("fs"), 1);
39089
39840
  var import_node_path21 = __toESM(require("path"), 1);
39090
39841
  function defaultStateFilePath(dataDir) {
39091
39842
  return import_node_path21.default.join(dataDir, "state.json");
@@ -39110,7 +39861,7 @@ var StateFileManager = class {
39110
39861
  }
39111
39862
  read() {
39112
39863
  try {
39113
- const raw = import_node_fs19.default.readFileSync(this.file, "utf8");
39864
+ const raw = import_node_fs20.default.readFileSync(this.file, "utf8");
39114
39865
  const parsed = JSON.parse(raw);
39115
39866
  return parsed;
39116
39867
  } catch {
@@ -39124,41 +39875,33 @@ var StateFileManager = class {
39124
39875
  return { status: "stale", existing };
39125
39876
  }
39126
39877
  write(state) {
39127
- import_node_fs19.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
39878
+ import_node_fs20.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
39128
39879
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
39129
- import_node_fs19.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
39130
- import_node_fs19.default.renameSync(tmp, this.file);
39880
+ import_node_fs20.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
39881
+ import_node_fs20.default.renameSync(tmp, this.file);
39131
39882
  if (process.platform !== "win32") {
39132
39883
  try {
39133
- import_node_fs19.default.chmodSync(this.file, 384);
39884
+ import_node_fs20.default.chmodSync(this.file, 384);
39134
39885
  } catch {
39135
39886
  }
39136
39887
  }
39137
39888
  }
39138
39889
  delete() {
39139
39890
  try {
39140
- import_node_fs19.default.unlinkSync(this.file);
39891
+ import_node_fs20.default.unlinkSync(this.file);
39141
39892
  } catch {
39142
39893
  }
39143
39894
  }
39144
39895
  };
39145
39896
 
39146
- // src/discovery/source-from-env.ts
39147
- function readDaemonSourceFromEnv(env = process.env) {
39148
- const v2 = env.CLAWD_DAEMON_SOURCE;
39149
- if (typeof v2 !== "string") return void 0;
39150
- const trimmed = v2.trim();
39151
- return trimmed.length > 0 ? trimmed : void 0;
39152
- }
39153
-
39154
39897
  // src/tunnel/tunnel-manager.ts
39155
- var import_node_fs23 = __toESM(require("fs"), 1);
39898
+ var import_node_fs24 = __toESM(require("fs"), 1);
39156
39899
  var import_node_path25 = __toESM(require("path"), 1);
39157
39900
  var import_node_crypto7 = __toESM(require("crypto"), 1);
39158
- var import_node_child_process5 = require("child_process");
39901
+ var import_node_child_process9 = require("child_process");
39159
39902
 
39160
39903
  // src/tunnel/tunnel-store.ts
39161
- var import_node_fs20 = __toESM(require("fs"), 1);
39904
+ var import_node_fs21 = __toESM(require("fs"), 1);
39162
39905
  var import_node_path22 = __toESM(require("path"), 1);
39163
39906
  var TunnelStore = class {
39164
39907
  constructor(filePath) {
@@ -39167,7 +39910,7 @@ var TunnelStore = class {
39167
39910
  filePath;
39168
39911
  async get() {
39169
39912
  try {
39170
- const raw = await import_node_fs20.default.promises.readFile(this.filePath, "utf8");
39913
+ const raw = await import_node_fs21.default.promises.readFile(this.filePath, "utf8");
39171
39914
  const obj = JSON.parse(raw);
39172
39915
  if (!isPersistedTunnel(obj)) return null;
39173
39916
  return obj;
@@ -39179,21 +39922,21 @@ var TunnelStore = class {
39179
39922
  }
39180
39923
  async set(v2) {
39181
39924
  const dir = import_node_path22.default.dirname(this.filePath);
39182
- await import_node_fs20.default.promises.mkdir(dir, { recursive: true });
39925
+ await import_node_fs21.default.promises.mkdir(dir, { recursive: true });
39183
39926
  const data = JSON.stringify(v2, null, 2);
39184
39927
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
39185
- await import_node_fs20.default.promises.writeFile(tmp, data, { mode: 384 });
39928
+ await import_node_fs21.default.promises.writeFile(tmp, data, { mode: 384 });
39186
39929
  if (process.platform !== "win32") {
39187
39930
  try {
39188
- await import_node_fs20.default.promises.chmod(tmp, 384);
39931
+ await import_node_fs21.default.promises.chmod(tmp, 384);
39189
39932
  } catch {
39190
39933
  }
39191
39934
  }
39192
- await import_node_fs20.default.promises.rename(tmp, this.filePath);
39935
+ await import_node_fs21.default.promises.rename(tmp, this.filePath);
39193
39936
  }
39194
39937
  async clear() {
39195
39938
  try {
39196
- await import_node_fs20.default.promises.unlink(this.filePath);
39939
+ await import_node_fs21.default.promises.unlink(this.filePath);
39197
39940
  } catch (err) {
39198
39941
  const code = err?.code;
39199
39942
  if (code !== "ENOENT") throw err;
@@ -39288,10 +40031,10 @@ function escape(v2) {
39288
40031
  }
39289
40032
 
39290
40033
  // src/tunnel/frpc-binary.ts
39291
- var import_node_fs21 = __toESM(require("fs"), 1);
40034
+ var import_node_fs22 = __toESM(require("fs"), 1);
39292
40035
  var import_node_os11 = __toESM(require("os"), 1);
39293
40036
  var import_node_path23 = __toESM(require("path"), 1);
39294
- var import_node_child_process3 = require("child_process");
40037
+ var import_node_child_process7 = require("child_process");
39295
40038
  var import_node_stream2 = require("stream");
39296
40039
  var import_promises3 = require("stream/promises");
39297
40040
  var FRPC_VERSION = "0.68.0";
@@ -39322,7 +40065,7 @@ function frpcDownloadUrl(version2, p2) {
39322
40065
  }
39323
40066
  async function ensureFrpcBinary(opts) {
39324
40067
  if (opts.override) {
39325
- if (!import_node_fs21.default.existsSync(opts.override)) {
40068
+ if (!import_node_fs22.default.existsSync(opts.override)) {
39326
40069
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
39327
40070
  }
39328
40071
  return opts.override;
@@ -39330,10 +40073,10 @@ async function ensureFrpcBinary(opts) {
39330
40073
  const version2 = opts.version ?? FRPC_VERSION;
39331
40074
  const platform = opts.platform ?? detectPlatform();
39332
40075
  const binDir = import_node_path23.default.join(opts.dataDir, "bin");
39333
- import_node_fs21.default.mkdirSync(binDir, { recursive: true });
40076
+ import_node_fs22.default.mkdirSync(binDir, { recursive: true });
39334
40077
  cleanupStaleArtifacts(binDir);
39335
40078
  const stableBin = import_node_path23.default.join(binDir, "frpc");
39336
- if (import_node_fs21.default.existsSync(stableBin)) return stableBin;
40079
+ if (import_node_fs22.default.existsSync(stableBin)) return stableBin;
39337
40080
  const partialBin = `${stableBin}.partial`;
39338
40081
  const tarballPath = import_node_path23.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
39339
40082
  try {
@@ -39344,8 +40087,8 @@ async function ensureFrpcBinary(opts) {
39344
40087
  } else {
39345
40088
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
39346
40089
  }
39347
- import_node_fs21.default.chmodSync(partialBin, 493);
39348
- import_node_fs21.default.renameSync(partialBin, stableBin);
40090
+ import_node_fs22.default.chmodSync(partialBin, 493);
40091
+ import_node_fs22.default.renameSync(partialBin, stableBin);
39349
40092
  } finally {
39350
40093
  safeUnlink(tarballPath);
39351
40094
  safeUnlink(partialBin);
@@ -39355,7 +40098,7 @@ async function ensureFrpcBinary(opts) {
39355
40098
  function cleanupStaleArtifacts(binDir) {
39356
40099
  let entries;
39357
40100
  try {
39358
- entries = import_node_fs21.default.readdirSync(binDir);
40101
+ entries = import_node_fs22.default.readdirSync(binDir);
39359
40102
  } catch {
39360
40103
  return;
39361
40104
  }
@@ -39363,7 +40106,7 @@ function cleanupStaleArtifacts(binDir) {
39363
40106
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
39364
40107
  const full = import_node_path23.default.join(binDir, name);
39365
40108
  try {
39366
- import_node_fs21.default.rmSync(full, { recursive: true, force: true });
40109
+ import_node_fs22.default.rmSync(full, { recursive: true, force: true });
39367
40110
  } catch {
39368
40111
  }
39369
40112
  }
@@ -39371,7 +40114,7 @@ function cleanupStaleArtifacts(binDir) {
39371
40114
  }
39372
40115
  function safeUnlink(p2) {
39373
40116
  try {
39374
- import_node_fs21.default.unlinkSync(p2);
40117
+ import_node_fs22.default.unlinkSync(p2);
39375
40118
  } catch {
39376
40119
  }
39377
40120
  }
@@ -39382,46 +40125,46 @@ async function downloadToFile(url, dest, fetchImpl) {
39382
40125
  if (!res.ok || !res.body) {
39383
40126
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
39384
40127
  }
39385
- const out = import_node_fs21.default.createWriteStream(dest);
40128
+ const out = import_node_fs22.default.createWriteStream(dest);
39386
40129
  const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
39387
40130
  await (0, import_promises3.pipeline)(nodeStream, out);
39388
40131
  }
39389
40132
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
39390
40133
  const work = import_node_path23.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
39391
- import_node_fs21.default.mkdirSync(work, { recursive: true });
40134
+ import_node_fs22.default.mkdirSync(work, { recursive: true });
39392
40135
  try {
39393
40136
  await new Promise((resolve6, reject) => {
39394
- const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
40137
+ const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
39395
40138
  proc.on("error", reject);
39396
40139
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
39397
40140
  });
39398
40141
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
39399
40142
  const src = import_node_path23.default.join(work, dirName, "frpc");
39400
- if (!import_node_fs21.default.existsSync(src)) {
40143
+ if (!import_node_fs22.default.existsSync(src)) {
39401
40144
  throw new Error(`frpc not found inside tarball at ${src}`);
39402
40145
  }
39403
- import_node_fs21.default.copyFileSync(src, destBin);
40146
+ import_node_fs22.default.copyFileSync(src, destBin);
39404
40147
  } finally {
39405
- import_node_fs21.default.rmSync(work, { recursive: true, force: true });
40148
+ import_node_fs22.default.rmSync(work, { recursive: true, force: true });
39406
40149
  }
39407
40150
  }
39408
40151
 
39409
40152
  // src/tunnel/frpc-process.ts
39410
- var import_node_fs22 = __toESM(require("fs"), 1);
40153
+ var import_node_fs23 = __toESM(require("fs"), 1);
39411
40154
  var import_node_path24 = __toESM(require("path"), 1);
39412
- var import_node_child_process4 = require("child_process");
40155
+ var import_node_child_process8 = require("child_process");
39413
40156
  function frpcPidFilePath(dataDir) {
39414
40157
  return import_node_path24.default.join(dataDir, "frpc.pid");
39415
40158
  }
39416
40159
  function writeFrpcPid(dataDir, pid) {
39417
40160
  try {
39418
- import_node_fs22.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
40161
+ import_node_fs23.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
39419
40162
  } catch {
39420
40163
  }
39421
40164
  }
39422
40165
  function clearFrpcPid(dataDir) {
39423
40166
  try {
39424
- import_node_fs22.default.unlinkSync(frpcPidFilePath(dataDir));
40167
+ import_node_fs23.default.unlinkSync(frpcPidFilePath(dataDir));
39425
40168
  } catch {
39426
40169
  }
39427
40170
  }
@@ -39437,7 +40180,7 @@ function defaultIsPidAlive(pid) {
39437
40180
  }
39438
40181
  function defaultReadPidFile(file) {
39439
40182
  try {
39440
- return import_node_fs22.default.readFileSync(file, "utf8");
40183
+ return import_node_fs23.default.readFileSync(file, "utf8");
39441
40184
  } catch {
39442
40185
  return null;
39443
40186
  }
@@ -39477,7 +40220,7 @@ async function killStaleFrpc(deps) {
39477
40220
  }
39478
40221
  if (victims.size === 0) {
39479
40222
  try {
39480
- import_node_fs22.default.unlinkSync(pidFile);
40223
+ import_node_fs23.default.unlinkSync(pidFile);
39481
40224
  } catch {
39482
40225
  }
39483
40226
  return;
@@ -39488,14 +40231,14 @@ async function killStaleFrpc(deps) {
39488
40231
  }
39489
40232
  await sleep(deps.reapWaitMs ?? 300);
39490
40233
  try {
39491
- import_node_fs22.default.unlinkSync(pidFile);
40234
+ import_node_fs23.default.unlinkSync(pidFile);
39492
40235
  } catch {
39493
40236
  }
39494
40237
  }
39495
40238
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
39496
40239
  if (process.platform === "win32") return [];
39497
40240
  return new Promise((resolve6) => {
39498
- const ps = (0, import_node_child_process4.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
40241
+ const ps = (0, import_node_child_process8.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
39499
40242
  let buf = "";
39500
40243
  ps.stdout.on("data", (c) => {
39501
40244
  buf += c.toString();
@@ -39663,12 +40406,12 @@ var TunnelManager = class {
39663
40406
  localPort,
39664
40407
  logLevel: "info"
39665
40408
  });
39666
- await import_node_fs23.default.promises.writeFile(tomlPath, toml, { mode: 384 });
39667
- const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
40409
+ await import_node_fs24.default.promises.writeFile(tomlPath, toml, { mode: 384 });
40410
+ const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
39668
40411
  stdio: ["ignore", "pipe", "pipe"]
39669
40412
  });
39670
40413
  const logFilePath = import_node_path25.default.join(this.deps.dataDir, "frpc.log");
39671
- const logStream = import_node_fs23.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
40414
+ const logStream = import_node_fs24.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
39672
40415
  logStream.on("error", () => {
39673
40416
  });
39674
40417
  const tee = (chunk) => {
@@ -39766,7 +40509,7 @@ function deriveStableDeviceKey(opts = {}) {
39766
40509
  }
39767
40510
 
39768
40511
  // src/auth-store.ts
39769
- var import_node_fs24 = __toESM(require("fs"), 1);
40512
+ var import_node_fs25 = __toESM(require("fs"), 1);
39770
40513
  var import_node_path27 = __toESM(require("path"), 1);
39771
40514
  var import_node_crypto9 = __toESM(require("crypto"), 1);
39772
40515
  var AUTH_FILE_NAME = "auth.json";
@@ -39805,7 +40548,7 @@ function defaultGenerateOwnerPrincipalId() {
39805
40548
  }
39806
40549
  function readAuthFile(file) {
39807
40550
  try {
39808
- const raw = import_node_fs24.default.readFileSync(file, "utf8");
40551
+ const raw = import_node_fs25.default.readFileSync(file, "utf8");
39809
40552
  const parsed = JSON.parse(raw);
39810
40553
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
39811
40554
  return null;
@@ -39824,16 +40567,16 @@ function readAuthFile(file) {
39824
40567
  }
39825
40568
  }
39826
40569
  function writeAuthFile(file, content) {
39827
- import_node_fs24.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
39828
- import_node_fs24.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
40570
+ import_node_fs25.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
40571
+ import_node_fs25.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
39829
40572
  try {
39830
- import_node_fs24.default.chmodSync(file, 384);
40573
+ import_node_fs25.default.chmodSync(file, 384);
39831
40574
  } catch {
39832
40575
  }
39833
40576
  }
39834
40577
 
39835
40578
  // src/owner-profile.ts
39836
- var import_node_fs25 = __toESM(require("fs"), 1);
40579
+ var import_node_fs26 = __toESM(require("fs"), 1);
39837
40580
  var import_node_os13 = __toESM(require("os"), 1);
39838
40581
  var import_node_path28 = __toESM(require("path"), 1);
39839
40582
  var PROFILE_FILENAME = "profile.json";
@@ -39842,7 +40585,7 @@ function loadOwnerDisplayName(dataDir) {
39842
40585
  const profilePath = import_node_path28.default.join(dataDir, PROFILE_FILENAME);
39843
40586
  let raw;
39844
40587
  try {
39845
- raw = import_node_fs25.default.readFileSync(profilePath, "utf8");
40588
+ raw = import_node_fs26.default.readFileSync(profilePath, "utf8");
39846
40589
  } catch {
39847
40590
  return fallback;
39848
40591
  }
@@ -39865,7 +40608,7 @@ function loadOwnerDisplayName(dataDir) {
39865
40608
  }
39866
40609
 
39867
40610
  // src/feishu-auth/owner-identity-store.ts
39868
- var import_node_fs26 = __toESM(require("fs"), 1);
40611
+ var import_node_fs27 = __toESM(require("fs"), 1);
39869
40612
  var import_node_path29 = __toESM(require("path"), 1);
39870
40613
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
39871
40614
  var OwnerIdentityStore = class {
@@ -39876,7 +40619,7 @@ var OwnerIdentityStore = class {
39876
40619
  read() {
39877
40620
  let raw;
39878
40621
  try {
39879
- raw = import_node_fs26.default.readFileSync(this.file, "utf8");
40622
+ raw = import_node_fs27.default.readFileSync(this.file, "utf8");
39880
40623
  } catch {
39881
40624
  return null;
39882
40625
  }
@@ -39903,16 +40646,16 @@ var OwnerIdentityStore = class {
39903
40646
  };
39904
40647
  }
39905
40648
  write(record) {
39906
- import_node_fs26.default.mkdirSync(import_node_path29.default.dirname(this.file), { recursive: true });
39907
- import_node_fs26.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
40649
+ import_node_fs27.default.mkdirSync(import_node_path29.default.dirname(this.file), { recursive: true });
40650
+ import_node_fs27.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
39908
40651
  try {
39909
- import_node_fs26.default.chmodSync(this.file, 384);
40652
+ import_node_fs27.default.chmodSync(this.file, 384);
39910
40653
  } catch {
39911
40654
  }
39912
40655
  }
39913
40656
  clear() {
39914
40657
  try {
39915
- import_node_fs26.default.unlinkSync(this.file);
40658
+ import_node_fs27.default.unlinkSync(this.file);
39916
40659
  } catch (err) {
39917
40660
  const code = err?.code;
39918
40661
  if (code !== "ENOENT") throw err;
@@ -40175,7 +40918,7 @@ function verifyConnectToken(args) {
40175
40918
  }
40176
40919
 
40177
40920
  // src/feishu-auth/server-key.ts
40178
- var fs35 = __toESM(require("fs"), 1);
40921
+ var fs36 = __toESM(require("fs"), 1);
40179
40922
  var path38 = __toESM(require("path"), 1);
40180
40923
  var FILE_NAME2 = "server-signing-key.json";
40181
40924
  var ServerKeyStore = class {
@@ -40189,7 +40932,7 @@ var ServerKeyStore = class {
40189
40932
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
40190
40933
  read() {
40191
40934
  try {
40192
- const raw = fs35.readFileSync(this.filePath(), "utf8");
40935
+ const raw = fs36.readFileSync(this.filePath(), "utf8");
40193
40936
  const parsed = JSON.parse(raw);
40194
40937
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
40195
40938
  return parsed.publicKeyPem;
@@ -40204,12 +40947,12 @@ var ServerKeyStore = class {
40204
40947
  publicKeyPem,
40205
40948
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
40206
40949
  };
40207
- fs35.mkdirSync(this.dataDir, { recursive: true });
40208
- fs35.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
40950
+ fs36.mkdirSync(this.dataDir, { recursive: true });
40951
+ fs36.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
40209
40952
  }
40210
40953
  clear() {
40211
40954
  try {
40212
- fs35.unlinkSync(this.filePath());
40955
+ fs36.unlinkSync(this.filePath());
40213
40956
  } catch {
40214
40957
  }
40215
40958
  }
@@ -40222,12 +40965,12 @@ init_protocol();
40222
40965
  init_protocol();
40223
40966
 
40224
40967
  // src/session/fork.ts
40225
- var import_node_fs27 = __toESM(require("fs"), 1);
40968
+ var import_node_fs28 = __toESM(require("fs"), 1);
40226
40969
  var import_node_os14 = __toESM(require("os"), 1);
40227
40970
  var import_node_path30 = __toESM(require("path"), 1);
40228
40971
  init_claude_history();
40229
40972
  function readJsonlEntries(file) {
40230
- const raw = import_node_fs27.default.readFileSync(file, "utf8");
40973
+ const raw = import_node_fs28.default.readFileSync(file, "utf8");
40231
40974
  const out = [];
40232
40975
  for (const line of raw.split("\n")) {
40233
40976
  const t = line.trim();
@@ -40243,7 +40986,7 @@ function forkSession(input) {
40243
40986
  const baseDir = input.baseDir ?? import_node_path30.default.join(import_node_os14.default.homedir(), ".claude");
40244
40987
  const projectDir = import_node_path30.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
40245
40988
  const sourceFile = import_node_path30.default.join(projectDir, `${input.toolSessionId}.jsonl`);
40246
- if (!import_node_fs27.default.existsSync(sourceFile)) {
40989
+ if (!import_node_fs28.default.existsSync(sourceFile)) {
40247
40990
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
40248
40991
  }
40249
40992
  const entries = readJsonlEntries(sourceFile);
@@ -40274,8 +41017,8 @@ function forkSession(input) {
40274
41017
  forkedLines.push(JSON.stringify(forked));
40275
41018
  }
40276
41019
  const forkedFilePath = import_node_path30.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
40277
- import_node_fs27.default.mkdirSync(projectDir, { recursive: true });
40278
- import_node_fs27.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
41020
+ import_node_fs28.default.mkdirSync(projectDir, { recursive: true });
41021
+ import_node_fs28.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
40279
41022
  return { forkedToolSessionId, forkedFilePath };
40280
41023
  }
40281
41024
 
@@ -40337,15 +41080,17 @@ function buildSessionHandlers(deps) {
40337
41080
  };
40338
41081
  const create = async (frame, _client, ctx) => {
40339
41082
  const args = SessionCreateArgs.parse(frame);
41083
+ let tool = args.tool;
40340
41084
  if (args.ownerPersonaId) {
40341
41085
  const persona = deps.personaRegistry.get(args.ownerPersonaId);
40342
41086
  if (!persona) {
40343
41087
  throw new Error(`persona not found: ${args.ownerPersonaId}`);
40344
41088
  }
41089
+ tool = persona.tool ?? args.tool;
40345
41090
  }
40346
41091
  ensurePersonaAccess(ctx, args.ownerPersonaId, "send");
40347
41092
  const creatorPrincipalId = ctx?.principal.id ?? ownerPrincipalId;
40348
- const { response, broadcast } = manager.create(args, creatorPrincipalId);
41093
+ const { response, broadcast } = manager.create({ ...args, tool }, creatorPrincipalId);
40349
41094
  return { response: { type: "session:info", ...response }, broadcast };
40350
41095
  };
40351
41096
  const list = async (_frame, _client, ctx) => {
@@ -40465,6 +41210,13 @@ function buildSessionHandlers(deps) {
40465
41210
  const sessionFile = file;
40466
41211
  manager.ensureSession(sessionFile);
40467
41212
  const adapter = getAdapter2(sessionFile.tool ?? "claude");
41213
+ const caps = await adapter.capabilities();
41214
+ if (caps.features.observe === false) {
41215
+ throw new ClawdError(
41216
+ ERROR_CODES.TOOL_NOT_SUPPORTED,
41217
+ `tool ${sessionFile.tool ?? "claude"} does not support observe`
41218
+ );
41219
+ }
40468
41220
  observer.start({
40469
41221
  sessionId: args.sessionId,
40470
41222
  cwd: sessionFile.cwd,
@@ -40714,7 +41466,7 @@ function assertGuestPath(ctx, absPath, personaRoot, method, usersRoot) {
40714
41466
  }
40715
41467
  }
40716
41468
  function buildHistoryHandlers(deps) {
40717
- const { manager, history, store, personaRoot, usersRoot } = deps;
41469
+ const { manager, history, getHistoryReader, store, personaRoot, usersRoot } = deps;
40718
41470
  const projects = async (_frame, _client, ctx) => {
40719
41471
  const list2 = await history.listProjects();
40720
41472
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -40758,7 +41510,7 @@ function buildHistoryHandlers(deps) {
40758
41510
  response: { type: "history:read", messages: [], total: 0, offset: 0 }
40759
41511
  };
40760
41512
  }
40761
- const res = await history.read({
41513
+ const res = await getHistoryReader(f.tool ?? "claude").read({
40762
41514
  cwd: f.cwd,
40763
41515
  toolSessionId: f.toolSessionId,
40764
41516
  limit: args.limit,
@@ -40837,7 +41589,7 @@ function assertGuestPath2(ctx, absPath, personaRoot, method, usersRoot) {
40837
41589
  }
40838
41590
  }
40839
41591
  function buildWorkspaceHandlers(deps) {
40840
- const { workspace, skills, agents, personaRoot, personaManager, usersRoot } = deps;
41592
+ const { workspace, skills, agents, getSkillsForTool, personaRoot, personaManager, usersRoot } = deps;
40841
41593
  const list = async (frame, _client, ctx) => {
40842
41594
  const args = WorkspaceListArgs.parse(frame);
40843
41595
  const isGuest = ctx?.principal.kind === "guest";
@@ -40859,7 +41611,7 @@ function buildWorkspaceHandlers(deps) {
40859
41611
  const args = SkillsListArgs.parse(frame);
40860
41612
  const cwdAbs = path42.resolve(args.cwd);
40861
41613
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
40862
- const list2 = skills.list(args);
41614
+ const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
40863
41615
  if (ctx?.principal.kind === "guest" && personaRoot) {
40864
41616
  const personaId = personaIdFromPath(cwdAbs, personaRoot);
40865
41617
  const enabled = personaId ? buildEnabledPluginNames(personaManager, personaId) : /* @__PURE__ */ new Set();
@@ -40871,6 +41623,9 @@ function buildWorkspaceHandlers(deps) {
40871
41623
  const args = AgentsListArgs.parse(frame);
40872
41624
  const cwdAbs = path42.resolve(args.cwd);
40873
41625
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
41626
+ if (args.tool === "codex") {
41627
+ return { response: { type: "agents:list", agents: [] } };
41628
+ }
40874
41629
  const list2 = agents.list(args);
40875
41630
  if (ctx?.principal.kind === "guest" && personaRoot) {
40876
41631
  const personaId = personaIdFromPath(cwdAbs, personaRoot);
@@ -40893,15 +41648,15 @@ init_protocol();
40893
41648
  init_protocol();
40894
41649
 
40895
41650
  // src/workspace/git.ts
40896
- var import_node_child_process6 = require("child_process");
40897
- var import_node_fs28 = __toESM(require("fs"), 1);
41651
+ var import_node_child_process10 = require("child_process");
41652
+ var import_node_fs29 = __toESM(require("fs"), 1);
40898
41653
  var import_node_path31 = __toESM(require("path"), 1);
40899
41654
  var import_node_util = require("util");
40900
- var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
41655
+ var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
40901
41656
  function normalizePath(p2) {
40902
41657
  const resolved = import_node_path31.default.resolve(p2);
40903
41658
  try {
40904
- return import_node_fs28.default.realpathSync(resolved);
41659
+ return import_node_fs29.default.realpathSync(resolved);
40905
41660
  } catch {
40906
41661
  return resolved;
40907
41662
  }
@@ -42091,22 +42846,22 @@ function pickExtId(frame) {
42091
42846
  }
42092
42847
  return extId;
42093
42848
  }
42094
- function composeState(rec, running, crashed, getPort) {
42095
- if (rec.state === "invalid") return rec;
42096
- if (manifestMode(rec.manifest) === "hosted") {
42849
+ function composeState(rec3, running, crashed, getPort) {
42850
+ if (rec3.state === "invalid") return rec3;
42851
+ if (manifestMode(rec3.manifest) === "hosted") {
42097
42852
  return {
42098
- ...rec,
42853
+ ...rec3,
42099
42854
  state: "running",
42100
- target: { kind: "hosted", url: rec.manifest.entry.url }
42855
+ target: { kind: "hosted", url: rec3.manifest.entry.url }
42101
42856
  };
42102
42857
  }
42103
- if (running.has(rec.extId)) {
42104
- const port = getPort(rec.extId);
42105
- if (port == null) return rec;
42106
- return { ...rec, state: "running", target: { kind: "local", port } };
42858
+ if (running.has(rec3.extId)) {
42859
+ const port = getPort(rec3.extId);
42860
+ if (port == null) return rec3;
42861
+ return { ...rec3, state: "running", target: { kind: "local", port } };
42107
42862
  }
42108
- if (crashed.has(rec.extId)) return { ...rec, state: "crashed" };
42109
- return rec;
42863
+ if (crashed.has(rec3.extId)) return { ...rec3, state: "crashed" };
42864
+ return rec3;
42110
42865
  }
42111
42866
  function buildExtensionHandlers(deps) {
42112
42867
  const list = async (_frame, _client, ctx) => {
@@ -42323,7 +43078,7 @@ function buildExtensionHandlers(deps) {
42323
43078
  }
42324
43079
 
42325
43080
  // src/app-builder/kill-port.ts
42326
- var import_node_child_process7 = require("child_process");
43081
+ var import_node_child_process11 = require("child_process");
42327
43082
  async function killPortOccupants(port, ownedPids, logger) {
42328
43083
  let pids;
42329
43084
  try {
@@ -42365,7 +43120,7 @@ async function killPortOccupants(port, ownedPids, logger) {
42365
43120
  }
42366
43121
  function listPidsOnPort(port) {
42367
43122
  return new Promise((resolve6, reject) => {
42368
- (0, import_node_child_process7.execFile)(
43123
+ (0, import_node_child_process11.execFile)(
42369
43124
  "lsof",
42370
43125
  ["-ti", `:${port}`],
42371
43126
  { timeout: 3e3 },
@@ -42437,8 +43192,8 @@ var PublishJobRegistry = class {
42437
43192
  };
42438
43193
 
42439
43194
  // src/app-builder/publish-job-runner.ts
42440
- var import_node_child_process8 = require("child_process");
42441
- var import_node_fs29 = require("fs");
43195
+ var import_node_child_process12 = require("child_process");
43196
+ var import_node_fs30 = require("fs");
42442
43197
  var import_node_path38 = require("path");
42443
43198
 
42444
43199
  // src/app-builder/publish-stage-parser.ts
@@ -42466,7 +43221,7 @@ function tailStderrLines(buf, n) {
42466
43221
  // src/app-builder/publish-job-runner.ts
42467
43222
  async function startPublishJob(deps, args) {
42468
43223
  const { registry: registry2, projectDir } = deps;
42469
- const spawn9 = deps.spawnImpl ?? import_node_child_process8.spawn;
43224
+ const spawn12 = deps.spawnImpl ?? import_node_child_process12.spawn;
42470
43225
  if (registry2.has(args.name)) {
42471
43226
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
42472
43227
  }
@@ -42474,11 +43229,11 @@ async function startPublishJob(deps, args) {
42474
43229
  const logPath = (0, import_node_path38.join)(projDir, ".publish.log");
42475
43230
  let logStream = null;
42476
43231
  try {
42477
- logStream = (0, import_node_fs29.createWriteStream)(logPath, { flags: "w" });
43232
+ logStream = (0, import_node_fs30.createWriteStream)(logPath, { flags: "w" });
42478
43233
  } catch {
42479
43234
  logStream = null;
42480
43235
  }
42481
- const child = spawn9("bash", [args.scriptPath, projDir], {
43236
+ const child = spawn12("bash", [args.scriptPath, projDir], {
42482
43237
  cwd: projDir,
42483
43238
  env: process.env,
42484
43239
  stdio: ["ignore", "pipe", "pipe"]
@@ -42732,7 +43487,7 @@ async function recoverInterruptedJobs(deps) {
42732
43487
  // src/handlers/app-builder.ts
42733
43488
  init_protocol();
42734
43489
  var import_node_path39 = require("path");
42735
- var import_node_fs30 = require("fs");
43490
+ var import_node_fs31 = require("fs");
42736
43491
  var APP_BUILDER_PERSONAS = ["persona-app-builder"];
42737
43492
  var PUBLISH_SCRIPT_REL = "extension-kit/scripts/publish.sh";
42738
43493
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
@@ -42814,7 +43569,7 @@ function buildAppBuilderHandlers(deps) {
42814
43569
  async function listAllUsersProjects() {
42815
43570
  if (!deps.usersRoot || !deps.getStore) return [];
42816
43571
  const getStore = deps.getStore;
42817
- const userIds = await import_node_fs30.promises.readdir(deps.usersRoot).catch(() => []);
43572
+ const userIds = await import_node_fs31.promises.readdir(deps.usersRoot).catch(() => []);
42818
43573
  const perUser = await Promise.all(
42819
43574
  userIds.map((uid) => getStore(uid).list().catch(() => []))
42820
43575
  );
@@ -43354,8 +44109,8 @@ function buildMethodHandlers(deps) {
43354
44109
  }
43355
44110
 
43356
44111
  // src/app-builder/project-store.ts
43357
- var import_node_fs31 = require("fs");
43358
- var import_node_child_process9 = require("child_process");
44112
+ var import_node_fs32 = require("fs");
44113
+ var import_node_child_process13 = require("child_process");
43359
44114
  var import_node_path42 = require("path");
43360
44115
  init_protocol();
43361
44116
  var PROJECTS_DIR = "projects";
@@ -43383,7 +44138,7 @@ var ProjectStore = class {
43383
44138
  async list() {
43384
44139
  let entries;
43385
44140
  try {
43386
- entries = await import_node_fs31.promises.readdir(this.projectsRoot());
44141
+ entries = await import_node_fs32.promises.readdir(this.projectsRoot());
43387
44142
  } catch (err) {
43388
44143
  if (err.code === "ENOENT") return [];
43389
44144
  throw err;
@@ -43391,7 +44146,7 @@ var ProjectStore = class {
43391
44146
  const out = [];
43392
44147
  for (const name of entries) {
43393
44148
  try {
43394
- const raw = await import_node_fs31.promises.readFile(this.metaPath(name), "utf8");
44149
+ const raw = await import_node_fs32.promises.readFile(this.metaPath(name), "utf8");
43395
44150
  const json = JSON.parse(raw);
43396
44151
  let migrated = false;
43397
44152
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -43402,7 +44157,7 @@ var ProjectStore = class {
43402
44157
  if (parsed.success) {
43403
44158
  out.push(parsed.data);
43404
44159
  if (migrated) {
43405
- void import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
44160
+ void import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
43406
44161
  });
43407
44162
  }
43408
44163
  }
@@ -43446,8 +44201,8 @@ var ProjectStore = class {
43446
44201
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
43447
44202
  }
43448
44203
  const dir = this.projectDir(name);
43449
- await import_node_fs31.promises.mkdir(dir, { recursive: true });
43450
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
44204
+ await import_node_fs32.promises.mkdir(dir, { recursive: true });
44205
+ await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
43451
44206
  return meta;
43452
44207
  }
43453
44208
  /**
@@ -43462,7 +44217,7 @@ var ProjectStore = class {
43462
44217
  const scriptPath = (0, import_node_path42.join)(personaRoot, SCAFFOLD_SCRIPT_REL);
43463
44218
  const destDir = this.projectDir(name);
43464
44219
  return await new Promise((resolve6, reject) => {
43465
- const child = (0, import_node_child_process9.spawn)("bash", [scriptPath, name, template, destDir], {
44220
+ const child = (0, import_node_child_process13.spawn)("bash", [scriptPath, name, template, destDir], {
43466
44221
  cwd: personaRoot,
43467
44222
  env: { ...process.env, PATH: process.env.PATH ?? "" },
43468
44223
  stdio: ["ignore", "pipe", "pipe"]
@@ -43492,7 +44247,7 @@ var ProjectStore = class {
43492
44247
  }
43493
44248
  async delete(name) {
43494
44249
  const dir = this.projectDir(name);
43495
- await import_node_fs31.promises.rm(dir, { recursive: true, force: true });
44250
+ await import_node_fs32.promises.rm(dir, { recursive: true, force: true });
43496
44251
  }
43497
44252
  async updatePort(name, newPort) {
43498
44253
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -43508,7 +44263,7 @@ var ProjectStore = class {
43508
44263
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
43509
44264
  }
43510
44265
  const updated = { ...target, port: newPort };
43511
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
44266
+ await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
43512
44267
  return updated;
43513
44268
  }
43514
44269
  /**
@@ -43525,7 +44280,7 @@ var ProjectStore = class {
43525
44280
  if (!validated.success) {
43526
44281
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
43527
44282
  }
43528
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44283
+ await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
43529
44284
  return validated.data;
43530
44285
  }
43531
44286
  /**
@@ -43546,7 +44301,7 @@ var ProjectStore = class {
43546
44301
  if (!validated.success) {
43547
44302
  throw new Error(`invalid publishJob: ${validated.error.message}`);
43548
44303
  }
43549
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44304
+ await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
43550
44305
  return validated.data;
43551
44306
  }
43552
44307
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -43561,13 +44316,13 @@ var ProjectStore = class {
43561
44316
  if (!validated.success) {
43562
44317
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
43563
44318
  }
43564
- await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
44319
+ await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
43565
44320
  return validated.data;
43566
44321
  }
43567
44322
  };
43568
44323
 
43569
44324
  // src/app-builder/dev-server-supervisor.ts
43570
- var import_node_child_process10 = require("child_process");
44325
+ var import_node_child_process14 = require("child_process");
43571
44326
  var import_node_events2 = require("events");
43572
44327
  var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
43573
44328
  var DevServerSupervisor = class extends import_node_events2.EventEmitter {
@@ -43604,7 +44359,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
43604
44359
  tunnelHost: args.tunnelHost,
43605
44360
  devCommand: cmd
43606
44361
  });
43607
- const child = (0, import_node_child_process10.spawn)("sh", ["-c", cmd], {
44362
+ const child = (0, import_node_child_process14.spawn)("sh", ["-c", cmd], {
43608
44363
  cwd: args.cwd,
43609
44364
  env,
43610
44365
  stdio: "pipe",
@@ -43996,7 +44751,7 @@ function computeGrantForFrame(method, frame) {
43996
44751
  }
43997
44752
 
43998
44753
  // src/extension/runtime.ts
43999
- var import_node_child_process11 = require("child_process");
44754
+ var import_node_child_process15 = require("child_process");
44000
44755
  var import_node_path43 = __toESM(require("path"), 1);
44001
44756
  var import_promises10 = require("timers/promises");
44002
44757
 
@@ -44083,17 +44838,17 @@ var Runtime = class {
44083
44838
  const existing = this.handles.get(extId);
44084
44839
  if (existing) return { kind: "local", port: existing.port };
44085
44840
  const records = await loadAll(this.root);
44086
- const rec = records.find((r) => r.extId === extId);
44087
- if (!rec) throw new RuntimeError("NOT_FOUND", `extension ${extId} not installed`);
44088
- if (rec.state === "invalid")
44089
- throw new RuntimeError("INVALID_MANIFEST", rec.invalidReason);
44090
- if (manifestMode(rec.manifest) === "hosted") {
44091
- return { kind: "hosted", url: rec.manifest.entry.url };
44841
+ const rec3 = records.find((r) => r.extId === extId);
44842
+ if (!rec3) throw new RuntimeError("NOT_FOUND", `extension ${extId} not installed`);
44843
+ if (rec3.state === "invalid")
44844
+ throw new RuntimeError("INVALID_MANIFEST", rec3.invalidReason);
44845
+ if (manifestMode(rec3.manifest) === "hosted") {
44846
+ return { kind: "hosted", url: rec3.manifest.entry.url };
44092
44847
  }
44093
44848
  const port = await this.allocator.allocate().catch(() => {
44094
44849
  throw new RuntimeError("PORT_EXHAUSTED", "no free port in configured range");
44095
44850
  });
44096
- const startCommand = rec.manifest.runtime.startCommand;
44851
+ const startCommand = rec3.manifest.runtime.startCommand;
44097
44852
  const cmd = startCommand.replace(
44098
44853
  /\$CLAWOS_EXT_PORT/g,
44099
44854
  String(port)
@@ -44104,7 +44859,7 @@ var Runtime = class {
44104
44859
  CLAWOS_EXT_PORT: String(port),
44105
44860
  CLAWOS_EXT_ID: extId
44106
44861
  };
44107
- const child = (0, import_node_child_process11.spawn)("sh", ["-c", cmd], {
44862
+ const child = (0, import_node_child_process15.spawn)("sh", ["-c", cmd], {
44108
44863
  cwd: dir,
44109
44864
  env,
44110
44865
  stdio: ["ignore", "pipe", "pipe"],
@@ -44540,7 +45295,7 @@ async function startDaemon(config) {
44540
45295
  const absPath = import_node_path46.default.isAbsolute(input.relPath) ? input.relPath : import_node_path46.default.join(input.cwd, input.relPath);
44541
45296
  let size = 0;
44542
45297
  try {
44543
- size = import_node_fs32.default.statSync(absPath).size;
45298
+ size = import_node_fs33.default.statSync(absPath).size;
44544
45299
  } catch (err) {
44545
45300
  logger.warn("attachment.onFileEdit stat failed", {
44546
45301
  sessionId: input.sessionId,
@@ -44610,6 +45365,7 @@ async function startDaemon(config) {
44610
45365
  onReady: (tsid) => manager.dispatchReadyDetected(tsid)
44611
45366
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
44612
45367
  registerAdapter("claude", claudeAdapter);
45368
+ registerAdapter("codex", new CodexAdapter({ logger, historyReader: new CodexHistoryReader() }));
44613
45369
  const personaRegistry = new PersonaRegistry(personaStore);
44614
45370
  const personaManager = new PersonaManager({
44615
45371
  store: personaStore,
@@ -44688,7 +45444,11 @@ async function startDaemon(config) {
44688
45444
  workspace,
44689
45445
  skills,
44690
45446
  agents,
45447
+ // skills:list 按 tool 路由:codex → app-server skills/list;缺省 claude → SkillsScanner(同步包成 Promise)。
45448
+ getSkillsForTool: (tool, cwd) => tool === "codex" ? listCodexSkills(cwd) : Promise.resolve(skills.list({ cwd })),
44691
45449
  history,
45450
+ // history:read 按 session.tool 路由:codex → adapter.historyReader(CodexHistoryReader);缺省 claude。
45451
+ getHistoryReader: (tool) => getAdapter(tool).historyReader ?? history,
44692
45452
  observer,
44693
45453
  getAdapter,
44694
45454
  store,
@@ -45027,8 +45787,7 @@ async function startDaemon(config) {
45027
45787
  protocolVersion: PROTOCOL_VERSION,
45028
45788
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
45029
45789
  authMode,
45030
- authToken: resolvedAuthToken ?? void 0,
45031
- source: readDaemonSourceFromEnv()
45790
+ authToken: resolvedAuthToken ?? void 0
45032
45791
  };
45033
45792
  stateMgr.write(stateSnapshot);
45034
45793
  process.stdout.write(`Ready: ${url}
@@ -45079,7 +45838,7 @@ ${bar}
45079
45838
  `);
45080
45839
  try {
45081
45840
  const connectPath = import_node_path46.default.join(config.dataDir, "connect.txt");
45082
- import_node_fs32.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
45841
+ import_node_fs33.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
45083
45842
  } catch {
45084
45843
  }
45085
45844
  } catch (err) {
@@ -45152,7 +45911,7 @@ ${bar}
45152
45911
  function migrateDropPersonsDir(dataDir) {
45153
45912
  const dir = import_node_path46.default.join(dataDir, "persons");
45154
45913
  try {
45155
- import_node_fs32.default.rmSync(dir, { recursive: true, force: true });
45914
+ import_node_fs33.default.rmSync(dir, { recursive: true, force: true });
45156
45915
  } catch {
45157
45916
  }
45158
45917
  }