@to11ai/sdk 0.7.0 → 1.0.0

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
@@ -12,7 +12,7 @@ export { ProjectEnvironmentResource } from "./projectEnvironments/resource";
12
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, PromptContext, RenderedChatMessage, RenderedPrompt, ResolvedPrompt, ResolvedPromptEnvelope, } from "./prompts/types";
15
+ export type { BlockRenderRecord, DeveloperRole, FetchedPrompt, FetchPromptOptions, RenderedChatMessage, RenderedPrompt, ResolvedPrompt, ResolvedPromptEnvelope, } from "./prompts/types";
16
16
  export { ENV_SLUG_REGEX } from "./prompts/types";
17
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
18
  export { RoutingRuleReleaseResource, RoutingRulesResource, RoutingRuleVersionResource, } from "./routingRules/resource";
package/dist/gateway.cjs CHANGED
@@ -40,8 +40,10 @@ var __export = (target, all) => {
40
40
  var exports_gateway = {};
41
41
  __export(exports_gateway, {
42
42
  toOpenAITools: () => toOpenAITools,
43
+ toOpenAIToolChoice: () => toOpenAIToolChoice,
43
44
  toOpenAIMessages: () => toOpenAIMessages,
44
45
  toAnthropicTools: () => toAnthropicTools,
46
+ toAnthropicToolChoice: () => toAnthropicToolChoice,
45
47
  toAnthropicMessages: () => toAnthropicMessages,
46
48
  gatewayPromptHeaders: () => gatewayPromptHeaders,
47
49
  gatewayAuthHeaders: () => gatewayAuthHeaders
@@ -102,6 +104,13 @@ function toOpenAITools(tools) {
102
104
  return { type: "function", function: fn };
103
105
  });
104
106
  }
107
+ function toOpenAIToolChoice(toolChoice) {
108
+ if (toolChoice == null)
109
+ return;
110
+ if (typeof toolChoice === "string")
111
+ return toolChoice;
112
+ return { type: "function", function: { name: toolChoice.name } };
113
+ }
105
114
  function toAnthropicTools(tools) {
106
115
  if (tools == null)
107
116
  return [];
@@ -116,6 +125,17 @@ function toAnthropicTools(tools) {
116
125
  return out;
117
126
  });
118
127
  }
