@agentshouse/mdruntime-adapter 0.1.0-cd028205a5103 → 0.1.0-cd0511bd2d033

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 (72) hide show
  1. package/README.md +2 -2
  2. package/dist/actions.d.ts +4 -5
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +13 -322
  5. package/dist/adapter.d.ts +1 -0
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +285 -205
  8. package/dist/app-reference.d.ts +2 -0
  9. package/dist/app-reference.d.ts.map +1 -0
  10. package/dist/app-reference.js +2 -0
  11. package/dist/crockford.d.ts +4 -0
  12. package/dist/crockford.d.ts.map +1 -0
  13. package/dist/crockford.js +3 -0
  14. package/dist/discovery.d.ts +25 -14
  15. package/dist/discovery.d.ts.map +1 -1
  16. package/dist/discovery.js +104 -51
  17. package/dist/history.d.ts +12 -0
  18. package/dist/history.d.ts.map +1 -0
  19. package/dist/history.js +92 -0
  20. package/dist/house-model.d.ts +719 -0
  21. package/dist/house-model.d.ts.map +1 -0
  22. package/dist/house-model.js +393 -0
  23. package/dist/index.d.ts +11 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +10 -0
  26. package/dist/model.d.ts +6 -3
  27. package/dist/model.d.ts.map +1 -1
  28. package/dist/model.js +15 -30
  29. package/dist/part.d.ts +14 -0
  30. package/dist/part.d.ts.map +1 -0
  31. package/dist/part.js +90 -0
  32. package/dist/read.d.ts +59 -41
  33. package/dist/read.d.ts.map +1 -1
  34. package/dist/read.js +254 -231
  35. package/dist/refusal.d.ts +2 -8
  36. package/dist/refusal.d.ts.map +1 -1
  37. package/dist/refusal.js +6 -14
  38. package/dist/room-stream.d.ts +19 -0
  39. package/dist/room-stream.d.ts.map +1 -0
  40. package/dist/room-stream.js +57 -0
  41. package/dist/room-types.d.ts +7 -0
  42. package/dist/room-types.d.ts.map +1 -0
  43. package/dist/room-types.js +125 -0
  44. package/dist/search.d.ts +5 -0
  45. package/dist/search.d.ts.map +1 -0
  46. package/dist/search.js +47 -0
  47. package/dist/site.d.ts +1 -1
  48. package/dist/site.d.ts.map +1 -1
  49. package/dist/site.js +130 -106
  50. package/dist/stream.d.ts +12 -12
  51. package/dist/stream.d.ts.map +1 -1
  52. package/dist/stream.js +204 -151
  53. package/dist/transport.d.ts +92 -24
  54. package/dist/transport.d.ts.map +1 -1
  55. package/dist/transport.js +55 -9
  56. package/dist/upload.d.ts +12 -0
  57. package/dist/upload.d.ts.map +1 -0
  58. package/dist/upload.js +63 -0
  59. package/dist/version.d.ts +1 -0
  60. package/dist/version.d.ts.map +1 -1
  61. package/dist/version.js +1 -1
  62. package/dist/write.d.ts +20 -10
  63. package/dist/write.d.ts.map +1 -1
  64. package/dist/write.js +162 -54
  65. package/package.json +9 -6
  66. package/AGENTS.md +0 -244
  67. package/dist/gather.d.ts +0 -3
  68. package/dist/gather.d.ts.map +0 -1
  69. package/dist/gather.js +0 -40
  70. package/dist/links.d.ts +0 -20
  71. package/dist/links.d.ts.map +0 -1
  72. package/dist/links.js +0 -104
package/dist/stream.js CHANGED
@@ -1,36 +1,95 @@
1
- import { acceptedMessage } from './actions.js';
2
- import { headChange } from './read.js';
3
- import { roomVersion } from './version.js';
4
- const HELD_FRAMES_MAX = 256;
1
+ import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
2
+ import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
3
+ import { streamedModels } from './model.js';
4
+ import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
5
+ import { houseDoorRoute, } from './transport.js';
6
+ import { DECIMAL, roomVersion } from './version.js';
5
7
  function turnOperation(frame) {
6
8
  const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
7
9
  return structuredClone(operation);
8
10
  }
