@oxy.so/contracts 4.12.0 → 4.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/accountGraph.js +15 -0
- package/dist/cjs/avatarCharacter.js +120 -0
- package/dist/cjs/index.js +22 -14
- package/dist/cjs/recommendations.js +3 -0
- package/dist/cjs/userResponse.js +7 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/accountGraph.js +15 -0
- package/dist/esm/avatarCharacter.js +115 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/recommendations.js +3 -0
- package/dist/esm/userResponse.js +7 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/accountGraph.d.ts +15 -4
- package/dist/types/agency.d.ts +44 -44
- package/dist/types/avatarCharacter.d.ts +57 -0
- package/dist/types/deviceDirectory.d.ts +66 -66
- package/dist/types/email/messages.d.ts +22 -22
- package/dist/types/externalIdentity.d.ts +11 -4
- package/dist/types/index.d.ts +2 -0
- package/dist/types/recommendations.d.ts +12 -0
- package/dist/types/userResponse.d.ts +100 -2
- package/package.json +1 -1
package/dist/esm/accountGraph.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* {@link ACCOUNT_CATEGORY_IDS} for the four rules that govern it.
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
import { avatarCharacterSchema } from './avatarCharacter.js';
|
|
10
11
|
import { usernameSchema, usernameSchemaForAccountKind } from './username.js';
|
|
11
12
|
/**
|
|
12
13
|
* The union is spelled out above and the array proves coverage BOTH ways
|
|
@@ -466,8 +467,22 @@ export const createAccountRequestSchema = z
|
|
|
466
467
|
* remedy must not either.
|
|
467
468
|
*/
|
|
468
469
|
isPrivateAccount: z.boolean().optional(),
|
|
470
|
+
/**
|
|
471
|
+
* The 3D avatar character of a `bot` — and ONLY of a bot (the refinement
|
|
472
|
+
* below). Optional on the wire: a bot created without one is given a look
|
|
473
|
+
* seeded from its handle (`avatarCharacterFor`), so every bot account has a
|
|
474
|
+
* character from birth and the owner customizes it afterwards.
|
|
475
|
+
*/
|
|
476
|
+
character: avatarCharacterSchema.optional(),
|
|
469
477
|
})
|
|
470
478
|
.superRefine((request, ctx) => {
|
|
479
|
+
if (request.character !== undefined && request.kind !== 'bot') {
|
|
480
|
+
ctx.addIssue({
|
|
481
|
+
code: z.ZodIssueCode.custom,
|
|
482
|
+
path: ['character'],
|
|
483
|
+
message: 'Only a bot account carries an avatar character',
|
|
484
|
+
});
|
|
485
|
+
}
|
|
471
486
|
// The ONE place `kind` and `username` arrive in the same object, so it is the
|
|
472
487
|
// only place a wire schema CAN apply the per-kind half of the policy: a bot's
|
|
473
488
|
// handle must end in `bot`. Not a second rule — it asks
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 3D avatar character a `bot` account carries.
|
|
3
|
+
*
|
|
4
|
+
* ONE definition for the wire shape, its validator and the generator that picks
|
|
5
|
+
* a look for a new bot, shared by the Oxy API (which stores and serves it) and
|
|
6
|
+
* every client. It mirrors Bloom's flat `AvatarCharacter`
|
|
7
|
+
* (`@oxy.so/bloom/agent-avatar`).
|
|
8
|
+
*
|
|
9
|
+
* ## The vocabulary is Bloom's and is NOT enforced here
|
|
10
|
+
*
|
|
11
|
+
* Bloom is a React Native package this one cannot depend on, so the ids a
|
|
12
|
+
* character is made of are restated below as a curated SUBSET, only to PICK a
|
|
13
|
+
* look for a new bot ({@link avatarCharacterFor}). A STORED character is never
|
|
14
|
+
* checked against them: validating against a stale copy of somebody else's
|
|
15
|
+
* catalogue is how a working look starts being refused. What the schema checks
|
|
16
|
+
* is the SHAPE of what a client writes: only the keys a character has, each an
|
|
17
|
+
* id-like string, a `#rrggbb` paint, a spacing in range. The client resolves
|
|
18
|
+
* the ids and falls back on a default look for one it cannot draw.
|
|
19
|
+
*/
|
|
20
|
+
import { z } from 'zod';
|
|
21
|
+
const ID = /^[a-z][a-z0-9_]{0,39}$/;
|
|
22
|
+
const HEX = /^#[0-9a-fA-F]{6}$/;
|
|
23
|
+
/** Bounds of {@link AvatarCharacter.eyeSpacing}. */
|
|
24
|
+
export const AVATAR_EYE_SPACING = { min: 0.5, max: 1.5 };
|
|
25
|
+
const idSchema = z.string().regex(ID);
|
|
26
|
+
/**
|
|
27
|
+
* A character a client sends. `.strict()` so a misspelled field is a refusal
|
|
28
|
+
* now rather than a look that never takes effect. A character with nothing in
|
|
29
|
+
* it draws nothing: it needs a preset, or a shape and a paint.
|
|
30
|
+
*/
|
|
31
|
+
export const avatarCharacterSchema = z
|
|
32
|
+
.object({
|
|
33
|
+
preset: idSchema.optional(),
|
|
34
|
+
shape: idSchema.optional(),
|
|
35
|
+
eyes: idSchema.optional(),
|
|
36
|
+
eyewear: idSchema.optional(),
|
|
37
|
+
accessory: idSchema.optional(),
|
|
38
|
+
color: idSchema.optional(),
|
|
39
|
+
bodyColor: z
|
|
40
|
+
.string()
|
|
41
|
+
.regex(HEX)
|
|
42
|
+
.transform((hex) => hex.toLowerCase())
|
|
43
|
+
.optional(),
|
|
44
|
+
eyeSpacing: z
|
|
45
|
+
.number()
|
|
46
|
+
.finite()
|
|
47
|
+
.min(AVATAR_EYE_SPACING.min)
|
|
48
|
+
.max(AVATAR_EYE_SPACING.max)
|
|
49
|
+
.optional(),
|
|
50
|
+
})
|
|
51
|
+
.strict()
|
|
52
|
+
.refine((c) => c.preset !== undefined ||
|
|
53
|
+
(c.shape !== undefined && (c.color !== undefined || c.bodyColor !== undefined)), { message: 'A character needs a preset, or a shape and a color' });
|
|
54
|
+
/** The validated character, or `null` for anything that is not one. */
|
|
55
|
+
export function parseAvatarCharacter(value) {
|
|
56
|
+
const parsed = avatarCharacterSchema.safeParse(value);
|
|
57
|
+
return parsed.success ? parsed.data : null;
|
|
58
|
+
}
|
|
59
|
+
/** The parts a new bot's look is picked from: the plain, friendly shapes, in the editor's order. */
|
|
60
|
+
export const AVATAR_PICKABLE_SHAPES = [
|
|
61
|
+
'rounded_triangle',
|
|
62
|
+
'capsule',
|
|
63
|
+
'rounded_head_two_ears',
|
|
64
|
+
'six_lobed_flower',
|
|
65
|
+
'heart',
|
|
66
|
+
'four_lobed_butterfly',
|
|
67
|
+
'circle_two_ears',
|
|
68
|
+
'twelve_scalloped_rosette',
|
|
69
|
+
'rounded_cube',
|
|
70
|
+
'rounded_diamond',
|
|
71
|
+
'slender',
|
|
72
|
+
'pocket',
|
|
73
|
+
'petal',
|
|
74
|
+
'star',
|
|
75
|
+
'cloud',
|
|
76
|
+
'shield',
|
|
77
|
+
'pebble',
|
|
78
|
+
'squircle',
|
|
79
|
+
];
|
|
80
|
+
/** Bloom's named paints. */
|
|
81
|
+
export const AVATAR_PICKABLE_COLORS = [
|
|
82
|
+
'pink',
|
|
83
|
+
'orchid',
|
|
84
|
+
'violet',
|
|
85
|
+
'blue',
|
|
86
|
+
'cyan',
|
|
87
|
+
'teal',
|
|
88
|
+
'lime',
|
|
89
|
+
'yellow',
|
|
90
|
+
'coral',
|
|
91
|
+
];
|
|
92
|
+
/** A small, stable hash: the same seed always picks the same look. */
|
|
93
|
+
function hash(seed) {
|
|
94
|
+
let h = 2166136261;
|
|
95
|
+
for (let i = 0; i < seed.length; i++) {
|
|
96
|
+
h ^= seed.charCodeAt(i);
|
|
97
|
+
h = Math.imul(h, 16777619);
|
|
98
|
+
}
|
|
99
|
+
return h >>> 0;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* A look for a new bot, picked from its seed (its handle): a shape and a paint,
|
|
103
|
+
* plain oval eyes, nothing on its head. Stable — the same seed is the same look
|
|
104
|
+
* — and the owner changes it afterwards.
|
|
105
|
+
*/
|
|
106
|
+
export function avatarCharacterFor(seed) {
|
|
107
|
+
const h = hash(seed);
|
|
108
|
+
return {
|
|
109
|
+
shape: AVATAR_PICKABLE_SHAPES[h % AVATAR_PICKABLE_SHAPES.length],
|
|
110
|
+
eyes: 'oval',
|
|
111
|
+
eyewear: 'none',
|
|
112
|
+
accessory: 'none',
|
|
113
|
+
color: AVATAR_PICKABLE_COLORS[Math.floor(h / AVATAR_PICKABLE_SHAPES.length) % AVATAR_PICKABLE_COLORS.length],
|
|
114
|
+
};
|
|
115
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* expo, no `require()` in the ESM build.
|
|
11
11
|
*/
|
|
12
12
|
export { ACCOUNT_KINDS, accountKindSchema, CHILD_ACCOUNT_KINDS, childAccountKindSchema, isAccountKind, isDelegatedActAsEligibleKind, isOperatorSwitchTargetKind, ACCOUNT_CATEGORY_IDS, ACCOUNT_CATEGORY_KINDS, accountCategoriesSchema, accountCategoryIdSchema, isSelectableAccountCategoryId, kindAcceptsAccountCategories, MAX_ACCOUNT_CATEGORIES, newlyAddedRetiredCategories, RETIRED_ACCOUNT_CATEGORY_IDS, SELECTABLE_ACCOUNT_CATEGORY_IDS, createAccountRequestSchema, } from './accountGraph.js';
|
|
13
|
+
export { AVATAR_EYE_SPACING, AVATAR_PICKABLE_COLORS, AVATAR_PICKABLE_SHAPES, avatarCharacterFor, avatarCharacterSchema, parseAvatarCharacter, } from './avatarCharacter.js';
|
|
13
14
|
export { ACCOUNT_ACTOR_NATURES, ACCOUNT_SUBJECT_CONTRACT_VERSION, FINANCIAL_EFFECT_DIRECTIONS, KIND_INDEPENDENT_ACCOUNT_DIMENSIONS, accountActorChainFromSession, accountActorChainSchema, accountActorNatureSchema, accountKindActorNature, accountKindActsAsItself, attributeFinancialEffect, financialEffectAttributionSchema, } from './accountSubject.js';
|
|
14
15
|
export { usernameSchema, usernameSchemaForAccountKind, isValidUsername, stripDisallowedUsernameCharacters, applyBotUsernameSuffix, USERNAME_MIN_LENGTH, USERNAME_MAX_LENGTH, USERNAME_INVALID_MESSAGE, BOT_USERNAME_INVALID_MESSAGE, RESERVED_USERNAME_MESSAGE, NUMERIC_USERNAME_MESSAGE, } from './username.js';
|
|
15
16
|
export {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* / expo, ESM-safe).
|
|
12
12
|
*/
|
|
13
13
|
import { z } from 'zod';
|
|
14
|
+
import { avatarCharacterSchema } from './avatarCharacter.js';
|
|
14
15
|
import { userNameSchema } from './userResponse.js';
|
|
15
16
|
/** User-type filters a caller may exclude from the recommendation surface. */
|
|
16
17
|
export const recommendationExcludeTypeSchema = z.enum(['federated', 'agent', 'automated']);
|
|
@@ -77,6 +78,8 @@ export const recommendationItemSchema = z
|
|
|
77
78
|
username: z.string().optional(),
|
|
78
79
|
name: userNameSchema,
|
|
79
80
|
avatar: z.string().nullable().optional(),
|
|
81
|
+
/** A bot's 3D avatar character; absent for every other kind. */
|
|
82
|
+
character: avatarCharacterSchema.optional(),
|
|
80
83
|
/** The account's accent colour, as on every profile; absent when unset. */
|
|
81
84
|
color: z.string().optional(),
|
|
82
85
|
description: z.string().nullable().optional(),
|
package/dist/esm/userResponse.js
CHANGED
|
@@ -46,6 +46,7 @@ export const USER_PROFILE_COLOR_PRESETS = [
|
|
|
46
46
|
import { z } from 'zod';
|
|
47
47
|
import { verifiedDomainSchema } from './identity.js';
|
|
48
48
|
import { accountCategoriesSchema, accountKindSchema } from './accountGraph.js';
|
|
49
|
+
import { avatarCharacterSchema } from './avatarCharacter.js';
|
|
49
50
|
export const userNameSchema = z
|
|
50
51
|
.object({
|
|
51
52
|
first: z.string().optional(),
|
|
@@ -222,6 +223,12 @@ export const userResponseSchema = z
|
|
|
222
223
|
* `user.accountCategories ?? []`.
|
|
223
224
|
*/
|
|
224
225
|
accountCategories: accountCategoriesSchema.optional(),
|
|
226
|
+
/**
|
|
227
|
+
* The 3D avatar character of a `kind: 'bot'` account — what Bloom's
|
|
228
|
+
* `Avatar` draws instead of a picture. Present ONLY on a bot's payload,
|
|
229
|
+
* never on a person's or an organization's, so those DTOs do not grow.
|
|
230
|
+
*/
|
|
231
|
+
character: avatarCharacterSchema.optional(),
|
|
225
232
|
/**
|
|
226
233
|
* The authenticated viewer's relationship to this profile. Present ONLY
|
|
227
234
|
* on single-profile fetches (`GET /profiles/username/:username`,
|