promptopskit 0.5.0 → 0.7.0
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-QK3WKE3K.js → chunk-35NN5F6O.js} +2 -2
- package/dist/{chunk-D75HKF64.js → chunk-3G3EAV7H.js} +2 -2
- package/dist/{chunk-LNGHGGJN.js → chunk-6NOUETAC.js} +2 -2
- package/dist/{chunk-KN7H4JRK.js → chunk-F552OBUV.js} +619 -502
- package/dist/chunk-F552OBUV.js.map +1 -0
- package/dist/{chunk-6BOUQVSX.js → chunk-FICB2ZSK.js} +3 -3
- package/dist/{chunk-6VLKZCNS.js → chunk-OWMP5NMV.js} +2 -2
- package/dist/{chunk-IN4KT5EU.js → chunk-R65RAHAG.js} +3 -3
- package/dist/{chunk-K6ZU3CGV.js → chunk-ULVY473P.js} +306 -17
- package/dist/chunk-ULVY473P.js.map +1 -0
- package/dist/cli/index.js +446 -103
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1223 -772
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +67 -18
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +902 -502
- 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 +902 -502
- 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 +901 -501
- 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 +902 -502
- 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 +902 -502
- 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 +902 -502
- 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-DBcSns_b.d.cts} +732 -206
- package/dist/{schema-D-RI4w-k.d.ts → schema-DBcSns_b.d.ts} +732 -206
- package/dist/testing.cjs +54 -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-8T2D5KB5.d.cts} +20 -2
- package/dist/{types-DbTAjlTN.d.cts → types-BlLXT5Qb.d.ts} +20 -2
- 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-QK3WKE3K.js.map → chunk-35NN5F6O.js.map} +0 -0
- /package/dist/{chunk-D75HKF64.js.map → chunk-3G3EAV7H.js.map} +0 -0
- /package/dist/{chunk-LNGHGGJN.js.map → chunk-6NOUETAC.js.map} +0 -0
- /package/dist/{chunk-6BOUQVSX.js.map → chunk-FICB2ZSK.js.map} +0 -0
- /package/dist/{chunk-6VLKZCNS.js.map → chunk-OWMP5NMV.js.map} +0 -0
- /package/dist/{chunk-IN4KT5EU.js.map → chunk-R65RAHAG.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,8 @@ __export(src_exports, {
|
|
|
37
37
|
PromptAssetOverridesSchema: () => PromptAssetOverridesSchema,
|
|
38
38
|
PromptAssetSchema: () => PromptAssetSchema,
|
|
39
39
|
PromptOpsKit: () => PromptOpsKit,
|
|
40
|
+
THETOKENCOMPANY_DEFAULT_BASE_URL: () => THETOKENCOMPANY_DEFAULT_BASE_URL,
|
|
41
|
+
THETOKENCOMPANY_DEFAULT_MODEL: () => THETOKENCOMPANY_DEFAULT_MODEL,
|
|
40
42
|
anthropicAdapter: () => anthropicAdapter,
|
|
41
43
|
applyOverrides: () => applyOverrides,
|
|
42
44
|
applyUsageTapEntitlements: () => applyUsageTapEntitlements,
|
|
@@ -72,7 +74,7 @@ __export(src_exports, {
|
|
|
72
74
|
withUsageTapCall: () => withUsageTapCall
|
|
73
75
|
});
|
|
74
76
|
module.exports = __toCommonJS(src_exports);
|
|
75
|
-
var
|
|
77
|
+
var import_node_path5 = require("path");
|
|
76
78
|
|
|
77
79
|
// src/renderer/interpolate.ts
|
|
78
80
|
var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
@@ -80,12 +82,13 @@ var ESCAPED_OPEN = /\\\{\\\{/g;
|
|
|
80
82
|
var ESCAPE_PLACEHOLDER = "\0ESCAPED_OPEN\0";
|
|
81
83
|
function interpolate(template, variables, options = {}) {
|
|
82
84
|
const { strict = false } = options;
|
|
85
|
+
const optionalVariables = new Set(options.optionalVariables ?? []);
|
|
83
86
|
let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);
|
|
84
87
|
result = result.replace(VARIABLE_RE, (match, name) => {
|
|
85
88
|
if (name in variables) {
|
|
86
89
|
return variables[name];
|
|
87
90
|
}
|
|
88
|
-
if (strict) {
|
|
91
|
+
if (strict && !optionalVariables.has(name)) {
|
|
89
92
|
throw new Error(`Missing required variable: "${name}"`);
|
|
90
93
|
}
|
|
91
94
|
return match;
|
|
@@ -103,159 +106,473 @@ function extractVariables(template) {
|
|
|
103
106
|
return [...vars];
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
// src/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
asset.sections.system_instructions,
|
|
113
|
-
variables,
|
|
114
|
-
{ strict }
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
if (asset.sections.prompt_template) {
|
|
118
|
-
result.prompt_template = interpolate(
|
|
119
|
-
asset.sections.prompt_template,
|
|
120
|
-
variables,
|
|
121
|
-
{ strict }
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
return result;
|
|
109
|
+
// src/context.ts
|
|
110
|
+
var textEncoder = new TextEncoder();
|
|
111
|
+
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
112
|
+
var REJECT_SECRETS_FLAGS = "i";
|
|
113
|
+
function getContextInputs(asset) {
|
|
114
|
+
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
125
115
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let result = { ...asset };
|
|
130
|
-
if (options.environment && result.environments?.[options.environment]) {
|
|
131
|
-
result = mergeOverride(result, result.environments[options.environment]);
|
|
116
|
+
function normalizeContextInput(input) {
|
|
117
|
+
if (typeof input === "string") {
|
|
118
|
+
return { name: input };
|
|
132
119
|
}
|
|
133
|
-
|
|
134
|
-
|
|
120
|
+
return {
|
|
121
|
+
name: input.name,
|
|
122
|
+
optional: input.optional,
|
|
123
|
+
warnings: input.warnings,
|
|
124
|
+
max_size: input.max_size,
|
|
125
|
+
trim: input.trim,
|
|
126
|
+
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
127
|
+
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
128
|
+
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
129
|
+
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function areContextInputWarningsEnabled(input) {
|
|
133
|
+
return input.warnings !== false;
|
|
134
|
+
}
|
|
135
|
+
function normalizeContextRegex(value) {
|
|
136
|
+
if (value === void 0) {
|
|
137
|
+
return void 0;
|
|
135
138
|
}
|
|
136
|
-
if (
|
|
137
|
-
|
|
139
|
+
if (typeof value === "string") {
|
|
140
|
+
const literal = parseRegexLiteral(value);
|
|
141
|
+
if (value.startsWith("/") && !literal) {
|
|
142
|
+
return {
|
|
143
|
+
pattern: value,
|
|
144
|
+
flags: "",
|
|
145
|
+
raw: value,
|
|
146
|
+
invalidLiteral: true
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
pattern: literal?.pattern ?? value,
|
|
151
|
+
flags: literal?.flags ?? "",
|
|
152
|
+
raw: value
|
|
153
|
+
};
|
|
138
154
|
}
|
|
139
|
-
return
|
|
155
|
+
return {
|
|
156
|
+
pattern: value.pattern,
|
|
157
|
+
flags: value.flags ?? "",
|
|
158
|
+
raw: JSON.stringify(value),
|
|
159
|
+
returnMessage: value.return_message
|
|
160
|
+
};
|
|
140
161
|
}
|
|
141
|
-
function
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
145
|
-
if (override.tools !== void 0) result.tools = override.tools;
|
|
146
|
-
if (override.reasoning !== void 0) {
|
|
147
|
-
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
162
|
+
function normalizeBuiltInValidator(value) {
|
|
163
|
+
if (value === void 0 || value === false) {
|
|
164
|
+
return void 0;
|
|
148
165
|
}
|
|
149
|
-
if (
|
|
150
|
-
|
|
166
|
+
if (value === true) {
|
|
167
|
+
return {};
|
|
151
168
|
}
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
return {
|
|
170
|
+
returnMessage: value.return_message
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function parseRegexLiteral(value) {
|
|
174
|
+
if (!value.startsWith("/")) {
|
|
175
|
+
return void 0;
|
|
154
176
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
177
|
+
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
178
|
+
if (value[index] !== "/") {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
let backslashCount = 0;
|
|
182
|
+
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
183
|
+
backslashCount += 1;
|
|
184
|
+
}
|
|
185
|
+
if (backslashCount % 2 === 1) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
pattern: value.slice(1, index),
|
|
190
|
+
flags: value.slice(index + 1)
|
|
163
191
|
};
|
|
164
192
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
return void 0;
|
|
194
|
+
}
|
|
195
|
+
function formatInvalidContextRegexMessage(details) {
|
|
196
|
+
return [
|
|
197
|
+
`Invalid context regex for prompt "${details.promptId}"`,
|
|
198
|
+
`variable "${details.variable}"`,
|
|
199
|
+
`field "${details.field}"`,
|
|
200
|
+
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
201
|
+
].join(", ");
|
|
202
|
+
}
|
|
203
|
+
function compileContextRegex(regex, details) {
|
|
204
|
+
if (regex.invalidLiteral) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
`POK013: ${formatInvalidContextRegexMessage({
|
|
207
|
+
...details,
|
|
208
|
+
raw: regex.raw,
|
|
209
|
+
reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
|
|
210
|
+
})}`
|
|
211
|
+
);
|
|
178
212
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
...result.provider_options?.anthropic,
|
|
185
|
-
...override.provider_options.anthropic
|
|
186
|
-
},
|
|
187
|
-
gemini: {
|
|
188
|
-
...result.provider_options?.gemini,
|
|
189
|
-
...override.provider_options.gemini
|
|
190
|
-
},
|
|
191
|
-
openrouter: {
|
|
192
|
-
...result.provider_options?.openrouter,
|
|
193
|
-
...override.provider_options.openrouter
|
|
194
|
-
},
|
|
195
|
-
llmasaservice: {
|
|
196
|
-
...result.provider_options?.llmasaservice,
|
|
197
|
-
...override.provider_options.llmasaservice
|
|
198
|
-
}
|
|
199
|
-
};
|
|
213
|
+
try {
|
|
214
|
+
return new RegExp(regex.pattern, regex.flags);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
217
|
+
throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
|
|
200
218
|
}
|
|
201
|
-
return result;
|
|
202
219
|
}
|
|
203
|
-
function
|
|
204
|
-
|
|
205
|
-
|
|
220
|
+
function getRejectSecretsRegex() {
|
|
221
|
+
return {
|
|
222
|
+
pattern: REJECT_SECRETS_PATTERN,
|
|
223
|
+
flags: REJECT_SECRETS_FLAGS,
|
|
224
|
+
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
225
|
+
};
|
|
206
226
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
227
|
+
function isTrimEnabled(mode) {
|
|
228
|
+
return mode === true || mode === "start" || mode === "end" || mode === "both";
|
|
229
|
+
}
|
|
230
|
+
function normalizeTrimMode(mode) {
|
|
231
|
+
if (mode === "start") {
|
|
232
|
+
return "start";
|
|
212
233
|
}
|
|
213
|
-
return
|
|
214
|
-
environment: runtime.environment,
|
|
215
|
-
tier: runtime.tier,
|
|
216
|
-
runtime: runtime.runtime
|
|
217
|
-
});
|
|
234
|
+
return "end";
|
|
218
235
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
var import_node_path3 = require("path");
|
|
224
|
-
|
|
225
|
-
// src/cache.ts
|
|
226
|
-
var import_node_fs = require("fs");
|
|
227
|
-
var PromptCache = class {
|
|
228
|
-
cache = /* @__PURE__ */ new Map();
|
|
229
|
-
maxSize;
|
|
230
|
-
constructor(maxSize = 100) {
|
|
231
|
-
this.maxSize = maxSize;
|
|
236
|
+
function trimToMaxSize(value, maxSize, mode) {
|
|
237
|
+
const measured = measureContextValueSize(value);
|
|
238
|
+
if (measured <= maxSize) {
|
|
239
|
+
return value;
|
|
232
240
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
const characters = Array.from(value);
|
|
242
|
+
const normalizedMode = normalizeTrimMode(mode);
|
|
243
|
+
if (normalizedMode === "start") {
|
|
244
|
+
let collected2 = "";
|
|
245
|
+
let size2 = 0;
|
|
246
|
+
for (let i = characters.length - 1; i >= 0; i -= 1) {
|
|
247
|
+
const next = characters[i];
|
|
248
|
+
const charSize = measureContextValueSize(next);
|
|
249
|
+
if (size2 + charSize > maxSize) {
|
|
250
|
+
break;
|
|
241
251
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return void 0;
|
|
252
|
+
collected2 = next + collected2;
|
|
253
|
+
size2 += charSize;
|
|
245
254
|
}
|
|
246
|
-
|
|
247
|
-
this.cache.set(filePath, entry);
|
|
248
|
-
return entry.value;
|
|
255
|
+
return collected2;
|
|
249
256
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
let collected = "";
|
|
258
|
+
let size = 0;
|
|
259
|
+
for (const char of characters) {
|
|
260
|
+
const charSize = measureContextValueSize(char);
|
|
261
|
+
if (size + charSize > maxSize) {
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
collected += char;
|
|
265
|
+
size += charSize;
|
|
266
|
+
}
|
|
267
|
+
return collected;
|
|
268
|
+
}
|
|
269
|
+
function sanitizeContextVariables(asset, variables = {}, options = {}) {
|
|
270
|
+
const { onContextOverflow } = options;
|
|
271
|
+
const sanitized = { ...variables };
|
|
272
|
+
for (const input of getContextInputs(asset)) {
|
|
273
|
+
const value = sanitized[input.name];
|
|
274
|
+
if (value === void 0) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
let candidate = value;
|
|
278
|
+
if (input.max_size !== void 0) {
|
|
279
|
+
const actualSize = measureContextValueSize(candidate);
|
|
280
|
+
if (actualSize > input.max_size && onContextOverflow) {
|
|
281
|
+
candidate = onContextOverflow({
|
|
282
|
+
promptId: asset.id,
|
|
283
|
+
variable: input.name,
|
|
284
|
+
value: candidate,
|
|
285
|
+
maxSize: input.max_size,
|
|
286
|
+
actualSize
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (isTrimEnabled(input.trim) && input.max_size !== void 0) {
|
|
291
|
+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
|
|
292
|
+
}
|
|
293
|
+
sanitized[input.name] = candidate;
|
|
294
|
+
if (input.allow_regex) {
|
|
295
|
+
const candidate2 = sanitized[input.name];
|
|
296
|
+
const matcher = compileContextRegex(input.allow_regex, {
|
|
297
|
+
promptId: asset.id,
|
|
298
|
+
variable: input.name,
|
|
299
|
+
field: "allow_regex"
|
|
300
|
+
});
|
|
301
|
+
if (!matcher.test(candidate2)) {
|
|
302
|
+
if (input.allow_regex.returnMessage) {
|
|
303
|
+
return {
|
|
304
|
+
variables: sanitized,
|
|
305
|
+
shortCircuit: {
|
|
306
|
+
returnMessage: input.allow_regex.returnMessage,
|
|
307
|
+
code: "POK031",
|
|
308
|
+
variable: input.name,
|
|
309
|
+
field: "allow_regex"
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
throw new Error(
|
|
314
|
+
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (input.deny_regex) {
|
|
319
|
+
const candidate2 = sanitized[input.name];
|
|
320
|
+
const matcher = compileContextRegex(input.deny_regex, {
|
|
321
|
+
promptId: asset.id,
|
|
322
|
+
variable: input.name,
|
|
323
|
+
field: "deny_regex"
|
|
324
|
+
});
|
|
325
|
+
if (matcher.test(candidate2)) {
|
|
326
|
+
if (input.deny_regex.returnMessage) {
|
|
327
|
+
return {
|
|
328
|
+
variables: sanitized,
|
|
329
|
+
shortCircuit: {
|
|
330
|
+
returnMessage: input.deny_regex.returnMessage,
|
|
331
|
+
code: "POK032",
|
|
332
|
+
variable: input.name,
|
|
333
|
+
field: "deny_regex"
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
throw new Error(
|
|
338
|
+
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (input.non_empty && candidate.trim().length === 0) {
|
|
343
|
+
if (input.non_empty.returnMessage) {
|
|
344
|
+
return {
|
|
345
|
+
variables: sanitized,
|
|
346
|
+
shortCircuit: {
|
|
347
|
+
returnMessage: input.non_empty.returnMessage,
|
|
348
|
+
code: "POK033",
|
|
349
|
+
variable: input.name,
|
|
350
|
+
field: "non_empty"
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
throw new Error(
|
|
355
|
+
`POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
if (input.reject_secrets) {
|
|
359
|
+
const matcher = compileContextRegex(getRejectSecretsRegex(), {
|
|
360
|
+
promptId: asset.id,
|
|
361
|
+
variable: input.name,
|
|
362
|
+
field: "reject_secrets"
|
|
363
|
+
});
|
|
364
|
+
if (matcher.test(candidate)) {
|
|
365
|
+
if (input.reject_secrets.returnMessage) {
|
|
366
|
+
return {
|
|
367
|
+
variables: sanitized,
|
|
368
|
+
shortCircuit: {
|
|
369
|
+
returnMessage: input.reject_secrets.returnMessage,
|
|
370
|
+
code: "POK034",
|
|
371
|
+
variable: input.name,
|
|
372
|
+
field: "reject_secrets"
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
throw new Error(
|
|
377
|
+
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return { variables: sanitized };
|
|
383
|
+
}
|
|
384
|
+
function measureContextValueSize(value) {
|
|
385
|
+
return textEncoder.encode(value).length;
|
|
386
|
+
}
|
|
387
|
+
function collectContextSizeWarnings(asset, variables = {}) {
|
|
388
|
+
const warnings = [];
|
|
389
|
+
for (const input of getContextInputs(asset)) {
|
|
390
|
+
if (!areContextInputWarningsEnabled(input)) {
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
if (input.max_size === void 0) {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
const value = variables[input.name];
|
|
397
|
+
if (value === void 0) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const actualSize = measureContextValueSize(value);
|
|
401
|
+
if (actualSize > input.max_size) {
|
|
402
|
+
warnings.push({
|
|
403
|
+
variable: input.name,
|
|
404
|
+
maxSize: input.max_size,
|
|
405
|
+
actualSize
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return warnings;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// src/renderer/renderer.ts
|
|
413
|
+
function renderSections(asset, options = {}) {
|
|
414
|
+
const { variables = {}, strict = false } = options;
|
|
415
|
+
const optionalVariables = getContextInputs(asset).filter((input) => input.optional === true).map((input) => input.name);
|
|
416
|
+
const result = {};
|
|
417
|
+
if (asset.sections.system_instructions) {
|
|
418
|
+
result.system_instructions = interpolate(
|
|
419
|
+
asset.sections.system_instructions,
|
|
420
|
+
variables,
|
|
421
|
+
{ strict, optionalVariables }
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
if (asset.sections.prompt_template) {
|
|
425
|
+
result.prompt_template = interpolate(
|
|
426
|
+
asset.sections.prompt_template,
|
|
427
|
+
variables,
|
|
428
|
+
{ strict, optionalVariables }
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// src/overrides/apply-overrides.ts
|
|
435
|
+
function applyOverrides(asset, options = {}) {
|
|
436
|
+
let result = { ...asset };
|
|
437
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
438
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
439
|
+
}
|
|
440
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
441
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
442
|
+
}
|
|
443
|
+
if (options.runtime) {
|
|
444
|
+
result = mergeOverride(result, options.runtime);
|
|
445
|
+
}
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
448
|
+
function mergeOverride(base, override) {
|
|
449
|
+
const result = { ...base };
|
|
450
|
+
if (override.model !== void 0) result.model = override.model;
|
|
451
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
452
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
453
|
+
if (override.reasoning !== void 0) {
|
|
454
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
455
|
+
}
|
|
456
|
+
if (override.sampling !== void 0) {
|
|
457
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
458
|
+
}
|
|
459
|
+
if (override.response !== void 0) {
|
|
460
|
+
result.response = { ...result.response, ...override.response };
|
|
461
|
+
}
|
|
462
|
+
if (override.compression !== void 0) {
|
|
463
|
+
result.compression = {
|
|
464
|
+
...result.compression,
|
|
465
|
+
...override.compression,
|
|
466
|
+
thetokencompany: mergeRecordBlock(
|
|
467
|
+
result.compression?.thetokencompany,
|
|
468
|
+
override.compression.thetokencompany
|
|
469
|
+
)
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
if (override.cache !== void 0) {
|
|
473
|
+
result.cache = {
|
|
474
|
+
...result.cache,
|
|
475
|
+
...override.cache,
|
|
476
|
+
openai: mergeRecordBlock(result.cache?.openai, override.cache.openai),
|
|
477
|
+
anthropic: mergeRecordBlock(result.cache?.anthropic, override.cache.anthropic),
|
|
478
|
+
gemini: mergeRecordBlock(result.cache?.gemini, override.cache.gemini),
|
|
479
|
+
google: mergeRecordBlock(result.cache?.google, override.cache.google)
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
if (override.raw !== void 0) {
|
|
483
|
+
result.raw = {
|
|
484
|
+
...result.raw,
|
|
485
|
+
...override.raw,
|
|
486
|
+
openai: mergeRecordBlock(result.raw?.openai, override.raw.openai),
|
|
487
|
+
"openai-responses": mergeRecordBlock(result.raw?.["openai-responses"], override.raw["openai-responses"]),
|
|
488
|
+
openai_responses: mergeRecordBlock(result.raw?.openai_responses, override.raw.openai_responses),
|
|
489
|
+
anthropic: mergeRecordBlock(result.raw?.anthropic, override.raw.anthropic),
|
|
490
|
+
gemini: mergeRecordBlock(result.raw?.gemini, override.raw.gemini),
|
|
491
|
+
google: mergeRecordBlock(result.raw?.google, override.raw.google),
|
|
492
|
+
openrouter: mergeRecordBlock(result.raw?.openrouter, override.raw.openrouter),
|
|
493
|
+
llmasaservice: mergeRecordBlock(result.raw?.llmasaservice, override.raw.llmasaservice)
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
if (override.provider_options !== void 0) {
|
|
497
|
+
result.provider_options = {
|
|
498
|
+
...result.provider_options,
|
|
499
|
+
...override.provider_options,
|
|
500
|
+
anthropic: {
|
|
501
|
+
...result.provider_options?.anthropic,
|
|
502
|
+
...override.provider_options.anthropic
|
|
503
|
+
},
|
|
504
|
+
gemini: {
|
|
505
|
+
...result.provider_options?.gemini,
|
|
506
|
+
...override.provider_options.gemini
|
|
507
|
+
},
|
|
508
|
+
openrouter: {
|
|
509
|
+
...result.provider_options?.openrouter,
|
|
510
|
+
...override.provider_options.openrouter
|
|
511
|
+
},
|
|
512
|
+
llmasaservice: {
|
|
513
|
+
...result.provider_options?.llmasaservice,
|
|
514
|
+
...override.provider_options.llmasaservice
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
519
|
+
}
|
|
520
|
+
function mergeRecordBlock(base, override) {
|
|
521
|
+
if (override === void 0) return base;
|
|
522
|
+
return { ...base, ...override };
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/providers/resolve-asset.ts
|
|
526
|
+
function resolveAssetForProvider(asset, runtime = {}) {
|
|
527
|
+
if (!runtime.environment && !runtime.tier && !runtime.runtime) {
|
|
528
|
+
return asset;
|
|
529
|
+
}
|
|
530
|
+
return applyOverrides(asset, {
|
|
531
|
+
environment: runtime.environment,
|
|
532
|
+
tier: runtime.tier,
|
|
533
|
+
runtime: runtime.runtime
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/prompt-resolution.ts
|
|
538
|
+
var import_promises4 = require("fs/promises");
|
|
539
|
+
var import_node_fs2 = require("fs");
|
|
540
|
+
var import_node_path4 = require("path");
|
|
541
|
+
|
|
542
|
+
// src/cache.ts
|
|
543
|
+
var import_node_fs = require("fs");
|
|
544
|
+
var PromptCache = class {
|
|
545
|
+
cache = /* @__PURE__ */ new Map();
|
|
546
|
+
maxSize;
|
|
547
|
+
constructor(maxSize = 100) {
|
|
548
|
+
this.maxSize = maxSize;
|
|
549
|
+
}
|
|
550
|
+
get(filePath) {
|
|
551
|
+
const entry = this.cache.get(filePath);
|
|
552
|
+
if (!entry) return void 0;
|
|
553
|
+
try {
|
|
554
|
+
const stat = (0, import_node_fs.statSync)(filePath);
|
|
555
|
+
if (stat.mtimeMs !== entry.mtime) {
|
|
556
|
+
this.cache.delete(filePath);
|
|
557
|
+
return void 0;
|
|
558
|
+
}
|
|
559
|
+
} catch {
|
|
560
|
+
this.cache.delete(filePath);
|
|
561
|
+
return void 0;
|
|
562
|
+
}
|
|
563
|
+
this.cache.delete(filePath);
|
|
564
|
+
this.cache.set(filePath, entry);
|
|
565
|
+
return entry.value;
|
|
566
|
+
}
|
|
567
|
+
set(filePath, value) {
|
|
568
|
+
try {
|
|
569
|
+
const stat = (0, import_node_fs.statSync)(filePath);
|
|
570
|
+
if (this.cache.has(filePath)) {
|
|
571
|
+
this.cache.delete(filePath);
|
|
572
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
573
|
+
const oldest = this.cache.keys().next().value;
|
|
574
|
+
if (oldest) this.cache.delete(oldest);
|
|
575
|
+
}
|
|
259
576
|
this.cache.set(filePath, { value, mtime: stat.mtimeMs });
|
|
260
577
|
} catch {
|
|
261
578
|
}
|
|
@@ -269,8 +586,8 @@ var PromptCache = class {
|
|
|
269
586
|
};
|
|
270
587
|
|
|
271
588
|
// src/composition/resolve-includes.ts
|
|
272
|
-
var
|
|
273
|
-
var
|
|
589
|
+
var import_promises3 = require("fs/promises");
|
|
590
|
+
var import_node_path3 = require("path");
|
|
274
591
|
|
|
275
592
|
// src/parser/parser.ts
|
|
276
593
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
@@ -306,10 +623,26 @@ var ResponseSchema = import_zod.z.object({
|
|
|
306
623
|
format: import_zod.z.enum(["text", "json", "markdown"]).optional(),
|
|
307
624
|
stream: import_zod.z.boolean().optional(),
|
|
308
625
|
schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
626
|
+
schema_ref: import_zod.z.string().min(1).optional(),
|
|
627
|
+
schema_source: import_zod.z.object({
|
|
628
|
+
mode: import_zod.z.enum(["inline", "schema_ref_json", "schema_ref_zod_module"]).optional(),
|
|
629
|
+
ref: import_zod.z.string().optional(),
|
|
630
|
+
resolved_path: import_zod.z.string().optional(),
|
|
631
|
+
hash: import_zod.z.string().optional()
|
|
632
|
+
}).optional(),
|
|
309
633
|
schema_name: import_zod.z.string().optional(),
|
|
310
634
|
schema_description: import_zod.z.string().optional(),
|
|
311
635
|
schema_strict: import_zod.z.boolean().optional()
|
|
312
636
|
});
|
|
637
|
+
var ResponseSchemaWithValidation = ResponseSchema.superRefine((value, ctx) => {
|
|
638
|
+
if (value.schema !== void 0 && value.schema_ref !== void 0) {
|
|
639
|
+
ctx.addIssue({
|
|
640
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
641
|
+
message: "response.schema and response.schema_ref are mutually exclusive",
|
|
642
|
+
path: ["schema_ref"]
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
});
|
|
313
646
|
var AnthropicProviderOptionsSchema = import_zod.z.object({
|
|
314
647
|
top_k: import_zod.z.number().int().min(0).optional(),
|
|
315
648
|
tool_choice: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
@@ -361,6 +694,14 @@ var RawProviderBodySchema = import_zod.z.object({
|
|
|
361
694
|
openrouter: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
362
695
|
llmasaservice: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
363
696
|
});
|
|
697
|
+
var TheTokenCompanyCompressionSchema = import_zod.z.object({
|
|
698
|
+
enabled: import_zod.z.boolean().optional(),
|
|
699
|
+
model: import_zod.z.string().min(1).optional(),
|
|
700
|
+
aggressiveness: import_zod.z.number().min(0).max(1).optional()
|
|
701
|
+
});
|
|
702
|
+
var CompressionSchema = import_zod.z.object({
|
|
703
|
+
thetokencompany: TheTokenCompanyCompressionSchema.optional()
|
|
704
|
+
});
|
|
364
705
|
var OpenAICacheSchema = import_zod.z.object({
|
|
365
706
|
prompt_cache_key: import_zod.z.string().min(1).optional(),
|
|
366
707
|
retention: import_zod.z.enum(["in_memory", "24h"]).optional()
|
|
@@ -401,6 +742,8 @@ var ContextBuiltInValidatorSchema = import_zod.z.union([
|
|
|
401
742
|
]);
|
|
402
743
|
var ContextInputDefinitionObjectSchema = import_zod.z.object({
|
|
403
744
|
name: import_zod.z.string(),
|
|
745
|
+
optional: import_zod.z.boolean().optional(),
|
|
746
|
+
warnings: import_zod.z.boolean().optional(),
|
|
404
747
|
max_size: import_zod.z.number().int().positive().optional(),
|
|
405
748
|
trim: import_zod.z.union([import_zod.z.boolean(), import_zod.z.enum(["start", "end", "both"])]).optional(),
|
|
406
749
|
allow_regex: ContextRegexSchema.optional(),
|
|
@@ -430,7 +773,8 @@ var PromptAssetOverridesSchema = import_zod.z.object({
|
|
|
430
773
|
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
431
774
|
reasoning: ReasoningSchema.optional(),
|
|
432
775
|
sampling: SamplingSchema.optional(),
|
|
433
|
-
response:
|
|
776
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
777
|
+
compression: CompressionSchema.optional(),
|
|
434
778
|
cache: CacheSchema.optional(),
|
|
435
779
|
raw: RawProviderBodySchema.optional(),
|
|
436
780
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
@@ -448,7 +792,20 @@ var SectionsSchema = import_zod.z.object({
|
|
|
448
792
|
var PromptDefaultsSchema = import_zod.z.object({
|
|
449
793
|
provider: import_zod.z.enum(["openai", "openai-responses", "anthropic", "google", "gemini", "openrouter", "llmasaservice", "any"]).optional(),
|
|
450
794
|
model: import_zod.z.string().optional(),
|
|
795
|
+
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
796
|
+
reasoning: ReasoningSchema.optional(),
|
|
797
|
+
sampling: SamplingSchema.optional(),
|
|
798
|
+
response: ResponseSchema.optional(),
|
|
799
|
+
compression: CompressionSchema.optional(),
|
|
451
800
|
cache: CacheSchema.optional(),
|
|
801
|
+
raw: RawProviderBodySchema.optional(),
|
|
802
|
+
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
803
|
+
provider_options: ProviderOptionsSchema.optional(),
|
|
804
|
+
mcp: MCPSchema.optional(),
|
|
805
|
+
context: ContextSchema.optional(),
|
|
806
|
+
includes: import_zod.z.array(import_zod.z.string()).optional(),
|
|
807
|
+
environments: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
808
|
+
tiers: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
452
809
|
metadata: MetadataSchema.optional(),
|
|
453
810
|
sections: import_zod.z.object({
|
|
454
811
|
system_instructions: import_zod.z.string().optional()
|
|
@@ -463,7 +820,8 @@ var PromptAssetSchema = import_zod.z.object({
|
|
|
463
820
|
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
464
821
|
reasoning: ReasoningSchema.optional(),
|
|
465
822
|
sampling: SamplingSchema.optional(),
|
|
466
|
-
response:
|
|
823
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
824
|
+
compression: CompressionSchema.optional(),
|
|
467
825
|
cache: CacheSchema.optional(),
|
|
468
826
|
raw: RawProviderBodySchema.optional(),
|
|
469
827
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
@@ -517,690 +875,640 @@ function assertRegexFrontMatterQuoting(content, filePath) {
|
|
|
517
875
|
if (!patternMatch?.groups) {
|
|
518
876
|
continue;
|
|
519
877
|
}
|
|
520
|
-
assertNoUnescapedBackslashInDoubleQuotedRegex(
|
|
521
|
-
patternMatch.groups.value.trim(),
|
|
522
|
-
`${pendingRegex.field}.pattern`,
|
|
523
|
-
filePath,
|
|
524
|
-
lineNumber
|
|
525
|
-
);
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
function assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber) {
|
|
529
|
-
const match = value.match(INLINE_PATTERN_FIELD);
|
|
530
|
-
const pattern = match?.groups?.value;
|
|
531
|
-
if (!pattern) {
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
assertNoUnescapedBackslashInDoubleQuotedRegex(pattern, `${field}.pattern`, filePath, lineNumber);
|
|
535
|
-
}
|
|
536
|
-
function extractFrontMatter(content) {
|
|
537
|
-
const lines = content.split(/\r?\n/);
|
|
538
|
-
if (!FRONT_MATTER_DELIMITER.test(lines[0] ?? "")) {
|
|
539
|
-
return void 0;
|
|
540
|
-
}
|
|
541
|
-
for (let index = 1; index < lines.length; index += 1) {
|
|
542
|
-
if (FRONT_MATTER_DELIMITER.test(lines[index] ?? "")) {
|
|
543
|
-
return {
|
|
544
|
-
lines: lines.slice(1, index),
|
|
545
|
-
startLine: 2
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
return void 0;
|
|
550
|
-
}
|
|
551
|
-
function assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber) {
|
|
552
|
-
if (!value.startsWith('"')) {
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
const quoted = readDoubleQuotedScalar(value);
|
|
556
|
-
if (!quoted) {
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
if (!hasUnescapedBackslash(quoted)) {
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
const location = filePath ? `${filePath}:${lineNumber}` : `line ${lineNumber}`;
|
|
563
|
-
throw new Error(
|
|
564
|
-
`POK013: Invalid context regex YAML at ${location}, field "${field}": double-quoted regex strings treat backslashes as YAML escapes. Use unquoted /pattern/i literal form, single quotes, or double each backslash.`
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
function readDoubleQuotedScalar(value) {
|
|
568
|
-
let result = "";
|
|
569
|
-
for (let index = 1; index < value.length; index += 1) {
|
|
570
|
-
const char = value[index];
|
|
571
|
-
if (char === '"') {
|
|
572
|
-
return result;
|
|
573
|
-
}
|
|
574
|
-
result += char;
|
|
575
|
-
if (char === "\\" && index + 1 < value.length) {
|
|
576
|
-
index += 1;
|
|
577
|
-
result += value[index];
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
return void 0;
|
|
581
|
-
}
|
|
582
|
-
function hasUnescapedBackslash(value) {
|
|
583
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
584
|
-
if (value[index] !== "\\") {
|
|
585
|
-
continue;
|
|
586
|
-
}
|
|
587
|
-
let count = 1;
|
|
588
|
-
while (value[index + count] === "\\") {
|
|
589
|
-
count += 1;
|
|
590
|
-
}
|
|
591
|
-
if (count % 2 === 1) {
|
|
592
|
-
return true;
|
|
593
|
-
}
|
|
594
|
-
index += count - 1;
|
|
595
|
-
}
|
|
596
|
-
return false;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// src/parser/sections.ts
|
|
600
|
-
var SECTION_MAP = {
|
|
601
|
-
"system instructions": "system_instructions",
|
|
602
|
-
"prompt template": "prompt_template",
|
|
603
|
-
"notes": "notes"
|
|
604
|
-
};
|
|
605
|
-
function extractSections(body) {
|
|
606
|
-
const lines = body.split(/\r?\n/);
|
|
607
|
-
const sections = {};
|
|
608
|
-
let currentKey = null;
|
|
609
|
-
let currentLines = [];
|
|
610
|
-
let foundAnyH1 = false;
|
|
611
|
-
for (const line of lines) {
|
|
612
|
-
const h1Match = line.match(/^#\s+(.+)$/);
|
|
613
|
-
if (h1Match) {
|
|
614
|
-
if (currentKey) {
|
|
615
|
-
sections[currentKey] = currentLines.join("\n").trim();
|
|
616
|
-
}
|
|
617
|
-
foundAnyH1 = true;
|
|
618
|
-
const heading = h1Match[1].trim().toLowerCase();
|
|
619
|
-
currentKey = SECTION_MAP[heading] ?? null;
|
|
620
|
-
currentLines = [];
|
|
621
|
-
} else {
|
|
622
|
-
currentLines.push(line);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
if (currentKey) {
|
|
626
|
-
sections[currentKey] = currentLines.join("\n").trim();
|
|
627
|
-
}
|
|
628
|
-
if (!foundAnyH1) {
|
|
629
|
-
const trimmed = body.trim();
|
|
630
|
-
if (trimmed) {
|
|
631
|
-
sections.prompt_template = trimmed;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
return sections;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// src/parser/parser.ts
|
|
638
|
-
function parsePrompt(content, filePath) {
|
|
639
|
-
assertRegexFrontMatterQuoting(content, filePath);
|
|
640
|
-
const { data: frontMatter, content: body } = (0, import_gray_matter.default)(content);
|
|
641
|
-
const sections = extractSections(body);
|
|
642
|
-
const raw = {
|
|
643
|
-
...frontMatter,
|
|
644
|
-
sections,
|
|
645
|
-
source: filePath ? { file_path: filePath } : void 0
|
|
646
|
-
};
|
|
647
|
-
const asset = PromptAssetSchema.parse(raw);
|
|
648
|
-
return {
|
|
649
|
-
asset,
|
|
650
|
-
raw: {
|
|
651
|
-
frontMatter,
|
|
652
|
-
body
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// src/parser/loader.ts
|
|
658
|
-
var import_promises = require("fs/promises");
|
|
659
|
-
var import_node_path = require("path");
|
|
660
|
-
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
661
|
-
var DEFAULTS_FILE_NAME = "defaults.md";
|
|
662
|
-
async function loadPromptFile(filePath, options = {}) {
|
|
663
|
-
const content = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
664
|
-
const parsed = parsePrompt(content, filePath);
|
|
665
|
-
const root = options.defaultsRoot ?? (0, import_node_path.dirname)(filePath);
|
|
666
|
-
const defaults = await loadDefaultsForPath(filePath, root);
|
|
667
|
-
const asset = applyDefaults(parsed.asset, defaults);
|
|
668
|
-
return {
|
|
669
|
-
...parsed,
|
|
670
|
-
asset
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
674
|
-
const directories = getDirectoriesToCheck(filePath, defaultsRoot);
|
|
675
|
-
let merged = {};
|
|
676
|
-
for (const dir of directories) {
|
|
677
|
-
const defaultsPath = (0, import_node_path.join)(dir, DEFAULTS_FILE_NAME);
|
|
678
|
-
try {
|
|
679
|
-
const defaultsContent = await (0, import_promises.readFile)(defaultsPath, "utf-8");
|
|
680
|
-
const defaults = parseDefaults(defaultsContent);
|
|
681
|
-
merged = mergeDefaults(merged, defaults);
|
|
682
|
-
} catch (error) {
|
|
683
|
-
if (error.code !== "ENOENT") {
|
|
684
|
-
throw error;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return merged;
|
|
689
|
-
}
|
|
690
|
-
function getDirectoriesToCheck(filePath, defaultsRoot) {
|
|
691
|
-
const dirs = [];
|
|
692
|
-
let current = (0, import_node_path.resolve)((0, import_node_path.dirname)(filePath));
|
|
693
|
-
const boundary = defaultsRoot ? (0, import_node_path.resolve)(defaultsRoot) : void 0;
|
|
694
|
-
while (true) {
|
|
695
|
-
dirs.unshift(current);
|
|
696
|
-
if (boundary && current === boundary || current === (0, import_node_path.dirname)(current)) {
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
current = (0, import_node_path.dirname)(current);
|
|
700
|
-
}
|
|
701
|
-
return dirs;
|
|
702
|
-
}
|
|
703
|
-
function parseDefaults(content) {
|
|
704
|
-
const { data: frontMatter, content: body } = (0, import_gray_matter2.default)(content);
|
|
705
|
-
const sections = extractSections(body);
|
|
706
|
-
return PromptDefaultsSchema.parse({
|
|
707
|
-
...frontMatter,
|
|
708
|
-
sections: {
|
|
709
|
-
system_instructions: sections.system_instructions
|
|
710
|
-
}
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
function mergeDefaults(base, local) {
|
|
714
|
-
return {
|
|
715
|
-
provider: local.provider ?? base.provider,
|
|
716
|
-
model: local.model ?? base.model,
|
|
717
|
-
cache: mergeCache(base.cache, local.cache),
|
|
718
|
-
metadata: {
|
|
719
|
-
...base.metadata ?? {},
|
|
720
|
-
...local.metadata ?? {}
|
|
721
|
-
},
|
|
722
|
-
sections: {
|
|
723
|
-
...base.sections ?? {},
|
|
724
|
-
...local.sections ?? {}
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
function applyDefaults(asset, defaults) {
|
|
729
|
-
const cache = mergeCache(defaults.cache, asset.cache);
|
|
730
|
-
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
731
|
-
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
732
|
-
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0;
|
|
733
|
-
const hasDefaultCache = cache !== void 0;
|
|
734
|
-
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultCache) {
|
|
735
|
-
return asset;
|
|
736
|
-
}
|
|
737
|
-
const mergedMetadata = {
|
|
738
|
-
...defaults.metadata ?? {},
|
|
739
|
-
...asset.metadata ?? {}
|
|
740
|
-
};
|
|
741
|
-
const metadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : void 0;
|
|
742
|
-
const systemInstructions = asset.sections?.system_instructions ?? defaults.sections?.system_instructions;
|
|
743
|
-
const sections = asset.sections ? { ...asset.sections, system_instructions: systemInstructions } : systemInstructions ? { system_instructions: systemInstructions } : void 0;
|
|
744
|
-
return {
|
|
745
|
-
...asset,
|
|
746
|
-
provider: asset.provider ?? defaults.provider,
|
|
747
|
-
model: asset.model ?? defaults.model,
|
|
748
|
-
cache,
|
|
749
|
-
metadata,
|
|
750
|
-
sections
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
function mergeCache(base, local) {
|
|
754
|
-
const merged = {
|
|
755
|
-
...base ?? {},
|
|
756
|
-
...local ?? {},
|
|
757
|
-
openai: {
|
|
758
|
-
...base?.openai ?? {},
|
|
759
|
-
...local?.openai ?? {}
|
|
760
|
-
},
|
|
761
|
-
anthropic: {
|
|
762
|
-
...base?.anthropic ?? {},
|
|
763
|
-
...local?.anthropic ?? {}
|
|
764
|
-
},
|
|
765
|
-
gemini: {
|
|
766
|
-
...base?.gemini ?? {},
|
|
767
|
-
...local?.gemini ?? {}
|
|
768
|
-
},
|
|
769
|
-
google: {
|
|
770
|
-
...base?.google ?? {},
|
|
771
|
-
...local?.google ?? {}
|
|
772
|
-
}
|
|
773
|
-
};
|
|
774
|
-
if (merged.openai && Object.keys(merged.openai).length === 0) delete merged.openai;
|
|
775
|
-
if (merged.anthropic && Object.keys(merged.anthropic).length === 0) delete merged.anthropic;
|
|
776
|
-
if (merged.gemini && Object.keys(merged.gemini).length === 0) delete merged.gemini;
|
|
777
|
-
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
778
|
-
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
878
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(
|
|
879
|
+
patternMatch.groups.value.trim(),
|
|
880
|
+
`${pendingRegex.field}.pattern`,
|
|
881
|
+
filePath,
|
|
882
|
+
lineNumber
|
|
883
|
+
);
|
|
884
|
+
}
|
|
779
885
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
if (!
|
|
784
|
-
return
|
|
886
|
+
function assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber) {
|
|
887
|
+
const match = value.match(INLINE_PATTERN_FIELD);
|
|
888
|
+
const pattern = match?.groups?.value;
|
|
889
|
+
if (!pattern) {
|
|
890
|
+
return;
|
|
785
891
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
892
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(pattern, `${field}.pattern`, filePath, lineNumber);
|
|
893
|
+
}
|
|
894
|
+
function extractFrontMatter(content) {
|
|
895
|
+
const lines = content.split(/\r?\n/);
|
|
896
|
+
if (!FRONT_MATTER_DELIMITER.test(lines[0] ?? "")) {
|
|
897
|
+
return void 0;
|
|
790
898
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
const content = await (0, import_promises2.readFile)(fullPath, "utf-8");
|
|
799
|
-
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
800
|
-
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
801
|
-
if (resolved.sections?.system_instructions) {
|
|
802
|
-
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
899
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
900
|
+
if (FRONT_MATTER_DELIMITER.test(lines[index] ?? "")) {
|
|
901
|
+
return {
|
|
902
|
+
lines: lines.slice(1, index),
|
|
903
|
+
startLine: 2
|
|
904
|
+
};
|
|
803
905
|
}
|
|
804
906
|
}
|
|
805
|
-
|
|
806
|
-
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
807
|
-
return {
|
|
808
|
-
...asset,
|
|
809
|
-
sections: {
|
|
810
|
-
...asset.sections,
|
|
811
|
-
system_instructions: combinedSystem
|
|
812
|
-
},
|
|
813
|
-
// Drop includes from the resolved asset — they've been inlined
|
|
814
|
-
includes: void 0
|
|
815
|
-
};
|
|
907
|
+
return void 0;
|
|
816
908
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
909
|
+
function assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber) {
|
|
910
|
+
if (!value.startsWith('"')) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const quoted = readDoubleQuotedScalar(value);
|
|
914
|
+
if (!quoted) {
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (!hasUnescapedBackslash(quoted)) {
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
const location = filePath ? `${filePath}:${lineNumber}` : `line ${lineNumber}`;
|
|
921
|
+
throw new Error(
|
|
922
|
+
`POK013: Invalid context regex YAML at ${location}, field "${field}": double-quoted regex strings treat backslashes as YAML escapes. Use unquoted /pattern/i literal form, single quotes, or double each backslash.`
|
|
923
|
+
);
|
|
827
924
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
835
|
-
if (mode === "auto") {
|
|
836
|
-
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
837
|
-
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
838
|
-
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
839
|
-
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
840
|
-
if (sourceMtime > compiledMtime) {
|
|
841
|
-
console.warn(
|
|
842
|
-
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
843
|
-
Run "promptopskit compile" or switch to source-only mode.`
|
|
844
|
-
);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
const content = await (0, import_promises3.readFile)(compiledFile, "utf-8");
|
|
849
|
-
return JSON.parse(content);
|
|
925
|
+
function readDoubleQuotedScalar(value) {
|
|
926
|
+
let result = "";
|
|
927
|
+
for (let index = 1; index < value.length; index += 1) {
|
|
928
|
+
const char = value[index];
|
|
929
|
+
if (char === '"') {
|
|
930
|
+
return result;
|
|
850
931
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
);
|
|
932
|
+
result += char;
|
|
933
|
+
if (char === "\\" && index + 1 < value.length) {
|
|
934
|
+
index += 1;
|
|
935
|
+
result += value[index];
|
|
856
936
|
}
|
|
857
937
|
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
}
|
|
938
|
+
return void 0;
|
|
939
|
+
}
|
|
940
|
+
function hasUnescapedBackslash(value) {
|
|
941
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
942
|
+
if (value[index] !== "\\") {
|
|
943
|
+
continue;
|
|
865
944
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
paths.unshift((0, import_node_path3.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
870
|
-
}
|
|
871
|
-
throw new Error(
|
|
872
|
-
`Prompt not found: "${promptPath}"
|
|
873
|
-
Searched:
|
|
874
|
-
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
875
|
-
);
|
|
945
|
+
let count = 1;
|
|
946
|
+
while (value[index + count] === "\\") {
|
|
947
|
+
count += 1;
|
|
876
948
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
promptCache.set(sourceFile, asset);
|
|
949
|
+
if (count % 2 === 1) {
|
|
950
|
+
return true;
|
|
880
951
|
}
|
|
881
|
-
|
|
952
|
+
index += count - 1;
|
|
882
953
|
}
|
|
883
|
-
|
|
954
|
+
return false;
|
|
884
955
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
956
|
+
|
|
957
|
+
// src/parser/sections.ts
|
|
958
|
+
var SECTION_MAP = {
|
|
959
|
+
"system instructions": "system_instructions",
|
|
960
|
+
"prompt template": "prompt_template",
|
|
961
|
+
"notes": "notes"
|
|
962
|
+
};
|
|
963
|
+
function extractSections(body) {
|
|
964
|
+
const lines = body.split(/\r?\n/);
|
|
965
|
+
const sections = {};
|
|
966
|
+
let currentKey = null;
|
|
967
|
+
let currentLines = [];
|
|
968
|
+
let foundAnyH1 = false;
|
|
969
|
+
for (const line of lines) {
|
|
970
|
+
const h1Match = line.match(/^#\s+(.+)$/);
|
|
971
|
+
if (h1Match) {
|
|
972
|
+
if (currentKey) {
|
|
973
|
+
sections[currentKey] = currentLines.join("\n").trim();
|
|
974
|
+
}
|
|
975
|
+
foundAnyH1 = true;
|
|
976
|
+
const heading = h1Match[1].trim().toLowerCase();
|
|
977
|
+
currentKey = SECTION_MAP[heading] ?? null;
|
|
978
|
+
currentLines = [];
|
|
979
|
+
} else {
|
|
980
|
+
currentLines.push(line);
|
|
981
|
+
}
|
|
891
982
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
return
|
|
902
|
-
environment: options.environment,
|
|
903
|
-
tier: options.tier,
|
|
904
|
-
runtime: options.runtime
|
|
905
|
-
});
|
|
983
|
+
if (currentKey) {
|
|
984
|
+
sections[currentKey] = currentLines.join("\n").trim();
|
|
985
|
+
}
|
|
986
|
+
if (!foundAnyH1) {
|
|
987
|
+
const trimmed = body.trim();
|
|
988
|
+
if (trimmed) {
|
|
989
|
+
sections.prompt_template = trimmed;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return sections;
|
|
906
993
|
}
|
|
907
994
|
|
|
908
|
-
// src/
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
if (typeof input === "string") {
|
|
920
|
-
return { name: input };
|
|
921
|
-
}
|
|
995
|
+
// src/parser/parser.ts
|
|
996
|
+
function parsePrompt(content, filePath) {
|
|
997
|
+
assertRegexFrontMatterQuoting(content, filePath);
|
|
998
|
+
const { data: frontMatter, content: body } = (0, import_gray_matter.default)(content);
|
|
999
|
+
const sections = extractSections(body);
|
|
1000
|
+
const raw = {
|
|
1001
|
+
...frontMatter,
|
|
1002
|
+
sections,
|
|
1003
|
+
source: filePath ? { file_path: filePath } : void 0
|
|
1004
|
+
};
|
|
1005
|
+
const asset = PromptAssetSchema.parse(raw);
|
|
922
1006
|
return {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
929
|
-
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
1007
|
+
asset,
|
|
1008
|
+
raw: {
|
|
1009
|
+
frontMatter,
|
|
1010
|
+
body
|
|
1011
|
+
}
|
|
930
1012
|
};
|
|
931
1013
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1014
|
+
|
|
1015
|
+
// src/parser/loader.ts
|
|
1016
|
+
var import_promises2 = require("fs/promises");
|
|
1017
|
+
var import_node_path2 = require("path");
|
|
1018
|
+
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
1019
|
+
|
|
1020
|
+
// src/parser/response-schema-ref.ts
|
|
1021
|
+
var import_promises = require("fs/promises");
|
|
1022
|
+
var import_node_crypto = require("crypto");
|
|
1023
|
+
var import_node_path = require("path");
|
|
1024
|
+
var import_node_url = require("url");
|
|
1025
|
+
var import_zod2 = require("zod");
|
|
1026
|
+
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
1027
|
+
var SUPPORTED_SCHEMA_REF_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
1028
|
+
async function resolveJsonSchemaRef(schemaRef, promptFilePath) {
|
|
1029
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
1030
|
+
let raw;
|
|
1031
|
+
try {
|
|
1032
|
+
raw = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
const code = error.code;
|
|
1035
|
+
if (code === "ENOENT") {
|
|
1036
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
945
1037
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1038
|
+
throw error;
|
|
1039
|
+
}
|
|
1040
|
+
let parsed;
|
|
1041
|
+
try {
|
|
1042
|
+
parsed = JSON.parse(raw);
|
|
1043
|
+
} catch {
|
|
1044
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" is not valid JSON`);
|
|
1045
|
+
}
|
|
1046
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1047
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" must resolve to a JSON object schema`);
|
|
951
1048
|
}
|
|
952
1049
|
return {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
returnMessage: value.return_message
|
|
1050
|
+
schema: parsed,
|
|
1051
|
+
resolvedPath,
|
|
1052
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(raw).digest("hex")
|
|
957
1053
|
};
|
|
958
1054
|
}
|
|
959
|
-
function
|
|
960
|
-
|
|
961
|
-
|
|
1055
|
+
async function resolveZodSchemaRef(schemaRef, promptFilePath) {
|
|
1056
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
1057
|
+
let moduleSource;
|
|
1058
|
+
try {
|
|
1059
|
+
moduleSource = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
const code = error.code;
|
|
1062
|
+
if (code === "ENOENT") {
|
|
1063
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
1064
|
+
}
|
|
1065
|
+
throw error;
|
|
962
1066
|
}
|
|
963
|
-
|
|
964
|
-
|
|
1067
|
+
let imported;
|
|
1068
|
+
try {
|
|
1069
|
+
imported = await import((0, import_node_url.pathToFileURL)(resolvedPath).href);
|
|
1070
|
+
} catch (error) {
|
|
1071
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1072
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" could not be imported as a module (${message})`);
|
|
1073
|
+
}
|
|
1074
|
+
const mod = imported;
|
|
1075
|
+
const candidate = mod.default ?? mod.schema;
|
|
1076
|
+
if (!(candidate instanceof import_zod2.z.ZodType)) {
|
|
1077
|
+
throw new Error('POK051: zod schema modules must export a Zod schema as default export or named export "schema"');
|
|
1078
|
+
}
|
|
1079
|
+
const jsonSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(candidate, {
|
|
1080
|
+
target: "jsonSchema7",
|
|
1081
|
+
$refStrategy: "none"
|
|
1082
|
+
});
|
|
1083
|
+
if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
|
|
1084
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" did not produce a valid JSON schema object`);
|
|
965
1085
|
}
|
|
966
1086
|
return {
|
|
967
|
-
|
|
1087
|
+
schema: jsonSchema,
|
|
1088
|
+
resolvedPath,
|
|
1089
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(moduleSource).digest("hex")
|
|
968
1090
|
};
|
|
969
1091
|
}
|
|
970
|
-
function
|
|
971
|
-
|
|
972
|
-
|
|
1092
|
+
async function resolveResponseSchemaRef(asset, promptFilePath) {
|
|
1093
|
+
const schemaRef = asset.response?.schema_ref;
|
|
1094
|
+
if (!schemaRef) return asset;
|
|
1095
|
+
const ext = (0, import_node_path.extname)(schemaRef).toLowerCase();
|
|
1096
|
+
if (!SUPPORTED_SCHEMA_REF_EXTENSIONS.has(ext)) {
|
|
1097
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" has unsupported extension "${ext}". Use .json, .js, .mjs, or .cjs`);
|
|
973
1098
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1099
|
+
const resolved = ext === ".json" ? await resolveJsonSchemaRef(schemaRef, promptFilePath) : await resolveZodSchemaRef(schemaRef, promptFilePath);
|
|
1100
|
+
return {
|
|
1101
|
+
...asset,
|
|
1102
|
+
response: {
|
|
1103
|
+
...asset.response,
|
|
1104
|
+
schema: resolved.schema,
|
|
1105
|
+
schema_ref: void 0,
|
|
1106
|
+
schema_source: {
|
|
1107
|
+
mode: ext === ".json" ? "schema_ref_json" : "schema_ref_zod_module",
|
|
1108
|
+
ref: schemaRef,
|
|
1109
|
+
resolved_path: resolved.resolvedPath,
|
|
1110
|
+
hash: resolved.hash
|
|
1111
|
+
}
|
|
977
1112
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// src/parser/loader.ts
|
|
1117
|
+
var DEFAULTS_FILE_NAME = "defaults.md";
|
|
1118
|
+
async function loadPromptFile(filePath, options = {}) {
|
|
1119
|
+
const content = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
1120
|
+
const parsed = parsePrompt(content, filePath);
|
|
1121
|
+
const root = options.defaultsRoot ?? (0, import_node_path2.dirname)(filePath);
|
|
1122
|
+
const defaults = await loadDefaultsForPath(filePath, root);
|
|
1123
|
+
const withDefaults = applyDefaults(parsed.asset, defaults);
|
|
1124
|
+
const resolved = await resolveResponseSchemaRef(withDefaults, filePath);
|
|
1125
|
+
const asset = resolved.response?.schema !== void 0 && !resolved.response?.schema_source ? {
|
|
1126
|
+
...resolved,
|
|
1127
|
+
response: {
|
|
1128
|
+
...resolved.response,
|
|
1129
|
+
schema_source: { mode: "inline" }
|
|
1130
|
+
}
|
|
1131
|
+
} : resolved;
|
|
1132
|
+
return {
|
|
1133
|
+
...parsed,
|
|
1134
|
+
asset
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
1138
|
+
const directories = getDirectoriesToCheck(filePath, defaultsRoot);
|
|
1139
|
+
let merged = {};
|
|
1140
|
+
for (const dir of directories) {
|
|
1141
|
+
const defaultsPath = (0, import_node_path2.join)(dir, DEFAULTS_FILE_NAME);
|
|
1142
|
+
try {
|
|
1143
|
+
const defaultsContent = await (0, import_promises2.readFile)(defaultsPath, "utf-8");
|
|
1144
|
+
const defaults = normalizeDefaultIncludes(parseDefaults(defaultsContent), defaultsPath, filePath);
|
|
1145
|
+
merged = mergeDefaults(merged, defaults);
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
if (error.code !== "ENOENT") {
|
|
1148
|
+
throw error;
|
|
1149
|
+
}
|
|
981
1150
|
}
|
|
982
|
-
|
|
983
|
-
|
|
1151
|
+
}
|
|
1152
|
+
return merged;
|
|
1153
|
+
}
|
|
1154
|
+
function getDirectoriesToCheck(filePath, defaultsRoot) {
|
|
1155
|
+
const dirs = [];
|
|
1156
|
+
let current = (0, import_node_path2.resolve)((0, import_node_path2.dirname)(filePath));
|
|
1157
|
+
const boundary = defaultsRoot ? (0, import_node_path2.resolve)(defaultsRoot) : void 0;
|
|
1158
|
+
while (true) {
|
|
1159
|
+
dirs.unshift(current);
|
|
1160
|
+
if (boundary && current === boundary || current === (0, import_node_path2.dirname)(current)) {
|
|
1161
|
+
break;
|
|
984
1162
|
}
|
|
985
|
-
|
|
986
|
-
pattern: value.slice(1, index),
|
|
987
|
-
flags: value.slice(index + 1)
|
|
988
|
-
};
|
|
1163
|
+
current = (0, import_node_path2.dirname)(current);
|
|
989
1164
|
}
|
|
990
|
-
return
|
|
1165
|
+
return dirs;
|
|
991
1166
|
}
|
|
992
|
-
function
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1167
|
+
function parseDefaults(content) {
|
|
1168
|
+
const { data: frontMatter, content: body } = (0, import_gray_matter2.default)(content);
|
|
1169
|
+
const sections = extractSections(body);
|
|
1170
|
+
return PromptDefaultsSchema.parse({
|
|
1171
|
+
...frontMatter,
|
|
1172
|
+
sections: {
|
|
1173
|
+
system_instructions: sections.system_instructions
|
|
1174
|
+
}
|
|
1175
|
+
});
|
|
999
1176
|
}
|
|
1000
|
-
function
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
)
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1177
|
+
function mergeDefaults(base, local) {
|
|
1178
|
+
return {
|
|
1179
|
+
provider: local.provider ?? base.provider,
|
|
1180
|
+
model: local.model ?? base.model,
|
|
1181
|
+
fallback_models: local.fallback_models ?? base.fallback_models,
|
|
1182
|
+
reasoning: mergeRecordBlock2(base.reasoning, local.reasoning),
|
|
1183
|
+
sampling: mergeRecordBlock2(base.sampling, local.sampling),
|
|
1184
|
+
response: mergeRecordBlock2(base.response, local.response),
|
|
1185
|
+
compression: mergeCompression(base.compression, local.compression),
|
|
1186
|
+
cache: mergeCache(base.cache, local.cache),
|
|
1187
|
+
raw: mergeRaw(base.raw, local.raw),
|
|
1188
|
+
tools: local.tools ?? base.tools,
|
|
1189
|
+
provider_options: mergeProviderOptions(base.provider_options, local.provider_options),
|
|
1190
|
+
mcp: mergeMcp(base.mcp, local.mcp),
|
|
1191
|
+
context: mergeContext(base.context, local.context),
|
|
1192
|
+
includes: local.includes ?? base.includes,
|
|
1193
|
+
environments: mergeOverrideMap(base.environments, local.environments),
|
|
1194
|
+
tiers: mergeOverrideMap(base.tiers, local.tiers),
|
|
1195
|
+
metadata: {
|
|
1196
|
+
...base.metadata ?? {},
|
|
1197
|
+
...local.metadata ?? {}
|
|
1198
|
+
},
|
|
1199
|
+
sections: {
|
|
1200
|
+
...base.sections ?? {},
|
|
1201
|
+
...local.sections ?? {}
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
function applyDefaults(asset, defaults) {
|
|
1206
|
+
const compression = mergeCompression(defaults.compression, asset.compression);
|
|
1207
|
+
const cache = mergeCache(defaults.cache, asset.cache);
|
|
1208
|
+
const raw = mergeRaw(defaults.raw, asset.raw);
|
|
1209
|
+
const providerOptions = mergeProviderOptions(defaults.provider_options, asset.provider_options);
|
|
1210
|
+
const reasoning = mergeRecordBlock2(defaults.reasoning, asset.reasoning);
|
|
1211
|
+
const sampling = mergeRecordBlock2(defaults.sampling, asset.sampling);
|
|
1212
|
+
const response = mergeRecordBlock2(defaults.response, asset.response);
|
|
1213
|
+
const mcp = mergeMcp(defaults.mcp, asset.mcp);
|
|
1214
|
+
const context = mergeContext(defaults.context, asset.context);
|
|
1215
|
+
const environments = mergeOverrideMap(defaults.environments, asset.environments);
|
|
1216
|
+
const tiers = mergeOverrideMap(defaults.tiers, asset.tiers);
|
|
1217
|
+
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
1218
|
+
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
1219
|
+
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0 || defaults.fallback_models !== void 0 || defaults.tools !== void 0 || defaults.includes !== void 0;
|
|
1220
|
+
const hasDefaultObjects = compression !== void 0 || 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;
|
|
1221
|
+
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultObjects) {
|
|
1222
|
+
return asset;
|
|
1015
1223
|
}
|
|
1224
|
+
const mergedMetadata = {
|
|
1225
|
+
...defaults.metadata ?? {},
|
|
1226
|
+
...asset.metadata ?? {}
|
|
1227
|
+
};
|
|
1228
|
+
const metadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : void 0;
|
|
1229
|
+
const systemInstructions = asset.sections?.system_instructions ?? defaults.sections?.system_instructions;
|
|
1230
|
+
const sections = asset.sections ? { ...asset.sections, system_instructions: systemInstructions } : systemInstructions ? { system_instructions: systemInstructions } : void 0;
|
|
1231
|
+
return {
|
|
1232
|
+
...asset,
|
|
1233
|
+
provider: asset.provider ?? defaults.provider,
|
|
1234
|
+
model: asset.model ?? defaults.model,
|
|
1235
|
+
fallback_models: asset.fallback_models ?? defaults.fallback_models,
|
|
1236
|
+
reasoning,
|
|
1237
|
+
sampling,
|
|
1238
|
+
response,
|
|
1239
|
+
compression,
|
|
1240
|
+
cache,
|
|
1241
|
+
raw,
|
|
1242
|
+
tools: asset.tools ?? defaults.tools,
|
|
1243
|
+
provider_options: providerOptions,
|
|
1244
|
+
mcp,
|
|
1245
|
+
context,
|
|
1246
|
+
includes: asset.includes ?? defaults.includes,
|
|
1247
|
+
environments,
|
|
1248
|
+
tiers,
|
|
1249
|
+
metadata,
|
|
1250
|
+
sections
|
|
1251
|
+
};
|
|
1016
1252
|
}
|
|
1017
|
-
function
|
|
1253
|
+
function normalizeDefaultIncludes(defaults, defaultsPath, filePath) {
|
|
1254
|
+
if (!defaults.includes) return defaults;
|
|
1255
|
+
const promptDir = (0, import_node_path2.dirname)(filePath);
|
|
1256
|
+
const defaultsDir = (0, import_node_path2.dirname)(defaultsPath);
|
|
1257
|
+
const includes = defaults.includes.map((includePath) => {
|
|
1258
|
+
const relativePath = (0, import_node_path2.relative)(promptDir, (0, import_node_path2.resolve)(defaultsDir, includePath)).replace(/\\/g, "/");
|
|
1259
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1260
|
+
});
|
|
1018
1261
|
return {
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
1262
|
+
...defaults,
|
|
1263
|
+
includes
|
|
1022
1264
|
};
|
|
1023
1265
|
}
|
|
1024
|
-
function
|
|
1025
|
-
|
|
1266
|
+
function mergeRecordBlock2(base, local) {
|
|
1267
|
+
if (base === void 0) return local;
|
|
1268
|
+
if (local === void 0) return base;
|
|
1269
|
+
return { ...base, ...local };
|
|
1026
1270
|
}
|
|
1027
|
-
function
|
|
1028
|
-
|
|
1029
|
-
return "start";
|
|
1030
|
-
}
|
|
1031
|
-
return "end";
|
|
1271
|
+
function mergeMcp(base, local) {
|
|
1272
|
+
return mergeRecordBlock2(base, local);
|
|
1032
1273
|
}
|
|
1033
|
-
function
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1274
|
+
function mergeContext(base, local) {
|
|
1275
|
+
const merged = {
|
|
1276
|
+
...base ?? {},
|
|
1277
|
+
...local ?? {},
|
|
1278
|
+
history: mergeRecordBlock2(base?.history, local?.history)
|
|
1279
|
+
};
|
|
1280
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1281
|
+
}
|
|
1282
|
+
function mergeCache(base, local) {
|
|
1283
|
+
const merged = {
|
|
1284
|
+
...base ?? {},
|
|
1285
|
+
...local ?? {},
|
|
1286
|
+
openai: {
|
|
1287
|
+
...base?.openai ?? {},
|
|
1288
|
+
...local?.openai ?? {}
|
|
1289
|
+
},
|
|
1290
|
+
anthropic: {
|
|
1291
|
+
...base?.anthropic ?? {},
|
|
1292
|
+
...local?.anthropic ?? {}
|
|
1293
|
+
},
|
|
1294
|
+
gemini: {
|
|
1295
|
+
...base?.gemini ?? {},
|
|
1296
|
+
...local?.gemini ?? {}
|
|
1297
|
+
},
|
|
1298
|
+
google: {
|
|
1299
|
+
...base?.google ?? {},
|
|
1300
|
+
...local?.google ?? {}
|
|
1060
1301
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1302
|
+
};
|
|
1303
|
+
if (merged.openai && Object.keys(merged.openai).length === 0) delete merged.openai;
|
|
1304
|
+
if (merged.anthropic && Object.keys(merged.anthropic).length === 0) delete merged.anthropic;
|
|
1305
|
+
if (merged.gemini && Object.keys(merged.gemini).length === 0) delete merged.gemini;
|
|
1306
|
+
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
1307
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1308
|
+
}
|
|
1309
|
+
function mergeCompression(base, local) {
|
|
1310
|
+
const merged = {
|
|
1311
|
+
...base ?? {},
|
|
1312
|
+
...local ?? {},
|
|
1313
|
+
thetokencompany: mergeRecordBlock2(base?.thetokencompany, local?.thetokencompany)
|
|
1314
|
+
};
|
|
1315
|
+
removeEmptyProviderBlocks(merged);
|
|
1316
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1317
|
+
}
|
|
1318
|
+
function mergeRaw(base, local) {
|
|
1319
|
+
const merged = {
|
|
1320
|
+
...base ?? {},
|
|
1321
|
+
...local ?? {},
|
|
1322
|
+
openai: mergeRecordBlock2(base?.openai, local?.openai),
|
|
1323
|
+
"openai-responses": mergeRecordBlock2(base?.["openai-responses"], local?.["openai-responses"]),
|
|
1324
|
+
openai_responses: mergeRecordBlock2(base?.openai_responses, local?.openai_responses),
|
|
1325
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1326
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1327
|
+
google: mergeRecordBlock2(base?.google, local?.google),
|
|
1328
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1329
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
1330
|
+
};
|
|
1331
|
+
removeEmptyProviderBlocks(merged);
|
|
1332
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1333
|
+
}
|
|
1334
|
+
function mergeProviderOptions(base, local) {
|
|
1335
|
+
const merged = {
|
|
1336
|
+
...base ?? {},
|
|
1337
|
+
...local ?? {},
|
|
1338
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1339
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1340
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1341
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
1342
|
+
};
|
|
1343
|
+
removeEmptyProviderBlocks(merged);
|
|
1344
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1345
|
+
}
|
|
1346
|
+
function mergeOverrideMap(base, local) {
|
|
1347
|
+
const merged = { ...base ?? {} };
|
|
1348
|
+
for (const [name, localOverride] of Object.entries(local ?? {})) {
|
|
1349
|
+
merged[name] = mergeOverrideConfig(merged[name], localOverride);
|
|
1063
1350
|
}
|
|
1064
|
-
return
|
|
1351
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1065
1352
|
}
|
|
1066
|
-
function
|
|
1067
|
-
const
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1353
|
+
function mergeOverrideConfig(base, local) {
|
|
1354
|
+
const merged = {
|
|
1355
|
+
...base ?? {},
|
|
1356
|
+
...local
|
|
1357
|
+
};
|
|
1358
|
+
const reasoning = mergeRecordBlock2(base?.reasoning, local.reasoning);
|
|
1359
|
+
const sampling = mergeRecordBlock2(base?.sampling, local.sampling);
|
|
1360
|
+
const response = mergeRecordBlock2(base?.response, local.response);
|
|
1361
|
+
const compression = mergeCompression(base?.compression, local.compression);
|
|
1362
|
+
const cache = mergeCache(base?.cache, local.cache);
|
|
1363
|
+
const raw = mergeRaw(base?.raw, local.raw);
|
|
1364
|
+
const providerOptions = mergeProviderOptions(base?.provider_options, local.provider_options);
|
|
1365
|
+
if (reasoning !== void 0) merged.reasoning = reasoning;
|
|
1366
|
+
if (sampling !== void 0) merged.sampling = sampling;
|
|
1367
|
+
if (response !== void 0) merged.response = response;
|
|
1368
|
+
if (compression !== void 0) merged.compression = compression;
|
|
1369
|
+
if (cache !== void 0) merged.cache = cache;
|
|
1370
|
+
if (raw !== void 0) merged.raw = raw;
|
|
1371
|
+
if (providerOptions !== void 0) merged.provider_options = providerOptions;
|
|
1372
|
+
return merged;
|
|
1373
|
+
}
|
|
1374
|
+
function removeEmptyProviderBlocks(value) {
|
|
1375
|
+
for (const key of Object.keys(value)) {
|
|
1376
|
+
const block = value[key];
|
|
1377
|
+
if (block === void 0) {
|
|
1378
|
+
delete value[key];
|
|
1072
1379
|
continue;
|
|
1073
1380
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1381
|
+
if (block !== null && typeof block === "object" && !Array.isArray(block) && Object.keys(block).length === 0) {
|
|
1382
|
+
delete value[key];
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
// src/composition/resolve-includes.ts
|
|
1388
|
+
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
1389
|
+
if (!asset.includes || asset.includes.length === 0) {
|
|
1390
|
+
return asset;
|
|
1391
|
+
}
|
|
1392
|
+
const baseDir = (0, import_node_path3.dirname)(basePath);
|
|
1393
|
+
const resolvedPath = (0, import_node_path3.resolve)(basePath);
|
|
1394
|
+
if (visited.has(resolvedPath)) {
|
|
1395
|
+
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
1396
|
+
}
|
|
1397
|
+
visited.add(resolvedPath);
|
|
1398
|
+
let mergedSystemInstructions = "";
|
|
1399
|
+
for (const includePath of asset.includes) {
|
|
1400
|
+
const fullPath = (0, import_node_path3.resolve)(baseDir, includePath);
|
|
1401
|
+
if (visited.has(fullPath)) {
|
|
1402
|
+
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
1086
1403
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1404
|
+
const content = await (0, import_promises3.readFile)(fullPath, "utf-8");
|
|
1405
|
+
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
1406
|
+
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
1407
|
+
if (resolved.sections?.system_instructions) {
|
|
1408
|
+
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
1089
1409
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1410
|
+
}
|
|
1411
|
+
const localSystem = asset.sections?.system_instructions ?? "";
|
|
1412
|
+
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
1413
|
+
return {
|
|
1414
|
+
...asset,
|
|
1415
|
+
sections: {
|
|
1416
|
+
...asset.sections,
|
|
1417
|
+
system_instructions: combinedSystem
|
|
1418
|
+
},
|
|
1419
|
+
// Drop includes from the resolved asset — they've been inlined
|
|
1420
|
+
includes: void 0
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// src/prompt-resolution.ts
|
|
1425
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
1426
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
1427
|
+
function withPromptResolutionDefaults(config) {
|
|
1428
|
+
return {
|
|
1429
|
+
...config,
|
|
1430
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
1431
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
var sharedPromptCache = new PromptCache();
|
|
1435
|
+
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
1436
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1437
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
1438
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
1439
|
+
const compiledFile = (0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json");
|
|
1440
|
+
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
1441
|
+
if (mode === "auto") {
|
|
1442
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1443
|
+
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1444
|
+
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
1445
|
+
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
1446
|
+
if (sourceMtime > compiledMtime) {
|
|
1447
|
+
console.warn(
|
|
1448
|
+
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
1449
|
+
Run "promptopskit compile" or switch to source-only mode.`
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1109
1452
|
}
|
|
1110
|
-
throw new Error(
|
|
1111
|
-
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
1112
|
-
);
|
|
1113
1453
|
}
|
|
1454
|
+
const content = await (0, import_promises4.readFile)(compiledFile, "utf-8");
|
|
1455
|
+
return JSON.parse(content);
|
|
1114
1456
|
}
|
|
1115
|
-
if (
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
code: "POK032",
|
|
1129
|
-
variable: input.name,
|
|
1130
|
-
field: "deny_regex"
|
|
1131
|
-
}
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
|
-
throw new Error(
|
|
1135
|
-
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
1136
|
-
);
|
|
1457
|
+
if (mode === "compiled-only") {
|
|
1458
|
+
throw new Error(
|
|
1459
|
+
`Compiled artifact not found: ${compiledFile}
|
|
1460
|
+
Run "promptopskit compile" to generate it.`
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
if (mode !== "compiled-only") {
|
|
1465
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1466
|
+
if (resolvedConfig.cache !== false) {
|
|
1467
|
+
const cached = promptCache.get(sourceFile);
|
|
1468
|
+
if (cached) {
|
|
1469
|
+
return cached;
|
|
1137
1470
|
}
|
|
1138
1471
|
}
|
|
1139
|
-
if (
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
shortCircuit: {
|
|
1144
|
-
returnMessage: input.non_empty.returnMessage,
|
|
1145
|
-
code: "POK033",
|
|
1146
|
-
variable: input.name,
|
|
1147
|
-
field: "non_empty"
|
|
1148
|
-
}
|
|
1149
|
-
};
|
|
1472
|
+
if (!(0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1473
|
+
const paths = [sourceFile];
|
|
1474
|
+
if (resolvedConfig.compiledDir) {
|
|
1475
|
+
paths.unshift((0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
1150
1476
|
}
|
|
1151
1477
|
throw new Error(
|
|
1152
|
-
`
|
|
1478
|
+
`Prompt not found: "${promptPath}"
|
|
1479
|
+
Searched:
|
|
1480
|
+
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
1153
1481
|
);
|
|
1154
1482
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
variable: input.name,
|
|
1159
|
-
field: "reject_secrets"
|
|
1160
|
-
});
|
|
1161
|
-
if (matcher.test(candidate)) {
|
|
1162
|
-
if (input.reject_secrets.returnMessage) {
|
|
1163
|
-
return {
|
|
1164
|
-
variables: sanitized,
|
|
1165
|
-
shortCircuit: {
|
|
1166
|
-
returnMessage: input.reject_secrets.returnMessage,
|
|
1167
|
-
code: "POK034",
|
|
1168
|
-
variable: input.name,
|
|
1169
|
-
field: "reject_secrets"
|
|
1170
|
-
}
|
|
1171
|
-
};
|
|
1172
|
-
}
|
|
1173
|
-
throw new Error(
|
|
1174
|
-
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
1175
|
-
);
|
|
1176
|
-
}
|
|
1483
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
1484
|
+
if (resolvedConfig.cache !== false) {
|
|
1485
|
+
promptCache.set(sourceFile, asset);
|
|
1177
1486
|
}
|
|
1487
|
+
return asset;
|
|
1178
1488
|
}
|
|
1179
|
-
|
|
1180
|
-
}
|
|
1181
|
-
function measureContextValueSize(value) {
|
|
1182
|
-
return textEncoder.encode(value).length;
|
|
1489
|
+
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
1183
1490
|
}
|
|
1184
|
-
function
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
const value = variables[input.name];
|
|
1191
|
-
if (value === void 0) {
|
|
1192
|
-
continue;
|
|
1193
|
-
}
|
|
1194
|
-
const actualSize = measureContextValueSize(value);
|
|
1195
|
-
if (actualSize > input.max_size) {
|
|
1196
|
-
warnings.push({
|
|
1197
|
-
variable: input.name,
|
|
1198
|
-
maxSize: input.max_size,
|
|
1199
|
-
actualSize
|
|
1200
|
-
});
|
|
1201
|
-
}
|
|
1491
|
+
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
1492
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1493
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
1494
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1495
|
+
if (asset.includes && asset.includes.length > 0 && (0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1496
|
+
asset = await resolveIncludes(asset, sourceFile);
|
|
1202
1497
|
}
|
|
1203
|
-
|
|
1498
|
+
asset = applyOverrides(asset, {
|
|
1499
|
+
environment: options.environment,
|
|
1500
|
+
tier: options.tier,
|
|
1501
|
+
runtime: options.runtime
|
|
1502
|
+
});
|
|
1503
|
+
return asset;
|
|
1504
|
+
}
|
|
1505
|
+
function resolveInlinePromptSource(source, options = {}) {
|
|
1506
|
+
const { asset } = parsePrompt(source);
|
|
1507
|
+
return applyOverrides(asset, {
|
|
1508
|
+
environment: options.environment,
|
|
1509
|
+
tier: options.tier,
|
|
1510
|
+
runtime: options.runtime
|
|
1511
|
+
});
|
|
1204
1512
|
}
|
|
1205
1513
|
|
|
1206
1514
|
// src/history.ts
|
|
@@ -1253,6 +1561,97 @@ function compactHistoryForPrompt(asset, runtime) {
|
|
|
1253
1561
|
return [compacted, ...preserved];
|
|
1254
1562
|
}
|
|
1255
1563
|
|
|
1564
|
+
// src/compression.ts
|
|
1565
|
+
var THETOKENCOMPANY_DEFAULT_MODEL = "bear-2";
|
|
1566
|
+
var THETOKENCOMPANY_DEFAULT_BASE_URL = "https://api.thetokencompany.com";
|
|
1567
|
+
async function applyPromptCompressionForRender(asset, runtime) {
|
|
1568
|
+
const config = asset.compression?.thetokencompany;
|
|
1569
|
+
if (config?.enabled !== true || !asset.sections.prompt_template) {
|
|
1570
|
+
return { asset, runtime, compression: [] };
|
|
1571
|
+
}
|
|
1572
|
+
const sections = renderSections(asset, {
|
|
1573
|
+
variables: runtime.variables,
|
|
1574
|
+
strict: runtime.strict
|
|
1575
|
+
});
|
|
1576
|
+
if (!sections.prompt_template) {
|
|
1577
|
+
return { asset, runtime, compression: [] };
|
|
1578
|
+
}
|
|
1579
|
+
const model = config.model ?? THETOKENCOMPANY_DEFAULT_MODEL;
|
|
1580
|
+
const result = await compressWithTheTokenCompany(sections.prompt_template, {
|
|
1581
|
+
apiKey: runtime.theTokenCompany?.apiKey,
|
|
1582
|
+
baseURL: runtime.theTokenCompany?.baseURL,
|
|
1583
|
+
fetch: runtime.theTokenCompany?.fetch,
|
|
1584
|
+
model,
|
|
1585
|
+
aggressiveness: config.aggressiveness
|
|
1586
|
+
});
|
|
1587
|
+
return {
|
|
1588
|
+
asset: {
|
|
1589
|
+
...asset,
|
|
1590
|
+
sections: {
|
|
1591
|
+
...asset.sections,
|
|
1592
|
+
...sections,
|
|
1593
|
+
prompt_template: result.output
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
runtime: {
|
|
1597
|
+
...runtime,
|
|
1598
|
+
variables: {},
|
|
1599
|
+
strict: false
|
|
1600
|
+
},
|
|
1601
|
+
compression: [{
|
|
1602
|
+
provider: "thetokencompany",
|
|
1603
|
+
model,
|
|
1604
|
+
inputTokens: result.input_tokens,
|
|
1605
|
+
outputTokens: result.output_tokens,
|
|
1606
|
+
tokensSaved: result.tokens_saved,
|
|
1607
|
+
compressionRatio: result.compression_ratio
|
|
1608
|
+
}]
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
async function compressWithTheTokenCompany(input, options) {
|
|
1612
|
+
const apiKey = options.apiKey ?? getEnv("THETOKENCOMPANY_API_KEY") ?? getEnv("TTC_API_KEY");
|
|
1613
|
+
if (!apiKey) {
|
|
1614
|
+
throw new Error(
|
|
1615
|
+
"TheTokenCompany compression is enabled, but no API key was provided. Pass theTokenCompany.apiKey to renderPrompt() or set THETOKENCOMPANY_API_KEY."
|
|
1616
|
+
);
|
|
1617
|
+
}
|
|
1618
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1619
|
+
if (!fetchImpl) {
|
|
1620
|
+
throw new Error("TheTokenCompany compression requires a runtime with fetch support.");
|
|
1621
|
+
}
|
|
1622
|
+
const baseURL = (options.baseURL ?? THETOKENCOMPANY_DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
1623
|
+
const compressionSettings = options.aggressiveness === void 0 ? void 0 : { aggressiveness: options.aggressiveness };
|
|
1624
|
+
const response = await fetchImpl(`${baseURL}/v1/compress`, {
|
|
1625
|
+
method: "POST",
|
|
1626
|
+
headers: {
|
|
1627
|
+
Authorization: `Bearer ${apiKey}`,
|
|
1628
|
+
"Content-Type": "application/json"
|
|
1629
|
+
},
|
|
1630
|
+
body: JSON.stringify({
|
|
1631
|
+
model: options.model,
|
|
1632
|
+
input,
|
|
1633
|
+
...compressionSettings ? { compression_settings: compressionSettings } : {}
|
|
1634
|
+
})
|
|
1635
|
+
});
|
|
1636
|
+
if (!response.ok) {
|
|
1637
|
+
const body = await response.text().catch(() => "");
|
|
1638
|
+
throw new Error(
|
|
1639
|
+
`TheTokenCompany compression failed with HTTP ${response.status}` + (body ? `: ${body}` : ".")
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
const data = await response.json();
|
|
1643
|
+
if (typeof data.output !== "string" || typeof data.output_tokens !== "number" || typeof data.input_tokens !== "number" || typeof data.tokens_saved !== "number" || typeof data.compression_ratio !== "number") {
|
|
1644
|
+
throw new Error("TheTokenCompany compression returned an invalid response payload.");
|
|
1645
|
+
}
|
|
1646
|
+
return data;
|
|
1647
|
+
}
|
|
1648
|
+
function getEnv(name) {
|
|
1649
|
+
if (typeof process === "undefined") {
|
|
1650
|
+
return void 0;
|
|
1651
|
+
}
|
|
1652
|
+
return process.env[name];
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1256
1655
|
// src/providers/prompt-input.ts
|
|
1257
1656
|
function isPromptLookup(input) {
|
|
1258
1657
|
return "path" in input && typeof input.path === "string";
|
|
@@ -1276,21 +1675,27 @@ function withPromptInputSupport(adapter) {
|
|
|
1276
1675
|
};
|
|
1277
1676
|
const renderPrompt2 = async (input, runtime) => {
|
|
1278
1677
|
const resolved = await resolveProviderPromptInput(input, runtime);
|
|
1279
|
-
const
|
|
1678
|
+
const resolvedForRender = resolveAssetForProvider(resolved, runtime);
|
|
1679
|
+
const sanitization = sanitizeContextVariables(resolvedForRender, runtime.variables, {
|
|
1280
1680
|
onContextOverflow: runtime.onContextOverflow
|
|
1281
1681
|
});
|
|
1282
1682
|
if (sanitization.shortCircuit) {
|
|
1283
1683
|
return {
|
|
1284
1684
|
provider: adapter.name,
|
|
1285
|
-
model:
|
|
1685
|
+
model: resolvedForRender.model ?? "",
|
|
1286
1686
|
returnMessage: sanitization.shortCircuit.returnMessage
|
|
1287
1687
|
};
|
|
1288
1688
|
}
|
|
1289
|
-
|
|
1689
|
+
const prepared = await applyPromptCompressionForRender(resolvedForRender, {
|
|
1290
1690
|
...runtime,
|
|
1691
|
+
environment: void 0,
|
|
1692
|
+
tier: void 0,
|
|
1693
|
+
runtime: void 0,
|
|
1291
1694
|
variables: sanitization.variables,
|
|
1292
|
-
history: compactHistoryForPrompt(
|
|
1695
|
+
history: compactHistoryForPrompt(resolvedForRender, runtime)
|
|
1293
1696
|
});
|
|
1697
|
+
const request = adapter.render(prepared.asset, prepared.runtime);
|
|
1698
|
+
return prepared.compression.length > 0 ? { ...request, compression: prepared.compression } : request;
|
|
1294
1699
|
};
|
|
1295
1700
|
return {
|
|
1296
1701
|
...adapter,
|
|
@@ -1982,9 +2387,22 @@ var KNOWN_FRONT_MATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
1982
2387
|
"tiers",
|
|
1983
2388
|
"metadata",
|
|
1984
2389
|
"cache",
|
|
2390
|
+
"compression",
|
|
1985
2391
|
"provider_options",
|
|
1986
2392
|
"raw"
|
|
1987
2393
|
]);
|
|
2394
|
+
function collectSchemaKeywords(value, acc) {
|
|
2395
|
+
if (!value || typeof value !== "object") return;
|
|
2396
|
+
if (Array.isArray(value)) {
|
|
2397
|
+
for (const item of value) collectSchemaKeywords(item, acc);
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2400
|
+
const record = value;
|
|
2401
|
+
for (const [key, child] of Object.entries(record)) {
|
|
2402
|
+
acc.add(key);
|
|
2403
|
+
collectSchemaKeywords(child, acc);
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
1988
2406
|
var RISKY_UNBOUNDED_INPUT_NAMES = [
|
|
1989
2407
|
"message",
|
|
1990
2408
|
"prompt",
|
|
@@ -2036,7 +2454,9 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2036
2454
|
}
|
|
2037
2455
|
}
|
|
2038
2456
|
}
|
|
2039
|
-
const
|
|
2457
|
+
const contextInputs = getContextInputs(asset);
|
|
2458
|
+
const declaredInputs = new Set(contextInputs.map((input) => input.name));
|
|
2459
|
+
const declaredInputsByName = new Map(contextInputs.map((input) => [input.name, input]));
|
|
2040
2460
|
const usedVars = /* @__PURE__ */ new Set();
|
|
2041
2461
|
if (asset.sections?.system_instructions) {
|
|
2042
2462
|
for (const v of extractVariables(asset.sections.system_instructions)) {
|
|
@@ -2058,7 +2478,8 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2058
2478
|
}
|
|
2059
2479
|
}
|
|
2060
2480
|
for (const v of declaredInputs) {
|
|
2061
|
-
|
|
2481
|
+
const input = declaredInputsByName.get(v);
|
|
2482
|
+
if (!usedVars.has(v) && input?.optional !== true && areContextInputWarningsEnabled(input ?? {})) {
|
|
2062
2483
|
warnings.push({
|
|
2063
2484
|
code: "POK012",
|
|
2064
2485
|
message: `Variable "${v}" is declared in context.inputs but never used`,
|
|
@@ -2074,9 +2495,10 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2074
2495
|
suggestion: "Declare context.inputs to enable input policy validation."
|
|
2075
2496
|
});
|
|
2076
2497
|
}
|
|
2077
|
-
for (const input of
|
|
2498
|
+
for (const input of contextInputs) {
|
|
2078
2499
|
const lowerName = input.name.toLowerCase();
|
|
2079
|
-
|
|
2500
|
+
const inputWarningsEnabled = areContextInputWarningsEnabled(input);
|
|
2501
|
+
if (inputWarningsEnabled && input.max_size === void 0 && RISKY_UNBOUNDED_INPUT_NAMES.some((needle) => lowerName.includes(needle))) {
|
|
2080
2502
|
warnings.push({
|
|
2081
2503
|
code: "POK040",
|
|
2082
2504
|
message: `Context input "${input.name}" has no max_size and appears unbounded.`,
|
|
@@ -2084,7 +2506,7 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2084
2506
|
suggestion: "Add max_size to constrain prompt payload growth."
|
|
2085
2507
|
});
|
|
2086
2508
|
}
|
|
2087
|
-
if (input.allow_regex === void 0 && input.deny_regex === void 0 && input.non_empty === void 0 && input.reject_secrets === void 0) {
|
|
2509
|
+
if (inputWarningsEnabled && input.optional !== true && input.allow_regex === void 0 && input.deny_regex === void 0 && input.non_empty === void 0 && input.reject_secrets === void 0) {
|
|
2088
2510
|
warnings.push({
|
|
2089
2511
|
code: "POK041",
|
|
2090
2512
|
message: `Context input "${input.name}" has no input hardening validators.`,
|
|
@@ -2092,7 +2514,7 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2092
2514
|
suggestion: "Consider non_empty/reject_secrets and allow/deny regex validators."
|
|
2093
2515
|
});
|
|
2094
2516
|
}
|
|
2095
|
-
if (input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
2517
|
+
if (inputWarningsEnabled && input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
2096
2518
|
warnings.push({
|
|
2097
2519
|
code: "POK014",
|
|
2098
2520
|
message: `Context input "${input.name}" sets trim but has no max_size; trim-to-budget will be skipped.`,
|
|
@@ -2119,6 +2541,30 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
2119
2541
|
}
|
|
2120
2542
|
}
|
|
2121
2543
|
}
|
|
2544
|
+
if (asset.response?.schema && asset.provider) {
|
|
2545
|
+
const keywords = /* @__PURE__ */ new Set();
|
|
2546
|
+
collectSchemaKeywords(asset.response.schema, keywords);
|
|
2547
|
+
const openAIUnsupported = ["patternProperties", "unevaluatedProperties", "$dynamicRef"];
|
|
2548
|
+
const geminiUnsupported = ["patternProperties", "$dynamicRef", "dependentSchemas"];
|
|
2549
|
+
const anthropicCaution = ["if", "then", "else"];
|
|
2550
|
+
const checks = [
|
|
2551
|
+
{ provider: ["openai", "openai-responses", "openrouter", "llmasaservice"], unsupported: openAIUnsupported, code: "POK052" },
|
|
2552
|
+
{ provider: ["gemini", "google"], unsupported: geminiUnsupported, code: "POK053" },
|
|
2553
|
+
{ provider: ["anthropic"], unsupported: anthropicCaution, code: "POK054" }
|
|
2554
|
+
];
|
|
2555
|
+
for (const check of checks) {
|
|
2556
|
+
if (!check.provider.includes(asset.provider)) continue;
|
|
2557
|
+
const hits = check.unsupported.filter((k) => keywords.has(k));
|
|
2558
|
+
if (hits.length > 0) {
|
|
2559
|
+
warnings.push({
|
|
2560
|
+
code: check.code,
|
|
2561
|
+
message: `response.schema includes provider-sensitive JSON Schema keywords for "${asset.provider}": ${hits.join(", ")}`,
|
|
2562
|
+
filePath,
|
|
2563
|
+
suggestion: "Validate schema compatibility with your provider docs or simplify the schema dialect."
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2122
2568
|
if (asset.provider) {
|
|
2123
2569
|
let providerCache;
|
|
2124
2570
|
let cacheSuggestionField;
|
|
@@ -2712,7 +3158,7 @@ var PromptOpsKit = class {
|
|
|
2712
3158
|
console.warn(`[promptopskit] Warning: ${warning}`);
|
|
2713
3159
|
}
|
|
2714
3160
|
}
|
|
2715
|
-
const
|
|
3161
|
+
const prepared = await applyPromptCompressionForRender(resolved, {
|
|
2716
3162
|
variables: sanitization.variables,
|
|
2717
3163
|
history: compactHistoryForPrompt(resolved, {
|
|
2718
3164
|
history: options.history,
|
|
@@ -2721,11 +3167,14 @@ var PromptOpsKit = class {
|
|
|
2721
3167
|
onHistoryCompaction: options.onHistoryCompaction,
|
|
2722
3168
|
toolRegistry: options.toolRegistry,
|
|
2723
3169
|
strict: options.strict,
|
|
2724
|
-
openaiResponses: options.openaiResponses
|
|
3170
|
+
openaiResponses: options.openaiResponses,
|
|
3171
|
+
theTokenCompany: options.theTokenCompany
|
|
2725
3172
|
});
|
|
3173
|
+
const request = adapter.render(prepared.asset, prepared.runtime);
|
|
2726
3174
|
return {
|
|
2727
3175
|
resolved,
|
|
2728
|
-
request,
|
|
3176
|
+
request: prepared.compression.length > 0 ? { ...request, compression: prepared.compression } : request,
|
|
3177
|
+
...prepared.compression.length > 0 ? { compression: prepared.compression } : {},
|
|
2729
3178
|
warnings: shouldIncludeContextWarningsInResult(contextWarningPolicy) ? [...validation.warnings, ...contextSizeWarnings] : validation.warnings
|
|
2730
3179
|
};
|
|
2731
3180
|
}
|
|
@@ -2733,7 +3182,7 @@ var PromptOpsKit = class {
|
|
|
2733
3182
|
* Validate a prompt file.
|
|
2734
3183
|
*/
|
|
2735
3184
|
async validatePrompt(promptPath) {
|
|
2736
|
-
const sourceFile = (0,
|
|
3185
|
+
const sourceFile = (0, import_node_path5.resolve)(this.config.sourceDir, promptPath + ".md");
|
|
2737
3186
|
try {
|
|
2738
3187
|
const asset = await this.loadPrompt(promptPath);
|
|
2739
3188
|
return validateAssetWithIncludes(asset, sourceFile);
|
|
@@ -2790,6 +3239,8 @@ async function renderPrompt(options) {
|
|
|
2790
3239
|
PromptAssetOverridesSchema,
|
|
2791
3240
|
PromptAssetSchema,
|
|
2792
3241
|
PromptOpsKit,
|
|
3242
|
+
THETOKENCOMPANY_DEFAULT_BASE_URL,
|
|
3243
|
+
THETOKENCOMPANY_DEFAULT_MODEL,
|
|
2793
3244
|
anthropicAdapter,
|
|
2794
3245
|
applyOverrides,
|
|
2795
3246
|
applyUsageTapEntitlements,
|