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,1138 @@
1
+ import { Fauna } from "../../index.js";
2
+ import { createScraper, getScraper, rebuildScraper, removeScraper, updateScraper } from "./scraper.js";
3
+ export class Schema {
4
+ static deserialize(data) {
5
+ switch (data?.type) {
6
+ case 'json':
7
+ return new SchemaJSON(deserializeLeaf(data.schema));
8
+ case 'csv':
9
+ return new SchemaCSV(Object.fromEntries(Object.entries(data.schema).map(([key, leaf]) => [key, deserializeLeaf(leaf)])), data.minimum, data.maximum, data.prompt ?? '');
10
+ default:
11
+ throw new Error(`Invalid schema type: ${data?.type}`);
12
+ }
13
+ }
14
+ }
15
+ export class SchemaJSON extends Schema {
16
+ constructor(schema) {
17
+ super();
18
+ Object.defineProperty(this, "type", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: 'json'
23
+ });
24
+ Object.defineProperty(this, "schema", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ this.schema = schema;
31
+ }
32
+ serialize() {
33
+ return { type: this.type, schema: serializeLeaf(this.schema) };
34
+ }
35
+ }
36
+ export class SchemaCSV extends Schema {
37
+ constructor(schema, minimum, maximum, prompt = '') {
38
+ super();
39
+ Object.defineProperty(this, "type", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: 'csv'
44
+ });
45
+ // Columns are keyed by name (mirrors how JSON object scopes are keyed),
46
+ // so the key becomes the output column header and extraction scope path.
47
+ Object.defineProperty(this, "schema", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: void 0
52
+ });
53
+ Object.defineProperty(this, "minimum", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: void 0
58
+ });
59
+ Object.defineProperty(this, "maximum", {
60
+ enumerable: true,
61
+ configurable: true,
62
+ writable: true,
63
+ value: void 0
64
+ });
65
+ Object.defineProperty(this, "prompt", {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: true,
69
+ value: void 0
70
+ });
71
+ for (const leaf of Object.values(schema)) {
72
+ if (!(leaf.value instanceof Fauna.Parrot.Format.Format)) {
73
+ throw new Error('Nested schema are not supported for CSV');
74
+ }
75
+ }
76
+ if (!Number.isInteger(minimum) || minimum < 0) {
77
+ throw new Error(`SchemaCSV minimum must be a non-negative integer, got ${minimum}`);
78
+ }
79
+ if (!Number.isInteger(maximum) || maximum < 0) {
80
+ throw new Error(`SchemaCSV maximum must be a non-negative integer, got ${maximum}`);
81
+ }
82
+ if (minimum > maximum) {
83
+ throw new Error(`SchemaCSV minimum (${minimum}) cannot exceed maximum (${maximum})`);
84
+ }
85
+ this.schema = schema;
86
+ this.minimum = minimum;
87
+ this.maximum = maximum;
88
+ this.prompt = prompt;
89
+ }
90
+ serialize() {
91
+ return {
92
+ type: this.type,
93
+ minimum: this.minimum,
94
+ maximum: this.maximum,
95
+ prompt: this.prompt,
96
+ schema: Object.fromEntries(Object.entries(this.schema).map(([key, leaf]) => [key, serializeLeaf(leaf)]))
97
+ };
98
+ }
99
+ }
100
+ function serializeLeaf(leaf) {
101
+ const { prompt, sources, optional, array, maxIterations, filters } = leaf;
102
+ const serialized = { prompt, sources, optional, array, maxIterations, filters };
103
+ if (leaf.value instanceof Fauna.Parrot.Format.Format) {
104
+ serialized.value = { question: leaf.value.toJSON() };
105
+ }
106
+ else if ('value' in leaf.value) {
107
+ serialized.value = { schema: serializeLeaf(leaf.value) };
108
+ }
109
+ else {
110
+ const children = {};
111
+ for (const key in leaf.value) {
112
+ children[key] = serializeLeaf(leaf.value[key]);
113
+ }
114
+ serialized.value = { children };
115
+ }
116
+ return serialized;
117
+ }
118
+ function deserializeLeaf(data) {
119
+ const { prompt, sources, optional, array, maxIterations, filters } = data;
120
+ if (array !== undefined) {
121
+ if (!Number.isInteger(array.minimum) || array.minimum < 0) {
122
+ throw new Error(`SchemaLeaf array.minimum must be a non-negative integer, got ${array.minimum}`);
123
+ }
124
+ if (!Number.isInteger(array.maximum) || array.maximum < 0) {
125
+ throw new Error(`SchemaLeaf array.maximum must be a non-negative integer, got ${array.maximum}`);
126
+ }
127
+ if (array.minimum > array.maximum) {
128
+ throw new Error(`SchemaLeaf array.minimum (${array.minimum}) cannot exceed array.maximum (${array.maximum})`);
129
+ }
130
+ }
131
+ return {
132
+ prompt,
133
+ sources,
134
+ optional,
135
+ array,
136
+ maxIterations,
137
+ filters,
138
+ value: 'question' in data.value
139
+ ? Fauna.Parrot.Format.Format.fromJSON(data.value.question)
140
+ : 'children' in data.value
141
+ ? Object.fromEntries(Object.entries(data.value.children).map(([k, v]) => [k, deserializeLeaf(v)]))
142
+ : deserializeLeaf(data.value.schema)
143
+ };
144
+ }
145
+ // ─── Schema Diff (migration) ───────────────────────────────────────────────────
146
+ function formatSignature(value) {
147
+ if (value instanceof Fauna.Parrot.Format.Format) {
148
+ const json = value.toJSON();
149
+ return `format:${json?.type ?? 'unknown'}`;
150
+ }
151
+ return 'composite';
152
+ }
153
+ function flattenLeafPaths(leaf, path, out) {
154
+ if (leaf.array) {
155
+ // A collection: descend into the inner leaf with an `[]` marker so
156
+ // every leaf below it is addressed per-element (e.g. "awards[].year").
157
+ flattenLeafPaths(leaf.value, `${path}[]`, out);
158
+ return;
159
+ }
160
+ const value = leaf.value;
161
+ if (value instanceof Fauna.Parrot.Format.Format) {
162
+ out.set(path || 'value', formatSignature(value));
163
+ return;
164
+ }
165
+ if ('value' in value) {
166
+ // Transparent single-child wrapper (e.g. an array's inner leaf).
167
+ flattenLeafPaths(value, path, out);
168
+ return;
169
+ }
170
+ for (const key of Object.keys(value)) {
171
+ const childPath = path ? `${path}.${key}` : key;
172
+ flattenLeafPaths(value[key], childPath, out);
173
+ }
174
+ }
175
+ /**
176
+ * Flatten a schema to a map of `leaf path → type signature`.
177
+ * - CSV: each column key is a path, signature is its Format type.
178
+ * - JSON: object keys descend with `.`, array leaves append `[]`, Format
179
+ * leaves terminate. e.g. "name", "address.city", "awards[].year".
180
+ */
181
+ export function schemaPaths(schema) {
182
+ const out = new Map();
183
+ if (schema instanceof SchemaCSV) {
184
+ for (const [key, leaf] of Object.entries(schema.schema)) {
185
+ out.set(key, formatSignature(leaf.value));
186
+ }
187
+ }
188
+ else {
189
+ flattenLeafPaths(schema.schema, '', out);
190
+ }
191
+ return out;
192
+ }
193
+ /**
194
+ * Diff two schema versions for a dataset migration. A path whose type
195
+ * signature changed shows up in BOTH lists (drop the old, add the new) — we
196
+ * deliberately do not attempt rename/retype detection. Renames and tree-shape
197
+ * changes therefore fall out naturally as drop + add.
198
+ */
199
+ export function diffSchema(baseline, target) {
200
+ const a = schemaPaths(baseline);
201
+ const b = schemaPaths(target);
202
+ const added = [];
203
+ const dropped = [];
204
+ for (const [path, signature] of b) {
205
+ if (a.get(path) !== signature)
206
+ added.push(path);
207
+ }
208
+ for (const [path, signature] of a) {
209
+ if (b.get(path) !== signature)
210
+ dropped.push(path);
211
+ }
212
+ return { added, dropped };
213
+ }
214
+ export const FeedRow = {
215
+ fromJSON(json) {
216
+ return { seq: Number(json.seq), value: json.value ?? null, sources: json.sources ?? null, created: new Date(json.created) };
217
+ },
218
+ };
219
+ export const PushResult = {
220
+ fromJSON(json) {
221
+ return {
222
+ added: Number(json.added ?? 0),
223
+ first: json.first ?? null,
224
+ last: json.last ?? null,
225
+ invalid: Array.isArray(json.invalid) ? json.invalid.map((i) => ({ index: Number(i.index), reason: String(i.reason) })) : [],
226
+ };
227
+ },
228
+ };
229
+ /** A push nothing in was let through: why, and each row's reason. */
230
+ export class PushRefused extends Error {
231
+ constructor(status, message, invalid) {
232
+ super(message);
233
+ Object.defineProperty(this, "status", {
234
+ enumerable: true,
235
+ configurable: true,
236
+ writable: true,
237
+ value: void 0
238
+ });
239
+ Object.defineProperty(this, "invalid", {
240
+ enumerable: true,
241
+ configurable: true,
242
+ writable: true,
243
+ value: void 0
244
+ });
245
+ this.status = status;
246
+ this.invalid = invalid;
247
+ }
248
+ }
249
+ const FEED_PAGE = 500;
250
+ function datasetDataURL(datasetId, options) {
251
+ const query = new URLSearchParams({ format: options?.format ?? 'json' });
252
+ if (options?.snapshot !== undefined)
253
+ query.set('snapshot', options.snapshot);
254
+ if (options?.sources)
255
+ query.set('sources', 'true');
256
+ return `${Fauna.getURL()}/marmot/dataset/${datasetId}/data?${query.toString()}`;
257
+ }
258
+ // ─── Snapshot ────────────────────────────────────────────────────────────────
259
+ export class Snapshot {
260
+ constructor(authorization, workspaceId, datasetId, id, createdAt, valid = true, group) {
261
+ Object.defineProperty(this, "id", {
262
+ enumerable: true,
263
+ configurable: true,
264
+ writable: true,
265
+ value: void 0
266
+ });
267
+ Object.defineProperty(this, "createdAt", {
268
+ enumerable: true,
269
+ configurable: true,
270
+ writable: true,
271
+ value: void 0
272
+ });
273
+ Object.defineProperty(this, "valid", {
274
+ enumerable: true,
275
+ configurable: true,
276
+ writable: true,
277
+ value: void 0
278
+ });
279
+ Object.defineProperty(this, "_authorization", {
280
+ enumerable: true,
281
+ configurable: true,
282
+ writable: true,
283
+ value: void 0
284
+ });
285
+ Object.defineProperty(this, "_workspaceId", {
286
+ enumerable: true,
287
+ configurable: true,
288
+ writable: true,
289
+ value: void 0
290
+ });
291
+ Object.defineProperty(this, "_datasetId", {
292
+ enumerable: true,
293
+ configurable: true,
294
+ writable: true,
295
+ value: void 0
296
+ });
297
+ Object.defineProperty(this, "_group", {
298
+ enumerable: true,
299
+ configurable: true,
300
+ writable: true,
301
+ value: void 0
302
+ });
303
+ Object.defineProperty(this, "_schema", {
304
+ enumerable: true,
305
+ configurable: true,
306
+ writable: true,
307
+ value: null
308
+ });
309
+ Object.defineProperty(this, "_data", {
310
+ enumerable: true,
311
+ configurable: true,
312
+ writable: true,
313
+ value: null
314
+ });
315
+ this._authorization = authorization;
316
+ this._workspaceId = workspaceId;
317
+ this._datasetId = datasetId;
318
+ this.id = id;
319
+ this.createdAt = createdAt;
320
+ this.valid = valid;
321
+ this._group = group;
322
+ }
323
+ async download(assets = false, revalidate = false) {
324
+ if (!assets && this._data && !revalidate)
325
+ return this._data;
326
+ const response = await fetch(`${Fauna.getURL()}/marmot/snapshot/${this._workspaceId}/${this._datasetId}/${this.id}/?assets=${assets}`, {
327
+ method: "GET",
328
+ headers: {
329
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
330
+ ...(this._group ? { Group: this._group.id } : {})
331
+ }
332
+ });
333
+ if (!response.ok) {
334
+ throw new Error(await response.text());
335
+ }
336
+ if (assets) {
337
+ return await response.blob();
338
+ }
339
+ const contentType = response.headers.get('content-type') ?? '';
340
+ const data = contentType.includes('application/json')
341
+ ? await response.json()
342
+ : await response.text();
343
+ this._data = data;
344
+ return data;
345
+ }
346
+ /** This snapshot's rows as CSV text or, by default, a JSON array. */
347
+ async data(options) {
348
+ const response = await fetch(datasetDataURL(this._datasetId, { ...options, snapshot: this.id }), {
349
+ method: "GET",
350
+ headers: {
351
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
352
+ }
353
+ });
354
+ if (!response.ok) {
355
+ throw new Error(await response.text());
356
+ }
357
+ return options?.format === 'csv' ? await response.text() : await response.json();
358
+ }
359
+ async downloadSchema(revalidate = false) {
360
+ if (this._schema && !revalidate)
361
+ return this._schema;
362
+ const response = await fetch(`${Fauna.getURL()}/marmot/snapshot/${this._workspaceId}/${this._datasetId}/${this.id}/schema`, {
363
+ method: "GET",
364
+ headers: {
365
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
366
+ ...(this._group ? { Group: this._group.id } : {})
367
+ }
368
+ });
369
+ if (!response.ok) {
370
+ throw new Error(await response.text());
371
+ }
372
+ this._schema = Schema.deserialize(await response.json());
373
+ return this._schema;
374
+ }
375
+ async downloadLog() {
376
+ const response = await fetch(`${Fauna.getURL()}/marmot/snapshot/${this._workspaceId}/${this._datasetId}/${this.id}/log`, {
377
+ method: "GET",
378
+ headers: {
379
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
380
+ ...(this._group ? { Group: this._group.id } : {})
381
+ }
382
+ });
383
+ if (!response.ok) {
384
+ throw new Error(await response.text());
385
+ }
386
+ return await response.blob();
387
+ }
388
+ async downloadEmbeddings() {
389
+ const response = await fetch(`${Fauna.getURL()}/marmot/snapshot/${this._workspaceId}/${this._datasetId}/${this.id}/embeddings`, {
390
+ method: "GET",
391
+ headers: {
392
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
393
+ ...(this._group ? { Group: this._group.id } : {})
394
+ }
395
+ });
396
+ if (!response.ok) {
397
+ throw new Error(await response.text());
398
+ }
399
+ return await response.blob();
400
+ }
401
+ async delete() {
402
+ const response = await fetch(`${Fauna.getURL()}/marmot/snapshot/${this._workspaceId}/${this._datasetId}/${this.id}`, {
403
+ method: "DELETE",
404
+ headers: {
405
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
406
+ ...(this._group ? { Group: this._group.id } : {})
407
+ }
408
+ });
409
+ if (!response.ok) {
410
+ throw new Error(await response.text());
411
+ }
412
+ }
413
+ }
414
+ export class Dataset {
415
+ constructor(authorization, workspaceId, id, name, schema, termination, contentTypes, proxy, documentModes, snapshots, group) {
416
+ Object.defineProperty(this, "id", {
417
+ enumerable: true,
418
+ configurable: true,
419
+ writable: true,
420
+ value: void 0
421
+ });
422
+ Object.defineProperty(this, "workspaceId", {
423
+ enumerable: true,
424
+ configurable: true,
425
+ writable: true,
426
+ value: void 0
427
+ });
428
+ Object.defineProperty(this, "name", {
429
+ enumerable: true,
430
+ configurable: true,
431
+ writable: true,
432
+ value: void 0
433
+ });
434
+ Object.defineProperty(this, "schema", {
435
+ enumerable: true,
436
+ configurable: true,
437
+ writable: true,
438
+ value: void 0
439
+ });
440
+ Object.defineProperty(this, "termination", {
441
+ enumerable: true,
442
+ configurable: true,
443
+ writable: true,
444
+ value: void 0
445
+ });
446
+ Object.defineProperty(this, "contentTypes", {
447
+ enumerable: true,
448
+ configurable: true,
449
+ writable: true,
450
+ value: void 0
451
+ });
452
+ Object.defineProperty(this, "proxy", {
453
+ enumerable: true,
454
+ configurable: true,
455
+ writable: true,
456
+ value: void 0
457
+ });
458
+ Object.defineProperty(this, "documentModes", {
459
+ enumerable: true,
460
+ configurable: true,
461
+ writable: true,
462
+ value: void 0
463
+ });
464
+ Object.defineProperty(this, "snapshots", {
465
+ enumerable: true,
466
+ configurable: true,
467
+ writable: true,
468
+ value: void 0
469
+ });
470
+ Object.defineProperty(this, "_authorization", {
471
+ enumerable: true,
472
+ configurable: true,
473
+ writable: true,
474
+ value: void 0
475
+ });
476
+ Object.defineProperty(this, "_group", {
477
+ enumerable: true,
478
+ configurable: true,
479
+ writable: true,
480
+ value: void 0
481
+ });
482
+ Object.defineProperty(this, "_ws", {
483
+ enumerable: true,
484
+ configurable: true,
485
+ writable: true,
486
+ value: null
487
+ });
488
+ this._authorization = authorization;
489
+ this.workspaceId = workspaceId;
490
+ this.id = id;
491
+ this.name = name;
492
+ this.schema = schema;
493
+ this.termination = termination;
494
+ this.contentTypes = contentTypes;
495
+ this.proxy = proxy;
496
+ this.documentModes = documentModes;
497
+ this.snapshots = snapshots;
498
+ this._group = group;
499
+ }
500
+ async research(callbacks, options) {
501
+ return this._runSocket({}, callbacks, options);
502
+ }
503
+ /** Join a live BrowserRoom opened by a research run. */
504
+ async joinBrowser(accessCode) {
505
+ const { BrowserRoom } = await import("./browser.js");
506
+ return BrowserRoom.join(this._authorization, { accessCode });
507
+ }
508
+ /**
509
+ * Attach to an *already-running* research/migration session for this
510
+ * dataset and replay its live timeline from the start, then keep streaming.
511
+ *
512
+ * Unlike `research`, this NEVER starts a new run: if nothing is in flight
513
+ * the returned promise rejects, so callers can `try/catch` it on load
514
+ * (e.g. to passively re-bind a run after a page reload). It otherwise
515
+ * resolves on the same terminal events as `research` (done / cancelled /
516
+ * convergence_failed / error).
517
+ */
518
+ async reconnect(callbacks, options) {
519
+ return this._runSocket({}, callbacks, options, true);
520
+ }
521
+ _runSocket(extra, callbacks, options, reconnect = false) {
522
+ return new Promise((resolve, reject) => {
523
+ const protocol = Fauna.getURL().startsWith('https') ? 'wss' : 'ws';
524
+ const route = Fauna.getURL().replace(/^https?:\/\//, '');
525
+ const params = { "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, ...(this._group ? { Group: this._group.id } : {}), Workspace: this.workspaceId, Dataset: this.id, ...extra };
526
+ if (options?.text)
527
+ params['Text'] = options.text;
528
+ if (options?.embedding)
529
+ params['Embedding'] = options.embedding;
530
+ // Attach-only: bind to an in-flight run and replay its log, but never
531
+ // start a new one. The server answers `inactive` if nothing is running.
532
+ if (reconnect)
533
+ params['Attach'] = 'true';
534
+ this._ws = new WebSocket(`${protocol}://${route}/marmot/research?authorization=${encodeURIComponent(JSON.stringify(params))}`);
535
+ // Guard against settling twice (a terminal event can be followed by
536
+ // the socket `close`/`error` firing).
537
+ let settled = false;
538
+ let attached = false;
539
+ const finish = () => { if (!settled) {
540
+ settled = true;
541
+ resolve();
542
+ } };
543
+ const fail = (message) => {
544
+ if (settled)
545
+ return;
546
+ settled = true;
547
+ this._ws?.close();
548
+ this._ws = null;
549
+ reject(new Error(message));
550
+ };
551
+ this._ws.addEventListener('message', (event) => {
552
+ const packet = JSON.parse(event.data);
553
+ switch (packet.event) {
554
+ case 'connection':
555
+ attached = packet.ongoing === true;
556
+ callbacks.onConnection?.(packet.ongoing === true);
557
+ break;
558
+ case 'inactive':
559
+ // Attach-only miss: nothing is running for this dataset.
560
+ fail('No active research run');
561
+ break;
562
+ case 'query':
563
+ callbacks.onQuery?.(packet.query);
564
+ break;
565
+ case 'source':
566
+ callbacks.onSource?.(packet.url, packet.title, packet.contentType);
567
+ break;
568
+ case 'answer':
569
+ callbacks.onAnswer?.(packet.field, packet.value, packet.converged, packet.answersCount, packet.sources);
570
+ break;
571
+ case 'nomination_accepted':
572
+ callbacks.onNomination?.(packet.scope, packet.row, packet.committedCount, packet.sources);
573
+ break;
574
+ case 'supervisor_query':
575
+ callbacks.onSupervisorQuery?.(packet.question);
576
+ break;
577
+ case 'supervisor_search':
578
+ callbacks.onSupervisorSearch?.(packet.query);
579
+ break;
580
+ case 'supervisor_answer':
581
+ callbacks.onSupervisorAnswer?.(packet.question, packet.answer);
582
+ break;
583
+ case 'supervisor_refused':
584
+ callbacks.onSupervisorRefused?.(packet.question);
585
+ break;
586
+ case 'browser':
587
+ callbacks.onBrowser?.({
588
+ url: packet.url,
589
+ reference: packet.reference,
590
+ code: packet.code,
591
+ mode: packet.mode,
592
+ });
593
+ break;
594
+ case 'browser_step':
595
+ callbacks.onBrowserStep?.(packet.url, packet.step, packet.action);
596
+ break;
597
+ case 'compress':
598
+ callbacks.onCompress?.();
599
+ break;
600
+ case 'info':
601
+ callbacks.onInfo?.(packet.message);
602
+ break;
603
+ case 'done': {
604
+ const snapshot = new Snapshot(this._authorization, this.workspaceId, this.id, packet.snapshotId, new Date(), packet.valid ?? true, this._group);
605
+ this.snapshots.push(snapshot);
606
+ callbacks.onDone?.(snapshot);
607
+ this._ws?.close();
608
+ this._ws = null;
609
+ finish();
610
+ break;
611
+ }
612
+ case 'cancelled':
613
+ callbacks.onCancelled?.(packet.reason ?? 'user');
614
+ this._ws?.close();
615
+ this._ws = null;
616
+ finish();
617
+ break;
618
+ case 'convergence_failed':
619
+ callbacks.onConvergenceFailed?.(packet.field, packet.reason, packet.candidates ?? []);
620
+ this._ws?.close();
621
+ this._ws = null;
622
+ finish();
623
+ break;
624
+ case 'error':
625
+ callbacks.onError?.(packet.message);
626
+ this._ws?.close();
627
+ this._ws = null;
628
+ finish();
629
+ break;
630
+ }
631
+ });
632
+ this._ws.addEventListener('error', () => {
633
+ this._ws = null;
634
+ // A connection-level failure before we attached to a run leaves a
635
+ // reconnect caller with nothing to resume — surface it as a reject.
636
+ if (reconnect && !attached) {
637
+ fail('Failed to connect to research run');
638
+ return;
639
+ }
640
+ callbacks.onError?.('WebSocket connection failed');
641
+ finish();
642
+ });
643
+ this._ws.addEventListener('close', () => {
644
+ // Socket closed before we ever attached (reconnect path): treat as
645
+ // "nothing to resume" so callers can try/catch on load.
646
+ if (reconnect && !attached) {
647
+ fail('No active research run');
648
+ return;
649
+ }
650
+ finish();
651
+ });
652
+ });
653
+ }
654
+ async cancel() {
655
+ // Send the cancel signal but do NOT close the socket. The server
656
+ // finishes the in-flight operation, breaks out of its loop, and emits
657
+ // a 'cancelled' event before closing the socket itself. Keeping the
658
+ // socket open lets the client observe trailing logs and the final
659
+ // 'cancelled' confirmation.
660
+ if (this._ws && this._ws.readyState === WebSocket.OPEN) {
661
+ this._ws.send(JSON.stringify({ event: 'cancel' }));
662
+ }
663
+ }
664
+ async rename(name) {
665
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
666
+ method: "POST",
667
+ headers: {
668
+ "Content-Type": "application/json",
669
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
670
+ ...(this._group ? { Group: this._group.id } : {})
671
+ },
672
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, name })
673
+ });
674
+ if (!response.ok) {
675
+ throw new Error(await response.text());
676
+ }
677
+ this.name = name;
678
+ }
679
+ /**
680
+ * Persist a new schema WITHOUT producing a snapshot. Use for edits that
681
+ * don't change the set of columns (prompt / sources / optional tweaks);
682
+ * for column add/drop use `migrate` instead so existing data is reconciled.
683
+ */
684
+ async saveSchema(schema) {
685
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
686
+ method: "POST",
687
+ headers: {
688
+ "Content-Type": "application/json",
689
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
690
+ ...(this._group ? { Group: this._group.id } : {})
691
+ },
692
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, schema: schema.serialize() })
693
+ });
694
+ if (!response.ok) {
695
+ throw new Error(await response.text());
696
+ }
697
+ this.schema = schema;
698
+ }
699
+ /**
700
+ * Migrate the dataset to a new schema, producing a fresh snapshot. Runs
701
+ * over the research WebSocket so the caller sees the same live timeline.
702
+ *
703
+ * - `seedSnapshotId` = a snapshot id: the migration starts from that
704
+ * snapshot's rows, drops removed columns, and backfills added columns
705
+ * (researching only the new fields per row, reusing each row's stored
706
+ * source URLs first).
707
+ * - `seedSnapshotId` = null: a from-scratch research run with the new
708
+ * schema (no backfill).
709
+ *
710
+ * The diff between the seed snapshot's schema and `schema` is recomputed
711
+ * authoritatively on the server. On completion the dataset's schema is
712
+ * updated to `schema`.
713
+ */
714
+ async migrate(schema, seedSnapshotId, callbacks, options) {
715
+ await this._runSocket({ Migrate: JSON.stringify({ seedSnapshotId, schema: schema.serialize() }) }, { ...callbacks, onDone: (snapshot) => { this.schema = schema; callbacks.onDone?.(snapshot); } }, options);
716
+ }
717
+ async setTermination(termination) {
718
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
719
+ method: "POST",
720
+ headers: {
721
+ "Content-Type": "application/json",
722
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
723
+ ...(this._group ? { Group: this._group.id } : {})
724
+ },
725
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, termination })
726
+ });
727
+ if (!response.ok) {
728
+ throw new Error(await response.text());
729
+ }
730
+ ;
731
+ this.termination = termination;
732
+ }
733
+ async setContentTypes(contentTypes) {
734
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
735
+ method: "POST",
736
+ headers: {
737
+ "Content-Type": "application/json",
738
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
739
+ ...(this._group ? { Group: this._group.id } : {})
740
+ },
741
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, contentTypes })
742
+ });
743
+ if (!response.ok) {
744
+ throw new Error(await response.text());
745
+ }
746
+ this.contentTypes = contentTypes;
747
+ }
748
+ async setProxy(proxy) {
749
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
750
+ method: "POST",
751
+ headers: {
752
+ "Content-Type": "application/json",
753
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
754
+ ...(this._group ? { Group: this._group.id } : {})
755
+ },
756
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, proxy })
757
+ });
758
+ if (!response.ok) {
759
+ throw new Error(await response.text());
760
+ }
761
+ this.proxy = proxy;
762
+ }
763
+ async setDocumentModes(documentModes) {
764
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/update`, {
765
+ method: "POST",
766
+ headers: {
767
+ "Content-Type": "application/json",
768
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
769
+ ...(this._group ? { Group: this._group.id } : {})
770
+ },
771
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id, documentModes })
772
+ });
773
+ if (!response.ok) {
774
+ throw new Error(await response.text());
775
+ }
776
+ this.documentModes = documentModes;
777
+ }
778
+ async remove() {
779
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/remove`, {
780
+ method: "POST",
781
+ headers: {
782
+ "Content-Type": "application/json",
783
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
784
+ ...(this._group ? { Group: this._group.id } : {})
785
+ },
786
+ body: JSON.stringify({ workspaceId: this.workspaceId, id: this.id })
787
+ });
788
+ if (!response.ok) {
789
+ throw new Error(await response.text());
790
+ }
791
+ }
792
+ /**
793
+ * The dataset's data as CSV text or, by default, a JSON array: its live
794
+ * snapshot when new rows are stored into it, else its newest valid snapshot.
795
+ */
796
+ async data(options) {
797
+ const response = await fetch(datasetDataURL(this.id, options), {
798
+ method: "GET",
799
+ headers: {
800
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
801
+ }
802
+ });
803
+ if (!response.ok) {
804
+ throw new Error(await response.text());
805
+ }
806
+ return options?.format === 'csv' ? await response.text() : await response.json();
807
+ }
808
+ /** The `/data` address, for pipelines and curl. Calls to it still need your authorization. */
809
+ dataURL(options) {
810
+ return datasetDataURL(this.id, options);
811
+ }
812
+ /**
813
+ * Push rows into the dataset: objects shaped like its rows, or CSV text with a
814
+ * header row. Rows that don't fit come back in `invalid`; when none fit, it
815
+ * throws a PushRefused listing them.
816
+ */
817
+ async addRows(rows, options) {
818
+ const query = options?.source ? `?${new URLSearchParams({ source: options.source }).toString()}` : '';
819
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/${this.id}/rows${query}`, {
820
+ method: "POST",
821
+ headers: {
822
+ "Content-Type": typeof rows === 'string' ? "text/csv" : "application/json",
823
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
824
+ },
825
+ body: typeof rows === 'string' ? rows : JSON.stringify(rows),
826
+ });
827
+ if (!response.ok) {
828
+ const text = await response.text();
829
+ let body = null;
830
+ try {
831
+ body = JSON.parse(text);
832
+ }
833
+ catch { /* plain text */ }
834
+ throw new PushRefused(response.status, body?.message ?? text, PushResult.fromJSON(body ?? {}).invalid);
835
+ }
836
+ return PushResult.fromJSON(await response.json());
837
+ }
838
+ /** Rows pushed after `since`, oldest first, at most `max`. The next page starts at the last `seq` here. */
839
+ async updates(query) {
840
+ const params = new URLSearchParams({ since: String(query.since), max: String(query.max) });
841
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/${this.id}/updates?${params.toString()}`, {
842
+ method: "GET",
843
+ headers: {
844
+ "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`,
845
+ },
846
+ });
847
+ if (!response.ok) {
848
+ throw new Error(await response.text());
849
+ }
850
+ return (await response.json()).map(FeedRow.fromJSON);
851
+ }
852
+ /**
853
+ * Every row pushed after `since`, then each new one as it lands. It opens the
854
+ * live socket first, catches up through `updates`, and skips rows it already
855
+ * gave, so nothing is missed or repeated. It reconnects by itself until `signal` aborts.
856
+ */
857
+ async *live(options) {
858
+ let since = options?.since ?? 0;
859
+ const signal = options?.signal;
860
+ while (!signal?.aborted) {
861
+ const held = [];
862
+ let ready = false;
863
+ let closed = false;
864
+ let nudge = null;
865
+ const wake = () => { const n = nudge; nudge = null; n?.(); };
866
+ const protocol = Fauna.getURL().startsWith('https') ? 'wss' : 'ws';
867
+ const route = Fauna.getURL().replace(/^https?:\/\//, '');
868
+ const params = { "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, Dataset: this.id };
869
+ const ws = new WebSocket(`${protocol}://${route}/marmot/dataset/live?authorization=${encodeURIComponent(JSON.stringify(params))}`);
870
+ const abort = () => ws.close();
871
+ signal?.addEventListener('abort', abort, { once: true });
872
+ ws.addEventListener('message', (event) => {
873
+ const packet = JSON.parse(event.data);
874
+ if (packet.event === 'ready')
875
+ ready = true;
876
+ else if (packet.event === 'rows')
877
+ held.push(...packet.rows.map(FeedRow.fromJSON));
878
+ wake();
879
+ });
880
+ ws.addEventListener('close', () => { closed = true; wake(); });
881
+ ws.addEventListener('error', () => { closed = true; wake(); });
882
+ try {
883
+ while (!ready && !closed)
884
+ await new Promise((resolve) => { nudge = resolve; });
885
+ if (ready) {
886
+ for (;;) {
887
+ const page = await this.updates({ since, max: FEED_PAGE });
888
+ for (const row of page) {
889
+ if (row.seq <= since)
890
+ continue;
891
+ since = row.seq;
892
+ yield row;
893
+ }
894
+ if (page.length < FEED_PAGE)
895
+ break;
896
+ }
897
+ while (!closed || held.length > 0) {
898
+ const row = held.shift();
899
+ if (!row) {
900
+ await new Promise((resolve) => { nudge = resolve; });
901
+ continue;
902
+ }
903
+ if (row.seq <= since)
904
+ continue;
905
+ since = row.seq;
906
+ yield row;
907
+ }
908
+ }
909
+ }
910
+ finally {
911
+ signal?.removeEventListener('abort', abort);
912
+ ws.close();
913
+ }
914
+ if (!signal?.aborted)
915
+ await new Promise((r) => setTimeout(r, 2000));
916
+ }
917
+ }
918
+ /** Whether this dataset is kept updated, and how it's going. Null when it isn't. */
919
+ async scraper() {
920
+ return getScraper(this._authorization, this.id);
921
+ }
922
+ /** Keep this dataset updated by its workspace's scraper agent. You become the person the agent runs as. */
923
+ async keepUpdated(settings = {}) {
924
+ return createScraper(this._authorization, this.id, settings);
925
+ }
926
+ async updateScraper(settings) {
927
+ return updateScraper(this._authorization, this.id, settings);
928
+ }
929
+ /** Ask the agent to go over this dataset's scraper again, with a note for it. */
930
+ async rebuildScraper(note) {
931
+ return rebuildScraper(this._authorization, this.id, note);
932
+ }
933
+ /** Stop keeping this dataset updated. */
934
+ async stopKeepingUpdated() {
935
+ return removeScraper(this._authorization, this.id);
936
+ }
937
+ }
938
+ // ─── API Functions ───────────────────────────────────────────────────────────
939
+ export async function listDatasets(authorization, workspaceId, opts) {
940
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/list`, {
941
+ method: "POST",
942
+ headers: {
943
+ "Content-Type": "application/json",
944
+ "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {})
945
+ },
946
+ body: JSON.stringify({ workspaceId })
947
+ });
948
+ if (!response.ok) {
949
+ throw new Error(await response.text());
950
+ }
951
+ const data = await response.json();
952
+ return data.map((d) => new Dataset(authorization, workspaceId, d.id, d.name, Schema.deserialize(d.schema), d.termination ?? [], d.contentTypes ?? [], (d.proxy ?? 'datacenter'), (d.documentModes ?? ['extraction']), (d.snapshots ?? []).map((s) => new Snapshot(authorization, workspaceId, d.id, s.id, new Date(s.createdAt), s.valid ?? true, opts?.group)), opts?.group));
953
+ }
954
+ export async function createDataset(authorization, workspaceId, options, opts) {
955
+ const response = await fetch(`${Fauna.getURL()}/marmot/dataset/create`, {
956
+ method: "POST",
957
+ headers: {
958
+ "Content-Type": "application/json",
959
+ "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {})
960
+ },
961
+ body: JSON.stringify({
962
+ workspaceId,
963
+ name: options.name,
964
+ schema: options.schema.serialize(),
965
+ termination: options.termination ?? [],
966
+ contentTypes: options.contentTypes ?? [],
967
+ proxy: options.proxy ?? 'datacenter',
968
+ documentModes: options.documentModes ?? ['extraction']
969
+ })
970
+ });
971
+ if (!response.ok) {
972
+ throw new Error(await response.text());
973
+ }
974
+ return await response.text();
975
+ }
976
+ function toBase64(data) {
977
+ let binary = '';
978
+ const chunk = 0x8000;
979
+ for (let i = 0; i < data.length; i += chunk) {
980
+ binary += String.fromCharCode.apply(null, Array.from(data.subarray(i, i + chunk)));
981
+ }
982
+ return typeof btoa !== 'undefined' ? btoa(binary) : Buffer.from(data).toString('base64');
983
+ }
984
+ export class Workspace {
985
+ constructor(authorization, id, name, description, createdAt, datasets = 0, files = 0, group) {
986
+ Object.defineProperty(this, "id", {
987
+ enumerable: true,
988
+ configurable: true,
989
+ writable: true,
990
+ value: void 0
991
+ });
992
+ Object.defineProperty(this, "name", {
993
+ enumerable: true,
994
+ configurable: true,
995
+ writable: true,
996
+ value: void 0
997
+ });
998
+ Object.defineProperty(this, "description", {
999
+ enumerable: true,
1000
+ configurable: true,
1001
+ writable: true,
1002
+ value: void 0
1003
+ });
1004
+ Object.defineProperty(this, "createdAt", {
1005
+ enumerable: true,
1006
+ configurable: true,
1007
+ writable: true,
1008
+ value: void 0
1009
+ });
1010
+ Object.defineProperty(this, "datasets", {
1011
+ enumerable: true,
1012
+ configurable: true,
1013
+ writable: true,
1014
+ value: void 0
1015
+ });
1016
+ Object.defineProperty(this, "files", {
1017
+ enumerable: true,
1018
+ configurable: true,
1019
+ writable: true,
1020
+ value: void 0
1021
+ });
1022
+ Object.defineProperty(this, "_authorization", {
1023
+ enumerable: true,
1024
+ configurable: true,
1025
+ writable: true,
1026
+ value: void 0
1027
+ });
1028
+ Object.defineProperty(this, "_group", {
1029
+ enumerable: true,
1030
+ configurable: true,
1031
+ writable: true,
1032
+ value: void 0
1033
+ });
1034
+ this._authorization = authorization;
1035
+ this.id = id;
1036
+ this.name = name;
1037
+ this.description = description;
1038
+ this.createdAt = createdAt;
1039
+ this.datasets = datasets;
1040
+ this.files = files;
1041
+ this._group = group;
1042
+ }
1043
+ async listDatasets() {
1044
+ return listDatasets(this._authorization, this.id, this._group ? { group: this._group } : undefined);
1045
+ }
1046
+ async createDataset(options) {
1047
+ return createDataset(this._authorization, this.id, options, this._group ? { group: this._group } : undefined);
1048
+ }
1049
+ async rename(name) {
1050
+ await updateWorkspace(this._authorization, this.id, { name }, this._group ? { group: this._group } : undefined);
1051
+ this.name = name;
1052
+ }
1053
+ async setDescription(description) {
1054
+ await updateWorkspace(this._authorization, this.id, { description }, this._group ? { group: this._group } : undefined);
1055
+ this.description = description;
1056
+ }
1057
+ async remove() {
1058
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/remove`, {
1059
+ method: "POST",
1060
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, ...(this._group ? { Group: this._group.id } : {}) },
1061
+ body: JSON.stringify({ id: this.id })
1062
+ });
1063
+ if (!response.ok)
1064
+ throw new Error(await response.text());
1065
+ }
1066
+ async getFiles() {
1067
+ const detail = await getWorkspace(this._authorization, this.id, this._group ? { group: this._group } : undefined);
1068
+ return detail.files;
1069
+ }
1070
+ async uploadFile(name, contentType, data) {
1071
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/file/upload`, {
1072
+ method: "POST",
1073
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, ...(this._group ? { Group: this._group.id } : {}) },
1074
+ body: JSON.stringify({ workspaceId: this.id, name, contentType, data: toBase64(data) })
1075
+ });
1076
+ if (!response.ok)
1077
+ throw new Error(await response.text());
1078
+ return await response.json();
1079
+ }
1080
+ async downloadFile(file) {
1081
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/file/get`, {
1082
+ method: "POST",
1083
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, ...(this._group ? { Group: this._group.id } : {}) },
1084
+ body: JSON.stringify({ key: file.key, contentType: file.contentType, workspaceId: this.id })
1085
+ });
1086
+ if (!response.ok)
1087
+ throw new Error(await response.text());
1088
+ return await response.blob();
1089
+ }
1090
+ async removeFile(key) {
1091
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/file/remove`, {
1092
+ method: "POST",
1093
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in this._authorization ? `Token ${this._authorization.token}` : `ApiKey ${this._authorization.id}`, ...(this._group ? { Group: this._group.id } : {}) },
1094
+ body: JSON.stringify({ workspaceId: this.id, key })
1095
+ });
1096
+ if (!response.ok)
1097
+ throw new Error(await response.text());
1098
+ }
1099
+ }
1100
+ export async function listWorkspaces(authorization, opts) {
1101
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/list`, {
1102
+ method: "POST",
1103
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {}) }
1104
+ });
1105
+ if (!response.ok)
1106
+ throw new Error(await response.text());
1107
+ const data = await response.json();
1108
+ return data.map((w) => new Workspace(authorization, w.id, w.name, w.description ?? '', w.createdAt ?? 0, w.datasets ?? 0, w.files ?? 0, opts?.group));
1109
+ }
1110
+ export async function getWorkspace(authorization, id, opts) {
1111
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/get`, {
1112
+ method: "POST",
1113
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {}) },
1114
+ body: JSON.stringify({ id })
1115
+ });
1116
+ if (!response.ok)
1117
+ throw new Error(await response.text());
1118
+ return await response.json();
1119
+ }
1120
+ export async function createWorkspace(authorization, name, description = '', opts) {
1121
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/create`, {
1122
+ method: "POST",
1123
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {}) },
1124
+ body: JSON.stringify({ name, description })
1125
+ });
1126
+ if (!response.ok)
1127
+ throw new Error(await response.text());
1128
+ return await response.text();
1129
+ }
1130
+ export async function updateWorkspace(authorization, id, update, opts) {
1131
+ const response = await fetch(`${Fauna.getURL()}/marmot/workspace/update`, {
1132
+ method: "POST",
1133
+ headers: { "Content-Type": "application/json", "Authorization": 'email' in authorization ? `Token ${authorization.token}` : `ApiKey ${authorization.id}`, ...(opts?.group ? { Group: opts.group.id } : {}) },
1134
+ body: JSON.stringify({ id, ...update })
1135
+ });
1136
+ if (!response.ok)
1137
+ throw new Error(await response.text());
1138
+ }