@agentshouse/mdruntime 0.1.0-cbbae1fff01c6 → 0.1.0-cc00e9289ddf4
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.
- package/README.md +17 -15
- package/dist/acceptance.d.ts.map +1 -1
- package/dist/acceptance.js +14 -23
- package/dist/act-lanes.d.ts +30 -0
- package/dist/act-lanes.d.ts.map +1 -0
- package/dist/act-lanes.js +225 -0
- package/dist/actions.d.ts +8 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +114 -63
- package/dist/adapter.d.ts +30 -12
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +0 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +0 -5
- package/dist/chat-types.d.ts +0 -2
- package/dist/chat-types.d.ts.map +1 -1
- package/dist/chat-types.js +0 -2
- package/dist/client.d.ts +8 -18
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +27 -15
- package/dist/compile.d.ts +2 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +17 -4
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +15 -13
- package/dist/conversation-live.d.ts +23 -8
- package/dist/conversation-live.d.ts.map +1 -1
- package/dist/conversation-live.js +21 -9
- package/dist/conversation-row.d.ts +2 -0
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +2 -0
- package/dist/conversation.d.ts +27 -5
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +279 -168
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +8 -6
- package/dist/durability.d.ts +4 -0
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +4 -0
- package/dist/entry.js +1 -1
- package/dist/expectation.d.ts +25 -14
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +51 -20
- package/dist/failure.d.ts +2 -0
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +3 -0
- package/dist/figures.d.ts.map +1 -1
- package/dist/figures.js +4 -2
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +2 -1
- package/dist/host.d.ts +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +39 -11
- package/dist/index.d.ts +11 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/install.d.ts +10 -4
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +45 -46
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +22 -16
- package/dist/listing.d.ts +7 -3
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +26 -13
- package/dist/live.d.ts +5 -3
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +71 -30
- package/dist/locks.d.ts.map +1 -1
- package/dist/locks.js +2 -3
- package/dist/lost.d.ts.map +1 -1
- package/dist/lost.js +2 -3
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +7 -10
- package/dist/memory.d.ts +3 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +50 -22
- package/dist/messages.d.ts +12 -3
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +24 -10
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +5 -8
- package/dist/observation.d.ts +27 -12
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +173 -69
- package/dist/opening.d.ts.map +1 -1
- package/dist/opening.js +3 -9
- package/dist/outcome.d.ts +7 -0
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +23 -2
- package/dist/overlay.d.ts +3 -0
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +8 -4
- package/dist/page-metadata.d.ts +8 -0
- package/dist/page-metadata.d.ts.map +1 -0
- package/dist/page-metadata.js +19 -0
- package/dist/parts.d.ts +2 -9
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +6 -14
- package/dist/preparation.d.ts +27 -6
- package/dist/preparation.d.ts.map +1 -1
- package/dist/preparation.js +137 -56
- package/dist/presence.d.ts +7 -1
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +22 -9
- package/dist/queries.d.ts +2 -2
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +62 -24
- package/dist/questions.d.ts +0 -5
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +0 -7
- package/dist/queue.d.ts +2 -2
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +25 -30
- package/dist/reach.d.ts +2 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +75 -21
- package/dist/react.d.ts +7 -5
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +28 -5
- package/dist/readiness.d.ts +9 -3
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +3 -5
- package/dist/reads.d.ts +3 -1
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +5 -1
- package/dist/recovery.d.ts +3 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +29 -7
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +1 -3
- package/dist/retried.d.ts +30 -0
- package/dist/retried.d.ts.map +1 -0
- package/dist/retried.js +72 -0
- package/dist/room-draft.d.ts +2 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +26 -21
- package/dist/rows.d.ts +2 -0
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +3 -0
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/save.d.ts +1 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +105 -55
- package/dist/saves.d.ts.map +1 -1
- package/dist/saves.js +3 -6
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +2 -2
- package/dist/shown.d.ts +3 -2
- package/dist/shown.d.ts.map +1 -1
- package/dist/shown.js +58 -39
- package/dist/socket/lanes.d.ts +12 -4
- package/dist/socket/lanes.d.ts.map +1 -1
- package/dist/socket/lanes.js +34 -8
- package/dist/socket.d.ts +3 -3
- package/dist/socket.d.ts.map +1 -1
- package/dist/socket.js +3 -9
- package/dist/source.d.ts +0 -7
- package/dist/source.d.ts.map +1 -1
- package/dist/store/installs.d.ts +2 -2
- package/dist/store/installs.d.ts.map +1 -1
- package/dist/store/installs.js +10 -4
- package/dist/store/readiness.d.ts +5 -4
- package/dist/store/readiness.d.ts.map +1 -1
- package/dist/store/readiness.js +28 -12
- package/dist/store/records.d.ts +11 -4
- package/dist/store/records.d.ts.map +1 -1
- package/dist/store/records.js +56 -20
- package/dist/store/rooms-shown.d.ts +8 -0
- package/dist/store/rooms-shown.d.ts.map +1 -0
- package/dist/store/rooms-shown.js +13 -0
- package/dist/store.d.ts +9 -6
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +11 -2
- package/dist/stored.d.ts +24 -13
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +73 -17
- package/dist/surface.d.ts +4 -3
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +12 -13
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +31 -17
- package/dist/tables.d.ts +14 -7
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +36 -15
- package/dist/tallies.d.ts.map +1 -1
- package/dist/tallies.js +1 -2
- package/dist/wire.d.ts +40 -3
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +11 -1
- package/package.json +3 -3
- package/dist/attempt.d.ts +0 -16
- package/dist/attempt.d.ts.map +0 -1
- package/dist/attempt.js +0 -70
- package/dist/job.d.ts +0 -5
- package/dist/job.d.ts.map +0 -1
- package/dist/job.js +0 -7
- package/dist/log.d.ts +0 -6
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js +0 -14
package/README.md
CHANGED
|
@@ -12,14 +12,14 @@ npm install @agentshouse/mdruntime
|
|
|
12
12
|
|
|
13
13
|
## Entries
|
|
14
14
|
|
|
15
|
-
| Entry | For
|
|
16
|
-
| ------------------------------- |
|
|
17
|
-
| `@agentshouse/mdruntime/client` | The host's client: `connectMdRuntime(port)`
|
|
18
|
-
| `@agentshouse/mdruntime/host` | The host that serves a Runtime: `serveMdRuntime`
|
|
19
|
-
| `@agentshouse/mdruntime` | Shared types
|
|
20
|
-
| `@agentshouse/mdruntime/memory` | Tests: `createMemoryAdapter`, an in-memory Adapter
|
|
21
|
-
| `@agentshouse/mdruntime/tables` | The host's database: the Authored store's and opened files' tables, `answerRuntime`
|
|
22
|
-
| `@agentshouse/mdruntime/react` | React over the client: `useObserve`, `useSave`; `
|
|
15
|
+
| Entry | For |
|
|
16
|
+
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `@agentshouse/mdruntime/client` | The host's client: `connectMdRuntime(port)` |
|
|
18
|
+
| `@agentshouse/mdruntime/host` | The host that serves a Runtime: `serveMdRuntime` |
|
|
19
|
+
| `@agentshouse/mdruntime` | Shared types |
|
|
20
|
+
| `@agentshouse/mdruntime/memory` | Tests: `createMemoryAdapter`, an in-memory Adapter |
|
|
21
|
+
| `@agentshouse/mdruntime/tables` | The host's database: the Authored store's and opened files' tables, `answerRuntime` |
|
|
22
|
+
| `@agentshouse/mdruntime/react` | React over the client: `useObserve`, `useSave`; `useExpected`, a reader of an expectation store; `useLane`, a reader of an act lane |
|
|
23
23
|
|
|
24
24
|
## Usage
|
|
25
25
|
|
|
@@ -33,18 +33,20 @@ const rooms = await runtime.rooms();
|
|
|
33
33
|
const notes = await runtime.query({ types: ['note'], select: 'all', limit: 20 });
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
`observe('storage-loss')` reports `null
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
`observe('storage-loss')` reports `null`, the stable code `storage-loss` when
|
|
37
|
+
unsynchronized Room Drafts and Pending Changes were lost, or `visit` while the host holds
|
|
38
|
+
the database in memory, which ends with the visit; the readiness `persistence` answer is then
|
|
39
|
+
`memory`. The host supplies the user-facing wording.
|
|
39
40
|
|
|
40
41
|
In House the bridge object the page holds as `window.houseBridge` places the Chat, which
|
|
41
|
-
House serves with the page: install and bundle nothing for it. Mount it in an element
|
|
42
|
-
|
|
42
|
+
House serves with the page: install and bundle nothing for it. Mount it in an element it
|
|
43
|
+
fills, where it lays out the User's chats by the element's width, themed by CSS custom
|
|
44
|
+
properties on that element:
|
|
43
45
|
|
|
44
46
|
```ts
|
|
45
|
-
const chat = await window.houseBridge.chat.mount(element, {
|
|
47
|
+
const chat = await window.houseBridge.chat.mount(element, { conversation });
|
|
46
48
|
element.style.setProperty('--chat-accent', '#2a6cf0');
|
|
47
|
-
chat.update({
|
|
49
|
+
chat.update({ conversation: null, agent });
|
|
48
50
|
chat.unmount();
|
|
49
51
|
```
|
|
50
52
|
|
package/dist/acceptance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acceptance.d.ts","sourceRoot":"","sources":["../src/acceptance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"acceptance.d.ts","sourceRoot":"","sources":["../src/acceptance.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AA0V5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,QAK5D"}
|
package/dist/acceptance.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { refusalError } from './failure.js';
|
|
1
2
|
import { changeSet } from './change-set.js';
|
|
2
3
|
import { declared } from './declaration.js';
|
|
3
4
|
import { leaving as leavingIn, partnerOf } from './change.js';
|
|
@@ -38,11 +39,6 @@ async function keepUpload({ socket, presence }, local, locator, identifier, uplo
|
|
|
38
39
|
if (!socket.continuing())
|
|
39
40
|
throw new Error();
|
|
40
41
|
}
|
|
41
|
-
function logAccepted({ journal }, locator, submitted, accepted) {
|
|
42
|
-
journal.record(`outcome ${locator} ${submitted.id} accepted ${accepted.roomVersion}` +
|
|
43
|
-
(accepted.author === undefined ? '' : ` author ${accepted.author}`) +
|
|
44
|
-
(accepted.time === undefined ? '' : ` time ${accepted.time}`));
|
|
45
|
-
}
|
|
46
42
|
function restands(adoptions) {
|
|
47
43
|
return adoptions.flatMap((one) => (one === null || !('record' in one) ? [] : [one]));
|
|
48
44
|
}
|
|
@@ -54,7 +50,6 @@ async function adoption(runtime, room, current, local, submitted, accepted) {
|
|
|
54
50
|
return null;
|
|
55
51
|
}
|
|
56
52
|
const held = current.record.roomVersion;
|
|
57
|
-
logAccepted(runtime, room.locator, submitted, accepted);
|
|
58
53
|
let record = current.record;
|
|
59
54
|
let adopted;
|
|
60
55
|
if (!socket.reads.reached(room.locator, held, accepted.roomVersion) &&
|
|
@@ -118,7 +113,7 @@ async function behindIn({ store }, locator, batch) {
|
|
|
118
113
|
return room ? order.indexOf(batch.id) > 0 : order.length > 0;
|
|
119
114
|
}
|
|
120
115
|
async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
121
|
-
const { store, socket, presence
|
|
116
|
+
const { store, socket, presence } = runtime;
|
|
122
117
|
while (socket.continuing() &&
|
|
123
118
|
socket.session.now().authorization !== undefined &&
|
|
124
119
|
!signal.aborted) {
|
|
@@ -151,12 +146,10 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
151
146
|
}
|
|
152
147
|
if (socket.writesHeld()) {
|
|
153
148
|
progress.complete = false;
|
|
154
|
-
journal.record(`submission ${room.locator} ${head.id} held`);
|
|
155
149
|
return 'done';
|
|
156
150
|
}
|
|
157
151
|
const lost = earlier || submission.state === 'submitted';
|
|
158
152
|
let result;
|
|
159
|
-
journal.record(`submission ${room.locator} ${head.id}`);
|
|
160
153
|
await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'submitted' }, lost));
|
|
161
154
|
if (socket.session.now().paused || presence.lost(room.locator))
|
|
162
155
|
return 'done';
|
|
@@ -165,7 +158,6 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
165
158
|
if (signal.aborted)
|
|
166
159
|
return 'done';
|
|
167
160
|
progress.complete = false;
|
|
168
|
-
journal.record(`submission ${room.locator} ${head.id} held`);
|
|
169
161
|
return 'done';
|
|
170
162
|
}
|
|
171
163
|
const opensBefore = socket.session.now().openSignals;
|
|
@@ -183,7 +175,8 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
183
175
|
...(state?.upload === undefined ? {} : { upload: state.upload }),
|
|
184
176
|
}, (upload) => store.exclusive(() => keepUpload(runtime, local, room.locator, head.id, upload)));
|
|
185
177
|
}
|
|
186
|
-
catch {
|
|
178
|
+
catch (error) {
|
|
179
|
+
runtime.retries.failed('sending', submitting(room.locator), error);
|
|
187
180
|
heard();
|
|
188
181
|
progress.complete = false;
|
|
189
182
|
if (socket.continuing())
|
|
@@ -198,7 +191,10 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
198
191
|
heard();
|
|
199
192
|
if (!socket.continuing())
|
|
200
193
|
return 'done';
|
|
194
|
+
if (result.kind === 'accepted')
|
|
195
|
+
runtime.retries.succeeded('sending', submitting(room.locator));
|
|
201
196
|
if (result.kind === 'transport-uncertainty') {
|
|
197
|
+
runtime.retries.uncertain('sending', submitting(room.locator), result);
|
|
202
198
|
progress.complete = false;
|
|
203
199
|
progress.reachable = false;
|
|
204
200
|
return 'again';
|
|
@@ -218,7 +214,6 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
218
214
|
return 'done';
|
|
219
215
|
}
|
|
220
216
|
if (result.kind === 'write-halted') {
|
|
221
|
-
journal.record(`outcome ${room.locator} ${head.id} write-halted`);
|
|
222
217
|
await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'waiting' }, lost));
|
|
223
218
|
if (!socket.haltedSince(opensBefore))
|
|
224
219
|
continue;
|
|
@@ -226,16 +221,8 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
226
221
|
return 'done';
|
|
227
222
|
}
|
|
228
223
|
const other = partner === null ? undefined : presence.room(partner);
|
|
229
|
-
if (result.kind === 'conflicted' ||
|
|
230
|
-
result.kind === 'rejected' ||
|
|
231
|
-
result.kind === 'retryable-refusal') {
|
|
232
|
-
journal.record(`outcome ${room.locator} ${head.id} ${result.kind}` +
|
|
233
|
-
(result.kind === 'conflicted' && result.roomVersion !== undefined
|
|
234
|
-
? ` ${result.roomVersion}`
|
|
235
|
-
: ''));
|
|
236
|
-
journal.record(`refusal ${result.kind} ${result.code}`);
|
|
237
|
-
}
|
|
238
224
|
if (result.kind === 'retryable-refusal') {
|
|
225
|
+
runtime.retries.failed('sending', submitting(room.locator), refusalError(result));
|
|
239
226
|
const reset = result.reset;
|
|
240
227
|
progress.complete = false;
|
|
241
228
|
await store.exclusive(() => mark(runtime, local, room.locator, head, reset === undefined ? { state: 'waiting' } : { state: 'reset', reset }, lost));
|
|
@@ -277,10 +264,13 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
277
264
|
}
|
|
278
265
|
return 'done';
|
|
279
266
|
}
|
|
267
|
+
function submitting(locator) {
|
|
268
|
+
return `submit ${locator}`;
|
|
269
|
+
}
|
|
280
270
|
export function submitLater(runtime, locator) {
|
|
281
271
|
if (runtime.localSaves)
|
|
282
272
|
return;
|
|
283
|
-
void runtime.recovery.attempt(
|
|
273
|
+
void runtime.recovery.attempt(submitting(locator), (signal) => submitPass(runtime, locator, signal));
|
|
284
274
|
}
|
|
285
275
|
async function submitPass(runtime, locator, signal) {
|
|
286
276
|
const { store, socket, presence } = runtime;
|
|
@@ -297,7 +287,8 @@ async function submitPass(runtime, locator, signal) {
|
|
|
297
287
|
return 'done';
|
|
298
288
|
next = await submitRoom(runtime, room, await store.open(), authorization, progress, signal);
|
|
299
289
|
}
|
|
300
|
-
catch {
|
|
290
|
+
catch (error) {
|
|
291
|
+
runtime.retries.failed('sending', submitting(locator), error);
|
|
301
292
|
progress.reachable = false;
|
|
302
293
|
next = 'again';
|
|
303
294
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Expected, type Expecting } from './expectation.js';
|
|
2
|
+
export type Ended = 'accepted' | 'refused' | 'unanswered' | 'unsent';
|
|
3
|
+
export type Send<O> = {
|
|
4
|
+
(name: string, input: unknown, sending: (operation: string) => Promise<O>): Promise<O>;
|
|
5
|
+
expect(expected: Expected): void;
|
|
6
|
+
};
|
|
7
|
+
export type LaneShown<O> = {
|
|
8
|
+
readonly busy: boolean;
|
|
9
|
+
readonly drawn: boolean;
|
|
10
|
+
readonly ended: O | null;
|
|
11
|
+
};
|
|
12
|
+
export type Lane<O> = {
|
|
13
|
+
run(steps: (send: Send<O>) => Promise<O>, expected?: Expected): Promise<O>;
|
|
14
|
+
shown(): LaneShown<O>;
|
|
15
|
+
subscribe(listener: () => void): () => void;
|
|
16
|
+
forget(): void;
|
|
17
|
+
};
|
|
18
|
+
export type Acting<O> = {
|
|
19
|
+
open(): Lane<O>;
|
|
20
|
+
};
|
|
21
|
+
export type ActingRules<O> = {
|
|
22
|
+
readonly store: Pick<Expecting, 'begin' | 'expect' | 'drop'>;
|
|
23
|
+
readonly uncertain: O;
|
|
24
|
+
ending(outcome: O): Ended;
|
|
25
|
+
acted?(): void;
|
|
26
|
+
mint?(): string;
|
|
27
|
+
settles?(operation: string): Promise<boolean>;
|
|
28
|
+
};
|
|
29
|
+
export declare function acting<O>(rules: ActingRules<O>): Acting<O>;
|
|
30
|
+
//# sourceMappingURL=act-lanes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"act-lanes.d.ts","sourceRoot":"","sources":["../src/act-lanes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG/E,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAErE,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;IACpB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,IAAI,CAAC,CAAC,IAAI;IACpB,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3E,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IACtB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IACtB,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;IAC7D,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACtB,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC;IAC1B,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,IAAI,CAAC,IAAI,MAAM,CAAC;IAChB,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/C,CAAC;AAUF,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CA6N1D"}
|
|
@@ -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
|
|
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
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|