@funkai/prompts 0.1.1 → 0.2.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.
@@ -1,16 +1,28 @@
1
1
 
2
- > @funkai/prompts@0.1.1 build /home/runner/work/funkai/funkai/packages/prompts
2
+ > @funkai/prompts@0.2.0 build /home/runner/work/funkai/funkai/packages/prompts
3
3
  > tsdown && cp -r src/prompts dist/prompts
4
4
 
5
- ℹ tsdown v0.21.2 powered by rolldown v1.0.0-rc.9
5
+ ℹ tsdown v0.21.3 powered by rolldown v1.0.0-rc.9
6
6
  ℹ config file: /home/runner/work/funkai/funkai/packages/prompts/tsdown.config.ts
7
- ℹ entry: src/index.ts
7
+ ℹ entry: src/index.ts, src/runtime.ts, src/cli.ts
8
8
  ℹ target: node22
9
9
  ℹ tsconfig: tsconfig.json
10
10
  ℹ Build start
11
- ℹ dist/lib/index.mjs 3.71 kB │ gzip: 1.65 kB
12
- ℹ dist/lib/index.mjs.map 5.24 kB │ gzip: 2.18 kB
13
- ℹ dist/lib/index.d.mts.map 0.89 kB │ gzip: 0.42 kB
14
- ℹ dist/lib/index.d.mts 3.62 kB │ gzip: 1.49 kB
15
- ℹ 4 files, total: 13.46 kB
16
- ✔ Build complete in 1855ms
11
+ ℹ dist/lib/index.mjs 1.66 kB │ gzip: 0.80 kB
12
+ ℹ dist/lib/cli.mjs 1.10 kB │ gzip: 0.63 kB
13
+ ℹ dist/lib/runtime.mjs 0.08 kB │ gzip: 0.08 kB
14
+ ℹ dist/lib/index.mjs.map 2.48 kB │ gzip: 1.12 kB
15
+ ℹ dist/lib/engine-B53whAlC.mjs.map 1.57 kB │ gzip: 0.79 kB
16
+ ℹ dist/lib/cli.mjs.map 1.37 kB │ gzip: 0.75 kB
17
+ ℹ dist/lib/engine-B53whAlC.mjs 1.15 kB │ gzip: 0.61 kB
18
+ ℹ dist/lib/types-CiSdNM0W.d.mts.map 0.53 kB │ gzip: 0.29 kB
19
+ ℹ dist/lib/engine-B6JHetwb.d.mts.map 0.22 kB │ gzip: 0.18 kB
20
+ ℹ dist/lib/index.d.mts.map 0.19 kB │ gzip: 0.16 kB
21
+ ℹ dist/lib/cli.d.mts.map 0.17 kB │ gzip: 0.15 kB
22
+ ℹ dist/lib/index.d.mts 1.04 kB │ gzip: 0.54 kB
23
+ ℹ dist/lib/cli.d.mts 0.68 kB │ gzip: 0.41 kB
24
+ ℹ dist/lib/runtime.d.mts 0.08 kB │ gzip: 0.08 kB
25
+ ℹ dist/lib/types-CiSdNM0W.d.mts 1.47 kB │ gzip: 0.71 kB
26
+ ℹ dist/lib/engine-B6JHetwb.d.mts 1.06 kB │ gzip: 0.57 kB
27
+ ℹ 16 files, total: 14.86 kB
28
+ ✔ Build complete in 1822ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @funkai/prompts
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8b89d9c: Simplify API surface across all packages: replace OpenRouter-specific provider layer with generic registry pattern, streamline agent internals, and restructure prompt entry points.
8
+
9
+ Migration notes:
10
+
11
+ - `@funkai/agents`: `AgentConfig.resolver` is replaced by `AgentConfig.registry`.
12
+ - `@funkai/models`: OpenRouter-specific provider exports (`openrouter.ts`, `resolver.ts`) were removed in favor of `createProviderRegistry` and `ProviderRegistry`.
13
+ - `@funkai/prompts`: Runtime helpers moved to `@funkai/prompts/runtime`, CLI helpers moved to `@funkai/prompts/cli`.
14
+
15
+ ## 0.1.2
16
+
17
+ ### Patch Changes
18
+
19
+ - 153c393: refactor: deep review cleanup across all packages
20
+
21
+ - **@funkai/agents**: Remove dead code (`resolve.ts`, `attempt.ts`), fix stale "Workflow" JSDoc references, deduplicate `buildOnFinishHandler`, complete `writeLog` JSDoc, remove orphaned `ResolveParam` export
22
+ - **@funkai/models**: Export missing `ProviderFactory` and `ProviderMap` types, convert per-provider `*Model()` lookup from O(n) `.find()` to O(1) Map, fix floating-point precision artifacts in generated pricing data
23
+ - **@funkai/prompts**: Rename generic `engine` export to `liquidEngine` for clarity
24
+
3
25
  ## 0.1.1
