@lotics/cli 0.165.0 → 0.172.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/src/cli.js CHANGED
@@ -26822,12 +26822,12 @@ var require_tokens = __commonJS({
26822
26822
  });
26823
26823
  }
26824
26824
  exports2.assignCategoriesMapProp = assignCategoriesMapProp;
26825
- function singleAssignCategoriesToksMap(path14, nextNode) {
26826
- utils_1.forEach(path14, function(pathNode) {
26825
+ function singleAssignCategoriesToksMap(path13, nextNode) {
26826
+ utils_1.forEach(path13, function(pathNode) {
26827
26827
  nextNode.categoryMatchesMap[pathNode.tokenTypeIdx] = true;
26828
26828
  });
26829
26829
  utils_1.forEach(nextNode.CATEGORIES, function(nextCategory) {
26830
- var newPath = path14.concat(nextNode);
26830
+ var newPath = path13.concat(nextNode);
26831
26831
  if (!utils_1.contains(newPath, nextCategory)) {
26832
26832
  singleAssignCategoriesToksMap(newPath, nextCategory);
26833
26833
  }
@@ -28590,10 +28590,10 @@ var require_interpreter = __commonJS({
28590
28590
  /** @class */
28591
28591
  (function(_super) {
28592
28592
  __extends(AbstractNextPossibleTokensWalker2, _super);
28593
- function AbstractNextPossibleTokensWalker2(topProd, path14) {
28593
+ function AbstractNextPossibleTokensWalker2(topProd, path13) {
28594
28594
  var _this = _super.call(this) || this;
28595
28595
  _this.topProd = topProd;
28596
- _this.path = path14;
28596
+ _this.path = path13;
28597
28597
  _this.possibleTokTypes = [];
28598
28598
  _this.nextProductionName = "";
28599
28599
  _this.nextProductionOccurrence = 0;
@@ -28647,9 +28647,9 @@ var require_interpreter = __commonJS({
28647
28647
  /** @class */
28648
28648
  (function(_super) {
28649
28649
  __extends(NextAfterTokenWalker2, _super);
28650
- function NextAfterTokenWalker2(topProd, path14) {
28651
- var _this = _super.call(this, topProd, path14) || this;
28652
- _this.path = path14;
28650
+ function NextAfterTokenWalker2(topProd, path13) {
28651
+ var _this = _super.call(this, topProd, path13) || this;
28652
+ _this.path = path13;
28653
28653
  _this.nextTerminalName = "";
28654
28654
  _this.nextTerminalOccurrence = 0;
28655
28655
  _this.nextTerminalName = _this.path.lastTok.name;
@@ -29346,10 +29346,10 @@ var require_lookahead = __commonJS({
29346
29346
  }
29347
29347
  return result;
29348
29348
  }
29349
- function pathToHashKeys(path14) {
29349
+ function pathToHashKeys(path13) {
29350
29350
  var keys3 = [""];
29351
- for (var i2 = 0; i2 < path14.length; i2++) {
29352
- var tokType = path14[i2];
29351
+ for (var i2 = 0; i2 < path13.length; i2++) {
29352
+ var tokType = path13[i2];
29353
29353
  var longerKeys = [];
29354
29354
  for (var j = 0; j < keys3.length; j++) {
29355
29355
  var currShorterKey = keys3[j];
@@ -29661,9 +29661,9 @@ var require_checks = __commonJS({
29661
29661
  return errors2;
29662
29662
  }
29663
29663
  exports2.validateRuleIsOverridden = validateRuleIsOverridden;
29664
- function validateNoLeftRecursion(topRule, currRule, errMsgProvider, path14) {
29665
- if (path14 === void 0) {
29666
- path14 = [];
29664
+ function validateNoLeftRecursion(topRule, currRule, errMsgProvider, path13) {
29665
+ if (path13 === void 0) {
29666
+ path13 = [];
29667
29667
  }
29668
29668
  var errors2 = [];
29669
29669
  var nextNonTerminals = getFirstNoneTerminal(currRule.definition);
@@ -29676,15 +29676,15 @@ var require_checks = __commonJS({
29676
29676
  errors2.push({
29677
29677
  message: errMsgProvider.buildLeftRecursionError({
29678
29678
  topLevelRule: topRule,
29679
- leftRecursionPath: path14
29679
+ leftRecursionPath: path13
29680
29680
  }),
29681
29681
  type: parser_1.ParserDefinitionErrorType.LEFT_RECURSION,
29682
29682
  ruleName
29683
29683
  });
29684
29684
  }
29685
- var validNextSteps = utils2.difference(nextNonTerminals, path14.concat([topRule]));
29685
+ var validNextSteps = utils2.difference(nextNonTerminals, path13.concat([topRule]));
29686
29686
  var errorsFromNextSteps = utils2.map(validNextSteps, function(currRefRule) {
29687
- var newPath = utils2.cloneArr(path14);
29687
+ var newPath = utils2.cloneArr(path13);
29688
29688
  newPath.push(currRefRule);
29689
29689
  return validateNoLeftRecursion(topRule, currRefRule, errMsgProvider, newPath);
29690
29690
  });
@@ -37293,8 +37293,8 @@ var require_utils4 = __commonJS({
37293
37293
  var result = transform2[inputType][outputType](input);
37294
37294
  return result;
37295
37295
  };
37296
- exports2.resolve = function(path14) {
37297
- var parts = path14.split("/");
37296
+ exports2.resolve = function(path13) {
37297
+ var parts = path13.split("/");
37298
37298
  var result = [];
37299
37299
  for (var index = 0; index < parts.length; index++) {
37300
37300
  var part = parts[index];
@@ -43147,18 +43147,18 @@ var require_object = __commonJS({
43147
43147
  var object2 = new ZipObject(name2, zipObjectContent, o);
43148
43148
  this.files[name2] = object2;
43149
43149
  };
43150
- var parentFolder = function(path14) {
43151
- if (path14.slice(-1) === "/") {
43152
- path14 = path14.substring(0, path14.length - 1);
43150
+ var parentFolder = function(path13) {
43151
+ if (path13.slice(-1) === "/") {
43152
+ path13 = path13.substring(0, path13.length - 1);
43153
43153
  }
43154
- var lastSlash = path14.lastIndexOf("/");
43155
- return lastSlash > 0 ? path14.substring(0, lastSlash) : "";
43154
+ var lastSlash = path13.lastIndexOf("/");
43155
+ return lastSlash > 0 ? path13.substring(0, lastSlash) : "";
43156
43156
  };
43157
- var forceTrailingSlash = function(path14) {
43158
- if (path14.slice(-1) !== "/") {
43159
- path14 += "/";
43157
+ var forceTrailingSlash = function(path13) {
43158
+ if (path13.slice(-1) !== "/") {
43159
+ path13 += "/";
43160
43160
  }
43161
- return path14;
43161
+ return path13;
43162
43162
  };
43163
43163
  var folderAdd = function(name2, createFolders) {
43164
43164
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults2.createFolders;
@@ -44162,7 +44162,7 @@ import dns from "node:dns";
44162
44162
  import net2 from "node:net";
44163
44163
  import fs14 from "node:fs";
44164
44164
  import os4 from "node:os";
44165
- import path13 from "node:path";
44165
+ import path12 from "node:path";
44166
44166
  import readline from "node:readline";
44167
44167
 
44168
44168
  // ../shared/src/transport_error.ts
@@ -44301,6 +44301,26 @@ function getMimeType(filename) {
44301
44301
  return MIME_MAP[ext] ?? "application/octet-stream";
44302
44302
  }
44303
44303
  var API_BASE_URL = process.env.LOTICS_API_URL ?? "https://api.lotics.ai";
44304
+ var WEB_APP_URL = "https://lotics.ai";
44305
+ async function fetchOfficialStarters() {
44306
+ let response;
44307
+ try {
44308
+ response = await fetch(`${API_BASE_URL}/v1/starters/official`, {
44309
+ signal: AbortSignal.timeout(SHELF_FETCH_TIMEOUT_MS)
44310
+ });
44311
+ } catch (error52) {
44312
+ throw new Error(
44313
+ `Could not reach Lotics to list the starters (${error52 instanceof Error ? error52.message : String(error52)}). Check your connection, or browse ${WEB_APP_URL}/docs/cli.`
44314
+ );
44315
+ }
44316
+ if (!response.ok) {
44317
+ throw new Error(
44318
+ `Lotics answered ${response.status} listing the starters. If this keeps happening, browse ${WEB_APP_URL}/docs/cli.`
44319
+ );
44320
+ }
44321
+ return await response.json();
44322
+ }
44323
+ var SHELF_FETCH_TIMEOUT_MS = 1e4;
44304
44324
  var LoticsClient = class {
44305
44325
  apiKey;
44306
44326
  workspaceId;
@@ -44358,8 +44378,8 @@ var LoticsClient = class {
44358
44378
  }
44359
44379
  return headers;
44360
44380
  }
44361
- async request(method, path14, body) {
44362
- const url2 = `${this.baseUrl}${path14}`;
44381
+ async request(method, path13, body) {
44382
+ const url2 = `${this.baseUrl}${path13}`;
44363
44383
  const headers = this.buildHeaders();
44364
44384
  const init = { method, headers };
44365
44385
  if (body !== void 0) {
@@ -45605,11 +45625,15 @@ function isNewerVersion(latest, current) {
45605
45625
  if (lMin !== cMin) return lMin > cMin;
45606
45626
  return lPat > cPat;
45607
45627
  }
45628
+ function updateCommand() {
45629
+ if (process.versions.bun === void 0) return "npm i -g @lotics/cli";
45630
+ return process.platform === "win32" ? "irm https://lotics.ai/install.ps1 | iex" : "curl -fsSL https://lotics.ai/install.sh | bash";
45631
+ }
45608
45632
  function printUpdateWarning(current, latest) {
45609
45633
  if (!isNewerVersion(latest, current)) return;
45610
45634
  console.error(`
45611
45635
  Update available: ${current} \u2192 ${latest}`);
45612
- console.error(`Run: npm i -g @lotics/cli
45636
+ console.error(`Run: ${updateCommand()}
45613
45637
  `);
45614
45638
  }
45615
45639
 
@@ -45672,17 +45696,22 @@ function resultSideEffects(result) {
45672
45696
  }
45673
45697
 
45674
45698
  // src/version.ts
45675
- import { readFileSync } from "node:fs";
45676
- import { fileURLToPath } from "node:url";
45677
- import path5 from "node:path";
45678
- var pkgPath = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../../package.json");
45679
- var pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
45680
- var VERSION = pkg.version;
45699
+ var VERSION = "0.172.0";
45700
+
45701
+ // src/timezone.ts
45702
+ function machineTimezone() {
45703
+ try {
45704
+ const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
45705
+ return zone !== void 0 && zone !== "" ? zone : void 0;
45706
+ } catch {
45707
+ return void 0;
45708
+ }
45709
+ }
45681
45710
 
45682
45711
  // src/docs_command.ts
45683
45712
  import fs5 from "node:fs";
45684
- import path6 from "node:path";
45685
- import { fileURLToPath as fileURLToPath2 } from "node:url";
45713
+ import path5 from "node:path";
45714
+ import { fileURLToPath } from "node:url";
45686
45715
  var READING_ORDER = ["@lotics/app-sdk", "@lotics/ui", "@lotics/cli"];
45687
45716
  function firstHeading(file2) {
45688
45717
  let text;
@@ -45699,35 +45728,35 @@ function firstHeading(file2) {
45699
45728
  }
45700
45729
  function readVersion(pkgDir) {
45701
45730
  try {
45702
- const raw = fs5.readFileSync(path6.join(pkgDir, "package.json"), "utf-8");
45731
+ const raw = fs5.readFileSync(path5.join(pkgDir, "package.json"), "utf-8");
45703
45732
  return JSON.parse(raw).version ?? "?";
45704
45733
  } catch {
45705
45734
  return "?";
45706
45735
  }
45707
45736
  }
45708
45737
  function ownPackageDir() {
45709
- return path6.resolve(path6.dirname(fileURLToPath2(import.meta.url)), "../..");
45738
+ return path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "../..");
45710
45739
  }
45711
45740
  function referencePackageDirs(projectDir) {
45712
45741
  const found = /* @__PURE__ */ new Map();
45713
45742
  for (let dir = projectDir; ; ) {
45714
- const scope = path6.join(dir, "node_modules", "@lotics");
45743
+ const scope = path5.join(dir, "node_modules", "@lotics");
45715
45744
  if (fs5.existsSync(scope)) {
45716
45745
  for (const name2 of fs5.readdirSync(scope)) {
45717
- const pkgDir = path6.join(scope, name2);
45718
- const carries = fs5.existsSync(path6.join(pkgDir, "AGENTS.md")) || fs5.existsSync(path6.join(pkgDir, "docs"));
45746
+ const pkgDir = path5.join(scope, name2);
45747
+ const carries = fs5.existsSync(path5.join(pkgDir, "AGENTS.md")) || fs5.existsSync(path5.join(pkgDir, "docs"));
45719
45748
  if (carries && !found.has(`@lotics/${name2}`)) found.set(`@lotics/${name2}`, pkgDir);
45720
45749
  }
45721
45750
  }
45722
- const parent = path6.dirname(dir);
45751
+ const parent = path5.dirname(dir);
45723
45752
  if (parent === dir) break;
45724
45753
  dir = parent;
45725
45754
  }
45726
45755
  const own = ownPackageDir();
45727
- if (!found.has("@lotics/cli") && fs5.existsSync(path6.join(own, "AGENTS.md"))) {
45756
+ if (!found.has("@lotics/cli") && fs5.existsSync(path5.join(own, "AGENTS.md"))) {
45728
45757
  found.set("@lotics/cli", own);
45729
45758
  }
45730
- return [...found.entries()].map(([pkg2, dir]) => ({ pkg: pkg2, dir })).sort((a, b) => {
45759
+ return [...found.entries()].map(([pkg, dir]) => ({ pkg, dir })).sort((a, b) => {
45731
45760
  const ia = READING_ORDER.indexOf(a.pkg);
45732
45761
  const ib = READING_ORDER.indexOf(b.pkg);
45733
45762
  if (ia !== ib) return (ia < 0 ? READING_ORDER.length : ia) - (ib < 0 ? READING_ORDER.length : ib);
@@ -45736,26 +45765,26 @@ function referencePackageDirs(projectDir) {
45736
45765
  }
45737
45766
  function collectDocAreas(projectDir) {
45738
45767
  const found = [];
45739
- for (const { pkg: pkg2, dir } of referencePackageDirs(projectDir)) {
45768
+ for (const { pkg, dir } of referencePackageDirs(projectDir)) {
45740
45769
  const version2 = readVersion(dir);
45741
- const index = path6.join(dir, "AGENTS.md");
45770
+ const index = path5.join(dir, "AGENTS.md");
45742
45771
  if (fs5.existsSync(index)) {
45743
45772
  found.push({
45744
- area: pkg2.replace("@lotics/", ""),
45745
- pkg: pkg2,
45773
+ area: pkg.replace("@lotics/", ""),
45774
+ pkg,
45746
45775
  version: version2,
45747
45776
  absPath: index,
45748
45777
  title: firstHeading(index)
45749
45778
  });
45750
45779
  }
45751
- const docsDir = path6.join(dir, "docs");
45780
+ const docsDir = path5.join(dir, "docs");
45752
45781
  if (!fs5.existsSync(docsDir)) continue;
45753
45782
  for (const file2 of fs5.readdirSync(docsDir).sort()) {
45754
45783
  if (!file2.endsWith(".md")) continue;
45755
- const abs2 = path6.join(docsDir, file2);
45784
+ const abs2 = path5.join(docsDir, file2);
45756
45785
  found.push({
45757
45786
  area: file2.replace(/\.md$/, ""),
45758
- pkg: pkg2,
45787
+ pkg,
45759
45788
  version: version2,
45760
45789
  absPath: abs2,
45761
45790
  title: firstHeading(abs2)
@@ -45802,7 +45831,7 @@ ${a.pkg} ${a.version}`);
45802
45831
  return lines.join("\n");
45803
45832
  }
45804
45833
  function docsCommand(args) {
45805
- const projectDir = path6.resolve(args.projectDir ?? process.cwd());
45834
+ const projectDir = path5.resolve(args.projectDir ?? process.cwd());
45806
45835
  const areas = collectDocAreas(projectDir);
45807
45836
  if (args.area === void 0 || args.area === "") {
45808
45837
  console.log(renderDocIndex(areas));
@@ -45824,13 +45853,26 @@ function docsCommand(args) {
45824
45853
  process.exit(1);
45825
45854
  }
45826
45855
  const hit = hits[0];
45827
- console.error(`${hit.pkg} ${hit.version} \xB7 ${path6.relative(projectDir, hit.absPath)}
45856
+ console.error(`${hit.pkg} ${hit.version} \xB7 ${path5.relative(projectDir, hit.absPath)}
45828
45857
  `);
45829
45858
  process.stdout.write(fs5.readFileSync(hit.absPath, "utf-8"));
45830
45859
  }
45831
45860
 
45832
45861
  // src/commands.ts
45833
45862
  var COMMANDS = [
45863
+ {
45864
+ verbs: ["start"],
45865
+ help: [
45866
+ " lotics start <starter_id> [path] --email <you@co.com>",
45867
+ " First run, one command: create an account if this",
45868
+ " machine has none, then copy the starter into its",
45869
+ " workspace \u2014 schema, templates, knowledge docs,",
45870
+ " sample records, a deployed app \u2014 and print a",
45871
+ " one-time sign-in link. Drop --email to copy into",
45872
+ " the account you already have. --json prints one",
45873
+ " object and nothing else"
45874
+ ]
45875
+ },
45834
45876
  {
45835
45877
  verbs: ["org"],
45836
45878
  help: [
@@ -45859,7 +45901,9 @@ var COMMANDS = [
45859
45901
  {
45860
45902
  verbs: ["starter"],
45861
45903
  help: [
45862
- " lotics starter list Starters you can copy into this workspace",
45904
+ " lotics starter list Starters you can copy into this workspace. Works with",
45905
+ " NO account \u2014 it then lists the published shelf, so you",
45906
+ " can decide whether to copy one or build before signing up",
45863
45907
  " lotics starter show <starter_id> What one carries: tables, docs, templates, sample data",
45864
45908
  " lotics starter init <starter_id> [path]",
45865
45909
  " Copy it in \u2014 schema, templates, knowledge docs,",
@@ -46046,7 +46090,7 @@ function matchesKnownFlag(known, arg) {
46046
46090
 
46047
46091
  // src/report_command.ts
46048
46092
  import fs6 from "node:fs";
46049
- import path7 from "node:path";
46093
+ import path6 from "node:path";
46050
46094
  var LIMITS = { goal: 2e3, expected: 2e3, actual: 4e3, tried: 4e3, wanted: 2e3 };
46051
46095
  var REPORT_USAGE = `Usage: lotics report '<json>' lotics report @report.json \u2026 | lotics report -
46052
46096
 
@@ -46107,9 +46151,9 @@ function parseReport(raw) {
46107
46151
  }
46108
46152
  function appIdOf(projectDir) {
46109
46153
  try {
46110
- const raw = fs6.readFileSync(path7.join(projectDir, "package.json"), "utf-8");
46111
- const pkg2 = JSON.parse(raw);
46112
- const appId = pkg2.lotics?.app_id;
46154
+ const raw = fs6.readFileSync(path6.join(projectDir, "package.json"), "utf-8");
46155
+ const pkg = JSON.parse(raw);
46156
+ const appId = pkg.lotics?.app_id;
46113
46157
  return typeof appId === "string" && appId !== "" ? appId : void 0;
46114
46158
  } catch {
46115
46159
  return void 0;
@@ -46147,7 +46191,7 @@ async function reportCommand(client, options) {
46147
46191
 
46148
46192
  // src/app_commands.ts
46149
46193
  import fs8 from "node:fs";
46150
- import path10 from "node:path";
46194
+ import path9 from "node:path";
46151
46195
  import { spawn as spawn2 } from "node:child_process";
46152
46196
  import { createHash as createHash3 } from "node:crypto";
46153
46197
  import { tmpdir } from "node:os";
@@ -46914,7 +46958,7 @@ function escapeHtml(s) {
46914
46958
  import http from "node:http";
46915
46959
  import net from "node:net";
46916
46960
  import { existsSync } from "node:fs";
46917
- import path8 from "node:path";
46961
+ import path7 from "node:path";
46918
46962
  import { spawn } from "node:child_process";
46919
46963
 
46920
46964
  // src/child_env.ts
@@ -47498,6 +47542,9 @@ var STOP_DEADLINE_MS = 2e3;
47498
47542
  function serializeRpcResult(result) {
47499
47543
  return JSON.stringify(result ?? null);
47500
47544
  }
47545
+ function nodeForChildProcess() {
47546
+ return process.versions.bun === void 0 ? process.execPath : "node";
47547
+ }
47501
47548
  async function startDevServer(args) {
47502
47549
  const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
47503
47550
  const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
@@ -47509,14 +47556,14 @@ async function startDevServer(args) {
47509
47556
  vite_url: viteUrl,
47510
47557
  api_url: args.api_url
47511
47558
  });
47512
- const viteEntry = path8.join(args.projectDir, "node_modules", "vite", "bin", "vite.js");
47559
+ const viteEntry = path7.join(args.projectDir, "node_modules", "vite", "bin", "vite.js");
47513
47560
  if (!existsSync(viteEntry)) {
47514
47561
  throw new Error(
47515
47562
  `Vite is not installed in ${args.projectDir} \u2014 run \`npm install\` there first.`
47516
47563
  );
47517
47564
  }
47518
47565
  const viteChild = spawn(
47519
- process.execPath,
47566
+ nodeForChildProcess(),
47520
47567
  [viteEntry, "--port", String(vitePort), "--strictPort"],
47521
47568
  {
47522
47569
  cwd: args.projectDir,
@@ -47871,6 +47918,36 @@ function openBrowser(url2) {
47871
47918
  child.unref();
47872
47919
  }
47873
47920
 
47921
+ // src/output.ts
47922
+ var machineMode = false;
47923
+ var collectedWarnings = [];
47924
+ function setMachineOutput(on) {
47925
+ machineMode = on;
47926
+ }
47927
+ function isMachineOutput() {
47928
+ return machineMode;
47929
+ }
47930
+ function note(text) {
47931
+ if (machineMode) return;
47932
+ console.error(text);
47933
+ }
47934
+ function warn(text) {
47935
+ if (machineMode) {
47936
+ collectedWarnings.push(text);
47937
+ return;
47938
+ }
47939
+ console.error(text);
47940
+ }
47941
+ function emitJson(value2) {
47942
+ const payload = collectedWarnings.length > 0 ? { ...value2, warnings: [...collectedWarnings] } : value2;
47943
+ collectedWarnings.length = 0;
47944
+ console.log(JSON.stringify(payload, null, 2));
47945
+ }
47946
+ function flushPendingWarnings() {
47947
+ for (const text of collectedWarnings) console.error(text);
47948
+ collectedWarnings.length = 0;
47949
+ }
47950
+
47874
47951
  // ../shared/src/app_dts.ts
47875
47952
  var IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
47876
47953
  function isValidIdentifier(name2) {
@@ -48437,7 +48514,7 @@ export type AppOptions = typeof OPT;
48437
48514
 
48438
48515
  // src/app_workflow_check.ts
48439
48516
  import fs7 from "node:fs";
48440
- import path9 from "node:path";
48517
+ import path8 from "node:path";
48441
48518
  import { createRequire } from "node:module";
48442
48519
 
48443
48520
  // ../shared/src/parse_workflow_js.ts
@@ -49209,10 +49286,10 @@ function mergeDefs(...defs) {
49209
49286
  function cloneDef(schema) {
49210
49287
  return mergeDefs(schema._zod.def);
49211
49288
  }
49212
- function getElementAtPath(obj, path14) {
49213
- if (!path14)
49289
+ function getElementAtPath(obj, path13) {
49290
+ if (!path13)
49214
49291
  return obj;
49215
- return path14.reduce((acc, key) => acc?.[key], obj);
49292
+ return path13.reduce((acc, key) => acc?.[key], obj);
49216
49293
  }
49217
49294
  function promiseAllObject(promisesObj) {
49218
49295
  const keys3 = Object.keys(promisesObj);
@@ -49621,11 +49698,11 @@ function explicitlyAborted(x2, startIndex = 0) {
49621
49698
  }
49622
49699
  return false;
49623
49700
  }
49624
- function prefixIssues(path14, issues) {
49701
+ function prefixIssues(path13, issues) {
49625
49702
  return issues.map((iss) => {
49626
49703
  var _a4;
49627
49704
  (_a4 = iss).path ?? (_a4.path = []);
49628
- iss.path.unshift(path14);
49705
+ iss.path.unshift(path13);
49629
49706
  return iss;
49630
49707
  });
49631
49708
  }
@@ -49772,16 +49849,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
49772
49849
  }
49773
49850
  function formatError(error52, mapper = (issue2) => issue2.message) {
49774
49851
  const fieldErrors = { _errors: [] };
49775
- const processError = (error53, path14 = []) => {
49852
+ const processError = (error53, path13 = []) => {
49776
49853
  for (const issue2 of error53.issues) {
49777
49854
  if (issue2.code === "invalid_union" && issue2.errors.length) {
49778
- issue2.errors.map((issues) => processError({ issues }, [...path14, ...issue2.path]));
49855
+ issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
49779
49856
  } else if (issue2.code === "invalid_key") {
49780
- processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
49857
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
49781
49858
  } else if (issue2.code === "invalid_element") {
49782
- processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
49859
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
49783
49860
  } else {
49784
- const fullpath = [...path14, ...issue2.path];
49861
+ const fullpath = [...path13, ...issue2.path];
49785
49862
  if (fullpath.length === 0) {
49786
49863
  fieldErrors._errors.push(mapper(issue2));
49787
49864
  } else {
@@ -49808,17 +49885,17 @@ function formatError(error52, mapper = (issue2) => issue2.message) {
49808
49885
  }
49809
49886
  function treeifyError(error52, mapper = (issue2) => issue2.message) {
49810
49887
  const result = { errors: [] };
49811
- const processError = (error53, path14 = []) => {
49888
+ const processError = (error53, path13 = []) => {
49812
49889
  var _a4, _b2;
49813
49890
  for (const issue2 of error53.issues) {
49814
49891
  if (issue2.code === "invalid_union" && issue2.errors.length) {
49815
- issue2.errors.map((issues) => processError({ issues }, [...path14, ...issue2.path]));
49892
+ issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
49816
49893
  } else if (issue2.code === "invalid_key") {
49817
- processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
49894
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
49818
49895
  } else if (issue2.code === "invalid_element") {
49819
- processError({ issues: issue2.issues }, [...path14, ...issue2.path]);
49896
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
49820
49897
  } else {
49821
- const fullpath = [...path14, ...issue2.path];
49898
+ const fullpath = [...path13, ...issue2.path];
49822
49899
  if (fullpath.length === 0) {
49823
49900
  result.errors.push(mapper(issue2));
49824
49901
  continue;
@@ -49850,8 +49927,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
49850
49927
  }
49851
49928
  function toDotPath(_path) {
49852
49929
  const segs = [];
49853
- const path14 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
49854
- for (const seg of path14) {
49930
+ const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
49931
+ for (const seg of path13) {
49855
49932
  if (typeof seg === "number")
49856
49933
  segs.push(`[${seg}]`);
49857
49934
  else if (typeof seg === "symbol")
@@ -62543,13 +62620,13 @@ function resolveRef(ref2, ctx) {
62543
62620
  if (!ref2.startsWith("#")) {
62544
62621
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
62545
62622
  }
62546
- const path14 = ref2.slice(1).split("/").filter(Boolean);
62547
- if (path14.length === 0) {
62623
+ const path13 = ref2.slice(1).split("/").filter(Boolean);
62624
+ if (path13.length === 0) {
62548
62625
  return ctx.rootSchema;
62549
62626
  }
62550
62627
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
62551
- if (path14[0] === defsKey) {
62552
- const key = path14[1];
62628
+ if (path13[0] === defsKey) {
62629
+ const key = path13[1];
62553
62630
  if (!key || !ctx.defs[key]) {
62554
62631
  throw new Error(`Reference not found: ${ref2}`);
62555
62632
  }
@@ -67305,9 +67382,9 @@ __export(expression_object_exports, {
67305
67382
  pick: () => pick3,
67306
67383
  values: () => values2
67307
67384
  });
67308
- function getNestedValue(obj, path14) {
67385
+ function getNestedValue(obj, path13) {
67309
67386
  if (obj == null) return void 0;
67310
- const parts = path14.split(".");
67387
+ const parts = path13.split(".");
67311
67388
  let value2 = obj;
67312
67389
  for (const part of parts) {
67313
67390
  if (value2 == null) return void 0;
@@ -67346,11 +67423,11 @@ function entries(obj) {
67346
67423
  }
67347
67424
  return Object.entries(obj);
67348
67425
  }
67349
- function get(obj, path14, defaultValue) {
67350
- if (typeof path14 !== "string") {
67426
+ function get(obj, path13, defaultValue) {
67427
+ if (typeof path13 !== "string") {
67351
67428
  throw new Error("get: path must be a string");
67352
67429
  }
67353
- const value2 = getNestedValue(obj, path14);
67430
+ const value2 = getNestedValue(obj, path13);
67354
67431
  return value2 !== void 0 ? value2 : defaultValue;
67355
67432
  }
67356
67433
  function pick3(obj, fields) {
@@ -69246,17 +69323,17 @@ function readFromChanges(chain2) {
69246
69323
  if (first3.kind === "bracket-number" || first3.kind === "bracket-expr") {
69247
69324
  fail(first3.node, "changes is keyed by field name, not numeric index.");
69248
69325
  }
69249
- const path14 = [{ at: "key", key: first3.key }];
69326
+ const path13 = [{ at: "key", key: first3.key }];
69250
69327
  for (const seg of segments.slice(1)) {
69251
69328
  if (seg.kind === "bracket-number") {
69252
- path14.push({ at: "index", index: seg.index });
69329
+ path13.push({ at: "index", index: seg.index });
69253
69330
  } else if (seg.kind === "bracket-expr") {
69254
- path14.push({ at: "index", index: seg.expr });
69331
+ path13.push({ at: "index", index: seg.expr });
69255
69332
  } else {
69256
- path14.push({ at: "key", key: seg.key });
69333
+ path13.push({ at: "key", key: seg.key });
69257
69334
  }
69258
69335
  }
69259
- return { kind: "read", source: { from: "trigger_changes" }, path: path14 };
69336
+ return { kind: "read", source: { from: "trigger_changes" }, path: path13 };
69260
69337
  });
69261
69338
  }
69262
69339
  var TRIGGER_RECORD_VIEWS = /* @__PURE__ */ new Map([
@@ -69274,17 +69351,17 @@ function readFromTrigger(chain2) {
69274
69351
  return view === "trigger_changes" ? readFromChanges(lowered) : readFromRecord(view, lowered);
69275
69352
  }
69276
69353
  return wrapOptionalGuards(chain2, (segments) => {
69277
- const path14 = [];
69354
+ const path13 = [];
69278
69355
  for (const seg of segments) {
69279
69356
  if (seg.kind === "bracket-number") {
69280
- path14.push({ at: "index", index: seg.index });
69357
+ path13.push({ at: "index", index: seg.index });
69281
69358
  } else if (seg.kind === "bracket-expr") {
69282
- path14.push({ at: "index", index: seg.expr });
69359
+ path13.push({ at: "index", index: seg.expr });
69283
69360
  } else {
69284
- path14.push({ at: "key", key: seg.key });
69361
+ path13.push({ at: "key", key: seg.key });
69285
69362
  }
69286
69363
  }
69287
- return { kind: "read", source: { from: "trigger" }, path: path14 };
69364
+ return { kind: "read", source: { from: "trigger" }, path: path13 };
69288
69365
  });
69289
69366
  }
69290
69367
  function readFromRuntime(chain2) {
@@ -69306,17 +69383,17 @@ function readFromRuntime(chain2) {
69306
69383
  const parked = PARKED_RUNTIME_KEYS.get(key);
69307
69384
  if (parked) fail(first3.node, parked, parkedRuntimeKeyConstruct(key));
69308
69385
  const source = { from: "runtime", key };
69309
- const path14 = [];
69386
+ const path13 = [];
69310
69387
  for (const seg of segments.slice(1)) {
69311
69388
  if (seg.kind === "bracket-number") {
69312
- path14.push({ at: "index", index: seg.index });
69389
+ path13.push({ at: "index", index: seg.index });
69313
69390
  } else if (seg.kind === "bracket-expr") {
69314
- path14.push({ at: "index", index: seg.expr });
69391
+ path13.push({ at: "index", index: seg.expr });
69315
69392
  } else {
69316
- path14.push({ at: "key", key: seg.key });
69393
+ path13.push({ at: "key", key: seg.key });
69317
69394
  }
69318
69395
  }
69319
- return { kind: "read", source, path: path14 };
69396
+ return { kind: "read", source, path: path13 };
69320
69397
  });
69321
69398
  }
69322
69399
  function readFromForeachItem(name2, chain2) {
@@ -69355,17 +69432,17 @@ function readFromLexical(name2, chain2) {
69355
69432
  }
69356
69433
  function readFromStepOutput(stepId, chain2) {
69357
69434
  return wrapOptionalGuards(chain2, (segments) => {
69358
- const path14 = [];
69435
+ const path13 = [];
69359
69436
  for (const seg of segments) {
69360
69437
  if (seg.kind === "bracket-number") {
69361
- path14.push({ at: "index", index: seg.index });
69438
+ path13.push({ at: "index", index: seg.index });
69362
69439
  } else if (seg.kind === "bracket-expr") {
69363
- path14.push({ at: "index", index: seg.expr });
69440
+ path13.push({ at: "index", index: seg.expr });
69364
69441
  } else {
69365
- path14.push({ at: "key", key: seg.key });
69442
+ path13.push({ at: "key", key: seg.key });
69366
69443
  }
69367
69444
  }
69368
- return { kind: "read", source: { from: "step_output", step_id: stepId }, path: path14 };
69445
+ return { kind: "read", source: { from: "step_output", step_id: stepId }, path: path13 };
69369
69446
  });
69370
69447
  }
69371
69448
  function classifyRecordPath(segs) {
@@ -71038,7 +71115,7 @@ function subsetIssues(bodySource, offset) {
71038
71115
  ];
71039
71116
  }
71040
71117
  async function loadProjectTypescript(projectDir) {
71041
- const requireFromProject = createRequire(path9.join(projectDir, "package.json"));
71118
+ const requireFromProject = createRequire(path8.join(projectDir, "package.json"));
71042
71119
  let resolved;
71043
71120
  try {
71044
71121
  resolved = requireFromProject.resolve("typescript");
@@ -71051,9 +71128,9 @@ async function loadProjectTypescript(projectDir) {
71051
71128
  return mod2.default ?? mod2;
71052
71129
  }
71053
71130
  function pathToImportUrl(p) {
71054
- const resolved = path9.resolve(p);
71131
+ const resolved = path8.resolve(p);
71055
71132
  const prefixed = resolved.startsWith("/") ? resolved : `/${resolved}`;
71056
- return `file://${prefixed.split(path9.sep).join("/")}`;
71133
+ return `file://${prefixed.split(path8.sep).join("/")}`;
71057
71134
  }
71058
71135
  function checkOneWorkflowBody(tsApi, input) {
71059
71136
  const wrapped = fs7.readFileSync(input.bodyPath, "utf-8");
@@ -71103,7 +71180,7 @@ function checkOneWorkflowBody(tsApi, input) {
71103
71180
  }
71104
71181
  function createCheckedSourceHost(tsApi, options, bodyPath, bodyText) {
71105
71182
  const base = tsApi.createCompilerHost(options, false);
71106
- const key = (fileName) => base.getCanonicalFileName(path9.resolve(fileName).replace(/\\/g, "/"));
71183
+ const key = (fileName) => base.getCanonicalFileName(path8.resolve(fileName).replace(/\\/g, "/"));
71107
71184
  const bodyKey = key(bodyPath);
71108
71185
  return {
71109
71186
  ...base,
@@ -71229,10 +71306,10 @@ function syncedEntry(entry) {
71229
71306
  }
71230
71307
  function readSynced(projectDir) {
71231
71308
  try {
71232
- const pkg2 = JSON.parse(
71233
- fs8.readFileSync(path10.join(projectDir, "package.json"), "utf-8")
71309
+ const pkg = JSON.parse(
71310
+ fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8")
71234
71311
  );
71235
- const raw = pkg2.lotics?.synced ?? {};
71312
+ const raw = pkg.lotics?.synced ?? {};
71236
71313
  return {
71237
71314
  workflows: normalizeSyncedMap(raw.workflows),
71238
71315
  agents: normalizeSyncedMap(raw.agents),
@@ -71251,19 +71328,19 @@ function normalizeSyncedMap(map3) {
71251
71328
  );
71252
71329
  }
71253
71330
  function writeSynced(projectDir, kind, alias, entry) {
71254
- const pkgPath2 = path10.join(projectDir, "package.json");
71255
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71256
- if (!pkg2.lotics) return;
71257
- pkg2.lotics.synced ??= {};
71258
- pkg2.lotics.synced[kind] = { ...pkg2.lotics.synced[kind], [alias]: entry };
71259
- fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
71331
+ const pkgPath = path9.join(projectDir, "package.json");
71332
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71333
+ if (!pkg.lotics) return;
71334
+ pkg.lotics.synced ??= {};
71335
+ pkg.lotics.synced[kind] = { ...pkg.lotics.synced[kind], [alias]: entry };
71336
+ fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
71260
71337
  }
71261
71338
  function readManifestEntry(projectDir, kind, alias) {
71262
- const pkg2 = readManifest(projectDir);
71263
- if (!pkg2.lotics) return { found: false };
71339
+ const pkg = readManifest(projectDir);
71340
+ if (!pkg.lotics) return { found: false };
71264
71341
  const entry = { found: true };
71265
71342
  let found = false;
71266
- const declarations = pkg2.lotics[kind];
71343
+ const declarations = pkg.lotics[kind];
71267
71344
  if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
71268
71345
  const map3 = declarations;
71269
71346
  if (alias in map3) {
@@ -71271,7 +71348,7 @@ function readManifestEntry(projectDir, kind, alias) {
71271
71348
  found = true;
71272
71349
  }
71273
71350
  }
71274
- const baselines = pkg2.lotics.synced?.[kind];
71351
+ const baselines = pkg.lotics.synced?.[kind];
71275
71352
  if (baselines && alias in baselines) {
71276
71353
  entry.synced = baselines[alias];
71277
71354
  found = true;
@@ -71279,31 +71356,31 @@ function readManifestEntry(projectDir, kind, alias) {
71279
71356
  return found ? entry : { found: false };
71280
71357
  }
71281
71358
  function readManifest(projectDir) {
71282
- const pkgPath2 = path10.join(projectDir, "package.json");
71283
- return JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71359
+ const pkgPath = path9.join(projectDir, "package.json");
71360
+ return JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71284
71361
  }
71285
71362
  function removeFromManifest(projectDir, kind, alias) {
71286
- const pkgPath2 = path10.join(projectDir, "package.json");
71287
- const pkg2 = readManifest(projectDir);
71288
- if (!pkg2.lotics) return;
71289
- const declarations = pkg2.lotics[kind];
71363
+ const pkgPath = path9.join(projectDir, "package.json");
71364
+ const pkg = readManifest(projectDir);
71365
+ if (!pkg.lotics) return;
71366
+ const declarations = pkg.lotics[kind];
71290
71367
  if (declarations && typeof declarations === "object" && !Array.isArray(declarations)) {
71291
71368
  delete declarations[alias];
71292
71369
  }
71293
- const baselines = pkg2.lotics.synced?.[kind];
71370
+ const baselines = pkg.lotics.synced?.[kind];
71294
71371
  if (baselines) delete baselines[alias];
71295
- fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
71372
+ fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
71296
71373
  }
71297
71374
  function parkPrunedDeclaration(projectDir, kind, alias, removed) {
71298
- const dir = path10.join(projectDir, ".lotics", "pruned", kind);
71375
+ const dir = path9.join(projectDir, ".lotics", "pruned", kind);
71299
71376
  fs8.mkdirSync(dir, { recursive: true });
71300
- const file2 = path10.join(dir, `${alias}.json`);
71377
+ const file2 = path9.join(dir, `${alias}.json`);
71301
71378
  fs8.writeFileSync(file2, JSON.stringify(removed, null, 2) + "\n");
71302
- return path10.relative(projectDir, file2);
71379
+ return path9.relative(projectDir, file2);
71303
71380
  }
71304
- var WORKFLOWS_DIR = path10.join("src", "workflows");
71305
- var WORKFLOW_GLOBALS_DIR = path10.join(".lotics", "workflows");
71306
- var AGENTS_DIR = path10.join("src", "agents");
71381
+ var WORKFLOWS_DIR = path9.join("src", "workflows");
71382
+ var WORKFLOW_GLOBALS_DIR = path9.join(".lotics", "workflows");
71383
+ var AGENTS_DIR = path9.join("src", "agents");
71307
71384
  var WORKFLOW_TSCONFIG_EXCLUDES = ["src/workflows", ".lotics/workflows"];
71308
71385
  var LOTICS_INCLUDE_GLOB = ".lotics/**/*";
71309
71386
  var STALE_LOTICS_INCLUDES = /* @__PURE__ */ new Set([".lotics", "./.lotics", ".lotics/"]);
@@ -71314,7 +71391,7 @@ function isMissingWorkflowBodyError(error52) {
71314
71391
  return /has no step source|cannot be rendered|unsupported step/i.test(error52);
71315
71392
  }
71316
71393
  function workflowFileHeader(alias) {
71317
- const refPath = path10.join("..", "..", WORKFLOW_GLOBALS_DIR, `${alias}.globals.d.ts`).split(path10.sep).join("/");
71394
+ const refPath = path9.join("..", "..", WORKFLOW_GLOBALS_DIR, `${alias}.globals.d.ts`).split(path9.sep).join("/");
71318
71395
  return (
71319
71396
  // The scaffold ships oxlint, whose `triple-slash-reference` rule flags the
71320
71397
  // line below — so every pulled body arrived with a warning its author could
@@ -71337,27 +71414,27 @@ export {};
71337
71414
  );
71338
71415
  }
71339
71416
  function workflowFilePath(projectDir, alias) {
71340
- return path10.join(projectDir, WORKFLOWS_DIR, `${alias}.ts`);
71417
+ return path9.join(projectDir, WORKFLOWS_DIR, `${alias}.ts`);
71341
71418
  }
71342
71419
  var GLOBALS_SUFFIX = ".globals.d.ts";
71343
71420
  function workflowGlobalsPath(projectDir, alias) {
71344
- return path10.join(projectDir, WORKFLOW_GLOBALS_DIR, `${alias}${GLOBALS_SUFFIX}`);
71421
+ return path9.join(projectDir, WORKFLOW_GLOBALS_DIR, `${alias}${GLOBALS_SUFFIX}`);
71345
71422
  }
71346
71423
  function pruneOrphanWorkflowGlobals(projectDir, declared) {
71347
- const dir = path10.join(projectDir, WORKFLOW_GLOBALS_DIR);
71424
+ const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
71348
71425
  if (!fs8.existsSync(dir)) return [];
71349
71426
  const removed = [];
71350
71427
  for (const entry of fs8.readdirSync(dir)) {
71351
71428
  if (!entry.endsWith(GLOBALS_SUFFIX)) continue;
71352
71429
  const alias = entry.slice(0, -GLOBALS_SUFFIX.length);
71353
71430
  if (declared.has(alias)) continue;
71354
- fs8.unlinkSync(path10.join(dir, entry));
71431
+ fs8.unlinkSync(path9.join(dir, entry));
71355
71432
  removed.push(alias);
71356
71433
  }
71357
71434
  return removed.sort();
71358
71435
  }
71359
71436
  function orphanWorkflowBodies(projectDir, declared) {
71360
- const dir = path10.join(projectDir, WORKFLOWS_DIR);
71437
+ const dir = path9.join(projectDir, WORKFLOWS_DIR);
71361
71438
  if (!fs8.existsSync(dir)) return [];
71362
71439
  return fs8.readdirSync(dir).filter((e) => e.endsWith(".ts") && !e.endsWith(".d.ts") && !e.endsWith(".test.ts")).map((e) => e.slice(0, -".ts".length)).filter((alias) => !declared.has(alias)).sort();
71363
71440
  }
@@ -71395,7 +71472,7 @@ function staleWorkflowGlobals(projectDir, workflows) {
71395
71472
  return out;
71396
71473
  }
71397
71474
  function writeWorkflowGlobals(projectDir, alias, dts, declaration) {
71398
- const dir = path10.join(projectDir, WORKFLOW_GLOBALS_DIR);
71475
+ const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
71399
71476
  fs8.mkdirSync(dir, { recursive: true });
71400
71477
  const file2 = workflowGlobalsPath(projectDir, alias);
71401
71478
  const stamp = `${GLOBALS_STAMP_PREFIX}${workflowDeclarationStamp(declaration)}`;
@@ -71408,7 +71485,7 @@ function normalizeWorkflowBody(source) {
71408
71485
  return source.replace(/\s+$/, "");
71409
71486
  }
71410
71487
  function writeWorkflowFile(projectDir, alias, source, envelope2 = { prefix: WORKFLOW_ENVELOPE_PREFIX, suffix: WORKFLOW_ENVELOPE_SUFFIX }) {
71411
- const dir = path10.join(projectDir, WORKFLOWS_DIR);
71488
+ const dir = path9.join(projectDir, WORKFLOWS_DIR);
71412
71489
  fs8.mkdirSync(dir, { recursive: true });
71413
71490
  const file2 = workflowFilePath(projectDir, alias);
71414
71491
  const body = normalizeWorkflowBody(source);
@@ -71418,14 +71495,14 @@ ${envelope2.prefix}${body}${envelope2.suffix}
71418
71495
  return file2;
71419
71496
  }
71420
71497
  function agentFilePath2(projectDir, alias) {
71421
- return path10.join(projectDir, ...agentFilePath(alias).split("/"));
71498
+ return path9.join(projectDir, ...agentFilePath(alias).split("/"));
71422
71499
  }
71423
71500
  var CLI_AGENT_NOTES = [
71424
71501
  "Pulled from the LIVE app row; edit here, then: lotics app agent set <alias>",
71425
71502
  "The typed fields (inputs/outputs/tool_names/model_tier) live in package.json#lotics.agents"
71426
71503
  ];
71427
71504
  function writeAgentFile(projectDir, alias, instructions) {
71428
- fs8.mkdirSync(path10.join(projectDir, AGENTS_DIR), { recursive: true });
71505
+ fs8.mkdirSync(path9.join(projectDir, AGENTS_DIR), { recursive: true });
71429
71506
  const file2 = agentFilePath2(projectDir, alias);
71430
71507
  fs8.writeFileSync(
71431
71508
  file2,
@@ -71451,15 +71528,15 @@ function writeAgentFiles(projectDir, agents, opts) {
71451
71528
  return written;
71452
71529
  }
71453
71530
  function parkLiveAgentProse(projectDir, alias, instructions) {
71454
- const dir = path10.join(projectDir, ".lotics", "agents");
71455
- const file2 = path10.join(dir, `${alias}.live.md`);
71531
+ const dir = path9.join(projectDir, ".lotics", "agents");
71532
+ const file2 = path9.join(dir, `${alias}.live.md`);
71456
71533
  try {
71457
71534
  fs8.mkdirSync(dir, { recursive: true });
71458
71535
  fs8.writeFileSync(file2, normalizeAgentInstructions(instructions) + "\n");
71459
- return path10.relative(projectDir, file2);
71536
+ return path9.relative(projectDir, file2);
71460
71537
  } catch (err2) {
71461
71538
  console.error(
71462
- `\u26A0 Could not write the live prose for ${alias} to ${path10.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
71539
+ `\u26A0 Could not write the live prose for ${alias} to ${path9.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
71463
71540
  );
71464
71541
  return null;
71465
71542
  }
@@ -71475,15 +71552,15 @@ function reportUnseenLive(kind, unseen, appId) {
71475
71552
  );
71476
71553
  }
71477
71554
  function parkLiveWorkflowBody(projectDir, alias, source) {
71478
- const dir = path10.join(projectDir, WORKFLOW_GLOBALS_DIR);
71479
- const file2 = path10.join(dir, `${alias}.live.ts`);
71555
+ const dir = path9.join(projectDir, WORKFLOW_GLOBALS_DIR);
71556
+ const file2 = path9.join(dir, `${alias}.live.ts`);
71480
71557
  try {
71481
71558
  fs8.mkdirSync(dir, { recursive: true });
71482
71559
  fs8.writeFileSync(file2, normalizeWorkflowBody(source) + "\n");
71483
- return path10.relative(projectDir, file2);
71560
+ return path9.relative(projectDir, file2);
71484
71561
  } catch (err2) {
71485
71562
  console.error(
71486
- `\u26A0 Could not write the live body for ${alias} to ${path10.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
71563
+ `\u26A0 Could not write the live body for ${alias} to ${path9.relative(projectDir, file2)}: ${err2 instanceof Error ? err2.message : String(err2)}`
71487
71564
  );
71488
71565
  return null;
71489
71566
  }
@@ -71573,12 +71650,12 @@ async function writeWorkflowFiles(client, projectDir, app_id, appName, workflows
71573
71650
  return { written, kept, unseenLive };
71574
71651
  }
71575
71652
  function writeWorkflowDescription(projectDir, alias, description) {
71576
- const pkgPath2 = path10.join(projectDir, "package.json");
71577
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71578
- const declaration = pkg2.lotics?.workflows?.[alias];
71653
+ const pkgPath = path9.join(projectDir, "package.json");
71654
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71655
+ const declaration = pkg.lotics?.workflows?.[alias];
71579
71656
  if (!declaration) return;
71580
71657
  declaration.description = description;
71581
- fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
71658
+ fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
71582
71659
  }
71583
71660
  async function fetchWorkflowGlobals(client, projectDir, app_id, alias, declaration) {
71584
71661
  try {
@@ -71616,63 +71693,128 @@ function runTar(args, cwd) {
71616
71693
  });
71617
71694
  });
71618
71695
  }
71696
+ function npmIsInstalled() {
71697
+ return new Promise((resolve2) => {
71698
+ const probe = spawn2("npm", ["--version"], {
71699
+ shell: process.platform === "win32",
71700
+ stdio: "ignore",
71701
+ env: ipv4ChildEnv(process.env)
71702
+ });
71703
+ probe.on("error", () => resolve2(false));
71704
+ probe.on("exit", (code) => resolve2(code === 0));
71705
+ });
71706
+ }
71619
71707
  function runNpm(args, cwd) {
71708
+ const quiet = isMachineOutput();
71620
71709
  return new Promise((resolve2, reject2) => {
71621
- const proc = spawn2("npm", args, { cwd, stdio: "inherit", env: ipv4ChildEnv(process.env) });
71622
- proc.on("error", reject2);
71710
+ const proc = spawn2("npm", args, {
71711
+ cwd,
71712
+ // On Windows `npm` is `npm.cmd`, a batch file Node will not execute
71713
+ // without a shell — bare `spawn("npm")` dies at ENOENT, which took every
71714
+ // command that installs or builds with it. A shell is safe here because
71715
+ // the arguments are literals this file writes (`run build`, `ci
71716
+ // --ignore-scripts`); nothing a caller supplies reaches the command line.
71717
+ //
71718
+ // The alternative — run npm's own JS entry with `process.execPath`, as
71719
+ // `dev/server.ts` does for vite — works there because vite sits at a known
71720
+ // path inside the project. npm does not: nvm-windows, volta, corepack and
71721
+ // the installer each put it somewhere different, and letting the platform
71722
+ // resolve its own shim is the one approach that finds all of them.
71723
+ shell: process.platform === "win32",
71724
+ stdio: quiet ? ["ignore", "pipe", "pipe"] : "inherit",
71725
+ env: ipv4ChildEnv(process.env)
71726
+ });
71727
+ let captured = "";
71728
+ if (quiet) {
71729
+ const collect = (chunk) => {
71730
+ captured += chunk.toString();
71731
+ if (captured.length > NPM_LOG_TAIL_BYTES * 2) {
71732
+ captured = captured.slice(-NPM_LOG_TAIL_BYTES);
71733
+ }
71734
+ };
71735
+ proc.stdout?.on("data", collect);
71736
+ proc.stderr?.on("data", collect);
71737
+ }
71738
+ proc.on("error", (error52) => void failed(error52, null));
71623
71739
  proc.on("exit", (code) => {
71624
- if (code === 0) resolve2();
71625
- else reject2(new Error(`npm ${args.join(" ")} exited with code ${code}`));
71740
+ if (code === 0) {
71741
+ resolve2();
71742
+ return;
71743
+ }
71744
+ void failed(void 0, code);
71626
71745
  });
71746
+ async function failed(error52, code) {
71747
+ if (!await npmIsInstalled()) {
71748
+ reject2(
71749
+ new Error(
71750
+ "npm was not found, and building an app needs it.\n Install Node.js 18 or newer (npm comes with it), then run this again:\n https://nodejs.org/en/download\n The Lotics CLI itself needs no Node \u2014 only this build step does."
71751
+ )
71752
+ );
71753
+ return;
71754
+ }
71755
+ if (error52 !== void 0) {
71756
+ reject2(error52);
71757
+ return;
71758
+ }
71759
+ const tail = captured.slice(-NPM_LOG_TAIL_BYTES).trim();
71760
+ reject2(
71761
+ new Error(
71762
+ `npm ${args.join(" ")} exited with code ${code}` + (tail === "" ? "" : `
71763
+ --- npm output ---
71764
+ ${tail}`)
71765
+ )
71766
+ );
71767
+ }
71627
71768
  });
71628
71769
  }
71770
+ var NPM_LOG_TAIL_BYTES = 8e3;
71629
71771
  function npmInstallArgs(hasLockfile) {
71630
71772
  return [hasLockfile ? "ci" : "install", "--ignore-scripts"];
71631
71773
  }
71632
71774
  function runNpmInstall(cwd) {
71633
- const hasLockfile = fs8.existsSync(path10.join(cwd, "package-lock.json"));
71634
- console.error(
71775
+ const hasLockfile = fs8.existsSync(path9.join(cwd, "package-lock.json"));
71776
+ note(
71635
71777
  hasLockfile ? "Installing npm dependencies (npm ci \u2014 the lockfile's exact tree, no install scripts)..." : "Installing npm dependencies (no lockfile yet \u2014 resolving ranges, no install scripts)..."
71636
71778
  );
71637
71779
  return runNpm(npmInstallArgs(hasLockfile), cwd);
71638
71780
  }
71639
71781
  function readAppWorkspaceId(projectDir) {
71640
71782
  try {
71641
- const pkgPath2 = path10.join(projectDir, "package.json");
71642
- if (!fs8.existsSync(pkgPath2)) return null;
71643
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71644
- return pkg2.lotics?.workspace_id ?? null;
71783
+ const pkgPath = path9.join(projectDir, "package.json");
71784
+ if (!fs8.existsSync(pkgPath)) return null;
71785
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71786
+ return pkg.lotics?.workspace_id ?? null;
71645
71787
  } catch {
71646
71788
  return null;
71647
71789
  }
71648
71790
  }
71649
71791
  function readAppMeta(projectDir) {
71650
- const pkgPath2 = path10.join(projectDir, "package.json");
71651
- if (!fs8.existsSync(pkgPath2)) {
71792
+ const pkgPath = path9.join(projectDir, "package.json");
71793
+ if (!fs8.existsSync(pkgPath)) {
71652
71794
  throw new Error(`No package.json found at ${projectDir}. Run 'lotics app create' first.`);
71653
71795
  }
71654
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71655
- if (!pkg2.lotics?.app_id || !pkg2.lotics.workspace_id) {
71796
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71797
+ if (!pkg.lotics?.app_id || !pkg.lotics.workspace_id) {
71656
71798
  throw new Error(
71657
71799
  `package.json is missing the 'lotics' field with app_id and workspace_id. Was this folder created with 'lotics app create'?`
71658
71800
  );
71659
71801
  }
71660
- noteScope({ app_id: pkg2.lotics.app_id });
71802
+ noteScope({ app_id: pkg.lotics.app_id });
71661
71803
  return {
71662
- app_id: pkg2.lotics.app_id,
71663
- workspace_id: pkg2.lotics.workspace_id,
71664
- current_version_id: pkg2.lotics.current_version_id ?? null,
71665
- version_number: pkg2.lotics.version_number ?? null,
71666
- workflows: pkg2.lotics.workflows ?? {},
71667
- queries: pkg2.lotics.queries ?? {},
71668
- agents: pkg2.lotics.agents ?? {},
71669
- capabilities: pkg2.lotics.capabilities
71804
+ app_id: pkg.lotics.app_id,
71805
+ workspace_id: pkg.lotics.workspace_id,
71806
+ current_version_id: pkg.lotics.current_version_id ?? null,
71807
+ version_number: pkg.lotics.version_number ?? null,
71808
+ workflows: pkg.lotics.workflows ?? {},
71809
+ queries: pkg.lotics.queries ?? {},
71810
+ agents: pkg.lotics.agents ?? {},
71811
+ capabilities: pkg.lotics.capabilities
71670
71812
  };
71671
71813
  }
71672
71814
  function writeAppMeta(projectDir, meta3) {
71673
- const pkgPath2 = path10.join(projectDir, "package.json");
71674
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71675
- const existing = pkg2.lotics && typeof pkg2.lotics === "object" ? pkg2.lotics : {};
71815
+ const pkgPath = path9.join(projectDir, "package.json");
71816
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71817
+ const existing = pkg.lotics && typeof pkg.lotics === "object" ? pkg.lotics : {};
71676
71818
  const supplied = new Set(
71677
71819
  Object.entries(meta3).filter(([, value2]) => value2 !== void 0).map(([key]) => key)
71678
71820
  );
@@ -71680,20 +71822,20 @@ function writeAppMeta(projectDir, meta3) {
71680
71822
  for (const [key, value2] of Object.entries(existing)) {
71681
71823
  if (!supplied.has(key)) preserved[key] = value2;
71682
71824
  }
71683
- pkg2.lotics = { ...meta3, ...preserved };
71684
- fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
71825
+ pkg.lotics = { ...meta3, ...preserved };
71826
+ fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
71685
71827
  }
71686
71828
  function writeWorkflowOutputs(projectDir, alias, outputs) {
71687
- const pkgPath2 = path10.join(projectDir, "package.json");
71688
- const pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
71689
- const declaration = pkg2.lotics?.workflows?.[alias];
71829
+ const pkgPath = path9.join(projectDir, "package.json");
71830
+ const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
71831
+ const declaration = pkg.lotics?.workflows?.[alias];
71690
71832
  if (!declaration) {
71691
71833
  throw new Error(
71692
71834
  `package.json#lotics.workflows.${alias} disappeared before the derived-outputs write-back.`
71693
71835
  );
71694
71836
  }
71695
71837
  declaration.outputs = outputs;
71696
- fs8.writeFileSync(pkgPath2, JSON.stringify(pkg2, null, 2) + "\n");
71838
+ fs8.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
71697
71839
  }
71698
71840
  function workflowBodyDrift(projectDir, workflows, synced = {}) {
71699
71841
  const drifted = [];
@@ -71709,7 +71851,7 @@ function workflowBodyDrift(projectDir, workflows, synced = {}) {
71709
71851
  return drifted;
71710
71852
  }
71711
71853
  function ensureAppTsconfig(projectDir) {
71712
- const tsconfigPath = path10.join(projectDir, "tsconfig.json");
71854
+ const tsconfigPath = path9.join(projectDir, "tsconfig.json");
71713
71855
  if (!fs8.existsSync(tsconfigPath)) {
71714
71856
  console.error(
71715
71857
  `\u26A0 No tsconfig.json at ${projectDir} \u2014 could not ensure "include" has "${LOTICS_INCLUDE_GLOB}" (a bare .lotics loads none of the generated types) or "exclude" has ${WORKFLOW_TSCONFIG_EXCLUDES.join(", ")}.`
@@ -71761,15 +71903,15 @@ function writeDevLinkTsconfig(projectDir) {
71761
71903
  if (uiSrc) {
71762
71904
  paths["@lotics/ui/*"] = [`${uiSrc}/*`];
71763
71905
  for (const peer of readKitPeerNames(projectDir)) {
71764
- const typesDir = path10.join(projectDir, "node_modules", typesPackageFor(peer));
71765
- const runtimeDir = path10.join(projectDir, "node_modules", peer);
71906
+ const typesDir = path9.join(projectDir, "node_modules", typesPackageFor(peer));
71907
+ const runtimeDir = path9.join(projectDir, "node_modules", peer);
71766
71908
  const target = fs8.existsSync(typesDir) ? `../node_modules/${typesPackageFor(peer)}` : fs8.existsSync(runtimeDir) ? `../node_modules/${peer}` : null;
71767
71909
  if (!target) continue;
71768
71910
  paths[peer] = [target];
71769
71911
  paths[`${peer}/*`] = [`${target}/*`];
71770
71912
  }
71771
71913
  }
71772
- const file2 = path10.join(projectDir, ".lotics", "tsconfig.link.json");
71914
+ const file2 = path9.join(projectDir, ".lotics", "tsconfig.link.json");
71773
71915
  const header = uiSrc ? `// GENERATED by \`lotics app codegen\` \u2014 do not edit.
71774
71916
  // LOTICS_UI_SRC is set, so @lotics/ui resolves to your working copy for tsc,
71775
71917
  // vitest, eslint and your editor \u2014 the same copy Vite is bundling. The peer
@@ -71786,8 +71928,8 @@ function writeDevLinkTsconfig(projectDir) {
71786
71928
  }
71787
71929
  function writeKitTypeAugmentation(projectDir) {
71788
71930
  const uiSrc = process.env.LOTICS_UI_SRC;
71789
- const source = uiSrc ? path10.join(uiSrc, "react_native.d.ts") : path10.join(projectDir, "node_modules", "@lotics", "ui", "src", "react_native.d.ts");
71790
- const target = path10.join(projectDir, ".lotics", "react_native.d.ts");
71931
+ const source = uiSrc ? path9.join(uiSrc, "react_native.d.ts") : path9.join(projectDir, "node_modules", "@lotics", "ui", "src", "react_native.d.ts");
71932
+ const target = path9.join(projectDir, ".lotics", "react_native.d.ts");
71791
71933
  if (!fs8.existsSync(source)) {
71792
71934
  if (fs8.existsSync(target)) fs8.rmSync(target);
71793
71935
  return;
@@ -71804,7 +71946,7 @@ function typesPackageFor(peer) {
71804
71946
  return peer.startsWith("@") ? `@types/${peer.slice(1).replace("/", "__")}` : `@types/${peer}`;
71805
71947
  }
71806
71948
  function readKitPeerNames(projectDir) {
71807
- const kitPkg = path10.join(projectDir, "node_modules", "@lotics", "ui", "package.json");
71949
+ const kitPkg = path9.join(projectDir, "node_modules", "@lotics", "ui", "package.json");
71808
71950
  if (!fs8.existsSync(kitPkg)) return [];
71809
71951
  const parsed = JSON.parse(fs8.readFileSync(kitPkg, "utf-8"));
71810
71952
  const peers = parsed.peerDependencies;
@@ -71815,12 +71957,12 @@ function writeAppDtsKitLinks(projectDir) {
71815
71957
  writeKitTypeAugmentation(projectDir);
71816
71958
  }
71817
71959
  function writeAppDts(projectDir, manifest) {
71818
- const dotLotics = path10.join(projectDir, ".lotics");
71960
+ const dotLotics = path9.join(projectDir, ".lotics");
71819
71961
  fs8.mkdirSync(dotLotics, { recursive: true });
71820
71962
  const written = [
71821
- [path10.join(dotLotics, "app_workflows.d.ts"), generateAppWorkflowsDts(manifest.workflows)],
71822
- [path10.join(dotLotics, "app_queries.d.ts"), generateAppQueriesDts(manifest.queries)],
71823
- [path10.join(dotLotics, "app_agents.d.ts"), generateAppAgentsDts(manifest.agents)]
71963
+ [path9.join(dotLotics, "app_workflows.d.ts"), generateAppWorkflowsDts(manifest.workflows)],
71964
+ [path9.join(dotLotics, "app_queries.d.ts"), generateAppQueriesDts(manifest.queries)],
71965
+ [path9.join(dotLotics, "app_agents.d.ts"), generateAppAgentsDts(manifest.agents)]
71824
71966
  ];
71825
71967
  for (const [file2, content] of written) fs8.writeFileSync(file2, content);
71826
71968
  writeAppDtsKitLinks(projectDir);
@@ -71829,8 +71971,8 @@ function writeAppDts(projectDir, manifest) {
71829
71971
  return written.map(([file2]) => file2);
71830
71972
  }
71831
71973
  function readCodegenTablesAllowlist(projectDir) {
71832
- const pkg2 = JSON.parse(fs8.readFileSync(path10.join(projectDir, "package.json"), "utf-8"));
71833
- const tables = pkg2.lotics?.codegen?.tables;
71974
+ const pkg = JSON.parse(fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8"));
71975
+ const tables = pkg.lotics?.codegen?.tables;
71834
71976
  return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
71835
71977
  }
71836
71978
  function resolveCodegenTableIds(projectDir, queries) {
@@ -71842,9 +71984,9 @@ function resolveCodegenTableIds(projectDir, queries) {
71842
71984
  return [...ids];
71843
71985
  }
71844
71986
  function writeAppFields(projectDir, tables) {
71845
- const dotLotics = path10.join(projectDir, ".lotics");
71987
+ const dotLotics = path9.join(projectDir, ".lotics");
71846
71988
  fs8.mkdirSync(dotLotics, { recursive: true });
71847
- const file2 = path10.join(dotLotics, "app_fields.ts");
71989
+ const file2 = path9.join(dotLotics, "app_fields.ts");
71848
71990
  fs8.writeFileSync(file2, generateAppFields(tables));
71849
71991
  return file2;
71850
71992
  }
@@ -71869,7 +72011,7 @@ async function writeGeneratedAppFields(client, projectDir, app, queries) {
71869
72011
  return;
71870
72012
  }
71871
72013
  const fieldsPath = writeAppFields(projectDir, tables);
71872
- console.error(
72014
+ note(
71873
72015
  `Wrote ${fieldsPath} (baked form \u2014 bespoke; ${tables.length} table${tables.length === 1 ? "" : "s"})`
71874
72016
  );
71875
72017
  }
@@ -71879,7 +72021,7 @@ async function writeGeneratedAppFields(client, projectDir, app, queries) {
71879
72021
  }
71880
72022
  function warnAppFieldsUnwritten(projectDir, err2) {
71881
72023
  const reason = err2 instanceof Error ? err2.message : String(err2);
71882
- if (fs8.existsSync(path10.join(projectDir, ".lotics", "app_fields.ts"))) {
72024
+ if (fs8.existsSync(path9.join(projectDir, ".lotics", "app_fields.ts"))) {
71883
72025
  console.error(`\u26A0 Could not regenerate .lotics/app_fields.ts (${reason}). Kept the existing file.`);
71884
72026
  return;
71885
72027
  }
@@ -71890,7 +72032,7 @@ function warnAppFieldsUnwritten(projectDir, err2) {
71890
72032
  function warnAboutDevLink(projectDir, command) {
71891
72033
  const uiSrc = process.env.LOTICS_UI_SRC;
71892
72034
  if (!uiSrc) return;
71893
- const viteConfigPath = path10.join(projectDir, "vite.config.ts");
72035
+ const viteConfigPath = path9.join(projectDir, "vite.config.ts");
71894
72036
  const config2 = fs8.existsSync(viteConfigPath) ? fs8.readFileSync(viteConfigPath, "utf-8") : "";
71895
72037
  const linked = config2.includes("loticsResolve") || config2.includes("LOTICS_UI_SRC");
71896
72038
  if (!linked) {
@@ -71909,9 +72051,9 @@ function warnAboutDevLink(projectDir, command) {
71909
72051
  }
71910
72052
  }
71911
72053
  var KIT_PACKAGES = ["@lotics/ui", "@lotics/app-sdk"];
71912
- function installedKitVersion(projectDir, pkg2) {
72054
+ function installedKitVersion(projectDir, pkg) {
71913
72055
  try {
71914
- const manifest = path10.join(projectDir, "node_modules", ...pkg2.split("/"), "package.json");
72056
+ const manifest = path9.join(projectDir, "node_modules", ...pkg.split("/"), "package.json");
71915
72057
  const parsed = JSON.parse(fs8.readFileSync(manifest, "utf-8"));
71916
72058
  const version2 = parsed.version;
71917
72059
  return typeof version2 === "string" ? version2 : null;
@@ -71919,12 +72061,12 @@ function installedKitVersion(projectDir, pkg2) {
71919
72061
  return null;
71920
72062
  }
71921
72063
  }
71922
- async function publishedKitVersion(pkg2) {
72064
+ async function publishedKitVersion(pkg) {
71923
72065
  const controller = new AbortController();
71924
72066
  const timeout = setTimeout(() => controller.abort(), 3e3);
71925
72067
  timeout.unref();
71926
72068
  try {
71927
- const response = await fetch(`https://registry.npmjs.org/${pkg2}/latest`, {
72069
+ const response = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
71928
72070
  signal: controller.signal
71929
72071
  });
71930
72072
  if (!response.ok) return null;
@@ -71938,13 +72080,13 @@ async function publishedKitVersion(pkg2) {
71938
72080
  }
71939
72081
  async function warnIfKitBehind(projectDir) {
71940
72082
  const checks = await Promise.all(
71941
- KIT_PACKAGES.map(async (pkg2) => {
71942
- const installed = installedKitVersion(projectDir, pkg2);
72083
+ KIT_PACKAGES.map(async (pkg) => {
72084
+ const installed = installedKitVersion(projectDir, pkg);
71943
72085
  if (!installed) return null;
71944
- const latest = await publishedKitVersion(pkg2);
72086
+ const latest = await publishedKitVersion(pkg);
71945
72087
  if (!latest || !isNewerVersion(latest, installed)) return null;
71946
72088
  const behindMajor = (Number.parseInt(latest, 10) || 0) > (Number.parseInt(installed, 10) || 0);
71947
- return { pkg: pkg2, installed, latest, behindMajor };
72089
+ return { pkg, installed, latest, behindMajor };
71948
72090
  })
71949
72091
  );
71950
72092
  const findings = checks.filter((c) => c !== null);
@@ -71959,7 +72101,7 @@ async function warnIfKitBehind(projectDir) {
71959
72101
 
71960
72102
  Breaking changes are listed newest-first in
71961
72103
  node_modules/@lotics/ui/MIGRATION.md.` : "";
71962
- console.error(
72104
+ warn(
71963
72105
  `
71964
72106
  \u26A0 This app builds against a kit a major release behind:
71965
72107
  ` + lines.join("\n") + migration + `
@@ -71975,12 +72117,12 @@ A newer kit is published \u2014 \`npm update ${findings.map((f) => f.pkg).join("
71975
72117
  );
71976
72118
  }
71977
72119
  function ensureAppVitestSetup(projectDir) {
71978
- const setupPath = path10.join(projectDir, VITEST_SETUP_FILENAME);
72120
+ const setupPath = path9.join(projectDir, VITEST_SETUP_FILENAME);
71979
72121
  if (!fs8.existsSync(setupPath)) {
71980
72122
  fs8.writeFileSync(setupPath, VITEST_SETUP_CONTENT);
71981
72123
  console.error(`Wrote ${VITEST_SETUP_FILENAME} (wired by vite.config.ts; empty until you fill it).`);
71982
72124
  }
71983
- const viteConfigPath = path10.join(projectDir, "vite.config.ts");
72125
+ const viteConfigPath = path9.join(projectDir, "vite.config.ts");
71984
72126
  if (!fs8.existsSync(viteConfigPath)) return;
71985
72127
  const viteConfig = fs8.readFileSync(viteConfigPath, "utf-8");
71986
72128
  if (/setupFiles\s*:/.test(viteConfig) && viteConfig.includes(VITEST_SETUP_FILENAME)) return;
@@ -71990,7 +72132,7 @@ function ensureAppVitestSetup(projectDir) {
71990
72132
  );
71991
72133
  }
71992
72134
  async function appCodegen(args) {
71993
- const projectDir = path10.resolve(args.projectDir ?? process.cwd());
72135
+ const projectDir = path9.resolve(args.projectDir ?? process.cwd());
71994
72136
  const meta3 = readAppMeta(projectDir);
71995
72137
  const dtsPaths = writeAppDts(projectDir, {
71996
72138
  workflows: meta3.workflows,
@@ -72004,7 +72146,7 @@ async function appCodegen(args) {
72004
72146
  }
72005
72147
  for (const alias of orphanWorkflowBodies(projectDir, declared)) {
72006
72148
  console.error(
72007
- `\u26A0 ${path10.join(WORKFLOWS_DIR, `${alias}.ts`)} is not declared in package.json#lotics.workflows \u2014 'workflow check' and 'workflow set' both skip it. Declare the alias or delete the file.`
72149
+ `\u26A0 ${path9.join(WORKFLOWS_DIR, `${alias}.ts`)} is not declared in package.json#lotics.workflows \u2014 'workflow check' and 'workflow set' both skip it. Declare the alias or delete the file.`
72008
72150
  );
72009
72151
  }
72010
72152
  if (!args.client) {
@@ -72063,15 +72205,15 @@ async function refreshWorkflowTypes(client, projectDir, app_id, alias, declarati
72063
72205
  return true;
72064
72206
  }
72065
72207
  function readPriorStamp(projectDir) {
72066
- const pkgPath2 = path10.join(projectDir, "package.json");
72067
- if (!fs8.existsSync(pkgPath2)) return null;
72068
- let pkg2;
72208
+ const pkgPath = path9.join(projectDir, "package.json");
72209
+ if (!fs8.existsSync(pkgPath)) return null;
72210
+ let pkg;
72069
72211
  try {
72070
- pkg2 = JSON.parse(fs8.readFileSync(pkgPath2, "utf-8"));
72212
+ pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf-8"));
72071
72213
  } catch {
72072
72214
  return null;
72073
72215
  }
72074
- const lotics = pkg2.lotics && typeof pkg2.lotics === "object" ? pkg2.lotics : null;
72216
+ const lotics = pkg.lotics && typeof pkg.lotics === "object" ? pkg.lotics : null;
72075
72217
  if (!lotics) return null;
72076
72218
  const id = lotics.current_version_id;
72077
72219
  const number4 = lotics.version_number;
@@ -72132,8 +72274,8 @@ function appDirName(name2) {
72132
72274
  }
72133
72275
  async function materializeScaffold(targetPath, files) {
72134
72276
  for (const file2 of files) {
72135
- const fullPath = path10.join(targetPath, file2.path);
72136
- fs8.mkdirSync(path10.dirname(fullPath), { recursive: true });
72277
+ const fullPath = path9.join(targetPath, file2.path);
72278
+ fs8.mkdirSync(path9.dirname(fullPath), { recursive: true });
72137
72279
  fs8.writeFileSync(fullPath, file2.content);
72138
72280
  }
72139
72281
  console.error(`Scaffolded ${files.length} files into ${targetPath}`);
@@ -72142,7 +72284,7 @@ async function materializeScaffold(targetPath, files) {
72142
72284
  writeAppDtsKitLinks(targetPath);
72143
72285
  }
72144
72286
  async function appCreate(client, args) {
72145
- const targetPath = path10.resolve(args.targetPath ?? appDirName(args.name));
72287
+ const targetPath = path9.resolve(args.targetPath ?? appDirName(args.name));
72146
72288
  if (fs8.existsSync(targetPath)) {
72147
72289
  const entries2 = fs8.readdirSync(targetPath);
72148
72290
  if (entries2.length > 0) {
@@ -72171,7 +72313,7 @@ async function appCreate(client, args) {
72171
72313
  });
72172
72314
  console.error(`
72173
72315
  Ready. Next steps:`);
72174
- console.error(` cd ${path10.relative(process.cwd(), targetPath) || "."}`);
72316
+ console.error(` cd ${path9.relative(process.cwd(), targetPath) || "."}`);
72175
72317
  console.error(` lotics docs # the contracts, at the versions installed here`);
72176
72318
  console.error(` # edit src/App.tsx, then:`);
72177
72319
  console.error(` lotics app check # every pre-flight a deploy runs`);
@@ -72230,17 +72372,17 @@ async function appVersions(client, args) {
72230
72372
  }
72231
72373
  }
72232
72374
  function defaultPullTarget(appId, appName) {
72233
- const cwdPkgPath = path10.join(process.cwd(), "package.json");
72375
+ const cwdPkgPath = path9.join(process.cwd(), "package.json");
72234
72376
  if (fs8.existsSync(cwdPkgPath)) {
72235
- let pkg2 = null;
72377
+ let pkg = null;
72236
72378
  try {
72237
- pkg2 = JSON.parse(fs8.readFileSync(cwdPkgPath, "utf-8"));
72379
+ pkg = JSON.parse(fs8.readFileSync(cwdPkgPath, "utf-8"));
72238
72380
  } catch (err2) {
72239
72381
  console.error(
72240
72382
  `\u26A0 Could not parse ${cwdPkgPath} (${err2 instanceof Error ? err2.message : String(err2)}) \u2014 pulling into a fresh ${appDirName(appName)}/ subdir.`
72241
72383
  );
72242
72384
  }
72243
- if (pkg2?.lotics?.app_id === appId) return process.cwd();
72385
+ if (pkg?.lotics?.app_id === appId) return process.cwd();
72244
72386
  }
72245
72387
  return appDirName(appName);
72246
72388
  }
@@ -72280,7 +72422,7 @@ async function hydrateAppProject(client, targetPath, app, opts) {
72280
72422
  );
72281
72423
  opts.kept.push(...kept);
72282
72424
  if (written.length > 0) {
72283
- console.error(
72425
+ note(
72284
72426
  `Wrote ${written.length} workflow ${written.length === 1 ? "body" : "bodies"} to ${WORKFLOWS_DIR}/ (${written.join(", ")})`
72285
72427
  );
72286
72428
  }
@@ -72312,7 +72454,7 @@ async function hydrateAppProject(client, targetPath, app, opts) {
72312
72454
  unseenLiveProse.push({ alias, parked: parkLiveAgentProse(targetPath, alias, instructions) });
72313
72455
  }
72314
72456
  if (written.length > 0) {
72315
- console.error(
72457
+ note(
72316
72458
  `Wrote ${written.length} agent instruction ${written.length === 1 ? "file" : "files"} to ${AGENTS_DIR}/ (${written.join(", ")})`
72317
72459
  );
72318
72460
  }
@@ -72332,21 +72474,21 @@ async function appPull(client, args) {
72332
72474
  if (!versionId) throw new Error(`App ${app.id} has no version to pull.`);
72333
72475
  const version2 = await client.getAppVersion(app.id, versionId);
72334
72476
  const sourceUrl = await client.getAppVersionSourceUrl(app.id, version2.id);
72335
- const targetPath = path10.resolve(args.targetPath ?? defaultPullTarget(app.id, app.name));
72477
+ const targetPath = path9.resolve(args.targetPath ?? defaultPullTarget(app.id, app.name));
72336
72478
  fs8.mkdirSync(targetPath, { recursive: true });
72337
72479
  const prior = readPriorStamp(targetPath);
72338
- const tmpFile = path10.join(tmpdir(), `lotics-app-${app.id}-${Date.now()}.tar.gz`);
72480
+ const tmpFile = path9.join(tmpdir(), `lotics-app-${app.id}-${Date.now()}.tar.gz`);
72339
72481
  console.error(`Downloading source archive...`);
72340
72482
  await downloadToFile(sourceUrl, tmpFile);
72341
72483
  const keptLocal = [];
72342
72484
  const restoredFromArchive = [];
72343
- const stagingDir = fs8.mkdtempSync(path10.join(tmpdir(), `lotics-pull-${app.id}-`));
72485
+ const stagingDir = fs8.mkdtempSync(path9.join(tmpdir(), `lotics-pull-${app.id}-`));
72344
72486
  try {
72345
72487
  await runTar(["-xzf", tmpFile, "-C", stagingDir], stagingDir);
72346
72488
  console.error(`Extracting to ${targetPath}...`);
72347
72489
  const copied = copyTree(stagingDir, targetPath, {
72348
72490
  overwrite: args.force === true,
72349
- skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(path10.sep).join("/"))
72491
+ skip: [WORKFLOWS_DIR, AGENTS_DIR].map((d) => d.split(path9.sep).join("/"))
72350
72492
  });
72351
72493
  keptLocal.push(...copied.kept);
72352
72494
  restoredFromArchive.push(...copied.created);
@@ -72375,20 +72517,20 @@ async function appPull(client, args) {
72375
72517
  });
72376
72518
  console.error(`
72377
72519
  Ready. Next steps:`);
72378
- console.error(` cd ${path10.relative(process.cwd(), targetPath) || "."}`);
72520
+ console.error(` cd ${path9.relative(process.cwd(), targetPath) || "."}`);
72379
72521
  console.error(` lotics docs # the contracts, at the versions installed here`);
72380
72522
  console.error(` # edit src/App.tsx, then:`);
72381
72523
  console.error(` lotics app deploy`);
72382
72524
  }
72383
72525
  function readAppSourceText(projectDir) {
72384
- const srcDir = path10.join(projectDir, "src");
72526
+ const srcDir = path9.join(projectDir, "src");
72385
72527
  if (!fs8.existsSync(srcDir)) return "";
72386
72528
  const parts = [];
72387
72529
  const walk2 = (dir) => {
72388
72530
  for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
72389
- const full = path10.join(dir, entry.name);
72531
+ const full = path9.join(dir, entry.name);
72390
72532
  if (entry.isDirectory()) walk2(full);
72391
- else if (isAppSourcePath(path10.relative(projectDir, full))) {
72533
+ else if (isAppSourcePath(path9.relative(projectDir, full))) {
72392
72534
  parts.push(fs8.readFileSync(full, "utf8"));
72393
72535
  }
72394
72536
  }
@@ -72397,7 +72539,7 @@ function readAppSourceText(projectDir) {
72397
72539
  return parts.join("\n");
72398
72540
  }
72399
72541
  async function appDeploy(client, args) {
72400
- const projectDir = path10.resolve(args.projectDir ?? process.cwd());
72542
+ const projectDir = path9.resolve(args.projectDir ?? process.cwd());
72401
72543
  const meta3 = readAppMeta(projectDir);
72402
72544
  warnAboutDevLink(projectDir, "deploy");
72403
72545
  const liveApp = await client.getApp(meta3.app_id);
@@ -72426,23 +72568,23 @@ async function appDeploy(client, args) {
72426
72568
  meta3.queries ?? {}
72427
72569
  );
72428
72570
  } catch (err2) {
72429
- console.error(
72571
+ warn(
72430
72572
  `\u26A0 Could not regenerate .lotics/app_fields.ts (${err2.message}).
72431
72573
  The build will use whatever is on disk \u2014 run 'lotics app codegen' if this app is published.`
72432
72574
  );
72433
72575
  }
72434
- console.error("Building...");
72576
+ note("Building...");
72435
72577
  await runNpm(["run", "build"], projectDir);
72436
- const distDir = path10.join(projectDir, "dist");
72578
+ const distDir = path9.join(projectDir, "dist");
72437
72579
  if (!fs8.existsSync(distDir)) {
72438
72580
  throw new Error(
72439
72581
  `Build did not produce a dist/ directory in ${projectDir}. Check that 'npm run build' is configured correctly (Vite/etc. defaults to dist/).`
72440
72582
  );
72441
72583
  }
72442
- const tmpSource = path10.join(tmpdir(), `lotics-source-${Date.now()}.tar.gz`);
72443
- const tmpDist = path10.join(tmpdir(), `lotics-dist-${Date.now()}.tar.gz`);
72584
+ const tmpSource = path9.join(tmpdir(), `lotics-source-${Date.now()}.tar.gz`);
72585
+ const tmpDist = path9.join(tmpdir(), `lotics-dist-${Date.now()}.tar.gz`);
72444
72586
  try {
72445
- console.error("Packaging source...");
72587
+ note("Packaging source...");
72446
72588
  await runTar(
72447
72589
  [
72448
72590
  "-czf",
@@ -72456,10 +72598,10 @@ async function appDeploy(client, args) {
72456
72598
  ],
72457
72599
  projectDir
72458
72600
  );
72459
- console.error("Packaging dist...");
72601
+ note("Packaging dist...");
72460
72602
  await runTar(["-czf", tmpDist, "-C", distDir, "."], projectDir);
72461
72603
  const liveQueries = await readLiveQueries(client, meta3.app_id);
72462
- console.error("Uploading...");
72604
+ note("Uploading...");
72463
72605
  try {
72464
72606
  const result = await client.deployAppVersion({
72465
72607
  queries: liveQueries,
@@ -72498,23 +72640,23 @@ async function appDeploy(client, args) {
72498
72640
  current_version_id: result.version_id,
72499
72641
  version_number: result.version_number
72500
72642
  });
72501
- console.error(`Deployed v${result.version_number} (${result.version_id})`);
72502
- console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
72643
+ note(`Deployed v${result.version_number} (${result.version_id})`);
72644
+ note(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
72503
72645
  try {
72504
72646
  const drifted = staleWorkflowGlobals(projectDir, meta3.workflows ?? {});
72505
72647
  for (const { alias, declaration } of drifted) {
72506
72648
  if (await refreshWorkflowTypes(client, projectDir, meta3.app_id, alias, declaration)) {
72507
- console.error(`Refreshed workflow types for ${alias} \u2014 this deploy moved its declaration.`);
72649
+ note(`Refreshed workflow types for ${alias} \u2014 this deploy moved its declaration.`);
72508
72650
  }
72509
72651
  }
72510
72652
  } catch (err2) {
72511
- console.error(`(types not refreshed: ${err2.message})`);
72653
+ warn(`(types not refreshed: ${err2.message})`);
72512
72654
  }
72513
72655
  let liveAfter;
72514
72656
  try {
72515
72657
  liveAfter = await client.getApp(meta3.app_id);
72516
72658
  } catch (err2) {
72517
- console.error(`(skipped post-deploy checks: ${err2.message})`);
72659
+ warn(`(skipped post-deploy checks: ${err2.message})`);
72518
72660
  }
72519
72661
  if (liveAfter) {
72520
72662
  warnIfUnbranded(liveAfter);
@@ -72555,7 +72697,7 @@ function warnIfUnbranded(app) {
72555
72697
  if (!app.icon) missing.push("icon");
72556
72698
  if (!app.theme?.color) missing.push("color");
72557
72699
  if (missing.length === 0) return;
72558
- console.error(
72700
+ warn(
72559
72701
  `
72560
72702
  \u26A0 This app has no ${missing.join(" or ")} set \u2014 it shows a generic tile in the launcher.
72561
72703
  Set it: lotics run update_app '{"app_id":"${app.id}","icon":"<lucide-name>","theme":{"color":"blue"}}'
@@ -72584,7 +72726,7 @@ async function readLiveQueries(client, appId) {
72584
72726
  }
72585
72727
  }
72586
72728
  async function appCheck(client, args = {}) {
72587
- const projectDir = path10.resolve(args.projectDir ?? process.cwd());
72729
+ const projectDir = path9.resolve(args.projectDir ?? process.cwd());
72588
72730
  const meta3 = readAppMeta(projectDir);
72589
72731
  const app = await client.getApp(meta3.app_id);
72590
72732
  assertProjectIsCurrent(meta3, app);
@@ -72859,10 +73001,10 @@ function copyTree(from, to, opts, relative = "") {
72859
73001
  const kept = [];
72860
73002
  const created = [];
72861
73003
  for (const entry of fs8.readdirSync(from, { withFileTypes: true })) {
72862
- const src = path10.join(from, entry.name);
72863
- const dest = path10.join(to, entry.name);
72864
- const rel = path10.join(relative, entry.name);
72865
- if (opts.skip?.includes(rel.split(path10.sep).join("/"))) continue;
73004
+ const src = path9.join(from, entry.name);
73005
+ const dest = path9.join(to, entry.name);
73006
+ const rel = path9.join(relative, entry.name);
73007
+ if (opts.skip?.includes(rel.split(path9.sep).join("/"))) continue;
72866
73008
  if (entry.isDirectory()) {
72867
73009
  fs8.mkdirSync(dest, { recursive: true });
72868
73010
  const child = copyTree(src, dest, opts, rel);
@@ -73035,9 +73177,9 @@ function warnIfProjectFootguns(projectDir, sourceText) {
73035
73177
  ].join("\n")
73036
73178
  );
73037
73179
  }
73038
- const configName = VITE_CONFIG_NAMES.find((name2) => fs8.existsSync(path10.join(projectDir, name2)));
73180
+ const configName = VITE_CONFIG_NAMES.find((name2) => fs8.existsSync(path9.join(projectDir, name2)));
73039
73181
  if (configName !== void 0) {
73040
- const config2 = fs8.readFileSync(path10.join(projectDir, configName), "utf-8");
73182
+ const config2 = fs8.readFileSync(path9.join(projectDir, configName), "utf-8");
73041
73183
  const defined = defineBlockKeys(config2);
73042
73184
  const missing = ["global", "__DEV__"].filter((name2) => !defined.has(name2));
73043
73185
  if (missing.length > 0) {
@@ -73133,7 +73275,7 @@ function warnIfUnboundAliases(app, called) {
73133
73275
  console.error(lines.join("\n"));
73134
73276
  }
73135
73277
  async function appDev(client, args) {
73136
- const projectDir = path10.resolve(args.projectDir ?? process.cwd());
73278
+ const projectDir = path9.resolve(args.projectDir ?? process.cwd());
73137
73279
  const meta3 = readAppMeta(projectDir);
73138
73280
  warnAboutDevLink(projectDir, "dev");
73139
73281
  writeAppDts(projectDir, { workflows: meta3.workflows, queries: meta3.queries, agents: meta3.agents });
@@ -73267,7 +73409,7 @@ async function appAgentSet(client, args) {
73267
73409
  }
73268
73410
  if (!hasDeclaration) {
73269
73411
  console.error(
73270
- `No instructions at ${path10.relative(projectDir, file2)}, and nothing declared in package.json#lotics.agents.${args.alias} to push instead.
73412
+ `No instructions at ${path9.relative(projectDir, file2)}, and nothing declared in package.json#lotics.agents.${args.alias} to push instead.
73271
73413
  Run 'lotics app pull ${meta3.app_id}' to write ${AGENTS_DIR}/${args.alias}.md, then edit it.`
73272
73414
  );
73273
73415
  process.exit(1);
@@ -73276,7 +73418,7 @@ async function appAgentSet(client, args) {
73276
73418
  const instructions = hasProse ? stripAgentHeader(fs8.readFileSync(file2, "utf-8")) : void 0;
73277
73419
  if (instructions === "") {
73278
73420
  console.error(
73279
- `${path10.relative(projectDir, file2)} is empty after stripping the header \u2014 refusing to push an empty prompt.`
73421
+ `${path9.relative(projectDir, file2)} is empty after stripping the header \u2014 refusing to push an empty prompt.`
73280
73422
  );
73281
73423
  process.exit(1);
73282
73424
  }
@@ -73343,7 +73485,7 @@ async function appWorkflowSet(client, args) {
73343
73485
  const file2 = workflowFilePath(projectDir, args.alias);
73344
73486
  if (!fs8.existsSync(file2)) {
73345
73487
  console.error(
73346
- `No workflow body at ${path10.relative(projectDir, file2)}.
73488
+ `No workflow body at ${path9.relative(projectDir, file2)}.
73347
73489
  If "${args.alias}" is already bound: lotics app pull ${meta3.app_id} (writes the body)
73348
73490
  If it is a NEW alias you declared: create that file yourself, then re-run this.`
73349
73491
  );
@@ -73352,7 +73494,7 @@ async function appWorkflowSet(client, args) {
73352
73494
  noteScope({ alias: args.alias });
73353
73495
  const source = stripWorkflowHeader(fs8.readFileSync(file2, "utf-8"));
73354
73496
  if (source.trim() === "") {
73355
- console.error(`Workflow body ${path10.relative(projectDir, file2)} is empty after stripping the header.`);
73497
+ console.error(`Workflow body ${path9.relative(projectDir, file2)} is empty after stripping the header.`);
73356
73498
  process.exit(1);
73357
73499
  }
73358
73500
  const res = await client.setAppWorkflow(meta3.app_id, args.alias, {
@@ -73491,13 +73633,13 @@ async function appWorkflowCheck(args) {
73491
73633
  const globalsPath = workflowGlobalsPath(projectDir, alias);
73492
73634
  if (!fs8.existsSync(bodyPath)) {
73493
73635
  console.error(
73494
- `\u26A0 Skipped "${alias}" \u2014 no body at ${path10.relative(projectDir, bodyPath)}. Run 'lotics app workflow pull' to write it.`
73636
+ `\u26A0 Skipped "${alias}" \u2014 no body at ${path9.relative(projectDir, bodyPath)}. Run 'lotics app workflow pull' to write it.`
73495
73637
  );
73496
73638
  continue;
73497
73639
  }
73498
73640
  if (!fs8.existsSync(globalsPath)) {
73499
73641
  console.error(
73500
- `Cannot check "${alias}" \u2014 missing types at ${path10.relative(projectDir, globalsPath)}. Run 'lotics app codegen' to fetch them (it refreshes types WITHOUT touching your body; a pull would overwrite it).`
73642
+ `Cannot check "${alias}" \u2014 missing types at ${path9.relative(projectDir, globalsPath)}. Run 'lotics app codegen' to fetch them (it refreshes types WITHOUT touching your body; a pull would overwrite it).`
73501
73643
  );
73502
73644
  process.exit(1);
73503
73645
  }
@@ -73533,7 +73675,7 @@ async function appWorkflowCheck(args) {
73533
73675
  function printWorkflowCheckResults(projectDir, results) {
73534
73676
  let totalErrors = 0;
73535
73677
  for (const r of results) {
73536
- const rel = path10.relative(projectDir, r.bodyPath);
73678
+ const rel = path9.relative(projectDir, r.bodyPath);
73537
73679
  if (r.issues.length === 0) {
73538
73680
  console.error(`\u2713 ${r.alias} (${rel}) \u2014 clean`);
73539
73681
  continue;
@@ -73585,6 +73727,7 @@ function parseArgs(argv) {
73585
73727
  remove: void 0,
73586
73728
  includeHidden: false,
73587
73729
  timezone: void 0,
73730
+ email: void 0,
73588
73731
  message: void 0,
73589
73732
  session: void 0,
73590
73733
  port: void 0,
@@ -73669,6 +73812,9 @@ function parseArgs(argv) {
73669
73812
  case "--name":
73670
73813
  flags.name = argv[++i2];
73671
73814
  break;
73815
+ case "--email":
73816
+ flags.email = argv[++i2];
73817
+ break;
73672
73818
  case "--description":
73673
73819
  flags.description = argv[++i2];
73674
73820
  break;
@@ -73779,8 +73925,53 @@ function parseArgs(argv) {
73779
73925
 
73780
73926
  // src/starter_commands.ts
73781
73927
  import fs9 from "node:fs";
73782
- import path11 from "node:path";
73928
+ import path10 from "node:path";
73783
73929
  import { tmpdir as tmpdir2 } from "node:os";
73930
+ function printStarterRows(rows) {
73931
+ const width = Math.max(...rows.map((row) => row.id.length));
73932
+ for (const row of rows) {
73933
+ const tags = row.tags ?? [];
73934
+ console.log(
73935
+ ` ${row.id.padEnd(width)} ${row.name}${tags.length > 0 ? ` [${tags.join(", ")}]` : ""}`
73936
+ );
73937
+ if (row.description) console.log(` ${" ".repeat(width)} ${row.description}`);
73938
+ }
73939
+ }
73940
+ function noteCopiedContent(templates, knowledgeDocs) {
73941
+ if (templates.length > 0) {
73942
+ note(
73943
+ `
73944
+ ${templates.length} document template${templates.length === 1 ? "" : "s"}: ${templates.join(", ")}
73945
+ These carry the publisher's wording and details, not yours \u2014 decide which should
73946
+ become your own documents. Editing them: lotics docs document_templates`
73947
+ );
73948
+ }
73949
+ if (knowledgeDocs.length > 0) {
73950
+ note(
73951
+ `
73952
+ ${knowledgeDocs.length} knowledge doc${knowledgeDocs.length === 1 ? "" : "s"}: ${knowledgeDocs.join(", ")}
73953
+ These describe how the publisher works, and the app's agents read them.
73954
+ Rewrite what differs: lotics docs knowledge_docs`
73955
+ );
73956
+ }
73957
+ }
73958
+ async function starterListPublic() {
73959
+ const starters = await fetchOfficialStarters();
73960
+ if (starters.length === 0) {
73961
+ console.error("No starters are published yet \u2014 build one with `lotics docs building_an_app`.");
73962
+ return;
73963
+ }
73964
+ console.error(`${starters.length} starter${starters.length === 1 ? "" : "s"} published by Lotics:
73965
+ `);
73966
+ printStarterRows(starters);
73967
+ console.error(
73968
+ `
73969
+ lotics start <starter_id> --email you@company.com Copy one \u2014 creates your account too
73970
+
73971
+ This machine has no Lotics account yet, so this is the published shelf.
73972
+ Signed in, the same command also lists what your own organization published.`
73973
+ );
73974
+ }
73784
73975
  async function starterList(client) {
73785
73976
  const starters = await client.listStarters();
73786
73977
  if (starters.length === 0) {
@@ -73789,19 +73980,19 @@ async function starterList(client) {
73789
73980
  );
73790
73981
  return;
73791
73982
  }
73792
- const width = Math.max(...starters.map((s) => s.id.length));
73793
73983
  console.error(`${starters.length} starter${starters.length === 1 ? "" : "s"}:
73794
73984
  `);
73795
- for (const s of starters) {
73796
- const tags = [
73797
- s.is_official ? "official" : null,
73798
- s.owned_by_caller === true ? "yours" : null
73799
- ].filter((t) => t !== null);
73800
- console.log(
73801
- ` ${s.id.padEnd(width)} ${s.name}${tags.length > 0 ? ` [${tags.join(", ")}]` : ""}`
73802
- );
73803
- if (s.description) console.log(` ${" ".repeat(width)} ${s.description}`);
73804
- }
73985
+ printStarterRows(
73986
+ starters.map((s) => ({
73987
+ id: s.id,
73988
+ name: s.name,
73989
+ description: s.description,
73990
+ tags: [
73991
+ s.is_official ? "official" : null,
73992
+ s.owned_by_caller === true ? "yours" : null
73993
+ ].filter((t) => t !== null)
73994
+ }))
73995
+ );
73805
73996
  console.error(`
73806
73997
  lotics starter init <starter_id> Copy one into this workspace`);
73807
73998
  }
@@ -73814,6 +74005,9 @@ async function starterShow(client, starter_id) {
73814
74005
  version ${starter.latest_version}
73815
74006
  trust ${starter.is_official ? "official \u2014 reviewed by Lotics" : starter.owned_by_caller === true ? "your organization's own" : "not copyable from this organization"}`
73816
74007
  );
74008
+ if (starter.icon !== void 0) {
74009
+ console.log(`icon ${starter.icon ?? "none \u2014 copies show a generic tile"}`);
74010
+ }
73817
74011
  if (starter.retired_at !== null) {
73818
74012
  console.log(`retired ${starter.retired_at} \u2014 can no longer be copied`);
73819
74013
  }
@@ -73821,7 +74015,7 @@ trust ${starter.is_official ? "official \u2014 reviewed by Lotics" : starter
73821
74015
  function reportKnowledgeWarnings(warnings) {
73822
74016
  const missing = warnings.missing_expected_docs;
73823
74017
  if (missing.length === 0) return;
73824
- console.error(
74018
+ warn(
73825
74019
  `
73826
74020
  \u26A0 ${missing.length} knowledge doc(s) this starter's agents expect are missing here:
73827
74021
  ` + missing.map((name2) => ` \u2022 ${name2}`).join("\n") + `
@@ -73831,40 +74025,55 @@ function reportKnowledgeWarnings(warnings) {
73831
74025
  }
73832
74026
  async function starterInit(client, args) {
73833
74027
  const starter = await client.getPackage(args.starter_id);
73834
- console.error(
74028
+ note(
73835
74029
  `Copying ${starter.name}${starter.is_official ? " (official)" : ""} into this workspace\u2026`
73836
74030
  );
73837
74031
  const result = await client.instantiateStarter(args.starter_id, {
73838
74032
  ...args.noSampleData === true ? { no_sample_data: true } : {},
73839
74033
  ...args.adopt === true ? { adopt: true } : {}
73840
74034
  });
73841
- const entities = Object.keys(result.binding.entities ?? {}).length;
73842
- const docs = Object.keys(result.binding.knowledge ?? {}).length;
73843
- const templates = Object.keys(result.binding.templates ?? {}).length;
74035
+ const tables = Object.keys(result.binding.entities ?? {}).sort();
74036
+ const knowledgeDocs = Object.keys(result.binding.knowledge ?? {}).sort();
74037
+ const templates = Object.keys(result.binding.templates ?? {}).sort();
73844
74038
  const records = Object.values(result.sample_record_ids).reduce((n, ids) => n + ids.length, 0);
73845
- console.error(
73846
- ` Created ${entities} table${entities === 1 ? "" : "s"}, ${templates} template${templates === 1 ? "" : "s"}, ${docs} knowledge doc${docs === 1 ? "" : "s"}, ${records} sample record${records === 1 ? "" : "s"}.`
74039
+ const created = {
74040
+ tables,
74041
+ templates,
74042
+ knowledge_docs: knowledgeDocs,
74043
+ sample_records: records
74044
+ };
74045
+ note(
74046
+ ` Created ${tables.length} table${tables.length === 1 ? "" : "s"}, ${templates.length} template${templates.length === 1 ? "" : "s"}, ${knowledgeDocs.length} knowledge doc${knowledgeDocs.length === 1 ? "" : "s"}, ${records} sample record${records === 1 ? "" : "s"}.`
73847
74047
  );
73848
74048
  reportKnowledgeWarnings(result.knowledge_warnings);
73849
74049
  if (result.app_id === null || result.bundle_url === null) {
73850
- console.error(`
73851
- Done. The documents and knowledge are yours to edit \u2014 nothing links back.`);
73852
- return;
74050
+ note(`
74051
+ Done \u2014 these are yours now, with no link back to the starter.`);
74052
+ noteCopiedContent(templates, knowledgeDocs);
74053
+ return {
74054
+ starter_id: args.starter_id,
74055
+ starter_name: starter.name,
74056
+ version: result.version,
74057
+ app_id: null,
74058
+ project_dir: null,
74059
+ created,
74060
+ signin_url: null
74061
+ };
73853
74062
  }
73854
- const targetPath = path11.resolve(args.targetPath ?? appDirName(starter.name));
74063
+ const targetPath = path10.resolve(args.targetPath ?? appDirName(starter.name));
73855
74064
  if (fs9.existsSync(targetPath) && fs9.readdirSync(targetPath).length > 0) {
73856
74065
  throw new Error(
73857
74066
  `Target directory ${targetPath} is not empty. The app (${result.app_id}) was created \u2014 pass an empty path and re-run, or finish it with "lotics app pull ${result.app_id}".`
73858
74067
  );
73859
74068
  }
73860
74069
  fs9.mkdirSync(targetPath, { recursive: true });
73861
- console.error(`Downloading source\u2026`);
73862
- const bundleFile = path11.join(tmpdir2(), `lotics-starter-${args.starter_id}-${process.pid}.tar.gz`);
73863
- const wrapperDir = fs9.mkdtempSync(path11.join(tmpdir2(), `lotics-starter-`));
74070
+ note(`Downloading source\u2026`);
74071
+ const bundleFile = path10.join(tmpdir2(), `lotics-starter-${args.starter_id}-${process.pid}.tar.gz`);
74072
+ const wrapperDir = fs9.mkdtempSync(path10.join(tmpdir2(), `lotics-starter-`));
73864
74073
  try {
73865
74074
  await downloadToFile(result.bundle_url, bundleFile);
73866
74075
  await runTar(["-xzf", bundleFile, "-C", wrapperDir], wrapperDir);
73867
- const sourceArchive = path11.join(wrapperDir, "source.tar.gz");
74076
+ const sourceArchive = path10.join(wrapperDir, "source.tar.gz");
73868
74077
  if (!fs9.existsSync(sourceArchive)) {
73869
74078
  throw new Error(
73870
74079
  `Starter bundle carried no source.tar.gz \u2014 the app (${result.app_id}) exists but has no code. Report this to the starter's publisher.`
@@ -73876,7 +74085,7 @@ Done. The documents and knowledge are yours to edit \u2014 nothing links back.`)
73876
74085
  fs9.rmSync(wrapperDir, { recursive: true, force: true });
73877
74086
  }
73878
74087
  for (const dir of ["knowledge", "fixtures"]) {
73879
- fs9.rmSync(path11.join(targetPath, dir), { recursive: true, force: true });
74088
+ fs9.rmSync(path10.join(targetPath, dir), { recursive: true, force: true });
73880
74089
  }
73881
74090
  const app = await client.getApp(result.app_id);
73882
74091
  const kept = [];
@@ -73886,15 +74095,14 @@ Done. The documents and knowledge are yours to edit \u2014 nothing links back.`)
73886
74095
  kept
73887
74096
  });
73888
74097
  if (starter.owned_by_caller !== true) {
73889
- console.error(
74098
+ warn(
73890
74099
  `
73891
74100
  Building ${starter.name} \u2014 this runs its build on your machine (its package scripts
73892
74101
  and vite config are the publisher's code, executed as you).${starter.is_official ? " Lotics reviewed this starter." : ""}`
73893
74102
  );
73894
74103
  } else {
73895
- console.error(`Building and deploying\u2026`);
74104
+ note(`Building and deploying\u2026`);
73896
74105
  }
73897
- await runNpm(["run", "build"], targetPath);
73898
74106
  await appDeploy(client, {
73899
74107
  projectDir: targetPath,
73900
74108
  message: `Copied from starter ${starter.name}`
@@ -73907,14 +74115,14 @@ Building ${starter.name} \u2014 this runs its build on your machine (its package
73907
74115
  });
73908
74116
  signInUrl = link.url ?? null;
73909
74117
  } catch (error52) {
73910
- console.error(
74118
+ warn(
73911
74119
  `
73912
74120
  (no sign-in link: ${error52 instanceof Error ? error52.message : String(error52)})
73913
74121
  The copy is complete either way \u2014 open it with "lotics auth web".`
73914
74122
  );
73915
74123
  signInUrl = null;
73916
74124
  }
73917
- console.error(
74125
+ note(
73918
74126
  `
73919
74127
  Done \u2014 ${starter.name} is live and yours.
73920
74128
  App: ${result.app_id}
@@ -73922,42 +74130,55 @@ Done \u2014 ${starter.name} is live and yours.
73922
74130
 
73923
74131
  Edit anything: the tables, the app source, the templates, the docs. There is no
73924
74132
  link back to the starter and nothing to upgrade \u2014 this is your app now.
73925
- Ship a change: cd ${path11.relative(process.cwd(), targetPath) || "."} && lotics app deploy -m "<what changed>"`
74133
+ Ship a change: cd ${path10.relative(process.cwd(), targetPath) || "."} && lotics app deploy -m "<what changed>"
74134
+
74135
+ How to change it: lotics docs building_an_app (then \`lotics docs\` for the rest \u2014
74136
+ the SDK and UI references are installed in this project, so they match its versions)`
73926
74137
  );
73927
74138
  if (records > 0) {
73928
- console.error(
74139
+ note(
73929
74140
  `
73930
74141
  ${records} sample record${records === 1 ? "" : "s"} came with it. They are ordinary records \u2014
73931
74142
  delete them whenever you like, or re-run with --no-sample-data next time.`
73932
74143
  );
73933
74144
  }
74145
+ noteCopiedContent(templates, knowledgeDocs);
73934
74146
  if (signInUrl !== null) {
73935
- console.error(
74147
+ note(
73936
74148
  `
73937
74149
  Open it \u2014 one-time sign-in link, expires in 15 minutes:
73938
74150
  ${signInUrl}`
73939
74151
  );
73940
74152
  }
74153
+ return {
74154
+ starter_id: args.starter_id,
74155
+ starter_name: starter.name,
74156
+ version: result.version,
74157
+ app_id: result.app_id,
74158
+ project_dir: targetPath,
74159
+ created,
74160
+ signin_url: signInUrl
74161
+ };
73941
74162
  }
73942
74163
  async function starterFixturesCapture(client, args) {
73943
- const projectDir = path11.resolve(args.projectDir ?? process.cwd());
74164
+ const projectDir = path10.resolve(args.projectDir ?? process.cwd());
73944
74165
  const meta3 = readAppMeta(projectDir);
73945
74166
  const result = await client.captureStarterFixtures(meta3.app_id, {
73946
74167
  entities: args.entities,
73947
74168
  ...args.limit !== void 0 ? { limit: args.limit } : {}
73948
74169
  });
73949
- const fixturesDir = path11.join(projectDir, "fixtures");
74170
+ const fixturesDir = path10.join(projectDir, "fixtures");
73950
74171
  fs9.mkdirSync(fixturesDir, { recursive: true });
73951
74172
  let totalRows = 0;
73952
74173
  for (const entry of result.captured) {
73953
- const file2 = path11.join(projectDir, entry.content_ref);
74174
+ const file2 = path10.join(projectDir, entry.content_ref);
73954
74175
  fs9.writeFileSync(file2, `${JSON.stringify(entry.file, null, 2)}
73955
74176
  `, "utf-8");
73956
74177
  totalRows += entry.file.rows.length;
73957
74178
  console.error(
73958
74179
  ` ${entry.content_ref} \u2014 ${entry.file.rows.length} row${entry.file.rows.length === 1 ? "" : "s"}`
73959
74180
  );
73960
- for (const note of entry.notes) console.error(` \u26A0 ${note}`);
74181
+ for (const line of entry.notes) console.error(` \u26A0 ${line}`);
73961
74182
  }
73962
74183
  if (result.captured.length === 0) {
73963
74184
  console.error(
@@ -74041,7 +74262,7 @@ import fs11 from "node:fs";
74041
74262
 
74042
74263
  // src/file_command_io.ts
74043
74264
  import fs10 from "node:fs";
74044
- import path12 from "node:path";
74265
+ import path11 from "node:path";
74045
74266
  var CliError = class extends Error {
74046
74267
  constructor(message2) {
74047
74268
  super(message2);
@@ -74064,8 +74285,8 @@ function rejectExtraArgs(rest2, arity, usage) {
74064
74285
  fail2(`${usage} takes ${arity} argument${arity === 1 ? "" : "s"} after <file>, got ${rest2.length}. Unused: ${rest2.slice(arity).join(" ")}`);
74065
74286
  }
74066
74287
  function writeFileAtomic(filePath, bytes) {
74067
- const dir = path12.dirname(path12.resolve(filePath));
74068
- const tmp = path12.join(dir, `.${path12.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
74288
+ const dir = path11.dirname(path11.resolve(filePath));
74289
+ const tmp = path11.join(dir, `.${path11.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
74069
74290
  fs10.writeFileSync(tmp, bytes);
74070
74291
  try {
74071
74292
  fs10.renameSync(tmp, filePath);
@@ -76868,16 +77089,16 @@ var MatcherView = class {
76868
77089
  * @returns {string|undefined}
76869
77090
  */
76870
77091
  getCurrentTag() {
76871
- const path14 = this._matcher.path;
76872
- return path14.length > 0 ? path14[path14.length - 1].tag : void 0;
77092
+ const path13 = this._matcher.path;
77093
+ return path13.length > 0 ? path13[path13.length - 1].tag : void 0;
76873
77094
  }
76874
77095
  /**
76875
77096
  * Get current namespace.
76876
77097
  * @returns {string|undefined}
76877
77098
  */
76878
77099
  getCurrentNamespace() {
76879
- const path14 = this._matcher.path;
76880
- return path14.length > 0 ? path14[path14.length - 1].namespace : void 0;
77100
+ const path13 = this._matcher.path;
77101
+ return path13.length > 0 ? path13[path13.length - 1].namespace : void 0;
76881
77102
  }
76882
77103
  /**
76883
77104
  * Get current node's attribute value.
@@ -76885,9 +77106,9 @@ var MatcherView = class {
76885
77106
  * @returns {*}
76886
77107
  */
76887
77108
  getAttrValue(attrName) {
76888
- const path14 = this._matcher.path;
76889
- if (path14.length === 0) return void 0;
76890
- return path14[path14.length - 1].values?.[attrName];
77109
+ const path13 = this._matcher.path;
77110
+ if (path13.length === 0) return void 0;
77111
+ return path13[path13.length - 1].values?.[attrName];
76891
77112
  }
76892
77113
  /**
76893
77114
  * Check if current node has an attribute.
@@ -76895,9 +77116,9 @@ var MatcherView = class {
76895
77116
  * @returns {boolean}
76896
77117
  */
76897
77118
  hasAttr(attrName) {
76898
- const path14 = this._matcher.path;
76899
- if (path14.length === 0) return false;
76900
- const current = path14[path14.length - 1];
77119
+ const path13 = this._matcher.path;
77120
+ if (path13.length === 0) return false;
77121
+ const current = path13[path13.length - 1];
76901
77122
  return current.values !== void 0 && attrName in current.values;
76902
77123
  }
76903
77124
  /**
@@ -76923,18 +77144,18 @@ var MatcherView = class {
76923
77144
  * @returns {number}
76924
77145
  */
76925
77146
  getPosition() {
76926
- const path14 = this._matcher.path;
76927
- if (path14.length === 0) return -1;
76928
- return path14[path14.length - 1].position ?? 0;
77147
+ const path13 = this._matcher.path;
77148
+ if (path13.length === 0) return -1;
77149
+ return path13[path13.length - 1].position ?? 0;
76929
77150
  }
76930
77151
  /**
76931
77152
  * Get current node's repeat counter (occurrence count of this tag name).
76932
77153
  * @returns {number}
76933
77154
  */
76934
77155
  getCounter() {
76935
- const path14 = this._matcher.path;
76936
- if (path14.length === 0) return -1;
76937
- return path14[path14.length - 1].counter ?? 0;
77156
+ const path13 = this._matcher.path;
77157
+ if (path13.length === 0) return -1;
77158
+ return path13[path13.length - 1].counter ?? 0;
76938
77159
  }
76939
77160
  /**
76940
77161
  * Get current node's sibling index (alias for getPosition).
@@ -82592,10 +82813,10 @@ function resolveRelativePath(basePath, relativePath) {
82592
82813
  }
82593
82814
  return resolved.join("/");
82594
82815
  }
82595
- function findZipEntry(zipEntries, path14) {
82596
- if (zipEntries[path14]) return zipEntries[path14];
82597
- if (zipEntries[`xl/${path14}`]) return zipEntries[`xl/${path14}`];
82598
- const noSlash = path14.replace(/^\//, "");
82816
+ function findZipEntry(zipEntries, path13) {
82817
+ if (zipEntries[path13]) return zipEntries[path13];
82818
+ if (zipEntries[`xl/${path13}`]) return zipEntries[`xl/${path13}`];
82819
+ const noSlash = path13.replace(/^\//, "");
82599
82820
  if (zipEntries[noSlash]) return zipEntries[noSlash];
82600
82821
  return void 0;
82601
82822
  }
@@ -84496,9 +84717,9 @@ function parseExcelFromZip(zip, options) {
84496
84717
  }
84497
84718
  return result;
84498
84719
  }
84499
- function findEntry(zip, path14) {
84500
- if (zip[path14]) return zip[path14];
84501
- const lower2 = path14.toLowerCase();
84720
+ function findEntry(zip, path13) {
84721
+ if (zip[path13]) return zip[path13];
84722
+ const lower2 = path13.toLowerCase();
84502
84723
  for (const key of Object.keys(zip)) {
84503
84724
  if (key.toLowerCase() === lower2) return zip[key];
84504
84725
  }
@@ -85135,12 +85356,12 @@ function extractPivotRoundTripInfo(originalZip) {
85135
85356
  if (paths.length > 0) pivotTablesBySheetIndex.set(i2, paths);
85136
85357
  }
85137
85358
  const pivotXmlPaths = [];
85138
- for (const path14 of Object.keys(originalZip)) {
85139
- if (path14.startsWith("xl/pivotTables/") && path14.endsWith(".xml")) {
85140
- pivotXmlPaths.push(path14);
85359
+ for (const path13 of Object.keys(originalZip)) {
85360
+ if (path13.startsWith("xl/pivotTables/") && path13.endsWith(".xml")) {
85361
+ pivotXmlPaths.push(path13);
85141
85362
  }
85142
- if (path14.startsWith("xl/pivotCache/") && path14.endsWith(".xml")) {
85143
- pivotXmlPaths.push(path14);
85363
+ if (path13.startsWith("xl/pivotCache/") && path13.endsWith(".xml")) {
85364
+ pivotXmlPaths.push(path13);
85144
85365
  }
85145
85366
  }
85146
85367
  return { cachesByWorkbook, pivotTablesBySheetIndex, pivotXmlPaths };
@@ -85148,15 +85369,15 @@ function extractPivotRoundTripInfo(originalZip) {
85148
85369
  function decode3(bytes) {
85149
85370
  return new TextDecoder().decode(bytes);
85150
85371
  }
85151
- function pivotContentTypeFor(path14) {
85152
- if (path14.startsWith("xl/pivotTables/") && path14.endsWith(".xml")) {
85153
- return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
85372
+ function pivotContentTypeFor(path13) {
85373
+ if (path13.startsWith("xl/pivotTables/") && path13.endsWith(".xml")) {
85374
+ return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml"/>`;
85154
85375
  }
85155
- if (path14.includes("/pivotCacheDefinition") && path14.endsWith(".xml")) {
85156
- return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
85376
+ if (path13.includes("/pivotCacheDefinition") && path13.endsWith(".xml")) {
85377
+ return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml"/>`;
85157
85378
  }
85158
- if (path14.includes("/pivotCacheRecords") && path14.endsWith(".xml")) {
85159
- return `<Override PartName="/${path14}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
85379
+ if (path13.includes("/pivotCacheRecords") && path13.endsWith(".xml")) {
85380
+ return `<Override PartName="/${path13}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml"/>`;
85160
85381
  }
85161
85382
  return void 0;
85162
85383
  }
@@ -85229,16 +85450,16 @@ function exportWorkbook(workbook, originalZip) {
85229
85450
  regeneratedPaths.add(`xl/worksheets/sheet${i2 + 1}.xml`);
85230
85451
  regeneratedPaths.add(`xl/worksheets/_rels/sheet${i2 + 1}.xml.rels`);
85231
85452
  }
85232
- for (const path14 of Object.keys(originalZip)) {
85233
- if (path14.startsWith("xl/drawings/") || path14.startsWith("xl/charts/") || path14.startsWith("xl/tables/") || path14.startsWith("xl/media/")) {
85234
- regeneratedPaths.add(path14);
85453
+ for (const path13 of Object.keys(originalZip)) {
85454
+ if (path13.startsWith("xl/drawings/") || path13.startsWith("xl/charts/") || path13.startsWith("xl/tables/") || path13.startsWith("xl/media/")) {
85455
+ regeneratedPaths.add(path13);
85235
85456
  }
85236
85457
  }
85237
- for (const [path14, data2] of Object.entries(originalZip)) {
85238
- if (regeneratedPaths.has(path14)) continue;
85239
- const ext = path14.slice(path14.lastIndexOf(".") + 1).toLowerCase();
85458
+ for (const [path13, data2] of Object.entries(originalZip)) {
85459
+ if (regeneratedPaths.has(path13)) continue;
85460
+ const ext = path13.slice(path13.lastIndexOf(".") + 1).toLowerCase();
85240
85461
  if (!DECLARED_EXTENSIONS.includes(ext)) continue;
85241
- entries2[path14] = data2;
85462
+ entries2[path13] = data2;
85242
85463
  }
85243
85464
  }
85244
85465
  const sharedStrings = buildSharedStrings(workbook);
@@ -85254,8 +85475,8 @@ function exportWorkbook(workbook, originalZip) {
85254
85475
  buildWorkbookRels(workbook, pivotInfo)
85255
85476
  );
85256
85477
  const extraContentTypes = [];
85257
- for (const path14 of pivotInfo.pivotXmlPaths) {
85258
- const ct = pivotContentTypeFor(path14);
85478
+ for (const path13 of pivotInfo.pivotXmlPaths) {
85479
+ const ct = pivotContentTypeFor(path13);
85259
85480
  if (ct) extraContentTypes.push(ct);
85260
85481
  }
85261
85482
  let globalChartIndex = 1;
@@ -94441,14 +94662,14 @@ var DependencyGraph = class {
94441
94662
  stack.push({ cell: p, path: [cell, p] });
94442
94663
  }
94443
94664
  while (stack.length > 0) {
94444
- const { cell: current, path: path14 } = stack.pop();
94445
- if (current === cell || originCoarse.has(current)) return path14;
94665
+ const { cell: current, path: path13 } = stack.pop();
94666
+ if (current === cell || originCoarse.has(current)) return path13;
94446
94667
  if (visited.has(current)) continue;
94447
94668
  visited.add(current);
94448
94669
  const nextPrec = this.precedents.get(current);
94449
94670
  if (!nextPrec) continue;
94450
94671
  for (const p of nextPrec) {
94451
- stack.push({ cell: p, path: [...path14, p] });
94672
+ stack.push({ cell: p, path: [...path13, p] });
94452
94673
  }
94453
94674
  }
94454
94675
  return null;
@@ -98510,15 +98731,15 @@ function finalizeParagraph(ctx, parts, startCp, markCp, isCellMark, numbering) {
98510
98731
  };
98511
98732
  }
98512
98733
  function readPictureAt(ctx, raw, cp) {
98513
- const note = (detail) => {
98734
+ const note2 = (detail) => {
98514
98735
  ctx.diagnostics.push({ kind: "image", location: { cp }, detail });
98515
98736
  return null;
98516
98737
  };
98517
- if (raw.picLocation === void 0) return note("Picture anchor carries no Data-stream location; dropped");
98518
- if (!ctx.data) return note("Picture anchor found but the document has no Data stream; dropped");
98738
+ if (raw.picLocation === void 0) return note2("Picture anchor carries no Data-stream location; dropped");
98739
+ if (!ctx.data) return note2("Picture anchor found but the document has no Data stream; dropped");
98519
98740
  const picture = readInlinePicture(ctx.data, raw.picLocation);
98520
98741
  if (!picture) {
98521
- return note(`Picture at Data+${raw.picLocation} is not a readable inline image; dropped`);
98742
+ return note2(`Picture at Data+${raw.picLocation} is not a readable inline image; dropped`);
98522
98743
  }
98523
98744
  return picture;
98524
98745
  }
@@ -101208,9 +101429,9 @@ function buildFootnotesXml(footnotes, ctx) {
101208
101429
  boilerplateNote("separator", "-1", "w:separator"),
101209
101430
  boilerplateNote("continuationSeparator", "0", "w:continuationSeparator")
101210
101431
  ];
101211
- for (const note of footnotes) {
101212
- const content = note.content.length > 0 ? note.content.map((b) => buildBlockElement(b, ctx)) : [{ "w:p": [] }];
101213
- notes.push({ "w:footnote": content, ":@": { "@_w:id": String(note.index) } });
101432
+ for (const note2 of footnotes) {
101433
+ const content = note2.content.length > 0 ? note2.content.map((b) => buildBlockElement(b, ctx)) : [{ "w:p": [] }];
101434
+ notes.push({ "w:footnote": content, ":@": { "@_w:id": String(note2.index) } });
101214
101435
  }
101215
101436
  const root = { "w:footnotes": notes, ":@": { "@_xmlns:w": W_NS3 } };
101216
101437
  return buildXml([root]);
@@ -101247,7 +101468,7 @@ function collectFonts(fonts, acc) {
101247
101468
  function walkModel(model) {
101248
101469
  const acc = { referencedStyleIstds: /* @__PURE__ */ new Set(), fontNames: /* @__PURE__ */ new Set() };
101249
101470
  walkBlocks(model.body, acc);
101250
- for (const note of model.footnotes) walkBlocks(note.content, acc);
101471
+ for (const note2 of model.footnotes) walkBlocks(note2.content, acc);
101251
101472
  for (const style of model.styles) {
101252
101473
  if (style.chp) collectFonts(style.chp.fonts, acc);
101253
101474
  }
@@ -101402,8 +101623,8 @@ async function docModelToDocx(model) {
101402
101623
  // ../ooxml/src/opc.ts
101403
101624
  var import_jszip = __toESM(require_lib4(), 1);
101404
101625
  function dropFolderEntries(zip) {
101405
- for (const [path14, entry] of Object.entries(zip.files)) {
101406
- if (entry.dir) delete zip.files[path14];
101626
+ for (const [path13, entry] of Object.entries(zip.files)) {
101627
+ if (entry.dir) delete zip.files[path13];
101407
101628
  }
101408
101629
  }
101409
101630
 
@@ -101658,11 +101879,11 @@ async function parseDocx(buffer) {
101658
101879
  const zip = await import_jszip3.default.loadAsync(buffer);
101659
101880
  const parts = /* @__PURE__ */ new Map();
101660
101881
  const filePromises = [];
101661
- zip.forEach((path14, file2) => {
101882
+ zip.forEach((path13, file2) => {
101662
101883
  if (file2.dir) return;
101663
101884
  filePromises.push(
101664
101885
  file2.async("uint8array").then((bytes) => {
101665
- parts.set(path14, bytes);
101886
+ parts.set(path13, bytes);
101666
101887
  })
101667
101888
  );
101668
101889
  });
@@ -101894,9 +102115,9 @@ var DEFAULT_PARTS = [
101894
102115
  ["word/theme/theme1.xml", () => encoder.encode(THEME_XML)]
101895
102116
  ];
101896
102117
  function fillDefaultParts(parts) {
101897
- for (const [path14, makeBytes] of DEFAULT_PARTS) {
101898
- if (!parts.has(path14)) {
101899
- parts.set(path14, makeBytes());
102118
+ for (const [path13, makeBytes] of DEFAULT_PARTS) {
102119
+ if (!parts.has(path13)) {
102120
+ parts.set(path13, makeBytes());
101900
102121
  }
101901
102122
  }
101902
102123
  return parts;
@@ -101906,9 +102127,9 @@ function fillDefaultParts(parts) {
101906
102127
  async function serializeDocx(doc) {
101907
102128
  const zip = new import_jszip4.default();
101908
102129
  const parts = fillDefaultParts(new Map(doc.parts));
101909
- for (const [path14, bytes] of parts) {
101910
- if (path14 === "word/document.xml") continue;
101911
- zip.file(path14, bytes);
102130
+ for (const [path13, bytes] of parts) {
102131
+ if (path13 === "word/document.xml") continue;
102132
+ zip.file(path13, bytes);
101912
102133
  }
101913
102134
  const documentXml = serializeDocumentXml(doc);
101914
102135
  zip.file("word/document.xml", documentXml);
@@ -102697,12 +102918,12 @@ async function runKnowledgeCommand(client, subcommand, toolArgs, flags, restArgs
102697
102918
  // src/preview.ts
102698
102919
  import { spawn as spawn3 } from "node:child_process";
102699
102920
  import { createServer } from "node:http";
102700
- import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdtempSync, rmSync, readdirSync } from "node:fs";
102921
+ import { readFileSync, writeFileSync, existsSync as existsSync2, mkdtempSync, rmSync, readdirSync } from "node:fs";
102701
102922
  import { tmpdir as tmpdir3 } from "node:os";
102702
102923
  import { join as join2, dirname, resolve, extname, basename } from "node:path";
102703
- import { fileURLToPath as fileURLToPath3 } from "node:url";
102924
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
102704
102925
  import { setTimeout as sleep } from "node:timers/promises";
102705
- var HERE = dirname(fileURLToPath3(import.meta.url));
102926
+ var HERE = dirname(fileURLToPath2(import.meta.url));
102706
102927
  function fail3(msg) {
102707
102928
  console.error(msg);
102708
102929
  process.exit(1);
@@ -102783,8 +103004,8 @@ async function runPreviewCommand(filePath, flags) {
102783
103004
  "No Chrome/Chromium found. Set CHROME_PATH to a Chrome binary, or install one:\n npx playwright install chromium (then it's auto-detected)\n or install Google Chrome / Chromium via your package manager."
102784
103005
  );
102785
103006
  }
102786
- const b64 = readFileSync2(abs2).toString("base64");
102787
- const bundle = readFileSync2(bundlePath, "utf8");
103007
+ const b64 = readFileSync(abs2).toString("base64");
103008
+ const bundle = readFileSync(bundlePath, "utf8");
102788
103009
  const html = `<!doctype html><html><head><meta charset="utf-8"><style>body{margin:0;background:#fff;font-family:sans-serif}#root{padding:20px;max-width:1240px;margin:0 auto}</style></head><body><div id="root"></div><script>window.__LOTICS_RENDER=${JSON.stringify({ type, b64 })}</script><script src="/render_page.js"></script></body></html>`;
102789
103010
  const server = createServer((req, res) => {
102790
103011
  if (req.url === "/render_page.js") {
@@ -102830,7 +103051,7 @@ async function runPreviewCommand(filePath, flags) {
102830
103051
  const portFile = join2(udd, "DevToolsActivePort");
102831
103052
  for (let i2 = 0; i2 < 100 && !cdpPort; i2++) {
102832
103053
  if (existsSync2(portFile)) {
102833
- const p = parseInt(readFileSync2(portFile, "utf8").split("\n")[0], 10);
103054
+ const p = parseInt(readFileSync(portFile, "utf8").split("\n")[0], 10);
102834
103055
  if (p) cdpPort = p;
102835
103056
  }
102836
103057
  if (!cdpPort) await sleep(100);
@@ -102886,7 +103107,7 @@ async function runPreviewCommand(filePath, flags) {
102886
103107
  const outPath = flags.output ? resolve(flags.output) : join2(dirname(abs2), basename(abs2, ext) + ".png");
102887
103108
  writeFileSync(outPath, Buffer.from(shot.data, "base64"));
102888
103109
  console.log(`Rendered ${basename(abs2)} \u2192 ${outPath} (${Math.min(w, MAX_CAPTURE)}\xD7${Math.min(h, MAX_CAPTURE)}, via ${basename(chrome)})`);
102889
- for (const warn of warnings) console.error(` \u26A0 ${warn}`);
103110
+ for (const warn2 of warnings) console.error(` \u26A0 ${warn2}`);
102890
103111
  } finally {
102891
103112
  cleanup();
102892
103113
  }
@@ -103007,7 +103228,7 @@ Auth flags:
103007
103228
  signup/api-key write a self-contained ./.lotics/config.json
103008
103229
  (inline key) \u2014 for a hermetic worktree or CI.
103009
103230
  --name <name> (signup) Display name (defaults to email prefix)
103010
- --timezone <timezone> (signup) Workspace timezone (defaults to UTC, e.g. Asia/Ho_Chi_Minh)
103231
+ --timezone <timezone> (signup) Workspace timezone (defaults to this machine's, e.g. Asia/Ho_Chi_Minh)
103011
103232
 
103012
103233
  API keys are stored once per org as named profiles in ~/.lotics/config.json.
103013
103234
  Registering a second key adds a profile \u2014 it does not overwrite the first.
@@ -103037,8 +103258,8 @@ function prompt(question) {
103037
103258
  });
103038
103259
  });
103039
103260
  }
103040
- async function publicPost(path14, body) {
103041
- const response = await fetch(`${API_BASE_URL}${path14}`, {
103261
+ async function publicPost(path13, body) {
103262
+ const response = await fetch(`${API_BASE_URL}${path13}`, {
103042
103263
  method: "POST",
103043
103264
  headers: { "Content-Type": "application/json" },
103044
103265
  body: JSON.stringify(body)
@@ -103046,35 +103267,74 @@ async function publicPost(path14, body) {
103046
103267
  const data2 = await response.json();
103047
103268
  return { ok: response.ok, status: response.status, data: data2 };
103048
103269
  }
103049
- async function handleSignup(positionalEmail, flags) {
103050
- const email3 = positionalEmail ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
103051
- if (!email3) {
103052
- console.error("Email is required. Usage: lotics auth signup <email>");
103053
- process.exit(1);
103054
- }
103055
- const name2 = flags.name ?? (process.stdin.isTTY ? await prompt("Name (enter to use email): ") : void 0);
103056
- const body = { email: email3 };
103057
- if (name2) body.name = name2;
103058
- if (flags.timezone) body.timezone = flags.timezone;
103270
+ async function signupAccount(args) {
103271
+ const body = { email: args.email };
103272
+ if (args.name) body.name = args.name;
103273
+ const timezone = args.timezone ?? machineTimezone();
103274
+ if (timezone) body.timezone = timezone;
103059
103275
  const { ok, status, data: data2 } = await publicPost("/v1/cli/signup", body);
103060
103276
  if (!ok) {
103061
103277
  if (status === 409) {
103062
- console.error("An account with this email already exists. Use: lotics auth api-key");
103063
- } else if (status === 429) {
103064
- console.error("Too many signup attempts. Try again later.");
103065
- } else {
103066
- console.error(`Signup failed: ${data2.message ?? JSON.stringify(data2)}`);
103278
+ throw new Error(
103279
+ `An account with ${args.email} already exists.
103280
+ If this machine is already signed in: lotics auth whoami
103281
+ Otherwise take an API key from Settings \u2192 API keys at ${WEB_APP_URL}, then:
103282
+ lotics auth api-key <key>`
103283
+ );
103067
103284
  }
103068
- process.exit(1);
103285
+ if (status === 429) {
103286
+ throw new Error("Too many signup attempts. Try again later.");
103287
+ }
103288
+ throw new Error(`Signup failed: ${data2.message ?? JSON.stringify(data2)}`);
103069
103289
  }
103070
103290
  const apiKey = data2.api_key;
103071
103291
  const orgId = data2.organization_id;
103072
103292
  const workspaceId = data2.workspace_id;
103073
- const orgName = name2 || email3.split("@")[0];
103293
+ const orgName = args.name || args.email.split("@")[0];
103074
103294
  upsertProfile(orgId, { api_key: apiKey, org_name: orgName, workspace_id: workspaceId });
103075
103295
  const existing = loadGlobalConfig() ?? {};
103076
- saveGlobalConfig({ ...existing, email: email3 });
103077
- setActiveOrg(orgId, flags.local ? "local" : "global");
103296
+ saveGlobalConfig({ ...existing, email: args.email });
103297
+ setActiveOrg(orgId, args.local ? "local" : "global");
103298
+ return { email: args.email, apiKey, orgId, orgName, workspaceId };
103299
+ }
103300
+ function alreadySetUp(email3) {
103301
+ const config2 = loadGlobalConfig();
103302
+ if (config2?.email !== email3) return false;
103303
+ return Object.keys(config2.profiles ?? {}).length > 0;
103304
+ }
103305
+ async function handleSignup(positionalEmail, flags) {
103306
+ const email3 = positionalEmail ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
103307
+ if (!email3) {
103308
+ console.error("Email is required. Usage: lotics auth signup <email>");
103309
+ process.exit(1);
103310
+ }
103311
+ if (alreadySetUp(email3)) {
103312
+ console.error(
103313
+ `This machine is already signed in as ${email3} \u2014 no new account needed.
103314
+ Carry on: lotics starter list
103315
+ Which account: lotics auth whoami` + // `--local` asked for a pin, and returning early gives none. Saying
103316
+ // nothing would leave a flag silently ignored, which is worse than the
103317
+ // 409 this replaced.
103318
+ (flags.local === true ? `
103319
+ --local pins a directory to an org, which signup does not do for an
103320
+ account that exists \u2014 use: lotics org use <name|id> --local` : "")
103321
+ );
103322
+ return;
103323
+ }
103324
+ const name2 = flags.name ?? (process.stdin.isTTY ? await prompt("Name (enter to use email): ") : void 0);
103325
+ let account;
103326
+ try {
103327
+ account = await signupAccount({
103328
+ email: email3,
103329
+ ...name2 ? { name: name2 } : {},
103330
+ ...flags.timezone ? { timezone: flags.timezone } : {},
103331
+ ...flags.local === true ? { local: true } : {}
103332
+ });
103333
+ } catch (error52) {
103334
+ console.error(error52 instanceof Error ? error52.message : String(error52));
103335
+ process.exit(1);
103336
+ }
103337
+ const { orgId, orgName } = account;
103078
103338
  console.error(`Account created. You can now use the CLI.`);
103079
103339
  console.error(` Email: ${email3}`);
103080
103340
  console.error(` Org: ${orgName} (${orgId})`);
@@ -103206,13 +103466,13 @@ async function resolveWorkspace(client, ctx) {
103206
103466
  function resolveUploadPaths(rawPaths) {
103207
103467
  const result = [];
103208
103468
  for (const p of rawPaths) {
103209
- const resolved = path13.resolve(p);
103469
+ const resolved = path12.resolve(p);
103210
103470
  const stat = fs14.statSync(resolved);
103211
103471
  if (stat.isDirectory()) {
103212
103472
  const entries2 = fs14.readdirSync(resolved, { withFileTypes: true });
103213
103473
  for (const entry of entries2) {
103214
103474
  if (entry.isFile()) {
103215
- result.push(path13.join(resolved, entry.name));
103475
+ result.push(path12.join(resolved, entry.name));
103216
103476
  }
103217
103477
  }
103218
103478
  } else {
@@ -103261,8 +103521,65 @@ async function main() {
103261
103521
  console.log(VERSION);
103262
103522
  return;
103263
103523
  }
103524
+ if (command === "start") {
103525
+ const starterId = subcommand;
103526
+ if (!starterId) {
103527
+ console.error("Usage: lotics start <starter_id> [path] [--email <you@co.com>] [--json]");
103528
+ console.error(" Creates an account if this machine has none, then copies the starter");
103529
+ console.error(" into its workspace: schema, templates, knowledge docs, sample records");
103530
+ console.error(" and a deployed app. Ends with a one-time sign-in link.");
103531
+ console.error(" --json prints one object and nothing else.");
103532
+ process.exit(1);
103533
+ }
103534
+ if (flags.json) setMachineOutput(true);
103535
+ const existing = resolveContext(flags);
103536
+ if (existing === null) {
103537
+ const email3 = flags.email ?? (process.stdin.isTTY ? await prompt("Email: ") : "");
103538
+ if (!email3) {
103539
+ console.error(
103540
+ "This machine has no Lotics credential yet, so `start` needs an email to create one:\n lotics start " + starterId + " --email you@company.com"
103541
+ );
103542
+ process.exit(1);
103543
+ }
103544
+ try {
103545
+ const account = await signupAccount({
103546
+ email: email3,
103547
+ ...flags.name ? { name: flags.name } : {},
103548
+ ...flags.timezone ? { timezone: flags.timezone } : {},
103549
+ ...flags.local === true ? { local: true } : {}
103550
+ });
103551
+ note(`Account created for ${account.email} \u2014 org ${account.orgName} (${account.orgId}).`);
103552
+ } catch (error52) {
103553
+ console.error(error52 instanceof Error ? error52.message : String(error52));
103554
+ process.exit(1);
103555
+ }
103556
+ } else if (flags.email !== void 0) {
103557
+ console.error(
103558
+ `Already authenticated (${SOURCE_LABELS[existing.source]}), so --email would create a SECOND account and copy into it.
103559
+ Copy into the account you have: lotics start ${starterId}
103560
+ Or create another one first: lotics auth signup ${flags.email}`
103561
+ );
103562
+ process.exit(1);
103563
+ }
103564
+ const { client: client2, ctx: ctx2 } = requireClient(flags);
103565
+ await resolveWorkspace(client2, ctx2);
103566
+ const result = await starterInit(client2, {
103567
+ starter_id: starterId,
103568
+ ...toolArgs !== void 0 ? { targetPath: toolArgs } : {},
103569
+ ...flags.noSampleData === true ? { noSampleData: true } : {},
103570
+ ...flags.adopt === true ? { adopt: true } : {}
103571
+ });
103572
+ if (flags.json) {
103573
+ emitJson({ organization_id: ctx2.orgId, workspace_id: ctx2.workspaceId, ...result });
103574
+ }
103575
+ return;
103576
+ }
103264
103577
  if (command === "starter") {
103265
103578
  if (subcommand === "list") {
103579
+ if (resolveContext(flags) === null) {
103580
+ await starterListPublic();
103581
+ return;
103582
+ }
103266
103583
  const { client: client2, ctx: ctx2 } = requireClient(flags);
103267
103584
  await resolveWorkspace(client2, ctx2);
103268
103585
  await starterList(client2);
@@ -103286,14 +103603,18 @@ async function main() {
103286
103603
  console.error(" locally, so it needs node and a few minutes.");
103287
103604
  process.exit(1);
103288
103605
  }
103606
+ if (flags.json) setMachineOutput(true);
103289
103607
  const { client: client2, ctx: ctx2 } = requireClient(flags);
103290
103608
  await resolveWorkspace(client2, ctx2);
103291
- await starterInit(client2, {
103609
+ const result = await starterInit(client2, {
103292
103610
  starter_id: toolArgs,
103293
103611
  ...restArgs[0] !== void 0 ? { targetPath: restArgs[0] } : {},
103294
103612
  ...flags.noSampleData === true ? { noSampleData: true } : {},
103295
103613
  ...flags.adopt === true ? { adopt: true } : {}
103296
103614
  });
103615
+ if (flags.json) {
103616
+ emitJson({ organization_id: ctx2.orgId, workspace_id: ctx2.workspaceId, ...result });
103617
+ }
103297
103618
  return;
103298
103619
  }
103299
103620
  if (subcommand === "fixtures") {
@@ -103464,7 +103785,7 @@ async function main() {
103464
103785
  if (command === "preview") {
103465
103786
  if (subcommand && isStoredFileId(subcommand)) {
103466
103787
  const { client: client2 } = requireClient(flags);
103467
- const tmpDir = fs14.mkdtempSync(path13.join(os4.tmpdir(), "lotics-preview-"));
103788
+ const tmpDir = fs14.mkdtempSync(path12.join(os4.tmpdir(), "lotics-preview-"));
103468
103789
  try {
103469
103790
  const { path: localPath, filename } = await client2.downloadFileById(subcommand, tmpDir);
103470
103791
  const output = flags.output ?? defaultPreviewOutputPath(filename, process.cwd());
@@ -104067,6 +104388,7 @@ ${JSON.stringify(info.input_schema, null, 2)}`);
104067
104388
  }
104068
104389
  }
104069
104390
  main().then(() => checkForUpdate(VERSION)).catch((error52) => {
104391
+ flushPendingWarnings();
104070
104392
  console.error(describeCliError(error52));
104071
104393
  process.exit(1);
104072
104394
  });