@kortyx/prompts 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/LICENSE +209 -0
- package/README.md +24 -2
- package/dist/browser.d.ts +180 -0
- package/dist/browser.js +491 -0
- package/dist/browser.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +840 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -3
package/dist/browser.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
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/browser.ts
|
|
31
|
+
var browser_exports = {};
|
|
32
|
+
__export(browser_exports, {
|
|
33
|
+
PROMPT_PROTOCOL_VERSION: () => PROMPT_PROTOCOL_VERSION,
|
|
34
|
+
PromptContentSchema: () => PromptContentSchema,
|
|
35
|
+
PromptError: () => PromptError,
|
|
36
|
+
PromptKeySchema: () => PromptKeySchema,
|
|
37
|
+
PromptMessageSchema: () => PromptMessageSchema,
|
|
38
|
+
PromptSnapshotSchema: () => PromptSnapshotSchema,
|
|
39
|
+
PromptTagSchema: () => PromptTagSchema,
|
|
40
|
+
PromptVersionSchema: () => PromptVersionSchema,
|
|
41
|
+
canonicalPromptJson: () => canonicalPromptJson,
|
|
42
|
+
compilePrompt: () => compilePrompt,
|
|
43
|
+
definePrompt: () => definePrompt,
|
|
44
|
+
expandPromptMessages: () => expandPromptMessages,
|
|
45
|
+
isCompiledPrompt: () => isCompiledPrompt,
|
|
46
|
+
isPromptUsageMetadata: () => isPromptUsageMetadata,
|
|
47
|
+
promptHash: () => promptHash,
|
|
48
|
+
promptReferencePattern: () => promptReferencePattern,
|
|
49
|
+
promptReferenceToken: () => promptReferenceToken,
|
|
50
|
+
promptReferences: () => promptReferences,
|
|
51
|
+
promptUsageMetadata: () => promptUsageMetadata,
|
|
52
|
+
promptVariables: () => promptVariables,
|
|
53
|
+
validatePromptContent: () => validatePromptContent,
|
|
54
|
+
validatePromptValue: () => validatePromptValue,
|
|
55
|
+
verifyPromptSnapshot: () => verifyPromptSnapshot
|
|
56
|
+
});
|
|
57
|
+
module.exports = __toCommonJS(browser_exports);
|
|
58
|
+
|
|
59
|
+
// src/compiler.ts
|
|
60
|
+
var import__ = __toESM(require("ajv/dist/2020"));
|
|
61
|
+
|
|
62
|
+
// src/contracts.ts
|
|
63
|
+
var import_zod = require("zod");
|
|
64
|
+
var PROMPT_PROTOCOL_VERSION = 1;
|
|
65
|
+
var PromptKeySchema = import_zod.z.string().min(1).max(200).regex(/^[a-zA-Z0-9][a-zA-Z0-9_./-]*$/);
|
|
66
|
+
var PromptTagSchema = import_zod.z.string().trim().min(1).max(64).regex(/^[a-z0-9][a-z0-9_-]*$/);
|
|
67
|
+
var PromptMessageSchema = import_zod.z.object({
|
|
68
|
+
role: import_zod.z.enum(["system", "user", "assistant"]),
|
|
69
|
+
content: import_zod.z.string().max(2e5)
|
|
70
|
+
}).strict();
|
|
71
|
+
var PromptContentSchema = import_zod.z.object({
|
|
72
|
+
format: import_zod.z.enum(["system-user", "chat"]),
|
|
73
|
+
messages: import_zod.z.array(PromptMessageSchema).min(1).max(100),
|
|
74
|
+
variablesSchema: import_zod.z.record(import_zod.z.string(), import_zod.z.json()),
|
|
75
|
+
configSchema: import_zod.z.record(import_zod.z.string(), import_zod.z.json()),
|
|
76
|
+
config: import_zod.z.record(import_zod.z.string(), import_zod.z.json()),
|
|
77
|
+
dependencies: import_zod.z.array(
|
|
78
|
+
import_zod.z.object({
|
|
79
|
+
id: PromptKeySchema,
|
|
80
|
+
version: import_zod.z.number().int().positive(),
|
|
81
|
+
hash: import_zod.z.string().regex(/^[a-f0-9]{64}$/)
|
|
82
|
+
}).strict()
|
|
83
|
+
).max(100).default([])
|
|
84
|
+
}).strict().superRefine((value, ctx) => {
|
|
85
|
+
if (value.format === "system-user" && (value.messages.length !== 2 || value.messages[0]?.role !== "system" || value.messages[1]?.role !== "user"))
|
|
86
|
+
ctx.addIssue({
|
|
87
|
+
code: "custom",
|
|
88
|
+
message: "system-user requires exactly one system message followed by one user message.",
|
|
89
|
+
path: ["messages"]
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
var PromptVersionSchema = import_zod.z.object({
|
|
93
|
+
id: PromptKeySchema,
|
|
94
|
+
version: import_zod.z.number().int().positive(),
|
|
95
|
+
hash: import_zod.z.string().regex(/^[a-f0-9]{64}$/),
|
|
96
|
+
content: PromptContentSchema
|
|
97
|
+
});
|
|
98
|
+
var PromptSnapshotSchema = import_zod.z.object({
|
|
99
|
+
schemaVersion: import_zod.z.literal(PROMPT_PROTOCOL_VERSION),
|
|
100
|
+
environment: import_zod.z.string().min(1).max(128),
|
|
101
|
+
tag: PromptTagSchema.optional(),
|
|
102
|
+
revision: import_zod.z.string().min(1),
|
|
103
|
+
versions: import_zod.z.record(import_zod.z.string(), PromptVersionSchema),
|
|
104
|
+
source: import_zod.z.enum(["studio", "local", "cache", "fallback", "eval"]),
|
|
105
|
+
resolvedAt: import_zod.z.iso.datetime(),
|
|
106
|
+
requestedIds: import_zod.z.array(PromptKeySchema).max(100).optional()
|
|
107
|
+
}).strict();
|
|
108
|
+
var PromptError = class extends Error {
|
|
109
|
+
constructor(code, message, status = 400) {
|
|
110
|
+
super(message);
|
|
111
|
+
this.code = code;
|
|
112
|
+
this.status = status;
|
|
113
|
+
}
|
|
114
|
+
code;
|
|
115
|
+
status;
|
|
116
|
+
name = "PromptError";
|
|
117
|
+
};
|
|
118
|
+
function canonicalPromptJson(value) {
|
|
119
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
120
|
+
if (Array.isArray(value))
|
|
121
|
+
return `[${value.map(canonicalPromptJson).join(",")}]`;
|
|
122
|
+
return `{${Object.keys(value).sort().map(
|
|
123
|
+
(key) => `${JSON.stringify(key)}:${canonicalPromptJson(value[key])}`
|
|
124
|
+
).join(",")}}`;
|
|
125
|
+
}
|
|
126
|
+
async function promptHash(content) {
|
|
127
|
+
const bytes = await crypto.subtle.digest(
|
|
128
|
+
"SHA-256",
|
|
129
|
+
new TextEncoder().encode(canonicalPromptJson(content))
|
|
130
|
+
);
|
|
131
|
+
return Array.from(
|
|
132
|
+
new Uint8Array(bytes),
|
|
133
|
+
(b) => b.toString(16).padStart(2, "0")
|
|
134
|
+
).join("");
|
|
135
|
+
}
|
|
136
|
+
async function verifyPromptSnapshot(value) {
|
|
137
|
+
const parsed = PromptSnapshotSchema.safeParse(value);
|
|
138
|
+
if (!parsed.success)
|
|
139
|
+
throw new PromptError(
|
|
140
|
+
"PROMPT_SNAPSHOT_INVALID",
|
|
141
|
+
"The prompt snapshot does not match the serving contract."
|
|
142
|
+
);
|
|
143
|
+
const snapshot = parsed.data;
|
|
144
|
+
if (Object.keys(snapshot.versions).length > 200)
|
|
145
|
+
throw new PromptError(
|
|
146
|
+
"PROMPT_SNAPSHOT_LIMIT",
|
|
147
|
+
"A snapshot supports at most 200 versions."
|
|
148
|
+
);
|
|
149
|
+
for (const [key, version] of Object.entries(snapshot.versions)) {
|
|
150
|
+
if (key !== version.id || await promptHash(version.content) !== version.hash)
|
|
151
|
+
throw new PromptError(
|
|
152
|
+
"PROMPT_HASH_MISMATCH",
|
|
153
|
+
`Prompt ${key} did not match its immutable hash.`
|
|
154
|
+
);
|
|
155
|
+
for (const dependency of version.content.dependencies) {
|
|
156
|
+
const actual = snapshot.versions[dependency.id];
|
|
157
|
+
if (!actual || actual.version !== dependency.version || actual.hash !== dependency.hash)
|
|
158
|
+
throw new PromptError(
|
|
159
|
+
"PROMPT_DEPENDENCY_MISMATCH",
|
|
160
|
+
`Missing exact dependency ${dependency.id}@${dependency.version}.`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const visit = (key, active, done2) => {
|
|
165
|
+
if (active.has(key))
|
|
166
|
+
throw new PromptError(
|
|
167
|
+
"PROMPT_DEPENDENCY_CYCLE",
|
|
168
|
+
`Prompt dependency cycle at ${key}.`
|
|
169
|
+
);
|
|
170
|
+
if (done2.has(key)) return;
|
|
171
|
+
active.add(key);
|
|
172
|
+
for (const dep of snapshot.versions[key]?.content.dependencies ?? [])
|
|
173
|
+
visit(dep.id, active, done2);
|
|
174
|
+
active.delete(key);
|
|
175
|
+
done2.add(key);
|
|
176
|
+
};
|
|
177
|
+
const done = /* @__PURE__ */ new Set();
|
|
178
|
+
for (const key of Object.keys(snapshot.versions)) visit(key, /* @__PURE__ */ new Set(), done);
|
|
179
|
+
const freeze = (value2) => {
|
|
180
|
+
if (value2 && typeof value2 === "object" && !Object.isFrozen(value2)) {
|
|
181
|
+
for (const nested of Object.values(value2)) freeze(nested);
|
|
182
|
+
Object.freeze(value2);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
freeze(snapshot);
|
|
186
|
+
return snapshot;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/references.ts
|
|
190
|
+
var promptReferencePattern = /\[\[prompt:([a-zA-Z0-9][a-zA-Z0-9_./-]*)\]\]/g;
|
|
191
|
+
function promptReferenceToken(id) {
|
|
192
|
+
return `[[prompt:${id}]]`;
|
|
193
|
+
}
|
|
194
|
+
function promptReferences(content) {
|
|
195
|
+
return [
|
|
196
|
+
...new Set(
|
|
197
|
+
content.messages.flatMap(
|
|
198
|
+
(message) => [...message.content.matchAll(promptReferencePattern)].map(
|
|
199
|
+
(match) => match[1]
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
function expandPromptMessages(root, versions = {}) {
|
|
206
|
+
const used = /* @__PURE__ */ new Map();
|
|
207
|
+
const cache = /* @__PURE__ */ new Map();
|
|
208
|
+
const expand = (owner, text, role, active) => {
|
|
209
|
+
const parts = [];
|
|
210
|
+
let size = 0, position = 0;
|
|
211
|
+
const append = (part) => {
|
|
212
|
+
size += part.length;
|
|
213
|
+
if (size > 2e5)
|
|
214
|
+
throw new PromptError(
|
|
215
|
+
"PROMPT_REFERENCE_LIMIT",
|
|
216
|
+
"An expanded message cannot exceed 200,000 characters."
|
|
217
|
+
);
|
|
218
|
+
parts.push(part);
|
|
219
|
+
};
|
|
220
|
+
for (const match of text.matchAll(promptReferencePattern)) {
|
|
221
|
+
append(text.slice(position, match.index));
|
|
222
|
+
position = match.index + match[0].length;
|
|
223
|
+
const id = match[1];
|
|
224
|
+
const dependency = owner.content.dependencies.find(
|
|
225
|
+
(item) => item.id === id
|
|
226
|
+
);
|
|
227
|
+
const child = versions[id];
|
|
228
|
+
if (!dependency || !child || child.version !== dependency.version || child.hash !== dependency.hash)
|
|
229
|
+
throw new PromptError(
|
|
230
|
+
"PROMPT_REFERENCE_MISSING",
|
|
231
|
+
`Include an exact dependency for referenced prompt ${id}.`
|
|
232
|
+
);
|
|
233
|
+
if (active.has(id) || active.size >= 200)
|
|
234
|
+
throw new PromptError(
|
|
235
|
+
"PROMPT_DEPENDENCY_CYCLE",
|
|
236
|
+
`Prompt reference cycle at ${id}.`
|
|
237
|
+
);
|
|
238
|
+
const messages = child.content.messages.filter(
|
|
239
|
+
(message) => message.role === role
|
|
240
|
+
);
|
|
241
|
+
if (!messages.length)
|
|
242
|
+
throw new PromptError(
|
|
243
|
+
"PROMPT_REFERENCE_ROLE",
|
|
244
|
+
`${id} has no ${role} message to include.`
|
|
245
|
+
);
|
|
246
|
+
used.set(id, child);
|
|
247
|
+
const cacheKey = `${id}@${child.version}:${role}`;
|
|
248
|
+
let included = cache.get(cacheKey);
|
|
249
|
+
if (included === void 0) {
|
|
250
|
+
const next = new Set(active).add(id);
|
|
251
|
+
const chunks = [];
|
|
252
|
+
let length = 0;
|
|
253
|
+
for (const message of messages) {
|
|
254
|
+
const chunk = expand(child, message.content, role, next);
|
|
255
|
+
length += chunk.length + (chunks.length ? 2 : 0);
|
|
256
|
+
if (length > 2e5)
|
|
257
|
+
throw new PromptError(
|
|
258
|
+
"PROMPT_REFERENCE_LIMIT",
|
|
259
|
+
"An expanded message cannot exceed 200,000 characters."
|
|
260
|
+
);
|
|
261
|
+
chunks.push(chunk);
|
|
262
|
+
}
|
|
263
|
+
included = chunks.join("\n\n");
|
|
264
|
+
cache.set(cacheKey, included);
|
|
265
|
+
}
|
|
266
|
+
append(included);
|
|
267
|
+
}
|
|
268
|
+
append(text.slice(position));
|
|
269
|
+
return parts.join("");
|
|
270
|
+
};
|
|
271
|
+
return {
|
|
272
|
+
messages: root.content.messages.map((message) => ({
|
|
273
|
+
...message,
|
|
274
|
+
content: expand(root, message.content, message.role, /* @__PURE__ */ new Set([root.id]))
|
|
275
|
+
})),
|
|
276
|
+
used: [...used.values()]
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/compiler.ts
|
|
281
|
+
var ajv = new import__.default({
|
|
282
|
+
strict: false,
|
|
283
|
+
allErrors: true,
|
|
284
|
+
validateFormats: false,
|
|
285
|
+
ownProperties: true
|
|
286
|
+
});
|
|
287
|
+
var validators = /* @__PURE__ */ new Map();
|
|
288
|
+
var compiledPrompts = /* @__PURE__ */ new WeakSet();
|
|
289
|
+
var usageMetadata = /* @__PURE__ */ new WeakSet();
|
|
290
|
+
function isCompiledPrompt(value) {
|
|
291
|
+
return Boolean(
|
|
292
|
+
value && typeof value === "object" && compiledPrompts.has(value)
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
function promptUsageMetadata(prompt) {
|
|
296
|
+
if (!isCompiledPrompt(prompt))
|
|
297
|
+
throw new PromptError(
|
|
298
|
+
"PROMPT_REASON_INVALID",
|
|
299
|
+
"Use a compiled prompt returned by usePrompt."
|
|
300
|
+
);
|
|
301
|
+
const metadata = Object.freeze({
|
|
302
|
+
id: prompt.ref.id,
|
|
303
|
+
version: prompt.ref.version,
|
|
304
|
+
hash: prompt.ref.hash,
|
|
305
|
+
environment: prompt.ref.environment,
|
|
306
|
+
snapshotRevision: prompt.ref.snapshotRevision,
|
|
307
|
+
...prompt.dependencies?.length ? { dependencies: prompt.dependencies } : {}
|
|
308
|
+
});
|
|
309
|
+
usageMetadata.add(metadata);
|
|
310
|
+
return metadata;
|
|
311
|
+
}
|
|
312
|
+
function isPromptUsageMetadata(value) {
|
|
313
|
+
return Boolean(
|
|
314
|
+
value && typeof value === "object" && usageMetadata.has(value)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
function freezeValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
318
|
+
if (value && typeof value === "object" && !seen.has(value)) {
|
|
319
|
+
seen.add(value);
|
|
320
|
+
for (const item of Object.values(value)) freezeValue(item, seen);
|
|
321
|
+
Object.freeze(value);
|
|
322
|
+
}
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
function validatePromptValue(schema, value, label) {
|
|
326
|
+
const key = canonicalPromptJson(schema);
|
|
327
|
+
let validator = validators.get(key);
|
|
328
|
+
if (!validator) {
|
|
329
|
+
if (validators.size >= 256) validators.clear();
|
|
330
|
+
try {
|
|
331
|
+
validator = ajv.compile(schema);
|
|
332
|
+
} catch {
|
|
333
|
+
throw new PromptError(
|
|
334
|
+
"PROMPT_SCHEMA_INVALID",
|
|
335
|
+
`${label} schema is invalid.`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
validators.set(key, validator);
|
|
339
|
+
}
|
|
340
|
+
if (!validator(value))
|
|
341
|
+
throw new PromptError(
|
|
342
|
+
"PROMPT_CONTRACT_MISMATCH",
|
|
343
|
+
`${label}: ${ajv.errorsText(validator.errors)}.`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
var placeholder = /\{\{\s*([A-Za-z_][A-Za-z0-9_.]*)\s*\}\}/g;
|
|
347
|
+
function promptVariables(content) {
|
|
348
|
+
return [
|
|
349
|
+
...new Set(
|
|
350
|
+
content.messages.flatMap(
|
|
351
|
+
(message) => [...message.content.matchAll(placeholder)].map(
|
|
352
|
+
(match) => match[1]
|
|
353
|
+
)
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
];
|
|
357
|
+
}
|
|
358
|
+
function validatePromptContent(content) {
|
|
359
|
+
validatePromptValue(content.configSchema, content.config, "Configuration");
|
|
360
|
+
try {
|
|
361
|
+
ajv.compile(content.variablesSchema);
|
|
362
|
+
} catch {
|
|
363
|
+
throw new PromptError(
|
|
364
|
+
"PROMPT_SCHEMA_INVALID",
|
|
365
|
+
"Template input schema is invalid."
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
const inputs = content.variablesSchema.properties;
|
|
369
|
+
for (const variable of promptVariables(content)) {
|
|
370
|
+
const top = variable.split(".")[0];
|
|
371
|
+
if (!inputs || !Object.hasOwn(inputs, top))
|
|
372
|
+
throw new PromptError(
|
|
373
|
+
"PROMPT_VARIABLE_UNKNOWN",
|
|
374
|
+
`Declare template input ${top} in the input schema.`
|
|
375
|
+
);
|
|
376
|
+
if (Object.hasOwn(content.config, top))
|
|
377
|
+
throw new PromptError(
|
|
378
|
+
"PROMPT_VARIABLE_CONFIG_OVERLAP",
|
|
379
|
+
`${top} cannot be both a template input and saved configuration.`
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function definePrompt(reference) {
|
|
384
|
+
if (!reference.id || !reference.variables || !reference.config)
|
|
385
|
+
throw new PromptError(
|
|
386
|
+
"PROMPT_REFERENCE_INVALID",
|
|
387
|
+
"A prompt reference needs id, variables and config schemas."
|
|
388
|
+
);
|
|
389
|
+
return Object.freeze({ ...reference });
|
|
390
|
+
}
|
|
391
|
+
function compilePrompt(ref, version, variables, identity, versions) {
|
|
392
|
+
if (version.id !== ref.id || version.content.format !== ref.format)
|
|
393
|
+
throw new PromptError(
|
|
394
|
+
"PROMPT_CONTRACT_MISMATCH",
|
|
395
|
+
`Prompt ${ref.id} format or identity differs from the application contract.`
|
|
396
|
+
);
|
|
397
|
+
const values = ref.variables.parse(variables);
|
|
398
|
+
validatePromptValue(
|
|
399
|
+
version.content.variablesSchema,
|
|
400
|
+
values,
|
|
401
|
+
"Template inputs"
|
|
402
|
+
);
|
|
403
|
+
validatePromptValue(
|
|
404
|
+
version.content.configSchema,
|
|
405
|
+
version.content.config,
|
|
406
|
+
"Configuration"
|
|
407
|
+
);
|
|
408
|
+
const config = ref.config.parse(structuredClone(version.content.config));
|
|
409
|
+
const expanded = expandPromptMessages(version, versions);
|
|
410
|
+
if (expanded.used.length)
|
|
411
|
+
validatePromptContent({ ...version.content, messages: expanded.messages });
|
|
412
|
+
for (const child of expanded.used) {
|
|
413
|
+
const properties = child.content.variablesSchema.properties;
|
|
414
|
+
const childValues = properties && typeof properties === "object" && !Array.isArray(properties) ? Object.fromEntries(
|
|
415
|
+
Object.keys(properties).filter((key) => Object.hasOwn(values, key)).map((key) => [key, values[key]])
|
|
416
|
+
) : values;
|
|
417
|
+
validatePromptValue(
|
|
418
|
+
child.content.variablesSchema,
|
|
419
|
+
childValues,
|
|
420
|
+
`Inputs for ${child.id}`
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
const messages = expanded.messages.map((message) => ({
|
|
424
|
+
role: message.role,
|
|
425
|
+
content: message.content.replace(placeholder, (_, path) => {
|
|
426
|
+
let value = values;
|
|
427
|
+
for (const key of path.split(".")) {
|
|
428
|
+
if (["__proto__", "constructor", "prototype"].includes(key) || !value || typeof value !== "object" || !Object.hasOwn(value, key))
|
|
429
|
+
throw new PromptError(
|
|
430
|
+
"PROMPT_VARIABLE_MISSING",
|
|
431
|
+
`Missing template input ${path}.`
|
|
432
|
+
);
|
|
433
|
+
value = value[key];
|
|
434
|
+
}
|
|
435
|
+
if (value === void 0)
|
|
436
|
+
throw new PromptError(
|
|
437
|
+
"PROMPT_VARIABLE_MISSING",
|
|
438
|
+
`Missing template input ${path}.`
|
|
439
|
+
);
|
|
440
|
+
return typeof value === "string" ? value : canonicalPromptJson(value);
|
|
441
|
+
})
|
|
442
|
+
}));
|
|
443
|
+
const compiled = freezeValue({
|
|
444
|
+
format: ref.format,
|
|
445
|
+
messages,
|
|
446
|
+
config,
|
|
447
|
+
...expanded.used.length ? {
|
|
448
|
+
dependencies: expanded.used.map(({ id, version: version2, hash }) => ({
|
|
449
|
+
id,
|
|
450
|
+
version: version2,
|
|
451
|
+
hash
|
|
452
|
+
}))
|
|
453
|
+
} : {},
|
|
454
|
+
...ref.format === "system-user" ? { system: messages[0]?.content, user: messages[1]?.content } : {},
|
|
455
|
+
ref: {
|
|
456
|
+
id: ref.id,
|
|
457
|
+
version: version.version,
|
|
458
|
+
hash: version.hash,
|
|
459
|
+
...identity
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
compiledPrompts.add(compiled);
|
|
463
|
+
return compiled;
|
|
464
|
+
}
|
|
465
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
466
|
+
0 && (module.exports = {
|
|
467
|
+
PROMPT_PROTOCOL_VERSION,
|
|
468
|
+
PromptContentSchema,
|
|
469
|
+
PromptError,
|
|
470
|
+
PromptKeySchema,
|
|
471
|
+
PromptMessageSchema,
|
|
472
|
+
PromptSnapshotSchema,
|
|
473
|
+
PromptTagSchema,
|
|
474
|
+
PromptVersionSchema,
|
|
475
|
+
canonicalPromptJson,
|
|
476
|
+
compilePrompt,
|
|
477
|
+
definePrompt,
|
|
478
|
+
expandPromptMessages,
|
|
479
|
+
isCompiledPrompt,
|
|
480
|
+
isPromptUsageMetadata,
|
|
481
|
+
promptHash,
|
|
482
|
+
promptReferencePattern,
|
|
483
|
+
promptReferenceToken,
|
|
484
|
+
promptReferences,
|
|
485
|
+
promptUsageMetadata,
|
|
486
|
+
promptVariables,
|
|
487
|
+
validatePromptContent,
|
|
488
|
+
validatePromptValue,
|
|
489
|
+
verifyPromptSnapshot
|
|
490
|
+
});
|
|
491
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/browser.ts","../src/compiler.ts","../src/contracts.ts","../src/references.ts"],"sourcesContent":["// Schemas, hashing and compilation have no Node integration or network side effects.\nexport * from \"./compiler\";\nexport * from \"./contracts\";\nexport * from \"./references\";\n","import Ajv2020 from \"ajv/dist/2020\";\nimport type { z } from \"zod\";\nimport {\n canonicalPromptJson,\n type PromptContent,\n PromptError,\n type PromptVersion,\n} from \"./contracts\";\nimport { expandPromptMessages } from \"./references\";\n\nconst ajv = new Ajv2020({\n strict: false,\n allErrors: true,\n validateFormats: false,\n ownProperties: true,\n});\nconst validators = new Map<string, ReturnType<typeof ajv.compile>>();\nconst compiledPrompts = new WeakSet<object>();\nconst usageMetadata = new WeakSet<object>();\nexport function isCompiledPrompt(value: unknown): value is CompiledPrompt {\n return Boolean(\n value && typeof value === \"object\" && compiledPrompts.has(value),\n );\n}\nexport function promptUsageMetadata(\n prompt: CompiledPrompt,\n): Record<string, unknown> {\n if (!isCompiledPrompt(prompt))\n throw new PromptError(\n \"PROMPT_REASON_INVALID\",\n \"Use a compiled prompt returned by usePrompt.\",\n );\n const metadata = Object.freeze({\n id: prompt.ref.id,\n version: prompt.ref.version,\n hash: prompt.ref.hash,\n environment: prompt.ref.environment,\n snapshotRevision: prompt.ref.snapshotRevision,\n ...(prompt.dependencies?.length\n ? { dependencies: prompt.dependencies }\n : {}),\n });\n usageMetadata.add(metadata);\n return metadata;\n}\nexport function isPromptUsageMetadata(value: unknown): value is {\n id: string;\n version: number;\n hash: string;\n environment: string;\n snapshotRevision: string;\n dependencies?: { id: string; version: number; hash: string }[];\n} {\n return Boolean(\n value && typeof value === \"object\" && usageMetadata.has(value),\n );\n}\nfunction freezeValue<T>(value: T, seen = new WeakSet<object>()): T {\n if (value && typeof value === \"object\" && !seen.has(value)) {\n seen.add(value);\n for (const item of Object.values(value)) freezeValue(item, seen);\n Object.freeze(value);\n }\n return value;\n}\nexport function validatePromptValue(\n schema: Record<string, unknown>,\n value: unknown,\n label: string,\n): void {\n const key = canonicalPromptJson(schema);\n let validator = validators.get(key);\n if (!validator) {\n if (validators.size >= 256) validators.clear();\n try {\n validator = ajv.compile(schema);\n } catch {\n throw new PromptError(\n \"PROMPT_SCHEMA_INVALID\",\n `${label} schema is invalid.`,\n );\n }\n validators.set(key, validator);\n }\n if (!validator(value))\n throw new PromptError(\n \"PROMPT_CONTRACT_MISMATCH\",\n `${label}: ${ajv.errorsText(validator.errors)}.`,\n );\n}\nconst placeholder = /\\{\\{\\s*([A-Za-z_][A-Za-z0-9_.]*)\\s*\\}\\}/g;\nexport function promptVariables(content: PromptContent): string[] {\n return [\n ...new Set(\n content.messages.flatMap((message) =>\n [...message.content.matchAll(placeholder)].map(\n (match) => match[1] as string,\n ),\n ),\n ),\n ];\n}\nexport function validatePromptContent(content: PromptContent): void {\n validatePromptValue(content.configSchema, content.config, \"Configuration\");\n // Compile both contracts before storing an executable version.\n try {\n ajv.compile(content.variablesSchema);\n } catch {\n throw new PromptError(\n \"PROMPT_SCHEMA_INVALID\",\n \"Template input schema is invalid.\",\n );\n }\n const inputs = content.variablesSchema.properties as\n | Record<string, unknown>\n | undefined;\n for (const variable of promptVariables(content)) {\n const top = variable.split(\".\")[0] as string;\n if (!inputs || !Object.hasOwn(inputs, top))\n throw new PromptError(\n \"PROMPT_VARIABLE_UNKNOWN\",\n `Declare template input ${top} in the input schema.`,\n );\n if (Object.hasOwn(content.config, top))\n throw new PromptError(\n \"PROMPT_VARIABLE_CONFIG_OVERLAP\",\n `${top} cannot be both a template input and saved configuration.`,\n );\n }\n}\nexport type PromptRef<\n Inputs = unknown,\n Config = unknown,\n Format extends \"system-user\" | \"chat\" = \"system-user\" | \"chat\",\n> = Readonly<{\n id: string;\n format: Format;\n variables: z.ZodType<Inputs>;\n config: z.ZodType<Config>;\n}>;\nexport function definePrompt<\n Inputs,\n Config,\n Format extends \"system-user\" | \"chat\",\n>(\n reference: PromptRef<Inputs, Config, Format>,\n): PromptRef<Inputs, Config, Format> {\n if (!reference.id || !reference.variables || !reference.config)\n throw new PromptError(\n \"PROMPT_REFERENCE_INVALID\",\n \"A prompt reference needs id, variables and config schemas.\",\n );\n return Object.freeze({ ...reference });\n}\nexport type CompiledPrompt<Config = unknown> = Readonly<{\n format: \"system-user\" | \"chat\";\n system?: string | undefined;\n user?: string | undefined;\n messages: { role: \"system\" | \"user\" | \"assistant\"; content: string }[];\n config: Config;\n dependencies?: { id: string; version: number; hash: string }[];\n ref: {\n id: string;\n version: number;\n hash: string;\n source: string;\n environment: string;\n snapshotRevision: string;\n };\n}>;\nexport function compilePrompt<Inputs, Config>(\n ref: PromptRef<Inputs, Config>,\n version: PromptVersion,\n variables: Inputs,\n identity: { source: string; environment: string; snapshotRevision: string },\n versions?: Readonly<Record<string, PromptVersion>>,\n): CompiledPrompt<Config> {\n if (version.id !== ref.id || version.content.format !== ref.format)\n throw new PromptError(\n \"PROMPT_CONTRACT_MISMATCH\",\n `Prompt ${ref.id} format or identity differs from the application contract.`,\n );\n const values = ref.variables.parse(variables);\n validatePromptValue(\n version.content.variablesSchema,\n values,\n \"Template inputs\",\n );\n validatePromptValue(\n version.content.configSchema,\n version.content.config,\n \"Configuration\",\n );\n const config = ref.config.parse(structuredClone(version.content.config));\n const expanded = expandPromptMessages(version, versions);\n if (expanded.used.length)\n validatePromptContent({ ...version.content, messages: expanded.messages });\n for (const child of expanded.used) {\n const properties = child.content.variablesSchema.properties;\n const childValues =\n properties && typeof properties === \"object\" && !Array.isArray(properties)\n ? Object.fromEntries(\n Object.keys(properties)\n .filter((key) => Object.hasOwn(values as object, key))\n .map((key) => [key, (values as Record<string, unknown>)[key]]),\n )\n : values;\n validatePromptValue(\n child.content.variablesSchema,\n childValues,\n `Inputs for ${child.id}`,\n );\n }\n const messages = expanded.messages.map((message) => ({\n role: message.role,\n content: message.content.replace(placeholder, (_, path: string) => {\n let value: unknown = values;\n for (const key of path.split(\".\")) {\n if (\n [\"__proto__\", \"constructor\", \"prototype\"].includes(key) ||\n !value ||\n typeof value !== \"object\" ||\n !Object.hasOwn(value, key)\n )\n throw new PromptError(\n \"PROMPT_VARIABLE_MISSING\",\n `Missing template input ${path}.`,\n );\n value = (value as Record<string, unknown>)[key];\n }\n if (value === undefined)\n throw new PromptError(\n \"PROMPT_VARIABLE_MISSING\",\n `Missing template input ${path}.`,\n );\n return typeof value === \"string\" ? value : canonicalPromptJson(value);\n }),\n }));\n const compiled = freezeValue({\n format: ref.format,\n messages,\n config,\n ...(expanded.used.length\n ? {\n dependencies: expanded.used.map(({ id, version, hash }) => ({\n id,\n version,\n hash,\n })),\n }\n : {}),\n ...(ref.format === \"system-user\"\n ? { system: messages[0]?.content, user: messages[1]?.content }\n : {}),\n ref: {\n id: ref.id,\n version: version.version,\n hash: version.hash,\n ...identity,\n },\n });\n compiledPrompts.add(compiled);\n return compiled;\n}\n","import { z } from \"zod\";\n\nexport const PROMPT_PROTOCOL_VERSION = 1 as const;\nexport const PromptKeySchema = z\n .string()\n .min(1)\n .max(200)\n .regex(/^[a-zA-Z0-9][a-zA-Z0-9_./-]*$/);\nexport const PromptTagSchema = z\n .string()\n .trim()\n .min(1)\n .max(64)\n .regex(/^[a-z0-9][a-z0-9_-]*$/);\nexport const PromptMessageSchema = z\n .object({\n role: z.enum([\"system\", \"user\", \"assistant\"]),\n content: z.string().max(200_000),\n })\n .strict();\nexport const PromptContentSchema = z\n .object({\n format: z.enum([\"system-user\", \"chat\"]),\n messages: z.array(PromptMessageSchema).min(1).max(100),\n variablesSchema: z.record(z.string(), z.json()),\n configSchema: z.record(z.string(), z.json()),\n config: z.record(z.string(), z.json()),\n dependencies: z\n .array(\n z\n .object({\n id: PromptKeySchema,\n version: z.number().int().positive(),\n hash: z.string().regex(/^[a-f0-9]{64}$/),\n })\n .strict(),\n )\n .max(100)\n .default([]),\n })\n .strict()\n .superRefine((value, ctx) => {\n if (\n value.format === \"system-user\" &&\n (value.messages.length !== 2 ||\n value.messages[0]?.role !== \"system\" ||\n value.messages[1]?.role !== \"user\")\n )\n ctx.addIssue({\n code: \"custom\",\n message:\n \"system-user requires exactly one system message followed by one user message.\",\n path: [\"messages\"],\n });\n });\nexport const PromptVersionSchema = z.object({\n id: PromptKeySchema,\n version: z.number().int().positive(),\n hash: z.string().regex(/^[a-f0-9]{64}$/),\n content: PromptContentSchema,\n});\nexport const PromptSnapshotSchema = z\n .object({\n schemaVersion: z.literal(PROMPT_PROTOCOL_VERSION),\n environment: z.string().min(1).max(128),\n tag: PromptTagSchema.optional(),\n revision: z.string().min(1),\n versions: z.record(z.string(), PromptVersionSchema),\n source: z.enum([\"studio\", \"local\", \"cache\", \"fallback\", \"eval\"]),\n resolvedAt: z.iso.datetime(),\n requestedIds: z.array(PromptKeySchema).max(100).optional(),\n })\n .strict();\nexport type PromptContent = z.infer<typeof PromptContentSchema>;\nexport type PromptVersion = z.infer<typeof PromptVersionSchema>;\nexport type PromptSnapshot = z.infer<typeof PromptSnapshotSchema>;\n\nexport class PromptError extends Error {\n override name = \"PromptError\";\n constructor(\n readonly code: string,\n message: string,\n readonly status = 400,\n ) {\n super(message);\n }\n}\n\n/** The executable hash excludes mutable names, categories, authors and notes. */\nexport function canonicalPromptJson(value: unknown): string {\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\n if (Array.isArray(value))\n return `[${value.map(canonicalPromptJson).join(\",\")}]`;\n return `{${Object.keys(value)\n .sort()\n .map(\n (key) =>\n `${JSON.stringify(key)}:${canonicalPromptJson((value as Record<string, unknown>)[key])}`,\n )\n .join(\",\")}}`;\n}\nexport async function promptHash(content: PromptContent): Promise<string> {\n const bytes = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(canonicalPromptJson(content)),\n );\n return Array.from(new Uint8Array(bytes), (b) =>\n b.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n}\n\nexport async function verifyPromptSnapshot(\n value: unknown,\n): Promise<PromptSnapshot> {\n const parsed = PromptSnapshotSchema.safeParse(value);\n if (!parsed.success)\n throw new PromptError(\n \"PROMPT_SNAPSHOT_INVALID\",\n \"The prompt snapshot does not match the serving contract.\",\n );\n const snapshot = parsed.data;\n if (Object.keys(snapshot.versions).length > 200)\n throw new PromptError(\n \"PROMPT_SNAPSHOT_LIMIT\",\n \"A snapshot supports at most 200 versions.\",\n );\n for (const [key, version] of Object.entries(snapshot.versions)) {\n if (\n key !== version.id ||\n (await promptHash(version.content)) !== version.hash\n )\n throw new PromptError(\n \"PROMPT_HASH_MISMATCH\",\n `Prompt ${key} did not match its immutable hash.`,\n );\n for (const dependency of version.content.dependencies) {\n const actual = snapshot.versions[dependency.id];\n if (\n !actual ||\n actual.version !== dependency.version ||\n actual.hash !== dependency.hash\n )\n throw new PromptError(\n \"PROMPT_DEPENDENCY_MISMATCH\",\n `Missing exact dependency ${dependency.id}@${dependency.version}.`,\n );\n }\n }\n const visit = (key: string, active: Set<string>, done: Set<string>) => {\n if (active.has(key))\n throw new PromptError(\n \"PROMPT_DEPENDENCY_CYCLE\",\n `Prompt dependency cycle at ${key}.`,\n );\n if (done.has(key)) return;\n active.add(key);\n for (const dep of snapshot.versions[key]?.content.dependencies ?? [])\n visit(dep.id, active, done);\n active.delete(key);\n done.add(key);\n };\n const done = new Set<string>();\n for (const key of Object.keys(snapshot.versions)) visit(key, new Set(), done);\n const freeze = (value: unknown): void => {\n if (value && typeof value === \"object\" && !Object.isFrozen(value)) {\n for (const nested of Object.values(value)) freeze(nested);\n Object.freeze(value);\n }\n };\n freeze(snapshot);\n return snapshot;\n}\n","import {\n type PromptContent,\n PromptError,\n type PromptVersion,\n} from \"./contracts\";\n\n// Display names are editable; persisted references use stable keys and exact\n// versions/hashes in the existing dependency manifest.\nexport const promptReferencePattern =\n /\\[\\[prompt:([a-zA-Z0-9][a-zA-Z0-9_./-]*)\\]\\]/g;\nexport function promptReferenceToken(id: string) {\n return `[[prompt:${id}]]`;\n}\nexport function promptReferences(content: PromptContent): string[] {\n return [\n ...new Set(\n content.messages.flatMap((message) =>\n [...message.content.matchAll(promptReferencePattern)].map(\n (match) => match[1]!,\n ),\n ),\n ),\n ];\n}\nexport function expandPromptMessages(\n root: PromptVersion,\n versions: Readonly<Record<string, PromptVersion>> = {},\n): { messages: PromptContent[\"messages\"]; used: PromptVersion[] } {\n const used = new Map<string, PromptVersion>();\n const cache = new Map<string, string>();\n const expand = (\n owner: PromptVersion,\n text: string,\n role: PromptContent[\"messages\"][number][\"role\"],\n active: Set<string>,\n ): string => {\n const parts: string[] = [];\n let size = 0,\n position = 0;\n const append = (part: string) => {\n size += part.length;\n if (size > 200_000)\n throw new PromptError(\n \"PROMPT_REFERENCE_LIMIT\",\n \"An expanded message cannot exceed 200,000 characters.\",\n );\n parts.push(part);\n };\n for (const match of text.matchAll(promptReferencePattern)) {\n append(text.slice(position, match.index));\n position = match.index! + match[0].length;\n const id = match[1]!;\n const dependency = owner.content.dependencies.find(\n (item) => item.id === id,\n );\n const child = versions[id];\n if (\n !dependency ||\n !child ||\n child.version !== dependency.version ||\n child.hash !== dependency.hash\n )\n throw new PromptError(\n \"PROMPT_REFERENCE_MISSING\",\n `Include an exact dependency for referenced prompt ${id}.`,\n );\n if (active.has(id) || active.size >= 200)\n throw new PromptError(\n \"PROMPT_DEPENDENCY_CYCLE\",\n `Prompt reference cycle at ${id}.`,\n );\n const messages = child.content.messages.filter(\n (message) => message.role === role,\n );\n if (!messages.length)\n throw new PromptError(\n \"PROMPT_REFERENCE_ROLE\",\n `${id} has no ${role} message to include.`,\n );\n used.set(id, child);\n const cacheKey = `${id}@${child.version}:${role}`;\n let included = cache.get(cacheKey);\n if (included === undefined) {\n const next = new Set(active).add(id);\n const chunks: string[] = [];\n let length = 0;\n for (const message of messages) {\n const chunk = expand(child, message.content, role, next);\n length += chunk.length + (chunks.length ? 2 : 0);\n if (length > 200_000)\n throw new PromptError(\n \"PROMPT_REFERENCE_LIMIT\",\n \"An expanded message cannot exceed 200,000 characters.\",\n );\n chunks.push(chunk);\n }\n included = chunks.join(\"\\n\\n\");\n cache.set(cacheKey, included);\n }\n append(included);\n }\n append(text.slice(position));\n return parts.join(\"\");\n };\n return {\n messages: root.content.messages.map((message) => ({\n ...message,\n content: expand(root, message.content, message.role, new Set([root.id])),\n })),\n used: [...used.values()],\n };\n}\n"],"mappings":"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","names":["done","value","Ajv2020","version"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { PromptSnapshot, PromptRef, CompiledPrompt } from './browser.js';
|
|
2
|
+
export { PROMPT_PROTOCOL_VERSION, PromptContent, PromptContentSchema, PromptError, PromptKeySchema, PromptMessageSchema, PromptSnapshotSchema, PromptTagSchema, PromptVersion, PromptVersionSchema, canonicalPromptJson, compilePrompt, definePrompt, expandPromptMessages, isCompiledPrompt, isPromptUsageMetadata, promptHash, promptReferencePattern, promptReferenceToken, promptReferences, promptUsageMetadata, promptVariables, validatePromptContent, validatePromptValue, verifyPromptSnapshot } from './browser.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
interface PromptSource {
|
|
6
|
+
readonly environment?: string;
|
|
7
|
+
readonly tag?: string;
|
|
8
|
+
readonly identity: string;
|
|
9
|
+
resolve(ids: readonly string[], options: {
|
|
10
|
+
environment: string;
|
|
11
|
+
tag?: string;
|
|
12
|
+
versions?: Record<string, number>;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
}): Promise<PromptSnapshot>;
|
|
15
|
+
}
|
|
16
|
+
interface PromptCache {
|
|
17
|
+
get(key: string): Promise<PromptSnapshot | undefined>;
|
|
18
|
+
set(key: string, snapshot: PromptSnapshot): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
interface PromptExecution {
|
|
21
|
+
recordUsage(usage: PromptUsageReceipt): void;
|
|
22
|
+
snapshot(stored?: unknown): Promise<PromptSnapshot>;
|
|
23
|
+
pin(id: string, version: number, stored?: unknown): Promise<PromptSnapshot>;
|
|
24
|
+
resolve<Inputs, Config>(ref: PromptRef<Inputs, Config>, options: {
|
|
25
|
+
variables: Inputs;
|
|
26
|
+
version?: number;
|
|
27
|
+
stored?: unknown;
|
|
28
|
+
pin?: PromptSnapshot;
|
|
29
|
+
}): Promise<CompiledPrompt<Config>>;
|
|
30
|
+
}
|
|
31
|
+
interface PromptManager {
|
|
32
|
+
definitions: readonly PromptRef[];
|
|
33
|
+
start(options?: {
|
|
34
|
+
snapshot?: PromptSnapshot;
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
onUsage?: (usage: PromptUsageReceipt) => void;
|
|
37
|
+
}): PromptExecution;
|
|
38
|
+
}
|
|
39
|
+
type PromptUsageReceipt = {
|
|
40
|
+
id: string;
|
|
41
|
+
version: number;
|
|
42
|
+
hash: string;
|
|
43
|
+
environment: string;
|
|
44
|
+
snapshotRevision: string;
|
|
45
|
+
model?: string;
|
|
46
|
+
};
|
|
47
|
+
declare function createPrompts(options: {
|
|
48
|
+
definitions: readonly PromptRef[];
|
|
49
|
+
source: PromptSource;
|
|
50
|
+
environment?: string;
|
|
51
|
+
fallback?: "last-known-good" | "error";
|
|
52
|
+
maxStaleMs?: number;
|
|
53
|
+
cache?: PromptCache;
|
|
54
|
+
}): PromptManager;
|
|
55
|
+
declare function studioPromptSource(options: {
|
|
56
|
+
apiUrl: string;
|
|
57
|
+
apiKey: string;
|
|
58
|
+
/** Version tag to serve. Promotion updates live; other tags are managed manually. */
|
|
59
|
+
tag?: string;
|
|
60
|
+
environment?: string;
|
|
61
|
+
projectId?: string;
|
|
62
|
+
environmentId?: string;
|
|
63
|
+
timeoutMs?: number;
|
|
64
|
+
retries?: number;
|
|
65
|
+
fetch?: typeof fetch;
|
|
66
|
+
}): PromptSource;
|
|
67
|
+
declare function localPromptSource(snapshot: PromptSnapshot): PromptSource;
|
|
68
|
+
|
|
69
|
+
export { CompiledPrompt, type PromptCache, type PromptExecution, type PromptManager, PromptRef, PromptSnapshot, type PromptSource, type PromptUsageReceipt, createPrompts, localPromptSource, studioPromptSource };
|