@gaia-ai/addon-gaia-ui 0.17.2 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/Entity/ticket/Component/edit-form/index.js +9 -2
- package/dist/src/Entity/ticket/Component/sections/index.js +5 -3
- package/dist/src/Entity/ticket/Component/ticket-content/index.d.ts +17 -0
- package/dist/src/Entity/ticket/Component/ticket-content/index.js +60 -2
- package/dist/src/Entity/ticket/Component/ticket-content/model.d.ts +1 -1
- package/dist/src/Entity/ticket/Component/ticket-content/model.js +33 -5
- package/dist/src/Entity/ticket/Component/ticket-detail/index.d.ts +6 -2
- package/dist/src/Entity/ticket/Component/ticket-detail/index.js +59 -4
- package/dist/src/Entity/ticket/Data/addons.d.ts +53 -0
- package/dist/src/Entity/ticket/Data/addons.js +35 -0
- package/dist/src/Entity/ticket/Data/detail.js +2 -0
- package/dist/src/Entity/ticket/Data/store.js +2 -0
- package/dist/src/Entity/ticket/Data/tickets.d.ts +13 -9
- package/dist/src/Entity/ticket/Data/tickets.js +12 -4
- package/dist/src/Entity/ticket/Data/write.d.ts +7 -0
- package/dist/src/Entity/ticket/Data/write.js +17 -0
- package/dist/src/Entity/ticket/Form/addon-action.d.ts +37 -0
- package/dist/src/Entity/ticket/Form/addon-action.js +80 -0
- package/dist/src/Entity/ticket/Form/create-data.d.ts +2 -0
- package/dist/src/Entity/ticket/Form/create-data.js +9 -1
- package/dist/src/Entity/ticket/Form/create.d.ts +5 -1
- package/dist/src/Entity/ticket/Form/create.js +3 -0
- package/dist/src/Entity/ticket/Form/edit-data.d.ts +2 -0
- package/dist/src/Entity/ticket/Form/edit-data.js +14 -1
- package/dist/src/Entity/ticket/Form/edit.d.ts +14 -1
- package/dist/src/Entity/ticket/Form/edit.js +31 -0
- package/dist/src/Entity/ticket/Form/reviewer-options.d.ts +10 -0
- package/dist/src/Entity/ticket/Form/reviewer-options.js +48 -0
- package/dist/src/Entity/ticket/Screen/conductor-tickets.d.ts +2 -2
- package/dist/src/Entity/ticket/Screen/create-ticket-form.js +4 -0
- package/dist/src/Entity/ticket/Screen/edit-assignment-form.js +30 -1
- package/dist/src/Entity/ticket/Screen/ticket-addons.d.ts +94 -0
- package/dist/src/Entity/ticket/Screen/ticket-addons.js +492 -0
- package/dist/src/Entity/ticket/Screen/ticket-content-screen.d.ts +21 -0
- package/dist/src/Entity/ticket/Screen/ticket-content-screen.js +122 -8
- package/dist/src/Entity/ticket/Screen/ticket-detail.js +4 -2
- package/dist/src/Entity/ticket/Screen/tickets.d.ts +2 -2
- package/dist/src/Entity/ticket/Screen/user-tickets.d.ts +2 -2
- package/dist/src/Routing/routes.js +3 -0
- package/dist/src/Widget/multiselect.js +7 -3
- package/dist/src/types.d.ts +5 -0
- package/package.json +3 -2
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { actionItem, } from '../../../Component/footer-actions/index.js';
|
|
2
2
|
import { copyThrough } from '../../../lib/clipboard.js';
|
|
3
|
+
import { serverMessage } from '../../../lib/jsonapi-error.js';
|
|
3
4
|
import { BORDER, textNode } from '../../../lib/vnode.js';
|
|
4
5
|
import { AsyncScreen, } from '../../../Screen/async-screen.js';
|
|
5
|
-
import {
|
|
6
|
+
import { runRowAction } from '../../../Screen/row-action.js';
|
|
7
|
+
import { ADDONS_KEY, hasAddonsMessages, TicketContent, } from '../Component/ticket-content/index.js';
|
|
6
8
|
import { initialExpandedKeys, resolveSelectedKey, retainExpandedKeys, ticketContentModel, ticketContentRowId, } from '../Component/ticket-content/model.js';
|
|
7
9
|
import { handleTicketCopy, ticketCopyActions, ticketEditAction, ticketHeaderTree, ticketTitleOf, } from '../Component/ticket-detail/index.js';
|
|
8
10
|
import { ticketTeaserLines, ticketTeaserTree, } from '../Component/ticket-teaser/index.js';
|
|
11
|
+
import { readTicketAddons } from '../Data/addons.js';
|
|
12
|
+
import { loadTicketDetail } from '../Data/detail.js';
|
|
9
13
|
import { ticketDetailInputContext } from '../Data/input.js';
|
|
10
14
|
import { loadTicketView, readTicket, refreshTicket, saveTicket, ticketLoaded, watchTicket, } from '../Data/store.js';
|
|
15
|
+
import { updateTicketFrozen } from '../Data/write.js';
|
|
11
16
|
/** Overview width when the context carries none — a pipe has no terminal. */
|
|
12
17
|
const DEFAULT_COLUMNS = 80;
|
|
13
18
|
/**
|
|
@@ -20,12 +25,16 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
20
25
|
initializedKey;
|
|
21
26
|
labels;
|
|
22
27
|
status = '';
|
|
28
|
+
freezeBusy = new Set();
|
|
23
29
|
releaseStore;
|
|
24
30
|
expanded = new Set();
|
|
25
31
|
viewMode = 'full';
|
|
26
32
|
/** Visit-local: the sidebar pane and Planning document tab last chosen. */
|
|
27
33
|
sidebarTab;
|
|
28
34
|
documentKey;
|
|
35
|
+
/** Overview only (GAIA-661); a stale load after navigating away is dropped. */
|
|
36
|
+
addonsPreview;
|
|
37
|
+
addonsPreviewGeneration = 0;
|
|
29
38
|
modelMemo;
|
|
30
39
|
compact() {
|
|
31
40
|
return this.viewMode !== 'full';
|
|
@@ -69,6 +78,10 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
69
78
|
...(this.documentKey === undefined
|
|
70
79
|
? {}
|
|
71
80
|
: { documentKey: this.documentKey }),
|
|
81
|
+
...(this.addonsPreview === undefined
|
|
82
|
+
? {}
|
|
83
|
+
: { addonsPreview: this.addonsPreview }),
|
|
84
|
+
onOpenAddons: () => this.openAddons(context),
|
|
72
85
|
onSidebarTab: (tab) => live(() => {
|
|
73
86
|
this.sidebarTab = tab;
|
|
74
87
|
}),
|
|
@@ -129,8 +142,31 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
129
142
|
this.replaceReady(document);
|
|
130
143
|
context.requestDraw();
|
|
131
144
|
});
|
|
145
|
+
this.loadAddonsPreview(context);
|
|
132
146
|
context.requestDraw();
|
|
133
147
|
}
|
|
148
|
+
/** The inline card's data (GAIA-661); Overview only, loaded once per visit. */
|
|
149
|
+
loadAddonsPreview(context) {
|
|
150
|
+
this.addonsPreview = undefined;
|
|
151
|
+
if (this.tab !== 'overview')
|
|
152
|
+
return;
|
|
153
|
+
const client = context.services?.client;
|
|
154
|
+
const ticketId = context.params?.ticketId;
|
|
155
|
+
if (!client || !ticketId)
|
|
156
|
+
return;
|
|
157
|
+
const generation = ++this.addonsPreviewGeneration;
|
|
158
|
+
void readTicketAddons(client, ticketId)
|
|
159
|
+
.then((model) => {
|
|
160
|
+
if (generation !== this.addonsPreviewGeneration || !context.isActive())
|
|
161
|
+
return;
|
|
162
|
+
this.addonsPreview = model;
|
|
163
|
+
context.requestDraw();
|
|
164
|
+
})
|
|
165
|
+
// Best-effort preview (matches route.ts's optional-fetch convention): a
|
|
166
|
+
// failed fetch just leaves the card absent rather than crashing the
|
|
167
|
+
// Overview screen or surfacing an unhandled rejection.
|
|
168
|
+
.catch(() => undefined);
|
|
169
|
+
}
|
|
134
170
|
leave() {
|
|
135
171
|
this.releaseStore?.();
|
|
136
172
|
this.releaseStore = undefined;
|
|
@@ -157,8 +193,31 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
157
193
|
setLabels(labels) {
|
|
158
194
|
this.labels = labels;
|
|
159
195
|
}
|
|
160
|
-
|
|
196
|
+
/**
|
|
197
|
+
* The model's selectable keys, plus the inline addons card's row (GAIA-661
|
|
198
|
+
* D1) when the Overview preview has a message worth reaching: a Tab/arrow
|
|
199
|
+
* visit stops there and Enter opens the full send/poll screen, the same
|
|
200
|
+
* keyboard reach the Details/Stats/Related sidebar card already has via its
|
|
201
|
+
* own (Technical details) row.
|
|
202
|
+
*/
|
|
203
|
+
selectableKeys(context) {
|
|
161
204
|
const keys = this.syncModel(context).selectableKeys;
|
|
205
|
+
if (this.tab === 'overview' &&
|
|
206
|
+
this.addonsPreview &&
|
|
207
|
+
hasAddonsMessages(this.addonsPreview)) {
|
|
208
|
+
return [...keys, ADDONS_KEY];
|
|
209
|
+
}
|
|
210
|
+
return keys;
|
|
211
|
+
}
|
|
212
|
+
openAddons(context) {
|
|
213
|
+
if (!context.isActive())
|
|
214
|
+
return;
|
|
215
|
+
context.navigate?.('ticket.addons', {
|
|
216
|
+
ticketId: context.params?.ticketId ?? '',
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
select(index, context) {
|
|
220
|
+
const keys = this.selectableKeys(context);
|
|
162
221
|
if (keys.length === 0)
|
|
163
222
|
return false;
|
|
164
223
|
const next = Math.max(0, Math.min(index, keys.length - 1));
|
|
@@ -172,10 +231,16 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
172
231
|
activate(index, context) {
|
|
173
232
|
if (!this.document)
|
|
174
233
|
return false;
|
|
175
|
-
const keys = this.
|
|
234
|
+
const keys = this.selectableKeys(context);
|
|
176
235
|
const key = keys[index];
|
|
177
236
|
if (key === undefined)
|
|
178
237
|
return false;
|
|
238
|
+
if (key === ADDONS_KEY) {
|
|
239
|
+
this.selectedKey = key;
|
|
240
|
+
context.requestDraw();
|
|
241
|
+
this.openAddons(context);
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
179
244
|
const next = new Set(this.expanded);
|
|
180
245
|
if (next.has(key))
|
|
181
246
|
next.delete(key);
|
|
@@ -186,18 +251,61 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
186
251
|
context.requestDraw();
|
|
187
252
|
return true;
|
|
188
253
|
}
|
|
254
|
+
isFrozen() {
|
|
255
|
+
return this.document?.data?.attributes?.frozen === true;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* PATCH `frozen` through the write client, then re-read on the session
|
|
259
|
+
* client so the ladder and document agree with the server.
|
|
260
|
+
*/
|
|
261
|
+
toggleFrozen(context) {
|
|
262
|
+
const id = this.document?.data?.id ?? context.params?.ticketId;
|
|
263
|
+
if (!id || !context.services)
|
|
264
|
+
return true;
|
|
265
|
+
const next = !this.isFrozen();
|
|
266
|
+
const guard = this.captureLifecycle(context);
|
|
267
|
+
return runRowAction({
|
|
268
|
+
rowId: id,
|
|
269
|
+
busy: this.freezeBusy,
|
|
270
|
+
context,
|
|
271
|
+
perform: async () => {
|
|
272
|
+
try {
|
|
273
|
+
await updateTicketFrozen(context.services?.writeClient ?? context.services?.client, id, next);
|
|
274
|
+
}
|
|
275
|
+
catch (caught) {
|
|
276
|
+
throw new Error(serverMessage(caught));
|
|
277
|
+
}
|
|
278
|
+
return { message: next ? 'frozen' : 'no longer frozen' };
|
|
279
|
+
},
|
|
280
|
+
refresh: async (ctx) => {
|
|
281
|
+
refreshTicket(ctx);
|
|
282
|
+
if (!ctx.services)
|
|
283
|
+
return;
|
|
284
|
+
const document = await loadTicketDetail(ctx.services.client, id, this.includes);
|
|
285
|
+
this.replaceReadyIfCurrent(guard, saveTicket(ctx, document), ctx);
|
|
286
|
+
},
|
|
287
|
+
setStatus: (status) => {
|
|
288
|
+
this.status = status;
|
|
289
|
+
},
|
|
290
|
+
captureLifecycle: () => guard,
|
|
291
|
+
lifecycleIsCurrent: (current, ctx) => this.lifecycleIsCurrent(current, ctx),
|
|
292
|
+
failPrefix: 'freeze failed',
|
|
293
|
+
});
|
|
294
|
+
}
|
|
189
295
|
handleInput(input, context) {
|
|
190
296
|
if (super.handleInput(input, context))
|
|
191
297
|
return true;
|
|
192
298
|
if (this.state !== 'ready' || this.viewMode !== 'full')
|
|
193
299
|
return false;
|
|
194
|
-
const keys = this.
|
|
300
|
+
const keys = this.selectableKeys(context);
|
|
195
301
|
const selectedIndex = this.selectedIndexOf(keys);
|
|
196
302
|
if (input === 'y' || input === 'Y') {
|
|
197
303
|
this.status = handleTicketCopy(input, context, this.document) ?? '';
|
|
198
304
|
context.requestDraw();
|
|
199
305
|
return true;
|
|
200
306
|
}
|
|
307
|
+
if (input === 'f')
|
|
308
|
+
return this.toggleFrozen(context);
|
|
201
309
|
if ((input === 'enter' || input === ' ') && keys.length > 0)
|
|
202
310
|
return this.activate(selectedIndex, context);
|
|
203
311
|
if (keys.length > 1 && (input === 'j' || input === 'down'))
|
|
@@ -258,7 +366,7 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
258
366
|
}),
|
|
259
367
|
], this.labels),
|
|
260
368
|
};
|
|
261
|
-
const keys = this.
|
|
369
|
+
const keys = this.selectableKeys(context);
|
|
262
370
|
const selectedIndex = this.selectedIndexOf(keys);
|
|
263
371
|
return {
|
|
264
372
|
selectable: keys.length,
|
|
@@ -272,13 +380,16 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
272
380
|
actions(context) {
|
|
273
381
|
if (!this.document || this.viewMode !== 'full')
|
|
274
382
|
return [];
|
|
275
|
-
const selectable = this.
|
|
383
|
+
const selectable = this.selectableKeys(context).length;
|
|
276
384
|
return [
|
|
277
385
|
actionItem('detail-tab', 'Tab', 'section'),
|
|
278
386
|
actionItem('detail-edit', 'e', 'edit'),
|
|
279
|
-
|
|
387
|
+
// Freeze and paging before copy: at 80 columns the footer clips the
|
|
388
|
+
// tail, and `Y:Copy link` is the hint that yields.
|
|
389
|
+
actionItem('detail-freeze', 'f', this.isFrozen() ? 'unfreeze' : 'freeze'),
|
|
280
390
|
actionItem('detail-arrows', '↑↓', selectable > 1 ? 'select' : 'scroll'),
|
|
281
391
|
actionItem('detail-page', 'PgUp/PgDn', 'page'),
|
|
392
|
+
...ticketCopyActions(),
|
|
282
393
|
...(selectable > 0
|
|
283
394
|
? [actionItem('detail-enter', 'Enter/Space', 'expand')]
|
|
284
395
|
: []),
|
|
@@ -294,10 +405,13 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
294
405
|
this.modelMemo = undefined;
|
|
295
406
|
this.sidebarTab = undefined;
|
|
296
407
|
this.documentKey = undefined;
|
|
408
|
+
this.addonsPreview = undefined;
|
|
409
|
+
this.addonsPreviewGeneration += 1;
|
|
297
410
|
this.selectedKey = undefined;
|
|
298
411
|
this.initializedKey = undefined;
|
|
299
412
|
this.labels = undefined;
|
|
300
413
|
this.status = '';
|
|
414
|
+
this.freezeBusy.clear();
|
|
301
415
|
this.expanded = new Set();
|
|
302
416
|
this.viewMode = 'full';
|
|
303
417
|
}
|
|
@@ -341,7 +455,7 @@ export class TicketContentScreen extends AsyncScreen {
|
|
|
341
455
|
memo.labels === this.labels &&
|
|
342
456
|
memo.now === now)
|
|
343
457
|
return memo.model;
|
|
344
|
-
const model = ticketContentModel(document, this.tab, this.labels, now);
|
|
458
|
+
const model = ticketContentModel(document, this.tab, this.labels, now, context.services?.baseUrl);
|
|
345
459
|
this.modelMemo = { document, labels: this.labels, now, model };
|
|
346
460
|
return model;
|
|
347
461
|
}
|
|
@@ -17,6 +17,8 @@ const INCLUDES = [
|
|
|
17
17
|
'owner_user_id',
|
|
18
18
|
'sub_tickets',
|
|
19
19
|
'referenced_tickets',
|
|
20
|
+
'reviewers',
|
|
21
|
+
'pending_reviews',
|
|
20
22
|
];
|
|
21
23
|
/** Public Overview route: the ticket's overview view and its interaction state. */
|
|
22
24
|
export class TicketDetailScreen extends TicketContentScreen {
|
|
@@ -41,8 +43,8 @@ export class TicketDetailScreen extends TicketContentScreen {
|
|
|
41
43
|
fullNonInteractive(document, context) {
|
|
42
44
|
const nowSeconds = context.nowSeconds?.() ?? Math.floor(Date.now() / 1000);
|
|
43
45
|
return flattenSections([
|
|
44
|
-
...detailSections(document, this.labels, nowSeconds).filter((section) => section.heading === 'State' || section.heading === 'Labels'),
|
|
45
|
-
...sectionsForTab(document, 0, this.labels, nowSeconds),
|
|
46
|
+
...detailSections(document, this.labels, nowSeconds, context.services?.baseUrl).filter((section) => section.heading === 'State' || section.heading === 'Labels'),
|
|
47
|
+
...sectionsForTab(document, 0, this.labels, nowSeconds, context.services?.baseUrl),
|
|
46
48
|
]).lines;
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -41,8 +41,8 @@ export declare class TicketsScreen extends ListScreen<TicketRow, void> {
|
|
|
41
41
|
}, {
|
|
42
42
|
readonly key: "run";
|
|
43
43
|
readonly label: "RUN";
|
|
44
|
-
readonly width:
|
|
45
|
-
readonly fields: readonly ["derived_status"];
|
|
44
|
+
readonly width: 12;
|
|
45
|
+
readonly fields: readonly ["derived_status", "stall_reason"];
|
|
46
46
|
readonly get: (r: TicketRow) => string;
|
|
47
47
|
}, {
|
|
48
48
|
readonly key: "parent";
|
|
@@ -42,8 +42,8 @@ export declare abstract class MemberTicketsScreen extends ListScreen<TicketRow,
|
|
|
42
42
|
}, {
|
|
43
43
|
readonly key: "run";
|
|
44
44
|
readonly label: "RUN";
|
|
45
|
-
readonly width:
|
|
46
|
-
readonly fields: readonly ["derived_status"];
|
|
45
|
+
readonly width: 12;
|
|
46
|
+
readonly fields: readonly ["derived_status", "stall_reason"];
|
|
47
47
|
readonly get: (r: TicketRow) => string;
|
|
48
48
|
}, {
|
|
49
49
|
readonly key: "parent";
|
|
@@ -21,6 +21,7 @@ import { MyWorkScreen } from '../Entity/ticket/Screen/my-work.js';
|
|
|
21
21
|
import { MyWorkParentFilterScreen } from '../Entity/ticket/Screen/my-work-parent-filter-form.js';
|
|
22
22
|
import { ParentFilterScreen } from '../Entity/ticket/Screen/parent-filter-form.js';
|
|
23
23
|
import { ProjectFilterScreen } from '../Entity/ticket/Screen/project-filter-form.js';
|
|
24
|
+
import { AddonActionFormScreen, TicketAddonsScreen, } from '../Entity/ticket/Screen/ticket-addons.js';
|
|
24
25
|
import { TicketAgentsScreen } from '../Entity/ticket/Screen/ticket-agents.js';
|
|
25
26
|
import { TicketCommentsScreen } from '../Entity/ticket/Screen/ticket-comments.js';
|
|
26
27
|
import { TicketDetailScreen } from '../Entity/ticket/Screen/ticket-detail.js';
|
|
@@ -102,6 +103,8 @@ const BUILT_IN = [
|
|
|
102
103
|
TicketPlanningScreen,
|
|
103
104
|
TicketCommentsScreen,
|
|
104
105
|
TicketRunsScreen,
|
|
106
|
+
TicketAddonsScreen,
|
|
107
|
+
AddonActionFormScreen,
|
|
105
108
|
RunDetailScreen,
|
|
106
109
|
EditRunFormScreen,
|
|
107
110
|
];
|
|
@@ -11,11 +11,15 @@ const multiselectWidget = {
|
|
|
11
11
|
inlineValue: false,
|
|
12
12
|
render(ctx) {
|
|
13
13
|
const rows = [`${ctx.field.label}:`];
|
|
14
|
+
const list = ctx.list() ?? [];
|
|
14
15
|
if (ctx.error !== undefined) {
|
|
15
|
-
|
|
16
|
+
rows.push(...note(ctx.error, BODY_INDENT, ctx.width));
|
|
17
|
+
// A failed roster can still hold prefilled selections the toggle keys
|
|
18
|
+
// act on and Save writes; they stay visible so none changes unseen.
|
|
19
|
+
if (list.length === 0)
|
|
20
|
+
return rows;
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
if (list.length === 0) {
|
|
22
|
+
else if (list.length === 0) {
|
|
19
23
|
// The honest empty case: the query SUCCEEDED and there is nothing to
|
|
20
24
|
// offer. `trusted` is false when a form-level failure means no read
|
|
21
25
|
// succeeded at all, and then the popup knows nothing about this bag and
|
package/dist/src/types.d.ts
CHANGED
|
@@ -48,6 +48,11 @@ export interface DropshClient {
|
|
|
48
48
|
* declaring it costs no HTTP plumbing and no new dependency.
|
|
49
49
|
*/
|
|
50
50
|
create(type: string, body: ResourceWriteBody): Promise<unknown>;
|
|
51
|
+
/**
|
|
52
|
+
* POST a raw document to a path — dropsh's `post`, for the custom resources
|
|
53
|
+
* that are not an entity create (the addon inbox send).
|
|
54
|
+
*/
|
|
55
|
+
post(path: string, body: unknown): Promise<unknown>;
|
|
51
56
|
}
|
|
52
57
|
/** A JSON:API relationship linkage. */
|
|
53
58
|
export interface JsonApiRelationship {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaia-ai/addon-gaia-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "GAIA TUI: interactive terminal UI (dashboard, projects, tickets) as a dropsh `tui` renderer plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"zustand": "^5.0.15"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@gaia-ai/core": "^0.
|
|
32
|
+
"@gaia-ai/core": "^0.19.0",
|
|
33
|
+
"@gaia-ai/message": "^0.19.0"
|
|
33
34
|
}
|
|
34
35
|
}
|