@ifc-lite/flow-nodes 0.6.0 → 0.8.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.
Files changed (72) hide show
  1. package/README.md +42 -0
  2. package/dist/ai-classify.d.ts +8 -0
  3. package/dist/ai-classify.d.ts.map +1 -0
  4. package/dist/ai-classify.js +113 -0
  5. package/dist/ai-classify.js.map +1 -0
  6. package/dist/ai-extract.d.ts +26 -0
  7. package/dist/ai-extract.d.ts.map +1 -0
  8. package/dist/ai-extract.js +127 -0
  9. package/dist/ai-extract.js.map +1 -0
  10. package/dist/ai-propose-fields.d.ts +12 -0
  11. package/dist/ai-propose-fields.d.ts.map +1 -0
  12. package/dist/ai-propose-fields.js +57 -0
  13. package/dist/ai-propose-fields.js.map +1 -0
  14. package/dist/ai-propose.d.ts +3 -0
  15. package/dist/ai-propose.d.ts.map +1 -0
  16. package/dist/ai-propose.js +94 -0
  17. package/dist/ai-propose.js.map +1 -0
  18. package/dist/ai-response-schemas.d.ts +11 -0
  19. package/dist/ai-response-schemas.d.ts.map +1 -0
  20. package/dist/ai-response-schemas.js +46 -0
  21. package/dist/ai-response-schemas.js.map +1 -0
  22. package/dist/ai-service.d.ts +60 -0
  23. package/dist/ai-service.d.ts.map +1 -0
  24. package/dist/ai-service.js +109 -0
  25. package/dist/ai-service.js.map +1 -0
  26. package/dist/ai-summarize.d.ts +3 -0
  27. package/dist/ai-summarize.d.ts.map +1 -0
  28. package/dist/ai-summarize.js +75 -0
  29. package/dist/ai-summarize.js.map +1 -0
  30. package/dist/ai.d.ts +15 -0
  31. package/dist/ai.d.ts.map +1 -0
  32. package/dist/ai.js +10 -0
  33. package/dist/ai.js.map +1 -0
  34. package/dist/bcf-nodes.d.ts.map +1 -1
  35. package/dist/bcf-nodes.js +12 -2
  36. package/dist/bcf-nodes.js.map +1 -1
  37. package/dist/bcf-publication.d.ts +13 -0
  38. package/dist/bcf-publication.d.ts.map +1 -0
  39. package/dist/bcf-publication.js +24 -0
  40. package/dist/bcf-publication.js.map +1 -0
  41. package/dist/bcf-write-gateway.d.ts +41 -0
  42. package/dist/bcf-write-gateway.d.ts.map +1 -0
  43. package/dist/bcf-write-gateway.js +75 -0
  44. package/dist/bcf-write-gateway.js.map +1 -0
  45. package/dist/capability.d.ts +4 -0
  46. package/dist/capability.d.ts.map +1 -0
  47. package/dist/capability.js +21 -0
  48. package/dist/capability.js.map +1 -0
  49. package/dist/element-nodes.d.ts +9 -1
  50. package/dist/element-nodes.d.ts.map +1 -1
  51. package/dist/element-nodes.js +82 -9
  52. package/dist/element-nodes.js.map +1 -1
  53. package/dist/host.d.ts +26 -40
  54. package/dist/host.d.ts.map +1 -1
  55. package/dist/host.js +2 -31
  56. package/dist/host.js.map +1 -1
  57. package/dist/ids-nodes.d.ts +23 -0
  58. package/dist/ids-nodes.d.ts.map +1 -0
  59. package/dist/ids-nodes.js +166 -0
  60. package/dist/ids-nodes.js.map +1 -0
  61. package/dist/index.d.ts +1 -0
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +2 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/ports.d.ts +38 -0
  66. package/dist/ports.d.ts.map +1 -0
  67. package/dist/ports.js +14 -0
  68. package/dist/ports.js.map +1 -0
  69. package/dist/speckle/url.d.ts.map +1 -1
  70. package/dist/speckle/url.js +9 -1
  71. package/dist/speckle/url.js.map +1 -1
  72. package/package.json +26 -12
