@clawos-dev/clawd 0.2.71-beta.127.52e9b3f → 0.2.71-beta.129.3d783e6

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 +92 -3
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -133,6 +133,11 @@ var init_methods = __esm({
133
133
  "remote-persona:add",
134
134
  "remote-persona:list",
135
135
  "remote-persona:remove",
136
+ // ---- whoami (v2 capability platform) ----
137
+ // 任何 authed connection 都能调;返回 owner 显示名 + 当前 capability wire 形态 +
138
+ // grants 对应的 persona 元数据 (id + displayName)。UI 端 AddRemotePersonaDialog
139
+ // 的 preview 一次性临时 client 用它判定身份和可用 persona。
140
+ "whoami",
136
141
  "info",
137
142
  "ping"
138
143
  ];
@@ -5086,7 +5091,7 @@ function stripSecretHash(cap) {
5086
5091
  const { secretHash: _hash, ...wire } = cap;
5087
5092
  return wire;
5088
5093
  }
5089
- var ResourceSchema, ActionSchema, GrantSchema, CapabilitySchema, CapabilityWireSchema, CapabilityErrorCodeSchema;
5094
+ var ResourceSchema, ActionSchema, GrantSchema, CapabilitySchema, CapabilityWireSchema, CapabilityErrorCodeSchema, WhoamiResponseSchema;
5090
5095
  var init_capability = __esm({
5091
5096
  "../protocol/src/capability.ts"() {
5092
5097
  "use strict";
@@ -5121,6 +5126,21 @@ var init_capability = __esm({
5121
5126
  "TOKEN_EXPIRED",
5122
5127
  "TOKEN_EXHAUSTED"
5123
5128
  ]);
5129
+ WhoamiResponseSchema = external_exports.object({
5130
+ type: external_exports.literal("whoami:ok"),
5131
+ owner: external_exports.object({
5132
+ id: external_exports.string(),
5133
+ kind: external_exports.enum(["owner", "guest"]),
5134
+ displayName: external_exports.string()
5135
+ }).strict(),
5136
+ capability: CapabilityWireSchema,
5137
+ grantedPersonas: external_exports.array(
5138
+ external_exports.object({
5139
+ id: external_exports.string().min(1),
5140
+ displayName: external_exports.string()
5141
+ }).strict()
5142
+ )
5143
+ }).strict();
5124
5144
  }
5125
5145
  });
5126
5146
 
@@ -5176,6 +5196,10 @@ var init_remote_persona = __esm({
5176
5196
  alias: external_exports.string().min(1),
5177
5197
  remoteUrl: external_exports.string().min(1),
5178
5198
  capabilityToken: external_exports.string().min(1),
5199
+ // v2 Phase 7: 远端 daemon 给我颁发的 capability id。preview 时 whoami 返回的
5200
+ // capability.id 直接存进来。旧 v1 持久化文件没此字段 → schema parse fail →
5201
+ // RemotePersonaStore.list 静默跳过 (alpha 阶段可接受, 老板重新 add 即可)。
5202
+ myCapabilityId: external_exports.string().min(1),
5179
5203
  remotePersonaId: external_exports.string().min(1),
5180
5204
  remoteDisplayName: external_exports.string(),
5181
5205
  ownerDisplayName: external_exports.string().optional(),
@@ -5187,6 +5211,8 @@ var init_remote_persona = __esm({
5187
5211
  alias: external_exports.string().min(1),
5188
5212
  remoteUrl: external_exports.string().min(1),
5189
5213
  capabilityToken: external_exports.string().min(1),
5214
+ // v2 Phase 7: UI 调 preview 后从 whoami response 取 capability.id 传入
5215
+ myCapabilityId: external_exports.string().min(1),
5190
5216
  remotePersonaId: external_exports.string().min(1),
5191
5217
  remoteDisplayName: external_exports.string(),
5192
5218
  ownerDisplayName: external_exports.string().optional()
@@ -26156,6 +26182,11 @@ var CapabilityManager = class {
26156
26182
  list() {
26157
26183
  return this.registry.list();
26158
26184
  }
26185
+ // whoami handler 用:根据 capabilityId 反查 caller 的 capability 实体。
26186
+ // 返回 Capability 持久化形态;handler 调 stripSecretHash 后再上 wire。
26187
+ findById(id) {
26188
+ return this.registry.findById(id);
26189
+ }
26159
26190
  issue(args) {
26160
26191
  if (!args.displayName.trim()) {
26161
26192
  throw new Error("CapabilityManager.issue: displayName must be non-empty");
@@ -28502,12 +28533,13 @@ function buildRemotePersonaHandlers(deps) {
28502
28533
  response: { type: "remote-persona:add:ok", remotePersona: stripRemotePersonaSecret(rp) }
28503
28534
  };
28504
28535
  };
28505
- const list = async () => {
28536
+ const list = async (_frame, _client, ctx) => {
28506
28537
  const all = store.list();
28538
+ const projected = ctx?.principal.kind === "owner" ? all : all.map(stripRemotePersonaSecret);
28507
28539
  return {
28508
28540
  response: {
28509
28541
  type: "remote-persona:list",
28510
- remotePersonas: all.map(stripRemotePersonaSecret)
28542
+ remotePersonas: projected
28511
28543
  }
28512
28544
  };
28513
28545
  };
@@ -28526,6 +28558,51 @@ function buildRemotePersonaHandlers(deps) {
28526
28558
  };
28527
28559
  }
28528
28560
 
28561
+ // src/handlers/whoami.ts
28562
+ init_protocol();
28563
+ function buildWhoamiHandler(deps) {
28564
+ return async (_frame, _client, ctx) => {
28565
+ if (!ctx) {
28566
+ throw new ClawdError(ERROR_CODES.INTERNAL, "whoami: missing ConnectionContext");
28567
+ }
28568
+ const owner = { ...OWNER_PRINCIPAL, displayName: deps.ownerDisplayName };
28569
+ let capability;
28570
+ if (ctx.principal.kind === "owner") {
28571
+ capability = {
28572
+ id: "owner",
28573
+ displayName: deps.ownerDisplayName,
28574
+ grants: ctx.grants,
28575
+ issuedAt: 0,
28576
+ usedCount: 0
28577
+ };
28578
+ } else {
28579
+ if (!ctx.capabilityId) {
28580
+ throw new ClawdError(ERROR_CODES.UNAUTHORIZED, "whoami: guest ctx without capabilityId");
28581
+ }
28582
+ const cap = deps.capabilityManager.findById(ctx.capabilityId);
28583
+ if (!cap) {
28584
+ throw new ClawdError(ERROR_CODES.UNAUTHORIZED, `whoami: capability not found: ${ctx.capabilityId}`);
28585
+ }
28586
+ capability = stripSecretHash(cap);
28587
+ }
28588
+ const grantedPersonas = [];
28589
+ for (const g2 of capability.grants) {
28590
+ if (g2.resource.type !== "persona") continue;
28591
+ const file = deps.personaStore.read(g2.resource.id);
28592
+ if (!file) continue;
28593
+ grantedPersonas.push({ id: file.personaId, displayName: file.label });
28594
+ }
28595
+ return {
28596
+ response: {
28597
+ type: "whoami:ok",
28598
+ owner,
28599
+ capability,
28600
+ grantedPersonas
28601
+ }
28602
+ };
28603
+ };
28604
+ }
28605
+
28529
28606
  // src/handlers/meta.ts
28530
28607
  var import_node_os13 = __toESM(require("os"), 1);
28531
28608
  init_protocol();
@@ -28786,6 +28863,11 @@ function buildMethodHandlers(deps) {
28786
28863
  capabilityRegistry: deps.capabilityRegistry
28787
28864
  }),
28788
28865
  ...buildRemotePersonaHandlers({ store: deps.remotePersonaStore }),
28866
+ whoami: buildWhoamiHandler({
28867
+ ownerDisplayName: deps.ownerDisplayName,
28868
+ personaStore: deps.personaStore,
28869
+ capabilityManager: deps.capabilityManager
28870
+ }),
28789
28871
  ...deps.attachment ? buildAttachmentHandlers(deps.attachment) : {}
28790
28872
  };
28791
28873
  }
@@ -28800,6 +28882,10 @@ var METHOD_GRANT_MAP = {
28800
28882
  // ---- public(meta-only,guest 也能调) ----
28801
28883
  "info": { kind: "public" },
28802
28884
  "ping": { kind: "public" },
28885
+ // v2 Phase 6: whoami 是身份反查,任何 authed connection (owner / guest) 都能调;
28886
+ // handler 内部按 ctx.principal.kind 决定返回 "合成 owner self capability" 还是
28887
+ // "查 capabilityManager 拿 caller 的 guest capability"。
28888
+ "whoami": { kind: "public" },
28803
28889
  // ---- capability platform(admin-only,本 PR 新增) ----
28804
28890
  "capability:issue": ADMIN_ANY,
28805
28891
  "capability:list": ADMIN_ANY,
@@ -29149,6 +29235,9 @@ async function startDaemon(config) {
29149
29235
  // v2 Phase 5: capability:issue 返回的 shareUrl 用此 base URL 拼接。
29150
29236
  // tunnel 拉起后切到反代 wss://... 地址;否则本机 ws://host:port。
29151
29237
  getShareBaseUrl: () => currentTunnelUrl ?? `ws://${config.host}:${config.port}`,
29238
+ // v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
29239
+ ownerDisplayName,
29240
+ personaStore,
29152
29241
  // Phase 4 Task 4.2: inbox:postMessage 要查 capabilityRegistry 解析 peer Principal
29153
29242
  capabilityRegistry,
29154
29243
  // Phase 3 Task 3.4: inbox:list/markRead handler 依赖
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.71-beta.127.52e9b3f",
3
+ "version": "0.2.71-beta.129.3d783e6",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",