@onesi/genesis-cli 0.1.13 → 0.2.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.
Files changed (63) hide show
  1. package/README.md +29 -2
  2. package/dist/beacons.js +68 -0
  3. package/dist/dials.js +7 -4
  4. package/dist/fleets.js +30 -0
  5. package/dist/flocks.d.ts +7 -1
  6. package/dist/flocks.js +257 -3
  7. package/dist/henry.d.ts +5 -1
  8. package/dist/henry.js +60 -1
  9. package/dist/hives-coverage.d.ts +12 -0
  10. package/dist/hives-coverage.js +116 -0
  11. package/dist/hives-node-transport.js +3 -0
  12. package/dist/hives-operations.d.ts +1 -0
  13. package/dist/hives-operations.js +2 -0
  14. package/dist/hives-platform.d.ts +13 -0
  15. package/dist/hives-platform.js +133 -0
  16. package/dist/iam-directory.d.ts +15 -0
  17. package/dist/iam-directory.js +71 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +255 -23
  20. package/dist/minds.d.ts +1 -1
  21. package/dist/minds.js +37 -2
  22. package/dist/onboard/art.d.ts +50 -0
  23. package/dist/onboard/art.js +139 -0
  24. package/dist/onboard/brand.d.ts +56 -0
  25. package/dist/onboard/brand.js +134 -0
  26. package/dist/onboard/caps.d.ts +90 -0
  27. package/dist/onboard/caps.js +232 -0
  28. package/dist/onboard/encode.d.ts +23 -0
  29. package/dist/onboard/encode.js +235 -0
  30. package/dist/onboard/eye.d.ts +103 -0
  31. package/dist/onboard/eye.js +147 -0
  32. package/dist/onboard/index.d.ts +61 -0
  33. package/dist/onboard/index.js +562 -0
  34. package/dist/onboard/mcp.d.ts +35 -0
  35. package/dist/onboard/mcp.js +118 -0
  36. package/dist/onboard/raster.d.ts +43 -0
  37. package/dist/onboard/raster.js +253 -0
  38. package/dist/onboard/sound.d.ts +2 -0
  39. package/dist/onboard/sound.js +54 -0
  40. package/dist/onboard/state.d.ts +24 -0
  41. package/dist/onboard/state.js +48 -0
  42. package/dist/onboard/term.d.ts +69 -0
  43. package/dist/onboard/term.js +292 -0
  44. package/dist/onboard/ui.d.ts +97 -0
  45. package/dist/onboard/ui.js +615 -0
  46. package/dist/orgs.d.ts +16 -0
  47. package/dist/orgs.js +89 -0
  48. package/dist/products.d.ts +6 -2
  49. package/dist/products.js +238 -12
  50. package/dist/relays-commands/certificates.d.ts +3 -0
  51. package/dist/relays-commands/certificates.js +20 -0
  52. package/dist/relays-commands/domains.d.ts +3 -0
  53. package/dist/relays-commands/domains.js +23 -0
  54. package/dist/relays-commands/index.d.ts +4 -0
  55. package/dist/relays-commands/index.js +10 -0
  56. package/dist/relays-commands/monitoring.d.ts +3 -0
  57. package/dist/relays-commands/monitoring.js +41 -0
  58. package/dist/relays-commands/telemetry.d.ts +3 -0
  59. package/dist/relays-commands/telemetry.js +28 -0
  60. package/dist/relays-commands/zones.d.ts +5 -0
  61. package/dist/relays-commands/zones.js +9 -0
  62. package/dist/runner.js +2 -0
  63. package/package.json +2 -2
