@agentshouse/mdruntime 0.1.0-cf04ede9fb796 → 0.1.0-cf0c43fc48aad

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 (220) hide show
  1. package/README.md +12 -12
  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 +118 -67
  11. package/dist/adapter.d.ts +27 -48
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/bootstrap.d.ts +1 -1
  14. package/dist/bootstrap.d.ts.map +1 -1
  15. package/dist/bootstrap.js +6 -19
  16. package/dist/change-set.d.ts +4 -0
  17. package/dist/change-set.d.ts.map +1 -1
  18. package/dist/change-set.js +6 -0
  19. package/dist/change.d.ts.map +1 -1
  20. package/dist/change.js +4 -2
  21. package/dist/client.d.ts +9 -18
  22. package/dist/client.d.ts.map +1 -1
  23. package/dist/client.js +32 -15
  24. package/dist/collection.d.ts +22 -4
  25. package/dist/collection.d.ts.map +1 -1
  26. package/dist/collection.js +12 -2
  27. package/dist/compile.d.ts +2 -0
  28. package/dist/compile.d.ts.map +1 -1
  29. package/dist/compile.js +31 -24
  30. package/dist/connection.d.ts.map +1 -1
  31. package/dist/connection.js +26 -21
  32. package/dist/conversation-live.d.ts +10 -6
  33. package/dist/conversation-live.d.ts.map +1 -1
  34. package/dist/conversation-live.js +8 -6
  35. package/dist/conversation.d.ts +28 -10
  36. package/dist/conversation.d.ts.map +1 -1
  37. package/dist/conversation.js +194 -141
  38. package/dist/declaration.d.ts +10 -0
  39. package/dist/declaration.d.ts.map +1 -0
  40. package/dist/declaration.js +24 -0
  41. package/dist/discovery.d.ts.map +1 -1
  42. package/dist/discovery.js +19 -44
  43. package/dist/durability.d.ts +3 -0
  44. package/dist/durability.d.ts.map +1 -1
  45. package/dist/entry.js +1 -1
  46. package/dist/expectation.d.ts +26 -13
  47. package/dist/expectation.d.ts.map +1 -1
  48. package/dist/expectation.js +72 -19
  49. package/dist/failure.d.ts +3 -0
  50. package/dist/failure.d.ts.map +1 -1
  51. package/dist/failure.js +6 -0
  52. package/dist/host.d.ts +17 -2
  53. package/dist/host.d.ts.map +1 -1
  54. package/dist/host.js +45 -11
  55. package/dist/index.d.ts +12 -8
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +10 -6
  58. package/dist/install.d.ts +2 -4
  59. package/dist/install.d.ts.map +1 -1
  60. package/dist/install.js +52 -78
  61. package/dist/lifecycle.d.ts +1 -1
  62. package/dist/lifecycle.d.ts.map +1 -1
  63. package/dist/lifecycle.js +40 -31
  64. package/dist/listing.d.ts +6 -11
  65. package/dist/listing.d.ts.map +1 -1
  66. package/dist/listing.js +25 -62
  67. package/dist/live.d.ts.map +1 -1
  68. package/dist/live.js +3 -3
  69. package/dist/locks.d.ts +2 -4
  70. package/dist/locks.d.ts.map +1 -1
  71. package/dist/locks.js +10 -39
  72. package/dist/lost.d.ts.map +1 -1
  73. package/dist/lost.js +10 -22
  74. package/dist/media.d.ts +1 -1
  75. package/dist/media.d.ts.map +1 -1
  76. package/dist/media.js +4 -4
  77. package/dist/memory.d.ts +4 -2
  78. package/dist/memory.d.ts.map +1 -1
  79. package/dist/memory.js +44 -23
  80. package/dist/messages.d.ts +9 -5
  81. package/dist/messages.d.ts.map +1 -1
  82. package/dist/messages.js +25 -35
  83. package/dist/model.d.ts +0 -1
  84. package/dist/model.d.ts.map +1 -1
  85. package/dist/model.js +0 -5
  86. package/dist/models.d.ts +4 -8
  87. package/dist/models.d.ts.map +1 -1
  88. package/dist/models.js +95 -137
  89. package/dist/observation.d.ts.map +1 -1
  90. package/dist/observation.js +12 -17
  91. package/dist/opened.d.ts +1 -1
  92. package/dist/opened.d.ts.map +1 -1
  93. package/dist/opened.js +5 -5
  94. package/dist/opening.d.ts.map +1 -1
  95. package/dist/opening.js +5 -9
  96. package/dist/outcome.d.ts +3 -0
  97. package/dist/outcome.d.ts.map +1 -1
  98. package/dist/outcome.js +15 -0
  99. package/dist/overlay.d.ts +5 -1
  100. package/dist/overlay.d.ts.map +1 -1
  101. package/dist/overlay.js +36 -21
  102. package/dist/page-metadata.d.ts +8 -0
  103. package/dist/page-metadata.d.ts.map +1 -0
  104. package/dist/page-metadata.js +19 -0
  105. package/dist/parts.d.ts +3 -59
  106. package/dist/parts.d.ts.map +1 -1
  107. package/dist/parts.js +10 -123
  108. package/dist/preparation.d.ts.map +1 -1
  109. package/dist/preparation.js +25 -24
  110. package/dist/presence.d.ts +52 -0
  111. package/dist/presence.d.ts.map +1 -0
  112. package/dist/presence.js +220 -0
  113. package/dist/queries.d.ts +1 -1
  114. package/dist/queries.d.ts.map +1 -1
  115. package/dist/queries.js +24 -14
  116. package/dist/query.d.ts +0 -1
  117. package/dist/query.d.ts.map +1 -1
  118. package/dist/questions.d.ts +0 -5
  119. package/dist/questions.d.ts.map +1 -1
  120. package/dist/questions.js +0 -7
  121. package/dist/queue.d.ts +40 -0
  122. package/dist/queue.d.ts.map +1 -0
  123. package/dist/queue.js +450 -0
  124. package/dist/reach.d.ts.map +1 -1
  125. package/dist/reach.js +67 -22
  126. package/dist/react.d.ts +5 -0
  127. package/dist/react.d.ts.map +1 -1
  128. package/dist/react.js +33 -1
  129. package/dist/reads.d.ts +3 -1
  130. package/dist/reads.d.ts.map +1 -1
  131. package/dist/reads.js +9 -2
  132. package/dist/recovery.d.ts +3 -1
  133. package/dist/recovery.d.ts.map +1 -1
  134. package/dist/recovery.js +29 -7
  135. package/dist/refresh.js +2 -2
  136. package/dist/refusal.d.ts.map +1 -1
  137. package/dist/refusal.js +5 -6
  138. package/dist/replica.d.ts +5 -11
  139. package/dist/replica.d.ts.map +1 -1
  140. package/dist/replica.js +13 -15
  141. package/dist/retried.d.ts +30 -0
  142. package/dist/retried.d.ts.map +1 -0
  143. package/dist/retried.js +72 -0
  144. package/dist/room-draft.d.ts +4 -6
  145. package/dist/room-draft.d.ts.map +1 -1
  146. package/dist/room-draft.js +46 -57
  147. package/dist/room-drafts.d.ts.map +1 -1
  148. package/dist/room-drafts.js +17 -16
  149. package/dist/rows.d.ts.map +1 -1
  150. package/dist/rows.js +3 -4
  151. package/dist/runtime.d.ts +9 -18
  152. package/dist/runtime.d.ts.map +1 -1
  153. package/dist/save.d.ts +42 -90
  154. package/dist/save.d.ts.map +1 -1
  155. package/dist/save.js +334 -167
  156. package/dist/saves.d.ts +2 -40
  157. package/dist/saves.d.ts.map +1 -1
  158. package/dist/saves.js +107 -705
  159. package/dist/seed.d.ts.map +1 -1
  160. package/dist/seed.js +2 -3
  161. package/dist/shared.d.ts +0 -5
  162. package/dist/shared.d.ts.map +1 -1
  163. package/dist/shared.js +4 -90
  164. package/dist/shown.d.ts +4 -3
  165. package/dist/shown.d.ts.map +1 -1
  166. package/dist/shown.js +26 -31
  167. package/dist/socket/lanes.d.ts +12 -4
  168. package/dist/socket/lanes.d.ts.map +1 -1
  169. package/dist/socket/lanes.js +34 -8
  170. package/dist/socket/session.d.ts +0 -1
  171. package/dist/socket/session.d.ts.map +1 -1
  172. package/dist/socket.d.ts +3 -6
  173. package/dist/socket.d.ts.map +1 -1
  174. package/dist/socket.js +5 -16
  175. package/dist/source.d.ts +0 -7
  176. package/dist/source.d.ts.map +1 -1
  177. package/dist/source.js +5 -4
  178. package/dist/store/records.d.ts +8 -6
  179. package/dist/store/records.d.ts.map +1 -1
  180. package/dist/store/records.js +13 -6
  181. package/dist/store/space.d.ts +1 -1
  182. package/dist/store/space.d.ts.map +1 -1
  183. package/dist/store/space.js +0 -2
  184. package/dist/store/watchers.js +1 -2
  185. package/dist/store.d.ts +11 -6
  186. package/dist/store.d.ts.map +1 -1
  187. package/dist/store.js +38 -13
  188. package/dist/stored.d.ts +2 -1
  189. package/dist/stored.d.ts.map +1 -1
  190. package/dist/stored.js +11 -11
  191. package/dist/surface.d.ts +1 -1
  192. package/dist/surface.d.ts.map +1 -1
  193. package/dist/surface.js +13 -16
  194. package/dist/sync.d.ts.map +1 -1
  195. package/dist/sync.js +88 -85
  196. package/dist/tables.d.ts +6 -8
  197. package/dist/tables.d.ts.map +1 -1
  198. package/dist/tables.js +41 -20
  199. package/dist/tallies.js +5 -5
  200. package/dist/validation.d.ts.map +1 -1
  201. package/dist/validation.js +2 -2
  202. package/dist/wire.d.ts +51 -7
  203. package/dist/wire.d.ts.map +1 -1
  204. package/dist/wire.js +15 -4
  205. package/package.json +3 -2
  206. package/dist/attempt.d.ts +0 -16
  207. package/dist/attempt.d.ts.map +0 -1
  208. package/dist/attempt.js +0 -70
  209. package/dist/job.d.ts +0 -33
  210. package/dist/job.d.ts.map +0 -1
  211. package/dist/job.js +0 -54
  212. package/dist/log.d.ts +0 -6
  213. package/dist/log.d.ts.map +0 -1
  214. package/dist/log.js +0 -14
  215. package/dist/socket/rooms.d.ts +0 -44
  216. package/dist/socket/rooms.d.ts.map +0 -1
  217. package/dist/socket/rooms.js +0 -90
  218. package/dist/store/fences.d.ts +0 -16
  219. package/dist/store/fences.d.ts.map +0 -1
  220. 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;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"}
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,16 +1,16 @@
1
1
  import { roomTarget, target } from '@agentshouse/mdmodel';
