@clawos-dev/clawd 0.2.227 → 0.2.228

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
@@ -6136,7 +6136,12 @@ var init_dispatch = __esm({
6136
6136
  prompt: external_exports.string(),
6137
6137
  // 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
6138
6138
  // 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
6139
- targetDeviceId: external_exports.string().min(1).optional()
6139
+ targetDeviceId: external_exports.string().min(1).optional(),
6140
+ // 可选:override B session 使用的 claude 模型。缺省 = 用 persona 默认。
6141
+ // 合法值集与 claude adapter capabilities.models[].id 一致(见 daemon
6142
+ // tools/claude.ts CLAUDE_MODEL_IDS);handler 层做二次校验,非法值 fail-fast。
6143
+ // protocol 层保持 string 便于未来跨 tool 扩展(届时 union 收合法字面量)。
6144
+ model: external_exports.string().min(1).optional()
6140
6145
  });
6141
6146
  DispatchCompleteArgsSchema = external_exports.object({
6142
6147
  dispatchId: external_exports.string().min(1),
@@ -12542,7 +12547,7 @@ function encodeClaudeStdin(text) {
12542
12547
  };
12543
12548
  return JSON.stringify(frame) + "\n";
12544
12549
  }
12545
- var import_node_child_process, import_node_child_process2, import_node_fs15, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12550
+ var import_node_child_process, import_node_child_process2, import_node_fs15, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODEL_IDS, CLAUDE_MODELS, _assertModelIdsAligned, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12546
12551
  var init_claude = __esm({
12547
12552
  "src/tools/claude.ts"() {
12548
12553
  "use strict";
@@ -12568,13 +12573,17 @@ var init_claude = __esm({
12568
12573
  gif: "image/gif",
12569
12574
  webp: "image/webp"
12570
12575
  };
12576
+ CLAUDE_MODEL_IDS = ["opus", "fable", "sonnet", "haiku"];
12571
12577
  CLAUDE_MODELS = [
12572
- { id: "", label: "Default", description: "CLI default model", contextWindowSize: 2e5, default: true },
12578
+ { id: "", label: "Default", description: "CLI default model", contextWindowSize: 1e6, default: true },
12573
12579
  { id: "opus", label: "Opus", description: "Most capable", contextWindowSize: 1e6 },
12574
- { id: "fable", label: "Fable", contextWindowSize: 2e5 },
12575
- { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 2e5 },
12576
- { id: "haiku", label: "Haiku", description: "Fastest, lightest", contextWindowSize: 2e5 }
12580
+ { id: "fable", label: "Fable", contextWindowSize: 1e6 },
12581
+ { id: "sonnet", label: "Sonnet", description: "Fast, balanced", contextWindowSize: 1e6 },
12582
+ { id: "haiku", label: "Haiku", description: "Fastest, lightest", contextWindowSize: 1e6 }
12577
12583
  ];
12584
+ _assertModelIdsAligned = CLAUDE_MODELS.filter(
12585
+ (m2) => m2.id !== ""
12586
+ ).map((m2) => m2.id);
12578
12587
  CLAUDE_PERMISSION_MODES = [
12579
12588
  { id: "", label: "Default", description: "Ask for every tool call" },
12580
12589
  { id: "plan", label: "Plan", description: "Read-only, no code changes" },
@@ -44602,6 +44611,8 @@ var SessionManager = class {
44602
44611
  creatorPrincipalId: args.guestPrincipalId,
44603
44612
  ...args.guestDisplayName ? { creatorDisplayName: args.guestDisplayName } : {}
44604
44613
  } : {},
44614
+ // T-20:dispatch model override 落盘(reducer spawn 路径读 SessionFile.model 生成 --model flag)
44615
+ ...args.model ? { model: args.model } : {},
44605
44616
  createdAt: now,
44606
44617
  updatedAt: now
44607
44618
  };
@@ -48819,12 +48830,19 @@ function canAccessPersona(grants, personaId, action) {
48819
48830
  }
48820
48831
 
48821
48832
  // src/handlers/persona-dispatch.ts
48833
+ init_claude();
48822
48834
  function buildPersonaDispatchHandlers(deps) {
48823
48835
  const { personaDispatchManager: mgr, spawnB, logger } = deps;
48824
48836
  const run = async (frame, _client, ctx) => {
48825
48837
  const { type: _t, requestId: _r, ...rest } = frame;
48826
48838
  const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
48827
48839
  const args = DispatchRunArgsSchema.parse(rest);
48840
+ if (args.model !== void 0 && !CLAUDE_MODEL_IDS.includes(args.model)) {
48841
+ throw new ClawdError(
48842
+ ERROR_CODES.INVALID_PARAM,
48843
+ `model '${args.model}' not supported; allowed: ${CLAUDE_MODEL_IDS.join(", ")}`
48844
+ );
48845
+ }
48828
48846
  if (args.targetDeviceId) {
48829
48847
  if (ctx?.principal.kind === "guest") {
48830
48848
  throw new ClawdError(
@@ -48842,7 +48860,8 @@ function buildPersonaDispatchHandlers(deps) {
48842
48860
  const outcome2 = await deps.forwardToPeer({
48843
48861
  targetDeviceId: args.targetDeviceId,
48844
48862
  targetPersona: args.targetPersona,
48845
- prompt: args.prompt
48863
+ prompt: args.prompt,
48864
+ ...args.model ? { model: args.model } : {}
48846
48865
  });
48847
48866
  return {
48848
48867
  response: { type: "personaDispatch:run:ok", outcome: outcome2 }
@@ -48872,7 +48891,8 @@ function buildPersonaDispatchHandlers(deps) {
48872
48891
  targetPersona: args.targetPersona,
48873
48892
  prompt: args.prompt,
48874
48893
  guestPrincipalId: ctx.principal.id,
48875
- guestDisplayName: ctx.principal.displayName
48894
+ guestDisplayName: ctx.principal.displayName,
48895
+ ...args.model ? { model: args.model } : {}
48876
48896
  }).then(() => logger?.info("dispatch.spawnB.ok", { dispatchId: dispatchId2 })).catch((err) => {
48877
48897
  const reason = err instanceof Error ? err.message : String(err);
48878
48898
  logger?.warn("dispatch.spawnB.failed", { dispatchId: dispatchId2, reason });
@@ -48905,7 +48925,8 @@ function buildPersonaDispatchHandlers(deps) {
48905
48925
  dispatchId,
48906
48926
  sourceSessionId,
48907
48927
  targetPersona: args.targetPersona,
48908
- prompt: args.prompt
48928
+ prompt: args.prompt,
48929
+ ...args.model ? { model: args.model } : {}
48909
48930
  }).then(() => {
48910
48931
  logger?.info("dispatch.spawnB.ok", { dispatchId });
48911
48932
  }).catch((err) => {
@@ -48963,7 +48984,12 @@ async function forwardDispatchToPeer(args) {
48963
48984
  authorization: `Bearer ${args.contact.connectToken}`
48964
48985
  },
48965
48986
  // 注意:不带 targetDeviceId —— B 端据此判定为本地执行(B 角色)。
48966
- body: JSON.stringify({ targetPersona: args.targetPersona, prompt: args.prompt })
48987
+ body: JSON.stringify({
48988
+ targetPersona: args.targetPersona,
48989
+ prompt: args.prompt,
48990
+ // T-20: 条件展开防 undefined 污染 JSON。远端 daemon handler 会再校验一次 model 合法性。
48991
+ ...args.model ? { model: args.model } : {}
48992
+ })
48967
48993
  });
48968
48994
  } catch (err) {
48969
48995
  const msg = err instanceof Error ? err.message : String(err);
@@ -60186,11 +60212,13 @@ async function startDaemon(config) {
60186
60212
  sourceJsonlPath,
60187
60213
  // B 角色(跨设备):非空 → guest scope + creatorPrincipalId/creatorDisplayName = A。
60188
60214
  guestPrincipalId: args.guestPrincipalId,
60189
- guestDisplayName: args.guestDisplayName
60215
+ guestDisplayName: args.guestDisplayName,
60216
+ // T-20: 可选 model override 透到 SessionFile.model
60217
+ ...args.model ? { model: args.model } : {}
60190
60218
  });
60191
60219
  },
60192
60220
  // A 角色:从 ContactStore 取 peer 可达 URL + connect token,转发到对端 daemon /rpc。
60193
- forwardToPeer: async ({ targetDeviceId, targetPersona, prompt }) => {
60221
+ forwardToPeer: async ({ targetDeviceId, targetPersona, prompt, model }) => {
60194
60222
  const contact = contactStore.get(targetDeviceId);
60195
60223
  if (!contact || !contact.remoteUrl || !contact.connectToken) {
60196
60224
  return {
@@ -60201,7 +60229,9 @@ async function startDaemon(config) {
60201
60229
  return forwardDispatchToPeer({
60202
60230
  contact: { remoteUrl: contact.remoteUrl, connectToken: contact.connectToken },
60203
60231
  targetPersona,
60204
- prompt
60232
+ prompt,
60233
+ // T-20: 跨设备也透 model,让远端 daemon 用同一 claude 模型 spawn B
60234
+ ...model ? { model } : {}
60205
60235
  });
60206
60236
  },
60207
60237
  // B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。