opentakeoff-mcp 0.9.85 → 0.9.86
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/server-core.js +136 -87
- package/package.json +2 -2
package/dist/server-core.js
CHANGED
|
@@ -1461,8 +1461,8 @@ function sweepHatchRuns(segs, meta, ws) {
|
|
|
1461
1461
|
clusters.pop();
|
|
1462
1462
|
}
|
|
1463
1463
|
}
|
|
1464
|
-
const median2 = (
|
|
1465
|
-
const a =
|
|
1464
|
+
const median2 = (arr3) => {
|
|
1465
|
+
const a = arr3.slice().sort((x, y) => x - y);
|
|
1466
1466
|
return a[a.length >> 1];
|
|
1467
1467
|
};
|
|
1468
1468
|
for (const members of clusters) {
|
|
@@ -1590,8 +1590,8 @@ function classifyOffsetAnnotationSegs(segs, meta, ws, maxOffsetPx, minOffsetPx,
|
|
|
1590
1590
|
t1: Math.max(c.x1 * dxu + c.y1 * dyu, c.x2 * dxu + c.y2 * dyu),
|
|
1591
1591
|
w: c.w
|
|
1592
1592
|
};
|
|
1593
|
-
const
|
|
1594
|
-
if (
|
|
1593
|
+
const arr3 = bins.get(b);
|
|
1594
|
+
if (arr3) arr3.push(r);
|
|
1595
1595
|
else bins.set(b, [r]);
|
|
1596
1596
|
}
|
|
1597
1597
|
for (const runs of bins.values()) {
|
|
@@ -1768,8 +1768,8 @@ function sweepDimensionStrings(segs, meta, ws, ftPx, rejects, dimTexts) {
|
|
|
1768
1768
|
t0: Math.min(c.x1 * dx + c.y1 * dy, c.x2 * dx + c.y2 * dy),
|
|
1769
1769
|
t1: Math.max(c.x1 * dx + c.y1 * dy, c.x2 * dx + c.y2 * dy)
|
|
1770
1770
|
};
|
|
1771
|
-
const
|
|
1772
|
-
if (
|
|
1771
|
+
const arr3 = bins.get(b);
|
|
1772
|
+
if (arr3) arr3.push(r);
|
|
1773
1773
|
else bins.set(b, [r]);
|
|
1774
1774
|
}
|
|
1775
1775
|
for (const [b, rows] of bins) {
|
|
@@ -6658,12 +6658,12 @@ function applyRuleToProject(rule, shapes, sheetData) {
|
|
|
6658
6658
|
const d = sheetData.get(s.sheet_id);
|
|
6659
6659
|
if (!d) continue;
|
|
6660
6660
|
const ring = s.verts_norm.map(([nx, ny]) => [nx * d.imgW, ny * d.imgH]);
|
|
6661
|
-
let
|
|
6662
|
-
if (!
|
|
6663
|
-
|
|
6664
|
-
deductsBySheet.set(s.sheet_id,
|
|
6661
|
+
let arr3 = deductsBySheet.get(s.sheet_id);
|
|
6662
|
+
if (!arr3) {
|
|
6663
|
+
arr3 = [];
|
|
6664
|
+
deductsBySheet.set(s.sheet_id, arr3);
|
|
6665
6665
|
}
|
|
6666
|
-
|
|
6666
|
+
arr3.push(ring);
|
|
6667
6667
|
}
|
|
6668
6668
|
const out = [];
|
|
6669
6669
|
const acceptedBySheet = /* @__PURE__ */ new Map();
|
|
@@ -6688,12 +6688,12 @@ function applyRuleToProject(rule, shapes, sheetData) {
|
|
|
6688
6688
|
verts_norm: ring.map(([x, y]) => [x / d.imgW, y / d.imgH]),
|
|
6689
6689
|
area_sf: +areaSf.toFixed(2)
|
|
6690
6690
|
});
|
|
6691
|
-
let
|
|
6692
|
-
if (!
|
|
6693
|
-
|
|
6694
|
-
acceptedBySheet.set(room.sheet_id,
|
|
6691
|
+
let arr3 = acceptedBySheet.get(room.sheet_id);
|
|
6692
|
+
if (!arr3) {
|
|
6693
|
+
arr3 = [];
|
|
6694
|
+
acceptedBySheet.set(room.sheet_id, arr3);
|
|
6695
6695
|
}
|
|
6696
|
-
|
|
6696
|
+
arr3.push(ring);
|
|
6697
6697
|
}
|
|
6698
6698
|
}
|
|
6699
6699
|
return out;
|
|
@@ -7712,11 +7712,82 @@ function drawMarks(ctx, toCanvas, marks, longEdge) {
|
|
|
7712
7712
|
return drawn;
|
|
7713
7713
|
}
|
|
7714
7714
|
|
|
7715
|
+
// ../web/src/lib/takeoffDocument.js
|
|
7716
|
+
var arr = (v) => Array.isArray(v) ? v : [];
|
|
7717
|
+
var obj = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
7718
|
+
var TAKEOFF_DOCUMENT_KEYS = Object.freeze([
|
|
7719
|
+
"schema",
|
|
7720
|
+
"project_name",
|
|
7721
|
+
"units",
|
|
7722
|
+
"client_info",
|
|
7723
|
+
"sheets",
|
|
7724
|
+
"conditions",
|
|
7725
|
+
"condition_columns",
|
|
7726
|
+
"shape_labels",
|
|
7727
|
+
"palette",
|
|
7728
|
+
"shapes",
|
|
7729
|
+
"markups",
|
|
7730
|
+
"rfis",
|
|
7731
|
+
"approvals",
|
|
7732
|
+
"proposals",
|
|
7733
|
+
"condition_edit_proposals",
|
|
7734
|
+
"rules",
|
|
7735
|
+
"sheet_group",
|
|
7736
|
+
"last_group",
|
|
7737
|
+
"sheet_tabs",
|
|
7738
|
+
"stitches",
|
|
7739
|
+
"sheet_levels",
|
|
7740
|
+
"layer_overrides",
|
|
7741
|
+
"provenance_counters"
|
|
7742
|
+
]);
|
|
7743
|
+
function sheetEntry({ sheet_id, units_per_px, scale_source = void 0, scale_confirmed = void 0 }) {
|
|
7744
|
+
return {
|
|
7745
|
+
sheet_id,
|
|
7746
|
+
units_per_px,
|
|
7747
|
+
...scale_source ? { scale_source } : {},
|
|
7748
|
+
...scale_confirmed === false ? { scale_confirmed: false } : {}
|
|
7749
|
+
};
|
|
7750
|
+
}
|
|
7751
|
+
function buildTakeoffDocument(f = {}) {
|
|
7752
|
+
const conditions = arr(f.conditions);
|
|
7753
|
+
const pinned = arr(f.palette).filter((id) => conditions.some((c) => c && c.id === id));
|
|
7754
|
+
const clientInfo = obj(f.client_info);
|
|
7755
|
+
const hasClient = Object.values(clientInfo).some((v) => v && String(v).trim());
|
|
7756
|
+
const sheetLevels = obj(f.sheet_levels);
|
|
7757
|
+
const layerOverrides = obj(f.layer_overrides);
|
|
7758
|
+
const prov = f.provenance_counters;
|
|
7759
|
+
const hasProv = !!(prov && prov.shapes_deleted && Object.keys(prov.shapes_deleted).length);
|
|
7760
|
+
return {
|
|
7761
|
+
schema: TAKEOFF_SCHEMA,
|
|
7762
|
+
project_name: typeof f.project_name === "string" ? f.project_name : "",
|
|
7763
|
+
...f.units === "metric" ? { units: "metric" } : {},
|
|
7764
|
+
...hasClient ? { client_info: clientInfo } : {},
|
|
7765
|
+
sheets: arr(f.sheets),
|
|
7766
|
+
conditions,
|
|
7767
|
+
...arr(f.condition_columns).length ? { condition_columns: f.condition_columns } : {},
|
|
7768
|
+
...arr(f.shape_labels).length ? { shape_labels: f.shape_labels } : {},
|
|
7769
|
+
...pinned.length ? { palette: pinned } : {},
|
|
7770
|
+
shapes: arr(f.shapes),
|
|
7771
|
+
markups: arr(f.markups),
|
|
7772
|
+
rfis: arr(f.rfis),
|
|
7773
|
+
...arr(f.approvals).length ? { approvals: f.approvals } : {},
|
|
7774
|
+
...arr(f.proposals).length ? { proposals: f.proposals } : {},
|
|
7775
|
+
...arr(f.condition_edit_proposals).length ? { condition_edit_proposals: f.condition_edit_proposals } : {},
|
|
7776
|
+
...arr(f.rules).length ? { rules: f.rules } : {},
|
|
7777
|
+
sheet_group: arr(f.sheet_group),
|
|
7778
|
+
last_group: arr(f.last_group),
|
|
7779
|
+
sheet_tabs: arr(f.sheet_tabs),
|
|
7780
|
+
...arr(f.stitches).length ? { stitches: f.stitches } : {},
|
|
7781
|
+
...Object.keys(sheetLevels).length ? { sheet_levels: sheetLevels } : {},
|
|
7782
|
+
...Object.keys(layerOverrides).length ? { layer_overrides: layerOverrides } : {},
|
|
7783
|
+
...hasProv ? { provenance_counters: prov } : {}
|
|
7784
|
+
};
|
|
7785
|
+
}
|
|
7786
|
+
|
|
7715
7787
|
// src/session.ts
|
|
7716
7788
|
var mintUuid2 = () => globalThis.crypto && typeof globalThis.crypto.randomUUID === "function" ? globalThis.crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
7717
7789
|
var uid = (p) => `${p}-${mintUuid2()}`;
|
|
7718
7790
|
var nowIso2 = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
7719
|
-
var ANN_SCHEMA = TAKEOFF_SCHEMA;
|
|
7720
7791
|
var sanitizeApprovals2 = sanitizeApprovals;
|
|
7721
7792
|
var applyApprovalCommand2 = applyApprovalCommand;
|
|
7722
7793
|
var CONTEXT_MIN_LEN_PX = 2;
|
|
@@ -8430,6 +8501,7 @@ var Session = class _Session {
|
|
|
8430
8501
|
const lc = nextPaletteColor(this.conditions.length);
|
|
8431
8502
|
c = {
|
|
8432
8503
|
id: uid("cnd"),
|
|
8504
|
+
created_at: nowIso2(),
|
|
8433
8505
|
finish_tag: tag,
|
|
8434
8506
|
color: lc,
|
|
8435
8507
|
fill: lc,
|
|
@@ -9637,9 +9709,9 @@ var Session = class _Session {
|
|
|
9637
9709
|
}
|
|
9638
9710
|
const tableRegions = /* @__PURE__ */ new Map();
|
|
9639
9711
|
for (const tb of graph.tables) {
|
|
9640
|
-
const
|
|
9641
|
-
|
|
9642
|
-
tableRegions.set(tb.sheet,
|
|
9712
|
+
const arr3 = tableRegions.get(tb.sheet) ?? [];
|
|
9713
|
+
arr3.push(tb.region);
|
|
9714
|
+
tableRegions.set(tb.sheet, arr3);
|
|
9643
9715
|
}
|
|
9644
9716
|
const VAL_RE = /^[0-9][0-9,]{0,6}$/;
|
|
9645
9717
|
const perMark = /* @__PURE__ */ new Map();
|
|
@@ -11505,41 +11577,18 @@ var Session = class _Session {
|
|
|
11505
11577
|
}
|
|
11506
11578
|
exportPayload() {
|
|
11507
11579
|
if (!this.docs.size) throw new UserError("No plan loaded \u2014 call load_plan first.");
|
|
11508
|
-
return {
|
|
11509
|
-
schema: ANN_SCHEMA,
|
|
11580
|
+
return buildTakeoffDocument({
|
|
11510
11581
|
project_name: "",
|
|
11511
11582
|
units: "imperial",
|
|
11512
|
-
sheets: [...this.sheets.values()].filter((s) => s.upp != null).map((s) => ({
|
|
11513
|
-
sheet_id: s.key,
|
|
11514
|
-
units_per_px: s.upp,
|
|
11515
|
-
// provenance rides the payload (it used to be dropped here): the canvas
|
|
11516
|
-
// hydrates scale_source for its report and scale_confirmed for the
|
|
11517
|
-
// scale gate's confirm affordance — absent = confirmed (pre-flag docs)
|
|
11518
|
-
...s.scaleSource ? { scale_source: s.scaleSource } : {},
|
|
11519
|
-
...s.scaleConfirmed === false ? { scale_confirmed: false } : {}
|
|
11520
|
-
})),
|
|
11583
|
+
sheets: [...this.sheets.values()].filter((s) => s.upp != null).map((s) => sheetEntry({ sheet_id: s.key, units_per_px: s.upp, scale_source: s.scaleSource, scale_confirmed: s.scaleConfirmed })),
|
|
11521
11584
|
conditions: this.conditions,
|
|
11522
11585
|
shapes: this.shapes,
|
|
11523
11586
|
markups: this.markups,
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
// has no tombstone notion (its delete is a removal), and a withdrawn
|
|
11530
|
-
// question must not resurface there as a stray Void row. Same
|
|
11531
|
-
// present-only-when-any convention as approvals.
|
|
11532
|
-
...this.liveRfis().length ? { rfis: this.liveRfis() } : {},
|
|
11533
|
-
// proposals (#365): the batches and the pending condition diffs ride
|
|
11534
|
-
// the payload as transport — present only when any exist, so a
|
|
11535
|
-
// proposal-free export stays byte-identical to a pre-#365 one.
|
|
11536
|
-
...this.proposals.length ? { proposals: this.proposals } : {},
|
|
11537
|
-
...this.conditionEditProposals.length ? { condition_edit_proposals: this.conditionEditProposals } : {},
|
|
11538
|
-
sheet_group: [],
|
|
11539
|
-
last_group: [],
|
|
11540
|
-
sheet_tabs: [],
|
|
11541
|
-
sheet_levels: {}
|
|
11542
|
-
};
|
|
11587
|
+
rfis: this.liveRfis(),
|
|
11588
|
+
approvals: this.approvals,
|
|
11589
|
+
proposals: this.proposals,
|
|
11590
|
+
condition_edit_proposals: this.conditionEditProposals
|
|
11591
|
+
});
|
|
11543
11592
|
}
|
|
11544
11593
|
/** The computed Report document — "opentakeoff.report.v1", the SAME schema
|
|
11545
11594
|
* and math as the canvas Report's JSON export (web reportJson, totals.js):
|
|
@@ -12169,7 +12218,7 @@ var exportDxfOutput = {
|
|
|
12169
12218
|
var exportTakeoffOutput = {
|
|
12170
12219
|
schema: z.string(),
|
|
12171
12220
|
project_name: z.string(),
|
|
12172
|
-
units: z.string(),
|
|
12221
|
+
units: z.string().optional().describe("Present only for a metric project; absent means imperial \u2014 the app's own diff-only convention"),
|
|
12173
12222
|
sheets: z.array(z.object({
|
|
12174
12223
|
sheet_id: z.string(),
|
|
12175
12224
|
units_per_px: z.number(),
|
|
@@ -12201,7 +12250,7 @@ var exportTakeoffOutput = {
|
|
|
12201
12250
|
sheet_group: z.array(z.unknown()),
|
|
12202
12251
|
last_group: z.array(z.unknown()),
|
|
12203
12252
|
sheet_tabs: z.array(z.unknown()),
|
|
12204
|
-
sheet_levels: z.object({}).passthrough(),
|
|
12253
|
+
sheet_levels: z.object({}).passthrough().optional().describe("Present only when a sheet carries a level label (the app omits it when empty)"),
|
|
12205
12254
|
proposals: z.array(z.object({ id: z.string(), label: z.string(), rationale: z.string(), created_at: z.string(), withdrawn_at: z.string().optional() }).passthrough()).optional().describe("Proposal batches (#365) \u2014 present only when any exist. Shapes reference them by origin.proposal_id; the canvas shows one Accept per batch"),
|
|
12206
12255
|
condition_edit_proposals: z.array(z.object({ id: z.string(), condition_id: z.string(), proposed: z.object({}).passthrough(), rationale: z.string(), proposed_at: z.string() }).passthrough()).optional().describe("Pending condition-edit diffs (#365) \u2014 present only when any exist. Nothing on the condition changes until the estimator accepts in the canvas")
|
|
12207
12256
|
};
|
|
@@ -13520,9 +13569,9 @@ async function buildMarkedSetPdf({ projectName, dark, sheets, shapes, markups, a
|
|
|
13520
13569
|
const { PDFDocument, StandardFonts, rgb, degrees, LineCapStyle } = await import("pdf-lib");
|
|
13521
13570
|
const condById = Object.fromEntries(conditions.map((c) => [c.id, c]));
|
|
13522
13571
|
const rfiNum = new Map((rfis || []).map((r) => [r.id, r.number]));
|
|
13523
|
-
const byKey = (
|
|
13572
|
+
const byKey = (arr3) => {
|
|
13524
13573
|
const m = /* @__PURE__ */ new Map();
|
|
13525
|
-
for (const s of
|
|
13574
|
+
for (const s of arr3) {
|
|
13526
13575
|
const a = m.get(s.sheet_id) || [];
|
|
13527
13576
|
a.push(s);
|
|
13528
13577
|
m.set(s.sheet_id, a);
|
|
@@ -14253,7 +14302,7 @@ function parseTakeoffImport(text) {
|
|
|
14253
14302
|
}
|
|
14254
14303
|
return doc;
|
|
14255
14304
|
}
|
|
14256
|
-
var
|
|
14305
|
+
var arr2 = (v) => Array.isArray(v) ? v : [];
|
|
14257
14306
|
var tagKey = (t) => String(t || "").trim().toUpperCase();
|
|
14258
14307
|
var freeId = (id, taken) => {
|
|
14259
14308
|
let n = 2, next = id;
|
|
@@ -14262,11 +14311,11 @@ var freeId = (id, taken) => {
|
|
|
14262
14311
|
};
|
|
14263
14312
|
function mergeTakeoffImport(current, imported, knownFiles = null) {
|
|
14264
14313
|
const cur = current && typeof current === "object" ? current : {};
|
|
14265
|
-
const impShapes =
|
|
14266
|
-
const impConds =
|
|
14267
|
-
const localScales = new Map(
|
|
14268
|
-
const incomingScales = new Map(
|
|
14269
|
-
const existingIds = new Set(
|
|
14314
|
+
const impShapes = arr2(imported.shapes).filter((s) => s && typeof s === "object" && typeof s.sheet_id === "string" && typeof s.id === "string").map(normalizeAgentReview);
|
|
14315
|
+
const impConds = arr2(imported.conditions).filter((c) => c && typeof c === "object" && typeof c.id === "string");
|
|
14316
|
+
const localScales = new Map(arr2(cur.sheets).filter((s) => typeof s?.sheet_id === "string").map((s) => [s.sheet_id, s.units_per_px]));
|
|
14317
|
+
const incomingScales = new Map(arr2(imported.sheets).filter((s) => typeof s?.sheet_id === "string").map((s) => [s.sheet_id, s.units_per_px]));
|
|
14318
|
+
const existingIds = new Set(arr2(cur.shapes).map((s) => s.id));
|
|
14270
14319
|
for (const s of impShapes) {
|
|
14271
14320
|
if (existingIds.has(s.id) || s.measure_role === "count") continue;
|
|
14272
14321
|
const local = localScales.get(s.sheet_id), incoming = incomingScales.get(s.sheet_id);
|
|
@@ -14280,20 +14329,20 @@ function mergeTakeoffImport(current, imported, knownFiles = null) {
|
|
|
14280
14329
|
return [...new Set(added.map((s) => String(s.sheet_id).split("#")[0]).filter((f) => !known.has(f)))];
|
|
14281
14330
|
};
|
|
14282
14331
|
const pendingCount = (shapes) => shapes.filter((s) => s.origin?.reviewed === false).length;
|
|
14283
|
-
if (!
|
|
14332
|
+
if (!arr2(cur.shapes).length && !arr2(cur.markups).length && !arr2(cur.approvals).length && !arr2(cur.sheets).some((s) => s?.units_per_px > 0)) {
|
|
14284
14333
|
const payload2 = {
|
|
14285
14334
|
...imported,
|
|
14286
14335
|
shapes: impShapes,
|
|
14287
|
-
...
|
|
14288
|
-
...
|
|
14289
|
-
...
|
|
14336
|
+
...arr2(imported.sheet_tabs).length ? {} : { sheet_tabs: arr2(cur.sheet_tabs) },
|
|
14337
|
+
...arr2(imported.sheet_group).length ? {} : { sheet_group: arr2(cur.sheet_group) },
|
|
14338
|
+
...arr2(imported.last_group).length ? {} : { last_group: arr2(cur.last_group) }
|
|
14290
14339
|
};
|
|
14291
14340
|
return {
|
|
14292
14341
|
payload: payload2,
|
|
14293
|
-
note: { replaced: true, shapes_added: impShapes.length, shapes_pending: pendingCount(impShapes), conditions_merged: 0, conditions_added: impConds.length, scales_adopted:
|
|
14342
|
+
note: { replaced: true, shapes_added: impShapes.length, shapes_pending: pendingCount(impShapes), conditions_merged: 0, conditions_added: impConds.length, scales_adopted: arr2(imported.sheets).length, unknown_files: unknownFiles(impShapes) }
|
|
14294
14343
|
};
|
|
14295
14344
|
}
|
|
14296
|
-
const conditions = [...
|
|
14345
|
+
const conditions = [...arr2(cur.conditions)];
|
|
14297
14346
|
const byTag = new Map(conditions.map((c) => [tagKey(c.finish_tag), c.id]));
|
|
14298
14347
|
const condIds = new Set(conditions.map((c) => c.id));
|
|
14299
14348
|
const condMap = /* @__PURE__ */ new Map();
|
|
@@ -14329,23 +14378,23 @@ function mergeTakeoffImport(current, imported, knownFiles = null) {
|
|
|
14329
14378
|
conditions[i] = next;
|
|
14330
14379
|
}
|
|
14331
14380
|
}
|
|
14332
|
-
const shapeIds = new Set(
|
|
14381
|
+
const shapeIds = new Set(arr2(cur.shapes).map((s) => s.id));
|
|
14333
14382
|
const addedShapes = impShapes.filter((s) => !shapeIds.has(s.id)).map((s) => condMap.has(s.condition_id) && condMap.get(s.condition_id) !== s.condition_id ? { ...s, condition_id: condMap.get(s.condition_id) } : s);
|
|
14334
|
-
const markupIds = new Set(
|
|
14335
|
-
const addedMarkups =
|
|
14336
|
-
const rfiIds = new Set(
|
|
14337
|
-
const addedRfis =
|
|
14338
|
-
const proposalIds = new Set(
|
|
14339
|
-
const addedProposals =
|
|
14340
|
-
const editIds = new Set(
|
|
14383
|
+
const markupIds = new Set(arr2(cur.markups).map((m) => m?.id).filter(Boolean));
|
|
14384
|
+
const addedMarkups = arr2(imported.markups).filter((m) => m && typeof m === "object" && (!m.id || !markupIds.has(m.id)));
|
|
14385
|
+
const rfiIds = new Set(arr2(cur.rfis).map((r) => r?.id).filter(Boolean));
|
|
14386
|
+
const addedRfis = arr2(imported.rfis).filter((r) => r && typeof r === "object" && r.id && !rfiIds.has(r.id));
|
|
14387
|
+
const proposalIds = new Set(arr2(cur.proposals).map((p) => p?.id).filter(Boolean));
|
|
14388
|
+
const addedProposals = arr2(imported.proposals).filter((p) => p && typeof p === "object" && typeof p.id === "string" && !proposalIds.has(p.id));
|
|
14389
|
+
const editIds = new Set(arr2(cur.condition_edit_proposals).map((p) => p?.id).filter(Boolean));
|
|
14341
14390
|
const takenTags = new Set(conditions.map((c) => tagKey(c.finish_tag)));
|
|
14342
|
-
const addedEdits =
|
|
14343
|
-
const approvalIds = new Set(
|
|
14391
|
+
const addedEdits = arr2(imported.condition_edit_proposals).filter((p) => p && typeof p === "object" && typeof p.id === "string" && !editIds.has(p.id) && p.proposed && typeof p.proposed === "object").map((p) => condMap.has(p.condition_id) ? { ...p, condition_id: condMap.get(p.condition_id) } : p).filter((p) => condIds.has(p.condition_id)).filter((p) => p.proposed.finish_tag === void 0 || !takenTags.has(tagKey(p.proposed.finish_tag)) || tagKey(p.proposed.finish_tag) === tagKey(conditions.find((c) => c.id === p.condition_id)?.finish_tag)).filter((p) => !arr2(cur.condition_edit_proposals).some((q) => q?.condition_id === p.condition_id));
|
|
14392
|
+
const approvalIds = new Set(arr2(cur.approvals).map((a) => a?.id).filter(Boolean));
|
|
14344
14393
|
const addedApprovals = sanitizeApprovals(imported.approvals).filter((a) => !approvalIds.has(a.id));
|
|
14345
|
-
const sheets = [...
|
|
14394
|
+
const sheets = [...arr2(cur.sheets)];
|
|
14346
14395
|
const scaled = new Set(sheets.map((s) => s?.sheet_id));
|
|
14347
14396
|
let scalesAdopted = 0;
|
|
14348
|
-
for (const s of
|
|
14397
|
+
for (const s of arr2(imported.sheets)) {
|
|
14349
14398
|
if (s && typeof s === "object" && s.sheet_id && s.units_per_px && !scaled.has(s.sheet_id)) {
|
|
14350
14399
|
sheets.push(s);
|
|
14351
14400
|
scaled.add(s.sheet_id);
|
|
@@ -14355,12 +14404,12 @@ function mergeTakeoffImport(current, imported, knownFiles = null) {
|
|
|
14355
14404
|
const payload = {
|
|
14356
14405
|
...cur,
|
|
14357
14406
|
conditions,
|
|
14358
|
-
shapes: [...
|
|
14359
|
-
markups: [...
|
|
14360
|
-
...addedRfis.length ? { rfis: [...
|
|
14361
|
-
...addedProposals.length ? { proposals: [...
|
|
14362
|
-
...addedEdits.length ? { condition_edit_proposals: [...
|
|
14363
|
-
...addedApprovals.length ? { approvals: [...
|
|
14407
|
+
shapes: [...arr2(cur.shapes), ...addedShapes],
|
|
14408
|
+
markups: [...arr2(cur.markups), ...addedMarkups],
|
|
14409
|
+
...addedRfis.length ? { rfis: [...arr2(cur.rfis), ...addedRfis] } : {},
|
|
14410
|
+
...addedProposals.length ? { proposals: [...arr2(cur.proposals), ...addedProposals] } : {},
|
|
14411
|
+
...addedEdits.length ? { condition_edit_proposals: [...arr2(cur.condition_edit_proposals), ...addedEdits] } : {},
|
|
14412
|
+
...addedApprovals.length ? { approvals: [...arr2(cur.approvals), ...addedApprovals] } : {},
|
|
14364
14413
|
sheets
|
|
14365
14414
|
};
|
|
14366
14415
|
return {
|
|
@@ -15089,7 +15138,7 @@ No review gate: the pencil-not-ink rule exists to stop an agent inventing geomet
|
|
|
15089
15138
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15090
15139
|
|
|
15091
15140
|
// src/wiki.generated.ts
|
|
15092
|
-
var WIKI_VERSION = "0.9.
|
|
15141
|
+
var WIKI_VERSION = "0.9.86";
|
|
15093
15142
|
var WIKI_PAGES = [
|
|
15094
15143
|
{
|
|
15095
15144
|
"key": "index",
|
|
@@ -15527,7 +15576,7 @@ function nameTheStageInRefusals(server) {
|
|
|
15527
15576
|
// package.json
|
|
15528
15577
|
var package_default = {
|
|
15529
15578
|
name: "opentakeoff-mcp",
|
|
15530
|
-
version: "0.9.
|
|
15579
|
+
version: "0.9.86",
|
|
15531
15580
|
mcpName: "io.github.Kentucky-ai/opentakeoff",
|
|
15532
15581
|
type: "module",
|
|
15533
15582
|
description: "OpenTakeoff MCP server \u2014 drive the takeoff engine from your MCP client over stdio.",
|
|
@@ -15547,7 +15596,7 @@ var package_default = {
|
|
|
15547
15596
|
"check:wiki": "node scripts/check-wiki.mjs",
|
|
15548
15597
|
"check:versions": "node ../scripts/check-version-consistency.mjs",
|
|
15549
15598
|
"check:tool-count": "node --import tsx scripts/check-tool-count.mjs",
|
|
15550
|
-
test: "node --import tsx --test test/checkers.test.ts test/conformance.test.ts test/constants.test.ts test/context.test.ts test/dxf.test.ts test/e2e.test.ts test/gate.test.ts test/graphEvalRowsym.test.ts test/labels.test.ts test/mep.test.ts test/overlap.test.ts test/parity.test.ts test/proposals.test.ts test/raster.test.ts test/resources.test.ts test/safewrite.test.ts test/scalewarn.test.ts test/scope.test.ts test/session.test.ts test/staging.test.ts test/sweepguard.test.ts test/tools.test.ts test/transitions.test.ts test/twins.test.ts test/view.test.ts test/wiki.test.ts"
|
|
15599
|
+
test: "node --import tsx --test test/checkers.test.ts test/conformance.test.ts test/constants.test.ts test/context.test.ts test/document.test.ts test/dxf.test.ts test/e2e.test.ts test/gate.test.ts test/graphEvalRowsym.test.ts test/labels.test.ts test/mep.test.ts test/overlap.test.ts test/parity.test.ts test/proposals.test.ts test/raster.test.ts test/resources.test.ts test/safewrite.test.ts test/scalewarn.test.ts test/scope.test.ts test/session.test.ts test/staging.test.ts test/sweepguard.test.ts test/tools.test.ts test/transitions.test.ts test/twins.test.ts test/view.test.ts test/wiki.test.ts"
|
|
15551
15600
|
},
|
|
15552
15601
|
dependencies: {
|
|
15553
15602
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opentakeoff-mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.86",
|
|
4
4
|
"mcpName": "io.github.Kentucky-ai/opentakeoff",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "OpenTakeoff MCP server — drive the takeoff engine from your MCP client over stdio.",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"check:wiki": "node scripts/check-wiki.mjs",
|
|
21
21
|
"check:versions": "node ../scripts/check-version-consistency.mjs",
|
|
22
22
|
"check:tool-count": "node --import tsx scripts/check-tool-count.mjs",
|
|
23
|
-
"test": "node --import tsx --test test/checkers.test.ts test/conformance.test.ts test/constants.test.ts test/context.test.ts test/dxf.test.ts test/e2e.test.ts test/gate.test.ts test/graphEvalRowsym.test.ts test/labels.test.ts test/mep.test.ts test/overlap.test.ts test/parity.test.ts test/proposals.test.ts test/raster.test.ts test/resources.test.ts test/safewrite.test.ts test/scalewarn.test.ts test/scope.test.ts test/session.test.ts test/staging.test.ts test/sweepguard.test.ts test/tools.test.ts test/transitions.test.ts test/twins.test.ts test/view.test.ts test/wiki.test.ts"
|
|
23
|
+
"test": "node --import tsx --test test/checkers.test.ts test/conformance.test.ts test/constants.test.ts test/context.test.ts test/document.test.ts test/dxf.test.ts test/e2e.test.ts test/gate.test.ts test/graphEvalRowsym.test.ts test/labels.test.ts test/mep.test.ts test/overlap.test.ts test/parity.test.ts test/proposals.test.ts test/raster.test.ts test/resources.test.ts test/safewrite.test.ts test/scalewarn.test.ts test/scope.test.ts test/session.test.ts test/staging.test.ts test/sweepguard.test.ts test/tools.test.ts test/transitions.test.ts test/twins.test.ts test/view.test.ts test/wiki.test.ts"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@modelcontextprotocol/sdk": "^1.12.0",
|