@agentshouse/mdruntime 0.1.0-cd26b960b7262 → 0.1.0-cd30853a1b15e
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 +21 -19
- package/dist/acceptance.d.ts +0 -3
- package/dist/acceptance.d.ts.map +1 -1
- package/dist/acceptance.js +72 -158
- 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 +118 -67
- package/dist/adapter.d.ts +81 -56
- 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/authored.d.ts +88 -0
- package/dist/authored.d.ts.map +1 -0
- package/dist/authored.js +345 -0
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +6 -19
- package/dist/change-set.d.ts +4 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +6 -0
- package/dist/change.d.ts +4 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +3 -0
- 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 +10 -19
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +30 -18
- package/dist/collection.d.ts +25 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +19 -2
- package/dist/column.d.ts +5 -0
- package/dist/column.d.ts.map +1 -0
- package/dist/column.js +9 -0
- package/dist/compile.d.ts +2 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +17 -5
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +31 -24
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +1 -1
- package/dist/conversation-live.d.ts +26 -12
- package/dist/conversation-live.d.ts.map +1 -1
- package/dist/conversation-live.js +23 -12
- package/dist/conversation-row.d.ts +8 -1
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +20 -7
- package/dist/conversation.d.ts +32 -10
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +317 -232
- package/dist/declaration.d.ts +10 -0
- package/dist/declaration.d.ts.map +1 -0
- package/dist/declaration.js +24 -0
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +19 -44
- 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 +3 -0
- package/dist/failure.d.ts.map +1 -1
- package/dist/failure.js +6 -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 +18 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +55 -15
- package/dist/index.d.ts +15 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/install.d.ts +10 -6
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +92 -109
- package/dist/lifecycle.d.ts +1 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +54 -40
- package/dist/listing.d.ts +11 -12
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +48 -72
- package/dist/live.d.ts +5 -3
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +74 -31
- package/dist/loaded.d.ts +5 -0
- package/dist/loaded.d.ts.map +1 -0
- package/dist/loaded.js +40 -0
- package/dist/locks.d.ts +2 -4
- package/dist/locks.d.ts.map +1 -1
- package/dist/locks.js +10 -39
- package/dist/lost.d.ts.map +1 -1
- package/dist/lost.js +11 -23
- package/dist/media.d.ts +5 -0
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +65 -14
- package/dist/memory.d.ts +7 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +56 -26
- package/dist/messages.d.ts +12 -6
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +25 -27
- package/dist/model.d.ts +0 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -5
- package/dist/models.d.ts +4 -8
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +97 -139
- package/dist/observation.d.ts +27 -12
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +173 -69
- package/dist/opened.d.ts +1 -1
- package/dist/opened.d.ts.map +1 -1
- package/dist/opened.js +2 -2
- package/dist/opening.d.ts.map +1 -1
- package/dist/opening.js +5 -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 +6 -2
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +37 -24
- 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 +3 -59
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +10 -123
- package/dist/preparation.d.ts +27 -6
- package/dist/preparation.d.ts.map +1 -1
- package/dist/preparation.js +154 -66
- package/dist/presence.d.ts +58 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +231 -0
- package/dist/queries.d.ts +2 -2
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +66 -30
- package/dist/questions.d.ts +1 -5
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +1 -7
- package/dist/queue.d.ts +40 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +480 -0
- package/dist/reach.d.ts +2 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +83 -25
- package/dist/react.d.ts +8 -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 +4 -2
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +11 -4
- package/dist/recovery.d.ts +3 -1
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +29 -7
- package/dist/refresh.js +2 -2
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +5 -5
- package/dist/replica.d.ts +5 -11
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +14 -16
- 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 +30 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +270 -63
- package/dist/room-drafts.d.ts.map +1 -1
- package/dist/room-drafts.js +8 -5
- package/dist/room-list.d.ts +10 -0
- package/dist/room-list.d.ts.map +1 -0
- package/dist/room-list.js +45 -0
- package/dist/rows.d.ts +2 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +9 -10
- package/dist/runtime.d.ts +9 -18
- package/dist/runtime.d.ts.map +1 -1
- package/dist/save.d.ts +42 -90
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +314 -223
- package/dist/saves.d.ts +2 -40
- package/dist/saves.d.ts.map +1 -1
- package/dist/saves.js +124 -703
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +4 -4
- package/dist/shown.d.ts +7 -5
- package/dist/shown.d.ts.map +1 -1
- package/dist/shown.js +75 -58
- 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 -6
- package/dist/socket.d.ts.map +1 -1
- package/dist/socket.js +3 -14
- package/dist/source.d.ts +5 -7
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +13 -2
- 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 +17 -6
- package/dist/store/records.d.ts.map +1 -1
- package/dist/store/records.js +56 -22
- 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 +23 -14
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +46 -17
- package/dist/stored.d.ts +24 -13
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +80 -29
- package/dist/surface.d.ts +5 -3
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +23 -21
- package/dist/sync.d.ts +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +89 -85
- package/dist/tables.d.ts +16 -56
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +86 -327
- package/dist/tallies.d.ts.map +1 -1
- package/dist/tallies.js +1 -2
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +4 -10
- package/dist/wire.d.ts +45 -7
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +15 -4
- package/package.json +3 -2
- 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 -33
- package/dist/job.d.ts.map +0 -1
- package/dist/job.js +0 -54
- package/dist/log.d.ts +0 -6
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js +0 -14
- package/dist/socket/rooms.d.ts +0 -44
- package/dist/socket/rooms.d.ts.map +0 -1
- package/dist/socket/rooms.js +0 -90
- package/dist/store/fences.d.ts +0 -16
- package/dist/store/fences.d.ts.map +0 -1
- package/dist/store/fences.js +0 -26
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
|
|
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: `formatted` lays it out for a device format, keeping the Authored store's tables and creating any it lacks, and `answerRuntime` answers it |
|
|
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,24 +33,26 @@ 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, or as the Chat button, House's dot that opens it in a sheet:
|
|
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({
|
|
48
|
-
chat.
|
|
49
|
+
chat.update({ conversation: null, agent });
|
|
50
|
+
const button = await window.houseBridge.chat.mountButton({});
|
|
51
|
+
button.open({ agent });
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
The rules an App's agent follows, including Local Query, search, Room
|
|
52
|
-
|
|
53
|
-
`guide/open` opens.
|
|
54
|
+
The rules an App's agent follows, including Local Query, search, Room Draft, Save and the
|
|
55
|
+
Chat, are the `apps/` pages of House's Guide, which House's `guide/open` opens.
|
|
54
56
|
|
|
55
57
|
## License
|
|
56
58
|
|
package/dist/acceptance.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
1
|
import type { Runtime } from './runtime.js';
|
|
2
|
-
import type { RuntimeStore } from './store.js';
|
|
3
|
-
export declare function unpair(runtime: Runtime, local: RuntimeStore): Promise<void>;
|
|
4
2
|
export declare function submitLater(runtime: Runtime, locator: string): void;
|
|
5
|
-
export declare function submitAll(runtime: Runtime): Promise<void>;
|
|
6
3
|
//# sourceMappingURL=acceptance.d.ts.map
|
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,18 +1,19 @@
|
|
|
1
|
+
import { refusalError } from './failure.js';
|
|
1
2
|
import { changeSet } from './change-set.js';
|
|
3
|
+
import { declared } from './declaration.js';
|
|
2
4
|
import { leaving as leavingIn, partnerOf } from './change.js';
|
|
3
5
|
import { olderThan, showing } from './install.js';
|
|
4
|
-
import {
|
|
6
|
+
import { scoped } from './models.js';
|
|
7
|
+
import { answered, settle } from './queue.js';
|
|
5
8
|
import { refuse } from './refusal.js';
|
|
6
|
-
import {
|
|
7
|
-
import { batchFile
|
|
9
|
+
import { returnedPaths, returning, slicing } from './replica.js';
|
|
10
|
+
import { batchFile } from './saves.js';
|
|
8
11
|
import { rest, roomUnreadable, statusShown } from './shown.js';
|
|
12
|
+
import { advanced, withhold } from './sync.js';
|
|
9
13
|
import { unconfirmed } from './transfer.js';
|
|
10
14
|
import { stepped } from './turn.js';
|
|
11
|
-
function pendingKey(locator, id) {
|
|
12
|
-
return `${locator}\u0000${id}`;
|
|
13
|
-
}
|
|
14
15
|
async function mark(runtime, local, locator, batch, submission, lost) {
|
|
15
|
-
const { store, socket } = runtime;
|
|
16
|
+
const { store, socket, presence } = runtime;
|
|
16
17
|
const partner = partnerOf(batch, locator);
|
|
17
18
|
for (const held of partner === null ? [locator] : [locator, partner]) {
|
|
18
19
|
const { state, room } = await local.pending(held, batch.id);
|
|
@@ -22,116 +23,86 @@ async function mark(runtime, local, locator, batch, submission, lost) {
|
|
|
22
23
|
continue;
|
|
23
24
|
}
|
|
24
25
|
await local.submit(held, batch.id, submission, lost);
|
|
25
|
-
if (
|
|
26
|
+
if (presence.lost(held))
|
|
26
27
|
continue;
|
|
27
28
|
if (room)
|
|
28
29
|
store.changed(changeSet(held, { queue: true }));
|
|
29
30
|
}
|
|
30
31
|
statusShown(runtime);
|
|
31
32
|
}
|
|
32
|
-
async function keepUpload({
|
|
33
|
+
async function keepUpload({ socket, presence }, local, locator, identifier, upload) {
|
|
33
34
|
if (!socket.continuing())
|
|
34
35
|
throw new Error();
|
|
35
36
|
await local.keepUpload(locator, identifier, upload);
|
|
36
|
-
if (
|
|
37
|
+
if (presence.lost(locator))
|
|
37
38
|
throw new Error();
|
|
38
39
|
if (!socket.continuing())
|
|
39
40
|
throw new Error();
|
|
40
41
|
}
|
|
41
|
-
function
|
|
42
|
-
return
|
|
43
|
-
batch,
|
|
44
|
-
returned: {
|
|
45
|
-
kind: result.kind,
|
|
46
|
-
code: result.code,
|
|
47
|
-
fields: result.fields,
|
|
48
|
-
retryable: result.retryable,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function logAccepted({ journal }, locator, submitted, accepted) {
|
|
53
|
-
journal.record(`outcome ${locator} ${submitted.id} accepted ${accepted.roomVersion}` +
|
|
54
|
-
(accepted.author === undefined ? '' : ` author ${accepted.author}`) +
|
|
55
|
-
(accepted.time === undefined ? '' : ` time ${accepted.time}`));
|
|
56
|
-
}
|
|
57
|
-
function settling(acceptance) {
|
|
58
|
-
return acceptance !== null && 'apply' in acceptance;
|
|
59
|
-
}
|
|
60
|
-
function failureOf(acceptance) {
|
|
61
|
-
return settling(acceptance) ? null : acceptance;
|
|
42
|
+
function restands(adoptions) {
|
|
43
|
+
return adoptions.flatMap((one) => (one === null || !('record' in one) ? [] : [one]));
|
|
62
44
|
}
|
|
63
|
-
async function
|
|
45
|
+
async function adoption(runtime, room, current, local, submitted, accepted) {
|
|
64
46
|
const { store, socket } = runtime;
|
|
65
47
|
if (!socket.continuing())
|
|
66
48
|
return unconfirmed;
|
|
67
|
-
const work = await store.work(room.locator);
|
|
68
|
-
const current = work.replica;
|
|
69
49
|
if (current === undefined || !current.queue.some((batch) => batch.id === submitted.id)) {
|
|
70
50
|
return null;
|
|
71
51
|
}
|
|
72
52
|
const held = current.record.roomVersion;
|
|
73
|
-
logAccepted(runtime, room.locator, submitted, accepted);
|
|
74
53
|
let record = current.record;
|
|
75
|
-
let
|
|
54
|
+
let adopted;
|
|
76
55
|
if (!socket.reads.reached(room.locator, held, accepted.roomVersion) &&
|
|
77
56
|
!olderThan(runtime, room.locator, accepted.roomVersion, held)) {
|
|
78
57
|
const paths = [...returnedPaths(submitted, accepted)];
|
|
79
58
|
const confirmedLayer = await stepped(slicing(await local.entries(record.key, 'confirmed', paths), paths));
|
|
80
|
-
|
|
59
|
+
adopted = await stepped(returning(confirmedLayer, submitted, accepted, accepted.roomVersion, store.composed(record)));
|
|
81
60
|
record = {
|
|
82
61
|
...record,
|
|
83
62
|
roomVersion: socket.follows(room.locator, held, accepted.roomVersion)
|
|
84
63
|
? accepted.roomVersion
|
|
85
64
|
: held,
|
|
86
65
|
};
|
|
87
|
-
changes = back;
|
|
88
66
|
}
|
|
89
|
-
const settled = await settlement(runtime, local, room.locator, work, record, current.queue.filter((batch) => batch.id !== submitted.id), { room: true, ...(changes === undefined ? {} : { changes }) });
|
|
90
67
|
const reached = record.roomVersion;
|
|
91
68
|
return {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
69
|
+
locator: room.locator,
|
|
70
|
+
record,
|
|
71
|
+
accepted: submitted.id,
|
|
72
|
+
...(adopted === undefined ? {} : { adopted }),
|
|
73
|
+
after() {
|
|
95
74
|
showing(runtime, room.locator, accepted.roomVersion, reached);
|
|
96
|
-
readable(
|
|
97
|
-
return set;
|
|
75
|
+
runtime.presence.readable(room.locator);
|
|
98
76
|
},
|
|
99
77
|
};
|
|
100
78
|
}
|
|
101
|
-
async function adoptedTogether(runtime, local, acceptances) {
|
|
102
|
-
const settlements = acceptances.filter(settling);
|
|
103
|
-
if (settlements.length > 0) {
|
|
104
|
-
const set = await together(runtime, local, settlements);
|
|
105
|
-
void statusShown(runtime);
|
|
106
|
-
void runtime.store.changed(set);
|
|
107
|
-
}
|
|
108
|
-
await unpair(runtime, local);
|
|
109
|
-
}
|
|
110
79
|
async function adopted(runtime, room, local, submitted, accepted) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
await
|
|
114
|
-
|
|
80
|
+
let kept = true;
|
|
81
|
+
await settle(runtime, [room.locator], async (held) => {
|
|
82
|
+
const adopting = await adoption(runtime, room, held.get(room.locator)?.replica, local, submitted, accepted);
|
|
83
|
+
kept = adopting !== unconfirmed;
|
|
84
|
+
return restands([adopting]);
|
|
115
85
|
});
|
|
116
|
-
return
|
|
86
|
+
return kept;
|
|
117
87
|
}
|
|
118
88
|
async function adoptedMove(runtime, room, partner, local, submitted, accepted) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const left = await
|
|
123
|
-
const
|
|
89
|
+
const other = runtime.presence.room(partner);
|
|
90
|
+
let kept = true;
|
|
91
|
+
await settle(runtime, [room.locator, partner], async (held) => {
|
|
92
|
+
const left = await adoption(runtime, room, held.get(room.locator)?.replica, local, submitted, accepted);
|
|
93
|
+
const there = held.get(partner)?.replica;
|
|
94
|
+
const arriving = there?.queue.find((batch) => batch.id === submitted.id);
|
|
124
95
|
const arrived = other === undefined || arriving === undefined || accepted.destination === undefined
|
|
125
96
|
? null
|
|
126
|
-
: await
|
|
97
|
+
: await adoption(runtime, other, there, local, arriving, {
|
|
127
98
|
kind: 'accepted',
|
|
128
99
|
...accepted.destination,
|
|
129
100
|
});
|
|
130
|
-
|
|
131
|
-
return
|
|
101
|
+
kept = left !== unconfirmed;
|
|
102
|
+
return restands([left, arrived]);
|
|
132
103
|
});
|
|
133
104
|
submitLater(runtime, partner);
|
|
134
|
-
return
|
|
105
|
+
return kept;
|
|
135
106
|
}
|
|
136
107
|
async function behindIn({ store }, locator, batch) {
|
|
137
108
|
const local = await store.open();
|
|
@@ -141,38 +112,12 @@ async function behindIn({ store }, locator, batch) {
|
|
|
141
112
|
]);
|
|
142
113
|
return room ? order.indexOf(batch.id) > 0 : order.length > 0;
|
|
143
114
|
}
|
|
144
|
-
async function unpaired(local, skipped) {
|
|
145
|
-
const { queued, moving } = await local.moving();
|
|
146
|
-
for (const { locator, batch, state } of moving) {
|
|
147
|
-
const partner = partnerOf(batch, locator);
|
|
148
|
-
if (partner === null || skipped.has(pendingKey(locator, batch.id)))
|
|
149
|
-
continue;
|
|
150
|
-
if (queued.get(partner)?.includes(batch.id) === true)
|
|
151
|
-
continue;
|
|
152
|
-
if (!leavingIn(batch, locator) || withdrawable(new Map([[batch.id, state]]))(batch)) {
|
|
153
|
-
return { locator, batch };
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
export async function unpair(runtime, local) {
|
|
159
|
-
const { store, socket } = runtime;
|
|
160
|
-
const handled = new Set();
|
|
161
|
-
for (let held = await unpaired(local, handled); held !== null && socket.continuing(); held = await unpaired(local, handled)) {
|
|
162
|
-
const { locator, batch } = held;
|
|
163
|
-
handled.add(pendingKey(locator, batch.id));
|
|
164
|
-
store.changed(await together(runtime, local, [await unpairing(runtime, local, locator, [batch])]));
|
|
165
|
-
}
|
|
166
|
-
if (handled.size === 0)
|
|
167
|
-
return;
|
|
168
|
-
statusShown(runtime);
|
|
169
|
-
}
|
|
170
115
|
async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
171
|
-
const { store, socket,
|
|
116
|
+
const { store, socket, presence } = runtime;
|
|
172
117
|
while (socket.continuing() &&
|
|
173
118
|
socket.session.now().authorization !== undefined &&
|
|
174
119
|
!signal.aborted) {
|
|
175
|
-
const headId = (await local.order(room.locator)).find((id) => store.
|
|
120
|
+
const headId = (await local.order(room.locator)).find((id) => store.conflicted.of(room.locator, id) === undefined);
|
|
176
121
|
if (headId === undefined)
|
|
177
122
|
return 'done';
|
|
178
123
|
const [head, pending] = await Promise.all([
|
|
@@ -201,27 +146,24 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
201
146
|
}
|
|
202
147
|
if (socket.writesHeld()) {
|
|
203
148
|
progress.complete = false;
|
|
204
|
-
journal.record(`submission ${room.locator} ${head.id} held`);
|
|
205
149
|
return 'done';
|
|
206
150
|
}
|
|
207
151
|
const lost = earlier || submission.state === 'submitted';
|
|
208
152
|
let result;
|
|
209
|
-
journal.record(`submission ${room.locator} ${head.id}`);
|
|
210
153
|
await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'submitted' }, lost));
|
|
211
|
-
if (socket.session.now().paused ||
|
|
154
|
+
if (socket.session.now().paused || presence.lost(room.locator))
|
|
212
155
|
return 'done';
|
|
213
156
|
if (signal.aborted || socket.writesHeld()) {
|
|
214
157
|
await store.exclusive(() => mark(runtime, local, room.locator, head, submission, earlier));
|
|
215
158
|
if (signal.aborted)
|
|
216
159
|
return 'done';
|
|
217
160
|
progress.complete = false;
|
|
218
|
-
journal.record(`submission ${room.locator} ${head.id} held`);
|
|
219
161
|
return 'done';
|
|
220
162
|
}
|
|
221
163
|
const opensBefore = socket.session.now().openSignals;
|
|
222
164
|
const answeredHere = socket.awaitingAnswer(room.locator);
|
|
223
165
|
const answeredThere = partner === null ? () => { } : socket.awaitingAnswer(partner);
|
|
224
|
-
const
|
|
166
|
+
const heard = () => {
|
|
225
167
|
answeredHere();
|
|
226
168
|
answeredThere();
|
|
227
169
|
};
|
|
@@ -233,29 +175,33 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
233
175
|
...(state?.upload === undefined ? {} : { upload: state.upload }),
|
|
234
176
|
}, (upload) => store.exclusive(() => keepUpload(runtime, local, room.locator, head.id, upload)));
|
|
235
177
|
}
|
|
236
|
-
catch {
|
|
237
|
-
|
|
178
|
+
catch (error) {
|
|
179
|
+
runtime.retries.failed('sending', submitting(room.locator), error);
|
|
180
|
+
heard();
|
|
238
181
|
progress.complete = false;
|
|
239
182
|
if (socket.continuing())
|
|
240
183
|
progress.reachable = false;
|
|
241
184
|
return 'again';
|
|
242
185
|
}
|
|
243
186
|
if (signal.aborted) {
|
|
244
|
-
|
|
187
|
+
heard();
|
|
245
188
|
return 'done';
|
|
246
189
|
}
|
|
247
190
|
if (result.kind !== 'accepted' || !socket.continuing())
|
|
248
|
-
|
|
191
|
+
heard();
|
|
249
192
|
if (!socket.continuing())
|
|
250
193
|
return 'done';
|
|
194
|
+
if (result.kind === 'accepted')
|
|
195
|
+
runtime.retries.succeeded('sending', submitting(room.locator));
|
|
251
196
|
if (result.kind === 'transport-uncertainty') {
|
|
197
|
+
runtime.retries.uncertain('sending', submitting(room.locator), result);
|
|
252
198
|
progress.complete = false;
|
|
253
199
|
progress.reachable = false;
|
|
254
200
|
return 'again';
|
|
255
201
|
}
|
|
256
202
|
if (result.kind === 'room-not-readable') {
|
|
257
203
|
progress.complete = false;
|
|
258
|
-
roomUnreadable(runtime,
|
|
204
|
+
roomUnreadable(runtime, (presence.room(result.locator) ?? room).locator);
|
|
259
205
|
return 'done';
|
|
260
206
|
}
|
|
261
207
|
if (result.kind === 'revoked-authorization') {
|
|
@@ -263,81 +209,54 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
263
209
|
return 'done';
|
|
264
210
|
}
|
|
265
211
|
if (result.kind === 'scoped-refusal') {
|
|
266
|
-
await
|
|
212
|
+
await scoped(runtime, result, room.locator, declared(room));
|
|
267
213
|
progress.complete = false;
|
|
268
214
|
return 'done';
|
|
269
215
|
}
|
|
270
216
|
if (result.kind === 'write-halted') {
|
|
271
|
-
journal.record(`outcome ${room.locator} ${head.id} write-halted`);
|
|
272
217
|
await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'waiting' }, lost));
|
|
273
218
|
if (!socket.haltedSince(opensBefore))
|
|
274
219
|
continue;
|
|
275
220
|
progress.complete = false;
|
|
276
221
|
return 'done';
|
|
277
222
|
}
|
|
278
|
-
const other = partner === null ? undefined :
|
|
279
|
-
if (result.kind === 'conflicted' ||
|
|
280
|
-
result.kind === 'rejected' ||
|
|
281
|
-
result.kind === 'retryable-refusal') {
|
|
282
|
-
journal.record(`outcome ${room.locator} ${head.id} ${result.kind}` +
|
|
283
|
-
(result.kind === 'conflicted' && result.roomVersion !== undefined
|
|
284
|
-
? ` ${result.roomVersion}`
|
|
285
|
-
: ''));
|
|
286
|
-
journal.record(`refusal ${result.kind} ${result.code}`);
|
|
287
|
-
}
|
|
223
|
+
const other = partner === null ? undefined : presence.room(partner);
|
|
288
224
|
if (result.kind === 'retryable-refusal') {
|
|
225
|
+
runtime.retries.failed('sending', submitting(room.locator), refusalError(result));
|
|
289
226
|
const reset = result.reset;
|
|
290
227
|
progress.complete = false;
|
|
291
228
|
await store.exclusive(() => mark(runtime, local, room.locator, head, reset === undefined ? { state: 'waiting' } : { state: 'reset', reset }, lost));
|
|
292
229
|
return reset === undefined ? 'again' : { at: Date.parse(reset) };
|
|
293
230
|
}
|
|
294
231
|
if (result.kind === 'conflicted' || result.kind === 'rejected') {
|
|
295
|
-
const left = leaving(head, result);
|
|
296
232
|
const refreshed = async () => ({
|
|
297
|
-
there: other === undefined ? null : await advanced(other, local, authorized),
|
|
298
|
-
here: await advanced(room, local, authorized),
|
|
233
|
+
there: other === undefined ? null : await advanced(runtime, other, local, authorized),
|
|
234
|
+
here: await advanced(runtime, room, local, authorized),
|
|
299
235
|
});
|
|
300
236
|
const judged = result.kind === 'conflicted' && other !== undefined ? await refreshed() : null;
|
|
301
237
|
if (judged !== null && (judged.there !== null || judged.here !== null)) {
|
|
302
238
|
await store.exclusive(() => mark(runtime, local, room.locator, head, { state: 'waiting' }, lost));
|
|
303
239
|
if (other !== undefined && judged.there !== null) {
|
|
304
|
-
await withhold(judged.there, other, local, progress);
|
|
240
|
+
await withhold(runtime, judged.there, other, local, progress);
|
|
305
241
|
}
|
|
306
242
|
if (judged.here !== null)
|
|
307
|
-
await withhold(judged.here, room, local, progress);
|
|
243
|
+
await withhold(runtime, judged.here, room, local, progress);
|
|
308
244
|
return 'done';
|
|
309
245
|
}
|
|
310
|
-
await
|
|
311
|
-
if (!socket.continuing())
|
|
312
|
-
return;
|
|
313
|
-
const work = await store.work(room.locator);
|
|
314
|
-
const current = work.replica;
|
|
315
|
-
if (current === undefined || !current.queue.some((batch) => batch.id === head.id)) {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
const confirmedLayer = await sliceAt(store, current.record, 'confirmed', [head]);
|
|
319
|
-
const held = result.kind === 'conflicted' &&
|
|
320
|
-
(await landedWhole(store, room.locator, head, confirmedLayer, result.affected));
|
|
321
|
-
if (held && partner === null && !landed(head, confirmedLayer)) {
|
|
322
|
-
store.landed.hold(room.locator, head.id, Object.fromEntries([...touchedBy([head])].map((path) => [path, confirmedLayer.revisions[path]])));
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
store.changed(await settle(runtime, local, room.locator, work, current.record, current.queue.filter((batch) => batch.id !== head.id), { leaving: [held ? { ...left, returned: null } : left] }));
|
|
326
|
-
await unpair(runtime, local);
|
|
327
|
-
statusShown(runtime);
|
|
328
|
-
});
|
|
246
|
+
await answered(runtime, room.locator, head, result);
|
|
329
247
|
const { there, here } = judged ?? (await refreshed());
|
|
330
|
-
if (other !== undefined && there !== null)
|
|
331
|
-
await withhold(there, other, local, progress);
|
|
248
|
+
if (other !== undefined && there !== null) {
|
|
249
|
+
await withhold(runtime, there, other, local, progress);
|
|
250
|
+
}
|
|
332
251
|
if (here !== null) {
|
|
333
|
-
await withhold(here, room, local, progress);
|
|
252
|
+
await withhold(runtime, here, room, local, progress);
|
|
334
253
|
return 'done';
|
|
335
254
|
}
|
|
336
255
|
continue;
|
|
337
256
|
}
|
|
338
257
|
const kept = await (partner === null
|
|
339
258
|
? adopted(runtime, room, local, head, result)
|
|
340
|
-
: adoptedMove(runtime, room, partner, local, head, result)).finally(
|
|
259
|
+
: adoptedMove(runtime, room, partner, local, head, result)).finally(heard);
|
|
341
260
|
if (!kept) {
|
|
342
261
|
progress.complete = false;
|
|
343
262
|
return 'done';
|
|
@@ -345,14 +264,17 @@ async function submitRoom(runtime, room, local, authorized, progress, signal) {
|
|
|
345
264
|
}
|
|
346
265
|
return 'done';
|
|
347
266
|
}
|
|
267
|
+
function submitting(locator) {
|
|
268
|
+
return `submit ${locator}`;
|
|
269
|
+
}
|
|
348
270
|
export function submitLater(runtime, locator) {
|
|
349
271
|
if (runtime.localSaves)
|
|
350
272
|
return;
|
|
351
|
-
void runtime.recovery.attempt(
|
|
273
|
+
void runtime.recovery.attempt(submitting(locator), (signal) => submitPass(runtime, locator, signal));
|
|
352
274
|
}
|
|
353
275
|
async function submitPass(runtime, locator, signal) {
|
|
354
|
-
const { store, socket } = runtime;
|
|
355
|
-
const room =
|
|
276
|
+
const { store, socket, presence } = runtime;
|
|
277
|
+
const room = presence.room(locator);
|
|
356
278
|
if (!socket.continuing() || socket.stopping() || room === undefined) {
|
|
357
279
|
return 'done';
|
|
358
280
|
}
|
|
@@ -365,7 +287,8 @@ async function submitPass(runtime, locator, signal) {
|
|
|
365
287
|
return 'done';
|
|
366
288
|
next = await submitRoom(runtime, room, await store.open(), authorization, progress, signal);
|
|
367
289
|
}
|
|
368
|
-
catch {
|
|
290
|
+
catch (error) {
|
|
291
|
+
runtime.retries.failed('sending', submitting(locator), error);
|
|
369
292
|
progress.reachable = false;
|
|
370
293
|
next = 'again';
|
|
371
294
|
}
|
|
@@ -374,12 +297,3 @@ async function submitPass(runtime, locator, signal) {
|
|
|
374
297
|
await rest(runtime, progress);
|
|
375
298
|
return next === 'again' && !socket.isOpen() ? 'done' : next;
|
|
376
299
|
}
|
|
377
|
-
export async function submitAll(runtime) {
|
|
378
|
-
const { store } = runtime;
|
|
379
|
-
if (runtime.localSaves)
|
|
380
|
-
return;
|
|
381
|
-
for (const locator of await (await store.open()).queued()) {
|
|
382
|
-
if (!store.fences.has(locator))
|
|
383
|
-
submitLater(runtime, locator);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
@@ -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"}
|