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