@clawos-dev/clawd 0.2.625 → 0.2.626

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.
@@ -21714,7 +21714,8 @@ var DeploySecretPresenceSchema = external_exports.object({
21714
21714
  }).strict();
21715
21715
  var DEPLOY_STAGE_STATUSES = ["pending", "running", "done", "failed", "waiting", "skipped"];
21716
21716
  var DeployStageStatusSchema = external_exports.enum(DEPLOY_STAGE_STATUSES);
21717
- var DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy"];
21717
+ var DEPLOY_VERIFY_STAGE = "verify";
21718
+ var DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy", DEPLOY_VERIFY_STAGE];
21718
21719
  var DeployStageKeySchema = external_exports.enum(DEPLOY_STAGE_KEYS);
21719
21720
  var DeployJobSchema = external_exports.object({
21720
21721
  key: DeployStageKeySchema,
@@ -24604,6 +24605,12 @@ var PackageFindingSchema = EnvPackageSchema.omit({ localVersion: true, artifact:
24604
24605
  artifact: external_exports.object({ url: external_exports.string().url(), bin: external_exports.string() }).strict().optional()
24605
24606
  });
24606
24607
 
24608
+ // src/feishu-auth/deploy-environments.ts
24609
+ var DEPLOY_TARGETS = {
24610
+ integration: { api: "https://api-int.clawos.chat", gateway: "https://persona-int.clawos.chat" },
24611
+ production: { api: "https://api.clawos.chat", gateway: "https://persona.clawos.chat" }
24612
+ };
24613
+
24607
24614
  // src/deploy/release-workflow.ts
24608
24615
  function renderDeployWorkflow(config2) {
24609
24616
  const identity = [
@@ -24807,6 +24814,22 @@ function renderDeployWorkflow(config2) {
24807
24814
  ...download("${{ inputs.environment == 'production' && 'persona-candidate' || 'persona-smoked' }}"),
24808
24815
  ...contract,
24809
24816
  ...runtime("register"),
24817
+ ...job(DEPLOY_VERIFY_STAGE),
24818
+ " needs: deploy",
24819
+ " if: inputs.environment != 'production'",
24820
+ " steps:",
24821
+ ...download("persona-smoked"),
24822
+ ...contract,
24823
+ " - name: Verify ordinary user conversation after deployment",
24824
+ " env:",
24825
+ ` CLAWD_INT_API_URL: \${{ vars.CLAWD_INT_API_URL || '${DEPLOY_TARGETS.integration.api}' }}`,
24826
+ " CLAWD_INT_TEST_LOGIN_PASS: ${{ secrets.CLAWD_INT_TEST_LOGIN_PASS }}",
24827
+ " run: |",
24828
+ " node clawos/cloud-host/pipeline/persona-verify.mjs \\",
24829
+ " --file candidate-release.json \\",
24830
+ " --persona-id '${{ steps.plan.outputs.persona_id }}' \\",
24831
+ " --engine '${{ steps.plan.outputs.engine }}'",
24832
+ "",
24810
24833
  ...upload("persona-verified-${{ github.run_attempt }}")
24811
24834
  ].join("\n");
24812
24835
  }
package/dist/cli.cjs CHANGED
@@ -6260,7 +6260,7 @@ function cloudEngineOk(tool) {
6260
6260
  function repoSlug(url) {
6261
6261
  return url.trim().replace(/^git@[^:]+:/, "").replace(/^https?:\/\/[^/]+\//, "").replace(/\.git$/, "");
6262
6262
  }
6263
- var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, 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, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6263
+ var DeployFileSchema, SCAN_BASE_KINDS, ScanBaseKindSchema, DeployScanStatusSchema, DeployScanSchema, DeployReleasedSchema, DEPLOY_PROMOTION_PHASES, DeployPromotionSchema, DeployScanFileSchema, DeployRepoSchema, DeploySecretPresenceSchema, ENGINE_AUTH_SECRETS, ENGINE_AUTH_PARTIAL_BLOCKER, DEPLOY_STAGE_STATUSES, DeployStageStatusSchema, DEPLOY_VERIFY_STAGE, DEPLOY_STAGE_KEYS, DeployStageKeySchema, DeployJobSchema, DeployRunSchema, CLOUD_ENGINES, DeployUnpublishRunSchema, DeployStateSchema, DeployUnpublishResultSchema, DeployPatchResultSchema, DeployReleaseResultSchema, DeployPersonaArgsSchema, DeployGetArgsSchema, DeployScanArgsSchema, DeployReleaseArgsSchema, DeployConfirmTestArgsSchema, DeployPromoteArgsSchema, DeployOpenTestArgsSchema, DeployEnvironmentArgsSchema, DeployConfirmTestResultSchema, DeployPromoteResultSchema, DeployOpenTestResultSchema, DeployPatchArgsSchema, DeployPutSecretArgsSchema, DeploySetEngineAuthArgsSchema, DeployRerunJobArgsSchema, DeployReportFindingArgsSchema, DeployFinishScanArgsSchema, PERSONA_REPO_ORG;
6264
6264
  var init_deploy_schemas = __esm({
6265
6265
  "../protocol/src/deploy-schemas.ts"() {
6266
6266
  "use strict";
@@ -6350,7 +6350,8 @@ var init_deploy_schemas = __esm({
6350
6350
  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";
6351
6351
  DEPLOY_STAGE_STATUSES = ["pending", "running", "done", "failed", "waiting", "skipped"];
6352
6352
  DeployStageStatusSchema = external_exports.enum(DEPLOY_STAGE_STATUSES);
6353
- DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy"];
6353
+ DEPLOY_VERIFY_STAGE = "verify";
6354
+ DEPLOY_STAGE_KEYS = ["build", "smoke", "deploy", DEPLOY_VERIFY_STAGE];
6354
6355
  DeployStageKeySchema = external_exports.enum(DEPLOY_STAGE_KEYS);
6355
6356
  DeployJobSchema = external_exports.object({
6356
6357
  key: DeployStageKeySchema,
@@ -60940,6 +60941,7 @@ async function storeGithubAuth(args) {
60940
60941
  }
60941
60942
 
60942
60943
  // src/deploy/release-workflow.ts
60944
+ init_protocol();
60943
60945
  function renderDeployWorkflow(config) {
60944
60946
  const identity = [
60945
60947
  " - name: Select pinned source identities",
@@ -61142,6 +61144,22 @@ function renderDeployWorkflow(config) {
61142
61144
  ...download("${{ inputs.environment == 'production' && 'persona-candidate' || 'persona-smoked' }}"),
61143
61145
  ...contract,
61144
61146
  ...runtime("register"),
61147
+ ...job(DEPLOY_VERIFY_STAGE),
61148
+ " needs: deploy",
61149
+ " if: inputs.environment != 'production'",
61150
+ " steps:",
61151
+ ...download("persona-smoked"),
61152
+ ...contract,
61153
+ " - name: Verify ordinary user conversation after deployment",
61154
+ " env:",
61155
+ ` CLAWD_INT_API_URL: \${{ vars.CLAWD_INT_API_URL || '${DEPLOY_TARGETS.integration.api}' }}`,
61156
+ " CLAWD_INT_TEST_LOGIN_PASS: ${{ secrets.CLAWD_INT_TEST_LOGIN_PASS }}",
61157
+ " run: |",
61158
+ " node clawos/cloud-host/pipeline/persona-verify.mjs \\",
61159
+ " --file candidate-release.json \\",
61160
+ " --persona-id '${{ steps.plan.outputs.persona_id }}' \\",
61161
+ " --engine '${{ steps.plan.outputs.engine }}'",
61162
+ "",
61145
61163
  ...upload("persona-verified-${{ github.run_attempt }}")
61146
61164
  ].join("\n");
61147
61165
  }
@@ -61738,6 +61756,11 @@ async function readVerifiedRelease(api, slug, run) {
61738
61756
  endpoint: DEPLOY_TARGETS.integration.gateway
61739
61757
  }) };
61740
61758
  }
61759
+ function requireDialogueVerification(release2, run) {
61760
+ if (!release2.verification.checks.includes("persona-dialogue") || !run.jobs.some((j2) => j2.key === DEPLOY_VERIFY_STAGE && j2.status === "done")) {
61761
+ throw new Error("\u8FD9\u6B21\u53D1\u5E03\u8FD8\u6CA1\u6709\u901A\u8FC7\u81EA\u52A8\u5BF9\u8BDD\u9A8C\u8BC1\uFF0C\u8BF7\u91CD\u65B0\u626B\u63CF\u5E76\u53D1\u5E03\u6D4B\u8BD5\u73AF\u5883");
61762
+ }
61763
+ }
61741
61764
  function integrationPersonaForRelease(cloud, release2, releaseId) {
61742
61765
  const cloudName = cloudPersonaIdOf("https://github.com/" + release2.repository);
61743
61766
  if (cloud.personaId !== cloudName || cloud.image !== release2.image) return void 0;
@@ -62652,6 +62675,9 @@ function buildDeployHandlers(deps) {
62652
62675
  }
62653
62676
  return view(personaId2);
62654
62677
  };
62678
+ const configureTestIdentity = async (api, slug) => {
62679
+ await api.putSecret(slug, "CLAWD_INT_TEST_LOGIN_PASS", await deps.testLoginPass(), "integration");
62680
+ };
62655
62681
  const releaseHandler = async (frame, _client, ctx) => {
62656
62682
  ensureOwner(ctx);
62657
62683
  const { personaId: personaId2, scanId } = parseArgs2(DeployReleaseArgsSchema, frame, "deploy:release");
@@ -62667,6 +62693,7 @@ function buildDeployHandlers(deps) {
62667
62693
  const pending = file.releases.find((r2) => r2.environment === "integration" && r2.scanId === scanId && !r2.pushed);
62668
62694
  if (pending) {
62669
62695
  try {
62696
+ await configureTestIdentity(api, repoSlug(repo2.url));
62670
62697
  await pushRelease(deps.exec, dir, auth, pending.head);
62671
62698
  await api.setDefaultBranch(repoSlug(repo2.url), "integration");
62672
62699
  await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === pending.id ? { ...r2, pushed: true } : r2) });
@@ -62676,7 +62703,10 @@ function buildDeployHandlers(deps) {
62676
62703
  }
62677
62704
  }
62678
62705
  const already = [...file.releases].reverse().find((r2) => r2.environment === "integration" && r2.scanId === scanId && r2.pushed && r2.head === repo2.head);
62679
- if (already && !repo2.dirty) return { response: { type: "deploy:release", sha: already.head, actionsUrl: "https://github.com/" + repoSlug(repo2.url) + "/actions" } };
62706
+ if (already && !repo2.dirty) {
62707
+ await configureTestIdentity(api, repoSlug(repo2.url));
62708
+ return { response: { type: "deploy:release", sha: already.head, actionsUrl: "https://github.com/" + repoSlug(repo2.url) + "/actions" } };
62709
+ }
62680
62710
  if (entry.status !== "done") throw invalid(entry.status === "scanning" ? "\u8FD9\u6B21\u626B\u63CF\u8FD8\u5728\u8DD1\uFF0C\u7B49\u5B83\u626B\u5B8C" : "\u8FD9\u6B21\u626B\u63CF\u6CA1\u8DD1\u5B8C\uFF0C\u6E05\u5355\u4E0D\u5B8C\u6574\u2014\u2014\u91CD\u65B0\u626B\u63CF");
62681
62711
  if (!isScanFresh(entry, repo2, file.releases.find((r2) => r2.head === repo2.head))) {
62682
62712
  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");
@@ -62698,6 +62728,7 @@ function buildDeployHandlers(deps) {
62698
62728
  blockers.push("\u8FD8\u6CA1\u9009\u6A21\u578B\uFF08\u5207\u5F15\u64CE\u65F6\u4F1A\u6E05\u7A7A\uFF09\u2014\u2014\u5728\u4E0A\u4E91\u9875\u300C\u5F15\u64CE\u4E0E\u6A21\u578B\u300D\u91CC\u9009\u4E00\u4E2A");
62699
62729
  }
62700
62730
  if (blockers.length > 0) throw invalid(`\u8FD8\u5DEE\uFF1A${blockers.join("\uFF1B")}`);
62731
+ await configureTestIdentity(api, repoSlug(repo2.url));
62701
62732
  if (await deps.claimPublisher(cloudPersonaIdOf(repo2.url), "integration") === "taken") throw invalid("\u6D4B\u8BD5\u73AF\u5883\u91CC\u7684\u8FD9\u4E2A\u540D\u5B57\u5DF2\u7531\u522B\u4EBA\u53D1\u5E03");
62702
62733
  const releaseId = (0, import_node_crypto14.randomUUID)();
62703
62734
  try {
@@ -62734,6 +62765,7 @@ function buildDeployHandlers(deps) {
62734
62765
  }
62735
62766
  try {
62736
62767
  if (record4?.environment === "integration") {
62768
+ await configureTestIdentity(api, slug);
62737
62769
  await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === record4.id ? { ...r2, confirmation: void 0, verified: void 0, artifactId: void 0 } : r2) });
62738
62770
  }
62739
62771
  await rerunJob(api, slug, jobId);
@@ -62770,7 +62802,7 @@ function buildDeployHandlers(deps) {
62770
62802
  const { type: _type, requestId: _requestId, ...args } = frame;
62771
62803
  return parseArgs2({ safeParse: schema.safeParse.bind(schema) }, args, String(frame.type));
62772
62804
  }
62773
- async function testedRelease(personaId2, releaseId, checkOnline = true) {
62805
+ async function testedRelease(personaId2, releaseId, checkOnline = true, requireDialogue = false) {
62774
62806
  const dir = mustPersona(personaId2);
62775
62807
  const file = await readHistory(dir);
62776
62808
  const record4 = file.releases.find((r2) => r2.id === releaseId);
@@ -62781,6 +62813,13 @@ function buildDeployHandlers(deps) {
62781
62813
  const run = record4.runId ? await runById(api, repoSlug(repo2.url), record4.runId, "integration") : await findReleaseRun(api, repoSlug(repo2.url), { environment: "integration", head: record4.head });
62782
62814
  if (!run || run.headSha !== record4.head) throw invalid("\u6682\u65F6\u67E5\u4E0D\u5230\u672C\u6B21\u6D4B\u8BD5\u6D41\u6C34\u7EBF\uFF0C\u8BF7\u5237\u65B0");
62783
62815
  const { artifactId, release: verified } = await readVerifiedRelease(api, repoSlug(repo2.url), run);
62816
+ if (requireDialogue) {
62817
+ try {
62818
+ requireDialogueVerification(verified, run);
62819
+ } catch (e) {
62820
+ throw invalid(e.message);
62821
+ }
62822
+ }
62784
62823
  if (checkOnline && (await deps.cloudState(cloudPersonaIdOf(repo2.url), "integration")).image !== verified.image) throw invalid("\u6D4B\u8BD5\u73AF\u5883\u7684\u7248\u672C\u5DF2\u7ECF\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u53D1\u5E03\u6D4B\u8BD5\u5E76\u786E\u8BA4");
62785
62824
  const changed = record4.runId !== run.runId || record4.runAttempt !== run.runAttempt || record4.verified?.verification.fingerprint !== verified.verification.fingerprint;
62786
62825
  const updated = { ...record4, artifactId, verified, runId: run.runId, runAttempt: run.runAttempt ?? 1, ...changed ? { confirmation: void 0 } : {} };
@@ -62813,7 +62852,7 @@ function buildDeployHandlers(deps) {
62813
62852
  const confirmTest = async (frame, _client, ctx) => {
62814
62853
  ensureOwner(ctx);
62815
62854
  const { personaId: personaId2, releaseId } = releaseArgs(frame, DeployConfirmTestArgsSchema);
62816
- const record4 = await testedRelease(personaId2, releaseId);
62855
+ const record4 = await testedRelease(personaId2, releaseId, true, true);
62817
62856
  const confirmation = record4.confirmation ?? { fingerprint: record4.verified.verification.fingerprint, runId: record4.runId, runAttempt: record4.runAttempt, at: deps.now() };
62818
62857
  const dir = mustPersona(personaId2), file = await readHistory(dir);
62819
62858
  await writeScanFile(dir, { ...file, releases: file.releases.map((r2) => r2.id === releaseId ? { ...r2, confirmation } : r2) });
@@ -62829,8 +62868,7 @@ function buildDeployHandlers(deps) {
62829
62868
  const stored = file.releases.find((r2) => r2.id === releaseId);
62830
62869
  const snapshot = old?.verified ?? (stored?.confirmation?.fingerprint === stored?.verified?.verification.fingerprint ? stored?.verified : void 0);
62831
62870
  if (recovering && (!snapshot || !stored)) throw invalid("\u539F\u4E0A\u7EBF\u4EFB\u52A1\u7684\u5DF2\u6D4B\u5236\u54C1\u8BB0\u5F55\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5148\u6838\u5B9E\u539F\u6D41\u6C34\u7EBF\uFF1B\u4E0D\u4F1A\u6539\u7528\u65B0\u7684\u6D4B\u8BD5\u7248\u672C");
62832
- const record4 = recovering ? { ...stored, verified: snapshot } : await testedRelease(personaId2, releaseId);
62833
- if (!recovering && (!record4.confirmation || record4.confirmation.fingerprint !== record4.verified.verification.fingerprint || record4.confirmation.runId !== record4.runId || record4.confirmation.runAttempt !== record4.runAttempt)) throw invalid("\u8BF7\u5148\u5728\u6D4B\u8BD5\u73AF\u5883\u8BD5\u7528\uFF0C\u5E76\u786E\u8BA4\u8FD9\u6B21\u6D4B\u8BD5\u901A\u8FC7");
62871
+ const record4 = recovering ? { ...stored, verified: snapshot } : await testedRelease(personaId2, releaseId, true, true);
62834
62872
  const repo2 = await repoInfo(deps.exec, mustPersona(personaId2));
62835
62873
  if (!repo2) throw invalid("\u4ED3\u5E93\u4E0D\u5B58\u5728");
62836
62874
  if (await deps.claimPublisher(cloudPersonaIdOf(repo2.url), "production") === "taken") throw invalid("\u7EBF\u4E0A\u73AF\u5883\u91CC\u7684\u8FD9\u4E2A\u540D\u5B57\u5DF2\u7531\u522B\u4EBA\u53D1\u5E03");
@@ -73562,7 +73600,7 @@ function computeMethodAccess(args) {
73562
73600
  }
73563
73601
 
73564
73602
  // src/version.ts
73565
- var version = "0.2.625".length > 0 ? "0.2.625" : "dev";
73603
+ var version = "0.2.626".length > 0 ? "0.2.626" : "dev";
73566
73604
 
73567
73605
  // src/cli-probe/probe.ts
73568
73606
  var fs84 = __toESM(require("fs"), 1);
@@ -77221,6 +77259,12 @@ async function startDaemon(config) {
77221
77259
  const persona = list.find((p3) => p3.personaId === personaId2);
77222
77260
  return { online: persona !== void 0, ...persona?.image ? { image: persona.image } : {} };
77223
77261
  },
77262
+ testLoginPass: async () => {
77263
+ const loginPass = requireEnvironmentIdentity(environmentStores, "integration").loginPass;
77264
+ const credentials = await centralGetApiKey({ api: targetApi("integration"), loginPass });
77265
+ if (!credentials.apiKey) await centralIssueApiKey({ api: targetApi("integration"), loginPass });
77266
+ return loginPass;
77267
+ },
77224
77268
  openTestPersona: async (_personaId, release2, releaseId) => {
77225
77269
  const loginPass = requireEnvironmentIdentity(environmentStores, "integration").loginPass;
77226
77270
  const credentials = await centralGetApiKey({ api: targetApi("integration"), loginPass });