@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/errors.cjs
CHANGED
|
@@ -39,6 +39,7 @@ var __export = (target, all) => {
|
|
|
39
39
|
// src/errors.ts
|
|
40
40
|
var exports_errors = {};
|
|
41
41
|
__export(exports_errors, {
|
|
42
|
+
UnknownRoleError: () => UnknownRoleError,
|
|
42
43
|
To11aiValidationError: () => To11aiValidationError,
|
|
43
44
|
To11aiResponseValidationError: () => To11aiResponseValidationError,
|
|
44
45
|
To11aiRateLimitError: () => To11aiRateLimitError,
|
|
@@ -53,9 +54,9 @@ __export(exports_errors, {
|
|
|
53
54
|
PromptLabelNotRegisteredError: () => PromptLabelNotRegisteredError,
|
|
54
55
|
NoApplicableRouteError: () => NoApplicableRouteError,
|
|
55
56
|
NoActiveReleaseError: () => NoActiveReleaseError,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
MissingLabelError: () => MissingLabelError,
|
|
58
|
+
LabelNotFoundError: () => LabelNotFoundError,
|
|
59
|
+
EnvNotEnabledForProviderError: () => EnvNotEnabledForProviderError
|
|
59
60
|
});
|
|
60
61
|
module.exports = __toCommonJS(exports_errors);
|
|
61
62
|
|
|
@@ -130,6 +131,22 @@ class To11aiResponseValidationError extends To11aiError {
|
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
class UnknownRoleError extends To11aiError {
|
|
135
|
+
code = "unknown_role";
|
|
136
|
+
role;
|
|
137
|
+
index;
|
|
138
|
+
constructor(role, index) {
|
|
139
|
+
super(`[to11ai/sdk] message[${index}] has unknown role ${JSON.stringify(role)}; expected system|user|assistant|developer|tool`);
|
|
140
|
+
this.name = "UnknownRoleError";
|
|
141
|
+
this.role = role;
|
|
142
|
+
this.index = index;
|
|
143
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
144
|
+
}
|
|
145
|
+
static is(err) {
|
|
146
|
+
return err instanceof UnknownRoleError;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
133
150
|
class PromptLabelNotRegisteredError extends To11aiApiError {
|
|
134
151
|
projectId;
|
|
135
152
|
label;
|
|
@@ -209,19 +226,27 @@ class PromptNotFoundError extends To11aiApiError {
|
|
|
209
226
|
}
|
|
210
227
|
}
|
|
211
228
|
|
|
212
|
-
class
|
|
213
|
-
|
|
214
|
-
constructor(message,
|
|
229
|
+
class LabelNotFoundError extends To11aiApiError {
|
|
230
|
+
label;
|
|
231
|
+
constructor(message, label, details, statusCode) {
|
|
215
232
|
super(message, statusCode, "ENV_NOT_FOUND", details);
|
|
216
|
-
this.name = "
|
|
217
|
-
this.
|
|
233
|
+
this.name = "LabelNotFoundError";
|
|
234
|
+
this.label = label;
|
|
218
235
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
219
236
|
}
|
|
220
|
-
static
|
|
221
|
-
return
|
|
237
|
+
static is(err) {
|
|
238
|
+
return err instanceof LabelNotFoundError;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
class MissingLabelError extends To11aiError {
|
|
243
|
+
constructor(message = "[to11ai/sdk] No label resolvable for prompts.render(): none supplied per call, and no client env (or TO11_ENV) to fall back to. Pass `label` to render(slug, { label }) or set `env` on createClient.") {
|
|
244
|
+
super(message);
|
|
245
|
+
this.name = "MissingLabelError";
|
|
246
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
222
247
|
}
|
|
223
248
|
static is(err) {
|
|
224
|
-
return err instanceof
|
|
249
|
+
return err instanceof MissingLabelError;
|
|
225
250
|
}
|
|
226
251
|
}
|
|
227
252
|
|
|
@@ -251,19 +276,6 @@ class PromptPolicyViolationError extends To11aiApiError {
|
|
|
251
276
|
}
|
|
252
277
|
}
|
|
253
278
|
|
|
254
|
-
class AmbiguousEnvLabelsError extends To11aiApiError {
|
|
255
|
-
reason;
|
|
256
|
-
constructor(message, reason, details, statusCode = 409) {
|
|
257
|
-
super(message, statusCode, "AMBIGUOUS_ENV_LABELS", details);
|
|
258
|
-
this.name = "AmbiguousEnvLabelsError";
|
|
259
|
-
this.reason = reason;
|
|
260
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
261
|
-
}
|
|
262
|
-
static is(err) {
|
|
263
|
-
return err instanceof AmbiguousEnvLabelsError;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
279
|
class RuleVersionInvalidSnapshotError extends To11aiApiError {
|
|
268
280
|
field;
|
|
269
281
|
reason;
|
package/dist/errors.d.ts
CHANGED
|
@@ -51,6 +51,23 @@ export declare class To11aiResponseValidationError extends To11aiError {
|
|
|
51
51
|
}[];
|
|
52
52
|
constructor(path: string, zodError: unknown, cause?: unknown);
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Thrown by the provider-shape converters (`toOpenAIMessages` /
|
|
56
|
+
* `toAnthropicMessages`, and `render({ format })`) in `onUnknownRole: "error"`
|
|
57
|
+
* mode when a message carries a role outside the known set
|
|
58
|
+
* (`system | user | assistant | developer | tool`). `code` is the stable
|
|
59
|
+
* `"unknown_role"` slug; `role` / `index` locate the offending turn.
|
|
60
|
+
*
|
|
61
|
+
* A client-side conversion error — it extends `To11aiError` (not
|
|
62
|
+
* `To11aiApiError`), so it never carries an HTTP status.
|
|
63
|
+
*/
|
|
64
|
+
export declare class UnknownRoleError extends To11aiError {
|
|
65
|
+
readonly code = "unknown_role";
|
|
66
|
+
readonly role: string;
|
|
67
|
+
readonly index: number;
|
|
68
|
+
constructor(role: string, index: number);
|
|
69
|
+
static is(err: unknown): err is UnknownRoleError;
|
|
70
|
+
}
|
|
54
71
|
/**
|
|
55
72
|
* Thrown when strict-mode rejects a label move for an unregistered label.
|
|
56
73
|
*
|
|
@@ -154,35 +171,29 @@ export declare class PromptNotFoundError extends To11aiApiError {
|
|
|
154
171
|
static is(err: unknown): err is PromptNotFoundError;
|
|
155
172
|
}
|
|
156
173
|
/**
|
|
157
|
-
*
|
|
174
|
+
* Thrown when the label supplied to `prompts.render()` does not resolve to an
|
|
175
|
+
* existing (active) label on the server. Surfaced from the server's
|
|
176
|
+
* `ENV_NOT_FOUND` code; `label` carries the rejected slug when the server
|
|
177
|
+
* echoes it.
|
|
158
178
|
*
|
|
159
|
-
* `
|
|
160
|
-
*
|
|
161
|
-
* CLIENT-side, eagerly, before any request (R4 / AC4); `env` is absent.
|
|
162
|
-
* - `"unknown"` — an env was supplied but the server's registry has no
|
|
163
|
-
* such (active) env. Surfaced from the `ENV_NOT_FOUND` server code; `env`
|
|
164
|
-
* carries the rejected slug when the server echoes it.
|
|
179
|
+
* This is distinct from `MissingLabelError`, which is raised client-side when
|
|
180
|
+
* no label was supplied at all.
|
|
165
181
|
*/
|
|
166
|
-
export
|
|
167
|
-
|
|
168
|
-
|
|
182
|
+
export declare class LabelNotFoundError extends To11aiApiError {
|
|
183
|
+
/** The label slug that could not be found, when the server echoes it. */
|
|
184
|
+
readonly label?: string;
|
|
185
|
+
constructor(message: string, label: string | undefined, details: unknown, statusCode: number);
|
|
186
|
+
static is(err: unknown): err is LabelNotFoundError;
|
|
169
187
|
}
|
|
170
188
|
/**
|
|
171
|
-
* Thrown
|
|
172
|
-
*
|
|
173
|
-
* `
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* The client-eager variant carries no `statusCode`/`errorCode` from the wire
|
|
177
|
-
* (no request was made); it reports status `0` and errorCode `ENV_NOT_FOUND`
|
|
178
|
-
* for a uniform catch surface.
|
|
189
|
+
* Thrown CLIENT-side, eagerly (before any request), when `prompts.render()` is
|
|
190
|
+
* called but no label is resolvable at all: none supplied per call, and no
|
|
191
|
+
* client `env` (or `TO11_ENV`) to fall back to. A usage error, not a lookup
|
|
192
|
+
* failure — distinct from `LabelNotFoundError`.
|
|
179
193
|
*/
|
|
180
|
-
export declare class
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
/** Build the client-eager (missing-at-both) variant — no transport call. */
|
|
184
|
-
static missing(env?: string): EnvNotFoundError;
|
|
185
|
-
static is(err: unknown): err is EnvNotFoundError;
|
|
194
|
+
export declare class MissingLabelError extends To11aiError {
|
|
195
|
+
constructor(message?: string);
|
|
196
|
+
static is(err: unknown): err is MissingLabelError;
|
|
186
197
|
}
|
|
187
198
|
/**
|
|
188
199
|
* Reason payload for `NoActiveReleaseError`.
|
|
@@ -233,28 +244,6 @@ export declare class PromptPolicyViolationError extends To11aiApiError {
|
|
|
233
244
|
constructor(message: string, reason: PromptPolicyViolationReason, details?: unknown, statusCode?: number);
|
|
234
245
|
static is(err: unknown): err is PromptPolicyViolationError;
|
|
235
246
|
}
|
|
236
|
-
/**
|
|
237
|
-
* Reason payload for `AmbiguousEnvLabelsError`.
|
|
238
|
-
*
|
|
239
|
-
* Carried when the supplied env-label matched more than one candidate
|
|
240
|
-
* version and the server cannot pick deterministically
|
|
241
|
-
* (`AMBIGUOUS_ENV_LABELS`).
|
|
242
|
-
*/
|
|
243
|
-
export interface AmbiguousEnvLabelsReason {
|
|
244
|
-
env?: string;
|
|
245
|
-
slug?: string;
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Thrown when the env→label resolution is ambiguous on the server
|
|
249
|
-
* (`AMBIGUOUS_ENV_LABELS`) — the label matched multiple candidates and the
|
|
250
|
-
* server declines to guess. Surfaces (rather than 500ing) so callers get a
|
|
251
|
-
* typed, actionable error.
|
|
252
|
-
*/
|
|
253
|
-
export declare class AmbiguousEnvLabelsError extends To11aiApiError {
|
|
254
|
-
readonly reason: AmbiguousEnvLabelsReason;
|
|
255
|
-
constructor(message: string, reason: AmbiguousEnvLabelsReason, details?: unknown, statusCode?: number);
|
|
256
|
-
static is(err: unknown): err is AmbiguousEnvLabelsError;
|
|
257
|
-
}
|
|
258
247
|
/**
|
|
259
248
|
* Thrown when version create rejects the snapshot for a structural
|
|
260
249
|
* reason — invalid variant params, malformed `when` clause, illegal
|
package/dist/errors.js
CHANGED
|
@@ -70,6 +70,22 @@ class To11aiResponseValidationError extends To11aiError {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
class UnknownRoleError extends To11aiError {
|
|
74
|
+
code = "unknown_role";
|
|
75
|
+
role;
|
|
76
|
+
index;
|
|
77
|
+
constructor(role, index) {
|
|
78
|
+
super(`[to11ai/sdk] message[${index}] has unknown role ${JSON.stringify(role)}; expected system|user|assistant|developer|tool`);
|
|
79
|
+
this.name = "UnknownRoleError";
|
|
80
|
+
this.role = role;
|
|
81
|
+
this.index = index;
|
|
82
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
83
|
+
}
|
|
84
|
+
static is(err) {
|
|
85
|
+
return err instanceof UnknownRoleError;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
73
89
|
class PromptLabelNotRegisteredError extends To11aiApiError {
|
|
74
90
|
projectId;
|
|
75
91
|
label;
|
|
@@ -149,19 +165,27 @@ class PromptNotFoundError extends To11aiApiError {
|
|
|
149
165
|
}
|
|
150
166
|
}
|
|
151
167
|
|
|
152
|
-
class
|
|
153
|
-
|
|
154
|
-
constructor(message,
|
|
168
|
+
class LabelNotFoundError extends To11aiApiError {
|
|
169
|
+
label;
|
|
170
|
+
constructor(message, label, details, statusCode) {
|
|
155
171
|
super(message, statusCode, "ENV_NOT_FOUND", details);
|
|
156
|
-
this.name = "
|
|
157
|
-
this.
|
|
172
|
+
this.name = "LabelNotFoundError";
|
|
173
|
+
this.label = label;
|
|
158
174
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
159
175
|
}
|
|
160
|
-
static
|
|
161
|
-
return
|
|
176
|
+
static is(err) {
|
|
177
|
+
return err instanceof LabelNotFoundError;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class MissingLabelError extends To11aiError {
|
|
182
|
+
constructor(message = "[to11ai/sdk] No label resolvable for prompts.render(): none supplied per call, and no client env (or TO11_ENV) to fall back to. Pass `label` to render(slug, { label }) or set `env` on createClient.") {
|
|
183
|
+
super(message);
|
|
184
|
+
this.name = "MissingLabelError";
|
|
185
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
162
186
|
}
|
|
163
187
|
static is(err) {
|
|
164
|
-
return err instanceof
|
|
188
|
+
return err instanceof MissingLabelError;
|
|
165
189
|
}
|
|
166
190
|
}
|
|
167
191
|
|
|
@@ -191,19 +215,6 @@ class PromptPolicyViolationError extends To11aiApiError {
|
|
|
191
215
|
}
|
|
192
216
|
}
|
|
193
217
|
|
|
194
|
-
class AmbiguousEnvLabelsError extends To11aiApiError {
|
|
195
|
-
reason;
|
|
196
|
-
constructor(message, reason, details, statusCode = 409) {
|
|
197
|
-
super(message, statusCode, "AMBIGUOUS_ENV_LABELS", details);
|
|
198
|
-
this.name = "AmbiguousEnvLabelsError";
|
|
199
|
-
this.reason = reason;
|
|
200
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
201
|
-
}
|
|
202
|
-
static is(err) {
|
|
203
|
-
return err instanceof AmbiguousEnvLabelsError;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
218
|
class RuleVersionInvalidSnapshotError extends To11aiApiError {
|
|
208
219
|
field;
|
|
209
220
|
reason;
|
|
@@ -221,6 +232,7 @@ class RuleVersionInvalidSnapshotError extends To11aiApiError {
|
|
|
221
232
|
}
|
|
222
233
|
}
|
|
223
234
|
export {
|
|
235
|
+
UnknownRoleError,
|
|
224
236
|
To11aiValidationError,
|
|
225
237
|
To11aiResponseValidationError,
|
|
226
238
|
To11aiRateLimitError,
|
|
@@ -235,7 +247,7 @@ export {
|
|
|
235
247
|
PromptLabelNotRegisteredError,
|
|
236
248
|
NoApplicableRouteError,
|
|
237
249
|
NoActiveReleaseError,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
250
|
+
MissingLabelError,
|
|
251
|
+
LabelNotFoundError,
|
|
252
|
+
EnvNotEnabledForProviderError
|
|
241
253
|
};
|
package/dist/gateway.cjs
CHANGED
|
@@ -44,11 +44,13 @@ __export(exports_gateway, {
|
|
|
44
44
|
toOpenAIMessages: () => toOpenAIMessages,
|
|
45
45
|
toAnthropicTools: () => toAnthropicTools,
|
|
46
46
|
toAnthropicToolChoice: () => toAnthropicToolChoice,
|
|
47
|
+
toAnthropicSystem: () => toAnthropicSystem,
|
|
47
48
|
toAnthropicMessages: () => toAnthropicMessages,
|
|
48
49
|
gatewayPromptHeaders: () => gatewayPromptHeaders,
|
|
49
50
|
gatewayAuthHeaders: () => gatewayAuthHeaders
|
|
50
51
|
});
|
|
51
52
|
module.exports = __toCommonJS(exports_gateway);
|
|
53
|
+
var import_errors = require("./errors");
|
|
52
54
|
var import_types = require("./prompts/types");
|
|
53
55
|
function gatewayAuthHeaders(options) {
|
|
54
56
|
if (options.apiKey.trim().length === 0) {
|
|
@@ -73,20 +75,27 @@ function gatewayAuthHeaders(options) {
|
|
|
73
75
|
return headers;
|
|
74
76
|
}
|
|
75
77
|
function gatewayPromptHeaders(prompt) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
const p = prompt != null && "metadata" in prompt ? prompt.metadata : prompt;
|
|
79
|
+
const headers = {};
|
|
80
|
+
if (p == null)
|
|
81
|
+
return headers;
|
|
82
|
+
if (typeof p.promptId === "string" && p.promptId.length > 0) {
|
|
83
|
+
headers["x-to11-prompt-id"] = p.promptId;
|
|
84
|
+
}
|
|
85
|
+
if (typeof p.version === "number" && Number.isFinite(p.version)) {
|
|
86
|
+
headers["x-to11-prompt-version"] = String(p.version);
|
|
87
|
+
}
|
|
88
|
+
if (typeof p.releaseId === "string" && p.releaseId.length > 0) {
|
|
89
|
+
headers["x-to11-release-id"] = p.releaseId;
|
|
83
90
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
headers["x-to11-variant-name"] = variantName;
|
|
91
|
+
if (typeof p.variantName === "string" && p.variantName.length > 0) {
|
|
92
|
+
headers["x-to11-variant-name"] = p.variantName;
|
|
87
93
|
}
|
|
88
|
-
if (
|
|
89
|
-
headers["x-to11-prompt-
|
|
94
|
+
if (typeof p.label === "string" && p.label.length > 0) {
|
|
95
|
+
headers["x-to11-prompt-label"] = p.label;
|
|
96
|
+
}
|
|
97
|
+
if (typeof p.slug === "string" && p.slug.length > 0) {
|
|
98
|
+
headers["x-to11-prompt-slug"] = p.slug;
|
|
90
99
|
}
|
|
91
100
|
return headers;
|
|
92
101
|
}
|
|
@@ -142,41 +151,73 @@ function requireToolCallId(id) {
|
|
|
142
151
|
}
|
|
143
152
|
return id;
|
|
144
153
|
}
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
var KNOWN_RENDERED_ROLES = new Set([
|
|
155
|
+
"system",
|
|
156
|
+
"user",
|
|
157
|
+
"assistant",
|
|
158
|
+
"developer",
|
|
159
|
+
"tool"
|
|
160
|
+
]);
|
|
161
|
+
function skipUnknownRole(role, index, mode) {
|
|
162
|
+
if (KNOWN_RENDERED_ROLES.has(role))
|
|
163
|
+
return false;
|
|
164
|
+
if (mode === "error")
|
|
165
|
+
throw new import_errors.UnknownRoleError(role, index);
|
|
166
|
+
if (mode === "warn") {
|
|
167
|
+
console.warn(`[to11ai/sdk] dropped message[${index}] with unknown role ${JSON.stringify(role)} (expected system|user|assistant|developer|tool)`);
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
function toOpenAIMessages(messages, options = {}) {
|
|
172
|
+
const mode = options.onUnknownRole ?? "drop";
|
|
173
|
+
const out = [];
|
|
174
|
+
messages.forEach((message, index) => {
|
|
175
|
+
if (skipUnknownRole(message.role, index, mode))
|
|
176
|
+
return;
|
|
147
177
|
if (message.role === "tool") {
|
|
148
|
-
|
|
178
|
+
out.push({
|
|
149
179
|
role: "tool",
|
|
150
180
|
tool_call_id: requireToolCallId(message.toolCallId),
|
|
151
181
|
content: message.content ?? ""
|
|
152
|
-
};
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
153
184
|
}
|
|
154
185
|
if (message.role === "assistant") {
|
|
155
|
-
const
|
|
186
|
+
const content2 = message.content ?? null;
|
|
187
|
+
out.push(message.toolCalls != null && message.toolCalls.length > 0 ? {
|
|
156
188
|
role: "assistant",
|
|
157
|
-
content:
|
|
158
|
-
|
|
159
|
-
if (message.toolCalls != null && message.toolCalls.length > 0) {
|
|
160
|
-
out.tool_calls = message.toolCalls.map((call) => ({
|
|
189
|
+
content: content2,
|
|
190
|
+
tool_calls: message.toolCalls.map((call) => ({
|
|
161
191
|
id: requireToolCallId(call.id),
|
|
162
192
|
type: "function",
|
|
163
193
|
function: {
|
|
164
194
|
name: call.name,
|
|
165
195
|
arguments: JSON.stringify(call.arguments)
|
|
166
196
|
}
|
|
167
|
-
}))
|
|
168
|
-
}
|
|
169
|
-
return
|
|
197
|
+
}))
|
|
198
|
+
} : { role: "assistant", content: content2 });
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const content = message.content ?? "";
|
|
202
|
+
if (message.role === "user") {
|
|
203
|
+
out.push({ role: "user", content });
|
|
204
|
+
} else if (message.role === "developer") {
|
|
205
|
+
out.push({ role: "developer", content });
|
|
206
|
+
} else {
|
|
207
|
+
out.push({ role: "system", content });
|
|
170
208
|
}
|
|
171
|
-
return { role: message.role, content: message.content ?? "" };
|
|
172
209
|
});
|
|
210
|
+
return out;
|
|
173
211
|
}
|
|
174
|
-
function toAnthropicMessages(messages) {
|
|
212
|
+
function toAnthropicMessages(messages, options = {}) {
|
|
213
|
+
const mode = options.onUnknownRole ?? "drop";
|
|
175
214
|
const out = [];
|
|
176
|
-
|
|
215
|
+
messages.forEach((message, index) => {
|
|
177
216
|
if (message.role === "system" || message.role === "developer") {
|
|
178
|
-
|
|
217
|
+
return;
|
|
179
218
|
}
|
|
219
|
+
if (skipUnknownRole(message.role, index, mode))
|
|
220
|
+
return;
|
|
180
221
|
if (message.role === "tool") {
|
|
181
222
|
out.push({
|
|
182
223
|
role: "user",
|
|
@@ -188,7 +229,7 @@ function toAnthropicMessages(messages) {
|
|
|
188
229
|
}
|
|
189
230
|
]
|
|
190
231
|
});
|
|
191
|
-
|
|
232
|
+
return;
|
|
192
233
|
}
|
|
193
234
|
if (message.role === "assistant") {
|
|
194
235
|
if (message.toolCalls != null && message.toolCalls.length > 0) {
|
|
@@ -208,9 +249,22 @@ function toAnthropicMessages(messages) {
|
|
|
208
249
|
} else {
|
|
209
250
|
out.push({ role: "assistant", content: message.content ?? "" });
|
|
210
251
|
}
|
|
211
|
-
|
|
252
|
+
return;
|
|
212
253
|
}
|
|
213
254
|
out.push({ role: "user", content: message.content ?? "" });
|
|
214
|
-
}
|
|
255
|
+
});
|
|
215
256
|
return out;
|
|
216
257
|
}
|
|
258
|
+
function toAnthropicSystem(messages) {
|
|
259
|
+
const parts = [];
|
|
260
|
+
for (const message of messages) {
|
|
261
|
+
if (message.role !== "system" && message.role !== "developer")
|
|
262
|
+
continue;
|
|
263
|
+
if (typeof message.content === "string" && message.content.length > 0) {
|
|
264
|
+
parts.push(message.content);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return parts.length > 0 ? parts.join(`
|
|
268
|
+
|
|
269
|
+
`) : undefined;
|
|
270
|
+
}
|
package/dist/gateway.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type RenderedChatMessage, type ResolvedPrompt, type ResolvedToolDefinition, type UnknownRoleMode } from "./prompts/types";
|
|
2
2
|
export interface GatewayAuthOptions {
|
|
3
3
|
apiKey: string;
|
|
4
4
|
projectId: string;
|
|
@@ -30,29 +30,46 @@ export interface GatewayAuthOptions {
|
|
|
30
30
|
*/
|
|
31
31
|
export declare function gatewayAuthHeaders(options: GatewayAuthOptions): Record<string, string>;
|
|
32
32
|
/**
|
|
33
|
-
* Build prompt provenance headers from a
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
33
|
+
* Build prompt provenance headers from a `render()` result (or a format-shaped
|
|
34
|
+
* result's `metadata`, unwrapped automatically).
|
|
35
|
+
*
|
|
36
|
+
* No provenance header is required, and the gateway rejects empty header
|
|
37
|
+
* values — so each header is emitted only when its value is present and valid,
|
|
38
|
+
* and the function never throws:
|
|
39
|
+
* - `x-to11-prompt-id` — a non-empty string.
|
|
40
|
+
* - `x-to11-prompt-version` — a finite number (a non-number/NaN is dropped
|
|
41
|
+
* rather than stringified to junk like `"[object Object]"`).
|
|
42
|
+
* - `x-to11-release-id` — a non-empty `releaseId` (the offline-fallback path
|
|
43
|
+
* can carry an explicit `null`, which is omitted).
|
|
44
|
+
* - `x-to11-variant-name` — present IFF the resolved release was weighted.
|
|
45
|
+
* - `x-to11-prompt-label` — the single label the prompt resolved through.
|
|
46
|
+
* - `x-to11-prompt-slug` — the prompt's human-readable slug.
|
|
47
|
+
*
|
|
48
|
+
* An input with no usable provenance yields an empty header bag — the same as
|
|
49
|
+
* a prompt-less `turn.headers()` call.
|
|
50
50
|
*
|
|
51
51
|
* @example
|
|
52
|
-
* const result = await client.prompts.
|
|
52
|
+
* const result = await client.prompts.render(slug, { label: "prod" });
|
|
53
53
|
* const headers = gatewayPromptHeaders(result);
|
|
54
54
|
*/
|
|
55
|
-
export
|
|
55
|
+
export interface GatewayPromptProvenance {
|
|
56
|
+
promptId: string;
|
|
57
|
+
version: number;
|
|
58
|
+
/** The single label the prompt resolved through (env slug today). */
|
|
59
|
+
label: string;
|
|
60
|
+
/**
|
|
61
|
+
* The prompt's human-readable slug (the `render()`/`resolve()` input). Present
|
|
62
|
+
* on an enriched `render()` result; a legacy `ResolvedPrompt` omits it.
|
|
63
|
+
*/
|
|
64
|
+
slug?: string;
|
|
65
|
+
/** Present on an enriched result; a legacy `resolve()` result omits it. */
|
|
66
|
+
releaseId?: string | null;
|
|
67
|
+
/** Present IFF the resolved release was weighted. */
|
|
68
|
+
variantName?: string;
|
|
69
|
+
}
|
|
70
|
+
export declare function gatewayPromptHeaders(prompt: GatewayPromptProvenance | {
|
|
71
|
+
metadata: GatewayPromptProvenance;
|
|
72
|
+
}): Record<string, string>;
|
|
56
73
|
/** OpenAI Chat Completions `tools[]` entry (`function` tool). */
|
|
57
74
|
export interface OpenAITool {
|
|
58
75
|
type: "function";
|
|
@@ -78,13 +95,33 @@ export interface OpenAIToolCall {
|
|
|
78
95
|
arguments: string;
|
|
79
96
|
};
|
|
80
97
|
}
|
|
81
|
-
/**
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
/**
|
|
99
|
+
* OpenAI Chat Completions `messages[]` entry — a per-role discriminated union
|
|
100
|
+
* matching what Chat Completions requires for each role, so an
|
|
101
|
+
* `OpenAIChatMessage[]` is structurally assignable to the `openai` package's
|
|
102
|
+
* `ChatCompletionMessageParam[]` (a `render({ format: "openai" })` result spreads
|
|
103
|
+
* straight into `openai.chat.completions.create({ messages })` with no cast).
|
|
104
|
+
* The SDK carries no dependency on the `openai` package — this only mirrors its
|
|
105
|
+
* shape. (Assignability is regression-guarded in `gateway.provider-types.test.ts`.)
|
|
106
|
+
*/
|
|
107
|
+
export type OpenAIChatMessage = {
|
|
108
|
+
role: "system";
|
|
109
|
+
content: string;
|
|
110
|
+
} | {
|
|
111
|
+
role: "developer";
|
|
112
|
+
content: string;
|
|
113
|
+
} | {
|
|
114
|
+
role: "user";
|
|
115
|
+
content: string;
|
|
116
|
+
} | {
|
|
117
|
+
role: "assistant";
|
|
84
118
|
content?: string | null;
|
|
85
119
|
tool_calls?: OpenAIToolCall[];
|
|
86
|
-
|
|
87
|
-
|
|
120
|
+
} | {
|
|
121
|
+
role: "tool";
|
|
122
|
+
tool_call_id: string;
|
|
123
|
+
content: string;
|
|
124
|
+
};
|
|
88
125
|
/** Anthropic Messages `tools[]` entry. */
|
|
89
126
|
export interface AnthropicTool {
|
|
90
127
|
name: string;
|
|
@@ -175,6 +212,16 @@ export declare function toAnthropicTools(tools: ReadonlyArray<ResolvedToolDefini
|
|
|
175
212
|
* await anthropic.messages.create({ model, system, messages, tools, tool_choice });
|
|
176
213
|
*/
|
|
177
214
|
export declare function toAnthropicToolChoice(toolChoice: ResolvedPrompt["toolChoice"]): AnthropicToolChoice | undefined;
|
|
215
|
+
/** Options shared by the message converters. */
|
|
216
|
+
export interface ConvertMessagesOptions {
|
|
217
|
+
/**
|
|
218
|
+
* Policy for a message whose role is outside the known set
|
|
219
|
+
* (`system | user | assistant | developer | tool`). `"drop"` (default) omits
|
|
220
|
+
* it silently; `"warn"` omits it and emits a `console.warn`; `"error"` throws
|
|
221
|
+
* {@link UnknownRoleError}. Both converters apply this identically.
|
|
222
|
+
*/
|
|
223
|
+
onUnknownRole?: UnknownRoleMode;
|
|
224
|
+
}
|
|
178
225
|
/**
|
|
179
226
|
* Shape rendered turns for the OpenAI Chat Completions `messages` field.
|
|
180
227
|
*
|
|
@@ -184,11 +231,15 @@ export declare function toAnthropicToolChoice(toolChoice: ResolvedPrompt["toolCh
|
|
|
184
231
|
* become `tool_calls[]` with JSON-stringified `arguments` (the OpenAI wire
|
|
185
232
|
* shape). A pure tool-call turn keeps `content: null`.
|
|
186
233
|
* - `tool` (result) → `{ role: "tool", tool_call_id, content }`.
|
|
234
|
+
* - an unrecognized role is handled per `options.onUnknownRole` (default
|
|
235
|
+
* `"drop"`) — dropped, dropped-with-warning, or throws `UnknownRoleError`.
|
|
187
236
|
*
|
|
188
237
|
* @example
|
|
189
238
|
* const messages = toOpenAIMessages(prompt.messages);
|
|
239
|
+
* @example Fail loudly on a malformed message array
|
|
240
|
+
* const messages = toOpenAIMessages(history, { onUnknownRole: "error" });
|
|
190
241
|
*/
|
|
191
|
-
export declare function toOpenAIMessages(messages: ReadonlyArray<RenderedChatMessage
|
|
242
|
+
export declare function toOpenAIMessages(messages: ReadonlyArray<RenderedChatMessage>, options?: ConvertMessagesOptions): OpenAIChatMessage[];
|
|
192
243
|
/**
|
|
193
244
|
* Shape rendered turns for the Anthropic Messages `messages` field.
|
|
194
245
|
*
|
|
@@ -201,8 +252,32 @@ export declare function toOpenAIMessages(messages: ReadonlyArray<RenderedChatMes
|
|
|
201
252
|
* ...tool_use] }`; without calls → `{ role: "assistant", content }`.
|
|
202
253
|
* - `tool` (result) → `{ role: "user", content: [{ type: "tool_result",
|
|
203
254
|
* tool_use_id, content }] }`.
|
|
255
|
+
* - an unrecognized role is handled per `options.onUnknownRole` (default
|
|
256
|
+
* `"drop"`) — dropped, dropped-with-warning, or throws `UnknownRoleError` —
|
|
257
|
+
* identically to {@link toOpenAIMessages}. (`system`/`developer` are known
|
|
258
|
+
* roles folded into `system`, not "unknown"; they are never dropped here.)
|
|
204
259
|
*
|
|
205
260
|
* @example
|
|
206
261
|
* const messages = toAnthropicMessages(prompt.messages);
|
|
262
|
+
* @example Fail loudly on a malformed message array
|
|
263
|
+
* const messages = toAnthropicMessages(history, { onUnknownRole: "error" });
|
|
264
|
+
*/
|
|
265
|
+
export declare function toAnthropicMessages(messages: ReadonlyArray<RenderedChatMessage>, options?: ConvertMessagesOptions): AnthropicMessage[];
|
|
266
|
+
/**
|
|
267
|
+
* Fold the `system` and `developer` instruction turns into Anthropic's
|
|
268
|
+
* top-level `system` string. Anthropic has no `developer` role and takes system
|
|
269
|
+
* instructions as a separate request field, so pair this with
|
|
270
|
+
* {@link toAnthropicMessages} (which omits those turns). Returns `undefined`
|
|
271
|
+
* when there is no system/developer content.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* const res = await anthropic.messages.create(
|
|
275
|
+
* {
|
|
276
|
+
* ...prompt.config,
|
|
277
|
+
* system: toAnthropicSystem(prompt.messages),
|
|
278
|
+
* messages: toAnthropicMessages(prompt.messages),
|
|
279
|
+
* },
|
|
280
|
+
* { headers: to11.turn().headers(prompt) },
|
|
281
|
+
* );
|
|
207
282
|
*/
|
|
208
|
-
export declare function
|
|
283
|
+
export declare function toAnthropicSystem(messages: ReadonlyArray<RenderedChatMessage>): string | undefined;
|