@lumi-ai-lab/harness-data 0.0.14 → 0.0.16
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 +1 -1
- package/src/commands/doctor.js +9 -4
- package/src/commands/install.js +10 -5
- package/src/commands/update.js +6 -2
- package/src/lib/config.js +10 -9
package/package.json
CHANGED
package/src/commands/doctor.js
CHANGED
|
@@ -40,10 +40,15 @@ function configPathsValid(workspace) {
|
|
|
40
40
|
return matches.length >= 3 && matches.every((entry) => fs.existsSync(entry));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
function
|
|
43
|
+
function casCredentialsValid(dir) {
|
|
44
|
+
const encrypted = path.join(dir, "credentials.enc");
|
|
44
45
|
try {
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if (fs.statSync(encrypted).size > 0) return true;
|
|
47
|
+
} catch {}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const config = JSON.parse(fs.readFileSync(path.join(dir, "config.json"), "utf8"));
|
|
51
|
+
return Boolean(config?.cas?.username && config?.cas?.password);
|
|
47
52
|
} catch {
|
|
48
53
|
return false;
|
|
49
54
|
}
|
|
@@ -65,7 +70,7 @@ export async function collectDoctor(workspace, options = {}) {
|
|
|
65
70
|
add("config/harness-config.yaml", fs.existsSync(path.join(workspace, "config", "harness-config.yaml")));
|
|
66
71
|
add("config/qdm-cli-paths.env", fs.existsSync(path.join(workspace, "config", "qdm-cli-paths.env")));
|
|
67
72
|
add("config CLI paths", configPathsValid(workspace));
|
|
68
|
-
add("CAS credentials file",
|
|
73
|
+
add("CAS credentials file", casCredentialsValid(casConfigDir), casConfigDir);
|
|
69
74
|
add("CMR token", await tokenCheck(workspace, "qdm-cmr-cli", env));
|
|
70
75
|
add("Indicators token", await tokenCheck(workspace, "qdm-indicators-cli", env));
|
|
71
76
|
add("Agent hook", concreteAgentNames.some((name) => agentOk(workspace, name)));
|
package/src/commands/install.js
CHANGED
|
@@ -170,8 +170,9 @@ async function writeCasCredentials(runtimeDir, options = {}) {
|
|
|
170
170
|
if (!username || !password) throw new Error("CAS username and password are required");
|
|
171
171
|
const dir = casConfigDir(runtimeDir);
|
|
172
172
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
const env = { QDM_CAS_CONFIG_DIR: dir };
|
|
174
|
+
await run(path.join(runtimeDir, "bin", binaryName("cas-cli")), ["config", "set-credentials", "--username", username, "--password", password], { cwd: runtimeDir, env });
|
|
175
|
+
ok("CAS 凭证已加密保存到 .qdm-auth/cas/credentials.enc");
|
|
175
176
|
return dir;
|
|
176
177
|
}
|
|
177
178
|
|
|
@@ -204,8 +205,10 @@ export async function buildAndCheck(runtimeDir, options = {}) {
|
|
|
204
205
|
return { ok: true, docs, recall, runtimeDocs };
|
|
205
206
|
}
|
|
206
207
|
|
|
207
|
-
export function printDoctorSummary(doctor) {
|
|
208
|
-
const
|
|
208
|
+
export function printDoctorSummary(doctor, options = {}) {
|
|
209
|
+
const nonBlocking = options.nonBlocking || (() => false);
|
|
210
|
+
const failed = doctor.checks.filter((check) => !check.ok && !nonBlocking(check));
|
|
211
|
+
const warnings = doctor.checks.filter((check) => !check.ok && nonBlocking(check));
|
|
209
212
|
if (!failed.length) {
|
|
210
213
|
ok("runtime");
|
|
211
214
|
ok("wikis/spec");
|
|
@@ -216,9 +219,11 @@ export function printDoctorSummary(doctor) {
|
|
|
216
219
|
ok("CAS 凭证");
|
|
217
220
|
ok("CMR Token");
|
|
218
221
|
ok("Indicators Token");
|
|
219
|
-
ok("Agent Hook");
|
|
222
|
+
if (!warnings.some((check) => check.name.startsWith("Agent hook"))) ok("Agent Hook");
|
|
223
|
+
for (const check of warnings) warn(`${check.name}${check.detail ? ` (${check.detail})` : ""}`);
|
|
220
224
|
return;
|
|
221
225
|
}
|
|
226
|
+
for (const check of warnings) warn(`${check.name}${check.detail ? ` (${check.detail})` : ""}`);
|
|
222
227
|
for (const check of failed) fail(`${check.name}${check.detail ? ` (${check.detail})` : ""}`);
|
|
223
228
|
}
|
|
224
229
|
|
package/src/commands/update.js
CHANGED
|
@@ -13,6 +13,10 @@ import { buildAndCheck, installRuntimeBundle, printDoctorSummary } from "./insta
|
|
|
13
13
|
import { collectDoctor } from "./doctor.js";
|
|
14
14
|
import { action, blank, header, ok, shortSha, skip, step, warn } from "../lib/log.js";
|
|
15
15
|
|
|
16
|
+
export function isNonBlockingUpdateDoctorCheck(check) {
|
|
17
|
+
return check.name === "Agent hook" || check.name.startsWith("Agent hook .");
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
async function npmLatest() {
|
|
17
21
|
try {
|
|
18
22
|
const response = await fetch("https://registry.npmjs.org/@lumi-ai-lab%2Fharness-data/latest", { signal: AbortSignal.timeout(5000) });
|
|
@@ -184,8 +188,8 @@ export async function updateCommand(options = {}) {
|
|
|
184
188
|
step(6, 6, "安装校验");
|
|
185
189
|
if (changed) {
|
|
186
190
|
const doctor = await collectDoctor(runtimeDir, trackingOptions);
|
|
187
|
-
printDoctorSummary(doctor);
|
|
188
|
-
if (doctor.checks.some((check) => !check.ok)) throw new Error("doctor failed; update is incomplete");
|
|
191
|
+
printDoctorSummary(doctor, { nonBlocking: isNonBlockingUpdateDoctorCheck });
|
|
192
|
+
if (doctor.checks.some((check) => !check.ok && !isNonBlockingUpdateDoctorCheck(check))) throw new Error("doctor failed; update is incomplete");
|
|
189
193
|
writeState(runtimeDir, {
|
|
190
194
|
...state,
|
|
191
195
|
runtimeTag,
|
package/src/lib/config.js
CHANGED
|
@@ -36,16 +36,17 @@ export function writeLocalConfig(workspace, options = {}) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export function validateCasConfigDir(dir) {
|
|
39
|
-
const
|
|
40
|
-
let config;
|
|
39
|
+
const encrypted = path.join(dir, "credentials.enc");
|
|
41
40
|
try {
|
|
42
|
-
|
|
43
|
-
} catch {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
if (fs.statSync(encrypted).size > 0) return;
|
|
42
|
+
} catch {}
|
|
43
|
+
|
|
44
|
+
const legacy = path.join(dir, "config.json");
|
|
45
|
+
try {
|
|
46
|
+
const config = JSON.parse(fs.readFileSync(legacy, "utf8"));
|
|
47
|
+
if (config?.cas?.username && config?.cas?.password) return;
|
|
48
|
+
} catch {}
|
|
49
|
+
throw new Error(`CAS credentials are missing or invalid in: ${dir}`);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
export function linkAgents(workspace, agent) {
|