@clawos-dev/clawd 0.2.732 → 0.2.734

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.
@@ -31378,12 +31378,6 @@ var EnvPackageSchema = external_exports.object({
31378
31378
  */
31379
31379
  aptVersion: external_exports.string().optional()
31380
31380
  });
31381
- var EnvSecretSchema = external_exports.object({
31382
- name: external_exports.string().min(1),
31383
- // 解析出的值注入到哪些环境变量。一份凭据可含多个字段(AK 是 id+secret 两个,
31384
- // supabase 是 url/anon/service-role/jwt 四个),所以是数组不是单值。
31385
- env: external_exports.array(external_exports.string().min(1)).min(1)
31386
- });
31387
31381
  var ConnectorNameSchema = external_exports.string().regex(/^[a-z0-9-]+$/, "\u8FDE\u63A5\u5668\u540D\u53EA\u80FD\u662F\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u77ED\u6A2A\u7EBF");
31388
31382
  var CONNECTOR_KINDS = ["proxy", "env"];
31389
31383
  var CONNECTOR_RUNNERS = ["mcp", "cli"];
@@ -31391,6 +31385,10 @@ var CONNECTOR_PROTOCOLS = ["bearer", "lark-sidecar"];
31391
31385
  var CREDENTIAL_SOURCES = ["none", "shared", "personal"];
31392
31386
  var CONNECTOR_AUTHS = ["oauth", "fields"];
31393
31387
  var ConnectorFieldSchema = external_exports.string().regex(/^[A-Z][A-Z0-9_]*$/, "\u8981\u586B\u7684\u53D8\u91CF\u540D\u53EA\u80FD\u662F\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4EE5\u5B57\u6BCD\u5F00\u5934");
