@ai-matrx/records 0.72.12 → 0.72.23

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/app-table/index.d.cts +3 -3
  3. package/dist/app-table/index.d.ts +3 -3
  4. package/dist/core/index.d.cts +5 -5
  5. package/dist/core/index.d.ts +5 -5
  6. package/dist/{declareTable-Br8pE4fr.d.cts → declareTable-CLvpMdgJ.d.cts} +2 -2
  7. package/dist/{declareTable-DM6z1tc-.d.ts → declareTable-DY3oN4rq.d.ts} +2 -2
  8. package/dist/index.d.cts +3 -3
  9. package/dist/index.d.ts +3 -3
  10. package/dist/memory/index.cjs +2681 -0
  11. package/dist/memory/index.cjs.map +1 -0
  12. package/dist/memory/index.d.cts +126 -0
  13. package/dist/memory/index.d.ts +126 -0
  14. package/dist/memory/index.js +2658 -0
  15. package/dist/memory/index.js.map +1 -0
  16. package/dist/{ports-DKBvsoya.d.cts → ports-DKOk7AT2.d.cts} +1 -1
  17. package/dist/{ports-Bhu2Q3V0.d.ts → ports-Df3VghxK.d.ts} +1 -1
  18. package/dist/{table-kind-D6Lz7ebE.d.ts → table-kind-CD9B1vtx.d.ts} +1 -1
  19. package/dist/{table-kind-D6VOew74.d.cts → table-kind-e-g5kGXV.d.cts} +1 -1
  20. package/dist/templates/index.cjs +59 -24
  21. package/dist/templates/index.cjs.map +1 -1
  22. package/dist/templates/index.d.cts +18 -1176
  23. package/dist/templates/index.d.ts +18 -1176
  24. package/dist/templates/index.js +59 -24
  25. package/dist/templates/index.js.map +1 -1
  26. package/dist/{validate-QtFxMmJc.d.ts → types-Ba11aOEO.d.ts} +1 -42
  27. package/dist/{validate-DUSrx-9E.d.cts → types-BtEKp3ot.d.cts} +1 -42
  28. package/dist/types-DxVoKKpL.d.ts +1186 -0
  29. package/dist/types-dlj1-2t2.d.cts +1186 -0
  30. package/dist/use-cases/index.d.cts +3 -2
  31. package/dist/use-cases/index.d.ts +3 -2
  32. package/dist/validate-CMb7R_ke.d.cts +44 -0
  33. package/dist/validate-E-g4LAZ6.d.ts +44 -0
  34. package/package.json +13 -1
@@ -3463,6 +3463,12 @@ function validateTemplate(raw, options = {}) {
3463
3463
  seedLooks.add(p);
3464
3464
  problems.push(p);
3465
3465
  };
3466
+ const galleryBar = /* @__PURE__ */ new WeakSet();
3467
+ const sayGallery = (at, says) => {
3468
+ const p = { at, says };
3469
+ galleryBar.add(p);
3470
+ problems.push(p);
3471
+ };
3466
3472
  const tz = raw.business?.timezone || "UTC";
3467
3473
  const tablesRaw = allTables(raw);
3468
3474
  const ISO_DAY = /\b\d{4}-\d{2}-\d{2}\b/;
@@ -3785,7 +3791,7 @@ function validateTemplate(raw, options = {}) {
3785
3791
  say(`${tat}.rows`, `Only ${titles.size} of ${table.rows.length} rows have a title of their own; a list of look-alike names reads as generated.`);
3786
3792
  }
3787
3793
  });
