@agentshouse/mdruntime 0.1.0-cef5833f6c689 → 0.1.0-cf04ede9fb796

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 (247) hide show
  1. package/README.md +1 -1
  2. package/dist/acceptance.d.ts +6 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +389 -0
  5. package/dist/actions.d.ts +20 -0
  6. package/dist/actions.d.ts.map +1 -0
  7. package/dist/actions.js +251 -0
  8. package/dist/adapter.d.ts +24 -21
  9. package/dist/adapter.d.ts.map +1 -1
  10. package/dist/attached-model.d.ts +3 -10
  11. package/dist/attached-model.d.ts.map +1 -1
  12. package/dist/attached-model.js +21 -56
  13. package/dist/bootstrap.d.ts +8 -4
  14. package/dist/bootstrap.d.ts.map +1 -1
  15. package/dist/bootstrap.js +207 -76
  16. package/dist/cell.d.ts +6 -0
  17. package/dist/cell.d.ts.map +1 -0
  18. package/dist/cell.js +9 -0
  19. package/dist/change.d.ts +1 -0
  20. package/dist/change.d.ts.map +1 -1
  21. package/dist/chat-types.d.ts +5 -0
  22. package/dist/chat-types.d.ts.map +1 -0
  23. package/dist/chat-types.js +13 -0
  24. package/dist/client.d.ts +15 -1
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +3 -0
  27. package/dist/compile.d.ts +5 -0
  28. package/dist/compile.d.ts.map +1 -1
  29. package/dist/compile.js +189 -61
  30. package/dist/connection.d.ts +5 -141
  31. package/dist/connection.d.ts.map +1 -1
  32. package/dist/connection.js +101 -5175
  33. package/dist/conversation-live.d.ts +136 -0
  34. package/dist/conversation-live.d.ts.map +1 -0
  35. package/dist/conversation-live.js +248 -0
  36. package/dist/conversation-row.d.ts +33 -0
  37. package/dist/conversation-row.d.ts.map +1 -0
  38. package/dist/conversation-row.js +53 -0
  39. package/dist/conversation.d.ts +29 -34
  40. package/dist/conversation.d.ts.map +1 -1
  41. package/dist/conversation.js +838 -821
  42. package/dist/discovery.d.ts +10 -0
  43. package/dist/discovery.d.ts.map +1 -0
  44. package/dist/discovery.js +175 -0
  45. package/dist/durability.d.ts +15 -0
  46. package/dist/durability.d.ts.map +1 -1
  47. package/dist/entry.d.ts.map +1 -1
  48. package/dist/entry.js +4 -3
  49. package/dist/figures.d.ts +49 -0
  50. package/dist/figures.d.ts.map +1 -0
  51. package/dist/figures.js +197 -0
  52. package/dist/holdings.d.ts +29 -0
  53. package/dist/holdings.d.ts.map +1 -0
  54. package/dist/holdings.js +95 -0
  55. package/dist/host.d.ts +1 -0
  56. package/dist/host.d.ts.map +1 -1
  57. package/dist/host.js +11 -4
  58. package/dist/index.d.ts +20 -6
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +5 -1
  61. package/dist/install.d.ts +56 -0
  62. package/dist/install.d.ts.map +1 -0
  63. package/dist/install.js +556 -0
  64. package/dist/job.d.ts +20 -1
  65. package/dist/job.d.ts.map +1 -1
  66. package/dist/job.js +26 -0
  67. package/dist/lifecycle.d.ts +7 -0
  68. package/dist/lifecycle.d.ts.map +1 -0
  69. package/dist/lifecycle.js +268 -0
  70. package/dist/listing.d.ts +53 -0
  71. package/dist/listing.d.ts.map +1 -0
  72. package/dist/listing.js +176 -0
  73. package/dist/live.d.ts +4 -4
  74. package/dist/live.d.ts.map +1 -1
  75. package/dist/live.js +53 -15
  76. package/dist/locks.d.ts +9 -0
  77. package/dist/locks.d.ts.map +1 -0
  78. package/dist/locks.js +61 -0
  79. package/dist/log.d.ts +1 -0
  80. package/dist/log.d.ts.map +1 -1
  81. package/dist/lost.d.ts +5 -0
  82. package/dist/lost.d.ts.map +1 -0
  83. package/dist/lost.js +61 -0
  84. package/dist/memory.d.ts +3 -1
  85. package/dist/memory.d.ts.map +1 -1
  86. package/dist/memory.js +43 -3
  87. package/dist/messages.d.ts +25 -1
  88. package/dist/messages.d.ts.map +1 -1
  89. package/dist/messages.js +82 -3
  90. package/dist/model.d.ts +1 -7
  91. package/dist/model.d.ts.map +1 -1
  92. package/dist/model.js +0 -6
  93. package/dist/models.d.ts +14 -0
  94. package/dist/models.d.ts.map +1 -0
  95. package/dist/models.js +195 -0
  96. package/dist/opening.d.ts +4 -0
  97. package/dist/opening.d.ts.map +1 -0
  98. package/dist/opening.js +57 -0
  99. package/dist/outcome.d.ts +4 -1
  100. package/dist/outcome.d.ts.map +1 -1
  101. package/dist/outcome.js +3 -0
  102. package/dist/overlay.d.ts +1 -0
  103. package/dist/overlay.d.ts.map +1 -1
  104. package/dist/overlay.js +11 -0
  105. package/dist/parts.d.ts +60 -0
  106. package/dist/parts.d.ts.map +1 -0
  107. package/dist/parts.js +126 -0
  108. package/dist/paths.d.ts +1 -0
  109. package/dist/paths.d.ts.map +1 -1
  110. package/dist/paths.js +22 -0
  111. package/dist/preparation.d.ts +20 -0
  112. package/dist/preparation.d.ts.map +1 -0
  113. package/dist/preparation.js +226 -0
  114. package/dist/queries.d.ts +16 -0
  115. package/dist/queries.d.ts.map +1 -0
  116. package/dist/queries.js +272 -0
  117. package/dist/query.d.ts +10 -1
  118. package/dist/query.d.ts.map +1 -1
  119. package/dist/questions.d.ts +34 -0
  120. package/dist/questions.d.ts.map +1 -0
  121. package/dist/questions.js +122 -0
  122. package/dist/reach.d.ts +8 -6
  123. package/dist/reach.d.ts.map +1 -1
  124. package/dist/reach.js +159 -100
  125. package/dist/react.d.ts +7 -1
  126. package/dist/react.d.ts.map +1 -1
  127. package/dist/read.d.ts +7 -0
  128. package/dist/read.d.ts.map +1 -0
  129. package/dist/read.js +17 -0
  130. package/dist/readiness.d.ts +0 -1
  131. package/dist/readiness.d.ts.map +1 -1
  132. package/dist/reads.d.ts +37 -0
  133. package/dist/reads.d.ts.map +1 -0
  134. package/dist/reads.js +171 -0
  135. package/dist/recovery.d.ts.map +1 -1
  136. package/dist/recovery.js +9 -1
  137. package/dist/refresh.d.ts +1 -1
  138. package/dist/refresh.d.ts.map +1 -1
  139. package/dist/refresh.js +8 -20
  140. package/dist/refusal.d.ts +5 -0
  141. package/dist/refusal.d.ts.map +1 -0
  142. package/dist/refusal.js +56 -0
  143. package/dist/replica.d.ts +7 -7
  144. package/dist/replica.d.ts.map +1 -1
  145. package/dist/replica.js +50 -18
  146. package/dist/room-drafts.d.ts +24 -0
  147. package/dist/room-drafts.d.ts.map +1 -0
  148. package/dist/room-drafts.js +216 -0
  149. package/dist/rows.d.ts +14 -5
  150. package/dist/rows.d.ts.map +1 -1
  151. package/dist/rows.js +50 -58
  152. package/dist/runtime.d.ts +43 -0
  153. package/dist/runtime.d.ts.map +1 -0
  154. package/dist/runtime.js +1 -0
  155. package/dist/save.d.ts +5 -1
  156. package/dist/save.d.ts.map +1 -1
  157. package/dist/save.js +19 -13
  158. package/dist/saves.d.ts +70 -0
  159. package/dist/saves.d.ts.map +1 -0
  160. package/dist/saves.js +1008 -0
  161. package/dist/seed.d.ts +11 -2
  162. package/dist/seed.d.ts.map +1 -1
  163. package/dist/seed.js +71 -0
  164. package/dist/shared.d.ts +1 -1
  165. package/dist/shared.d.ts.map +1 -1
  166. package/dist/shared.js +9 -5
  167. package/dist/shown.d.ts +31 -0
  168. package/dist/shown.d.ts.map +1 -0
  169. package/dist/shown.js +295 -0
  170. package/dist/socket/admission.d.ts +7 -0
  171. package/dist/socket/admission.d.ts.map +1 -0
  172. package/dist/socket/admission.js +39 -0
  173. package/dist/socket/answers.d.ts +6 -0
  174. package/dist/socket/answers.d.ts.map +1 -0
  175. package/dist/socket/answers.js +20 -0
  176. package/dist/socket/lanes.d.ts +20 -0
  177. package/dist/socket/lanes.d.ts.map +1 -0
  178. package/dist/socket/lanes.js +77 -0
  179. package/dist/socket/reads.d.ts +10 -0
  180. package/dist/socket/reads.d.ts.map +1 -0
  181. package/dist/socket/reads.js +31 -0
  182. package/dist/socket/rooms.d.ts +44 -0
  183. package/dist/socket/rooms.d.ts.map +1 -0
  184. package/dist/socket/rooms.js +90 -0
  185. package/dist/socket/session.d.ts +39 -0
  186. package/dist/socket/session.d.ts.map +1 -0
  187. package/dist/socket/session.js +23 -0
  188. package/dist/socket.d.ts +70 -0
  189. package/dist/socket.d.ts.map +1 -0
  190. package/dist/socket.js +175 -0
  191. package/dist/source.d.ts +61 -0
  192. package/dist/source.d.ts.map +1 -0
  193. package/dist/source.js +81 -0
  194. package/dist/status.d.ts +0 -2
  195. package/dist/status.d.ts.map +1 -1
  196. package/dist/status.js +0 -6
  197. package/dist/store/fences.d.ts +16 -0
  198. package/dist/store/fences.d.ts.map +1 -0
  199. package/dist/store/fences.js +26 -0
  200. package/dist/store/installs.d.ts +30 -0
  201. package/dist/store/installs.d.ts.map +1 -0
  202. package/dist/store/installs.js +34 -0
  203. package/dist/store/readiness.d.ts +10 -0
  204. package/dist/store/readiness.d.ts.map +1 -0
  205. package/dist/store/readiness.js +52 -0
  206. package/dist/store/records.d.ts +212 -0
  207. package/dist/store/records.d.ts.map +1 -0
  208. package/dist/store/records.js +431 -0
  209. package/dist/store/room-held.d.ts +8 -0
  210. package/dist/store/room-held.d.ts.map +1 -0
  211. package/dist/store/room-held.js +17 -0
  212. package/dist/store/space.d.ts +11 -0
  213. package/dist/store/space.d.ts.map +1 -0
  214. package/dist/store/space.js +43 -0
  215. package/dist/store/watchers.d.ts +17 -0
  216. package/dist/store/watchers.d.ts.map +1 -0
  217. package/dist/store/watchers.js +57 -0
  218. package/dist/store/writes.d.ts +24 -0
  219. package/dist/store/writes.d.ts.map +1 -0
  220. package/dist/store/writes.js +125 -0
  221. package/dist/store.d.ts +107 -152
  222. package/dist/store.d.ts.map +1 -1
  223. package/dist/store.js +143 -394
  224. package/dist/stored.d.ts +58 -64
  225. package/dist/stored.d.ts.map +1 -1
  226. package/dist/stored.js +253 -147
  227. package/dist/surface.d.ts +88 -0
  228. package/dist/surface.d.ts.map +1 -0
  229. package/dist/surface.js +223 -0
  230. package/dist/sync.d.ts +19 -0
  231. package/dist/sync.d.ts.map +1 -0
  232. package/dist/sync.js +532 -0
  233. package/dist/tables.d.ts +114 -49
  234. package/dist/tables.d.ts.map +1 -1
  235. package/dist/tables.js +203 -49
  236. package/dist/tallies.d.ts +18 -0
  237. package/dist/tallies.d.ts.map +1 -0
  238. package/dist/tallies.js +129 -0
  239. package/dist/validation.d.ts.map +1 -1
  240. package/dist/validation.js +4 -4
  241. package/dist/wire.d.ts +16 -1
  242. package/dist/wire.d.ts.map +1 -1
  243. package/dist/wire.js +6 -0
  244. package/package.json +2 -2
  245. package/dist/fence.d.ts +0 -6
  246. package/dist/fence.d.ts.map +0 -1
  247. package/dist/fence.js +0 -10