31388
+ var EnvVarSchema = external_exports.object({
31389
+ name: external_exports.string().min(1),
31390
+ env: external_exports.array(ConnectorFieldSchema).min(1)
31391
+ });
31394
31392
  var EnvConnectorSchema = external_exports.object({
31395
31393
  name: ConnectorNameSchema,
31396
31394
  kind: external_exports.enum(CONNECTOR_KINDS),
@@ -31415,6 +31413,12 @@ var normalizeLegacyManifest = (v) => {
31415
31413
  const { assets: _dropped, ...rest } = o;
31416
31414
  o = rest;
31417
31415
  }
31416
+ if ("secrets" in o && Array.isArray(o.secrets)) {
31417
+ const { secrets, ...rest } = o;
31418
+ const fields = new Set((Array.isArray(rest.connectors) ? rest.connectors : []).flatMap((c) => Array.isArray(c?.fields) ? c.fields : []));
31419
+ const legacy = secrets.map((g) => ({ ...g, env: Array.isArray(g?.env) ? g.env.filter((e) => !fields.has(e)) : g?.env })).filter((g) => !Array.isArray(g.env) || g.env.length > 0);
31420
+ o = { ...rest, envVars: [...Array.isArray(rest.envVars) ? rest.envVars : [], ...legacy] };
31421
+ }
31418
31422
  return o;
31419
31423
  };
31420
31424
  var PublisherTestSchema = external_exports.object({
@@ -31426,12 +31430,13 @@ var PublisherTestSchema = external_exports.object({
31426
31430
  var MANIFEST_BODY = {
31427
31431
  test: PublisherTestSchema.optional(),
31428
31432
  packages: external_exports.array(EnvPackageSchema),
31429
- secrets: external_exports.array(EnvSecretSchema),
31433
+ /** 环境变量(见 `EnvVarSchema`)。缺省空:没声明就是没有。 */
31434
+ envVars: external_exports.array(EnvVarSchema).default([]),
31430
31435
  /**
31431
31436
  * 装了哪些连接器(design 2026-09-11-mcp-connector §3.1)。一条一个对象,形状见 `EnvConnectorSchema`。
31432
31437
  *
31433
- * 不复用 secrets:那段说的是「需要一份值,由部署者填」;连接器的凭据谁出是单据上点出来的,
31434
- * 三种来源里只有「共享」才落到 Secrets,而且靠 `sharedConnectorSecrets` 在消费处并入,不写进那段。
31438
+ * 凭据归连接器自己(`fields`),不进 envVars:谁出是单据上点出来的,
31439
+ * 三种来源里只有「共享」才落到 Secrets,而且靠 `sharedConnectorSecrets` 在消费处并入。
31435
31440
  *
31436
31441
  * **缺省空而不是必填**:本机上已有的单据不用为此重扫一遍;没声明就是没装。
31437
31442
  */
@@ -31445,7 +31450,7 @@ var EnvironmentManifestSchema = external_exports.preprocess(normalizeLegacyManif
31445
31450
  ...MANIFEST_BODY
31446
31451
  }).strict());
31447
31452
  var EnvEvidenceSchema = external_exports.object({
31448
- // 这条证据支持的是哪一项:`${kind}:${name}`,如 'package:aliyun' / 'secret:aliyun-ak' / 'connector:feishu'
31453
+ // 这条证据支持的是哪一项:`${kind}:${name}`,如 'package:aliyun' / 'env:aliyun-ak' / 'connector:feishu'
31449
31454
  target: external_exports.string().min(1),
31450
31455
  reason: external_exports.string().min(1),
31451
31456
  file: external_exports.string().min(1),
@@ -31950,7 +31955,7 @@ var DeployRerunJobArgsSchema = external_exports.object({
31950
31955
  }).strict();
31951
31956
  var DeployReportFindingArgsSchema = external_exports.object({
31952
31957
  personaId: external_exports.string().min(1),
31953
- kind: external_exports.enum(["package", "secret", "connector"]),
31958
+ kind: external_exports.enum(["package", "env", "connector"]),
31954
31959
  // 该条目在 manifest 对应数组里的内容(形状随 kind 变,handler 按 kind 收窄校验)
31955
31960
  // connector 的 item 是 butler 报的 CLI 连接器({ name, fields? }),daemon 补齐 kind / runner / id 后落进清单;
31956
31961
  // MCP 连接器不经这里——由 daemon 从 .mcp.json 机械列出(design 2026-09-11-mcp-connector §3.2)
@@ -32954,7 +32959,7 @@ var EngineConnectPoolResponseSchema = external_exports.object({
32954
32959
  }).strict();
32955
32960
 
32956
32961
  // ../protocol/src/dashboard-schemas.ts
32957
- var DASHBOARD_PAGES = ["cloud-persona-metrics", "cloud-persona-conversations"];
32962
+ var DASHBOARD_PAGES = ["cloud-persona-metrics", "cloud-persona-conversations", "cloud-persona-schedules"];
32958
32963
  var DashboardPageSchema = external_exports.enum(DASHBOARD_PAGES);
32959
32964
  var DASHBOARD_LINK_TTL_SECONDS = 24 * 3600;
32960
32965
  var DashboardOpenUrlArgs = external_exports.object({ page: DashboardPageSchema }).strict();
@@ -34013,7 +34018,7 @@ var METHOD_DOCS = {
34013
34018
  }
34014
34019
  },
34015
34020
  "deploy:reportFinding": {
34016
- summary: "\u626B\u63CF\u4E2D\u7684 butler \u9010\u6761\u4E0A\u62A5\u4E00\u4E2A\u53D1\u73B0\uFF08cli / secret / asset\uFF09\u3002**\u8FB9\u626B\u8FB9\u62A5**\uFF0C\u9875\u9762\u968F\u4E4B\u4E00\u70B9\u70B9\u586B\u5145\uFF1B\u540C (kind,name) \u91CD\u590D\u4E0A\u62A5\u5373\u8986\u76D6\u3002\u53EA\u56DE\u626B\u63CF\u5386\u53F2 `scans`\uFF08\u540C deploy:patch\uFF09\uFF0C\u4E0D\u56DE\u6574\u4EFD\u72B6\u6001\uFF1Bowner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
34021
+ summary: "\u626B\u63CF\u4E2D\u7684 butler \u9010\u6761\u4E0A\u62A5\u4E00\u4E2A\u53D1\u73B0\uFF08package / env / connector\uFF09\u3002**\u8FB9\u626B\u8FB9\u62A5**\uFF0C\u9875\u9762\u968F\u4E4B\u4E00\u70B9\u70B9\u586B\u5145\uFF1B\u540C (kind,name) \u91CD\u590D\u4E0A\u62A5\u5373\u8986\u76D6\u3002\u53EA\u56DE\u626B\u63CF\u5386\u53F2 `scans`\uFF08\u540C deploy:patch\uFF09\uFF0C\u4E0D\u56DE\u6574\u4EFD\u72B6\u6001\uFF1Bowner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
34017
34022
  args: DeployReportFindingArgsSchema
34018
34023
  },
34019
34024
  "deploy:finishScan": {
package/dist/cli.cjs CHANGED
@@ -6174,9 +6174,13 @@ function sharedConnectorSecrets(m3) {
6174
6174
  return m3.connectors.filter((c2) => c2.credentialSource === "shared" && c2.fields.length > 0).map((c2) => ({ name: c2.name, env: [...c2.fields] }));
6175
6175
  }
6176
6176
  function requiredSecretEnvNames(m3) {
6177
- return [.../* @__PURE__ */ new Set([...m3.secrets.flatMap((s2) => s2.env), ...sharedConnectorSecrets(m3).flatMap((s2) => s2.env)])];
6177
+ return [.../* @__PURE__ */ new Set([...m3.envVars.flatMap((s2) => s2.env), ...sharedConnectorSecrets(m3).flatMap((s2) => s2.env)])];
6178
6178
  }
6179
- var EnvArtifactSchema, CLOUD_DEBIAN, CLOUD_ROOT_PROVIDES, CLOUD_BASE_PROVIDES, EnvPackageSchema, EnvSecretSchema, ConnectorNameSchema, CONNECTOR_KINDS, CONNECTOR_RUNNERS, CONNECTOR_PROTOCOLS, CREDENTIAL_SOURCES, CONNECTOR_AUTHS, ConnectorFieldSchema, EnvConnectorSchema, FEISHU_BOT_FIELDS, GO_SPEC_RE, GO_MOVING_REFS, normalizeLegacyManifest, PUBLISHER_TEST_NOTE_PREFIX, PublisherTestSchema, MANIFEST_BODY, EnvManifestBodySchema, EnvironmentManifestSchema, EnvEvidenceSchema;
6179
+ function envVarBlockers(m3) {
6180
+ const fields = new Set(m3.connectors.flatMap((c2) => c2.fields));
6181
+ return [...new Set(m3.envVars.flatMap((v3) => v3.env))].filter((env) => fields.has(env)).map((env) => `${env} \u540C\u65F6\u662F\u73AF\u5883\u53D8\u91CF\u548C\u8FDE\u63A5\u5668\u7684\u5B57\u6BB5\uFF0C\u53EA\u80FD\u7559\u4E00\u5904\u2014\u2014\u91CD\u65B0\u626B\u63CF`);
6182
+ }
6183
+ var EnvArtifactSchema, CLOUD_DEBIAN, CLOUD_ROOT_PROVIDES, CLOUD_BASE_PROVIDES, EnvPackageSchema, ConnectorNameSchema, CONNECTOR_KINDS, CONNECTOR_RUNNERS, CONNECTOR_PROTOCOLS, CREDENTIAL_SOURCES, CONNECTOR_AUTHS, ConnectorFieldSchema, EnvVarSchema, EnvConnectorSchema, FEISHU_BOT_FIELDS, GO_SPEC_RE, GO_MOVING_REFS, normalizeLegacyManifest, PUBLISHER_TEST_NOTE_PREFIX, PublisherTestSchema, MANIFEST_BODY, EnvManifestBodySchema, EnvironmentManifestSchema, EnvEvidenceSchema;
6180
6184
  var init_environment_schemas = __esm({
6181
6185
  "../protocol/src/environment-schemas.ts"() {
6182
6186
  "use strict";
@@ -6246,12 +6250,6 @@ var init_environment_schemas = __esm({
6246
6250
  */
6247
6251
  aptVersion: external_exports.string().optional()
6248
6252
  });
6249
- EnvSecretSchema = external_exports.object({
6250
- name: external_exports.string().min(1),
6251
- // 解析出的值注入到哪些环境变量。一份凭据可含多个字段(AK 是 id+secret 两个,
6252
- // supabase 是 url/anon/service-role/jwt 四个),所以是数组不是单值。
6253
- env: external_exports.array(external_exports.string().min(1)).min(1)
6254
- });
6255
6253
  ConnectorNameSchema = external_exports.string().regex(/^[a-z0-9-]+$/, "\u8FDE\u63A5\u5668\u540D\u53EA\u80FD\u662F\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u77ED\u6A2A\u7EBF");
6256
6254
  CONNECTOR_KINDS = ["proxy", "env"];
6257
6255
  CONNECTOR_RUNNERS = ["mcp", "cli"];
@@ -6259,6 +6257,10 @@ var init_environment_schemas = __esm({
6259
6257
  CREDENTIAL_SOURCES = ["none", "shared", "personal"];
6260
6258
  CONNECTOR_AUTHS = ["oauth", "fields"];
6261
6259
  ConnectorFieldSchema = external_exports.string().regex(/^[A-Z][A-Z0-9_]*$/, "\u8981\u586B\u7684\u53D8\u91CF\u540D\u53EA\u80FD\u662F\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4EE5\u5B57\u6BCD\u5F00\u5934");
6260
+ EnvVarSchema = external_exports.object({
6261
+ name: external_exports.string().min(1),
6262
+ env: external_exports.array(ConnectorFieldSchema).min(1)
6263
+ });
6262
6264
  EnvConnectorSchema = external_exports.object({
6263
6265
  name: ConnectorNameSchema,
6264
6266
  kind: external_exports.enum(CONNECTOR_KINDS),
@@ -6286,6 +6288,12 @@ var init_environment_schemas = __esm({
6286
6288
  const { assets: _dropped, ...rest } = o2;
6287
6289
  o2 = rest;
6288
6290
  }
6291
+ if ("secrets" in o2 && Array.isArray(o2.secrets)) {
6292
+ const { secrets, ...rest } = o2;
6293
+ const fields = new Set((Array.isArray(rest.connectors) ? rest.connectors : []).flatMap((c2) => Array.isArray(c2?.fields) ? c2.fields : []));
6294
+ const legacy = secrets.map((g3) => ({ ...g3, env: Array.isArray(g3?.env) ? g3.env.filter((e) => !fields.has(e)) : g3?.env })).filter((g3) => !Array.isArray(g3.env) || g3.env.length > 0);
6295
+ o2 = { ...rest, envVars: [...Array.isArray(rest.envVars) ? rest.envVars : [], ...legacy] };
6296
+ }
6289
6297
  return o2;
6290
6298
  };
6291
6299
  PUBLISHER_TEST_NOTE_PREFIX = "Publisher test: ";
@@ -6298,12 +6306,13 @@ var init_environment_schemas = __esm({
6298
6306
  MANIFEST_BODY = {
6299
6307
  test: PublisherTestSchema.optional(),
6300
6308
  packages: external_exports.array(EnvPackageSchema),
6301
- secrets: external_exports.array(EnvSecretSchema),
6309
+ /** 环境变量(见 `EnvVarSchema`)。缺省空:没声明就是没有。 */
6310
+ envVars: external_exports.array(EnvVarSchema).default([]),
6302
6311
  /**
6303
6312
  * 装了哪些连接器(design 2026-09-11-mcp-connector §3.1)。一条一个对象,形状见 `EnvConnectorSchema`。
6304
6313
  *
6305
- * 不复用 secrets:那段说的是「需要一份值,由部署者填」;连接器的凭据谁出是单据上点出来的,
6306
- * 三种来源里只有「共享」才落到 Secrets,而且靠 `sharedConnectorSecrets` 在消费处并入,不写进那段。
6314
+ * 凭据归连接器自己(`fields`),不进 envVars:谁出是单据上点出来的,
6315
+ * 三种来源里只有「共享」才落到 Secrets,而且靠 `sharedConnectorSecrets` 在消费处并入。
6307
6316
  *
6308
6317
  * **缺省空而不是必填**:本机上已有的单据不用为此重扫一遍;没声明就是没装。
6309
6318
  */
@@ -6317,7 +6326,7 @@ var init_environment_schemas = __esm({
6317
6326
  ...MANIFEST_BODY
6318
6327
  }).strict());
6319
6328
  EnvEvidenceSchema = external_exports.object({
6320
- // 这条证据支持的是哪一项:`${kind}:${name}`,如 'package:aliyun' / 'secret:aliyun-ak' / 'connector:feishu'
6329
+ // 这条证据支持的是哪一项:`${kind}:${name}`,如 'package:aliyun' / 'env:aliyun-ak' / 'connector:feishu'
6321
6330
  target: external_exports.string().min(1),
6322
6331
  reason: external_exports.string().min(1),
6323
6332
  file: external_exports.string().min(1),
@@ -6934,7 +6943,7 @@ var init_deploy_schemas = __esm({
6934
6943
  DEPLOY_STALE_BASE_ERROR = "\u5E95\u5EA7\u5DF2\u66F4\u65B0\uFF0C\u91CD\u8BD5\u4ECD\u4F1A\u7528\u65E7\u5E95\u5EA7\u6784\u5EFA\u2014\u2014\u8BF7\u91CD\u65B0\u53D1\u5E03\u6D4B\u8BD5\u73AF\u5883";
6935
6944
  DeployReportFindingArgsSchema = external_exports.object({
6936
6945
  personaId: external_exports.string().min(1),
6937
- kind: external_exports.enum(["package", "secret", "connector"]),
6946
+ kind: external_exports.enum(["package", "env", "connector"]),
6938
6947
  // 该条目在 manifest 对应数组里的内容(形状随 kind 变,handler 按 kind 收窄校验)
6939
6948
  // connector 的 item 是 butler 报的 CLI 连接器({ name, fields? }),daemon 补齐 kind / runner / id 后落进清单;
6940
6949
  // MCP 连接器不经这里——由 daemon 从 .mcp.json 机械列出(design 2026-09-11-mcp-connector §3.2)
@@ -8123,7 +8132,7 @@ var init_dashboard_schemas = __esm({
8123
8132
  "../protocol/src/dashboard-schemas.ts"() {
8124
8133
  "use strict";
8125
8134
  init_zod();
8126
- DASHBOARD_PAGES = ["cloud-persona-metrics", "cloud-persona-conversations"];
8135
+ DASHBOARD_PAGES = ["cloud-persona-metrics", "cloud-persona-conversations", "cloud-persona-schedules"];
8127
8136
  DashboardPageSchema = external_exports.enum(DASHBOARD_PAGES);
8128
8137
  DASHBOARD_LINK_TTL_SECONDS = 24 * 3600;
8129
8138
  DashboardOpenUrlArgs = external_exports.object({ page: DashboardPageSchema }).strict();
@@ -9286,7 +9295,7 @@ var init_methods = __esm({
9286
9295
  }
9287
9296
  },
9288
9297
  "deploy:reportFinding": {
9289
- summary: "\u626B\u63CF\u4E2D\u7684 butler \u9010\u6761\u4E0A\u62A5\u4E00\u4E2A\u53D1\u73B0\uFF08cli / secret / asset\uFF09\u3002**\u8FB9\u626B\u8FB9\u62A5**\uFF0C\u9875\u9762\u968F\u4E4B\u4E00\u70B9\u70B9\u586B\u5145\uFF1B\u540C (kind,name) \u91CD\u590D\u4E0A\u62A5\u5373\u8986\u76D6\u3002\u53EA\u56DE\u626B\u63CF\u5386\u53F2 `scans`\uFF08\u540C deploy:patch\uFF09\uFF0C\u4E0D\u56DE\u6574\u4EFD\u72B6\u6001\uFF1Bowner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
9298
+ summary: "\u626B\u63CF\u4E2D\u7684 butler \u9010\u6761\u4E0A\u62A5\u4E00\u4E2A\u53D1\u73B0\uFF08package / env / connector\uFF09\u3002**\u8FB9\u626B\u8FB9\u62A5**\uFF0C\u9875\u9762\u968F\u4E4B\u4E00\u70B9\u70B9\u586B\u5145\uFF1B\u540C (kind,name) \u91CD\u590D\u4E0A\u62A5\u5373\u8986\u76D6\u3002\u53EA\u56DE\u626B\u63CF\u5386\u53F2 `scans`\uFF08\u540C deploy:patch\uFF09\uFF0C\u4E0D\u56DE\u6574\u4EFD\u72B6\u6001\uFF1Bowner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
9290
9299
  args: DeployReportFindingArgsSchema
9291
9300
  },
9292
9301
  "deploy:finishScan": {
@@ -49195,6 +49204,33 @@ function attachPersonaSecretMcp(ctx, resolve9) {
49195
49204
  return { ...ctx, mcpConfigs: [...ctx.mcpConfigs ?? [], ref] };
49196
49205
  }
49197
49206
 
49207
+ // src/persona/persona-env-vars.ts
49208
+ init_protocol();
49209
+ function personaEnvVars(args) {
49210
+ let parsed;
49211
+ try {
49212
+ parsed = DeployFileSchema.safeParse(JSON.parse(args.manifestText));
49213
+ } catch {
49214
+ throw new Error("deploy.json \u4E0D\u662F\u5408\u6CD5 JSON");
49215
+ }
49216
+ if (!parsed.success) throw new Error("deploy.json \u8BFB\u4E0D\u51FA\u6E05\u5355");
49217
+ const names = [...new Set(parsed.data.manifest.envVars.flatMap((v3) => v3.env))];
49218
+ const env = {};
49219
+ const missing = [];
49220
+ for (const name of names) {
49221
+ const value = args.secrets[name];
49222
+ if (value) env[name] = value;
49223
+ else missing.push(name);
49224
+ }
49225
+ return { env, missing };
49226
+ }
49227
+ function attachPersonaEnvVars(ctx, resolve9) {
49228
+ if (!resolve9 || !ctx.personaId) return ctx;
49229
+ const vars = resolve9(ctx.personaId);
49230
+ if (Object.keys(vars).length === 0) return ctx;
49231
+ return { ...ctx, env: { ...vars, ...ctx.env } };
49232
+ }
49233
+
49198
49234
  // src/ipc-recorder.ts
49199
49235
  var import_node_fs15 = __toESM(require("fs"), 1);
49200
49236
  var import_node_path14 = __toESM(require("path"), 1);
@@ -49696,6 +49732,7 @@ var SessionRunner = class {
49696
49732
  let ctx;
49697
49733
  try {
49698
49734
  ctx = attachPersonaSecretMcp(rawCtx, this.hooks.resolvePersonaMcpConfig);
49735
+ if (!this.state.file.larkChatId) ctx = attachPersonaEnvVars(ctx, this.hooks.resolvePersonaEnvVars);
49699
49736
  } catch (err) {
49700
49737
  const message = `persona secret mcp render failed: ${err instanceof Error ? err.message : String(err)}`;
49701
49738
  this.hooks.logger?.error("persona.mcp-secret.render-failed", {
@@ -50236,6 +50273,7 @@ var SessionManager = class {
50236
50273
  getClawosApi: this.deps.getClawosApi,
50237
50274
  getMcpConfigs: () => this.deps.mcpConfigs ?? [],
50238
50275
  resolvePersonaMcpConfig: this.deps.resolvePersonaMcpConfig,
50276
+ resolvePersonaEnvVars: this.deps.resolvePersonaEnvVars,
50239
50277
  // 只传人格补充层读闭包,避免把整个 store 下沉;缺 store 不追加。
50240
50278
  readPersonalityLocal: this.deps.personaStore ? (id) => this.deps.personaStore?.readPersonalityLocal(id) ?? null : void 0,
50241
50279
  lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
@@ -53632,9 +53670,10 @@ var DashboardDataError = class extends Error {
53632
53670
  };
53633
53671
  var SUBROUTES = {
53634
53672
  "cloud-persona-metrics": ["personas", "data", "issues"],
53635
- "cloud-persona-conversations": ["personas", "threads", "thread"]
53673
+ "cloud-persona-conversations": ["personas", "threads", "thread"],
53674
+ "cloud-persona-schedules": ["personas", "schedules", "runs"]
53636
53675
  };
53637
- var UPSTREAM_DOWN = { personas: "UPSTREAM_UNREACHABLE", data: "GATEWAY_UNREACHABLE", issues: "GATEWAY_UNREACHABLE", threads: "CENTER_UNREACHABLE", thread: "CENTER_UNREACHABLE" };
53676
+ var UPSTREAM_DOWN = { personas: "UPSTREAM_UNREACHABLE", data: "GATEWAY_UNREACHABLE", issues: "GATEWAY_UNREACHABLE", threads: "CENTER_UNREACHABLE", thread: "CENTER_UNREACHABLE", schedules: "GATEWAY_UNREACHABLE", runs: "GATEWAY_UNREACHABLE" };
53638
53677
  var NO_STORE = { "cache-control": "no-store" };
53639
53678
  function send(res, status, contentType, body) {
53640
53679
  res.writeHead(status, { "content-type": contentType, ...NO_STORE });
@@ -53703,6 +53742,21 @@ function createDashboardRoutes(deps) {
53703
53742
  sendPassthrough(res, await deps.data.issues({ personaId: personaId2, threadId: threadId2, window: q3.get("window"), entry: q3.get("entry"), cursor, snapshotTo: rawSnapshot === null ? null : Number(rawSnapshot) }));
53704
53743
  return true;
53705
53744
  }
53745
+ if (sub === "schedules") {
53746
+ sendPassthrough(res, await deps.data.schedules({ personaId: personaId2 }));
53747
+ return true;
53748
+ }
53749
+ if (sub === "runs") {
53750
+ const scheduleId = q3.get("id") ?? "";
53751
+ const limit = q3.get("limit");
53752
+ const before = q3.get("before");
53753
+ if (!/^[0-9a-f-]{36}$/.test(scheduleId) || limit !== null && !/^\d{1,3}$/.test(limit) || before !== null && !/^[1-9]\d{0,15}$/.test(before)) {
53754
+ sendJson(res, 400, { code: "INVALID_PARAM", message: "id / limit / before \u65E0\u6548" });
53755
+ return true;
53756
+ }
53757
+ sendPassthrough(res, await deps.data.schedules({ personaId: personaId2, scheduleId, limit: limit === null ? null : Number(limit), before: before === null ? null : Number(before) }));
53758
+ return true;
53759
+ }
53706
53760
  if (sub === "threads") {
53707
53761
  const limit = q3.get("limit");
53708
53762
  if (limit !== null && !/^\d{1,3}$/.test(limit)) {
@@ -54071,6 +54125,7 @@ function createDashboardData(deps) {
54071
54125
  },
54072
54126
  metrics: (q3) => deps.metrics(q3),
54073
54127
  issues: (q3) => deps.issues(q3),
54128
+ schedules: (q3) => deps.schedules(q3),
54074
54129
  async threads(q3) {
54075
54130
  return deps.threads(mustLoginPass(), q3);
54076
54131
  },
@@ -58304,7 +58359,9 @@ var GATEWAY_ROUTES = {
58304
58359
  volume: () => "/me/volume",
58305
58360
  workspace: (personaId2) => `/p/${encodeURIComponent(personaId2)}/workspace`,
58306
58361
  fork: (personaId2) => `/p/${encodeURIComponent(personaId2)}/fork`,
58307
- metrics: (personaId2) => `/metrics/${encodeURIComponent(personaId2)}`
58362
+ metrics: (personaId2) => `/metrics/${encodeURIComponent(personaId2)}`,
58363
+ schedules: (personaId2) => `/schedules/${encodeURIComponent(personaId2)}`,
58364
+ scheduleRuns: (personaId2, scheduleId) => `/schedules/${encodeURIComponent(personaId2)}/${encodeURIComponent(scheduleId)}/runs`
58308
58365
  };
58309
58366
  var METRICS_TIMEOUT_MS = 3e4;
58310
58367
  var trimSlash = (u2) => u2.replace(/\/+$/, "");
@@ -58504,6 +58561,27 @@ var CloudGatewayClient = class {
58504
58561
  throw e;
58505
58562
  }
58506
58563
  }
58564
+ /**
58565
+ * 看板的定时任务页(design 2026-10-27-cloud-schedule):gateway 回什么原样转(状态码 + body),鉴权同 fetchMetrics。
58566
+ * 带 scheduleId = 展开一条任务的运行记录一页(limit / before 分页)
58567
+ */
58568
+ async fetchSchedules(q3) {
58569
+ const { apiKey, gatewayUrl } = await this.credentials();
58570
+ const qs = new URLSearchParams();
58571
+ if (q3.limit != null) qs.set("limit", String(q3.limit));
58572
+ if (q3.before != null) qs.set("before", String(q3.before));
58573
+ const path113 = q3.scheduleId ? GATEWAY_ROUTES.scheduleRuns(q3.personaId, q3.scheduleId) + (qs.size ? `?${qs}` : "") : GATEWAY_ROUTES.schedules(q3.personaId);
58574
+ try {
58575
+ const res = await this.fetchImpl(gatewayUrl + path113, {
58576
+ headers: { authorization: `Bearer ${apiKey}` },
58577
+ signal: AbortSignal.timeout(METRICS_TIMEOUT_MS)
58578
+ });
58579
+ return { status: res.status, body: await res.text() };
58580
+ } catch (e) {
58581
+ if (e.name === "TimeoutError") throw new Error(`\u4E91\u4E0A\u670D\u52A1 ${METRICS_TIMEOUT_MS / 1e3} \u79D2\u6CA1\u56DE`);
58582
+ throw e;
58583
+ }
58584
+ }
58507
58585
  async fetchThreadIssues(q3) {
58508
58586
  const { apiKey, gatewayUrl } = await this.credentials();
58509
58587
  const qs = new URLSearchParams({ threadId: q3.threadId });
@@ -58985,7 +59063,9 @@ function normalizeLegacyScan(raw) {
58985
59063
  rest.evidence = rest.evidence.map((e) => {
58986
59064
  if (!e || typeof e !== "object" || typeof e.target !== "string") return e;
58987
59065
  const target = e.target;
58988
- return target.startsWith("cli:") ? { ...e, target: `package:${target.slice("cli:".length)}` } : e;
59066
+ if (target.startsWith("cli:")) return { ...e, target: `package:${target.slice("cli:".length)}` };
59067
+ if (target.startsWith("secret:")) return { ...e, target: `env:${target.slice("secret:".length)}` };
59068
+ return e;
58989
59069
  });
58990
59070
  }
58991
59071
  return rest;
@@ -59029,14 +59109,14 @@ function replaceScan(file, entry) {
59029
59109
  return { ...file, scans: idx === -1 ? [...file.scans, entry] : file.scans.map((s2, i2) => i2 === idx ? entry : s2) };
59030
59110
  }
59031
59111
  function emptyDeployFile() {
59032
- return { version: 1, manifest: { version: 1, packages: [], secrets: [], connectors: [] } };
59112
+ return { version: 1, manifest: { version: 1, packages: [], envVars: [], connectors: [] } };
59033
59113
  }
59034
59114
  var PackageFindingSchema = EnvPackageSchema.omit({ localVersion: true, artifact: true, aptMissing: true, aptVersion: true }).extend({
59035
59115
  artifact: external_exports.object({ url: external_exports.string().url(), bin: external_exports.string() }).strict().optional()
59036
59116
  });
59037
59117
  var FINDING_SCHEMAS = {
59038
59118
  package: PackageFindingSchema,
59039
- secret: EnvSecretSchema,
59119
+ env: EnvVarSchema,
59040
59120
  // 仅收 CLI 连接器发现;MCP 由 scanMcpConnectors 从配置列出。
59041
59121
  connector: CliConnectorFindingSchema
59042
59122
  };
@@ -59090,7 +59170,7 @@ function upsertFinding(manifest, kind, item) {
59090
59170
  const connectors = idx2 === -1 ? [...have, merged] : have.map((c2, i2) => i2 === idx2 ? merged : c2);
59091
59171
  return { ...manifest, connectors };
59092
59172
  }
59093
- const key = kind === "package" ? "packages" : "secrets";
59173
+ const key = kind === "package" ? "packages" : "envVars";
59094
59174
  const list = [...manifest[key]];
59095
59175
  const idx = list.findIndex((x2) => x2.name === item.name);
59096
59176
  if (idx === -1) list.push(item);
@@ -64606,8 +64686,8 @@ function buildDeployHandlers(deps) {
64606
64686
  const args = parseArgs2(DeployPutSecretArgsSchema, frame, "deploy:putSecret");
64607
64687
  const dir = mustPersona(args.personaId);
64608
64688
  const { manifest } = mustScan(await readHistory(dir), args.scanId);
64609
- const declared = [...manifest.secrets, ...sharedConnectorSecrets(manifest)].find((s2) => s2.name === args.name);
64610
- if (!declared) throw invalid(`\u6E05\u5355\u91CC\u6CA1\u6709\u53EB\u300C${args.name}\u300D\u7684\u51ED\u636E`);
64689
+ const declared = [...manifest.envVars, ...sharedConnectorSecrets(manifest)].find((s2) => s2.name === args.name);
64690
+ if (!declared) throw invalid(`\u6E05\u5355\u91CC\u6CA1\u6709\u53EB\u300C${args.name}\u300D\u7684\u73AF\u5883\u53D8\u91CF\u6216\u5171\u4EAB\u8FDE\u63A5\u5668`);
64611
64691
  const allowed = new Set(declared.env);
64612
64692
  for (const key of Object.keys(args.values)) {
64613
64693
  if (!allowed.has(key)) throw invalid(`\u300C${args.name}\u300D\u6CA1\u6709\u58F0\u660E\u73AF\u5883\u53D8\u91CF ${key}`);
@@ -64893,6 +64973,7 @@ function buildDeployHandlers(deps) {
64893
64973
  if (missing.length > 0) blockers.push(`${missing.join(" / ")} \u8FD8\u6CA1\u586B`);
64894
64974
  if (engineAuthState(secrets) === "partial") blockers.push(ENGINE_AUTH_PARTIAL_BLOCKER);
64895
64975
  for (const c2 of entry.manifest.connectors) blockers.push(...connectorBlockers(c2));
64976
+ blockers.push(...envVarBlockers(entry.manifest));
64896
64977
  for (const p3 of entry.manifest.packages) blockers.push(...packageBlockers(p3));
64897
64978
  const cloudEngine = cloudEngineSettings(deps.personaEngine(personaId2) ?? {});
64898
64979
  if (!cloudEngine.model) {
@@ -76181,7 +76262,7 @@ function computeMethodAccess(args) {
76181
76262
  }
76182
76263
 
76183
76264
  // src/version.ts
76184
- var version = "0.2.732".length > 0 ? "0.2.732" : "dev";
76265
+ var version = "0.2.734".length > 0 ? "0.2.734" : "dev";
76185
76266
 
76186
76267
  // src/cli-probe/probe.ts
76187
76268
  var fs87 = __toESM(require("fs"), 1);
@@ -78961,6 +79042,23 @@ async function startDaemon(config) {
78961
79042
  logger
78962
79043
  });
78963
79044
  };
79045
+ const resolvePersonaEnvVars = (personaId2) => {
79046
+ const file = import_node_path90.default.join(config.dataDir, "personas", personaId2, DEPLOY_FILE);
79047
+ let manifestText;
79048
+ try {
79049
+ manifestText = import_node_fs69.default.readFileSync(file, "utf8");
79050
+ } catch {
79051
+ return {};
79052
+ }
79053
+ try {
79054
+ const { env, missing } = personaEnvVars({ manifestText, secrets: readSecrets() });
79055
+ if (missing.length > 0) logger.warn("persona.env-vars.missing", { personaId: personaId2, names: missing });
79056
+ return env;
79057
+ } catch (err) {
79058
+ logger.warn("persona.env-vars.unreadable", { personaId: personaId2, message: err instanceof Error ? err.message : String(err) });
79059
+ return {};
79060
+ }
79061
+ };
78964
79062
  const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
78965
79063
  const dispatchServerCandidates = [
78966
79064
  import_node_path90.default.join(here, "dispatch", "mcp-server.cjs"),
@@ -79152,6 +79250,7 @@ async function startDaemon(config) {
79152
79250
  mcpConfigs,
79153
79251
  // Render MCP configs outside the pure reducer because rendering performs filesystem IO.
79154
79252
  resolvePersonaMcpConfig,
79253
+ resolvePersonaEnvVars,
79155
79254
  generateTitle: (file, firstMessage, signal) => generateSessionTitle(file, firstMessage, {
79156
79255
  logger,
79157
79256
  signal,
@@ -80117,6 +80216,7 @@ async function startDaemon(config) {
80117
80216
  visiblePersonas: (loginPass) => centralVisiblePersonas({ api: dashboardApi(), loginPass }),
80118
80217
  metrics: (q3) => cloudGateway.fetchMetrics(q3),
80119
80218
  issues: (q3) => cloudGateway.fetchThreadIssues(q3),
80219
+ schedules: (q3) => cloudGateway.fetchSchedules(q3),
80120
80220
  threads: (loginPass, q3) => centralPersonaThreads({ api: dashboardApi(), loginPass, ...q3 }),
80121
80221
  thread: (loginPass, q3) => centralPersonaThread({ api: dashboardApi(), loginPass, ...q3 }),
80122
80222
  logger