@agentshouse/mdruntime 0.1.0-alpha.9 → 0.1.0-c009335e08279

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 (124) hide show
  1. package/AGENTS.md +208 -0
  2. package/README.md +44 -0
  3. package/dist/adapter.d.ts +147 -12
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +2 -3
  6. package/dist/attachment.d.ts +3 -0
  7. package/dist/attachment.d.ts.map +1 -0
  8. package/dist/attachment.js +8 -0
  9. package/dist/bootstrap.d.ts +3 -7
  10. package/dist/bootstrap.d.ts.map +1 -1
  11. package/dist/bootstrap.js +28 -27
  12. package/dist/change-set.d.ts +33 -0
  13. package/dist/change-set.d.ts.map +1 -0
  14. package/dist/change-set.js +83 -0
  15. package/dist/change.d.ts +9 -0
  16. package/dist/change.d.ts.map +1 -1
  17. package/dist/change.js +6 -5
  18. package/dist/client.d.ts +38 -32
  19. package/dist/client.d.ts.map +1 -1
  20. package/dist/client.js +115 -177
  21. package/dist/collection.d.ts +13 -16
  22. package/dist/collection.d.ts.map +1 -1
  23. package/dist/collection.js +45 -88
  24. package/dist/connection.d.ts +46 -39
  25. package/dist/connection.d.ts.map +1 -1
  26. package/dist/connection.js +1376 -975
  27. package/dist/conversation.d.ts +41 -19
  28. package/dist/conversation.d.ts.map +1 -1
  29. package/dist/conversation.js +483 -327
  30. package/dist/durability.js +6 -6
  31. package/dist/file.d.ts +2 -2
  32. package/dist/file.d.ts.map +1 -1
  33. package/dist/file.js +48 -71
  34. package/dist/host.d.ts +6 -2
  35. package/dist/host.d.ts.map +1 -1
  36. package/dist/host.js +83 -108
  37. package/dist/identity.d.ts +1 -0
  38. package/dist/identity.d.ts.map +1 -1
  39. package/dist/identity.js +10 -9
  40. package/dist/index.d.ts +12 -11
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +1 -3
  43. package/dist/log.js +5 -6
  44. package/dist/memory.d.ts +6 -3
  45. package/dist/memory.d.ts.map +1 -1
  46. package/dist/memory.js +205 -210
  47. package/dist/model.d.ts +10 -25
  48. package/dist/model.d.ts.map +1 -1
  49. package/dist/model.js +18 -21
  50. package/dist/observation.d.ts +25 -0
  51. package/dist/observation.d.ts.map +1 -0
  52. package/dist/observation.js +85 -0
  53. package/dist/outcome.d.ts +10 -29
  54. package/dist/outcome.d.ts.map +1 -1
  55. package/dist/outcome.js +1 -23
  56. package/dist/overlay.d.ts +9 -2
  57. package/dist/overlay.d.ts.map +1 -1
  58. package/dist/overlay.js +187 -43
  59. package/dist/paths.d.ts +0 -1
  60. package/dist/paths.d.ts.map +1 -1
  61. package/dist/paths.js +12 -19
  62. package/dist/query.d.ts +210 -10
  63. package/dist/query.d.ts.map +1 -1
  64. package/dist/query.js +420 -15
  65. package/dist/read-side.d.ts +14 -0
  66. package/dist/read-side.d.ts.map +1 -0
  67. package/dist/read-side.js +371 -0
  68. package/dist/refresh.d.ts +4 -5
  69. package/dist/refresh.d.ts.map +1 -1
  70. package/dist/refresh.js +45 -30
  71. package/dist/replica.d.ts +25 -5
  72. package/dist/replica.d.ts.map +1 -1
  73. package/dist/replica.js +228 -38
  74. package/dist/room-draft.d.ts +124 -0
  75. package/dist/room-draft.d.ts.map +1 -0
  76. package/dist/room-draft.js +327 -0
  77. package/dist/rows.d.ts +41 -0
  78. package/dist/rows.d.ts.map +1 -0
  79. package/dist/rows.js +100 -0
  80. package/dist/save.d.ts +8 -4
  81. package/dist/save.d.ts.map +1 -1
  82. package/dist/save.js +264 -350
  83. package/dist/search.d.ts +61 -0
  84. package/dist/search.d.ts.map +1 -0
  85. package/dist/search.js +125 -0
  86. package/dist/status.d.ts +4 -6
  87. package/dist/status.d.ts.map +1 -1
  88. package/dist/status.js +9 -13
  89. package/dist/store.d.ts +59 -31
  90. package/dist/store.d.ts.map +1 -1
  91. package/dist/store.js +338 -134
  92. package/dist/transfer.d.ts +5 -0
  93. package/dist/transfer.d.ts.map +1 -1
  94. package/dist/transfer.js +1 -5
  95. package/dist/wire.d.ts +4 -3
  96. package/dist/wire.d.ts.map +1 -1
  97. package/dist/wire.js +47 -68
  98. package/package.json +6 -12
  99. package/dist/adapter.js.map +0 -1
  100. package/dist/bootstrap.js.map +0 -1
  101. package/dist/change.js.map +0 -1
  102. package/dist/client.js.map +0 -1
  103. package/dist/collection.js.map +0 -1
  104. package/dist/connection.js.map +0 -1
  105. package/dist/conversation.js.map +0 -1
  106. package/dist/durability.js.map +0 -1
  107. package/dist/file.js.map +0 -1
  108. package/dist/host.js.map +0 -1
  109. package/dist/identity.js.map +0 -1
  110. package/dist/index.js.map +0 -1
  111. package/dist/log.js.map +0 -1
  112. package/dist/memory.js.map +0 -1
  113. package/dist/model.js.map +0 -1
  114. package/dist/outcome.js.map +0 -1
  115. package/dist/overlay.js.map +0 -1
  116. package/dist/paths.js.map +0 -1
  117. package/dist/query.js.map +0 -1
  118. package/dist/refresh.js.map +0 -1
  119. package/dist/replica.js.map +0 -1
  120. package/dist/save.js.map +0 -1
  121. package/dist/status.js.map +0 -1
  122. package/dist/store.js.map +0 -1
  123. package/dist/transfer.js.map +0 -1
  124. package/dist/wire.js.map +0 -1