128
+ function toAnthropicToolChoice(toolChoice) {
129
+ if (toolChoice == null)
130
+ return;
131
+ if (toolChoice === "auto")
132
+ return { type: "auto" };
133
+ if (toolChoice === "none")
134
+ return { type: "none" };
135
+ if (toolChoice === "required")
136
+ return { type: "any" };
137
+ return { type: "tool", name: toolChoice.name };
138
+ }
119
139
  function requireToolCallId(id) {
120
140
  if (typeof id !== "string" || id.length === 0) {
121
141
  throw new Error("to11 SDK: malformed tool history — a tool call/result is missing its id (toolCallId). Author a non-empty id before converting messages.");
package/dist/gateway.d.ts CHANGED
@@ -62,6 +62,13 @@ export interface OpenAITool {
62
62
  parameters: Record<string, unknown>;
63
63
  };
64
64
  }
65
+ /** OpenAI `tool_choice` value for a Chat Completions request. */
66
+ export type OpenAIToolChoice = "auto" | "none" | "required" | {
67
+ type: "function";
68
+ function: {
69
+ name: string;
70
+ };
71
+ };
65
72
  /** OpenAI Chat Completions assistant `tool_calls[]` entry. */
66
73
  export interface OpenAIToolCall {
67
74
  id: string;
@@ -103,6 +110,17 @@ export interface AnthropicMessage {
103
110
  role: "user" | "assistant";
104
111
  content: string | AnthropicContentBlock[];
105
112
  }
113
+ /** Anthropic Messages `tool_choice` value. */
114
+ export type AnthropicToolChoice = {
115
+ type: "auto";
116
+ } | {
117
+ type: "any";
118
+ } | {
119
+ type: "none";
120
+ } | {
121
+ type: "tool";
122
+ name: string;
123
+ };
106
124
  /**
107
125
  * Shape resolved tool definitions for the OpenAI Chat Completions `tools`
108
126
  * field: `{ type: "function", function: { name, description?, parameters } }`.
@@ -112,9 +130,24 @@ export interface AnthropicMessage {
112
130
  *
113
131
  * @example
114
132
  * const tools = toOpenAITools(prompt.tools);
115
- * await openai.chat.completions.create({ model, messages, tools });
133
+ * const tool_choice = toOpenAIToolChoice(prompt.toolChoice);
134
+ * await openai.chat.completions.create({ model, messages, tools, tool_choice });
116
135
  */
117
136
  export declare function toOpenAITools(tools: ReadonlyArray<ResolvedToolDefinition> | null | undefined): OpenAITool[];
137
+ /**
138
+ * Map a resolved prompt's provider-neutral `toolChoice` to the OpenAI
139
+ * Chat Completions `tool_choice` field.
140
+ *
141
+ * - `null` / `undefined` → `undefined` (omit the field)
142
+ * - `"auto"` → `"auto"`, `"none"` → `"none"`, `"required"` → `"required"`
143
+ * - `{ name }` → `{ type: "function", function: { name } }`
144
+ *
145
+ * @example
146
+ * const tools = toOpenAITools(prompt.tools);
147
+ * const tool_choice = toOpenAIToolChoice(prompt.toolChoice);
148
+ * await openai.chat.completions.create({ model, messages, tools, tool_choice });
149
+ */
150
+ export declare function toOpenAIToolChoice(toolChoice: ResolvedPrompt["toolChoice"]): OpenAIToolChoice | undefined;
118
151
  /**
119
152
  * Shape resolved tool definitions for the Anthropic Messages `tools` field:
120
153
  * `{ name, description?, input_schema }` (Anthropic names the JSON Schema field
@@ -122,9 +155,26 @@ export declare function toOpenAITools(tools: ReadonlyArray<ResolvedToolDefinitio
122
155
  *
123
156
  * @example
124
157
  * const tools = toAnthropicTools(prompt.tools);
125
- * await anthropic.messages.create({ model, system, messages, tools });
158
+ * const tool_choice = toAnthropicToolChoice(prompt.toolChoice);
159
+ * await anthropic.messages.create({ model, system, messages, tools, tool_choice });
126
160
  */
127
161
  export declare function toAnthropicTools(tools: ReadonlyArray<ResolvedToolDefinition> | null | undefined): AnthropicTool[];
162
+ /**
163
+ * Map a resolved prompt's provider-neutral `toolChoice` to the Anthropic
164
+ * Messages `tool_choice` field.
165
+ *
166
+ * - `null` / `undefined` → `undefined` (omit the field)
167
+ * - `"auto"` → `{ type: "auto" }`
168
+ * - `"none"` → `{ type: "none" }` (the Anthropic API supports this natively)
169
+ * - `"required"` → `{ type: "any" }` (Anthropic's name for "must invoke a tool")
170
+ * - `{ name }` → `{ type: "tool", name }`
171
+ *
172
+ * @example
173
+ * const tools = toAnthropicTools(prompt.tools);
174
+ * const tool_choice = toAnthropicToolChoice(prompt.toolChoice);
175
+ * await anthropic.messages.create({ model, system, messages, tools, tool_choice });
176
+ */
177
+ export declare function toAnthropicToolChoice(toolChoice: ResolvedPrompt["toolChoice"]): AnthropicToolChoice | undefined;
128
178
  /**
129
179
  * Shape rendered turns for the OpenAI Chat Completions `messages` field.
130
180
  *
package/dist/gateway.js CHANGED
@@ -56,6 +56,13 @@ function toOpenAITools(tools) {
56
56
  return { type: "function", function: fn };
57
57
  });
58
58
  }
59
+ function toOpenAIToolChoice(toolChoice) {
60
+ if (toolChoice == null)
61
+ return;
62
+ if (typeof toolChoice === "string")
63
+ return toolChoice;
64
+ return { type: "function", function: { name: toolChoice.name } };
65
+ }
59
66
  function toAnthropicTools(tools) {
60
67
  if (tools == null)
61
68
  return [];
@@ -70,6 +77,17 @@ function toAnthropicTools(tools) {
70
77
  return out;
71
78
  });
72
79
  }
80
+ function toAnthropicToolChoice(toolChoice) {
81
+ if (toolChoice == null)
82
+ return;
83
+ if (toolChoice === "auto")
84
+ return { type: "auto" };
85
+ if (toolChoice === "none")
86
+ return { type: "none" };
87
+ if (toolChoice === "required")
88
+ return { type: "any" };
89
+ return { type: "tool", name: toolChoice.name };
90
+ }
73
91
  function requireToolCallId(id) {
74
92
  if (typeof id !== "string" || id.length === 0) {
75
93
  throw new Error("to11 SDK: malformed tool history — a tool call/result is missing its id (toolCallId). Author a non-empty id before converting messages.");
@@ -150,8 +168,10 @@ function toAnthropicMessages(messages) {
150
168
  }
151
169
  export {
152
170
  toOpenAITools,
171
+ toOpenAIToolChoice,
153
172
  toOpenAIMessages,
154
173
  toAnthropicTools,
174
+ toAnthropicToolChoice,
155
175
  toAnthropicMessages,
156
176
  gatewayPromptHeaders,
157
177
  gatewayAuthHeaders
@@ -279,6 +279,9 @@ export type ResolvedPrompt = {
279
279
  releaseId: string;
280
280
  rendered: RenderedPrompt;
281
281
  subjectHash?: string | null;
282
+ toolChoice?: 'auto' | 'none' | 'required' | {
283
+ name: string;
284
+ } | null;
282
285
  tools?: Array<ResolvedToolDefinition> | null;
283
286
  variantName?: string | null;
284
287
  version: number;
@@ -14740,6 +14743,7 @@ export type PromptsGetPromptVersionDiffResponses = {
14740
14743
  name: string;
14741
14744
  op: 'add';
14742
14745
  role: 'system' | 'user' | 'assistant' | 'developer' | 'tool';
14746
+ toolCallId?: string | null;
14743
14747
  toolCalls?: Array<{
14744
14748
  arguments: {
14745
14749
  [key: string]: unknown;
@@ -14747,15 +14751,6 @@ export type PromptsGetPromptVersionDiffResponses = {
14747
14751
  id: string;
14748
14752
  name: string;
14749
14753
  }> | null;
14750
- toolSchema?: {
14751
- content?: string | null;
14752
- description?: string | null;
14753
- parameters?: {
14754
- [key: string]: unknown;
14755
- } | null;
14756
- toolCallId?: string | null;
14757
- toolKind?: 'definition' | 'result' | null;
14758
- } | null;
14759
14754
  } | {
14760
14755
  condition: {
14761
14756
  kind: string;
@@ -14764,6 +14759,7 @@ export type PromptsGetPromptVersionDiffResponses = {
14764
14759
  name: string;
14765
14760
  op: 'remove';
14766
14761
  role: 'system' | 'user' | 'assistant' | 'developer' | 'tool';
14762
+ toolCallId?: string | null;
14767
14763
  toolCalls?: Array<{
14768
14764
  arguments: {
14769
14765
  [key: string]: unknown;
@@ -14771,15 +14767,6 @@ export type PromptsGetPromptVersionDiffResponses = {
14771
14767
  id: string;
14772
14768
  name: string;
14773
14769
  }> | null;
14774
- toolSchema?: {
14775
- content?: string | null;
14776
- description?: string | null;
14777
- parameters?: {
14778
- [key: string]: unknown;
14779
- } | null;
14780
- toolCallId?: string | null;
14781
- toolKind?: 'definition' | 'result' | null;
14782
- } | null;
14783
14770
  } | {
14784
14771
  after: string;
14785
14772
  before: string;
@@ -14805,26 +14792,10 @@ export type PromptsGetPromptVersionDiffResponses = {
14805
14792
  name: string;
14806
14793
  op: 'edit_required';
14807
14794
  } | {
14808
- after: {
14809
- content?: string | null;
14810
- description?: string | null;
14811
- parameters?: {
14812
- [key: string]: unknown;
14813
- } | null;
14814
- toolCallId?: string | null;
14815
- toolKind?: 'definition' | 'result' | null;
14816
- };
14817
- before: {
14818
- content?: string | null;
14819
- description?: string | null;
14820
- parameters?: {
14821
- [key: string]: unknown;
14822
- } | null;
14823
- toolCallId?: string | null;
14824
- toolKind?: 'definition' | 'result' | null;
14825
- };
14795
+ after: string;
14796
+ before: string;
14826
14797
  name: string;
14827
- op: 'edit_tool_schema';
14798
+ op: 'edit_tool_call_id';
14828
14799
  } | {
14829
14800
  after: Array<{
14830
14801
  arguments: {
@@ -15285,9 +15256,6 @@ export type PromptsWithdrawPromptReviewResponses = {
15285
15256
  export type PromptsWithdrawPromptReviewResponse = PromptsWithdrawPromptReviewResponses[keyof PromptsWithdrawPromptReviewResponses];
15286
15257
  export type PromptsResolvePromptData = {
15287
15258
  body: {
15288
- context?: {
15289
- [key: string]: string | number | boolean;
15290
- } | null;
15291
15259
  developerRole?: 'user' | 'developer' | 'system' | null;
15292
15260
  labels: Array<string>;
15293
15261
  slug: string;
@@ -489,6 +489,13 @@ export declare const zResolvedPrompt: z.ZodObject<{
489
489
  }, z.core.$strip>]>>;
490
490
  }, z.core.$strip>]>;
491
491
  subjectHash: z.ZodOptional<z.ZodNullable<z.ZodString>>;
492
+ toolChoice: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodEnum<{
493
+ auto: "auto";
494
+ none: "none";
495
+ required: "required";
496
+ }>, z.ZodObject<{
497
+ name: z.ZodString;
498
+ }, z.core.$strip>]>>>;
492
499
  tools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
493
500
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
494
501
  name: z.ZodString;
@@ -8505,21 +8512,12 @@ export declare const zPromptsGetPromptVersionDiffResponse: z.ZodObject<{
8505
8512
  tool: "tool";
8506
8513
  assistant: "assistant";
8507
8514
  }>;
8515
+ toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8508
8516
  toolCalls: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
8509
8517
  arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
8510
8518
  id: z.ZodString;
8511
8519
  name: z.ZodString;
8512
8520
  }, z.core.$strip>>>>;
8513
- toolSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
8514
- content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8515
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8516
- parameters: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
8517
- toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8518
- toolKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
8519
- definition: "definition";
8520
- result: "result";
8521
- }>>>;
8522
- }, z.core.$strip>>>;
8523
8521
  }, z.core.$strip>, z.ZodObject<{
8524
8522
  condition: z.ZodObject<{
8525
8523
  kind: z.ZodString;
@@ -8536,21 +8534,12 @@ export declare const zPromptsGetPromptVersionDiffResponse: z.ZodObject<{
8536
8534
  tool: "tool";
8537
8535
  assistant: "assistant";
8538
8536
  }>;
8537
+ toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8539
8538
  toolCalls: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
8540
8539
  arguments: z.ZodRecord<z.ZodString, z.ZodUnknown>;
8541
8540
  id: z.ZodString;
8542
8541
  name: z.ZodString;
8543
8542
  }, z.core.$strip>>>>;
8544
- toolSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
8545
- content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8546
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8547
- parameters: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
8548
- toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8549
- toolKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
8550
- definition: "definition";
8551
- result: "result";
8552
- }>>>;
8553
- }, z.core.$strip>>>;
8554
8543
  }, z.core.$strip>, z.ZodObject<{
8555
8544
  after: z.ZodString;
8556
8545
  before: z.ZodString;
@@ -8596,29 +8585,11 @@ export declare const zPromptsGetPromptVersionDiffResponse: z.ZodObject<{
8596
8585
  edit_required: "edit_required";
8597
8586
  }>;
8598
8587
  }, z.core.$strip>, z.ZodObject<{
8599
- after: z.ZodObject<{
8600
- content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8601
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8602
- parameters: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
8603
- toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8604
- toolKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
8605
- definition: "definition";
8606
- result: "result";
8607
- }>>>;
8608
- }, z.core.$strip>;
8609
- before: z.ZodObject<{
8610
- content: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8611
- description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8612
- parameters: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
8613
- toolCallId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8614
- toolKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
8615
- definition: "definition";
8616
- result: "result";
8617
- }>>>;
8618
- }, z.core.$strip>;
8588
+ after: z.ZodString;
8589
+ before: z.ZodString;
8619
8590
  name: z.ZodString;
8620
8591
  op: z.ZodEnum<{
8621
- edit_tool_schema: "edit_tool_schema";
8592
+ edit_tool_call_id: "edit_tool_call_id";
8622
8593
  }>;
8623
8594
  }, z.core.$strip>, z.ZodObject<{
8624
8595
  after: z.ZodArray<z.ZodObject<{
@@ -8889,7 +8860,6 @@ export declare const zPromptsWithdrawPromptReviewResponse: z.ZodObject<{
8889
8860
  success: z.ZodBoolean;
8890
8861
  }, z.core.$strip>;
8891
8862
  export declare const zPromptsResolvePromptBody: z.ZodObject<{
8892
- context: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
8893
8863
  developerRole: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
8894
8864
  user: "user";
8895
8865
  system: "system";
@@ -8952,6 +8922,13 @@ export declare const zPromptsResolvePromptResponse: z.ZodObject<{
8952
8922
  }, z.core.$strip>]>>;
8953
8923
  }, z.core.$strip>]>;
8954
8924
  subjectHash: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8925
+ toolChoice: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodEnum<{
8926
+ auto: "auto";
8927
+ none: "none";
8928
+ required: "required";
8929
+ }>, z.ZodObject<{
8930
+ name: z.ZodString;
8931
+ }, z.core.$strip>]>>>;
8955
8932
  tools: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
8956
8933
  description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
8957
8934
  name: z.ZodString;
@@ -1,4 +1,4 @@
1
- import type { FetchedPrompt, PromptContext, ResolvedPrompt } from "./types";
1
+ import type { FetchedPrompt, ResolvedPrompt } from "./types";
2
2
  export interface CacheConfig {
3
3
  /** Time-to-live in seconds. Default: 300 (5 minutes) */
4
4
  ttlSeconds?: number;
@@ -26,9 +26,9 @@ export declare function buildCacheKey(projectId: string, slug: string, labels: s
26
26
  /**
27
27
  * Build a cache key for an env-aware `fetch()` call.
28
28
  *
29
- * Folds in `env`, `context`, and `subject` ON TOP of the base
29
+ * Folds in `env` and `subject` ON TOP of the base
30
30
  * project/slug/labels/variables key so two calls that differ only by
31
- * env/context/subject do not return a stale cross-env / cross-cohort hit
31
+ * env/subject do not return a stale cross-env / cross-cohort hit
32
32
  * (spec §3 "Caching key changes"). The env slug is also forwarded as the
33
33
  * single resolution label (env→label mapping, correction #3), so it appears
34
34
  * in the `labels` segment too; including it explicitly here keeps the key
@@ -38,7 +38,7 @@ export declare function buildCacheKey(projectId: string, slug: string, labels: s
38
38
  * caches as the same deterministic variant on repeat (D8); the
39
39
  * weighted-no-subject bypass is handled in the resource, not here.
40
40
  */
41
- export declare function buildFetchCacheKey(projectId: string, slug: string, env: string, context?: PromptContext, subject?: string, variables?: Record<string, unknown>, developerRole?: string): string;
41
+ export declare function buildFetchCacheKey(projectId: string, slug: string, env: string, subject?: string, variables?: Record<string, unknown>, developerRole?: string): string;
42
42
  /**
43
43
  * In-memory LRU cache for ResolvedPrompt objects.
44
44
  *
@@ -54,7 +54,8 @@ var zResolvedPromptLegacy = import_zod2.zResolvedPrompt.pick({
54
54
  labels: true,
55
55
  contentHash: true,
56
56
  rendered: true,
57
- tools: true
57
+ tools: true,
58
+ toolChoice: true
58
59
  });
59
60
  var zResolvedPromptEnvelope = import_zod2.zResolvedPrompt.partial({ releaseId: true }).extend({ strategy: import_zod.z.enum(["single", "weighted"]).optional() });
60
61
  function unwrap(envelope) {
@@ -88,6 +89,9 @@ function normalizeResolvedEnvelope(raw) {
88
89
  if (raw.tools != null && raw.tools.length > 0) {
89
90
  result.tools = raw.tools;
90
91
  }
92
+ if (raw.toolChoice != null) {
93
+ result.toolChoice = raw.toolChoice;
94
+ }
91
95
  if (typeof provenance.variantName === "string" && provenance.variantName.length > 0) {
92
96
  result.variantName = provenance.variantName;
93
97
  }
@@ -215,22 +219,19 @@ class PromptResource {
215
219
  throw new Error(`[to11ai/sdk] \`env\` must match ${import_types.ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
216
220
  }
217
221
  const {
218
- context,
219
222
  subject,
220
223
  variables,
221
224
  cache: useCache = true,
222
225
  fallback,
223
226
  developerRole
224
227
  } = options;
225
- const cacheKey = import_cache.buildFetchCacheKey(this.projectId, slug, env, context, subject, variables, developerRole);
228
+ const cacheKey = import_cache.buildFetchCacheKey(this.projectId, slug, env, subject, variables, developerRole);
226
229
  if (useCache) {
227
230
  const cached = this.cache.get(cacheKey);
228
231
  if (cached && "messages" in cached)
229
232
  return structuredClone(cached);
230
233
  }
231
234
  const body = { slug, labels: [env] };
232
- if (context !== undefined)
233
- body.context = context;
234
235
  if (subject !== undefined)
235
236
  body.subject = subject;
236
237
  if (variables !== undefined)
@@ -2,7 +2,7 @@ import type { Transport } from "../transport";
2
2
  import type { CacheConfig } from "./cache";
3
3
  import type { ArchivePromptInput, ArchivePromptResult, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, FetchedPrompt, FetchPromptOptions, GetProjectPromptLabelInput, GetProjectPromptLabelResult, GetPromptInput, GetPromptResult, GetPromptVersionInput, GetPromptVersionResult, ListLabelEventsInput, ListLabelEventsResult, ListProjectPromptLabelsInput, ListProjectPromptLabelsResult, ListProjectPromptLabelUsagesInput, ListProjectPromptLabelUsagesResult, ListPromptLabelsInput, ListPromptLabelsResult, ListPromptsInput, ListPromptsResult, ListPromptVersionsInput, ListPromptVersionsResult, MovePromptLabelInput, MovePromptLabelResult, PaginatedResult, ResolvePromptInput, ResolvePromptResult, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult } from "./types";
4
4
  export type { CacheConfig } from "./cache";
5
- export type { ArchivePromptInput, ArchivePromptResult, BlockRenderRecord, ChatMessage, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, FetchedPrompt, FetchPromptOptions, GetProjectPromptLabelInput, GetProjectPromptLabelResult, GetPromptInput, GetPromptResult, GetPromptVersionInput, GetPromptVersionResult, ListLabelEventsInput, ListLabelEventsResult, ListProjectPromptLabelsInput, ListProjectPromptLabelsResult, ListProjectPromptLabelUsagesInput, ListProjectPromptLabelUsagesResult, ListPromptLabelsInput, ListPromptLabelsResult, ListPromptsInput, ListPromptsResult, ListPromptVersionsInput, ListPromptVersionsResult, MovePromptLabelInput, MovePromptLabelResult, PaginatedResult, PaginationInfo, PaletteToken, ProjectPromptLabel, ProjectPromptLabelUsage, Prompt, PromptContext, PromptFormat, PromptLabelEvent, PromptLabelPointer, PromptStatus, PromptVersion, RenderedChatMessage, RenderedPrompt, ResolvedPrompt, ResolvedPromptEnvelope, ResolvedToolCall, ResolvedToolDefinition, ResolvePromptInput, ResolvePromptResult, RowError, TextChatMessage, TextChatRole, ToolChatMessage, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult, } from "./types";
5
+ export type { ArchivePromptInput, ArchivePromptResult, BlockRenderRecord, ChatMessage, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, FetchedPrompt, FetchPromptOptions, GetProjectPromptLabelInput, GetProjectPromptLabelResult, GetPromptInput, GetPromptResult, GetPromptVersionInput, GetPromptVersionResult, ListLabelEventsInput, ListLabelEventsResult, ListProjectPromptLabelsInput, ListProjectPromptLabelsResult, ListProjectPromptLabelUsagesInput, ListProjectPromptLabelUsagesResult, ListPromptLabelsInput, ListPromptLabelsResult, ListPromptsInput, ListPromptsResult, ListPromptVersionsInput, ListPromptVersionsResult, MovePromptLabelInput, MovePromptLabelResult, PaginatedResult, PaginationInfo, PaletteToken, ProjectPromptLabel, ProjectPromptLabelUsage, Prompt, PromptFormat, PromptLabelEvent, PromptLabelPointer, PromptStatus, PromptVersion, RenderedChatMessage, RenderedPrompt, ResolvedPrompt, ResolvedPromptEnvelope, ResolvedToolCall, ResolvedToolDefinition, ResolvePromptInput, ResolvePromptResult, RowError, TextChatMessage, TextChatRole, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult, } from "./types";
6
6
  /**
7
7
  * Init-time config for the env-aware `fetch()` surface (TO11-980 / S9).
8
8
  *
@@ -41,8 +41,8 @@ export declare class PromptResource {
41
41
  * label-based (`/v1/projects/:projectId/prompts:resolve`, body
42
42
  * `labels[]`); it does NOT accept a top-level `env` field. The resolved
43
43
  * env slug (lowercase-kebab — a valid label name) is therefore sent as
44
- * the single resolution label: body `{ slug, labels: [env], context?,
45
- * subject?, variables? }`.
44
+ * the single resolution label: body `{ slug, labels: [env], subject?,
45
+ * variables? }`.
46
46
  * - **No silent fallback (R4):** if no env is resolvable (none at init AND
47
47
  * none per call) this throws `EnvNotFoundError` (`reason.source =
48
48
  * "missing"`) CLIENT-side, eagerly, before any transport call.
@@ -55,8 +55,8 @@ export declare class PromptResource {
55
55
  fetch(slug: string, options?: FetchPromptOptions): Promise<FetchedPrompt>;
56
56
  /**
57
57
  * @deprecated Use {@link PromptResource.fetch | `prompts.fetch(slug,
58
- * options?)`} instead. `resolve()` is env-agnostic (no `env` / `context` /
59
- * `subject`, no enriched release/variant provenance, no typed-env errors)
58
+ * options?)`} instead. `resolve()` is env-agnostic (no `env` / `subject`,
59
+ * no enriched release/variant provenance, no typed-env errors)
60
60
  * and is retained only for back-compat. It is NOT subject to the R4
61
61
  * no-silent-fallback env gate (it has no env concept). New code should
62
62
  * configure `projectId` + `env` at `createClient` and call `fetch()`.
@@ -11,7 +11,8 @@ var zResolvedPromptLegacy = zResolvedPrompt.pick({
11
11
  labels: true,
12
12
  contentHash: true,
13
13
  rendered: true,
14
- tools: true
14
+ tools: true,
15
+ toolChoice: true
15
16
  });
16
17
  var zResolvedPromptEnvelope = zResolvedPrompt.partial({ releaseId: true }).extend({ strategy: z.enum(["single", "weighted"]).optional() });
17
18
  function unwrap(envelope) {
@@ -45,6 +46,9 @@ function normalizeResolvedEnvelope(raw) {
45
46
  if (raw.tools != null && raw.tools.length > 0) {
46
47
  result.tools = raw.tools;
47
48
  }
49
+ if (raw.toolChoice != null) {
50
+ result.toolChoice = raw.toolChoice;
51
+ }
48
52
  if (typeof provenance.variantName === "string" && provenance.variantName.length > 0) {
49
53
  result.variantName = provenance.variantName;
50
54
  }
@@ -172,22 +176,19 @@ class PromptResource {
172
176
  throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
173
177
  }
174
178
  const {
175
- context,
176
179
  subject,
177
180
  variables,
178
181
  cache: useCache = true,
179
182
  fallback,
180
183
  developerRole
181
184
  } = options;
182
- const cacheKey = buildFetchCacheKey(this.projectId, slug, env, context, subject, variables, developerRole);
185
+ const cacheKey = buildFetchCacheKey(this.projectId, slug, env, subject, variables, developerRole);
183
186
  if (useCache) {
184
187
  const cached = this.cache.get(cacheKey);
185
188
  if (cached && "messages" in cached)
186
189
  return structuredClone(cached);
187
190
  }
188
191
  const body = { slug, labels: [env] };
189
- if (context !== undefined)
190
- body.context = context;
191
192
  if (subject !== undefined)
192
193
  body.subject = subject;
193
194
  if (variables !== undefined)
@@ -15,14 +15,7 @@ export interface TextChatMessage {
15
15
  content: string;
16
16
  disabled?: boolean;
17
17
  }
18
- export interface ToolChatMessage {
19
- role: "tool";
20
- name: string;
21
- description?: string;
22
- parameters: unknown;
23
- disabled?: boolean;
24
- }
25
- export type ChatMessage = TextChatMessage | ToolChatMessage;
18
+ export type ChatMessage = TextChatMessage;
26
19
  export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
27
20
  export type RenderedPrompt = GenRenderedPrompt;
28
21
  /**
@@ -36,7 +29,7 @@ export type ResolvedToolDefinition = GenResolvedToolDefinition;
36
29
  * on a rendered `assistant` turn (few-shot multi-tool history).
37
30
  */
38
31
  export type ResolvedToolCall = GenResolvedToolCall;
39
- export type ResolvedPrompt = Pick<GenResolvedPrompt, "promptId" | "versionId" | "version" | "labels" | "contentHash" | "rendered" | "tools">;
32
+ export type ResolvedPrompt = Pick<GenResolvedPrompt, "promptId" | "versionId" | "version" | "labels" | "contentHash" | "rendered" | "tools" | "toolChoice">;
40
33
  export interface PaginationInfo {
41
34
  page: number;
42
35
  limit: number;
@@ -129,7 +122,6 @@ export interface ResolvePromptInput {
129
122
  export type ResolvePromptResult = ResolvedPrompt;
130
123
  export declare const ENV_SLUG_REGEX: RegExp;
131
124
  export type BlockRenderRecord = Record<string, "rendered" | "dimmed">;
132
- export type PromptContext = Record<string, string | number | boolean>;
133
125
  export interface FetchedPrompt {
134
126
  messages: RenderedChatMessage[];
135
127
  version: number;
@@ -147,6 +139,16 @@ export interface FetchedPrompt {
147
139
  * tools. Shape for a provider with `toOpenAITools` / `toAnthropicTools`.
148
140
  */
149
141
  tools?: ResolvedToolDefinition[];
142
+ /**
143
+ * Provider-neutral tool-choice directive lifted from the resolved version.
144
+ * Absent (rather than `null`) when the version declares none. Feed straight
145
+ * into `toOpenAIToolChoice` / `toAnthropicToolChoice`.
146
+ *
147
+ * `NonNullable` because `normalizeResolvedEnvelope` maps wire-`null` to absent,
148
+ * so a present `FetchedPrompt.toolChoice` is never `null` — callers get the
149
+ * key or nothing, and never have to branch on `null`.
150
+ */
151
+ toolChoice?: NonNullable<ResolvedPrompt["toolChoice"]>;
150
152
  }
151
153
  export type ResolvedPromptEnvelope = GenResolvedPrompt & {
152
154
  /** Active release strategy. Used to decide weighted-no-subject cache bypass (D8). */
@@ -161,7 +163,6 @@ export type ResolvedPromptEnvelope = GenResolvedPrompt & {
161
163
  export type DeveloperRole = "user" | "developer" | "system";
162
164
  export interface FetchPromptOptions {
163
165
  env?: string;
164
- context?: PromptContext;
165
166
  subject?: string;
166
167
  variables?: Record<string, unknown>;
167
168
  cache?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@to11ai/sdk",
3
- "version": "0.7.0",
3
+ "version": "1.0.0",
4
4
  "license": "MPL-2.0",
5
5
  "repository": {
6
6
  "type": "git",
package/src/client.ts CHANGED
@@ -69,7 +69,6 @@ export type {
69
69
  DeveloperRole,
70
70
  FetchedPrompt,
71
71
  FetchPromptOptions,
72
- PromptContext,
73
72
  RenderedChatMessage,
74
73
  RenderedPrompt,
75
74
  ResolvedPrompt,
package/src/gateway.ts CHANGED
@@ -138,6 +138,13 @@ export interface OpenAITool {
138
138
  };
139
139
  }
140
140
 
141
+ /** OpenAI `tool_choice` value for a Chat Completions request. */
142
+ export type OpenAIToolChoice =
143
+ | "auto"
144
+ | "none"
145
+ | "required"
146
+ | { type: "function"; function: { name: string } };
147
+
141
148
  /** OpenAI Chat Completions assistant `tool_calls[]` entry. */
142
149
  export interface OpenAIToolCall {
143
150
  id: string;
@@ -177,6 +184,13 @@ export interface AnthropicMessage {
177
184
  content: string | AnthropicContentBlock[];
178
185
  }
179
186
 
187
+ /** Anthropic Messages `tool_choice` value. */
188
+ export type AnthropicToolChoice =
189
+ | { type: "auto" }
190
+ | { type: "any" }
191
+ | { type: "none" }
192
+ | { type: "tool"; name: string };
193
+
180
194
  /**
181
195
  * Shape resolved tool definitions for the OpenAI Chat Completions `tools`
182
196
  * field: `{ type: "function", function: { name, description?, parameters } }`.
@@ -186,7 +200,8 @@ export interface AnthropicMessage {
186
200
  *
187
201
  * @example
188
202
  * const tools = toOpenAITools(prompt.tools);
189
- * await openai.chat.completions.create({ model, messages, tools });
203
+ * const tool_choice = toOpenAIToolChoice(prompt.toolChoice);
204
+ * await openai.chat.completions.create({ model, messages, tools, tool_choice });
190
205
  */
191
206
  export function toOpenAITools(
192
207
  tools: ReadonlyArray<ResolvedToolDefinition> | null | undefined,
@@ -204,6 +219,27 @@ export function toOpenAITools(
204
219
  });
205
220
  }
206
221
 
222
+ /**
223
+ * Map a resolved prompt's provider-neutral `toolChoice` to the OpenAI
224
+ * Chat Completions `tool_choice` field.
225
+ *
226
+ * - `null` / `undefined` → `undefined` (omit the field)
227
+ * - `"auto"` → `"auto"`, `"none"` → `"none"`, `"required"` → `"required"`
228
+ * - `{ name }` → `{ type: "function", function: { name } }`
229
+ *
230
+ * @example
231
+ * const tools = toOpenAITools(prompt.tools);
232
+ * const tool_choice = toOpenAIToolChoice(prompt.toolChoice);
233
+ * await openai.chat.completions.create({ model, messages, tools, tool_choice });
234
+ */
235
+ export function toOpenAIToolChoice(
236
+ toolChoice: ResolvedPrompt["toolChoice"],
237
+ ): OpenAIToolChoice | undefined {
238
+ if (toolChoice == null) return undefined;
239
+ if (typeof toolChoice === "string") return toolChoice;
240
+ return { type: "function", function: { name: toolChoice.name } };
241
+ }
242
+
207
243
  /**
208
244
  * Shape resolved tool definitions for the Anthropic Messages `tools` field:
209
245
  * `{ name, description?, input_schema }` (Anthropic names the JSON Schema field
@@ -211,7 +247,8 @@ export function toOpenAITools(
211
247
  *
212
248
  * @example
213
249
  * const tools = toAnthropicTools(prompt.tools);
214
- * await anthropic.messages.create({ model, system, messages, tools });
250
+ * const tool_choice = toAnthropicToolChoice(prompt.toolChoice);
251
+ * await anthropic.messages.create({ model, system, messages, tools, tool_choice });
215
252
  */
216
253
  export function toAnthropicTools(
217
254
  tools: ReadonlyArray<ResolvedToolDefinition> | null | undefined,
@@ -229,6 +266,31 @@ export function toAnthropicTools(
229
266
  });
230
267
  }
231
268
 
269
+ /**
270
+ * Map a resolved prompt's provider-neutral `toolChoice` to the Anthropic
271
+ * Messages `tool_choice` field.
272
+ *
273
+ * - `null` / `undefined` → `undefined` (omit the field)
274
+ * - `"auto"` → `{ type: "auto" }`
275
+ * - `"none"` → `{ type: "none" }` (the Anthropic API supports this natively)
276
+ * - `"required"` → `{ type: "any" }` (Anthropic's name for "must invoke a tool")
277
+ * - `{ name }` → `{ type: "tool", name }`
278
+ *
279
+ * @example
280
+ * const tools = toAnthropicTools(prompt.tools);
281
+ * const tool_choice = toAnthropicToolChoice(prompt.toolChoice);
282
+ * await anthropic.messages.create({ model, system, messages, tools, tool_choice });
283
+ */
284
+ export function toAnthropicToolChoice(
285
+ toolChoice: ResolvedPrompt["toolChoice"],
286
+ ): AnthropicToolChoice | undefined {
287
+ if (toolChoice == null) return undefined;
288
+ if (toolChoice === "auto") return { type: "auto" };
289
+ if (toolChoice === "none") return { type: "none" };
290
+ if (toolChoice === "required") return { type: "any" };
291
+ return { type: "tool", name: toolChoice.name };
292
+ }
293
+
232
294
  /**
233
295
  * Guard a tool-call linkage id before it is serialized into a provider payload.
234
296
  * A missing/empty id means malformed tool history (an assistant tool call or a
@@ -308,6 +308,9 @@ export type ResolvedPrompt = {
308
308
  releaseId: string;
309
309
  rendered: RenderedPrompt;
310
310
  subjectHash?: string | null;
311
+ toolChoice?: 'auto' | 'none' | 'required' | {
312
+ name: string;
313
+ } | null;
311
314
  tools?: Array<ResolvedToolDefinition> | null;
312
315
  variantName?: string | null;
313
316
  version: number;
@@ -15484,6 +15487,7 @@ export type PromptsGetPromptVersionDiffResponses = {
15484
15487
  name: string;
15485
15488
  op: 'add';
15486
15489
  role: 'system' | 'user' | 'assistant' | 'developer' | 'tool';
15490
+ toolCallId?: string | null;
15487
15491
  toolCalls?: Array<{
15488
15492
  arguments: {
15489
15493
  [key: string]: unknown;
@@ -15491,15 +15495,6 @@ export type PromptsGetPromptVersionDiffResponses = {
15491
15495
  id: string;
15492
15496
  name: string;
15493
15497
  }> | null;
15494
- toolSchema?: {
15495
- content?: string | null;
15496
- description?: string | null;
15497
- parameters?: {
15498
- [key: string]: unknown;
15499
- } | null;
15500
- toolCallId?: string | null;
15501
- toolKind?: 'definition' | 'result' | null;
15502
- } | null;
15503
15498
  } | {
15504
15499
  condition: {
15505
15500
  kind: string;
@@ -15508,6 +15503,7 @@ export type PromptsGetPromptVersionDiffResponses = {
15508
15503
  name: string;
15509
15504
  op: 'remove';
15510
15505
  role: 'system' | 'user' | 'assistant' | 'developer' | 'tool';
15506
+ toolCallId?: string | null;
15511
15507
  toolCalls?: Array<{
15512
15508
  arguments: {
15513
15509
  [key: string]: unknown;
@@ -15515,15 +15511,6 @@ export type PromptsGetPromptVersionDiffResponses = {
15515
15511
  id: string;
15516
15512
  name: string;
15517
15513
  }> | null;
15518
- toolSchema?: {
15519
- content?: string | null;
15520
- description?: string | null;
15521
- parameters?: {
15522
- [key: string]: unknown;
15523
- } | null;
15524
- toolCallId?: string | null;
15525
- toolKind?: 'definition' | 'result' | null;
15526
- } | null;
15527
15514
  } | {
15528
15515
  after: string;
15529
15516
  before: string;
@@ -15549,26 +15536,10 @@ export type PromptsGetPromptVersionDiffResponses = {
15549
15536
  name: string;
15550
15537
  op: 'edit_required';
15551
15538
  } | {
15552
- after: {
15553
- content?: string | null;
15554
- description?: string | null;
15555
- parameters?: {
15556
- [key: string]: unknown;
15557
- } | null;
15558
- toolCallId?: string | null;
15559
- toolKind?: 'definition' | 'result' | null;
15560
- };
15561
- before: {
15562
- content?: string | null;
15563
- description?: string | null;
15564
- parameters?: {
15565
- [key: string]: unknown;
15566
- } | null;
15567
- toolCallId?: string | null;
15568
- toolKind?: 'definition' | 'result' | null;
15569
- };
15539
+ after: string;
15540
+ before: string;
15570
15541
  name: string;
15571
- op: 'edit_tool_schema';
15542
+ op: 'edit_tool_call_id';
15572
15543
  } | {
15573
15544
  after: Array<{
15574
15545
  arguments: {
@@ -16051,9 +16022,6 @@ export type PromptsWithdrawPromptReviewResponse = PromptsWithdrawPromptReviewRes
16051
16022
 
16052
16023
  export type PromptsResolvePromptData = {
16053
16024
  body: {
16054
- context?: {
16055
- [key: string]: string | number | boolean;
16056
- } | null;
16057
16025
  developerRole?: 'user' | 'developer' | 'system' | null;
16058
16026
  labels: Array<string>;
16059
16027
  slug: string;
@@ -355,6 +355,16 @@ export const zResolvedPrompt = z.object({
355
355
  releaseId: z.string(),
356
356
  rendered: zRenderedPrompt,
357
357
  subjectHash: z.string().nullish(),
358
+ toolChoice: z.union([
359
+ z.enum([
360
+ 'auto',
361
+ 'none',
362
+ 'required'
363
+ ]),
364
+ z.object({
365
+ name: z.string().min(1)
366
+ })
367
+ ]).nullish(),
358
368
  tools: z.array(zResolvedToolDefinition).nullish(),
359
369
  variantName: z.string().nullish(),
360
370
  version: z.number(),
@@ -7954,18 +7964,12 @@ export const zPromptsGetPromptVersionDiffResponse = z.object({
7954
7964
  'developer',
7955
7965
  'tool'
7956
7966
  ]),
7967
+ toolCallId: z.string().nullish(),
7957
7968
  toolCalls: z.array(z.object({
7958
7969
  arguments: z.record(z.string(), z.unknown()),
7959
7970
  id: z.string(),
7960
7971
  name: z.string()
7961
- })).nullish(),
7962
- toolSchema: z.object({
7963
- content: z.string().nullish(),
7964
- description: z.string().nullish(),
7965
- parameters: z.record(z.string(), z.unknown()).nullish(),
7966
- toolCallId: z.string().nullish(),
7967
- toolKind: z.enum(['definition', 'result']).nullish()
7968
- }).nullish()
7972
+ })).nullish()
7969
7973
  }),
7970
7974
  z.object({
7971
7975
  condition: z.object({
@@ -7981,18 +7985,12 @@ export const zPromptsGetPromptVersionDiffResponse = z.object({
7981
7985
  'developer',
7982
7986
  'tool'
7983
7987
  ]),
7988
+ toolCallId: z.string().nullish(),
7984
7989
  toolCalls: z.array(z.object({
7985
7990
  arguments: z.record(z.string(), z.unknown()),
7986
7991
  id: z.string(),
7987
7992
  name: z.string()
7988
- })).nullish(),
7989
- toolSchema: z.object({
7990
- content: z.string().nullish(),
7991
- description: z.string().nullish(),
7992
- parameters: z.record(z.string(), z.unknown()).nullish(),
7993
- toolCallId: z.string().nullish(),
7994
- toolKind: z.enum(['definition', 'result']).nullish()
7995
- }).nullish()
7993
+ })).nullish()
7996
7994
  }),
7997
7995
  z.object({
7998
7996
  after: z.string(),
@@ -8035,22 +8033,10 @@ export const zPromptsGetPromptVersionDiffResponse = z.object({
8035
8033
  op: z.enum(['edit_required'])
8036
8034
  }),
8037
8035
  z.object({
8038
- after: z.object({
8039
- content: z.string().nullish(),
8040
- description: z.string().nullish(),
8041
- parameters: z.record(z.string(), z.unknown()).nullish(),
8042
- toolCallId: z.string().nullish(),
8043
- toolKind: z.enum(['definition', 'result']).nullish()
8044
- }),
8045
- before: z.object({
8046
- content: z.string().nullish(),
8047
- description: z.string().nullish(),
8048
- parameters: z.record(z.string(), z.unknown()).nullish(),
8049
- toolCallId: z.string().nullish(),
8050
- toolKind: z.enum(['definition', 'result']).nullish()
8051
- }),
8036
+ after: z.string(),
8037
+ before: z.string(),
8052
8038
  name: z.string(),
8053
- op: z.enum(['edit_tool_schema'])
8039
+ op: z.enum(['edit_tool_call_id'])
8054
8040
  }),
8055
8041
  z.object({
8056
8042
  after: z.array(z.object({
@@ -8314,11 +8300,6 @@ export const zPromptsWithdrawPromptReviewResponse = z.object({
8314
8300
  });
8315
8301
 
8316
8302
  export const zPromptsResolvePromptBody = z.object({
8317
- context: z.record(z.string(), z.union([
8318
- z.string(),
8319
- z.number(),
8320
- z.boolean()
8321
- ])).nullish(),
8322
8303
  developerRole: z.enum([
8323
8304
  'user',
8324
8305
  'developer',
@@ -1,4 +1,4 @@
1
- import type { FetchedPrompt, PromptContext, ResolvedPrompt } from "./types";
1
+ import type { FetchedPrompt, ResolvedPrompt } from "./types";
2
2
 
3
3
  export interface CacheConfig {
4
4
  /** Time-to-live in seconds. Default: 300 (5 minutes) */
@@ -46,9 +46,9 @@ export function buildCacheKey(
46
46
  /**
47
47
  * Build a cache key for an env-aware `fetch()` call.
48
48
  *
49
- * Folds in `env`, `context`, and `subject` ON TOP of the base
49
+ * Folds in `env` and `subject` ON TOP of the base
50
50
  * project/slug/labels/variables key so two calls that differ only by
51
- * env/context/subject do not return a stale cross-env / cross-cohort hit
51
+ * env/subject do not return a stale cross-env / cross-cohort hit
52
52
  * (spec §3 "Caching key changes"). The env slug is also forwarded as the
53
53
  * single resolution label (env→label mapping, correction #3), so it appears
54
54
  * in the `labels` segment too; including it explicitly here keeps the key
@@ -62,17 +62,14 @@ export function buildFetchCacheKey(
62
62
  projectId: string,
63
63
  slug: string,
64
64
  env: string,
65
- context?: PromptContext,
66
65
  subject?: string,
67
66
  variables?: Record<string, unknown>,
68
67
  developerRole?: string,
69
68
  ): string {
70
69
  const base = buildCacheKey(projectId, slug, [env], variables);
71
- const ctxPart =
72
- context !== undefined ? JSON.stringify(sortObjectKeys(context)) : null;
73
70
  // `developerRole` partitions the cache; coalesce the default so omitted and
74
71
  // `"user"` (the documented default) share one entry, not two.
75
- return `fetch|${base}|${JSON.stringify(env)}|${JSON.stringify(ctxPart)}|${JSON.stringify(subject ?? null)}|${JSON.stringify(developerRole ?? "user")}`;
72
+ return `fetch|${base}|${JSON.stringify(env)}|${JSON.stringify(subject ?? null)}|${JSON.stringify(developerRole ?? "user")}`;
76
73
  }
77
74
 
78
75
  function sortObjectKeys(obj: unknown): unknown {
@@ -94,7 +94,6 @@ export type {
94
94
  ProjectPromptLabel,
95
95
  ProjectPromptLabelUsage,
96
96
  Prompt,
97
- PromptContext,
98
97
  PromptFormat,
99
98
  PromptLabelEvent,
100
99
  PromptLabelPointer,
@@ -111,7 +110,6 @@ export type {
111
110
  RowError,
112
111
  TextChatMessage,
113
112
  TextChatRole,
114
- ToolChatMessage,
115
113
  UpdateProjectPromptLabelInput,
116
114
  UpdateProjectPromptLabelResult,
117
115
  UpdatePromptInput,
@@ -126,6 +124,7 @@ const zResolvedPromptLegacy = zResolvedPrompt.pick({
126
124
  contentHash: true,
127
125
  rendered: true,
128
126
  tools: true,
127
+ toolChoice: true,
129
128
  });
130
129
 
131
130
  const zResolvedPromptEnvelope = zResolvedPrompt
@@ -187,6 +186,13 @@ function normalizeResolvedEnvelope(
187
186
  if (raw.tools != null && raw.tools.length > 0) {
188
187
  result.tools = raw.tools;
189
188
  }
189
+ // `toolChoice` mirrors `tools`: present IFF the resolved version declares a
190
+ // directive. The wire may send `null` (or omit it); normalize both to absent
191
+ // so callers feed `toOpenAIToolChoice` / `toAnthropicToolChoice` (which map
192
+ // `null`/`undefined` → omit) without a separate guard.
193
+ if (raw.toolChoice != null) {
194
+ result.toolChoice = raw.toolChoice;
195
+ }
190
196
  // Set `variantName` only when it is a non-empty string, so the key is
191
197
  // genuinely absent for `single`-strategy releases (R5: present IFF weighted —
192
198
  // never `null`, never `""`). A `null`/`""` from the wire is normalized to
@@ -441,8 +447,8 @@ export class PromptResource {
441
447
  * label-based (`/v1/projects/:projectId/prompts:resolve`, body
442
448
  * `labels[]`); it does NOT accept a top-level `env` field. The resolved
443
449
  * env slug (lowercase-kebab — a valid label name) is therefore sent as
444
- * the single resolution label: body `{ slug, labels: [env], context?,
445
- * subject?, variables? }`.
450
+ * the single resolution label: body `{ slug, labels: [env], subject?,
451
+ * variables? }`.
446
452
  * - **No silent fallback (R4):** if no env is resolvable (none at init AND
447
453
  * none per call) this throws `EnvNotFoundError` (`reason.source =
448
454
  * "missing"`) CLIENT-side, eagerly, before any transport call.
@@ -481,7 +487,6 @@ export class PromptResource {
481
487
  }
482
488
 
483
489
  const {
484
- context,
485
490
  subject,
486
491
  variables,
487
492
  cache: useCache = true,
@@ -493,7 +498,6 @@ export class PromptResource {
493
498
  this.projectId,
494
499
  slug,
495
500
  env,
496
- context,
497
501
  subject,
498
502
  variables,
499
503
  developerRole,
@@ -508,7 +512,6 @@ export class PromptResource {
508
512
 
509
513
  // env→label mapping: the env slug is the single resolution label.
510
514
  const body: Record<string, unknown> = { slug, labels: [env] };
511
- if (context !== undefined) body.context = context;
512
515
  if (subject !== undefined) body.subject = subject;
513
516
  if (variables !== undefined) body.variables = variables;
514
517
  if (developerRole !== undefined) body.developerRole = developerRole;
@@ -559,8 +562,8 @@ export class PromptResource {
559
562
 
560
563
  /**
561
564
  * @deprecated Use {@link PromptResource.fetch | `prompts.fetch(slug,
562
- * options?)`} instead. `resolve()` is env-agnostic (no `env` / `context` /
563
- * `subject`, no enriched release/variant provenance, no typed-env errors)
565
+ * options?)`} instead. `resolve()` is env-agnostic (no `env` / `subject`,
566
+ * no enriched release/variant provenance, no typed-env errors)
564
567
  * and is retained only for back-compat. It is NOT subject to the R4
565
568
  * no-silent-fallback env gate (it has no env concept). New code should
566
569
  * configure `projectId` + `env` at `createClient` and call `fetch()`.
@@ -32,15 +32,7 @@ export interface TextChatMessage {
32
32
  disabled?: boolean;
33
33
  }
34
34
 
35
- export interface ToolChatMessage {
36
- role: "tool";
37
- name: string;
38
- description?: string;
39
- parameters: unknown;
40
- disabled?: boolean;
41
- }
42
-
43
- export type ChatMessage = TextChatMessage | ToolChatMessage;
35
+ export type ChatMessage = TextChatMessage;
44
36
 
45
37
  export type RenderedChatMessage = GenRenderedChatPrompt["messages"][number];
46
38
 
@@ -68,6 +60,7 @@ export type ResolvedPrompt = Pick<
68
60
  | "contentHash"
69
61
  | "rendered"
70
62
  | "tools"
63
+ | "toolChoice"
71
64
  >;
72
65
 
73
66
  export interface PaginationInfo {
@@ -188,8 +181,6 @@ export const ENV_SLUG_REGEX = /^[a-z0-9-]{1,63}$/;
188
181
 
189
182
  export type BlockRenderRecord = Record<string, "rendered" | "dimmed">;
190
183
 
191
- export type PromptContext = Record<string, string | number | boolean>;
192
-
193
184
  export interface FetchedPrompt {
194
185
  messages: RenderedChatMessage[];
195
186
  version: number;
@@ -207,6 +198,16 @@ export interface FetchedPrompt {
207
198
  * tools. Shape for a provider with `toOpenAITools` / `toAnthropicTools`.
208
199
  */
209
200
  tools?: ResolvedToolDefinition[];
201
+ /**
202
+ * Provider-neutral tool-choice directive lifted from the resolved version.
203
+ * Absent (rather than `null`) when the version declares none. Feed straight
204
+ * into `toOpenAIToolChoice` / `toAnthropicToolChoice`.
205
+ *
206
+ * `NonNullable` because `normalizeResolvedEnvelope` maps wire-`null` to absent,
207
+ * so a present `FetchedPrompt.toolChoice` is never `null` — callers get the
208
+ * key or nothing, and never have to branch on `null`.
209
+ */
210
+ toolChoice?: NonNullable<ResolvedPrompt["toolChoice"]>;
210
211
  }
211
212
 
212
213
  export type ResolvedPromptEnvelope = GenResolvedPrompt & {
@@ -224,7 +225,6 @@ export type DeveloperRole = "user" | "developer" | "system";
224
225
 
225
226
  export interface FetchPromptOptions {
226
227
  env?: string;
227
- context?: PromptContext;
228
228
  subject?: string;
229
229
  variables?: Record<string, unknown>;
230
230
  cache?: boolean;