@kaana.ai/contracts 7.0.0 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/internal/attribution.d.ts +32 -23
  2. package/dist/internal/attribution.js +14 -12
  3. package/dist/internal/catalogue.d.ts +3 -4
  4. package/dist/internal/catalogue.js +18 -18
  5. package/dist/internal/credentialControl.js +4 -3
  6. package/dist/internal/decisions.d.ts +30 -4
  7. package/dist/internal/embeddings.js +4 -3
  8. package/dist/internal/errors.js +3 -2
  9. package/dist/internal/grant.d.ts +36 -9
  10. package/dist/internal/grant.js +34 -15
  11. package/dist/internal/identifiers.js +13 -5
  12. package/dist/internal/realtime.d.ts +15 -2
  13. package/dist/internal/realtime.js +4 -3
  14. package/dist/internal/request.d.ts +15 -2
  15. package/dist/internal/request.js +4 -3
  16. package/dist/internal/routing.js +2 -1
  17. package/dist/internal/settlement.d.ts +30 -4
  18. package/dist/internal/settlement.js +7 -6
  19. package/dist/internal/usage.d.ts +15 -2
  20. package/dist/public/audio.js +12 -7
  21. package/dist/public/audioFormats.js +2 -1
  22. package/dist/public/catalogue.js +18 -13
  23. package/dist/public/chatCompletions.js +26 -23
  24. package/dist/public/decisions.js +4 -3
  25. package/dist/public/embeddings.js +7 -3
  26. package/dist/public/errors.js +4 -3
  27. package/dist/public/generations.js +5 -4
  28. package/dist/public/identifiers.js +20 -14
  29. package/dist/public/images.js +8 -7
  30. package/dist/public/messages.js +31 -17
  31. package/dist/public/money.js +2 -1
  32. package/dist/public/policy.js +2 -1
  33. package/dist/public/realtime.js +30 -20
  34. package/dist/public/responses.js +10 -3
  35. package/dist/public/streamEvents.js +9 -4
  36. package/dist/public/version.d.ts +1 -1
  37. package/dist/public/version.js +1 -1
  38. package/dist/stringBounds.d.ts +11 -0
  39. package/dist/stringBounds.js +61 -0
  40. package/dist/timestampCheck.d.ts +3 -0
  41. package/dist/timestampCheck.js +18 -0
  42. package/openapi.json +7 -15
  43. package/package.json +3 -4
@@ -14,22 +14,23 @@
14
14
  * the Oxy edge rendered them in code only.
15
15
  */
16
16
  import { z } from 'zod';
17
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
17
18
  import { reasoningEffortSchema } from './catalogue.js';
18
19
  import { publicErrorCodeSchema } from './errors.js';
19
20
  import { inferenceContentPartSchema } from './messages.js';
20
21
  import { modelTargetSchema } from './responses.js';
21
22
  /** `stop` in the OpenAI dialect: one sequence or a list of them. */
22
23
  const openAiStopSchema = z.union([
23
- z.string().min(1).max(256),
24
- z.array(z.string().min(1).max(256)).max(8),
24
+ z.string().check(minUtf16Length(1)).check(maxUtf16Length(256)),
25
+ z.array(z.string().check(minUtf16Length(1)).check(maxUtf16Length(256))).max(8),
25
26
  ]);
26
27
  const openAiToolCallSchema = z
27
28
  .object({
28
- id: z.string().min(1).max(128),
29
+ id: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
29
30
  type: z.literal('function'),
30
31
  function: z
31
32
  .object({
32
- name: z.string().min(1).max(128),
33
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
33
34
  arguments: z.string(),
34
35
  })
35
36
  .strict(),
@@ -47,8 +48,8 @@ export const chatCompletionMessageSchema = z
47
48
  .union([z.string(), z.array(inferenceContentPartSchema)])
48
49
  .nullable()
49
50
  .optional(),
50
- name: z.string().max(128).optional(),
51
- tool_call_id: z.string().min(1).max(128).optional(),
51
+ name: z.string().check(maxUtf16Length(128)).optional(),
52
+ tool_call_id: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
52
53
  tool_calls: z.array(openAiToolCallSchema).optional(),
53
54
  })
54
55
  .strict();
@@ -57,8 +58,8 @@ const openAiToolSchema = z
57
58
  type: z.literal('function'),
58
59
  function: z
