@lumi-ai-lab/harness-data 0.0.11 → 0.0.13

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumi-ai-lab/harness-data",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Installer and updater for Harness Data",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,6 +6,7 @@ import { ask, askSecret, chooseAgent } from "../lib/prompt.js";
6
6
  import { resolveWorkspaceDir, writeState } from "../lib/paths.js";
7
7
  import { installToolsFromManifest, manifestDigest, readManifest } from "../lib/manifest.js";
8
8
  import { binaryName, platformKey } from "../lib/platform.js";
9
+ import { resolveLatestManifest } from "../lib/tool-release.js";
9
10
  import { collectDoctor } from "./doctor.js";
10
11
  import { packageVersion } from "../lib/package.js";
11
12
  import { downloadReleaseAsset, findReleaseAsset, githubToken, hasGithubAuth, latestRelease } from "../lib/github.js";
@@ -236,10 +237,13 @@ export async function installCommand(options = {}) {
236
237
  let manifest;
237
238
  let localTools = {};
238
239
  if (tokenMode) {
239
- manifest = await installToolsFromManifest(runtimeDir, manifestPath, options);
240
+ manifest = readManifest(manifestPath);
241
+ const latestManifest = await resolveLatestManifest(manifest, key, options);
242
+ manifest = await installToolsFromManifest(runtimeDir, manifestPath, { ...options, manifestOverride: latestManifest });
240
243
  } else {
241
244
  manifest = readManifest(manifestPath);
242
- await installToolsFromManifest(runtimeDir, manifestPath, { ...options, tools: ["data-harness-cli"] });
245
+ const latestManifest = await resolveLatestManifest(manifest, key, { ...options, tools: ["data-harness-cli"] });
246
+ await installToolsFromManifest(runtimeDir, manifestPath, { ...options, manifestOverride: latestManifest });
243
247
  localTools = await installLocalTools(runtimeDir, options);
244
248
  }
245
249
  ok(`${Object.keys(manifest.installedTools || {}).length + Object.keys(localTools).length} 个 CLI 已安装到 bin/`);
@@ -7,6 +7,8 @@ import { installToolsFromManifest, manifestDigest, readManifest } from "../lib/m
7
7
  import { packageVersion } from "../lib/package.js";
8
8
  import { platformKey } from "../lib/platform.js";
9
9
  import { githubToken, latestRelease } from "../lib/github.js";
10
+ import { resolveLatestTool } from "../lib/tool-release.js";
11
+ import { protocolFromUrl, runGitWithProtocol } from "../lib/git-auth.js";
10
12
  import { buildAndCheck, installRuntimeBundle, printDoctorSummary } from "./install.js";
11
13
  import { collectDoctor } from "./doctor.js";
12
14
  import { action, blank, header, ok, shortSha, skip, step, warn } from "../lib/log.js";
@@ -22,48 +24,17 @@ async function npmLatest() {
22
24
  }
23
25
  }
24
26
 