4
26
 
5
27
  ### Patch Changes
@@ -0,0 +1,18 @@
1
+ import { n as Liquid, t as CreateEngineOptions } from "./types-CiSdNM0W.mjs";
2
+ import { t as createEngine } from "./engine-B6JHetwb.mjs";
3
+
4
+ //#region src/clean.d.ts
5
+ /**
6
+ * Clean a raw `.prompt` file into a render-ready template.
7
+ *
8
+ * Runs the source through a pipeline of transforms — currently
9
+ * strips frontmatter, with more steps added over time.
10
+ */
11
+ declare function clean(text: string): string;
12
+ //#endregion
13
+ //#region src/partials-dir.d.ts
14
+ /** Absolute path to the SDK's built-in partials directory. */
15
+ declare const PARTIALS_DIR: string;
16
+ //#endregion
17
+ export { type CreateEngineOptions, type Liquid, PARTIALS_DIR, clean, createEngine };
18
+ //# sourceMappingURL=cli.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.mts","names":[],"sources":["../../src/clean.ts","../../src/partials-dir.ts"],"mappings":";;;;;;;;AAsBA;;iBAAgB,KAAA,CAAM,IAAA;;;;cClBT,YAAA"}
@@ -0,0 +1,33 @@
1
+ import { t as createEngine } from "./engine-B53whAlC.mjs";
2
+ import { flow } from "es-toolkit";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ //#region src/clean.ts
6
+ const FRONTMATTER_RE = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/;
7
+ /**
8
+ * Remove YAML frontmatter from the beginning of a string.
9
+ *
10
+ * Frontmatter is a block delimited by `---` at the start of the file.
11
+ * If no frontmatter is present, the string is returned unchanged.
12
+ */
13
+ function stripFrontmatter(text) {
14
+ return text.replace(FRONTMATTER_RE, "");
15
+ }
16
+ const pipeline = flow(stripFrontmatter);
17
+ /**
18
+ * Clean a raw `.prompt` file into a render-ready template.
19
+ *
20
+ * Runs the source through a pipeline of transforms — currently
21
+ * strips frontmatter, with more steps added over time.
22
+ */
23
+ function clean(text) {
24
+ return pipeline(text);
25
+ }
26
+ //#endregion
27
+ //#region src/partials-dir.ts
28
+ /** Absolute path to the SDK's built-in partials directory. */
29
+ const PARTIALS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), "../prompts");
30
+ //#endregion
31
+ export { PARTIALS_DIR, clean, createEngine };
32
+
33
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../../src/clean.ts","../../src/partials-dir.ts"],"sourcesContent":["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"],"mappings":";;;;;AAEA,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"}
@@ -0,0 +1,38 @@
1
+ import { Liquid } from "liquidjs";
2
+ //#region src/engine.ts
3
+ /**
4
+ * Create a LiquidJS engine with custom options.
5
+ *
6
+ * The `partialsDir` is used as the root for `{% render %}` resolution.
7
+ * The `.prompt` extension is appended automatically.
8
+ *
9
+ * @param partialsDir - Root directory for `{% render %}` partial resolution.
10
+ * @param options - Optional overrides for the LiquidJS engine configuration.
11
+ * @returns A configured {@link Liquid} engine instance.
12
+ */
13
+ function createEngine(partialsDir, options) {
14
+ return new Liquid({
15
+ root: [partialsDir],
16
+ partials: [partialsDir],
17
+ extname: ".prompt",
18
+ cache: true,
19
+ strictFilters: true,
20
+ ownPropertyOnly: true,
21
+ ...options
22
+ });
23
+ }
24
+ /**
25
+ * Shared LiquidJS engine for rendering prompt templates at runtime.
26
+ *
27
+ * Partials are flattened at codegen time by the CLI, so this engine
28
+ * only needs to handle `{{ var }}` expressions and basic Liquid
29
+ * control flow (`{% if %}`, `{% for %}`). No filesystem access required.
30
+ */
31
+ const liquidEngine = new Liquid({
32
+ strictFilters: true,
33
+ ownPropertyOnly: true
34
+ });
35
+ //#endregion
36
+ export { liquidEngine as n, createEngine as t };
37
+
38
+ //# sourceMappingURL=engine-B53whAlC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-B53whAlC.mjs","names":[],"sources":["../../src/engine.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 liquidEngine = new Liquid({\n strictFilters: true,\n ownPropertyOnly: true,\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,eAAe,IAAI,OAAO;CACrC,eAAe;CACf,iBAAiB;CAClB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { t as CreateEngineOptions } from "./types-CiSdNM0W.mjs";
2
+ import { Liquid } from "liquidjs";
3
+
4
+ //#region src/engine.d.ts
5
+ /**
6
+ * Create a LiquidJS engine with custom options.
7
+ *
8
+ * The `partialsDir` is used as the root for `{% render %}` resolution.
9
+ * The `.prompt` extension is appended automatically.
10
+ *
11
+ * @param partialsDir - Root directory for `{% render %}` partial resolution.
12
+ * @param options - Optional overrides for the LiquidJS engine configuration.
13
+ * @returns A configured {@link Liquid} engine instance.
14
+ */
15
+ declare function createEngine(partialsDir: string, options?: Partial<CreateEngineOptions>): Liquid;
16
+ /**
17
+ * Shared LiquidJS engine for rendering prompt templates at runtime.
18
+ *
19
+ * Partials are flattened at codegen time by the CLI, so this engine
20
+ * only needs to handle `{{ var }}` expressions and basic Liquid
21
+ * control flow (`{% if %}`, `{% for %}`). No filesystem access required.
22
+ */
23
+ declare const liquidEngine: Liquid;
24
+ //#endregion
25
+ export { liquidEngine as n, createEngine as t };
26
+ //# sourceMappingURL=engine-B6JHetwb.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-B6JHetwb.d.mts","names":[],"sources":["../../src/engine.ts"],"mappings":";;;;;;AAcA;;;;;;;;iBAAgB,YAAA,CAAa,WAAA,UAAqB,OAAA,GAAU,OAAA,CAAQ,mBAAA,IAAuB,MAAA;;;;;;;AAmB3F;cAAa,YAAA,EAAY,MAAA"}
@@ -1,78 +1,5 @@
1
- import { Liquid, Liquid as Liquid$1, LiquidOptions } from "liquidjs";
2
- import { ZodType } from "zod";
1
+ import { a as PromptRegistry, i as PromptNamespace, r as PromptModule } from "./types-CiSdNM0W.mjs";
3
2
 
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
3
  //#region src/registry.d.ts