2
- import { resendConversations } from './conversation.js';
2
+ import { CATCHING_UP, holdsSubmission, resendConversations } from './conversation.js';
3
3
  import { listingNow } from './listing.js';
4
4
  import { locked, lockedRooms } from './locks.js';
5
5
  import { scoped } from './models.js';
6
- 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';
7
7
  import { refuse } from './refusal.js';
8
8
  function operationOf(input) {
9
9
  const operation = input?.operation_id;
10
10
  return typeof operation === 'string' ? operation : null;
11
11
  }
12
12
  export async function readHistory(runtime, locator, path, query = {}) {
13
- const { store, socket, journal } = runtime;
13
+ const { store, socket, presence } = runtime;
14
14
  const { session } = socket;
15
15
  if (socket.closed() || session.now().refusal !== null)
16
16
  return UNCERTAIN;
@@ -26,13 +26,7 @@ export async function readHistory(runtime, locator, path, query = {}) {
26
26
  const { closed, authorization, refusal } = session.now();
27
27
  if (closed || authorization === undefined || refusal !== null)
28
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(' '));
29
+ const since = presence.losses();
36
30
  try {
37
31
  const result = await socket.history(authorization, {
38
32
  locator,
@@ -40,20 +34,18 @@ export async function readHistory(runtime, locator, path, query = {}) {
40
34
  ...(query.revision === undefined ? {} : { revision: query.revision }),
41
35
  ...(query.pageToken === undefined ? {} : { pageToken: query.pageToken }),
42
36
  });
43
- journal.record(`outcome history ${result.kind}`);
44
- if (store.fences.since(locator, since))
37
+ if (presence.lostSince(locator, since))
45
38
  return failure({ kind: 'room-not-readable', locator });
46
39
  if (result.kind === 'scoped-refusal') {
47
40
  const room = await store.record(result.locator);
48
41
  if (room !== undefined)
49
- await scoped(runtime, result, room, await store.open());
42
+ await scoped(runtime, result, room.locator, room.declaration);
50
43
  }
51
44
  if (result.kind === 'revoked-authorization')
52
45
  await refuse(runtime, 'revoked-authorization');
53
46
  return historyAnswer(result);
54
47
  }
55
48
  catch {
56
- journal.record('outcome history transport-uncertainty');
57
49
  return UNCERTAIN;
58
50
  }
59
51
  }
@@ -110,62 +102,57 @@ async function calledRooms(runtime, name, input) {
110
102
  const named = input[member];
111
103
  return (Array.isArray(named) ? named : [named]).filter((room) => typeof room === 'string');
112
104
  }
113
- export async function invokeAction(runtime, name, input, dispatching) {
114
- const { store, socket, journal } = runtime;
105
+ export async function invokeAction(runtime, name, input, { dispatching, attempt } = {}) {
106
+ const { store, socket, retries } = runtime;
115
107
  const { session } = socket;
116
108
  await socket.ready;
117
- if (socket.closed() || session.now().refusal !== null)
118
- return UNCERTAIN;
109
+ if (socket.closed() || session.now().refusal !== null) {
110
+ return handedOutcome(retries, attempt, UNANSWERED);
111
+ }
119
112
  if ((await declaredAction(runtime, name)) === undefined)
120
113
  return undeclared(name);
121
114
  try {
122
115
  await socket.authorize();
123
116
  }
124
117
  catch {
125
- return UNCERTAIN;
118
+ return handedOutcome(retries, attempt, UNANSWERED);
126
119
  }
127
120
  const { closed, authorization, refusal } = session.now();
128
- if (closed || authorization === undefined || refusal !== null)
129
- return UNCERTAIN;
121
+ if (closed || authorization === undefined || refusal !== null) {
122
+ return handedOutcome(retries, attempt, UNANSWERED);
123
+ }
130
124
  await dispatching?.();
131
- journal.record(`transfer action ${name}`);
132
125
  try {
133
126
  const result = await socket.action(authorization, { name, input });
134
127
  if (result.kind === 'scoped-refusal') {
135
128
  const room = await store.record(result.locator);
136
129
  if (room !== undefined)
137
- await scoped(runtime, result, room, await store.open());
130
+ await scoped(runtime, result, room.locator, room.declaration);
138
131
  }
139
132
  if (result.kind === 'revoked-authorization')
140
133
  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);
134
+ return handedOutcome(retries, attempt, result);
145
135
  }
146
- catch {
147
- journal.record('outcome action transport-uncertainty');
148
- return UNCERTAIN;
136
+ catch (error) {
137
+ return handedOutcome(retries, attempt, { kind: 'transport-uncertainty', failure: error });
149
138
  }
150
139
  }
151
140
  export async function readConversationHistory(runtime, request) {
152
- const { socket, journal } = runtime;
141
+ const { socket, retries } = runtime;
142
+ const caught = { step: 'conversations', instance: CATCHING_UP };
153
143
  await socket.ready;
154
144
  const stream = socket.conversations();
155
145
  if (socket.closed() || socket.session.now().refusal !== null || stream?.history === undefined) {
156
- return UNCERTAIN;
146
+ return handedOutcome(retries, caught, UNANSWERED);
157
147
  }
158
- journal.record('transfer conversation history');
159
148
  try {
160
149
  const result = await stream.history(request);
161
150
  if (result.kind === 'revoked-authorization')
162
151
  await refuse(runtime, 'revoked-authorization');
163
- journal.record(`outcome conversation history ${result.kind}`);
164
- return calledResult(result);
152
+ return handedOutcome(retries, caught, result);
165
153
  }
166
- catch {
167
- journal.record('outcome conversation history transport-uncertainty');
168
- return UNCERTAIN;
154
+ catch (error) {
155
+ return handedOutcome(retries, caught, { kind: 'transport-uncertainty', failure: error });
169
156
  }
170
157
  }
171
158
  function unsettled(result) {
@@ -173,59 +160,123 @@ function unsettled(result) {
173
160
  return false;
174
161
  return result.retryable && (result.kind !== 'rejected' || result.reset === undefined);
175
162
  }
176
- async function recoveredAction(runtime, name, input) {
177
- 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;
178
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;
179
213
  const operation = operationOf(input);
180
214
  if (operation === null)
181
- return invokeAction(runtime, name, input);
182
- const kept = async () => (await store.open()).keepCall({ operation, name, input });
183
- 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;
184
221
  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;
222
+ first = await sender.send();
223
+ }
224
+ catch (error) {
225
+ sender.release();
226
+ throw error;
199
227
  }
200
- finally {
201
- lanes.called(operation);
228
+ if (!unsettled(first)) {
229
+ sender.release();
230
+ return first;
202
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;
203
242
  }
204
- export async function called(runtime, name, input) {
243
+ export async function called(runtime, name, input, attempt) {
205
244
  await runtime.socket.ready;
206
245
  const lockedNow = await lockedRooms(runtime);
207
246
  const room = (await calledRooms(runtime, name, input)).find((one) => lockedNow.includes(one));
208
- return room === undefined ? recoveredAction(runtime, name, input) : lockedRoom(room);
247
+ return room === undefined ? recoveredAction(runtime, name, input, attempt) : lockedRoom(room);
209
248
  }
210
- export async function resendCalls(runtime, signal) {
249
+ export async function answeredCall(runtime, operation) {
211
250
  const { store, socket } = runtime;
212
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;
213
265
  if (!socket.isOpen() || socket.closed() || socket.stopping())
214
266
  return 'done';
215
267
  const local = await store.open();
216
268
  for (const held of await local.calls()) {
217
- if (lanes.calling(held.operation))
269
+ if (socket.lanes.sender(held.operation) !== undefined)
218
270
  continue;
219
271
  if (socket.closed() || signal.aborted)
220
272
  return 'done';
221
- lanes.call(held.operation);
273
+ const sender = keptSender(runtime, held.name, held.input, held.operation, true);
222
274
  try {
223
- if (unsettled(await invokeAction(runtime, held.name, held.input)))
275
+ if (unsettled(await sender.send()))
224
276
  return 'again';
225
- await local.dropCall(held.operation);
226
277
  }
227
278
  finally {
228
- lanes.called(held.operation);
279
+ sender.release();
229
280
  }
230
281
  }
231
282
  return 'done';