@clawos-dev/clawd 0.2.479 → 0.2.480

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.
@@ -21609,6 +21609,22 @@ var AuthGetIdentityResponseSchema = external_exports.object({
21609
21609
  var AuthLogoutResponseSchema = external_exports.object({
21610
21610
  type: external_exports.literal("auth:logout:ok")
21611
21611
  });
21612
+ var GatewayUrl = external_exports.string().nullable();
21613
+ var AuthApiKeyGetResponseSchema = external_exports.object({
21614
+ type: external_exports.literal("auth:apiKey:get:ok"),
21615
+ /** null = 还没发过。**发过就能一直看到** —— 中心存的是明文,设置页据此展示 */
21616
+ apiKey: external_exports.string().nullable(),
21617
+ /** ISO 时间;apiKey 为 null 时同为 null */
21618
+ createdAt: external_exports.string().nullable(),
21619
+ gatewayUrl: GatewayUrl
21620
+ });
21621
+ var AuthApiKeyRegenerateResponseSchema = external_exports.object({
21622
+ type: external_exports.literal("auth:apiKey:regenerate:ok"),
21623
+ /** 新发的那把。**旧的当场失效** —— 一人一把,按 union_id 覆盖 */
21624
+ apiKey: external_exports.string().min(1),
21625
+ createdAt: external_exports.string().min(1),
21626
+ gatewayUrl: GatewayUrl
21627
+ });
21612
21628
  var AuthLoginDoneEventSchema = external_exports.object({
21613
21629
  type: external_exports.literal("auth:login:done"),
21614
21630
  identity: FeishuIdentitySchema
@@ -24283,6 +24299,14 @@ var METHOD_DOCS = {
24283
24299
  summary: "\u767B\u51FA\u98DE\u4E66\u8EAB\u4EFD\uFF08\u6E05 owner-identity \u843D\u76D8\uFF09\u3002owner-only",
24284
24300
  args: NO_ARGS
24285
24301
  },
24302
+ "auth:apiKey:get": {
24303
+ summary: "\u8BFB\u56DE\u81EA\u5DF1\u90A3\u628A\u4E91 persona \u8C03\u7528 key\uFF08\u6CA1\u53D1\u8FC7 \u2192 apiKey:null\uFF09\u3002daemon \u62FF\u672C\u673A\u767B\u5F55\u51ED\u8BC1\u5411\u4E2D\u5FC3\u4EE3\u53D6\uFF0C\u51ED\u8BC1\u4E0D\u51FA ws\u3002owner-only",
24304
+ args: NO_ARGS
24305
+ },
24306
+ "auth:apiKey:regenerate": {
24307
+ summary: "\u6362\u4E00\u628A\u65B0\u7684\u4E91 persona \u8C03\u7528 key\uFF0C**\u65E7\u7684\u5F53\u573A\u5931\u6548**\uFF08\u4E00\u4EBA\u4E00\u628A\uFF0C\u4E2D\u5FC3\u6309 union_id \u8986\u76D6\uFF09\u3002owner-only",
24308
+ args: NO_ARGS
24309
+ },
24286
24310
  "device:list": {
24287
24311
  summary: "\u5217\u51FA\u516C\u5171\u8BBE\u5907\u76EE\u5F55\u91CC\u53EF\u8FDE\u63A5\u7684\u8BBE\u5907\uFF08daemon \u4EE3\u7406\u4E2D\u5FC3 server\uFF09\u3002owner-only",
24288
24312
  args: NO_ARGS
package/dist/cli.cjs CHANGED
@@ -6240,7 +6240,7 @@ var init_contact = __esm({
6240
6240
  });
6241
6241
 
6242
6242
  // ../protocol/src/feishu-auth.ts
6243
- var FEISHU_GATED_METHODS, LOGIN_EXPIRED_ERROR_MARKER, DeviceEntrySchema, DeviceListResponseSchema, DeviceConnectArgsSchema, DeviceConnectResponseSchema, FeishuIdentitySchema, AuthLoginStartResponseSchema, AuthGetIdentityResponseSchema, AuthLogoutResponseSchema, AuthLoginDoneEventSchema, AuthLoginFailedEventSchema;
6243
+ var FEISHU_GATED_METHODS, LOGIN_EXPIRED_ERROR_MARKER, DeviceEntrySchema, DeviceListResponseSchema, DeviceConnectArgsSchema, DeviceConnectResponseSchema, FeishuIdentitySchema, AuthLoginStartResponseSchema, AuthGetIdentityResponseSchema, AuthLogoutResponseSchema, GatewayUrl, AuthApiKeyGetResponseSchema, AuthApiKeyRegenerateResponseSchema, AuthLoginDoneEventSchema, AuthLoginFailedEventSchema;
6244
6244
  var init_feishu_auth = __esm({
6245
6245
  "../protocol/src/feishu-auth.ts"() {
6246
6246
  "use strict";
@@ -6337,6 +6337,22 @@ var init_feishu_auth = __esm({
6337
6337
  AuthLogoutResponseSchema = external_exports.object({
6338
6338
  type: external_exports.literal("auth:logout:ok")
6339
6339
  });
6340
+ GatewayUrl = external_exports.string().nullable();
6341
+ AuthApiKeyGetResponseSchema = external_exports.object({
6342
+ type: external_exports.literal("auth:apiKey:get:ok"),
6343
+ /** null = 还没发过。**发过就能一直看到** —— 中心存的是明文,设置页据此展示 */
6344
+ apiKey: external_exports.string().nullable(),
6345
+ /** ISO 时间;apiKey 为 null 时同为 null */
6346
+ createdAt: external_exports.string().nullable(),
6347
+ gatewayUrl: GatewayUrl
6348
+ });
6349
+ AuthApiKeyRegenerateResponseSchema = external_exports.object({
6350
+ type: external_exports.literal("auth:apiKey:regenerate:ok"),
6351
+ /** 新发的那把。**旧的当场失效** —— 一人一把,按 union_id 覆盖 */
6352
+ apiKey: external_exports.string().min(1),
6353
+ createdAt: external_exports.string().min(1),
6354
+ gatewayUrl: GatewayUrl
6355
+ });
6340
6356
  AuthLoginDoneEventSchema = external_exports.object({
6341
6357
  type: external_exports.literal("auth:login:done"),
6342
6358
  identity: FeishuIdentitySchema
@@ -9235,6 +9251,14 @@ var init_methods = __esm({
9235
9251
  summary: "\u767B\u51FA\u98DE\u4E66\u8EAB\u4EFD\uFF08\u6E05 owner-identity \u843D\u76D8\uFF09\u3002owner-only",
9236
9252
  args: NO_ARGS
9237
9253
  },
9254
+ "auth:apiKey:get": {
9255
+ summary: "\u8BFB\u56DE\u81EA\u5DF1\u90A3\u628A\u4E91 persona \u8C03\u7528 key\uFF08\u6CA1\u53D1\u8FC7 \u2192 apiKey:null\uFF09\u3002daemon \u62FF\u672C\u673A\u767B\u5F55\u51ED\u8BC1\u5411\u4E2D\u5FC3\u4EE3\u53D6\uFF0C\u51ED\u8BC1\u4E0D\u51FA ws\u3002owner-only",
9256
+ args: NO_ARGS
9257
+ },
9258
+ "auth:apiKey:regenerate": {
9259
+ summary: "\u6362\u4E00\u628A\u65B0\u7684\u4E91 persona \u8C03\u7528 key\uFF0C**\u65E7\u7684\u5F53\u573A\u5931\u6548**\uFF08\u4E00\u4EBA\u4E00\u628A\uFF0C\u4E2D\u5FC3\u6309 union_id \u8986\u76D6\uFF09\u3002owner-only",
9260
+ args: NO_ARGS
9261
+ },
9238
9262
  "device:list": {
9239
9263
  summary: "\u5217\u51FA\u516C\u5171\u8BBE\u5907\u76EE\u5F55\u91CC\u53EF\u8FDE\u63A5\u7684\u8BBE\u5907\uFF08daemon \u4EE3\u7406\u4E2D\u5FC3 server\uFF09\u3002owner-only",
9240
9264
  args: NO_ARGS
@@ -54732,7 +54756,7 @@ var L = [
54732
54756
  "# \u6784\u5EFA\u5668 / \u6D41\u6C34\u7EBF\u811A\u672C / \u968F\u884C\u8D44\u4EA7\u5728 ottin4ttc/clawos \u4ED3\u5E93\u91CC\uFF0C\u8FD9\u91CC checkout \u4E00\u4EFD\u6765\u7528\u3002",
54733
54757
  "#",
54734
54758
  "# \u8981\u7684\u7EC4\u7EC7\u7EA7 Secrets\uFF1AALI_DOCKER_USERNAME / ALI_DOCKER_PASSWORD\uFF08\u63A8 ACR\uFF09\u3001CLAWOS_READ_TOKEN",
54735
- "#\uFF08\u8BFB clawos \u4ED3\u5E93\uFF09\u3001CLAWD_GATEWAY_ADMIN_KEY / CLAWD_GATEWAY_API_KEY\uFF1B\u7EC4\u7EC7\u7EA7 Variable\uFF1ACLAWD_GATEWAY_URL\u3002",
54759
+ "#\uFF08\u8BFB clawos \u4ED3\u5E93\uFF09\u3001CLAWD_GATEWAY_ADMIN_KEY\uFF1B\u7EC4\u7EC7\u7EA7 Variable\uFF1ACLAWD_GATEWAY_URL\u3002",
54736
54760
  "# \u4ED3\u5E93\u7EA7\u540C\u540D\u914D\u7F6E\u4F1A\u76D6\u8FC7\u7EC4\u7EC7\u7EA7\u2014\u2014\u67D0\u4E2A persona \u8981\u6307\u5230\u53E6\u4E00\u53F0 gateway\uFF0C\u5728\u81EA\u5DF1\u4ED3\u5E93\u91CC\u914D\u5373\u53EF\u3002",
54737
54761
  "",
54738
54762
  "on:",
@@ -54878,7 +54902,6 @@ var L = [
54878
54902
  " env:",
54879
54903
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",
54880
54904
  " CLAWD_GATEWAY_ADMIN_KEY: ${{ secrets.CLAWD_GATEWAY_ADMIN_KEY }}",
54881
- " CLAWD_GATEWAY_API_KEY: ${{ secrets.CLAWD_GATEWAY_API_KEY }}",
54882
54905
  " CLAWD_SECRETS_JSON: ${{ toJSON(secrets) }}",
54883
54906
  " CLAWD_ENV_NAMES: ${{ needs.build.outputs.env_names }}",
54884
54907
  " run: |",
@@ -61556,6 +61579,40 @@ async function centralPrincipalStatus(opts) {
61556
61579
  }
61557
61580
  return { active: body.active };
61558
61581
  }
61582
+ async function centralGetApiKey(opts) {
61583
+ const body = await centralRequest(
61584
+ opts,
61585
+ `/api/persona-cloud/api-key?provider=${encodeURIComponent(opts.provider)}`,
61586
+ { method: "GET", bearer: opts.ttcJwt }
61587
+ );
61588
+ if (body.apiKey !== null && typeof body.apiKey !== "string") {
61589
+ throw new CentralClientError("BAD_RESPONSE", "api-key: apiKey must be string or null");
61590
+ }
61591
+ return {
61592
+ apiKey: body.apiKey,
61593
+ createdAt: typeof body.createdAt === "string" ? body.createdAt : null,
61594
+ // 中心没配就是 null —— 不当成错误,key 本身照样有效
61595
+ gatewayUrl: typeof body.gatewayUrl === "string" ? body.gatewayUrl : null
61596
+ };
61597
+ }
61598
+ async function centralIssueApiKey(opts) {
61599
+ const body = await centralRequest(opts, "/api/persona-cloud/api-key", {
61600
+ method: "POST",
61601
+ bearer: opts.ttcJwt,
61602
+ body: { provider: opts.provider }
61603
+ });
61604
+ if (typeof body.apiKey !== "string" || body.apiKey.length === 0) {
61605
+ throw new CentralClientError("BAD_RESPONSE", "api-key: missing apiKey");
61606
+ }
61607
+ if (typeof body.createdAt !== "string" || body.createdAt.length === 0) {
61608
+ throw new CentralClientError("BAD_RESPONSE", "api-key: missing createdAt");
61609
+ }
61610
+ return {
61611
+ apiKey: body.apiKey,
61612
+ createdAt: body.createdAt,
61613
+ gatewayUrl: typeof body.gatewayUrl === "string" ? body.gatewayUrl : null
61614
+ };
61615
+ }
61559
61616
  async function centralListDevices(opts) {
61560
61617
  const body = await centralRequest(
61561
61618
  opts,
@@ -63966,6 +64023,7 @@ function buildWhoamiHandler(deps) {
63966
64023
  }
63967
64024
 
63968
64025
  // src/handlers/feishu-auth.ts
64026
+ init_protocol();
63969
64027
  function buildFeishuAuthHandlers(deps) {
63970
64028
  const loginStart = async () => {
63971
64029
  const { authUrl, state } = deps.loginFlow.start();
@@ -63994,10 +64052,34 @@ function buildFeishuAuthHandlers(deps) {
63994
64052
  response: { type: "auth:logout:ok" }
63995
64053
  };
63996
64054
  };
64055
+ function requireLogin() {
64056
+ const record3 = deps.ownerIdentityStore.read();
64057
+ if (!record3) {
64058
+ throw new ClawdError(
64059
+ ERROR_CODES.FEISHU_LOGIN_REQUIRED,
64060
+ "\u8FD8\u6CA1\u767B\u5F55\u98DE\u4E66\uFF0C\u62FF\u4E0D\u5230\u4E91 persona \u7684\u8C03\u7528 key"
64061
+ );
64062
+ }
64063
+ return { ttcJwt: record3.ttcToken, provider: record3.identity.provider };
64064
+ }
64065
+ const apiKeyGet = async () => {
64066
+ const { apiKey, createdAt, gatewayUrl } = await deps.apiKeyClient.get(requireLogin());
64067
+ return {
64068
+ response: { type: "auth:apiKey:get:ok", apiKey, createdAt, gatewayUrl }
64069
+ };
64070
+ };
64071
+ const apiKeyRegenerate = async () => {
64072
+ const { apiKey, createdAt, gatewayUrl } = await deps.apiKeyClient.issue(requireLogin());
64073
+ return {
64074
+ response: { type: "auth:apiKey:regenerate:ok", apiKey, createdAt, gatewayUrl }
64075
+ };
64076
+ };
63997
64077
  return {
63998
64078
  "auth:login:start": loginStart,
63999
64079
  "auth:getIdentity": getIdentity,
64000
- "auth:logout": logout
64080
+ "auth:logout": logout,
64081
+ "auth:apiKey:get": apiKeyGet,
64082
+ "auth:apiKey:regenerate": apiKeyRegenerate
64001
64083
  };
64002
64084
  }
64003
64085
 
@@ -64238,6 +64320,9 @@ var METHOD_GRANT_MAP = {
64238
64320
  "auth:login:start": ADMIN_ANY,
64239
64321
  "auth:getIdentity": ADMIN_ANY,
64240
64322
  "auth:logout": ADMIN_ANY,
64323
+ // 云 persona 调用 key:本机主人自己的东西,guest 一律够不着
64324
+ "auth:apiKey:get": ADMIN_ANY,
64325
+ "auth:apiKey:regenerate": ADMIN_ANY,
64241
64326
  // ---- device:* 设备目录 + 连接(决策 #15,owner-only) ----
64242
64327
  // 设备目录 / 连接都是 owner 本机操作(用 owner 的 ttcJwt 找中心 server),guest 不可调
64243
64328
  "device:list": ADMIN_ANY,
@@ -64301,7 +64386,7 @@ function computeMethodAccess(args) {
64301
64386
  }
64302
64387
 
64303
64388
  // src/version.ts
64304
- var version = "0.2.479".length > 0 ? "0.2.479" : "dev";
64389
+ var version = "0.2.480".length > 0 ? "0.2.480" : "dev";
64305
64390
 
64306
64391
  // src/cli-probe/probe.ts
64307
64392
  var fs70 = __toESM(require("fs"), 1);
@@ -69302,6 +69387,12 @@ async function startDaemon(config) {
69302
69387
  ownerId = "";
69303
69388
  ownerProvider = "";
69304
69389
  ownerDisplayName = loadOwnerDisplayName(config.dataDir);
69390
+ },
69391
+ // 云 persona 调用 key(design 2026-09-08):daemon 拿本机登录凭证向中心代取。
69392
+ // 凭证不出 ws —— UI 只拿到 key 本身,跟 exchange / listDevices 同一条纪律。
69393
+ apiKeyClient: {
69394
+ get: (args) => centralGetApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args }),
69395
+ issue: (args) => centralIssueApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
69305
69396
  }
69306
69397
  },
69307
69398
  // 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
@@ -21602,6 +21602,22 @@ var AuthGetIdentityResponseSchema = external_exports.object({
21602
21602
  var AuthLogoutResponseSchema = external_exports.object({
21603
21603
  type: external_exports.literal("auth:logout:ok")
21604
21604
  });
21605
+ var GatewayUrl = external_exports.string().nullable();
21606
+ var AuthApiKeyGetResponseSchema = external_exports.object({
21607
+ type: external_exports.literal("auth:apiKey:get:ok"),
21608
+ /** null = 还没发过。**发过就能一直看到** —— 中心存的是明文,设置页据此展示 */
21609
+ apiKey: external_exports.string().nullable(),
21610
+ /** ISO 时间;apiKey 为 null 时同为 null */
21611
+ createdAt: external_exports.string().nullable(),
21612
+ gatewayUrl: GatewayUrl
21613
+ });
21614
+ var AuthApiKeyRegenerateResponseSchema = external_exports.object({
21615
+ type: external_exports.literal("auth:apiKey:regenerate:ok"),
21616
+ /** 新发的那把。**旧的当场失效** —— 一人一把,按 union_id 覆盖 */
21617
+ apiKey: external_exports.string().min(1),
21618
+ createdAt: external_exports.string().min(1),
21619
+ gatewayUrl: GatewayUrl
21620
+ });
21605
21621
  var AuthLoginDoneEventSchema = external_exports.object({
21606
21622
  type: external_exports.literal("auth:login:done"),
21607
21623
  identity: FeishuIdentitySchema
@@ -24275,6 +24291,14 @@ var METHOD_DOCS = {
24275
24291
  summary: "\u767B\u51FA\u98DE\u4E66\u8EAB\u4EFD\uFF08\u6E05 owner-identity \u843D\u76D8\uFF09\u3002owner-only",
24276
24292
  args: NO_ARGS
24277
24293
  },
24294
+ "auth:apiKey:get": {
24295
+ summary: "\u8BFB\u56DE\u81EA\u5DF1\u90A3\u628A\u4E91 persona \u8C03\u7528 key\uFF08\u6CA1\u53D1\u8FC7 \u2192 apiKey:null\uFF09\u3002daemon \u62FF\u672C\u673A\u767B\u5F55\u51ED\u8BC1\u5411\u4E2D\u5FC3\u4EE3\u53D6\uFF0C\u51ED\u8BC1\u4E0D\u51FA ws\u3002owner-only",
24296
+ args: NO_ARGS
24297
+ },
24298
+ "auth:apiKey:regenerate": {
24299
+ summary: "\u6362\u4E00\u628A\u65B0\u7684\u4E91 persona \u8C03\u7528 key\uFF0C**\u65E7\u7684\u5F53\u573A\u5931\u6548**\uFF08\u4E00\u4EBA\u4E00\u628A\uFF0C\u4E2D\u5FC3\u6309 union_id \u8986\u76D6\uFF09\u3002owner-only",
24300
+ args: NO_ARGS
24301
+ },
24278
24302
  "device:list": {
24279
24303
  summary: "\u5217\u51FA\u516C\u5171\u8BBE\u5907\u76EE\u5F55\u91CC\u53EF\u8FDE\u63A5\u7684\u8BBE\u5907\uFF08daemon \u4EE3\u7406\u4E2D\u5FC3 server\uFF09\u3002owner-only",
24280
24304
  args: NO_ARGS