@floless/app 0.74.0 → 0.76.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 +746 -270
- package/dist/schemas/steel.takeoff.v1.schema.json +26 -7
- package/dist/web/app.css +21 -2
- package/dist/web/app.js +13 -1
- package/dist/web/aware.js +16 -3
- package/dist/web/index.html +9 -0
- package/dist/web/steel-3d-view.js +17 -1
- package/dist/web/steel-editor.html +247 -14
- package/dist/web/workspaces.js +196 -9
- 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: join34 } = 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"] || join34(__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: existsSync29 } = require("node:fs");
|
|
6010
6010
|
var getCallers = require_caller();
|
|
6011
|
-
var { join:
|
|
6011
|
+
var { join: join34, 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) && !existsSync29(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"] || join34(__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"] || join34(__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 join34(__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 join34 = ",";
|
|
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
|
+
join34 = `,
|
|
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 += join34;
|
|
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 += `${join34}"... ${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
|
+
join34 = `,
|
|
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 = join34;
|
|
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 = join34;
|
|
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 join34 = ",";
|
|
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
|
+
join34 = `,
|
|
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 += join34;
|
|
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 += `${join34}"... ${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
|
+
join34 = `,
|
|
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 = join34;
|
|
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 join35 = `,
|
|
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 += join35;
|
|
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 += `${join35}"... ${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 join34 = `,
|
|
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, join34, maximumBreadth);
|
|
7438
7438
|
keys = keys.slice(value.length);
|
|
7439
7439
|
maximumPropertiesToStringify -= value.length;
|
|
7440
|
-
separator =
|
|
7440
|
+
separator = join34;
|
|
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 = join34;
|
|
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 = join34;
|
|
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 join34 = 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(join34(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 = join34(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_path33 = require("node:path");
|
|
50831
50831
|
var import_node_os21 = require("node:os");
|
|
50832
|
-
var
|
|
50832
|
+
var import_node_fs35 = 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.76.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.76.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_crypto10 = require("node:crypto");
|
|
53401
53472
|
|
|
53402
53473
|
// graft.ts
|
|
53403
53474
|
var TEKLA_MARKER = "Recipe: Tekla model plug-in";
|
|
@@ -53694,6 +53765,29 @@ function deleteRequest(id) {
|
|
|
53694
53765
|
(0, import_node_fs16.rmSync)((0, import_node_path14.join)(REQUESTS_DIR, file));
|
|
53695
53766
|
return true;
|
|
53696
53767
|
}
|
|
53768
|
+
function getRequest(id) {
|
|
53769
|
+
if (!(0, import_node_fs16.existsSync)(REQUESTS_DIR)) return null;
|
|
53770
|
+
const file = (0, import_node_fs16.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
|
|
53771
|
+
if (!file) return null;
|
|
53772
|
+
try {
|
|
53773
|
+
return JSON.parse((0, import_node_fs16.readFileSync)((0, import_node_path14.join)(REQUESTS_DIR, file), "utf8"));
|
|
53774
|
+
} catch {
|
|
53775
|
+
return null;
|
|
53776
|
+
}
|
|
53777
|
+
}
|
|
53778
|
+
function patchRequest(id, patch2) {
|
|
53779
|
+
if (!(0, import_node_fs16.existsSync)(REQUESTS_DIR)) return null;
|
|
53780
|
+
const file = (0, import_node_fs16.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
|
|
53781
|
+
if (!file) return null;
|
|
53782
|
+
try {
|
|
53783
|
+
const cur = JSON.parse((0, import_node_fs16.readFileSync)((0, import_node_path14.join)(REQUESTS_DIR, file), "utf8"));
|
|
53784
|
+
const next = { ...cur, ...patch2, id: cur.id, createdAt: cur.createdAt };
|
|
53785
|
+
(0, import_node_fs16.writeFileSync)((0, import_node_path14.join)(REQUESTS_DIR, file), JSON.stringify(next, null, 2));
|
|
53786
|
+
return next;
|
|
53787
|
+
} catch {
|
|
53788
|
+
return null;
|
|
53789
|
+
}
|
|
53790
|
+
}
|
|
53697
53791
|
function clearRequests() {
|
|
53698
53792
|
if (!(0, import_node_fs16.existsSync)(REQUESTS_DIR)) return 0;
|
|
53699
53793
|
const allFiles = (0, import_node_fs16.readdirSync)(REQUESTS_DIR);
|
|
@@ -53746,14 +53840,190 @@ function decodeSnapshots(inputs) {
|
|
|
53746
53840
|
});
|
|
53747
53841
|
}
|
|
53748
53842
|
|
|
53843
|
+
// connection-import.ts
|
|
53844
|
+
var import_node_fs17 = require("node:fs");
|
|
53845
|
+
var import_node_path15 = require("node:path");
|
|
53846
|
+
var AGENT = "connection-reader";
|
|
53847
|
+
var MAX_PARTS = 5e3;
|
|
53848
|
+
var MAX_VERTICES = 3e6;
|
|
53849
|
+
var readerChain = Promise.resolve();
|
|
53850
|
+
var ConnectionImportError = class extends Error {
|
|
53851
|
+
};
|
|
53852
|
+
async function ensureConnectionReader() {
|
|
53853
|
+
try {
|
|
53854
|
+
await aware.ensureAgentInstalled(AGENT);
|
|
53855
|
+
await aware.ensureConnectionReaderBridge();
|
|
53856
|
+
} catch (e) {
|
|
53857
|
+
throw new ConnectionImportError(`could not set up the connection reader \u2014 check your network and try again${e instanceof Error && e.message ? ` (${e.message})` : ""}`);
|
|
53858
|
+
}
|
|
53859
|
+
}
|
|
53860
|
+
function writeReaderApp(companionId, command, ifcPath, id) {
|
|
53861
|
+
const dir = appPath(companionId);
|
|
53862
|
+
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
53863
|
+
const flo = (0, import_node_path15.join)(dir, `${companionId}.flo`);
|
|
53864
|
+
const lines = [
|
|
53865
|
+
`app: ${companionId}`,
|
|
53866
|
+
"version: 0.1.0",
|
|
53867
|
+
`display-name: Connection reader (${command})`,
|
|
53868
|
+
`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."}`,
|
|
53869
|
+
"exposes-as-agent: false",
|
|
53870
|
+
"requires:",
|
|
53871
|
+
` - ${AGENT}@0.1.x`,
|
|
53872
|
+
"layout: linear",
|
|
53873
|
+
"nodes:",
|
|
53874
|
+
` - id: ${command}`,
|
|
53875
|
+
` agent: ${AGENT}`,
|
|
53876
|
+
` command: ${command}`,
|
|
53877
|
+
" config:",
|
|
53878
|
+
` ifc-path: ${JSON.stringify(ifcPath)}`
|
|
53879
|
+
];
|
|
53880
|
+
if (command === "extract") lines.push(` id: ${JSON.stringify(id ?? "")}`);
|
|
53881
|
+
lines.push("");
|
|
53882
|
+
(0, import_node_fs17.writeFileSync)(flo, lines.join("\n"));
|
|
53883
|
+
return flo;
|
|
53884
|
+
}
|
|
53885
|
+
function nodeOutput(traceText, node) {
|
|
53886
|
+
const events = traceText ? parseTrace(traceText) : [];
|
|
53887
|
+
const ev = [...events].reverse().find((e) => e.kind === "node-output" && e.node === node);
|
|
53888
|
+
const data = ev ? ev.data : null;
|
|
53889
|
+
return data && typeof data === "object" ? data : null;
|
|
53890
|
+
}
|
|
53891
|
+
async function runReader(companionId, command, ifcPath, id) {
|
|
53892
|
+
const prev = readerChain;
|
|
53893
|
+
let release;
|
|
53894
|
+
readerChain = new Promise((r) => release = r);
|
|
53895
|
+
await prev.catch(() => {
|
|
53896
|
+
});
|
|
53897
|
+
try {
|
|
53898
|
+
const flo = writeReaderApp(companionId, command, ifcPath, id);
|
|
53899
|
+
try {
|
|
53900
|
+
await aware.compile(flo);
|
|
53901
|
+
} catch (e) {
|
|
53902
|
+
throw new ConnectionImportError(`could not compile the connection reader: ${e instanceof Error ? e.message : "compile error"}`);
|
|
53903
|
+
}
|
|
53904
|
+
let traceText;
|
|
53905
|
+
try {
|
|
53906
|
+
({ traceText } = await aware.run(companionId, {}));
|
|
53907
|
+
} catch (e) {
|
|
53908
|
+
const reason = e instanceof AwareError ? String(e.detail?.stderr ?? "").trim() : "";
|
|
53909
|
+
throw new ConnectionImportError(reason || (e instanceof Error ? e.message : "the connection reader failed"));
|
|
53910
|
+
}
|
|
53911
|
+
const out = nodeOutput(traceText, command);
|
|
53912
|
+
if (!out) throw new ConnectionImportError("the connection reader returned no result");
|
|
53913
|
+
return out;
|
|
53914
|
+
} finally {
|
|
53915
|
+
release();
|
|
53916
|
+
}
|
|
53917
|
+
}
|
|
53918
|
+
async function listConnections(companionId, ifcPath) {
|
|
53919
|
+
await ensureConnectionReader();
|
|
53920
|
+
const out = await runReader(companionId, "list", ifcPath);
|
|
53921
|
+
if (!Array.isArray(out.connections)) {
|
|
53922
|
+
throw new ConnectionImportError(typeof out.message === "string" ? out.message : "no connections found in that IFC file");
|
|
53923
|
+
}
|
|
53924
|
+
return out.connections.filter((c) => !!c && typeof c === "object");
|
|
53925
|
+
}
|
|
53926
|
+
function bboxCenter(parts) {
|
|
53927
|
+
let mnx = Infinity, mny = Infinity, mnz = Infinity, mxx = -Infinity, mxy = -Infinity, mxz = -Infinity;
|
|
53928
|
+
for (const p of parts) {
|
|
53929
|
+
for (let i = 0; i + 2 < p.positions.length; i += 3) {
|
|
53930
|
+
const x = p.positions[i], y = p.positions[i + 1], z = p.positions[i + 2];
|
|
53931
|
+
if (x < mnx) mnx = x;
|
|
53932
|
+
if (x > mxx) mxx = x;
|
|
53933
|
+
if (y < mny) mny = y;
|
|
53934
|
+
if (y > mxy) mxy = y;
|
|
53935
|
+
if (z < mnz) mnz = z;
|
|
53936
|
+
if (z > mxz) mxz = z;
|
|
53937
|
+
}
|
|
53938
|
+
}
|
|
53939
|
+
if (!isFinite(mnx)) return [0, 0, 0];
|
|
53940
|
+
return [(mnx + mxx) / 2, (mny + mxy) / 2, (mnz + mxz) / 2];
|
|
53941
|
+
}
|
|
53942
|
+
function shiftPositions(positions, [dx, dy, dz]) {
|
|
53943
|
+
const out = new Array(positions.length);
|
|
53944
|
+
for (let i = 0; i + 2 < positions.length; i += 3) {
|
|
53945
|
+
out[i] = positions[i] - dx;
|
|
53946
|
+
out[i + 1] = positions[i + 1] - dy;
|
|
53947
|
+
out[i + 2] = positions[i + 2] - dz;
|
|
53948
|
+
}
|
|
53949
|
+
return out;
|
|
53950
|
+
}
|
|
53951
|
+
function validPart(p) {
|
|
53952
|
+
const q = p;
|
|
53953
|
+
return !!q && Array.isArray(q.positions) && Array.isArray(q.indices) && q.positions.length >= 9 && q.indices.length >= 3 && q.positions.length % 3 === 0;
|
|
53954
|
+
}
|
|
53955
|
+
function toCustomConnection(raw, fallbackId) {
|
|
53956
|
+
const conn = raw.connection;
|
|
53957
|
+
if (!conn || typeof conn !== "object") {
|
|
53958
|
+
throw new ConnectionImportError(typeof raw.message === "string" ? raw.message : "could not read that connection");
|
|
53959
|
+
}
|
|
53960
|
+
const c = conn;
|
|
53961
|
+
const valid = (Array.isArray(c.parts) ? c.parts : []).filter(validPart);
|
|
53962
|
+
if (valid.length > MAX_PARTS) throw new ConnectionImportError(`that connection has too many parts (${valid.length}) to import`);
|
|
53963
|
+
let totalVerts = 0;
|
|
53964
|
+
for (const p of valid) totalVerts += p.positions.length / 3;
|
|
53965
|
+
if (totalVerts > MAX_VERTICES) throw new ConnectionImportError(`that connection is too large to import (${Math.round(totalVerts / 1e3)}k vertices)`);
|
|
53966
|
+
const anchor = bboxCenter(valid);
|
|
53967
|
+
const geometry = valid.map((p) => ({
|
|
53968
|
+
...typeof p.id === "string" ? { id: p.id } : {},
|
|
53969
|
+
...typeof p.role === "string" ? { role: p.role } : {},
|
|
53970
|
+
positions: shiftPositions(p.positions, anchor),
|
|
53971
|
+
indices: p.indices.slice()
|
|
53972
|
+
}));
|
|
53973
|
+
const recipe = sanitizeRecipe(c.recipe);
|
|
53974
|
+
return {
|
|
53975
|
+
id: typeof c.id === "string" ? c.id : fallbackId,
|
|
53976
|
+
name: typeof c.name === "string" ? c.name : "Imported connection",
|
|
53977
|
+
type: typeof c.type === "string" ? c.type : null,
|
|
53978
|
+
members: Array.isArray(c.members) ? c.members.filter((m) => typeof m === "string") : [],
|
|
53979
|
+
geometry,
|
|
53980
|
+
...recipe ? { recipe } : {}
|
|
53981
|
+
};
|
|
53982
|
+
}
|
|
53983
|
+
var BASE_PLATE_PARAMS = {
|
|
53984
|
+
thickness: [1, 500],
|
|
53985
|
+
plateWidth: [1, 5e3],
|
|
53986
|
+
plateDepth: [1, 5e3],
|
|
53987
|
+
boltDia: [1, 200],
|
|
53988
|
+
boltCols: [1, 20],
|
|
53989
|
+
boltRows: [1, 20],
|
|
53990
|
+
edgeDist: [0, 5e3],
|
|
53991
|
+
weldLeg: [0, 200]
|
|
53992
|
+
};
|
|
53993
|
+
function sanitizeRecipe(raw) {
|
|
53994
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
53995
|
+
const r = raw;
|
|
53996
|
+
if (typeof r.kind !== "string" || !r.kind || !r.params || typeof r.params !== "object") return void 0;
|
|
53997
|
+
const num2 = {};
|
|
53998
|
+
for (const [k, v] of Object.entries(r.params)) {
|
|
53999
|
+
if (typeof v === "number" && isFinite(v)) num2[k] = v;
|
|
54000
|
+
}
|
|
54001
|
+
if (r.kind === "base-plate") {
|
|
54002
|
+
const params = {};
|
|
54003
|
+
for (const [k, [lo, hi]] of Object.entries(BASE_PLATE_PARAMS)) {
|
|
54004
|
+
if (k in num2) {
|
|
54005
|
+
if (!(num2[k] >= lo && num2[k] <= hi)) return void 0;
|
|
54006
|
+
params[k] = num2[k];
|
|
54007
|
+
}
|
|
54008
|
+
}
|
|
54009
|
+
return Object.keys(params).length ? { kind: r.kind, params } : void 0;
|
|
54010
|
+
}
|
|
54011
|
+
return Object.keys(num2).length ? { kind: r.kind, params: num2 } : void 0;
|
|
54012
|
+
}
|
|
54013
|
+
async function extractConnection(companionId, ifcPath, id) {
|
|
54014
|
+
await ensureConnectionReader();
|
|
54015
|
+
const out = await runReader(companionId, "extract", ifcPath, id);
|
|
54016
|
+
return toCustomConnection(out, id);
|
|
54017
|
+
}
|
|
54018
|
+
|
|
53749
54019
|
// contract-store.ts
|
|
53750
|
-
var
|
|
53751
|
-
var
|
|
54020
|
+
var import_node_fs19 = require("node:fs");
|
|
54021
|
+
var import_node_path17 = require("node:path");
|
|
53752
54022
|
var import_node_os12 = require("node:os");
|
|
53753
54023
|
|
|
53754
54024
|
// contract-schema.ts
|
|
53755
|
-
var
|
|
53756
|
-
var
|
|
54025
|
+
var import_node_fs18 = require("node:fs");
|
|
54026
|
+
var import_node_path16 = require("node:path");
|
|
53757
54027
|
var import_node_url2 = require("node:url");
|
|
53758
54028
|
function validate(doc, schema) {
|
|
53759
54029
|
const errors = [];
|
|
@@ -53855,16 +54125,16 @@ var _cache = /* @__PURE__ */ new Map();
|
|
|
53855
54125
|
function loadContractSchema(file) {
|
|
53856
54126
|
const hit = _cache.get(file);
|
|
53857
54127
|
if (hit) return hit;
|
|
53858
|
-
const here2 = (0,
|
|
54128
|
+
const here2 = (0, import_node_path16.dirname)((0, import_node_url2.fileURLToPath)(__import_meta_url));
|
|
53859
54129
|
const candidates = [
|
|
53860
|
-
(0,
|
|
54130
|
+
(0, import_node_path16.join)(here2, "..", "schemas", file),
|
|
53861
54131
|
// dev: server/ next to schemas/
|
|
53862
|
-
(0,
|
|
54132
|
+
(0, import_node_path16.join)(here2, "schemas", file)
|
|
53863
54133
|
// bundled: dist/ holds ./schemas
|
|
53864
54134
|
];
|
|
53865
54135
|
for (const p of candidates) {
|
|
53866
54136
|
try {
|
|
53867
|
-
const parsed = JSON.parse((0,
|
|
54137
|
+
const parsed = JSON.parse((0, import_node_fs18.readFileSync)(p, "utf8"));
|
|
53868
54138
|
_cache.set(file, parsed);
|
|
53869
54139
|
return parsed;
|
|
53870
54140
|
} catch (err2) {
|
|
@@ -53894,8 +54164,8 @@ function validateContract(doc) {
|
|
|
53894
54164
|
// contract-store.ts
|
|
53895
54165
|
var ContractError = class extends Error {
|
|
53896
54166
|
};
|
|
53897
|
-
var ROOT3 = process.env.FLOLESS_HOME ?? (0,
|
|
53898
|
-
var DIR = (0,
|
|
54167
|
+
var ROOT3 = process.env.FLOLESS_HOME ?? (0, import_node_path17.join)((0, import_node_os12.homedir)(), ".floless");
|
|
54168
|
+
var DIR = (0, import_node_path17.join)(ROOT3, "contracts");
|
|
53899
54169
|
function safeId(appId) {
|
|
53900
54170
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId)) throw new ContractError(`invalid appId: ${appId}`);
|
|
53901
54171
|
return appId;
|
|
@@ -53905,14 +54175,14 @@ function safeProjectSeg(projectId) {
|
|
|
53905
54175
|
return projectId;
|
|
53906
54176
|
}
|
|
53907
54177
|
function contractPath(appId, projectId) {
|
|
53908
|
-
if (projectId) return (0,
|
|
53909
|
-
return (0,
|
|
54178
|
+
if (projectId) return (0, import_node_path17.join)(ROOT3, "projects", safeProjectSeg(projectId), "contract.json");
|
|
54179
|
+
return (0, import_node_path17.join)(DIR, `${safeId(appId)}.json`);
|
|
53910
54180
|
}
|
|
53911
54181
|
function readContract(appId, projectId) {
|
|
53912
54182
|
const p = contractPath(appId, projectId);
|
|
53913
|
-
if (!(0,
|
|
54183
|
+
if (!(0, import_node_fs19.existsSync)(p)) return null;
|
|
53914
54184
|
try {
|
|
53915
|
-
return JSON.parse((0,
|
|
54185
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(p, "utf8"));
|
|
53916
54186
|
} catch (e) {
|
|
53917
54187
|
console.warn(`readContract: ignoring unreadable contract at ${p}: ${e instanceof Error ? e.message : e}`);
|
|
53918
54188
|
return null;
|
|
@@ -53926,11 +54196,11 @@ function writeContract(appId, doc, projectId) {
|
|
|
53926
54196
|
throw new ContractError(`contract failed schema validation \u2014 ${first}`);
|
|
53927
54197
|
}
|
|
53928
54198
|
if (projectId) {
|
|
53929
|
-
if (!(0,
|
|
53930
|
-
} else if (!(0,
|
|
53931
|
-
(0,
|
|
54199
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path17.dirname)(p))) throw new ContractError(`unknown project: ${projectId}`);
|
|
54200
|
+
} else if (!(0, import_node_fs19.existsSync)(DIR)) {
|
|
54201
|
+
(0, import_node_fs19.mkdirSync)(DIR, { recursive: true });
|
|
53932
54202
|
}
|
|
53933
|
-
(0,
|
|
54203
|
+
(0, import_node_fs19.writeFileSync)(p, JSON.stringify(doc));
|
|
53934
54204
|
}
|
|
53935
54205
|
|
|
53936
54206
|
// contract-resolve.ts
|
|
@@ -53953,15 +54223,15 @@ function readContractForApp(appId, readAppFn = readApp) {
|
|
|
53953
54223
|
}
|
|
53954
54224
|
|
|
53955
54225
|
// projects-store.ts
|
|
53956
|
-
var
|
|
53957
|
-
var
|
|
54226
|
+
var import_node_fs20 = require("node:fs");
|
|
54227
|
+
var import_node_path18 = require("node:path");
|
|
53958
54228
|
var import_node_os13 = require("node:os");
|
|
53959
54229
|
var import_node_crypto6 = require("node:crypto");
|
|
53960
54230
|
var ProjectError = class extends Error {
|
|
53961
54231
|
};
|
|
53962
|
-
var ROOT4 = process.env.FLOLESS_HOME ?? (0,
|
|
53963
|
-
var DIR2 = (0,
|
|
53964
|
-
var ARCHIVE = (0,
|
|
54232
|
+
var ROOT4 = process.env.FLOLESS_HOME ?? (0, import_node_path18.join)((0, import_node_os13.homedir)(), ".floless");
|
|
54233
|
+
var DIR2 = (0, import_node_path18.join)(ROOT4, "projects");
|
|
54234
|
+
var ARCHIVE = (0, import_node_path18.join)(DIR2, ".archive");
|
|
53965
54235
|
function safeProjectId(id) {
|
|
53966
54236
|
if (typeof id !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(id)) {
|
|
53967
54237
|
throw new ProjectError(`invalid project id: ${String(id)}`);
|
|
@@ -53973,28 +54243,28 @@ function slugify(name) {
|
|
|
53973
54243
|
return s || "project";
|
|
53974
54244
|
}
|
|
53975
54245
|
function projectDir(id) {
|
|
53976
|
-
return (0,
|
|
54246
|
+
return (0, import_node_path18.join)(DIR2, safeProjectId(id));
|
|
53977
54247
|
}
|
|
53978
54248
|
function projectExportsDir(id) {
|
|
53979
|
-
return (0,
|
|
54249
|
+
return (0, import_node_path18.join)(projectDir(id), "exports");
|
|
53980
54250
|
}
|
|
53981
|
-
var metaPath = (id) => (0,
|
|
54251
|
+
var metaPath = (id) => (0, import_node_path18.join)(projectDir(id), "project.json");
|
|
53982
54252
|
function readMeta(id) {
|
|
53983
54253
|
const p = metaPath(id);
|
|
53984
|
-
if (!(0,
|
|
54254
|
+
if (!(0, import_node_fs20.existsSync)(p)) return null;
|
|
53985
54255
|
try {
|
|
53986
|
-
const meta = JSON.parse((0,
|
|
54256
|
+
const meta = JSON.parse((0, import_node_fs20.readFileSync)(p, "utf8"));
|
|
53987
54257
|
return meta && meta.id === id ? meta : null;
|
|
53988
54258
|
} catch (e) {
|
|
53989
54259
|
console.warn(`projects-store: ignoring unreadable project.json at ${p}: ${e instanceof Error ? e.message : e}`);
|
|
53990
54260
|
return null;
|
|
53991
54261
|
}
|
|
53992
54262
|
}
|
|
53993
|
-
var writeMeta = (meta) => (0,
|
|
54263
|
+
var writeMeta = (meta) => (0, import_node_fs20.writeFileSync)(metaPath(meta.id), JSON.stringify(meta, null, 2));
|
|
53994
54264
|
function listProjects() {
|
|
53995
|
-
if (!(0,
|
|
54265
|
+
if (!(0, import_node_fs20.existsSync)(DIR2)) return [];
|
|
53996
54266
|
const out = [];
|
|
53997
|
-
for (const entry2 of (0,
|
|
54267
|
+
for (const entry2 of (0, import_node_fs20.readdirSync)(DIR2, { withFileTypes: true })) {
|
|
53998
54268
|
if (!entry2.isDirectory() || entry2.name.startsWith(".")) continue;
|
|
53999
54269
|
const meta = readMeta(entry2.name);
|
|
54000
54270
|
if (meta) out.push(meta);
|
|
@@ -54010,8 +54280,8 @@ function createProject(input) {
|
|
|
54010
54280
|
if (!name) throw new ProjectError("project name required");
|
|
54011
54281
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(app)) throw new ProjectError(`invalid app id: ${app || "(empty)"}`);
|
|
54012
54282
|
let id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
|
|
54013
|
-
while ((0,
|
|
54014
|
-
(0,
|
|
54283
|
+
while ((0, import_node_fs20.existsSync)(projectDir(id))) id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
|
|
54284
|
+
(0, import_node_fs20.mkdirSync)(projectDir(id), { recursive: true });
|
|
54015
54285
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
54016
54286
|
const meta = { id, name, app, createdAt: now, updatedAt: now };
|
|
54017
54287
|
writeMeta(meta);
|
|
@@ -54046,7 +54316,7 @@ function duplicateProject(id, name) {
|
|
|
54046
54316
|
name: typeof name === "string" && name.trim() ? name.trim() : `${src.name} (copy)`,
|
|
54047
54317
|
app: src.app
|
|
54048
54318
|
});
|
|
54049
|
-
(0,
|
|
54319
|
+
(0, import_node_fs20.cpSync)(projectDir(src.id), projectDir(copy.id), {
|
|
54050
54320
|
recursive: true,
|
|
54051
54321
|
filter: (p) => !p.endsWith("project.json")
|
|
54052
54322
|
});
|
|
@@ -54054,36 +54324,42 @@ function duplicateProject(id, name) {
|
|
|
54054
54324
|
}
|
|
54055
54325
|
function archiveProject(id) {
|
|
54056
54326
|
const dir = projectDir(id);
|
|
54057
|
-
if (!(0,
|
|
54058
|
-
(0,
|
|
54059
|
-
const dest = (0,
|
|
54060
|
-
if ((0,
|
|
54061
|
-
(0,
|
|
54327
|
+
if (!(0, import_node_fs20.existsSync)(dir)) throw new ProjectError(`unknown project: ${id}`);
|
|
54328
|
+
(0, import_node_fs20.mkdirSync)(ARCHIVE, { recursive: true });
|
|
54329
|
+
const dest = (0, import_node_path18.join)(ARCHIVE, id);
|
|
54330
|
+
if ((0, import_node_fs20.existsSync)(dest)) throw new ProjectError(`already archived: ${id}`);
|
|
54331
|
+
(0, import_node_fs20.renameSync)(dir, dest);
|
|
54062
54332
|
}
|
|
54063
54333
|
|
|
54064
54334
|
// project-versions-store.ts
|
|
54065
54335
|
var import_node_crypto7 = require("node:crypto");
|
|
54066
|
-
var
|
|
54067
|
-
var
|
|
54336
|
+
var import_node_fs21 = require("node:fs");
|
|
54337
|
+
var import_node_path19 = require("node:path");
|
|
54068
54338
|
var BLOB_MIN = 8192;
|
|
54069
54339
|
var BLOB_KEY = "__blobRef__";
|
|
54070
54340
|
var HASH_RE = /^[0-9a-f]{64}$/;
|
|
54071
|
-
var versionsDir = (id) => (0,
|
|
54072
|
-
var objectsDir = (id) => (0,
|
|
54073
|
-
var logPath = (id) => (0,
|
|
54341
|
+
var versionsDir = (id) => (0, import_node_path19.join)(projectDir(id), "versions");
|
|
54342
|
+
var objectsDir = (id) => (0, import_node_path19.join)(projectDir(id), "objects");
|
|
54343
|
+
var logPath = (id) => (0, import_node_path19.join)(versionsDir(id), "log.json");
|
|
54074
54344
|
function writeAtomic(path, text) {
|
|
54075
54345
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
54076
|
-
(0,
|
|
54077
|
-
(0,
|
|
54346
|
+
(0, import_node_fs21.writeFileSync)(tmp, text);
|
|
54347
|
+
(0, import_node_fs21.renameSync)(tmp, path);
|
|
54078
54348
|
}
|
|
54079
54349
|
function isVersionMeta(v) {
|
|
54080
54350
|
if (!v || typeof v !== "object") return false;
|
|
54081
54351
|
const r = v;
|
|
54082
|
-
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");
|
|
54352
|
+
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" || r.kind === "revision-read") && isValidSource(r.source);
|
|
54353
|
+
}
|
|
54354
|
+
function isValidSource(s) {
|
|
54355
|
+
if (s === void 0) return true;
|
|
54356
|
+
if (!s || typeof s !== "object") return false;
|
|
54357
|
+
const files2 = s.files;
|
|
54358
|
+
return Array.isArray(files2) && files2.every((f) => !!f && typeof f === "object" && typeof f.sha256 === "string");
|
|
54083
54359
|
}
|
|
54084
54360
|
function loadLog(id) {
|
|
54085
54361
|
try {
|
|
54086
|
-
const parsed = JSON.parse((0,
|
|
54362
|
+
const parsed = JSON.parse((0, import_node_fs21.readFileSync)(logPath(id), "utf8"));
|
|
54087
54363
|
const raw = parsed && typeof parsed === "object" && Array.isArray(parsed.versions) ? parsed.versions : [];
|
|
54088
54364
|
return { versions: raw.filter(isVersionMeta) };
|
|
54089
54365
|
} catch {
|
|
@@ -54114,7 +54390,7 @@ function rehydrate(node, id) {
|
|
|
54114
54390
|
const keys = Object.keys(obj);
|
|
54115
54391
|
const ref = obj[BLOB_KEY];
|
|
54116
54392
|
if (keys.length === 1 && keys[0] === BLOB_KEY && typeof ref === "string" && HASH_RE.test(ref)) {
|
|
54117
|
-
return (0,
|
|
54393
|
+
return (0, import_node_fs21.readFileSync)((0, import_node_path19.join)(objectsDir(id), ref), "utf8");
|
|
54118
54394
|
}
|
|
54119
54395
|
const out = {};
|
|
54120
54396
|
for (const [k, v] of Object.entries(obj)) out[k] = rehydrate(v, id);
|
|
@@ -54123,13 +54399,13 @@ function rehydrate(node, id) {
|
|
|
54123
54399
|
return node;
|
|
54124
54400
|
}
|
|
54125
54401
|
function createVersion(id, contract, meta) {
|
|
54126
|
-
(0,
|
|
54127
|
-
(0,
|
|
54402
|
+
(0, import_node_fs21.mkdirSync)(versionsDir(id), { recursive: true });
|
|
54403
|
+
(0, import_node_fs21.mkdirSync)(objectsDir(id), { recursive: true });
|
|
54128
54404
|
const blobs = /* @__PURE__ */ new Map();
|
|
54129
54405
|
const skeleton = dehydrate(contract, blobs);
|
|
54130
54406
|
for (const [hash, text] of blobs) {
|
|
54131
|
-
const p = (0,
|
|
54132
|
-
if (!(0,
|
|
54407
|
+
const p = (0, import_node_path19.join)(objectsDir(id), hash);
|
|
54408
|
+
if (!(0, import_node_fs21.existsSync)(p)) writeAtomic(p, text);
|
|
54133
54409
|
}
|
|
54134
54410
|
const log2 = loadLog(id);
|
|
54135
54411
|
const n = (log2.versions.at(-1)?.n ?? 0) + 1;
|
|
@@ -54139,9 +54415,11 @@ function createVersion(id, contract, meta) {
|
|
|
54139
54415
|
author: meta.author,
|
|
54140
54416
|
message: meta.message,
|
|
54141
54417
|
gate: meta.gate,
|
|
54142
|
-
kind: meta.kind
|
|
54418
|
+
kind: meta.kind,
|
|
54419
|
+
...meta.source ? { source: meta.source } : {}
|
|
54420
|
+
// revision-read provenance (small metadata; not dehydrated)
|
|
54143
54421
|
};
|
|
54144
|
-
writeAtomic((0,
|
|
54422
|
+
writeAtomic((0, import_node_path19.join)(versionsDir(id), `${n}.json`), JSON.stringify({ meta: row, contract: skeleton }, null, 2));
|
|
54145
54423
|
log2.versions.push(row);
|
|
54146
54424
|
writeAtomic(logPath(id), JSON.stringify(log2, null, 2));
|
|
54147
54425
|
return row;
|
|
@@ -54153,18 +54431,38 @@ function listVersions(id) {
|
|
|
54153
54431
|
}
|
|
54154
54432
|
function readVersion(id, n) {
|
|
54155
54433
|
try {
|
|
54156
|
-
const snap = JSON.parse((0,
|
|
54434
|
+
const snap = JSON.parse((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(versionsDir(id), `${n}.json`), "utf8"));
|
|
54157
54435
|
return rehydrate(snap.contract, id);
|
|
54158
54436
|
} catch {
|
|
54159
54437
|
return null;
|
|
54160
54438
|
}
|
|
54161
54439
|
}
|
|
54162
54440
|
|
|
54441
|
+
// project-sources-store.ts
|
|
54442
|
+
var import_node_crypto8 = require("node:crypto");
|
|
54443
|
+
var import_node_fs22 = require("node:fs");
|
|
54444
|
+
var import_node_path20 = require("node:path");
|
|
54445
|
+
var sourcesDir = (id) => (0, import_node_path20.join)(projectDir(id), "sources");
|
|
54446
|
+
var safeExt = (ext) => typeof ext === "string" && /^[a-z0-9]{1,8}$/i.test(ext) ? ext.toLowerCase() : "bin";
|
|
54447
|
+
function writeAtomic2(path, buf) {
|
|
54448
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
54449
|
+
(0, import_node_fs22.writeFileSync)(tmp, buf);
|
|
54450
|
+
(0, import_node_fs22.renameSync)(tmp, path);
|
|
54451
|
+
}
|
|
54452
|
+
function saveSource(id, file) {
|
|
54453
|
+
(0, import_node_fs22.mkdirSync)(sourcesDir(id), { recursive: true });
|
|
54454
|
+
const sha2562 = (0, import_node_crypto8.createHash)("sha256").update(file.buf).digest("hex");
|
|
54455
|
+
const ext = safeExt(file.ext);
|
|
54456
|
+
const p = (0, import_node_path20.join)(sourcesDir(id), `${sha2562}.${ext}`);
|
|
54457
|
+
if (!(0, import_node_fs22.existsSync)(p)) writeAtomic2(p, file.buf);
|
|
54458
|
+
return { name: String(file.name), sha256: sha2562, ext, bytes: file.buf.length };
|
|
54459
|
+
}
|
|
54460
|
+
|
|
54163
54461
|
// contract-bake.ts
|
|
54164
|
-
var
|
|
54462
|
+
var import_node_fs23 = require("node:fs");
|
|
54165
54463
|
var import_yaml5 = __toESM(require_dist6(), 1);
|
|
54166
54464
|
function bakeContractIntoApp(sourcePath, contract) {
|
|
54167
|
-
const doc = (0, import_yaml5.parseDocument)((0,
|
|
54465
|
+
const doc = (0, import_yaml5.parseDocument)((0, import_node_fs23.readFileSync)(sourcePath, "utf8"));
|
|
54168
54466
|
if (doc.errors.length > 0) {
|
|
54169
54467
|
throw new Error(`contract bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
54170
54468
|
}
|
|
@@ -54214,7 +54512,7 @@ function bakeContractIntoApp(sourcePath, contract) {
|
|
|
54214
54512
|
);
|
|
54215
54513
|
}
|
|
54216
54514
|
doc.setIn(["nodes", idx, "config", "takeoff"], baked);
|
|
54217
|
-
(0,
|
|
54515
|
+
(0, import_node_fs23.writeFileSync)(sourcePath, doc.toString());
|
|
54218
54516
|
}
|
|
54219
54517
|
|
|
54220
54518
|
// vectorize.ts
|
|
@@ -54537,8 +54835,12 @@ var GROUPS = {
|
|
|
54537
54835
|
bolt: { key: "bolt", label: "Bolts", color: "#b0c4d8" },
|
|
54538
54836
|
// cool zinc-grey (matches the anchor fasteners)
|
|
54539
54837
|
stiffener: { key: "stiffener", label: "Stiffeners", color: "#9aafc3" },
|
|
54540
|
-
cope: { key: "cope", label: "Copes", color: "#c2703a" }
|
|
54838
|
+
cope: { key: "cope", label: "Copes", color: "#c2703a" },
|
|
54541
54839
|
// a muted cut/burn amber — the removed corner (subtractive; rendered as the notch, not a swatch mesh)
|
|
54840
|
+
// Imported (custom) connection — one neutral steel band for the whole opaque assembly, so it reads
|
|
54841
|
+
// as a single imported unit (not scattered across the recipe-part legend rows). Roles (plate/bolt/
|
|
54842
|
+
// weld) are kept on each part's meta for labels, but share this one legend group + colour.
|
|
54843
|
+
custom: { key: "custom", label: "Imported connections", color: "#8a97a8" }
|
|
54542
54844
|
};
|
|
54543
54845
|
var EMBED = 1;
|
|
54544
54846
|
function num(params, key, def) {
|
|
@@ -54897,17 +55199,48 @@ function expandShearPlate(joint, beam, support) {
|
|
|
54897
55199
|
if (cope.bottom) pushCope("bottom", cope.bottom);
|
|
54898
55200
|
return parts;
|
|
54899
55201
|
}
|
|
55202
|
+
function expandCustom(joint) {
|
|
55203
|
+
const place = finite3(joint.place) ? joint.place : [0, 0, 0];
|
|
55204
|
+
const [dx, dy, dz] = place;
|
|
55205
|
+
const out = [];
|
|
55206
|
+
(joint.geometry ?? []).forEach((g, i) => {
|
|
55207
|
+
if (!g || !Array.isArray(g.positions) || !Array.isArray(g.indices)) return;
|
|
55208
|
+
if (g.positions.length < 9 || g.indices.length < 3 || g.positions.length % 3 !== 0) return;
|
|
55209
|
+
const positions = new Array(g.positions.length);
|
|
55210
|
+
for (let k = 0; k < g.positions.length; k += 3) {
|
|
55211
|
+
positions[k] = g.positions[k] + dx;
|
|
55212
|
+
positions[k + 1] = g.positions[k + 1] + dy;
|
|
55213
|
+
positions[k + 2] = g.positions[k + 2] + dz;
|
|
55214
|
+
}
|
|
55215
|
+
const role = typeof g.role === "string" ? g.role : void 0;
|
|
55216
|
+
const label = role ? role.charAt(0).toUpperCase() + role.slice(1) : "Imported part";
|
|
55217
|
+
out.push({ id: `${joint.id}:${g.id || `m${i}`}`, group: "custom", kind: "mesh", positions, indices: g.indices.slice(), meta: { label, role } });
|
|
55218
|
+
});
|
|
55219
|
+
return out;
|
|
55220
|
+
}
|
|
54900
55221
|
function expandJoints(joints, memberGeo) {
|
|
54901
55222
|
const elements = [];
|
|
54902
55223
|
const skipped = [];
|
|
54903
55224
|
const usedGroups = /* @__PURE__ */ new Set();
|
|
54904
55225
|
(joints ?? []).forEach((j, i) => {
|
|
54905
|
-
if (!j || !j.id
|
|
54906
|
-
skipped.push(
|
|
55226
|
+
if (!j || !j.id) {
|
|
55227
|
+
skipped.push(`joint#${i}`);
|
|
54907
55228
|
return;
|
|
54908
55229
|
}
|
|
54909
|
-
if (j.kind === "
|
|
54910
|
-
const
|
|
55230
|
+
if (j.kind === "custom") {
|
|
55231
|
+
const parts = expandCustom(j);
|
|
55232
|
+
if (!parts.length) {
|
|
55233
|
+
skipped.push(j.id);
|
|
55234
|
+
return;
|
|
55235
|
+
}
|
|
55236
|
+
for (const part of parts) {
|
|
55237
|
+
part.conn = j.id;
|
|
55238
|
+
part.connKind = j.kind;
|
|
55239
|
+
elements.push(part);
|
|
55240
|
+
usedGroups.add(part.group);
|
|
55241
|
+
}
|
|
55242
|
+
} else if (j.kind === "base-plate") {
|
|
55243
|
+
const col = j.main ? memberGeo.get(j.main) : void 0;
|
|
54911
55244
|
if (!col || col.role !== "column") {
|
|
54912
55245
|
skipped.push(j.id);
|
|
54913
55246
|
return;
|
|
@@ -54923,7 +55256,7 @@ function expandJoints(joints, memberGeo) {
|
|
|
54923
55256
|
usedGroups.add(part.group);
|
|
54924
55257
|
}
|
|
54925
55258
|
} else if (j.kind === "shear-plate") {
|
|
54926
|
-
const beam = memberGeo.get(j.main);
|
|
55259
|
+
const beam = j.main ? memberGeo.get(j.main) : void 0;
|
|
54927
55260
|
if (!beam || beam.role !== "beam") {
|
|
54928
55261
|
skipped.push(j.id);
|
|
54929
55262
|
return;
|
|
@@ -55145,10 +55478,10 @@ function contractToBom(contractInput) {
|
|
|
55145
55478
|
|
|
55146
55479
|
// bom-export.ts
|
|
55147
55480
|
var import_node_os14 = require("node:os");
|
|
55148
|
-
var
|
|
55481
|
+
var import_node_path21 = require("node:path");
|
|
55149
55482
|
|
|
55150
55483
|
// node_modules/write-excel-file/modules/export/writeXlsxFileNode.js
|
|
55151
|
-
var
|
|
55484
|
+
var import_node_fs24 = __toESM(require("node:fs"), 1);
|
|
55152
55485
|
|
|
55153
55486
|
// node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js
|
|
55154
55487
|
function _createForOfIteratorHelperLoose(r, e) {
|
|
@@ -59320,7 +59653,7 @@ function writeXlsxFile(arg1, arg2, arg3) {
|
|
|
59320
59653
|
},
|
|
59321
59654
|
toFile: function toFile(filePath) {
|
|
59322
59655
|
return createReadableStream().then(function(readableStream) {
|
|
59323
|
-
return pipe(readableStream,
|
|
59656
|
+
return pipe(readableStream, import_node_fs24.default.createWriteStream(filePath));
|
|
59324
59657
|
});
|
|
59325
59658
|
}
|
|
59326
59659
|
};
|
|
@@ -59345,8 +59678,8 @@ function pipe(readableStream, writableStream) {
|
|
|
59345
59678
|
|
|
59346
59679
|
// bom-export.ts
|
|
59347
59680
|
function bomExportPath(appId, format) {
|
|
59348
|
-
const root = process.env.FLOLESS_HOME ?? (0,
|
|
59349
|
-
return (0,
|
|
59681
|
+
const root = process.env.FLOLESS_HOME ?? (0, import_node_path21.join)((0, import_node_os14.homedir)(), ".floless");
|
|
59682
|
+
return (0, import_node_path21.join)(root, "exports", appId, `${appId}-bom.${format}`);
|
|
59350
59683
|
}
|
|
59351
59684
|
function csvField(v) {
|
|
59352
59685
|
let s = String(v);
|
|
@@ -59374,11 +59707,11 @@ async function bomToXlsx(bom) {
|
|
|
59374
59707
|
}
|
|
59375
59708
|
|
|
59376
59709
|
// scene-bake.ts
|
|
59377
|
-
var
|
|
59378
|
-
var
|
|
59710
|
+
var import_node_fs25 = require("node:fs");
|
|
59711
|
+
var import_node_path22 = require("node:path");
|
|
59379
59712
|
var import_yaml6 = __toESM(require_dist6(), 1);
|
|
59380
59713
|
function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
|
|
59381
|
-
const doc = (0, import_yaml6.parseDocument)((0,
|
|
59714
|
+
const doc = (0, import_yaml6.parseDocument)((0, import_node_fs25.readFileSync)(sourcePath, "utf8"));
|
|
59382
59715
|
if (doc.errors.length > 0) {
|
|
59383
59716
|
throw new Error(`scene bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
59384
59717
|
}
|
|
@@ -59387,10 +59720,10 @@ function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
|
|
|
59387
59720
|
const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.agent === agent);
|
|
59388
59721
|
if (idx < 0) throw new Error(`no ${agent} render node to bake the scene into`);
|
|
59389
59722
|
doc.setIn(["nodes", idx, "config", "scene"], scene);
|
|
59390
|
-
(0,
|
|
59723
|
+
(0, import_node_fs25.writeFileSync)(sourcePath, doc.toString());
|
|
59391
59724
|
}
|
|
59392
59725
|
function bakeNodeConfigById(sourcePath, nodeId, patch2) {
|
|
59393
|
-
const doc = (0, import_yaml6.parseDocument)((0,
|
|
59726
|
+
const doc = (0, import_yaml6.parseDocument)((0, import_node_fs25.readFileSync)(sourcePath, "utf8"));
|
|
59394
59727
|
if (doc.errors.length > 0) {
|
|
59395
59728
|
throw new Error(`node bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
|
|
59396
59729
|
}
|
|
@@ -59399,12 +59732,12 @@ function bakeNodeConfigById(sourcePath, nodeId, patch2) {
|
|
|
59399
59732
|
const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.id === nodeId);
|
|
59400
59733
|
if (idx < 0) throw new Error(`no node with id "${nodeId}"`);
|
|
59401
59734
|
for (const [key, value] of Object.entries(patch2)) doc.setIn(["nodes", idx, "config", key], value);
|
|
59402
|
-
(0,
|
|
59735
|
+
(0, import_node_fs25.writeFileSync)(sourcePath, doc.toString());
|
|
59403
59736
|
}
|
|
59404
59737
|
function writeViewer3dApp(dir, appId, scene) {
|
|
59405
|
-
(0,
|
|
59406
|
-
const flo = (0,
|
|
59407
|
-
(0,
|
|
59738
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
59739
|
+
const flo = (0, import_node_path22.join)(dir, `${appId}.flo`);
|
|
59740
|
+
(0, import_node_fs25.writeFileSync)(flo, [
|
|
59408
59741
|
`app: ${appId}`,
|
|
59409
59742
|
"version: 0.1.0",
|
|
59410
59743
|
"display-name: Steel 3D",
|
|
@@ -59425,11 +59758,11 @@ function writeViewer3dApp(dir, appId, scene) {
|
|
|
59425
59758
|
return flo;
|
|
59426
59759
|
}
|
|
59427
59760
|
function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
|
|
59428
|
-
(0,
|
|
59429
|
-
const flo = (0,
|
|
59761
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
59762
|
+
const flo = (0, import_node_path22.join)(dir, `${appId}.flo`);
|
|
59430
59763
|
const displayName = opts.displayName ?? "Steel IFC";
|
|
59431
59764
|
const description = opts.description ?? "IFC file written from an approved steel.takeoff/v1 contract (a companion export; the contract is the source of truth).";
|
|
59432
|
-
(0,
|
|
59765
|
+
(0, import_node_fs25.writeFileSync)(flo, [
|
|
59433
59766
|
`app: ${appId}`,
|
|
59434
59767
|
"version: 0.1.0",
|
|
59435
59768
|
`display-name: ${displayName}`,
|
|
@@ -59452,9 +59785,9 @@ function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
|
|
|
59452
59785
|
return flo;
|
|
59453
59786
|
}
|
|
59454
59787
|
function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
|
|
59455
|
-
(0,
|
|
59456
|
-
const flo = (0,
|
|
59457
|
-
(0,
|
|
59788
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
59789
|
+
const flo = (0, import_node_path22.join)(dir, `${appId}.flo`);
|
|
59790
|
+
(0, import_node_fs25.writeFileSync)(flo, [
|
|
59458
59791
|
`app: ${appId}`,
|
|
59459
59792
|
"version: 0.1.0",
|
|
59460
59793
|
"display-name: Steel to Tekla",
|
|
@@ -59862,13 +60195,13 @@ function scoreContract2(contractInput) {
|
|
|
59862
60195
|
}
|
|
59863
60196
|
|
|
59864
60197
|
// app-lifecycle.ts
|
|
59865
|
-
var
|
|
60198
|
+
var import_node_fs28 = require("node:fs");
|
|
59866
60199
|
var import_node_os16 = require("node:os");
|
|
59867
|
-
var
|
|
60200
|
+
var import_node_path25 = require("node:path");
|
|
59868
60201
|
|
|
59869
60202
|
// routines.ts
|
|
59870
|
-
var
|
|
59871
|
-
var
|
|
60203
|
+
var import_node_fs27 = require("node:fs");
|
|
60204
|
+
var import_node_path24 = require("node:path");
|
|
59872
60205
|
|
|
59873
60206
|
// sse.ts
|
|
59874
60207
|
var clients = /* @__PURE__ */ new Set();
|
|
@@ -59905,11 +60238,11 @@ function clientCount() {
|
|
|
59905
60238
|
}
|
|
59906
60239
|
|
|
59907
60240
|
// trigger-sessions.ts
|
|
59908
|
-
var
|
|
60241
|
+
var import_node_fs26 = require("node:fs");
|
|
59909
60242
|
var import_node_os15 = require("node:os");
|
|
59910
|
-
var
|
|
60243
|
+
var import_node_path23 = require("node:path");
|
|
59911
60244
|
var import_yaml7 = __toESM(require_dist6(), 1);
|
|
59912
|
-
var AGENTS_DIR2 = process.env.AWARE_HOME ? (0,
|
|
60245
|
+
var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path23.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path23.join)((0, import_node_os15.homedir)(), ".aware", "agents");
|
|
59913
60246
|
function summarizeFire(data) {
|
|
59914
60247
|
if (!data) return "event";
|
|
59915
60248
|
const type = typeof data.type === "string" ? data.type : "";
|
|
@@ -59926,10 +60259,10 @@ function mapTriggerState(phase) {
|
|
|
59926
60259
|
function isHostBacked(agent, agentsDir = AGENTS_DIR2) {
|
|
59927
60260
|
const safe = (n) => !n.includes("/") && !n.includes("\\") && !n.includes("..");
|
|
59928
60261
|
if (!safe(agent)) return false;
|
|
59929
|
-
const manifestPath = (0,
|
|
59930
|
-
if (!(0,
|
|
60262
|
+
const manifestPath = (0, import_node_path23.join)(agentsDir, agent, "manifest.yaml");
|
|
60263
|
+
if (!(0, import_node_fs26.existsSync)(manifestPath)) return false;
|
|
59931
60264
|
try {
|
|
59932
|
-
const doc = (0, import_yaml7.parse)((0,
|
|
60265
|
+
const doc = (0, import_yaml7.parse)((0, import_node_fs26.readFileSync)(manifestPath, "utf8"));
|
|
59933
60266
|
const transport = doc?.transport;
|
|
59934
60267
|
return !!(transport && typeof transport === "object" && "cli" in transport);
|
|
59935
60268
|
} catch {
|
|
@@ -60214,7 +60547,7 @@ var RoutineError = class extends Error {
|
|
|
60214
60547
|
}
|
|
60215
60548
|
status;
|
|
60216
60549
|
};
|
|
60217
|
-
var ROUTINES_FILE = (0,
|
|
60550
|
+
var ROUTINES_FILE = (0, import_node_path24.join)(flolessRoot, "routines.json");
|
|
60218
60551
|
var routines = [];
|
|
60219
60552
|
var loaded = false;
|
|
60220
60553
|
function ensureLoaded() {
|
|
@@ -60250,10 +60583,10 @@ function sanitizeRoutine(raw) {
|
|
|
60250
60583
|
};
|
|
60251
60584
|
}
|
|
60252
60585
|
function loadFromDisk() {
|
|
60253
|
-
if (!(0,
|
|
60586
|
+
if (!(0, import_node_fs27.existsSync)(ROUTINES_FILE)) return [];
|
|
60254
60587
|
let text;
|
|
60255
60588
|
try {
|
|
60256
|
-
text = (0,
|
|
60589
|
+
text = (0, import_node_fs27.readFileSync)(ROUTINES_FILE, "utf8");
|
|
60257
60590
|
} catch {
|
|
60258
60591
|
return [];
|
|
60259
60592
|
}
|
|
@@ -60262,17 +60595,17 @@ function loadFromDisk() {
|
|
|
60262
60595
|
return Array.isArray(parsed) ? parsed.map(sanitizeRoutine).filter((r) => r !== null) : [];
|
|
60263
60596
|
} catch {
|
|
60264
60597
|
try {
|
|
60265
|
-
(0,
|
|
60598
|
+
(0, import_node_fs27.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
|
|
60266
60599
|
} catch {
|
|
60267
60600
|
}
|
|
60268
60601
|
return [];
|
|
60269
60602
|
}
|
|
60270
60603
|
}
|
|
60271
60604
|
function saveRoutines() {
|
|
60272
|
-
if (!(0,
|
|
60605
|
+
if (!(0, import_node_fs27.existsSync)(flolessRoot)) (0, import_node_fs27.mkdirSync)(flolessRoot, { recursive: true });
|
|
60273
60606
|
const tmp = `${ROUTINES_FILE}.${process.pid}.tmp`;
|
|
60274
|
-
(0,
|
|
60275
|
-
(0,
|
|
60607
|
+
(0, import_node_fs27.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
|
|
60608
|
+
(0, import_node_fs27.renameSync)(tmp, ROUTINES_FILE);
|
|
60276
60609
|
}
|
|
60277
60610
|
function listRoutines() {
|
|
60278
60611
|
ensureLoaded();
|
|
@@ -60680,13 +61013,13 @@ var AppLifecycleError = class extends Error {
|
|
|
60680
61013
|
}
|
|
60681
61014
|
};
|
|
60682
61015
|
function appsDir() {
|
|
60683
|
-
return process.env.AWARE_HOME ? (0,
|
|
61016
|
+
return process.env.AWARE_HOME ? (0, import_node_path25.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path25.join)((0, import_node_os16.homedir)(), ".aware", "apps");
|
|
60684
61017
|
}
|
|
60685
61018
|
function appDirPath(id) {
|
|
60686
|
-
return (0,
|
|
61019
|
+
return (0, import_node_path25.join)(appsDir(), id);
|
|
60687
61020
|
}
|
|
60688
61021
|
function appInstalled(id) {
|
|
60689
|
-
return APP_ID3.test(id) && (0,
|
|
61022
|
+
return APP_ID3.test(id) && (0, import_node_fs28.existsSync)(appDirPath(id));
|
|
60690
61023
|
}
|
|
60691
61024
|
function logCascade(what, e) {
|
|
60692
61025
|
console.error(`[app-lifecycle] cascade step failed (${what}):`, e instanceof Error ? e.message : e);
|
|
@@ -60802,9 +61135,9 @@ function isGatedAwareRoute(url, method) {
|
|
|
60802
61135
|
|
|
60803
61136
|
// autostart.mjs
|
|
60804
61137
|
var import_node_child_process5 = require("node:child_process");
|
|
60805
|
-
var
|
|
61138
|
+
var import_node_fs29 = require("node:fs");
|
|
60806
61139
|
var import_node_os17 = require("node:os");
|
|
60807
|
-
var
|
|
61140
|
+
var import_node_path26 = require("node:path");
|
|
60808
61141
|
|
|
60809
61142
|
// teardown.mjs
|
|
60810
61143
|
var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
|
@@ -60916,8 +61249,8 @@ function removeLegacyRunKey() {
|
|
|
60916
61249
|
}
|
|
60917
61250
|
function logLine(msg) {
|
|
60918
61251
|
try {
|
|
60919
|
-
(0,
|
|
60920
|
-
(0,
|
|
61252
|
+
(0, import_node_fs29.mkdirSync)(logDir(), { recursive: true });
|
|
61253
|
+
(0, import_node_fs29.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
60921
61254
|
`);
|
|
60922
61255
|
} catch {
|
|
60923
61256
|
}
|
|
@@ -60925,8 +61258,8 @@ function logLine(msg) {
|
|
|
60925
61258
|
function registerAutostart(exePath) {
|
|
60926
61259
|
if (!isWin) return;
|
|
60927
61260
|
const xml = buildAutostartTaskXml(exePath, currentUserId());
|
|
60928
|
-
const tmp = (0,
|
|
60929
|
-
(0,
|
|
61261
|
+
const tmp = (0, import_node_path26.join)((0, import_node_os17.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
|
|
61262
|
+
(0, import_node_fs29.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
|
|
60930
61263
|
try {
|
|
60931
61264
|
(0, import_node_child_process5.execFileSync)("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", tmp, "/F"], {
|
|
60932
61265
|
stdio: ["ignore", "ignore", "ignore"],
|
|
@@ -60937,7 +61270,7 @@ function registerAutostart(exePath) {
|
|
|
60937
61270
|
throw err2;
|
|
60938
61271
|
} finally {
|
|
60939
61272
|
try {
|
|
60940
|
-
(0,
|
|
61273
|
+
(0, import_node_fs29.rmSync)(tmp, { force: true });
|
|
60941
61274
|
} catch {
|
|
60942
61275
|
}
|
|
60943
61276
|
}
|
|
@@ -60971,27 +61304,27 @@ function unregisterAutostart() {
|
|
|
60971
61304
|
|
|
60972
61305
|
// updater.ts
|
|
60973
61306
|
var import_node_child_process6 = require("node:child_process");
|
|
60974
|
-
var
|
|
60975
|
-
var
|
|
61307
|
+
var import_node_crypto9 = require("node:crypto");
|
|
61308
|
+
var import_node_fs31 = require("node:fs");
|
|
60976
61309
|
var import_node_stream3 = require("node:stream");
|
|
60977
61310
|
var import_promises = require("node:stream/promises");
|
|
60978
|
-
var
|
|
61311
|
+
var import_node_path28 = require("node:path");
|
|
60979
61312
|
|
|
60980
61313
|
// post-update-marker.mjs
|
|
60981
|
-
var
|
|
61314
|
+
var import_node_fs30 = require("node:fs");
|
|
60982
61315
|
var import_node_os18 = require("node:os");
|
|
60983
|
-
var
|
|
61316
|
+
var import_node_path27 = require("node:path");
|
|
60984
61317
|
var FRESH_MS = 12e4;
|
|
60985
61318
|
function markerPath() {
|
|
60986
61319
|
const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
|
|
60987
61320
|
if (override) return override;
|
|
60988
|
-
const root = process.env.FLOLESS_HOME ?? (0,
|
|
60989
|
-
return (0,
|
|
61321
|
+
const root = process.env.FLOLESS_HOME ?? (0, import_node_path27.join)((0, import_node_os18.homedir)(), ".floless");
|
|
61322
|
+
return (0, import_node_path27.join)(root, ".post-update");
|
|
60990
61323
|
}
|
|
60991
61324
|
function legacyMarkerPath() {
|
|
60992
61325
|
if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
|
|
60993
61326
|
try {
|
|
60994
|
-
return (0,
|
|
61327
|
+
return (0, import_node_path27.join)((0, import_node_path27.dirname)((0, import_node_path27.dirname)(process.execPath)), ".floless-post-update");
|
|
60995
61328
|
} catch {
|
|
60996
61329
|
return null;
|
|
60997
61330
|
}
|
|
@@ -61001,7 +61334,7 @@ function writePostUpdateMarker() {
|
|
|
61001
61334
|
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
61002
61335
|
if (!p) continue;
|
|
61003
61336
|
try {
|
|
61004
|
-
(0,
|
|
61337
|
+
(0, import_node_fs30.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
|
|
61005
61338
|
wrote = true;
|
|
61006
61339
|
} catch {
|
|
61007
61340
|
}
|
|
@@ -61013,9 +61346,9 @@ function consumePostUpdateMarker() {
|
|
|
61013
61346
|
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
61014
61347
|
if (!p) continue;
|
|
61015
61348
|
try {
|
|
61016
|
-
if (!(0,
|
|
61017
|
-
const ageMs = Date.now() - (0,
|
|
61018
|
-
(0,
|
|
61349
|
+
if (!(0, import_node_fs30.existsSync)(p)) continue;
|
|
61350
|
+
const ageMs = Date.now() - (0, import_node_fs30.statSync)(p).mtimeMs;
|
|
61351
|
+
(0, import_node_fs30.rmSync)(p, { force: true });
|
|
61019
61352
|
if (ageMs < FRESH_MS) fresh = true;
|
|
61020
61353
|
} catch {
|
|
61021
61354
|
}
|
|
@@ -61032,13 +61365,13 @@ function currentVersion() {
|
|
|
61032
61365
|
return appVersion();
|
|
61033
61366
|
}
|
|
61034
61367
|
function installRoot() {
|
|
61035
|
-
return (0,
|
|
61368
|
+
return (0, import_node_path28.dirname)((0, import_node_path28.dirname)(process.execPath));
|
|
61036
61369
|
}
|
|
61037
61370
|
function updateExePath() {
|
|
61038
|
-
return (0,
|
|
61371
|
+
return (0, import_node_path28.join)(installRoot(), "Update.exe");
|
|
61039
61372
|
}
|
|
61040
61373
|
function packagesDir() {
|
|
61041
|
-
return (0,
|
|
61374
|
+
return (0, import_node_path28.join)(installRoot(), "packages");
|
|
61042
61375
|
}
|
|
61043
61376
|
function feedUrl() {
|
|
61044
61377
|
const env2 = (process.env.FLOLESS_UPDATE_URL ?? "").trim().replace(/\/+$/, "");
|
|
@@ -61130,23 +61463,23 @@ async function checkForUpdate() {
|
|
|
61130
61463
|
return { supported: true, currentVersion: cur, updateAvailable: true, targetVersion: latest.Version, asset: latest };
|
|
61131
61464
|
}
|
|
61132
61465
|
async function sha1OfFile(path) {
|
|
61133
|
-
const hash = (0,
|
|
61134
|
-
await (0, import_promises.pipeline)((0,
|
|
61466
|
+
const hash = (0, import_node_crypto9.createHash)("sha1");
|
|
61467
|
+
await (0, import_promises.pipeline)((0, import_node_fs31.createReadStream)(path), hash);
|
|
61135
61468
|
return hash.digest("hex").toUpperCase();
|
|
61136
61469
|
}
|
|
61137
61470
|
async function downloadPackage(asset) {
|
|
61138
61471
|
if (!NUPKG_NAME.test(asset.FileName)) throw new Error(`refusing suspicious package name: ${asset.FileName}`);
|
|
61139
61472
|
const want = asset.SHA1.toUpperCase();
|
|
61140
61473
|
const dir = packagesDir();
|
|
61141
|
-
(0,
|
|
61142
|
-
const dest = (0,
|
|
61143
|
-
if ((0,
|
|
61474
|
+
(0, import_node_fs31.mkdirSync)(dir, { recursive: true });
|
|
61475
|
+
const dest = (0, import_node_path28.join)(dir, asset.FileName);
|
|
61476
|
+
if ((0, import_node_fs31.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
|
|
61144
61477
|
const res = await authedFetch(`${feedUrl()}/${encodeURIComponent(asset.FileName)}`, {
|
|
61145
61478
|
redirect: "follow",
|
|
61146
61479
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
61147
61480
|
});
|
|
61148
61481
|
if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status} for ${asset.FileName}`);
|
|
61149
|
-
await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0,
|
|
61482
|
+
await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0, import_node_fs31.createWriteStream)(dest));
|
|
61150
61483
|
const got = await sha1OfFile(dest);
|
|
61151
61484
|
if (got !== want) throw new Error(`SHA1 mismatch for ${asset.FileName}: feed=${want} got=${got}`);
|
|
61152
61485
|
return dest;
|
|
@@ -61155,7 +61488,7 @@ async function applyUpdate(check, opts) {
|
|
|
61155
61488
|
if (!check.supported) return { applied: false, message: check.reason ?? "auto-update not supported in this runtime" };
|
|
61156
61489
|
if (!check.updateAvailable || !check.asset) return { applied: false, message: check.reason ?? "no update available" };
|
|
61157
61490
|
const exe = updateExePath();
|
|
61158
|
-
if (!(0,
|
|
61491
|
+
if (!(0, import_node_fs31.existsSync)(exe)) {
|
|
61159
61492
|
return { applied: false, message: `Update.exe not found at ${exe} \u2014 is this a Velopack install?` };
|
|
61160
61493
|
}
|
|
61161
61494
|
const pkg = await downloadPackage(check.asset);
|
|
@@ -61395,12 +61728,12 @@ function isTraceCorrupt(events) {
|
|
|
61395
61728
|
|
|
61396
61729
|
// launch.mjs
|
|
61397
61730
|
var import_node_child_process7 = require("node:child_process");
|
|
61398
|
-
var
|
|
61731
|
+
var import_node_path29 = require("node:path");
|
|
61399
61732
|
var import_node_url3 = require("node:url");
|
|
61400
|
-
var
|
|
61733
|
+
var import_node_fs32 = require("node:fs");
|
|
61401
61734
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
61402
61735
|
var import_node_readline = require("node:readline");
|
|
61403
|
-
var __dirname2 = (0,
|
|
61736
|
+
var __dirname2 = (0, import_node_path29.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
|
|
61404
61737
|
var PORT = Number(process.env.PORT ?? 4317);
|
|
61405
61738
|
var HEALTH_URL = `http://127.0.0.1:${PORT}/api/health`;
|
|
61406
61739
|
var BROWSER_URL = `http://floless.localhost:${PORT}`;
|
|
@@ -61472,8 +61805,8 @@ async function waitHealthy(timeoutMs = 3e4) {
|
|
|
61472
61805
|
function resolveServerStart() {
|
|
61473
61806
|
const packaged = /flolessapp\.exe$/i.test(process.execPath);
|
|
61474
61807
|
if (packaged) return { cmd: process.execPath, args: ["--serve"], shell: false };
|
|
61475
|
-
const bundle = (0,
|
|
61476
|
-
if ((0,
|
|
61808
|
+
const bundle = (0, import_node_path29.join)(__dirname2, "dist", "floless-server.cjs");
|
|
61809
|
+
if ((0, import_node_fs32.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
|
|
61477
61810
|
return { cmd: "npm", args: ["run", "start"], shell: isWin2 };
|
|
61478
61811
|
}
|
|
61479
61812
|
function startServerDetached() {
|
|
@@ -61626,8 +61959,8 @@ function taskkillArgs(pid, { tree = true } = {}) {
|
|
|
61626
61959
|
}
|
|
61627
61960
|
function killSupervisor({ tree = true } = {}) {
|
|
61628
61961
|
if (!isWin2) return;
|
|
61629
|
-
const isNpmChannel = /^node(\.exe)?$/i.test((0,
|
|
61630
|
-
const scriptMatch = isNpmChannel ? (0,
|
|
61962
|
+
const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path29.basename)(process.execPath));
|
|
61963
|
+
const scriptMatch = isNpmChannel ? (0, import_node_path29.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
|
|
61631
61964
|
const realExe = resolveRealInstallExe(process.execPath);
|
|
61632
61965
|
const exeMatch = realExe === process.execPath ? process.execPath : [process.execPath, realExe];
|
|
61633
61966
|
const pids = supervisorPidsToKill(enumerateProcesses(), process.pid, exeMatch, scriptMatch);
|
|
@@ -61792,7 +62125,7 @@ async function runAction(arg, flagArgv = [], selfVersion = null) {
|
|
|
61792
62125
|
}
|
|
61793
62126
|
await action(parseTeardownFlags(flagArgv));
|
|
61794
62127
|
}
|
|
61795
|
-
var entry = (0,
|
|
62128
|
+
var entry = (0, import_node_path29.basename)(process.argv[1] ?? "").toLowerCase();
|
|
61796
62129
|
if (entry === "launch.mjs") {
|
|
61797
62130
|
runAction(process.argv[2], process.argv.slice(3)).catch((e) => {
|
|
61798
62131
|
log(`error: ${e?.message ?? e}`);
|
|
@@ -61866,9 +62199,9 @@ function awareUpgradeBlockReason(s) {
|
|
|
61866
62199
|
}
|
|
61867
62200
|
|
|
61868
62201
|
// skill-sync.ts
|
|
61869
|
-
var
|
|
62202
|
+
var import_node_fs33 = require("node:fs");
|
|
61870
62203
|
var import_node_os19 = require("node:os");
|
|
61871
|
-
var
|
|
62204
|
+
var import_node_path30 = require("node:path");
|
|
61872
62205
|
var import_node_url4 = require("node:url");
|
|
61873
62206
|
var import_yaml8 = __toESM(require_dist6(), 1);
|
|
61874
62207
|
|
|
@@ -61911,14 +62244,14 @@ function selectShippedSkillNames(names) {
|
|
|
61911
62244
|
}
|
|
61912
62245
|
|
|
61913
62246
|
// skill-sync.ts
|
|
61914
|
-
var __dirname3 = (0,
|
|
62247
|
+
var __dirname3 = (0, import_node_path30.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
|
|
61915
62248
|
function bundledSkillsRoot() {
|
|
61916
62249
|
const candidates = [
|
|
61917
|
-
(0,
|
|
61918
|
-
(0,
|
|
61919
|
-
(0,
|
|
62250
|
+
(0, import_node_path30.join)(__dirname3, "skills"),
|
|
62251
|
+
(0, import_node_path30.join)((0, import_node_path30.dirname)(process.execPath), "skills"),
|
|
62252
|
+
(0, import_node_path30.join)(__dirname3, "..", ".claude", "skills")
|
|
61920
62253
|
];
|
|
61921
|
-
return candidates.find((p) => (0,
|
|
62254
|
+
return candidates.find((p) => (0, import_node_fs33.existsSync)(p)) ?? null;
|
|
61922
62255
|
}
|
|
61923
62256
|
function targetConfigDirs() {
|
|
61924
62257
|
const override = process.env.FLOLESS_SKILL_TARGETS;
|
|
@@ -61927,14 +62260,14 @@ function targetConfigDirs() {
|
|
|
61927
62260
|
}
|
|
61928
62261
|
const home = (0, import_node_os19.homedir)();
|
|
61929
62262
|
return [
|
|
61930
|
-
{ runtime: "claude", dir: (0,
|
|
61931
|
-
{ runtime: "codex", dir: (0,
|
|
61932
|
-
{ runtime: "opencode", dir: (0,
|
|
62263
|
+
{ runtime: "claude", dir: (0, import_node_path30.join)(home, ".claude") },
|
|
62264
|
+
{ runtime: "codex", dir: (0, import_node_path30.join)(home, ".codex") },
|
|
62265
|
+
{ runtime: "opencode", dir: (0, import_node_path30.join)(home, ".opencode") }
|
|
61933
62266
|
];
|
|
61934
62267
|
}
|
|
61935
62268
|
function skillVersion(skillMdPath) {
|
|
61936
62269
|
try {
|
|
61937
|
-
const text = (0,
|
|
62270
|
+
const text = (0, import_node_fs33.readFileSync)(skillMdPath, "utf8");
|
|
61938
62271
|
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
|
61939
62272
|
if (!m || m[1] === void 0) return null;
|
|
61940
62273
|
const fm = (0, import_yaml8.parse)(m[1]);
|
|
@@ -61974,21 +62307,21 @@ function decideAction(installed, bundled) {
|
|
|
61974
62307
|
function bundledSkills(root) {
|
|
61975
62308
|
let entries = [];
|
|
61976
62309
|
try {
|
|
61977
|
-
entries = selectShippedSkillNames((0,
|
|
62310
|
+
entries = selectShippedSkillNames((0, import_node_fs33.readdirSync)(root));
|
|
61978
62311
|
} catch {
|
|
61979
62312
|
return [];
|
|
61980
62313
|
}
|
|
61981
62314
|
const out = [];
|
|
61982
62315
|
for (const name of entries) {
|
|
61983
|
-
const dir = (0,
|
|
62316
|
+
const dir = (0, import_node_path30.join)(root, name);
|
|
61984
62317
|
let isDir = false;
|
|
61985
62318
|
try {
|
|
61986
|
-
isDir = (0,
|
|
62319
|
+
isDir = (0, import_node_fs33.statSync)(dir).isDirectory();
|
|
61987
62320
|
} catch {
|
|
61988
62321
|
isDir = false;
|
|
61989
62322
|
}
|
|
61990
62323
|
if (!isDir) continue;
|
|
61991
|
-
const v = skillVersion((0,
|
|
62324
|
+
const v = skillVersion((0, import_node_path30.join)(dir, "SKILL.md"));
|
|
61992
62325
|
if (!v) continue;
|
|
61993
62326
|
out.push({ name, dir, version: v });
|
|
61994
62327
|
}
|
|
@@ -62001,17 +62334,17 @@ function syncSkills() {
|
|
|
62001
62334
|
const skills = bundledSkills(root);
|
|
62002
62335
|
if (!skills.length) return results;
|
|
62003
62336
|
for (const { runtime, dir: cfg } of targetConfigDirs()) {
|
|
62004
|
-
if (!(0,
|
|
62005
|
-
const skillsDir = (0,
|
|
62337
|
+
if (!(0, import_node_fs33.existsSync)(cfg)) continue;
|
|
62338
|
+
const skillsDir = (0, import_node_path30.join)(cfg, "skills");
|
|
62006
62339
|
for (const s of skills) {
|
|
62007
|
-
const dest = (0,
|
|
62008
|
-
const installedMd = (0,
|
|
62009
|
-
const installed = (0,
|
|
62340
|
+
const dest = (0, import_node_path30.join)(skillsDir, s.name);
|
|
62341
|
+
const installedMd = (0, import_node_path30.join)(dest, "SKILL.md");
|
|
62342
|
+
const installed = (0, import_node_fs33.existsSync)(installedMd) ? skillVersion(installedMd) : null;
|
|
62010
62343
|
const action = decideAction(installed, s.version);
|
|
62011
62344
|
if (action === "installed" || action === "updated") {
|
|
62012
62345
|
try {
|
|
62013
|
-
if (action === "updated") (0,
|
|
62014
|
-
(0,
|
|
62346
|
+
if (action === "updated") (0, import_node_fs33.rmSync)(dest, { recursive: true, force: true });
|
|
62347
|
+
(0, import_node_fs33.cpSync)(s.dir, dest, { recursive: true });
|
|
62015
62348
|
results.push({ runtime, skill: s.name, action, from: installed, to: s.version });
|
|
62016
62349
|
} catch {
|
|
62017
62350
|
}
|
|
@@ -62025,8 +62358,8 @@ function syncSkills() {
|
|
|
62025
62358
|
|
|
62026
62359
|
// watch.ts
|
|
62027
62360
|
var import_node_os20 = require("node:os");
|
|
62028
|
-
var
|
|
62029
|
-
var
|
|
62361
|
+
var import_node_path32 = require("node:path");
|
|
62362
|
+
var import_node_fs34 = require("node:fs");
|
|
62030
62363
|
|
|
62031
62364
|
// node_modules/chokidar/esm/index.js
|
|
62032
62365
|
var import_fs2 = require("fs");
|
|
@@ -62037,7 +62370,7 @@ var sysPath2 = __toESM(require("path"), 1);
|
|
|
62037
62370
|
// node_modules/readdirp/esm/index.js
|
|
62038
62371
|
var import_promises2 = require("node:fs/promises");
|
|
62039
62372
|
var import_node_stream4 = require("node:stream");
|
|
62040
|
-
var
|
|
62373
|
+
var import_node_path31 = require("node:path");
|
|
62041
62374
|
var EntryTypes = {
|
|
62042
62375
|
FILE_TYPE: "files",
|
|
62043
62376
|
DIR_TYPE: "directories",
|
|
@@ -62112,7 +62445,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62112
62445
|
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
62113
62446
|
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
62114
62447
|
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
62115
|
-
this._root = (0,
|
|
62448
|
+
this._root = (0, import_node_path31.resolve)(root);
|
|
62116
62449
|
this._isDirent = !opts.alwaysStat;
|
|
62117
62450
|
this._statsProp = this._isDirent ? "dirent" : "stats";
|
|
62118
62451
|
this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
|
|
@@ -62183,8 +62516,8 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62183
62516
|
let entry2;
|
|
62184
62517
|
const basename5 = this._isDirent ? dirent.name : dirent;
|
|
62185
62518
|
try {
|
|
62186
|
-
const fullPath = (0,
|
|
62187
|
-
entry2 = { path: (0,
|
|
62519
|
+
const fullPath = (0, import_node_path31.resolve)((0, import_node_path31.join)(path, basename5));
|
|
62520
|
+
entry2 = { path: (0, import_node_path31.relative)(this._root, fullPath), fullPath, basename: basename5 };
|
|
62188
62521
|
entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
62189
62522
|
} catch (err2) {
|
|
62190
62523
|
this._onError(err2);
|
|
@@ -62218,7 +62551,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
|
|
|
62218
62551
|
}
|
|
62219
62552
|
if (entryRealPathStats.isDirectory()) {
|
|
62220
62553
|
const len2 = entryRealPath.length;
|
|
62221
|
-
if (full.startsWith(entryRealPath) && full.substr(len2, 1) ===
|
|
62554
|
+
if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path31.sep) {
|
|
62222
62555
|
const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
|
|
62223
62556
|
recursiveError.code = RECURSIVE_ERROR_CODE;
|
|
62224
62557
|
return this._onError(recursiveError);
|
|
@@ -63726,33 +64059,33 @@ function appIdFromLogPath(path) {
|
|
|
63726
64059
|
return i >= 0 && parts[i + 1] ? parts[i + 1] : null;
|
|
63727
64060
|
}
|
|
63728
64061
|
function samePath(a, b) {
|
|
63729
|
-
const ra = (0,
|
|
63730
|
-
const rb = (0,
|
|
64062
|
+
const ra = (0, import_node_path32.resolve)(a);
|
|
64063
|
+
const rb = (0, import_node_path32.resolve)(b);
|
|
63731
64064
|
return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
|
|
63732
64065
|
}
|
|
63733
64066
|
function underDir(path, dir) {
|
|
63734
|
-
const rp = (0,
|
|
63735
|
-
const rd = (0,
|
|
64067
|
+
const rp = (0, import_node_path32.resolve)(path);
|
|
64068
|
+
const rd = (0, import_node_path32.resolve)(dir);
|
|
63736
64069
|
const [p, d] = process.platform === "win32" ? [rp.toLowerCase(), rd.toLowerCase()] : [rp, rd];
|
|
63737
|
-
return p === d || p.startsWith(d +
|
|
64070
|
+
return p === d || p.startsWith(d + import_node_path32.sep);
|
|
63738
64071
|
}
|
|
63739
64072
|
function startWatcher() {
|
|
63740
|
-
const awareDir = process.env.AWARE_HOME ?? (0,
|
|
63741
|
-
const credentialsDir = (0,
|
|
63742
|
-
if (!(0,
|
|
64073
|
+
const awareDir = process.env.AWARE_HOME ?? (0, import_node_path32.join)((0, import_node_os20.homedir)(), ".aware");
|
|
64074
|
+
const credentialsDir = (0, import_node_path32.join)(awareDir, "credentials");
|
|
64075
|
+
if (!(0, import_node_fs34.existsSync)(credentialsDir)) {
|
|
63743
64076
|
try {
|
|
63744
|
-
(0,
|
|
64077
|
+
(0, import_node_fs34.mkdirSync)(credentialsDir, { recursive: true });
|
|
63745
64078
|
} catch {
|
|
63746
64079
|
}
|
|
63747
64080
|
}
|
|
63748
|
-
if (!(0,
|
|
64081
|
+
if (!(0, import_node_fs34.existsSync)(uiDir)) {
|
|
63749
64082
|
try {
|
|
63750
|
-
(0,
|
|
64083
|
+
(0, import_node_fs34.mkdirSync)(uiDir, { recursive: true });
|
|
63751
64084
|
} catch {
|
|
63752
64085
|
}
|
|
63753
64086
|
}
|
|
63754
|
-
const targets = ["apps", "logs", "credentials"].map((d) => (0,
|
|
63755
|
-
if ((0,
|
|
64087
|
+
const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path32.join)(awareDir, d)).filter((p) => (0, import_node_fs34.existsSync)(p));
|
|
64088
|
+
if ((0, import_node_fs34.existsSync)(uiDir)) targets.push(uiDir);
|
|
63756
64089
|
if (targets.length === 0) {
|
|
63757
64090
|
return null;
|
|
63758
64091
|
}
|
|
@@ -63781,11 +64114,11 @@ function startWatcher() {
|
|
|
63781
64114
|
const isCredential = path.split(/[\\/]/).includes("credentials");
|
|
63782
64115
|
const kind = isCredential ? "credential" : path.endsWith(".jsonl") ? "trace" : path.endsWith(".lock") ? "lock" : path.endsWith(".flo") || path.endsWith(".app") ? "source" : "file";
|
|
63783
64116
|
broadcast({ type: "fs-change", kind, event, path });
|
|
63784
|
-
if (kind === "trace" && event !== "unlink" && (0,
|
|
64117
|
+
if (kind === "trace" && event !== "unlink" && (0, import_node_fs34.existsSync)(path)) {
|
|
63785
64118
|
const id = appIdFromLogPath(path);
|
|
63786
64119
|
if (!id) return;
|
|
63787
64120
|
try {
|
|
63788
|
-
broadcast({ type: "trace-file", id, runId: path.split(
|
|
64121
|
+
broadcast({ type: "trace-file", id, runId: path.split(import_node_path32.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs34.readFileSync)(path, "utf8")) });
|
|
63789
64122
|
} catch {
|
|
63790
64123
|
}
|
|
63791
64124
|
}
|
|
@@ -63794,10 +64127,10 @@ function startWatcher() {
|
|
|
63794
64127
|
}
|
|
63795
64128
|
|
|
63796
64129
|
// index.ts
|
|
63797
|
-
var __dirname4 = (0,
|
|
63798
|
-
var WEB_ROOT = [(0,
|
|
63799
|
-
(p) => (0,
|
|
63800
|
-
) ?? (0,
|
|
64130
|
+
var __dirname4 = (0, import_node_path33.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
|
|
64131
|
+
var WEB_ROOT = [(0, import_node_path33.join)(__dirname4, "web"), (0, import_node_path33.join)((0, import_node_path33.dirname)(process.execPath), "web"), (0, import_node_path33.join)(__dirname4, "..", "web")].find(
|
|
64132
|
+
(p) => (0, import_node_fs35.existsSync)(p)
|
|
64133
|
+
) ?? (0, import_node_path33.join)(__dirname4, "..", "web");
|
|
63801
64134
|
var PORT2 = Number(process.env.PORT ?? 4317);
|
|
63802
64135
|
var HOST = "127.0.0.1";
|
|
63803
64136
|
var crashHandlersInstalled = false;
|
|
@@ -63813,7 +64146,7 @@ function installCrashHandlers() {
|
|
|
63813
64146
|
${stack}
|
|
63814
64147
|
`;
|
|
63815
64148
|
try {
|
|
63816
|
-
(0,
|
|
64149
|
+
(0, import_node_fs35.appendFileSync)(logFilePath(), line);
|
|
63817
64150
|
} catch {
|
|
63818
64151
|
}
|
|
63819
64152
|
if (process.stderr.isTTY) process.stderr.write(line);
|
|
@@ -64110,9 +64443,9 @@ async function startServer() {
|
|
|
64110
64443
|
const { id, templateId, templatePath, srcPath, appDirPath: appDirPath2, fromVersion, contract, verb } = opts;
|
|
64111
64444
|
const bdir = backupDir(id, fromVersion, Date.now());
|
|
64112
64445
|
try {
|
|
64113
|
-
(0,
|
|
64114
|
-
(0,
|
|
64115
|
-
(0,
|
|
64446
|
+
(0, import_node_fs35.mkdirSync)((0, import_node_path33.dirname)(bdir), { recursive: true });
|
|
64447
|
+
(0, import_node_fs35.cpSync)(appDirPath2, bdir, { recursive: true });
|
|
64448
|
+
(0, import_node_fs35.cpSync)(templatePath, srcPath);
|
|
64116
64449
|
if (id !== templateId) stampSourceAppId(srcPath, id);
|
|
64117
64450
|
if (contract != null) {
|
|
64118
64451
|
bakeContractIntoApp(srcPath, contract);
|
|
@@ -64123,8 +64456,8 @@ async function startServer() {
|
|
|
64123
64456
|
} catch (e) {
|
|
64124
64457
|
const msg = e instanceof Error ? e.message : String(e);
|
|
64125
64458
|
try {
|
|
64126
|
-
(0,
|
|
64127
|
-
(0,
|
|
64459
|
+
(0, import_node_fs35.rmSync)(appDirPath2, { recursive: true, force: true });
|
|
64460
|
+
(0, import_node_fs35.cpSync)(bdir, appDirPath2, { recursive: true });
|
|
64128
64461
|
} catch (re) {
|
|
64129
64462
|
const rmsg = re instanceof Error ? re.message : String(re);
|
|
64130
64463
|
throw new TemplateSwapError(`${verb} failed (${msg}) AND rollback failed (${rmsg}) \u2014 restore manually from ${bdir}`, "rollback-failed", bdir);
|
|
@@ -64155,7 +64488,7 @@ async function startServer() {
|
|
|
64155
64488
|
return reply.status(409).send({ ok: false, error: `"${id}" is already at ${fromVersion}`, code: "up-to-date" });
|
|
64156
64489
|
}
|
|
64157
64490
|
const contract = readContract(id);
|
|
64158
|
-
if (contract == null && (0,
|
|
64491
|
+
if (contract == null && (0, import_node_fs35.existsSync)(contractPath(id))) {
|
|
64159
64492
|
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" });
|
|
64160
64493
|
}
|
|
64161
64494
|
if (contract != null) {
|
|
@@ -64360,6 +64693,92 @@ async function startServer() {
|
|
|
64360
64693
|
broadcast({ type: "contract-changed", appId: project.app, project: project.id });
|
|
64361
64694
|
return { ok: true, version: row };
|
|
64362
64695
|
});
|
|
64696
|
+
app.post(
|
|
64697
|
+
"/api/projects/:id/revision-requests",
|
|
64698
|
+
{ bodyLimit: 96 * 1024 * 1024 },
|
|
64699
|
+
// a revised SET = multiple structural PDFs (matches /api/rebake)
|
|
64700
|
+
async (req, reply) => {
|
|
64701
|
+
const project = getProject(req.params.id);
|
|
64702
|
+
if (!project) return reply.status(404).send({ ok: false, error: `unknown project: ${req.params.id}` });
|
|
64703
|
+
const appId = typeof req.body?.appId === "string" ? req.body.appId : project.app;
|
|
64704
|
+
if (appId !== project.app) {
|
|
64705
|
+
return reply.status(404).send({ ok: false, error: `project "${project.id}" belongs to app "${project.app}", not "${appId}"` });
|
|
64706
|
+
}
|
|
64707
|
+
let decoded;
|
|
64708
|
+
try {
|
|
64709
|
+
decoded = decodeSnapshots(req.body?.snapshots);
|
|
64710
|
+
} catch (e) {
|
|
64711
|
+
return reply.status(400).send({ ok: false, error: e instanceof Error ? e.message : "bad snapshot" });
|
|
64712
|
+
}
|
|
64713
|
+
if (!decoded.length) return reply.status(400).send({ ok: false, error: "attach at least one drawing file" });
|
|
64714
|
+
const inputs = req.body?.snapshots ?? [];
|
|
64715
|
+
const sourceRefs = decoded.map((d, i) => {
|
|
64716
|
+
const nm = inputs[i]?.name;
|
|
64717
|
+
return saveSource(project.id, { name: typeof nm === "string" && nm || `sheet-${i + 1}.${d.ext}`, buf: d.buf, ext: d.ext });
|
|
64718
|
+
});
|
|
64719
|
+
const baseVersion = listVersions(project.id)[0]?.n ?? 0;
|
|
64720
|
+
const request = addRequest(
|
|
64721
|
+
{
|
|
64722
|
+
type: "revision-read",
|
|
64723
|
+
appId: project.app,
|
|
64724
|
+
project: project.id,
|
|
64725
|
+
baseVersion,
|
|
64726
|
+
sourceRefs,
|
|
64727
|
+
...typeof req.body?.message === "string" && req.body.message.trim() ? { instruction: req.body.message.trim() } : {}
|
|
64728
|
+
},
|
|
64729
|
+
decoded
|
|
64730
|
+
);
|
|
64731
|
+
broadcast({ type: "request-added", request });
|
|
64732
|
+
return { ok: true, request };
|
|
64733
|
+
}
|
|
64734
|
+
);
|
|
64735
|
+
app.post(
|
|
64736
|
+
"/api/projects/:id/revision-read",
|
|
64737
|
+
{ bodyLimit: 25 * 1024 * 1024 },
|
|
64738
|
+
// the contract embeds rasters (matches the contract PUT)
|
|
64739
|
+
async (req, reply) => {
|
|
64740
|
+
const project = getProject(req.params.id);
|
|
64741
|
+
if (!project) return reply.status(404).send({ ok: false, error: `unknown project: ${req.params.id}` });
|
|
64742
|
+
if (req.body?.contract == null) return reply.status(400).send({ ok: false, error: "contract required" });
|
|
64743
|
+
const requestId = typeof req.body?.requestId === "string" ? req.body.requestId : "";
|
|
64744
|
+
const request = requestId ? getRequest(requestId) : null;
|
|
64745
|
+
if (!request || request.type !== "revision-read" || request.project !== project.id) {
|
|
64746
|
+
return reply.status(400).send({ ok: false, error: "a valid queued revision-read requestId for this project is required" });
|
|
64747
|
+
}
|
|
64748
|
+
const head = listVersions(project.id)[0]?.n ?? 0;
|
|
64749
|
+
if ((request.baseVersion ?? 0) !== head) {
|
|
64750
|
+
return reply.status(409).send({ ok: false, error: `project changed since this read started (base v${request.baseVersion ?? 0}, now v${head}) \u2014 re-read the current version` });
|
|
64751
|
+
}
|
|
64752
|
+
try {
|
|
64753
|
+
writeContract(project.app, req.body.contract, project.id);
|
|
64754
|
+
} catch (e) {
|
|
64755
|
+
if (e instanceof ContractError) return reply.status(400).send({ ok: false, error: e.message });
|
|
64756
|
+
throw e;
|
|
64757
|
+
}
|
|
64758
|
+
clearApproval(project.id);
|
|
64759
|
+
const message = typeof req.body?.message === "string" && req.body.message.trim() ? req.body.message.trim() : "Re-read a revised drawing set";
|
|
64760
|
+
const source = request.sourceRefs && request.sourceRefs.length ? { files: request.sourceRefs, requestId: request.id } : void 0;
|
|
64761
|
+
const version = createVersion(project.id, req.body.contract, { author: "AI", message, gate: null, kind: "revision-read", source });
|
|
64762
|
+
broadcast({ type: "contract-changed", appId: project.app, project: project.id });
|
|
64763
|
+
deleteRequest(request.id);
|
|
64764
|
+
return { ok: true, version };
|
|
64765
|
+
}
|
|
64766
|
+
);
|
|
64767
|
+
app.post(
|
|
64768
|
+
"/api/projects/:id/revision-requests/:reqId/fail",
|
|
64769
|
+
async (req, reply) => {
|
|
64770
|
+
const project = getProject(req.params.id);
|
|
64771
|
+
if (!project) return reply.status(404).send({ ok: false, error: `unknown project: ${req.params.id}` });
|
|
64772
|
+
const existing = getRequest(req.params.reqId);
|
|
64773
|
+
if (!existing || existing.type !== "revision-read" || existing.project !== project.id) {
|
|
64774
|
+
return reply.status(404).send({ ok: false, error: `unknown revision request for this project: ${req.params.reqId}` });
|
|
64775
|
+
}
|
|
64776
|
+
const error = typeof req.body?.error === "string" && req.body.error.trim() ? req.body.error.trim().slice(0, 2e3) : "the read could not be completed";
|
|
64777
|
+
const request = patchRequest(existing.id, { status: "failed", error });
|
|
64778
|
+
broadcast({ type: "request-added", request });
|
|
64779
|
+
return { ok: true, request };
|
|
64780
|
+
}
|
|
64781
|
+
);
|
|
64363
64782
|
function projectAppMismatch(appId, project) {
|
|
64364
64783
|
const p = getProject(project);
|
|
64365
64784
|
if (!p) return `unknown project: ${project}`;
|
|
@@ -64517,10 +64936,10 @@ async function startServer() {
|
|
|
64517
64936
|
if (bad) return reply.status(404).send({ ok: false, error: bad });
|
|
64518
64937
|
const dir = projectExportsDir(project);
|
|
64519
64938
|
const exports2 = projectExportFiles(req.params.appId).map(({ kind, filename }) => {
|
|
64520
|
-
const path = (0,
|
|
64939
|
+
const path = (0, import_node_path33.join)(dir, filename);
|
|
64521
64940
|
let exportedAt = null;
|
|
64522
64941
|
try {
|
|
64523
|
-
const st = (0,
|
|
64942
|
+
const st = (0, import_node_fs35.statSync)(path);
|
|
64524
64943
|
if (st.isFile()) exportedAt = st.mtime.toISOString();
|
|
64525
64944
|
} catch {
|
|
64526
64945
|
}
|
|
@@ -64604,8 +65023,8 @@ async function startServer() {
|
|
|
64604
65023
|
}
|
|
64605
65024
|
const companionId = `${req.params.appId}-ifc`;
|
|
64606
65025
|
const filename = `${req.params.appId}.ifc`;
|
|
64607
|
-
const outPath = project ? (0,
|
|
64608
|
-
if (project) (0,
|
|
65026
|
+
const outPath = project ? (0, import_node_path33.join)(projectExportsDir(project), filename) : (0, import_node_path33.join)(appPath(companionId), filename);
|
|
65027
|
+
if (project) (0, import_node_fs35.mkdirSync)((0, import_node_path33.dirname)(outPath), { recursive: true });
|
|
64609
65028
|
let flo;
|
|
64610
65029
|
try {
|
|
64611
65030
|
flo = writeIfcApp(appPath(companionId), companionId, scene, outPath, writeOpts);
|
|
@@ -64628,8 +65047,8 @@ async function startServer() {
|
|
|
64628
65047
|
}
|
|
64629
65048
|
throw e;
|
|
64630
65049
|
}
|
|
64631
|
-
if (!(0,
|
|
64632
|
-
const content = (0,
|
|
65050
|
+
if (!(0, import_node_fs35.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
|
|
65051
|
+
const content = (0, import_node_fs35.readFileSync)(outPath, "utf8");
|
|
64633
65052
|
broadcast({ type: "apps-changed" });
|
|
64634
65053
|
return { ok: true, filename, savedTo: outPath, content, bytes: Buffer.byteLength(content), skipped, ...extrusionsSkipped ? { extrusionsSkipped } : {} };
|
|
64635
65054
|
});
|
|
@@ -64718,17 +65137,17 @@ async function startServer() {
|
|
|
64718
65137
|
return reply.status(422).send({ ok: false, error: "no priced members to export \u2014 every member is an RFI (no AISC size / weight yet)" });
|
|
64719
65138
|
}
|
|
64720
65139
|
const filename = `${appId}-bom.${format}`;
|
|
64721
|
-
const outPath = project ? (0,
|
|
64722
|
-
const dir = (0,
|
|
65140
|
+
const outPath = project ? (0, import_node_path33.join)(projectExportsDir(project), filename) : bomExportPath(appId, format);
|
|
65141
|
+
const dir = (0, import_node_path33.dirname)(outPath);
|
|
64723
65142
|
try {
|
|
64724
|
-
(0,
|
|
65143
|
+
(0, import_node_fs35.mkdirSync)(dir, { recursive: true });
|
|
64725
65144
|
if (format === "csv") {
|
|
64726
65145
|
const text = bomToCsv(bom);
|
|
64727
|
-
(0,
|
|
65146
|
+
(0, import_node_fs35.writeFileSync)(outPath, text, "utf8");
|
|
64728
65147
|
return { ok: true, filename, encoding: "utf8", content: text, bytes: Buffer.byteLength(text), savedTo: outPath };
|
|
64729
65148
|
}
|
|
64730
65149
|
const buf = await bomToXlsx(bom);
|
|
64731
|
-
(0,
|
|
65150
|
+
(0, import_node_fs35.writeFileSync)(outPath, buf);
|
|
64732
65151
|
return { ok: true, filename, encoding: "base64", content: buf.toString("base64"), bytes: buf.length, savedTo: outPath };
|
|
64733
65152
|
} catch (e) {
|
|
64734
65153
|
app.log.error({ appId, format, err: e instanceof Error ? e.message : e }, "export-bom: generation failed");
|
|
@@ -64798,7 +65217,7 @@ async function startServer() {
|
|
|
64798
65217
|
return reply.status(404).send({ ok: false, error: `"${id}" is not installed`, code: "not-installed" });
|
|
64799
65218
|
}
|
|
64800
65219
|
const contract = readContract(id);
|
|
64801
|
-
if (contract == null && (0,
|
|
65220
|
+
if (contract == null && (0, import_node_fs35.existsSync)(contractPath(id))) {
|
|
64802
65221
|
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" });
|
|
64803
65222
|
}
|
|
64804
65223
|
if (contract != null) {
|
|
@@ -64876,11 +65295,11 @@ async function startServer() {
|
|
|
64876
65295
|
if (appExists(id)) {
|
|
64877
65296
|
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 });
|
|
64878
65297
|
}
|
|
64879
|
-
const stageRoot = (0,
|
|
65298
|
+
const stageRoot = (0, import_node_fs35.mkdtempSync)((0, import_node_path33.join)((0, import_node_os21.tmpdir)(), "floless-import-"));
|
|
64880
65299
|
try {
|
|
64881
|
-
const stageDir = (0,
|
|
64882
|
-
(0,
|
|
64883
|
-
(0,
|
|
65300
|
+
const stageDir = (0, import_node_path33.join)(stageRoot, id);
|
|
65301
|
+
(0, import_node_fs35.mkdirSync)(stageDir);
|
|
65302
|
+
(0, import_node_fs35.writeFileSync)((0, import_node_path33.join)(stageDir, `${id}.flo`), content);
|
|
64884
65303
|
await aware.install(stageDir);
|
|
64885
65304
|
} catch (err2) {
|
|
64886
65305
|
try {
|
|
@@ -64890,7 +65309,7 @@ async function startServer() {
|
|
|
64890
65309
|
const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
|
|
64891
65310
|
return reply.status(502).send({ ok: false, error: `import failed: ${msg}` });
|
|
64892
65311
|
} finally {
|
|
64893
|
-
(0,
|
|
65312
|
+
(0, import_node_fs35.rmSync)(stageRoot, { recursive: true, force: true });
|
|
64894
65313
|
}
|
|
64895
65314
|
broadcast({ type: "apps-changed", id });
|
|
64896
65315
|
return { ok: true, id };
|
|
@@ -64904,13 +65323,13 @@ async function startServer() {
|
|
|
64904
65323
|
}
|
|
64905
65324
|
const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
|
|
64906
65325
|
const baked = bakeFloSource(appData.source.text, inputs);
|
|
64907
|
-
const tmpRoot = (0,
|
|
64908
|
-
const backupDir2 = (0,
|
|
64909
|
-
const bakeDir = (0,
|
|
64910
|
-
(0,
|
|
64911
|
-
(0,
|
|
65326
|
+
const tmpRoot = (0, import_node_fs35.mkdtempSync)((0, import_node_path33.join)((0, import_node_os21.tmpdir)(), "floless-bake-"));
|
|
65327
|
+
const backupDir2 = (0, import_node_path33.join)(tmpRoot, `${id}-backup`);
|
|
65328
|
+
const bakeDir = (0, import_node_path33.join)(tmpRoot, id);
|
|
65329
|
+
(0, import_node_fs35.cpSync)(appDir(id), backupDir2, { recursive: true });
|
|
65330
|
+
(0, import_node_fs35.cpSync)(appDir(id), bakeDir, { recursive: true });
|
|
64912
65331
|
const floName = appData.source.path.split(/[\\/]/).pop();
|
|
64913
|
-
(0,
|
|
65332
|
+
(0, import_node_fs35.writeFileSync)((0, import_node_path33.join)(bakeDir, floName), baked);
|
|
64914
65333
|
let appInstalled2 = true;
|
|
64915
65334
|
try {
|
|
64916
65335
|
await aware.uninstall(id);
|
|
@@ -64932,17 +65351,17 @@ async function startServer() {
|
|
|
64932
65351
|
throw installErr;
|
|
64933
65352
|
}
|
|
64934
65353
|
try {
|
|
64935
|
-
await aware.compile((0,
|
|
65354
|
+
await aware.compile((0, import_node_path33.join)(appDir(id), floName));
|
|
64936
65355
|
} catch (compileErr) {
|
|
64937
65356
|
app.log.warn({ id, compileErr: String(compileErr) }, "bake: post-install recompile failed (app baked but may need a manual Compile)");
|
|
64938
65357
|
}
|
|
64939
65358
|
broadcast({ type: "baked", id });
|
|
64940
65359
|
return { ok: true, id, agent: id, inputs };
|
|
64941
65360
|
} finally {
|
|
64942
|
-
if (appInstalled2) (0,
|
|
65361
|
+
if (appInstalled2) (0, import_node_fs35.rmSync)(tmpRoot, { recursive: true, force: true });
|
|
64943
65362
|
}
|
|
64944
65363
|
});
|
|
64945
|
-
const graftAgentsDir = () => (0,
|
|
65364
|
+
const graftAgentsDir = () => (0, import_node_path33.join)((0, import_node_os21.homedir)(), ".aware", "agents");
|
|
64946
65365
|
app.post("/api/graft/match", async (req, reply) => {
|
|
64947
65366
|
const { glob } = req.body ?? {};
|
|
64948
65367
|
if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
|
|
@@ -64959,7 +65378,7 @@ async function startServer() {
|
|
|
64959
65378
|
if (!sourceKind || !sourceRef) {
|
|
64960
65379
|
return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
|
|
64961
65380
|
}
|
|
64962
|
-
const tempHome = (0,
|
|
65381
|
+
const tempHome = (0, import_node_fs35.mkdtempSync)((0, import_node_path33.join)((0, import_node_os21.tmpdir)(), "floless-graft-"));
|
|
64963
65382
|
let result;
|
|
64964
65383
|
try {
|
|
64965
65384
|
result = await aware.build({
|
|
@@ -64972,19 +65391,19 @@ async function startServer() {
|
|
|
64972
65391
|
awareHome: tempHome
|
|
64973
65392
|
});
|
|
64974
65393
|
} catch (err2) {
|
|
64975
|
-
(0,
|
|
65394
|
+
(0, import_node_fs35.rmSync)(tempHome, { recursive: true, force: true });
|
|
64976
65395
|
const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
|
|
64977
65396
|
return reply.status(422).send({ ok: false, error: msg });
|
|
64978
65397
|
}
|
|
64979
65398
|
const manifest = readStagedManifest(result.agentDir);
|
|
64980
65399
|
if (!manifest) {
|
|
64981
|
-
(0,
|
|
65400
|
+
(0, import_node_fs35.rmSync)(tempHome, { recursive: true, force: true });
|
|
64982
65401
|
return reply.status(502).send({ ok: false, error: `build produced output at ${result.agentDir} but no manifest.yaml` });
|
|
64983
65402
|
}
|
|
64984
|
-
const token = (0,
|
|
65403
|
+
const token = (0, import_node_crypto10.randomUUID)();
|
|
64985
65404
|
registerStage(token, tempHome, result.agentId);
|
|
64986
65405
|
const preview = buildPreview(manifest, sourceKind, sourceRef, token);
|
|
64987
|
-
if ((0,
|
|
65406
|
+
if ((0, import_node_fs35.existsSync)((0, import_node_path33.join)(graftAgentsDir(), result.agentId))) {
|
|
64988
65407
|
preview.warnings.unshift(`An agent named "${result.agentId}" is already installed \u2014 creating it will overwrite it.`);
|
|
64989
65408
|
}
|
|
64990
65409
|
return { ok: true, preview };
|
|
@@ -65003,7 +65422,7 @@ async function startServer() {
|
|
|
65003
65422
|
registerStage(stagedRef, stage.tempDir, stage.agentId);
|
|
65004
65423
|
return reply.status(409).send({ ok: false, error: err2.message, agentId: stage.agentId, collision: true });
|
|
65005
65424
|
}
|
|
65006
|
-
(0,
|
|
65425
|
+
(0, import_node_fs35.rmSync)(stage.tempDir, { recursive: true, force: true });
|
|
65007
65426
|
throw err2;
|
|
65008
65427
|
}
|
|
65009
65428
|
broadcast({ type: "grafted", id: stage.agentId });
|
|
@@ -65274,11 +65693,11 @@ async function startServer() {
|
|
|
65274
65693
|
app.get("/api/requests/:id/snapshot/:n", async (req, reply) => {
|
|
65275
65694
|
const n = Number.parseInt(req.params.n, 10);
|
|
65276
65695
|
const p = Number.isInteger(n) ? snapshotPathFor(req.params.id, n) : null;
|
|
65277
|
-
if (!p || !(0,
|
|
65696
|
+
if (!p || !(0, import_node_fs35.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
|
|
65278
65697
|
const ext = p.split(".").pop().toLowerCase();
|
|
65279
65698
|
reply.header("Content-Type", ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "pdf" ? "application/pdf" : "image/jpeg");
|
|
65280
65699
|
reply.header("Cache-Control", "no-store");
|
|
65281
|
-
return (0,
|
|
65700
|
+
return (0, import_node_fs35.readFileSync)(p);
|
|
65282
65701
|
});
|
|
65283
65702
|
app.post(
|
|
65284
65703
|
"/api/tweak",
|
|
@@ -65360,6 +65779,63 @@ async function startServer() {
|
|
|
65360
65779
|
}
|
|
65361
65780
|
}
|
|
65362
65781
|
);
|
|
65782
|
+
const CONN_APPID = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
65783
|
+
app.post(
|
|
65784
|
+
"/api/import-connection/list",
|
|
65785
|
+
{ bodyLimit: 96 * 1024 * 1024 },
|
|
65786
|
+
// a base64 IFC inflates ~4/3; 96 MB covers the 64 MB stash cap
|
|
65787
|
+
async (req, reply) => {
|
|
65788
|
+
const { appId, dataUrl } = req.body ?? {};
|
|
65789
|
+
if (!appId || !CONN_APPID.test(appId)) return reply.status(400).send({ ok: false, error: "a valid appId is required" });
|
|
65790
|
+
if (!dataUrl) return reply.status(400).send({ ok: false, error: "an IFC file is required" });
|
|
65791
|
+
let stored;
|
|
65792
|
+
try {
|
|
65793
|
+
stored = storeIfcInput(appId, dataUrl);
|
|
65794
|
+
} catch (e) {
|
|
65795
|
+
if (e instanceof VisualInputError) return reply.status(400).send({ ok: false, error: e.message });
|
|
65796
|
+
throw e;
|
|
65797
|
+
}
|
|
65798
|
+
let done = false;
|
|
65799
|
+
req.raw.on("close", () => {
|
|
65800
|
+
if (!done && isRunActive()) cancelActiveRun();
|
|
65801
|
+
});
|
|
65802
|
+
try {
|
|
65803
|
+
const connections = await listConnections(`${appId}-connimport`, stored.path);
|
|
65804
|
+
return { ok: true, sha: stored.sha256, connections };
|
|
65805
|
+
} catch (e) {
|
|
65806
|
+
if (e instanceof ConnectionImportError) return reply.send({ ok: false, error: e.message });
|
|
65807
|
+
app.log.error({ appId, err: e instanceof Error ? e.message : e }, "import-connection list failed");
|
|
65808
|
+
return reply.status(500).send({ ok: false, error: "could not read the IFC file" });
|
|
65809
|
+
} finally {
|
|
65810
|
+
done = true;
|
|
65811
|
+
}
|
|
65812
|
+
}
|
|
65813
|
+
);
|
|
65814
|
+
app.post(
|
|
65815
|
+
"/api/import-connection/extract",
|
|
65816
|
+
async (req, reply) => {
|
|
65817
|
+
const { appId, sha, id } = req.body ?? {};
|
|
65818
|
+
if (!appId || !CONN_APPID.test(appId)) return reply.status(400).send({ ok: false, error: "a valid appId is required" });
|
|
65819
|
+
if (!sha || !id) return reply.status(400).send({ ok: false, error: "sha and connection id are required" });
|
|
65820
|
+
const path = ifcInputPath(appId, sha);
|
|
65821
|
+
if (!path) return reply.status(404).send({ ok: false, error: "the uploaded IFC is no longer available \u2014 drop the file again" });
|
|
65822
|
+
let done = false;
|
|
65823
|
+
req.raw.on("close", () => {
|
|
65824
|
+
if (!done && isRunActive()) cancelActiveRun();
|
|
65825
|
+
});
|
|
65826
|
+
try {
|
|
65827
|
+
const connection = await extractConnection(`${appId}-connimport`, path, id);
|
|
65828
|
+
if (!connection.geometry.length) return reply.send({ ok: false, error: "that connection has no importable geometry" });
|
|
65829
|
+
return { ok: true, connection };
|
|
65830
|
+
} catch (e) {
|
|
65831
|
+
if (e instanceof ConnectionImportError) return reply.send({ ok: false, error: e.message });
|
|
65832
|
+
app.log.error({ appId, id, err: e instanceof Error ? e.message : e }, "import-connection extract failed");
|
|
65833
|
+
return reply.status(500).send({ ok: false, error: "could not read that connection" });
|
|
65834
|
+
} finally {
|
|
65835
|
+
done = true;
|
|
65836
|
+
}
|
|
65837
|
+
}
|
|
65838
|
+
);
|
|
65363
65839
|
app.post("/api/use-template", async (req, reply) => {
|
|
65364
65840
|
const { appId, templateId } = req.body ?? {};
|
|
65365
65841
|
if (!appId || !templateId) return reply.status(400).send({ ok: false, error: "appId and templateId required" });
|
|
@@ -65447,7 +65923,7 @@ async function startServer() {
|
|
|
65447
65923
|
warn(`last-run-status:${ref} \u2014 trace exists but couldn't be parsed (corrupt/truncated)`);
|
|
65448
65924
|
let finishedAt2 = null;
|
|
65449
65925
|
try {
|
|
65450
|
-
finishedAt2 = (0,
|
|
65926
|
+
finishedAt2 = (0, import_node_fs35.statSync)(latest.path).mtime.toISOString();
|
|
65451
65927
|
} catch {
|
|
65452
65928
|
finishedAt2 = null;
|
|
65453
65929
|
}
|
|
@@ -65457,7 +65933,7 @@ async function startServer() {
|
|
|
65457
65933
|
let finishedAt = typeof runEnd?.ts === "string" ? runEnd.ts : null;
|
|
65458
65934
|
if (!finishedAt) {
|
|
65459
65935
|
try {
|
|
65460
|
-
finishedAt = (0,
|
|
65936
|
+
finishedAt = (0, import_node_fs35.statSync)(latest.path).mtime.toISOString();
|
|
65461
65937
|
} catch {
|
|
65462
65938
|
finishedAt = null;
|
|
65463
65939
|
}
|