@funkai/prompts 0.3.0 → 0.4.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,5 +1,5 @@
1
1
 
2
- > @funkai/prompts@0.3.0 build /home/runner/work/funkai/funkai/packages/prompts
2
+ > @funkai/prompts@0.4.0 build /home/runner/work/funkai/funkai/packages/prompts
3
3
  > tsdown && cp -r src/prompts dist/prompts
4
4
 
5
5
  ℹ tsdown v0.21.4 powered by rolldown v1.0.0-rc.9
@@ -8,21 +8,21 @@
8
8
  ℹ target: node22
9
9
  ℹ tsconfig: tsconfig.json
10
10
  ℹ Build start
11
- ℹ dist/lib/index.mjs 1.70 kB │ gzip: 0.82 kB
11
+ ℹ dist/lib/index.mjs 3.92 kB │ gzip: 1.53 kB
12
12
  ℹ dist/lib/cli.mjs 1.39 kB │ gzip: 0.75 kB
13
13
  ℹ dist/lib/runtime.mjs 0.08 kB │ gzip: 0.08 kB
14
- ℹ dist/lib/index.mjs.map 2.71 kB │ gzip: 1.16 kB
14
+ ℹ dist/lib/index.mjs.map 5.72 kB │ gzip: 2.08 kB
15
15
  ℹ dist/lib/cli.mjs.map 1.86 kB │ gzip: 0.90 kB
16
16
  ℹ dist/lib/engine-CPKs9QbX.mjs.map 1.67 kB │ gzip: 0.85 kB
17
17
  ℹ dist/lib/engine-CPKs9QbX.mjs 1.17 kB │ gzip: 0.62 kB
18
- ℹ dist/lib/types-2PI_9h-M.d.mts.map 0.53 kB │ gzip: 0.29 kB
19
- ℹ dist/lib/engine-CQfJbVz6.d.mts.map 0.22 kB │ gzip: 0.18 kB
20
- ℹ dist/lib/index.d.mts.map 0.19 kB │ gzip: 0.15 kB
18
+ ℹ dist/lib/types-DmnHC99v.d.mts.map 0.66 kB │ gzip: 0.34 kB
19
+ ℹ dist/lib/index.d.mts.map 0.45 kB │ gzip: 0.25 kB
20
+ ℹ dist/lib/engine-BAYeiay3.d.mts.map 0.22 kB │ gzip: 0.17 kB
21
21
  ℹ dist/lib/cli.d.mts.map 0.18 kB │ gzip: 0.15 kB
22
- ℹ dist/lib/index.d.mts 1.04 kB │ gzip: 0.54 kB
22
+ ℹ dist/lib/index.d.mts 3.02 kB │ gzip: 1.14 kB
23
23
  ℹ dist/lib/cli.d.mts 0.94 kB │ gzip: 0.53 kB
24
24
  ℹ dist/lib/runtime.d.mts 0.08 kB │ gzip: 0.08 kB
25
- ℹ dist/lib/types-2PI_9h-M.d.mts 1.43 kB │ gzip: 0.69 kB
26
- ℹ dist/lib/engine-CQfJbVz6.d.mts 1.08 kB │ gzip: 0.58 kB
27
- ℹ 16 files, total: 16.28 kB
28
- ✔ Build complete in 1612ms
25
+ ℹ dist/lib/types-DmnHC99v.d.mts 2.17 kB │ gzip: 0.94 kB
26
+ ℹ dist/lib/engine-BAYeiay3.d.mts 1.08 kB │ gzip: 0.58 kB
27
+ ℹ 16 files, total: 24.62 kB
28
+ ✔ Build complete in 2257ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @funkai/prompts
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c8569db: feat(prompts): add createPrompt, createPromptGroup, and config-based group assignment
8
+
9
+ - Add `createPrompt<T>(config)` factory for building prompt modules at runtime and codegen
10
+ - Add `createPromptGroup(name, prompts)` for grouping prompt modules into namespaces
11
+ - Add `PromptConfig<T>` type for prompt module configuration
12
+ - Codegen now uses `createPrompt()` instead of raw object literals
13
+ - Scope name uniqueness to group+name instead of global name
14
+ - Derive file slugs and import names from group+name to avoid collisions
15
+ - Replace `roots` config field with `includes`/`excludes` glob patterns
16
+ - Add `groups` config field for pattern-based group assignment via picomatch
17
+ - Frontmatter `group` takes precedence over config-defined groups
18
+ - Updated banner format for generated files
19
+
3
20
  ## 0.3.0
