@floless/app 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 } = require("worker_threads");
5492
- var { join: join28 } = require("path");
5492
+ var { join: join29 } = require("path");
5493
5493
  var { pathToFileURL } = require("url");
5494
5494
  var { wait } = require_wait();
5495
5495
  var {
@@ -5540,7 +5540,7 @@ var require_thread_stream = __commonJS({
5540
5540
  function createWorker(stream, opts) {
5541
5541
  const { filename, workerData } = opts;
5542
5542
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
5543
- const toExecute = bundlerOverrides["thread-stream-worker"] || join28(__dirname, "lib", "worker.js");
5543
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join29(__dirname, "lib", "worker.js");
5544
5544
  const worker = new Worker(toExecute, {
5545
5545
  ...opts.workerOpts,
5546
5546
  name: opts.workerOpts?.name || "thread-stream",
@@ -6006,10 +6006,10 @@ var require_transport = __commonJS({
6006
6006
  "node_modules/pino/lib/transport.js"(exports2, module2) {
6007
6007
  "use strict";
6008
6008
  var { createRequire: createRequire4 } = require("module");
6009
- var { existsSync: existsSync24 } = require("node:fs");
6009
+ var { existsSync: existsSync25 } = require("node:fs");
6010
6010
  var getCallers = require_caller();
6011
- var { join: join28, isAbsolute: isAbsolute2, sep: sep4 } = require("node:path");
6012
- var { fileURLToPath: fileURLToPath5 } = require("node:url");
6011
+ var { join: join29, isAbsolute: isAbsolute2, sep: sep4 } = require("node:path");
6012
+ var { fileURLToPath: fileURLToPath6 } = require("node:url");
6013
6013
  var sleep = require_atomic_sleep();
6014
6014
  var onExit = require_on_exit_leak_free();
6015
6015
  var ThreadStream = require_thread_stream();
@@ -6075,12 +6075,12 @@ var require_transport = __commonJS({
6075
6075
  let path = unquoted;
6076
6076
  if (path.startsWith("file://")) {
6077
6077
  try {
6078
- path = fileURLToPath5(path);
6078
+ path = fileURLToPath6(path);
6079
6079
  } catch {
6080
6080
  return false;
6081
6081
  }
6082
6082
  }
6083
- return isAbsolute2(path) && !existsSync24(path);
6083
+ return isAbsolute2(path) && !existsSync25(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"] || join28(__dirname, "worker.js");
6164
+ target = bundlerOverrides["pino-worker"] || join29(__dirname, "worker.js");
6165
6165
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
6166
6166
  return {
6167
6167
  ...dest,
@@ -6179,7 +6179,7 @@ var require_transport = __commonJS({
6179
6179
  });
6180
6180
  });
6181
6181
  } else if (pipeline2) {
6182
- target = bundlerOverrides["pino-worker"] || join28(__dirname, "worker.js");
6182
+ target = bundlerOverrides["pino-worker"] || join29(__dirname, "worker.js");
6183
6183
  options.pipelines = [pipeline2.map((dest) => {
6184
6184
  return {
6185
6185
  ...dest,
@@ -6202,7 +6202,7 @@ var require_transport = __commonJS({
6202
6202
  return origin;
6203
6203
  }
6204
6204
  if (origin === "pino/file") {
6205
- return join28(__dirname, "..", "file.js");
6205
+ return join29(__dirname, "..", "file.js");
6206
6206
  }
6207
6207
  let fixTarget2;
6208
6208
  for (const filePath of callers) {
@@ -7182,7 +7182,7 @@ var require_safe_stable_stringify = __commonJS({
7182
7182
  return circularValue;
7183
7183
  }
7184
7184
  let res = "";
7185
- let join28 = ",";
7185
+ let join29 = ",";
7186
7186
  const originalIndentation = indentation;
7187
7187
  if (Array.isArray(value)) {
7188
7188
  if (value.length === 0) {
@@ -7196,7 +7196,7 @@ var require_safe_stable_stringify = __commonJS({
7196
7196
  indentation += spacer;
7197
7197
  res += `
7198
7198
  ${indentation}`;
7199
- join28 = `,
7199
+ join29 = `,
7200
7200
  ${indentation}`;
7201
7201
  }
7202
7202
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -7204,13 +7204,13 @@ ${indentation}`;
7204
7204
  for (; i < maximumValuesToStringify - 1; i++) {
7205
7205
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
7206
7206
  res += tmp2 !== void 0 ? tmp2 : "null";
7207
- res += join28;
7207
+ res += join29;
7208
7208
  }
7209
7209
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
7210
7210
  res += tmp !== void 0 ? tmp : "null";
7211
7211
  if (value.length - 1 > maximumBreadth) {
7212
7212
  const removedKeys = value.length - maximumBreadth - 1;
7213
- res += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
7213
+ res += `${join29}"... ${getItemCount(removedKeys)} not stringified"`;
7214
7214
  }
7215
7215
  if (spacer !== "") {
7216
7216
  res += `
@@ -7231,7 +7231,7 @@ ${originalIndentation}`;
7231
7231
  let separator = "";
7232
7232
  if (spacer !== "") {
7233
7233
  indentation += spacer;
7234
- join28 = `,
7234
+ join29 = `,
7235
7235
  ${indentation}`;
7236
7236
  whitespace = " ";
7237
7237
  }
@@ -7245,13 +7245,13 @@ ${indentation}`;
7245
7245
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
7246
7246
  if (tmp !== void 0) {
7247
7247
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
7248
- separator = join28;
7248
+ separator = join29;
7249
7249
  }
7250
7250
  }
7251
7251
  if (keyLength > maximumBreadth) {
7252
7252
  const removedKeys = keyLength - maximumBreadth;
7253
7253
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
7254
- separator = join28;
7254
+ separator = join29;
7255
7255
  }
7256
7256
  if (spacer !== "" && separator.length > 1) {
7257
7257
  res = `
@@ -7292,7 +7292,7 @@ ${originalIndentation}`;
7292
7292
  }
7293
7293
  const originalIndentation = indentation;
7294
7294
  let res = "";
7295
- let join28 = ",";
7295
+ let join29 = ",";
7296
7296
  if (Array.isArray(value)) {
7297
7297
  if (value.length === 0) {
7298
7298
  return "[]";
@@ -7305,7 +7305,7 @@ ${originalIndentation}`;
7305
7305
  indentation += spacer;
7306
7306
  res += `
7307
7307
  ${indentation}`;
7308
- join28 = `,
7308
+ join29 = `,
7309
7309
  ${indentation}`;
7310
7310
  }
7311
7311
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -7313,13 +7313,13 @@ ${indentation}`;
7313
7313
  for (; i < maximumValuesToStringify - 1; i++) {
7314
7314
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
7315
7315
  res += tmp2 !== void 0 ? tmp2 : "null";
7316
- res += join28;
7316
+ res += join29;
7317
7317
  }
7318
7318
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
7319
7319
  res += tmp !== void 0 ? tmp : "null";
7320
7320
  if (value.length - 1 > maximumBreadth) {
7321
7321
  const removedKeys = value.length - maximumBreadth - 1;
7322
- res += `${join28}"... ${getItemCount(removedKeys)} not stringified"`;
7322
+ res += `${join29}"... ${getItemCount(removedKeys)} not stringified"`;
7323
7323
  }
7324
7324
  if (spacer !== "") {
7325
7325
  res += `
@@ -7332,7 +7332,7 @@ ${originalIndentation}`;
7332
7332
  let whitespace = "";
7333
7333
  if (spacer !== "") {
7334
7334
  indentation += spacer;
7335
- join28 = `,
7335
+ join29 = `,
7336
7336
  ${indentation}`;
7337
7337
  whitespace = " ";
7338
7338
  }
@@ -7341,7 +7341,7 @@ ${indentation}`;
7341
7341
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
7342
7342
  if (tmp !== void 0) {
7343
7343
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
7344
- separator = join28;
7344
+ separator = join29;
7345
7345
  }
7346
7346
  }
7347
7347
  if (spacer !== "" && separator.length > 1) {
@@ -7399,20 +7399,20 @@ ${originalIndentation}`;
7399
7399
  indentation += spacer;
7400
7400
  let res2 = `
7401
7401
  ${indentation}`;
7402
- const join29 = `,
7402
+ const join30 = `,
7403
7403
  ${indentation}`;
7404
7404
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
7405
7405
  let i = 0;
7406
7406
  for (; i < maximumValuesToStringify - 1; i++) {
7407
7407
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
7408
7408
  res2 += tmp2 !== void 0 ? tmp2 : "null";
7409
- res2 += join29;
7409
+ res2 += join30;
7410
7410
  }
7411
7411
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
7412
7412
  res2 += tmp !== void 0 ? tmp : "null";
7413
7413
  if (value.length - 1 > maximumBreadth) {
7414
7414
  const removedKeys = value.length - maximumBreadth - 1;
7415
- res2 += `${join29}"... ${getItemCount(removedKeys)} not stringified"`;
7415
+ res2 += `${join30}"... ${getItemCount(removedKeys)} not stringified"`;
7416
7416
  }
7417
7417
  res2 += `
7418
7418
  ${originalIndentation}`;
@@ -7428,16 +7428,16 @@ ${originalIndentation}`;
7428
7428
  return '"[Object]"';
7429
7429
  }
7430
7430
  indentation += spacer;
7431
- const join28 = `,
7431
+ const join29 = `,
7432
7432
  ${indentation}`;
7433
7433
  let res = "";
7434
7434
  let separator = "";
7435
7435
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
7436
7436
  if (isTypedArrayWithEntries(value)) {
7437
- res += stringifyTypedArray(value, join28, maximumBreadth);
7437
+ res += stringifyTypedArray(value, join29, maximumBreadth);
7438
7438
  keys = keys.slice(value.length);
7439
7439
  maximumPropertiesToStringify -= value.length;
7440
- separator = join28;
7440
+ separator = join29;
7441
7441
  }
7442
7442
  if (deterministic) {
7443
7443
  keys = sort(keys, comparator);
@@ -7448,13 +7448,13 @@ ${indentation}`;
7448
7448
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
7449
7449
  if (tmp !== void 0) {
7450
7450
  res += `${separator}${strEscape(key2)}: ${tmp}`;
7451
- separator = join28;
7451
+ separator = join29;
7452
7452
  }
7453
7453
  }
7454
7454
  if (keyLength > maximumBreadth) {
7455
7455
  const removedKeys = keyLength - maximumBreadth;
7456
7456
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
7457
- separator = join28;
7457
+ separator = join29;
7458
7458
  }
7459
7459
  if (separator !== "") {
7460
7460
  res = `
@@ -41991,7 +41991,7 @@ var require_send = __commonJS({
41991
41991
  var { parseTokenList } = require_parseTokenList();
41992
41992
  var { createHttpError } = require_createHttpError();
41993
41993
  var extname2 = path.extname;
41994
- var join28 = path.join;
41994
+ var join29 = path.join;
41995
41995
  var normalize2 = path.normalize;
41996
41996
  var resolve6 = path.resolve;
41997
41997
  var sep4 = path.sep;
@@ -42078,7 +42078,7 @@ var require_send = __commonJS({
42078
42078
  return { statusCode: 403 };
42079
42079
  }
42080
42080
  parts = path2.split(sep4);
42081
- path2 = normalize2(join28(root, path2));
42081
+ path2 = normalize2(join29(root, path2));
42082
42082
  } else {
42083
42083
  if (UP_PATH_REGEXP.test(path2)) {
42084
42084
  debug('malicious path "%s"', path2);
@@ -42361,7 +42361,7 @@ var require_send = __commonJS({
42361
42361
  let err;
42362
42362
  for (let i = 0; i < options.index.length; i++) {
42363
42363
  const index = options.index[i];
42364
- const p = join28(path2, index);
42364
+ const p = join29(path2, index);
42365
42365
  const { error, stat: stat4 } = await tryStat(p);
42366
42366
  if (error) {
42367
42367
  err = error;
@@ -43011,7 +43011,7 @@ var require_static = __commonJS({
43011
43011
  "node_modules/@fastify/static/index.js"(exports2, module2) {
43012
43012
  "use strict";
43013
43013
  var path = require("node:path");
43014
- var { fileURLToPath: fileURLToPath5 } = require("node:url");
43014
+ var { fileURLToPath: fileURLToPath6 } = require("node:url");
43015
43015
  var { statSync: statSync8 } = require("node:fs");
43016
43016
  var { glob } = require_commonjs6();
43017
43017
  var fp = require_plugin2();
@@ -43145,8 +43145,8 @@ var require_static = __commonJS({
43145
43145
  }
43146
43146
  }
43147
43147
  }
43148
- for (const [dirname11, rootPath] of indexDirs.entries()) {
43149
- const pathname = dirname11 + (dirname11.endsWith("/") ? "" : "/");
43148
+ for (const [dirname12, rootPath] of indexDirs.entries()) {
43149
+ const pathname = dirname12 + (dirname12.endsWith("/") ? "" : "/");
43150
43150
  const file = "/" + pathname.replace(prefix, "");
43151
43151
  setUpHeadAndGet(routeOpts, pathname, file, rootPath);
43152
43152
  if (opts.redirect === true) {
@@ -43330,13 +43330,13 @@ var require_static = __commonJS({
43330
43330
  return root;
43331
43331
  }
43332
43332
  if (root instanceof URL && root.protocol === "file:") {
43333
- return fileURLToPath5(root);
43333
+ return fileURLToPath6(root);
43334
43334
  }
43335
43335
  if (Array.isArray(root)) {
43336
43336
  const result = [];
43337
43337
  for (let i = 0, il = root.length; i < il; ++i) {
43338
43338
  if (root[i] instanceof URL && root[i].protocol === "file:") {
43339
- result.push(fileURLToPath5(root[i]));
43339
+ result.push(fileURLToPath6(root[i]));
43340
43340
  } else {
43341
43341
  result.push(root[i]);
43342
43342
  }
@@ -50826,10 +50826,10 @@ var import_node_child_process9 = require("node:child_process");
50826
50826
  var import_node_readline2 = require("node:readline");
50827
50827
 
50828
50828
  // index.ts
50829
- var import_node_url4 = require("node:url");
50830
- var import_node_path26 = require("node:path");
50831
- var import_node_os18 = require("node:os");
50832
- var import_node_fs28 = require("node:fs");
50829
+ var import_node_url5 = require("node:url");
50830
+ var import_node_path27 = require("node:path");
50831
+ var import_node_os19 = require("node:os");
50832
+ var import_node_fs29 = require("node:fs");
50833
50833
  var import_node_child_process7 = require("node:child_process");
50834
50834
 
50835
50835
  // log.mjs
@@ -52856,7 +52856,7 @@ function appVersion() {
52856
52856
  return resolveVersion({
52857
52857
  isSea: isSea2(),
52858
52858
  sqVersionXml: readSqVersionXml(),
52859
- define: true ? "0.42.0" : void 0,
52859
+ define: true ? "0.44.0" : void 0,
52860
52860
  pkgVersion: readPkgVersion()
52861
52861
  });
52862
52862
  }
@@ -52866,14 +52866,111 @@ function resolveChannel(s) {
52866
52866
  return "dev";
52867
52867
  }
52868
52868
  function appChannel() {
52869
- return resolveChannel({ isSea: isSea2(), define: true ? "0.42.0" : void 0 });
52869
+ return resolveChannel({ isSea: isSea2(), define: true ? "0.44.0" : void 0 });
52870
52870
  }
52871
52871
 
52872
- // oauth-presets.ts
52872
+ // workflow-update.ts
52873
+ var import_node_fs8 = require("node:fs");
52873
52874
  var import_node_os7 = require("node:os");
52874
52875
  var import_node_path7 = require("node:path");
52876
+ var import_node_url = require("node:url");
52877
+ var import_yaml2 = __toESM(require_dist6(), 1);
52878
+ var here = (0, import_node_path7.dirname)((0, import_node_url.fileURLToPath)(__import_meta_url));
52879
+ function compareSemver(a, b) {
52880
+ const pa = String(a).split(".");
52881
+ const pb = String(b).split(".");
52882
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
52883
+ const na = Number.parseInt(pa[i] ?? "0", 10) || 0;
52884
+ const nb = Number.parseInt(pb[i] ?? "0", 10) || 0;
52885
+ if (na !== nb) return na > nb ? 1 : -1;
52886
+ }
52887
+ return 0;
52888
+ }
52889
+ function changelogSince(changelog, installed) {
52890
+ return (changelog ?? []).filter((e) => e && compareSemver(String(e.version), installed) > 0);
52891
+ }
52892
+ function detectUpdates(installed, templates) {
52893
+ const out = [];
52894
+ for (const t of templates) {
52895
+ if (t.publisher !== "floless") continue;
52896
+ const iv = installed[t.id];
52897
+ if (iv == null) continue;
52898
+ if (compareSemver(t.version, iv) <= 0) continue;
52899
+ out.push({
52900
+ id: t.id,
52901
+ installed: iv,
52902
+ available: t.version,
52903
+ module: t.module,
52904
+ changelog: changelogSince(t.changelog, iv)
52905
+ });
52906
+ }
52907
+ return out;
52908
+ }
52909
+ function readTemplateMeta(path) {
52910
+ const doc2 = (0, import_yaml2.parse)((0, import_node_fs8.readFileSync)(path, "utf8")) ?? {};
52911
+ return {
52912
+ id: String(doc2.app ?? ""),
52913
+ version: doc2.version != null ? String(doc2.version) : "0.0.0",
52914
+ publisher: typeof doc2.publisher === "string" ? doc2.publisher : void 0,
52915
+ module: typeof doc2.module === "string" ? doc2.module : void 0,
52916
+ changelog: Array.isArray(doc2.changelog) ? doc2.changelog : void 0,
52917
+ path
52918
+ };
52919
+ }
52920
+ function templatePaths(roots) {
52921
+ const envDir = process.env.FLOLESS_TEMPLATES_DIR;
52922
+ const flatDirs = roots ?? [
52923
+ ...envDir ? [envDir] : [],
52924
+ (0, import_node_path7.join)(here, "templates"),
52925
+ // bundled: dist/templates beside the cjs
52926
+ (0, import_node_path7.join)(here, "dist", "templates"),
52927
+ // dev: the built bundle at server/dist
52928
+ (0, import_node_path7.join)((0, import_node_path7.dirname)(process.execPath), "templates")
52929
+ // SEA exe
52930
+ ];
52931
+ for (const d of flatDirs) {
52932
+ if (!(0, import_node_fs8.existsSync)(d)) continue;
52933
+ const flos = (0, import_node_fs8.readdirSync)(d).filter((f) => f.endsWith(".flo"));
52934
+ if (flos.length) return flos.map((f) => (0, import_node_path7.join)(d, f));
52935
+ }
52936
+ for (const demos of [(0, import_node_path7.join)(here, "..", "demos"), (0, import_node_path7.join)(here, "..", "..", "demos")]) {
52937
+ if (!(0, import_node_fs8.existsSync)(demos)) continue;
52938
+ const out = [];
52939
+ for (const dir of (0, import_node_fs8.readdirSync)(demos)) {
52940
+ try {
52941
+ for (const f of (0, import_node_fs8.readdirSync)((0, import_node_path7.join)(demos, dir))) if (f.endsWith(".flo")) out.push((0, import_node_path7.join)(demos, dir, f));
52942
+ } catch {
52943
+ }
52944
+ }
52945
+ return out;
52946
+ }
52947
+ return [];
52948
+ }
52949
+ function loadTemplates(roots) {
52950
+ const out = [];
52951
+ for (const p of templatePaths(roots)) {
52952
+ try {
52953
+ out.push(readTemplateMeta(p));
52954
+ } catch (e) {
52955
+ console.warn(`workflow-update: skipping unreadable template ${p}: ${e instanceof Error ? e.message : e}`);
52956
+ }
52957
+ }
52958
+ return out;
52959
+ }
52960
+ function backupDir(id, version, ts) {
52961
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path7.join)((0, import_node_os7.homedir)(), ".floless");
52962
+ const safe = (s) => {
52963
+ const c = String(s).replace(/[^0-9A-Za-z._-]/g, "_");
52964
+ return /^\.+$/.test(c) ? "_" : c || "_";
52965
+ };
52966
+ return (0, import_node_path7.join)(root, "app-backups", safe(id), `${safe(version)}-${ts}`);
52967
+ }
52968
+
52969
+ // oauth-presets.ts
52970
+ var import_node_os8 = require("node:os");
52971
+ var import_node_path8 = require("node:path");
52875
52972
  var import_node_net = __toESM(require("node:net"), 1);
52876
- var import_node_fs8 = require("node:fs");
52973
+ var import_node_fs9 = require("node:fs");
52877
52974
  var MANAGED_HEADER = "# managed by floless.app - do not edit";
52878
52975
  var OAUTH_PRESETS = {
52879
52976
  "trimble-connect": {
@@ -52903,7 +53000,7 @@ function managedProfileYaml(preset) {
52903
53000
  ].join("\n");
52904
53001
  }
52905
53002
  function oauthDir() {
52906
- return process.env.AWARE_HOME ? (0, import_node_path7.join)(process.env.AWARE_HOME, "oauth") : (0, import_node_path7.join)((0, import_node_os7.homedir)(), ".aware", "oauth");
53003
+ return process.env.AWARE_HOME ? (0, import_node_path8.join)(process.env.AWARE_HOME, "oauth") : (0, import_node_path8.join)((0, import_node_os8.homedir)(), ".aware", "oauth");
52907
53004
  }
52908
53005
  function isUpgradableLegacyProfile(existing, preset) {
52909
53006
  if (existing.startsWith(MANAGED_HEADER)) return false;
@@ -52917,15 +53014,15 @@ function ensureManagedProfile(id) {
52917
53014
  const preset = OAUTH_PRESETS[id];
52918
53015
  if (!preset) return "not-managed";
52919
53016
  const dir = oauthDir();
52920
- const file = (0, import_node_path7.join)(dir, `${id}.yaml`);
52921
- const existing = (0, import_node_fs8.existsSync)(file) ? (0, import_node_fs8.readFileSync)(file, "utf8") : null;
53017
+ const file = (0, import_node_path8.join)(dir, `${id}.yaml`);
53018
+ const existing = (0, import_node_fs9.existsSync)(file) ? (0, import_node_fs9.readFileSync)(file, "utf8") : null;
52922
53019
  if (existing !== null && !existing.startsWith(MANAGED_HEADER) && !isUpgradableLegacyProfile(existing, preset)) {
52923
53020
  return "skipped";
52924
53021
  }
52925
53022
  const desired = managedProfileYaml(preset);
52926
53023
  if (existing === desired) return "unchanged";
52927
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
52928
- (0, import_node_fs8.writeFileSync)(file, desired, "utf8");
53024
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
53025
+ (0, import_node_fs9.writeFileSync)(file, desired, "utf8");
52929
53026
  return "written";
52930
53027
  }
52931
53028
  function isPortBindable(port, host = "127.0.0.1") {
@@ -52937,7 +53034,7 @@ function isPortBindable(port, host = "127.0.0.1") {
52937
53034
  }
52938
53035
 
52939
53036
  // bake.ts
52940
- var import_yaml2 = __toESM(require_dist6(), 1);
53037
+ var import_yaml3 = __toESM(require_dist6(), 1);
52941
53038
  function buildExposedCommands(inputs) {
52942
53039
  const runInputs = {};
52943
53040
  for (const inp of inputs) {
@@ -52954,7 +53051,7 @@ function buildExposedCommands(inputs) {
52954
53051
  };
52955
53052
  }
52956
53053
  function bakeFloSource(source, inputs) {
52957
- const doc2 = (0, import_yaml2.parseDocument)(source);
53054
+ const doc2 = (0, import_yaml3.parseDocument)(source);
52958
53055
  if (doc2.errors.length > 0) {
52959
53056
  throw new Error(`bake: source is not valid YAML: ${doc2.errors[0]?.message ?? "parse error"}`);
52960
53057
  }
@@ -53118,16 +53215,16 @@ function extractReportHtml(events, appId) {
53118
53215
  }
53119
53216
 
53120
53217
  // steel-output-path.ts
53121
- var import_node_path8 = require("node:path");
53122
- var import_node_os8 = require("node:os");
53123
- var import_node_fs9 = require("node:fs");
53218
+ var import_node_path9 = require("node:path");
53219
+ var import_node_os9 = require("node:os");
53220
+ var import_node_fs10 = require("node:fs");
53124
53221
  function steelIfcRunInputs(id, inputs) {
53125
53222
  if (id !== "steel-to-ifc") return inputs;
53126
53223
  const op = inputs?.output_path;
53127
53224
  if (op != null && op !== "" && op !== "steel-from-drawings.ifc") return inputs;
53128
- const dl = (0, import_node_path8.join)((0, import_node_os8.homedir)(), "Downloads");
53129
- const dir = (0, import_node_fs9.existsSync)(dl) ? dl : (0, import_node_os8.homedir)();
53130
- return { ...inputs ?? {}, output_path: (0, import_node_path8.join)(dir, "steel-from-drawings.ifc") };
53225
+ const dl = (0, import_node_path9.join)((0, import_node_os9.homedir)(), "Downloads");
53226
+ const dir = (0, import_node_fs10.existsSync)(dl) ? dl : (0, import_node_os9.homedir)();
53227
+ return { ...inputs ?? {}, output_path: (0, import_node_path9.join)(dir, "steel-from-drawings.ifc") };
53131
53228
  }
53132
53229
 
53133
53230
  // index.ts
@@ -53175,16 +53272,16 @@ function buildPreview(m, sourceKind, sourceRef, stagedRef) {
53175
53272
  }
53176
53273
 
53177
53274
  // graft-manifest-reader.ts
53178
- var import_node_fs10 = require("node:fs");
53179
- var import_node_path9 = require("node:path");
53180
- var import_yaml3 = __toESM(require_dist6(), 1);
53275
+ var import_node_fs11 = require("node:fs");
53276
+ var import_node_path10 = require("node:path");
53277
+ var import_yaml4 = __toESM(require_dist6(), 1);
53181
53278
  var asRecord2 = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
53182
53279
  function readStagedManifest(agentDir) {
53183
- const manifestPath = (0, import_node_path9.join)(agentDir, "manifest.yaml");
53184
- if (!(0, import_node_fs10.existsSync)(manifestPath)) return null;
53280
+ const manifestPath = (0, import_node_path10.join)(agentDir, "manifest.yaml");
53281
+ if (!(0, import_node_fs11.existsSync)(manifestPath)) return null;
53185
53282
  let doc2;
53186
53283
  try {
53187
- doc2 = asRecord2((0, import_yaml3.parse)((0, import_node_fs10.readFileSync)(manifestPath, "utf8")));
53284
+ doc2 = asRecord2((0, import_yaml4.parse)((0, import_node_fs11.readFileSync)(manifestPath, "utf8")));
53188
53285
  } catch {
53189
53286
  return null;
53190
53287
  }
@@ -53214,10 +53311,10 @@ function readStagedManifest(agentDir) {
53214
53311
  }
53215
53312
  let skillCount = Array.isArray(doc2.skills) ? doc2.skills.length : 0;
53216
53313
  if (!skillCount) {
53217
- const skillsDir = (0, import_node_path9.join)(agentDir, "skills");
53218
- if ((0, import_node_fs10.existsSync)(skillsDir)) {
53314
+ const skillsDir = (0, import_node_path10.join)(agentDir, "skills");
53315
+ if ((0, import_node_fs11.existsSync)(skillsDir)) {
53219
53316
  try {
53220
- skillCount = (0, import_node_fs10.readdirSync)(skillsDir).filter((f) => f.endsWith(".md")).length;
53317
+ skillCount = (0, import_node_fs11.readdirSync)(skillsDir).filter((f) => f.endsWith(".md")).length;
53221
53318
  } catch {
53222
53319
  }
53223
53320
  }
@@ -53231,7 +53328,7 @@ function readStagedManifest(agentDir) {
53231
53328
  }
53232
53329
 
53233
53330
  // graft-stage-registry.ts
53234
- var import_node_fs11 = require("node:fs");
53331
+ var import_node_fs12 = require("node:fs");
53235
53332
  var TTL_MS = 30 * 60 * 1e3;
53236
53333
  var registry = /* @__PURE__ */ new Map();
53237
53334
  function registerStage(token, tempDir, agentId) {
@@ -53253,7 +53350,7 @@ function evict(token) {
53253
53350
  clearTimeout(e.timer);
53254
53351
  registry.delete(token);
53255
53352
  try {
53256
- (0, import_node_fs11.rmSync)(e.tempDir, { recursive: true, force: true });
53353
+ (0, import_node_fs12.rmSync)(e.tempDir, { recursive: true, force: true });
53257
53354
  } catch {
53258
53355
  }
53259
53356
  }
@@ -53262,8 +53359,8 @@ function clearAllStages() {
53262
53359
  }
53263
53360
 
53264
53361
  // graft-commit.ts
53265
- var import_node_fs12 = require("node:fs");
53266
- var import_node_path10 = require("node:path");
53362
+ var import_node_fs13 = require("node:fs");
53363
+ var import_node_path11 = require("node:path");
53267
53364
  var GraftCommitError = class extends Error {
53268
53365
  constructor(message, code) {
53269
53366
  super(message);
@@ -53273,34 +53370,34 @@ var GraftCommitError = class extends Error {
53273
53370
  code;
53274
53371
  };
53275
53372
  function commitStaged(tempDir, agentId, targetAgentsDir, force) {
53276
- const staged = (0, import_node_path10.join)(tempDir, "agents", agentId);
53277
- const target = (0, import_node_path10.join)(targetAgentsDir, agentId);
53278
- if ((0, import_node_fs12.existsSync)(target)) {
53373
+ const staged = (0, import_node_path11.join)(tempDir, "agents", agentId);
53374
+ const target = (0, import_node_path11.join)(targetAgentsDir, agentId);
53375
+ if ((0, import_node_fs13.existsSync)(target)) {
53279
53376
  if (!force) throw new GraftCommitError(`an agent named "${agentId}" is already installed`, "collision");
53280
- (0, import_node_fs12.rmSync)(target, { recursive: true, force: true });
53377
+ (0, import_node_fs13.rmSync)(target, { recursive: true, force: true });
53281
53378
  }
53282
- (0, import_node_fs12.mkdirSync)(targetAgentsDir, { recursive: true });
53379
+ (0, import_node_fs13.mkdirSync)(targetAgentsDir, { recursive: true });
53283
53380
  try {
53284
- (0, import_node_fs12.renameSync)(staged, target);
53381
+ (0, import_node_fs13.renameSync)(staged, target);
53285
53382
  } catch {
53286
- (0, import_node_fs12.cpSync)(staged, target, { recursive: true });
53383
+ (0, import_node_fs13.cpSync)(staged, target, { recursive: true });
53287
53384
  }
53288
- (0, import_node_fs12.rmSync)(tempDir, { recursive: true, force: true });
53385
+ (0, import_node_fs13.rmSync)(tempDir, { recursive: true, force: true });
53289
53386
  return { agentId };
53290
53387
  }
53291
53388
  function matchAssemblies(globOrDir) {
53292
53389
  let dir;
53293
53390
  let pattern;
53294
- if ((0, import_node_fs12.existsSync)(globOrDir) && (0, import_node_fs12.statSync)(globOrDir).isDirectory()) {
53391
+ if ((0, import_node_fs13.existsSync)(globOrDir) && (0, import_node_fs13.statSync)(globOrDir).isDirectory()) {
53295
53392
  dir = globOrDir;
53296
53393
  pattern = "*.dll";
53297
53394
  } else {
53298
- dir = (0, import_node_path10.dirname)(globOrDir);
53299
- pattern = (0, import_node_path10.basename)(globOrDir);
53395
+ dir = (0, import_node_path11.dirname)(globOrDir);
53396
+ pattern = (0, import_node_path11.basename)(globOrDir);
53300
53397
  }
53301
- if (!dir || !(0, import_node_fs12.existsSync)(dir) || !(0, import_node_fs12.statSync)(dir).isDirectory()) return [];
53398
+ if (!dir || !(0, import_node_fs13.existsSync)(dir) || !(0, import_node_fs13.statSync)(dir).isDirectory()) return [];
53302
53399
  const re = globToRegExp(pattern);
53303
- return (0, import_node_fs12.readdirSync)(dir).filter((f) => re.test(f)).sort();
53400
+ return (0, import_node_fs13.readdirSync)(dir).filter((f) => re.test(f)).sort();
53304
53401
  }
53305
53402
  function globToRegExp(p) {
53306
53403
  const esc2 = p.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
@@ -53309,24 +53406,24 @@ function globToRegExp(p) {
53309
53406
 
53310
53407
  // floless-store.ts
53311
53408
  var import_node_crypto4 = require("node:crypto");
53312
- var import_node_fs13 = require("node:fs");
53313
- var import_node_os9 = require("node:os");
53314
- var import_node_path11 = require("node:path");
53315
- var ROOT2 = process.env.FLOLESS_HOME ?? (0, import_node_path11.join)((0, import_node_os9.homedir)(), ".floless");
53316
- var TEMPLATES_FILE = (0, import_node_path11.join)(ROOT2, "templates.json");
53317
- var REQUESTS_DIR = (0, import_node_path11.join)(ROOT2, "requests");
53409
+ var import_node_fs14 = require("node:fs");
53410
+ var import_node_os10 = require("node:os");
53411
+ var import_node_path12 = require("node:path");
53412
+ var ROOT2 = process.env.FLOLESS_HOME ?? (0, import_node_path12.join)((0, import_node_os10.homedir)(), ".floless");
53413
+ var TEMPLATES_FILE = (0, import_node_path12.join)(ROOT2, "templates.json");
53414
+ var REQUESTS_DIR = (0, import_node_path12.join)(ROOT2, "requests");
53318
53415
  function ensureRoot() {
53319
- if (!(0, import_node_fs13.existsSync)(ROOT2)) (0, import_node_fs13.mkdirSync)(ROOT2, { recursive: true });
53416
+ if (!(0, import_node_fs14.existsSync)(ROOT2)) (0, import_node_fs14.mkdirSync)(ROOT2, { recursive: true });
53320
53417
  }
53321
53418
  function withinRequestsDir(p) {
53322
- const base = (0, import_node_path11.resolve)(REQUESTS_DIR);
53323
- const full = (0, import_node_path11.resolve)(p);
53324
- return full === base || full.startsWith(base + import_node_path11.sep);
53419
+ const base = (0, import_node_path12.resolve)(REQUESTS_DIR);
53420
+ const full = (0, import_node_path12.resolve)(p);
53421
+ return full === base || full.startsWith(base + import_node_path12.sep);
53325
53422
  }
53326
53423
  function listTemplates() {
53327
- if (!(0, import_node_fs13.existsSync)(TEMPLATES_FILE)) return [];
53424
+ if (!(0, import_node_fs14.existsSync)(TEMPLATES_FILE)) return [];
53328
53425
  try {
53329
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)(TEMPLATES_FILE, "utf8"));
53426
+ const parsed = JSON.parse((0, import_node_fs14.readFileSync)(TEMPLATES_FILE, "utf8"));
53330
53427
  return Array.isArray(parsed) ? parsed : [];
53331
53428
  } catch {
53332
53429
  return [];
@@ -53335,8 +53432,8 @@ function listTemplates() {
53335
53432
  function writeTemplates(list) {
53336
53433
  ensureRoot();
53337
53434
  const tmp = `${TEMPLATES_FILE}.${process.pid}.tmp`;
53338
- (0, import_node_fs13.writeFileSync)(tmp, JSON.stringify(list, null, 2));
53339
- (0, import_node_fs13.renameSync)(tmp, TEMPLATES_FILE);
53435
+ (0, import_node_fs14.writeFileSync)(tmp, JSON.stringify(list, null, 2));
53436
+ (0, import_node_fs14.renameSync)(tmp, TEMPLATES_FILE);
53340
53437
  }
53341
53438
  function addTemplate(input) {
53342
53439
  const list = listTemplates();
@@ -53381,13 +53478,13 @@ function updateTemplate(id, patch) {
53381
53478
  }
53382
53479
  function addRequest(req, decoded = []) {
53383
53480
  ensureRoot();
53384
- if (!(0, import_node_fs13.existsSync)(REQUESTS_DIR)) (0, import_node_fs13.mkdirSync)(REQUESTS_DIR, { recursive: true });
53481
+ if (!(0, import_node_fs14.existsSync)(REQUESTS_DIR)) (0, import_node_fs14.mkdirSync)(REQUESTS_DIR, { recursive: true });
53385
53482
  const id = (0, import_node_crypto4.randomUUID)();
53386
53483
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
53387
53484
  const base = `${createdAt.replace(/[:.]/g, "-")}__${id}`;
53388
53485
  const snapshots = decoded.map((d, i) => {
53389
- const p = (0, import_node_path11.join)(REQUESTS_DIR, `${base}__snap${i + 1}.${d.ext}`);
53390
- (0, import_node_fs13.writeFileSync)(p, d.buf);
53486
+ const p = (0, import_node_path12.join)(REQUESTS_DIR, `${base}__snap${i + 1}.${d.ext}`);
53487
+ (0, import_node_fs14.writeFileSync)(p, d.buf);
53391
53488
  return p;
53392
53489
  });
53393
53490
  const full = {
@@ -53397,55 +53494,55 @@ function addRequest(req, decoded = []) {
53397
53494
  ...req,
53398
53495
  ...snapshots.length ? { snapshots } : {}
53399
53496
  };
53400
- (0, import_node_fs13.writeFileSync)((0, import_node_path11.join)(REQUESTS_DIR, `${base}.json`), JSON.stringify(full, null, 2));
53497
+ (0, import_node_fs14.writeFileSync)((0, import_node_path12.join)(REQUESTS_DIR, `${base}.json`), JSON.stringify(full, null, 2));
53401
53498
  return full;
53402
53499
  }
53403
53500
  function listRequests() {
53404
- if (!(0, import_node_fs13.existsSync)(REQUESTS_DIR)) return [];
53405
- return (0, import_node_fs13.readdirSync)(REQUESTS_DIR).filter((f) => f.endsWith(".json")).sort().map((f) => {
53501
+ if (!(0, import_node_fs14.existsSync)(REQUESTS_DIR)) return [];
53502
+ return (0, import_node_fs14.readdirSync)(REQUESTS_DIR).filter((f) => f.endsWith(".json")).sort().map((f) => {
53406
53503
  try {
53407
- return JSON.parse((0, import_node_fs13.readFileSync)((0, import_node_path11.join)(REQUESTS_DIR, f), "utf8"));
53504
+ return JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path12.join)(REQUESTS_DIR, f), "utf8"));
53408
53505
  } catch {
53409
53506
  return null;
53410
53507
  }
53411
53508
  }).filter((r) => r !== null);
53412
53509
  }
53413
53510
  function deleteRequest(id) {
53414
- if (!(0, import_node_fs13.existsSync)(REQUESTS_DIR)) return false;
53415
- const file = (0, import_node_fs13.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
53511
+ if (!(0, import_node_fs14.existsSync)(REQUESTS_DIR)) return false;
53512
+ const file = (0, import_node_fs14.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
53416
53513
  if (!file) return false;
53417
53514
  try {
53418
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)((0, import_node_path11.join)(REQUESTS_DIR, file), "utf8"));
53515
+ const parsed = JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path12.join)(REQUESTS_DIR, file), "utf8"));
53419
53516
  for (const p of parsed.snapshots ?? []) {
53420
53517
  if (!withinRequestsDir(p)) continue;
53421
53518
  try {
53422
- (0, import_node_fs13.rmSync)(p);
53519
+ (0, import_node_fs14.rmSync)(p);
53423
53520
  } catch {
53424
53521
  }
53425
53522
  }
53426
53523
  } catch {
53427
53524
  }
53428
- (0, import_node_fs13.rmSync)((0, import_node_path11.join)(REQUESTS_DIR, file));
53525
+ (0, import_node_fs14.rmSync)((0, import_node_path12.join)(REQUESTS_DIR, file));
53429
53526
  return true;
53430
53527
  }
53431
53528
  function clearRequests() {
53432
- if (!(0, import_node_fs13.existsSync)(REQUESTS_DIR)) return 0;
53433
- const allFiles = (0, import_node_fs13.readdirSync)(REQUESTS_DIR);
53529
+ if (!(0, import_node_fs14.existsSync)(REQUESTS_DIR)) return 0;
53530
+ const allFiles = (0, import_node_fs14.readdirSync)(REQUESTS_DIR);
53434
53531
  const jsonFiles = allFiles.filter((f) => f.endsWith(".json"));
53435
53532
  for (const f of allFiles) {
53436
53533
  try {
53437
- (0, import_node_fs13.rmSync)((0, import_node_path11.join)(REQUESTS_DIR, f));
53534
+ (0, import_node_fs14.rmSync)((0, import_node_path12.join)(REQUESTS_DIR, f));
53438
53535
  } catch {
53439
53536
  }
53440
53537
  }
53441
53538
  return jsonFiles.length;
53442
53539
  }
53443
53540
  function snapshotPathFor(id, n) {
53444
- if (!(0, import_node_fs13.existsSync)(REQUESTS_DIR)) return null;
53445
- const file = (0, import_node_fs13.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
53541
+ if (!(0, import_node_fs14.existsSync)(REQUESTS_DIR)) return null;
53542
+ const file = (0, import_node_fs14.readdirSync)(REQUESTS_DIR).find((f) => f.endsWith(`__${id}.json`));
53446
53543
  if (!file) return null;
53447
53544
  try {
53448
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)((0, import_node_path11.join)(REQUESTS_DIR, file), "utf8"));
53545
+ const parsed = JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path12.join)(REQUESTS_DIR, file), "utf8"));
53449
53546
  const cand = parsed.snapshots?.[n] ?? null;
53450
53547
  return cand && withinRequestsDir(cand) ? cand : null;
53451
53548
  } catch {
@@ -53482,15 +53579,15 @@ function decodeSnapshots(inputs) {
53482
53579
 
53483
53580
  // visual-input-store.ts
53484
53581
  var import_node_crypto5 = require("node:crypto");
53485
- var import_node_fs14 = require("node:fs");
53486
- var import_node_os10 = require("node:os");
53487
- var import_node_path12 = require("node:path");
53582
+ var import_node_fs15 = require("node:fs");
53583
+ var import_node_os11 = require("node:os");
53584
+ var import_node_path13 = require("node:path");
53488
53585
  var MAX_BYTES3 = 25 * 1024 * 1024;
53489
53586
  var VisualInputError = class extends Error {
53490
53587
  };
53491
53588
  function inputsDir() {
53492
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path12.join)((0, import_node_os10.homedir)(), ".floless");
53493
- return (0, import_node_path12.join)(root, "inputs");
53589
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path13.join)((0, import_node_os11.homedir)(), ".floless");
53590
+ return (0, import_node_path13.join)(root, "inputs");
53494
53591
  }
53495
53592
  function sniffExt2(buf) {
53496
53593
  if (buf.length >= 8 && buf[0] === 137 && buf[1] === 80 && buf[2] === 78 && buf[3] === 71) return "png";
@@ -53502,7 +53599,7 @@ function sniffExt2(buf) {
53502
53599
  var RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
53503
53600
  function safeSegment(s) {
53504
53601
  if (!s || s === "." || s.includes("..")) return false;
53505
- if (s.includes("/") || s.includes("\\") || s.includes(import_node_path12.sep)) return false;
53602
+ if (s.includes("/") || s.includes("\\") || s.includes(import_node_path13.sep)) return false;
53506
53603
  for (let i = 0; i < s.length; i++) {
53507
53604
  const c = s.charCodeAt(i);
53508
53605
  if (c < 32 || c === 58) return false;
@@ -53520,51 +53617,51 @@ function storeVisualInput(appId, dataUrl) {
53520
53617
  const ext = sniffExt2(buf);
53521
53618
  if (!ext) throw new VisualInputError("visual input must be PNG, JPEG, WebP, or PDF");
53522
53619
  const sha2562 = (0, import_node_crypto5.createHash)("sha256").update(buf).digest("hex");
53523
- const dir = (0, import_node_path12.join)(inputsDir(), appId);
53524
- const path = (0, import_node_path12.join)(dir, `${sha2562}.${ext}`);
53525
- const root = (0, import_node_path12.resolve)(inputsDir());
53526
- const target = (0, import_node_path12.resolve)(path);
53527
- if (target !== root && !target.startsWith(root + import_node_path12.sep)) {
53620
+ const dir = (0, import_node_path13.join)(inputsDir(), appId);
53621
+ const path = (0, import_node_path13.join)(dir, `${sha2562}.${ext}`);
53622
+ const root = (0, import_node_path13.resolve)(inputsDir());
53623
+ const target = (0, import_node_path13.resolve)(path);
53624
+ if (target !== root && !target.startsWith(root + import_node_path13.sep)) {
53528
53625
  throw new VisualInputError("refusing to write outside the inputs root");
53529
53626
  }
53530
- (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
53531
- if (!(0, import_node_fs14.existsSync)(path)) {
53627
+ (0, import_node_fs15.mkdirSync)(dir, { recursive: true });
53628
+ if (!(0, import_node_fs15.existsSync)(path)) {
53532
53629
  const tmp = `${path}.tmp`;
53533
- (0, import_node_fs14.writeFileSync)(tmp, buf);
53534
- (0, import_node_fs14.renameSync)(tmp, path);
53630
+ (0, import_node_fs15.writeFileSync)(tmp, buf);
53631
+ (0, import_node_fs15.renameSync)(tmp, path);
53535
53632
  }
53536
- return { path, ext, bytes: (0, import_node_fs14.statSync)(path).size, sha256: sha2562 };
53633
+ return { path, ext, bytes: (0, import_node_fs15.statSync)(path).size, sha256: sha2562 };
53537
53634
  }
53538
53635
  function renameVisualInputs(oldId, newId) {
53539
53636
  if (!safeSegment(oldId) || !safeSegment(newId)) throw new VisualInputError("invalid app id");
53540
- const from = (0, import_node_path12.join)(inputsDir(), oldId);
53541
- if (!(0, import_node_fs14.existsSync)(from)) return;
53542
- const to = (0, import_node_path12.join)(inputsDir(), newId);
53543
- if ((0, import_node_fs14.existsSync)(to)) (0, import_node_fs14.rmSync)(to, { recursive: true, force: true });
53544
- (0, import_node_fs14.mkdirSync)(inputsDir(), { recursive: true });
53545
- (0, import_node_fs14.renameSync)(from, to);
53637
+ const from = (0, import_node_path13.join)(inputsDir(), oldId);
53638
+ if (!(0, import_node_fs15.existsSync)(from)) return;
53639
+ const to = (0, import_node_path13.join)(inputsDir(), newId);
53640
+ if ((0, import_node_fs15.existsSync)(to)) (0, import_node_fs15.rmSync)(to, { recursive: true, force: true });
53641
+ (0, import_node_fs15.mkdirSync)(inputsDir(), { recursive: true });
53642
+ (0, import_node_fs15.renameSync)(from, to);
53546
53643
  }
53547
53644
  function copyVisualInputs(srcId, newId) {
53548
53645
  if (!safeSegment(srcId) || !safeSegment(newId)) throw new VisualInputError("invalid app id");
53549
- const from = (0, import_node_path12.join)(inputsDir(), srcId);
53550
- if (!(0, import_node_fs14.existsSync)(from)) return;
53551
- (0, import_node_fs14.cpSync)(from, (0, import_node_path12.join)(inputsDir(), newId), { recursive: true });
53646
+ const from = (0, import_node_path13.join)(inputsDir(), srcId);
53647
+ if (!(0, import_node_fs15.existsSync)(from)) return;
53648
+ (0, import_node_fs15.cpSync)(from, (0, import_node_path13.join)(inputsDir(), newId), { recursive: true });
53552
53649
  }
53553
53650
  function deleteVisualInputs(id) {
53554
53651
  if (!safeSegment(id)) throw new VisualInputError("invalid app id");
53555
- const dir = (0, import_node_path12.join)(inputsDir(), id);
53556
- if ((0, import_node_fs14.existsSync)(dir)) (0, import_node_fs14.rmSync)(dir, { recursive: true, force: true });
53652
+ const dir = (0, import_node_path13.join)(inputsDir(), id);
53653
+ if ((0, import_node_fs15.existsSync)(dir)) (0, import_node_fs15.rmSync)(dir, { recursive: true, force: true });
53557
53654
  }
53558
53655
 
53559
53656
  // contract-store.ts
53560
- var import_node_fs16 = require("node:fs");
53561
- var import_node_path14 = require("node:path");
53562
- var import_node_os11 = require("node:os");
53657
+ var import_node_fs17 = require("node:fs");
53658
+ var import_node_path15 = require("node:path");
53659
+ var import_node_os12 = require("node:os");
53563
53660
 
53564
53661
  // contract-schema.ts
53565
- var import_node_fs15 = require("node:fs");
53566
- var import_node_path13 = require("node:path");
53567
- var import_node_url = require("node:url");
53662
+ var import_node_fs16 = require("node:fs");
53663
+ var import_node_path14 = require("node:path");
53664
+ var import_node_url2 = require("node:url");
53568
53665
  function validate(doc2, schema) {
53569
53666
  const errors = [];
53570
53667
  walk(doc2, schema, schema, "$", errors);
@@ -53664,16 +53761,16 @@ function walk(value, node, root, path, errors) {
53664
53761
  var _cached = null;
53665
53762
  function loadSteelTakeoffSchema() {
53666
53763
  if (_cached) return _cached;
53667
- const here = (0, import_node_path13.dirname)((0, import_node_url.fileURLToPath)(__import_meta_url));
53764
+ const here2 = (0, import_node_path14.dirname)((0, import_node_url2.fileURLToPath)(__import_meta_url));
53668
53765
  const candidates = [
53669
- (0, import_node_path13.join)(here, "..", "schemas", "steel.takeoff.v1.schema.json"),
53766
+ (0, import_node_path14.join)(here2, "..", "schemas", "steel.takeoff.v1.schema.json"),
53670
53767
  // dev: server/ next to schemas/
53671
- (0, import_node_path13.join)(here, "schemas", "steel.takeoff.v1.schema.json")
53768
+ (0, import_node_path14.join)(here2, "schemas", "steel.takeoff.v1.schema.json")
53672
53769
  // bundled: dist/ holds ./schemas
53673
53770
  ];
53674
53771
  for (const p of candidates) {
53675
53772
  try {
53676
- const text = (0, import_node_fs15.readFileSync)(p, "utf8");
53773
+ const text = (0, import_node_fs16.readFileSync)(p, "utf8");
53677
53774
  _cached = JSON.parse(text);
53678
53775
  return _cached;
53679
53776
  } catch (err) {
@@ -53689,20 +53786,20 @@ function validateSteelTakeoff(doc2) {
53689
53786
  // contract-store.ts
53690
53787
  var ContractError = class extends Error {
53691
53788
  };
53692
- var ROOT3 = process.env.FLOLESS_HOME ?? (0, import_node_path14.join)((0, import_node_os11.homedir)(), ".floless");
53693
- var DIR = (0, import_node_path14.join)(ROOT3, "contracts");
53789
+ var ROOT3 = process.env.FLOLESS_HOME ?? (0, import_node_path15.join)((0, import_node_os12.homedir)(), ".floless");
53790
+ var DIR = (0, import_node_path15.join)(ROOT3, "contracts");
53694
53791
  function safeId(appId) {
53695
53792
  if (!/^[a-z0-9][a-z0-9._-]*$/i.test(appId)) throw new ContractError(`invalid appId: ${appId}`);
53696
53793
  return appId;
53697
53794
  }
53698
53795
  function contractPath(appId) {
53699
- return (0, import_node_path14.join)(DIR, `${safeId(appId)}.json`);
53796
+ return (0, import_node_path15.join)(DIR, `${safeId(appId)}.json`);
53700
53797
  }
53701
53798
  function readContract(appId) {
53702
53799
  const p = contractPath(appId);
53703
- if (!(0, import_node_fs16.existsSync)(p)) return null;
53800
+ if (!(0, import_node_fs17.existsSync)(p)) return null;
53704
53801
  try {
53705
- return JSON.parse((0, import_node_fs16.readFileSync)(p, "utf8"));
53802
+ return JSON.parse((0, import_node_fs17.readFileSync)(p, "utf8"));
53706
53803
  } catch (e) {
53707
53804
  console.warn(`readContract: ignoring unreadable contract at ${p}: ${e instanceof Error ? e.message : e}`);
53708
53805
  return null;
@@ -53715,8 +53812,8 @@ function writeContract(appId, doc2) {
53715
53812
  const first = res.errors.slice(0, 5).map((e) => `${e.path}: ${e.message}`).join("; ");
53716
53813
  throw new ContractError(`contract failed schema validation \u2014 ${first}`);
53717
53814
  }
53718
- if (!(0, import_node_fs16.existsSync)(DIR)) (0, import_node_fs16.mkdirSync)(DIR, { recursive: true });
53719
- (0, import_node_fs16.writeFileSync)(p, JSON.stringify(doc2));
53815
+ if (!(0, import_node_fs17.existsSync)(DIR)) (0, import_node_fs17.mkdirSync)(DIR, { recursive: true });
53816
+ (0, import_node_fs17.writeFileSync)(p, JSON.stringify(doc2));
53720
53817
  }
53721
53818
 
53722
53819
  // contract-resolve.ts
@@ -53738,16 +53835,16 @@ function readContractForApp(appId, readAppFn = readApp) {
53738
53835
  }
53739
53836
 
53740
53837
  // contract-bake.ts
53741
- var import_node_fs17 = require("node:fs");
53742
- var import_yaml4 = __toESM(require_dist6(), 1);
53838
+ var import_node_fs18 = require("node:fs");
53839
+ var import_yaml5 = __toESM(require_dist6(), 1);
53743
53840
  function bakeContractIntoApp(sourcePath, contract) {
53744
- const doc2 = (0, import_yaml4.parseDocument)((0, import_node_fs17.readFileSync)(sourcePath, "utf8"));
53841
+ const doc2 = (0, import_yaml5.parseDocument)((0, import_node_fs18.readFileSync)(sourcePath, "utf8"));
53745
53842
  if (doc2.errors.length > 0) {
53746
53843
  throw new Error(`contract bake: source is not valid YAML: ${doc2.errors[0]?.message ?? "parse error"}`);
53747
53844
  }
53748
53845
  const seq = doc2.get("nodes");
53749
- const items = (0, import_yaml4.isSeq)(seq) ? seq.items : [];
53750
- const nodeOf = (it) => (0, import_yaml4.isMap)(it) ? it.toJSON() : null;
53846
+ const items = (0, import_yaml5.isSeq)(seq) ? seq.items : [];
53847
+ const nodeOf = (it) => (0, import_yaml5.isMap)(it) ? it.toJSON() : null;
53751
53848
  let idx = items.findIndex((it) => nodeOf(it)?.config?.contract === contract.type);
53752
53849
  if (idx < 0) idx = items.findIndex((it) => nodeOf(it)?.agent === "steel-takeoff-us");
53753
53850
  if (idx < 0) throw new Error("no contract-emitting node to bake the contract into");
@@ -53770,7 +53867,7 @@ function bakeContractIntoApp(sourcePath, contract) {
53770
53867
  baked.filter = { ...filter, page };
53771
53868
  }
53772
53869
  doc2.setIn(["nodes", idx, "config", "takeoff"], baked);
53773
- (0, import_node_fs17.writeFileSync)(sourcePath, doc2.toString());
53870
+ (0, import_node_fs18.writeFileSync)(sourcePath, doc2.toString());
53774
53871
  }
53775
53872
 
53776
53873
  // contract-to-scene.ts
@@ -53867,37 +53964,37 @@ function contractToScene(contractInput) {
53867
53964
  }
53868
53965
 
53869
53966
  // scene-bake.ts
53870
- var import_node_fs18 = require("node:fs");
53871
- var import_node_path15 = require("node:path");
53872
- var import_yaml5 = __toESM(require_dist6(), 1);
53967
+ var import_node_fs19 = require("node:fs");
53968
+ var import_node_path16 = require("node:path");
53969
+ var import_yaml6 = __toESM(require_dist6(), 1);
53873
53970
  function bakeSceneIntoApp(sourcePath, scene, agent = "viewer-3d") {
53874
- const doc2 = (0, import_yaml5.parseDocument)((0, import_node_fs18.readFileSync)(sourcePath, "utf8"));
53971
+ const doc2 = (0, import_yaml6.parseDocument)((0, import_node_fs19.readFileSync)(sourcePath, "utf8"));
53875
53972
  if (doc2.errors.length > 0) {
53876
53973
  throw new Error(`scene bake: source is not valid YAML: ${doc2.errors[0]?.message ?? "parse error"}`);
53877
53974
  }
53878
53975
  const seq = doc2.get("nodes");
53879
- const items = (0, import_yaml5.isSeq)(seq) ? seq.items : [];
53880
- const idx = items.findIndex((it) => ((0, import_yaml5.isMap)(it) ? it.toJSON() : null)?.agent === agent);
53976
+ const items = (0, import_yaml6.isSeq)(seq) ? seq.items : [];
53977
+ const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.agent === agent);
53881
53978
  if (idx < 0) throw new Error(`no ${agent} render node to bake the scene into`);
53882
53979
  doc2.setIn(["nodes", idx, "config", "scene"], scene);
53883
- (0, import_node_fs18.writeFileSync)(sourcePath, doc2.toString());
53980
+ (0, import_node_fs19.writeFileSync)(sourcePath, doc2.toString());
53884
53981
  }
53885
53982
  function bakeNodeConfigById(sourcePath, nodeId, patch) {
53886
- const doc2 = (0, import_yaml5.parseDocument)((0, import_node_fs18.readFileSync)(sourcePath, "utf8"));
53983
+ const doc2 = (0, import_yaml6.parseDocument)((0, import_node_fs19.readFileSync)(sourcePath, "utf8"));
53887
53984
  if (doc2.errors.length > 0) {
53888
53985
  throw new Error(`node bake: source is not valid YAML: ${doc2.errors[0]?.message ?? "parse error"}`);
53889
53986
  }
53890
53987
  const seq = doc2.get("nodes");
53891
- const items = (0, import_yaml5.isSeq)(seq) ? seq.items : [];
53892
- const idx = items.findIndex((it) => ((0, import_yaml5.isMap)(it) ? it.toJSON() : null)?.id === nodeId);
53988
+ const items = (0, import_yaml6.isSeq)(seq) ? seq.items : [];
53989
+ const idx = items.findIndex((it) => ((0, import_yaml6.isMap)(it) ? it.toJSON() : null)?.id === nodeId);
53893
53990
  if (idx < 0) throw new Error(`no node with id "${nodeId}"`);
53894
53991
  for (const [key, value] of Object.entries(patch)) doc2.setIn(["nodes", idx, "config", key], value);
53895
- (0, import_node_fs18.writeFileSync)(sourcePath, doc2.toString());
53992
+ (0, import_node_fs19.writeFileSync)(sourcePath, doc2.toString());
53896
53993
  }
53897
53994
  function writeViewer3dApp(dir, appId, scene) {
53898
- (0, import_node_fs18.mkdirSync)(dir, { recursive: true });
53899
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
53900
- (0, import_node_fs18.writeFileSync)(flo, [
53995
+ (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
53996
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
53997
+ (0, import_node_fs19.writeFileSync)(flo, [
53901
53998
  `app: ${appId}`,
53902
53999
  "version: 0.1.0",
53903
54000
  "display-name: Steel 3D",
@@ -53918,9 +54015,9 @@ function writeViewer3dApp(dir, appId, scene) {
53918
54015
  return flo;
53919
54016
  }
53920
54017
  function writeIfcApp(dir, appId, scene, outputPath) {
53921
- (0, import_node_fs18.mkdirSync)(dir, { recursive: true });
53922
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
53923
- (0, import_node_fs18.writeFileSync)(flo, [
54018
+ (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
54019
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
54020
+ (0, import_node_fs19.writeFileSync)(flo, [
53924
54021
  `app: ${appId}`,
53925
54022
  "version: 0.1.0",
53926
54023
  "display-name: Steel IFC",
@@ -53943,9 +54040,9 @@ function writeIfcApp(dir, appId, scene, outputPath) {
53943
54040
  return flo;
53944
54041
  }
53945
54042
  function writeTeklaApp(dir, appId, scene, teklaVersion = "2026.0") {
53946
- (0, import_node_fs18.mkdirSync)(dir, { recursive: true });
53947
- const flo = (0, import_node_path15.join)(dir, `${appId}.flo`);
53948
- (0, import_node_fs18.writeFileSync)(flo, [
54043
+ (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
54044
+ const flo = (0, import_node_path16.join)(dir, `${appId}.flo`);
54045
+ (0, import_node_fs19.writeFileSync)(flo, [
53949
54046
  `app: ${appId}`,
53950
54047
  "version: 0.1.0",
53951
54048
  "display-name: Steel to Tekla",
@@ -54322,13 +54419,13 @@ function scoreContract2(contractInput) {
54322
54419
  }
54323
54420
 
54324
54421
  // app-lifecycle.ts
54325
- var import_node_fs21 = require("node:fs");
54326
- var import_node_os13 = require("node:os");
54327
- var import_node_path18 = require("node:path");
54422
+ var import_node_fs22 = require("node:fs");
54423
+ var import_node_os14 = require("node:os");
54424
+ var import_node_path19 = require("node:path");
54328
54425
 
54329
54426
  // routines.ts
54330
- var import_node_fs20 = require("node:fs");
54331
- var import_node_path17 = require("node:path");
54427
+ var import_node_fs21 = require("node:fs");
54428
+ var import_node_path18 = require("node:path");
54332
54429
 
54333
54430
  // sse.ts
54334
54431
  var clients = /* @__PURE__ */ new Set();
@@ -54365,11 +54462,11 @@ function clientCount() {
54365
54462
  }
54366
54463
 
54367
54464
  // trigger-sessions.ts
54368
- var import_node_fs19 = require("node:fs");
54369
- var import_node_os12 = require("node:os");
54370
- var import_node_path16 = require("node:path");
54371
- var import_yaml6 = __toESM(require_dist6(), 1);
54372
- var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path16.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path16.join)((0, import_node_os12.homedir)(), ".aware", "agents");
54465
+ var import_node_fs20 = require("node:fs");
54466
+ var import_node_os13 = require("node:os");
54467
+ var import_node_path17 = require("node:path");
54468
+ var import_yaml7 = __toESM(require_dist6(), 1);
54469
+ var AGENTS_DIR2 = process.env.AWARE_HOME ? (0, import_node_path17.join)(process.env.AWARE_HOME, "agents") : (0, import_node_path17.join)((0, import_node_os13.homedir)(), ".aware", "agents");
54373
54470
  function summarizeFire(data) {
54374
54471
  if (!data) return "event";
54375
54472
  const type = typeof data.type === "string" ? data.type : "";
@@ -54386,10 +54483,10 @@ function mapTriggerState(phase) {
54386
54483
  function isHostBacked(agent, agentsDir = AGENTS_DIR2) {
54387
54484
  const safe = (n) => !n.includes("/") && !n.includes("\\") && !n.includes("..");
54388
54485
  if (!safe(agent)) return false;
54389
- const manifestPath = (0, import_node_path16.join)(agentsDir, agent, "manifest.yaml");
54390
- if (!(0, import_node_fs19.existsSync)(manifestPath)) return false;
54486
+ const manifestPath = (0, import_node_path17.join)(agentsDir, agent, "manifest.yaml");
54487
+ if (!(0, import_node_fs20.existsSync)(manifestPath)) return false;
54391
54488
  try {
54392
- const doc2 = (0, import_yaml6.parse)((0, import_node_fs19.readFileSync)(manifestPath, "utf8"));
54489
+ const doc2 = (0, import_yaml7.parse)((0, import_node_fs20.readFileSync)(manifestPath, "utf8"));
54393
54490
  const transport = doc2?.transport;
54394
54491
  return !!(transport && typeof transport === "object" && "cli" in transport);
54395
54492
  } catch {
@@ -54674,7 +54771,7 @@ var RoutineError = class extends Error {
54674
54771
  }
54675
54772
  status;
54676
54773
  };
54677
- var ROUTINES_FILE = (0, import_node_path17.join)(flolessRoot, "routines.json");
54774
+ var ROUTINES_FILE = (0, import_node_path18.join)(flolessRoot, "routines.json");
54678
54775
  var routines = [];
54679
54776
  var loaded = false;
54680
54777
  function ensureLoaded() {
@@ -54710,10 +54807,10 @@ function sanitizeRoutine(raw) {
54710
54807
  };
54711
54808
  }
54712
54809
  function loadFromDisk() {
54713
- if (!(0, import_node_fs20.existsSync)(ROUTINES_FILE)) return [];
54810
+ if (!(0, import_node_fs21.existsSync)(ROUTINES_FILE)) return [];
54714
54811
  let text;
54715
54812
  try {
54716
- text = (0, import_node_fs20.readFileSync)(ROUTINES_FILE, "utf8");
54813
+ text = (0, import_node_fs21.readFileSync)(ROUTINES_FILE, "utf8");
54717
54814
  } catch {
54718
54815
  return [];
54719
54816
  }
@@ -54722,17 +54819,17 @@ function loadFromDisk() {
54722
54819
  return Array.isArray(parsed) ? parsed.map(sanitizeRoutine).filter((r) => r !== null) : [];
54723
54820
  } catch {
54724
54821
  try {
54725
- (0, import_node_fs20.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
54822
+ (0, import_node_fs21.renameSync)(ROUTINES_FILE, `${ROUTINES_FILE}.corrupt-${Date.now()}`);
54726
54823
  } catch {
54727
54824
  }
54728
54825
  return [];
54729
54826
  }
54730
54827
  }
54731
54828
  function saveRoutines() {
54732
- if (!(0, import_node_fs20.existsSync)(flolessRoot)) (0, import_node_fs20.mkdirSync)(flolessRoot, { recursive: true });
54829
+ if (!(0, import_node_fs21.existsSync)(flolessRoot)) (0, import_node_fs21.mkdirSync)(flolessRoot, { recursive: true });
54733
54830
  const tmp = `${ROUTINES_FILE}.${process.pid}.tmp`;
54734
- (0, import_node_fs20.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
54735
- (0, import_node_fs20.renameSync)(tmp, ROUTINES_FILE);
54831
+ (0, import_node_fs21.writeFileSync)(tmp, JSON.stringify(routines, null, 2));
54832
+ (0, import_node_fs21.renameSync)(tmp, ROUTINES_FILE);
54736
54833
  }
54737
54834
  function listRoutines() {
54738
54835
  ensureLoaded();
@@ -55140,13 +55237,13 @@ var AppLifecycleError = class extends Error {
55140
55237
  }
55141
55238
  };
55142
55239
  function appsDir() {
55143
- return process.env.AWARE_HOME ? (0, import_node_path18.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path18.join)((0, import_node_os13.homedir)(), ".aware", "apps");
55240
+ return process.env.AWARE_HOME ? (0, import_node_path19.join)(process.env.AWARE_HOME, "apps") : (0, import_node_path19.join)((0, import_node_os14.homedir)(), ".aware", "apps");
55144
55241
  }
55145
55242
  function appDirPath(id) {
55146
- return (0, import_node_path18.join)(appsDir(), id);
55243
+ return (0, import_node_path19.join)(appsDir(), id);
55147
55244
  }
55148
55245
  function appInstalled(id) {
55149
- return APP_ID3.test(id) && (0, import_node_fs21.existsSync)(appDirPath(id));
55246
+ return APP_ID3.test(id) && (0, import_node_fs22.existsSync)(appDirPath(id));
55150
55247
  }
55151
55248
  function logCascade(what, e) {
55152
55249
  console.error(`[app-lifecycle] cascade step failed (${what}):`, e instanceof Error ? e.message : e);
@@ -55247,9 +55344,9 @@ function isGatedAwareRoute(url, method) {
55247
55344
 
55248
55345
  // autostart.mjs
55249
55346
  var import_node_child_process4 = require("node:child_process");
55250
- var import_node_fs22 = require("node:fs");
55251
- var import_node_os14 = require("node:os");
55252
- var import_node_path19 = require("node:path");
55347
+ var import_node_fs23 = require("node:fs");
55348
+ var import_node_os15 = require("node:os");
55349
+ var import_node_path20 = require("node:path");
55253
55350
 
55254
55351
  // teardown.mjs
55255
55352
  var RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
@@ -55361,8 +55458,8 @@ function removeLegacyRunKey() {
55361
55458
  }
55362
55459
  function logLine(msg) {
55363
55460
  try {
55364
- (0, import_node_fs22.mkdirSync)(logDir(), { recursive: true });
55365
- (0, import_node_fs22.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
55461
+ (0, import_node_fs23.mkdirSync)(logDir(), { recursive: true });
55462
+ (0, import_node_fs23.appendFileSync)(logFilePath(), `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
55366
55463
  `);
55367
55464
  } catch {
55368
55465
  }
@@ -55370,8 +55467,8 @@ function logLine(msg) {
55370
55467
  function registerAutostart(exePath) {
55371
55468
  if (!isWin) return;
55372
55469
  const xml = buildAutostartTaskXml(exePath, currentUserId());
55373
- const tmp = (0, import_node_path19.join)((0, import_node_os14.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
55374
- (0, import_node_fs22.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
55470
+ const tmp = (0, import_node_path20.join)((0, import_node_os15.tmpdir)(), `floless-autostart-${process.pid}-${Date.now()}.xml`);
55471
+ (0, import_node_fs23.writeFileSync)(tmp, "\uFEFF" + xml, { encoding: "utf16le" });
55375
55472
  try {
55376
55473
  (0, import_node_child_process4.execFileSync)("schtasks", ["/Create", "/TN", TASK_NAME, "/XML", tmp, "/F"], {
55377
55474
  stdio: ["ignore", "ignore", "ignore"],
@@ -55382,7 +55479,7 @@ function registerAutostart(exePath) {
55382
55479
  throw err;
55383
55480
  } finally {
55384
55481
  try {
55385
- (0, import_node_fs22.rmSync)(tmp, { force: true });
55482
+ (0, import_node_fs23.rmSync)(tmp, { force: true });
55386
55483
  } catch {
55387
55484
  }
55388
55485
  }
@@ -55417,26 +55514,26 @@ function unregisterAutostart() {
55417
55514
  // updater.ts
55418
55515
  var import_node_child_process5 = require("node:child_process");
55419
55516
  var import_node_crypto6 = require("node:crypto");
55420
- var import_node_fs24 = require("node:fs");
55517
+ var import_node_fs25 = require("node:fs");
55421
55518
  var import_node_stream = require("node:stream");
55422
55519
  var import_promises = require("node:stream/promises");
55423
- var import_node_path21 = require("node:path");
55520
+ var import_node_path22 = require("node:path");
55424
55521
 
55425
55522
  // post-update-marker.mjs
55426
- var import_node_fs23 = require("node:fs");
55427
- var import_node_os15 = require("node:os");
55428
- var import_node_path20 = require("node:path");
55523
+ var import_node_fs24 = require("node:fs");
55524
+ var import_node_os16 = require("node:os");
55525
+ var import_node_path21 = require("node:path");
55429
55526
  var FRESH_MS = 12e4;
55430
55527
  function markerPath() {
55431
55528
  const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
55432
55529
  if (override) return override;
55433
- const root = process.env.FLOLESS_HOME ?? (0, import_node_path20.join)((0, import_node_os15.homedir)(), ".floless");
55434
- return (0, import_node_path20.join)(root, ".post-update");
55530
+ const root = process.env.FLOLESS_HOME ?? (0, import_node_path21.join)((0, import_node_os16.homedir)(), ".floless");
55531
+ return (0, import_node_path21.join)(root, ".post-update");
55435
55532
  }
55436
55533
  function legacyMarkerPath() {
55437
55534
  if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
55438
55535
  try {
55439
- return (0, import_node_path20.join)((0, import_node_path20.dirname)((0, import_node_path20.dirname)(process.execPath)), ".floless-post-update");
55536
+ return (0, import_node_path21.join)((0, import_node_path21.dirname)((0, import_node_path21.dirname)(process.execPath)), ".floless-post-update");
55440
55537
  } catch {
55441
55538
  return null;
55442
55539
  }
@@ -55446,7 +55543,7 @@ function writePostUpdateMarker() {
55446
55543
  for (const p of [markerPath(), legacyMarkerPath()]) {
55447
55544
  if (!p) continue;
55448
55545
  try {
55449
- (0, import_node_fs23.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
55546
+ (0, import_node_fs24.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
55450
55547
  wrote = true;
55451
55548
  } catch {
55452
55549
  }
@@ -55458,9 +55555,9 @@ function consumePostUpdateMarker() {
55458
55555
  for (const p of [markerPath(), legacyMarkerPath()]) {
55459
55556
  if (!p) continue;
55460
55557
  try {
55461
- if (!(0, import_node_fs23.existsSync)(p)) continue;
55462
- const ageMs = Date.now() - (0, import_node_fs23.statSync)(p).mtimeMs;
55463
- (0, import_node_fs23.rmSync)(p, { force: true });
55558
+ if (!(0, import_node_fs24.existsSync)(p)) continue;
55559
+ const ageMs = Date.now() - (0, import_node_fs24.statSync)(p).mtimeMs;
55560
+ (0, import_node_fs24.rmSync)(p, { force: true });
55464
55561
  if (ageMs < FRESH_MS) fresh = true;
55465
55562
  } catch {
55466
55563
  }
@@ -55477,13 +55574,13 @@ function currentVersion() {
55477
55574
  return appVersion();
55478
55575
  }
55479
55576
  function installRoot() {
55480
- return (0, import_node_path21.dirname)((0, import_node_path21.dirname)(process.execPath));
55577
+ return (0, import_node_path22.dirname)((0, import_node_path22.dirname)(process.execPath));
55481
55578
  }
55482
55579
  function updateExePath() {
55483
- return (0, import_node_path21.join)(installRoot(), "Update.exe");
55580
+ return (0, import_node_path22.join)(installRoot(), "Update.exe");
55484
55581
  }
55485
55582
  function packagesDir() {
55486
- return (0, import_node_path21.join)(installRoot(), "packages");
55583
+ return (0, import_node_path22.join)(installRoot(), "packages");
55487
55584
  }
55488
55585
  function feedUrl() {
55489
55586
  const env2 = (process.env.FLOLESS_UPDATE_URL ?? "").trim().replace(/\/+$/, "");
@@ -55576,22 +55673,22 @@ async function checkForUpdate() {
55576
55673
  }
55577
55674
  async function sha1OfFile(path) {
55578
55675
  const hash = (0, import_node_crypto6.createHash)("sha1");
55579
- await (0, import_promises.pipeline)((0, import_node_fs24.createReadStream)(path), hash);
55676
+ await (0, import_promises.pipeline)((0, import_node_fs25.createReadStream)(path), hash);
55580
55677
  return hash.digest("hex").toUpperCase();
55581
55678
  }
55582
55679
  async function downloadPackage(asset) {
55583
55680
  if (!NUPKG_NAME.test(asset.FileName)) throw new Error(`refusing suspicious package name: ${asset.FileName}`);
55584
55681
  const want = asset.SHA1.toUpperCase();
55585
55682
  const dir = packagesDir();
55586
- (0, import_node_fs24.mkdirSync)(dir, { recursive: true });
55587
- const dest = (0, import_node_path21.join)(dir, asset.FileName);
55588
- if ((0, import_node_fs24.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
55683
+ (0, import_node_fs25.mkdirSync)(dir, { recursive: true });
55684
+ const dest = (0, import_node_path22.join)(dir, asset.FileName);
55685
+ if ((0, import_node_fs25.existsSync)(dest) && await sha1OfFile(dest) === want) return dest;
55589
55686
  const res = await authedFetch(`${feedUrl()}/${encodeURIComponent(asset.FileName)}`, {
55590
55687
  redirect: "follow",
55591
55688
  signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
55592
55689
  });
55593
55690
  if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status} for ${asset.FileName}`);
55594
- await (0, import_promises.pipeline)(import_node_stream.Readable.fromWeb(res.body), (0, import_node_fs24.createWriteStream)(dest));
55691
+ await (0, import_promises.pipeline)(import_node_stream.Readable.fromWeb(res.body), (0, import_node_fs25.createWriteStream)(dest));
55595
55692
  const got = await sha1OfFile(dest);
55596
55693
  if (got !== want) throw new Error(`SHA1 mismatch for ${asset.FileName}: feed=${want} got=${got}`);
55597
55694
  return dest;
@@ -55600,7 +55697,7 @@ async function applyUpdate(check, opts) {
55600
55697
  if (!check.supported) return { applied: false, message: check.reason ?? "auto-update not supported in this runtime" };
55601
55698
  if (!check.updateAvailable || !check.asset) return { applied: false, message: check.reason ?? "no update available" };
55602
55699
  const exe = updateExePath();
55603
- if (!(0, import_node_fs24.existsSync)(exe)) {
55700
+ if (!(0, import_node_fs25.existsSync)(exe)) {
55604
55701
  return { applied: false, message: `Update.exe not found at ${exe} \u2014 is this a Velopack install?` };
55605
55702
  }
55606
55703
  const pkg = await downloadPackage(check.asset);
@@ -55840,12 +55937,12 @@ function isTraceCorrupt(events) {
55840
55937
 
55841
55938
  // launch.mjs
55842
55939
  var import_node_child_process6 = require("node:child_process");
55843
- var import_node_path22 = require("node:path");
55844
- var import_node_url2 = require("node:url");
55845
- var import_node_fs25 = require("node:fs");
55940
+ var import_node_path23 = require("node:path");
55941
+ var import_node_url3 = require("node:url");
55942
+ var import_node_fs26 = require("node:fs");
55846
55943
  var import_node_http = __toESM(require("node:http"), 1);
55847
55944
  var import_node_readline = require("node:readline");
55848
- var __dirname2 = (0, import_node_path22.dirname)((0, import_node_url2.fileURLToPath)(__import_meta_url));
55945
+ var __dirname2 = (0, import_node_path23.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
55849
55946
  var PORT = Number(process.env.PORT ?? 4317);
55850
55947
  var HEALTH_URL = `http://127.0.0.1:${PORT}/api/health`;
55851
55948
  var BROWSER_URL = `http://floless.localhost:${PORT}`;
@@ -55917,8 +56014,8 @@ async function waitHealthy(timeoutMs = 3e4) {
55917
56014
  function resolveServerStart() {
55918
56015
  const packaged = /flolessapp\.exe$/i.test(process.execPath);
55919
56016
  if (packaged) return { cmd: process.execPath, args: ["--serve"], shell: false };
55920
- const bundle = (0, import_node_path22.join)(__dirname2, "dist", "floless-server.cjs");
55921
- if ((0, import_node_fs25.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
56017
+ const bundle = (0, import_node_path23.join)(__dirname2, "dist", "floless-server.cjs");
56018
+ if ((0, import_node_fs26.existsSync)(bundle)) return { cmd: process.execPath, args: [bundle, "--serve"], shell: false };
55922
56019
  return { cmd: "npm", args: ["run", "start"], shell: isWin2 };
55923
56020
  }
55924
56021
  function startServerDetached() {
@@ -56071,8 +56168,8 @@ function taskkillArgs(pid, { tree = true } = {}) {
56071
56168
  }
56072
56169
  function killSupervisor({ tree = true } = {}) {
56073
56170
  if (!isWin2) return;
56074
- const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path22.basename)(process.execPath));
56075
- const scriptMatch = isNpmChannel ? (0, import_node_path22.basename)((0, import_node_url2.fileURLToPath)(__import_meta_url)) : void 0;
56171
+ const isNpmChannel = /^node(\.exe)?$/i.test((0, import_node_path23.basename)(process.execPath));
56172
+ const scriptMatch = isNpmChannel ? (0, import_node_path23.basename)((0, import_node_url3.fileURLToPath)(__import_meta_url)) : void 0;
56076
56173
  const realExe = resolveRealInstallExe(process.execPath);
56077
56174
  const exeMatch = realExe === process.execPath ? process.execPath : [process.execPath, realExe];
56078
56175
  const pids = supervisorPidsToKill(enumerateProcesses(), process.pid, exeMatch, scriptMatch);
@@ -56237,7 +56334,7 @@ async function runAction(arg, flagArgv = [], selfVersion = null) {
56237
56334
  }
56238
56335
  await action(parseTeardownFlags(flagArgv));
56239
56336
  }
56240
- var entry = (0, import_node_path22.basename)(process.argv[1] ?? "").toLowerCase();
56337
+ var entry = (0, import_node_path23.basename)(process.argv[1] ?? "").toLowerCase();
56241
56338
  if (entry === "launch.mjs") {
56242
56339
  runAction(process.argv[2], process.argv.slice(3)).catch((e) => {
56243
56340
  log(`error: ${e?.message ?? e}`);
@@ -56311,11 +56408,11 @@ function awareUpgradeBlockReason(s) {
56311
56408
  }
56312
56409
 
56313
56410
  // skill-sync.ts
56314
- var import_node_fs26 = require("node:fs");
56315
- var import_node_os16 = require("node:os");
56316
- var import_node_path23 = require("node:path");
56317
- var import_node_url3 = require("node:url");
56318
- var import_yaml7 = __toESM(require_dist6(), 1);
56411
+ var import_node_fs27 = require("node:fs");
56412
+ var import_node_os17 = require("node:os");
56413
+ var import_node_path24 = require("node:path");
56414
+ var import_node_url4 = require("node:url");
56415
+ var import_yaml8 = __toESM(require_dist6(), 1);
56319
56416
 
56320
56417
  // build/ship-skills.mjs
56321
56418
  var PRODUCT_SKILLS = [
@@ -56348,33 +56445,33 @@ function selectShippedSkillNames(names) {
56348
56445
  }
56349
56446
 
56350
56447
  // skill-sync.ts
56351
- var __dirname3 = (0, import_node_path23.dirname)((0, import_node_url3.fileURLToPath)(__import_meta_url));
56448
+ var __dirname3 = (0, import_node_path24.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
56352
56449
  function bundledSkillsRoot() {
56353
56450
  const candidates = [
56354
- (0, import_node_path23.join)(__dirname3, "skills"),
56355
- (0, import_node_path23.join)((0, import_node_path23.dirname)(process.execPath), "skills"),
56356
- (0, import_node_path23.join)(__dirname3, "..", ".claude", "skills")
56451
+ (0, import_node_path24.join)(__dirname3, "skills"),
56452
+ (0, import_node_path24.join)((0, import_node_path24.dirname)(process.execPath), "skills"),
56453
+ (0, import_node_path24.join)(__dirname3, "..", ".claude", "skills")
56357
56454
  ];
56358
- return candidates.find((p) => (0, import_node_fs26.existsSync)(p)) ?? null;
56455
+ return candidates.find((p) => (0, import_node_fs27.existsSync)(p)) ?? null;
56359
56456
  }
56360
56457
  function targetConfigDirs() {
56361
56458
  const override = process.env.FLOLESS_SKILL_TARGETS;
56362
56459
  if (override) {
56363
56460
  return override.split(";").map((d) => d.trim()).filter(Boolean).map((dir) => ({ runtime: "custom", dir }));
56364
56461
  }
56365
- const home = (0, import_node_os16.homedir)();
56462
+ const home = (0, import_node_os17.homedir)();
56366
56463
  return [
56367
- { runtime: "claude", dir: (0, import_node_path23.join)(home, ".claude") },
56368
- { runtime: "codex", dir: (0, import_node_path23.join)(home, ".codex") },
56369
- { runtime: "opencode", dir: (0, import_node_path23.join)(home, ".opencode") }
56464
+ { runtime: "claude", dir: (0, import_node_path24.join)(home, ".claude") },
56465
+ { runtime: "codex", dir: (0, import_node_path24.join)(home, ".codex") },
56466
+ { runtime: "opencode", dir: (0, import_node_path24.join)(home, ".opencode") }
56370
56467
  ];
56371
56468
  }
56372
56469
  function skillVersion(skillMdPath) {
56373
56470
  try {
56374
- const text = (0, import_node_fs26.readFileSync)(skillMdPath, "utf8");
56471
+ const text = (0, import_node_fs27.readFileSync)(skillMdPath, "utf8");
56375
56472
  const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
56376
56473
  if (!m || m[1] === void 0) return null;
56377
- const fm = (0, import_yaml7.parse)(m[1]);
56474
+ const fm = (0, import_yaml8.parse)(m[1]);
56378
56475
  const meta = fm?.metadata;
56379
56476
  const v = meta?.version;
56380
56477
  return typeof v === "string" || typeof v === "number" ? String(v) : null;
@@ -56411,21 +56508,21 @@ function decideAction(installed, bundled) {
56411
56508
  function bundledSkills(root) {
56412
56509
  let entries = [];
56413
56510
  try {
56414
- entries = selectShippedSkillNames((0, import_node_fs26.readdirSync)(root));
56511
+ entries = selectShippedSkillNames((0, import_node_fs27.readdirSync)(root));
56415
56512
  } catch {
56416
56513
  return [];
56417
56514
  }
56418
56515
  const out = [];
56419
56516
  for (const name of entries) {
56420
- const dir = (0, import_node_path23.join)(root, name);
56517
+ const dir = (0, import_node_path24.join)(root, name);
56421
56518
  let isDir = false;
56422
56519
  try {
56423
- isDir = (0, import_node_fs26.statSync)(dir).isDirectory();
56520
+ isDir = (0, import_node_fs27.statSync)(dir).isDirectory();
56424
56521
  } catch {
56425
56522
  isDir = false;
56426
56523
  }
56427
56524
  if (!isDir) continue;
56428
- const v = skillVersion((0, import_node_path23.join)(dir, "SKILL.md"));
56525
+ const v = skillVersion((0, import_node_path24.join)(dir, "SKILL.md"));
56429
56526
  if (!v) continue;
56430
56527
  out.push({ name, dir, version: v });
56431
56528
  }
@@ -56438,17 +56535,17 @@ function syncSkills() {
56438
56535
  const skills = bundledSkills(root);
56439
56536
  if (!skills.length) return results;
56440
56537
  for (const { runtime, dir: cfg } of targetConfigDirs()) {
56441
- if (!(0, import_node_fs26.existsSync)(cfg)) continue;
56442
- const skillsDir = (0, import_node_path23.join)(cfg, "skills");
56538
+ if (!(0, import_node_fs27.existsSync)(cfg)) continue;
56539
+ const skillsDir = (0, import_node_path24.join)(cfg, "skills");
56443
56540
  for (const s of skills) {
56444
- const dest = (0, import_node_path23.join)(skillsDir, s.name);
56445
- const installedMd = (0, import_node_path23.join)(dest, "SKILL.md");
56446
- const installed = (0, import_node_fs26.existsSync)(installedMd) ? skillVersion(installedMd) : null;
56541
+ const dest = (0, import_node_path24.join)(skillsDir, s.name);
56542
+ const installedMd = (0, import_node_path24.join)(dest, "SKILL.md");
56543
+ const installed = (0, import_node_fs27.existsSync)(installedMd) ? skillVersion(installedMd) : null;
56447
56544
  const action = decideAction(installed, s.version);
56448
56545
  if (action === "installed" || action === "updated") {
56449
56546
  try {
56450
- if (action === "updated") (0, import_node_fs26.rmSync)(dest, { recursive: true, force: true });
56451
- (0, import_node_fs26.cpSync)(s.dir, dest, { recursive: true });
56547
+ if (action === "updated") (0, import_node_fs27.rmSync)(dest, { recursive: true, force: true });
56548
+ (0, import_node_fs27.cpSync)(s.dir, dest, { recursive: true });
56452
56549
  results.push({ runtime, skill: s.name, action, from: installed, to: s.version });
56453
56550
  } catch {
56454
56551
  }
@@ -56461,9 +56558,9 @@ function syncSkills() {
56461
56558
  }
56462
56559
 
56463
56560
  // watch.ts
56464
- var import_node_os17 = require("node:os");
56465
- var import_node_path25 = require("node:path");
56466
- var import_node_fs27 = require("node:fs");
56561
+ var import_node_os18 = require("node:os");
56562
+ var import_node_path26 = require("node:path");
56563
+ var import_node_fs28 = require("node:fs");
56467
56564
 
56468
56565
  // node_modules/chokidar/esm/index.js
56469
56566
  var import_fs2 = require("fs");
@@ -56474,7 +56571,7 @@ var sysPath2 = __toESM(require("path"), 1);
56474
56571
  // node_modules/readdirp/esm/index.js
56475
56572
  var import_promises2 = require("node:fs/promises");
56476
56573
  var import_node_stream2 = require("node:stream");
56477
- var import_node_path24 = require("node:path");
56574
+ var import_node_path25 = require("node:path");
56478
56575
  var EntryTypes = {
56479
56576
  FILE_TYPE: "files",
56480
56577
  DIR_TYPE: "directories",
@@ -56549,7 +56646,7 @@ var ReaddirpStream = class extends import_node_stream2.Readable {
56549
56646
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
56550
56647
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
56551
56648
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
56552
- this._root = (0, import_node_path24.resolve)(root);
56649
+ this._root = (0, import_node_path25.resolve)(root);
56553
56650
  this._isDirent = !opts.alwaysStat;
56554
56651
  this._statsProp = this._isDirent ? "dirent" : "stats";
56555
56652
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
@@ -56620,8 +56717,8 @@ var ReaddirpStream = class extends import_node_stream2.Readable {
56620
56717
  let entry2;
56621
56718
  const basename5 = this._isDirent ? dirent.name : dirent;
56622
56719
  try {
56623
- const fullPath = (0, import_node_path24.resolve)((0, import_node_path24.join)(path, basename5));
56624
- entry2 = { path: (0, import_node_path24.relative)(this._root, fullPath), fullPath, basename: basename5 };
56720
+ const fullPath = (0, import_node_path25.resolve)((0, import_node_path25.join)(path, basename5));
56721
+ entry2 = { path: (0, import_node_path25.relative)(this._root, fullPath), fullPath, basename: basename5 };
56625
56722
  entry2[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
56626
56723
  } catch (err) {
56627
56724
  this._onError(err);
@@ -56655,7 +56752,7 @@ var ReaddirpStream = class extends import_node_stream2.Readable {
56655
56752
  }
56656
56753
  if (entryRealPathStats.isDirectory()) {
56657
56754
  const len2 = entryRealPath.length;
56658
- if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path24.sep) {
56755
+ if (full.startsWith(entryRealPath) && full.substr(len2, 1) === import_node_path25.sep) {
56659
56756
  const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
56660
56757
  recursiveError.code = RECURSIVE_ERROR_CODE;
56661
56758
  return this._onError(recursiveError);
@@ -57194,9 +57291,9 @@ var NodeFsHandler = class {
57194
57291
  if (this.fsw.closed) {
57195
57292
  return;
57196
57293
  }
57197
- const dirname11 = sysPath.dirname(file);
57294
+ const dirname12 = sysPath.dirname(file);
57198
57295
  const basename5 = sysPath.basename(file);
57199
- const parent = this.fsw._getWatchedDir(dirname11);
57296
+ const parent = this.fsw._getWatchedDir(dirname12);
57200
57297
  let prevStats = stats;
57201
57298
  if (parent.has(basename5))
57202
57299
  return;
@@ -57223,7 +57320,7 @@ var NodeFsHandler = class {
57223
57320
  prevStats = newStats2;
57224
57321
  }
57225
57322
  } catch (error) {
57226
- this.fsw._remove(dirname11, basename5);
57323
+ this.fsw._remove(dirname12, basename5);
57227
57324
  }
57228
57325
  } else if (parent.has(basename5)) {
57229
57326
  const at = newStats.atimeMs;
@@ -58163,33 +58260,33 @@ function appIdFromLogPath(path) {
58163
58260
  return i >= 0 && parts[i + 1] ? parts[i + 1] : null;
58164
58261
  }
58165
58262
  function samePath(a, b) {
58166
- const ra = (0, import_node_path25.resolve)(a);
58167
- const rb = (0, import_node_path25.resolve)(b);
58263
+ const ra = (0, import_node_path26.resolve)(a);
58264
+ const rb = (0, import_node_path26.resolve)(b);
58168
58265
  return process.platform === "win32" ? ra.toLowerCase() === rb.toLowerCase() : ra === rb;
58169
58266
  }
58170
58267
  function underDir(path, dir) {
58171
- const rp = (0, import_node_path25.resolve)(path);
58172
- const rd = (0, import_node_path25.resolve)(dir);
58268
+ const rp = (0, import_node_path26.resolve)(path);
58269
+ const rd = (0, import_node_path26.resolve)(dir);
58173
58270
  const [p, d] = process.platform === "win32" ? [rp.toLowerCase(), rd.toLowerCase()] : [rp, rd];
58174
- return p === d || p.startsWith(d + import_node_path25.sep);
58271
+ return p === d || p.startsWith(d + import_node_path26.sep);
58175
58272
  }
58176
58273
  function startWatcher() {
58177
- const awareDir = process.env.AWARE_HOME ?? (0, import_node_path25.join)((0, import_node_os17.homedir)(), ".aware");
58178
- const credentialsDir = (0, import_node_path25.join)(awareDir, "credentials");
58179
- if (!(0, import_node_fs27.existsSync)(credentialsDir)) {
58274
+ const awareDir = process.env.AWARE_HOME ?? (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".aware");
58275
+ const credentialsDir = (0, import_node_path26.join)(awareDir, "credentials");
58276
+ if (!(0, import_node_fs28.existsSync)(credentialsDir)) {
58180
58277
  try {
58181
- (0, import_node_fs27.mkdirSync)(credentialsDir, { recursive: true });
58278
+ (0, import_node_fs28.mkdirSync)(credentialsDir, { recursive: true });
58182
58279
  } catch {
58183
58280
  }
58184
58281
  }
58185
- if (!(0, import_node_fs27.existsSync)(uiDir)) {
58282
+ if (!(0, import_node_fs28.existsSync)(uiDir)) {
58186
58283
  try {
58187
- (0, import_node_fs27.mkdirSync)(uiDir, { recursive: true });
58284
+ (0, import_node_fs28.mkdirSync)(uiDir, { recursive: true });
58188
58285
  } catch {
58189
58286
  }
58190
58287
  }
58191
- const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path25.join)(awareDir, d)).filter((p) => (0, import_node_fs27.existsSync)(p));
58192
- if ((0, import_node_fs27.existsSync)(uiDir)) targets.push(uiDir);
58288
+ const targets = ["apps", "logs", "credentials"].map((d) => (0, import_node_path26.join)(awareDir, d)).filter((p) => (0, import_node_fs28.existsSync)(p));
58289
+ if ((0, import_node_fs28.existsSync)(uiDir)) targets.push(uiDir);
58193
58290
  if (targets.length === 0) {
58194
58291
  return null;
58195
58292
  }
@@ -58218,11 +58315,11 @@ function startWatcher() {
58218
58315
  const isCredential = path.split(/[\\/]/).includes("credentials");
58219
58316
  const kind = isCredential ? "credential" : path.endsWith(".jsonl") ? "trace" : path.endsWith(".lock") ? "lock" : path.endsWith(".flo") || path.endsWith(".app") ? "source" : "file";
58220
58317
  broadcast({ type: "fs-change", kind, event, path });
58221
- if (kind === "trace" && event !== "unlink" && (0, import_node_fs27.existsSync)(path)) {
58318
+ if (kind === "trace" && event !== "unlink" && (0, import_node_fs28.existsSync)(path)) {
58222
58319
  const id = appIdFromLogPath(path);
58223
58320
  if (!id) return;
58224
58321
  try {
58225
- broadcast({ type: "trace-file", id, runId: path.split(import_node_path25.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs27.readFileSync)(path, "utf8")) });
58322
+ broadcast({ type: "trace-file", id, runId: path.split(import_node_path26.sep).pop()?.replace(/\.jsonl$/, "") ?? null, events: parseTrace((0, import_node_fs28.readFileSync)(path, "utf8")) });
58226
58323
  } catch {
58227
58324
  }
58228
58325
  }
@@ -58231,10 +58328,10 @@ function startWatcher() {
58231
58328
  }
58232
58329
 
58233
58330
  // index.ts
58234
- var __dirname4 = (0, import_node_path26.dirname)((0, import_node_url4.fileURLToPath)(__import_meta_url));
58235
- var WEB_ROOT = [(0, import_node_path26.join)(__dirname4, "web"), (0, import_node_path26.join)((0, import_node_path26.dirname)(process.execPath), "web"), (0, import_node_path26.join)(__dirname4, "..", "web")].find(
58236
- (p) => (0, import_node_fs28.existsSync)(p)
58237
- ) ?? (0, import_node_path26.join)(__dirname4, "..", "web");
58331
+ var __dirname4 = (0, import_node_path27.dirname)((0, import_node_url5.fileURLToPath)(__import_meta_url));
58332
+ var WEB_ROOT = [(0, import_node_path27.join)(__dirname4, "web"), (0, import_node_path27.join)((0, import_node_path27.dirname)(process.execPath), "web"), (0, import_node_path27.join)(__dirname4, "..", "web")].find(
58333
+ (p) => (0, import_node_fs29.existsSync)(p)
58334
+ ) ?? (0, import_node_path27.join)(__dirname4, "..", "web");
58238
58335
  var PORT2 = Number(process.env.PORT ?? 4317);
58239
58336
  var HOST = "127.0.0.1";
58240
58337
  var crashHandlersInstalled = false;
@@ -58250,7 +58347,7 @@ function installCrashHandlers() {
58250
58347
  ${stack}
58251
58348
  `;
58252
58349
  try {
58253
- (0, import_node_fs28.appendFileSync)(logFilePath(), line);
58350
+ (0, import_node_fs29.appendFileSync)(logFilePath(), line);
58254
58351
  } catch {
58255
58352
  }
58256
58353
  if (process.stderr.isTTY) process.stderr.write(line);
@@ -58515,6 +58612,73 @@ async function startServer() {
58515
58612
  const apps = await aware.list();
58516
58613
  return { ok: true, apps: apps.map((a) => ({ ...a, provider: appProvider(a.id), baked: appBaked(a.id) })) };
58517
58614
  });
58615
+ app.get("/api/workflows/updates", async () => {
58616
+ const apps = await aware.list();
58617
+ const installed = {};
58618
+ for (const a of apps) {
58619
+ try {
58620
+ installed[a.id] = readApp(a.id).version;
58621
+ } catch {
58622
+ }
58623
+ }
58624
+ return { ok: true, updates: detectUpdates(installed, loadTemplates()) };
58625
+ });
58626
+ const _wfUpdating = /* @__PURE__ */ new Set();
58627
+ app.post("/api/workflows/:id/update", async (req, reply) => {
58628
+ const id = req.params.id;
58629
+ const t = loadTemplates().find((x) => x.id === id);
58630
+ if (!t) return reply.status(404).send({ ok: false, error: `no bundled template for "${id}"`, code: "no-template" });
58631
+ if (t.publisher !== "floless") return reply.status(400).send({ ok: false, error: `"${id}" is not a FloLess-published workflow`, code: "not-published" });
58632
+ if (_wfUpdating.has(id)) return reply.status(409).send({ ok: false, error: `an update for "${id}" is already in progress`, code: "in-progress" });
58633
+ let fromVersion;
58634
+ let srcPath;
58635
+ let appDirPath2;
58636
+ try {
58637
+ const a = readApp(id);
58638
+ fromVersion = a.version;
58639
+ srcPath = a.source.path;
58640
+ appDirPath2 = appDir(id);
58641
+ } catch {
58642
+ return reply.status(404).send({ ok: false, error: `"${id}" is not installed`, code: "not-installed" });
58643
+ }
58644
+ if (compareSemver(t.version, fromVersion) <= 0) {
58645
+ return reply.status(409).send({ ok: false, error: `"${id}" is already at ${fromVersion}`, code: "up-to-date" });
58646
+ }
58647
+ const contract = readContract(id);
58648
+ if (contract == null && (0, import_node_fs29.existsSync)(contractPath(id))) {
58649
+ 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" });
58650
+ }
58651
+ if (contract != null) {
58652
+ const v = validateSteelTakeoff(contract);
58653
+ if (!v.valid) return reply.status(409).send({ ok: false, error: `"${id}"'s saved data is invalid \u2014 re-save it in the editor before updating`, code: "contract-invalid" });
58654
+ }
58655
+ _wfUpdating.add(id);
58656
+ const bdir = backupDir(id, fromVersion, Date.now());
58657
+ try {
58658
+ (0, import_node_fs29.mkdirSync)((0, import_node_path27.dirname)(bdir), { recursive: true });
58659
+ (0, import_node_fs29.cpSync)(appDirPath2, bdir, { recursive: true });
58660
+ (0, import_node_fs29.cpSync)(t.path, srcPath);
58661
+ if (contract != null) {
58662
+ bakeContractIntoApp(srcPath, contract);
58663
+ bakeDownstream(srcPath, contract);
58664
+ }
58665
+ await aware.compile(srcPath);
58666
+ broadcast({ type: "apps-changed", id });
58667
+ return { ok: true, id, fromVersion, toVersion: t.version, backupPath: bdir };
58668
+ } catch (e) {
58669
+ const msg = e instanceof Error ? e.message : String(e);
58670
+ try {
58671
+ (0, import_node_fs29.rmSync)(appDirPath2, { recursive: true, force: true });
58672
+ (0, import_node_fs29.cpSync)(bdir, appDirPath2, { recursive: true });
58673
+ } catch (re) {
58674
+ const rmsg = re instanceof Error ? re.message : String(re);
58675
+ return reply.status(500).send({ ok: false, error: `update failed (${msg}) AND rollback failed (${rmsg}) \u2014 restore manually from ${bdir}`, code: "rollback-failed", backupPath: bdir });
58676
+ }
58677
+ return reply.status(500).send({ ok: false, error: `update failed (rolled back to ${fromVersion}): ${msg}`, code: "update-failed" });
58678
+ } finally {
58679
+ _wfUpdating.delete(id);
58680
+ }
58681
+ });
58518
58682
  app.get("/api/agents", async () => {
58519
58683
  const agents = await aware.agentList();
58520
58684
  return { ok: true, agents };
@@ -58777,7 +58941,7 @@ async function startServer() {
58777
58941
  }
58778
58942
  const companionId = `${req.params.appId}-ifc`;
58779
58943
  const filename = `${req.params.appId}.ifc`;
58780
- const outPath = (0, import_node_path26.join)(appPath(companionId), filename);
58944
+ const outPath = (0, import_node_path27.join)(appPath(companionId), filename);
58781
58945
  let flo;
58782
58946
  try {
58783
58947
  flo = writeIfcApp(appPath(companionId), companionId, scene, outPath);
@@ -58800,8 +58964,8 @@ async function startServer() {
58800
58964
  }
58801
58965
  throw e;
58802
58966
  }
58803
- if (!(0, import_node_fs28.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
58804
- const content = (0, import_node_fs28.readFileSync)(outPath, "utf8");
58967
+ if (!(0, import_node_fs29.existsSync)(outPath)) return reply.send({ ok: false, error: "the IFC export produced no file" });
58968
+ const content = (0, import_node_fs29.readFileSync)(outPath, "utf8");
58805
58969
  broadcast({ type: "apps-changed" });
58806
58970
  return { ok: true, filename, content, bytes: Buffer.byteLength(content), skipped };
58807
58971
  });
@@ -58950,11 +59114,11 @@ async function startServer() {
58950
59114
  if (appExists(id)) {
58951
59115
  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 });
58952
59116
  }
58953
- const stageRoot = (0, import_node_fs28.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-import-"));
59117
+ const stageRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-import-"));
58954
59118
  try {
58955
- const stageDir = (0, import_node_path26.join)(stageRoot, id);
58956
- (0, import_node_fs28.mkdirSync)(stageDir);
58957
- (0, import_node_fs28.writeFileSync)((0, import_node_path26.join)(stageDir, `${id}.flo`), content);
59119
+ const stageDir = (0, import_node_path27.join)(stageRoot, id);
59120
+ (0, import_node_fs29.mkdirSync)(stageDir);
59121
+ (0, import_node_fs29.writeFileSync)((0, import_node_path27.join)(stageDir, `${id}.flo`), content);
58958
59122
  await aware.install(stageDir);
58959
59123
  } catch (err) {
58960
59124
  try {
@@ -58964,7 +59128,7 @@ async function startServer() {
58964
59128
  const msg = err instanceof AwareError ? err.message : String(err?.message ?? err);
58965
59129
  return reply.status(502).send({ ok: false, error: `import failed: ${msg}` });
58966
59130
  } finally {
58967
- (0, import_node_fs28.rmSync)(stageRoot, { recursive: true, force: true });
59131
+ (0, import_node_fs29.rmSync)(stageRoot, { recursive: true, force: true });
58968
59132
  }
58969
59133
  broadcast({ type: "apps-changed", id });
58970
59134
  return { ok: true, id };
@@ -58978,13 +59142,13 @@ async function startServer() {
58978
59142
  }
58979
59143
  const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
58980
59144
  const baked = bakeFloSource(appData.source.text, inputs);
58981
- const tmpRoot = (0, import_node_fs28.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-bake-"));
58982
- const backupDir = (0, import_node_path26.join)(tmpRoot, `${id}-backup`);
58983
- const bakeDir = (0, import_node_path26.join)(tmpRoot, id);
58984
- (0, import_node_fs28.cpSync)(appDir(id), backupDir, { recursive: true });
58985
- (0, import_node_fs28.cpSync)(appDir(id), bakeDir, { recursive: true });
59145
+ const tmpRoot = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-bake-"));
59146
+ const backupDir2 = (0, import_node_path27.join)(tmpRoot, `${id}-backup`);
59147
+ const bakeDir = (0, import_node_path27.join)(tmpRoot, id);
59148
+ (0, import_node_fs29.cpSync)(appDir(id), backupDir2, { recursive: true });
59149
+ (0, import_node_fs29.cpSync)(appDir(id), bakeDir, { recursive: true });
58986
59150
  const floName = appData.source.path.split(/[\\/]/).pop();
58987
- (0, import_node_fs28.writeFileSync)((0, import_node_path26.join)(bakeDir, floName), baked);
59151
+ (0, import_node_fs29.writeFileSync)((0, import_node_path27.join)(bakeDir, floName), baked);
58988
59152
  let appInstalled2 = true;
58989
59153
  try {
58990
59154
  await aware.uninstall(id);
@@ -58994,29 +59158,29 @@ async function startServer() {
58994
59158
  appInstalled2 = true;
58995
59159
  } catch (installErr) {
58996
59160
  try {
58997
- await aware.install(backupDir);
59161
+ await aware.install(backupDir2);
58998
59162
  appInstalled2 = true;
58999
59163
  } catch (restoreErr) {
59000
59164
  app.log.error({ id, tmpRoot, restoreErr: String(restoreErr) }, "bake: install AND restore failed \u2014 app uninstalled; backup retained");
59001
59165
  return reply.status(502).send({
59002
59166
  ok: false,
59003
- error: `bake failed and the app could not be restored \u2014 its source is backed up at ${backupDir}. Reinstall it from there with: aware app install "${backupDir}"`
59167
+ error: `bake failed and the app could not be restored \u2014 its source is backed up at ${backupDir2}. Reinstall it from there with: aware app install "${backupDir2}"`
59004
59168
  });
59005
59169
  }
59006
59170
  throw installErr;
59007
59171
  }
59008
59172
  try {
59009
- await aware.compile((0, import_node_path26.join)(appDir(id), floName));
59173
+ await aware.compile((0, import_node_path27.join)(appDir(id), floName));
59010
59174
  } catch (compileErr) {
59011
59175
  app.log.warn({ id, compileErr: String(compileErr) }, "bake: post-install recompile failed (app baked but may need a manual Compile)");
59012
59176
  }
59013
59177
  broadcast({ type: "baked", id });
59014
59178
  return { ok: true, id, agent: id, inputs };
59015
59179
  } finally {
59016
- if (appInstalled2) (0, import_node_fs28.rmSync)(tmpRoot, { recursive: true, force: true });
59180
+ if (appInstalled2) (0, import_node_fs29.rmSync)(tmpRoot, { recursive: true, force: true });
59017
59181
  }
59018
59182
  });
59019
- const graftAgentsDir = () => (0, import_node_path26.join)((0, import_node_os18.homedir)(), ".aware", "agents");
59183
+ const graftAgentsDir = () => (0, import_node_path27.join)((0, import_node_os19.homedir)(), ".aware", "agents");
59020
59184
  app.post("/api/graft/match", async (req, reply) => {
59021
59185
  const { glob } = req.body ?? {};
59022
59186
  if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
@@ -59033,7 +59197,7 @@ async function startServer() {
59033
59197
  if (!sourceKind || !sourceRef) {
59034
59198
  return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
59035
59199
  }
59036
- const tempHome = (0, import_node_fs28.mkdtempSync)((0, import_node_path26.join)((0, import_node_os18.tmpdir)(), "floless-graft-"));
59200
+ const tempHome = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os19.tmpdir)(), "floless-graft-"));
59037
59201
  let result;
59038
59202
  try {
59039
59203
  result = await aware.build({
@@ -59046,19 +59210,19 @@ async function startServer() {
59046
59210
  awareHome: tempHome
59047
59211
  });
59048
59212
  } catch (err) {
59049
- (0, import_node_fs28.rmSync)(tempHome, { recursive: true, force: true });
59213
+ (0, import_node_fs29.rmSync)(tempHome, { recursive: true, force: true });
59050
59214
  const msg = err instanceof AwareError ? err.message : String(err?.message ?? err);
59051
59215
  return reply.status(422).send({ ok: false, error: msg });
59052
59216
  }
59053
59217
  const manifest = readStagedManifest(result.agentDir);
59054
59218
  if (!manifest) {
59055
- (0, import_node_fs28.rmSync)(tempHome, { recursive: true, force: true });
59219
+ (0, import_node_fs29.rmSync)(tempHome, { recursive: true, force: true });
59056
59220
  return reply.status(502).send({ ok: false, error: `build produced output at ${result.agentDir} but no manifest.yaml` });
59057
59221
  }
59058
59222
  const token = (0, import_node_crypto7.randomUUID)();
59059
59223
  registerStage(token, tempHome, result.agentId);
59060
59224
  const preview = buildPreview(manifest, sourceKind, sourceRef, token);
59061
- if ((0, import_node_fs28.existsSync)((0, import_node_path26.join)(graftAgentsDir(), result.agentId))) {
59225
+ if ((0, import_node_fs29.existsSync)((0, import_node_path27.join)(graftAgentsDir(), result.agentId))) {
59062
59226
  preview.warnings.unshift(`An agent named "${result.agentId}" is already installed \u2014 creating it will overwrite it.`);
59063
59227
  }
59064
59228
  return { ok: true, preview };
@@ -59077,7 +59241,7 @@ async function startServer() {
59077
59241
  registerStage(stagedRef, stage.tempDir, stage.agentId);
59078
59242
  return reply.status(409).send({ ok: false, error: err.message, agentId: stage.agentId, collision: true });
59079
59243
  }
59080
- (0, import_node_fs28.rmSync)(stage.tempDir, { recursive: true, force: true });
59244
+ (0, import_node_fs29.rmSync)(stage.tempDir, { recursive: true, force: true });
59081
59245
  throw err;
59082
59246
  }
59083
59247
  broadcast({ type: "grafted", id: stage.agentId });
@@ -59310,11 +59474,11 @@ async function startServer() {
59310
59474
  app.get("/api/requests/:id/snapshot/:n", async (req, reply) => {
59311
59475
  const n = Number.parseInt(req.params.n, 10);
59312
59476
  const p = Number.isInteger(n) ? snapshotPathFor(req.params.id, n) : null;
59313
- if (!p || !(0, import_node_fs28.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
59477
+ if (!p || !(0, import_node_fs29.existsSync)(p)) return reply.status(404).send({ ok: false, error: "snapshot not found" });
59314
59478
  const ext = p.split(".").pop().toLowerCase();
59315
59479
  reply.header("Content-Type", ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "pdf" ? "application/pdf" : "image/jpeg");
59316
59480
  reply.header("Cache-Control", "no-store");
59317
- return (0, import_node_fs28.readFileSync)(p);
59481
+ return (0, import_node_fs29.readFileSync)(p);
59318
59482
  });
59319
59483
  app.post(
59320
59484
  "/api/tweak",
@@ -59464,7 +59628,7 @@ async function startServer() {
59464
59628
  warn(`last-run-status:${ref} \u2014 trace exists but couldn't be parsed (corrupt/truncated)`);
59465
59629
  let finishedAt2 = null;
59466
59630
  try {
59467
- finishedAt2 = (0, import_node_fs28.statSync)(latest.path).mtime.toISOString();
59631
+ finishedAt2 = (0, import_node_fs29.statSync)(latest.path).mtime.toISOString();
59468
59632
  } catch {
59469
59633
  finishedAt2 = null;
59470
59634
  }
@@ -59474,7 +59638,7 @@ async function startServer() {
59474
59638
  let finishedAt = typeof runEnd?.ts === "string" ? runEnd.ts : null;
59475
59639
  if (!finishedAt) {
59476
59640
  try {
59477
- finishedAt = (0, import_node_fs28.statSync)(latest.path).mtime.toISOString();
59641
+ finishedAt = (0, import_node_fs29.statSync)(latest.path).mtime.toISOString();
59478
59642
  } catch {
59479
59643
  finishedAt = null;
59480
59644
  }