77
4
  /**
78
5
  * Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.
@@ -95,5 +22,5 @@ declare const PARTIALS_DIR: string;
95
22
  */
96
23
  declare function createPromptRegistry<T extends PromptNamespace>(modules: T): PromptRegistry<T>;
97
24
  //#endregion
98
- export { type CreateEngineOptions, type Liquid, PARTIALS_DIR, type PromptModule, type PromptNamespace, type PromptRegistry, clean, createEngine, createPromptRegistry, engine };
25
+ export { type PromptModule, type PromptNamespace, type PromptRegistry, createPromptRegistry };
99
26
  //# sourceMappingURL=index.d.mts.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/registry.ts"],"mappings":";;;;;AA8DA;;;;;;;;;;;;;;;;;iBAAgB,oBAAA,WAA+B,eAAA,CAAA,CAAiB,OAAA,EAAS,CAAA,GAAI,cAAA,CAAe,CAAA"}
@@ -1,67 +1,3 @@
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
1
  //#region src/registry.ts
66
2
  /**
67
3
  * Check whether a value looks like a PromptModule leaf.
@@ -112,6 +48,6 @@ function createPromptRegistry(modules) {
112
48
  return deepFreeze({ ...modules });
113
49
  }
114
50
  //#endregion
115
- export { PARTIALS_DIR, clean, createEngine, createPromptRegistry, engine };
51
+ export { createPromptRegistry };
116
52
 
117
53
  //# sourceMappingURL=index.mjs.map
@@ -1 +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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/registry.ts"],"sourcesContent":["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":";;;;;;;AAQA,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,2 @@
1
+ import { n as liquidEngine } from "./engine-B6JHetwb.mjs";
2
+ export { liquidEngine };
@@ -0,0 +1,2 @@
1
+ import { n as liquidEngine } from "./engine-B53whAlC.mjs";
2
+ export { liquidEngine };
@@ -0,0 +1,43 @@
1
+ import { 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
+ export { PromptRegistry as a, PromptNamespace as i, Liquid$1 as n, PromptModule as r, CreateEngineOptions as t };
43
+ //# sourceMappingURL=types-CiSdNM0W.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CiSdNM0W.d.mts","names":[],"sources":["../../src/types.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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funkai/prompts",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "description": "Prompt SDK with LiquidJS templating and Zod validation",
6
6
  "keywords": [
@@ -27,6 +27,14 @@
27
27
  ".": {
28
28
  "types": "./dist/lib/index.d.mts",
29
29
  "import": "./dist/lib/index.mjs"
30
+ },
31
+ "./runtime": {
32
+ "types": "./dist/lib/runtime.d.mts",
33
+ "import": "./dist/lib/runtime.mjs"
34
+ },
35
+ "./cli": {
36
+ "types": "./dist/lib/cli.d.mts",
37
+ "import": "./dist/lib/cli.mjs"
30
38
  }
31
39
  },
32
40
  "dependencies": {
@@ -37,7 +45,7 @@
37
45
  "devDependencies": {
38
46
  "@types/node": "^25.5.0",
39
47
  "@vitest/coverage-v8": "^4.1.0",
40
- "tsdown": "^0.21.2",
48
+ "tsdown": "^0.21.3",
41
49
  "typescript": "^5.9.3",
42
50
  "vitest": "^4.1.0"
43
51
  },
@@ -47,7 +55,6 @@
47
55
  "scripts": {
48
56
  "build": "tsdown && cp -r src/prompts dist/prompts",
49
57
  "typecheck": "tsc --noEmit",
50
- "test": "vitest run",
51
- "test:coverage": "vitest run --coverage"
58
+ "test": "vitest run"
52
59
  }
53
60
  }
package/src/cli.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { clean } from "./clean.js";
2
+ export { createEngine } from "./engine.js";
3
+ export { PARTIALS_DIR } from "./partials-dir.js";
4
+ export type { CreateEngineOptions, Liquid } from "./types.js";
@@ -1,7 +1,7 @@
1
1
  import { Liquid } from "liquidjs";
2
2
  import { describe, expect, it } from "vitest";
3
3
 
4
- import { createEngine, engine } from "@/engine.js";
4
+ import { createEngine, liquidEngine } from "@/engine.js";
5
5
 
6
6
  describe("createEngine", () => {
7
7
  it("should return a Liquid instance", () => {
@@ -26,19 +26,19 @@ describe("createEngine", () => {
26
26
  });
27
27
  });
28
28
 
29
- describe("engine", () => {
29
+ describe("liquidEngine", () => {
30
30
  it("should be a Liquid instance", () => {
31
- expect(engine).toBeInstanceOf(Liquid);
31
+ expect(liquidEngine).toBeInstanceOf(Liquid);
32
32
  });
33
33
 
34
34
  it("should render variable expressions", () => {
35
- const result = engine.parseAndRenderSync("Hello {{ name }}", { name: "World" });
35
+ const result = liquidEngine.parseAndRenderSync("Hello {{ name }}", { name: "World" });
36
36
  expect(result).toBe("Hello World");
37
37
  });
38
38
 
39
39
  it("should throw on unknown filters (strictFilters)", () => {
40
40
  expect(() => {
41
- engine.parseAndRenderSync("{{ name | bogus }}", { name: "test" });
41
+ liquidEngine.parseAndRenderSync("{{ name | bogus }}", { name: "test" });
42
42
  }).toThrow();
43
43
  });
44
44
  });
package/src/engine.ts CHANGED
@@ -31,7 +31,7 @@ export function createEngine(partialsDir: string, options?: Partial<CreateEngine
31
31
  * only needs to handle `{{ var }}` expressions and basic Liquid
32
32
  * control flow (`{% if %}`, `{% for %}`). No filesystem access required.
33
33
  */
34
- export const engine = new Liquid({
34
+ export const liquidEngine = new Liquid({
35
35
  strictFilters: true,
36
36
  ownPropertyOnly: true,
37
37
  });
package/src/index.ts CHANGED
@@ -1,11 +1,2 @@
1
- export { engine, createEngine } from "./engine.js";
2
- export { clean } from "./clean.js";
3
- export { PARTIALS_DIR } from "./partials-dir.js";
4
1
  export { createPromptRegistry } from "./registry.js";
5
- export type {
6
- CreateEngineOptions,
7
- Liquid,
8
- PromptModule,
9
- PromptNamespace,
10
- PromptRegistry,
11
- } from "./types.js";
2
+ export type { PromptModule, PromptNamespace, PromptRegistry } from "./types.js";
package/src/runtime.ts ADDED
@@ -0,0 +1 @@
1
+ export { liquidEngine } from "./engine.js";
package/tsdown.config.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { defineConfig } from "tsdown";
2
2
 
3
3
  export default defineConfig({
4
- entry: ["src/index.ts"],
4
+ entry: ["src/index.ts", "src/runtime.ts", "src/cli.ts"],
5
5
  outDir: "dist/lib",
6
6
  format: ["esm"],
7
7
  dts: true,