@floless/app 0.73.1 → 0.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/floless-server.cjs +686 -254
- package/dist/schemas/steel.takeoff.v1.schema.json +26 -7
- package/dist/web/app.css +62 -1
- package/dist/web/index.html +5 -0
- package/dist/web/steel-3d-view.js +17 -1
- package/dist/web/steel-editor.html +185 -9
- package/dist/web/workspaces.js +139 -0
- package/package.json +1 -1
package/dist/floless-server.cjs
CHANGED
|
@@ -5489,7 +5489,7 @@ var require_thread_stream = __commonJS({
|
|
|
5489
5489
|
var { version } = require_package();
|
|
5490
5490
|
var { EventEmitter: EventEmitter2 } = require("events");
|
|
5491
5491
|
var { Worker: Worker2 } = require("worker_threads");
|
|
5492
|
-
var { join:
|
|
5492
|
+
var { join: join33 } = require("path");
|
|
5493
5493
|
var { pathToFileURL } = require("url");
|
|
5494
5494
|
var { wait } = require_wait();
|
|
5495
5495
|
var {
|
|
@@ -5540,7 +5540,7 @@ var require_thread_stream = __commonJS({
|
|
|
5540
5540
|
function createWorker(stream, opts) {
|
|
5541
5541
|
const { filename, workerData } = opts;
|
|
5542
5542
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
5543
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
5543
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join33(__dirname, "lib", "worker.js");
|
|
5544
5544
|
const worker = new Worker2(toExecute, {
|
|
5545
5545
|
...opts.workerOpts,
|
|
5546
5546
|
name: opts.workerOpts?.name || "thread-stream",
|
|
@@ -6006,9 +6006,9 @@ var require_transport = __commonJS({
|
|
|
6006
6006
|
"node_modules/pino/lib/transport.js"(exports2, module2) {
|
|
6007
6007
|
"use strict";
|
|
6008
6008
|
var { createRequire: createRequire5 } = require("module");
|
|
6009
|
-
var { existsSync:
|
|
6009
|
+
var { existsSync: existsSync28 } = require("node:fs");
|
|
6010
6010
|
var getCallers = require_caller();
|
|
6011
|
-
var { join:
|
|
6011
|
+
var { join: join33, isAbsolute: isAbsolute2, sep: sep4 } = require("node:path");
|
|
6012
6012
|
var { fileURLToPath: fileURLToPath6 } = require("node:url");
|
|
6013
6013
|
var sleep = require_atomic_sleep();
|
|
6014
6014
|
var onExit = require_on_exit_leak_free();
|
|
@@ -6080,7 +6080,7 @@ var require_transport = __commonJS({
|
|
|
6080
6080
|
return false;
|
|
6081
6081
|
}
|
|
6082
6082
|
}
|
|
6083
|
-
return isAbsolute2(path) && !
|
|
6083
|
+
return isAbsolute2(path) && !existsSync28(path);
|
|
6084
6084
|
}
|
|
6085
6085
|
function stripQuotes(value) {
|
|
6086
6086
|
const first = value[0];
|
|
@@ -6161,7 +6161,7 @@ var require_transport = __commonJS({
|
|
|
6161
6161
|
throw new Error("only one of target or targets can be specified");
|
|
6162
6162
|
}
|
|
6163
6163
|
if (targets) {
|
|
6164
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
6164
|
+
target = bundlerOverrides["pino-worker"] || join33(__dirname, "worker.js");
|
|
6165
6165
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
6166
6166
|
return {
|
|
6167
6167
|
...dest,
|
|
@@ -6179,7 +6179,7 @@ var require_transport = __commonJS({
|
|
|
6179
6179
|
});
|
|
6180
6180
|
});
|
|
6181
6181
|
} else if (pipeline2) {
|
|
6182
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
6182
|
+
target = bundlerOverrides["pino-worker"] || join33(__dirname, "worker.js");
|
|
6183
6183
|
options.pipelines = [pipeline2.map((dest) => {
|
|
6184
6184
|
return {
|
|
6185
6185
|
...dest,
|
|
@@ -6202,7 +6202,7 @@ var require_transport = __commonJS({
|
|
|
6202
6202
|
return origin;
|
|
6203
6203
|
}
|
|
6204
6204
|
if (origin === "pino/file") {
|
|
6205
|
-
return
|
|
6205
|
+
return join33(__dirname, "..", "file.js");
|
|
6206
6206
|
}
|
|
6207
6207
|
let fixTarget2;
|
|
6208
6208
|
for (const filePath of callers) {
|
|
@@ -7182,7 +7182,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
7182
7182
|
return circularValue;
|
|
7183
7183
|
}
|
|
7184
7184
|
let res = "";
|
|
7185
|
-
let
|
|
7185
|
+
let join33 = ",";
|
|
7186
7186
|
const originalIndentation = indentation;
|
|
7187
7187
|
if (Array.isArray(value)) {
|
|
7188
7188
|
if (value.length === 0) {
|
|
@@ -7196,7 +7196,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
7196
7196
|
indentation += spacer;
|
|
7197
7197
|
res += `
|
|
7198
7198
|
${indentation}`;
|
|
7199
|
-
|
|
7199
|
+
join33 = `,
|
|
7200
7200
|
${indentation}`;
|
|
7201
7201
|
}
|
|
7202
7202
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -7204,13 +7204,13 @@ ${indentation}`;
|
|
|
7204
7204
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
7205
7205
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
7206
7206
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
7207
|
-
res +=
|
|
7207
|
+
res += join33;
|
|
7208
7208
|
}
|
|
7209
7209
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
7210
7210
|
res += tmp !== void 0 ? tmp : "null";
|
|
7211
7211
|
if (value.length - 1 > maximumBreadth) {
|
|
7212
7212
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
7213
|
-
res += `${
|
|
7213
|
+
res += `${join33}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
7214
7214
|
}
|
|
7215
7215
|
if (spacer !== "") {
|
|
7216
7216
|
res += `
|
|
@@ -7231,7 +7231,7 @@ ${originalIndentation}`;
|
|
|
7231
7231
|
let separator = "";
|
|
7232
7232
|
if (spacer !== "") {
|
|
7233
7233
|
indentation += spacer;
|
|
7234
|
-
|
|
7234
|
+
join33 = `,
|
|
7235
7235
|
${indentation}`;
|
|
7236
7236
|
whitespace = " ";
|
|
7237
7237
|
}
|
|
@@ -7245,13 +7245,13 @@ ${indentation}`;
|
|
|
7245
7245
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
7246
7246
|
if (tmp !== void 0) {
|
|
7247
7247
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
7248
|
-
separator =
|
|
7248
|
+
separator = join33;
|
|
7249
7249
|
}
|
|
7250
7250
|
}
|
|
7251
7251
|
if (keyLength > maximumBreadth) {
|
|
7252
7252
|
const removedKeys = keyLength - maximumBreadth;
|
|
7253
7253
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
7254
|
-
separator =
|
|
7254
|
+
separator = join33;
|
|
7255
7255
|
}
|
|
7256
7256
|
if (spacer !== "" && separator.length > 1) {
|
|
7257
7257
|
res = `
|
|
@@ -7292,7 +7292,7 @@ ${originalIndentation}`;
|
|
|
7292
7292
|
}
|
|
7293
7293
|
const originalIndentation = indentation;
|
|
7294
7294
|
let res = "";
|
|
7295
|
-
let
|
|
7295
|
+
let join33 = ",";
|
|
7296
7296
|
if (Array.isArray(value)) {
|
|
7297
7297
|
if (value.length === 0) {
|
|
7298
7298
|
return "[]";
|
|
@@ -7305,7 +7305,7 @@ ${originalIndentation}`;
|
|
|
7305
7305
|
indentation += spacer;
|
|
7306
7306
|
res += `
|
|
7307
7307
|
${indentation}`;
|
|
7308
|
-
|
|
7308
|
+
join33 = `,
|
|
7309
7309
|
${indentation}`;
|
|
7310
7310
|
}
|
|
7311
7311
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -7313,13 +7313,13 @@ ${indentation}`;
|
|
|
7313
7313
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
7314
7314
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
7315
7315
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
7316
|
-
res +=
|
|
7316
|
+
res += join33;
|
|
7317
7317
|
}
|
|
7318
7318
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
7319
7319
|
res += tmp !== void 0 ? tmp : "null";
|
|
7320
7320
|
if (value.length - 1 > maximumBreadth) {
|
|
7321
7321
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
7322
|
-
res += `${
|
|
7322
|
+
res += `${join33}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
7323
7323
|
}
|
|
7324
7324
|
if (spacer !== "") {
|
|
7325
7325
|
res += `
|
|
@@ -7332,7 +7332,7 @@ ${originalIndentation}`;
|
|
|
7332
7332
|
let whitespace = "";
|
|
7333
7333
|
if (spacer !== "") {
|
|
7334
7334
|
indentation += spacer;
|
|
7335
|
-
|
|
7335
|
+
join33 = `,
|
|
7336
7336
|
${indentation}`;
|
|
7337
7337
|
whitespace = " ";
|
|
7338
7338
|
}
|
|
@@ -7341,7 +7341,7 @@ ${indentation}`;
|
|
|
7341
7341
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
7342
7342
|
if (tmp !== void 0) {
|
|
7343
7343
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
7344
|
-
separator =
|
|
7344
|
+
separator = join33;
|
|
7345
7345
|
}
|
|
7346
7346
|
}
|
|
7347
7347
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -7399,20 +7399,20 @@ ${originalIndentation}`;
|
|
|
7399
7399
|
indentation += spacer;
|
|
7400
7400
|
let res2 = `
|
|
7401
7401
|
${indentation}`;
|
|
7402
|
-
const
|
|
7402
|
+
const join34 = `,
|
|
7403
7403
|
${indentation}`;
|
|
7404
7404
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
7405
7405
|
let i = 0;
|
|
7406
7406
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
7407
7407
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
7408
7408
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
7409
|
-
res2 +=
|
|
7409
|
+
res2 += join34;
|
|
7410
7410
|
}
|
|
7411
7411
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
7412
7412
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
7413
7413
|
if (value.length - 1 > maximumBreadth) {
|
|
7414
7414
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
7415
|
-
res2 += `${
|
|
7415
|
+
res2 += `${join34}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
7416
7416
|
}
|
|
7417
7417
|
res2 += `
|
|
7418
7418
|
${originalIndentation}`;
|
|
@@ -7428,16 +7428,16 @@ ${originalIndentation}`;
|
|
|
7428
7428
|
return '"[Object]"';
|
|
7429
7429
|
}
|
|
7430
7430
|
indentation += spacer;
|
|
7431
|
-
const
|
|
7431
|
+
const join33 = `,
|
|
7432
7432
|
${indentation}`;
|
|
7433
7433
|
let res = "";
|
|
7434
7434
|
let separator = "";
|
|
7435
7435
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
7436
7436
|
if (isTypedArrayWithEntries(value)) {
|
|
7437
|
-
res += stringifyTypedArray(value,
|
|
7437
|
+
res += stringifyTypedArray(value, join33, maximumBreadth);
|
|
7438
7438
|
keys = keys.slice(value.length);
|
|
7439
7439
|
maximumPropertiesToStringify -= value.length;
|
|
7440
|
-
separator =
|
|
7440
|
+
separator = join33;
|
|
7441
7441
|
}
|
|
7442
7442
|
if (deterministic) {
|
|
7443
7443
|
keys = sort(keys, comparator);
|
|
@@ -7448,13 +7448,13 @@ ${indentation}`;
|
|
|
7448
7448
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
7449
7449
|
if (tmp !== void 0) {
|
|
7450
7450
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
7451
|
-
separator =
|
|
7451
|
+
separator = join33;
|
|
7452
7452
|
}
|
|
7453
7453
|
}
|
|
7454
7454
|
if (keyLength > maximumBreadth) {
|
|
7455
7455
|
const removedKeys = keyLength - maximumBreadth;
|
|
7456
7456
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
7457
|
-
separator =
|
|
7457
|
+
separator = join33;
|
|
7458
7458
|
}
|
|
7459
7459
|
if (separator !== "") {
|
|
7460
7460
|
res = `
|
|
@@ -41991,7 +41991,7 @@ var require_send = __commonJS({
|
|
|
41991
41991
|
var { parseTokenList } = require_parseTokenList();
|
|
41992
41992
|
var { createHttpError } = require_createHttpError();
|
|
41993
41993
|
var extname3 = path.extname;
|
|
41994
|
-
var
|
|
41994
|
+
var join33 = path.join;
|
|
41995
41995
|
var normalize2 = path.normalize;
|
|
41996
41996
|
var resolve6 = path.resolve;
|
|
41997
41997
|
var sep4 = path.sep;
|
|
@@ -42078,7 +42078,7 @@ var require_send = __commonJS({
|
|
|
42078
42078
|
return { statusCode: 403 };
|
|
42079
42079
|
}
|
|
42080
42080
|
parts = path2.split(sep4);
|
|
42081
|
-
path2 = normalize2(
|
|
42081
|
+
path2 = normalize2(join33(root, path2));
|
|
42082
42082
|
} else {
|
|
42083
42083
|
if (UP_PATH_REGEXP.test(path2)) {
|
|
42084
42084
|
debug('malicious path "%s"', path2);
|
|
@@ -42361,7 +42361,7 @@ var require_send = __commonJS({
|
|
|
42361
42361
|
let err2;
|
|
42362
42362
|
for (let i = 0; i < options.index.length; i++) {
|
|
42363
42363
|
const index = options.index[i];
|
|
42364
|
-
const p =
|
|
42364
|
+
const p = join33(path2, index);
|
|
42365
42365
|
const { error, stat: stat4 } = await tryStat(p);
|
|
42366
42366
|
if (error) {
|
|
42367
42367
|
err2 = error;
|
|
@@ -50827,9 +50827,9 @@ var import_node_readline2 = require("node:readline");
|
|
|
50827
50827
|
|
|
50828
50828
|
// index.ts
|
|
50829
50829
|
var import_node_url5 = require("node:url");
|
|
50830
|
-
var
|
|
50830
|
+
var import_node_path32 = require("node:path");
|
|
50831
50831
|
var import_node_os21 = require("node:os");
|
|
50832
|
-
var
|
|
50832
|
+
var import_node_fs34 = require("node:fs");
|
|
50833
50833
|
var import_node_child_process8 = require("node:child_process");
|
|
50834
50834
|
|
|
50835
50835
|
// log.mjs
|
|
@@ -50948,6 +50948,48 @@ function storeVisualInput(appId, dataUrl) {
|
|
|
50948
50948
|
}
|
|
50949
50949
|
return { path, ext, bytes: (0, import_node_fs3.statSync)(path).size, sha256: sha2562 };
|
|
50950
50950
|
}
|
|
50951
|
+
var MAX_IFC_BYTES = 64 * 1024 * 1024;
|
|
50952
|
+
function sniffIfc(buf) {
|
|
50953
|
+
let off = 0;
|
|
50954
|
+
if (buf.length >= 3 && buf[0] === 239 && buf[1] === 187 && buf[2] === 191) off = 3;
|
|
50955
|
+
if (buf.length >= off + 12 && buf.toString("ascii", off, off + 12) === "ISO-10303-21") return "ifc";
|
|
50956
|
+
if (buf.length >= 4 && buf[0] === 80 && buf[1] === 75 && (buf[2] === 3 || buf[2] === 5 || buf[2] === 7)) return "ifczip";
|
|
50957
|
+
return null;
|
|
50958
|
+
}
|
|
50959
|
+
function storeIfcInput(appId, dataUrl) {
|
|
50960
|
+
if (!safeSegment(appId)) throw new VisualInputError("invalid app id");
|
|
50961
|
+
const m = /^data:([\w/+.-]*);base64,(.*)$/s.exec(dataUrl || "");
|
|
50962
|
+
if (!m) throw new VisualInputError("IFC must be a base64 data URL");
|
|
50963
|
+
const buf = Buffer.from(m[2] ?? "", "base64");
|
|
50964
|
+
if (buf.length === 0) throw new VisualInputError("empty IFC file");
|
|
50965
|
+
if (buf.length > MAX_IFC_BYTES) throw new VisualInputError("IFC file too large (max 64 MB)");
|
|
50966
|
+
const ext = sniffIfc(buf);
|
|
50967
|
+
if (!ext) throw new VisualInputError("that file is not an IFC (.ifc / .ifczip)");
|
|
50968
|
+
const sha2562 = (0, import_node_crypto.createHash)("sha256").update(buf).digest("hex");
|
|
50969
|
+
const dir = (0, import_node_path2.join)(inputsDir(), appId);
|
|
50970
|
+
const path = (0, import_node_path2.join)(dir, `${sha2562}.${ext}`);
|
|
50971
|
+
const root = (0, import_node_path2.resolve)(inputsDir());
|
|
50972
|
+
const target = (0, import_node_path2.resolve)(path);
|
|
50973
|
+
if (target !== root && !target.startsWith(root + import_node_path2.sep)) {
|
|
50974
|
+
throw new VisualInputError("refusing to write outside the inputs root");
|
|
50975
|
+
}
|
|
50976
|
+
(0, import_node_fs3.mkdirSync)(dir, { recursive: true });
|
|
50977
|
+
if (!(0, import_node_fs3.existsSync)(path)) {
|
|
50978
|
+
const tmp = `${path}.tmp`;
|
|
50979
|
+
(0, import_node_fs3.writeFileSync)(tmp, buf);
|
|
50980
|
+
(0, import_node_fs3.renameSync)(tmp, path);
|
|
50981
|
+
}
|
|
50982
|
+
return { path, sha256: sha2562, bytes: (0, import_node_fs3.statSync)(path).size };
|
|
50983
|
+
}
|
|
50984
|
+
function ifcInputPath(appId, sha2562) {
|
|
50985
|
+
if (!safeSegment(appId) || !safeSegment(sha2562) || !/^[a-f0-9]{64}$/i.test(sha2562)) return null;
|
|
50986
|
+
const root = (0, import_node_path2.resolve)(inputsDir());
|
|
50987
|
+
for (const ext of ["ifc", "ifczip"]) {
|
|
50988
|
+
const path = (0, import_node_path2.resolve)((0, import_node_path2.join)(inputsDir(), appId, `${sha2562}.${ext}`));
|
|
50989
|
+
if ((path === root || path.startsWith(root + import_node_path2.sep)) && (0, import_node_fs3.existsSync)(path)) return path;
|
|
50990
|
+
}
|
|
50991
|
+
return null;
|
|
50992
|
+
}
|
|
50951
50993
|
function renameVisualInputs(oldId, newId) {
|
|
50952
50994
|
if (!safeSegment(oldId) || !safeSegment(newId)) throw new VisualInputError("invalid app id");
|
|
50953
50995
|
const from = (0, import_node_path2.join)(inputsDir(), oldId);
|
|
@@ -51567,6 +51609,10 @@ function resolveTeklaBridge() {
|
|
|
51567
51609
|
].filter((p) => !!p);
|
|
51568
51610
|
return candidates.find((p) => (0, import_node_fs6.existsSync)(p)) ?? null;
|
|
51569
51611
|
}
|
|
51612
|
+
function resolveConnectionReaderBridge() {
|
|
51613
|
+
const p = (0, import_node_path5.join)((0, import_node_os5.homedir)(), ".aware", "bridges", "aware-connection-reader.exe");
|
|
51614
|
+
return (0, import_node_fs6.existsSync)(p) ? p : null;
|
|
51615
|
+
}
|
|
51570
51616
|
function injectDebugger(code) {
|
|
51571
51617
|
const lines = code.split(/\r?\n/);
|
|
51572
51618
|
let lastUsing = -1;
|
|
@@ -51889,6 +51935,9 @@ function agentInstallArgv(id) {
|
|
|
51889
51935
|
function agentUpdateArgv(id) {
|
|
51890
51936
|
return ["agent", "update", assertId(id)];
|
|
51891
51937
|
}
|
|
51938
|
+
function sidecarInstallArgv(host) {
|
|
51939
|
+
return ["sidecar", "install", assertId(host)];
|
|
51940
|
+
}
|
|
51892
51941
|
function parseAgentInstallOutput(stdout) {
|
|
51893
51942
|
const m = stdout.match(/✓\s+(?:installed|updated)\s+(\S+)/);
|
|
51894
51943
|
return { installed: m?.[1] ?? null };
|
|
@@ -52235,6 +52284,28 @@ var aware = {
|
|
|
52235
52284
|
if (isAgentInstalled(agents, id)) return { installed: id, output: "already installed" };
|
|
52236
52285
|
return this.agentInstall(id);
|
|
52237
52286
|
},
|
|
52287
|
+
/**
|
|
52288
|
+
* Install a cli-transport agent's host bridge (`aware sidecar install <host>`). Downloads a
|
|
52289
|
+
* platform zip (~30 MB observed) from the matching GitHub release into ~/.aware/bridges/ — well
|
|
52290
|
+
* over runRaw's 60s default — so use the generous timeout. NOT idempotent-safe to assume: prefer
|
|
52291
|
+
* ensureConnectionReaderBridge for the reader (checks the bridge is on disk first).
|
|
52292
|
+
*/
|
|
52293
|
+
async sidecarInstall(host) {
|
|
52294
|
+
const { code, stdout, stderr } = await runRawWithEnv(sidecarInstallArgv(host), void 0, 6e5);
|
|
52295
|
+
if (code !== 0) throw new AwareError(`aware sidecar install ${host} failed (exit ${code})`, { stdout, stderr });
|
|
52296
|
+
return { output: stdout.trim() };
|
|
52297
|
+
},
|
|
52298
|
+
/**
|
|
52299
|
+
* Ensure the connection-reader bridge (the web-ifc Node SEA) is present, idempotently: if it's
|
|
52300
|
+
* already in ~/.aware/bridges/ this is a cheap no-op; otherwise fetch it via `sidecar install`.
|
|
52301
|
+
* `aware app run` on a connection-reader node needs this bridge (the tessellator is web-ifc, not
|
|
52302
|
+
* Rust) — the reader agent's manifest alone isn't enough.
|
|
52303
|
+
*/
|
|
52304
|
+
async ensureConnectionReaderBridge() {
|
|
52305
|
+
if (resolveConnectionReaderBridge()) return { present: true, output: "already installed" };
|
|
52306
|
+
const r = await this.sidecarInstall("connection-reader");
|
|
52307
|
+
return { present: !!resolveConnectionReaderBridge(), output: r.output };
|
|
52308
|
+
},
|
|
52238
52309
|
/**
|
|
52239
52310
|
* Update an installed agent to the latest registry version (`aware agent update
|
|
52240
52311
|
* <id>`). Unlike `ensureAgentInstalled`, this always re-pulls — it is the Agent
|
|
@@ -53022,7 +53093,7 @@ function appVersion() {
|
|
|
53022
53093
|
return resolveVersion({
|
|
53023
53094
|
isSea: isSea2(),
|
|
53024
53095
|
sqVersionXml: readSqVersionXml(),
|
|
53025
|
-
define: true ? "0.
|
|
53096
|
+
define: true ? "0.75.0" : void 0,
|
|
53026
53097
|
pkgVersion: readPkgVersion()
|
|
53027
53098
|
});
|
|
53028
53099
|
}
|
|
@@ -53032,7 +53103,7 @@ function resolveChannel(s) {
|
|
|
53032
53103
|
return "dev";
|
|
53033
53104
|
}
|
|
53034
53105
|
function appChannel() {
|
|
53035
|
-
return resolveChannel({ isSea: isSea2(), define: true ? "0.
|
|
53106
|
+
return resolveChannel({ isSea: isSea2(), define: true ? "0.75.0" : void 0 });
|
|
53036
53107
|
}
|
|
53037
53108
|
|
|
53038
53109
|
// workflow-update.ts
|
|
@@ -53397,7 +53468,7 @@ function extractSavedPath(events) {
|
|
|
53397
53468
|
var aisc_shapes_default = { "C10X15.3": 2.6, C10X20: 2.74, C10X25: 2.89, C10X30: 3.03, "C12X20.7": 2.94, C12X25: 3.05, C12X30: 3.17, "C15X33.9": 3.4, C15X40: 3.52, C15X50: 3.72, "C3X3.5": 1.37, "C3X4.1": 1.41, C3X5: 1.5, C3X6: 1.6, "C4X4.5": 1.52, "C4X5.4": 1.58, "C4X6.25": 1.65, "C4X7.25": 1.72, "C5X6.7": 1.75, C5X9: 1.89, "C6X10.5": 2.03, C6X13: 2.16, "C6X8.2": 1.92, "C7X12.25": 2.19, "C7X14.75": 2.3, "C7X9.8": 2.09, "C8X11.5": 2.26, "C8X13.75": 2.34, "C8X18.75": 2.53, "C9X13.4": 2.43, C9X15: 2.49, C9X20: 2.65, HP10X42: 10.1, HP10X57: 10.2, HP12X53: 12, HP12X63: 12.1, HP12X74: 12.2, HP12X84: 12.3, HP12X89: 12.3, HP14X102: 14.8, HP14X117: 14.9, HP14X73: 14.6, HP14X89: 14.7, HP16X101: 15.8, HP16X121: 15.9, HP16X141: 16, HP16X162: 16.1, HP16X183: 16.3, HP16X88: 15.7, HP18X135: 17.8, HP18X157: 17.9, HP18X181: 18, HP18X204: 18.1, HP8X36: 8.16, "M10X7.5": 2.69, M10X8: 2.69, M10X9: 2.69, "M12.5X11.6": 3.5, "M12.5X12.4": 3.75, M12X10: 3.25, "M12X10.8": 3.07, "M12X11.8": 3.07, "M3X2.9": 2.25, "M4X3.2": 2.25, "M4X3.45": 2.25, "M4X4.08": 2.25, M4X6: 3.8, "M5X18.9": 5, "M6X3.7": 2, "M6X4.4": 1.84, "M8X6.2": 2.28, "M8X6.5": 2.28, MC10X22: 3.32, MC10X25: 3.41, "MC10X28.5": 3.95, "MC10X33.6": 4.1, "MC10X41.1": 4.32, "MC10X6.5": 1.17, "MC10X8.4": 1.5, "MC12X10.6": 1.5, "MC12X14.3": 2.12, MC12X31: 3.67, MC12X35: 3.77, MC12X40: 3.89, MC12X45: 4.01, MC12X50: 4.14, "MC13X31.8": 4, MC13X35: 4.07, MC13X40: 4.19, MC13X50: 4.41, "MC18X42.7": 3.95, "MC18X45.8": 4, "MC18X51.9": 4.1, MC18X58: 4.2, "MC3X7.1": 1.94, "MC4X13.8": 2.5, MC6X12: 2.5, "MC6X15.1": 2.94, "MC6X15.3": 3.5, "MC6X16.3": 3, MC6X18: 3.5, "MC6X6.5": 1.85, MC6X7: 1.88, "MC7X19.1": 3.45, "MC7X22.7": 3.6, "MC8X18.7": 2.98, MC8X20: 3.03, "MC8X21.4": 3.45, "MC8X22.8": 3.5, "MC8X8.5": 1.87, "MC9X23.9": 3.45, "MC9X25.4": 3.5, "MT2.5X9.45": 5, MT2X3: 3.8, "MT3X1.85": 2, "MT3X2.2": 1.84, "MT4X3.1": 2.28, "MT4X3.25": 2.28, "MT5X3.75": 2.69, MT5X4: 2.69, "MT5X4.5": 2.69, "MT6.25X5.8": 3.5, "MT6.25X6.2": 3.75, MT6X5: 3.25, "MT6X5.4": 3.07, "MT6X5.9": 3.07, "S10X25.4": 4.66, S10X35: 4.94, "S12X31.8": 5, S12X35: 5.08, "S12X40.8": 5.25, S12X50: 5.48, "S15X42.9": 5.5, S15X50: 5.64, "S18X54.7": 6, S18X70: 6.25, S20X66: 6.26, S20X75: 6.39, S20X86: 7.06, S20X96: 7.2, S24X100: 7.25, S24X106: 7.87, S24X121: 8.05, S24X80: 7, S24X90: 7.13, "S3X5.7": 2.33, "S3X7.5": 2.51, "S4X7.7": 2.66, "S4X9.5": 2.8, S5X10: 3, "S6X12.5": 3.33, "S6X17.25": 3.57, "S8X18.4": 4, S8X23: 4.17, "ST1.5X2.85": 2.33, "ST1.5X3.75": 2.51, ST10X33: 6.26, "ST10X37.5": 6.39, ST10X43: 7.06, ST10X48: 7.2, ST12X40: 7, ST12X45: 7.13, ST12X50: 7.25, ST12X53: 7.87, "ST12X60.5": 8.05, "ST2.5X5": 3, "ST2X3.85": 2.66, "ST2X4.75": 2.8, "ST3X6.25": 3.33, "ST3X8.6": 3.57, "ST4X11.5": 4.17, "ST4X9.2": 4, "ST5X12.7": 4.66, "ST5X17.5": 4.94, "ST6X15.9": 5, "ST6X17.5": 5.08, "ST6X20.4": 5.25, ST6X25: 5.48, "ST7.5X21.45": 5.5, "ST7.5X25": 5.64, "ST9X27.35": 6, ST9X35: 6.25, W10X100: 10.3, W10X112: 10.4, W10X12: 3.96, W10X15: 4, W10X17: 4.01, W10X19: 4.02, W10X22: 5.75, W10X26: 5.77, W10X30: 5.81, W10X33: 7.96, W10X39: 7.99, W10X45: 8.02, W10X49: 10, W10X54: 10, W10X60: 10.1, W10X68: 10.1, W10X77: 10.2, W10X88: 10.3, W12X106: 12.2, W12X120: 12.3, W12X136: 12.4, W12X14: 3.97, W12X152: 12.5, W12X16: 3.99, W12X170: 12.6, W12X19: 4.01, W12X190: 12.7, W12X210: 12.8, W12X22: 4.03, W12X230: 12.9, W12X252: 13, W12X26: 6.49, W12X279: 13.1, W12X30: 6.52, W12X305: 13.2, W12X336: 13.4, W12X35: 6.56, W12X40: 8.01, W12X45: 8.05, W12X50: 8.08, W12X53: 10, W12X58: 10, W12X65: 12, W12X72: 12, W12X79: 12.1, W12X87: 12.1, W12X96: 12.2, W14X109: 14.6, W14X120: 14.7, W14X132: 14.7, W14X145: 15.5, W14X159: 15.6, W14X176: 15.7, W14X193: 15.7, W14X211: 15.8, W14X22: 5, W14X233: 15.9, W14X257: 16, W14X26: 5.03, W14X283: 16.1, W14X30: 6.73, W14X311: 16.2, W14X34: 6.75, W14X342: 16.4, W14X370: 16.5, W14X38: 6.77, W14X398: 16.6, W14X426: 16.7, W14X43: 8, W14X455: 16.8, W14X48: 8.03, W14X500: 17, W14X53: 8.06, W14X550: 17.2, W14X605: 17.4, W14X61: 10, W14X665: 17.7, W14X68: 10, W14X730: 17.9, W14X74: 10.1, W14X808: 18.6, W14X82: 10.1, W14X873: 18.8, W14X90: 14.5, W14X99: 14.6, W16X100: 10.4, W16X26: 5.5, W16X31: 5.53, W16X36: 6.99, W16X40: 7, W16X45: 7.04, W16X50: 7.07, W16X57: 7.12, W16X67: 10.2, W16X77: 10.3, W16X89: 10.4, W18X106: 11.2, W18X119: 11.3, W18X130: 11.2, W18X143: 11.2, W18X158: 11.3, W18X175: 11.4, W18X192: 11.5, W18X211: 11.6, W18X234: 11.7, W18X258: 11.8, W18X283: 11.9, W18X311: 12, W18X35: 6, W18X40: 6.02, W18X46: 6.06, W18X50: 7.5, W18X55: 7.53, W18X60: 7.56, W18X65: 7.59, W18X71: 7.64, W18X76: 11, W18X86: 11.1, W18X97: 11.1, W21X101: 12.3, W21X111: 12.3, W21X122: 12.4, W21X132: 12.4, W21X147: 12.5, W21X166: 12.4, W21X182: 12.5, W21X201: 12.6, W21X223: 12.7, W21X248: 12.8, W21X275: 12.9, W21X44: 6.5, W21X48: 8.14, W21X50: 6.53, W21X55: 8.22, W21X57: 6.56, W21X62: 8.24, W21X68: 8.27, W21X73: 8.3, W21X83: 8.36, W21X93: 8.42, W24X103: 9, W24X104: 12.8, W24X117: 12.8, W24X131: 12.9, W24X146: 12.9, W24X162: 13, W24X176: 12.9, W24X192: 13, W24X207: 13, W24X229: 13.1, W24X250: 13.2, W24X279: 13.3, W24X306: 13.4, W24X335: 13.5, W24X370: 13.7, W24X55: 7.01, W24X62: 7.04, W24X68: 8.97, W24X76: 8.99, W24X84: 9.02, W24X94: 9.07, W27X102: 10, W27X114: 10.1, W27X129: 10, W27X146: 14, W27X161: 14, W27X178: 14.1, W27X194: 14, W27X217: 14.1, W27X235: 14.2, W27X258: 14.3, W27X281: 14.4, W27X307: 14.4, W27X336: 14.6, W27X368: 14.7, W27X539: 15.3, W27X84: 10, W27X94: 10, W30X108: 10.5, W30X116: 10.5, W30X124: 10.5, W30X132: 10.5, W30X148: 10.5, W30X173: 15, W30X191: 15, W30X211: 15.1, W30X235: 15.1, W30X261: 15.2, W30X292: 15.3, W30X326: 15.4, W30X357: 15.5, W30X391: 15.6, W30X90: 10.4, W30X99: 10.5, W33X118: 11.5, W33X130: 11.5, W33X141: 11.5, W33X152: 11.6, W33X169: 11.5, W33X201: 15.7, W33X221: 15.8, W33X241: 15.9, W33X263: 15.8, W33X291: 15.9, W33X318: 16, W33X354: 16.1, W33X387: 16.2, W36X135: 12, W36X150: 12, W36X160: 12, W36X170: 12, W36X182: 12.1, W36X194: 12.1, W36X210: 12.2, W36X231: 16.5, W36X232: 12.1, W36X247: 16.5, W36X256: 12.2, W36X262: 16.6, W36X282: 16.6, W36X302: 16.7, W36X330: 16.6, W36X361: 16.7, W36X395: 16.8, W36X441: 17, W36X487: 17.1, W36X529: 17.2, W36X652: 17.6, W36X723: 17.8, W36X802: 18, W36X853: 18.2, W36X925: 18.6, W40X149: 11.8, W40X167: 11.8, W40X183: 11.8, W40X199: 15.8, W40X211: 11.8, W40X215: 15.8, W40X235: 11.9, W40X249: 15.8, W40X264: 11.9, W40X277: 15.8, W40X278: 12, W40X294: 12, W40X297: 15.8, W40X324: 15.9, W40X327: 12.1, W40X331: 12.2, W40X362: 16, W40X372: 16.1, W40X392: 12.4, W40X397: 16.1, W40X431: 16.2, W40X503: 16.4, W40X593: 16.7, W40X655: 16.9, W44X230: 15.8, W44X262: 15.8, W44X290: 15.8, W44X335: 15.9, W4X13: 4.06, W5X16: 5, W5X19: 5.03, W6X12: 4, W6X15: 5.99, W6X16: 4.03, W6X20: 6.02, W6X25: 6.08, "W6X8.5": 3.94, W6X9: 3.94, W8X10: 3.94, W8X13: 4, W8X15: 4.02, W8X18: 5.25, W8X21: 5.27, W8X24: 6.5, W8X28: 6.54, W8X31: 8, W8X35: 8.02, W8X40: 8.07, W8X48: 8.11, W8X58: 8.22, W8X67: 8.28, "WT10.5X100.5": 12.6, "WT10.5X111.5": 12.7, "WT10.5X124": 12.8, "WT10.5X137.5": 12.9, "WT10.5X22": 6.5, "WT10.5X24": 8.14, "WT10.5X25": 6.53, "WT10.5X27.5": 8.22, "WT10.5X28.5": 6.56, "WT10.5X31": 8.24, "WT10.5X34": 8.27, "WT10.5X36.5": 8.3, "WT10.5X41.5": 8.36, "WT10.5X46.5": 8.42, "WT10.5X50.5": 12.3, "WT10.5X55.5": 12.3, "WT10.5X61": 12.4, "WT10.5X66": 12.4, "WT10.5X73.5": 12.5, "WT10.5X83": 12.4, "WT10.5X91": 12.5, "WT12X103.5": 13, "WT12X114.5": 13.1, WT12X125: 13.2, "WT12X139.5": 13.3, WT12X153: 13.4, "WT12X167.5": 13.5, WT12X185: 13.7, "WT12X27.5": 7.01, WT12X31: 7.04, WT12X34: 8.97, WT12X38: 8.99, WT12X42: 9.02, WT12X47: 9.07, "WT12X51.5": 9, WT12X52: 12.8, "WT12X58.5": 12.8, "WT12X65.5": 12.9, WT12X73: 12.9, WT12X81: 13, WT12X88: 12.9, WT12X96: 13, "WT13.5X108.5": 14.1, "WT13.5X117.5": 14.2, "WT13.5X129": 14.3, "WT13.5X140.5": 14.4, "WT13.5X153.5": 14.4, "WT13.5X168": 14.6, "WT13.5X184": 14.7, "WT13.5X269.5": 15.3, "WT13.5X42": 10, "WT13.5X47": 10, "WT13.5X51": 10, "WT13.5X57": 10.1, "WT13.5X64.5": 10, "WT13.5X73": 14, "WT13.5X80.5": 14, "WT13.5X89": 14.1, "WT13.5X97": 14, "WT15X105.5": 15.1, "WT15X117.5": 15.1, "WT15X130.5": 15.2, WT15X146: 15.3, WT15X163: 15.4, "WT15X178.5": 15.5, "WT15X195.5": 15.6, WT15X45: 10.4, "WT15X49.5": 10.5, WT15X54: 10.5, WT15X58: 10.5, WT15X62: 10.5, WT15X66: 10.5, WT15X74: 10.5, "WT15X86.5": 15, "WT15X95.5": 15, "WT16.5X100.5": 15.7, "WT16.5X110.5": 15.8, "WT16.5X120.5": 15.9, "WT16.5X131.5": 15.8, "WT16.5X145.5": 15.9, "WT16.5X159": 16, "WT16.5X177": 16.1, "WT16.5X193.5": 16.2, "WT16.5X59": 11.5, "WT16.5X65": 11.5, "WT16.5X70.5": 11.5, "WT16.5X76": 11.6, "WT16.5X84.5": 11.5, WT18X105: 12.2, "WT18X115.5": 16.5, WT18X116: 12.1, "WT18X123.5": 16.5, WT18X128: 12.2, WT18X131: 16.6, WT18X141: 16.6, WT18X151: 16.7, WT18X165: 16.6, "WT18X180.5": 16.7, "WT18X197.5": 16.8, "WT18X220.5": 17, "WT18X243.5": 17.1, "WT18X264.5": 17.2, WT18X326: 17.6, "WT18X361.5": 17.8, WT18X401: 18, "WT18X426.5": 18.2, "WT18X462.5": 18.6, "WT18X67.5": 12, WT18X75: 12, WT18X80: 12, WT18X85: 12, WT18X91: 12.1, WT18X97: 12.1, "WT2.5X8": 5, "WT2.5X9.5": 5.03, "WT20X105.5": 11.8, "WT20X107.5": 15.8, "WT20X117.5": 11.9, "WT20X124.5": 15.8, WT20X132: 11.9, "WT20X138.5": 15.8, WT20X139: 12, WT20X147: 12, "WT20X148.5": 15.8, WT20X162: 15.9, "WT20X163.5": 12.1, "WT20X165.5": 12.2, WT20X181: 16, WT20X186: 16.1, WT20X196: 12.4, "WT20X198.5": 16.1, "WT20X215.5": 16.2, "WT20X251.5": 16.4, "WT20X296.5": 16.7, "WT20X327.5": 16.9, "WT20X74.5": 11.8, "WT20X83.5": 11.8, "WT20X91.5": 11.8, "WT20X99.5": 15.8, WT22X115: 15.8, WT22X131: 15.8, WT22X145: 15.8, "WT22X167.5": 15.9, "WT2X6.5": 4.06, WT3X10: 6.02, "WT3X12.5": 6.08, "WT3X4.25": 3.94, "WT3X4.5": 3.94, WT3X6: 4, "WT3X7.5": 5.99, WT3X8: 4.03, "WT4X10.5": 5.27, WT4X12: 6.5, WT4X14: 6.54, "WT4X15.5": 8, "WT4X17.5": 8.02, WT4X20: 8.07, WT4X24: 8.11, WT4X29: 8.22, "WT4X33.5": 8.28, WT4X5: 3.94, "WT4X6.5": 4, "WT4X7.5": 4.02, WT4X9: 5.25, WT5X11: 5.75, WT5X13: 5.77, WT5X15: 5.81, "WT5X16.5": 7.96, "WT5X19.5": 7.99, "WT5X22.5": 8.02, "WT5X24.5": 10, WT5X27: 10, WT5X30: 10.1, WT5X34: 10.1, "WT5X38.5": 10.2, WT5X44: 10.3, WT5X50: 10.3, WT5X56: 10.4, WT5X6: 3.96, "WT5X7.5": 4, "WT5X8.5": 4.01, "WT5X9.5": 4.02, WT6X105: 12.8, WT6X11: 4.03, WT6X115: 12.9, WT6X126: 13, WT6X13: 6.49, "WT6X139.5": 13.1, WT6X15: 6.52, "WT6X152.5": 13.2, WT6X168: 13.4, "WT6X17.5": 6.56, WT6X20: 8.01, "WT6X22.5": 8.05, WT6X25: 8.08, "WT6X26.5": 10, WT6X29: 10, "WT6X32.5": 12, WT6X36: 12, "WT6X39.5": 12.1, "WT6X43.5": 12.1, WT6X48: 12.2, WT6X53: 12.2, WT6X60: 12.3, WT6X68: 12.4, WT6X7: 3.97, WT6X76: 12.5, WT6X8: 3.99, WT6X85: 12.6, "WT6X9.5": 4.01, WT6X95: 12.7, "WT7X105.5": 15.8, WT7X11: 5, "WT7X116.5": 15.9, "WT7X128.5": 16, WT7X13: 5.03, "WT7X141.5": 16.1, WT7X15: 6.73, "WT7X155.5": 16.2, WT7X17: 6.75, WT7X171: 16.4, WT7X185: 16.5, WT7X19: 6.77, WT7X199: 16.6, "WT7X21.5": 8, WT7X213: 16.7, "WT7X227.5": 16.8, WT7X24: 8.03, WT7X250: 17, "WT7X26.5": 8.06, WT7X275: 17.2, "WT7X30.5": 10, "WT7X302.5": 17.4, "WT7X332.5": 17.7, WT7X34: 10, WT7X365: 17.9, WT7X37: 10.1, WT7X404: 18.6, WT7X41: 10.1, "WT7X436.5": 18.8, WT7X45: 14.5, "WT7X49.5": 14.6, "WT7X54.5": 14.6, WT7X60: 14.7, WT7X66: 14.7, "WT7X72.5": 15.5, "WT7X79.5": 15.6, WT7X88: 15.7, "WT7X96.5": 15.7, WT8X13: 5.5, "WT8X15.5": 5.53, WT8X18: 6.99, WT8X20: 7, "WT8X22.5": 7.04, WT8X25: 7.07, "WT8X28.5": 7.12, "WT8X33.5": 10.2, "WT8X38.5": 10.3, "WT8X44.5": 10.4, WT8X50: 10.4, "WT9X105.5": 11.6, WT9X117: 11.7, WT9X129: 11.8, "WT9X141.5": 11.9, "WT9X155.5": 12, "WT9X17.5": 6, WT9X20: 6.02, WT9X23: 6.06, WT9X25: 7.5, "WT9X27.5": 7.53, WT9X30: 7.56, "WT9X32.5": 7.59, "WT9X35.5": 7.64, WT9X38: 11, WT9X43: 11.1, "WT9X48.5": 11.1, WT9X53: 11.2, "WT9X59.5": 11.3, WT9X65: 11.2, "WT9X71.5": 11.2, WT9X79: 11.3, "WT9X87.5": 11.4, WT9X96: 11.5 };
|
|
53398
53469
|
|
|
53399
53470
|
// index.ts
|
|
53400
|
-
var
|
|
53471
|
+
var import_node_crypto9 = require("node:crypto");
|
|
53401
53472
|
|
|
53402
53473
|
// graft.ts
|
|
53403
53474
|
var TEKLA_MARKER = "Recipe: Tekla model plug-in";
|
|
@@ -53746,14 +53817,158 @@ function decodeSnapshots(inputs) {
|
|
|
53746
53817
|
});
|
|
53747
53818
|
}
|
|
53748
53819
|
|
|
53820
|
+
// connection-import.ts
|
|
53821
|
+
var import_node_fs17 = require("node:fs");
|
|
53822
|
+
var import_node_path15 = require("node:path");
|
|
53823
|
+
var AGENT = "connection-reader";
|
|
53824
|
+
var MAX_PARTS = 5e3;
|
|
53825
|
+
var MAX_VERTICES = 3e6;
|
|
53826
|
+
var readerChain = Promise.resolve();
|
|
53827
|
+
var ConnectionImportError = class extends Error {
|
|
53828
|
+
};
|
|
53829
|
+
async function ensureConnectionReader() {
|
|
53830
|
+
try {
|
|
53831
|
+
await aware.ensureAgentInstalled(AGENT);
|
|
53832
|
+
await aware.ensureConnectionReaderBridge();
|
|
53833
|
+
} catch (e) {
|
|
53834
|
+
throw new ConnectionImportError(`could not set up the connection reader \u2014 check your network and try again${e instanceof Error && e.message ? ` (${e.message})` : ""}`);
|
|
53835
|
+
}
|
|
53836
|
+
}
|
|
53837
|
+
function writeReaderApp(companionId, command, ifcPath, id) {
|
|
53838
|
+
const dir = appPath(companionId);
|
|
53839
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
53840
|
+
const flo = (0, import_node_path15.join)(dir, `${companionId}.flo`);
|
|
53841
|
+
const lines = [
|
|
53842
|
+
`app: ${companionId}`,
|
|
53843
|
+
"version: 0.1.0",
|
|
53844
|
+
`display-name: Connection reader (${command})`,
|
|
53845
|
+
`description: ${command === "list" ? "List the steel connections found in an IFC file \u2014 the candidates a user picks from before importing one." : "Read one steel connection from an IFC file as tessellated mesh geometry, for import into the model."}`,
|
|
53846
|
+
"exposes-as-agent: false",
|
|
53847
|
+
"requires:",
|
|
53848
|
+
` - ${AGENT}@0.1.x`,
|
|
53849
|
+
"layout: linear",
|
|
53850
|
+
"nodes:",
|
|
53851
|
+
` - id: ${command}`,
|
|
53852
|
+
` agent: ${AGENT}`,
|
|
53853
|
+
` command: ${command}`,
|
|
53854
|
+
" config:",
|
|
53855
|
+
` ifc-path: ${JSON.stringify(ifcPath)}`
|
|
53856
|
+
];
|
|
53857
|
+
if (command === "extract") lines.push(` id: ${JSON.stringify(id ?? "")}`);
|
|
53858
|
+
lines.push("");
|
|
53859
|
+
(0, import_node_fs17.writeFileSync)(flo, lines.join("\n"));
|
|
53860
|
+
return flo;
|
|
53861
|
+
}
|
|
53862
|
+
function nodeOutput(traceText, node) {
|
|
53863
|
+
const events = traceText ? parseTrace(traceText) : [];
|
|
53864
|
+
const ev = [...events].reverse().find((e) => e.kind === "node-output" && e.node === node);
|
|
53865
|
+
const data = ev ? ev.data : null;
|
|
53866
|
+
return data && typeof data === "object" ? data : null;
|
|
53867
|
+
}
|
|
53868
|
+
async function runReader(companionId, command, ifcPath, id) {
|
|
53869
|
+
const prev = readerChain;
|
|
53870
|
+
let release;
|
|
53871
|
+
readerChain = new Promise((r) => release = r);
|
|
53872
|
+
await prev.catch(() => {
|
|
53873
|
+
});
|
|
53874
|
+
try {
|
|
53875
|
+
const flo = writeReaderApp(companionId, command, ifcPath, id);
|
|
53876
|
+
try {
|
|
53877
|
+
await aware.compile(flo);
|
|
53878
|
+
} catch (e) {
|
|
53879
|
+
throw new ConnectionImportError(`could not compile the connection reader: ${e instanceof Error ? e.message : "compile error"}`);
|
|
53880
|
+
}
|
|
53881
|
+
let traceText;
|
|
53882
|
+
try {
|
|
53883
|
+
({ traceText } = await aware.run(companionId, {}));
|
|
53884
|
+
} catch (e) {
|
|
53885
|
+
const reason = e instanceof AwareError ? String(e.detail?.stderr ?? "").trim() : "";
|
|
53886
|
+
throw new ConnectionImportError(reason || (e instanceof Error ? e.message : "the connection reader failed"));
|
|
53887
|
+
}
|
|
53888
|
+
const out = nodeOutput(traceText, command);
|
|
53889
|
+
if (!out) throw new ConnectionImportError("the connection reader returned no result");
|
|
53890
|
+
return out;
|
|
53891
|
+
} finally {
|
|
53892
|
+
release();
|
|
53893
|
+
}
|
|
53894
|
+
}
|
|
53895
|
+
async function listConnections(companionId, ifcPath) {
|
|
53896
|
+
await ensureConnectionReader();
|
|
53897
|
+
const out = await runReader(companionId, "list", ifcPath);
|
|
53898
|
+
if (!Array.isArray(out.connections)) {
|
|
53899
|
+
throw new ConnectionImportError(typeof out.message === "string" ? out.message : "no connections found in that IFC file");
|
|
53900
|
+
}
|
|
53901
|
+
return out.connections.filter((c) => !!c && typeof c === "object");
|
|
53902
|
+
}
|
|
53903
|
+
function bboxCenter(parts) {
|
|
53904
|
+
let mnx = Infinity, mny = Infinity, mnz = Infinity, mxx = -Infinity, mxy = -Infinity, mxz = -Infinity;
|
|
53905
|
+
for (const p of parts) {
|
|
53906
|
+
for (let i = 0; i + 2 < p.positions.length; i += 3) {
|
|
53907
|
+
const x = p.positions[i], y = p.positions[i + 1], z = p.positions[i + 2];
|
|
53908
|
+
if (x < mnx) mnx = x;
|
|
53909
|
+
if (x > mxx) mxx = x;
|
|
53910
|
+
if (y < mny) mny = y;
|
|
53911
|
+
if (y > mxy) mxy = y;
|
|
53912
|
+
if (z < mnz) mnz = z;
|
|
53913
|
+
if (z > mxz) mxz = z;
|
|
53914
|
+
}
|
|
53915
|
+
}
|
|
53916
|
+
if (!isFinite(mnx)) return [0, 0, 0];
|
|
53917
|
+
return [(mnx + mxx) / 2, (mny + mxy) / 2, (mnz + mxz) / 2];
|
|
53918
|
+
}
|
|
53919
|
+
function shiftPositions(positions, [dx, dy, dz]) {
|
|
53920
|
+
const out = new Array(positions.length);
|
|
53921
|
+
for (let i = 0; i + 2 < positions.length; i += 3) {
|
|
53922
|
+
out[i] = positions[i] - dx;
|
|
53923
|
+
out[i + 1] = positions[i + 1] - dy;
|
|
53924
|
+
out[i + 2] = positions[i + 2] - dz;
|
|
53925
|
+
}
|
|
53926
|
+
return out;
|
|
53927
|
+
}
|
|
53928
|
+
function validPart(p) {
|
|
53929
|
+
const q = p;
|
|
53930
|
+
return !!q && Array.isArray(q.positions) && Array.isArray(q.indices) && q.positions.length >= 9 && q.indices.length >= 3 && q.positions.length % 3 === 0;
|
|
53931
|
+
}
|
|
53932
|
+
function toCustomConnection(raw, fallbackId) {
|
|
53933
|
+
const conn = raw.connection;
|
|
53934
|
+
if (!conn || typeof conn !== "object") {
|
|
53935
|
+
throw new ConnectionImportError(typeof raw.message === "string" ? raw.message : "could not read that connection");
|
|
53936
|
+
}
|
|
53937
|
+
const c = conn;
|
|
53938
|
+
const valid = (Array.isArray(c.parts) ? c.parts : []).filter(validPart);
|
|
53939
|
+
if (valid.length > MAX_PARTS) throw new ConnectionImportError(`that connection has too many parts (${valid.length}) to import`);
|
|
53940
|
+
let totalVerts = 0;
|
|
53941
|
+
for (const p of valid) totalVerts += p.positions.length / 3;
|
|
53942
|
+
if (totalVerts > MAX_VERTICES) throw new ConnectionImportError(`that connection is too large to import (${Math.round(totalVerts / 1e3)}k vertices)`);
|
|
53943
|
+
const anchor = bboxCenter(valid);
|
|
53944
|
+
const geometry = valid.map((p) => ({
|
|
53945
|
+
...typeof p.id === "string" ? { id: p.id } : {},
|
|
53946
|
+
...typeof p.role === "string" ? { role: p.role } : {},
|
|
53947
|
+
positions: shiftPositions(p.positions, anchor),
|
|
53948
|
+
indices: p.indices.slice()
|
|
53949
|
+
}));
|
|
53950
|
+
return {
|
|
53951
|
+
id: typeof c.id === "string" ? c.id : fallbackId,
|
|
53952
|
+
name: typeof c.name === "string" ? c.name : "Imported connection",
|
|
53953
|
+
type: typeof c.type === "string" ? c.type : null,
|
|
53954
|
+
members: Array.isArray(c.members) ? c.members.filter((m) => typeof m === "string") : [],
|
|
53955
|
+
geometry
|
|
53956
|
+
};
|
|
53957
|
+
}
|
|
53958
|
+
async function extractConnection(companionId, ifcPath, id) {
|
|
53959
|
+
await ensureConnectionReader();
|
|
53960
|
+
const out = await runReader(companionId, "extract", ifcPath, id);
|
|
53961
|
+
return toCustomConnection(out, id);
|
|
53962
|
+
}
|
|
53963
|
+
|
|
53749
53964
|
// contract-store.ts
|
|
53750
|
-
var
|
|
53751
|
-
var
|
|
53965
|
+
var import_node_fs19 = require("node:fs");
|
|
53966
|
+
var import_node_path17 = require("node:path");
|
|
53752
53967
|
var import_node_os12 = require("node:os");
|
|
53753
53968
|
|
|
53754
53969
|
// contract-schema.ts
|
|
53755
|
-
var
|
|
53756
|
-
var
|
|
53970
|
+
var import_node_fs18 = require("node:fs");
|
|
53971
|
+
var import_node_path16 = require("node:path");
|
|
53757
53972
|
var import_node_url2 = require("node:url");
|
|
53758
53973
|
function validate(doc, schema) {
|
|
53759
53974
|
const errors = [];
|
|
@@ -53855,16 +54070,16 @@ var _cache = /* @__PURE__ */ new Map();
|
|
|
53855
54070
|
function loadContractSchema(file) {
|
|
53856
54071
|
const hit = _cache.get(file);
|
|
53857
54072
|
if (hit) return hit;
|
|
53858
|
-
const here2 = (0,
|
|
54073
|
+
const here2 = (0, import_node_path16.dirname)((0, import_node_url2.fileURLToPath)(__import_meta_url));
|
|
53859
54074
|
const candidates = [
|
|
53860
|
-
(0,
|
|
54075
|
+
(0, import_node_path16.join)(here2, "..", "schemas", file),
|
|
53861
54076
|
// dev: server/ next to schemas/
|
|
53862
|
-
(0,
|
|
54077
|
+
(0, import_node_path16.join)(here2, "schemas", file)
|
|
53863
54078
|
// bundled: dist/ holds ./schemas
|
|
53864
54079
|
];
|
|
53865
54080
|
for (const p of candidates) {
|
|
53866
54081
|
try {
|
|
53867
|
-
const parsed = JSON.parse((0,
|
|
54082
|
+
const parsed = JSON.parse((0, import_node_fs18.readFileSync)(p, "utf8"));
|
|
53868
54083
|
_cache.set(file, parsed);
|
|
53869
54084
|
return parsed;
|
|
53870
54085
|
} catch (err2) {
|
|
@@ -53894,8 +54109,8 @@ function validateContract(doc) {
|
|
|
53894
54109
|
// contract-store.ts
|
|
53895
54110
|
var ContractError = class extends Error {
|
|
53896
54111
|
};
|
|
53897
|
-
var ROOT3 = process.env.FLOLESS_HOME ?? (0,
|
|
53898
|
-
var DIR = (0,
|
|
54112
|
+
var ROOT3 = process.env.FLOLESS_HOME ?? (0, import_node_path17.join)((0, import_node_os12.homedir)(), ".floless");
|
|
54113
|
+
var DIR = (0, import_node_path17.join)(ROOT3, "contracts");
|
|
53899
54114
|
function safeId(appId) {
|
|
53900
54115
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId)) throw new ContractError(`invalid appId: ${appId}`);
|
|
53901
54116
|
return appId;
|
|
@@ -53905,14 +54120,14 @@ function safeProjectSeg(projectId) {
|
|
|
53905
54120
|
return projectId;
|
|
53906
54121
|
}
|
|
53907
54122
|
function contractPath(appId, projectId) {
|
|
53908
|
-
if (projectId) return (0,
|
|
53909
|
-
return (0,
|
|
54123
|
+
if (projectId) return (0, import_node_path17.join)(ROOT3, "projects", safeProjectSeg(projectId), "contract.json");
|
|
54124
|
+
return (0, import_node_path17.join)(DIR, `${safeId(appId)}.json`);
|
|
53910
54125
|
}
|
|
53911
54126
|
function readContract(appId, projectId) {
|
|
53912
54127
|
const p = contractPath(appId, projectId);
|
|
53913
|
-
if (!(0,
|
|
54128
|
+
if (!(0, import_node_fs19.existsSync)(p)) return null;
|
|
53914
54129
|
try {
|
|
53915
|
-
return JSON.parse((0,
|
|
54130
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(p, "utf8"));
|
|
53916
54131
|
} catch (e) {
|
|
53917
54132
|
console.warn(`readContract: ignoring unreadable contract at ${p}: ${e instanceof Error ? e.message : e}`);
|
|
53918
54133
|
return null;
|
|
@@ -53926,11 +54141,11 @@ function writeContract(appId, doc, projectId) {
|
|
|
53926
54141
|
throw new ContractError(`contract failed schema validation \u2014 ${first}`);
|
|
53927
54142
|
}
|
|
53928
54143
|
if (projectId) {
|
|
53929
|
-
if (!(0,
|
|
53930
|
-
} else if (!(0,
|
|
53931
|
-
(0,
|
|
54144
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path17.dirname)(p))) throw new ContractError(`unknown project: ${projectId}`);
|
|
54145
|
+
} else if (!(0, import_node_fs19.existsSync)(DIR)) {
|
|
54146
|
+
(0, import_node_fs19.mkdirSync)(DIR, { recursive: true });
|
|
53932
54147
|
}
|
|
53933
|
-
(0,
|
|
54148
|
+
(0, import_node_fs19.writeFileSync)(p, JSON.stringify(doc));
|
|
53934
54149
|
}
|
|
53935
54150
|
|
|
53936
54151
|
// contract-resolve.ts
|
|
@@ -53953,15 +54168,15 @@ function readContractForApp(appId, readAppFn = readApp) {
|
|
|
53953
54168
|
}
|
|
53954
54169
|
|
|
53955
54170
|
// projects-store.ts
|
|
53956
|
-
var
|
|
53957
|
-
var
|
|
54171
|
+
var import_node_fs20 = require("node:fs");
|
|
54172
|
+
var import_node_path18 = require("node:path");
|
|
53958
54173
|
var import_node_os13 = require("node:os");
|
|
53959
54174
|
var import_node_crypto6 = require("node:crypto");
|
|
53960
54175
|
var ProjectError = class extends Error {
|
|
53961
54176
|
};
|
|
53962
|
-
var ROOT4 = process.env.FLOLESS_HOME ?? (0,
|
|
53963
|
-
var DIR2 = (0,
|
|
53964
|
-
var ARCHIVE = (0,
|
|
54177
|
+
var ROOT4 = process.env.FLOLESS_HOME ?? (0, import_node_path18.join)((0, import_node_os13.homedir)(), ".floless");
|
|
54178
|
+
var DIR2 = (0, import_node_path18.join)(ROOT4, "projects");
|
|
54179
|
+
var ARCHIVE = (0, import_node_path18.join)(DIR2, ".archive");
|
|
53965
54180
|
function safeProjectId(id) {
|
|
53966
54181
|
if (typeof id !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(id)) {
|
|
53967
54182
|
throw new ProjectError(`invalid project id: ${String(id)}`);
|
|
@@ -53973,28 +54188,28 @@ function slugify(name) {
|
|
|
53973
54188
|
return s || "project";
|
|
53974
54189
|
}
|
|
53975
54190
|
function projectDir(id) {
|
|
53976
|
-
return (0,
|
|
54191
|
+
return (0, import_node_path18.join)(DIR2, safeProjectId(id));
|
|
53977
54192
|
}
|
|
53978
54193
|
function projectExportsDir(id) {
|
|
53979
|
-
return (0,
|
|
54194
|
+
return (0, import_node_path18.join)(projectDir(id), "exports");
|
|
53980
54195
|
}
|
|
53981
|
-
var metaPath = (id) => (0,
|
|
54196
|
+
var metaPath = (id) => (0, import_node_path18.join)(projectDir(id), "project.json");
|
|
53982
54197
|
function readMeta(id) {
|
|
53983
54198
|
const p = metaPath(id);
|
|
53984
|
-
if (!(0,
|
|
54199
|
+
if (!(0, import_node_fs20.existsSync)(p)) return null;
|
|
53985
54200
|
try {
|
|
53986
|
-
const meta = JSON.parse((0,
|
|
54201
|
+
const meta = JSON.parse((0, import_node_fs20.readFileSync)(p, "utf8"));
|
|
53987
54202
|
return meta && meta.id === id ? meta : null;
|
|
53988
54203
|
} catch (e) {
|
|
53989
54204
|
console.warn(`projects-store: ignoring unreadable project.json at ${p}: ${e instanceof Error ? e.message : e}`);
|
|
53990
54205
|
return null;
|
|
53991
54206
|
}
|
|
53992
54207
|
}
|
|
53993
|
-
var writeMeta = (meta) => (0,
|
|
54208
|
+
var writeMeta = (meta) => (0, import_node_fs20.writeFileSync)(metaPath(meta.id), JSON.stringify(meta, null, 2));
|
|
53994
54209
|
function listProjects() {
|
|
53995
|
-
if (!(0,
|
|
54210
|
+
if (!(0, import_node_fs20.existsSync)(DIR2)) return [];
|
|
53996
54211
|
const out = [];
|
|
53997
|
-
for (const entry2 of (0,
|
|
54212
|
+
for (const entry2 of (0, import_node_fs20.readdirSync)(DIR2, { withFileTypes: true })) {
|
|
53998
54213
|
if (!entry2.isDirectory() || entry2.name.startsWith(".")) continue;
|
|
53999
54214
|
const meta = readMeta(entry2.name);
|
|
54000
54215
|
if (meta) out.push(meta);
|
|
@@ -54010,8 +54225,8 @@ function createProject(input) {
|
|
|
54010
54225
|
if (!name) throw new ProjectError("project name required");
|
|
54011
54226
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(app)) throw new ProjectError(`invalid app id: ${app || "(empty)"}`);
|
|
54012
54227
|
let id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
|
|
54013
|
-
while ((0,
|
|
54014
|
-
(0,
|
|
54228
|
+
while ((0, import_node_fs20.existsSync)(projectDir(id))) id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
|
|
54229
|
+
(0, import_node_fs20.mkdirSync)(projectDir(id), { recursive: true });
|
|
54015
54230
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
54016
54231
|
const meta = { id, name, app, createdAt: now, updatedAt: now };
|
|
54017
54232
|
writeMeta(meta);
|
|
@@ -54046,7 +54261,7 @@ function duplicateProject(id, name) {
|
|
|
54046
54261
|
name: typeof name === "string" && name.trim() ? name.trim() : `${src.name} (copy)`,
|
|
54047
54262
|
app: src.app
|
|
54048
54263
|
});
|
|
54049
|
-
(0,
|
|
54264
|
+
(0, import_node_fs20.cpSync)(projectDir(src.id), projectDir(copy.id), {
|
|
54050
54265
|
recursive: true,
|
|
54051
54266
|
filter: (p) => !p.endsWith("project.json")
|
|
54052
54267
|
});
|
|
@@ -54054,18 +54269,117 @@ function duplicateProject(id, name) {
|
|
|
54054
54269
|
}
|
|
54055
54270
|
function archiveProject(id) {
|
|
54056
54271
|
const dir = projectDir(id);
|
|
54057
|
-
if (!(0,
|
|
54058
|
-
(0,
|
|
54059
|
-
const dest = (0,
|
|
54060
|
-
if ((0,
|
|
54061
|
-
(0,
|
|
54272
|
+
if (!(0, import_node_fs20.existsSync)(dir)) throw new ProjectError(`unknown project: ${id}`);
|
|
54273
|
+
(0, import_node_fs20.mkdirSync)(ARCHIVE, { recursive: true });
|
|
54274
|
+
const dest = (0, import_node_path18.join)(ARCHIVE, id);
|
|
54275
|
+
if ((0, import_node_fs20.existsSync)(dest)) throw new ProjectError(`already archived: ${id}`);
|
|
54276
|
+
(0, import_node_fs20.renameSync)(dir, dest);
|
|
54277
|
+
}
|
|
54278
|
+
|
|
54279
|
+
// project-versions-store.ts
|
|
54280
|
+
var import_node_crypto7 = require("node:crypto");
|
|
54281
|
+
var import_node_fs21 = require("node:fs");
|
|
54282
|
+
var import_node_path19 = require("node:path");
|
|
54283
|
+
var BLOB_MIN = 8192;
|
|
54284
|
+
var BLOB_KEY = "__blobRef__";
|
|
54285
|
+
var HASH_RE = /^[0-9a-f]{64}$/;
|
|
54286
|
+
var versionsDir = (id) => (0, import_node_path19.join)(projectDir(id), "versions");
|
|
54287
|
+
var objectsDir = (id) => (0, import_node_path19.join)(projectDir(id), "objects");
|
|
54288
|
+
var logPath = (id) => (0, import_node_path19.join)(versionsDir(id), "log.json");
|
|
54289
|
+
function writeAtomic(path, text) {
|
|
54290
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
54291
|
+
(0, import_node_fs21.writeFileSync)(tmp, text);
|
|
54292
|
+
(0, import_node_fs21.renameSync)(tmp, path);
|
|
54293
|
+
}
|
|
54294
|
+
function isVersionMeta(v) {
|
|
54295
|
+
if (!v || typeof v !== "object") return false;
|
|
54296
|
+
const r = v;
|
|
54297
|
+
return Number.isInteger(r.n) && typeof r.ts === "string" && typeof r.author === "string" && typeof r.message === "string" && (r.gate === "model" || r.gate === null) && (r.kind === "approve" || r.kind === "rollback" || r.kind === "rebake");
|
|
54298
|
+
}
|
|
54299
|
+
function loadLog(id) {
|
|
54300
|
+
try {
|
|
54301
|
+
const parsed = JSON.parse((0, import_node_fs21.readFileSync)(logPath(id), "utf8"));
|
|
54302
|
+
const raw = parsed && typeof parsed === "object" && Array.isArray(parsed.versions) ? parsed.versions : [];
|
|
54303
|
+
return { versions: raw.filter(isVersionMeta) };
|
|
54304
|
+
} catch {
|
|
54305
|
+
return { versions: [] };
|
|
54306
|
+
}
|
|
54307
|
+
}
|
|
54308
|
+
function dehydrate(node, blobs) {
|
|
54309
|
+
if (typeof node === "string") {
|
|
54310
|
+
if (node.length > BLOB_MIN) {
|
|
54311
|
+
const hash = (0, import_node_crypto7.createHash)("sha256").update(node).digest("hex");
|
|
54312
|
+
blobs.set(hash, node);
|
|
54313
|
+
return { [BLOB_KEY]: hash };
|
|
54314
|
+
}
|
|
54315
|
+
return node;
|
|
54316
|
+
}
|
|
54317
|
+
if (Array.isArray(node)) return node.map((x) => dehydrate(x, blobs));
|
|
54318
|
+
if (node && typeof node === "object") {
|
|
54319
|
+
const out = {};
|
|
54320
|
+
for (const [k, v] of Object.entries(node)) out[k] = dehydrate(v, blobs);
|
|
54321
|
+
return out;
|
|
54322
|
+
}
|
|
54323
|
+
return node;
|
|
54324
|
+
}
|
|
54325
|
+
function rehydrate(node, id) {
|
|
54326
|
+
if (Array.isArray(node)) return node.map((x) => rehydrate(x, id));
|
|
54327
|
+
if (node && typeof node === "object") {
|
|
54328
|
+
const obj = node;
|
|
54329
|
+
const keys = Object.keys(obj);
|
|
54330
|
+
const ref = obj[BLOB_KEY];
|
|
54331
|
+
if (keys.length === 1 && keys[0] === BLOB_KEY && typeof ref === "string" && HASH_RE.test(ref)) {
|
|
54332
|
+
return (0, import_node_fs21.readFileSync)((0, import_node_path19.join)(objectsDir(id), ref), "utf8");
|
|
54333
|
+
}
|
|
54334
|
+
const out = {};
|
|
54335
|
+
for (const [k, v] of Object.entries(obj)) out[k] = rehydrate(v, id);
|
|
54336
|
+
return out;
|
|
54337
|
+
}
|
|
54338
|
+
return node;
|
|
54339
|
+
}
|
|
54340
|
+
function createVersion(id, contract, meta) {
|
|
54341
|
+
(0, import_node_fs21.mkdirSync)(versionsDir(id), { recursive: true });
|
|
54342
|
+
(0, import_node_fs21.mkdirSync)(objectsDir(id), { recursive: true });
|
|
54343
|
+
const blobs = /* @__PURE__ */ new Map();
|
|
54344
|
+
const skeleton = dehydrate(contract, blobs);
|
|
54345
|
+
for (const [hash, text] of blobs) {
|
|
54346
|
+
const p = (0, import_node_path19.join)(objectsDir(id), hash);
|
|
54347
|
+
if (!(0, import_node_fs21.existsSync)(p)) writeAtomic(p, text);
|
|
54348
|
+
}
|
|
54349
|
+
const log2 = loadLog(id);
|
|
54350
|
+
const n = (log2.versions.at(-1)?.n ?? 0) + 1;
|
|
54351
|
+
const row = {
|
|
54352
|
+
n,
|
|
54353
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
54354
|
+
author: meta.author,
|
|
54355
|
+
message: meta.message,
|
|
54356
|
+
gate: meta.gate,
|
|
54357
|
+
kind: meta.kind
|
|
54358
|
+
};
|
|
54359
|
+
writeAtomic((0, import_node_path19.join)(versionsDir(id), `${n}.json`), JSON.stringify({ meta: row, contract: skeleton }, null, 2));
|
|
54360
|
+
log2.versions.push(row);
|
|
54361
|
+
writeAtomic(logPath(id), JSON.stringify(log2, null, 2));
|
|
54362
|
+
return row;
|
|
54363
|
+
}
|
|
54364
|
+
function listVersions(id) {
|
|
54365
|
+
const versions = loadLog(id).versions;
|
|
54366
|
+
const tip = versions.at(-1)?.n;
|
|
54367
|
+
return versions.map((v) => ({ ...v, current: v.n === tip })).reverse();
|
|
54368
|
+
}
|
|
54369
|
+
function readVersion(id, n) {
|
|
54370
|
+
try {
|
|
54371
|
+
const snap = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(versionsDir(id), `${n}.json`), "utf8"));
|
|
54372
|
+
return rehydrate(snap.contract, id);
|
|
54373
|
+
} catch {
|
|
54374
|
+
return null;
|
|
54375
|
+
}
|
|
54062
54376
|
}
|
|
54063
54377
|
|
|
54064
54378
|
// contract-bake.ts
|
|
54065
|
-
var
|
|
54379
|
+
var import_node_fs22 = require("node:fs");
|
|
54066
54380
|
var import_yaml5 = __toESM(require_dist6(), 1);
|
|
54067
54381
|
function bakeContractIntoApp(sourcePath, contract) {
|
|
54068
|
-
const doc = (0, import_yaml5.parseDocument)((0,
|
|
54382
|
+
const doc = (0, import_yaml5.parseDocument)((0, import_node_fs22.readFileSync)(sourcePath, "utf8"));
|
|
54069
54383
|
if (doc.errors.length > 0) {
|
|
54070
54384
|
throw new Error(`contract bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
54071
54385
|
}
|
|
@@ -54115,7 +54429,7 @@ function bakeContractIntoApp(sourcePath, contract) {
|
|
|
54115
54429
|
);
|
|
54116
54430
|
}
|
|
54117
54431
|
doc.setIn(["nodes", idx, "config", "takeoff"], baked);
|
|
54118
|
-
(0,
|
|
54432
|
+
(0, import_node_fs22.writeFileSync)(sourcePath, doc.toString());
|
|
54119
54433
|
}
|
|
54120
54434
|
|
|
54121
54435
|
// vectorize.ts
|
|
@@ -54438,8 +54752,12 @@ var GROUPS = {
|
|
|
54438
54752
|
bolt: { key: "bolt", label: "Bolts", color: "#b0c4d8" },
|
|
54439
54753
|
// cool zinc-grey (matches the anchor fasteners)
|
|
54440
54754
|
stiffener: { key: "stiffener", label: "Stiffeners", color: "#9aafc3" },
|
|
54441
|
-
cope: { key: "cope", label: "Copes", color: "#c2703a" }
|
|
54755
|
+
cope: { key: "cope", label: "Copes", color: "#c2703a" },
|
|
54442
54756
|
// a muted cut/burn amber — the removed corner (subtractive; rendered as the notch, not a swatch mesh)
|
|
54757
|
+
// Imported (custom) connection — one neutral steel band for the whole opaque assembly, so it reads
|
|
54758
|
+
// as a single imported unit (not scattered across the recipe-part legend rows). Roles (plate/bolt/
|
|
54759
|
+
// weld) are kept on each part's meta for labels, but share this one legend group + colour.
|
|
54760
|
+
custom: { key: "custom", label: "Imported connections", color: "#8a97a8" }
|
|
54443
54761
|
};
|
|
54444
54762
|
var EMBED = 1;
|
|
54445
54763
|
function num(params, key, def) {
|
|
@@ -54798,17 +55116,48 @@ function expandShearPlate(joint, beam, support) {
|
|
|
54798
55116
|
if (cope.bottom) pushCope("bottom", cope.bottom);
|
|
54799
55117
|
return parts;
|
|
54800
55118
|
}
|
|
55119
|
+
function expandCustom(joint) {
|
|
55120
|
+
const place = finite3(joint.place) ? joint.place : [0, 0, 0];
|
|
55121
|
+
const [dx, dy, dz] = place;
|
|
55122
|
+
const out = [];
|
|
55123
|
+
(joint.geometry ?? []).forEach((g, i) => {
|
|
55124
|
+
if (!g || !Array.isArray(g.positions) || !Array.isArray(g.indices)) return;
|
|
55125
|
+
if (g.positions.length < 9 || g.indices.length < 3 || g.positions.length % 3 !== 0) return;
|
|
55126
|
+
const positions = new Array(g.positions.length);
|
|
55127
|
+
for (let k = 0; k < g.positions.length; k += 3) {
|
|
55128
|
+
positions[k] = g.positions[k] + dx;
|
|
55129
|
+
positions[k + 1] = g.positions[k + 1] + dy;
|
|
55130
|
+
positions[k + 2] = g.positions[k + 2] + dz;
|
|
55131
|
+
}
|
|
55132
|
+
const role = typeof g.role === "string" ? g.role : void 0;
|
|
55133
|
+
const label = role ? role.charAt(0).toUpperCase() + role.slice(1) : "Imported part";
|
|
55134
|
+
out.push({ id: `${joint.id}:${g.id || `m${i}`}`, group: "custom", kind: "mesh", positions, indices: g.indices.slice(), meta: { label, role } });
|
|
55135
|
+
});
|
|
55136
|
+
return out;
|
|
55137
|
+
}
|
|
54801
55138
|
function expandJoints(joints, memberGeo) {
|
|
54802
55139
|
const elements = [];
|
|
54803
55140
|
const skipped = [];
|
|
54804
55141
|
const usedGroups = /* @__PURE__ */ new Set();
|
|
54805
55142
|
(joints ?? []).forEach((j, i) => {
|
|
54806
|
-
if (!j || !j.id
|
|
54807
|
-
skipped.push(
|
|
55143
|
+
if (!j || !j.id) {
|
|
55144
|
+
skipped.push(`joint#${i}`);
|
|
54808
55145
|
return;
|
|
54809
55146
|
}
|
|
54810
|
-
if (j.kind === "
|
|
54811
|
-
const
|
|
55147
|
+
if (j.kind === "custom") {
|
|
55148
|
+
const parts = expandCustom(j);
|
|
55149
|
+
if (!parts.length) {
|
|
55150
|
+
skipped.push(j.id);
|
|
55151
|
+
return;
|
|
55152
|
+
}
|
|
55153
|
+
for (const part of parts) {
|
|
55154
|
+
part.conn = j.id;
|
|
55155
|
+
part.connKind = j.kind;
|
|
55156
|
+
elements.push(part);
|
|
55157
|
+
usedGroups.add(part.group);
|
|
55158
|
+
}
|
|
55159
|
+
} else if (j.kind === "base-plate") {
|
|
55160
|
+
const col = j.main ? memberGeo.get(j.main) : void 0;
|
|
54812
55161
|
if (!col || col.role !== "column") {
|
|
54813
55162
|
skipped.push(j.id);
|
|
54814
55163
|
return;
|
|
@@ -54824,7 +55173,7 @@ function expandJoints(joints, memberGeo) {
|
|
|
54824
55173
|
usedGroups.add(part.group);
|
|
54825
55174
|
}
|
|
54826
55175
|
} else if (j.kind === "shear-plate") {
|
|
54827
|
-
const beam = memberGeo.get(j.main);
|
|
55176
|
+
const beam = j.main ? memberGeo.get(j.main) : void 0;
|
|
54828
55177
|
if (!beam || beam.role !== "beam") {
|
|
54829
55178
|
skipped.push(j.id);
|
|
54830
55179
|
return;
|
|
@@ -55046,10 +55395,10 @@ function contractToBom(contractInput) {
|
|
|
55046
55395
|
|
|
55047
55396
|
// bom-export.ts
|
|
55048
55397
|
var import_node_os14 = require("node:os");
|
|
55049
|
-
var
|
|
55398
|
+
var import_node_path20 = require("node:path");
|
|
55050
55399
|
|
|
55051
55400
|
// node_modules/write-excel-file/modules/export/writeXlsxFileNode.js
|
|
55052
|
-
var
|
|
55401
|
+
var import_node_fs23 = __toESM(require("node:fs"), 1);
|
|
55053
55402
|
|
|
55054
55403
|
// node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js
|
|
55055
55404
|
function _createForOfIteratorHelperLoose(r, e) {
|
|
@@ -59221,7 +59570,7 @@ function writeXlsxFile(arg1, arg2, arg3) {
|
|
|
59221
59570
|
},
|
|
59222
59571
|
toFile: function toFile(filePath) {
|
|
59223
59572
|
return createReadableStream().then(function(readableStream) {
|
|
59224
|
-
return pipe(readableStream,
|
|
59573
|
+
return pipe(readableStream, import_node_fs23.default.createWriteStream(filePath));
|
|
59225
59574
|
});
|
|
59226
59575
|
}
|
|
59227
59576
|
};
|
|
@@ -59246,8 +59595,8 @@ function pipe(readableStream, writableStream) {
|
|
|
59246
59595
|
|
|
59247
59596
|
// bom-export.ts
|
|
59248
59597
|
function bomExportPath(appId, format) {
|
|
59249
|
-
const root = process.env.FLOLESS_HOME ?? (0,
|
|
59250
|
-
return (0,
|
|
59598
|
+
const root = process.env.FLOLESS_HOME ?? (0, import_node_path20.join)((0, import_node_os14.homedir)(), ".floless");
|
|
59599
|
+
return (0, import_node_path20.join)(root, "exports", appId, `${appId}-bom.${format}`);
|
|
59251
59600
|
}
|
|
59252
59601
|
function csvField(v) {
|
|
59253
59602
|
let s = String(v);
|
|
@@ -59275,11 +59624,11 @@ async function bomToXlsx(bom) {
|
|
|
59275
59624
|
}
|
|
59276
59625
|
|
|
59277
59626
|
// scene-bake.ts
|
|
59278
|
-
var
|
|
59279
|
-
var
|
|
59627
|
+
var import_node_fs24 = require("node:fs");
|
|
59628
|
+
var import_node_path21 = require("node:path");
|
|
59280
59629
|
var import_yaml6 = __toESM(require_dist6(), 1);
|
|
59281
59630
|
function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
|
|
59282
|
-
const doc = (0, import_yaml6.parseDocument)((0,
|
|
59631
|
+
const doc = (0, import_yaml6.parseDocument)((0, import_node_fs24.readFileSync)(sourcePath, "utf8"));
|
|
59283
59632
|
if (doc.errors.length > 0) {
|
|
59284
59633
|
throw new Error(`scene bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
59285
59634
|
}
|
|
@@ -59288,10 +59637,10 @@ function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
|
|
|
59288
59637
|
const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.agent === agent);
|
|
59289
59638
|
if (idx < 0) throw new Error(`no ${agent} render node to bake the scene into`);
|
|
59290
59639
|
doc.setIn(["nodes", idx, "config", "scene"], scene);
|
|
59291
|
-
(0,
|
|
59640
|
+
(0, import_node_fs24.writeFileSync)(sourcePath, doc.toString());
|
|
59292
59641
|
}
|
|
59293
59642
|
function bakeNodeConfigById(sourcePath, nodeId, patch2) {
|
|
59294
|
-
const doc = (0, import_yaml6.parseDocument)((0,
|
|
59643
|
+
const doc = (0, import_yaml6.parseDocument)((0, import_node_fs24.readFileSync)(sourcePath, "utf8"));
|
|
59295
59644
|
if (doc.errors.length > 0) {
|
|
59296
59645
|
throw new Error(`node bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
59297
59646
|
}
|
|
@@ -59300,12 +59649,12 @@ function bakeNodeConfigById(sourcePath, nodeId, patch2) {
|
|
|
59300
59649
|
const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.id === nodeId);
|
|
59301
59650
|
if (idx < 0) throw new Error(`no node with id "${nodeId}"`);
|
|
59302
59651
|
for (const [key, value] of Object.entries(patch2)) doc.setIn(["nodes", idx, "config", key], value);
|
|
59303
|
-
(0,
|
|
59652
|
+
(0, import_node_fs24.writeFileSync)(sourcePath, doc.toString());
|
|
59304
59653
|
}
|
|
59305
59654
|
function writeViewer3dApp(dir, appId, scene) {
|
|
59306
|
-
(0,
|
|
59307
|
-
const flo = (0,
|
|
59308
|
-
(0,
|
|
59655
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
59656
|
+
const flo = (0, import_node_path21.join)(dir, `${appId}.flo`);
|
|
59657
|
+
(0, import_node_fs24.writeFileSync)(flo, [
|
|
59309
59658
|
`app: ${appId}`,
|
|
59310
59659
|
"version: 0.1.0",
|
|
59311
59660
|
"display-name: Steel 3D",
|
|
@@ -59326,11 +59675,11 @@ function writeViewer3dApp(dir, appId, scene) {
|
|
|
59326
59675
|
return flo;
|
|
59327
59676
|
}
|
|
59328
59677
|
function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
|
|
59329
|
-
(0,
|
|
59330
|
-
const flo = (0,
|
|
59678
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
59679
|
+
const flo = (0, import_node_path21.join)(dir, `${appId}.flo`);
|
|
59331
59680
|
const displayName = opts.displayName ?? "Steel IFC";
|
|
59332
59681
|
const description = opts.description ?? "IFC file written from an approved steel.takeoff/v1 contract (a companion export; the contract is the source of truth).";
|
|
59333
|
-
(0,
|
|
59682
|
+
(0, import_node_fs24.writeFileSync)(flo, [
|
|
59334
59683
|
`app: ${appId}`,
|
|
59335
59684
|
"version: 0.1.0",
|
|
59336
59685
|
`display-name: ${displayName}`,
|
|
@@ -59353,9 +59702,9 @@ function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
|
|
|
59353
59702
|
return flo;
|
|
59354
59703
|
}
|
|
59355
59704
|
function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
|
|
59356
|
-
(0,
|
|
59357
|
-
const flo = (0,
|
|
59358
|
-
(0,
|
|
59705
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
59706
|
+
const flo = (0, import_node_path21.join)(dir, `${appId}.flo`);
|
|
59707
|
+
(0, import_node_fs24.writeFileSync)(flo, [
|
|
59359
59708
|
`app: ${appId}`,
|
|
59360
59709
|
"version: 0.1.0",
|
|
59361
59710
|
"display-name: Steel to Tekla",
|
|
@@ -59763,13 +60112,13 @@ function scoreContract2(contractInput) {
|
|
|
59763
60112
|
}
|
|
59764
60113
|
|
|
59765
60114
|
// app-lifecycle.ts
|
|
59766
|
-
var
|
|
60115
|
+
var import_node_fs27 = require("node:fs");
|
|
59767
60116
|
var import_node_os16 = require("node:os");
|
|
59768
|
-
var
|
|
60117
|
+
var import_node_path24 = require("node:path");
|
|
59769
60118
|
|
|
59770
60119
|
// routines.ts
|
|
59771
|
-
var
|
|
59772
|
-
var
|
|
60120
|
+
var import_node_fs26 = require("node:fs");
|
|
60121
|
+
var import_node_path23 = require("node:path");
|
|
59773
60122
|
|
|
59774
60123
|
// sse.ts
|
|
59775
60124
|
var clients = /* @__PURE__ */ new Set();
|
|
@@ -59806,11 +60155,11 @@ function clientCount() {
|
|
|
59806
60155
|
}
|
|
59807
60156
|
|
|
59808
60157
|
// trigger-sessions.ts
|
|
59809
|
-
var
|
|
60158
|
+
var import_node_fs25 = require("node:fs");
|
|
59810
60159
|
var import_node_os15 = require("node:os");
|
|
59811
|
-
var
|
|
60160
|
+
var import_node_path22 = require("node:path");
|
|
59812
60161
|
var import_yaml7 = __toESM(require_dist6(), 1);
|
|
59813
|
-
var AGENTS_DIR2 = process.env.AWARE_HOME ? (0,
|
|
60162
|
+
var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path22.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path22.join)((0, import_node_os15.homedir)(), ".aware", "agents");
|
|
59814
60163
|
function summarizeFire(data) {
|
|
59815
60164
|
if (!data) return "event";
|
|
59816
60165
|
const type = typeof data.type === "string" ? data.type : "";
|
|
@@ -59827,10 +60176,10 @@ function mapTriggerState(phase) {
|
|
|
59827
60176
|
function isHostBacked(agent, agentsDir = AGENTS_DIR2) {
|
|
59828
60177
|
const safe = (n) => !n.includes("/") && !n.includes("\\") && !n.includes("..");
|
|
59829
60178
|
if (!safe(agent)) return false;
|
|
59830
|
-
const manifestPath = (0,
|
|
59831
|
-
if (!(0,
|
|
60179
|
+
const manifestPath = (0, import_node_path22.join)(agentsDir, agent, "manifest.yaml");
|
|
60180
|
+
if (!(0, import_node_fs25.existsSync)(manifestPath)) return false;
|
|
59832
60181
|
try {
|
|
59833
|
-
const doc = (0, import_yaml7.parse)((0,
|
|
60182
|
+
const doc = (0, import_yaml7.parse)((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
|
|
59834
60183
|
const transport = doc?.transport;
|
|
59835
60184
|
return !!(transport && typeof transport === "object" && "cli" in transport);
|
|
59836
60185
|
} catch {
|
|
@@ -60115,7 +60464,7 @@ var RoutineError = class extends Error {
|
|
|
60115
60464
|
}
|
|
60116
60465
|
status;
|
|
60117
60466
|
};
|
|
60118
|
-
var ROUTINES_FILE = (0,
|
|
60467
|
+
var ROUTINES_FILE = (0, import_node_path23.join)(flolessRoot, "routines.json");
|
|
60119
60468
|
var routines = [];
|
|
60120
60469
|
var loaded = false;
|
|
60121
60470
|
function ensureLoaded() {
|
|
@@ -60151,10 +60500,10 @@ function sanitizeRoutine(raw) {
|
|
|
60151
60500
|
};
|
|
60152
60501
|
}
|
|
60153
60502
|
function loadFromDisk() {
|
|
60154
|
-
if (!(0,
|
|
60503
|
+
if (!(0, import_node_fs26.existsSync)(ROUTINES_FILE)) return [];
|
|
60155
60504
|
let text;
|
|
60156
60505
|
try {
|
|
60157
|
-
text = (0,
|
|
60506
|
+
text = (0, import_node_fs26.readFileSync)(ROUTINES_FILE, "utf8");
|
|
60158
60507
|
} catch {
|
|
60159
60508
|
return [];
|
|
60160
60509
|
}
|
|
@@ -60163,17 +60512,17 @@ function loadFromDisk() {
|
|
|
60163
60512
|
return Array.isArray(parsed) ? parsed.map(sanitizeRoutine).filter((r) => r !== null) : [];
|
|
60164
60513
|
} catch {
|
|
60165
60514
|
try {
|
|
60166
|
-
(0,
|
|
60515
|
+
(0, import_node_fs26.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
|
|
60167
60516
|
} catch {
|
|
60168
60517
|
}
|
|
60169
60518
|
return [];
|
|
60170
60519
|
}
|
|
60171
60520
|
}
|
|
60172
60521
|
function saveRoutines() {
|
|
60173
|
-
if (!(0,
|
|
60522
|
+
if (!(0, import_node_fs26.existsSync)(flolessRoot)) (0, import_node_fs26.mkdirSync)(flolessRoot, { recursive: true });
|
|
60174
60523
|
const tmp = `${ROUTINES_FILE}.${process.pid}.tmp`;
|
|
60175
|
-
(0,
|
|
60176
|
-
(0,
|
|
60524
|
+
(0, import_node_fs26.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
|
|
60525
|
+
(0, import_node_fs26.renameSync)(tmp, ROUTINES_FILE);
|
|
60177
60526
|
}
|
|
60178
60527
|
function listRoutines() {
|
|
60179
60528
|
ensureLoaded();
|
|
@@ -60581,13 +60930,13 @@ var AppLifecycleError = class extends Error {
|
|
|
60581
60930
|
}
|
|
60582
60931
|
};
|
|
60583
60932
|
function appsDir() {
|
|
60584
|
-
return process.env.AWARE_HOME ? (0,
|
|
60933
|
+
return process.env.AWARE_HOME ? (0, import_node_path24.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path24.join)((0, import_node_os16.homedir)(), ".aware", "apps");
|
|
60585
60934
|
}
|
|
60586
60935
|
function appDirPath(id) {
|
|
60587
|
-
return (0,
|
|
60936
|
+
return (0, import_node_path24.join)(appsDir(), id);
|
|
60588
60937
|
}
|
|
60589
60938
|
function appInstalled(id) {
|
|
60590
|
-
return APP_ID3.test(id) && (0,
|
|
60939
|
+
return APP_ID3.test(id) && (0, import_node_fs27.existsSync)(appDirPath(id));
|
|
60591
60940
|
}
|
|
60592
60941
|
function logCascade(what, e) {
|
|
60593
60942
|
console.error(`[app-lifecycle] cascade step failed (${what}):`, e instanceof Error ? e.message : e);
|
|
@@ -60703,9 +61052,9 @@ function isGatedAwareRoute(url, method) {
|
|
|
60703
61052
|
|
|
60704
61053
|
// autostart.mjs
|
|
60705
61054
|
var import_node_child_process5 = require("node:child_process");
|
|
60706
|
-
var
|
|
61055
|
+
var import_node_fs28 = require("node:fs");
|
|
60707
61056
|
var import_node_os17 = require("node:os");
|
|
60708
|
-
var
|
|
61057
|
+
var import_node_path25 = require("node:path");
|
|
60709
61058
|
|
|
60710
61059
|
// teardown.mjs
|
|
60711
61060
|
var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
|
@@ -60817,8 +61166,8 @@ function removeLegacyRunKey() {
|
|
|
60817
61166
|
}
|
|
60818
61167
|
function logLine(msg) {
|
|
60819
61168
|
try {
|
|
60820
|
-
(0,
|
|
60821
|
-
(0,
|
|
61169
|
+
(0, import_node_fs28.mkdirSync)(logDir(), { recursive: true });
|
|
61170
|
+
(0, import_node_fs28.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
60822
61171
|
`);
|
|
60823
61172
|
} catch {
|
|
60824
61173
|
}
|
|
@@ -60826,8 +61175,8 @@ function logLine(msg) {
|
|
|
60826
61175
|
function registerAutostart(exePath) {
|
|
60827
61176
|
if (!isWin) return;
|
|
60828
61177
|
const xml = buildAutostartTaskXml(exePath, currentUserId());
|
|
60829
|
-
const tmp = (0,
|
|
60830
|
-
(0,
|
|
61178
|
+
const tmp = (0, import_node_path25.join)((0, import_node_os17.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
|
|
61179
|
+
(0, import_node_fs28.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
|
|
60831
61180
|
try {
|
|
60832
61181
|
(0, import_node_child_process5.execFileSync)("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", tmp, "/F"], {
|
|
60833
61182
|
stdio: ["ignore", "ignore", "ignore"],
|
|
@@ -60838,7 +61187,7 @@ function registerAutostart(exePath) {
|
|
|
60838
61187
|
throw err2;
|
|
60839
61188
|
} finally {
|
|
60840
61189
|
try {
|
|
60841
|
-
(0,
|
|
61190
|
+
(0, import_node_fs28.rmSync)(tmp, { force: true });
|
|
60842
61191
|
} catch {
|
|
60843
61192
|
}
|
|
60844
61193
|
}
|
|
@@ -60872,27 +61221,27 @@ function unregisterAutostart() {
|
|
|
60872
61221
|
|
|
60873
61222
|
// updater.ts
|
|
60874
61223
|
var import_node_child_process6 = require("node:child_process");
|
|
60875
|
-
var
|
|
60876
|
-
var
|
|
61224
|
+
var import_node_crypto8 = require("node:crypto");
|
|
61225
|
+
var import_node_fs30 = require("node:fs");
|
|
60877
61226
|
var import_node_stream3 = require("node:stream");
|
|
60878
61227
|
var import_promises = require("node:stream/promises");
|
|
60879
|
-
var
|
|
61228
|
+
var import_node_path27 = require("node:path");
|
|
60880
61229
|
|
|
60881
61230
|
// post-update-marker.mjs
|
|
60882
|
-
var
|
|
61231
|
+
var import_node_fs29 = require("node:fs");
|
|
60883
61232
|
var import_node_os18 = require("node:os");
|
|
60884
|
-
var
|
|
61233
|
+
var import_node_path26 = require("node:path");
|
|
60885
61234
|
var FRESH_MS = 12e4;
|
|
60886
61235
|
function markerPath() {
|
|
60887
61236
|
const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
|
|
60888
61237
|
if (override) return override;
|
|
60889
|
-
const root = process.env.FLOLESS_HOME ?? (0,
|
|
60890
|
-
return (0,
|
|
61238
|
+
const root = process.env.FLOLESS_HOME ?? (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".floless");
|
|
61239
|
+
return (0, import_node_path26.join)(root, ".post-update");
|
|
60891
61240
|
}
|
|
60892
61241
|
function legacyMarkerPath() {
|
|
60893
61242
|
if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
|
|
60894
61243
|
try {
|
|
60895
|
-
return (0,
|
|
61244
|
+
return (0, import_node_path26.join)((0, import_node_path26.dirname)((0, import_node_path26.dirname)(process.execPath)), ".floless-post-update");
|
|
60896
61245
|
} catch {
|
|
60897
61246
|
return null;
|
|
60898
61247
|
}
|
|
@@ -60902,7 +61251,7 @@ function writePostUpdateMarker() {
|
|
|
60902
61251
|
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
60903
61252
|
if (!p) continue;
|
|
60904
61253
|
try {
|
|
60905
|
-
(0,
|
|
61254
|
+
(0, import_node_fs29.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
|
|
60906
61255
|
wrote = true;
|
|
60907
61256
|
} catch {
|
|
60908
61257
|
}
|
|
@@ -60914,9 +61263,9 @@ function consumePostUpdateMarker() {
|
|
|
60914
61263
|
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
60915
61264
|
if (!p) continue;
|
|
60916
61265
|
try {
|
|
60917
|
-
if (!(0,
|
|
60918
|
-
const ageMs = Date.now() - (0,
|
|
60919
|
-
(0,
|
|
61266
|
+
if (!(0, import_node_fs29.existsSync)(p)) continue;
|
|
61267
|
+
const ageMs = Date.now() - (0, import_node_fs29.statSync)(p).mtimeMs;
|
|
61268
|
+
(0, import_node_fs29.rmSync)(p, { force: true });
|
|
60920
61269
|
if (ageMs < FRESH_MS) fresh = true;
|
|
60921
61270
|
} catch {
|
|
60922
61271
|
}
|
|
@@ -60933,13 +61282,13 @@ function currentVersion() {
|
|
|
60933
61282
|
return appVersion();
|
|
60934
61283
|
}
|
|
60935
61284
|
function installRoot() {
|
|
60936
|
-
return (0,
|
|
61285
|
+
return (0, import_node_path27.dirname)((0, import_node_path27.dirname)(process.execPath));
|
|
60937
61286
|
}
|
|
60938
61287
|
function updateExePath() {
|
|
60939
|
-
return (0,
|
|
61288
|
+
return (0, import_node_path27.join)(installRoot(), "Update.exe");
|
|
60940
61289
|
}
|
|
60941
61290
|
function packagesDir() {
|
|
60942
|
-
return (0,
|
|
61291
|
+
return (0, import_node_path27.join)(installRoot(), "packages");
|
|
60943
61292
|
}
|
|
60944
61293
|
function feedUrl() {
|
|
60945
61294
|
const env2 = (process.env.FLOLESS_UPDATE_URL ?? "").trim().replace(/\/+$/, "");
|
|
@@ -61031,23 +61380,23 @@ async function checkForUpdate() {
|
|
|
61031
61380
|
return { supported: true, currentVersion: cur, updateAvailable: true, targetVersion: latest.Version, asset: latest };
|
|
61032
61381
|
}
|
|
61033
61382
|
async function sha1OfFile(path) {
|
|
61034
|
-
const hash = (0,
|
|
61035
|
-
await (0, import_promises.pipeline)((0,
|
|
61383
|
+
const hash = (0, import_node_crypto8.createHash)("sha1");
|
|
61384
|
+
await (0, import_promises.pipeline)((0, import_node_fs30.createReadStream)(path), hash);
|
|
61036
61385
|
return hash.digest("hex").toUpperCase();
|
|
61037
61386
|
}
|
|
61038
61387
|
async function downloadPackage(asset) {
|
|
61039
61388
|
if (!NUPKG_NAME.test(asset.FileName)) throw new Error(`refusing suspicious package name: ${asset.FileName}`);
|
|
61040
61389
|
const want = asset.SHA1.toUpperCase();
|
|
61041
61390
|
const dir = packagesDir();
|
|
61042
|
-
(0,
|
|
61043
|
-
const dest = (0,
|
|
61044
|
-
if ((0,
|
|
61391
|
+
(0, import_node_fs30.mkdirSync)(dir, { recursive: true });
|
|
61392
|
+
const dest = (0, import_node_path27.join)(dir, asset.FileName);
|
|
61393
|
+
if ((0, import_node_fs30.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
|
|
61045
61394
|
const res = await authedFetch(`${feedUrl()}/${encodeURIComponent(asset.FileName)}`, {
|
|
61046
61395
|
redirect: "follow",
|
|
61047
61396
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
61048
61397
|
});
|
|
61049
61398
|
if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status} for ${asset.FileName}`);
|
|
61050
|
-
await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0,
|
|
61399
|
+
await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0, import_node_fs30.createWriteStream)(dest));
|
|
61051
61400
|
const got = await sha1OfFile(dest);
|
|
61052
61401
|
if (got !== want) throw new Error(`SHA1 mismatch for ${asset.FileName}: feed=${want} got=${got}`);
|
|
61053
61402
|
return dest;
|
|
@@ -61056,7 +61405,7 @@ async function applyUpdate(check, opts) {
|
|
|
61056
61405
|
if (!check.supported) return { applied: false, message: check.reason ?? "auto-update not supported in this runtime" };
|
|
61057
61406
|
if (!check.updateAvailable || !check.asset) return { applied: false, message: check.reason ?? "no update available" };
|
|
61058
61407
|
const exe = updateExePath();
|
|
61059
|
-
if (!(0,
|
|
61408
|
+
if (!(0, import_node_fs30.existsSync)(exe)) {
|
|
61060
61409
|
return { applied: false, message: `Update.exe not found at ${exe} \u2014 is this a Velopack install?` };
|
|
61061
61410
|
}
|
|
61062
61411
|
const pkg = await downloadPackage(check.asset);
|
|
@@ -61296,12 +61645,12 @@ function isTraceCorrupt(events) {
|
|
|
61296
61645
|
|
|
61297
61646
|
// launch.mjs
|
|
61298
61647
|
var import_node_child_process7 = require("node:child_process");
|
|
61299
|
-
var
|
|
61648
|
+
var import_node_path28 = require("node:path");
|
|
61300
61649
|
var import_node_url3 = require("node:url");
|
|
61301
|
-
var
|
|
61650
|
+
var import_node_fs31 = require("node:fs");
|
|
61302
61651
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
61303
61652
|
var import_node_readline = require("node:readline");
|
|
61304
|
-
var __dirname2 = (0,
|
|
61653
|
+
var __dirname2 = (0, import_node_path28.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
|
|
61305
61654
|
var PORT = Number(process.env.PORT ?? 4317);
|
|
61306
61655
|
var HEALTH_URL = `http://127.0.0.1:${PORT}/api/health`;
|
|
61307
61656
|
var BROWSER_URL = `http://floless.localhost:${PORT}`;
|
|
@@ -61373,8 +61722,8 @@ async function waitHealthy(timeoutMs = 3e4) {
|
|
|
61373
61722
|
function resolveServerStart() {
|
|
61374
61723
|
const packaged = /flolessapp\.exe$/i.test(process.execPath);
|
|
61375
61724
|
if (packaged) return { cmd: process.execPath, args: ["--serve"], shell: false };
|
|
61376
|
-
const bundle = (0,
|
|
61377
|
-
if ((0,
|
|
61725
|
+
const bundle = (0, import_node_path28.join)(__dirname2, "dist", "floless-server.cjs");
|
|
61726
|
+
if ((0, import_node_fs31.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
|
|
61378
61727
|
return { cmd: "npm", args: ["run", "start"], shell: isWin2 };
|
|
61379
61728
|
}
|
|
61380
61729
|
function startServerDetached() {
|
|
@@ -61527,8 +61876,8 @@ function taskkillArgs(pid, { tree = true } = {}) {
|
|
|
61527
61876
|
}
|
|
61528
61877
|
function killSupervisor({ tree = true } = {}) {
|
|
61529
61878
|
if (!isWin2) return;
|
|
61530
|
-
const isNpmChannel = /^node(\.exe)?$/i.test((0,
|
|
61531
|
-
const scriptMatch = isNpmChannel ? (0,
|
|
61879
|
+
const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path28.basename)(process.execPath));
|
|
61880
|
+
const scriptMatch = isNpmChannel ? (0, import_node_path28.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
|
|
61532
61881
|
const realExe = resolveRealInstallExe(process.execPath);
|
|
61533
61882
|
const exeMatch = realExe === process.execPath ? process.execPath : [process.execPath, realExe];
|
|
61534
61883
|
const pids = supervisorPidsToKill(enumerateProcesses(), process.pid, exeMatch, scriptMatch);
|
|
@@ -61693,7 +62042,7 @@ async function runAction(arg, flagArgv = [], selfVersion = null) {
|
|
|
61693
62042
|
}
|
|
61694
62043
|
await action(parseTeardownFlags(flagArgv));
|
|
61695
62044
|
}
|
|
61696
|
-
var entry = (0,
|
|
62045
|
+
var entry = (0, import_node_path28.basename)(process.argv[1] ?? "").toLowerCase();
|
|
61697
62046
|
if (entry === "launch.mjs") {
|
|
61698
62047
|
runAction(process.argv[2], process.argv.slice(3)).catch((e) => {
|
|
61699
62048
|
log(`error: ${e?.message ?? e}`);
|
|
@@ -61767,9 +62116,9 @@ function awareUpgradeBlockReason(s) {
|
|
|
61767
62116
|
}
|
|
61768
62117
|
|
|
61769
62118
|
// skill-sync.ts
|
|
61770
|
-
var
|
|
62119
|
+
var import_node_fs32 = require("node:fs");
|
|
61771
62120
|
var import_node_os19 = require("node:os");
|
|
61772
|
-
var
|
|
62121
|
+
var import_node_path29 = require("node:path");
|
|
61773
62122
|
var import_node_url4 = require("node:url");
|
|
61774
62123
|
var import_yaml8 = __toESM(require_dist6(), 1);
|
|
61775
62124
|
|
|
@@ -61812,14 +62161,14 @@ function selectShippedSkillNames(names) {
|
|
|
61812
62161
|
}
|
|
61813
62162
|
|
|
61814
62163
|
// skill-sync.ts
|
|
61815
|
-
var __dirname3 = (0,
|
|
62164
|
+
var __dirname3 = (0, import_node_path29.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
|
|
61816
62165
|
function bundledSkillsRoot() {
|
|
61817
62166
|
const candidates = [
|
|
61818
|
-
(0,
|
|
61819
|
-
(0,
|
|
61820
|
-
(0,
|
|
62167
|
+
(0, import_node_path29.join)(__dirname3, "skills"),
|
|
62168
|
+
(0, import_node_path29.join)((0, import_node_path29.dirname)(process.execPath), "skills"),
|
|
62169
|
+
(0, import_node_path29.join)(__dirname3, "..", ".claude", "skills")
|
|
61821
62170
|
];
|
|
61822
|
-
return candidates.find((p) => (0,
|
|
62171
|
+
return candidates.find((p) => (0, import_node_fs32.existsSync)(p)) ?? null;
|
|
61823
62172
|
}
|
|
61824
62173
|
function targetConfigDirs() {
|
|
61825
62174
|
const override = process.env.FLOLESS_SKILL_TARGETS;
|
|
@@ -61828,14 +62177,14 @@ function targetConfigDirs() {
|
|
|
61828
62177
|
}
|
|
61829
62178
|
const home = (0, import_node_os19.homedir)();
|
|
61830
62179
|
return [
|
|
61831
|
-
{ runtime: "claude", dir: (0,
|
|
61832
|
-
{ runtime: "codex", dir: (0,
|
|
61833
|
-
{ runtime: "opencode", dir: (0,
|
|
62180
|
+
{ runtime: "claude", dir: (0, import_node_path29.join)(home, ".claude") },
|
|
62181
|
+
{ runtime: "codex", dir: (0, import_node_path29.join)(home, ".codex") },
|
|
62182
|
+
{ runtime: "opencode", dir: (0, import_node_path29.join)(home, ".opencode") }
|
|
61834
62183
|
];
|
|
61835
62184
|
}
|
|
61836
62185
|
function skillVersion(skillMdPath) {
|
|
61837
62186
|
try {
|
|
61838
|
-
const text = (0,
|
|
62187
|
+
const text = (0, import_node_fs32.readFileSync)(skillMdPath, "utf8");
|
|
61839
62188
|
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
|
61840
62189
|
if (!m || m[1] === void 0) return null;
|
|
61841
62190
|
const fm = (0, import_yaml8.parse)(m[1]);
|
|
@@ -61875,21 +62224,21 @@ function decideAction(installed, bundled) {
|
|
|
61875
62224
|
function bundledSkills(root) {
|
|
61876
62225
|
let entries = [];
|
|
61877
62226
|
try {
|
|
61878
|
-
entries = selectShippedSkillNames((0,
|
|
62227
|
+
entries = selectShippedSkillNames((0, import_node_fs32.readdirSync)(root));
|
|
61879
62228
|
} catch {
|
|
61880
62229
|
return [];
|
|
61881
62230
|
}
|
|
61882
62231
|
const out = [];
|
|
61883
62232
|
for (const name of entries) {
|
|
61884
|
-
const dir = (0,
|
|
62233
|
+
const dir = (0, import_node_path29.join)(root, name);
|
|
61885
62234
|
let isDir = false;
|
|
61886
62235
|
try {
|
|
61887
|
-
isDir = (0,
|
|
62236
|
+
isDir = (0, import_node_fs32.statSync)(dir).isDirectory();
|
|
61888
62237
|
} catch {
|
|
61889
62238
|
isDir = false;
|
|
61890
62239
|
}
|
|
61891
62240
|
if (!isDir) continue;
|
|
61892
|
-
const v = skillVersion((0,
|
|
62241
|
+
const v = skillVersion((0, import_node_path29.join)(dir, "SKILL.md"));
|
|
61893
62242
|
if (!v) continue;
|
|
61894
62243
|
out.push({ name, dir, version: v });
|
|
61895
62244
|
}
|
|
@@ -61902,17 +62251,17 @@ function syncSkills() {
|
|
|
61902
62251
|
const skills = bundledSkills(root);
|
|
61903
62252
|
if (!skills.length) return results;
|
|
61904
62253
|
for (const { runtime, dir: cfg } of targetConfigDirs()) {
|
|
61905
|
-
if (!(0,
|
|
61906
|
-
const skillsDir = (0,
|
|
62254
|
+
if (!(0, import_node_fs32.existsSync)(cfg)) continue;
|
|
62255
|
+
const skillsDir = (0, import_node_path29.join)(cfg, "skills");
|
|
61907
62256
|
for (const s of skills) {
|
|
61908
|
-
const dest = (0,
|
|
61909
|
-
const installedMd = (0,
|
|
61910
|
-
const installed = (0,
|
|
62257
|
+
const dest = (0, import_node_path29.join)(skillsDir, s.name);
|
|
62258
|
+
const installedMd = (0, import_node_path29.join)(dest, "SKILL.md");
|
|
62259
|
+
const installed = (0, import_node_fs32.existsSync)(installedMd) ? skillVersion(installedMd) : null;
|
|
61911
62260
|
const action = decideAction(installed, s.version);
|
|
61912
62261
|
if (action === "installed" || action === "updated") {
|
|
61913
62262
|
try {
|
|
61914
|
-
if (action === "updated") (0,
|
|
61915
|
-
(0,
|
|
62263
|
+
if (action === "updated") (0, import_node_fs32.rmSync)(dest, { recursive: true, force: true });
|
|
62264
|
+
(0, import_node_fs32.cpSync)(s.dir, dest, { recursive: true });
|
|
61916
62265
|
results.push({ runtime, skill: s.name, action, from: installed, to: s.version });
|
|
61917
62266
|
} catch {
|
|
61918
62267
|
}
|
|
@@ -61926,8 +62275,8 @@ function syncSkills() {
|
|
|
61926
62275
|
|
|
61927
62276
|
// watch.ts
|
|
61928
62277
|
var import_node_os20 = require("node:os");
|
|
61929
|
-
var
|
|
61930
|
-
var
|
|
62278
|
+
var import_node_path31 = require("node:path");
|
|
62279
|
+
var import_node_fs33 = require("node:fs");
|
|
61931
62280
|
|
|
61932
62281
|
// node_modules/chokidar/esm/index.js
|
|
61933
62282
|
var import_fs2 = require("fs");
|
|
@@ -61938,7 +62287,7 @@ var sysPath2 = __toESM(require("path"), 1);
|
|
|
61938
62287
|
// node_modules/readdirp/esm/index.js
|
|
61939
62288
|
var import_promises2 = require("node:fs/promises");
|
|
61940
62289
|
var import_node_stream4 = require("node:stream");
|
|
61941
|
-
var
|
|
62290
|
+
var import_node_path30 = require("node:path");
|
|
61942
62291
|
var EntryTypes = {
|
|
61943
62292
|
FILE_TYPE: "files",
|
|
61944
62293
|
DIR_TYPE: "directories",
|
|
@@ -62013,7 +62362,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62013
62362
|
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
62014
62363
|
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
62015
62364
|
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
62016
|
-
this._root = (0,
|
|
62365
|
+
this._root = (0, import_node_path30.resolve)(root);
|
|
62017
62366
|
this._isDirent = !opts.alwaysStat;
|
|
62018
62367
|
this._statsProp = this._isDirent ? "dirent" : "stats";
|
|
62019
62368
|
this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
|
|
@@ -62084,8 +62433,8 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62084
62433
|
let entry2;
|
|
62085
62434
|
const basename5 = this._isDirent ? dirent.name : dirent;
|
|
62086
62435
|
try {
|
|
62087
|
-
const fullPath = (0,
|
|
62088
|
-
entry2 = { path: (0,
|
|
62436
|
+
const fullPath = (0, import_node_path30.resolve)((0, import_node_path30.join)(path, basename5));
|
|
62437
|
+
entry2 = { path: (0, import_node_path30.relative)(this._root, fullPath), fullPath, basename: basename5 };
|
|
62089
62438
|
entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
62090
62439
|
} catch (err2) {
|
|
62091
62440
|
this._onError(err2);
|
|
@@ -62119,7 +62468,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62119
62468
|
}
|
|
62120
62469
|
if (entryRealPathStats.isDirectory()) {
|
|
62121
62470
|
const len2 = entryRealPath.length;
|
|
62122
|
-
if (full.startsWith(entryRealPath) && full.substr(len2, 1) ===
|
|
62471
|
+
if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path30.sep) {
|
|
62123
62472
|
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
62124
62473
|
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
62125
62474
|
return this._onError(recursiveError);
|
|
@@ -63627,33 +63976,33 @@ function appIdFromLogPath(path) {
|
|
|
63627
63976
|
return i >= 0 && parts[i + 1] ? parts[i + 1] : null;
|
|
63628
63977
|
}
|
|
63629
63978
|
function samePath(a, b) {
|
|
63630
|
-
const ra = (0,
|
|
63631
|
-
const rb = (0,
|
|
63979
|
+
const ra = (0, import_node_path31.resolve)(a);
|
|
63980
|
+
const rb = (0, import_node_path31.resolve)(b);
|
|
63632
63981
|
return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
|
|
63633
63982
|
}
|
|
63634
63983
|
function underDir(path, dir) {
|
|
63635
|
-
const rp = (0,
|
|
63636
|
-
const rd = (0,
|
|
63984
|
+
const rp = (0, import_node_path31.resolve)(path);
|
|
63985
|
+
const rd = (0, import_node_path31.resolve)(dir);
|
|
63637
63986
|
const [p, d] = process.platform === "win32" ? [rp.toLowerCase(), rd.toLowerCase()] : [rp, rd];
|
|
63638
|
-
return p === d || p.startsWith(d +
|
|
63987
|
+
return p === d || p.startsWith(d + import_node_path31.sep);
|
|
63639
63988
|
}
|
|
63640
63989
|
function startWatcher() {
|
|
63641
|
-
const awareDir = process.env.AWARE_HOME ?? (0,
|
|
63642
|
-
const credentialsDir = (0,
|
|
63643
|
-
if (!(0,
|
|
63990
|
+
const awareDir = process.env.AWARE_HOME ?? (0, import_node_path31.join)((0, import_node_os20.homedir)(), ".aware");
|
|
63991
|
+
const credentialsDir = (0, import_node_path31.join)(awareDir, "credentials");
|
|
63992
|
+
if (!(0, import_node_fs33.existsSync)(credentialsDir)) {
|
|
63644
63993
|
try {
|
|
63645
|
-
(0,
|
|
63994
|
+
(0, import_node_fs33.mkdirSync)(credentialsDir, { recursive: true });
|
|
63646
63995
|
} catch {
|
|
63647
63996
|
}
|
|
63648
63997
|
}
|
|
63649
|
-
if (!(0,
|
|
63998
|
+
if (!(0, import_node_fs33.existsSync)(uiDir)) {
|
|
63650
63999
|
try {
|
|
63651
|
-
(0,
|
|
64000
|
+
(0, import_node_fs33.mkdirSync)(uiDir, { recursive: true });
|
|
63652
64001
|
} catch {
|
|
63653
64002
|
}
|
|
63654
64003
|
}
|
|
63655
|
-
const targets = ["apps", "logs", "credentials"].map((d) => (0,
|
|
63656
|
-
if ((0,
|
|
64004
|
+
const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path31.join)(awareDir, d)).filter((p) => (0, import_node_fs33.existsSync)(p));
|
|
64005
|
+
if ((0, import_node_fs33.existsSync)(uiDir)) targets.push(uiDir);
|
|
63657
64006
|
if (targets.length === 0) {
|
|
63658
64007
|
return null;
|
|
63659
64008
|
}
|
|
@@ -63682,11 +64031,11 @@ function startWatcher() {
|
|
|
63682
64031
|
const isCredential = path.split(/[\\/]/).includes("credentials");
|
|
63683
64032
|
const kind = isCredential ? "credential" : path.endsWith(".jsonl") ? "trace" : path.endsWith(".lock") ? "lock" : path.endsWith(".flo") || path.endsWith(".app") ? "source" : "file";
|
|
63684
64033
|
broadcast({ type: "fs-change", kind, event, path });
|
|
63685
|
-
if (kind === "trace" && event !== "unlink" && (0,
|
|
64034
|
+
if (kind === "trace" && event !== "unlink" && (0, import_node_fs33.existsSync)(path)) {
|
|
63686
64035
|
const id = appIdFromLogPath(path);
|
|
63687
64036
|
if (!id) return;
|
|
63688
64037
|
try {
|
|
63689
|
-
broadcast({ type: "trace-file", id, runId: path.split(
|
|
64038
|
+
broadcast({ type: "trace-file", id, runId: path.split(import_node_path31.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs33.readFileSync)(path, "utf8")) });
|
|
63690
64039
|
} catch {
|
|
63691
64040
|
}
|
|
63692
64041
|
}
|
|
@@ -63695,10 +64044,10 @@ function startWatcher() {
|
|
|
63695
64044
|
}
|
|
63696
64045
|
|
|
63697
64046
|
// index.ts
|
|
63698
|
-
var __dirname4 = (0,
|
|
63699
|
-
var WEB_ROOT = [(0,
|
|
63700
|
-
(p) => (0,
|
|
63701
|
-
) ?? (0,
|
|
64047
|
+
var __dirname4 = (0, import_node_path32.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
|
|
64048
|
+
var WEB_ROOT = [(0, import_node_path32.join)(__dirname4, "web"), (0, import_node_path32.join)((0, import_node_path32.dirname)(process.execPath), "web"), (0, import_node_path32.join)(__dirname4, "..", "web")].find(
|
|
64049
|
+
(p) => (0, import_node_fs34.existsSync)(p)
|
|
64050
|
+
) ?? (0, import_node_path32.join)(__dirname4, "..", "web");
|
|
63702
64051
|
var PORT2 = Number(process.env.PORT ?? 4317);
|
|
63703
64052
|
var HOST = "127.0.0.1";
|
|
63704
64053
|
var crashHandlersInstalled = false;
|
|
@@ -63714,7 +64063,7 @@ function installCrashHandlers() {
|
|
|
63714
64063
|
${stack}
|
|
63715
64064
|
`;
|
|
63716
64065
|
try {
|
|
63717
|
-
(0,
|
|
64066
|
+
(0, import_node_fs34.appendFileSync)(logFilePath(), line);
|
|
63718
64067
|
} catch {
|
|
63719
64068
|
}
|
|
63720
64069
|
if (process.stderr.isTTY) process.stderr.write(line);
|
|
@@ -64011,9 +64360,9 @@ async function startServer() {
|
|
|
64011
64360
|
const { id, templateId, templatePath, srcPath, appDirPath: appDirPath2, fromVersion, contract, verb } = opts;
|
|
64012
64361
|
const bdir = backupDir(id, fromVersion, Date.now());
|
|
64013
64362
|
try {
|
|
64014
|
-
(0,
|
|
64015
|
-
(0,
|
|
64016
|
-
(0,
|
|
64363
|
+
(0, import_node_fs34.mkdirSync)((0, import_node_path32.dirname)(bdir), { recursive: true });
|
|
64364
|
+
(0, import_node_fs34.cpSync)(appDirPath2, bdir, { recursive: true });
|
|
64365
|
+
(0, import_node_fs34.cpSync)(templatePath, srcPath);
|
|
64017
64366
|
if (id !== templateId) stampSourceAppId(srcPath, id);
|
|
64018
64367
|
if (contract != null) {
|
|
64019
64368
|
bakeContractIntoApp(srcPath, contract);
|
|
@@ -64024,8 +64373,8 @@ async function startServer() {
|
|
|
64024
64373
|
} catch (e) {
|
|
64025
64374
|
const msg = e instanceof Error ? e.message : String(e);
|
|
64026
64375
|
try {
|
|
64027
|
-
(0,
|
|
64028
|
-
(0,
|
|
64376
|
+
(0, import_node_fs34.rmSync)(appDirPath2, { recursive: true, force: true });
|
|
64377
|
+
(0, import_node_fs34.cpSync)(bdir, appDirPath2, { recursive: true });
|
|
64029
64378
|
} catch (re) {
|
|
64030
64379
|
const rmsg = re instanceof Error ? re.message : String(re);
|
|
64031
64380
|
throw new TemplateSwapError(`${verb} failed (${msg}) AND rollback failed (${rmsg}) \u2014 restore manually from ${bdir}`, "rollback-failed", bdir);
|
|
@@ -64056,7 +64405,7 @@ async function startServer() {
|
|
|
64056
64405
|
return reply.status(409).send({ ok: false, error: `"${id}" is already at ${fromVersion}`, code: "up-to-date" });
|
|
64057
64406
|
}
|
|
64058
64407
|
const contract = readContract(id);
|
|
64059
|
-
if (contract == null && (0,
|
|
64408
|
+
if (contract == null && (0, import_node_fs34.existsSync)(contractPath(id))) {
|
|
64060
64409
|
return reply.status(409).send({ ok: false, error: `"${id}"'s saved data is unreadable \u2014 open it in the editor and re-save before updating`, code: "contract-corrupt" });
|
|
64061
64410
|
}
|
|
64062
64411
|
if (contract != null) {
|
|
@@ -64238,6 +64587,29 @@ async function startServer() {
|
|
|
64238
64587
|
throw e;
|
|
64239
64588
|
}
|
|
64240
64589
|
});
|
|
64590
|
+
app.get("/api/projects/:id/versions", async (req, reply) => {
|
|
64591
|
+
const p = getProject(req.params.id);
|
|
64592
|
+
if (!p) return reply.status(404).send({ ok: false, error: `unknown project: ${req.params.id}` });
|
|
64593
|
+
return { ok: true, versions: listVersions(req.params.id), approvedAt: p.approvedAt ?? null };
|
|
64594
|
+
});
|
|
64595
|
+
app.post("/api/projects/:id/versions/:n/rollback", async (req, reply) => {
|
|
64596
|
+
const project = getProject(req.params.id);
|
|
64597
|
+
if (!project) return reply.status(404).send({ ok: false, error: `unknown project: ${req.params.id}` });
|
|
64598
|
+
const n = Number(req.params.n);
|
|
64599
|
+
if (!Number.isInteger(n) || n < 1) return reply.status(400).send({ ok: false, error: `invalid version: ${req.params.n}` });
|
|
64600
|
+
const doc = readVersion(project.id, n);
|
|
64601
|
+
if (doc == null) return reply.status(404).send({ ok: false, error: `could not read version v${n} (missing or corrupt)` });
|
|
64602
|
+
try {
|
|
64603
|
+
writeContract(project.app, doc, project.id);
|
|
64604
|
+
} catch (e) {
|
|
64605
|
+
if (e instanceof ContractError) return reply.status(400).send({ ok: false, error: e.message });
|
|
64606
|
+
throw e;
|
|
64607
|
+
}
|
|
64608
|
+
clearApproval(project.id);
|
|
64609
|
+
const row = createVersion(project.id, doc, { author: "You", message: `Rolled back to v${n}`, gate: null, kind: "rollback" });
|
|
64610
|
+
broadcast({ type: "contract-changed", appId: project.app, project: project.id });
|
|
64611
|
+
return { ok: true, version: row };
|
|
64612
|
+
});
|
|
64241
64613
|
function projectAppMismatch(appId, project) {
|
|
64242
64614
|
const p = getProject(project);
|
|
64243
64615
|
if (!p) return `unknown project: ${project}`;
|
|
@@ -64320,7 +64692,10 @@ async function startServer() {
|
|
|
64320
64692
|
}
|
|
64321
64693
|
broadcast({ type: "compiled", id: req.params.appId, lockPath: result.lockPath });
|
|
64322
64694
|
let approvedAt;
|
|
64323
|
-
if (project)
|
|
64695
|
+
if (project) {
|
|
64696
|
+
createVersion(project, doc, { author: "You", message: "Approved the model", gate: "model", kind: "approve" });
|
|
64697
|
+
approvedAt = markApproved(project).approvedAt;
|
|
64698
|
+
}
|
|
64324
64699
|
return { ok: true, result, approvedAt };
|
|
64325
64700
|
});
|
|
64326
64701
|
app.post(
|
|
@@ -64392,10 +64767,10 @@ async function startServer() {
|
|
|
64392
64767
|
if (bad) return reply.status(404).send({ ok: false, error: bad });
|
|
64393
64768
|
const dir = projectExportsDir(project);
|
|
64394
64769
|
const exports2 = projectExportFiles(req.params.appId).map(({ kind, filename }) => {
|
|
64395
|
-
const path = (0,
|
|
64770
|
+
const path = (0, import_node_path32.join)(dir, filename);
|
|
64396
64771
|
let exportedAt = null;
|
|
64397
64772
|
try {
|
|
64398
|
-
const st = (0,
|
|
64773
|
+
const st = (0, import_node_fs34.statSync)(path);
|
|
64399
64774
|
if (st.isFile()) exportedAt = st.mtime.toISOString();
|
|
64400
64775
|
} catch {
|
|
64401
64776
|
}
|
|
@@ -64479,8 +64854,8 @@ async function startServer() {
|
|
|
64479
64854
|
}
|
|
64480
64855
|
const companionId = `${req.params.appId}-ifc`;
|
|
64481
64856
|
const filename = `${req.params.appId}.ifc`;
|
|
64482
|
-
const outPath = project ? (0,
|
|
64483
|
-
if (project) (0,
|
|
64857
|
+
const outPath = project ? (0, import_node_path32.join)(projectExportsDir(project), filename) : (0, import_node_path32.join)(appPath(companionId), filename);
|
|
64858
|
+
if (project) (0, import_node_fs34.mkdirSync)((0, import_node_path32.dirname)(outPath), { recursive: true });
|
|
64484
64859
|
let flo;
|
|
64485
64860
|
try {
|
|
64486
64861
|
flo = writeIfcApp(appPath(companionId), companionId, scene, outPath, writeOpts);
|
|
@@ -64503,8 +64878,8 @@ async function startServer() {
|
|
|
64503
64878
|
}
|
|
64504
64879
|
throw e;
|
|
64505
64880
|
}
|
|
64506
|
-
if (!(0,
|
|
64507
|
-
const content = (0,
|
|
64881
|
+
if (!(0, import_node_fs34.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
|
|
64882
|
+
const content = (0, import_node_fs34.readFileSync)(outPath, "utf8");
|
|
64508
64883
|
broadcast({ type: "apps-changed" });
|
|
64509
64884
|
return { ok: true, filename, savedTo: outPath, content, bytes: Buffer.byteLength(content), skipped, ...extrusionsSkipped ? { extrusionsSkipped } : {} };
|
|
64510
64885
|
});
|
|
@@ -64593,17 +64968,17 @@ async function startServer() {
|
|
|
64593
64968
|
return reply.status(422).send({ ok: false, error: "no priced members to export \u2014 every member is an RFI (no AISC size / weight yet)" });
|
|
64594
64969
|
}
|
|
64595
64970
|
const filename = `${appId}-bom.${format}`;
|
|
64596
|
-
const outPath = project ? (0,
|
|
64597
|
-
const dir = (0,
|
|
64971
|
+
const outPath = project ? (0, import_node_path32.join)(projectExportsDir(project), filename) : bomExportPath(appId, format);
|
|
64972
|
+
const dir = (0, import_node_path32.dirname)(outPath);
|
|
64598
64973
|
try {
|
|
64599
|
-
(0,
|
|
64974
|
+
(0, import_node_fs34.mkdirSync)(dir, { recursive: true });
|
|
64600
64975
|
if (format === "csv") {
|
|
64601
64976
|
const text = bomToCsv(bom);
|
|
64602
|
-
(0,
|
|
64977
|
+
(0, import_node_fs34.writeFileSync)(outPath, text, "utf8");
|
|
64603
64978
|
return { ok: true, filename, encoding: "utf8", content: text, bytes: Buffer.byteLength(text), savedTo: outPath };
|
|
64604
64979
|
}
|
|
64605
64980
|
const buf = await bomToXlsx(bom);
|
|
64606
|
-
(0,
|
|
64981
|
+
(0, import_node_fs34.writeFileSync)(outPath, buf);
|
|
64607
64982
|
return { ok: true, filename, encoding: "base64", content: buf.toString("base64"), bytes: buf.length, savedTo: outPath };
|
|
64608
64983
|
} catch (e) {
|
|
64609
64984
|
app.log.error({ appId, format, err: e instanceof Error ? e.message : e }, "export-bom: generation failed");
|
|
@@ -64673,7 +65048,7 @@ async function startServer() {
|
|
|
64673
65048
|
return reply.status(404).send({ ok: false, error: `"${id}" is not installed`, code: "not-installed" });
|
|
64674
65049
|
}
|
|
64675
65050
|
const contract = readContract(id);
|
|
64676
|
-
if (contract == null && (0,
|
|
65051
|
+
if (contract == null && (0, import_node_fs34.existsSync)(contractPath(id))) {
|
|
64677
65052
|
return reply.status(409).send({ ok: false, error: `"${id}"'s saved data is unreadable \u2014 open it in the editor and re-save before restoring`, code: "contract-corrupt" });
|
|
64678
65053
|
}
|
|
64679
65054
|
if (contract != null) {
|
|
@@ -64751,11 +65126,11 @@ async function startServer() {
|
|
|
64751
65126
|
if (appExists(id)) {
|
|
64752
65127
|
return reply.status(409).send({ ok: false, error: `a workflow named "${id}" is already installed \u2014 remove it first, or rename the file's app: id`, code: "exists", id });
|
|
64753
65128
|
}
|
|
64754
|
-
const stageRoot = (0,
|
|
65129
|
+
const stageRoot = (0, import_node_fs34.mkdtempSync)((0, import_node_path32.join)((0, import_node_os21.tmpdir)(), "floless-import-"));
|
|
64755
65130
|
try {
|
|
64756
|
-
const stageDir = (0,
|
|
64757
|
-
(0,
|
|
64758
|
-
(0,
|
|
65131
|
+
const stageDir = (0, import_node_path32.join)(stageRoot, id);
|
|
65132
|
+
(0, import_node_fs34.mkdirSync)(stageDir);
|
|
65133
|
+
(0, import_node_fs34.writeFileSync)((0, import_node_path32.join)(stageDir, `${id}.flo`), content);
|
|
64759
65134
|
await aware.install(stageDir);
|
|
64760
65135
|
} catch (err2) {
|
|
64761
65136
|
try {
|
|
@@ -64765,7 +65140,7 @@ async function startServer() {
|
|
|
64765
65140
|
const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
|
|
64766
65141
|
return reply.status(502).send({ ok: false, error: `import failed: ${msg}` });
|
|
64767
65142
|
} finally {
|
|
64768
|
-
(0,
|
|
65143
|
+
(0, import_node_fs34.rmSync)(stageRoot, { recursive: true, force: true });
|
|
64769
65144
|
}
|
|
64770
65145
|
broadcast({ type: "apps-changed", id });
|
|
64771
65146
|
return { ok: true, id };
|
|
@@ -64779,13 +65154,13 @@ async function startServer() {
|
|
|
64779
65154
|
}
|
|
64780
65155
|
const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
|
|
64781
65156
|
const baked = bakeFloSource(appData.source.text, inputs);
|
|
64782
|
-
const tmpRoot = (0,
|
|
64783
|
-
const backupDir2 = (0,
|
|
64784
|
-
const bakeDir = (0,
|
|
64785
|
-
(0,
|
|
64786
|
-
(0,
|
|
65157
|
+
const tmpRoot = (0, import_node_fs34.mkdtempSync)((0, import_node_path32.join)((0, import_node_os21.tmpdir)(), "floless-bake-"));
|
|
65158
|
+
const backupDir2 = (0, import_node_path32.join)(tmpRoot, `${id}-backup`);
|
|
65159
|
+
const bakeDir = (0, import_node_path32.join)(tmpRoot, id);
|
|
65160
|
+
(0, import_node_fs34.cpSync)(appDir(id), backupDir2, { recursive: true });
|
|
65161
|
+
(0, import_node_fs34.cpSync)(appDir(id), bakeDir, { recursive: true });
|
|
64787
65162
|
const floName = appData.source.path.split(/[\\/]/).pop();
|
|
64788
|
-
(0,
|
|
65163
|
+
(0, import_node_fs34.writeFileSync)((0, import_node_path32.join)(bakeDir, floName), baked);
|
|
64789
65164
|
let appInstalled2 = true;
|
|
64790
65165
|
try {
|
|
64791
65166
|
await aware.uninstall(id);
|
|
@@ -64807,17 +65182,17 @@ async function startServer() {
|
|
|
64807
65182
|
throw installErr;
|
|
64808
65183
|
}
|
|
64809
65184
|
try {
|
|
64810
|
-
await aware.compile((0,
|
|
65185
|
+
await aware.compile((0, import_node_path32.join)(appDir(id), floName));
|
|
64811
65186
|
} catch (compileErr) {
|
|
64812
65187
|
app.log.warn({ id, compileErr: String(compileErr) }, "bake: post-install recompile failed (app baked but may need a manual Compile)");
|
|
64813
65188
|
}
|
|
64814
65189
|
broadcast({ type: "baked", id });
|
|
64815
65190
|
return { ok: true, id, agent: id, inputs };
|
|
64816
65191
|
} finally {
|
|
64817
|
-
if (appInstalled2) (0,
|
|
65192
|
+
if (appInstalled2) (0, import_node_fs34.rmSync)(tmpRoot, { recursive: true, force: true });
|
|
64818
65193
|
}
|
|
64819
65194
|
});
|
|
64820
|
-
const graftAgentsDir = () => (0,
|
|
65195
|
+
const graftAgentsDir = () => (0, import_node_path32.join)((0, import_node_os21.homedir)(), ".aware", "agents");
|
|
64821
65196
|
app.post("/api/graft/match", async (req, reply) => {
|
|
64822
65197
|
const { glob } = req.body ?? {};
|
|
64823
65198
|
if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
|
|
@@ -64834,7 +65209,7 @@ async function startServer() {
|
|
|
64834
65209
|
if (!sourceKind || !sourceRef) {
|
|
64835
65210
|
return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
|
|
64836
65211
|
}
|
|
64837
|
-
const tempHome = (0,
|
|
65212
|
+
const tempHome = (0, import_node_fs34.mkdtempSync)((0, import_node_path32.join)((0, import_node_os21.tmpdir)(), "floless-graft-"));
|
|
64838
65213
|
let result;
|
|
64839
65214
|
try {
|
|
64840
65215
|
result = await aware.build({
|
|
@@ -64847,19 +65222,19 @@ async function startServer() {
|
|
|
64847
65222
|
awareHome: tempHome
|
|
64848
65223
|
});
|
|
64849
65224
|
} catch (err2) {
|
|
64850
|
-
(0,
|
|
65225
|
+
(0, import_node_fs34.rmSync)(tempHome, { recursive: true, force: true });
|
|
64851
65226
|
const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
|
|
64852
65227
|
return reply.status(422).send({ ok: false, error: msg });
|
|
64853
65228
|
}
|
|
64854
65229
|
const manifest = readStagedManifest(result.agentDir);
|
|
64855
65230
|
if (!manifest) {
|
|
64856
|
-
(0,
|
|
65231
|
+
(0, import_node_fs34.rmSync)(tempHome, { recursive: true, force: true });
|
|
64857
65232
|
return reply.status(502).send({ ok: false, error: `build produced output at ${result.agentDir} but no manifest.yaml` });
|
|
64858
65233
|
}
|
|
64859
|
-
const token = (0,
|
|
65234
|
+
const token = (0, import_node_crypto9.randomUUID)();
|
|
64860
65235
|
registerStage(token, tempHome, result.agentId);
|
|
64861
65236
|
const preview = buildPreview(manifest, sourceKind, sourceRef, token);
|
|
64862
|
-
if ((0,
|
|
65237
|
+
if ((0, import_node_fs34.existsSync)((0, import_node_path32.join)(graftAgentsDir(), result.agentId))) {
|
|
64863
65238
|
preview.warnings.unshift(`An agent named "${result.agentId}" is already installed \u2014 creating it will overwrite it.`);
|
|
64864
65239
|
}
|
|
64865
65240
|
return { ok: true, preview };
|
|
@@ -64878,7 +65253,7 @@ async function startServer() {
|
|
|
64878
65253
|
registerStage(stagedRef, stage.tempDir, stage.agentId);
|
|
64879
65254
|
return reply.status(409).send({ ok: false, error: err2.message, agentId: stage.agentId, collision: true });
|
|
64880
65255
|
}
|
|
64881
|
-
(0,
|
|
65256
|
+
(0, import_node_fs34.rmSync)(stage.tempDir, { recursive: true, force: true });
|
|
64882
65257
|
throw err2;
|
|
64883
65258
|
}
|
|
64884
65259
|
broadcast({ type: "grafted", id: stage.agentId });
|
|
@@ -65149,11 +65524,11 @@ async function startServer() {
|
|
|
65149
65524
|
app.get("/api/requests/:id/snapshot/:n", async (req, reply) => {
|
|
65150
65525
|
const n = Number.parseInt(req.params.n, 10);
|
|
65151
65526
|
const p = Number.isInteger(n) ? snapshotPathFor(req.params.id, n) : null;
|
|
65152
|
-
if (!p || !(0,
|
|
65527
|
+
if (!p || !(0, import_node_fs34.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
|
|
65153
65528
|
const ext = p.split(".").pop().toLowerCase();
|
|
65154
65529
|
reply.header("Content-Type", ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "pdf" ? "application/pdf" : "image/jpeg");
|
|
65155
65530
|
reply.header("Cache-Control", "no-store");
|
|
65156
|
-
return (0,
|
|
65531
|
+
return (0, import_node_fs34.readFileSync)(p);
|
|
65157
65532
|
});
|
|
65158
65533
|
app.post(
|
|
65159
65534
|
"/api/tweak",
|
|
@@ -65235,6 +65610,63 @@ async function startServer() {
|
|
|
65235
65610
|
}
|
|
65236
65611
|
}
|
|
65237
65612
|
);
|
|
65613
|
+
const CONN_APPID = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
65614
|
+
app.post(
|
|
65615
|
+
"/api/import-connection/list",
|
|
65616
|
+
{ bodyLimit: 96 * 1024 * 1024 },
|
|
65617
|
+
// a base64 IFC inflates ~4/3; 96 MB covers the 64 MB stash cap
|
|
65618
|
+
async (req, reply) => {
|
|
65619
|
+
const { appId, dataUrl } = req.body ?? {};
|
|
65620
|
+
if (!appId || !CONN_APPID.test(appId)) return reply.status(400).send({ ok: false, error: "a valid appId is required" });
|
|
65621
|
+
if (!dataUrl) return reply.status(400).send({ ok: false, error: "an IFC file is required" });
|
|
65622
|
+
let stored;
|
|
65623
|
+
try {
|
|
65624
|
+
stored = storeIfcInput(appId, dataUrl);
|
|
65625
|
+
} catch (e) {
|
|
65626
|
+
if (e instanceof VisualInputError) return reply.status(400).send({ ok: false, error: e.message });
|
|
65627
|
+
throw e;
|
|
65628
|
+
}
|
|
65629
|
+
let done = false;
|
|
65630
|
+
req.raw.on("close", () => {
|
|
65631
|
+
if (!done && isRunActive()) cancelActiveRun();
|
|
65632
|
+
});
|
|
65633
|
+
try {
|
|
65634
|
+
const connections = await listConnections(`${appId}-connimport`, stored.path);
|
|
65635
|
+
return { ok: true, sha: stored.sha256, connections };
|
|
65636
|
+
} catch (e) {
|
|
65637
|
+
if (e instanceof ConnectionImportError) return reply.send({ ok: false, error: e.message });
|
|
65638
|
+
app.log.error({ appId, err: e instanceof Error ? e.message : e }, "import-connection list failed");
|
|
65639
|
+
return reply.status(500).send({ ok: false, error: "could not read the IFC file" });
|
|
65640
|
+
} finally {
|
|
65641
|
+
done = true;
|
|
65642
|
+
}
|
|
65643
|
+
}
|
|
65644
|
+
);
|
|
65645
|
+
app.post(
|
|
65646
|
+
"/api/import-connection/extract",
|
|
65647
|
+
async (req, reply) => {
|
|
65648
|
+
const { appId, sha, id } = req.body ?? {};
|
|
65649
|
+
if (!appId || !CONN_APPID.test(appId)) return reply.status(400).send({ ok: false, error: "a valid appId is required" });
|
|
65650
|
+
if (!sha || !id) return reply.status(400).send({ ok: false, error: "sha and connection id are required" });
|
|
65651
|
+
const path = ifcInputPath(appId, sha);
|
|
65652
|
+
if (!path) return reply.status(404).send({ ok: false, error: "the uploaded IFC is no longer available \u2014 drop the file again" });
|
|
65653
|
+
let done = false;
|
|
65654
|
+
req.raw.on("close", () => {
|
|
65655
|
+
if (!done && isRunActive()) cancelActiveRun();
|
|
65656
|
+
});
|
|
65657
|
+
try {
|
|
65658
|
+
const connection = await extractConnection(`${appId}-connimport`, path, id);
|
|
65659
|
+
if (!connection.geometry.length) return reply.send({ ok: false, error: "that connection has no importable geometry" });
|
|
65660
|
+
return { ok: true, connection };
|
|
65661
|
+
} catch (e) {
|
|
65662
|
+
if (e instanceof ConnectionImportError) return reply.send({ ok: false, error: e.message });
|
|
65663
|
+
app.log.error({ appId, id, err: e instanceof Error ? e.message : e }, "import-connection extract failed");
|
|
65664
|
+
return reply.status(500).send({ ok: false, error: "could not read that connection" });
|
|
65665
|
+
} finally {
|
|
65666
|
+
done = true;
|
|
65667
|
+
}
|
|
65668
|
+
}
|
|
65669
|
+
);
|
|
65238
65670
|
app.post("/api/use-template", async (req, reply) => {
|
|
65239
65671
|
const { appId, templateId } = req.body ?? {};
|
|
65240
65672
|
if (!appId || !templateId) return reply.status(400).send({ ok: false, error: "appId and templateId required" });
|
|
@@ -65322,7 +65754,7 @@ async function startServer() {
|
|
|
65322
65754
|
warn(`last-run-status:${ref} \u2014 trace exists but couldn't be parsed (corrupt/truncated)`);
|
|
65323
65755
|
let finishedAt2 = null;
|
|
65324
65756
|
try {
|
|
65325
|
-
finishedAt2 = (0,
|
|
65757
|
+
finishedAt2 = (0, import_node_fs34.statSync)(latest.path).mtime.toISOString();
|
|
65326
65758
|
} catch {
|
|
65327
65759
|
finishedAt2 = null;
|
|
65328
65760
|
}
|
|
@@ -65332,7 +65764,7 @@ async function startServer() {
|
|
|
65332
65764
|
let finishedAt = typeof runEnd?.ts === "string" ? runEnd.ts : null;
|
|
65333
65765
|
if (!finishedAt) {
|
|
65334
65766
|
try {
|
|
65335
|
-
finishedAt = (0,
|
|
65767
|
+
finishedAt = (0, import_node_fs34.statSync)(latest.path).mtime.toISOString();
|
|
65336
65768
|
} catch {
|
|
65337
65769
|
finishedAt = null;
|
|
65338
65770
|
}
|