package/README.md CHANGED
@@ -31,6 +31,18 @@ const result = await runFlow(doc, { host: { bim }, registry, features: BROWSER_F
31
31
  `host.grants` (parsed capabilities from `@ifc-lite/extensions`) gates every node;
32
32
  omit it only for a trusted caller such as the CLI running a local file.
33
33
 
34
+ ## Stair and railing authoring
35
+
36
+ `element.stair` and `element.railing` produce specs for the existing tracked
37
+ `model.addElement` node. Their PascalCase parameters reuse the canonical SDK
38
+ builders; dimensions are storey-local metres. Stair update/removal removes the
39
+ uniquely owned parent/flight pair, retaining shared representation leaves and
40
+ refusing ambiguous ownership or foreign product references. Unsupported backend
41
+ capabilities refuse explicitly. All `model.addElement` updates use the optional
42
+ atomic replacement capability, preserving the old graph and tracking entry
43
+ on refusal, including a spec-kind change. Reuse a tracking store for keep/update/remove;
44
+ public MCP `run_flow` starts fresh tracking on each call.
45
+
34
46
  ## Session automation host
35
47
 
36
48
  The seven standard automation definitions call `host.automation` and pass the
@@ -63,3 +75,33 @@ not rerun a comparison against the loaded models.
63
75
  ## License
64
76
 
65
77
  MPL-2.0
78
+
79
+ The separate `@ifc-lite/flow-nodes/ai` entry includes `ai.propose`: a bounded,
80
+ review-required draft over selected finding columns and explicit native
81
+ field/value constraints. Its portable `model.changes` output cites captured
82
+ rows and expected values, and performs no writes. Current-state validation and
83
+ mutation approval remain native host responsibilities. See the
84
+ [AI node and checkpoint contract](../../docs/guide/flow.md#ai-nodes-and-review-checkpoints).
85
+
86
+ ## BCF write response boundary
87
+
88
+ Both create operations enrol the actual resolved bearer, including short literal
89
+ and Player values. Successful DTO data, dynamic keys and outward diagnostics
90
+ redact raw and JSON-escaped bearer occurrences. The primary `guid` and optional
91
+ comment `topic_guid`, `viewpoint_guid` and `reply_to_comment_guid` are validated
92
+ before an owned gateway saves the receipt and before any returned receipt is
93
+ emitted. A credential-bearing identifier leaves the retained server effect
94
+ uncertain; it is never silently renamed or retried. Clean identifier values,
95
+ nullable optional relationships and their fixed protocol keys stay exact, even
96
+ when a short bearer equals part of a key. Browser intent admission validates a
97
+ closed schema and checks credential values and dynamic keys, so a bearer such
98
+ as `id` does not reject fixed names such as `topicGuid`. Unknown fields and
99
+ credential values, URL credentials and Authorization/Bearer syntax stay refused.
100
+ A fixed protocol field name is not server-echoed credential data. Gateway errors preserve the host's refusal
101
+ or recovery message as a plain `Error`, without its original class or cause.
102
+ Direct sends use dispatch provenance: a preflight denial is definite; a refused
103
+ redirect, HTTP 409, HTTP 5xx or missing response remains uncertain and never retries.
104
+ Direct remote failures expose only the safe failure class and valid HTTP status;
105
+ remote response bodies, detail URLs and error causes are discarded. Known local
106
+ preflight diagnostics and gateway refusal/recovery text are retained after
107
+ redacting the actual bearer, without carrying their original error cause.
@@ -0,0 +1,8 @@
1
+ import type { FlowNodeDef } from './host.js';
2
+ /** Read one batch reply into per-row results; anything not provable stays `unknown`. */
3
+ export declare function readClassifications(value: Record<string, unknown>, batchKeys: ReadonlySet<string>, labels: ReadonlySet<string>, columns: ReadonlySet<string>): Map<string, {
4
+ label: string | null;
5
+ evidence: string[];
6
+ }>;
7
+ export declare const aiClassifyNode: FlowNodeDef;
8
+ //# sourceMappingURL=ai-classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-classify.d.ts","sourceRoot":"","sources":["../src/ai-classify.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAsB7C,wFAAwF;AACxF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GACxH,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAa3D;AAED,eAAO,MAAM,cAAc,EAAE,WA2E5B,CAAC"}
@@ -0,0 +1,113 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { SCALAR_ITEM, TABLE_ITEM } from './ports.js';
5
+ import { AI_CAPABILITY, AI_FEATURE, aiService, dataBlock, positiveInt, requestJson, rowKeys, sentColumns } from './ai-service.js';
6
+ import { classificationSchema } from './ai-response-schemas.js';
7
+ function categoriesOf(value) {
8
+ if (!Array.isArray(value) || value.length === 0 || value.length > 50)
9
+ throw new Error('"categories" must list 1 to 50 { label, definition } entries');
10
+ const seen = new Set();
11
+ return value.map((c, i) => {
12
+ const label = typeof c?.label === 'string' ? c.label.trim() : '';
13
+ if (!label || label.length > 80 || label === 'unknown' || seen.has(label))
14
+ throw new Error(`category ${i + 1} needs a unique label other than "unknown"`);
15
+ seen.add(label);
16
+ return { label, definition: typeof c.definition === 'string' ? c.definition.slice(0, 500) : '' };
17
+ });
18
+ }
19
+ /** Read one batch reply into per-row results; anything not provable stays `unknown`. */
20
+ export function readClassifications(value, batchKeys, labels, columns) {
21
+ const out = new Map();
22
+ const items = Array.isArray(value.items) ? value.items : [];
23
+ for (const raw of items) {
24
+ if (!raw || typeof raw !== 'object')
25
+ continue;
26
+ const item = raw;
27
+ const key = typeof item.key === 'string' ? item.key : null;
28
+ if (key === null || !batchKeys.has(key) || out.has(key))
29
+ continue;
30
+ const evidence = Array.isArray(item.evidence) ? [...new Set(item.evidence.filter((e) => typeof e === 'string' && columns.has(e)))] : [];
31
+ const label = typeof item.label === 'string' && labels.has(item.label) && evidence.length > 0 ? item.label : null;
32
+ out.set(key, { label, evidence: label ? evidence : [] });
33
+ }
34
+ return out;
35
+ }
36
+ export const aiClassifyNode = {
37
+ type: 'ai.classify', title: 'AI classify rows', category: 'ai',
38
+ doc: 'Label each row with one of the listed categories using the host AI model. Rows carry an outcome (classified, unknown, failed, not-sent) and the columns cited as evidence. The run pauses for review of the labels.',
39
+ inputs: [{ name: 'table', type: TABLE_ITEM }],
40
+ outputs: [{ name: 'table', type: TABLE_ITEM }, { name: 'coverage', type: SCALAR_ITEM }],
41
+ params: [
42
+ { name: 'categories', kind: 'json', default: [], doc: '[{ "label": "...", "definition": "..." }]' },
43
+ { name: 'version', kind: 'string', default: '1', doc: 'Version of the category definitions, kept with the result.' },
44
+ { name: 'columns', kind: 'json', default: [], doc: 'Columns sent to the model; select at least one explicitly.' },
45
+ { name: 'maxRows', kind: 'number', default: 200 },
46
+ { name: 'batchSize', kind: 'number', default: 25 },
47
+ { name: 'maxOutputTokens', kind: 'number', default: 2000, doc: 'Output ceiling per request.' },
48
+ ],
49
+ capabilities: [AI_CAPABILITY], requires: { backend: [AI_FEATURE], network: true }, volatile: true, review: 'required',
50
+ run: async (ctx, inputs, p) => {
51
+ const table = inputs.table;
52
+ const categories = categoriesOf(p.categories);
53
+ const columns = sentColumns(table, Array.isArray(p.columns) ? p.columns.map(String) : []);
54
+ const maxRows = positiveInt(p.maxRows, 'maxRows', 5000);
55
+ const batchSize = positiveInt(p.batchSize, 'batchSize', 100);
56
+ const maxOutputTokens = positiveInt(p.maxOutputTokens, 'maxOutputTokens', 32_000);
57
+ const service = aiService(ctx);
58
+ const keys = rowKeys(table);
59
+ const outcome = keys.map(() => 'not-sent');
60
+ const label = keys.map(() => null);
61
+ const evidence = keys.map(() => []);
62
+ const labels = new Set(categories.map((c) => c.label));
63
+ const task = [
64
+ `Classify each data row into exactly one category (definitions version ${String(p.version)}):`,
65
+ ...categories.map((c) => `- ${c.label}: ${c.definition}`),
66
+ 'Reply {"items":[{"key":"<row key>","label":"<category label or unknown>","evidence":["<column name>"]}]} with one item per row.',
67
+ 'Cite the column names whose values justify the label. Use "unknown" when the data does not decide it.',
68
+ ].join('\n');
69
+ let requests = 0;
70
+ const sendable = keys.map((_, i) => i).slice(0, maxRows);
71
+ for (let start = 0; start < sendable.length; start += batchSize) {
72
+ const batch = sendable.slice(start, start + batchSize);
73
+ const reply = await requestJson(ctx, service, task, dataBlock(table, keys, batch, columns), maxOutputTokens, classificationSchema(batch.map(i => keys[i]), [...labels], columns), 'flow.ai.classify.v1');
74
+ if (reply.kind === 'budget') {
75
+ ctx.log('warn', `the AI budget ran out after ${requests} request(s); ${sendable.length - start} row(s) were not sent`);
76
+ break;
77
+ }
78
+ requests += 1;
79
+ if (reply.kind === 'failed' || !Array.isArray(reply.value.items)) {
80
+ ctx.log('warn', `rows ${start + 1}-${start + batch.length}: ${reply.kind === 'failed' ? reply.message : 'the reply has no items array'}`);
81
+ for (const i of batch)
82
+ outcome[i] = 'failed';
83
+ continue;
84
+ }
85
+ const read = readClassifications(reply.value, new Set(batch.map((i) => keys[i])), labels, new Set(columns));
86
+ for (const i of batch) {
87
+ const r = read.get(keys[i]);
88
+ label[i] = r?.label ?? null;
89
+ evidence[i] = r?.evidence ?? [];
90
+ outcome[i] = r === undefined ? 'failed' : r.label ? 'classified' : 'unknown';
91
+ }
92
+ }
93
+ if (keys.length > maxRows)
94
+ ctx.log('warn', `${keys.length - maxRows} row(s) beyond maxRows ${maxRows} were not sent`);
95
+ const count = (o) => outcome.filter((x) => x === o).length;
96
+ const result = {
97
+ key: 'key',
98
+ columns: [
99
+ { name: 'key', type: 'identifier' }, { name: 'label', type: 'label' },
100
+ { name: 'evidence', type: 'text' }, { name: 'outcome', type: 'enum' },
101
+ ],
102
+ rows: keys.map((key, i) => ({ key, label: label[i], evidence: evidence[i].join(', '), outcome: outcome[i] })),
103
+ };
104
+ return {
105
+ table: result,
106
+ coverage: {
107
+ model: service.model, categoriesVersion: String(p.version), rows: keys.length, requests,
108
+ classified: count('classified'), unknown: count('unknown'), failed: count('failed'), notSent: count('not-sent'),
109
+ },
110
+ };
111
+ },
112
+ };
113
+ //# sourceMappingURL=ai-classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-classify.js","sourceRoot":"","sources":["../src/ai-classify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `ai.extract` (#6923): typed candidate records from supplied text passages.
3
+ *
4
+ * Each record names the passage it came from and quotes a source span. A
5
+ * record is `supported` only when that span occurs verbatim in its passage
6
+ * and every value has its field's type; otherwise it is kept as
7
+ * `unsupported` with the offending values blanked, so a reviewer sees what
8
+ * the model claimed. This is a quote-and-type check, not a semantic check
9
+ * that the quoted text entails each typed value. All records remain candidates
10
+ * awaiting human review. Passages beyond
11
+ * `maxPassages`, or past a budget stop, are reported as not sent. The run
12
+ * pauses here for review.
13
+ */
14
+ import type { Cell } from '@ifc-lite/flow';
15
+ import type { FlowNodeDef } from './host.js';
16
+ type FieldType = 'string' | 'number' | 'boolean';
17
+ interface Field {
18
+ readonly name: string;
19
+ readonly type: FieldType;
20
+ readonly description: string;
21
+ }
22
+ /** One reply's records, checked against their passages. */
23
+ export declare function readRecords(value: Record<string, unknown>, passages: ReadonlyMap<number, string>, fields: readonly Field[]): Record<string, Cell>[];
24
+ export declare const aiExtractNode: FlowNodeDef;
25
+ export {};
26
+ //# sourceMappingURL=ai-extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-extract.d.ts","sourceRoot":"","sources":["../src/ai-extract.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,gBAAgB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,KAAK,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AACjD,UAAU,KAAK;IAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AAiBjG,2DAA2D;AAC3D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAsBnJ;AAID,eAAO,MAAM,aAAa,EAAE,WAmE3B,CAAC"}
@@ -0,0 +1,127 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { SCALAR_ITEM, SCALAR_LIST, TABLE_ITEM } from './ports.js';
5
+ import { AI_CAPABILITY, AI_FEATURE, aiService, positiveInt, requestJson } from './ai-service.js';
6
+ import { extractionSchema } from './ai-response-schemas.js';
7
+ const RESERVED = new Set(['passage', 'span', 'outcome']);
8
+ function fieldsOf(value) {
9
+ if (!Array.isArray(value) || value.length === 0 || value.length > 30)
10
+ throw new Error('"fields" must list 1 to 30 { name, type, description } entries');
11
+ const seen = new Set();
12
+ return value.map((f, i) => {
13
+ const name = typeof f?.name === 'string' ? f.name.trim() : '';
14
+ const type = f?.type;
15
+ if (!/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(name) || RESERVED.has(name) || seen.has(name))
16
+ throw new Error(`field ${i + 1} needs a unique identifier name other than passage, span or outcome`);
17
+ if (type !== 'string' && type !== 'number' && type !== 'boolean')
18
+ throw new Error(`field "${name}" must have type string, number or boolean`);
19
+ seen.add(name);
20
+ return { name, type, description: typeof f.description === 'string' ? f.description.slice(0, 300) : '' };
21
+ });
22
+ }
23
+ /** One reply's records, checked against their passages. */
24
+ export function readRecords(value, passages, fields) {
25
+ const records = Array.isArray(value.records) ? value.records : [];
26
+ return records.flatMap((raw) => {
27
+ if (!raw || typeof raw !== 'object')
28
+ return [];
29
+ const record = raw;
30
+ const passage = typeof record.passage === 'number' ? record.passage : -1;
31
+ const source = passages.get(passage);
32
+ if (source === undefined)
33
+ return [];
34
+ const sourceSpan = typeof record.span === 'string' ? record.span : '';
35
+ const span = sourceSpan.slice(0, 1000);
36
+ const values = record.values && typeof record.values === 'object' ? record.values : {};
37
+ let supported = sourceSpan.length > 0 && sourceSpan.length <= 1000 && source.includes(sourceSpan);
38
+ const row = { passage, span };
39
+ for (const f of fields) {
40
+ const v = values[f.name];
41
+ const ok = v === null || v === undefined || (f.type === 'number' ? typeof v === 'number' && Number.isFinite(v) : typeof v === f.type);
42
+ if (!ok)
43
+ supported = false;
44
+ row[f.name] = ok && v !== undefined ? v : null;
45
+ }
46
+ row.outcome = supported ? 'supported' : 'unsupported';
47
+ return [row];
48
+ });
49
+ }
50
+ const COLUMN_TYPE = { string: 'text', number: 'real', boolean: 'boolean' };
51
+ export const aiExtractNode = {
52
+ type: 'ai.extract', title: 'AI extract records', category: 'ai',
53
+ doc: 'Extract typed records from text passages using the host AI model. Each record quotes its source span; records whose span is not in the passage or whose values have the wrong type are marked unsupported. The run pauses for review of the records.',
54
+ inputs: [{ name: 'passages', type: SCALAR_LIST }],
55
+ outputs: [{ name: 'records', type: TABLE_ITEM }, { name: 'coverage', type: SCALAR_ITEM }],
56
+ params: [
57
+ { name: 'fields', kind: 'json', default: [], doc: '[{ "name": "...", "type": "string|number|boolean", "description": "..." }]' },
58
+ { name: 'maxPassages', kind: 'number', default: 50 },
59
+ { name: 'batchSize', kind: 'number', default: 10 },
60
+ { name: 'maxRecords', kind: 'number', default: 200 },
61
+ { name: 'maxOutputTokens', kind: 'number', default: 2000 },
62
+ ],
63
+ capabilities: [AI_CAPABILITY], requires: { backend: [AI_FEATURE], network: true }, volatile: true, review: 'required',
64
+ run: async (ctx, inputs, p) => {
65
+ const passages = inputs.passages.map((v) => (typeof v === 'string' ? v : v === null || v === undefined ? '' : String(v)));
66
+ const fields = fieldsOf(p.fields);
67
+ const maxPassages = positiveInt(p.maxPassages, 'maxPassages', 1000);
68
+ const batchSize = positiveInt(p.batchSize, 'batchSize', 50);
69
+ const maxRecords = positiveInt(p.maxRecords, 'maxRecords', 5000);
70
+ const maxOutputTokens = positiveInt(p.maxOutputTokens, 'maxOutputTokens', 32_000);
71
+ const service = aiService(ctx);
72
+ const task = [
73
+ 'Extract records with these fields from the passages:',
74
+ ...fields.map((f) => `- ${f.name} (${f.type}): ${f.description}`),
75
+ 'Reply {"records":[{"passage":<passage number>,"span":"<exact quote from that passage>","values":{...}}]}.',
76
+ 'Quote the span verbatim. Use null for a value the passage does not state.',
77
+ ].join('\n');
78
+ const rows = [];
79
+ let requests = 0;
80
+ let sent = 0;
81
+ let failed = 0;
82
+ const sendable = Math.min(passages.length, maxPassages);
83
+ for (let start = 0; start < sendable && rows.length < maxRecords; start += batchSize) {
84
+ const batch = new Map();
85
+ for (let i = start; i < Math.min(start + batchSize, sendable); i++)
86
+ batch.set(i, passages[i].slice(0, 8000));
87
+ const data = [...batch].map(([i, t]) => JSON.stringify({ passage: i, text: t })).join('\n');
88
+ const reply = await requestJson(ctx, service, task, `<data>\n${data}\n</data>`, maxOutputTokens, extractionSchema([...batch.keys()], fields), 'flow.ai.extract.v1');
89
+ if (reply.kind === 'budget') {
90
+ ctx.log('warn', `the AI budget ran out after ${requests} request(s)`);
91
+ break;
92
+ }
93
+ requests += 1;
94
+ sent += batch.size;
95
+ if (reply.kind === 'failed') {
96
+ failed += batch.size;
97
+ ctx.log('warn', `passages ${start + 1}-${start + batch.size}: ${reply.message}`);
98
+ continue;
99
+ }
100
+ if (!Array.isArray(reply.value.records)) {
101
+ failed += batch.size;
102
+ ctx.log('warn', `passages ${start + 1}-${start + batch.size}: reply must contain a records array`);
103
+ continue;
104
+ }
105
+ rows.push(...readRecords(reply.value, batch, fields));
106
+ }
107
+ if (rows.length > maxRecords)
108
+ ctx.log('warn', `${rows.length - maxRecords} record(s) beyond maxRecords were dropped`);
109
+ const kept = rows.slice(0, maxRecords);
110
+ const records = {
111
+ key: 'passage',
112
+ columns: [
113
+ { name: 'passage', type: 'integer' }, ...fields.map((f) => ({ name: f.name, type: COLUMN_TYPE[f.type] })),
114
+ { name: 'span', type: 'text' }, { name: 'outcome', type: 'enum' },
115
+ ],
116
+ rows: kept,
117
+ };
118
+ return {
119
+ records,
120
+ coverage: {
121
+ model: service.model, passages: passages.length, sent, failed, notSent: passages.length - sent, requests,
122
+ records: kept.length, unsupported: kept.filter((r) => r.outcome === 'unsupported').length,
123
+ },
124
+ };
125
+ },
126
+ };
127
+ //# sourceMappingURL=ai-extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-extract.js","sourceRoot":"","sources":["../src/ai-extract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** #7070: native field constraints for portable model-change drafts. */
2
+ import { type ChangeScalar, type ModelChange } from '@ifc-lite/ai/artifacts';
3
+ export interface ProposalField {
4
+ readonly native: ModelChange;
5
+ readonly expectedColumn: string;
6
+ readonly allowedValues: readonly ChangeScalar[];
7
+ }
8
+ /** Native parsing checks each allowed value's IFC type, rather than copying that validator. */
9
+ export declare function proposalFields(raw: unknown, columns: readonly string[]): ProposalField[];
10
+ /** Every effect field and candidate value must be explicitly allowed by the graph. */
11
+ export declare function constrainedField(change: ModelChange, fields: readonly ProposalField[]): ProposalField;
12
+ //# sourceMappingURL=ai-propose-fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-propose-fields.d.ts","sourceRoot":"","sources":["../src/ai-propose-fields.ts"],"names":[],"mappings":"AAIA,wEAAwE;AACxE,OAAO,EAAoC,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE/G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAC;CACjD;AAKD,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,EAAE,CA4BxF;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,CAQrG"}
@@ -0,0 +1,57 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /** #7070: native field constraints for portable model-change drafts. */
5
+ import { changeKey, parseModelChangeBatch } from '@ifc-lite/ai/artifacts';
6
+ const sampleTarget = { globalId: '0000000000000000000000' };
7
+ const fieldKey = (change) => changeKey({ ...change, target: sampleTarget });
8
+ const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
9
+ /** Native parsing checks each allowed value's IFC type, rather than copying that validator. */
10
+ export function proposalFields(raw, columns) {
11
+ if (!Array.isArray(raw) || !raw.length || raw.length > 50)
12
+ throw new Error('Select 1 to 50 native fields for the proposal');
13
+ const seen = new Set();
14
+ return raw.map((value, index) => {
15
+ if (!record(value))
16
+ throw new Error(`Field ${index + 1} must be an object`);
17
+ const { expectedColumn, allowedValues, ...binding } = value;
18
+ const keys = ['op', 'name', 'pset', 'qset', 'dataType'];
19
+ if (Object.keys(binding).some(key => !keys.includes(key)))
20
+ throw new Error(`Field ${index + 1} has an unknown constraint`);
21
+ if (typeof expectedColumn !== 'string' || !columns.includes(expectedColumn))
22
+ throw new Error(`Field ${index + 1} needs a selected expectedColumn`);
23
+ const deleting = binding.op === 'property.delete';
24
+ if (deleting ? allowedValues !== undefined : !Array.isArray(allowedValues) || !allowedValues.length || allowedValues.length > 20) {
25
+ throw new Error('Set fields need 1 to 20 allowedValues; delete fields must omit them');
26
+ }
27
+ const values = deleting ? ['existing value'] : allowedValues;
28
+ const parsed = values.map(candidate => parseModelChangeBatch(JSON.stringify({ version: 1, kind: 'model.changes', title: 'Field constraint', changes: [{
29
+ ...binding, target: sampleTarget, expected: deleting ? 'existing value' : binding.op === 'attribute.set' ? '' : binding.op === 'quantity.set' ? 0 : null,
30
+ ...(!deleting ? { value: candidate } : {}),
31
+ }] })).changes[0]);
32
+ const native = parsed[0];
33
+ // Cross-operation fields must not smuggle unused binding names into the prompt.
34
+ const allowedKeys = native.op === 'property.set' ? ['op', 'name', 'pset', 'dataType']
35
+ : native.op === 'property.delete' ? ['op', 'name', 'pset'] : native.op === 'quantity.set' ? ['op', 'name', 'qset'] : ['op', 'name'];
36
+ if (Object.keys(binding).some(key => !allowedKeys.includes(key)))
37
+ throw new Error(`Field ${index + 1} has a binding for another operation`);
38
+ const key = fieldKey(native);
39
+ if (seen.has(key))
40
+ throw new Error('Each native value may have only one field constraint');
41
+ seen.add(key);
42
+ return { native, expectedColumn, allowedValues: deleting ? [] : parsed.map(change => 'value' in change ? change.value : null) };
43
+ });
44
+ }
45
+ /** Every effect field and candidate value must be explicitly allowed by the graph. */
46
+ export function constrainedField(change, fields) {
47
+ const field = fields.find(candidate => fieldKey(candidate.native) === fieldKey(change) && candidate.native.op === change.op);
48
+ if (!field)
49
+ throw new Error('The proposed change is outside the selected native fields');
50
+ if (change.op === 'property.set' && field.native.op === 'property.set' && change.dataType !== field.native.dataType) {
51
+ throw new Error('The proposed property dataType differs from its native field constraint');
52
+ }
53
+ if ('value' in change && !field.allowedValues.some(value => Object.is(value, change.value)))
54
+ throw new Error('The proposed value is outside allowedValues');
55
+ return field;
56
+ }
57
+ //# sourceMappingURL=ai-propose-fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-propose-fields.js","sourceRoot":"","sources":["../src/ai-propose-fields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FlowNodeDef } from './host.js';
2
+ export declare const aiProposeNode: FlowNodeDef;
3
+ //# sourceMappingURL=ai-propose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-propose.d.ts","sourceRoot":"","sources":["../src/ai-propose.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAK7C,eAAO,MAAM,aAAa,EAAE,WAoE3B,CAAC"}
@@ -0,0 +1,94 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /** #7070: one constrained portable draft; never native writes or publication. */
5
+ import { MODEL_CHANGE_LIMIT, MODEL_DATA_CHANGE_OUTPUT_GUIDANCE, parseModelChangeBatch } from '@ifc-lite/ai/artifacts';
6
+ import { SCALAR_ITEM, TABLE_ITEM } from './ports.js';
7
+ import { AI_CAPABILITY, AI_FEATURE, aiService, dataBlock, positiveInt, requestJson, rowKeys, sentColumns } from './ai-service.js';
8
+ import { constrainedField, proposalFields } from './ai-propose-fields.js';
9
+ import { proposalSchema } from './ai-response-schemas.js';
10
+ export const aiProposeNode = {
11
+ type: 'ai.propose', title: 'AI propose a native artifact', category: 'ai',
12
+ doc: 'Draft a model.changes artifact over explicitly selected findings and native fields. Every change cites one captured row, copies its expected value and uses an allowed candidate value. No effects run before checkpoint review; current values and permissions still need native mutation preflight.',
13
+ inputs: [{ name: 'table', type: TABLE_ITEM }],
14
+ outputs: [{ name: 'proposal', type: SCALAR_ITEM }, { name: 'coverage', type: SCALAR_ITEM }],
15
+ params: [
16
+ { name: 'artifactKind', kind: 'string', default: 'model.changes', doc: 'Closed native allowlist: model.changes. Unsupported kinds are refused before spending.' },
17
+ { name: 'instructions', kind: 'string', default: '', doc: 'The requested correction policy; rows are evidence, never instructions.' },
18
+ { name: 'columns', kind: 'json', default: [], doc: 'Columns explicitly sent to the model, including target and expected-value columns.' },
19
+ { name: 'targetColumn', kind: 'string', default: 'GlobalId' },
20
+ { name: 'modelColumn', kind: 'string', default: '', doc: 'Optional selected column of native model ids; required to disambiguate a shared GlobalId.' },
21
+ { name: 'fields', kind: 'json', default: [], doc: '[{ "op":"property.set", "pset":"Pset_WallCommon", "name":"IsExternal", "expectedColumn":"IsExternal", "allowedValues":[true], "dataType":"IfcBoolean" }]' },
22
+ { name: 'maxRows', kind: 'number', default: 200 },
23
+ { name: 'maxChanges', kind: 'number', default: 100 },
24
+ { name: 'maxOutputTokens', kind: 'number', default: 2000 },
25
+ ],
26
+ capabilities: [AI_CAPABILITY], requires: { backend: [AI_FEATURE], network: true }, volatile: true, review: 'required',
27
+ run: async (ctx, inputs, p) => {
28
+ if (p.artifactKind !== 'model.changes')
29
+ throw new Error('This host supports only the model.changes artifact kind');
30
+ if (typeof p.instructions !== 'string' || !p.instructions.trim() || p.instructions.length > 4000)
31
+ throw new Error('Supply a bounded correction policy');
32
+ const table = inputs.table;
33
+ const columns = sentColumns(table, Array.isArray(p.columns) ? p.columns.map(String) : []);
34
+ if (typeof p.targetColumn !== 'string' || !columns.includes(p.targetColumn))
35
+ throw new Error('Select the target GlobalId column');
36
+ const targetColumn = p.targetColumn;
37
+ if (typeof p.modelColumn !== 'string' || (p.modelColumn && !columns.includes(p.modelColumn)))
38
+ throw new Error('Select the native model id column');
39
+ const modelColumn = p.modelColumn;
40
+ const fields = proposalFields(p.fields, columns);
41
+ const maxRows = positiveInt(p.maxRows, 'maxRows', MODEL_CHANGE_LIMIT);
42
+ const maxChanges = positiveInt(p.maxChanges, 'maxChanges', MODEL_CHANGE_LIMIT);
43
+ const maxOutputTokens = positiveInt(p.maxOutputTokens, 'maxOutputTokens', 32_000);
44
+ const sent = { ...table, rows: table.rows.slice(0, maxRows) };
45
+ if (!sent.rows.length)
46
+ throw new Error('There are no findings to propose changes for');
47
+ for (const row of sent.rows) {
48
+ if (typeof row[targetColumn] !== 'string' || !/^[0-9A-Za-z_$]{22}$/.test(row[targetColumn]))
49
+ throw new Error('Every sent finding needs a native IFC GlobalId');
50
+ if (modelColumn && (typeof row[modelColumn] !== 'string' || !String(row[modelColumn]).trim()))
51
+ throw new Error('Every sent finding needs a native model id');
52
+ }
53
+ const keys = rowKeys(sent), known = new Set(keys);
54
+ const task = `${MODEL_DATA_CHANGE_OUTPUT_GUIDANCE}\nReply {"artifact":<model.changes>,"citations":["<row key>"],"clarification":null}. Each change must match exactly one cited row. Use targetColumn ${JSON.stringify(targetColumn)} and modelColumn ${JSON.stringify(modelColumn)}; copy each expected value from its field's expectedColumn. Never propose more than ${maxChanges} changes. Use only the supplied fields and allowedValues. If evidence cannot decide, return {"artifact":null,"citations":[],"clarification":"What input is missing"}.\nRequested policy: ${p.instructions}\nField constraints: ${JSON.stringify(p.fields)}`;
55
+ const service = aiService(ctx);
56
+ const reply = await requestJson(ctx, service, task, dataBlock(sent, keys, keys.map((_, index) => index), columns), maxOutputTokens, proposalSchema(fields, keys, !!modelColumn), 'flow.ai.propose.v1');
57
+ if (reply.kind !== 'value')
58
+ throw new Error(reply.kind === 'budget' ? 'The AI proposal budget is exhausted' : reply.message);
59
+ if (reply.value.kind === 'clarification')
60
+ throw new Error(`Proposal needs clarification: ${String(reply.value.message ?? 'Missing evidence').slice(0, 1000)}`);
61
+ if (typeof reply.value.clarification === 'string')
62
+ throw new Error(`Proposal needs clarification: ${reply.value.clarification.slice(0, 1000)}`);
63
+ if (reply.value.clarification !== undefined && reply.value.clarification !== null)
64
+ throw new Error('Invalid proposal clarification');
65
+ if (Object.keys(reply.value).some(key => key !== 'artifact' && key !== 'citations' && key !== 'clarification'))
66
+ throw new Error('Unknown proposal envelope field');
67
+ const citations = reply.value.citations;
68
+ if (!Array.isArray(citations) || !citations.length || citations.some(key => typeof key !== 'string' || !known.has(key)) || new Set(citations).size !== citations.length) {
69
+ throw new Error('The proposal must cite distinct sent finding keys');
70
+ }
71
+ if (!reply.value.artifact || typeof reply.value.artifact !== 'object' || Array.isArray(reply.value.artifact))
72
+ throw new Error('A native model.changes artifact is required');
73
+ const artifact = parseModelChangeBatch(JSON.stringify(reply.value.artifact));
74
+ if (artifact.changes.length > maxChanges)
75
+ throw new Error('The proposal exceeds maxChanges');
76
+ const used = new Set();
77
+ for (const change of artifact.changes) {
78
+ const field = constrainedField(change, fields);
79
+ const matches = sent.rows.map((row, index) => ({ row, key: keys[index] })).filter(({ row, key }) => citations.includes(key) && row[targetColumn] === change.target.globalId
80
+ && (modelColumn ? row[modelColumn] === change.target.modelId : change.target.modelId === undefined));
81
+ if (matches.length !== 1)
82
+ throw new Error('A proposed target is absent or ambiguous in the cited findings');
83
+ const { row, key } = matches[0];
84
+ if (!Object.hasOwn(row, field.expectedColumn) || !Object.is(row[field.expectedColumn], change.expected))
85
+ throw new Error('The proposed expected value differs from the captured finding');
86
+ used.add(key);
87
+ }
88
+ if (used.size !== citations.length)
89
+ throw new Error('The proposal cites rows without a proposed change');
90
+ return { proposal: { artifact, citations }, coverage: { model: service.model, kind: 'model.changes', rows: table.rows.length,
91
+ sent: sent.rows.length, notSent: table.rows.length - sent.rows.length, requests: 1, changes: artifact.changes.length, citedRows: used.size } };
92
+ },
93
+ };
94
+ //# sourceMappingURL=ai-propose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-propose.js","sourceRoot":"","sources":["../src/ai-propose.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Native Flow JSON shapes, shared by every provider and host (#7132). */
2
+ import type { JsonResponseSchema } from '@ifc-lite/ai';
3
+ import type { ProposalField } from './ai-propose-fields.js';
4
+ export declare function classificationSchema(keys: readonly string[], labels: readonly string[], columns: readonly string[]): JsonResponseSchema;
5
+ export declare function extractionSchema(passages: readonly number[], fields: readonly {
6
+ name: string;
7
+ type: string;
8
+ }[]): JsonResponseSchema;
9
+ export declare function summarySchema(keys: readonly string[]): JsonResponseSchema;
10
+ export declare function proposalSchema(fields: readonly ProposalField[], keys: readonly string[], withModel: boolean): JsonResponseSchema;
11
+ //# sourceMappingURL=ai-response-schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-response-schemas.d.ts","sourceRoot":"","sources":["../src/ai-response-schemas.ts"],"names":[],"mappings":"AAIA,0EAA0E;AAC1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAc5D,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CAIvI;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,kBAAkB,CAKnI;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CAIzE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,OAAO,GAAG,kBAAkB,CAehI"}