@to11ai/sdk 2.0.0-rc.3 → 2.0.0-rc.4
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 +16 -41
- package/dist/client.d.ts +17 -37
- package/dist/client.js +14 -50
- package/dist/errors.cjs +19 -24
- package/dist/errors.d.ts +18 -46
- package/dist/errors.js +19 -24
- package/dist/gateway.cjs +18 -12
- package/dist/gateway.d.ts +19 -20
- package/dist/gateway.js +18 -12
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/types.gen.d.ts +103 -0
- package/dist/generated/zod.gen.d.ts +55 -12
- package/dist/prompts/resource.cjs +13 -28
- package/dist/prompts/resource.d.ts +8 -14
- package/dist/prompts/resource.js +17 -28
- package/dist/prompts/shape.d.ts +1 -1
- package/dist/prompts/types.d.ts +17 -13
- package/dist/transport.d.ts +2 -6
- package/package.json +3 -11
- package/src/client.ts +31 -118
- package/src/context.ts +3 -5
- package/src/errors.ts +34 -78
- package/src/gateway.ts +44 -39
- package/src/generated/index.ts +1 -1
- package/src/generated/types.gen.ts +108 -0
- package/src/generated/zod.gen.ts +46 -0
- package/src/prompts/resource.ts +36 -74
- package/src/prompts/shape.ts +1 -1
- package/src/prompts/types.ts +17 -14
- package/src/transport.ts +53 -40
- package/dist/prompts/cache.d.ts +0 -58
- package/dist/routingRules/resource.cjs +0 -138
- package/dist/routingRules/resource.js +0 -98
- package/src/prompts/cache.ts +0 -153
package/dist/prompts/resource.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// src/prompts/resource.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
MissingLabelError,
|
|
4
|
+
To11aiApiError,
|
|
5
|
+
To11aiNetworkError
|
|
6
|
+
} from "../errors";
|
|
4
7
|
import { zResolvedPrompt } from "../generated/zod.gen";
|
|
5
|
-
import { buildRenderCacheKey, PromptCache } from "./cache";
|
|
6
8
|
import { shapePrompt } from "./shape";
|
|
7
9
|
import { ENV_SLUG_REGEX } from "./types";
|
|
8
|
-
var zResolvedPromptEnvelope = zResolvedPrompt.partial({ releaseId: true })
|
|
10
|
+
var zResolvedPromptEnvelope = zResolvedPrompt.partial({ releaseId: true });
|
|
9
11
|
function unwrap(envelope) {
|
|
10
12
|
if (envelope.data === null || envelope.data === undefined) {
|
|
11
13
|
throw new Error("API returned success but data is null");
|
|
@@ -85,14 +87,12 @@ function buildLabelEventsQuery(input) {
|
|
|
85
87
|
|
|
86
88
|
class PromptResource {
|
|
87
89
|
transport;
|
|
88
|
-
cache;
|
|
89
90
|
projectId;
|
|
90
91
|
env;
|
|
91
92
|
format;
|
|
92
93
|
onUnknownRole;
|
|
93
|
-
constructor(transport,
|
|
94
|
+
constructor(transport, config) {
|
|
94
95
|
this.transport = transport;
|
|
95
|
-
this.cache = new PromptCache(cacheConfig);
|
|
96
96
|
this.projectId = config?.projectId;
|
|
97
97
|
this.env = config?.env;
|
|
98
98
|
this.format = config?.format;
|
|
@@ -187,21 +187,15 @@ class PromptResource {
|
|
|
187
187
|
if (this.projectId === undefined || this.projectId.trim() === "") {
|
|
188
188
|
throw new Error("[to11ai/sdk] `prompts.render()` requires a `projectId` on the client — pass it to createClient({ projectId, ... }).");
|
|
189
189
|
}
|
|
190
|
-
const
|
|
191
|
-
if (
|
|
192
|
-
throw
|
|
190
|
+
const label = options.label ?? this.env;
|
|
191
|
+
if (label === undefined) {
|
|
192
|
+
throw new MissingLabelError;
|
|
193
193
|
}
|
|
194
|
-
if (!ENV_SLUG_REGEX.test(
|
|
195
|
-
throw new Error(`[to11ai/sdk] \`
|
|
194
|
+
if (!ENV_SLUG_REGEX.test(label)) {
|
|
195
|
+
throw new Error(`[to11ai/sdk] \`label\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(label)}`);
|
|
196
196
|
}
|
|
197
|
-
const { subject, variables,
|
|
198
|
-
const
|
|
199
|
-
if (useCache) {
|
|
200
|
-
const cached = this.cache.get(cacheKey);
|
|
201
|
-
if (cached)
|
|
202
|
-
return structuredClone(cached);
|
|
203
|
-
}
|
|
204
|
-
const body = { slug, labels: [env] };
|
|
197
|
+
const { subject, variables, fallback } = options;
|
|
198
|
+
const body = { slug, labels: [label] };
|
|
205
199
|
if (subject !== undefined)
|
|
206
200
|
body.subject = subject;
|
|
207
201
|
if (variables !== undefined)
|
|
@@ -212,15 +206,10 @@ class PromptResource {
|
|
|
212
206
|
decode: (data) => zResolvedPromptEnvelope.parse(data)
|
|
213
207
|
});
|
|
214
208
|
const raw = unwrap(envelope);
|
|
215
|
-
|
|
216
|
-
const isWeighted = raw.strategy === "weighted" || result.variantName !== undefined;
|
|
217
|
-
const cacheable = !(isWeighted && subject === undefined);
|
|
218
|
-
if (useCache && cacheable) {
|
|
219
|
-
this.cache.set(cacheKey, structuredClone(result));
|
|
220
|
-
}
|
|
221
|
-
return result;
|
|
209
|
+
return normalizeResolvedEnvelope(raw, slug);
|
|
222
210
|
} catch (err) {
|
|
223
|
-
|
|
211
|
+
const transient = err instanceof To11aiNetworkError || err instanceof To11aiApiError && err.statusCode >= 500;
|
|
212
|
+
if (transient && fallback !== undefined) {
|
|
224
213
|
return liftFallbackToRendered(fallback, slug);
|
|
225
214
|
}
|
|
226
215
|
throw err;
|
package/dist/prompts/shape.d.ts
CHANGED
|
@@ -52,5 +52,5 @@ export interface AnthropicRenderedPrompt {
|
|
|
52
52
|
export type RenderResult<F extends RenderFormat | undefined> = F extends "openai" ? OpenAiRenderedPrompt : F extends "anthropic" ? AnthropicRenderedPrompt : RenderedPrompt;
|
|
53
53
|
export declare function shapeOpenAI(prompt: RenderedPrompt, options?: ConvertMessagesOptions): OpenAiRenderedPrompt;
|
|
54
54
|
export declare function shapeAnthropic(prompt: RenderedPrompt, options?: ConvertMessagesOptions): AnthropicRenderedPrompt;
|
|
55
|
-
/** Shape a
|
|
55
|
+
/** Shape a rendered prompt for `format`, or return it neutral when unset. */
|
|
56
56
|
export declare function shapePrompt(prompt: RenderedPrompt, format: RenderFormat | undefined, options?: ConvertMessagesOptions): RenderedPrompt | OpenAiRenderedPrompt | AnthropicRenderedPrompt;
|
package/dist/prompts/types.d.ts
CHANGED
|
@@ -9,13 +9,12 @@ export type PromptStatus = Prompt["status"];
|
|
|
9
9
|
export type PromptVersion = GenPromptVersion;
|
|
10
10
|
export type PromptFormat = PromptVersion["format"];
|
|
11
11
|
export type PromptLabelPointer = GenPromptLabelPointer;
|
|
12
|
-
export type
|
|
13
|
-
export interface
|
|
14
|
-
role:
|
|
12
|
+
export type ChatRole = "system" | "user" | "assistant" | "developer";
|
|
13
|
+
export interface ChatMessage {
|
|
14
|
+
role: ChatRole;
|
|
15
15
|
content: string;
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
}
|
|
18
|
-
export type ChatMessage = TextChatMessage;
|
|
19
18
|
export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
|
|
20
19
|
/** Provider shape for `prompts.render()` output. Omit for the neutral result. */
|
|
21
20
|
export type RenderFormat = "openai" | "anthropic";
|
|
@@ -118,6 +117,13 @@ export interface ListPromptLabelsInput {
|
|
|
118
117
|
promptId: string;
|
|
119
118
|
}
|
|
120
119
|
export type ListPromptLabelsResult = PromptLabelPointer[];
|
|
120
|
+
/**
|
|
121
|
+
* Slug rule for a `render()` label — lowercase-kebab, 1-63 chars. Env slugs are
|
|
122
|
+
* a special case of a label value, so labels are held to the same strict rule
|
|
123
|
+
* (no uppercase, no underscores): a label is a routing key, and case-insensitive
|
|
124
|
+
* routing keys invite silent "production" vs "Production" mismatches. Intentionally
|
|
125
|
+
* strict — do not loosen.
|
|
126
|
+
*/
|
|
121
127
|
export declare const ENV_SLUG_REGEX: RegExp;
|
|
122
128
|
export type BlockRenderRecord = Record<string, "rendered" | "dimmed">;
|
|
123
129
|
export interface RenderedPrompt {
|
|
@@ -164,19 +170,17 @@ export interface RenderedPrompt {
|
|
|
164
170
|
*/
|
|
165
171
|
toolChoice?: NonNullable<ResolvedPrompt["toolChoice"]>;
|
|
166
172
|
}
|
|
167
|
-
export type ResolvedPromptEnvelope = GenResolvedPrompt
|
|
168
|
-
/** Active release strategy. Used to decide weighted-no-subject cache bypass (D8). */
|
|
169
|
-
strategy?: "single" | "weighted";
|
|
170
|
-
};
|
|
173
|
+
export type ResolvedPromptEnvelope = GenResolvedPrompt;
|
|
171
174
|
export interface RenderOptions {
|
|
172
|
-
/**
|
|
173
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Label to resolve this call's prompt version; overrides the client default.
|
|
177
|
+
* When omitted, falls back to the client's `env` (env is a label value).
|
|
178
|
+
*/
|
|
179
|
+
label?: string;
|
|
174
180
|
/** Stable id so a weighted release sends the same caller to the same variant. */
|
|
175
181
|
subject?: string;
|
|
176
182
|
variables?: Record<string, unknown>;
|
|
177
|
-
/**
|
|
178
|
-
cache?: boolean;
|
|
179
|
-
/** Prompt served if the API is unreachable on a network error and cache is empty. */
|
|
183
|
+
/** Prompt served if the API is unreachable on a network error. */
|
|
180
184
|
fallback?: RenderedPrompt;
|
|
181
185
|
/** Provider shape for this call's output; overrides the client default. */
|
|
182
186
|
format?: RenderFormat;
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { BehaviorStore } from "./behaviors/store";
|
|
2
|
-
export
|
|
2
|
+
export interface AuthConfig {
|
|
3
3
|
readonly apiKey: string;
|
|
4
|
-
|
|
5
|
-
} | {
|
|
6
|
-
readonly getAccessToken: () => Promise<string>;
|
|
7
|
-
readonly apiKey?: never;
|
|
8
|
-
};
|
|
4
|
+
}
|
|
9
5
|
export interface TransportConfig {
|
|
10
6
|
readonly baseUrl: string;
|
|
11
7
|
readonly auth: AuthConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@to11ai/sdk",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.4",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,14 +44,6 @@
|
|
|
44
44
|
"require": "./dist/projectEnvironments/resource.cjs",
|
|
45
45
|
"default": "./dist/projectEnvironments/resource.js"
|
|
46
46
|
},
|
|
47
|
-
"./routingRules": {
|
|
48
|
-
"types": "./dist/routingRules/resource.d.ts",
|
|
49
|
-
"bun": "./src/routingRules/resource.ts",
|
|
50
|
-
"deno": "./src/routingRules/resource.ts",
|
|
51
|
-
"import": "./dist/routingRules/resource.js",
|
|
52
|
-
"require": "./dist/routingRules/resource.cjs",
|
|
53
|
-
"default": "./dist/routingRules/resource.js"
|
|
54
|
-
},
|
|
55
47
|
"./errors": {
|
|
56
48
|
"types": "./dist/errors.d.ts",
|
|
57
49
|
"bun": "./src/errors.ts",
|
|
@@ -75,8 +67,8 @@
|
|
|
75
67
|
"scripts": {
|
|
76
68
|
"build": "bun run build:clean && bun run build:esm && bun run build:cjs && bun run build:types",
|
|
77
69
|
"build:clean": "rm -rf dist",
|
|
78
|
-
"build:esm": "bun build src/client.ts src/prompts/resource.ts src/projectEnvironments/resource.ts src/
|
|
79
|
-
"build:cjs": "bun build src/client.ts src/prompts/resource.ts src/projectEnvironments/resource.ts src/
|
|
70
|
+
"build:esm": "bun build src/client.ts src/prompts/resource.ts src/projectEnvironments/resource.ts src/errors.ts src/gateway.ts --outdir dist --target node --format esm --external '*'",
|
|
71
|
+
"build:cjs": "bun build src/client.ts src/prompts/resource.ts src/projectEnvironments/resource.ts src/errors.ts src/gateway.ts --outdir dist --target node --format cjs --external '*' --entry-naming '[dir]/[name].cjs'",
|
|
80
72
|
"build:types": "tsc -p tsconfig.build.json",
|
|
81
73
|
"prepack": "bun run build",
|
|
82
74
|
"codegen": "openapi-ts",
|
package/src/client.ts
CHANGED
|
@@ -8,46 +8,30 @@ import {
|
|
|
8
8
|
} from "./context";
|
|
9
9
|
import { gatewayAuthHeaders } from "./gateway";
|
|
10
10
|
import { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
11
|
-
import type { CacheConfig } from "./prompts/cache";
|
|
12
11
|
import { PromptResource } from "./prompts/resource";
|
|
13
12
|
import {
|
|
14
13
|
ENV_SLUG_REGEX,
|
|
15
14
|
type RenderFormat,
|
|
16
15
|
type UnknownRoleMode,
|
|
17
16
|
} from "./prompts/types";
|
|
18
|
-
import { RoutingRulesResource } from "./routingRules/resource";
|
|
19
17
|
import { Transport } from "./transport";
|
|
20
18
|
|
|
21
|
-
// SDK-behavior delivery (TO11-2100): the resolution store + helpers.
|
|
22
|
-
export {
|
|
23
|
-
BehaviorStore,
|
|
24
|
-
type BehaviorStoreOptions,
|
|
25
|
-
envVarNameForKey,
|
|
26
|
-
type SdkBehaviorEnvelope,
|
|
27
|
-
} from "./behaviors/store";
|
|
28
19
|
export type { TurnAuthContext } from "./context";
|
|
29
20
|
export { Conversation, Session, Turn } from "./context";
|
|
30
21
|
// Re-export all error types for convenience
|
|
31
22
|
export type {
|
|
32
|
-
AmbiguousEnvLabelsReason,
|
|
33
|
-
EnvNotFoundReason,
|
|
34
23
|
NoActiveReleaseReason,
|
|
35
|
-
NoApplicableRouteReason,
|
|
36
24
|
PromptNotFoundReason,
|
|
37
25
|
PromptPolicyViolationReason,
|
|
38
26
|
} from "./errors";
|
|
39
27
|
export {
|
|
40
28
|
// TO11-980 (S9) prompt-resolution typed errors.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
EnvNotFoundError,
|
|
29
|
+
LabelNotFoundError,
|
|
30
|
+
MissingLabelError,
|
|
44
31
|
NoActiveReleaseError,
|
|
45
|
-
NoApplicableRouteError,
|
|
46
32
|
PromptLabelNotRegisteredError,
|
|
47
33
|
PromptNotFoundError,
|
|
48
34
|
PromptPolicyViolationError,
|
|
49
|
-
RuleNotFoundError,
|
|
50
|
-
RuleVersionInvalidSnapshotError,
|
|
51
35
|
To11aiApiError,
|
|
52
36
|
To11aiAuthError,
|
|
53
37
|
To11aiError,
|
|
@@ -75,7 +59,6 @@ export type {
|
|
|
75
59
|
UpdateProjectEnvironmentResult,
|
|
76
60
|
} from "./projectEnvironments/resource";
|
|
77
61
|
export { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
78
|
-
export type { CacheConfig } from "./prompts/cache";
|
|
79
62
|
export type { PromptResourceConfig } from "./prompts/resource";
|
|
80
63
|
export { PromptResource } from "./prompts/resource";
|
|
81
64
|
export type {
|
|
@@ -92,42 +75,9 @@ export type {
|
|
|
92
75
|
RenderedPrompt,
|
|
93
76
|
RenderFormat,
|
|
94
77
|
RenderOptions,
|
|
95
|
-
ResolvedPrompt,
|
|
96
|
-
ResolvedPromptEnvelope,
|
|
97
78
|
UnknownRoleMode,
|
|
98
79
|
} from "./prompts/types";
|
|
99
80
|
export { ENV_SLUG_REGEX } from "./prompts/types";
|
|
100
|
-
export type {
|
|
101
|
-
CreateRuleVersionInput,
|
|
102
|
-
CreateRuleVersionResult,
|
|
103
|
-
GetRuleVersionInput,
|
|
104
|
-
GetRuleVersionResult,
|
|
105
|
-
ListRuleReleasesInput,
|
|
106
|
-
ListRuleReleasesResult,
|
|
107
|
-
ListRuleVersionsInput,
|
|
108
|
-
ListRuleVersionsResult,
|
|
109
|
-
RollbackRuleReleaseInput,
|
|
110
|
-
RollbackRuleReleaseResult,
|
|
111
|
-
RuleModelBinding,
|
|
112
|
-
RuleProviderRef,
|
|
113
|
-
RuleRelease,
|
|
114
|
-
RuleReleaseActorType,
|
|
115
|
-
RuleReleaseApprovalStatus,
|
|
116
|
-
RuleReleaseChangeKind,
|
|
117
|
-
RuleReleaseStrategy,
|
|
118
|
-
RuleReleaseWeight,
|
|
119
|
-
RuleSnapshot,
|
|
120
|
-
RuleStrategy,
|
|
121
|
-
RuleVersion,
|
|
122
|
-
SetRuleReleaseInput,
|
|
123
|
-
SetRuleReleaseResult,
|
|
124
|
-
} from "./routingRules/resource";
|
|
125
|
-
export {
|
|
126
|
-
RoutingRuleReleaseResource,
|
|
127
|
-
RoutingRulesResource,
|
|
128
|
-
RoutingRuleVersionResource,
|
|
129
|
-
} from "./routingRules/resource";
|
|
130
|
-
export type { Transport } from "./transport";
|
|
131
81
|
|
|
132
82
|
// ─── Client options ────────────────────────────────────────────────────────
|
|
133
83
|
|
|
@@ -143,12 +93,11 @@ export interface ClientOptions {
|
|
|
143
93
|
*/
|
|
144
94
|
gatewayUrl?: string;
|
|
145
95
|
/**
|
|
146
|
-
* API key for server-side use. Precedence: this
|
|
147
|
-
* Rejected in browser contexts —
|
|
96
|
+
* API key for server-side use (server, CLI, backend job). Precedence: this
|
|
97
|
+
* option → `TO11_API_KEY` env. Required. Rejected in browser contexts — a
|
|
98
|
+
* to11 API key carries gateway access and must never ship in client code.
|
|
148
99
|
*/
|
|
149
100
|
apiKey?: string;
|
|
150
|
-
/** Token callback for browser / edge contexts — avoids static secrets. */
|
|
151
|
-
getAccessToken?: () => Promise<string>;
|
|
152
101
|
/**
|
|
153
102
|
* Provider API key (BYOK) carried by `openaiOptions()` / `anthropicOptions()`
|
|
154
103
|
* as the provider client's `apiKey`, so a BYOK call is a single
|
|
@@ -183,17 +132,10 @@ export interface ClientOptions {
|
|
|
183
132
|
* via `render(slug, { onUnknownRole })`.
|
|
184
133
|
*/
|
|
185
134
|
onUnknownRole?: UnknownRoleMode;
|
|
186
|
-
/** LRU cache configuration for render(). Defaults: ttlSeconds=300, maxEntries=100 */
|
|
187
|
-
cache?: CacheConfig;
|
|
188
135
|
/** Request timeout in milliseconds. Default: 30_000 */
|
|
189
136
|
timeoutMs?: number;
|
|
190
137
|
/** Max retry attempts for network errors / 5xx. Default: 3 */
|
|
191
138
|
maxRetries?: number;
|
|
192
|
-
/**
|
|
193
|
-
* Purely local overrides for server-evaluated SDK-behavior flags (TO11-2100).
|
|
194
|
-
* An init option here wins over a `TO11_SDK_BEHAVIOR_*` env var. No LaunchDarkly.
|
|
195
|
-
*/
|
|
196
|
-
behaviorOverrides?: Record<string, unknown>;
|
|
197
139
|
}
|
|
198
140
|
|
|
199
141
|
// ─── Provider-client options (openaiOptions / anthropicOptions) ─────────────
|
|
@@ -230,19 +172,10 @@ export type ProviderClientOptions<
|
|
|
230
172
|
export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
231
173
|
readonly prompts: PromptResource<F>;
|
|
232
174
|
readonly projectEnvironments: ProjectEnvironmentResource;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
* var) → server-delivered value (captured from responses the client has
|
|
238
|
-
* already made) → the `codedDefault` passed here. A value whose runtime type
|
|
239
|
-
* disagrees with `codedDefault` falls through to the next tier. The SDK
|
|
240
|
-
* carries no LaunchDarkly dependency; this only reads what the server
|
|
241
|
-
* delivered on the envelope.
|
|
242
|
-
*/
|
|
243
|
-
readonly resolveBehavior: <T>(key: string, codedDefault: T) => T;
|
|
244
|
-
/** Resolved API key (server mode); `undefined` in browser (`getAccessToken`) mode. */
|
|
245
|
-
readonly apiKey: string | undefined;
|
|
175
|
+
/** Resolved API key (option → `TO11_API_KEY`). */
|
|
176
|
+
readonly apiKey: string;
|
|
177
|
+
/** Resolved control-plane base URL (option → `TO11_API_URL` → default). */
|
|
178
|
+
readonly baseUrl: string;
|
|
246
179
|
/** Resolved data-plane gateway URL (option → `TO11_GATEWAY_URL` → default). */
|
|
247
180
|
readonly gatewayUrl: string;
|
|
248
181
|
/**
|
|
@@ -251,6 +184,11 @@ export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
|
251
184
|
* already default to it, so you don't need to pass it back into calls.
|
|
252
185
|
*/
|
|
253
186
|
readonly projectId: string | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* Resolved default serving environment (option → `TO11_ENV`); `undefined`
|
|
189
|
+
* when none is configured. `prompts.render()` already defaults to it.
|
|
190
|
+
*/
|
|
191
|
+
readonly env: string | undefined;
|
|
254
192
|
/** A new session (unit of work). Pass an id to group telemetry by your own id. */
|
|
255
193
|
session(id?: string): Session;
|
|
256
194
|
/**
|
|
@@ -299,9 +237,8 @@ export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
|
299
237
|
* - URLs (`baseUrl` / `gatewayUrl`) — option → env var → built-in default.
|
|
300
238
|
* - `apiKey` / `projectId` — option → env var (no default).
|
|
301
239
|
* - `env` / `format` — option only.
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
* - `getAccessToken` → browser-safe; token fetched per request.
|
|
240
|
+
* Authenticate with `apiKey` (or `TO11_API_KEY`) — required, and server-side
|
|
241
|
+
* only (server, CLI, backend job); constructing with `apiKey` in a browser throws.
|
|
305
242
|
*
|
|
306
243
|
* @example Minimal setup (single call)
|
|
307
244
|
* import { createClient } from "@to11ai/sdk";
|
|
@@ -371,15 +308,7 @@ export function createClient<
|
|
|
371
308
|
)
|
|
372
309
|
.replace(/\/+$/, "")
|
|
373
310
|
.replace(/\/v1$/, "");
|
|
374
|
-
const
|
|
375
|
-
// Explicit token auth suppresses an ambient `TO11_API_KEY` so a shared env
|
|
376
|
-
// (SSR / CI / edge) can't defeat an explicit `getAccessToken`. Only an
|
|
377
|
-
// *explicit* `options.apiKey` alongside `getAccessToken` stays ambiguous and
|
|
378
|
-
// is rejected by the exactly-one check below.
|
|
379
|
-
const apiKey =
|
|
380
|
-
getAccessToken !== undefined
|
|
381
|
-
? options.apiKey
|
|
382
|
-
: pick(options.apiKey, "TO11_API_KEY");
|
|
311
|
+
const apiKey = pick(options.apiKey, "TO11_API_KEY");
|
|
383
312
|
const projectId = pick(options.projectId, "TO11_PROJECT_ID");
|
|
384
313
|
// Default serving env: explicit option → `TO11_ENV` env var — the same
|
|
385
314
|
// `pick(option, "TO11_*")` resolution `apiKey`/`projectId` use (empty option
|
|
@@ -395,7 +324,7 @@ export function createClient<
|
|
|
395
324
|
// undefined in the browser, so only the explicit option can reach here.
|
|
396
325
|
if (isBrowser && options.apiKey !== undefined) {
|
|
397
326
|
throw new Error(
|
|
398
|
-
"[to11ai/sdk] Do not use `apiKey` in browser
|
|
327
|
+
"[to11ai/sdk] Do not use `apiKey` in a browser — a to11 API key carries gateway access and must stay server-side (server, CLI, or backend job).",
|
|
399
328
|
);
|
|
400
329
|
}
|
|
401
330
|
|
|
@@ -422,23 +351,19 @@ export function createClient<
|
|
|
422
351
|
);
|
|
423
352
|
}
|
|
424
353
|
|
|
425
|
-
//
|
|
426
|
-
|
|
427
|
-
const hasGetAccessToken = getAccessToken !== undefined;
|
|
428
|
-
if (hasApiKey === hasGetAccessToken) {
|
|
354
|
+
// `apiKey` is the only auth source and is required.
|
|
355
|
+
if (apiKey === undefined) {
|
|
429
356
|
throw new Error(
|
|
430
|
-
"[to11ai/sdk]
|
|
357
|
+
"[to11ai/sdk] An `apiKey` (or `TO11_API_KEY`) is required.",
|
|
431
358
|
);
|
|
432
359
|
}
|
|
433
360
|
|
|
434
|
-
const auth =
|
|
435
|
-
? ({ apiKey: apiKey as string } as const)
|
|
436
|
-
: ({ getAccessToken: getAccessToken as () => Promise<string> } as const);
|
|
361
|
+
const auth = { apiKey } as const;
|
|
437
362
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
});
|
|
363
|
+
// The SDK-behavior store (TO11-2100) still captures any server-delivered
|
|
364
|
+
// flags off responses, but the public `resolveBehavior` accessor is hidden
|
|
365
|
+
// for the 2.0 surface — kept internal so it can be re-exposed step by step.
|
|
366
|
+
const behaviorStore = new BehaviorStore({ env: processEnv });
|
|
442
367
|
|
|
443
368
|
const transport = new Transport({
|
|
444
369
|
baseUrl,
|
|
@@ -448,24 +373,18 @@ export function createClient<
|
|
|
448
373
|
behaviorStore,
|
|
449
374
|
});
|
|
450
375
|
|
|
451
|
-
const prompts = new PromptResource<F>(transport,
|
|
376
|
+
const prompts = new PromptResource<F>(transport, {
|
|
452
377
|
projectId,
|
|
453
378
|
env,
|
|
454
379
|
format: options.format,
|
|
455
380
|
onUnknownRole: options.onUnknownRole,
|
|
456
381
|
});
|
|
457
382
|
const projectEnvironments = new ProjectEnvironmentResource(transport);
|
|
458
|
-
const routingRules = new RoutingRulesResource(transport);
|
|
459
383
|
|
|
460
384
|
// ── Gateway observability context (session → conversation → turn) ──
|
|
461
|
-
// These build gateway auth headers, so they require a
|
|
462
|
-
//
|
|
385
|
+
// These build gateway auth headers, so they require a projectId; fail loudly
|
|
386
|
+
// rather than emit a broken header bag.
|
|
463
387
|
const gatewayAuthContext = (): TurnAuthContext => {
|
|
464
|
-
if (apiKey === undefined) {
|
|
465
|
-
throw new Error(
|
|
466
|
-
"[to11ai/sdk] session()/turn()/openaiOptions() need an `apiKey` (or `TO11_API_KEY`) — gateway calls require a server-side key. In the browser use `getAccessToken` for control-plane calls only.",
|
|
467
|
-
);
|
|
468
|
-
}
|
|
469
388
|
if (projectId === undefined) {
|
|
470
389
|
throw new Error(
|
|
471
390
|
"[to11ai/sdk] session()/turn() need a `projectId` (or `TO11_PROJECT_ID`).",
|
|
@@ -496,11 +415,6 @@ export function createClient<
|
|
|
496
415
|
defaultBaseURL: string,
|
|
497
416
|
overrides?: T,
|
|
498
417
|
): ProviderClientOptions<T> => {
|
|
499
|
-
if (apiKey === undefined) {
|
|
500
|
-
throw new Error(
|
|
501
|
-
"[to11ai/sdk] openaiOptions()/anthropicOptions() need an `apiKey` (or `TO11_API_KEY`) — gateway calls require a server-side key. In the browser use `getAccessToken` for control-plane calls only.",
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
418
|
if (projectId === undefined) {
|
|
505
419
|
throw new Error(
|
|
506
420
|
"[to11ai/sdk] openaiOptions()/anthropicOptions() need a `projectId` (or `TO11_PROJECT_ID`) — it authenticates the gateway call via `x-to11-project-id`.",
|
|
@@ -530,12 +444,11 @@ export function createClient<
|
|
|
530
444
|
return {
|
|
531
445
|
prompts,
|
|
532
446
|
projectEnvironments,
|
|
533
|
-
routingRules,
|
|
534
|
-
resolveBehavior: (key, codedDefault) =>
|
|
535
|
-
behaviorStore.resolve(key, codedDefault),
|
|
536
447
|
apiKey,
|
|
448
|
+
baseUrl,
|
|
537
449
|
gatewayUrl,
|
|
538
450
|
projectId,
|
|
451
|
+
env,
|
|
539
452
|
session: (id) => new Session(gatewayAuthContext(), id),
|
|
540
453
|
conversation: (id) => clientDefaultSession().conversation(id),
|
|
541
454
|
turn: () => clientDefaultSession().turn(),
|
package/src/context.ts
CHANGED
|
@@ -49,10 +49,6 @@ function newId(): string {
|
|
|
49
49
|
return crypto.randomUUID();
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function provenanceOf(prompt: PromptForHeaders): GatewayPromptProvenance {
|
|
53
|
-
return "metadata" in prompt ? prompt.metadata : prompt;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
52
|
/**
|
|
57
53
|
* One agent turn — a single trace. A turn's `traceparent` is fixed for its
|
|
58
54
|
* lifetime, so every LLM-call made under it groups into one trace.
|
|
@@ -105,7 +101,9 @@ export class Turn {
|
|
|
105
101
|
traceparent: this.traceparent,
|
|
106
102
|
};
|
|
107
103
|
if (prompt !== undefined) {
|
|
108
|
-
|
|
104
|
+
// gatewayPromptHeaders accepts a RenderedPrompt or a format-shaped
|
|
105
|
+
// result and unwraps `metadata` itself.
|
|
106
|
+
Object.assign(headers, gatewayPromptHeaders(prompt));
|
|
109
107
|
}
|
|
110
108
|
return headers;
|
|
111
109
|
}
|
package/src/errors.ts
CHANGED
|
@@ -342,60 +342,54 @@ export class PromptNotFoundError extends To11aiApiError {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
/**
|
|
345
|
-
*
|
|
345
|
+
* Thrown when the label supplied to `prompts.render()` does not resolve to an
|
|
346
|
+
* existing (active) label on the server. Surfaced from the server's
|
|
347
|
+
* `ENV_NOT_FOUND` code; `label` carries the rejected slug when the server
|
|
348
|
+
* echoes it.
|
|
346
349
|
*
|
|
347
|
-
* `
|
|
348
|
-
*
|
|
349
|
-
* CLIENT-side, eagerly, before any request (R4 / AC4); `env` is absent.
|
|
350
|
-
* - `"unknown"` — an env was supplied but the server's registry has no
|
|
351
|
-
* such (active) env. Surfaced from the `ENV_NOT_FOUND` server code; `env`
|
|
352
|
-
* carries the rejected slug when the server echoes it.
|
|
350
|
+
* This is distinct from `MissingLabelError`, which is raised client-side when
|
|
351
|
+
* no label was supplied at all.
|
|
353
352
|
*/
|
|
354
|
-
export
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Thrown when no serving environment can be resolved for a `prompts.render()`
|
|
361
|
-
* call. One class, two `reason.source` discriminants (see
|
|
362
|
-
* `EnvNotFoundReason`): client-eager `"missing"` (R4) and server-forwarded
|
|
363
|
-
* `"unknown"` (`ENV_NOT_FOUND`).
|
|
364
|
-
*
|
|
365
|
-
* The client-eager variant carries no `statusCode`/`errorCode` from the wire
|
|
366
|
-
* (no request was made); it reports status `0` and errorCode `ENV_NOT_FOUND`
|
|
367
|
-
* for a uniform catch surface.
|
|
368
|
-
*/
|
|
369
|
-
export class EnvNotFoundError extends To11aiApiError {
|
|
370
|
-
readonly reason: EnvNotFoundReason;
|
|
353
|
+
export class LabelNotFoundError extends To11aiApiError {
|
|
354
|
+
/** The label slug that could not be found, when the server echoes it. */
|
|
355
|
+
readonly label?: string;
|
|
371
356
|
|
|
372
357
|
constructor(
|
|
373
358
|
message: string,
|
|
374
|
-
|
|
359
|
+
label: string | undefined,
|
|
375
360
|
details: unknown,
|
|
376
|
-
// Required (no misleading default): the client-eager `missing()` variant
|
|
377
|
-
// passes 0 (no HTTP call) and the transport mapper passes the real server
|
|
378
|
-
// status, so a hardcoded default would never reflect reality.
|
|
379
361
|
statusCode: number,
|
|
380
362
|
) {
|
|
363
|
+
// The wire code is unchanged (`ENV_NOT_FOUND`); only the SDK class name
|
|
364
|
+
// is label-oriented, decoupled from the server error code.
|
|
381
365
|
super(message, statusCode, "ENV_NOT_FOUND", details);
|
|
382
|
-
this.name = "
|
|
383
|
-
this.
|
|
366
|
+
this.name = "LabelNotFoundError";
|
|
367
|
+
this.label = label;
|
|
384
368
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
385
369
|
}
|
|
386
370
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
371
|
+
static is(err: unknown): err is LabelNotFoundError {
|
|
372
|
+
return err instanceof LabelNotFoundError;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Thrown CLIENT-side, eagerly (before any request), when `prompts.render()` is
|
|
378
|
+
* called but no label is resolvable at all: none supplied per call, and no
|
|
379
|
+
* client `env` (or `TO11_ENV`) to fall back to. A usage error, not a lookup
|
|
380
|
+
* failure — distinct from `LabelNotFoundError`.
|
|
381
|
+
*/
|
|
382
|
+
export class MissingLabelError extends To11aiError {
|
|
383
|
+
constructor(
|
|
384
|
+
message = "[to11ai/sdk] No label resolvable for prompts.render(): none supplied per call, and no client env (or TO11_ENV) to fall back to. Pass `label` to render(slug, { label }) or set `env` on createClient.",
|
|
385
|
+
) {
|
|
386
|
+
super(message);
|
|
387
|
+
this.name = "MissingLabelError";
|
|
388
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
395
389
|
}
|
|
396
390
|
|
|
397
|
-
static is(err: unknown): err is
|
|
398
|
-
return err instanceof
|
|
391
|
+
static is(err: unknown): err is MissingLabelError {
|
|
392
|
+
return err instanceof MissingLabelError;
|
|
399
393
|
}
|
|
400
394
|
}
|
|
401
395
|
|
|
@@ -480,44 +474,6 @@ export class PromptPolicyViolationError extends To11aiApiError {
|
|
|
480
474
|
}
|
|
481
475
|
}
|
|
482
476
|
|
|
483
|
-
/**
|
|
484
|
-
* Reason payload for `AmbiguousEnvLabelsError`.
|
|
485
|
-
*
|
|
486
|
-
* Carried when the supplied env-label matched more than one candidate
|
|
487
|
-
* version and the server cannot pick deterministically
|
|
488
|
-
* (`AMBIGUOUS_ENV_LABELS`).
|
|
489
|
-
*/
|
|
490
|
-
export interface AmbiguousEnvLabelsReason {
|
|
491
|
-
env?: string;
|
|
492
|
-
slug?: string;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* Thrown when the env→label resolution is ambiguous on the server
|
|
497
|
-
* (`AMBIGUOUS_ENV_LABELS`) — the label matched multiple candidates and the
|
|
498
|
-
* server declines to guess. Surfaces (rather than 500ing) so callers get a
|
|
499
|
-
* typed, actionable error.
|
|
500
|
-
*/
|
|
501
|
-
export class AmbiguousEnvLabelsError extends To11aiApiError {
|
|
502
|
-
readonly reason: AmbiguousEnvLabelsReason;
|
|
503
|
-
|
|
504
|
-
constructor(
|
|
505
|
-
message: string,
|
|
506
|
-
reason: AmbiguousEnvLabelsReason,
|
|
507
|
-
details?: unknown,
|
|
508
|
-
statusCode = 409,
|
|
509
|
-
) {
|
|
510
|
-
super(message, statusCode, "AMBIGUOUS_ENV_LABELS", details);
|
|
511
|
-
this.name = "AmbiguousEnvLabelsError";
|
|
512
|
-
this.reason = reason;
|
|
513
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
static is(err: unknown): err is AmbiguousEnvLabelsError {
|
|
517
|
-
return err instanceof AmbiguousEnvLabelsError;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
477
|
/**
|
|
522
478
|
* Thrown when version create rejects the snapshot for a structural
|
|
523
479
|
* reason — invalid variant params, malformed `when` clause, illegal
|