promptopskit 0.3.4 → 0.3.5
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/README.md +6 -8
- package/dist/{chunk-VU3WKLFI.js → chunk-2X5HFPSD.js} +2 -2
- package/dist/{chunk-R5PKK6Y7.js → chunk-4QW4BSGE.js} +2 -2
- package/dist/{chunk-UJA7XBQZ.js → chunk-7RWTFGMS.js} +2 -2
- package/dist/{chunk-S5YHGHK5.js → chunk-M5VKRDIY.js} +27 -14
- package/dist/chunk-M5VKRDIY.js.map +1 -0
- package/dist/{chunk-U7IDX2P7.js → chunk-ROBYCHAW.js} +3 -3
- package/dist/cli/index.js +113 -54
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +30 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +14 -11
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +24 -13
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/gemini.cjs +24 -13
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.d.cts +1 -1
- package/dist/providers/gemini.d.ts +1 -1
- package/dist/providers/gemini.js +2 -2
- package/dist/providers/openai.cjs +24 -13
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.cjs +24 -13
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.d.cts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +3 -3
- package/dist/{types-CgA7_wNI.d.cts → types-ClXTFaX-.d.cts} +1 -1
- package/dist/{types-D_-336jx.d.ts → types-lLD7m02V.d.ts} +1 -1
- package/dist/usagetap/index.d.cts +1 -1
- package/dist/usagetap/index.d.ts +1 -1
- package/package.json +4 -1
- package/dist/chunk-S5YHGHK5.js.map +0 -1
- /package/dist/{chunk-VU3WKLFI.js.map → chunk-2X5HFPSD.js.map} +0 -0
- /package/dist/{chunk-R5PKK6Y7.js.map → chunk-4QW4BSGE.js.map} +0 -0
- /package/dist/{chunk-UJA7XBQZ.js.map → chunk-7RWTFGMS.js.map} +0 -0
- /package/dist/{chunk-U7IDX2P7.js.map → chunk-ROBYCHAW.js.map} +0 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ npm install promptopskit
|
|
|
34
34
|
### 1. Scaffold starter prompts
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
npx promptopskit init
|
|
37
|
+
npx promptopskit init
|
|
38
38
|
npx promptopskit skill
|
|
39
39
|
```
|
|
40
40
|
|
|
@@ -84,7 +84,7 @@ You are a helpful support assistant working in {{ app_context }}.
|
|
|
84
84
|
```typescript
|
|
85
85
|
import { createPromptOpsKit } from 'promptopskit';
|
|
86
86
|
|
|
87
|
-
const kit = createPromptOpsKit(
|
|
87
|
+
const kit = createPromptOpsKit();
|
|
88
88
|
|
|
89
89
|
const result = await kit.renderPrompt({
|
|
90
90
|
path: 'support/reply',
|
|
@@ -110,7 +110,6 @@ You can control context size warning behavior at the kit level:
|
|
|
110
110
|
|
|
111
111
|
```typescript
|
|
112
112
|
const kit = createPromptOpsKit({
|
|
113
|
-
sourceDir: './prompts',
|
|
114
113
|
warnings: {
|
|
115
114
|
contextSize: process.env.NODE_ENV === 'production' ? 'off' : 'console-and-result',
|
|
116
115
|
},
|
|
@@ -141,7 +140,7 @@ Each adapter produces a `{ body, provider, model }` object shaped for the target
|
|
|
141
140
|
```typescript
|
|
142
141
|
// OpenAI
|
|
143
142
|
import { createPromptOpsKit } from 'promptopskit';
|
|
144
|
-
const kit = createPromptOpsKit(
|
|
143
|
+
const kit = createPromptOpsKit();
|
|
145
144
|
const { request } = await kit.renderPrompt({
|
|
146
145
|
path: 'hello',
|
|
147
146
|
provider: 'openai',
|
|
@@ -207,17 +206,14 @@ const request = openaiAdapter.render(prompt, {
|
|
|
207
206
|
|
|
208
207
|
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
208
|
|
|
210
|
-
On the server, adapters also provide async prompt-aware helpers so you can
|
|
209
|
+
On the server, adapters also provide async prompt-aware helpers so you can use the default `./prompts` and `./.generated-prompts/json` directories without creating a `PromptOpsKit` instance:
|
|
211
210
|
|
|
212
211
|
```typescript
|
|
213
|
-
import path from 'node:path';
|
|
214
212
|
import { openaiAdapter } from 'promptopskit/openai';
|
|
215
213
|
|
|
216
214
|
const request = await openaiAdapter.renderPrompt(
|
|
217
215
|
{
|
|
218
216
|
path: 'summarizePullRequest',
|
|
219
|
-
sourceDir: path.join(process.cwd(), 'prompts'),
|
|
220
|
-
compiledDir: path.join(process.cwd(), '.generated-prompts', 'json'),
|
|
221
217
|
},
|
|
222
218
|
{
|
|
223
219
|
environment: 'dev',
|
|
@@ -229,6 +225,8 @@ const request = await openaiAdapter.renderPrompt(
|
|
|
229
225
|
);
|
|
230
226
|
```
|
|
231
227
|
|
|
228
|
+
If you need a different layout, keep passing `sourceDir` and `compiledDir` explicitly.
|
|
229
|
+
|
|
232
230
|
`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
231
|
|
|
234
232
|
## Optional UsageTap Tracking
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
renderSections,
|
|
3
3
|
resolveAssetForProvider,
|
|
4
4
|
withPromptInputSupport
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M5VKRDIY.js";
|
|
6
6
|
|
|
7
7
|
// src/providers/openai.ts
|
|
8
8
|
var openaiAdapter = withPromptInputSupport({
|
|
@@ -84,4 +84,4 @@ var openaiAdapter = withPromptInputSupport({
|
|
|
84
84
|
export {
|
|
85
85
|
openaiAdapter
|
|
86
86
|
};
|
|
87
|
-
//# sourceMappingURL=chunk-
|
|
87
|
+
//# sourceMappingURL=chunk-2X5HFPSD.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
renderSections,
|
|
3
3
|
resolveAssetForProvider,
|
|
4
4
|
withPromptInputSupport
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M5VKRDIY.js";
|
|
6
6
|
|
|
7
7
|
// src/providers/anthropic.ts
|
|
8
8
|
var anthropicAdapter = withPromptInputSupport({
|
|
@@ -89,4 +89,4 @@ var anthropicAdapter = withPromptInputSupport({
|
|
|
89
89
|
export {
|
|
90
90
|
anthropicAdapter
|
|
91
91
|
};
|
|
92
|
-
//# sourceMappingURL=chunk-
|
|
92
|
+
//# sourceMappingURL=chunk-4QW4BSGE.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
renderSections,
|
|
3
3
|
resolveAssetForProvider,
|
|
4
4
|
withPromptInputSupport
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-M5VKRDIY.js";
|
|
6
6
|
|
|
7
7
|
// src/providers/gemini.ts
|
|
8
8
|
var geminiAdapter = withPromptInputSupport({
|
|
@@ -93,4 +93,4 @@ var geminiAdapter = withPromptInputSupport({
|
|
|
93
93
|
export {
|
|
94
94
|
geminiAdapter
|
|
95
95
|
};
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
96
|
+
//# sourceMappingURL=chunk-7RWTFGMS.js.map
|
|
@@ -185,14 +185,24 @@ async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Se
|
|
|
185
185
|
import { readFile as readFile2 } from "fs/promises";
|
|
186
186
|
import { existsSync, statSync as statSync2 } from "fs";
|
|
187
187
|
import { resolve as resolve2 } from "path";
|
|
188
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
189
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
190
|
+
function withPromptResolutionDefaults(config) {
|
|
191
|
+
return {
|
|
192
|
+
...config,
|
|
193
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
194
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
195
|
+
};
|
|
196
|
+
}
|
|
188
197
|
var sharedPromptCache = new PromptCache();
|
|
189
198
|
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
199
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
200
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
201
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
202
|
+
const compiledFile = resolve2(resolvedConfig.compiledDir, promptPath + ".json");
|
|
193
203
|
if (existsSync(compiledFile)) {
|
|
194
204
|
if (mode === "auto") {
|
|
195
|
-
const sourceFile = resolve2(
|
|
205
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
196
206
|
if (existsSync(sourceFile)) {
|
|
197
207
|
const compiledMtime = statSync2(compiledFile).mtimeMs;
|
|
198
208
|
const sourceMtime = statSync2(sourceFile).mtimeMs;
|
|
@@ -215,8 +225,8 @@ Run "promptopskit compile" to generate it.`
|
|
|
215
225
|
}
|
|
216
226
|
}
|
|
217
227
|
if (mode !== "compiled-only") {
|
|
218
|
-
const sourceFile = resolve2(
|
|
219
|
-
if (
|
|
228
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
229
|
+
if (resolvedConfig.cache !== false) {
|
|
220
230
|
const cached = promptCache.get(sourceFile);
|
|
221
231
|
if (cached) {
|
|
222
232
|
return cached;
|
|
@@ -224,8 +234,8 @@ Run "promptopskit compile" to generate it.`
|
|
|
224
234
|
}
|
|
225
235
|
if (!existsSync(sourceFile)) {
|
|
226
236
|
const paths = [sourceFile];
|
|
227
|
-
if (
|
|
228
|
-
paths.unshift(resolve2(
|
|
237
|
+
if (resolvedConfig.compiledDir) {
|
|
238
|
+
paths.unshift(resolve2(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
229
239
|
}
|
|
230
240
|
throw new Error(
|
|
231
241
|
`Prompt not found: "${promptPath}"
|
|
@@ -233,8 +243,8 @@ Searched:
|
|
|
233
243
|
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
234
244
|
);
|
|
235
245
|
}
|
|
236
|
-
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot:
|
|
237
|
-
if (
|
|
246
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
247
|
+
if (resolvedConfig.cache !== false) {
|
|
238
248
|
promptCache.set(sourceFile, asset);
|
|
239
249
|
}
|
|
240
250
|
return asset;
|
|
@@ -242,8 +252,9 @@ ${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
|
242
252
|
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
243
253
|
}
|
|
244
254
|
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
245
|
-
|
|
246
|
-
|
|
255
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
256
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
257
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
247
258
|
if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {
|
|
248
259
|
asset = await resolveIncludes(asset, sourceFile);
|
|
249
260
|
}
|
|
@@ -265,7 +276,7 @@ function resolveInlinePromptSource(source, options = {}) {
|
|
|
265
276
|
|
|
266
277
|
// src/providers/prompt-input.ts
|
|
267
278
|
function isPromptLookup(input) {
|
|
268
|
-
return "path" in input && typeof input.path === "string"
|
|
279
|
+
return "path" in input && typeof input.path === "string";
|
|
269
280
|
}
|
|
270
281
|
function isInlinePromptSource(input) {
|
|
271
282
|
return "source" in input && typeof input.source === "string";
|
|
@@ -303,9 +314,11 @@ export {
|
|
|
303
314
|
resolveAssetForProvider,
|
|
304
315
|
PromptCache,
|
|
305
316
|
resolveIncludes,
|
|
317
|
+
DEFAULT_PROMPTS_DIR,
|
|
318
|
+
withPromptResolutionDefaults,
|
|
306
319
|
loadPromptAsset,
|
|
307
320
|
resolvePromptAsset,
|
|
308
321
|
resolveInlinePromptSource,
|
|
309
322
|
withPromptInputSupport
|
|
310
323
|
};
|
|
311
|
-
//# sourceMappingURL=chunk-
|
|
324
|
+
//# sourceMappingURL=chunk-M5VKRDIY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderer/interpolate.ts","../src/renderer/renderer.ts","../src/overrides/apply-overrides.ts","../src/providers/resolve-asset.ts","../src/cache.ts","../src/composition/resolve-includes.ts","../src/prompt-resolution.ts","../src/providers/prompt-input.ts"],"sourcesContent":["export interface InterpolateOptions {\n strict?: boolean;\n}\n\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\nconst ESCAPED_OPEN = /\\\\\\{\\\\\\{/g;\nconst ESCAPE_PLACEHOLDER = '\\x00ESCAPED_OPEN\\x00';\n\n/**\n * Interpolate variables into a template string.\n *\n * Syntax: {{ variable_name }}\n * Escape: \\{\\{ produces literal {{\n *\n * In strict mode, throws on missing variables.\n * In permissive mode, leaves {{ placeholder }} intact.\n */\nexport function interpolate(\n template: string,\n variables: Record<string, string>,\n options: InterpolateOptions = {},\n): string {\n const { strict = false } = options;\n\n // Replace escaped sequences with placeholder\n let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);\n\n result = result.replace(VARIABLE_RE, (match, name: string) => {\n if (name in variables) {\n return variables[name];\n }\n if (strict) {\n throw new Error(`Missing required variable: \"${name}\"`);\n }\n return match; // leave placeholder intact in permissive mode\n });\n\n // Restore escaped sequences\n result = result.replaceAll(ESCAPE_PLACEHOLDER, '{{');\n\n return result;\n}\n\n/**\n * Extract all variable names referenced in a template.\n */\nexport function extractVariables(template: string): string[] {\n const vars = new Set<string>();\n let match: RegExpExecArray | null;\n const re = new RegExp(VARIABLE_RE.source, 'g');\n while ((match = re.exec(template)) !== null) {\n vars.add(match[1]);\n }\n return [...vars];\n}\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport { interpolate, extractVariables } from './interpolate.js';\n\nexport interface RenderOptions {\n variables?: Record<string, string>;\n strict?: boolean;\n}\n\nexport interface RenderedSections {\n system_instructions?: string;\n prompt_template?: string;\n}\n\n/**\n * Render the sections of a resolved prompt asset with variable interpolation.\n */\nexport function renderSections(\n asset: ResolvedPromptAsset,\n options: RenderOptions = {},\n): RenderedSections {\n const { variables = {}, strict = false } = options;\n\n const result: RenderedSections = {};\n\n if (asset.sections.system_instructions) {\n result.system_instructions = interpolate(\n asset.sections.system_instructions,\n variables,\n { strict },\n );\n }\n\n if (asset.sections.prompt_template) {\n result.prompt_template = interpolate(\n asset.sections.prompt_template,\n variables,\n { strict },\n );\n }\n\n return result;\n}\n\n/**\n * Get all variable names used across all sections.\n */\nexport function getRequiredVariables(asset: ResolvedPromptAsset): string[] {\n const vars = new Set<string>();\n\n if (asset.sections.system_instructions) {\n for (const v of extractVariables(asset.sections.system_instructions)) {\n vars.add(v);\n }\n }\n\n if (asset.sections.prompt_template) {\n for (const v of extractVariables(asset.sections.prompt_template)) {\n vars.add(v);\n }\n }\n\n return [...vars];\n}\n","import type { PromptAsset, PromptAssetOverrides } from '../schema/index.js';\n\nexport interface OverrideOptions {\n environment?: string;\n tier?: string;\n runtime?: Partial<PromptAssetOverrides>;\n}\n\n/**\n * Apply environment, tier, and runtime overrides to a prompt asset.\n *\n * Precedence: base → environment → tier → runtime\n * Scalars are replaced. Arrays are replaced (not concatenated).\n */\nexport function applyOverrides(\n asset: PromptAsset,\n options: OverrideOptions = {},\n): PromptAsset {\n let result = { ...asset };\n\n // Apply environment override\n if (options.environment && result.environments?.[options.environment]) {\n result = mergeOverride(result, result.environments[options.environment]);\n }\n\n // Apply tier override\n if (options.tier && result.tiers?.[options.tier]) {\n result = mergeOverride(result, result.tiers[options.tier]);\n }\n\n // Apply runtime overrides\n if (options.runtime) {\n result = mergeOverride(result, options.runtime);\n }\n\n return result;\n}\n\nfunction mergeOverride(\n base: PromptAsset,\n override: Partial<PromptAssetOverrides>,\n): PromptAsset {\n const result = { ...base };\n\n if (override.model !== undefined) result.model = override.model;\n if (override.fallback_models !== undefined) result.fallback_models = override.fallback_models;\n if (override.tools !== undefined) result.tools = override.tools;\n\n if (override.reasoning !== undefined) {\n result.reasoning = { ...result.reasoning, ...override.reasoning };\n }\n if (override.sampling !== undefined) {\n result.sampling = { ...result.sampling, ...override.sampling };\n }\n if (override.response !== undefined) {\n result.response = { ...result.response, ...override.response };\n }\n\n return result;\n}\n","import { applyOverrides } from '../overrides/index.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type { RuntimeRenderOptions } from './types.js';\n\nexport function resolveAssetForProvider(\n asset: ResolvedPromptAsset,\n runtime: Pick<RuntimeRenderOptions, 'environment' | 'tier' | 'runtime'> = {},\n): ResolvedPromptAsset {\n if (!runtime.environment && !runtime.tier && !runtime.runtime) {\n return asset;\n }\n\n return applyOverrides(asset, {\n environment: runtime.environment,\n tier: runtime.tier,\n runtime: runtime.runtime,\n }) as ResolvedPromptAsset;\n}","import { statSync } from 'node:fs';\n\ninterface CacheEntry<T> {\n value: T;\n mtime: number;\n}\n\n/**\n * Simple in-memory LRU cache keyed by file path + mtime.\n * Used to avoid re-parsing prompt files on every renderPrompt() call.\n */\nexport class PromptCache<T> {\n private cache = new Map<string, CacheEntry<T>>();\n private maxSize: number;\n\n constructor(maxSize = 100) {\n this.maxSize = maxSize;\n }\n\n get(filePath: string): T | undefined {\n const entry = this.cache.get(filePath);\n if (!entry) return undefined;\n\n try {\n const stat = statSync(filePath);\n if (stat.mtimeMs !== entry.mtime) {\n this.cache.delete(filePath);\n return undefined;\n }\n } catch {\n this.cache.delete(filePath);\n return undefined;\n }\n\n // Refresh recency for true LRU semantics.\n this.cache.delete(filePath);\n this.cache.set(filePath, entry);\n\n return entry.value;\n }\n\n set(filePath: string, value: T): void {\n try {\n const stat = statSync(filePath);\n\n if (this.cache.has(filePath)) {\n this.cache.delete(filePath);\n } else if (this.cache.size >= this.maxSize) {\n const oldest = this.cache.keys().next().value;\n if (oldest) this.cache.delete(oldest);\n }\n\n this.cache.set(filePath, { value, mtime: stat.mtimeMs });\n } catch {\n // Can't stat the file — don't cache\n }\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve, dirname } from 'node:path';\nimport { parsePrompt } from '../parser/index.js';\nimport type { PromptAsset } from '../schema/index.js';\n\n/**\n * Resolve includes for a prompt asset, inlining content from referenced files.\n * Detects and rejects circular includes.\n */\nexport async function resolveIncludes(\n asset: PromptAsset,\n basePath: string,\n visited: Set<string> = new Set(),\n): Promise<PromptAsset> {\n if (!asset.includes || asset.includes.length === 0) {\n return asset;\n }\n\n const baseDir = dirname(basePath);\n const resolvedPath = resolve(basePath);\n\n if (visited.has(resolvedPath)) {\n throw new Error(`Circular include detected: ${resolvedPath}`);\n }\n visited.add(resolvedPath);\n\n let mergedSystemInstructions = '';\n\n for (const includePath of asset.includes) {\n const fullPath = resolve(baseDir, includePath);\n\n if (visited.has(fullPath)) {\n throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);\n }\n\n const content = await readFile(fullPath, 'utf-8');\n const { asset: includedAsset } = parsePrompt(content, fullPath);\n\n // Recursively resolve nested includes\n const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));\n\n // Append included system instructions before local ones\n if (resolved.sections?.system_instructions) {\n mergedSystemInstructions += resolved.sections.system_instructions + '\\n\\n';\n }\n }\n\n // Prepend included system instructions before the local ones\n const localSystem = asset.sections?.system_instructions ?? '';\n const combinedSystem = (mergedSystemInstructions + localSystem).trim() || undefined;\n\n return {\n ...asset,\n sections: {\n ...asset.sections,\n system_instructions: combinedSystem,\n },\n // Drop includes from the resolved asset — they've been inlined\n includes: undefined,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { existsSync, statSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { PromptCache } from './cache.js';\nimport { resolveIncludes } from './composition/index.js';\nimport { applyOverrides } from './overrides/index.js';\nimport { parsePrompt, loadPromptFile } from './parser/index.js';\nimport type { PromptAsset, PromptAssetOverrides, ResolvedPromptAsset } from './schema/index.js';\n\nexport type PromptResolutionMode = 'auto' | 'compiled-only' | 'source-only';\n\nexport const DEFAULT_PROMPTS_DIR = './prompts';\nexport const DEFAULT_COMPILED_JSON_DIR = './.generated-prompts/json';\nexport const DEFAULT_COMPILED_ESM_DIR = './.generated-prompts/esm';\n\nexport interface PromptResolutionConfig {\n sourceDir?: string;\n compiledDir?: string;\n mode?: PromptResolutionMode;\n cache?: boolean;\n}\n\nexport interface ResolvedPromptResolutionConfig {\n sourceDir: string;\n compiledDir: string;\n mode?: PromptResolutionMode;\n cache?: boolean;\n}\n\nexport function defaultCompiledDirForFormat(format: 'json' | 'esm'): string {\n return format === 'esm' ? DEFAULT_COMPILED_ESM_DIR : DEFAULT_COMPILED_JSON_DIR;\n}\n\nexport function withPromptResolutionDefaults(config: PromptResolutionConfig): ResolvedPromptResolutionConfig {\n return {\n ...config,\n sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,\n compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR,\n };\n}\n\nconst sharedPromptCache = new PromptCache<PromptAsset>();\n\nexport async function loadPromptAsset(\n promptPath: string,\n config: PromptResolutionConfig,\n promptCache: PromptCache<PromptAsset> = sharedPromptCache,\n): Promise<PromptAsset> {\n const resolvedConfig = withPromptResolutionDefaults(config);\n const mode = resolvedConfig.mode ?? 'auto';\n\n if (mode !== 'source-only' && resolvedConfig.compiledDir) {\n const compiledFile = resolve(resolvedConfig.compiledDir, promptPath + '.json');\n if (existsSync(compiledFile)) {\n if (mode === 'auto') {\n const sourceFile = resolve(resolvedConfig.sourceDir, promptPath + '.md');\n if (existsSync(sourceFile)) {\n const compiledMtime = statSync(compiledFile).mtimeMs;\n const sourceMtime = statSync(sourceFile).mtimeMs;\n if (sourceMtime > compiledMtime) {\n console.warn(\n `[promptopskit] Warning: compiled artifact for \"${promptPath}\" is older than source .md file.\\n`\n + ' Run \"promptopskit compile\" or switch to source-only mode.',\n );\n }\n }\n }\n\n const content = await readFile(compiledFile, 'utf-8');\n return JSON.parse(content) as PromptAsset;\n }\n\n if (mode === 'compiled-only') {\n throw new Error(\n `Compiled artifact not found: ${compiledFile}\\n`\n + 'Run \"promptopskit compile\" to generate it.',\n );\n }\n }\n\n if (mode !== 'compiled-only') {\n const sourceFile = resolve(resolvedConfig.sourceDir, promptPath + '.md');\n\n if (resolvedConfig.cache !== false) {\n const cached = promptCache.get(sourceFile);\n if (cached) {\n return cached;\n }\n }\n\n if (!existsSync(sourceFile)) {\n const paths = [sourceFile];\n if (resolvedConfig.compiledDir) {\n paths.unshift(resolve(resolvedConfig.compiledDir, promptPath + '.json'));\n }\n\n throw new Error(\n `Prompt not found: \"${promptPath}\"\\nSearched:\\n${paths.map((candidate) => ` - ${candidate}`).join('\\n')}`,\n );\n }\n\n const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });\n\n if (resolvedConfig.cache !== false) {\n promptCache.set(sourceFile, asset);\n }\n\n return asset;\n }\n\n throw new Error(`Prompt not found: \"${promptPath}\"`);\n}\n\nexport async function resolvePromptAsset(\n promptPath: string,\n config: PromptResolutionConfig,\n options: { environment?: string; tier?: string; runtime?: Partial<PromptAssetOverrides> } = {},\n promptCache: PromptCache<PromptAsset> = sharedPromptCache,\n): Promise<ResolvedPromptAsset> {\n const resolvedConfig = withPromptResolutionDefaults(config);\n let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);\n\n const sourceFile = resolve(resolvedConfig.sourceDir, promptPath + '.md');\n if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {\n asset = await resolveIncludes(asset, sourceFile);\n }\n\n asset = applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\n });\n\n return asset as ResolvedPromptAsset;\n}\n\nexport function resolveInlinePromptSource(\n source: string,\n options: { environment?: string; tier?: string; runtime?: Partial<PromptAssetOverrides> } = {},\n): ResolvedPromptAsset {\n const { asset } = parsePrompt(source);\n return applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\n }) as ResolvedPromptAsset;\n}","import { resolveInlinePromptSource, resolvePromptAsset } from '../prompt-resolution.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderPromptInput,\n RenderPromptMethod,\n RuntimeRenderOptions,\n ValidatePromptMethod,\n} from './types.js';\n\ntype SyncProviderAdapter = Omit<ProviderAdapter, 'validatePrompt' | 'renderPrompt'>;\n\nfunction isPromptLookup(input: ProviderPromptInput): input is Extract<ProviderPromptInput, { path: string }> {\n return 'path' in input && typeof input.path === 'string';\n}\n\nfunction isInlinePromptSource(input: ProviderPromptInput): input is Extract<ProviderPromptInput, { source: string }> {\n return 'source' in input && typeof input.source === 'string';\n}\n\nasync function resolveProviderPromptInput(\n input: ProviderPromptInput,\n runtime?: Pick<RuntimeRenderOptions, 'environment' | 'tier' | 'runtime'>,\n): Promise<ResolvedPromptAsset> {\n if (isPromptLookup(input)) {\n return resolvePromptAsset(input.path, input, runtime);\n }\n\n if (isInlinePromptSource(input)) {\n return resolveInlinePromptSource(input.source, runtime);\n }\n\n return input;\n}\n\nexport function withPromptInputSupport(adapter: SyncProviderAdapter): ProviderAdapter {\n const validatePrompt: ValidatePromptMethod = async (input, runtime) => {\n const resolved = await resolveProviderPromptInput(input, runtime);\n return adapter.validate(resolved, runtime);\n };\n\n const renderPrompt: RenderPromptMethod = async (input, runtime) => {\n const resolved = await resolveProviderPromptInput(input, runtime);\n return adapter.render(resolved, runtime);\n };\n\n return {\n ...adapter,\n validatePrompt,\n renderPrompt,\n };\n}"],"mappings":"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","names":["readFile","statSync","resolve","resolve","statSync","readFile"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
openaiAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2X5HFPSD.js";
|
|
4
4
|
import {
|
|
5
5
|
withPromptInputSupport
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-M5VKRDIY.js";
|
|
7
7
|
|
|
8
8
|
// src/providers/openrouter.ts
|
|
9
9
|
var openrouterAdapter = withPromptInputSupport({
|
|
@@ -23,4 +23,4 @@ var openrouterAdapter = withPromptInputSupport({
|
|
|
23
23
|
export {
|
|
24
24
|
openrouterAdapter
|
|
25
25
|
};
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
26
|
+
//# sourceMappingURL=chunk-ROBYCHAW.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -568,6 +568,99 @@ async function collectPromptFiles(dir) {
|
|
|
568
568
|
// src/cli/commands/compile.ts
|
|
569
569
|
import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
|
|
570
570
|
import { join as join3, extname as extname2, relative, dirname as dirname3 } from "path";
|
|
571
|
+
|
|
572
|
+
// src/prompt-resolution.ts
|
|
573
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
574
|
+
import { existsSync, statSync as statSync2 } from "fs";
|
|
575
|
+
import { resolve as resolve3 } from "path";
|
|
576
|
+
|
|
577
|
+
// src/cache.ts
|
|
578
|
+
import { statSync } from "fs";
|
|
579
|
+
var PromptCache = class {
|
|
580
|
+
cache = /* @__PURE__ */ new Map();
|
|
581
|
+
maxSize;
|
|
582
|
+
constructor(maxSize = 100) {
|
|
583
|
+
this.maxSize = maxSize;
|
|
584
|
+
}
|
|
585
|
+
get(filePath) {
|
|
586
|
+
const entry = this.cache.get(filePath);
|
|
587
|
+
if (!entry) return void 0;
|
|
588
|
+
try {
|
|
589
|
+
const stat = statSync(filePath);
|
|
590
|
+
if (stat.mtimeMs !== entry.mtime) {
|
|
591
|
+
this.cache.delete(filePath);
|
|
592
|
+
return void 0;
|
|
593
|
+
}
|
|
594
|
+
} catch {
|
|
595
|
+
this.cache.delete(filePath);
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
598
|
+
this.cache.delete(filePath);
|
|
599
|
+
this.cache.set(filePath, entry);
|
|
600
|
+
return entry.value;
|
|
601
|
+
}
|
|
602
|
+
set(filePath, value) {
|
|
603
|
+
try {
|
|
604
|
+
const stat = statSync(filePath);
|
|
605
|
+
if (this.cache.has(filePath)) {
|
|
606
|
+
this.cache.delete(filePath);
|
|
607
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
608
|
+
const oldest = this.cache.keys().next().value;
|
|
609
|
+
if (oldest) this.cache.delete(oldest);
|
|
610
|
+
}
|
|
611
|
+
this.cache.set(filePath, { value, mtime: stat.mtimeMs });
|
|
612
|
+
} catch {
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
clear() {
|
|
616
|
+
this.cache.clear();
|
|
617
|
+
}
|
|
618
|
+
get size() {
|
|
619
|
+
return this.cache.size;
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
// src/overrides/apply-overrides.ts
|
|
624
|
+
function applyOverrides(asset, options = {}) {
|
|
625
|
+
let result = { ...asset };
|
|
626
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
627
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
628
|
+
}
|
|
629
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
630
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
631
|
+
}
|
|
632
|
+
if (options.runtime) {
|
|
633
|
+
result = mergeOverride(result, options.runtime);
|
|
634
|
+
}
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
function mergeOverride(base, override) {
|
|
638
|
+
const result = { ...base };
|
|
639
|
+
if (override.model !== void 0) result.model = override.model;
|
|
640
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
641
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
642
|
+
if (override.reasoning !== void 0) {
|
|
643
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
644
|
+
}
|
|
645
|
+
if (override.sampling !== void 0) {
|
|
646
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
647
|
+
}
|
|
648
|
+
if (override.response !== void 0) {
|
|
649
|
+
result.response = { ...result.response, ...override.response };
|
|
650
|
+
}
|
|
651
|
+
return result;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/prompt-resolution.ts
|
|
655
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
656
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
657
|
+
var DEFAULT_COMPILED_ESM_DIR = "./.generated-prompts/esm";
|
|
658
|
+
function defaultCompiledDirForFormat(format) {
|
|
659
|
+
return format === "esm" ? DEFAULT_COMPILED_ESM_DIR : DEFAULT_COMPILED_JSON_DIR;
|
|
660
|
+
}
|
|
661
|
+
var sharedPromptCache = new PromptCache();
|
|
662
|
+
|
|
663
|
+
// src/cli/commands/compile.ts
|
|
571
664
|
var HELP2 = `
|
|
572
665
|
promptopskit compile [sourceDir] [outputDir] [options]
|
|
573
666
|
|
|
@@ -594,8 +687,8 @@ async function compile(args) {
|
|
|
594
687
|
console.error(`Error: Unknown format "${format}". Use "json" or "esm".`);
|
|
595
688
|
process.exit(1);
|
|
596
689
|
}
|
|
597
|
-
const sourceDir = getFlag(args, "--source", "-s") ?? positional[0] ??
|
|
598
|
-
const outputDir = getFlag(args, "--output", "-o") ?? positional[1] ??
|
|
690
|
+
const sourceDir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
|
|
691
|
+
const outputDir = getFlag(args, "--output", "-o") ?? positional[1] ?? defaultCompiledDirForFormat(format);
|
|
599
692
|
const files = await collectPromptFiles2(sourceDir);
|
|
600
693
|
if (files.length === 0) {
|
|
601
694
|
console.log(`No .md prompt files found in ${sourceDir}`);
|
|
@@ -644,9 +737,6 @@ async function compile(args) {
|
|
|
644
737
|
process.exit(1);
|
|
645
738
|
}
|
|
646
739
|
}
|
|
647
|
-
function defaultOutputDirForFormat(format) {
|
|
648
|
-
return format === "esm" ? "./.generated-prompts/esm" : "./.generated-prompts/json";
|
|
649
|
-
}
|
|
650
740
|
function getPositionalArgs(args, flagsWithValues) {
|
|
651
741
|
const positional = [];
|
|
652
742
|
for (let index = 0; index < args.length; index++) {
|
|
@@ -683,49 +773,18 @@ async function collectPromptFiles2(dir) {
|
|
|
683
773
|
}
|
|
684
774
|
|
|
685
775
|
// src/cli/commands/render.ts
|
|
686
|
-
import { readFile as
|
|
687
|
-
import { existsSync as
|
|
688
|
-
|
|
689
|
-
// src/overrides/apply-overrides.ts
|
|
690
|
-
function applyOverrides(asset, options = {}) {
|
|
691
|
-
let result = { ...asset };
|
|
692
|
-
if (options.environment && result.environments?.[options.environment]) {
|
|
693
|
-
result = mergeOverride(result, result.environments[options.environment]);
|
|
694
|
-
}
|
|
695
|
-
if (options.tier && result.tiers?.[options.tier]) {
|
|
696
|
-
result = mergeOverride(result, result.tiers[options.tier]);
|
|
697
|
-
}
|
|
698
|
-
if (options.runtime) {
|
|
699
|
-
result = mergeOverride(result, options.runtime);
|
|
700
|
-
}
|
|
701
|
-
return result;
|
|
702
|
-
}
|
|
703
|
-
function mergeOverride(base, override) {
|
|
704
|
-
const result = { ...base };
|
|
705
|
-
if (override.model !== void 0) result.model = override.model;
|
|
706
|
-
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
707
|
-
if (override.tools !== void 0) result.tools = override.tools;
|
|
708
|
-
if (override.reasoning !== void 0) {
|
|
709
|
-
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
710
|
-
}
|
|
711
|
-
if (override.sampling !== void 0) {
|
|
712
|
-
result.sampling = { ...result.sampling, ...override.sampling };
|
|
713
|
-
}
|
|
714
|
-
if (override.response !== void 0) {
|
|
715
|
-
result.response = { ...result.response, ...override.response };
|
|
716
|
-
}
|
|
717
|
-
return result;
|
|
718
|
-
}
|
|
776
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
777
|
+
import { existsSync as existsSync3 } from "fs";
|
|
719
778
|
|
|
720
779
|
// src/cli/commands/defaults-root.ts
|
|
721
|
-
import { existsSync } from "fs";
|
|
722
|
-
import { dirname as dirname4, join as join4, resolve as
|
|
780
|
+
import { existsSync as existsSync2 } from "fs";
|
|
781
|
+
import { dirname as dirname4, join as join4, resolve as resolve4 } from "path";
|
|
723
782
|
function findDefaultsRoot(filePath) {
|
|
724
|
-
let current =
|
|
783
|
+
let current = resolve4(dirname4(filePath));
|
|
725
784
|
let root = current;
|
|
726
785
|
let foundDefaults = false;
|
|
727
786
|
while (true) {
|
|
728
|
-
if (
|
|
787
|
+
if (existsSync2(join4(current, "defaults.md"))) {
|
|
729
788
|
root = current;
|
|
730
789
|
foundDefaults = true;
|
|
731
790
|
} else if (foundDefaults) {
|
|
@@ -768,13 +827,13 @@ async function render(args) {
|
|
|
768
827
|
const jsonOutput = args.includes("--json");
|
|
769
828
|
let variables = {};
|
|
770
829
|
if (varsFile) {
|
|
771
|
-
const varsContent = await
|
|
830
|
+
const varsContent = await readFile4(varsFile, "utf-8");
|
|
772
831
|
variables = JSON.parse(varsContent);
|
|
773
832
|
} else {
|
|
774
833
|
const sidecarPath = file.replace(/\.md$/, ".test.yaml");
|
|
775
|
-
if (
|
|
834
|
+
if (existsSync3(sidecarPath)) {
|
|
776
835
|
const { default: yaml } = await import("gray-matter");
|
|
777
|
-
const sidecarContent = await
|
|
836
|
+
const sidecarContent = await readFile4(sidecarPath, "utf-8");
|
|
778
837
|
const parsed2 = yaml(`---
|
|
779
838
|
${sidecarContent}---
|
|
780
839
|
`);
|
|
@@ -859,7 +918,7 @@ async function inspect(args) {
|
|
|
859
918
|
// src/cli/commands/init.ts
|
|
860
919
|
import { writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
861
920
|
import { join as join5, dirname as dirname5 } from "path";
|
|
862
|
-
import { existsSync as
|
|
921
|
+
import { existsSync as existsSync4, readFileSync } from "fs";
|
|
863
922
|
var HELP5 = `
|
|
864
923
|
promptopskit init [dir]
|
|
865
924
|
|
|
@@ -1010,7 +1069,7 @@ async function init(args) {
|
|
|
1010
1069
|
let created = 0;
|
|
1011
1070
|
let skipped = 0;
|
|
1012
1071
|
for (const file of files) {
|
|
1013
|
-
if (
|
|
1072
|
+
if (existsSync4(file.path)) {
|
|
1014
1073
|
console.log(` skip ${file.path} (already exists)`);
|
|
1015
1074
|
skipped++;
|
|
1016
1075
|
continue;
|
|
@@ -1022,7 +1081,7 @@ async function init(args) {
|
|
|
1022
1081
|
}
|
|
1023
1082
|
console.log();
|
|
1024
1083
|
console.log(`Created ${created} file(s), skipped ${skipped} existing.`);
|
|
1025
|
-
if (
|
|
1084
|
+
if (existsSync4("package.json")) {
|
|
1026
1085
|
try {
|
|
1027
1086
|
const pkg = JSON.parse(readFileSync("package.json", "utf-8"));
|
|
1028
1087
|
if (!pkg.scripts?.["build:prompts"]) {
|
|
@@ -1036,9 +1095,9 @@ async function init(args) {
|
|
|
1036
1095
|
}
|
|
1037
1096
|
|
|
1038
1097
|
// src/cli/commands/skill.ts
|
|
1039
|
-
import { writeFile as writeFile3, readFile as
|
|
1098
|
+
import { writeFile as writeFile3, readFile as readFile5, mkdir as mkdir3 } from "fs/promises";
|
|
1040
1099
|
import { dirname as dirname6 } from "path";
|
|
1041
|
-
import { existsSync as
|
|
1100
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1042
1101
|
var MARKER_START = "<!-- promptopskit:start -->";
|
|
1043
1102
|
var MARKER_END = "<!-- promptopskit:end -->";
|
|
1044
1103
|
var HELP6 = `
|
|
@@ -1124,8 +1183,8 @@ async function skill(args) {
|
|
|
1124
1183
|
continue;
|
|
1125
1184
|
}
|
|
1126
1185
|
const markedContent = config.wrap(wrapMarkers(STUB_CONTENT));
|
|
1127
|
-
if (
|
|
1128
|
-
const existing = await
|
|
1186
|
+
if (existsSync5(filePath) && !force) {
|
|
1187
|
+
const existing = await readFile5(filePath, "utf-8");
|
|
1129
1188
|
const merged = mergeContent(existing, markedContent);
|
|
1130
1189
|
if (merged === existing) {
|
|
1131
1190
|
console.log(` skip ${filePath} (already up to date)`);
|
|
@@ -1148,13 +1207,13 @@ async function skill(args) {
|
|
|
1148
1207
|
}
|
|
1149
1208
|
async function deployClaude(filePath, force) {
|
|
1150
1209
|
const content = CLAUDE_LINE + "\n";
|
|
1151
|
-
if (!
|
|
1210
|
+
if (!existsSync5(filePath) || force) {
|
|
1152
1211
|
await mkdir3(dirname6(filePath), { recursive: true });
|
|
1153
1212
|
await writeFile3(filePath, content, "utf-8");
|
|
1154
1213
|
console.log(` \u2713 ${filePath}`);
|
|
1155
1214
|
return 1;
|
|
1156
1215
|
}
|
|
1157
|
-
const existing = await
|
|
1216
|
+
const existing = await readFile5(filePath, "utf-8");
|
|
1158
1217
|
if (existing.split("\n").some((line) => line.trim() === CLAUDE_LINE)) {
|
|
1159
1218
|
console.log(` skip ${filePath} (already up to date)`);
|
|
1160
1219
|
return 0;
|