@@ -0,0 +1,23 @@
1
+ import { Canvas, type Color } from './raster.js';
2
+ import type { ColorDepth } from './caps.js';
3
+ /** Nearest xterm-256 colour: the 6×6×6 cube or the grey ramp, whichever is closer. */
4
+ export declare function ansi256({ r, g, b }: Color): number;
5
+ export declare function ansi16(c: Color): number;
6
+ export declare function fg(c: Color, depth: ColorDepth): string;
7
+ export declare function bg(c: Color, depth: ColorDepth): string;
8
+ export interface CellOptions {
9
+ depth: ColorDepth;
10
+ background: Color | null;
11
+ unicode: boolean;
12
+ }
13
+ /** One string per text row. Runs of identical SGR are merged, so a frame stays small enough to draw at 60 fps. */
14
+ export declare function toCells(cv: Canvas, o: CellOptions): string[];
15
+ /** RGBA PNG of the canvas (straight alpha), for the Kitty and iTerm2 protocols. */
16
+ export declare function png(cv: Canvas): Buffer;
17
+ /** Kitty graphics: transmit and display at the cursor, `cols`×`rows` cells, chunked at 4096 bytes; the cursor does not move. */
18
+ export declare function kittyImage(data: Buffer, cols: number, rows: number, id?: number): string;
19
+ export declare const kittyDelete: (id?: number) => string;
20
+ /** iTerm2 inline image (also WezTerm), sized in cells. */
21
+ export declare function itermImage(data: Buffer, cols: number, rows: number): string;
22
+ /** Sixel with a small palette: the background and up to 63 blends of each ink present. Background pixels are left transparent. */
23
+ export declare function sixel(cv: Canvas, background: Color): string;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Canvas → terminal. Text cells carry two pixels each (▀ with the top as foreground, the bottom as background), so a
3
+ * row of text is two rows of pixels. Edges are anti-aliased against the terminal's real background when the probe
4
+ * learned it (OSC 11), so a blended edge is the exact colour a browser would paint; when the background is unknown we
5
+ * never paint a cell's background at all and pick ▀, ▄ or █ by coverage instead, so nothing ever shows a box.
6
+ * Images (Kitty, iTerm2, sixel) get the same canvas at device resolution.
7
+ */
8
+ import { deflateSync } from 'node:zlib';
9
+ import { mix } from './raster.js';
10
+ const ESC = '\x1b';
11
+ function cube(v) { return v < 48 ? 0 : v < 115 ? 1 : Math.floor((v - 35) / 40); }
12
+ /** Nearest xterm-256 colour: the 6×6×6 cube or the grey ramp, whichever is closer. */
13
+ export function ansi256({ r, g, b }) {
14
+ const cr = cube(r), cg = cube(g), cb = cube(b);
15
+ const lv = [0, 95, 135, 175, 215, 255];
16
+ const cd = (lv[cr] - r) ** 2 + (lv[cg] - g) ** 2 + (lv[cb] - b) ** 2;
17
+ const grey = Math.max(0, Math.min(23, Math.round(((r + g + b) / 3 - 8) / 10)));
18
+ const gv = 8 + grey * 10, gd = (gv - r) ** 2 + (gv - g) ** 2 + (gv - b) ** 2;
19
+ return gd < cd ? 232 + grey : 16 + 36 * cr + 6 * cg + cb;
20
+ }
21
+ const BASIC = [[30, { r: 0, g: 0, b: 0 }], [31, { r: 205, g: 49, b: 49 }], [32, { r: 13, g: 188, b: 121 }], [33, { r: 229, g: 229, b: 16 }],
22
+ [34, { r: 36, g: 114, b: 200 }], [35, { r: 188, g: 63, b: 188 }], [36, { r: 17, g: 168, b: 205 }], [37, { r: 229, g: 229, b: 229 }],
23
+ [90, { r: 102, g: 102, b: 102 }], [91, { r: 241, g: 76, b: 76 }], [92, { r: 35, g: 209, b: 139 }], [93, { r: 245, g: 245, b: 67 }],
24
+ [94, { r: 59, g: 142, b: 234 }], [95, { r: 214, g: 112, b: 214 }], [96, { r: 41, g: 184, b: 219 }], [97, { r: 255, g: 255, b: 255 }]];
25
+ export function ansi16(c) {
26
+ let best = 37, d = Infinity;
27
+ for (const [code, v] of BASIC) {
28
+ const e = (v.r - c.r) ** 2 + (v.g - c.g) ** 2 + (v.b - c.b) ** 2;
29
+ if (e < d) {
30
+ d = e;
31
+ best = code;
32
+ }
33
+ }
34
+ return best;
35
+ }
36
+ const isInk = (c) => c.r === 1 && c.g === 2 && c.b === 3; // art.DEFAULT_INK: the terminal's own foreground
37
+ export function fg(c, depth) {
38
+ if (isInk(c))
39
+ return `${ESC}[39m`;
40
+ if (depth === 24)
41
+ return `${ESC}[38;2;${c.r};${c.g};${c.b}m`;
42
+ if (depth === 8)
43
+ return `${ESC}[38;5;${ansi256(c)}m`;
44
+ if (depth === 4)
45
+ return `${ESC}[${ansi16(c)}m`;
46
+ return '';
47
+ }
48
+ export function bg(c, depth) {
49
+ if (depth === 24)
50
+ return `${ESC}[48;2;${c.r};${c.g};${c.b}m`;
51
+ if (depth === 8)
52
+ return `${ESC}[48;5;${ansi256(c)}m`;
53
+ if (depth === 4)
54
+ return `${ESC}[${ansi16(c) + 10}m`;
55
+ return '';
56
+ }
57
+ /** One string per text row. Runs of identical SGR are merged, so a frame stays small enough to draw at 60 fps. */
58
+ export function toCells(cv, o) {
59
+ const rows = [];
60
+ const THRESH = 0.5;
61
+ for (let y = 0; y < cv.height; y += 2) {
62
+ let line = '', last = '';
63
+ const put = (sgr, ch) => { if (sgr !== last) {
64
+ line += (last ? `${ESC}[0m` : '') + sgr;
65
+ last = sgr;
66
+ } line += ch; };
67
+ for (let x = 0; x < cv.width; x++) {
68
+ const t = cv.pixel(x, y), b = y + 1 < cv.height ? cv.pixel(x, y + 1) : { c: t.c, a: 0 };
69
+ if (t.a < 0.02 && b.a < 0.02) {
70
+ put('', ' ');
71
+ continue;
72
+ }
73
+ if (!o.unicode || o.depth === 0) {
74
+ // No colour (NO_COLOR) or no Unicode: the shape alone, in the terminal's own ink.
75
+ const on = Math.max(t.a, b.a) >= THRESH;
76
+ put('', on ? (o.unicode ? (t.a >= THRESH && b.a >= THRESH ? '█' : t.a >= THRESH ? '▀' : '▄') : '#') : ' ');
77
+ continue;
78
+ }
79
+ if (o.background) {
80
+ const bgc = o.background;
81
+ const top = mix(bgc, t.c, t.a), bot = mix(bgc, b.c, b.a);
82
+ if (b.a < 0.02)
83
+ put(fg(top, o.depth), '▀');
84
+ else if (t.a < 0.02)
85
+ put(fg(bot, o.depth), '▄');
86
+ else if (t.a > 0.98 && b.a > 0.98 && same(top, bot))
87
+ put(fg(top, o.depth), '█');
88
+ else
89
+ put(fg(top, o.depth) + bg(bot, o.depth), '▀');
90
+ }
91
+ else {
92
+ // Unknown background: never paint it. Partial edges keep their colour at full strength and are drawn only
93
+ // when at least half covered, so the silhouette stays honest.
94
+ const T = t.a >= THRESH, B = b.a >= THRESH;
95
+ if (T && B) {
96
+ if (same(t.c, b.c))
97
+ put(fg(t.c, o.depth), '█');
98
+ else if (isInk(b.c))
99
+ put(fg(b.c, o.depth) + bg(t.c, o.depth), '▄'); // the default ink can only be a foreground
100
+ else
101
+ put(fg(t.c, o.depth) + bg(b.c, o.depth), '▀');
102
+ }
103
+ else if (T)
104
+ put(fg(t.c, o.depth), '▀');
105
+ else if (B)
106
+ put(fg(b.c, o.depth), '▄');
107
+ else
108
+ put('', ' ');
109
+ }
110
+ }
111
+ rows.push((line + (last ? `${ESC}[0m` : '')).replace(/ +$/, ''));
112
+ }
113
+ return rows;
114
+ }
115
+ const same = (a, b) => a.r === b.r && a.g === b.g && a.b === b.b;
116
+ // ── images ─────────────────────────────────────────────────────────────────
117
+ const CRC = (() => { const t = new Uint32Array(256); for (let n = 0; n < 256; n++) {
118
+ let c = n;
119
+ for (let k = 0; k < 8; k++)
120
+ c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
121
+ t[n] = c >>> 0;
122
+ } return t; })();
123
+ function crc32(buf) { let c = 0xffffffff; for (const b of buf)
124
+ c = CRC[(c ^ b) & 255] ^ (c >>> 8); return (c ^ 0xffffffff) >>> 0; }
125
+ function chunk(type, data) {
126
+ const len = Buffer.alloc(4);
127
+ len.writeUInt32BE(data.length);
128
+ const td = Buffer.concat([Buffer.from(type, 'ascii'), data]);
129
+ const crc = Buffer.alloc(4);
130
+ crc.writeUInt32BE(crc32(td));
131
+ return Buffer.concat([len, td, crc]);
132
+ }
133
+ /** RGBA PNG of the canvas (straight alpha), for the Kitty and iTerm2 protocols. */
134
+ export function png(cv) {
135
+ const { width: W, height: H } = cv;
136
+ const raw = Buffer.alloc((W * 4 + 1) * H);
137
+ for (let y = 0; y < H; y++) {
138
+ raw[y * (W * 4 + 1)] = 0;
139
+ for (let x = 0; x < W; x++) {
140
+ const { c, a } = cv.pixel(x, y), o = y * (W * 4 + 1) + 1 + x * 4;
141
+ raw[o] = c.r;
142
+ raw[o + 1] = c.g;
143
+ raw[o + 2] = c.b;
144
+ raw[o + 3] = Math.round(a * 255);
145
+ }
146
+ }
147
+ const ihdr = Buffer.alloc(13);
148
+ ihdr.writeUInt32BE(W, 0);
149
+ ihdr.writeUInt32BE(H, 4);
150
+ ihdr[8] = 8;
151
+ ihdr[9] = 6;
152
+ return Buffer.concat([Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), chunk('IHDR', ihdr), chunk('IDAT', deflateSync(raw, { level: 6 })), chunk('IEND', Buffer.alloc(0))]);
153
+ }
154
+ /** Kitty graphics: transmit and display at the cursor, `cols`×`rows` cells, chunked at 4096 bytes; the cursor does not move. */
155
+ export function kittyImage(data, cols, rows, id = 4242) {
156
+ const b64 = data.toString('base64');
157
+ let out = '';
158
+ for (let i = 0; i < b64.length; i += 4096) {
159
+ const part = b64.slice(i, i + 4096), more = i + 4096 < b64.length ? 1 : 0;
160
+ out += i === 0 ? `${ESC}_Ga=T,f=100,q=2,i=${id},c=${cols},r=${rows},C=1,m=${more};${part}${ESC}\\` : `${ESC}_Gm=${more},q=2;${part}${ESC}\\`;
161
+ }
162
+ return out;
163
+ }
164
+ export const kittyDelete = (id = 4242) => `${ESC}_Ga=d,d=I,i=${id},q=2${ESC}\\`;
165
+ /** iTerm2 inline image (also WezTerm), sized in cells. */
166
+ export function itermImage(data, cols, rows) {
167
+ return `${ESC}]1337;File=inline=1;size=${data.length};width=${cols};height=${rows};preserveAspectRatio=1;doNotMoveCursor=1:${data.toString('base64')}\x07`;
168
+ }
169
+ /** Sixel with a small palette: the background and up to 63 blends of each ink present. Background pixels are left transparent. */
170
+ export function sixel(cv, background) {
171
+ const { width: W, height: H } = cv;
172
+ const palette = [];
173
+ const index = new Map();
174
+ const idx = new Int16Array(W * H).fill(-1);
175
+ for (let y = 0; y < H; y++)
176
+ for (let x = 0; x < W; x++) {
177
+ const { c, a } = cv.pixel(x, y);
178
+ if (a < 0.03)
179
+ continue;
180
+ const q = (v) => Math.round(v / 16) * 16;
181
+ const m = mix(background, c, Math.round(a * 8) / 8), key = `${q(m.r)},${q(m.g)},${q(m.b)}`;
182
+ let n = index.get(key);
183
+ if (n === undefined) {
184
+ if (palette.length >= 255)
185
+ n = nearest(palette, m);
186
+ else {
187
+ n = palette.length;
188
+ palette.push(m);
189
+ index.set(key, n);
190
+ }
191
+ }
192
+ idx[y * W + x] = n;
193
+ }
194
+ let out = `${ESC}P0;1;0q"1;1;${W};${H}`;
195
+ palette.forEach((c, n) => { out += `#${n};2;${Math.round(c.r / 2.55)};${Math.round(c.g / 2.55)};${Math.round(c.b / 2.55)}`; });
196
+ for (let band = 0; band < H; band += 6) {
197
+ const used = new Set();
198
+ for (let y = band; y < Math.min(H, band + 6); y++)
199
+ for (let x = 0; x < W; x++)
200
+ if (idx[y * W + x] >= 0)
201
+ used.add(idx[y * W + x]);
202
+ let first = true;
203
+ for (const n of used) {
204
+ out += (first ? '' : '$') + `#${n}`;
205
+ first = false;
206
+ let run = '', prev = '', count = 0;
207
+ const flush = () => { if (!count)
208
+ return; run += count > 3 ? `!${count}${prev}` : prev.repeat(count); };
209
+ for (let x = 0; x < W; x++) {
210
+ let bits = 0;
211
+ for (let k = 0; k < 6; k++) {
212
+ const y = band + k;
213
+ if (y < H && idx[y * W + x] === n)
214
+ bits |= 1 << k;
215
+ }
216
+ const ch = String.fromCharCode(63 + bits);
217
+ if (ch === prev)
218
+ count++;
219
+ else {
220
+ flush();
221
+ prev = ch;
222
+ count = 1;
223
+ }
224
+ }
225
+ flush();
226
+ out += run;
227
+ }
228
+ out += '-';
229
+ }
230
+ return out + `${ESC}\\`;
231
+ }
232
+ function nearest(p, c) { let best = 0, d = Infinity; p.forEach((v, n) => { const e = (v.r - c.r) ** 2 + (v.g - c.g) ** 2 + (v.b - c.b) ** 2; if (e < d) {
233
+ d = e;
234
+ best = n;
235
+ } }); return best; }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * One's eye, from agent-eye.js (the One site's vendor/brand/agent-eye, engine sha256 83cc379a…): its geometry, pose
3
+ * math, easing curves and moments, ported line for line so the terminal eye blinks, glances and smiles on exactly the
4
+ * site's timing. Only the drawing is ours (raster.ts); the numbers are agent-eye's. The bar's painted-on-a-ball bend is
5
+ * left out: at terminal sizes it is under a tenth of a pixel.
6
+ */
7
+ export declare const GEOMETRY: {
8
+ readonly radius: 100;
9
+ readonly barWidth: number;
10
+ readonly barHeight: number;
11
+ readonly cornerRadius: number;
12
+ };
13
+ export declare const MOTION: {
14
+ readonly maxTurn: 55;
15
+ readonly turnRadius: 70;
16
+ readonly foreshorten: 0.8;
17
+ readonly maxLift: 14;
18
+ readonly closedHeight: 7;
19
+ readonly lidSquash: 0.3;
20
+ readonly safeRadius: 89;
21
+ readonly smileLift: 2.5;
22
+ readonly smileSquint: 35;
23
+ readonly squeeze: 1;
24
+ };
25
+ export declare const MOUTH: {
26
+ readonly y: 66;
27
+ readonly halfWidth: 44;
28
+ readonly birthHalfWidth: 20;
29
+ readonly thickness: number;
30
+ readonly born: 3;
31
+ readonly follow: 0.6;
32
+ };
33
+ export interface Pose {
34
+ look: number;
35
+ lift: number;
36
+ open: number;
37
+ smile: number;
38
+ mouth: number;
39
+ }
40
+ export declare const REST: Pose;
41
+ /** The bar for a pose, in the -100…100 head box: centre (x, y), width w, height h. */
42
+ export declare function poseToBar(p: Partial<Pose>): {
43
+ x: number;
44
+ y: number;
45
+ w: number;
46
+ h: number;
47
+ };
48
+ export declare function poseToMouth(p: Partial<Pose>): {
49
+ x: number;
50
+ y: number;
51
+ w: number;
52
+ h: number;
53
+ o: number;
54
+ } | null;
55
+ export declare const EASE: {
56
+ readonly linear: readonly [0, 0, 1, 1];
57
+ readonly shut: readonly [0.6, 0, 0.9, 0.55];
58
+ readonly snap: readonly [0.1, 0.9, 0.25, 1];
59
+ readonly settle: readonly [0.3, 0, 0.3, 1];
60
+ readonly glide: readonly [0.45, 0, 0.25, 1];
61
+ readonly emerge: readonly [0.2, 0.6, 0.35, 1];
62
+ readonly charge: readonly [0.4, 0, 0.2, 1];
63
+ readonly exit: readonly [0.45, 0, 0.7, 0.9];
64
+ readonly enter: readonly [0.16, 1, 0.3, 1];
65
+ readonly leave: readonly [0.7, 0, 0.84, 0];
66
+ };
67
+ export type EaseName = keyof typeof EASE;
68
+ export declare function cubicBezier(x1: number, y1: number, x2: number, y2: number): (x: number) => number;
69
+ export declare const ease: (name: EaseName, x: number) => number;
70
+ /** A curve is [[seconds, value, ease into this key], …]. */
71
+ export type Curve = readonly (readonly [number, number, EaseName?])[];
72
+ export declare function sample(curve: Curve, t: number): number;
73
+ export declare const curveEnd: (c: Curve) => number;
74
+ /** agent-eye BLINK: 80 ms close, 50 ms shut, 170 ms open with a little overshoot. Multiplies openness. */
75
+ export declare const BLINK: Curve;
76
+ export declare const DOUBLE_BLINK: Curve;
77
+ /** agent-eye SMILE, 2.9 s. */
78
+ export declare const SMILE: {
79
+ smile: Curve;
80
+ mouth: Curve;
81
+ };
82
+ /** agent-eye RAINBOW_MOMENT's light, worn here in One's amber: it charges up the bar, holds, and leaves through the top. */
83
+ export declare const LIGHT: Curve;
84
+ /**
85
+ * The idle eye: agent-eye's alive mode in miniature. Blinks every 2.5–6 s (18 % of them double), glances now and then.
86
+ * Deterministic for a seed, so a recorded demo is the same every time.
87
+ */
88
+ export declare class IdleEye {
89
+ private nextBlink;
90
+ private blinkAt;
91
+ private curve;
92
+ private lookFrom;
93
+ private lookTo;
94
+ private lookAt;
95
+ private nextGlance;
96
+ private rnd;
97
+ constructor(seed?: number);
98
+ /** Look toward x (-1…1) now, e.g. at the text it is waiting beside, or straight at you when the window regains focus. */
99
+ look(t: number, x: number): void;
100
+ blink(t: number, double?: boolean): void;
101
+ private lookNow;
102
+ pose(t: number): Pose;
103
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * One's eye, from agent-eye.js (the One site's vendor/brand/agent-eye, engine sha256 83cc379a…): its geometry, pose
3
+ * math, easing curves and moments, ported line for line so the terminal eye blinks, glances and smiles on exactly the
4
+ * site's timing. Only the drawing is ours (raster.ts); the numbers are agent-eye's. The bar's painted-on-a-ball bend is
5
+ * left out: at terminal sizes it is under a tenth of a pixel.
6
+ */
7
+ export const GEOMETRY = { radius: 100, barWidth: 200 / 9, barHeight: 400 / 3, cornerRadius: 200 / 45 };
8
+ export const MOTION = { maxTurn: 55, turnRadius: 70, foreshorten: 0.8, maxLift: 14, closedHeight: 7, lidSquash: 0.3, safeRadius: 89, smileLift: 2.5, smileSquint: 35, squeeze: 1 };
9
+ export const MOUTH = { y: 66, halfWidth: 44, birthHalfWidth: 20, thickness: 200 / 9, born: 3, follow: 0.6 };
10
+ export const REST = { look: 0, lift: 0, open: 1, smile: 0, mouth: 0 };
11
+ const DEG = Math.PI / 180;
12
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
13
+ /** The bar for a pose, in the -100…100 head box: centre (x, y), width w, height h. */
14
+ export function poseToBar(p) {
15
+ const { look = 0, lift = 0, open = 1, smile = 0 } = p;
16
+ const turn = clamp(look, -1, 1) * MOTION.maxTurn * DEG;
17
+ const x = MOTION.turnRadius * Math.sin(turn);
18
+ const y = clamp(lift, -1, 1) * MOTION.maxLift - (MOTION.smileLift + MOTION.smileSquint / 2) * smile;
19
+ const shut = 1 - clamp(open, 0, 1);
20
+ const w = GEOMETRY.barWidth * (1 - MOTION.foreshorten * (1 - Math.cos(turn))) * (1 + MOTION.lidSquash * shut);
21
+ let h = Math.max(MOTION.closedHeight, MOTION.closedHeight + (GEOMETRY.barHeight - MOTION.closedHeight) * Math.max(0, open) - MOTION.smileSquint * smile);
22
+ h *= 1 - MOTION.squeeze * (1 - Math.sqrt(1 - (x / GEOMETRY.radius) ** 2));
23
+ // Keep the whole bar inside the safe radius (agent-eye fitHeight, without tilt).
24
+ const fits = (hh) => Math.hypot(Math.abs(x) + w / 2, Math.abs(y) + hh / 2) <= MOTION.safeRadius + GEOMETRY.cornerRadius;
25
+ if (!fits(h)) {
26
+ let lo = 0, hi = h;
27
+ for (let i = 0; i < 24; i++) {
28
+ const mid = (lo + hi) / 2;
29
+ if (fits(mid))
30
+ lo = mid;
31
+ else
32
+ hi = mid;
33
+ }
34
+ h = lo;
35
+ }
36
+ return { x, y, w, h };
37
+ }
38
+ export function poseToMouth(p) {
39
+ const m = Math.max(0, p.mouth ?? 0);
40
+ if (m === 0)
41
+ return null;
42
+ const turn = clamp(p.look ?? 0, -1, 1) * MOTION.maxTurn * DEG;
43
+ const half = (MOUTH.birthHalfWidth + (MOUTH.halfWidth - MOUTH.birthHalfWidth) * m) * (1 - 0.5 * (1 - Math.cos(turn)));
44
+ return { x: MOUTH.follow * MOTION.turnRadius * Math.sin(turn), y: MOUTH.y + MOUTH.born * (1 - Math.min(1, m)) + 0.5 * clamp(p.lift ?? 0, -1, 1) * MOTION.maxLift,
45
+ w: half * 2, h: MOUTH.thickness, o: clamp((m - 0.05) / 0.4, 0, 1) };
46
+ }
47
+ export const EASE = {
48
+ linear: [0, 0, 1, 1], shut: [0.6, 0, 0.9, 0.55], snap: [0.1, 0.9, 0.25, 1], settle: [0.3, 0, 0.3, 1],
49
+ glide: [0.45, 0, 0.25, 1], emerge: [0.2, 0.6, 0.35, 1], charge: [0.4, 0, 0.2, 1], exit: [0.45, 0, 0.7, 0.9],
50
+ // The site's motion curves (lib/motion CURVES): ease-out-expo for anything that arrives, ease-in-expo for leaving.
51
+ enter: [0.16, 1, 0.3, 1], leave: [0.7, 0, 0.84, 0],
52
+ };
53
+ export function cubicBezier(x1, y1, x2, y2) {
54
+ const cx = 3 * x1, bx = 3 * (x2 - x1) - cx, ax = 1 - cx - bx;
55
+ const cy = 3 * y1, by = 3 * (y2 - y1) - cy, ay = 1 - cy - by;
56
+ const sx = (t) => ((ax * t + bx) * t + cx) * t, sy = (t) => ((ay * t + by) * t + cy) * t;
57
+ const dx = (t) => (3 * ax * t + 2 * bx) * t + cx;
58
+ return (x) => {
59
+ if (x <= 0)
60
+ return 0;
61
+ if (x >= 1)
62
+ return 1;
63
+ let t = x;
64
+ for (let i = 0; i < 8; i++) {
65
+ const err = sx(t) - x;
66
+ if (Math.abs(err) < 1e-7)
67
+ return sy(t);
68
+ const d = dx(t);
69
+ if (Math.abs(d) < 1e-6)
70
+ break;
71
+ t -= err / d;
72
+ }
73
+ let lo = 0, hi = 1;
74
+ t = x;
75
+ while (hi - lo > 1e-7) {
76
+ if (sx(t) < x)
77
+ lo = t;
78
+ else
79
+ hi = t;
80
+ t = (lo + hi) / 2;
81
+ }
82
+ return sy(t);
83
+ };
84
+ }
85
+ const FN = Object.fromEntries(Object.entries(EASE).map(([k, v]) => [k, cubicBezier(v[0], v[1], v[2], v[3])]));
86
+ export const ease = (name, x) => FN[name](x);
87
+ export function sample(curve, t) {
88
+ if (t <= curve[0][0])
89
+ return curve[0][1];
90
+ for (let i = 1; i < curve.length; i++) {
91
+ const [t1, v1, e = 'linear'] = curve[i];
92
+ if (t < t1) {
93
+ const [t0, v0] = curve[i - 1];
94
+ return v0 + (v1 - v0) * FN[e]((t - t0) / (t1 - t0));
95
+ }
96
+ }
97
+ return curve[curve.length - 1][1];
98
+ }
99
+ export const curveEnd = (c) => c[c.length - 1][0];
100
+ /** agent-eye BLINK: 80 ms close, 50 ms shut, 170 ms open with a little overshoot. Multiplies openness. */
101
+ export const BLINK = [[0, 1], [0.08, 0, 'shut'], [0.13, 0], [0.3, 1.04, 'snap'], [0.42, 1, 'settle']];
102
+ export const DOUBLE_BLINK = [[0, 1], [0.07, 0, 'shut'], [0.11, 0], [0.23, 1, 'snap'], [0.3, 1], [0.37, 0, 'shut'], [0.41, 0], [0.57, 1.04, 'snap'], [0.69, 1, 'settle']];
103
+ /** agent-eye SMILE, 2.9 s. */
104
+ export const SMILE = {
105
+ smile: [[0, 0], [0.36, 1, 'glide'], [1.3, 1], [1.46, 1.12, 'snap'], [1.76, 1, 'settle'], [2.2, 1], [2.7, -0.06, 'glide'], [2.9, 0, 'settle']],
106
+ mouth: [[0, 0], [0.2, 0], [0.46, 0.8, 'emerge'], [0.62, 1.04, 'snap'], [0.82, 1, 'settle'], [1.3, 1], [1.46, 1.05, 'snap'], [1.76, 1, 'settle'], [2.05, 1], [2.26, 0.12, 'glide'], [2.32, 0]],
107
+ };
108
+ /** agent-eye RAINBOW_MOMENT's light, worn here in One's amber: it charges up the bar, holds, and leaves through the top. */
109
+ export const LIGHT = [[0, -1], [0.42, 0, 'charge'], [1.2, 0], [1.8, 1, 'exit']];
110
+ /**
111
+ * The idle eye: agent-eye's alive mode in miniature. Blinks every 2.5–6 s (18 % of them double), glances now and then.
112
+ * Deterministic for a seed, so a recorded demo is the same every time.
113
+ */
114
+ export class IdleEye {
115
+ nextBlink;
116
+ blinkAt = -10;
117
+ curve = BLINK;
118
+ lookFrom = 0;
119
+ lookTo = 0;
120
+ lookAt = -10;
121
+ nextGlance;
122
+ rnd;
123
+ constructor(seed = 7) {
124
+ let s = seed >>> 0 || 1;
125
+ this.rnd = () => { s ^= s << 13; s >>>= 0; s ^= s >>> 17; s ^= s << 5; s >>>= 0; return s / 4294967296; };
126
+ this.nextBlink = 0.9 + this.rnd() * 1.2;
127
+ this.nextGlance = 2.2 + this.rnd() * 2;
128
+ }
129
+ /** Look toward x (-1…1) now, e.g. at the text it is waiting beside, or straight at you when the window regains focus. */
130
+ look(t, x) { this.lookFrom = this.lookNow(t); this.lookTo = x; this.lookAt = t; }
131
+ blink(t, double = false) { this.blinkAt = t; this.curve = double ? DOUBLE_BLINK : BLINK; this.nextBlink = t + 2.5 + this.rnd() * 3.5; }
132
+ lookNow(t) { const k = Math.min(1, (t - this.lookAt) / 0.22); return this.lookFrom + (this.lookTo - this.lookFrom) * ease('snap', Math.max(0, k)); }
133
+ pose(t) {
134
+ if (t >= this.nextBlink)
135
+ this.blink(t, this.rnd() < 0.18);
136
+ if (t >= this.nextGlance) {
137
+ const target = Math.abs(this.lookTo) > 0.1 ? 0 : (this.rnd() < 0.5 ? -1 : 1) * (0.45 + this.rnd() * 0.4);
138
+ this.look(t, target);
139
+ this.nextGlance = t + (target === 0 ? 2.5 + this.rnd() * 3 : 0.8 + this.rnd() * 1.1);
140
+ if (this.rnd() < 0.3)
141
+ this.blink(t);
142
+ }
143
+ const since = t - this.blinkAt;
144
+ const open = since >= 0 && since < curveEnd(this.curve) ? sample(this.curve, since) : 1;
145
+ return { ...REST, look: this.lookNow(t), open };
146
+ }
147
+ }
@@ -0,0 +1,61 @@
1
+ import type { AuthConfig } from '../auth.js';
2
+ import type { CredentialStore } from '../store.js';
3
+ import { type Caps } from './caps.js';
4
+ import { type SetupState } from './state.js';
5
+ import { type McpEnv } from './mcp.js';
6
+ /** The two SDK calls setup makes, typed here so this module needs nothing from the SDK at load time. */
7
+ export interface SetupClient {
8
+ whoami(): Promise<{
9
+ org: string;
10
+ principal?: string | null;
11
+ kind: string;
12
+ }>;
13
+ keys: {
14
+ create(org: string, body: {
15
+ name: string;
16
+ custody: 'reveal' | 'blinds';
17
+ scopes?: string[];
18
+ }): Promise<{
19
+ id: string;
20
+ value?: unknown;
21
+ blinds_credential_ref?: unknown;
22
+ }>;
23
+ };
24
+ }
25
+ export interface SetupDeps {
26
+ version: string;
27
+ env: Record<string, string | undefined>;
28
+ fetch: typeof fetch;
29
+ auth: AuthConfig;
30
+ getStore: () => Promise<CredentialStore>;
31
+ client: () => Promise<SetupClient>;
32
+ openBrowser: (url: string) => void;
33
+ baseUrl: string;
34
+ stdout?: NodeJS.WriteStream;
35
+ stdin?: NodeJS.ReadStream;
36
+ log: (s: string) => void;
37
+ flags: {
38
+ json?: boolean;
39
+ animation?: boolean;
40
+ screenReader?: boolean;
41
+ sound?: boolean;
42
+ screencast?: boolean;
43
+ restart?: boolean;
44
+ step?: string;
45
+ probe?: boolean;
46
+ };
47
+ login: {
48
+ startLogin: typeof import('../auth.js').startLogin;
49
+ completeLogin: typeof import('../auth.js').completeLogin;
50
+ selectSavedContext: typeof import('../auth.js').selectSavedContext;
51
+ savedLoginProvider: typeof import('../auth.js').savedLoginProvider;
52
+ startDeviceLogin: typeof import('../device-login.js').startDeviceLogin;
53
+ completeDeviceLogin: typeof import('../device-login.js').completeDeviceLogin;
54
+ };
55
+ mcpEnv?: McpEnv;
56
+ /** Tests pin the parade's cast and the clock-free copy. */
57
+ seed?: number;
58
+ }
59
+ export declare function capsFor(d: SetupDeps): Promise<Caps>;
60
+ export declare function runSetup(d: SetupDeps): Promise<number>;
61
+ export type { SetupState };