@omgbase/core 0.21.0 → 0.23.0
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/dist/src/core/ids.d.ts +1 -1
- package/dist/src/core/read/document.d.ts +4 -1
- package/dist/src/core/read/document.js +18 -6
- package/dist/src/core/store/archive.d.ts +196 -0
- package/dist/src/core/store/archive.js +606 -0
- package/dist/src/core/store/gc.d.ts +25 -4
- package/dist/src/core/store/gc.js +43 -28
- package/dist/src/core/store/rebuild.d.ts +2 -0
- package/dist/src/core/store/rebuild.js +8 -2
- package/dist/src/core/store/retention.d.ts +138 -0
- package/dist/src/core/store/retention.js +409 -0
- package/dist/src/core/store/schema.d.ts +3 -2
- package/dist/src/core/store/schema.js +30 -4
- package/dist/src/core/store/size.d.ts +21 -2
- package/dist/src/core/store/size.js +24 -3
- package/dist/src/core/store/store.d.ts +1 -0
- package/dist/src/core/store/store.js +53 -1
- package/dist/src/graph/history.d.ts +2 -0
- package/dist/src/graph/history.js +8 -4
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.js +3 -0
- package/dist/src/mcp/errors.d.ts +1 -1
- package/dist/src/mcp/errors.js +4 -0
- package/dist/src/mcp/reference.d.ts +1 -1
- package/dist/src/mcp/reference.js +24 -6
- package/dist/src/mcp/server.js +2 -2
- package/dist/src/oqx-js/context.js +21 -5
- package/dist/src/oqx-js/dates.d.ts +105 -0
- package/dist/src/oqx-js/dates.js +427 -0
- package/dist/src/oqx-js/names.js +14 -3
- package/dist/src/oqx-js/planner.js +17 -2
- package/dist/src/oqx-js/run.d.ts +1 -0
- package/dist/src/oqx-js/run.js +66 -1
- package/dist/src/spec-versions.d.ts +4 -4
- package/dist/src/spec-versions.js +3 -3
- package/package.json +2 -2
package/dist/src/oqx-js/run.js
CHANGED
|
@@ -9,6 +9,7 @@ import { makeStoreContext, rowRef } from "./context.js";
|
|
|
9
9
|
import { SQLiteQueryPlanner } from "./planner.js";
|
|
10
10
|
import { REPO_REMOVED_MESSAGE, ROOTS, bareTargetMessage, pastRootMessage, unknownTargetMessage } from "./root-row.js";
|
|
11
11
|
import { checkNames } from "./names.js";
|
|
12
|
+
import { DATE_FUNCTIONS, DATE_METHODS, dateFunction, dateMethod } from "./dates.js";
|
|
12
13
|
import { FilterInvalid } from "../search/cel/parser.js";
|
|
13
14
|
import { float32ToBlob } from "../core/vec.js";
|
|
14
15
|
import { encodeCursor as encodeKeyset, decodePathCursor } from "../core/cursor.js";
|
|
@@ -91,8 +92,32 @@ export function checkRootSpellings(q) {
|
|
|
91
92
|
},
|
|
92
93
|
});
|
|
93
94
|
}
|
|
95
|
+
// Dates over literals fold to literals (spec/surface §1.3 "Dates and
|
|
96
|
+
// durations", 4.8): `date("today")`, `dur("30 days")`, and a date method whose
|
|
97
|
+
// receiver and arguments are literals (`date("today").minus(dur("30 days"))`,
|
|
98
|
+
// folded inside-out since `transform` maps children first) become the string /
|
|
99
|
+
// number / null they evaluate to — by the SAME functions the context runs, so
|
|
100
|
+
// nothing changes in meaning — before the planner sees the tree. So `where
|
|
101
|
+
// updated_at < date("today")` is a text-vs-text comparison the translator
|
|
102
|
+
// pushes down (a call is otherwise an unconditional decline), and a named point
|
|
103
|
+
// is resolved ONCE per query. A call with the wrong arity is left in place: it
|
|
104
|
+
// raises when evaluated, and an empty source never evaluates it (spec/oqx §11).
|
|
105
|
+
const isLit = (e) => e.kind === "lit";
|
|
106
|
+
export function foldDates(e) {
|
|
107
|
+
if (e.kind !== "call" || !e.args.every(isLit))
|
|
108
|
+
return e;
|
|
109
|
+
const args = e.args.map((a) => a.value);
|
|
110
|
+
if (e.recv === null) {
|
|
111
|
+
if (!Object.hasOwn(DATE_FUNCTIONS, e.name) || DATE_FUNCTIONS[e.name] !== args.length)
|
|
112
|
+
return e;
|
|
113
|
+
return build.lit(dateFunction(e.name, args).value);
|
|
114
|
+
}
|
|
115
|
+
if (!isLit(e.recv) || !Object.hasOwn(DATE_METHODS, e.name) || DATE_METHODS[e.name] !== args.length)
|
|
116
|
+
return e;
|
|
117
|
+
return build.lit(dateMethod(e.name, e.recv.value, args).value);
|
|
118
|
+
}
|
|
94
119
|
function rewriteQuery(q) {
|
|
95
|
-
return transform(q, (e) => (e.kind === "call" && e.recv === null && ROW_FNS.has(e.name) ? { ...e, recv: build.ident("$self") } : rootPathLiterals(e)));
|
|
120
|
+
return transform(q, (e) => (e.kind === "call" && e.recv === null && ROW_FNS.has(e.name) ? { ...e, recv: build.ident("$self") } : foldDates(rootPathLiterals(e))));
|
|
96
121
|
}
|
|
97
122
|
// A top-level `limit`/`offset` on the collect path is applied by the runner (see
|
|
98
123
|
// oqxRunInner), so it must be a plain number literal here — there is no row to
|
|
@@ -347,6 +372,18 @@ function runResolved(store, repoId, raw, opts) {
|
|
|
347
372
|
const res = engine.run(parsed, []);
|
|
348
373
|
return { hits: [], truncated: false, cursor: null, consumer: "none", none: res.consumer === "none" ? res.none : true };
|
|
349
374
|
}
|
|
375
|
+
// A grouped query (oqx 0.24, SEMANTICS §24) yields GROUPS, not store rows:
|
|
376
|
+
// the envelope does not apply — there is no `id`/`path` to inject and no
|
|
377
|
+
// keyset to page by — so a hit is the group's projection as the query wrote
|
|
378
|
+
// it (`{ layer, n }`), exactly what `bare` yields for a row query; `bare` is
|
|
379
|
+
// accepted and changes nothing. Rows that surface as values (`rows collect {
|
|
380
|
+
// }` with an empty projection, `collect(doc)`) render as `{ id, path }` refs
|
|
381
|
+
// like every row-as-value. Paging is by position: the query's own
|
|
382
|
+
// `limit`/`offset` define the set, the tool's `limit` takes the first page,
|
|
383
|
+
// `truncated` says whether more groups follow, the cursor is always null (as
|
|
384
|
+
// under a custom `order by`). `distinct` cannot occur (a parse error).
|
|
385
|
+
if (parsed.groupBy)
|
|
386
|
+
return runGrouped(engine, parsed, consumer, opts);
|
|
350
387
|
// collect / first / single: inject id + path so every hit carries them. A
|
|
351
388
|
// top-level `select distinct` is applied HERE, not in the engine: the injected
|
|
352
389
|
// id/path are unique per row and would defeat the engine's projection dedup, so
|
|
@@ -417,6 +454,34 @@ function runResolved(store, repoId, raw, opts) {
|
|
|
417
454
|
return { hits: [], truncated, cursor, consumer: "collect", values: page.map((s) => s.proj[VALUE_KEY]) };
|
|
418
455
|
return { hits: page.map(render), truncated, cursor, consumer: "collect" };
|
|
419
456
|
}
|
|
457
|
+
// The collect/first/single path of a grouped query (see `runResolved`).
|
|
458
|
+
function runGrouped(engine, parsed, consumer, opts) {
|
|
459
|
+
const topValues = parsed.values;
|
|
460
|
+
// A `values` projection rides as a record under VALUE_KEY and is peeled off
|
|
461
|
+
// the page, as on the row path.
|
|
462
|
+
const select = topValues ? [{ ...parsed.select[0], name: VALUE_KEY }] : parsed.select;
|
|
463
|
+
const { limit: topLimit, offset: topOffset } = parsed;
|
|
464
|
+
const base = consumer === "collect" ? { ...parsed, limit: null, offset: null } : parsed;
|
|
465
|
+
const res = engine.run({ ...base, values: false, select }, []);
|
|
466
|
+
const project = (row) => renderValue(row);
|
|
467
|
+
if (consumer === "first" || consumer === "single") {
|
|
468
|
+
const row = res.consumer === "first" || res.consumer === "single" ? res.row : null;
|
|
469
|
+
if (topValues)
|
|
470
|
+
return { hits: [], truncated: false, cursor: null, consumer, values: row == null ? [] : [project(row)[VALUE_KEY]] };
|
|
471
|
+
return { hits: row == null ? [] : [project(row)], truncated: false, cursor: null, consumer };
|
|
472
|
+
}
|
|
473
|
+
let groups = (res.consumer === "collect" ? res.rows : []).map(project);
|
|
474
|
+
const offset = constBound(topOffset, "offset") ?? 0;
|
|
475
|
+
const limit = constBound(topLimit, "limit");
|
|
476
|
+
if (offset || limit != null)
|
|
477
|
+
groups = groups.slice(offset, limit == null ? undefined : offset + limit);
|
|
478
|
+
const cap = opts.limit ?? 50;
|
|
479
|
+
const truncated = groups.length > cap;
|
|
480
|
+
const page = groups.slice(0, cap);
|
|
481
|
+
if (topValues)
|
|
482
|
+
return { hits: [], truncated, cursor: null, consumer: "collect", values: page.map((g) => g[VALUE_KEY]) };
|
|
483
|
+
return { hits: page, truncated, cursor: null, consumer: "collect" };
|
|
484
|
+
}
|
|
420
485
|
export async function oqxRunAsync(store, repoId, source, opts = {}, embedQuery) {
|
|
421
486
|
const phrases = collectSemanticPhrases(source);
|
|
422
487
|
if (phrases.length === 0)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export declare const SPEC_VERSIONS: {
|
|
2
|
-
readonly oqx: "0.
|
|
2
|
+
readonly oqx: "0.24";
|
|
3
3
|
readonly format: "0.2";
|
|
4
4
|
readonly reconcile: "2.3";
|
|
5
|
-
readonly store: "
|
|
5
|
+
readonly store: "15.0";
|
|
6
6
|
readonly properties: "1.1";
|
|
7
7
|
readonly graph: "1.1";
|
|
8
8
|
readonly search: "2.0";
|
|
9
9
|
readonly mutate: "3.5";
|
|
10
10
|
readonly sync: "2.2";
|
|
11
|
-
readonly surface: "4.
|
|
12
|
-
readonly cli: "4.
|
|
11
|
+
readonly surface: "4.9";
|
|
12
|
+
readonly cli: "4.6";
|
|
13
13
|
};
|
|
14
14
|
export type SpecName = keyof typeof SPEC_VERSIONS;
|
|
@@ -13,13 +13,13 @@ export const SPEC_VERSIONS = {
|
|
|
13
13
|
oqx: LANGUAGE_VERSION,
|
|
14
14
|
format: "0.2",
|
|
15
15
|
reconcile: "2.3",
|
|
16
|
-
store: "
|
|
16
|
+
store: "15.0",
|
|
17
17
|
properties: "1.1",
|
|
18
18
|
graph: "1.1",
|
|
19
19
|
search: "2.0",
|
|
20
20
|
mutate: "3.5",
|
|
21
21
|
sync: "2.2",
|
|
22
|
-
surface: "4.
|
|
23
|
-
cli: "4.
|
|
22
|
+
surface: "4.9",
|
|
23
|
+
cli: "4.6",
|
|
24
24
|
};
|
|
25
25
|
//# sourceMappingURL=spec-versions.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omgbase/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Open Markdown Graph Base — embedded engine",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
58
|
-
"@omgbase/oqx": "^0.
|
|
58
|
+
"@omgbase/oqx": "^0.24.0",
|
|
59
59
|
"better-sqlite3": "^13.0.3",
|
|
60
60
|
"mdast-util-from-markdown": "^2.0.2",
|
|
61
61
|
"mdast-util-frontmatter": "^2.0.1",
|