@promptlycms/prompts 0.2.0 → 0.3.0-canary.2f7697e
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 +64 -6
- package/dist/cli.js +183 -20
- package/dist/index.cjs +133 -4
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +130 -3
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/types-DIVyjOlH.d.cts +198 -0
- package/dist/types-DIVyjOlH.d.ts +198 -0
- package/package.json +14 -14
- package/dist/types-BbNpKJej.d.cts +0 -118
- package/dist/types-BbNpKJej.d.ts +0 -118
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
TypeScript SDK for the [Promptly CMS](https://promptlycms.com) API. Stop hardcoding prompts in your codebase — manage them in a purpose-built CMS with versioning and instant publishing, then fetch them at runtime with full type safety.
|
|
4
4
|
|
|
5
5
|
- **Zero hardcoded prompts** — fetch prompts at runtime; update wording, models, and settings from the [CMS](https://promptlycms.com) without code changes or redeploys
|
|
6
|
-
- **Runtime client** — `getPrompt()` and `
|
|
7
|
-
- **
|
|
6
|
+
- **Runtime client** — `getPrompt()`, `getPrompts()`, `getComposer()`, and `getComposers()` with full TypeScript support
|
|
7
|
+
- **Composers** — fetch multi-segment documents that combine static HTML with prompt references, then assemble AI-generated output with `formatComposer()`
|
|
8
|
+
- **Codegen CLI** — generates typed template variables and composer types via declaration merging
|
|
8
9
|
- **AI SDK integration** — destructure directly into [Vercel AI SDK](https://ai-sdk.dev/) `generateText` / `streamText`
|
|
9
10
|
- **Any AI provider** — supports [all providers](https://ai-sdk.dev/providers/ai-sdk-providers#provider-support) supported by the Vercel AI SDK
|
|
10
11
|
- **Structured output** — Zod schemas built from CMS-defined output schemas
|
|
@@ -18,7 +19,8 @@ npm install @promptlycms/prompts
|
|
|
18
19
|
Peer dependencies:
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
|
-
npm install zod ai
|
|
22
|
+
npm install zod ai
|
|
23
|
+
npm install --save-dev typescript
|
|
22
24
|
```
|
|
23
25
|
|
|
24
26
|
You'll also need at least one AI provider SDK for model resolution:
|
|
@@ -46,7 +48,7 @@ PROMPTLY_API_KEY=pk_live_...
|
|
|
46
48
|
npx promptly generate
|
|
47
49
|
```
|
|
48
50
|
|
|
49
|
-
This fetches all your prompts from the API and generates a `promptly-env.d.ts` file in your project root with typed autocomplete for every prompt ID
|
|
51
|
+
This fetches all your prompts and composers from the API and generates a `promptly-env.d.ts` file in your project root with typed autocomplete for every prompt ID, composer ID, template variables, and prompt names.
|
|
50
52
|
|
|
51
53
|
```bash
|
|
52
54
|
# Custom output path
|
|
@@ -135,6 +137,49 @@ const { text } = await generateText({
|
|
|
135
137
|
|
|
136
138
|
The model configured in the CMS is auto-resolved to the correct AI SDK provider.
|
|
137
139
|
|
|
140
|
+
## Fetching composers
|
|
141
|
+
|
|
142
|
+
A composer is a document template that combines static HTML segments with prompt references. Fetch a composer and use `compose()` to run all prompts and assemble the output in one call:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { generateText } from 'ai';
|
|
146
|
+
|
|
147
|
+
const composer = await promptly.getComposer('my-composer-id', {
|
|
148
|
+
input: { text: 'Hello world', targetLang: 'French' },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// One line — runs all prompts in parallel, assembles the output
|
|
152
|
+
const output = await composer.compose(generateText);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Override parameters per prompt:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
const output = await composer.compose((prompt) =>
|
|
159
|
+
generateText({ ...prompt, maxTokens: 500 })
|
|
160
|
+
);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For full control, use the manual flow with named prompts and `formatComposer()`:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
const { introPrompt, reviewPrompt, formatComposer } = composer;
|
|
167
|
+
|
|
168
|
+
const output = formatComposer({
|
|
169
|
+
introPrompt: await generateText(introPrompt),
|
|
170
|
+
reviewPrompt: await generateText(reviewPrompt),
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Batch fetch multiple composers in parallel:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const [first, second] = await promptly.getComposers([
|
|
178
|
+
{ composerId: 'comp-a', input: { name: 'Dan' } },
|
|
179
|
+
{ composerId: 'comp-b', input: { topic: 'AI' } },
|
|
180
|
+
]);
|
|
181
|
+
```
|
|
182
|
+
|
|
138
183
|
## Model auto-detection
|
|
139
184
|
|
|
140
185
|
The SDK automatically resolves models configured in the CMS to the correct AI SDK provider based on the model name prefix:
|
|
@@ -187,7 +232,7 @@ declare module '@promptlycms/prompts' {
|
|
|
187
232
|
}
|
|
188
233
|
```
|
|
189
234
|
|
|
190
|
-
With this file present, `getPrompt()` and `getPrompts()` return typed `userMessage` functions with autocomplete.
|
|
235
|
+
With this file present, `getPrompt()` and `getPrompts()` return typed `userMessage` functions with autocomplete. `getComposer()` and `getComposers()` get typed `input` and named prompt properties. Unknown IDs fall back to `Record<string, string>`.
|
|
191
236
|
|
|
192
237
|
Add the generated file to version control so types are available without running codegen in CI. Re-run `npx promptly generate` whenever you add, remove, or rename template variables in the CMS.
|
|
193
238
|
|
|
@@ -221,7 +266,7 @@ try {
|
|
|
221
266
|
| `baseUrl` | `string` | No | API base URL (default: `https://api.promptlycms.com`) |
|
|
222
267
|
| `model` | `(modelId: string) => LanguageModel` | No | Custom model resolver — overrides auto-detection |
|
|
223
268
|
|
|
224
|
-
Returns a `PromptlyClient` with `getPrompt()` and `
|
|
269
|
+
Returns a `PromptlyClient` with `getPrompt()`, `getPrompts()`, `getComposer()`, and `getComposers()` methods.
|
|
225
270
|
|
|
226
271
|
### `client.getPrompt(promptId, options?)`
|
|
227
272
|
|
|
@@ -235,6 +280,19 @@ Fetch a single prompt. Returns `PromptResult` with typed `userMessage` when code
|
|
|
235
280
|
|
|
236
281
|
Fetch multiple prompts in parallel. Accepts `PromptRequest[]` and returns a typed tuple matching the input order.
|
|
237
282
|
|
|
283
|
+
### `client.getComposer(composerId, options?)`
|
|
284
|
+
|
|
285
|
+
Fetch a single composer. Returns `ComposerResult` with named prompt properties, a `prompts` array, and `formatComposer()`.
|
|
286
|
+
|
|
287
|
+
| Option | Type | Description |
|
|
288
|
+
|-----------|---------------------------|----------------------|
|
|
289
|
+
| `input` | `Record<string, string>` | Template variables to interpolate |
|
|
290
|
+
| `version` | `string` | Specific version to fetch (default: latest) |
|
|
291
|
+
|
|
292
|
+
### `client.getComposers(entries)`
|
|
293
|
+
|
|
294
|
+
Fetch multiple composers in parallel. Accepts `ComposerRequest[]` and returns results in the same order.
|
|
295
|
+
|
|
238
296
|
### `@promptlycms/prompts/schema`
|
|
239
297
|
|
|
240
298
|
Subpath export for working with Zod schemas from CMS schema fields:
|
package/dist/cli.js
CHANGED
|
@@ -65,6 +65,7 @@ var detectProviderName = (modelId) => {
|
|
|
65
65
|
}
|
|
66
66
|
return void 0;
|
|
67
67
|
};
|
|
68
|
+
var toCamelCase = (name) => name.replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase()).replace(/^[A-Z]/, (char) => char.toLowerCase());
|
|
68
69
|
|
|
69
70
|
// src/cli/generate.ts
|
|
70
71
|
var PROVIDER_PACKAGES = {
|
|
@@ -98,6 +99,50 @@ var fetchAllPrompts = async (apiKey, baseUrl) => {
|
|
|
98
99
|
}
|
|
99
100
|
return response.json();
|
|
100
101
|
};
|
|
102
|
+
var fetchAllComposers = async (apiKey, baseUrl) => {
|
|
103
|
+
const url = new URL("/composers", baseUrl ?? DEFAULT_BASE_URL);
|
|
104
|
+
url.searchParams.set("include_versions", "true");
|
|
105
|
+
const response = await fetch(url.toString(), {
|
|
106
|
+
headers: {
|
|
107
|
+
Authorization: `Bearer ${apiKey}`
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok) {
|
|
111
|
+
throw await createErrorFromResponse(response);
|
|
112
|
+
}
|
|
113
|
+
return response.json();
|
|
114
|
+
};
|
|
115
|
+
var extractComposerVariables = (composer) => {
|
|
116
|
+
const vars = /* @__PURE__ */ new Set();
|
|
117
|
+
for (const segment of composer.segments) {
|
|
118
|
+
if (segment.type !== "prompt") {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (!segment.userMessage) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
for (const v of extractTemplateVariables(segment.userMessage)) {
|
|
125
|
+
vars.add(v);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return [...vars];
|
|
129
|
+
};
|
|
130
|
+
var extractComposerPromptNames = (composer) => {
|
|
131
|
+
const seen = /* @__PURE__ */ new Set();
|
|
132
|
+
const names = [];
|
|
133
|
+
for (const segment of composer.segments) {
|
|
134
|
+
if (segment.type !== "prompt") {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const camelName = toCamelCase(segment.promptName);
|
|
138
|
+
if (seen.has(camelName)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
seen.add(camelName);
|
|
142
|
+
names.push(camelName);
|
|
143
|
+
}
|
|
144
|
+
return names;
|
|
145
|
+
};
|
|
101
146
|
var compareSemver = (a, b) => {
|
|
102
147
|
const pa = a.split(".").map(Number);
|
|
103
148
|
const pb = b.split(".").map(Number);
|
|
@@ -171,7 +216,43 @@ var groupAndSortVersions = (prompt) => {
|
|
|
171
216
|
});
|
|
172
217
|
return result;
|
|
173
218
|
};
|
|
174
|
-
var
|
|
219
|
+
var ELEMENT_TYPE_MAP = {
|
|
220
|
+
string: "string",
|
|
221
|
+
number: "number",
|
|
222
|
+
boolean: "boolean"
|
|
223
|
+
};
|
|
224
|
+
var schemaFieldToTsType = (field) => {
|
|
225
|
+
if (!field) {
|
|
226
|
+
return "string";
|
|
227
|
+
}
|
|
228
|
+
switch (field.type) {
|
|
229
|
+
case "number":
|
|
230
|
+
case "boolean":
|
|
231
|
+
return field.type;
|
|
232
|
+
case "array": {
|
|
233
|
+
const elementTs = ELEMENT_TYPE_MAP[field.params.elementType ?? ""] ?? "string";
|
|
234
|
+
return `${elementTs}[]`;
|
|
235
|
+
}
|
|
236
|
+
case "enum": {
|
|
237
|
+
if (field.params.enumValues && field.params.enumValues.length > 0) {
|
|
238
|
+
return field.params.enumValues.map((v) => `'${v}'`).join(" | ");
|
|
239
|
+
}
|
|
240
|
+
return "string";
|
|
241
|
+
}
|
|
242
|
+
case "object":
|
|
243
|
+
return "Record<string, unknown>";
|
|
244
|
+
default:
|
|
245
|
+
return "string";
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
var buildSchemaMap = (schema) => {
|
|
249
|
+
const map = /* @__PURE__ */ new Map();
|
|
250
|
+
for (const field of schema) {
|
|
251
|
+
map.set(field.name, field);
|
|
252
|
+
}
|
|
253
|
+
return map;
|
|
254
|
+
};
|
|
255
|
+
var generateMappedTypeBlock = (group, indent, schemaMap = /* @__PURE__ */ new Map()) => {
|
|
175
256
|
const lines = [];
|
|
176
257
|
const { versions, variables } = group;
|
|
177
258
|
if (versions.length === 1) {
|
|
@@ -181,7 +262,9 @@ var generateMappedTypeBlock = (group, indent) => {
|
|
|
181
262
|
} else {
|
|
182
263
|
lines.push(`${indent}[V in ${vKey}]: {`);
|
|
183
264
|
for (const v of variables) {
|
|
184
|
-
lines.push(
|
|
265
|
+
lines.push(
|
|
266
|
+
`${indent} ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
|
|
267
|
+
);
|
|
185
268
|
}
|
|
186
269
|
lines.push(`${indent}};`);
|
|
187
270
|
}
|
|
@@ -202,14 +285,16 @@ var generateMappedTypeBlock = (group, indent) => {
|
|
|
202
285
|
}
|
|
203
286
|
if (variables.length > 0) {
|
|
204
287
|
for (const v of variables) {
|
|
205
|
-
lines.push(
|
|
288
|
+
lines.push(
|
|
289
|
+
`${indent} ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
|
|
290
|
+
);
|
|
206
291
|
}
|
|
207
292
|
lines.push(`${indent}};`);
|
|
208
293
|
}
|
|
209
294
|
}
|
|
210
295
|
return lines;
|
|
211
296
|
};
|
|
212
|
-
var generateTypeDeclaration = (prompts) => {
|
|
297
|
+
var generateTypeDeclaration = (prompts, composers = []) => {
|
|
213
298
|
const lines = [
|
|
214
299
|
"// Auto-generated by @promptlycms/prompts \u2014 do not edit",
|
|
215
300
|
"import '@promptlycms/prompts';",
|
|
@@ -219,11 +304,12 @@ var generateTypeDeclaration = (prompts) => {
|
|
|
219
304
|
];
|
|
220
305
|
for (const prompt of prompts) {
|
|
221
306
|
const groups = groupAndSortVersions(prompt);
|
|
307
|
+
const schemaMap = buildSchemaMap(prompt.config.schema);
|
|
222
308
|
if (groups.length === 1) {
|
|
223
309
|
const group = groups[0];
|
|
224
310
|
if (group) {
|
|
225
311
|
lines.push(` '${prompt.promptId}': {`);
|
|
226
|
-
lines.push(...generateMappedTypeBlock(group, " "));
|
|
312
|
+
lines.push(...generateMappedTypeBlock(group, " ", schemaMap));
|
|
227
313
|
lines.push(" };");
|
|
228
314
|
}
|
|
229
315
|
} else {
|
|
@@ -237,33 +323,102 @@ var generateTypeDeclaration = (prompts) => {
|
|
|
237
323
|
} else {
|
|
238
324
|
lines.push(" } & {");
|
|
239
325
|
}
|
|
240
|
-
lines.push(...generateMappedTypeBlock(group, " "));
|
|
326
|
+
lines.push(...generateMappedTypeBlock(group, " ", schemaMap));
|
|
241
327
|
}
|
|
242
328
|
lines.push(" };");
|
|
243
329
|
}
|
|
244
330
|
}
|
|
245
331
|
lines.push(" }");
|
|
332
|
+
if (composers.length > 0) {
|
|
333
|
+
lines.push(" interface ComposerVariableMap {");
|
|
334
|
+
for (const composer of composers) {
|
|
335
|
+
const variables = extractComposerVariables(composer);
|
|
336
|
+
const schemaMap = buildSchemaMap(composer.config.schema);
|
|
337
|
+
const versions = ["'latest'"];
|
|
338
|
+
if (composer.publishedVersions) {
|
|
339
|
+
for (const pv of composer.publishedVersions) {
|
|
340
|
+
versions.push(`'${pv.version}'`);
|
|
341
|
+
}
|
|
342
|
+
} else {
|
|
343
|
+
versions.push(`'${composer.version}'`);
|
|
344
|
+
}
|
|
345
|
+
lines.push(` '${composer.composerId}': {`);
|
|
346
|
+
if (versions.length === 1) {
|
|
347
|
+
if (variables.length === 0) {
|
|
348
|
+
lines.push(` [V in ${versions[0]}]: Record<string, never>;`);
|
|
349
|
+
} else {
|
|
350
|
+
lines.push(` [V in ${versions[0]}]: {`);
|
|
351
|
+
for (const v of variables) {
|
|
352
|
+
lines.push(
|
|
353
|
+
` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
lines.push(" };");
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
const versionUnion = versions.join(" | ");
|
|
360
|
+
if (variables.length === 0) {
|
|
361
|
+
lines.push(` [V in ${versionUnion}]: Record<string, never>;`);
|
|
362
|
+
} else {
|
|
363
|
+
lines.push(` [V in ${versionUnion}]: {`);
|
|
364
|
+
for (const v of variables) {
|
|
365
|
+
lines.push(
|
|
366
|
+
` ${v}: ${schemaFieldToTsType(schemaMap.get(v))};`
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
lines.push(" };");
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
lines.push(" };");
|
|
373
|
+
}
|
|
374
|
+
lines.push(" }");
|
|
375
|
+
lines.push(" interface ComposerPromptMap {");
|
|
376
|
+
for (const composer of composers) {
|
|
377
|
+
const names = extractComposerPromptNames(composer);
|
|
378
|
+
if (names.length === 0) {
|
|
379
|
+
lines.push(` '${composer.composerId}': never;`);
|
|
380
|
+
} else {
|
|
381
|
+
const union = names.map((n) => `'${n}'`).join(" | ");
|
|
382
|
+
lines.push(` '${composer.composerId}': ${union};`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
lines.push(" }");
|
|
386
|
+
}
|
|
246
387
|
lines.push("}");
|
|
247
388
|
lines.push("");
|
|
248
389
|
return lines.join("\n");
|
|
249
390
|
};
|
|
250
|
-
var warnMissingProviders = (prompts) => {
|
|
391
|
+
var warnMissingProviders = (prompts, composers = []) => {
|
|
251
392
|
const require2 = createRequire(import.meta.url);
|
|
252
393
|
const needed = /* @__PURE__ */ new Map();
|
|
253
|
-
|
|
254
|
-
const provider = detectProviderName(
|
|
394
|
+
const trackModel = (modelId, label) => {
|
|
395
|
+
const provider = detectProviderName(modelId);
|
|
255
396
|
if (!provider) {
|
|
256
|
-
|
|
397
|
+
return;
|
|
257
398
|
}
|
|
258
399
|
const pkg = PROVIDER_PACKAGES[provider];
|
|
259
400
|
if (!pkg) {
|
|
260
|
-
|
|
401
|
+
return;
|
|
261
402
|
}
|
|
262
403
|
const existing = needed.get(pkg);
|
|
263
404
|
if (existing) {
|
|
264
|
-
existing.push(
|
|
405
|
+
existing.push(label);
|
|
265
406
|
} else {
|
|
266
|
-
needed.set(pkg, [
|
|
407
|
+
needed.set(pkg, [label]);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
for (const prompt of prompts) {
|
|
411
|
+
trackModel(prompt.config.model, prompt.promptName);
|
|
412
|
+
}
|
|
413
|
+
for (const composer of composers) {
|
|
414
|
+
for (const segment of composer.segments) {
|
|
415
|
+
if (segment.type !== "prompt") {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const modelId = segment.config.model;
|
|
419
|
+
if (modelId) {
|
|
420
|
+
trackModel(modelId, `${composer.composerName}/${segment.promptName}`);
|
|
421
|
+
}
|
|
267
422
|
}
|
|
268
423
|
}
|
|
269
424
|
for (const [pkg, promptNames] of needed) {
|
|
@@ -278,14 +433,22 @@ var warnMissingProviders = (prompts) => {
|
|
|
278
433
|
}
|
|
279
434
|
};
|
|
280
435
|
var generate = async (apiKey, outputPath, baseUrl) => {
|
|
281
|
-
const prompts = await
|
|
282
|
-
|
|
283
|
-
|
|
436
|
+
const [prompts, composers] = await Promise.all([
|
|
437
|
+
fetchAllPrompts(apiKey, baseUrl),
|
|
438
|
+
fetchAllComposers(apiKey, baseUrl).catch(() => [])
|
|
439
|
+
]);
|
|
440
|
+
if (prompts.length === 0 && composers.length === 0) {
|
|
441
|
+
console.log(" No prompts or composers found for this API key.");
|
|
284
442
|
return;
|
|
285
443
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
444
|
+
if (prompts.length > 0) {
|
|
445
|
+
console.log(` Found ${prompts.length} prompt(s)`);
|
|
446
|
+
}
|
|
447
|
+
if (composers.length > 0) {
|
|
448
|
+
console.log(` Found ${composers.length} composer(s)`);
|
|
449
|
+
}
|
|
450
|
+
warnMissingProviders(prompts, composers);
|
|
451
|
+
const content = generateTypeDeclaration(prompts, composers);
|
|
289
452
|
await writeFile(outputPath, content, "utf-8");
|
|
290
453
|
console.log(` Generated ${outputPath}`);
|
|
291
454
|
};
|
|
@@ -355,7 +518,7 @@ var formatPromptlyError = (error) => {
|
|
|
355
518
|
var generateCommand = defineCommand({
|
|
356
519
|
meta: {
|
|
357
520
|
name: "generate",
|
|
358
|
-
description: "Generate typed TypeScript declarations from Promptly CMS prompts"
|
|
521
|
+
description: "Generate typed TypeScript declarations from Promptly CMS prompts and composers"
|
|
359
522
|
},
|
|
360
523
|
args: {
|
|
361
524
|
output: {
|
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,9 @@ __export(src_exports, {
|
|
|
33
33
|
PromptlyError: () => PromptlyError,
|
|
34
34
|
createPromptlyClient: () => createPromptlyClient,
|
|
35
35
|
getSdkModelId: () => getSdkModelId,
|
|
36
|
-
interpolate: () => interpolate
|
|
36
|
+
interpolate: () => interpolate,
|
|
37
|
+
interpolateStaticSegment: () => interpolateStaticSegment,
|
|
38
|
+
toCamelCase: () => toCamelCase
|
|
37
39
|
});
|
|
38
40
|
module.exports = __toCommonJS(src_exports);
|
|
39
41
|
|
|
@@ -145,7 +147,7 @@ var resolveModel = async (modelId) => {
|
|
|
145
147
|
var interpolate = (template, variables) => {
|
|
146
148
|
let result = template;
|
|
147
149
|
for (const [key, value] of Object.entries(variables)) {
|
|
148
|
-
result = result.replaceAll(`\${${key}}`, value);
|
|
150
|
+
result = result.replaceAll(`\${${key}}`, String(value));
|
|
149
151
|
}
|
|
150
152
|
return result;
|
|
151
153
|
};
|
|
@@ -180,6 +182,26 @@ var createModelResolver = (config) => {
|
|
|
180
182
|
);
|
|
181
183
|
};
|
|
182
184
|
};
|
|
185
|
+
var toCamelCase = (name) => name.replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.toUpperCase()).replace(/^[A-Z]/, (char) => char.toLowerCase());
|
|
186
|
+
var VARIABLE_REF_REGEX = /<span[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*\sdata-field-path="([^"]+)"[^>]*><\/span>/g;
|
|
187
|
+
var VARIABLE_REF_ALT_REGEX = /<span[^>]*\sdata-field-path="([^"]+)"[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*><\/span>/g;
|
|
188
|
+
var MUSTACHE_REGEX = /\{\{(\w[\w.]*)\}\}/g;
|
|
189
|
+
var interpolateStaticSegment = (content, input) => {
|
|
190
|
+
let result = content;
|
|
191
|
+
result = result.replace(
|
|
192
|
+
VARIABLE_REF_REGEX,
|
|
193
|
+
(_, fieldPath) => fieldPath in input ? String(input[fieldPath]) : ""
|
|
194
|
+
);
|
|
195
|
+
result = result.replace(
|
|
196
|
+
VARIABLE_REF_ALT_REGEX,
|
|
197
|
+
(_, fieldPath) => fieldPath in input ? String(input[fieldPath]) : ""
|
|
198
|
+
);
|
|
199
|
+
result = result.replace(
|
|
200
|
+
MUSTACHE_REGEX,
|
|
201
|
+
(_, fieldPath) => fieldPath in input ? String(input[fieldPath]) : ""
|
|
202
|
+
);
|
|
203
|
+
return result;
|
|
204
|
+
};
|
|
183
205
|
var createPromptlyClient = (config) => {
|
|
184
206
|
const apiKey = config?.apiKey ?? process.env.PROMPTLY_API_KEY;
|
|
185
207
|
if (!apiKey) {
|
|
@@ -224,12 +246,119 @@ var createPromptlyClient = (config) => {
|
|
|
224
246
|
);
|
|
225
247
|
return results;
|
|
226
248
|
};
|
|
227
|
-
|
|
249
|
+
const fetchComposer = async (composerId, options) => {
|
|
250
|
+
const url = new URL(`/composers/${composerId}`, baseUrl);
|
|
251
|
+
if (options?.version) {
|
|
252
|
+
url.searchParams.set("version", options.version);
|
|
253
|
+
}
|
|
254
|
+
const response = await fetch(url.toString(), {
|
|
255
|
+
headers: {
|
|
256
|
+
Authorization: `Bearer ${apiKey}`
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
throw await createErrorFromResponse(response);
|
|
261
|
+
}
|
|
262
|
+
return response.json();
|
|
263
|
+
};
|
|
264
|
+
const getComposer = async (composerId, options) => {
|
|
265
|
+
const response = await fetchComposer(composerId, options);
|
|
266
|
+
const input = options?.input ?? {};
|
|
267
|
+
const promptsByName = /* @__PURE__ */ new Map();
|
|
268
|
+
const promptsOrdered = [];
|
|
269
|
+
const processedSegments = [];
|
|
270
|
+
for (const segment of response.segments) {
|
|
271
|
+
if (segment.type === "static") {
|
|
272
|
+
processedSegments.push({
|
|
273
|
+
type: "static",
|
|
274
|
+
content: interpolateStaticSegment(segment.content, input)
|
|
275
|
+
});
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const camelName = toCamelCase(segment.promptName);
|
|
279
|
+
if (!promptsByName.has(camelName)) {
|
|
280
|
+
const segmentConfig = segment.config;
|
|
281
|
+
const model = await modelResolver(segmentConfig.model ?? "");
|
|
282
|
+
const userMessage = segment.userMessage ? interpolate(segment.userMessage, input) : "";
|
|
283
|
+
const temperature = segmentConfig.temperature ?? 0.7;
|
|
284
|
+
const composerPrompt = {
|
|
285
|
+
model,
|
|
286
|
+
system: segment.systemMessage ?? void 0,
|
|
287
|
+
prompt: userMessage,
|
|
288
|
+
temperature,
|
|
289
|
+
promptId: segment.promptId,
|
|
290
|
+
promptName: segment.promptName
|
|
291
|
+
};
|
|
292
|
+
promptsByName.set(camelName, composerPrompt);
|
|
293
|
+
promptsOrdered.push(composerPrompt);
|
|
294
|
+
}
|
|
295
|
+
processedSegments.push({ type: "prompt", camelName });
|
|
296
|
+
}
|
|
297
|
+
const formatComposer = (results) => {
|
|
298
|
+
const parts = [];
|
|
299
|
+
for (const seg of processedSegments) {
|
|
300
|
+
if (seg.type === "static") {
|
|
301
|
+
parts.push(seg.content);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
const val = results[seg.camelName];
|
|
305
|
+
if (val === void 0) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
parts.push(typeof val === "string" ? val : val.text);
|
|
309
|
+
}
|
|
310
|
+
return parts.join("");
|
|
311
|
+
};
|
|
312
|
+
const compose = async (generate) => {
|
|
313
|
+
const entries = [...promptsByName.entries()];
|
|
314
|
+
const results = await Promise.all(
|
|
315
|
+
entries.map(([, prompt]) => generate(prompt))
|
|
316
|
+
);
|
|
317
|
+
const resultMap = {};
|
|
318
|
+
entries.forEach(([name], i) => {
|
|
319
|
+
resultMap[name] = results[i] ?? "";
|
|
320
|
+
});
|
|
321
|
+
return formatComposer(resultMap);
|
|
322
|
+
};
|
|
323
|
+
const result = {
|
|
324
|
+
composerId: response.composerId,
|
|
325
|
+
composerName: response.composerName,
|
|
326
|
+
version: response.version,
|
|
327
|
+
config: response.config,
|
|
328
|
+
segments: response.segments,
|
|
329
|
+
prompts: promptsOrdered,
|
|
330
|
+
formatComposer,
|
|
331
|
+
compose
|
|
332
|
+
};
|
|
333
|
+
for (const [name, prompt] of promptsByName) {
|
|
334
|
+
result[name] = prompt;
|
|
335
|
+
}
|
|
336
|
+
return result;
|
|
337
|
+
};
|
|
338
|
+
const getComposers = async (entries) => {
|
|
339
|
+
const results = await Promise.all(
|
|
340
|
+
entries.map(
|
|
341
|
+
(entry) => getComposer(entry.composerId, {
|
|
342
|
+
input: entry.input,
|
|
343
|
+
version: entry.version
|
|
344
|
+
})
|
|
345
|
+
)
|
|
346
|
+
);
|
|
347
|
+
return results;
|
|
348
|
+
};
|
|
349
|
+
return {
|
|
350
|
+
getPrompt,
|
|
351
|
+
getPrompts,
|
|
352
|
+
getComposer,
|
|
353
|
+
getComposers
|
|
354
|
+
};
|
|
228
355
|
};
|
|
229
356
|
// Annotate the CommonJS export names for ESM import in node:
|
|
230
357
|
0 && (module.exports = {
|
|
231
358
|
PromptlyError,
|
|
232
359
|
createPromptlyClient,
|
|
233
360
|
getSdkModelId,
|
|
234
|
-
interpolate
|
|
361
|
+
interpolate,
|
|
362
|
+
interpolateStaticSegment,
|
|
363
|
+
toCamelCase
|
|
235
364
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-
|
|
2
|
-
export { b as ErrorResponse, G as GetOptions,
|
|
1
|
+
import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DIVyjOlH.cjs';
|
|
2
|
+
export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerId, e as ComposerInputFor, f as ComposerPrompt, g as ComposerPromptMap, h as ComposerPromptNamesFor, i as ComposerPromptSegment, j as ComposerRequest, k as ComposerResponse, l as ComposerResult, m as ComposerSegment, n as ComposerStaticSegment, o as ComposerVariableMap, p as ComposerVersion, q as ErrorResponse, F as FormatInput, G as GetComposerOptions, r as GetOptions, s as PromptConfig, t as PromptId, u as PromptMessage, v as PromptRequest, w as PromptResponse, x as PromptResult, y as PromptVariableMap, z as PromptVersion, A as PublishedVersion, S as SchemaField, B as SchemaFieldParams, V as ValidationRule } from './types-DIVyjOlH.cjs';
|
|
3
3
|
import 'ai';
|
|
4
4
|
|
|
5
5
|
declare const getSdkModelId: (modelId: string) => string;
|
|
6
|
-
declare const interpolate: (template: string, variables: Record<string,
|
|
6
|
+
declare const interpolate: (template: string, variables: Record<string, unknown>) => string;
|
|
7
|
+
declare const toCamelCase: (name: string) => string;
|
|
8
|
+
declare const interpolateStaticSegment: (content: string, input: Record<string, unknown>) => string;
|
|
7
9
|
declare const createPromptlyClient: (config?: PromptlyClientConfig) => PromptlyClient;
|
|
8
10
|
|
|
9
11
|
declare class PromptlyError extends Error {
|
|
@@ -14,4 +16,4 @@ declare class PromptlyError extends Error {
|
|
|
14
16
|
constructor(message: string, code: ErrorCode, status: number, usage?: unknown, upgradeUrl?: string);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
export { ErrorCode, PromptlyClient, PromptlyClientConfig, PromptlyError, createPromptlyClient, getSdkModelId, interpolate };
|
|
19
|
+
export { ErrorCode, PromptlyClient, PromptlyClientConfig, PromptlyError, createPromptlyClient, getSdkModelId, interpolate, interpolateStaticSegment, toCamelCase };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-
|
|
2
|
-
export { b as ErrorResponse, G as GetOptions,
|
|
1
|
+
import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DIVyjOlH.js';
|
|
2
|
+
export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerId, e as ComposerInputFor, f as ComposerPrompt, g as ComposerPromptMap, h as ComposerPromptNamesFor, i as ComposerPromptSegment, j as ComposerRequest, k as ComposerResponse, l as ComposerResult, m as ComposerSegment, n as ComposerStaticSegment, o as ComposerVariableMap, p as ComposerVersion, q as ErrorResponse, F as FormatInput, G as GetComposerOptions, r as GetOptions, s as PromptConfig, t as PromptId, u as PromptMessage, v as PromptRequest, w as PromptResponse, x as PromptResult, y as PromptVariableMap, z as PromptVersion, A as PublishedVersion, S as SchemaField, B as SchemaFieldParams, V as ValidationRule } from './types-DIVyjOlH.js';
|
|
3
3
|
import 'ai';
|
|
4
4
|
|
|
5
5
|
declare const getSdkModelId: (modelId: string) => string;
|
|
6
|
-
declare const interpolate: (template: string, variables: Record<string,
|
|
6
|
+
declare const interpolate: (template: string, variables: Record<string, unknown>) => string;
|
|
7
|
+
declare const toCamelCase: (name: string) => string;
|
|
8
|
+
declare const interpolateStaticSegment: (content: string, input: Record<string, unknown>) => string;
|
|
7
9
|
declare const createPromptlyClient: (config?: PromptlyClientConfig) => PromptlyClient;
|
|
8
10
|
|
|
9
11
|
declare class PromptlyError extends Error {
|
|
@@ -14,4 +16,4 @@ declare class PromptlyError extends Error {
|
|
|
14
16
|
constructor(message: string, code: ErrorCode, status: number, usage?: unknown, upgradeUrl?: string);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
export { ErrorCode, PromptlyClient, PromptlyClientConfig, PromptlyError, createPromptlyClient, getSdkModelId, interpolate };
|
|
19
|
+
export { ErrorCode, PromptlyClient, PromptlyClientConfig, PromptlyError, createPromptlyClient, getSdkModelId, interpolate, interpolateStaticSegment, toCamelCase };
|