@agentshouse/mdruntime 0.1.0-cd3486bd400ed → 0.1.0-cd37f80239af0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -9
- package/dist/adapter.d.ts +149 -46
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +5 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +38 -4
- package/dist/attempt.d.ts.map +1 -1
- package/dist/attempt.js +14 -1
- package/dist/binary.d.ts +18 -0
- package/dist/binary.d.ts.map +1 -0
- package/dist/binary.js +8 -0
- package/dist/bootstrap.d.ts +27 -11
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +184 -84
- package/dist/chain.d.ts +11 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +64 -0
- package/dist/change-set.d.ts +9 -14
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +11 -62
- package/dist/change.d.ts +41 -0
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +34 -0
- package/dist/client.d.ts +31 -13
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +103 -7
- package/dist/collection.d.ts +10 -7
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +38 -79
- package/dist/compile.d.ts +16 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +786 -0
- package/dist/connection.d.ts +50 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +3786 -931
- package/dist/conversation.d.ts +37 -16
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +700 -257
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/durability.d.ts +4 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +20 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +151 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/file.d.ts +2 -19
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +7 -122
- package/dist/fulltext.d.ts +27 -0
- package/dist/fulltext.d.ts.map +1 -0
- package/dist/fulltext.js +370 -0
- package/dist/host.d.ts +13 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +130 -17
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +17 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/live.d.ts +22 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +123 -0
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +218 -0
- package/dist/memory.d.ts +17 -7
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +231 -91
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +90 -0
- package/dist/model.d.ts +9 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +8 -2
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +20 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +113 -12
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/outcome.d.ts +52 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +46 -0
- package/dist/overlay.d.ts +15 -5
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +129 -177
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +68 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +48 -7
- package/dist/reach.d.ts +18 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +224 -55
- package/dist/react.d.ts +9 -6
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/readiness.d.ts +52 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +27 -0
- package/dist/recovery.d.ts +26 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +224 -0
- package/dist/refresh.d.ts +17 -14
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +136 -56
- package/dist/replica.d.ts +58 -33
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +307 -159
- package/dist/room-draft.d.ts +51 -4
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +210 -18
- package/dist/rows.d.ts +37 -35
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +173 -102
- package/dist/save.d.ts +70 -3
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +805 -147
- package/dist/search.d.ts +39 -28
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +37 -105
- 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 +15 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +421 -0
- package/dist/status.d.ts +5 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +107 -80
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +325 -461
- package/dist/stored.d.ts +130 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +560 -0
- package/dist/tables.d.ts +325 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +578 -0
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/turn.d.ts +9 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +75 -0
- package/dist/validation.d.ts +29 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +101 -0
- package/dist/windows.d.ts +22 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +89 -0
- package/dist/wire.d.ts +165 -30
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +56 -29
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +156 -0
- package/package.json +26 -15
- package/AGENTS.md +0 -290
- package/dist/attachment.d.ts +0 -3
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -8
- package/dist/chat/acts.d.ts +0 -34
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/messages.d.ts +0 -21
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -151
- package/dist/chat/overlay.d.ts +0 -31
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -97
- package/dist/chat/parts.d.ts +0 -57
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -119
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -57
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -637
- package/dist/chat/questions.d.ts +0 -31
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/questions.js +0 -111
- package/dist/chat/read.d.ts +0 -5
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/read.js +0 -13
- package/dist/chat.d.ts +0 -7
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -2
- package/dist/read-side.d.ts +0 -18
- package/dist/read-side.d.ts.map +0 -1
- package/dist/read-side.js +0 -433
package/dist/chat/questions.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { list, record, text } from './read.js';
|
|
2
|
-
const OPTION = 'optionId';
|
|
3
|
-
function choicesOf(schema) {
|
|
4
|
-
const items = record(schema.items);
|
|
5
|
-
const listed = [schema.oneOf, schema.enum, items.anyOf, items.enum].find(Array.isArray) ?? [];
|
|
6
|
-
return listed.flatMap((one) => {
|
|
7
|
-
if (typeof one === 'string')
|
|
8
|
-
return [{ value: one, label: one, about: null }];
|
|
9
|
-
const value = text(record(one), 'const');
|
|
10
|
-
return value === null
|
|
11
|
-
? []
|
|
12
|
-
: [
|
|
13
|
-
{
|
|
14
|
-
value,
|
|
15
|
-
label: text(record(one), 'title') ?? value,
|
|
16
|
-
about: text(record(one), 'description'),
|
|
17
|
-
},
|
|
18
|
-
];
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
function fieldOf(name, schema) {
|
|
22
|
-
const type = text(schema, 'type');
|
|
23
|
-
const kind = type === 'boolean' || type === 'number' || type === 'integer'
|
|
24
|
-
? type
|
|
25
|
-
: type === 'array'
|
|
26
|
-
? 'multi-select'
|
|
27
|
-
: 'string';
|
|
28
|
-
return {
|
|
29
|
-
name,
|
|
30
|
-
kind,
|
|
31
|
-
prompt: text(schema, 'title') ?? name,
|
|
32
|
-
about: text(schema, 'description'),
|
|
33
|
-
choices: kind === 'boolean' ? [] : choicesOf(schema),
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
export function entered(field) {
|
|
37
|
-
return field.kind !== 'boolean' && field.choices.length === 0;
|
|
38
|
-
}
|
|
39
|
-
function valueOf(field, raw) {
|
|
40
|
-
return field.kind === 'number' || field.kind === 'integer' ? Number(raw) : raw;
|
|
41
|
-
}
|
|
42
|
-
function typed(fields, answer) {
|
|
43
|
-
return Object.fromEntries(Object.entries(answer).map(([name, value]) => {
|
|
44
|
-
const field = fields.find((one) => one.name === name);
|
|
45
|
-
return [
|
|
46
|
-
name,
|
|
47
|
-
field !== undefined && entered(field) && typeof value === 'string'
|
|
48
|
-
? valueOf(field, value)
|
|
49
|
-
: value,
|
|
50
|
-
];
|
|
51
|
-
}));
|
|
52
|
-
}
|
|
53
|
-
function askedOf(request) {
|
|
54
|
-
const params = record(request.params);
|
|
55
|
-
const method = text(request, 'method');
|
|
56
|
-
if (method === 'session/request_permission') {
|
|
57
|
-
return {
|
|
58
|
-
message: '',
|
|
59
|
-
fields: [
|
|
60
|
-
{
|
|
61
|
-
name: OPTION,
|
|
62
|
-
kind: 'string',
|
|
63
|
-
prompt: text(record(params.toolCall), 'title') ?? '',
|
|
64
|
-
about: null,
|
|
65
|
-
choices: list(params, 'options').flatMap((entry) => {
|
|
66
|
-
const one = record(entry);
|
|
67
|
-
const value = text(one, OPTION);
|
|
68
|
-
return value === null
|
|
69
|
-
? []
|
|
70
|
-
: [{ value, label: text(one, 'name') ?? value, about: null }];
|
|
71
|
-
}),
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
accept: (answer) => ({ outcome: { outcome: 'selected', optionId: answer[OPTION] } }),
|
|
75
|
-
decline: null,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
if (method !== 'elicitation/create')
|
|
79
|
-
return null;
|
|
80
|
-
const fields = Object.entries(record(record(params.requestedSchema).properties)).map(([name, schema]) => fieldOf(name, record(schema)));
|
|
81
|
-
return {
|
|
82
|
-
message: text(params, 'message') ?? '',
|
|
83
|
-
fields,
|
|
84
|
-
accept: (answer) => ({ action: 'accept', content: typed(fields, answer) }),
|
|
85
|
-
decline: { action: 'decline' },
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
export function questionsOf(view) {
|
|
89
|
-
return (view?.questions ?? []).flatMap((entry) => {
|
|
90
|
-
const one = record(entry);
|
|
91
|
-
const interaction = text(one, 'interaction_id');
|
|
92
|
-
const asked = askedOf(record(one.request));
|
|
93
|
-
return asked === null || interaction === null
|
|
94
|
-
? []
|
|
95
|
-
: [
|
|
96
|
-
{
|
|
97
|
-
interaction,
|
|
98
|
-
secret: one.secret === true,
|
|
99
|
-
undelivered: one.telegram_undelivered === true,
|
|
100
|
-
...asked,
|
|
101
|
-
},
|
|
102
|
-
];
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
export function loneOf(questions) {
|
|
106
|
-
const asked = questions.length === 1 && !questions[0]?.secret ? questions[0] : undefined;
|
|
107
|
-
const only = asked?.fields.length === 1 ? asked.fields[0] : undefined;
|
|
108
|
-
return asked !== undefined && only !== undefined && entered(only)
|
|
109
|
-
? { question: asked, field: only }
|
|
110
|
-
: null;
|
|
111
|
-
}
|
package/dist/chat/read.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export type Fields = Readonly<Record<string, unknown>>;
|
|
2
|
-
export declare function record(entry: unknown): Fields;
|
|
3
|
-
export declare function text(fields: Fields, name: string): string | null;
|
|
4
|
-
export declare function list(fields: Fields, name: string): readonly unknown[];
|
|
5
|
-
//# sourceMappingURL=read.d.ts.map
|
package/dist/chat/read.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/chat/read.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAI7C;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAGrE"}
|
package/dist/chat/read.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export function record(entry) {
|
|
2
|
-
return typeof entry === 'object' && entry !== null && !Array.isArray(entry)
|
|
3
|
-
? entry
|
|
4
|
-
: {};
|
|
5
|
-
}
|
|
6
|
-
export function text(fields, name) {
|
|
7
|
-
const value = fields[name];
|
|
8
|
-
return typeof value === 'string' && value !== '' ? value : null;
|
|
9
|
-
}
|
|
10
|
-
export function list(fields, name) {
|
|
11
|
-
const value = fields[name];
|
|
12
|
-
return Array.isArray(value) ? value : [];
|
|
13
|
-
}
|
package/dist/chat.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { ChatProvider, useChat, type ChatActing, type ChatOpened, type ChatProviderProps, type ChatQueued, type ChatState, } from './chat/provider.js';
|
|
2
|
-
export { chatMessages } from './chat/messages.js';
|
|
3
|
-
export type { ChatOutcome } from './chat/acts.js';
|
|
4
|
-
export type { ChatWork } from './chat/parts.js';
|
|
5
|
-
export type { ChatCommand, ChatOption, ChatOptionValue } from './chat/process.js';
|
|
6
|
-
export type { ChatAnswer, ChatChoice, ChatField, ChatLone, ChatQuestion, } from './chat/questions.js';
|
|
7
|
-
//# sourceMappingURL=chat.d.ts.map
|
package/dist/chat.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,OAAO,EACP,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,SAAS,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAClF,YAAY,EACV,UAAU,EACV,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,GACb,MAAM,qBAAqB,CAAC"}
|
package/dist/chat.js
DELETED
package/dist/read-side.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { ChangeSet } from './change-set.js';
|
|
2
|
-
import { type KeyedResult, type QueryChange } from './observation.js';
|
|
3
|
-
import type { Plan, QueryResult } from './query.js';
|
|
4
|
-
import type { SearchedDocument } from './search.js';
|
|
5
|
-
export type ReadSide = {
|
|
6
|
-
apply(set: ChangeSet): void;
|
|
7
|
-
query(plan: Plan): Promise<QueryResult>;
|
|
8
|
-
watch(plan: Plan, identity: string, deliver: (message: KeyedResult | QueryChange) => void): () => void;
|
|
9
|
-
documents(): readonly SearchedDocument[];
|
|
10
|
-
document(room: string, path: string): SearchedDocument | null;
|
|
11
|
-
close(): void;
|
|
12
|
-
};
|
|
13
|
-
export declare function reconciled(previous: KeyedResult, next: KeyedResult): {
|
|
14
|
-
keyed: KeyedResult;
|
|
15
|
-
change: QueryChange;
|
|
16
|
-
} | null;
|
|
17
|
-
export declare function createReadSide(): ReadSide;
|
|
18
|
-
//# sourceMappingURL=read-side.d.ts.map
|
package/dist/read-side.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-side.d.ts","sourceRoot":"","sources":["../src/read-side.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAU,KAAK,WAAW,EAAE,KAAK,WAAW,EAAe,MAAM,kBAAkB,CAAC;AAC3F,OAAO,KAAK,EAOV,IAAI,EAIJ,WAAW,EAIZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAuDpD,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,KAAK,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,KAAK,IAAI,GACpD,MAAM,IAAI,CAAC;IACd,SAAS,IAAI,SAAS,gBAAgB,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC9D,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AA+UF,wBAAgB,UAAU,CACxB,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,WAAW,GAChB;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG,IAAI,CA4BpD;AAED,wBAAgB,cAAc,IAAI,QAAQ,CA4HzC"}
|
package/dist/read-side.js
DELETED
|
@@ -1,433 +0,0 @@
|
|
|
1
|
-
import { and, BasicIndex, configureIndexDevMode, count, createCollection, createLiveQueryCollection, deepEquals, eq, inArray, or, toArray, } from '@tanstack/db';
|
|
2
|
-
import { ARRAY_INDEX, pointerSegments } from '@agentshouse/mdmodel';
|
|
3
|
-
import { rowsOf } from './observation.js';
|
|
4
|
-
import { documentKey } from './rows.js';
|
|
5
|
-
function every(expressions) {
|
|
6
|
-
const [first, second, ...rest] = expressions;
|
|
7
|
-
return second === undefined ? first : and(first, second, ...rest);
|
|
8
|
-
}
|
|
9
|
-
function same(held, value) {
|
|
10
|
-
return Array.isArray(held) ? held.includes(value) : held === value;
|
|
11
|
-
}
|
|
12
|
-
function ordered(held, [operator, bound]) {
|
|
13
|
-
if (typeof held !== typeof bound || held === null || typeof held === 'object')
|
|
14
|
-
return false;
|
|
15
|
-
const left = held;
|
|
16
|
-
const right = bound;
|
|
17
|
-
if (operator === 'gt')
|
|
18
|
-
return left > right;
|
|
19
|
-
if (operator === 'gte')
|
|
20
|
-
return left >= right;
|
|
21
|
-
if (operator === 'lt')
|
|
22
|
-
return left < right;
|
|
23
|
-
return left <= right;
|
|
24
|
-
}
|
|
25
|
-
function satisfied(test, held) {
|
|
26
|
-
if (test.op === 'eq')
|
|
27
|
-
return same(held, test.value);
|
|
28
|
-
if (test.op === 'ne')
|
|
29
|
-
return !same(held, test.value);
|
|
30
|
-
if (test.op === 'in')
|
|
31
|
-
return test.values.some((value) => same(held, value));
|
|
32
|
-
if (test.op === 'nin')
|
|
33
|
-
return !test.values.some((value) => same(held, value));
|
|
34
|
-
if (test.op === 'range')
|
|
35
|
-
return test.bounds.every((bound) => ordered(held, bound));
|
|
36
|
-
if (test.op === 'all')
|
|
37
|
-
return Array.isArray(held) && test.values.every((value) => same(held, value));
|
|
38
|
-
return Array.isArray(held) && held.length === test.size;
|
|
39
|
-
}
|
|
40
|
-
function tested(test, reached) {
|
|
41
|
-
if (test.op === 'exists')
|
|
42
|
-
return test.exists === (reached !== undefined);
|
|
43
|
-
if (reached === undefined)
|
|
44
|
-
return test.op === 'ne' || test.op === 'nin';
|
|
45
|
-
return reached.some((held) => satisfied(test, held));
|
|
46
|
-
}
|
|
47
|
-
function conditioned(condition, row) {
|
|
48
|
-
if ('every' in condition)
|
|
49
|
-
return condition.every.every((item) => conditioned(item, row));
|
|
50
|
-
if ('some' in condition)
|
|
51
|
-
return condition.some.some((item) => conditioned(item, row));
|
|
52
|
-
return tested(condition.test, row.reached[condition.field]);
|
|
53
|
-
}
|
|
54
|
-
function narrowed(query, where, alias) {
|
|
55
|
-
return where === null ? query : query.fn.where((row) => conditioned(where, row[alias]));
|
|
56
|
-
}
|
|
57
|
-
function reached(reach, room, document) {
|
|
58
|
-
return reach === null
|
|
59
|
-
? []
|
|
60
|
-
: [or(inArray(room, [...reach.rooms]), inArray(document, [...reach.documents]))];
|
|
61
|
-
}
|
|
62
|
-
function scoped(scope, row, rooms, reach) {
|
|
63
|
-
return every([
|
|
64
|
-
eq(row.kind, 'document'),
|
|
65
|
-
...(rooms === null ? [] : [inArray(row.room, [...rooms])]),
|
|
66
|
-
...reached(reach, row.room, row.key),
|
|
67
|
-
...(scope.types === null ? [] : [inArray(row.type, [...scope.types])]),
|
|
68
|
-
...(scope.pathPrefix === null ? [] : [inArray(scope.pathPrefix, row.directories)]),
|
|
69
|
-
]);
|
|
70
|
-
}
|
|
71
|
-
function keyed(key, row) {
|
|
72
|
-
return key.of === 'field' ? row.values[key.field] : row[key.of];
|
|
73
|
-
}
|
|
74
|
-
function live(query) {
|
|
75
|
-
return createLiveQueryCollection({
|
|
76
|
-
query: query,
|
|
77
|
-
startSync: true,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
function related(q, rows, scope, field, kept, reach) {
|
|
81
|
-
const matched = kept === 'source' ? 'target' : 'source';
|
|
82
|
-
const from = q.from({ r: rows });
|
|
83
|
-
const joined = from
|
|
84
|
-
.where(({ r }) => every([eq(r.kind, 'reference'), ...(field === null ? [] : [inArray(field, r.forms)])]))
|
|
85
|
-
.innerJoin({ m: rows }, ({ r, m }) => eq(r[matched], m.key))
|
|
86
|
-
.where(({ m }) => scoped(scope, m, null, reach));
|
|
87
|
-
return narrowed(joined, scope.where, 'm')
|
|
88
|
-
.groupBy(({ r }) => r[kept])
|
|
89
|
-
.select(({ r }) => ({ key: r[kept] }));
|
|
90
|
-
}
|
|
91
|
-
function filtered(q, rows, plan) {
|
|
92
|
-
const from = q.from({ d: rows });
|
|
93
|
-
let query = narrowed(from.where(({ d }) => scoped(plan.root, d, plan.rooms, plan.reach)), plan.root.where, 'd');
|
|
94
|
-
if (plan.hop !== null) {
|
|
95
|
-
const hop = related(q, rows, plan.hop, plan.hop.field, 'source', plan.reach);
|
|
96
|
-
query = query.innerJoin({ h: hop }, ({ d, h }) => eq(d.key, h.key));
|
|
97
|
-
}
|
|
98
|
-
if (plan.backlinks !== null) {
|
|
99
|
-
const backlinks = related(q, rows, plan.backlinks, plan.backlinks.field, 'target', plan.reach);
|
|
100
|
-
query = query.innerJoin({ k: backlinks }, ({ d, k }) => eq(d.key, k.key));
|
|
101
|
-
}
|
|
102
|
-
return query;
|
|
103
|
-
}
|
|
104
|
-
function named(prefix, names, source) {
|
|
105
|
-
return Object.fromEntries(names.map((name, index) => [`${prefix}${index}`, source[name]]));
|
|
106
|
-
}
|
|
107
|
-
function documents(q, rows, plan, shape) {
|
|
108
|
-
let query = filtered(q, rows, plan);
|
|
109
|
-
if (shape.sections !== null || shape.preamble || shape.markdown) {
|
|
110
|
-
query = query.leftJoin({ b: rows }, ({ d, b }) => eq(d.body, b.key));
|
|
111
|
-
}
|
|
112
|
-
for (const { key, options } of shape.orderBy) {
|
|
113
|
-
query = query.orderBy(({ d }) => keyed(key, d), options);
|
|
114
|
-
}
|
|
115
|
-
if (shape.orderBy.length === 0 && plan.limit !== null) {
|
|
116
|
-
query = query.orderBy(({ d }) => d.key, { stringSort: 'lexical' });
|
|
117
|
-
}
|
|
118
|
-
if (plan.limit !== null)
|
|
119
|
-
query = query.limit(plan.limit);
|
|
120
|
-
return query.select(({ d, b }) => ({
|
|
121
|
-
room: d.room,
|
|
122
|
-
path: d.path,
|
|
123
|
-
type: d.type,
|
|
124
|
-
...(shape.fields === null ? {} : { fields: d.fields }),
|
|
125
|
-
...(shape.sections === 'all' ? { sections: b.sections } : {}),
|
|
126
|
-
...(Array.isArray(shape.sections) ? named('section', shape.sections, b.sections) : {}),
|
|
127
|
-
...(shape.preamble ? { preamble: b.preamble } : {}),
|
|
128
|
-
...(shape.markdown ? { markdown: b.markdown } : {}),
|
|
129
|
-
...(shape.backlinks ? { backlinks: toArray(backlinked(q, rows, d, plan.reach)) } : {}),
|
|
130
|
-
...(shape.change ? { change: d.change } : {}),
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
function backlinked(q, rows, document, reach) {
|
|
134
|
-
const from = q.from({ r: rows });
|
|
135
|
-
return from
|
|
136
|
-
.where(({ r }) => every([eq(r.target, document.key), ...reached(reach, r.room, r.source)]))
|
|
137
|
-
.orderBy(({ r }) => r.path, { stringSort: 'lexical' })
|
|
138
|
-
.orderBy(({ r }) => r.field, { stringSort: 'lexical' })
|
|
139
|
-
.select(({ r }) => ({ path: r.path, type: r.type, field: r.field }));
|
|
140
|
-
}
|
|
141
|
-
function groups(q, stage, shape, limit) {
|
|
142
|
-
const keys = shape.groupBy.map((_, index) => `key${index}`);
|
|
143
|
-
const from = q.from({ m: stage });
|
|
144
|
-
let query = from.groupBy(({ m }) => keys.map((key) => m[key]));
|
|
145
|
-
for (const { by, direction } of shape.orderBy) {
|
|
146
|
-
query = query.orderBy(({ m }) => (by === 'count' ? count(m.key) : m[keys[by]]), direction);
|
|
147
|
-
}
|
|
148
|
-
if (limit !== null && shape.orderBy.length > 0)
|
|
149
|
-
query = query.limit(limit);
|
|
150
|
-
return query.select(({ m }) => ({
|
|
151
|
-
...Object.fromEntries(keys.map((key) => [key, m[key]])),
|
|
152
|
-
count: count(m.key),
|
|
153
|
-
}));
|
|
154
|
-
}
|
|
155
|
-
function built(rows, plan) {
|
|
156
|
-
const shape = plan.shape;
|
|
157
|
-
if (shape.kind === 'documents') {
|
|
158
|
-
const collection = live((q) => documents(q, rows, plan, shape));
|
|
159
|
-
return { live: collection, dispose: () => void collection.cleanup() };
|
|
160
|
-
}
|
|
161
|
-
const stage = live((q) => filtered(q, rows, plan).select(({ d }) => ({
|
|
162
|
-
key: d.key,
|
|
163
|
-
...Object.fromEntries(shape.groupBy.map((key, index) => [`key${index}`, keyed(key, d)])),
|
|
164
|
-
})));
|
|
165
|
-
const collection = live((q) => groups(q, stage, shape, plan.limit));
|
|
166
|
-
return {
|
|
167
|
-
live: collection,
|
|
168
|
-
dispose: () => {
|
|
169
|
-
void collection.cleanup();
|
|
170
|
-
void stage.cleanup();
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
function present(entries) {
|
|
175
|
-
return Object.fromEntries(entries.filter(([, value]) => value !== undefined));
|
|
176
|
-
}
|
|
177
|
-
function part(row, prefix, names, whole) {
|
|
178
|
-
if (names === 'all')
|
|
179
|
-
return whole;
|
|
180
|
-
return present(names.map((name, index) => [name, row[`${prefix}${index}`]]));
|
|
181
|
-
}
|
|
182
|
-
function masked(pointers) {
|
|
183
|
-
const root = { whole: false, members: new Map() };
|
|
184
|
-
for (const pointer of pointers) {
|
|
185
|
-
let mask = root;
|
|
186
|
-
for (const token of pointerSegments(pointer)) {
|
|
187
|
-
const next = mask.members.get(token) ?? { whole: false, members: new Map() };
|
|
188
|
-
mask.members.set(token, next);
|
|
189
|
-
mask = next;
|
|
190
|
-
}
|
|
191
|
-
mask.whole = true;
|
|
192
|
-
}
|
|
193
|
-
return root;
|
|
194
|
-
}
|
|
195
|
-
function merged(left, right) {
|
|
196
|
-
if (left === undefined)
|
|
197
|
-
return right;
|
|
198
|
-
const members = new Map(left.members);
|
|
199
|
-
for (const [token, mask] of right.members)
|
|
200
|
-
members.set(token, merged(members.get(token), mask));
|
|
201
|
-
return { whole: left.whole || right.whole, members };
|
|
202
|
-
}
|
|
203
|
-
function cut(value, mask) {
|
|
204
|
-
if (mask.whole)
|
|
205
|
-
return value;
|
|
206
|
-
if (Array.isArray(value)) {
|
|
207
|
-
const each = {
|
|
208
|
-
whole: false,
|
|
209
|
-
members: new Map([...mask.members].filter(([token]) => !ARRAY_INDEX.test(token))),
|
|
210
|
-
};
|
|
211
|
-
const kept = [];
|
|
212
|
-
value.forEach((item, index) => {
|
|
213
|
-
const part = cut(item, merged(mask.members.get(String(index)), each));
|
|
214
|
-
if (part !== undefined)
|
|
215
|
-
kept[index] = part;
|
|
216
|
-
});
|
|
217
|
-
return kept.length === 0 ? undefined : kept;
|
|
218
|
-
}
|
|
219
|
-
if (typeof value !== 'object' || value === null)
|
|
220
|
-
return undefined;
|
|
221
|
-
const kept = Object.entries(value).flatMap(([key, held]) => {
|
|
222
|
-
const member = mask.members.get(key);
|
|
223
|
-
const part = member === undefined ? undefined : cut(held, member);
|
|
224
|
-
return part === undefined ? [] : [[key, part]];
|
|
225
|
-
});
|
|
226
|
-
return kept.length === 0 ? undefined : Object.fromEntries(kept);
|
|
227
|
-
}
|
|
228
|
-
function selected(fields, pointers) {
|
|
229
|
-
return (cut(fields, masked(pointers)) ?? {});
|
|
230
|
-
}
|
|
231
|
-
function documentOf(row, shape) {
|
|
232
|
-
if (row.type === null)
|
|
233
|
-
return { room: row.room, path: row.path };
|
|
234
|
-
return {
|
|
235
|
-
room: row.room,
|
|
236
|
-
path: row.path,
|
|
237
|
-
type: row.type,
|
|
238
|
-
...(shape.fields === null
|
|
239
|
-
? {}
|
|
240
|
-
: {
|
|
241
|
-
fields: shape.fields === 'all'
|
|
242
|
-
? row.fields
|
|
243
|
-
: selected(row.fields, shape.fields),
|
|
244
|
-
}),
|
|
245
|
-
...(shape.sections === null
|
|
246
|
-
? {}
|
|
247
|
-
: {
|
|
248
|
-
sections: part(row, 'section', shape.sections, row.sections),
|
|
249
|
-
}),
|
|
250
|
-
...(shape.preamble ? { preamble: row.preamble } : {}),
|
|
251
|
-
...(shape.markdown ? { markdown: row.markdown } : {}),
|
|
252
|
-
...(shape.backlinks
|
|
253
|
-
? {
|
|
254
|
-
backlinks: row.backlinks.map(({ path, type, field }) => ({ path, type, field })),
|
|
255
|
-
}
|
|
256
|
-
: {}),
|
|
257
|
-
...(shape.change ? { change: row.change } : {}),
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function keyedOf(plan, entries) {
|
|
261
|
-
const shape = plan.shape;
|
|
262
|
-
if (shape.kind === 'documents') {
|
|
263
|
-
return {
|
|
264
|
-
result: structuredClone({ documents: entries.map(([, row]) => documentOf(row, shape)) }),
|
|
265
|
-
keys: entries.map(([key]) => key),
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
const bounded = shape.orderBy.length === 0 && plan.limit !== null ? entries.slice(0, plan.limit) : entries;
|
|
269
|
-
return {
|
|
270
|
-
result: structuredClone({
|
|
271
|
-
groups: bounded.map(([, row]) => ({
|
|
272
|
-
key: shape.groupBy.map((_, index) => row[`key${index}`]),
|
|
273
|
-
count: row.count,
|
|
274
|
-
})),
|
|
275
|
-
}),
|
|
276
|
-
keys: bounded.map(([key]) => key),
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
export function reconciled(previous, next) {
|
|
280
|
-
const before = rowsOf(previous.result);
|
|
281
|
-
const held = new Map(previous.keys.map((key, index) => [key, before[index]]));
|
|
282
|
-
const changed = [];
|
|
283
|
-
const rows = rowsOf(next.result).map((row, index) => {
|
|
284
|
-
const key = next.keys[index];
|
|
285
|
-
const kept = held.get(key);
|
|
286
|
-
if (kept !== undefined && deepEquals(kept, row))
|
|
287
|
-
return kept;
|
|
288
|
-
changed.push([key, row]);
|
|
289
|
-
return row;
|
|
290
|
-
});
|
|
291
|
-
const present = new Set(next.keys);
|
|
292
|
-
const survivors = previous.keys.filter((key) => present.has(key));
|
|
293
|
-
const removed = previous.keys.filter((key) => !present.has(key));
|
|
294
|
-
const moved = survivors.length !== next.keys.length ||
|
|
295
|
-
survivors.some((key, index) => key !== next.keys[index]);
|
|
296
|
-
if (changed.length === 0 && removed.length === 0 && !moved)
|
|
297
|
-
return null;
|
|
298
|
-
return {
|
|
299
|
-
keyed: {
|
|
300
|
-
result: 'groups' in next.result
|
|
301
|
-
? { groups: rows }
|
|
302
|
-
: { documents: rows },
|
|
303
|
-
keys: next.keys,
|
|
304
|
-
},
|
|
305
|
-
change: { changed, removed, order: moved ? next.keys : null },
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
export function createReadSide() {
|
|
309
|
-
configureIndexDevMode({ enabled: false });
|
|
310
|
-
let sync;
|
|
311
|
-
const rows = createCollection({
|
|
312
|
-
getKey: (row) => row.key,
|
|
313
|
-
gcTime: 0,
|
|
314
|
-
startSync: true,
|
|
315
|
-
autoIndex: 'eager',
|
|
316
|
-
defaultIndexType: BasicIndex,
|
|
317
|
-
sync: {
|
|
318
|
-
rowUpdateMode: 'full',
|
|
319
|
-
sync: (params) => {
|
|
320
|
-
sync = params;
|
|
321
|
-
params.markReady();
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
});
|
|
325
|
-
const shared = new Map();
|
|
326
|
-
function searched(row) {
|
|
327
|
-
const body = rows.get(row.body);
|
|
328
|
-
return {
|
|
329
|
-
room: row.room,
|
|
330
|
-
path: row.path,
|
|
331
|
-
type: row.type,
|
|
332
|
-
fields: row.fields,
|
|
333
|
-
preamble: body.preamble,
|
|
334
|
-
sections: body.sections,
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
function publish(entry) {
|
|
338
|
-
const next = reconciled(entry.result, keyedOf(entry.plan, [...entry.built.live.entries()]));
|
|
339
|
-
if (next === null)
|
|
340
|
-
return;
|
|
341
|
-
entry.result = next.keyed;
|
|
342
|
-
for (const listener of entry.listeners)
|
|
343
|
-
listener(next.change);
|
|
344
|
-
}
|
|
345
|
-
return {
|
|
346
|
-
apply(set) {
|
|
347
|
-
const next = new Map();
|
|
348
|
-
for (const change of set.documents) {
|
|
349
|
-
for (const row of change.before)
|
|
350
|
-
next.set(row.key, null);
|
|
351
|
-
for (const row of change.after)
|
|
352
|
-
next.set(row.key, row);
|
|
353
|
-
}
|
|
354
|
-
if (next.size === 0)
|
|
355
|
-
return;
|
|
356
|
-
sync.begin();
|
|
357
|
-
for (const [key, row] of next) {
|
|
358
|
-
if (row === null) {
|
|
359
|
-
if (rows.has(key))
|
|
360
|
-
sync.write({ type: 'delete', key });
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
sync.write({ type: rows.has(key) ? 'update' : 'insert', value: row });
|
|
364
|
-
}
|
|
365
|
-
sync.commit();
|
|
366
|
-
},
|
|
367
|
-
async query(plan) {
|
|
368
|
-
const { live: collection, dispose } = built(rows, plan);
|
|
369
|
-
try {
|
|
370
|
-
await collection.toArrayWhenReady();
|
|
371
|
-
return keyedOf(plan, [...collection.entries()]).result;
|
|
372
|
-
}
|
|
373
|
-
finally {
|
|
374
|
-
dispose();
|
|
375
|
-
}
|
|
376
|
-
},
|
|
377
|
-
watch(plan, identity, deliver) {
|
|
378
|
-
let entry = shared.get(identity);
|
|
379
|
-
if (entry === undefined) {
|
|
380
|
-
const created = {
|
|
381
|
-
plan,
|
|
382
|
-
built: built(rows, plan),
|
|
383
|
-
result: undefined,
|
|
384
|
-
listeners: new Set(),
|
|
385
|
-
subscription: null,
|
|
386
|
-
};
|
|
387
|
-
created.built.live.on('status:change', ({ status }) => {
|
|
388
|
-
if (status === 'cleaned-up' && created.listeners.size === 0)
|
|
389
|
-
shared.delete(identity);
|
|
390
|
-
});
|
|
391
|
-
shared.set(identity, created);
|
|
392
|
-
entry = created;
|
|
393
|
-
}
|
|
394
|
-
const observed = entry;
|
|
395
|
-
observed.listeners.add(deliver);
|
|
396
|
-
observed.built.live.onFirstReady(() => {
|
|
397
|
-
if (!observed.listeners.has(deliver))
|
|
398
|
-
return;
|
|
399
|
-
if (observed.subscription === null) {
|
|
400
|
-
observed.result = keyedOf(observed.plan, [...observed.built.live.entries()]);
|
|
401
|
-
observed.subscription = observed.built.live.subscribeChanges(() => {
|
|
402
|
-
publish(observed);
|
|
403
|
-
}, { includeInitialState: false });
|
|
404
|
-
}
|
|
405
|
-
deliver(observed.result);
|
|
406
|
-
});
|
|
407
|
-
return () => {
|
|
408
|
-
if (!observed.listeners.delete(deliver) || observed.listeners.size > 0)
|
|
409
|
-
return;
|
|
410
|
-
observed.subscription?.unsubscribe();
|
|
411
|
-
observed.subscription = null;
|
|
412
|
-
};
|
|
413
|
-
},
|
|
414
|
-
documents() {
|
|
415
|
-
return rows.toArray
|
|
416
|
-
.filter((row) => row.kind === 'document' && row.type !== null)
|
|
417
|
-
.map(searched);
|
|
418
|
-
},
|
|
419
|
-
document(room, path) {
|
|
420
|
-
const row = rows.get(documentKey(room, path));
|
|
421
|
-
return row === undefined || row.type === null ? null : searched(row);
|
|
422
|
-
},
|
|
423
|
-
close() {
|
|
424
|
-
for (const entry of shared.values()) {
|
|
425
|
-
entry.listeners.clear();
|
|
426
|
-
entry.subscription?.unsubscribe();
|
|
427
|
-
entry.built.dispose();
|
|
428
|
-
}
|
|
429
|
-
shared.clear();
|
|
430
|
-
void rows.cleanup();
|
|
431
|
-
},
|
|
432
|
-
};
|
|
433
|
-
}
|