@clawos-dev/clawd 0.2.584 → 0.2.585

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.
@@ -21787,6 +21787,10 @@ var DeployPutSecretArgsSchema = external_exports.object({
21787
21787
  // 环境变量名 → 值。key 必须是该 secret 声明过的 env 之一,handler 校验。
21788
21788
  values: external_exports.record(external_exports.string(), external_exports.string())
21789
21789
  }).strict();
21790
+ var DeploySetEngineAuthArgsSchema = external_exports.object({
21791
+ personaId: external_exports.string().min(1),
21792
+ auth: external_exports.object({ baseUrl: external_exports.string(), apiKey: external_exports.string() }).strict().nullable()
21793
+ }).strict();
21790
21794
  var DeployRerunJobArgsSchema = external_exports.object({
21791
21795
  personaId: external_exports.string().min(1),
21792
21796
  /** GitHub 的 job databaseId。**是数字**——字符串会在拼命令时静默出错 */
@@ -24273,9 +24277,13 @@ var METHOD_DOCS = {
24273
24277
  args: DeployPatchArgsSchema
24274
24278
  },
24275
24279
  "deploy:putSecret": {
24276
- summary: "\u628A\u4E00\u6761\u51ED\u636E\u7684\u503C\u5199\u8FDB\u4ED3\u5E93\u7684 GitHub Secrets\uFF08GitHub REST\uFF0C\u503C\u7528\u4ED3\u5E93\u516C\u94A5\u5C01\u7BB1\u540E\u4E0A\u4F20\uFF09\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\u3002env \u540D\u5FC5\u987B\u662F scanId \u90A3\u6B21\u6E05\u5355\u91CC\u8BE5\u51ED\u636E\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
24280
+ summary: "\u628A\u4E00\u6761\u51ED\u636E\u7684\u503C\u5199\u8FDB\u4ED3\u5E93\u7684 GitHub Secrets\uFF08GitHub REST\uFF0C\u503C\u7528\u4ED3\u5E93\u516C\u94A5\u5C01\u7BB1\u540E\u4E0A\u4F20\uFF09\u3002**\u8FD9\u662F\u6E05\u5355\u51ED\u636E\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF08\u6A21\u578B\u8BA2\u9605\u8D70 deploy:setEngineAuth\uFF09\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\u3002env \u540D\u5FC5\u987B\u662F scanId \u90A3\u6B21\u6E05\u5355\u91CC\u8BE5\u51ED\u636E\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
24277
24281
  args: DeployPutSecretArgsSchema
24278
24282
  },
24283
+ "deploy:setEngineAuth": {
24284
+ summary: "\u6A21\u578B\u8BA2\u9605\uFF08\u4E91\u4E0A\u8DD1\u8FD9\u4E2A persona \u82B1\u8C01\u7684\u6A21\u578B\u989D\u5EA6\uFF09\uFF1Aauth = { baseUrl, apiKey } \u5199\u8FDB\u4ED3\u5E93 GitHub Secrets \u7684 CLAWD_ENGINE_BASE_URL / CLAWD_ENGINE_API_KEY\uFF08\u5730\u5740\u89C4\u8303\u6210 \u2026/v1\uFF09\uFF0Cnull = \u5220\u8FD9\u4E24\u6761\u3001\u6539\u56DE\u5E73\u53F0\u9ED8\u8BA4\u3002\u4E0B\u6B21\u53D1\u5E03\u751F\u6548\u3002\u540C putSecret \u7684\u7EAA\u5F8B\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\uFF1B\u56DE deploy:get \u540C\u5F62\u7684\u72B6\u6001\uFF1Bowner-only\u3001human-only",
24285
+ args: DeploySetEngineAuthArgsSchema
24286
+ },
24279
24287
  "deploy:reportFinding": {
24280
24288
  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\u3002owner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
24281
24289
  args: DeployReportFindingArgsSchema
package/dist/cli.cjs CHANGED
@@ -6154,6 +6154,26 @@ var init_environment_schemas = __esm({
6154
6154
  });
6155
6155
 
6156
6156
  // ../protocol/src/deploy-schemas.ts
6157
+ function engineAuthState(secrets) {
6158
+ if (!secrets) return void 0;
6159
+ const has = (env) => secrets.some((p3) => p3.env === env && p3.setAt !== void 0);
6160
+ const n2 = [ENGINE_AUTH_SECRETS.baseUrl, ENGINE_AUTH_SECRETS.apiKey].filter(has).length;
6161
+ return n2 === 2 ? "own" : n2 === 0 ? "platform" : "partial";
6162
+ }
6163
+ function normalizeEngineBaseUrl(raw) {
6164
+ const s2 = raw.trim();
6165
+ let url;
6166
+ try {
6167
+ url = new URL(s2);
6168
+ } catch {
6169
+ throw new Error("\u8BA2\u9605\u5730\u5740\u8981\u4EE5 http:// \u6216 https:// \u5F00\u5934\uFF0C\u5F62\u5982 https://cpa.example.com");
6170
+ }
6171
+ if (url.protocol !== "http:" && url.protocol !== "https:" || !url.hostname) {
6172
+ throw new Error("\u8BA2\u9605\u5730\u5740\u8981\u4EE5 http:// \u6216 https:// \u5F00\u5934\uFF0C\u5F62\u5982 https://cpa.example.com");
6173
+ }
6174
+ const base = `${url.origin}${url.pathname}`.replace(/\/+$/, "");
6175
+ return base.endsWith("/v1") ? base : `${base}/v1`;
6176
+ }
6157
6177
  function contentHeadOf(repo2, released) {
6158
6178
  return released && repo2.head === released.head ? released.contentHead : repo2.head;
6159
6179
  }
@@ -6168,7 +6188,7 @@ function cloudEngineOk(tool) {
6168
6188
  function repoSlug(url) {
6169
6189
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6170
6190
  }
6171
- var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6191
+ var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6172
6192
  var init_deploy_schemas = __esm({
6173
6193
  "../protocol/src/deploy-schemas.ts"() {
6174
6194
  "use strict";
@@ -6253,6 +6273,8 @@ var init_deploy_schemas = __esm({
6253
6273
  env: external_exports.string().min(1),
6254
6274
  setAt: external_exports.number().optional()
6255
6275
  }).strict();
6276
+ ENGINE_AUTH_SECRETS = { baseUrl: "CLAWD_ENGINE_BASE_URL", apiKey: "CLAWD_ENGINE_API_KEY" };
6277
+ ENGINE_AUTH_PARTIAL_BLOCKER = "\u6A21\u578B\u8BA2\u9605\u53EA\u5199\u8FDB\u53BB\u4E00\u534A\u2014\u2014\u91CD\u586B\u6216\u6539\u56DE\u5E73\u53F0\u9ED8\u8BA4";
6256
6278
  DEPLOY_STAGE_STATUSES = ["pending", "running", "done", "failed", "waiting", "skipped"];
6257
6279
  DeployStageStatusSchema = external_exports.enum(DEPLOY_STAGE_STATUSES);
6258
6280
  DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy"];
@@ -6358,6 +6380,10 @@ var init_deploy_schemas = __esm({
6358
6380
  // 环境变量名 → 值。key 必须是该 secret 声明过的 env 之一,handler 校验。
6359
6381
  values: external_exports.record(external_exports.string(), external_exports.string())
6360
6382
  }).strict();
6383
+ DeploySetEngineAuthArgsSchema = external_exports.object({
6384
+ personaId: external_exports.string().min(1),
6385
+ auth: external_exports.object({ baseUrl: external_exports.string(), apiKey: external_exports.string() }).strict().nullable()
6386
+ }).strict();
6361
6387
  DeployRerunJobArgsSchema = external_exports.object({
6362
6388
  personaId: external_exports.string().min(1),
6363
6389
  /** GitHub 的 job databaseId。**是数字**——字符串会在拼命令时静默出错 */
@@ -9137,9 +9163,13 @@ var init_methods = __esm({
9137
9163
  args: DeployPatchArgsSchema
9138
9164
  },
9139
9165
  "deploy:putSecret": {
9140
- summary: "\u628A\u4E00\u6761\u51ED\u636E\u7684\u503C\u5199\u8FDB\u4ED3\u5E93\u7684 GitHub Secrets\uFF08GitHub REST\uFF0C\u503C\u7528\u4ED3\u5E93\u516C\u94A5\u5C01\u7BB1\u540E\u4E0A\u4F20\uFF09\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\u3002env \u540D\u5FC5\u987B\u662F scanId \u90A3\u6B21\u6E05\u5355\u91CC\u8BE5\u51ED\u636E\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
9166
+ summary: "\u628A\u4E00\u6761\u51ED\u636E\u7684\u503C\u5199\u8FDB\u4ED3\u5E93\u7684 GitHub Secrets\uFF08GitHub REST\uFF0C\u503C\u7528\u4ED3\u5E93\u516C\u94A5\u5C01\u7BB1\u540E\u4E0A\u4F20\uFF09\u3002**\u8FD9\u662F\u6E05\u5355\u51ED\u636E\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF08\u6A21\u578B\u8BA2\u9605\u8D70 deploy:setEngineAuth\uFF09\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\u3002env \u540D\u5FC5\u987B\u662F scanId \u90A3\u6B21\u6E05\u5355\u91CC\u8BE5\u51ED\u636E\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
9141
9167
  args: DeployPutSecretArgsSchema
9142
9168
  },
9169
+ "deploy:setEngineAuth": {
9170
+ summary: "\u6A21\u578B\u8BA2\u9605\uFF08\u4E91\u4E0A\u8DD1\u8FD9\u4E2A persona \u82B1\u8C01\u7684\u6A21\u578B\u989D\u5EA6\uFF09\uFF1Aauth = { baseUrl, apiKey } \u5199\u8FDB\u4ED3\u5E93 GitHub Secrets \u7684 CLAWD_ENGINE_BASE_URL / CLAWD_ENGINE_API_KEY\uFF08\u5730\u5740\u89C4\u8303\u6210 \u2026/v1\uFF09\uFF0Cnull = \u5220\u8FD9\u4E24\u6761\u3001\u6539\u56DE\u5E73\u53F0\u9ED8\u8BA4\u3002\u4E0B\u6B21\u53D1\u5E03\u751F\u6548\u3002\u540C putSecret \u7684\u7EAA\u5F8B\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u503C\u3001\u672C\u673A\u4E0D\u843D\u76D8\uFF1B\u56DE deploy:get \u540C\u5F62\u7684\u72B6\u6001\uFF1Bowner-only\u3001human-only",
9171
+ args: DeploySetEngineAuthArgsSchema
9172
+ },
9143
9173
  "deploy:reportFinding": {
9144
9174
  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\u3002owner-only\u2014\u2014butler \u4F1A\u8BDD\u672C\u8EAB\u8DD1\u5728 owner \u6A21\u5F0F",
9145
9175
  args: DeployReportFindingArgsSchema
@@ -60865,6 +60895,11 @@ function createGithubApi(args) {
60865
60895
  const encrypted_value = await seal(pk.key, value);
60866
60896
  await must("PUT", `/repos/${slug}/actions/secrets/${encodeURIComponent(name)}`, `\u5199 ${name}`, { encrypted_value, key_id: pk.key_id });
60867
60897
  },
60898
+ async deleteSecret(slug, name) {
60899
+ const r2 = await request("DELETE", `/repos/${slug}/actions/secrets/${encodeURIComponent(name)}`);
60900
+ if (r2.status === 404) return;
60901
+ if (r2.status < 200 || r2.status >= 300) throw new GithubApiError(r2.status, explain(r2.status, `\u5220 ${name}`, r2.json));
60902
+ },
60868
60903
  async listSecrets(slug) {
60869
60904
  const j2 = await must("GET", `/repos/${slug}/actions/secrets?per_page=100`, "\u67E5\u4ED3\u5E93 Secrets");
60870
60905
  const rows = Array.isArray(j2?.secrets) ? j2.secrets : [];
@@ -61430,6 +61465,15 @@ async function setSecret(exec, api, args) {
61430
61465
  throw new RepoError(err instanceof Error ? err.message : String(err));
61431
61466
  }
61432
61467
  }
61468
+ async function deleteSecret(exec, api, args) {
61469
+ const info = await repoInfo(exec, args.dir);
61470
+ if (!info) throw new RepoError("\u8FD8\u6CA1\u6709\u4ED3\u5E93\uFF0CSecrets \u6CA1\u5730\u65B9\u5220");
61471
+ try {
61472
+ await api.deleteSecret(repoSlug(info.url), args.env);
61473
+ } catch (err) {
61474
+ throw new RepoError(err instanceof Error ? err.message : String(err));
61475
+ }
61476
+ }
61433
61477
  async function listSecrets(exec, api, dir) {
61434
61478
  const info = await repoInfo(exec, dir);
61435
61479
  if (!info) return [];
@@ -61849,6 +61893,36 @@ function buildDeployHandlers(deps) {
61849
61893
  secretsCache.delete(args.personaId);
61850
61894
  return view(args.personaId);
61851
61895
  };
61896
+ const setEngineAuth = async (frame, _client, ctx) => {
61897
+ ensureOwner(ctx);
61898
+ const args = parseArgs2(DeploySetEngineAuthArgsSchema, frame, "deploy:setEngineAuth");
61899
+ const dir = mustPersona(args.personaId);
61900
+ let writes;
61901
+ if (args.auth) {
61902
+ let baseUrl;
61903
+ try {
61904
+ baseUrl = normalizeEngineBaseUrl(args.auth.baseUrl);
61905
+ } catch (err) {
61906
+ throw invalid(err instanceof Error ? err.message : String(err));
61907
+ }
61908
+ const apiKey = args.auth.apiKey.trim();
61909
+ if (!apiKey) throw invalid("key \u4E0D\u80FD\u662F\u7A7A\u7684");
61910
+ if (/[\s\p{Cc}]/u.test(apiKey)) throw invalid("key \u91CC\u4E0D\u80FD\u6709\u7A7A\u767D\u6216\u63A7\u5236\u5B57\u7B26\uFF08\u591A\u534A\u662F\u7C98\u8D34\u65F6\u5E26\u8FDB\u4E86\u6362\u884C\u6216\u7A7A\u683C\uFF09");
61911
+ writes = [[ENGINE_AUTH_SECRETS.apiKey, apiKey], [ENGINE_AUTH_SECRETS.baseUrl, baseUrl]];
61912
+ }
61913
+ const { api } = await requireGithub();
61914
+ try {
61915
+ if (writes) {
61916
+ await deleteSecret(deps.exec, api, { dir, env: ENGINE_AUTH_SECRETS.baseUrl });
61917
+ for (const [env, value] of writes) await setSecret(deps.exec, api, { dir, env, value });
61918
+ } else for (const env of [ENGINE_AUTH_SECRETS.apiKey, ENGINE_AUTH_SECRETS.baseUrl]) await deleteSecret(deps.exec, api, { dir, env });
61919
+ } catch (err) {
61920
+ throw toClawdError(err);
61921
+ } finally {
61922
+ secretsCache.delete(args.personaId);
61923
+ }
61924
+ return view(args.personaId);
61925
+ };
61852
61926
  async function settlePackage(pkg) {
61853
61927
  const localVersion = await deps.probeLocalVersion(pkg);
61854
61928
  const { artifact: reported, ...rest } = pkg;
@@ -61992,14 +62066,16 @@ function buildDeployHandlers(deps) {
61992
62066
  throw invalid(repo2.dirty ? "\u6709\u672A\u63D0\u4EA4\u7684\u6539\u52A8\uFF0C\u6E05\u5355\u662F\u6539\u52A8\u524D\u626B\u7684\u2014\u2014\u91CD\u65B0\u626B\u63CF" : "\u8FD9\u6B21\u626B\u63CF\u5BF9\u5E94\u7684\u4E0D\u662F\u5F53\u524D\u8FD9\u4E00\u7248 persona\u2014\u2014\u91CD\u65B0\u626B\u63CF");
61993
62067
  }
61994
62068
  const blockers = [];
61995
- let present;
62069
+ let secrets;
61996
62070
  try {
61997
- present = new Set((await cachedSecrets(personaId2, dir, api, true)).filter((p3) => p3.setAt).map((p3) => p3.env));
62071
+ secrets = await cachedSecrets(personaId2, dir, api, true);
61998
62072
  } catch (err) {
61999
62073
  throw toClawdError(err);
62000
62074
  }
62075
+ const present = new Set(secrets.filter((p3) => p3.setAt).map((p3) => p3.env));
62001
62076
  const missing = requiredEnvNames(entry.manifest).filter((e) => !present.has(e));
62002
62077
  if (missing.length > 0) blockers.push(`${missing.join(" / ")} \u8FD8\u6CA1\u586B`);
62078
+ if (engineAuthState(secrets) === "partial") blockers.push(ENGINE_AUTH_PARTIAL_BLOCKER);
62003
62079
  for (const c2 of entry.manifest.connectors) blockers.push(...connectorBlockers(c2));
62004
62080
  for (const p3 of entry.manifest.packages) blockers.push(...packageBlockers(p3));
62005
62081
  if (!deps.personaEngine(personaId2)?.model) {
@@ -62075,6 +62151,7 @@ function buildDeployHandlers(deps) {
62075
62151
  "deploy:scan": scanHandler,
62076
62152
  "deploy:patch": patch,
62077
62153
  "deploy:putSecret": putSecret,
62154
+ "deploy:setEngineAuth": setEngineAuth,
62078
62155
  "deploy:reportFinding": reportFinding,
62079
62156
  "deploy:finishScan": finishScan,
62080
62157
  "deploy:release": releaseHandler,
@@ -72021,6 +72098,7 @@ var METHOD_GRANT_MAP = {
72021
72098
  "deploy:scan": ADMIN_ANY,
72022
72099
  "deploy:patch": ADMIN_ANY,
72023
72100
  "deploy:putSecret": ADMIN_ANY,
72101
+ "deploy:setEngineAuth": ADMIN_ANY,
72024
72102
  "deploy:reportFinding": ADMIN_ANY,
72025
72103
  "deploy:finishScan": ADMIN_ANY,
72026
72104
  "deploy:release": ADMIN_ANY,
@@ -72238,6 +72316,7 @@ var HUMAN_ONLY_METHODS = [
72238
72316
  "deploy:scan",
72239
72317
  "deploy:release",
72240
72318
  "deploy:putSecret",
72319
+ "deploy:setEngineAuth",
72241
72320
  "deploy:rerunJob",
72242
72321
  "deploy:unpublish",
72243
72322
  "githubAuth:oauthStart",
@@ -72284,7 +72363,7 @@ function computeMethodAccess(args) {
72284
72363
  }
72285
72364
 
72286
72365
  // src/version.ts
72287
- var version = "0.2.584".length > 0 ? "0.2.584" : "dev";
72366
+ var version = "0.2.585".length > 0 ? "0.2.585" : "dev";
72288
72367
 
72289
72368
  // src/cli-probe/probe.ts
72290
72369
  var fs80 = __toESM(require("fs"), 1);