@agentshouse/mdruntime 0.1.0-c0136de3edfbe → 0.1.0-c01d4615bfe46

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 (245) hide show
  1. package/README.md +16 -15
  2. package/dist/acceptance.d.ts +0 -3
  3. package/dist/acceptance.d.ts.map +1 -1
  4. package/dist/acceptance.js +74 -164
  5. package/dist/act-lanes.d.ts +30 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +225 -0
  8. package/dist/actions.d.ts +8 -2
  9. package/dist/actions.d.ts.map +1 -1
  10. package/dist/actions.js +122 -68
  11. package/dist/adapter.d.ts +49 -55
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +0 -1
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +0 -5
  16. package/dist/bootstrap.d.ts +1 -1
  17. package/dist/bootstrap.d.ts.map +1 -1
  18. package/dist/bootstrap.js +6 -18
  19. package/dist/change-set.d.ts +4 -0
  20. package/dist/change-set.d.ts.map +1 -1
  21. package/dist/change-set.js +6 -0
  22. package/dist/change.d.ts.map +1 -1
  23. package/dist/change.js +4 -2
  24. package/dist/chat-types.d.ts +2 -2
  25. package/dist/chat-types.d.ts.map +1 -1
  26. package/dist/chat-types.js +11 -2
  27. package/dist/client.d.ts +13 -19
  28. package/dist/client.d.ts.map +1 -1
  29. package/dist/client.js +35 -19
  30. package/dist/collection.d.ts +22 -4
  31. package/dist/collection.d.ts.map +1 -1
  32. package/dist/collection.js +12 -2
  33. package/dist/compile.d.ts +2 -0
  34. package/dist/compile.d.ts.map +1 -1
  35. package/dist/compile.js +31 -24
  36. package/dist/connection.d.ts.map +1 -1
  37. package/dist/connection.js +32 -24
  38. package/dist/conversation-live.d.ts +147 -0
  39. package/dist/conversation-live.d.ts.map +1 -0
  40. package/dist/conversation-live.js +258 -0
  41. package/dist/conversation-row.d.ts.map +1 -1
  42. package/dist/conversation-row.js +7 -1
  43. package/dist/conversation.d.ts +52 -44
  44. package/dist/conversation.d.ts.map +1 -1
  45. package/dist/conversation.js +956 -1029
  46. package/dist/declaration.d.ts +10 -0
  47. package/dist/declaration.d.ts.map +1 -0
  48. package/dist/declaration.js +24 -0
  49. package/dist/discovery.d.ts.map +1 -1
  50. package/dist/discovery.js +19 -44
  51. package/dist/durability.d.ts +13 -0
  52. package/dist/durability.d.ts.map +1 -1
  53. package/dist/durability.js +4 -0
  54. package/dist/entry.js +1 -1
  55. package/dist/expectation.d.ts +26 -13
  56. package/dist/expectation.d.ts.map +1 -1
  57. package/dist/expectation.js +72 -19
  58. package/dist/failure.d.ts +3 -0
  59. package/dist/failure.d.ts.map +1 -1
  60. package/dist/failure.js +6 -0
  61. package/dist/figures.d.ts +1 -0
  62. package/dist/figures.d.ts.map +1 -1
  63. package/dist/figures.js +2 -2
  64. package/dist/file.d.ts.map +1 -1
  65. package/dist/file.js +2 -1
  66. package/dist/holdings.d.ts +29 -0
  67. package/dist/holdings.d.ts.map +1 -0
  68. package/dist/holdings.js +95 -0
  69. package/dist/host.d.ts +18 -2
  70. package/dist/host.d.ts.map +1 -1
  71. package/dist/host.js +46 -11
  72. package/dist/index.d.ts +17 -9
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +13 -6
  75. package/dist/install.d.ts +2 -4
  76. package/dist/install.d.ts.map +1 -1
  77. package/dist/install.js +53 -83
  78. package/dist/lifecycle.d.ts +1 -1
  79. package/dist/lifecycle.d.ts.map +1 -1
  80. package/dist/lifecycle.js +45 -35
  81. package/dist/listing.d.ts +6 -11
  82. package/dist/listing.d.ts.map +1 -1
  83. package/dist/listing.js +25 -61
  84. package/dist/live.d.ts.map +1 -1
  85. package/dist/live.js +3 -3
  86. package/dist/locks.d.ts +2 -4
  87. package/dist/locks.d.ts.map +1 -1
  88. package/dist/locks.js +10 -39
  89. package/dist/lost.d.ts.map +1 -1
  90. package/dist/lost.js +10 -22
  91. package/dist/media.d.ts +1 -1
  92. package/dist/media.d.ts.map +1 -1
  93. package/dist/media.js +10 -13
  94. package/dist/memory.d.ts +7 -3
  95. package/dist/memory.d.ts.map +1 -1
  96. package/dist/memory.js +58 -27
  97. package/dist/messages.d.ts +10 -6
  98. package/dist/messages.d.ts.map +1 -1
  99. package/dist/messages.js +26 -36
  100. package/dist/model.d.ts +0 -1
  101. package/dist/model.d.ts.map +1 -1
  102. package/dist/model.js +0 -5
  103. package/dist/models.d.ts +4 -8
  104. package/dist/models.d.ts.map +1 -1
  105. package/dist/models.js +95 -135
  106. package/dist/observation.d.ts +3 -2
  107. package/dist/observation.d.ts.map +1 -1
  108. package/dist/observation.js +22 -21
  109. package/dist/opened.d.ts +1 -1
  110. package/dist/opened.d.ts.map +1 -1
  111. package/dist/opened.js +5 -5
  112. package/dist/opening.d.ts.map +1 -1
  113. package/dist/opening.js +7 -10
  114. package/dist/outcome.d.ts +10 -1
  115. package/dist/outcome.d.ts.map +1 -1
  116. package/dist/outcome.js +23 -2
  117. package/dist/overlay.d.ts +5 -1
  118. package/dist/overlay.d.ts.map +1 -1
  119. package/dist/overlay.js +36 -21
  120. package/dist/page-metadata.d.ts +8 -0
  121. package/dist/page-metadata.d.ts.map +1 -0
  122. package/dist/page-metadata.js +19 -0
  123. package/dist/parts.d.ts +3 -58
  124. package/dist/parts.d.ts.map +1 -1
  125. package/dist/parts.js +10 -115
  126. package/dist/paths.d.ts +1 -0
  127. package/dist/paths.d.ts.map +1 -1
  128. package/dist/paths.js +22 -0
  129. package/dist/preparation.d.ts.map +1 -1
  130. package/dist/preparation.js +25 -24
  131. package/dist/presence.d.ts +52 -0
  132. package/dist/presence.d.ts.map +1 -0
  133. package/dist/presence.js +220 -0
  134. package/dist/queries.d.ts +1 -1
  135. package/dist/queries.d.ts.map +1 -1
  136. package/dist/queries.js +24 -14
  137. package/dist/query.d.ts +0 -1
  138. package/dist/query.d.ts.map +1 -1
  139. package/dist/questions.d.ts +2 -5
  140. package/dist/questions.d.ts.map +1 -1
  141. package/dist/questions.js +3 -6
  142. package/dist/queue.d.ts +40 -0
  143. package/dist/queue.d.ts.map +1 -0
  144. package/dist/queue.js +450 -0
  145. package/dist/reach.d.ts.map +1 -1
  146. package/dist/reach.js +68 -23
  147. package/dist/react.d.ts +11 -1
  148. package/dist/react.d.ts.map +1 -1
  149. package/dist/react.js +33 -1
  150. package/dist/readiness.d.ts +1 -2
  151. package/dist/readiness.d.ts.map +1 -1
  152. package/dist/reads.d.ts +4 -1
  153. package/dist/reads.d.ts.map +1 -1
  154. package/dist/reads.js +47 -5
  155. package/dist/recovery.d.ts +3 -1
  156. package/dist/recovery.d.ts.map +1 -1
  157. package/dist/recovery.js +29 -7
  158. package/dist/refresh.js +2 -2
  159. package/dist/refusal.d.ts.map +1 -1
  160. package/dist/refusal.js +5 -6
  161. package/dist/replica.d.ts +5 -10
  162. package/dist/replica.d.ts.map +1 -1
  163. package/dist/replica.js +15 -16
  164. package/dist/retried.d.ts +30 -0
  165. package/dist/retried.d.ts.map +1 -0
  166. package/dist/retried.js +72 -0
  167. package/dist/room-draft.d.ts +4 -6
  168. package/dist/room-draft.d.ts.map +1 -1
  169. package/dist/room-draft.js +48 -59
  170. package/dist/room-drafts.d.ts.map +1 -1
  171. package/dist/room-drafts.js +17 -16
  172. package/dist/rows.d.ts.map +1 -1
  173. package/dist/rows.js +3 -4
  174. package/dist/runtime.d.ts +11 -19
  175. package/dist/runtime.d.ts.map +1 -1
  176. package/dist/save.d.ts +42 -86
  177. package/dist/save.d.ts.map +1 -1
  178. package/dist/save.js +333 -163
  179. package/dist/saves.d.ts +2 -40
  180. package/dist/saves.d.ts.map +1 -1
  181. package/dist/saves.js +109 -703
  182. package/dist/seed.d.ts.map +1 -1
  183. package/dist/seed.js +2 -3
  184. package/dist/shared.d.ts +1 -6
  185. package/dist/shared.d.ts.map +1 -1
  186. package/dist/shared.js +13 -95
  187. package/dist/shown.d.ts +6 -4
  188. package/dist/shown.d.ts.map +1 -1
  189. package/dist/shown.js +43 -35
  190. package/dist/socket/lanes.d.ts +12 -4
  191. package/dist/socket/lanes.d.ts.map +1 -1
  192. package/dist/socket/lanes.js +34 -8
  193. package/dist/socket/session.d.ts +0 -1
  194. package/dist/socket/session.d.ts.map +1 -1
  195. package/dist/socket.d.ts +3 -6
  196. package/dist/socket.d.ts.map +1 -1
  197. package/dist/socket.js +5 -16
  198. package/dist/source.d.ts +0 -7
  199. package/dist/source.d.ts.map +1 -1
  200. package/dist/source.js +5 -4
  201. package/dist/store/records.d.ts +11 -8
  202. package/dist/store/records.d.ts.map +1 -1
  203. package/dist/store/records.js +43 -12
  204. package/dist/store/space.d.ts +1 -1
  205. package/dist/store/space.d.ts.map +1 -1
  206. package/dist/store/space.js +0 -2
  207. package/dist/store/watchers.js +1 -2
  208. package/dist/store.d.ts +12 -7
  209. package/dist/store.d.ts.map +1 -1
  210. package/dist/store.js +38 -13
  211. package/dist/stored.d.ts +2 -1
  212. package/dist/stored.d.ts.map +1 -1
  213. package/dist/stored.js +27 -15
  214. package/dist/surface.d.ts +7 -4
  215. package/dist/surface.d.ts.map +1 -1
  216. package/dist/surface.js +30 -25
  217. package/dist/sync.d.ts +0 -1
  218. package/dist/sync.d.ts.map +1 -1
  219. package/dist/sync.js +93 -89
  220. package/dist/tables.d.ts +19 -11
  221. package/dist/tables.d.ts.map +1 -1
  222. package/dist/tables.js +58 -21
  223. package/dist/tallies.d.ts.map +1 -1
  224. package/dist/tallies.js +6 -7
  225. package/dist/validation.d.ts.map +1 -1
  226. package/dist/validation.js +2 -2
  227. package/dist/wire.d.ts +53 -7
  228. package/dist/wire.d.ts.map +1 -1
  229. package/dist/wire.js +17 -4
  230. package/package.json +3 -2
  231. package/dist/attempt.d.ts +0 -16
  232. package/dist/attempt.d.ts.map +0 -1
  233. package/dist/attempt.js +0 -70
  234. package/dist/job.d.ts +0 -33
  235. package/dist/job.d.ts.map +0 -1
  236. package/dist/job.js +0 -54
  237. package/dist/log.d.ts +0 -6
  238. package/dist/log.d.ts.map +0 -1
  239. package/dist/log.js +0 -14
  240. package/dist/socket/rooms.d.ts +0 -43
  241. package/dist/socket/rooms.d.ts.map +0 -1
  242. package/dist/socket/rooms.js +0 -90
  243. package/dist/store/fences.d.ts +0 -16
  244. package/dist/store/fences.d.ts.map +0 -1
  245. package/dist/store/fences.js +0 -26
