@agentshouse/mdruntime 0.1.0-c014edb0e9d9b → 0.1.0-c01d4615bfe46
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/README.md +16 -15
- package/dist/acceptance.d.ts.map +1 -1
- package/dist/acceptance.js +1 -20
- package/dist/act-lanes.d.ts +11 -14
- package/dist/act-lanes.d.ts.map +1 -1
- package/dist/act-lanes.js +53 -5
- package/dist/actions.d.ts +1 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +88 -47
- package/dist/adapter.d.ts +20 -12
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +0 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +0 -5
- package/dist/chat-types.d.ts +0 -2
- package/dist/chat-types.d.ts.map +1 -1
- package/dist/chat-types.js +0 -2
- package/dist/client.d.ts +6 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -5
- package/dist/compile.d.ts +2 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +17 -4
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +5 -10
- package/dist/conversation-live.d.ts +13 -4
- package/dist/conversation-live.d.ts.map +1 -1
- package/dist/conversation-live.js +15 -6
- package/dist/conversation.d.ts +11 -3
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +201 -154
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +1 -4
- package/dist/durability.d.ts +1 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +4 -0
- package/dist/entry.js +1 -1
- package/dist/expectation.d.ts +25 -14
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +51 -20
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +2 -1
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +8 -3
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/install.d.ts +1 -1
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +4 -13
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +3 -5
- package/dist/locks.d.ts.map +1 -1
- package/dist/locks.js +0 -1
- package/dist/lost.d.ts.map +1 -1
- package/dist/lost.js +1 -2
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +6 -9
- package/dist/memory.d.ts +3 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +20 -7
- package/dist/messages.d.ts +9 -2
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +15 -7
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +2 -5
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +11 -5
- package/dist/opening.d.ts.map +1 -1
- package/dist/opening.js +3 -9
- package/dist/outcome.d.ts +4 -0
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +8 -2
- package/dist/overlay.d.ts +3 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +8 -4
- package/dist/parts.d.ts +2 -9
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +6 -14
- package/dist/preparation.d.ts.map +1 -1
- package/dist/preparation.js +6 -12
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +19 -7
- package/dist/questions.d.ts +0 -5
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +0 -7
- package/dist/queue.d.ts +2 -2
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +25 -30
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +41 -15
- package/dist/react.d.ts +6 -11
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +22 -4
- package/dist/readiness.d.ts +1 -1
- package/dist/readiness.d.ts.map +1 -1
- package/dist/recovery.d.ts +3 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +29 -7
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +1 -3
- package/dist/room-draft.d.ts +2 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +26 -21
- package/dist/runtime.d.ts +0 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/save.d.ts +1 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +105 -55
- package/dist/saves.d.ts.map +1 -1
- package/dist/saves.js +3 -6
- package/dist/shown.d.ts +2 -1
- package/dist/shown.d.ts.map +1 -1
- package/dist/shown.js +18 -6
- package/dist/socket/lanes.d.ts +10 -3
- package/dist/socket/lanes.d.ts.map +1 -1
- package/dist/socket/lanes.js +29 -6
- package/dist/socket.d.ts +2 -3
- package/dist/socket.d.ts.map +1 -1
- package/dist/socket.js +2 -9
- package/dist/source.d.ts +0 -7
- package/dist/source.d.ts.map +1 -1
- package/dist/store/records.d.ts +8 -5
- package/dist/store/records.d.ts.map +1 -1
- package/dist/store/records.js +12 -3
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/stored.d.ts +1 -0
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +5 -5
- package/dist/surface.d.ts +4 -3
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +11 -12
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +5 -10
- package/dist/tables.d.ts +6 -3
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +34 -10
- package/dist/tallies.d.ts.map +1 -1
- package/dist/tallies.js +1 -2
- package/dist/wire.d.ts +12 -3
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +4 -1
- package/package.json +3 -3
- package/dist/log.d.ts +0 -6
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js +0 -14
package/dist/conversation.js
CHANGED
|
@@ -29,12 +29,12 @@ export function unheldView(conversation) {
|
|
|
29
29
|
deliveryWaiting: [],
|
|
30
30
|
deliveryUnknown: [],
|
|
31
31
|
chatDraft: null,
|
|
32
|
+
dismissedSuggestion: null,
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
export const SESSION_STARTED = 'Session started';
|
|
35
36
|
const NEW_CHAT = 'new:';
|
|
36
37
|
const LISTING = 'listing';
|
|
37
|
-
const AGENTS = 'agents';
|
|
38
38
|
export const CATCHING_UP = 'catching-up';
|
|
39
39
|
export const HISTORY_CONVERSATIONS = 64;
|
|
40
40
|
export function newChat(agent) {
|
|
@@ -198,17 +198,17 @@ function withSubmitted(draft, submitted) {
|
|
|
198
198
|
const { submitted: _held, ...unsent } = draft;
|
|
199
199
|
return submitted.length === 0 ? unsent : { ...unsent, submitted };
|
|
200
200
|
}
|
|
201
|
-
function
|
|
202
|
-
return
|
|
201
|
+
export function joinedDraft(first, second) {
|
|
202
|
+
return [first, second].filter((one) => one !== '').join('\n');
|
|
203
203
|
}
|
|
204
204
|
function returned(draft, submission, others) {
|
|
205
205
|
return withSubmitted({
|
|
206
206
|
conversation: draft.conversation,
|
|
207
|
-
|
|
207
|
+
text: joinedDraft(submission.text, draft.text),
|
|
208
208
|
revision: chatDraftRevision(),
|
|
209
209
|
}, others);
|
|
210
210
|
}
|
|
211
|
-
function viewOf(alive, conversation, held, frame, draft, ended) {
|
|
211
|
+
function viewOf(alive, conversation, held, frame, draft, ended, dismissed) {
|
|
212
212
|
const facts = alive.liveOf(conversation);
|
|
213
213
|
return {
|
|
214
214
|
conversation,
|
|
@@ -231,6 +231,7 @@ function viewOf(alive, conversation, held, frame, draft, ended) {
|
|
|
231
231
|
deliveryWaiting: [...facts.deliveryWaiting],
|
|
232
232
|
deliveryUnknown: [...facts.deliveryUnknown],
|
|
233
233
|
chatDraft: draft === null || unwritten(draft) ? null : { text: draft.text, revision: draft.revision },
|
|
234
|
+
dismissedSuggestion: dismissed,
|
|
234
235
|
};
|
|
235
236
|
}
|
|
236
237
|
function sessionOf(facts, held, ended) {
|
|
@@ -250,13 +251,14 @@ function emit(alive, conversation) {
|
|
|
250
251
|
if (alive.deps.closed())
|
|
251
252
|
return;
|
|
252
253
|
for (const view of alive.views()) {
|
|
253
|
-
const { window, draft, ended } = view.held.now();
|
|
254
|
+
const { window, draft, ended, dismissed } = view.held.now();
|
|
254
255
|
if (view.conversation !== conversation || window === null)
|
|
255
256
|
continue;
|
|
256
257
|
const ready = view.ready();
|
|
257
258
|
if (ready.length === 0)
|
|
258
259
|
continue;
|
|
259
|
-
const
|
|
260
|
+
const frame = sharedFrame(view, window);
|
|
261
|
+
const value = viewOf(alive, conversation, window, frame, draft, ended, dismissed);
|
|
260
262
|
for (const watcher of ready)
|
|
261
263
|
watcher.notify(value);
|
|
262
264
|
}
|
|
@@ -302,66 +304,90 @@ function rowOf(alive, conversation) {
|
|
|
302
304
|
};
|
|
303
305
|
}
|
|
304
306
|
async function entries(alive) {
|
|
305
|
-
const
|
|
306
|
-
if (
|
|
307
|
+
const listing = await heldListing(alive);
|
|
308
|
+
if (listing === null)
|
|
309
|
+
return null;
|
|
310
|
+
const list = listing.conversations;
|
|
311
|
+
const agents = new Map(listing.agents.map((agent) => [agent.id, agent]));
|
|
312
|
+
if (list.some((entry) => !agents.has(entry.agent)))
|
|
307
313
|
return null;
|
|
308
314
|
const held = list.length === 0
|
|
309
315
|
? []
|
|
310
316
|
: await alive.deps.durably((local) => local.conversationRows(list.map(({ conversation }) => conversation)));
|
|
311
317
|
const rows = new Map(held.map((one) => [one.conversation, one]));
|
|
312
|
-
return list.map((entry) =>
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
318
|
+
return list.map((entry) => {
|
|
319
|
+
const agent = agents.get(entry.agent);
|
|
320
|
+
return {
|
|
321
|
+
conversation: entry.conversation,
|
|
322
|
+
agent: { identity: agent.id, name: agent.name, retired: agent.retired_at !== null },
|
|
323
|
+
name: entry.name,
|
|
324
|
+
created: entry.created,
|
|
325
|
+
finished: entry.finished,
|
|
326
|
+
outcome: entry.outcome,
|
|
327
|
+
waiting: entry.waiting,
|
|
328
|
+
subject: entry.subject,
|
|
329
|
+
...rowOf(alive, entry.conversation),
|
|
330
|
+
...heldFacts(rows.get(entry.conversation), entry),
|
|
331
|
+
};
|
|
332
|
+
});
|
|
323
333
|
}
|
|
324
|
-
async function
|
|
325
|
-
const
|
|
326
|
-
if (
|
|
327
|
-
return
|
|
328
|
-
return !alive.known() && alive.deps.stream() !== undefined && alive.deps.online()
|
|
334
|
+
async function heldListing(alive) {
|
|
335
|
+
const { conversationList, agentList } = await (await alive.deps.local()).facts();
|
|
336
|
+
if (conversationList !== null && agentList !== null)
|
|
337
|
+
return { conversations: conversationList, agents: agentList };
|
|
338
|
+
return !alive.known() && alive.deps.stream() !== undefined && alive.deps.online()
|
|
339
|
+
? null
|
|
340
|
+
: { conversations: [], agents: [] };
|
|
329
341
|
}
|
|
330
342
|
async function endedIn(alive, conversation) {
|
|
331
|
-
const
|
|
332
|
-
return
|
|
343
|
+
const listing = await heldListing(alive);
|
|
344
|
+
return (listing?.conversations.find((entry) => entry.conversation === conversation)?.processEnded ??
|
|
345
|
+
null);
|
|
346
|
+
}
|
|
347
|
+
function upserted(kept, set, key) {
|
|
348
|
+
const held = new Map(kept.map((one) => [key(one), one]));
|
|
349
|
+
for (const one of set)
|
|
350
|
+
held.set(key(one), { ...one });
|
|
351
|
+
return held;
|
|
333
352
|
}
|
|
334
353
|
function listChanged(alive, change) {
|
|
335
354
|
void alive.deps
|
|
336
355
|
.durably(async (local) => {
|
|
337
|
-
const { conversationList, conversationCursor } = await local.facts();
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
for (const entry of change.set) {
|
|
341
|
-
held.set(entry.conversation, { ...entry });
|
|
356
|
+
const { conversationList, agentList, conversationCursor } = await local.facts();
|
|
357
|
+
const held = upserted(change.replacing ? [] : (conversationList ?? []), change.set, (entry) => entry.conversation);
|
|
358
|
+
for (const entry of change.set)
|
|
342
359
|
alive.created(entry.conversation);
|
|
343
|
-
}
|
|
344
360
|
if (change.gone !== null)
|
|
345
361
|
held.delete(change.gone);
|
|
346
362
|
const list = [...held.values()];
|
|
363
|
+
const agents = [
|
|
364
|
+
...upserted(change.replacing ? [] : (agentList ?? []), change.agents, (agent) => agent.id).values(),
|
|
365
|
+
];
|
|
347
366
|
if (JSON.stringify(list) !== JSON.stringify(conversationList)) {
|
|
348
367
|
await local.fact('conversationList', list);
|
|
349
368
|
}
|
|
369
|
+
if (JSON.stringify(agents) !== JSON.stringify(agentList)) {
|
|
370
|
+
await local.fact('agentList', agents);
|
|
371
|
+
}
|
|
350
372
|
if (change.cursor !== undefined) {
|
|
351
373
|
if (change.cursor !== conversationCursor) {
|
|
352
374
|
await local.fact('conversationCursor', change.cursor);
|
|
353
375
|
}
|
|
354
376
|
alive.deps.stream()?.hold(change.cursor);
|
|
355
377
|
}
|
|
356
|
-
return list;
|
|
378
|
+
return { conversations: list, agents };
|
|
379
|
+
})
|
|
380
|
+
.catch(async () => {
|
|
381
|
+
const { conversationList, agentList } = await (await alive.deps.local()).facts();
|
|
382
|
+
return { conversations: conversationList ?? [], agents: agentList ?? [] };
|
|
357
383
|
})
|
|
358
|
-
.
|
|
359
|
-
.then((list) => {
|
|
384
|
+
.then((listing) => {
|
|
360
385
|
if (alive.deps.closed() || change.paged === true)
|
|
361
386
|
return;
|
|
387
|
+
const list = listing.conversations;
|
|
362
388
|
endedAnew(alive, list);
|
|
363
389
|
if (change.cursor !== undefined) {
|
|
364
|
-
alive.held.set({ listKnown: true });
|
|
390
|
+
alive.held.set({ listKnown: true, openingListed: true });
|
|
365
391
|
settleBehind(alive, list);
|
|
366
392
|
openingEnded(alive);
|
|
367
393
|
alive.deps.settled();
|
|
@@ -369,11 +395,12 @@ function listChanged(alive, change) {
|
|
|
369
395
|
emitList(alive);
|
|
370
396
|
if (!alive.known())
|
|
371
397
|
return;
|
|
372
|
-
retiredDrafts(alive,
|
|
373
|
-
const { replicated } = alive.held.now();
|
|
374
|
-
if (change.cursor === undefined
|
|
375
|
-
|
|
376
|
-
list.some(({ conversation }) => !replicated.has(conversation))
|
|
398
|
+
retiredDrafts(alive, listing);
|
|
399
|
+
const { replicated, openingRead } = alive.held.now();
|
|
400
|
+
if (change.cursor === undefined
|
|
401
|
+
? list.length !== replicated.size ||
|
|
402
|
+
list.some(({ conversation }) => !replicated.has(conversation))
|
|
403
|
+
: openingRead) {
|
|
377
404
|
alive.deps.again();
|
|
378
405
|
}
|
|
379
406
|
}, uncaught);
|
|
@@ -389,23 +416,23 @@ function endedAnew(alive, list) {
|
|
|
389
416
|
emit(alive, view.conversation);
|
|
390
417
|
}
|
|
391
418
|
}
|
|
392
|
-
function
|
|
393
|
-
const reading =
|
|
419
|
+
function shownListing(alive, work) {
|
|
420
|
+
const reading = heldListing(alive);
|
|
394
421
|
alive.inOrder(async () => {
|
|
395
|
-
const
|
|
422
|
+
const listing = await reading.catch((error) => {
|
|
396
423
|
uncaught(error);
|
|
397
424
|
return null;
|
|
398
425
|
});
|
|
399
|
-
if (
|
|
426
|
+
if (listing === null || alive.deps.closed())
|
|
400
427
|
return;
|
|
401
|
-
work(
|
|
428
|
+
work(listing);
|
|
402
429
|
});
|
|
403
430
|
}
|
|
404
431
|
async function told(alive) {
|
|
405
432
|
try {
|
|
406
433
|
while (alive.held.now().listOwed && !alive.deps.closed()) {
|
|
407
434
|
alive.held.set({ listOwed: false });
|
|
408
|
-
const value = await untilAnswered(retrying(alive.deps.retries, 'conversations', LISTING, () => entries(alive)), alive.closing);
|
|
435
|
+
const value = await untilAnswered(retrying(alive.deps.retries, 'conversations', LISTING, () => entries(alive)), alive.closing, () => true, alive.deps.recovery);
|
|
409
436
|
if (alive.deps.closed())
|
|
410
437
|
return;
|
|
411
438
|
if (value === null)
|
|
@@ -443,66 +470,46 @@ export function conversationsLearned(alive) {
|
|
|
443
470
|
return;
|
|
444
471
|
if (alive.listeners.waiting())
|
|
445
472
|
tellList(alive);
|
|
446
|
-
if (!alive.agentListeners.waiting())
|
|
473
|
+
if (!alive.agentListeners.waiting() && !alive.listedListeners.waiting())
|
|
447
474
|
return;
|
|
448
|
-
|
|
475
|
+
shownListing(alive, (listing) => {
|
|
476
|
+
alive.agentListeners.welcome(agentsOf(listing));
|
|
477
|
+
alive.listedListeners.welcome(structuredClone(listing.agents));
|
|
478
|
+
});
|
|
449
479
|
}
|
|
450
|
-
function
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
identity,
|
|
464
|
-
name: agent.name,
|
|
465
|
-
cli: held.cli,
|
|
466
|
-
environment: structuredClone(held.environment),
|
|
467
|
-
};
|
|
468
|
-
})
|
|
480
|
+
function agentsOf(listing) {
|
|
481
|
+
return listing.agents
|
|
482
|
+
.filter((agent) => agent.retired_at === null)
|
|
483
|
+
.map((agent) => ({
|
|
484
|
+
identity: agent.id,
|
|
485
|
+
name: agent.name,
|
|
486
|
+
cli: agent.cli,
|
|
487
|
+
environment: {
|
|
488
|
+
identity: agent.environment,
|
|
489
|
+
name: agent.environment_name,
|
|
490
|
+
state: agent.environment_connected ? 'online' : 'offline',
|
|
491
|
+
},
|
|
492
|
+
}))
|
|
469
493
|
.sort((left, right) => left.name === right.name
|
|
470
494
|
? left.identity.localeCompare(right.identity)
|
|
471
495
|
: left.name.localeCompare(right.name));
|
|
472
496
|
}
|
|
473
|
-
function readAgents(alive) {
|
|
474
|
-
const stream = alive.deps.stream();
|
|
475
|
-
if (stream?.agents === undefined || !alive.deps.online() || alive.held.now().agentsReading)
|
|
476
|
-
return;
|
|
477
|
-
const { agents: read } = stream;
|
|
478
|
-
const { agentListeners } = alive;
|
|
479
|
-
alive.held.set({ agentsReading: true });
|
|
480
|
-
void alive.deps.recovery
|
|
481
|
-
.attempt('agents', async () => {
|
|
482
|
-
if (!alive.deps.online() || (!agentListeners.waiting() && !agentListeners.told())) {
|
|
483
|
-
return 'done';
|
|
484
|
-
}
|
|
485
|
-
const listed = await retrying(alive.deps.retries, 'conversations', AGENTS, read)();
|
|
486
|
-
if (listed === null)
|
|
487
|
-
return 'done';
|
|
488
|
-
alive.held.set({ listedAgents: listed });
|
|
489
|
-
emitAgents(alive);
|
|
490
|
-
return 'done';
|
|
491
|
-
})
|
|
492
|
-
.finally(() => {
|
|
493
|
-
alive.held.set({ agentsReading: false });
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
497
|
function emitAgents(alive) {
|
|
497
|
-
|
|
498
|
+
const { agentListeners, listedListeners } = alive;
|
|
499
|
+
if (alive.deps.closed() || (!agentListeners.told() && !listedListeners.told()))
|
|
498
500
|
return;
|
|
499
|
-
|
|
500
|
-
const value =
|
|
501
|
+
shownListing(alive, (listing) => {
|
|
502
|
+
const value = agentsOf(listing);
|
|
501
503
|
const shown = JSON.stringify(value);
|
|
502
|
-
if (shown
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
504
|
+
if (shown !== alive.held.now().agentsShown) {
|
|
505
|
+
alive.held.set({ agentsShown: shown });
|
|
506
|
+
agentListeners.tell(value);
|
|
507
|
+
}
|
|
508
|
+
const listed = JSON.stringify(listing.agents);
|
|
509
|
+
if (listed !== alive.held.now().listedShown) {
|
|
510
|
+
alive.held.set({ listedShown: listed });
|
|
511
|
+
listedListeners.tell(structuredClone(listing.agents));
|
|
512
|
+
}
|
|
506
513
|
});
|
|
507
514
|
}
|
|
508
515
|
function setLive(alive, conversation, next) {
|
|
@@ -516,11 +523,11 @@ function setLive(alive, conversation, next) {
|
|
|
516
523
|
after.asked !== before.asked)
|
|
517
524
|
tellSoon(alive);
|
|
518
525
|
}
|
|
519
|
-
function retiredChat(conversation,
|
|
526
|
+
function retiredChat(conversation, listing) {
|
|
520
527
|
if (!conversation.startsWith(NEW_CHAT))
|
|
521
528
|
return false;
|
|
522
529
|
const agent = conversation.slice(NEW_CHAT.length);
|
|
523
|
-
return
|
|
530
|
+
return listing.agents.some((one) => one.id === agent && one.retired_at !== null);
|
|
524
531
|
}
|
|
525
532
|
function live(alive, conversation, change) {
|
|
526
533
|
alive.factsHeard(conversation, FACTS.filter((one) => one in change));
|
|
@@ -573,19 +580,13 @@ function handReplicated(alive) {
|
|
|
573
580
|
}
|
|
574
581
|
async function remove(alive, leaving) {
|
|
575
582
|
await alive.deps.durably(async (local) => {
|
|
576
|
-
const kept = new Set(
|
|
577
|
-
...(await local.conversations(leaving)).map(({ conversation }) => conversation),
|
|
578
|
-
...(await local.chatDrafts())
|
|
579
|
-
.filter(({ conversation }) => leaving.includes(conversation))
|
|
580
|
-
.map(({ conversation }) => conversation),
|
|
581
|
-
]);
|
|
582
|
-
await local.dropConversations(leaving);
|
|
583
|
+
const kept = new Set(await local.dropConversations(leaving));
|
|
583
584
|
const changed = [];
|
|
584
585
|
for (const conversation of leaving) {
|
|
585
586
|
if (kept.has(conversation) || alive.liveHeld(conversation) !== undefined) {
|
|
586
587
|
changed.push(conversation);
|
|
587
588
|
}
|
|
588
|
-
|
|
589
|
+
heldInViews(alive, conversation, { draft: null, dismissed: null });
|
|
589
590
|
alive.forget(conversation);
|
|
590
591
|
setLive(alive, conversation, null);
|
|
591
592
|
await slide(alive, local, conversation, null);
|
|
@@ -614,7 +615,7 @@ async function readsOf(local, conversations) {
|
|
|
614
615
|
return new Map((await local.conversations(conversations)).map((held) => [held.conversation, held]));
|
|
615
616
|
}
|
|
616
617
|
function retiredDrafts(alive, list) {
|
|
617
|
-
if (!list.some((
|
|
618
|
+
if (!list.agents.some((agent) => agent.retired_at !== null))
|
|
618
619
|
return;
|
|
619
620
|
void alive.deps
|
|
620
621
|
.local()
|
|
@@ -810,19 +811,27 @@ function heard(alive, event) {
|
|
|
810
811
|
emit(alive, conversation);
|
|
811
812
|
}
|
|
812
813
|
async function kept(alive, local, conversation, following) {
|
|
813
|
-
const
|
|
814
|
-
if (
|
|
814
|
+
const draft = following === null || empty(following) ? null : following;
|
|
815
|
+
if (draft === null)
|
|
815
816
|
await local.dropChatDraft(conversation);
|
|
816
817
|
else
|
|
817
|
-
await local.keepChatDrafts([
|
|
818
|
-
|
|
818
|
+
await local.keepChatDrafts([draft]);
|
|
819
|
+
heldInViews(alive, conversation, { draft });
|
|
819
820
|
}
|
|
820
|
-
function
|
|
821
|
+
function heldInViews(alive, conversation, held) {
|
|
821
822
|
for (const view of alive.views()) {
|
|
822
823
|
if (view.conversation === conversation)
|
|
823
|
-
view.held.set(
|
|
824
|
+
view.held.set(held);
|
|
824
825
|
}
|
|
825
826
|
}
|
|
827
|
+
async function factOf(local, name) {
|
|
828
|
+
return Object.fromEntries((await local.conversationFacts())
|
|
829
|
+
.filter((fact) => fact.name === name)
|
|
830
|
+
.map(({ conversation, value }) => [conversation, value]));
|
|
831
|
+
}
|
|
832
|
+
async function dismissedIn(local, conversation) {
|
|
833
|
+
return (await factOf(local, 'dismissedSuggestion'))[conversation] ?? null;
|
|
834
|
+
}
|
|
826
835
|
async function draftAt(local, conversation) {
|
|
827
836
|
return (await local.chatDraft(conversation)) ?? undefined;
|
|
828
837
|
}
|
|
@@ -853,9 +862,9 @@ function moved(alive, agent, operation, to) {
|
|
|
853
862
|
: [{ ...unsent, conversation: to }];
|
|
854
863
|
const left = { ...(taken.length === 0 ? unsent : blank), moves: [...earlier, operation] };
|
|
855
864
|
await local.keepChatDrafts([left, ...taken]);
|
|
856
|
-
|
|
865
|
+
heldInViews(alive, from, { draft: left });
|
|
857
866
|
for (const one of taken)
|
|
858
|
-
|
|
867
|
+
heldInViews(alive, to, { draft: one });
|
|
859
868
|
alive.deps.publish(conversationChangeSet([from, to]));
|
|
860
869
|
});
|
|
861
870
|
}
|
|
@@ -886,7 +895,7 @@ async function submitted(alive, conversation, operation, draft) {
|
|
|
886
895
|
});
|
|
887
896
|
return submission;
|
|
888
897
|
}
|
|
889
|
-
async function dispatched(alive, conversation, submission) {
|
|
898
|
+
async function dispatched(alive, conversation, submission, resent = false) {
|
|
890
899
|
const dispatch = alive.sendingBegan(submission.operation);
|
|
891
900
|
try {
|
|
892
901
|
const result = await invoke(alive, 'conversations/send', conversation, submission.operation, { text: submission.text }, { step: 'sending', instance: `message ${submission.operation}` });
|
|
@@ -897,6 +906,7 @@ async function dispatched(alive, conversation, submission) {
|
|
|
897
906
|
alive.deps.unanswered();
|
|
898
907
|
return result;
|
|
899
908
|
}
|
|
909
|
+
alive.deps.heard(submission.operation, resent);
|
|
900
910
|
const turn = answered(result, 'message_id');
|
|
901
911
|
await withDraft(alive, conversation, async (current, local) => {
|
|
902
912
|
const held = current?.submitted?.find((one) => one.operation === submission.operation);
|
|
@@ -938,7 +948,7 @@ export function conversationSurface(alive) {
|
|
|
938
948
|
return alive.deps.durably(async (local) => {
|
|
939
949
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before, phrase);
|
|
940
950
|
const total = asked.total ? await local.messageCount(conversation, phrase) : null;
|
|
941
|
-
return structuredClone(viewOf(alive, conversation, messages, frameOf(asked, messages, more, total), (await local.chatDraft(conversation)) ?? null, await endedIn(alive, conversation)));
|
|
951
|
+
return structuredClone(viewOf(alive, conversation, messages, frameOf(asked, messages, more, total), (await local.chatDraft(conversation)) ?? null, await endedIn(alive, conversation), await dismissedIn(local, conversation)));
|
|
942
952
|
});
|
|
943
953
|
},
|
|
944
954
|
async create(input) {
|
|
@@ -946,7 +956,7 @@ export function conversationSurface(alive) {
|
|
|
946
956
|
const conversation = answered(result, 'conversation_id');
|
|
947
957
|
if (conversation === null)
|
|
948
958
|
return result;
|
|
949
|
-
const listed = (await
|
|
959
|
+
const listed = (await heldListing(alive))?.conversations ?? [];
|
|
950
960
|
if (!listed.some((entry) => entry.conversation === conversation)) {
|
|
951
961
|
alive.creating(conversation);
|
|
952
962
|
}
|
|
@@ -1019,33 +1029,44 @@ export function conversationSurface(alive) {
|
|
|
1019
1029
|
return alive.deps.durably((local) => local.fact('chatPins', [...figures]));
|
|
1020
1030
|
},
|
|
1021
1031
|
async openedTurns() {
|
|
1022
|
-
return (await
|
|
1032
|
+
return factOf(await alive.deps.local(), 'openedTurn');
|
|
1023
1033
|
},
|
|
1024
1034
|
openTurn(conversation, turn) {
|
|
1035
|
+
return alive.deps.durably((local) => local.keepConversationFact({ conversation, name: 'openedTurn', value: turn }));
|
|
1036
|
+
},
|
|
1037
|
+
dismissSuggestion(conversation, suggestion) {
|
|
1025
1038
|
return alive.deps.durably(async (local) => {
|
|
1026
|
-
|
|
1027
|
-
|
|
1039
|
+
if ((await dismissedIn(local, conversation)) === suggestion)
|
|
1040
|
+
return;
|
|
1041
|
+
await local.keepConversationFact({
|
|
1042
|
+
conversation,
|
|
1043
|
+
name: 'dismissedSuggestion',
|
|
1044
|
+
value: suggestion,
|
|
1045
|
+
});
|
|
1046
|
+
heldInViews(alive, conversation, { dismissed: suggestion });
|
|
1047
|
+
alive.deps.publish(conversationChangeSet([conversation]));
|
|
1028
1048
|
});
|
|
1029
1049
|
},
|
|
1030
1050
|
};
|
|
1031
1051
|
}
|
|
1052
|
+
function rewritten(alive, conversation, text, revision = chatDraftRevision()) {
|
|
1053
|
+
return withDraft(alive, conversation, (current) => ({
|
|
1054
|
+
conversation,
|
|
1055
|
+
text: text(current?.text ?? ''),
|
|
1056
|
+
revision,
|
|
1057
|
+
...(current === undefined ? {} : pending(current)),
|
|
1058
|
+
}));
|
|
1059
|
+
}
|
|
1032
1060
|
export function chatDraftSurface(alive) {
|
|
1033
1061
|
return {
|
|
1034
|
-
write(conversation, draft, revision
|
|
1035
|
-
return
|
|
1036
|
-
conversation,
|
|
1037
|
-
text: draft.text,
|
|
1038
|
-
revision,
|
|
1039
|
-
...(current === undefined ? {} : pending(current)),
|
|
1040
|
-
}));
|
|
1062
|
+
write(conversation, draft, revision) {
|
|
1063
|
+
return rewritten(alive, conversation, () => draft.text, revision);
|
|
1041
1064
|
},
|
|
1042
1065
|
prepend(conversation, draft) {
|
|
1043
|
-
return
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
...(current === undefined ? {} : pending(current)),
|
|
1048
|
-
}));
|
|
1066
|
+
return rewritten(alive, conversation, (held) => joinedDraft(draft.text, held));
|
|
1067
|
+
},
|
|
1068
|
+
append(conversation, draft) {
|
|
1069
|
+
return rewritten(alive, conversation, (held) => joinedDraft(held, draft.text));
|
|
1049
1070
|
},
|
|
1050
1071
|
discard(conversation) {
|
|
1051
1072
|
return withDraft(alive, conversation, (current) => current === undefined
|
|
@@ -1055,31 +1076,34 @@ export function chatDraftSurface(alive) {
|
|
|
1055
1076
|
};
|
|
1056
1077
|
}
|
|
1057
1078
|
export async function conversationsOpened(alive, local) {
|
|
1058
|
-
const { conversationList, conversationCursor } = await local.facts();
|
|
1059
|
-
if (conversationList === null || alive.known())
|
|
1079
|
+
const { conversationList, agentList, conversationCursor } = await local.facts();
|
|
1080
|
+
if (conversationList === null || agentList === null || alive.known())
|
|
1060
1081
|
return;
|
|
1061
1082
|
alive.deps.stream()?.hold(conversationCursor);
|
|
1062
1083
|
conversationsLearned(alive);
|
|
1063
1084
|
}
|
|
1085
|
+
export function reconcileOpening(alive) {
|
|
1086
|
+
alive.held.set({ openingRead: true });
|
|
1087
|
+
return reconcileConversations(alive);
|
|
1088
|
+
}
|
|
1064
1089
|
export async function reconcileConversations(alive) {
|
|
1065
1090
|
if (!alive.known())
|
|
1066
1091
|
return;
|
|
1067
1092
|
const local = await alive.deps.local();
|
|
1068
|
-
const [held,
|
|
1093
|
+
const [held, stored, { conversationList, agentList }] = await Promise.all([
|
|
1069
1094
|
local.conversations(),
|
|
1070
|
-
local.
|
|
1095
|
+
local.storedConversations(),
|
|
1071
1096
|
local.facts(),
|
|
1072
1097
|
]);
|
|
1073
1098
|
const list = conversationList ?? [];
|
|
1099
|
+
const listing = { conversations: list, agents: agentList ?? [] };
|
|
1074
1100
|
const entries = new Map(list.map((entry) => [entry.conversation, entry]));
|
|
1075
1101
|
const named = new Set(entries.keys());
|
|
1076
1102
|
const reads = new Map(held.map((one) => [one.conversation, one]));
|
|
1077
1103
|
const { replicated } = alive.held.now();
|
|
1078
|
-
const leaving = [
|
|
1079
|
-
...new Set([...replicated, ...reads.keys(), ...kept.map(({ conversation }) => conversation)]),
|
|
1080
|
-
].filter((conversation) => !named.has(conversation) &&
|
|
1104
|
+
const leaving = [...new Set([...replicated, ...stored])].filter((conversation) => !named.has(conversation) &&
|
|
1081
1105
|
!alive.isCreating(conversation) &&
|
|
1082
|
-
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation,
|
|
1106
|
+
(!conversation.startsWith(NEW_CHAT) || retiredChat(conversation, listing)));
|
|
1083
1107
|
for (const conversation of named) {
|
|
1084
1108
|
if (!replicated.has(conversation) &&
|
|
1085
1109
|
missed(alive, conversation, reads.get(conversation), entries.get(conversation))) {
|
|
@@ -1114,6 +1138,17 @@ export async function catchUpConversations(alive, progress) {
|
|
|
1114
1138
|
if (!alive.current())
|
|
1115
1139
|
progress.complete = false;
|
|
1116
1140
|
}
|
|
1141
|
+
export async function holdsSubmission(alive, operation) {
|
|
1142
|
+
if (alive.sending(operation))
|
|
1143
|
+
return true;
|
|
1144
|
+
const local = await alive.deps.local();
|
|
1145
|
+
for (const { conversation } of await local.chatDrafts()) {
|
|
1146
|
+
const held = (await local.chatDraft(conversation))?.submitted;
|
|
1147
|
+
if (held?.some((one) => one.operation === operation && one.turn === null) === true)
|
|
1148
|
+
return true;
|
|
1149
|
+
}
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1117
1152
|
export async function resendConversations(alive, progress) {
|
|
1118
1153
|
const local = await alive.deps.local();
|
|
1119
1154
|
const tried = new Set();
|
|
@@ -1125,7 +1160,7 @@ export async function resendConversations(alive, progress) {
|
|
|
1125
1160
|
if (alive.deps.closed())
|
|
1126
1161
|
return;
|
|
1127
1162
|
tried.add(submission.operation);
|
|
1128
|
-
const result = await dispatched(alive, conversation, submission);
|
|
1163
|
+
const result = await dispatched(alive, conversation, submission, true);
|
|
1129
1164
|
if (result.kind === 'revoked-authorization')
|
|
1130
1165
|
return;
|
|
1131
1166
|
if (result.kind === 'transport-uncertainty') {
|
|
@@ -1151,6 +1186,7 @@ export function watchConversation(alive, conversation, options, deliver) {
|
|
|
1151
1186
|
const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
|
|
1152
1187
|
held.set({ draft: (await local.chatDraft(conversation)) ?? null });
|
|
1153
1188
|
held.set({ ended: await endedIn(alive, conversation) });
|
|
1189
|
+
held.set({ dismissed: await dismissedIn(local, conversation) });
|
|
1154
1190
|
held.set({ window: messages });
|
|
1155
1191
|
held.set({ more });
|
|
1156
1192
|
held.set({ total: asked.total ? await local.messageCount(conversation) : null });
|
|
@@ -1158,9 +1194,10 @@ export function watchConversation(alive, conversation, options, deliver) {
|
|
|
1158
1194
|
.then(() => {
|
|
1159
1195
|
if (alive.deps.closed() || !view.admit(watcher))
|
|
1160
1196
|
return;
|
|
1161
|
-
const { window, draft, ended } = held.now();
|
|
1197
|
+
const { window, draft, ended, dismissed } = held.now();
|
|
1162
1198
|
const shown = window ?? [];
|
|
1163
|
-
|
|
1199
|
+
const frame = sharedFrame(view, shown);
|
|
1200
|
+
watcher.notify(viewOf(alive, conversation, shown, frame, draft, ended, dismissed));
|
|
1164
1201
|
})
|
|
1165
1202
|
.catch(() => { });
|
|
1166
1203
|
return () => {
|
|
@@ -1176,9 +1213,13 @@ export function watchConversationList(alive, deliver) {
|
|
|
1176
1213
|
export function watchConversationAgents(alive, deliver) {
|
|
1177
1214
|
alive.agentListeners.join(deliver);
|
|
1178
1215
|
conversationsLearned(alive);
|
|
1179
|
-
readAgents(alive);
|
|
1180
1216
|
return () => alive.agentListeners.leave(deliver);
|
|
1181
1217
|
}
|
|
1218
|
+
export function watchListedAgents(alive, deliver) {
|
|
1219
|
+
alive.listedListeners.join(deliver);
|
|
1220
|
+
conversationsLearned(alive);
|
|
1221
|
+
return () => alive.listedListeners.leave(deliver);
|
|
1222
|
+
}
|
|
1182
1223
|
export function conversationsChanged(alive, set) {
|
|
1183
1224
|
for (const conversation of set.conversations)
|
|
1184
1225
|
emit(alive, conversation);
|
|
@@ -1190,26 +1231,32 @@ export function receiveConversationEvent(alive, event) {
|
|
|
1190
1231
|
if (event.whole)
|
|
1191
1232
|
alive.relistBegun();
|
|
1192
1233
|
if (alive.relisting())
|
|
1193
|
-
alive.relistHeard(event.entries);
|
|
1234
|
+
alive.relistHeard(event.entries, event.agents);
|
|
1194
1235
|
if (event.more && alive.relisting())
|
|
1195
1236
|
return;
|
|
1196
1237
|
const whole = alive.relistTaken();
|
|
1197
1238
|
listChanged(alive, {
|
|
1198
1239
|
replacing: whole !== null,
|
|
1199
|
-
set: whole === null ? event.entries : [...whole.values()],
|
|
1240
|
+
set: whole === null ? event.entries : [...whole.conversations.values()],
|
|
1241
|
+
agents: whole === null ? event.agents : [...whole.agents.values()],
|
|
1200
1242
|
gone: null,
|
|
1201
1243
|
...(event.more ? { paged: true } : { cursor: event.cursor }),
|
|
1202
1244
|
});
|
|
1203
1245
|
return;
|
|
1204
1246
|
}
|
|
1205
1247
|
if (event.kind === 'listed') {
|
|
1206
|
-
alive.relistHeard([event.entry]);
|
|
1207
|
-
listChanged(alive, { replacing: false, set: [event.entry], gone: null });
|
|
1248
|
+
alive.relistHeard([event.entry], []);
|
|
1249
|
+
listChanged(alive, { replacing: false, set: [event.entry], agents: [], gone: null });
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
if (event.kind === 'agent') {
|
|
1253
|
+
alive.relistHeard([], [event.agent]);
|
|
1254
|
+
listChanged(alive, { replacing: false, set: [], agents: [event.agent], gone: null });
|
|
1208
1255
|
return;
|
|
1209
1256
|
}
|
|
1210
1257
|
if (event.kind === 'unlisted') {
|
|
1211
1258
|
alive.relistDropped(event.conversation);
|
|
1212
|
-
listChanged(alive, { replacing: false, set: [], gone: event.conversation });
|
|
1259
|
+
listChanged(alive, { replacing: false, set: [], agents: [], gone: event.conversation });
|
|
1213
1260
|
return;
|
|
1214
1261
|
}
|
|
1215
1262
|
heard(alive, event);
|
package/dist/discovery.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,cAAc,EACd,MAAM,EAEP,MAAM,cAAc,CAAC;AAOtB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAsB1E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CA0CpC;AAYD,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,iBAI1F;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,cAAc,EACd,MAAM,EAEP,MAAM,cAAc,CAAC;AAOtB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAsB1E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CA0CpC;AAYD,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,iBAI1F;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC,CA+D3C"}
|