11
+ async function houseAgents(transport) {
12
+ const answer = await transport.door(houseDoorRoute('agents/read'), {});
13
+ const agents = answer.status === 200 ? answer.body?.agents : null;
14
+ if (!Array.isArray(agents))
15
+ return null;
16
+ return agents.flatMap((one) => {
17
+ const { id, name, retired_at: retired } = (one ?? {});
18
+ return typeof id === 'string' && typeof name === 'string'
19
+ ? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
20
+ : [];
21
+ });
22
+ }
9
23
  function listedConversation(listed) {
10
24
  return {
11
25
  conversation: listed.conversation_id,
12
26
  agent: listed.agent_id,
27
+ agentName: listed.agent_name,
28
+ agentRetired: listed.agent_retired,
13
29
  name: listed.name,
14
30
  created: listed.created_at,
15
31
  finished: listed.finished_at,
16
32
  outcome: listed.outcome,
33
+ waiting: listed.waiting,
34
+ newest: listed.newest === null ? null : cursorPosition(listed.newest),
35
+ processEnded: listed.process_ended_at,
17
36
  };
18
37
  }
19
38
  function position(value) {
20
- if (!/^(?:0|[1-9][0-9]*)$/.test(value))
39
+ if (!DECIMAL.test(value))
21
40
  return null;
22
41
  return BigInt(value);
23
42
  }
