@to11ai/sdk 1.1.0 → 2.0.0-rc.1
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/dist/client.cjs +85 -18
- package/dist/client.d.ts +140 -39
- package/dist/client.js +91 -19
- package/dist/config.d.ts +9 -0
- package/dist/context.d.ts +124 -0
- package/dist/errors.cjs +18 -1
- package/dist/errors.d.ts +18 -1
- package/dist/errors.js +18 -1
- package/dist/gateway.cjs +62 -22
- package/dist/gateway.d.ts +57 -9
- package/dist/gateway.js +62 -22
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/types.gen.d.ts +1299 -167
- package/dist/generated/zod.gen.d.ts +393 -232
- package/dist/prompts/cache.d.ts +3 -3
- package/dist/prompts/resource.cjs +21 -16
- package/dist/prompts/resource.d.ts +59 -28
- package/dist/prompts/resource.js +21 -16
- package/dist/prompts/shape.d.ts +54 -0
- package/dist/prompts/types.d.ts +31 -13
- package/package.json +1 -1
- package/src/client.ts +326 -80
- package/src/config.ts +13 -0
- package/src/context.ts +198 -0
- package/src/errors.ts +33 -3
- package/src/gateway.ts +135 -33
- package/src/generated/index.ts +1 -1
- package/src/generated/types.gen.ts +1310 -167
- package/src/generated/zod.gen.ts +358 -268
- package/src/prompts/cache.ts +3 -6
- package/src/prompts/resource.ts +89 -41
- package/src/prompts/shape.ts +149 -0
- package/src/prompts/types.ts +35 -14
package/src/prompts/cache.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface CacheConfig {
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* The cache stores either a legacy `resolve()` result or an enriched
|
|
12
|
-
* `
|
|
12
|
+
* `render()` result. Both are JSON-cloneable; the cache is shape-agnostic.
|
|
13
13
|
*/
|
|
14
14
|
export type CacheableResolved = ResolvedPrompt | FetchedPrompt;
|
|
15
15
|
|
|
@@ -44,7 +44,7 @@ export function buildCacheKey(
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Build a cache key for an env-aware `
|
|
47
|
+
* Build a cache key for an env-aware `render()` call.
|
|
48
48
|
*
|
|
49
49
|
* Folds in `env` and `subject` ON TOP of the base
|
|
50
50
|
* project/slug/labels/variables key so two calls that differ only by
|
|
@@ -64,12 +64,9 @@ export function buildFetchCacheKey(
|
|
|
64
64
|
env: string,
|
|
65
65
|
subject?: string,
|
|
66
66
|
variables?: Record<string, unknown>,
|
|
67
|
-
developerRole?: string,
|
|
68
67
|
): string {
|
|
69
68
|
const base = buildCacheKey(projectId, slug, [env], variables);
|
|
70
|
-
|
|
71
|
-
// `"user"` (the documented default) share one entry, not two.
|
|
72
|
-
return `fetch|${base}|${JSON.stringify(env)}|${JSON.stringify(subject ?? null)}|${JSON.stringify(developerRole ?? "user")}`;
|
|
69
|
+
return `fetch|${base}|${JSON.stringify(env)}|${JSON.stringify(subject ?? null)}`;
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
function sortObjectKeys(obj: unknown): unknown {
|
package/src/prompts/resource.ts
CHANGED
|
@@ -4,6 +4,12 @@ import { zResolvedPrompt } from "../generated/zod.gen";
|
|
|
4
4
|
import type { ApiEnvelope, Transport } from "../transport";
|
|
5
5
|
import type { CacheConfig } from "./cache";
|
|
6
6
|
import { buildCacheKey, buildFetchCacheKey, PromptCache } from "./cache";
|
|
7
|
+
import type {
|
|
8
|
+
AnthropicRenderedPrompt,
|
|
9
|
+
OpenAiRenderedPrompt,
|
|
10
|
+
RenderResult,
|
|
11
|
+
} from "./shape";
|
|
12
|
+
import { shapePrompt } from "./shape";
|
|
7
13
|
import type {
|
|
8
14
|
ArchivePromptInput,
|
|
9
15
|
ArchivePromptResult,
|
|
@@ -40,10 +46,13 @@ import type {
|
|
|
40
46
|
PaginatedResult,
|
|
41
47
|
RenderedChatMessage,
|
|
42
48
|
RenderedPrompt,
|
|
49
|
+
RenderFormat,
|
|
50
|
+
RenderOptions,
|
|
43
51
|
ResolvedPrompt,
|
|
44
52
|
ResolvedPromptEnvelope,
|
|
45
53
|
ResolvePromptInput,
|
|
46
54
|
ResolvePromptResult,
|
|
55
|
+
UnknownRoleMode,
|
|
47
56
|
UpdateProjectPromptLabelInput,
|
|
48
57
|
UpdateProjectPromptLabelResult,
|
|
49
58
|
UpdatePromptInput,
|
|
@@ -120,11 +129,12 @@ const zResolvedPromptLegacy = zResolvedPrompt.pick({
|
|
|
120
129
|
promptId: true,
|
|
121
130
|
versionId: true,
|
|
122
131
|
version: true,
|
|
123
|
-
|
|
132
|
+
label: true,
|
|
124
133
|
contentHash: true,
|
|
125
134
|
rendered: true,
|
|
126
135
|
tools: true,
|
|
127
136
|
toolChoice: true,
|
|
137
|
+
modelConfig: true,
|
|
128
138
|
});
|
|
129
139
|
|
|
130
140
|
const zResolvedPromptEnvelope = zResolvedPrompt
|
|
@@ -177,8 +187,9 @@ function normalizeResolvedEnvelope(
|
|
|
177
187
|
promptId: raw.promptId,
|
|
178
188
|
versionId: raw.versionId,
|
|
179
189
|
contentHash: raw.contentHash,
|
|
180
|
-
|
|
190
|
+
label: raw.label,
|
|
181
191
|
rendered: raw.rendered,
|
|
192
|
+
modelConfig: provenance.modelConfig,
|
|
182
193
|
};
|
|
183
194
|
// `tools` is present IFF the resolved version declares tool definitions; the
|
|
184
195
|
// wire may send `null` (or omit it) — normalize both to absent so callers
|
|
@@ -209,7 +220,7 @@ function normalizeResolvedEnvelope(
|
|
|
209
220
|
|
|
210
221
|
/**
|
|
211
222
|
* Lift a caller-supplied offline `fallback` into the enriched `FetchedPrompt`
|
|
212
|
-
* shape (D7), so `
|
|
223
|
+
* shape (D7), so `render()` returns an identical shape on the online and
|
|
213
224
|
* offline paths. An already-enriched `FetchedPrompt` is returned as-is; a
|
|
214
225
|
* legacy `ResolvedPrompt` is lifted (messages synthesized; `releaseId` → its
|
|
215
226
|
* own value or explicit `null`; `blockRenderRecord` → `{}`; `variantName`
|
|
@@ -261,34 +272,48 @@ function buildLabelEventsQuery(input: ListLabelEventsInput): string {
|
|
|
261
272
|
}
|
|
262
273
|
|
|
263
274
|
/**
|
|
264
|
-
* Init-time config for the env-aware `
|
|
275
|
+
* Init-time config for the env-aware `render()` surface (TO11-980 / S9).
|
|
265
276
|
*
|
|
266
277
|
* `projectId` and `env` come from `createClient`. `projectId` is required for
|
|
267
|
-
* `
|
|
268
|
-
* serving environment inherited by every `
|
|
278
|
+
* `render()` (it builds the project-scoped resolve path); `env` is the default
|
|
279
|
+
* serving environment inherited by every `render(slug)` call.
|
|
269
280
|
*/
|
|
270
281
|
export interface PromptResourceConfig {
|
|
271
|
-
/** Project the client is bound to. Required for `
|
|
282
|
+
/** Project the client is bound to. Required for `render()`; validated at createClient. */
|
|
272
283
|
projectId?: string;
|
|
273
|
-
/** Default serving env for `
|
|
284
|
+
/** Default serving env for `render()`. Validated against ENV_SLUG_REGEX at createClient. */
|
|
274
285
|
env?: string;
|
|
286
|
+
/** Default provider shape for `render()` output. Per-call override allowed. */
|
|
287
|
+
format?: RenderFormat;
|
|
288
|
+
/**
|
|
289
|
+
* Default unknown-role policy for `render({ format })` output conversion.
|
|
290
|
+
* Per-call override allowed; defaults to `"drop"`.
|
|
291
|
+
*/
|
|
292
|
+
onUnknownRole?: UnknownRoleMode;
|
|
275
293
|
}
|
|
276
294
|
|
|
277
|
-
export class PromptResource {
|
|
295
|
+
export class PromptResource<F extends RenderFormat | undefined = undefined> {
|
|
278
296
|
private readonly transport: Transport;
|
|
279
297
|
private readonly cache: PromptCache;
|
|
280
298
|
private readonly projectId: string | undefined;
|
|
281
299
|
private readonly env: string | undefined;
|
|
300
|
+
private readonly format: RenderFormat | undefined;
|
|
301
|
+
private readonly onUnknownRole: UnknownRoleMode | undefined;
|
|
282
302
|
|
|
283
303
|
constructor(
|
|
284
304
|
transport: Transport,
|
|
285
305
|
cacheConfig?: CacheConfig,
|
|
286
|
-
|
|
306
|
+
// `format` is bound to the class generic `F` (not the wider `RenderFormat`)
|
|
307
|
+
// so the constructed default shape cannot disagree with what `render()`'s
|
|
308
|
+
// return type (`RenderResult<F>`) promises.
|
|
309
|
+
config?: Omit<PromptResourceConfig, "format"> & { format?: F },
|
|
287
310
|
) {
|
|
288
311
|
this.transport = transport;
|
|
289
312
|
this.cache = new PromptCache(cacheConfig);
|
|
290
313
|
this.projectId = config?.projectId;
|
|
291
314
|
this.env = config?.env;
|
|
315
|
+
this.format = config?.format;
|
|
316
|
+
this.onUnknownRole = config?.onUnknownRole;
|
|
292
317
|
}
|
|
293
318
|
|
|
294
319
|
// ─── Create ──────────────────────────────────────────────────────────────
|
|
@@ -436,35 +461,65 @@ export class PromptResource {
|
|
|
436
461
|
return unwrap(envelope);
|
|
437
462
|
}
|
|
438
463
|
|
|
439
|
-
// ───
|
|
464
|
+
// ─── Render (env-aware resolution + format shaping, TO11-980 / TO11-2691) ──
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Resolve and (optionally) shape a prompt for the client's configured
|
|
468
|
+
* `projectId` + `env`, in one control-plane request. With a `format` (per
|
|
469
|
+
* call or inherited from the client) the result is provider-shaped
|
|
470
|
+
* `{ messages, config, metadata }`; without one it is the neutral
|
|
471
|
+
* `FetchedPrompt`. Resolves by the client's `env`; for label-addressed
|
|
472
|
+
* resolution see {@link PromptResource.resolve | `resolve()`}.
|
|
473
|
+
*
|
|
474
|
+
* @example Render an OpenAI-shaped prompt and send it through the gateway
|
|
475
|
+
* const prompt = await to11.prompts.render("weather-concierge", {
|
|
476
|
+
* variables: { city: "NYC" },
|
|
477
|
+
* });
|
|
478
|
+
* const res = await openai.chat.completions.create(
|
|
479
|
+
* { ...prompt.config, messages: prompt.messages },
|
|
480
|
+
* { headers: to11.turn().headers(prompt) },
|
|
481
|
+
* );
|
|
482
|
+
*/
|
|
483
|
+
async render(
|
|
484
|
+
slug: string,
|
|
485
|
+
options: RenderOptions & { format: "openai" },
|
|
486
|
+
): Promise<OpenAiRenderedPrompt>;
|
|
487
|
+
async render(
|
|
488
|
+
slug: string,
|
|
489
|
+
options: RenderOptions & { format: "anthropic" },
|
|
490
|
+
): Promise<AnthropicRenderedPrompt>;
|
|
491
|
+
async render(slug: string, options?: RenderOptions): Promise<RenderResult<F>>;
|
|
492
|
+
async render(
|
|
493
|
+
slug: string,
|
|
494
|
+
options: RenderOptions = {},
|
|
495
|
+
): Promise<FetchedPrompt | OpenAiRenderedPrompt | AnthropicRenderedPrompt> {
|
|
496
|
+
const fetched = await this.resolveToFetched(slug, options);
|
|
497
|
+
return shapePrompt(fetched, options.format ?? this.format, {
|
|
498
|
+
onUnknownRole: options.onUnknownRole ?? this.onUnknownRole,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
440
501
|
|
|
441
502
|
/**
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
* `createClient` and inherited here, with an optional per-call override.
|
|
503
|
+
* Env-aware resolution → neutral `FetchedPrompt`. Carries the resolve /
|
|
504
|
+
* cache / offline-fallback logic; `render()` is the public shaping surface.
|
|
445
505
|
*
|
|
446
|
-
* - **env→label wire mapping
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* env slug (lowercase-kebab — a valid label name) is therefore sent as
|
|
450
|
-
* the single resolution label: body `{ slug, labels: [env], subject?,
|
|
451
|
-
* variables? }`.
|
|
506
|
+
* - **env→label wire mapping:** the resolve route is label-based
|
|
507
|
+
* (`/v1/projects/:projectId/prompts:resolve`, body `labels[]`); the
|
|
508
|
+
* resolved env slug is sent as the single resolution label.
|
|
452
509
|
* - **No silent fallback (R4):** if no env is resolvable (none at init AND
|
|
453
|
-
* none per call) this throws `EnvNotFoundError`
|
|
454
|
-
*
|
|
510
|
+
* none per call) this throws `EnvNotFoundError` CLIENT-side, eagerly,
|
|
511
|
+
* before any transport call.
|
|
455
512
|
* - **Cache (D8):** caches `single`-strategy releases and weighted releases
|
|
456
513
|
* WITH a `subject`; BYPASSES the cache for weighted releases with NO
|
|
457
514
|
* `subject` (a uniform-random assignment must not be pinned for the TTL).
|
|
458
|
-
*
|
|
459
|
-
* Prefer this over the deprecated `resolve()`.
|
|
460
515
|
*/
|
|
461
|
-
async
|
|
516
|
+
private async resolveToFetched(
|
|
462
517
|
slug: string,
|
|
463
518
|
options: FetchPromptOptions = {},
|
|
464
519
|
): Promise<FetchedPrompt> {
|
|
465
520
|
if (this.projectId === undefined || this.projectId.trim() === "") {
|
|
466
521
|
throw new Error(
|
|
467
|
-
"[to11ai/sdk] `prompts.
|
|
522
|
+
"[to11ai/sdk] `prompts.render()` requires a `projectId` on the client — pass it to createClient({ projectId, ... }).",
|
|
468
523
|
);
|
|
469
524
|
}
|
|
470
525
|
|
|
@@ -486,13 +541,7 @@ export class PromptResource {
|
|
|
486
541
|
);
|
|
487
542
|
}
|
|
488
543
|
|
|
489
|
-
const {
|
|
490
|
-
subject,
|
|
491
|
-
variables,
|
|
492
|
-
cache: useCache = true,
|
|
493
|
-
fallback,
|
|
494
|
-
developerRole,
|
|
495
|
-
} = options;
|
|
544
|
+
const { subject, variables, cache: useCache = true, fallback } = options;
|
|
496
545
|
|
|
497
546
|
const cacheKey = buildFetchCacheKey(
|
|
498
547
|
this.projectId,
|
|
@@ -500,7 +549,6 @@ export class PromptResource {
|
|
|
500
549
|
env,
|
|
501
550
|
subject,
|
|
502
551
|
variables,
|
|
503
|
-
developerRole,
|
|
504
552
|
);
|
|
505
553
|
|
|
506
554
|
if (useCache) {
|
|
@@ -514,7 +562,6 @@ export class PromptResource {
|
|
|
514
562
|
const body: Record<string, unknown> = { slug, labels: [env] };
|
|
515
563
|
if (subject !== undefined) body.subject = subject;
|
|
516
564
|
if (variables !== undefined) body.variables = variables;
|
|
517
|
-
if (developerRole !== undefined) body.developerRole = developerRole;
|
|
518
565
|
|
|
519
566
|
try {
|
|
520
567
|
const envelope = await this.transport.request<ResolvedPromptEnvelope>(
|
|
@@ -561,12 +608,13 @@ export class PromptResource {
|
|
|
561
608
|
// ─── Resolve ──────────────────────────────────────────────────────────────
|
|
562
609
|
|
|
563
610
|
/**
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
611
|
+
* Resolve a prompt by explicit `labels` for a given `projectId`, in one
|
|
612
|
+
* control-plane request. This is the label-addressed counterpart to
|
|
613
|
+
* {@link PromptResource.render | `render()`}, which resolves by the client's
|
|
614
|
+
* configured `env`. Reach for `resolve()` when you address prompts by label
|
|
615
|
+
* rather than by environment; it is env-agnostic, so it carries no `env` /
|
|
616
|
+
* `subject`, no enriched release/variant provenance, and no typed-env errors,
|
|
617
|
+
* and is not subject to the env-based no-silent-fallback gate.
|
|
570
618
|
*/
|
|
571
619
|
async resolve(input: ResolvePromptInput): Promise<ResolvePromptResult> {
|
|
572
620
|
const {
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-at-load shaping: turn a neutral `FetchedPrompt` into a provider-shaped
|
|
3
|
+
* `{ messages, config, metadata }` result the caller spreads into their own
|
|
4
|
+
* provider `create()` call. Header-only — this only reshapes data, it never
|
|
5
|
+
* sends a request. See docs/product-specs/2026-07-14-to11-2691-sdk-simpler-setup.md.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type AnthropicMessage,
|
|
10
|
+
type AnthropicTool,
|
|
11
|
+
type AnthropicToolChoice,
|
|
12
|
+
type ConvertMessagesOptions,
|
|
13
|
+
type OpenAIChatMessage,
|
|
14
|
+
type OpenAITool,
|
|
15
|
+
type OpenAIToolChoice,
|
|
16
|
+
toAnthropicMessages,
|
|
17
|
+
toAnthropicSystem,
|
|
18
|
+
toAnthropicToolChoice,
|
|
19
|
+
toAnthropicTools,
|
|
20
|
+
toOpenAIMessages,
|
|
21
|
+
toOpenAIToolChoice,
|
|
22
|
+
toOpenAITools,
|
|
23
|
+
} from "../gateway";
|
|
24
|
+
import type { FetchedPrompt, RenderFormat } from "./types";
|
|
25
|
+
|
|
26
|
+
/** Model params passed through verbatim from the resolved version's modelConfig. */
|
|
27
|
+
export interface PromptConfig {
|
|
28
|
+
model?: string;
|
|
29
|
+
temperature?: number;
|
|
30
|
+
// Snake_case to match the stored modelConfig and the provider wire key
|
|
31
|
+
// (spread verbatim into e.g. OpenAI's `create()`), per TO11-2691.
|
|
32
|
+
max_tokens?: number;
|
|
33
|
+
/** Any additional stored model-config keys are passed through unchanged. */
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Prompt provenance for `turn.headers()` — kept apart from the request body. */
|
|
38
|
+
export interface PromptMetadata {
|
|
39
|
+
promptId: string;
|
|
40
|
+
versionId: string;
|
|
41
|
+
version: number;
|
|
42
|
+
releaseId: string | null;
|
|
43
|
+
/** The single label the prompt resolved through (env slug today). */
|
|
44
|
+
label: string;
|
|
45
|
+
variantName?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** OpenAI-shaped render result: spread `{ ...config, messages }` into create(). */
|
|
49
|
+
export interface OpenAiRenderedPrompt {
|
|
50
|
+
messages: OpenAIChatMessage[];
|
|
51
|
+
config: PromptConfig;
|
|
52
|
+
metadata: PromptMetadata;
|
|
53
|
+
/** Authored tools, provider-shaped. Present only when the prompt declares tools. */
|
|
54
|
+
tools?: OpenAITool[];
|
|
55
|
+
/** Authored tool-choice directive. Present only when the prompt sets one. */
|
|
56
|
+
tool_choice?: OpenAIToolChoice;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Anthropic-shaped render result: system/developer folded into `system`. */
|
|
60
|
+
export interface AnthropicRenderedPrompt {
|
|
61
|
+
/** Folded system/developer instruction text (Anthropic's top-level `system`). */
|
|
62
|
+
system?: string;
|
|
63
|
+
messages: AnthropicMessage[];
|
|
64
|
+
config: PromptConfig;
|
|
65
|
+
metadata: PromptMetadata;
|
|
66
|
+
/** Authored tools, provider-shaped. Present only when the prompt declares tools. */
|
|
67
|
+
tools?: AnthropicTool[];
|
|
68
|
+
/** Authored tool-choice directive. Present only when the prompt sets one. */
|
|
69
|
+
tool_choice?: AnthropicToolChoice;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** The render return type for a given client/call format. */
|
|
73
|
+
export type RenderResult<F extends RenderFormat | undefined> =
|
|
74
|
+
F extends "openai"
|
|
75
|
+
? OpenAiRenderedPrompt
|
|
76
|
+
: F extends "anthropic"
|
|
77
|
+
? AnthropicRenderedPrompt
|
|
78
|
+
: FetchedPrompt;
|
|
79
|
+
|
|
80
|
+
function toPromptConfig(modelConfig: unknown): PromptConfig {
|
|
81
|
+
return modelConfig !== null && typeof modelConfig === "object"
|
|
82
|
+
? { ...(modelConfig as Record<string, unknown>) }
|
|
83
|
+
: {};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function toMetadata(prompt: FetchedPrompt): PromptMetadata {
|
|
87
|
+
const metadata: PromptMetadata = {
|
|
88
|
+
promptId: prompt.promptId,
|
|
89
|
+
versionId: prompt.versionId,
|
|
90
|
+
version: prompt.version,
|
|
91
|
+
releaseId: prompt.releaseId,
|
|
92
|
+
label: prompt.label,
|
|
93
|
+
};
|
|
94
|
+
if (prompt.variantName !== undefined)
|
|
95
|
+
metadata.variantName = prompt.variantName;
|
|
96
|
+
return metadata;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function shapeOpenAI(
|
|
100
|
+
prompt: FetchedPrompt,
|
|
101
|
+
options: ConvertMessagesOptions = {},
|
|
102
|
+
): OpenAiRenderedPrompt {
|
|
103
|
+
const result: OpenAiRenderedPrompt = {
|
|
104
|
+
messages: toOpenAIMessages(prompt.messages, options),
|
|
105
|
+
config: toPromptConfig(prompt.modelConfig),
|
|
106
|
+
metadata: toMetadata(prompt),
|
|
107
|
+
};
|
|
108
|
+
// Carry authored tools so the spread-ready result is complete for
|
|
109
|
+
// tool-using prompts. Omit when empty/absent so we never send `tools: []`.
|
|
110
|
+
const tools = toOpenAITools(prompt.tools);
|
|
111
|
+
if (tools.length > 0) result.tools = tools;
|
|
112
|
+
const toolChoice = toOpenAIToolChoice(prompt.toolChoice);
|
|
113
|
+
if (toolChoice !== undefined) result.tool_choice = toolChoice;
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function shapeAnthropic(
|
|
118
|
+
prompt: FetchedPrompt,
|
|
119
|
+
options: ConvertMessagesOptions = {},
|
|
120
|
+
): AnthropicRenderedPrompt {
|
|
121
|
+
const result: AnthropicRenderedPrompt = {
|
|
122
|
+
messages: toAnthropicMessages(prompt.messages, options),
|
|
123
|
+
config: toPromptConfig(prompt.modelConfig),
|
|
124
|
+
metadata: toMetadata(prompt),
|
|
125
|
+
};
|
|
126
|
+
const system = toAnthropicSystem(prompt.messages);
|
|
127
|
+
if (system !== undefined) result.system = system;
|
|
128
|
+
const tools = toAnthropicTools(prompt.tools);
|
|
129
|
+
if (tools.length > 0) result.tools = tools;
|
|
130
|
+
const toolChoice = toAnthropicToolChoice(prompt.toolChoice);
|
|
131
|
+
if (toolChoice !== undefined) result.tool_choice = toolChoice;
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Shape a fetched prompt for `format`, or return it neutral when unset. */
|
|
136
|
+
export function shapePrompt(
|
|
137
|
+
prompt: FetchedPrompt,
|
|
138
|
+
format: RenderFormat | undefined,
|
|
139
|
+
options: ConvertMessagesOptions = {},
|
|
140
|
+
): FetchedPrompt | OpenAiRenderedPrompt | AnthropicRenderedPrompt {
|
|
141
|
+
switch (format) {
|
|
142
|
+
case "openai":
|
|
143
|
+
return shapeOpenAI(prompt, options);
|
|
144
|
+
case "anthropic":
|
|
145
|
+
return shapeAnthropic(prompt, options);
|
|
146
|
+
default:
|
|
147
|
+
return prompt;
|
|
148
|
+
}
|
|
149
|
+
}
|
package/src/prompts/types.ts
CHANGED
|
@@ -38,6 +38,18 @@ export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
|
|
|
38
38
|
|
|
39
39
|
export type RenderedPrompt = GenRenderedPrompt;
|
|
40
40
|
|
|
41
|
+
/** Provider shape for `prompts.render()` output. Omit for the neutral result. */
|
|
42
|
+
export type RenderFormat = "openai" | "anthropic";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Policy for a message whose role is outside the known set
|
|
46
|
+
* (`system | user | assistant | developer | tool`) when converting to a
|
|
47
|
+
* provider shape. `"drop"` (default) omits it silently; `"warn"` omits it and
|
|
48
|
+
* emits a `console.warn`; `"error"` throws `UnknownRoleError`. Applies to the
|
|
49
|
+
* standalone converters and to `render({ format })`.
|
|
50
|
+
*/
|
|
51
|
+
export type UnknownRoleMode = "drop" | "warn" | "error";
|
|
52
|
+
|
|
41
53
|
/**
|
|
42
54
|
* A provider-neutral tool definition (`{ name, description?, parameters }`),
|
|
43
55
|
* sourced from authored tool-definition blocks. Surfaced on the resolved
|
|
@@ -56,11 +68,12 @@ export type ResolvedPrompt = Pick<
|
|
|
56
68
|
| "promptId"
|
|
57
69
|
| "versionId"
|
|
58
70
|
| "version"
|
|
59
|
-
| "
|
|
71
|
+
| "label"
|
|
60
72
|
| "contentHash"
|
|
61
73
|
| "rendered"
|
|
62
74
|
| "tools"
|
|
63
75
|
| "toolChoice"
|
|
76
|
+
| "modelConfig"
|
|
64
77
|
>;
|
|
65
78
|
|
|
66
79
|
export interface PaginationInfo {
|
|
@@ -190,8 +203,19 @@ export interface FetchedPrompt {
|
|
|
190
203
|
promptId: string;
|
|
191
204
|
versionId: string;
|
|
192
205
|
contentHash: string;
|
|
193
|
-
|
|
206
|
+
/**
|
|
207
|
+
* The single label the prompt resolved through — the env slug today, a real
|
|
208
|
+
* label once labels ship. Surfaced as `x-to11-prompt-label` by
|
|
209
|
+
* `gatewayPromptHeaders` / `turn.headers()` (TO11-2725).
|
|
210
|
+
*/
|
|
211
|
+
label: string;
|
|
194
212
|
rendered: RenderedPrompt;
|
|
213
|
+
/**
|
|
214
|
+
* The served version's model config (model, temperature, max_tokens, …),
|
|
215
|
+
* passed through verbatim. Surfaced as `config` by `render({ format })`.
|
|
216
|
+
* Optional: absent when a pre-`modelConfig` API omits it.
|
|
217
|
+
*/
|
|
218
|
+
modelConfig?: unknown;
|
|
195
219
|
/**
|
|
196
220
|
* Provider-neutral tool definitions lifted from authored tool-definition
|
|
197
221
|
* blocks. Absent (rather than `[]`) when the resolved version declares no
|
|
@@ -215,26 +239,23 @@ export type ResolvedPromptEnvelope = GenResolvedPrompt & {
|
|
|
215
239
|
strategy?: "single" | "weighted";
|
|
216
240
|
};
|
|
217
241
|
|
|
218
|
-
/**
|
|
219
|
-
* How an authored `developer` block is rendered. The caller controls this
|
|
220
|
-
* per-call because it knows the upstream it targets. Omitted ⇒ `"user"`
|
|
221
|
-
* (back-compatible; safe for any upstream). `"developer"` preserves the role
|
|
222
|
-
* (OpenAI); `"system"` folds it into a system message.
|
|
223
|
-
*/
|
|
224
|
-
export type DeveloperRole = "user" | "developer" | "system";
|
|
225
|
-
|
|
226
242
|
export interface FetchPromptOptions {
|
|
227
243
|
env?: string;
|
|
228
244
|
subject?: string;
|
|
229
245
|
variables?: Record<string, unknown>;
|
|
230
246
|
cache?: boolean;
|
|
231
247
|
fallback?: ResolvedPrompt | FetchedPrompt;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface RenderOptions extends FetchPromptOptions {
|
|
251
|
+
/** Provider shape for this call's output; overrides the client default. */
|
|
252
|
+
format?: RenderFormat;
|
|
232
253
|
/**
|
|
233
|
-
* How
|
|
234
|
-
*
|
|
235
|
-
*
|
|
254
|
+
* How to handle a message with an unrecognized role while shaping for a
|
|
255
|
+
* provider (`format` set). Overrides the client default; defaults to `"drop"`.
|
|
256
|
+
* Only meaningful with a `format` — the neutral result runs no converter.
|
|
236
257
|
*/
|
|
237
|
-
|
|
258
|
+
onUnknownRole?: UnknownRoleMode;
|
|
238
259
|
}
|
|
239
260
|
|
|
240
261
|
export type PaletteToken = ProjectPromptLabel["displayColor"];
|