@clawos-dev/clawd 0.2.135-beta.279.732f6db → 0.2.135-beta.281.fb1ead2

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 +72 -9
  2. package/package.json +1 -1
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
@@ -31762,6 +31767,9 @@ function buildSpawnContext(state, deps) {
31762
31767
  if (meta?.addDirs && meta.addDirs.length > 0) {
31763
31768
  ctx.addDirs = meta.addDirs;
31764
31769
  }
31770
+ if (meta?.networkAccess !== void 0) {
31771
+ ctx.networkAccess = meta.networkAccess;
31772
+ }
31765
31773
  return ctx;
31766
31774
  }
31767
31775
  function sessionInfoFrame(file) {
@@ -33258,6 +33266,8 @@ var SessionManager = class {
33258
33266
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
33259
33267
  const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
33260
33268
  subSessionMeta.extraSettings = JSON.stringify(settings);
33269
+ const domains = settings.sandbox?.network?.allowedDomains;
33270
+ subSessionMeta.networkAccess = Array.isArray(domains) && domains.length > 0;
33261
33271
  }
33262
33272
  const attachmentGroup = this.deps.attachmentGroup;
33263
33273
  const runner = new SessionRunner(makeInitialState(file, subSessionMeta), {
@@ -34472,6 +34482,11 @@ var PersonaStore = class {
34472
34482
  claudeMdPath(personaId) {
34473
34483
  return path9.join(this.personaDir(personaId), "CLAUDE.md");
34474
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
+ }
34475
34490
  /**
34476
34491
  * persona 级 sandbox 模板落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
34477
34492
  * source 自动发现扫不到(owner `--setting-sources user,project,local` 不会顺手带进来)。
@@ -34485,6 +34500,7 @@ var PersonaStore = class {
34485
34500
  const dir = this.personaDir(persona.personaId);
34486
34501
  fs7.mkdirSync(path9.join(dir, ".clawd"), { recursive: true });
34487
34502
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
34503
+ this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
34488
34504
  this.atomicWrite(
34489
34505
  this.sandboxSettingsPath(persona.personaId),
34490
34506
  JSON.stringify(buildGuestSettingsV1(), null, 2)
@@ -34493,6 +34509,21 @@ var PersonaStore = class {
34493
34509
  }
34494
34510
  writePersonality(personaId, personality) {
34495
34511
  this.atomicWrite(this.claudeMdPath(personaId), personality);
34512
+ this.atomicWrite(this.agentsMdPath(personaId), personality);
34513
+ }
34514
+ /**
34515
+ * 历史 persona 补 AGENTS.md:人格双写镜像是 codex 适配后才加的,更早落盘的 persona 只有
34516
+ * CLAUDE.md。codex 原生读 cwd 的 AGENTS.md,缺失则切到 codex 后人格丢失。daemon 启动跑一次
34517
+ * migrate(见 seed.migrateAgentsMirror)。幂等:已有 AGENTS.md(含用户手改的)不覆盖;
34518
+ * 无 CLAUDE.md 不凭空造。返回是否实际补写。
34519
+ */
34520
+ ensureAgentsMirror(personaId) {
34521
+ const claudeMd = this.claudeMdPath(personaId);
34522
+ const agentsMd = this.agentsMdPath(personaId);
34523
+ if (!fs7.existsSync(claudeMd)) return false;
34524
+ if (fs7.existsSync(agentsMd)) return false;
34525
+ this.atomicWrite(agentsMd, fs7.readFileSync(claudeMd, "utf8"));
34526
+ return true;
34496
34527
  }
34497
34528
  /**
34498
34529
  * 覆盖式写 persona 级 sandbox 配置(seed 给有 profile 的 persona 写 base⊕profile;owner 之后可手编)。
@@ -34522,9 +34553,11 @@ var PersonaStore = class {
34522
34553
  return fs7.existsSync(this.metaPath(personaId));
34523
34554
  }
34524
34555
  readPersonality(personaId) {
34525
- const p2 = this.claudeMdPath(personaId);
34526
- if (!fs7.existsSync(p2)) return null;
34527
- return fs7.readFileSync(p2, "utf8");
34556
+ const claudeMd = this.claudeMdPath(personaId);
34557
+ if (fs7.existsSync(claudeMd)) return fs7.readFileSync(claudeMd, "utf8");
34558
+ const agentsMd = this.agentsMdPath(personaId);
34559
+ if (fs7.existsSync(agentsMd)) return fs7.readFileSync(agentsMd, "utf8");
34560
+ return null;
34528
34561
  }
34529
34562
  /**
34530
34563
  * 读 sandbox-settings.json 当前内容;文件不存在 / JSON 解析失败均返回 null。
@@ -34926,6 +34959,7 @@ var PersonaManager = class {
34926
34959
  personaId,
34927
34960
  label: args.label,
34928
34961
  model: args.model,
34962
+ tool: args.tool,
34929
34963
  public: args.public ?? false,
34930
34964
  iconKey: args.iconKey,
34931
34965
  createdAt: now,
@@ -35205,6 +35239,23 @@ function refreshDaemonManagedDirs(args) {
35205
35239
  }
35206
35240
  }
35207
35241
  }
35242
+ function migrateAgentsMirror(args) {
35243
+ let mirrored = 0;
35244
+ for (const personaId of args.store.list()) {
35245
+ try {
35246
+ if (args.store.ensureAgentsMirror(personaId)) {
35247
+ mirrored++;
35248
+ args.logger.info("persona.agents-mirror.synced", { personaId });
35249
+ }
35250
+ } catch (err) {
35251
+ args.logger.warn("persona.agents-mirror.failed", {
35252
+ personaId,
35253
+ error: err instanceof Error ? err.message : String(err)
35254
+ });
35255
+ }
35256
+ }
35257
+ if (mirrored > 0) args.logger.info("persona.agents-mirror.done", { mirrored });
35258
+ }
35208
35259
 
35209
35260
  // src/index.ts
35210
35261
  init_claude();
@@ -35392,24 +35443,29 @@ function num(v2) {
35392
35443
 
35393
35444
  // src/tools/codex-app-server-params.ts
35394
35445
  function resolveSandbox(ctx) {
35395
- if (ctx.personaMode === "guest") throw new Error("codex \u6682\u4E0D\u652F\u6301 guest persona session\uFF1B\u8BF7\u7528 claude \u6216 owner");
35446
+ if (ctx.personaMode === "guest") return "workspace-write";
35396
35447
  return "danger-full-access";
35397
35448
  }
35398
35449
  function resolveApprovalPolicy(ctx) {
35450
+ if (ctx.personaMode === "owner" || ctx.personaMode === "guest") return "never";
35399
35451
  const m2 = ctx.permissionMode ?? "";
35400
35452
  if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
35401
35453
  return "on-request";
35402
35454
  }
35403
35455
  function threadStartParams(ctx) {
35404
- return {
35456
+ const params = {
35405
35457
  cwd: ctx.cwd,
35406
35458
  sandbox: resolveSandbox(ctx),
35407
- // persona 侧
35408
35459
  approvalPolicy: resolveApprovalPolicy(ctx),
35409
- // 会话设置侧
35410
35460
  approvalsReviewer: "user",
35411
35461
  ...ctx.model ? { model: ctx.model } : {}
35412
35462
  };
35463
+ if (ctx.personaMode === "guest") {
35464
+ params.config = {
35465
+ sandbox_workspace_write: { writable_roots: ctx.addDirs ?? [], network_access: ctx.networkAccess ?? false }
35466
+ };
35467
+ }
35468
+ return params;
35413
35469
  }
35414
35470
  var ATTACHMENT_RE2 = /\[attachment:(image|file):([^\]]+)\]/g;
35415
35471
  var SKILL_RE = /\[skill:(.+?):(\/[^\]]+)\]/g;
@@ -35598,6 +35654,10 @@ var CODEX_CAPABILITIES = {
35598
35654
  }
35599
35655
  ]
35600
35656
  };
35657
+ function sanitizeCodexModel(model) {
35658
+ if (model === void 0) return void 0;
35659
+ return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
35660
+ }
35601
35661
  async function probeCodex(env = process.env) {
35602
35662
  if (env.CODEX_BIN && import_node_fs10.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
35603
35663
  try {
@@ -35631,7 +35691,7 @@ var CodexAdapter = class {
35631
35691
  return (CODEX_MODELS.find((m2) => m2.id === (modelId ?? "")) ?? CODEX_MODELS[0]).contextWindowSize;
35632
35692
  }
35633
35693
  createSession(ctx, sink) {
35634
- return createCodexSession(ctx, sink, { logger: this.logger });
35694
+ return createCodexSession({ ...ctx, model: sanitizeCodexModel(ctx.model) }, sink, { logger: this.logger });
35635
35695
  }
35636
35696
  spawn(_ctx) {
35637
35697
  throw new Error("CodexAdapter uses createSession, not spawn");
@@ -41051,15 +41111,17 @@ function buildSessionHandlers(deps) {
41051
41111
  };
41052
41112
  const create = async (frame, _client, ctx) => {
41053
41113
  const args = SessionCreateArgs.parse(frame);
41114
+ let tool = args.tool;
41054
41115
  if (args.ownerPersonaId) {
41055
41116
  const persona = deps.personaRegistry.get(args.ownerPersonaId);
41056
41117
  if (!persona) {
41057
41118
  throw new Error(`persona not found: ${args.ownerPersonaId}`);
41058
41119
  }
41120
+ tool = persona.tool ?? args.tool;
41059
41121
  }
41060
41122
  ensurePersonaAccess(ctx, args.ownerPersonaId, "send");
41061
41123
  const creatorPrincipalId = ctx?.principal.id ?? ownerPrincipalId;
41062
- const { response, broadcast } = manager.create(args, creatorPrincipalId);
41124
+ const { response, broadcast } = manager.create({ ...args, tool }, creatorPrincipalId);
41063
41125
  return { response: { type: "session:info", ...response }, broadcast };
41064
41126
  };
41065
41127
  const list = async (_frame, _client, ctx) => {
@@ -45221,6 +45283,7 @@ async function startDaemon(config) {
45221
45283
  } else {
45222
45284
  logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
45223
45285
  }
45286
+ migrateAgentsMirror({ store: personaStore, logger });
45224
45287
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
45225
45288
  const manager = new SessionManager({
45226
45289
  store,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.135-beta.279.732f6db",
3
+ "version": "0.2.135-beta.281.fb1ead2",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",