@agentshouse/mdruntime 0.1.0-cebcd51f70ed1 → 0.1.0-cedb03eaa48b6
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/AGENTS.md +283 -222
- package/README.md +20 -10
- package/dist/adapter.d.ts +95 -20
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +15 -2
- package/dist/attempt.d.ts +16 -0
- package/dist/attempt.d.ts.map +1 -0
- package/dist/attempt.js +70 -0
- package/dist/binary.d.ts +23 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +8 -0
- package/dist/bootstrap.d.ts +18 -5
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +113 -37
- package/dist/change-set.d.ts +2 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +49 -16
- package/dist/change.d.ts +15 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +26 -1
- package/dist/chat/acts.d.ts +33 -0
- package/dist/chat/acts.d.ts.map +1 -0
- package/dist/chat/acts.js +36 -0
- package/dist/chat/context.d.ts +3 -0
- package/dist/chat/context.d.ts.map +1 -0
- package/dist/chat/context.js +10 -0
- package/dist/chat/earlier.d.ts +10 -0
- package/dist/chat/earlier.d.ts.map +1 -0
- package/dist/chat/earlier.js +54 -0
- package/dist/chat/input.d.ts +9 -0
- package/dist/chat/input.d.ts.map +1 -0
- package/dist/chat/input.js +99 -0
- package/dist/chat/kit.d.ts +61 -0
- package/dist/chat/kit.d.ts.map +1 -0
- package/dist/chat/kit.js +123 -0
- package/dist/chat/lasting.d.ts +6 -0
- package/dist/chat/lasting.d.ts.map +1 -0
- package/dist/chat/lasting.js +19 -0
- package/dist/chat/list.d.ts +27 -0
- package/dist/chat/list.d.ts.map +1 -0
- package/dist/chat/list.js +99 -0
- package/dist/chat/markdown.d.ts +20 -0
- package/dist/chat/markdown.d.ts.map +1 -0
- package/dist/chat/markdown.js +188 -0
- package/dist/chat/message.d.ts +6 -0
- package/dist/chat/message.d.ts.map +1 -0
- package/dist/chat/message.js +192 -0
- package/dist/chat/messages.d.ts +22 -0
- package/dist/chat/messages.d.ts.map +1 -0
- package/dist/chat/messages.js +155 -0
- package/dist/chat/name.d.ts +6 -0
- package/dist/chat/name.d.ts.map +1 -0
- package/dist/chat/name.js +37 -0
- package/dist/chat/opened.d.ts +11 -0
- package/dist/chat/opened.d.ts.map +1 -0
- package/dist/chat/opened.js +17 -0
- package/dist/chat/overlay.d.ts +31 -0
- package/dist/chat/overlay.d.ts.map +1 -0
- package/dist/chat/overlay.js +97 -0
- package/dist/chat/parts.d.ts +57 -0
- package/dist/chat/parts.d.ts.map +1 -0
- package/dist/chat/parts.js +119 -0
- package/dist/chat/process.d.ts +20 -0
- package/dist/chat/process.d.ts.map +1 -0
- package/dist/chat/process.js +32 -0
- package/dist/chat/provider.d.ts +63 -0
- package/dist/chat/provider.d.ts.map +1 -0
- package/dist/chat/provider.js +628 -0
- package/dist/chat/question.d.ts +9 -0
- package/dist/chat/question.d.ts.map +1 -0
- package/dist/chat/question.js +69 -0
- package/dist/chat/questions.d.ts +31 -0
- package/dist/chat/questions.d.ts.map +1 -0
- package/dist/chat/questions.js +111 -0
- package/dist/chat/read.d.ts +5 -0
- package/dist/chat/read.d.ts.map +1 -0
- package/dist/chat/read.js +13 -0
- package/dist/chat/ready.d.ts +34 -0
- package/dist/chat/ready.d.ts.map +1 -0
- package/dist/chat/ready.js +91 -0
- package/dist/chat/style.d.ts +4 -0
- package/dist/chat/style.d.ts.map +1 -0
- package/dist/chat/style.js +302 -0
- package/dist/chat.d.ts +14 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +8 -0
- package/dist/client.d.ts +30 -13
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +79 -16
- package/dist/collection.d.ts +21 -12
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +301 -23
- package/dist/connection.d.ts +50 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1936 -415
- package/dist/conversation.d.ts +31 -10
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +521 -170
- package/dist/durability.d.ts +7 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +17 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +157 -0
- package/dist/expectation.d.ts +21 -0
- package/dist/expectation.d.ts.map +1 -0
- package/dist/expectation.js +70 -0
- package/dist/failure.d.ts +13 -0
- package/dist/failure.d.ts.map +1 -0
- package/dist/failure.js +19 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/host.d.ts +15 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +102 -19
- package/dist/identity.d.ts +5 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +19 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/memory.d.ts +11 -4
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +91 -24
- package/dist/model.d.ts +14 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +12 -1
- package/dist/observation.d.ts +7 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +29 -12
- package/dist/open.d.ts +2 -0
- package/dist/open.d.ts.map +1 -0
- package/dist/open.js +1 -0
- package/dist/outcome.d.ts +38 -3
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +45 -1
- package/dist/overlay.d.ts +16 -3
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +118 -77
- package/dist/query.d.ts +60 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +41 -38
- package/dist/reach.d.ts +8 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +73 -24
- package/dist/react.d.ts +31 -20
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +13 -21
- package/dist/read-side.d.ts +16 -7
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +493 -102
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -0
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/recovery.d.ts +25 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +197 -0
- package/dist/refresh.d.ts +13 -3
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +49 -38
- package/dist/replica.d.ts +13 -6
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +143 -70
- package/dist/room-draft.d.ts +38 -9
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +134 -25
- package/dist/rows.d.ts +10 -13
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +19 -14
- package/dist/save.d.ts +32 -1
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +390 -45
- package/dist/search.d.ts +52 -8
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +192 -47
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +11 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +368 -0
- package/dist/status.d.ts +6 -2
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +0 -8
- package/dist/store.d.ts +89 -18
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +573 -200
- package/dist/turn.d.ts +7 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +51 -0
- package/dist/windows.d.ts +26 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +93 -0
- package/dist/wire.d.ts +157 -33
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +65 -31
- package/package.json +26 -14
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
package/dist/client.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { observed } from './observation.js';
|
|
2
|
+
import { runtimeError } from './failure.js';
|
|
2
3
|
import { answer, AUTHORIZATION_ENDED, PORT_CLOSED, } from './wire.js';
|
|
4
|
+
// React renders an arrived value in a later task and opens what that render observes as it commits, so this many frames opening nothing mean the page drew what it observes.
|
|
5
|
+
const SETTLED_FRAMES = 2;
|
|
6
|
+
function refused(refusal) {
|
|
7
|
+
return runtimeError(refusal.code, refusal.code, refusal.retryable);
|
|
8
|
+
}
|
|
3
9
|
export function connectMdRuntime(port) {
|
|
4
10
|
let sequence = 0;
|
|
5
11
|
let refusal = null;
|
|
@@ -7,6 +13,8 @@ export function connectMdRuntime(port) {
|
|
|
7
13
|
const calls = new Map();
|
|
8
14
|
const opening = new Map();
|
|
9
15
|
const observations = new Map();
|
|
16
|
+
let drawing = null;
|
|
17
|
+
let settling = null;
|
|
10
18
|
const send = (message) => {
|
|
11
19
|
port.postMessage(message);
|
|
12
20
|
};
|
|
@@ -25,7 +33,7 @@ export function connectMdRuntime(port) {
|
|
|
25
33
|
if (topic === 'connection-refusal')
|
|
26
34
|
handle.receive(reported);
|
|
27
35
|
}
|
|
28
|
-
const failure =
|
|
36
|
+
const failure = refused(reported);
|
|
29
37
|
for (const [id, waiting] of opening) {
|
|
30
38
|
if (waiting.topic === 'connection-refusal')
|
|
31
39
|
waiting.settle(begin(id, waiting.topic, reported));
|
|
@@ -36,12 +44,12 @@ export function connectMdRuntime(port) {
|
|
|
36
44
|
for (const waiting of calls.values())
|
|
37
45
|
waiting.fail(failure);
|
|
38
46
|
calls.clear();
|
|
47
|
+
drawing?.();
|
|
39
48
|
}
|
|
40
|
-
function end(
|
|
49
|
+
function end(failure) {
|
|
41
50
|
if (ended !== null)
|
|
42
51
|
return;
|
|
43
|
-
ended =
|
|
44
|
-
const failure = new Error(reason);
|
|
52
|
+
ended = failure;
|
|
45
53
|
for (const waiting of opening.values())
|
|
46
54
|
waiting.fail(failure);
|
|
47
55
|
opening.clear();
|
|
@@ -51,6 +59,7 @@ export function connectMdRuntime(port) {
|
|
|
51
59
|
for (const { handle } of observations.values())
|
|
52
60
|
handle.end();
|
|
53
61
|
observations.clear();
|
|
62
|
+
drawing?.();
|
|
54
63
|
}
|
|
55
64
|
port.addEventListener('message', (event) => {
|
|
56
65
|
const message = answer(event.data);
|
|
@@ -61,7 +70,11 @@ export function connectMdRuntime(port) {
|
|
|
61
70
|
return;
|
|
62
71
|
}
|
|
63
72
|
if (message.kind === 'ended') {
|
|
64
|
-
|
|
73
|
+
for (const { topic, handle } of observations.values()) {
|
|
74
|
+
if (topic === 'member')
|
|
75
|
+
handle.receive(null);
|
|
76
|
+
}
|
|
77
|
+
end(runtimeError('authorization-ended', AUTHORIZATION_ENDED));
|
|
65
78
|
return;
|
|
66
79
|
}
|
|
67
80
|
if (message.kind === 'event') {
|
|
@@ -71,31 +84,34 @@ export function connectMdRuntime(port) {
|
|
|
71
84
|
const waiting = opening.get(message.id);
|
|
72
85
|
if (waiting !== undefined) {
|
|
73
86
|
opening.delete(message.id);
|
|
74
|
-
if (message.kind === 'failure')
|
|
75
|
-
waiting.fail(
|
|
87
|
+
if (message.kind === 'failure') {
|
|
88
|
+
waiting.fail(runtimeError(message.code, message.message, message.retryable));
|
|
89
|
+
}
|
|
76
90
|
else
|
|
77
91
|
waiting.settle(begin(message.id, waiting.topic, message.value));
|
|
92
|
+
drawing?.();
|
|
78
93
|
return;
|
|
79
94
|
}
|
|
80
95
|
const called = calls.get(message.id);
|
|
81
96
|
if (called === undefined)
|
|
82
97
|
return;
|
|
83
98
|
calls.delete(message.id);
|
|
84
|
-
if (message.kind === 'failure')
|
|
85
|
-
called.fail(
|
|
99
|
+
if (message.kind === 'failure') {
|
|
100
|
+
called.fail(runtimeError(message.code, message.message, message.retryable));
|
|
101
|
+
}
|
|
86
102
|
else
|
|
87
103
|
called.settle(message.value);
|
|
88
104
|
});
|
|
89
105
|
port.addEventListener('close', () => {
|
|
90
|
-
end(PORT_CLOSED);
|
|
106
|
+
end(runtimeError('port-closed', PORT_CLOSED));
|
|
91
107
|
});
|
|
92
108
|
port.start();
|
|
93
109
|
send({ kind: 'hello' });
|
|
94
110
|
function ask(member, input) {
|
|
95
111
|
if (ended !== null)
|
|
96
|
-
return Promise.reject(
|
|
112
|
+
return Promise.reject(ended);
|
|
97
113
|
if (refusal !== null)
|
|
98
|
-
return Promise.reject(
|
|
114
|
+
return Promise.reject(refused(refusal));
|
|
99
115
|
const id = (sequence += 1);
|
|
100
116
|
return new Promise((settle, fail) => {
|
|
101
117
|
calls.set(id, { settle: settle, fail });
|
|
@@ -104,17 +120,47 @@ export function connectMdRuntime(port) {
|
|
|
104
120
|
}
|
|
105
121
|
function watch(topic, input) {
|
|
106
122
|
if (ended !== null)
|
|
107
|
-
return Promise.reject(
|
|
123
|
+
return Promise.reject(ended);
|
|
108
124
|
const id = (sequence += 1);
|
|
109
125
|
if (refusal !== null) {
|
|
110
126
|
return topic === 'connection-refusal'
|
|
111
127
|
? Promise.resolve(begin(id, topic, refusal))
|
|
112
|
-
: Promise.reject(
|
|
128
|
+
: Promise.reject(refused(refusal));
|
|
113
129
|
}
|
|
114
130
|
return new Promise((settle, fail) => {
|
|
115
131
|
opening.set(id, { topic, settle, fail });
|
|
116
132
|
send({ kind: 'observe', id, topic, input });
|
|
133
|
+
drawing?.();
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function settled() {
|
|
137
|
+
if (settling !== null)
|
|
138
|
+
return settling;
|
|
139
|
+
settling = new Promise((resolve) => {
|
|
140
|
+
let moved = 0;
|
|
141
|
+
const check = () => {
|
|
142
|
+
moved += 1;
|
|
143
|
+
if (opening.size > 0)
|
|
144
|
+
return;
|
|
145
|
+
const at = moved;
|
|
146
|
+
const waited = (frames) => {
|
|
147
|
+
requestAnimationFrame(() => {
|
|
148
|
+
if (frames < SETTLED_FRAMES) {
|
|
149
|
+
waited(frames + 1);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (moved !== at || opening.size > 0)
|
|
153
|
+
return;
|
|
154
|
+
drawing = null;
|
|
155
|
+
resolve();
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
waited(1);
|
|
159
|
+
};
|
|
160
|
+
drawing = check;
|
|
161
|
+
check();
|
|
117
162
|
});
|
|
163
|
+
return settling;
|
|
118
164
|
}
|
|
119
165
|
return {
|
|
120
166
|
rooms: () => ask('rooms', []),
|
|
@@ -128,15 +174,17 @@ export function connectMdRuntime(port) {
|
|
|
128
174
|
discard: (room, path, revision) => ask('roomDraft.discard', [room, path, revision]),
|
|
129
175
|
},
|
|
130
176
|
save: (room, roomDrafts) => ask('save', [room, roomDrafts]),
|
|
177
|
+
saveParts: (room, parts) => ask('saveParts', [room, parts]),
|
|
131
178
|
presentation: {
|
|
132
179
|
read: () => ask('presentation.read', []),
|
|
133
180
|
write: (value) => ask('presentation.write', [value]),
|
|
181
|
+
edit: (members) => ask('presentation.edit', [members]),
|
|
134
182
|
},
|
|
135
183
|
conversation: {
|
|
136
184
|
list: () => ask('conversation.list', []),
|
|
137
185
|
read: (conversation, options) => ask('conversation.read', [conversation, options]),
|
|
138
186
|
create: (input) => ask('conversation.create', [input]),
|
|
139
|
-
send: (conversation) => ask('conversation.send', [conversation]),
|
|
187
|
+
send: (conversation, operation, draft) => ask('conversation.send', [conversation, operation, draft]),
|
|
140
188
|
answer: (conversation, answer) => ask('conversation.answer', [conversation, answer]),
|
|
141
189
|
interrupt: (conversation) => ask('conversation.interrupt', [conversation]),
|
|
142
190
|
kill: (conversation) => ask('conversation.kill', [conversation]),
|
|
@@ -144,15 +192,30 @@ export function connectMdRuntime(port) {
|
|
|
144
192
|
delete: (conversation) => ask('conversation.delete', [conversation]),
|
|
145
193
|
},
|
|
146
194
|
chatDraft: {
|
|
147
|
-
write: (conversation, draft) => ask('chatDraft.write', [conversation, draft]),
|
|
195
|
+
write: (conversation, draft, revision) => ask('chatDraft.write', [conversation, draft, revision]),
|
|
196
|
+
prepend: (conversation, draft) => ask('chatDraft.prepend', [conversation, draft]),
|
|
148
197
|
discard: (conversation) => ask('chatDraft.discard', [conversation]),
|
|
149
198
|
},
|
|
150
199
|
history: (locator, path, query) => ask('history', [locator, path, query]),
|
|
200
|
+
binaryFile: {
|
|
201
|
+
read: (room, path, revision) => ask('binaryFile.read', [room, path, revision]),
|
|
202
|
+
link: (room, path, revision) => ask('binaryFile.link', [room, path, revision]),
|
|
203
|
+
readReference: (reference) => ask('binaryFile.readReference', [reference]),
|
|
204
|
+
},
|
|
151
205
|
call: (name, input) => ask('call', [name, input]),
|
|
152
206
|
reached: (locator, roomVersion, path) => ask('reached', [locator, roomVersion, path]),
|
|
153
207
|
log: () => ask('log', []),
|
|
154
208
|
persistence: () => ask('persistence', []),
|
|
209
|
+
retry: () => ask('retry', []),
|
|
155
210
|
observe: ((topic, ...input) => watch(topic, input)),
|
|
156
211
|
reauthorize: () => ask('reauthorize', []),
|
|
212
|
+
settled,
|
|
157
213
|
};
|
|
158
214
|
}
|
|
215
|
+
const turns = new WeakMap();
|
|
216
|
+
export function inTurn(client, work) {
|
|
217
|
+
const turn = (turns.get(client) ?? Promise.resolve()).then(work);
|
|
218
|
+
turns.set(client, turn.then(() => undefined, () => undefined));
|
|
219
|
+
return turn;
|
|
220
|
+
}
|
|
221
|
+
export { unanswered } from './wire.js';
|
package/dist/collection.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { type Document, type Validation } from '@agentshouse/mdmodel';
|
|
2
|
-
import type
|
|
1
|
+
import { type Document, type Frontmatter, type Validation } from '@agentshouse/mdmodel';
|
|
2
|
+
import { type ModelState } from './model.js';
|
|
3
3
|
import type { MdModelIdentity } from './adapter.js';
|
|
4
|
+
import { type Paths } from './shared.js';
|
|
4
5
|
import type { Refused } from './transfer.js';
|
|
6
|
+
import { type Later } from './turn.js';
|
|
5
7
|
export declare const MD_MODEL: MdModelIdentity;
|
|
6
8
|
export type Collection = {
|
|
7
|
-
|
|
9
|
+
text: Readonly<Record<string, string>>;
|
|
8
10
|
composition: Composition;
|
|
11
|
+
document(path: string): Document | undefined;
|
|
9
12
|
};
|
|
10
13
|
export type Composition = {
|
|
11
14
|
model: ModelState;
|
|
@@ -15,16 +18,22 @@ export type Composition = {
|
|
|
15
18
|
} | null;
|
|
16
19
|
};
|
|
17
20
|
export declare function governing(composition: Composition, path: string): ModelState;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export declare function parseCollection(text: Readonly<Record<string, string>>, composition: Composition, previous?: Previous): Collection;
|
|
23
|
-
export declare function readCollection(text: Readonly<Record<string, string>>, composition: Composition, previous?: Previous): {
|
|
24
|
-
kind: 'read';
|
|
25
|
-
collection: Collection;
|
|
26
|
-
} | Refused;
|
|
21
|
+
export declare function collectionOf(text: Readonly<Record<string, string>>, composition: Composition, previous?: Collection): Collection;
|
|
22
|
+
export declare function passingFrontmatter(collection: Collection, path: string): Frontmatter | undefined;
|
|
23
|
+
export declare function documentsOf(collection: Collection): Generator<readonly [string, Document]>;
|
|
24
|
+
export declare function unreadable(text: Readonly<Record<string, string>>, previous?: Readonly<Record<string, string>>): Refused | null;
|
|
27
25
|
export declare function validRoot(root: unknown): root is string;
|
|
28
26
|
export declare function validateCollection(text: Readonly<Record<string, string>>, binaryTargets: readonly string[], composition: Composition): Validation;
|
|
27
|
+
type Held = {
|
|
28
|
+
text: Paths<string>;
|
|
29
|
+
binaries: Paths<unknown>;
|
|
30
|
+
};
|
|
31
|
+
export declare function indexReferrers(held: Held, composition: Composition): Later<void>;
|
|
32
|
+
export declare function referencesIndexed(held: Held, composition: Composition): boolean;
|
|
33
|
+
export declare function referring(held: Held, composition: Composition, targets: Iterable<string>): ReadonlySet<string> | null;
|
|
34
|
+
export declare function available(composition: Composition): boolean;
|
|
35
|
+
export declare function changedCleanly(next: Held, previous: Held & {
|
|
36
|
+
composition: Composition;
|
|
37
|
+
}, composition: Composition): boolean;
|
|
29
38
|
export {};
|
|
30
39
|
//# sourceMappingURL=collection.d.ts.map
|
package/dist/collection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
|
package/dist/collection.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { parse, validate, VERSION, } from '@agentshouse/mdmodel';
|
|
1
|
+
import { checkDocument, parseFrontmatter, references, sectionReferences, target, parse, resolves, validate, VERSION, } from '@agentshouse/mdmodel';
|
|
2
2
|
import { beneath, normalize } from './paths.js';
|
|
3
|
+
import { sameTyping } from './model.js';
|
|
4
|
+
import { differing, patched, shared, sizeOf } from './shared.js';
|
|
5
|
+
import { after, inUnits, ROW_WEIGHT } from './turn.js';
|
|
3
6
|
export const MD_MODEL = { identity: '@agentshouse/mdmodel', version: VERSION };
|
|
4
7
|
const NO_TYPES = { types: {} };
|
|
5
8
|
function selected(composition, path) {
|
|
@@ -11,30 +14,81 @@ export function governing(composition, path) {
|
|
|
11
14
|
? composition.selection.model
|
|
12
15
|
: composition.model;
|
|
13
16
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
const parsedIn = new WeakMap();
|
|
18
|
+
function carried(previous, text) {
|
|
19
|
+
const held = parsedIn.get(previous);
|
|
20
|
+
if (held === undefined)
|
|
21
|
+
return shared({});
|
|
22
|
+
const kept = patched(held.base, held.added);
|
|
23
|
+
held.base = kept;
|
|
24
|
+
held.added = new Map();
|
|
25
|
+
return patched(kept, [], differing(previous.text, text));
|
|
26
|
+
}
|
|
27
|
+
function cachedIn(collection, path) {
|
|
28
|
+
const held = parsedIn.get(collection);
|
|
29
|
+
if (held === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (held.added.has(path))
|
|
32
|
+
return held.added.get(path);
|
|
33
|
+
return Object.hasOwn(held.base, path) ? held.base[path] : undefined;
|
|
34
|
+
}
|
|
35
|
+
export function collectionOf(text, composition, previous) {
|
|
36
|
+
const parsed = {
|
|
37
|
+
base: previous === undefined ? shared({}) : carried(previous, text),
|
|
38
|
+
added: new Map(),
|
|
39
|
+
};
|
|
40
|
+
const collection = {
|
|
41
|
+
text,
|
|
42
|
+
composition,
|
|
43
|
+
document(path) {
|
|
44
|
+
const held = cachedIn(collection, path);
|
|
45
|
+
if (held !== undefined)
|
|
46
|
+
return held ?? undefined;
|
|
47
|
+
const content = text[path];
|
|
48
|
+
if (content === undefined)
|
|
49
|
+
return undefined;
|
|
50
|
+
const read = parse(content, path);
|
|
51
|
+
parsed.added.set(path, read.ok ? read.document : null);
|
|
52
|
+
return read.ok ? read.document : undefined;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
parsedIn.set(collection, parsed);
|
|
56
|
+
return collection;
|
|
57
|
+
}
|
|
58
|
+
export function passingFrontmatter(collection, path) {
|
|
59
|
+
const held = cachedIn(collection, path);
|
|
60
|
+
if (held !== undefined)
|
|
61
|
+
return held ?? undefined;
|
|
62
|
+
const content = collection.text[path];
|
|
63
|
+
if (content === undefined)
|
|
64
|
+
return undefined;
|
|
65
|
+
const read = parseFrontmatter(content, path);
|
|
66
|
+
return read.ok ? read.frontmatter : undefined;
|
|
67
|
+
}
|
|
68
|
+
export function* documentsOf(collection) {
|
|
69
|
+
for (const path of Object.keys(collection.text).sort()) {
|
|
70
|
+
const held = cachedIn(collection, path);
|
|
71
|
+
if (held === null)
|
|
72
|
+
continue;
|
|
73
|
+
if (held !== undefined) {
|
|
74
|
+
yield [path, held];
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const read = parse(collection.text[path], path);
|
|
78
|
+
if (read.ok)
|
|
79
|
+
yield [path, read.document];
|
|
26
80
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
81
|
+
}
|
|
82
|
+
export function unreadable(text, previous) {
|
|
83
|
+
const paths = previous === undefined
|
|
84
|
+
? Object.keys(text)
|
|
85
|
+
: [...differing(previous, text)].filter((path) => text[path] !== undefined);
|
|
86
|
+
for (const path of paths.sort()) {
|
|
87
|
+
const read = parse(text[path], path);
|
|
88
|
+
if (!read.ok)
|
|
89
|
+
return { kind: 'refused', refusal: read.refusal };
|
|
36
90
|
}
|
|
37
|
-
return
|
|
91
|
+
return null;
|
|
38
92
|
}
|
|
39
93
|
export function validRoot(root) {
|
|
40
94
|
return typeof root === 'string' && normalize(root) === root;
|
|
@@ -70,3 +124,227 @@ export function validateCollection(text, binaryTargets, composition) {
|
|
|
70
124
|
return verdicts[0];
|
|
71
125
|
return refusals.find((refusal) => refusal.rule !== 'model-unavailable') ?? refusals[0];
|
|
72
126
|
}
|
|
127
|
+
const NO_REFERRERS = shared({});
|
|
128
|
+
const referrersOf = new WeakMap();
|
|
129
|
+
function typing(left, right) {
|
|
130
|
+
return (sameTyping(left.model, right.model) &&
|
|
131
|
+
(left.selection === null || right.selection === null
|
|
132
|
+
? left.selection === right.selection
|
|
133
|
+
: sameTyping(left.selection.model, right.selection.model)) &&
|
|
134
|
+
JSON.stringify(left.selection?.roots ?? null) === JSON.stringify(right.selection?.roots ?? null));
|
|
135
|
+
}
|
|
136
|
+
function declared(content) {
|
|
137
|
+
if (content === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
const read = parseFrontmatter(content);
|
|
140
|
+
return read.ok ? (read.frontmatter.type ?? 'any') : undefined;
|
|
141
|
+
}
|
|
142
|
+
function typedIn(content) {
|
|
143
|
+
const type = declared(content);
|
|
144
|
+
return type !== undefined && type !== 'any';
|
|
145
|
+
}
|
|
146
|
+
function modelOf(composition, path) {
|
|
147
|
+
const model = governing(composition, path);
|
|
148
|
+
return model.status === 'unavailable' ? null : { types: model.types };
|
|
149
|
+
}
|
|
150
|
+
function checked(path, content, composition) {
|
|
151
|
+
return checkDocument(path, content, modelOf(composition, path) ?? NO_TYPES);
|
|
152
|
+
}
|
|
153
|
+
function targetsOf(check) {
|
|
154
|
+
if (!check.ok)
|
|
155
|
+
return [];
|
|
156
|
+
return [...new Set(check.references.flatMap(({ target }) => (target === null ? [] : [target])))];
|
|
157
|
+
}
|
|
158
|
+
function referencedBy(path, content, composition) {
|
|
159
|
+
const model = modelOf(composition, path);
|
|
160
|
+
if (model === null)
|
|
161
|
+
return [];
|
|
162
|
+
const read = parseFrontmatter(content, path);
|
|
163
|
+
const type = read.ok ? read.frontmatter.type : undefined;
|
|
164
|
+
if (!read.ok || type === undefined || !Object.hasOwn(model.types, type))
|
|
165
|
+
return [];
|
|
166
|
+
const definition = model.types[type];
|
|
167
|
+
return [
|
|
168
|
+
...new Set([
|
|
169
|
+
...references(read.frontmatter, definition).flatMap(({ value }) => {
|
|
170
|
+
const found = target(path, value);
|
|
171
|
+
return found === null ? [] : [found];
|
|
172
|
+
}),
|
|
173
|
+
...sectionReferences(path, content, definition).flatMap(({ target }) => target === null ? [] : [target]),
|
|
174
|
+
]),
|
|
175
|
+
];
|
|
176
|
+
}
|
|
177
|
+
function referrersOfTarget(index, target) {
|
|
178
|
+
return Object.hasOwn(index.referrers, target) ? index.referrers[target] : NO_REFERRERS;
|
|
179
|
+
}
|
|
180
|
+
function reindexed(index, changed) {
|
|
181
|
+
const referrers = new Map();
|
|
182
|
+
const held = (target) => referrers.get(target) ?? referrersOfTarget(index, target);
|
|
183
|
+
for (const [path, found] of changed) {
|
|
184
|
+
const before = Object.hasOwn(index.targets, path) ? index.targets[path] : [];
|
|
185
|
+
for (const target of before) {
|
|
186
|
+
if (!found.includes(target))
|
|
187
|
+
referrers.set(target, patched(held(target), [], [path]));
|
|
188
|
+
}
|
|
189
|
+
for (const target of found) {
|
|
190
|
+
if (!before.includes(target))
|
|
191
|
+
referrers.set(target, patched(held(target), [[path, true]]));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
composition: index.composition,
|
|
196
|
+
targets: patched(index.targets, [...changed].filter(([, found]) => found.length > 0), [...changed].filter(([, found]) => found.length === 0).map(([path]) => path)),
|
|
197
|
+
referrers: patched(index.referrers, [...referrers].filter(([, files]) => sizeOf(files) > 0), [...referrers].filter(([, files]) => sizeOf(files) === 0).map(([target]) => target)),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function storedIn(entries) {
|
|
201
|
+
let stored = shared({});
|
|
202
|
+
let unit = [];
|
|
203
|
+
return after(inUnits(entries, (entry) => {
|
|
204
|
+
unit.push(entry);
|
|
205
|
+
return ROW_WEIGHT;
|
|
206
|
+
}, () => {
|
|
207
|
+
stored = patched(stored, unit);
|
|
208
|
+
unit = [];
|
|
209
|
+
}), () => stored);
|
|
210
|
+
}
|
|
211
|
+
function storedReferrers(referrers) {
|
|
212
|
+
const sets = new Map();
|
|
213
|
+
let unit = new Map();
|
|
214
|
+
const pairs = function* () {
|
|
215
|
+
for (const [target, files] of referrers)
|
|
216
|
+
for (const file of files)
|
|
217
|
+
yield [target, file];
|
|
218
|
+
};
|
|
219
|
+
return after(inUnits(pairs(), ([target, file]) => {
|
|
220
|
+
const files = unit.get(target);
|
|
221
|
+
if (files === undefined)
|
|
222
|
+
unit.set(target, [file]);
|
|
223
|
+
else
|
|
224
|
+
files.push(file);
|
|
225
|
+
return ROW_WEIGHT;
|
|
226
|
+
}, () => {
|
|
227
|
+
for (const [target, files] of unit) {
|
|
228
|
+
sets.set(target, patched(sets.get(target) ?? NO_REFERRERS, files.map((file) => [file, true])));
|
|
229
|
+
}
|
|
230
|
+
unit = new Map();
|
|
231
|
+
}), () => storedIn(sets));
|
|
232
|
+
}
|
|
233
|
+
function heldIndex(held, composition) {
|
|
234
|
+
const index = referrersOf.get(held.text);
|
|
235
|
+
return index !== undefined && typing(index.composition, composition) ? index : null;
|
|
236
|
+
}
|
|
237
|
+
const indexing = new WeakMap();
|
|
238
|
+
export function indexReferrers(held, composition) {
|
|
239
|
+
if (heldIndex(held, composition) !== null)
|
|
240
|
+
return;
|
|
241
|
+
const running = indexing.get(held.text);
|
|
242
|
+
if (running !== undefined)
|
|
243
|
+
return running;
|
|
244
|
+
const targets = new Map();
|
|
245
|
+
const referrers = new Map();
|
|
246
|
+
const filled = inUnits(Object.keys(held.text), (path) => {
|
|
247
|
+
const content = held.text[path];
|
|
248
|
+
const found = referencedBy(path, content, composition);
|
|
249
|
+
if (found.length > 0)
|
|
250
|
+
targets.set(path, found);
|
|
251
|
+
for (const target of found) {
|
|
252
|
+
const files = referrers.get(target);
|
|
253
|
+
if (files === undefined)
|
|
254
|
+
referrers.set(target, [path]);
|
|
255
|
+
else
|
|
256
|
+
files.push(path);
|
|
257
|
+
}
|
|
258
|
+
return ROW_WEIGHT + content.length;
|
|
259
|
+
});
|
|
260
|
+
const indexed = after(filled, () => after(storedIn(targets), (storedTargets) => after(storedReferrers(referrers), (stored) => {
|
|
261
|
+
referrersOf.set(held.text, { composition, targets: storedTargets, referrers: stored });
|
|
262
|
+
})));
|
|
263
|
+
if (!(indexed instanceof Promise))
|
|
264
|
+
return;
|
|
265
|
+
const building = indexed.finally(() => indexing.delete(held.text));
|
|
266
|
+
indexing.set(held.text, building);
|
|
267
|
+
return building;
|
|
268
|
+
}
|
|
269
|
+
export function referencesIndexed(held, composition) {
|
|
270
|
+
return heldIndex(held, composition) !== null;
|
|
271
|
+
}
|
|
272
|
+
export function referring(held, composition, targets) {
|
|
273
|
+
const index = heldIndex(held, composition);
|
|
274
|
+
if (index === null)
|
|
275
|
+
return null;
|
|
276
|
+
const found = new Set();
|
|
277
|
+
for (const target of targets) {
|
|
278
|
+
for (const file of Object.keys(referrersOfTarget(index, target)))
|
|
279
|
+
found.add(file);
|
|
280
|
+
}
|
|
281
|
+
return found;
|
|
282
|
+
}
|
|
283
|
+
export function available(composition) {
|
|
284
|
+
return (composition.model.status !== 'unavailable' &&
|
|
285
|
+
(composition.selection === null || composition.selection.model.status !== 'unavailable'));
|
|
286
|
+
}
|
|
287
|
+
export function changedCleanly(next, previous, composition) {
|
|
288
|
+
if (!typing(previous.composition, composition))
|
|
289
|
+
return false;
|
|
290
|
+
const paths = new Set([
|
|
291
|
+
...differing(previous.text, next.text),
|
|
292
|
+
...differing(previous.binaries, next.binaries, () => true),
|
|
293
|
+
]);
|
|
294
|
+
const binary = (path) => Object.hasOwn(next.binaries, path);
|
|
295
|
+
const within = (file) => (path) => selected(composition, path) === selected(composition, file);
|
|
296
|
+
const reaching = (file, check) => {
|
|
297
|
+
if (!check.ok)
|
|
298
|
+
return false;
|
|
299
|
+
const part = within(file);
|
|
300
|
+
return check.references.every((reference) => resolves(reference, (path) => (part(path) ? declared(next.text[path]) : undefined), (path) => part(path) && binary(path)));
|
|
301
|
+
};
|
|
302
|
+
const changedTargets = new Map();
|
|
303
|
+
const shifted = [];
|
|
304
|
+
for (const path of paths) {
|
|
305
|
+
const now = next.text[path];
|
|
306
|
+
const was = previous.text[path];
|
|
307
|
+
const modeled = modelOf(composition, path) !== null;
|
|
308
|
+
if ((now === undefined) !== (was === undefined) ||
|
|
309
|
+
declared(now) !== declared(was) ||
|
|
310
|
+
binary(path) !== Object.hasOwn(previous.binaries, path)) {
|
|
311
|
+
shifted.push(path);
|
|
312
|
+
}
|
|
313
|
+
if (!modeled && typedIn(was) && !typedIn(now))
|
|
314
|
+
return false;
|
|
315
|
+
if (now === undefined) {
|
|
316
|
+
if (modeled)
|
|
317
|
+
changedTargets.set(path, []);
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (binary(path))
|
|
321
|
+
return false;
|
|
322
|
+
if (!modeled) {
|
|
323
|
+
if (declared(now) === undefined)
|
|
324
|
+
return false;
|
|
325
|
+
if (!typedIn(now) && !checked(path, now, composition).ok)
|
|
326
|
+
return false;
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const check = checked(path, now, composition);
|
|
330
|
+
if (!reaching(path, check))
|
|
331
|
+
return false;
|
|
332
|
+
changedTargets.set(path, targetsOf(check));
|
|
333
|
+
}
|
|
334
|
+
const index = heldIndex(previous, composition);
|
|
335
|
+
if (index === null && shifted.length > 0)
|
|
336
|
+
return false;
|
|
337
|
+
for (const target of shifted) {
|
|
338
|
+
const files = index === null ? [] : Object.keys(referrersOfTarget(index, target));
|
|
339
|
+
for (const file of files) {
|
|
340
|
+
if (paths.has(file))
|
|
341
|
+
continue;
|
|
342
|
+
if (!reaching(file, checked(file, next.text[file], composition)))
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (index !== null) {
|
|
347
|
+
referrersOf.set(next.text, changedTargets.size === 0 ? index : reindexed(index, changedTargets));
|
|
348
|
+
}
|
|
349
|
+
return true;
|
|
350
|
+
}
|