@meshagent/meshagent-agents 0.43.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 (55) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +1 -0
  3. package/README.md +206 -0
  4. package/dist/browser/agent-messages.d.ts +343 -0
  5. package/dist/browser/agent-messages.js +1015 -0
  6. package/dist/browser/change-emitter.d.ts +8 -0
  7. package/dist/browser/change-emitter.js +20 -0
  8. package/dist/browser/chat-client.d.ts +225 -0
  9. package/dist/browser/chat-client.js +642 -0
  10. package/dist/browser/images-dataset.d.ts +83 -0
  11. package/dist/browser/images-dataset.js +282 -0
  12. package/dist/browser/index.d.ts +6 -0
  13. package/dist/browser/index.js +22 -0
  14. package/dist/browser/package.json +1 -0
  15. package/dist/browser/room-shell-toolkit.d.ts +14 -0
  16. package/dist/browser/room-shell-toolkit.js +274 -0
  17. package/dist/browser/room-storage-toolkit.d.ts +11 -0
  18. package/dist/browser/room-storage-toolkit.js +513 -0
  19. package/dist/browser/thread-storage.d.ts +102 -0
  20. package/dist/browser/thread-storage.js +476 -0
  21. package/dist/esm/agent-messages.d.ts +343 -0
  22. package/dist/esm/agent-messages.js +989 -0
  23. package/dist/esm/change-emitter.d.ts +8 -0
  24. package/dist/esm/change-emitter.js +16 -0
  25. package/dist/esm/chat-client.d.ts +225 -0
  26. package/dist/esm/chat-client.js +632 -0
  27. package/dist/esm/images-dataset.d.ts +83 -0
  28. package/dist/esm/images-dataset.js +274 -0
  29. package/dist/esm/index.d.ts +6 -0
  30. package/dist/esm/index.js +6 -0
  31. package/dist/esm/package.json +1 -0
  32. package/dist/esm/room-shell-toolkit.d.ts +14 -0
  33. package/dist/esm/room-shell-toolkit.js +270 -0
  34. package/dist/esm/room-storage-toolkit.d.ts +11 -0
  35. package/dist/esm/room-storage-toolkit.js +509 -0
  36. package/dist/esm/thread-storage.d.ts +102 -0
  37. package/dist/esm/thread-storage.js +465 -0
  38. package/dist/node/agent-messages.d.ts +343 -0
  39. package/dist/node/agent-messages.js +1015 -0
  40. package/dist/node/change-emitter.d.ts +8 -0
  41. package/dist/node/change-emitter.js +20 -0
  42. package/dist/node/chat-client.d.ts +225 -0
  43. package/dist/node/chat-client.js +642 -0
  44. package/dist/node/images-dataset.d.ts +83 -0
  45. package/dist/node/images-dataset.js +282 -0
  46. package/dist/node/index.d.ts +6 -0
  47. package/dist/node/index.js +22 -0
  48. package/dist/node/package.json +1 -0
  49. package/dist/node/room-shell-toolkit.d.ts +14 -0
  50. package/dist/node/room-shell-toolkit.js +274 -0
  51. package/dist/node/room-storage-toolkit.d.ts +11 -0
  52. package/dist/node/room-storage-toolkit.js +513 -0
  53. package/dist/node/thread-storage.d.ts +102 -0
  54. package/dist/node/thread-storage.js +476 -0
  55. package/package.json +57 -0
