crewhaus 0.2.4 → 0.3.0
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/dist/ci-scaffold.d.ts +18 -0
- package/dist/ci-scaffold.js +74 -0
- package/dist/doctor-probe.d.ts +72 -0
- package/dist/doctor-probe.js +92 -0
- package/dist/dream-cli.d.ts +53 -0
- package/dist/dream-cli.js +329 -0
- package/dist/fleet.d.ts +50 -0
- package/dist/fleet.js +78 -2
- package/dist/index.js +716 -128
- package/dist/init-conversation.d.ts +87 -0
- package/dist/init-conversation.js +306 -0
- package/dist/init-interactive.d.ts +39 -39
- package/dist/init-interactive.js +66 -56
- package/dist/lint.js +17 -1
- package/dist/memory-cli.d.ts +92 -0
- package/dist/memory-cli.js +278 -0
- package/dist/run-failure.d.ts +34 -0
- package/dist/run-failure.js +38 -0
- package/dist/sessions-index.d.ts +7 -19
- package/dist/sessions-index.js +7 -43
- package/dist/thredz-probe.d.ts +36 -0
- package/dist/thredz-probe.js +93 -0
- package/dist/upgrade.d.ts +42 -0
- package/dist/upgrade.js +110 -6
- package/dist/wiki-cli.d.ts +40 -0
- package/dist/wiki-cli.js +133 -0
- package/package.json +92 -89
package/dist/fleet.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type FailureClass } from "@crewhaus/errors";
|
|
1
2
|
import type { Manifest } from "@crewhaus/spec-registry";
|
|
2
3
|
/** The spec file that roots a standalone harness. */
|
|
3
4
|
export declare const HARNESS_SPEC_FILENAME = "crewhaus.yaml";
|
|
@@ -165,6 +166,41 @@ export type FleetRunner = (opts: {
|
|
|
165
166
|
readonly exitCode: number;
|
|
166
167
|
readonly tail: string;
|
|
167
168
|
}>;
|
|
169
|
+
/**
|
|
170
|
+
* Is `entryPath` the Bun standalone-executable virtual-FS sentinel — i.e. are
|
|
171
|
+
* we running a `bun build --compile` single-file binary rather than
|
|
172
|
+
* `bun run …/index.ts`? Bun rewrites the entry (`process.argv[1]` / `Bun.main`)
|
|
173
|
+
* to a path inside its embedded root: `/$bunfs/root/<name>` on POSIX,
|
|
174
|
+
* `B:\~BUN\root\<name>` on Windows.
|
|
175
|
+
*/
|
|
176
|
+
export declare function isCompiledEntryPath(entryPath: string): boolean;
|
|
177
|
+
/** The runtime facts the self-invoke argv depends on, injected so the builder
|
|
178
|
+
* is a pure function: production passes the live `process.execPath` +
|
|
179
|
+
* `Bun.main`; tests pass fixed strings for either mode. */
|
|
180
|
+
export type SelfInvokeContext = {
|
|
181
|
+
/** The real running executable — `bun` in dev, the compiled binary itself
|
|
182
|
+
* when compiled (`process.execPath`, NOT `process.argv[0]`, which the
|
|
183
|
+
* compiled runtime reports as the literal string `"bun"`). */
|
|
184
|
+
readonly execPath: string;
|
|
185
|
+
/** The entry path as the runtime sees it (`process.argv[1]` / `Bun.main`):
|
|
186
|
+
* the real `…/index.ts` in dev, the `/$bunfs/…` sentinel when compiled. */
|
|
187
|
+
readonly entryPath: string;
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Build the argv to re-invoke THIS running CLI in a child process with
|
|
191
|
+
* `childArgv` (e.g. `["doctor"]`) — correct under BOTH `bun run
|
|
192
|
+
* apps/cli/src/index.ts …` and a `bun build --compile` single-file binary.
|
|
193
|
+
*
|
|
194
|
+
* The compiled case is the subtle one. A standalone binary RE-INJECTS its own
|
|
195
|
+
* embedded entry every time it is spawned, so the child already receives
|
|
196
|
+
* `[<exe>, /$bunfs/root/<name>, ...childArgv]`. If we ALSO passed our own
|
|
197
|
+
* `entryPath` (the `/$bunfs/…` sentinel) it would land in the child's user
|
|
198
|
+
* args and be parsed as the subcommand — the v0.2.4 bug where `fleet run
|
|
199
|
+
* doctor` reported `unknown subcommand: /$bunfs/root/crewhaus-…` for every
|
|
200
|
+
* harness. So: compiled → `[execPath, ...childArgv]` and let Bun supply the
|
|
201
|
+
* entry; dev → `[execPath, entryPath, ...childArgv]` with the real script path.
|
|
202
|
+
*/
|
|
203
|
+
export declare function fleetSelfInvokeArgv(ctx: SelfInvokeContext, childArgv: ReadonlyArray<string>): string[];
|
|
168
204
|
/** Per-harness confirm seam for `--allow-mutating` (interactive prompt in the
|
|
169
205
|
* CLI; a predicate in tests). Returning false skips that harness. */
|
|
170
206
|
export type ConfirmMutating = (inv: HarnessInventory, argv: ReadonlyArray<string>) => Promise<boolean>;
|
|
@@ -203,5 +239,19 @@ export type RunFleetBulkReport = {
|
|
|
203
239
|
* runner is the sole side-effect surface, injected for testability.
|
|
204
240
|
*/
|
|
205
241
|
export declare function runFleetBulk(opts: RunFleetBulkOptions): Promise<RunFleetBulkReport>;
|
|
242
|
+
/**
|
|
243
|
+
* v0.3.0 Goal 6 — decode a child process's exit code back into its failure
|
|
244
|
+
* class + report title. The coded exits are the documented `EXIT_CODES`
|
|
245
|
+
* contract every terminal surface (die(), the compiled-bundle catch
|
|
246
|
+
* wrappers) now honours, so fleet can say "out of funding" instead of
|
|
247
|
+
* "exit 31" without parsing any output. Titles mirror the
|
|
248
|
+
* `BUILTIN_FAILURE_CLASSES` wording (recovery-engine) for the provider
|
|
249
|
+
* classes and the `EXIT_CODES` doc comments for the rest. Exit 0 and
|
|
250
|
+
* unmapped codes return undefined (a plain `exit N` line).
|
|
251
|
+
*/
|
|
252
|
+
export declare function describeFleetExit(exitCode: number): {
|
|
253
|
+
readonly class: FailureClass;
|
|
254
|
+
readonly title: string;
|
|
255
|
+
} | undefined;
|
|
206
256
|
/** Render a bulk-run report as summary lines for `fleet run`. */
|
|
207
257
|
export declare function formatBulkReport(report: RunFleetBulkReport): ReadonlyArray<string>;
|
package/dist/fleet.js
CHANGED
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
*/
|
|
50
50
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
51
51
|
import { join, resolve } from "node:path";
|
|
52
|
+
import { EXIT_CODES } from "@crewhaus/errors";
|
|
52
53
|
import { extractFeedbackRecords, mergeFeedback } from "./feedback";
|
|
53
54
|
/** The spec file that roots a standalone harness. */
|
|
54
55
|
export const HARNESS_SPEC_FILENAME = "crewhaus.yaml";
|
|
@@ -426,6 +427,35 @@ export function matchesFilter(inv, filter) {
|
|
|
426
427
|
const glob = new Bun.Glob(filter);
|
|
427
428
|
return glob.match(inv.specName) || glob.match(basenameOf(inv.dir));
|
|
428
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* Is `entryPath` the Bun standalone-executable virtual-FS sentinel — i.e. are
|
|
432
|
+
* we running a `bun build --compile` single-file binary rather than
|
|
433
|
+
* `bun run …/index.ts`? Bun rewrites the entry (`process.argv[1]` / `Bun.main`)
|
|
434
|
+
* to a path inside its embedded root: `/$bunfs/root/<name>` on POSIX,
|
|
435
|
+
* `B:\~BUN\root\<name>` on Windows.
|
|
436
|
+
*/
|
|
437
|
+
export function isCompiledEntryPath(entryPath) {
|
|
438
|
+
return (entryPath.includes("/$bunfs/") || entryPath.includes("\\~BUN\\") || entryPath.includes("/~BUN/"));
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Build the argv to re-invoke THIS running CLI in a child process with
|
|
442
|
+
* `childArgv` (e.g. `["doctor"]`) — correct under BOTH `bun run
|
|
443
|
+
* apps/cli/src/index.ts …` and a `bun build --compile` single-file binary.
|
|
444
|
+
*
|
|
445
|
+
* The compiled case is the subtle one. A standalone binary RE-INJECTS its own
|
|
446
|
+
* embedded entry every time it is spawned, so the child already receives
|
|
447
|
+
* `[<exe>, /$bunfs/root/<name>, ...childArgv]`. If we ALSO passed our own
|
|
448
|
+
* `entryPath` (the `/$bunfs/…` sentinel) it would land in the child's user
|
|
449
|
+
* args and be parsed as the subcommand — the v0.2.4 bug where `fleet run
|
|
450
|
+
* doctor` reported `unknown subcommand: /$bunfs/root/crewhaus-…` for every
|
|
451
|
+
* harness. So: compiled → `[execPath, ...childArgv]` and let Bun supply the
|
|
452
|
+
* entry; dev → `[execPath, entryPath, ...childArgv]` with the real script path.
|
|
453
|
+
*/
|
|
454
|
+
export function fleetSelfInvokeArgv(ctx, childArgv) {
|
|
455
|
+
return isCompiledEntryPath(ctx.entryPath)
|
|
456
|
+
? [ctx.execPath, ...childArgv]
|
|
457
|
+
: [ctx.execPath, ctx.entryPath, ...childArgv];
|
|
458
|
+
}
|
|
429
459
|
/**
|
|
430
460
|
* Run one subcommand across the filtered fleet. Read-only commands run
|
|
431
461
|
* unconditionally on every matched harness; a mutating command (only reachable
|
|
@@ -462,6 +492,35 @@ export async function runFleetBulk(opts) {
|
|
|
462
492
|
}
|
|
463
493
|
return { plan, results, failed, passed, skipped };
|
|
464
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* v0.3.0 Goal 6 — decode a child process's exit code back into its failure
|
|
497
|
+
* class + report title. The coded exits are the documented `EXIT_CODES`
|
|
498
|
+
* contract every terminal surface (die(), the compiled-bundle catch
|
|
499
|
+
* wrappers) now honours, so fleet can say "out of funding" instead of
|
|
500
|
+
* "exit 31" without parsing any output. Titles mirror the
|
|
501
|
+
* `BUILTIN_FAILURE_CLASSES` wording (recovery-engine) for the provider
|
|
502
|
+
* classes and the `EXIT_CODES` doc comments for the rest. Exit 0 and
|
|
503
|
+
* unmapped codes return undefined (a plain `exit N` line).
|
|
504
|
+
*/
|
|
505
|
+
export function describeFleetExit(exitCode) {
|
|
506
|
+
const table = {
|
|
507
|
+
[EXIT_CODES.generic]: { class: "unknown", title: "unclassified failure" },
|
|
508
|
+
[EXIT_CODES.spec]: { class: "spec", title: "spec parse/validation failed" },
|
|
509
|
+
[EXIT_CODES.config]: { class: "config", title: "config / missing env" },
|
|
510
|
+
[EXIT_CODES.auth]: { class: "auth", title: "provider rejected the credentials" },
|
|
511
|
+
[EXIT_CODES.billing]: { class: "billing", title: "provider account out of funding" },
|
|
512
|
+
[EXIT_CODES.rate_limit]: {
|
|
513
|
+
class: "rate_limit",
|
|
514
|
+
title: "provider rate limit still exceeded after retries",
|
|
515
|
+
},
|
|
516
|
+
[EXIT_CODES.crewhaus_budget]: {
|
|
517
|
+
class: "crewhaus_budget",
|
|
518
|
+
title: "run stopped by the configured budget cap",
|
|
519
|
+
},
|
|
520
|
+
[EXIT_CODES.tool]: { class: "tool", title: "tool / MCP failure" },
|
|
521
|
+
};
|
|
522
|
+
return table[exitCode];
|
|
523
|
+
}
|
|
465
524
|
/** Render a bulk-run report as summary lines for `fleet run`. */
|
|
466
525
|
export function formatBulkReport(report) {
|
|
467
526
|
const cmd = report.plan.argv.join(" ");
|
|
@@ -475,7 +534,12 @@ export function formatBulkReport(report) {
|
|
|
475
534
|
continue;
|
|
476
535
|
}
|
|
477
536
|
const mark = r.exitCode === 0 ? "✓" : "✗";
|
|
478
|
-
|
|
537
|
+
// v0.3.0 Goal 6 — a coded exit renders its failure title inline:
|
|
538
|
+
// ✗ support-bot — provider account out of funding · exit 31
|
|
539
|
+
const described = r.exitCode !== 0 ? describeFleetExit(r.exitCode ?? 0) : undefined;
|
|
540
|
+
lines.push(described !== undefined
|
|
541
|
+
? `${mark} ${r.inv.specName} — ${described.title} · exit ${r.exitCode}`
|
|
542
|
+
: `${mark} ${r.inv.specName} — exit ${r.exitCode}`);
|
|
479
543
|
const tail = (r.tail ?? "").trim();
|
|
480
544
|
if (tail !== "") {
|
|
481
545
|
for (const line of tail.split("\n").slice(-3))
|
|
@@ -483,6 +547,18 @@ export function formatBulkReport(report) {
|
|
|
483
547
|
}
|
|
484
548
|
}
|
|
485
549
|
lines.push("");
|
|
486
|
-
|
|
550
|
+
// v0.3.0 Goal 6 — class-keyed failure rollup: `2 failed (billing ×1,
|
|
551
|
+
// unknown ×1)` so a fleet-wide funding outage reads at a glance.
|
|
552
|
+
const classCounts = new Map();
|
|
553
|
+
for (const r of report.results) {
|
|
554
|
+
if (!r.ran || r.exitCode === 0 || r.exitCode === undefined)
|
|
555
|
+
continue;
|
|
556
|
+
const cls = describeFleetExit(r.exitCode)?.class ?? "unknown";
|
|
557
|
+
classCounts.set(cls, (classCounts.get(cls) ?? 0) + 1);
|
|
558
|
+
}
|
|
559
|
+
const rollup = classCounts.size > 0
|
|
560
|
+
? ` (${[...classCounts.entries()].map(([cls, n]) => `${cls} ×${n}`).join(", ")})`
|
|
561
|
+
: "";
|
|
562
|
+
lines.push(`summary: ${report.passed} passed, ${report.failed} failed${rollup}, ${report.skipped} skipped`);
|
|
487
563
|
return lines;
|
|
488
564
|
}
|