@oxy.so/contracts 1.3.0 → 1.5.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 +675 -201
- package/NOTICE +7 -2
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/index.js +8 -4
- package/dist/cjs/inference/catalogue.js +23 -1
- package/dist/cjs/inference/request.js +13 -1
- package/dist/cjs/inference/version.js +1 -1
- package/dist/cjs/linkedAccounts.js +93 -0
- package/dist/cjs/notifications.js +81 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/index.js +4 -2
- package/dist/esm/inference/catalogue.js +22 -0
- package/dist/esm/inference/request.js +13 -1
- package/dist/esm/inference/version.js +1 -1
- package/dist/esm/linkedAccounts.js +90 -0
- package/dist/esm/notifications.js +78 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +6 -4
- package/dist/types/inference/catalogue.d.ts +51 -0
- package/dist/types/inference/modelDocumentation.d.ts +12 -0
- package/dist/types/inference/request.d.ts +35 -0
- package/dist/types/inference/version.d.ts +1 -1
- package/dist/types/linkedAccounts.d.ts +341 -0
- package/dist/types/notifications.d.ts +93 -0
- package/package.json +2 -2
package/dist/esm/index.js
CHANGED
|
@@ -138,7 +138,7 @@ export {
|
|
|
138
138
|
priceVersionStatusSchema, priceVersionSchema, priceSnapshotSchema, } from './inference/priceVersion.js';
|
|
139
139
|
export {
|
|
140
140
|
// The six distinct catalogue objects + the customer-safe projection.
|
|
141
|
-
inferenceModalitySchema, modelCapabilitiesSchema, modelLicenseSchema, modelProvenanceSchema, inferenceDataPolicySchema, availabilityScopeSchema, commercialPermissionSchema, modelDeprecationSchema, modelEvaluationResultSchema, modelSafetyMetadataSchema, modelPublisherSchema, catalogueModelSchema, modelRevisionSchema, inferenceProviderSchema, modelDeploymentSchema, routingProfileCandidateSchema, routingProfileSchema, cataloguePublisherSummarySchema, catalogueServingProviderSummarySchema, modelCatalogueEntrySchema, } from './inference/catalogue.js';
|
|
141
|
+
inferenceModalitySchema, reasoningEffortSchema, modelCapabilitiesSchema, modelLicenseSchema, modelProvenanceSchema, inferenceDataPolicySchema, availabilityScopeSchema, commercialPermissionSchema, modelDeprecationSchema, modelEvaluationResultSchema, modelSafetyMetadataSchema, modelPublisherSchema, catalogueModelSchema, modelRevisionSchema, inferenceProviderSchema, modelDeploymentSchema, routingProfileCandidateSchema, routingProfileSchema, cataloguePublisherSummarySchema, catalogueServingProviderSummarySchema, modelCatalogueEntrySchema, } from './inference/catalogue.js';
|
|
142
142
|
export {
|
|
143
143
|
// Routing policy: every control, plus the refinement that rejects a policy
|
|
144
144
|
// no route could ever satisfy.
|
|
@@ -155,7 +155,7 @@ export {
|
|
|
155
155
|
modelDistributionMethodSchema, modelSystemicRiskTierSchema, trainingComputeFlopsSchema, SYSTEMIC_RISK_COMPUTE_THRESHOLD_FLOPS, modelDownstreamDocumentationSchema, modelGpaiDocumentationSchema, modelLineDeclarationSchema, modelReleaseIngestionRequestSchema, modelReleaseIngestionResultSchema, modelDocumentationSchema, } from './inference/modelDocumentation.js';
|
|
156
156
|
export {
|
|
157
157
|
// The normalized Oxy→data-plane request envelope.
|
|
158
|
-
inferenceContentSourceSchema, inferenceContentPartSchema, inferenceToolCallSchema, inferenceMessageRoleSchema, inferenceMessageSchema, inferenceInputSchema, samplingParametersSchema, toolDefinitionSchema, toolChoiceSchema, responseFormatSchema, clientRequestMetadataSchema, inferenceRequestSchema, inferenceSpeechParametersSchema, } from './inference/request.js';
|
|
158
|
+
inferenceContentSourceSchema, inferenceContentPartSchema, inferenceToolCallSchema, inferenceMessageRoleSchema, inferenceMessageSchema, inferenceInputSchema, samplingParametersSchema, inferenceReasoningSchema, toolDefinitionSchema, toolChoiceSchema, responseFormatSchema, clientRequestMetadataSchema, inferenceRequestSchema, inferenceSpeechParametersSchema, } from './inference/request.js';
|
|
159
159
|
export {
|
|
160
160
|
// Normalized SSE events.
|
|
161
161
|
inferenceStreamStartEventSchema, inferenceStreamDeltaEventSchema, inferenceAudioMediaTypeSchema, MAX_INFERENCE_AUDIO_BYTES, inferenceStreamAudioEventSchema, inferenceStreamToolCallEventSchema, inferenceStreamUsageEventSchema, inferenceRouteSwitchDetailSchema, inferenceRouteSwitchReasonSchema, inferenceStreamRouteSwitchEventSchema, inferenceStreamErrorEventSchema, inferenceFinishReasonSchema, inferenceStreamDoneEventSchema, inferenceStreamEventSchema, } from './inference/streamEvents.js';
|
|
@@ -178,3 +178,5 @@ export { AUTONOMY_LEVELS, CAPABILITY_PACKAGES, autonomyLevelSchema, capabilityPa
|
|
|
178
178
|
export { emailContextAddressSchema, emailContextMailboxSchema, emailContextMessageSchema, emailAgentContextSchema, } from './emailAgentContext.js';
|
|
179
179
|
export { inboxComposeRequestSchema, inboxDailyBriefRequestSchema, inboxNaturalSearchRequestSchema, inboxMessageInferenceParamsSchema, inboxInferenceTextResponseSchema, inboxNaturalSearchResponseSchema, inboxSmartRepliesResponseSchema, inboxThreadSummaryResponseSchema, inboxInferenceStreamEventSchema, } from './inference/inbox.js';
|
|
180
180
|
export * from './externalIdentity.js';
|
|
181
|
+
export * from './linkedAccounts.js';
|
|
182
|
+
export * from './notifications.js';
|
|
@@ -40,6 +40,15 @@ export const inferenceModalitySchema = z.enum([
|
|
|
40
40
|
'video',
|
|
41
41
|
'embedding',
|
|
42
42
|
]);
|
|
43
|
+
/**
|
|
44
|
+
* How hard a reasoning model is asked to think before it answers.
|
|
45
|
+
*
|
|
46
|
+
* A closed, provider-neutral vocabulary: Kaana translates each value into the
|
|
47
|
+
* serving provider's own control. A model advertises the subset it accepts in
|
|
48
|
+
* `modelCapabilitiesSchema.reasoningEfforts`, and Oxy refuses a request for an
|
|
49
|
+
* effort the resolved model does not advertise rather than dropping it.
|
|
50
|
+
*/
|
|
51
|
+
export const reasoningEffortSchema = z.enum(['low', 'medium', 'high']);
|
|
43
52
|
/**
|
|
44
53
|
* What a model can do, in the terms a caller has to decide against before
|
|
45
54
|
* sending a request: can it call tools, does it accept images, will it honour a
|
|
@@ -54,6 +63,13 @@ export const modelCapabilitiesSchema = z
|
|
|
54
63
|
structuredOutput: z.boolean(),
|
|
55
64
|
jsonMode: z.boolean(),
|
|
56
65
|
reasoning: z.boolean(),
|
|
66
|
+
/**
|
|
67
|
+
* The reasoning efforts a request may name for this model, in the order
|
|
68
|
+
* low → high. Empty means the model takes no effort control at all (it may
|
|
69
|
+
* still reason: `reasoning` answers that). Added in contract set 3.1.0;
|
|
70
|
+
* absent on the wire from an older producer, it parses as `[]`.
|
|
71
|
+
*/
|
|
72
|
+
reasoningEfforts: z.array(reasoningEffortSchema).default([]),
|
|
57
73
|
streaming: z.boolean(),
|
|
58
74
|
promptCaching: z.boolean(),
|
|
59
75
|
maxContextTokens: z.number().int().positive().safe(),
|
|
@@ -469,6 +485,12 @@ export const modelCatalogueEntrySchema = z.object({
|
|
|
469
485
|
provenance: modelProvenanceSchema,
|
|
470
486
|
knowledgeCutoff: inferenceDateSchema.optional(),
|
|
471
487
|
releasedOn: inferenceDateSchema.optional(),
|
|
488
|
+
/**
|
|
489
|
+
* When the upstream provider first published this model, as that provider
|
|
490
|
+
* reports it. Present only when a provider reported it; never an Oxy or Kaana
|
|
491
|
+
* observation time. Lets a picker order models newest first.
|
|
492
|
+
*/
|
|
493
|
+
releasedAt: inferenceTimestampSchema.optional(),
|
|
472
494
|
regions: z.array(inferenceRegionSchema).default([]),
|
|
473
495
|
servingProviders: z.array(catalogueServingProviderSummarySchema).default([]),
|
|
474
496
|
dataPolicy: inferenceDataPolicySchema,
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { z } from "zod";
|
|
27
27
|
import { inferenceAttributionSchema } from "./attribution.js";
|
|
28
|
-
import { inferenceModalitySchema } from "./catalogue.js";
|
|
28
|
+
import { inferenceModalitySchema, reasoningEffortSchema } from "./catalogue.js";
|
|
29
29
|
import { idempotencyKeySchema, inferenceTimestampSchema } from "./identifiers.js";
|
|
30
30
|
import { authorizedRouteSchema, routingPolicyReferenceSchema, routingTargetSchema, } from "./routingPolicy.js";
|
|
31
31
|
/* -------------------------------------------------------------------------- */
|
|
@@ -260,6 +260,16 @@ export const responseFormatSchema = z.discriminatedUnion("type", [
|
|
|
260
260
|
})
|
|
261
261
|
.strict(),
|
|
262
262
|
]);
|
|
263
|
+
/**
|
|
264
|
+
* The caller's reasoning control. Strict, like every leaf: a provider-specific
|
|
265
|
+
* knob (`budget_tokens`, `summary`) is refused rather than silently dropped.
|
|
266
|
+
*
|
|
267
|
+
* Oxy forwards it only after checking the resolved model advertises the effort
|
|
268
|
+
* in its catalogue `reasoningEfforts`; Kaana translates it per provider.
|
|
269
|
+
*/
|
|
270
|
+
export const inferenceReasoningSchema = z
|
|
271
|
+
.object({ effort: reasoningEffortSchema })
|
|
272
|
+
.strict();
|
|
263
273
|
/* -------------------------------------------------------------------------- */
|
|
264
274
|
/* Client metadata */
|
|
265
275
|
/* -------------------------------------------------------------------------- */
|
|
@@ -336,6 +346,8 @@ export const inferenceRequestSchema = z
|
|
|
336
346
|
stream: z.boolean(),
|
|
337
347
|
maxOutputTokens: z.number().int().positive().safe().optional(),
|
|
338
348
|
sampling: samplingParametersSchema,
|
|
349
|
+
/** Absent means the route's own default reasoning behaviour. */
|
|
350
|
+
reasoning: inferenceReasoningSchema.optional(),
|
|
339
351
|
speech: inferenceSpeechParametersSchema.optional(),
|
|
340
352
|
tools: z.array(toolDefinitionSchema).default([]),
|
|
341
353
|
toolChoice: toolChoiceSchema.optional(),
|
|
@@ -99,4 +99,4 @@
|
|
|
99
99
|
* change to, say, the catalogue reject every in-flight inference request; the
|
|
100
100
|
* per-shape `schemaVersion` is what a message is validated against.
|
|
101
101
|
*/
|
|
102
|
-
export const INFERENCE_CONTRACT_VERSION = '3.
|
|
102
|
+
export const INFERENCE_CONTRACT_VERSION = '3.1.0';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract for Oxy linked accounts — external accounts (any Mastodon-API
|
|
3
|
+
* server, Bluesky) a LOCAL Oxy user has proven they own by completing an OAuth
|
|
4
|
+
* authorization there.
|
|
5
|
+
*
|
|
6
|
+
* Every response schema is `.strict()` and carries no field a third-party token
|
|
7
|
+
* could occupy: Oxy uses the OAuth flow only to learn which account authorized
|
|
8
|
+
* it, then discards the token. See `docs/identity/linked-accounts.md`.
|
|
9
|
+
*
|
|
10
|
+
* Platform-agnostic — zod only, no react/react-native/expo.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
export const LINKED_ACCOUNT_NETWORKS = ['activitypub', 'atproto'];
|
|
14
|
+
export const linkedAccountNetworkSchema = z.enum(LINKED_ACCOUNT_NETWORKS);
|
|
15
|
+
/**
|
|
16
|
+
* `POST /linked-accounts/:network/start`.
|
|
17
|
+
*
|
|
18
|
+
* - `instance` (activitypub): `mastodon.social`, `https://mastodon.social` or
|
|
19
|
+
* `@user@mastodon.social`.
|
|
20
|
+
* - `handle` (atproto): a handle (`alice.bsky.social`) or a DID.
|
|
21
|
+
* - `returnTo` + `clientId`: where the browser lands afterwards, with
|
|
22
|
+
* `?link_code=` or `?link_error=`. `returnTo` must exactly match a redirect
|
|
23
|
+
* URI registered on the TRUSTED (first-party) application `clientId` names.
|
|
24
|
+
*/
|
|
25
|
+
export const startLinkedAccountRequestSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
instance: z.string().trim().min(1).max(320).optional(),
|
|
28
|
+
handle: z.string().trim().min(1).max(320).optional(),
|
|
29
|
+
clientId: z.string().trim().min(1).max(256),
|
|
30
|
+
returnTo: z.string().trim().min(1).max(2048),
|
|
31
|
+
})
|
|
32
|
+
.strict();
|
|
33
|
+
export const startLinkedAccountResponseSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
authorizeUrl: z.string().url(),
|
|
36
|
+
expiresAt: z.string().datetime(),
|
|
37
|
+
})
|
|
38
|
+
.strict();
|
|
39
|
+
/**
|
|
40
|
+
* `POST /linked-accounts/complete`, with the session of the user who STARTED
|
|
41
|
+
* the flow: `code` is the one-time `link_code` the callback appended to
|
|
42
|
+
* `returnTo`. It expires five minutes after the callback. Presented by any
|
|
43
|
+
* other user it is refused (403) and burned.
|
|
44
|
+
*/
|
|
45
|
+
export const completeLinkedAccountRequestSchema = z
|
|
46
|
+
.object({ code: z.string().trim().min(1).max(256) })
|
|
47
|
+
.strict();
|
|
48
|
+
/** One live linked account, as its owner sees it. */
|
|
49
|
+
export const linkedAccountSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
id: z.string().min(1),
|
|
52
|
+
network: linkedAccountNetworkSchema,
|
|
53
|
+
/** `username@domain` for ActivityPub; the DID for atproto. */
|
|
54
|
+
accountKey: z.string().min(1),
|
|
55
|
+
/** ActivityPub actor id, or the DID for atproto. */
|
|
56
|
+
actorUri: z.string().min(1),
|
|
57
|
+
handle: z.string().min(1),
|
|
58
|
+
host: z.string().min(1),
|
|
59
|
+
proofMethod: z.literal('oauth'),
|
|
60
|
+
verifiedAt: z.string().datetime(),
|
|
61
|
+
createdAt: z.string().datetime(),
|
|
62
|
+
})
|
|
63
|
+
.strict();
|
|
64
|
+
export const completeLinkedAccountResponseSchema = z
|
|
65
|
+
.object({ linkedAccount: linkedAccountSchema })
|
|
66
|
+
.strict();
|
|
67
|
+
export const linkedAccountListResponseSchema = z
|
|
68
|
+
.object({ linkedAccounts: z.array(linkedAccountSchema) })
|
|
69
|
+
.strict();
|
|
70
|
+
/**
|
|
71
|
+
* `GET /linked-accounts/by-user/:userId` (service token with the privileged
|
|
72
|
+
* `linked-accounts:read`). Adds `federatedUserId`: the FEDERATED shadow user Oxy
|
|
73
|
+
* already holds for that external account, if any — the anchor for adopting
|
|
74
|
+
* content Oxy federated in before the account was linked.
|
|
75
|
+
*/
|
|
76
|
+
export const serviceLinkedAccountSchema = linkedAccountSchema
|
|
77
|
+
.extend({ federatedUserId: z.string().min(1).nullable() })
|
|
78
|
+
.strict();
|
|
79
|
+
export const serviceLinkedAccountListResponseSchema = z
|
|
80
|
+
.object({ userId: z.string().min(1), linkedAccounts: z.array(serviceLinkedAccountSchema) })
|
|
81
|
+
.strict();
|
|
82
|
+
/**
|
|
83
|
+
* Error codes the callback appends as `?link_error=<code>` to `returnTo`. An
|
|
84
|
+
* account already linked to someone else is reported by `/complete` (409).
|
|
85
|
+
*/
|
|
86
|
+
export const LINKED_ACCOUNT_CALLBACK_ERRORS = [
|
|
87
|
+
'access_denied',
|
|
88
|
+
'verification_failed',
|
|
89
|
+
'provider_unavailable',
|
|
90
|
+
];
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed set of Oxy in-app notification types — owned here so the API's
|
|
3
|
+
* CHECK constraint (`notifications.type`), its request validation and the SDK
|
|
4
|
+
* all read one tuple.
|
|
5
|
+
*
|
|
6
|
+
* `system` is a message from an Oxy service about the recipient's OWN account
|
|
7
|
+
* (Oxy Move's "your migration finished"): the actor is the recipient, and the
|
|
8
|
+
* entity is their profile or an `app` id. It is the only type an actor does not
|
|
9
|
+
* cause.
|
|
10
|
+
*
|
|
11
|
+
* Platform-agnostic — zod only, no react/react-native/expo.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
export const OXY_NOTIFICATION_TYPES = [
|
|
15
|
+
'like',
|
|
16
|
+
'reply',
|
|
17
|
+
'mention',
|
|
18
|
+
'follow',
|
|
19
|
+
'repost',
|
|
20
|
+
'quote',
|
|
21
|
+
'welcome',
|
|
22
|
+
'system',
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* What a notification's `entityId` names.
|
|
26
|
+
*
|
|
27
|
+
* `app` means `entityId` is an OPAQUE id in the notifying application's own
|
|
28
|
+
* namespace (Oxy Move's migration job id). Oxy never resolves it; it exists so
|
|
29
|
+
* a `system` notification about something that is not a post or a profile does
|
|
30
|
+
* not have to pretend to be one. Valid only with `type: 'system'`.
|
|
31
|
+
*/
|
|
32
|
+
export const OXY_NOTIFICATION_ENTITY_TYPES = ['post', 'reply', 'profile', 'app'];
|
|
33
|
+
/** Length caps on the text a `system` notification carries (enforced by CHECKs too). */
|
|
34
|
+
export const OXY_SYSTEM_NOTIFICATION_TITLE_MAX = 120;
|
|
35
|
+
export const OXY_SYSTEM_NOTIFICATION_MESSAGE_MAX = 500;
|
|
36
|
+
export const OXY_NOTIFICATION_URL_MAX = 2048;
|
|
37
|
+
/**
|
|
38
|
+
* `POST /notifications` (service token with `notifications:write`).
|
|
39
|
+
*
|
|
40
|
+
* Only a `system` notification carries text: `title` and `message` are REQUIRED
|
|
41
|
+
* for it and stored, and `url` is an optional deep link (https, or a custom
|
|
42
|
+
* scheme registered as a redirect URI on the calling application). For every
|
|
43
|
+
* other type the client renders from `type` + entity, and `title` / `message` /
|
|
44
|
+
* `data` are accepted but discarded, as they always were.
|
|
45
|
+
*
|
|
46
|
+
* `system` notifications share the duplicate guard (recipient, actor, type,
|
|
47
|
+
* entityId): use a caller-unique `entityId` (a job id) for each distinct event.
|
|
48
|
+
*/
|
|
49
|
+
export const createOxyNotificationRequestSchema = z
|
|
50
|
+
.object({
|
|
51
|
+
recipientId: z.string().min(1),
|
|
52
|
+
actorId: z.string().min(1),
|
|
53
|
+
type: z.enum(OXY_NOTIFICATION_TYPES),
|
|
54
|
+
entityId: z.string().min(1),
|
|
55
|
+
entityType: z.enum(OXY_NOTIFICATION_ENTITY_TYPES),
|
|
56
|
+
title: z.string().trim().min(1).max(OXY_SYSTEM_NOTIFICATION_TITLE_MAX).optional(),
|
|
57
|
+
message: z.string().trim().min(1).max(OXY_SYSTEM_NOTIFICATION_MESSAGE_MAX).optional(),
|
|
58
|
+
url: z.string().trim().min(1).max(OXY_NOTIFICATION_URL_MAX).optional(),
|
|
59
|
+
data: z.record(z.string(), z.unknown()).optional(),
|
|
60
|
+
})
|
|
61
|
+
.superRefine((value, context) => {
|
|
62
|
+
if (value.type === 'system') {
|
|
63
|
+
if (value.actorId !== value.recipientId)
|
|
64
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['actorId'], message: 'a system notification is from the recipient\'s own account' });
|
|
65
|
+
if (!value.title)
|
|
66
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['title'], message: 'title is required for a system notification' });
|
|
67
|
+
if (!value.message)
|
|
68
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['message'], message: 'message is required for a system notification' });
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
if (value.url !== undefined) {
|
|
72
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['url'], message: 'url is only stored for a system notification' });
|
|
73
|
+
}
|
|
74
|
+
if (value.entityType === 'app') {
|
|
75
|
+
context.addIssue({ code: z.ZodIssueCode.custom, path: ['entityType'], message: "entityType 'app' is only valid for a system notification" });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|