@floless/app 0.53.0 → 0.54.1

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.
@@ -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: join28 } = require("path");
5492
+ var { join: join29 } = 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"] || join28(__dirname, "lib", "worker.js");
5543
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join29(__dirname, "lib", "worker.js");
5544
5544
  const worker = new Worker2(toExecute, {
5545
5545
  ...opts.workerOpts,
5546
5546
  name: opts.workerOpts?.name || "thread-stream",
@@ -6008,7 +6008,7 @@ var require_transport = __commonJS({
6008
6008
  var { createRequire: createRequire5 } = require("module");
6009
6009
  var { existsSync: existsSync24 } = require("node:fs");
6010
6010
  var getCallers = require_caller();
6011
- var { join: join28, isAbsolute: isAbsolute2, sep: sep4 } = require("node:path");
6011
+ var { join: join29, 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();
@@ -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"] || join28(__dirname, "worker.js");
6164
+ target = bundlerOverrides["pino-worker"] || join29(__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"] || join28(__dirname, "worker.js");
6182
+ target = bundlerOverrides["pino-worker"] || join29(__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 join28(__dirname, "..", "file.js");
6205
+ return join29(__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 join28 = ",";
7185
+ let join29 = ",";
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
- join28 = `,
7199
+ join29 = `,
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 += join28;
7207
+ res += join29;
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 += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
7213
+ res += `${join29}"... ${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
- join28 = `,
7234
+ join29 = `,
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 = join28;
7248
+ separator = join29;
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 = join28;
7254
+ separator = join29;
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 join28 = ",";
7295
+ let join29 = ",";
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
- join28 = `,
7308
+ join29 = `,
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 += join28;
7316
+ res += join29;
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 += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
7322
+ res += `${join29}"... ${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
- join28 = `,
7335
+ join29 = `,
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 = join28;
7344
+ separator = join29;
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 join29 = `,
7402
+ const join30 = `,
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 += join29;
7409
+ res2 += join30;
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 += `${join29}"... ${getItemCount(removedKeys)} not stringified"`;
7415
+ res2 += `${join30}"... ${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 join28 = `,
7431
+ const join29 = `,
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, join28, maximumBreadth);
7437
+ res += stringifyTypedArray(value, join29, maximumBreadth);
7438
7438
  keys = keys.slice(value.length);
7439
7439
  maximumPropertiesToStringify -= value.length;
7440
- separator = join28;
7440
+ separator = join29;
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 = join28;
7451
+ separator = join29;
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 = join28;
7457
+ separator = join29;
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 extname2 = path.extname;
41994
- var join28 = path.join;
41994
+ var join29 = 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(join28(root, path2));
42081
+ path2 = normalize2(join29(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 = join28(path2, index);
42364
+ const p = join29(path2, index);
42365
42365
  const { error, stat: stat4 } = await tryStat(p);
42366
42366
  if (error) {
42367
42367
  err2 = error;
@@ -50827,8 +50827,8 @@ var import_node_readline2 = require("node:readline");
50827
50827
 
50828
50828
  // index.ts
50829
50829
  var import_node_url5 = require("node:url");
50830
- var import_node_path26 = require("node:path");
50831
- var import_node_os18 = require("node:os");
50830
+ var import_node_path27 = require("node:path");
50831
+ var import_node_os19 = require("node:os");
50832
50832
  var import_node_fs29 = require("node:fs");
50833
50833
  var import_node_child_process7 = require("node:child_process");
50834
50834
 
@@ -52856,7 +52856,7 @@ function appVersion() {
52856
52856
  return resolveVersion({
52857
52857
  isSea: isSea2(),
52858
52858
  sqVersionXml: readSqVersionXml(),
52859
- define: true ? "0.53.0" : void 0,
52859
+ define: true ? "0.54.1" : void 0,
52860
52860
  pkgVersion: readPkgVersion()
52861
52861
  });
52862
52862
  }
@@ -52866,7 +52866,7 @@ function resolveChannel(s) {
52866
52866
  return "dev";
52867
52867
  }
52868
52868
  function appChannel() {
52869
- return resolveChannel({ isSea: isSea2(), define: true ? "0.53.0" : void 0 });
52869
+ return resolveChannel({ isSea: isSea2(), define: true ? "0.54.1" : void 0 });
52870
52870
  }
52871
52871
 
52872
52872
  // workflow-update.ts
@@ -53958,6 +53958,10 @@ function contractToBom(contractInput) {
53958
53958
  };
53959
53959
  }
53960
53960
 
53961
+ // bom-export.ts
53962
+ var import_node_os12 = require("node:os");
53963
+ var import_node_path15 = require("node:path");
53964
+
53961
53965
  // node_modules/write-excel-file/modules/export/writeXlsxFileNode.js
53962
53966
  var import_node_fs18 = __toESM(require("node:fs"), 1);
53963
53967
 
@@ -58155,6 +58159,10 @@ function pipe(readableStream, writableStream) {
58155
58159
  }
58156
58160
 
58157
58161
  // bom-export.ts
58162
+ function bomExportPath(appId, format) {
58163
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path15.join)((0, import_node_os12.homedir)(), ".floless");
58164
+ return (0, import_node_path15.join)(root, "exports", appId, `${appId}-bom.${format}`);
58165
+ }
58158
58166
  function csvField(v) {
58159
58167
  let s = String(v);
58160
58168
  if (typeof v === "string" && /^[=+\-@\t\r]/.test(s)) s = `'${s}`;
@@ -58182,7 +58190,7 @@ async function bomToXlsx(bom) {
58182
58190
 
58183
58191
  // scene-bake.ts
58184
58192
  var import_node_fs19 = require("node:fs");
58185
- var import_node_path15 = require("node:path");
58193
+ var import_node_path16 = require("node:path");
58186
58194
  var import_yaml6 = __toESM(require_dist6(), 1);
58187
58195
  function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
58188
58196
  const doc = (0, import_yaml6.parseDocument)((0, import_node_fs19.readFileSync)(sourcePath, "utf8"));
@@ -58210,7 +58218,7 @@ function bakeNodeConfigById(sourcePath, nodeId, patch) {
58210
58218
  }
58211
58219
  function writeViewer3dApp(dir, appId, scene) {
58212
58220
  (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
58213
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
58221
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
58214
58222
  (0, import_node_fs19.writeFileSync)(flo, [
58215
58223
  `app: ${appId}`,
58216
58224
  "version: 0.1.0",
@@ -58233,7 +58241,7 @@ function writeViewer3dApp(dir, appId, scene) {
58233
58241
  }
58234
58242
  function writeIfcApp(dir, appId, scene, outputPath) {
58235
58243
  (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
58236
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
58244
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
58237
58245
  (0, import_node_fs19.writeFileSync)(flo, [
58238
58246
  `app: ${appId}`,
58239
58247
  "version: 0.1.0",
@@ -58258,7 +58266,7 @@ function writeIfcApp(dir, appId, scene, outputPath) {
58258
58266
  }
58259
58267
  function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
58260
58268
  (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
58261
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
58269
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
58262
58270
  (0, import_node_fs19.writeFileSync)(flo, [
58263
58271
  `app: ${appId}`,
58264
58272
  "version: 0.1.0",
@@ -58285,6 +58293,41 @@ function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
58285
58293
  return flo;
58286
58294
  }
58287
58295
 
58296
+ // bom-export-bake.ts
58297
+ var EXPORT_NODES = [
58298
+ { id: "csv-export", format: "csv" },
58299
+ { id: "xlsx-export", format: "xlsx" }
58300
+ ];
58301
+ async function bakeBomExportNodes(sourcePath, appId, contract) {
58302
+ const baked = [];
58303
+ const bom = contract != null ? contractToBom(contract) : null;
58304
+ const bytesFor = {
58305
+ csv: bom ? bomToCsv(bom) : null,
58306
+ xlsx: bom ? (await bomToXlsx(bom)).toString("base64") : null
58307
+ };
58308
+ for (const { id, format } of EXPORT_NODES) {
58309
+ const patch = { path: bomExportPath(appId, format) };
58310
+ const bytes = bytesFor[format];
58311
+ if (bytes != null) patch.bytes = bytes;
58312
+ try {
58313
+ bakeNodeConfigById(sourcePath, id, patch);
58314
+ baked.push(id);
58315
+ } catch (e) {
58316
+ if (!(e instanceof Error && /no node with id/.test(e.message))) throw e;
58317
+ }
58318
+ }
58319
+ return baked;
58320
+ }
58321
+ function exportPathsNeedingBake(nodes, appId) {
58322
+ const out = [];
58323
+ for (const { id, format } of EXPORT_NODES) {
58324
+ const node = nodes.find((n) => n.id === id);
58325
+ if (!node || node.agent !== "file" || node.frozen) continue;
58326
+ if (node.config?.path !== bomExportPath(appId, format)) out.push(id);
58327
+ }
58328
+ return out;
58329
+ }
58330
+
58288
58331
  // tekla-version.ts
58289
58332
  var import_node_child_process3 = require("node:child_process");
58290
58333
  var import_node_util = require("node:util");
@@ -58322,7 +58365,7 @@ async function teklaVersionToBake() {
58322
58365
  }
58323
58366
 
58324
58367
  // downstream-bake.ts
58325
- function bakeDownstream(sourcePath, contract) {
58368
+ async function bakeDownstream(sourcePath, appId, contract) {
58326
58369
  const { scene } = contractToScene(contract);
58327
58370
  let sceneElements = 0;
58328
58371
  try {
@@ -58339,7 +58382,8 @@ function bakeDownstream(sourcePath, contract) {
58339
58382
  } catch (e) {
58340
58383
  if (!(e instanceof Error && /no node with id "bom"/.test(e.message))) throw e;
58341
58384
  }
58342
- return { sceneElements, bomRows };
58385
+ const exportNodes = (await bakeBomExportNodes(sourcePath, appId, contract)).length;
58386
+ return { sceneElements, bomRows, exportNodes };
58343
58387
  }
58344
58388
 
58345
58389
  // steel-confidence.ts
@@ -58623,12 +58667,12 @@ function scoreContract2(contractInput) {
58623
58667
 
58624
58668
  // app-lifecycle.ts
58625
58669
  var import_node_fs22 = require("node:fs");
58626
- var import_node_os13 = require("node:os");
58627
- var import_node_path18 = require("node:path");
58670
+ var import_node_os14 = require("node:os");
58671
+ var import_node_path19 = require("node:path");
58628
58672
 
58629
58673
  // routines.ts
58630
58674
  var import_node_fs21 = require("node:fs");
58631
- var import_node_path17 = require("node:path");
58675
+ var import_node_path18 = require("node:path");
58632
58676
 
58633
58677
  // sse.ts
58634
58678
  var clients = /* @__PURE__ */ new Set();
@@ -58666,10 +58710,10 @@ function clientCount() {
58666
58710
 
58667
58711
  // trigger-sessions.ts
58668
58712
  var import_node_fs20 = require("node:fs");
58669
- var import_node_os12 = require("node:os");
58670
- var import_node_path16 = require("node:path");
58713
+ var import_node_os13 = require("node:os");
58714
+ var import_node_path17 = require("node:path");
58671
58715
  var import_yaml7 = __toESM(require_dist6(), 1);
58672
- var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path16.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path16.join)((0, import_node_os12.homedir)(), ".aware", "agents");
58716
+ var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path17.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path17.join)((0, import_node_os13.homedir)(), ".aware", "agents");
58673
58717
  function summarizeFire(data) {
58674
58718
  if (!data) return "event";
58675
58719
  const type = typeof data.type === "string" ? data.type : "";
@@ -58686,7 +58730,7 @@ function mapTriggerState(phase) {
58686
58730
  function isHostBacked(agent, agentsDir = AGENTS_DIR2) {
58687
58731
  const safe = (n) => !n.includes("/") && !n.includes("\\") && !n.includes("..");
58688
58732
  if (!safe(agent)) return false;
58689
- const manifestPath = (0, import_node_path16.join)(agentsDir, agent, "manifest.yaml");
58733
+ const manifestPath = (0, import_node_path17.join)(agentsDir, agent, "manifest.yaml");
58690
58734
  if (!(0, import_node_fs20.existsSync)(manifestPath)) return false;
58691
58735
  try {
58692
58736
  const doc = (0, import_yaml7.parse)((0, import_node_fs20.readFileSync)(manifestPath, "utf8"));
@@ -58974,7 +59018,7 @@ var RoutineError = class extends Error {
58974
59018
  }
58975
59019
  status;
58976
59020
  };
58977
- var ROUTINES_FILE = (0, import_node_path17.join)(flolessRoot, "routines.json");
59021
+ var ROUTINES_FILE = (0, import_node_path18.join)(flolessRoot, "routines.json");
58978
59022
  var routines = [];
58979
59023
  var loaded = false;
58980
59024
  function ensureLoaded() {
@@ -59440,10 +59484,10 @@ var AppLifecycleError = class extends Error {
59440
59484
  }
59441
59485
  };
59442
59486
  function appsDir() {
59443
- return process.env.AWARE_HOME ? (0, import_node_path18.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path18.join)((0, import_node_os13.homedir)(), ".aware", "apps");
59487
+ return process.env.AWARE_HOME ? (0, import_node_path19.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path19.join)((0, import_node_os14.homedir)(), ".aware", "apps");
59444
59488
  }
59445
59489
  function appDirPath(id) {
59446
- return (0, import_node_path18.join)(appsDir(), id);
59490
+ return (0, import_node_path19.join)(appsDir(), id);
59447
59491
  }
59448
59492
  function appInstalled(id) {
59449
59493
  return APP_ID3.test(id) && (0, import_node_fs22.existsSync)(appDirPath(id));
@@ -59548,8 +59592,8 @@ function isGatedAwareRoute(url, method) {
59548
59592
  // autostart.mjs
59549
59593
  var import_node_child_process4 = require("node:child_process");
59550
59594
  var import_node_fs23 = require("node:fs");
59551
- var import_node_os14 = require("node:os");
59552
- var import_node_path19 = require("node:path");
59595
+ var import_node_os15 = require("node:os");
59596
+ var import_node_path20 = require("node:path");
59553
59597
 
59554
59598
  // teardown.mjs
59555
59599
  var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -59670,7 +59714,7 @@ function logLine(msg) {
59670
59714
  function registerAutostart(exePath) {
59671
59715
  if (!isWin) return;
59672
59716
  const xml = buildAutostartTaskXml(exePath, currentUserId());
59673
- const tmp = (0, import_node_path19.join)((0, import_node_os14.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
59717
+ const tmp = (0, import_node_path20.join)((0, import_node_os15.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
59674
59718
  (0, import_node_fs23.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
59675
59719
  try {
59676
59720
  (0, import_node_child_process4.execFileSync)("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", tmp, "/F"], {
@@ -59720,23 +59764,23 @@ var import_node_crypto6 = require("node:crypto");
59720
59764
  var import_node_fs25 = require("node:fs");
59721
59765
  var import_node_stream3 = require("node:stream");
59722
59766
  var import_promises = require("node:stream/promises");
59723
- var import_node_path21 = require("node:path");
59767
+ var import_node_path22 = require("node:path");
59724
59768
 
59725
59769
  // post-update-marker.mjs
59726
59770
  var import_node_fs24 = require("node:fs");
59727
- var import_node_os15 = require("node:os");
59728
- var import_node_path20 = require("node:path");
59771
+ var import_node_os16 = require("node:os");
59772
+ var import_node_path21 = require("node:path");
59729
59773
  var FRESH_MS = 12e4;
59730
59774
  function markerPath() {
59731
59775
  const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
59732
59776
  if (override) return override;
59733
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path20.join)((0, import_node_os15.homedir)(), ".floless");
59734
- return (0, import_node_path20.join)(root, ".post-update");
59777
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path21.join)((0, import_node_os16.homedir)(), ".floless");
59778
+ return (0, import_node_path21.join)(root, ".post-update");
59735
59779
  }
59736
59780
  function legacyMarkerPath() {
59737
59781
  if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
59738
59782
  try {
59739
- return (0, import_node_path20.join)((0, import_node_path20.dirname)((0, import_node_path20.dirname)(process.execPath)), ".floless-post-update");
59783
+ return (0, import_node_path21.join)((0, import_node_path21.dirname)((0, import_node_path21.dirname)(process.execPath)), ".floless-post-update");
59740
59784
  } catch {
59741
59785
  return null;
59742
59786
  }
@@ -59777,13 +59821,13 @@ function currentVersion() {
59777
59821
  return appVersion();
59778
59822
  }
59779
59823
  function installRoot() {
59780
- return (0, import_node_path21.dirname)((0, import_node_path21.dirname)(process.execPath));
59824
+ return (0, import_node_path22.dirname)((0, import_node_path22.dirname)(process.execPath));
59781
59825
  }
59782
59826
  function updateExePath() {
59783
- return (0, import_node_path21.join)(installRoot(), "Update.exe");
59827
+ return (0, import_node_path22.join)(installRoot(), "Update.exe");
59784
59828
  }
59785
59829
  function packagesDir() {
59786
- return (0, import_node_path21.join)(installRoot(), "packages");
59830
+ return (0, import_node_path22.join)(installRoot(), "packages");
59787
59831
  }
59788
59832
  function feedUrl() {
59789
59833
  const env2 = (process.env.FLOLESS_UPDATE_URL ?? "").trim().replace(/\/+$/, "");
@@ -59884,7 +59928,7 @@ async function downloadPackage(asset) {
59884
59928
  const want = asset.SHA1.toUpperCase();
59885
59929
  const dir = packagesDir();
59886
59930
  (0, import_node_fs25.mkdirSync)(dir, { recursive: true });
59887
- const dest = (0, import_node_path21.join)(dir, asset.FileName);
59931
+ const dest = (0, import_node_path22.join)(dir, asset.FileName);
59888
59932
  if ((0, import_node_fs25.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
59889
59933
  const res = await authedFetch(`${feedUrl()}/${encodeURIComponent(asset.FileName)}`, {
59890
59934
  redirect: "follow",
@@ -60140,12 +60184,12 @@ function isTraceCorrupt(events) {
60140
60184
 
60141
60185
  // launch.mjs
60142
60186
  var import_node_child_process6 = require("node:child_process");
60143
- var import_node_path22 = require("node:path");
60187
+ var import_node_path23 = require("node:path");
60144
60188
  var import_node_url3 = require("node:url");
60145
60189
  var import_node_fs26 = require("node:fs");
60146
60190
  var import_node_http = __toESM(require("node:http"), 1);
60147
60191
  var import_node_readline = require("node:readline");
60148
- var __dirname2 = (0, import_node_path22.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
60192
+ var __dirname2 = (0, import_node_path23.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
60149
60193
  var PORT = Number(process.env.PORT ?? 4317);
60150
60194
  var HEALTH_URL = `http://127.0.0.1:${PORT}/api/health`;
60151
60195
  var BROWSER_URL = `http://floless.localhost:${PORT}`;
@@ -60217,7 +60261,7 @@ async function waitHealthy(timeoutMs = 3e4) {
60217
60261
  function resolveServerStart() {
60218
60262
  const packaged = /flolessapp\.exe$/i.test(process.execPath);
60219
60263
  if (packaged) return { cmd: process.execPath, args: ["--serve"], shell: false };
60220
- const bundle = (0, import_node_path22.join)(__dirname2, "dist", "floless-server.cjs");
60264
+ const bundle = (0, import_node_path23.join)(__dirname2, "dist", "floless-server.cjs");
60221
60265
  if ((0, import_node_fs26.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
60222
60266
  return { cmd: "npm", args: ["run", "start"], shell: isWin2 };
60223
60267
  }
@@ -60371,8 +60415,8 @@ function taskkillArgs(pid, { tree = true } = {}) {
60371
60415
  }
60372
60416
  function killSupervisor({ tree = true } = {}) {
60373
60417
  if (!isWin2) return;
60374
- const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path22.basename)(process.execPath));
60375
- const scriptMatch = isNpmChannel ? (0, import_node_path22.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
60418
+ const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path23.basename)(process.execPath));
60419
+ const scriptMatch = isNpmChannel ? (0, import_node_path23.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
60376
60420
  const realExe = resolveRealInstallExe(process.execPath);
60377
60421
  const exeMatch = realExe === process.execPath ? process.execPath : [process.execPath, realExe];
60378
60422
  const pids = supervisorPidsToKill(enumerateProcesses(), process.pid, exeMatch, scriptMatch);
@@ -60537,7 +60581,7 @@ async function runAction(arg, flagArgv = [], selfVersion = null) {
60537
60581
  }
60538
60582
  await action(parseTeardownFlags(flagArgv));
60539
60583
  }
60540
- var entry = (0, import_node_path22.basename)(process.argv[1] ?? "").toLowerCase();
60584
+ var entry = (0, import_node_path23.basename)(process.argv[1] ?? "").toLowerCase();
60541
60585
  if (entry === "launch.mjs") {
60542
60586
  runAction(process.argv[2], process.argv.slice(3)).catch((e) => {
60543
60587
  log(`error: ${e?.message ?? e}`);
@@ -60612,8 +60656,8 @@ function awareUpgradeBlockReason(s) {
60612
60656
 
60613
60657
  // skill-sync.ts
60614
60658
  var import_node_fs27 = require("node:fs");
60615
- var import_node_os16 = require("node:os");
60616
- var import_node_path23 = require("node:path");
60659
+ var import_node_os17 = require("node:os");
60660
+ var import_node_path24 = require("node:path");
60617
60661
  var import_node_url4 = require("node:url");
60618
60662
  var import_yaml8 = __toESM(require_dist6(), 1);
60619
60663
 
@@ -60641,8 +60685,10 @@ var PRODUCT_SKILLS = [
60641
60685
  // compose Custom Panels (~/.floless/ui/extensions.json) for the Dashboard
60642
60686
  "floless-app-workflows",
60643
60687
  // author/run .flo workflows
60644
- "reading-structural-drawings"
60688
+ "reading-structural-drawings",
60645
60689
  // the drawing-set reading discipline (non-namespace) the steel guide + reader lean on; shipped so users get it too
60690
+ "steel-drawing-abbreviations"
60691
+ // default US/AISC abbreviations+shapes legend (non-namespace) the steel reader falls back to when a set omits its own legend sheet
60646
60692
  ];
60647
60693
  function selectShippedSkillNames(names) {
60648
60694
  const present = new Set(names);
@@ -60650,12 +60696,12 @@ function selectShippedSkillNames(names) {
60650
60696
  }
60651
60697
 
60652
60698
  // skill-sync.ts
60653
- var __dirname3 = (0, import_node_path23.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
60699
+ var __dirname3 = (0, import_node_path24.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
60654
60700
  function bundledSkillsRoot() {
60655
60701
  const candidates = [
60656
- (0, import_node_path23.join)(__dirname3, "skills"),
60657
- (0, import_node_path23.join)((0, import_node_path23.dirname)(process.execPath), "skills"),
60658
- (0, import_node_path23.join)(__dirname3, "..", ".claude", "skills")
60702
+ (0, import_node_path24.join)(__dirname3, "skills"),
60703
+ (0, import_node_path24.join)((0, import_node_path24.dirname)(process.execPath), "skills"),
60704
+ (0, import_node_path24.join)(__dirname3, "..", ".claude", "skills")
60659
60705
  ];
60660
60706
  return candidates.find((p) => (0, import_node_fs27.existsSync)(p)) ?? null;
60661
60707
  }
@@ -60664,11 +60710,11 @@ function targetConfigDirs() {
60664
60710
  if (override) {
60665
60711
  return override.split(";").map((d) => d.trim()).filter(Boolean).map((dir) => ({ runtime: "custom", dir }));
60666
60712
  }
60667
- const home = (0, import_node_os16.homedir)();
60713
+ const home = (0, import_node_os17.homedir)();
60668
60714
  return [
60669
- { runtime: "claude", dir: (0, import_node_path23.join)(home, ".claude") },
60670
- { runtime: "codex", dir: (0, import_node_path23.join)(home, ".codex") },
60671
- { runtime: "opencode", dir: (0, import_node_path23.join)(home, ".opencode") }
60715
+ { runtime: "claude", dir: (0, import_node_path24.join)(home, ".claude") },
60716
+ { runtime: "codex", dir: (0, import_node_path24.join)(home, ".codex") },
60717
+ { runtime: "opencode", dir: (0, import_node_path24.join)(home, ".opencode") }
60672
60718
  ];
60673
60719
  }
60674
60720
  function skillVersion(skillMdPath) {
@@ -60719,7 +60765,7 @@ function bundledSkills(root) {
60719
60765
  }
60720
60766
  const out = [];
60721
60767
  for (const name of entries) {
60722
- const dir = (0, import_node_path23.join)(root, name);
60768
+ const dir = (0, import_node_path24.join)(root, name);
60723
60769
  let isDir = false;
60724
60770
  try {
60725
60771
  isDir = (0, import_node_fs27.statSync)(dir).isDirectory();
@@ -60727,7 +60773,7 @@ function bundledSkills(root) {
60727
60773
  isDir = false;
60728
60774
  }
60729
60775
  if (!isDir) continue;
60730
- const v = skillVersion((0, import_node_path23.join)(dir, "SKILL.md"));
60776
+ const v = skillVersion((0, import_node_path24.join)(dir, "SKILL.md"));
60731
60777
  if (!v) continue;
60732
60778
  out.push({ name, dir, version: v });
60733
60779
  }
@@ -60741,10 +60787,10 @@ function syncSkills() {
60741
60787
  if (!skills.length) return results;
60742
60788
  for (const { runtime, dir: cfg } of targetConfigDirs()) {
60743
60789
  if (!(0, import_node_fs27.existsSync)(cfg)) continue;
60744
- const skillsDir = (0, import_node_path23.join)(cfg, "skills");
60790
+ const skillsDir = (0, import_node_path24.join)(cfg, "skills");
60745
60791
  for (const s of skills) {
60746
- const dest = (0, import_node_path23.join)(skillsDir, s.name);
60747
- const installedMd = (0, import_node_path23.join)(dest, "SKILL.md");
60792
+ const dest = (0, import_node_path24.join)(skillsDir, s.name);
60793
+ const installedMd = (0, import_node_path24.join)(dest, "SKILL.md");
60748
60794
  const installed = (0, import_node_fs27.existsSync)(installedMd) ? skillVersion(installedMd) : null;
60749
60795
  const action = decideAction(installed, s.version);
60750
60796
  if (action === "installed" || action === "updated") {
@@ -60763,8 +60809,8 @@ function syncSkills() {
60763
60809
  }
60764
60810
 
60765
60811
  // watch.ts
60766
- var import_node_os17 = require("node:os");
60767
- var import_node_path25 = require("node:path");
60812
+ var import_node_os18 = require("node:os");
60813
+ var import_node_path26 = require("node:path");
60768
60814
  var import_node_fs28 = require("node:fs");
60769
60815
 
60770
60816
  // node_modules/chokidar/esm/index.js
@@ -60776,7 +60822,7 @@ var sysPath2 = __toESM(require("path"), 1);
60776
60822
  // node_modules/readdirp/esm/index.js
60777
60823
  var import_promises2 = require("node:fs/promises");
60778
60824
  var import_node_stream4 = require("node:stream");
60779
- var import_node_path24 = require("node:path");
60825
+ var import_node_path25 = require("node:path");
60780
60826
  var EntryTypes = {
60781
60827
  FILE_TYPE: "files",
60782
60828
  DIR_TYPE: "directories",
@@ -60851,7 +60897,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
60851
60897
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
60852
60898
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
60853
60899
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
60854
- this._root = (0, import_node_path24.resolve)(root);
60900
+ this._root = (0, import_node_path25.resolve)(root);
60855
60901
  this._isDirent = !opts.alwaysStat;
60856
60902
  this._statsProp = this._isDirent ? "dirent" : "stats";
60857
60903
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
@@ -60922,8 +60968,8 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
60922
60968
  let entry2;
60923
60969
  const basename5 = this._isDirent ? dirent.name : dirent;
60924
60970
  try {
60925
- const fullPath = (0, import_node_path24.resolve)((0, import_node_path24.join)(path, basename5));
60926
- entry2 = { path: (0, import_node_path24.relative)(this._root, fullPath), fullPath, basename: basename5 };
60971
+ const fullPath = (0, import_node_path25.resolve)((0, import_node_path25.join)(path, basename5));
60972
+ entry2 = { path: (0, import_node_path25.relative)(this._root, fullPath), fullPath, basename: basename5 };
60927
60973
  entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
60928
60974
  } catch (err2) {
60929
60975
  this._onError(err2);
@@ -60957,7 +61003,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
60957
61003
  }
60958
61004
  if (entryRealPathStats.isDirectory()) {
60959
61005
  const len2 = entryRealPath.length;
60960
- if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path24.sep) {
61006
+ if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path25.sep) {
60961
61007
  const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
60962
61008
  recursiveError.code = RECURSIVE_ERROR_CODE;
60963
61009
  return this._onError(recursiveError);
@@ -62465,19 +62511,19 @@ function appIdFromLogPath(path) {
62465
62511
  return i >= 0 && parts[i + 1] ? parts[i + 1] : null;
62466
62512
  }
62467
62513
  function samePath(a, b) {
62468
- const ra = (0, import_node_path25.resolve)(a);
62469
- const rb = (0, import_node_path25.resolve)(b);
62514
+ const ra = (0, import_node_path26.resolve)(a);
62515
+ const rb = (0, import_node_path26.resolve)(b);
62470
62516
  return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
62471
62517
  }
62472
62518
  function underDir(path, dir) {
62473
- const rp = (0, import_node_path25.resolve)(path);
62474
- const rd = (0, import_node_path25.resolve)(dir);
62519
+ const rp = (0, import_node_path26.resolve)(path);
62520
+ const rd = (0, import_node_path26.resolve)(dir);
62475
62521
  const [p, d] = process.platform === "win32" ? [rp.toLowerCase(), rd.toLowerCase()] : [rp, rd];
62476
- return p === d || p.startsWith(d + import_node_path25.sep);
62522
+ return p === d || p.startsWith(d + import_node_path26.sep);
62477
62523
  }
62478
62524
  function startWatcher() {
62479
- const awareDir = process.env.AWARE_HOME ?? (0, import_node_path25.join)((0, import_node_os17.homedir)(), ".aware");
62480
- const credentialsDir = (0, import_node_path25.join)(awareDir, "credentials");
62525
+ const awareDir = process.env.AWARE_HOME ?? (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".aware");
62526
+ const credentialsDir = (0, import_node_path26.join)(awareDir, "credentials");
62481
62527
  if (!(0, import_node_fs28.existsSync)(credentialsDir)) {
62482
62528
  try {
62483
62529
  (0, import_node_fs28.mkdirSync)(credentialsDir, { recursive: true });
@@ -62490,7 +62536,7 @@ function startWatcher() {
62490
62536
  } catch {
62491
62537
  }
62492
62538
  }
62493
- const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path25.join)(awareDir, d)).filter((p) => (0, import_node_fs28.existsSync)(p));
62539
+ const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path26.join)(awareDir, d)).filter((p) => (0, import_node_fs28.existsSync)(p));
62494
62540
  if ((0, import_node_fs28.existsSync)(uiDir)) targets.push(uiDir);
62495
62541
  if (targets.length === 0) {
62496
62542
  return null;
@@ -62524,7 +62570,7 @@ function startWatcher() {
62524
62570
  const id = appIdFromLogPath(path);
62525
62571
  if (!id) return;
62526
62572
  try {
62527
- broadcast({ type: "trace-file", id, runId: path.split(import_node_path25.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs28.readFileSync)(path, "utf8")) });
62573
+ broadcast({ type: "trace-file", id, runId: path.split(import_node_path26.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs28.readFileSync)(path, "utf8")) });
62528
62574
  } catch {
62529
62575
  }
62530
62576
  }
@@ -62533,10 +62579,10 @@ function startWatcher() {
62533
62579
  }
62534
62580
 
62535
62581
  // index.ts
62536
- var __dirname4 = (0, import_node_path26.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
62537
- var WEB_ROOT = [(0, import_node_path26.join)(__dirname4, "web"), (0, import_node_path26.join)((0, import_node_path26.dirname)(process.execPath), "web"), (0, import_node_path26.join)(__dirname4, "..", "web")].find(
62582
+ var __dirname4 = (0, import_node_path27.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
62583
+ var WEB_ROOT = [(0, import_node_path27.join)(__dirname4, "web"), (0, import_node_path27.join)((0, import_node_path27.dirname)(process.execPath), "web"), (0, import_node_path27.join)(__dirname4, "..", "web")].find(
62538
62584
  (p) => (0, import_node_fs29.existsSync)(p)
62539
- ) ?? (0, import_node_path26.join)(__dirname4, "..", "web");
62585
+ ) ?? (0, import_node_path27.join)(__dirname4, "..", "web");
62540
62586
  var PORT2 = Number(process.env.PORT ?? 4317);
62541
62587
  var HOST = "127.0.0.1";
62542
62588
  var crashHandlersInstalled = false;
@@ -62860,12 +62906,12 @@ async function startServer() {
62860
62906
  _wfUpdating.add(id);
62861
62907
  const bdir = backupDir(id, fromVersion, Date.now());
62862
62908
  try {
62863
- (0, import_node_fs29.mkdirSync)((0, import_node_path26.dirname)(bdir), { recursive: true });
62909
+ (0, import_node_fs29.mkdirSync)((0, import_node_path27.dirname)(bdir), { recursive: true });
62864
62910
  (0, import_node_fs29.cpSync)(appDirPath2, bdir, { recursive: true });
62865
62911
  (0, import_node_fs29.cpSync)(t.path, srcPath);
62866
62912
  if (contract != null) {
62867
62913
  bakeContractIntoApp(srcPath, contract);
62868
- bakeDownstream(srcPath, contract);
62914
+ await bakeDownstream(srcPath, id, contract);
62869
62915
  }
62870
62916
  await aware.compile(srcPath);
62871
62917
  broadcast({ type: "apps-changed", id });
@@ -63027,7 +63073,7 @@ async function startServer() {
63027
63073
  const sourcePath = readApp(req.params.appId).source.path;
63028
63074
  try {
63029
63075
  bakeContractIntoApp(sourcePath, doc);
63030
- bakeDownstream(sourcePath, doc);
63076
+ await bakeDownstream(sourcePath, req.params.appId, doc);
63031
63077
  } catch (e) {
63032
63078
  return reply.status(422).send({ ok: false, error: e instanceof Error ? e.message : "bake failed" });
63033
63079
  }
@@ -63146,7 +63192,7 @@ async function startServer() {
63146
63192
  }
63147
63193
  const companionId = `${req.params.appId}-ifc`;
63148
63194
  const filename = `${req.params.appId}.ifc`;
63149
- const outPath = (0, import_node_path26.join)(appPath(companionId), filename);
63195
+ const outPath = (0, import_node_path27.join)(appPath(companionId), filename);
63150
63196
  let flo;
63151
63197
  try {
63152
63198
  flo = writeIfcApp(appPath(companionId), companionId, scene, outPath);
@@ -63248,10 +63294,9 @@ async function startServer() {
63248
63294
  if (bom.rows.filter((r) => r.Profile !== "TOTAL").length === 0) {
63249
63295
  return reply.status(422).send({ ok: false, error: "no priced members to export \u2014 every member is an RFI (no AISC size / weight yet)" });
63250
63296
  }
63251
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".floless");
63252
- const dir = (0, import_node_path26.join)(root, "exports", appId);
63297
+ const outPath = bomExportPath(appId, format);
63298
+ const dir = (0, import_node_path27.dirname)(outPath);
63253
63299
  const filename = `${appId}-bom.${format}`;
63254
- const outPath = (0, import_node_path26.join)(dir, filename);
63255
63300
  try {
63256
63301
  (0, import_node_fs29.mkdirSync)(dir, { recursive: true });
63257
63302
  if (format === "csv") {
@@ -63354,11 +63399,11 @@ async function startServer() {
63354
63399
  if (appExists(id)) {
63355
63400
  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 });
63356
63401
  }
63357
- const stageRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-import-"));
63402
+ const stageRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-import-"));
63358
63403
  try {
63359
- const stageDir = (0, import_node_path26.join)(stageRoot, id);
63404
+ const stageDir = (0, import_node_path27.join)(stageRoot, id);
63360
63405
  (0, import_node_fs29.mkdirSync)(stageDir);
63361
- (0, import_node_fs29.writeFileSync)((0, import_node_path26.join)(stageDir, `${id}.flo`), content);
63406
+ (0, import_node_fs29.writeFileSync)((0, import_node_path27.join)(stageDir, `${id}.flo`), content);
63362
63407
  await aware.install(stageDir);
63363
63408
  } catch (err2) {
63364
63409
  try {
@@ -63382,13 +63427,13 @@ async function startServer() {
63382
63427
  }
63383
63428
  const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
63384
63429
  const baked = bakeFloSource(appData.source.text, inputs);
63385
- const tmpRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-bake-"));
63386
- const backupDir2 = (0, import_node_path26.join)(tmpRoot, `${id}-backup`);
63387
- const bakeDir = (0, import_node_path26.join)(tmpRoot, id);
63430
+ const tmpRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-bake-"));
63431
+ const backupDir2 = (0, import_node_path27.join)(tmpRoot, `${id}-backup`);
63432
+ const bakeDir = (0, import_node_path27.join)(tmpRoot, id);
63388
63433
  (0, import_node_fs29.cpSync)(appDir(id), backupDir2, { recursive: true });
63389
63434
  (0, import_node_fs29.cpSync)(appDir(id), bakeDir, { recursive: true });
63390
63435
  const floName = appData.source.path.split(/[\\/]/).pop();
63391
- (0, import_node_fs29.writeFileSync)((0, import_node_path26.join)(bakeDir, floName), baked);
63436
+ (0, import_node_fs29.writeFileSync)((0, import_node_path27.join)(bakeDir, floName), baked);
63392
63437
  let appInstalled2 = true;
63393
63438
  try {
63394
63439
  await aware.uninstall(id);
@@ -63410,7 +63455,7 @@ async function startServer() {
63410
63455
  throw installErr;
63411
63456
  }
63412
63457
  try {
63413
- await aware.compile((0, import_node_path26.join)(appDir(id), floName));
63458
+ await aware.compile((0, import_node_path27.join)(appDir(id), floName));
63414
63459
  } catch (compileErr) {
63415
63460
  app.log.warn({ id, compileErr: String(compileErr) }, "bake: post-install recompile failed (app baked but may need a manual Compile)");
63416
63461
  }
@@ -63420,7 +63465,7 @@ async function startServer() {
63420
63465
  if (appInstalled2) (0, import_node_fs29.rmSync)(tmpRoot, { recursive: true, force: true });
63421
63466
  }
63422
63467
  });
63423
- const graftAgentsDir = () => (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".aware", "agents");
63468
+ const graftAgentsDir = () => (0, import_node_path27.join)((0, import_node_os19.homedir)(), ".aware", "agents");
63424
63469
  app.post("/api/graft/match", async (req, reply) => {
63425
63470
  const { glob } = req.body ?? {};
63426
63471
  if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
@@ -63437,7 +63482,7 @@ async function startServer() {
63437
63482
  if (!sourceKind || !sourceRef) {
63438
63483
  return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
63439
63484
  }
63440
- const tempHome = (0, import_node_fs29.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-graft-"));
63485
+ const tempHome = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-graft-"));
63441
63486
  let result;
63442
63487
  try {
63443
63488
  result = await aware.build({
@@ -63462,7 +63507,7 @@ async function startServer() {
63462
63507
  const token = (0, import_node_crypto7.randomUUID)();
63463
63508
  registerStage(token, tempHome, result.agentId);
63464
63509
  const preview = buildPreview(manifest, sourceKind, sourceRef, token);
63465
- if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(graftAgentsDir(), result.agentId))) {
63510
+ if ((0, import_node_fs29.existsSync)((0, import_node_path27.join)(graftAgentsDir(), result.agentId))) {
63466
63511
  preview.warnings.unshift(`An agent named "${result.agentId}" is already installed \u2014 creating it will overwrite it.`);
63467
63512
  }
63468
63513
  return { ok: true, preview };
@@ -63512,6 +63557,33 @@ async function startServer() {
63512
63557
  }
63513
63558
  return false;
63514
63559
  }
63560
+ let _fileAgentReady = false;
63561
+ let _fileEnsureInflight = null;
63562
+ async function ensureSteelExportReady(id) {
63563
+ let appData;
63564
+ try {
63565
+ appData = readApp(id);
63566
+ } catch {
63567
+ return;
63568
+ }
63569
+ if (!appData.requires.some((r) => r.split("@")[0] === "file")) return;
63570
+ if (!_fileAgentReady) {
63571
+ _fileEnsureInflight ??= aware.ensureAgentInstalled("file").then(() => {
63572
+ _fileAgentReady = true;
63573
+ }).catch((e) => app.log.warn({ id, err: String(e) }, "ensure file agent before run failed (run will surface any real error)")).finally(() => {
63574
+ _fileEnsureInflight = null;
63575
+ });
63576
+ await _fileEnsureInflight;
63577
+ }
63578
+ if (appData.runnable && exportPathsNeedingBake(appData.nodes, id).length > 0) {
63579
+ try {
63580
+ await bakeBomExportNodes(appData.source.path, id);
63581
+ await aware.compile(appData.source.path);
63582
+ } catch (e) {
63583
+ app.log.warn({ id, err: String(e) }, "bake export path before run failed (run will surface any real error)");
63584
+ }
63585
+ }
63586
+ }
63515
63587
  app.post(
63516
63588
  "/api/run",
63517
63589
  async (req, reply) => {
@@ -63519,6 +63591,7 @@ async function startServer() {
63519
63591
  if (!id) return reply.status(400).send({ ok: false, error: "id required" });
63520
63592
  const blocked = hostRunBlocked(appProvider(id));
63521
63593
  if (blocked) return reply.send({ ok: false, error: blocked, blocked: true, simulate: !!simulate });
63594
+ if (!simulate) await ensureSteelExportReady(id);
63522
63595
  let result;
63523
63596
  try {
63524
63597
  result = await aware.run(id, { dryRun, simulate, inputs });