Skip to content

Commit 71147ec

Browse files
FEATURE: Context input arguments now support max_size to warn and validate when context limits are excessive
1 parent fd92a82 commit 71147ec

15 files changed

Lines changed: 522 additions & 23 deletions

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ sampling:
6363
context:
6464
inputs:
6565
- user_message
66-
- app_context
66+
- name: app_context
67+
max_size: 2000
6768
includes:
6869
- ./shared/tone.md
6970
---
@@ -104,6 +105,19 @@ const response = await fetch('https://api.openai.com/v1/chat/completions', {
104105
});
105106
```
106107

108+
You can control context size warning behavior at the kit level:
109+
110+
```typescript
111+
const kit = createPromptOpsKit({
112+
sourceDir: './prompts',
113+
warnings: {
114+
contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
115+
},
116+
});
117+
```
118+
119+
Supported values for `warnings.contextSize` are `auto`, `off`, `result-only`, `console`, and `console-and-result`.
120+
107121
## Features
108122

109123
- **Prompts as Markdown** — YAML front matter for settings, H1 headings for sections (`# System instructions`, `# Prompt template`, `# Notes`)
@@ -113,6 +127,8 @@ const response = await fetch('https://api.openai.com/v1/chat/completions', {
113127
- **Overrides** — Environment and tier-based overrides (base → env → tier → runtime)
114128
- **4 provider adapters** — OpenAI, Anthropic, Gemini, OpenRouter — body-only output
115129
- **Validation** — Zod schema validation, Levenshtein-based "did you mean?" for typos, variable usage checks
130+
- **Context size guardrails** — optional per-input `max_size` metadata with non-blocking render-time warnings
131+
- **Warning controls** — top-level config can suppress or emit context size warnings differently in dev and prod
116132
- **Caching** — LRU cache with mtime-based invalidation
117133
- **CLI** — init, validate, compile, render, inspect, skill
118134
- **Compiled artifacts** — Pre-compile `.md` → JSON or ESM for production
@@ -333,6 +349,7 @@ Creates a `PromptOpsKit` instance.
333349
| `compiledDir` | `string` || Path to compiled artifacts |
334350
| `mode` | `'auto' \| 'compiled-only' \| 'source-only'` | `'auto'` | Resolution strategy |
335351
| `cache` | `boolean` | `true` | Enable LRU cache with mtime invalidation |
352+
| `warnings.contextSize` | `'auto' \| 'off' \| 'result-only' \| 'console' \| 'console-and-result'` | `'auto'` | Control whether render-time context size warnings are returned, logged, both, or suppressed |
336353

337354
### `kit.renderPrompt(options)`
338355

@@ -347,6 +364,7 @@ Renders a prompt for a specific provider. Returns `{ resolved, request, warnings
347364
| `environment` | `string` | Environment override name |
348365
| `tier` | `string` | Tier override name |
349366
| `history` | `Array<{ role, content }>` | Conversation history |
367+
| `toolRegistry` | `Record<string, unknown>` | Tool definitions for resolving string tool references |
350368
| `strict` | `boolean` | Fail on missing variables |
351369

352370
### `kit.loadPrompt(path)` / `kit.resolvePrompt(path, options)` / `kit.validatePrompt(path)`
@@ -375,7 +393,7 @@ Prompt files use YAML front matter with these fields:
375393
| `response` | `object` | `{ format, stream }` |
376394
| `tools` | `array` | Tool references (string names or inline definitions) |
377395
| `mcp` | `object` | MCP server references |
378-
| `context` | `object` | `{ inputs, history }` — declare expected variables |
396+
| `context` | `object` | `{ inputs, history }` — declare expected variables, with optional per-input `max_size` budgets |
379397
| `includes` | `string[]` | Paths to included prompt files |
380398
| `environments` | `object` | Named environment overrides |
381399
| `tiers` | `object` | Named tier overrides |

SKILL.md

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ provider: openai
2929
model: gpt-5.4
3030
context:
3131
inputs:
32-
- name
32+
- name: name
33+
max_size: 2000
3334
---
3435

3536
# System instructions
@@ -65,7 +66,7 @@ the fields required by that specific file:
6566
| `response` | object | no | `{ format: text|json|markdown, stream: boolean }` |
6667
| `tools` | array | no | Tool names (strings) or inline definitions with `{ name, description, input_schema }` |
6768
| `mcp` | object | no | `{ servers: [string | { name, config }] }` |
68-
| `context.inputs` | string[] | no | Declared variable names used in templates |
69+
| `context.inputs` | `Array<string | { name, max_size? }>` | no | Declared variable names used in templates, with optional size budgets |
6970
| `context.history` | object | no | `{ max_items: number }` |
7071
| `includes` | string[] | no | Relative paths to other prompt files to include |
7172
| `environments` | object | no | Per-environment overrides (see Overrides) |
@@ -98,10 +99,23 @@ Rules:
9899
- Declare all variables in `context.inputs` — validation warns on undeclared usage
99100
- Before finishing a new prompt file, scan the body for every `{{ variable }}` and
100101
ensure each exact variable name appears in `context.inputs`
102+
- Use object-form inputs with `max_size` when a variable is likely to grow large and should trigger early warnings
101103
- Escape literal braces with `\{{` and `\}}`
102104
- In strict mode, missing variables throw an error
103105
- In permissive mode, unresolved placeholders are left intact
104106

107+
Example with a size budget:
108+
109+
```yaml
110+
context:
111+
inputs:
112+
- user_message
113+
- name: account_summary
114+
max_size: 4096
115+
```
116+
117+
If a rendered value exceeds `max_size`, `renderPrompt()` emits a non-blocking `POK030` warning.
118+
105119
Example: this is the minimal valid shape for a prompt that references
106120
`{{ pull_request }}` even when provider/model are inherited from defaults:
107121

@@ -238,19 +252,32 @@ import { createPromptOpsKit } from 'promptopskit';
238252
const kit = createPromptOpsKit({ sourceDir: './prompts' });
239253
240254
// Load → resolve includes → apply overrides → render
241-
const request = await kit.renderPrompt('greeting', {
255+
const result = await kit.renderPrompt({
256+
path: 'greeting',
257+
provider: 'openai',
242258
variables: { name: 'Alice' },
243259
environment: 'production',
244260
});
245261
246-
// request.body is ready for the provider's API
262+
// result.request.body is ready for the provider's API
247263
const response = await fetch('https://api.openai.com/v1/chat/completions', {
248264
method: 'POST',
249265
headers: {
250266
'Content-Type': 'application/json',
251267
Authorization: `Bearer ${apiKey}`,
252268
},
253-
body: JSON.stringify(request.body),
269+
body: JSON.stringify(result.request.body),
270+
});
271+
```
272+
273+
You can control render-time context size warnings at the top level:
274+
275+
```typescript
276+
const kit = createPromptOpsKit({
277+
sourceDir: './prompts',
278+
warnings: {
279+
contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
280+
},
254281
});
255282
```
256283

@@ -307,7 +334,7 @@ const asset = parsePrompt(source);
307334
const result = validateAsset(asset);
308335

309336
if (!result.valid) {
310-
console.error(result.errors); // Error codes: POK001-POK021
337+
console.error(result.errors); // Validation error codes: POK001-POK021
311338
}
312339
```
313340

docs/api-reference.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ const kit = createPromptOpsKit({
1212
compiledDir: './dist/prompts',
1313
mode: 'auto',
1414
cache: true,
15+
warnings: {
16+
contextSize: 'auto',
17+
},
1518
});
1619
```
1720

@@ -21,6 +24,7 @@ const kit = createPromptOpsKit({
2124
| `compiledDir` | `string` || Path to compiled artifacts |
2225
| `mode` | `'auto' \| 'compiled-only' \| 'source-only'` | `'auto'` | Resolution strategy |
2326
| `cache` | `boolean` | `true` | Enable LRU cache with mtime invalidation |
27+
| `warnings.contextSize` | `'auto' \| 'off' \| 'result-only' \| 'console' \| 'console-and-result'` | `'auto'` | Control whether render-time context size warnings are returned, logged, both, or suppressed |
2428

2529
### Resolution modes
2630

@@ -69,10 +73,12 @@ Either `path` or `source` must be provided.
6973
interface RenderResult {
7074
resolved: ResolvedPromptAsset; // Fully resolved asset
7175
request: ProviderRequest; // { body, provider, model }
72-
warnings: string[]; // Non-fatal provider warnings
76+
warnings: string[]; // Non-fatal provider and render-time warnings
7377
}
7478
```
7579

80+
`warnings` may include provider adapter warnings and render-time `POK030` context size warnings when configured to be included in results.
81+
7682
## `kit.loadPrompt(path)`
7783

7884
Load a prompt asset from compiled or source (based on mode). Returns a `PromptAsset`.
@@ -101,6 +107,8 @@ const result = await kit.validatePrompt('support/reply');
101107
// { valid: boolean, errors: ValidationError[], warnings: ValidationError[] }
102108
```
103109

110+
`validatePrompt()` covers schema, include-graph, and variable declaration issues. Render-time context size warnings are produced by `renderPrompt()`, not validation.
111+
104112
## `kit.clearCache()`
105113

106114
Clear the internal LRU cache.
@@ -234,6 +242,7 @@ const result = await renderPrompt({
234242
provider: 'openai',
235243
variables: { name: 'World' },
236244
sourceDir: './prompts', // defaults to '.'
245+
warnings: { contextSize: 'result-only' },
237246
});
238247
```
239248

docs/getting-started.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ const response = await fetch('https://api.openai.com/v1/chat/completions', {
8787
});
8888
```
8989

90+
To make context size warnings loud in development and silent in production, configure the kit once:
91+
92+
```typescript
93+
const kit = createPromptOpsKit({
94+
sourceDir: './prompts',
95+
warnings: {
96+
contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
97+
},
98+
});
99+
```
100+
90101
`renderPrompt` returns `{ resolved, request, warnings }`:
91102

92103
| Field | Type | Description |

docs/prompt-format.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,21 @@ context:
160160
inputs:
161161
- name
162162
- company
163-
- app_context
163+
- name: app_context
164+
max_size: 2000
164165
```
165166
167+
Each entry can be either a string variable name or an object with:
168+
169+
- `name` — the template variable name
170+
- `max_size` — optional UTF-8 byte limit for the injected value
171+
166172
The validator warns about:
167173
- Variables used in templates but not declared in `context.inputs`
168174
- Variables declared in `context.inputs` but never used
169175

176+
At render time, PromptOpsKit also emits a non-blocking `POK030` warning when a provided variable exceeds its declared `max_size`. In source and auto modes, the warning is also written to `console.warn` to make local development issues visible early.
177+
170178
## Minimal example
171179

172180
The simplest valid prompt:
@@ -204,7 +212,8 @@ response:
204212
context:
205213
inputs:
206214
- user_message
207-
- account_summary
215+
- name: account_summary
216+
max_size: 8000
208217
history:
209218
max_items: 8
210219
tools:

docs/schema.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,29 @@ mcp:
131131
context:
132132
inputs:
133133
- user_message
134-
- account_summary
134+
- name: account_summary
135+
max_size: 4096
135136
history:
136137
max_items: 8
137138
```
138139

139140
| Field | Type | Description |
140141
|-------|------|-------------|
141-
| `inputs` | `string[]` | Expected variable names (used for validation) |
142+
| `inputs` | `Array<string | { name, max_size? }>` | Expected variable names, optionally with a UTF-8 byte budget for render-time warnings |
142143
| `history` | `object` | History settings |
143144
| `history.max_items` | `number` | Maximum history items |
144145

146+
String-form inputs remain valid:
147+
148+
```yaml
149+
context:
150+
inputs:
151+
- user_message
152+
- account_summary
153+
```
154+
155+
Object-form inputs add optional `max_size`, which is checked during `renderPrompt()` and can produce a `POK030` warning when the injected value exceeds the declared budget.
156+
145157
## `includes`
146158

147159
```yaml

docs/validation.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Validation
22

3-
PromptOpsKit validates prompts at multiple levels — schema structure, front matter keys, variable usage, and include graphs.
3+
PromptOpsKit validates prompts at multiple levels — schema structure, front matter keys, variable usage, and include graphs. Render-time context size limits are checked separately during prompt rendering.
44

55
## Quick start
66

@@ -18,6 +18,12 @@ const result = await kit.validatePrompt('support/reply');
1818
// { valid: boolean, errors: ValidationError[], warnings: ValidationError[] }
1919
```
2020

21+
`validatePrompt()` does not execute render-time context size checks. Those warnings are produced by `renderPrompt()` when variables are provided.
22+
23+
## Render-time warnings
24+
25+
`renderPrompt()` can emit `POK030` when a provided variable exceeds the `max_size` declared for a context input.
26+
2127
## Error codes
2228

2329
| Code | Severity | Description |
@@ -58,6 +64,36 @@ context:
5864
Hello {{ name }} from {{ company }}! <!-- POK011 warning: company used but not declared -->
5965
```
6066
67+
Object-form inputs can also declare size limits:
68+
69+
```yaml
70+
context:
71+
inputs:
72+
- name: account_summary
73+
max_size: 4096
74+
```
75+
76+
If `account_summary` is rendered with a value larger than 4096 UTF-8 bytes, `renderPrompt()` returns a `POK030` warning. In source and auto modes, PromptOpsKit also writes the warning to `console.warn` so oversized context is visible during local development.
77+
78+
You can override that behavior at the kit level:
79+
80+
```typescript
81+
const kit = createPromptOpsKit({
82+
sourceDir: './prompts',
83+
warnings: {
84+
contextSize: 'off',
85+
},
86+
});
87+
```
88+
89+
`warnings.contextSize` supports:
90+
91+
- `auto` — default behavior; include in `renderPrompt().warnings`, and log to console outside `compiled-only`
92+
- `off` — suppress context size warnings entirely
93+
- `result-only` — return warnings but do not log them
94+
- `console` — log warnings but do not include them in the returned `warnings` array
95+
- `console-and-result` — log and return warnings in all modes
96+
6197
## Include validation
6298

6399
`validateAssetWithIncludes` resolves the full include graph and catches:

0 commit comments

Comments
 (0)