4
21
 
5
22
  ### Minor Changes
@@ -1,5 +1,5 @@
1
- import { n as Liquid, t as CreateEngineOptions } from "./types-2PI_9h-M.mjs";
2
- import { t as createEngine } from "./engine-CQfJbVz6.mjs";
1
+ import { n as Liquid, t as CreateEngineOptions } from "./types-DmnHC99v.mjs";
2
+ import { t as createEngine } from "./engine-BAYeiay3.mjs";
3
3
 
4
4
  //#region src/clean.d.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as CreateEngineOptions } from "./types-2PI_9h-M.mjs";
1
+ import { t as CreateEngineOptions } from "./types-DmnHC99v.mjs";
2
2
  import { Liquid } from "liquidjs";
3
3
 
4
4
  //#region src/engine.d.ts
@@ -25,4 +25,4 @@ declare function createEngine(partialsDir: string, options?: Partial<CreateEngin
25
25
  declare const liquidEngine: Liquid;
26
26
  //#endregion
27
27
  export { liquidEngine as n, createEngine as t };
28
- //# sourceMappingURL=engine-CQfJbVz6.d.mts.map
28
+ //# sourceMappingURL=engine-BAYeiay3.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine-CQfJbVz6.d.mts","names":[],"sources":["../../src/engine.ts"],"mappings":";;;;;;AAcA;;;;;;;;iBAAgB,YAAA,CAAa,WAAA,UAAqB,OAAA,GAAU,OAAA,CAAQ,mBAAA,IAAuB,MAAA;;;;;;;AAsB3F;;;cAAa,YAAA,EAAY,MAAA"}
1
+ {"version":3,"file":"engine-BAYeiay3.d.mts","names":[],"sources":["../../src/engine.ts"],"mappings":";;;;;;AAcA;;;;;;;;iBAAgB,YAAA,CAAa,WAAA,UAAqB,OAAA,GAAU,OAAA,CAAQ,mBAAA,IAAuB,MAAA;;;;;;;AAsB3F;;;cAAa,YAAA,EAAY,MAAA"}
@@ -1,5 +1,62 @@
1
- import { a as PromptRegistry, i as PromptNamespace, r as PromptModule } from "./types-2PI_9h-M.mjs";
1
+ import { a as PromptNamespace, i as PromptModule, o as PromptRegistry, r as PromptConfig } from "./types-DmnHC99v.mjs";
2
2
 
3
+ //#region src/group.d.ts
4
+ /**
5
+ * Create a prompt group namespace from a record of prompt modules.
6
+ *
7
+ * Sets the `group` field on each module to the given group name,
8
+ * producing a new namespace object without mutating the originals.
9
+ *
10
+ * @param name - Group name applied to each prompt (e.g. `'agents'`, `'agents/core'`).
11
+ * @param prompts - Record of prompt modules to group.
12
+ * @returns A new {@link PromptNamespace} with group-tagged prompt modules.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createPrompt, createPromptGroup } from '@funkai/prompts'
17
+ * import { z } from 'zod'
18
+ *
19
+ * const agents = createPromptGroup('agents', {
20
+ * greeting: createPrompt({
21
+ * name: 'greeting',
22
+ * template: 'Hello {{ name }}!',
23
+ * schema: z.object({ name: z.string() }),
24
+ * }),
25
+ * })
26
+ *
27
+ * agents.greeting.render({ name: 'Alice' })
28
+ * ```
29
+ */
30
+ declare function createPromptGroup<T extends Record<string, PromptModule>>(name: string, prompts: T): T;
31
+ //#endregion
32
+ //#region src/prompt.d.ts
33
+ /**
34
+ * Create a prompt module from a config object.
35
+ *
36
+ * Encapsulates template rendering (via LiquidJS) and variable validation
37
+ * (via Zod) into a single {@link PromptModule}. Works for both codegen
38
+ * output and runtime on-the-fly prompt construction.
39
+ *
40
+ * @param config - Prompt configuration with name, template, schema, and optional group.
41
+ * @returns A {@link PromptModule} with `render` and `validate` methods.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import { createPrompt } from '@funkai/prompts'
46
+ * import { z } from 'zod'
47
+ *
48
+ * const greeting = createPrompt({
49
+ * name: 'greeting',
50
+ * template: 'Hello {{ name }}, welcome to {{ place }}!',
51
+ * schema: z.object({ name: z.string(), place: z.string() }),
52
+ * })
53
+ *
54
+ * greeting.render({ name: 'Alice', place: 'Wonderland' })
55
+ * // => "Hello Alice, welcome to Wonderland!"
56
+ * ```
57
+ */
58
+ declare function createPrompt<T>(config: PromptConfig<T>): PromptModule<T>;
59
+ //#endregion
3
60
  //#region src/registry.d.ts
4
61
  /**
5
62
  * Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.
@@ -22,5 +79,5 @@ import { a as PromptRegistry, i as PromptNamespace, r as PromptModule } from "./
22
79
  */
23
80
  declare function createPromptRegistry<T extends PromptNamespace>(modules: T): PromptRegistry<T>;
24
81
  //#endregion
25
- export { type PromptModule, type PromptNamespace, type PromptRegistry, createPromptRegistry };
82
+ export { type PromptConfig, type PromptModule, type PromptNamespace, type PromptRegistry, createPrompt, createPromptGroup, createPromptRegistry };
26
83
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/registry.ts"],"mappings":";;;;;AAqBA;;;;;;;;;;;;;;;;;iBAAgB,oBAAA,WAA+B,eAAA,CAAA,CAAiB,OAAA,EAAS,CAAA,GAAI,cAAA,CAAe,CAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/group.ts","../../src/prompt.ts","../../src/registry.ts"],"mappings":";;;;;AA4BA;;;;;;;;;;;;;;;;;;;;;ACAA;;;iBDAgB,iBAAA,WAA4B,MAAA,SAAe,YAAA,EAAA,CACzD,IAAA,UACA,OAAA,EAAS,CAAA,GACR,CAAA;;;;;AAHH;;;;;;;;;;;;;;;;;;;;;ACAA;;iBAAgB,YAAA,GAAA,CAAgB,MAAA,EAAQ,YAAA,CAAa,CAAA,IAAK,YAAA,CAAa,CAAA;;;;;ADAvE;;;;;;;;;;;;;;;;;iBEPgB,oBAAA,WAA+B,eAAA,CAAA,CAAiB,OAAA,EAAS,CAAA,GAAI,cAAA,CAAe,CAAA"}
@@ -1,3 +1,79 @@
1
+ import { n as liquidEngine } from "./engine-CPKs9QbX.mjs";
2
+ //#region src/group.ts
3
+ /**
4
+ * Create a prompt group namespace from a record of prompt modules.
5
+ *
6
+ * Sets the `group` field on each module to the given group name,
7
+ * producing a new namespace object without mutating the originals.
8
+ *
9
+ * @param name - Group name applied to each prompt (e.g. `'agents'`, `'agents/core'`).
10
+ * @param prompts - Record of prompt modules to group.
11
+ * @returns A new {@link PromptNamespace} with group-tagged prompt modules.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createPrompt, createPromptGroup } from '@funkai/prompts'
16
+ * import { z } from 'zod'
17
+ *
18
+ * const agents = createPromptGroup('agents', {
19
+ * greeting: createPrompt({
20
+ * name: 'greeting',
21
+ * template: 'Hello {{ name }}!',
22
+ * schema: z.object({ name: z.string() }),
23
+ * }),
24
+ * })
25
+ *
26
+ * agents.greeting.render({ name: 'Alice' })
27
+ * ```
28
+ */
29
+ function createPromptGroup(name, prompts) {
30
+ return Object.fromEntries(Object.entries(prompts).map(([key, module]) => [key, {
31
+ ...module,
32
+ group: name
33
+ }]));
34
+ }
35
+ //#endregion
36
+ //#region src/prompt.ts
37
+ /**
38
+ * Create a prompt module from a config object.
39
+ *
40
+ * Encapsulates template rendering (via LiquidJS) and variable validation
41
+ * (via Zod) into a single {@link PromptModule}. Works for both codegen
42
+ * output and runtime on-the-fly prompt construction.
43
+ *
44
+ * @param config - Prompt configuration with name, template, schema, and optional group.
45
+ * @returns A {@link PromptModule} with `render` and `validate` methods.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { createPrompt } from '@funkai/prompts'
50
+ * import { z } from 'zod'
51
+ *
52
+ * const greeting = createPrompt({
53
+ * name: 'greeting',
54
+ * template: 'Hello {{ name }}, welcome to {{ place }}!',
55
+ * schema: z.object({ name: z.string(), place: z.string() }),
56
+ * })
57
+ *
58
+ * greeting.render({ name: 'Alice', place: 'Wonderland' })
59
+ * // => "Hello Alice, welcome to Wonderland!"
60
+ * ```
61
+ */
62
+ function createPrompt(config) {
63
+ const { name, group, template, schema } = config;
64
+ return {
65
+ name,
66
+ group,
67
+ schema,
68
+ render(variables) {
69
+ return liquidEngine.parseAndRenderSync(template, schema.parse(variables));
70
+ },
71
+ validate(variables) {
72
+ return schema.parse(variables);
73
+ }
74
+ };
75
+ }
76
+ //#endregion
1
77
  //#region src/registry.ts
2
78
  /**
3
79
  * Create a typed, frozen prompt registry from a (possibly nested) map of prompt modules.
@@ -47,6 +123,6 @@ function deepFreeze(obj) {
47
123
  return obj;
48
124
  }
49
125
  //#endregion
50
- export { createPromptRegistry };
126
+ export { createPrompt, createPromptGroup, createPromptRegistry };
51
127
 
52
128
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/registry.ts"],"sourcesContent":["import type { PromptModule, PromptNamespace, PromptRegistry } from \"./types.js\";\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\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\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 intentionally left unfrozen\n * to avoid breaking Zod internal state.\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 for (const value of Object.values(obj)) {\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,qBAAgD,SAA+B;AAC7F,QAAO,WAAW,EAAE,GAAG,SAAS,CAAC;;;;;;;;AAanC,SAAS,eAAe,OAAuC;AAC7D,QACE,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,YAAY,SACZ,UAAU;;;;;;;;;;;;;AAed,SAAS,WAAsC,KAA2B;AACxE,QAAO,OAAO,IAAI;AAClB,MAAK,MAAM,SAAS,OAAO,OAAO,IAAI,CACpC,KACE,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,OAAO,SAAS,MAAM,IACvB,CAAC,eAAe,MAAM,CAEtB,YAAW,MAAyB;AAGxC,QAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/group.ts","../../src/prompt.ts","../../src/registry.ts"],"sourcesContent":["import type { PromptModule } from \"./types.js\";\n\n/**\n * Create a prompt group namespace from a record of prompt modules.\n *\n * Sets the `group` field on each module to the given group name,\n * producing a new namespace object without mutating the originals.\n *\n * @param name - Group name applied to each prompt (e.g. `'agents'`, `'agents/core'`).\n * @param prompts - Record of prompt modules to group.\n * @returns A new {@link PromptNamespace} with group-tagged prompt modules.\n *\n * @example\n * ```ts\n * import { createPrompt, createPromptGroup } from '@funkai/prompts'\n * import { z } from 'zod'\n *\n * const agents = createPromptGroup('agents', {\n * greeting: createPrompt({\n * name: 'greeting',\n * template: 'Hello {{ name }}!',\n * schema: z.object({ name: z.string() }),\n * }),\n * })\n *\n * agents.greeting.render({ name: 'Alice' })\n * ```\n */\nexport function createPromptGroup<T extends Record<string, PromptModule>>(\n name: string,\n prompts: T,\n): T {\n return Object.fromEntries(\n Object.entries(prompts).map(([key, module]) => [key, { ...module, group: name }]),\n ) as T;\n}\n","import { liquidEngine } from \"./engine.js\";\nimport type { PromptConfig, PromptModule } from \"./types.js\";\n\n/**\n * Create a prompt module from a config object.\n *\n * Encapsulates template rendering (via LiquidJS) and variable validation\n * (via Zod) into a single {@link PromptModule}. Works for both codegen\n * output and runtime on-the-fly prompt construction.\n *\n * @param config - Prompt configuration with name, template, schema, and optional group.\n * @returns A {@link PromptModule} with `render` and `validate` methods.\n *\n * @example\n * ```ts\n * import { createPrompt } from '@funkai/prompts'\n * import { z } from 'zod'\n *\n * const greeting = createPrompt({\n * name: 'greeting',\n * template: 'Hello {{ name }}, welcome to {{ place }}!',\n * schema: z.object({ name: z.string(), place: z.string() }),\n * })\n *\n * greeting.render({ name: 'Alice', place: 'Wonderland' })\n * // => \"Hello Alice, welcome to Wonderland!\"\n * ```\n */\nexport function createPrompt<T>(config: PromptConfig<T>): PromptModule<T> {\n const { name, group, template, schema } = config;\n\n return {\n name,\n group,\n schema,\n render(variables: T): string {\n return liquidEngine.parseAndRenderSync(\n template,\n schema.parse(variables) as Record<string, unknown>,\n );\n },\n validate(variables: unknown): T {\n return schema.parse(variables);\n },\n };\n}\n","import type { PromptModule, PromptNamespace, PromptRegistry } from \"./types.js\";\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\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\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 intentionally left unfrozen\n * to avoid breaking Zod internal state.\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 for (const value of Object.values(obj)) {\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,kBACd,MACA,SACG;AACH,QAAO,OAAO,YACZ,OAAO,QAAQ,QAAQ,CAAC,KAAK,CAAC,KAAK,YAAY,CAAC,KAAK;EAAE,GAAG;EAAQ,OAAO;EAAM,CAAC,CAAC,CAClF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNH,SAAgB,aAAgB,QAA0C;CACxE,MAAM,EAAE,MAAM,OAAO,UAAU,WAAW;AAE1C,QAAO;EACL;EACA;EACA;EACA,OAAO,WAAsB;AAC3B,UAAO,aAAa,mBAClB,UACA,OAAO,MAAM,UAAU,CACxB;;EAEH,SAAS,WAAuB;AAC9B,UAAO,OAAO,MAAM,UAAU;;EAEjC;;;;;;;;;;;;;;;;;;;;;;;ACvBH,SAAgB,qBAAgD,SAA+B;AAC7F,QAAO,WAAW,EAAE,GAAG,SAAS,CAAC;;;;;;;;AAanC,SAAS,eAAe,OAAuC;AAC7D,QACE,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,YAAY,SACZ,UAAU;;;;;;;;;;;;;AAed,SAAS,WAAsC,KAA2B;AACxE,QAAO,OAAO,IAAI;AAClB,MAAK,MAAM,SAAS,OAAO,OAAO,IAAI,CACpC,KACE,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,OAAO,SAAS,MAAM,IACvB,CAAC,eAAe,MAAM,CAEtB,YAAW,MAAyB;AAGxC,QAAO"}
@@ -1,2 +1,2 @@
1
- import { n as liquidEngine } from "./engine-CQfJbVz6.mjs";
1
+ import { n as liquidEngine } from "./engine-BAYeiay3.mjs";
2
2
  export { liquidEngine };