@@ -0,0 +1,476 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatasetThreadStorage = exports.AgentThreadStorageRepository = exports.DatasetThreadStorageRepository = exports.DatasetThreadListRef = exports.ThreadStorageRepository = exports.ThreadStorage = exports.ThreadListEntry = exports.defaultUntitledThreadName = void 0;
4
+ exports.defaultThreadDisplayNameFromPath = defaultThreadDisplayNameFromPath;
5
+ const apache_arrow_1 = require("apache-arrow");
6
+ const change_emitter_js_1 = require("./change-emitter.js");
7
+ const agent_messages_js_1 = require("./agent-messages.js");
8
+ exports.defaultUntitledThreadName = "New Chat";
9
+ const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
10
+ class ThreadListEntry {
11
+ constructor({ path, name, createdAt, modifiedAt }) {
12
+ this.path = path;
13
+ this.name = name;
14
+ this.createdAt = createdAt;
15
+ this.modifiedAt = modifiedAt;
16
+ }
17
+ renamed(name, modifiedAt) {
18
+ return new ThreadListEntry({
19
+ path: this.path,
20
+ name,
21
+ createdAt: this.createdAt,
22
+ modifiedAt,
23
+ });
24
+ }
25
+ static fromDatasetRow(row) {
26
+ const rawPath = row.path;
27
+ if (typeof rawPath !== "string" || rawPath.trim() === "") {
28
+ return null;
29
+ }
30
+ const threadPath = rawPath.trim();
31
+ const rawName = row.name;
32
+ const rawCreatedAt = row.created_at;
33
+ const rawModifiedAt = row.modified_at;
34
+ return new ThreadListEntry({
35
+ path: threadPath,
36
+ name: typeof rawName === "string" && rawName.trim() !== "" ? rawName.trim() : defaultThreadDisplayNameFromPath(threadPath),
37
+ createdAt: typeof rawCreatedAt === "string" ? rawCreatedAt : "",
38
+ modifiedAt: typeof rawModifiedAt === "string" ? rawModifiedAt : "",
39
+ });
40
+ }
41
+ }
42
+ exports.ThreadListEntry = ThreadListEntry;
43
+ class ThreadStorage {
44
+ }
45
+ exports.ThreadStorage = ThreadStorage;
46
+ class ThreadStorageRepository extends change_emitter_js_1.ChangeEmitter {
47
+ }
48
+ exports.ThreadStorageRepository = ThreadStorageRepository;
49
+ class DatasetThreadListRef {
50
+ constructor({ namespace, table }) {
51
+ this.namespace = namespace;
52
+ this.table = table;
53
+ }
54
+ static parse(url) {
55
+ let path = url.trim();
56
+ if (!path.startsWith("dataset://")) {
57
+ throw new TypeError("dataset thread list URL must start with dataset://");
58
+ }
59
+ path = path.slice("dataset://".length);
60
+ if (path.startsWith("/")) {
61
+ throw new TypeError("dataset thread list URL must use dataset://path");
62
+ }
63
+ const parts = path.split("/").map((part) => part.trim()).filter((part) => part !== "");
64
+ if (parts.length === 0) {
65
+ throw new TypeError("dataset thread list URL must include a table name");
66
+ }
67
+ return new DatasetThreadListRef({
68
+ namespace: parts.length === 1 ? undefined : parts.slice(0, -1),
69
+ table: parts[parts.length - 1],
70
+ });
71
+ }
72
+ }
73
+ exports.DatasetThreadListRef = DatasetThreadListRef;
74
+ class DatasetThreadStorageRepository extends ThreadStorageRepository {
75
+ constructor({ room, path }) {
76
+ super();
77
+ this.entriesByPath = new Map();
78
+ this.initialSnapshotReady = false;
79
+ this.closed = true;
80
+ this.room = room;
81
+ this.path = path.trim();
82
+ this.ref = DatasetThreadListRef.parse(this.path);
83
+ }
84
+ async open() {
85
+ this.closed = false;
86
+ await this.ensureTable();
87
+ this.abortController = new AbortController();
88
+ const ready = new Promise((resolve, reject) => {
89
+ this.watchTask = this.watchLoop(resolve, reject);
90
+ });
91
+ await ready;
92
+ }
93
+ async watchLoop(resolveReady, rejectReady) {
94
+ let readyResolved = false;
95
+ try {
96
+ for await (const event of this.room.datasets.watchTable({ table: this.ref.table, namespace: this.ref.namespace })) {
97
+ if (this.closed) {
98
+ return;
99
+ }
100
+ const initialSnapshotCompleted = this.handleWatchEvent(event);
101
+ if (initialSnapshotCompleted && !readyResolved) {
102
+ readyResolved = true;
103
+ resolveReady();
104
+ }
105
+ }
106
+ if (!readyResolved && !this.closed) {
107
+ rejectReady(new Error("Dataset thread list watch closed before initial snapshot."));
108
+ }
109
+ }
110
+ catch (error) {
111
+ if (this.closed) {
112
+ return;
113
+ }
114
+ if (!readyResolved) {
115
+ rejectReady(error);
116
+ }
117
+ else {
118
+ throw error;
119
+ }
120
+ }
121
+ }
122
+ async close() {
123
+ this.abortController?.abort();
124
+ this.abortController = undefined;
125
+ this.initialSnapshotReady = false;
126
+ this.closed = true;
127
+ this.watchTask = undefined;
128
+ const refreshEntriesFuture = this.refreshEntriesFuture;
129
+ this.refreshEntriesFuture = undefined;
130
+ if (refreshEntriesFuture != null) {
131
+ try {
132
+ await refreshEntriesFuture;
133
+ }
134
+ catch {
135
+ }
136
+ }
137
+ }
138
+ entries() {
139
+ return [...this.entriesByPath.values()];
140
+ }
141
+ async addOrUpdateThread(entry) {
142
+ await this.ensureTable();
143
+ await this.room.datasets.merge({
144
+ table: this.ref.table,
145
+ on: "path",
146
+ records: this.batchFor([entry]),
147
+ namespace: this.ref.namespace,
148
+ });
149
+ }
150
+ async deleteThread(threadPath) {
151
+ const normalized = normalizeThreadPath(threadPath);
152
+ await this.ensureTable();
153
+ await this.room.datasets.delete({
154
+ table: this.ref.table,
155
+ where: pathWhere(normalized),
156
+ namespace: this.ref.namespace,
157
+ });
158
+ if (this.entriesByPath.delete(normalized)) {
159
+ this.notifyListeners();
160
+ }
161
+ }
162
+ async renameThread(threadPath, name) {
163
+ const normalized = normalizeThreadPath(threadPath);
164
+ const trimmedName = name.trim();
165
+ if (trimmedName === "") {
166
+ throw new TypeError("thread name cannot be empty");
167
+ }
168
+ const now = new Date().toISOString();
169
+ const existing = this.entriesByPath.get(normalized);
170
+ await this.addOrUpdateThread(new ThreadListEntry({
171
+ path: normalized,
172
+ name: trimmedName,
173
+ createdAt: existing?.createdAt ?? now,
174
+ modifiedAt: now,
175
+ }));
176
+ }
177
+ async ensureTable() {
178
+ await this.room.datasets.createTableWithSchema({
179
+ name: this.ref.table,
180
+ schema: DatasetThreadStorageRepository.schema,
181
+ mode: "create_if_not_exists",
182
+ namespace: this.ref.namespace,
183
+ });
184
+ }
185
+ handleWatchEvent(event) {
186
+ const rows = event.table == null ? [] : rowsFromTable(event.table);
187
+ if (event.phase === "initial") {
188
+ for (const row of rows) {
189
+ const entry = ThreadListEntry.fromDatasetRow(row);
190
+ if (entry != null) {
191
+ this.entriesByPath.set(entry.path, entry);
192
+ }
193
+ }
194
+ if (event.kind === "ready") {
195
+ this.initialSnapshotReady = true;
196
+ return true;
197
+ }
198
+ if (this.initialSnapshotReady && rows.length > 0) {
199
+ this.notifyListeners();
200
+ }
201
+ return false;
202
+ }
203
+ if (event.kind === "ready") {
204
+ return false;
205
+ }
206
+ const changeType = event.changeType?.trim().toLowerCase() ?? "";
207
+ if (changeType === "deleted" ||
208
+ changeType === "delete" ||
209
+ changeType === "removed" ||
210
+ changeType === "remove" ||
211
+ event.deletePredicate != null ||
212
+ event.kind.trim().toLowerCase() === "delete") {
213
+ let removed = false;
214
+ for (const row of rows) {
215
+ const entry = ThreadListEntry.fromDatasetRow(row);
216
+ if (entry != null) {
217
+ removed = this.entriesByPath.delete(entry.path) || removed;
218
+ }
219
+ }
220
+ const deletedPath = threadPathFromDeletePredicate(event.deletePredicate);
221
+ if (deletedPath != null) {
222
+ removed = this.entriesByPath.delete(deletedPath) || removed;
223
+ }
224
+ if (rows.length === 0 && deletedPath == null) {
225
+ const refreshEntriesFuture = this.refreshEntries();
226
+ this.refreshEntriesFuture = refreshEntriesFuture;
227
+ void refreshEntriesFuture.catch(() => undefined);
228
+ return false;
229
+ }
230
+ if (removed || rows.length === 0) {
231
+ this.notifyListeners();
232
+ }
233
+ return false;
234
+ }
235
+ let changed = false;
236
+ for (const row of rows) {
237
+ const entry = ThreadListEntry.fromDatasetRow(row);
238
+ if (entry != null) {
239
+ this.entriesByPath.set(entry.path, entry);
240
+ changed = true;
241
+ }
242
+ }
243
+ if (changed) {
244
+ this.notifyListeners();
245
+ }
246
+ return false;
247
+ }
248
+ async refreshEntries() {
249
+ if (this.closed) {
250
+ return;
251
+ }
252
+ const table = await this.room.datasets.search({
253
+ table: this.ref.table,
254
+ namespace: this.ref.namespace,
255
+ select: ["path", "name", "created_at", "modified_at"],
256
+ });
257
+ if (this.closed) {
258
+ return;
259
+ }
260
+ const nextEntries = new Map();
261
+ for (const row of rowsFromTable(table)) {
262
+ const entry = ThreadListEntry.fromDatasetRow(row);
263
+ if (entry != null) {
264
+ nextEntries.set(entry.path, entry);
265
+ }
266
+ }
267
+ this.entriesByPath.clear();
268
+ for (const [path, entry] of nextEntries) {
269
+ this.entriesByPath.set(path, entry);
270
+ }
271
+ if (!this.closed) {
272
+ this.notifyListeners();
273
+ }
274
+ }
275
+ batchFor(entries) {
276
+ return (0, apache_arrow_1.tableFromArrays)({
277
+ path: entries.map((entry) => entry.path),
278
+ name: entries.map((entry) => entry.name),
279
+ created_at: entries.map((entry) => entry.createdAt),
280
+ modified_at: entries.map((entry) => entry.modifiedAt),
281
+ });
282
+ }
283
+ }
284
+ exports.DatasetThreadStorageRepository = DatasetThreadStorageRepository;
285
+ DatasetThreadStorageRepository.schema = new apache_arrow_1.Schema([
286
+ new apache_arrow_1.Field("path", new apache_arrow_1.Utf8(), false),
287
+ new apache_arrow_1.Field("name", new apache_arrow_1.Utf8(), true),
288
+ new apache_arrow_1.Field("created_at", new apache_arrow_1.Utf8(), true),
289
+ new apache_arrow_1.Field("modified_at", new apache_arrow_1.Utf8(), true),
290
+ ]);
291
+ class AgentThreadStorageRepository extends ThreadStorageRepository {
292
+ constructor({ chatClient, limit = 200 }) {
293
+ super();
294
+ this.entriesByPath = new Map();
295
+ this.closed = true;
296
+ this.chatClient = chatClient;
297
+ this.limit = limit;
298
+ }
299
+ async open() {
300
+ if (!this.closed) {
301
+ return;
302
+ }
303
+ this.closed = false;
304
+ const iterator = this.chatClient.events[Symbol.asyncIterator]();
305
+ let active = true;
306
+ this.subscription = () => { active = false; };
307
+ void (async () => {
308
+ while (active && !this.closed) {
309
+ const next = await iterator.next();
310
+ if (next.done) {
311
+ return;
312
+ }
313
+ this.handleEvent(next.value);
314
+ }
315
+ })();
316
+ await new Promise((resolve) => {
317
+ this.pendingOpen = { resolve };
318
+ void this.requestList();
319
+ });
320
+ }
321
+ async close() {
322
+ this.closed = true;
323
+ this.subscription?.();
324
+ this.subscription = undefined;
325
+ this.pendingListMessageId = undefined;
326
+ this.pendingOpen?.resolve();
327
+ this.pendingOpen = undefined;
328
+ }
329
+ entries() {
330
+ return [...this.entriesByPath.values()];
331
+ }
332
+ async addOrUpdateThread(_entry) {
333
+ throw new Error("Agent thread storage cannot directly upsert thread entries.");
334
+ }
335
+ async deleteThread(threadPath) {
336
+ const normalized = normalizeThreadPath(threadPath);
337
+ await this.chatClient.sendAgentMessage(new agent_messages_js_1.DeleteThread({ threadId: normalized }));
338
+ if (this.entriesByPath.delete(normalized)) {
339
+ this.notifyListeners();
340
+ }
341
+ void this.requestList();
342
+ }
343
+ async renameThread(threadPath, name) {
344
+ const normalized = normalizeThreadPath(threadPath);
345
+ const trimmedName = name.trim();
346
+ if (trimmedName === "") {
347
+ throw new TypeError("thread name cannot be empty");
348
+ }
349
+ await this.chatClient.sendAgentMessage(new agent_messages_js_1.RenameThread({ threadId: normalized, name: trimmedName }));
350
+ const existing = this.entriesByPath.get(normalized);
351
+ if (existing != null) {
352
+ this.entriesByPath.set(normalized, existing.renamed(trimmedName, new Date().toISOString()));
353
+ this.notifyListeners();
354
+ }
355
+ void this.requestList();
356
+ }
357
+ async requestList() {
358
+ if (this.closed) {
359
+ return;
360
+ }
361
+ const request = new agent_messages_js_1.ListThreads({ limit: this.limit, offset: 0 });
362
+ this.pendingListMessageId = request.messageId;
363
+ await this.chatClient.sendAgentMessage(request, { ignoreOffline: true });
364
+ }
365
+ handleEvent(event) {
366
+ const message = event.message;
367
+ if (message.type === "meshagent.agent.thread.listed") {
368
+ this.handleThreadsListed(message);
369
+ return;
370
+ }
371
+ if (message.type === "meshagent.agent.thread.created") {
372
+ this.upsertThread(message.thread);
373
+ return;
374
+ }
375
+ if (message.type === "meshagent.agent.thread.updated") {
376
+ this.upsertThread(message.thread);
377
+ return;
378
+ }
379
+ if (message.type === "meshagent.agent.thread.deleted") {
380
+ const normalized = normalizeThreadPath(String(message.path));
381
+ if (this.entriesByPath.delete(normalized) && !this.closed) {
382
+ this.notifyListeners();
383
+ }
384
+ }
385
+ }
386
+ handleThreadsListed(message) {
387
+ const nextEntries = new Map();
388
+ for (const thread of message.threads) {
389
+ const entry = this.entryFromAgentThread(thread);
390
+ if (entry != null) {
391
+ nextEntries.set(entry.path, entry);
392
+ }
393
+ }
394
+ this.entriesByPath.clear();
395
+ for (const [path, entry] of nextEntries) {
396
+ this.entriesByPath.set(path, entry);
397
+ }
398
+ if (this.pendingOpen != null && (this.pendingListMessageId == null || message.sourceMessageId === this.pendingListMessageId)) {
399
+ this.pendingOpen.resolve();
400
+ this.pendingOpen = undefined;
401
+ }
402
+ if (!this.closed) {
403
+ this.notifyListeners();
404
+ }
405
+ }
406
+ upsertThread(thread) {
407
+ const entry = this.entryFromAgentThread(thread);
408
+ if (entry == null) {
409
+ return;
410
+ }
411
+ this.entriesByPath.set(entry.path, entry);
412
+ if (!this.closed) {
413
+ this.notifyListeners();
414
+ }
415
+ }
416
+ entryFromAgentThread(thread) {
417
+ const path = thread.path.trim();
418
+ if (path === "") {
419
+ return null;
420
+ }
421
+ const name = thread.name.trim();
422
+ return new ThreadListEntry({
423
+ path,
424
+ name: name !== "" ? name : defaultThreadDisplayNameFromPath(path),
425
+ createdAt: thread.createdAt,
426
+ modifiedAt: thread.modifiedAt,
427
+ });
428
+ }
429
+ }
430
+ exports.AgentThreadStorageRepository = AgentThreadStorageRepository;
431
+ class DatasetThreadStorage extends DatasetThreadStorageRepository {
432
+ }
433
+ exports.DatasetThreadStorage = DatasetThreadStorage;
434
+ function defaultThreadDisplayNameFromPath(path) {
435
+ const segments = path.split("/").filter((segment) => segment !== "");
436
+ const basename = segments.length === 0 ? path : segments[segments.length - 1];
437
+ const rawName = basename.endsWith(".thread") ? basename.slice(0, -".thread".length) : basename;
438
+ const trimmed = rawName.trim();
439
+ if (trimmed === "" || uuidPattern.test(trimmed)) {
440
+ return exports.defaultUntitledThreadName;
441
+ }
442
+ const normalized = trimmed.replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
443
+ if (normalized === "") {
444
+ return exports.defaultUntitledThreadName;
445
+ }
446
+ return normalized
447
+ .split(" ")
448
+ .filter((segment) => segment !== "")
449
+ .map((segment) => segment.length === 1 ? segment.toUpperCase() : `${segment[0].toUpperCase()}${segment.slice(1)}`)
450
+ .join(" ");
451
+ }
452
+ function normalizeThreadPath(threadPath) {
453
+ const normalized = threadPath.trim();
454
+ if (normalized === "") {
455
+ throw new TypeError("thread path cannot be empty");
456
+ }
457
+ return normalized;
458
+ }
459
+ function pathWhere(threadPath) {
460
+ return `path = ${datasetStringLiteral(threadPath)}`;
461
+ }
462
+ function datasetStringLiteral(value) {
463
+ return `'${value.replace(/'/g, "''")}'`;
464
+ }
465
+ function threadPathFromDeletePredicate(predicate) {
466
+ const trimmed = predicate?.trim();
467
+ if (trimmed == null || trimmed === "") {
468
+ return undefined;
469
+ }
470
+ const match = /^path\s*=\s*(['"])(.*)\1$/i.exec(trimmed);
471
+ return match == null ? undefined : match[2].replace(/''/g, "'");
472
+ }
473
+ function rowsFromTable(table) {
474
+ const tables = Array.isArray(table) ? table : [table];
475
+ return tables.flatMap((entry) => entry.toArray().map((row) => ({ ...row })));
476
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@meshagent/meshagent-agents",
3
+ "version": "0.43.0",
4
+ "description": "Agent chat sessions and clients for Meshagent TypeScript applications.",
5
+ "homepage": "https://github.com/meshagent/meshagent-agents-ts",
6
+ "scripts": {
7
+ "test": "./run-tests.sh",
8
+ "build": "mkdir -p dist && ./scripts/build.sh"
9
+ },
10
+ "author": "Timu, LLC",
11
+ "license": "Apache-2.0",
12
+ "main": "./dist/node/index.js",
13
+ "types": "./dist/node/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/node/index.d.ts",
17
+ "node": {
18
+ "import": "./dist/esm/index.js",
19
+ "require": "./dist/node/index.js"
20
+ },
21
+ "browser": {
22
+ "import": "./dist/esm/index.js",
23
+ "require": "./dist/browser/index.js"
24
+ },
25
+ "import": "./dist/esm/index.js",
26
+ "require": "./dist/node/index.js",
27
+ "default": "./dist/esm/index.js"
28
+ },
29
+ "./package.json": "./package.json"
30
+ },
31
+ "browser": {
32
+ "./dist/node/index.js": "./dist/browser/index.js"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "!dist/**/test",
37
+ "LICENSE",
38
+ "README.md",
39
+ "CHANGELOG.md"
40
+ ],
41
+ "devDependencies": {
42
+ "@types/chai": "^5.0.1",
43
+ "@types/mocha": "^10.0.10",
44
+ "@types/node": "^22.13.9",
45
+ "chai": "^5.2.0",
46
+ "mocha": "^12.0.0-beta-9.2",
47
+ "typescript": "^5.8.2"
48
+ },
49
+ "dependencies": {
50
+ "@meshagent/meshagent": "^0.43.0",
51
+ "apache-arrow": "^21.0.0",
52
+ "uuid": "^14.0.0"
53
+ },
54
+ "overrides": {
55
+ "rollup": "4.52.5"
56
+ }
57
+ }