@funkai/prompts 0.3.0 → 0.4.1
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 +13 -13
- package/CHANGELOG.md +28 -0
- package/README.md +3 -3
- package/dist/lib/cli.d.mts +2 -2
- package/dist/lib/cli.mjs +1 -1
- package/dist/lib/{engine-CQfJbVz6.d.mts → engine-BAYeiay3.d.mts} +2 -2
- package/dist/lib/{engine-CQfJbVz6.d.mts.map → engine-BAYeiay3.d.mts.map} +1 -1
- package/dist/lib/{engine-CPKs9QbX.mjs → engine-Bhv5Zxdu.mjs} +3 -1
- package/dist/lib/{engine-CPKs9QbX.mjs.map → engine-Bhv5Zxdu.mjs.map} +1 -1
- package/dist/lib/index.d.mts +59 -2
- package/dist/lib/index.d.mts.map +1 -1
- package/dist/lib/index.mjs +84 -4
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/runtime.d.mts +1 -1
- package/dist/lib/runtime.mjs +1 -1
- package/dist/lib/{types-2PI_9h-M.d.mts → types-DmnHC99v.d.mts} +25 -3
- package/dist/lib/types-DmnHC99v.d.mts.map +1 -0
- package/docs/cli/commands.md +8 -8
- package/docs/cli/overview.md +1 -1
- package/docs/cli.md +132 -0
- package/docs/codegen.md +142 -0
- package/docs/file-format/overview.md +1 -1
- package/docs/file-format.md +306 -0
- package/docs/guides/author-prompt.md +2 -2
- package/docs/guides/setup-project.md +1 -1
- package/docs/overview.md +9 -36
- package/docs/setup.md +76 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +2 -2
- package/src/engine.ts +2 -0
- package/src/group.test.ts +89 -0
- package/src/group.ts +36 -0
- package/src/index.ts +3 -1
- package/src/prompt.test.ts +90 -0
- package/src/prompt.ts +60 -0
- package/src/registry.test.ts +10 -20
- package/src/registry.ts +11 -11
- package/src/types.ts +24 -1
- package/tsconfig.json +12 -5
- package/dist/lib/types-2PI_9h-M.d.mts.map +0 -1
package/docs/codegen.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Code Generation & Library
|
|
2
|
+
|
|
3
|
+
The CLI transforms `.prompt` source files into typed TypeScript modules. This doc covers the pipeline stages, generated output shape, and the runtime library API.
|
|
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
|
+
## Runtime Library API
|
|
80
|
+
|
|
81
|
+
The library surface provides the runtime engine and registry used by generated code and consuming packages.
|
|
82
|
+
|
|
83
|
+
### Exports
|
|
84
|
+
|
|
85
|
+
| Export | Type | Description |
|
|
86
|
+
| ---------------------- | ----------------------------------- | -------------------------------------------------------------------------- |
|
|
87
|
+
| `engine` | `Liquid` | Shared LiquidJS instance (no filesystem, strict filters) |
|
|
88
|
+
| `createEngine` | `(partialsDir, options?) => Liquid` | Factory for filesystem-backed engines (used by CLI for partial resolution) |
|
|
89
|
+
| `clean` | `(content: string) => string` | Strips frontmatter, returns render-ready template |
|
|
90
|
+
| `createPromptRegistry` | `(modules) => PromptRegistry` | Creates typed registry from prompt module map |
|
|
91
|
+
|
|
92
|
+
### Engine
|
|
93
|
+
|
|
94
|
+
The shared `engine` instance is configured with `ownPropertyOnly: true` and `strictFilters: true` for security. No filesystem access -- templates are rendered from strings via `parseAndRenderSync`.
|
|
95
|
+
|
|
96
|
+
`createEngine` accepts a `partialsDir` and optional overrides. It enables filesystem-backed partial resolution (`.prompt` extension, caching enabled) for use during codegen flattening.
|
|
97
|
+
|
|
98
|
+
### Registry
|
|
99
|
+
|
|
100
|
+
`createPromptRegistry` accepts a (possibly nested) record of `PromptModule` objects and namespace nodes. It returns a deep-frozen `PromptRegistry` with direct property access:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const prompts = createPromptRegistry({
|
|
104
|
+
agents: { coverageAssessor },
|
|
105
|
+
greeting,
|
|
106
|
+
});
|
|
107
|
+
prompts.agents.coverageAssessor.render({ scope: "full" });
|
|
108
|
+
prompts.greeting.render();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Nesting is driven by the `group` field in frontmatter. Each `/`-separated segment becomes a nesting level, with all names converted to camelCase. The registry is frozen at creation time to prevent mutation.
|
|
112
|
+
|
|
113
|
+
## Consumer Import Pattern
|
|
114
|
+
|
|
115
|
+
The generated `index.ts` calls `createPromptRegistry` with all prompt modules organized by group and exports a `prompts` const object. Consumers import via the `~prompts` tsconfig alias:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { prompts } from "~prompts";
|
|
119
|
+
|
|
120
|
+
// Flat (no group)
|
|
121
|
+
const text = prompts.greeting.render();
|
|
122
|
+
|
|
123
|
+
// Nested (group: agents)
|
|
124
|
+
const text = prompts.agents.coverageAssessor.render({ scope: "full" });
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Types are inferred from the object structure, giving full type safety on `render` and `validate` arguments at every nesting level.
|
|
128
|
+
|
|
129
|
+
## Types Reference
|
|
130
|
+
|
|
131
|
+
| Type | Description |
|
|
132
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| `PromptModule` | Interface: `name`, `group`, `schema` (ZodType), `render(vars)`, `validate(vars)` |
|
|
134
|
+
| `PromptNamespace` | A nested namespace node -- values are `PromptModule` leaves or further nested namespaces |
|
|
135
|
+
| `PromptRegistry` | Deep-readonly mapped type over a `PromptNamespace` tree |
|
|
136
|
+
| `CreateEngineOptions` | Options for `createEngine`: `root`, `partials`, `extname`, `cache`, `strictFilters`, `strictVariables`, `ownPropertyOnly` |
|
|
137
|
+
| `Liquid` | Re-exported LiquidJS engine type |
|
|
138
|
+
|
|
139
|
+
## References
|
|
140
|
+
|
|
141
|
+
- [File Format](file-format.md)
|
|
142
|
+
- [CLI](cli.md)
|
|
@@ -44,7 +44,7 @@ Names must match `^[a-z0-9-]+$` (lowercase, digits, hyphens). The `name` field i
|
|
|
44
44
|
|
|
45
45
|
## Discovery
|
|
46
46
|
|
|
47
|
-
The CLI scans `--
|
|
47
|
+
The CLI scans `--includes` glob patterns 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
48
|
|
|
49
49
|
Results are sorted alphabetically by name.
|
|
50
50
|
|
|
@@ -0,0 +1,306 @@
|
|
|
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
|
+
## File Anatomy
|
|
6
|
+
|
|
7
|
+
Every `.prompt` file has two sections: a YAML frontmatter block delimited by `---` fences, and a LiquidJS template body.
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
---
|
|
11
|
+
name: coverage-assessor
|
|
12
|
+
group: agents/coverage-assessor
|
|
13
|
+
schema:
|
|
14
|
+
scope:
|
|
15
|
+
type: string
|
|
16
|
+
description: Assessment scope
|
|
17
|
+
target:
|
|
18
|
+
type: string
|
|
19
|
+
required: false
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
You are a coverage assessor for {{ scope }}.
|
|
23
|
+
{% if target %}Targeting {{ target }} docs.{% endif %}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
| Section | Description |
|
|
27
|
+
| ------------------- | ------------------------------------------------------------- |
|
|
28
|
+
| Frontmatter (`---`) | YAML metadata block defining name, group, and variable schema |
|
|
29
|
+
| Body | LiquidJS template rendered at runtime with typed variables |
|
|
30
|
+
|
|
31
|
+
## Template Syntax
|
|
32
|
+
|
|
33
|
+
| Syntax | Purpose |
|
|
34
|
+
| --------------------------------------- | ----------------------------------- |
|
|
35
|
+
| `{{ var }}` | Variable output |
|
|
36
|
+
| `{{ var \| filter }}` | Filtered output |
|
|
37
|
+
| `{% if var %}...{% endif %}` | Conditional |
|
|
38
|
+
| `{% for item in list %}...{% endfor %}` | Iteration |
|
|
39
|
+
| `{% render 'name', key: 'value' %}` | Partial inclusion (build-time only) |
|
|
40
|
+
|
|
41
|
+
Strict filters are enabled -- unknown filters throw an error. Variable access is restricted to own properties only.
|
|
42
|
+
|
|
43
|
+
## Frontmatter Reference
|
|
44
|
+
|
|
45
|
+
The YAML frontmatter block defines metadata and the variable schema.
|
|
46
|
+
|
|
47
|
+
### Fields
|
|
48
|
+
|
|
49
|
+
| Field | Required | Type | Description |
|
|
50
|
+
| --------- | -------- | -------- | ------------------------------------------------ |
|
|
51
|
+
| `name` | Yes | `string` | Unique kebab-case identifier (`^[a-z0-9-]+$`) |
|
|
52
|
+
| `group` | No | `string` | Namespace path (e.g. `agents/coverage-assessor`) |
|
|
53
|
+
| `version` | No | `string` | Version identifier |
|
|
54
|
+
| `schema` | No | `object` | Variable declarations map |
|
|
55
|
+
|
|
56
|
+
### Validation Rules
|
|
57
|
+
|
|
58
|
+
- `name` is required and must match `^[a-z0-9-]+$`
|
|
59
|
+
- Frontmatter must be valid YAML between `---` delimiters
|
|
60
|
+
- `schema` must be an object (not an array)
|
|
61
|
+
- Missing or empty `name` throws a parse error with the file path
|
|
62
|
+
- Non-object frontmatter (e.g. a bare string) is rejected
|
|
63
|
+
|
|
64
|
+
## Schema Variables
|
|
65
|
+
|
|
66
|
+
Each key under `schema` declares a template variable. Two syntaxes are supported.
|
|
67
|
+
|
|
68
|
+
**Shorthand** -- type string only, defaults to required:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
schema:
|
|
72
|
+
scope: string
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Full object** -- explicit control over all fields:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
schema:
|
|
79
|
+
scope:
|
|
80
|
+
type: string
|
|
81
|
+
required: true
|
|
82
|
+
description: Assessment scope
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Shorthand `scope: string` expands to `{ type: 'string', required: true }`.
|
|
86
|
+
|
|
87
|
+
### Variable Fields
|
|
88
|
+
|
|
89
|
+
| Field | Default | Description |
|
|
90
|
+
| ------------- | -------- | ---------------------------------------------------- |
|
|
91
|
+
| `type` | `string` | Variable type (only `string` supported) |
|
|
92
|
+
| `required` | `true` | Whether the variable must be provided at render time |
|
|
93
|
+
| `description` | -- | Human-readable description (used in generated JSDoc) |
|
|
94
|
+
|
|
95
|
+
## Naming and Discovery
|
|
96
|
+
|
|
97
|
+
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`).
|
|
98
|
+
|
|
99
|
+
The CLI scans `--includes` glob patterns recursively (max depth 5). Files must have the `.prompt` extension. Symbolic links are skipped. Duplicate names across roots cause an error with paths listed. Results are sorted alphabetically by name.
|
|
100
|
+
|
|
101
|
+
### Recommended File Structure
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
src/
|
|
105
|
+
agents/
|
|
106
|
+
coverage-assessor/
|
|
107
|
+
prompt.prompt
|
|
108
|
+
prompts/
|
|
109
|
+
identity.prompt
|
|
110
|
+
constraints.prompt
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Partials
|
|
114
|
+
|
|
115
|
+
Partials are reusable template fragments included with `{% render %}` tags. They are resolved and flattened at build time -- the generated output contains no render tags.
|
|
116
|
+
|
|
117
|
+
### Syntax
|
|
118
|
+
|
|
119
|
+
```liquid
|
|
120
|
+
{% render 'identity', role: 'Coverage Assessor', desc: 'an expert at assessing documentation coverage' %}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Only literal string parameters are supported. Variable references (e.g. `key: myVar`) are not allowed and throw an error at codegen time. Whitespace trim variants `{%-` and `-%}` are supported.
|
|
124
|
+
|
|
125
|
+
### Resolution Order
|
|
126
|
+
|
|
127
|
+
Partials are resolved from two locations, searched in order (first match wins):
|
|
128
|
+
|
|
129
|
+
| Priority | Location | Description |
|
|
130
|
+
| -------- | -------------------- | ------------------------------------------------ |
|
|
131
|
+
| 1 | `.prompts/partials/` | Custom project partials (committed to git) |
|
|
132
|
+
| 2 | SDK `src/prompts/` | Built-in partials shipped with `@funkai/prompts` |
|
|
133
|
+
|
|
134
|
+
Custom partials take precedence -- a custom partial with the same name as a built-in overrides it.
|
|
135
|
+
|
|
136
|
+
### Built-in Partials
|
|
137
|
+
|
|
138
|
+
| Partial | Parameters | Purpose |
|
|
139
|
+
| ------------- | -------------------------------------------------- | --------------------------------------------------- |
|
|
140
|
+
| `identity` | `role`, `desc`, `context` (optional) | Agent identity block (`<identity>` wrapper) |
|
|
141
|
+
| `constraints` | `in_scope`, `out_of_scope`, `rules` (all optional) | Scoping constraints block (`<constraints>` wrapper) |
|
|
142
|
+
| `tools` | `tools` (optional) | Tool listing block (`<tools>` wrapper) |
|
|
143
|
+
|
|
144
|
+
**identity** source:
|
|
145
|
+
|
|
146
|
+
```liquid
|
|
147
|
+
<identity>
|
|
148
|
+
You are {{ role }}, {{ desc }}.
|
|
149
|
+
{% if context %}
|
|
150
|
+
{{ context }}
|
|
151
|
+
{% endif %}
|
|
152
|
+
</identity>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**constraints** source:
|
|
156
|
+
|
|
157
|
+
```liquid
|
|
158
|
+
<constraints>
|
|
159
|
+
{% if in_scope %}
|
|
160
|
+
## In Scope
|
|
161
|
+
{% for item in in_scope %}
|
|
162
|
+
- {{ item }}
|
|
163
|
+
{% endfor %}
|
|
164
|
+
{% endif %}
|
|
165
|
+
{% if out_of_scope %}
|
|
166
|
+
## Out of Scope
|
|
167
|
+
{% for item in out_of_scope %}
|
|
168
|
+
- {{ item }}
|
|
169
|
+
{% endfor %}
|
|
170
|
+
{% endif %}
|
|
171
|
+
{% if rules %}
|
|
172
|
+
## Rules
|
|
173
|
+
{% for rule in rules %}
|
|
174
|
+
- {{ rule }}
|
|
175
|
+
{% endfor %}
|
|
176
|
+
{% endif %}
|
|
177
|
+
</constraints>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Custom Partials
|
|
181
|
+
|
|
182
|
+
Place custom `.prompt` files in `.prompts/partials/`:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
.prompts/
|
|
186
|
+
client/ # Generated (gitignored)
|
|
187
|
+
partials/ # Custom partials (committed)
|
|
188
|
+
summary.prompt
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The CLI auto-discovers this directory:
|
|
192
|
+
|
|
193
|
+
- `prompts generate` derives it from `--out` (sibling `partials/` dir)
|
|
194
|
+
- `prompts lint` defaults to `.prompts/partials` (configurable via `--partials`)
|
|
195
|
+
|
|
196
|
+
**Creating a custom partial:**
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
prompts create summary --partial
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Or create `.prompts/partials/<name>.prompt` by hand:
|
|
203
|
+
|
|
204
|
+
```liquid
|
|
205
|
+
<summary>
|
|
206
|
+
{{ content }}
|
|
207
|
+
{% if notes %}
|
|
208
|
+
Notes: {{ notes }}
|
|
209
|
+
{% endif %}
|
|
210
|
+
</summary>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Use it in a `.prompt` file:
|
|
214
|
+
|
|
215
|
+
```liquid
|
|
216
|
+
{% render 'summary', content: 'Analysis complete' %}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Run `prompts generate` -- the partial is flattened into the generated output. No `{% render %}` tags remain.
|
|
220
|
+
|
|
221
|
+
**Overriding built-ins:** Create a file with the same name in `.prompts/partials/` (e.g. `.prompts/partials/identity.prompt`). Custom partials take precedence over SDK built-ins.
|
|
222
|
+
|
|
223
|
+
**Adding a built-in partial (SDK contributors):**
|
|
224
|
+
|
|
225
|
+
1. Create `packages/prompts/src/prompts/<name>.prompt`
|
|
226
|
+
2. Write the partial template using XML-style wrapper tags and Liquid variables
|
|
227
|
+
3. Test with a consumer `.prompt` file and run `prompts generate`
|
|
228
|
+
|
|
229
|
+
## Authoring Walkthrough
|
|
230
|
+
|
|
231
|
+
### Prerequisites
|
|
232
|
+
|
|
233
|
+
- `@funkai/prompts` installed
|
|
234
|
+
- Project configured ([Setup guide](setup.md))
|
|
235
|
+
|
|
236
|
+
### Steps
|
|
237
|
+
|
|
238
|
+
1. **Scaffold** with the CLI:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
prompts create my-agent --out src/agents/my-agent
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
2. **Edit** the frontmatter -- set `name`, `group`, and `schema` variables.
|
|
245
|
+
|
|
246
|
+
3. **Write** the template body using `{{ var }}` syntax and conditionals.
|
|
247
|
+
|
|
248
|
+
4. **Add partials** if needed:
|
|
249
|
+
|
|
250
|
+
```liquid
|
|
251
|
+
{% render 'identity', role: 'Analyzer', desc: 'a code analyzer' %}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
5. **Lint:**
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
prompts lint --includes "src/agents/**"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
6. **Generate:**
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
prompts generate --out .prompts/client --includes "src/agents/**"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
7. **Import and use:**
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { prompts } from "~prompts";
|
|
270
|
+
|
|
271
|
+
const text = prompts.myAgent.render({ scope: "full" });
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Verification
|
|
275
|
+
|
|
276
|
+
- `prompts lint` reports no errors
|
|
277
|
+
- Generated file exists at `.prompts/client/my-agent.ts`
|
|
278
|
+
- TypeScript compiles without errors
|
|
279
|
+
|
|
280
|
+
### Troubleshooting
|
|
281
|
+
|
|
282
|
+
#### Undefined variable error
|
|
283
|
+
|
|
284
|
+
**Fix:** Add the variable to the frontmatter `schema` block.
|
|
285
|
+
|
|
286
|
+
#### Duplicate prompt name
|
|
287
|
+
|
|
288
|
+
**Fix:** Two `.prompt` files share the same `name` -- rename one to a unique kebab-case identifier.
|
|
289
|
+
|
|
290
|
+
#### TypeScript can't find `~prompts`
|
|
291
|
+
|
|
292
|
+
**Fix:** Run `prompts setup` or add the path alias to `tsconfig.json`. See [setup.md](setup.md).
|
|
293
|
+
|
|
294
|
+
#### Variable reference not supported in partial
|
|
295
|
+
|
|
296
|
+
**Fix:** Only literal string params are allowed in `{% render %}` tags. Replace variable references with string literals.
|
|
297
|
+
|
|
298
|
+
#### Partial not found
|
|
299
|
+
|
|
300
|
+
**Fix:** Verify the file is in `.prompts/partials/` (custom) or `src/prompts/` (built-in) with `.prompt` extension.
|
|
301
|
+
|
|
302
|
+
## References
|
|
303
|
+
|
|
304
|
+
- [Code Generation & Library](codegen.md)
|
|
305
|
+
- [CLI](cli.md)
|
|
306
|
+
- [Setup](setup.md)
|
|
@@ -26,13 +26,13 @@ prompts create my-agent --out src/agents/my-agent
|
|
|
26
26
|
5. Lint:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
prompts lint --
|
|
29
|
+
prompts lint --includes "src/agents/**"
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
6. Generate:
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
prompts generate --out .prompts/client --
|
|
35
|
+
prompts generate --out .prompts/client --includes "src/agents/**"
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
7. Import and use:
|
|
@@ -50,7 +50,7 @@ Or configure manually (steps 3-6).
|
|
|
50
50
|
```json
|
|
51
51
|
{
|
|
52
52
|
"scripts": {
|
|
53
|
-
"prompts:generate": "prompts generate --out .prompts/client --
|
|
53
|
+
"prompts:generate": "prompts generate --out .prompts/client --includes \"prompts/**\" \"src/agents/**\""
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
```
|
package/docs/overview.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Prompts SDK
|
|
1
|
+
# Prompts SDK
|
|
2
2
|
|
|
3
3
|
Prompt authoring SDK with two surfaces: a **CLI** for build-time code generation from `.prompt` files, and a **library** for runtime template rendering with full type safety.
|
|
4
4
|
|
|
@@ -51,28 +51,6 @@ flowchart LR
|
|
|
51
51
|
classDef gateway fill:#313244,stroke:#fab387,stroke-width:2px,color:#cdd6f4
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
## Package Structure
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
📁 packages/prompts/
|
|
58
|
-
├── 📁 src/
|
|
59
|
-
│ ├── 📁 prompts/ # Built-in partials (identity, constraints, tools)
|
|
60
|
-
│ ├── 📄 engine.ts # LiquidJS engine factory
|
|
61
|
-
│ ├── 📄 registry.ts # Typed prompt registry
|
|
62
|
-
│ ├── 📄 clean.ts # Frontmatter stripping pipeline
|
|
63
|
-
│ ├── 📄 partials-dir.ts # PARTIALS_DIR export for CLI/consumers
|
|
64
|
-
│ ├── 📄 types.ts # PromptModule, PromptNamespace, PromptRegistry types
|
|
65
|
-
│ └── 📄 index.ts # Public exports
|
|
66
|
-
└── 📁 docs/
|
|
67
|
-
|
|
68
|
-
📁 packages/cli/ # @funkai/cli — CLI binary (see @funkai/cli README)
|
|
69
|
-
├── 📁 commands/ # generate, lint, create, setup
|
|
70
|
-
├── 📁 src/lib/ # codegen, frontmatter, flatten, lint, paths
|
|
71
|
-
└── 📄 index.ts # CLI entry point (kidd-cli)
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
> **Note:** The CLI was extracted to `@funkai/cli`. Install it separately for the `prompts` binary.
|
|
75
|
-
|
|
76
54
|
## Dual Surface
|
|
77
55
|
|
|
78
56
|
| Surface | When | What |
|
|
@@ -83,20 +61,15 @@ flowchart LR
|
|
|
83
61
|
## Quick Start
|
|
84
62
|
|
|
85
63
|
1. Create a `.prompt` file with YAML frontmatter and a LiquidJS template body.
|
|
86
|
-
2. Run `prompts generate --out .prompts/client --
|
|
64
|
+
2. Run `prompts generate --out .prompts/client --includes "src/agents/**"` to produce typed modules.
|
|
87
65
|
3. Import from the `~prompts` alias in your application code.
|
|
88
66
|
4. Call `.render({ vars })` with full type safety derived from the Zod schema in frontmatter.
|
|
89
67
|
|
|
90
|
-
##
|
|
68
|
+
## Documentation
|
|
91
69
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- [Library API](library/overview.md)
|
|
99
|
-
- [Guide: Author a Prompt](guides/author-prompt.md)
|
|
100
|
-
- [Guide: Setup Project](guides/setup-project.md)
|
|
101
|
-
- [Guide: Add a Partial](guides/add-partial.md)
|
|
102
|
-
- [Troubleshooting](troubleshooting.md)
|
|
70
|
+
| Topic | Description |
|
|
71
|
+
| --------------------------------------- | ------------------------------------------------------------------------- |
|
|
72
|
+
| [File Format](file-format.md) | .prompt anatomy, frontmatter, schema variables, partials, authoring guide |
|
|
73
|
+
| [Code Generation & Library](codegen.md) | Build pipeline, generated output, runtime API, consumer patterns |
|
|
74
|
+
| [Project Setup](setup.md) | VSCode, .gitignore, tsconfig, package.json configuration |
|
|
75
|
+
| [Troubleshooting](troubleshooting.md) | Common errors and fixes |
|
package/docs/setup.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Setup Prompt Development
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- Node 24
|
|
6
|
+
- pnpm workspace
|
|
7
|
+
|
|
8
|
+
## Steps
|
|
9
|
+
|
|
10
|
+
1. Install:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm add @funkai/prompts --workspace
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. Run interactive setup:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
prompts setup
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or configure manually (steps 3-6).
|
|
23
|
+
|
|
24
|
+
3. Add VSCode file association in `.vscode/settings.json`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"files.associations": {
|
|
29
|
+
"*.prompt": "markdown"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
4. Add `.prompts/client/` to `.gitignore`.
|
|
35
|
+
|
|
36
|
+
5. Add `~prompts` path alias to `tsconfig.json`:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"compilerOptions": {
|
|
41
|
+
"paths": {
|
|
42
|
+
"~prompts": ["./.prompts/client/index.ts"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
6. Add generate script to `package.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"scripts": {
|
|
53
|
+
"prompts:generate": "prompts generate --out .prompts/client --includes \"prompts/**\" \"src/agents/**\""
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Verification
|
|
59
|
+
|
|
60
|
+
Run `prompts generate` and verify `.prompts/client/` directory is created with an `index.ts`.
|
|
61
|
+
|
|
62
|
+
## Troubleshooting
|
|
63
|
+
|
|
64
|
+
### VSCode not highlighting `.prompt` files
|
|
65
|
+
|
|
66
|
+
**Fix:** Check `.vscode/settings.json` file association is set correctly.
|
|
67
|
+
|
|
68
|
+
### TypeScript can't resolve `~prompts`
|
|
69
|
+
|
|
70
|
+
**Fix:** Verify `tsconfig.json` paths alias points to `./.prompts/client/index.ts`.
|
|
71
|
+
|
|
72
|
+
## References
|
|
73
|
+
|
|
74
|
+
- [CLI](cli.md)
|
|
75
|
+
- [File Format](file-format.md)
|
|
76
|
+
- [Code Generation & Library](codegen.md)
|
package/docs/troubleshooting.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funkai/prompts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Prompt SDK with LiquidJS templating and Zod validation",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"es-toolkit": "^1.45.1",
|
|
45
|
-
"liquidjs": "^10.25.
|
|
45
|
+
"liquidjs": "^10.25.1",
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
package/src/engine.ts
CHANGED
|
@@ -21,6 +21,7 @@ export function createEngine(partialsDir: string, options?: Partial<CreateEngine
|
|
|
21
21
|
...options,
|
|
22
22
|
// Safety defaults — applied after spread so callers cannot disable them
|
|
23
23
|
strictFilters: true,
|
|
24
|
+
strictVariables: true,
|
|
24
25
|
ownPropertyOnly: true,
|
|
25
26
|
});
|
|
26
27
|
}
|
|
@@ -36,5 +37,6 @@ export function createEngine(partialsDir: string, options?: Partial<CreateEngine
|
|
|
36
37
|
*/
|
|
37
38
|
export const liquidEngine = new Liquid({
|
|
38
39
|
strictFilters: true,
|
|
40
|
+
strictVariables: true,
|
|
39
41
|
ownPropertyOnly: true,
|
|
40
42
|
});
|