@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/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 { RoutingRulesResource } from "./routingRules/resource";
5
- export { BehaviorStore, type BehaviorStoreOptions, envVarNameForKey, type SdkBehaviorEnvelope, } from "./behaviors/store";
6
- export type { AmbiguousEnvLabelsReason, EnvNotFoundReason, NoActiveReleaseReason, NoApplicableRouteReason, PromptNotFoundReason, PromptPolicyViolationReason, } from "./errors";
7
- export { AmbiguousEnvLabelsError, EnvNotEnabledForProviderError, EnvNotFoundError, NoActiveReleaseError, NoApplicableRouteError, PromptLabelNotRegisteredError, PromptNotFoundError, PromptPolicyViolationError, RuleNotFoundError, RuleVersionInvalidSnapshotError, To11aiApiError, To11aiAuthError, To11aiError, To11aiNetworkError, To11aiRateLimitError, To11aiValidationError, } from "./errors";
8
- export type { GatewayAuthOptions } from "./gateway";
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 { BlockRenderRecord, DeveloperRole, FetchedPrompt, FetchPromptOptions, RenderedChatMessage, RenderedPrompt, ResolvedPrompt, ResolvedPromptEnvelope, } from "./prompts/types";
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 type { CreateRuleVersionInput, CreateRuleVersionResult, GetRuleVersionInput, GetRuleVersionResult, ListRuleReleasesInput, ListRuleReleasesResult, ListRuleVersionsInput, ListRuleVersionsResult, RollbackRuleReleaseInput, RollbackRuleReleaseResult, RuleModelBinding, RuleProviderRef, RuleRelease, RuleReleaseActorType, RuleReleaseApprovalStatus, RuleReleaseChangeKind, RuleReleaseStrategy, RuleReleaseWeight, RuleSnapshot, RuleStrategy, RuleVersion, SetRuleReleaseInput, SetRuleReleaseResult, } from "./routingRules/resource";
18
- export { RoutingRuleReleaseResource, RoutingRulesResource, RoutingRuleVersionResource, } from "./routingRules/resource";
19
- export type { Transport } from "./transport";
20
- interface ServerAuthOptions {
21
- /** API key for server-side use. Must not be used in browser contexts. */
22
- apiKey: string;
23
- getAccessToken?: never;
24
- }
25
- interface BrowserAuthOptions {
26
- /** Token callback for browser / edge contexts — avoids static secrets. */
27
- getAccessToken: () => Promise<string>;
28
- apiKey?: never;
29
- }
30
- type AuthOptions = ServerAuthOptions | BrowserAuthOptions;
31
- export type ClientOptions = AuthOptions & {
32
- baseUrl: string;
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
- * Project the client is bound to (TO11-980 / S9). Required for the
35
- * env-aware `prompts.fetch(slug, …)` surface, which builds the
36
- * project-scoped resolve path from it. Validated non-empty at
37
- * construction. The deprecated `prompts.resolve()` keeps its per-call
38
- * `projectId` and ignores this.
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.fetch(slug)` (TO11-980 / S9,
43
- * Style-A). When set, every `fetch()` call inherits it unless overridden
44
- * per call. Validated eagerly against the project-environments registry
45
- * rule (lowercase-kebab, `^[a-z0-9-]{1,63}$`): empty / whitespace-only /
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
- /** LRU cache configuration for resolve(). Defaults: ttlSeconds=300, maxEntries=100 */
51
- cache?: CacheConfig;
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
- * Purely local overrides for server-evaluated SDK-behavior flags (TO11-2100),
58
- * keyed by namespaced flag key (e.g. `{ "sdk.retry-v2": true }`). These take
59
- * precedence over server-delivered values and the SDK's coded defaults. For
60
- * the same flag key, an init option here wins over a `TO11_SDK_BEHAVIOR_*`
61
- * environment variable. Published-SDK only — no LaunchDarkly involved.
62
- */
63
- behaviorOverrides?: Record<string, unknown>;
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
- readonly routingRules: RoutingRulesResource;
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
- * Resolve a server-evaluated SDK-behavior flag value (TO11-2100) under the
71
- * fixed precedence: local override (init option → `TO11_SDK_BEHAVIOR_*` env
72
- * var) → server-delivered value (captured from responses the client has
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
- readonly resolveBehavior: <T>(key: string, codedDefault: T) => T;
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
- * Auth mode is inferred from options:
84
- * - `apiKey` → server-side; rejected in browser contexts.
85
- * - `getAccessToken` → browser-safe; token fetched per request.
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: ClientOptions): To11aiClient;
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
- BehaviorStore as BehaviorStore2,
10
- envVarNameForKey
11
- } from "./behaviors/store";
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
- AmbiguousEnvLabelsError,
14
- EnvNotEnabledForProviderError,
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
- import {
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
- if ((isDomBrowser || isWorkerBrowser) && options.apiKey !== undefined) {
45
- throw new Error("[to11ai/sdk] Do not use `apiKey` in browser contexts — use `getAccessToken` instead.");
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 && !ENV_SLUG_REGEX.test(options.env)) {
54
- throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(options.env)}`);
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
- const hasApiKey = options.apiKey !== undefined;
57
- const hasGetAccessToken = options.getAccessToken !== undefined;
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
- const auth = options.apiKey !== undefined ? { apiKey: options.apiKey } : { getAccessToken };
63
- const isBrowser = isDomBrowser || isWorkerBrowser;
64
- const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
65
- const behaviorStore = new BehaviorStore({
66
- initOverrides: options.behaviorOverrides,
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: options.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, options.cache, {
77
- projectId: options.projectId,
78
- env: options.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 routingRules = new RoutingRulesResource(transport);
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
- routingRules,
86
- resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault)
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
- RuleVersionInvalidSnapshotError,
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
- EnvNotFoundError,
113
- EnvNotEnabledForProviderError,
153
+ MissingLabelError,
154
+ LabelNotFoundError,
114
155
  ENV_SLUG_REGEX2 as ENV_SLUG_REGEX,
115
- BehaviorStore2 as BehaviorStore,
116
- AmbiguousEnvLabelsError
156
+ Conversation
117
157
  };
@@ -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
+ }