@to11ai/sdk 2.0.0-rc.1 → 2.0.0-rc.3
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 +5 -1
- package/dist/client.d.ts +10 -3
- package/dist/client.js +5 -1
- package/dist/context.d.ts +1 -1
- package/dist/gateway.cjs +3 -0
- package/dist/gateway.d.ts +8 -0
- package/dist/gateway.js +3 -0
- package/dist/prompts/cache.d.ts +8 -9
- package/dist/prompts/resource.cjs +57 -78
- package/dist/prompts/resource.d.ts +14 -18
- package/dist/prompts/resource.js +58 -79
- package/dist/prompts/shape.d.ts +8 -6
- package/dist/prompts/types.d.ts +34 -39
- package/package.json +1 -1
- package/src/client.ts +21 -5
- package/src/context.ts +1 -1
- package/src/gateway.ts +13 -0
- package/src/generated/zod.gen.ts +3 -3
- package/src/prompts/cache.ts +10 -11
- package/src/prompts/resource.ts +111 -137
- package/src/prompts/shape.ts +11 -8
- package/src/prompts/types.ts +33 -43
package/dist/prompts/resource.js
CHANGED
|
@@ -2,20 +2,9 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { EnvNotFoundError, To11aiNetworkError } from "../errors";
|
|
4
4
|
import { zResolvedPrompt } from "../generated/zod.gen";
|
|
5
|
-
import {
|
|
5
|
+
import { buildRenderCacheKey, PromptCache } from "./cache";
|
|
6
6
|
import { shapePrompt } from "./shape";
|
|
7
7
|
import { ENV_SLUG_REGEX } from "./types";
|
|
8
|
-
var zResolvedPromptLegacy = zResolvedPrompt.pick({
|
|
9
|
-
promptId: true,
|
|
10
|
-
versionId: true,
|
|
11
|
-
version: true,
|
|
12
|
-
label: true,
|
|
13
|
-
contentHash: true,
|
|
14
|
-
rendered: true,
|
|
15
|
-
tools: true,
|
|
16
|
-
toolChoice: true,
|
|
17
|
-
modelConfig: true
|
|
18
|
-
});
|
|
19
8
|
var zResolvedPromptEnvelope = zResolvedPrompt.partial({ releaseId: true }).extend({ strategy: z.enum(["single", "weighted"]).optional() });
|
|
20
9
|
function unwrap(envelope) {
|
|
21
10
|
if (envelope.data === null || envelope.data === undefined) {
|
|
@@ -27,12 +16,12 @@ function getProjectPromptsPath(projectId) {
|
|
|
27
16
|
return `/v1/projects/${encodeURIComponent(projectId)}/prompts`;
|
|
28
17
|
}
|
|
29
18
|
function renderedToMessages(rendered) {
|
|
30
|
-
if (rendered.format
|
|
31
|
-
|
|
19
|
+
if (rendered.format !== "chat") {
|
|
20
|
+
throw new Error("[to11ai/sdk] Unsupported non-chat prompt format; author the prompt as chat blocks.");
|
|
32
21
|
}
|
|
33
|
-
return
|
|
22
|
+
return rendered.messages;
|
|
34
23
|
}
|
|
35
|
-
function normalizeResolvedEnvelope(raw) {
|
|
24
|
+
function normalizeResolvedEnvelope(raw, slug) {
|
|
36
25
|
const provenance = raw;
|
|
37
26
|
const result = {
|
|
38
27
|
messages: renderedToMessages(raw.rendered),
|
|
@@ -43,7 +32,7 @@ function normalizeResolvedEnvelope(raw) {
|
|
|
43
32
|
versionId: raw.versionId,
|
|
44
33
|
contentHash: raw.contentHash,
|
|
45
34
|
label: raw.label,
|
|
46
|
-
|
|
35
|
+
slug,
|
|
47
36
|
modelConfig: provenance.modelConfig
|
|
48
37
|
};
|
|
49
38
|
if (raw.tools != null && raw.tools.length > 0) {
|
|
@@ -57,11 +46,11 @@ function normalizeResolvedEnvelope(raw) {
|
|
|
57
46
|
}
|
|
58
47
|
return result;
|
|
59
48
|
}
|
|
60
|
-
function
|
|
61
|
-
if (
|
|
62
|
-
|
|
49
|
+
function liftFallbackToRendered(fallback, slug) {
|
|
50
|
+
if (!Array.isArray(fallback.messages)) {
|
|
51
|
+
throw new Error("[to11ai/sdk] `fallback` must be a RenderedPrompt (as returned by render()); the legacy resolve() shape is no longer supported.");
|
|
63
52
|
}
|
|
64
|
-
return
|
|
53
|
+
return { ...structuredClone(fallback), slug: fallback.slug || slug };
|
|
65
54
|
}
|
|
66
55
|
function getProjectPromptPath(projectId, promptId) {
|
|
67
56
|
return `${getProjectPromptsPath(projectId)}/${encodeURIComponent(promptId)}`;
|
|
@@ -109,13 +98,22 @@ class PromptResource {
|
|
|
109
98
|
this.format = config?.format;
|
|
110
99
|
this.onUnknownRole = config?.onUnknownRole;
|
|
111
100
|
}
|
|
101
|
+
resolveProjectId(perCall) {
|
|
102
|
+
const projectId = perCall ?? this.projectId;
|
|
103
|
+
if (projectId === undefined || projectId.trim() === "") {
|
|
104
|
+
throw new Error("[to11ai/sdk] this call needs a `projectId` — pass it on the call or bind one via createClient({ projectId, ... }).");
|
|
105
|
+
}
|
|
106
|
+
return projectId.trim();
|
|
107
|
+
}
|
|
112
108
|
async create(input) {
|
|
113
|
-
const { projectId, ...body } = input;
|
|
109
|
+
const { projectId: perCallProjectId, ...body } = input;
|
|
110
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
114
111
|
const envelope = await this.transport.request("POST", getProjectPromptsPath(projectId), { body });
|
|
115
112
|
return unwrap(envelope);
|
|
116
113
|
}
|
|
117
|
-
async list(input) {
|
|
118
|
-
const { projectId, ...queryRest } = input;
|
|
114
|
+
async list(input = {}) {
|
|
115
|
+
const { projectId: perCallProjectId, ...queryRest } = input;
|
|
116
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
119
117
|
const envelope = await this.transport.request("GET", getProjectPromptsPath(projectId), {
|
|
120
118
|
query: {
|
|
121
119
|
...queryRest
|
|
@@ -132,52 +130,60 @@ class PromptResource {
|
|
|
132
130
|
return { items, pagination };
|
|
133
131
|
}
|
|
134
132
|
async get(input) {
|
|
135
|
-
const { projectId, promptId } = input;
|
|
133
|
+
const { projectId: perCallProjectId, promptId } = input;
|
|
134
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
136
135
|
const envelope = await this.transport.request("GET", getProjectPromptPath(projectId, promptId));
|
|
137
136
|
return unwrap(envelope);
|
|
138
137
|
}
|
|
139
138
|
async update(input) {
|
|
140
|
-
const { projectId, promptId, ...body } = input;
|
|
139
|
+
const { projectId: perCallProjectId, promptId, ...body } = input;
|
|
140
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
141
141
|
const envelope = await this.transport.request("PATCH", getProjectPromptPath(projectId, promptId), { body });
|
|
142
142
|
return unwrap(envelope);
|
|
143
143
|
}
|
|
144
144
|
async archive(input) {
|
|
145
|
-
const { projectId, promptId } = input;
|
|
145
|
+
const { projectId: perCallProjectId, promptId } = input;
|
|
146
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
146
147
|
const envelope = await this.transport.request("DELETE", getProjectPromptPath(projectId, promptId));
|
|
147
148
|
return unwrap(envelope);
|
|
148
149
|
}
|
|
149
150
|
async createVersion(input) {
|
|
150
|
-
const { projectId, promptId, ...body } = input;
|
|
151
|
+
const { projectId: perCallProjectId, promptId, ...body } = input;
|
|
152
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
151
153
|
const envelope = await this.transport.request("POST", `${getProjectPromptPath(projectId, promptId)}/versions`, { body });
|
|
152
154
|
return unwrap(envelope);
|
|
153
155
|
}
|
|
154
156
|
async listVersions(input) {
|
|
155
|
-
const { projectId, promptId } = input;
|
|
157
|
+
const { projectId: perCallProjectId, promptId } = input;
|
|
158
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
156
159
|
const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/versions`);
|
|
157
160
|
return unwrap(envelope);
|
|
158
161
|
}
|
|
159
162
|
async getVersion(input) {
|
|
160
|
-
const { projectId, promptId, versionNumber } = input;
|
|
163
|
+
const { projectId: perCallProjectId, promptId, versionNumber } = input;
|
|
164
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
161
165
|
const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/versions/${encodeURIComponent(String(versionNumber))}`);
|
|
162
166
|
return unwrap(envelope);
|
|
163
167
|
}
|
|
164
168
|
async moveLabel(input) {
|
|
165
|
-
const { projectId, promptId, label, ...body } = input;
|
|
169
|
+
const { projectId: perCallProjectId, promptId, label, ...body } = input;
|
|
170
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
166
171
|
const envelope = await this.transport.request("PUT", `${getProjectPromptPath(projectId, promptId)}/labels/${encodeURIComponent(label)}`, { body });
|
|
167
172
|
return unwrap(envelope);
|
|
168
173
|
}
|
|
169
174
|
async listLabels(input) {
|
|
170
|
-
const { projectId, promptId } = input;
|
|
175
|
+
const { projectId: perCallProjectId, promptId } = input;
|
|
176
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
171
177
|
const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/labels`);
|
|
172
178
|
return unwrap(envelope);
|
|
173
179
|
}
|
|
174
180
|
async render(slug, options = {}) {
|
|
175
|
-
const
|
|
176
|
-
return shapePrompt(
|
|
181
|
+
const rendered = await this.resolveToRendered(slug, options);
|
|
182
|
+
return shapePrompt(rendered, options.format ?? this.format, {
|
|
177
183
|
onUnknownRole: options.onUnknownRole ?? this.onUnknownRole
|
|
178
184
|
});
|
|
179
185
|
}
|
|
180
|
-
async
|
|
186
|
+
async resolveToRendered(slug, options = {}) {
|
|
181
187
|
if (this.projectId === undefined || this.projectId.trim() === "") {
|
|
182
188
|
throw new Error("[to11ai/sdk] `prompts.render()` requires a `projectId` on the client — pass it to createClient({ projectId, ... }).");
|
|
183
189
|
}
|
|
@@ -189,10 +195,10 @@ class PromptResource {
|
|
|
189
195
|
throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
|
|
190
196
|
}
|
|
191
197
|
const { subject, variables, cache: useCache = true, fallback } = options;
|
|
192
|
-
const cacheKey =
|
|
198
|
+
const cacheKey = buildRenderCacheKey(this.projectId, slug, env, subject, variables);
|
|
193
199
|
if (useCache) {
|
|
194
200
|
const cached = this.cache.get(cacheKey);
|
|
195
|
-
if (cached
|
|
201
|
+
if (cached)
|
|
196
202
|
return structuredClone(cached);
|
|
197
203
|
}
|
|
198
204
|
const body = { slug, labels: [env] };
|
|
@@ -206,7 +212,7 @@ class PromptResource {
|
|
|
206
212
|
decode: (data) => zResolvedPromptEnvelope.parse(data)
|
|
207
213
|
});
|
|
208
214
|
const raw = unwrap(envelope);
|
|
209
|
-
const result = normalizeResolvedEnvelope(raw);
|
|
215
|
+
const result = normalizeResolvedEnvelope(raw, slug);
|
|
210
216
|
const isWeighted = raw.strategy === "weighted" || result.variantName !== undefined;
|
|
211
217
|
const cacheable = !(isWeighted && subject === undefined);
|
|
212
218
|
if (useCache && cacheable) {
|
|
@@ -215,61 +221,33 @@ class PromptResource {
|
|
|
215
221
|
return result;
|
|
216
222
|
} catch (err) {
|
|
217
223
|
if (err instanceof To11aiNetworkError && fallback !== undefined) {
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
throw err;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
async resolve(input) {
|
|
224
|
-
const {
|
|
225
|
-
projectId,
|
|
226
|
-
slug,
|
|
227
|
-
labels,
|
|
228
|
-
variables,
|
|
229
|
-
cache: useCache = true,
|
|
230
|
-
fallback
|
|
231
|
-
} = input;
|
|
232
|
-
const cacheKey = buildCacheKey(projectId, slug, labels, variables);
|
|
233
|
-
if (useCache) {
|
|
234
|
-
const cached = this.cache.get(cacheKey);
|
|
235
|
-
if (cached && !("messages" in cached))
|
|
236
|
-
return structuredClone(cached);
|
|
237
|
-
}
|
|
238
|
-
try {
|
|
239
|
-
const envelope = await this.transport.request("POST", `${getProjectPromptsPath(projectId)}:resolve`, {
|
|
240
|
-
body: { slug, labels, variables },
|
|
241
|
-
decode: (data) => zResolvedPromptLegacy.parse(data)
|
|
242
|
-
});
|
|
243
|
-
const result = unwrap(envelope);
|
|
244
|
-
if (useCache) {
|
|
245
|
-
this.cache.set(cacheKey, structuredClone(result));
|
|
246
|
-
}
|
|
247
|
-
return result;
|
|
248
|
-
} catch (err) {
|
|
249
|
-
if (err instanceof To11aiNetworkError && fallback !== undefined) {
|
|
250
|
-
return fallback;
|
|
224
|
+
return liftFallbackToRendered(fallback, slug);
|
|
251
225
|
}
|
|
252
226
|
throw err;
|
|
253
227
|
}
|
|
254
228
|
}
|
|
255
|
-
async listProjectLabels(input) {
|
|
256
|
-
const { projectId, includeArchived } = input;
|
|
229
|
+
async listProjectLabels(input = {}) {
|
|
230
|
+
const { projectId: perCallProjectId, includeArchived } = input;
|
|
231
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
257
232
|
const envelope = await this.transport.request("GET", getProjectPromptLabelsPath(projectId), {
|
|
258
233
|
query: includeArchived ? { includeArchived: "true" } : undefined
|
|
259
234
|
});
|
|
260
235
|
return unwrap(envelope);
|
|
261
236
|
}
|
|
262
237
|
async createProjectLabel(input) {
|
|
263
|
-
const { projectId, ...body } = input;
|
|
238
|
+
const { projectId: perCallProjectId, ...body } = input;
|
|
239
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
264
240
|
const envelope = await this.transport.request("POST", getProjectPromptLabelsPath(projectId), { body });
|
|
265
241
|
return unwrap(envelope);
|
|
266
242
|
}
|
|
267
243
|
async getProjectLabel(input) {
|
|
268
|
-
const
|
|
244
|
+
const projectId = this.resolveProjectId(input.projectId);
|
|
245
|
+
const envelope = await this.transport.request("GET", getProjectPromptLabelPath(projectId, input.label));
|
|
269
246
|
return unwrap(envelope);
|
|
270
247
|
}
|
|
271
248
|
async updateProjectLabel(input) {
|
|
272
|
-
const { projectId, label, ...rest } = input;
|
|
249
|
+
const { projectId: perCallProjectId, label, ...rest } = input;
|
|
250
|
+
const projectId = this.resolveProjectId(perCallProjectId);
|
|
273
251
|
const body = {};
|
|
274
252
|
if (rest.isDefault !== undefined)
|
|
275
253
|
body.isDefault = rest.isDefault;
|
|
@@ -281,15 +259,16 @@ class PromptResource {
|
|
|
281
259
|
return unwrap(envelope);
|
|
282
260
|
}
|
|
283
261
|
async deleteProjectLabel(input) {
|
|
284
|
-
const
|
|
262
|
+
const projectId = this.resolveProjectId(input.projectId);
|
|
263
|
+
const envelope = await this.transport.request("DELETE", getProjectPromptLabelPath(projectId, input.label));
|
|
285
264
|
return unwrap(envelope);
|
|
286
265
|
}
|
|
287
266
|
async listProjectLabelUsages(input) {
|
|
288
|
-
const envelope = await this.transport.request("GET", `${getProjectPromptLabelPath(input.projectId, input.label)}/usages`);
|
|
267
|
+
const envelope = await this.transport.request("GET", `${getProjectPromptLabelPath(this.resolveProjectId(input.projectId), input.label)}/usages`);
|
|
289
268
|
return unwrap(envelope);
|
|
290
269
|
}
|
|
291
270
|
async listLabelEvents(input) {
|
|
292
|
-
const projectSeg = encodeURIComponent(input.projectId);
|
|
271
|
+
const projectSeg = encodeURIComponent(this.resolveProjectId(input.projectId));
|
|
293
272
|
let path;
|
|
294
273
|
switch (input.scope) {
|
|
295
274
|
case "label":
|
package/dist/prompts/shape.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Format-at-load shaping: turn a neutral `
|
|
2
|
+
* Format-at-load shaping: turn a neutral `RenderedPrompt` into a provider-shaped
|
|
3
3
|
* `{ messages, config, metadata }` result the caller spreads into their own
|
|
4
4
|
* provider `create()` call. Header-only — this only reshapes data, it never
|
|
5
5
|
* sends a request. See docs/product-specs/2026-07-14-to11-2691-sdk-simpler-setup.md.
|
|
6
6
|
*/
|
|
7
7
|
import { type AnthropicMessage, type AnthropicTool, type AnthropicToolChoice, type ConvertMessagesOptions, type OpenAIChatMessage, type OpenAITool, type OpenAIToolChoice } from "../gateway";
|
|
8
|
-
import type {
|
|
8
|
+
import type { RenderedPrompt, RenderFormat } from "./types";
|
|
9
9
|
/** Model params passed through verbatim from the resolved version's modelConfig. */
|
|
10
10
|
export interface PromptConfig {
|
|
11
11
|
model?: string;
|
|
@@ -22,6 +22,8 @@ export interface PromptMetadata {
|
|
|
22
22
|
releaseId: string | null;
|
|
23
23
|
/** The single label the prompt resolved through (env slug today). */
|
|
24
24
|
label: string;
|
|
25
|
+
/** The prompt's human-readable slug — surfaced as `x-to11-prompt-slug`. */
|
|
26
|
+
slug: string;
|
|
25
27
|
variantName?: string;
|
|
26
28
|
}
|
|
27
29
|
/** OpenAI-shaped render result: spread `{ ...config, messages }` into create(). */
|
|
@@ -47,8 +49,8 @@ export interface AnthropicRenderedPrompt {
|
|
|
47
49
|
tool_choice?: AnthropicToolChoice;
|
|
48
50
|
}
|
|
49
51
|
/** The render return type for a given client/call format. */
|
|
50
|
-
export type RenderResult<F extends RenderFormat | undefined> = F extends "openai" ? OpenAiRenderedPrompt : F extends "anthropic" ? AnthropicRenderedPrompt :
|
|
51
|
-
export declare function shapeOpenAI(prompt:
|
|
52
|
-
export declare function shapeAnthropic(prompt:
|
|
52
|
+
export type RenderResult<F extends RenderFormat | undefined> = F extends "openai" ? OpenAiRenderedPrompt : F extends "anthropic" ? AnthropicRenderedPrompt : RenderedPrompt;
|
|
53
|
+
export declare function shapeOpenAI(prompt: RenderedPrompt, options?: ConvertMessagesOptions): OpenAiRenderedPrompt;
|
|
54
|
+
export declare function shapeAnthropic(prompt: RenderedPrompt, options?: ConvertMessagesOptions): AnthropicRenderedPrompt;
|
|
53
55
|
/** Shape a fetched prompt for `format`, or return it neutral when unset. */
|
|
54
|
-
export declare function shapePrompt(prompt:
|
|
56
|
+
export declare function shapePrompt(prompt: RenderedPrompt, format: RenderFormat | undefined, options?: ConvertMessagesOptions): RenderedPrompt | OpenAiRenderedPrompt | AnthropicRenderedPrompt;
|
package/dist/prompts/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ProjectPromptLabel as GenProjectPromptLabel, ProjectPromptLabelUsage as GenProjectPromptLabelUsage, Prompt as GenPrompt, PromptLabelEvent as GenPromptLabelEvent, PromptLabelPointer as GenPromptLabelPointer, PromptVersion as GenPromptVersion, RenderedChatPrompt as GenRenderedChatPrompt,
|
|
1
|
+
import type { ProjectPromptLabel as GenProjectPromptLabel, ProjectPromptLabelUsage as GenProjectPromptLabelUsage, Prompt as GenPrompt, PromptLabelEvent as GenPromptLabelEvent, PromptLabelPointer as GenPromptLabelPointer, PromptVersion as GenPromptVersion, RenderedChatPrompt as GenRenderedChatPrompt, ResolvedPrompt as GenResolvedPrompt, ResolvedToolCall as GenResolvedToolCall, ResolvedToolDefinition as GenResolvedToolDefinition } from "../generated/types.gen";
|
|
2
2
|
export interface RowError {
|
|
3
3
|
path: ReadonlyArray<string | number>;
|
|
4
4
|
code: string;
|
|
@@ -17,7 +17,6 @@ export interface TextChatMessage {
|
|
|
17
17
|
}
|
|
18
18
|
export type ChatMessage = TextChatMessage;
|
|
19
19
|
export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
|
|
20
|
-
export type RenderedPrompt = GenRenderedPrompt;
|
|
21
20
|
/** Provider shape for `prompts.render()` output. Omit for the neutral result. */
|
|
22
21
|
export type RenderFormat = "openai" | "anthropic";
|
|
23
22
|
/**
|
|
@@ -51,7 +50,7 @@ export interface PaginatedResult<T> {
|
|
|
51
50
|
pagination: PaginationInfo;
|
|
52
51
|
}
|
|
53
52
|
export interface CreatePromptInput {
|
|
54
|
-
projectId
|
|
53
|
+
projectId?: string;
|
|
55
54
|
name: string;
|
|
56
55
|
slug: string;
|
|
57
56
|
description?: string;
|
|
@@ -59,7 +58,7 @@ export interface CreatePromptInput {
|
|
|
59
58
|
}
|
|
60
59
|
export type CreatePromptResult = Prompt;
|
|
61
60
|
export interface ListPromptsInput {
|
|
62
|
-
projectId
|
|
61
|
+
projectId?: string;
|
|
63
62
|
status?: PromptStatus;
|
|
64
63
|
sortBy?: "createdAt" | "updatedAt" | "name";
|
|
65
64
|
tags?: string;
|
|
@@ -68,12 +67,12 @@ export interface ListPromptsInput {
|
|
|
68
67
|
}
|
|
69
68
|
export type ListPromptsResult = Prompt;
|
|
70
69
|
export interface GetPromptInput {
|
|
71
|
-
projectId
|
|
70
|
+
projectId?: string;
|
|
72
71
|
promptId: string;
|
|
73
72
|
}
|
|
74
73
|
export type GetPromptResult = Prompt;
|
|
75
74
|
export interface UpdatePromptInput {
|
|
76
|
-
projectId
|
|
75
|
+
projectId?: string;
|
|
77
76
|
promptId: string;
|
|
78
77
|
name?: string;
|
|
79
78
|
description?: string | null;
|
|
@@ -81,12 +80,12 @@ export interface UpdatePromptInput {
|
|
|
81
80
|
}
|
|
82
81
|
export type UpdatePromptResult = Prompt;
|
|
83
82
|
export interface ArchivePromptInput {
|
|
84
|
-
projectId
|
|
83
|
+
projectId?: string;
|
|
85
84
|
promptId: string;
|
|
86
85
|
}
|
|
87
86
|
export type ArchivePromptResult = Prompt;
|
|
88
87
|
export interface CreatePromptVersionInput {
|
|
89
|
-
projectId
|
|
88
|
+
projectId?: string;
|
|
90
89
|
promptId: string;
|
|
91
90
|
format: PromptFormat;
|
|
92
91
|
templateJson: unknown;
|
|
@@ -96,18 +95,18 @@ export interface CreatePromptVersionInput {
|
|
|
96
95
|
}
|
|
97
96
|
export type CreatePromptVersionResult = PromptVersion;
|
|
98
97
|
export interface ListPromptVersionsInput {
|
|
99
|
-
projectId
|
|
98
|
+
projectId?: string;
|
|
100
99
|
promptId: string;
|
|
101
100
|
}
|
|
102
101
|
export type ListPromptVersionsResult = PromptVersion[];
|
|
103
102
|
export interface GetPromptVersionInput {
|
|
104
|
-
projectId
|
|
103
|
+
projectId?: string;
|
|
105
104
|
promptId: string;
|
|
106
105
|
versionNumber: number;
|
|
107
106
|
}
|
|
108
107
|
export type GetPromptVersionResult = PromptVersion;
|
|
109
108
|
export interface MovePromptLabelInput {
|
|
110
|
-
projectId
|
|
109
|
+
projectId?: string;
|
|
111
110
|
promptId: string;
|
|
112
111
|
label: string;
|
|
113
112
|
versionId: string;
|
|
@@ -115,24 +114,13 @@ export interface MovePromptLabelInput {
|
|
|
115
114
|
}
|
|
116
115
|
export type MovePromptLabelResult = PromptLabelPointer;
|
|
117
116
|
export interface ListPromptLabelsInput {
|
|
118
|
-
projectId
|
|
117
|
+
projectId?: string;
|
|
119
118
|
promptId: string;
|
|
120
119
|
}
|
|
121
120
|
export type ListPromptLabelsResult = PromptLabelPointer[];
|
|
122
|
-
export interface ResolvePromptInput {
|
|
123
|
-
projectId: string;
|
|
124
|
-
slug: string;
|
|
125
|
-
labels: string[];
|
|
126
|
-
variables?: Record<string, unknown>;
|
|
127
|
-
/** Set false to bypass the LRU cache for this call. Default: true */
|
|
128
|
-
cache?: boolean;
|
|
129
|
-
/** Fallback prompt served if the API is unreachable and cache is empty. */
|
|
130
|
-
fallback?: ResolvedPrompt;
|
|
131
|
-
}
|
|
132
|
-
export type ResolvePromptResult = ResolvedPrompt;
|
|
133
121
|
export declare const ENV_SLUG_REGEX: RegExp;
|
|
134
122
|
export type BlockRenderRecord = Record<string, "rendered" | "dimmed">;
|
|
135
|
-
export interface
|
|
123
|
+
export interface RenderedPrompt {
|
|
136
124
|
messages: RenderedChatMessage[];
|
|
137
125
|
version: number;
|
|
138
126
|
releaseId: string | null;
|
|
@@ -147,7 +135,12 @@ export interface FetchedPrompt {
|
|
|
147
135
|
* `gatewayPromptHeaders` / `turn.headers()` (TO11-2725).
|
|
148
136
|
*/
|
|
149
137
|
label: string;
|
|
150
|
-
|
|
138
|
+
/**
|
|
139
|
+
* The prompt's human-readable slug (the `render()` input). Surfaced as
|
|
140
|
+
* `x-to11-prompt-slug` by `gatewayPromptHeaders` / `turn.headers()` so traces
|
|
141
|
+
* carry a readable name alongside the opaque `promptId` (TO11-2727).
|
|
142
|
+
*/
|
|
143
|
+
slug: string;
|
|
151
144
|
/**
|
|
152
145
|
* The served version's model config (model, temperature, max_tokens, …),
|
|
153
146
|
* passed through verbatim. Surfaced as `config` by `render({ format })`.
|
|
@@ -166,7 +159,7 @@ export interface FetchedPrompt {
|
|
|
166
159
|
* into `toOpenAIToolChoice` / `toAnthropicToolChoice`.
|
|
167
160
|
*
|
|
168
161
|
* `NonNullable` because `normalizeResolvedEnvelope` maps wire-`null` to absent,
|
|
169
|
-
* so a present `
|
|
162
|
+
* so a present `RenderedPrompt.toolChoice` is never `null` — callers get the
|
|
170
163
|
* key or nothing, and never have to branch on `null`.
|
|
171
164
|
*/
|
|
172
165
|
toolChoice?: NonNullable<ResolvedPrompt["toolChoice"]>;
|
|
@@ -175,14 +168,16 @@ export type ResolvedPromptEnvelope = GenResolvedPrompt & {
|
|
|
175
168
|
/** Active release strategy. Used to decide weighted-no-subject cache bypass (D8). */
|
|
176
169
|
strategy?: "single" | "weighted";
|
|
177
170
|
};
|
|
178
|
-
export interface
|
|
171
|
+
export interface RenderOptions {
|
|
172
|
+
/** Serving environment for this call; overrides the client default. */
|
|
179
173
|
env?: string;
|
|
174
|
+
/** Stable id so a weighted release sends the same caller to the same variant. */
|
|
180
175
|
subject?: string;
|
|
181
176
|
variables?: Record<string, unknown>;
|
|
177
|
+
/** Set false to bypass the LRU cache for this call. Default: true */
|
|
182
178
|
cache?: boolean;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
export interface RenderOptions extends FetchPromptOptions {
|
|
179
|
+
/** Prompt served if the API is unreachable on a network error and cache is empty. */
|
|
180
|
+
fallback?: RenderedPrompt;
|
|
186
181
|
/** Provider shape for this call's output; overrides the client default. */
|
|
187
182
|
format?: RenderFormat;
|
|
188
183
|
/**
|
|
@@ -197,13 +192,13 @@ export type ProjectPromptLabel = GenProjectPromptLabel;
|
|
|
197
192
|
export type ProjectPromptLabelUsage = GenProjectPromptLabelUsage;
|
|
198
193
|
export type PromptLabelEvent = GenPromptLabelEvent;
|
|
199
194
|
export interface ListProjectPromptLabelsInput {
|
|
200
|
-
projectId
|
|
195
|
+
projectId?: string;
|
|
201
196
|
/** Set true to include archived (soft-deleted) entries. Default: false. */
|
|
202
197
|
includeArchived?: boolean;
|
|
203
198
|
}
|
|
204
199
|
export type ListProjectPromptLabelsResult = ProjectPromptLabel[];
|
|
205
200
|
export interface CreateProjectPromptLabelInput {
|
|
206
|
-
projectId
|
|
201
|
+
projectId?: string;
|
|
207
202
|
label: string;
|
|
208
203
|
isDefault?: boolean;
|
|
209
204
|
description?: string;
|
|
@@ -211,12 +206,12 @@ export interface CreateProjectPromptLabelInput {
|
|
|
211
206
|
}
|
|
212
207
|
export type CreateProjectPromptLabelResult = ProjectPromptLabel;
|
|
213
208
|
export interface GetProjectPromptLabelInput {
|
|
214
|
-
projectId
|
|
209
|
+
projectId?: string;
|
|
215
210
|
label: string;
|
|
216
211
|
}
|
|
217
212
|
export type GetProjectPromptLabelResult = ProjectPromptLabel;
|
|
218
213
|
export interface UpdateProjectPromptLabelInput {
|
|
219
|
-
projectId
|
|
214
|
+
projectId?: string;
|
|
220
215
|
label: string;
|
|
221
216
|
isDefault?: boolean;
|
|
222
217
|
description?: string | null;
|
|
@@ -224,18 +219,18 @@ export interface UpdateProjectPromptLabelInput {
|
|
|
224
219
|
}
|
|
225
220
|
export type UpdateProjectPromptLabelResult = ProjectPromptLabel;
|
|
226
221
|
export interface DeleteProjectPromptLabelInput {
|
|
227
|
-
projectId
|
|
222
|
+
projectId?: string;
|
|
228
223
|
label: string;
|
|
229
224
|
}
|
|
230
225
|
export type DeleteProjectPromptLabelResult = ProjectPromptLabel;
|
|
231
226
|
export interface ListProjectPromptLabelUsagesInput {
|
|
232
|
-
projectId
|
|
227
|
+
projectId?: string;
|
|
233
228
|
label: string;
|
|
234
229
|
}
|
|
235
230
|
export type ListProjectPromptLabelUsagesResult = ProjectPromptLabelUsage[];
|
|
236
231
|
export type ListLabelEventsInput = {
|
|
237
232
|
scope: "label";
|
|
238
|
-
projectId
|
|
233
|
+
projectId?: string;
|
|
239
234
|
promptId: string;
|
|
240
235
|
label: string;
|
|
241
236
|
page?: number;
|
|
@@ -244,7 +239,7 @@ export type ListLabelEventsInput = {
|
|
|
244
239
|
until?: string;
|
|
245
240
|
} | {
|
|
246
241
|
scope: "prompt";
|
|
247
|
-
projectId
|
|
242
|
+
projectId?: string;
|
|
248
243
|
promptId: string;
|
|
249
244
|
label?: string;
|
|
250
245
|
page?: number;
|
|
@@ -253,7 +248,7 @@ export type ListLabelEventsInput = {
|
|
|
253
248
|
until?: string;
|
|
254
249
|
} | {
|
|
255
250
|
scope: "project";
|
|
256
|
-
projectId
|
|
251
|
+
projectId?: string;
|
|
257
252
|
promptId?: string;
|
|
258
253
|
label?: string;
|
|
259
254
|
page?: number;
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -88,8 +88,6 @@ export type {
|
|
|
88
88
|
// TO11-980 (S9): env-aware render() surface types at the package entrypoint (AC9).
|
|
89
89
|
export type {
|
|
90
90
|
BlockRenderRecord,
|
|
91
|
-
FetchedPrompt,
|
|
92
|
-
FetchPromptOptions,
|
|
93
91
|
RenderedChatMessage,
|
|
94
92
|
RenderedPrompt,
|
|
95
93
|
RenderFormat,
|
|
@@ -168,8 +166,9 @@ export interface ClientOptions {
|
|
|
168
166
|
projectId?: string;
|
|
169
167
|
/**
|
|
170
168
|
* Default serving environment for `prompts.render(slug)`, inherited by every
|
|
171
|
-
* render unless overridden per call.
|
|
172
|
-
* project-environments slug rule
|
|
169
|
+
* render unless overridden per call. Precedence: this option → `TO11_ENV`
|
|
170
|
+
* env. Validated eagerly against the project-environments slug rule
|
|
171
|
+
* (`^[a-z0-9-]{1,63}$`).
|
|
173
172
|
*/
|
|
174
173
|
env?: string;
|
|
175
174
|
/**
|
|
@@ -246,6 +245,12 @@ export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
|
246
245
|
readonly apiKey: string | undefined;
|
|
247
246
|
/** Resolved data-plane gateway URL (option → `TO11_GATEWAY_URL` → default). */
|
|
248
247
|
readonly gatewayUrl: string;
|
|
248
|
+
/**
|
|
249
|
+
* Resolved project id (option → `TO11_PROJECT_ID`); `undefined` when none is
|
|
250
|
+
* configured. Read-only, for your own logging / manual headers — `prompts.*`
|
|
251
|
+
* already default to it, so you don't need to pass it back into calls.
|
|
252
|
+
*/
|
|
253
|
+
readonly projectId: string | undefined;
|
|
249
254
|
/** A new session (unit of work). Pass an id to group telemetry by your own id. */
|
|
250
255
|
session(id?: string): Session;
|
|
251
256
|
/**
|
|
@@ -376,7 +381,12 @@ export function createClient<
|
|
|
376
381
|
? options.apiKey
|
|
377
382
|
: pick(options.apiKey, "TO11_API_KEY");
|
|
378
383
|
const projectId = pick(options.projectId, "TO11_PROJECT_ID");
|
|
379
|
-
|
|
384
|
+
// Default serving env: explicit option → `TO11_ENV` env var — the same
|
|
385
|
+
// `pick(option, "TO11_*")` resolution `apiKey`/`projectId` use (empty option
|
|
386
|
+
// or empty env var trims to absent). An explicit empty option is rejected by
|
|
387
|
+
// the dedicated guard below (mirroring `apiKey`/`projectId`); a non-empty but
|
|
388
|
+
// malformed value fails the `ENV_SLUG_REGEX` check.
|
|
389
|
+
const env = pick(options.env, "TO11_ENV");
|
|
380
390
|
// Provider (BYOK) key — option only, no env fallback (which provider's env
|
|
381
391
|
// var is ambiguous). Empty trims to absent so it falls back to the placeholder.
|
|
382
392
|
const providerApiKey = options.providerApiKey?.trim() || undefined;
|
|
@@ -398,6 +408,11 @@ export function createClient<
|
|
|
398
408
|
"[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.",
|
|
399
409
|
);
|
|
400
410
|
}
|
|
411
|
+
if (options.env !== undefined && options.env.trim() === "") {
|
|
412
|
+
throw new Error(
|
|
413
|
+
"[to11ai/sdk] `env` must not be an empty string — omit it or pass a valid env slug.",
|
|
414
|
+
);
|
|
415
|
+
}
|
|
401
416
|
|
|
402
417
|
// Validate the init-time `env` against the project-environments slug rule so
|
|
403
418
|
// a malformed env fails locally rather than round-tripping to ENV_NOT_FOUND.
|
|
@@ -520,6 +535,7 @@ export function createClient<
|
|
|
520
535
|
behaviorStore.resolve(key, codedDefault),
|
|
521
536
|
apiKey,
|
|
522
537
|
gatewayUrl,
|
|
538
|
+
projectId,
|
|
523
539
|
session: (id) => new Session(gatewayAuthContext(), id),
|
|
524
540
|
conversation: (id) => clientDefaultSession().conversation(id),
|
|
525
541
|
turn: () => clientDefaultSession().turn(),
|
package/src/context.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface TurnAuthContext {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* A prompt argument accepted by `turn.headers()`. Either the flat provenance
|
|
27
|
-
* (a neutral `
|
|
27
|
+
* (a neutral `RenderedPrompt`) or a `format`-shaped result carrying it under
|
|
28
28
|
* `metadata` — both are accepted so the format and neutral render paths carry
|
|
29
29
|
* provenance identically.
|
|
30
30
|
*/
|
package/src/gateway.ts
CHANGED
|
@@ -85,6 +85,9 @@ export function gatewayAuthHeaders(
|
|
|
85
85
|
* release was weighted); omitted for `single`-strategy releases.
|
|
86
86
|
* - `x-to11-prompt-label` — the single label the prompt resolved through (the
|
|
87
87
|
* env slug today); omitted when empty (the gateway rejects empty values).
|
|
88
|
+
* - `x-to11-prompt-slug` — the prompt's human-readable slug, so traces show a
|
|
89
|
+
* readable name alongside the opaque `x-to11-prompt-id`; omitted when empty
|
|
90
|
+
* or absent (a legacy `resolve()` result carries no slug).
|
|
88
91
|
*
|
|
89
92
|
* The parameter type is WIDENED to accept either the enriched `render()`
|
|
90
93
|
* result or the legacy `ResolvedPrompt`. The new fields are read when present
|
|
@@ -100,6 +103,11 @@ export interface GatewayPromptProvenance {
|
|
|
100
103
|
version: number;
|
|
101
104
|
/** The single label the prompt resolved through (env slug today). */
|
|
102
105
|
label: string;
|
|
106
|
+
/**
|
|
107
|
+
* The prompt's human-readable slug (the `render()`/`resolve()` input). Present
|
|
108
|
+
* on an enriched `render()` result; a legacy `ResolvedPrompt` omits it.
|
|
109
|
+
*/
|
|
110
|
+
slug?: string;
|
|
103
111
|
/** Present on an enriched result; a legacy `resolve()` result omits it. */
|
|
104
112
|
releaseId?: string | null;
|
|
105
113
|
/** Present IFF the resolved release was weighted. */
|
|
@@ -127,6 +135,11 @@ export function gatewayPromptHeaders(
|
|
|
127
135
|
if (prompt.label.length > 0) {
|
|
128
136
|
headers["x-to11-prompt-label"] = prompt.label;
|
|
129
137
|
}
|
|
138
|
+
// The prompt's human-readable slug. Omit when absent/empty — a legacy
|
|
139
|
+
// `resolve()` result carries no slug, and the gateway rejects empty values.
|
|
140
|
+
if (typeof prompt.slug === "string" && prompt.slug.length > 0) {
|
|
141
|
+
headers["x-to11-prompt-slug"] = prompt.slug;
|
|
142
|
+
}
|
|
130
143
|
return headers;
|
|
131
144
|
}
|
|
132
145
|
|