@floless/app 0.71.0 → 0.72.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: join30 } = require("path");
5492
+ var { join: join31 } = 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"] || join30(__dirname, "lib", "worker.js");
5543
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join31(__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: existsSync26 } = require("node:fs");
6009
+ var { existsSync: existsSync27 } = require("node:fs");
6010
6010
  var getCallers = require_caller();
6011
- var { join: join30, isAbsolute: isAbsolute2, sep: sep4 } = require("node:path");
6011
+ var { join: join31, 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) && !existsSync26(path);
6083
+ return isAbsolute2(path) && !existsSync27(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"] || join30(__dirname, "worker.js");
6164
+ target = bundlerOverrides["pino-worker"] || join31(__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"] || join30(__dirname, "worker.js");
6182
+ target = bundlerOverrides["pino-worker"] || join31(__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 join30(__dirname, "..", "file.js");
6205
+ return join31(__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 join30 = ",";
7185
+ let join31 = ",";
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
- join30 = `,
7199
+ join31 = `,
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 += join30;
7207
+ res += join31;
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 += `${join30}"... ${getItemCount(removedKeys)} not stringified"`;
7213
+ res += `${join31}"... ${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
- join30 = `,
7234
+ join31 = `,
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 = join30;
7248
+ separator = join31;
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 = join30;
7254
+ separator = join31;
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 join30 = ",";
7295
+ let join31 = ",";
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
- join30 = `,
7308
+ join31 = `,
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 += join30;
7316
+ res += join31;
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 += `${join30}"... ${getItemCount(removedKeys)} not stringified"`;
7322
+ res += `${join31}"... ${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
- join30 = `,
7335
+ join31 = `,
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 = join30;
7344
+ separator = join31;
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 join31 = `,
7402
+ const join32 = `,
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 += join31;
7409
+ res2 += join32;
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 += `${join31}"... ${getItemCount(removedKeys)} not stringified"`;
7415
+ res2 += `${join32}"... ${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 join30 = `,
7431
+ const join31 = `,
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, join30, maximumBreadth);
7437
+ res += stringifyTypedArray(value, join31, maximumBreadth);
7438
7438
  keys = keys.slice(value.length);
7439
7439
  maximumPropertiesToStringify -= value.length;
7440
- separator = join30;
7440
+ separator = join31;
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 = join30;
7451
+ separator = join31;
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 = join30;
7457
+ separator = join31;
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 join30 = path.join;
41994
+ var join31 = 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(join30(root, path2));
42081
+ path2 = normalize2(join31(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 = join30(path2, index);
42364
+ const p = join31(path2, index);
42365
42365
  const { error, stat: stat4 } = await tryStat(p);
42366
42366
  if (error) {
42367
42367
  err2 = error;
@@ -43145,8 +43145,8 @@ var require_static = __commonJS({
43145
43145
  }
43146
43146
  }
43147
43147
  }
43148
- for (const [dirname14, rootPath] of indexDirs.entries()) {
43149
- const pathname = dirname14 + (dirname14.endsWith("/") ? "" : "/");
43148
+ for (const [dirname15, rootPath] of indexDirs.entries()) {
43149
+ const pathname = dirname15 + (dirname15.endsWith("/") ? "" : "/");
43150
43150
  const file = "/" + pathname.replace(prefix, "");
43151
43151
  setUpHeadAndGet(routeOpts, pathname, file, rootPath);
43152
43152
  if (opts.redirect === true) {
@@ -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 import_node_path29 = require("node:path");
50831
- var import_node_os20 = require("node:os");
50832
- var import_node_fs31 = require("node:fs");
50830
+ var import_node_path30 = require("node:path");
50831
+ var import_node_os21 = require("node:os");
50832
+ var import_node_fs32 = require("node:fs");
50833
50833
  var import_node_child_process8 = require("node:child_process");
50834
50834
 
50835
50835
  // log.mjs
@@ -53022,7 +53022,7 @@ function appVersion() {
53022
53022
  return resolveVersion({
53023
53023
  isSea: isSea2(),
53024
53024
  sqVersionXml: readSqVersionXml(),
53025
- define: true ? "0.71.0" : void 0,
53025
+ define: true ? "0.72.1" : void 0,
53026
53026
  pkgVersion: readPkgVersion()
53027
53027
  });
53028
53028
  }
@@ -53032,7 +53032,7 @@ function resolveChannel(s) {
53032
53032
  return "dev";
53033
53033
  }
53034
53034
  function appChannel() {
53035
- return resolveChannel({ isSea: isSea2(), define: true ? "0.71.0" : void 0 });
53035
+ return resolveChannel({ isSea: isSea2(), define: true ? "0.72.1" : void 0 });
53036
53036
  }
53037
53037
 
53038
53038
  // workflow-update.ts
@@ -53395,7 +53395,7 @@ function extractSavedPath(events) {
53395
53395
  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 };
53396
53396
 
53397
53397
  // index.ts
53398
- var import_node_crypto7 = require("node:crypto");
53398
+ var import_node_crypto8 = require("node:crypto");
53399
53399
 
53400
53400
  // graft.ts
53401
53401
  var TEKLA_MARKER = "Recipe: Tekla model plug-in";
@@ -53898,11 +53898,16 @@ function safeId(appId) {
53898
53898
  if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId)) throw new ContractError(`invalid appId: ${appId}`);
53899
53899
  return appId;
53900
53900
  }
53901
- function contractPath(appId) {
53901
+ function safeProjectSeg(projectId) {
53902
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(projectId)) throw new ContractError(`invalid project id: ${projectId}`);
53903
+ return projectId;
53904
+ }
53905
+ function contractPath(appId, projectId) {
53906
+ if (projectId) return (0, import_node_path16.join)(ROOT3, "projects", safeProjectSeg(projectId), "contract.json");
53902
53907
  return (0, import_node_path16.join)(DIR, `${safeId(appId)}.json`);
53903
53908
  }
53904
- function readContract(appId) {
53905
- const p = contractPath(appId);
53909
+ function readContract(appId, projectId) {
53910
+ const p = contractPath(appId, projectId);
53906
53911
  if (!(0, import_node_fs18.existsSync)(p)) return null;
53907
53912
  try {
53908
53913
  return JSON.parse((0, import_node_fs18.readFileSync)(p, "utf8"));
@@ -53911,14 +53916,18 @@ function readContract(appId) {
53911
53916
  return null;
53912
53917
  }
53913
53918
  }
53914
- function writeContract(appId, doc) {
53915
- const p = contractPath(appId);
53919
+ function writeContract(appId, doc, projectId) {
53920
+ const p = contractPath(appId, projectId);
53916
53921
  const res = validateContract(doc);
53917
53922
  if (!res.valid) {
53918
53923
  const first = res.errors.slice(0, 5).map((e) => `${e.path}: ${e.message}`).join("; ");
53919
53924
  throw new ContractError(`contract failed schema validation \u2014 ${first}`);
53920
53925
  }
53921
- if (!(0, import_node_fs18.existsSync)(DIR)) (0, import_node_fs18.mkdirSync)(DIR, { recursive: true });
53926
+ if (projectId) {
53927
+ if (!(0, import_node_fs18.existsSync)((0, import_node_path16.dirname)(p))) throw new ContractError(`unknown project: ${projectId}`);
53928
+ } else if (!(0, import_node_fs18.existsSync)(DIR)) {
53929
+ (0, import_node_fs18.mkdirSync)(DIR, { recursive: true });
53930
+ }
53922
53931
  (0, import_node_fs18.writeFileSync)(p, JSON.stringify(doc));
53923
53932
  }
53924
53933
 
@@ -53941,11 +53950,107 @@ function readContractForApp(appId, readAppFn = readApp) {
53941
53950
  return t;
53942
53951
  }
53943
53952
 
53944
- // contract-bake.ts
53953
+ // projects-store.ts
53945
53954
  var import_node_fs19 = require("node:fs");
53955
+ var import_node_path17 = require("node:path");
53956
+ var import_node_os13 = require("node:os");
53957
+ var import_node_crypto6 = require("node:crypto");
53958
+ var ProjectError = class extends Error {
53959
+ };
53960
+ var ROOT4 = process.env.FLOLESS_HOME ?? (0, import_node_path17.join)((0, import_node_os13.homedir)(), ".floless");
53961
+ var DIR2 = (0, import_node_path17.join)(ROOT4, "projects");
53962
+ var ARCHIVE = (0, import_node_path17.join)(DIR2, ".archive");
53963
+ function safeProjectId(id) {
53964
+ if (typeof id !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(id)) {
53965
+ throw new ProjectError(`invalid project id: ${String(id)}`);
53966
+ }
53967
+ return id;
53968
+ }
53969
+ function slugify(name) {
53970
+ const s = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40);
53971
+ return s || "project";
53972
+ }
53973
+ function projectDir(id) {
53974
+ return (0, import_node_path17.join)(DIR2, safeProjectId(id));
53975
+ }
53976
+ var metaPath = (id) => (0, import_node_path17.join)(projectDir(id), "project.json");
53977
+ function readMeta(id) {
53978
+ const p = metaPath(id);
53979
+ if (!(0, import_node_fs19.existsSync)(p)) return null;
53980
+ try {
53981
+ const meta = JSON.parse((0, import_node_fs19.readFileSync)(p, "utf8"));
53982
+ return meta && meta.id === id ? meta : null;
53983
+ } catch (e) {
53984
+ console.warn(`projects-store: ignoring unreadable project.json at ${p}: ${e instanceof Error ? e.message : e}`);
53985
+ return null;
53986
+ }
53987
+ }
53988
+ var writeMeta = (meta) => (0, import_node_fs19.writeFileSync)(metaPath(meta.id), JSON.stringify(meta, null, 2));
53989
+ function listProjects() {
53990
+ if (!(0, import_node_fs19.existsSync)(DIR2)) return [];
53991
+ const out = [];
53992
+ for (const entry2 of (0, import_node_fs19.readdirSync)(DIR2, { withFileTypes: true })) {
53993
+ if (!entry2.isDirectory() || entry2.name.startsWith(".")) continue;
53994
+ const meta = readMeta(entry2.name);
53995
+ if (meta) out.push(meta);
53996
+ }
53997
+ return out.sort((a, b) => a.updatedAt < b.updatedAt ? 1 : -1);
53998
+ }
53999
+ function getProject(id) {
54000
+ return readMeta(safeProjectId(id));
54001
+ }
54002
+ function createProject(input) {
54003
+ const name = typeof input.name === "string" ? input.name.trim() : "";
54004
+ const app = typeof input.app === "string" ? input.app.trim() : "";
54005
+ if (!name) throw new ProjectError("project name required");
54006
+ if (!/^[a-z0-9][a-z0-9._-]*$/i.test(app)) throw new ProjectError(`invalid app id: ${app || "(empty)"}`);
54007
+ let id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
54008
+ while ((0, import_node_fs19.existsSync)(projectDir(id))) id = `${slugify(name)}-${(0, import_node_crypto6.randomBytes)(3).toString("hex")}`;
54009
+ (0, import_node_fs19.mkdirSync)(projectDir(id), { recursive: true });
54010
+ const now = (/* @__PURE__ */ new Date()).toISOString();
54011
+ const meta = { id, name, app, createdAt: now, updatedAt: now };
54012
+ writeMeta(meta);
54013
+ return meta;
54014
+ }
54015
+ function renameProject(id, name) {
54016
+ const meta = readMeta(safeProjectId(id));
54017
+ if (!meta) throw new ProjectError(`unknown project: ${id}`);
54018
+ if (typeof name !== "string" || !name.trim()) throw new ProjectError("project name required");
54019
+ const next = { ...meta, name: name.trim(), updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
54020
+ writeMeta(next);
54021
+ return next;
54022
+ }
54023
+ function touchProject(id) {
54024
+ const meta = readMeta(safeProjectId(id));
54025
+ if (meta) writeMeta({ ...meta, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
54026
+ }
54027
+ function duplicateProject(id, name) {
54028
+ const src = readMeta(safeProjectId(id));
54029
+ if (!src) throw new ProjectError(`unknown project: ${id}`);
54030
+ const copy = createProject({
54031
+ name: typeof name === "string" && name.trim() ? name.trim() : `${src.name} (copy)`,
54032
+ app: src.app
54033
+ });
54034
+ (0, import_node_fs19.cpSync)(projectDir(src.id), projectDir(copy.id), {
54035
+ recursive: true,
54036
+ filter: (p) => !p.endsWith("project.json")
54037
+ });
54038
+ return copy;
54039
+ }
54040
+ function archiveProject(id) {
54041
+ const dir = projectDir(id);
54042
+ if (!(0, import_node_fs19.existsSync)(dir)) throw new ProjectError(`unknown project: ${id}`);
54043
+ (0, import_node_fs19.mkdirSync)(ARCHIVE, { recursive: true });
54044
+ const dest = (0, import_node_path17.join)(ARCHIVE, id);
54045
+ if ((0, import_node_fs19.existsSync)(dest)) throw new ProjectError(`already archived: ${id}`);
54046
+ (0, import_node_fs19.renameSync)(dir, dest);
54047
+ }
54048
+
54049
+ // contract-bake.ts
54050
+ var import_node_fs20 = require("node:fs");
53946
54051
  var import_yaml5 = __toESM(require_dist6(), 1);
53947
54052
  function bakeContractIntoApp(sourcePath, contract) {
53948
- const doc = (0, import_yaml5.parseDocument)((0, import_node_fs19.readFileSync)(sourcePath, "utf8"));
54053
+ const doc = (0, import_yaml5.parseDocument)((0, import_node_fs20.readFileSync)(sourcePath, "utf8"));
53949
54054
  if (doc.errors.length > 0) {
53950
54055
  throw new Error(`contract bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
53951
54056
  }
@@ -53995,7 +54100,7 @@ function bakeContractIntoApp(sourcePath, contract) {
53995
54100
  );
53996
54101
  }
53997
54102
  doc.setIn(["nodes", idx, "config", "takeoff"], baked);
53998
- (0, import_node_fs19.writeFileSync)(sourcePath, doc.toString());
54103
+ (0, import_node_fs20.writeFileSync)(sourcePath, doc.toString());
53999
54104
  }
54000
54105
 
54001
54106
  // vectorize.ts
@@ -54925,11 +55030,11 @@ function contractToBom(contractInput) {
54925
55030
  }
54926
55031
 
54927
55032
  // bom-export.ts
54928
- var import_node_os13 = require("node:os");
54929
- var import_node_path17 = require("node:path");
55033
+ var import_node_os14 = require("node:os");
55034
+ var import_node_path18 = require("node:path");
54930
55035
 
54931
55036
  // node_modules/write-excel-file/modules/export/writeXlsxFileNode.js
54932
- var import_node_fs20 = __toESM(require("node:fs"), 1);
55037
+ var import_node_fs21 = __toESM(require("node:fs"), 1);
54933
55038
 
54934
55039
  // node_modules/write-excel-file/modules/xlsx/helpers/features/getAdditionalContent.js
54935
55040
  function _createForOfIteratorHelperLoose(r, e) {
@@ -59101,7 +59206,7 @@ function writeXlsxFile(arg1, arg2, arg3) {
59101
59206
  },
59102
59207
  toFile: function toFile(filePath) {
59103
59208
  return createReadableStream().then(function(readableStream) {
59104
- return pipe(readableStream, import_node_fs20.default.createWriteStream(filePath));
59209
+ return pipe(readableStream, import_node_fs21.default.createWriteStream(filePath));
59105
59210
  });
59106
59211
  }
59107
59212
  };
@@ -59126,8 +59231,8 @@ function pipe(readableStream, writableStream) {
59126
59231
 
59127
59232
  // bom-export.ts
59128
59233
  function bomExportPath(appId, format) {
59129
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path17.join)((0, import_node_os13.homedir)(), ".floless");
59130
- return (0, import_node_path17.join)(root, "exports", appId, `${appId}-bom.${format}`);
59234
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path18.join)((0, import_node_os14.homedir)(), ".floless");
59235
+ return (0, import_node_path18.join)(root, "exports", appId, `${appId}-bom.${format}`);
59131
59236
  }
