@agentshouse/mdruntime 0.1.0-ce531b51ff088 → 0.1.0-ceb97106cc2fd
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 +273 -175
- package/README.md +21 -11
- package/dist/acquisition.d.ts +14 -0
- package/dist/acquisition.d.ts.map +1 -0
- package/dist/acquisition.js +24 -0
- package/dist/adapter.d.ts +129 -41
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +1 -9
- package/dist/attached-model.d.ts +11 -0
- package/dist/attached-model.d.ts.map +1 -0
- package/dist/attached-model.js +47 -0
- 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 +20 -6
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +114 -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/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 +63 -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 +629 -0
- package/dist/chat/question.d.ts +9 -0
- package/dist/chat/question.d.ts.map +1 -0
- package/dist/chat/question.js +80 -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 +28 -14
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +71 -26
- package/dist/collection.d.ts +21 -12
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +271 -23
- package/dist/connection.d.ts +50 -23
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2074 -735
- package/dist/conversation.d.ts +41 -14
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +546 -214
- 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 +156 -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 +24 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +126 -45
- 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 +17 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +159 -46
- package/dist/model.d.ts +17 -14
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +16 -4
- package/dist/observation.d.ts +6 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +38 -17
- 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 +32 -3
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +42 -1
- package/dist/overlay.d.ts +16 -3
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +118 -77
- package/dist/paths.d.ts +0 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +0 -16
- package/dist/query.d.ts +46 -6
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +85 -37
- package/dist/reach.d.ts +45 -0
- package/dist/reach.d.ts.map +1 -0
- package/dist/reach.js +306 -0
- package/dist/react.d.ts +44 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +66 -0
- package/dist/read-side.d.ts +16 -5
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +408 -137
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -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 +12 -1
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +51 -36
- package/dist/replica.d.ts +10 -7
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +129 -73
- package/dist/room-draft.d.ts +41 -9
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +139 -28
- package/dist/rows.d.ts +11 -14
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +87 -50
- package/dist/save.d.ts +32 -3
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +465 -92
- package/dist/search.d.ts +37 -8
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +116 -45
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +61 -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 +76 -19
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +539 -200
- package/dist/turn.d.ts +7 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +45 -0
- package/dist/wire.d.ts +162 -19
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +82 -61
- package/package.json +31 -7
- 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,9 @@
|
|
|
1
1
|
import { observed } from './observation.js';
|
|
2
|
-
import {
|
|
2
|
+
import { runtimeError } from './failure.js';
|
|
3
|
+
import { answer, AUTHORIZATION_ENDED, PORT_CLOSED, } from './wire.js';
|
|
4
|
+
function refused(refusal) {
|
|
5
|
+
return runtimeError(refusal.code, refusal.code, refusal.retryable);
|
|
6
|
+
}
|
|
3
7
|
export function connectMdRuntime(port) {
|
|
4
8
|
let sequence = 0;
|
|
5
9
|
let refusal = null;
|
|
@@ -7,8 +11,10 @@ export function connectMdRuntime(port) {
|
|
|
7
11
|
const calls = new Map();
|
|
8
12
|
const opening = new Map();
|
|
9
13
|
const observations = new Map();
|
|
14
|
+
let drawing = null;
|
|
15
|
+
let settling = null;
|
|
10
16
|
const send = (message) => {
|
|
11
|
-
port.postMessage(
|
|
17
|
+
port.postMessage(message);
|
|
12
18
|
};
|
|
13
19
|
function begin(id, topic, first) {
|
|
14
20
|
const handle = observed(first, () => {
|
|
@@ -25,7 +31,7 @@ export function connectMdRuntime(port) {
|
|
|
25
31
|
if (topic === 'connection-refusal')
|
|
26
32
|
handle.receive(reported);
|
|
27
33
|
}
|
|
28
|
-
const failure =
|
|
34
|
+
const failure = refused(reported);
|
|
29
35
|
for (const [id, waiting] of opening) {
|
|
30
36
|
if (waiting.topic === 'connection-refusal')
|
|
31
37
|
waiting.settle(begin(id, waiting.topic, reported));
|
|
@@ -36,12 +42,12 @@ export function connectMdRuntime(port) {
|
|
|
36
42
|
for (const waiting of calls.values())
|
|
37
43
|
waiting.fail(failure);
|
|
38
44
|
calls.clear();
|
|
45
|
+
drawing?.();
|
|
39
46
|
}
|
|
40
|
-
function end(
|
|
47
|
+
function end(failure) {
|
|
41
48
|
if (ended !== null)
|
|
42
49
|
return;
|
|
43
|
-
ended =
|
|
44
|
-
const failure = new Error(reason);
|
|
50
|
+
ended = failure;
|
|
45
51
|
for (const waiting of opening.values())
|
|
46
52
|
waiting.fail(failure);
|
|
47
53
|
opening.clear();
|
|
@@ -51,16 +57,10 @@ export function connectMdRuntime(port) {
|
|
|
51
57
|
for (const { handle } of observations.values())
|
|
52
58
|
handle.end();
|
|
53
59
|
observations.clear();
|
|
60
|
+
drawing?.();
|
|
54
61
|
}
|
|
55
62
|
port.addEventListener('message', (event) => {
|
|
56
|
-
const
|
|
57
|
-
if (wire === null)
|
|
58
|
-
return;
|
|
59
|
-
if (!wire.matching) {
|
|
60
|
-
refuse(PROTOCOL_MISMATCH);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const message = answer(wire.message);
|
|
63
|
+
const message = answer(event.data);
|
|
64
64
|
if (message === null)
|
|
65
65
|
return;
|
|
66
66
|
if (message.kind === 'refusal') {
|
|
@@ -68,7 +68,11 @@ export function connectMdRuntime(port) {
|
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
if (message.kind === 'ended') {
|
|
71
|
-
|
|
71
|
+
for (const { topic, handle } of observations.values()) {
|
|
72
|
+
if (topic === 'member')
|
|
73
|
+
handle.receive(null);
|
|
74
|
+
}
|
|
75
|
+
end(runtimeError('authorization-ended', AUTHORIZATION_ENDED));
|
|
72
76
|
return;
|
|
73
77
|
}
|
|
74
78
|
if (message.kind === 'event') {
|
|
@@ -78,31 +82,34 @@ export function connectMdRuntime(port) {
|
|
|
78
82
|
const waiting = opening.get(message.id);
|
|
79
83
|
if (waiting !== undefined) {
|
|
80
84
|
opening.delete(message.id);
|
|
81
|
-
if (message.kind === 'failure')
|
|
82
|
-
waiting.fail(
|
|
85
|
+
if (message.kind === 'failure') {
|
|
86
|
+
waiting.fail(runtimeError(message.code, message.message, message.retryable));
|
|
87
|
+
}
|
|
83
88
|
else
|
|
84
89
|
waiting.settle(begin(message.id, waiting.topic, message.value));
|
|
90
|
+
drawing?.();
|
|
85
91
|
return;
|
|
86
92
|
}
|
|
87
93
|
const called = calls.get(message.id);
|
|
88
94
|
if (called === undefined)
|
|
89
95
|
return;
|
|
90
96
|
calls.delete(message.id);
|
|
91
|
-
if (message.kind === 'failure')
|
|
92
|
-
called.fail(
|
|
97
|
+
if (message.kind === 'failure') {
|
|
98
|
+
called.fail(runtimeError(message.code, message.message, message.retryable));
|
|
99
|
+
}
|
|
93
100
|
else
|
|
94
101
|
called.settle(message.value);
|
|
95
102
|
});
|
|
96
103
|
port.addEventListener('close', () => {
|
|
97
|
-
end(PORT_CLOSED);
|
|
104
|
+
end(runtimeError('port-closed', PORT_CLOSED));
|
|
98
105
|
});
|
|
99
106
|
port.start();
|
|
100
107
|
send({ kind: 'hello' });
|
|
101
108
|
function ask(member, input) {
|
|
102
109
|
if (ended !== null)
|
|
103
|
-
return Promise.reject(
|
|
110
|
+
return Promise.reject(ended);
|
|
104
111
|
if (refusal !== null)
|
|
105
|
-
return Promise.reject(
|
|
112
|
+
return Promise.reject(refused(refusal));
|
|
106
113
|
const id = (sequence += 1);
|
|
107
114
|
return new Promise((settle, fail) => {
|
|
108
115
|
calls.set(id, { settle: settle, fail });
|
|
@@ -111,18 +118,43 @@ export function connectMdRuntime(port) {
|
|
|
111
118
|
}
|
|
112
119
|
function watch(topic, input) {
|
|
113
120
|
if (ended !== null)
|
|
114
|
-
return Promise.reject(
|
|
121
|
+
return Promise.reject(ended);
|
|
115
122
|
const id = (sequence += 1);
|
|
116
123
|
if (refusal !== null) {
|
|
117
124
|
return topic === 'connection-refusal'
|
|
118
125
|
? Promise.resolve(begin(id, topic, refusal))
|
|
119
|
-
: Promise.reject(
|
|
126
|
+
: Promise.reject(refused(refusal));
|
|
120
127
|
}
|
|
121
128
|
return new Promise((settle, fail) => {
|
|
122
129
|
opening.set(id, { topic, settle, fail });
|
|
123
130
|
send({ kind: 'observe', id, topic, input });
|
|
131
|
+
drawing?.();
|
|
124
132
|
});
|
|
125
133
|
}
|
|
134
|
+
function settled() {
|
|
135
|
+
if (settling !== null)
|
|
136
|
+
return settling;
|
|
137
|
+
settling = new Promise((resolve) => {
|
|
138
|
+
let moved = 0;
|
|
139
|
+
const check = () => {
|
|
140
|
+
moved += 1;
|
|
141
|
+
if (opening.size > 0)
|
|
142
|
+
return;
|
|
143
|
+
const at = moved;
|
|
144
|
+
requestAnimationFrame(() => {
|
|
145
|
+
requestAnimationFrame(() => {
|
|
146
|
+
if (moved !== at || opening.size > 0)
|
|
147
|
+
return;
|
|
148
|
+
drawing = null;
|
|
149
|
+
resolve();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
drawing = check;
|
|
154
|
+
check();
|
|
155
|
+
});
|
|
156
|
+
return settling;
|
|
157
|
+
}
|
|
126
158
|
return {
|
|
127
159
|
rooms: () => ask('rooms', []),
|
|
128
160
|
query: ((query) => ask('query', [query])),
|
|
@@ -143,7 +175,7 @@ export function connectMdRuntime(port) {
|
|
|
143
175
|
list: () => ask('conversation.list', []),
|
|
144
176
|
read: (conversation, options) => ask('conversation.read', [conversation, options]),
|
|
145
177
|
create: (input) => ask('conversation.create', [input]),
|
|
146
|
-
send: (conversation) => ask('conversation.send', [conversation]),
|
|
178
|
+
send: (conversation, operation, draft) => ask('conversation.send', [conversation, operation, draft]),
|
|
147
179
|
answer: (conversation, answer) => ask('conversation.answer', [conversation, answer]),
|
|
148
180
|
interrupt: (conversation) => ask('conversation.interrupt', [conversation]),
|
|
149
181
|
kill: (conversation) => ask('conversation.kill', [conversation]),
|
|
@@ -151,15 +183,28 @@ export function connectMdRuntime(port) {
|
|
|
151
183
|
delete: (conversation) => ask('conversation.delete', [conversation]),
|
|
152
184
|
},
|
|
153
185
|
chatDraft: {
|
|
154
|
-
write: (conversation, draft) => ask('chatDraft.write', [conversation, draft]),
|
|
186
|
+
write: (conversation, draft, revision) => ask('chatDraft.write', [conversation, draft, revision]),
|
|
155
187
|
discard: (conversation) => ask('chatDraft.discard', [conversation]),
|
|
156
188
|
},
|
|
157
189
|
history: (locator, path, query) => ask('history', [locator, path, query]),
|
|
190
|
+
binaryFile: {
|
|
191
|
+
read: (room, path, revision) => ask('binaryFile.read', [room, path, revision]),
|
|
192
|
+
readReference: (reference) => ask('binaryFile.readReference', [reference]),
|
|
193
|
+
},
|
|
158
194
|
call: (name, input) => ask('call', [name, input]),
|
|
159
195
|
reached: (locator, roomVersion, path) => ask('reached', [locator, roomVersion, path]),
|
|
160
196
|
log: () => ask('log', []),
|
|
161
197
|
persistence: () => ask('persistence', []),
|
|
198
|
+
retry: () => ask('retry', []),
|
|
162
199
|
observe: ((topic, ...input) => watch(topic, input)),
|
|
163
200
|
reauthorize: () => ask('reauthorize', []),
|
|
201
|
+
settled,
|
|
164
202
|
};
|
|
165
203
|
}
|
|
204
|
+
const turns = new WeakMap();
|
|
205
|
+
export function inTurn(client, work) {
|
|
206
|
+
const next = (turns.get(client) ?? Promise.resolve()).then(work).catch(() => undefined);
|
|
207
|
+
turns.set(client, next);
|
|
208
|
+
return next;
|
|
209
|
+
}
|
|
210
|
+
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 } from './shared.js';
|
|
5
|
+
import { 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,197 @@ 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 referrersOf = new WeakMap();
|
|
128
|
+
function typing(left, right) {
|
|
129
|
+
return (sameTyping(left.model, right.model) &&
|
|
130
|
+
(left.selection === null || right.selection === null
|
|
131
|
+
? left.selection === right.selection
|
|
132
|
+
: sameTyping(left.selection.model, right.selection.model)) &&
|
|
133
|
+
JSON.stringify(left.selection?.roots ?? null) === JSON.stringify(right.selection?.roots ?? null));
|
|
134
|
+
}
|
|
135
|
+
function declared(content) {
|
|
136
|
+
if (content === undefined)
|
|
137
|
+
return undefined;
|
|
138
|
+
const read = parseFrontmatter(content);
|
|
139
|
+
return read.ok ? (read.frontmatter.type ?? 'any') : undefined;
|
|
140
|
+
}
|
|
141
|
+
function typedIn(content) {
|
|
142
|
+
const type = declared(content);
|
|
143
|
+
return type !== undefined && type !== 'any';
|
|
144
|
+
}
|
|
145
|
+
function modelOf(composition, path) {
|
|
146
|
+
const model = governing(composition, path);
|
|
147
|
+
return model.status === 'unavailable' ? null : { types: model.types };
|
|
148
|
+
}
|
|
149
|
+
function checked(path, content, composition) {
|
|
150
|
+
return checkDocument(path, content, modelOf(composition, path) ?? NO_TYPES);
|
|
151
|
+
}
|
|
152
|
+
function targetsOf(check) {
|
|
153
|
+
if (!check.ok)
|
|
154
|
+
return [];
|
|
155
|
+
return [...new Set(check.references.flatMap(({ target }) => (target === null ? [] : [target])))];
|
|
156
|
+
}
|
|
157
|
+
function referencedBy(path, content, composition) {
|
|
158
|
+
const model = modelOf(composition, path);
|
|
159
|
+
if (model === null)
|
|
160
|
+
return [];
|
|
161
|
+
const read = parseFrontmatter(content, path);
|
|
162
|
+
const type = read.ok ? read.frontmatter.type : undefined;
|
|
163
|
+
if (!read.ok || type === undefined || !Object.hasOwn(model.types, type))
|
|
164
|
+
return [];
|
|
165
|
+
const definition = model.types[type];
|
|
166
|
+
return [
|
|
167
|
+
...new Set([
|
|
168
|
+
...references(read.frontmatter, definition).flatMap(({ value }) => {
|
|
169
|
+
const found = target(path, value);
|
|
170
|
+
return found === null ? [] : [found];
|
|
171
|
+
}),
|
|
172
|
+
...sectionReferences(path, content, definition).flatMap(({ target }) => target === null ? [] : [target]),
|
|
173
|
+
]),
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
function reindexed(index, changed) {
|
|
177
|
+
const referrers = new Map();
|
|
178
|
+
const touch = (target) => {
|
|
179
|
+
let held = referrers.get(target);
|
|
180
|
+
if (held === undefined) {
|
|
181
|
+
held = new Set(Object.hasOwn(index.referrers, target) ? index.referrers[target] : []);
|
|
182
|
+
referrers.set(target, held);
|
|
183
|
+
}
|
|
184
|
+
return held;
|
|
185
|
+
};
|
|
186
|
+
for (const [path, found] of changed) {
|
|
187
|
+
const before = Object.hasOwn(index.targets, path) ? index.targets[path] : [];
|
|
188
|
+
for (const target of before)
|
|
189
|
+
touch(target).delete(path);
|
|
190
|
+
for (const target of found)
|
|
191
|
+
touch(target).add(path);
|
|
192
|
+
}
|
|
193
|
+
const emptied = [...referrers].filter(([, held]) => held.size === 0).map(([target]) => target);
|
|
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]
|
|
198
|
+
.filter(([, held]) => held.size > 0)
|
|
199
|
+
.map(([target, held]) => [target, [...held]]), emptied),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function heldIndex(held, composition) {
|
|
203
|
+
const index = referrersOf.get(held.text);
|
|
204
|
+
return index !== undefined && typing(index.composition, composition) ? index : null;
|
|
205
|
+
}
|
|
206
|
+
const indexing = new WeakMap();
|
|
207
|
+
export function indexReferrers(held, composition) {
|
|
208
|
+
if (heldIndex(held, composition) !== null)
|
|
209
|
+
return;
|
|
210
|
+
const running = indexing.get(held.text);
|
|
211
|
+
if (running !== undefined)
|
|
212
|
+
return running;
|
|
213
|
+
const targets = new Map();
|
|
214
|
+
const referrers = new Map();
|
|
215
|
+
const filled = inUnits(Object.keys(held.text), (path) => {
|
|
216
|
+
const content = held.text[path];
|
|
217
|
+
const found = referencedBy(path, content, composition);
|
|
218
|
+
if (found.length > 0)
|
|
219
|
+
targets.set(path, found);
|
|
220
|
+
for (const target of found)
|
|
221
|
+
referrers.set(target, [...(referrers.get(target) ?? []), path]);
|
|
222
|
+
return ROW_WEIGHT + content.length;
|
|
223
|
+
});
|
|
224
|
+
const indexed = () => {
|
|
225
|
+
referrersOf.set(held.text, {
|
|
226
|
+
composition,
|
|
227
|
+
targets: patched(shared({}), targets),
|
|
228
|
+
referrers: patched(shared({}), referrers),
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
if (!(filled instanceof Promise))
|
|
232
|
+
return indexed();
|
|
233
|
+
const building = filled.then(indexed).finally(() => indexing.delete(held.text));
|
|
234
|
+
indexing.set(held.text, building);
|
|
235
|
+
return building;
|
|
236
|
+
}
|
|
237
|
+
export function referencesIndexed(held, composition) {
|
|
238
|
+
return heldIndex(held, composition) !== null;
|
|
239
|
+
}
|
|
240
|
+
export function referring(held, composition, targets) {
|
|
241
|
+
const index = heldIndex(held, composition);
|
|
242
|
+
if (index === null)
|
|
243
|
+
return null;
|
|
244
|
+
const found = new Set();
|
|
245
|
+
for (const target of targets) {
|
|
246
|
+
if (!Object.hasOwn(index.referrers, target))
|
|
247
|
+
continue;
|
|
248
|
+
for (const file of index.referrers[target])
|
|
249
|
+
found.add(file);
|
|
250
|
+
}
|
|
251
|
+
return found;
|
|
252
|
+
}
|
|
253
|
+
export function available(composition) {
|
|
254
|
+
return (composition.model.status !== 'unavailable' &&
|
|
255
|
+
(composition.selection === null || composition.selection.model.status !== 'unavailable'));
|
|
256
|
+
}
|
|
257
|
+
export function changedCleanly(next, previous, composition) {
|
|
258
|
+
if (!typing(previous.composition, composition))
|
|
259
|
+
return false;
|
|
260
|
+
const paths = new Set([
|
|
261
|
+
...differing(previous.text, next.text),
|
|
262
|
+
...differing(previous.binaries, next.binaries, () => true),
|
|
263
|
+
]);
|
|
264
|
+
const binary = (path) => Object.hasOwn(next.binaries, path);
|
|
265
|
+
const within = (file) => (path) => selected(composition, path) === selected(composition, file);
|
|
266
|
+
const reaching = (file, check) => {
|
|
267
|
+
if (!check.ok)
|
|
268
|
+
return false;
|
|
269
|
+
const part = within(file);
|
|
270
|
+
return check.references.every((reference) => resolves(reference, (path) => (part(path) ? declared(next.text[path]) : undefined), (path) => part(path) && binary(path)));
|
|
271
|
+
};
|
|
272
|
+
const changedTargets = new Map();
|
|
273
|
+
const shifted = [];
|
|
274
|
+
for (const path of paths) {
|
|
275
|
+
const now = next.text[path];
|
|
276
|
+
const was = previous.text[path];
|
|
277
|
+
const modeled = modelOf(composition, path) !== null;
|
|
278
|
+
if ((now === undefined) !== (was === undefined) ||
|
|
279
|
+
declared(now) !== declared(was) ||
|
|
280
|
+
binary(path) !== Object.hasOwn(previous.binaries, path)) {
|
|
281
|
+
shifted.push(path);
|
|
282
|
+
}
|
|
283
|
+
if (!modeled && typedIn(was) && !typedIn(now))
|
|
284
|
+
return false;
|
|
285
|
+
if (now === undefined) {
|
|
286
|
+
if (modeled)
|
|
287
|
+
changedTargets.set(path, []);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (binary(path))
|
|
291
|
+
return false;
|
|
292
|
+
if (!modeled) {
|
|
293
|
+
if (declared(now) === undefined)
|
|
294
|
+
return false;
|
|
295
|
+
if (!typedIn(now) && !checked(path, now, composition).ok)
|
|
296
|
+
return false;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const check = checked(path, now, composition);
|
|
300
|
+
if (!reaching(path, check))
|
|
301
|
+
return false;
|
|
302
|
+
changedTargets.set(path, targetsOf(check));
|
|
303
|
+
}
|
|
304
|
+
const index = heldIndex(previous, composition);
|
|
305
|
+
if (index === null && shifted.length > 0)
|
|
306
|
+
return false;
|
|
307
|
+
for (const target of shifted) {
|
|
308
|
+
const files = index !== null && Object.hasOwn(index.referrers, target) ? index.referrers[target] : [];
|
|
309
|
+
for (const file of files) {
|
|
310
|
+
if (paths.has(file))
|
|
311
|
+
continue;
|
|
312
|
+
if (!reaching(file, checked(file, next.text[file], composition)))
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (index !== null) {
|
|
317
|
+
referrersOf.set(next.text, changedTargets.size === 0 ? index : reindexed(index, changedTargets));
|
|
318
|
+
}
|
|
319
|
+
return true;
|
|
320
|
+
}
|