@clawos-dev/clawd 0.2.659 → 0.2.661

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +135 -77
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -63130,7 +63130,8 @@ async function latestRun(api, slug) {
63130
63130
  async function runByHead(api, slug, head) {
63131
63131
  return fetchRun(api, slug, `head_sha=${encodeURIComponent(head)}&per_page=1`);
63132
63132
  }
63133
- async function findReleaseRun(api, slug, target) {
63133
+ var COMPLETED_JOBS_CACHE_MAX = 256;
63134
+ async function findReleaseRun(api, slug, target, jobsCache) {
63134
63135
  try {
63135
63136
  const branch = target.environment === "integration" ? "integration" : "main";
63136
63137
  if (target.environment === "production" && !target.promotionId) return void 0;
@@ -63142,38 +63143,47 @@ async function findReleaseRun(api, slug, target) {
63142
63143
  ));
63143
63144
  if (!Array.isArray(listed?.workflow_runs)) return void 0;
63144
63145
  const raw = listed.workflow_runs.find((r2) => r2.head_branch === branch && (target.environment === "production" ? r2.event === "workflow_dispatch" && r2.display_title === `persona-production-${target.promotionId}` : r2.head_sha === target.head && (r2.event === "push" || r2.event === "workflow_dispatch")));
63145
- if (raw) return readPinnedRun(api, slug, raw, target.environment, target.promotionId);
63146
+ if (raw) return readPinnedRun(api, slug, raw, target.environment, target.promotionId, jobsCache);
63146
63147
  if (listed.workflow_runs.length < 100 && (listed.total_count === void 0 || page * 100 >= listed.total_count)) return null;
63147
63148
  }
63148
63149
  } catch {
63149
63150
  }
63150
63151
  return void 0;
63151
63152
  }