@@ -0,0 +1,225 @@
1
+ import { expectedList } from './expectation.js';
2
+ import { changeBatchIdentity } from './identity.js';
3
+ const IDLE = { busy: false, drawn: false, ended: null };
4
+ export function acting(rules) {
5
+ const { store, uncertain, ending, settles } = rules;
6
+ const mint = rules.mint ?? (() => changeBatchIdentity());
7
+ const identities = new Map();
8
+ const waiting = new Map();
9
+ const settling = new Map();
10
+ const blobs = new WeakMap();
11
+ let counted = 0;
12
+ let touches = 0;
13
+ const requestOf = (name, input) => {
14
+ const carried = [];
15
+ const json = JSON.stringify(input, (_key, value) => {
16
+ if (!(value instanceof Blob))
17
+ return value;
18
+ let one = blobs.get(value);
19
+ if (one === undefined) {
20
+ counted += 1;
21
+ one = counted;
22
+ blobs.set(value, one);
23
+ }
24
+ carried.push(one);
25
+ return null;
26
+ });
27
+ return `${name}\u0000${json}\u0000${carried.join(',')}`;
28
+ };
29
+ const identityOf = (request) => {
30
+ const held = identities.get(request);
31
+ if (held !== undefined)
32
+ return held;
33
+ const fresh = { operation: mint(), touched: 0, flying: 0 };
34
+ identities.set(request, fresh);
35
+ return fresh;
36
+ };
37
+ const settled = (act, ended, calls) => {
38
+ const released = new Map();
39
+ for (const { request, identity, ended: answered } of calls) {
40
+ const heard = answered === 'accepted' || answered === 'refused';
41
+ if (ended === 'accepted' && heard)
42
+ released.set(request, identity.touched);
43
+ else {
44
+ touches += 1;
45
+ identity.touched = touches;
46
+ identities.set(request, identity);
47
+ }
48
+ }
49
+ if (ended === 'refused' || ended === 'unsent')
50
+ store.drop(act);
51
+ for (const { request, ended: answered } of calls) {
52
+ const earlier = waiting.get(request);
53
+ if (answered === 'unsent' && earlier !== undefined)
54
+ continue;
55
+ if (earlier !== undefined && earlier !== act)
56
+ store.drop(earlier);
57
+ if (ended === 'unanswered')
58
+ waiting.set(request, act);
59
+ else
60
+ waiting.delete(request);
61
+ }
62
+ if (ended === 'accepted' || calls.some((one) => one.ended === 'accepted'))
63
+ rules.acted?.();
64
+ return released;
65
+ };
66
+ const release = (released) => {
67
+ for (const [request, touched] of released) {
68
+ const held = identities.get(request);
69
+ if (held !== undefined && held.touched === touched && held.flying === 0) {
70
+ identities.delete(request);
71
+ }
72
+ }
73
+ };
74
+ return {
75
+ open() {
76
+ const listeners = new Set();
77
+ const releasing = new Map();
78
+ let tail = Promise.resolve();
79
+ let pressed = 0;
80
+ let drawing = 0;
81
+ let ended = null;
82
+ let held = null;
83
+ let presses = 0;
84
+ let shown = IDLE;
85
+ const show = () => {
86
+ const busy = pressed > 0;
87
+ const drawn = drawing > 0;
88
+ if (shown.busy === busy && shown.drawn === drawn && shown.ended === ended)
89
+ return;
90
+ shown = { busy, drawn, ended };
91
+ for (const listener of listeners)
92
+ listener();
93
+ };
94
+ const awaiting = (outcome, operations, heard, again) => new Promise((resolve) => {
95
+ const forgotten = () => {
96
+ for (const operation of operations)
97
+ if (settling.get(operation) === record)
98
+ settling.delete(operation);
99
+ };
100
+ const record = {
101
+ supersede() {
102
+ if (held !== record)
103
+ return;
104
+ held = null;
105
+ forgotten();
106
+ resolve(outcome);
107
+ },
108
+ };
109
+ held = record;
110
+ for (const operation of operations)
111
+ settling.set(operation, record);
112
+ const answers = operations.map((operation) => heard(operation).then((answered) => {
113
+ if (!answered)
114
+ record.supersede();
115
+ return answered;
116
+ }));
117
+ void Promise.all(answers).then(() => {
118
+ if (held !== record)
119
+ return;
120
+ held = null;
121
+ forgotten();
122
+ resolve(again());
123
+ }, () => record.supersede());
124
+ });
125
+ const attempt = (steps, expected, press) => {
126
+ const act = store.begin();
127
+ let drew = false;
128
+ const expect = (more) => {
129
+ if (expectedList(more).length === 0)
130
+ return;
131
+ store.expect(act, more);
132
+ if (drew)
133
+ return;
134
+ drew = true;
135
+ drawing += 1;
136
+ show();
137
+ };
138
+ pressed += 1;
139
+ expect(expected);
140
+ show();
141
+ const calls = [];
142
+ const send = Object.assign(async (name, input, sending) => {
143
+ const request = requestOf(name, input);
144
+ const identity = identityOf(request);
145
+ settling.get(identity.operation)?.supersede();
146
+ const called = { request, identity, ended: null };
147
+ calls.push(called);
148
+ touches += 1;
149
+ identity.touched = touches;
150
+ identity.flying += 1;
151
+ let outcome;
152
+ try {
153
+ outcome = await sending(identity.operation);
154
+ }
155
+ catch {
156
+ outcome = uncertain;
157
+ }
158
+ finally {
159
+ identity.flying -= 1;
160
+ }
161
+ called.ended = ending(outcome);
162
+ return outcome;
163
+ }, { expect });
164
+ const end = (outcome, how) => {
165
+ for (const [request, touched] of settled(act, how, calls))
166
+ releasing.set(request, touched);
167
+ pressed -= 1;
168
+ if (drew)
169
+ drawing -= 1;
170
+ ended = outcome;
171
+ if (pressed === 0) {
172
+ release(releasing);
173
+ releasing.clear();
174
+ }
175
+ show();
176
+ };
177
+ const turn = tail.then(async () => {
178
+ ended = null;
179
+ show();
180
+ let outcome;
181
+ try {
182
+ outcome = await steps(send);
183
+ }
184
+ catch (error) {
185
+ end(uncertain, 'unanswered');
186
+ throw error;
187
+ }
188
+ const how = ending(outcome);
189
+ end(outcome, how);
190
+ return { outcome, how };
191
+ });
192
+ tail = turn.catch(() => undefined);
193
+ return turn.then(({ outcome, how }) => {
194
+ const lost = calls.flatMap(({ identity, ended: answered }) => answered === 'unanswered' ? [identity.operation] : []);
195
+ if (how !== 'unanswered' || lost.length === 0 || settles === undefined)
196
+ return outcome;
197
+ if (press !== presses)
198
+ return outcome;
199
+ return awaiting(outcome, lost, settles, () => attempt(steps, expected, press));
200
+ });
201
+ };
202
+ const run = (steps, expected = null) => {
203
+ held?.supersede();
204
+ presses += 1;
205
+ return attempt(steps, expected, presses);
206
+ };
207
+ return {
208
+ run,
209
+ shown: () => shown,
210
+ subscribe(listener) {
211
+ listeners.add(listener);
212
+ return () => {
213
+ listeners.delete(listener);
214
+ };
215
+ },
216
+ forget() {
217
+ if (pressed > 0 || ended === null)
218
+ return;
219
+ ended = null;
220
+ show();
221
+ },
222
+ };
223
+ },
224
+ };
225
+ }
package/dist/actions.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ConversationHistoryRequest } from './adapter.js';
2
2
  import { type CallResult, type HistoryAnswer, type Resolution } from './outcome.js';
