promptopskit 0.5.0 → 0.6.2
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 +9 -7
- package/SKILL.md +16 -10
- package/dist/{chunk-6VLKZCNS.js → chunk-55B7QQBK.js} +2 -2
- package/dist/{chunk-6BOUQVSX.js → chunk-FNCIBZJF.js} +3 -3
- package/dist/{chunk-D75HKF64.js → chunk-GLT3YYWK.js} +2 -2
- package/dist/{chunk-IN4KT5EU.js → chunk-IPFD5Y3O.js} +3 -3
- package/dist/{chunk-KN7H4JRK.js → chunk-JR7252DG.js} +393 -386
- package/dist/chunk-JR7252DG.js.map +1 -0
- package/dist/{chunk-K6ZU3CGV.js → chunk-UY5OKMVP.js} +281 -17
- package/dist/chunk-UY5OKMVP.js.map +1 -0
- package/dist/{chunk-QK3WKE3K.js → chunk-VMLGUI4F.js} +2 -2
- package/dist/{chunk-LNGHGGJN.js → chunk-XEZJZ3IG.js} +2 -2
- package/dist/cli/index.js +410 -103
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +971 -660
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +55 -15
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +675 -407
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +2 -2
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +3 -3
- package/dist/providers/gemini.cjs +675 -407
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.d.cts +2 -2
- package/dist/providers/gemini.d.ts +2 -2
- package/dist/providers/gemini.js +3 -3
- package/dist/providers/llmasaservice.cjs +675 -407
- package/dist/providers/llmasaservice.cjs.map +1 -1
- package/dist/providers/llmasaservice.d.cts +2 -2
- package/dist/providers/llmasaservice.d.ts +2 -2
- package/dist/providers/llmasaservice.js +4 -4
- package/dist/providers/openai-responses.cjs +675 -407
- package/dist/providers/openai-responses.cjs.map +1 -1
- package/dist/providers/openai-responses.d.cts +2 -2
- package/dist/providers/openai-responses.d.ts +2 -2
- package/dist/providers/openai-responses.js +3 -3
- package/dist/providers/openai.cjs +675 -407
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +2 -2
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +3 -3
- package/dist/providers/openrouter.cjs +675 -407
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.d.cts +2 -2
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/openrouter.js +4 -4
- package/dist/{schema-D-RI4w-k.d.cts → schema-CuYsv8JA.d.cts} +540 -206
- package/dist/{schema-D-RI4w-k.d.ts → schema-CuYsv8JA.d.ts} +540 -206
- package/dist/testing.cjs +43 -5
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-B3dxBGu6.d.ts → types-DpK0mTHL.d.ts} +1 -1
- package/dist/{types-DbTAjlTN.d.cts → types-UA_p9uJy.d.cts} +1 -1
- package/dist/usagetap/index.d.cts +2 -2
- package/dist/usagetap/index.d.ts +2 -2
- package/package.json +9 -2
- package/dist/chunk-K6ZU3CGV.js.map +0 -1
- package/dist/chunk-KN7H4JRK.js.map +0 -1
- /package/dist/{chunk-6VLKZCNS.js.map → chunk-55B7QQBK.js.map} +0 -0
- /package/dist/{chunk-6BOUQVSX.js.map → chunk-FNCIBZJF.js.map} +0 -0
- /package/dist/{chunk-D75HKF64.js.map → chunk-GLT3YYWK.js.map} +0 -0
- /package/dist/{chunk-IN4KT5EU.js.map → chunk-IPFD5Y3O.js.map} +0 -0
- /package/dist/{chunk-QK3WKE3K.js.map → chunk-VMLGUI4F.js.map} +0 -0
- /package/dist/{chunk-LNGHGGJN.js.map → chunk-XEZJZ3IG.js.map} +0 -0
|
@@ -40,12 +40,13 @@ var ESCAPED_OPEN = /\\\{\\\{/g;
|
|
|
40
40
|
var ESCAPE_PLACEHOLDER = "\0ESCAPED_OPEN\0";
|
|
41
41
|
function interpolate(template, variables, options = {}) {
|
|
42
42
|
const { strict = false } = options;
|
|
43
|
+
const optionalVariables = new Set(options.optionalVariables ?? []);
|
|
43
44
|
let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);
|
|
44
45
|
result = result.replace(VARIABLE_RE, (match, name) => {
|
|
45
46
|
if (name in variables) {
|
|
46
47
|
return variables[name];
|
|
47
48
|
}
|
|
48
|
-
if (strict) {
|
|
49
|
+
if (strict && !optionalVariables.has(name)) {
|
|
49
50
|
throw new Error(`Missing required variable: "${name}"`);
|
|
50
51
|
}
|
|
51
52
|
return match;
|
|
@@ -54,22 +55,299 @@ function interpolate(template, variables, options = {}) {
|
|
|
54
55
|
return result;
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
// src/context.ts
|
|
59
|
+
var textEncoder = new TextEncoder();
|
|
60
|
+
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
61
|
+
var REJECT_SECRETS_FLAGS = "i";
|
|
62
|
+
function getContextInputs(asset) {
|
|
63
|
+
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
64
|
+
}
|
|
65
|
+
function normalizeContextInput(input) {
|
|
66
|
+
if (typeof input === "string") {
|
|
67
|
+
return { name: input };
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
name: input.name,
|
|
71
|
+
optional: input.optional,
|
|
72
|
+
warnings: input.warnings,
|
|
73
|
+
max_size: input.max_size,
|
|
74
|
+
trim: input.trim,
|
|
75
|
+
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
76
|
+
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
77
|
+
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
78
|
+
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function normalizeContextRegex(value) {
|
|
82
|
+
if (value === void 0) {
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
if (typeof value === "string") {
|
|
86
|
+
const literal = parseRegexLiteral(value);
|
|
87
|
+
if (value.startsWith("/") && !literal) {
|
|
88
|
+
return {
|
|
89
|
+
pattern: value,
|
|
90
|
+
flags: "",
|
|
91
|
+
raw: value,
|
|
92
|
+
invalidLiteral: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
pattern: literal?.pattern ?? value,
|
|
97
|
+
flags: literal?.flags ?? "",
|
|
98
|
+
raw: value
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
pattern: value.pattern,
|
|
103
|
+
flags: value.flags ?? "",
|
|
104
|
+
raw: JSON.stringify(value),
|
|
105
|
+
returnMessage: value.return_message
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function normalizeBuiltInValidator(value) {
|
|
109
|
+
if (value === void 0 || value === false) {
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
if (value === true) {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
returnMessage: value.return_message
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function parseRegexLiteral(value) {
|
|
120
|
+
if (!value.startsWith("/")) {
|
|
121
|
+
return void 0;
|
|
122
|
+
}
|
|
123
|
+
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
124
|
+
if (value[index] !== "/") {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
let backslashCount = 0;
|
|
128
|
+
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
129
|
+
backslashCount += 1;
|
|
130
|
+
}
|
|
131
|
+
if (backslashCount % 2 === 1) {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
pattern: value.slice(1, index),
|
|
136
|
+
flags: value.slice(index + 1)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return void 0;
|
|
140
|
+
}
|
|
141
|
+
function formatInvalidContextRegexMessage(details) {
|
|
142
|
+
return [
|
|
143
|
+
`Invalid context regex for prompt "${details.promptId}"`,
|
|
144
|
+
`variable "${details.variable}"`,
|
|
145
|
+
`field "${details.field}"`,
|
|
146
|
+
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
147
|
+
].join(", ");
|
|
148
|
+
}
|
|
149
|
+
function compileContextRegex(regex, details) {
|
|
150
|
+
if (regex.invalidLiteral) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`POK013: ${formatInvalidContextRegexMessage({
|
|
153
|
+
...details,
|
|
154
|
+
raw: regex.raw,
|
|
155
|
+
reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
|
|
156
|
+
})}`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
return new RegExp(regex.pattern, regex.flags);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
163
|
+
throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function getRejectSecretsRegex() {
|
|
167
|
+
return {
|
|
168
|
+
pattern: REJECT_SECRETS_PATTERN,
|
|
169
|
+
flags: REJECT_SECRETS_FLAGS,
|
|
170
|
+
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function isTrimEnabled(mode) {
|
|
174
|
+
return mode === true || mode === "start" || mode === "end" || mode === "both";
|
|
175
|
+
}
|
|
176
|
+
function normalizeTrimMode(mode) {
|
|
177
|
+
if (mode === "start") {
|
|
178
|
+
return "start";
|
|
179
|
+
}
|
|
180
|
+
return "end";
|
|
181
|
+
}
|
|
182
|
+
function trimToMaxSize(value, maxSize, mode) {
|
|
183
|
+
const measured = measureContextValueSize(value);
|
|
184
|
+
if (measured <= maxSize) {
|
|
185
|
+
return value;
|
|
186
|
+
}
|
|
187
|
+
const characters = Array.from(value);
|
|
188
|
+
const normalizedMode = normalizeTrimMode(mode);
|
|
189
|
+
if (normalizedMode === "start") {
|
|
190
|
+
let collected2 = "";
|
|
191
|
+
let size2 = 0;
|
|
192
|
+
for (let i = characters.length - 1; i >= 0; i -= 1) {
|
|
193
|
+
const next = characters[i];
|
|
194
|
+
const charSize = measureContextValueSize(next);
|
|
195
|
+
if (size2 + charSize > maxSize) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
collected2 = next + collected2;
|
|
199
|
+
size2 += charSize;
|
|
200
|
+
}
|
|
201
|
+
return collected2;
|
|
202
|
+
}
|
|
203
|
+
let collected = "";
|
|
204
|
+
let size = 0;
|
|
205
|
+
for (const char of characters) {
|
|
206
|
+
const charSize = measureContextValueSize(char);
|
|
207
|
+
if (size + charSize > maxSize) {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
collected += char;
|
|
211
|
+
size += charSize;
|
|
212
|
+
}
|
|
213
|
+
return collected;
|
|
214
|
+
}
|
|
215
|
+
function sanitizeContextVariables(asset, variables = {}, options = {}) {
|
|
216
|
+
const { onContextOverflow } = options;
|
|
217
|
+
const sanitized = { ...variables };
|
|
218
|
+
for (const input of getContextInputs(asset)) {
|
|
219
|
+
const value = sanitized[input.name];
|
|
220
|
+
if (value === void 0) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
let candidate = value;
|
|
224
|
+
if (input.max_size !== void 0) {
|
|
225
|
+
const actualSize = measureContextValueSize(candidate);
|
|
226
|
+
if (actualSize > input.max_size && onContextOverflow) {
|
|
227
|
+
candidate = onContextOverflow({
|
|
228
|
+
promptId: asset.id,
|
|
229
|
+
variable: input.name,
|
|
230
|
+
value: candidate,
|
|
231
|
+
maxSize: input.max_size,
|
|
232
|
+
actualSize
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (isTrimEnabled(input.trim) && input.max_size !== void 0) {
|
|
237
|
+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
|
|
238
|
+
}
|
|
239
|
+
sanitized[input.name] = candidate;
|
|
240
|
+
if (input.allow_regex) {
|
|
241
|
+
const candidate2 = sanitized[input.name];
|
|
242
|
+
const matcher = compileContextRegex(input.allow_regex, {
|
|
243
|
+
promptId: asset.id,
|
|
244
|
+
variable: input.name,
|
|
245
|
+
field: "allow_regex"
|
|
246
|
+
});
|
|
247
|
+
if (!matcher.test(candidate2)) {
|
|
248
|
+
if (input.allow_regex.returnMessage) {
|
|
249
|
+
return {
|
|
250
|
+
variables: sanitized,
|
|
251
|
+
shortCircuit: {
|
|
252
|
+
returnMessage: input.allow_regex.returnMessage,
|
|
253
|
+
code: "POK031",
|
|
254
|
+
variable: input.name,
|
|
255
|
+
field: "allow_regex"
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
throw new Error(
|
|
260
|
+
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (input.deny_regex) {
|
|
265
|
+
const candidate2 = sanitized[input.name];
|
|
266
|
+
const matcher = compileContextRegex(input.deny_regex, {
|
|
267
|
+
promptId: asset.id,
|
|
268
|
+
variable: input.name,
|
|
269
|
+
field: "deny_regex"
|
|
270
|
+
});
|
|
271
|
+
if (matcher.test(candidate2)) {
|
|
272
|
+
if (input.deny_regex.returnMessage) {
|
|
273
|
+
return {
|
|
274
|
+
variables: sanitized,
|
|
275
|
+
shortCircuit: {
|
|
276
|
+
returnMessage: input.deny_regex.returnMessage,
|
|
277
|
+
code: "POK032",
|
|
278
|
+
variable: input.name,
|
|
279
|
+
field: "deny_regex"
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
throw new Error(
|
|
284
|
+
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (input.non_empty && candidate.trim().length === 0) {
|
|
289
|
+
if (input.non_empty.returnMessage) {
|
|
290
|
+
return {
|
|
291
|
+
variables: sanitized,
|
|
292
|
+
shortCircuit: {
|
|
293
|
+
returnMessage: input.non_empty.returnMessage,
|
|
294
|
+
code: "POK033",
|
|
295
|
+
variable: input.name,
|
|
296
|
+
field: "non_empty"
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
throw new Error(
|
|
301
|
+
`POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (input.reject_secrets) {
|
|
305
|
+
const matcher = compileContextRegex(getRejectSecretsRegex(), {
|
|
306
|
+
promptId: asset.id,
|
|
307
|
+
variable: input.name,
|
|
308
|
+
field: "reject_secrets"
|
|
309
|
+
});
|
|
310
|
+
if (matcher.test(candidate)) {
|
|
311
|
+
if (input.reject_secrets.returnMessage) {
|
|
312
|
+
return {
|
|
313
|
+
variables: sanitized,
|
|
314
|
+
shortCircuit: {
|
|
315
|
+
returnMessage: input.reject_secrets.returnMessage,
|
|
316
|
+
code: "POK034",
|
|
317
|
+
variable: input.name,
|
|
318
|
+
field: "reject_secrets"
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
throw new Error(
|
|
323
|
+
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return { variables: sanitized };
|
|
329
|
+
}
|
|
330
|
+
function measureContextValueSize(value) {
|
|
331
|
+
return textEncoder.encode(value).length;
|
|
332
|
+
}
|
|
333
|
+
|
|
57
334
|
// src/renderer/renderer.ts
|
|
58
335
|
function renderSections(asset, options = {}) {
|
|
59
336
|
const { variables = {}, strict = false } = options;
|
|
337
|
+
const optionalVariables = getContextInputs(asset).filter((input) => input.optional === true).map((input) => input.name);
|
|
60
338
|
const result = {};
|
|
61
339
|
if (asset.sections.system_instructions) {
|
|
62
340
|
result.system_instructions = interpolate(
|
|
63
341
|
asset.sections.system_instructions,
|
|
64
342
|
variables,
|
|
65
|
-
{ strict }
|
|
343
|
+
{ strict, optionalVariables }
|
|
66
344
|
);
|
|
67
345
|
}
|
|
68
346
|
if (asset.sections.prompt_template) {
|
|
69
347
|
result.prompt_template = interpolate(
|
|
70
348
|
asset.sections.prompt_template,
|
|
71
349
|
variables,
|
|
72
|
-
{ strict }
|
|
350
|
+
{ strict, optionalVariables }
|
|
73
351
|
);
|
|
74
352
|
}
|
|
75
353
|
return result;
|
|
@@ -169,9 +447,9 @@ function resolveAssetForProvider(asset, runtime = {}) {
|
|
|
169
447
|
}
|
|
170
448
|
|
|
171
449
|
// src/prompt-resolution.ts
|
|
172
|
-
var
|
|
450
|
+
var import_promises4 = require("fs/promises");
|
|
173
451
|
var import_node_fs2 = require("fs");
|
|
174
|
-
var
|
|
452
|
+
var import_node_path4 = require("path");
|
|
175
453
|
|
|
176
454
|
// src/cache.ts
|
|
177
455
|
var import_node_fs = require("fs");
|
|
@@ -220,8 +498,8 @@ var PromptCache = class {
|
|
|
220
498
|
};
|
|
221
499
|
|
|
222
500
|
// src/composition/resolve-includes.ts
|
|
223
|
-
var
|
|
224
|
-
var
|
|
501
|
+
var import_promises3 = require("fs/promises");
|
|
502
|
+
var import_node_path3 = require("path");
|
|
225
503
|
|
|
226
504
|
// src/parser/parser.ts
|
|
227
505
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
@@ -257,10 +535,26 @@ var ResponseSchema = import_zod.z.object({
|
|
|
257
535
|
format: import_zod.z.enum(["text", "json", "markdown"]).optional(),
|
|
258
536
|
stream: import_zod.z.boolean().optional(),
|
|
259
537
|
schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
538
|
+
schema_ref: import_zod.z.string().min(1).optional(),
|
|
539
|
+
schema_source: import_zod.z.object({
|
|
540
|
+
mode: import_zod.z.enum(["inline", "schema_ref_json", "schema_ref_zod_module"]).optional(),
|
|
541
|
+
ref: import_zod.z.string().optional(),
|
|
542
|
+
resolved_path: import_zod.z.string().optional(),
|
|
543
|
+
hash: import_zod.z.string().optional()
|
|
544
|
+
}).optional(),
|
|
260
545
|
schema_name: import_zod.z.string().optional(),
|
|
261
546
|
schema_description: import_zod.z.string().optional(),
|
|
262
547
|
schema_strict: import_zod.z.boolean().optional()
|
|
263
548
|
});
|
|
549
|
+
var ResponseSchemaWithValidation = ResponseSchema.superRefine((value, ctx) => {
|
|
550
|
+
if (value.schema !== void 0 && value.schema_ref !== void 0) {
|
|
551
|
+
ctx.addIssue({
|
|
552
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
553
|
+
message: "response.schema and response.schema_ref are mutually exclusive",
|
|
554
|
+
path: ["schema_ref"]
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
});
|
|
264
558
|
var AnthropicProviderOptionsSchema = import_zod.z.object({
|
|
265
559
|
top_k: import_zod.z.number().int().min(0).optional(),
|
|
266
560
|
tool_choice: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
@@ -352,6 +646,8 @@ var ContextBuiltInValidatorSchema = import_zod.z.union([
|
|
|
352
646
|
]);
|
|
353
647
|
var ContextInputDefinitionObjectSchema = import_zod.z.object({
|
|
354
648
|
name: import_zod.z.string(),
|
|
649
|
+
optional: import_zod.z.boolean().optional(),
|
|
650
|
+
warnings: import_zod.z.boolean().optional(),
|
|
355
651
|
max_size: import_zod.z.number().int().positive().optional(),
|
|
356
652
|
trim: import_zod.z.union([import_zod.z.boolean(), import_zod.z.enum(["start", "end", "both"])]).optional(),
|
|
357
653
|
allow_regex: ContextRegexSchema.optional(),
|
|
@@ -381,7 +677,7 @@ var PromptAssetOverridesSchema = import_zod.z.object({
|
|
|
381
677
|
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
382
678
|
reasoning: ReasoningSchema.optional(),
|
|
383
679
|
sampling: SamplingSchema.optional(),
|
|
384
|
-
response:
|
|
680
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
385
681
|
cache: CacheSchema.optional(),
|
|
386
682
|
raw: RawProviderBodySchema.optional(),
|
|
387
683
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
@@ -399,7 +695,19 @@ var SectionsSchema = import_zod.z.object({
|
|
|
399
695
|
var PromptDefaultsSchema = import_zod.z.object({
|
|
400
696
|
provider: import_zod.z.enum(["openai", "openai-responses", "anthropic", "google", "gemini", "openrouter", "llmasaservice", "any"]).optional(),
|
|
401
697
|
model: import_zod.z.string().optional(),
|
|
698
|
+
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
699
|
+
reasoning: ReasoningSchema.optional(),
|
|
700
|
+
sampling: SamplingSchema.optional(),
|
|
701
|
+
response: ResponseSchema.optional(),
|
|
402
702
|
cache: CacheSchema.optional(),
|
|
703
|
+
raw: RawProviderBodySchema.optional(),
|
|
704
|
+
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
705
|
+
provider_options: ProviderOptionsSchema.optional(),
|
|
706
|
+
mcp: MCPSchema.optional(),
|
|
707
|
+
context: ContextSchema.optional(),
|
|
708
|
+
includes: import_zod.z.array(import_zod.z.string()).optional(),
|
|
709
|
+
environments: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
710
|
+
tiers: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
403
711
|
metadata: MetadataSchema.optional(),
|
|
404
712
|
sections: import_zod.z.object({
|
|
405
713
|
system_instructions: import_zod.z.string().optional()
|
|
@@ -414,7 +722,7 @@ var PromptAssetSchema = import_zod.z.object({
|
|
|
414
722
|
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
415
723
|
reasoning: ReasoningSchema.optional(),
|
|
416
724
|
sampling: SamplingSchema.optional(),
|
|
417
|
-
response:
|
|
725
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
418
726
|
cache: CacheSchema.optional(),
|
|
419
727
|
raw: RawProviderBodySchema.optional(),
|
|
420
728
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
@@ -595,27 +903,133 @@ function parsePrompt(content, filePath) {
|
|
|
595
903
|
sections,
|
|
596
904
|
source: filePath ? { file_path: filePath } : void 0
|
|
597
905
|
};
|
|
598
|
-
const asset = PromptAssetSchema.parse(raw);
|
|
906
|
+
const asset = PromptAssetSchema.parse(raw);
|
|
907
|
+
return {
|
|
908
|
+
asset,
|
|
909
|
+
raw: {
|
|
910
|
+
frontMatter,
|
|
911
|
+
body
|
|
912
|
+
}
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/parser/loader.ts
|
|
917
|
+
var import_promises2 = require("fs/promises");
|
|
918
|
+
var import_node_path2 = require("path");
|
|
919
|
+
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
920
|
+
|
|
921
|
+
// src/parser/response-schema-ref.ts
|
|
922
|
+
var import_promises = require("fs/promises");
|
|
923
|
+
var import_node_crypto = require("crypto");
|
|
924
|
+
var import_node_path = require("path");
|
|
925
|
+
var import_node_url = require("url");
|
|
926
|
+
var import_zod2 = require("zod");
|
|
927
|
+
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
928
|
+
var SUPPORTED_SCHEMA_REF_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
929
|
+
async function resolveJsonSchemaRef(schemaRef, promptFilePath) {
|
|
930
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
931
|
+
let raw;
|
|
932
|
+
try {
|
|
933
|
+
raw = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
934
|
+
} catch (error) {
|
|
935
|
+
const code = error.code;
|
|
936
|
+
if (code === "ENOENT") {
|
|
937
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
938
|
+
}
|
|
939
|
+
throw error;
|
|
940
|
+
}
|
|
941
|
+
let parsed;
|
|
942
|
+
try {
|
|
943
|
+
parsed = JSON.parse(raw);
|
|
944
|
+
} catch {
|
|
945
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" is not valid JSON`);
|
|
946
|
+
}
|
|
947
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
948
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" must resolve to a JSON object schema`);
|
|
949
|
+
}
|
|
950
|
+
return {
|
|
951
|
+
schema: parsed,
|
|
952
|
+
resolvedPath,
|
|
953
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(raw).digest("hex")
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
async function resolveZodSchemaRef(schemaRef, promptFilePath) {
|
|
957
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
958
|
+
let moduleSource;
|
|
959
|
+
try {
|
|
960
|
+
moduleSource = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
961
|
+
} catch (error) {
|
|
962
|
+
const code = error.code;
|
|
963
|
+
if (code === "ENOENT") {
|
|
964
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
965
|
+
}
|
|
966
|
+
throw error;
|
|
967
|
+
}
|
|
968
|
+
let imported;
|
|
969
|
+
try {
|
|
970
|
+
imported = await import((0, import_node_url.pathToFileURL)(resolvedPath).href);
|
|
971
|
+
} catch (error) {
|
|
972
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
973
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" could not be imported as a module (${message})`);
|
|
974
|
+
}
|
|
975
|
+
const mod = imported;
|
|
976
|
+
const candidate = mod.default ?? mod.schema;
|
|
977
|
+
if (!(candidate instanceof import_zod2.z.ZodType)) {
|
|
978
|
+
throw new Error('POK051: zod schema modules must export a Zod schema as default export or named export "schema"');
|
|
979
|
+
}
|
|
980
|
+
const jsonSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(candidate, {
|
|
981
|
+
target: "jsonSchema7",
|
|
982
|
+
$refStrategy: "none"
|
|
983
|
+
});
|
|
984
|
+
if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
|
|
985
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" did not produce a valid JSON schema object`);
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
schema: jsonSchema,
|
|
989
|
+
resolvedPath,
|
|
990
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(moduleSource).digest("hex")
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
async function resolveResponseSchemaRef(asset, promptFilePath) {
|
|
994
|
+
const schemaRef = asset.response?.schema_ref;
|
|
995
|
+
if (!schemaRef) return asset;
|
|
996
|
+
const ext = (0, import_node_path.extname)(schemaRef).toLowerCase();
|
|
997
|
+
if (!SUPPORTED_SCHEMA_REF_EXTENSIONS.has(ext)) {
|
|
998
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" has unsupported extension "${ext}". Use .json, .js, .mjs, or .cjs`);
|
|
999
|
+
}
|
|
1000
|
+
const resolved = ext === ".json" ? await resolveJsonSchemaRef(schemaRef, promptFilePath) : await resolveZodSchemaRef(schemaRef, promptFilePath);
|
|
599
1001
|
return {
|
|
600
|
-
asset,
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
1002
|
+
...asset,
|
|
1003
|
+
response: {
|
|
1004
|
+
...asset.response,
|
|
1005
|
+
schema: resolved.schema,
|
|
1006
|
+
schema_ref: void 0,
|
|
1007
|
+
schema_source: {
|
|
1008
|
+
mode: ext === ".json" ? "schema_ref_json" : "schema_ref_zod_module",
|
|
1009
|
+
ref: schemaRef,
|
|
1010
|
+
resolved_path: resolved.resolvedPath,
|
|
1011
|
+
hash: resolved.hash
|
|
1012
|
+
}
|
|
604
1013
|
}
|
|
605
1014
|
};
|
|
606
1015
|
}
|
|
607
1016
|
|
|
608
1017
|
// src/parser/loader.ts
|
|
609
|
-
var import_promises = require("fs/promises");
|
|
610
|
-
var import_node_path = require("path");
|
|
611
|
-
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
612
1018
|
var DEFAULTS_FILE_NAME = "defaults.md";
|
|
613
1019
|
async function loadPromptFile(filePath, options = {}) {
|
|
614
|
-
const content = await (0,
|
|
1020
|
+
const content = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
615
1021
|
const parsed = parsePrompt(content, filePath);
|
|
616
|
-
const root = options.defaultsRoot ?? (0,
|
|
1022
|
+
const root = options.defaultsRoot ?? (0, import_node_path2.dirname)(filePath);
|
|
617
1023
|
const defaults = await loadDefaultsForPath(filePath, root);
|
|
618
|
-
const
|
|
1024
|
+
const withDefaults = applyDefaults(parsed.asset, defaults);
|
|
1025
|
+
const resolved = await resolveResponseSchemaRef(withDefaults, filePath);
|
|
1026
|
+
const asset = resolved.response?.schema !== void 0 && !resolved.response?.schema_source ? {
|
|
1027
|
+
...resolved,
|
|
1028
|
+
response: {
|
|
1029
|
+
...resolved.response,
|
|
1030
|
+
schema_source: { mode: "inline" }
|
|
1031
|
+
}
|
|
1032
|
+
} : resolved;
|
|
619
1033
|
return {
|
|
620
1034
|
...parsed,
|
|
621
1035
|
asset
|
|
@@ -625,10 +1039,10 @@ async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
|
625
1039
|
const directories = getDirectoriesToCheck(filePath, defaultsRoot);
|
|
626
1040
|
let merged = {};
|
|
627
1041
|
for (const dir of directories) {
|
|
628
|
-
const defaultsPath = (0,
|
|
1042
|
+
const defaultsPath = (0, import_node_path2.join)(dir, DEFAULTS_FILE_NAME);
|
|
629
1043
|
try {
|
|
630
|
-
const defaultsContent = await (0,
|
|
631
|
-
const defaults = parseDefaults(defaultsContent);
|
|
1044
|
+
const defaultsContent = await (0, import_promises2.readFile)(defaultsPath, "utf-8");
|
|
1045
|
+
const defaults = normalizeDefaultIncludes(parseDefaults(defaultsContent), defaultsPath, filePath);
|
|
632
1046
|
merged = mergeDefaults(merged, defaults);
|
|
633
1047
|
} catch (error) {
|
|
634
1048
|
if (error.code !== "ENOENT") {
|
|
@@ -640,14 +1054,14 @@ async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
|
640
1054
|
}
|
|
641
1055
|
function getDirectoriesToCheck(filePath, defaultsRoot) {
|
|
642
1056
|
const dirs = [];
|
|
643
|
-
let current = (0,
|
|
644
|
-
const boundary = defaultsRoot ? (0,
|
|
1057
|
+
let current = (0, import_node_path2.resolve)((0, import_node_path2.dirname)(filePath));
|
|
1058
|
+
const boundary = defaultsRoot ? (0, import_node_path2.resolve)(defaultsRoot) : void 0;
|
|
645
1059
|
while (true) {
|
|
646
1060
|
dirs.unshift(current);
|
|
647
|
-
if (boundary && current === boundary || current === (0,
|
|
1061
|
+
if (boundary && current === boundary || current === (0, import_node_path2.dirname)(current)) {
|
|
648
1062
|
break;
|
|
649
1063
|
}
|
|
650
|
-
current = (0,
|
|
1064
|
+
current = (0, import_node_path2.dirname)(current);
|
|
651
1065
|
}
|
|
652
1066
|
return dirs;
|
|
653
1067
|
}
|
|
@@ -665,7 +1079,19 @@ function mergeDefaults(base, local) {
|
|
|
665
1079
|
return {
|
|
666
1080
|
provider: local.provider ?? base.provider,
|
|
667
1081
|
model: local.model ?? base.model,
|
|
1082
|
+
fallback_models: local.fallback_models ?? base.fallback_models,
|
|
1083
|
+
reasoning: mergeRecordBlock2(base.reasoning, local.reasoning),
|
|
1084
|
+
sampling: mergeRecordBlock2(base.sampling, local.sampling),
|
|
1085
|
+
response: mergeRecordBlock2(base.response, local.response),
|
|
668
1086
|
cache: mergeCache(base.cache, local.cache),
|
|
1087
|
+
raw: mergeRaw(base.raw, local.raw),
|
|
1088
|
+
tools: local.tools ?? base.tools,
|
|
1089
|
+
provider_options: mergeProviderOptions(base.provider_options, local.provider_options),
|
|
1090
|
+
mcp: mergeMcp(base.mcp, local.mcp),
|
|
1091
|
+
context: mergeContext(base.context, local.context),
|
|
1092
|
+
includes: local.includes ?? base.includes,
|
|
1093
|
+
environments: mergeOverrideMap(base.environments, local.environments),
|
|
1094
|
+
tiers: mergeOverrideMap(base.tiers, local.tiers),
|
|
669
1095
|
metadata: {
|
|
670
1096
|
...base.metadata ?? {},
|
|
671
1097
|
...local.metadata ?? {}
|
|
@@ -678,11 +1104,20 @@ function mergeDefaults(base, local) {
|
|
|
678
1104
|
}
|
|
679
1105
|
function applyDefaults(asset, defaults) {
|
|
680
1106
|
const cache = mergeCache(defaults.cache, asset.cache);
|
|
1107
|
+
const raw = mergeRaw(defaults.raw, asset.raw);
|
|
1108
|
+
const providerOptions = mergeProviderOptions(defaults.provider_options, asset.provider_options);
|
|
1109
|
+
const reasoning = mergeRecordBlock2(defaults.reasoning, asset.reasoning);
|
|
1110
|
+
const sampling = mergeRecordBlock2(defaults.sampling, asset.sampling);
|
|
1111
|
+
const response = mergeRecordBlock2(defaults.response, asset.response);
|
|
1112
|
+
const mcp = mergeMcp(defaults.mcp, asset.mcp);
|
|
1113
|
+
const context = mergeContext(defaults.context, asset.context);
|
|
1114
|
+
const environments = mergeOverrideMap(defaults.environments, asset.environments);
|
|
1115
|
+
const tiers = mergeOverrideMap(defaults.tiers, asset.tiers);
|
|
681
1116
|
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
682
1117
|
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
683
|
-
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0;
|
|
684
|
-
const
|
|
685
|
-
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !
|
|
1118
|
+
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0 || defaults.fallback_models !== void 0 || defaults.tools !== void 0 || defaults.includes !== void 0;
|
|
1119
|
+
const hasDefaultObjects = cache !== void 0 || raw !== void 0 || providerOptions !== void 0 || reasoning !== void 0 || sampling !== void 0 || response !== void 0 || mcp !== void 0 || context !== void 0 || environments !== void 0 || tiers !== void 0;
|
|
1120
|
+
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultObjects) {
|
|
686
1121
|
return asset;
|
|
687
1122
|
}
|
|
688
1123
|
const mergedMetadata = {
|
|
@@ -696,11 +1131,52 @@ function applyDefaults(asset, defaults) {
|
|
|
696
1131
|
...asset,
|
|
697
1132
|
provider: asset.provider ?? defaults.provider,
|
|
698
1133
|
model: asset.model ?? defaults.model,
|
|
1134
|
+
fallback_models: asset.fallback_models ?? defaults.fallback_models,
|
|
1135
|
+
reasoning,
|
|
1136
|
+
sampling,
|
|
1137
|
+
response,
|
|
699
1138
|
cache,
|
|
1139
|
+
raw,
|
|
1140
|
+
tools: asset.tools ?? defaults.tools,
|
|
1141
|
+
provider_options: providerOptions,
|
|
1142
|
+
mcp,
|
|
1143
|
+
context,
|
|
1144
|
+
includes: asset.includes ?? defaults.includes,
|
|
1145
|
+
environments,
|
|
1146
|
+
tiers,
|
|
700
1147
|
metadata,
|
|
701
1148
|
sections
|
|
702
1149
|
};
|
|
703
1150
|
}
|
|
1151
|
+
function normalizeDefaultIncludes(defaults, defaultsPath, filePath) {
|
|
1152
|
+
if (!defaults.includes) return defaults;
|
|
1153
|
+
const promptDir = (0, import_node_path2.dirname)(filePath);
|
|
1154
|
+
const defaultsDir = (0, import_node_path2.dirname)(defaultsPath);
|
|
1155
|
+
const includes = defaults.includes.map((includePath) => {
|
|
1156
|
+
const relativePath = (0, import_node_path2.relative)(promptDir, (0, import_node_path2.resolve)(defaultsDir, includePath)).replace(/\\/g, "/");
|
|
1157
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1158
|
+
});
|
|
1159
|
+
return {
|
|
1160
|
+
...defaults,
|
|
1161
|
+
includes
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
function mergeRecordBlock2(base, local) {
|
|
1165
|
+
if (base === void 0) return local;
|
|
1166
|
+
if (local === void 0) return base;
|
|
1167
|
+
return { ...base, ...local };
|
|
1168
|
+
}
|
|
1169
|
+
function mergeMcp(base, local) {
|
|
1170
|
+
return mergeRecordBlock2(base, local);
|
|
1171
|
+
}
|
|
1172
|
+
function mergeContext(base, local) {
|
|
1173
|
+
const merged = {
|
|
1174
|
+
...base ?? {},
|
|
1175
|
+
...local ?? {},
|
|
1176
|
+
history: mergeRecordBlock2(base?.history, local?.history)
|
|
1177
|
+
};
|
|
1178
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1179
|
+
}
|
|
704
1180
|
function mergeCache(base, local) {
|
|
705
1181
|
const merged = {
|
|
706
1182
|
...base ?? {},
|
|
@@ -728,406 +1204,198 @@ function mergeCache(base, local) {
|
|
|
728
1204
|
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
729
1205
|
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
730
1206
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
let mergedSystemInstructions = "";
|
|
744
|
-
for (const includePath of asset.includes) {
|
|
745
|
-
const fullPath = (0, import_node_path2.resolve)(baseDir, includePath);
|
|
746
|
-
if (visited.has(fullPath)) {
|
|
747
|
-
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
748
|
-
}
|
|
749
|
-
const content = await (0, import_promises2.readFile)(fullPath, "utf-8");
|
|
750
|
-
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
751
|
-
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
752
|
-
if (resolved.sections?.system_instructions) {
|
|
753
|
-
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
const localSystem = asset.sections?.system_instructions ?? "";
|
|
757
|
-
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
758
|
-
return {
|
|
759
|
-
...asset,
|
|
760
|
-
sections: {
|
|
761
|
-
...asset.sections,
|
|
762
|
-
system_instructions: combinedSystem
|
|
763
|
-
},
|
|
764
|
-
// Drop includes from the resolved asset — they've been inlined
|
|
765
|
-
includes: void 0
|
|
766
|
-
};
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// src/prompt-resolution.ts
|
|
770
|
-
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
771
|
-
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
772
|
-
function withPromptResolutionDefaults(config) {
|
|
773
|
-
return {
|
|
774
|
-
...config,
|
|
775
|
-
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
776
|
-
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
var sharedPromptCache = new PromptCache();
|
|
780
|
-
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
781
|
-
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
782
|
-
const mode = resolvedConfig.mode ?? "auto";
|
|
783
|
-
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
784
|
-
const compiledFile = (0, import_node_path3.resolve)(resolvedConfig.compiledDir, promptPath + ".json");
|
|
785
|
-
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
786
|
-
if (mode === "auto") {
|
|
787
|
-
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
788
|
-
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
789
|
-
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
790
|
-
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
791
|
-
if (sourceMtime > compiledMtime) {
|
|
792
|
-
console.warn(
|
|
793
|
-
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
794
|
-
Run "promptopskit compile" or switch to source-only mode.`
|
|
795
|
-
);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
const content = await (0, import_promises3.readFile)(compiledFile, "utf-8");
|
|
800
|
-
return JSON.parse(content);
|
|
801
|
-
}
|
|
802
|
-
if (mode === "compiled-only") {
|
|
803
|
-
throw new Error(
|
|
804
|
-
`Compiled artifact not found: ${compiledFile}
|
|
805
|
-
Run "promptopskit compile" to generate it.`
|
|
806
|
-
);
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
if (mode !== "compiled-only") {
|
|
810
|
-
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
811
|
-
if (resolvedConfig.cache !== false) {
|
|
812
|
-
const cached = promptCache.get(sourceFile);
|
|
813
|
-
if (cached) {
|
|
814
|
-
return cached;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
if (!(0, import_node_fs2.existsSync)(sourceFile)) {
|
|
818
|
-
const paths = [sourceFile];
|
|
819
|
-
if (resolvedConfig.compiledDir) {
|
|
820
|
-
paths.unshift((0, import_node_path3.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
821
|
-
}
|
|
822
|
-
throw new Error(
|
|
823
|
-
`Prompt not found: "${promptPath}"
|
|
824
|
-
Searched:
|
|
825
|
-
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
826
|
-
);
|
|
827
|
-
}
|
|
828
|
-
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
829
|
-
if (resolvedConfig.cache !== false) {
|
|
830
|
-
promptCache.set(sourceFile, asset);
|
|
831
|
-
}
|
|
832
|
-
return asset;
|
|
833
|
-
}
|
|
834
|
-
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
835
|
-
}
|
|
836
|
-
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
837
|
-
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
838
|
-
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
839
|
-
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
840
|
-
if (asset.includes && asset.includes.length > 0 && (0, import_node_fs2.existsSync)(sourceFile)) {
|
|
841
|
-
asset = await resolveIncludes(asset, sourceFile);
|
|
842
|
-
}
|
|
843
|
-
asset = applyOverrides(asset, {
|
|
844
|
-
environment: options.environment,
|
|
845
|
-
tier: options.tier,
|
|
846
|
-
runtime: options.runtime
|
|
847
|
-
});
|
|
848
|
-
return asset;
|
|
849
|
-
}
|
|
850
|
-
function resolveInlinePromptSource(source, options = {}) {
|
|
851
|
-
const { asset } = parsePrompt(source);
|
|
852
|
-
return applyOverrides(asset, {
|
|
853
|
-
environment: options.environment,
|
|
854
|
-
tier: options.tier,
|
|
855
|
-
runtime: options.runtime
|
|
856
|
-
});
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
// src/context.ts
|
|
860
|
-
var textEncoder = new TextEncoder();
|
|
861
|
-
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
862
|
-
var REJECT_SECRETS_FLAGS = "i";
|
|
863
|
-
function getContextInputs(asset) {
|
|
864
|
-
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
865
|
-
}
|
|
866
|
-
function normalizeContextInput(input) {
|
|
867
|
-
if (typeof input === "string") {
|
|
868
|
-
return { name: input };
|
|
869
|
-
}
|
|
870
|
-
return {
|
|
871
|
-
name: input.name,
|
|
872
|
-
max_size: input.max_size,
|
|
873
|
-
trim: input.trim,
|
|
874
|
-
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
875
|
-
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
876
|
-
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
877
|
-
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
function normalizeContextRegex(value) {
|
|
881
|
-
if (value === void 0) {
|
|
882
|
-
return void 0;
|
|
883
|
-
}
|
|
884
|
-
if (typeof value === "string") {
|
|
885
|
-
const literal = parseRegexLiteral(value);
|
|
886
|
-
if (value.startsWith("/") && !literal) {
|
|
887
|
-
return {
|
|
888
|
-
pattern: value,
|
|
889
|
-
flags: "",
|
|
890
|
-
raw: value,
|
|
891
|
-
invalidLiteral: true
|
|
892
|
-
};
|
|
893
|
-
}
|
|
894
|
-
return {
|
|
895
|
-
pattern: literal?.pattern ?? value,
|
|
896
|
-
flags: literal?.flags ?? "",
|
|
897
|
-
raw: value
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
return {
|
|
901
|
-
pattern: value.pattern,
|
|
902
|
-
flags: value.flags ?? "",
|
|
903
|
-
raw: JSON.stringify(value),
|
|
904
|
-
returnMessage: value.return_message
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
function normalizeBuiltInValidator(value) {
|
|
908
|
-
if (value === void 0 || value === false) {
|
|
909
|
-
return void 0;
|
|
910
|
-
}
|
|
911
|
-
if (value === true) {
|
|
912
|
-
return {};
|
|
913
|
-
}
|
|
914
|
-
return {
|
|
915
|
-
returnMessage: value.return_message
|
|
916
|
-
};
|
|
917
|
-
}
|
|
918
|
-
function parseRegexLiteral(value) {
|
|
919
|
-
if (!value.startsWith("/")) {
|
|
920
|
-
return void 0;
|
|
921
|
-
}
|
|
922
|
-
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
923
|
-
if (value[index] !== "/") {
|
|
924
|
-
continue;
|
|
925
|
-
}
|
|
926
|
-
let backslashCount = 0;
|
|
927
|
-
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
928
|
-
backslashCount += 1;
|
|
929
|
-
}
|
|
930
|
-
if (backslashCount % 2 === 1) {
|
|
931
|
-
continue;
|
|
932
|
-
}
|
|
933
|
-
return {
|
|
934
|
-
pattern: value.slice(1, index),
|
|
935
|
-
flags: value.slice(index + 1)
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
return void 0;
|
|
939
|
-
}
|
|
940
|
-
function formatInvalidContextRegexMessage(details) {
|
|
941
|
-
return [
|
|
942
|
-
`Invalid context regex for prompt "${details.promptId}"`,
|
|
943
|
-
`variable "${details.variable}"`,
|
|
944
|
-
`field "${details.field}"`,
|
|
945
|
-
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
946
|
-
].join(", ");
|
|
947
|
-
}
|
|
948
|
-
function compileContextRegex(regex, details) {
|
|
949
|
-
if (regex.invalidLiteral) {
|
|
950
|
-
throw new Error(
|
|
951
|
-
`POK013: ${formatInvalidContextRegexMessage({
|
|
952
|
-
...details,
|
|
953
|
-
raw: regex.raw,
|
|
954
|
-
reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
|
|
955
|
-
})}`
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
try {
|
|
959
|
-
return new RegExp(regex.pattern, regex.flags);
|
|
960
|
-
} catch (error) {
|
|
961
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
962
|
-
throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
function getRejectSecretsRegex() {
|
|
966
|
-
return {
|
|
967
|
-
pattern: REJECT_SECRETS_PATTERN,
|
|
968
|
-
flags: REJECT_SECRETS_FLAGS,
|
|
969
|
-
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
1207
|
+
function mergeRaw(base, local) {
|
|
1208
|
+
const merged = {
|
|
1209
|
+
...base ?? {},
|
|
1210
|
+
...local ?? {},
|
|
1211
|
+
openai: mergeRecordBlock2(base?.openai, local?.openai),
|
|
1212
|
+
"openai-responses": mergeRecordBlock2(base?.["openai-responses"], local?.["openai-responses"]),
|
|
1213
|
+
openai_responses: mergeRecordBlock2(base?.openai_responses, local?.openai_responses),
|
|
1214
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1215
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1216
|
+
google: mergeRecordBlock2(base?.google, local?.google),
|
|
1217
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1218
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
970
1219
|
};
|
|
1220
|
+
removeEmptyProviderBlocks(merged);
|
|
1221
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
971
1222
|
}
|
|
972
|
-
function
|
|
973
|
-
|
|
1223
|
+
function mergeProviderOptions(base, local) {
|
|
1224
|
+
const merged = {
|
|
1225
|
+
...base ?? {},
|
|
1226
|
+
...local ?? {},
|
|
1227
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1228
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1229
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1230
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
1231
|
+
};
|
|
1232
|
+
removeEmptyProviderBlocks(merged);
|
|
1233
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
974
1234
|
}
|
|
975
|
-
function
|
|
976
|
-
|
|
977
|
-
|
|
1235
|
+
function mergeOverrideMap(base, local) {
|
|
1236
|
+
const merged = { ...base ?? {} };
|
|
1237
|
+
for (const [name, localOverride] of Object.entries(local ?? {})) {
|
|
1238
|
+
merged[name] = mergeOverrideConfig(merged[name], localOverride);
|
|
978
1239
|
}
|
|
979
|
-
return
|
|
1240
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
980
1241
|
}
|
|
981
|
-
function
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
}
|
|
986
|
-
const
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1242
|
+
function mergeOverrideConfig(base, local) {
|
|
1243
|
+
const merged = {
|
|
1244
|
+
...base ?? {},
|
|
1245
|
+
...local
|
|
1246
|
+
};
|
|
1247
|
+
const reasoning = mergeRecordBlock2(base?.reasoning, local.reasoning);
|
|
1248
|
+
const sampling = mergeRecordBlock2(base?.sampling, local.sampling);
|
|
1249
|
+
const response = mergeRecordBlock2(base?.response, local.response);
|
|
1250
|
+
const cache = mergeCache(base?.cache, local.cache);
|
|
1251
|
+
const raw = mergeRaw(base?.raw, local.raw);
|
|
1252
|
+
const providerOptions = mergeProviderOptions(base?.provider_options, local.provider_options);
|
|
1253
|
+
if (reasoning !== void 0) merged.reasoning = reasoning;
|
|
1254
|
+
if (sampling !== void 0) merged.sampling = sampling;
|
|
1255
|
+
if (response !== void 0) merged.response = response;
|
|
1256
|
+
if (cache !== void 0) merged.cache = cache;
|
|
1257
|
+
if (raw !== void 0) merged.raw = raw;
|
|
1258
|
+
if (providerOptions !== void 0) merged.provider_options = providerOptions;
|
|
1259
|
+
return merged;
|
|
1260
|
+
}
|
|
1261
|
+
function removeEmptyProviderBlocks(value) {
|
|
1262
|
+
for (const key of Object.keys(value)) {
|
|
1263
|
+
const block = value[key];
|
|
1264
|
+
if (block === void 0) {
|
|
1265
|
+
delete value[key];
|
|
1266
|
+
continue;
|
|
999
1267
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
let collected = "";
|
|
1003
|
-
let size = 0;
|
|
1004
|
-
for (const char of characters) {
|
|
1005
|
-
const charSize = measureContextValueSize(char);
|
|
1006
|
-
if (size + charSize > maxSize) {
|
|
1007
|
-
break;
|
|
1268
|
+
if (block !== null && typeof block === "object" && !Array.isArray(block) && Object.keys(block).length === 0) {
|
|
1269
|
+
delete value[key];
|
|
1008
1270
|
}
|
|
1009
|
-
collected += char;
|
|
1010
|
-
size += charSize;
|
|
1011
1271
|
}
|
|
1012
|
-
return collected;
|
|
1013
1272
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
actualSize
|
|
1032
|
-
});
|
|
1033
|
-
}
|
|
1273
|
+
|
|
1274
|
+
// src/composition/resolve-includes.ts
|
|
1275
|
+
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
1276
|
+
if (!asset.includes || asset.includes.length === 0) {
|
|
1277
|
+
return asset;
|
|
1278
|
+
}
|
|
1279
|
+
const baseDir = (0, import_node_path3.dirname)(basePath);
|
|
1280
|
+
const resolvedPath = (0, import_node_path3.resolve)(basePath);
|
|
1281
|
+
if (visited.has(resolvedPath)) {
|
|
1282
|
+
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
1283
|
+
}
|
|
1284
|
+
visited.add(resolvedPath);
|
|
1285
|
+
let mergedSystemInstructions = "";
|
|
1286
|
+
for (const includePath of asset.includes) {
|
|
1287
|
+
const fullPath = (0, import_node_path3.resolve)(baseDir, includePath);
|
|
1288
|
+
if (visited.has(fullPath)) {
|
|
1289
|
+
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
1034
1290
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1291
|
+
const content = await (0, import_promises3.readFile)(fullPath, "utf-8");
|
|
1292
|
+
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
1293
|
+
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
1294
|
+
if (resolved.sections?.system_instructions) {
|
|
1295
|
+
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
1037
1296
|
}
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1297
|
+
}
|
|
1298
|
+
const localSystem = asset.sections?.system_instructions ?? "";
|
|
1299
|
+
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
1300
|
+
return {
|
|
1301
|
+
...asset,
|
|
1302
|
+
sections: {
|
|
1303
|
+
...asset.sections,
|
|
1304
|
+
system_instructions: combinedSystem
|
|
1305
|
+
},
|
|
1306
|
+
// Drop includes from the resolved asset — they've been inlined
|
|
1307
|
+
includes: void 0
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// src/prompt-resolution.ts
|
|
1312
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
1313
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
1314
|
+
function withPromptResolutionDefaults(config) {
|
|
1315
|
+
return {
|
|
1316
|
+
...config,
|
|
1317
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
1318
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
var sharedPromptCache = new PromptCache();
|
|
1322
|
+
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
1323
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1324
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
1325
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
1326
|
+
const compiledFile = (0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json");
|
|
1327
|
+
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
1328
|
+
if (mode === "auto") {
|
|
1329
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1330
|
+
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1331
|
+
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
1332
|
+
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
1333
|
+
if (sourceMtime > compiledMtime) {
|
|
1334
|
+
console.warn(
|
|
1335
|
+
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
1336
|
+
Run "promptopskit compile" or switch to source-only mode.`
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1057
1339
|
}
|
|
1058
|
-
throw new Error(
|
|
1059
|
-
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
1060
|
-
);
|
|
1061
1340
|
}
|
|
1341
|
+
const content = await (0, import_promises4.readFile)(compiledFile, "utf-8");
|
|
1342
|
+
return JSON.parse(content);
|
|
1062
1343
|
}
|
|
1063
|
-
if (
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
code: "POK032",
|
|
1077
|
-
variable: input.name,
|
|
1078
|
-
field: "deny_regex"
|
|
1079
|
-
}
|
|
1080
|
-
};
|
|
1081
|
-
}
|
|
1082
|
-
throw new Error(
|
|
1083
|
-
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
1084
|
-
);
|
|
1344
|
+
if (mode === "compiled-only") {
|
|
1345
|
+
throw new Error(
|
|
1346
|
+
`Compiled artifact not found: ${compiledFile}
|
|
1347
|
+
Run "promptopskit compile" to generate it.`
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
if (mode !== "compiled-only") {
|
|
1352
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1353
|
+
if (resolvedConfig.cache !== false) {
|
|
1354
|
+
const cached = promptCache.get(sourceFile);
|
|
1355
|
+
if (cached) {
|
|
1356
|
+
return cached;
|
|
1085
1357
|
}
|
|
1086
1358
|
}
|
|
1087
|
-
if (
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
shortCircuit: {
|
|
1092
|
-
returnMessage: input.non_empty.returnMessage,
|
|
1093
|
-
code: "POK033",
|
|
1094
|
-
variable: input.name,
|
|
1095
|
-
field: "non_empty"
|
|
1096
|
-
}
|
|
1097
|
-
};
|
|
1359
|
+
if (!(0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1360
|
+
const paths = [sourceFile];
|
|
1361
|
+
if (resolvedConfig.compiledDir) {
|
|
1362
|
+
paths.unshift((0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
1098
1363
|
}
|
|
1099
1364
|
throw new Error(
|
|
1100
|
-
`
|
|
1365
|
+
`Prompt not found: "${promptPath}"
|
|
1366
|
+
Searched:
|
|
1367
|
+
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
1101
1368
|
);
|
|
1102
1369
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
variable: input.name,
|
|
1107
|
-
field: "reject_secrets"
|
|
1108
|
-
});
|
|
1109
|
-
if (matcher.test(candidate)) {
|
|
1110
|
-
if (input.reject_secrets.returnMessage) {
|
|
1111
|
-
return {
|
|
1112
|
-
variables: sanitized,
|
|
1113
|
-
shortCircuit: {
|
|
1114
|
-
returnMessage: input.reject_secrets.returnMessage,
|
|
1115
|
-
code: "POK034",
|
|
1116
|
-
variable: input.name,
|
|
1117
|
-
field: "reject_secrets"
|
|
1118
|
-
}
|
|
1119
|
-
};
|
|
1120
|
-
}
|
|
1121
|
-
throw new Error(
|
|
1122
|
-
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
1123
|
-
);
|
|
1124
|
-
}
|
|
1370
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
1371
|
+
if (resolvedConfig.cache !== false) {
|
|
1372
|
+
promptCache.set(sourceFile, asset);
|
|
1125
1373
|
}
|
|
1374
|
+
return asset;
|
|
1126
1375
|
}
|
|
1127
|
-
|
|
1376
|
+
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
1128
1377
|
}
|
|
1129
|
-
function
|
|
1130
|
-
|
|
1378
|
+
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
1379
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1380
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
1381
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1382
|
+
if (asset.includes && asset.includes.length > 0 && (0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1383
|
+
asset = await resolveIncludes(asset, sourceFile);
|
|
1384
|
+
}
|
|
1385
|
+
asset = applyOverrides(asset, {
|
|
1386
|
+
environment: options.environment,
|
|
1387
|
+
tier: options.tier,
|
|
1388
|
+
runtime: options.runtime
|
|
1389
|
+
});
|
|
1390
|
+
return asset;
|
|
1391
|
+
}
|
|
1392
|
+
function resolveInlinePromptSource(source, options = {}) {
|
|
1393
|
+
const { asset } = parsePrompt(source);
|
|
1394
|
+
return applyOverrides(asset, {
|
|
1395
|
+
environment: options.environment,
|
|
1396
|
+
tier: options.tier,
|
|
1397
|
+
runtime: options.runtime
|
|
1398
|
+
});
|
|
1131
1399
|
}
|
|
1132
1400
|
|
|
1133
1401
|
// src/history.ts
|