@to11ai/sdk 1.1.0 → 2.0.0-rc.10
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 +99 -258
- package/dist/client.cjs +91 -45
- package/dist/client.d.ts +149 -61
- package/dist/client.js +95 -55
- package/dist/config.d.ts +9 -0
- package/dist/context.d.ts +124 -0
- package/dist/errors.cjs +36 -24
- package/dist/errors.d.ts +35 -46
- package/dist/errors.js +36 -24
- package/dist/gateway.cjs +85 -31
- package/dist/gateway.d.ts +102 -27
- package/dist/gateway.js +85 -31
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/types.gen.d.ts +2802 -502
- package/dist/generated/zod.gen.d.ts +1018 -243
- package/dist/prompts/resource.cjs +80 -113
- package/dist/prompts/resource.d.ts +60 -39
- package/dist/prompts/resource.js +84 -113
- package/dist/prompts/shape.d.ts +56 -0
- package/dist/prompts/types.d.ts +76 -61
- package/dist/transport.d.ts +2 -6
- package/package.json +5 -11
- package/src/client.ts +332 -157
- package/src/config.ts +13 -0
- package/src/context.ts +196 -0
- package/src/errors.ts +65 -79
- package/src/gateway.ts +212 -67
- package/src/generated/index.ts +1 -1
- package/src/generated/types.gen.ts +2977 -611
- package/src/generated/zod.gen.ts +1029 -338
- package/src/prompts/resource.ts +211 -226
- package/src/prompts/shape.ts +152 -0
- package/src/prompts/types.ts +77 -65
- package/src/transport.ts +53 -40
- package/dist/prompts/cache.d.ts +0 -59
- package/dist/routingRules/resource.cjs +0 -138
- package/dist/routingRules/resource.js +0 -98
- package/src/prompts/cache.ts +0 -157
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-at-load shaping: turn a neutral `RenderedPrompt` 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 { RenderedPrompt, 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
|
+
/** The prompt's human-readable slug — surfaced as `x-to11-prompt-slug`. */
|
|
46
|
+
slug: string;
|
|
47
|
+
variantName?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** OpenAI-shaped render result: spread `{ ...config, messages }` into create(). */
|
|
51
|
+
export interface OpenAiRenderedPrompt {
|
|
52
|
+
messages: OpenAIChatMessage[];
|
|
53
|
+
config: PromptConfig;
|
|
54
|
+
metadata: PromptMetadata;
|
|
55
|
+
/** Authored tools, provider-shaped. Present only when the prompt declares tools. */
|
|
56
|
+
tools?: OpenAITool[];
|
|
57
|
+
/** Authored tool-choice directive. Present only when the prompt sets one. */
|
|
58
|
+
tool_choice?: OpenAIToolChoice;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Anthropic-shaped render result: system/developer folded into `system`. */
|
|
62
|
+
export interface AnthropicRenderedPrompt {
|
|
63
|
+
/** Folded system/developer instruction text (Anthropic's top-level `system`). */
|
|
64
|
+
system?: string;
|
|
65
|
+
messages: AnthropicMessage[];
|
|
66
|
+
config: PromptConfig;
|
|
67
|
+
metadata: PromptMetadata;
|
|
68
|
+
/** Authored tools, provider-shaped. Present only when the prompt declares tools. */
|
|
69
|
+
tools?: AnthropicTool[];
|
|
70
|
+
/** Authored tool-choice directive. Present only when the prompt sets one. */
|
|
71
|
+
tool_choice?: AnthropicToolChoice;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The render return type for a given client/call format. */
|
|
75
|
+
export type RenderResult<F extends RenderFormat | undefined> =
|
|
76
|
+
F extends "openai"
|
|
77
|
+
? OpenAiRenderedPrompt
|
|
78
|
+
: F extends "anthropic"
|
|
79
|
+
? AnthropicRenderedPrompt
|
|
80
|
+
: RenderedPrompt;
|
|
81
|
+
|
|
82
|
+
function toPromptConfig(modelConfig: unknown): PromptConfig {
|
|
83
|
+
return modelConfig !== null && typeof modelConfig === "object"
|
|
84
|
+
? { ...(modelConfig as Record<string, unknown>) }
|
|
85
|
+
: {};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function toMetadata(prompt: RenderedPrompt): PromptMetadata {
|
|
89
|
+
const metadata: PromptMetadata = {
|
|
90
|
+
promptId: prompt.promptId,
|
|
91
|
+
versionId: prompt.versionId,
|
|
92
|
+
version: prompt.version,
|
|
93
|
+
releaseId: prompt.releaseId,
|
|
94
|
+
label: prompt.label,
|
|
95
|
+
slug: prompt.slug,
|
|
96
|
+
};
|
|
97
|
+
if (prompt.variantName !== undefined)
|
|
98
|
+
metadata.variantName = prompt.variantName;
|
|
99
|
+
return metadata;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function shapeOpenAI(
|
|
103
|
+
prompt: RenderedPrompt,
|
|
104
|
+
options: ConvertMessagesOptions = {},
|
|
105
|
+
): OpenAiRenderedPrompt {
|
|
106
|
+
const result: OpenAiRenderedPrompt = {
|
|
107
|
+
messages: toOpenAIMessages(prompt.messages, options),
|
|
108
|
+
config: toPromptConfig(prompt.modelConfig),
|
|
109
|
+
metadata: toMetadata(prompt),
|
|
110
|
+
};
|
|
111
|
+
// Carry authored tools so the spread-ready result is complete for
|
|
112
|
+
// tool-using prompts. Omit when empty/absent so we never send `tools: []`.
|
|
113
|
+
const tools = toOpenAITools(prompt.tools);
|
|
114
|
+
if (tools.length > 0) result.tools = tools;
|
|
115
|
+
const toolChoice = toOpenAIToolChoice(prompt.toolChoice);
|
|
116
|
+
if (toolChoice !== undefined) result.tool_choice = toolChoice;
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function shapeAnthropic(
|
|
121
|
+
prompt: RenderedPrompt,
|
|
122
|
+
options: ConvertMessagesOptions = {},
|
|
123
|
+
): AnthropicRenderedPrompt {
|
|
124
|
+
const result: AnthropicRenderedPrompt = {
|
|
125
|
+
messages: toAnthropicMessages(prompt.messages, options),
|
|
126
|
+
config: toPromptConfig(prompt.modelConfig),
|
|
127
|
+
metadata: toMetadata(prompt),
|
|
128
|
+
};
|
|
129
|
+
const system = toAnthropicSystem(prompt.messages);
|
|
130
|
+
if (system !== undefined) result.system = system;
|
|
131
|
+
const tools = toAnthropicTools(prompt.tools);
|
|
132
|
+
if (tools.length > 0) result.tools = tools;
|
|
133
|
+
const toolChoice = toAnthropicToolChoice(prompt.toolChoice);
|
|
134
|
+
if (toolChoice !== undefined) result.tool_choice = toolChoice;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Shape a rendered prompt for `format`, or return it neutral when unset. */
|
|
139
|
+
export function shapePrompt(
|
|
140
|
+
prompt: RenderedPrompt,
|
|
141
|
+
format: RenderFormat | undefined,
|
|
142
|
+
options: ConvertMessagesOptions = {},
|
|
143
|
+
): RenderedPrompt | OpenAiRenderedPrompt | AnthropicRenderedPrompt {
|
|
144
|
+
switch (format) {
|
|
145
|
+
case "openai":
|
|
146
|
+
return shapeOpenAI(prompt, options);
|
|
147
|
+
case "anthropic":
|
|
148
|
+
return shapeAnthropic(prompt, options);
|
|
149
|
+
default:
|
|
150
|
+
return prompt;
|
|
151
|
+
}
|
|
152
|
+
}
|
package/src/prompts/types.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
PromptLabelPointer as GenPromptLabelPointer,
|
|
7
7
|
PromptVersion as GenPromptVersion,
|
|
8
8
|
RenderedChatPrompt as GenRenderedChatPrompt,
|
|
9
|
-
RenderedPrompt as GenRenderedPrompt,
|
|
10
9
|
ResolvedPrompt as GenResolvedPrompt,
|
|
11
10
|
ResolvedToolCall as GenResolvedToolCall,
|
|
12
11
|
ResolvedToolDefinition as GenResolvedToolDefinition,
|
|
@@ -24,19 +23,27 @@ export type PromptVersion = GenPromptVersion;
|
|
|
24
23
|
export type PromptFormat = PromptVersion["format"];
|
|
25
24
|
export type PromptLabelPointer = GenPromptLabelPointer;
|
|
26
25
|
|
|
27
|
-
export type
|
|
26
|
+
export type ChatRole = "system" | "user" | "assistant" | "developer";
|
|
28
27
|
|
|
29
|
-
export interface
|
|
30
|
-
role:
|
|
28
|
+
export interface ChatMessage {
|
|
29
|
+
role: ChatRole;
|
|
31
30
|
content: string;
|
|
32
31
|
disabled?: boolean;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
export type ChatMessage = TextChatMessage;
|
|
36
|
-
|
|
37
34
|
export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
/** Provider shape for `prompts.render()` output. Omit for the neutral result. */
|
|
37
|
+
export type RenderFormat = "openai" | "anthropic";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Policy for a message whose role is outside the known set
|
|
41
|
+
* (`system | user | assistant | developer | tool`) when converting to a
|
|
42
|
+
* provider shape. `"drop"` (default) omits it silently; `"warn"` omits it and
|
|
43
|
+
* emits a `console.warn`; `"error"` throws `UnknownRoleError`. Applies to the
|
|
44
|
+
* standalone converters and to `render({ format })`.
|
|
45
|
+
*/
|
|
46
|
+
export type UnknownRoleMode = "drop" | "warn" | "error";
|
|
40
47
|
|
|
41
48
|
/**
|
|
42
49
|
* A provider-neutral tool definition (`{ name, description?, parameters }`),
|
|
@@ -56,11 +63,12 @@ export type ResolvedPrompt = Pick<
|
|
|
56
63
|
| "promptId"
|
|
57
64
|
| "versionId"
|
|
58
65
|
| "version"
|
|
59
|
-
| "
|
|
66
|
+
| "label"
|
|
60
67
|
| "contentHash"
|
|
61
68
|
| "rendered"
|
|
62
69
|
| "tools"
|
|
63
70
|
| "toolChoice"
|
|
71
|
+
| "modelConfig"
|
|
64
72
|
>;
|
|
65
73
|
|
|
66
74
|
export interface PaginationInfo {
|
|
@@ -76,7 +84,7 @@ export interface PaginatedResult<T> {
|
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
export interface CreatePromptInput {
|
|
79
|
-
projectId
|
|
87
|
+
projectId?: string;
|
|
80
88
|
name: string;
|
|
81
89
|
slug: string;
|
|
82
90
|
description?: string;
|
|
@@ -86,7 +94,7 @@ export interface CreatePromptInput {
|
|
|
86
94
|
export type CreatePromptResult = Prompt;
|
|
87
95
|
|
|
88
96
|
export interface ListPromptsInput {
|
|
89
|
-
projectId
|
|
97
|
+
projectId?: string;
|
|
90
98
|
status?: PromptStatus;
|
|
91
99
|
sortBy?: "createdAt" | "updatedAt" | "name";
|
|
92
100
|
tags?: string;
|
|
@@ -97,14 +105,14 @@ export interface ListPromptsInput {
|
|
|
97
105
|
export type ListPromptsResult = Prompt;
|
|
98
106
|
|
|
99
107
|
export interface GetPromptInput {
|
|
100
|
-
projectId
|
|
108
|
+
projectId?: string;
|
|
101
109
|
promptId: string;
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
export type GetPromptResult = Prompt;
|
|
105
113
|
|
|
106
114
|
export interface UpdatePromptInput {
|
|
107
|
-
projectId
|
|
115
|
+
projectId?: string;
|
|
108
116
|
promptId: string;
|
|
109
117
|
name?: string;
|
|
110
118
|
description?: string | null;
|
|
@@ -114,14 +122,14 @@ export interface UpdatePromptInput {
|
|
|
114
122
|
export type UpdatePromptResult = Prompt;
|
|
115
123
|
|
|
116
124
|
export interface ArchivePromptInput {
|
|
117
|
-
projectId
|
|
125
|
+
projectId?: string;
|
|
118
126
|
promptId: string;
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
export type ArchivePromptResult = Prompt;
|
|
122
130
|
|
|
123
131
|
export interface CreatePromptVersionInput {
|
|
124
|
-
projectId
|
|
132
|
+
projectId?: string;
|
|
125
133
|
promptId: string;
|
|
126
134
|
format: PromptFormat;
|
|
127
135
|
templateJson: unknown;
|
|
@@ -133,14 +141,14 @@ export interface CreatePromptVersionInput {
|
|
|
133
141
|
export type CreatePromptVersionResult = PromptVersion;
|
|
134
142
|
|
|
135
143
|
export interface ListPromptVersionsInput {
|
|
136
|
-
projectId
|
|
144
|
+
projectId?: string;
|
|
137
145
|
promptId: string;
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
export type ListPromptVersionsResult = PromptVersion[];
|
|
141
149
|
|
|
142
150
|
export interface GetPromptVersionInput {
|
|
143
|
-
projectId
|
|
151
|
+
projectId?: string;
|
|
144
152
|
promptId: string;
|
|
145
153
|
versionNumber: number;
|
|
146
154
|
}
|
|
@@ -148,7 +156,7 @@ export interface GetPromptVersionInput {
|
|
|
148
156
|
export type GetPromptVersionResult = PromptVersion;
|
|
149
157
|
|
|
150
158
|
export interface MovePromptLabelInput {
|
|
151
|
-
projectId
|
|
159
|
+
projectId?: string;
|
|
152
160
|
promptId: string;
|
|
153
161
|
label: string;
|
|
154
162
|
versionId: string;
|
|
@@ -158,30 +166,24 @@ export interface MovePromptLabelInput {
|
|
|
158
166
|
export type MovePromptLabelResult = PromptLabelPointer;
|
|
159
167
|
|
|
160
168
|
export interface ListPromptLabelsInput {
|
|
161
|
-
projectId
|
|
169
|
+
projectId?: string;
|
|
162
170
|
promptId: string;
|
|
163
171
|
}
|
|
164
172
|
|
|
165
173
|
export type ListPromptLabelsResult = PromptLabelPointer[];
|
|
166
174
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/** Fallback prompt served if the API is unreachable and cache is empty. */
|
|
175
|
-
fallback?: ResolvedPrompt;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export type ResolvePromptResult = ResolvedPrompt;
|
|
179
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Slug rule for a `render()` label — lowercase-kebab, 1-63 chars. Env slugs are
|
|
177
|
+
* a special case of a label value, so labels are held to the same strict rule
|
|
178
|
+
* (no uppercase, no underscores): a label is a routing key, and case-insensitive
|
|
179
|
+
* routing keys invite silent "production" vs "Production" mismatches. Intentionally
|
|
180
|
+
* strict — do not loosen.
|
|
181
|
+
*/
|
|
180
182
|
export const ENV_SLUG_REGEX = /^[a-z0-9-]{1,63}$/;
|
|
181
183
|
|
|
182
184
|
export type BlockRenderRecord = Record<string, "rendered" | "dimmed">;
|
|
183
185
|
|
|
184
|
-
export interface
|
|
186
|
+
export interface RenderedPrompt {
|
|
185
187
|
messages: RenderedChatMessage[];
|
|
186
188
|
version: number;
|
|
187
189
|
releaseId: string | null;
|
|
@@ -190,8 +192,24 @@ export interface FetchedPrompt {
|
|
|
190
192
|
promptId: string;
|
|
191
193
|
versionId: string;
|
|
192
194
|
contentHash: string;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
/**
|
|
196
|
+
* The single label the prompt resolved through — the env slug today, a real
|
|
197
|
+
* label once labels ship. Surfaced as `x-to11-prompt-label` by
|
|
198
|
+
* `gatewayPromptHeaders` / `turn.headers()` (TO11-2725).
|
|
199
|
+
*/
|
|
200
|
+
label: string;
|
|
201
|
+
/**
|
|
202
|
+
* The prompt's human-readable slug (the `render()` input). Surfaced as
|
|
203
|
+
* `x-to11-prompt-slug` by `gatewayPromptHeaders` / `turn.headers()` so traces
|
|
204
|
+
* carry a readable name alongside the opaque `promptId` (TO11-2727).
|
|
205
|
+
*/
|
|
206
|
+
slug: string;
|
|
207
|
+
/**
|
|
208
|
+
* The served version's model config (model, temperature, max_tokens, …),
|
|
209
|
+
* passed through verbatim. Surfaced as `config` by `render({ format })`.
|
|
210
|
+
* Optional: absent when a pre-`modelConfig` API omits it.
|
|
211
|
+
*/
|
|
212
|
+
modelConfig?: unknown;
|
|
195
213
|
/**
|
|
196
214
|
* Provider-neutral tool definitions lifted from authored tool-definition
|
|
197
215
|
* blocks. Absent (rather than `[]`) when the resolved version declares no
|
|
@@ -204,37 +222,31 @@ export interface FetchedPrompt {
|
|
|
204
222
|
* into `toOpenAIToolChoice` / `toAnthropicToolChoice`.
|
|
205
223
|
*
|
|
206
224
|
* `NonNullable` because `normalizeResolvedEnvelope` maps wire-`null` to absent,
|
|
207
|
-
* so a present `
|
|
225
|
+
* so a present `RenderedPrompt.toolChoice` is never `null` — callers get the
|
|
208
226
|
* key or nothing, and never have to branch on `null`.
|
|
209
227
|
*/
|
|
210
228
|
toolChoice?: NonNullable<ResolvedPrompt["toolChoice"]>;
|
|
211
229
|
}
|
|
212
230
|
|
|
213
|
-
export type ResolvedPromptEnvelope = GenResolvedPrompt
|
|
214
|
-
/** Active release strategy. Used to decide weighted-no-subject cache bypass (D8). */
|
|
215
|
-
strategy?: "single" | "weighted";
|
|
216
|
-
};
|
|
217
|
-
|
|
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";
|
|
231
|
+
export type ResolvedPromptEnvelope = GenResolvedPrompt;
|
|
225
232
|
|
|
226
|
-
export interface
|
|
227
|
-
|
|
228
|
-
|
|
233
|
+
export interface RenderOptions {
|
|
234
|
+
/**
|
|
235
|
+
* Label to resolve this call's prompt version; overrides the client default.
|
|
236
|
+
* When omitted, falls back to the client's `env` (env is a label value).
|
|
237
|
+
*/
|
|
238
|
+
label?: string;
|
|
229
239
|
variables?: Record<string, unknown>;
|
|
230
|
-
|
|
231
|
-
fallback?:
|
|
240
|
+
/** Prompt served if the API is unreachable on a network error. */
|
|
241
|
+
fallback?: RenderedPrompt;
|
|
242
|
+
/** Provider shape for this call's output; overrides the client default. */
|
|
243
|
+
format?: RenderFormat;
|
|
232
244
|
/**
|
|
233
|
-
* How
|
|
234
|
-
*
|
|
235
|
-
*
|
|
245
|
+
* How to handle a message with an unrecognized role while shaping for a
|
|
246
|
+
* provider (`format` set). Overrides the client default; defaults to `"drop"`.
|
|
247
|
+
* Only meaningful with a `format` — the neutral result runs no converter.
|
|
236
248
|
*/
|
|
237
|
-
|
|
249
|
+
onUnknownRole?: UnknownRoleMode;
|
|
238
250
|
}
|
|
239
251
|
|
|
240
252
|
export type PaletteToken = ProjectPromptLabel["displayColor"];
|
|
@@ -246,7 +258,7 @@ export type ProjectPromptLabelUsage = GenProjectPromptLabelUsage;
|
|
|
246
258
|
export type PromptLabelEvent = GenPromptLabelEvent;
|
|
247
259
|
|
|
248
260
|
export interface ListProjectPromptLabelsInput {
|
|
249
|
-
projectId
|
|
261
|
+
projectId?: string;
|
|
250
262
|
/** Set true to include archived (soft-deleted) entries. Default: false. */
|
|
251
263
|
includeArchived?: boolean;
|
|
252
264
|
}
|
|
@@ -254,7 +266,7 @@ export interface ListProjectPromptLabelsInput {
|
|
|
254
266
|
export type ListProjectPromptLabelsResult = ProjectPromptLabel[];
|
|
255
267
|
|
|
256
268
|
export interface CreateProjectPromptLabelInput {
|
|
257
|
-
projectId
|
|
269
|
+
projectId?: string;
|
|
258
270
|
label: string;
|
|
259
271
|
isDefault?: boolean;
|
|
260
272
|
description?: string;
|
|
@@ -264,14 +276,14 @@ export interface CreateProjectPromptLabelInput {
|
|
|
264
276
|
export type CreateProjectPromptLabelResult = ProjectPromptLabel;
|
|
265
277
|
|
|
266
278
|
export interface GetProjectPromptLabelInput {
|
|
267
|
-
projectId
|
|
279
|
+
projectId?: string;
|
|
268
280
|
label: string;
|
|
269
281
|
}
|
|
270
282
|
|
|
271
283
|
export type GetProjectPromptLabelResult = ProjectPromptLabel;
|
|
272
284
|
|
|
273
285
|
export interface UpdateProjectPromptLabelInput {
|
|
274
|
-
projectId
|
|
286
|
+
projectId?: string;
|
|
275
287
|
label: string;
|
|
276
288
|
isDefault?: boolean;
|
|
277
289
|
description?: string | null;
|
|
@@ -281,14 +293,14 @@ export interface UpdateProjectPromptLabelInput {
|
|
|
281
293
|
export type UpdateProjectPromptLabelResult = ProjectPromptLabel;
|
|
282
294
|
|
|
283
295
|
export interface DeleteProjectPromptLabelInput {
|
|
284
|
-
projectId
|
|
296
|
+
projectId?: string;
|
|
285
297
|
label: string;
|
|
286
298
|
}
|
|
287
299
|
|
|
288
300
|
export type DeleteProjectPromptLabelResult = ProjectPromptLabel;
|
|
289
301
|
|
|
290
302
|
export interface ListProjectPromptLabelUsagesInput {
|
|
291
|
-
projectId
|
|
303
|
+
projectId?: string;
|
|
292
304
|
label: string;
|
|
293
305
|
}
|
|
294
306
|
|
|
@@ -297,7 +309,7 @@ export type ListProjectPromptLabelUsagesResult = ProjectPromptLabelUsage[];
|
|
|
297
309
|
export type ListLabelEventsInput =
|
|
298
310
|
| {
|
|
299
311
|
scope: "label";
|
|
300
|
-
projectId
|
|
312
|
+
projectId?: string;
|
|
301
313
|
promptId: string;
|
|
302
314
|
label: string;
|
|
303
315
|
page?: number;
|
|
@@ -307,7 +319,7 @@ export type ListLabelEventsInput =
|
|
|
307
319
|
}
|
|
308
320
|
| {
|
|
309
321
|
scope: "prompt";
|
|
310
|
-
projectId
|
|
322
|
+
projectId?: string;
|
|
311
323
|
promptId: string;
|
|
312
324
|
label?: string;
|
|
313
325
|
page?: number;
|
|
@@ -317,7 +329,7 @@ export type ListLabelEventsInput =
|
|
|
317
329
|
}
|
|
318
330
|
| {
|
|
319
331
|
scope: "project";
|
|
320
|
-
projectId
|
|
332
|
+
projectId?: string;
|
|
321
333
|
promptId?: string;
|
|
322
334
|
label?: string;
|
|
323
335
|
page?: number;
|
package/src/transport.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { BehaviorStore } from "./behaviors/store";
|
|
2
2
|
import {
|
|
3
|
-
AmbiguousEnvLabelsError,
|
|
4
3
|
EnvNotEnabledForProviderError,
|
|
5
|
-
|
|
4
|
+
LabelNotFoundError,
|
|
6
5
|
NoActiveReleaseError,
|
|
7
6
|
NoApplicableRouteError,
|
|
8
7
|
PromptLabelNotRegisteredError,
|
|
@@ -108,14 +107,11 @@ function mapPromptResolveError(
|
|
|
108
107
|
);
|
|
109
108
|
}
|
|
110
109
|
if (detailsCode === "ENV_NOT_FOUND") {
|
|
111
|
-
// Server-side unknown-
|
|
112
|
-
// raised in resource.ts before any request
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
details,
|
|
117
|
-
status,
|
|
118
|
-
);
|
|
110
|
+
// Server-side unknown-label. (The client-side MissingLabelError — no
|
|
111
|
+
// label supplied at all — is raised in resource.ts before any request.)
|
|
112
|
+
// Prefer `details.label`, falling back to `details.env`.
|
|
113
|
+
const label = typeof d.label === "string" ? d.label : env;
|
|
114
|
+
return new LabelNotFoundError(message, label, details, status);
|
|
119
115
|
}
|
|
120
116
|
if (detailsCode === "NO_ACTIVE_RELEASE") {
|
|
121
117
|
return new NoActiveReleaseError(
|
|
@@ -125,9 +121,6 @@ function mapPromptResolveError(
|
|
|
125
121
|
status,
|
|
126
122
|
);
|
|
127
123
|
}
|
|
128
|
-
if (detailsCode === "AMBIGUOUS_ENV_LABELS") {
|
|
129
|
-
return new AmbiguousEnvLabelsError(message, { env, slug }, details, status);
|
|
130
|
-
}
|
|
131
124
|
if (PROMPT_POLICY_VIOLATION_DETAILS_CODES.has(detailsCode)) {
|
|
132
125
|
const policy = typeof d.policy === "string" ? d.policy : undefined;
|
|
133
126
|
return new PromptPolicyViolationError(
|
|
@@ -140,9 +133,9 @@ function mapPromptResolveError(
|
|
|
140
133
|
return undefined;
|
|
141
134
|
}
|
|
142
135
|
|
|
143
|
-
export
|
|
144
|
-
|
|
145
|
-
|
|
136
|
+
export interface AuthConfig {
|
|
137
|
+
readonly apiKey: string;
|
|
138
|
+
}
|
|
146
139
|
|
|
147
140
|
export interface TransportConfig {
|
|
148
141
|
readonly baseUrl: string;
|
|
@@ -248,12 +241,25 @@ function mapHttpError(
|
|
|
248
241
|
}
|
|
249
242
|
if (status === 429) {
|
|
250
243
|
const retryAfterHeader = headers?.get("retry-after");
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
244
|
+
let retryAfterSeconds: number | undefined;
|
|
245
|
+
if (retryAfterHeader) {
|
|
246
|
+
const numeric = Number(retryAfterHeader);
|
|
247
|
+
if (Number.isFinite(numeric)) {
|
|
248
|
+
retryAfterSeconds = Math.max(0, numeric);
|
|
249
|
+
} else {
|
|
250
|
+
// RFC 9110 HTTP-date form → seconds until that instant.
|
|
251
|
+
const when = Date.parse(retryAfterHeader);
|
|
252
|
+
if (!Number.isNaN(when)) {
|
|
253
|
+
retryAfterSeconds = Math.max(
|
|
254
|
+
0,
|
|
255
|
+
Math.round((when - Date.now()) / 1000),
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
254
260
|
return new To11aiRateLimitError(
|
|
255
261
|
message,
|
|
256
|
-
|
|
262
|
+
retryAfterSeconds,
|
|
257
263
|
errorCode,
|
|
258
264
|
details,
|
|
259
265
|
);
|
|
@@ -395,25 +401,20 @@ export class Transport {
|
|
|
395
401
|
private readonly behaviorStore: BehaviorStore | undefined;
|
|
396
402
|
|
|
397
403
|
constructor(config: TransportConfig) {
|
|
398
|
-
this.baseUrl = config.baseUrl.replace(
|
|
404
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
399
405
|
this.auth = config.auth;
|
|
400
406
|
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
401
407
|
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
402
408
|
this.behaviorStore = config.behaviorStore;
|
|
403
409
|
}
|
|
404
410
|
|
|
405
|
-
private
|
|
411
|
+
private buildHeaders(): Record<string, string> {
|
|
406
412
|
const headers: Record<string, string> = {
|
|
407
413
|
"content-type": "application/json",
|
|
408
414
|
accept: "application/json",
|
|
409
415
|
};
|
|
410
416
|
|
|
411
|
-
|
|
412
|
-
headers.authorization = `Bearer ${this.auth.apiKey}`;
|
|
413
|
-
} else if (this.auth.getAccessToken) {
|
|
414
|
-
const token = await this.auth.getAccessToken();
|
|
415
|
-
headers.authorization = `Bearer ${token}`;
|
|
416
|
-
}
|
|
417
|
+
headers.authorization = `Bearer ${this.auth.apiKey}`;
|
|
417
418
|
|
|
418
419
|
const tp = activeTraceContext();
|
|
419
420
|
if (tp) {
|
|
@@ -452,7 +453,7 @@ export class Transport {
|
|
|
452
453
|
let attempt = 0;
|
|
453
454
|
|
|
454
455
|
while (true) {
|
|
455
|
-
const headers =
|
|
456
|
+
const headers = this.buildHeaders();
|
|
456
457
|
const controller = new AbortController();
|
|
457
458
|
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
458
459
|
|
|
@@ -495,16 +496,28 @@ export class Transport {
|
|
|
495
496
|
let json: ApiEnvelope<T> | undefined;
|
|
496
497
|
const text = await response.text();
|
|
497
498
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
response.status,
|
|
504
|
-
null,
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
499
|
+
if (text === "" && response.ok) {
|
|
500
|
+
// A successful empty body (e.g. 204): synthesize an empty-data
|
|
501
|
+
// envelope rather than mis-mapping it to an API error.
|
|
502
|
+
json = {
|
|
503
|
+
success: true,
|
|
504
|
+
code: response.status,
|
|
505
|
+
data: null,
|
|
506
|
+
error: null,
|
|
507
|
+
pagination: null,
|
|
508
|
+
} as ApiEnvelope<T>;
|
|
509
|
+
} else {
|
|
510
|
+
try {
|
|
511
|
+
json = JSON.parse(text) as ApiEnvelope<T>;
|
|
512
|
+
} catch {
|
|
513
|
+
// Not a JSON body — treat as generic API error
|
|
514
|
+
throw mapHttpError(
|
|
515
|
+
response.status,
|
|
516
|
+
null,
|
|
517
|
+
text || response.statusText,
|
|
518
|
+
response.headers,
|
|
519
|
+
);
|
|
520
|
+
}
|
|
508
521
|
}
|
|
509
522
|
|
|
510
523
|
if (!response.ok) {
|
|
@@ -554,7 +567,7 @@ export class Transport {
|
|
|
554
567
|
const isTimeout =
|
|
555
568
|
err instanceof DOMException && err.name === "AbortError";
|
|
556
569
|
// Only retry on genuine network failures (fetch throws TypeError) or timeouts.
|
|
557
|
-
//
|
|
570
|
+
// Other unexpected errors propagate immediately.
|
|
558
571
|
const isNetworkError = err instanceof TypeError;
|
|
559
572
|
|
|
560
573
|
if (
|