@lumi-ai-lab/harness-data 0.0.7 → 0.0.10
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/README.md +1 -1
- package/package.json +1 -1
- package/src/cli.js +1 -0
- package/src/commands/doctor.js +7 -1
- package/src/commands/install.js +2 -2
- package/src/lib/config.js +22 -4
- package/src/lib/prompt.js +4 -5
package/README.md
CHANGED
|
@@ -40,4 +40,4 @@ npx @lumi-ai-lab/harness-data doctor
|
|
|
40
40
|
|
|
41
41
|
The runtime is assembled from the `harness-data` runtime bundle, platform-specific CLI Release assets, `harness-data-wikis`, generated local config, CAS credentials, and selected Agent symlinks.
|
|
42
42
|
|
|
43
|
-
`--agent` supports `claude`, `codex`, `pi`, and `all`; the default is `all`.
|
|
43
|
+
`--agent` supports `claude`, `codex`, `pi`, `openclaw`, `hermes`, `both`, and `all`; the default is `all`. `both` installs Claude + Codex, while `all` installs Claude + Codex + Pi + OpenClaw + Hermes.
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -43,6 +43,7 @@ Commands:
|
|
|
43
43
|
|
|
44
44
|
Install options:
|
|
45
45
|
--dir PATH Runtime directory (default: current directory)
|
|
46
|
+
--agent NAME claude, codex, pi, openclaw, hermes, both, or all
|
|
46
47
|
--github-token TOKEN GitHub token for private Release assets`);
|
|
47
48
|
if (unknown) process.exitCode = 1;
|
|
48
49
|
}
|
package/src/commands/doctor.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { run } from "../lib/exec.js";
|
|
4
4
|
import { findWorkspaceDir } from "../lib/paths.js";
|
|
5
5
|
import { binaryName } from "../lib/platform.js";
|
|
6
|
+
import { concreteAgentNames } from "../lib/config.js";
|
|
6
7
|
|
|
7
8
|
function existsExecutable(file) {
|
|
8
9
|
try {
|
|
@@ -67,7 +68,12 @@ export async function collectDoctor(workspace, options = {}) {
|
|
|
67
68
|
add("CAS credentials file", jsonFileValid(path.join(casConfigDir, "config.json")), casConfigDir);
|
|
68
69
|
add("CMR token", await tokenCheck(workspace, "qdm-cmr-cli", env));
|
|
69
70
|
add("Indicators token", await tokenCheck(workspace, "qdm-indicators-cli", env));
|
|
70
|
-
add("Agent hook",
|
|
71
|
+
add("Agent hook", concreteAgentNames.some((name) => agentOk(workspace, name)));
|
|
72
|
+
for (const name of ["openclaw", "hermes"]) {
|
|
73
|
+
if (fs.existsSync(path.join(workspace, `.${name}`))) {
|
|
74
|
+
add(`Agent hook .${name}`, agentOk(workspace, name), `agents/${name}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
71
77
|
if (!fs.existsSync(path.join(workspace, ".harness", "index", "wikis-index.json")) &&
|
|
72
78
|
!fs.existsSync(path.join(workspace, ".harness", "index", "wikis-runtime-index.json"))) {
|
|
73
79
|
checks.push({ name: "wikis index", ok: true, detail: "missing; run data-harness-cli wikis build-index --skip-checks" });
|
package/src/commands/install.js
CHANGED
|
@@ -265,8 +265,8 @@ export async function installCommand(options = {}) {
|
|
|
265
265
|
blank();
|
|
266
266
|
|
|
267
267
|
step(8, 8, "配置 Agent Hook");
|
|
268
|
-
linkAgents(runtimeDir, await chooseAgent(options));
|
|
269
|
-
for (const [
|
|
268
|
+
const linkedAgents = linkAgents(runtimeDir, await chooseAgent(options));
|
|
269
|
+
for (const [source, target] of linkedAgents) {
|
|
270
270
|
if (fs.existsSync(path.join(runtimeDir, target))) ok(`${target} -> ${source}`);
|
|
271
271
|
}
|
|
272
272
|
blank();
|
package/src/lib/config.js
CHANGED
|
@@ -2,6 +2,25 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { binaryName } from "./platform.js";
|
|
4
4
|
|
|
5
|
+
export const agentChoices = ["claude", "codex", "pi", "openclaw", "hermes", "both", "all"];
|
|
6
|
+
export const concreteAgentNames = ["claude", "codex", "pi", "openclaw", "hermes"];
|
|
7
|
+
export const agentLinks = {
|
|
8
|
+
claude: [["agents/claude", ".claude"]],
|
|
9
|
+
codex: [["agents/codex", ".codex"]],
|
|
10
|
+
pi: [["agents/pi", ".pi"]],
|
|
11
|
+
openclaw: [["agents/openclaw", ".openclaw"]],
|
|
12
|
+
hermes: [["agents/hermes", ".hermes"]],
|
|
13
|
+
both: [["agents/claude", ".claude"], ["agents/codex", ".codex"]],
|
|
14
|
+
all: [
|
|
15
|
+
["agents/claude", ".claude"],
|
|
16
|
+
["agents/codex", ".codex"],
|
|
17
|
+
["agents/pi", ".pi"],
|
|
18
|
+
["agents/openclaw", ".openclaw"],
|
|
19
|
+
["agents/hermes", ".hermes"],
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
export const agentChoiceText = agentChoices.join(", ");
|
|
23
|
+
|
|
5
24
|
export function writeLocalConfig(workspace, options = {}) {
|
|
6
25
|
const configDir = path.join(workspace, "config");
|
|
7
26
|
fs.mkdirSync(configDir, { recursive: true });
|
|
@@ -30,10 +49,8 @@ export function validateCasConfigDir(dir) {
|
|
|
30
49
|
}
|
|
31
50
|
|
|
32
51
|
export function linkAgents(workspace, agent) {
|
|
33
|
-
const pairs = [];
|
|
34
|
-
if (
|
|
35
|
-
if (agent === "codex" || agent === "all") pairs.push(["agents/codex", ".codex"]);
|
|
36
|
-
if (agent === "pi" || agent === "all") pairs.push(["agents/pi", ".pi"]);
|
|
52
|
+
const pairs = agentLinks[agent];
|
|
53
|
+
if (!pairs) throw new Error(`agent must be ${agentChoiceText}`);
|
|
37
54
|
for (const [sourceRel, targetRel] of pairs) {
|
|
38
55
|
const source = path.join(workspace, sourceRel);
|
|
39
56
|
const target = path.join(workspace, targetRel);
|
|
@@ -41,4 +58,5 @@ export function linkAgents(workspace, agent) {
|
|
|
41
58
|
if (fs.existsSync(target)) fs.rmSync(target, { recursive: true, force: true });
|
|
42
59
|
fs.symlinkSync(source, target, "junction");
|
|
43
60
|
}
|
|
61
|
+
return pairs;
|
|
44
62
|
}
|
package/src/lib/prompt.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import readline from "node:readline/promises";
|
|
2
2
|
import { stdin as input, stdout as output } from "node:process";
|
|
3
3
|
import { Writable } from "node:stream";
|
|
4
|
-
|
|
5
|
-
const agentChoices = ["claude", "codex", "pi", "all"];
|
|
4
|
+
import { agentChoices, agentChoiceText } from "./config.js";
|
|
6
5
|
|
|
7
6
|
export async function confirm(message, options = {}) {
|
|
8
7
|
if (options.yes) return true;
|
|
@@ -20,15 +19,15 @@ export async function confirm(message, options = {}) {
|
|
|
20
19
|
export async function chooseAgent(options = {}) {
|
|
21
20
|
if (options.agent) {
|
|
22
21
|
const value = String(options.agent).trim().toLowerCase();
|
|
23
|
-
if (!agentChoices.includes(value)) throw new Error(
|
|
22
|
+
if (!agentChoices.includes(value)) throw new Error(`agent must be ${agentChoiceText}`);
|
|
24
23
|
return value;
|
|
25
24
|
}
|
|
26
25
|
if (options.yes) return "all";
|
|
27
26
|
const rl = readline.createInterface({ input, output });
|
|
28
27
|
try {
|
|
29
|
-
const answer = (await rl.question(
|
|
28
|
+
const answer = (await rl.question(`选择 Agent:${agentChoiceText} [all] `)).trim().toLowerCase();
|
|
30
29
|
const value = answer || "all";
|
|
31
|
-
if (!agentChoices.includes(value)) throw new Error(
|
|
30
|
+
if (!agentChoices.includes(value)) throw new Error(`agent must be ${agentChoiceText}`);
|
|
32
31
|
return value;
|
|
33
32
|
} finally {
|
|
34
33
|
rl.close();
|