59132
59237
  function csvField(v) {
59133
59238
  let s = String(v);
@@ -59155,11 +59260,11 @@ async function bomToXlsx(bom) {
59155
59260
  }
59156
59261
 
59157
59262
  // scene-bake.ts
59158
- var import_node_fs21 = require("node:fs");
59159
- var import_node_path18 = require("node:path");
59263
+ var import_node_fs22 = require("node:fs");
59264
+ var import_node_path19 = require("node:path");
59160
59265
  var import_yaml6 = __toESM(require_dist6(), 1);
59161
59266
  function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
59162
- const doc = (0, import_yaml6.parseDocument)((0, import_node_fs21.readFileSync)(sourcePath, "utf8"));
59267
+ const doc = (0, import_yaml6.parseDocument)((0, import_node_fs22.readFileSync)(sourcePath, "utf8"));
59163
59268
  if (doc.errors.length > 0) {
59164
59269
  throw new Error(`scene bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
59165
59270
  }
@@ -59168,10 +59273,10 @@ function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
59168
59273
  const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.agent === agent);
59169
59274
  if (idx < 0) throw new Error(`no ${agent} render node to bake the scene into`);
59170
59275
  doc.setIn(["nodes", idx, "config", "scene"], scene);
59171
- (0, import_node_fs21.writeFileSync)(sourcePath, doc.toString());
59276
+ (0, import_node_fs22.writeFileSync)(sourcePath, doc.toString());
59172
59277
  }
59173
59278
  function bakeNodeConfigById(sourcePath, nodeId, patch2) {
59174
- const doc = (0, import_yaml6.parseDocument)((0, import_node_fs21.readFileSync)(sourcePath, "utf8"));
59279
+ const doc = (0, import_yaml6.parseDocument)((0, import_node_fs22.readFileSync)(sourcePath, "utf8"));
59175
59280
  if (doc.errors.length > 0) {
59176
59281
  throw new Error(`node bake: source is not valid YAML: ${doc.errors[0]?.message ?? "parse error"}`);
59177
59282
  }
@@ -59180,12 +59285,12 @@ function bakeNodeConfigById(sourcePath, nodeId, patch2) {
59180
59285
  const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.id === nodeId);
59181
59286
  if (idx < 0) throw new Error(`no node with id "${nodeId}"`);
59182
59287
  for (const [key, value] of Object.entries(patch2)) doc.setIn(["nodes", idx, "config", key], value);
59183
- (0, import_node_fs21.writeFileSync)(sourcePath, doc.toString());
59288
+ (0, import_node_fs22.writeFileSync)(sourcePath, doc.toString());
59184
59289
  }
59185
59290
  function writeViewer3dApp(dir, appId, scene) {
59186
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
59187
- const flo = (0, import_node_path18.join)(dir, `${appId}.flo`);
59188
- (0, import_node_fs21.writeFileSync)(flo, [
59291
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
59292
+ const flo = (0, import_node_path19.join)(dir, `${appId}.flo`);
59293
+ (0, import_node_fs22.writeFileSync)(flo, [
59189
59294
  `app: ${appId}`,
59190
59295
  "version: 0.1.0",
59191
59296
  "display-name: Steel 3D",
@@ -59206,11 +59311,11 @@ function writeViewer3dApp(dir, appId, scene) {
59206
59311
  return flo;
59207
59312
  }
59208
59313
  function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
59209
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
59210
- const flo = (0, import_node_path18.join)(dir, `${appId}.flo`);
59314
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
59315
+ const flo = (0, import_node_path19.join)(dir, `${appId}.flo`);
59211
59316
  const displayName = opts.displayName ?? "Steel IFC";
59212
59317
  const description = opts.description ?? "IFC file written from an approved steel.takeoff/v1 contract (a companion export; the contract is the source of truth).";
59213
- (0, import_node_fs21.writeFileSync)(flo, [
59318
+ (0, import_node_fs22.writeFileSync)(flo, [
59214
59319
  `app: ${appId}`,
59215
59320
  "version: 0.1.0",
59216
59321
  `display-name: ${displayName}`,
@@ -59233,9 +59338,9 @@ function writeIfcApp(dir, appId, scene, outputPath, opts = {}) {
59233
59338
  return flo;
59234
59339
  }
59235
59340
  function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
59236
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
59237
- const flo = (0, import_node_path18.join)(dir, `${appId}.flo`);
59238
- (0, import_node_fs21.writeFileSync)(flo, [
59341
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
59342
+ const flo = (0, import_node_path19.join)(dir, `${appId}.flo`);
59343
+ (0, import_node_fs22.writeFileSync)(flo, [
59239
59344
  `app: ${appId}`,
59240
59345
  "version: 0.1.0",
59241
59346
  "display-name: Steel to Tekla",
@@ -59643,13 +59748,13 @@ function scoreContract2(contractInput) {
59643
59748
  }
59644
59749
 
59645
59750
  // app-lifecycle.ts
59646
- var import_node_fs24 = require("node:fs");
59647
- var import_node_os15 = require("node:os");
59648
- var import_node_path21 = require("node:path");
59751
+ var import_node_fs25 = require("node:fs");
59752
+ var import_node_os16 = require("node:os");
59753
+ var import_node_path22 = require("node:path");
59649
59754
 
59650
59755
  // routines.ts
59651
- var import_node_fs23 = require("node:fs");
59652
- var import_node_path20 = require("node:path");
59756
+ var import_node_fs24 = require("node:fs");
59757
+ var import_node_path21 = require("node:path");
59653
59758
 
59654
59759
  // sse.ts
59655
59760
  var clients = /* @__PURE__ */ new Set();
@@ -59686,11 +59791,11 @@ function clientCount() {
59686
59791
  }
59687
59792
 
59688
59793
  // trigger-sessions.ts
59689
- var import_node_fs22 = require("node:fs");
59690
- var import_node_os14 = require("node:os");
59691
- var import_node_path19 = require("node:path");
59794
+ var import_node_fs23 = require("node:fs");
59795
+ var import_node_os15 = require("node:os");
59796
+ var import_node_path20 = require("node:path");
59692
59797
  var import_yaml7 = __toESM(require_dist6(), 1);
59693
- var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path19.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path19.join)((0, import_node_os14.homedir)(), ".aware", "agents");
59798
+ var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path20.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path20.join)((0, import_node_os15.homedir)(), ".aware", "agents");
59694
59799
  function summarizeFire(data) {
59695
59800
  if (!data) return "event";
59696
59801
  const type = typeof data.type === "string" ? data.type : "";
@@ -59707,10 +59812,10 @@ function mapTriggerState(phase) {
59707
59812
  function isHostBacked(agent, agentsDir = AGENTS_DIR2) {
59708
59813
  const safe = (n) => !n.includes("/") && !n.includes("\\") && !n.includes("..");
59709
59814
  if (!safe(agent)) return false;
59710
- const manifestPath = (0, import_node_path19.join)(agentsDir, agent, "manifest.yaml");
59711
- if (!(0, import_node_fs22.existsSync)(manifestPath)) return false;
59815
+ const manifestPath = (0, import_node_path20.join)(agentsDir, agent, "manifest.yaml");
59816
+ if (!(0, import_node_fs23.existsSync)(manifestPath)) return false;
59712
59817
  try {
59713
- const doc = (0, import_yaml7.parse)((0, import_node_fs22.readFileSync)(manifestPath, "utf8"));
59818
+ const doc = (0, import_yaml7.parse)((0, import_node_fs23.readFileSync)(manifestPath, "utf8"));
59714
59819
  const transport = doc?.transport;
59715
59820
  return !!(transport && typeof transport === "object" && "cli" in transport);
59716
59821
  } catch {
@@ -59995,7 +60100,7 @@ var RoutineError = class extends Error {
59995
60100
  }
59996
60101
  status;
59997
60102
  };
59998
- var ROUTINES_FILE = (0, import_node_path20.join)(flolessRoot, "routines.json");
60103
+ var ROUTINES_FILE = (0, import_node_path21.join)(flolessRoot, "routines.json");
59999
60104
  var routines = [];
60000
60105
  var loaded = false;
60001
60106
  function ensureLoaded() {
@@ -60031,10 +60136,10 @@ function sanitizeRoutine(raw) {
60031
60136
  };
60032
60137
  }
60033
60138
  function loadFromDisk() {
60034
- if (!(0, import_node_fs23.existsSync)(ROUTINES_FILE)) return [];
60139
+ if (!(0, import_node_fs24.existsSync)(ROUTINES_FILE)) return [];
60035
60140
  let text;
60036
60141
  try {
60037
- text = (0, import_node_fs23.readFileSync)(ROUTINES_FILE, "utf8");
60142
+ text = (0, import_node_fs24.readFileSync)(ROUTINES_FILE, "utf8");
60038
60143
  } catch {
60039
60144
  return [];
60040
60145
  }
@@ -60043,17 +60148,17 @@ function loadFromDisk() {
60043
60148
  return Array.isArray(parsed) ? parsed.map(sanitizeRoutine).filter((r) => r !== null) : [];
60044
60149
  } catch {
60045
60150
  try {
60046
- (0, import_node_fs23.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
60151
+ (0, import_node_fs24.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
60047
60152
  } catch {
60048
60153
  }
60049
60154
  return [];
60050
60155
  }
60051
60156
  }
60052
60157
  function saveRoutines() {
60053
- if (!(0, import_node_fs23.existsSync)(flolessRoot)) (0, import_node_fs23.mkdirSync)(flolessRoot, { recursive: true });
60158
+ if (!(0, import_node_fs24.existsSync)(flolessRoot)) (0, import_node_fs24.mkdirSync)(flolessRoot, { recursive: true });
60054
60159
  const tmp = `${ROUTINES_FILE}.${process.pid}.tmp`;
60055
- (0, import_node_fs23.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
60056
- (0, import_node_fs23.renameSync)(tmp, ROUTINES_FILE);
60160
+ (0, import_node_fs24.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
60161
+ (0, import_node_fs24.renameSync)(tmp, ROUTINES_FILE);
60057
60162
  }
60058
60163
  function listRoutines() {
60059
60164
  ensureLoaded();
@@ -60109,7 +60214,7 @@ function coerceInputs(app, raw) {
60109
60214
  }
60110
60215
  return out;
60111
60216
  }
60112
- function slugify(s) {
60217
+ function slugify2(s) {
60113
60218
  const base = s.toLowerCase().trim().replace(/[^a-z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 48);
60114
60219
  return SLUG.test(base) ? base : "routine";
60115
60220
  }
@@ -60187,7 +60292,7 @@ function createRoutine(input) {
60187
60292
  }
60188
60293
  const now = /* @__PURE__ */ new Date();
60189
60294
  const r = {
60190
- id: uniqueId(slugify(name)),
60295
+ id: uniqueId(slugify2(name)),
60191
60296
  name,
60192
60297
  kind,
60193
60298
  workflow: app.id,
@@ -60461,13 +60566,13 @@ var AppLifecycleError = class extends Error {
60461
60566
  }
60462
60567
  };
60463
60568
  function appsDir() {
60464
- return process.env.AWARE_HOME ? (0, import_node_path21.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path21.join)((0, import_node_os15.homedir)(), ".aware", "apps");
60569
+ return process.env.AWARE_HOME ? (0, import_node_path22.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path22.join)((0, import_node_os16.homedir)(), ".aware", "apps");
60465
60570
  }
60466
60571
  function appDirPath(id) {
60467
- return (0, import_node_path21.join)(appsDir(), id);
60572
+ return (0, import_node_path22.join)(appsDir(), id);
60468
60573
  }
60469
60574
  function appInstalled(id) {
60470
- return APP_ID3.test(id) && (0, import_node_fs24.existsSync)(appDirPath(id));
60575
+ return APP_ID3.test(id) && (0, import_node_fs25.existsSync)(appDirPath(id));
60471
60576
  }
60472
60577
  function logCascade(what, e) {
60473
60578
  console.error(`[app-lifecycle] cascade step failed (${what}):`, e instanceof Error ? e.message : e);
@@ -60583,9 +60688,9 @@ function isGatedAwareRoute(url, method) {
60583
60688
 
60584
60689
  // autostart.mjs
60585
60690
  var import_node_child_process5 = require("node:child_process");
60586
- var import_node_fs25 = require("node:fs");
60587
- var import_node_os16 = require("node:os");
60588
- var import_node_path22 = require("node:path");
60691
+ var import_node_fs26 = require("node:fs");
60692
+ var import_node_os17 = require("node:os");
60693
+ var import_node_path23 = require("node:path");
60589
60694
 
60590
60695
  // teardown.mjs
60591
60696
  var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -60697,8 +60802,8 @@ function removeLegacyRunKey() {
60697
60802
  }
60698
60803
  function logLine(msg) {
60699
60804
  try {
60700
- (0, import_node_fs25.mkdirSync)(logDir(), { recursive: true });
60701
- (0, import_node_fs25.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
60805
+ (0, import_node_fs26.mkdirSync)(logDir(), { recursive: true });
60806
+ (0, import_node_fs26.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
60702
60807
  `);
60703
60808
  } catch {
60704
60809
  }
@@ -60706,8 +60811,8 @@ function logLine(msg) {
60706
60811
  function registerAutostart(exePath) {
60707
60812
  if (!isWin) return;
60708
60813
  const xml = buildAutostartTaskXml(exePath, currentUserId());
60709
- const tmp = (0, import_node_path22.join)((0, import_node_os16.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
60710
- (0, import_node_fs25.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
60814
+ const tmp = (0, import_node_path23.join)((0, import_node_os17.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
60815
+ (0, import_node_fs26.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
60711
60816
  try {
60712
60817
  (0, import_node_child_process5.execFileSync)("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", tmp, "/F"], {
60713
60818
  stdio: ["ignore", "ignore", "ignore"],
@@ -60718,7 +60823,7 @@ function registerAutostart(exePath) {
60718
60823
  throw err2;
60719
60824
  } finally {
60720
60825
  try {
60721
- (0, import_node_fs25.rmSync)(tmp, { force: true });
60826
+ (0, import_node_fs26.rmSync)(tmp, { force: true });
60722
60827
  } catch {
60723
60828
  }
60724
60829
  }
@@ -60752,27 +60857,27 @@ function unregisterAutostart() {
60752
60857
 
60753
60858
  // updater.ts
60754
60859
  var import_node_child_process6 = require("node:child_process");
60755
- var import_node_crypto6 = require("node:crypto");
60756
- var import_node_fs27 = require("node:fs");
60860
+ var import_node_crypto7 = require("node:crypto");
60861
+ var import_node_fs28 = require("node:fs");
60757
60862
  var import_node_stream3 = require("node:stream");
60758
60863
  var import_promises = require("node:stream/promises");
60759
- var import_node_path24 = require("node:path");
60864
+ var import_node_path25 = require("node:path");
60760
60865
 
60761
60866
  // post-update-marker.mjs
60762
- var import_node_fs26 = require("node:fs");
60763
- var import_node_os17 = require("node:os");
60764
- var import_node_path23 = require("node:path");
60867
+ var import_node_fs27 = require("node:fs");
60868
+ var import_node_os18 = require("node:os");
60869
+ var import_node_path24 = require("node:path");
60765
60870
  var FRESH_MS = 12e4;
60766
60871
  function markerPath() {
60767
60872
  const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
60768
60873
  if (override) return override;
60769
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path23.join)((0, import_node_os17.homedir)(), ".floless");
60770
- return (0, import_node_path23.join)(root, ".post-update");
60874
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path24.join)((0, import_node_os18.homedir)(), ".floless");
60875
+ return (0, import_node_path24.join)(root, ".post-update");
60771
60876
  }
60772
60877
  function legacyMarkerPath() {
60773
60878
  if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
60774
60879
  try {
60775
- return (0, import_node_path23.join)((0, import_node_path23.dirname)((0, import_node_path23.dirname)(process.execPath)), ".floless-post-update");
60880
+ return (0, import_node_path24.join)((0, import_node_path24.dirname)((0, import_node_path24.dirname)(process.execPath)), ".floless-post-update");
60776
60881
  } catch {
60777
60882
  return null;
60778
60883
  }
@@ -60782,7 +60887,7 @@ function writePostUpdateMarker() {
60782
60887
  for (const p of [markerPath(), legacyMarkerPath()]) {
60783
60888
  if (!p) continue;
60784
60889
  try {
60785
- (0, import_node_fs26.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
60890
+ (0, import_node_fs27.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
60786
60891
  wrote = true;
60787
60892
  } catch {
60788
60893
  }
@@ -60794,9 +60899,9 @@ function consumePostUpdateMarker() {
60794
60899
  for (const p of [markerPath(), legacyMarkerPath()]) {
60795
60900
  if (!p) continue;
60796
60901
  try {
60797
- if (!(0, import_node_fs26.existsSync)(p)) continue;
60798
- const ageMs = Date.now() - (0, import_node_fs26.statSync)(p).mtimeMs;
60799
- (0, import_node_fs26.rmSync)(p, { force: true });
60902
+ if (!(0, import_node_fs27.existsSync)(p)) continue;
60903
+ const ageMs = Date.now() - (0, import_node_fs27.statSync)(p).mtimeMs;
60904
+ (0, import_node_fs27.rmSync)(p, { force: true });
60800
60905
  if (ageMs < FRESH_MS) fresh = true;
60801
60906
  } catch {
60802
60907
  }
@@ -60813,13 +60918,13 @@ function currentVersion() {
60813
60918
  return appVersion();
60814
60919
  }
60815
60920
  function installRoot() {
60816
- return (0, import_node_path24.dirname)((0, import_node_path24.dirname)(process.execPath));
60921
+ return (0, import_node_path25.dirname)((0, import_node_path25.dirname)(process.execPath));
60817
60922
  }
60818
60923
  function updateExePath() {
60819
- return (0, import_node_path24.join)(installRoot(), "Update.exe");
60924
+ return (0, import_node_path25.join)(installRoot(), "Update.exe");
60820
60925
  }
60821
60926
  function packagesDir() {
60822
- return (0, import_node_path24.join)(installRoot(), "packages");
60927
+ return (0, import_node_path25.join)(installRoot(), "packages");
60823
60928
  }
60824
60929
  function feedUrl() {
60825
60930
  const env2 = (process.env.FLOLESS_UPDATE_URL ?? "").trim().replace(/\/+$/, "");
@@ -60911,23 +61016,23 @@ async function checkForUpdate() {
60911
61016
  return { supported: true, currentVersion: cur, updateAvailable: true, targetVersion: latest.Version, asset: latest };
60912
61017
  }
60913
61018
  async function sha1OfFile(path) {
60914
- const hash = (0, import_node_crypto6.createHash)("sha1");
60915
- await (0, import_promises.pipeline)((0, import_node_fs27.createReadStream)(path), hash);
61019
+ const hash = (0, import_node_crypto7.createHash)("sha1");
61020
+ await (0, import_promises.pipeline)((0, import_node_fs28.createReadStream)(path), hash);
60916
61021
  return hash.digest("hex").toUpperCase();
60917
61022
  }
60918
61023
  async function downloadPackage(asset) {
60919
61024
  if (!NUPKG_NAME.test(asset.FileName)) throw new Error(`refusing suspicious package name: ${asset.FileName}`);
60920
61025
  const want = asset.SHA1.toUpperCase();
60921
61026
  const dir = packagesDir();
60922
- (0, import_node_fs27.mkdirSync)(dir, { recursive: true });
60923
- const dest = (0, import_node_path24.join)(dir, asset.FileName);
60924
- if ((0, import_node_fs27.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
61027
+ (0, import_node_fs28.mkdirSync)(dir, { recursive: true });
61028
+ const dest = (0, import_node_path25.join)(dir, asset.FileName);
61029
+ if ((0, import_node_fs28.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
60925
61030
  const res = await authedFetch(`${feedUrl()}/${encodeURIComponent(asset.FileName)}`, {
60926
61031
  redirect: "follow",
60927
61032
  signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
60928
61033
  });
60929
61034
  if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status} for ${asset.FileName}`);
60930
- await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0, import_node_fs27.createWriteStream)(dest));
61035
+ await (0, import_promises.pipeline)(import_node_stream3.Readable.fromWeb(res.body), (0, import_node_fs28.createWriteStream)(dest));
60931
61036
  const got = await sha1OfFile(dest);
60932
61037
  if (got !== want) throw new Error(`SHA1 mismatch for ${asset.FileName}: feed=${want} got=${got}`);
60933
61038
  return dest;
@@ -60936,7 +61041,7 @@ async function applyUpdate(check, opts) {
60936
61041
  if (!check.supported) return { applied: false, message: check.reason ?? "auto-update not supported in this runtime" };
60937
61042
  if (!check.updateAvailable || !check.asset) return { applied: false, message: check.reason ?? "no update available" };
60938
61043
  const exe = updateExePath();
60939
- if (!(0, import_node_fs27.existsSync)(exe)) {
61044
+ if (!(0, import_node_fs28.existsSync)(exe)) {
60940
61045
  return { applied: false, message: `Update.exe not found at ${exe} \u2014 is this a Velopack install?` };
60941
61046
  }
60942
61047
  const pkg = await downloadPackage(check.asset);
@@ -61176,12 +61281,12 @@ function isTraceCorrupt(events) {
61176
61281
 
61177
61282
  // launch.mjs
61178
61283
  var import_node_child_process7 = require("node:child_process");
61179
- var import_node_path25 = require("node:path");
61284
+ var import_node_path26 = require("node:path");
61180
61285
  var import_node_url3 = require("node:url");
61181
- var import_node_fs28 = require("node:fs");
61286
+ var import_node_fs29 = require("node:fs");
61182
61287
  var import_node_http = __toESM(require("node:http"), 1);
61183
61288
  var import_node_readline = require("node:readline");
61184
- var __dirname2 = (0, import_node_path25.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
61289
+ var __dirname2 = (0, import_node_path26.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
61185
61290
  var PORT = Number(process.env.PORT ?? 4317);
61186
61291
  var HEALTH_URL = `http://127.0.0.1:${PORT}/api/health`;
61187
61292
  var BROWSER_URL = `http://floless.localhost:${PORT}`;
@@ -61253,8 +61358,8 @@ async function waitHealthy(timeoutMs = 3e4) {
61253
61358
  function resolveServerStart() {
61254
61359
  const packaged = /flolessapp\.exe$/i.test(process.execPath);
61255
61360
  if (packaged) return { cmd: process.execPath, args: ["--serve"], shell: false };
61256
- const bundle = (0, import_node_path25.join)(__dirname2, "dist", "floless-server.cjs");
61257
- if ((0, import_node_fs28.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
61361
+ const bundle = (0, import_node_path26.join)(__dirname2, "dist", "floless-server.cjs");
61362
+ if ((0, import_node_fs29.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
61258
61363
  return { cmd: "npm", args: ["run", "start"], shell: isWin2 };
61259
61364
  }
61260
61365
  function startServerDetached() {
@@ -61407,8 +61512,8 @@ function taskkillArgs(pid, { tree = true } = {}) {
61407
61512
  }
61408
61513
  function killSupervisor({ tree = true } = {}) {
61409
61514
  if (!isWin2) return;
61410
- const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path25.basename)(process.execPath));
61411
- const scriptMatch = isNpmChannel ? (0, import_node_path25.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
61515
+ const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path26.basename)(process.execPath));
61516
+ const scriptMatch = isNpmChannel ? (0, import_node_path26.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
61412
61517
  const realExe = resolveRealInstallExe(process.execPath);
61413
61518
  const exeMatch = realExe === process.execPath ? process.execPath : [process.execPath, realExe];
61414
61519
  const pids = supervisorPidsToKill(enumerateProcesses(), process.pid, exeMatch, scriptMatch);
@@ -61573,7 +61678,7 @@ async function runAction(arg, flagArgv = [], selfVersion = null) {
61573
61678
  }
61574
61679
  await action(parseTeardownFlags(flagArgv));
61575
61680
  }
61576
- var entry = (0, import_node_path25.basename)(process.argv[1] ?? "").toLowerCase();
61681
+ var entry = (0, import_node_path26.basename)(process.argv[1] ?? "").toLowerCase();
61577
61682
  if (entry === "launch.mjs") {
61578
61683
  runAction(process.argv[2], process.argv.slice(3)).catch((e) => {
61579
61684
  log(`error: ${e?.message ?? e}`);
@@ -61647,9 +61752,9 @@ function awareUpgradeBlockReason(s) {
61647
61752
  }
61648
61753
 
61649
61754
  // skill-sync.ts
61650
- var import_node_fs29 = require("node:fs");
61651
- var import_node_os18 = require("node:os");
61652
- var import_node_path26 = require("node:path");
61755
+ var import_node_fs30 = require("node:fs");
61756
+ var import_node_os19 = require("node:os");
61757
+ var import_node_path27 = require("node:path");
61653
61758
  var import_node_url4 = require("node:url");
61654
61759
  var import_yaml8 = __toESM(require_dist6(), 1);
61655
61760
 
@@ -61692,30 +61797,30 @@ function selectShippedSkillNames(names) {
61692
61797
  }
61693
61798
 
61694
61799
  // skill-sync.ts
61695
- var __dirname3 = (0, import_node_path26.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
61800
+ var __dirname3 = (0, import_node_path27.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
61696
61801
  function bundledSkillsRoot() {
61697
61802
  const candidates = [
61698
- (0, import_node_path26.join)(__dirname3, "skills"),
61699
- (0, import_node_path26.join)((0, import_node_path26.dirname)(process.execPath), "skills"),
61700
- (0, import_node_path26.join)(__dirname3, "..", ".claude", "skills")
61803
+ (0, import_node_path27.join)(__dirname3, "skills"),
61804
+ (0, import_node_path27.join)((0, import_node_path27.dirname)(process.execPath), "skills"),
61805
+ (0, import_node_path27.join)(__dirname3, "..", ".claude", "skills")
61701
61806
  ];
61702
- return candidates.find((p) => (0, import_node_fs29.existsSync)(p)) ?? null;
61807
+ return candidates.find((p) => (0, import_node_fs30.existsSync)(p)) ?? null;
61703
61808
  }
61704
61809
  function targetConfigDirs() {
61705
61810
  const override = process.env.FLOLESS_SKILL_TARGETS;
61706
61811
  if (override) {
61707
61812
  return override.split(";").map((d) => d.trim()).filter(Boolean).map((dir) => ({ runtime: "custom", dir }));
61708
61813
  }
61709
- const home = (0, import_node_os18.homedir)();
61814
+ const home = (0, import_node_os19.homedir)();
61710
61815
  return [
61711
- { runtime: "claude", dir: (0, import_node_path26.join)(home, ".claude") },
61712
- { runtime: "codex", dir: (0, import_node_path26.join)(home, ".codex") },
61713
- { runtime: "opencode", dir: (0, import_node_path26.join)(home, ".opencode") }
61816
+ { runtime: "claude", dir: (0, import_node_path27.join)(home, ".claude") },
61817
+ { runtime: "codex", dir: (0, import_node_path27.join)(home, ".codex") },
61818
+ { runtime: "opencode", dir: (0, import_node_path27.join)(home, ".opencode") }
61714
61819
  ];
61715
61820
  }
61716
61821
  function skillVersion(skillMdPath) {
61717
61822
  try {
61718
- const text = (0, import_node_fs29.readFileSync)(skillMdPath, "utf8");
61823
+ const text = (0, import_node_fs30.readFileSync)(skillMdPath, "utf8");
61719
61824
  const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
61720
61825
  if (!m || m[1] === void 0) return null;
61721
61826
  const fm = (0, import_yaml8.parse)(m[1]);
@@ -61755,21 +61860,21 @@ function decideAction(installed, bundled) {
61755
61860
  function bundledSkills(root) {
61756
61861
  let entries = [];
61757
61862
  try {
61758
- entries = selectShippedSkillNames((0, import_node_fs29.readdirSync)(root));
61863
+ entries = selectShippedSkillNames((0, import_node_fs30.readdirSync)(root));
61759
61864
  } catch {
61760
61865
  return [];
61761
61866
  }
61762
61867
  const out = [];
61763
61868
  for (const name of entries) {
61764
- const dir = (0, import_node_path26.join)(root, name);
61869
+ const dir = (0, import_node_path27.join)(root, name);
61765
61870
  let isDir = false;
61766
61871
  try {
61767
- isDir = (0, import_node_fs29.statSync)(dir).isDirectory();
61872
+ isDir = (0, import_node_fs30.statSync)(dir).isDirectory();
61768
61873
  } catch {
61769
61874
  isDir = false;
61770
61875
  }
61771
61876
  if (!isDir) continue;
61772
- const v = skillVersion((0, import_node_path26.join)(dir, "SKILL.md"));
61877
+ const v = skillVersion((0, import_node_path27.join)(dir, "SKILL.md"));
61773
61878
  if (!v) continue;
61774
61879
  out.push({ name, dir, version: v });
61775
61880
  }
@@ -61782,17 +61887,17 @@ function syncSkills() {
61782
61887
  const skills = bundledSkills(root);
61783
61888
  if (!skills.length) return results;
61784
61889
  for (const { runtime, dir: cfg } of targetConfigDirs()) {
61785
- if (!(0, import_node_fs29.existsSync)(cfg)) continue;
61786
- const skillsDir = (0, import_node_path26.join)(cfg, "skills");
61890
+ if (!(0, import_node_fs30.existsSync)(cfg)) continue;
61891
+ const skillsDir = (0, import_node_path27.join)(cfg, "skills");
61787
61892
  for (const s of skills) {
61788
- const dest = (0, import_node_path26.join)(skillsDir, s.name);
61789
- const installedMd = (0, import_node_path26.join)(dest, "SKILL.md");
61790
- const installed = (0, import_node_fs29.existsSync)(installedMd) ? skillVersion(installedMd) : null;
61893
+ const dest = (0, import_node_path27.join)(skillsDir, s.name);
61894
+ const installedMd = (0, import_node_path27.join)(dest, "SKILL.md");
61895
+ const installed = (0, import_node_fs30.existsSync)(installedMd) ? skillVersion(installedMd) : null;
61791
61896
  const action = decideAction(installed, s.version);
61792
61897
  if (action === "installed" || action === "updated") {
61793
61898
  try {
61794
- if (action === "updated") (0, import_node_fs29.rmSync)(dest, { recursive: true, force: true });
61795
- (0, import_node_fs29.cpSync)(s.dir, dest, { recursive: true });
61899
+ if (action === "updated") (0, import_node_fs30.rmSync)(dest, { recursive: true, force: true });
61900
+ (0, import_node_fs30.cpSync)(s.dir, dest, { recursive: true });
61796
61901
  results.push({ runtime, skill: s.name, action, from: installed, to: s.version });
61797
61902
  } catch {
61798
61903
  }
@@ -61805,9 +61910,9 @@ function syncSkills() {
61805
61910
  }
61806
61911
 
61807
61912
  // watch.ts
61808
- var import_node_os19 = require("node:os");
61809
- var import_node_path28 = require("node:path");
61810
- var import_node_fs30 = require("node:fs");
61913
+ var import_node_os20 = require("node:os");
61914
+ var import_node_path29 = require("node:path");
61915
+ var import_node_fs31 = require("node:fs");
61811
61916
 
61812
61917
  // node_modules/chokidar/esm/index.js
61813
61918
  var import_fs2 = require("fs");
@@ -61818,7 +61923,7 @@ var sysPath2 = __toESM(require("path"), 1);
61818
61923
  // node_modules/readdirp/esm/index.js
61819
61924
  var import_promises2 = require("node:fs/promises");
61820
61925
  var import_node_stream4 = require("node:stream");
61821
- var import_node_path27 = require("node:path");
61926
+ var import_node_path28 = require("node:path");
61822
61927
  var EntryTypes = {
61823
61928
  FILE_TYPE: "files",
61824
61929
  DIR_TYPE: "directories",
@@ -61893,7 +61998,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
61893
61998
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
61894
61999
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
61895
62000
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
61896
- this._root = (0, import_node_path27.resolve)(root);
62001
+ this._root = (0, import_node_path28.resolve)(root);
61897
62002
  this._isDirent = !opts.alwaysStat;
61898
62003
  this._statsProp = this._isDirent ? "dirent" : "stats";
61899
62004
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
@@ -61964,8 +62069,8 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
61964
62069
  let entry2;
61965
62070
  const basename5 = this._isDirent ? dirent.name : dirent;
61966
62071
  try {
61967
- const fullPath = (0, import_node_path27.resolve)((0, import_node_path27.join)(path, basename5));
61968
- entry2 = { path: (0, import_node_path27.relative)(this._root, fullPath), fullPath, basename: basename5 };
62072
+ const fullPath = (0, import_node_path28.resolve)((0, import_node_path28.join)(path, basename5));
62073
+ entry2 = { path: (0, import_node_path28.relative)(this._root, fullPath), fullPath, basename: basename5 };
61969
62074
  entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
61970
62075
  } catch (err2) {
61971
62076
  this._onError(err2);
@@ -61999,7 +62104,7 @@ var ReaddirpStream = class extends import_node_stream4.Readable {
61999
62104
  }
62000
62105
  if (entryRealPathStats.isDirectory()) {
62001
62106
  const len2 = entryRealPath.length;
62002
- if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path27.sep) {
62107
+ if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path28.sep) {
62003
62108
  const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
62004
62109
  recursiveError.code = RECURSIVE_ERROR_CODE;
62005
62110
  return this._onError(recursiveError);
@@ -62538,9 +62643,9 @@ var NodeFsHandler = class {
62538
62643
  if (this.fsw.closed) {
62539
62644
  return;
62540
62645
  }
62541
- const dirname14 = sysPath.dirname(file);
62646
+ const dirname15 = sysPath.dirname(file);
62542
62647
  const basename5 = sysPath.basename(file);
62543
- const parent = this.fsw._getWatchedDir(dirname14);
62648
+ const parent = this.fsw._getWatchedDir(dirname15);
62544
62649
  let prevStats = stats;
62545
62650
  if (parent.has(basename5))
62546
62651
  return;
@@ -62567,7 +62672,7 @@ var NodeFsHandler = class {
62567
62672
  prevStats = newStats2;
62568
62673
  }
62569
62674
  } catch (error) {
62570
- this.fsw._remove(dirname14, basename5);
62675
+ this.fsw._remove(dirname15, basename5);
62571
62676
  }
62572
62677
  } else if (parent.has(basename5)) {
62573
62678
  const at = newStats.atimeMs;
@@ -63507,33 +63612,33 @@ function appIdFromLogPath(path) {
63507
63612
  return i >= 0 && parts[i + 1] ? parts[i + 1] : null;
63508
63613
  }
63509
63614
  function samePath(a, b) {
63510
- const ra = (0, import_node_path28.resolve)(a);
63511
- const rb = (0, import_node_path28.resolve)(b);
63615
+ const ra = (0, import_node_path29.resolve)(a);
63616
+ const rb = (0, import_node_path29.resolve)(b);
63512
63617
  return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
63513
63618
  }
63514
63619
  function underDir(path, dir) {
63515
- const rp = (0, import_node_path28.resolve)(path);
63516
- const rd = (0, import_node_path28.resolve)(dir);
63620
+ const rp = (0, import_node_path29.resolve)(path);
63621
+ const rd = (0, import_node_path29.resolve)(dir);
63517
63622
  const [p, d] = process.platform === "win32" ? [rp.toLowerCase(), rd.toLowerCase()] : [rp, rd];
63518
- return p === d || p.startsWith(d + import_node_path28.sep);
63623
+ return p === d || p.startsWith(d + import_node_path29.sep);
63519
63624
  }
63520
63625
  function startWatcher() {
63521
- const awareDir = process.env.AWARE_HOME ?? (0, import_node_path28.join)((0, import_node_os19.homedir)(), ".aware");
63522
- const credentialsDir = (0, import_node_path28.join)(awareDir, "credentials");
63523
- if (!(0, import_node_fs30.existsSync)(credentialsDir)) {
63626
+ const awareDir = process.env.AWARE_HOME ?? (0, import_node_path29.join)((0, import_node_os20.homedir)(), ".aware");
63627
+ const credentialsDir = (0, import_node_path29.join)(awareDir, "credentials");
63628
+ if (!(0, import_node_fs31.existsSync)(credentialsDir)) {
63524
63629
  try {
63525
- (0, import_node_fs30.mkdirSync)(credentialsDir, { recursive: true });
63630
+ (0, import_node_fs31.mkdirSync)(credentialsDir, { recursive: true });
63526
63631
  } catch {
63527
63632
  }
63528
63633
  }
63529
- if (!(0, import_node_fs30.existsSync)(uiDir)) {
63634
+ if (!(0, import_node_fs31.existsSync)(uiDir)) {
63530
63635
  try {
63531
- (0, import_node_fs30.mkdirSync)(uiDir, { recursive: true });
63636
+ (0, import_node_fs31.mkdirSync)(uiDir, { recursive: true });
63532
63637
  } catch {
63533
63638
  }
63534
63639
  }
63535
- const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path28.join)(awareDir, d)).filter((p) => (0, import_node_fs30.existsSync)(p));
63536
- if ((0, import_node_fs30.existsSync)(uiDir)) targets.push(uiDir);
63640
+ const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path29.join)(awareDir, d)).filter((p) => (0, import_node_fs31.existsSync)(p));
63641
+ if ((0, import_node_fs31.existsSync)(uiDir)) targets.push(uiDir);
63537
63642
  if (targets.length === 0) {
63538
63643
  return null;
63539
63644
  }
@@ -63562,11 +63667,11 @@ function startWatcher() {
63562
63667
  const isCredential = path.split(/[\\/]/).includes("credentials");
63563
63668
  const kind = isCredential ? "credential" : path.endsWith(".jsonl") ? "trace" : path.endsWith(".lock") ? "lock" : path.endsWith(".flo") || path.endsWith(".app") ? "source" : "file";
63564
63669
  broadcast({ type: "fs-change", kind, event, path });
63565
- if (kind === "trace" && event !== "unlink" && (0, import_node_fs30.existsSync)(path)) {
63670
+ if (kind === "trace" && event !== "unlink" && (0, import_node_fs31.existsSync)(path)) {
63566
63671
  const id = appIdFromLogPath(path);
63567
63672
  if (!id) return;
63568
63673
  try {
63569
- broadcast({ type: "trace-file", id, runId: path.split(import_node_path28.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs30.readFileSync)(path, "utf8")) });
63674
+ broadcast({ type: "trace-file", id, runId: path.split(import_node_path29.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs31.readFileSync)(path, "utf8")) });
63570
63675
  } catch {
63571
63676
  }
63572
63677
  }
@@ -63575,10 +63680,10 @@ function startWatcher() {
63575
63680
  }
63576
63681
 
63577
63682
  // index.ts
63578
- var __dirname4 = (0, import_node_path29.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
63579
- var WEB_ROOT = [(0, import_node_path29.join)(__dirname4, "web"), (0, import_node_path29.join)((0, import_node_path29.dirname)(process.execPath), "web"), (0, import_node_path29.join)(__dirname4, "..", "web")].find(
63580
- (p) => (0, import_node_fs31.existsSync)(p)
63581
- ) ?? (0, import_node_path29.join)(__dirname4, "..", "web");
63683
+ var __dirname4 = (0, import_node_path30.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
63684
+ var WEB_ROOT = [(0, import_node_path30.join)(__dirname4, "web"), (0, import_node_path30.join)((0, import_node_path30.dirname)(process.execPath), "web"), (0, import_node_path30.join)(__dirname4, "..", "web")].find(
63685
+ (p) => (0, import_node_fs32.existsSync)(p)
63686
+ ) ?? (0, import_node_path30.join)(__dirname4, "..", "web");
63582
63687
  var PORT2 = Number(process.env.PORT ?? 4317);
63583
63688
  var HOST = "127.0.0.1";
63584
63689
  var crashHandlersInstalled = false;
@@ -63594,7 +63699,7 @@ function installCrashHandlers() {
63594
63699
  ${stack}
63595
63700
  `;
63596
63701
  try {
63597
- (0, import_node_fs31.appendFileSync)(logFilePath(), line);
63702
+ (0, import_node_fs32.appendFileSync)(logFilePath(), line);
63598
63703
  } catch {
63599
63704
  }
63600
63705
  if (process.stderr.isTTY) process.stderr.write(line);
@@ -63888,9 +63993,9 @@ async function startServer() {
63888
63993
  const { id, templateId, templatePath, srcPath, appDirPath: appDirPath2, fromVersion, contract, verb } = opts;
63889
63994
  const bdir = backupDir(id, fromVersion, Date.now());
63890
63995
  try {
63891
- (0, import_node_fs31.mkdirSync)((0, import_node_path29.dirname)(bdir), { recursive: true });
63892
- (0, import_node_fs31.cpSync)(appDirPath2, bdir, { recursive: true });
63893
- (0, import_node_fs31.cpSync)(templatePath, srcPath);
63996
+ (0, import_node_fs32.mkdirSync)((0, import_node_path30.dirname)(bdir), { recursive: true });
63997
+ (0, import_node_fs32.cpSync)(appDirPath2, bdir, { recursive: true });
63998
+ (0, import_node_fs32.cpSync)(templatePath, srcPath);
63894
63999
  if (id !== templateId) stampSourceAppId(srcPath, id);
63895
64000
  if (contract != null) {
63896
64001
  bakeContractIntoApp(srcPath, contract);
@@ -63901,8 +64006,8 @@ async function startServer() {
63901
64006
  } catch (e) {
63902
64007
  const msg = e instanceof Error ? e.message : String(e);
63903
64008
  try {
63904
- (0, import_node_fs31.rmSync)(appDirPath2, { recursive: true, force: true });
63905
- (0, import_node_fs31.cpSync)(bdir, appDirPath2, { recursive: true });
64009
+ (0, import_node_fs32.rmSync)(appDirPath2, { recursive: true, force: true });
64010
+ (0, import_node_fs32.cpSync)(bdir, appDirPath2, { recursive: true });
63906
64011
  } catch (re) {
63907
64012
  const rmsg = re instanceof Error ? re.message : String(re);
63908
64013
  throw new TemplateSwapError(`${verb} failed (${msg}) AND rollback failed (${rmsg}) \u2014 restore manually from ${bdir}`, "rollback-failed", bdir);
@@ -63933,7 +64038,7 @@ async function startServer() {
63933
64038
  return reply.status(409).send({ ok: false, error: `"${id}" is already at ${fromVersion}`, code: "up-to-date" });
63934
64039
  }
63935
64040
  const contract = readContract(id);
63936
- if (contract == null && (0, import_node_fs31.existsSync)(contractPath(id))) {
64041
+ if (contract == null && (0, import_node_fs32.existsSync)(contractPath(id))) {
63937
64042
  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" });
63938
64043
  }
63939
64044
  if (contract != null) {
@@ -64067,8 +64172,67 @@ async function startServer() {
64067
64172
  app.get("/api/app/:id", async (req) => {
64068
64173
  return { ok: true, app: readApp(req.params.id) };
64069
64174
  });
64175
+ app.get("/api/projects", async () => ({ ok: true, projects: listProjects() }));
64176
+ app.post(
64177
+ "/api/projects",
64178
+ async (req, reply) => {
64179
+ try {
64180
+ const project = createProject({ name: req.body?.name, app: req.body?.app });
64181
+ let seeded = false;
64182
+ if (req.body?.seedFromApp) {
64183
+ const legacy = readContract(project.app);
64184
+ if (legacy != null) {
64185
+ writeContract(project.app, legacy, project.id);
64186
+ seeded = true;
64187
+ }
64188
+ }
64189
+ return { ok: true, project, seeded };
64190
+ } catch (e) {
64191
+ if (e instanceof ProjectError || e instanceof ContractError) {
64192
+ return reply.status(400).send({ ok: false, error: e.message });
64193
+ }
64194
+ throw e;
64195
+ }
64196
+ }
64197
+ );
64198
+ app.patch("/api/projects/:id", async (req, reply) => {
64199
+ try {
64200
+ return { ok: true, project: renameProject(req.params.id, req.body?.name) };
64201
+ } catch (e) {
64202
+ if (e instanceof ProjectError) return reply.status(400).send({ ok: false, error: e.message });
64203
+ throw e;
64204
+ }
64205
+ });
64206
+ app.post("/api/projects/:id/duplicate", async (req, reply) => {
64207
+ try {
64208
+ return { ok: true, project: duplicateProject(req.params.id, req.body?.name) };
64209
+ } catch (e) {
64210
+ if (e instanceof ProjectError) return reply.status(400).send({ ok: false, error: e.message });
64211
+ throw e;
64212
+ }
64213
+ });
64214
+ app.post("/api/projects/:id/archive", async (req, reply) => {
64215
+ try {
64216
+ archiveProject(req.params.id);
64217
+ return { ok: true };
64218
+ } catch (e) {
64219
+ if (e instanceof ProjectError) return reply.status(400).send({ ok: false, error: e.message });
64220
+ throw e;
64221
+ }
64222
+ });
64223
+ function projectAppMismatch(appId, project) {
64224
+ const p = getProject(project);
64225
+ if (!p) return `unknown project: ${project}`;
64226
+ if (p.app !== appId) return `project "${project}" belongs to app "${p.app}", not "${appId}"`;
64227
+ return null;
64228
+ }
64070
64229
  app.get("/api/contract/:appId", async (req, reply) => {
64071
- const doc = readContractForApp(req.params.appId);
64230
+ const project = req.query.project || void 0;
64231
+ if (project) {
64232
+ const bad = projectAppMismatch(req.params.appId, project);
64233
+ if (bad) return reply.status(404).send({ ok: false, error: bad });
64234
+ }
64235
+ const doc = project ? readContract(req.params.appId, project) : readContractForApp(req.params.appId);
64072
64236
  if (doc == null) return reply.status(404).send({ ok: false, error: "no contract for this app yet" });
64073
64237
  if (doc && typeof doc === "object" && doc.type === "drawing.vector/v1") {
64074
64238
  return postProcess(doc);
@@ -64080,18 +64244,29 @@ async function startServer() {
64080
64244
  { bodyLimit: 25 * 1024 * 1024 },
64081
64245
  // contracts embed rasters
64082
64246
  async (req, reply) => {
64247
+ const project = req.query.project || void 0;
64248
+ if (project) {
64249
+ const bad = projectAppMismatch(req.params.appId, project);
64250
+ if (bad) return reply.status(404).send({ ok: false, error: bad });
64251
+ }
64083
64252
  try {
64084
- writeContract(req.params.appId, req.body);
64253
+ writeContract(req.params.appId, req.body, project);
64085
64254
  } catch (e) {
64086
64255
  if (e instanceof ContractError) return reply.status(400).send({ ok: false, error: e.message });
64087
64256
  throw e;
64088
64257
  }
64089
- broadcast({ type: "contract-changed", appId: req.params.appId });
64258
+ if (project) touchProject(project);
64259
+ broadcast({ type: "contract-changed", appId: req.params.appId, project });
64090
64260
  return { ok: true };
64091
64261
  }
64092
64262
  );
64093
64263
  app.post("/api/contract/:appId/approve", async (req, reply) => {
64094
- const doc = readContract(req.params.appId);
64264
+ const project = req.query.project || void 0;
64265
+ if (project) {
64266
+ const bad = projectAppMismatch(req.params.appId, project);
64267
+ if (bad) return reply.status(404).send({ ok: false, error: bad });
64268
+ }
64269
+ const doc = readContract(req.params.appId, project);
64095
64270
  if (doc == null) return reply.status(404).send({ ok: false, error: "no contract to approve" });
64096
64271
  const v = validateContract(doc);
64097
64272
  if (!v.valid) return reply.status(400).send({ ok: false, error: "stored contract is invalid \u2014 re-save it in the editor" });
@@ -64247,7 +64422,7 @@ async function startServer() {
64247
64422
  }
64248
64423
  const companionId = `${req.params.appId}-ifc`;
64249
64424
  const filename = `${req.params.appId}.ifc`;
64250
- const outPath = (0, import_node_path29.join)(appPath(companionId), filename);
64425
+ const outPath = (0, import_node_path30.join)(appPath(companionId), filename);
64251
64426
  let flo;
64252
64427
  try {
64253
64428
  flo = writeIfcApp(appPath(companionId), companionId, scene, outPath, writeOpts);
@@ -64270,8 +64445,8 @@ async function startServer() {
64270
64445
  }
64271
64446
  throw e;
64272
64447
  }
64273
- if (!(0, import_node_fs31.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
64274
- const content = (0, import_node_fs31.readFileSync)(outPath, "utf8");
64448
+ if (!(0, import_node_fs32.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
64449
+ const content = (0, import_node_fs32.readFileSync)(outPath, "utf8");
64275
64450
  broadcast({ type: "apps-changed" });
64276
64451
  return { ok: true, filename, content, bytes: Buffer.byteLength(content), skipped, ...extrusionsSkipped ? { extrusionsSkipped } : {} };
64277
64452
  });
@@ -64350,17 +64525,17 @@ async function startServer() {
64350
64525
  return reply.status(422).send({ ok: false, error: "no priced members to export \u2014 every member is an RFI (no AISC size / weight yet)" });
64351
64526
  }
64352
64527
  const outPath = bomExportPath(appId, format);
64353
- const dir = (0, import_node_path29.dirname)(outPath);
64528
+ const dir = (0, import_node_path30.dirname)(outPath);
64354
64529
  const filename = `${appId}-bom.${format}`;
64355
64530
  try {
64356
- (0, import_node_fs31.mkdirSync)(dir, { recursive: true });
64531
+ (0, import_node_fs32.mkdirSync)(dir, { recursive: true });
64357
64532
  if (format === "csv") {
64358
64533
  const text = bomToCsv(bom);
64359
- (0, import_node_fs31.writeFileSync)(outPath, text, "utf8");
64534
+ (0, import_node_fs32.writeFileSync)(outPath, text, "utf8");
64360
64535
  return { ok: true, filename, encoding: "utf8", content: text, bytes: Buffer.byteLength(text), savedTo: outPath };
64361
64536
  }
64362
64537
  const buf = await bomToXlsx(bom);
64363
- (0, import_node_fs31.writeFileSync)(outPath, buf);
64538
+ (0, import_node_fs32.writeFileSync)(outPath, buf);
64364
64539
  return { ok: true, filename, encoding: "base64", content: buf.toString("base64"), bytes: buf.length, savedTo: outPath };
64365
64540
  } catch (e) {
64366
64541
  app.log.error({ appId, format, err: e instanceof Error ? e.message : e }, "export-bom: generation failed");
@@ -64430,7 +64605,7 @@ async function startServer() {
64430
64605
  return reply.status(404).send({ ok: false, error: `"${id}" is not installed`, code: "not-installed" });
64431
64606
  }
64432
64607
  const contract = readContract(id);
64433
- if (contract == null && (0, import_node_fs31.existsSync)(contractPath(id))) {
64608
+ if (contract == null && (0, import_node_fs32.existsSync)(contractPath(id))) {
64434
64609
  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" });
64435
64610
  }
64436
64611
  if (contract != null) {
@@ -64508,11 +64683,11 @@ async function startServer() {
64508
64683
  if (appExists(id)) {
64509
64684
  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 });
64510
64685
  }
64511
- const stageRoot = (0, import_node_fs31.mkdtempSync)((0, import_node_path29.join)((0, import_node_os20.tmpdir)(), "floless-import-"));
64686
+ const stageRoot = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os21.tmpdir)(), "floless-import-"));
64512
64687
  try {
64513
- const stageDir = (0, import_node_path29.join)(stageRoot, id);
64514
- (0, import_node_fs31.mkdirSync)(stageDir);
64515
- (0, import_node_fs31.writeFileSync)((0, import_node_path29.join)(stageDir, `${id}.flo`), content);
64688
+ const stageDir = (0, import_node_path30.join)(stageRoot, id);
64689
+ (0, import_node_fs32.mkdirSync)(stageDir);
64690
+ (0, import_node_fs32.writeFileSync)((0, import_node_path30.join)(stageDir, `${id}.flo`), content);
64516
64691
  await aware.install(stageDir);
64517
64692
  } catch (err2) {
64518
64693
  try {
@@ -64522,7 +64697,7 @@ async function startServer() {
64522
64697
  const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
64523
64698
  return reply.status(502).send({ ok: false, error: `import failed: ${msg}` });
64524
64699
  } finally {
64525
- (0, import_node_fs31.rmSync)(stageRoot, { recursive: true, force: true });
64700
+ (0, import_node_fs32.rmSync)(stageRoot, { recursive: true, force: true });
64526
64701
  }
64527
64702
  broadcast({ type: "apps-changed", id });
64528
64703
  return { ok: true, id };
@@ -64536,13 +64711,13 @@ async function startServer() {
64536
64711
  }
64537
64712
  const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
64538
64713
  const baked = bakeFloSource(appData.source.text, inputs);
64539
- const tmpRoot = (0, import_node_fs31.mkdtempSync)((0, import_node_path29.join)((0, import_node_os20.tmpdir)(), "floless-bake-"));
64540
- const backupDir2 = (0, import_node_path29.join)(tmpRoot, `${id}-backup`);
64541
- const bakeDir = (0, import_node_path29.join)(tmpRoot, id);
64542
- (0, import_node_fs31.cpSync)(appDir(id), backupDir2, { recursive: true });
64543
- (0, import_node_fs31.cpSync)(appDir(id), bakeDir, { recursive: true });
64714
+ const tmpRoot = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os21.tmpdir)(), "floless-bake-"));
64715
+ const backupDir2 = (0, import_node_path30.join)(tmpRoot, `${id}-backup`);
64716
+ const bakeDir = (0, import_node_path30.join)(tmpRoot, id);
64717
+ (0, import_node_fs32.cpSync)(appDir(id), backupDir2, { recursive: true });
64718
+ (0, import_node_fs32.cpSync)(appDir(id), bakeDir, { recursive: true });
64544
64719
  const floName = appData.source.path.split(/[\\/]/).pop();
64545
- (0, import_node_fs31.writeFileSync)((0, import_node_path29.join)(bakeDir, floName), baked);
64720
+ (0, import_node_fs32.writeFileSync)((0, import_node_path30.join)(bakeDir, floName), baked);
64546
64721
  let appInstalled2 = true;
64547
64722
  try {
64548
64723
  await aware.uninstall(id);
@@ -64564,17 +64739,17 @@ async function startServer() {
64564
64739
  throw installErr;
64565
64740
  }
64566
64741
  try {
64567
- await aware.compile((0, import_node_path29.join)(appDir(id), floName));
64742
+ await aware.compile((0, import_node_path30.join)(appDir(id), floName));
64568
64743
  } catch (compileErr) {
64569
64744
  app.log.warn({ id, compileErr: String(compileErr) }, "bake: post-install recompile failed (app baked but may need a manual Compile)");
64570
64745
  }
64571
64746
  broadcast({ type: "baked", id });
64572
64747
  return { ok: true, id, agent: id, inputs };
64573
64748
  } finally {
64574
- if (appInstalled2) (0, import_node_fs31.rmSync)(tmpRoot, { recursive: true, force: true });
64749
+ if (appInstalled2) (0, import_node_fs32.rmSync)(tmpRoot, { recursive: true, force: true });
64575
64750
  }
64576
64751
  });
64577
- const graftAgentsDir = () => (0, import_node_path29.join)((0, import_node_os20.homedir)(), ".aware", "agents");
64752
+ const graftAgentsDir = () => (0, import_node_path30.join)((0, import_node_os21.homedir)(), ".aware", "agents");
64578
64753
  app.post("/api/graft/match", async (req, reply) => {
64579
64754
  const { glob } = req.body ?? {};
64580
64755
  if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
@@ -64591,7 +64766,7 @@ async function startServer() {
64591
64766
  if (!sourceKind || !sourceRef) {
64592
64767
  return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
64593
64768
  }
64594
- const tempHome = (0, import_node_fs31.mkdtempSync)((0, import_node_path29.join)((0, import_node_os20.tmpdir)(), "floless-graft-"));
64769
+ const tempHome = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os21.tmpdir)(), "floless-graft-"));
64595
64770
  let result;
64596
64771
  try {
64597
64772
  result = await aware.build({
@@ -64604,19 +64779,19 @@ async function startServer() {
64604
64779
  awareHome: tempHome
64605
64780
  });
64606
64781
  } catch (err2) {
64607
- (0, import_node_fs31.rmSync)(tempHome, { recursive: true, force: true });
64782
+ (0, import_node_fs32.rmSync)(tempHome, { recursive: true, force: true });
64608
64783
  const msg = err2 instanceof AwareError ? err2.message : String(err2?.message ?? err2);
64609
64784
  return reply.status(422).send({ ok: false, error: msg });
64610
64785
  }
64611
64786
  const manifest = readStagedManifest(result.agentDir);
64612
64787
  if (!manifest) {
64613
- (0, import_node_fs31.rmSync)(tempHome, { recursive: true, force: true });
64788
+ (0, import_node_fs32.rmSync)(tempHome, { recursive: true, force: true });
64614
64789
  return reply.status(502).send({ ok: false, error: `build produced output at ${result.agentDir} but no manifest.yaml` });
64615
64790
  }
64616
- const token = (0, import_node_crypto7.randomUUID)();
64791
+ const token = (0, import_node_crypto8.randomUUID)();
64617
64792
  registerStage(token, tempHome, result.agentId);
64618
64793
  const preview = buildPreview(manifest, sourceKind, sourceRef, token);
64619
- if ((0, import_node_fs31.existsSync)((0, import_node_path29.join)(graftAgentsDir(), result.agentId))) {
64794
+ if ((0, import_node_fs32.existsSync)((0, import_node_path30.join)(graftAgentsDir(), result.agentId))) {
64620
64795
  preview.warnings.unshift(`An agent named "${result.agentId}" is already installed \u2014 creating it will overwrite it.`);
64621
64796
  }
64622
64797
  return { ok: true, preview };
@@ -64635,7 +64810,7 @@ async function startServer() {
64635
64810
  registerStage(stagedRef, stage.tempDir, stage.agentId);
64636
64811
  return reply.status(409).send({ ok: false, error: err2.message, agentId: stage.agentId, collision: true });
64637
64812
  }
64638
- (0, import_node_fs31.rmSync)(stage.tempDir, { recursive: true, force: true });
64813
+ (0, import_node_fs32.rmSync)(stage.tempDir, { recursive: true, force: true });
64639
64814
  throw err2;
64640
64815
  }
64641
64816
  broadcast({ type: "grafted", id: stage.agentId });
@@ -64906,11 +65081,11 @@ async function startServer() {
64906
65081
  app.get("/api/requests/:id/snapshot/:n", async (req, reply) => {
64907
65082
  const n = Number.parseInt(req.params.n, 10);
64908
65083
  const p = Number.isInteger(n) ? snapshotPathFor(req.params.id, n) : null;
64909
- if (!p || !(0, import_node_fs31.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
65084
+ if (!p || !(0, import_node_fs32.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
64910
65085
  const ext = p.split(".").pop().toLowerCase();
64911
65086
  reply.header("Content-Type", ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "pdf" ? "application/pdf" : "image/jpeg");
64912
65087
  reply.header("Cache-Control", "no-store");
64913
- return (0, import_node_fs31.readFileSync)(p);
65088
+ return (0, import_node_fs32.readFileSync)(p);
64914
65089
  });
64915
65090
  app.post(
64916
65091
  "/api/tweak",
@@ -64935,7 +65110,7 @@ async function startServer() {
64935
65110
  "/api/contract-request",
64936
65111
  { bodyLimit: 25 * 1024 * 1024 },
64937
65112
  async (req, reply) => {
64938
- const { appId, instruction, intent, target, snapshots } = req.body ?? {};
65113
+ const { appId, project, instruction, intent, target, snapshots } = req.body ?? {};
64939
65114
  if (!appId || !instruction) {
64940
65115
  return reply.status(400).send({ ok: false, error: "appId, instruction required" });
64941
65116
  }
@@ -64946,7 +65121,7 @@ async function startServer() {
64946
65121
  return reply.status(400).send({ ok: false, error: e instanceof Error ? e.message : "bad snapshot" });
64947
65122
  }
64948
65123
  const request = addRequest(
64949
- { type: "tweak-contract", appId, instruction, ...intent ? { intent } : {}, ...target ? { target } : {} },
65124
+ { type: "tweak-contract", appId, ...project ? { project } : {}, instruction, ...intent ? { intent } : {}, ...target ? { target } : {} },
64950
65125
  decoded
64951
65126
  );
64952
65127
  broadcast({ type: "request-added", request });
@@ -65079,7 +65254,7 @@ async function startServer() {
65079
65254
  warn(`last-run-status:${ref} \u2014 trace exists but couldn't be parsed (corrupt/truncated)`);
65080
65255
  let finishedAt2 = null;
65081
65256
  try {
65082
- finishedAt2 = (0, import_node_fs31.statSync)(latest.path).mtime.toISOString();
65257
+ finishedAt2 = (0, import_node_fs32.statSync)(latest.path).mtime.toISOString();
65083
65258
  } catch {
65084
65259
  finishedAt2 = null;
65085
65260
  }
@@ -65089,7 +65264,7 @@ async function startServer() {
65089
65264
  let finishedAt = typeof runEnd?.ts === "string" ? runEnd.ts : null;
65090
65265
  if (!finishedAt) {
65091
65266
  try {
65092
- finishedAt = (0, import_node_fs31.statSync)(latest.path).mtime.toISOString();
65267
+ finishedAt = (0, import_node_fs32.statSync)(latest.path).mtime.toISOString();
65093
65268
  } catch {
65094
65269
  finishedAt = null;
65095
65270
  }