@markbrutx/promptbook-cli 0.1.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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -0
  3. package/bin/promptbook.ts +4 -0
  4. package/dist/bin/promptbook.d.ts +3 -0
  5. package/dist/bin/promptbook.d.ts.map +1 -0
  6. package/dist/bin/promptbook.js +4 -0
  7. package/dist/bin/promptbook.js.map +1 -0
  8. package/dist/src/args.d.ts +43 -0
  9. package/dist/src/args.d.ts.map +1 -0
  10. package/dist/src/args.js +96 -0
  11. package/dist/src/args.js.map +1 -0
  12. package/dist/src/commands/annotations.d.ts +10 -0
  13. package/dist/src/commands/annotations.d.ts.map +1 -0
  14. package/dist/src/commands/annotations.js +92 -0
  15. package/dist/src/commands/annotations.js.map +1 -0
  16. package/dist/src/commands/bundle.d.ts +13 -0
  17. package/dist/src/commands/bundle.d.ts.map +1 -0
  18. package/dist/src/commands/bundle.js +61 -0
  19. package/dist/src/commands/bundle.js.map +1 -0
  20. package/dist/src/commands/eval.d.ts +13 -0
  21. package/dist/src/commands/eval.d.ts.map +1 -0
  22. package/dist/src/commands/eval.js +113 -0
  23. package/dist/src/commands/eval.js.map +1 -0
  24. package/dist/src/commands/lint.d.ts +11 -0
  25. package/dist/src/commands/lint.d.ts.map +1 -0
  26. package/dist/src/commands/lint.js +66 -0
  27. package/dist/src/commands/lint.js.map +1 -0
  28. package/dist/src/commands/ls.d.ts +11 -0
  29. package/dist/src/commands/ls.d.ts.map +1 -0
  30. package/dist/src/commands/ls.js +84 -0
  31. package/dist/src/commands/ls.js.map +1 -0
  32. package/dist/src/commands/resolve.d.ts +9 -0
  33. package/dist/src/commands/resolve.d.ts.map +1 -0
  34. package/dist/src/commands/resolve.js +41 -0
  35. package/dist/src/commands/resolve.js.map +1 -0
  36. package/dist/src/commands/view.d.ts +30 -0
  37. package/dist/src/commands/view.d.ts.map +1 -0
  38. package/dist/src/commands/view.js +51 -0
  39. package/dist/src/commands/view.js.map +1 -0
  40. package/dist/src/config.d.ts +56 -0
  41. package/dist/src/config.d.ts.map +1 -0
  42. package/dist/src/config.js +175 -0
  43. package/dist/src/config.js.map +1 -0
  44. package/dist/src/index.d.ts +4 -0
  45. package/dist/src/index.d.ts.map +1 -0
  46. package/dist/src/index.js +2 -0
  47. package/dist/src/index.js.map +1 -0
  48. package/dist/src/io.d.ts +43 -0
  49. package/dist/src/io.d.ts.map +1 -0
  50. package/dist/src/io.js +37 -0
  51. package/dist/src/io.js.map +1 -0
  52. package/dist/src/render-eval.d.ts +8 -0
  53. package/dist/src/render-eval.d.ts.map +1 -0
  54. package/dist/src/render-eval.js +51 -0
  55. package/dist/src/render-eval.js.map +1 -0
  56. package/dist/src/render-explain.d.ts +8 -0
  57. package/dist/src/render-explain.d.ts.map +1 -0
  58. package/dist/src/render-explain.js +57 -0
  59. package/dist/src/render-explain.js.map +1 -0
  60. package/dist/src/render-lint.d.ts +8 -0
  61. package/dist/src/render-lint.d.ts.map +1 -0
  62. package/dist/src/render-lint.js +57 -0
  63. package/dist/src/render-lint.js.map +1 -0
  64. package/dist/src/run.d.ts +8 -0
  65. package/dist/src/run.d.ts.map +1 -0
  66. package/dist/src/run.js +105 -0
  67. package/dist/src/run.js.map +1 -0
  68. package/dist/src/style.d.ts +16 -0
  69. package/dist/src/style.d.ts.map +1 -0
  70. package/dist/src/style.js +22 -0
  71. package/dist/src/style.js.map +1 -0
  72. package/package.json +50 -0
  73. package/src/args.ts +145 -0
  74. package/src/commands/annotations.ts +107 -0
  75. package/src/commands/bundle.ts +71 -0
  76. package/src/commands/eval.ts +137 -0
  77. package/src/commands/lint.ts +71 -0
  78. package/src/commands/ls.ts +90 -0
  79. package/src/commands/resolve.ts +47 -0
  80. package/src/commands/view.ts +82 -0
  81. package/src/config.ts +209 -0
  82. package/src/index.ts +3 -0
  83. package/src/io.ts +77 -0
  84. package/src/render-eval.ts +55 -0
  85. package/src/render-explain.ts +64 -0
  86. package/src/render-lint.ts +63 -0
  87. package/src/run.ts +107 -0
  88. package/src/style.ts +37 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 markbrutx
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # @markbrutx/promptbook-cli
2
+
3
+ Thin terminal surface over [`@markbrutx/promptbook-core`](https://www.npmjs.com/package/@markbrutx/promptbook-core):
4
+ the command surface for agents and CI. Part of [promptbook](https://github.com/markbrutx/promptbook).
5
+
6
+ ```
7
+ npm i -D @markbrutx/promptbook-cli
8
+ ```
9
+
10
+ ## Commands
11
+
12
+ ```
13
+ promptbook resolve <name> --explain # assemble a prompt; print the explain trace
14
+ promptbook ls # list fragments / compositions / code-prompts
15
+ promptbook lint <name> # static checks: token budget, banned tokens, dead rules…
16
+ promptbook eval --case <fixture> # run fixtures against a model adapter → pass-rate
17
+ promptbook bundle -o book.generated.ts # serialize a prompts folder to a portable module
18
+ promptbook view # open the viewer (needs @markbrutx/promptbook-viewer)
19
+ promptbook annotations list|resolve|clear
20
+ ```
21
+
22
+ The prompts folder is resolved from `--dir`, then `promptbook.json`, then
23
+ `./prompts`.
24
+
25
+ ```
26
+ promptbook resolve assistant --ctx mode=terse --ctx locale=ru
27
+ ```
28
+
29
+ - **stdout** = payload; **stderr** = explain / warnings / errors.
30
+ - `--json` = machine-readable output on stdout.
31
+ - Honors `NO_COLOR`.
32
+
33
+ `eval` uses [`@markbrutx/promptbook-openrouter`](https://www.npmjs.com/package/@markbrutx/promptbook-openrouter)
34
+ as its default model adapter; `view` lazily imports the optional
35
+ [`@markbrutx/promptbook-viewer`](https://www.npmjs.com/package/@markbrutx/promptbook-viewer).
36
+
37
+ ## License
38
+
39
+ [MIT](./LICENSE)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "../src/run.js";
3
+
4
+ process.exit(await run(process.argv.slice(2)));
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=promptbook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptbook.d.ts","sourceRoot":"","sources":["../../bin/promptbook.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { run } from "../src/run.js";
3
+ process.exit(await run(process.argv.slice(2)));
4
+ //# sourceMappingURL=promptbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptbook.js","sourceRoot":"","sources":["../../bin/promptbook.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /** Normalized view of the command line, independent of `parseArgs` shape. */
2
+ export interface ParsedArgs {
3
+ /** First positional: the subcommand, or undefined when none was given. */
4
+ command: string | undefined;
5
+ /** Positionals after the subcommand (e.g. the prompt name). */
6
+ operands: string[];
7
+ help: boolean;
8
+ version: boolean;
9
+ dir?: string;
10
+ json: boolean;
11
+ explain: boolean;
12
+ /** bundle: write the generated module to this file instead of stdout. */
13
+ out?: string;
14
+ /** bundle: emit a plain module without the type-only import/annotation. */
15
+ plain: boolean;
16
+ /** Repeated `--ctx key=value` pairs, parsed later by config. */
17
+ ctx: string[];
18
+ contextFile?: string;
19
+ fragments: boolean;
20
+ compositions: boolean;
21
+ /** lint: estimated token ceiling for the token-budget rule. */
22
+ maxTokens?: number;
23
+ /** lint: treat warnings as failures for the exit code. */
24
+ strict: boolean;
25
+ /** eval: model id passed to the adapter (overrides promptbook.json). */
26
+ model?: string;
27
+ /** eval: default samples per fixture when the fixture sets none. */
28
+ samples?: number;
29
+ /** eval: a fixture passes when passRate >= this threshold. */
30
+ threshold?: number;
31
+ /** eval: run lint on each resolved variant before sampling. */
32
+ lint: boolean;
33
+ /** view: port for the viewer server (0/undefined picks a free port). */
34
+ port?: number;
35
+ /** view: do not open the browser after the server starts. */
36
+ noOpen: boolean;
37
+ }
38
+ /**
39
+ * Parse argv into {@link ParsedArgs}. Strict mode throws on unknown flags; the
40
+ * caller turns that into a friendly stderr message and a non-zero exit.
41
+ */
42
+ export declare function parseCliArgs(argv: string[]): ParsedArgs;
43
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../src/args.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,KAAK,EAAE,OAAO,CAAC;IACf,gEAAgE;IAChE,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,MAAM,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;IACd,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,MAAM,EAAE,OAAO,CAAC;CACjB;AAgCD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAsEvD"}
@@ -0,0 +1,96 @@
1
+ import { parseArgs } from "node:util";
2
+ /**
3
+ * Parse an optional numeric flag, validating against `spec`. Returns undefined
4
+ * when the flag was not given; throws a uniform `invalid --name` error when the
5
+ * value is not a number or falls outside the allowed range.
6
+ */
7
+ function parseNumberFlag(raw, name, spec) {
8
+ if (raw === undefined) {
9
+ return undefined;
10
+ }
11
+ const parsed = Number(raw);
12
+ const valid = Number.isFinite(parsed) &&
13
+ (!spec.integer || Number.isInteger(parsed)) &&
14
+ (spec.min === undefined || parsed >= spec.min) &&
15
+ (spec.max === undefined || parsed <= spec.max);
16
+ if (!valid) {
17
+ throw new Error(`invalid --${name} "${raw}"; expected ${spec.expected}`);
18
+ }
19
+ return parsed;
20
+ }
21
+ /**
22
+ * Parse argv into {@link ParsedArgs}. Strict mode throws on unknown flags; the
23
+ * caller turns that into a friendly stderr message and a non-zero exit.
24
+ */
25
+ export function parseCliArgs(argv) {
26
+ const { values, positionals } = parseArgs({
27
+ args: argv,
28
+ allowPositionals: true,
29
+ options: {
30
+ help: { type: "boolean", short: "h" },
31
+ version: { type: "boolean", short: "v" },
32
+ dir: { type: "string" },
33
+ json: { type: "boolean" },
34
+ explain: { type: "boolean" },
35
+ out: { type: "string", short: "o" },
36
+ plain: { type: "boolean" },
37
+ ctx: { type: "string", multiple: true },
38
+ "context-file": { type: "string" },
39
+ fragments: { type: "boolean" },
40
+ compositions: { type: "boolean" },
41
+ "max-tokens": { type: "string" },
42
+ strict: { type: "boolean" },
43
+ model: { type: "string" },
44
+ samples: { type: "string" },
45
+ threshold: { type: "string" },
46
+ lint: { type: "boolean" },
47
+ port: { type: "string" },
48
+ "no-open": { type: "boolean" },
49
+ },
50
+ });
51
+ const maxTokens = parseNumberFlag(values["max-tokens"], "max-tokens", {
52
+ integer: true,
53
+ min: 1,
54
+ expected: "a positive integer",
55
+ });
56
+ const samples = parseNumberFlag(values.samples, "samples", {
57
+ integer: true,
58
+ min: 1,
59
+ expected: "a positive integer",
60
+ });
61
+ const threshold = parseNumberFlag(values.threshold, "threshold", {
62
+ min: 0,
63
+ max: 1,
64
+ expected: "a number between 0 and 1",
65
+ });
66
+ const port = parseNumberFlag(values.port, "port", {
67
+ integer: true,
68
+ min: 0,
69
+ max: 65535,
70
+ expected: "a port between 0 and 65535",
71
+ });
72
+ return {
73
+ command: positionals[0],
74
+ operands: positionals.slice(1),
75
+ help: values.help ?? false,
76
+ version: values.version ?? false,
77
+ dir: values.dir,
78
+ json: values.json ?? false,
79
+ explain: values.explain ?? false,
80
+ out: values.out,
81
+ plain: values.plain ?? false,
82
+ ctx: values.ctx ?? [],
83
+ contextFile: values["context-file"],
84
+ fragments: values.fragments ?? false,
85
+ compositions: values.compositions ?? false,
86
+ maxTokens,
87
+ strict: values.strict ?? false,
88
+ model: values.model,
89
+ samples,
90
+ threshold,
91
+ lint: values.lint ?? false,
92
+ port,
93
+ noOpen: values["no-open"] ?? false,
94
+ };
95
+ }
96
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/args.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ParsedArgs } from "../args.js";
2
+ import type { IO } from "../io.js";
3
+ /**
4
+ * `annotations`: the terminal-agnostic side of the viewer's feedback bridge.
5
+ * `list` prints open annotations (or `--json`), `resolve <id>` removes one, and
6
+ * `clear` empties the queue. All operate on `<dir>/.annotations/inbox.jsonl` —
7
+ * the same file the viewer writes — so any agent can drain it from any terminal.
8
+ */
9
+ export declare function cmdAnnotations(args: ParsedArgs, io: IO): Promise<number>;
10
+ //# sourceMappingURL=annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../../src/commands/annotations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAuEnC;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB9E"}
@@ -0,0 +1,92 @@
1
+ import { join } from "node:path";
2
+ import { ANNOTATION_QUEUE_DIR, ANNOTATION_QUEUE_FILE, parseInbox, serializeInbox } from "@markbrutx/promptbook-core";
3
+ import { requirePromptsDir } from "../config.js";
4
+ import { formatContext, plural } from "../style.js";
5
+ function queueFile(promptsDir) {
6
+ return join(promptsDir, ANNOTATION_QUEUE_DIR, ANNOTATION_QUEUE_FILE);
7
+ }
8
+ /** Read the queue via the injected fs; a missing file reads as empty. */
9
+ async function readQueue(io, file) {
10
+ try {
11
+ return parseInbox(await io.fs.readFile(file));
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
17
+ function describeTarget(annotation) {
18
+ const { target } = annotation;
19
+ if (target.prompt !== undefined) {
20
+ const ctx = formatContext(target.context ?? {});
21
+ return ctx === "" ? target.prompt : `${target.prompt} @ ${ctx}`;
22
+ }
23
+ return target.fragmentId ?? "(unknown)";
24
+ }
25
+ function renderAnnotation(annotation) {
26
+ return [
27
+ `• ${annotation.id} [${describeTarget(annotation)}]`,
28
+ ` anchor: ${annotation.anchor.fragmentId} — “${annotation.anchor.anchorText}”`,
29
+ ` ${annotation.comment}`,
30
+ ].join("\n");
31
+ }
32
+ async function listAnnotations(args, io, file) {
33
+ const open = (await readQueue(io, file)).filter((a) => a.status === "open");
34
+ if (args.json) {
35
+ io.stdout(`${JSON.stringify(open, null, 2)}\n`);
36
+ return 0;
37
+ }
38
+ if (open.length === 0) {
39
+ io.stdout("No open annotations.\n");
40
+ return 0;
41
+ }
42
+ io.stdout(`${open.map(renderAnnotation).join("\n\n")}\n`);
43
+ return 0;
44
+ }
45
+ async function resolveAnnotation(args, io, file) {
46
+ const id = args.operands[1];
47
+ if (id === undefined || id === "") {
48
+ io.stderr('error: "annotations resolve" needs an <id>.\n');
49
+ return 1;
50
+ }
51
+ const all = await readQueue(io, file);
52
+ const next = all.filter((a) => a.id !== id);
53
+ if (next.length === all.length) {
54
+ io.stderr(`error: no annotation with id "${id}".\n`);
55
+ return 1;
56
+ }
57
+ await io.writeFile(file, serializeInbox(next));
58
+ io.stdout(`Resolved ${id}.\n`);
59
+ return 0;
60
+ }
61
+ async function clearAnnotations(io, file) {
62
+ const open = (await readQueue(io, file)).filter((a) => a.status === "open");
63
+ await io.writeFile(file, "");
64
+ io.stdout(`Cleared ${plural(open.length, "annotation")}.\n`);
65
+ return 0;
66
+ }
67
+ /**
68
+ * `annotations`: the terminal-agnostic side of the viewer's feedback bridge.
69
+ * `list` prints open annotations (or `--json`), `resolve <id>` removes one, and
70
+ * `clear` empties the queue. All operate on `<dir>/.annotations/inbox.jsonl` —
71
+ * the same file the viewer writes — so any agent can drain it from any terminal.
72
+ */
73
+ export async function cmdAnnotations(args, io) {
74
+ const promptsDir = await requirePromptsDir(io, args.dir);
75
+ if (promptsDir === null) {
76
+ return 1;
77
+ }
78
+ const file = queueFile(promptsDir);
79
+ const action = args.operands[0] ?? "list";
80
+ switch (action) {
81
+ case "list":
82
+ return listAnnotations(args, io, file);
83
+ case "resolve":
84
+ return resolveAnnotation(args, io, file);
85
+ case "clear":
86
+ return clearAnnotations(io, file);
87
+ default:
88
+ io.stderr(`error: unknown annotations action "${action}". Use list, resolve <id> or clear.\n`);
89
+ return 1;
90
+ }
91
+ }
92
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../../src/commands/annotations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ParsedArgs } from "../args.js";
2
+ import { type IO } from "../io.js";
3
+ /**
4
+ * `bundle [<dir>]`: load a prompts folder and emit it as a single importable
5
+ * module exporting `book: PromptBook` (so a runtime can import the book instead
6
+ * of reading the disk). Writes to stdout, or to a file with `-o`. `--json`
7
+ * emits a structured dump instead of the TypeScript module.
8
+ *
9
+ * The folder comes from the positional `<dir>`, else `--dir`, else config /
10
+ * `./prompts` (the standard resolution).
11
+ */
12
+ export declare function cmdBundle(args: ParsedArgs, io: IO): Promise<number>;
13
+ //# sourceMappingURL=bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/commands/bundle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAgB,KAAK,EAAE,EAAE,MAAM,UAAU,CAAC;AA+BjD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBzE"}
@@ -0,0 +1,61 @@
1
+ import { isAbsolute, relative, resolve as resolvePath, sep } from "node:path";
2
+ import { loadPrompts, serializeBook, serializeBookJson } from "@markbrutx/promptbook-core";
3
+ import { requirePromptsDir } from "../config.js";
4
+ import { emitWarnings } from "../io.js";
5
+ /** Rewrite an absolute source path to a portable, forward-slash path relative to `dir`. */
6
+ function relativizeSource(sourceFile, dir) {
7
+ if (!isAbsolute(sourceFile)) {
8
+ return sourceFile;
9
+ }
10
+ return relative(dir, sourceFile).split(sep).join("/");
11
+ }
12
+ /** Copy a keyed map, relativizing each value's `sourceFile`. */
13
+ function relativizeMap(map, dir) {
14
+ return new Map([...map].map(([key, value]) => [key, { ...value, sourceFile: relativizeSource(value.sourceFile, dir) }]));
15
+ }
16
+ /**
17
+ * Copy the book with every `sourceFile` made relative to the prompts folder, so
18
+ * the generated module carries portable paths instead of one machine's absolute
19
+ * layout. Resolution and lint ignore `sourceFile`, so this never affects output.
20
+ */
21
+ function portableBook(book, dir) {
22
+ return {
23
+ fragments: relativizeMap(book.fragments, dir),
24
+ compositions: relativizeMap(book.compositions, dir),
25
+ codePrompts: relativizeMap(book.codePrompts, dir),
26
+ warnings: book.warnings,
27
+ };
28
+ }
29
+ /**
30
+ * `bundle [<dir>]`: load a prompts folder and emit it as a single importable
31
+ * module exporting `book: PromptBook` (so a runtime can import the book instead
32
+ * of reading the disk). Writes to stdout, or to a file with `-o`. `--json`
33
+ * emits a structured dump instead of the TypeScript module.
34
+ *
35
+ * The folder comes from the positional `<dir>`, else `--dir`, else config /
36
+ * `./prompts` (the standard resolution).
37
+ */
38
+ export async function cmdBundle(args, io) {
39
+ const promptsDir = await requirePromptsDir(io, args.operands[0] ?? args.dir);
40
+ if (promptsDir === null) {
41
+ return 1;
42
+ }
43
+ const book = portableBook(await loadPrompts(promptsDir, io.fs), promptsDir);
44
+ emitWarnings(io, book.warnings);
45
+ const output = args.json ? serializeBookJson(book) : serializeBook(book, { typed: !args.plain });
46
+ if (args.out === undefined) {
47
+ io.stdout(output);
48
+ return 0;
49
+ }
50
+ const outPath = resolvePath(io.cwd(), args.out);
51
+ try {
52
+ await io.writeFile(outPath, output);
53
+ }
54
+ catch (error) {
55
+ io.stderr(`error: cannot write "${outPath}": ${error.message}\n`);
56
+ return 1;
57
+ }
58
+ io.stderr(`wrote ${outPath}\n`);
59
+ return 0;
60
+ }
61
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../src/commands/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ParsedArgs } from "../args.js";
2
+ import { type IO } from "../io.js";
3
+ /**
4
+ * `eval [<name|glob>]`: load fixtures from `<dir>/fixtures`, assemble each
5
+ * prompt, sample it through a model adapter and report pass-rate. A fixture
6
+ * passes when its `passRate >= --threshold` (default 1). Exit is non-zero when
7
+ * any fixture fails the gate or on any error (no key, unknown prompt/fixture,
8
+ * missing folder). `--lint` runs a static gate over every variant first; with
9
+ * any lint error it aborts before spending tokens. Adapter is injectable via
10
+ * `io.makeAdapter` so tests never touch the network.
11
+ */
12
+ export declare function cmdEval(args: ParsedArgs, io: IO): Promise<number>;
13
+ //# sourceMappingURL=eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/commands/eval.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAqC,KAAK,EAAE,EAAE,MAAM,UAAU,CAAC;AAoCtE;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwEvE"}
@@ -0,0 +1,113 @@
1
+ import { defaultRules, evaluate, lint, loadFixtures, loadPrompts, resolveBook } from "@markbrutx/promptbook-core";
2
+ import { openRouterAdapter } from "@markbrutx/promptbook-openrouter";
3
+ import { evalConfigFrom, loadConfig, requirePromptsDir } from "../config.js";
4
+ import { colorEnabled } from "../io.js";
5
+ import { renderEvalReport } from "../render-eval.js";
6
+ /** Convert a `name|glob` pattern (only `*` is special) into an anchored regex. */
7
+ function globToRegExp(pattern) {
8
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
9
+ return new RegExp(`^${escaped}$`);
10
+ }
11
+ /** Build the model adapter: the injected one for tests, else OpenRouter. */
12
+ function buildAdapter(io, options) {
13
+ if (io.makeAdapter) {
14
+ return io.makeAdapter(options);
15
+ }
16
+ if (options.model === undefined) {
17
+ throw new Error('eval requires a model: pass --model <id> or set "eval.model" in promptbook.json.');
18
+ }
19
+ const adapterOptions = { model: options.model, apiKey: options.apiKey, baseUrl: options.baseUrl };
20
+ return openRouterAdapter(adapterOptions);
21
+ }
22
+ /** Lint every resolved variant; return findings with error severity. */
23
+ function lintGate(book, fixtures, rules) {
24
+ const errors = [];
25
+ for (const fixture of fixtures) {
26
+ const result = resolveBook(book, fixture.prompt, fixture.context ?? {});
27
+ const report = lint({ book, result }, rules);
28
+ for (const finding of report.findings) {
29
+ if (finding.severity === "error") {
30
+ errors.push({ ...finding, message: `${fixture.name}: ${finding.message}` });
31
+ }
32
+ }
33
+ }
34
+ return errors;
35
+ }
36
+ /**
37
+ * `eval [<name|glob>]`: load fixtures from `<dir>/fixtures`, assemble each
38
+ * prompt, sample it through a model adapter and report pass-rate. A fixture
39
+ * passes when its `passRate >= --threshold` (default 1). Exit is non-zero when
40
+ * any fixture fails the gate or on any error (no key, unknown prompt/fixture,
41
+ * missing folder). `--lint` runs a static gate over every variant first; with
42
+ * any lint error it aborts before spending tokens. Adapter is injectable via
43
+ * `io.makeAdapter` so tests never touch the network.
44
+ */
45
+ export async function cmdEval(args, io) {
46
+ const config = await loadConfig(io);
47
+ const promptsDir = await requirePromptsDir(io, args.dir, config);
48
+ if (promptsDir === null) {
49
+ return 1;
50
+ }
51
+ let fixtures;
52
+ try {
53
+ fixtures = await loadFixtures(promptsDir, io.fs);
54
+ }
55
+ catch (error) {
56
+ io.stderr(`error: ${error.message}\n`);
57
+ return 1;
58
+ }
59
+ const filter = args.operands[0];
60
+ if (filter !== undefined) {
61
+ const re = globToRegExp(filter);
62
+ fixtures = fixtures.filter((f) => re.test(f.name));
63
+ if (fixtures.length === 0) {
64
+ io.stderr(`error: no fixtures match "${filter}".\n`);
65
+ return 1;
66
+ }
67
+ }
68
+ if (fixtures.length === 0) {
69
+ io.stderr(`error: no fixtures found in ${promptsDir}/fixtures.\n`);
70
+ return 1;
71
+ }
72
+ const book = await loadPrompts(promptsDir, io.fs);
73
+ const threshold = args.threshold ?? 1;
74
+ let report;
75
+ try {
76
+ if (args.lint) {
77
+ const errors = lintGate(book, fixtures, defaultRules());
78
+ if (errors.length > 0) {
79
+ io.stderr("error: lint gate failed before sampling:\n");
80
+ for (const finding of errors) {
81
+ io.stderr(` ${finding.ruleId}: ${finding.message}\n`);
82
+ }
83
+ return 1;
84
+ }
85
+ }
86
+ const evalConfig = evalConfigFrom(config);
87
+ const adapter = buildAdapter(io, {
88
+ model: args.model ?? evalConfig.model,
89
+ apiKey: io.env.OPENROUTER_API_KEY,
90
+ baseUrl: evalConfig.baseUrl,
91
+ });
92
+ const evalInput = {
93
+ book,
94
+ fixtures,
95
+ adapter,
96
+ passThreshold: threshold,
97
+ ...(args.samples !== undefined ? { samples: args.samples } : {}),
98
+ };
99
+ report = await evaluate(evalInput);
100
+ }
101
+ catch (error) {
102
+ io.stderr(`error: ${error.message}\n`);
103
+ return 1;
104
+ }
105
+ if (args.json) {
106
+ io.stdout(`${JSON.stringify(report, null, 2)}\n`);
107
+ }
108
+ else {
109
+ io.stdout(renderEvalReport(report, threshold, colorEnabled(io)));
110
+ }
111
+ return report.failed > 0 ? 1 : 0;
112
+ }
113
+ //# sourceMappingURL=eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../../src/commands/eval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { ParsedArgs } from "../args.js";
2
+ import { type IO } from "../io.js";
3
+ /**
4
+ * `lint [<prompt>]`: run static checks over the prompts folder. With a prompt
5
+ * it resolves under the given context and runs both book- and resolved-scope
6
+ * rules; without one it runs book-scope rules over the whole book. The report
7
+ * (human-readable or `--json`) goes to stdout; warnings go to stderr. Exit is
8
+ * non-zero when any error is found, or any warning under `--strict`.
9
+ */
10
+ export declare function cmdLint(args: ParsedArgs, io: IO): Promise<number>;
11
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../../src/commands/lint.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAA8B,KAAK,EAAE,EAAE,MAAM,UAAU,CAAC;AAG/D;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDvE"}