@to11ai/sdk 2.0.0-rc.1 → 2.0.0-rc.3

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 CHANGED
@@ -108,7 +108,7 @@ function createClient(options = {}) {
108
108
  const getAccessToken = options.getAccessToken;
109
109
  const apiKey = getAccessToken !== undefined ? options.apiKey : pick(options.apiKey, "TO11_API_KEY");
110
110
  const projectId = pick(options.projectId, "TO11_PROJECT_ID");
111
- const env = options.env;
111
+ const env = pick(options.env, "TO11_ENV");
112
112
  const providerApiKey = options.providerApiKey?.trim() || undefined;
113
113
  if (isBrowser && options.apiKey !== undefined) {
114
114
  throw new Error("[to11ai/sdk] Do not use `apiKey` in browser contexts — use `getAccessToken` instead.");
@@ -119,6 +119,9 @@ function createClient(options = {}) {
119
119
  if (options.projectId !== undefined && options.projectId.trim() === "") {
120
120
  throw new Error("[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.");
121
121
  }
122
+ if (options.env !== undefined && options.env.trim() === "") {
123
+ throw new Error("[to11ai/sdk] `env` must not be an empty string — omit it or pass a valid env slug.");
124
+ }
122
125
  if (env !== undefined && !import_types.ENV_SLUG_REGEX.test(env)) {
123
126
  throw new Error(`[to11ai/sdk] \`env\` must match ${import_types.ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
124
127
  }
@@ -191,6 +194,7 @@ function createClient(options = {}) {
191
194
  resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault),
192
195
  apiKey,
193
196
  gatewayUrl,
197
+ projectId,
194
198
  session: (id) => new import_context.Session(gatewayAuthContext(), id),
195
199
  conversation: (id) => clientDefaultSession().conversation(id),
196
200
  turn: () => clientDefaultSession().turn(),
package/dist/client.d.ts CHANGED
@@ -17,7 +17,7 @@ export type { CacheConfig } from "./prompts/cache";
17
17
  export type { PromptResourceConfig } from "./prompts/resource";
18
18
  export { PromptResource } from "./prompts/resource";
19
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";
20
+ export type { BlockRenderRecord, RenderedChatMessage, RenderedPrompt, RenderFormat, RenderOptions, ResolvedPrompt, ResolvedPromptEnvelope, UnknownRoleMode, } from "./prompts/types";
21
21
  export { ENV_SLUG_REGEX } from "./prompts/types";
22
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";
23
23
  export { RoutingRuleReleaseResource, RoutingRulesResource, RoutingRuleVersionResource, } from "./routingRules/resource";
@@ -57,8 +57,9 @@ export interface ClientOptions {
57
57
  projectId?: string;
58
58
  /**
59
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}$`).
60
+ * render unless overridden per call. Precedence: this option → `TO11_ENV`
61
+ * env. Validated eagerly against the project-environments slug rule
62
+ * (`^[a-z0-9-]{1,63}$`).
62
63
  */
63
64
  env?: string;
64
65
  /**
@@ -126,6 +127,12 @@ export interface To11aiClient<F extends RenderFormat | undefined = undefined> {
126
127
  readonly apiKey: string | undefined;
127
128
  /** Resolved data-plane gateway URL (option → `TO11_GATEWAY_URL` → default). */
128
129
  readonly gatewayUrl: string;
130
+ /**
131
+ * Resolved project id (option → `TO11_PROJECT_ID`); `undefined` when none is
132
+ * configured. Read-only, for your own logging / manual headers — `prompts.*`
133
+ * already default to it, so you don't need to pass it back into calls.
134
+ */
135
+ readonly projectId: string | undefined;
129
136
  /** A new session (unit of work). Pass an id to group telemetry by your own id. */
130
137
  session(id?: string): Session;
131
138
  /**
package/dist/client.js CHANGED
@@ -64,7 +64,7 @@ function createClient(options = {}) {
64
64
  const getAccessToken = options.getAccessToken;
65
65
  const apiKey = getAccessToken !== undefined ? options.apiKey : pick(options.apiKey, "TO11_API_KEY");
66
66
  const projectId = pick(options.projectId, "TO11_PROJECT_ID");
67
- const env = options.env;
67
+ const env = pick(options.env, "TO11_ENV");
68
68
  const providerApiKey = options.providerApiKey?.trim() || undefined;
69
69
  if (isBrowser && options.apiKey !== undefined) {
70
70
  throw new Error("[to11ai/sdk] Do not use `apiKey` in browser contexts — use `getAccessToken` instead.");
@@ -75,6 +75,9 @@ function createClient(options = {}) {
75
75
  if (options.projectId !== undefined && options.projectId.trim() === "") {
76
76
  throw new Error("[to11ai/sdk] `projectId` must not be an empty string — omit it or pass a valid project id.");
77
77
  }
78
+ if (options.env !== undefined && options.env.trim() === "") {
79
+ throw new Error("[to11ai/sdk] `env` must not be an empty string — omit it or pass a valid env slug.");
80
+ }
78
81
  if (env !== undefined && !ENV_SLUG_REGEX.test(env)) {
79
82
  throw new Error(`[to11ai/sdk] \`env\` must match ${ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
80
83
  }
@@ -147,6 +150,7 @@ function createClient(options = {}) {
147
150
  resolveBehavior: (key, codedDefault) => behaviorStore.resolve(key, codedDefault),
148
151
  apiKey,
149
152
  gatewayUrl,
153
+ projectId,
150
154
  session: (id) => new Session(gatewayAuthContext(), id),
151
155
  conversation: (id) => clientDefaultSession().conversation(id),
152
156
  turn: () => clientDefaultSession().turn(),
package/dist/context.d.ts CHANGED
@@ -17,7 +17,7 @@ export interface TurnAuthContext {
17
17
  }
18
18
  /**
19
19
  * A prompt argument accepted by `turn.headers()`. Either the flat provenance
20
- * (a neutral `FetchedPrompt`) or a `format`-shaped result carrying it under
20
+ * (a neutral `RenderedPrompt`) or a `format`-shaped result carrying it under
21
21
  * `metadata` — both are accepted so the format and neutral render paths carry
22
22
  * provenance identically.
23
23
  */
package/dist/gateway.cjs CHANGED
@@ -88,6 +88,9 @@ function gatewayPromptHeaders(prompt) {
88
88
  if (prompt.label.length > 0) {
89
89
  headers["x-to11-prompt-label"] = prompt.label;
90
90
  }
91
+ if (typeof prompt.slug === "string" && prompt.slug.length > 0) {
92
+ headers["x-to11-prompt-slug"] = prompt.slug;
93
+ }
91
94
  return headers;
92
95
  }
93
96
  function toOpenAITools(tools) {
package/dist/gateway.d.ts CHANGED
@@ -42,6 +42,9 @@ export declare function gatewayAuthHeaders(options: GatewayAuthOptions): Record<
42
42
  * release was weighted); omitted for `single`-strategy releases.
43
43
  * - `x-to11-prompt-label` — the single label the prompt resolved through (the
44
44
  * env slug today); omitted when empty (the gateway rejects empty values).
45
+ * - `x-to11-prompt-slug` — the prompt's human-readable slug, so traces show a
46
+ * readable name alongside the opaque `x-to11-prompt-id`; omitted when empty
47
+ * or absent (a legacy `resolve()` result carries no slug).
45
48
  *
46
49
  * The parameter type is WIDENED to accept either the enriched `render()`
47
50
  * result or the legacy `ResolvedPrompt`. The new fields are read when present
@@ -57,6 +60,11 @@ export interface GatewayPromptProvenance {
57
60
  version: number;
58
61
  /** The single label the prompt resolved through (env slug today). */
59
62
  label: string;
63
+ /**
64
+ * The prompt's human-readable slug (the `render()`/`resolve()` input). Present
65
+ * on an enriched `render()` result; a legacy `ResolvedPrompt` omits it.
66
+ */
67
+ slug?: string;
60
68
  /** Present on an enriched result; a legacy `resolve()` result omits it. */
61
69
  releaseId?: string | null;
62
70
  /** Present IFF the resolved release was weighted. */
package/dist/gateway.js CHANGED
@@ -39,6 +39,9 @@ function gatewayPromptHeaders(prompt) {
39
39
  if (prompt.label.length > 0) {
40
40
  headers["x-to11-prompt-label"] = prompt.label;
41
41
  }
42
+ if (typeof prompt.slug === "string" && prompt.slug.length > 0) {
43
+ headers["x-to11-prompt-slug"] = prompt.slug;
44
+ }
42
45
  return headers;
43
46
  }
44
47
  function toOpenAITools(tools) {
@@ -1,4 +1,4 @@
1
- import type { FetchedPrompt, ResolvedPrompt } from "./types";
1
+ import type { RenderedPrompt } from "./types";
2
2
  export interface CacheConfig {
3
3
  /** Time-to-live in seconds. Default: 300 (5 minutes) */
4
4
  ttlSeconds?: number;
@@ -6,12 +6,11 @@ export interface CacheConfig {
6
6
  maxEntries?: number;
7
7
  }
8
8
  /**
9
- * The cache stores either a legacy `resolve()` result or an enriched
10
- * `render()` result. Both are JSON-cloneable; the cache is shape-agnostic.
9
+ * The cache stores enriched `render()` results, which are JSON-cloneable.
11
10
  */
12
- export type CacheableResolved = ResolvedPrompt | FetchedPrompt;
11
+ export type CacheableRendered = RenderedPrompt;
13
12
  /**
14
- * Build a canonical cache key for a resolve() call.
13
+ * Build a canonical base cache key from project/slug/labels/variables.
15
14
  *
16
15
  * - projectId is included to prevent cross-project cache collisions: a single
17
16
  * PromptResource can serve multiple projects, so the same slug+labels must
@@ -38,9 +37,9 @@ export declare function buildCacheKey(projectId: string, slug: string, labels: s
38
37
  * caches as the same deterministic variant on repeat (D8); the
39
38
  * weighted-no-subject bypass is handled in the resource, not here.
40
39
  */
41
- export declare function buildFetchCacheKey(projectId: string, slug: string, env: string, subject?: string, variables?: Record<string, unknown>): string;
40
+ export declare function buildRenderCacheKey(projectId: string, slug: string, env: string, subject?: string, variables?: Record<string, unknown>): string;
42
41
  /**
43
- * In-memory LRU cache for ResolvedPrompt objects.
42
+ * In-memory LRU cache for RenderedPrompt objects.
44
43
  *
45
44
  * Uses a Map (insertion-ordered) as the backing store. On every access, the
46
45
  * entry is deleted and re-inserted to maintain LRU order — oldest entries sit
@@ -51,8 +50,8 @@ export declare class PromptCache {
51
50
  private readonly maxEntries;
52
51
  private readonly store;
53
52
  constructor(config?: CacheConfig);
54
- get(key: string): CacheableResolved | undefined;
55
- set(key: string, value: CacheableResolved): void;
53
+ get(key: string): CacheableRendered | undefined;
54
+ set(key: string, value: CacheableRendered): void;
56
55
  delete(key: string): void;
57
56
  clear(): void;
58
57
  get size(): number;
@@ -48,17 +48,6 @@ var import_zod2 = require("../generated/zod.gen");
48
48
  var import_cache = require("./cache");
49
49
  var import_shape = require("./shape");
50
50
  var import_types = require("./types");
51
- var zResolvedPromptLegacy = import_zod2.zResolvedPrompt.pick({
52
- promptId: true,
53
- versionId: true,
54
- version: true,
55
- label: true,
56
- contentHash: true,
57
- rendered: true,
58
- tools: true,
59
- toolChoice: true,
60
- modelConfig: true
61
- });
62
51
  var zResolvedPromptEnvelope = import_zod2.zResolvedPrompt.partial({ releaseId: true }).extend({ strategy: import_zod.z.enum(["single", "weighted"]).optional() });
63
52
  function unwrap(envelope) {
64
53
  if (envelope.data === null || envelope.data === undefined) {
@@ -70,12 +59,12 @@ function getProjectPromptsPath(projectId) {
70
59
  return `/v1/projects/${encodeURIComponent(projectId)}/prompts`;
71
60
  }
72
61
  function renderedToMessages(rendered) {
73
- if (rendered.format === "chat") {
74
- return rendered.messages;
62
+ if (rendered.format !== "chat") {
63
+ throw new Error("[to11ai/sdk] Unsupported non-chat prompt format; author the prompt as chat blocks.");
75
64
  }
76
- return [{ role: "user", content: rendered.text }];
65
+ return rendered.messages;
77
66
  }
78
- function normalizeResolvedEnvelope(raw) {
67
+ function normalizeResolvedEnvelope(raw, slug) {
79
68
  const provenance = raw;
80
69
  const result = {
81
70
  messages: renderedToMessages(raw.rendered),
@@ -86,7 +75,7 @@ function normalizeResolvedEnvelope(raw) {
86
75
  versionId: raw.versionId,
87
76
  contentHash: raw.contentHash,
88
77
  label: raw.label,
89
- rendered: raw.rendered,
78
+ slug,
90
79
  modelConfig: provenance.modelConfig
91
80
  };
92
81
  if (raw.tools != null && raw.tools.length > 0) {
@@ -100,11 +89,11 @@ function normalizeResolvedEnvelope(raw) {
100
89
  }
101
90
  return result;
102
91
  }
103
- function liftFallbackToFetched(fallback) {
104
- if ("messages" in fallback) {
105
- return structuredClone(fallback);
92
+ function liftFallbackToRendered(fallback, slug) {
93
+ if (!Array.isArray(fallback.messages)) {
94
+ throw new Error("[to11ai/sdk] `fallback` must be a RenderedPrompt (as returned by render()); the legacy resolve() shape is no longer supported.");
106
95
  }
107
- return normalizeResolvedEnvelope(fallback);
96
+ return { ...structuredClone(fallback), slug: fallback.slug || slug };
108
97
  }
109
98
  function getProjectPromptPath(projectId, promptId) {
110
99
  return `${getProjectPromptsPath(projectId)}/${encodeURIComponent(promptId)}`;
@@ -152,13 +141,22 @@ class PromptResource {
152
141
  this.format = config?.format;
153
142
  this.onUnknownRole = config?.onUnknownRole;
154
143
  }
144
+ resolveProjectId(perCall) {
145
+ const projectId = perCall ?? this.projectId;
146
+ if (projectId === undefined || projectId.trim() === "") {
147
+ throw new Error("[to11ai/sdk] this call needs a `projectId` — pass it on the call or bind one via createClient({ projectId, ... }).");
148
+ }
149
+ return projectId.trim();
150
+ }
155
151
  async create(input) {
156
- const { projectId, ...body } = input;
152
+ const { projectId: perCallProjectId, ...body } = input;
153
+ const projectId = this.resolveProjectId(perCallProjectId);
157
154
  const envelope = await this.transport.request("POST", getProjectPromptsPath(projectId), { body });
158
155
  return unwrap(envelope);
159
156
  }
160
- async list(input) {
161
- const { projectId, ...queryRest } = input;
157
+ async list(input = {}) {
158
+ const { projectId: perCallProjectId, ...queryRest } = input;
159
+ const projectId = this.resolveProjectId(perCallProjectId);
162
160
  const envelope = await this.transport.request("GET", getProjectPromptsPath(projectId), {
163
161
  query: {
164
162
  ...queryRest
@@ -175,52 +173,60 @@ class PromptResource {
175
173
  return { items, pagination };
176
174
  }
177
175
  async get(input) {
178
- const { projectId, promptId } = input;
176
+ const { projectId: perCallProjectId, promptId } = input;
177
+ const projectId = this.resolveProjectId(perCallProjectId);
179
178
  const envelope = await this.transport.request("GET", getProjectPromptPath(projectId, promptId));
180
179
  return unwrap(envelope);
181
180
  }
182
181
  async update(input) {
183
- const { projectId, promptId, ...body } = input;
182
+ const { projectId: perCallProjectId, promptId, ...body } = input;
183
+ const projectId = this.resolveProjectId(perCallProjectId);
184
184
  const envelope = await this.transport.request("PATCH", getProjectPromptPath(projectId, promptId), { body });
185
185
  return unwrap(envelope);
186
186
  }
187
187
  async archive(input) {
188
- const { projectId, promptId } = input;
188
+ const { projectId: perCallProjectId, promptId } = input;
189
+ const projectId = this.resolveProjectId(perCallProjectId);
189
190
  const envelope = await this.transport.request("DELETE", getProjectPromptPath(projectId, promptId));
190
191
  return unwrap(envelope);
191
192
  }
192
193
  async createVersion(input) {
193
- const { projectId, promptId, ...body } = input;
194
+ const { projectId: perCallProjectId, promptId, ...body } = input;
195
+ const projectId = this.resolveProjectId(perCallProjectId);
194
196
  const envelope = await this.transport.request("POST", `${getProjectPromptPath(projectId, promptId)}/versions`, { body });
195
197
  return unwrap(envelope);
196
198
  }
197
199
  async listVersions(input) {
198
- const { projectId, promptId } = input;
200
+ const { projectId: perCallProjectId, promptId } = input;
201
+ const projectId = this.resolveProjectId(perCallProjectId);
199
202
  const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/versions`);
200
203
  return unwrap(envelope);
201
204
  }
202
205
  async getVersion(input) {
203
- const { projectId, promptId, versionNumber } = input;
206
+ const { projectId: perCallProjectId, promptId, versionNumber } = input;
207
+ const projectId = this.resolveProjectId(perCallProjectId);
204
208
  const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/versions/${encodeURIComponent(String(versionNumber))}`);
205
209
  return unwrap(envelope);
206
210
  }
207
211
  async moveLabel(input) {
208
- const { projectId, promptId, label, ...body } = input;
212
+ const { projectId: perCallProjectId, promptId, label, ...body } = input;
213
+ const projectId = this.resolveProjectId(perCallProjectId);
209
214
  const envelope = await this.transport.request("PUT", `${getProjectPromptPath(projectId, promptId)}/labels/${encodeURIComponent(label)}`, { body });
210
215
  return unwrap(envelope);
211
216
  }
212
217
  async listLabels(input) {
213
- const { projectId, promptId } = input;
218
+ const { projectId: perCallProjectId, promptId } = input;
219
+ const projectId = this.resolveProjectId(perCallProjectId);
214
220
  const envelope = await this.transport.request("GET", `${getProjectPromptPath(projectId, promptId)}/labels`);
215
221
  return unwrap(envelope);
216
222
  }
217
223
  async render(slug, options = {}) {
218
- const fetched = await this.resolveToFetched(slug, options);
219
- return import_shape.shapePrompt(fetched, options.format ?? this.format, {
224
+ const rendered = await this.resolveToRendered(slug, options);
225
+ return import_shape.shapePrompt(rendered, options.format ?? this.format, {
220
226
  onUnknownRole: options.onUnknownRole ?? this.onUnknownRole
221
227
  });
222
228
  }
223
- async resolveToFetched(slug, options = {}) {
229
+ async resolveToRendered(slug, options = {}) {
224
230
  if (this.projectId === undefined || this.projectId.trim() === "") {
225
231
  throw new Error("[to11ai/sdk] `prompts.render()` requires a `projectId` on the client — pass it to createClient({ projectId, ... }).");
226
232
  }
@@ -232,10 +238,10 @@ class PromptResource {
232
238
  throw new Error(`[to11ai/sdk] \`env\` must match ${import_types.ENV_SLUG_REGEX} (lowercase-kebab, 1-63 chars). Received: ${JSON.stringify(env)}`);
233
239
  }
234
240
  const { subject, variables, cache: useCache = true, fallback } = options;
235
- const cacheKey = import_cache.buildFetchCacheKey(this.projectId, slug, env, subject, variables);
241
+ const cacheKey = import_cache.buildRenderCacheKey(this.projectId, slug, env, subject, variables);
236
242
  if (useCache) {
237
243
  const cached = this.cache.get(cacheKey);
238
- if (cached && "messages" in cached)
244
+ if (cached)
239
245
  return structuredClone(cached);
240
246
  }
241
247
  const body = { slug, labels: [env] };
@@ -249,7 +255,7 @@ class PromptResource {
249
255
  decode: (data) => zResolvedPromptEnvelope.parse(data)
250
256
  });
251
257
  const raw = unwrap(envelope);
252
- const result = normalizeResolvedEnvelope(raw);
258
+ const result = normalizeResolvedEnvelope(raw, slug);
253
259
  const isWeighted = raw.strategy === "weighted" || result.variantName !== undefined;
254
260
  const cacheable = !(isWeighted && subject === undefined);
255
261
  if (useCache && cacheable) {
@@ -258,61 +264,33 @@ class PromptResource {
258
264
  return result;
259
265
  } catch (err) {
260
266
  if (err instanceof import_errors.To11aiNetworkError && fallback !== undefined) {
261
- return liftFallbackToFetched(fallback);
262
- }
263
- throw err;
264
- }
265
- }
266
- async resolve(input) {
267
- const {
268
- projectId,
269
- slug,
270
- labels,
271
- variables,
272
- cache: useCache = true,
273
- fallback
274
- } = input;
275
- const cacheKey = import_cache.buildCacheKey(projectId, slug, labels, variables);
276
- if (useCache) {
277
- const cached = this.cache.get(cacheKey);
278
- if (cached && !("messages" in cached))
279
- return structuredClone(cached);
280
- }
281
- try {
282
- const envelope = await this.transport.request("POST", `${getProjectPromptsPath(projectId)}:resolve`, {
283
- body: { slug, labels, variables },
284
- decode: (data) => zResolvedPromptLegacy.parse(data)
285
- });
286
- const result = unwrap(envelope);
287
- if (useCache) {
288
- this.cache.set(cacheKey, structuredClone(result));
289
- }
290
- return result;
291
- } catch (err) {
292
- if (err instanceof import_errors.To11aiNetworkError && fallback !== undefined) {
293
- return fallback;
267
+ return liftFallbackToRendered(fallback, slug);
294
268
  }
295
269
  throw err;
296
270
  }
297
271
  }
298
- async listProjectLabels(input) {
299
- const { projectId, includeArchived } = input;
272
+ async listProjectLabels(input = {}) {
273
+ const { projectId: perCallProjectId, includeArchived } = input;
274
+ const projectId = this.resolveProjectId(perCallProjectId);
300
275
  const envelope = await this.transport.request("GET", getProjectPromptLabelsPath(projectId), {
301
276
  query: includeArchived ? { includeArchived: "true" } : undefined
302
277
  });
303
278
  return unwrap(envelope);
304
279
  }
305
280
  async createProjectLabel(input) {
306
- const { projectId, ...body } = input;
281
+ const { projectId: perCallProjectId, ...body } = input;
282
+ const projectId = this.resolveProjectId(perCallProjectId);
307
283
  const envelope = await this.transport.request("POST", getProjectPromptLabelsPath(projectId), { body });
308
284
  return unwrap(envelope);
309
285
  }
310
286
  async getProjectLabel(input) {
311
- const envelope = await this.transport.request("GET", getProjectPromptLabelPath(input.projectId, input.label));
287
+ const projectId = this.resolveProjectId(input.projectId);
288
+ const envelope = await this.transport.request("GET", getProjectPromptLabelPath(projectId, input.label));
312
289
  return unwrap(envelope);
313
290
  }
314
291
  async updateProjectLabel(input) {
315
- const { projectId, label, ...rest } = input;
292
+ const { projectId: perCallProjectId, label, ...rest } = input;
293
+ const projectId = this.resolveProjectId(perCallProjectId);
316
294
  const body = {};
317
295
  if (rest.isDefault !== undefined)
318
296
  body.isDefault = rest.isDefault;
@@ -324,15 +302,16 @@ class PromptResource {
324
302
  return unwrap(envelope);
325
303
  }
326
304
  async deleteProjectLabel(input) {
327
- const envelope = await this.transport.request("DELETE", getProjectPromptLabelPath(input.projectId, input.label));
305
+ const projectId = this.resolveProjectId(input.projectId);
306
+ const envelope = await this.transport.request("DELETE", getProjectPromptLabelPath(projectId, input.label));
328
307
  return unwrap(envelope);
329
308
  }
330
309
  async listProjectLabelUsages(input) {
331
- const envelope = await this.transport.request("GET", `${getProjectPromptLabelPath(input.projectId, input.label)}/usages`);
310
+ const envelope = await this.transport.request("GET", `${getProjectPromptLabelPath(this.resolveProjectId(input.projectId), input.label)}/usages`);
332
311
  return unwrap(envelope);
333
312
  }
334
313
  async listLabelEvents(input) {
335
- const projectSeg = encodeURIComponent(input.projectId);
314
+ const projectSeg = encodeURIComponent(this.resolveProjectId(input.projectId));
336
315
  let path;
337
316
  switch (input.scope) {
338
317
  case "label":
@@ -1,9 +1,9 @@
1
1
  import type { Transport } from "../transport";
2
2
  import type { CacheConfig } from "./cache";
3
3
  import type { AnthropicRenderedPrompt, OpenAiRenderedPrompt, RenderResult } from "./shape";
4
- import type { ArchivePromptInput, ArchivePromptResult, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, GetProjectPromptLabelInput, GetProjectPromptLabelResult, GetPromptInput, GetPromptResult, GetPromptVersionInput, GetPromptVersionResult, ListLabelEventsInput, ListLabelEventsResult, ListProjectPromptLabelsInput, ListProjectPromptLabelsResult, ListProjectPromptLabelUsagesInput, ListProjectPromptLabelUsagesResult, ListPromptLabelsInput, ListPromptLabelsResult, ListPromptsInput, ListPromptsResult, ListPromptVersionsInput, ListPromptVersionsResult, MovePromptLabelInput, MovePromptLabelResult, PaginatedResult, RenderFormat, RenderOptions, ResolvePromptInput, ResolvePromptResult, UnknownRoleMode, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult } from "./types";
4
+ import type { ArchivePromptInput, ArchivePromptResult, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, GetProjectPromptLabelInput, GetProjectPromptLabelResult, GetPromptInput, GetPromptResult, GetPromptVersionInput, GetPromptVersionResult, ListLabelEventsInput, ListLabelEventsResult, ListProjectPromptLabelsInput, ListProjectPromptLabelsResult, ListProjectPromptLabelUsagesInput, ListProjectPromptLabelUsagesResult, ListPromptLabelsInput, ListPromptLabelsResult, ListPromptsInput, ListPromptsResult, ListPromptVersionsInput, ListPromptVersionsResult, MovePromptLabelInput, MovePromptLabelResult, PaginatedResult, RenderFormat, RenderOptions, UnknownRoleMode, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult } from "./types";
5
5
  export type { CacheConfig } from "./cache";
6
- 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
+ export type { ArchivePromptInput, ArchivePromptResult, BlockRenderRecord, ChatMessage, CreateProjectPromptLabelInput, CreateProjectPromptLabelResult, CreatePromptInput, CreatePromptResult, CreatePromptVersionInput, CreatePromptVersionResult, DeleteProjectPromptLabelInput, DeleteProjectPromptLabelResult, 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, RenderFormat, RenderOptions, ResolvedPrompt, ResolvedPromptEnvelope, ResolvedToolCall, ResolvedToolDefinition, RowError, TextChatMessage, TextChatRole, UnknownRoleMode, UpdateProjectPromptLabelInput, UpdateProjectPromptLabelResult, UpdatePromptInput, UpdatePromptResult, } from "./types";
7
7
  /**
8
8
  * Init-time config for the env-aware `render()` surface (TO11-980 / S9).
9
9
  *
@@ -34,8 +34,15 @@ export declare class PromptResource<F extends RenderFormat | undefined = undefin
34
34
  constructor(transport: Transport, cacheConfig?: CacheConfig, config?: Omit<PromptResourceConfig, "format"> & {
35
35
  format?: F;
36
36
  });
37
+ /**
38
+ * Resolve the project for a control-plane call: the per-call `projectId`
39
+ * wins, else the client-bound one from `createClient({ projectId })`. Throws
40
+ * if neither is set. Mirrors how `render()` resolves its project, so every
41
+ * method honors the bound `projectId` and callers need not repeat it.
42
+ */
43
+ private resolveProjectId;
37
44
  create(input: CreatePromptInput): Promise<CreatePromptResult>;
38
- list(input: ListPromptsInput): Promise<PaginatedResult<ListPromptsResult>>;
45
+ list(input?: ListPromptsInput): Promise<PaginatedResult<ListPromptsResult>>;
39
46
  get(input: GetPromptInput): Promise<GetPromptResult>;
40
47
  update(input: UpdatePromptInput): Promise<UpdatePromptResult>;
41
48
  archive(input: ArchivePromptInput): Promise<ArchivePromptResult>;
@@ -49,8 +56,7 @@ export declare class PromptResource<F extends RenderFormat | undefined = undefin
49
56
  * `projectId` + `env`, in one control-plane request. With a `format` (per
50
57
  * call or inherited from the client) the result is provider-shaped
51
58
  * `{ messages, config, metadata }`; without one it is the neutral
52
- * `FetchedPrompt`. Resolves by the client's `env`; for label-addressed
53
- * resolution see {@link PromptResource.resolve | `resolve()`}.
59
+ * `RenderedPrompt`. Resolves by the client's configured `env`.
54
60
  *
55
61
  * @example Render an OpenAI-shaped prompt and send it through the gateway
56
62
  * const prompt = await to11.prompts.render("weather-concierge", {
@@ -69,7 +75,7 @@ export declare class PromptResource<F extends RenderFormat | undefined = undefin
69
75
  }): Promise<AnthropicRenderedPrompt>;
70
76
  render(slug: string, options?: RenderOptions): Promise<RenderResult<F>>;
71
77
  /**
72
- * Env-aware resolution → neutral `FetchedPrompt`. Carries the resolve /
78
+ * Env-aware resolution → neutral `RenderedPrompt`. Carries the resolve /
73
79
  * cache / offline-fallback logic; `render()` is the public shaping surface.
74
80
  *
75
81
  * - **env→label wire mapping:** the resolve route is label-based
@@ -82,17 +88,7 @@ export declare class PromptResource<F extends RenderFormat | undefined = undefin
82
88
  * WITH a `subject`; BYPASSES the cache for weighted releases with NO
83
89
  * `subject` (a uniform-random assignment must not be pinned for the TTL).
84
90
  */
85
- private resolveToFetched;
86
- /**
87
- * Resolve a prompt by explicit `labels` for a given `projectId`, in one
88
- * control-plane request. This is the label-addressed counterpart to
89
- * {@link PromptResource.render | `render()`}, which resolves by the client's
90
- * configured `env`. Reach for `resolve()` when you address prompts by label
91
- * rather than by environment; it is env-agnostic, so it carries no `env` /
92
- * `subject`, no enriched release/variant provenance, and no typed-env errors,
93
- * and is not subject to the env-based no-silent-fallback gate.
94
- */
95
- resolve(input: ResolvePromptInput): Promise<ResolvePromptResult>;
91
+ private resolveToRendered;
96
92
  /**
97
93
  * List the project-level label registry.
98
94
  *
@@ -100,7 +96,7 @@ export declare class PromptResource<F extends RenderFormat | undefined = undefin
100
96
  * include rows with a non-null `archivedAt` (useful for admin / history
101
97
  * affordances). Gated on `prompt:read` server-side.
102
98
  */
103
- listProjectLabels(input: ListProjectPromptLabelsInput): Promise<ListProjectPromptLabelsResult>;
99
+ listProjectLabels(input?: ListProjectPromptLabelsInput): Promise<ListProjectPromptLabelsResult>;
104
100
  /**
105
101
  * Create a new project label.
106
102
  *