@agentshouse/mdruntime 0.1.0-alpha.2 → 0.1.0-alpha.3

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 (59) hide show
  1. package/dist/adapter.d.ts +12 -10
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/adapter.js.map +1 -1
  4. package/dist/bootstrap.d.ts +5 -12
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/bootstrap.js +13 -20
  7. package/dist/bootstrap.js.map +1 -1
  8. package/dist/change.d.ts +64 -0
  9. package/dist/change.d.ts.map +1 -0
  10. package/dist/change.js +12 -0
  11. package/dist/change.js.map +1 -0
  12. package/dist/collection.d.ts +1 -0
  13. package/dist/collection.d.ts.map +1 -1
  14. package/dist/collection.js +10 -6
  15. package/dist/collection.js.map +1 -1
  16. package/dist/connection.d.ts +19 -0
  17. package/dist/connection.d.ts.map +1 -1
  18. package/dist/connection.js +238 -32
  19. package/dist/connection.js.map +1 -1
  20. package/dist/index.d.ts +5 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/memory.d.ts +1 -0
  24. package/dist/memory.d.ts.map +1 -1
  25. package/dist/memory.js +67 -6
  26. package/dist/memory.js.map +1 -1
  27. package/dist/overlay.d.ts +8 -0
  28. package/dist/overlay.d.ts.map +1 -0
  29. package/dist/overlay.js +139 -0
  30. package/dist/overlay.js.map +1 -0
  31. package/dist/paths.d.ts +6 -0
  32. package/dist/paths.d.ts.map +1 -0
  33. package/dist/paths.js +47 -0
  34. package/dist/paths.js.map +1 -0
  35. package/dist/refresh.d.ts +13 -0
  36. package/dist/refresh.d.ts.map +1 -0
  37. package/dist/refresh.js +63 -0
  38. package/dist/refresh.js.map +1 -0
  39. package/dist/replica.d.ts +19 -0
  40. package/dist/replica.d.ts.map +1 -0
  41. package/dist/replica.js +36 -0
  42. package/dist/replica.js.map +1 -0
  43. package/dist/save.d.ts +26 -0
  44. package/dist/save.d.ts.map +1 -0
  45. package/dist/save.js +496 -0
  46. package/dist/save.js.map +1 -0
  47. package/dist/status.d.ts +15 -0
  48. package/dist/status.d.ts.map +1 -0
  49. package/dist/status.js +29 -0
  50. package/dist/status.js.map +1 -0
  51. package/dist/store.d.ts +21 -0
  52. package/dist/store.d.ts.map +1 -1
  53. package/dist/store.js +77 -2
  54. package/dist/store.js.map +1 -1
  55. package/dist/transfer.d.ts +5 -0
  56. package/dist/transfer.d.ts.map +1 -0
  57. package/dist/transfer.js +5 -0
  58. package/dist/transfer.js.map +1 -0
  59. package/package.json +3 -3
@@ -1,27 +1,47 @@
1
1
  import { query as evaluate } from '@agentshouse/query';
2
2
  import { ROOM_CONTRACT_VERSION, VERSION_1_CAPABILITIES } from './adapter.js';
3
- import { adoptReplica, bootstrapRoom } from './bootstrap.js';
3
+ import { bootstrapRoom } from './bootstrap.js';
4
4
  import { MD_MODEL, PRESENTED } from './collection.js';
5
+ import { refreshRoom } from './refresh.js';
6
+ import { buildBatch } from './save.js';
7
+ import { readConfirmed, replicaOf } from './replica.js';
8
+ import { settled, same, saving, STARTING, transferring } from './status.js';
5
9
  import { openReplicaStore } from './store.js';
10
+ import { unconfirmed } from './transfer.js';
6
11
  const DEFAULT_DISCOVERY_INTERVAL_MS = 60_000;
7
12
  const knownCapabilities = new Set(VERSION_1_CAPABILITIES);
