promptopskit 0.3.0 → 0.3.3

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.
Files changed (58) hide show
  1. package/README.md +49 -0
  2. package/SKILL.md +134 -71
  3. package/dist/{chunk-VYVEVJC3.js → chunk-R5PKK6Y7.js} +28 -24
  4. package/dist/chunk-R5PKK6Y7.js.map +1 -0
  5. package/dist/chunk-S5YHGHK5.js +311 -0
  6. package/dist/chunk-S5YHGHK5.js.map +1 -0
  7. package/dist/{chunk-PU3UPUND.js → chunk-U7IDX2P7.js} +9 -6
  8. package/dist/chunk-U7IDX2P7.js.map +1 -0
  9. package/dist/{chunk-5BI5FP5L.js → chunk-UJA7XBQZ.js} +24 -20
  10. package/dist/chunk-UJA7XBQZ.js.map +1 -0
  11. package/dist/chunk-VU3WKLFI.js +87 -0
  12. package/dist/chunk-VU3WKLFI.js.map +1 -0
  13. package/dist/cli/index.js +44 -20
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/index.cjs +325 -245
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +7 -4
  18. package/dist/index.d.ts +7 -4
  19. package/dist/index.js +29 -195
  20. package/dist/index.js.map +1 -1
  21. package/dist/providers/anthropic.cjs +534 -21
  22. package/dist/providers/anthropic.cjs.map +1 -1
  23. package/dist/providers/anthropic.d.cts +2 -2
  24. package/dist/providers/anthropic.d.ts +2 -2
  25. package/dist/providers/anthropic.js +3 -2
  26. package/dist/providers/gemini.cjs +530 -17
  27. package/dist/providers/gemini.cjs.map +1 -1
  28. package/dist/providers/gemini.d.cts +2 -2
  29. package/dist/providers/gemini.d.ts +2 -2
  30. package/dist/providers/gemini.js +3 -2
  31. package/dist/providers/openai.cjs +535 -22
  32. package/dist/providers/openai.cjs.map +1 -1
  33. package/dist/providers/openai.d.cts +2 -2
  34. package/dist/providers/openai.d.ts +2 -2
  35. package/dist/providers/openai.js +3 -2
  36. package/dist/providers/openrouter.cjs +539 -26
  37. package/dist/providers/openrouter.cjs.map +1 -1
  38. package/dist/providers/openrouter.d.cts +2 -2
  39. package/dist/providers/openrouter.d.ts +2 -2
  40. package/dist/providers/openrouter.js +4 -3
  41. package/dist/testing.d.cts +1 -1
  42. package/dist/testing.d.ts +1 -1
  43. package/dist/types-CgA7_wNI.d.cts +68 -0
  44. package/dist/types-D_-336jx.d.ts +68 -0
  45. package/dist/usagetap/index.d.cts +2 -2
  46. package/dist/usagetap/index.d.ts +2 -2
  47. package/package.json +1 -1
  48. package/dist/chunk-5BI5FP5L.js.map +0 -1
  49. package/dist/chunk-6KGBPHSY.js +0 -56
  50. package/dist/chunk-6KGBPHSY.js.map +0 -1
  51. package/dist/chunk-PU3UPUND.js.map +0 -1
  52. package/dist/chunk-UYTUGV7Z.js +0 -83
  53. package/dist/chunk-UYTUGV7Z.js.map +0 -1
  54. package/dist/chunk-VYVEVJC3.js.map +0 -1
  55. package/dist/types-1zDDD-Ij.d.cts +0 -40
  56. package/dist/types-CQhlfAnR.d.ts +0 -40
  57. package/dist/{schema-DIOA4OiO.d.cts → schema-Dq0jKest.d.cts} +42 -42
  58. package/dist/{schema-DIOA4OiO.d.ts → schema-Dq0jKest.d.ts} +42 -42
package/README.md CHANGED
@@ -182,6 +182,55 @@ import { geminiAdapter } from 'promptopskit/gemini';
182
182
  import { openrouterAdapter } from 'promptopskit/openrouter';
