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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadPromptFile,
|
|
3
3
|
parsePrompt
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UY5OKMVP.js";
|
|
5
5
|
|
|
6
6
|
// src/renderer/interpolate.ts
|
|
7
7
|
var VARIABLE_RE = /\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/g;
|
|
@@ -9,12 +9,13 @@ var ESCAPED_OPEN = /\\\{\\\{/g;
|
|
|
9
9
|
var ESCAPE_PLACEHOLDER = "\0ESCAPED_OPEN\0";
|
|
10
10
|
function interpolate(template, variables, options = {}) {
|
|
11
11
|
const { strict = false } = options;
|
|
12
|
+
const optionalVariables = new Set(options.optionalVariables ?? []);
|
|
12
13
|
let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);
|
|
13
14
|
result = result.replace(VARIABLE_RE, (match, name) => {
|
|
14
15
|
if (name in variables) {
|
|
15
16
|
return variables[name];
|
|
16
17
|
}
|
|
17
|
-
if (strict) {
|
|
18
|
+
if (strict && !optionalVariables.has(name)) {
|
|
18
19
|
throw new Error(`Missing required variable: "${name}"`);
|
|
19
20
|
}
|
|
20
21
|
return match;
|
|
@@ -32,589 +33,650 @@ function extractVariables(template) {
|
|
|
32
33
|
return [...vars];
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
// src/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
asset.sections.system_instructions,
|
|
42
|
-
variables,
|
|
43
|
-
{ strict }
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
if (asset.sections.prompt_template) {
|
|
47
|
-
result.prompt_template = interpolate(
|
|
48
|
-
asset.sections.prompt_template,
|
|
49
|
-
variables,
|
|
50
|
-
{ strict }
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
36
|
+
// src/context.ts
|
|
37
|
+
var textEncoder = new TextEncoder();
|
|
38
|
+
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
39
|
+
var REJECT_SECRETS_FLAGS = "i";
|
|
40
|
+
function getContextInputs(asset) {
|
|
41
|
+
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
54
42
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let result = { ...asset };
|
|
59
|
-
if (options.environment && result.environments?.[options.environment]) {
|
|
60
|
-
result = mergeOverride(result, result.environments[options.environment]);
|
|
43
|
+
function normalizeContextInput(input) {
|
|
44
|
+
if (typeof input === "string") {
|
|
45
|
+
return { name: input };
|
|
61
46
|
}
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
return {
|
|
48
|
+
name: input.name,
|
|
49
|
+
optional: input.optional,
|
|
50
|
+
warnings: input.warnings,
|
|
51
|
+
max_size: input.max_size,
|
|
52
|
+
trim: input.trim,
|
|
53
|
+
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
54
|
+
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
55
|
+
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
56
|
+
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function areContextInputWarningsEnabled(input) {
|
|
60
|
+
return input.warnings !== false;
|
|
61
|
+
}
|
|
62
|
+
function normalizeContextRegex(value) {
|
|
63
|
+
if (value === void 0) {
|
|
64
|
+
return void 0;
|
|
64
65
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
66
|
+
if (typeof value === "string") {
|
|
67
|
+
const literal = parseRegexLiteral(value);
|
|
68
|
+
if (value.startsWith("/") && !literal) {
|
|
69
|
+
return {
|
|
70
|
+
pattern: value,
|
|
71
|
+
flags: "",
|
|
72
|
+
raw: value,
|
|
73
|
+
invalidLiteral: true
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
pattern: literal?.pattern ?? value,
|
|
78
|
+
flags: literal?.flags ?? "",
|
|
79
|
+
raw: value
|
|
80
|
+
};
|
|
67
81
|
}
|
|
68
|
-
return
|
|
82
|
+
return {
|
|
83
|
+
pattern: value.pattern,
|
|
84
|
+
flags: value.flags ?? "",
|
|
85
|
+
raw: JSON.stringify(value),
|
|
86
|
+
returnMessage: value.return_message
|
|
87
|
+
};
|
|
69
88
|
}
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
74
|
-
if (override.tools !== void 0) result.tools = override.tools;
|
|
75
|
-
if (override.reasoning !== void 0) {
|
|
76
|
-
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
89
|
+
function normalizeBuiltInValidator(value) {
|
|
90
|
+
if (value === void 0 || value === false) {
|
|
91
|
+
return void 0;
|
|
77
92
|
}
|
|
78
|
-
if (
|
|
79
|
-
|
|
93
|
+
if (value === true) {
|
|
94
|
+
return {};
|
|
80
95
|
}
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
return {
|
|
97
|
+
returnMessage: value.return_message
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function parseRegexLiteral(value) {
|
|
101
|
+
if (!value.startsWith("/")) {
|
|
102
|
+
return void 0;
|
|
83
103
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
105
|
+
if (value[index] !== "/") {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
let backslashCount = 0;
|
|
109
|
+
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
110
|
+
backslashCount += 1;
|
|
111
|
+
}
|
|
112
|
+
if (backslashCount % 2 === 1) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
pattern: value.slice(1, index),
|
|
117
|
+
flags: value.slice(index + 1)
|
|
92
118
|
};
|
|
93
119
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
function formatInvalidContextRegexMessage(details) {
|
|
123
|
+
return [
|
|
124
|
+
`Invalid context regex for prompt "${details.promptId}"`,
|
|
125
|
+
`variable "${details.variable}"`,
|
|
126
|
+
`field "${details.field}"`,
|
|
127
|
+
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
128
|
+
].join(", ");
|
|
129
|
+
}
|
|
130
|
+
function compileContextRegex(regex, details) {
|
|
131
|
+
if (regex.invalidLiteral) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`POK013: ${formatInvalidContextRegexMessage({
|
|
134
|
+
...details,
|
|
135
|
+
raw: regex.raw,
|
|
136
|
+
reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
|
|
137
|
+
})}`
|
|
138
|
+
);
|
|
106
139
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
...result.provider_options?.anthropic,
|
|
113
|
-
...override.provider_options.anthropic
|
|
114
|
-
},
|
|
115
|
-
gemini: {
|
|
116
|
-
...result.provider_options?.gemini,
|
|
117
|
-
...override.provider_options.gemini
|
|
118
|
-
},
|
|
119
|
-
openrouter: {
|
|
120
|
-
...result.provider_options?.openrouter,
|
|
121
|
-
...override.provider_options.openrouter
|
|
122
|
-
}
|
|
123
|
-
};
|
|
140
|
+
try {
|
|
141
|
+
return new RegExp(regex.pattern, regex.flags);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
144
|
+
throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
|
|
124
145
|
}
|
|
125
|
-
return result;
|
|
126
146
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
147
|
+
function getRejectSecretsRegex() {
|
|
148
|
+
return {
|
|
149
|
+
pattern: REJECT_SECRETS_PATTERN,
|
|
150
|
+
flags: REJECT_SECRETS_FLAGS,
|
|
151
|
+
raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
|
|
152
|
+
};
|
|
130
153
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
154
|
+
function isTrimEnabled(mode) {
|
|
155
|
+
return mode === true || mode === "start" || mode === "end" || mode === "both";
|
|
156
|
+
}
|
|
157
|
+
function normalizeTrimMode(mode) {
|
|
158
|
+
if (mode === "start") {
|
|
159
|
+
return "start";
|
|
136
160
|
}
|
|
137
|
-
return
|
|
138
|
-
environment: runtime.environment,
|
|
139
|
-
tier: runtime.tier,
|
|
140
|
-
runtime: runtime.runtime
|
|
141
|
-
});
|
|
161
|
+
return "end";
|
|
142
162
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
cache = /* @__PURE__ */ new Map();
|
|
148
|
-
maxSize;
|
|
149
|
-
constructor(maxSize = 100) {
|
|
150
|
-
this.maxSize = maxSize;
|
|
163
|
+
function trimToMaxSize(value, maxSize, mode) {
|
|
164
|
+
const measured = measureContextValueSize(value);
|
|
165
|
+
if (measured <= maxSize) {
|
|
166
|
+
return value;
|
|
151
167
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
const characters = Array.from(value);
|
|
169
|
+
const normalizedMode = normalizeTrimMode(mode);
|
|
170
|
+
if (normalizedMode === "start") {
|
|
171
|
+
let collected2 = "";
|
|
172
|
+
let size2 = 0;
|
|
173
|
+
for (let i = characters.length - 1; i >= 0; i -= 1) {
|
|
174
|
+
const next = characters[i];
|
|
175
|
+
const charSize = measureContextValueSize(next);
|
|
176
|
+
if (size2 + charSize > maxSize) {
|
|
177
|
+
break;
|
|
160
178
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return void 0;
|
|
179
|
+
collected2 = next + collected2;
|
|
180
|
+
size2 += charSize;
|
|
164
181
|
}
|
|
165
|
-
|
|
166
|
-
this.cache.set(filePath, entry);
|
|
167
|
-
return entry.value;
|
|
182
|
+
return collected2;
|
|
168
183
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const oldest = this.cache.keys().next().value;
|
|
176
|
-
if (oldest) this.cache.delete(oldest);
|
|
177
|
-
}
|
|
178
|
-
this.cache.set(filePath, { value, mtime: stat.mtimeMs });
|
|
179
|
-
} catch {
|
|
184
|
+
let collected = "";
|
|
185
|
+
let size = 0;
|
|
186
|
+
for (const char of characters) {
|
|
187
|
+
const charSize = measureContextValueSize(char);
|
|
188
|
+
if (size + charSize > maxSize) {
|
|
189
|
+
break;
|
|
180
190
|
}
|
|
191
|
+
collected += char;
|
|
192
|
+
size += charSize;
|
|
181
193
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
import { readFile } from "fs/promises";
|
|
192
|
-
import { resolve, dirname } from "path";
|
|
193
|
-
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
194
|
-
if (!asset.includes || asset.includes.length === 0) {
|
|
195
|
-
return asset;
|
|
196
|
-
}
|
|
197
|
-
const baseDir = dirname(basePath);
|
|
198
|
-
const resolvedPath = resolve(basePath);
|
|
199
|
-
if (visited.has(resolvedPath)) {
|
|
200
|
-
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
201
|
-
}
|
|
202
|
-
visited.add(resolvedPath);
|
|
203
|
-
let mergedSystemInstructions = "";
|
|
204
|
-
for (const includePath of asset.includes) {
|
|
205
|
-
const fullPath = resolve(baseDir, includePath);
|
|
206
|
-
if (visited.has(fullPath)) {
|
|
207
|
-
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
194
|
+
return collected;
|
|
195
|
+
}
|
|
196
|
+
function sanitizeContextVariables(asset, variables = {}, options = {}) {
|
|
197
|
+
const { onContextOverflow } = options;
|
|
198
|
+
const sanitized = { ...variables };
|
|
199
|
+
for (const input of getContextInputs(asset)) {
|
|
200
|
+
const value = sanitized[input.name];
|
|
201
|
+
if (value === void 0) {
|
|
202
|
+
continue;
|
|
208
203
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
204
|
+
let candidate = value;
|
|
205
|
+
if (input.max_size !== void 0) {
|
|
206
|
+
const actualSize = measureContextValueSize(candidate);
|
|
207
|
+
if (actualSize > input.max_size && onContextOverflow) {
|
|
208
|
+
candidate = onContextOverflow({
|
|
209
|
+
promptId: asset.id,
|
|
210
|
+
variable: input.name,
|
|
211
|
+
value: candidate,
|
|
212
|
+
maxSize: input.max_size,
|
|
213
|
+
actualSize
|
|
214
|
+
});
|
|
215
|
+
}
|
|
214
216
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
...config,
|
|
238
|
-
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
239
|
-
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
var sharedPromptCache = new PromptCache();
|
|
243
|
-
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
244
|
-
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
245
|
-
const mode = resolvedConfig.mode ?? "auto";
|
|
246
|
-
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
247
|
-
const compiledFile = resolve2(resolvedConfig.compiledDir, promptPath + ".json");
|
|
248
|
-
if (existsSync(compiledFile)) {
|
|
249
|
-
if (mode === "auto") {
|
|
250
|
-
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
251
|
-
if (existsSync(sourceFile)) {
|
|
252
|
-
const compiledMtime = statSync2(compiledFile).mtimeMs;
|
|
253
|
-
const sourceMtime = statSync2(sourceFile).mtimeMs;
|
|
254
|
-
if (sourceMtime > compiledMtime) {
|
|
255
|
-
console.warn(
|
|
256
|
-
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
257
|
-
Run "promptopskit compile" or switch to source-only mode.`
|
|
258
|
-
);
|
|
259
|
-
}
|
|
217
|
+
if (isTrimEnabled(input.trim) && input.max_size !== void 0) {
|
|
218
|
+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
|
|
219
|
+
}
|
|
220
|
+
sanitized[input.name] = candidate;
|
|
221
|
+
if (input.allow_regex) {
|
|
222
|
+
const candidate2 = sanitized[input.name];
|
|
223
|
+
const matcher = compileContextRegex(input.allow_regex, {
|
|
224
|
+
promptId: asset.id,
|
|
225
|
+
variable: input.name,
|
|
226
|
+
field: "allow_regex"
|
|
227
|
+
});
|
|
228
|
+
if (!matcher.test(candidate2)) {
|
|
229
|
+
if (input.allow_regex.returnMessage) {
|
|
230
|
+
return {
|
|
231
|
+
variables: sanitized,
|
|
232
|
+
shortCircuit: {
|
|
233
|
+
returnMessage: input.allow_regex.returnMessage,
|
|
234
|
+
code: "POK031",
|
|
235
|
+
variable: input.name,
|
|
236
|
+
field: "allow_regex"
|
|
237
|
+
}
|
|
238
|
+
};
|
|
260
239
|
}
|
|
240
|
+
throw new Error(
|
|
241
|
+
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
242
|
+
);
|
|
261
243
|
}
|
|
262
|
-
const content = await readFile2(compiledFile, "utf-8");
|
|
263
|
-
return JSON.parse(content);
|
|
264
|
-
}
|
|
265
|
-
if (mode === "compiled-only") {
|
|
266
|
-
throw new Error(
|
|
267
|
-
`Compiled artifact not found: ${compiledFile}
|
|
268
|
-
Run "promptopskit compile" to generate it.`
|
|
269
|
-
);
|
|
270
244
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
245
|
+
if (input.deny_regex) {
|
|
246
|
+
const candidate2 = sanitized[input.name];
|
|
247
|
+
const matcher = compileContextRegex(input.deny_regex, {
|
|
248
|
+
promptId: asset.id,
|
|
249
|
+
variable: input.name,
|
|
250
|
+
field: "deny_regex"
|
|
251
|
+
});
|
|
252
|
+
if (matcher.test(candidate2)) {
|
|
253
|
+
if (input.deny_regex.returnMessage) {
|
|
254
|
+
return {
|
|
255
|
+
variables: sanitized,
|
|
256
|
+
shortCircuit: {
|
|
257
|
+
returnMessage: input.deny_regex.returnMessage,
|
|
258
|
+
code: "POK032",
|
|
259
|
+
variable: input.name,
|
|
260
|
+
field: "deny_regex"
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
throw new Error(
|
|
265
|
+
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
266
|
+
);
|
|
278
267
|
}
|
|
279
268
|
}
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
269
|
+
if (input.non_empty && candidate.trim().length === 0) {
|
|
270
|
+
if (input.non_empty.returnMessage) {
|
|
271
|
+
return {
|
|
272
|
+
variables: sanitized,
|
|
273
|
+
shortCircuit: {
|
|
274
|
+
returnMessage: input.non_empty.returnMessage,
|
|
275
|
+
code: "POK033",
|
|
276
|
+
variable: input.name,
|
|
277
|
+
field: "non_empty"
|
|
278
|
+
}
|
|
279
|
+
};
|
|
284
280
|
}
|
|
285
281
|
throw new Error(
|
|
286
|
-
`
|
|
287
|
-
Searched:
|
|
288
|
-
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
282
|
+
`POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
|
|
289
283
|
);
|
|
290
284
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
const { asset } = parsePrompt(source);
|
|
315
|
-
return applyOverrides(asset, {
|
|
316
|
-
environment: options.environment,
|
|
317
|
-
tier: options.tier,
|
|
318
|
-
runtime: options.runtime
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// src/context.ts
|
|
323
|
-
var textEncoder = new TextEncoder();
|
|
324
|
-
var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
|
|
325
|
-
var REJECT_SECRETS_FLAGS = "i";
|
|
326
|
-
function getContextInputs(asset) {
|
|
327
|
-
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
328
|
-
}
|
|
329
|
-
function getContextInputNames(asset) {
|
|
330
|
-
return getContextInputs(asset).map((input) => input.name);
|
|
331
|
-
}
|
|
332
|
-
function normalizeContextInput(input) {
|
|
333
|
-
if (typeof input === "string") {
|
|
334
|
-
return { name: input };
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
name: input.name,
|
|
338
|
-
max_size: input.max_size,
|
|
339
|
-
trim: input.trim,
|
|
340
|
-
allow_regex: normalizeContextRegex(input.allow_regex),
|
|
341
|
-
deny_regex: normalizeContextRegex(input.deny_regex),
|
|
342
|
-
non_empty: normalizeBuiltInValidator(input.non_empty),
|
|
343
|
-
reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
function normalizeContextRegex(value) {
|
|
347
|
-
if (value === void 0) {
|
|
348
|
-
return void 0;
|
|
349
|
-
}
|
|
350
|
-
if (typeof value === "string") {
|
|
351
|
-
const literal = parseRegexLiteral(value);
|
|
352
|
-
if (value.startsWith("/") && !literal) {
|
|
353
|
-
return {
|
|
354
|
-
pattern: value,
|
|
355
|
-
flags: "",
|
|
356
|
-
raw: value,
|
|
357
|
-
invalidLiteral: true
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
return {
|
|
361
|
-
pattern: literal?.pattern ?? value,
|
|
362
|
-
flags: literal?.flags ?? "",
|
|
363
|
-
raw: value
|
|
364
|
-
};
|
|
285
|
+
if (input.reject_secrets) {
|
|
286
|
+
const matcher = compileContextRegex(getRejectSecretsRegex(), {
|
|
287
|
+
promptId: asset.id,
|
|
288
|
+
variable: input.name,
|
|
289
|
+
field: "reject_secrets"
|
|
290
|
+
});
|
|
291
|
+
if (matcher.test(candidate)) {
|
|
292
|
+
if (input.reject_secrets.returnMessage) {
|
|
293
|
+
return {
|
|
294
|
+
variables: sanitized,
|
|
295
|
+
shortCircuit: {
|
|
296
|
+
returnMessage: input.reject_secrets.returnMessage,
|
|
297
|
+
code: "POK034",
|
|
298
|
+
variable: input.name,
|
|
299
|
+
field: "reject_secrets"
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
throw new Error(
|
|
304
|
+
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
365
308
|
}
|
|
366
|
-
return {
|
|
367
|
-
pattern: value.pattern,
|
|
368
|
-
flags: value.flags ?? "",
|
|
369
|
-
raw: JSON.stringify(value),
|
|
370
|
-
returnMessage: value.return_message
|
|
371
|
-
};
|
|
309
|
+
return { variables: sanitized };
|
|
372
310
|
}
|
|
373
|
-
function
|
|
374
|
-
|
|
375
|
-
return void 0;
|
|
376
|
-
}
|
|
377
|
-
if (value === true) {
|
|
378
|
-
return {};
|
|
379
|
-
}
|
|
380
|
-
return {
|
|
381
|
-
returnMessage: value.return_message
|
|
382
|
-
};
|
|
311
|
+
function measureContextValueSize(value) {
|
|
312
|
+
return textEncoder.encode(value).length;
|
|
383
313
|
}
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
for (let index = value.length - 1; index > 0; index -= 1) {
|
|
389
|
-
if (value[index] !== "/") {
|
|
314
|
+
function collectContextSizeWarnings(asset, variables = {}) {
|
|
315
|
+
const warnings = [];
|
|
316
|
+
for (const input of getContextInputs(asset)) {
|
|
317
|
+
if (!areContextInputWarningsEnabled(input)) {
|
|
390
318
|
continue;
|
|
391
319
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
backslashCount += 1;
|
|
320
|
+
if (input.max_size === void 0) {
|
|
321
|
+
continue;
|
|
395
322
|
}
|
|
396
|
-
|
|
323
|
+
const value = variables[input.name];
|
|
324
|
+
if (value === void 0) {
|
|
397
325
|
continue;
|
|
398
326
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
327
|
+
const actualSize = measureContextValueSize(value);
|
|
328
|
+
if (actualSize > input.max_size) {
|
|
329
|
+
warnings.push({
|
|
330
|
+
variable: input.name,
|
|
331
|
+
maxSize: input.max_size,
|
|
332
|
+
actualSize
|
|
333
|
+
});
|
|
334
|
+
}
|
|
403
335
|
}
|
|
404
|
-
return
|
|
405
|
-
}
|
|
406
|
-
function formatInvalidContextRegexMessage(details) {
|
|
407
|
-
return [
|
|
408
|
-
`Invalid context regex for prompt "${details.promptId}"`,
|
|
409
|
-
`variable "${details.variable}"`,
|
|
410
|
-
`field "${details.field}"`,
|
|
411
|
-
`value ${JSON.stringify(details.raw)}: ${details.reason}`
|
|
412
|
-
].join(", ");
|
|
336
|
+
return warnings;
|
|
413
337
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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 }
|
|
422
349
|
);
|
|
423
350
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
351
|
+
if (asset.sections.prompt_template) {
|
|
352
|
+
result.prompt_template = interpolate(
|
|
353
|
+
asset.sections.prompt_template,
|
|
354
|
+
variables,
|
|
355
|
+
{ strict, optionalVariables }
|
|
356
|
+
);
|
|
429
357
|
}
|
|
358
|
+
return result;
|
|
430
359
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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;
|
|
437
374
|
}
|
|
438
|
-
function
|
|
439
|
-
|
|
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;
|
|
440
436
|
}
|
|
441
|
-
function
|
|
442
|
-
if (
|
|
443
|
-
|
|
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;
|
|
444
446
|
}
|
|
445
|
-
return
|
|
447
|
+
return applyOverrides(asset, {
|
|
448
|
+
environment: runtime.environment,
|
|
449
|
+
tier: runtime.tier,
|
|
450
|
+
runtime: runtime.runtime
|
|
451
|
+
});
|
|
446
452
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
453
|
+
|
|
454
|
+
// src/cache.ts
|
|
455
|
+
import { statSync } from "fs";
|
|
456
|
+
var PromptCache = class {
|
|
457
|
+
cache = /* @__PURE__ */ new Map();
|
|
458
|
+
maxSize;
|
|
459
|
+
constructor(maxSize = 100) {
|
|
460
|
+
this.maxSize = maxSize;
|
|
451
461
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if (size2 + charSize > maxSize) {
|
|
461
|
-
break;
|
|
462
|
+
get(filePath) {
|
|
463
|
+
const entry = this.cache.get(filePath);
|
|
464
|
+
if (!entry) return void 0;
|
|
465
|
+
try {
|
|
466
|
+
const stat = statSync(filePath);
|
|
467
|
+
if (stat.mtimeMs !== entry.mtime) {
|
|
468
|
+
this.cache.delete(filePath);
|
|
469
|
+
return void 0;
|
|
462
470
|
}
|
|
463
|
-
|
|
464
|
-
|
|
471
|
+
} catch {
|
|
472
|
+
this.cache.delete(filePath);
|
|
473
|
+
return void 0;
|
|
465
474
|
}
|
|
466
|
-
|
|
475
|
+
this.cache.delete(filePath);
|
|
476
|
+
this.cache.set(filePath, entry);
|
|
477
|
+
return entry.value;
|
|
478
|
+
}
|
|
479
|
+
set(filePath, value) {
|
|
480
|
+
try {
|
|
481
|
+
const stat = statSync(filePath);
|
|
482
|
+
if (this.cache.has(filePath)) {
|
|
483
|
+
this.cache.delete(filePath);
|
|
484
|
+
} else if (this.cache.size >= this.maxSize) {
|
|
485
|
+
const oldest = this.cache.keys().next().value;
|
|
486
|
+
if (oldest) this.cache.delete(oldest);
|
|
487
|
+
}
|
|
488
|
+
this.cache.set(filePath, { value, mtime: stat.mtimeMs });
|
|
489
|
+
} catch {
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
clear() {
|
|
493
|
+
this.cache.clear();
|
|
494
|
+
}
|
|
495
|
+
get size() {
|
|
496
|
+
return this.cache.size;
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// src/composition/resolve-includes.ts
|
|
501
|
+
import { readFile } from "fs/promises";
|
|
502
|
+
import { resolve, dirname } from "path";
|
|
503
|
+
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
504
|
+
if (!asset.includes || asset.includes.length === 0) {
|
|
505
|
+
return asset;
|
|
506
|
+
}
|
|
507
|
+
const baseDir = dirname(basePath);
|
|
508
|
+
const resolvedPath = resolve(basePath);
|
|
509
|
+
if (visited.has(resolvedPath)) {
|
|
510
|
+
throw new Error(`Circular include detected: ${resolvedPath}`);
|
|
467
511
|
}
|
|
468
|
-
|
|
469
|
-
let
|
|
470
|
-
for (const
|
|
471
|
-
const
|
|
472
|
-
if (
|
|
473
|
-
|
|
512
|
+
visited.add(resolvedPath);
|
|
513
|
+
let mergedSystemInstructions = "";
|
|
514
|
+
for (const includePath of asset.includes) {
|
|
515
|
+
const fullPath = resolve(baseDir, includePath);
|
|
516
|
+
if (visited.has(fullPath)) {
|
|
517
|
+
throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);
|
|
518
|
+
}
|
|
519
|
+
const content = await readFile(fullPath, "utf-8");
|
|
520
|
+
const { asset: includedAsset } = parsePrompt(content, fullPath);
|
|
521
|
+
const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));
|
|
522
|
+
if (resolved.sections?.system_instructions) {
|
|
523
|
+
mergedSystemInstructions += resolved.sections.system_instructions + "\n\n";
|
|
474
524
|
}
|
|
475
|
-
collected += char;
|
|
476
|
-
size += charSize;
|
|
477
525
|
}
|
|
478
|
-
|
|
526
|
+
const localSystem = asset.sections?.system_instructions ?? "";
|
|
527
|
+
const combinedSystem = (mergedSystemInstructions + localSystem).trim() || void 0;
|
|
528
|
+
return {
|
|
529
|
+
...asset,
|
|
530
|
+
sections: {
|
|
531
|
+
...asset.sections,
|
|
532
|
+
system_instructions: combinedSystem
|
|
533
|
+
},
|
|
534
|
+
// Drop includes from the resolved asset — they've been inlined
|
|
535
|
+
includes: void 0
|
|
536
|
+
};
|
|
479
537
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if (!matcher.test(candidate2)) {
|
|
513
|
-
if (input.allow_regex.returnMessage) {
|
|
514
|
-
return {
|
|
515
|
-
variables: sanitized,
|
|
516
|
-
shortCircuit: {
|
|
517
|
-
returnMessage: input.allow_regex.returnMessage,
|
|
518
|
-
code: "POK031",
|
|
519
|
-
variable: input.name,
|
|
520
|
-
field: "allow_regex"
|
|
521
|
-
}
|
|
522
|
-
};
|
|
538
|
+
|
|
539
|
+
// src/prompt-resolution.ts
|
|
540
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
541
|
+
import { existsSync, statSync as statSync2 } from "fs";
|
|
542
|
+
import { resolve as resolve2 } from "path";
|
|
543
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
544
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
545
|
+
function withPromptResolutionDefaults(config) {
|
|
546
|
+
return {
|
|
547
|
+
...config,
|
|
548
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
549
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
var sharedPromptCache = new PromptCache();
|
|
553
|
+
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
554
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
555
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
556
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
557
|
+
const compiledFile = resolve2(resolvedConfig.compiledDir, promptPath + ".json");
|
|
558
|
+
if (existsSync(compiledFile)) {
|
|
559
|
+
if (mode === "auto") {
|
|
560
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
561
|
+
if (existsSync(sourceFile)) {
|
|
562
|
+
const compiledMtime = statSync2(compiledFile).mtimeMs;
|
|
563
|
+
const sourceMtime = statSync2(sourceFile).mtimeMs;
|
|
564
|
+
if (sourceMtime > compiledMtime) {
|
|
565
|
+
console.warn(
|
|
566
|
+
`[promptopskit] Warning: compiled artifact for "${promptPath}" is older than source .md file.
|
|
567
|
+
Run "promptopskit compile" or switch to source-only mode.`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
523
570
|
}
|
|
524
|
-
throw new Error(
|
|
525
|
-
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
526
|
-
);
|
|
527
571
|
}
|
|
572
|
+
const content = await readFile2(compiledFile, "utf-8");
|
|
573
|
+
return JSON.parse(content);
|
|
528
574
|
}
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
code: "POK032",
|
|
543
|
-
variable: input.name,
|
|
544
|
-
field: "deny_regex"
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
throw new Error(
|
|
549
|
-
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
550
|
-
);
|
|
575
|
+
if (mode === "compiled-only") {
|
|
576
|
+
throw new Error(
|
|
577
|
+
`Compiled artifact not found: ${compiledFile}
|
|
578
|
+
Run "promptopskit compile" to generate it.`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
if (mode !== "compiled-only") {
|
|
583
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
584
|
+
if (resolvedConfig.cache !== false) {
|
|
585
|
+
const cached = promptCache.get(sourceFile);
|
|
586
|
+
if (cached) {
|
|
587
|
+
return cached;
|
|
551
588
|
}
|
|
552
589
|
}
|
|
553
|
-
if (
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
shortCircuit: {
|
|
558
|
-
returnMessage: input.non_empty.returnMessage,
|
|
559
|
-
code: "POK033",
|
|
560
|
-
variable: input.name,
|
|
561
|
-
field: "non_empty"
|
|
562
|
-
}
|
|
563
|
-
};
|
|
590
|
+
if (!existsSync(sourceFile)) {
|
|
591
|
+
const paths = [sourceFile];
|
|
592
|
+
if (resolvedConfig.compiledDir) {
|
|
593
|
+
paths.unshift(resolve2(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
564
594
|
}
|
|
565
595
|
throw new Error(
|
|
566
|
-
`
|
|
596
|
+
`Prompt not found: "${promptPath}"
|
|
597
|
+
Searched:
|
|
598
|
+
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
567
599
|
);
|
|
568
600
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
variable: input.name,
|
|
573
|
-
field: "reject_secrets"
|
|
574
|
-
});
|
|
575
|
-
if (matcher.test(candidate)) {
|
|
576
|
-
if (input.reject_secrets.returnMessage) {
|
|
577
|
-
return {
|
|
578
|
-
variables: sanitized,
|
|
579
|
-
shortCircuit: {
|
|
580
|
-
returnMessage: input.reject_secrets.returnMessage,
|
|
581
|
-
code: "POK034",
|
|
582
|
-
variable: input.name,
|
|
583
|
-
field: "reject_secrets"
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
}
|
|
587
|
-
throw new Error(
|
|
588
|
-
`POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
|
|
589
|
-
);
|
|
590
|
-
}
|
|
601
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
602
|
+
if (resolvedConfig.cache !== false) {
|
|
603
|
+
promptCache.set(sourceFile, asset);
|
|
591
604
|
}
|
|
605
|
+
return asset;
|
|
592
606
|
}
|
|
593
|
-
|
|
607
|
+
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
594
608
|
}
|
|
595
|
-
function
|
|
596
|
-
|
|
609
|
+
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
610
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
611
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
612
|
+
const sourceFile = resolve2(resolvedConfig.sourceDir, promptPath + ".md");
|
|
613
|
+
if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {
|
|
614
|
+
asset = await resolveIncludes(asset, sourceFile);
|
|
615
|
+
}
|
|
616
|
+
asset = applyOverrides(asset, {
|
|
617
|
+
environment: options.environment,
|
|
618
|
+
tier: options.tier,
|
|
619
|
+
runtime: options.runtime
|
|
620
|
+
});
|
|
621
|
+
return asset;
|
|
597
622
|
}
|
|
598
|
-
function
|
|
599
|
-
const
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
623
|
+
function resolveInlinePromptSource(source, options = {}) {
|
|
624
|
+
const { asset } = parsePrompt(source);
|
|
625
|
+
return applyOverrides(asset, {
|
|
626
|
+
environment: options.environment,
|
|
627
|
+
tier: options.tier,
|
|
628
|
+
runtime: options.runtime
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/history.ts
|
|
633
|
+
function defaultCompactHistory(info) {
|
|
634
|
+
const content = info.overflow.map((message) => `${message.role}: ${message.content}`).join("\n\n");
|
|
635
|
+
return {
|
|
636
|
+
role: "user",
|
|
637
|
+
content: `Earlier conversation compacted to preserve history:
|
|
638
|
+
|
|
639
|
+
${content}`
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function normalizeCompactionResult(result) {
|
|
643
|
+
if (typeof result === "string") {
|
|
644
|
+
return {
|
|
645
|
+
role: "user",
|
|
646
|
+
content: result
|
|
647
|
+
};
|
|
616
648
|
}
|
|
617
|
-
return
|
|
649
|
+
return result;
|
|
650
|
+
}
|
|
651
|
+
function compactHistoryForPrompt(asset, runtime) {
|
|
652
|
+
const history = runtime.history;
|
|
653
|
+
const maxItems = asset.context?.history?.max_items;
|
|
654
|
+
if (!history || maxItems === void 0 || history.length <= maxItems) {
|
|
655
|
+
return history;
|
|
656
|
+
}
|
|
657
|
+
if (maxItems === 1) {
|
|
658
|
+
const info2 = {
|
|
659
|
+
promptId: asset.id,
|
|
660
|
+
maxItems,
|
|
661
|
+
overflow: history,
|
|
662
|
+
preserved: [],
|
|
663
|
+
history
|
|
664
|
+
};
|
|
665
|
+
const compacted2 = runtime.onHistoryCompaction ? normalizeCompactionResult(runtime.onHistoryCompaction(info2)) : defaultCompactHistory(info2);
|
|
666
|
+
return [compacted2];
|
|
667
|
+
}
|
|
668
|
+
const preservedCount = maxItems - 1;
|
|
669
|
+
const overflow = history.slice(0, history.length - preservedCount);
|
|
670
|
+
const preserved = history.slice(-preservedCount);
|
|
671
|
+
const info = {
|
|
672
|
+
promptId: asset.id,
|
|
673
|
+
maxItems,
|
|
674
|
+
overflow,
|
|
675
|
+
preserved,
|
|
676
|
+
history
|
|
677
|
+
};
|
|
678
|
+
const compacted = runtime.onHistoryCompaction ? normalizeCompactionResult(runtime.onHistoryCompaction(info)) : defaultCompactHistory(info);
|
|
679
|
+
return [compacted, ...preserved];
|
|
618
680
|
}
|
|
619
681
|
|
|
620
682
|
// src/providers/prompt-input.ts
|
|
@@ -652,7 +714,8 @@ function withPromptInputSupport(adapter) {
|
|
|
652
714
|
}
|
|
653
715
|
return adapter.render(resolved, {
|
|
654
716
|
...runtime,
|
|
655
|
-
variables: sanitization.variables
|
|
717
|
+
variables: sanitization.variables,
|
|
718
|
+
history: compactHistoryForPrompt(resolved, runtime)
|
|
656
719
|
});
|
|
657
720
|
};
|
|
658
721
|
return {
|
|
@@ -680,6 +743,11 @@ function getRawProviderBody(asset, provider) {
|
|
|
680
743
|
export {
|
|
681
744
|
interpolate,
|
|
682
745
|
extractVariables,
|
|
746
|
+
getContextInputs,
|
|
747
|
+
areContextInputWarningsEnabled,
|
|
748
|
+
compileContextRegex,
|
|
749
|
+
sanitizeContextVariables,
|
|
750
|
+
collectContextSizeWarnings,
|
|
683
751
|
renderSections,
|
|
684
752
|
applyOverrides,
|
|
685
753
|
resolveAssetForProvider,
|
|
@@ -690,12 +758,8 @@ export {
|
|
|
690
758
|
loadPromptAsset,
|
|
691
759
|
resolvePromptAsset,
|
|
692
760
|
resolveInlinePromptSource,
|
|
693
|
-
|
|
694
|
-
getContextInputNames,
|
|
695
|
-
compileContextRegex,
|
|
696
|
-
sanitizeContextVariables,
|
|
697
|
-
collectContextSizeWarnings,
|
|
761
|
+
compactHistoryForPrompt,
|
|
698
762
|
withPromptInputSupport,
|
|
699
763
|
applyRawProviderBody
|
|
700
764
|
};
|
|
701
|
-
//# sourceMappingURL=chunk-
|
|
765
|
+
//# sourceMappingURL=chunk-JR7252DG.js.map
|