8
13
  export function createMdRuntime(options) {
9
14
  const period = options.discoveryIntervalMs ?? DEFAULT_DISCOVERY_INTERVAL_MS;
10
15
  let authorization = options.authorization;
16
+ let opening;
11
17
  let store;
12
18
  const replicas = new Map();
19
+ const drafts = new Map();
20
+ let limits = [];
13
21
  const rooms = new Map();
14
22
  const unreadable = new Set();
15
23
  let refusal = null;
24
+ let status = STARTING;
16
25
  let discoveryPaused = false;
17
26
  let timer;
18
27
  let closed = false;
19
28
  let chain = Promise.resolve();
29
+ let mutations = Promise.resolve();
20
30
  let inflight = false;
21
31
  let queued = false;
22
32
  const roomListeners = new Set();
23
33
  const refusalListeners = new Set();
34
+ const statusListeners = new Set();
24
35
  const querySubscriptions = new Set();
36
+ const queueSubscriptions = new Set();
37
+ function at(locator, path) {
38
+ return `${locator} ${path}`;
39
+ }
40
+ function pending() {
41
+ return [
42
+ ...replicas.values()
43
+ ].some((replica)=>replica.queue.length > 0);
44
+ }
25
45
  function listed() {
26
46
  return [
27
47
  ...rooms.values()
@@ -31,9 +51,9 @@ export function createMdRuntime(options) {
31
51
  return [
32
52
  ...replicas.values()
33
53
  ].map((replica)=>({
34
- room: replica.record.locator,
35
- roomVersion: replica.record.roomVersion,
36
- documents: replica.collection.documents
54
+ room: replica.confirmed.record.locator,
55
+ roomVersion: replica.confirmed.record.roomVersion,
56
+ documents: replica.visible.collection.documents
37
57
  }));
38
58
  }
39
59
  function emitRooms() {
@@ -43,6 +63,11 @@ export function createMdRuntime(options) {
43
63
  function emitRefusal() {
44
64
  for (const listener of refusalListeners)listener(refusal);
45
65
  }
66
+ function moveTo(next) {
67
+ if (closed || same(status, next)) return;
68
+ status = next;
69
+ for (const listener of statusListeners)listener(status);
70
+ }
46
71
  function visible(request) {
47
72
  return evaluate(queryRooms(), {
48
73
  ...request,
@@ -59,6 +84,15 @@ export function createMdRuntime(options) {
59
84
  subscription.notify(visible(subscription.query));
60
85
  }
61
86
  }
87
+ function queueOf(locator) {
88
+ return replicas.get(locator)?.queue ?? [];
89
+ }
90
+ function emitQueue(locator) {
91
+ const batches = queueOf(locator);
92
+ for (const subscription of queueSubscriptions){
93
+ if (subscription.locator === locator) subscription.notify(batches);
94
+ }
95
+ }
62
96
  function stopTimer() {
63
97
  if (timer === undefined) return;
64
98
  clearInterval(timer);
@@ -85,7 +119,7 @@ export function createMdRuntime(options) {
85
119
  locator: room.locator,
86
120
  writeGrants: room.writeGrants,
87
121
  providerOwnedPaths: room.providerOwnedPaths,
88
- roomVersion: replicas.get(room.locator)?.record.roomVersion ?? null,
122
+ roomVersion: replicas.get(room.locator)?.confirmed.record.roomVersion ?? null,
89
123
  synchronizationAvailable
90
124
  });
91
125
  }
@@ -102,54 +136,160 @@ export function createMdRuntime(options) {
102
136
  });
103
137
  }
104
138
  emitRooms();
139
+ return listedLocators;
105
140
  }
106
- async function openLocal() {
107
- if (store !== undefined) return store;
141
+ async function open() {
108
142
  const opened = await openReplicaStore();
109
- const records = await opened.all();
143
+ const [records, queues, kept, lastCompleted, declared] = await Promise.all([
144
+ opened.all(),
145
+ opened.queues(),
146
+ opened.drafts(),
147
+ opened.lastCompleted(),
148
+ opened.providerLimits()
149
+ ]);
110
150
  store = opened;
151
+ limits = declared;
152
+ for (const draft of kept)drafts.set(at(draft.locator, draft.path), draft.content);
153
+ const queued = new Map(queues.map((queue)=>[
154
+ queue.locator,
155
+ queue.batches
156
+ ]));
111
157
  for (const record of records){
112
- const staged = adoptReplica(record);
113
- if (staged === null) continue;
114
- replicas.set(record.locator, staged);
158
+ const confirmed = readConfirmed(record);
159
+ if (confirmed === null) continue;
160
+ replicas.set(record.locator, replicaOf(confirmed, queued.get(record.locator) ?? []));
115
161
  list(record, false);
116
162
  }
163
+ moveTo({
164
+ ...status,
165
+ lastCompleted
166
+ });
117
167
  if (replicas.size > 0) {
118
168
  emitRooms();
119
169
  emitVisible();
120
170
  }
121
171
  return opened;
122
172
  }
123
- async function bootstrapMissing(discovered, local) {
173
+ function openLocal() {
174
+ opening ??= open().catch((error)=>{
175
+ opening = undefined;
176
+ throw error;
177
+ });
178
+ return opening;
179
+ }
180
+ function exclusive(work) {
181
+ const next = mutations.then(work, work);
182
+ mutations = next.then(()=>undefined, ()=>undefined);
183
+ return next;
184
+ }
185
+ function publish(local, room, confirmed) {
186
+ return exclusive(async ()=>{
187
+ await local.publish(confirmed.record);
188
+ unreadable.delete(room.locator);
189
+ replicas.set(room.locator, replicaOf(confirmed, replicas.get(room.locator)?.queue ?? []));
190
+ list(room, true);
191
+ emitRooms();
192
+ emitVisible();
193
+ });
194
+ }
195
+ async function write(locator, changes) {
196
+ const replica = replicas.get(locator);
197
+ const room = rooms.get(locator);
198
+ if (replica === undefined || room === undefined) {
199
+ throw new Error(`No Local Replica for ${locator}`);
200
+ }
201
+ const built = buildBatch({
202
+ baseRoomVersion: replica.confirmed.record.roomVersion,
203
+ writeGrants: room.writeGrants,
204
+ providerOwnedPaths: room.providerOwnedPaths,
205
+ providerLimits: limits,
206
+ visible: replica.visible,
207
+ changes
208
+ });
209
+ if (built.kind === 'refused') return {
210
+ outcome: 'refused',
211
+ ...built.refusal
212
+ };
213
+ const local = await openLocal();
214
+ const batches = [
215
+ ...replica.queue,
216
+ built.batch
217
+ ];
218
+ const consumed = [
219
+ ...new Set(changes.map((change)=>change.path))
220
+ ];
221
+ await local.append({
222
+ locator,
223
+ batches
224
+ }, consumed);
225
+ for (const path of consumed)drafts.delete(at(locator, path));
226
+ replicas.set(locator, replicaOf(replica.confirmed, batches));
227
+ emitQueue(locator);
228
+ emitVisible();
229
+ moveTo(saving(status));
230
+ return {
231
+ outcome: 'saved',
232
+ id: built.batch.id
233
+ };
234
+ }
235
+ async function advance(room, local, authorized) {
236
+ const held = replicas.get(room.locator);
237
+ if (held !== undefined) {
238
+ const refreshed = await refreshRoom(options.adapter, authorized, held.confirmed);
239
+ if (refreshed.kind === 'still-current') {
240
+ if (unreadable.delete(room.locator)) {
241
+ list(room, true);
242
+ emitRooms();
243
+ }
244
+ return null;
245
+ }
246
+ if (refreshed.kind === 'advanced') {
247
+ if (closed) return unconfirmed;
248
+ await publish(local, room, refreshed.confirmed);
249
+ return null;
250
+ }
251
+ if (refreshed.kind !== 'beyond-horizon') return refreshed;
252
+ }
253
+ const bootstrapped = await bootstrapRoom(options.adapter, authorized, room);
254
+ if (bootstrapped.kind !== 'staged') return bootstrapped;
255
+ if (closed) return unconfirmed;
256
+ await publish(local, room, bootstrapped.confirmed);
257
+ return null;
258
+ }
259
+ async function synchronize(discovered, local, progress) {
124
260
  for (const room of discovered){
125
- if (closed || authorization === undefined) return;
126
- if (replicas.has(room.locator)) continue;
127
- const outcome = await bootstrapRoom(options.adapter, authorization, room);
128
- if (outcome.kind === 'revoked-authorization') {
129
- refuse('revoked-authorization');
261
+ if (closed || authorization === undefined) {
262
+ progress.complete = false;
130
263
  return;
131
264
  }
132
- if (outcome.kind === 'room-not-readable') {
265
+ const withheld = await advance(room, local, authorization);
266
+ if (withheld === null) continue;
267
+ progress.complete = false;
268
+ if (withheld.kind === 'transport-uncertainty') {
269
+ progress.reachable = false;
270
+ continue;
271
+ }
272
+ if (withheld.kind === 'room-not-readable') {
133
273
  unreadable.add(room.locator);
134
274
  list(room, false);
135
275
  emitRooms();
136
276
  continue;
137
277
  }
138
- if (outcome.kind === 'unconfirmed') continue;
139
- if (closed) return;
140
- await local.publish(outcome.replica.record);
141
- unreadable.delete(room.locator);
142
- replicas.set(room.locator, outcome.replica);
143
- list(room, true);
144
- emitRooms();
145
- emitVisible();
278
+ if (withheld.kind === 'revoked-authorization') {
279
+ refuse('revoked-authorization');
280
+ return;
281
+ }
146
282
  }
147
283
  }
148
- async function cycle(local) {
284
+ async function cycle(local, progress) {
149
285
  if (closed || authorization === undefined) return;
286
+ moveTo(transferring(status));
150
287
  const result = await options.adapter.discover(authorization);
151
288
  if (closed) return;
152
- if (result.kind === 'transport-uncertainty') return;
289
+ if (result.kind === 'transport-uncertainty') {
290
+ progress.reachable = false;
291
+ return;
292
+ }
153
293
  if (result.kind === 'revoked-authorization') {
154
294
  refuse('revoked-authorization');
155
295
  return;
@@ -173,8 +313,15 @@ export function createMdRuntime(options) {
173
313
  refusal = null;
174
314
  emitRefusal();
175
315
  }
176
- applyDiscovery(result.rooms);
177
- await bootstrapMissing(result.rooms, local);
316
+ if (JSON.stringify(result.providerLimits) !== JSON.stringify(limits)) {
317
+ limits = result.providerLimits;
318
+ await local.declare(limits);
319
+ }
320
+ const listedLocators = applyDiscovery(result.rooms);
321
+ progress.complete = [
322
+ ...replicas.keys()
323
+ ].every((locator)=>listedLocators.has(locator));
324
+ await synchronize(result.rooms, local, progress);
178
325
  }
179
326
  async function ensureAuthorization() {
180
327
  if (authorization !== undefined) return;
@@ -183,14 +330,27 @@ export function createMdRuntime(options) {
183
330
  async function connect() {
184
331
  if (closed || discoveryPaused) return;
185
332
  startTimer();
333
+ const progress = {
334
+ complete: false,
335
+ reachable: true
336
+ };
337
+ let completedAt = new Date().toISOString();
186
338
  try {
187
339
  const local = await openLocal();
188
340
  if (closed) return;
189
341
  await ensureAuthorization();
190
342
  if (closed) return;
191
- await cycle(local);
343
+ await cycle(local, progress);
344
+ if (closed) return;
345
+ if (progress.complete) {
346
+ completedAt = new Date().toISOString();
347
+ await local.complete(completedAt);
348
+ }
192
349
  } catch {
350
+ progress.complete = false;
193
351
  return;
352
+ } finally{
353
+ moveTo(settled(status, progress, completedAt, pending()));
194
354
  }
195
355
  }
196
356
  async function run() {
@@ -219,7 +379,9 @@ export function createMdRuntime(options) {
219
379
  store?.close();
220
380
  roomListeners.clear();
221
381
  refusalListeners.clear();
382
+ statusListeners.clear();
222
383
  querySubscriptions.clear();
384
+ queueSubscriptions.clear();
223
385
  }
224
386
  options.signal?.addEventListener('abort', close, {
225
387
  once: true
@@ -234,7 +396,32 @@ export function createMdRuntime(options) {
234
396
  return visible(request);
235
397
  },
236
398
  types (locator) {
237
- return replicas.get(locator)?.collection.types ?? [];
399
+ return replicas.get(locator)?.visible.collection.types ?? [];
400
+ },
401
+ syncStatus () {
402
+ return status;
403
+ },
404
+ draft: {
405
+ read (locator, path) {
406
+ return drafts.get(at(locator, path)) ?? null;
407
+ },
408
+ async replace (locator, path, content) {
409
+ const local = await openLocal();
410
+ await local.keep({
411
+ locator,
412
+ path,
413
+ content
414
+ });
415
+ drafts.set(at(locator, path), content);
416
+ },
417
+ async discard (locator, path) {
418
+ const local = await openLocal();
419
+ await local.discard(locator, path);
420
+ drafts.delete(at(locator, path));
421
+ }
422
+ },
423
+ save (locator, changes) {
424
+ return exclusive(()=>write(locator, changes));
238
425
  },
239
426
  observe (topic, second, third) {
240
427
  if (topic === 'rooms') {
@@ -253,6 +440,25 @@ export function createMdRuntime(options) {
253
440
  refusalListeners.delete(notify);
254
441
  };
255
442
  }
443
+ if (topic === 'sync-status') {
444
+ const notify = second;
445
+ statusListeners.add(notify);
446
+ notify(status);
447
+ return ()=>{
448
+ statusListeners.delete(notify);
449
+ };
450
+ }
451
+ if (topic === 'queue') {
452
+ const queue = {
453
+ locator: second,
454
+ notify: third
455
+ };
456
+ queueSubscriptions.add(queue);
457
+ queue.notify(queueOf(queue.locator));
458
+ return ()=>{
459
+ queueSubscriptions.delete(queue);
460
+ };
461
+ }
256
462
  const subscription = {
257
463
  query: second,
258
464
  notify: third
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/connection.ts"],"sourcesContent":["import {\n query as evaluate,\n type QueryOptions,\n type QueryResult,\n type QueryRoom,\n} from '@agentshouse/query';\nimport {\n ROOM_CONTRACT_VERSION,\n VERSION_1_CAPABILITIES,\n type Adapter,\n type Authorization,\n type DiscoveredRoom,\n} from './adapter.js';\nimport { adoptReplica, bootstrapRoom, type StagedReplica } from './bootstrap.js';\nimport { MD_MODEL, PRESENTED, type MdType } from './collection.js';\nimport { openReplicaStore, type ReplicaRecord, type ReplicaStore } from './store.js';\n\nconst DEFAULT_DISCOVERY_INTERVAL_MS = 60_000;\n\nconst knownCapabilities = new Set<string>(VERSION_1_CAPABILITIES);\n\nexport type AppRoom = {\n name: string;\n locator: string;\n writeGrants: readonly string[];\n providerOwnedPaths: readonly string[];\n roomVersion: string | null;\n synchronizationAvailable: boolean;\n};\n\nexport type ConnectionRefusalReason =\n | 'no-matching-version'\n | 'missing-required-guarantee'\n | 'md-model-version-mismatch'\n | 'revoked-authorization';\n\nexport type ConnectionRefusal = {\n reason: ConnectionRefusalReason;\n reauthorizationOffered: boolean;\n};\n\nexport type MdRuntimeOptions = {\n adapter: Adapter;\n requiredGuarantees: readonly string[];\n authorization?: Authorization;\n discoveryIntervalMs?: number;\n signal?: AbortSignal;\n};\n\nexport type MdRuntime = {\n rooms(): readonly AppRoom[];\n query(options?: QueryOptions): QueryResult;\n types(locator: string): readonly MdType[];\n observe: {\n (topic: 'rooms', listener: (rooms: readonly AppRoom[]) => void): () => void;\n (\n topic: 'connection-refusal',\n listener: (refusal: ConnectionRefusal | null) => void,\n ): () => void;\n (topic: 'query', query: QueryOptions, listener: (result: QueryResult) => void): () => void;\n };\n reauthorize(): Promise<void>;\n};\n\ntype QuerySubscription = {\n query: QueryOptions;\n notify: (result: QueryResult) => void;\n};\n\nexport function createMdRuntime(options: MdRuntimeOptions): MdRuntime {\n const period = options.discoveryIntervalMs ?? DEFAULT_DISCOVERY_INTERVAL_MS;\n let authorization: Authorization | undefined = options.authorization;\n let store: ReplicaStore | undefined;\n const replicas = new Map<string, StagedReplica>();\n const rooms = new Map<string, AppRoom>();\n const unreadable = new Set<string>();\n let refusal: ConnectionRefusal | null = null;\n let discoveryPaused = false;\n let timer: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n let chain: Promise<void> = Promise.resolve();\n let inflight = false;\n let queued = false;\n const roomListeners = new Set<(rooms: readonly AppRoom[]) => void>();\n const refusalListeners = new Set<(refusal: ConnectionRefusal | null) => void>();\n const querySubscriptions = new Set<QuerySubscription>();\n\n function listed(): readonly AppRoom[] {\n return [...rooms.values()];\n }\n\n function queryRooms(): readonly QueryRoom[] {\n return [...replicas.values()].map((replica) => ({\n room: replica.record.locator,\n roomVersion: replica.record.roomVersion,\n documents: replica.collection.documents,\n }));\n }\n\n function emitRooms() {\n const value = listed();\n for (const listener of roomListeners) listener(value);\n }\n\n function emitRefusal() {\n for (const listener of refusalListeners) listener(refusal);\n }\n\n function visible(request: QueryOptions): QueryResult {\n return evaluate(queryRooms(), {\n ...request,\n selector: { $and: [PRESENTED, request.selector ?? {}] },\n });\n }\n\n function emitVisible() {\n for (const subscription of querySubscriptions) {\n subscription.notify(visible(subscription.query));\n }\n }\n\n function stopTimer() {\n if (timer === undefined) return;\n clearInterval(timer);\n timer = undefined;\n }\n\n function startTimer() {\n if (timer !== undefined) return;\n timer = setInterval(() => {\n void enqueue();\n }, period);\n }\n\n function refuse(reason: ConnectionRefusalReason) {\n stopTimer();\n discoveryPaused = true;\n refusal = {\n reason,\n reauthorizationOffered: reason === 'revoked-authorization',\n };\n emitRefusal();\n }\n\n function list(room: DiscoveredRoom, synchronizationAvailable: boolean) {\n rooms.set(room.locator, {\n name: room.name,\n locator: room.locator,\n writeGrants: room.writeGrants,\n providerOwnedPaths: room.providerOwnedPaths,\n roomVersion: replicas.get(room.locator)?.record.roomVersion ?? null,\n synchronizationAvailable,\n });\n }\n\n function applyDiscovery(discovered: readonly DiscoveredRoom[]) {\n const listedLocators = new Set(discovered.map((room) => room.locator));\n for (const room of discovered) {\n list(room, !unreadable.has(room.locator));\n }\n for (const [locator, room] of rooms) {\n if (listedLocators.has(locator)) continue;\n rooms.set(locator, { ...room, synchronizationAvailable: false });\n }\n emitRooms();\n }\n\n async function openLocal(): Promise<ReplicaStore> {\n if (store !== undefined) return store;\n const opened = await openReplicaStore();\n const records = await opened.all();\n store = opened;\n for (const record of records) {\n const staged = adoptReplica(record);\n if (staged === null) continue;\n replicas.set(record.locator, staged);\n list(record, false);\n }\n if (replicas.size > 0) {\n emitRooms();\n emitVisible();\n }\n return opened;\n }\n\n async function bootstrapMissing(discovered: readonly DiscoveredRoom[], local: ReplicaStore) {\n for (const room of discovered) {\n if (closed || authorization === undefined) return;\n if (replicas.has(room.locator)) continue;\n const outcome = await bootstrapRoom(options.adapter, authorization, room);\n if (outcome.kind === 'revoked-authorization') {\n refuse('revoked-authorization');\n return;\n }\n if (outcome.kind === 'room-not-readable') {\n unreadable.add(room.locator);\n list(room, false);\n emitRooms();\n continue;\n }\n if (outcome.kind === 'unconfirmed') continue;\n if (closed) return;\n await local.publish(outcome.replica.record);\n unreadable.delete(room.locator);\n replicas.set(room.locator, outcome.replica);\n list(room, true);\n emitRooms();\n emitVisible();\n }\n }\n\n async function cycle(local: ReplicaStore) {\n if (closed || authorization === undefined) return;\n const result = await options.adapter.discover(authorization);\n if (closed) return;\n if (result.kind === 'transport-uncertainty') return;\n if (result.kind === 'revoked-authorization') {\n refuse('revoked-authorization');\n return;\n }\n if (!result.supportedVersions.includes(ROOM_CONTRACT_VERSION)) {\n refuse('no-matching-version');\n return;\n }\n if (\n result.mdModel.identity !== MD_MODEL.identity ||\n result.mdModel.version !== MD_MODEL.version\n ) {\n refuse('md-model-version-mismatch');\n return;\n }\n const declared = new Set(result.capabilities.map((capability) => capability.name));\n for (const required of options.requiredGuarantees) {\n if (!knownCapabilities.has(required) || !declared.has(required)) {\n refuse('missing-required-guarantee');\n return;\n }\n }\n if (refusal !== null) {\n refusal = null;\n emitRefusal();\n }\n applyDiscovery(result.rooms);\n await bootstrapMissing(result.rooms, local);\n }\n\n async function ensureAuthorization() {\n if (authorization !== undefined) return;\n authorization = await options.adapter.authorize();\n }\n\n async function connect() {\n if (closed || discoveryPaused) return;\n startTimer();\n try {\n const local = await openLocal();\n if (closed) return;\n await ensureAuthorization();\n if (closed) return;\n await cycle(local);\n } catch {\n return;\n }\n }\n\n async function run() {\n try {\n await connect();\n } finally {\n inflight = false;\n if (queued && !closed) {\n queued = false;\n void enqueue();\n }\n }\n }\n\n function enqueue() {\n if (inflight) {\n queued = true;\n return chain;\n }\n inflight = true;\n chain = chain.then(run, run);\n return chain;\n }\n\n function close() {\n closed = true;\n stopTimer();\n store?.close();\n roomListeners.clear();\n refusalListeners.clear();\n querySubscriptions.clear();\n }\n\n options.signal?.addEventListener('abort', close, { once: true });\n if (options.signal?.aborted) close();\n\n void enqueue();\n\n return {\n rooms() {\n return listed();\n },\n query(request: QueryOptions = {}) {\n return visible(request);\n },\n types(locator: string) {\n return replicas.get(locator)?.collection.types ?? [];\n },\n observe(\n topic: 'rooms' | 'connection-refusal' | 'query',\n second: QueryOptions | ((value: never) => void),\n third?: (value: never) => void,\n ) {\n if (topic === 'rooms') {\n const notify = second as (value: readonly AppRoom[]) => void;\n roomListeners.add(notify);\n notify(listed());\n return () => {\n roomListeners.delete(notify);\n };\n }\n if (topic === 'connection-refusal') {\n const notify = second as (value: ConnectionRefusal | null) => void;\n refusalListeners.add(notify);\n notify(refusal);\n return () => {\n refusalListeners.delete(notify);\n };\n }\n const subscription: QuerySubscription = {\n query: second as QueryOptions,\n notify: third as (result: QueryResult) => void,\n };\n const first = visible(subscription.query);\n querySubscriptions.add(subscription);\n subscription.notify(first);\n return () => {\n querySubscriptions.delete(subscription);\n };\n },\n async reauthorize() {\n if (refusal === null || !refusal.reauthorizationOffered) return;\n authorization = undefined;\n discoveryPaused = false;\n await enqueue();\n },\n };\n}\n"],"names":["query","evaluate","ROOM_CONTRACT_VERSION","VERSION_1_CAPABILITIES","adoptReplica","bootstrapRoom","MD_MODEL","PRESENTED","openReplicaStore","DEFAULT_DISCOVERY_INTERVAL_MS","knownCapabilities","Set","createMdRuntime","options","period","discoveryIntervalMs","authorization","store","replicas","Map","rooms","unreadable","refusal","discoveryPaused","timer","closed","chain","Promise","resolve","inflight","queued","roomListeners","refusalListeners","querySubscriptions","listed","values","queryRooms","map","replica","room","record","locator","roomVersion","documents","collection","emitRooms","value","listener","emitRefusal","visible","request","selector","$and","emitVisible","subscription","notify","stopTimer","undefined","clearInterval","startTimer","setInterval","enqueue","refuse","reason","reauthorizationOffered","list","synchronizationAvailable","set","name","writeGrants","providerOwnedPaths","get","applyDiscovery","discovered","listedLocators","has","openLocal","opened","records","all","staged","size","bootstrapMissing","local","outcome","adapter","kind","add","publish","delete","cycle","result","discover","supportedVersions","includes","mdModel","identity","version","declared","capabilities","capability","required","requiredGuarantees","ensureAuthorization","authorize","connect","run","then","close","clear","signal","addEventListener","once","aborted","types","observe","topic","second","third","first","reauthorize"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/connection.ts"],"sourcesContent":["import {\n query as evaluate,\n type QueryOptions,\n type QueryResult,\n type QueryRoom,\n} from '@agentshouse/query';\nimport {\n ROOM_CONTRACT_VERSION,\n VERSION_1_CAPABILITIES,\n type Adapter,\n type AdapterFailure,\n type Authorization,\n type DiscoveredRoom,\n type ProviderLimit,\n} from './adapter.js';\nimport { bootstrapRoom } from './bootstrap.js';\nimport type { Change, ChangeBatch } from './change.js';\nimport { MD_MODEL, PRESENTED, type MdType } from './collection.js';\nimport { refreshRoom } from './refresh.js';\nimport { buildBatch, type SaveRefusal } from './save.js';\nimport { readConfirmed, replicaOf, type ConfirmedLayer, type Replica } from './replica.js';\nimport {\n settled,\n same,\n saving,\n STARTING,\n transferring,\n type CycleProgress,\n type SyncStatus,\n} from './status.js';\nimport { openReplicaStore, type ReplicaStore } from './store.js';\nimport { unconfirmed, type Unconfirmed } from './transfer.js';\n\nconst DEFAULT_DISCOVERY_INTERVAL_MS = 60_000;\n\nconst knownCapabilities = new Set<string>(VERSION_1_CAPABILITIES);\n\nexport type AppRoom = {\n name: string;\n locator: string;\n writeGrants: readonly string[];\n providerOwnedPaths: readonly string[];\n roomVersion: string | null;\n synchronizationAvailable: boolean;\n};\n\nexport type ConnectionRefusalReason =\n | 'no-matching-version'\n | 'missing-required-guarantee'\n | 'md-model-version-mismatch'\n | 'revoked-authorization';\n\nexport type ConnectionRefusal = {\n reason: ConnectionRefusalReason;\n reauthorizationOffered: boolean;\n};\n\nexport type MdRuntimeOptions = {\n adapter: Adapter;\n requiredGuarantees: readonly string[];\n authorization?: Authorization;\n discoveryIntervalMs?: number;\n signal?: AbortSignal;\n};\n\nexport type SaveResult = { outcome: 'saved'; id: string } | ({ outcome: 'refused' } & SaveRefusal);\n\nexport type DraftSurface = {\n read(locator: string, path: string): unknown;\n replace(locator: string, path: string, content: unknown): Promise<void>;\n discard(locator: string, path: string): Promise<void>;\n};\n\nexport type MdRuntime = {\n rooms(): readonly AppRoom[];\n query(options?: QueryOptions): QueryResult;\n types(locator: string): readonly MdType[];\n syncStatus(): SyncStatus;\n draft: DraftSurface;\n save(locator: string, changes: readonly Change[]): Promise<SaveResult>;\n observe: {\n (topic: 'rooms', listener: (rooms: readonly AppRoom[]) => void): () => void;\n (\n topic: 'connection-refusal',\n listener: (refusal: ConnectionRefusal | null) => void,\n ): () => void;\n (topic: 'sync-status', listener: (status: SyncStatus) => void): () => void;\n (topic: 'query', query: QueryOptions, listener: (result: QueryResult) => void): () => void;\n (\n topic: 'queue',\n locator: string,\n listener: (batches: readonly ChangeBatch[]) => void,\n ): () => void;\n };\n reauthorize(): Promise<void>;\n};\n\ntype QuerySubscription = {\n query: QueryOptions;\n notify: (result: QueryResult) => void;\n};\n\ntype QueueSubscription = {\n locator: string;\n notify: (batches: readonly ChangeBatch[]) => void;\n};\n\ntype Withheld = AdapterFailure | Unconfirmed;\n\nexport function createMdRuntime(options: MdRuntimeOptions): MdRuntime {\n const period = options.discoveryIntervalMs ?? DEFAULT_DISCOVERY_INTERVAL_MS;\n let authorization: Authorization | undefined = options.authorization;\n let opening: Promise<ReplicaStore> | undefined;\n let store: ReplicaStore | undefined;\n const replicas = new Map<string, Replica>();\n const drafts = new Map<string, unknown>();\n let limits: readonly ProviderLimit[] = [];\n const rooms = new Map<string, AppRoom>();\n const unreadable = new Set<string>();\n let refusal: ConnectionRefusal | null = null;\n let status: SyncStatus = STARTING;\n let discoveryPaused = false;\n let timer: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n let chain: Promise<void> = Promise.resolve();\n let mutations: Promise<unknown> = Promise.resolve();\n let inflight = false;\n let queued = false;\n const roomListeners = new Set<(rooms: readonly AppRoom[]) => void>();\n const refusalListeners = new Set<(refusal: ConnectionRefusal | null) => void>();\n const statusListeners = new Set<(status: SyncStatus) => void>();\n const querySubscriptions = new Set<QuerySubscription>();\n const queueSubscriptions = new Set<QueueSubscription>();\n\n function at(locator: string, path: string) {\n return `${locator} ${path}`;\n }\n\n function pending() {\n return [...replicas.values()].some((replica) => replica.queue.length > 0);\n }\n\n function listed(): readonly AppRoom[] {\n return [...rooms.values()];\n }\n\n function queryRooms(): readonly QueryRoom[] {\n return [...replicas.values()].map((replica) => ({\n room: replica.confirmed.record.locator,\n roomVersion: replica.confirmed.record.roomVersion,\n documents: replica.visible.collection.documents,\n }));\n }\n\n function emitRooms() {\n const value = listed();\n for (const listener of roomListeners) listener(value);\n }\n\n function emitRefusal() {\n for (const listener of refusalListeners) listener(refusal);\n }\n\n function moveTo(next: SyncStatus) {\n if (closed || same(status, next)) return;\n status = next;\n for (const listener of statusListeners) listener(status);\n }\n\n function visible(request: QueryOptions): QueryResult {\n return evaluate(queryRooms(), {\n ...request,\n selector: { $and: [PRESENTED, request.selector ?? {}] },\n });\n }\n\n function emitVisible() {\n for (const subscription of querySubscriptions) {\n subscription.notify(visible(subscription.query));\n }\n }\n\n function queueOf(locator: string): readonly ChangeBatch[] {\n return replicas.get(locator)?.queue ?? [];\n }\n\n function emitQueue(locator: string) {\n const batches = queueOf(locator);\n for (const subscription of queueSubscriptions) {\n if (subscription.locator === locator) subscription.notify(batches);\n }\n }\n\n function stopTimer() {\n if (timer === undefined) return;\n clearInterval(timer);\n timer = undefined;\n }\n\n function startTimer() {\n if (timer !== undefined) return;\n timer = setInterval(() => {\n void enqueue();\n }, period);\n }\n\n function refuse(reason: ConnectionRefusalReason) {\n stopTimer();\n discoveryPaused = true;\n refusal = {\n reason,\n reauthorizationOffered: reason === 'revoked-authorization',\n };\n emitRefusal();\n }\n\n function list(room: DiscoveredRoom, synchronizationAvailable: boolean) {\n rooms.set(room.locator, {\n name: room.name,\n locator: room.locator,\n writeGrants: room.writeGrants,\n providerOwnedPaths: room.providerOwnedPaths,\n roomVersion: replicas.get(room.locator)?.confirmed.record.roomVersion ?? null,\n synchronizationAvailable,\n });\n }\n\n function applyDiscovery(discovered: readonly DiscoveredRoom[]): ReadonlySet<string> {\n const listedLocators = new Set(discovered.map((room) => room.locator));\n for (const room of discovered) {\n list(room, !unreadable.has(room.locator));\n }\n for (const [locator, room] of rooms) {\n if (listedLocators.has(locator)) continue;\n rooms.set(locator, { ...room, synchronizationAvailable: false });\n }\n emitRooms();\n return listedLocators;\n }\n\n async function open(): Promise<ReplicaStore> {\n const opened = await openReplicaStore();\n const [records, queues, kept, lastCompleted, declared] = await Promise.all([\n opened.all(),\n opened.queues(),\n opened.drafts(),\n opened.lastCompleted(),\n opened.providerLimits(),\n ]);\n store = opened;\n limits = declared;\n for (const draft of kept) drafts.set(at(draft.locator, draft.path), draft.content);\n const queued = new Map(queues.map((queue) => [queue.locator, queue.batches]));\n for (const record of records) {\n const confirmed = readConfirmed(record);\n if (confirmed === null) continue;\n replicas.set(record.locator, replicaOf(confirmed, queued.get(record.locator) ?? []));\n list(record, false);\n }\n moveTo({ ...status, lastCompleted });\n if (replicas.size > 0) {\n emitRooms();\n emitVisible();\n }\n return opened;\n }\n\n function openLocal(): Promise<ReplicaStore> {\n opening ??= open().catch((error: unknown) => {\n opening = undefined;\n throw error;\n });\n return opening;\n }\n\n function exclusive<T>(work: () => Promise<T>): Promise<T> {\n const next = mutations.then(work, work);\n mutations = next.then(\n () => undefined,\n () => undefined,\n );\n return next;\n }\n\n function publish(local: ReplicaStore, room: DiscoveredRoom, confirmed: ConfirmedLayer) {\n return exclusive(async () => {\n await local.publish(confirmed.record);\n unreadable.delete(room.locator);\n replicas.set(room.locator, replicaOf(confirmed, replicas.get(room.locator)?.queue ?? []));\n list(room, true);\n emitRooms();\n emitVisible();\n });\n }\n\n async function write(locator: string, changes: readonly Change[]): Promise<SaveResult> {\n const replica = replicas.get(locator);\n const room = rooms.get(locator);\n if (replica === undefined || room === undefined) {\n throw new Error(`No Local Replica for ${locator}`);\n }\n const built = buildBatch({\n baseRoomVersion: replica.confirmed.record.roomVersion,\n writeGrants: room.writeGrants,\n providerOwnedPaths: room.providerOwnedPaths,\n providerLimits: limits,\n visible: replica.visible,\n changes,\n });\n if (built.kind === 'refused') return { outcome: 'refused', ...built.refusal };\n const local = await openLocal();\n const batches = [...replica.queue, built.batch];\n const consumed = [...new Set(changes.map((change) => change.path))];\n await local.append({ locator, batches }, consumed);\n for (const path of consumed) drafts.delete(at(locator, path));\n replicas.set(locator, replicaOf(replica.confirmed, batches));\n emitQueue(locator);\n emitVisible();\n moveTo(saving(status));\n return { outcome: 'saved', id: built.batch.id };\n }\n\n async function advance(\n room: DiscoveredRoom,\n local: ReplicaStore,\n authorized: Authorization,\n ): Promise<Withheld | null> {\n const held = replicas.get(room.locator);\n if (held !== undefined) {\n const refreshed = await refreshRoom(options.adapter, authorized, held.confirmed);\n if (refreshed.kind === 'still-current') {\n if (unreadable.delete(room.locator)) {\n list(room, true);\n emitRooms();\n }\n return null;\n }\n if (refreshed.kind === 'advanced') {\n if (closed) return unconfirmed;\n await publish(local, room, refreshed.confirmed);\n return null;\n }\n if (refreshed.kind !== 'beyond-horizon') return refreshed;\n }\n const bootstrapped = await bootstrapRoom(options.adapter, authorized, room);\n if (bootstrapped.kind !== 'staged') return bootstrapped;\n if (closed) return unconfirmed;\n await publish(local, room, bootstrapped.confirmed);\n return null;\n }\n\n async function synchronize(\n discovered: readonly DiscoveredRoom[],\n local: ReplicaStore,\n progress: CycleProgress,\n ) {\n for (const room of discovered) {\n if (closed || authorization === undefined) {\n progress.complete = false;\n return;\n }\n const withheld = await advance(room, local, authorization);\n if (withheld === null) continue;\n progress.complete = false;\n if (withheld.kind === 'transport-uncertainty') {\n progress.reachable = false;\n continue;\n }\n if (withheld.kind === 'room-not-readable') {\n unreadable.add(room.locator);\n list(room, false);\n emitRooms();\n continue;\n }\n if (withheld.kind === 'revoked-authorization') {\n refuse('revoked-authorization');\n return;\n }\n }\n }\n\n async function cycle(local: ReplicaStore, progress: CycleProgress) {\n if (closed || authorization === undefined) return;\n moveTo(transferring(status));\n const result = await options.adapter.discover(authorization);\n if (closed) return;\n if (result.kind === 'transport-uncertainty') {\n progress.reachable = false;\n return;\n }\n if (result.kind === 'revoked-authorization') {\n refuse('revoked-authorization');\n return;\n }\n if (!result.supportedVersions.includes(ROOM_CONTRACT_VERSION)) {\n refuse('no-matching-version');\n return;\n }\n if (\n result.mdModel.identity !== MD_MODEL.identity ||\n result.mdModel.version !== MD_MODEL.version\n ) {\n refuse('md-model-version-mismatch');\n return;\n }\n const declared = new Set(result.capabilities.map((capability) => capability.name));\n for (const required of options.requiredGuarantees) {\n if (!knownCapabilities.has(required) || !declared.has(required)) {\n refuse('missing-required-guarantee');\n return;\n }\n }\n if (refusal !== null) {\n refusal = null;\n emitRefusal();\n }\n if (JSON.stringify(result.providerLimits) !== JSON.stringify(limits)) {\n limits = result.providerLimits;\n await local.declare(limits);\n }\n const listedLocators = applyDiscovery(result.rooms);\n progress.complete = [...replicas.keys()].every((locator) => listedLocators.has(locator));\n await synchronize(result.rooms, local, progress);\n }\n\n async function ensureAuthorization() {\n if (authorization !== undefined) return;\n authorization = await options.adapter.authorize();\n }\n\n async function connect() {\n if (closed || discoveryPaused) return;\n startTimer();\n const progress: CycleProgress = { complete: false, reachable: true };\n let completedAt = new Date().toISOString();\n try {\n const local = await openLocal();\n if (closed) return;\n await ensureAuthorization();\n if (closed) return;\n await cycle(local, progress);\n if (closed) return;\n if (progress.complete) {\n completedAt = new Date().toISOString();\n await local.complete(completedAt);\n }\n } catch {\n progress.complete = false;\n return;\n } finally {\n moveTo(settled(status, progress, completedAt, pending()));\n }\n }\n\n async function run() {\n try {\n await connect();\n } finally {\n inflight = false;\n if (queued && !closed) {\n queued = false;\n void enqueue();\n }\n }\n }\n\n function enqueue() {\n if (inflight) {\n queued = true;\n return chain;\n }\n inflight = true;\n chain = chain.then(run, run);\n return chain;\n }\n\n function close() {\n closed = true;\n stopTimer();\n store?.close();\n roomListeners.clear();\n refusalListeners.clear();\n statusListeners.clear();\n querySubscriptions.clear();\n queueSubscriptions.clear();\n }\n\n options.signal?.addEventListener('abort', close, { once: true });\n if (options.signal?.aborted) close();\n\n void enqueue();\n\n return {\n rooms() {\n return listed();\n },\n query(request: QueryOptions = {}) {\n return visible(request);\n },\n types(locator: string) {\n return replicas.get(locator)?.visible.collection.types ?? [];\n },\n syncStatus() {\n return status;\n },\n draft: {\n read(locator: string, path: string) {\n return drafts.get(at(locator, path)) ?? null;\n },\n async replace(locator: string, path: string, content: unknown) {\n const local = await openLocal();\n await local.keep({ locator, path, content });\n drafts.set(at(locator, path), content);\n },\n async discard(locator: string, path: string) {\n const local = await openLocal();\n await local.discard(locator, path);\n drafts.delete(at(locator, path));\n },\n },\n save(locator: string, changes: readonly Change[]): Promise<SaveResult> {\n return exclusive(() => write(locator, changes));\n },\n observe(\n topic: 'rooms' | 'connection-refusal' | 'sync-status' | 'query' | 'queue',\n second: QueryOptions | string | ((value: never) => void),\n third?: (value: never) => void,\n ) {\n if (topic === 'rooms') {\n const notify = second as (value: readonly AppRoom[]) => void;\n roomListeners.add(notify);\n notify(listed());\n return () => {\n roomListeners.delete(notify);\n };\n }\n if (topic === 'connection-refusal') {\n const notify = second as (value: ConnectionRefusal | null) => void;\n refusalListeners.add(notify);\n notify(refusal);\n return () => {\n refusalListeners.delete(notify);\n };\n }\n if (topic === 'sync-status') {\n const notify = second as (value: SyncStatus) => void;\n statusListeners.add(notify);\n notify(status);\n return () => {\n statusListeners.delete(notify);\n };\n }\n if (topic === 'queue') {\n const queue: QueueSubscription = {\n locator: second as string,\n notify: third as (batches: readonly ChangeBatch[]) => void,\n };\n queueSubscriptions.add(queue);\n queue.notify(queueOf(queue.locator));\n return () => {\n queueSubscriptions.delete(queue);\n };\n }\n const subscription: QuerySubscription = {\n query: second as QueryOptions,\n notify: third as (result: QueryResult) => void,\n };\n const first = visible(subscription.query);\n querySubscriptions.add(subscription);\n subscription.notify(first);\n return () => {\n querySubscriptions.delete(subscription);\n };\n },\n async reauthorize() {\n if (refusal === null || !refusal.reauthorizationOffered) return;\n authorization = undefined;\n discoveryPaused = false;\n await enqueue();\n },\n };\n}\n"],"names":["query","evaluate","ROOM_CONTRACT_VERSION","VERSION_1_CAPABILITIES","bootstrapRoom","MD_MODEL","PRESENTED","refreshRoom","buildBatch","readConfirmed","replicaOf","settled","same","saving","STARTING","transferring","openReplicaStore","unconfirmed","DEFAULT_DISCOVERY_INTERVAL_MS","knownCapabilities","Set","createMdRuntime","options","period","discoveryIntervalMs","authorization","opening","store","replicas","Map","drafts","limits","rooms","unreadable","refusal","status","discoveryPaused","timer","closed","chain","Promise","resolve","mutations","inflight","queued","roomListeners","refusalListeners","statusListeners","querySubscriptions","queueSubscriptions","at","locator","path","pending","values","some","replica","queue","length","listed","queryRooms","map","room","confirmed","record","roomVersion","documents","visible","collection","emitRooms","value","listener","emitRefusal","moveTo","next","request","selector","$and","emitVisible","subscription","notify","queueOf","get","emitQueue","batches","stopTimer","undefined","clearInterval","startTimer","setInterval","enqueue","refuse","reason","reauthorizationOffered","list","synchronizationAvailable","set","name","writeGrants","providerOwnedPaths","applyDiscovery","discovered","listedLocators","has","open","opened","records","queues","kept","lastCompleted","declared","all","providerLimits","draft","content","size","openLocal","catch","error","exclusive","work","then","publish","local","delete","write","changes","Error","built","baseRoomVersion","kind","outcome","batch","consumed","change","append","id","advance","authorized","held","refreshed","adapter","bootstrapped","synchronize","progress","complete","withheld","reachable","add","cycle","result","discover","supportedVersions","includes","mdModel","identity","version","capabilities","capability","required","requiredGuarantees","JSON","stringify","declare","keys","every","ensureAuthorization","authorize","connect","completedAt","Date","toISOString","run","close","clear","signal","addEventListener","once","aborted","types","syncStatus","read","replace","keep","discard","save","observe","topic","second","third","first","reauthorize"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
- export type { ActionDeclaration, ActionRequest, ActionResult, Adapter, AdapterFailure, Authorization, BootstrapPage, BootstrapRequest, BootstrapResult, Capability, DiscoverResult, DiscoveredRoom, Discovery, HistoryRequest, HistoryResult, MdModelIdentity, MutationRequest, MutationResult, PageToken, ProviderLimit, RefreshRequest, RefreshResult, Retention, RevokedAuthorization, RoomNotReadable, TransportUncertainty, } from './adapter.js';
1
+ export type { ActionDeclaration, ActionRequest, ActionResult, Adapter, AdapterFailure, Authorization, BootstrapPage, BootstrapRequest, BootstrapResult, Capability, DiscoverResult, DiscoveredRoom, Discovery, HistoryRequest, HistoryResult, MdModelIdentity, MutationRequest, MutationResult, PageToken, ProviderLimit, RefreshPage, RefreshRequest, RefreshResult, Retention, RevokedAuthorization, RoomNotReadable, TransportUncertainty, } from './adapter.js';
2
+ export type { Change, ChangeBatch, Precondition } from './change.js';
2
3
  export type { MdType } from './collection.js';
3
- export type { AppRoom, ConnectionRefusal, ConnectionRefusalReason, MdRuntime, MdRuntimeOptions, } from './connection.js';
4
+ export type { AppRoom, ConnectionRefusal, ConnectionRefusalReason, DraftSurface, MdRuntime, MdRuntimeOptions, SaveResult, } from './connection.js';
5
+ export type { SaveRefusal } from './save.js';
4
6
  export { createMdRuntime } from './connection.js';
7
+ export type { SyncStatus } from './status.js';
5
8
  export type { Backlink, QueryDocument, QueryGroup, QueryOptions, QueryResult, Selector, } from '@agentshouse/query';
6
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,OAAO,EACP,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,eAAe,EACf,cAAc,EACd,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,eAAe,EACf,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EACV,OAAO,EACP,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EACV,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,OAAO,EACP,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,cAAc,EACd,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,eAAe,EACf,eAAe,EACf,cAAc,EACd,SAAS,EACT,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,eAAe,EACf,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,YAAY,EACV,OAAO,EACP,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EACV,QAAQ,EACR,aAAa,EACb,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,oBAAoB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdruntime/src/index.ts"],"sourcesContent":["export type {\n ActionDeclaration,\n ActionRequest,\n ActionResult,\n Adapter,\n AdapterFailure,\n Authorization,\n BootstrapPage,\n BootstrapRequest,\n BootstrapResult,\n Capability,\n DiscoverResult,\n DiscoveredRoom,\n Discovery,\n HistoryRequest,\n HistoryResult,\n MdModelIdentity,\n MutationRequest,\n MutationResult,\n PageToken,\n ProviderLimit,\n RefreshRequest,\n RefreshResult,\n Retention,\n RevokedAuthorization,\n RoomNotReadable,\n TransportUncertainty,\n} from './adapter.js';\nexport type { MdType } from './collection.js';\nexport type {\n AppRoom,\n ConnectionRefusal,\n ConnectionRefusalReason,\n MdRuntime,\n MdRuntimeOptions,\n} from './connection.js';\nexport { createMdRuntime } from './connection.js';\nexport type {\n Backlink,\n QueryDocument,\n QueryGroup,\n QueryOptions,\n QueryResult,\n Selector,\n} from '@agentshouse/query';\n"],"names":["createMdRuntime"],"mappings":"AAoCA,SAASA,eAAe,QAAQ,kBAAkB"}
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/index.ts"],"sourcesContent":["export type {\n ActionDeclaration,\n ActionRequest,\n ActionResult,\n Adapter,\n AdapterFailure,\n Authorization,\n BootstrapPage,\n BootstrapRequest,\n BootstrapResult,\n Capability,\n DiscoverResult,\n DiscoveredRoom,\n Discovery,\n HistoryRequest,\n HistoryResult,\n MdModelIdentity,\n MutationRequest,\n MutationResult,\n PageToken,\n ProviderLimit,\n RefreshPage,\n RefreshRequest,\n RefreshResult,\n Retention,\n RevokedAuthorization,\n RoomNotReadable,\n TransportUncertainty,\n} from './adapter.js';\nexport type { Change, ChangeBatch, Precondition } from './change.js';\nexport type { MdType } from './collection.js';\nexport type {\n AppRoom,\n ConnectionRefusal,\n ConnectionRefusalReason,\n DraftSurface,\n MdRuntime,\n MdRuntimeOptions,\n SaveResult,\n} from './connection.js';\nexport type { SaveRefusal } from './save.js';\nexport { createMdRuntime } from './connection.js';\nexport type { SyncStatus } from './status.js';\nexport type {\n Backlink,\n QueryDocument,\n QueryGroup,\n QueryOptions,\n QueryResult,\n Selector,\n} from '@agentshouse/query';\n"],"names":["createMdRuntime"],"mappings":"AAyCA,SAASA,eAAe,QAAQ,kBAAkB"}
package/dist/memory.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type Adapter, type Capability, type DiscoveredRoom, type MdModelIdentity, type ProviderLimit, type Retention } from './adapter.js';
2
2
  export type MemoryRoom = DiscoveredRoom & {
3
3
  documents?: Readonly<Record<string, string>>;
4
+ revisions?: Readonly<Record<string, string>>;
4
5
  binaryTargets?: readonly string[];
5
6
  };
6
7
  export type MemoryAdapterOptions = {
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EAIZ,KAAK,UAAU,EAEf,KAAK,cAAc,EAGnB,KAAK,eAAe,EAGpB,KAAK,aAAa,EAGlB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACrC,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACzD,CAAC;AAaF,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CA6IrF"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,OAAO,EAIZ,KAAK,UAAU,EAEf,KAAK,cAAc,EAGnB,KAAK,eAAe,EAGpB,KAAK,aAAa,EAGlB,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,YAAY,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACrC,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAAC;IAC7C,MAAM,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACzD,CAAC;AA+BF,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CA0MrF"}