@agentshouse/mdruntime 0.1.0-c0136de3edfbe → 0.1.0-c01d4615bfe46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -15
- package/dist/acceptance.d.ts +0 -3
- package/dist/acceptance.d.ts.map +1 -1
- package/dist/acceptance.js +74 -164
- 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 +122 -68
- package/dist/adapter.d.ts +49 -55
- 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/bootstrap.d.ts +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +6 -18
- 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.map +1 -1
- package/dist/change.js +4 -2
- package/dist/chat-types.d.ts +2 -2
- package/dist/chat-types.d.ts.map +1 -1
- package/dist/chat-types.js +11 -2
- package/dist/client.d.ts +13 -19
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +35 -19
- package/dist/collection.d.ts +22 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +12 -2
- package/dist/compile.d.ts +2 -0
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +31 -24
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +32 -24
- package/dist/conversation-live.d.ts +147 -0
- package/dist/conversation-live.d.ts.map +1 -0
- package/dist/conversation-live.js +258 -0
- package/dist/conversation-row.d.ts.map +1 -1
- package/dist/conversation-row.js +7 -1
- package/dist/conversation.d.ts +52 -44
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +956 -1029
- 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 +13 -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 +26 -13
- package/dist/expectation.d.ts.map +1 -1
- package/dist/expectation.js +72 -19
- 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 +1 -0
- package/dist/figures.d.ts.map +1 -1
- package/dist/figures.js +2 -2
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +2 -1
- package/dist/holdings.d.ts +29 -0
- package/dist/holdings.d.ts.map +1 -0
- package/dist/holdings.js +95 -0
- package/dist/host.d.ts +18 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +46 -11
- package/dist/index.d.ts +17 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -6
- package/dist/install.d.ts +2 -4
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +53 -83
- package/dist/lifecycle.d.ts +1 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +45 -35
- package/dist/listing.d.ts +6 -11
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +25 -61
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +3 -3
- 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 +10 -22
- package/dist/media.d.ts +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +10 -13
- package/dist/memory.d.ts +7 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +58 -27
- package/dist/messages.d.ts +10 -6
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +26 -36
- 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 +95 -135
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +22 -21
- package/dist/opened.d.ts +1 -1
- package/dist/opened.d.ts.map +1 -1
- package/dist/opened.js +5 -5
- package/dist/opening.d.ts.map +1 -1
- package/dist/opening.js +7 -10
- package/dist/outcome.d.ts +10 -1
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +23 -2
- package/dist/overlay.d.ts +5 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +36 -21
- 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 -58
- package/dist/parts.d.ts.map +1 -1
- package/dist/parts.js +10 -115
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +22 -0
- package/dist/preparation.d.ts.map +1 -1
- package/dist/preparation.js +25 -24
- package/dist/presence.d.ts +52 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +220 -0
- package/dist/queries.d.ts +1 -1
- package/dist/queries.d.ts.map +1 -1
- package/dist/queries.js +24 -14
- package/dist/query.d.ts +0 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/questions.d.ts +2 -5
- package/dist/questions.d.ts.map +1 -1
- package/dist/questions.js +3 -6
- package/dist/queue.d.ts +40 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +450 -0
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +68 -23
- package/dist/react.d.ts +11 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +33 -1
- package/dist/readiness.d.ts +1 -2
- package/dist/readiness.d.ts.map +1 -1
- package/dist/reads.d.ts +4 -1
- package/dist/reads.d.ts.map +1 -1
- package/dist/reads.js +47 -5
- 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 -6
- package/dist/replica.d.ts +5 -10
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +15 -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 +4 -6
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +48 -59
- package/dist/room-drafts.d.ts.map +1 -1
- package/dist/room-drafts.js +17 -16
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +3 -4
- package/dist/runtime.d.ts +11 -19
- package/dist/runtime.d.ts.map +1 -1
- package/dist/save.d.ts +42 -86
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +333 -163
- package/dist/saves.d.ts +2 -40
- package/dist/saves.d.ts.map +1 -1
- package/dist/saves.js +109 -703
- package/dist/seed.d.ts.map +1 -1
- package/dist/seed.js +2 -3
- package/dist/shared.d.ts +1 -6
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +13 -95
- package/dist/shown.d.ts +6 -4
- package/dist/shown.d.ts.map +1 -1
- package/dist/shown.js +43 -35
- 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/session.d.ts +0 -1
- package/dist/socket/session.d.ts.map +1 -1
- package/dist/socket.d.ts +3 -6
- package/dist/socket.d.ts.map +1 -1
- package/dist/socket.js +5 -16
- package/dist/source.d.ts +0 -7
- package/dist/source.d.ts.map +1 -1
- package/dist/source.js +5 -4
- package/dist/store/records.d.ts +11 -8
- package/dist/store/records.d.ts.map +1 -1
- package/dist/store/records.js +43 -12
- package/dist/store/space.d.ts +1 -1
- package/dist/store/space.d.ts.map +1 -1
- package/dist/store/space.js +0 -2
- package/dist/store/watchers.js +1 -2
- package/dist/store.d.ts +12 -7
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +38 -13
- package/dist/stored.d.ts +2 -1
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +27 -15
- package/dist/surface.d.ts +7 -4
- package/dist/surface.d.ts.map +1 -1
- package/dist/surface.js +30 -25
- package/dist/sync.d.ts +0 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +93 -89
- package/dist/tables.d.ts +19 -11
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +58 -21
- package/dist/tallies.d.ts.map +1 -1
- package/dist/tallies.js +6 -7
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +2 -2
- package/dist/wire.d.ts +53 -7
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +17 -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 -43
- 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
|
@@ -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"}
|
package/dist/actions.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { roomTarget, target } from '@agentshouse/mdmodel';
|
|
2
|
+
import { CATCHING_UP, holdsSubmission, resendConversations } from './conversation.js';
|
|
2
3
|
import { listingNow } from './listing.js';
|
|
3
4
|
import { locked, lockedRooms } from './locks.js';
|
|
4
5
|
import { scoped } from './models.js';
|
|
5
|
-
import { ABSENT_TARGET,
|
|
6
|
+
import { ABSENT_TARGET, failure, historyAnswer, LOCKED_UNREADABLE, lockedRoom, handedOutcome, UNANSWERED, undeclared, UNCERTAIN, UNREADABLE, } from './outcome.js';
|
|
6
7
|
import { refuse } from './refusal.js';
|
|
7
8
|
function operationOf(input) {
|
|
8
9
|
const operation = input?.operation_id;
|
|
9
10
|
return typeof operation === 'string' ? operation : null;
|
|
10
11
|
}
|
|
11
12
|
export async function readHistory(runtime, locator, path, query = {}) {
|
|
12
|
-
const { store, socket,
|
|
13
|
+
const { store, socket, presence } = runtime;
|
|
13
14
|
const { session } = socket;
|
|
14
15
|
if (socket.closed() || session.now().refusal !== null)
|
|
15
16
|
return UNCERTAIN;
|
|
@@ -25,13 +26,7 @@ export async function readHistory(runtime, locator, path, query = {}) {
|
|
|
25
26
|
const { closed, authorization, refusal } = session.now();
|
|
26
27
|
if (closed || authorization === undefined || refusal !== null)
|
|
27
28
|
return UNCERTAIN;
|
|
28
|
-
const since =
|
|
29
|
-
const transfer = ['transfer', 'history', locator, path];
|
|
30
|
-
if (query.revision !== undefined)
|
|
31
|
-
transfer.push(query.revision);
|
|
32
|
-
if (query.pageToken !== undefined)
|
|
33
|
-
transfer.push(query.pageToken);
|
|
34
|
-
journal.record(transfer.join(' '));
|
|
29
|
+
const since = presence.losses();
|
|
35
30
|
try {
|
|
36
31
|
const result = await socket.history(authorization, {
|
|
37
32
|
locator,
|
|
@@ -39,20 +34,18 @@ export async function readHistory(runtime, locator, path, query = {}) {
|
|
|
39
34
|
...(query.revision === undefined ? {} : { revision: query.revision }),
|
|
40
35
|
...(query.pageToken === undefined ? {} : { pageToken: query.pageToken }),
|
|
41
36
|
});
|
|
42
|
-
|
|
43
|
-
if (store.fences.since(locator, since))
|
|
37
|
+
if (presence.lostSince(locator, since))
|
|
44
38
|
return failure({ kind: 'room-not-readable', locator });
|
|
45
39
|
if (result.kind === 'scoped-refusal') {
|
|
46
40
|
const room = await store.record(result.locator);
|
|
47
41
|
if (room !== undefined)
|
|
48
|
-
await scoped(runtime, result, room,
|
|
42
|
+
await scoped(runtime, result, room.locator, room.declaration);
|
|
49
43
|
}
|
|
50
44
|
if (result.kind === 'revoked-authorization')
|
|
51
45
|
await refuse(runtime, 'revoked-authorization');
|
|
52
46
|
return historyAnswer(result);
|
|
53
47
|
}
|
|
54
48
|
catch {
|
|
55
|
-
journal.record('outcome history transport-uncertainty');
|
|
56
49
|
return UNCERTAIN;
|
|
57
50
|
}
|
|
58
51
|
}
|
|
@@ -109,120 +102,181 @@ async function calledRooms(runtime, name, input) {
|
|
|
109
102
|
const named = input[member];
|
|
110
103
|
return (Array.isArray(named) ? named : [named]).filter((room) => typeof room === 'string');
|
|
111
104
|
}
|
|
112
|
-
export async function invokeAction(runtime, name, input, dispatching) {
|
|
113
|
-
const { store, socket,
|
|
105
|
+
export async function invokeAction(runtime, name, input, { dispatching, attempt } = {}) {
|
|
106
|
+
const { store, socket, retries } = runtime;
|
|
114
107
|
const { session } = socket;
|
|
115
108
|
await socket.ready;
|
|
116
|
-
if (socket.closed() || session.now().refusal !== null)
|
|
117
|
-
return
|
|
109
|
+
if (socket.closed() || session.now().refusal !== null) {
|
|
110
|
+
return handedOutcome(retries, attempt, UNANSWERED);
|
|
111
|
+
}
|
|
118
112
|
if ((await declaredAction(runtime, name)) === undefined)
|
|
119
113
|
return undeclared(name);
|
|
120
114
|
try {
|
|
121
115
|
await socket.authorize();
|
|
122
116
|
}
|
|
123
117
|
catch {
|
|
124
|
-
return
|
|
118
|
+
return handedOutcome(retries, attempt, UNANSWERED);
|
|
125
119
|
}
|
|
126
120
|
const { closed, authorization, refusal } = session.now();
|
|
127
|
-
if (closed || authorization === undefined || refusal !== null)
|
|
128
|
-
return
|
|
121
|
+
if (closed || authorization === undefined || refusal !== null) {
|
|
122
|
+
return handedOutcome(retries, attempt, UNANSWERED);
|
|
123
|
+
}
|
|
129
124
|
await dispatching?.();
|
|
130
|
-
journal.record(`transfer action ${name}`);
|
|
131
125
|
try {
|
|
132
126
|
const result = await socket.action(authorization, { name, input });
|
|
133
127
|
if (result.kind === 'scoped-refusal') {
|
|
134
128
|
const room = await store.record(result.locator);
|
|
135
129
|
if (room !== undefined)
|
|
136
|
-
await scoped(runtime, result, room,
|
|
130
|
+
await scoped(runtime, result, room.locator, room.declaration);
|
|
137
131
|
}
|
|
138
132
|
if (result.kind === 'revoked-authorization')
|
|
139
133
|
await refuse(runtime, 'revoked-authorization');
|
|
140
|
-
|
|
141
|
-
if (result.kind === 'rejected')
|
|
142
|
-
journal.record(`refusal rejected ${result.code}`);
|
|
143
|
-
return calledResult(result);
|
|
134
|
+
return handedOutcome(retries, attempt, result);
|
|
144
135
|
}
|
|
145
|
-
catch {
|
|
146
|
-
|
|
147
|
-
return UNCERTAIN;
|
|
136
|
+
catch (error) {
|
|
137
|
+
return handedOutcome(retries, attempt, { kind: 'transport-uncertainty', failure: error });
|
|
148
138
|
}
|
|
149
139
|
}
|
|
150
140
|
export async function readConversationHistory(runtime, request) {
|
|
151
|
-
const { socket,
|
|
141
|
+
const { socket, retries } = runtime;
|
|
142
|
+
const caught = { step: 'conversations', instance: CATCHING_UP };
|
|
152
143
|
await socket.ready;
|
|
153
144
|
const stream = socket.conversations();
|
|
154
145
|
if (socket.closed() || socket.session.now().refusal !== null || stream?.history === undefined) {
|
|
155
|
-
return
|
|
146
|
+
return handedOutcome(retries, caught, UNANSWERED);
|
|
156
147
|
}
|
|
157
|
-
journal.record('transfer conversation history');
|
|
158
148
|
try {
|
|
159
149
|
const result = await stream.history(request);
|
|
160
150
|
if (result.kind === 'revoked-authorization')
|
|
161
151
|
await refuse(runtime, 'revoked-authorization');
|
|
162
|
-
|
|
163
|
-
return calledResult(result);
|
|
152
|
+
return handedOutcome(retries, caught, result);
|
|
164
153
|
}
|
|
165
|
-
catch {
|
|
166
|
-
|
|
167
|
-
return UNCERTAIN;
|
|
154
|
+
catch (error) {
|
|
155
|
+
return handedOutcome(retries, caught, { kind: 'transport-uncertainty', failure: error });
|
|
168
156
|
}
|
|
169
157
|
}
|
|
170
158
|
function unsettled(result) {
|
|
171
|
-
|
|
159
|
+
if (result.kind === 'action')
|
|
160
|
+
return false;
|
|
161
|
+
return result.retryable && (result.kind !== 'rejected' || result.reset === undefined);
|
|
172
162
|
}
|
|
173
|
-
|
|
174
|
-
|
|
163
|
+
function numberedCall(runtime, name, input, operation, dispatching) {
|
|
164
|
+
return invokeAction(runtime, name, input, {
|
|
165
|
+
dispatching,
|
|
166
|
+
attempt: { step: 'sending', instance: `action ${operation}` },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function keptSender(runtime, name, input, operation, resent = false) {
|
|
170
|
+
const { store, socket } = runtime;
|
|
175
171
|
const { lanes } = socket;
|
|
172
|
+
const dispatching = async () => (await store.open()).keepCall({ operation, name, input });
|
|
173
|
+
let waiting = [];
|
|
174
|
+
let last = UNCERTAIN;
|
|
175
|
+
let lost = resent;
|
|
176
|
+
const tell = (result) => {
|
|
177
|
+
last = result;
|
|
178
|
+
const told = waiting;
|
|
179
|
+
waiting = [];
|
|
180
|
+
for (const answer of told)
|
|
181
|
+
answer(result);
|
|
182
|
+
};
|
|
183
|
+
const sender = {
|
|
184
|
+
next: () => new Promise((answer) => waiting.push(answer)),
|
|
185
|
+
async send() {
|
|
186
|
+
let result;
|
|
187
|
+
try {
|
|
188
|
+
result = await numberedCall(runtime, name, input, operation, dispatching);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
tell(last);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
if (unsettled(result))
|
|
195
|
+
lost = true;
|
|
196
|
+
else {
|
|
197
|
+
await (await store.open()).dropCall(operation);
|
|
198
|
+
lanes.settle(operation, lost);
|
|
199
|
+
}
|
|
200
|
+
tell(result);
|
|
201
|
+
return result;
|
|
202
|
+
},
|
|
203
|
+
release() {
|
|
204
|
+
lanes.sent(operation, sender);
|
|
205
|
+
tell(last);
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
lanes.sending(operation, sender);
|
|
209
|
+
return sender;
|
|
210
|
+
}
|
|
211
|
+
async function recoveredAction(runtime, name, input, attempt) {
|
|
212
|
+
const { socket, recovery } = runtime;
|
|
176
213
|
const operation = operationOf(input);
|
|
177
214
|
if (operation === null)
|
|
178
|
-
return invokeAction(runtime, name, input);
|
|
179
|
-
const
|
|
180
|
-
|
|
215
|
+
return invokeAction(runtime, name, input, { attempt });
|
|
216
|
+
const held = socket.lanes.sender(operation);
|
|
217
|
+
if (held !== undefined)
|
|
218
|
+
return held.next();
|
|
219
|
+
const sender = keptSender(runtime, name, input, operation);
|
|
220
|
+
let first;
|
|
181
221
|
try {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (!socket.isOpen())
|
|
188
|
-
return 'again';
|
|
189
|
-
result = await invokeAction(runtime, name, input, kept);
|
|
190
|
-
return unsettled(result) ? 'again' : 'done';
|
|
191
|
-
}, { again: true });
|
|
192
|
-
}
|
|
193
|
-
if (!unsettled(result))
|
|
194
|
-
await (await store.open()).dropCall(operation);
|
|
195
|
-
return result;
|
|
222
|
+
first = await sender.send();
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
sender.release();
|
|
226
|
+
throw error;
|
|
196
227
|
}
|
|
197
|
-
|
|
198
|
-
|
|
228
|
+
if (!unsettled(first)) {
|
|
229
|
+
sender.release();
|
|
230
|
+
return first;
|
|
199
231
|
}
|
|
232
|
+
void recovery
|
|
233
|
+
.attempt(`action ${operation}`, async () => {
|
|
234
|
+
if (socket.closed() || socket.session.now().refusal !== null)
|
|
235
|
+
return 'done';
|
|
236
|
+
if (!socket.isOpen())
|
|
237
|
+
return 'again';
|
|
238
|
+
return unsettled(await sender.send()) ? 'again' : 'done';
|
|
239
|
+
}, { again: true })
|
|
240
|
+
.finally(() => sender.release());
|
|
241
|
+
return first;
|
|
200
242
|
}
|
|
201
|
-
export async function called(runtime, name, input) {
|
|
243
|
+
export async function called(runtime, name, input, attempt) {
|
|
202
244
|
await runtime.socket.ready;
|
|
203
245
|
const lockedNow = await lockedRooms(runtime);
|
|
204
246
|
const room = (await calledRooms(runtime, name, input)).find((one) => lockedNow.includes(one));
|
|
205
|
-
return room === undefined ? recoveredAction(runtime, name, input) : lockedRoom(room);
|
|
247
|
+
return room === undefined ? recoveredAction(runtime, name, input, attempt) : lockedRoom(room);
|
|
206
248
|
}
|
|
207
|
-
export async function
|
|
249
|
+
export async function answeredCall(runtime, operation) {
|
|
208
250
|
const { store, socket } = runtime;
|
|
209
251
|
const { lanes } = socket;
|
|
252
|
+
const held = () => lanes.sender(operation) !== undefined || lanes.unclaimed(operation);
|
|
253
|
+
if (!held()) {
|
|
254
|
+
const calls = await (await store.open()).calls();
|
|
255
|
+
const kept = calls.some((one) => one.operation === operation) ||
|
|
256
|
+
(await holdsSubmission(runtime.conversations, operation));
|
|
257
|
+
if (!held() && !kept)
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
await lanes.settled(operation);
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
export async function resendCalls(runtime, signal) {
|
|
264
|
+
const { store, socket } = runtime;
|
|
210
265
|
if (!socket.isOpen() || socket.closed() || socket.stopping())
|
|
211
266
|
return 'done';
|
|
212
267
|
const local = await store.open();
|
|
213
268
|
for (const held of await local.calls()) {
|
|
214
|
-
if (lanes.
|
|
269
|
+
if (socket.lanes.sender(held.operation) !== undefined)
|
|
215
270
|
continue;
|
|
216
271
|
if (socket.closed() || signal.aborted)
|
|
217
272
|
return 'done';
|
|
218
|
-
|
|
273
|
+
const sender = keptSender(runtime, held.name, held.input, held.operation, true);
|
|
219
274
|
try {
|
|
220
|
-
if (unsettled(await
|
|
275
|
+
if (unsettled(await sender.send()))
|
|
221
276
|
return 'again';
|
|
222
|
-
await local.dropCall(held.operation);
|
|
223
277
|
}
|
|
224
278
|
finally {
|
|
225
|
-
|
|
279
|
+
sender.release();
|
|
226
280
|
}
|
|
227
281
|
}
|
|
228
282
|
return 'done';
|
|
@@ -232,7 +286,7 @@ async function resendPass({ socket, conversations }, signal) {
|
|
|
232
286
|
return 'done';
|
|
233
287
|
const reading = { complete: true, reachable: true };
|
|
234
288
|
try {
|
|
235
|
-
await conversations
|
|
289
|
+
await resendConversations(conversations, reading);
|
|
236
290
|
}
|
|
237
291
|
catch {
|
|
238
292
|
reading.reachable = false;
|