@clawos-dev/clawd 0.2.653 → 0.2.655

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 +67 -30
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -57093,6 +57093,7 @@ function buildShiftInternalHandlers(deps) {
57093
57093
 
57094
57094
  // src/handlers/deploy.ts
57095
57095
  var import_node_crypto14 = require("crypto");
57096
+ var import_node_perf_hooks = require("perf_hooks");
57096
57097
 
57097
57098
  // src/deploy/persona-test.ts
57098
57099
  var import_node_fs33 = __toESM(require("fs"), 1);
@@ -62855,6 +62856,7 @@ function reconcileInterruptedScans(deps) {
62855
62856
  var SECRETS_CACHE_MS = 2e4;
62856
62857
  var RUN_CACHE_MS = 4e3;
62857
62858
  var ONLINE_CACHE_MS = 2e4;
62859
+ var directRead = async (_stage, action) => action();
62858
62860
  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";
62859
62861
  function ensureOwner(ctx) {
62860
62862
  if (!ctx || ctx.principal.kind !== "owner") {
@@ -62995,12 +62997,12 @@ function buildDeployHandlers(deps) {
62995
62997
  for (const env of ["integration", "production"]) secretsCache.delete(personaId2 + ":" + env);
62996
62998
  secretsCache.delete(personaId2);
62997
62999
  }
62998
- async function stateOf(personaId2, selection = {}) {
63000
+ async function stateOf(personaId2, selection = {}, measure = directRead) {
62999
63001
  const { releaseHead, releaseId, environment } = selection;
63000
63002
  const historical = releaseHead !== void 0 || releaseId !== void 0;
63001
63003
  const dir = deps.personaDir(personaId2);
63002
- const repo2 = await repoInfo(deps.exec, dir);
63003
- const github = await deps.githubIdentity.status();
63004
+ const repo2 = await measure("repo", () => repoInfo(deps.exec, dir));
63005
+ const github = await measure("github.identity", () => deps.githubIdentity.status());
63004
63006
  const auth = deps.githubIdentity.cached();
63005
63007
  const rawApi = auth ? deps.githubApi(auth.token) : void 0;
63006
63008
  const requests = /* @__PURE__ */ new Map();
@@ -63008,11 +63010,18 @@ function buildDeployHandlers(deps) {
63008
63010
  const key = (strict ? "strict:" : "") + url;
63009
63011
  const hit = requests.get(key);
63010
63012
  if (hit) return hit;
63011
- const promise = strict ? rawApi.getJsonStrict(url) : rawApi.getJson(url);
63013
+ const resource = url.includes("clawd-unpublish.yml") ? "unpublish" : url.includes("/artifacts") ? "artifacts" : url.includes("/jobs") ? "jobs" : url.includes("/runs?") ? "runs" : url.includes("/runs/") ? "run" : "other";
63014
+ const promise = measure("github.read", () => strict ? rawApi.getJsonStrict(url) : rawApi.getJson(url), { resource });
63012
63015
  requests.set(key, promise);
63013
63016
  return promise;
63014
63017
  };
63015
- const api = rawApi ? { ...rawApi, getJson: (url) => query(url), getJsonStrict: (url) => query(url, true) } : void 0;
63018
+ const api = rawApi ? {
63019
+ ...rawApi,
63020
+ getJson: (url) => query(url),
63021
+ getJsonStrict: (url) => query(url, true),
63022
+ listSecrets: (slug, environment2) => measure("github.secrets", () => rawApi.listSecrets(slug, environment2), { environment: environment2, resource: environment2 ? "environment" : "repository" }),
63023
+ downloadArtifact: (slug, artifactId) => measure("github.artifact-download", () => rawApi.downloadArtifact(slug, artifactId))
63024
+ } : void 0;
63016
63025
  const snapshots = /* @__PURE__ */ new Map();
63017
63026
  const observe = (environment2) => {
63018
63027
  let promise = snapshots.get(environment2);
@@ -63025,11 +63034,11 @@ function buildDeployHandlers(deps) {
63025
63034
  let file = emptyScanFile();
63026
63035
  let historyError;
63027
63036
  try {
63028
- file = await readHistory(dir);
63037
+ file = await measure("history", () => readHistory(dir));
63029
63038
  } catch (err) {
63030
63039
  historyError = err instanceof Error ? err.message : String(err);
63031
63040
  }
63032
- file = await settleStale(personaId2, dir, file);
63041
+ file = await measure("history.settle", () => settleStale(personaId2, dir, file));
63033
63042
  const pending = file.promotions.at(-1);
63034
63043
  const bound = pending && file.releases.find((r2) => r2.id === pending.releaseId);
63035
63044
  if (!historical && pending && !pending.verified && !["completed", "failed"].includes(pending.phase) && bound?.verified && bound.confirmation?.fingerprint === bound.verified.verification.fingerprint) {
@@ -63043,8 +63052,8 @@ function buildDeployHandlers(deps) {
63043
63052
  let unpublish;
63044
63053
  if (repo2 && api && github.status === "authorized") {
63045
63054
  const legacy = historical ? selected : latestProductionRelease(file.releases);
63046
- run = legacy?.legacy ? await cachedRun(personaId2, api, repoSlug(repo2.url), legacy.head) : void 0;
63047
- if (!historical) unpublish = await cachedUnpublish(personaId2, api, repoSlug(repo2.url));
63055
+ run = legacy?.legacy ? await measure("run", () => cachedRun(personaId2, api, repoSlug(repo2.url), legacy.head), { environment: legacy.environment }) : void 0;
63056
+ if (!historical) unpublish = await measure("unpublish", () => cachedUnpublish(personaId2, api, repoSlug(repo2.url)), { environment: "production" });
63048
63057
  }
63049
63058
  let online;
63050
63059
  const targets = {};
@@ -63053,13 +63062,14 @@ function buildDeployHandlers(deps) {
63053
63062
  const integration = historical ? selected?.environment === "integration" ? selected : void 0 : [...file.releases].reverse().find((r2) => r2.environment === "integration");
63054
63063
  let intRun;
63055
63064
  if (integration) {
63056
- intRun = integration.runId ? await runById(api, slug, integration.runId, "integration") : await findReleaseRun(api, slug, { environment: "integration", head: integration.head }) ?? void 0;
63065
+ 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" });
63057
63066
  if (intRun && intRun.headSha === integration.head) {
63058
63067
  let updated = { ...integration, runId: intRun.runId, runAttempt: intRun.runAttempt };
63059
63068
  if (integration.runAttempt !== intRun.runAttempt) updated = { ...updated, verified: void 0, artifactId: void 0, confirmation: void 0 };
63060
63069
  if (intRun.status === "completed" && intRun.conclusion === "success" && !updated.verified) {
63061
63070
  try {
63062
- const result = await readVerifiedRelease(api, slug, intRun);
63071
+ const verifiedRun = intRun;
63072
+ const result = await measure("artifact", () => readVerifiedRelease(api, slug, verifiedRun));
63063
63073
  updated = { ...updated, artifactId: result.artifactId, verified: result.release };
63064
63074
  } catch {
63065
63075
  }
@@ -63073,27 +63083,27 @@ function buildDeployHandlers(deps) {
63073
63083
  const promotion = file.promotions.at(-1);
63074
63084
  const source = promotion && file.releases.find((r2) => r2.id === promotion.releaseId);
63075
63085
  if (!historical && promotion?.verified && source && ["dispatched", "dispatching"].includes(promotion.phase)) {
63076
- await continuePromotion(personaId2, { ...source, verified: promotion.verified }, promotion, false, api, async () => (await observe("production")).image);
63086
+ await measure("promotion", () => continuePromotion(personaId2, { ...source, verified: promotion.verified }, promotion, false, api, async () => (await observe("production")).image));
63077
63087
  file = await readHistory(dir);
63078
63088
  }
63079
63089
  const latestPromotion = file.promotions.at(-1);
63080
63090
  let prodRun;
63081
63091
  if (historical && selected?.environment === "production" && !selected.legacy && selected.runId) {
63082
- prodRun = await runById(api, slug, selected.runId, "production", file.promotions.find((p3) => p3.id + "-production" === selected.id)?.id);
63092
+ prodRun = await measure("run", () => runById(api, slug, selected.runId, "production", file.promotions.find((p3) => p3.id + "-production" === selected.id)?.id), { environment: "production" });
63083
63093
  if (prodRun?.headSha !== selected.head) prodRun = void 0;
63084
63094
  } else if (!historical && latestPromotion) {
63085
63095
  const release2 = file.releases.find((r2) => r2.id === latestPromotion.releaseId);
63086
- if (release2) prodRun = await findReleaseRun(api, slug, { environment: "production", head: release2.head, promotionId: latestPromotion.id }) ?? void 0;
63096
+ if (release2) prodRun = await measure("run", async () => await findReleaseRun(api, slug, { environment: "production", head: release2.head, promotionId: latestPromotion.id }) ?? void 0, { environment: "production" });
63087
63097
  }
63088
63098
  const loadTarget = async (environment2, targetRun) => {
63089
63099
  if (historical) return targetRun ? { run: targetRun } : {};
63090
63100
  let targetSecretsList;
63091
63101
  try {
63092
- targetSecretsList = await targetSecrets(personaId2, dir, api, environment2);
63102
+ targetSecretsList = await measure("secrets", () => targetSecrets(personaId2, dir, api, environment2), { environment: environment2 });
63093
63103
  } catch {
63094
63104
  }
63095
- const targetUnpublish = await cachedUnpublish(personaId2, api, slug, environment2);
63096
- const cloud = file.releases.some((r2) => r2.environment === environment2) || environment2 === "production" && latestPromotion ? await cachedCloud(personaId2, environment2, targetRun, targetUnpublish, cloudName, () => observe(environment2), snapshots.has(environment2)) : {};
63105
+ const targetUnpublish = await measure("unpublish", () => cachedUnpublish(personaId2, api, slug, environment2), { environment: environment2 });
63106
+ 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 }) : {};
63097
63107
  const { image, online: targetOnline } = cloud;
63098
63108
  return { ...targetUnpublish ? { unpublish: targetUnpublish } : {}, ...targetRun ? { run: targetRun } : {}, ...targetSecretsList ? { secrets: targetSecretsList } : {}, ...image ? { image } : {}, ...targetOnline !== void 0 ? { online: targetOnline } : {} };
63099
63109
  };
@@ -63107,12 +63117,12 @@ function buildDeployHandlers(deps) {
63107
63117
  }
63108
63118
  run = historical ? selected?.environment === "integration" ? intRun : prodRun ?? run : prodTarget.run;
63109
63119
  }
63110
- if (!historical && latestProductionRelease(file.releases) && (!api || github.status !== "authorized")) online = (await cachedCloud(personaId2, "production", run, unpublish, repo2 ? cloudPersonaIdOf(repo2.url) : personaId2)).online;
63120
+ 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;
63111
63121
  let publisherFeishuAuth;
63112
63122
  if (scans.at(-1)?.manifest.connectors.some(isFeishuPublisherConnector)) {
63113
63123
  const query2 = async (environment2) => {
63114
63124
  try {
63115
- return await deps.publisherFeishuAuth(repo2 ? cloudPersonaIdOf(repo2.url) : personaId2, environment2);
63125
+ return await measure("feishu.auth", () => deps.publisherFeishuAuth(repo2 ? cloudPersonaIdOf(repo2.url) : personaId2, environment2), { environment: environment2 });
63116
63126
  } catch (e) {
63117
63127
  return { connected: false, error: e instanceof Error ? e.message : "\u98DE\u4E66\u6388\u6743\u72B6\u6001\u67E5\u8BE2\u5931\u8D25" };
63118
63128
  }
@@ -63136,8 +63146,8 @@ function buildDeployHandlers(deps) {
63136
63146
  ...historyError ? { historyError } : {}
63137
63147
  };
63138
63148
  }
63139
- const view = async (personaId2, selection) => ({
63140
- response: { type: "deploy:state", ...await stateOf(personaId2, selection) }
63149
+ const view = async (personaId2, selection, measure) => ({
63150
+ response: { type: "deploy:state", ...await stateOf(personaId2, selection, measure) }
63141
63151
  });
63142
63152
  async function beginScan(personaId2, dir, file, contentHead, want) {
63143
63153
  liveScans.set(personaId2, {});
@@ -63197,12 +63207,6 @@ function buildDeployHandlers(deps) {
63197
63207
  }));
63198
63208
  }
63199
63209
  }
63200
- const get = async (frame, _client, ctx) => {
63201
- ensureOwner(ctx);
63202
- const { personaId: personaId2, ...selection } = parseArgs2(DeployGetArgsSchema, frame, "deploy:get");
63203
- mustPersona(personaId2);
63204
- return view(personaId2, selection);
63205
- };
63206
63210
  const patch = async (frame, _client, ctx) => {
63207
63211
  ensureOwner(ctx);
63208
63212
  const args = parseArgs2(DeployPatchArgsSchema, frame, "deploy:patch");
@@ -63652,14 +63656,46 @@ function buildDeployHandlers(deps) {
63652
63656
  return { response: { type: "deploy:openTest", personaId: id, expectedImage: record4.verified.image } };
63653
63657
  };
63654
63658
  const getInFlight = /* @__PURE__ */ new Map();
63655
- const serialGet = serial(get);
63656
63659
  const coalescedGet = async (frame, client, ctx) => {
63657
63660
  ensureOwner(ctx);
63658
63661
  const args = parseArgs2(DeployGetArgsSchema, frame, "deploy:get");
63659
63662
  const key = JSON.stringify(args);
63660
63663
  const hit = getInFlight.get(key);
63661
63664
  if (hit) return hit;
63662
- const promise = serialGet(frame, client, ctx);
63665
+ const started = import_node_perf_hooks.performance.now();
63666
+ const traceId = (0, import_node_crypto14.randomUUID)();
63667
+ const log = (message, meta) => {
63668
+ try {
63669
+ deps.logger?.info(message, { personaId: args.personaId, traceId, ...meta });
63670
+ } catch {
63671
+ }
63672
+ };
63673
+ const measure = async (stage, action, details) => {
63674
+ const stageStarted = stage === "total" ? started : import_node_perf_hooks.performance.now();
63675
+ let status = "error";
63676
+ try {
63677
+ const result = await action();
63678
+ status = "ok";
63679
+ return result;
63680
+ } finally {
63681
+ const finished = import_node_perf_hooks.performance.now();
63682
+ log(stage === "total" ? "deploy.get.finished" : "deploy.get.stage", {
63683
+ stage,
63684
+ status,
63685
+ ...details,
63686
+ durationMs: Math.round((finished - stageStarted) * 100) / 100,
63687
+ elapsedMs: Math.round((finished - started) * 100) / 100
63688
+ });
63689
+ }
63690
+ };
63691
+ log("deploy.get.started", { historical: args.releaseHead !== void 0 || args.releaseId !== void 0, ...args.environment ? { environment: args.environment } : {} });
63692
+ const promise = measure("total", () => enqueue(args.personaId, async () => {
63693
+ const durationMs = Math.round((import_node_perf_hooks.performance.now() - started) * 100) / 100;
63694
+ log("deploy.get.stage", { stage: "queue", status: "ok", durationMs, elapsedMs: durationMs });
63695
+ const { personaId: personaId2, ...selection } = args;
63696
+ mustPersona(personaId2);
63697
+ return view(personaId2, selection, measure);
63698
+ }));
63663
63699
  getInFlight.set(key, promise);
63664
63700
  void promise.finally(() => {
63665
63701
  if (getInFlight.get(key) === promise) getInFlight.delete(key);
@@ -74493,7 +74529,7 @@ function computeMethodAccess(args) {
74493
74529
  }
74494
74530
 
74495
74531
  // src/version.ts
74496
- var version = "0.2.653".length > 0 ? "0.2.653" : "dev";
74532
+ var version = "0.2.655".length > 0 ? "0.2.655" : "dev";
74497
74533
 
74498
74534
  // src/cli-probe/probe.ts
74499
74535
  var fs85 = __toESM(require("fs"), 1);
@@ -78146,6 +78182,7 @@ async function startDaemon(config) {
78146
78182
  },
78147
78183
  now: () => Date.now(),
78148
78184
  warn: (msg, meta) => logger.warn(msg, meta),
78185
+ logger,
78149
78186
  // 在不在线上 = gateway 正式登记表里有没有它(design 2026-09-24-deploy-unpublish §3.3):跟 persona 列表的云卡片同一个来源。
78150
78187
  // 拉不到(没登录飞书 / gateway 不通 / healthz 5s 没回)→ undefined,页面不给下线按钮也不撤「线上」标。
78151
78188
  // 失败上界:中心那一跳自带 15s,healthz 这一趟 5s——deploy:get 要保证页面打得开,gateway 接了连接不回时不能挂到 undici 默认的 300s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.653",
3
+ "version": "0.2.655",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",