fauna-api 0.0.0-stage → 1.0.679

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 (171) hide show
  1. package/dist/brands.d.ts +2 -0
  2. package/dist/brands.js +2 -0
  3. package/dist/index.d.ts +64 -0
  4. package/dist/index.js +121 -0
  5. package/dist/src/ant/chat.d.ts +130 -0
  6. package/dist/src/ant/chat.js +467 -0
  7. package/dist/src/ant/format.d.ts +40 -0
  8. package/dist/src/ant/format.js +143 -0
  9. package/dist/src/ant/graph.d.ts +130 -0
  10. package/dist/src/ant/graph.js +449 -0
  11. package/dist/src/ant/index.d.ts +16 -0
  12. package/dist/src/ant/index.js +61 -0
  13. package/dist/src/ant/persona.d.ts +151 -0
  14. package/dist/src/ant/persona.js +136 -0
  15. package/dist/src/ant/timeline.d.ts +283 -0
  16. package/dist/src/ant/timeline.js +1025 -0
  17. package/dist/src/authentification.d.ts +45 -0
  18. package/dist/src/authentification.js +194 -0
  19. package/dist/src/billing.d.ts +135 -0
  20. package/dist/src/billing.js +128 -0
  21. package/dist/src/calendar.d.ts +83 -0
  22. package/dist/src/calendar.js +133 -0
  23. package/dist/src/chats.d.ts +113 -0
  24. package/dist/src/chats.js +100 -0
  25. package/dist/src/cicada/contacts.d.ts +31 -0
  26. package/dist/src/cicada/contacts.js +28 -0
  27. package/dist/src/cicada/conversations.d.ts +73 -0
  28. package/dist/src/cicada/conversations.js +236 -0
  29. package/dist/src/cicada/inboxes.d.ts +48 -0
  30. package/dist/src/cicada/inboxes.js +82 -0
  31. package/dist/src/cicada/index.d.ts +16 -0
  32. package/dist/src/cicada/index.js +61 -0
  33. package/dist/src/cicada/phone.d.ts +48 -0
  34. package/dist/src/cicada/phone.js +306 -0
  35. package/dist/src/drive.d.ts +80 -0
  36. package/dist/src/drive.js +472 -0
  37. package/dist/src/extensions/index.d.ts +4 -0
  38. package/dist/src/extensions/index.js +5 -0
  39. package/dist/src/extensions/web/index.d.ts +6 -0
  40. package/dist/src/extensions/web/index.js +7 -0
  41. package/dist/src/extensions/web/session.d.ts +108 -0
  42. package/dist/src/extensions/web/session.js +470 -0
  43. package/dist/src/extensions/web/tools.d.ts +13 -0
  44. package/dist/src/extensions/web/tools.js +72 -0
  45. package/dist/src/friends.d.ts +39 -0
  46. package/dist/src/friends.js +119 -0
  47. package/dist/src/groups.d.ts +82 -0
  48. package/dist/src/groups.js +269 -0
  49. package/dist/src/inbox.d.ts +11 -0
  50. package/dist/src/inbox.js +35 -0
  51. package/dist/src/integrations.d.ts +52 -0
  52. package/dist/src/integrations.js +205 -0
  53. package/dist/src/magpie/explorer.d.ts +14 -0
  54. package/dist/src/magpie/explorer.js +36 -0
  55. package/dist/src/magpie/index.d.ts +16 -0
  56. package/dist/src/magpie/index.js +61 -0
  57. package/dist/src/magpie/portfolio.d.ts +52 -0
  58. package/dist/src/magpie/portfolio.js +179 -0
  59. package/dist/src/magpie/quotes.d.ts +35 -0
  60. package/dist/src/magpie/quotes.js +47 -0
  61. package/dist/src/magpie/room.d.ts +61 -0
  62. package/dist/src/magpie/room.js +238 -0
  63. package/dist/src/maps.d.ts +159 -0
  64. package/dist/src/maps.js +171 -0
  65. package/dist/src/marmot/browser.d.ts +139 -0
  66. package/dist/src/marmot/browser.js +389 -0
  67. package/dist/src/marmot/index.d.ts +20 -0
  68. package/dist/src/marmot/index.js +65 -0
  69. package/dist/src/marmot/media.d.ts +56 -0
  70. package/dist/src/marmot/media.js +265 -0
  71. package/dist/src/marmot/research.d.ts +337 -0
  72. package/dist/src/marmot/research.js +1138 -0
  73. package/dist/src/marmot/scraper.d.ts +59 -0
  74. package/dist/src/marmot/scraper.js +94 -0
  75. package/dist/src/marmot/web.d.ts +402 -0
  76. package/dist/src/marmot/web.js +2586 -0
  77. package/dist/src/marmot/workspace.d.ts +81 -0
  78. package/dist/src/marmot/workspace.js +263 -0
  79. package/dist/src/parrot/agent.d.ts +53 -0
  80. package/dist/src/parrot/agent.js +93 -0
  81. package/dist/src/parrot/chat.d.ts +84 -0
  82. package/dist/src/parrot/chat.js +237 -0
  83. package/dist/src/parrot/format.d.ts +128 -0
  84. package/dist/src/parrot/format.js +639 -0
  85. package/dist/src/parrot/generative.d.ts +261 -0
  86. package/dist/src/parrot/generative.js +185 -0
  87. package/dist/src/parrot/index.d.ts +22 -0
  88. package/dist/src/parrot/index.js +67 -0
  89. package/dist/src/parrot/room.d.ts +225 -0
  90. package/dist/src/parrot/room.js +466 -0
  91. package/dist/src/parrot/routing.d.ts +90 -0
  92. package/dist/src/parrot/routing.js +78 -0
  93. package/dist/src/parrot/share.d.ts +126 -0
  94. package/dist/src/parrot/share.js +261 -0
  95. package/dist/src/parrot/socket.d.ts +41 -0
  96. package/dist/src/parrot/socket.js +478 -0
  97. package/dist/src/payments.d.ts +73 -0
  98. package/dist/src/payments.js +107 -0
  99. package/dist/src/private/cards.css +75 -0
  100. package/dist/src/rooms.d.ts +76 -0
  101. package/dist/src/rooms.js +168 -0
  102. package/dist/src/shared/schema.d.ts +24 -0
  103. package/dist/src/shared/schema.js +1 -0
  104. package/dist/src/shared/server.d.ts +65 -0
  105. package/dist/src/shared/server.js +302 -0
  106. package/dist/src/termite/environment.d.ts +110 -0
  107. package/dist/src/termite/environment.js +263 -0
  108. package/dist/src/termite/index.d.ts +14 -0
  109. package/dist/src/termite/index.js +59 -0
  110. package/dist/src/termite/os.d.ts +326 -0
  111. package/dist/src/termite/os.js +572 -0
  112. package/dist/src/termite/versioning.d.ts +94 -0
  113. package/dist/src/termite/versioning.js +217 -0
  114. package/dist/src/tickets.d.ts +43 -0
  115. package/dist/src/tickets.js +138 -0
  116. package/dist/src/travel.d.ts +85 -0
  117. package/dist/src/travel.js +44 -0
  118. package/dist/src/ui/authentification.d.ts +24 -0
  119. package/dist/src/ui/authentification.js +177 -0
  120. package/dist/src/ui/brands.css +11 -0
  121. package/dist/src/ui/brands.d.ts +7 -0
  122. package/dist/src/ui/brands.js +14 -0
  123. package/dist/src/ui/browser.d.ts +74 -0
  124. package/dist/src/ui/browser.js +470 -0
  125. package/dist/src/ui/chat.d.ts +183 -0
  126. package/dist/src/ui/chat.js +2379 -0
  127. package/dist/src/ui/chatPanel.d.ts +109 -0
  128. package/dist/src/ui/chatPanel.js +768 -0
  129. package/dist/src/ui/chatSequence.d.ts +36 -0
  130. package/dist/src/ui/chatSequence.js +42 -0
  131. package/dist/src/ui/crown.d.ts +19 -0
  132. package/dist/src/ui/crown.js +199 -0
  133. package/dist/src/ui/cursor.d.ts +73 -0
  134. package/dist/src/ui/cursor.js +175 -0
  135. package/dist/src/ui/device.d.ts +33 -0
  136. package/dist/src/ui/device.js +49 -0
  137. package/dist/src/ui/drive.d.ts +69 -0
  138. package/dist/src/ui/drive.js +1243 -0
  139. package/dist/src/ui/generative.d.ts +39 -0
  140. package/dist/src/ui/generative.js +313 -0
  141. package/dist/src/ui/hover.d.ts +6 -0
  142. package/dist/src/ui/hover.js +210 -0
  143. package/dist/src/ui/index.d.ts +42 -0
  144. package/dist/src/ui/index.js +87 -0
  145. package/dist/src/ui/integrations.d.ts +13 -0
  146. package/dist/src/ui/integrations.js +175 -0
  147. package/dist/src/ui/maps.d.ts +87 -0
  148. package/dist/src/ui/maps.js +547 -0
  149. package/dist/src/ui/roster.d.ts +32 -0
  150. package/dist/src/ui/roster.js +163 -0
  151. package/dist/src/ui/talk.d.ts +12 -0
  152. package/dist/src/ui/talk.js +560 -0
  153. package/dist/src/ui/tickets.d.ts +13 -0
  154. package/dist/src/ui/tickets.js +966 -0
  155. package/dist/src/ui/toast.d.ts +7 -0
  156. package/dist/src/ui/toast.js +258 -0
  157. package/dist/src/ui/tokenText.d.ts +18 -0
  158. package/dist/src/ui/tokenText.js +96 -0
  159. package/dist/src/ui/tokenized.d.ts +42 -0
  160. package/dist/src/ui/tokenized.js +622 -0
  161. package/dist/src/ui/ui.css +4763 -0
  162. package/dist/src/ui/view.d.ts +23 -0
  163. package/dist/src/ui/view.js +584 -0
  164. package/dist/src/view.d.ts +113 -0
  165. package/dist/src/view.js +386 -0
  166. package/dist/src/webhooks.d.ts +66 -0
  167. package/dist/src/webhooks.js +78 -0
  168. package/dist/ui.d.ts +1 -0
  169. package/dist/ui.js +1 -0
  170. package/package.json +87 -4
  171. package/README.md +0 -3
