@clawos-dev/clawd 0.2.233 → 0.2.234

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
@@ -4820,6 +4820,14 @@ var init_schemas = __esm({
4820
4820
  * 或 deps.ownerDisplayName(owner)。
4821
4821
  */
4822
4822
  creatorDisplayName: external_exports.string().min(1).optional(),
4823
+ /**
4824
+ * 创建该 session 的连接者飞书 union_id(一次性 stamp,T-31 persona prompt injection)。
4825
+ * session:create / dispatch spawnB handler 从 ctx.principal.feishuUnionId(guest 场景来自
4826
+ * connect token subOwner)或 deps.ownerFeishuUnionId(owner 场景)传入;newRunner 时读这个
4827
+ * 字段派生 SubSessionMeta.callerFeishuUnionId 注入 cc system prompt「身份卡」的 union_id 行。
4828
+ * Optional:老 SessionFile / owner 未登飞书路径缺省,缺省时 prompt 不渲染该行(向后兼容)。
4829
+ */
4830
+ creatorFeishuUnionId: external_exports.string().min(1).optional(),
4823
4831
  /**
4824
4832
  * Mirror peer sessions (2026-05-26): mirror 标识。**我在朋友 daemon 上创建的 session**,
4825
4833
  * 远端是 source of truth,本机是持久化副本,方便 sidebar 跨设备聚合。
@@ -41423,11 +41431,17 @@ function scopeSubPath(scope) {
41423
41431
  if (scope.mode === "guest") return [scope.personaId, "guests", scope.capId];
41424
41432
  return [scope.personaId, scope.mode];
41425
41433
  }
41426
- function metaFromScope(scope, personaRoot, usersRoot, ownerPrincipalId, callerDisplayName) {
41434
+ function metaFromScope(scope, personaRoot, usersRoot, ownerPrincipalId, callerDisplayName, callerFeishuUnionId) {
41427
41435
  if (scope.kind === "default") return void 0;
41428
41436
  if (scope.mode === "owner") {
41429
41437
  if (!ownerPrincipalId || !usersRoot) {
41430
- return { idleKillEnabled: false, personaMode: "owner", callerDisplayName };
41438
+ return {
41439
+ idleKillEnabled: false,
41440
+ personaMode: "owner",
41441
+ callerDisplayName,
41442
+ callerDeviceId: ownerPrincipalId,
41443
+ callerFeishuUnionId
41444
+ };
41431
41445
  }
41432
41446
  const userWorkDir2 = deriveUserWorkDir(ownerPrincipalId, usersRoot);
41433
41447
  return {
@@ -41435,7 +41449,9 @@ function metaFromScope(scope, personaRoot, usersRoot, ownerPrincipalId, callerDi
41435
41449
  personaMode: "owner",
41436
41450
  userWorkDir: userWorkDir2,
41437
41451
  addDirs: [userWorkDir2],
41438
- callerDisplayName
41452
+ callerDisplayName,
41453
+ callerDeviceId: ownerPrincipalId,
41454
+ callerFeishuUnionId
41439
41455
  };
41440
41456
  }
41441
41457
  const userWorkDir = deriveUserWorkDir(scope.capId, usersRoot);
@@ -41444,7 +41460,9 @@ function metaFromScope(scope, personaRoot, usersRoot, ownerPrincipalId, callerDi
41444
41460
  personaMode: "guest",
41445
41461
  userWorkDir,
41446
41462
  addDirs: [userWorkDir],
41447
- callerDisplayName
41463
+ callerDisplayName,
41464
+ callerDeviceId: scope.capId,
41465
+ callerFeishuUnionId
41448
41466
  };
41449
41467
  }
41450
41468
  function scopeForFile(file, ownerPrincipalId) {
@@ -41844,30 +41862,61 @@ function buildRule(tool, input) {
41844
41862
  }
41845
41863
 
41846
41864
  // src/persona/connection-prompt.ts
41847
- var OWNER_TEMPLATE = `# \u8FDE\u63A5\u4E0A\u4E0B\u6587
41848
- \u4F60\u73B0\u5728\u4EE5 Owner \u8EAB\u4EFD\u88AB\u8FDE\u63A5\uFF0C\u5BF9\u65B9\u5C31\u662F owner \u672C\u4EBA\uFF08{ownerLabel}\uFF09\u3002
41849
- \u81EA\u6211\u4ECB\u7ECD\u65F6\u4F7F\u7528\u7B2C\u4E00/\u7B2C\u4E8C\u4EBA\u79F0\uFF0C\u4F8B\u5982\u300C\u6211\u662F\u60A8\u7684 xxx \u52A9\u624B\u300D\u3002`;
41850
- var GUEST_TEMPLATE = `# \u8FDE\u63A5\u4E0A\u4E0B\u6587
41851
- \u4F60\u73B0\u5728\u4EE5 Guest \u8EAB\u4EFD\u88AB\u8FDE\u63A5\uFF0C\u672C persona \u7684 owner \u662F\u300C{ownerLabel}\u300D\uFF0C\u5F53\u524D\u5BF9\u8BDD\u7684\u5BF9\u65B9\u662F\u300C{guestLabel}\u300D\uFF0C\u4E0D\u662F owner \u672C\u4EBA\u3002
41852
- \u81EA\u6211\u4ECB\u7ECD\u65F6\u7B2C\u4E09\u4EBA\u79F0\u6307\u4EE3 owner\u3001\u7B2C\u4E8C\u4EBA\u79F0\u79F0\u547C\u5BF9\u65B9\uFF0C\u4F8B\u5982\u300C{guestLabel}\uFF0C\u6211\u662F {ownerLabel} \u7684 xxx \u52A9\u624B\uFF0C\u4F60\u53EF\u4EE5\u901A\u8FC7\u6211\u770B\u5230\u4ED6\u7684 xxx\u300D\u3002\u4E0D\u8981\u628A\u5BF9\u65B9\u5F53\u6210 owner\uFF0C\u4E0D\u8981\u66FF owner \u505A\u51FA\u627F\u8BFA\u3002`;
41865
+ function renderIdentityLines(fields) {
41866
+ const lines = [`- \u663E\u793A\u540D\uFF1A${fields.label}`];
41867
+ if (fields.feishuUnionId) lines.push(`- \u98DE\u4E66 union_id\uFF1A${fields.feishuUnionId}`);
41868
+ if (fields.deviceId) lines.push(`- \u8BBE\u5907 id\uFF1A${fields.deviceId}`);
41869
+ if (fields.extraLastLine) lines.push(fields.extraLastLine);
41870
+ return lines.join("\n");
41871
+ }
41853
41872
  function buildConnectionPrompt(args) {
41854
- let result;
41855
- if (args.mode === "guest") {
41856
- result = GUEST_TEMPLATE.replace(/\{ownerLabel\}/g, args.ownerLabel).replace(
41857
- /\{guestLabel\}/g,
41858
- args.guestLabel
41873
+ const parts = ["# \u8FDE\u63A5\u4E0A\u4E0B\u6587"];
41874
+ if (args.mode === "owner") {
41875
+ parts.push("\u5F53\u524D\u8FDE\u63A5\u65B9\uFF08\u5C31\u662F owner \u672C\u4EBA\uFF09\uFF1A");
41876
+ parts.push(
41877
+ renderIdentityLines({
41878
+ label: args.ownerLabel,
41879
+ feishuUnionId: args.ownerFeishuUnionId,
41880
+ deviceId: args.ownerDeviceId
41881
+ })
41859
41882
  );
41860
41883
  } else {
41861
- result = OWNER_TEMPLATE.replace(/\{ownerLabel\}/g, args.ownerLabel);
41884
+ parts.push("\u5F53\u524D\u8FDE\u63A5\u65B9\uFF08\u4E0D\u662F owner \u672C\u4EBA\uFF09\uFF1A");
41885
+ parts.push(
41886
+ renderIdentityLines({
41887
+ label: args.guestLabel,
41888
+ feishuUnionId: args.guestFeishuUnionId,
41889
+ deviceId: args.guestDeviceId,
41890
+ extraLastLine: "- \u8EAB\u4EFD\uFF1AGuest\uFF08\u8FDC\u7A0B\u8FDE\u63A5\u8FDB\u6765\u7684\u8054\u7CFB\u4EBA\uFF09"
41891
+ })
41892
+ );
41893
+ parts.push("");
41894
+ parts.push("\u672C persona \u7684 owner\uFF1A");
41895
+ parts.push(
41896
+ renderIdentityLines({
41897
+ label: args.ownerLabel,
41898
+ feishuUnionId: args.ownerFeishuUnionId,
41899
+ deviceId: args.ownerDeviceId
41900
+ })
41901
+ );
41862
41902
  }
41863
41903
  if (args.workDir) {
41864
- result += `
41865
- \u4F60\u7684\u6587\u4EF6\u5DE5\u4F5C\u76EE\u5F55\u662F ${args.workDir}\uFF0C\u8FD9\u4E2A\u76EE\u5F55\u5BF9\u4F60\u53EF\u8BFB\u53EF\u5199\uFF0C\u6587\u4EF6\u7684\u8BFB\u53D6/\u521B\u5EFA/\u4FEE\u6539\u90FD\u5728\u8FD9\u91CC\u8FDB\u884C\u3002`;
41904
+ parts.push("");
41905
+ let line = `\u4F60\u7684\u6587\u4EF6\u5DE5\u4F5C\u76EE\u5F55\u662F ${args.workDir}\uFF0C\u8FD9\u4E2A\u76EE\u5F55\u5BF9\u4F60\u53EF\u8BFB\u53EF\u5199\uFF0C\u6587\u4EF6\u7684\u8BFB\u53D6/\u521B\u5EFA/\u4FEE\u6539\u90FD\u5728\u8FD9\u91CC\u8FDB\u884C\u3002`;
41866
41906
  if (args.mode === "guest") {
41867
- result += "persona \u76EE\u5F55\u5BF9\u4F60\u53EA\u8BFB\uFF0C\u4E0D\u8981\u5F80\u91CC\u5199\u3002";
41907
+ line += "persona \u76EE\u5F55\u5BF9\u4F60\u53EA\u8BFB\uFF0C\u4E0D\u8981\u5F80\u91CC\u5199\u3002";
41868
41908
  }
41909
+ parts.push(line);
41869
41910
  }
41870
- return result;
41911
+ parts.push("");
41912
+ if (args.mode === "owner") {
41913
+ parts.push("\u81EA\u6211\u4ECB\u7ECD\u65F6\u4F7F\u7528\u7B2C\u4E00/\u7B2C\u4E8C\u4EBA\u79F0\uFF0C\u4F8B\u5982\u300C\u6211\u662F\u60A8\u7684 xxx \u52A9\u624B\u300D\u3002");
41914
+ } else {
41915
+ parts.push(
41916
+ `\u81EA\u6211\u4ECB\u7ECD\u65F6\u7B2C\u4E09\u4EBA\u79F0\u6307\u4EE3 owner\u3001\u7B2C\u4E8C\u4EBA\u79F0\u79F0\u547C\u5BF9\u65B9\uFF0C\u4F8B\u5982\u300C${args.guestLabel}\uFF0C\u6211\u662F ${args.ownerLabel} \u7684 xxx \u52A9\u624B\uFF0C\u4F60\u53EF\u4EE5\u901A\u8FC7\u6211\u770B\u5230\u4ED6\u7684 xxx\u300D\u3002\u4E0D\u8981\u628A\u5BF9\u65B9\u5F53\u6210 owner\uFF0C\u4E0D\u8981\u66FF owner \u505A\u51FA\u627F\u8BFA\u3002`
41917
+ );
41918
+ }
41919
+ return parts.join("\n");
41871
41920
  }
41872
41921
 
41873
41922
  // src/persona/sharing-prompt.ts
@@ -42065,13 +42114,19 @@ function buildSpawnContext(state, deps) {
42065
42114
  promptArgs = {
42066
42115
  mode: "guest",
42067
42116
  ownerLabel: deps.ownerDisplayName,
42117
+ ownerDeviceId: deps.ownerDeviceId,
42118
+ ownerFeishuUnionId: deps.ownerFeishuUnionId,
42068
42119
  guestLabel: meta.callerDisplayName,
42120
+ guestDeviceId: meta.callerDeviceId,
42121
+ guestFeishuUnionId: meta.callerFeishuUnionId,
42069
42122
  workDir: meta.userWorkDir
42070
42123
  };
42071
42124
  } else {
42072
42125
  promptArgs = {
42073
42126
  mode: "owner",
42074
42127
  ownerLabel: meta.callerDisplayName ?? deps.ownerDisplayName,
42128
+ ownerDeviceId: meta.callerDeviceId ?? deps.ownerDeviceId,
42129
+ ownerFeishuUnionId: meta.callerFeishuUnionId ?? deps.ownerFeishuUnionId,
42075
42130
  workDir: meta.userWorkDir
42076
42131
  };
42077
42132
  }
@@ -42856,6 +42911,8 @@ var SessionRunner = class {
42856
42911
  resolveContextWindow: this.hooks.resolveContextWindow,
42857
42912
  genUuid: this.hooks.genUuid ?? v4_default,
42858
42913
  ownerDisplayName: this.hooks.ownerDisplayName,
42914
+ ownerDeviceId: this.hooks.ownerDeviceId,
42915
+ ownerFeishuUnionId: this.hooks.ownerFeishuUnionId,
42859
42916
  personaRoot: this.hooks.personaRoot,
42860
42917
  // 单栏 refactor (spec 2026-06-02 §5.1): cc 子进程 env 注入 CLAWD_DAEMON_URL,让 assistant
42861
42918
  // curl daemon HTTP RPC adapter (/api/rpc/<method>) 触发管理操作。null = HTTP adapter 未启。
@@ -43634,12 +43691,14 @@ var SessionManager = class {
43634
43691
  const adapter = this.deps.getAdapter(file.tool ?? "claude");
43635
43692
  const store = this.storeFor(scope);
43636
43693
  const callerDisplayName = file.creatorDisplayName ?? (scope.kind === "persona" ? scope.mode === "owner" ? this.deps.ownerDisplayName : this.deps.contactStore?.get(scope.capId)?.displayName : void 0);
43694
+ const callerFeishuUnionId = file.creatorFeishuUnionId ?? (scope.kind === "persona" && scope.mode === "owner" ? this.deps.ownerFeishuUnionId : void 0);
43637
43695
  const subSessionMeta = metaFromScope(
43638
43696
  scope,
43639
43697
  this.deps.personaRoot ?? "",
43640
43698
  this.deps.usersRoot ?? "",
43641
43699
  this.deps.ownerPrincipalId,
43642
- callerDisplayName
43700
+ callerDisplayName,
43701
+ callerFeishuUnionId
43643
43702
  );
43644
43703
  if (subSessionMeta?.userWorkDir) {
43645
43704
  import_node_fs9.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
@@ -43686,6 +43745,11 @@ var SessionManager = class {
43686
43745
  // personaStore 不再透给 runner hooks(in-place mention 注入路径已删,runner 不用);
43687
43746
  // manager 自身的 sandbox 派生仍直接读 this.deps.personaStore。
43688
43747
  ownerDisplayName: this.deps.ownerDisplayName,
43748
+ // T-31 persona prompt injection:owner 设备 id(= ownerPrincipalId)+ 飞书 union_id
43749
+ // 供 reducer 组 promptArgs 时作为「本 persona 的 owner」身份卡数据源(guest session 用)
43750
+ // 或「当前连接方」身份卡的兜底源(owner session 老路径未 stamp caller 时)。
43751
+ ownerDeviceId: this.deps.ownerPrincipalId,
43752
+ ownerFeishuUnionId: this.deps.ownerFeishuUnionId,
43689
43753
  // Phase 2 capability platform (plan §3): 透传 personaRoot, buildSpawnArgs 据
43690
43754
  // cwd 是否在 personaRoot 下自动决定是否注入 --settings sandbox-settings.json.
43691
43755
  personaRoot: this.deps.personaRoot,
@@ -43801,7 +43865,7 @@ var SessionManager = class {
43801
43865
  }
43802
43866
  }
43803
43867
  // ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
43804
- create(args, creatorPrincipalId, creatorDisplayName) {
43868
+ create(args, creatorPrincipalId, creatorDisplayName, creatorFeishuUnionId) {
43805
43869
  let cwd;
43806
43870
  if (args.ownerPersonaId) {
43807
43871
  cwd = derivePersonaSpawnCwd(
@@ -43846,6 +43910,7 @@ var SessionManager = class {
43846
43910
  ephemeral: args.ephemeral,
43847
43911
  creatorPrincipalId,
43848
43912
  creatorDisplayName,
43913
+ ...creatorFeishuUnionId ? { creatorFeishuUnionId } : {},
43849
43914
  createdAt: iso,
43850
43915
  updatedAt: iso
43851
43916
  };
@@ -44616,7 +44681,9 @@ var SessionManager = class {
44616
44681
  // creatorDisplayName = A 的 displayName,供 guest meta callerDisplayName(reducer 要求)。
44617
44682
  ...args.guestPrincipalId ? {
44618
44683
  creatorPrincipalId: args.guestPrincipalId,
44619
- ...args.guestDisplayName ? { creatorDisplayName: args.guestDisplayName } : {}
44684
+ ...args.guestDisplayName ? { creatorDisplayName: args.guestDisplayName } : {},
44685
+ // T-31: A 的飞书 union_id stamp 到 B 的 SessionFile;guest meta 由 newRunner 派生
44686
+ ...args.guestFeishuUnionId ? { creatorFeishuUnionId: args.guestFeishuUnionId } : {}
44620
44687
  } : {},
44621
44688
  // T-20:dispatch model override 落盘(reducer spawn 路径读 SessionFile.model 生成 --model flag)
44622
44689
  ...args.model ? { model: args.model } : {},
@@ -48890,6 +48957,8 @@ function buildPersonaDispatchHandlers(deps) {
48890
48957
  prompt: args.prompt,
48891
48958
  guestPrincipalId: ctx.principal.id,
48892
48959
  guestDisplayName: ctx.principal.displayName,
48960
+ // T-31: 把 A 的飞书 union_id 透传给 B(connectGuestContext 已把它挂在 principal.feishuUnionId)
48961
+ ...ctx.principal.feishuUnionId ? { guestFeishuUnionId: ctx.principal.feishuUnionId } : {},
48893
48962
  ...args.model ? { model: args.model } : {}
48894
48963
  }).then(() => logger?.info("dispatch.spawnB.ok", { dispatchId: dispatchId2 })).catch((err) => {
48895
48964
  const reason = err instanceof Error ? err.message : String(err);
@@ -50662,7 +50731,7 @@ function ownerContext(ownerPrincipalId, displayName, feishuUnionId) {
50662
50731
  }
50663
50732
  function connectGuestContext(subDevice, subOwner, provider, displayName) {
50664
50733
  return {
50665
- principal: { id: subDevice, kind: "guest", displayName },
50734
+ principal: { id: subDevice, kind: "guest", displayName, feishuUnionId: subOwner },
50666
50735
  grants: PERSONAL_CAP_GRANTS.map((g2) => ({
50667
50736
  resource: { ...g2.resource },
50668
50737
  actions: [...g2.actions]
@@ -54920,10 +54989,12 @@ function buildSessionHandlers(deps) {
54920
54989
  ensurePersonaAccess(ctx, args.ownerPersonaId, "send");
54921
54990
  const creatorPrincipalId = ctx?.principal.id ?? ownerPrincipalId;
54922
54991
  const creatorDisplayName = ctx?.principal.displayName ?? "Owner";
54992
+ const creatorFeishuUnionId = ctx?.principal.feishuUnionId;
54923
54993
  const { response, broadcast } = manager.create(
54924
54994
  { ...args, tool },
54925
54995
  creatorPrincipalId,
54926
- creatorDisplayName
54996
+ creatorDisplayName,
54997
+ creatorFeishuUnionId
54927
54998
  );
54928
54999
  return { response: { type: "session:info", ...response }, broadcast };
54929
55000
  };
@@ -60227,6 +60298,8 @@ async function startDaemon(config) {
60227
60298
  // B 角色(跨设备):非空 → guest scope + creatorPrincipalId/creatorDisplayName = A。
60228
60299
  guestPrincipalId: args.guestPrincipalId,
60229
60300
  guestDisplayName: args.guestDisplayName,
60301
+ // T-31: 把 A 的飞书 union_id stamp 到 B SessionFile,供 cc prompt 身份卡 union_id 行
60302
+ guestFeishuUnionId: args.guestFeishuUnionId,
60230
60303
  // T-20: 可选 model override 透到 SessionFile.model
60231
60304
  ...args.model ? { model: args.model } : {}
60232
60305
  });
@@ -39876,6 +39876,14 @@ var SessionFileSchema = external_exports.object({
39876
39876
  * 或 deps.ownerDisplayName(owner)。
39877
39877
  */
39878
39878
  creatorDisplayName: external_exports.string().min(1).optional(),
39879
+ /**
39880
+ * 创建该 session 的连接者飞书 union_id(一次性 stamp,T-31 persona prompt injection)。
39881
+ * session:create / dispatch spawnB handler 从 ctx.principal.feishuUnionId(guest 场景来自
39882
+ * connect token subOwner)或 deps.ownerFeishuUnionId(owner 场景)传入;newRunner 时读这个
39883
+ * 字段派生 SubSessionMeta.callerFeishuUnionId 注入 cc system prompt「身份卡」的 union_id 行。
39884
+ * Optional:老 SessionFile / owner 未登飞书路径缺省,缺省时 prompt 不渲染该行(向后兼容)。
39885
+ */
39886
+ creatorFeishuUnionId: external_exports.string().min(1).optional(),
39879
39887
  /**
39880
39888
  * Mirror peer sessions (2026-05-26): mirror 标识。**我在朋友 daemon 上创建的 session**,
39881
39889
  * 远端是 source of truth,本机是持久化副本,方便 sidebar 跨设备聚合。