24
- export function houseNotifications(transport, mode) {
43
+ function* changed(tracked, entries, version, schemas) {
44
+ const answer = answering();
45
+ for (const entry of entries) {
46
+ yield ROW_WEIGHT + (entry.text?.length ?? 0);
47
+ if (entry.kind === 'folder') {
48
+ folded(answer, entry.path, entry.removed === true);
49
+ continue;
50
+ }
51
+ if (entry.path === tracked.schema)
52
+ schemas.set(entry.path, entry);
53
+ forgotten(answer, entry.path);
54
+ if (entry.kind === 'removed') {
55
+ answer.removals.add(entry.path);
56
+ continue;
57
+ }
58
+ const binary = binaryFileOf(entry);
59
+ if (binary === undefined)
60
+ answer.documents.set(entry.path, entry.text ?? '');
61
+ else if (binary !== null)
62
+ answer.binaryFiles.set(entry.path, binary);
63
+ if (binary === undefined && entry.facts !== undefined)
64
+ answer.facts.set(entry.path, entry.facts);
65
+ const revision = entry.revision ?? binary?.sha256;
66
+ if (revision !== undefined)
67
+ revised(answer, entry.path, revision);
68
+ const head = headChange(entry);
69
+ if (head)
70
+ answer.changes.set(entry.path, head);
71
+ }
72
+ return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
73
+ }
74
+ async function changePage(tracked, entries, version, mode) {
75
+ const schemas = new Map();
76
+ const page = await stepped(changed(tracked, entries, version, schemas));
77
+ const models = await streamedModels(schemas, tracked, mode);
78
+ return models === undefined ? page : { ...page, models };
79
+ }
80
+ export function houseNotifications(transport, mode, discovering) {
25
81
  const stream = transport.stream;
26
- const lines = new Map();
27
- const locators = new Map();
82
+ const staged = new Map();
83
+ let socket = null;
84
+ const tracking = new Map();
28
85
  const observers = new Set();
29
86
  const conversationObservers = new Set();
30
87
  const modeObservers = new Set();
31
88
  let replicated = [];
89
+ let listedCursor = null;
32
90
  const live = new Set();
33
91
  let opening = null;
92
+ let announced = null;
34
93
  const runtime = crypto.randomUUID();
35
94
  function emit(event) {
36
95
  for (const observer of observers)
@@ -41,7 +100,11 @@ export function houseNotifications(transport, mode) {
41
100
  event.kind === 'questions' ||
42
101
  event.kind === 'process' ||
43
102
  event.kind === 'commands' ||
44
- event.kind === 'options') {
103
+ event.kind === 'options' ||
104
+ event.kind === 'starting' ||
105
+ event.kind === 'subagents' ||
106
+ event.kind === 'link' ||
107
+ event.kind === 'deliveries') {
45
108
  live.add(event.conversation);
46
109
  }
47
110
  for (const observer of conversationObservers)
@@ -49,11 +112,31 @@ export function houseNotifications(transport, mode) {
49
112
  }
50
113
  function reopened(next) {
51
114
  opening = next;
115
+ announced = null;
116
+ socket = next;
117
+ staged.clear();
52
118
  const gapped = new Set([...replicated, ...live]);
53
119
  live.clear();
54
120
  for (const conversation of gapped)
55
121
  emitConversation({ kind: 'gap', conversation });
56
122
  emit({ kind: 'opened' });
123
+ if (mode === 'site')
124
+ announce(next, null);
125
+ }
126
+ function announce(via, frame) {
127
+ void discovering.opened(frame).then((discovery) => {
128
+ if (socket !== via)
129
+ return;
130
+ if (discovery === null) {
131
+ via.close();
132
+ return;
133
+ }
134
+ announced = { kind: 'discovered', discovery };
135
+ emit(announced);
136
+ }, () => {
137
+ if (socket === via)
138
+ via.close();
139
+ });
57
140
  }
58
141
  function converse(frame) {
59
142
  const conversation = frame.conversation_id;
@@ -72,6 +155,7 @@ export function houseNotifications(transport, mode) {
72
155
  return;
73
156
  emitConversation({ kind: 'commands', conversation, commands: [] });
74
157
  emitConversation({ kind: 'options', conversation, options: [] });
158
+ emitConversation({ kind: 'subagents', conversation, subagents: [] });
75
159
  return;
76
160
  }
77
161
  if (frame.type === 'commands') {
@@ -86,6 +170,26 @@ export function houseNotifications(transport, mode) {
86
170
  emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
87
171
  return;
88
172
  }
173
+ if (frame.type === 'starting') {
174
+ emitConversation({ kind: 'starting', conversation, step: frame.step });
175
+ return;
176
+ }
177
+ if (frame.type === 'subagents') {
178
+ emitConversation({
179
+ kind: 'subagents',
180
+ conversation,
181
+ subagents: structuredClone(frame.subagents),
182
+ });
183
+ return;
184
+ }
185
+ if (frame.type === 'link') {
186
+ emitConversation({ kind: 'link', conversation, connected: frame.connected });
187
+ return;
188
+ }
189
+ if (frame.type === 'deliveries') {
190
+ emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
191
+ return;
192
+ }
89
193
  if (frame.type === 'interactions') {
90
194
  emitConversation({
91
195
  kind: 'questions',
@@ -99,18 +203,32 @@ export function houseNotifications(transport, mode) {
99
203
  return;
100
204
  emitConversation({ kind: 'accepted-message', conversation, message });
101
205
  }
102
- function announce(authority, at) {
103
- const version = roomVersion(at);
104
- for (const locator of locators.get(authority) ?? []) {
105
- emit({ kind: 'room-version', locator, roomVersion: version });
206
+ function stage(frame, via) {
207
+ const held = staged.get(frame.carry);
208
+ if (frame.index !== (held?.parts ?? 0)) {
209
+ staged.delete(frame.carry);
210
+ return;
106
211
  }
212
+ if (held === undefined) {
213
+ for (const [carry, other] of staged) {
214
+ if (other.authority === frame.authority)
215
+ staged.delete(carry);
216
+ }
217
+ }
218
+ const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
219
+ next.entries.push(...frame.entries);
220
+ next.parts += 1;
221
+ staged.set(frame.carry, next);
222
+ via?.received(frame.authority, frame.carry, frame.index);
107
223
  }
108
- function interrupt(authority) {
109
- const line = lines.get(authority);
110
- if (line !== undefined)
111
- lines.set(authority, { ...line, frames: [] });
224
+ function carried(frame) {
225
+ const held = staged.get(frame.carry);
226
+ staged.delete(frame.carry);
227
+ if ((held?.parts ?? 0) !== frame.parts)
228
+ return;
229
+ publish(frame, held?.entries ?? []);
112
230
  }
113
- function receive(frame) {
231
+ function handle(frame, via) {
114
232
  if (frame.type === 'signal') {
115
233
  const mode = frame.service_mode;
116
234
  if (mode !== 'open' && mode !== 'write-halted')
@@ -120,14 +238,31 @@ export function houseNotifications(transport, mode) {
120
238
  return;
121
239
  }
122
240
  if (frame.type === 'opening') {
241
+ if (via !== null && mode === 'credential')
242
+ announce(via, frame);
243
+ return;
244
+ }
245
+ if (frame.type === 'caught_up') {
123
246
  emit({
124
- kind: 'opening',
125
- expired: frame.expired.flatMap((authority) => locators.get(authority) ?? []),
247
+ kind: 'caught-up',
248
+ expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
126
249
  });
127
250
  return;
128
251
  }
252
+ if (frame.type === 'authority_changed') {
253
+ const change = discovering.changed(frame);
254
+ if (change !== null)
255
+ emit(change);
256
+ return;
257
+ }
129
258
  if (frame.type === 'conversations') {
130
- emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
259
+ emitConversation({
260
+ kind: 'list',
261
+ entries: frame.conversations.map(listedConversation),
262
+ whole: frame.whole,
263
+ more: frame.more,
264
+ cursor: frame.cursor,
265
+ });
131
266
  return;
132
267
  }
133
268
  if (frame.type === 'conversation') {
@@ -142,40 +277,45 @@ export function houseNotifications(transport, mode) {
142
277
  frame.type === 'process' ||
143
278
  frame.type === 'commands' ||
144
279
  frame.type === 'options' ||
280
+ frame.type === 'starting' ||
281
+ frame.type === 'subagents' ||
282
+ frame.type === 'link' ||
283
+ frame.type === 'deliveries' ||
145
284
  frame.type === 'interactions' ||
146
285
  frame.type === 'message') {
147
286
  converse(frame);
148
287
  return;
149
288
  }
150
- if (frame.type !== 'entries')
151
- return;
289
+ if (frame.type === 'part')
290
+ stage(frame, via);
291
+ else if (frame.type === 'carried')
292
+ carried(frame);
293
+ }
294
+ function publish(frame, entries) {
152
295
  const at = position(frame.position);
153
296
  const after = position(frame.after);
154
- if (at === null || after === null || after >= at) {
155
- interrupt(frame.authority);
297
+ if (at === null || after === null || after >= at)
156
298
  return;
299
+ const from = roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
300
+ const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
301
+ for (const tracked of tracking.get(frame.authority) ?? []) {
302
+ emit({
303
+ kind: 'room-change',
304
+ locator: tracked.locator,
305
+ from,
306
+ roomVersion: version,
307
+ read: () => changePage(tracked, entries, version, mode),
308
+ });
157
309
  }
158
- const line = lines.get(frame.authority);
159
- if (line?.logEpoch === frame.log_epoch) {
160
- if (line.held !== null && at <= line.held)
161
- return;
162
- const last = line.frames.at(-1);
163
- if (last !== undefined && at <= last.position)
164
- return;
165
- const held = { after, position: at, entries: frame.entries };
166
- const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
167
- lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
168
- }
169
- else {
170
- interrupt(frame.authority);
171
- }
172
- announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
173
310
  }
174
- stream.observe(receive);
311
+ stream.observe((frame) => handle(frame, socket));
175
312
  stream.opened(reopened);
176
- stream.closed((revoked) => {
313
+ stream.closed(({ revoked, lost, authorityChanged }) => {
177
314
  opening = null;
178
- emit({ kind: 'closed', revoked });
315
+ announced = null;
316
+ socket = null;
317
+ staged.clear();
318
+ emit({ kind: 'closed', revoked, lost, authorityChanged });
179
319
  });
180
320
  return {
181
321
  runtime,
@@ -191,19 +331,30 @@ export function houseNotifications(transport, mode) {
191
331
  replicate(next) {
192
332
  replicated = [...next];
193
333
  },
334
+ hold(cursor) {
335
+ listedCursor = cursor;
336
+ },
194
337
  observe(notify) {
195
338
  conversationObservers.add(notify);
196
339
  return () => {
197
340
  conversationObservers.delete(notify);
198
341
  };
199
342
  },
343
+ ...(mode === 'credential'
344
+ ? {
345
+ agents: () => houseAgents(transport),
346
+ history: (request) => houseHistory(transport, request),
347
+ }
348
+ : {}),
200
349
  },
201
350
  observe(notify) {
202
351
  observers.add(notify);
203
- if (opening !== null) {
352
+ const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
353
+ if (replayed.length > 0) {
204
354
  queueMicrotask(() => {
205
- if (observers.has(notify))
206
- notify({ kind: 'opened' });
355
+ for (const event of replayed)
356
+ if (event !== null && observers.has(notify))
357
+ notify(event);
207
358
  });
208
359
  }
209
360
  return () => {
@@ -211,117 +362,19 @@ export function houseNotifications(transport, mode) {
211
362
  };
212
363
  },
213
364
  send(rooms) {
214
- for (const room of rooms) {
215
- const line = lines.get(room.authority);
216
- const held = position(room.position);
217
- if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
218
- continue;
219
- lines.set(room.authority, { ...line, frames: [], held });
220
- }
221
- const current = opening;
222
- opening = null;
223
- current?.hold(rooms, runtime);
224
- },
225
- reopen() {
226
- const current = opening;
227
365
  opening = null;
228
- current?.close();
366
+ announced = null;
367
+ socket?.hold(rooms, runtime, listedCursor);
229
368
  },
230
369
  track(entries) {
231
- locators.clear();
370
+ tracking.clear();
232
371
  for (const entry of entries) {
233
- locators.set(entry.authority, [...(locators.get(entry.authority) ?? []), entry.locator]);
234
- if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
235
- lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
236
- }
237
- }
238
- for (const authority of lines.keys()) {
239
- if (!locators.has(authority))
240
- lines.delete(authority);
372
+ tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
241
373
  }
242
- },
243
- reach(authority, at) {
244
- const line = lines.get(authority);
245
- const held = position(at.position);
246
- if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
247
- return;
248
- if (line.held !== null && held <= line.held)
249
- return;
250
- lines.set(authority, {
251
- ...line,
252
- frames: line.frames.filter((frame) => frame.position > held),
253
- held,
254
- });
255
- },
256
- advance(tracked, from, holds) {
257
- const line = lines.get(tracked.authority);
258
- const start = position(from.position);
259
- if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
260
- return null;
261
- const pending = line.frames.filter((frame) => frame.position > start);
262
- const first = pending[0];
263
- if (first === undefined || first.after > start)
264
- return null;
265
- const documents = {};
266
- const revisions = {};
267
- const changes = {};
268
- const removals = [];
269
- const applied = [];
270
- const schemas = new Map();
271
- const forget = (path) => {
272
- delete documents[path];
273
- delete revisions[path];
274
- delete changes[path];
275
- const removed = removals.indexOf(path);
276
- if (removed !== -1)
277
- removals.splice(removed, 1);
278
- };
279
- for (const frame of pending) {
280
- for (const entry of frame.entries) {
281
- if (entry.kind === 'edited' &&
282
- entry.revision !== undefined &&
283
- holds?.(entry.path, entry.revision) === true) {
284
- forget(entry.path);
285
- continue;
286
- }
287
- applied.push(entry);
288
- if (tracked.schemas.includes(entry.path))
289
- schemas.set(entry.path, entry);
290
- if (entry.kind === 'removed') {
291
- forget(entry.path);
292
- removals.push(entry.path);
293
- continue;
294
- }
295
- if (entry.text === undefined)
296
- return null;
297
- if (mode === 'credential' && entry.revision === undefined)
298
- return null;
299
- const head = headChange(entry);
300
- if (head === null)
301
- return null;
302
- forget(entry.path);
303
- documents[entry.path] = entry.text;
304
- if (entry.revision !== undefined)
305
- revisions[entry.path] = entry.revision;
306
- if (head !== undefined)
307
- changes[entry.path] = head;
308
- }
374
+ for (const [carry, held] of staged) {
375
+ if (!tracking.has(held.authority))
376
+ staged.delete(carry);
309
377
  }
310
- const last = pending.at(-1);
311
- lines.set(tracked.authority, { ...line, frames: pending, held: last.position });
312
- return {
313
- page: {
314
- kind: 'net-advancement',
315
- roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
316
- documents,
317
- revisions,
318
- changes,
319
- binaryTargets: [],
320
- removals: removals.sort(),
321
- },
322
- entries: applied,
323
- schemas,
324
- };
325
378
  },
326
379
  };
327
380
  }