59
60
  .object({
60
- name: z.string().min(1).max(128),
61
- description: z.string().max(2000).optional(),
61
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
62
+ description: z.string().check(maxUtf16Length(2000)).optional(),
62
63
  parameters: z.record(z.string(), z.unknown()),
63
64
  strict: z.boolean().optional(),
64
65
  })
@@ -70,7 +71,9 @@ const openAiToolChoiceSchema = z.union([
70
71
  z
71
72
  .object({
72
73
  type: z.literal('function'),
73
- function: z.object({ name: z.string().min(1).max(128) }).strict(),
74
+ function: z
75
+ .object({ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)) })
76
+ .strict(),
74
77
  })
75
78
  .strict(),
76
79
  ]);
@@ -81,7 +84,7 @@ const openAiToolChoiceSchema = z.union([
81
84
  */
82
85
  const openAiAudioOutputSchema = z
83
86
  .object({
84
- voice: z.string().min(1).max(64),
87
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)),
85
88
  format: z.enum(['wav', 'mp3', 'flac', 'opus', 'pcm16']),
86
89
  })
87
90
  .strict();
@@ -92,7 +95,7 @@ const openAiResponseFormatSchema = z.union([
92
95
  type: z.literal('json_schema'),
93
96
  json_schema: z
94
97
  .object({
95
- name: z.string().min(1).max(128),
98
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
96
99
  schema: z.record(z.string(), z.unknown()),
97
100
  strict: z.boolean().optional(),
98
101
  })
@@ -135,7 +138,7 @@ export const chatCompletionsRequestSchema = z
135
138
  * OpenAI's end-user attribution field: the DELEGATED user id, attribution
136
139
  * only. `X-Oxy-User-Id` wins when both are present.
137
140
  */
138
- user: z.string().min(1).max(64).optional(),
141
+ user: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
139
142
  })
140
143
  .strict()
