promptopskit 0.4.2 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -62
- package/SKILL.md +376 -16
- package/dist/{chunk-7MRMN3SW.js → chunk-55B7QQBK.js} +6 -4
- package/dist/chunk-55B7QQBK.js.map +1 -0
- package/dist/{chunk-HWEVRBKZ.js → chunk-AGTGIZMR.js} +6 -2
- package/dist/chunk-AGTGIZMR.js.map +1 -0
- package/dist/chunk-FNCIBZJF.js +130 -0
- package/dist/chunk-FNCIBZJF.js.map +1 -0
- package/dist/{chunk-XL76NHZR.js → chunk-GLT3YYWK.js} +6 -4
- package/dist/chunk-GLT3YYWK.js.map +1 -0
- package/dist/{chunk-5AAYDOPU.js → chunk-IPFD5Y3O.js} +4 -3
- package/dist/chunk-IPFD5Y3O.js.map +1 -0
- package/dist/{chunk-YI4LILPY.js → chunk-JR7252DG.js} +584 -520
- package/dist/chunk-JR7252DG.js.map +1 -0
- package/dist/{chunk-JKBWC5WJ.js → chunk-UY5OKMVP.js} +302 -21
- package/dist/chunk-UY5OKMVP.js.map +1 -0
- package/dist/{chunk-MI3M6KDD.js → chunk-VMLGUI4F.js} +6 -4
- package/dist/chunk-VMLGUI4F.js.map +1 -0
- package/dist/{chunk-Z4IPWEUU.js → chunk-XEZJZ3IG.js} +6 -4
- package/dist/chunk-XEZJZ3IG.js.map +1 -0
- package/dist/cli/index.js +435 -106
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +1159 -636
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.js +79 -17
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +875 -533
- 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 +875 -533
- 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 +1735 -0
- package/dist/providers/llmasaservice.cjs.map +1 -0
- package/dist/providers/llmasaservice.d.cts +28 -0
- package/dist/providers/llmasaservice.d.ts +28 -0
- package/dist/providers/llmasaservice.js +20 -0
- package/dist/providers/llmasaservice.js.map +1 -0
- package/dist/providers/openai-responses.cjs +875 -533
- 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 +875 -533
- 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 +876 -533
- 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-B9A1zLRk.d.cts → schema-CuYsv8JA.d.cts} +853 -7
- package/dist/{schema-B9A1zLRk.d.ts → schema-CuYsv8JA.d.ts} +853 -7
- package/dist/testing.cjs +64 -9
- 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-DjGAwJxC.d.ts → types-DpK0mTHL.d.ts} +18 -6
- package/dist/{types-DpbzzZO2.d.cts → types-UA_p9uJy.d.cts} +18 -6
- package/dist/usagetap/index.cjs +6 -1
- package/dist/usagetap/index.cjs.map +1 -1
- package/dist/usagetap/index.d.cts +4 -3
- package/dist/usagetap/index.d.ts +4 -3
- package/dist/usagetap/index.js +3 -1
- package/package.json +19 -2
- package/dist/chunk-5AAYDOPU.js.map +0 -1
- package/dist/chunk-7MRMN3SW.js.map +0 -1
- package/dist/chunk-HWEVRBKZ.js.map +0 -1
- package/dist/chunk-JKBWC5WJ.js.map +0 -1
- package/dist/chunk-MI3M6KDD.js.map +0 -1
- package/dist/chunk-XL76NHZR.js.map +0 -1
- package/dist/chunk-YI4LILPY.js.map +0 -1
- package/dist/chunk-Z4IPWEUU.js.map +0 -1
|
@@ -0,0 +1,1735 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/providers/llmasaservice.ts
|
|
31
|
+
var llmasaservice_exports = {};
|
|
32
|
+
__export(llmasaservice_exports, {
|
|
33
|
+
LLMASASERVICE_BASE_URL: () => LLMASASERVICE_BASE_URL,
|
|
34
|
+
LLMASASERVICE_DEFAULT_MODEL: () => LLMASASERVICE_DEFAULT_MODEL,
|
|
35
|
+
LLMASASERVICE_RESPONSE_HEADER_NAMES: () => LLMASASERVICE_RESPONSE_HEADER_NAMES,
|
|
36
|
+
LLMASASERVICE_SDK_PLACEHOLDER_API_KEY: () => LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,
|
|
37
|
+
createLLMAsAServiceOpenAIConfig: () => createLLMAsAServiceOpenAIConfig,
|
|
38
|
+
llmasaserviceAdapter: () => llmasaserviceAdapter
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(llmasaservice_exports);
|
|
41
|
+
|
|
42
|
+
// src/renderer/interpolate.ts
|
|
43
|
+
var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
44
|
+
var ESCAPED_OPEN = /\\\{\\\{/g;
|
|
45
|
+
var ESCAPE_PLACEHOLDER = "\0ESCAPED_OPEN\0";
|
|
46
|
+
function interpolate(template, variables, options = {}) {
|
|
47
|
+
const { strict = false } = options;
|
|
48
|
+
const optionalVariables = new Set(options.optionalVariables ?? []);
|
|
49
|
+
let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);
|
|
50
|
+
result = result.replace(VARIABLE_RE, (match, name) => {
|
|
51
|
+
if (name in variables) {
|
|
52
|
+
return variables[name];
|
|
53
|
+
}
|
|
54
|
+
if (strict && !optionalVariables.has(name)) {
|
|
55
|
+
throw new Error(`Missing required variable: "${name}"`);
|
|
56
|
+
}
|
|
57
|
+
return match;
|
|
58
|
+
});
|
|
59
|
+
result = result.replaceAll(ESCAPE_PLACEHOLDER, "{{");
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/context.ts
|
|
64
|
+
var textEncoder = new TextEncoder();
|
|
65
|
+
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
66
|
+
var REJECT_SECRETS_FLAGS = "i";
|
|
67
|
+
function getContextInputs(asset) {
|
|
68
|
+
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
69
|
+
}
|
|
70
|
+
function normalizeContextInput(input) {
|
|
71
|
+
if (typeof input === "string") {
|
|
72
|
+
return { name: input };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
name: input.name,
|
|
76
|
+
optional: input.optional,
|
|
77
|
+
warnings: input.warnings,
|
|
78
|
+
max_size: input.max_size,
|
|
79
|
+
trim: input.trim,
|
|
80
|
+
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
81
|
+
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
82
|
+
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
83
|
+
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function normalizeContextRegex(value) {
|
|
87
|
+
if (value === void 0) {
|
|
88
|
+
return void 0;
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
const literal = parseRegexLiteral(value);
|
|
92
|
+
if (value.startsWith("/") && !literal) {
|
|
93
|
+
return {
|
|
94
|
+
pattern: value,
|
|
95
|
+
flags: "",
|
|
96
|
+
raw: value,
|
|
97
|
+
invalidLiteral: true
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
pattern: literal?.pattern ?? value,
|
|
102
|
+
flags: literal?.flags ?? "",
|
|
103
|
+
raw: value
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
pattern: value.pattern,
|
|
108
|
+
flags: value.flags ?? "",
|
|
109
|
+
raw: JSON.stringify(value),
|
|
110
|
+
returnMessage: value.return_message
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function normalizeBuiltInValidator(value) {
|
|
114
|
+
if (value === void 0 || value === false) {
|
|
115
|
+
return void 0;
|
|
116
|
+
}
|
|
117
|
+
if (value === true) {
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
returnMessage: value.return_message
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function parseRegexLiteral(value) {
|
|
125
|
+
if (!value.startsWith("/")) {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
129
|
+
if (value[index] !== "/") {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
let backslashCount = 0;
|
|
133
|
+
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
134
|
+
backslashCount += 1;
|
|
135
|
+
}
|
|
136
|
+
if (backslashCount % 2 === 1) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
pattern: value.slice(1, index),
|
|
141
|
+
flags: value.slice(index + 1)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
146
|
+
function formatInvalidContextRegexMessage(details) {
|
|
147
|
+
return [
|
|
148
|
+
`Invalid context regex for prompt "${details.promptId}"`,
|
|
149
|
+
`variable "${details.variable}"`,
|
|
150
|
+
`field "${details.field}"`,
|
|
151
|
+
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
152
|
+
].join(", ");
|
|
153
|
+
}
|
|
154
|
+
function compileContextRegex(regex, details) {
|
|
155
|
+
if (regex.invalidLiteral) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`POK013: ${formatInvalidContextRegexMessage({
|
|
158
|
+
...details,
|
|
159
|
+
raw: regex.raw,
|
|
160
|
+
reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
|
|
161
|
+
})}`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
return new RegExp(regex.pattern, regex.flags);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
168
|
+
throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function getRejectSecretsRegex() {
|
|
172
|
+
return {
|
|
173
|
+
pattern: REJECT_SECRETS_PATTERN,
|
|
174
|
+
flags: REJECT_SECRETS_FLAGS,
|
|
175
|
+
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function isTrimEnabled(mode) {
|
|
179
|
+
return mode === true || mode === "start" || mode === "end" || mode === "both";
|
|
180
|
+
}
|
|
181
|
+
function normalizeTrimMode(mode) {
|
|
182
|
+
if (mode === "start") {
|
|
183
|
+
return "start";
|
|
184
|
+
}
|
|
185
|
+
return "end";
|
|
186
|
+
}
|
|
187
|
+
function trimToMaxSize(value, maxSize, mode) {
|
|
188
|
+
const measured = measureContextValueSize(value);
|
|
189
|
+
if (measured <= maxSize) {
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
const characters = Array.from(value);
|
|
193
|
+
const normalizedMode = normalizeTrimMode(mode);
|
|
194
|
+
if (normalizedMode === "start") {
|
|
195
|
+
let collected2 = "";
|
|
196
|
+
let size2 = 0;
|
|
197
|
+
for (let i = characters.length - 1; i >= 0; i -= 1) {
|
|
198
|
+
const next = characters[i];
|
|
199
|
+
const charSize = measureContextValueSize(next);
|
|
200
|
+
if (size2 + charSize > maxSize) {
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
collected2 = next + collected2;
|
|
204
|
+
size2 += charSize;
|
|
205
|
+
}
|
|
206
|
+
return collected2;
|
|
207
|
+
}
|
|
208
|
+
let collected = "";
|
|
209
|
+
let size = 0;
|
|
210
|
+
for (const char of characters) {
|
|
211
|
+
const charSize = measureContextValueSize(char);
|
|
212
|
+
if (size + charSize > maxSize) {
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
collected += char;
|
|
216
|
+
size += charSize;
|
|
217
|
+
}
|
|
218
|
+
return collected;
|
|
219
|
+
}
|
|
220
|
+
function sanitizeContextVariables(asset, variables = {}, options = {}) {
|
|
221
|
+
const { onContextOverflow } = options;
|
|
222
|
+
const sanitized = { ...variables };
|
|
223
|
+
for (const input of getContextInputs(asset)) {
|
|
224
|
+
const value = sanitized[input.name];
|
|
225
|
+
if (value === void 0) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
let candidate = value;
|
|
229
|
+
if (input.max_size !== void 0) {
|
|
230
|
+
const actualSize = measureContextValueSize(candidate);
|
|
231
|
+
if (actualSize > input.max_size && onContextOverflow) {
|
|
232
|
+
candidate = onContextOverflow({
|
|
233
|
+
promptId: asset.id,
|
|
234
|
+
variable: input.name,
|
|
235
|
+
value: candidate,
|
|
236
|
+
maxSize: input.max_size,
|
|
237
|
+
actualSize
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (isTrimEnabled(input.trim) && input.max_size !== void 0) {
|
|
242
|
+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
|
|
243
|
+
}
|
|
244
|
+
sanitized[input.name] = candidate;
|
|
245
|
+
if (input.allow_regex) {
|
|
246
|
+
const candidate2 = sanitized[input.name];
|
|
247
|
+
const matcher = compileContextRegex(input.allow_regex, {
|
|
248
|
+
promptId: asset.id,
|
|
249
|
+
variable: input.name,
|
|
250
|
+
field: "allow_regex"
|
|
251
|
+
});
|
|
252
|
+
if (!matcher.test(candidate2)) {
|
|
253
|
+
if (input.allow_regex.returnMessage) {
|
|
254
|
+
return {
|
|
255
|
+
variables: sanitized,
|
|
256
|
+
shortCircuit: {
|
|
257
|
+
returnMessage: input.allow_regex.returnMessage,
|
|
258
|
+
code: "POK031",
|
|
259
|
+
variable: input.name,
|
|
260
|
+
field: "allow_regex"
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
throw new Error(
|
|
265
|
+
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (input.deny_regex) {
|
|
270
|
+
const candidate2 = sanitized[input.name];
|
|
271
|
+
const matcher = compileContextRegex(input.deny_regex, {
|
|
272
|
+
promptId: asset.id,
|
|
273
|
+
variable: input.name,
|
|
274
|
+
field: "deny_regex"
|
|
275
|
+
});
|
|
276
|
+
if (matcher.test(candidate2)) {
|
|
277
|
+
if (input.deny_regex.returnMessage) {
|
|
278
|
+
return {
|
|
279
|
+
variables: sanitized,
|
|
280
|
+
shortCircuit: {
|
|
281
|
+
returnMessage: input.deny_regex.returnMessage,
|
|
282
|
+
code: "POK032",
|
|
283
|
+
variable: input.name,
|
|
284
|
+
field: "deny_regex"
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
throw new Error(
|
|
289
|
+
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (input.non_empty && candidate.trim().length === 0) {
|
|
294
|
+
if (input.non_empty.returnMessage) {
|
|
295
|
+
return {
|
|
296
|
+
variables: sanitized,
|
|
297
|
+
shortCircuit: {
|
|
298
|
+
returnMessage: input.non_empty.returnMessage,
|
|
299
|
+
code: "POK033",
|
|
300
|
+
variable: input.name,
|
|
301
|
+
field: "non_empty"
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
throw new Error(
|
|
306
|
+
`POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
if (input.reject_secrets) {
|
|
310
|
+
const matcher = compileContextRegex(getRejectSecretsRegex(), {
|
|
311
|
+
promptId: asset.id,
|
|
312
|
+
variable: input.name,
|
|
313
|
+
field: "reject_secrets"
|
|
314
|
+
});
|
|
315
|
+
if (matcher.test(candidate)) {
|
|
316
|
+
if (input.reject_secrets.returnMessage) {
|
|
317
|
+
return {
|
|
318
|
+
variables: sanitized,
|
|
319
|
+
shortCircuit: {
|
|
320
|
+
returnMessage: input.reject_secrets.returnMessage,
|
|
321
|
+
code: "POK034",
|
|
322
|
+
variable: input.name,
|
|
323
|
+
field: "reject_secrets"
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
throw new Error(
|
|
328
|
+
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return { variables: sanitized };
|
|
334
|
+
}
|
|
335
|
+
function measureContextValueSize(value) {
|
|
336
|
+
return textEncoder.encode(value).length;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/renderer/renderer.ts
|
|
340
|
+
function renderSections(asset, options = {}) {
|
|
341
|
+
const { variables = {}, strict = false } = options;
|
|
342
|
+
const optionalVariables = getContextInputs(asset).filter((input) => input.optional === true).map((input) => input.name);
|
|
343
|
+
const result = {};
|
|
344
|
+
if (asset.sections.system_instructions) {
|
|
345
|
+
result.system_instructions = interpolate(
|
|
346
|
+
asset.sections.system_instructions,
|
|
347
|
+
variables,
|
|
348
|
+
{ strict, optionalVariables }
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (asset.sections.prompt_template) {
|
|
352
|
+
result.prompt_template = interpolate(
|
|
353
|
+
asset.sections.prompt_template,
|
|
354
|
+
variables,
|
|
355
|
+
{ strict, optionalVariables }
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return result;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/overrides/apply-overrides.ts
|
|
362
|
+
function applyOverrides(asset, options = {}) {
|
|
363
|
+
let result = { ...asset };
|
|
364
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
365
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
366
|
+
}
|
|
367
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
368
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
369
|
+
}
|
|
370
|
+
if (options.runtime) {
|
|
371
|
+
result = mergeOverride(result, options.runtime);
|
|
372
|
+
}
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
function mergeOverride(base, override) {
|
|
376
|
+
const result = { ...base };
|
|
377
|
+
if (override.model !== void 0) result.model = override.model;
|
|
378
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
379
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
380
|
+
if (override.reasoning !== void 0) {
|
|
381
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
382
|
+
}
|
|
383
|
+
if (override.sampling !== void 0) {
|
|
384
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
385
|
+
}
|
|
386
|
+
if (override.response !== void 0) {
|
|
387
|
+
result.response = { ...result.response, ...override.response };
|
|
388
|
+
}
|
|
389
|
+
if (override.cache !== void 0) {
|
|
390
|
+
result.cache = {
|
|
391
|
+
...result.cache,
|
|
392
|
+
...override.cache,
|
|
393
|
+
openai: mergeRecordBlock(result.cache?.openai, override.cache.openai),
|
|
394
|
+
anthropic: mergeRecordBlock(result.cache?.anthropic, override.cache.anthropic),
|
|
395
|
+
gemini: mergeRecordBlock(result.cache?.gemini, override.cache.gemini),
|
|
396
|
+
google: mergeRecordBlock(result.cache?.google, override.cache.google)
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
if (override.raw !== void 0) {
|
|
400
|
+
result.raw = {
|
|
401
|
+
...result.raw,
|
|
402
|
+
...override.raw,
|
|
403
|
+
openai: mergeRecordBlock(result.raw?.openai, override.raw.openai),
|
|
404
|
+
"openai-responses": mergeRecordBlock(result.raw?.["openai-responses"], override.raw["openai-responses"]),
|
|
405
|
+
openai_responses: mergeRecordBlock(result.raw?.openai_responses, override.raw.openai_responses),
|
|
406
|
+
anthropic: mergeRecordBlock(result.raw?.anthropic, override.raw.anthropic),
|
|
407
|
+
gemini: mergeRecordBlock(result.raw?.gemini, override.raw.gemini),
|
|
408
|
+
google: mergeRecordBlock(result.raw?.google, override.raw.google),
|
|
409
|
+
openrouter: mergeRecordBlock(result.raw?.openrouter, override.raw.openrouter),
|
|
410
|
+
llmasaservice: mergeRecordBlock(result.raw?.llmasaservice, override.raw.llmasaservice)
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if (override.provider_options !== void 0) {
|
|
414
|
+
result.provider_options = {
|
|
415
|
+
...result.provider_options,
|
|
416
|
+
...override.provider_options,
|
|
417
|
+
anthropic: {
|
|
418
|
+
...result.provider_options?.anthropic,
|
|
419
|
+
...override.provider_options.anthropic
|
|
420
|
+
},
|
|
421
|
+
gemini: {
|
|
422
|
+
...result.provider_options?.gemini,
|
|
423
|
+
...override.provider_options.gemini
|
|
424
|
+
},
|
|
425
|
+
openrouter: {
|
|
426
|
+
...result.provider_options?.openrouter,
|
|
427
|
+
...override.provider_options.openrouter
|
|
428
|
+
},
|
|
429
|
+
llmasaservice: {
|
|
430
|
+
...result.provider_options?.llmasaservice,
|
|
431
|
+
...override.provider_options.llmasaservice
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
return result;
|
|
436
|
+
}
|
|
437
|
+
function mergeRecordBlock(base, override) {
|
|
438
|
+
if (override === void 0) return base;
|
|
439
|
+
return { ...base, ...override };
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/providers/resolve-asset.ts
|
|
443
|
+
function resolveAssetForProvider(asset, runtime = {}) {
|
|
444
|
+
if (!runtime.environment && !runtime.tier && !runtime.runtime) {
|
|
445
|
+
return asset;
|
|
446
|
+
}
|
|
447
|
+
return applyOverrides(asset, {
|
|
448
|
+
environment: runtime.environment,
|
|
449
|
+
tier: runtime.tier,
|
|
450
|
+
runtime: runtime.runtime
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// src/prompt-resolution.ts
|
|
455
|
+
var import_promises4 = require("fs/promises");
|
|
456
|
+
var import_node_fs2 = require("fs");
|
|
457
|
+
var import_node_path4 = require("path");
|
|
458
|
+
|
|
459
|
+
// src/cache.ts
|
|
460
|
+
var import_node_fs = require("fs");
|
|
461
|
+
var PromptCache = class {
|
|
462
|
+
cache = /* @__PURE__ */ new Map();
|
|
463
|
+
maxSize;
|
|
464
|
+
constructor(maxSize = 100) {
|
|
465
|
+
this.maxSize = maxSize;
|
|
466
|
+
}
|
|
467
|
+
get(filePath) {
|
|
468
|
+
const entry = this.cache.get(filePath);
|
|
469
|
+
if (!entry) return void 0;
|
|
470
|
+
try {
|
|
471
|
+
const stat = (0, import_node_fs.statSync)(filePath);
|
|
472
|
+
if (stat.mtimeMs !== entry.mtime) {
|
|
473
|
+
this.cache.delete(filePath);
|
|
474
|
+
return void 0;
|
|
475
|
+
}
|
|
476
|
+
} catch {
|
|
477
|
+
this.cache.delete(filePath);
|
|
478
|
+
return void 0;
|
|
479
|
+
}
|
|
480
|
+
this.cache.delete(filePath);
|
|
481
|
+
this.cache.set(filePath, entry);
|
|
482
|
+
return entry.value;
|
|
483
|
+
}
|
|
484
|
+
set(filePath, value) {
|
|
485
|
+
try {
|
|
486
|
+
const stat = (0, import_node_fs.statSync)(filePath);
|
|
487
|
+
if (this.cache.has(filePath)) {
|
|
488
|
+
this.cache.delete(filePath);
|
|
489
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
490
|
+
const oldest = this.cache.keys().next().value;
|
|
491
|
+
if (oldest) this.cache.delete(oldest);
|
|
492
|
+
}
|
|
493
|
+
this.cache.set(filePath, { value, mtime: stat.mtimeMs });
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
clear() {
|
|
498
|
+
this.cache.clear();
|
|
499
|
+
}
|
|
500
|
+
get size() {
|
|
501
|
+
return this.cache.size;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/composition/resolve-includes.ts
|
|
506
|
+
var import_promises3 = require("fs/promises");
|
|
507
|
+
var import_node_path3 = require("path");
|
|
508
|
+
|
|
509
|
+
// src/parser/parser.ts
|
|
510
|
+
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
511
|
+
|
|
512
|
+
// src/schema/schema.ts
|
|
513
|
+
var import_zod = require("zod");
|
|
514
|
+
var InlineToolDefSchema = import_zod.z.object({
|
|
515
|
+
name: import_zod.z.string(),
|
|
516
|
+
description: import_zod.z.string().optional(),
|
|
517
|
+
input_schema: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
518
|
+
});
|
|
519
|
+
var ToolRefSchema = import_zod.z.union([import_zod.z.string(), InlineToolDefSchema]);
|
|
520
|
+
var MCPServerRefSchema = import_zod.z.union([
|
|
521
|
+
import_zod.z.string(),
|
|
522
|
+
import_zod.z.object({
|
|
523
|
+
name: import_zod.z.string(),
|
|
524
|
+
config: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
525
|
+
})
|
|
526
|
+
]);
|
|
527
|
+
var ReasoningSchema = import_zod.z.object({
|
|
528
|
+
effort: import_zod.z.enum(["low", "medium", "high"]).optional(),
|
|
529
|
+
budget_tokens: import_zod.z.number().int().positive().optional()
|
|
530
|
+
});
|
|
531
|
+
var SamplingSchema = import_zod.z.object({
|
|
532
|
+
temperature: import_zod.z.number().min(0).max(2).optional(),
|
|
533
|
+
top_p: import_zod.z.number().min(0).max(1).optional(),
|
|
534
|
+
frequency_penalty: import_zod.z.number().optional(),
|
|
535
|
+
presence_penalty: import_zod.z.number().optional(),
|
|
536
|
+
stop: import_zod.z.array(import_zod.z.string()).optional(),
|
|
537
|
+
max_output_tokens: import_zod.z.number().int().positive().optional()
|
|
538
|
+
});
|
|
539
|
+
var ResponseSchema = import_zod.z.object({
|
|
540
|
+
format: import_zod.z.enum(["text", "json", "markdown"]).optional(),
|
|
541
|
+
stream: import_zod.z.boolean().optional(),
|
|
542
|
+
schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
543
|
+
schema_ref: import_zod.z.string().min(1).optional(),
|
|
544
|
+
schema_source: import_zod.z.object({
|
|
545
|
+
mode: import_zod.z.enum(["inline", "schema_ref_json", "schema_ref_zod_module"]).optional(),
|
|
546
|
+
ref: import_zod.z.string().optional(),
|
|
547
|
+
resolved_path: import_zod.z.string().optional(),
|
|
548
|
+
hash: import_zod.z.string().optional()
|
|
549
|
+
}).optional(),
|
|
550
|
+
schema_name: import_zod.z.string().optional(),
|
|
551
|
+
schema_description: import_zod.z.string().optional(),
|
|
552
|
+
schema_strict: import_zod.z.boolean().optional()
|
|
553
|
+
});
|
|
554
|
+
var ResponseSchemaWithValidation = ResponseSchema.superRefine((value, ctx) => {
|
|
555
|
+
if (value.schema !== void 0 && value.schema_ref !== void 0) {
|
|
556
|
+
ctx.addIssue({
|
|
557
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
558
|
+
message: "response.schema and response.schema_ref are mutually exclusive",
|
|
559
|
+
path: ["schema_ref"]
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
var AnthropicProviderOptionsSchema = import_zod.z.object({
|
|
564
|
+
top_k: import_zod.z.number().int().min(0).optional(),
|
|
565
|
+
tool_choice: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
566
|
+
output_config: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
567
|
+
});
|
|
568
|
+
var GeminiProviderOptionsSchema = import_zod.z.object({
|
|
569
|
+
candidate_count: import_zod.z.number().int().positive().optional(),
|
|
570
|
+
top_k: import_zod.z.number().int().min(0).optional(),
|
|
571
|
+
seed: import_zod.z.number().int().optional(),
|
|
572
|
+
response_schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
573
|
+
response_json_schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
574
|
+
response_modalities: import_zod.z.array(import_zod.z.string()).optional(),
|
|
575
|
+
thinking_budget_tokens: import_zod.z.number().int().positive().optional()
|
|
576
|
+
});
|
|
577
|
+
var OpenRouterProviderOptionsSchema = import_zod.z.object({
|
|
578
|
+
provider: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
579
|
+
transforms: import_zod.z.array(import_zod.z.string()).optional(),
|
|
580
|
+
plugins: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).optional(),
|
|
581
|
+
models: import_zod.z.array(import_zod.z.string()).optional()
|
|
582
|
+
});
|
|
583
|
+
var LLMAsAServiceCustomerSchema = import_zod.z.object({
|
|
584
|
+
customer_id: import_zod.z.string(),
|
|
585
|
+
customer_name: import_zod.z.string().optional(),
|
|
586
|
+
customer_user_id: import_zod.z.string().optional(),
|
|
587
|
+
customer_user_name: import_zod.z.string().optional(),
|
|
588
|
+
customer_user_email: import_zod.z.string().optional()
|
|
589
|
+
});
|
|
590
|
+
var LLMAsAServiceProviderOptionsSchema = import_zod.z.object({
|
|
591
|
+
base_url: import_zod.z.string().url().optional(),
|
|
592
|
+
project_id: import_zod.z.string().optional(),
|
|
593
|
+
customer: LLMAsAServiceCustomerSchema.optional(),
|
|
594
|
+
conversationId: import_zod.z.string().optional(),
|
|
595
|
+
conversationTitle: import_zod.z.string().optional(),
|
|
596
|
+
projectId: import_zod.z.string().optional()
|
|
597
|
+
});
|
|
598
|
+
var ProviderOptionsSchema = import_zod.z.object({
|
|
599
|
+
anthropic: AnthropicProviderOptionsSchema.optional(),
|
|
600
|
+
gemini: GeminiProviderOptionsSchema.optional(),
|
|
601
|
+
openrouter: OpenRouterProviderOptionsSchema.optional(),
|
|
602
|
+
llmasaservice: LLMAsAServiceProviderOptionsSchema.optional()
|
|
603
|
+
});
|
|
604
|
+
var RawProviderBodySchema = import_zod.z.object({
|
|
605
|
+
openai: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
606
|
+
"openai-responses": import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
607
|
+
openai_responses: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
608
|
+
anthropic: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
609
|
+
gemini: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
610
|
+
google: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
611
|
+
openrouter: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
612
|
+
llmasaservice: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
613
|
+
});
|
|
614
|
+
var OpenAICacheSchema = import_zod.z.object({
|
|
615
|
+
prompt_cache_key: import_zod.z.string().min(1).optional(),
|
|
616
|
+
retention: import_zod.z.enum(["in_memory", "24h"]).optional()
|
|
617
|
+
});
|
|
618
|
+
var AnthropicCacheSchema = import_zod.z.object({
|
|
619
|
+
mode: import_zod.z.enum(["automatic", "explicit"]).optional(),
|
|
620
|
+
type: import_zod.z.literal("ephemeral").optional(),
|
|
621
|
+
ttl: import_zod.z.enum(["5m", "1h"]).optional(),
|
|
622
|
+
cache_system_instructions: import_zod.z.boolean().optional(),
|
|
623
|
+
cache_tools: import_zod.z.boolean().optional(),
|
|
624
|
+
cache_prompt_template: import_zod.z.boolean().optional()
|
|
625
|
+
});
|
|
626
|
+
var GeminiCacheSchema = import_zod.z.object({
|
|
627
|
+
cached_content: import_zod.z.string().min(1).optional()
|
|
628
|
+
});
|
|
629
|
+
var CacheSchema = import_zod.z.object({
|
|
630
|
+
openai: OpenAICacheSchema.optional(),
|
|
631
|
+
anthropic: AnthropicCacheSchema.optional(),
|
|
632
|
+
gemini: GeminiCacheSchema.optional(),
|
|
633
|
+
google: GeminiCacheSchema.optional()
|
|
634
|
+
});
|
|
635
|
+
var HistorySchema = import_zod.z.object({
|
|
636
|
+
max_items: import_zod.z.number().int().positive().optional()
|
|
637
|
+
});
|
|
638
|
+
var ContextRegexSchema = import_zod.z.union([
|
|
639
|
+
import_zod.z.string(),
|
|
640
|
+
import_zod.z.object({
|
|
641
|
+
pattern: import_zod.z.string(),
|
|
642
|
+
flags: import_zod.z.string().optional(),
|
|
643
|
+
return_message: import_zod.z.string().optional()
|
|
644
|
+
})
|
|
645
|
+
]);
|
|
646
|
+
var ContextBuiltInValidatorSchema = import_zod.z.union([
|
|
647
|
+
import_zod.z.boolean(),
|
|
648
|
+
import_zod.z.object({
|
|
649
|
+
return_message: import_zod.z.string().optional()
|
|
650
|
+
})
|
|
651
|
+
]);
|
|
652
|
+
var ContextInputDefinitionObjectSchema = import_zod.z.object({
|
|
653
|
+
name: import_zod.z.string(),
|
|
654
|
+
optional: import_zod.z.boolean().optional(),
|
|
655
|
+
warnings: import_zod.z.boolean().optional(),
|
|
656
|
+
max_size: import_zod.z.number().int().positive().optional(),
|
|
657
|
+
trim: import_zod.z.union([import_zod.z.boolean(), import_zod.z.enum(["start", "end", "both"])]).optional(),
|
|
658
|
+
allow_regex: ContextRegexSchema.optional(),
|
|
659
|
+
deny_regex: ContextRegexSchema.optional(),
|
|
660
|
+
non_empty: ContextBuiltInValidatorSchema.optional(),
|
|
661
|
+
reject_secrets: ContextBuiltInValidatorSchema.optional()
|
|
662
|
+
});
|
|
663
|
+
var ContextInputDefinitionSchema = import_zod.z.union([
|
|
664
|
+
import_zod.z.string(),
|
|
665
|
+
ContextInputDefinitionObjectSchema
|
|
666
|
+
]);
|
|
667
|
+
var ContextSchema = import_zod.z.object({
|
|
668
|
+
inputs: import_zod.z.array(ContextInputDefinitionSchema).optional(),
|
|
669
|
+
history: HistorySchema.optional()
|
|
670
|
+
});
|
|
671
|
+
var MetadataSchema = import_zod.z.object({
|
|
672
|
+
owner: import_zod.z.string().optional(),
|
|
673
|
+
tags: import_zod.z.array(import_zod.z.string()).optional(),
|
|
674
|
+
review_required: import_zod.z.boolean().optional(),
|
|
675
|
+
stable: import_zod.z.boolean().optional()
|
|
676
|
+
});
|
|
677
|
+
var MCPSchema = import_zod.z.object({
|
|
678
|
+
servers: import_zod.z.array(MCPServerRefSchema).optional()
|
|
679
|
+
});
|
|
680
|
+
var PromptAssetOverridesSchema = import_zod.z.object({
|
|
681
|
+
model: import_zod.z.string().optional(),
|
|
682
|
+
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
683
|
+
reasoning: ReasoningSchema.optional(),
|
|
684
|
+
sampling: SamplingSchema.optional(),
|
|
685
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
686
|
+
cache: CacheSchema.optional(),
|
|
687
|
+
raw: RawProviderBodySchema.optional(),
|
|
688
|
+
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
689
|
+
provider_options: ProviderOptionsSchema.optional()
|
|
690
|
+
});
|
|
691
|
+
var SourceSchema = import_zod.z.object({
|
|
692
|
+
file_path: import_zod.z.string().optional(),
|
|
693
|
+
checksum: import_zod.z.string().optional()
|
|
694
|
+
});
|
|
695
|
+
var SectionsSchema = import_zod.z.object({
|
|
696
|
+
system_instructions: import_zod.z.string().optional(),
|
|
697
|
+
prompt_template: import_zod.z.string().optional(),
|
|
698
|
+
notes: import_zod.z.string().optional()
|
|
699
|
+
});
|
|
700
|
+
var PromptDefaultsSchema = import_zod.z.object({
|
|
701
|
+
provider: import_zod.z.enum(["openai", "openai-responses", "anthropic", "google", "gemini", "openrouter", "llmasaservice", "any"]).optional(),
|
|
702
|
+
model: import_zod.z.string().optional(),
|
|
703
|
+
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
704
|
+
reasoning: ReasoningSchema.optional(),
|
|
705
|
+
sampling: SamplingSchema.optional(),
|
|
706
|
+
response: ResponseSchema.optional(),
|
|
707
|
+
cache: CacheSchema.optional(),
|
|
708
|
+
raw: RawProviderBodySchema.optional(),
|
|
709
|
+
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
710
|
+
provider_options: ProviderOptionsSchema.optional(),
|
|
711
|
+
mcp: MCPSchema.optional(),
|
|
712
|
+
context: ContextSchema.optional(),
|
|
713
|
+
includes: import_zod.z.array(import_zod.z.string()).optional(),
|
|
714
|
+
environments: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
715
|
+
tiers: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
716
|
+
metadata: MetadataSchema.optional(),
|
|
717
|
+
sections: import_zod.z.object({
|
|
718
|
+
system_instructions: import_zod.z.string().optional()
|
|
719
|
+
}).optional()
|
|
720
|
+
});
|
|
721
|
+
var PromptAssetSchema = import_zod.z.object({
|
|
722
|
+
id: import_zod.z.string(),
|
|
723
|
+
schema_version: import_zod.z.number().int().positive().default(1),
|
|
724
|
+
description: import_zod.z.string().optional(),
|
|
725
|
+
provider: import_zod.z.enum(["openai", "openai-responses", "anthropic", "google", "gemini", "openrouter", "llmasaservice", "any"]).optional(),
|
|
726
|
+
model: import_zod.z.string().optional(),
|
|
727
|
+
fallback_models: import_zod.z.array(import_zod.z.string()).optional(),
|
|
728
|
+
reasoning: ReasoningSchema.optional(),
|
|
729
|
+
sampling: SamplingSchema.optional(),
|
|
730
|
+
response: ResponseSchemaWithValidation.optional(),
|
|
731
|
+
cache: CacheSchema.optional(),
|
|
732
|
+
raw: RawProviderBodySchema.optional(),
|
|
733
|
+
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
734
|
+
provider_options: ProviderOptionsSchema.optional(),
|
|
735
|
+
mcp: MCPSchema.optional(),
|
|
736
|
+
context: ContextSchema.optional(),
|
|
737
|
+
includes: import_zod.z.array(import_zod.z.string()).optional(),
|
|
738
|
+
environments: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
739
|
+
tiers: import_zod.z.record(PromptAssetOverridesSchema).optional(),
|
|
740
|
+
metadata: MetadataSchema.optional(),
|
|
741
|
+
// Populated by parser, not authored in YAML
|
|
742
|
+
sections: SectionsSchema.optional(),
|
|
743
|
+
source: SourceSchema.optional()
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
// src/parser/frontmatter-guard.ts
|
|
747
|
+
var FRONT_MATTER_DELIMITER = /^---[ \t]*$/;
|
|
748
|
+
var REGEX_FIELD = /^(?<indent>\s*)(?<field>allow_regex|deny_regex)\s*:\s*(?<value>.*)$/;
|
|
749
|
+
var PATTERN_FIELD = /^(?<indent>\s*)pattern\s*:\s*(?<value>.*)$/;
|
|
750
|
+
var INLINE_PATTERN_FIELD = /(?:^|[{,]\s*)pattern\s*:\s*(?<value>"(?:\\.|[^"\\])*")/;
|
|
751
|
+
function assertRegexFrontMatterQuoting(content, filePath) {
|
|
752
|
+
const frontMatter = extractFrontMatter(content);
|
|
753
|
+
if (!frontMatter) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
let pendingRegex;
|
|
757
|
+
for (const [index, line] of frontMatter.lines.entries()) {
|
|
758
|
+
const lineNumber = frontMatter.startLine + index;
|
|
759
|
+
const regexMatch = line.match(REGEX_FIELD);
|
|
760
|
+
if (regexMatch?.groups) {
|
|
761
|
+
const field = regexMatch.groups.field;
|
|
762
|
+
const indent2 = regexMatch.groups.indent.length;
|
|
763
|
+
const value = regexMatch.groups.value.trim();
|
|
764
|
+
pendingRegex = value === "" ? { field, indent: indent2 } : void 0;
|
|
765
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber);
|
|
766
|
+
assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber);
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
if (!pendingRegex) {
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
if (line.trim() === "" || line.trimStart().startsWith("#")) {
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
776
|
+
if (indent <= pendingRegex.indent) {
|
|
777
|
+
pendingRegex = void 0;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
const patternMatch = line.match(PATTERN_FIELD);
|
|
781
|
+
if (!patternMatch?.groups) {
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(
|
|
785
|
+
patternMatch.groups.value.trim(),
|
|
786
|
+
`${pendingRegex.field}.pattern`,
|
|
787
|
+
filePath,
|
|
788
|
+
lineNumber
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
function assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber) {
|
|
793
|
+
const match = value.match(INLINE_PATTERN_FIELD);
|
|
794
|
+
const pattern = match?.groups?.value;
|
|
795
|
+
if (!pattern) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(pattern, `${field}.pattern`, filePath, lineNumber);
|
|
799
|
+
}
|
|
800
|
+
function extractFrontMatter(content) {
|
|
801
|
+
const lines = content.split(/\r?\n/);
|
|
802
|
+
if (!FRONT_MATTER_DELIMITER.test(lines[0] ?? "")) {
|
|
803
|
+
return void 0;
|
|
804
|
+
}
|
|
805
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
806
|
+
if (FRONT_MATTER_DELIMITER.test(lines[index] ?? "")) {
|
|
807
|
+
return {
|
|
808
|
+
lines: lines.slice(1, index),
|
|
809
|
+
startLine: 2
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return void 0;
|
|
814
|
+
}
|
|
815
|
+
function assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber) {
|
|
816
|
+
if (!value.startsWith('"')) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
const quoted = readDoubleQuotedScalar(value);
|
|
820
|
+
if (!quoted) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (!hasUnescapedBackslash(quoted)) {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
const location = filePath ? `${filePath}:${lineNumber}` : `line ${lineNumber}`;
|
|
827
|
+
throw new Error(
|
|
828
|
+
`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.`
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
function readDoubleQuotedScalar(value) {
|
|
832
|
+
let result = "";
|
|
833
|
+
for (let index = 1; index < value.length; index += 1) {
|
|
834
|
+
const char = value[index];
|
|
835
|
+
if (char === '"') {
|
|
836
|
+
return result;
|
|
837
|
+
}
|
|
838
|
+
result += char;
|
|
839
|
+
if (char === "\\" && index + 1 < value.length) {
|
|
840
|
+
index += 1;
|
|
841
|
+
result += value[index];
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return void 0;
|
|
845
|
+
}
|
|
846
|
+
function hasUnescapedBackslash(value) {
|
|
847
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
848
|
+
if (value[index] !== "\\") {
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
let count = 1;
|
|
852
|
+
while (value[index + count] === "\\") {
|
|
853
|
+
count += 1;
|
|
854
|
+
}
|
|
855
|
+
if (count % 2 === 1) {
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
index += count - 1;
|
|
859
|
+
}
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/parser/sections.ts
|
|
864
|
+
var SECTION_MAP = {
|
|
865
|
+
"system instructions": "system_instructions",
|
|
866
|
+
"prompt template": "prompt_template",
|
|
867
|
+
"notes": "notes"
|
|
868
|
+
};
|
|
869
|
+
function extractSections(body) {
|
|
870
|
+
const lines = body.split(/\r?\n/);
|
|
871
|
+
const sections = {};
|
|
872
|
+
let currentKey = null;
|
|
873
|
+
let currentLines = [];
|
|
874
|
+
let foundAnyH1 = false;
|
|
875
|
+
for (const line of lines) {
|
|
876
|
+
const h1Match = line.match(/^#\s+(.+)$/);
|
|
877
|
+
if (h1Match) {
|
|
878
|
+
if (currentKey) {
|
|
879
|
+
sections[currentKey] = currentLines.join("\n").trim();
|
|
880
|
+
}
|
|
881
|
+
foundAnyH1 = true;
|
|
882
|
+
const heading = h1Match[1].trim().toLowerCase();
|
|
883
|
+
currentKey = SECTION_MAP[heading] ?? null;
|
|
884
|
+
currentLines = [];
|
|
885
|
+
} else {
|
|
886
|
+
currentLines.push(line);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
if (currentKey) {
|
|
890
|
+
sections[currentKey] = currentLines.join("\n").trim();
|
|
891
|
+
}
|
|
892
|
+
if (!foundAnyH1) {
|
|
893
|
+
const trimmed = body.trim();
|
|
894
|
+
if (trimmed) {
|
|
895
|
+
sections.prompt_template = trimmed;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return sections;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// src/parser/parser.ts
|
|
902
|
+
function parsePrompt(content, filePath) {
|
|
903
|
+
assertRegexFrontMatterQuoting(content, filePath);
|
|
904
|
+
const { data: frontMatter, content: body } = (0, import_gray_matter.default)(content);
|
|
905
|
+
const sections = extractSections(body);
|
|
906
|
+
const raw = {
|
|
907
|
+
...frontMatter,
|
|
908
|
+
sections,
|
|
909
|
+
source: filePath ? { file_path: filePath } : void 0
|
|
910
|
+
};
|
|
911
|
+
const asset = PromptAssetSchema.parse(raw);
|
|
912
|
+
return {
|
|
913
|
+
asset,
|
|
914
|
+
raw: {
|
|
915
|
+
frontMatter,
|
|
916
|
+
body
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/parser/loader.ts
|
|
922
|
+
var import_promises2 = require("fs/promises");
|
|
923
|
+
var import_node_path2 = require("path");
|
|
924
|
+
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
925
|
+
|
|
926
|
+
// src/parser/response-schema-ref.ts
|
|
927
|
+
var import_promises = require("fs/promises");
|
|
928
|
+
var import_node_crypto = require("crypto");
|
|
929
|
+
var import_node_path = require("path");
|
|
930
|
+
var import_node_url = require("url");
|
|
931
|
+
var import_zod2 = require("zod");
|
|
932
|
+
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
933
|
+
var SUPPORTED_SCHEMA_REF_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".js", ".mjs", ".cjs"]);
|
|
934
|
+
async function resolveJsonSchemaRef(schemaRef, promptFilePath) {
|
|
935
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
936
|
+
let raw;
|
|
937
|
+
try {
|
|
938
|
+
raw = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
939
|
+
} catch (error) {
|
|
940
|
+
const code = error.code;
|
|
941
|
+
if (code === "ENOENT") {
|
|
942
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
943
|
+
}
|
|
944
|
+
throw error;
|
|
945
|
+
}
|
|
946
|
+
let parsed;
|
|
947
|
+
try {
|
|
948
|
+
parsed = JSON.parse(raw);
|
|
949
|
+
} catch {
|
|
950
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" is not valid JSON`);
|
|
951
|
+
}
|
|
952
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
953
|
+
throw new Error(`POK050: response.schema_ref "${schemaRef}" must resolve to a JSON object schema`);
|
|
954
|
+
}
|
|
955
|
+
return {
|
|
956
|
+
schema: parsed,
|
|
957
|
+
resolvedPath,
|
|
958
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(raw).digest("hex")
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
async function resolveZodSchemaRef(schemaRef, promptFilePath) {
|
|
962
|
+
const resolvedPath = (0, import_node_path.resolve)((0, import_node_path.dirname)(promptFilePath), schemaRef);
|
|
963
|
+
let moduleSource;
|
|
964
|
+
try {
|
|
965
|
+
moduleSource = await (0, import_promises.readFile)(resolvedPath, "utf-8");
|
|
966
|
+
} catch (error) {
|
|
967
|
+
const code = error.code;
|
|
968
|
+
if (code === "ENOENT") {
|
|
969
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" not found (resolved from ${promptFilePath})`);
|
|
970
|
+
}
|
|
971
|
+
throw error;
|
|
972
|
+
}
|
|
973
|
+
let imported;
|
|
974
|
+
try {
|
|
975
|
+
imported = await import((0, import_node_url.pathToFileURL)(resolvedPath).href);
|
|
976
|
+
} catch (error) {
|
|
977
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
978
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" could not be imported as a module (${message})`);
|
|
979
|
+
}
|
|
980
|
+
const mod = imported;
|
|
981
|
+
const candidate = mod.default ?? mod.schema;
|
|
982
|
+
if (!(candidate instanceof import_zod2.z.ZodType)) {
|
|
983
|
+
throw new Error('POK051: zod schema modules must export a Zod schema as default export or named export "schema"');
|
|
984
|
+
}
|
|
985
|
+
const jsonSchema = (0, import_zod_to_json_schema.zodToJsonSchema)(candidate, {
|
|
986
|
+
target: "jsonSchema7",
|
|
987
|
+
$refStrategy: "none"
|
|
988
|
+
});
|
|
989
|
+
if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
|
|
990
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" did not produce a valid JSON schema object`);
|
|
991
|
+
}
|
|
992
|
+
return {
|
|
993
|
+
schema: jsonSchema,
|
|
994
|
+
resolvedPath,
|
|
995
|
+
hash: (0, import_node_crypto.createHash)("sha256").update(moduleSource).digest("hex")
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
async function resolveResponseSchemaRef(asset, promptFilePath) {
|
|
999
|
+
const schemaRef = asset.response?.schema_ref;
|
|
1000
|
+
if (!schemaRef) return asset;
|
|
1001
|
+
const ext = (0, import_node_path.extname)(schemaRef).toLowerCase();
|
|
1002
|
+
if (!SUPPORTED_SCHEMA_REF_EXTENSIONS.has(ext)) {
|
|
1003
|
+
throw new Error(`POK051: response.schema_ref "${schemaRef}" has unsupported extension "${ext}". Use .json, .js, .mjs, or .cjs`);
|
|
1004
|
+
}
|
|
1005
|
+
const resolved = ext === ".json" ? await resolveJsonSchemaRef(schemaRef, promptFilePath) : await resolveZodSchemaRef(schemaRef, promptFilePath);
|
|
1006
|
+
return {
|
|
1007
|
+
...asset,
|
|
1008
|
+
response: {
|
|
1009
|
+
...asset.response,
|
|
1010
|
+
schema: resolved.schema,
|
|
1011
|
+
schema_ref: void 0,
|
|
1012
|
+
schema_source: {
|
|
1013
|
+
mode: ext === ".json" ? "schema_ref_json" : "schema_ref_zod_module",
|
|
1014
|
+
ref: schemaRef,
|
|
1015
|
+
resolved_path: resolved.resolvedPath,
|
|
1016
|
+
hash: resolved.hash
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
// src/parser/loader.ts
|
|
1023
|
+
var DEFAULTS_FILE_NAME = "defaults.md";
|
|
1024
|
+
async function loadPromptFile(filePath, options = {}) {
|
|
1025
|
+
const content = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
1026
|
+
const parsed = parsePrompt(content, filePath);
|
|
1027
|
+
const root = options.defaultsRoot ?? (0, import_node_path2.dirname)(filePath);
|
|
1028
|
+
const defaults = await loadDefaultsForPath(filePath, root);
|
|
1029
|
+
const withDefaults = applyDefaults(parsed.asset, defaults);
|
|
1030
|
+
const resolved = await resolveResponseSchemaRef(withDefaults, filePath);
|
|
1031
|
+
const asset = resolved.response?.schema !== void 0 && !resolved.response?.schema_source ? {
|
|
1032
|
+
...resolved,
|
|
1033
|
+
response: {
|
|
1034
|
+
...resolved.response,
|
|
1035
|
+
schema_source: { mode: "inline" }
|
|
1036
|
+
}
|
|
1037
|
+
} : resolved;
|
|
1038
|
+
return {
|
|
1039
|
+
...parsed,
|
|
1040
|
+
asset
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
async function loadDefaultsForPath(filePath, defaultsRoot) {
|
|
1044
|
+
const directories = getDirectoriesToCheck(filePath, defaultsRoot);
|
|
1045
|
+
let merged = {};
|
|
1046
|
+
for (const dir of directories) {
|
|
1047
|
+
const defaultsPath = (0, import_node_path2.join)(dir, DEFAULTS_FILE_NAME);
|
|
1048
|
+
try {
|
|
1049
|
+
const defaultsContent = await (0, import_promises2.readFile)(defaultsPath, "utf-8");
|
|
1050
|
+
const defaults = normalizeDefaultIncludes(parseDefaults(defaultsContent), defaultsPath, filePath);
|
|
1051
|
+
merged = mergeDefaults(merged, defaults);
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
if (error.code !== "ENOENT") {
|
|
1054
|
+
throw error;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
return merged;
|
|
1059
|
+
}
|
|
1060
|
+
function getDirectoriesToCheck(filePath, defaultsRoot) {
|
|
1061
|
+
const dirs = [];
|
|
1062
|
+
let current = (0, import_node_path2.resolve)((0, import_node_path2.dirname)(filePath));
|
|
1063
|
+
const boundary = defaultsRoot ? (0, import_node_path2.resolve)(defaultsRoot) : void 0;
|
|
1064
|
+
while (true) {
|
|
1065
|
+
dirs.unshift(current);
|
|
1066
|
+
if (boundary && current === boundary || current === (0, import_node_path2.dirname)(current)) {
|
|
1067
|
+
break;
|
|
1068
|
+
}
|
|
1069
|
+
current = (0, import_node_path2.dirname)(current);
|
|
1070
|
+
}
|
|
1071
|
+
return dirs;
|
|
1072
|
+
}
|
|
1073
|
+
function parseDefaults(content) {
|
|
1074
|
+
const { data: frontMatter, content: body } = (0, import_gray_matter2.default)(content);
|
|
1075
|
+
const sections = extractSections(body);
|
|
1076
|
+
return PromptDefaultsSchema.parse({
|
|
1077
|
+
...frontMatter,
|
|
1078
|
+
sections: {
|
|
1079
|
+
system_instructions: sections.system_instructions
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
function mergeDefaults(base, local) {
|
|
1084
|
+
return {
|
|
1085
|
+
provider: local.provider ?? base.provider,
|
|
1086
|
+
model: local.model ?? base.model,
|
|
1087
|
+
fallback_models: local.fallback_models ?? base.fallback_models,
|
|
1088
|
+
reasoning: mergeRecordBlock2(base.reasoning, local.reasoning),
|
|
1089
|
+
sampling: mergeRecordBlock2(base.sampling, local.sampling),
|
|
1090
|
+
response: mergeRecordBlock2(base.response, local.response),
|
|
1091
|
+
cache: mergeCache(base.cache, local.cache),
|
|
1092
|
+
raw: mergeRaw(base.raw, local.raw),
|
|
1093
|
+
tools: local.tools ?? base.tools,
|
|
1094
|
+
provider_options: mergeProviderOptions(base.provider_options, local.provider_options),
|
|
1095
|
+
mcp: mergeMcp(base.mcp, local.mcp),
|
|
1096
|
+
context: mergeContext(base.context, local.context),
|
|
1097
|
+
includes: local.includes ?? base.includes,
|
|
1098
|
+
environments: mergeOverrideMap(base.environments, local.environments),
|
|
1099
|
+
tiers: mergeOverrideMap(base.tiers, local.tiers),
|
|
1100
|
+
metadata: {
|
|
1101
|
+
...base.metadata ?? {},
|
|
1102
|
+
...local.metadata ?? {}
|
|
1103
|
+
},
|
|
1104
|
+
sections: {
|
|
1105
|
+
...base.sections ?? {},
|
|
1106
|
+
...local.sections ?? {}
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function applyDefaults(asset, defaults) {
|
|
1111
|
+
const cache = mergeCache(defaults.cache, asset.cache);
|
|
1112
|
+
const raw = mergeRaw(defaults.raw, asset.raw);
|
|
1113
|
+
const providerOptions = mergeProviderOptions(defaults.provider_options, asset.provider_options);
|
|
1114
|
+
const reasoning = mergeRecordBlock2(defaults.reasoning, asset.reasoning);
|
|
1115
|
+
const sampling = mergeRecordBlock2(defaults.sampling, asset.sampling);
|
|
1116
|
+
const response = mergeRecordBlock2(defaults.response, asset.response);
|
|
1117
|
+
const mcp = mergeMcp(defaults.mcp, asset.mcp);
|
|
1118
|
+
const context = mergeContext(defaults.context, asset.context);
|
|
1119
|
+
const environments = mergeOverrideMap(defaults.environments, asset.environments);
|
|
1120
|
+
const tiers = mergeOverrideMap(defaults.tiers, asset.tiers);
|
|
1121
|
+
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
1122
|
+
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
1123
|
+
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0 || defaults.fallback_models !== void 0 || defaults.tools !== void 0 || defaults.includes !== void 0;
|
|
1124
|
+
const hasDefaultObjects = cache !== void 0 || raw !== void 0 || providerOptions !== void 0 || reasoning !== void 0 || sampling !== void 0 || response !== void 0 || mcp !== void 0 || context !== void 0 || environments !== void 0 || tiers !== void 0;
|
|
1125
|
+
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultObjects) {
|
|
1126
|
+
return asset;
|
|
1127
|
+
}
|
|
1128
|
+
const mergedMetadata = {
|
|
1129
|
+
...defaults.metadata ?? {},
|
|
1130
|
+
...asset.metadata ?? {}
|
|
1131
|
+
};
|
|
1132
|
+
const metadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : void 0;
|
|
1133
|
+
const systemInstructions = asset.sections?.system_instructions ?? defaults.sections?.system_instructions;
|
|
1134
|
+
const sections = asset.sections ? { ...asset.sections, system_instructions: systemInstructions } : systemInstructions ? { system_instructions: systemInstructions } : void 0;
|
|
1135
|
+
return {
|
|
1136
|
+
...asset,
|
|
1137
|
+
provider: asset.provider ?? defaults.provider,
|
|
1138
|
+
model: asset.model ?? defaults.model,
|
|
1139
|
+
fallback_models: asset.fallback_models ?? defaults.fallback_models,
|
|
1140
|
+
reasoning,
|
|
1141
|
+
sampling,
|
|
1142
|
+
response,
|
|
1143
|
+
cache,
|
|
1144
|
+
raw,
|
|
1145
|
+
tools: asset.tools ?? defaults.tools,
|
|
1146
|
+
provider_options: providerOptions,
|
|
1147
|
+
mcp,
|
|
1148
|
+
context,
|
|
1149
|
+
includes: asset.includes ?? defaults.includes,
|
|
1150
|
+
environments,
|
|
1151
|
+
tiers,
|
|
1152
|
+
metadata,
|
|
1153
|
+
sections
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
function normalizeDefaultIncludes(defaults, defaultsPath, filePath) {
|
|
1157
|
+
if (!defaults.includes) return defaults;
|
|
1158
|
+
const promptDir = (0, import_node_path2.dirname)(filePath);
|
|
1159
|
+
const defaultsDir = (0, import_node_path2.dirname)(defaultsPath);
|
|
1160
|
+
const includes = defaults.includes.map((includePath) => {
|
|
1161
|
+
const relativePath = (0, import_node_path2.relative)(promptDir, (0, import_node_path2.resolve)(defaultsDir, includePath)).replace(/\\/g, "/");
|
|
1162
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
1163
|
+
});
|
|
1164
|
+
return {
|
|
1165
|
+
...defaults,
|
|
1166
|
+
includes
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function mergeRecordBlock2(base, local) {
|
|
1170
|
+
if (base === void 0) return local;
|
|
1171
|
+
if (local === void 0) return base;
|
|
1172
|
+
return { ...base, ...local };
|
|
1173
|
+
}
|
|
1174
|
+
function mergeMcp(base, local) {
|
|
1175
|
+
return mergeRecordBlock2(base, local);
|
|
1176
|
+
}
|
|
1177
|
+
function mergeContext(base, local) {
|
|
1178
|
+
const merged = {
|
|
1179
|
+
...base ?? {},
|
|
1180
|
+
...local ?? {},
|
|
1181
|
+
history: mergeRecordBlock2(base?.history, local?.history)
|
|
1182
|
+
};
|
|
1183
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1184
|
+
}
|
|
1185
|
+
function mergeCache(base, local) {
|
|
1186
|
+
const merged = {
|
|
1187
|
+
...base ?? {},
|
|
1188
|
+
...local ?? {},
|
|
1189
|
+
openai: {
|
|
1190
|
+
...base?.openai ?? {},
|
|
1191
|
+
...local?.openai ?? {}
|
|
1192
|
+
},
|
|
1193
|
+
anthropic: {
|
|
1194
|
+
...base?.anthropic ?? {},
|
|
1195
|
+
...local?.anthropic ?? {}
|
|
1196
|
+
},
|
|
1197
|
+
gemini: {
|
|
1198
|
+
...base?.gemini ?? {},
|
|
1199
|
+
...local?.gemini ?? {}
|
|
1200
|
+
},
|
|
1201
|
+
google: {
|
|
1202
|
+
...base?.google ?? {},
|
|
1203
|
+
...local?.google ?? {}
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
if (merged.openai && Object.keys(merged.openai).length === 0) delete merged.openai;
|
|
1207
|
+
if (merged.anthropic && Object.keys(merged.anthropic).length === 0) delete merged.anthropic;
|
|
1208
|
+
if (merged.gemini && Object.keys(merged.gemini).length === 0) delete merged.gemini;
|
|
1209
|
+
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
1210
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1211
|
+
}
|
|
1212
|
+
function mergeRaw(base, local) {
|
|
1213
|
+
const merged = {
|
|
1214
|
+
...base ?? {},
|
|
1215
|
+
...local ?? {},
|
|
1216
|
+
openai: mergeRecordBlock2(base?.openai, local?.openai),
|
|
1217
|
+
"openai-responses": mergeRecordBlock2(base?.["openai-responses"], local?.["openai-responses"]),
|
|
1218
|
+
openai_responses: mergeRecordBlock2(base?.openai_responses, local?.openai_responses),
|
|
1219
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1220
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1221
|
+
google: mergeRecordBlock2(base?.google, local?.google),
|
|
1222
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1223
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
1224
|
+
};
|
|
1225
|
+
removeEmptyProviderBlocks(merged);
|
|
1226
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1227
|
+
}
|
|
1228
|
+
function mergeProviderOptions(base, local) {
|
|
1229
|
+
const merged = {
|
|
1230
|
+
...base ?? {},
|
|
1231
|
+
...local ?? {},
|
|
1232
|
+
anthropic: mergeRecordBlock2(base?.anthropic, local?.anthropic),
|
|
1233
|
+
gemini: mergeRecordBlock2(base?.gemini, local?.gemini),
|
|
1234
|
+
openrouter: mergeRecordBlock2(base?.openrouter, local?.openrouter),
|
|
1235
|
+
llmasaservice: mergeRecordBlock2(base?.llmasaservice, local?.llmasaservice)
|
|
1236
|
+
};
|
|
1237
|
+
removeEmptyProviderBlocks(merged);
|
|
1238
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1239
|
+
}
|
|
1240
|
+
function mergeOverrideMap(base, local) {
|
|
1241
|
+
const merged = { ...base ?? {} };
|
|
1242
|
+
for (const [name, localOverride] of Object.entries(local ?? {})) {
|
|
1243
|
+
merged[name] = mergeOverrideConfig(merged[name], localOverride);
|
|
1244
|
+
}
|
|
1245
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
1246
|
+
}
|
|
1247
|
+
function mergeOverrideConfig(base, local) {
|
|
1248
|
+
const merged = {
|
|
1249
|
+
...base ?? {},
|
|
1250
|
+
...local
|
|
1251
|
+
};
|
|
1252
|
+
const reasoning = mergeRecordBlock2(base?.reasoning, local.reasoning);
|
|
1253
|
+
const sampling = mergeRecordBlock2(base?.sampling, local.sampling);
|
|
1254
|
+
const response = mergeRecordBlock2(base?.response, local.response);
|
|
1255
|
+
const cache = mergeCache(base?.cache, local.cache);
|
|
1256
|
+
const raw = mergeRaw(base?.raw, local.raw);
|
|
1257
|
+
const providerOptions = mergeProviderOptions(base?.provider_options, local.provider_options);
|
|
1258
|
+
if (reasoning !== void 0) merged.reasoning = reasoning;
|
|
1259
|
+
if (sampling !== void 0) merged.sampling = sampling;
|
|
1260
|
+
if (response !== void 0) merged.response = response;
|
|
1261
|
+
if (cache !== void 0) merged.cache = cache;
|
|
1262
|
+
if (raw !== void 0) merged.raw = raw;
|
|
1263
|
+
if (providerOptions !== void 0) merged.provider_options = providerOptions;
|
|
1264
|
+
return merged;
|
|
1265
|
+
}
|
|
1266
|
+
function removeEmptyProviderBlocks(value) {
|
|
1267
|
+
for (const key of Object.keys(value)) {
|
|
1268
|
+
const block = value[key];
|
|
1269
|
+
if (block === void 0) {
|
|
1270
|
+
delete value[key];
|
|
1271
|
+
continue;
|
|
1272
|
+
}
|
|
1273
|
+
if (block !== null && typeof block === "object" && !Array.isArray(block) && Object.keys(block).length === 0) {
|
|
1274
|
+
delete value[key];
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
// src/composition/resolve-includes.ts
|
|
1280
|
+
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
1281
|
+
if (!asset.includes || asset.includes.length === 0) {
|
|
1282
|
+
return asset;
|
|
1283
|
+
}
|
|
1284
|
+
const baseDir = (0, import_node_path3.dirname)(basePath);
|
|
1285
|
+
const resolvedPath = (0, import_node_path3.resolve)(basePath);
|
|
1286
|
+
if (visited.has(resolvedPath)) {
|
|
1287
|
+
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
1288
|
+
}
|
|
1289
|
+
visited.add(resolvedPath);
|
|
1290
|
+
let mergedSystemInstructions = "";
|
|
1291
|
+
for (const includePath of asset.includes) {
|
|
1292
|
+
const fullPath = (0, import_node_path3.resolve)(baseDir, includePath);
|
|
1293
|
+
if (visited.has(fullPath)) {
|
|
1294
|
+
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
1295
|
+
}
|
|
1296
|
+
const content = await (0, import_promises3.readFile)(fullPath, "utf-8");
|
|
1297
|
+
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
1298
|
+
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
1299
|
+
if (resolved.sections?.system_instructions) {
|
|
1300
|
+
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
const localSystem = asset.sections?.system_instructions ?? "";
|
|
1304
|
+
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
1305
|
+
return {
|
|
1306
|
+
...asset,
|
|
1307
|
+
sections: {
|
|
1308
|
+
...asset.sections,
|
|
1309
|
+
system_instructions: combinedSystem
|
|
1310
|
+
},
|
|
1311
|
+
// Drop includes from the resolved asset — they've been inlined
|
|
1312
|
+
includes: void 0
|
|
1313
|
+
};
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// src/prompt-resolution.ts
|
|
1317
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
1318
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
1319
|
+
function withPromptResolutionDefaults(config) {
|
|
1320
|
+
return {
|
|
1321
|
+
...config,
|
|
1322
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
1323
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
var sharedPromptCache = new PromptCache();
|
|
1327
|
+
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
1328
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1329
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
1330
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
1331
|
+
const compiledFile = (0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json");
|
|
1332
|
+
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
1333
|
+
if (mode === "auto") {
|
|
1334
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1335
|
+
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1336
|
+
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
1337
|
+
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
1338
|
+
if (sourceMtime > compiledMtime) {
|
|
1339
|
+
console.warn(
|
|
1340
|
+
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
1341
|
+
Run "promptopskit compile" or switch to source-only mode.`
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
const content = await (0, import_promises4.readFile)(compiledFile, "utf-8");
|
|
1347
|
+
return JSON.parse(content);
|
|
1348
|
+
}
|
|
1349
|
+
if (mode === "compiled-only") {
|
|
1350
|
+
throw new Error(
|
|
1351
|
+
`Compiled artifact not found: ${compiledFile}
|
|
1352
|
+
Run "promptopskit compile" to generate it.`
|
|
1353
|
+
);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
if (mode !== "compiled-only") {
|
|
1357
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1358
|
+
if (resolvedConfig.cache !== false) {
|
|
1359
|
+
const cached = promptCache.get(sourceFile);
|
|
1360
|
+
if (cached) {
|
|
1361
|
+
return cached;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
if (!(0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1365
|
+
const paths = [sourceFile];
|
|
1366
|
+
if (resolvedConfig.compiledDir) {
|
|
1367
|
+
paths.unshift((0, import_node_path4.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
1368
|
+
}
|
|
1369
|
+
throw new Error(
|
|
1370
|
+
`Prompt not found: "${promptPath}"
|
|
1371
|
+
Searched:
|
|
1372
|
+
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
1376
|
+
if (resolvedConfig.cache !== false) {
|
|
1377
|
+
promptCache.set(sourceFile, asset);
|
|
1378
|
+
}
|
|
1379
|
+
return asset;
|
|
1380
|
+
}
|
|
1381
|
+
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
1382
|
+
}
|
|
1383
|
+
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
1384
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
1385
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
1386
|
+
const sourceFile = (0, import_node_path4.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
1387
|
+
if (asset.includes && asset.includes.length > 0 && (0, import_node_fs2.existsSync)(sourceFile)) {
|
|
1388
|
+
asset = await resolveIncludes(asset, sourceFile);
|
|
1389
|
+
}
|
|
1390
|
+
asset = applyOverrides(asset, {
|
|
1391
|
+
environment: options.environment,
|
|
1392
|
+
tier: options.tier,
|
|
1393
|
+
runtime: options.runtime
|
|
1394
|
+
});
|
|
1395
|
+
return asset;
|
|
1396
|
+
}
|
|
1397
|
+
function resolveInlinePromptSource(source, options = {}) {
|
|
1398
|
+
const { asset } = parsePrompt(source);
|
|
1399
|
+
return applyOverrides(asset, {
|
|
1400
|
+
environment: options.environment,
|
|
1401
|
+
tier: options.tier,
|
|
1402
|
+
runtime: options.runtime
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// src/history.ts
|
|
1407
|
+
function defaultCompactHistory(info) {
|
|
1408
|
+
const content = info.overflow.map((message) => `${message.role}: ${message.content}`).join("\n\n");
|
|
1409
|
+
return {
|
|
1410
|
+
role: "user",
|
|
1411
|
+
content: `Earlier conversation compacted to preserve history:
|
|
1412
|
+
|
|
1413
|
+
${content}`
|
|
1414
|
+
};
|
|
1415
|
+
}
|
|
1416
|
+
function normalizeCompactionResult(result) {
|
|
1417
|
+
if (typeof result === "string") {
|
|
1418
|
+
return {
|
|
1419
|
+
role: "user",
|
|
1420
|
+
content: result
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
return result;
|
|
1424
|
+
}
|
|
1425
|
+
function compactHistoryForPrompt(asset, runtime) {
|
|
1426
|
+
const history = runtime.history;
|
|
1427
|
+
const maxItems = asset.context?.history?.max_items;
|
|
1428
|
+
if (!history || maxItems === void 0 || history.length <= maxItems) {
|
|
1429
|
+
return history;
|
|
1430
|
+
}
|
|
1431
|
+
if (maxItems === 1) {
|
|
1432
|
+
const info2 = {
|
|
1433
|
+
promptId: asset.id,
|
|
1434
|
+
maxItems,
|
|
1435
|
+
overflow: history,
|
|
1436
|
+
preserved: [],
|
|
1437
|
+
history
|
|
1438
|
+
};
|
|
1439
|
+
const compacted2 = runtime.onHistoryCompaction ? normalizeCompactionResult(runtime.onHistoryCompaction(info2)) : defaultCompactHistory(info2);
|
|
1440
|
+
return [compacted2];
|
|
1441
|
+
}
|
|
1442
|
+
const preservedCount = maxItems - 1;
|
|
1443
|
+
const overflow = history.slice(0, history.length - preservedCount);
|
|
1444
|
+
const preserved = history.slice(-preservedCount);
|
|
1445
|
+
const info = {
|
|
1446
|
+
promptId: asset.id,
|
|
1447
|
+
maxItems,
|
|
1448
|
+
overflow,
|
|
1449
|
+
preserved,
|
|
1450
|
+
history
|
|
1451
|
+
};
|
|
1452
|
+
const compacted = runtime.onHistoryCompaction ? normalizeCompactionResult(runtime.onHistoryCompaction(info)) : defaultCompactHistory(info);
|
|
1453
|
+
return [compacted, ...preserved];
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
// src/providers/prompt-input.ts
|
|
1457
|
+
function isPromptLookup(input) {
|
|
1458
|
+
return "path" in input && typeof input.path === "string";
|
|
1459
|
+
}
|
|
1460
|
+
function isInlinePromptSource(input) {
|
|
1461
|
+
return "source" in input && typeof input.source === "string";
|
|
1462
|
+
}
|
|
1463
|
+
async function resolveProviderPromptInput(input, runtime) {
|
|
1464
|
+
if (isPromptLookup(input)) {
|
|
1465
|
+
return resolvePromptAsset(input.path, input, runtime);
|
|
1466
|
+
}
|
|
1467
|
+
if (isInlinePromptSource(input)) {
|
|
1468
|
+
return resolveInlinePromptSource(input.source, runtime);
|
|
1469
|
+
}
|
|
1470
|
+
return input;
|
|
1471
|
+
}
|
|
1472
|
+
function withPromptInputSupport(adapter) {
|
|
1473
|
+
const validatePrompt = async (input, runtime) => {
|
|
1474
|
+
const resolved = await resolveProviderPromptInput(input, runtime);
|
|
1475
|
+
return adapter.validate(resolved, runtime);
|
|
1476
|
+
};
|
|
1477
|
+
const renderPrompt = async (input, runtime) => {
|
|
1478
|
+
const resolved = await resolveProviderPromptInput(input, runtime);
|
|
1479
|
+
const sanitization = sanitizeContextVariables(resolved, runtime.variables, {
|
|
1480
|
+
onContextOverflow: runtime.onContextOverflow
|
|
1481
|
+
});
|
|
1482
|
+
if (sanitization.shortCircuit) {
|
|
1483
|
+
return {
|
|
1484
|
+
provider: adapter.name,
|
|
1485
|
+
model: resolved.model ?? "",
|
|
1486
|
+
returnMessage: sanitization.shortCircuit.returnMessage
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
return adapter.render(resolved, {
|
|
1490
|
+
...runtime,
|
|
1491
|
+
variables: sanitization.variables,
|
|
1492
|
+
history: compactHistoryForPrompt(resolved, runtime)
|
|
1493
|
+
});
|
|
1494
|
+
};
|
|
1495
|
+
return {
|
|
1496
|
+
...adapter,
|
|
1497
|
+
validatePrompt,
|
|
1498
|
+
renderPrompt
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
// src/providers/raw.ts
|
|
1503
|
+
function applyRawProviderBody(body, asset, provider) {
|
|
1504
|
+
const raw = getRawProviderBody(asset, provider);
|
|
1505
|
+
return raw ? { ...body, ...raw } : body;
|
|
1506
|
+
}
|
|
1507
|
+
function getRawProviderBody(asset, provider) {
|
|
1508
|
+
if (provider === "openai-responses") {
|
|
1509
|
+
return asset.raw?.["openai-responses"] ?? asset.raw?.openai_responses;
|
|
1510
|
+
}
|
|
1511
|
+
if (provider === "gemini") {
|
|
1512
|
+
return asset.raw?.gemini ?? asset.raw?.google;
|
|
1513
|
+
}
|
|
1514
|
+
return asset.raw?.[provider];
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
// src/providers/openai.ts
|
|
1518
|
+
var openaiAdapter = withPromptInputSupport({
|
|
1519
|
+
name: "openai",
|
|
1520
|
+
validate(asset, runtime) {
|
|
1521
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1522
|
+
const errors = [];
|
|
1523
|
+
const warnings = [];
|
|
1524
|
+
if (!resolvedAsset.model) {
|
|
1525
|
+
errors.push("OpenAI adapter requires a model to be specified.");
|
|
1526
|
+
}
|
|
1527
|
+
if (resolvedAsset.reasoning?.budget_tokens !== void 0) {
|
|
1528
|
+
warnings.push("OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.");
|
|
1529
|
+
}
|
|
1530
|
+
if (resolvedAsset.response?.schema !== void 0 && resolvedAsset.response?.format !== "json") {
|
|
1531
|
+
warnings.push("OpenAI response.schema requires response.format: json. schema will still be applied as JSON schema output.");
|
|
1532
|
+
}
|
|
1533
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
1534
|
+
},
|
|
1535
|
+
render(asset, runtime) {
|
|
1536
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1537
|
+
const sections = renderSections(resolvedAsset, {
|
|
1538
|
+
variables: runtime.variables,
|
|
1539
|
+
strict: runtime.strict
|
|
1540
|
+
});
|
|
1541
|
+
const messages = [];
|
|
1542
|
+
if (sections.system_instructions) {
|
|
1543
|
+
messages.push({ role: "system", content: sections.system_instructions });
|
|
1544
|
+
}
|
|
1545
|
+
const history = compactHistoryForPrompt(resolvedAsset, runtime);
|
|
1546
|
+
if (history) {
|
|
1547
|
+
for (const msg of history) {
|
|
1548
|
+
messages.push({ role: msg.role, content: msg.content });
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
if (sections.prompt_template) {
|
|
1552
|
+
messages.push({ role: "user", content: sections.prompt_template });
|
|
1553
|
+
}
|
|
1554
|
+
const body = {
|
|
1555
|
+
model: resolvedAsset.model,
|
|
1556
|
+
messages
|
|
1557
|
+
};
|
|
1558
|
+
const openaiCacheConfig = resolvedAsset.cache?.openai;
|
|
1559
|
+
if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
|
|
1560
|
+
if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
|
|
1561
|
+
if (resolvedAsset.sampling?.frequency_penalty !== void 0) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;
|
|
1562
|
+
if (resolvedAsset.sampling?.presence_penalty !== void 0) body.presence_penalty = resolvedAsset.sampling.presence_penalty;
|
|
1563
|
+
if (resolvedAsset.sampling?.stop !== void 0) body.stop = resolvedAsset.sampling.stop;
|
|
1564
|
+
if (resolvedAsset.sampling?.max_output_tokens !== void 0) body.max_tokens = resolvedAsset.sampling.max_output_tokens;
|
|
1565
|
+
if (resolvedAsset.reasoning?.effort) {
|
|
1566
|
+
body.reasoning_effort = resolvedAsset.reasoning.effort;
|
|
1567
|
+
}
|
|
1568
|
+
if (resolvedAsset.response?.schema) {
|
|
1569
|
+
body.response_format = {
|
|
1570
|
+
type: "json_schema",
|
|
1571
|
+
json_schema: {
|
|
1572
|
+
name: resolvedAsset.response.schema_name ?? `${resolvedAsset.id}_response`,
|
|
1573
|
+
...resolvedAsset.response.schema_description ? { description: resolvedAsset.response.schema_description } : {},
|
|
1574
|
+
schema: resolvedAsset.response.schema,
|
|
1575
|
+
strict: resolvedAsset.response.schema_strict ?? true
|
|
1576
|
+
}
|
|
1577
|
+
};
|
|
1578
|
+
} else if (resolvedAsset.response?.format === "json") {
|
|
1579
|
+
body.response_format = { type: "json_object" };
|
|
1580
|
+
}
|
|
1581
|
+
if (resolvedAsset.response?.stream !== void 0) {
|
|
1582
|
+
body.stream = resolvedAsset.response.stream;
|
|
1583
|
+
}
|
|
1584
|
+
if (openaiCacheConfig?.prompt_cache_key) {
|
|
1585
|
+
body.prompt_cache_key = openaiCacheConfig.prompt_cache_key;
|
|
1586
|
+
}
|
|
1587
|
+
if (openaiCacheConfig?.retention) {
|
|
1588
|
+
body.prompt_cache_retention = openaiCacheConfig.retention;
|
|
1589
|
+
}
|
|
1590
|
+
if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
|
|
1591
|
+
body.tools = resolvedAsset.tools.map((tool) => {
|
|
1592
|
+
if (typeof tool === "string") {
|
|
1593
|
+
const def = runtime.toolRegistry?.[tool];
|
|
1594
|
+
if (def) return def;
|
|
1595
|
+
return { type: "function", function: { name: tool } };
|
|
1596
|
+
}
|
|
1597
|
+
return {
|
|
1598
|
+
type: "function",
|
|
1599
|
+
function: {
|
|
1600
|
+
name: tool.name,
|
|
1601
|
+
description: tool.description,
|
|
1602
|
+
parameters: tool.input_schema
|
|
1603
|
+
}
|
|
1604
|
+
};
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
return {
|
|
1608
|
+
body: applyRawProviderBody(body, resolvedAsset, "openai"),
|
|
1609
|
+
provider: "openai",
|
|
1610
|
+
model: resolvedAsset.model ?? "unknown"
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
|
|
1615
|
+
// src/providers/llmasaservice.ts
|
|
1616
|
+
var LLMASASERVICE_BASE_URL = "https://gateway.llmasaservice.io";
|
|
1617
|
+
var LLMASASERVICE_SDK_PLACEHOLDER_API_KEY = "not-used-by-llm-gateway";
|
|
1618
|
+
var LLMASASERVICE_DEFAULT_MODEL = "group:standard";
|
|
1619
|
+
var LLMASASERVICE_RESPONSE_HEADER_NAMES = [
|
|
1620
|
+
"x-request-id",
|
|
1621
|
+
"x-llm-model-id",
|
|
1622
|
+
"x-llm-model-group"
|
|
1623
|
+
];
|
|
1624
|
+
function createLLMAsAServiceOpenAIConfig(options = {}) {
|
|
1625
|
+
return {
|
|
1626
|
+
baseURL: options.baseURL ?? LLMASASERVICE_BASE_URL,
|
|
1627
|
+
apiKey: LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,
|
|
1628
|
+
defaultHeaders: {
|
|
1629
|
+
"x-project-id": options.projectId ?? ""
|
|
1630
|
+
}
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
function isGPT5ModelSelector(model) {
|
|
1634
|
+
if (!model) return false;
|
|
1635
|
+
return model.split(/[|,]/).map((candidate) => candidate.trim()).some((candidate) => candidate.startsWith("gpt-5") || candidate.startsWith("openai:gpt-5"));
|
|
1636
|
+
}
|
|
1637
|
+
function defaultModel() {
|
|
1638
|
+
return LLMASASERVICE_DEFAULT_MODEL;
|
|
1639
|
+
}
|
|
1640
|
+
function isRecord(value) {
|
|
1641
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1642
|
+
}
|
|
1643
|
+
function rawCustomerId(asset) {
|
|
1644
|
+
const customer = isRecord(asset.raw?.llmasaservice?.customer) ? asset.raw.llmasaservice.customer : void 0;
|
|
1645
|
+
return customer?.customer_id;
|
|
1646
|
+
}
|
|
1647
|
+
function isGatewayRenderValidation(runtime) {
|
|
1648
|
+
return runtime?.runtime !== void 0;
|
|
1649
|
+
}
|
|
1650
|
+
var llmasaserviceAdapter = withPromptInputSupport({
|
|
1651
|
+
name: "llmasaservice",
|
|
1652
|
+
validate(asset, runtime) {
|
|
1653
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1654
|
+
const validation = openaiAdapter.validate(
|
|
1655
|
+
{
|
|
1656
|
+
...resolvedAsset,
|
|
1657
|
+
model: resolvedAsset.model ?? defaultModel()
|
|
1658
|
+
},
|
|
1659
|
+
runtime
|
|
1660
|
+
);
|
|
1661
|
+
const warnings = validation.warnings.filter(
|
|
1662
|
+
(warning) => warning !== "OpenAI adapter requires a model to be specified."
|
|
1663
|
+
);
|
|
1664
|
+
const errors = [...validation.errors];
|
|
1665
|
+
const gatewayOptions = resolvedAsset.provider_options?.llmasaservice;
|
|
1666
|
+
const missingProjectId = !gatewayOptions?.project_id;
|
|
1667
|
+
const missingCustomerId = !gatewayOptions?.customer?.customer_id && typeof rawCustomerId(resolvedAsset) !== "string";
|
|
1668
|
+
const validateRenderMetadata = isGatewayRenderValidation(runtime);
|
|
1669
|
+
if (missingProjectId && validateRenderMetadata) {
|
|
1670
|
+
errors.push(
|
|
1671
|
+
"LLMAsAService adapter requires provider_options.llmasaservice.project_id for x-project-id routing."
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
if (missingCustomerId && validateRenderMetadata) {
|
|
1675
|
+
errors.push(
|
|
1676
|
+
"LLMAsAService adapter requires customer.customer_id in provider_options.llmasaservice.customer or raw.llmasaservice.customer."
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1679
|
+
if ((missingProjectId || missingCustomerId) && !validateRenderMetadata) {
|
|
1680
|
+
warnings.push(
|
|
1681
|
+
"LLMAsAService project_id and customer.customer_id must be supplied before rendering, usually through runtime provider_options."
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
return {
|
|
1685
|
+
valid: errors.length === 0,
|
|
1686
|
+
errors,
|
|
1687
|
+
warnings
|
|
1688
|
+
};
|
|
1689
|
+
},
|
|
1690
|
+
render(asset, runtime) {
|
|
1691
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1692
|
+
const options = resolvedAsset.provider_options?.llmasaservice;
|
|
1693
|
+
const model = resolvedAsset.model ?? defaultModel();
|
|
1694
|
+
const result = openaiAdapter.render(
|
|
1695
|
+
{ ...resolvedAsset, model, raw: void 0 },
|
|
1696
|
+
{
|
|
1697
|
+
variables: runtime.variables,
|
|
1698
|
+
history: runtime.history,
|
|
1699
|
+
onHistoryCompaction: runtime.onHistoryCompaction,
|
|
1700
|
+
toolRegistry: runtime.toolRegistry,
|
|
1701
|
+
strict: runtime.strict
|
|
1702
|
+
}
|
|
1703
|
+
);
|
|
1704
|
+
let body = { ...result.body };
|
|
1705
|
+
if (isGPT5ModelSelector(model) && body.max_tokens !== void 0 && body.max_completion_tokens === void 0) {
|
|
1706
|
+
body.max_completion_tokens = body.max_tokens;
|
|
1707
|
+
delete body.max_tokens;
|
|
1708
|
+
}
|
|
1709
|
+
if (options?.customer !== void 0) body.customer = options.customer;
|
|
1710
|
+
if (options?.conversationId !== void 0) body.conversationId = options.conversationId;
|
|
1711
|
+
if (options?.conversationTitle !== void 0) body.conversationTitle = options.conversationTitle;
|
|
1712
|
+
if (options?.projectId !== void 0) body.projectId = options.projectId;
|
|
1713
|
+
body = applyRawProviderBody(body, resolvedAsset, "llmasaservice");
|
|
1714
|
+
const projectId = options?.project_id ?? "";
|
|
1715
|
+
return {
|
|
1716
|
+
body,
|
|
1717
|
+
provider: "llmasaservice",
|
|
1718
|
+
model,
|
|
1719
|
+
baseURL: options?.base_url ?? LLMASASERVICE_BASE_URL,
|
|
1720
|
+
headers: {
|
|
1721
|
+
"x-project-id": projectId
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1726
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1727
|
+
0 && (module.exports = {
|
|
1728
|
+
LLMASASERVICE_BASE_URL,
|
|
1729
|
+
LLMASASERVICE_DEFAULT_MODEL,
|
|
1730
|
+
LLMASASERVICE_RESPONSE_HEADER_NAMES,
|
|
1731
|
+
LLMASASERVICE_SDK_PLACEHOLDER_API_KEY,
|
|
1732
|
+
createLLMAsAServiceOpenAIConfig,
|
|
1733
|
+
llmasaserviceAdapter
|
|
1734
|
+
});
|
|
1735
|
+
//# sourceMappingURL=llmasaservice.cjs.map
|