@to11ai/sdk 1.0.0 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +85 -18
- package/dist/client.d.ts +140 -39
- package/dist/client.js +91 -19
- package/dist/config.d.ts +9 -0
- package/dist/context.d.ts +124 -0
- package/dist/errors.cjs +18 -1
- package/dist/errors.d.ts +18 -1
- package/dist/errors.js +18 -1
- package/dist/gateway.cjs +62 -22
- package/dist/gateway.d.ts +57 -9
- package/dist/gateway.js +62 -22
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/types.gen.d.ts +1313 -166
- package/dist/generated/zod.gen.d.ts +406 -232
- package/dist/prompts/cache.d.ts +3 -3
- package/dist/prompts/resource.cjs +21 -16
- package/dist/prompts/resource.d.ts +59 -28
- package/dist/prompts/resource.js +21 -16
- package/dist/prompts/shape.d.ts +54 -0
- package/dist/prompts/types.d.ts +31 -13
- package/package.json +1 -1
- package/src/client.ts +326 -80
- package/src/config.ts +13 -0
- package/src/context.ts +198 -0
- package/src/errors.ts +33 -3
- package/src/gateway.ts +135 -33
- package/src/generated/index.ts +1 -1
- package/src/generated/types.gen.ts +1324 -166
- package/src/generated/zod.gen.ts +371 -268
- package/src/prompts/cache.ts +3 -6
- package/src/prompts/resource.ts +89 -41
- package/src/prompts/shape.ts +149 -0
- package/src/prompts/types.ts +35 -14
package/dist/client.cjs
CHANGED
|
@@ -39,16 +39,19 @@ var __export = (target, all) => {
|
|
|
39
39
|
// src/client.ts
|
|
40
40
|
var exports_client = {};
|
|
41
41
|
__export(exports_client, {
|
|
42
|
-
gatewayPromptHeaders: () =>
|
|
43
|
-
gatewayAuthHeaders: () =>
|
|
42
|
+
gatewayPromptHeaders: () => import_gateway2.gatewayPromptHeaders,
|
|
43
|
+
gatewayAuthHeaders: () => import_gateway2.gatewayAuthHeaders,
|
|
44
44
|
envVarNameForKey: () => import_store2.envVarNameForKey,
|
|
45
45
|
createClient: () => createClient,
|
|
46
|
+
UnknownRoleError: () => import_errors.UnknownRoleError,
|
|
47
|
+
Turn: () => import_context2.Turn,
|
|
46
48
|
To11aiValidationError: () => import_errors.To11aiValidationError,
|
|
47
49
|
To11aiRateLimitError: () => import_errors.To11aiRateLimitError,
|
|
48
50
|
To11aiNetworkError: () => import_errors.To11aiNetworkError,
|
|
49
51
|
To11aiError: () => import_errors.To11aiError,
|
|
50
52
|
To11aiAuthError: () => import_errors.To11aiAuthError,
|
|
51
53
|
To11aiApiError: () => import_errors.To11aiApiError,
|
|
54
|
+
Session: () => import_context2.Session,
|
|
52
55
|
RuleVersionInvalidSnapshotError: () => import_errors.RuleVersionInvalidSnapshotError,
|
|
53
56
|
RuleNotFoundError: () => import_errors.RuleNotFoundError,
|
|
54
57
|
RoutingRulesResource: () => import_resource6.RoutingRulesResource,
|
|
@@ -64,29 +67,50 @@ __export(exports_client, {
|
|
|
64
67
|
EnvNotFoundError: () => import_errors.EnvNotFoundError,
|
|
65
68
|
EnvNotEnabledForProviderError: () => import_errors.EnvNotEnabledForProviderError,
|
|
66
69
|
ENV_SLUG_REGEX: () => import_types2.ENV_SLUG_REGEX,
|
|
70
|
+
Conversation: () => import_context2.Conversation,
|
|
67
71
|
BehaviorStore: () => import_store2.BehaviorStore,
|
|
68
72
|
AmbiguousEnvLabelsError: () => import_errors.AmbiguousEnvLabelsError
|
|
69
73
|
});
|
|
70
74
|
module.exports = __toCommonJS(exports_client);
|
|
71
75
|
var import_store = require("./behaviors/store");
|
|
76
|
+
var import_config = require("./config");
|
|
77
|
+
var import_context = require("./context");
|
|
78
|
+
var import_gateway = require("./gateway");
|
|
72
79
|
var import_resource = require("./projectEnvironments/resource");
|
|
73
80
|
var import_resource2 = require("./prompts/resource");
|
|
74
81
|
var import_types = require("./prompts/types");
|
|
75
82
|
var import_resource3 = require("./routingRules/resource");
|
|
76
83
|
var import_transport = require("./transport");
|
|
77
84
|
var import_store2 = require("./behaviors/store");
|
|
85
|
+
var import_context2 = require("./context");
|
|
78
86
|
var import_errors = require("./errors");
|
|
79
|
-
var
|
|
87
|
+
var import_gateway2 = require("./gateway");
|
|
80
88
|
var import_resource4 = require("./projectEnvironments/resource");
|
|
81
89
|
var import_resource5 = require("./prompts/resource");
|
|
82
90
|
var import_types2 = require("./prompts/types");
|
|
83
91
|
var import_resource6 = require("./routingRules/resource");
|
|
84
|
-
function createClient(options) {
|
|
92
|
+
function createClient(options = {}) {
|
|
85
93
|
const isDomBrowser = typeof globalThis === "object" && typeof globalThis.document !== "undefined";
|
|
86
94
|
const workerLikeGlobal = globalThis;
|
|
87
95
|
const isBunMainThread = workerLikeGlobal.Bun?.isMainThread === true;
|
|
88
96
|
const isWorkerBrowser = typeof globalThis === "object" && (typeof workerLikeGlobal.importScripts === "function" || !isBunMainThread && typeof workerLikeGlobal.postMessage === "function" && typeof workerLikeGlobal.onmessage !== "undefined");
|
|
89
|
-
|
|
97
|
+
const isBrowser = isDomBrowser || isWorkerBrowser;
|
|
98
|
+
const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
|
|
99
|
+
const pick = (opt, envKey) => {
|
|
100
|
+
const fromOpt = opt?.trim();
|
|
101
|
+
if (fromOpt)
|
|
102
|
+
return fromOpt;
|
|
103
|
+
const fromEnv = processEnv?.[envKey]?.trim();
|
|
104
|
+
return fromEnv ? fromEnv : undefined;
|
|
105
|
+
};
|
|
106
|
+
const baseUrl = pick(options.baseUrl, "TO11_API_URL") ?? import_config.DEFAULT_API_URL;
|
|
107
|
+
const gatewayUrl = (pick(options.gatewayUrl, "TO11_GATEWAY_URL") ?? import_config.DEFAULT_GATEWAY_URL).replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
108
|
+
const getAccessToken = options.getAccessToken;
|
|
109
|
+
const apiKey = getAccessToken !== undefined ? options.apiKey : pick(options.apiKey, "TO11_API_KEY");
|
|
110
|
+
const projectId = pick(options.projectId, "TO11_PROJECT_ID");
|
|
111
|
+
const env = options.env;
|
|
112
|
+
const providerApiKey = options.providerApiKey?.trim() || undefined;
|
|
113
|
+
if (isBrowser && options.apiKey !== undefined) {
|
|
90
114
|
throw new Error("[to11ai/sdk] Do not use `apiKey` in browser contexts — use `getAccessToken` instead.");
|
|
91
115
|
}
|
|
92
116
|
if (options.apiKey !== undefined && options.apiKey.trim() === "") {
|
|
@@ -95,39 +119,82 @@ function createClient(options) {
|
|
|
95
119
|
if (options.projectId !== undefined && options.projectId.trim() === "") {
|
|
96
120
|
throw new Error("[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.");
|
|
97
121
|
}
|
|
98
|
-
if (
|
|
99
|
-
throw new Error(`[to11ai/sdk] \`env\` must match ${import_types.ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(
|
|
122
|
+
if (env !== undefined && !import_types.ENV_SLUG_REGEX.test(env)) {
|
|
123
|
+
throw new Error(`[to11ai/sdk] \`env\` must match ${import_types.ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
|
|
100
124
|
}
|
|
101
|
-
const hasApiKey =
|
|
102
|
-
const hasGetAccessToken =
|
|
103
|
-
const getAccessToken = options.getAccessToken;
|
|
125
|
+
const hasApiKey = apiKey !== undefined;
|
|
126
|
+
const hasGetAccessToken = getAccessToken !== undefined;
|
|
104
127
|
if (hasApiKey === hasGetAccessToken) {
|
|
105
|
-
throw new Error("[to11ai/sdk] Provide exactly one of `apiKey` (
|
|
128
|
+
throw new Error("[to11ai/sdk] Provide exactly one of `apiKey` (or `TO11_API_KEY`) or `getAccessToken`.");
|
|
106
129
|
}
|
|
107
|
-
const auth =
|
|
108
|
-
const isBrowser = isDomBrowser || isWorkerBrowser;
|
|
109
|
-
const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
|
|
130
|
+
const auth = hasApiKey ? { apiKey } : { getAccessToken };
|
|
110
131
|
const behaviorStore = new import_store.BehaviorStore({
|
|
111
132
|
initOverrides: options.behaviorOverrides,
|
|
112
133
|
env: processEnv
|
|
113
134
|
});
|
|
114
135
|
const transport = new import_transport.Transport({
|
|
115
|
-
baseUrl
|
|
136
|
+
baseUrl,
|
|
116
137
|
auth,
|
|
117
138
|
timeoutMs: options.timeoutMs,
|
|
118
139
|
maxRetries: options.maxRetries,
|
|
119
140
|
behaviorStore
|
|
120
141
|
});
|
|
121
142
|
const prompts = new import_resource2.PromptResource(transport, options.cache, {
|
|
122
|
-
projectId
|
|
123
|
-
env
|
|
143
|
+
projectId,
|
|
144
|
+
env,
|
|
145
|
+
format: options.format,
|
|
146
|
+
onUnknownRole: options.onUnknownRole
|
|
124
147
|
});
|
|
125
148
|
const projectEnvironments = new import_resource.ProjectEnvironmentResource(transport);
|
|
126
149
|
const routingRules = new import_resource3.RoutingRulesResource(transport);
|
|
150
|
+
const gatewayAuthContext = () => {
|
|
151
|
+
if (apiKey === undefined) {
|
|
152
|
+
throw new Error("[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.");
|
|
153
|
+
}
|
|
154
|
+
if (projectId === undefined) {
|
|
155
|
+
throw new Error("[to11ai/sdk] session()/turn() need a `projectId` (or `TO11_PROJECT_ID`).");
|
|
156
|
+
}
|
|
157
|
+
return env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId };
|
|
158
|
+
};
|
|
159
|
+
let defaultSession;
|
|
160
|
+
const clientDefaultSession = () => {
|
|
161
|
+
if (defaultSession === undefined) {
|
|
162
|
+
defaultSession = new import_context.Session(gatewayAuthContext());
|
|
163
|
+
}
|
|
164
|
+
return defaultSession;
|
|
165
|
+
};
|
|
166
|
+
const gatewayClientOptions = (defaultBaseURL, overrides) => {
|
|
167
|
+
if (apiKey === undefined) {
|
|
168
|
+
throw new Error("[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.");
|
|
169
|
+
}
|
|
170
|
+
if (projectId === undefined) {
|
|
171
|
+
throw new Error("[to11ai/sdk] openaiOptions()/anthropicOptions() need a `projectId` (or `TO11_PROJECT_ID`) — it authenticates the gateway call via `x-to11-project-id`.");
|
|
172
|
+
}
|
|
173
|
+
const authHeaders = import_gateway.gatewayAuthHeaders(env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId });
|
|
174
|
+
const {
|
|
175
|
+
apiKey: overrideApiKey,
|
|
176
|
+
baseURL: overrideBaseURL,
|
|
177
|
+
defaultHeaders: overrideHeaders,
|
|
178
|
+
...passthrough
|
|
179
|
+
} = overrides ?? {};
|
|
180
|
+
return {
|
|
181
|
+
...passthrough,
|
|
182
|
+
baseURL: overrideBaseURL ?? defaultBaseURL,
|
|
183
|
+
apiKey: overrideApiKey ?? providerApiKey ?? apiKey,
|
|
184
|
+
defaultHeaders: { ...authHeaders, ...overrideHeaders }
|
|
185
|
+
};
|
|
186
|
+
};
|
|
127
187
|
return {
|
|
128
188
|
prompts,
|
|
129
189
|
projectEnvironments,
|
|
130
190
|
routingRules,
|
|
131
|
-
resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault)
|
|
191
|
+
resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault),
|
|
192
|
+
apiKey,
|
|
193
|
+
gatewayUrl,
|
|
194
|
+
session: (id) => new import_context.Session(gatewayAuthContext(), id),
|
|
195
|
+
conversation: (id) => clientDefaultSession().conversation(id),
|
|
196
|
+
turn: () => clientDefaultSession().turn(),
|
|
197
|
+
openaiOptions: (overrides) => gatewayClientOptions(`${gatewayUrl}/v1`, overrides),
|
|
198
|
+
anthropicOptions: (overrides) => gatewayClientOptions(gatewayUrl, overrides)
|
|
132
199
|
};
|
|
133
200
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,69 +1,115 @@
|
|
|
1
|
+
import { type Conversation, Session, type Turn } from "./context";
|
|
1
2
|
import { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
2
3
|
import type { CacheConfig } from "./prompts/cache";
|
|
3
4
|
import { PromptResource } from "./prompts/resource";
|
|
5
|
+
import { type RenderFormat, type UnknownRoleMode } from "./prompts/types";
|
|
4
6
|
import { RoutingRulesResource } from "./routingRules/resource";
|
|
5
7
|
export { BehaviorStore, type BehaviorStoreOptions, envVarNameForKey, type SdkBehaviorEnvelope, } from "./behaviors/store";
|
|
8
|
+
export type { TurnAuthContext } from "./context";
|
|
9
|
+
export { Conversation, Session, Turn } from "./context";
|
|
6
10
|
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";
|
|
11
|
+
export { AmbiguousEnvLabelsError, EnvNotEnabledForProviderError, EnvNotFoundError, NoActiveReleaseError, NoApplicableRouteError, PromptLabelNotRegisteredError, PromptNotFoundError, PromptPolicyViolationError, RuleNotFoundError, RuleVersionInvalidSnapshotError, To11aiApiError, To11aiAuthError, To11aiError, To11aiNetworkError, To11aiRateLimitError, To11aiValidationError, UnknownRoleError, } from "./errors";
|
|
12
|
+
export type { ConvertMessagesOptions, GatewayAuthOptions } from "./gateway";
|
|
9
13
|
export { gatewayAuthHeaders, gatewayPromptHeaders } from "./gateway";
|
|
10
14
|
export type { ArchiveProjectEnvironmentInput, ArchiveProjectEnvironmentResult, CreateProjectEnvironmentInput, CreateProjectEnvironmentResult, GetProjectEnvironmentInput, GetProjectEnvironmentResult, ListProjectEnvironmentsInput, ListProjectEnvironmentsResult, LivePointerCounts, ProjectEnvironment, RestoreProjectEnvironmentInput, RestoreProjectEnvironmentResult, UpdateProjectEnvironmentInput, UpdateProjectEnvironmentResult, } from "./projectEnvironments/resource";
|
|
11
15
|
export { ProjectEnvironmentResource } from "./projectEnvironments/resource";
|
|
12
16
|
export type { CacheConfig } from "./prompts/cache";
|
|
13
17
|
export type { PromptResourceConfig } from "./prompts/resource";
|
|
14
18
|
export { PromptResource } from "./prompts/resource";
|
|
15
|
-
export type {
|
|
19
|
+
export type { AnthropicRenderedPrompt, OpenAiRenderedPrompt, PromptConfig, PromptMetadata, RenderResult, } from "./prompts/shape";
|
|
20
|
+
export type { BlockRenderRecord, FetchedPrompt, FetchPromptOptions, RenderedChatMessage, RenderedPrompt, RenderFormat, RenderOptions, ResolvedPrompt, ResolvedPromptEnvelope, UnknownRoleMode, } from "./prompts/types";
|
|
16
21
|
export { ENV_SLUG_REGEX } from "./prompts/types";
|
|
17
22
|
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
23
|
export { RoutingRuleReleaseResource, RoutingRulesResource, RoutingRuleVersionResource, } from "./routingRules/resource";
|
|
19
24
|
export type { Transport } from "./transport";
|
|
20
|
-
interface
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
export interface ClientOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Control-plane base URL. Precedence: this option → `TO11_API_URL` env →
|
|
28
|
+
* `https://api.to11.ai`.
|
|
29
|
+
*/
|
|
30
|
+
baseUrl?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Data-plane gateway URL (the app's provider-client `baseURL`). Precedence:
|
|
33
|
+
* this option → `TO11_GATEWAY_URL` env → `https://gw.to11.ai`.
|
|
34
|
+
*/
|
|
35
|
+
gatewayUrl?: string;
|
|
36
|
+
/**
|
|
37
|
+
* API key for server-side use. Precedence: this option → `TO11_API_KEY` env.
|
|
38
|
+
* Rejected in browser contexts — use `getAccessToken` there.
|
|
39
|
+
*/
|
|
40
|
+
apiKey?: string;
|
|
26
41
|
/** Token callback for browser / edge contexts — avoids static secrets. */
|
|
27
|
-
getAccessToken
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
42
|
+
getAccessToken?: () => Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Provider API key (BYOK) carried by `openaiOptions()` / `anthropicOptions()`
|
|
45
|
+
* as the provider client's `apiKey`, so a BYOK call is a single
|
|
46
|
+
* `new OpenAI(to11.openaiOptions())`. When omitted, those helpers fall back to
|
|
47
|
+
* the to11 `apiKey` as a placeholder (the managed / server-side-credential
|
|
48
|
+
* path). Option only — no env fallback. Whether the gateway actually uses this
|
|
49
|
+
* key depends on the provider's passthrough mode; otherwise the project's
|
|
50
|
+
* stored credential wins.
|
|
51
|
+
*/
|
|
52
|
+
providerApiKey?: string;
|
|
33
53
|
/**
|
|
34
|
-
* Project the client is bound to
|
|
35
|
-
* env
|
|
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.
|
|
54
|
+
* Project the client is bound to. Precedence: this option → `TO11_PROJECT_ID`
|
|
55
|
+
* env. Required for `prompts.render()` and the gateway context helpers.
|
|
39
56
|
*/
|
|
40
57
|
projectId?: string;
|
|
41
58
|
/**
|
|
42
|
-
* Default serving environment for `prompts.
|
|
43
|
-
*
|
|
44
|
-
*
|
|
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.
|
|
59
|
+
* Default serving environment for `prompts.render(slug)`, inherited by every
|
|
60
|
+
* render unless overridden per call. Validated eagerly against the
|
|
61
|
+
* project-environments slug rule (`^[a-z0-9-]{1,63}$`).
|
|
48
62
|
*/
|
|
49
63
|
env?: string;
|
|
50
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Default provider shape for `prompts.render()` output (`"openai"` |
|
|
66
|
+
* `"anthropic"`). Omit for the neutral result. Per-call override allowed.
|
|
67
|
+
*/
|
|
68
|
+
format?: RenderFormat;
|
|
69
|
+
/**
|
|
70
|
+
* Default policy for a message with an unrecognized role while shaping
|
|
71
|
+
* `render({ format })` output: `"drop"` (default, silent), `"warn"` (drop +
|
|
72
|
+
* `console.warn`), or `"error"` (throw `UnknownRoleError`). Per-call override
|
|
73
|
+
* via `render(slug, { onUnknownRole })`.
|
|
74
|
+
*/
|
|
75
|
+
onUnknownRole?: UnknownRoleMode;
|
|
76
|
+
/** LRU cache configuration for render(). Defaults: ttlSeconds=300, maxEntries=100 */
|
|
51
77
|
cache?: CacheConfig;
|
|
52
78
|
/** Request timeout in milliseconds. Default: 30_000 */
|
|
53
79
|
timeoutMs?: number;
|
|
54
80
|
/** Max retry attempts for network errors / 5xx. Default: 3 */
|
|
55
81
|
maxRetries?: number;
|
|
56
82
|
/**
|
|
57
|
-
* Purely local overrides for server-evaluated SDK-behavior flags (TO11-2100)
|
|
58
|
-
*
|
|
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.
|
|
83
|
+
* Purely local overrides for server-evaluated SDK-behavior flags (TO11-2100).
|
|
84
|
+
* An init option here wins over a `TO11_SDK_BEHAVIOR_*` env var. No LaunchDarkly.
|
|
62
85
|
*/
|
|
63
86
|
behaviorOverrides?: Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Overrides accepted by `openaiOptions()` / `anthropicOptions()`. The three
|
|
90
|
+
* known fields are merged (`apiKey` / `baseURL` override; `defaultHeaders`
|
|
91
|
+
* shallow-merges over the tenant-auth headers, caller wins); any other keys —
|
|
92
|
+
* `timeout`, `maxRetries`, `fetch`, … — pass through untouched to the provider
|
|
93
|
+
* client, so `new OpenAI(to11.openaiOptions({ apiKey, timeout }))` needs no
|
|
94
|
+
* outer spread.
|
|
95
|
+
*/
|
|
96
|
+
export interface ProviderClientOverrides {
|
|
97
|
+
apiKey?: string;
|
|
98
|
+
baseURL?: string;
|
|
99
|
+
defaultHeaders?: Record<string, string>;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The spread-ready result of `openaiOptions()` / `anthropicOptions()`: the three
|
|
103
|
+
* managed fields plus whatever passthrough keys the caller supplied (their types
|
|
104
|
+
* preserved), so it drops straight into `new OpenAI(...)` / `new Anthropic(...)`.
|
|
105
|
+
*/
|
|
106
|
+
export type ProviderClientOptions<T extends ProviderClientOverrides = ProviderClientOverrides> = Omit<T, "apiKey" | "baseURL" | "defaultHeaders"> & {
|
|
107
|
+
baseURL: string;
|
|
108
|
+
apiKey: string;
|
|
109
|
+
defaultHeaders: Record<string, string>;
|
|
64
110
|
};
|
|
65
|
-
export interface To11aiClient {
|
|
66
|
-
readonly prompts: PromptResource
|
|
111
|
+
export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
|
|
112
|
+
readonly prompts: PromptResource<F>;
|
|
67
113
|
readonly projectEnvironments: ProjectEnvironmentResource;
|
|
68
114
|
readonly routingRules: RoutingRulesResource;
|
|
69
115
|
/**
|
|
@@ -76,12 +122,67 @@ export interface To11aiClient {
|
|
|
76
122
|
* delivered on the envelope.
|
|
77
123
|
*/
|
|
78
124
|
readonly resolveBehavior: <T>(key: string, codedDefault: T) => T;
|
|
125
|
+
/** Resolved API key (server mode); `undefined` in browser (`getAccessToken`) mode. */
|
|
126
|
+
readonly apiKey: string | undefined;
|
|
127
|
+
/** Resolved data-plane gateway URL (option → `TO11_GATEWAY_URL` → default). */
|
|
128
|
+
readonly gatewayUrl: string;
|
|
129
|
+
/** A new session (unit of work). Pass an id to group telemetry by your own id. */
|
|
130
|
+
session(id?: string): Session;
|
|
131
|
+
/**
|
|
132
|
+
* A conversation in the client's default session (for side / parallel agents).
|
|
133
|
+
*
|
|
134
|
+
* @example Two agents under one session
|
|
135
|
+
* const research = to11.conversation(); // a separate thread from to11.turn()'s default
|
|
136
|
+
* const res = await openai.chat.completions.create(
|
|
137
|
+
* { ...researchPrompt.config, messages },
|
|
138
|
+
* { headers: research.turn().headers(researchPrompt) },
|
|
139
|
+
* );
|
|
140
|
+
*/
|
|
141
|
+
conversation(id?: string): Conversation;
|
|
142
|
+
/** A turn in the client's default session + default conversation. */
|
|
143
|
+
turn(): Turn;
|
|
144
|
+
/**
|
|
145
|
+
* Spread-ready options for `new OpenAI(...)` targeting the gateway:
|
|
146
|
+
* `{ baseURL, apiKey, defaultHeaders }` (baseURL carries `/v1`). `defaultHeaders`
|
|
147
|
+
* holds the static tenant auth, so the client authenticates on its own; add
|
|
148
|
+
* `turn().headers(prompt)` per call for trace + prompt provenance. Pass
|
|
149
|
+
* `overrides` to change `apiKey`/`baseURL`, merge extra `defaultHeaders`, or
|
|
150
|
+
* forward any other provider-SDK option (`timeout`, …).
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* const openai = new OpenAI(to11.openaiOptions());
|
|
154
|
+
* @example BYOK + a provider-SDK option, no outer spread
|
|
155
|
+
* const openai = new OpenAI(to11.openaiOptions({ apiKey: MY_KEY, timeout: 60_000 }));
|
|
156
|
+
*/
|
|
157
|
+
openaiOptions<T extends ProviderClientOverrides = ProviderClientOverrides>(overrides?: T): ProviderClientOptions<T>;
|
|
158
|
+
/**
|
|
159
|
+
* Spread-ready options for `new Anthropic(...)` targeting the gateway root
|
|
160
|
+
* (the Anthropic SDK appends `/v1/messages` itself). Same shape and merge
|
|
161
|
+
* rules as {@link To11aiClient.openaiOptions}.
|
|
162
|
+
*/
|
|
163
|
+
anthropicOptions<T extends ProviderClientOverrides = ProviderClientOverrides>(overrides?: T): ProviderClientOptions<T>;
|
|
79
164
|
}
|
|
80
165
|
/**
|
|
81
|
-
* Create a to11ai SDK client.
|
|
166
|
+
* Create a to11ai SDK client. Resolution precedence differs per option:
|
|
167
|
+
* - URLs (`baseUrl` / `gatewayUrl`) — option → env var → built-in default.
|
|
168
|
+
* - `apiKey` / `projectId` — option → env var (no default).
|
|
169
|
+
* - `env` / `format` — option only.
|
|
170
|
+
* Auth mode:
|
|
171
|
+
* - `apiKey` (or `TO11_API_KEY`) → server-side; rejected in browser contexts.
|
|
172
|
+
* - `getAccessToken` → browser-safe; token fetched per request.
|
|
173
|
+
*
|
|
174
|
+
* @example Minimal setup (single call)
|
|
175
|
+
* import { createClient } from "@to11ai/sdk";
|
|
176
|
+
* import OpenAI from "openai";
|
|
82
177
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
178
|
+
* const to11 = createClient({ env: "prod", format: "openai" });
|
|
179
|
+
* const openai = new OpenAI(to11.openaiOptions());
|
|
180
|
+
* const prompt = await to11.prompts.render("weather-concierge", { variables: { city: "NYC" } });
|
|
181
|
+
* const res = await openai.chat.completions.create(
|
|
182
|
+
* { ...prompt.config, messages: prompt.messages },
|
|
183
|
+
* { headers: to11.turn().headers(prompt) },
|
|
184
|
+
* );
|
|
86
185
|
*/
|
|
87
|
-
export declare function createClient(options
|
|
186
|
+
export declare function createClient<const F extends RenderFormat | undefined = undefined>(options?: Omit<ClientOptions, "format"> & {
|
|
187
|
+
format?: F;
|
|
188
|
+
}): To11aiClient<F>;
|
package/dist/client.js
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
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 {
|
|
10
|
+
import {
|
|
11
|
+
ENV_SLUG_REGEX
|
|
12
|
+
} from "./prompts/types";
|
|
6
13
|
import { RoutingRulesResource } from "./routingRules/resource";
|
|
7
14
|
import { Transport } from "./transport";
|
|
8
15
|
import {
|
|
9
16
|
BehaviorStore as BehaviorStore2,
|
|
10
17
|
envVarNameForKey
|
|
11
18
|
} from "./behaviors/store";
|
|
19
|
+
import { Conversation, Session as Session2, Turn } from "./context";
|
|
12
20
|
import {
|
|
13
21
|
AmbiguousEnvLabelsError,
|
|
14
22
|
EnvNotEnabledForProviderError,
|
|
@@ -25,9 +33,10 @@ import {
|
|
|
25
33
|
To11aiError,
|
|
26
34
|
To11aiNetworkError,
|
|
27
35
|
To11aiRateLimitError,
|
|
28
|
-
To11aiValidationError
|
|
36
|
+
To11aiValidationError,
|
|
37
|
+
UnknownRoleError
|
|
29
38
|
} from "./errors";
|
|
30
|
-
import { gatewayAuthHeaders, gatewayPromptHeaders } from "./gateway";
|
|
39
|
+
import { gatewayAuthHeaders as gatewayAuthHeaders2, gatewayPromptHeaders } from "./gateway";
|
|
31
40
|
import { ProjectEnvironmentResource as ProjectEnvironmentResource2 } from "./projectEnvironments/resource";
|
|
32
41
|
import { PromptResource as PromptResource2 } from "./prompts/resource";
|
|
33
42
|
import { ENV_SLUG_REGEX as ENV_SLUG_REGEX2 } from "./prompts/types";
|
|
@@ -36,12 +45,28 @@ import {
|
|
|
36
45
|
RoutingRulesResource as RoutingRulesResource2,
|
|
37
46
|
RoutingRuleVersionResource
|
|
38
47
|
} from "./routingRules/resource";
|
|
39
|
-
function createClient(options) {
|
|
48
|
+
function createClient(options = {}) {
|
|
40
49
|
const isDomBrowser = typeof globalThis === "object" && typeof globalThis.document !== "undefined";
|
|
41
50
|
const workerLikeGlobal = globalThis;
|
|
42
51
|
const isBunMainThread = workerLikeGlobal.Bun?.isMainThread === true;
|
|
43
52
|
const isWorkerBrowser = typeof globalThis === "object" && (typeof workerLikeGlobal.importScripts === "function" || !isBunMainThread && typeof workerLikeGlobal.postMessage === "function" && typeof workerLikeGlobal.onmessage !== "undefined");
|
|
44
|
-
|
|
53
|
+
const isBrowser = isDomBrowser || isWorkerBrowser;
|
|
54
|
+
const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
|
|
55
|
+
const pick = (opt, envKey) => {
|
|
56
|
+
const fromOpt = opt?.trim();
|
|
57
|
+
if (fromOpt)
|
|
58
|
+
return fromOpt;
|
|
59
|
+
const fromEnv = processEnv?.[envKey]?.trim();
|
|
60
|
+
return fromEnv ? fromEnv : undefined;
|
|
61
|
+
};
|
|
62
|
+
const baseUrl = pick(options.baseUrl, "TO11_API_URL") ?? DEFAULT_API_URL;
|
|
63
|
+
const gatewayUrl = (pick(options.gatewayUrl, "TO11_GATEWAY_URL") ?? DEFAULT_GATEWAY_URL).replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
64
|
+
const getAccessToken = options.getAccessToken;
|
|
65
|
+
const apiKey = getAccessToken !== undefined ? options.apiKey : pick(options.apiKey, "TO11_API_KEY");
|
|
66
|
+
const projectId = pick(options.projectId, "TO11_PROJECT_ID");
|
|
67
|
+
const env = options.env;
|
|
68
|
+
const providerApiKey = options.providerApiKey?.trim() || undefined;
|
|
69
|
+
if (isBrowser && options.apiKey !== undefined) {
|
|
45
70
|
throw new Error("[to11ai/sdk] Do not use `apiKey` in browser contexts — use `getAccessToken` instead.");
|
|
46
71
|
}
|
|
47
72
|
if (options.apiKey !== undefined && options.apiKey.trim() === "") {
|
|
@@ -50,53 +75,99 @@ function createClient(options) {
|
|
|
50
75
|
if (options.projectId !== undefined && options.projectId.trim() === "") {
|
|
51
76
|
throw new Error("[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.");
|
|
52
77
|
}
|
|
53
|
-
if (
|
|
54
|
-
throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(
|
|
78
|
+
if (env !== undefined && !ENV_SLUG_REGEX.test(env)) {
|
|
79
|
+
throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
|
|
55
80
|
}
|
|
56
|
-
const hasApiKey =
|
|
57
|
-
const hasGetAccessToken =
|
|
58
|
-
const getAccessToken = options.getAccessToken;
|
|
81
|
+
const hasApiKey = apiKey !== undefined;
|
|
82
|
+
const hasGetAccessToken = getAccessToken !== undefined;
|
|
59
83
|
if (hasApiKey === hasGetAccessToken) {
|
|
60
|
-
throw new Error("[to11ai/sdk] Provide exactly one of `apiKey` (
|
|
84
|
+
throw new Error("[to11ai/sdk] Provide exactly one of `apiKey` (or `TO11_API_KEY`) or `getAccessToken`.");
|
|
61
85
|
}
|
|
62
|
-
const auth =
|
|
63
|
-
const isBrowser = isDomBrowser || isWorkerBrowser;
|
|
64
|
-
const processEnv = !isBrowser && typeof process !== "undefined" && typeof process.env === "object" ? process.env : undefined;
|
|
86
|
+
const auth = hasApiKey ? { apiKey } : { getAccessToken };
|
|
65
87
|
const behaviorStore = new BehaviorStore({
|
|
66
88
|
initOverrides: options.behaviorOverrides,
|
|
67
89
|
env: processEnv
|
|
68
90
|
});
|
|
69
91
|
const transport = new Transport({
|
|
70
|
-
baseUrl
|
|
92
|
+
baseUrl,
|
|
71
93
|
auth,
|
|
72
94
|
timeoutMs: options.timeoutMs,
|
|
73
95
|
maxRetries: options.maxRetries,
|
|
74
96
|
behaviorStore
|
|
75
97
|
});
|
|
76
98
|
const prompts = new PromptResource(transport, options.cache, {
|
|
77
|
-
projectId
|
|
78
|
-
env
|
|
99
|
+
projectId,
|
|
100
|
+
env,
|
|
101
|
+
format: options.format,
|
|
102
|
+
onUnknownRole: options.onUnknownRole
|
|
79
103
|
});
|
|
80
104
|
const projectEnvironments = new ProjectEnvironmentResource(transport);
|
|
81
105
|
const routingRules = new RoutingRulesResource(transport);
|
|
106
|
+
const gatewayAuthContext = () => {
|
|
107
|
+
if (apiKey === undefined) {
|
|
108
|
+
throw new Error("[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.");
|
|
109
|
+
}
|
|
110
|
+
if (projectId === undefined) {
|
|
111
|
+
throw new Error("[to11ai/sdk] session()/turn() need a `projectId` (or `TO11_PROJECT_ID`).");
|
|
112
|
+
}
|
|
113
|
+
return env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId };
|
|
114
|
+
};
|
|
115
|
+
let defaultSession;
|
|
116
|
+
const clientDefaultSession = () => {
|
|
117
|
+
if (defaultSession === undefined) {
|
|
118
|
+
defaultSession = new Session(gatewayAuthContext());
|
|
119
|
+
}
|
|
120
|
+
return defaultSession;
|
|
121
|
+
};
|
|
122
|
+
const gatewayClientOptions = (defaultBaseURL, overrides) => {
|
|
123
|
+
if (apiKey === undefined) {
|
|
124
|
+
throw new Error("[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.");
|
|
125
|
+
}
|
|
126
|
+
if (projectId === undefined) {
|
|
127
|
+
throw new Error("[to11ai/sdk] openaiOptions()/anthropicOptions() need a `projectId` (or `TO11_PROJECT_ID`) — it authenticates the gateway call via `x-to11-project-id`.");
|
|
128
|
+
}
|
|
129
|
+
const authHeaders = gatewayAuthHeaders(env !== undefined ? { apiKey, projectId, env } : { apiKey, projectId });
|
|
130
|
+
const {
|
|
131
|
+
apiKey: overrideApiKey,
|
|
132
|
+
baseURL: overrideBaseURL,
|
|
133
|
+
defaultHeaders: overrideHeaders,
|
|
134
|
+
...passthrough
|
|
135
|
+
} = overrides ?? {};
|
|
136
|
+
return {
|
|
137
|
+
...passthrough,
|
|
138
|
+
baseURL: overrideBaseURL ?? defaultBaseURL,
|
|
139
|
+
apiKey: overrideApiKey ?? providerApiKey ?? apiKey,
|
|
140
|
+
defaultHeaders: { ...authHeaders, ...overrideHeaders }
|
|
141
|
+
};
|
|
142
|
+
};
|
|
82
143
|
return {
|
|
83
144
|
prompts,
|
|
84
145
|
projectEnvironments,
|
|
85
146
|
routingRules,
|
|
86
|
-
resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault)
|
|
147
|
+
resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault),
|
|
148
|
+
apiKey,
|
|
149
|
+
gatewayUrl,
|
|
150
|
+
session: (id) => new Session(gatewayAuthContext(), id),
|
|
151
|
+
conversation: (id) => clientDefaultSession().conversation(id),
|
|
152
|
+
turn: () => clientDefaultSession().turn(),
|
|
153
|
+
openaiOptions: (overrides) => gatewayClientOptions(`${gatewayUrl}/v1`, overrides),
|
|
154
|
+
anthropicOptions: (overrides) => gatewayClientOptions(gatewayUrl, overrides)
|
|
87
155
|
};
|
|
88
156
|
}
|
|
89
157
|
export {
|
|
90
158
|
gatewayPromptHeaders,
|
|
91
|
-
gatewayAuthHeaders,
|
|
159
|
+
gatewayAuthHeaders2 as gatewayAuthHeaders,
|
|
92
160
|
envVarNameForKey,
|
|
93
161
|
createClient,
|
|
162
|
+
UnknownRoleError,
|
|
163
|
+
Turn,
|
|
94
164
|
To11aiValidationError,
|
|
95
165
|
To11aiRateLimitError,
|
|
96
166
|
To11aiNetworkError,
|
|
97
167
|
To11aiError,
|
|
98
168
|
To11aiAuthError,
|
|
99
169
|
To11aiApiError,
|
|
170
|
+
Session2 as Session,
|
|
100
171
|
RuleVersionInvalidSnapshotError,
|
|
101
172
|
RuleNotFoundError,
|
|
102
173
|
RoutingRulesResource2 as RoutingRulesResource,
|
|
@@ -112,6 +183,7 @@ export {
|
|
|
112
183
|
EnvNotFoundError,
|
|
113
184
|
EnvNotEnabledForProviderError,
|
|
114
185
|
ENV_SLUG_REGEX2 as ENV_SLUG_REGEX,
|
|
186
|
+
Conversation,
|
|
115
187
|
BehaviorStore2 as BehaviorStore,
|
|
116
188
|
AmbiguousEnvLabelsError
|
|
117
189
|
};
|
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";
|