@clawos-dev/clawd 0.2.479 → 0.2.481

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:",
@@ -54764,6 +54788,10 @@ var L = [
54764
54788
  " image: ${{ steps.plan.outputs.image }}",
54765
54789
  " persona_id: ${{ steps.plan.outputs.persona_id }}",
54766
54790
  " env_names: ${{ steps.plan.outputs.env_names }}",
54791
+ // 云上跑哪个模型 = 发布这一刻 persona 配的(build 段从仓库里的 .clawd/persona.json 读)。
54792
+ // smoke 与 deploy 都要:smoke 得用正式那份模型探活,否则验的不是将要上线的东西。
54793
+ " model: ${{ steps.plan.outputs.model }}",
54794
+ " effort: ${{ steps.plan.outputs.effort }}",
54767
54795
  " steps:",
54768
54796
  " - name: Checkout persona",
54769
54797
  " uses: actions/checkout@v4",
@@ -54878,13 +54906,14 @@ var L = [
54878
54906
  " env:",
54879
54907
  " CLAWD_GATEWAY_URL: ${{ vars.CLAWD_GATEWAY_URL }}",
54880
54908
  " CLAWD_GATEWAY_ADMIN_KEY: ${{ secrets.CLAWD_GATEWAY_ADMIN_KEY }}",
54881
- " CLAWD_GATEWAY_API_KEY: ${{ secrets.CLAWD_GATEWAY_API_KEY }}",
54882
54909
  " CLAWD_SECRETS_JSON: ${{ toJSON(secrets) }}",
54883
54910
  " CLAWD_ENV_NAMES: ${{ needs.build.outputs.env_names }}",
54884
54911
  " run: |",
54885
54912
  " node clawos/cloud-host/pipeline/smoke.mjs \\",
54886
54913
  " --image '${{ needs.build.outputs.image }}' \\",
54887
54914
  " --persona-id '${{ needs.build.outputs.persona_id }}' \\",
54915
+ " --model '${{ needs.build.outputs.model }}' \\",
54916
+ " --effort '${{ needs.build.outputs.effort }}' \\",
54888
54917
  " --run-number '${{ github.run_number }}'",
54889
54918
  "",
54890
54919
  " deploy:",
@@ -54912,7 +54941,9 @@ var L = [
54912
54941
  " run: |",
54913
54942
  " node clawos/cloud-host/pipeline/register.mjs \\",
54914
54943
  " --image '${{ needs.build.outputs.image }}' \\",
54915
- " --persona-id '${{ needs.build.outputs.persona_id }}'",
54944
+ " --persona-id '${{ needs.build.outputs.persona_id }}' \\",
54945
+ " --model '${{ needs.build.outputs.model }}' \\",
54946
+ " --effort '${{ needs.build.outputs.effort }}'",
54916
54947
  ""
54917
54948
  ];
54918
54949
  var WORKFLOW_TEMPLATE = L.join("\n");
@@ -55349,6 +55380,13 @@ function buildDeployHandlers(deps) {
55349
55380
  }
55350
55381
  const missing = requiredEnvNames(file).filter((e) => !present.has(e));
55351
55382
  if (missing.length > 0) blockers.push(`${missing.join(" / ")} \u8FD8\u6CA1\u586B`);
55383
+ const engine = deps.personaEngine(personaId2);
55384
+ const tool = engine?.tool || "claude";
55385
+ if (tool !== "codex") {
55386
+ blockers.push(`\u5F15\u64CE\u662F ${tool}\uFF0C\u4E91\u4E0A\u53EA\u8DD1 Codex\u2014\u2014\u53BB persona \u8BBE\u7F6E\u91CC\u628A\u5F15\u64CE\u5207\u6210 Codex\uFF0C\u518D\u9009\u4E2A\u6A21\u578B`);
55387
+ } else if (!engine?.model) {
55388
+ blockers.push("\u8FD8\u6CA1\u9009\u6A21\u578B\uFF08\u5207\u5F15\u64CE\u65F6\u4F1A\u6E05\u7A7A\uFF09\u2014\u2014\u53BB persona \u8BBE\u7F6E\u91CC\u9009\u4E00\u4E2A");
55389
+ }
55352
55390
  if (blockers.length > 0) throw invalid(`\u8FD8\u5DEE\uFF1A${blockers.join("\uFF1B")}`);
55353
55391
  try {
55354
55392
  const result = await release(deps.exec, { dir, now: deps.now });
@@ -61556,6 +61594,40 @@ async function centralPrincipalStatus(opts) {
61556
61594
  }
61557
61595
  return { active: body.active };
61558
61596
  }
61597
+ async function centralGetApiKey(opts) {
61598
+ const body = await centralRequest(
61599
+ opts,
61600
+ `/api/persona-cloud/api-key?provider=${encodeURIComponent(opts.provider)}`,
61601
+ { method: "GET", bearer: opts.ttcJwt }
61602
+ );
61603
+ if (body.apiKey !== null && typeof body.apiKey !== "string") {
61604
+ throw new CentralClientError("BAD_RESPONSE", "api-key: apiKey must be string or null");
61605
+ }
61606
+ return {
61607
+ apiKey: body.apiKey,
61608
+ createdAt: typeof body.createdAt === "string" ? body.createdAt : null,
61609
+ // 中心没配就是 null —— 不当成错误,key 本身照样有效
61610
+ gatewayUrl: typeof body.gatewayUrl === "string" ? body.gatewayUrl : null
61611
+ };
61612
+ }
61613
+ async function centralIssueApiKey(opts) {
61614
+ const body = await centralRequest(opts, "/api/persona-cloud/api-key", {
61615
+ method: "POST",
61616
+ bearer: opts.ttcJwt,
61617
+ body: { provider: opts.provider }
61618
+ });
61619
+ if (typeof body.apiKey !== "string" || body.apiKey.length === 0) {
61620
+ throw new CentralClientError("BAD_RESPONSE", "api-key: missing apiKey");
61621
+ }
61622
+ if (typeof body.createdAt !== "string" || body.createdAt.length === 0) {
61623
+ throw new CentralClientError("BAD_RESPONSE", "api-key: missing createdAt");
61624
+ }
61625
+ return {
61626
+ apiKey: body.apiKey,
61627
+ createdAt: body.createdAt,
61628
+ gatewayUrl: typeof body.gatewayUrl === "string" ? body.gatewayUrl : null
61629
+ };
61630
+ }
61559
61631
  async function centralListDevices(opts) {
61560
61632
  const body = await centralRequest(
61561
61633
  opts,
@@ -63966,6 +64038,7 @@ function buildWhoamiHandler(deps) {
63966
64038
  }
63967
64039
 
63968
64040
  // src/handlers/feishu-auth.ts
64041
+ init_protocol();
63969
64042
  function buildFeishuAuthHandlers(deps) {
63970
64043
  const loginStart = async () => {
63971
64044
  const { authUrl, state } = deps.loginFlow.start();
@@ -63994,10 +64067,34 @@ function buildFeishuAuthHandlers(deps) {
63994
64067
  response: { type: "auth:logout:ok" }
63995
64068
  };
63996
64069
  };
64070
+ function requireLogin() {
64071
+ const record3 = deps.ownerIdentityStore.read();
64072
+ if (!record3) {
64073
+ throw new ClawdError(
64074
+ ERROR_CODES.FEISHU_LOGIN_REQUIRED,
64075
+ "\u8FD8\u6CA1\u767B\u5F55\u98DE\u4E66\uFF0C\u62FF\u4E0D\u5230\u4E91 persona \u7684\u8C03\u7528 key"
64076
+ );
64077
+ }
64078
+ return { ttcJwt: record3.ttcToken, provider: record3.identity.provider };
64079
+ }
64080
+ const apiKeyGet = async () => {
64081
+ const { apiKey, createdAt, gatewayUrl } = await deps.apiKeyClient.get(requireLogin());
64082
+ return {
64083
+ response: { type: "auth:apiKey:get:ok", apiKey, createdAt, gatewayUrl }
64084
+ };
64085
+ };
64086
+ const apiKeyRegenerate = async () => {
64087
+ const { apiKey, createdAt, gatewayUrl } = await deps.apiKeyClient.issue(requireLogin());
64088
+ return {
64089
+ response: { type: "auth:apiKey:regenerate:ok", apiKey, createdAt, gatewayUrl }
64090
+ };
64091
+ };
63997
64092
  return {
63998
64093
  "auth:login:start": loginStart,
63999
64094
  "auth:getIdentity": getIdentity,
64000
- "auth:logout": logout
64095
+ "auth:logout": logout,
64096
+ "auth:apiKey:get": apiKeyGet,
64097
+ "auth:apiKey:regenerate": apiKeyRegenerate
64001
64098
  };
64002
64099
  }
64003
64100
 
@@ -64238,6 +64335,9 @@ var METHOD_GRANT_MAP = {
64238
64335
  "auth:login:start": ADMIN_ANY,
64239
64336
  "auth:getIdentity": ADMIN_ANY,
64240
64337
  "auth:logout": ADMIN_ANY,
64338
+ // 云 persona 调用 key:本机主人自己的东西,guest 一律够不着
64339
+ "auth:apiKey:get": ADMIN_ANY,
64340
+ "auth:apiKey:regenerate": ADMIN_ANY,
64241
64341
  // ---- device:* 设备目录 + 连接(决策 #15,owner-only) ----
64242
64342
  // 设备目录 / 连接都是 owner 本机操作(用 owner 的 ttcJwt 找中心 server),guest 不可调
64243
64343
  "device:list": ADMIN_ANY,
@@ -64301,7 +64401,7 @@ function computeMethodAccess(args) {
64301
64401
  }
64302
64402
 
64303
64403
  // src/version.ts
64304
- var version = "0.2.479".length > 0 ? "0.2.479" : "dev";
64404
+ var version = "0.2.481".length > 0 ? "0.2.481" : "dev";
64305
64405
 
64306
64406
  // src/cli-probe/probe.ts
64307
64407
  var fs70 = __toESM(require("fs"), 1);
@@ -69302,6 +69402,12 @@ async function startDaemon(config) {
69302
69402
  ownerId = "";
69303
69403
  ownerProvider = "";
69304
69404
  ownerDisplayName = loadOwnerDisplayName(config.dataDir);
69405
+ },
69406
+ // 云 persona 调用 key(design 2026-09-08):daemon 拿本机登录凭证向中心代取。
69407
+ // 凭证不出 ws —— UI 只拿到 key 本身,跟 exchange / listDevices 同一条纪律。
69408
+ apiKeyClient: {
69409
+ get: (args) => centralGetApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args }),
69410
+ issue: (args) => centralIssueApiKey({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
69305
69411
  }
69306
69412
  },
69307
69413
  // 设备目录 + 连接(决策 #15:daemon 代理中心 server)。
@@ -69469,6 +69575,11 @@ async function startDaemon(config) {
69469
69575
  const deployHandlers = buildDeployHandlers({
69470
69576
  hasPersona: (personaId2) => personaStore.has(personaId2),
69471
69577
  personaDir: (personaId2) => personaStore.personaDirPath(personaId2),
69578
+ // 发布前落闸要看它现在配的引擎和模型(云上只跑 codex,且模型跟着这次发布走)
69579
+ personaEngine: (personaId2) => {
69580
+ const p2 = personaRegistry.get(personaId2);
69581
+ return p2 ? { ...p2.tool ? { tool: p2.tool } : {}, ...p2.model ? { model: p2.model } : {} } : void 0;
69582
+ },
69472
69583
  exec: runCommand,
69473
69584
  org: PERSONA_REPO_ORG,
69474
69585
  now: () => Date.now(),
@@ -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