package/dist/memory.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import type { ModelResult } from './model.js';
2
- import { type ActionResult, type Adapter, type Capability, type ConversationAction, type ConversationEvent, type ConversationMessage, type DiscoveredRoom, type MdModelIdentity, type ProviderLimit, type Retention, type RoomVersionNotification } from './adapter.js';
2
+ import { type AcceptedMessage, type ActionResult, type Adapter, type Capability, type ConversationAction, type ConversationEvent, type DiscoveredRoom, type HeadChange, type MdModelIdentity, type ProviderLimit, type Retention, type RoomAttachment, type RoomVersionNotification, type ServiceMode } from './adapter.js';
3
3
  export type MemoryRoom = DiscoveredRoom & {
4
4
  model?: ModelResult;
5
5
  selectionModel?: ModelResult;
6
6
  documents?: Readonly<Record<string, string>>;
7
7
  revisions?: Readonly<Record<string, string>>;
8
+ changes?: Readonly<Record<string, HeadChange>>;
8
9
  binaryTargets?: readonly string[];
10
+ attachments?: readonly RoomAttachment[];
9
11
  };
10
12
  export type MemoryConversation = {
11
13
  conversation: string;
12
- messages?: readonly ConversationMessage[];
14
+ messages?: readonly AcceptedMessage[];
13
15
  outcomes?: Partial<Record<ConversationAction, ActionResult>>;
14
16
  };