3
3
  import type { Attempted } from './recovery.js';
4
+ import type { Attempt } from './retried.js';
4
5
  import type { Runtime } from './runtime.js';
5
6
  export type HistoryQuery = {
6
7
  revision?: string;
@@ -12,9 +13,14 @@ export declare function located(runtime: Runtime, room: string, path: string, de
12
13
  path: string;
13
14
  } | null>;
14
15
  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 type Invoked = {
17
+ readonly dispatching?: () => Promise<void>;
18
+ readonly attempt?: Attempt;
19
+ };
20
+ export declare function invokeAction(runtime: Runtime, name: string, input: unknown, { dispatching, attempt }?: Invoked): Promise<CallResult>;
16
21
  export declare function readConversationHistory(runtime: Runtime, request: ConversationHistoryRequest): Promise<CallResult>;
17
- export declare function called(runtime: Runtime, name: string, input: unknown): Promise<CallResult>;
22
+ export declare function called(runtime: Runtime, name: string, input: unknown, attempt?: Attempt): Promise<CallResult>;
23
+ export declare function answeredCall(runtime: Runtime, operation: string): Promise<boolean>;
18
24
  export declare function resendCalls(runtime: Runtime, signal: AbortSignal): Promise<Attempted>;
19
25
  export declare function resendLater(runtime: Runtime): void;
20
26
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAI/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;AAsCD,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"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM/D,OAAO,EAWL,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;AAC5C,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,CA+BxB;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,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,wBAAsB,YAAY,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,EAAE,WAAW,EAAE,OAAO,EAAE,GAAE,OAAY,GACrC,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,UAAU,CAAC,CAerB;AA4GD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,UAAU,CAAC,CAKrB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAaxF;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAe3F;AAiBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,QAG3C"}
package/dist/actions.js CHANGED
@@ -1,15 +1,16 @@
1
1
  import { roomTarget, target } from '@agentshouse/mdmodel';