63152
- async function runById(api, slug, runId, environment, promotionId) {
63153
+ async function runById(api, slug, runId, environment, promotionId, jobsCache) {
63153
63154
  try {
63154
63155
  const raw = await api.getJsonStrict(`/repos/${slug}/actions/runs/${runId}`);
63155
63156
  if (raw.id !== runId || raw.head_branch !== (environment === "integration" ? "integration" : "main")) return void 0;
63156
63157
  if (environment === "production" && (!promotionId || raw.display_title !== `persona-production-${promotionId}`)) return void 0;
63157
- return readPinnedRun(api, slug, raw, environment, promotionId);
63158
+ return readPinnedRun(api, slug, raw, environment, promotionId, jobsCache);
63158
63159
  } catch {
63159
63160
  return void 0;
63160
63161
  }
63161
63162
  }
63162
- async function readPinnedRun(api, slug, raw, environment, promotionId) {
63163
+ async function readPinnedRun(api, slug, raw, environment, promotionId, jobsCache) {
63163
63164
  if (typeof raw.id !== "number" || typeof raw.head_sha !== "string" || typeof raw.html_url !== "string") return void 0;
63164
63165
  const attempt = typeof raw.run_attempt === "number" ? raw.run_attempt : 1;
63165
- const byKey = /* @__PURE__ */ new Map();
63166
- for (let page = 1; page <= 30; page++) {
63167
- const listed = await api.getJsonStrict(`/repos/${slug}/actions/runs/${raw.id}/attempts/${attempt}/jobs?per_page=100&page=${page}`);
63168
- if (!Array.isArray(listed?.jobs)) return void 0;
63169
- for (const row of listed.jobs) {
63170
- const job = toJob(row);
63171
- if (job) byKey.set(job.key, job);
63166
+ const status = runStatusOf(String(raw.status ?? ""));
63167
+ const cacheKey = `${slug}:${raw.id}:${attempt}`;
63168
+ let jobs = status === "completed" ? jobsCache?.get(cacheKey) : void 0;
63169
+ if (!jobs) {
63170
+ const byKey = /* @__PURE__ */ new Map();
63171
+ for (let page = 1; page <= 30; page++) {
63172
+ const listed = await api.getJsonStrict(`/repos/${slug}/actions/runs/${raw.id}/attempts/${attempt}/jobs?per_page=100&page=${page}`);
63173
+ if (!Array.isArray(listed?.jobs)) return void 0;
63174
+ for (const row of listed.jobs) {
63175
+ const job = toJob(row);
63176
+ if (job) byKey.set(job.key, job);
63177
+ }
63178
+ if (listed.jobs.length < 100 && (listed.total_count === void 0 || page * 100 >= listed.total_count)) break;
63179
+ if (page === 30) return void 0;
63180
+ }
63181
+ jobs = DEPLOY_STAGE_KEYS.map((key) => byKey.get(key)).filter((j2) => j2 !== void 0);
63182
+ if (status === "completed" && jobsCache) {
63183
+ if (jobsCache.size >= COMPLETED_JOBS_CACHE_MAX) jobsCache.delete(jobsCache.keys().next().value);
63184
+ jobsCache.set(cacheKey, jobs);
63172
63185
  }
63173
- if (listed.jobs.length < 100 && (listed.total_count === void 0 || page * 100 >= listed.total_count)) break;
63174
- if (page === 30) return void 0;
63175
63186
  }
63176
- const status = runStatusOf(String(raw.status ?? ""));
63177
63187
  return {
63178
63188
  runId: raw.id,
63179
63189
  headSha: raw.head_sha,
@@ -63185,7 +63195,7 @@ async function readPinnedRun(api, slug, raw, environment, promotionId) {
63185
63195
  ...typeof raw.event === "string" ? { event: raw.event } : {},
63186
63196
  ...status === "completed" ? { conclusion: raw.conclusion === "success" ? "success" : "failure" } : {},
63187
63197
  ...promotionId ? { promotionId } : {},
63188
- jobs: DEPLOY_STAGE_KEYS.map((key) => byKey.get(key)).filter((j2) => j2 !== void 0)
63198
+ jobs
63189
63199
  };
63190
63200
  }
63191
63201
  async function fetchRun(api, slug, query) {
@@ -63258,6 +63268,7 @@ function reconcileInterruptedScans(deps) {
63258
63268
  var SECRETS_CACHE_MS = 2e4;
63259
63269
  var RUN_CACHE_MS = 4e3;
63260
63270
  var ONLINE_CACHE_MS = 2e4;
63271
+ var ONLINE_STALE_MS = 12e4;
63261
63272
  var directRead = async (_stage, action) => action();
63262
63273
  var UNPUBLISH_NEEDS_REPUBLISH = "\u8FD9\u4E2A persona \u7684\u6D41\u6C34\u7EBF\u662F\u65E7\u7248\u7684\uFF0C\u5148\u91CD\u65B0\u626B\u63CF\u3001\u53D1\u5E03\u4E00\u6B21\u518D\u4E0B\u7EBF";
63263
63274
  function ensureOwner(ctx) {
@@ -63349,20 +63360,42 @@ function buildDeployHandlers(deps) {
63349
63360
  return run;
63350
63361
  };
63351
63362
  const cloudCache = /* @__PURE__ */ new Map();
63363
+ const cloudRefreshing = /* @__PURE__ */ new Set();
63364
+ const cloudGeneration = /* @__PURE__ */ new Map();
63365
+ const invalidateCloud = (key) => {
63366
+ cloudCache.delete(key);
63367
+ cloudGeneration.set(key, (cloudGeneration.get(key) ?? 0) + 1);
63368
+ };
63352
63369
  const cachedCloud = async (personaId2, environment, run, unpublish, cloudName = personaId2, observe = () => deps.cloudState(cloudName, environment), fresh = false) => {
63353
63370
  const key = personaId2 + ":" + environment;
63354
63371
  const stamp = `${run?.runId ?? "-"}:${run?.runAttempt ?? "-"}:${run?.status ?? "-"}|${unpublish?.runId ?? "-"}:${unpublish?.status ?? "-"}`;
63355
63372
  const hit = cloudCache.get(key);
63356
- if (!fresh && hit && hit.stamp === stamp && deps.now() - hit.at < ONLINE_CACHE_MS) return hit.state;
63357
- let state;
63358
- try {
63359
- state = await observe();
63360
- } catch {
63361
- state = {};
63373
+ const refresh = async () => {
63374
+ const generation = cloudGeneration.get(key) ?? 0;
63375
+ let state;
63376
+ try {
63377
+ state = await observe();
63378
+ } catch {
63379
+ state = {};
63380
+ }
63381
+ if ((cloudGeneration.get(key) ?? 0) === generation) cloudCache.set(key, { stamp, at: deps.now(), state });
63382
+ return state;
63383
+ };
63384
+ if (!fresh && hit && hit.stamp === stamp) {
63385
+ const age = deps.now() - hit.at;
63386
+ if (age < ONLINE_CACHE_MS) return hit.state;
63387
+ if (age < ONLINE_STALE_MS) {
63388
+ if (!cloudRefreshing.has(key)) {
63389
+ cloudRefreshing.add(key);
63390
+ void refresh().finally(() => cloudRefreshing.delete(key));
63391
+ }
63392
+ return hit.state;
63393
+ }
63362
63394
  }
63363
- cloudCache.set(key, { stamp, at: deps.now(), state });
63364
- return state;
63395
+ return refresh();
63365
63396
  };
63397
+ const completedJobs = /* @__PURE__ */ new Map();
63398
+ const productionRunIds = /* @__PURE__ */ new Map();
63366
63399
  deps.githubIdentity.onChange(() => secretsCache.clear());
63367
63400
  async function requireGithub() {
63368
63401
  const auth = await deps.githubIdentity.refresh();
@@ -63449,28 +63482,36 @@ function buildDeployHandlers(deps) {
63449
63482
  }
63450
63483
  const { scans } = file;
63451
63484
  const selected = releaseId ? file.releases.find((r2) => r2.id === releaseId && (!environment || r2.environment === environment)) : releaseHead ? file.releases.find((r2) => r2.head === releaseHead && (!environment || r2.environment === environment)) : void 0;
63485
+ const publisherFeishuAuthRead = scans.at(-1)?.manifest.connectors.some(isFeishuPublisherConnector) ? (async () => {
63486
+ const query2 = async (environment2) => {
63487
+ try {
63488
+ return await measure("feishu.auth", () => deps.publisherFeishuAuth(repo2 ? cloudPersonaIdOf(repo2.url) : personaId2, environment2), { environment: environment2 });
63489
+ } catch (e) {
63490
+ return { connected: false, error: e instanceof Error ? e.message : "\u98DE\u4E66\u6388\u6743\u72B6\u6001\u67E5\u8BE2\u5931\u8D25" };
63491
+ }
63492
+ };
63493
+ const [integration, production] = await Promise.all([query2("integration"), query2("production")]);
63494
+ return { integration, production };
63495
+ })() : void 0;
63452
63496
  let secrets;
63453
63497
  let run;
63454
63498
  let unpublish;
63455
- if (repo2 && api && github.status === "authorized") {
63456
- const legacy = historical ? selected : latestProductionRelease(file.releases);
63457
- run = legacy?.legacy ? await measure("run", () => cachedRun(personaId2, api, repoSlug(repo2.url), legacy.head), { environment: legacy.environment }) : void 0;
63458
- if (!historical) unpublish = await measure("unpublish", () => cachedUnpublish(personaId2, api, repoSlug(repo2.url)), { environment: "production" });
63459
- }
63460
63499
  let online;
63461
63500
  const targets = {};
63462
63501
  if (repo2 && api && github.status === "authorized") {
63463
63502
  const slug = repoSlug(repo2.url), cloudName = cloudPersonaIdOf(repo2.url);
63503
+ const legacy = historical ? selected : latestProductionRelease(file.releases);
63504
+ const legacyRunRead = legacy?.legacy ? measure("run", () => cachedRun(personaId2, api, slug, legacy.head), { environment: legacy.environment }) : Promise.resolve(void 0);
63464
63505
  const integration = historical ? selected?.environment === "integration" ? selected : void 0 : [...file.releases].reverse().find((r2) => r2.environment === "integration");
63465
- let intRun;
63466
- if (integration) {
63467
- intRun = await measure("run", async () => integration.runId ? runById(api, slug, integration.runId, "integration") : await findReleaseRun(api, slug, { environment: "integration", head: integration.head }) ?? void 0, { environment: "integration" });
63468
- if (intRun && intRun.headSha === integration.head) {
63469
- let updated = { ...integration, runId: intRun.runId, runAttempt: intRun.runAttempt };
63470
- if (integration.runAttempt !== intRun.runAttempt) updated = { ...updated, verified: void 0, artifactId: void 0, confirmation: void 0 };
63471
- if (intRun.status === "completed" && intRun.conclusion === "success" && !updated.verified) {
63506
+ const intRunRead = (async () => {
63507
+ if (!integration) return void 0;
63508
+ const intRun2 = await measure("run", async () => integration.runId ? runById(api, slug, integration.runId, "integration", void 0, completedJobs) : await findReleaseRun(api, slug, { environment: "integration", head: integration.head }, completedJobs) ?? void 0, { environment: "integration" });
63509
+ if (intRun2 && intRun2.headSha === integration.head) {
63510
+ let updated = { ...integration, runId: intRun2.runId, runAttempt: intRun2.runAttempt };
63511
+ if (integration.runAttempt !== intRun2.runAttempt) updated = { ...updated, verified: void 0, artifactId: void 0, confirmation: void 0 };
63512
+ if (intRun2.status === "completed" && intRun2.conclusion === "success" && !updated.verified) {
63472
63513
  try {
63473
- const verifiedRun = intRun;
63514
+ const verifiedRun = intRun2;
63474
63515
  const result = await measure("artifact", () => readVerifiedRelease(api, slug, verifiedRun));
63475
63516
  updated = { ...updated, artifactId: result.artifactId, verified: result.release };
63476
63517
  } catch {
@@ -63481,35 +63522,58 @@ function buildDeployHandlers(deps) {
63481
63522
  await writeScanFile(dir, file);
63482
63523
  }
63483
63524
  }
63484
- }
63485
- const promotion = file.promotions.at(-1);
63486
- const source = promotion && file.releases.find((r2) => r2.id === promotion.releaseId);
63487
- if (!historical && promotion?.verified && source && ["dispatched", "dispatching"].includes(promotion.phase)) {
63488
- await measure("promotion", () => continuePromotion(personaId2, { ...source, verified: promotion.verified }, promotion, false, api, async () => (await observe("production")).image));
63489
- file = await readHistory(dir);
63490
- }
63491
- const latestPromotion = file.promotions.at(-1);
63492
- let prodRun;
63493
- if (historical && selected?.environment === "production" && !selected.legacy && selected.runId) {
63494
- prodRun = await measure("run", () => runById(api, slug, selected.runId, "production", file.promotions.find((p3) => p3.id + "-production" === selected.id)?.id), { environment: "production" });
63495
- if (prodRun?.headSha !== selected.head) prodRun = void 0;
63496
- } else if (!historical && latestPromotion) {
63497
- const release2 = file.releases.find((r2) => r2.id === latestPromotion.releaseId);
63498
- if (release2) prodRun = await measure("run", async () => await findReleaseRun(api, slug, { environment: "production", head: release2.head, promotionId: latestPromotion.id }) ?? void 0, { environment: "production" });
63499
- }
63500
- const loadTarget = async (environment2, targetRun) => {
63501
- if (historical) return targetRun ? { run: targetRun } : {};
63502
- let targetSecretsList;
63503
- try {
63504
- targetSecretsList = await measure("secrets", () => targetSecrets(personaId2, dir, api, environment2), { environment: environment2 });
63505
- } catch {
63525
+ return intRun2;
63526
+ })();
63527
+ const prodRunRead = (async () => {
63528
+ const pending2 = file.promotions.at(-1);
63529
+ if (!historical && pending2?.verified && ["dispatched", "dispatching"].includes(pending2.phase)) {
63530
+ await intRunRead;
63531
+ const source = file.releases.find((r2) => r2.id === pending2.releaseId);
63532
+ if (source) {
63533
+ await measure("promotion", () => continuePromotion(personaId2, { ...source, verified: pending2.verified }, pending2, false, api, async () => (await observe("production")).image));
63534
+ file = await readHistory(dir);
63535
+ }
63536
+ }
63537
+ const latestPromotion = file.promotions.at(-1);
63538
+ if (historical && selected?.environment === "production" && !selected.legacy && selected.runId) {
63539
+ const prodRun2 = await measure("run", () => runById(api, slug, selected.runId, "production", file.promotions.find((p3) => p3.id + "-production" === selected.id)?.id, completedJobs), { environment: "production" });
63540
+ return prodRun2?.headSha !== selected.head ? void 0 : prodRun2;
63541
+ }
63542
+ if (!historical && latestPromotion) {
63543
+ const release2 = file.releases.find((r2) => r2.id === latestPromotion.releaseId);
63544
+ if (release2) return measure("run", async () => {
63545
+ const key = personaId2 + ":" + latestPromotion.id;
63546
+ const knownId = productionRunIds.get(key);
63547
+ const found = (knownId ? await runById(api, slug, knownId, "production", latestPromotion.id, completedJobs) : void 0) ?? await findReleaseRun(api, slug, { environment: "production", head: release2.head, promotionId: latestPromotion.id }, completedJobs) ?? void 0;
63548
+ if (found) productionRunIds.set(key, found.runId);
63549
+ return found;
63550
+ }, { environment: "production" });
63506
63551
  }
63507
- const targetUnpublish = await measure("unpublish", () => cachedUnpublish(personaId2, api, slug, environment2), { environment: environment2 });
63552
+ return void 0;
63553
+ })();
63554
+ const loadTarget = async (environment2, runRead) => {
63555
+ if (historical) {
63556
+ const targetRun2 = await runRead;
63557
+ return targetRun2 ? { run: targetRun2 } : {};
63558
+ }
63559
+ const [targetRun, targetSecretsList, targetUnpublish] = await Promise.all([
63560
+ runRead,
63561
+ measure("secrets", () => targetSecrets(personaId2, dir, api, environment2), { environment: environment2 }).catch(
63562
+ () => void 0
63563
+ /* unknown stays unknown */
63564
+ ),
63565
+ measure("unpublish", () => cachedUnpublish(personaId2, api, slug, environment2), { environment: environment2 })
63566
+ ]);
63567
+ const latestPromotion = file.promotions.at(-1);
63508
63568
  const cloud = file.releases.some((r2) => r2.environment === environment2) || environment2 === "production" && latestPromotion ? await measure("cloud", () => cachedCloud(personaId2, environment2, targetRun, targetUnpublish, cloudName, () => observe(environment2), snapshots.has(environment2)), { environment: environment2 }) : {};
63509
63569
  const { image, online: targetOnline } = cloud;
63510
63570
  return { ...targetUnpublish ? { unpublish: targetUnpublish } : {}, ...targetRun ? { run: targetRun } : {}, ...targetSecretsList ? { secrets: targetSecretsList } : {}, ...image ? { image } : {}, ...targetOnline !== void 0 ? { online: targetOnline } : {} };
63511
63571
  };
63512
- const [intTarget, prodTarget] = await Promise.all([loadTarget("integration", intRun), loadTarget("production", prodRun ?? (latestProductionRelease(file.releases)?.legacy ? run : void 0))]);
63572
+ const productionRunRead = Promise.all([prodRunRead, legacyRunRead]).then(([prodRun2, legacyRun2]) => prodRun2 ?? (latestProductionRelease(file.releases)?.legacy ? legacyRun2 : void 0));
63573
+ const settled = await Promise.allSettled([loadTarget("integration", intRunRead), loadTarget("production", productionRunRead), intRunRead, prodRunRead, legacyRunRead]);
63574
+ const failure = settled.find((r2) => r2.status === "rejected");
63575
+ if (failure) throw failure.reason;
63576
+ const [intTarget, prodTarget, intRun, prodRun, legacyRun] = settled.map((r2) => r2.value);
63513
63577
  targets.integration = intTarget;
63514
63578
  targets.production = prodTarget;
63515
63579
  if (!historical) {
@@ -63517,21 +63581,10 @@ function buildDeployHandlers(deps) {
63517
63581
  unpublish = prodTarget.unpublish;
63518
63582
  secrets = prodTarget.secrets;
63519
63583
  }
63520
- run = historical ? selected?.environment === "integration" ? intRun : prodRun ?? run : prodTarget.run;
63584
+ run = historical ? selected?.environment === "integration" ? intRun : prodRun ?? legacyRun : prodTarget.run;
63521
63585
  }
63522
63586
  if (!historical && latestProductionRelease(file.releases) && (!api || github.status !== "authorized")) online = (await measure("cloud", () => cachedCloud(personaId2, "production", run, unpublish, repo2 ? cloudPersonaIdOf(repo2.url) : personaId2), { environment: "production" })).online;
63523
- let publisherFeishuAuth;
63524
- if (scans.at(-1)?.manifest.connectors.some(isFeishuPublisherConnector)) {
63525
- const query2 = async (environment2) => {
63526
- try {
63527
- return await measure("feishu.auth", () => deps.publisherFeishuAuth(repo2 ? cloudPersonaIdOf(repo2.url) : personaId2, environment2), { environment: environment2 });
63528
- } catch (e) {
63529
- return { connected: false, error: e instanceof Error ? e.message : "\u98DE\u4E66\u6388\u6743\u72B6\u6001\u67E5\u8BE2\u5931\u8D25" };
63530
- }
63531
- };
63532
- const [integration, production] = await Promise.all([query2("integration"), query2("production")]);
63533
- publisherFeishuAuth = { integration, production };
63534
- }
63587
+ const publisherFeishuAuth = await publisherFeishuAuthRead;
63535
63588
  return {
63536
63589
  personaId: personaId2,
63537
63590
  github,
@@ -63680,7 +63733,12 @@ function buildDeployHandlers(deps) {
63680
63733
  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");
63681
63734
  writes = [[ENGINE_AUTH_SECRETS.apiKey, apiKey], [ENGINE_AUTH_SECRETS.baseUrl, baseUrl]];
63682
63735
  }
63683
- const { api } = await requireGithub();
63736
+ const { auth: githubAuth, api } = await requireGithub();
63737
+ try {
63738
+ await ensureRepo(deps.exec, api, { dir, org: deps.org, personaId: args.personaId, auth: githubAuth });
63739
+ } catch (err) {
63740
+ throw toClawdError(err);
63741
+ }
63684
63742
  const before = await readHistory(dir);
63685
63743
  await writeScanFile(dir, { ...before, engineChannels: { ...before.engineChannels, [args.environment]: null } });
63686
63744
  try {
@@ -63965,7 +64023,7 @@ function buildDeployHandlers(deps) {
63965
64023
  throw new ClawdError(ERROR_CODES.INTERNAL, err instanceof Error ? err.message : String(err));
63966
64024
  }
63967
64025
  unpublishCache.delete(personaId2 + ":" + environment);
63968
- cloudCache.delete(personaId2 + ":" + environment);
64026
+ invalidateCloud(personaId2 + ":" + environment);
63969
64027
  return { response: { type: "deploy:unpublish", before: before?.runId ?? null } };
63970
64028
  };
63971
64029
  function releaseArgs(frame, schema) {
@@ -74650,7 +74708,7 @@ function computeMethodAccess(args) {
74650
74708
  }
74651
74709
 
74652
74710
  // src/version.ts
74653
- var version = "0.2.659".length > 0 ? "0.2.659" : "dev";
74711
+ var version = "0.2.661".length > 0 ? "0.2.661" : "dev";
74654
74712
 
74655
74713
  // src/cli-probe/probe.ts
74656
74714
  var fs85 = __toESM(require("fs"), 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.659",
3
+ "version": "0.2.661",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",