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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.cjs +215 -71
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -4495,7 +4495,7 @@ var init_attachment_schemas = __esm({
4495
4495
  });
4496
4496
 
4497
4497
  // ../protocol/src/persona-schemas.ts
4498
- var PersonaFileSchema, PersonaSkillSummarySchema, PersonaPluginSummarySchema, PersonaSandboxSettingsSchema, PersonaInfoResponseSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema;
4498
+ var PersonaFileSchema, PersonaSkillSummarySchema, PersonaPluginSummarySchema, PersonaSandboxSettingsSchema, PersonaInfoResponseSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema, CodexSandboxSettingsSchema;
4499
4499
  var init_persona_schemas = __esm({
4500
4500
  "../protocol/src/persona-schemas.ts"() {
4501
4501
  "use strict";
@@ -4580,6 +4580,14 @@ var init_persona_schemas = __esm({
4580
4580
  iconKey: external_exports.string().nullable().optional()
4581
4581
  }).strict()
4582
4582
  }).strict();
4583
+ CodexSandboxSettingsSchema = external_exports.object({
4584
+ // 额外可写的绝对路径或 ~ 路径(pnpm 工具链等);workspace(cwd) 和 userWorkDir 由 daemon 自动加,不用列。
4585
+ writableRoots: external_exports.array(external_exports.string()).optional(),
4586
+ // 禁读 glob(相对 workspace root 或绝对),如 ".secrets/**"、"**/*.env"。
4587
+ denyRead: external_exports.array(external_exports.string()).optional(),
4588
+ // true → 网络全放(*);缺省/false → 断网。
4589
+ network: external_exports.boolean().optional()
4590
+ }).strict();
4583
4591
  }
4584
4592
  });
4585
4593
 