183
183
  ```
184
184
 
185
+ Direct adapter rendering also accepts `environment` and `tier` selectors. This is useful for compiled JSON/ESM assets in browser, edge, or worker code:
186
+
187
+ ```typescript
188
+ import type { ResolvedPromptAsset } from 'promptopskit';
189
+ import { openaiAdapter } from 'promptopskit/openai';
190
+ import compiledPrompt from './dist/prompts/summarizePullRequest.mjs';
191
+
192
+ const prompt = compiledPrompt as ResolvedPromptAsset;
193
+
194
+ const validation = openaiAdapter.validate(prompt, { environment: 'dev' });
195
+ if (!validation.valid) {
196
+ throw new Error(validation.errors.join(' '));
197
+ }
198
+
199
+ const request = openaiAdapter.render(prompt, {
200
+ environment: 'dev',
201
+ variables: {
202
+ pull_request_body: 'Implement theming and dark mode across the app.',
203
+ },
204
+ strict: true,
205
+ });
206
+ ```
207
+
208
+ In browser or client-side code, keep provider credentials on the server. Use the rendered request body with your own server endpoint, server action, or edge function rather than calling a provider directly from the client.
209
+
210
+ On the server, adapters also provide async prompt-aware helpers so you can pass a prompt key plus `sourceDir` and `compiledDir` without creating a `PromptOpsKit` instance:
211
+
212
+ ```typescript
213
+ import path from 'node:path';
214
+ import { openaiAdapter } from 'promptopskit/openai';
215
+
216
+ const request = await openaiAdapter.renderPrompt(
217
+ {
218
+ path: 'summarizePullRequest',
219
+ sourceDir: path.join(process.cwd(), 'prompts'),
220
+ compiledDir: path.join(process.cwd(), 'output-json'),
221
+ },
222
+ {
223
+ environment: 'dev',
224
+ variables: {
225
+ pull_request_body: 'Implement theming and dark mode across the app.',
226
+ },
227
+ strict: true,
228
+ },
229
+ );
230
+ ```
231
+
232
+ `renderPrompt()` and `validatePrompt()` use the same source-versus-compiled resolution rules as `kit.renderPrompt()`. The existing synchronous `render()` and `validate()` methods still work for already-resolved compiled or inline assets.
233
+
185
234
  ## Optional UsageTap Tracking
186
235
 
187
236
  PromptOpsKit can also help you track provider calls with UsageTap.com while keeping the core render API body-only.
package/SKILL.md CHANGED
@@ -242,90 +242,155 @@ cases:
242
242
 
243
243
  ---
244
244
 
245
- ## Using the library (TypeScript / JavaScript)
245
+ ## Runtime choice guide
246
246
 
247
- ### Quick start
247
+ Choose the narrowest runtime surface that fits the environment.
248
+
249
+ ### Use `createPromptOpsKit().renderPrompt()` when:
250
+
251
+ - You are on the server or in a Node runtime
252
+ - Prompts live as `.md` files in a source tree
253
+ - You want promptopskit to handle loading, defaults, includes, overrides, and provider shaping in one step
254
+ - You want auto mode to prefer compiled artifacts when present but still fall back to source
248
255
 
249
256
  ```typescript
250
257
  import { createPromptOpsKit } from 'promptopskit';
251
258
 
252
- const kit = createPromptOpsKit({ sourceDir: './prompts' });
259
+ const kit = createPromptOpsKit({
260
+ sourceDir: './prompts',
261
+ compiledDir: './dist/prompts',
262
+ warnings: {
263
+ contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
264
+ },
265
+ });
253
266
 
