@funkai/prompts 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/.turbo/turbo-build.log +18 -0
- package/.turbo/turbo-test$colon$coverage.log +26 -0
- package/.turbo/turbo-test.log +26 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/banner.svg +100 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/clean.ts.html +160 -0
- package/coverage/lcov-report/engine.ts.html +196 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +161 -0
- package/coverage/lcov-report/partials-dir.ts.html +100 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/registry.ts.html +280 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +75 -0
- package/dist/lib/index.d.mts +99 -0
- package/dist/lib/index.d.mts.map +1 -0
- package/dist/lib/index.mjs +117 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/prompts/constraints.prompt +20 -0
- package/dist/prompts/identity.prompt +6 -0
- package/dist/prompts/prompts/constraints.prompt +20 -0
- package/dist/prompts/prompts/identity.prompt +6 -0
- package/dist/prompts/prompts/tools.prompt +14 -0
- package/dist/prompts/tools.prompt +14 -0
- package/docs/cli/commands.md +73 -0
- package/docs/cli/overview.md +73 -0
- package/docs/codegen/overview.md +83 -0
- package/docs/file-format/frontmatter.md +55 -0
- package/docs/file-format/overview.md +67 -0
- package/docs/file-format/partials.md +87 -0
- package/docs/guides/add-partial.md +75 -0
- package/docs/guides/author-prompt.md +70 -0
- package/docs/guides/setup-project.md +75 -0
- package/docs/library/overview.md +64 -0
- package/docs/overview.md +102 -0
- package/docs/troubleshooting.md +37 -0
- package/logo.svg +20 -0
- package/package.json +53 -0
- package/src/clean.test.ts +44 -0
- package/src/clean.ts +25 -0
- package/src/engine.test.ts +44 -0
- package/src/engine.ts +37 -0
- package/src/index.ts +11 -0
- package/src/partials-dir.test.ts +15 -0
- package/src/partials-dir.ts +5 -0
- package/src/prompts/constraints.prompt +20 -0
- package/src/prompts/identity.prompt +6 -0
- package/src/prompts/tools.prompt +14 -0
- package/src/registry.test.ts +69 -0
- package/src/registry.ts +65 -0
- package/src/types.ts +62 -0
- package/tsconfig.json +25 -0
- package/tsdown.config.ts +12 -0
- package/vitest.config.ts +21 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Liquid, Liquid as Liquid$1, LiquidOptions } from "liquidjs";
|
|
2
|
+
import { ZodType } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for creating a custom LiquidJS engine.
|
|
7
|
+
*/
|
|
8
|
+
type CreateEngineOptions = Pick<LiquidOptions, "root" | "partials" | "extname" | "cache" | "strictFilters" | "strictVariables" | "ownPropertyOnly">;
|
|
9
|
+
/**
|
|
10
|
+
* A single prompt module produced by codegen.
|
|
11
|
+
*
|
|
12
|
+
* Each `.prompt` file generates a default export conforming to this shape.
|
|
13
|
+
*/
|
|
14
|
+
interface PromptModule<T = unknown> {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly group: string | undefined;
|
|
17
|
+
readonly schema: ZodType<T>;
|
|
18
|
+
render(variables: T): string;
|
|
19
|
+
validate(variables: unknown): T;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A nested namespace node in the prompt tree.
|
|
23
|
+
* Values are either PromptModule leaves or further nested namespaces.
|
|
24
|
+
*/
|
|
25
|
+
type PromptNamespace = {
|
|
26
|
+
readonly [key: string]: PromptModule | PromptNamespace;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Deep-readonly version of a prompt tree.
|
|
30
|
+
* Prevents reassignment at any nesting level.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* type MyRegistry = PromptRegistry<{
|
|
35
|
+
* agents: { coverageAssessor: PromptModule }
|
|
36
|
+
* greeting: PromptModule
|
|
37
|
+
* }>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
type PromptRegistry<T extends PromptNamespace> = { readonly [K in keyof T]: T[K] extends PromptModule ? T[K] : T[K] extends PromptNamespace ? PromptRegistry<T[K]> : T[K] };
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/engine.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* Create a LiquidJS engine with custom options.
|
|
45
|
+
*
|
|
46
|
+
* The `partialsDir` is used as the root for `{% render %}` resolution.
|
|
47
|
+
* The `.prompt` extension is appended automatically.
|
|
48
|
+
*
|
|
49
|
+
* @param partialsDir - Root directory for `{% render %}` partial resolution.
|
|
50
|
+
* @param options - Optional overrides for the LiquidJS engine configuration.
|
|
51
|
+
* @returns A configured {@link Liquid} engine instance.
|
|
52
|
+
*/
|
|
53
|
+
declare function createEngine(partialsDir: string, options?: Partial<CreateEngineOptions>): Liquid$1;
|
|
54
|
+
/**
|
|
55
|
+
* Shared LiquidJS engine for rendering prompt templates at runtime.
|
|
56
|
+
*
|
|
57
|
+
* Partials are flattened at codegen time by the CLI, so this engine
|
|
58
|
+
* only needs to handle `{{ var }}` expressions and basic Liquid
|
|
59
|
+
* control flow (`{% if %}`, `{% for %}`). No filesystem access required.
|
|
60
|
+
*/
|
|
61
|
+
declare const engine: Liquid$1;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/clean.d.ts
|
|
64
|
+
/**
|
|
65
|
+
* Clean a raw `.prompt` file into a render-ready template.
|
|
66
|
+
*
|
|
67
|
+
* Runs the source through a pipeline of transforms — currently
|
|
68
|
+
* strips frontmatter, with more steps added over time.
|
|
69
|
+
*/
|
|
70
|
+
declare function clean(text: string): string;
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/partials-dir.d.ts
|
|
73
|
+
/** Absolute path to the SDK's built-in partials directory. */
|
|
74
|
+
declare const PARTIALS_DIR: string;
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/registry.d.ts
|
|
77
|
+
/**
|
|
78
|
+
* Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.
|
|
79
|
+
*
|
|
80
|
+
* The registry is typically created by generated code — the CLI produces
|
|
81
|
+
* an `index.ts` that calls `createPromptRegistry()` with all discovered
|
|
82
|
+
* prompt modules keyed by camelCase name, nested by group.
|
|
83
|
+
*
|
|
84
|
+
* @param modules - Record mapping camelCase prompt names (or group namespaces) to their modules.
|
|
85
|
+
* @returns A deep-frozen, typed record with direct property access.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const prompts = createPromptRegistry({
|
|
90
|
+
* agents: { coverageAssessor },
|
|
91
|
+
* greeting,
|
|
92
|
+
* })
|
|
93
|
+
* prompts.agents.coverageAssessor.render({ scope: 'full' })
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
declare function createPromptRegistry<T extends PromptNamespace>(modules: T): PromptRegistry<T>;
|
|
97
|
+
//#endregion
|
|
98
|
+
export { type CreateEngineOptions, type Liquid, PARTIALS_DIR, type PromptModule, type PromptNamespace, type PromptRegistry, clean, createEngine, createPromptRegistry, engine };
|
|
99
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/engine.ts","../../src/clean.ts","../../src/partials-dir.ts","../../src/registry.ts"],"mappings":";;;;;;AAMA;KAAY,mBAAA,GAAsB,IAAA,CAChC,aAAA;;;;AAeF;;UAAiB,YAAA;EAAA,SACN,IAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA,EAAQ,OAAA,CAAQ,CAAA;EACzB,MAAA,CAAO,SAAA,EAAW,CAAA;EAClB,QAAA,CAAS,SAAA,YAAqB,CAAA;AAAA;;;;;KAOpB,eAAA;EAAA,UACA,GAAA,WAAc,YAAA,GAAe,eAAA;AAAA;;;;;;;;AADzC;;;;;KAgBY,cAAA,WAAyB,eAAA,2BACd,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,YAAA,GAClC,CAAA,CAAE,CAAA,IACF,CAAA,CAAE,CAAA,UAAW,eAAA,GACX,cAAA,CAAe,CAAA,CAAE,CAAA,KACjB,CAAA,CAAE,CAAA;;;;;AAjDV;;;;;AAgBA;;;iBCRgB,YAAA,CAAa,WAAA,UAAqB,OAAA,GAAU,OAAA,CAAQ,mBAAA,IAAuB,QAAA;;;;;;;;cAmB9E,MAAA,EAAM,QAAA;;;;;;;AD3BnB;;iBEgBgB,KAAA,CAAM,IAAA;;;;cClBT,YAAA;;;;;;AHEb;;;;;AAgBA;;;;;;;;;;;iBIwCgB,oBAAA,WAA+B,eAAA,CAAA,CAAiB,OAAA,EAAS,CAAA,GAAI,cAAA,CAAe,CAAA"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Liquid } from "liquidjs";
|
|
2
|
+
import { flow } from "es-toolkit";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
//#region src/engine.ts
|
|
6
|
+
/**
|
|
7
|
+
* Create a LiquidJS engine with custom options.
|
|
8
|
+
*
|
|
9
|
+
* The `partialsDir` is used as the root for `{% render %}` resolution.
|
|
10
|
+
* The `.prompt` extension is appended automatically.
|
|
11
|
+
*
|
|
12
|
+
* @param partialsDir - Root directory for `{% render %}` partial resolution.
|
|
13
|
+
* @param options - Optional overrides for the LiquidJS engine configuration.
|
|
14
|
+
* @returns A configured {@link Liquid} engine instance.
|
|
15
|
+
*/
|
|
16
|
+
function createEngine(partialsDir, options) {
|
|
17
|
+
return new Liquid({
|
|
18
|
+
root: [partialsDir],
|
|
19
|
+
partials: [partialsDir],
|
|
20
|
+
extname: ".prompt",
|
|
21
|
+
cache: true,
|
|
22
|
+
strictFilters: true,
|
|
23
|
+
ownPropertyOnly: true,
|
|
24
|
+
...options
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Shared LiquidJS engine for rendering prompt templates at runtime.
|
|
29
|
+
*
|
|
30
|
+
* Partials are flattened at codegen time by the CLI, so this engine
|
|
31
|
+
* only needs to handle `{{ var }}` expressions and basic Liquid
|
|
32
|
+
* control flow (`{% if %}`, `{% for %}`). No filesystem access required.
|
|
33
|
+
*/
|
|
34
|
+
const engine = new Liquid({
|
|
35
|
+
strictFilters: true,
|
|
36
|
+
ownPropertyOnly: true
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/clean.ts
|
|
40
|
+
const FRONTMATTER_RE = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/;
|
|
41
|
+
/**
|
|
42
|
+
* Remove YAML frontmatter from the beginning of a string.
|
|
43
|
+
*
|
|
44
|
+
* Frontmatter is a block delimited by `---` at the start of the file.
|
|
45
|
+
* If no frontmatter is present, the string is returned unchanged.
|
|
46
|
+
*/
|
|
47
|
+
function stripFrontmatter(text) {
|
|
48
|
+
return text.replace(FRONTMATTER_RE, "");
|
|
49
|
+
}
|
|
50
|
+
const pipeline = flow(stripFrontmatter);
|
|
51
|
+
/**
|
|
52
|
+
* Clean a raw `.prompt` file into a render-ready template.
|
|
53
|
+
*
|
|
54
|
+
* Runs the source through a pipeline of transforms — currently
|
|
55
|
+
* strips frontmatter, with more steps added over time.
|
|
56
|
+
*/
|
|
57
|
+
function clean(text) {
|
|
58
|
+
return pipeline(text);
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/partials-dir.ts
|
|
62
|
+
/** Absolute path to the SDK's built-in partials directory. */
|
|
63
|
+
const PARTIALS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../prompts");
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/registry.ts
|
|
66
|
+
/**
|
|
67
|
+
* Check whether a value looks like a PromptModule leaf.
|
|
68
|
+
* Leaves have `name`, `schema`, and `render` — namespaces do not.
|
|
69
|
+
*
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
function isPromptModule(value) {
|
|
73
|
+
return typeof value === "object" && value !== null && "render" in value && "schema" in value && "name" in value;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Recursively freeze a prompt namespace tree.
|
|
77
|
+
* Only recurses into plain namespace nodes — PromptModule leaves
|
|
78
|
+
* (which contain Zod schemas) are frozen shallowly.
|
|
79
|
+
*
|
|
80
|
+
* @param obj - The namespace object to freeze.
|
|
81
|
+
* @returns The frozen object cast to its deep-readonly type.
|
|
82
|
+
*
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
function deepFreeze(obj) {
|
|
86
|
+
Object.freeze(obj);
|
|
87
|
+
Object.values(obj).forEach((value) => {
|
|
88
|
+
if (typeof value === "object" && value !== null && !Object.isFrozen(value) && !isPromptModule(value)) deepFreeze(value);
|
|
89
|
+
});
|
|
90
|
+
return obj;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.
|
|
94
|
+
*
|
|
95
|
+
* The registry is typically created by generated code — the CLI produces
|
|
96
|
+
* an `index.ts` that calls `createPromptRegistry()` with all discovered
|
|
97
|
+
* prompt modules keyed by camelCase name, nested by group.
|
|
98
|
+
*
|
|
99
|
+
* @param modules - Record mapping camelCase prompt names (or group namespaces) to their modules.
|
|
100
|
+
* @returns A deep-frozen, typed record with direct property access.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const prompts = createPromptRegistry({
|
|
105
|
+
* agents: { coverageAssessor },
|
|
106
|
+
* greeting,
|
|
107
|
+
* })
|
|
108
|
+
* prompts.agents.coverageAssessor.render({ scope: 'full' })
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
function createPromptRegistry(modules) {
|
|
112
|
+
return deepFreeze({ ...modules });
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { PARTIALS_DIR, clean, createEngine, createPromptRegistry, engine };
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/engine.ts","../../src/clean.ts","../../src/partials-dir.ts","../../src/registry.ts"],"sourcesContent":["import { Liquid } from \"liquidjs\";\n\nimport type { CreateEngineOptions } from \"./types.js\";\n\n/**\n * Create a LiquidJS engine with custom options.\n *\n * The `partialsDir` is used as the root for `{% render %}` resolution.\n * The `.prompt` extension is appended automatically.\n *\n * @param partialsDir - Root directory for `{% render %}` partial resolution.\n * @param options - Optional overrides for the LiquidJS engine configuration.\n * @returns A configured {@link Liquid} engine instance.\n */\nexport function createEngine(partialsDir: string, options?: Partial<CreateEngineOptions>): Liquid {\n return new Liquid({\n root: [partialsDir],\n partials: [partialsDir],\n extname: \".prompt\",\n cache: true,\n strictFilters: true,\n ownPropertyOnly: true,\n ...options,\n });\n}\n\n/**\n * Shared LiquidJS engine for rendering prompt templates at runtime.\n *\n * Partials are flattened at codegen time by the CLI, so this engine\n * only needs to handle `{{ var }}` expressions and basic Liquid\n * control flow (`{% if %}`, `{% for %}`). No filesystem access required.\n */\nexport const engine = new Liquid({\n strictFilters: true,\n ownPropertyOnly: true,\n});\n","import { flow } from \"es-toolkit\";\n\nconst FRONTMATTER_RE = /^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n?/;\n\n/**\n * Remove YAML frontmatter from the beginning of a string.\n *\n * Frontmatter is a block delimited by `---` at the start of the file.\n * If no frontmatter is present, the string is returned unchanged.\n */\nfunction stripFrontmatter(text: string): string {\n return text.replace(FRONTMATTER_RE, \"\");\n}\n\nconst pipeline = flow(stripFrontmatter);\n\n/**\n * Clean a raw `.prompt` file into a render-ready template.\n *\n * Runs the source through a pipeline of transforms — currently\n * strips frontmatter, with more steps added over time.\n */\nexport function clean(text: string): string {\n return pipeline(text);\n}\n","import { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/** Absolute path to the SDK's built-in partials directory. */\nexport const PARTIALS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), \"../prompts\");\n","import type { PromptModule, PromptNamespace, PromptRegistry } from \"./types.js\";\n\n/**\n * Check whether a value looks like a PromptModule leaf.\n * Leaves have `name`, `schema`, and `render` — namespaces do not.\n *\n * @private\n */\nfunction isPromptModule(value: unknown): value is PromptModule {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"render\" in value &&\n \"schema\" in value &&\n \"name\" in value\n );\n}\n\n/**\n * Recursively freeze a prompt namespace tree.\n * Only recurses into plain namespace nodes — PromptModule leaves\n * (which contain Zod schemas) are frozen shallowly.\n *\n * @param obj - The namespace object to freeze.\n * @returns The frozen object cast to its deep-readonly type.\n *\n * @private\n */\nfunction deepFreeze<T extends PromptNamespace>(obj: T): PromptRegistry<T> {\n Object.freeze(obj);\n Object.values(obj).forEach((value) => {\n if (\n typeof value === \"object\" &&\n value !== null &&\n !Object.isFrozen(value) &&\n !isPromptModule(value)\n ) {\n deepFreeze(value as PromptNamespace);\n }\n });\n return obj as PromptRegistry<T>;\n}\n\n/**\n * Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.\n *\n * The registry is typically created by generated code — the CLI produces\n * an `index.ts` that calls `createPromptRegistry()` with all discovered\n * prompt modules keyed by camelCase name, nested by group.\n *\n * @param modules - Record mapping camelCase prompt names (or group namespaces) to their modules.\n * @returns A deep-frozen, typed record with direct property access.\n *\n * @example\n * ```ts\n * const prompts = createPromptRegistry({\n * agents: { coverageAssessor },\n * greeting,\n * })\n * prompts.agents.coverageAssessor.render({ scope: 'full' })\n * ```\n */\nexport function createPromptRegistry<T extends PromptNamespace>(modules: T): PromptRegistry<T> {\n return deepFreeze({ ...modules });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,SAAgB,aAAa,aAAqB,SAAgD;AAChG,QAAO,IAAI,OAAO;EAChB,MAAM,CAAC,YAAY;EACnB,UAAU,CAAC,YAAY;EACvB,SAAS;EACT,OAAO;EACP,eAAe;EACf,iBAAiB;EACjB,GAAG;EACJ,CAAC;;;;;;;;;AAUJ,MAAa,SAAS,IAAI,OAAO;CAC/B,eAAe;CACf,iBAAiB;CAClB,CAAC;;;AClCF,MAAM,iBAAiB;;;;;;;AAQvB,SAAS,iBAAiB,MAAsB;AAC9C,QAAO,KAAK,QAAQ,gBAAgB,GAAG;;AAGzC,MAAM,WAAW,KAAK,iBAAiB;;;;;;;AAQvC,SAAgB,MAAM,MAAsB;AAC1C,QAAO,SAAS,KAAK;;;;;ACnBvB,MAAa,eAAe,QAAQ,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EAAE,aAAa;;;;;;;;;ACI1F,SAAS,eAAe,OAAuC;AAC7D,QACE,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,YAAY,SACZ,UAAU;;;;;;;;;;;;AAcd,SAAS,WAAsC,KAA2B;AACxE,QAAO,OAAO,IAAI;AAClB,QAAO,OAAO,IAAI,CAAC,SAAS,UAAU;AACpC,MACE,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,OAAO,SAAS,MAAM,IACvB,CAAC,eAAe,MAAM,CAEtB,YAAW,MAAyB;GAEtC;AACF,QAAO;;;;;;;;;;;;;;;;;;;;;AAsBT,SAAgB,qBAAgD,SAA+B;AAC7F,QAAO,WAAW,EAAE,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<constraints>
|
|
2
|
+
{% if in_scope %}
|
|
3
|
+
## In Scope
|
|
4
|
+
{% for item in in_scope %}
|
|
5
|
+
- {{ item }}
|
|
6
|
+
{% endfor %}
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if out_of_scope %}
|
|
9
|
+
## Out of Scope
|
|
10
|
+
{% for item in out_of_scope %}
|
|
11
|
+
- {{ item }}
|
|
12
|
+
{% endfor %}
|
|
13
|
+
{% endif %}
|
|
14
|
+
{% if rules %}
|
|
15
|
+
## Rules
|
|
16
|
+
{% for rule in rules %}
|
|
17
|
+
- {{ rule }}
|
|
18
|
+
{% endfor %}
|
|
19
|
+
{% endif %}
|
|
20
|
+
</constraints>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<constraints>
|
|
2
|
+
{% if in_scope %}
|
|
3
|
+
## In Scope
|
|
4
|
+
{% for item in in_scope %}
|
|
5
|
+
- {{ item }}
|
|
6
|
+
{% endfor %}
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if out_of_scope %}
|
|
9
|
+
## Out of Scope
|
|
10
|
+
{% for item in out_of_scope %}
|
|
11
|
+
- {{ item }}
|
|
12
|
+
{% endfor %}
|
|
13
|
+
{% endif %}
|
|
14
|
+
{% if rules %}
|
|
15
|
+
## Rules
|
|
16
|
+
{% for rule in rules %}
|
|
17
|
+
- {{ rule }}
|
|
18
|
+
{% endfor %}
|
|
19
|
+
{% endif %}
|
|
20
|
+
</constraints>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<tools>
|
|
2
|
+
You have access to the following tools:
|
|
3
|
+
{% if tools %}
|
|
4
|
+
{% for tool in tools %}
|
|
5
|
+
**{{ tool.name }}** -- {{ tool.description }}
|
|
6
|
+
{% for param in tool.params %}
|
|
7
|
+
- `{{ param.name }}` ({{ param.type }}{% if param.required %}, required{% endif %}) -- {{ param.description }}
|
|
8
|
+
{% endfor %}
|
|
9
|
+
|
|
10
|
+
{% endfor %}
|
|
11
|
+
{% else %}
|
|
12
|
+
No tools are configured for this agent.
|
|
13
|
+
{% endif %}
|
|
14
|
+
</tools>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<tools>
|
|
2
|
+
You have access to the following tools:
|
|
3
|
+
{% if tools %}
|
|
4
|
+
{% for tool in tools %}
|
|
5
|
+
**{{ tool.name }}** -- {{ tool.description }}
|
|
6
|
+
{% for param in tool.params %}
|
|
7
|
+
- `{{ param.name }}` ({{ param.type }}{% if param.required %}, required{% endif %}) -- {{ param.description }}
|
|
8
|
+
{% endfor %}
|
|
9
|
+
|
|
10
|
+
{% endfor %}
|
|
11
|
+
{% else %}
|
|
12
|
+
No tools are configured for this agent.
|
|
13
|
+
{% endif %}
|
|
14
|
+
</tools>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# CLI Commands Reference
|
|
2
|
+
|
|
3
|
+
## `prompts generate`
|
|
4
|
+
|
|
5
|
+
Generate typed TypeScript modules from `.prompt` files.
|
|
6
|
+
|
|
7
|
+
**Alias:** `gen`
|
|
8
|
+
|
|
9
|
+
| Flag | Alias | Required | Description |
|
|
10
|
+
| ---------- | ----- | -------- | ------------------------------------------------------- |
|
|
11
|
+
| `--out` | `-o` | Yes | Output directory for generated files |
|
|
12
|
+
| `--roots` | `-r` | Yes | Space-separated directories to scan for `.prompt` files |
|
|
13
|
+
| `--silent` | --- | No | Suppress output except errors |
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
prompts generate --out .prompts/client --roots prompts src/agents src/workflows
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Custom partials are auto-discovered from the sibling `partials/` directory (relative to `--out`).
|
|
20
|
+
|
|
21
|
+
Runs lint validation automatically before generating. Exits with code 1 on lint errors.
|
|
22
|
+
|
|
23
|
+
## `prompts lint`
|
|
24
|
+
|
|
25
|
+
Validate `.prompt` files without generating output.
|
|
26
|
+
|
|
27
|
+
| Flag | Alias | Required | Description |
|
|
28
|
+
| ------------ | ----- | -------- | -------------------------------------------------------- |
|
|
29
|
+
| `--roots` | `-r` | Yes | Directories to scan |
|
|
30
|
+
| `--partials` | `-p` | No | Custom partials directory (default: `.prompts/partials`) |
|
|
31
|
+
| `--silent` | --- | No | Suppress output except errors |
|
|
32
|
+
|
|
33
|
+
**Diagnostics:**
|
|
34
|
+
|
|
35
|
+
| Level | Meaning |
|
|
36
|
+
| ----- | ---------------------------------------- |
|
|
37
|
+
| Error | Template variable not declared in schema |
|
|
38
|
+
| Warn | Schema variable not used in template |
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
prompts lint --roots prompts src/agents
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## `prompts create`
|
|
45
|
+
|
|
46
|
+
Scaffold a new `.prompt` file.
|
|
47
|
+
|
|
48
|
+
| Arg/Flag | Required | Description |
|
|
49
|
+
| ----------- | -------- | ------------------------------------------------------------- |
|
|
50
|
+
| `<name>` | Yes | Prompt name (kebab-case) |
|
|
51
|
+
| `--out` | No | Output directory (defaults to cwd) |
|
|
52
|
+
| `--partial` | No | Create as a partial in `.prompts/partials/` (ignores `--out`) |
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
prompts create coverage-assessor --out src/agents/coverage-assessor
|
|
56
|
+
prompts create summary --partial
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## `prompts setup`
|
|
60
|
+
|
|
61
|
+
Interactive project configuration for `.prompt` development. No flags -- fully interactive.
|
|
62
|
+
|
|
63
|
+
Configures:
|
|
64
|
+
|
|
65
|
+
1. VSCode file association (`*.prompt` -> Markdown)
|
|
66
|
+
2. VSCode Liquid extension recommendation
|
|
67
|
+
3. `.gitignore` entry for generated `.prompts/client/` directory
|
|
68
|
+
4. `tsconfig.json` path alias (`~prompts` -> `./.prompts/client/index.ts`)
|
|
69
|
+
|
|
70
|
+
## References
|
|
71
|
+
|
|
72
|
+
- [CLI Overview](overview.md)
|
|
73
|
+
- [Troubleshooting](../troubleshooting.md)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# CLI Overview
|
|
2
|
+
|
|
3
|
+
The `prompts` CLI discovers, validates, and generates typed TypeScript from `.prompt` files.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Available as the `prompts` binary from `@funkai/cli`. Install it as a workspace dependency:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @funkai/cli --workspace
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
```mermaid
|
|
16
|
+
%%{init: {
|
|
17
|
+
'theme': 'base',
|
|
18
|
+
'themeVariables': {
|
|
19
|
+
'primaryColor': '#313244',
|
|
20
|
+
'primaryTextColor': '#cdd6f4',
|
|
21
|
+
'primaryBorderColor': '#6c7086',
|
|
22
|
+
'lineColor': '#89b4fa',
|
|
23
|
+
'secondaryColor': '#45475a',
|
|
24
|
+
'tertiaryColor': '#1e1e2e',
|
|
25
|
+
'actorBkg': '#313244',
|
|
26
|
+
'actorBorder': '#89b4fa',
|
|
27
|
+
'actorTextColor': '#cdd6f4',
|
|
28
|
+
'signalColor': '#cdd6f4',
|
|
29
|
+
'signalTextColor': '#cdd6f4'
|
|
30
|
+
}
|
|
31
|
+
}}%%
|
|
32
|
+
sequenceDiagram
|
|
33
|
+
participant Dev as Developer
|
|
34
|
+
participant CLI as prompts CLI
|
|
35
|
+
participant FS as File System
|
|
36
|
+
|
|
37
|
+
Dev->>CLI: prompts generate
|
|
38
|
+
CLI->>FS: Discover .prompt files from roots
|
|
39
|
+
CLI->>CLI: Parse frontmatter + extract variables
|
|
40
|
+
CLI->>CLI: Lint (schema vs template match)
|
|
41
|
+
CLI->>CLI: Flatten partials
|
|
42
|
+
CLI->>FS: Write generated .ts modules
|
|
43
|
+
FS-->>Dev: Import typed prompts from ~prompts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Commands
|
|
47
|
+
|
|
48
|
+
| Command | Alias | Description |
|
|
49
|
+
| ------------------ | ----- | ---------------------------------------------- |
|
|
50
|
+
| `prompts generate` | `gen` | Generate typed TS modules from `.prompt` files |
|
|
51
|
+
| `prompts lint` | --- | Validate `.prompt` files without generating |
|
|
52
|
+
| `prompts create` | --- | Scaffold a new `.prompt` file |
|
|
53
|
+
| `prompts setup` | --- | Interactive project configuration |
|
|
54
|
+
|
|
55
|
+
See the [Commands Reference](commands.md) for flags, examples, and diagnostics.
|
|
56
|
+
|
|
57
|
+
## Integration
|
|
58
|
+
|
|
59
|
+
Add a generate script to your `package.json`:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"scripts": {
|
|
64
|
+
"prompts:generate": "prompts generate --out .prompts/client --roots prompts src/agents"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## References
|
|
70
|
+
|
|
71
|
+
- [Commands Reference](commands.md)
|
|
72
|
+
- [Code Generation](../codegen/overview.md)
|
|
73
|
+
- [Setup Guide](../guides/setup-project.md)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Code Generation
|
|
2
|
+
|
|
3
|
+
The CLI transforms `.prompt` source files into typed TypeScript modules. This doc explains the pipeline stages and the shape of generated output.
|
|
4
|
+
|
|
5
|
+
## Pipeline
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
%%{init: {
|
|
9
|
+
'theme': 'base',
|
|
10
|
+
'themeVariables': {
|
|
11
|
+
'primaryColor': '#313244',
|
|
12
|
+
'primaryTextColor': '#cdd6f4',
|
|
13
|
+
'primaryBorderColor': '#6c7086',
|
|
14
|
+
'lineColor': '#89b4fa',
|
|
15
|
+
'secondaryColor': '#45475a',
|
|
16
|
+
'tertiaryColor': '#1e1e2e',
|
|
17
|
+
'background': '#1e1e2e',
|
|
18
|
+
'mainBkg': '#313244',
|
|
19
|
+
'clusterBkg': '#1e1e2e',
|
|
20
|
+
'clusterBorder': '#45475a'
|
|
21
|
+
},
|
|
22
|
+
'flowchart': { 'curve': 'basis', 'padding': 15 }
|
|
23
|
+
}}%%
|
|
24
|
+
flowchart TD
|
|
25
|
+
classDef core fill:#313244,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
|
|
26
|
+
classDef agent fill:#313244,stroke:#a6e3a1,stroke-width:2px,color:#cdd6f4
|
|
27
|
+
|
|
28
|
+
subgraph Per Prompt
|
|
29
|
+
A[discoverPrompts]:::core --> B[parseFrontmatter]:::core
|
|
30
|
+
B --> C[clean]:::core
|
|
31
|
+
C --> D[flattenPartials]:::core
|
|
32
|
+
D --> E[extractVariables]:::core
|
|
33
|
+
E --> F[lintPrompt]:::core
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
subgraph Output
|
|
37
|
+
F --> G[generatePromptModule]:::agent
|
|
38
|
+
F --> H[generateRegistry]:::agent
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Pipeline Stages
|
|
43
|
+
|
|
44
|
+
| Stage | Input | Output | Description |
|
|
45
|
+
| ----------------- | ---------------------------- | ---------------------------------- | ------------------------------------------------------- |
|
|
46
|
+
| Discover | Root directories | `DiscoveredPrompt[]` | Scans for `.prompt` files (max depth 5) |
|
|
47
|
+
| Parse Frontmatter | Raw file content | `{ name, group, version, schema }` | Extracts and validates YAML metadata |
|
|
48
|
+
| Clean | Raw content | Template string | Strips frontmatter delimiters |
|
|
49
|
+
| Flatten Partials | Template with `{% render %}` | Resolved template | Inlines partial content with bound params |
|
|
50
|
+
| Extract Variables | Template string | `string[]` | Finds `{{ var }}`, `{% if var %}`, `{% for x in var %}` |
|
|
51
|
+
| Lint | Schema + variables | Diagnostics | Checks schema/template variable alignment |
|
|
52
|
+
|
|
53
|
+
## Generated Output
|
|
54
|
+
|
|
55
|
+
### Per-Prompt Module (`<name>.ts`)
|
|
56
|
+
|
|
57
|
+
Each module exports a default object conforming to `PromptModule`:
|
|
58
|
+
|
|
59
|
+
| Member | Type | Description |
|
|
60
|
+
| --------------------- | ------------------------ | ------------------------------------------------ |
|
|
61
|
+
| `name` | `string` (const) | Prompt name from frontmatter |
|
|
62
|
+
| `group` | `string \| undefined` | Optional grouping key |
|
|
63
|
+
| `schema` | `ZodObject` | Zod schema built from frontmatter `schema` block |
|
|
64
|
+
| `render(variables)` | `(Variables) => string` | Validates input then renders via LiquidJS |
|
|
65
|
+
| `validate(variables)` | `(unknown) => Variables` | Zod parse only |
|
|
66
|
+
|
|
67
|
+
### Registry (`index.ts`)
|
|
68
|
+
|
|
69
|
+
Aggregates all per-prompt modules into a single entry point:
|
|
70
|
+
|
|
71
|
+
| Export | Type | Description |
|
|
72
|
+
| --------- | --------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
73
|
+
| `prompts` | `PromptRegistry<...>` | Deep-frozen const object with dot-access, nested by group. Use `typeof prompts` for type-level access. |
|
|
74
|
+
|
|
75
|
+
## Output Directory
|
|
76
|
+
|
|
77
|
+
Generated files go to the `--out` directory (conventionally `.prompts/client/`). This subdirectory should be gitignored. The parent `.prompts/` directory also holds `partials/` for custom partials (committed to git). Import generated code via the `~prompts` tsconfig alias.
|
|
78
|
+
|
|
79
|
+
## References
|
|
80
|
+
|
|
81
|
+
- [File Format](../file-format/overview.md)
|
|
82
|
+
- [Library API](../library/overview.md)
|
|
83
|
+
- [CLI Commands](../cli/commands.md)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Frontmatter Reference
|
|
2
|
+
|
|
3
|
+
The YAML frontmatter block defines metadata and the variable schema for a `.prompt` file. It is delimited by `---` fences at the top of the file.
|
|
4
|
+
|
|
5
|
+
## Fields
|
|
6
|
+
|
|
7
|
+
| Field | Required | Type | Description |
|
|
8
|
+
| --------- | -------- | -------- | ------------------------------------------------ |
|
|
9
|
+
| `name` | Yes | `string` | Unique kebab-case identifier (`^[a-z0-9-]+$`) |
|
|
10
|
+
| `group` | No | `string` | Namespace path (e.g. `agents/coverage-assessor`) |
|
|
11
|
+
| `version` | No | `string` | Version identifier |
|
|
12
|
+
| `schema` | No | `object` | Variable declarations map |
|
|
13
|
+
|
|
14
|
+
## Schema Variables
|
|
15
|
+
|
|
16
|
+
Each key under `schema` declares a template variable. Two syntaxes are supported.
|
|
17
|
+
|
|
18
|
+
**Shorthand** -- type string only, defaults to required:
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
schema:
|
|
22
|
+
scope: string
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Full object** -- explicit control over all fields:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
schema:
|
|
29
|
+
scope:
|
|
30
|
+
type: string
|
|
31
|
+
required: true
|
|
32
|
+
description: Assessment scope
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Variable Fields
|
|
36
|
+
|
|
37
|
+
| Field | Default | Description |
|
|
38
|
+
| ------------- | -------- | ---------------------------------------------------- |
|
|
39
|
+
| `type` | `string` | Variable type (only `string` supported) |
|
|
40
|
+
| `required` | `true` | Whether the variable must be provided at render time |
|
|
41
|
+
| `description` | -- | Human-readable description (used in generated JSDoc) |
|
|
42
|
+
|
|
43
|
+
## Validation Rules
|
|
44
|
+
|
|
45
|
+
- `name` is required and must match `^[a-z0-9-]+$`
|
|
46
|
+
- Frontmatter must be valid YAML between `---` delimiters
|
|
47
|
+
- `schema` must be an object (not an array)
|
|
48
|
+
- Shorthand `scope: string` expands to `{ type: 'string', required: true }`
|
|
49
|
+
- Missing or empty `name` throws a parse error with the file path
|
|
50
|
+
- Non-object frontmatter (e.g. a bare string) is rejected
|
|
51
|
+
|
|
52
|
+
## References
|
|
53
|
+
|
|
54
|
+
- [File Format Overview](overview.md)
|
|
55
|
+
- [Code Generation](../codegen/overview.md)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# .prompt File Format
|
|
2
|
+
|
|
3
|
+
A `.prompt` file is a LiquidJS template with YAML frontmatter. It is a declarative prompt authoring format compiled to typed TypeScript at build time.
|
|
4
|
+
|
|
5
|
+
## Anatomy
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
---
|
|
9
|
+
name: coverage-assessor
|
|
10
|
+
group: agents/coverage-assessor
|
|
11
|
+
schema:
|
|
12
|
+
scope:
|
|
13
|
+
type: string
|
|
14
|
+
description: Assessment scope
|
|
15
|
+
target:
|
|
16
|
+
type: string
|
|
17
|
+
required: false
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
You are a coverage assessor for {{ scope }}.
|
|
21
|
+
{% if target %}Targeting {{ target }} docs.{% endif %}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Section | Description |
|
|
25
|
+
| ------------------- | ------------------------------------------------------------- |
|
|
26
|
+
| Frontmatter (`---`) | YAML metadata block defining name, group, and variable schema |
|
|
27
|
+
| Body | LiquidJS template rendered at runtime with typed variables |
|
|
28
|
+
|
|
29
|
+
## Template Language
|
|
30
|
+
|
|
31
|
+
| Syntax | Purpose |
|
|
32
|
+
| --------------------------------------- | ----------------------------------- |
|
|
33
|
+
| `{{ var }}` | Variable output |
|
|
34
|
+
| `{{ var \| filter }}` | Filtered output |
|
|
35
|
+
| `{% if var %}...{% endif %}` | Conditional |
|
|
36
|
+
| `{% for item in list %}...{% endfor %}` | Iteration |
|
|
37
|
+
| `{% render 'name', key: 'value' %}` | Partial inclusion (build-time only) |
|
|
38
|
+
|
|
39
|
+
Strict filters are enabled -- unknown filters throw an error. Variable access is restricted to own properties only.
|
|
40
|
+
|
|
41
|
+
## Naming Convention
|
|
42
|
+
|
|
43
|
+
Names must match `^[a-z0-9-]+$` (lowercase, digits, hyphens). The `name` field in frontmatter is required and takes precedence. A file named `prompt.prompt` derives its name from the parent directory (e.g. `agents/gap-detector/prompt.prompt` becomes `gap-detector`).
|
|
44
|
+
|
|
45
|
+
## Discovery
|
|
46
|
+
|
|
47
|
+
The CLI scans `--roots` directories recursively (max depth 5). Files must have the `.prompt` extension. Symbolic links are skipped. Duplicate names across roots cause an error with paths listed.
|
|
48
|
+
|
|
49
|
+
Results are sorted alphabetically by name.
|
|
50
|
+
|
|
51
|
+
## File Structure
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
📁 src/
|
|
55
|
+
├── 📁 agents/
|
|
56
|
+
│ └── 📁 coverage-assessor/
|
|
57
|
+
│ └── 📄 prompt.prompt
|
|
58
|
+
├── 📁 prompts/
|
|
59
|
+
│ ├── 📄 identity.prompt
|
|
60
|
+
│ └── 📄 constraints.prompt
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## References
|
|
64
|
+
|
|
65
|
+
- [Frontmatter Reference](frontmatter.md)
|
|
66
|
+
- [Partials](partials.md)
|
|
67
|
+
- [Author a Prompt](../guides/author-prompt.md)
|