@clawos-dev/clawd 0.2.529 → 0.2.531

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.
@@ -21947,6 +21947,11 @@ var AuthApiKeyRegenerateResponseSchema = external_exports.object({
21947
21947
  createdAt: external_exports.string().min(1),
21948
21948
  gatewayUrl: GatewayUrl
21949
21949
  });
21950
+ var AuthApiKeyRevokeResponseSchema = external_exports.object({
21951
+ type: external_exports.literal("auth:apiKey:revoke:ok"),
21952
+ /** 之前有没有那把——没发过也算成功(幂等) */
21953
+ revoked: external_exports.boolean()
21954
+ });
21950
21955
  var AuthLoginDoneEventSchema = external_exports.object({
21951
21956
  type: external_exports.literal("auth:login:done"),
21952
21957
  identity: FeishuIdentitySchema
@@ -24494,6 +24499,10 @@ var METHOD_DOCS = {
24494
24499
  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",
24495
24500
  args: NO_ARGS
24496
24501
  },
24502
+ "auth:apiKey:revoke": {
24503
+ summary: "\u64A4\u9500\u81EA\u5DF1\u7684\u4E91 persona \u8C03\u7528 key\uFF1A\u4E2D\u5FC3\u5220\u6389\u90A3\u4E00\u884C\u3001**\u4E0D\u53D1\u65B0\u7684**\u3002gateway \u53EA\u5728\u5F00\u4F1A\u8BDD\u548C\u6BCF\u6B21\u4E0A\u884C\u65F6\u9A8C key\uFF0C\u6240\u4EE5\u5F00\u7740\u7684\u4E91\u4F1A\u8BDD\u4E0B\u4E00\u6761\u6D88\u606F\u624D\u53D1\u4E0D\u51FA\u53BB\u3001\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u4F1A\u8DD1\u5B8C\u3002\u6CA1\u53D1\u8FC7\u4E5F\u56DE ok\uFF08revoked:false\uFF09\u3002owner-only",
24504
+ args: NO_ARGS
24505
+ },
24497
24506
  "device:list": {
24498
24507
  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",
24499
24508
  args: NO_ARGS
package/dist/cli.cjs CHANGED
@@ -6431,7 +6431,7 @@ var init_contact = __esm({
6431
6431
  });
6432
6432
 
6433
6433
  // ../protocol/src/feishu-auth.ts
6434
- var FEISHU_GATED_METHODS, LOGIN_EXPIRED_ERROR_MARKER, DeviceEntrySchema, DeviceListResponseSchema, DeviceConnectArgsSchema, DeviceConnectResponseSchema, FeishuIdentitySchema, AuthLoginStartResponseSchema, AuthGetIdentityResponseSchema, AuthLogoutResponseSchema, GatewayUrl, AuthApiKeyGetResponseSchema, AuthApiKeyRegenerateResponseSchema, AuthLoginDoneEventSchema, AuthLoginFailedEventSchema;
6434
+ var FEISHU_GATED_METHODS, LOGIN_EXPIRED_ERROR_MARKER, DeviceEntrySchema, DeviceListResponseSchema, DeviceConnectArgsSchema, DeviceConnectResponseSchema, FeishuIdentitySchema, AuthLoginStartResponseSchema, AuthGetIdentityResponseSchema, AuthLogoutResponseSchema, GatewayUrl, AuthApiKeyGetResponseSchema, AuthApiKeyRegenerateResponseSchema, AuthApiKeyRevokeResponseSchema, AuthLoginDoneEventSchema, AuthLoginFailedEventSchema;
6435
6435
  var init_feishu_auth = __esm({
6436
6436
  "../protocol/src/feishu-auth.ts"() {
6437
6437
  "use strict";
@@ -6538,6 +6538,11 @@ var init_feishu_auth = __esm({
6538
6538
  createdAt: external_exports.string().min(1),
6539
6539
  gatewayUrl: GatewayUrl
6540
6540
  });
6541
+ AuthApiKeyRevokeResponseSchema = external_exports.object({
6542
+ type: external_exports.literal("auth:apiKey:revoke:ok"),
6543
+ /** 之前有没有那把——没发过也算成功(幂等) */
6544
+ revoked: external_exports.boolean()
6545
+ });
6541
6546
  AuthLoginDoneEventSchema = external_exports.object({
6542
6547
  type: external_exports.literal("auth:login:done"),
6543
6548
  identity: FeishuIdentitySchema
@@ -9311,6 +9316,10 @@ var init_methods = __esm({
9311
9316
  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",
9312
9317
  args: NO_ARGS
9313
9318
  },
9319
+ "auth:apiKey:revoke": {
9320
+ summary: "\u64A4\u9500\u81EA\u5DF1\u7684\u4E91 persona \u8C03\u7528 key\uFF1A\u4E2D\u5FC3\u5220\u6389\u90A3\u4E00\u884C\u3001**\u4E0D\u53D1\u65B0\u7684**\u3002gateway \u53EA\u5728\u5F00\u4F1A\u8BDD\u548C\u6BCF\u6B21\u4E0A\u884C\u65F6\u9A8C key\uFF0C\u6240\u4EE5\u5F00\u7740\u7684\u4E91\u4F1A\u8BDD\u4E0B\u4E00\u6761\u6D88\u606F\u624D\u53D1\u4E0D\u51FA\u53BB\u3001\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u4F1A\u8DD1\u5B8C\u3002\u6CA1\u53D1\u8FC7\u4E5F\u56DE ok\uFF08revoked:false\uFF09\u3002owner-only",
9321
+ args: NO_ARGS
9322
+ },
9314
9323
  "device:list": {
9315
9324
  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",
9316
9325
  args: NO_ARGS
@@ -62214,6 +62223,16 @@ async function centralIssueApiKey(opts) {
62214
62223
  gatewayUrl: typeof body.gatewayUrl === "string" ? body.gatewayUrl : null
62215
62224
  };
62216
62225
  }
62226
+ async function centralRevokeApiKey(opts) {
62227
+ const body = await centralRequest(opts, "/api/persona-cloud/api-key", {
62228
+ method: "DELETE",
62229
+ bearer: opts.loginPass
62230
+ });
62231
+ if (typeof body.revoked !== "boolean") {
62232
+ throw new CentralClientError("BAD_RESPONSE", "api-key: revoked must be boolean");
62233
+ }
62234
+ return { revoked: body.revoked };
62235
+ }
62217
62236
  async function centralListDevices(opts) {
62218
62237
  const body = await centralRequest(opts, "/api/clawd-identity/devices", {
62219
62238
  method: "GET",
@@ -62278,6 +62297,12 @@ var GATEWAY_ROUTES = {
62278
62297
  thread: (threadId) => `/threads/${encodeURIComponent(threadId)}`
62279
62298
  };
62280
62299
  var trimSlash = (u2) => u2.replace(/\/+$/, "");
62300
+ var CloudApiKeyRequiredError = class extends Error {
62301
+ constructor() {
62302
+ super("\u8FD8\u6CA1\u751F\u6210\u4E91 persona \u7684\u8C03\u7528 key\u3002\u5230\u300C\u8BBE\u7F6E \u2192 \u8D26\u53F7\u300D\u6216\u8FD9\u4E2A persona \u7684\u5361\u7247\u4E0A\u751F\u6210\u4E00\u628A\uFF0C\u518D\u5F00\u4F1A\u8BDD");
62303
+ this.name = "CloudApiKeyRequiredError";
62304
+ }
62305
+ };
62281
62306
  var CLOUD_PERSONA_ID_SUFFIX = "-cloud";
62282
62307
  function cloudPersonaToFile(p3) {
62283
62308
  const at3 = p3.registeredAt ?? 0;
@@ -62300,20 +62325,27 @@ var CloudGatewayClient = class {
62300
62325
  }
62301
62326
  deps;
62302
62327
  fetchImpl;
62303
- async credentials() {
62328
+ /**
62329
+ * gateway 在哪 + 这个人有没有 key。要登录、要中心配了地址;**不要求有 key**——
62330
+ * 登记表是全局的、/healthz 不看票,列表只需要地址。key 到开会话才要(见 credentials)。
62331
+ * 曾把两样绑在一起:没生成 key 的用户连列表都看不到,也就永远不知道要去设置页生成一把(2026-09-16 修)。
62332
+ */
62333
+ async locate() {
62304
62334
  const loginPass = this.deps.getLoginPass();
62305
62335
  if (!loginPass) throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "\u8FD8\u6CA1\u767B\u5F55\u98DE\u4E66\uFF0C\u4E91\u4E0A persona \u7528\u4E0D\u4E86");
62306
62336
  const get = this.deps.getApiKey ?? ((args) => centralGetApiKey({ api: this.deps.centralApi ?? "", fetchImpl: this.fetchImpl, ...args }));
62307
62337
  const { apiKey, gatewayUrl } = await get({ loginPass });
62308
- if (!apiKey) throw new Error("\u8FD8\u6CA1\u751F\u6210\u4E91 persona \u7684\u8C03\u7528 key\uFF0C\u53BB\u300C\u8BBE\u7F6E \u2192 \u4E91\u4E0A persona\u300D\u751F\u6210\u4E00\u628A");
62309
62338
  if (!gatewayUrl) throw new Error("\u4E2D\u5FC3\u6CA1\u914D\u4E91 gateway \u5730\u5740\uFF08gatewayUrl \u4E3A\u7A7A\uFF09");
62310
62339
  return { apiKey, gatewayUrl: trimSlash(gatewayUrl) };
62311
62340
  }
62341
+ async credentials() {
62342
+ const { apiKey, gatewayUrl } = await this.locate();
62343
+ if (!apiKey) throw new CloudApiKeyRequiredError();
62344
+ return { apiKey, gatewayUrl };
62345
+ }
62312
62346
  async listPersonas() {
62313
- const { apiKey, gatewayUrl } = await this.credentials();
62314
- const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz(), {
62315
- headers: { authorization: `Bearer ${apiKey}` }
62316
- });
62347
+ const { gatewayUrl } = await this.locate();
62348
+ const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
62317
62349
  if (!res.ok) throw new Error(`gateway /healthz \u56DE ${res.status}`);
62318
62350
  const body = await res.json();
62319
62351
  const rows = Array.isArray(body.deployments) ? body.deployments : [];
@@ -62428,7 +62460,9 @@ function openHttpLineStream(opts) {
62428
62460
  }
62429
62461
  if (!res.ok) {
62430
62462
  logger?.warn("cloud session send failed", { status: res.status });
62431
- fail(`\u4E0A\u884C\u53D1\u4E0D\u51FA\u53BB\uFF08gateway \u56DE ${res.status}\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86`);
62463
+ fail(
62464
+ res.status === 401 ? "\u8C03\u7528 key \u5DF2\u5931\u6548\uFF08\u64A4\u9500\u6216\u91CD\u65B0\u751F\u6210\u8FC7\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86\u3002\u5230\u300C\u8BBE\u7F6E \u2192 \u8D26\u53F7\u300D\u6216\u8FD9\u4E2A persona \u7684\u5361\u7247\u4E0A\u751F\u6210\u4E00\u628A\uFF0C\u518D\u5F00\u65B0\u4F1A\u8BDD" : `\u4E0A\u884C\u53D1\u4E0D\u51FA\u53BB\uFF08gateway \u56DE ${res.status}\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86`
62465
+ );
62432
62466
  }
62433
62467
  }).catch((e) => {
62434
62468
  if (closed) return;
@@ -62719,7 +62753,7 @@ function createCloudCodexSession(ctx, sink, deps) {
62719
62753
  stream.attach(channel);
62720
62754
  },
62721
62755
  (e) => {
62722
- sink.onError(`\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
62756
+ sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
62723
62757
  stream.close();
62724
62758
  }
62725
62759
  );
@@ -69969,12 +70003,19 @@ function buildFeishuAuthHandlers(deps) {
69969
70003
  response: { type: "auth:apiKey:regenerate:ok", apiKey, createdAt, gatewayUrl }
69970
70004
  };
69971
70005
  };
70006
+ const apiKeyRevoke = async () => {
70007
+ const { revoked } = await deps.apiKeyClient.revoke(requireLogin());
70008
+ return {
70009
+ response: { type: "auth:apiKey:revoke:ok", revoked }
70010
+ };
70011
+ };
69972
70012
  return {
69973
70013
  "auth:login:start": loginStart,
69974
70014
  "auth:getIdentity": getIdentity,
69975
70015
  "auth:logout": logout,
69976
70016
  "auth:apiKey:get": apiKeyGet,
69977
- "auth:apiKey:regenerate": apiKeyRegenerate
70017
+ "auth:apiKey:regenerate": apiKeyRegenerate,
70018
+ "auth:apiKey:revoke": apiKeyRevoke
69978
70019
  };
69979
70020
  }
69980
70021
 
@@ -70274,6 +70315,7 @@ var METHOD_GRANT_MAP = {
70274
70315
  // 云 persona 调用 key:本机主人自己的东西,guest 一律够不着
70275
70316
  "auth:apiKey:get": ADMIN_ANY,
70276
70317
  "auth:apiKey:regenerate": ADMIN_ANY,
70318
+ "auth:apiKey:revoke": ADMIN_ANY,
70277
70319
  // ---- device:* 设备目录 + 连接(决策 #15,owner-only) ----
70278
70320
  // 设备目录 / 连接都是 owner 本机操作(用本机登录票找中心 server),guest 不可调
70279
70321
  "device:list": ADMIN_ANY,
@@ -70328,7 +70370,7 @@ function computeMethodAccess(args) {
70328
70370
  }
70329
70371
 
70330
70372
  // src/version.ts
70331
- var version = "0.2.529".length > 0 ? "0.2.529" : "dev";
70373
+ var version = "0.2.531".length > 0 ? "0.2.531" : "dev";
70332
70374
 
70333
70375
  // src/cli-probe/probe.ts
70334
70376
  var fs77 = __toESM(require("fs"), 1);
@@ -73964,7 +74006,8 @@ async function startDaemon(config) {
73964
74006
  // 凭证不出 ws —— UI 只拿到 key 本身,跟 exchange / listDevices 同一条纪律。
73965
74007
  apiKeyClient: {
73966
74008
  get: (args) => centralGetApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args }),
73967
- issue: (args) => centralIssueApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
74009
+ issue: (args) => centralIssueApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args }),
74010
+ revoke: (args) => centralRevokeApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
73968
74011
  }
73969
74012
  },
73970
74013
  // 云 persona 卡片上的连接器区(design 2026-09-11-mcp-connector §3.8):装了什么以 gateway 登记行为真源,
@@ -21762,6 +21762,11 @@ var AuthApiKeyRegenerateResponseSchema = external_exports.object({
21762
21762
  createdAt: external_exports.string().min(1),
21763
21763
  gatewayUrl: GatewayUrl
21764
21764
  });
21765
+ var AuthApiKeyRevokeResponseSchema = external_exports.object({
21766
+ type: external_exports.literal("auth:apiKey:revoke:ok"),
21767
+ /** 之前有没有那把——没发过也算成功(幂等) */
21768
+ revoked: external_exports.boolean()
21769
+ });
21765
21770
  var AuthLoginDoneEventSchema = external_exports.object({
21766
21771
  type: external_exports.literal("auth:login:done"),
21767
21772
  identity: FeishuIdentitySchema
@@ -24309,6 +24314,10 @@ var METHOD_DOCS = {
24309
24314
  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",
24310
24315
  args: NO_ARGS
24311
24316
  },
24317
+ "auth:apiKey:revoke": {
24318
+ summary: "\u64A4\u9500\u81EA\u5DF1\u7684\u4E91 persona \u8C03\u7528 key\uFF1A\u4E2D\u5FC3\u5220\u6389\u90A3\u4E00\u884C\u3001**\u4E0D\u53D1\u65B0\u7684**\u3002gateway \u53EA\u5728\u5F00\u4F1A\u8BDD\u548C\u6BCF\u6B21\u4E0A\u884C\u65F6\u9A8C key\uFF0C\u6240\u4EE5\u5F00\u7740\u7684\u4E91\u4F1A\u8BDD\u4E0B\u4E00\u6761\u6D88\u606F\u624D\u53D1\u4E0D\u51FA\u53BB\u3001\u6B63\u5728\u8DD1\u7684\u90A3\u4E00\u8F6E\u4F1A\u8DD1\u5B8C\u3002\u6CA1\u53D1\u8FC7\u4E5F\u56DE ok\uFF08revoked:false\uFF09\u3002owner-only",
24319
+ args: NO_ARGS
24320
+ },
24312
24321
  "device:list": {
24313
24322
  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",
24314
24323
  args: NO_ARGS