@@ -0,0 +1,639 @@
1
+ import { generateEmbedding, generateTextSync } from "./generative.js";
2
+ export class Format {
3
+ constructor(instruction, tool) {
4
+ Object.defineProperty(this, "instruction", {
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true,
8
+ value: void 0
9
+ });
10
+ Object.defineProperty(this, "tool", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: void 0
15
+ });
16
+ Object.defineProperty(this, "response", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: undefined
21
+ });
22
+ this.instruction = instruction;
23
+ this.tool = tool;
24
+ }
25
+ answer(response) {
26
+ this.response = response;
27
+ }
28
+ async llm(authorization, model, options = {}) {
29
+ const prompt = this.instruction + (this.tool.instruction ? '\n' + this.tool.instruction({}) : '');
30
+ const response = await generateTextSync(authorization, model, { content: (options.content ?? []) });
31
+ response.content.parts.push({
32
+ type: 'TEXT',
33
+ text: prompt
34
+ });
35
+ const invocations = response.content.parts.filter((part) => part.type === 'INVOCATION');
36
+ if (invocations.length > 0) {
37
+ this.answer(JSON.parse(await this.tool.evaluate(invocations[0].args)));
38
+ }
39
+ return response;
40
+ }
41
+ getResponse() {
42
+ return this.response;
43
+ }
44
+ static optional(format) {
45
+ const clone = format.clone();
46
+ const original = { ...clone.tool };
47
+ const { required, ...rest } = clone.tool.function.parameters;
48
+ clone.tool.function.parameters = rest;
49
+ clone.tool.instruction = (params) => {
50
+ return format.tool.instruction(params) + ' This is optional. If you would opt out of answering, you may skip the parameters.';
51
+ };
52
+ clone.tool.evaluate = async (params) => {
53
+ if (!params) {
54
+ return JSON.stringify(null);
55
+ }
56
+ try {
57
+ const response = await original.evaluate(params);
58
+ return response ?? JSON.stringify(null);
59
+ }
60
+ catch (err) {
61
+ return JSON.stringify(null);
62
+ }
63
+ };
64
+ return clone;
65
+ }
66
+ static calculateDistance(a, b) {
67
+ switch (true) {
68
+ case a instanceof NumericalFormat && b instanceof NumericalFormat: {
69
+ return NumericalFormat.distance(a, b);
70
+ }
71
+ case a instanceof VectorFormat && b instanceof VectorFormat: {
72
+ return VectorFormat.distance(a, b);
73
+ }
74
+ case a instanceof CategoricalFormat && b instanceof CategoricalFormat: {
75
+ return CategoricalFormat.distance(a, b);
76
+ }
77
+ case a instanceof SelectionFormat && b instanceof SelectionFormat: {
78
+ return SelectionFormat.distance(a, b);
79
+ }
80
+ case a instanceof UtteranceFormat && b instanceof UtteranceFormat: {
81
+ return UtteranceFormat.distance(a, b);
82
+ }
83
+ }
84
+ throw new Error(`Invalid format type: ${a.constructor.name} and ${b.constructor.name}`);
85
+ }
86
+ // Serialization
87
+ static fromJSON(json) {
88
+ var format = undefined;
89
+ switch (json.type) {
90
+ case 'numerical': {
91
+ format = new NumericalFormat(json.instruction, json.bounds);
92
+ break;
93
+ }
94
+ case 'vector': {
95
+ format = new VectorFormat(json.instruction, json.dimension, json.bounds);
96
+ break;
97
+ }
98
+ case 'categorical': {
99
+ format = new CategoricalFormat(json.instruction, json.categories);
100
+ break;
101
+ }
102
+ case 'selection': {
103
+ format = new SelectionFormat(json.instruction, json.options);
104
+ break;
105
+ }
106
+ case 'utterance': {
107
+ format = new UtteranceFormat(json.instruction, json.time);
108
+ break;
109
+ }
110
+ }
111
+ if (format) {
112
+ format.answer(json.answer);
113
+ return format;
114
+ }
115
+ throw new Error(`Invalid format type: ${json.type} for format:\n${JSON.stringify(json)}`);
116
+ }
117
+ }
118
+ export class NumericalFormat extends Format {
119
+ constructor(instruction, bounds) {
120
+ super(instruction, NumericalFormat.tool());
121
+ Object.defineProperty(this, "bounds", {
122
+ enumerable: true,
123
+ configurable: true,
124
+ writable: true,
125
+ value: void 0
126
+ });
127
+ this.bounds = bounds;
128
+ }
129
+ clone() {
130
+ return new NumericalFormat(this.instruction, this.bounds);
131
+ }
132
+ getResponse() {
133
+ if (this.bounds != undefined && this.response != undefined) {
134
+ var formattedResponse = this.response;
135
+ if (this.bounds[0] != undefined && formattedResponse < this.bounds[0]) {
136
+ formattedResponse = this.bounds[0];
137
+ }
138
+ if (this.bounds[1] != undefined && formattedResponse > this.bounds[1]) {
139
+ formattedResponse = this.bounds[1];
140
+ }
141
+ return formattedResponse;
142
+ }
143
+ const response = super.getResponse();
144
+ if (typeof response !== 'number') {
145
+ return undefined;
146
+ }
147
+ return super.getResponse();
148
+ }
149
+ toJSON() {
150
+ return {
151
+ type: 'numerical',
152
+ instruction: this.instruction,
153
+ bounds: this.bounds,
154
+ answer: this.getResponse()
155
+ };
156
+ }
157
+ /**
158
+ * Encode the scalar as a 2-dim unit vector `[x, 1] / sqrt(x²+1)`. Direct
159
+ * unit-norm on a 1-dim scalar would collapse to just the sign and discard
160
+ * magnitude; the 2-dim wrap preserves magnitude as the vector's angle so
161
+ * two identical scalars yield identical unit vectors and different scalars
162
+ * yield distinguishable directions.
163
+ */
164
+ toVector() {
165
+ const x = this.getResponse();
166
+ if (x === undefined)
167
+ return [];
168
+ const norm = Math.sqrt(x * x + 1);
169
+ return [x / norm, 1 / norm];
170
+ }
171
+ static compare(a, b) {
172
+ const EPSILON = 1e-8;
173
+ const denom = Math.max(Math.abs(a), Math.abs(b), EPSILON);
174
+ const relativeDiff = Math.abs(a - b) / denom;
175
+ return 1 / (1 + relativeDiff);
176
+ }
177
+ static distance(a, b) {
178
+ const numA = a.getResponse();
179
+ const numB = b.getResponse();
180
+ if (numA == undefined || numB == undefined) {
181
+ return 0;
182
+ }
183
+ return NumericalFormat.compare(numA, numB);
184
+ }
185
+ static tool(bounds) {
186
+ return {
187
+ function: {
188
+ name: "return_float",
189
+ description: "Return a number as a float.",
190
+ parameters: {
191
+ type: 'OBJECT',
192
+ properties: {
193
+ number: {
194
+ type: 'NUMBER',
195
+ description: "The numeric answer."
196
+ }
197
+ },
198
+ required: ["number"]
199
+ }
200
+ },
201
+ evaluate: async (params) => {
202
+ return JSON.stringify(params['number']);
203
+ },
204
+ instruction: (_params) => {
205
+ if (bounds != undefined) {
206
+ if (bounds[0] != undefined && bounds[1] != undefined) {
207
+ return `Use the tool "return_float" to return your answer as a number on the scale of ${bounds[0]} to ${bounds[1]}.`;
208
+ }
209
+ else if (bounds[0] != undefined) {
210
+ return `Use the tool "return_float" to return your answer as a number greater than ${bounds[0]}.`;
211
+ }
212
+ else {
213
+ return `Use the tool "return_float" to return your answer as a number less than ${bounds[1]}.`;
214
+ }
215
+ }
216
+ return `Use the tool "return_float" to return your answer as a number.`;
217
+ }
218
+ };
219
+ }
220
+ }
221
+ export class VectorFormat extends Format {
222
+ constructor(instruction, dimension, bounds) {
223
+ super(instruction, VectorFormat.tool(dimension, bounds));
224
+ Object.defineProperty(this, "dimension", {
225
+ enumerable: true,
226
+ configurable: true,
227
+ writable: true,
228
+ value: void 0
229
+ });
230
+ Object.defineProperty(this, "bounds", {
231
+ enumerable: true,
232
+ configurable: true,
233
+ writable: true,
234
+ value: void 0
235
+ });
236
+ this.dimension = dimension;
237
+ this.bounds = bounds;
238
+ }
239
+ clone() {
240
+ return new VectorFormat(this.instruction, this.dimension, this.bounds);
241
+ }
242
+ getResponse() {
243
+ if (this.bounds && this.response) {
244
+ var formattedResponse = [];
245
+ for (let i = 0; i < this.response.length; i++) {
246
+ var number = this.response[i];
247
+ if (i < this.bounds.length) {
248
+ const bounds = this.bounds[i];
249
+ if (bounds) {
250
+ if (bounds[0] != undefined && number < bounds[0]) {
251
+ number = bounds[0];
252
+ }
253
+ if (bounds[1] != undefined && number > bounds[1]) {
254
+ number = bounds[1];
255
+ }
256
+ }
257
+ }
258
+ formattedResponse.push(number);
259
+ }
260
+ return formattedResponse;
261
+ }
262
+ return super.getResponse();
263
+ }
264
+ toJSON() {
265
+ return {
266
+ type: 'vector',
267
+ instruction: this.instruction,
268
+ dimension: this.dimension,
269
+ bounds: this.bounds,
270
+ answer: this.getResponse()
271
+ };
272
+ }
273
+ toVector() {
274
+ const v = this.getResponse();
275
+ if (v === undefined || v.length === 0)
276
+ return [];
277
+ let normSquared = 0;
278
+ for (const x of v)
279
+ normSquared += x * x;
280
+ if (normSquared === 0)
281
+ return [];
282
+ const norm = Math.sqrt(normSquared);
283
+ return v.map((x) => x / norm);
284
+ }
285
+ static distance(a, b) {
286
+ const vectorA = a.getResponse();
287
+ const vectorB = b.getResponse();
288
+ if (vectorA == undefined || vectorB == undefined) {
289
+ return 0;
290
+ }
291
+ var aggregate = 0;
292
+ for (let i = 0; i < vectorA.length; i++) {
293
+ aggregate += NumericalFormat.compare(vectorA[i], vectorB[i]);
294
+ }
295
+ return aggregate / vectorA.length;
296
+ }
297
+ static tool(dimension, bounds) {
298
+ return {
299
+ function: {
300
+ name: "return_vector",
301
+ description: `Return a vector of ${dimension} numbers.`,
302
+ parameters: {
303
+ type: 'OBJECT',
304
+ properties: {
305
+ vector: {
306
+ type: 'ARRAY',
307
+ items: { type: 'NUMBER' },
308
+ minimum: dimension,
309
+ maximum: dimension,
310
+ description: `A vector of exactly ${dimension} numbers.`
311
+ }
312
+ },
313
+ required: ["vector"]
314
+ }
315
+ },
316
+ evaluate: async (params) => {
317
+ return JSON.stringify(params['vector']);
318
+ },
319
+ instruction: (_params) => {
320
+ if (bounds == undefined) {
321
+ return `Use the tool "return_vector" to return your answer as a numerical vector of dimension ${dimension}.`;
322
+ }
323
+ var lowerBound = '[';
324
+ var upperBound = '[';
325
+ for (let i = 0; i < dimension; i++) {
326
+ if (bounds[i] == undefined || (bounds[i][0] == undefined && bounds[i][1] == undefined)) {
327
+ lowerBound = lowerBound + '-infinity';
328
+ upperBound = upperBound + 'infinity';
329
+ }
330
+ else if (bounds[i][0] != undefined) {
331
+ lowerBound = lowerBound + `>${bounds[i][0].toString()}`;
332
+ upperBound = upperBound + `infinity`;
333
+ }
334
+ else {
335
+ lowerBound = lowerBound + `-infinity`;
336
+ upperBound = upperBound + `<${bounds[i][1].toString()}`;
337
+ }
338
+ if (i < dimension - 1) {
339
+ lowerBound = lowerBound + ', ';
340
+ upperBound = upperBound + ', ';
341
+ }
342
+ }
343
+ lowerBound = lowerBound + ']';
344
+ upperBound = upperBound + ']';
345
+ return `Use the tool "return_vector" to return your answer as a numerical vector of dimension ${dimension} of scale ${lowerBound} to ${upperBound}.`;
346
+ }
347
+ };
348
+ }
349
+ }
350
+ export class CategoricalFormat extends Format {
351
+ constructor(instruction, categories) {
352
+ super(instruction, CategoricalFormat.tool(categories));
353
+ Object.defineProperty(this, "categories", {
354
+ enumerable: true,
355
+ configurable: true,
356
+ writable: true,
357
+ value: void 0
358
+ });
359
+ this.categories = categories;
360
+ }
361
+ clone() {
362
+ return new CategoricalFormat(this.instruction, this.categories);
363
+ }
364
+ getCategories() {
365
+ return this.categories;
366
+ }
367
+ getResponse() {
368
+ if (this.response) {
369
+ for (const category of this.categories) {
370
+ if (category == this.response) {
371
+ return category;
372
+ }
373
+ }
374
+ console.error(`Response: ${this.response} not in categories: ${JSON.stringify(this.categories)}`);
375
+ return undefined;
376
+ }
377
+ return super.getResponse();
378
+ }
379
+ toJSON() {
380
+ return {
381
+ type: 'categorical',
382
+ instruction: this.instruction,
383
+ categories: this.categories,
384
+ answer: this.getResponse()
385
+ };
386
+ }
387
+ /** One-hot over the category set — already unit-length. */
388
+ toVector() {
389
+ const category = this.getResponse();
390
+ if (category === undefined)
391
+ return [];
392
+ const vector = new Array(this.categories.length).fill(0);
393
+ const index = this.categories.indexOf(category);
394
+ if (index < 0)
395
+ return [];
396
+ vector[index] = 1;
397
+ return vector;
398
+ }
399
+ static distance(a, b) {
400
+ const categoryA = a.getResponse();
401
+ const categoryB = b.getResponse();
402
+ if (categoryA == undefined || categoryB == undefined) {
403
+ return 0;
404
+ }
405
+ return categoryA === categoryB ? 1 : 0;
406
+ }
407
+ static tool(categories) {
408
+ return {
409
+ function: {
410
+ name: "return_category",
411
+ description: "Return one of the predefined categories.",
412
+ parameters: {
413
+ type: 'OBJECT',
414
+ properties: {
415
+ category: {
416
+ type: 'STRING',
417
+ enum: categories,
418
+ description: "The selected category."
419
+ }
420
+ },
421
+ required: ["category"]
422
+ }
423
+ },
424
+ evaluate: async (params) => {
425
+ return JSON.stringify(params['category']);
426
+ },
427
+ instruction: (_params) => {
428
+ return `Use the tool "return_category" to return your answer as one of the categories: ${JSON.stringify(categories)}.`;
429
+ }
430
+ };
431
+ }
432
+ }
433
+ export class SelectionFormat extends Format {
434
+ constructor(instruction, options) {
435
+ super(instruction, SelectionFormat.tool(options));
436
+ Object.defineProperty(this, "options", {
437
+ enumerable: true,
438
+ configurable: true,
439
+ writable: true,
440
+ value: void 0
441
+ });
442
+ this.options = options;
443
+ }
444
+ clone() {
445
+ return new SelectionFormat(this.instruction, this.options);
446
+ }
447
+ getOptions() {
448
+ return this.options;
449
+ }
450
+ getResponse() {
451
+ if (this.response) {
452
+ const selections = [];
453
+ for (const selection of this.response) {
454
+ if (this.options.includes(selection)) {
455
+ selections.push(selection);
456
+ }
457
+ }
458
+ return selections;
459
+ }
460
+ return [];
461
+ }
462
+ toJSON() {
463
+ return {
464
+ type: 'selection',
465
+ instruction: this.instruction,
466
+ options: this.options,
467
+ answer: this.getResponse()
468
+ };
469
+ }
470
+ /** Multi-hot scaled by 1/sqrt(count) so the vector is unit-length. */
471
+ toVector() {
472
+ const selections = this.getResponse();
473
+ if (!selections || selections.length === 0)
474
+ return [];
475
+ const vector = new Array(this.options.length).fill(0);
476
+ let count = 0;
477
+ for (const selection of selections) {
478
+ const index = this.options.indexOf(selection);
479
+ if (index >= 0) {
480
+ vector[index] = 1;
481
+ count++;
482
+ }
483
+ }
484
+ if (count === 0)
485
+ return [];
486
+ const scale = 1 / Math.sqrt(count);
487
+ for (let i = 0; i < vector.length; i++)
488
+ vector[i] *= scale;
489
+ return vector;
490
+ }
491
+ static distance(a, b) {
492
+ const selectionsA = a.getResponse();
493
+ const selectionsB = b.getResponse();
494
+ if (!selectionsA || !selectionsB || selectionsA.length === 0 && selectionsB.length === 0) {
495
+ return 1;
496
+ }
497
+ if (selectionsA.length === 0 || selectionsB.length === 0) {
498
+ return 0;
499
+ }
500
+ const setA = new Set(selectionsA);
501
+ const setB = new Set(selectionsB);
502
+ let intersectionSize = 0;
503
+ for (const value of setA) {
504
+ if (setB.has(value)) {
505
+ intersectionSize += 1;
506
+ }
507
+ }
508
+ const unionSize = new Set([...selectionsA, ...selectionsB]).size;
509
+ return intersectionSize / unionSize;
510
+ }
511
+ static tool(options) {
512
+ return {
513
+ function: {
514
+ name: "return_selections",
515
+ description: "Return one or more selected options.",
516
+ parameters: {
517
+ type: 'OBJECT',
518
+ properties: {
519
+ selections: {
520
+ type: 'ARRAY',
521
+ items: {
522
+ type: 'STRING',
523
+ enum: options
524
+ },
525
+ description: "The selected options."
526
+ }
527
+ },
528
+ required: ["selections"]
529
+ }
530
+ },
531
+ evaluate: async (params) => {
532
+ return JSON.stringify(params['selections']);
533
+ },
534
+ instruction: (_params) => {
535
+ return `Use the tool "return_selections" to return your answer as a categorical vector of one or more in ${JSON.stringify(options)}`;
536
+ }
537
+ };
538
+ }
539
+ }
540
+ export class UtteranceFormat extends Format {
541
+ constructor(instruction, time) {
542
+ super(instruction, UtteranceFormat.tool());
543
+ Object.defineProperty(this, "time", {
544
+ enumerable: true,
545
+ configurable: true,
546
+ writable: true,
547
+ value: void 0
548
+ });
549
+ Object.defineProperty(this, "embedding", {
550
+ enumerable: true,
551
+ configurable: true,
552
+ writable: true,
553
+ value: void 0
554
+ });
555
+ this.time = time;
556
+ }
557
+ clone() {
558
+ return new UtteranceFormat(this.instruction, this.time);
559
+ }
560
+ toJSON() {
561
+ return {
562
+ type: 'utterance',
563
+ instruction: this.instruction,
564
+ time: this.time,
565
+ answer: this.getResponse()
566
+ };
567
+ }
568
+ /**
569
+ * Returns the unit-normalized embedding. The caller MUST have populated
570
+ * `embedding` first (via `embed()` or the research agent's extraction
571
+ * pipeline) — otherwise we return an empty slice and the field is
572
+ * excluded from the rank check. Embedding-less utterances cannot
573
+ * participate in dedup.
574
+ */
575
+ toVector() {
576
+ if (this.embedding === undefined || this.embedding.length === 0)
577
+ return [];
578
+ let normSquared = 0;
579
+ for (const x of this.embedding)
580
+ normSquared += x * x;
581
+ if (normSquared === 0)
582
+ return [];
583
+ const norm = Math.sqrt(normSquared);
584
+ return this.embedding.map((x) => x / norm);
585
+ }
586
+ async embed(authorization, model) {
587
+ const utterance = this.getResponse();
588
+ if (utterance == undefined) {
589
+ throw new Error('Cannot embed an utterance format without an answer.');
590
+ }
591
+ const result = await generateEmbedding(authorization, model, utterance);
592
+ this.embedding = result.embedding;
593
+ }
594
+ static distance(a, b) {
595
+ function linearCosineSimilarity(a, b) {
596
+ let dotProduct = 0;
597
+ let normA = 0;
598
+ let normB = 0;
599
+ for (let i = 0; i < a.length; i++) {
600
+ dotProduct += a[i] * b[i];
601
+ normA += a[i] ** 2;
602
+ normB += b[i] ** 2;
603
+ }
604
+ normA = Math.sqrt(normA);
605
+ normB = Math.sqrt(normB);
606
+ const similarity = normA && normB ? dotProduct / (normA * normB) : 0;
607
+ const linearized = 1 - (Math.acos(Math.min(1, Math.max(-1, similarity))) / Math.PI);
608
+ return linearized;
609
+ }
610
+ if (a.embedding == undefined || b.embedding == undefined) {
611
+ throw new Error('Both utterance formats must be embedded before computing distance. Call embed() first.');
612
+ }
613
+ return linearCosineSimilarity(a.embedding, b.embedding);
614
+ }
615
+ static tool(time) {
616
+ return {
617
+ function: {
618
+ name: "return_text",
619
+ description: `Return a free-form text response ${time ? ` within ${time} seconds)` : ''}.`,
620
+ parameters: {
621
+ type: 'OBJECT',
622
+ properties: {
623
+ content: {
624
+ type: 'STRING',
625
+ description: "The text response."
626
+ }
627
+ },
628
+ required: ["content"]
629
+ }
630
+ },
631
+ evaluate: async (params) => {
632
+ return JSON.stringify(params['content']);
633
+ },
634
+ instruction: (_params) => {
635
+ return `Use the tool "return_text" to return your answer as a string of ${time ? `length within ${time} seconds` : 'any length'}.`;
636
+ }
637
+ };
638
+ }
639
+ }