25
- function archiveSuffix(url) {
26
- if (url.endsWith(".zip")) return "zip";
27
- if (url.endsWith(".tar.gz")) return "tar.gz";
28
- return "";
29
- }
30
-
31
- function toolAssetName(tool, tag, key) {
32
- const current = tool.platforms?.[key]?.url || "";
33
- const suffix = archiveSuffix(current) || (key.startsWith("windows-") ? "zip" : "tar.gz");
34
- return `${tool.binary}-${tag}-${key}.${suffix}`;
35
- }
36
-
37
- function releaseAsset(release, name) {
38
- return (release.assets || []).find((asset) => asset.name === name);
39
- }
40
-
41
- function oneToolManifest(manifest, tool, tag, asset, key) {
27
+ function oneToolManifest(manifest, tool) {
42
28
  return {
43
29
  ...manifest,
44
- tools: [{
45
- ...tool,
46
- version: tag,
47
- platforms: {
48
- [key]: {
49
- url: asset.browser_download_url || `https://github.com/${tool.repo}/releases/download/${tag}/${asset.name}`,
50
- sha256: ""
51
- }
52
- }
53
- }]
30
+ tools: [tool]
54
31
  };
55
32
  }
56
33
 
57
34
  async function maybeUpdateTool(runtimeDir, manifest, tool, options, state) {
58
35
  const key = platformKey();
59
- const release = await latestRelease(tool.repo, options);
60
- const tag = release.tag_name;
61
- const assetName = toolAssetName(tool, tag, key);
62
- const asset = releaseAsset(release, assetName);
63
- if (!asset) {
64
- warn(`${tool.name} 最新 release 缺少 ${assetName},已跳过`);
65
- return null;
66
- }
36
+ const latestTool = await resolveLatestTool(tool, key, options);
37
+ const tag = latestTool.version;
67
38
  const current = state.tools?.[tool.name] || {};
68
39
  const tagChanged = current.version && current.version !== tag;
69
40
  const firstInstall = !current.version;
@@ -77,17 +48,24 @@ async function maybeUpdateTool(runtimeDir, manifest, tool, options, state) {
77
48
  options.skippedUpdates?.push(`${tool.name} ${tag}`);
78
49
  return null;
79
50
  }
80
- const updatedManifest = oneToolManifest(manifest, tool, tag, asset, key);
51
+ const updatedManifest = oneToolManifest(manifest, latestTool);
81
52
  const installed = await installToolsFromManifest(runtimeDir, path.join(runtimeDir, ".bootstrap-cache", `${tool.name}-manifest.json`), {
82
53
  ...options,
83
54
  manifestOverride: updatedManifest
84
55
  });
85
- const result = installed.installedTools?.[tool.name] || { version: tag, asset: assetName };
56
+ const result = installed.installedTools?.[tool.name] || { version: tag };
86
57
  ok(`${tool.name} 已更新到 ${tag}`);
87
58
  return result;
88
59
  }
89
60
 
90
- async function updateWikis(runtimeDir, options, state) {
61
+ async function updateWikisGit(wikisDir, args, options) {
62
+ const remote = (await run("git", ["-C", wikisDir, "remote", "get-url", "origin"], { ...options, allowFailure: true })).stdout.trim();
63
+ const protocol = protocolFromUrl(remote);
64
+ if (!protocol) return run("git", ["-C", wikisDir, ...args], options);
65
+ return runGitWithProtocol(protocol, ["-C", wikisDir, ...args], options);
66
+ }
67
+
68
+ export async function updateWikis(runtimeDir, options, state) {
91
69
  const wikisDir = path.join(runtimeDir, "wikis");
92
70
  if (!githubToken(options) && state.installMode !== "github-token") {
93
71
  skip("harness-data-wikis 为本地路径模式,请手动检查");
@@ -97,9 +75,9 @@ async function updateWikis(runtimeDir, options, state) {
97
75
  skip("harness-data-wikis 不是 git checkout");
98
76
  return null;
99
77
  }
100
- await run("git", ["-C", wikisDir, "fetch", "origin"]);
101
- const local = (await run("git", ["-C", wikisDir, "rev-parse", "HEAD"])).stdout.trim();
102
- const remote = (await run("git", ["-C", wikisDir, "rev-parse", "origin/HEAD"], { allowFailure: true })).stdout.trim();
78
+ await updateWikisGit(wikisDir, ["fetch", "origin"], options);
79
+ const local = (await run("git", ["-C", wikisDir, "rev-parse", "HEAD"], options)).stdout.trim();
80
+ const remote = (await run("git", ["-C", wikisDir, "rev-parse", "origin/HEAD"], { ...options, allowFailure: true })).stdout.trim();
103
81
  if (!remote || local === remote) {
104
82
  ok(`harness-data-wikis 已是最新 ${shortSha(local)}`);
105
83
  return null;
@@ -110,8 +88,8 @@ async function updateWikis(runtimeDir, options, state) {
110
88
  options.skippedUpdates?.push(`harness-data-wikis ${shortSha(remote)}`);
111
89
  return null;
112
90
  }
113
- await run("git", ["-C", wikisDir, "pull", "--ff-only"]);
114
- const commit = (await run("git", ["-C", wikisDir, "rev-parse", "HEAD"])).stdout.trim();
91
+ await updateWikisGit(wikisDir, ["pull", "--ff-only"], options);
92
+ const commit = (await run("git", ["-C", wikisDir, "rev-parse", "HEAD"], options)).stdout.trim();
115
93
  ok(`harness-data-wikis 已更新到 ${shortSha(commit)}`);
116
94
  return { commit };
117
95
  }
@@ -0,0 +1,47 @@
1
+ import { latestRelease } from "./github.js";
2
+
3
+ function archiveSuffix(asset, key) {
4
+ if (asset?.archive) return asset.archive;
5
+ if (asset?.url?.endsWith(".zip")) return "zip";
6
+ if (asset?.url?.endsWith(".tar.gz")) return "tar.gz";
7
+ return key.startsWith("windows-") ? "zip" : "tar.gz";
8
+ }
9
+
10
+ export function toolAssetName(tool, tag, key) {
11
+ const suffix = archiveSuffix(tool.platforms?.[key], key);
12
+ return `${tool.binary}-${tag}-${key}.${suffix}`;
13
+ }
14
+
15
+ export function releaseAsset(release, name) {
16
+ return (release.assets || []).find((asset) => asset.name === name);
17
+ }
18
+
19
+ export async function resolveLatestTool(tool, key, options = {}) {
20
+ const release = await latestRelease(tool.repo, options);
21
+ const tag = release.tag_name;
22
+ const name = toolAssetName(tool, tag, key);
23
+ const asset = releaseAsset(release, name);
24
+ if (!asset) {
25
+ throw new Error(`${tool.name} latest release ${tag} missing ${key} asset in ${tool.repo}: ${name}`);
26
+ }
27
+ return {
28
+ ...tool,
29
+ version: tag,
30
+ platforms: {
31
+ [key]: {
32
+ url: asset.browser_download_url || `https://github.com/${tool.repo}/releases/download/${tag}/${asset.name}`,
33
+ sha256: ""
34
+ }
35
+ }
36
+ };
37
+ }
38
+
39
+ export async function resolveLatestManifest(manifest, key, options = {}) {
40
+ const only = options.tools ? new Set(options.tools) : null;
41
+ const tools = [];
42
+ for (const tool of manifest.tools || []) {
43
+ if (only && !only.has(tool.name)) continue;
44
+ tools.push(await resolveLatestTool(tool, key, options));
45
+ }
46
+ return { ...manifest, tools };
47
+ }