@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
package/dist/client.d.ts
CHANGED
|
@@ -1,87 +1,175 @@
|
|
|
1
|
+
import { type Conversation, Session, type Turn } from "./context";
|
|
1
2
|
import { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
2
|
-
import type { CacheConfig } from "./prompts/cache";
|
|
3
3
|
import { PromptResource } from "./prompts/resource";
|
|
4
|
-
import {
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export {
|
|
8
|
-
export
|
|
4
|
+
import { type RenderFormat, type UnknownRoleMode } from "./prompts/types";
|
|
5
|
+
export type { TurnAuthContext } from "./context";
|
|
6
|
+
export { Conversation, Session, Turn } from "./context";
|
|
7
|
+
export type { NoActiveReleaseReason, PromptNotFoundReason, PromptPolicyViolationReason, } from "./errors";
|
|
8
|
+
export { LabelNotFoundError, MissingLabelError, NoActiveReleaseError, PromptLabelNotRegisteredError, PromptNotFoundError, PromptPolicyViolationError, To11aiApiError, To11aiAuthError, To11aiError, To11aiNetworkError, To11aiRateLimitError, To11aiValidationError, UnknownRoleError, } from "./errors";
|
|
9
|
+
export type { ConvertMessagesOptions, GatewayAuthOptions } from "./gateway";
|
|
9
10
|
export { gatewayAuthHeaders, gatewayPromptHeaders } from "./gateway";
|
|
10
11
|
export type { ArchiveProjectEnvironmentInput, ArchiveProjectEnvironmentResult, CreateProjectEnvironmentInput, CreateProjectEnvironmentResult, GetProjectEnvironmentInput, GetProjectEnvironmentResult, ListProjectEnvironmentsInput, ListProjectEnvironmentsResult, LivePointerCounts, ProjectEnvironment, RestoreProjectEnvironmentInput, RestoreProjectEnvironmentResult, UpdateProjectEnvironmentInput, UpdateProjectEnvironmentResult, } from "./projectEnvironments/resource";
|
|
11
12
|
export { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
12
|
-
export type { CacheConfig } from "./prompts/cache";
|
|
13
13
|
export type { PromptResourceConfig } from "./prompts/resource";
|
|
14
14
|
export { PromptResource } from "./prompts/resource";
|
|
15
|
-
export type {
|
|
15
|
+
export type { AnthropicRenderedPrompt, OpenAiRenderedPrompt, PromptConfig, PromptMetadata, RenderResult, } from "./prompts/shape";
|
|
16
|
+
export type { BlockRenderRecord, RenderedChatMessage, RenderedPrompt, RenderFormat, RenderOptions, UnknownRoleMode, } from "./prompts/types";
|
|
16
17
|
export { ENV_SLUG_REGEX } from "./prompts/types";
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
18
|
+
export interface ClientOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Control-plane base URL. Precedence: this option → `TO11_API_URL` env →
|
|
21
|
+
* `https://api.to11.ai`.
|
|
22
|
+
*/
|
|
23
|
+
baseUrl?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Data-plane gateway URL (the app's provider-client `baseURL`). Precedence:
|
|
26
|
+
* this option → `TO11_GATEWAY_URL` env → `https://gw.to11.ai`.
|
|
27
|
+
*/
|
|
28
|
+
gatewayUrl?: string;
|
|
29
|
+
/**
|
|
30
|
+
* API key for server-side use (server, CLI, backend job). Precedence: this
|
|
31
|
+
* option → `TO11_API_KEY` env. Required. Rejected in browser contexts — a
|
|
32
|
+
* to11 API key carries gateway access and must never ship in client code.
|
|
33
|
+
*/
|
|
34
|
+
apiKey?: string;
|
|
33
35
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* Provider API key (BYOK) carried by `openaiOptions()` / `anthropicOptions()`
|
|
37
|
+
* as the provider client's `apiKey`, so a BYOK call is a single
|
|
38
|
+
* `new OpenAI(to11.openaiOptions())`. When omitted, those helpers fall back to
|
|
39
|
+
* the to11 `apiKey` as a placeholder (the managed / server-side-credential
|
|
40
|
+
* path). Option only — no env fallback. Whether the gateway actually uses this
|
|
41
|
+
* key depends on the provider's passthrough mode; otherwise the project's
|
|
42
|
+
* stored credential wins.
|
|
43
|
+
*/
|
|
44
|
+
providerApiKey?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Project the client is bound to. Precedence: this option → `TO11_PROJECT_ID`
|
|
47
|
+
* env. Required for `prompts.render()` and the gateway context helpers.
|
|
39
48
|
*/
|
|
40
49
|
projectId?: string;
|
|
41
50
|
/**
|
|
42
|
-
* Default serving environment for `prompts.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* uppercase / 64+-char values throw at construction with a loud
|
|
47
|
-
* `[to11ai/sdk]` message before any request hits the wire.
|
|
51
|
+
* Default serving environment for `prompts.render(slug)`, inherited by every
|
|
52
|
+
* render unless overridden per call. Precedence: this option → `TO11_ENV`
|
|
53
|
+
* env. Validated eagerly against the project-environments slug rule
|
|
54
|
+
* (`^[a-z0-9-]{1,63}$`).
|
|
48
55
|
*/
|
|
49
56
|
env?: string;
|
|
50
|
-
/**
|
|
51
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Default provider shape for `prompts.render()` output (`"openai"` |
|
|
59
|
+
* `"anthropic"`). Omit for the neutral result. Per-call override allowed.
|
|
60
|
+
*/
|
|
61
|
+
format?: RenderFormat;
|
|
62
|
+
/**
|
|
63
|
+
* Default policy for a message with an unrecognized role while shaping
|
|
64
|
+
* `render({ format })` output: `"drop"` (default, silent), `"warn"` (drop +
|
|
65
|
+
* `console.warn`), or `"error"` (throw `UnknownRoleError`). Per-call override
|
|
66
|
+
* via `render(slug, { onUnknownRole })`.
|
|
67
|
+
*/
|
|
68
|
+
onUnknownRole?: UnknownRoleMode;
|
|
52
69
|
/** Request timeout in milliseconds. Default: 30_000 */
|
|
53
70
|
timeoutMs?: number;
|
|
54
71
|
/** Max retry attempts for network errors / 5xx. Default: 3 */
|
|
55
72
|
maxRetries?: number;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Overrides accepted by `openaiOptions()` / `anthropicOptions()`. The three
|
|
76
|
+
* known fields are merged (`apiKey` / `baseURL` override; `defaultHeaders`
|
|
77
|
+
* shallow-merges over the tenant-auth headers, caller wins); any other keys —
|
|
78
|
+
* `timeout`, `maxRetries`, `fetch`, … — pass through untouched to the provider
|
|
79
|
+
* client, so `new OpenAI(to11.openaiOptions({ apiKey, timeout }))` needs no
|
|
80
|
+
* outer spread.
|
|
81
|
+
*/
|
|
82
|
+
export interface ProviderClientOverrides {
|
|
83
|
+
apiKey?: string;
|
|
84
|
+
baseURL?: string;
|
|
85
|
+
defaultHeaders?: Record<string, string>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The spread-ready result of `openaiOptions()` / `anthropicOptions()`: the three
|
|
89
|
+
* managed fields plus whatever passthrough keys the caller supplied (their types
|
|
90
|
+
* preserved), so it drops straight into `new OpenAI(...)` / `new Anthropic(...)`.
|
|
91
|
+
*/
|
|
92
|
+
export type ProviderClientOptions<T extends ProviderClientOverrides = ProviderClientOverrides> = Omit<T, "apiKey" | "baseURL" | "defaultHeaders"> & {
|
|
93
|
+
baseURL: string;
|
|
94
|
+
apiKey: string;
|
|
95
|
+
defaultHeaders: Record<string, string>;
|
|
64
96
|
};
|
|
65
|
-
export interface To11aiClient {
|
|
66
|
-
readonly prompts: PromptResource
|
|
97
|
+
export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
98
|
+
readonly prompts: PromptResource<F>;
|
|
67
99
|
readonly projectEnvironments: ProjectEnvironmentResource;
|
|
68
|
-
|
|
100
|
+
/** Resolved API key (option → `TO11_API_KEY`). */
|
|
101
|
+
readonly apiKey: string;
|
|
102
|
+
/** Resolved control-plane base URL (option → `TO11_API_URL` → default). */
|
|
103
|
+
readonly baseUrl: string;
|
|
104
|
+
/** Resolved data-plane gateway URL (option → `TO11_GATEWAY_URL` → default). */
|
|
105
|
+
readonly gatewayUrl: string;
|
|
106
|
+
/**
|
|
107
|
+
* Resolved project id (option → `TO11_PROJECT_ID`); `undefined` when none is
|
|
108
|
+
* configured. Read-only, for your own logging / manual headers — `prompts.*`
|
|
109
|
+
* already default to it, so you don't need to pass it back into calls.
|
|
110
|
+
*/
|
|
111
|
+
readonly projectId: string | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Resolved default serving environment (option → `TO11_ENV`); `undefined`
|
|
114
|
+
* when none is configured. `prompts.render()` already defaults to it.
|
|
115
|
+
*/
|
|
116
|
+
readonly env: string | undefined;
|
|
117
|
+
/** A new session (unit of work). Pass an id to group telemetry by your own id. */
|
|
118
|
+
session(id?: string): Session;
|
|
119
|
+
/**
|
|
120
|
+
* A conversation in the client's default session (for side / parallel agents).
|
|
121
|
+
*
|
|
122
|
+
* @example Two agents under one session
|
|
123
|
+
* const research = to11.conversation(); // a separate thread from to11.turn()'s default
|
|
124
|
+
* const res = await openai.chat.completions.create(
|
|
125
|
+
* { ...researchPrompt.config, messages },
|
|
126
|
+
* { headers: research.turn().headers(researchPrompt) },
|
|
127
|
+
* );
|
|
128
|
+
*/
|
|
129
|
+
conversation(id?: string): Conversation;
|
|
130
|
+
/** A turn in the client's default session + default conversation. */
|
|
131
|
+
turn(): Turn;
|
|
132
|
+
/**
|
|
133
|
+
* Spread-ready options for `new OpenAI(...)` targeting the gateway:
|
|
134
|
+
* `{ baseURL, apiKey, defaultHeaders }` (baseURL carries `/v1`). `defaultHeaders`
|
|
135
|
+
* holds the static tenant auth, so the client authenticates on its own; add
|
|
136
|
+
* `turn().headers(prompt)` per call for trace + prompt provenance. Pass
|
|
137
|
+
* `overrides` to change `apiKey`/`baseURL`, merge extra `defaultHeaders`, or
|
|
138
|
+
* forward any other provider-SDK option (`timeout`, …).
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* const openai = new OpenAI(to11.openaiOptions());
|
|
142
|
+
* @example BYOK + a provider-SDK option, no outer spread
|
|
143
|
+
* const openai = new OpenAI(to11.openaiOptions({ apiKey: MY_KEY, timeout: 60_000 }));
|
|
144
|
+
*/
|
|
145
|
+
openaiOptions<T extends ProviderClientOverrides = ProviderClientOverrides>(overrides?: T): ProviderClientOptions<T>;
|
|
69
146
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* already made) → the `codedDefault` passed here. A value whose runtime type
|
|
74
|
-
* disagrees with `codedDefault` falls through to the next tier. The SDK
|
|
75
|
-
* carries no LaunchDarkly dependency; this only reads what the server
|
|
76
|
-
* delivered on the envelope.
|
|
147
|
+
* Spread-ready options for `new Anthropic(...)` targeting the gateway root
|
|
148
|
+
* (the Anthropic SDK appends `/v1/messages` itself). Same shape and merge
|
|
149
|
+
* rules as {@link To11aiClient.openaiOptions}.
|
|
77
150
|
*/
|
|
78
|
-
|
|
151
|
+
anthropicOptions<T extends ProviderClientOverrides = ProviderClientOverrides>(overrides?: T): ProviderClientOptions<T>;
|
|
79
152
|
}
|
|
80
153
|
/**
|
|
81
|
-
* Create a to11ai SDK client.
|
|
154
|
+
* Create a to11ai SDK client. Resolution precedence differs per option:
|
|
155
|
+
* - URLs (`baseUrl` / `gatewayUrl`) — option → env var → built-in default.
|
|
156
|
+
* - `apiKey` / `projectId` — option → env var (no default).
|
|
157
|
+
* - `env` / `format` — option only.
|
|
158
|
+
* Authenticate with `apiKey` (or `TO11_API_KEY`) — required, and server-side
|
|
159
|
+
* only (server, CLI, backend job); constructing with `apiKey` in a browser throws.
|
|
160
|
+
*
|
|
161
|
+
* @example Minimal setup (single call)
|
|
162
|
+
* import { createClient } from "@to11ai/sdk";
|
|
163
|
+
* import OpenAI from "openai";
|
|
82
164
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
165
|
+
* const to11 = createClient({ env: "prod", format: "openai" });
|
|
166
|
+
* const openai = new OpenAI(to11.openaiOptions());
|
|
167
|
+
* const prompt = await to11.prompts.render("weather-concierge", { variables: { city: "NYC" } });
|
|
168
|
+
* const res = await openai.chat.completions.create(
|
|
169
|
+
* { ...prompt.config, messages: prompt.messages },
|
|
170
|
+
* { headers: to11.turn().headers(prompt) },
|
|
171
|
+
* );
|
|
86
172
|
*/
|
|
87
|
-
export declare function createClient(options
|
|
173
|
+
export declare function createClient<const F extends RenderFormat | undefined = undefined>(options?: Omit<ClientOptions, "format"> & {
|
|
174
|
+
format?: F;
|
|
175
|
+
}): To11aiClient<F>;
|
package/dist/client.js
CHANGED
|
@@ -1,48 +1,58 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
2
|
import { BehaviorStore } from "./behaviors/store";
|
|
3
|
+
import { DEFAULT_API_URL, DEFAULT_GATEWAY_URL } from "./config";
|
|
4
|
+
import {
|
|
5
|
+
Session
|
|
6
|
+
} from "./context";
|
|
7
|
+
import { gatewayAuthHeaders } from "./gateway";
|
|
3
8
|
import { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
4
9
|
import { PromptResource } from "./prompts/resource";
|
|
5
|
-
import { ENV_SLUG_REGEX } from "./prompts/types";
|
|
6
|
-
import { RoutingRulesResource } from "./routingRules/resource";
|
|
7
|
-
import { Transport } from "./transport";
|
|
8
10
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "./
|
|
11
|
+
ENV_SLUG_REGEX
|
|
12
|
+
} from "./prompts/types";
|
|
13
|
+
import { Transport } from "./transport";
|
|
14
|
+
import { Conversation, Session as Session2, Turn } from "./context";
|
|
12
15
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
EnvNotFoundError,
|
|
16
|
+
LabelNotFoundError,
|
|
17
|
+
MissingLabelError,
|
|
16
18
|
NoActiveReleaseError,
|
|
17
|
-
NoApplicableRouteError,
|
|
18
19
|
PromptLabelNotRegisteredError,
|
|
19
20
|
PromptNotFoundError,
|
|
20
21
|
PromptPolicyViolationError,
|
|
21
|
-
RuleNotFoundError,
|
|
22
|
-
RuleVersionInvalidSnapshotError,
|
|
23
22
|
To11aiApiError,
|
|
24
23
|
To11aiAuthError,
|
|
25
24
|
To11aiError,
|
|
26
25
|
To11aiNetworkError,
|
|
27
26
|
To11aiRateLimitError,
|
|
28
|
-
To11aiValidationError
|
|
27
|
+
To11aiValidationError,
|
|
28
|
+
UnknownRoleError
|
|
29
29
|
} from "./errors";
|
|
30
|
-
import { gatewayAuthHeaders, gatewayPromptHeaders } from "./gateway";
|
|
30
|
+
import { gatewayAuthHeaders as gatewayAuthHeaders2, gatewayPromptHeaders } from "./gateway";
|
|
31
31
|
import { ProjectEnvironmentResource as ProjectEnvironmentResource2 } from "./projectEnvironments/resource";
|
|
32
32
|
import { PromptResource as PromptResource2 } from "./prompts/resource";
|
|
33
33
|
import { ENV_SLUG_REGEX as ENV_SLUG_REGEX2 } from "./prompts/types";
|
|
34
|
-
|
|
35
|
-
RoutingRuleReleaseResource,
|
|
36
|
-
RoutingRulesResource as RoutingRulesResource2,
|
|
37
|
-
RoutingRuleVersionResource
|
|
38
|
-
} from "./routingRules/resource";
|
|
39
|
-
function createClient(options) {
|
|
34
|
+
function createClient(options = {}) {
|
|
40
35
|
const isDomBrowser = typeof globalThis === "object" && typeof globalThis.document !== "undefined";
|
|
41
36
|
const workerLikeGlobal = globalThis;
|
|
42
37
|
const isBunMainThread = workerLikeGlobal.Bun?.isMainThread === true;
|
|
43
38
|
const isWorkerBrowser = typeof globalThis === "object" && (typeof workerLikeGlobal.importScripts === "function" || !isBunMainThread && typeof workerLikeGlobal.postMessage === "function" && typeof workerLikeGlobal.onmessage !== "undefined");
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const isBrowser = isDomBrowser || isWorkerBrowser;
|
|
40
|
+
const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
|
|
41
|
+
const pick = (opt, envKey) => {
|
|
42
|
+
const fromOpt = opt?.trim();
|
|
43
|
+
if (fromOpt)
|
|
44
|
+
return fromOpt;
|
|
45
|
+
const fromEnv = processEnv?.[envKey]?.trim();
|
|
46
|
+
return fromEnv ? fromEnv : undefined;
|
|
47
|
+
};
|
|
48
|
+
const baseUrl = pick(options.baseUrl, "TO11_API_URL") ?? DEFAULT_API_URL;
|
|
49
|
+
const gatewayUrl = (pick(options.gatewayUrl, "TO11_GATEWAY_URL") ?? DEFAULT_GATEWAY_URL).replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
50
|
+
const apiKey = pick(options.apiKey, "TO11_API_KEY");
|
|
51
|
+
const projectId = pick(options.projectId, "TO11_PROJECT_ID");
|
|
52
|
+
const env = pick(options.env, "TO11_ENV");
|
|
53
|
+
const providerApiKey = options.providerApiKey?.trim() || undefined;
|
|
54
|
+
if (isBrowser && options.apiKey !== undefined) {
|
|
55
|
+
throw new Error("[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).");
|
|
46
56
|
}
|
|
47
57
|
if (options.apiKey !== undefined && options.apiKey.trim() === "") {
|
|
48
58
|
throw new Error("[to11ai/sdk] `apiKey` must not be an empty string.");
|
|
@@ -50,68 +60,98 @@ function createClient(options) {
|
|
|
50
60
|
if (options.projectId !== undefined && options.projectId.trim() === "") {
|
|
51
61
|
throw new Error("[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.");
|
|
52
62
|
}
|
|
53
|
-
if (options.env !== undefined &&
|
|
54
|
-
throw new Error(
|
|
63
|
+
if (options.env !== undefined && options.env.trim() === "") {
|
|
64
|
+
throw new Error("[to11ai/sdk] `env` must not be an empty string — omit it or pass a valid env slug.");
|
|
55
65
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const getAccessToken = options.getAccessToken;
|
|
59
|
-
if (hasApiKey === hasGetAccessToken) {
|
|
60
|
-
throw new Error("[to11ai/sdk] Provide exactly one of `apiKey` (server) or `getAccessToken` (browser).");
|
|
66
|
+
if (env !== undefined && !ENV_SLUG_REGEX.test(env)) {
|
|
67
|
+
throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
|
|
61
68
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
env: processEnv
|
|
68
|
-
});
|
|
69
|
+
if (apiKey === undefined) {
|
|
70
|
+
throw new Error("[to11ai/sdk] An `apiKey` (or `TO11_API_KEY`) is required.");
|
|
71
|
+
}
|
|
72
|
+
const auth = { apiKey };
|
|
73
|
+
const behaviorStore = new BehaviorStore({ env: processEnv });
|
|
69
74
|
const transport = new Transport({
|
|
70
|
-
baseUrl
|
|
75
|
+
baseUrl,
|
|
71
76
|
auth,
|
|
72
77
|
timeoutMs: options.timeoutMs,
|
|
73
78
|
maxRetries: options.maxRetries,
|
|
74
79
|
behaviorStore
|
|
75
80
|
});
|
|
76
|
-
const prompts = new PromptResource(transport,
|
|
77
|
-
projectId
|
|
78
|
-
env
|
|
81
|
+
const prompts = new PromptResource(transport, {
|
|
82
|
+
projectId,
|
|
83
|
+
env,
|
|
84
|
+
format: options.format,
|
|
85
|
+
onUnknownRole: options.onUnknownRole
|
|
79
86
|
});
|
|
80
87
|
const projectEnvironments = new ProjectEnvironmentResource(transport);
|
|
81
|
-
const
|
|
88
|
+
const gatewayAuthContext = () => {
|
|
89
|
+
if (projectId === undefined) {
|
|
90
|
+
throw new Error("[to11ai/sdk] session()/turn() need a `projectId` (or `TO11_PROJECT_ID`).");
|
|
91
|
+
}
|
|
92
|
+
return env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId };
|
|
93
|
+
};
|
|
94
|
+
let defaultSession;
|
|
95
|
+
const clientDefaultSession = () => {
|
|
96
|
+
if (defaultSession === undefined) {
|
|
97
|
+
defaultSession = new Session(gatewayAuthContext());
|
|
98
|
+
}
|
|
99
|
+
return defaultSession;
|
|
100
|
+
};
|
|
101
|
+
const gatewayClientOptions = (defaultBaseURL, overrides) => {
|
|
102
|
+
if (projectId === undefined) {
|
|
103
|
+
throw new Error("[to11ai/sdk] openaiOptions()/anthropicOptions() need a `projectId` (or `TO11_PROJECT_ID`) — it authenticates the gateway call via `x-to11-project-id`.");
|
|
104
|
+
}
|
|
105
|
+
const authHeaders = gatewayAuthHeaders(env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId });
|
|
106
|
+
const {
|
|
107
|
+
apiKey: overrideApiKey,
|
|
108
|
+
baseURL: overrideBaseURL,
|
|
109
|
+
defaultHeaders: overrideHeaders,
|
|
110
|
+
...passthrough
|
|
111
|
+
} = overrides ?? {};
|
|
112
|
+
return {
|
|
113
|
+
...passthrough,
|
|
114
|
+
baseURL: overrideBaseURL ?? defaultBaseURL,
|
|
115
|
+
apiKey: overrideApiKey ?? providerApiKey ?? apiKey,
|
|
116
|
+
defaultHeaders: { ...authHeaders, ...overrideHeaders }
|
|
117
|
+
};
|
|
118
|
+
};
|
|
82
119
|
return {
|
|
83
120
|
prompts,
|
|
84
121
|
projectEnvironments,
|
|
85
|
-
|
|
86
|
-
|
|
122
|
+
apiKey,
|
|
123
|
+
baseUrl,
|
|
124
|
+
gatewayUrl,
|
|
125
|
+
projectId,
|
|
126
|
+
env,
|
|
127
|
+
session: (id) => new Session(gatewayAuthContext(), id),
|
|
128
|
+
conversation: (id) => clientDefaultSession().conversation(id),
|
|
129
|
+
turn: () => clientDefaultSession().turn(),
|
|
130
|
+
openaiOptions: (overrides) => gatewayClientOptions(`${gatewayUrl}/v1`, overrides),
|
|
131
|
+
anthropicOptions: (overrides) => gatewayClientOptions(gatewayUrl, overrides)
|
|
87
132
|
};
|
|
88
133
|
}
|
|
89
134
|
export {
|
|
90
135
|
gatewayPromptHeaders,
|
|
91
|
-
gatewayAuthHeaders,
|
|
92
|
-
envVarNameForKey,
|
|
136
|
+
gatewayAuthHeaders2 as gatewayAuthHeaders,
|
|
93
137
|
createClient,
|
|
138
|
+
UnknownRoleError,
|
|
139
|
+
Turn,
|
|
94
140
|
To11aiValidationError,
|
|
95
141
|
To11aiRateLimitError,
|
|
96
142
|
To11aiNetworkError,
|
|
97
143
|
To11aiError,
|
|
98
144
|
To11aiAuthError,
|
|
99
145
|
To11aiApiError,
|
|
100
|
-
|
|
101
|
-
RuleNotFoundError,
|
|
102
|
-
RoutingRulesResource2 as RoutingRulesResource,
|
|
103
|
-
RoutingRuleVersionResource,
|
|
104
|
-
RoutingRuleReleaseResource,
|
|
146
|
+
Session2 as Session,
|
|
105
147
|
PromptResource2 as PromptResource,
|
|
106
148
|
PromptPolicyViolationError,
|
|
107
149
|
PromptNotFoundError,
|
|
108
150
|
PromptLabelNotRegisteredError,
|
|
109
151
|
ProjectEnvironmentResource2 as ProjectEnvironmentResource,
|
|
110
|
-
NoApplicableRouteError,
|
|
111
152
|
NoActiveReleaseError,
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
MissingLabelError,
|
|
154
|
+
LabelNotFoundError,
|
|
114
155
|
ENV_SLUG_REGEX2 as ENV_SLUG_REGEX,
|
|
115
|
-
|
|
116
|
-
AmbiguousEnvLabelsError
|
|
156
|
+
Conversation
|
|
117
157
|
};
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal default endpoints. Deliberately NOT re-exported from the package
|
|
3
|
+
* root: `createClient` resolves the URLs (option → env → default) and exposes
|
|
4
|
+
* the resolved data-plane URL as `to11.gatewayUrl`, so app code never imports a
|
|
5
|
+
* bare URL constant. Keeping these out of the public surface avoids a JS-only
|
|
6
|
+
* exported symbol that would need a Python-parity record.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_API_URL = "https://api.to11.ai";
|
|
9
|
+
export declare const DEFAULT_GATEWAY_URL = "https://gw.to11.ai";
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability context — the `session → conversation → turn` hierarchy that
|
|
3
|
+
* maps onto to11's telemetry grouping (Session → Conversation → Turn →
|
|
4
|
+
* LLM-Call). Each level provides a lazy default for the level below; explicit
|
|
5
|
+
* control is opt-in per use case. See
|
|
6
|
+
* docs/product-specs/2026-07-14-to11-2691-sdk-simpler-setup.md.
|
|
7
|
+
*
|
|
8
|
+
* Header-only: `turn.headers(prompt?)` returns a plain object the caller applies
|
|
9
|
+
* to their own provider client. It never sends a request.
|
|
10
|
+
*/
|
|
11
|
+
import { type GatewayPromptProvenance } from "./gateway";
|
|
12
|
+
/** Auth/config the client hands to the context for gateway header building. */
|
|
13
|
+
export interface TurnAuthContext {
|
|
14
|
+
readonly apiKey: string;
|
|
15
|
+
readonly projectId: string;
|
|
16
|
+
readonly env?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A prompt argument accepted by `turn.headers()`. Either the flat provenance
|
|
20
|
+
* (a neutral `RenderedPrompt`) or a `format`-shaped result carrying it under
|
|
21
|
+
* `metadata` — both are accepted so the format and neutral render paths carry
|
|
22
|
+
* provenance identically.
|
|
23
|
+
*/
|
|
24
|
+
export type PromptForHeaders = GatewayPromptProvenance | {
|
|
25
|
+
metadata: GatewayPromptProvenance;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* One agent turn — a single trace. A turn's `traceparent` is fixed for its
|
|
29
|
+
* lifetime, so every LLM-call made under it groups into one trace.
|
|
30
|
+
*/
|
|
31
|
+
export declare class Turn {
|
|
32
|
+
private readonly auth;
|
|
33
|
+
readonly sessionId: string;
|
|
34
|
+
readonly conversationId: string;
|
|
35
|
+
/** The fixed W3C traceparent for this turn (one trace). */
|
|
36
|
+
readonly traceparent: string;
|
|
37
|
+
constructor(auth: TurnAuthContext, sessionId: string, conversationId: string, traceparent?: string);
|
|
38
|
+
/**
|
|
39
|
+
* The complete gateway header bag: auth + session + conversation +
|
|
40
|
+
* traceparent, plus prompt provenance when a `prompt` is supplied. A pure
|
|
41
|
+
* read of the turn's fixed ids — reuse it across a tool-loop or call per
|
|
42
|
+
* request; the result is identical.
|
|
43
|
+
*
|
|
44
|
+
* Only valid for requests targeting the gateway (`GATEWAY_URL`); it carries
|
|
45
|
+
* the to11 API key and must never be attached to a direct provider endpoint.
|
|
46
|
+
*
|
|
47
|
+
* @example One call (inline turn)
|
|
48
|
+
* const res = await openai.chat.completions.create(
|
|
49
|
+
* { ...prompt.config, messages: prompt.messages },
|
|
50
|
+
* { headers: to11.turn().headers(prompt) },
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* @example Tool loop — hoist the turn so every call shares one trace
|
|
54
|
+
* const turn = to11.turn();
|
|
55
|
+
* const headers = turn.headers(prompt);
|
|
56
|
+
* while (true) {
|
|
57
|
+
* const res = await openai.chat.completions.create({ ...prompt.config, messages, tools }, { headers });
|
|
58
|
+
* // …reuse `headers` for every call in the loop…
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
headers(prompt?: PromptForHeaders): Record<string, string>;
|
|
62
|
+
}
|
|
63
|
+
/** One agent thread — a stable conversation id shared across all its turns. */
|
|
64
|
+
export declare class Conversation {
|
|
65
|
+
private readonly auth;
|
|
66
|
+
readonly sessionId: string;
|
|
67
|
+
/** Stable conversation id, reused by every turn created from this object. */
|
|
68
|
+
readonly id: string;
|
|
69
|
+
constructor(auth: TurnAuthContext, sessionId: string, id?: string);
|
|
70
|
+
/** Start a new turn (fresh trace) in this conversation. */
|
|
71
|
+
turn(): Turn;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One unit of work. Groups conversations under a single session id. A session
|
|
75
|
+
* lazily owns one default conversation, used by `session.turn()`; call
|
|
76
|
+
* `session.conversation()` for additional (side/parallel) agent threads.
|
|
77
|
+
*/
|
|
78
|
+
export declare class Session {
|
|
79
|
+
private readonly auth;
|
|
80
|
+
/** Stable session id, carried by every conversation and turn beneath it. */
|
|
81
|
+
readonly id: string;
|
|
82
|
+
private defaultConversation;
|
|
83
|
+
constructor(auth: TurnAuthContext, id?: string);
|
|
84
|
+
/**
|
|
85
|
+
* Create a distinct conversation (a separate agent thread) in this session.
|
|
86
|
+
* Use this when one unit of work runs multiple agents (side / parallel
|
|
87
|
+
* agents): each conversation gets its own `x-to11-conversation-id`, all under
|
|
88
|
+
* the one session.
|
|
89
|
+
*
|
|
90
|
+
* @example Multiple agents in one session
|
|
91
|
+
* const session = to11.session();
|
|
92
|
+
* const main = session.conversation(); // main agent thread
|
|
93
|
+
* const research = session.conversation(); // separate research thread, same session
|
|
94
|
+
*
|
|
95
|
+
* await openai.chat.completions.create(
|
|
96
|
+
* { ...mainPrompt.config, messages: mainMessages },
|
|
97
|
+
* { headers: main.turn().headers(mainPrompt) },
|
|
98
|
+
* );
|
|
99
|
+
* await openai.chat.completions.create(
|
|
100
|
+
* { ...researchPrompt.config, messages: researchMessages },
|
|
101
|
+
* { headers: research.turn().headers(researchPrompt) },
|
|
102
|
+
* );
|
|
103
|
+
*/
|
|
104
|
+
conversation(id?: string): Conversation;
|
|
105
|
+
/**
|
|
106
|
+
* Start a turn in the session's single implicit conversation. The default
|
|
107
|
+
* conversation is created lazily on first call and reused, so consecutive
|
|
108
|
+
* `session.turn()` calls share one `x-to11-conversation-id` (each with its
|
|
109
|
+
* own `traceparent`).
|
|
110
|
+
*
|
|
111
|
+
* @example Multi-turn chat — every turn shares the session's conversation
|
|
112
|
+
* const session = to11.session();
|
|
113
|
+
* for await (const input of inputs) {
|
|
114
|
+
* messages.push({ role: "user", content: input });
|
|
115
|
+
* const turn = session.turn(); // fresh trace, same conversation id
|
|
116
|
+
* const res = await openai.chat.completions.create(
|
|
117
|
+
* { ...prompt.config, messages },
|
|
118
|
+
* { headers: turn.headers(prompt) },
|
|
119
|
+
* );
|
|
120
|
+
* messages.push(res.choices[0].message);
|
|
121
|
+
* }
|
|
122
|
+
*/
|
|
123
|
+
turn(): Turn;
|
|
124
|
+
}
|