15
17
  export type MemoryAdapterOptions = {
@@ -29,8 +31,9 @@ export type MemoryAdapter = Adapter & {
29
31
  script(operation: keyof Adapter, answer: unknown): void;
30
32
  notifyRoomVersion(notification: RoomVersionNotification): void;
31
33
  notifyConversation(event: ConversationEvent): void;
34
+ notifyServiceMode(mode: ServiceMode): void;
32
35
  selectedRooms(): readonly string[];
33
- viewedConversations(): readonly string[];
36
+ replicatedConversations(): readonly string[];
34
37
  };
35
38
  export declare function createMemoryAdapter(options?: MemoryAdapterOptions): MemoryAdapter;
36
39
  //# sourceMappingURL=memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAExB,KAAK,cAAc,EAGnB,KAAK,eAAe,EAGpB,KAAK,aAAa,EAGlB,KAAK,SAAS,EACd,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAkBtB,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,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,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC,CAAC;CAC9D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,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;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAAC;IAC7C,gBAAgB,CAAC,aAAa,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI,CAAC;IACrE,MAAM,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACxD,iBAAiB,CAAC,YAAY,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC/D,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnD,aAAa,IAAI,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,IAAI,SAAS,MAAM,EAAE,CAAC;CAC1C,CAAC;AA+BF,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAwUrF"}
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAEL,KAAK,eAAe,EAEpB,KAAK,YAAY,EACjB,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EAItB,KAAK,cAAc,EACnB,KAAK,UAAU,EAGf,KAAK,eAAe,EAGpB,KAAK,aAAa,EAGlB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAmBtB,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,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,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/C,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC,CAAC;CAC9D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,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;CACvB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAAC;IAC7C,gBAAgB,CAAC,aAAa,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI,CAAC;IACrE,MAAM,CAAC,SAAS,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACxD,iBAAiB,CAAC,YAAY,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC/D,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnD,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,aAAa,IAAI,SAAS,MAAM,EAAE,CAAC;IACnC,uBAAuB,IAAI,SAAS,MAAM,EAAE,CAAC;CAC9C,CAAC;AA+BF,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAiZrF"}
package/dist/memory.js CHANGED
@@ -1,16 +1,15 @@
1
- import { ROOM_CONTRACT_VERSION } from './adapter.js';
1
+ import { ROOM_CONTRACT_VERSION, } from './adapter.js';
2
2
  import { MD_MODEL } from './collection.js';
3
+ import { sameChange } from './overlay.js';
3
4
  const FIXTURE_RETENTION = {
4
- history: {
5
- kind: 'duration',
6
- seconds: 1
7
- },
5
+ history: { kind: 'duration', seconds: 1 },
8
6
  outcome: 1,
9
- refreshHorizon: 1
7
+ refreshHorizon: 1,
10
8
  };
11
9
  function declaredRetention(value) {
12
10
  const retention = value ?? FIXTURE_RETENTION;
13
- if (retention.history.kind === 'no-declared-time-bound') return retention;
11
+ if (retention.history.kind === 'no-declared-time-bound')
12
+ return retention;
14
13
  if (Number.isFinite(retention.history.seconds) && retention.history.seconds > 0) {
15
14
  return retention;
16
15
  }
@@ -18,24 +17,22 @@ function declaredRetention(value) {
18
17
  }
19
18
  function named(source, paths) {
20
19
  const taken = {};
21
- for (const path of paths){
20
+ for (const path of paths) {
22
21
  const value = source[path];
23
- if (value !== undefined) taken[path] = value;
22
+ if (value !== undefined)
23
+ taken[path] = value;
24
24
  }
25
25
  return taken;
26
26
  }
27
27
  async function resolveScript(answer, fallback, request) {
28
- if (answer === undefined) return fallback();
28
+ if (answer === undefined)
29
+ return fallback();
29
30
  return typeof answer === 'function' ? answer(request) : answer;
30
31
  }
31
32
  export function createMemoryAdapter(options = {}) {
32
- let rooms = options.rooms === undefined ? [] : [
33
- ...options.rooms
34
- ];
33
+ let rooms = options.rooms === undefined ? [] : [...options.rooms];
35
34
  const mdModel = options.mdModel ?? MD_MODEL;
36
- const supportedVersions = options.supportedVersions ?? [
37
- ROOM_CONTRACT_VERSION
38
- ];
35
+ const supportedVersions = options.supportedVersions ?? [ROOM_CONTRACT_VERSION];
39
36
  const capabilities = options.capabilities ?? [];
40
37
  const providerLimits = options.providerLimits ?? [];
41
38
  const retention = declaredRetention(options.retention);
@@ -45,20 +42,43 @@ export function createMemoryAdapter(options = {}) {
45
42
  const refreshPages = new Map();
46
43
  const observers = new Set();
47
44
  const listeners = new Set();
45
+ const modeObservers = new Set();
48
46
  const scripted = new Map();
49
47
  const unsealed = new Map();
50
48
  const sealed = new Set();
51
49
  const historyPageSize = options.historyPageSize;
52
50
  let selected = [];
53
- let viewed = [];
51
+ let replicated = [];
54
52
  let issued = 0;
55
53
  function scriptConversations(entries) {
56
54
  scripted.clear();
57
- for (const entry of entries)scripted.set(entry.conversation, entry);
55
+ for (const entry of entries)
56
+ scripted.set(entry.conversation, entry);
58
57
  }
59
58
  scriptConversations(options.conversations ?? []);
59
+ const ordinals = new Map();
60
+ function note(locator, answer) {
61
+ const roomVersion = answer.roomVersion;
62
+ const key = `${locator}\u0000${String(roomVersion)}`;
63
+ if (typeof roomVersion === 'string' && !ordinals.has(key))
64
+ ordinals.set(key, ordinals.size);
65
+ return answer;
66
+ }
67
+ function reached(locator, roomVersion, target) {
68
+ const scripted = scripts.reached;
69
+ if (typeof scripted === 'boolean')
70
+ return scripted;
71
+ if (scripted !== undefined)
72
+ return scripted(locator, roomVersion, target);
73
+ if (roomVersion === target)
74
+ return true;
75
+ const held = ordinals.get(`${locator}\u0000${roomVersion}`);
76
+ const wanted = ordinals.get(`${locator}\u0000${target}`);
77
+ return held !== undefined && wanted !== undefined && held >= wanted;
78
+ }
60
79
  function retain(entries) {
61
- for (const room of entries){
80
+ for (const room of entries) {
81
+ note(room.locator, room);
62
82
  const versions = served.get(room.locator) ?? new Map();
63
83
  versions.set(room.roomVersion, room);
64
84
  served.set(room.locator, versions);
@@ -69,15 +89,12 @@ export function createMemoryAdapter(options = {}) {
69
89
  return {
70
90
  name: room.name,
71
91
  locator: room.locator,
72
- collectionRoot: room.collectionRoot,
73
92
  roomVersion: room.roomVersion,
74
93
  operations: room.operations,
75
94
  replica: room.replica,
76
95
  attachedModel: room.attachedModel,
77
- ...room.typedSelection === undefined ? {} : {
78
- typedSelection: room.typedSelection
79
- },
80
- providerOwnedPaths: room.providerOwnedPaths
96
+ ...(room.typedSelection === undefined ? {} : { typedSelection: room.typedSelection }),
97
+ providerOwnedPaths: room.providerOwnedPaths,
81
98
  };
82
99
  }
83
100
  function page(room, from) {
@@ -85,15 +102,16 @@ export function createMemoryAdapter(options = {}) {
85
102
  const size = pageSize ?? paths.length;
86
103
  const taken = paths.slice(from, from + size);
87
104
  const next = from + taken.length;
105
+ const targets = from === 0 ? (room.binaryTargets ?? []) : [];
88
106
  return {
89
107
  kind: 'bootstrap',
90
108
  roomVersion: room.roomVersion,
91
109
  documents: named(room.documents ?? {}, taken),
92
110
  revisions: named(room.revisions ?? {}, taken),
93
- binaryTargets: from === 0 ? room.binaryTargets ?? [] : [],
94
- ...next < paths.length ? {
95
- pageToken: String(next)
96
- } : {}
111
+ changes: named(room.changes ?? {}, [...taken, ...targets]),
112
+ binaryTargets: targets,
113
+ ...(from === 0 && room.attachments !== undefined ? { attachments: room.attachments } : {}),
114
+ ...(next < paths.length ? { pageToken: String(next) } : {}),
97
115
  };
98
116
  }
99
117
  function advancement(room, from, at) {
@@ -101,128 +119,107 @@ export function createMemoryAdapter(options = {}) {
101
119
  const previous = from.documents ?? {};
102
120
  const currentTargets = new Set(room.binaryTargets ?? []);
103
121
  const previousTargets = new Set(from.binaryTargets ?? []);
104
- const changed = Object.keys(current).filter((path)=>current[path] !== previous[path]).sort();
122
+ const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
123
+ !sameChange(room.changes?.[path], from.changes?.[path]);
124
+ const changed = Object.keys(current)
125
+ .filter((path) => current[path] !== previous[path] || headMoved(path))
126
+ .sort();
105
127
  const size = pageSize ?? changed.length;
106
128
  const taken = changed.slice(at, at + size);
107
129
  const next = at + taken.length;
108
130
  const opening = at === 0;
109
131
  const pageToken = next < changed.length ? `refresh-${refreshPages.size}` : undefined;
110
- if (pageToken !== undefined) refreshPages.set(pageToken, {
111
- room,
112
- from,
113
- at: next
114
- });
132
+ if (pageToken !== undefined)
133
+ refreshPages.set(pageToken, { room, from, at: next });
134
+ const targets = opening
135
+ ? [...currentTargets].filter((target) => !previousTargets.has(target) || headMoved(target))
136
+ : [];
137
+ const attachments = room.attachments ?? [];
138
+ const declared = opening && JSON.stringify(attachments) !== JSON.stringify(from.attachments ?? []);
115
139
  return {
116
140
  kind: 'net-advancement',
117
141
  roomVersion: room.roomVersion,
118
142
  documents: named(current, taken),
119
143
  revisions: named(room.revisions ?? {}, taken),
120
- binaryTargets: opening ? [
121
- ...currentTargets
122
- ].filter((target)=>!previousTargets.has(target)) : [],
123
- removals: opening ? [
124
- ...Object.keys(previous).filter((path)=>!(path in current) && !currentTargets.has(path)),
125
- ...[
126
- ...previousTargets
127
- ].filter((target)=>!currentTargets.has(target) && !(target in current))
128
- ].sort() : [],
129
- ...pageToken === undefined ? {} : {
130
- pageToken
131
- }
144
+ changes: named(room.changes ?? {}, [...taken, ...targets]),
145
+ binaryTargets: targets,
146
+ removals: opening
147
+ ? [
148
+ ...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
149
+ ...[...previousTargets].filter((target) => !currentTargets.has(target) && !(target in current)),
150
+ ].sort()
151
+ : [],
152
+ ...(declared ? { attachments } : {}),
153
+ ...(pageToken === undefined ? {} : { pageToken }),
132
154
  };
133
155
  }
134
- function historyOf(conversation, cursor) {
156
+ function pageOf(conversation, after) {
135
157
  const messages = conversation.messages ?? [];
136
- const until = typeof cursor === 'string' ? Number(cursor) : messages.length;
137
- if (!Number.isInteger(until) || until < 0 || until > messages.length) {
138
- return {
139
- kind: 'rejected',
140
- code: 'unknown-cursor',
141
- fields: {
142
- cursor
143
- }
144
- };
145
- }
146
- const size = historyPageSize ?? messages.length;
147
- const from = Math.max(0, until - size);
158
+ const first = typeof after === 'string' ? messages.findIndex((message) => message.position > after) : 0;
159
+ const from = first === -1 ? messages.length : first;
160
+ const page = messages.slice(from, from + (historyPageSize ?? messages.length));
161
+ const last = page.at(-1);
148
162
  return {
149
- kind: 'action',
150
- result: {
151
- messages: messages.slice(from, until),
152
- ...from === 0 ? {} : {
153
- cursor: String(from)
154
- }
155
- }
163
+ conversation: conversation.conversation,
164
+ messages: page,
165
+ ...(last !== undefined && from + page.length < messages.length
166
+ ? { next: last.position }
167
+ : {}),
156
168
  };
157
169
  }
170
+ function historiesOf(input) {
171
+ const asked = input?.conversations;
172
+ if (!Array.isArray(asked))
173
+ return { kind: 'rejected', code: 'invalid_request', fields: {} };
174
+ const histories = [];
175
+ for (const entry of asked) {
176
+ const conversation = typeof entry.conversation === 'string' ? scripted.get(entry.conversation) : undefined;
177
+ if (conversation === undefined)
178
+ continue;
179
+ const outcome = conversation.outcomes?.['conversation.history'];
180
+ if (outcome !== undefined)
181
+ return outcome;
182
+ histories.push(pageOf(conversation, entry.after));
183
+ }
184
+ const result = { histories };
185
+ return { kind: 'action', result };
186
+ }
158
187
  function conversationAction(request) {
159
188
  const name = request.name;
160
- const input = request.input ?? {};
189
+ const input = (request.input ?? {});
190
+ if (name === 'conversation.history')
191
+ return historiesOf(request.input);
161
192
  if (name === 'conversation.create') {
162
193
  issued += 1;
163
194
  const conversation = `conversation-${issued}`;
164
- scripted.set(conversation, {
165
- conversation
166
- });
167
- return {
168
- kind: 'action',
169
- result: {
170
- conversation
171
- }
172
- };
195
+ scripted.set(conversation, { conversation });
196
+ return { kind: 'action', result: { conversation } };
173
197
  }
174
198
  const named = typeof input.conversation === 'string' ? input.conversation : '';
175
199
  const conversation = scripted.get(named);
176
200
  if (conversation === undefined) {
177
- return {
178
- kind: 'rejected',
179
- code: 'unknown-conversation',
180
- fields: {
181
- conversation: named
182
- }
183
- };
201
+ return { kind: 'rejected', code: 'unknown-conversation', fields: { conversation: named } };
184
202
  }
185
203
  const outcome = conversation.outcomes?.[name];
186
- if (outcome !== undefined) return outcome;
187
- if (name === 'conversation.history') return historyOf(conversation, input.cursor);
204
+ if (outcome !== undefined)
205
+ return outcome;
188
206
  if (name === 'conversation.send') {
189
207
  issued += 1;
190
208
  const turn = `turn-${issued}`;
191
209
  unsealed.set(turn, named);
192
- return {
193
- kind: 'action',
194
- result: {
195
- turn
196
- }
197
- };
210
+ return { kind: 'action', result: { turn } };
198
211
  }
199
212
  if (name === 'conversation.cancel') {
200
213
  const turn = typeof input.turn === 'string' ? input.turn : '';
201
214
  if (sealed.has(turn) || !unsealed.has(turn)) {
202
- return {
203
- kind: 'rejected',
204
- code: 'turn-sealed',
205
- fields: {
206
- turn
207
- }
208
- };
215
+ return { kind: 'rejected', code: 'turn-sealed', fields: { turn } };
209
216
  }
210
217
  unsealed.delete(turn);
211
- return {
212
- kind: 'action',
213
- result: {
214
- turn,
215
- cancelled: true
216
- }
217
- };
218
+ return { kind: 'action', result: { turn, cancelled: true } };
218
219
  }
219
- if (name === 'conversation.delete') scripted.delete(named);
220
- return {
221
- kind: 'action',
222
- result: {
223
- conversation: named
224
- }
225
- };
220
+ if (name === 'conversation.delete')
221
+ scripted.delete(named);
222
+ return { kind: 'action', result: { conversation: named } };
226
223
  }
227
224
  function discovery() {
228
225
  return {
@@ -232,164 +229,162 @@ export function createMemoryAdapter(options = {}) {
232
229
  rooms: rooms.map(declared),
233
230
  capabilities,
234
231
  providerLimits,
235
- retention
232
+ retention,
236
233
  };
237
234
  }
238
235
  return {
239
- setRooms (next) {
240
- rooms = [
241
- ...next
242
- ];
236
+ setRooms(next) {
237
+ rooms = [...next];
243
238
  retain(rooms);
244
239
  },
245
- setConversations (next) {
240
+ setConversations(next) {
246
241
  scriptConversations(next);
247
242
  },
248
- notifyRoomVersion (notification) {
249
- for (const observer of observers)observer(notification);
243
+ notifyRoomVersion(notification) {
244
+ for (const observer of observers)
245
+ observer(notification);
250
246
  },
251
- notifyConversation (event) {
247
+ notifyConversation(event) {
252
248
  if (event.kind === 'accepted-message') {
253
249
  sealed.add(event.message.turn);
254
250
  unsealed.delete(event.message.turn);
255
251
  }
256
- for (const listener of listeners)listener(event);
252
+ for (const listener of listeners)
253
+ listener(event);
254
+ },
255
+ notifyServiceMode(mode) {
256
+ for (const observer of modeObservers)
257
+ observer(mode);
257
258
  },
258
- selectedRooms () {
259
+ selectedRooms() {
259
260
  return selected;
260
261
  },
261
- viewedConversations () {
262
- return viewed;
262
+ replicatedConversations() {
263
+ return replicated;
263
264
  },
264
265
  conversations: {
265
- view (next) {
266
- viewed = [
267
- ...next
268
- ];
266
+ replicate(next) {
267
+ replicated = [...next];
269
268
  },
270
- observe (notify) {
269
+ observe(notify) {
271
270
  listeners.add(notify);
272
- return ()=>{
271
+ return () => {
273
272
  listeners.delete(notify);
274
273
  };
275
- }
274
+ },
275
+ },
276
+ serviceMode: {
277
+ observe(notify) {
278
+ modeObservers.add(notify);
279
+ return () => {
280
+ modeObservers.delete(notify);
281
+ };
282
+ },
276
283
  },
277
284
  roomVersions: {
278
- select (locators) {
279
- selected = [
280
- ...locators
281
- ];
285
+ select(locators) {
286
+ selected = [...locators];
282
287
  },
283
- observe (notify) {
288
+ observe(notify) {
284
289
  observers.add(notify);
285
- return ()=>{
290
+ return () => {
286
291
  observers.delete(notify);
287
292
  };
288
- }
293
+ },
289
294
  },
290
- script (operation, answer) {
291
- if (answer === undefined) delete scripts[operation];
292
- else scripts[operation] = answer;
295
+ script(operation, answer) {
296
+ if (answer === undefined)
297
+ delete scripts[operation];
298
+ else
299
+ scripts[operation] = answer;
293
300
  },
294
- async model (_authorization, request) {
295
- return resolveScript(scripts.model, ()=>{
296
- const room = rooms.find((entry)=>entry.locator === request.locator);
301
+ async model(_authorization, request) {
302
+ return resolveScript(scripts.model, () => {
303
+ const room = rooms.find((entry) => entry.locator === request.locator);
297
304
  const answer = request.attached === 'collection' ? room?.model : room?.selectionModel;
298
- return answer ?? {
299
- kind: 'model-unavailable',
300
- reason: 'not-readable'
301
- };
305
+ return answer ?? { kind: 'model-unavailable', reason: 'not-readable' };
302
306
  }, request);
303
307
  },
304
- async authorize () {
305
- return resolveScript(scripts.authorize, ()=>({}), undefined);
308
+ async authorize() {
309
+ return resolveScript(scripts.authorize, () => ({}), undefined);
306
310
  },
307
- async discover (_authorization) {
308
- return resolveScript(scripts.discover, discovery, undefined);
311
+ async discover(_authorization) {
312
+ return resolveScript(scripts.discover, discovery, undefined).then((answer) => {
313
+ if (answer.kind === 'discovery')
314
+ for (const room of answer.rooms)
315
+ note(room.locator, room);
316
+ return answer;
317
+ });
309
318
  },
310
- async bootstrap (_authorization, request) {
311
- return resolveScript(scripts.bootstrap, ()=>{
312
- const room = rooms.find((entry)=>entry.locator === request.locator);
319
+ reached,
320
+ async bootstrap(_authorization, request) {
321
+ return resolveScript(scripts.bootstrap, () => {
322
+ const room = rooms.find((entry) => entry.locator === request.locator);
313
323
  if (room === undefined) {
314
- return {
315
- kind: 'room-not-readable',
316
- locator: request.locator
317
- };
324
+ return { kind: 'room-not-readable', locator: request.locator };
318
325
  }
319
326
  return page(room, request.pageToken === undefined ? 0 : Number(request.pageToken));
320
- }, request);
327
+ }, request).then((answer) => note(request.locator, answer));
321
328
  },
322
- async refresh (_authorization, request) {
323
- return resolveScript(scripts.refresh, ()=>{
324
- const room = rooms.find((entry)=>entry.locator === request.locator);
329
+ async refresh(_authorization, request) {
330
+ return resolveScript(scripts.refresh, () => {
331
+ const room = rooms.find((entry) => entry.locator === request.locator);
325
332
  if (room === undefined) {
326
- return {
327
- kind: 'room-not-readable',
328
- locator: request.locator
329
- };
333
+ return { kind: 'room-not-readable', locator: request.locator };
330
334
  }
331
335
  if (request.pageToken !== undefined) {
332
336
  const continuation = refreshPages.get(request.pageToken);
333
- if (continuation === undefined || continuation.room.locator !== request.locator || continuation.from.roomVersion !== request.fromRoomVersion) {
337
+ if (continuation === undefined ||
338
+ continuation.room.locator !== request.locator ||
339
+ continuation.from.roomVersion !== request.fromRoomVersion) {
334
340
  throw new Error('Invalid Refresh Page Token');
335
341
  }
336
342
  return advancement(continuation.room, continuation.from, continuation.at);
337
343
  }
344
+ if (request.minPosition !== undefined &&
345
+ !reached(room.locator, room.roomVersion, request.minPosition)) {
346
+ return { kind: 'retryable-refusal', code: 'replica_behind', fields: {} };
347
+ }
338
348
  if (request.fromRoomVersion === room.roomVersion) {
339
- return {
340
- kind: 'still-current'
341
- };
349
+ return { kind: 'still-current' };
342
350
  }
343
351
  const from = served.get(room.locator)?.get(request.fromRoomVersion);
344
- if (from === undefined) return {
345
- kind: 'beyond-horizon'
346
- };
352
+ if (from === undefined)
353
+ return { kind: 'beyond-horizon' };
347
354
  return advancement(room, from, 0);
348
- }, request);
355
+ }, request).then((answer) => note(request.locator, answer));
349
356
  },
350
- async mutate (_authorization, request) {
351
- return resolveScript(scripts.mutate, ()=>{
352
- const room = rooms.find((entry)=>entry.locator === request.locator);
357
+ async mutate(_authorization, request) {
358
+ return resolveScript(scripts.mutate, () => {
359
+ const room = rooms.find((entry) => entry.locator === request.locator);
353
360
  if (room === undefined) {
354
- return {
355
- kind: 'room-not-readable',
356
- locator: request.locator
357
- };
361
+ return { kind: 'room-not-readable', locator: request.locator };
358
362
  }
359
- return {
360
- kind: 'rejected',
361
- code: 'unscripted-mutation',
362
- fields: {},
363
- affected: {}
364
- };
365
- }, request);
363
+ return { kind: 'rejected', code: 'unscripted-mutation', fields: {}, affected: {} };
364
+ }, request).then((answer) => note(request.locator, answer));
366
365
  },
367
- async history (_authorization, request) {
368
- return resolveScript(scripts.history, ()=>{
369
- const room = rooms.find((entry)=>entry.locator === request.locator);
366
+ async history(_authorization, request) {
367
+ return resolveScript(scripts.history, () => {
368
+ const room = rooms.find((entry) => entry.locator === request.locator);
370
369
  if (room === undefined) {
371
- return {
372
- kind: 'room-not-readable',
373
- locator: request.locator
374
- };
370
+ return { kind: 'room-not-readable', locator: request.locator };
375
371
  }
376
372
  return {
377
373
  kind: 'history',
378
- revisions: []
374
+ revisions: [],
379
375
  };
380
376
  }, request);
381
377
  },
382
- async action (_authorization, request) {
383
- return resolveScript(scripts.action, ()=>{
384
- if (request.name.startsWith('conversation.')) return conversationAction(request);
385
- return {
386
- kind: 'rejected',
387
- code: 'unscripted-action',
388
- fields: {}
389
- };
390
- }, request);
391
- }
378
+ async action(_authorization, request) {
379
+ return resolveScript(scripts.action, () => {
380
+ if (request.name.startsWith('conversation.'))
381
+ return conversationAction(request);
382
+ return { kind: 'rejected', code: 'unscripted-action', fields: {} };
383
+ }, request).then((answer) => {
384
+ if (answer.kind === 'action' && answer.at !== undefined)
385
+ note(answer.at.locator, answer.at);
386
+ return answer;
387
+ });
388
+ },
392
389
  };
393
390
  }
394
-
395
- //# sourceMappingURL=memory.js.map