254
- // Load resolve includes apply overrides → render
255
- const result = await kit.renderPrompt({
256
- path: 'greeting',
267
+ const { request } = await kit.renderPrompt({
268
+ path: 'support/reply',
257
269
  provider: 'openai',
258
- variables: { name: 'Alice' },
259
270
  environment: 'production',
260
- });
261
-
262
- // result.request.body is ready for the provider's API
263
- const response = await fetch('https://api.openai.com/v1/chat/completions', {
264
- method: 'POST',
265
- headers: {
266
- 'Content-Type': 'application/json',
267
- Authorization: `Bearer ${apiKey}`,
271
+ variables: {
272
+ user_message: 'How do I reset my password?',
273
+ app_context: 'Account settings',
268
274
  },
269
- body: JSON.stringify(result.request.body),
270
275
  });
271
276
  ```
272
277
 
273
- You can control render-time context size warnings at the top level:
278
+ ### Use `adapter.renderPrompt()` when:
279
+
280
+ - You want direct provider adapter imports such as `promptopskit/openai`
281
+ - You are on the server and want adapter-level ergonomics
282
+ - You still want the adapter to resolve either source `.md` or compiled output from disk
274
283
 
275
284
  ```typescript
276
- const kit = createPromptOpsKit({
277
- sourceDir: './prompts',
278
- warnings: {
279
- contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
285
+ import path from 'node:path';
286
+ import { openaiAdapter } from 'promptopskit/openai';
287
+
288
+ const request = await openaiAdapter.renderPrompt(
289
+ {
290
+ path: 'support/reply',
291
+ sourceDir: path.join(process.cwd(), 'prompts'),
292
+ compiledDir: path.join(process.cwd(), 'dist/prompts'),
280
293
  },
281
- });
294
+ {
295
+ environment: 'production',
296
+ variables: {
297
+ user_message: 'How do I reset my password?',
298
+ app_context: 'Account settings',
299
+ },
300
+ strict: true,
301
+ },
302
+ );
282
303
  ```
283
304
 
284
- ### Step-by-step API
305
+ ### Use `adapter.render()` when:
306
+
307
+ - You already have a compiled JSON or ESM prompt artifact
308
+ - You are in edge, worker, or browser-oriented code and cannot read prompt files from disk
309
+ - You want the smallest runtime surface and no file loading behavior
285
310
 
286
311
  ```typescript
287
- import {
288
- parsePrompt,
289
- resolveIncludes,
290
- applyOverrides,
291
- getAdapter,
292
- } from 'promptopskit';
293
- import { readFileSync } from 'fs';
294
-
295
- // 1. Parse a prompt file
296
- const source = readFileSync('./prompts/greeting.md', 'utf-8');
297
- const asset = parsePrompt(source, 'greeting.md');
298
-
299
- // 2. Resolve includes
300
- const resolved = await resolveIncludes(asset, './prompts');
301
-
302
- // 3. Apply overrides
303
- const configured = applyOverrides(resolved, {
312
+ import type { ResolvedPromptAsset } from 'promptopskit';
313
+ import { openaiAdapter } from 'promptopskit/openai';
314
+ import compiledPrompt from './dist/prompts/support/reply.mjs';
315
+
316
+ const prompt = compiledPrompt as ResolvedPromptAsset;
317
+
318
+ const request = openaiAdapter.render(prompt, {
304
319
  environment: 'production',
305
- tier: 'premium',
320
+ variables: {
321
+ user_message: 'How do I reset my password?',
322
+ app_context: 'Account settings',
323
+ },
324
+ strict: true,
306
325
  });
326
+ ```
327
+
328
+ ### Browser guidance
329
+
330
+ - Do not recommend direct provider API calls from browser or client components unless the user explicitly wants a demo-only setup
331
+ - Do not use `createPromptOpsKit()` in browser-only code; it is Node-oriented
332
+ - For client-side rendering, use precompiled ESM or inline a small `ResolvedPromptAsset`, then pass the request body to a server endpoint or server action that holds provider credentials
333
+ - If the user insists on a pure browser provider call, explicitly call out that API keys will be exposed and treat it as unsafe for production
307
334
 
308
- // 4. Get provider adapter and render
309
- const adapter = getAdapter(configured.provider ?? 'openai');
310
- const request = adapter.render(configured, {
311
- variables: { name: 'Alice' },
312
- history: [
313
- { role: 'user', content: 'Previous message' },
314
- { role: 'assistant', content: 'Previous response' },
315
- ],
335
+ ---
336
+
337
+ ## Build integration
338
+
339
+ Prompts should usually be validated and compiled as part of the normal build pipeline rather than handled ad hoc.
340
+
341
+ ### Recommended package.json scripts
342
+
343
+ ```json
344
+ {
345
+ "scripts": {
346
+ "validate:prompts": "promptopskit validate ./prompts --strict",
347
+ "build:prompts": "promptopskit compile ./prompts ./dist/prompts --format json",
348
+ "build": "npm run validate:prompts && npm run build:prompts && tsup"
349
+ }
350
+ }
351
+ ```
352
+
353
+ Use `--format json` for server-side Node usage where prompts are loaded from disk. Use `--format esm` when prompts need to be imported into a bundle.
354
+
355
+ ### Build strategy by environment
356
+
357
+ - Node server: compile to JSON and configure `compiledDir`
358
+ - Browser or client bundle: compile to ESM and import specific prompt artifacts
359
+ - Mixed app: compile JSON for server loading and ESM only for prompts that must ship in a client bundle
360
+
361
+ ### What to tell users when setting this up
362
+
363
+ - Add `validate:prompts` before `build:prompts` so schema or variable mistakes fail fast
364
+ - Treat compiled artifacts as build outputs, not the source of truth
365
+ - Keep prompt source in `./prompts` and compiled output in a generated directory such as `./dist/prompts` or `./src/generated/prompts`
366
+ - If using `createPromptOpsKit` in `auto` mode, point both `sourceDir` and `compiledDir` at those directories so local development can fall back to source when artifacts are stale or missing
367
+
368
+ ### Typical server-side setup
369
+
370
+ ```typescript
371
+ import { createPromptOpsKit } from 'promptopskit';
372
+
373
+ export const prompts = createPromptOpsKit({
374
+ sourceDir: './prompts',
375
+ compiledDir: './dist/prompts',
376
+ mode: 'auto',
316
377
  });
317
378
  ```
318
379
 
319
- ### Available provider adapters
380
+ ### Typical client-side setup
381
+
382
+ ```typescript
383
+ import type { ResolvedPromptAsset } from 'promptopskit';
384
+ import compiledPrompt from './generated/prompts/support/reply.mjs';
385
+
386
+ const prompt = compiledPrompt as ResolvedPromptAsset;
387
+ ```
388
+
389
+ ---
320
390
 
321
- | Provider | Import path | Provider request format |
322
- |----------|------------|----------------------|
323
- | OpenAI | `promptopskit` or `promptopskit/openai` | Chat Completions API |
324
- | Anthropic | `promptopskit/anthropic` | Messages API |
325
- | Gemini | `promptopskit/gemini` | GenerateContent API |
326
- | OpenRouter | `promptopskit/openrouter` | OpenAI-compatible + extras |
391
+ ## Validation and testing helpers
327
392
 
328
- ### Validation
393
+ Use `validateAsset()` when you are working with an already-parsed asset and want schema or variable diagnostics before rendering.
329
394
 
330
395
  ```typescript
331
396
  import { validateAsset, parsePrompt } from 'promptopskit';
@@ -334,19 +399,17 @@ const asset = parsePrompt(source);
334
399
  const result = validateAsset(asset);
335
400
 
336
401
  if (!result.valid) {
337
- console.error(result.errors); // Validation error codes: POK001-POK021
402
+ console.error(result.errors);
338
403
  }
339
404
  ```
340
405
 
341
- ### Testing helpers
406
+ Use `promptopskit/testing` helpers for unit tests around prompt behavior or request shaping.
342
407
 
343
408
  ```typescript
344
409
  import { createMockAsset, parseTestPrompt } from 'promptopskit/testing';
345
410
 
346
- // Create a mock asset for unit tests
347
411
  const mock = createMockAsset({ model: 'gpt-4.1-mini' });
348
412
 
349
- // Parse an inline prompt string for tests
350
413
  const asset = parseTestPrompt(`
351
414
  ---
352
415
  id: test
@@ -369,8 +432,8 @@ Hello {{ name }}
369
432
  |---------|-------------|
370
433
  | `promptopskit init [dir]` | Scaffold a prompts directory with starter files (including `defaults.md`) |
371
434
  | `promptopskit validate <dir>` | Validate all prompt files in a directory |
372
- | `promptopskit compile <src> <out>` | Compile .md prompts to JSON artifacts |
373
- | `promptopskit render <file> [--set key=value]` | Render a prompt preview |
435
+ | `promptopskit compile <src> <out>` | Compile `.md` prompts to JSON or ESM artifacts |
436
+ | `promptopskit render <file>` | Render a prompt preview |
374
437
  | `promptopskit inspect <file>` | Print the normalized prompt asset |
375
438
 
376
439
  ---
@@ -378,13 +441,13 @@ Hello {{ name }}
378
441
  ## Conventions to follow
379
442
 
380
443
  1. **One prompt per file** — each `.md` file is a single prompt asset
381
- 2. **Always set `id` and `schema_version: 1`** in front matter (or inherit `schema_version` from `defaults.md`)
382
- 3. **Declare all variables** in `context.inputs` that appear in templates; do not leave placeholders undeclared just because other settings come from `defaults.md`
383
- 4. **Use includes** for shared system instructions (tone, safety, formatting)
384
- 5. **Keep prompt templates focused** compose behavior via includes, not duplication
385
- 6. **Use environment overrides** for dev/staging/prod model differences
386
- 7. **Add test sidecars** (`.test.yaml`) for critical prompts
387
- 8. **Run `promptopskit validate`** before committing changes
388
- 9. **Use `defaults.md`** to share provider, model, metadata, and system instructions across a folder
444
+ 2. **Always set `id` and `schema_version: 1`** unless a surrounding tool explicitly generates those fields
445
+ 3. **Declare every placeholder** in `context.inputs`; do not rely on defaults or includes to infer variables
446
+ 4. **Use `defaults.md` for shared provider, model, metadata, and fallback system instructions**
447
+ 5. **Use includes for reusable system behavior**, not for user-specific prompt bodies
448
+ 6. **Prefer `createPromptOpsKit().renderPrompt()` for server-side app code** when prompts live as source files
449
+ 7. **Prefer direct adapters for compiled assets or provider-specific integration points**
450
+ 8. **Do not suggest browser-side provider calls for production** because credentials belong on the server
451
+ 9. **Validate before compile and compile before shipping** when prompts are part of the build
389
452
  10. **Variable names** should be `snake_case`
390
453
  11. **Prompt file names** should be `kebab-case.md`
@@ -1,29 +1,33 @@
1
1
  import {
2
- renderSections
3
- } from "./chunk-6KGBPHSY.js";
2
+ renderSections,
3
+ resolveAssetForProvider,
4
+ withPromptInputSupport
5
+ } from "./chunk-S5YHGHK5.js";
4
6
 
5
7
  // src/providers/anthropic.ts
6
- var anthropicAdapter = {
8
+ var anthropicAdapter = withPromptInputSupport({
7
9
  name: "anthropic",
8
- validate(asset) {
10
+ validate(asset, runtime) {
11
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
9
12
  const errors = [];
10
13
  const warnings = [];
11
- if (!asset.model) {
14
+ if (!resolvedAsset.model) {
12
15
  errors.push("Anthropic adapter requires a model to be specified.");
13
16
  }
14
- if (asset.sampling?.frequency_penalty !== void 0) {
17
+ if (resolvedAsset.sampling?.frequency_penalty !== void 0) {
15
18
  warnings.push("Anthropic does not support frequency_penalty. It will be ignored.");
16
19
  }
17
- if (asset.sampling?.presence_penalty !== void 0) {
20
+ if (resolvedAsset.sampling?.presence_penalty !== void 0) {
18
21
  warnings.push("Anthropic does not support presence_penalty. It will be ignored.");
19
22
  }
20
- if (asset.reasoning?.effort !== void 0) {
23
+ if (resolvedAsset.reasoning?.effort !== void 0) {
21
24
  warnings.push("Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.");
22
25
  }
23
26
  return { valid: errors.length === 0, errors, warnings };
24
27
  },
25
28
  render(asset, runtime) {
26
- const sections = renderSections(asset, {
29
+ const resolvedAsset = resolveAssetForProvider(asset, runtime);
30
+ const sections = renderSections(resolvedAsset, {
27
31
  variables: runtime.variables,
28
32
  strict: runtime.strict
29
33
  });
@@ -37,31 +41,31 @@ var anthropicAdapter = {
37
41
  messages.push({ role: "user", content: sections.prompt_template });
38
42
  }
39
43
  const body = {
40
- model: asset.model,
44
+ model: resolvedAsset.model,
41
45
  messages
42
46
  };
43
47
  if (sections.system_instructions) {
44
48
  body.system = sections.system_instructions;
45
49
  }
46
- if (asset.sampling?.temperature !== void 0) body.temperature = asset.sampling.temperature;
47
- if (asset.sampling?.top_p !== void 0) body.top_p = asset.sampling.top_p;
48
- if (asset.sampling?.stop !== void 0) body.stop_sequences = asset.sampling.stop;
49
- if (asset.sampling?.max_output_tokens !== void 0) {
50
- body.max_tokens = asset.sampling.max_output_tokens;
50
+ if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
51
+ if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
52
+ if (resolvedAsset.sampling?.stop !== void 0) body.stop_sequences = resolvedAsset.sampling.stop;
53
+ if (resolvedAsset.sampling?.max_output_tokens !== void 0) {
54
+ body.max_tokens = resolvedAsset.sampling.max_output_tokens;
51
55
  } else {
52
56
  body.max_tokens = 4096;
53
57
  }
54
- if (asset.reasoning?.budget_tokens) {
58
+ if (resolvedAsset.reasoning?.budget_tokens) {
55
59
  body.thinking = {
56
60
  type: "enabled",
57
- budget_tokens: asset.reasoning.budget_tokens
61
+ budget_tokens: resolvedAsset.reasoning.budget_tokens
58
62
  };
59
63
  }
60
- if (asset.response?.stream !== void 0) {
61
- body.stream = asset.response.stream;
64
+ if (resolvedAsset.response?.stream !== void 0) {
65
+ body.stream = resolvedAsset.response.stream;
62
66
  }
63
- if (asset.tools && asset.tools.length > 0) {
64
- body.tools = asset.tools.map((tool) => {
67
+ if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
68
+ body.tools = resolvedAsset.tools.map((tool) => {
65
69
  if (typeof tool === "string") {
66
70
  const def = runtime.toolRegistry?.[tool];
67
71
  if (def) return def;
@@ -77,12 +81,12 @@ var anthropicAdapter = {
77
81
  return {
78
82
  body,
79
83
  provider: "anthropic",
80
- model: asset.model ?? "unknown"
84
+ model: resolvedAsset.model ?? "unknown"
81
85
  };
82
86
  }
83
- };
87
+ });
84
88
 
85
89
  export {
86
90
  anthropicAdapter
87
91
  };
88
- //# sourceMappingURL=chunk-VYVEVJC3.js.map
92
+ //# sourceMappingURL=chunk-R5PKK6Y7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/anthropic.ts"],"sourcesContent":["import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\nimport { resolveAssetForProvider } from './resolve-asset.js';\nimport { withPromptInputSupport } from './prompt-input.js';\n\n/**\n * Anthropic provider adapter.\n * Produces request bodies compatible with the Anthropic Messages API.\n */\nexport const anthropicAdapter: ProviderAdapter = withPromptInputSupport({\n name: 'anthropic',\n\n validate(asset: ResolvedPromptAsset, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!resolvedAsset.model) {\n errors.push('Anthropic adapter requires a model to be specified.');\n }\n\n if (resolvedAsset.sampling?.frequency_penalty !== undefined) {\n warnings.push('Anthropic does not support frequency_penalty. It will be ignored.');\n }\n if (resolvedAsset.sampling?.presence_penalty !== undefined) {\n warnings.push('Anthropic does not support presence_penalty. It will be ignored.');\n }\n if (resolvedAsset.reasoning?.effort !== undefined) {\n warnings.push('Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const sections = renderSections(resolvedAsset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n\n const messages: Array<Record<string, unknown>> = [];\n\n // History\n if (runtime.history) {\n for (const msg of runtime.history) {\n messages.push({ role: msg.role, content: msg.content });\n }\n }\n\n // User message (prompt template)\n if (sections.prompt_template) {\n messages.push({ role: 'user', content: sections.prompt_template });\n }\n\n const body: Record<string, unknown> = {\n model: resolvedAsset.model,\n messages,\n };\n\n // System goes as top-level field in Anthropic\n if (sections.system_instructions) {\n body.system = sections.system_instructions;\n }\n\n // Sampling params\n if (resolvedAsset.sampling?.temperature !== undefined) body.temperature = resolvedAsset.sampling.temperature;\n if (resolvedAsset.sampling?.top_p !== undefined) body.top_p = resolvedAsset.sampling.top_p;\n if (resolvedAsset.sampling?.stop !== undefined) body.stop_sequences = resolvedAsset.sampling.stop;\n if (resolvedAsset.sampling?.max_output_tokens !== undefined) {\n body.max_tokens = resolvedAsset.sampling.max_output_tokens;\n } else {\n // Anthropic requires max_tokens\n body.max_tokens = 4096;\n }\n\n // Thinking/reasoning\n if (resolvedAsset.reasoning?.budget_tokens) {\n body.thinking = {\n type: 'enabled',\n budget_tokens: resolvedAsset.reasoning.budget_tokens,\n };\n }\n\n // Streaming\n if (resolvedAsset.response?.stream !== undefined) {\n body.stream = resolvedAsset.response.stream;\n }\n\n // Tools\n if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {\n body.tools = resolvedAsset.tools.map((tool) => {\n if (typeof tool === 'string') {\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { name: tool };\n }\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.input_schema ?? { type: 'object', properties: {} },\n };\n });\n }\n\n return {\n body,\n provider: 'anthropic',\n model: resolvedAsset.model ?? 'unknown',\n };\n },\n});\n"],"mappings":";;;;;;;AAeO,IAAM,mBAAoC,uBAAuB;AAAA,EACtE,MAAM;AAAA,EAEN,SAAS,OAA4B,SAAkD;AACrF,UAAM,gBAAgB,wBAAwB,OAAO,OAAO;AAC5D,UAAM,SAAmB,CAAC;AAC1B,UAAM,WAAqB,CAAC;AAE5B,QAAI,CAAC,cAAc,OAAO;AACxB,aAAO,KAAK,qDAAqD;AAAA,IACnE;AAEA,QAAI,cAAc,UAAU,sBAAsB,QAAW;AAC3D,eAAS,KAAK,mEAAmE;AAAA,IACnF;AACA,QAAI,cAAc,UAAU,qBAAqB,QAAW;AAC1D,eAAS,KAAK,kEAAkE;AAAA,IAClF;AACA,QAAI,cAAc,WAAW,WAAW,QAAW;AACjD,eAAS,KAAK,6FAA6F;AAAA,IAC7G;AAEA,WAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AAAA,EACxD;AAAA,EAEA,OAAO,OAA4B,SAAgD;AACjF,UAAM,gBAAgB,wBAAwB,OAAO,OAAO;AAC5D,UAAM,WAAW,eAAe,eAAe;AAAA,MAC7C,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,UAAM,WAA2C,CAAC;AAGlD,QAAI,QAAQ,SAAS;AACnB,iBAAW,OAAO,QAAQ,SAAS;AACjC,iBAAS,KAAK,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,QAAI,SAAS,iBAAiB;AAC5B,eAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,gBAAgB,CAAC;AAAA,IACnE;AAEA,UAAM,OAAgC;AAAA,MACpC,OAAO,cAAc;AAAA,MACrB;AAAA,IACF;AAGA,QAAI,SAAS,qBAAqB;AAChC,WAAK,SAAS,SAAS;AAAA,IACzB;AAGA,QAAI,cAAc,UAAU,gBAAgB,OAAW,MAAK,cAAc,cAAc,SAAS;AACjG,QAAI,cAAc,UAAU,UAAU,OAAW,MAAK,QAAQ,cAAc,SAAS;AACrF,QAAI,cAAc,UAAU,SAAS,OAAW,MAAK,iBAAiB,cAAc,SAAS;AAC7F,QAAI,cAAc,UAAU,sBAAsB,QAAW;AAC3D,WAAK,aAAa,cAAc,SAAS;AAAA,IAC3C,OAAO;AAEL,WAAK,aAAa;AAAA,IACpB;AAGA,QAAI,cAAc,WAAW,eAAe;AAC1C,WAAK,WAAW;AAAA,QACd,MAAM;AAAA,QACN,eAAe,cAAc,UAAU;AAAA,MACzC;AAAA,IACF;AAGA,QAAI,cAAc,UAAU,WAAW,QAAW;AAChD,WAAK,SAAS,cAAc,SAAS;AAAA,IACvC;AAGA,QAAI,cAAc,SAAS,cAAc,MAAM,SAAS,GAAG;AACzD,WAAK,QAAQ,cAAc,MAAM,IAAI,CAAC,SAAS;AAC7C,YAAI,OAAO,SAAS,UAAU;AAC5B,gBAAM,MAAM,QAAQ,eAAe,IAAI;AACvC,cAAI,IAAK,QAAO;AAChB,iBAAO,EAAE,MAAM,KAAK;AAAA,QACtB;AACA,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,aAAa,KAAK;AAAA,UAClB,cAAc,KAAK,gBAAgB,EAAE,MAAM,UAAU,YAAY,CAAC,EAAE;AAAA,QACtE;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,OAAO,cAAc,SAAS;AAAA,IAChC;AAAA,EACF;AACF,CAAC;","names":[]}