




















@@ -65,10 +65,19 @@ interface NpmUpdateSummary {
6565packageSpec: string;
6666updateTarget: string;
6767updateExpected: string;
68+updateTargetBuildCommit: string;
69+updateTargetPackageVersion: string;
70+updateTargetTarball: string;
6871provider: Provider;
6972latestVersion: string;
7073currentHead: string;
7174runDir: string;
75+slowestTiming?: {
76+durationMs: number;
77+label: string;
78+phase: "fresh" | "fresh-target" | "update";
79+};
80+totalDurationMs: number;
7281fresh: Record<Platform, string>;
7382freshTarget: Record<Platform, string>;
7483freshTargetSpec: string;
@@ -184,6 +193,13 @@ function platformRecord<T>(value: T): Record<Platform, T> {
184193return { linux: value, macos: value, windows: value };
185194}
186195196+function formatDuration(durationMs: number): string {
197+const seconds = Math.round(durationMs / 1000);
198+const minutes = Math.floor(seconds / 60);
199+const remainder = seconds % 60;
200+return minutes > 0 ? `${minutes}m ${remainder}s` : `${remainder}s`;
201+}
202+187203class NpmUpdateSmoke {
188204private auth: ProviderAuth;
189205private windowsAuth: ProviderAuth;
@@ -197,8 +213,12 @@ class NpmUpdateSmoke {
197213private server: HostServer | null = null;
198214private artifact: PackageArtifact | null = null;
199215private freshTargetSpec = "";
216+private startedAt = Date.now();
217+private updateTargetBuildCommit = "";
200218private updateTargetEffective = "";
201219private updateExpectedNeedle = "";
220+private updateTargetPackageVersion = "";
221+private updateTargetTarball = "";
202222private linuxVm = linuxVmDefault;
203223204224private freshStatus = platformRecord("skip");
@@ -221,6 +241,7 @@ class NpmUpdateSmoke {
221241}
222242223243async run(): Promise<void> {
244+this.startedAt = Date.now();
224245this.runDir = await makeTempDir("openclaw-parallels-npm-update.");
225246this.tgzDir = await makeTempDir("openclaw-parallels-npm-update-tgz.");
226247try {
@@ -394,12 +415,76 @@ class NpmUpdateSmoke {
394415});
395416this.updateTargetEffective = this.server.urlFor(this.artifact.path);
396417this.updateExpectedNeedle = this.currentHeadShort;
418+this.updateTargetPackageVersion = this.artifact.version ?? "";
419+this.updateTargetBuildCommit =
420+this.artifact.buildCommitShort ?? this.artifact.buildCommit ?? "";
421+this.updateTargetTarball = this.updateTargetEffective;
397422return;
398423}
399424this.updateTargetEffective = this.options.updateTarget;
400425this.updateExpectedNeedle = this.isExplicitPackageTarget(this.updateTargetEffective)
401426 ? ""
402427 : resolveOpenClawRegistryVersion(this.updateTargetEffective) || this.updateTargetEffective;
428+const metadata = this.resolveRegistryPackageMetadata(this.updateTargetEffective);
429+this.updateTargetPackageVersion = metadata.version;
430+this.updateTargetBuildCommit =
431+metadata.gitHead || this.resolvePackageBuildCommit(metadata.tarball);
432+this.updateTargetTarball = metadata.tarball;
433+}
434+435+private resolvePackageBuildCommit(tarball: string): string {
436+if (!tarball) {
437+return "";
438+}
439+const output = run(
440+"bash",
441+["-lc", `curl -fsSL ${shellQuote(tarball)} | tar -xzOf - package/dist/build-info.json`],
442+{
443+check: false,
444+quiet: true,
445+},
446+).stdout.trim();
447+if (!output) {
448+return "";
449+}
450+try {
451+const parsed = JSON.parse(output) as { commit?: string };
452+return parsed.commit ? parsed.commit.slice(0, 7) : "";
453+} catch {
454+return "";
455+}
456+}
457+458+private resolveRegistryPackageMetadata(target: string): {
459+gitHead: string;
460+tarball: string;
461+version: string;
462+} {
463+if (this.isExplicitPackageTarget(target)) {
464+return { gitHead: "", tarball: "", version: "" };
465+}
466+const spec = target.startsWith("openclaw@") ? target : `openclaw@${target}`;
467+const output = run("npm", ["view", spec, "version", "dist.tarball", "gitHead", "--json"], {
468+check: false,
469+quiet: true,
470+}).stdout.trim();
471+if (!output) {
472+return { gitHead: "", tarball: "", version: "" };
473+}
474+try {
475+const parsed = JSON.parse(output) as {
476+dist?: { tarball?: string };
477+gitHead?: string;
478+version?: string;
479+};
480+return {
481+gitHead: parsed.gitHead ?? "",
482+tarball: parsed.dist?.tarball ?? "",
483+version: parsed.version ?? "",
484+};
485+} catch {
486+return { gitHead: "", tarball: "", version: "" };
487+}
403488}
404489405490private async runSameGuestUpdates(): Promise<void> {
@@ -900,6 +985,7 @@ class NpmUpdateSmoke {
900985}
901986902987private async writeSummary(): Promise<string> {
988+const slowestTiming = this.timings.toSorted((a, b) => b.durationMs - a.durationMs)[0];
903989const summary: NpmUpdateSummary = {
904990currentHead: this.currentHeadShort,
905991fresh: this.freshStatus,
@@ -915,7 +1001,18 @@ class NpmUpdateSmoke {
9151001windows: { status: this.updateStatus.windows, version: this.updateVersion.windows },
9161002},
9171003timings: this.timings,
1004+slowestTiming: slowestTiming
1005+ ? {
1006+durationMs: slowestTiming.durationMs,
1007+label: slowestTiming.label,
1008+phase: slowestTiming.phase,
1009+}
1010+ : undefined,
1011+totalDurationMs: Date.now() - this.startedAt,
9181012updateExpected: this.updateExpectedNeedle,
1013+updateTargetBuildCommit: this.updateTargetBuildCommit,
1014+updateTargetPackageVersion: this.updateTargetPackageVersion,
1015+updateTargetTarball: this.updateTargetTarball,
9191016updateTarget: this.updateTargetEffective,
9201017};
9211018const summaryPath = path.join(this.runDir, "summary.json");
@@ -924,10 +1021,14 @@ class NpmUpdateSmoke {
9241021lines: [
9251022`- package spec: ${summary.packageSpec}`,
9261023`- update target: ${summary.updateTarget}`,
1024+`- update target package: ${summary.updateTargetPackageVersion || "unknown"}${summary.updateTargetBuildCommit ? ` (${summary.updateTargetBuildCommit})` : ""}`,
1025+`- update target tarball: ${summary.updateTargetTarball || "n/a"}`,
9271026`- update expected: ${summary.updateExpected}`,
9281027`- fresh: macOS=${summary.fresh.macos}, Windows=${summary.fresh.windows}, Linux=${summary.fresh.linux}`,
9291028`- update: macOS=${summary.update.macos.status} (${summary.update.macos.version}), Windows=${summary.update.windows.status} (${summary.update.windows.version}), Linux=${summary.update.linux.status} (${summary.update.linux.version})`,
9301029`- fresh target: ${summary.freshTargetSpec || "skip"} macOS=${summary.freshTarget.macos}, Windows=${summary.freshTarget.windows}, Linux=${summary.freshTarget.linux}`,
1030+`- wall clock: ${formatDuration(summary.totalDurationMs)}`,
1031+`- slowest phase: ${summary.slowestTiming ? `${summary.slowestTiming.phase}/${summary.slowestTiming.label} ${formatDuration(summary.slowestTiming.durationMs)}` : "n/a"}`,
9311032`- logs: ${summary.runDir}`,
9321033],
9331034 summaryPath,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。