@oxy.so/contracts 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/LICENSE +202 -0
- package/NOTICE +16 -0
- package/dist/cjs/.tsbuildinfo +1 -0
- package/dist/cjs/accountGraph.js +489 -0
- package/dist/cjs/agency.js +439 -0
- package/dist/cjs/browserHub.js +215 -0
- package/dist/cjs/civic.js +163 -0
- package/dist/cjs/commonsSignIn.js +59 -0
- package/dist/cjs/deviceBoot.js +50 -0
- package/dist/cjs/deviceDirectory.js +189 -0
- package/dist/cjs/devicePairing.js +138 -0
- package/dist/cjs/deviceSession.js +164 -0
- package/dist/cjs/emailAgentContext.js +32 -0
- package/dist/cjs/followGraph.js +28 -0
- package/dist/cjs/identity.js +258 -0
- package/dist/cjs/inboxPush.js +24 -0
- package/dist/cjs/index.js +618 -0
- package/dist/cjs/inference/accountBilling.js +334 -0
- package/dist/cjs/inference/aliaModelRelease.js +262 -0
- package/dist/cjs/inference/attribution.js +106 -0
- package/dist/cjs/inference/catalogue.js +487 -0
- package/dist/cjs/inference/entitlement.js +217 -0
- package/dist/cjs/inference/errors.js +309 -0
- package/dist/cjs/inference/identifiers.js +224 -0
- package/dist/cjs/inference/inbox.js +105 -0
- package/dist/cjs/inference/modelDocumentation.js +433 -0
- package/dist/cjs/inference/money.js +188 -0
- package/dist/cjs/inference/priceVersion.js +110 -0
- package/dist/cjs/inference/providerConnection.js +455 -0
- package/dist/cjs/inference/request.js +477 -0
- package/dist/cjs/inference/routingPolicy.js +318 -0
- package/dist/cjs/inference/streamEvents.js +258 -0
- package/dist/cjs/inference/usage.js +329 -0
- package/dist/cjs/inference/version.js +105 -0
- package/dist/cjs/keyRecovery.js +91 -0
- package/dist/cjs/keyRotation.js +75 -0
- package/dist/cjs/links.js +68 -0
- package/dist/cjs/moderationReputation.js +298 -0
- package/dist/cjs/oauth.js +66 -0
- package/dist/cjs/oxyRecordTypes.js +71 -0
- package/dist/cjs/protocol.js +53 -0
- package/dist/cjs/recommendations.js +168 -0
- package/dist/cjs/reputation.js +297 -0
- package/dist/cjs/sessionStatus.js +121 -0
- package/dist/cjs/transparency.js +89 -0
- package/dist/cjs/updates.js +252 -0
- package/dist/cjs/userInvalidation.js +89 -0
- package/dist/cjs/userResponse.js +245 -0
- package/dist/cjs/username.js +290 -0
- package/dist/cjs/webauthn.js +71 -0
- package/dist/esm/.tsbuildinfo +1 -0
- package/dist/esm/accountGraph.js +480 -0
- package/dist/esm/agency.js +436 -0
- package/dist/esm/browserHub.js +212 -0
- package/dist/esm/civic.js +160 -0
- package/dist/esm/commonsSignIn.js +56 -0
- package/dist/esm/deviceBoot.js +47 -0
- package/dist/esm/deviceDirectory.js +186 -0
- package/dist/esm/devicePairing.js +135 -0
- package/dist/esm/deviceSession.js +161 -0
- package/dist/esm/emailAgentContext.js +29 -0
- package/dist/esm/followGraph.js +27 -0
- package/dist/esm/identity.js +255 -0
- package/dist/esm/inboxPush.js +21 -0
- package/dist/esm/index.js +172 -0
- package/dist/esm/inference/accountBilling.js +331 -0
- package/dist/esm/inference/aliaModelRelease.js +259 -0
- package/dist/esm/inference/attribution.js +103 -0
- package/dist/esm/inference/catalogue.js +484 -0
- package/dist/esm/inference/entitlement.js +214 -0
- package/dist/esm/inference/errors.js +306 -0
- package/dist/esm/inference/identifiers.js +221 -0
- package/dist/esm/inference/inbox.js +102 -0
- package/dist/esm/inference/modelDocumentation.js +430 -0
- package/dist/esm/inference/money.js +185 -0
- package/dist/esm/inference/priceVersion.js +107 -0
- package/dist/esm/inference/providerConnection.js +452 -0
- package/dist/esm/inference/request.js +474 -0
- package/dist/esm/inference/routingPolicy.js +315 -0
- package/dist/esm/inference/streamEvents.js +255 -0
- package/dist/esm/inference/usage.js +326 -0
- package/dist/esm/inference/version.js +102 -0
- package/dist/esm/keyRecovery.js +88 -0
- package/dist/esm/keyRotation.js +72 -0
- package/dist/esm/links.js +65 -0
- package/dist/esm/moderationReputation.js +295 -0
- package/dist/esm/oauth.js +63 -0
- package/dist/esm/oxyRecordTypes.js +68 -0
- package/dist/esm/protocol.js +50 -0
- package/dist/esm/recommendations.js +165 -0
- package/dist/esm/reputation.js +293 -0
- package/dist/esm/sessionStatus.js +118 -0
- package/dist/esm/transparency.js +86 -0
- package/dist/esm/updates.js +249 -0
- package/dist/esm/userInvalidation.js +85 -0
- package/dist/esm/userResponse.js +240 -0
- package/dist/esm/username.js +283 -0
- package/dist/esm/webauthn.js +68 -0
- package/dist/types/.tsbuildinfo +1 -0
- package/dist/types/accountGraph.d.ts +378 -0
- package/dist/types/agency.d.ts +2162 -0
- package/dist/types/browserHub.d.ts +856 -0
- package/dist/types/civic.d.ts +338 -0
- package/dist/types/commonsSignIn.d.ts +58 -0
- package/dist/types/deviceBoot.d.ts +74 -0
- package/dist/types/deviceDirectory.d.ts +1317 -0
- package/dist/types/devicePairing.d.ts +130 -0
- package/dist/types/deviceSession.d.ts +411 -0
- package/dist/types/emailAgentContext.d.ts +248 -0
- package/dist/types/followGraph.d.ts +150 -0
- package/dist/types/identity.d.ts +402 -0
- package/dist/types/inboxPush.d.ts +30 -0
- package/dist/types/index.d.ts +100 -0
- package/dist/types/inference/accountBilling.d.ts +738 -0
- package/dist/types/inference/aliaModelRelease.d.ts +609 -0
- package/dist/types/inference/attribution.d.ts +176 -0
- package/dist/types/inference/catalogue.d.ts +1618 -0
- package/dist/types/inference/entitlement.d.ts +519 -0
- package/dist/types/inference/errors.d.ts +242 -0
- package/dist/types/inference/identifiers.d.ts +182 -0
- package/dist/types/inference/inbox.d.ts +374 -0
- package/dist/types/inference/modelDocumentation.d.ts +1603 -0
- package/dist/types/inference/money.d.ts +185 -0
- package/dist/types/inference/priceVersion.d.ts +182 -0
- package/dist/types/inference/providerConnection.d.ts +968 -0
- package/dist/types/inference/request.d.ts +2800 -0
- package/dist/types/inference/routingPolicy.d.ts +616 -0
- package/dist/types/inference/streamEvents.d.ts +950 -0
- package/dist/types/inference/usage.d.ts +1164 -0
- package/dist/types/inference/version.d.ts +102 -0
- package/dist/types/keyRecovery.d.ts +138 -0
- package/dist/types/keyRotation.d.ts +103 -0
- package/dist/types/links.d.ts +96 -0
- package/dist/types/moderationReputation.d.ts +487 -0
- package/dist/types/oauth.d.ts +86 -0
- package/dist/types/oxyRecordTypes.d.ts +62 -0
- package/dist/types/protocol.d.ts +86 -0
- package/dist/types/recommendations.d.ts +542 -0
- package/dist/types/reputation.d.ts +457 -0
- package/dist/types/sessionStatus.d.ts +231 -0
- package/dist/types/transparency.d.ts +392 -0
- package/dist/types/updates.d.ts +545 -0
- package/dist/types/userInvalidation.d.ts +94 -0
- package/dist/types/userResponse.d.ts +1706 -0
- package/dist/types/username.d.ts +265 -0
- package/dist/types/webauthn.d.ts +77 -0
- package/package.json +87 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identifiers, references and wire primitives shared by every Oxy↔data-plane
|
|
3
|
+
* inference contract.
|
|
4
|
+
*
|
|
5
|
+
* Two kinds of identifier live here, and the difference matters:
|
|
6
|
+
*
|
|
7
|
+
* - **Principal identifiers** owned by Oxy (`accountId`, `applicationId`,
|
|
8
|
+
* `credentialId`, the optional delegated `userId`). The data plane may store
|
|
9
|
+
* them as immutable references; it never owns, mints or mutates them.
|
|
10
|
+
* - **Catalogue references** (`<publisher>/<model>`, `<publisher>/<model>@<revision>`,
|
|
11
|
+
* a routing-profile slug). These are the strings a customer types, so their
|
|
12
|
+
* grammar is part of the public contract, not an implementation detail.
|
|
13
|
+
*
|
|
14
|
+
* Platform-agnostic — zod only. Every regex here is plain ASCII: this package
|
|
15
|
+
* is imported by React Native apps running on Hermes, which rejects Unicode
|
|
16
|
+
* property escapes (`\p{…}`) at runtime.
|
|
17
|
+
*
|
|
18
|
+
* Decided in: docs/adr/0007-canonical-request-attribution.md, docs/adr/0008-catalogue-concept-separation.md.
|
|
19
|
+
*/
|
|
20
|
+
import { z } from 'zod';
|
|
21
|
+
/* -------------------------------------------------------------------------- */
|
|
22
|
+
/* Principal identifiers */
|
|
23
|
+
/* -------------------------------------------------------------------------- */
|
|
24
|
+
/**
|
|
25
|
+
* An Oxy account id — the account that owns the workload and is financially
|
|
26
|
+
* responsible for it.
|
|
27
|
+
*
|
|
28
|
+
* Branded, and that brand is load-bearing rather than decorative: it is the
|
|
29
|
+
* type-level half of the rule that a delegated end-user identity can never
|
|
30
|
+
* become the billing identity (see {@link delegatedUserIdSchema} and
|
|
31
|
+
* `billingPrincipalSchema`). A plain `string` — and therefore any id read out
|
|
32
|
+
* of a header, a JWT claim or a request body — is not assignable to it; the
|
|
33
|
+
* only way to obtain one is to parse a value through this schema.
|
|
34
|
+
*/
|
|
35
|
+
export const oxyAccountIdSchema = z.string().min(1).max(64).brand();
|
|
36
|
+
/**
|
|
37
|
+
* A delegated end-user identity (Alia's `X-Oxy-User-Id`), branded with a
|
|
38
|
+
* DIFFERENT brand from {@link oxyAccountIdSchema} so the two cannot be
|
|
39
|
+
* substituted for one another in either direction, in any consumer, without a
|
|
40
|
+
* cast that review would catch.
|
|
41
|
+
*
|
|
42
|
+
* It exists for attribution and product-side personalisation only. It is never
|
|
43
|
+
* a billing principal, never an access-control principal, and its presence
|
|
44
|
+
* never changes which account is charged.
|
|
45
|
+
*/
|
|
46
|
+
export const delegatedUserIdSchema = z.string().min(1).max(64).brand();
|
|
47
|
+
/**
|
|
48
|
+
* An Oxy `Application._id`. Not branded: no invariant in this contract turns on
|
|
49
|
+
* confusing it with another id, and brand inflation costs every producer a
|
|
50
|
+
* parse call for no safety. The two ids above are branded because ADR 0007's
|
|
51
|
+
* rule is exactly that they must not be interchangeable.
|
|
52
|
+
*/
|
|
53
|
+
export const oxyApplicationIdSchema = z.string().min(1).max(64);
|
|
54
|
+
/** An Oxy `ApplicationCredential._id` — the credential used for this request. */
|
|
55
|
+
export const oxyCredentialIdSchema = z.string().min(1).max(64);
|
|
56
|
+
/**
|
|
57
|
+
* A request id allocated by the Oxy EDGE, at admission and BEFORE
|
|
58
|
+
* authentication, so that a request rejected for a bad credential is as
|
|
59
|
+
* traceable as one that was served (ADR 0007, and step 1 of ADR 0010's edge
|
|
60
|
+
* order). It is required on the inbound envelope, which is what makes the data
|
|
61
|
+
* plane a consumer of this id rather than its source: the data plane echoes it
|
|
62
|
+
* on every stream event, on the usage report, in its response header and on
|
|
63
|
+
* anything it can be asked about later. It never mints one for a request it
|
|
64
|
+
* received.
|
|
65
|
+
*
|
|
66
|
+
* The one case that is NOT an exception to that: an envelope the data plane
|
|
67
|
+
* cannot read or authenticate carries no id to echo, so its rejection is
|
|
68
|
+
* labelled with an id of the data plane's own — visibly local, and never
|
|
69
|
+
* correlated with an Oxy request, because there is no Oxy request it belongs to.
|
|
70
|
+
* Saying so is what stops "consumer, not source" from being read as forbidding
|
|
71
|
+
* the only id such a rejection could have.
|
|
72
|
+
*
|
|
73
|
+
* Correlates the Oxy edge, the data plane, the financial ledger and the
|
|
74
|
+
* customer-visible receipt, so it appears on every stream event and every
|
|
75
|
+
* ledger record.
|
|
76
|
+
*/
|
|
77
|
+
export const requestIdSchema = z.string().min(1).max(128);
|
|
78
|
+
/**
|
|
79
|
+
* A generation id generated by the data plane, present when a request produced
|
|
80
|
+
* a generation that can be looked up later (`GET /v1/generations/:id`).
|
|
81
|
+
*/
|
|
82
|
+
export const generationIdSchema = z.string().min(1).max(128);
|
|
83
|
+
/**
|
|
84
|
+
* A caller-supplied idempotency key. Every reserve/settle/refund call is keyed
|
|
85
|
+
* on one so a retry, a redelivered event or a duplicated webhook can never
|
|
86
|
+
* charge twice.
|
|
87
|
+
*/
|
|
88
|
+
export const idempotencyKeySchema = z.string().min(1).max(255);
|
|
89
|
+
/** Credential environments. A credential is issued into exactly one of them. */
|
|
90
|
+
export const inferenceEnvironmentSchema = z.enum(['development', 'staging', 'production']);
|
|
91
|
+
/* -------------------------------------------------------------------------- */
|
|
92
|
+
/* Wire primitives */
|
|
93
|
+
/* -------------------------------------------------------------------------- */
|
|
94
|
+
/**
|
|
95
|
+
* An instant, as an ISO 8601 string in UTC (`2026-08-15T09:41:00.000Z`).
|
|
96
|
+
*
|
|
97
|
+
* Validated rather than left free-form — unlike the session contracts, which
|
|
98
|
+
* carry legacy expiry strings no consumer interprets, every instant here is
|
|
99
|
+
* read: a reservation expires, a price version starts applying, a receipt is
|
|
100
|
+
* settled. One canonical spelling (UTC, `Z`) so two records that describe the
|
|
101
|
+
* same moment compare and sort as equal, which a mix of offsets would not.
|
|
102
|
+
*/
|
|
103
|
+
export const inferenceTimestampSchema = z.string().datetime();
|
|
104
|
+
/**
|
|
105
|
+
* A calendar DATE with no instant attached (`2026-05-01`) — a knowledge cutoff
|
|
106
|
+
* or a release date, which are published as days and become wrong when a
|
|
107
|
+
* timezone is invented for them.
|
|
108
|
+
*/
|
|
109
|
+
export const inferenceDateSchema = z
|
|
110
|
+
.string()
|
|
111
|
+
.regex(/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/, 'must be an ISO 8601 calendar date (YYYY-MM-DD)');
|
|
112
|
+
/** An absolute https URL, for model cards, licenses and provider documentation. */
|
|
113
|
+
export const inferenceHttpsUrlSchema = z
|
|
114
|
+
.string()
|
|
115
|
+
.max(2048)
|
|
116
|
+
.regex(/^https:\/\/[^\s]+$/, 'must be an absolute https URL');
|
|
117
|
+
/**
|
|
118
|
+
* A content digest, `sha256:<64 lowercase hex>`.
|
|
119
|
+
*
|
|
120
|
+
* ONE spelling, because a digest is compared for equality and nothing else: an
|
|
121
|
+
* uppercase or unprefixed variant of the same hash is a different string, so two
|
|
122
|
+
* records describing the same bytes would not match. Lowercase hex with the
|
|
123
|
+
* algorithm prefix is what the `inference_model_revisions` CHECK stores and what
|
|
124
|
+
* every artifact registry emits.
|
|
125
|
+
*/
|
|
126
|
+
export const sha256DigestSchema = z
|
|
127
|
+
.string()
|
|
128
|
+
.regex(/^sha256:[a-f0-9]{64}$/, 'digest must be sha256:<64 lowercase hex>');
|
|
129
|
+
/* -------------------------------------------------------------------------- */
|
|
130
|
+
/* Catalogue references */
|
|
131
|
+
/* -------------------------------------------------------------------------- */
|
|
132
|
+
/** One path segment of a canonical model id: a lowercase, URL-safe slug. */
|
|
133
|
+
const SLUG_PATTERN = '[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?';
|
|
134
|
+
/** A revision label. Case-preserving, because upstream revisions often are. */
|
|
135
|
+
const REVISION_PATTERN = '[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9])?';
|
|
136
|
+
/** A publisher slug, e.g. `openai`, `anthropic`, `meta`, `alia`. */
|
|
137
|
+
export const publisherSlugSchema = z
|
|
138
|
+
.string()
|
|
139
|
+
.max(64)
|
|
140
|
+
.regex(new RegExp(`^${SLUG_PATTERN}$`), 'publisher must be a lowercase URL-safe slug');
|
|
141
|
+
/** A model slug within its publisher's namespace, e.g. `gpt-5`, `llama-3.1-70b`. */
|
|
142
|
+
export const modelSlugSchema = z
|
|
143
|
+
.string()
|
|
144
|
+
.max(64)
|
|
145
|
+
.regex(new RegExp(`^${SLUG_PATTERN}$`), 'model must be a lowercase URL-safe slug');
|
|
146
|
+
/**
|
|
147
|
+
* A canonical model id, `<publisher>/<model>`. This names a MODEL — a
|
|
148
|
+
* long-lived product identity whose behaviour changes as revisions ship. It
|
|
149
|
+
* does not name a revision, a deployment or a provider.
|
|
150
|
+
*/
|
|
151
|
+
export const modelIdSchema = z
|
|
152
|
+
.string()
|
|
153
|
+
.max(129)
|
|
154
|
+
.regex(new RegExp(`^${SLUG_PATTERN}/${SLUG_PATTERN}$`), 'model id must be <publisher>/<model>');
|
|
155
|
+
/** An immutable revision label, unique within its model, e.g. `2026-05-01`. */
|
|
156
|
+
export const modelRevisionLabelSchema = z
|
|
157
|
+
.string()
|
|
158
|
+
.max(64)
|
|
159
|
+
.regex(new RegExp(`^${REVISION_PATTERN}$`), 'revision must be a URL-safe label');
|
|
160
|
+
/**
|
|
161
|
+
* A model reference as a customer writes it: `<publisher>/<model>` (the model's
|
|
162
|
+
* current revision, chosen by Oxy) or `<publisher>/<model>@<revision>` (an
|
|
163
|
+
* immutable revision the customer pinned).
|
|
164
|
+
*
|
|
165
|
+
* Both forms name a CONCRETE MODEL. Neither can name a routing profile — see
|
|
166
|
+
* {@link routingProfileSlugSchema} — which is what makes "a request for a
|
|
167
|
+
* concrete model is never silently replaced with a different model" a
|
|
168
|
+
* distinction the type system can carry rather than a convention.
|
|
169
|
+
*/
|
|
170
|
+
export const modelReferenceSchema = z
|
|
171
|
+
.string()
|
|
172
|
+
.max(194)
|
|
173
|
+
.regex(new RegExp(`^${SLUG_PATTERN}/${SLUG_PATTERN}(?:@${REVISION_PATTERN})?$`), 'model reference must be <publisher>/<model> or <publisher>/<model>@<revision>');
|
|
174
|
+
/**
|
|
175
|
+
* A routing-profile slug, e.g. `auto`, `fast`, `quality`.
|
|
176
|
+
*
|
|
177
|
+
* Deliberately refuses a `/`, so a profile can never be written in the shape of
|
|
178
|
+
* a model id and no caller can be confused about whether they asked for a
|
|
179
|
+
* concrete model or for Oxy to choose one. Modes like `auto`/`fast`/`quality`
|
|
180
|
+
* are profiles or product presets; they are never model objects.
|
|
181
|
+
*/
|
|
182
|
+
export const routingProfileSlugSchema = z
|
|
183
|
+
.string()
|
|
184
|
+
.max(64)
|
|
185
|
+
.regex(new RegExp(`^${SLUG_PATTERN}$`), 'routing profile must be a lowercase URL-safe slug');
|
|
186
|
+
/**
|
|
187
|
+
* The opaque PostgreSQL identity of one routing profile.
|
|
188
|
+
*
|
|
189
|
+
* No trim, case-folding or format heuristic: callers selecting by id must name
|
|
190
|
+
* the exact stored bytes. The database lookup is the authority for existence.
|
|
191
|
+
*/
|
|
192
|
+
export const routingProfileIdSchema = z.string().min(1).max(128);
|
|
193
|
+
/** An inference provider slug, e.g. `openai`, `bedrock`, `oxy-hosted`. */
|
|
194
|
+
export const inferenceProviderSlugSchema = z
|
|
195
|
+
.string()
|
|
196
|
+
.max(64)
|
|
197
|
+
.regex(new RegExp(`^${SLUG_PATTERN}$`), 'provider must be a lowercase URL-safe slug');
|
|
198
|
+
/**
|
|
199
|
+
* A deployment/endpoint id. Opaque to customers: which concrete endpoint served
|
|
200
|
+
* a request is the data plane's operational detail, and only the customer-safe
|
|
201
|
+
* subset of it is ever attributed back (see the catalogue's serving-boundary
|
|
202
|
+
* rules).
|
|
203
|
+
*/
|
|
204
|
+
export const deploymentIdSchema = z.string().min(1).max(128);
|
|
205
|
+
/**
|
|
206
|
+
* A region identifier, e.g. `us-west-2`, `eu-central-1`. Free-form rather than
|
|
207
|
+
* a closed enum because the set is provider-defined and grows without any
|
|
208
|
+
* contract change; residency policies match on exact strings.
|
|
209
|
+
*/
|
|
210
|
+
export const inferenceRegionSchema = z
|
|
211
|
+
.string()
|
|
212
|
+
.max(64)
|
|
213
|
+
.regex(new RegExp(`^${SLUG_PATTERN}$`), 'region must be a lowercase URL-safe slug');
|
|
214
|
+
/**
|
|
215
|
+
* The publisher namespace reserved for models Alia actually owns or derives.
|
|
216
|
+
*
|
|
217
|
+
* `alia/*` is never a re-badged third-party route and never a prompt preset —
|
|
218
|
+
* enforcing that is the job of `modelSchema`'s provenance refinement, which
|
|
219
|
+
* this constant exists to be checked against.
|
|
220
|
+
*/
|
|
221
|
+
export const RESERVED_ALIA_PUBLISHER = 'alia';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { inferenceErrorSchema } from './errors.js';
|
|
3
|
+
const inboxTextSchema = z.string().trim().min(1).max(20000);
|
|
4
|
+
const inboxMessageIdSchema = z.string().min(1).max(128);
|
|
5
|
+
const DAILY_BRIEF_MIN_WINDOW_MS = 23 * 60 * 60 * 1000;
|
|
6
|
+
const DAILY_BRIEF_MAX_WINDOW_MS = 25 * 60 * 60 * 1000;
|
|
7
|
+
const inboxUtcTimestampSchema = z
|
|
8
|
+
.string()
|
|
9
|
+
.datetime({ offset: false })
|
|
10
|
+
.refine((value) => value.endsWith('Z'), 'Timestamp must use the UTC Z suffix');
|
|
11
|
+
export const inboxComposeRequestSchema = z.discriminatedUnion('operation', [
|
|
12
|
+
z.object({
|
|
13
|
+
operation: z.literal('draft'),
|
|
14
|
+
prompt: inboxTextSchema,
|
|
15
|
+
tone: z.enum(['professional', 'casual', 'friendly', 'formal']),
|
|
16
|
+
stream: z.boolean().optional(),
|
|
17
|
+
}).strict(),
|
|
18
|
+
z.object({ operation: z.literal('polish'), text: inboxTextSchema }).strict(),
|
|
19
|
+
z.object({
|
|
20
|
+
operation: z.literal('change_tone'),
|
|
21
|
+
text: inboxTextSchema,
|
|
22
|
+
tone: z.enum(['professional', 'casual', 'friendly', 'formal']),
|
|
23
|
+
}).strict(),
|
|
24
|
+
z.object({
|
|
25
|
+
operation: z.literal('adjust_length'),
|
|
26
|
+
text: inboxTextSchema,
|
|
27
|
+
direction: z.enum(['shorter', 'longer']),
|
|
28
|
+
}).strict(),
|
|
29
|
+
z.object({ operation: z.literal('suggest_subject'), body: inboxTextSchema }).strict(),
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* The client owns the user's timezone and therefore supplies the UTC instants
|
|
33
|
+
* that bracket one local calendar day. The server treats this as [start, end):
|
|
34
|
+
* requiring a 23-25 hour window admits both DST transitions but refuses an
|
|
35
|
+
* arbitrary history export disguised as a brief.
|
|
36
|
+
*/
|
|
37
|
+
export const inboxDailyBriefRequestSchema = z.object({
|
|
38
|
+
startAt: inboxUtcTimestampSchema,
|
|
39
|
+
endAt: inboxUtcTimestampSchema,
|
|
40
|
+
stream: z.boolean().optional(),
|
|
41
|
+
}).strict().superRefine((value, context) => {
|
|
42
|
+
const durationMs = Date.parse(value.endAt) - Date.parse(value.startAt);
|
|
43
|
+
if (!Number.isFinite(durationMs) || durationMs <= 0) {
|
|
44
|
+
context.addIssue({
|
|
45
|
+
code: z.ZodIssueCode.custom,
|
|
46
|
+
path: ['endAt'],
|
|
47
|
+
message: 'endAt must be after startAt',
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (durationMs < DAILY_BRIEF_MIN_WINDOW_MS || durationMs > DAILY_BRIEF_MAX_WINDOW_MS) {
|
|
52
|
+
context.addIssue({
|
|
53
|
+
code: z.ZodIssueCode.custom,
|
|
54
|
+
path: ['endAt'],
|
|
55
|
+
message: 'Daily brief window must be between 23 and 25 hours',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
export const inboxNaturalSearchRequestSchema = z.object({ query: z.string().trim().min(1).max(512) }).strict();
|
|
60
|
+
export const inboxMessageInferenceParamsSchema = z.object({ messageId: inboxMessageIdSchema }).strict();
|
|
61
|
+
export const inboxInferenceTextResponseSchema = z.object({
|
|
62
|
+
schemaVersion: z.literal(1),
|
|
63
|
+
requestId: z.string().min(1).max(128),
|
|
64
|
+
generationId: z.string().min(1).max(128).optional(),
|
|
65
|
+
text: z.string().max(40000),
|
|
66
|
+
}).strict();
|
|
67
|
+
export const inboxNaturalSearchResponseSchema = z.object({
|
|
68
|
+
query: z.object({
|
|
69
|
+
q: z.string().max(512).optional(),
|
|
70
|
+
from: z.string().max(320).optional(),
|
|
71
|
+
to: z.string().max(320).optional(),
|
|
72
|
+
subject: z.string().max(512).optional(),
|
|
73
|
+
hasAttachment: z.boolean().optional(),
|
|
74
|
+
starred: z.boolean().optional(),
|
|
75
|
+
unread: z.boolean().optional(),
|
|
76
|
+
after: z.string().date().optional(),
|
|
77
|
+
before: z.string().date().optional(),
|
|
78
|
+
mailbox: z.enum(['inbox', 'sent', 'drafts', 'trash', 'spam', 'archive']).optional(),
|
|
79
|
+
}).strict(),
|
|
80
|
+
interpretation: z.string().max(1000),
|
|
81
|
+
}).strict();
|
|
82
|
+
export const inboxSmartRepliesResponseSchema = z.object({
|
|
83
|
+
replies: z.array(z.string().trim().min(1).max(500)).max(3),
|
|
84
|
+
}).strict();
|
|
85
|
+
export const inboxThreadSummaryResponseSchema = z.object({
|
|
86
|
+
summary: z.string().max(4000),
|
|
87
|
+
keyPoints: z.array(z.string().max(1000)).max(12),
|
|
88
|
+
actionItems: z.array(z.object({
|
|
89
|
+
text: z.string().max(1000),
|
|
90
|
+
owner: z.string().max(320).nullable(),
|
|
91
|
+
deadline: z.string().max(128).nullable(),
|
|
92
|
+
}).strict()).max(12),
|
|
93
|
+
}).strict();
|
|
94
|
+
export const inboxInferenceStreamEventSchema = z.discriminatedUnion('type', [
|
|
95
|
+
z.object({ type: z.literal('delta'), text: z.string().min(1).max(16384) }).strict(),
|
|
96
|
+
z.object({
|
|
97
|
+
type: z.literal('done'),
|
|
98
|
+
requestId: z.string().min(1).max(128),
|
|
99
|
+
generationId: z.string().min(1).max(128).optional(),
|
|
100
|
+
}).strict(),
|
|
101
|
+
z.object({ type: z.literal('error'), error: inferenceErrorSchema }).strict(),
|
|
102
|
+
]);
|