@yansirplus/cli 0.5.18 → 0.5.20
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/agent-catalog/agentOS/SKILL.md +2 -2
- package/agent-catalog/agentOS/references/package-map.md +57 -56
- package/agent-catalog/agentOS/references/provenance.json +27 -27
- package/agent-catalog/agentOS/references/public-api/client.md +2 -0
- package/agent-catalog/agentOS/references/public-api/core.md +90 -0
- package/agent-catalog/agentOS/references/public-api/runtime.md +49 -0
- package/dist/build/agent-authoring/static-target.js +120 -22
- package/dist/build/build-cli.js +15 -0
- package/dist/consumer-overlay.mjs +545 -66
- package/dist/main.mjs +90 -33
- package/dist/release-status.mjs +515 -0
- package/package.json +4 -4
|
@@ -0,0 +1,515 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
consumerStatusData,
|
|
8
|
+
exportEquivalenceForInstallManifest,
|
|
9
|
+
resolveConsumerRoot,
|
|
10
|
+
} from "./consumer-overlay.mjs";
|
|
11
|
+
|
|
12
|
+
const releaseStatusSchemaVersion = 1;
|
|
13
|
+
|
|
14
|
+
const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
|
|
15
|
+
|
|
16
|
+
const sha256File = (file) =>
|
|
17
|
+
crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
|
|
18
|
+
|
|
19
|
+
const parseArgs = (args) => {
|
|
20
|
+
const parsed = { _: [] };
|
|
21
|
+
const booleanKeys = new Set(["json", "check-npm"]);
|
|
22
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
23
|
+
const arg = args[index];
|
|
24
|
+
if (!arg.startsWith("--")) {
|
|
25
|
+
parsed._.push(arg);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const eq = arg.indexOf("=");
|
|
29
|
+
if (eq >= 0) {
|
|
30
|
+
parsed[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const key = arg.slice(2);
|
|
34
|
+
if (booleanKeys.has(key)) {
|
|
35
|
+
parsed[key] = true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const next = args[index + 1];
|
|
39
|
+
if (next !== undefined && !next.startsWith("--")) {
|
|
40
|
+
parsed[key] = next;
|
|
41
|
+
index += 1;
|
|
42
|
+
} else {
|
|
43
|
+
parsed[key] = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const boolArg = (args, name) => args[name] === true || args[name] === "true";
|
|
50
|
+
|
|
51
|
+
const gitValue = (cwd, args) => {
|
|
52
|
+
const result = spawnSync("git", args, {
|
|
53
|
+
cwd,
|
|
54
|
+
encoding: "utf8",
|
|
55
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
56
|
+
});
|
|
57
|
+
if (result.status !== 0) return undefined;
|
|
58
|
+
const value = result.stdout.trim();
|
|
59
|
+
return value.length === 0 ? undefined : value;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const gitSourceProjection = (sourceRoot) => {
|
|
63
|
+
if (typeof sourceRoot !== "string") {
|
|
64
|
+
return {
|
|
65
|
+
owner: "git",
|
|
66
|
+
status: "unavailable",
|
|
67
|
+
reason: "source checkout identity is unavailable in this CLI installation",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const branch = gitValue(sourceRoot, ["branch", "--show-current"]) ?? "unknown";
|
|
71
|
+
const head = gitValue(sourceRoot, ["rev-parse", "HEAD"]) ?? "unknown";
|
|
72
|
+
const statusShort = gitValue(sourceRoot, ["status", "--short"]);
|
|
73
|
+
const dirty = statusShort === undefined ? undefined : statusShort.length !== 0;
|
|
74
|
+
const upstreamRef = gitValue(sourceRoot, [
|
|
75
|
+
"rev-parse",
|
|
76
|
+
"--abbrev-ref",
|
|
77
|
+
"--symbolic-full-name",
|
|
78
|
+
"@{upstream}",
|
|
79
|
+
]);
|
|
80
|
+
let upstream = { status: "not_configured" };
|
|
81
|
+
if (upstreamRef !== undefined) {
|
|
82
|
+
const counts = gitValue(sourceRoot, [
|
|
83
|
+
"rev-list",
|
|
84
|
+
"--left-right",
|
|
85
|
+
"--count",
|
|
86
|
+
`${upstreamRef}...HEAD`,
|
|
87
|
+
]);
|
|
88
|
+
const [behindRaw, aheadRaw] = counts?.split(/\s+/u) ?? [];
|
|
89
|
+
upstream = {
|
|
90
|
+
status: "configured",
|
|
91
|
+
ref: upstreamRef,
|
|
92
|
+
ahead: Number(aheadRaw ?? 0),
|
|
93
|
+
behind: Number(behindRaw ?? 0),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
owner: "git",
|
|
98
|
+
status: "available",
|
|
99
|
+
repoRoot: sourceRoot,
|
|
100
|
+
branch,
|
|
101
|
+
head,
|
|
102
|
+
dirty: dirty ?? false,
|
|
103
|
+
upstream,
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const releasePackagePath = (context) => {
|
|
108
|
+
const sourcePackage = path.join(context.sourceRoot ?? "", "package.json");
|
|
109
|
+
if (typeof context.sourceRoot === "string" && fs.existsSync(sourcePackage)) return sourcePackage;
|
|
110
|
+
return path.join(context.packageRoot ?? process.cwd(), "package.json");
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const releaseIdentityProjection = (context) => {
|
|
114
|
+
const packagePath = releasePackagePath(context);
|
|
115
|
+
const manifest = readJson(packagePath);
|
|
116
|
+
const packageName = typeof manifest.name === "string" ? manifest.name : undefined;
|
|
117
|
+
const packageScope = packageName?.startsWith("@") ? packageName.split("/")[0] : undefined;
|
|
118
|
+
return {
|
|
119
|
+
owner: "package.json#agentOsRelease",
|
|
120
|
+
packageJson: packagePath,
|
|
121
|
+
packageName,
|
|
122
|
+
version:
|
|
123
|
+
typeof manifest.agentOsRelease?.version === "string"
|
|
124
|
+
? manifest.agentOsRelease.version
|
|
125
|
+
: manifest.version,
|
|
126
|
+
npmScope:
|
|
127
|
+
typeof manifest.agentOsRelease?.npmScope === "string"
|
|
128
|
+
? manifest.agentOsRelease.npmScope
|
|
129
|
+
: packageScope,
|
|
130
|
+
npmAccess: manifest.agentOsRelease?.npmAccess,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const sourcePackageScope = "@agent-os";
|
|
135
|
+
|
|
136
|
+
const publicPackageName = (sourceName, npmScope) => {
|
|
137
|
+
if (typeof npmScope !== "string" || !sourceName.startsWith(`${sourcePackageScope}/`)) {
|
|
138
|
+
return sourceName;
|
|
139
|
+
}
|
|
140
|
+
return `${npmScope}/${sourceName.slice(sourcePackageScope.length + 1)}`;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const publishedPackagesProjection = (context, release) => {
|
|
144
|
+
const surfacePath =
|
|
145
|
+
typeof context.sourceRoot === "string"
|
|
146
|
+
? path.join(context.sourceRoot, "docs", "surface.json")
|
|
147
|
+
: undefined;
|
|
148
|
+
if (surfacePath === undefined || !fs.existsSync(surfacePath)) {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
const surface = readJson(surfacePath);
|
|
152
|
+
return (surface.packages ?? [])
|
|
153
|
+
.filter((pkg) => pkg?.published === true && typeof pkg.name === "string")
|
|
154
|
+
.map((pkg) => ({
|
|
155
|
+
sourceName: pkg.name,
|
|
156
|
+
publicName: publicPackageName(pkg.name, release.npmScope),
|
|
157
|
+
path: pkg.path,
|
|
158
|
+
status: pkg.status,
|
|
159
|
+
}))
|
|
160
|
+
.sort((left, right) => left.publicName.localeCompare(right.publicName));
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const fileSpecPath = (spec) => {
|
|
164
|
+
if (typeof spec !== "string" || !spec.startsWith("file:")) return undefined;
|
|
165
|
+
return spec.slice("file:".length);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const artifactProjection = (manifestPath) => {
|
|
169
|
+
const base = {
|
|
170
|
+
owner: "dist/internal-npm/install-manifest.json",
|
|
171
|
+
path: manifestPath,
|
|
172
|
+
};
|
|
173
|
+
if (typeof manifestPath !== "string") {
|
|
174
|
+
return { ...base, status: "unavailable", packages: [] };
|
|
175
|
+
}
|
|
176
|
+
if (!fs.existsSync(manifestPath)) {
|
|
177
|
+
return { ...base, status: "missing", packages: [] };
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const manifest = readJson(manifestPath);
|
|
181
|
+
const packages = Object.entries(manifest.tarballs ?? {})
|
|
182
|
+
.map(([packageName, entry]) => {
|
|
183
|
+
const tarball = fileSpecPath(entry?.spec);
|
|
184
|
+
const expectedSha = typeof entry?.sha256 === "string" ? entry.sha256 : undefined;
|
|
185
|
+
const exists = typeof tarball === "string" && fs.existsSync(tarball);
|
|
186
|
+
const actualSha = exists ? sha256File(tarball) : undefined;
|
|
187
|
+
const status =
|
|
188
|
+
tarball === undefined || expectedSha === undefined
|
|
189
|
+
? "invalid"
|
|
190
|
+
: !exists
|
|
191
|
+
? "missing"
|
|
192
|
+
: actualSha === expectedSha
|
|
193
|
+
? "verified"
|
|
194
|
+
: "sha_mismatch";
|
|
195
|
+
return {
|
|
196
|
+
packageName,
|
|
197
|
+
tarball,
|
|
198
|
+
expectedSha256: expectedSha,
|
|
199
|
+
actualSha256: actualSha,
|
|
200
|
+
status,
|
|
201
|
+
};
|
|
202
|
+
})
|
|
203
|
+
.sort((left, right) => left.packageName.localeCompare(right.packageName));
|
|
204
|
+
const protocolOk = manifest.protocol === "agentos-install-manifest@1";
|
|
205
|
+
const status =
|
|
206
|
+
protocolOk && packages.length > 0 && packages.every((pkg) => pkg.status === "verified")
|
|
207
|
+
? "verified"
|
|
208
|
+
: "failed";
|
|
209
|
+
return {
|
|
210
|
+
...base,
|
|
211
|
+
status,
|
|
212
|
+
sha256: sha256File(manifestPath),
|
|
213
|
+
protocol: manifest.protocol,
|
|
214
|
+
version: manifest.version,
|
|
215
|
+
generatedBy: manifest.generatedBy,
|
|
216
|
+
packages,
|
|
217
|
+
};
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return {
|
|
220
|
+
...base,
|
|
221
|
+
status: "failed",
|
|
222
|
+
packages: [],
|
|
223
|
+
error: error instanceof Error ? error.message : String(error),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const releaseExportEquivalenceProjection = (manifestPath, context) => {
|
|
229
|
+
if (typeof manifestPath !== "string" || !fs.existsSync(manifestPath)) {
|
|
230
|
+
return {
|
|
231
|
+
status: "not_checked",
|
|
232
|
+
packagesChecked: 0,
|
|
233
|
+
packages: [],
|
|
234
|
+
failures: [],
|
|
235
|
+
reason: "install manifest is unavailable",
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
const manifest = readJson(manifestPath);
|
|
240
|
+
return exportEquivalenceForInstallManifest(manifest, { sourceRoot: context.sourceRoot });
|
|
241
|
+
} catch (error) {
|
|
242
|
+
return {
|
|
243
|
+
status: "failed",
|
|
244
|
+
packagesChecked: 0,
|
|
245
|
+
packages: [],
|
|
246
|
+
failures: [
|
|
247
|
+
{
|
|
248
|
+
code: "export_install_manifest_unreadable",
|
|
249
|
+
comparison: "manifest",
|
|
250
|
+
error: error instanceof Error ? error.message : String(error),
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const npmProjection = (packages, options) => {
|
|
258
|
+
if (options.checkNpm !== true) {
|
|
259
|
+
return {
|
|
260
|
+
owner: "npm registry",
|
|
261
|
+
status: "not_checked",
|
|
262
|
+
reason: "pass --check-npm to observe npm dist-tags",
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
const registry = typeof options.registry === "string" ? options.registry : undefined;
|
|
266
|
+
const rows = {};
|
|
267
|
+
for (const pkg of packages) {
|
|
268
|
+
const args = ["view", pkg.publicName, "dist-tags", "--json"];
|
|
269
|
+
if (registry !== undefined && registry.length > 0) args.push("--registry", registry);
|
|
270
|
+
const result = spawnSync("npm", args, {
|
|
271
|
+
encoding: "utf8",
|
|
272
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
273
|
+
});
|
|
274
|
+
if (result.status !== 0) {
|
|
275
|
+
rows[pkg.publicName] = {
|
|
276
|
+
status: "unresolved",
|
|
277
|
+
detail: result.stderr.trim() || result.stdout.trim(),
|
|
278
|
+
};
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
rows[pkg.publicName] = {
|
|
283
|
+
status: "resolved",
|
|
284
|
+
distTags: JSON.parse(result.stdout.trim()),
|
|
285
|
+
};
|
|
286
|
+
} catch (error) {
|
|
287
|
+
rows[pkg.publicName] = {
|
|
288
|
+
status: "invalid_json",
|
|
289
|
+
detail: error instanceof Error ? error.message : String(error),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
owner: "npm registry",
|
|
295
|
+
status: "checked",
|
|
296
|
+
...(registry === undefined ? {} : { registry }),
|
|
297
|
+
packages: rows,
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const issue = (code, severity, dimension, message, detail = {}) => ({
|
|
302
|
+
code,
|
|
303
|
+
severity,
|
|
304
|
+
dimension,
|
|
305
|
+
message,
|
|
306
|
+
...detail,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
const releaseGate = (projection) => {
|
|
310
|
+
const hardFailures = [];
|
|
311
|
+
const signals = [];
|
|
312
|
+
if (projection.artifacts.status === "failed") {
|
|
313
|
+
hardFailures.push(
|
|
314
|
+
issue(
|
|
315
|
+
"local_artifacts_failed",
|
|
316
|
+
"hard",
|
|
317
|
+
"artifacts",
|
|
318
|
+
"local package artifacts failed integrity checks",
|
|
319
|
+
),
|
|
320
|
+
);
|
|
321
|
+
} else if (projection.artifacts.status !== "verified") {
|
|
322
|
+
signals.push(
|
|
323
|
+
issue(
|
|
324
|
+
"local_artifacts_not_verified",
|
|
325
|
+
"signal",
|
|
326
|
+
"artifacts",
|
|
327
|
+
`local package artifacts are ${projection.artifacts.status}`,
|
|
328
|
+
),
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
for (const failure of projection.exportEquivalence?.failures ?? []) {
|
|
332
|
+
hardFailures.push(
|
|
333
|
+
issue(
|
|
334
|
+
failure.code,
|
|
335
|
+
"hard",
|
|
336
|
+
"export_equivalence",
|
|
337
|
+
`release export equivalence failed: ${failure.code}`,
|
|
338
|
+
{ exportIssue: failure },
|
|
339
|
+
),
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
if (projection.source.status !== "available") {
|
|
343
|
+
signals.push(
|
|
344
|
+
issue("source_unavailable", "signal", "source", "source checkout identity is unavailable"),
|
|
345
|
+
);
|
|
346
|
+
} else {
|
|
347
|
+
if (projection.source.dirty === true) {
|
|
348
|
+
signals.push(
|
|
349
|
+
issue("source_dirty", "signal", "source", "source checkout has uncommitted changes"),
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
if (
|
|
353
|
+
projection.source.upstream?.status === "configured" &&
|
|
354
|
+
projection.source.upstream.ahead > 0
|
|
355
|
+
) {
|
|
356
|
+
signals.push(
|
|
357
|
+
issue("source_ahead", "signal", "source", "source checkout is ahead of upstream", {
|
|
358
|
+
ahead: projection.source.upstream.ahead,
|
|
359
|
+
upstream: projection.source.upstream.ref,
|
|
360
|
+
}),
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
if (
|
|
364
|
+
projection.source.upstream?.status === "configured" &&
|
|
365
|
+
projection.source.upstream.behind > 0
|
|
366
|
+
) {
|
|
367
|
+
signals.push(
|
|
368
|
+
issue("source_behind", "signal", "source", "source checkout is behind upstream", {
|
|
369
|
+
behind: projection.source.upstream.behind,
|
|
370
|
+
upstream: projection.source.upstream.ref,
|
|
371
|
+
}),
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (projection.npm.status === "not_checked") {
|
|
376
|
+
signals.push(issue("npm_not_checked", "signal", "npm", "npm dist-tags were not checked"));
|
|
377
|
+
} else if (projection.npm.status === "checked") {
|
|
378
|
+
for (const [packageName, row] of Object.entries(projection.npm.packages ?? {})) {
|
|
379
|
+
if (row.status !== "resolved") {
|
|
380
|
+
signals.push(
|
|
381
|
+
issue(
|
|
382
|
+
"npm_unresolved",
|
|
383
|
+
"signal",
|
|
384
|
+
"npm",
|
|
385
|
+
`${packageName} npm dist-tags were not resolved`,
|
|
386
|
+
{
|
|
387
|
+
packageName,
|
|
388
|
+
status: row.status,
|
|
389
|
+
},
|
|
390
|
+
),
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (projection.consumer === undefined) {
|
|
396
|
+
signals.push(
|
|
397
|
+
issue("consumer_not_checked", "signal", "consumer", "no consumer root was provided"),
|
|
398
|
+
);
|
|
399
|
+
} else {
|
|
400
|
+
for (const failure of projection.consumer.gate?.hardFailures ?? []) {
|
|
401
|
+
hardFailures.push(
|
|
402
|
+
issue(
|
|
403
|
+
failure.code,
|
|
404
|
+
"hard",
|
|
405
|
+
"consumer",
|
|
406
|
+
failure.message ?? `consumer gate failed: ${failure.code}`,
|
|
407
|
+
{ consumerIssue: failure },
|
|
408
|
+
),
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
for (const signal of projection.consumer.gate?.signals ?? []) {
|
|
412
|
+
signals.push(
|
|
413
|
+
issue(
|
|
414
|
+
signal.code,
|
|
415
|
+
"signal",
|
|
416
|
+
"consumer",
|
|
417
|
+
signal.message ?? `consumer gate signal: ${signal.code}`,
|
|
418
|
+
{ consumerIssue: signal },
|
|
419
|
+
),
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
status: hardFailures.length > 0 ? "fail" : signals.length > 0 ? "warn" : "pass",
|
|
425
|
+
hardFailures,
|
|
426
|
+
signals,
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
export const releaseStatusData = (input = {}) => {
|
|
431
|
+
const context = input.context ?? {};
|
|
432
|
+
const release = releaseIdentityProjection(context);
|
|
433
|
+
const packages = publishedPackagesProjection(context, release);
|
|
434
|
+
const manifestPath = input.installManifestPath ?? context.defaultInstallManifestPath;
|
|
435
|
+
const projection = {
|
|
436
|
+
schemaVersion: releaseStatusSchemaVersion,
|
|
437
|
+
release: {
|
|
438
|
+
...release,
|
|
439
|
+
packages,
|
|
440
|
+
},
|
|
441
|
+
source: gitSourceProjection(context.sourceRoot),
|
|
442
|
+
artifacts: artifactProjection(manifestPath),
|
|
443
|
+
exportEquivalence: releaseExportEquivalenceProjection(manifestPath, context),
|
|
444
|
+
npm: npmProjection(packages, {
|
|
445
|
+
checkNpm: input.checkNpm,
|
|
446
|
+
registry: input.registry,
|
|
447
|
+
}),
|
|
448
|
+
...(input.consumerRoot === undefined
|
|
449
|
+
? {}
|
|
450
|
+
: {
|
|
451
|
+
consumer: consumerStatusData(input.consumerRoot, {
|
|
452
|
+
packageRoot: context.packageRoot,
|
|
453
|
+
sourceRoot: context.sourceRoot,
|
|
454
|
+
checkNpm: input.checkNpm,
|
|
455
|
+
registry: input.registry,
|
|
456
|
+
}),
|
|
457
|
+
}),
|
|
458
|
+
};
|
|
459
|
+
return {
|
|
460
|
+
...projection,
|
|
461
|
+
gate: releaseGate(projection),
|
|
462
|
+
};
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const printReleaseStatus = (status) => {
|
|
466
|
+
console.log(`release version: ${status.release.version}`);
|
|
467
|
+
console.log(`npm scope: ${status.release.npmScope ?? "unknown"}`);
|
|
468
|
+
console.log(`source: ${status.source.status}`);
|
|
469
|
+
if (status.source.status === "available") {
|
|
470
|
+
console.log(
|
|
471
|
+
`source head: ${status.source.branch}@${status.source.head} dirty=${status.source.dirty}`,
|
|
472
|
+
);
|
|
473
|
+
if (status.source.upstream?.status === "configured") {
|
|
474
|
+
console.log(
|
|
475
|
+
`source upstream: ${status.source.upstream.ref} ahead=${status.source.upstream.ahead} behind=${status.source.upstream.behind}`,
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
console.log(`artifacts: ${status.artifacts.status}`);
|
|
480
|
+
console.log(`export equivalence: ${status.exportEquivalence.status}`);
|
|
481
|
+
console.log(`npm: ${status.npm.status}`);
|
|
482
|
+
console.log(`consumer: ${status.consumer?.truthMode ?? "not_checked"}`);
|
|
483
|
+
console.log(`gate: ${status.gate.status}`);
|
|
484
|
+
for (const failure of status.gate.hardFailures) {
|
|
485
|
+
console.log(`failure ${failure.code}: ${failure.message}`);
|
|
486
|
+
}
|
|
487
|
+
for (const signal of status.gate.signals) {
|
|
488
|
+
console.log(`signal ${signal.code}: ${signal.message}`);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
export const releaseStatus = (rawArgs, context = {}) => {
|
|
493
|
+
const args = parseArgs(rawArgs);
|
|
494
|
+
const positional = args._ ?? [];
|
|
495
|
+
if (positional.length > 1) {
|
|
496
|
+
throw new Error("agentos release status: expected at most one consumer path");
|
|
497
|
+
}
|
|
498
|
+
const consumerRoot = positional[0] === undefined ? undefined : resolveConsumerRoot(positional[0]);
|
|
499
|
+
const installManifestPath =
|
|
500
|
+
typeof args["install-manifest"] === "string"
|
|
501
|
+
? path.resolve(process.cwd(), args["install-manifest"])
|
|
502
|
+
: undefined;
|
|
503
|
+
const status = releaseStatusData({
|
|
504
|
+
context,
|
|
505
|
+
consumerRoot,
|
|
506
|
+
installManifestPath,
|
|
507
|
+
checkNpm: boolArg(args, "check-npm"),
|
|
508
|
+
registry: typeof args.registry === "string" ? args.registry : undefined,
|
|
509
|
+
});
|
|
510
|
+
if (boolArg(args, "json")) {
|
|
511
|
+
console.log(JSON.stringify(status, null, 2));
|
|
512
|
+
} else {
|
|
513
|
+
printReleaseStatus(status);
|
|
514
|
+
}
|
|
515
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yansirplus/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.20",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"publishConfig": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"PUBLIC_API.md"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@yansirplus/core": "0.5.
|
|
28
|
-
"@yansirplus/evals": "0.5.
|
|
29
|
-
"@yansirplus/runtime": "0.5.
|
|
27
|
+
"@yansirplus/core": "0.5.20",
|
|
28
|
+
"@yansirplus/evals": "0.5.20",
|
|
29
|
+
"@yansirplus/runtime": "0.5.20",
|
|
30
30
|
"esbuild": "0.27.3",
|
|
31
31
|
"yaml": "2.9.0"
|
|
32
32
|
},
|