@agentshouse/mdruntime-adapter 0.1.0-cafd7caa7ae65 → 0.1.0-cb0bbc4ccacd0

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