@markbrutx/promptbook-core 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.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/annotations.d.ts +56 -0
- package/dist/annotations.d.ts.map +1 -0
- package/dist/annotations.js +50 -0
- package/dist/annotations.js.map +1 -0
- package/dist/bundle.d.ts +44 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +135 -0
- package/dist/bundle.js.map +1 -0
- package/dist/edge/index.js +192 -0
- package/dist/edge.d.ts +12 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +11 -0
- package/dist/edge.js.map +1 -0
- package/dist/eval/assertions.d.ts +15 -0
- package/dist/eval/assertions.d.ts.map +1 -0
- package/dist/eval/assertions.js +131 -0
- package/dist/eval/assertions.js.map +1 -0
- package/dist/eval/evaluate.d.ts +15 -0
- package/dist/eval/evaluate.d.ts.map +1 -0
- package/dist/eval/evaluate.js +65 -0
- package/dist/eval/evaluate.js.map +1 -0
- package/dist/eval/load-fixtures.d.ts +12 -0
- package/dist/eval/load-fixtures.d.ts.map +1 -0
- package/dist/eval/load-fixtures.js +87 -0
- package/dist/eval/load-fixtures.js.map +1 -0
- package/dist/eval/types.d.ts +123 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +2 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/frontmatter.d.ts +12 -0
- package/dist/frontmatter.d.ts.map +1 -0
- package/dist/frontmatter.js +22 -0
- package/dist/frontmatter.js.map +1 -0
- package/dist/fs.d.ts +11 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +20 -0
- package/dist/fs.js.map +1 -0
- package/dist/guards.d.ts +6 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +9 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +11 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +25 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/lint/lint.d.ts +11 -0
- package/dist/lint/lint.d.ts.map +1 -0
- package/dist/lint/lint.js +30 -0
- package/dist/lint/lint.js.map +1 -0
- package/dist/lint/references.d.ts +18 -0
- package/dist/lint/references.d.ts.map +1 -0
- package/dist/lint/references.js +39 -0
- package/dist/lint/references.js.map +1 -0
- package/dist/lint/rules/banned-tokens.d.ts +13 -0
- package/dist/lint/rules/banned-tokens.d.ts.map +1 -0
- package/dist/lint/rules/banned-tokens.js +38 -0
- package/dist/lint/rules/banned-tokens.js.map +1 -0
- package/dist/lint/rules/dangling-reference.d.ts +11 -0
- package/dist/lint/rules/dangling-reference.d.ts.map +1 -0
- package/dist/lint/rules/dangling-reference.js +37 -0
- package/dist/lint/rules/dangling-reference.js.map +1 -0
- package/dist/lint/rules/dead-rule.d.ts +21 -0
- package/dist/lint/rules/dead-rule.d.ts.map +1 -0
- package/dist/lint/rules/dead-rule.js +135 -0
- package/dist/lint/rules/dead-rule.js.map +1 -0
- package/dist/lint/rules/example-balance.d.ts +19 -0
- package/dist/lint/rules/example-balance.d.ts.map +1 -0
- package/dist/lint/rules/example-balance.js +57 -0
- package/dist/lint/rules/example-balance.js.map +1 -0
- package/dist/lint/rules/index.d.ts +28 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/index.js +30 -0
- package/dist/lint/rules/index.js.map +1 -0
- package/dist/lint/rules/language-directive-position.d.ts +16 -0
- package/dist/lint/rules/language-directive-position.d.ts.map +1 -0
- package/dist/lint/rules/language-directive-position.js +42 -0
- package/dist/lint/rules/language-directive-position.js.map +1 -0
- package/dist/lint/rules/token-budget.d.ts +18 -0
- package/dist/lint/rules/token-budget.d.ts.map +1 -0
- package/dist/lint/rules/token-budget.js +39 -0
- package/dist/lint/rules/token-budget.js.map +1 -0
- package/dist/lint/rules/unused-fragment.d.ts +11 -0
- package/dist/lint/rules/unused-fragment.d.ts.map +1 -0
- package/dist/lint/rules/unused-fragment.js +33 -0
- package/dist/lint/rules/unused-fragment.js.map +1 -0
- package/dist/lint/types.d.ts +50 -0
- package/dist/lint/types.d.ts.map +1 -0
- package/dist/lint/types.js +2 -0
- package/dist/lint/types.js.map +1 -0
- package/dist/load.d.ts +12 -0
- package/dist/load.d.ts.map +1 -0
- package/dist/load.js +238 -0
- package/dist/load.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +25 -0
- package/dist/paths.js.map +1 -0
- package/dist/resolve-book.d.ts +15 -0
- package/dist/resolve-book.d.ts.map +1 -0
- package/dist/resolve-book.js +195 -0
- package/dist/resolve-book.js.map +1 -0
- package/dist/resolve.d.ts +13 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +17 -0
- package/dist/resolve.js.map +1 -0
- package/dist/types.d.ts +173 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/package.json +48 -0
- package/src/annotations.ts +100 -0
- package/src/bundle.ts +163 -0
- package/src/edge.ts +11 -0
- package/src/eval/assertions.ts +174 -0
- package/src/eval/evaluate.ts +84 -0
- package/src/eval/load-fixtures.ts +91 -0
- package/src/eval/types.ts +134 -0
- package/src/frontmatter.ts +28 -0
- package/src/fs.ts +21 -0
- package/src/guards.ts +11 -0
- package/src/index.ts +84 -0
- package/src/interpolate.ts +27 -0
- package/src/lint/lint.ts +32 -0
- package/src/lint/references.ts +50 -0
- package/src/lint/rules/banned-tokens.ts +46 -0
- package/src/lint/rules/dangling-reference.ts +43 -0
- package/src/lint/rules/dead-rule.ts +147 -0
- package/src/lint/rules/example-balance.ts +68 -0
- package/src/lint/rules/index.ts +47 -0
- package/src/lint/rules/language-directive-position.ts +51 -0
- package/src/lint/rules/token-budget.ts +50 -0
- package/src/lint/rules/unused-fragment.ts +38 -0
- package/src/lint/types.ts +55 -0
- package/src/load.ts +282 -0
- package/src/paths.ts +27 -0
- package/src/resolve-book.ts +237 -0
- package/src/resolve.ts +18 -0
- package/src/types.ts +191 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lint/rules/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAO,GAAwB,EAAE;IAC5D,OAAO;QACL,WAAW,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,yBAAyB,EAAE;QAC3B,cAAc,EAAE;QAChB,YAAY,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,cAAc,EAAE;QAChB,iBAAiB,EAAE;QACnB,QAAQ,EAAE;KACX,CAAC;AACJ,CAAC;AAGD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAE7E,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LintRule, Severity } from "../types.js";
|
|
2
|
+
export interface LanguageDirectivePositionOptions {
|
|
3
|
+
/** Fragment `kind` that must sit at an edge. */
|
|
4
|
+
kind?: string;
|
|
5
|
+
/** How many leading/trailing positions count as an edge. */
|
|
6
|
+
edgeWindow?: number;
|
|
7
|
+
severity?: Severity;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* `language-directive-position` (resolved): fragments of the configured kind
|
|
11
|
+
* must appear within the first or last `edgeWindow` positions of the final
|
|
12
|
+
* order. A language directive buried in the middle is easy for a model to
|
|
13
|
+
* miss, so it is flagged.
|
|
14
|
+
*/
|
|
15
|
+
export declare function languageDirectivePosition(options?: LanguageDirectivePositionOptions): LintRule;
|
|
16
|
+
//# sourceMappingURL=language-directive-position.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-directive-position.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/language-directive-position.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,gCAAgC;IAC/C,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,gCAAqC,GAAG,QAAQ,CAkClG"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `language-directive-position` (resolved): fragments of the configured kind
|
|
3
|
+
* must appear within the first or last `edgeWindow` positions of the final
|
|
4
|
+
* order. A language directive buried in the middle is easy for a model to
|
|
5
|
+
* miss, so it is flagged.
|
|
6
|
+
*/
|
|
7
|
+
export function languageDirectivePosition(options = {}) {
|
|
8
|
+
const kind = options.kind ?? "language-directive";
|
|
9
|
+
const edgeWindow = options.edgeWindow ?? 2;
|
|
10
|
+
const severity = options.severity ?? "warning";
|
|
11
|
+
return {
|
|
12
|
+
id: "language-directive-position",
|
|
13
|
+
description: `Fragments of kind "${kind}" should sit within the first/last ${edgeWindow} positions.`,
|
|
14
|
+
scope: "resolved",
|
|
15
|
+
check(input) {
|
|
16
|
+
const result = input.result;
|
|
17
|
+
if (result === undefined) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const order = result.trace.finalOrder;
|
|
21
|
+
const total = order.length;
|
|
22
|
+
const findings = [];
|
|
23
|
+
order.forEach((id, position) => {
|
|
24
|
+
if (input.book.fragments.get(id)?.kind !== kind) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const atStart = position < edgeWindow;
|
|
28
|
+
const atEnd = position >= total - edgeWindow;
|
|
29
|
+
if (!atStart && !atEnd) {
|
|
30
|
+
findings.push({
|
|
31
|
+
ruleId: "language-directive-position",
|
|
32
|
+
severity,
|
|
33
|
+
message: `fragment "${id}" (kind "${kind}") is at position ${position + 1} of ${total}, not within the first/last ${edgeWindow}`,
|
|
34
|
+
fragmentId: id,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return findings;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=language-directive-position.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-directive-position.js","sourceRoot":"","sources":["../../../src/lint/rules/language-directive-position.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAO,GAAqC,EAAE;IACtF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,oBAAoB,CAAC;IAClD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC/C,OAAO;QACL,EAAE,EAAE,6BAA6B;QACjC,WAAW,EAAE,sBAAsB,IAAI,sCAAsC,UAAU,aAAa;QACpG,KAAK,EAAE,UAAU;QACjB,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC;YACtC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,MAAM,QAAQ,GAAkB,EAAE,CAAC;YACnC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;gBAC7B,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;oBAChD,OAAO;gBACT,CAAC;gBACD,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;gBACtC,MAAM,KAAK,GAAG,QAAQ,IAAI,KAAK,GAAG,UAAU,CAAC;gBAC7C,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;oBACvB,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,6BAA6B;wBACrC,QAAQ;wBACR,OAAO,EAAE,aAAa,EAAE,YAAY,IAAI,qBAAqB,QAAQ,GAAG,CAAC,OAAO,KAAK,+BAA+B,UAAU,EAAE;wBAChI,UAAU,EAAE,EAAE;qBACf,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LintRule, Severity } from "../types.js";
|
|
2
|
+
/** Heuristic token estimate: ~4 characters per token. Not a real tokenizer. */
|
|
3
|
+
export declare function estimateTokensByChars(text: string): number;
|
|
4
|
+
export interface TokenBudgetOptions {
|
|
5
|
+
/** Maximum estimated tokens before a finding is raised. */
|
|
6
|
+
maxTokens?: number;
|
|
7
|
+
/** Inject a real token counter; defaults to the chars/4 heuristic. */
|
|
8
|
+
estimateTokens?: (text: string) => number;
|
|
9
|
+
severity?: Severity;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `token-budget` (resolved): estimate the assembled text's token count and
|
|
13
|
+
* report when it exceeds `maxTokens`. The estimate is a deterministic
|
|
14
|
+
* heuristic (chars/4) so the core stays dependency-free; callers can inject a
|
|
15
|
+
* precise counter via `estimateTokens`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function tokenBudget(options?: TokenBudgetOptions): LintRule;
|
|
18
|
+
//# sourceMappingURL=token-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-budget.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/token-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAID;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,QAAQ,CA0BtE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Heuristic token estimate: ~4 characters per token. Not a real tokenizer. */
|
|
2
|
+
export function estimateTokensByChars(text) {
|
|
3
|
+
return Math.ceil(text.length / 4);
|
|
4
|
+
}
|
|
5
|
+
const DEFAULT_MAX_TOKENS = 8000;
|
|
6
|
+
/**
|
|
7
|
+
* `token-budget` (resolved): estimate the assembled text's token count and
|
|
8
|
+
* report when it exceeds `maxTokens`. The estimate is a deterministic
|
|
9
|
+
* heuristic (chars/4) so the core stays dependency-free; callers can inject a
|
|
10
|
+
* precise counter via `estimateTokens`.
|
|
11
|
+
*/
|
|
12
|
+
export function tokenBudget(options = {}) {
|
|
13
|
+
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
14
|
+
const estimate = options.estimateTokens ?? estimateTokensByChars;
|
|
15
|
+
const severity = options.severity ?? "warning";
|
|
16
|
+
return {
|
|
17
|
+
id: "token-budget",
|
|
18
|
+
description: `Resolved prompt should fit within ~${maxTokens} estimated tokens.`,
|
|
19
|
+
scope: "resolved",
|
|
20
|
+
check(input) {
|
|
21
|
+
const result = input.result;
|
|
22
|
+
if (result === undefined) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const tokens = estimate(result.text);
|
|
26
|
+
if (tokens <= maxTokens) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
ruleId: "token-budget",
|
|
32
|
+
severity,
|
|
33
|
+
message: `estimated ${tokens} tokens exceeds budget of ${maxTokens}`,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=token-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../../src/lint/rules/token-budget.ts"],"names":[],"mappings":"AAEA,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAUD,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,OAAO,GAAuB,EAAE;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,IAAI,qBAAqB,CAAC;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC/C,OAAO;QACL,EAAE,EAAE,cAAc;QAClB,WAAW,EAAE,sCAAsC,SAAS,oBAAoB;QAChF,KAAK,EAAE,UAAU;QACjB,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC5B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO;gBACL;oBACE,MAAM,EAAE,cAAc;oBACtB,QAAQ;oBACR,OAAO,EAAE,aAAa,MAAM,6BAA6B,SAAS,EAAE;iBACrE;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LintRule, Severity } from "../types.js";
|
|
2
|
+
export interface UnusedFragmentOptions {
|
|
3
|
+
severity?: Severity;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* `unused-fragment` (book): a fragment that no composition mentions — not in a
|
|
7
|
+
* base, order, or any rule (add/replace/forbid/order/after) — is dead weight
|
|
8
|
+
* and is flagged. Findings are sorted by id for deterministic output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function unusedFragment(options?: UnusedFragmentOptions): LintRule;
|
|
11
|
+
//# sourceMappingURL=unused-fragment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unused-fragment.d.ts","sourceRoot":"","sources":["../../../src/lint/rules/unused-fragment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,QAAQ,CAyB5E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { iterateReferences } from "../references.js";
|
|
2
|
+
/**
|
|
3
|
+
* `unused-fragment` (book): a fragment that no composition mentions — not in a
|
|
4
|
+
* base, order, or any rule (add/replace/forbid/order/after) — is dead weight
|
|
5
|
+
* and is flagged. Findings are sorted by id for deterministic output.
|
|
6
|
+
*/
|
|
7
|
+
export function unusedFragment(options = {}) {
|
|
8
|
+
const severity = options.severity ?? "warning";
|
|
9
|
+
return {
|
|
10
|
+
id: "unused-fragment",
|
|
11
|
+
description: "Every fragment should be referenced by at least one composition or rule.",
|
|
12
|
+
scope: "book",
|
|
13
|
+
check(input) {
|
|
14
|
+
const referenced = new Set();
|
|
15
|
+
for (const reference of iterateReferences(input.book)) {
|
|
16
|
+
referenced.add(reference.id);
|
|
17
|
+
}
|
|
18
|
+
const findings = [];
|
|
19
|
+
for (const id of [...input.book.fragments.keys()].sort()) {
|
|
20
|
+
if (!referenced.has(id)) {
|
|
21
|
+
findings.push({
|
|
22
|
+
ruleId: "unused-fragment",
|
|
23
|
+
severity,
|
|
24
|
+
message: `fragment "${id}" is not referenced by any composition or rule`,
|
|
25
|
+
fragmentId: id,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return findings;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=unused-fragment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unused-fragment.js","sourceRoot":"","sources":["../../../src/lint/rules/unused-fragment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAOrD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAO,GAA0B,EAAE;IAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;IAC/C,OAAO;QACL,EAAE,EAAE,iBAAiB;QACrB,WAAW,EAAE,0EAA0E;QACvF,KAAK,EAAE,MAAM;QACb,KAAK,CAAC,KAAK;YACT,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;YACrC,KAAK,MAAM,SAAS,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtD,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;YACD,MAAM,QAAQ,GAAkB,EAAE,CAAC;YACnC,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBACxB,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,iBAAiB;wBACzB,QAAQ;wBACR,OAAO,EAAE,aAAa,EAAE,gDAAgD;wBACxE,UAAU,EAAE,EAAE;qBACf,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the lint engine.
|
|
3
|
+
*
|
|
4
|
+
* Lint is static and deterministic: it runs pluggable rules over an assembled
|
|
5
|
+
* `{ text, trace }` and/or the book structure. It never calls a model and adds
|
|
6
|
+
* no runtime dependencies.
|
|
7
|
+
*/
|
|
8
|
+
import type { PromptBook, ResolveResult } from "../types.js";
|
|
9
|
+
/** How serious a finding is. `error` drives a non-zero CLI exit. */
|
|
10
|
+
export type Severity = "error" | "warning" | "info";
|
|
11
|
+
/** When a rule can run: over a resolved prompt, or over the book structure. */
|
|
12
|
+
export type LintScope = "resolved" | "book";
|
|
13
|
+
/** A single problem a rule reports. */
|
|
14
|
+
export interface LintFinding {
|
|
15
|
+
/** Id of the rule that produced this finding. */
|
|
16
|
+
ruleId: string;
|
|
17
|
+
severity: Severity;
|
|
18
|
+
/** Human-readable, domain-agnostic description. */
|
|
19
|
+
message: string;
|
|
20
|
+
/** Fragment the finding points at, when applicable. */
|
|
21
|
+
fragmentId?: string;
|
|
22
|
+
/** Composition rule index the finding points at, when applicable. */
|
|
23
|
+
ruleIndex?: number;
|
|
24
|
+
}
|
|
25
|
+
/** What lint runs against. `result` is present only for resolved-scope rules. */
|
|
26
|
+
export interface LintInput {
|
|
27
|
+
book: PromptBook;
|
|
28
|
+
result?: ResolveResult;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A pluggable rule. Created by a factory so thresholds are configurable, e.g.
|
|
32
|
+
* `tokenBudget({ maxTokens })`. `check` is pure: same input, same findings.
|
|
33
|
+
*/
|
|
34
|
+
export interface LintRule {
|
|
35
|
+
/** Stable id, e.g. "token-budget". */
|
|
36
|
+
id: string;
|
|
37
|
+
/** One-line explanation of what the rule enforces. */
|
|
38
|
+
description: string;
|
|
39
|
+
/** Scope decides whether the rule needs `input.result`. */
|
|
40
|
+
scope: LintScope;
|
|
41
|
+
/** Inspect the input and return zero or more findings. */
|
|
42
|
+
check(input: LintInput): LintFinding[];
|
|
43
|
+
}
|
|
44
|
+
/** The aggregated outcome of a lint run. */
|
|
45
|
+
export interface LintReport {
|
|
46
|
+
findings: LintFinding[];
|
|
47
|
+
errorCount: number;
|
|
48
|
+
warningCount: number;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lint/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7D,oEAAoE;AACpE,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5C,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iFAAiF;AACjF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,KAAK,EAAE,SAAS,CAAC;IACjB,0DAA0D;IAC1D,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,EAAE,CAAC;CACxC;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lint/types.ts"],"names":[],"mappings":""}
|
package/dist/load.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FsAdapter, PromptBook } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Load a prompts folder (`fragments/` + `rules/` + optional `code-prompts/`)
|
|
4
|
+
* into a {@link PromptBook}.
|
|
5
|
+
*
|
|
6
|
+
* Throws only on structural errors (missing/duplicate fragment id, malformed
|
|
7
|
+
* rule). Soft issues (empty rules file, duplicate composition name, broken
|
|
8
|
+
* code-prompt manifest/sample) become warnings. Code-prompts hold snapshot text
|
|
9
|
+
* only — the builder is never executed. Reference checks happen in `resolve`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadPrompts(promptsDir: string, fs?: FsAdapter): Promise<PromptBook>;
|
|
12
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAOV,SAAS,EACT,UAAU,EAGX,MAAM,YAAY,CAAC;AAwPpB;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,GAAE,SAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQnG"}
|
package/dist/load.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { parse as parseYaml } from "yaml";
|
|
2
|
+
import { parseFrontmatter } from "./frontmatter.js";
|
|
3
|
+
import { nodeFs } from "./fs.js";
|
|
4
|
+
import { isContextValue, isMapping } from "./guards.js";
|
|
5
|
+
import { joinPath, listFiles, stripExt } from "./paths.js";
|
|
6
|
+
const ACTION_KEYS = ["add", "replace", "forbid", "order"];
|
|
7
|
+
function toStringArray(raw) {
|
|
8
|
+
if (!Array.isArray(raw)) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
return raw.map((value) => String(value));
|
|
12
|
+
}
|
|
13
|
+
function toScalar(value) {
|
|
14
|
+
return isContextValue(value) ? value : String(value);
|
|
15
|
+
}
|
|
16
|
+
function parseWhen(raw) {
|
|
17
|
+
if (!isMapping(raw)) {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
const when = {};
|
|
21
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
22
|
+
when[key] = toScalar(value);
|
|
23
|
+
}
|
|
24
|
+
return when;
|
|
25
|
+
}
|
|
26
|
+
/** Parse a context bag, or `undefined` when absent/empty (keeps the field optional). */
|
|
27
|
+
function parseContextBag(raw) {
|
|
28
|
+
const bag = parseWhen(raw);
|
|
29
|
+
return Object.keys(bag).length > 0 ? bag : undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Load every `.yaml`/`.yml` file in `dir` into a name-keyed map. Owns the shared
|
|
33
|
+
* scaffold: parallel reads, skip-with-warning on a non-mapping doc, and the
|
|
34
|
+
* duplicate-name warning (later wins). The caller's `build` turns one parsed doc
|
|
35
|
+
* into a named value; `noun` labels the warnings ("Composition", "Code-prompt").
|
|
36
|
+
*/
|
|
37
|
+
async function loadYamlDir(fs, dir, noun, warnings, build) {
|
|
38
|
+
const map = new Map();
|
|
39
|
+
const files = await listFiles(fs, dir, [".yaml", ".yml"]);
|
|
40
|
+
const loaded = await Promise.all(files.map(async (file) => {
|
|
41
|
+
const full = joinPath(dir, file);
|
|
42
|
+
return { file, full, raw: await fs.readFile(full) };
|
|
43
|
+
}));
|
|
44
|
+
for (const { file, full, raw } of loaded) {
|
|
45
|
+
const doc = parseYaml(raw);
|
|
46
|
+
if (!isMapping(doc)) {
|
|
47
|
+
warnings.push(`${noun} file "${full}" is empty or not a mapping; skipped.`);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const value = await build(doc, file, full);
|
|
51
|
+
const previous = map.get(value.name);
|
|
52
|
+
if (previous) {
|
|
53
|
+
warnings.push(`Duplicate ${noun.toLowerCase()} name "${value.name}" in "${previous.sourceFile}" and "${full}"; using the latter.`);
|
|
54
|
+
}
|
|
55
|
+
map.set(value.name, value);
|
|
56
|
+
}
|
|
57
|
+
return map;
|
|
58
|
+
}
|
|
59
|
+
function parseReplaceMap(raw, index, file) {
|
|
60
|
+
if (!isMapping(raw)) {
|
|
61
|
+
throw new Error(`Rule #${index} in "${file}" has a "replace" that is not a mapping.`);
|
|
62
|
+
}
|
|
63
|
+
const map = {};
|
|
64
|
+
for (const [from, to] of Object.entries(raw)) {
|
|
65
|
+
map[from] = String(to);
|
|
66
|
+
}
|
|
67
|
+
return map;
|
|
68
|
+
}
|
|
69
|
+
function parseRule(entry, index, file) {
|
|
70
|
+
if (!isMapping(entry)) {
|
|
71
|
+
throw new Error(`Rule #${index} in "${file}" must be a mapping.`);
|
|
72
|
+
}
|
|
73
|
+
const obj = entry;
|
|
74
|
+
const present = ACTION_KEYS.filter((key) => obj[key] !== undefined);
|
|
75
|
+
if (present.length !== 1) {
|
|
76
|
+
throw new Error(`Rule #${index} in "${file}" must declare exactly one action (${ACTION_KEYS.join(" / ")}); found ${present.length}.`);
|
|
77
|
+
}
|
|
78
|
+
const action = present[0];
|
|
79
|
+
const rule = { index, when: parseWhen(obj.when), action };
|
|
80
|
+
switch (action) {
|
|
81
|
+
case "add":
|
|
82
|
+
rule.add = toStringArray(obj.add);
|
|
83
|
+
if (typeof obj.after === "string") {
|
|
84
|
+
rule.after = obj.after;
|
|
85
|
+
}
|
|
86
|
+
break;
|
|
87
|
+
case "replace":
|
|
88
|
+
rule.replace = parseReplaceMap(obj.replace, index, file);
|
|
89
|
+
break;
|
|
90
|
+
case "forbid":
|
|
91
|
+
rule.forbid = toStringArray(obj.forbid);
|
|
92
|
+
break;
|
|
93
|
+
case "order":
|
|
94
|
+
rule.order = toStringArray(obj.order);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
return rule;
|
|
98
|
+
}
|
|
99
|
+
function parseRules(raw, file) {
|
|
100
|
+
if (raw === undefined || raw === null) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
if (!Array.isArray(raw)) {
|
|
104
|
+
throw new Error(`"rules" in "${file}" must be a list.`);
|
|
105
|
+
}
|
|
106
|
+
return raw.map((entry, index) => parseRule(entry, index, file));
|
|
107
|
+
}
|
|
108
|
+
async function loadFragments(fs, dir) {
|
|
109
|
+
const fragments = new Map();
|
|
110
|
+
const sourceById = new Map();
|
|
111
|
+
const fragmentsDir = joinPath(dir, "fragments");
|
|
112
|
+
const files = await listFiles(fs, fragmentsDir, [".md", ".markdown"]);
|
|
113
|
+
// Reads run in parallel; the sorted file order still drives processing,
|
|
114
|
+
// so duplicate detection and output stay deterministic.
|
|
115
|
+
const loaded = await Promise.all(files.map(async (file) => {
|
|
116
|
+
const full = joinPath(fragmentsDir, file);
|
|
117
|
+
return { full, raw: await fs.readFile(full) };
|
|
118
|
+
}));
|
|
119
|
+
for (const { full, raw } of loaded) {
|
|
120
|
+
const { data, body } = parseFrontmatter(raw);
|
|
121
|
+
const id = typeof data.id === "string" ? data.id : undefined;
|
|
122
|
+
if (!id) {
|
|
123
|
+
throw new Error(`Fragment "${full}" is missing a string "id" in its frontmatter.`);
|
|
124
|
+
}
|
|
125
|
+
const existing = sourceById.get(id);
|
|
126
|
+
if (existing) {
|
|
127
|
+
throw new Error(`Duplicate fragment id "${id}" in "${existing}" and "${full}".`);
|
|
128
|
+
}
|
|
129
|
+
sourceById.set(id, full);
|
|
130
|
+
const fragment = { id, body: body.trim(), sourceFile: full };
|
|
131
|
+
if (typeof data.kind === "string") {
|
|
132
|
+
fragment.kind = data.kind;
|
|
133
|
+
}
|
|
134
|
+
if (Array.isArray(data.tags)) {
|
|
135
|
+
fragment.tags = data.tags.map((tag) => String(tag));
|
|
136
|
+
}
|
|
137
|
+
fragments.set(id, fragment);
|
|
138
|
+
}
|
|
139
|
+
return fragments;
|
|
140
|
+
}
|
|
141
|
+
function loadCompositions(fs, dir, warnings) {
|
|
142
|
+
return loadYamlDir(fs, joinPath(dir, "rules"), "Composition", warnings, (obj, file, full) => {
|
|
143
|
+
const name = typeof obj.name === "string" ? obj.name : stripExt(file);
|
|
144
|
+
const composition = {
|
|
145
|
+
name,
|
|
146
|
+
base: toStringArray(obj.base),
|
|
147
|
+
rules: parseRules(obj.rules, full),
|
|
148
|
+
sourceFile: full,
|
|
149
|
+
};
|
|
150
|
+
if (obj.order !== undefined) {
|
|
151
|
+
composition.order = toStringArray(obj.order);
|
|
152
|
+
}
|
|
153
|
+
return composition;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Load the captured output samples of one code-prompt manifest. A sample's text
|
|
158
|
+
* comes inline (`output`) or from a sibling file (`file`). Malformed entries
|
|
159
|
+
* and missing files become warnings, never throws — the core never runs the
|
|
160
|
+
* builder, so a broken snapshot just drops out of the menu.
|
|
161
|
+
*/
|
|
162
|
+
async function loadCodePromptSamples(fs, codeDir, raw, manifest, warnings) {
|
|
163
|
+
if (raw === undefined || raw === null) {
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
if (!Array.isArray(raw)) {
|
|
167
|
+
warnings.push(`"samples" in "${manifest}" must be a list; ignored.`);
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
const samples = [];
|
|
171
|
+
for (let index = 0; index < raw.length; index++) {
|
|
172
|
+
const entry = raw[index];
|
|
173
|
+
if (!isMapping(entry)) {
|
|
174
|
+
warnings.push(`Sample #${index} in "${manifest}" must be a mapping; skipped.`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const label = typeof entry.label === "string" ? entry.label : undefined;
|
|
178
|
+
if (!label) {
|
|
179
|
+
warnings.push(`Sample #${index} in "${manifest}" is missing a string "label"; skipped.`);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
let output;
|
|
183
|
+
if (typeof entry.output === "string") {
|
|
184
|
+
output = entry.output;
|
|
185
|
+
}
|
|
186
|
+
else if (typeof entry.file === "string") {
|
|
187
|
+
try {
|
|
188
|
+
output = await fs.readFile(joinPath(codeDir, entry.file));
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
warnings.push(`Sample "${label}" in "${manifest}" references missing file "${entry.file}"; skipped.`);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
warnings.push(`Sample "${label}" in "${manifest}" must set "output" or "file"; skipped.`);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const sample = { label, output };
|
|
200
|
+
const context = parseContextBag(entry.context);
|
|
201
|
+
if (context !== undefined) {
|
|
202
|
+
sample.context = context;
|
|
203
|
+
}
|
|
204
|
+
samples.push(sample);
|
|
205
|
+
}
|
|
206
|
+
return samples;
|
|
207
|
+
}
|
|
208
|
+
function loadCodePrompts(fs, dir, warnings) {
|
|
209
|
+
const codeDir = joinPath(dir, "code-prompts");
|
|
210
|
+
return loadYamlDir(fs, codeDir, "Code-prompt", warnings, async (obj, file, full) => {
|
|
211
|
+
const name = typeof obj.name === "string" ? obj.name : stripExt(file);
|
|
212
|
+
const samples = await loadCodePromptSamples(fs, codeDir, obj.samples, full, warnings);
|
|
213
|
+
const codePrompt = { name, samples, sourceFile: full };
|
|
214
|
+
if (typeof obj.description === "string") {
|
|
215
|
+
codePrompt.description = obj.description;
|
|
216
|
+
}
|
|
217
|
+
return codePrompt;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Load a prompts folder (`fragments/` + `rules/` + optional `code-prompts/`)
|
|
222
|
+
* into a {@link PromptBook}.
|
|
223
|
+
*
|
|
224
|
+
* Throws only on structural errors (missing/duplicate fragment id, malformed
|
|
225
|
+
* rule). Soft issues (empty rules file, duplicate composition name, broken
|
|
226
|
+
* code-prompt manifest/sample) become warnings. Code-prompts hold snapshot text
|
|
227
|
+
* only — the builder is never executed. Reference checks happen in `resolve`.
|
|
228
|
+
*/
|
|
229
|
+
export async function loadPrompts(promptsDir, fs = nodeFs()) {
|
|
230
|
+
const warnings = [];
|
|
231
|
+
const [fragments, compositions, codePrompts] = await Promise.all([
|
|
232
|
+
loadFragments(fs, promptsDir),
|
|
233
|
+
loadCompositions(fs, promptsDir, warnings),
|
|
234
|
+
loadCodePrompts(fs, promptsDir, warnings),
|
|
235
|
+
]);
|
|
236
|
+
return { fragments, compositions, codePrompts, warnings };
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=load.js.map
|
package/dist/load.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FsAdapter } from "./types.js";
|
|
2
|
+
/** Join a directory and child with a single `/`, tolerating a trailing slash. */
|
|
3
|
+
export declare function joinPath(dir: string, child: string): string;
|
|
4
|
+
/** Drop a file extension, e.g. `assistant.yaml` -> `assistant`. */
|
|
5
|
+
export declare function stripExt(name: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* List files in `dir` whose name ends with one of `exts`, sorted for
|
|
8
|
+
* deterministic processing. A missing/unreadable directory yields `[]` so
|
|
9
|
+
* callers can treat an absent folder as "no files".
|
|
10
|
+
*/
|
|
11
|
+
export declare function listFiles(fs: FsAdapter, dir: string, exts: string[]): Promise<string[]>;
|
|
12
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,mEAAmE;AACnE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7F"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Join a directory and child with a single `/`, tolerating a trailing slash. */
|
|
2
|
+
export function joinPath(dir, child) {
|
|
3
|
+
return dir.endsWith("/") ? `${dir}${child}` : `${dir}/${child}`;
|
|
4
|
+
}
|
|
5
|
+
/** Drop a file extension, e.g. `assistant.yaml` -> `assistant`. */
|
|
6
|
+
export function stripExt(name) {
|
|
7
|
+
const dot = name.lastIndexOf(".");
|
|
8
|
+
return dot === -1 ? name : name.slice(0, dot);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* List files in `dir` whose name ends with one of `exts`, sorted for
|
|
12
|
+
* deterministic processing. A missing/unreadable directory yields `[]` so
|
|
13
|
+
* callers can treat an absent folder as "no files".
|
|
14
|
+
*/
|
|
15
|
+
export async function listFiles(fs, dir, exts) {
|
|
16
|
+
let entries;
|
|
17
|
+
try {
|
|
18
|
+
entries = await fs.readDir(dir);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
return entries.filter((name) => exts.some((ext) => name.endsWith(ext))).sort();
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAEA,iFAAiF;AACjF,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,KAAa;IACjD,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;AAClE,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,EAAa,EAAE,GAAW,EAAE,IAAc;IACxE,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Context, ContextValue, PromptBook, ResolveResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pure resolver over an already-loaded {@link PromptBook}. No filesystem, no
|
|
4
|
+
* YAML, no Node builtins — the entire dependency footprint is {@link interpolate}
|
|
5
|
+
* and type-only imports. This is the determinism boundary: given the same book
|
|
6
|
+
* and context, the returned `text` is byte-for-byte stable, and the module
|
|
7
|
+
* bundles to a self-contained artifact for edge runtimes (see `edge.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Conflict strategy: rules apply in declaration order, later wins (cascade).
|
|
10
|
+
* `forbid` is the one exception — it is applied as a final filter and always
|
|
11
|
+
* wins, so a forbidden id never reaches the output even if added earlier.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveBook(book: PromptBook, prompt: string, context: Context): ResolveResult;
|
|
14
|
+
export declare function valuesEqual(a: ContextValue, b: ContextValue): boolean;
|
|
15
|
+
//# sourceMappingURL=resolve-book.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-book.d.ts","sourceRoot":"","sources":["../src/resolve-book.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,OAAO,EACP,YAAY,EAEZ,UAAU,EAEV,aAAa,EAKd,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CA8G7F;AAoBD,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CAErE"}
|