3788
- if (!hasLookupOrRollup) say("tables", "At least one relationship has to be read across: add a lookup or a rollup through a relation field.");
3794
+ if (!hasLookupOrRollup) sayGallery("tables", "At least one relationship has to be read across: add a lookup or a rollup through a relation field.");
3789
3795
  if (main) {
3790
3796
  const normTitle = (v) => (storeText(v) ?? "").toLowerCase().replace(/\s+/g, " ").trim();
3791
3797
  const rows = main.rows;
@@ -3853,8 +3859,8 @@ function validateTemplate(raw, options = {}) {
3853
3859
  else surfaces.set(token, { at, ...table ? { table } : {} });
3854
3860
  };
3855
3861
  const views = spec.views ?? [];
3856
- if (views.length < 3) say("views", `A template shows at least three views; this one has ${views.length}.`);
3857
- if (!views.some((v) => v.kind === "grid")) say("views", "One of the views is a grid \u2014 the table everyone recognises.");
3862
+ if (views.length < 3) sayGallery("views", `A template shows at least three views; this one has ${views.length}.`);
3863
+ if (!views.some((v) => v.kind === "grid")) sayGallery("views", "One of the views is a grid \u2014 the table everyone recognises.");
3858
3864
  views.forEach((view, i) => {
3859
3865
  const at = `views[${i}] (${view.token})`;
3860
3866
  claim(view.token, at, view.table);
@@ -3980,7 +3986,7 @@ function validateTemplate(raw, options = {}) {
3980
3986
  }
3981
3987
  };
3982
3988
  const extras = spec.extras ?? [];
3983
- if (extras.length < 2) say("extras", `A template carries at least two extras; this one has ${extras.length}.`);
3989
+ if (extras.length < 2) sayGallery("extras", `A template carries at least two extras; this one has ${extras.length}.`);
3984
3990
  const formTokens = new Set(forms.map((f) => f.token));
3985
3991
  const viewTokens = new Set(views.map((v) => v.token));
3986
3992
  const docTokens = new Set(extras.filter((e) => e.kind === "document").map((e) => e.token));
@@ -4329,7 +4335,8 @@ function validateTemplate(raw, options = {}) {
4329
4335
  if (here >= 0 && Number.isFinite(firstWhen) && here < firstWhen && !TERMINAL_STAGE.test(st)) {
4330
4336
  for (const k of rule.filled ?? []) {
4331
4337
  if (!/^(?:datetime|date|checkbox|signature|attachment)$/.test(fieldOf(table, k)?.parityType ?? "")) continue;
4332
- if (filled(row.values?.[k])) say(at, `"${row.key}" is ${st}, but already has "${fieldOf(table, k)?.label ?? k}", which only a ${rule.when.join("/")} record carries. Leave it empty until the record gets there.`);
4338
+ const v = row.values?.[k];
4339
+ if (fieldOf(table, k)?.parityType === "checkbox" ? v === true || v === "true" : filled(v)) say(at, `"${row.key}" is ${st}, but already has "${fieldOf(table, k)?.label ?? k}", which only a ${rule.when.join("/")} record carries. Leave it empty until the record gets there.`);
4333
4340
  }
4334
4341
  }
4335
4342
  if (!rule.when.includes(st)) continue;
@@ -4667,6 +4674,7 @@ function validateTemplate(raw, options = {}) {
4667
4674
  }
4668
4675
  }
4669
4676
  adds += 1;
4677
+ for (const f of table.fields) if (f.default !== void 0 && !isComputed(f) && values[f.key] === void 0) values[f.key] = f.default;
4670
4678
  const added = { key: `walk-${i}-${ri}`, values };
4671
4679
  const landed = rules ? storeText(values[rules.stageField]) : null;
4672
4680
  for (const k of landed ? rules?.requires?.[landed] ?? [] : []) if (!filled(values[k])) say(`${at}.action.rows[${ri}]`, `The new row "${keyValue}" lands in "${landed}", which needs "${k}" filled; the store would refuse it.`);
@@ -4990,7 +4998,8 @@ function validateTemplate(raw, options = {}) {
4990
4998
  const at = `tables (${t.token}).fields (${f.key})`;
4991
4999
  const text2 = `${f.key} ${norm(f.label)}`;
4992
5000
  const e = effective(t.token, f);
4993
- const criminalCharges = /(^|_)charges?($|_)/.test(f.key) && behaviorOf(f) === "text";
5001
+ const billingTable = /(invoice|bill|statement|receipt|payment|charge|fee|order|account)/i.test(`${t.token} ${t.labelSingular}`);
5002
+ const criminalCharges = /(^|_)charges?($|_)/.test(f.key) && behaviorOf(f) === "text" && !billingTable;
4994
5003
  const phoneLike = behaviorOf(f) === "text" && /\b(cell|mobile|phone)\b/.test(norm(f.label));
4995
5004
  const personal = PERSONAL_ONLY.test(f.key) || /\b(medical conditions?|medications?|diagnos[ie]s)\b/.test(norm(f.label));
4996
5005
  const floored = (RESTRICTED_KEY.test(f.key) || RESTRICTED_LABEL.test(norm(f.label)) || criminalCharges) && (!personal || holdsPeople(t));
@@ -5294,7 +5303,8 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
5294
5303
  const qq = agent.question;
5295
5304
  const ask = norm(qq.ask);
5296
5305
  const words = (t) => norm(t).split(" ").filter((w) => w.length >= 4);
5297
- const mentions = (t) => words(t).some((w) => ask.includes(w.replace(/s$/, "")));
5306
+ const askWords = new Set(ask.split(" "));
5307
+ const mentions = (t) => !!norm(t) && ask.includes(norm(t)) || words(t).some((w) => ask.includes(w.replace(/s$/, ""))) || words(t).length === 0 && norm(t).split(" ").filter(Boolean).some((w) => w.length >= 3 && (askWords.has(w) || askWords.has(`${w}s`)));
5298
5308
  for (const [k, v] of Object.entries(qq.expect.filter ?? {})) {
5299
5309
  if (typeof v === "string" && !mentions(v) && !ask.includes(norm(v))) say("agent.question.ask", `It filters on ${k} = "${v}", and the question never says so.`);
5300
5310
  }
@@ -5375,7 +5385,8 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
5375
5385
  const named = (t) => {
5376
5386
  if (!t) return false;
5377
5387
  if (says.includes(norm(t))) return true;
5378
- const words = [...new Set(norm(t).split(" ").filter((w) => w.length >= 4))];
5388
+ const long = [...new Set(norm(t).split(" ").filter((w) => w.length >= 4))];
5389
+ const words = long.length ? long : [...new Set(norm(t).split(" ").filter((w) => w.length >= 2))];
5379
5390
  const said = new Set(says.split(" "));
5380
5391
  return words.length > 0 && words.filter((w) => said.has(w) || said.has(`${w}s`)).length >= Math.min(2, words.length);
5381
5392
  };
@@ -5791,7 +5802,7 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
5791
5802
  if (bothDates && !datesStated) say(`${at}.childDates`, `"${t.token}" and its ${rel.label.toLowerCase()} ("${parent.token}") both carry dates; say how they agree, e.g. {"relation": "${rel.key}", "field": "<this table's date>", "parentField": "<${parent.token}'s date>"} or say why they are independent in independentOf {"${rel.key}": "<reason>"}.`);
5792
5803
  if (bothStatus && !statusStated) say(`${at}.statusAgrees`, `"${t.token}" and its ${rel.label.toLowerCase()} ("${parent.token}") both carry a status; say which child statuses need which parent status (statusAgrees), e.g. a Closed deal means a Sold listing.`);
5793
5804
  }
5794
- for (const f of t.fields.filter((x) => isNumber(x) && !isComputed(x) && /(^|_)(count|roster_size|size|number_of|enrolled|headcount|players|members)($|_)/.test(x.key))) {
5805
+ for (const f of t.fields.filter((x) => isNumber(x) && !isComputed(x) && /(^|_)(count|roster_size|team_size|class_size|number_of|enrolled|headcount|players|members)($|_)/.test(x.key))) {
5795
5806
  const linked = own.find((c) => c.fields.some((cf) => isRelation(cf) && cf.relationTarget === t.token));
5796
5807
  const declared = (t.countMatches ?? []).find((c) => c.field === f.key);
5797
5808
  const linkers = own.filter((c) => c.fields.some((cf) => isRelation(cf) && cf.relationTarget === t.token)).map((c) => c.labelPlural.toLowerCase());
@@ -5826,7 +5837,7 @@ ${e.body}`.matchAll(MERGE_TOKEN)].map((m) => m[1]));
5826
5837
  const describeOwes = (p) => {
5827
5838
  const root = p.at.split(/[.\s[(]/)[0];
5828
5839
  if (GALLERY_ONLY_ROOTS.includes(root)) return false;
5829
- if (seedLooks.has(p)) return false;
5840
+ if (seedLooks.has(p) || galleryBar.has(p)) return false;
5830
5841
  if (/^tables\[\d+\] \([^)]*\)\.rows$/.test(p.at)) return false;
5831
5842
  return true;
5832
5843
  };
@@ -5925,7 +5936,14 @@ function compileInstallPlan(written) {
5925
5936
  const attachments = written.attachments ?? [];
5926
5937
  const attachmentKeys = new Set(attachments.map((a) => a.key));
5927
5938
  const spec = tokenizeValues({ ...written, attachments: void 0 }, attachmentKeys);
5928
- const tables = allTables(spec);
5939
+ const bound = new Map(allTables(spec).filter((t) => t.bindsTo?.tableId).map((t) => [t.token, t.bindsTo]));
5940
+ const has = (token, key) => bound.get(token)?.fields.includes(key) ?? false;
5941
+ const tables = allTables(spec).map((t) => {
5942
+ if (bound.has(t.token)) return { ...t, rows: [] };
5943
+ const toBound = t.fields.filter((f) => f.parityType === "relation" && f.relationTarget && bound.has(f.relationTarget)).map((f) => f.key);
5944
+ if (!toBound.length) return t;
5945
+ return { ...t, rows: t.rows.map((r) => ({ ...r, values: Object.fromEntries(Object.entries(r.values ?? {}).filter(([k]) => !toBound.includes(k))) })) };
5946
+ });
5929
5947
  const steps = [];
5930
5948
  const tableRef = (token) => {
5931
5949
  if (!tables.some((t) => t.token === token)) throw new Error(`The template names a table "${token}" it does not have.`);
@@ -5955,6 +5973,18 @@ function compileInstallPlan(written) {
5955
5973
  }
5956
5974
  }
5957
5975
  for (const t of tables) {
5976
+ if (bound.has(t.token)) {
5977
+ for (const f of t.fields.filter((x) => !DERIVED.has(x.parityType) && x.parityType !== "formula" && x.parityType !== "relation" && !isSelfDeclaredField(x) && !has(t.token, x.key))) {
5978
+ steps.push({
5979
+ label: `bound.${t.token}.${f.key}`,
5980
+ door: "field_declare",
5981
+ args: { p_organization_id: "${org}", p_table_id: tableRef(t.token), p_spec: selfDeclaredFieldSpec(f) },
5982
+ save: { [`fields.${t.token}.${f.key}`]: [] },
5983
+ made: [{ kind: "field", ref: `fields.${t.token}.${f.key}`, table: `tables.${t.token}` }]
5984
+ });
5985
+ }
5986
+ continue;
5987
+ }
5958
5988
  steps.push({
5959
5989
  label: `tables.${t.token}`,
5960
5990
  door: "table_from_example",
@@ -5965,7 +5995,7 @@ function compileInstallPlan(written) {
5965
5995
  }
5966
5996
  steps.push(...membersAddRowsSteps(spec, tableRef));
5967
5997
  for (const t of tables) {
5968
- for (const f of t.fields.filter((x) => x.parityType === "relation" && x.relationTarget)) {
5998
+ for (const f of t.fields.filter((x) => x.parityType === "relation" && x.relationTarget && !has(t.token, x.key))) {
5969
5999
  steps.push({
5970
6000
  label: `relations.${t.token}.${f.key}`,
5971
6001
  door: "field_declare",
@@ -5976,7 +6006,7 @@ function compileInstallPlan(written) {
5976
6006
  }
5977
6007
  }
5978
6008
  for (const t of tables) {
5979
- for (const f of t.fields.filter(isSelfDeclaredField)) {
6009
+ for (const f of t.fields.filter((x) => isSelfDeclaredField(x) && !has(t.token, x.key))) {
5980
6010
  steps.push({
5981
6011
  label: `self_declared.${t.token}.${f.key}`,
5982
6012
  door: "field_declare",
@@ -6012,7 +6042,7 @@ function compileInstallPlan(written) {
6012
6042
  }
6013
6043
  }
6014
6044
  for (const t of tables) {
6015
- for (const f of t.fields.filter((x) => DERIVED.has(x.parityType))) {
6045
+ for (const f of t.fields.filter((x) => DERIVED.has(x.parityType) && !has(t.token, x.key))) {
6016
6046
  steps.push({
6017
6047
  label: `derived.${t.token}.${f.key}`,
6018
6048
  door: "field_declare",
@@ -6023,7 +6053,7 @@ function compileInstallPlan(written) {
6023
6053
  }
6024
6054
  }
6025
6055
  for (const t of tables) {
6026
- for (const f of formulaOrder(t)) {
6056
+ for (const f of formulaOrder(t).filter((x) => !has(t.token, x.key))) {
6027
6057
  steps.push({
6028
6058
  label: `formula.${t.token}.${f.key}`,
6029
6059
  door: "field_declare",
@@ -6049,7 +6079,7 @@ function compileInstallPlan(written) {
6049
6079
  saveEach: { array: [], key: ["data", "key"], value: ["id"], prefix: `fields.${token}.` }
6050
6080
  });
6051
6081
  }
6052
- for (const d of spec.dimensions) {
6082
+ for (const d of spec.dimensions.filter((x) => !bound.has(x.table))) {
6053
6083
  const overrides = {};
6054
6084
  if (d.dimensions) overrides["dimensions"] = d.dimensions;
6055
6085
  if (d.measures) overrides["measures"] = d.measures;
@@ -6206,18 +6236,22 @@ function compileInstallPlan(written) {
6206
6236
  });
6207
6237
  }
6208
6238
  const host = compileHostExtras(spec);
6239
+ const agent = spec.agent;
6209
6240
  return {
6210
6241
  planVersion: INSTALL_PLAN_VERSION,
6211
6242
  timezone: spec.business.timezone || "UTC",
6212
6243
  steps,
6213
- agent: {
6214
- platformAgent: spec.agent.platformAgent,
6215
- name: spec.agent.name,
6216
- bindings: spec.agent.variables.map((v) => {
6217
- const binding = host.agentBindings.get(v.name);
6218
- return { variable: v.name, tableToken: v.table, describes: v.describes, ...binding ? { binding } : {} };
6219
- })
6220
- },
6244
+ ...agent?.platformAgent ? {
6245
+ agent: {
6246
+ platformAgent: agent.platformAgent,
6247
+ name: agent.name,
6248
+ bindings: (agent.variables ?? []).map((v) => {
6249
+ const binding = host.agentBindings.get(v.name);
6250
+ return { variable: v.name, tableToken: v.table, describes: v.describes, ...binding ? { binding } : {} };
6251
+ })
6252
+ }
6253
+ } : {},
6254
+ ...bound.size ? { ids: Object.fromEntries([...bound].map(([token, b]) => [`ref:tables.${token}`, b.tableId])) } : {},
6221
6255
  ...host.extras
6222
6256
  };
6223
6257
  }
@@ -6277,6 +6311,7 @@ export {
6277
6311
  RECORDS_UI_FIELD_SURFACES,
6278
6312
  RECORDS_UI_VIEW_LAYOUTS,
6279
6313
  RELATIVE_DATE,
6314
+ RESOLVABLE_FIELD_TYPE_WORDS,
6280
6315
  SERVER_DATE_GRAMMAR,
6281
6316
  SHARED_BLOCKS,
6282
6317
  SHARED_BLOCK_IDS,