@@ -10047,7 +10055,7 @@ var require_multistream = __commonJS({
10047
10055
  var require_pino = __commonJS({
10048
10056
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
10049
10057
  "use strict";
10050
- var os21 = require("os");
10058
+ var os22 = require("os");
10051
10059
  var stdSerializers = require_pino_std_serializers();
10052
10060
  var caller = require_caller();
10053
10061
  var redaction = require_redaction();
@@ -10094,7 +10102,7 @@ var require_pino = __commonJS({
10094
10102
  } = symbols;
10095
10103
  var { epochTime, nullTime } = time;
10096
10104
  var { pid } = process;
10097
- var hostname = os21.hostname();
10105
+ var hostname = os22.hostname();
10098
10106
  var defaultErrorSerializer = stdSerializers.err;
10099
10107
  var defaultOptions = {
10100
10108
  level: "info",
@@ -11333,12 +11341,12 @@ function readCurrentContent(filePath) {
11333
11341
  return null;
11334
11342
  }
11335
11343
  }
11336
- var import_node_fs8, import_node_os3, import_node_path8, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11344
+ var import_node_fs8, import_node_os4, import_node_path8, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11337
11345
  var init_claude_history = __esm({
11338
11346
  "src/tools/claude-history.ts"() {
11339
11347
  "use strict";
11340
11348
  import_node_fs8 = __toESM(require("fs"), 1);
11341
- import_node_os3 = __toESM(require("os"), 1);
11349
+ import_node_os4 = __toESM(require("os"), 1);
11342
11350
  import_node_path8 = __toESM(require("path"), 1);
11343
11351
  init_lib();
11344
11352
  init_tool_result_extra();
@@ -11363,7 +11371,7 @@ var init_claude_history = __esm({
11363
11371
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
11364
11372
  fileHistoryRoot;
11365
11373
  constructor(opts = {}) {
11366
- const base = opts.baseDir ?? import_node_path8.default.join(import_node_os3.default.homedir(), ".claude");
11374
+ const base = opts.baseDir ?? import_node_path8.default.join(import_node_os4.default.homedir(), ".claude");
11367
11375
  this.projectsRoot = import_node_path8.default.join(base, "projects");
11368
11376
  this.fileHistoryRoot = import_node_path8.default.join(base, "file-history");
11369
11377
  }
@@ -11760,7 +11768,7 @@ function probeViaWhich() {
11760
11768
  }
11761
11769
  return null;
11762
11770
  }
11763
- async function probeClaude(env = process.env, home = import_node_os4.default.homedir()) {
11771
+ async function probeClaude(env = process.env, home = import_node_os5.default.homedir()) {
11764
11772
  if (env.CLAUDE_BIN && import_node_fs9.default.existsSync(env.CLAUDE_BIN)) {
11765
11773
  return { available: true, path: env.CLAUDE_BIN };
11766
11774
  }
@@ -12200,14 +12208,14 @@ function encodeClaudeStdin(text) {
12200
12208
  };
12201
12209
  return JSON.stringify(frame) + "\n";
12202
12210
  }
12203
- var import_node_child_process, import_node_child_process2, import_node_fs9, import_node_os4, import_node_path9, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12211
+ var import_node_child_process, import_node_child_process2, import_node_fs9, import_node_os5, import_node_path9, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12204
12212
  var init_claude = __esm({
12205
12213
  "src/tools/claude.ts"() {
12206
12214
  "use strict";
12207
12215
  import_node_child_process = require("child_process");
12208
12216
  import_node_child_process2 = require("child_process");
12209
12217
  import_node_fs9 = __toESM(require("fs"), 1);
12210
- import_node_os4 = __toESM(require("os"), 1);
12218
+ import_node_os5 = __toESM(require("os"), 1);
12211
12219
  import_node_path9 = __toESM(require("path"), 1);
12212
12220
  init_protocol();
12213
12221
  init_claude_history();
@@ -30840,7 +30848,7 @@ var init_wire = __esm({
30840
30848
  // src/run-case/controller.ts
30841
30849
  async function runController(opts) {
30842
30850
  const now = opts.now ?? Date.now;
30843
- const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(import_node_path48.default.join(import_node_os19.default.tmpdir(), "clawd-runcase-"));
30851
+ const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(import_node_path48.default.join(import_node_os20.default.tmpdir(), "clawd-runcase-"));
30844
30852
  const ownsCwd = opts.cwd === void 0;
30845
30853
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
30846
30854
  const spawnCtx = { cwd };
@@ -31007,12 +31015,12 @@ async function runController(opts) {
31007
31015
  }
31008
31016
  return exitCode ?? 0;
31009
31017
  }
31010
- var import_node_fs35, import_node_os19, import_node_path48;
31018
+ var import_node_fs35, import_node_os20, import_node_path48;
31011
31019
  var init_controller = __esm({
31012
31020
  "src/run-case/controller.ts"() {
31013
31021
  "use strict";
31014
31022
  import_node_fs35 = require("fs");
31015
- import_node_os19 = __toESM(require("os"), 1);
31023
+ import_node_os20 = __toESM(require("os"), 1);
31016
31024
  import_node_path48 = __toESM(require("path"), 1);
31017
31025
  init_claude();
31018
31026
  init_stdout_splitter();
@@ -31490,6 +31498,7 @@ var SessionStoreFactory = class {
31490
31498
  // src/session/manager.ts
31491
31499
  var import_node_fs6 = __toESM(require("fs"), 1);
31492
31500
  var import_node_path6 = __toESM(require("path"), 1);
31501
+ var import_node_os2 = __toESM(require("os"), 1);
31493
31502
 
31494
31503
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
31495
31504
  var byteToHex = [];
@@ -31767,8 +31776,8 @@ function buildSpawnContext(state, deps) {
31767
31776
  if (meta?.addDirs && meta.addDirs.length > 0) {
31768
31777
  ctx.addDirs = meta.addDirs;
31769
31778
  }
31770
- if (meta?.networkAccess !== void 0) {
31771
- ctx.networkAccess = meta.networkAccess;
31779
+ if (meta?.codexSandbox) {
31780
+ ctx.codexSandbox = meta.codexSandbox;
31772
31781
  }
31773
31782
  return ctx;
31774
31783
  }
@@ -33266,8 +33275,14 @@ var SessionManager = class {
33266
33275
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
33267
33276
  const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
33268
33277
  subSessionMeta.extraSettings = JSON.stringify(settings);
33269
- const domains = settings.sandbox?.network?.allowedDomains;
33270
- subSessionMeta.networkAccess = Array.isArray(domains) && domains.length > 0;
33278
+ const home = import_node_os2.default.homedir();
33279
+ const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path6.default.join(home, p2.slice(2)) : p2;
33280
+ const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
33281
+ subSessionMeta.codexSandbox = {
33282
+ writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
33283
+ denyRead: codexCfg?.denyRead ?? [],
33284
+ network: codexCfg?.network ?? false
33285
+ };
33271
33286
  }
33272
33287
  const attachmentGroup = this.deps.attachmentGroup;
33273
33288
  const runner = new SessionRunner(makeInitialState(file, subSessionMeta), {
@@ -34511,6 +34526,20 @@ var PersonaStore = class {
34511
34526
  this.atomicWrite(this.claudeMdPath(personaId), personality);
34512
34527
  this.atomicWrite(this.agentsMdPath(personaId), personality);
34513
34528
  }
34529
+ /**
34530
+ * 历史 persona 补 AGENTS.md:人格双写镜像是 codex 适配后才加的,更早落盘的 persona 只有
34531
+ * CLAUDE.md。codex 原生读 cwd 的 AGENTS.md,缺失则切到 codex 后人格丢失。daemon 启动跑一次
34532
+ * migrate(见 seed.migrateAgentsMirror)。幂等:已有 AGENTS.md(含用户手改的)不覆盖;
34533
+ * 无 CLAUDE.md 不凭空造。返回是否实际补写。
34534
+ */
34535
+ ensureAgentsMirror(personaId) {
34536
+ const claudeMd = this.claudeMdPath(personaId);
34537
+ const agentsMd = this.agentsMdPath(personaId);
34538
+ if (!fs7.existsSync(claudeMd)) return false;
34539
+ if (fs7.existsSync(agentsMd)) return false;
34540
+ this.atomicWrite(agentsMd, fs7.readFileSync(claudeMd, "utf8"));
34541
+ return true;
34542
+ }
34514
34543
  /**
34515
34544
  * 覆盖式写 persona 级 sandbox 配置(seed 给有 profile 的 persona 写 base⊕profile;owner 之后可手编)。
34516
34545
  * 这份是 guest 沙箱的 **base 真源**:manager spawn 时 composeGuestSandbox 读它 + 叠强制底座
@@ -34522,6 +34551,25 @@ var PersonaStore = class {
34522
34551
  JSON.stringify(settings, null, 2)
34523
34552
  );
34524
34553
  }
34554
+ codexSandboxSettingsPath(personaId) {
34555
+ return path9.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
34556
+ }
34557
+ /** 读 codex-sandbox.json;不存在/损坏 → null。 */
34558
+ readCodexSandboxSettings(personaId) {
34559
+ const p2 = this.codexSandboxSettingsPath(personaId);
34560
+ if (!fs7.existsSync(p2)) return null;
34561
+ try {
34562
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs7.readFileSync(p2, "utf8")));
34563
+ } catch {
34564
+ return null;
34565
+ }
34566
+ }
34567
+ /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
34568
+ writeCodexSandboxSettings(personaId, settings) {
34569
+ const dir = path9.join(this.personaDir(personaId), ".clawd");
34570
+ fs7.mkdirSync(dir, { recursive: true });
34571
+ this.atomicWrite(this.codexSandboxSettingsPath(personaId), JSON.stringify(settings, null, 2));
34572
+ }
34525
34573
  writeMeta(persona) {
34526
34574
  this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
34527
34575
  }
@@ -34661,7 +34709,7 @@ var import_node_crypto3 = __toESM(require("crypto"), 1);
34661
34709
 
34662
34710
  // src/skills/scanner.ts
34663
34711
  var import_node_fs7 = __toESM(require("fs"), 1);
34664
- var import_node_os2 = __toESM(require("os"), 1);
34712
+ var import_node_os3 = __toESM(require("os"), 1);
34665
34713
  var import_node_path7 = __toESM(require("path"), 1);
34666
34714
 
34667
34715
  // src/skills/frontmatter.ts
@@ -34895,7 +34943,7 @@ var SkillsScanner = class {
34895
34943
  home;
34896
34944
  extraPluginRoots;
34897
34945
  constructor(opts = {}) {
34898
- this.home = opts.home ?? import_node_os2.default.homedir();
34946
+ this.home = opts.home ?? import_node_os3.default.homedir();
34899
34947
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
34900
34948
  }
34901
34949
  /**
@@ -35102,6 +35150,11 @@ var DEFAULT_PERSONAS = [
35102
35150
  allowLocalBinding: true
35103
35151
  }
35104
35152
  }
35153
+ },
35154
+ codexSandbox: {
35155
+ writableRoots: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
35156
+ denyRead: [".secrets/**"],
35157
+ network: true
35105
35158
  }
35106
35159
  },
35107
35160
  {
@@ -35181,6 +35234,10 @@ function seedDefaultPersonas(args) {
35181
35234
  args.store.writeSandboxSettings(entry.personaId, settings);
35182
35235
  args.logger.info("persona.seed.sandbox-profile", { personaId: entry.personaId });
35183
35236
  }
35237
+ if (entry.codexSandbox) {
35238
+ args.store.writeCodexSandboxSettings(entry.personaId, entry.codexSandbox);
35239
+ args.logger.info("persona.seed.codex-sandbox", { personaId: entry.personaId });
35240
+ }
35184
35241
  copyBundleExtras(bundleDir, args.store.personaDirPath(entry.personaId));
35185
35242
  args.logger.info("persona.seed.created", { personaId: entry.personaId });
35186
35243
  }
@@ -35225,6 +35282,39 @@ function refreshDaemonManagedDirs(args) {
35225
35282
  }
35226
35283
  }
35227
35284
  }
35285
+ function migrateAgentsMirror(args) {
35286
+ let mirrored = 0;
35287
+ for (const personaId of args.store.list()) {
35288
+ try {
35289
+ if (args.store.ensureAgentsMirror(personaId)) {
35290
+ mirrored++;
35291
+ args.logger.info("persona.agents-mirror.synced", { personaId });
35292
+ }
35293
+ } catch (err) {
35294
+ args.logger.warn("persona.agents-mirror.failed", {
35295
+ personaId,
35296
+ error: err instanceof Error ? err.message : String(err)
35297
+ });
35298
+ }
35299
+ }
35300
+ if (mirrored > 0) args.logger.info("persona.agents-mirror.done", { mirrored });
35301
+ }
35302
+ function migrateCodexSandbox(args) {
35303
+ const entries = args.entries ?? DEFAULT_PERSONAS;
35304
+ let n = 0;
35305
+ for (const personaId of args.store.list()) {
35306
+ if (args.store.readCodexSandboxSettings(personaId)) continue;
35307
+ try {
35308
+ const def = entries.find((e) => e.personaId === personaId)?.codexSandbox ?? { writableRoots: [], denyRead: [], network: false };
35309
+ args.store.writeCodexSandboxSettings(personaId, def);
35310
+ n++;
35311
+ args.logger.info("persona.codex-sandbox.synced", { personaId });
35312
+ } catch (err) {
35313
+ args.logger.warn("persona.codex-sandbox.failed", { personaId, error: err instanceof Error ? err.message : String(err) });
35314
+ }
35315
+ }
35316
+ if (n > 0) args.logger.info("persona.codex-sandbox.done", { migrated: n });
35317
+ }
35228
35318
 
35229
35319
  // src/index.ts
35230
35320
  init_claude();
@@ -35421,19 +35511,58 @@ function resolveApprovalPolicy(ctx) {
35421
35511
  if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
35422
35512
  return "on-request";
35423
35513
  }
35514
+ function buildCodexGuestConfig(cs) {
35515
+ const filesystem = {};
35516
+ for (const w2 of cs.writableRoots ?? []) filesystem[w2] = "write";
35517
+ const deny = cs.denyRead ?? [];
35518
+ if (deny.length > 0) {
35519
+ const wsScoped = {};
35520
+ for (const d of deny) wsScoped[d] = "deny";
35521
+ filesystem[":workspace_roots"] = wsScoped;
35522
+ }
35523
+ return {
35524
+ default_permissions: "clawos_guest",
35525
+ permissions: {
35526
+ clawos_guest: {
35527
+ extends: ":workspace",
35528
+ filesystem,
35529
+ network: cs.network ? { enabled: true, domains: { "*": "allow" } } : { enabled: false }
35530
+ }
35531
+ }
35532
+ };
35533
+ }
35534
+ function tomlValue(v2) {
35535
+ if (typeof v2 === "string") return JSON.stringify(v2);
35536
+ if (typeof v2 === "boolean" || typeof v2 === "number") return String(v2);
35537
+ if (Array.isArray(v2)) return "[" + v2.map(tomlValue).join(",") + "]";
35538
+ if (v2 && typeof v2 === "object") {
35539
+ return "{" + Object.entries(v2).map(([k2, val]) => `${/^[A-Za-z0-9_-]+$/.test(k2) ? k2 : JSON.stringify(k2)}=${tomlValue(val)}`).join(",") + "}";
35540
+ }
35541
+ return JSON.stringify(v2);
35542
+ }
35543
+ function codexGuestCliArgs(cs) {
35544
+ const cfg = buildCodexGuestConfig(cs);
35545
+ const profile = cfg.permissions.clawos_guest;
35546
+ return [
35547
+ "-c",
35548
+ `default_permissions=${tomlValue("clawos_guest")}`,
35549
+ "-c",
35550
+ `permissions.clawos_guest=${tomlValue(profile)}`
35551
+ ];
35552
+ }
35424
35553
  function threadStartParams(ctx) {
35425
35554
  const params = {
35426
35555
  cwd: ctx.cwd,
35427
- sandbox: resolveSandbox(ctx),
35428
35556
  approvalPolicy: resolveApprovalPolicy(ctx),
35429
35557
  approvalsReviewer: "user",
35430
- ...ctx.model ? { model: ctx.model } : {}
35558
+ ...ctx.model ? { model: ctx.model } : {},
35559
+ // guest 沙箱由 app-server 启动 -c 注入的 permission profile(codexGuestCliArgs)控制——profile 是
35560
+ // 进程启动解析的。故 guest **不发 sandbox 字段**(避免 sandbox mode 覆盖 profile);owner/普通按 sandbox mode。
35561
+ ...ctx.personaMode === "guest" ? {} : { sandbox: resolveSandbox(ctx) },
35562
+ // 连接 intro(owner/guest 人称差异化)走 developerInstructions(developer 级、不进消息流、不显示在 UI),
35563
+ // 取代旧的"折进首条 turn 文本"(那个被当用户消息显示)。thread/start + thread/resume 都带,幂等。
35564
+ ...ctx.extraSystemPrompt ? { developerInstructions: ctx.extraSystemPrompt } : {}
35431
35565
  };
35432
- if (ctx.personaMode === "guest") {
35433
- params.config = {
35434
- sandbox_workspace_write: { writable_roots: ctx.addDirs ?? [], network_access: ctx.networkAccess ?? false }
35435
- };
35436
- }
35437
35566
  return params;
35438
35567
  }
35439
35568
  var ATTACHMENT_RE2 = /\[attachment:(image|file):([^\]]+)\]/g;
@@ -35462,12 +35591,14 @@ function turnStartInput(text) {
35462
35591
  function createCodexSession(ctx, sink, deps = {}) {
35463
35592
  const cmd = process.env.CODEX_BIN ?? "codex";
35464
35593
  const args = ["app-server", "--listen", "stdio://"];
35594
+ if (ctx.personaMode === "guest" && ctx.codexSandbox) {
35595
+ args.push(...codexGuestCliArgs(ctx.codexSandbox));
35596
+ }
35465
35597
  const env = { ...process.env, ...ctx.env };
35466
35598
  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
35599
  let threadId = ctx.toolSessionId;
35468
35600
  let turnId;
35469
35601
  const approvalIds = /* @__PURE__ */ new Map();
35470
- let pendingSystemPrompt = ctx.toolSessionId ? void 0 : ctx.extraSystemPrompt;
35471
35602
  const effort = ctx.effort;
35472
35603
  let exited = false;
35473
35604
  const finish = (code) => {
@@ -35530,15 +35661,11 @@ function createCodexSession(ctx, sink, deps = {}) {
35530
35661
  })().catch((e) => sink.onError(`codex app-server init failed: ${e.message}`));
35531
35662
  return {
35532
35663
  startTurn(text) {
35533
- const body = pendingSystemPrompt ? `${pendingSystemPrompt}
35534
-
35535
- ${text}` : text;
35536
- pendingSystemPrompt = void 0;
35537
35664
  void ready.then(() => {
35538
35665
  if (threadId)
35539
35666
  void client.request("turn/start", {
35540
35667
  threadId,
35541
- input: turnStartInput(body),
35668
+ input: turnStartInput(text),
35542
35669
  // TurnStartParams 字段是 `effort`(不是 `reasoningEffort`,0.138 改名)——传错名字
35543
35670
  // codex 静默忽略, reasoning effort 改了不生效。"override for this turn and subsequent turns"。
35544
35671
  ...effort ? { effort } : {}
@@ -35677,7 +35804,7 @@ var CodexAdapter = class {
35677
35804
 
35678
35805
  // src/tools/claude-tui.ts
35679
35806
  var import_node_fs11 = __toESM(require("fs"), 1);
35680
- var import_node_os5 = __toESM(require("os"), 1);
35807
+ var import_node_os6 = __toESM(require("os"), 1);
35681
35808
  var import_node_path10 = __toESM(require("path"), 1);
35682
35809
  var import_headless = __toESM(require_xterm_headless(), 1);
35683
35810
 
@@ -36657,7 +36784,7 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
36657
36784
  }
36658
36785
  function jsonlExistsForCtx(ctx) {
36659
36786
  if (!ctx.toolSessionId) return false;
36660
- const home = import_node_os5.default.homedir();
36787
+ const home = import_node_os6.default.homedir();
36661
36788
  const file = import_node_path10.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
36662
36789
  try {
36663
36790
  return import_node_fs11.default.statSync(file).isFile();
@@ -36901,7 +37028,7 @@ async function listCodexSkills(cwd, deps = {}) {
36901
37028
 
36902
37029
  // src/workspace/browser.ts
36903
37030
  var import_node_fs12 = __toESM(require("fs"), 1);
36904
- var import_node_os6 = __toESM(require("os"), 1);
37031
+ var import_node_os7 = __toESM(require("os"), 1);
36905
37032
  var import_node_path11 = __toESM(require("path"), 1);
36906
37033
  init_protocol();
36907
37034
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
@@ -36927,7 +37054,7 @@ function ensureCwd(cwd) {
36927
37054
  }
36928
37055
  var WorkspaceBrowser = class {
36929
37056
  list(args) {
36930
- const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
37057
+ const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
36931
37058
  ensureCwd(cwd);
36932
37059
  const full = resolveInsideCwd(cwd, args.path);
36933
37060
  const dirents = import_node_fs12.default.readdirSync(full, { withFileTypes: true });
@@ -36986,7 +37113,7 @@ var WorkspaceBrowser = class {
36986
37113
 
36987
37114
  // src/skills/agents-scanner.ts
36988
37115
  var import_node_fs13 = __toESM(require("fs"), 1);
36989
- var import_node_os7 = __toESM(require("os"), 1);
37116
+ var import_node_os8 = __toESM(require("os"), 1);
36990
37117
  var import_node_path12 = __toESM(require("path"), 1);
36991
37118
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
36992
37119
  function isDirLikeSync2(p2) {
@@ -37129,7 +37256,7 @@ var AgentsScanner = class {
37129
37256
  extraPluginRoots;
37130
37257
  policyDir;
37131
37258
  constructor(opts = {}) {
37132
- this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os7.default.homedir();
37259
+ this.home = opts.home ?? process.env.CLAUDE_CONFIG_DIR ?? import_node_os8.default.homedir();
37133
37260
  this.extraPluginRoots = opts.extraPluginRoots ?? [];
37134
37261
  if (opts.policyDir !== void 0) {
37135
37262
  this.policyDir = opts.policyDir;
@@ -37177,20 +37304,20 @@ var AgentsScanner = class {
37177
37304
 
37178
37305
  // src/observer/session-observer.ts
37179
37306
  var import_node_fs15 = __toESM(require("fs"), 1);
37180
- var import_node_os9 = __toESM(require("os"), 1);
37307
+ var import_node_os10 = __toESM(require("os"), 1);
37181
37308
  var import_node_path14 = __toESM(require("path"), 1);
37182
37309
  init_claude_history();
37183
37310
 
37184
37311
  // src/observer/subagent-meta-observer.ts
37185
37312
  var import_node_fs14 = __toESM(require("fs"), 1);
37186
- var import_node_os8 = __toESM(require("os"), 1);
37313
+ var import_node_os9 = __toESM(require("os"), 1);
37187
37314
  var import_node_path13 = __toESM(require("path"), 1);
37188
37315
  init_claude_history();
37189
37316
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
37190
37317
  var SubagentMetaObserver = class {
37191
37318
  constructor(opts) {
37192
37319
  this.opts = opts;
37193
- this.home = opts.home ?? import_node_os8.default.homedir();
37320
+ this.home = opts.home ?? import_node_os9.default.homedir();
37194
37321
  }
37195
37322
  opts;
37196
37323
  home;
@@ -37301,7 +37428,7 @@ var SubagentMetaObserver = class {
37301
37428
  var SessionObserver = class {
37302
37429
  constructor(opts) {
37303
37430
  this.opts = opts;
37304
- this.home = opts.home ?? import_node_os9.default.homedir();
37431
+ this.home = opts.home ?? import_node_os10.default.homedir();
37305
37432
  this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
37306
37433
  }
37307
37434
  opts;
@@ -38619,20 +38746,35 @@ async function connectRemote(args) {
38619
38746
  return;
38620
38747
  }
38621
38748
  if (f.type === "auth:ok") {
38622
- ws.off("message", onMessage);
38749
+ finish();
38623
38750
  resolve6();
38624
38751
  return;
38625
38752
  }
38626
38753
  if (f.type === "auth:error" || f.code === 4401) {
38627
- ws.off("message", onMessage);
38754
+ finish();
38628
38755
  reject(new Error(`auth failed: ${f.message ?? f.type ?? "unknown"}`));
38629
38756
  }
38630
38757
  };
38631
- ws.on("message", onMessage);
38632
- setTimeout(() => {
38633
- ws.off("message", onMessage);
38758
+ const onClose = (code, reason) => {
38759
+ finish();
38760
+ const detail = reason.toString() || (code === 4401 ? "BAD_TOKEN" : `code ${code}`);
38761
+ reject(
38762
+ new Error(
38763
+ code === 4401 ? `auth rejected: ${detail}` : `connection closed before auth (code ${code})`
38764
+ )
38765
+ );
38766
+ };
38767
+ const timer = setTimeout(() => {
38768
+ finish();
38634
38769
  reject(new Error("auth handshake timeout"));
38635
38770
  }, HANDSHAKE_TIMEOUT_MS);
38771
+ function finish() {
38772
+ ws.off("message", onMessage);
38773
+ ws.off("close", onClose);
38774
+ clearTimeout(timer);
38775
+ }
38776
+ ws.on("message", onMessage);
38777
+ ws.once("close", onClose);
38636
38778
  });
38637
38779
  function call(method, payload) {
38638
38780
  const requestId = crypto5.randomUUID();
@@ -39093,7 +39235,7 @@ async function writeUploadedAttachment(args) {
39093
39235
  // src/extension/import.ts
39094
39236
  var import_promises2 = __toESM(require("fs/promises"), 1);
39095
39237
  var import_node_path17 = __toESM(require("path"), 1);
39096
- var import_node_os10 = __toESM(require("os"), 1);
39238
+ var import_node_os11 = __toESM(require("os"), 1);
39097
39239
  var import_jszip = __toESM(require_lib3(), 1);
39098
39240
  var ImportError = class extends Error {
39099
39241
  constructor(code, message) {
@@ -39153,7 +39295,7 @@ async function importZip(buf, root) {
39153
39295
  if (destExists) {
39154
39296
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
39155
39297
  }
39156
- const stage = await import_promises2.default.mkdtemp(import_node_path17.default.join(import_node_os10.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
39298
+ const stage = await import_promises2.default.mkdtemp(import_node_path17.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
39157
39299
  try {
39158
39300
  for (const [name, entry] of Object.entries(zip.files)) {
39159
39301
  const dest = import_node_path17.default.join(stage, name);
@@ -40032,7 +40174,7 @@ function escape(v2) {
40032
40174
 
40033
40175
  // src/tunnel/frpc-binary.ts
40034
40176
  var import_node_fs22 = __toESM(require("fs"), 1);
40035
- var import_node_os11 = __toESM(require("os"), 1);
40177
+ var import_node_os12 = __toESM(require("os"), 1);
40036
40178
  var import_node_path23 = __toESM(require("path"), 1);
40037
40179
  var import_node_child_process7 = require("child_process");
40038
40180
  var import_node_stream2 = require("stream");
@@ -40493,14 +40635,14 @@ async function waitForFrpcReady(proc, timeoutMs) {
40493
40635
  }
40494
40636
 
40495
40637
  // src/tunnel/device-key.ts
40496
- var import_node_os12 = __toESM(require("os"), 1);
40638
+ var import_node_os13 = __toESM(require("os"), 1);
40497
40639
  var import_node_path26 = __toESM(require("path"), 1);
40498
40640
  var import_node_crypto8 = __toESM(require("crypto"), 1);
40499
40641
  var DERIVE_SALT = "clawd-tunnel-device-v1";
40500
40642
  function deriveStableDeviceKey(opts = {}) {
40501
- const hostname = opts.hostname ?? import_node_os12.default.hostname();
40502
- const uid = opts.uid ?? (typeof import_node_os12.default.userInfo === "function" ? import_node_os12.default.userInfo().uid : 0);
40503
- const home = opts.home ?? import_node_os12.default.homedir();
40643
+ const hostname = opts.hostname ?? import_node_os13.default.hostname();
40644
+ const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
40645
+ const home = opts.home ?? import_node_os13.default.homedir();
40504
40646
  const defaultDataDir = import_node_path26.default.resolve(import_node_path26.default.join(home, ".clawd"));
40505
40647
  const normalizedDataDir = opts.dataDir ? import_node_path26.default.resolve(opts.dataDir) : null;
40506
40648
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
@@ -40577,11 +40719,11 @@ function writeAuthFile(file, content) {
40577
40719
 
40578
40720
  // src/owner-profile.ts
40579
40721
  var import_node_fs26 = __toESM(require("fs"), 1);
40580
- var import_node_os13 = __toESM(require("os"), 1);
40722
+ var import_node_os14 = __toESM(require("os"), 1);
40581
40723
  var import_node_path28 = __toESM(require("path"), 1);
40582
40724
  var PROFILE_FILENAME = "profile.json";
40583
40725
  function loadOwnerDisplayName(dataDir) {
40584
- const fallback = import_node_os13.default.userInfo().username;
40726
+ const fallback = import_node_os14.default.userInfo().username;
40585
40727
  const profilePath = import_node_path28.default.join(dataDir, PROFILE_FILENAME);
40586
40728
  let raw;
40587
40729
  try {
@@ -40966,7 +41108,7 @@ init_protocol();
40966
41108
 
40967
41109
  // src/session/fork.ts
40968
41110
  var import_node_fs28 = __toESM(require("fs"), 1);
40969
- var import_node_os14 = __toESM(require("os"), 1);
41111
+ var import_node_os15 = __toESM(require("os"), 1);
40970
41112
  var import_node_path30 = __toESM(require("path"), 1);
40971
41113
  init_claude_history();
40972
41114
  function readJsonlEntries(file) {
@@ -40983,7 +41125,7 @@ function readJsonlEntries(file) {
40983
41125
  return out;
40984
41126
  }
40985
41127
  function forkSession(input) {
40986
- const baseDir = input.baseDir ?? import_node_path30.default.join(import_node_os14.default.homedir(), ".claude");
41128
+ const baseDir = input.baseDir ?? import_node_path30.default.join(import_node_os15.default.homedir(), ".claude");
40987
41129
  const projectDir = import_node_path30.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
40988
41130
  const sourceFile = import_node_path30.default.join(projectDir, `${input.toolSessionId}.jsonl`);
40989
41131
  if (!import_node_fs28.default.existsSync(sourceFile)) {
@@ -41553,7 +41695,7 @@ function buildHistoryHandlers(deps) {
41553
41695
 
41554
41696
  // src/handlers/workspace.ts
41555
41697
  var path42 = __toESM(require("path"), 1);
41556
- var os15 = __toESM(require("os"), 1);
41698
+ var os16 = __toESM(require("os"), 1);
41557
41699
  init_protocol();
41558
41700
  init_protocol();
41559
41701
  function buildEnabledPluginNames(personaManager, personaId) {
@@ -41593,7 +41735,7 @@ function buildWorkspaceHandlers(deps) {
41593
41735
  const list = async (frame, _client, ctx) => {
41594
41736
  const args = WorkspaceListArgs.parse(frame);
41595
41737
  const isGuest = ctx?.principal.kind === "guest";
41596
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
41738
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
41597
41739
  const resolvedCwd = path42.resolve(args.cwd ?? fallbackCwd);
41598
41740
  const target = args.path ? path42.resolve(resolvedCwd, args.path) : resolvedCwd;
41599
41741
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
@@ -42020,6 +42162,7 @@ function buildFeishuAuthHandlers(deps) {
42020
42162
  };
42021
42163
  const logout = async () => {
42022
42164
  deps.ownerIdentityStore.clear();
42165
+ deps.serverKeyStore.clear();
42023
42166
  return {
42024
42167
  response: { type: "auth:logout:ok" }
42025
42168
  };
@@ -42117,7 +42260,7 @@ function buildDeviceHandlers(deps) {
42117
42260
  }
42118
42261
 
42119
42262
  // src/handlers/meta.ts
42120
- var import_node_os15 = __toESM(require("os"), 1);
42263
+ var import_node_os16 = __toESM(require("os"), 1);
42121
42264
  init_protocol();
42122
42265
 
42123
42266
  // src/version.ts
@@ -42148,7 +42291,7 @@ function buildReadyFrame(deps, client) {
42148
42291
  return {
42149
42292
  version,
42150
42293
  protocolVersion: PROTOCOL_VERSION,
42151
- hostname: import_node_os15.default.hostname(),
42294
+ hostname: import_node_os16.default.hostname(),
42152
42295
  os: process.platform,
42153
42296
  tools,
42154
42297
  runningSessions: info.runningSessions,
@@ -42487,15 +42630,15 @@ function computePublishCheck(args) {
42487
42630
  // src/extension/install-flow.ts
42488
42631
  var import_promises5 = __toESM(require("fs/promises"), 1);
42489
42632
  var import_node_path35 = __toESM(require("path"), 1);
42490
- var import_node_os17 = __toESM(require("os"), 1);
42633
+ var import_node_os18 = __toESM(require("os"), 1);
42491
42634
  var import_node_crypto12 = __toESM(require("crypto"), 1);
42492
42635
  var import_jszip3 = __toESM(require_lib3(), 1);
42493
42636
 
42494
42637
  // src/extension/paths.ts
42495
- var import_node_os16 = __toESM(require("os"), 1);
42638
+ var import_node_os17 = __toESM(require("os"), 1);
42496
42639
  var import_node_path34 = __toESM(require("path"), 1);
42497
42640
  function clawdHomeRoot(override) {
42498
- return override ?? process.env.CLAWD_HOME ?? import_node_path34.default.join(import_node_os16.default.homedir(), ".clawd");
42641
+ return override ?? process.env.CLAWD_HOME ?? import_node_path34.default.join(import_node_os17.default.homedir(), ".clawd");
42499
42642
  }
42500
42643
  function extensionsRoot(override) {
42501
42644
  return import_node_path34.default.join(clawdHomeRoot(override), "extensions");
@@ -42577,7 +42720,7 @@ async function installFromChannel(args, deps) {
42577
42720
  );
42578
42721
  }
42579
42722
  const stage = await import_promises5.default.mkdtemp(
42580
- import_node_path35.default.join(import_node_os17.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
42723
+ import_node_path35.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
42581
42724
  );
42582
42725
  try {
42583
42726
  for (const [name, entry] of Object.entries(zip.files)) {
@@ -42608,7 +42751,7 @@ async function installFromChannel(args, deps) {
42608
42751
  // src/extension/update-flow.ts
42609
42752
  var import_promises6 = __toESM(require("fs/promises"), 1);
42610
42753
  var import_node_path36 = __toESM(require("path"), 1);
42611
- var import_node_os18 = __toESM(require("os"), 1);
42754
+ var import_node_os19 = __toESM(require("os"), 1);
42612
42755
  var import_node_crypto13 = __toESM(require("crypto"), 1);
42613
42756
  var import_jszip4 = __toESM(require_lib3(), 1);
42614
42757
  var UpdateError = class extends Error {
@@ -42696,7 +42839,7 @@ async function updateFromChannel(args, deps) {
42696
42839
  await import_promises6.default.rm(prevDir, { recursive: true, force: true });
42697
42840
  await import_promises6.default.rename(liveDir, prevDir);
42698
42841
  const stage = await import_promises6.default.mkdtemp(
42699
- import_node_path36.default.join(import_node_os18.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
42842
+ import_node_path36.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
42700
42843
  );
42701
42844
  try {
42702
42845
  for (const [name, entry] of Object.entries(zip.files)) {
@@ -45252,6 +45395,8 @@ async function startDaemon(config) {
45252
45395
  } else {
45253
45396
  logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
45254
45397
  }
45398
+ migrateAgentsMirror({ store: personaStore, logger });
45399
+ migrateCodexSandbox({ store: personaStore, logger });
45255
45400
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
45256
45401
  const manager = new SessionManager({
45257
45402
  store,
@@ -45402,15 +45547,14 @@ async function startDaemon(config) {
45402
45547
  };
45403
45548
  const fetchServerKey = async () => {
45404
45549
  if (!feishuActive) return;
45405
- if (serverKeyStore.read()) return;
45406
45550
  try {
45407
45551
  const { publicKeyPem } = await centralGetPublicKey({
45408
45552
  api: config.clawosApi ?? DEFAULT_CLAWOS_API
45409
45553
  });
45410
45554
  serverKeyStore.write(publicKeyPem);
45411
- logger.info("server signing key cached");
45555
+ logger.info("server signing key refreshed");
45412
45556
  } catch (err) {
45413
- logger.warn("server signing key fetch failed (guest \u5165\u7AD9\u5C06\u88AB\u62D2\u7EDD)", {
45557
+ logger.warn("server signing key fetch failed (\u4FDD\u7559\u65E7\u7F13\u5B58)", {
45414
45558
  err: err.message
45415
45559
  });
45416
45560
  }
@@ -45516,7 +45660,7 @@ async function startDaemon(config) {
45516
45660
  bundleCache,
45517
45661
  // 飞书统一身份 Phase 1:登录 RPC handlers(auth:login:start / getIdentity / logout)
45518
45662
  // deviceId(决策 #15):getIdentity 返回给 UI 拼"我的设备标识"
45519
- feishuAuth: { loginFlow, ownerIdentityStore, deviceId: authFile.deviceId },
45663
+ feishuAuth: { loginFlow, ownerIdentityStore, deviceId: authFile.deviceId, serverKeyStore },
45520
45664
  // 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
45521
45665
  // exchange/listDevices 包掉 owner ttcJwt(每次现读 store——热切换后立即用新身份);
45522
45666
  // dispatcher 的 FEISHU_GATED_METHODS gate 已保证未登录时这些 RPC 到不了 handler,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.135-beta.280.568890f",
3
+ "version": "0.2.135-beta.282.8ee36dc",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",