@@ -7,7 +7,29 @@ import { ZodType } from "zod";
7
7
  */
8
8
  type CreateEngineOptions = Pick<LiquidOptions, "root" | "partials" | "extname" | "cache" | "strictVariables">;
9
9
  /**
10
- * A single prompt module produced by codegen.
10
+ * Configuration for creating a prompt module via {@link createPrompt}.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const config: PromptConfig<{ name: string }> = {
15
+ * name: 'greeting',
16
+ * template: 'Hello {{ name }}!',
17
+ * schema: z.object({ name: z.string() }),
18
+ * }
19
+ * ```
20
+ */
21
+ interface PromptConfig<T = unknown> {
22
+ /** Kebab-case prompt identifier (e.g. `'greeting'`, `'worker-system'`). */
23
+ readonly name: string;
24
+ /** LiquidJS template string with `{{ variable }}` expressions. */
25
+ readonly template: string;
26
+ /** Zod schema for validating template variables. */
27
+ readonly schema: ZodType<T>;
28
+ /** Optional group path (e.g. `'agents'`, `'agents/core'`). */
29
+ readonly group?: string;
30
+ }
31
+ /**
32
+ * A single prompt module produced by {@link createPrompt} or codegen.
11
33
  *
12
34
  * Each `.prompt` file generates a default export conforming to this shape.
13
35
  */
