@mnmal-ai/substrate-nl 1.0.0-alpha.12 → 1.0.0-alpha.14
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 +2 -1
- package/dist/ask/run.d.ts.map +1 -1
- package/dist/{bootstrap-CLYwjrrl.js → bootstrap-DbMpquDD.js} +281 -26
- package/dist/bootstrap.js +1 -1
- package/dist/index.js +1 -1
- package/dist/parse/parse.d.ts.map +1 -1
- package/dist/parse/time.d.ts +13 -5
- package/dist/parse/time.d.ts.map +1 -1
- package/dist/parse/walks.d.ts +6 -0
- package/dist/parse/walks.d.ts.map +1 -1
- package/dist/routes.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,7 +4,8 @@ Natural-language ask surface. A deterministic parser reads a question against a
|
|
|
4
4
|
|
|
5
5
|
## Contract
|
|
6
6
|
|
|
7
|
-
- `POST /substrate/v1/nl` with `{ namespace, question, project?, type? }` returns one of `rows`, `recall`, `clarify` or `refuse`, plus a `trail` of how it got there. Send `accept: text/event-stream` for the same as SSE events (`parsed`, `judging`, `judged`, then the outcome, then `done`), otherwise it is one JSON body.
|
|
7
|
+
- `POST /substrate/v1/nl` with `{ namespace, question, project?, type?, asOf? }` returns one of `rows`, `recall`, `clarify` or `refuse`, plus a `trail` of how it got there. Send `accept: text/event-stream` for the same as SSE events (`parsed`, `judging`, `judged`, then the outcome, then `done`), otherwise it is one JSON body.
|
|
8
|
+
- `asOf` is "now" for relative dates ("yesterday", "last week") and for the year of a month-day ("on Oct 23"): an ISO-8601 date-time with an offset, such as `2026-10-02T12:00:00-05:00`. Day boundaries are in its offset. Anything else is `400 invalid_params`. Without it the server clock is used. The `parsed` event's `asOf` says which clock the question was read against.
|
|
8
9
|
- `GET /substrate/v1/nl/pack/<ns>` returns the namespace pack (types, fields, values, rulings) with an `etag`; send `if-none-match` for a `304`.
|
|
9
10
|
- NL is read-only: a mutation-shaped question is `refuse`, never executed.
|
|
10
11
|
|
package/dist/ask/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/ask/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAGf,KAAK,gBAAgB,EAGtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,KAAK,KAAK,EAAqC,MAAM,mBAAmB,CAAC;AAElF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAa,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAmCD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,GAAG,UAAU,EAAE,CA2B9F;AAuID,wBAAuB,MAAM,CAC3B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,OAAO,GACZ,cAAc,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/ask/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAGf,KAAK,gBAAgB,EAGtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,KAAK,KAAK,EAAqC,MAAM,mBAAmB,CAAC;AAElF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAa,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAmCD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,GAAG,UAAU,EAAE,CA2B9F;AAuID,wBAAuB,MAAM,CAC3B,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,OAAO,GACZ,cAAc,CAAC,OAAO,CAAC,CAgJzB"}
|
|
@@ -201,14 +201,28 @@ const WEEKDAYS = [
|
|
|
201
201
|
"friday",
|
|
202
202
|
"saturday"
|
|
203
203
|
];
|
|
204
|
+
/** An ISO-8601 date-time with an offset: the only accepted `asOf`. */
|
|
205
|
+
const AS_OF = /^(\d{4})-(\d{2})-(\d{2})T[\d:.]+(Z|[+-]\d{2}:\d{2})$/;
|
|
206
|
+
/** True when `asOf` is an ISO-8601 date-time with an offset naming a real instant. */
|
|
207
|
+
function validAsOf(asOf) {
|
|
208
|
+
if (typeof asOf !== "string") return false;
|
|
209
|
+
const m = AS_OF.exec(asOf);
|
|
210
|
+
if (m === null || !Number.isFinite(Date.parse(asOf))) return false;
|
|
211
|
+
const [y, mo, d] = [
|
|
212
|
+
Number(m[1]),
|
|
213
|
+
Number(m[2]),
|
|
214
|
+
Number(m[3])
|
|
215
|
+
];
|
|
216
|
+
return new Date(Date.UTC(y, mo - 1, d)).getUTCDate() === d;
|
|
217
|
+
}
|
|
204
218
|
/**
|
|
205
219
|
* The range a time phrase names, relative to `asOf` and in its offset:
|
|
206
220
|
* today, yesterday, this/last week (weeks start Monday), this/last month,
|
|
207
|
-
* rolling "past <unit>" and "last N <units>", "since <weekday>"
|
|
208
|
-
* the phrase is not a time phrase.
|
|
221
|
+
* rolling "past <unit>" and "last N <units>", "since <weekday>"; and explicit
|
|
222
|
+
* dates (see `explicitRange`). Null when the phrase is not a time phrase.
|
|
209
223
|
*/
|
|
210
224
|
function rangeFor(phrase, asOf) {
|
|
211
|
-
const m =
|
|
225
|
+
const m = AS_OF.exec(asOf);
|
|
212
226
|
if (m === null) throw new Error(`asOf must be ISO-8601 with an offset: ${asOf}`);
|
|
213
227
|
const [, y, mo, d, offset] = m;
|
|
214
228
|
const today = Date.UTC(Number(y), Number(mo) - 1, Number(d));
|
|
@@ -268,6 +282,99 @@ function rangeFor(phrase, asOf) {
|
|
|
268
282
|
lt: at(today + day)
|
|
269
283
|
};
|
|
270
284
|
}
|
|
285
|
+
return explicitRange(phrase, today, at, offset);
|
|
286
|
+
}
|
|
287
|
+
const MONTHS = [
|
|
288
|
+
"january",
|
|
289
|
+
"february",
|
|
290
|
+
"march",
|
|
291
|
+
"april",
|
|
292
|
+
"may",
|
|
293
|
+
"june",
|
|
294
|
+
"july",
|
|
295
|
+
"august",
|
|
296
|
+
"september",
|
|
297
|
+
"october",
|
|
298
|
+
"november",
|
|
299
|
+
"december"
|
|
300
|
+
];
|
|
301
|
+
const DAY_MS = 864e5;
|
|
302
|
+
/**
|
|
303
|
+
* Explicit dates, always after a lead word: "on D" (that day), "from D to D" and
|
|
304
|
+
* "between D and D" (inclusive of the last day), "since D" / "after D" (from
|
|
305
|
+
* D / the day after), "before D" / "until D" (before D / through D). A date
|
|
306
|
+
* is ISO `YYYY-MM-DD`, an ISO date-time (an exact instant), or a month name
|
|
307
|
+
* (full, three-letter, or "sept") with a day, optional ordinal and optional year, in
|
|
308
|
+
* either order. A month-day without a year is the most recent one not after
|
|
309
|
+
* `today`. An invalid date is not a date.
|
|
310
|
+
*/
|
|
311
|
+
function explicitRange(phrase, today, at, offset) {
|
|
312
|
+
const operand = (words) => {
|
|
313
|
+
if (words.length === 1) {
|
|
314
|
+
const w = words[0];
|
|
315
|
+
const iso = /^(\d{4})-(\d{2})-(\d{2})$/.exec(w);
|
|
316
|
+
if (iso !== null) return dayOf(Number(iso[1]), Number(iso[2]), Number(iso[3]));
|
|
317
|
+
const dt = /^(\d{4})-(\d{2})-(\d{2})t((?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?)(z|[+-](?:[01]\d|2[0-3]):[0-5]\d)?$/.exec(w);
|
|
318
|
+
if (dt === null || dayOf(Number(dt[1]), Number(dt[2]), Number(dt[3])) === null) return null;
|
|
319
|
+
const instant = `${dt[1]}-${dt[2]}-${dt[3]}T${dt[4]}${dt[5] === void 0 ? offset : dt[5].toUpperCase()}`;
|
|
320
|
+
return {
|
|
321
|
+
start: instant,
|
|
322
|
+
end: instant
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
if (words.length !== 2 && words.length !== 3) return null;
|
|
326
|
+
const [a = "", b = "", year] = words;
|
|
327
|
+
const month = (w) => MONTHS.findIndex((m) => w === m || w.length === 3 && m.startsWith(w)) + 1 || (w === "sept" ? 9 : 0);
|
|
328
|
+
const dom = (w) => /^(\d{1,2})(?:st|nd|rd|th)?$/.exec(w)?.[1];
|
|
329
|
+
const [mo, d] = month(a) > 0 ? [month(a), dom(b)] : [month(b), dom(a)];
|
|
330
|
+
if (mo === 0 || d === void 0) return null;
|
|
331
|
+
if (year !== void 0) return /^\d{4}$/.test(year) ? dayOf(Number(year), mo, Number(d)) : null;
|
|
332
|
+
for (let y = new Date(today).getUTCFullYear(), n = 0; n < 8; y--, n++) {
|
|
333
|
+
const t = Date.UTC(y, mo - 1, Number(d));
|
|
334
|
+
if (t <= today && valid(y, mo, Number(d))) return {
|
|
335
|
+
start: at(t),
|
|
336
|
+
end: at(t + DAY_MS)
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return null;
|
|
340
|
+
};
|
|
341
|
+
const valid = (y, mo, d) => {
|
|
342
|
+
const t = new Date(Date.UTC(y, mo - 1, d));
|
|
343
|
+
return t.getUTCFullYear() === y && t.getUTCMonth() === mo - 1 && t.getUTCDate() === d;
|
|
344
|
+
};
|
|
345
|
+
const dayOf = (y, mo, d) => {
|
|
346
|
+
if (!valid(y, mo, d)) return null;
|
|
347
|
+
const t = Date.UTC(y, mo - 1, d);
|
|
348
|
+
return {
|
|
349
|
+
start: at(t),
|
|
350
|
+
end: at(t + DAY_MS)
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
const [head = "", ...rest] = phrase.split(" ");
|
|
354
|
+
if (head === "from" || head === "between") {
|
|
355
|
+
const sep = head === "from" ? "to" : "and";
|
|
356
|
+
const i = rest.indexOf(sep);
|
|
357
|
+
if (i < 0) return null;
|
|
358
|
+
const x = operand(rest.slice(0, i));
|
|
359
|
+
const y = operand(rest.slice(i + 1));
|
|
360
|
+
if (x === null || y === null || Date.parse(y.end) <= Date.parse(x.start)) return null;
|
|
361
|
+
return {
|
|
362
|
+
gte: x.start,
|
|
363
|
+
lt: y.end
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const o = operand(rest);
|
|
367
|
+
if (o === null) return null;
|
|
368
|
+
switch (head) {
|
|
369
|
+
case "on": return o.start === o.end ? null : {
|
|
370
|
+
gte: o.start,
|
|
371
|
+
lt: o.end
|
|
372
|
+
};
|
|
373
|
+
case "since": return { gte: o.start };
|
|
374
|
+
case "after": return { gte: o.end };
|
|
375
|
+
case "before": return { lt: o.start };
|
|
376
|
+
case "until": return { lt: o.end };
|
|
377
|
+
}
|
|
271
378
|
return null;
|
|
272
379
|
}
|
|
273
380
|
|
|
@@ -685,7 +792,13 @@ function compose(input) {
|
|
|
685
792
|
w.pick = pick;
|
|
686
793
|
}
|
|
687
794
|
let seedLatest;
|
|
795
|
+
let seedOrder;
|
|
688
796
|
for (const k of claims.picks) if (k.phrase.type === seed && k.kind === "latest") seedLatest = k.span;
|
|
797
|
+
else if (k.phrase.type === seed && (k.span === "highest" || k.span === "lowest") && k.phrase.entry.value === void 0) seedOrder = {
|
|
798
|
+
span: `${k.span} ${k.phrase.span}`,
|
|
799
|
+
dir: k.kind === "max" ? "desc" : "asc",
|
|
800
|
+
phrase: k.phrase
|
|
801
|
+
};
|
|
689
802
|
else if (k.phrase.type === seed) dropped.push({
|
|
690
803
|
span: `${k.span} ${k.phrase.span}`,
|
|
691
804
|
reason: `"${k.span}" picks one neighbour, and ${seed} is the type being asked about`,
|
|
@@ -821,10 +934,7 @@ function compose(input) {
|
|
|
821
934
|
else {
|
|
822
935
|
const field = timeField(type);
|
|
823
936
|
const ruled = own(rulings.timeField, type) !== void 0;
|
|
824
|
-
w.window.push(filter({ [field]: {
|
|
825
|
-
gte: input.time.range.gte,
|
|
826
|
-
lt: input.time.range.lt
|
|
827
|
-
} }, [field], `window:${input.time.span}${ruled ? "" : ` on ${field} (default)`}`));
|
|
937
|
+
w.window.push(filter({ [field]: { ...input.time.range } }, [field], `window:${input.time.span}${ruled ? "" : ` on ${field} (default)`}`));
|
|
828
938
|
}
|
|
829
939
|
}
|
|
830
940
|
}
|
|
@@ -918,6 +1028,7 @@ function compose(input) {
|
|
|
918
1028
|
dropped,
|
|
919
1029
|
timeOnSeed,
|
|
920
1030
|
...seedLatest !== void 0 ? { seedLatest } : {},
|
|
1031
|
+
...seedOrder !== void 0 ? { seedOrder } : {},
|
|
921
1032
|
walked: walks.size > 0 || seedParts.some((p) => p.plan.some((c) => c.kind === "ref")) || plan.length > 0,
|
|
922
1033
|
strict: pickDropped || ordered.some((w) => w.pick !== void 0) || composed.some((p) => p.plan.some((c) => c.kind === "ref"))
|
|
923
1034
|
};
|
|
@@ -1092,7 +1203,7 @@ function parseQuestion(question, pack, ctx) {
|
|
|
1092
1203
|
const tokens = (question.replace(CLAUSE, (span, _q, field, raw) => {
|
|
1093
1204
|
clauses.push(parseClause(span, field, raw));
|
|
1094
1205
|
return " ";
|
|
1095
|
-
}).toLowerCase().replace(/[‘’]/g, "'").match(
|
|
1206
|
+
}).toLowerCase().replace(/[‘’]/g, "'").match(/\d{4}-\d{2}-\d{2}t\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:z|[+-]\d{2}:\d{2})?|\$\d+(?:\.\d+)?|\d+(?:\.\d+)?[%×]|#\d+|[a-z0-9@[][a-z0-9@._'\]-]*/g) ?? []).map((t) => t.replace(/[.'-]+$/, "").replace(/'s$/, "")).filter((t) => t.length > 0).map((text) => ({
|
|
1096
1207
|
text,
|
|
1097
1208
|
used: false
|
|
1098
1209
|
}));
|
|
@@ -1141,8 +1252,9 @@ function parseQuestion(question, pack, ctx) {
|
|
|
1141
1252
|
if (time !== null) evidence.push({
|
|
1142
1253
|
span: time.span,
|
|
1143
1254
|
role: "time",
|
|
1144
|
-
detail: `${time.range.gte} .. ${time.range.lt}
|
|
1255
|
+
detail: `${time.range.gte ?? ""} .. ${time.range.lt ?? ""}`.trim()
|
|
1145
1256
|
});
|
|
1257
|
+
const fieldOrder = claimFieldOrder(tokens, walkClaims, pack, rulings);
|
|
1146
1258
|
const ids = [];
|
|
1147
1259
|
let bareNumber = false;
|
|
1148
1260
|
tokens.forEach((t, i) => {
|
|
@@ -1387,6 +1499,8 @@ function parseQuestion(question, pack, ctx) {
|
|
|
1387
1499
|
clauses,
|
|
1388
1500
|
time: composed === void 0 || composed.timeOnSeed ? time : null,
|
|
1389
1501
|
order,
|
|
1502
|
+
fieldOrder: fieldOrder ?? composed?.seedOrder ?? null,
|
|
1503
|
+
plural: mentioned.get(type)?.plural ?? false,
|
|
1390
1504
|
count,
|
|
1391
1505
|
allProjects,
|
|
1392
1506
|
historyWord,
|
|
@@ -1447,15 +1561,46 @@ function assemble(type, a) {
|
|
|
1447
1561
|
detail: "desc, limit 1"
|
|
1448
1562
|
}] : a.evidence;
|
|
1449
1563
|
const recency = a.order ?? (seedLatest !== void 0 ? "desc" : null);
|
|
1450
|
-
const
|
|
1564
|
+
const derived = a.composed?.params.orderBy !== void 0;
|
|
1565
|
+
const fieldOrder = [];
|
|
1566
|
+
let sortBy = null;
|
|
1567
|
+
if (a.fieldOrder !== null && a.count) fieldOrder.push({
|
|
1568
|
+
span: a.fieldOrder.span,
|
|
1569
|
+
reason: "ordering does not apply to a count",
|
|
1570
|
+
kind: "filter"
|
|
1571
|
+
});
|
|
1572
|
+
if (a.fieldOrder !== null && !a.count) {
|
|
1573
|
+
const r = orderField(a.fieldOrder, type, pack, rulings);
|
|
1574
|
+
const reason = "reason" in r ? r.reason : derived ? "it conflicts with the derived ordering, which is kept" : null;
|
|
1575
|
+
if (reason !== null) fieldOrder.push({
|
|
1576
|
+
span: a.fieldOrder.span,
|
|
1577
|
+
reason,
|
|
1578
|
+
kind: "order"
|
|
1579
|
+
});
|
|
1580
|
+
else if ("field" in r) sortBy = {
|
|
1581
|
+
field: r.field,
|
|
1582
|
+
dir: a.fieldOrder.dir,
|
|
1583
|
+
limit: a.fieldOrder.limit ?? (a.plural ? 10 : 1)
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
const conflict = (derived || sortBy !== null) && recency !== null;
|
|
1451
1587
|
const order = conflict ? null : recency;
|
|
1452
1588
|
const orderSpan = evidence.find((e) => e.role === "order")?.span ?? "";
|
|
1453
1589
|
const ev = conflict ? evidence.filter((e) => e.role !== "order") : [...evidence];
|
|
1454
|
-
|
|
1455
|
-
span:
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
}
|
|
1590
|
+
if (sortBy !== null) ev.push({
|
|
1591
|
+
span: a.fieldOrder?.span ?? "",
|
|
1592
|
+
role: "order",
|
|
1593
|
+
detail: `${sortBy.field} ${sortBy.dir}, limit ${sortBy.limit}`
|
|
1594
|
+
});
|
|
1595
|
+
const dropped = [
|
|
1596
|
+
...a.composed?.dropped ?? [],
|
|
1597
|
+
...fieldOrder,
|
|
1598
|
+
...conflict ? [{
|
|
1599
|
+
span: orderSpan,
|
|
1600
|
+
reason: `it conflicts with the ${derived ? "derived" : "field"} ordering, which is kept`,
|
|
1601
|
+
kind: "order"
|
|
1602
|
+
}] : []
|
|
1603
|
+
];
|
|
1459
1604
|
const where = [];
|
|
1460
1605
|
const wherePlan = /* @__PURE__ */ new Map();
|
|
1461
1606
|
const yields = [];
|
|
@@ -1510,6 +1655,8 @@ function assemble(type, a) {
|
|
|
1510
1655
|
}
|
|
1511
1656
|
for (const field of usedFields) creditFieldWords(tokens, fields[field]);
|
|
1512
1657
|
if (a.author !== null) where.push({ createdById: { startsWith: a.author } });
|
|
1658
|
+
const orderExclude = a.fieldOrder?.phrase?.entry.exclude;
|
|
1659
|
+
if (sortBy !== null && orderExclude !== void 0) where.push({ NOT: orderExclude });
|
|
1513
1660
|
for (const flag of a.flags) {
|
|
1514
1661
|
usedFields.add(flag.detail);
|
|
1515
1662
|
where.push({ [flag.detail]: { eq: true } });
|
|
@@ -1535,10 +1682,7 @@ function assemble(type, a) {
|
|
|
1535
1682
|
if (a.time !== null) {
|
|
1536
1683
|
const named = Object.entries(fields).find(([, f]) => f.valueType === "date" && f.kind !== "metadata" && creditFieldWords(tokens, f));
|
|
1537
1684
|
const dateField = named?.[0] ?? (a.closeVerb || a.updateVerb ? "updatedAt" : own(rulings.timeField, type) ?? "createdAt");
|
|
1538
|
-
const clause = { [dateField]: {
|
|
1539
|
-
gte: a.time.range.gte,
|
|
1540
|
-
lt: a.time.range.lt
|
|
1541
|
-
} };
|
|
1685
|
+
const clause = { [dateField]: { ...a.time.range } };
|
|
1542
1686
|
where.push(clause);
|
|
1543
1687
|
if (a.composed !== void 0) {
|
|
1544
1688
|
const ruled = named !== void 0 || a.closeVerb || a.updateVerb || own(rulings.timeField, type) !== void 0;
|
|
@@ -1610,9 +1754,13 @@ function assemble(type, a) {
|
|
|
1610
1754
|
params.orderBy = [{ [own(rulings.timeField, type) ?? "createdAt"]: order }];
|
|
1611
1755
|
params.limit = 1;
|
|
1612
1756
|
}
|
|
1757
|
+
if (sortBy !== null) {
|
|
1758
|
+
params.orderBy = [{ [sortBy.field]: sortBy.dir }];
|
|
1759
|
+
params.limit = sortBy.limit;
|
|
1760
|
+
}
|
|
1613
1761
|
Object.assign(params, a.composed?.params ?? {});
|
|
1614
1762
|
if (a.count && a.composed?.walked === true) params.count = true;
|
|
1615
|
-
const answer = a.askField !== null ? a.askField.group ? `group:${a.askField.field}` : `field:${a.askField.field}` : a.count ? "count" : order !== null || a.ids.length === 1 ? "single" : "rows";
|
|
1763
|
+
const answer = a.askField !== null ? a.askField.group ? `group:${a.askField.field}` : `field:${a.askField.field}` : a.count ? "count" : order !== null || a.ids.length === 1 || sortBy?.limit === 1 ? "single" : "rows";
|
|
1616
1764
|
return {
|
|
1617
1765
|
type,
|
|
1618
1766
|
frame: { [`${pack.namespace}/${type}`]: { params } },
|
|
@@ -1621,8 +1769,109 @@ function assemble(type, a) {
|
|
|
1621
1769
|
residual: contentWords(tokens),
|
|
1622
1770
|
plan,
|
|
1623
1771
|
dropped,
|
|
1624
|
-
strict: a.count || order !== null || a.ids.length === 1 || a.composed?.strict === true
|
|
1772
|
+
strict: a.count || order !== null || sortBy !== null || a.ids.length === 1 || a.composed?.strict === true
|
|
1773
|
+
};
|
|
1774
|
+
}
|
|
1775
|
+
/** A field named by words on one type: one of its field phrases, else its name or an alias. */
|
|
1776
|
+
function fieldByWords(words, fields, rulings) {
|
|
1777
|
+
return Object.entries(fields).find(([, f]) => f.phrases.includes(words))?.[0] ?? (words.includes(" ") ? null : resolveField(words, fields, rulings));
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Claims one field ordering. Field words are a field phrase claim, else the
|
|
1781
|
+
* longest run of up to three free words naming a field on some type; after
|
|
1782
|
+
* "by", "highest" or "lowest" an unknown single word is claimed too, so the
|
|
1783
|
+
* reading can drop it with a reason.
|
|
1784
|
+
*/
|
|
1785
|
+
function claimFieldOrder(tokens, walkClaims, pack, rulings) {
|
|
1786
|
+
const somewhere = (w, numeric) => Object.values(pack.types).some((t) => {
|
|
1787
|
+
const name = fieldByWords(w, t.fields, rulings);
|
|
1788
|
+
return name !== null && (!numeric || t.fields[name]?.valueType === "number");
|
|
1789
|
+
});
|
|
1790
|
+
const fieldAt = (i, numeric) => {
|
|
1791
|
+
const p = walkClaims.phrases.find((x) => x.at[0] === i && x.field !== void 0 && x.entry.value === void 0);
|
|
1792
|
+
if (p !== void 0) return {
|
|
1793
|
+
phrase: p,
|
|
1794
|
+
span: p.span,
|
|
1795
|
+
end: p.at[1]
|
|
1796
|
+
};
|
|
1797
|
+
for (let n = 3; n >= 1; n--) {
|
|
1798
|
+
const slice = tokens.slice(i, i + n);
|
|
1799
|
+
if (slice.length < n || slice.some((t) => t.used)) continue;
|
|
1800
|
+
const w = slice.map((t) => t.text).join(" ");
|
|
1801
|
+
if (somewhere(w, numeric)) return {
|
|
1802
|
+
words: w,
|
|
1803
|
+
span: w,
|
|
1804
|
+
end: i + n - 1
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1807
|
+
const t = tokens[i];
|
|
1808
|
+
return !numeric && t !== void 0 && !t.used && !GLUE.has(t.text) && !/^\d/.test(t.text) ? {
|
|
1809
|
+
words: t.text,
|
|
1810
|
+
span: t.text,
|
|
1811
|
+
end: i
|
|
1812
|
+
} : null;
|
|
1813
|
+
};
|
|
1814
|
+
const take = (from, f) => {
|
|
1815
|
+
for (let k = from; k <= f.end; k++) tokens[k].used = true;
|
|
1816
|
+
if (f.phrase !== void 0) walkClaims.phrases.splice(walkClaims.phrases.indexOf(f.phrase), 1);
|
|
1625
1817
|
};
|
|
1818
|
+
const field = (f) => f.phrase !== void 0 ? { phrase: f.phrase } : { words: f.words };
|
|
1819
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1820
|
+
const t = tokens[i];
|
|
1821
|
+
if (t.used) continue;
|
|
1822
|
+
if (t.text === "top" || t.text === "bottom") {
|
|
1823
|
+
const n = tokens[i + 1];
|
|
1824
|
+
const limit = n !== void 0 && !n.used && /^[1-9]\d*$/.test(n.text) ? n : void 0;
|
|
1825
|
+
const by = tokens.findIndex((x, j) => j > i && x.text === "by" && !x.used && !AUTHOR_VERBS.has(tokens[j - 1]?.text ?? ""));
|
|
1826
|
+
const f = by < 0 ? null : fieldAt(by + 1, false);
|
|
1827
|
+
if (f === null) continue;
|
|
1828
|
+
t.used = true;
|
|
1829
|
+
if (limit !== void 0) limit.used = true;
|
|
1830
|
+
take(by, f);
|
|
1831
|
+
return {
|
|
1832
|
+
span: [
|
|
1833
|
+
t.text,
|
|
1834
|
+
limit?.text,
|
|
1835
|
+
"by",
|
|
1836
|
+
f.span
|
|
1837
|
+
].filter((x) => x !== void 0).join(" "),
|
|
1838
|
+
dir: t.text === "top" ? "desc" : "asc",
|
|
1839
|
+
...limit !== void 0 ? { limit: Number(limit.text) } : {},
|
|
1840
|
+
...field(f)
|
|
1841
|
+
};
|
|
1842
|
+
}
|
|
1843
|
+
if (t.text === "highest" || t.text === "lowest" || t.text === "most") {
|
|
1844
|
+
const numeric = t.text === "most";
|
|
1845
|
+
const f = fieldAt(i + 1, numeric);
|
|
1846
|
+
if (f === null) continue;
|
|
1847
|
+
take(i, f);
|
|
1848
|
+
return {
|
|
1849
|
+
span: `${t.text} ${f.span}`,
|
|
1850
|
+
dir: t.text === "lowest" ? "asc" : "desc",
|
|
1851
|
+
...numeric ? { numeric } : {},
|
|
1852
|
+
...field(f)
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
return null;
|
|
1857
|
+
}
|
|
1858
|
+
/** The seed field an ordering sorts by on `type`, or why it cannot. */
|
|
1859
|
+
function orderField(o, type, pack, rulings) {
|
|
1860
|
+
const fields = own(pack.types, type)?.fields ?? {};
|
|
1861
|
+
const walked = { reason: "ordering across a walk is not supported" };
|
|
1862
|
+
let name;
|
|
1863
|
+
if (o.phrase !== void 0) {
|
|
1864
|
+
if (o.phrase.type !== type) return walked;
|
|
1865
|
+
name = o.phrase.field ?? null;
|
|
1866
|
+
} else {
|
|
1867
|
+
const words = o.words ?? "";
|
|
1868
|
+
name = fieldByWords(words, fields, rulings);
|
|
1869
|
+
if (name === null) return Object.values(pack.types).some((t) => fieldByWords(words, t.fields, rulings) !== null) ? walked : { reason: `${type} has no field "${words}"` };
|
|
1870
|
+
}
|
|
1871
|
+
const f = name === null ? void 0 : fields[name];
|
|
1872
|
+
if (name === null || f === void 0) return { reason: `${type} has no field "${o.span}"` };
|
|
1873
|
+
if (!((f.kind === "scalar" || f.kind === "metadata") && (f.valueType === "number" || f.valueType === "date" && o.numeric !== true))) return { reason: o.numeric === true ? `"most" needs a number field; ${name} is a ${f.valueType ?? f.kind} field` : `${name} is a ${f.valueType ?? f.kind} field; only number and date fields order` };
|
|
1874
|
+
return { field: name };
|
|
1626
1875
|
}
|
|
1627
1876
|
/** A clause's field name: the field itself, case-insensitively, then the rulings' and built-in aliases. */
|
|
1628
1877
|
function resolveField(raw, fields, rulings) {
|
|
@@ -1750,7 +1999,7 @@ function pickField(candidates, fields, words) {
|
|
|
1750
1999
|
}
|
|
1751
2000
|
function claimTime(tokens, asOf) {
|
|
1752
2001
|
let found = null;
|
|
1753
|
-
claimNgrams(tokens,
|
|
2002
|
+
claimNgrams(tokens, 8, (key, at) => {
|
|
1754
2003
|
if (found !== null) return false;
|
|
1755
2004
|
const range = rangeFor(key, asOf);
|
|
1756
2005
|
if (range === null) return false;
|
|
@@ -2216,7 +2465,7 @@ function clarify(question, reason, candidates, pack) {
|
|
|
2216
2465
|
const isAborted = (http) => http.signal?.aborted === true;
|
|
2217
2466
|
async function* runAsk(req, http, deps) {
|
|
2218
2467
|
const ctx = {
|
|
2219
|
-
asOf: (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
2468
|
+
asOf: req.asOf ?? (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
2220
2469
|
rulings: deps.pack.rulings,
|
|
2221
2470
|
...req.project !== void 0 ? { project: req.project } : {},
|
|
2222
2471
|
...req.type !== void 0 ? { forceType: req.type } : {}
|
|
@@ -2229,7 +2478,8 @@ async function* runAsk(req, http, deps) {
|
|
|
2229
2478
|
...best !== void 0 ? { frame: executable(best, deps.pack) } : {},
|
|
2230
2479
|
evidence: best?.evidence ?? first.evidence ?? [],
|
|
2231
2480
|
residual: first.residual,
|
|
2232
|
-
...first.reason !== void 0 ? { reason: first.reason } : {}
|
|
2481
|
+
...first.reason !== void 0 ? { reason: first.reason } : {},
|
|
2482
|
+
asOf: ctx.asOf
|
|
2233
2483
|
};
|
|
2234
2484
|
if (isAborted(http)) return yield { event: "done" };
|
|
2235
2485
|
/**
|
|
@@ -2796,16 +3046,21 @@ function askHandler(deps) {
|
|
|
2796
3046
|
const parsed = parseJsonBody(req);
|
|
2797
3047
|
if (!parsed.ok) return parsed.response;
|
|
2798
3048
|
const body = parsed.value;
|
|
2799
|
-
if (body === null || typeof body !== "object" || Array.isArray(body)) return error400("body must be a JSON object: { namespace, question, project?, type? }");
|
|
3049
|
+
if (body === null || typeof body !== "object" || Array.isArray(body)) return error400("body must be a JSON object: { namespace, question, project?, type?, asOf? }");
|
|
2800
3050
|
if (!str(body.namespace)) return error400("body.namespace must be a non-empty string");
|
|
2801
3051
|
if (!str(body.question)) return error400("body.question must be a non-empty string");
|
|
2802
3052
|
if (body.question.length > MAX_QUESTION_CHARS) return error400(`body.question is longer than ${MAX_QUESTION_CHARS} characters`);
|
|
2803
3053
|
for (const k of ["project", "type"]) if (body[k] !== void 0 && !str(body[k])) return error400(`body.${k} must be a non-empty string when given`);
|
|
3054
|
+
if (body.asOf !== void 0 && !validAsOf(body.asOf)) return jsonResponse(400, {
|
|
3055
|
+
error: "body.asOf must be an ISO-8601 date-time with an offset, e.g. 2026-10-02T12:00:00-05:00",
|
|
3056
|
+
code: "invalid_params"
|
|
3057
|
+
});
|
|
2804
3058
|
const ask = {
|
|
2805
3059
|
namespace: body.namespace,
|
|
2806
3060
|
question: body.question,
|
|
2807
3061
|
...str(body.project) ? { project: body.project } : {},
|
|
2808
|
-
...str(body.type) ? { type: body.type } : {}
|
|
3062
|
+
...str(body.type) ? { type: body.type } : {},
|
|
3063
|
+
...validAsOf(body.asOf) ? { asOf: body.asOf } : {}
|
|
2809
3064
|
};
|
|
2810
3065
|
let served;
|
|
2811
3066
|
try {
|
package/dist/bootstrap.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as askHandler, c as profileNamespace, d as runAsk, f as parseWithJudge, g as readRulings, h as mergeRulings, i as createNlPlugin, l as buildNamespacePack, m as NamespaceRulingsSchema, n as bootstrap, o as packHandler, p as parseQuestion, r as CONTRACT_VERSION, s as PackService, t as NlBootstrapConfigSchema, u as OllamaJudge } from "./bootstrap-
|
|
1
|
+
import { a as askHandler, c as profileNamespace, d as runAsk, f as parseWithJudge, g as readRulings, h as mergeRulings, i as createNlPlugin, l as buildNamespacePack, m as NamespaceRulingsSchema, n as bootstrap, o as packHandler, p as parseQuestion, r as CONTRACT_VERSION, s as PackService, t as NlBootstrapConfigSchema, u as OllamaJudge } from "./bootstrap-DbMpquDD.js";
|
|
2
2
|
import { complete } from "./complete.js";
|
|
3
3
|
|
|
4
4
|
export { CONTRACT_VERSION, NamespaceRulingsSchema, NlBootstrapConfigSchema, OllamaJudge, PackService, askHandler, bootstrap, buildNamespacePack, complete, createNlPlugin, mergeRulings, packHandler, parseQuestion, parseWithJudge, profileNamespace, readRulings, runAsk };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/parse/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/parse/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,kBAAkB,CAAC;AAgBjE,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAElC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,qGAAqG;IACrG,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,yFAAyF;IACzF,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB;;;OAGG;IACH,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG,aAAa,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;IACtB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiHD,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,YAAY,GAChB,WAAW,CAoWb"}
|
package/dist/parse/time.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
/** A half-open range of instants, ISO-8601 with the asking offset. */
|
|
2
|
-
export
|
|
1
|
+
/** A half-open range of instants, ISO-8601 with the asking offset. One bound may be open. */
|
|
2
|
+
export type DateRange = {
|
|
3
3
|
gte: string;
|
|
4
4
|
lt: string;
|
|
5
|
-
}
|
|
5
|
+
} | {
|
|
6
|
+
gte: string;
|
|
7
|
+
lt?: never;
|
|
8
|
+
} | {
|
|
9
|
+
gte?: never;
|
|
10
|
+
lt: string;
|
|
11
|
+
};
|
|
12
|
+
/** True when `asOf` is an ISO-8601 date-time with an offset naming a real instant. */
|
|
13
|
+
export declare function validAsOf(asOf: unknown): asOf is string;
|
|
6
14
|
/**
|
|
7
15
|
* The range a time phrase names, relative to `asOf` and in its offset:
|
|
8
16
|
* today, yesterday, this/last week (weeks start Monday), this/last month,
|
|
9
|
-
* rolling "past <unit>" and "last N <units>", "since <weekday>"
|
|
10
|
-
* the phrase is not a time phrase.
|
|
17
|
+
* rolling "past <unit>" and "last N <units>", "since <weekday>"; and explicit
|
|
18
|
+
* dates (see `explicitRange`). Null when the phrase is not a time phrase.
|
|
11
19
|
*/
|
|
12
20
|
export declare function rangeFor(phrase: string, asOf: string): DateRange | null;
|
|
13
21
|
//# sourceMappingURL=time.d.ts.map
|
package/dist/parse/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/parse/time.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/parse/time.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,MAAM,MAAM,SAAS,GACjB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAE,GAC3B;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAOhC,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,CAMvD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAgDvE"}
|
package/dist/parse/walks.d.ts
CHANGED
|
@@ -107,6 +107,12 @@ export interface Composed {
|
|
|
107
107
|
strict: boolean;
|
|
108
108
|
/** The recency word ("latest") claimed by a seed phrase: the seed is ordered by it. */
|
|
109
109
|
seedLatest?: string;
|
|
110
|
+
/** "highest"/"lowest" on a seed field phrase: the seed is ordered by that field. */
|
|
111
|
+
seedOrder?: {
|
|
112
|
+
span: string;
|
|
113
|
+
dir: 'desc' | 'asc';
|
|
114
|
+
phrase: PhraseClaim;
|
|
115
|
+
};
|
|
110
116
|
}
|
|
111
117
|
/** Clauses as one where: the clause itself, or an AND with plan paths re-rooted. */
|
|
112
118
|
export declare function andOf(parts: Part[]): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"walks.d.ts","sourceRoot":"","sources":["../../src/parse/walks.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"walks.d.ts","sourceRoot":"","sources":["../../src/parse/walks.ts"],"names":[],"mappings":"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"}
|
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,yBAAyB,CAAC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,yBAAyB,CAAC;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9B;AAkBD,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CA8DzD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAwB1D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnmal-ai/substrate-nl",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Natural-language questions for Substrate — a deterministic parser with an optional constrained judge, served at POST /substrate/v1/nl and GET /substrate/v1/nl/pack/:ns, plus browser-safe completion.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@biomejs/biome": "2.6.4",
|
|
40
|
-
"@mnmal-ai/substrate": "1.0.0-alpha.
|
|
41
|
-
"@mnmal-ai/substrate-config": "1.0.0-alpha.
|
|
40
|
+
"@mnmal-ai/substrate": "1.0.0-alpha.14",
|
|
41
|
+
"@mnmal-ai/substrate-config": "1.0.0-alpha.14",
|
|
42
42
|
"@types/node": "^26.6.4",
|
|
43
43
|
"tsdown": "^0.23.0",
|
|
44
44
|
"typescript": "^7.0.2",
|