141
144
  .superRefine((request, ctx) => {
@@ -214,12 +217,12 @@ export const chatCompletionUsageSchema = z
214
217
  */
215
218
  export const chatCompletionSchema = z
216
219
  .object({
217
- id: z.string().min(1),
220
+ id: z.string().check(minUtf16Length(1)),
218
221
  object: z.literal('chat.completion'),
219
222
  /** Unix seconds, as OpenAI's own field is. */
220
223
  created: z.number().int().nonnegative(),
221
224
  /** The revision that served the request. */
222
- model: z.string().min(1),
225
+ model: z.string().check(minUtf16Length(1)),
223
226
  choices: z.array(z
224
227
  .object({
225
228
  index: z.number().int().nonnegative(),
@@ -231,7 +234,7 @@ export const chatCompletionSchema = z
231
234
  /** Spoken output. `expires_at` is `created`: Kaana retains no audio. */
232
235
  audio: z
233
236
  .object({
234
- id: z.string().min(1),
237
+ id: z.string().check(minUtf16Length(1)),
235
238
  data: z.string(),
236
239
  transcript: z.string(),
237
240
  expires_at: z.number().int().nonnegative(),
@@ -245,7 +248,7 @@ export const chatCompletionSchema = z
245
248
  * OpenAI's vocabulary, which has neither `cancelled` nor `refusal`:
246
249
  * both are reported as `stop` here.
247
250
  */
248
- finish_reason: z.string().min(1),
251
+ finish_reason: z.string().check(minUtf16Length(1)),
249
252
  })
250
253
  .strict()),
251
254
  usage: chatCompletionUsageSchema,
@@ -261,10 +264,10 @@ export const chatCompletionSchema = z
261
264
  */
262
265
  export const chatCompletionChunkSchema = z
263
266
  .object({
264
- id: z.string().min(1),
267
+ id: z.string().check(minUtf16Length(1)),
265
268
  object: z.literal('chat.completion.chunk'),
266
269
  created: z.number().int().nonnegative(),
267
- model: z.string().min(1),
270
+ model: z.string().check(minUtf16Length(1)),
268
271
  choices: z.array(z
269
272
  .object({
270
273
  index: z.number().int().nonnegative(),
@@ -275,7 +278,7 @@ export const chatCompletionChunkSchema = z
275
278
  refusal: z.string().optional(),
276
279
  audio: z
277
280
  .object({
278
- id: z.string().min(1),
281
+ id: z.string().check(minUtf16Length(1)),
279
282
  data: z.string().optional(),
280
283
  transcript: z.string().optional(),
281
284
  expires_at: z.number().int().nonnegative().optional(),
@@ -286,7 +289,7 @@ export const chatCompletionChunkSchema = z
286
289
  .array(z
287
290
  .object({
288
291
  index: z.number().int().nonnegative(),
289
- id: z.string().min(1).optional(),
292
+ id: z.string().check(minUtf16Length(1)).optional(),
290
293
  type: z.literal('function').optional(),
291
294
  function: z
292
295
  .object({ name: z.string().optional(), arguments: z.string().optional() })
@@ -296,7 +299,7 @@ export const chatCompletionChunkSchema = z
296
299
  .optional(),
297
300
  })
298
301
  .strict(),
299
- finish_reason: z.string().min(1).nullable(),
302
+ finish_reason: z.string().check(minUtf16Length(1)).nullable(),
300
303
  })
301
304
  .strict()),
302
305
  usage: chatCompletionUsageSchema.optional(),
@@ -311,8 +314,8 @@ export const chatCompletionErrorSchema = z
311
314
  .object({
312
315
  error: z
313
316
  .object({
314
- message: z.string().min(1),
315
- type: z.string().min(1),
317
+ message: z.string().check(minUtf16Length(1)),
318
+ type: z.string().check(minUtf16Length(1)),
316
319
  param: z.string().nullable(),
317
320
  code: publicErrorCodeSchema,
318
321
  })
@@ -4,12 +4,13 @@
4
4
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/decisions.ts`) by Kaana ADR 0002.
5
5
  */
6
6
  import { z } from 'zod';
7
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
7
8
  import { modelReferenceSchema, requestIdSchema } from './identifiers.js';
8
9
  import { usageQuantitySchema } from './money.js';
9
10
  import { routingPolicyReferenceSchema } from './policy.js';
10
11
  const probability = z.number().finite().min(0).max(1);
11
- const text = z.string().min(1).max(65536);
12
- const id = z.string().min(1).max(128);
12
+ const text = z.string().check(minUtf16Length(1)).check(maxUtf16Length(65536));
13
+ const id = z.string().check(minUtf16Length(1)).check(maxUtf16Length(128));
13
14
  const tolerance = 1e-6;
14
15
  export const decisionEffortSchema = z.enum(['instant', 'low', 'medium', 'high', 'xhigh']);
15
16
  const common = { id, question: text, criteria: text.optional() };
@@ -31,7 +32,7 @@ export const decisionQuestionSchema = z.discriminatedUnion('kind', [
31
32
  z.object({ ...common, kind: z.literal('noul') }).strict(),
32
33
  ]);
33
34
  const payloadFields = {
34
- state: z.string().max(65536),
35
+ state: z.string().check(maxUtf16Length(65536)),
35
36
  instructions: text.optional(),
36
37
  questions: z.array(decisionQuestionSchema).min(1).max(255),
37
38
  effort: decisionEffortSchema.optional(),
@@ -8,6 +8,7 @@
8
8
  * vectors of at most 1024 dimensions.
9
9
  */
10
10
  import { z } from 'zod';
11
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
11
12
  import { modelReferenceSchema } from './identifiers.js';
12
13
  /** The most inputs one request may embed. */
13
14
  export const MAX_EMBEDDING_INPUTS = 2048;
@@ -16,15 +17,18 @@ export const embeddingsRequestSchema = z
16
17
  /** A concrete model: an embedding space is a property of exact weights. */
17
18
  model: modelReferenceSchema,
18
19
  input: z.union([
19
- z.string().min(1),
20
- z.array(z.string().min(1)).min(1).max(MAX_EMBEDDING_INPUTS),
20
+ z.string().check(minUtf16Length(1)),
21
+ z
22
+ .array(z.string().check(minUtf16Length(1)))
23
+ .min(1)
24
+ .max(MAX_EMBEDDING_INPUTS),
21
25
  ]),
22
26
  /** Only `float`: base64 vectors are an encoding the contract does not carry. */
23
27
  encoding_format: z.literal('float').optional(),
24
28
  /** Requested output dimension, for models that can shorten their vectors. */
25
29
  dimensions: z.number().int().positive().max(1024).optional(),
26
30
  /** OpenAI's end-user attribution field: the delegated user id, attribution only. */
27
- user: z.string().min(1).max(64).optional(),
31
+ user: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
28
32
  })
29
33
  .strict();
30
34
  export const embeddingsResponseSchema = z
@@ -4,6 +4,7 @@
4
4
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/errors.ts`) by Kaana ADR 0002.
5
5
  */
6
6
  import { z } from 'zod';
7
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
7
8
  import { requestIdSchema } from './identifiers.js';
8
9
  /**
9
10
  * A run of characters long enough and opaque enough to BE a credential.
@@ -104,8 +105,8 @@ const CREDENTIAL_PATTERNS = [
104
105
  */
105
106
  export const safeErrorTextSchema = z
106
107
  .string()
107
- .min(1)
108
- .max(2000)
108
+ .check(minUtf16Length(1))
109
+ .check(maxUtf16Length(2000))
109
110
  .refine((value) => !CREDENTIAL_PATTERNS.some((pattern) => pattern.test(value)), 'error text must not contain credential-shaped material');
110
111
  /**
111
112
  * A coarse classification of an upstream failure (ADR 0010's `upstreamCategory`).
@@ -251,7 +252,7 @@ export const publicErrorSchema = z
251
252
  /** How long to wait before retrying. Only meaningful when `retryable`. */
252
253
  retryAfterMs: z.number().int().nonnegative().safe().optional(),
253
254
  /** The request field at fault, for `invalid_request`. */
254
- param: z.string().max(128).optional(),
255
+ param: z.string().check(maxUtf16Length(128)).optional(),
255
256
  /** The kind of upstream failure, when an upstream was reached. Provider-neutral. */
256
257
  upstreamCategory: upstreamErrorCategorySchema.optional(),
257
258
  })
@@ -14,6 +14,7 @@
14
14
  * provider: no public record names a provider, a key or a deployment.
15
15
  */
16
16
  import { z } from 'zod';
17
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
17
18
  import { delegatedUserIdSchema, generationIdSchema, inferenceEnvironmentSchema, inferenceTimestampSchema, modelReferenceSchema, oxyApplicationIdSchema, oxyCredentialIdSchema, requestIdSchema, } from './identifiers.js';
18
19
  import { requestLabelsSchema } from './messages.js';
19
20
  import { currencyCodeSchema, exactDecimalSchema, priceSnapshotSchema, usageQuantitySchema, usageSourceSchema, } from './money.js';
@@ -65,7 +66,7 @@ export const chargedGenerationRecordSchema = z
65
66
  .object({
66
67
  ...recordFields,
67
68
  kind: z.literal('charge'),
68
- receiptId: z.string().min(1).max(128),
69
+ receiptId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
69
70
  priceSnapshot: priceSnapshotSchema,
70
71
  billedAmount: exactDecimalSchema,
71
72
  currency: currencyCodeSchema,
@@ -91,7 +92,7 @@ export const meteredGenerationRecordSchema = z
91
92
  .object({
92
93
  ...recordFields,
93
94
  kind: z.literal('metered_usage'),
94
- meteredUsageId: z.string().min(1).max(128),
95
+ meteredUsageId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
95
96
  /** The request this one ran inside, for a child such as an Auto classification. */
96
97
  parentRequestId: requestIdSchema.optional(),
97
98
  tariff: z.discriminatedUnion('status', [
@@ -100,13 +101,13 @@ export const meteredGenerationRecordSchema = z
100
101
  status: z.literal('quoted'),
101
102
  amount: exactDecimalSchema,
102
103
  currency: currencyCodeSchema,
103
- priceVersionId: z.string().min(1).max(128),
104
+ priceVersionId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
104
105
  })
105
106
  .strict(),
106
107
  z
107
108
  .object({
108
109
  status: z.literal('unpriced'),
109
- priceVersionId: z.string().min(1).max(128).nullable(),
110
+ priceVersionId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).nullable(),
110
111
  })
111
112
  .strict(),
112
113
  ]),
@@ -7,6 +7,8 @@
7
7
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/identifiers.ts`) by Kaana ADR 0002.
8
8
  */
9
9
  import { z } from 'zod';
10
+ import { utcTimestampCheck } from '../timestampCheck.js';
11
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
10
12
  /**
11
13
  * A delegated end-user identity (Alia's `X-Oxy-User-Id`), branded with a
12
14
  * DIFFERENT brand from {@link oxyAccountIdSchema} so the two cannot be
@@ -17,16 +19,20 @@ import { z } from 'zod';
17
19
  * a billing principal, never an access-control principal, and its presence
18
20
  * never changes which account is charged.
19
21
  */
20
- export const delegatedUserIdSchema = z.string().min(1).max(64).brand();
22
+ export const delegatedUserIdSchema = z
23
+ .string()
24
+ .check(minUtf16Length(1))
25
+ .check(maxUtf16Length(64))
26
+ .brand();
21
27
  /**
22
28
  * An Oxy `Application._id`. Not branded: no invariant in this contract turns on
23
29
  * confusing it with another id, and brand inflation costs every producer a
24
30
  * parse call for no safety. The two ids above are branded because ADR 0007's
25
31
  * rule is exactly that they must not be interchangeable.
26
32
  */
27
- export const oxyApplicationIdSchema = z.string().min(1).max(64);
33
+ export const oxyApplicationIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(64));
28
34
  /** An Oxy `ApplicationCredential._id` — the credential used for this request. */
29
- export const oxyCredentialIdSchema = z.string().min(1).max(64);
35
+ export const oxyCredentialIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(64));
30
36
  /**
31
37
  * A request id allocated by the Oxy EDGE, at admission and BEFORE
32
38
  * authentication, so that a request rejected for a bad credential is as
@@ -48,18 +54,18 @@ export const oxyCredentialIdSchema = z.string().min(1).max(64);
48
54
  * customer-visible receipt, so it appears on every stream event and every
49
55
  * ledger record.
50
56
  */
51
- export const requestIdSchema = z.string().min(1).max(128);
57
+ export const requestIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(128));
52
58
  /**
53
59
  * A generation id generated by the data plane, present when a request produced
54
60
  * a generation that can be looked up later (`GET /v1/generations/:id`).
55
61
  */
56
- export const generationIdSchema = z.string().min(1).max(128);
62
+ export const generationIdSchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(128));
57
63
  /**
58
64
  * A caller-supplied idempotency key. Every reserve/settle/refund call is keyed
59
65
  * on one so a retry, a redelivered event or a duplicated webhook can never
60
66
  * charge twice.
61
67
  */
62
- export const idempotencyKeySchema = z.string().min(1).max(255);
68
+ export const idempotencyKeySchema = z.string().check(minUtf16Length(1)).check(maxUtf16Length(255));
63
69
  /** Credential environments. A credential is issued into exactly one of them. */
64
70
  export const inferenceEnvironmentSchema = z.enum(['development', 'staging', 'production']);
65
71
  /**
@@ -71,7 +77,7 @@ export const inferenceEnvironmentSchema = z.enum(['development', 'staging', 'pro
71
77
  * settled. One canonical spelling (UTC, `Z`) so two records that describe the
72
78
  * same moment compare and sort as equal, which a mix of offsets would not.
73
79
  */
74
- export const inferenceTimestampSchema = z.string().datetime();
80
+ export const inferenceTimestampSchema = z.string().check(utcTimestampCheck());
75
81
  /**
76
82
  * A calendar DATE with no instant attached (`2026-05-01`) — a knowledge cutoff
77
83
  * or a release date, which are published as days and become wrong when a
@@ -83,7 +89,7 @@ export const inferenceDateSchema = z
83
89
  /** An absolute https URL, for model cards, licenses and provider documentation. */
84
90
  export const inferenceHttpsUrlSchema = z
85
91
  .string()
86
- .max(2048)
92
+ .check(maxUtf16Length(2048))
87
93
  .regex(/^https:\/\/[^\s]+$/, 'must be an absolute https URL');
88
94
  /**
89
95
  * A content digest, `sha256:<64 lowercase hex>`.
@@ -106,12 +112,12 @@ const REVISION_PATTERN = '[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?';
106
112
  /** A publisher slug, e.g. `openai`, `anthropic`, `meta`, `alia`. */
107
113
  export const publisherSlugSchema = z
108
114
  .string()
109
- .max(64)
115
+ .check(maxUtf16Length(64))
110
116
  .regex(new RegExp(`^${SLUG_PATTERN}$`), 'publisher must be a lowercase URL-safe slug');
111
117
  /** A model slug within its publisher's namespace, e.g. `gpt-5`, `llama-3.1-70b`. */
112
118
  export const modelSlugSchema = z
113
119
  .string()
114
- .max(64)
120
+ .check(maxUtf16Length(64))
115
121
  .regex(new RegExp(`^${SLUG_PATTERN}$`), 'model must be a lowercase URL-safe slug');
116
122
  /**
117
123
  * A canonical model id, `<publisher>/<model>`. This names a MODEL — a
@@ -120,12 +126,12 @@ export const modelSlugSchema = z
120
126
  */
121
127
  export const modelIdSchema = z
122
128
  .string()
123
- .max(129)
129
+ .check(maxUtf16Length(129))
124
130
  .regex(new RegExp(`^${SLUG_PATTERN}/${SLUG_PATTERN}$`), 'model id must be <publisher>/<model>');
125
131
  /** An immutable revision label, unique within its model, e.g. `2026-05-01`. */
126
132
  export const modelRevisionLabelSchema = z
127
133
  .string()
128
- .max(64)
134
+ .check(maxUtf16Length(64))
129
135
  .regex(new RegExp(`^${REVISION_PATTERN}$`), 'revision must be a URL-safe label');
130
136
  /**
131
137
  * A model reference as a customer writes it: `<publisher>/<model>` (the model's
@@ -139,7 +145,7 @@ export const modelRevisionLabelSchema = z
139
145
  */
140
146
  export const modelReferenceSchema = z
141
147
  .string()
142
- .max(194)
148
+ .check(maxUtf16Length(194))
143
149
  .regex(new RegExp(`^${SLUG_PATTERN}/${SLUG_PATTERN}(?:@${REVISION_PATTERN})?$`), 'model reference must be <publisher>/<model> or <publisher>/<model>@<revision>');
144
150
  /**
145
151
  * A region identifier, e.g. `us-west-2`, `eu-central-1`. Free-form rather than
@@ -148,7 +154,7 @@ export const modelReferenceSchema = z
148
154
  */
149
155
  export const inferenceRegionSchema = z
150
156
  .string()
151
- .max(64)
157
+ .check(maxUtf16Length(64))
152
158
  .regex(new RegExp(`^${SLUG_PATTERN}$`), 'region must be a lowercase URL-safe slug');
153
159
  /**
154
160
  * The publisher namespace reserved for models Alia actually owns or derives.
@@ -7,18 +7,19 @@
7
7
  * catalogue, because a price prices a unit, not a `(unit, size, quality)` tuple.
8
8
  */
9
9
  import { z } from 'zod';
10
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
10
11
  import { modelReferenceSchema } from './identifiers.js';
11
12
  export const imageGenerationsRequestSchema = z
12
13
  .object({
13
14
  model: modelReferenceSchema,
14
- prompt: z.string().min(1).max(32_000),
15
+ prompt: z.string().check(minUtf16Length(1)).check(maxUtf16Length(32_000)),
15
16
  /** OpenAI caps this at 10. Exact, declared, and the whole ceiling. */
16
17
  n: z.number().int().min(1).max(10).optional(),
17
- size: z.string().min(1).max(32).optional(),
18
- quality: z.string().min(1).max(32).optional(),
19
- style: z.string().min(1).max(32).optional(),
18
+ size: z.string().check(minUtf16Length(1)).check(maxUtf16Length(32)).optional(),
19
+ quality: z.string().check(minUtf16Length(1)).check(maxUtf16Length(32)).optional(),
20
+ style: z.string().check(minUtf16Length(1)).check(maxUtf16Length(32)).optional(),
20
21
  response_format: z.enum(['url', 'b64_json']).optional(),
21
- user: z.string().min(1).max(64).optional(),
22
+ user: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)).optional(),
22
23
  })
23
24
  .strict();
24
25
  /**
@@ -29,8 +30,8 @@ export const imageGenerationsSchema = z
29
30
  .object({
30
31
  created: z.number().int().nonnegative(),
31
32
  data: z.array(z.union([
32
- z.object({ url: z.string().min(1) }).strict(),
33
- z.object({ b64_json: z.string().min(1) }).strict(),
33
+ z.object({ url: z.string().check(minUtf16Length(1)) }).strict(),
34
+ z.object({ b64_json: z.string().check(minUtf16Length(1)) }).strict(),
34
35
  ])),
35
36
  })
36
37
  .strict();
@@ -5,6 +5,7 @@
5
5
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/request.ts`) by Kaana ADR 0002.
6
6
  */
7
7
  import { z } from 'zod';
8
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
8
9
  import { languageTagSchema } from './audioFormats.js';
9
10
  import { reasoningEffortSchema } from './catalogue.js';
10
11
  /**
@@ -15,12 +16,17 @@ import { reasoningEffortSchema } from './catalogue.js';
15
16
  * neither appears in a receipt, a log line or a telemetry event.
16
17
  */
17
18
  export const inferenceContentSourceSchema = z.discriminatedUnion('kind', [
18
- z.object({ kind: z.literal('url'), url: z.string().min(1).max(4096) }).strict(),
19
+ z
20
+ .object({
21
+ kind: z.literal('url'),
22
+ url: z.string().check(minUtf16Length(1)).check(maxUtf16Length(4096)),
23
+ })
24
+ .strict(),
19
25
  z
20
26
  .object({
21
27
  kind: z.literal('inline'),
22
- mediaType: z.string().min(1).max(255),
23
- data: z.string().min(1),
28
+ mediaType: z.string().check(minUtf16Length(1)).check(maxUtf16Length(255)),
29
+ data: z.string().check(minUtf16Length(1)),
24
30
  })
25
31
  .strict(),
26
32
  ]);
@@ -71,7 +77,7 @@ export const inferenceContentPartSchema = z.discriminatedUnion('type', [
71
77
  .object({
72
78
  type: z.literal('file'),
73
79
  source: inferenceContentSourceSchema,
74
- filename: z.string().max(255).optional(),
80
+ filename: z.string().check(maxUtf16Length(255)).optional(),
75
81
  })
76
82
  .strict(),
77
83
  /**
@@ -89,8 +95,8 @@ export const inferenceContentPartSchema = z.discriminatedUnion('type', [
89
95
  */
90
96
  export const inferenceToolCallSchema = z
91
97
  .object({
92
- id: z.string().min(1).max(128),
93
- name: z.string().min(1).max(128),
98
+ id: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
99
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
94
100
  arguments: z.string(),
95
101
  })
96
102
  .strict();
@@ -114,9 +120,9 @@ export const inferenceMessageSchema = z
114
120
  role: inferenceMessageRoleSchema,
115
121
  content: z.array(inferenceContentPartSchema),
116
122
  /** Participant name, where the dialect supports naming participants. */
117
- name: z.string().max(128).optional(),
123
+ name: z.string().check(maxUtf16Length(128)).optional(),
118
124
  /** The tool call this message answers. Required on, and only on, `tool`. */
119
- toolCallId: z.string().min(1).max(128).optional(),
125
+ toolCallId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)).optional(),
120
126
  /** Tool calls the assistant made. Only on `assistant`. */
121
127
  toolCalls: z.array(inferenceToolCallSchema).optional(),
122
128
  })
@@ -168,7 +174,10 @@ export const samplingParametersSchema = z
168
174
  presencePenalty: z.number().min(-2).max(2).optional(),
169
175
  /** A seed makes a request reproducible on providers that honour one. */
170
176
  seed: z.number().int().safe().optional(),
171
- stopSequences: z.array(z.string().min(1).max(256)).max(8).optional(),
177
+ stopSequences: z
178
+ .array(z.string().check(minUtf16Length(1)).check(maxUtf16Length(256)))
179
+ .max(8)
180
+ .optional(),
172
181
  })
173
182
  .strict();
174
183
  /**
@@ -179,8 +188,8 @@ export const samplingParametersSchema = z
179
188
  export const toolDefinitionSchema = z
180
189
  .object({
181
190
  type: z.literal('function'),
182
- name: z.string().min(1).max(128),
183
- description: z.string().max(2000).optional(),
191
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
192
+ description: z.string().check(maxUtf16Length(2000)).optional(),
184
193
  parameters: z.record(z.string(), z.unknown()),
185
194
  /** Ask the provider to enforce the schema, where it supports enforcement. */
186
195
  strict: z.boolean().optional(),
@@ -189,7 +198,12 @@ export const toolDefinitionSchema = z
189
198
  /** Whether, and which, tool the model must call. */
190
199
  export const toolChoiceSchema = z.union([
191
200
  z.enum(['auto', 'none', 'required']),
192
- z.object({ type: z.literal('function'), name: z.string().min(1).max(128) }).strict(),
201
+ z
202
+ .object({
203
+ type: z.literal('function'),
204
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
205
+ })
206
+ .strict(),
193
207
  ]);
194
208
  /** Structured-output request: free text, any JSON object, or a named schema. */
195
209
  export const responseFormatSchema = z.discriminatedUnion('type', [
@@ -198,7 +212,7 @@ export const responseFormatSchema = z.discriminatedUnion('type', [
198
212
  z
199
213
  .object({
200
214
  type: z.literal('json_schema'),
201
- name: z.string().min(1).max(128),
215
+ name: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
202
216
  schema: z.record(z.string(), z.unknown()),
203
217
  strict: z.boolean(),
204
218
  })
@@ -215,7 +229,7 @@ export const inferenceReasoningSchema = z.object({ effort: reasoningEffortSchema
215
229
  /** Parameters for text-to-speech, preserved in the signed request. */
216
230
  export const inferenceSpeechParametersSchema = z
217
231
  .object({
218
- voice: z.string().min(1).max(64),
232
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)),
219
233
  responseFormat: z.enum(['mp3', 'opus', 'aac', 'flac', 'wav', 'pcm']),
220
234
  speed: z.number().min(0.25).max(4).optional(),
221
235
  })
@@ -231,7 +245,7 @@ export const inferenceTranscriptionParametersSchema = z
231
245
  .object({
232
246
  language: languageTagSchema.optional(),
233
247
  /** Vocabulary or context, never an instruction (contract set 5.0.0). */
234
- prompt: z.string().max(4096).optional(),
248
+ prompt: z.string().check(maxUtf16Length(4096)).optional(),
235
249
  })
236
250
  .strict();
237
251
  /**
@@ -249,7 +263,7 @@ export const inferenceTranscriptionParametersSchema = z
249
263
  */
250
264
  export const inferenceAudioOutputParametersSchema = z
251
265
  .object({
252
- voice: z.string().min(1).max(64),
266
+ voice: z.string().check(minUtf16Length(1)).check(maxUtf16Length(64)),
253
267
  format: z.enum(['wav', 'mp3', 'flac', 'opus', 'pcm']),
254
268
  })
255
269
  .strict();
@@ -262,5 +276,5 @@ export const inferenceAudioOutputParametersSchema = z
262
276
  * Moved from the Oxy edge (`packages/api/src/schemas/inferenceEdge.schemas.ts`).
263
277
  */
264
278
  export const requestLabelsSchema = z
265
- .record(z.string(), z.string().max(256))
279
+ .record(z.string(), z.string().check(maxUtf16Length(256)))
266
280
  .refine((labels) => Object.keys(labels).length <= 16, 'at most 16 labels may be attached to one request');
@@ -6,6 +6,7 @@
6
6
  * itself stays in `@oxy.so/contracts`, because Oxy owns the price lists.
7
7
  */
8
8
  import { z } from 'zod';
9
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
9
10
  /** ISO 4217 alpha-3 currency code, e.g. `USD`. */
10
11
  export const currencyCodeSchema = z
11
12
  .string()
@@ -219,7 +220,7 @@ export const unitPriceSchema = z
219
220
  */
220
221
  export const priceSnapshotSchema = z
221
222
  .object({
222
- priceVersionId: z.string().min(1).max(128),
223
+ priceVersionId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
223
224
  currency: currencyCodeSchema,
224
225
  unitPrices: z.array(unitPriceSchema).min(1),
225
226
  })
@@ -7,6 +7,7 @@
7
7
  * Moved from `@oxy.so/contracts` 4.12.0 (`src/inference/routingPolicy.ts`) by Kaana ADR 0002.
8
8
  */
9
9
  import { z } from 'zod';
10
+ import { maxUtf16Length, minUtf16Length } from '../stringBounds.js';
10
11
  /**
11
12
  * The reference a request records: which policy, at which of the customer's own
12
13
  * revisions. Embedded in the request envelope and in the settled receipt, so a
@@ -14,7 +15,7 @@ import { z } from 'zod';
14
15
  */
15
16
  export const routingPolicyReferenceSchema = z
16
17
  .object({
17
- routingPolicyId: z.string().min(1).max(128),
18
+ routingPolicyId: z.string().check(minUtf16Length(1)).check(maxUtf16Length(128)),
18
19
  policyVersion: z.number().int().positive().safe(),
19
20
  })
20
21
  .strict();