@@ -39,5 +61,5 @@ interface PromptNamespace {
39
61
  */
40
62
  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
63
  //#endregion
42
- export { PromptRegistry as a, PromptNamespace as i, Liquid$1 as n, PromptModule as r, CreateEngineOptions as t };
43
- //# sourceMappingURL=types-2PI_9h-M.d.mts.map
64
+ export { PromptNamespace as a, PromptModule as i, Liquid$1 as n, PromptRegistry as o, PromptConfig as r, CreateEngineOptions as t };
65
+ //# sourceMappingURL=types-DmnHC99v.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DmnHC99v.d.mts","names":[],"sources":["../../src/types.ts"],"mappings":";;;;;;AAMA;KAAY,mBAAA,GAAsB,IAAA,CAChC,aAAA;;;;AAgBF;;;;;;;;;UAAiB,YAAA;EAQN;EAAA,SANA,IAAA;EAMK;EAAA,SAJL,QAAA;EAYkB;EAAA,SAVlB,MAAA,EAAQ,OAAA,CAAQ,CAAA;EAaA;EAAA,SAXhB,KAAA;AAAA;;;;;;UAQM,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;;;;;UAOf,eAAA;EAAA,UACL,GAAA,WAAc,YAAA,GAAe,eAAA;AAAA;;;;;;;;AAezC;;;;;KAAY,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.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "description": "Prompt SDK with LiquidJS templating and Zod validation",
6
6
  "keywords": [
@@ -0,0 +1,89 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { z } from "zod";
3
+
4
+ import { createPromptGroup } from "@/group.js";
5
+ import { createPrompt } from "@/prompt.js";
6
+
7
+ describe(createPromptGroup, () => {
8
+ it("should set the group on each prompt module", () => {
9
+ const greeting = createPrompt({
10
+ name: "greeting",
11
+ template: "Hello {{ name }}!",
12
+ schema: z.object({ name: z.string() }),
13
+ });
14
+
15
+ const group = createPromptGroup("agents", { greeting });
16
+
17
+ expect(group.greeting.group).toBe("agents");
18
+ });
19
+
20
+ it("should override existing group on prompt modules", () => {
21
+ const greeting = createPrompt({
22
+ name: "greeting",
23
+ group: "old-group",
24
+ template: "Hello {{ name }}!",
25
+ schema: z.object({ name: z.string() }),
26
+ });
27
+
28
+ const group = createPromptGroup("agents", { greeting });
29
+
30
+ expect(group.greeting.group).toBe("agents");
31
+ });
32
+
33
+ it("should not mutate the original prompt module", () => {
34
+ const greeting = createPrompt({
35
+ name: "greeting",
36
+ template: "Hello {{ name }}!",
37
+ schema: z.object({ name: z.string() }),
38
+ });
39
+
40
+ createPromptGroup("agents", { greeting });
41
+
42
+ expect(greeting.group).toBeUndefined();
43
+ });
44
+
45
+ it("should preserve render functionality", () => {
46
+ const greeting = createPrompt({
47
+ name: "greeting",
48
+ template: "Hello {{ name }}!",
49
+ schema: z.object({ name: z.string() }),
50
+ });
51
+
52
+ const group = createPromptGroup("agents", { greeting });
53
+
54
+ expect(group.greeting.render({ name: "Alice" })).toBe("Hello Alice!");
55
+ });
56
+
57
+ it("should support multiple prompts in a group", () => {
58
+ const greeting = createPrompt({
59
+ name: "greeting",
60
+ template: "Hello {{ name }}!",
61
+ schema: z.object({ name: z.string() }),
62
+ });
63
+
64
+ const farewell = createPrompt({
65
+ name: "farewell",
66
+ template: "Goodbye {{ name }}!",
67
+ schema: z.object({ name: z.string() }),
68
+ });
69
+
70
+ const group = createPromptGroup("agents", { greeting, farewell });
71
+
72
+ expect(group.greeting.group).toBe("agents");
73
+ expect(group.farewell.group).toBe("agents");
74
+ expect(group.greeting.render({ name: "Alice" })).toBe("Hello Alice!");
75
+ expect(group.farewell.render({ name: "Bob" })).toBe("Goodbye Bob!");
76
+ });
77
+
78
+ it("should support nested group paths", () => {
79
+ const system = createPrompt({
80
+ name: "system",
81
+ template: "You are a {{ role }}.",
82
+ schema: z.object({ role: z.string() }),
83
+ });
84
+
85
+ const group = createPromptGroup("agents/core", { system });
86
+
87
+ expect(group.system.group).toBe("agents/core");
88
+ });
89
+ });
package/src/group.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type { PromptModule } from "./types.js";
2
+
3
+ /**
4
+ * Create a prompt group namespace from a record of prompt modules.
5
+ *
6
+ * Sets the `group` field on each module to the given group name,
7
+ * producing a new namespace object without mutating the originals.
8
+ *
9
+ * @param name - Group name applied to each prompt (e.g. `'agents'`, `'agents/core'`).
10
+ * @param prompts - Record of prompt modules to group.
11
+ * @returns A new {@link PromptNamespace} with group-tagged prompt modules.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { createPrompt, createPromptGroup } from '@funkai/prompts'
16
+ * import { z } from 'zod'
17
+ *
18
+ * const agents = createPromptGroup('agents', {
19
+ * greeting: createPrompt({
20
+ * name: 'greeting',
21
+ * template: 'Hello {{ name }}!',
22
+ * schema: z.object({ name: z.string() }),
23
+ * }),
24
+ * })
25
+ *
26
+ * agents.greeting.render({ name: 'Alice' })
27
+ * ```
28
+ */
29
+ export function createPromptGroup<T extends Record<string, PromptModule>>(
30
+ name: string,
31
+ prompts: T,
32
+ ): T {
33
+ return Object.fromEntries(
34
+ Object.entries(prompts).map(([key, module]) => [key, { ...module, group: name }]),
35
+ ) as T;
36
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export { createPromptGroup } from "./group.js";
2
+ export { createPrompt } from "./prompt.js";
1
3
  export { createPromptRegistry } from "./registry.js";
2
- export type { PromptModule, PromptNamespace, PromptRegistry } from "./types.js";
4
+ export type { PromptConfig, PromptModule, PromptNamespace, PromptRegistry } from "./types.js";
@@ -0,0 +1,90 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { z } from "zod";
3
+
4
+ import { createPrompt } from "@/prompt.js";
5
+
6
+ describe(createPrompt, () => {
7
+ it("should create a prompt module with name and group", () => {
8
+ const prompt = createPrompt({
9
+ name: "greeting",
10
+ group: "agents",
11
+ template: "Hello {{ name }}!",
12
+ schema: z.object({ name: z.string() }),
13
+ });
14
+
15
+ expect(prompt.name).toBe("greeting");
16
+ expect(prompt.group).toBe("agents");
17
+ });
18
+
19
+ it("should set group to undefined when not provided", () => {
20
+ const prompt = createPrompt({
21
+ name: "greeting",
22
+ template: "Hello!",
23
+ schema: z.object({}),
24
+ });
25
+
26
+ expect(prompt.group).toBeUndefined();
27
+ });
28
+
29
+ it("should render a template with variables", () => {
30
+ const prompt = createPrompt({
31
+ name: "greeting",
32
+ template: "Hello {{ name }}, welcome to {{ place }}!",
33
+ schema: z.object({ name: z.string(), place: z.string() }),
34
+ });
35
+
36
+ const result = prompt.render({ name: "Alice", place: "Wonderland" });
37
+ expect(result).toBe("Hello Alice, welcome to Wonderland!");
38
+ });
39
+
40
+ it("should render a static template with no variables", () => {
41
+ const prompt = createPrompt({
42
+ name: "static",
43
+ template: "No variables here.",
44
+ schema: z.object({}),
45
+ });
46
+
47
+ expect(prompt.render({})).toBe("No variables here.");
48
+ });
49
+
50
+ it("should validate variables against the schema", () => {
51
+ const prompt = createPrompt({
52
+ name: "greeting",
53
+ template: "Hello {{ name }}!",
54
+ schema: z.object({ name: z.string() }),
55
+ });
56
+
57
+ expect(prompt.validate({ name: "Alice" })).toEqual({ name: "Alice" });
58
+ });
59
+
60
+ it("should throw on invalid variables during render", () => {
61
+ const prompt = createPrompt({
62
+ name: "greeting",
63
+ template: "Hello {{ name }}!",
64
+ schema: z.object({ name: z.string() }),
65
+ });
66
+
67
+ expect(() => prompt.render({ name: 42 } as never)).toThrow();
68
+ });
69
+
70
+ it("should throw on invalid variables during validate", () => {
71
+ const prompt = createPrompt({
72
+ name: "greeting",
73
+ template: "Hello {{ name }}!",
74
+ schema: z.object({ name: z.string() }),
75
+ });
76
+
77
+ expect(() => prompt.validate({ name: 42 })).toThrow();
78
+ });
79
+
80
+ it("should expose the schema for external validation", () => {
81
+ const schema = z.object({ name: z.string() });
82
+ const prompt = createPrompt({
83
+ name: "greeting",
84
+ template: "Hello {{ name }}!",
85
+ schema,
86
+ });
87
+
88
+ expect(prompt.schema).toBe(schema);
89
+ });
90
+ });
package/src/prompt.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { liquidEngine } from "./engine.js";
2
+ import type { PromptConfig, PromptModule } from "./types.js";
3
+
4
+ /**
5
+ * Create a prompt module from a config object.
6
+ *
7
+ * Encapsulates template rendering (via LiquidJS) and variable validation
8
+ * (via Zod) into a single {@link PromptModule}. Works for both codegen
9
+ * output and runtime on-the-fly prompt construction.
10
+ *
11
+ * @param config - Prompt configuration with name, template, schema, and optional group.
12
+ * @returns A {@link PromptModule} with `render` and `validate` methods.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createPrompt } from '@funkai/prompts'
17
+ * import { z } from 'zod'
18
+ *
19
+ * const greeting = createPrompt({
20
+ * name: 'greeting',
21
+ * template: 'Hello {{ name }}, welcome to {{ place }}!',
22
+ * schema: z.object({ name: z.string(), place: z.string() }),
23
+ * })
24
+ *
25
+ * greeting.render({ name: 'Alice', place: 'Wonderland' })
26
+ * // => "Hello Alice, welcome to Wonderland!"
27
+ * ```
28
+ */
29
+ export function createPrompt<T>(config: PromptConfig<T>): PromptModule<T> {
30
+ const { name, group, template, schema } = config;
31
+
32
+ return {
33
+ name,
34
+ group,
35
+ schema,
36
+ render(variables: T): string {
37
+ return liquidEngine.parseAndRenderSync(
38
+ template,
39
+ schema.parse(variables) as Record<string, unknown>,
40
+ );
41
+ },
42
+ validate(variables: unknown): T {
43
+ return schema.parse(variables);
44
+ },
45
+ };
46
+ }
@@ -1,31 +1,21 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { z } from "zod";
3
3
 
4
+ import { createPrompt } from "@/prompt.js";
4
5
  import { createPromptRegistry } from "@/registry.js";
5
6
 
6
- const mockPrompt = {
7
- name: "test-prompt" as const,
8
- group: "agents" as const,
7
+ const mockPrompt = createPrompt({
8
+ name: "test-prompt",
9
+ group: "agents",
10
+ template: "Hello {{ name }}",
9
11
  schema: z.object({ name: z.string() }),
10
- render(variables: { name: string }) {
11
- return `Hello ${variables.name}`;
12
- },
13
- validate(variables: unknown) {
14
- return z.object({ name: z.string() }).parse(variables);
15
- },
16
- };
12
+ });
17
13
 
18
- const emptyPrompt = {
19
- name: "empty" as const,
20
- group: undefined,
14
+ const emptyPrompt = createPrompt({
15
+ name: "empty",
16
+ template: "static",
21
17
  schema: z.object({}),
22
- render() {
23
- return "static";
24
- },
25
- validate(variables: unknown) {
26
- return z.object({}).parse(variables);
27
- },
28
- };
18
+ });
29
19
 
30
20
  describe(createPromptRegistry, () => {
31
21
  it("should provide dot-access to a registered prompt", () => {
package/src/types.ts CHANGED
@@ -10,7 +10,30 @@ export type CreateEngineOptions = Pick<
10
10
  >;
11
11
 
12
12
  /**
13
- * A single prompt module produced by codegen.
13
+ * Configuration for creating a prompt module via {@link createPrompt}.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const config: PromptConfig<{ name: string }> = {
18
+ * name: 'greeting',
19
+ * template: 'Hello {{ name }}!',
20
+ * schema: z.object({ name: z.string() }),
21
+ * }
22
+ * ```
23
+ */
24
+ export interface PromptConfig<T = unknown> {
25
+ /** Kebab-case prompt identifier (e.g. `'greeting'`, `'worker-system'`). */
26
+ readonly name: string;
27
+ /** LiquidJS template string with `{{ variable }}` expressions. */
28
+ readonly template: string;
29
+ /** Zod schema for validating template variables. */
30
+ readonly schema: ZodType<T>;
31
+ /** Optional group path (e.g. `'agents'`, `'agents/core'`). */
32
+ readonly group?: string;
33
+ }
34
+
35
+ /**
36
+ * A single prompt module produced by {@link createPrompt} or codegen.
14
37
  *
15
38
  * Each `.prompt` file generates a default export conforming to this shape.
16
39
  */
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-2PI_9h-M.d.mts","names":[],"sources":["../../src/types.ts"],"mappings":";;;;;;AAMA;KAAY,mBAAA,GAAsB,IAAA,CAChC,aAAA;;;;AASF;;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;;;;;UAOf,eAAA;EAAA,UACL,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"}