2
+ import { CATCHING_UP, holdsSubmission, resendConversations } from './conversation.js';
2
3
  import { listingNow } from './listing.js';
3
4
  import { locked, lockedRooms } from './locks.js';
4
5
  import { scoped } from './models.js';
5
- import { ABSENT_TARGET, calledResult, failure, historyAnswer, LOCKED_UNREADABLE, lockedRoom, undeclared, UNCERTAIN, UNREADABLE, } from './outcome.js';
6
+ import { ABSENT_TARGET, failure, historyAnswer, LOCKED_UNREADABLE, lockedRoom, handedOutcome, UNANSWERED, undeclared, UNCERTAIN, UNREADABLE, } from './outcome.js';
6
7
  import { refuse } from './refusal.js';
7
8
  function operationOf(input) {
8
9
  const operation = input?.operation_id;
9
10
  return typeof operation === 'string' ? operation : null;
10
11
  }
11
12
  export async function readHistory(runtime, locator, path, query = {}) {
12
- const { store, socket, journal } = runtime;
13
+ const { store, socket, presence } = runtime;
13
14
  const { session } = socket;
14
15
  if (socket.closed() || session.now().refusal !== null)
15
16
  return UNCERTAIN;
@@ -25,13 +26,7 @@ export async function readHistory(runtime, locator, path, query = {}) {
25
26
  const { closed, authorization, refusal } = session.now();
26
27
  if (closed || authorization === undefined || refusal !== null)
27
28
  return UNCERTAIN;
28
- const since = store.fences.count();
29
- const transfer = ['transfer', 'history', locator, path];
30
- if (query.revision !== undefined)
31
- transfer.push(query.revision);
32
- if (query.pageToken !== undefined)
33
- transfer.push(query.pageToken);
34
- journal.record(transfer.join(' '));
29
+ const since = presence.losses();
35
30
  try {
36
31
  const result = await socket.history(authorization, {
37
32
  locator,
@@ -39,20 +34,18 @@ export async function readHistory(runtime, locator, path, query = {}) {
39
34
  ...(query.revision === undefined ? {} : { revision: query.revision }),
40
35
  ...(query.pageToken === undefined ? {} : { pageToken: query.pageToken }),
41
36
  });
42
- journal.record(`outcome history ${result.kind}`);
43
- if (store.fences.since(locator, since))
37
+ if (presence.lostSince(locator, since))
44
38
  return failure({ kind: 'room-not-readable', locator });
45
39
  if (result.kind === 'scoped-refusal') {
46
40
  const room = await store.record(result.locator);
47
41
  if (room !== undefined)
48
- await scoped(runtime, result, room, await store.open());
42
+ await scoped(runtime, result, room.locator, room.declaration);
49
43
  }
50
44
  if (result.kind === 'revoked-authorization')
51
45
  await refuse(runtime, 'revoked-authorization');
52
46
  return historyAnswer(result);
53
47
  }
54
48
  catch {
55
- journal.record('outcome history transport-uncertainty');
56
49
  return UNCERTAIN;
57
50
  }
58
51
  }
@@ -109,120 +102,181 @@ async function calledRooms(runtime, name, input) {
109
102
  const named = input[member];
110
103
  return (Array.isArray(named) ? named : [named]).filter((room) => typeof room === 'string');
111
104
  }
112
- export async function invokeAction(runtime, name, input, dispatching) {
113
- const { store, socket, journal } = runtime;
105
+ export async function invokeAction(runtime, name, input, { dispatching, attempt } = {}) {
106
+ const { store, socket, retries } = runtime;
114
107
  const { session } = socket;
115
108
  await socket.ready;
116
- if (socket.closed() || session.now().refusal !== null)
117
- return UNCERTAIN;
109
+ if (socket.closed() || session.now().refusal !== null) {
110
+ return handedOutcome(retries, attempt, UNANSWERED);
111
+ }
118
112
  if ((await declaredAction(runtime, name)) === undefined)
119
113
  return undeclared(name);
120
114
  try {
121
115
  await socket.authorize();
122
116
  }
123
117
  catch {
124
- return UNCERTAIN;
118
+ return handedOutcome(retries, attempt, UNANSWERED);
125
119
  }
126
120
  const { closed, authorization, refusal } = session.now();
127
- if (closed || authorization === undefined || refusal !== null)
128
- return UNCERTAIN;
121
+ if (closed || authorization === undefined || refusal !== null) {
122
+ return handedOutcome(retries, attempt, UNANSWERED);
123
+ }
129
124
  await dispatching?.();
130
- journal.record(`transfer action ${name}`);
131
125
  try {
132
126
  const result = await socket.action(authorization, { name, input });
133
127
  if (result.kind === 'scoped-refusal') {
134
128
  const room = await store.record(result.locator);
135
129
  if (room !== undefined)
136
- await scoped(runtime, result, room, await store.open());
130
+ await scoped(runtime, result, room.locator, room.declaration);
137
131
  }
138
132
  if (result.kind === 'revoked-authorization')
139
133
  await refuse(runtime, 'revoked-authorization');
140
- journal.record(`outcome action ${result.kind}`);
141
- if (result.kind === 'rejected')
142
- journal.record(`refusal rejected ${result.code}`);
143
- return calledResult(result);
134
+ return handedOutcome(retries, attempt, result);
144
135
  }
145
- catch {
146
- journal.record('outcome action transport-uncertainty');
147
- return UNCERTAIN;
136
+ catch (error) {
137
+ return handedOutcome(retries, attempt, { kind: 'transport-uncertainty', failure: error });
148
138
  }
149
139
  }
150
140
  export async function readConversationHistory(runtime, request) {
151
- const { socket, journal } = runtime;
141
+ const { socket, retries } = runtime;
142
+ const caught = { step: 'conversations', instance: CATCHING_UP };
152
143
  await socket.ready;
153
144
  const stream = socket.conversations();
154
145
  if (socket.closed() || socket.session.now().refusal !== null || stream?.history === undefined) {
155
- return UNCERTAIN;
146
+ return handedOutcome(retries, caught, UNANSWERED);
156
147
  }
157
- journal.record('transfer conversation history');
158
148
  try {
159
149
  const result = await stream.history(request);
160
150
  if (result.kind === 'revoked-authorization')
161
151
  await refuse(runtime, 'revoked-authorization');
162
- journal.record(`outcome conversation history ${result.kind}`);
163
- return calledResult(result);
152
+ return handedOutcome(retries, caught, result);
164
153
  }
165
- catch {
166
- journal.record('outcome conversation history transport-uncertainty');
167
- return UNCERTAIN;
154
+ catch (error) {
155
+ return handedOutcome(retries, caught, { kind: 'transport-uncertainty', failure: error });
168
156
  }
169
157
  }
170
158
  function unsettled(result) {
171
- return result.kind !== 'action' && result.retryable;
159
+ if (result.kind === 'action')
160
+ return false;
161
+ return result.retryable && (result.kind !== 'rejected' || result.reset === undefined);
172
162
  }
173
- async function recoveredAction(runtime, name, input) {
174
- const { store, socket, recovery } = runtime;
163
+ function numberedCall(runtime, name, input, operation, dispatching) {
164
+ return invokeAction(runtime, name, input, {
165
+ dispatching,
166
+ attempt: { step: 'sending', instance: `action ${operation}` },
167
+ });
168
+ }
169
+ function keptSender(runtime, name, input, operation, resent = false) {
170
+ const { store, socket } = runtime;
175
171
  const { lanes } = socket;
172
+ const dispatching = async () => (await store.open()).keepCall({ operation, name, input });
173
+ let waiting = [];
174
+ let last = UNCERTAIN;
175
+ let lost = resent;
176
+ const tell = (result) => {
177
+ last = result;
178
+ const told = waiting;
179
+ waiting = [];
180
+ for (const answer of told)
181
+ answer(result);
182
+ };
183
+ const sender = {
184
+ next: () => new Promise((answer) => waiting.push(answer)),
185
+ async send() {
186
+ let result;
187
+ try {
188
+ result = await numberedCall(runtime, name, input, operation, dispatching);
189
+ }
190
+ catch (error) {
191
+ tell(last);
192
+ throw error;
193
+ }
194
+ if (unsettled(result))
195
+ lost = true;
196
+ else {
197
+ await (await store.open()).dropCall(operation);
198
+ lanes.settle(operation, lost);
199
+ }
200
+ tell(result);
201
+ return result;
202
+ },
203
+ release() {
204
+ lanes.sent(operation, sender);
205
+ tell(last);
206
+ },
207
+ };
208
+ lanes.sending(operation, sender);
209
+ return sender;
210
+ }
211
+ async function recoveredAction(runtime, name, input, attempt) {
212
+ const { socket, recovery } = runtime;
176
213
  const operation = operationOf(input);
177
214
  if (operation === null)
178
- return invokeAction(runtime, name, input);
179
- const kept = async () => (await store.open()).keepCall({ operation, name, input });
180
- lanes.call(operation);
215
+ return invokeAction(runtime, name, input, { attempt });
216
+ const held = socket.lanes.sender(operation);
217
+ if (held !== undefined)
218
+ return held.next();
219
+ const sender = keptSender(runtime, name, input, operation);
220
+ let first;
181
221
  try {
182
- let result = await invokeAction(runtime, name, input, kept);
183
- if (unsettled(result)) {
184
- await recovery.attempt(`action ${operation}`, async () => {
185
- if (socket.closed() || socket.session.now().refusal !== null)
186
- return 'done';
187
- if (!socket.isOpen())
188
- return 'again';
189
- result = await invokeAction(runtime, name, input, kept);
190
- return unsettled(result) ? 'again' : 'done';
191
- }, { again: true });
192
- }
193
- if (!unsettled(result))
194
- await (await store.open()).dropCall(operation);
195
- return result;
222
+ first = await sender.send();
223
+ }
224
+ catch (error) {
225
+ sender.release();
226
+ throw error;
196
227
  }
197
- finally {
198
- lanes.called(operation);
228
+ if (!unsettled(first)) {
229
+ sender.release();
230
+ return first;
199
231
  }
232
+ void recovery
233
+ .attempt(`action ${operation}`, async () => {
234
+ if (socket.closed() || socket.session.now().refusal !== null)
235
+ return 'done';
236
+ if (!socket.isOpen())
237
+ return 'again';
238
+ return unsettled(await sender.send()) ? 'again' : 'done';
239
+ }, { again: true })
240
+ .finally(() => sender.release());
241
+ return first;
200
242
  }
201
- export async function called(runtime, name, input) {
243
+ export async function called(runtime, name, input, attempt) {
202
244
  await runtime.socket.ready;
203
245
  const lockedNow = await lockedRooms(runtime);
204
246
  const room = (await calledRooms(runtime, name, input)).find((one) => lockedNow.includes(one));
205
- return room === undefined ? recoveredAction(runtime, name, input) : lockedRoom(room);
247
+ return room === undefined ? recoveredAction(runtime, name, input, attempt) : lockedRoom(room);
206
248
  }
207
- export async function resendCalls(runtime, signal) {
249
+ export async function answeredCall(runtime, operation) {
208
250
  const { store, socket } = runtime;
209
251
  const { lanes } = socket;
252
+ const held = () => lanes.sender(operation) !== undefined || lanes.unclaimed(operation);
253
+ if (!held()) {
254
+ const calls = await (await store.open()).calls();
255
+ const kept = calls.some((one) => one.operation === operation) ||
256
+ (await holdsSubmission(runtime.conversations, operation));
257
+ if (!held() && !kept)
258
+ return false;
259
+ }
260
+ await lanes.settled(operation);
261
+ return true;
262
+ }
263
+ export async function resendCalls(runtime, signal) {
264
+ const { store, socket } = runtime;
210
265
  if (!socket.isOpen() || socket.closed() || socket.stopping())
211
266
  return 'done';
212
267
  const local = await store.open();
213
268
  for (const held of await local.calls()) {
214
- if (lanes.calling(held.operation))
269
+ if (socket.lanes.sender(held.operation) !== undefined)
215
270
  continue;
216
271
  if (socket.closed() || signal.aborted)
217
272
  return 'done';
218
- lanes.call(held.operation);
273
+ const sender = keptSender(runtime, held.name, held.input, held.operation, true);
219
274
  try {
220
- if (unsettled(await invokeAction(runtime, held.name, held.input)))
275
+ if (unsettled(await sender.send()))
221
276
  return 'again';
222
- await local.dropCall(held.operation);
223
277
  }
224
278
  finally {
225
- lanes.called(held.operation);
279
+ sender.release();
226
280
  }
227
281
  }
228
282
  return 'done';
@@ -232,7 +286,7 @@ async function resendPass({ socket, conversations }, signal) {
232
286
  return 'done';
233
287
  const reading = { complete: true, reachable: true };
234
288
  try {
235
- await conversations.resend(reading);
289
+ await resendConversations(conversations, reading);
236
290
  }
237
291
  catch {
238
292
  reading.reachable = false;