package/README.md CHANGED
@@ -50,7 +50,7 @@ chat.unmount();
50
50
 
51
51
  The rules an App's agent follows, including Local Query, search, Room
52
52
  Draft, Save and the Chat, are the `apps/` pages of House's Guide, which House's
53
- `open_guide` opens.
53
+ `guide/open` opens.
54
54
 
55
55
  ## License
56
56
 
@@ -0,0 +1,6 @@
1
+ import type { Runtime } from './runtime.js';
2
+ import type { RuntimeStore } from './store.js';
3
+ export declare function unpair(runtime: Runtime, local: RuntimeStore): Promise<void>;
4
+ export declare function submitLater(runtime: Runtime, locator: string): void;
5
+ export declare function submitAll(runtime: Runtime): Promise<void>;
6
+ //# sourceMappingURL=acceptance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance.d.ts","sourceRoot":"","sources":["../src/acceptance.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,YAAY,CAAC;AAkO5D,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBjF;AAoOD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAK5D;AA4BD,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,iBAM/C"}
@@ -0,0 +1,389 @@
1
+ import { changeSet } from './change-set.js';
2
+ import { leaving as leavingIn, partnerOf } from './change.js';
3
+ import { runtimeError } from './failure.js';
4
+ import { olderThan, showing } from './install.js';
5
+ import { readable } from './listing.js';
6
+ import { refuse } from './refusal.js';
7
+ import { landed, returnedPaths, returning, slicing, touchedBy } from './replica.js';
8
+ import { batchFile, landedWhole, settle, settlement, sliceAt, together, unpairing, withdrawable, } from './saves.js';
9
+ import { rest, roomUnreadable, statusShown } from './shown.js';
10
+ import { unconfirmed } from './transfer.js';
11
+ import { stepped } from './turn.js';
12
+ function pendingKey(locator, id) {
13
+ return `${locator}\u0000${id}`;
14
+ }
15
+ async function mark(runtime, local, locator, batch, submission, lost) {
16
+ const { store, socket } = runtime;
17
+ const partner = partnerOf(batch, locator);
18
+ for (const held of partner === null ? [locator] : [locator, partner]) {
19
+ const { state, room } = await local.pending(held, batch.id);
20
+ if (!socket.continuing() ||
21
+ state === undefined ||
22
+ (JSON.stringify(state.submission) === JSON.stringify(submission) && state.lost === lost)) {
23
+ continue;
24
+ }
25
+ await local.submit(held, batch.id, submission, lost);
26
+ if (store.fences.has(held))
27
+ continue;
28
+ if (room)
29
+ store.changed(changeSet(held, { queue: true }));
30
+ }
31
+ statusShown(runtime);
32
+ }
33
+ async function keepUpload({ store, socket }, local, locator, identifier, upload) {
34
+ if (!socket.continuing())
35
+ throw new Error('connection refused');
36
+ await local.keepUpload(locator, identifier, upload);
37
+ if (store.fences.has(locator))
38
+ throw runtimeError('unknown-room', `Unknown Room ${locator}`);
39
+ if (!socket.continuing())
40
+ throw new Error('connection refused');
41
+ }
42
+ function leaving(batch, result) {
43
+ return {
44
+ batch,
45
+ returned: {
46
+ kind: result.kind,
47
+ code: result.code,
48
+ fields: result.fields,
49
+ retryable: result.retryable,
50
+ },
51
+ };
52
+ }
53
+ function logAccepted({ journal }, locator, submitted, accepted) {
54
+ journal.record(`outcome ${locator} ${submitted.id} accepted ${accepted.roomVersion}` +
55
+ (accepted.author === undefined ? '' : ` author ${accepted.author}`) +
56
+ (accepted.time === undefined ? '' : ` time ${accepted.time}`));
57
+ }
58
+ function settling(acceptance) {
59
+ return acceptance !== null && 'apply' in acceptance;
60
+ }
61
+ function failureOf(acceptance) {
62
+ return settling(acceptance) ? null : acceptance;
63
+ }
64
+ async function acceptance(runtime, room, local, submitted, accepted) {
65
+ const { store, socket } = runtime;
66
+ if (!socket.continuing())
67
+ return unconfirmed;
68
+ const work = await store.work(room.locator);
69
+ const current = work.replica;
70
+ if (current === undefined || !current.queue.some((batch) => batch.id === submitted.id)) {
71
+ return null;
72
+ }
73
+ const held = current.record.roomVersion;
74
+ logAccepted(runtime, room.locator, submitted, accepted);
75
+ let record = current.record;
76
+ let changes;
77
+ if (!socket.reads.reached(room.locator, held, accepted.roomVersion) &&
78
+ !olderThan(runtime, room.locator, accepted.roomVersion, held)) {
79
+ const paths = [...returnedPaths(submitted, accepted)];
80
+ const confirmedLayer = await stepped(slicing(await local.entries(record.key, 'confirmed', paths), paths));
81
+ const back = await stepped(returning(confirmedLayer, submitted, accepted, accepted.roomVersion, store.composed(record)));
82
+ record = {
83
+ ...record,
84
+ roomVersion: socket.follows(room.locator, held, accepted.roomVersion)
85
+ ? accepted.roomVersion
86
+ : held,
87
+ };
88
+ changes = back;
89
+ }
90
+ const settled = await settlement(runtime, local, room.locator, work, record, current.queue.filter((batch) => batch.id !== submitted.id), { room: true, ...(changes === undefined ? {} : { changes }) });
91
+ const reached = record.roomVersion;
92
+ return {
93
+ ...settled,
94
+ apply(answer) {
95
+ const set = settled.apply(answer);
96
+ showing(runtime, room.locator, accepted.roomVersion, reached);
97
+ readable(runtime, room);
98
+ return set;
99
+ },
100
+ };
101
+ }
102
+ async function adoptedTogether(runtime, local, acceptances) {
103
+ const settlements = acceptances.filter(settling);
104
+ if (settlements.length > 0) {
105
+ const set = await together(runtime, local, settlements);
106
+ void statusShown(runtime);
107
+ void runtime.store.changed(set);
108
+ }
109
+ await unpair(runtime, local);
110
+ }
111
+ async function adopted(runtime, room, local, submitted, accepted) {
112
+ const failed = await runtime.store.exclusive(async () => {
113
+ const adopting = await acceptance(runtime, room, local, submitted, accepted);
114
+ await adoptedTogether(runtime, local, [adopting]);
115
+ return failureOf(adopting);
116
+ });
117
+ return failed === null;
118
+ }
119
+ async function adoptedMove(runtime, room, partner, local, submitted, accepted) {
120
+ const { store, socket } = runtime;
121
+ const other = socket.rooms.discovered(partner);
122
+ const failed = await store.exclusive(async () => {
123
+ const left = await acceptance(runtime, room, local, submitted, accepted);
124
+ const arriving = (await store.replica(partner))?.queue.find((batch) => batch.id === submitted.id);
125
+ const arrived = other === undefined || arriving === undefined || accepted.destination === undefined
126
+ ? null
127
+ : await acceptance(runtime, other, local, arriving, {
128
+ kind: 'accepted',
129
+ ...accepted.destination,
130
+ });
131
+ await adoptedTogether(runtime, local, [left, arrived]);
132
+ return failureOf(left);
133
+ });
134
+ submitLater(runtime, partner);
135
+ return failed === null;
136
+ }
137
+ async function behindIn({ store }, locator, batch) {
138
+ const local = await store.open();
139
+ const [order, { room }] = await Promise.all([
140
+ local.order(locator),
141
+ local.pending(locator, batch.id),
142
+ ]);
143
+ return room ? order.indexOf(batch.id) > 0 : order.length > 0;
144
+ }
145
+ async function unpaired(local, skipped) {
146
+ const { queued, moving } = await local.moving();
147
+ for (const { locator, batch, state } of moving) {
148
+ const partner = partnerOf(batch, locator);
149
+ if (partner === null || skipped.has(pendingKey(locator, batch.id)))
150
+ continue;
151
+ if (queued.get(partner)?.includes(batch.id) === true)
152
+ continue;
153
+ if (!leavingIn(batch, locator) || withdrawable(new Map([[batch.id, state]]))(batch)) {
154
+ return { locator, batch };
155
+ }
156
+ }
157
+ return null;
158
+ }
159
+ export async function unpair(runtime, local) {
160
+ const { store, socket } = runtime;
161
+ const handled = new Set();
162
+ for (let held = await unpaired(local, handled); held !== null && socket.continuing(); held = await unpaired(local, handled)) {
163
+ const { locator, batch } = held;
164
+ handled.add(pendingKey(locator, batch.id));
165
+ store.changed(await together(runtime, local, [await unpairing(runtime, local, locator, [batch])]));
166
+ }
167
+ if (handled.size === 0)
168
+ return;
169
+ statusShown(runtime);
170
+ }
171
+ async function submitRoom(runtime, room, local, authorized, progress, signal) {
172
+ const { store, socket, journal, advanced, withhold } = runtime;
173
+ while (socket.continuing() &&
174
+ socket.session.now().authorization !== undefined &&
175
+ !signal.aborted) {
176
+ const headId = (await local.order(room.locator)).find((id) => store.landed.of(room.locator, id) === undefined);
177
+ if (headId === undefined)
178
+ return 'done';
179
+ const [head, pending] = await Promise.all([
180
+ local.batch(room.locator, headId),
181
+ local.pending(room.locator, headId),
182
+ ]);
183
+ if (head === null || !pending.room)
184
+ return 'done';
185
+ const { state } = pending;
186
+ const partner = partnerOf(head, room.locator);
187
+ if (partner !== null && !leavingIn(head, room.locator)) {
188
+ submitLater(runtime, partner);
189
+ return 'done';
190
+ }
191
+ if (partner !== null && (await behindIn(runtime, partner, head))) {
192
+ progress.complete = false;
193
+ return 'done';
194
+ }
195
+ const { submission, lost: earlier } = state ?? {
196
+ submission: { state: 'waiting' },
197
+ lost: false,
198
+ };
199
+ if (submission.state === 'reset' && Date.now() < Date.parse(submission.reset)) {
200
+ progress.complete = false;
201
+ return { at: Date.parse(submission.reset) };
202
+ }
203
+ if (socket.writesHeld()) {
204
+ progress.complete = false;
205
+ journal.record(`submission ${room.locator} ${head.id} held`);
206
+ return 'done';
207
+ }
208
+ const lost = earlier || submission.state === 'submitted';
209
+ let result;
210
+ journal.record(`submission ${room.locator} ${head.id}`);
211
+ await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'submitted' }, lost));
212
+ if (socket.session.now().paused || store.fences.has(room.locator))
213
+ return 'done';
214
+ if (signal.aborted || socket.writesHeld()) {
215
+ await store.exclusive(() => mark(runtime, local, room.locator, head, submission, earlier));
216
+ if (signal.aborted)
217
+ return 'done';
218
+ progress.complete = false;
219
+ journal.record(`submission ${room.locator} ${head.id} held`);
220
+ return 'done';
221
+ }
222
+ const opensBefore = socket.session.now().openSignals;
223
+ const answeredHere = socket.awaitingAnswer(room.locator);
224
+ const answeredThere = partner === null ? () => { } : socket.awaitingAnswer(partner);
225
+ const answered = () => {
226
+ answeredHere();
227
+ answeredThere();
228
+ };
229
+ try {
230
+ result = await socket.mutate(authorized, {
231
+ locator: room.locator,
232
+ changeBatch: head,
233
+ file: batchFile(store, head),
234
+ ...(state?.upload === undefined ? {} : { upload: state.upload }),
235
+ }, (upload) => store.exclusive(() => keepUpload(runtime, local, room.locator, head.id, upload)));
236
+ }
237
+ catch {
238
+ answered();
239
+ progress.complete = false;
240
+ if (socket.continuing())
241
+ progress.reachable = false;
242
+ return 'again';
243
+ }
244
+ if (signal.aborted) {
245
+ answered();
246
+ return 'done';
247
+ }
248
+ if (result.kind !== 'accepted' || !socket.continuing())
249
+ answered();
250
+ if (!socket.continuing())
251
+ return 'done';
252
+ if (result.kind === 'transport-uncertainty') {
253
+ progress.complete = false;
254
+ progress.reachable = false;
255
+ return 'again';
256
+ }
257
+ if (result.kind === 'room-not-readable') {
258
+ progress.complete = false;
259
+ roomUnreadable(runtime, socket.rooms.discovered(result.locator) ?? room);
260
+ return 'done';
261
+ }
262
+ if (result.kind === 'revoked-authorization') {
263
+ await refuse(runtime, 'revoked-authorization');
264
+ return 'done';
265
+ }
266
+ if (result.kind === 'scoped-refusal') {
267
+ await runtime.scoped(result, room, local);
268
+ progress.complete = false;
269
+ return 'done';
270
+ }
271
+ if (result.kind === 'write-halted') {
272
+ journal.record(`outcome ${room.locator} ${head.id} write-halted`);
273
+ await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'waiting' }, lost));
274
+ if (!socket.haltedSince(opensBefore))
275
+ continue;
276
+ progress.complete = false;
277
+ return 'done';
278
+ }
279
+ const other = partner === null ? undefined : socket.rooms.discovered(partner);
280
+ if (result.kind === 'conflicted' ||
281
+ result.kind === 'rejected' ||
282
+ result.kind === 'retryable-refusal') {
283
+ journal.record(`outcome ${room.locator} ${head.id} ${result.kind}` +
284
+ (result.kind === 'conflicted' && result.roomVersion !== undefined
285
+ ? ` ${result.roomVersion}`
286
+ : ''));
287
+ journal.record(`refusal ${result.kind} ${result.code}`);
288
+ }
289
+ if (result.kind === 'retryable-refusal') {
290
+ const reset = result.reset;
291
+ progress.complete = false;
292
+ await store.exclusive(() => mark(runtime, local, room.locator, head, reset === undefined ? { state: 'waiting' } : { state: 'reset', reset }, lost));
293
+ return reset === undefined ? 'again' : { at: Date.parse(reset) };
294
+ }
295
+ if (result.kind === 'conflicted' || result.kind === 'rejected') {
296
+ const left = leaving(head, result);
297
+ const refreshed = async () => ({
298
+ there: other === undefined ? null : await advanced(other, local, authorized),
299
+ here: await advanced(room, local, authorized),
300
+ });
301
+ const judged = result.kind === 'conflicted' && other !== undefined ? await refreshed() : null;
302
+ if (judged !== null && (judged.there !== null || judged.here !== null)) {
303
+ await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'waiting' }, lost));
304
+ if (other !== undefined && judged.there !== null) {
305
+ await withhold(judged.there, other, local, progress);
306
+ }
307
+ if (judged.here !== null)
308
+ await withhold(judged.here, room, local, progress);
309
+ return 'done';
310
+ }
311
+ await store.exclusive(async () => {
312
+ if (!socket.continuing())
313
+ return;
314
+ const work = await store.work(room.locator);
315
+ const current = work.replica;
316
+ if (current === undefined || !current.queue.some((batch) => batch.id === head.id)) {
317
+ return;
318
+ }
319
+ const confirmedLayer = await sliceAt(store, current.record, 'confirmed', [head]);
320
+ const held = result.kind === 'conflicted' &&
321
+ (await landedWhole(store, room.locator, head, confirmedLayer, result.affected));
322
+ if (held &&
323
+ result.kind === 'conflicted' &&
324
+ partner === null &&
325
+ !landed(head, confirmedLayer)) {
326
+ store.landed.hold(room.locator, head.id, Object.fromEntries([...touchedBy([head])].map((path) => [path, confirmedLayer.revisions[path]])));
327
+ return;
328
+ }
329
+ store.changed(await settle(runtime, local, room.locator, work, current.record, current.queue.filter((batch) => batch.id !== head.id), { leaving: [held ? { ...left, returned: null } : left] }));
330
+ await unpair(runtime, local);
331
+ statusShown(runtime);
332
+ });
333
+ const { there, here } = judged ?? (await refreshed());
334
+ if (other !== undefined && there !== null)
335
+ await withhold(there, other, local, progress);
336
+ if (here !== null) {
337
+ await withhold(here, room, local, progress);
338
+ return 'done';
339
+ }
340
+ continue;
341
+ }
342
+ const kept = await (partner === null
343
+ ? adopted(runtime, room, local, head, result)
344
+ : adoptedMove(runtime, room, partner, local, head, result)).finally(answered);
345
+ if (!kept) {
346
+ progress.complete = false;
347
+ return 'done';
348
+ }
349
+ }
350
+ return 'done';
351
+ }
352
+ export function submitLater(runtime, locator) {
353
+ if (runtime.localSaves)
354
+ return;
355
+ void runtime.recovery.attempt(`submit ${locator}`, (signal) => submitPass(runtime, locator, signal));
356
+ }
357
+ async function submitPass(runtime, locator, signal) {
358
+ const { store, socket } = runtime;
359
+ const room = socket.rooms.discovered(locator);
360
+ if (!socket.continuing() || socket.stopping() || room === undefined) {
361
+ return 'done';
362
+ }
363
+ const progress = { complete: true, reachable: true };
364
+ let next;
365
+ try {
366
+ await socket.authorize();
367
+ const { authorization } = socket.session.now();
368
+ if (authorization === undefined)
369
+ return 'done';
370
+ next = await submitRoom(runtime, room, await store.open(), authorization, progress, signal);
371
+ }
372
+ catch {
373
+ progress.reachable = false;
374
+ next = 'again';
375
+ }
376
+ if (signal.aborted)
377
+ return 'done';
378
+ await rest(runtime, progress);
379
+ return next === 'again' && !socket.isOpen() ? 'done' : next;
380
+ }
381
+ export async function submitAll(runtime) {
382
+ const { store } = runtime;
383
+ if (runtime.localSaves)
384
+ return;
385
+ for (const locator of await (await store.open()).queued()) {
386
+ if (!store.fences.has(locator))
387
+ submitLater(runtime, locator);
388
+ }
389
+ }
@@ -0,0 +1,20 @@
1
+ import type { ConversationHistoryRequest } from './adapter.js';
2
+ import { type CallResult, type HistoryAnswer, type Resolution } from './outcome.js';
3
+ import type { Attempted } from './recovery.js';
4
+ import type { Runtime } from './runtime.js';
5
+ export type HistoryQuery = {
6
+ revision?: string;
7
+ pageToken?: string;
8
+ };
9
+ export declare function readHistory(runtime: Runtime, locator: string, path: string, query?: HistoryQuery): Promise<HistoryAnswer>;
10
+ export declare function located(runtime: Runtime, room: string, path: string, destination: string): Promise<{
11
+ room: string;
12
+ path: string;
13
+ } | null>;
14
+ export declare function resolveReference(runtime: Runtime, room: string, path: string, destination: string): Promise<Resolution>;
15
+ export declare function invokeAction(runtime: Runtime, name: string, input: unknown, dispatching?: () => Promise<void>): Promise<CallResult>;
16
+ export declare function readConversationHistory(runtime: Runtime, request: ConversationHistoryRequest): Promise<CallResult>;
17
+ export declare function called(runtime: Runtime, name: string, input: unknown): Promise<CallResult>;
18
+ export declare function resendCalls(runtime: Runtime, signal: AbortSignal): Promise<Attempted>;
19
+ export declare function resendLater(runtime: Runtime): void;
20
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAK/D,OAAO,EAUL,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAG5C,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF,wBAAsB,WAAW,CAC/B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,YAAiB,GACvB,OAAO,CAAC,aAAa,CAAC,CAqCxB;AAED,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAShD;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAwBD,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAChC,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,UAAU,CAAC,CAiBrB;AAuCD,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAKhG;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAiB3F;AAiBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAG3C"}
@@ -0,0 +1,251 @@
1
+ import { roomTarget, target } from '@agentshouse/mdmodel';
2
+ import { resendConversations } from './conversation.js';
3
+ import { listingNow } from './listing.js';
4
+ import { locked, lockedRooms } from './locks.js';
5
+ import { scoped } from './models.js';
6
+ import { ABSENT_TARGET, calledResult, failure, historyAnswer, LOCKED_UNREADABLE, lockedRoom, undeclared, UNCERTAIN, UNREADABLE, } from './outcome.js';
7
+ import { refuse } from './refusal.js';
8
+ function operationOf(input) {
9
+ const operation = input?.operation_id;
10
+ return typeof operation === 'string' ? operation : null;
11
+ }
12
+ export async function readHistory(runtime, locator, path, query = {}) {
13
+ const { store, socket, journal } = runtime;
14
+ const { session } = socket;
15
+ if (socket.closed() || session.now().refusal !== null)
16
+ return UNCERTAIN;
17
+ await socket.firstDiscovery;
18
+ if (!session.now().roomsNamed)
19
+ return UNCERTAIN;
20
+ try {
21
+ await socket.authorize();
22
+ }
23
+ catch {
24
+ return UNCERTAIN;
25
+ }
26
+ const { closed, authorization, refusal } = session.now();
27
+ if (closed || authorization === undefined || refusal !== null)
28
+ return UNCERTAIN;
29
+ const since = store.fences.count();
30
+ const transfer = ['transfer', 'history', locator, path];
31
+ if (query.revision !== undefined)
32
+ transfer.push(query.revision);
33
+ if (query.pageToken !== undefined)
34
+ transfer.push(query.pageToken);
35
+ journal.record(transfer.join(' '));
36
+ try {
37
+ const result = await socket.history(authorization, {
38
+ locator,
39
+ path,
40
+ ...(query.revision === undefined ? {} : { revision: query.revision }),
41
+ ...(query.pageToken === undefined ? {} : { pageToken: query.pageToken }),
42
+ });
43
+ journal.record(`outcome history ${result.kind}`);
44
+ if (store.fences.since(locator, since))
45
+ return failure({ kind: 'room-not-readable', locator });
46
+ if (result.kind === 'scoped-refusal') {
47
+ const room = await store.record(result.locator);
48
+ if (room !== undefined)
49
+ await scoped(runtime, result, room, await store.open());
50
+ }
51
+ if (result.kind === 'revoked-authorization')
52
+ await refuse(runtime, 'revoked-authorization');
53
+ return historyAnswer(result);
54
+ }
55
+ catch {
56
+ journal.record('outcome history transport-uncertainty');
57
+ return UNCERTAIN;
58
+ }
59
+ }
60
+ export async function located(runtime, room, path, destination) {
61
+ const crossing = roomTarget(destination);
62
+ const listing = await listingNow(runtime);
63
+ if (crossing === null) {
64
+ const named = target(path, destination);
65
+ return named === null || !listing.has(room) ? null : { room, path: named };
66
+ }
67
+ const held = [...listing.values()].find((listed) => listed.handle === crossing.handle);
68
+ return held === undefined ? null : { room: held.locator, path: crossing.path };
69
+ }
70
+ export async function resolveReference(runtime, room, path, destination) {
71
+ const { store } = runtime;
72
+ if (roomTarget(destination) === null && target(path, destination) === null) {
73
+ return ABSENT_TARGET;
74
+ }
75
+ const at = await located(runtime, room, path, destination);
76
+ if (at === null)
77
+ return UNREADABLE;
78
+ if (await locked(runtime, at.room))
79
+ return LOCKED_UNREADABLE;
80
+ const held = await store.record(at.room);
81
+ if (held !== undefined &&
82
+ (await (await store.open()).entries(held.key, 'visible', [at.path])).length > 0) {
83
+ return { kind: 'document', ...at };
84
+ }
85
+ const history = await readHistory(runtime, at.room, at.path);
86
+ if (history.kind === 'no-history' || history.kind === 'revision')
87
+ return ABSENT_TARGET;
88
+ if (history.kind !== 'history')
89
+ return history;
90
+ const [last] = history.revisions;
91
+ if (last === undefined)
92
+ return ABSENT_TARGET;
93
+ return history.deleted === true
94
+ ? { kind: 'deleted', ...at, revision: last }
95
+ : { kind: 'document', ...at };
96
+ }
97
+ async function declaredAction({ store }, name) {
98
+ for (const capability of (await (await store.open()).facts()).capabilities) {
99
+ for (const action of capability.actions ?? []) {
100
+ if (action.name === name)
101
+ return action;
102
+ }
103
+ }
104
+ return undefined;
105
+ }
106
+ async function calledRooms(runtime, name, input) {
107
+ const member = (await declaredAction(runtime, name))?.room;
108
+ if (member === undefined || input === null || typeof input !== 'object')
109
+ return [];
110
+ const named = input[member];
111
+ return (Array.isArray(named) ? named : [named]).filter((room) => typeof room === 'string');
112
+ }
113
+ export async function invokeAction(runtime, name, input, dispatching) {
114
+ const { store, socket, journal } = runtime;
115
+ const { session } = socket;
116
+ await socket.ready;
117
+ if (socket.closed() || session.now().refusal !== null)
118
+ return UNCERTAIN;
119
+ if ((await declaredAction(runtime, name)) === undefined)
120
+ return undeclared(name);
121
+ try {
122
+ await socket.authorize();
123
+ }
124
+ catch {
125
+ return UNCERTAIN;
126
+ }
127
+ const { closed, authorization, refusal } = session.now();
128
+ if (closed || authorization === undefined || refusal !== null)
129
+ return UNCERTAIN;
130
+ await dispatching?.();
131
+ journal.record(`transfer action ${name}`);
132
+ try {
133
+ const result = await socket.action(authorization, { name, input });
134
+ if (result.kind === 'scoped-refusal') {
135
+ const room = await store.record(result.locator);
136
+ if (room !== undefined)
137
+ await scoped(runtime, result, room, await store.open());
138
+ }
139
+ if (result.kind === 'revoked-authorization')
140
+ await refuse(runtime, 'revoked-authorization');
141
+ journal.record(`outcome action ${result.kind}`);
142
+ if (result.kind === 'rejected')
143
+ journal.record(`refusal rejected ${result.code}`);
144
+ return calledResult(result);
145
+ }
146
+ catch {
147
+ journal.record('outcome action transport-uncertainty');
148
+ return UNCERTAIN;
149
+ }
150
+ }
151
+ export async function readConversationHistory(runtime, request) {
152
+ const { socket, journal } = runtime;
153
+ await socket.ready;
154
+ const stream = socket.conversations();
155
+ if (socket.closed() || socket.session.now().refusal !== null || stream?.history === undefined) {
156
+ return UNCERTAIN;
157
+ }
158
+ journal.record('transfer conversation history');
159
+ try {
160
+ const result = await stream.history(request);
161
+ if (result.kind === 'revoked-authorization')
162
+ await refuse(runtime, 'revoked-authorization');
163
+ journal.record(`outcome conversation history ${result.kind}`);
164
+ return calledResult(result);
165
+ }
166
+ catch {
167
+ journal.record('outcome conversation history transport-uncertainty');
168
+ return UNCERTAIN;
169
+ }
170
+ }
171
+ function unsettled(result) {
172
+ if (result.kind === 'action')
173
+ return false;
174
+ return result.retryable && (result.kind !== 'rejected' || result.reset === undefined);
175
+ }
176
+ async function recoveredAction(runtime, name, input) {
177
+ const { store, socket, recovery } = runtime;
178
+ const { lanes } = socket;
179
+ const operation = operationOf(input);
180
+ if (operation === null)
181
+ return invokeAction(runtime, name, input);
182
+ const kept = async () => (await store.open()).keepCall({ operation, name, input });
183
+ lanes.call(operation);
184
+ try {
185
+ let result = await invokeAction(runtime, name, input, kept);
186
+ if (unsettled(result)) {
187
+ await recovery.attempt(`action ${operation}`, async () => {
188
+ if (socket.closed() || socket.session.now().refusal !== null)
189
+ return 'done';
190
+ if (!socket.isOpen())
191
+ return 'again';
192
+ result = await invokeAction(runtime, name, input, kept);
193
+ return unsettled(result) ? 'again' : 'done';
194
+ }, { again: true });
195
+ }
196
+ if (!unsettled(result))
197
+ await (await store.open()).dropCall(operation);
198
+ return result;
199
+ }
200
+ finally {
201
+ lanes.called(operation);
202
+ }
203
+ }
204
+ export async function called(runtime, name, input) {
205
+ await runtime.socket.ready;
206
+ const lockedNow = await lockedRooms(runtime);
207
+ const room = (await calledRooms(runtime, name, input)).find((one) => lockedNow.includes(one));
208
+ return room === undefined ? recoveredAction(runtime, name, input) : lockedRoom(room);
209
+ }
210
+ export async function resendCalls(runtime, signal) {
211
+ const { store, socket } = runtime;
212
+ const { lanes } = socket;
213
+ if (!socket.isOpen() || socket.closed() || socket.stopping())
214
+ return 'done';
215
+ const local = await store.open();
216
+ for (const held of await local.calls()) {
217
+ if (lanes.calling(held.operation))
218
+ continue;
219
+ if (socket.closed() || signal.aborted)
220
+ return 'done';
221
+ lanes.call(held.operation);
222
+ try {
223
+ if (unsettled(await invokeAction(runtime, held.name, held.input)))
224
+ return 'again';
225
+ await local.dropCall(held.operation);
226
+ }
227
+ finally {
228
+ lanes.called(held.operation);
229
+ }
230
+ }
231
+ return 'done';
232
+ }
233
+ async function resendPass({ socket, conversations }, signal) {
234
+ if (!socket.continuing() || !socket.isOpen() || socket.stopping())
235
+ return 'done';
236
+ const reading = { complete: true, reachable: true };
237
+ try {
238
+ await resendConversations(conversations, reading);
239
+ }
240
+ catch {
241
+ reading.reachable = false;
242
+ }
243
+ if (signal.aborted)
244
+ return 'done';
245
+ return reading.reachable && reading.complete ? 'done' : 'again';
246
+ }
247
+ export function resendLater(runtime) {
248
+ if (!runtime.socket.isOpen())
249
+ return;
250
+ void runtime.recovery.attempt('resend', (signal) => resendPass(runtime, signal), { again: true });
251
+ }