@runfusion/fusion 0.8.0 → 0.8.2

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.
Files changed (33) hide show
  1. package/dist/bin.js +962 -566
  2. package/dist/client/assets/{AgentDetailView-C3Xcrxnp.js → AgentDetailView-B6wfIQ9j.js} +1 -1
  3. package/dist/client/assets/{AgentsView-EjE4y4rM.js → AgentsView-Fcym0XCw.js} +3 -3
  4. package/dist/client/assets/{ChatView-DQLvKCYj.js → ChatView-DEckS3f3.js} +1 -1
  5. package/dist/client/assets/{DevServerView-CX7paFRQ.js → DevServerView-CmMS4D6V.js} +1 -1
  6. package/dist/client/assets/{DirectoryPicker-_cBPx6Nx.js → DirectoryPicker-CQtE-YyA.js} +1 -1
  7. package/dist/client/assets/{DocumentsView-Wz33aYqp.js → DocumentsView-C4HDkN_0.js} +1 -1
  8. package/dist/client/assets/{InsightsView-C7YPnS92.js → InsightsView-oNQ7h5e8.js} +1 -1
  9. package/dist/client/assets/{MemoryView-DKQtFzFQ.js → MemoryView-DPYGW09y.js} +1 -1
  10. package/dist/client/assets/{NodesView-CI4rUQC4.js → NodesView-DsM-c8RF.js} +1 -1
  11. package/dist/client/assets/{PiExtensionsManager-BFmdKgHZ.js → PiExtensionsManager-DHgMjjRE.js} +1 -1
  12. package/dist/client/assets/{PluginManager-BGQU1IIw.js → PluginManager-N-7Sw_tE.js} +1 -1
  13. package/dist/client/assets/{RoadmapsView-Cts3hoIS.js → RoadmapsView-BgX79uYM.js} +1 -1
  14. package/dist/client/assets/{SettingsModal-DXvBGZHf.js → SettingsModal-BIKEMPwb.js} +1 -1
  15. package/dist/client/assets/{SettingsModal-DvRd0ZOE.js → SettingsModal-C4EwtN6K.js} +4 -4
  16. package/dist/client/assets/SetupWizardModal-D2m0i9Io.js +1 -0
  17. package/dist/client/assets/{SkillsView-BXvrHzEZ.js → SkillsView-Eb1Mngnt.js} +1 -1
  18. package/dist/client/assets/{TodoView-NZHkv9YQ.js → TodoView-BN8FQYyp.js} +1 -1
  19. package/dist/client/assets/{folder-open-Kh0ScTc5.js → folder-open-BqZBHfoZ.js} +1 -1
  20. package/dist/client/assets/{index-CWz44REw.css → index-D2fXOwWF.css} +1 -1
  21. package/dist/client/assets/{index-D1gavMG-.js → index-DlHPhpDu.js} +3 -3
  22. package/dist/client/assets/{list-checks-CvoT0bwU.js → list-checks-D2EURsP0.js} +1 -1
  23. package/dist/client/assets/{star-BdfwSLBU.js → star-CNQlAD8p.js} +1 -1
  24. package/dist/client/assets/{upload-Bx8Yk_7Q.js → upload-uoxlYkig.js} +1 -1
  25. package/dist/client/assets/{users-DgVaFEsz.js → users-BLvidusm.js} +1 -1
  26. package/dist/client/index.html +2 -2
  27. package/dist/client/version.json +1 -1
  28. package/dist/extension.js +500 -196
  29. package/dist/pi-claude-cli/package.json +1 -1
  30. package/dist/pi-claude-cli/src/process-manager.ts +1 -1
  31. package/package.json +1 -1
  32. package/dist/client/assets/SetupWizardModal-Y2ewEE8Y.js +0 -1
  33. package/dist/pi-claude-cli/src/types/cross-spawn.d.ts +0 -7
package/dist/bin.js CHANGED
@@ -2434,7 +2434,7 @@ var init_db = __esm({
2434
2434
  "use strict";
2435
2435
  init_sqlite_adapter();
2436
2436
  init_types();
2437
- SCHEMA_VERSION = 50;
2437
+ SCHEMA_VERSION = 51;
2438
2438
  SCHEMA_SQL = `
2439
2439
  -- Tasks table with JSON columns for nested data
2440
2440
  CREATE TABLE IF NOT EXISTS tasks (
@@ -3967,6 +3967,13 @@ CREATE INDEX IF NOT EXISTS idxTodoItemsSortOrder ON todo_items(listId, sortOrder
3967
3967
  this.addColumnIfMissing("tasks", "effectiveNodeSource", "TEXT");
3968
3968
  });
3969
3969
  }
3970
+ if (version < 51) {
3971
+ this.applyMigration(51, () => {
3972
+ if (this.hasTable("chat_messages")) {
3973
+ this.addColumnIfMissing("chat_messages", "attachments", "TEXT");
3974
+ }
3975
+ });
3976
+ }
3970
3977
  }
3971
3978
  /**
3972
3979
  * Run a single migration step inside a transaction and bump the version.
@@ -6479,9 +6486,9 @@ var init_global_settings = __esm({
6479
6486
  * Serialize operations via promise chain to prevent lost-update races.
6480
6487
  */
6481
6488
  withLock(fn) {
6482
- let resolve36;
6489
+ let resolve39;
6483
6490
  const next = new Promise((r) => {
6484
- resolve36 = r;
6491
+ resolve39 = r;
6485
6492
  });
6486
6493
  const prev = this.lock;
6487
6494
  this.lock = next;
@@ -6489,7 +6496,7 @@ var init_global_settings = __esm({
6489
6496
  try {
6490
6497
  return await fn();
6491
6498
  } finally {
6492
- resolve36();
6499
+ resolve39();
6493
6500
  }
6494
6501
  });
6495
6502
  }
@@ -11799,8 +11806,8 @@ import { join as join8, dirname as dirname2 } from "node:path";
11799
11806
  import { fileURLToPath } from "node:url";
11800
11807
  function getAppVersion() {
11801
11808
  if (cachedVersion !== null) return cachedVersion;
11802
- const __dirname3 = dirname2(fileURLToPath(import.meta.url));
11803
- let currentDir = __dirname3;
11809
+ const __dirname2 = dirname2(fileURLToPath(import.meta.url));
11810
+ let currentDir = __dirname2;
11804
11811
  for (let i = 0; i < 10; i++) {
11805
11812
  try {
11806
11813
  const pkgPath = join8(currentDir, "package.json");
@@ -27785,9 +27792,9 @@ var init_automation_store = __esm({
27785
27792
  */
27786
27793
  withScheduleLock(id, fn) {
27787
27794
  const prev = this.scheduleLocks.get(id) ?? Promise.resolve();
27788
- let resolve36;
27795
+ let resolve39;
27789
27796
  const next = new Promise((r) => {
27790
- resolve36 = r;
27797
+ resolve39 = r;
27791
27798
  });
27792
27799
  this.scheduleLocks.set(id, next);
27793
27800
  return prev.then(async () => {
@@ -27797,7 +27804,7 @@ var init_automation_store = __esm({
27797
27804
  if (this.scheduleLocks.get(id) === next) {
27798
27805
  this.scheduleLocks.delete(id);
27799
27806
  }
27800
- resolve36();
27807
+ resolve39();
27801
27808
  }
27802
27809
  });
27803
27810
  }
@@ -29585,7 +29592,7 @@ var init_project_memory = __esm({
29585
29592
  // ../core/src/run-command.ts
29586
29593
  import { spawn } from "node:child_process";
29587
29594
  function runCommandAsync(command, options = {}) {
29588
- return new Promise((resolve36) => {
29595
+ return new Promise((resolve39) => {
29589
29596
  const maxBuffer = options.maxBuffer ?? DEFAULT_MAX_BUFFER;
29590
29597
  let stdout = "";
29591
29598
  let stderr = "";
@@ -29644,7 +29651,7 @@ function runCommandAsync(command, options = {}) {
29644
29651
  clearTimeout(forceKillTimer);
29645
29652
  forceKillTimer = null;
29646
29653
  }
29647
- resolve36({
29654
+ resolve39({
29648
29655
  stdout,
29649
29656
  stderr,
29650
29657
  exitCode: null,
@@ -29662,7 +29669,7 @@ function runCommandAsync(command, options = {}) {
29662
29669
  }
29663
29670
  signalProcessGroup("SIGTERM");
29664
29671
  scheduleForceKill(NORMAL_CLEANUP_FORCE_KILL_DELAY_MS);
29665
- resolve36({
29672
+ resolve39({
29666
29673
  stdout,
29667
29674
  stderr,
29668
29675
  exitCode: code,
@@ -30812,9 +30819,9 @@ ${outcome}`;
30812
30819
  * lost-update races on the nextId counter.
30813
30820
  */
30814
30821
  withConfigLock(fn) {
30815
- let resolve36;
30822
+ let resolve39;
30816
30823
  const next = new Promise((r) => {
30817
- resolve36 = r;
30824
+ resolve39 = r;
30818
30825
  });
30819
30826
  const prev = this.configLock;
30820
30827
  this.configLock = next;
@@ -30822,7 +30829,7 @@ ${outcome}`;
30822
30829
  try {
30823
30830
  return await fn();
30824
30831
  } finally {
30825
- resolve36();
30832
+ resolve39();
30826
30833
  }
30827
30834
  });
30828
30835
  }
@@ -30832,9 +30839,9 @@ ${outcome}`;
30832
30839
  */
30833
30840
  withTaskLock(id, fn) {
30834
30841
  const prev = this.taskLocks.get(id) ?? Promise.resolve();
30835
- let resolve36;
30842
+ let resolve39;
30836
30843
  const next = new Promise((r) => {
30837
- resolve36 = r;
30844
+ resolve39 = r;
30838
30845
  });
30839
30846
  this.taskLocks.set(id, next);
30840
30847
  return prev.then(async () => {
@@ -30844,7 +30851,7 @@ ${outcome}`;
30844
30851
  if (this.taskLocks.get(id) === next) {
30845
30852
  this.taskLocks.delete(id);
30846
30853
  }
30847
- resolve36();
30854
+ resolve39();
30848
30855
  }
30849
30856
  });
30850
30857
  }
@@ -32502,8 +32509,8 @@ ${task.description}
32502
32509
  if (this.isWatching) this.taskCache.delete(id);
32503
32510
  const dir2 = this.taskDir(id);
32504
32511
  if (existsSync12(dir2)) {
32505
- const { rm: rm5 } = await import("node:fs/promises");
32506
- await rm5(dir2, { recursive: true });
32512
+ const { rm: rm6 } = await import("node:fs/promises");
32513
+ await rm6(dir2, { recursive: true });
32507
32514
  }
32508
32515
  for (const dependentTask of rewrittenDependents) {
32509
32516
  this.emit("task:updated", dependentTask);
@@ -32838,8 +32845,8 @@ ${task.description}
32838
32845
  this.archiveDb.upsert(entry);
32839
32846
  this.db.prepare("DELETE FROM tasks WHERE id = ?").run(id);
32840
32847
  this.db.bumpLastModified();
32841
- const { rm: rm5 } = await import("node:fs/promises");
32842
- await rm5(dir2, { recursive: true, force: true });
32848
+ const { rm: rm6 } = await import("node:fs/promises");
32849
+ await rm6(dir2, { recursive: true, force: true });
32843
32850
  if (this.isWatching) {
32844
32851
  this.taskCache.delete(id);
32845
32852
  }
@@ -32999,7 +33006,7 @@ ${task.description}
32999
33006
  }
33000
33007
  }
33001
33008
  }
33002
- await new Promise((resolve36) => setImmediate(resolve36));
33009
+ await new Promise((resolve39) => setImmediate(resolve39));
33003
33010
  const selectClause = this.getTaskSelectClause(true);
33004
33011
  const changedRows = this.lastPollTime ? this.db.prepare(`SELECT ${selectClause} FROM tasks WHERE updatedAt > ? OR columnMovedAt > ?`).all(this.lastPollTime, this.lastPollTime) : this.db.prepare(`SELECT ${selectClause} FROM tasks`).all();
33005
33012
  this.lastPollTime = (/* @__PURE__ */ new Date()).toISOString();
@@ -33019,7 +33026,7 @@ ${task.description}
33019
33026
  this.emit("task:updated", task);
33020
33027
  }
33021
33028
  if (i > 0 && i % 50 === 0) {
33022
- await new Promise((resolve36) => setImmediate(resolve36));
33029
+ await new Promise((resolve39) => setImmediate(resolve39));
33023
33030
  }
33024
33031
  }
33025
33032
  const elapsed = Date.now() - startTime;
@@ -33802,14 +33809,14 @@ ${task.description}
33802
33809
  if (rows.length === 0) {
33803
33810
  return;
33804
33811
  }
33805
- const { rm: rm5 } = await import("node:fs/promises");
33812
+ const { rm: rm6 } = await import("node:fs/promises");
33806
33813
  for (const row of rows) {
33807
33814
  const task = this.rowToTask(row);
33808
33815
  const archivedAt = task.columnMovedAt ?? task.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
33809
33816
  const entry = await this.taskToArchiveEntry(task, archivedAt);
33810
33817
  this.archiveDb.upsert(entry);
33811
33818
  this.db.prepare("DELETE FROM tasks WHERE id = ?").run(task.id);
33812
- await rm5(this.taskDir(task.id), { recursive: true, force: true });
33819
+ await rm6(this.taskDir(task.id), { recursive: true, force: true });
33813
33820
  if (this.isWatching) {
33814
33821
  this.taskCache.delete(task.id);
33815
33822
  }
@@ -33832,8 +33839,8 @@ ${task.description}
33832
33839
  this.archiveDb.upsert(entry);
33833
33840
  this.db.prepare("DELETE FROM tasks WHERE id = ?").run(task.id);
33834
33841
  this.db.bumpLastModified();
33835
- const { rm: rm5 } = await import("node:fs/promises");
33836
- await rm5(dir2, { recursive: true, force: true });
33842
+ const { rm: rm6 } = await import("node:fs/promises");
33843
+ await rm6(dir2, { recursive: true, force: true });
33837
33844
  if (this.isWatching) {
33838
33845
  this.taskCache.delete(task.id);
33839
33846
  }
@@ -34845,7 +34852,7 @@ function runGh(args, cwd) {
34845
34852
  }
34846
34853
  function runGhAsync(args, cwdOrOptions) {
34847
34854
  const { cwd, signal: externalSignal, timeoutMs = DEFAULT_GH_TIMEOUT_MS } = normalizeRunGhOptions(cwdOrOptions);
34848
- return new Promise((resolve36, reject2) => {
34855
+ return new Promise((resolve39, reject2) => {
34849
34856
  if (externalSignal?.aborted) {
34850
34857
  reject2(makeGhError(`gh command aborted: ${describeAbortReason(externalSignal.reason)}`, "ABORT_ERR"));
34851
34858
  return;
@@ -34896,7 +34903,7 @@ function runGhAsync(args, cwdOrOptions) {
34896
34903
  ghError.stderr = stderr ?? "";
34897
34904
  reject2(ghError);
34898
34905
  } else {
34899
- resolve36(stdout ?? "");
34906
+ resolve39(stdout ?? "");
34900
34907
  }
34901
34908
  }
34902
34909
  );
@@ -35184,9 +35191,9 @@ var init_routine_store = __esm({
35184
35191
  */
35185
35192
  withRoutineLock(id, fn) {
35186
35193
  const prev = this.routineLocks.get(id) ?? Promise.resolve();
35187
- let resolve36;
35194
+ let resolve39;
35188
35195
  const next = new Promise((r) => {
35189
- resolve36 = r;
35196
+ resolve39 = r;
35190
35197
  });
35191
35198
  this.routineLocks.set(id, next);
35192
35199
  return prev.then(async () => {
@@ -35196,7 +35203,7 @@ var init_routine_store = __esm({
35196
35203
  if (this.routineLocks.get(id) === next) {
35197
35204
  this.routineLocks.delete(id);
35198
35205
  }
35199
- resolve36();
35206
+ resolve39();
35200
35207
  }
35201
35208
  });
35202
35209
  }
@@ -35795,13 +35802,13 @@ var init_plugin_loader = __esm({
35795
35802
  * Execute a promise with a timeout.
35796
35803
  */
35797
35804
  withTimeout(promise, ms, timeoutMessage) {
35798
- return new Promise((resolve36, reject2) => {
35805
+ return new Promise((resolve39, reject2) => {
35799
35806
  const timer = setTimeout(() => {
35800
35807
  reject2(new Error(timeoutMessage));
35801
35808
  }, ms);
35802
35809
  promise.then((result) => {
35803
35810
  clearTimeout(timer);
35804
- resolve36(result);
35811
+ resolve39(result);
35805
35812
  }).catch((err) => {
35806
35813
  clearTimeout(timer);
35807
35814
  reject2(err);
@@ -39008,7 +39015,7 @@ var require_get_stream = __commonJS({
39008
39015
  };
39009
39016
  const { maxBuffer } = options;
39010
39017
  let stream;
39011
- await new Promise((resolve36, reject2) => {
39018
+ await new Promise((resolve39, reject2) => {
39012
39019
  const rejectPromise = (error) => {
39013
39020
  if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
39014
39021
  error.bufferedData = stream.getBufferedValue();
@@ -39020,7 +39027,7 @@ var require_get_stream = __commonJS({
39020
39027
  rejectPromise(error);
39021
39028
  return;
39022
39029
  }
39023
- resolve36();
39030
+ resolve39();
39024
39031
  });
39025
39032
  stream.on("data", () => {
39026
39033
  if (stream.getBufferedLength() > maxBuffer) {
@@ -40314,7 +40321,7 @@ var require_extract_zip = __commonJS({
40314
40321
  debug("opening", this.zipPath, "with opts", this.opts);
40315
40322
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
40316
40323
  this.canceled = false;
40317
- return new Promise((resolve36, reject2) => {
40324
+ return new Promise((resolve39, reject2) => {
40318
40325
  this.zipfile.on("error", (err) => {
40319
40326
  this.canceled = true;
40320
40327
  reject2(err);
@@ -40323,7 +40330,7 @@ var require_extract_zip = __commonJS({
40323
40330
  this.zipfile.on("close", () => {
40324
40331
  if (!this.canceled) {
40325
40332
  debug("zip extraction complete");
40326
- resolve36();
40333
+ resolve39();
40327
40334
  }
40328
40335
  });
40329
40336
  this.zipfile.on("entry", async (entry) => {
@@ -47773,10 +47780,10 @@ function pushAlias(aliases, value) {
47773
47780
  if (pathRef !== normalized && pathRef.length > 0) {
47774
47781
  aliases.add(pathRef);
47775
47782
  }
47776
- const basename16 = extractPathBasename(value);
47777
- if (basename16) {
47778
- aliases.add(basename16);
47779
- const basenameSlug = slugifyAgentReference(basename16);
47783
+ const basename17 = extractPathBasename(value);
47784
+ if (basename17) {
47785
+ aliases.add(basename17);
47786
+ const basenameSlug = slugifyAgentReference(basename17);
47780
47787
  if (basenameSlug.length > 0) {
47781
47788
  aliases.add(basenameSlug);
47782
47789
  }
@@ -48503,6 +48510,7 @@ var init_chat_store = __esm({
48503
48510
  content: row.content,
48504
48511
  thinkingOutput: row.thinkingOutput ?? null,
48505
48512
  metadata: fromJson(row.metadata) ?? null,
48513
+ attachments: fromJson(row.attachments) ?? void 0,
48506
48514
  createdAt: row.createdAt
48507
48515
  };
48508
48516
  }
@@ -48721,11 +48729,12 @@ var init_chat_store = __esm({
48721
48729
  content: input.content,
48722
48730
  thinkingOutput: input.thinkingOutput ?? null,
48723
48731
  metadata: input.metadata ?? null,
48732
+ attachments: input.attachments,
48724
48733
  createdAt: now
48725
48734
  };
48726
48735
  this.db.prepare(`
48727
- INSERT INTO chat_messages (id, sessionId, role, content, thinkingOutput, metadata, createdAt)
48728
- VALUES (?, ?, ?, ?, ?, ?, ?)
48736
+ INSERT INTO chat_messages (id, sessionId, role, content, thinkingOutput, metadata, attachments, createdAt)
48737
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
48729
48738
  `).run(
48730
48739
  message.id,
48731
48740
  message.sessionId,
@@ -48733,6 +48742,7 @@ var init_chat_store = __esm({
48733
48742
  message.content,
48734
48743
  message.thinkingOutput,
48735
48744
  toJsonNullable(message.metadata),
48745
+ toJsonNullable(message.attachments),
48736
48746
  message.createdAt
48737
48747
  );
48738
48748
  this.db.prepare("UPDATE chat_sessions SET updatedAt = ? WHERE id = ?").run(now, sessionId);
@@ -48740,6 +48750,28 @@ var init_chat_store = __esm({
48740
48750
  this.emit("chat:message:added", message);
48741
48751
  return message;
48742
48752
  }
48753
+ /**
48754
+ * Append a file attachment metadata record to an existing message.
48755
+ */
48756
+ addMessageAttachment(sessionId, messageId, attachment) {
48757
+ const message = this.getMessage(messageId);
48758
+ if (!message || message.sessionId !== sessionId) {
48759
+ throw new Error(`Message ${messageId} not found in session ${sessionId}`);
48760
+ }
48761
+ const updatedAttachments = [...message.attachments ?? [], attachment];
48762
+ this.db.prepare(`
48763
+ UPDATE chat_messages
48764
+ SET attachments = ?
48765
+ WHERE id = ?
48766
+ `).run(toJsonNullable(updatedAttachments), messageId);
48767
+ const updated = this.getMessage(messageId);
48768
+ if (!updated) {
48769
+ throw new Error(`Failed to update message ${messageId}`);
48770
+ }
48771
+ this.db.bumpLastModified();
48772
+ this.emit("chat:message:updated", updated);
48773
+ return updated;
48774
+ }
48743
48775
  /**
48744
48776
  * Get messages for a chat session with optional filtering.
48745
48777
  *
@@ -51040,12 +51072,12 @@ var init_concurrency = __esm({
51040
51072
  this._active++;
51041
51073
  return Promise.resolve();
51042
51074
  }
51043
- return new Promise((resolve36) => {
51075
+ return new Promise((resolve39) => {
51044
51076
  this._waiters.push({
51045
51077
  priority,
51046
51078
  resolve: () => {
51047
51079
  this._active++;
51048
- resolve36();
51080
+ resolve39();
51049
51081
  }
51050
51082
  });
51051
51083
  });
@@ -53466,20 +53498,20 @@ async function withRateLimitRetry(fn, options = {}) {
53466
53498
  throw lastError ?? new Error("withRateLimitRetry: unexpected state");
53467
53499
  }
53468
53500
  function sleep(ms, signal) {
53469
- return new Promise((resolve36, reject2) => {
53501
+ return new Promise((resolve39, reject2) => {
53470
53502
  if (signal?.aborted) {
53471
53503
  reject2(signal.reason ?? new Error("Aborted"));
53472
53504
  return;
53473
53505
  }
53474
- const timer = setTimeout(resolve36, ms);
53506
+ const timer = setTimeout(resolve39, ms);
53475
53507
  if (signal) {
53476
53508
  const onAbort = () => {
53477
53509
  clearTimeout(timer);
53478
53510
  reject2(signal.reason ?? new Error("Aborted"));
53479
53511
  };
53480
53512
  signal.addEventListener("abort", onAbort, { once: true });
53481
- const origResolve = resolve36;
53482
- resolve36 = () => {
53513
+ const origResolve = resolve39;
53514
+ resolve39 = () => {
53483
53515
  signal.removeEventListener("abort", onAbort);
53484
53516
  origResolve();
53485
53517
  };
@@ -55446,7 +55478,7 @@ import { existsSync as existsSync21 } from "node:fs";
55446
55478
  import { join as join26 } from "node:path";
55447
55479
  import { Type as Type3 } from "typebox";
55448
55480
  async function execWithProcessGroup(command, options) {
55449
- return new Promise((resolve36, reject2) => {
55481
+ return new Promise((resolve39, reject2) => {
55450
55482
  if (options.signal?.aborted) {
55451
55483
  reject2(Object.assign(
55452
55484
  new Error(`Command aborted before start: ${command}`),
@@ -55539,7 +55571,7 @@ async function execWithProcessGroup(command, options) {
55539
55571
  return;
55540
55572
  }
55541
55573
  if (code === 0) {
55542
- resolve36({ stdout, stderr, bufferOverflow: stdoutOverflow || stderrOverflow });
55574
+ resolve39({ stdout, stderr, bufferOverflow: stdoutOverflow || stderrOverflow });
55543
55575
  return;
55544
55576
  }
55545
55577
  reject2(Object.assign(
@@ -56102,21 +56134,31 @@ ${failureContext.output.slice(0, VERIFICATION_LOG_MAX_CHARS)}
56102
56134
  return false;
56103
56135
  }
56104
56136
  }
56105
- async function amendMergeCommitWithFixes(rootDir, taskId, authorArg) {
56137
+ function resetMergeWithWarn(rootDir, taskId, label) {
56138
+ try {
56139
+ execSync("git reset --merge", { cwd: rootDir, stdio: "pipe" });
56140
+ } catch (err) {
56141
+ const msg = err instanceof Error ? err.message : String(err);
56142
+ mergerLog.warn(`${taskId}: git reset --merge cleanup failed during ${label}: ${msg}`);
56143
+ }
56144
+ }
56145
+ function buildDeterministicMergeMessage(params) {
56146
+ const { taskId, branch, commitLog, includeTaskId } = params;
56147
+ const prefix = includeTaskId ? `feat(${taskId})` : "feat";
56148
+ const subject = `${prefix}: merge ${branch}`;
56149
+ const body = commitLog && commitLog.trim().length > 0 ? commitLog.trim() : `- merge ${branch}`;
56150
+ const escape = (s) => s.replace(/(["\\$`])/g, "\\$1");
56151
+ return {
56152
+ subjectArg: `-m "${escape(subject)}"`,
56153
+ bodyArg: `-m "${escape(body)}"`
56154
+ };
56155
+ }
56156
+ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, includeTaskId, preAttemptHeadSha, authorArg) {
56106
56157
  try {
56107
- const { stdout: stagedFiles } = await execAsync2("git diff --cached --name-only", {
56108
- cwd: rootDir,
56109
- encoding: "utf-8"
56110
- });
56111
56158
  const { stdout: unstagedFiles } = await execAsync2("git diff --name-only", {
56112
56159
  cwd: rootDir,
56113
56160
  encoding: "utf-8"
56114
56161
  });
56115
- const hasChanges = stagedFiles.trim().length > 0 || unstagedFiles.trim().length > 0;
56116
- if (!hasChanges) {
56117
- mergerLog.log(`${taskId}: no changes to amend after verification fix`);
56118
- return false;
56119
- }
56120
56162
  if (unstagedFiles.trim().length > 0) {
56121
56163
  await execAsync2("git add -A", { cwd: rootDir });
56122
56164
  }
@@ -56124,12 +56166,10 @@ async function amendMergeCommitWithFixes(rootDir, taskId, authorArg) {
56124
56166
  cwd: rootDir,
56125
56167
  encoding: "utf-8"
56126
56168
  });
56127
- const gitlinkPaths = [];
56128
56169
  for (const line of staged.split("\n")) {
56129
56170
  const match = line.match(/^:\d{6} 160000 [^\t]+\t(.+)$/);
56130
- if (match) gitlinkPaths.push(match[1]);
56131
- }
56132
- for (const path5 of gitlinkPaths) {
56171
+ if (!match) continue;
56172
+ const path5 = match[1];
56133
56173
  mergerLog.warn(`${taskId}: refusing to stage gitlink "${path5}" (project uses no submodules \u2014 likely a nested worktree). Unstaging.`);
56134
56174
  try {
56135
56175
  await execAsync2(`git reset HEAD -- "${path5}"`, { cwd: rootDir });
@@ -56142,15 +56182,43 @@ async function amendMergeCommitWithFixes(rootDir, taskId, authorArg) {
56142
56182
  cwd: rootDir,
56143
56183
  encoding: "utf-8"
56144
56184
  });
56145
- if (finalStaged.trim().length > 0) {
56146
- await execAsync2(`git commit --amend --no-edit${authorArg}`, { cwd: rootDir });
56147
- mergerLog.log(`${taskId}: amended merge commit with verification fixes`);
56185
+ const hasStaged = finalStaged.trim().length > 0;
56186
+ const { stdout: currentHeadOut } = await execAsync2("git rev-parse HEAD", {
56187
+ cwd: rootDir,
56188
+ encoding: "utf-8"
56189
+ });
56190
+ const currentHead = currentHeadOut.trim();
56191
+ const headMoved = currentHead !== preAttemptHeadSha;
56192
+ if (!hasStaged && !headMoved) {
56193
+ mergerLog.warn(
56194
+ `${taskId}: refusing to record merge \u2014 no commit was created and no changes are staged. This usually means the AI agent never ran git commit and the in-merge fix had nothing to add.`
56195
+ );
56196
+ return false;
56197
+ }
56198
+ const { subjectArg, bodyArg } = buildDeterministicMergeMessage({
56199
+ taskId,
56200
+ branch,
56201
+ commitLog,
56202
+ includeTaskId
56203
+ });
56204
+ const trailerArg = buildTaskIdTrailerArg(taskId);
56205
+ if (!headMoved) {
56206
+ await execAsync2(
56207
+ `git commit ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
56208
+ { cwd: rootDir }
56209
+ );
56210
+ mergerLog.log(`${taskId}: created fresh merge commit after verification fix (no prior commit to amend)`);
56148
56211
  return true;
56149
56212
  }
56150
- return false;
56213
+ await execAsync2(
56214
+ `git commit --amend ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
56215
+ { cwd: rootDir }
56216
+ );
56217
+ mergerLog.log(`${taskId}: amended merge commit with verification fixes (deterministic message)`);
56218
+ return true;
56151
56219
  } catch (err) {
56152
56220
  const errorMessage = err instanceof Error ? err.message : String(err);
56153
- mergerLog.warn(`${taskId}: failed to amend merge commit: ${errorMessage}`);
56221
+ mergerLog.warn(`${taskId}: failed to finalize merge commit: ${errorMessage}`);
56154
56222
  return false;
56155
56223
  }
56156
56224
  }
@@ -56401,6 +56469,11 @@ function getCommitAuthorArg(settings) {
56401
56469
  const email = settings.commitAuthorEmail || "noreply@runfusion.ai";
56402
56470
  return ` --author="${name} <${email}>"`;
56403
56471
  }
56472
+ function buildSourceIssueRef(sourceIssue) {
56473
+ if (!sourceIssue || sourceIssue.provider !== "github") return "";
56474
+ if (!sourceIssue.repository || !sourceIssue.issueNumber) return "";
56475
+ return `${sourceIssue.repository}#${sourceIssue.issueNumber}`;
56476
+ }
56404
56477
  function buildMergeSystemPrompt(includeTaskId, agentPrompts, authorArg) {
56405
56478
  const commitFormat = includeTaskId ? `\`\`\`
56406
56479
  git commit -m "<type>(<scope>): <summary>" -m "<body>"${authorArg || ""}
@@ -56411,6 +56484,7 @@ Message format:
56411
56484
  - **Scope:** the task ID (e.g., KB-001)
56412
56485
  - **Summary:** one line describing what the squash brings in (imperative mood)
56413
56486
  - **Body:** 2-5 bullet points summarizing the key changes, each starting with "- "
56487
+ - **GitHub reference:** when the prompt includes a source issue reference, add \`Ref: owner/repo#N\` to the commit body
56414
56488
  ${authorArg ? `- **Author:** Always include the --author flag as shown in the example above.` : ""}
56415
56489
 
56416
56490
  Example:
@@ -56428,6 +56502,7 @@ Message format:
56428
56502
  - **Type:** feat, fix, refactor, docs, test, chore
56429
56503
  - **Summary:** one line describing what the squash brings in (imperative mood)
56430
56504
  - **Body:** 2-5 bullet points summarizing the key changes, each starting with "- "
56505
+ - **GitHub reference:** when the prompt includes a source issue reference, add \`Ref: owner/repo#N\` to the commit body
56431
56506
  ${authorArg ? `- **Author:** Always include the --author flag as shown in the example above.` : ""}
56432
56507
  Do NOT include a scope in the commit message type.
56433
56508
 
@@ -56811,6 +56886,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
56811
56886
  throw new Error(`Cannot merge ${taskId}: ${mergeBlocker}`);
56812
56887
  }
56813
56888
  const branch = task.branch || `fusion/${taskId.toLowerCase()}`;
56889
+ const sourceIssueRef = buildSourceIssueRef(task.sourceIssue);
56814
56890
  const worktreePath = task.worktree;
56815
56891
  const result = {
56816
56892
  task,
@@ -57114,6 +57190,17 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
57114
57190
  void 0,
57115
57191
  "merger"
57116
57192
  );
57193
+ let preAttemptHeadSha = "";
57194
+ try {
57195
+ const { stdout } = await execAsync2("git rev-parse HEAD", {
57196
+ cwd: rootDir,
57197
+ encoding: "utf-8"
57198
+ });
57199
+ preAttemptHeadSha = stdout.trim();
57200
+ } catch (err) {
57201
+ const msg = err instanceof Error ? err.message : String(err);
57202
+ mergerLog.warn(`${taskId}: failed to capture pre-attempt HEAD (${msg}) \u2014 verification-fix finalizer will fall back to amend`);
57203
+ }
57117
57204
  try {
57118
57205
  const success = await executeMergeAttempt({
57119
57206
  store,
@@ -57123,6 +57210,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
57123
57210
  commitLog,
57124
57211
  diffStat,
57125
57212
  includeTaskId,
57213
+ sourceIssueRef,
57126
57214
  smartConflictResolution,
57127
57215
  mergeConflictStrategy,
57128
57216
  attemptNum,
@@ -57231,12 +57319,27 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
57231
57319
  }
57232
57320
  if (fixSuccess) {
57233
57321
  const authorArg = getCommitAuthorArg(settings);
57234
- await amendMergeCommitWithFixes(rootDir, taskId, authorArg);
57322
+ const finalized = await commitOrAmendMergeWithFixes(
57323
+ rootDir,
57324
+ taskId,
57325
+ branch,
57326
+ commitLog,
57327
+ includeTaskId,
57328
+ preAttemptHeadSha,
57329
+ authorArg
57330
+ );
57331
+ if (!finalized) {
57332
+ resetMergeWithWarn(rootDir, taskId, "verification-fix finalize");
57333
+ throw new Error(
57334
+ `${taskId}: verification fix succeeded but no merge commit could be created \u2014 refusing to mark merge complete.`
57335
+ );
57336
+ }
57235
57337
  return true;
57236
57338
  }
57237
57339
  }
57238
57340
  }
57239
57341
  mergerLog.error(`${taskId}: deterministic verification failed \u2014 aborting merge (in-merge fix exhausted or disabled)`);
57342
+ resetMergeWithWarn(rootDir, taskId, "deterministic-verification rollback");
57240
57343
  throw error;
57241
57344
  }
57242
57345
  if (error.message?.includes("Build verification failed")) {
@@ -57307,7 +57410,21 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
57307
57410
  }
57308
57411
  if (fixSuccess) {
57309
57412
  const authorArg = getCommitAuthorArg(settings);
57310
- await amendMergeCommitWithFixes(rootDir, taskId, authorArg);
57413
+ const finalized = await commitOrAmendMergeWithFixes(
57414
+ rootDir,
57415
+ taskId,
57416
+ branch,
57417
+ commitLog,
57418
+ includeTaskId,
57419
+ preAttemptHeadSha,
57420
+ authorArg
57421
+ );
57422
+ if (!finalized) {
57423
+ resetMergeWithWarn(rootDir, taskId, "build-verification fix finalize");
57424
+ throw new Error(
57425
+ `${taskId}: build verification fix succeeded but no merge commit could be created \u2014 refusing to mark merge complete.`
57426
+ );
57427
+ }
57311
57428
  return true;
57312
57429
  }
57313
57430
  }
@@ -57321,10 +57438,11 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
57321
57438
  await audit.git({ type: "reset:hard", target: branch, metadata: { purpose: "build-retry" } });
57322
57439
  } catch (err) {
57323
57440
  const msg = err instanceof Error ? err.message : String(err);
57324
- mergerLog.warn(`${taskId}: git reset --merge cleanup failed (build-retry): ${msg}`);
57441
+ mergerLog.warn(`${taskId}: git reset --merge cleanup failed during build-verification rollback (build-retry): ${msg}`);
57325
57442
  }
57326
57443
  return false;
57327
57444
  }
57445
+ resetMergeWithWarn(rootDir, taskId, "build-verification rollback (no retries left)");
57328
57446
  throw error;
57329
57447
  }
57330
57448
  if (error.name === "MergeNonConflictError") {
@@ -57672,6 +57790,7 @@ async function executeMergeAttempt(params, aiTracker) {
57672
57790
  commitLog,
57673
57791
  diffStat,
57674
57792
  includeTaskId,
57793
+ sourceIssueRef,
57675
57794
  smartConflictResolution,
57676
57795
  attemptNum,
57677
57796
  options,
@@ -57862,19 +57981,12 @@ async function executeMergeAttempt(params, aiTracker) {
57862
57981
  simplifiedContext: attemptNum === 2,
57863
57982
  options,
57864
57983
  testCommand,
57865
- buildCommand: buildCommand2
57984
+ buildCommand: buildCommand2,
57985
+ sourceIssueRef
57866
57986
  });
57867
57987
  if (!agentResult.success) {
57868
57988
  const errorMessage = agentResult.error || "Build verification failed";
57869
57989
  await store.logEntry(taskId, "Build verification failed during merge", errorMessage);
57870
- try {
57871
- execSync("git reset --merge", { cwd: rootDir, stdio: "pipe" });
57872
- } catch (resetErr) {
57873
- const msg = resetErr instanceof Error ? resetErr.message : String(resetErr);
57874
- mergerLog.warn(
57875
- `${taskId}: git reset --merge cleanup failed during build-verification rollback (build-verification reset, build-retry): ${msg}`
57876
- );
57877
- }
57878
57990
  throw new Error(`Build verification failed for ${taskId}: ${errorMessage}`);
57879
57991
  }
57880
57992
  if (testCommand || buildCommand2) {
@@ -57890,6 +58002,24 @@ async function executeMergeAttempt(params, aiTracker) {
57890
58002
  options.signal
57891
58003
  );
57892
58004
  }
58005
+ try {
58006
+ const authorArg = getCommitAuthorArg(params.settings);
58007
+ const { subjectArg, bodyArg } = buildDeterministicMergeMessage({
58008
+ taskId,
58009
+ branch,
58010
+ commitLog,
58011
+ includeTaskId
58012
+ });
58013
+ const trailerArg = buildTaskIdTrailerArg(taskId);
58014
+ await execAsync2(
58015
+ `git commit --amend ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
58016
+ { cwd: rootDir }
58017
+ );
58018
+ mergerLog.log(`${taskId}: rewrote AI-authored merge commit message with deterministic body`);
58019
+ } catch (err) {
58020
+ const msg = err instanceof Error ? err.message : String(err);
58021
+ mergerLog.warn(`${taskId}: failed to canonicalize merge commit message (${msg}) \u2014 keeping AI-written message`);
58022
+ }
57893
58023
  return true;
57894
58024
  } catch (error) {
57895
58025
  if (error instanceof Error && error.name === "MergeAbortedError") {
@@ -57912,7 +58042,7 @@ async function executeMergeAttempt(params, aiTracker) {
57912
58042
  }
57913
58043
  }
57914
58044
  async function attemptWithSideStrategy(params, side = "theirs", aiTracker) {
57915
- const { rootDir, branch, commitLog, includeTaskId, taskId, store, settings, testCommand, buildCommand: buildCommand2, testSource, buildSource } = params;
58045
+ const { rootDir, branch, commitLog, includeTaskId, sourceIssueRef, taskId, store, settings, testCommand, buildCommand: buildCommand2, testSource, buildSource } = params;
57916
58046
  mergerLog.log(`${taskId}: attempting merge with -X ${side} strategy`);
57917
58047
  try {
57918
58048
  throwIfAborted(params.options.signal, taskId);
@@ -57953,8 +58083,9 @@ async function attemptWithSideStrategy(params, side = "theirs", aiTracker) {
57953
58083
  const fallbackPrefix = includeTaskId ? `feat(${taskId})` : "feat";
57954
58084
  const authorArg = getCommitAuthorArg(settings);
57955
58085
  const trailerArg = buildTaskIdTrailerArg(taskId);
58086
+ const issueRefBodyArg = sourceIssueRef ? ` -m "Ref: ${sourceIssueRef}"` : "";
57956
58087
  await execAsync2(
57957
- `git commit -m "${fallbackPrefix}: merge ${branch} (auto-resolved)" -m "${escapedLog}"${trailerArg}${authorArg}`,
58088
+ `git commit -m "${fallbackPrefix}: merge ${branch} (auto-resolved)" -m "${escapedLog}"${issueRefBodyArg}${trailerArg}${authorArg}`,
57958
58089
  { cwd: rootDir }
57959
58090
  );
57960
58091
  mergerLog.log(`${taskId}: committed with -X ${side} auto-resolution`);
@@ -57991,6 +58122,7 @@ async function runAiAgentForCommit(params) {
57991
58122
  includeTaskId,
57992
58123
  hasConflicts,
57993
58124
  simplifiedContext,
58125
+ sourceIssueRef,
57994
58126
  options,
57995
58127
  testCommand,
57996
58128
  buildCommand: buildCommand2
@@ -58089,7 +58221,8 @@ async function runAiAgentForCommit(params) {
58089
58221
  simplifiedContext,
58090
58222
  testCommand,
58091
58223
  buildCommand: buildCommand2,
58092
- authorArg
58224
+ authorArg,
58225
+ sourceIssueRef
58093
58226
  });
58094
58227
  mergerLog.log(`${taskId}: starting fresh merge agent session`);
58095
58228
  try {
@@ -58121,7 +58254,8 @@ async function runAiAgentForCommit(params) {
58121
58254
  // Also skip detailed context
58122
58255
  testCommand,
58123
58256
  buildCommand: buildCommand2,
58124
- authorArg
58257
+ authorArg,
58258
+ sourceIssueRef
58125
58259
  });
58126
58260
  try {
58127
58261
  await withRateLimitRetry(async () => {
@@ -58163,8 +58297,9 @@ async function runAiAgentForCommit(params) {
58163
58297
  const fallbackPrefix = includeTaskId ? `feat(${taskId})` : "feat";
58164
58298
  const authorArg2 = getCommitAuthorArg(settings);
58165
58299
  const trailerArg = buildTaskIdTrailerArg(taskId);
58300
+ const issueRefBodyArg = sourceIssueRef ? ` -m "Ref: ${sourceIssueRef}"` : "";
58166
58301
  await execAsync2(
58167
- `git commit -m "${fallbackPrefix}: merge ${branch}" -m "${escapedLog}"${trailerArg}${authorArg2}`,
58302
+ `git commit -m "${fallbackPrefix}: merge ${branch}" -m "${escapedLog}"${issueRefBodyArg}${trailerArg}${authorArg2}`,
58168
58303
  { cwd: rootDir }
58169
58304
  );
58170
58305
  } else {
@@ -58187,7 +58322,7 @@ async function runAiAgentForCommit(params) {
58187
58322
  }
58188
58323
  }
58189
58324
  function buildMergePrompt(params) {
58190
- const { taskId, branch, commitLog, diffStat, hasConflicts, simplifiedContext, testCommand, buildCommand: buildCommand2, authorArg } = params;
58325
+ const { taskId, branch, commitLog, diffStat, hasConflicts, simplifiedContext, sourceIssueRef, testCommand, buildCommand: buildCommand2, authorArg } = params;
58191
58326
  const truncatedCommitLog = truncateWithEllipsis(commitLog, MERGE_COMMIT_LOG_MAX_CHARS);
58192
58327
  const truncatedDiffStat = truncateWithEllipsis(diffStat, MERGE_DIFF_STAT_MAX_CHARS);
58193
58328
  const parts = [
@@ -58223,6 +58358,13 @@ function buildMergePrompt(params) {
58223
58358
  `Write and run the \`git commit\` command with a good message summarizing the work.${authorArg ? ` Be sure to include \`${authorArg.trim()}\` in the commit command.` : ""}`
58224
58359
  );
58225
58360
  }
58361
+ if (sourceIssueRef) {
58362
+ parts.push(
58363
+ "",
58364
+ "Include this in the commit message body:",
58365
+ `- Ref: ${sourceIssueRef}`
58366
+ );
58367
+ }
58226
58368
  if (testCommand) {
58227
58369
  parts.push(
58228
58370
  "",
@@ -59398,7 +59540,7 @@ function resolveExecutorModelPair(taskModelProvider, taskModelId, settings) {
59398
59540
  return { provider: void 0, modelId: void 0 };
59399
59541
  }
59400
59542
  function sleep2(ms) {
59401
- return new Promise((resolve36) => setTimeout(resolve36, ms));
59543
+ return new Promise((resolve39) => setTimeout(resolve39, ms));
59402
59544
  }
59403
59545
  var execAsync4, stepExecLog, MAX_STEP_RETRIES, RETRY_DELAYS_MS, NOOP_TASK_STORE, StepSessionExecutor;
59404
59546
  var init_step_session_executor = __esm({
@@ -60146,6 +60288,7 @@ function buildExecutionPrompt(task, rootDir, settings, worktreePath) {
60146
60288
  const reviewMatch = prompt.match(/##\s*Review Level[:\s]*(\d)/);
60147
60289
  const reviewLevel = reviewMatch ? parseInt(reviewMatch[1], 10) : 0;
60148
60290
  const authorArg = settings?.commitAuthorEnabled !== false ? ` --author="${settings?.commitAuthorName || "Fusion"} <${settings?.commitAuthorEmail || "noreply@runfusion.ai"}>"` : "";
60291
+ const sourceIssueRef = task.sourceIssue?.provider === "github" && task.sourceIssue.repository && task.sourceIssue.issueNumber ? `${task.sourceIssue.repository}#${task.sourceIssue.issueNumber}` : "";
60149
60292
  const hasProgress = task.steps.length > 0 && task.steps.some((s) => s.status !== "pending");
60150
60293
  let progressSection = "";
60151
60294
  if (hasProgress) {
@@ -60248,7 +60391,7 @@ ${hasProgress ? `Resume from Step ${task.currentStep}. Do NOT redo completed ste
60248
60391
  Use \`fn_task_update\` to report progress on every step transition.
60249
60392
  Use \`fn_task_log\` for important actions and decisions.
60250
60393
  Use \`fn_task_create\` for truly separate follow-up work, not for fixes required to get tests, build, or typecheck back to green.
60251
- Commit at step boundaries: \`git commit -m "feat(${task.id}): complete Step N \u2014 description"${authorArg}\`
60394
+ Commit at step boundaries: \`git commit -m "feat(${task.id}): complete Step N \u2014 description"${sourceIssueRef ? ` -m "Ref: ${sourceIssueRef}"` : ""}${authorArg}\`
60252
60395
  When all steps are complete: call \`fn_task_done()\`
60253
60396
 
60254
60397
  If a build command is configured, run that exact command in this worktree before calling \`fn_task_done()\`.
@@ -60281,7 +60424,7 @@ function detectReviewHandoffIntent(commentText) {
60281
60424
  ];
60282
60425
  return handoffPhrases.some((phrase) => text.includes(phrase));
60283
60426
  }
60284
- var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
60427
+ var execAsync5, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, COMPLETED_TASK_WATCHDOG_MS, WORKFLOW_RERUN_WATCHDOG_MS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
60285
60428
  var init_executor = __esm({
60286
60429
  "../engine/src/executor.ts"() {
60287
60430
  "use strict";
@@ -60317,6 +60460,8 @@ var init_executor = __esm({
60317
60460
  MAX_WORKFLOW_STEP_RETRIES = 3;
60318
60461
  MAX_TASK_DONE_SESSION_RETRIES = 3;
60319
60462
  MAX_TASK_DONE_REQUEUE_RETRIES = 3;
60463
+ COMPLETED_TASK_WATCHDOG_MS = 6e4;
60464
+ WORKFLOW_RERUN_WATCHDOG_MS = 15e3;
60320
60465
  WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2 = 4e3;
60321
60466
  NonRetryableWorktreeError = class extends Error {
60322
60467
  };
@@ -60434,6 +60579,7 @@ If the task's PROMPT.md includes a "Documentation Requirements" section listing
60434
60579
  ## Git discipline
60435
60580
  - Commit after completing each step (not after every file change)
60436
60581
  - Use conventional commit messages prefixed with the task ID
60582
+ - When the task has a GitHub issue reference, include \`Ref: owner/repo#N\` in the commit body
60437
60583
  - Do NOT commit broken or half-implemented code
60438
60584
 
60439
60585
  ## Worktree Boundaries
@@ -60526,6 +60672,7 @@ Lint, tests, and typecheck are also hard quality gates:
60526
60672
  store.on("task:moved", ({ task, from, to }) => {
60527
60673
  executorLog.log(`[event:task:moved] ${task.id}: ${from} \u2192 ${to}`);
60528
60674
  if (to === "in-progress") {
60675
+ this.clearWorkflowRerunWatchdog(task.id);
60529
60676
  executorLog.log(`[event:task:moved] Initiating execute() for ${task.id}`);
60530
60677
  void (async () => {
60531
60678
  const taskForExecution = await this.resetMergeStateIfNeeded(task, from);
@@ -60534,6 +60681,7 @@ Lint, tests, and typecheck are also hard quality gates:
60534
60681
  (err) => executorLog.error(`Failed to start ${task.id}:`, err)
60535
60682
  );
60536
60683
  } else if (from === "in-progress") {
60684
+ this.clearCompletedTaskWatchdog(task.id);
60537
60685
  if (this.activeSessions.has(task.id)) {
60538
60686
  executorLog.log(`${task.id} moved from in-progress to ${to} \u2014 terminating agent session`);
60539
60687
  this.pausedAborted.add(task.id);
@@ -60725,6 +60873,10 @@ Lint, tests, and typecheck are also hard quality gates:
60725
60873
  spawnedAgents = /* @__PURE__ */ new Map();
60726
60874
  /** Per-task baseline of session stats used for delta persistence across repeated updates. */
60727
60875
  tokenUsageBaselines = /* @__PURE__ */ new Map();
60876
+ /** One-shot watchdogs for completed tasks that should have transitioned to in-review. */
60877
+ completedTaskWatchdogs = /* @__PURE__ */ new Map();
60878
+ /** One-shot watchdogs for workflow reruns that should have bounced back to in-progress. */
60879
+ workflowRerunWatchdogs = /* @__PURE__ */ new Map();
60728
60880
  async finalizeAlreadyReviewedTask(taskId) {
60729
60881
  const latestTask = await this.store.getTask(taskId);
60730
60882
  if (!latestTask || latestTask.column !== "in-review") {
@@ -60880,6 +61032,120 @@ Lint, tests, and typecheck are also hard quality gates:
60880
61032
  await this.store.updateTask(task.id, updates);
60881
61033
  }
60882
61034
  }
61035
+ clearCompletedTaskWatchdog(taskId) {
61036
+ const handle = this.completedTaskWatchdogs.get(taskId);
61037
+ if (!handle) return;
61038
+ clearTimeout(handle);
61039
+ this.completedTaskWatchdogs.delete(taskId);
61040
+ }
61041
+ clearWorkflowRerunWatchdog(taskId) {
61042
+ const handle = this.workflowRerunWatchdogs.get(taskId);
61043
+ if (!handle) return;
61044
+ clearTimeout(handle);
61045
+ this.workflowRerunWatchdogs.delete(taskId);
61046
+ }
61047
+ scheduleCompletedTaskWatchdog(taskId, trigger) {
61048
+ this.clearCompletedTaskWatchdog(taskId);
61049
+ const handle = setTimeout(async () => {
61050
+ this.completedTaskWatchdogs.delete(taskId);
61051
+ let currentTask = null;
61052
+ try {
61053
+ currentTask = await this.store.getTask(taskId);
61054
+ } catch (err) {
61055
+ const errorMessage = err instanceof Error ? err.message : String(err);
61056
+ executorLog.warn(`${taskId}: completed-task watchdog could not read latest task state: ${errorMessage}`);
61057
+ return;
61058
+ }
61059
+ if (!currentTask || currentTask.column !== "in-progress" || currentTask.paused) {
61060
+ return;
61061
+ }
61062
+ if (this.activeSessions.has(taskId) || this.activeStepExecutors.has(taskId) || this.recoveringCompleted.has(taskId)) {
61063
+ return;
61064
+ }
61065
+ if (!this.isTaskWorkComplete(currentTask)) {
61066
+ return;
61067
+ }
61068
+ executorLog.warn(
61069
+ `${taskId}: completed-task watchdog fired after ${COMPLETED_TASK_WATCHDOG_MS / 1e3}s (${trigger}) \u2014 attempting direct recovery to in-review`
61070
+ );
61071
+ await this.store.logEntry(
61072
+ taskId,
61073
+ `Watchdog: task remained in-progress ${COMPLETED_TASK_WATCHDOG_MS / 1e3}s after ${trigger} \u2014 attempting direct recovery to in-review`
61074
+ ).catch(() => void 0);
61075
+ this.recoveringCompleted.add(taskId);
61076
+ try {
61077
+ const recovered = await this.recoverCompletedTask(currentTask);
61078
+ if (!recovered) {
61079
+ await this.store.logEntry(
61080
+ taskId,
61081
+ "Watchdog recovery attempt could not finalize completed task \u2014 leaving for follow-up recovery"
61082
+ ).catch(() => void 0);
61083
+ }
61084
+ } finally {
61085
+ this.recoveringCompleted.delete(taskId);
61086
+ }
61087
+ }, COMPLETED_TASK_WATCHDOG_MS);
61088
+ this.completedTaskWatchdogs.set(taskId, handle);
61089
+ }
61090
+ async performWorkflowRerunBounce(taskId, worktreePath) {
61091
+ const latestTask = await this.store.getTask(taskId);
61092
+ if (!latestTask) {
61093
+ throw new Error("task missing during workflow rerun bounce");
61094
+ }
61095
+ if (latestTask.column === "in-progress") {
61096
+ await this.store.moveTask(taskId, "todo");
61097
+ await this.store.updateTask(taskId, { worktree: worktreePath });
61098
+ await this.store.moveTask(taskId, "in-progress");
61099
+ return;
61100
+ }
61101
+ if (latestTask.column === "todo") {
61102
+ await this.store.updateTask(taskId, { worktree: worktreePath });
61103
+ await this.store.moveTask(taskId, "in-progress");
61104
+ return;
61105
+ }
61106
+ throw new Error(`task is in '${latestTask.column}', cannot bounce to in-progress`);
61107
+ }
61108
+ scheduleWorkflowRerun(taskId, worktreePath, successMessage) {
61109
+ this.clearWorkflowRerunWatchdog(taskId);
61110
+ setTimeout(async () => {
61111
+ try {
61112
+ await this.performWorkflowRerunBounce(taskId, worktreePath);
61113
+ executorLog.log(successMessage);
61114
+ } catch (err) {
61115
+ const errorMessage = err instanceof Error ? err.message : String(err);
61116
+ executorLog.error(`${taskId}: failed to schedule rerun bounce: ${errorMessage}`);
61117
+ }
61118
+ }, 0);
61119
+ const watchdog = setTimeout(async () => {
61120
+ this.workflowRerunWatchdogs.delete(taskId);
61121
+ let currentTask = null;
61122
+ try {
61123
+ currentTask = await this.store.getTask(taskId);
61124
+ } catch (err) {
61125
+ const errorMessage = err instanceof Error ? err.message : String(err);
61126
+ executorLog.warn(`${taskId}: workflow rerun watchdog could not read latest task state: ${errorMessage}`);
61127
+ return;
61128
+ }
61129
+ if (!currentTask || currentTask.paused || currentTask.column === "in-progress") {
61130
+ return;
61131
+ }
61132
+ executorLog.warn(
61133
+ `${taskId}: workflow rerun watchdog fired after ${WORKFLOW_RERUN_WATCHDOG_MS / 1e3}s \u2014 task is still ${currentTask.column}; retrying handoff once`
61134
+ );
61135
+ await this.store.logEntry(
61136
+ taskId,
61137
+ `Watchdog: workflow rerun handoff stalled for ${WORKFLOW_RERUN_WATCHDOG_MS / 1e3}s (still ${currentTask.column}) \u2014 retrying once`
61138
+ ).catch(() => void 0);
61139
+ try {
61140
+ await this.performWorkflowRerunBounce(taskId, worktreePath);
61141
+ executorLog.warn(`${taskId}: workflow rerun watchdog retry succeeded`);
61142
+ } catch (err) {
61143
+ const errorMessage = err instanceof Error ? err.message : String(err);
61144
+ executorLog.error(`${taskId}: workflow rerun watchdog retry failed: ${errorMessage}`);
61145
+ }
61146
+ }, WORKFLOW_RERUN_WATCHDOG_MS);
61147
+ this.workflowRerunWatchdogs.set(taskId, watchdog);
61148
+ }
60883
61149
  async shouldFinalizeCompletedTask(taskId, taskDone) {
60884
61150
  const task = await this.store.getTask(taskId);
60885
61151
  const completionBlocker = await this.getTaskCompletionBlocker(task);
@@ -61013,6 +61279,7 @@ Lint, tests, and typecheck are also hard quality gates:
61013
61279
  }
61014
61280
  await this.persistTokenUsage(task.id);
61015
61281
  await this.store.moveTask(task.id, "in-review");
61282
+ this.clearCompletedTaskWatchdog(task.id);
61016
61283
  await this.store.logEntry(task.id, "Auto-recovered: task work was complete but stuck in in-progress \u2014 moved to in-review");
61017
61284
  executorLog.log(`\u2713 ${task.id} auto-recovered completed task \u2192 in-review`);
61018
61285
  this.options.onComplete?.(task);
@@ -61509,6 +61776,7 @@ Lint, tests, and typecheck are also hard quality gates:
61509
61776
  executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
61510
61777
  await audit.filesystem({ type: "file:capture-modified", target: task.id, metadata: { files: modifiedFiles } });
61511
61778
  }
61779
+ this.scheduleCompletedTaskWatchdog(task.id, "step-session completion");
61512
61780
  if (executionMode !== "fast") {
61513
61781
  const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
61514
61782
  if (!workflowResult.allPassed) {
@@ -61529,6 +61797,7 @@ Lint, tests, and typecheck are also hard quality gates:
61529
61797
  }
61530
61798
  await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
61531
61799
  await this.store.moveTask(task.id, "in-review");
61800
+ this.clearCompletedTaskWatchdog(task.id);
61532
61801
  await audit.database({ type: "task:move", target: task.id, metadata: { to: "in-review" } });
61533
61802
  executorLog.log(`\u2713 ${task.id} completed (step-session) \u2192 in-review`);
61534
61803
  this.options.onComplete?.(task);
@@ -61865,6 +62134,7 @@ Lint, tests, and typecheck are also hard quality gates:
61865
62134
  await this.store.logEntry(task.id, "Execution paused after completion \u2014 finalizing to in-review");
61866
62135
  await this.persistTokenUsage(task.id);
61867
62136
  await this.store.moveTask(task.id, "in-review");
62137
+ this.clearCompletedTaskWatchdog(task.id);
61868
62138
  this.options.onComplete?.(task);
61869
62139
  } else {
61870
62140
  executorLog.log(`${task.id} paused (graceful session exit) \u2014 moving to todo`);
@@ -61885,6 +62155,7 @@ Lint, tests, and typecheck are also hard quality gates:
61885
62155
  taskDone = true;
61886
62156
  executorLog.log(`${task.id} all steps done \u2014 treating as implicit fn_task_done`);
61887
62157
  await this.store.logEntry(task.id, "All steps complete \u2014 implicit fn_task_done (agent did not call tool explicitly)", void 0, this.currentRunContext);
62158
+ this.scheduleCompletedTaskWatchdog(task.id, "implicit fn_task_done");
61888
62159
  }
61889
62160
  }
61890
62161
  if (taskDone) {
@@ -61894,6 +62165,7 @@ Lint, tests, and typecheck are also hard quality gates:
61894
62165
  await this.store.updateTask(task.id, { modifiedFiles });
61895
62166
  executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
61896
62167
  }
62168
+ this.scheduleCompletedTaskWatchdog(task.id, "task completion");
61897
62169
  if (executionMode !== "fast") {
61898
62170
  const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
61899
62171
  if (!workflowResult.allPassed) {
@@ -61915,6 +62187,7 @@ Lint, tests, and typecheck are also hard quality gates:
61915
62187
  await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
61916
62188
  await this.persistTokenUsage(task.id);
61917
62189
  await this.store.moveTask(task.id, "in-review");
62190
+ this.clearCompletedTaskWatchdog(task.id);
61918
62191
  executorLog.log(`\u2713 ${task.id} completed \u2192 in-review`);
61919
62192
  this.options.onComplete?.(task);
61920
62193
  } else {
@@ -61988,6 +62261,7 @@ Lint, tests, and typecheck are also hard quality gates:
61988
62261
  taskDone = true;
61989
62262
  executorLog.log(`${task.id} all steps done \u2014 treating as implicit fn_task_done`);
61990
62263
  await this.store.logEntry(task.id, "All steps complete \u2014 implicit fn_task_done (agent did not call tool explicitly)", void 0, this.currentRunContext);
62264
+ this.scheduleCompletedTaskWatchdog(task.id, "implicit fn_task_done");
61991
62265
  }
61992
62266
  }
61993
62267
  }
@@ -61998,6 +62272,7 @@ Lint, tests, and typecheck are also hard quality gates:
61998
62272
  await this.store.updateTask(task.id, { modifiedFiles });
61999
62273
  executorLog.log(`${task.id}: captured ${modifiedFiles.length} modified files`);
62000
62274
  }
62275
+ this.scheduleCompletedTaskWatchdog(task.id, "task completion retry");
62001
62276
  if (executionMode !== "fast") {
62002
62277
  const workflowResult = await this.runWorkflowSteps(task, worktreePath, settings);
62003
62278
  if (!workflowResult.allPassed) {
@@ -62015,6 +62290,7 @@ Lint, tests, and typecheck are also hard quality gates:
62015
62290
  await this.store.updateTask(task.id, { workflowStepRetries: void 0, taskDoneRetryCount: null });
62016
62291
  await this.persistTokenUsage(task.id);
62017
62292
  await this.store.moveTask(task.id, "in-review");
62293
+ this.clearCompletedTaskWatchdog(task.id);
62018
62294
  executorLog.log(`\u2713 ${task.id} completed on retry \u2192 in-review`);
62019
62295
  this.options.onComplete?.(task);
62020
62296
  } else {
@@ -62442,6 +62718,7 @@ Lint, tests, and typecheck are also hard quality gates:
62442
62718
  await store.updateTask(taskId, { summary: params.summary });
62443
62719
  }
62444
62720
  await store.logEntry(taskId, "Task marked done by agent");
62721
+ this.scheduleCompletedTaskWatchdog(taskId, "fn_task_done");
62445
62722
  const successMessage = params.summary ? "Task marked complete with summary. All steps done. Moving to in-review." : "Task marked complete. All steps done. Moving to in-review.";
62446
62723
  return {
62447
62724
  content: [{ type: "text", text: successMessage }],
@@ -62668,6 +62945,7 @@ Take a different approach. Do NOT repeat the rejected strategy. Re-read the step
62668
62945
  */
62669
62946
  async handleWorkflowRevisionRequest(task, worktreePath, feedback, stepName) {
62670
62947
  executorLog.log(`${task.id}: workflow revision requested by step "${stepName}"`);
62948
+ this.clearCompletedTaskWatchdog(task.id);
62671
62949
  const updatedTask = await this.store.getTask(task.id);
62672
62950
  const reopen = await this.reopenLastStepForRevision(task.id, updatedTask);
62673
62951
  const reopenSummary = reopen ? `re-opening Step ${reopen.index + 1} ("${reopen.name}") for in-place fix` : "no step to re-open (none were completed)";
@@ -62682,21 +62960,11 @@ Take a different approach. Do NOT repeat the rejected strategy. Re-read the step
62682
62960
  sessionFile: null
62683
62961
  });
62684
62962
  executorLog.log(`${task.id}: scheduling fresh execution after revision request`);
62685
- setTimeout(async () => {
62686
- try {
62687
- await this.store.moveTask(task.id, "todo");
62688
- await this.store.updateTask(task.id, { worktree: worktreePath });
62689
- await this.store.moveTask(task.id, "in-progress");
62690
- executorLog.log(`${task.id}: revision rerun scheduled \u2014 moved to todo then in-progress`);
62691
- } catch (err) {
62692
- const errorMessage = err instanceof Error ? err.message : String(err);
62693
- executorLog.error(`${task.id}: failed to schedule revision rerun: ${errorMessage}`);
62694
- await this.store.logEntry(
62695
- task.id,
62696
- "Workflow revision requested \u2014 executor ready for fresh execution"
62697
- );
62698
- }
62699
- }, 0);
62963
+ this.scheduleWorkflowRerun(
62964
+ task.id,
62965
+ worktreePath,
62966
+ `${task.id}: revision rerun scheduled \u2014 moved to todo then in-progress`
62967
+ );
62700
62968
  }
62701
62969
  /**
62702
62970
  * Re-open the last non-pending step so a revision/failure handler gives the
@@ -62783,6 +63051,7 @@ ${feedback}
62783
63051
  * @returns true if a retry was scheduled, false if retries are exhausted
62784
63052
  */
62785
63053
  async handleWorkflowStepFailure(task, worktreePath, failureFeedback, stepName) {
63054
+ this.clearCompletedTaskWatchdog(task.id);
62786
63055
  const currentRetries = task.workflowStepRetries ?? 0;
62787
63056
  if (currentRetries >= MAX_WORKFLOW_STEP_RETRIES) {
62788
63057
  executorLog.warn(`${task.id}: workflow step "${stepName}" failed \u2014 retries exhausted (${MAX_WORKFLOW_STEP_RETRIES}/${MAX_WORKFLOW_STEP_RETRIES})`);
@@ -62801,21 +63070,11 @@ ${feedback}
62801
63070
  sessionFile: null
62802
63071
  });
62803
63072
  executorLog.log(`${task.id}: scheduling fresh execution after workflow step failure (retry ${retryCount}/${MAX_WORKFLOW_STEP_RETRIES})`);
62804
- setTimeout(async () => {
62805
- try {
62806
- await this.store.moveTask(task.id, "todo");
62807
- await this.store.updateTask(task.id, { worktree: worktreePath });
62808
- await this.store.moveTask(task.id, "in-progress");
62809
- executorLog.log(`${task.id}: workflow step retry scheduled \u2014 moved to todo then in-progress`);
62810
- } catch (err) {
62811
- const errorMessage = err instanceof Error ? err.message : String(err);
62812
- executorLog.error(`${task.id}: failed to schedule workflow step retry: ${errorMessage}`);
62813
- await this.store.logEntry(
62814
- task.id,
62815
- "Workflow step failed \u2014 executor ready for fresh execution"
62816
- );
62817
- }
62818
- }, 0);
63073
+ this.scheduleWorkflowRerun(
63074
+ task.id,
63075
+ worktreePath,
63076
+ `${task.id}: workflow step retry scheduled \u2014 moved to todo then in-progress`
63077
+ );
62819
63078
  return true;
62820
63079
  }
62821
63080
  /**
@@ -62825,6 +63084,7 @@ ${feedback}
62825
63084
  */
62826
63085
  async sendTaskBackForFix(task, worktreePath, failureFeedback, stepName, reason) {
62827
63086
  const taskId = task.id;
63087
+ this.clearCompletedTaskWatchdog(taskId);
62828
63088
  await this.store.addTaskComment(
62829
63089
  taskId,
62830
63090
  `${reason}. The failing workflow step was "${stepName}". Feedback:
@@ -62846,17 +63106,11 @@ Please fix the issues so the verification can pass on the next attempt.`,
62846
63106
  sessionFile: null,
62847
63107
  workflowStepRetries: 0
62848
63108
  });
62849
- setTimeout(async () => {
62850
- try {
62851
- await this.store.moveTask(taskId, "todo");
62852
- await this.store.updateTask(taskId, { worktree: worktreePath });
62853
- await this.store.moveTask(taskId, "in-progress");
62854
- executorLog.log(`${taskId}: sent back to in-progress for remediation`);
62855
- } catch (err) {
62856
- const errorMessage = err instanceof Error ? err.message : String(err);
62857
- executorLog.error(`${taskId}: failed to move back to in-progress: ${errorMessage}`);
62858
- }
62859
- }, 0);
63109
+ this.scheduleWorkflowRerun(
63110
+ taskId,
63111
+ worktreePath,
63112
+ `${taskId}: sent back to in-progress for remediation`
63113
+ );
62860
63114
  }
62861
63115
  /**
62862
63116
  * Inject or update the "Workflow Step Failure" section in PROMPT.md.
@@ -63407,7 +63661,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
63407
63661
  );
63408
63662
  }
63409
63663
  const delay2 = this.WORKTREE_RETRY_DELAYS[attempt] || 1e3;
63410
- await new Promise((resolve36) => setTimeout(resolve36, delay2));
63664
+ await new Promise((resolve39) => setTimeout(resolve39, delay2));
63411
63665
  }
63412
63666
  }
63413
63667
  throw new Error("Unexpected exit from worktree creation retry loop");
@@ -72731,13 +72985,13 @@ var init_plugin_runner = __esm({
72731
72985
  * Returns the result on success, throws on timeout.
72732
72986
  */
72733
72987
  withTimeout(promise, ms, timeoutMessage) {
72734
- return new Promise((resolve36, reject2) => {
72988
+ return new Promise((resolve39, reject2) => {
72735
72989
  const timer = setTimeout(() => {
72736
72990
  reject2(new Error(timeoutMessage));
72737
72991
  }, ms);
72738
72992
  promise.then((result) => {
72739
72993
  clearTimeout(timer);
72740
- resolve36(result);
72994
+ resolve39(result);
72741
72995
  }).catch((err) => {
72742
72996
  clearTimeout(timer);
72743
72997
  reject2(err);
@@ -73406,7 +73660,7 @@ var init_in_process_runtime = __esm({
73406
73660
  runtimeLog.log(
73407
73661
  `Waiting for ${metrics.inFlightTasks} in-flight tasks to complete...`
73408
73662
  );
73409
- await new Promise((resolve36) => setTimeout(resolve36, 1e3));
73663
+ await new Promise((resolve39) => setTimeout(resolve39, 1e3));
73410
73664
  }
73411
73665
  const finalMetrics = this.getMetrics();
73412
73666
  if (finalMetrics.inFlightTasks > 0) {
@@ -73803,13 +74057,13 @@ var init_ipc_host = __esm({
73803
74057
  }
73804
74058
  const id = generateCorrelationId();
73805
74059
  const message = { type, id, payload };
73806
- return new Promise((resolve36, reject2) => {
74060
+ return new Promise((resolve39, reject2) => {
73807
74061
  const timeout2 = setTimeout(() => {
73808
74062
  this.pendingCommands.delete(id);
73809
74063
  reject2(new Error(`Command ${type} timed out after ${timeoutMs ?? this.commandTimeoutMs}ms`));
73810
74064
  }, timeoutMs ?? this.commandTimeoutMs);
73811
74065
  this.pendingCommands.set(id, {
73812
- resolve: resolve36,
74066
+ resolve: resolve39,
73813
74067
  reject: reject2,
73814
74068
  timeout: timeout2,
73815
74069
  type
@@ -74618,8 +74872,8 @@ var init_remote_node_client = __esm({
74618
74872
  return error instanceof TypeError;
74619
74873
  }
74620
74874
  async sleep(ms) {
74621
- await new Promise((resolve36) => {
74622
- setTimeout(resolve36, ms);
74875
+ await new Promise((resolve39) => {
74876
+ setTimeout(resolve39, ms);
74623
74877
  });
74624
74878
  }
74625
74879
  };
@@ -74883,14 +75137,14 @@ var init_remote_node_runtime = __esm({
74883
75137
  return error instanceof Error ? error : new Error(String(error));
74884
75138
  }
74885
75139
  async sleep(ms, signal) {
74886
- await new Promise((resolve36) => {
75140
+ await new Promise((resolve39) => {
74887
75141
  const timeout2 = setTimeout(() => {
74888
75142
  cleanup();
74889
- resolve36();
75143
+ resolve39();
74890
75144
  }, ms);
74891
75145
  const onAbort = () => {
74892
75146
  cleanup();
74893
- resolve36();
75147
+ resolve39();
74894
75148
  };
74895
75149
  const cleanup = () => {
74896
75150
  clearTimeout(timeout2);
@@ -75777,10 +76031,10 @@ var init_tunnel_process_manager = __esm({
75777
76031
  lastError: null
75778
76032
  });
75779
76033
  this.emitLog("info", "manager", `Stopping ${currentHandle.provider} tunnel (pid=${currentHandle.child.pid ?? "n/a"})`);
75780
- this.activeStopPromise = new Promise((resolve36) => {
76034
+ this.activeStopPromise = new Promise((resolve39) => {
75781
76035
  const onClose = () => {
75782
76036
  currentHandle.child.removeListener("close", onClose);
75783
- resolve36();
76037
+ resolve39();
75784
76038
  };
75785
76039
  currentHandle.child.once("close", onClose);
75786
76040
  killManagedProcess(currentHandle.child, "SIGTERM");
@@ -76336,12 +76590,12 @@ ${detail}`
76336
76590
  */
76337
76591
  async onMerge(taskId) {
76338
76592
  if (this.mergeActive.has(taskId)) {
76339
- return new Promise((resolve36, reject2) => {
76340
- this.manualMergeResolvers.set(taskId, { resolve: resolve36, reject: reject2 });
76593
+ return new Promise((resolve39, reject2) => {
76594
+ this.manualMergeResolvers.set(taskId, { resolve: resolve39, reject: reject2 });
76341
76595
  });
76342
76596
  }
76343
- return new Promise((resolve36, reject2) => {
76344
- this.manualMergeResolvers.set(taskId, { resolve: resolve36, reject: reject2 });
76597
+ return new Promise((resolve39, reject2) => {
76598
+ this.manualMergeResolvers.set(taskId, { resolve: resolve39, reject: reject2 });
76345
76599
  this.internalEnqueueMerge(taskId);
76346
76600
  });
76347
76601
  }
@@ -82211,7 +82465,7 @@ function hermesProfileHome(profileName) {
82211
82465
  async function listHermesProfiles(opts) {
82212
82466
  const binary = resolveBinaryForSpawn(opts?.binaryPath ?? "hermes");
82213
82467
  const timeoutMs = opts?.timeoutMs ?? 5e3;
82214
- return new Promise((resolve36, reject2) => {
82468
+ return new Promise((resolve39, reject2) => {
82215
82469
  let settled = false;
82216
82470
  const child = spawn4(binary, ["profile", "list"], {
82217
82471
  stdio: ["ignore", "pipe", "pipe"],
@@ -82254,7 +82508,7 @@ async function listHermesProfiles(opts) {
82254
82508
  ${combined}`));
82255
82509
  return;
82256
82510
  }
82257
- resolve36(parseProfileListOutput(stdout));
82511
+ resolve39(parseProfileListOutput(stdout));
82258
82512
  });
82259
82513
  });
82260
82514
  }
@@ -82331,7 +82585,7 @@ function buildHermesArgs(prompt, settings, resumeSessionId) {
82331
82585
  async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
82332
82586
  const args = buildHermesArgs(prompt, settings, resumeSessionId);
82333
82587
  const binary = resolveBinaryForSpawn(settings.binaryPath);
82334
- return new Promise((resolve36, reject2) => {
82588
+ return new Promise((resolve39, reject2) => {
82335
82589
  let settled = false;
82336
82590
  const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
82337
82591
  if (settings.profile) {
@@ -82399,7 +82653,7 @@ ${combined}`));
82399
82653
  return;
82400
82654
  }
82401
82655
  try {
82402
- resolve36(parseHermesOutput(stdout, stderr));
82656
+ resolve39(parseHermesOutput(stdout, stderr));
82403
82657
  } catch (parseErr) {
82404
82658
  reject2(parseErr);
82405
82659
  }
@@ -82717,7 +82971,7 @@ async function promptCli(session, message, config, callbacks, signal) {
82717
82971
  const args = buildOpenClawArgs(config, session.sessionId, message);
82718
82972
  const cb = { ...session.callbacks, ...callbacks };
82719
82973
  cb.onToolStart?.("openclaw.agent", { sessionId: session.sessionId });
82720
- return new Promise((resolve36, reject2) => {
82974
+ return new Promise((resolve39, reject2) => {
82721
82975
  let settled = false;
82722
82976
  const child = spawn6(config.binaryPath, args, {
82723
82977
  stdio: ["ignore", "pipe", "pipe"]
@@ -82810,7 +83064,7 @@ async function promptCli(session, message, config, callbacks, signal) {
82810
83064
  ...metaError ? { error: metaError } : {},
82811
83065
  ...errorText.length > 0 ? { toolErrors: errorText } : {}
82812
83066
  });
82813
- resolve36();
83067
+ resolve39();
82814
83068
  });
82815
83069
  });
82816
83070
  }
@@ -83552,10 +83806,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
83552
83806
  nextRecoveryAt: null
83553
83807
  });
83554
83808
  if (retrySpecification) {
83555
- const { rm: rm5 } = await import("node:fs/promises");
83809
+ const { rm: rm6 } = await import("node:fs/promises");
83556
83810
  const { join: join65 } = await import("node:path");
83557
83811
  const promptPath = join65(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
83558
- await rm5(promptPath, { force: true });
83812
+ await rm6(promptPath, { force: true });
83559
83813
  await scopedStore.logEntry(req.params.id, "Retry requested from dashboard (planning retry budget reset)");
83560
83814
  const updated2 = await scopedStore.getTask(req.params.id);
83561
83815
  res.json(updated2);
@@ -83975,10 +84229,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
83975
84229
  }
83976
84230
  await scopedStore.logEntry(task.id, "Plan rejected by user", "Specification will be regenerated");
83977
84231
  await scopedStore.updateTask(task.id, { status: void 0 });
83978
- const { rm: rm5 } = await import("node:fs/promises");
84232
+ const { rm: rm6 } = await import("node:fs/promises");
83979
84233
  const { join: join65 } = await import("node:path");
83980
84234
  const promptPath = join65(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
83981
- await rm5(promptPath, { force: true });
84235
+ await rm6(promptPath, { force: true });
83982
84236
  const updated = await scopedStore.getTask(task.id);
83983
84237
  res.json(updated);
83984
84238
  } catch (err) {
@@ -84246,10 +84500,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
84246
84500
  const task = await scopedStore.getTask(req.params.id);
84247
84501
  if (task.column === "triage") {
84248
84502
  await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
84249
- const { rm: rm6 } = await import("node:fs/promises");
84503
+ const { rm: rm7 } = await import("node:fs/promises");
84250
84504
  const { join: join66 } = await import("node:path");
84251
84505
  const promptPath2 = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
84252
- await rm6(promptPath2, { force: true });
84506
+ await rm7(promptPath2, { force: true });
84253
84507
  await scopedStore.updateTask(task.id, { status: "needs-replan" });
84254
84508
  const updated2 = await scopedStore.getTask(task.id);
84255
84509
  res.json(updated2);
@@ -84263,10 +84517,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
84263
84517
  }
84264
84518
  await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
84265
84519
  const updated = await scopedStore.moveTask(task.id, "triage");
84266
- const { rm: rm5 } = await import("node:fs/promises");
84520
+ const { rm: rm6 } = await import("node:fs/promises");
84267
84521
  const { join: join65 } = await import("node:path");
84268
84522
  const promptPath = join65(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
84269
- await rm5(promptPath, { force: true });
84523
+ await rm6(promptPath, { force: true });
84270
84524
  await scopedStore.updateTask(task.id, { status: "needs-replan" });
84271
84525
  res.json(updated);
84272
84526
  } catch (err) {
@@ -84284,10 +84538,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
84284
84538
  const task = await scopedStore.getTask(req.params.id);
84285
84539
  if (task.column === "triage") {
84286
84540
  await scopedStore.logEntry(task.id, "Specification rebuild requested by user");
84287
- const { rm: rm6 } = await import("node:fs/promises");
84541
+ const { rm: rm7 } = await import("node:fs/promises");
84288
84542
  const { join: join66 } = await import("node:path");
84289
84543
  const promptPath2 = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
84290
- await rm6(promptPath2, { force: true });
84544
+ await rm7(promptPath2, { force: true });
84291
84545
  await scopedStore.updateTask(task.id, { status: "needs-replan" });
84292
84546
  const updated2 = await scopedStore.getTask(task.id);
84293
84547
  res.json(updated2);
@@ -84299,10 +84553,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
84299
84553
  }
84300
84554
  await scopedStore.logEntry(task.id, "Specification rebuild requested by user");
84301
84555
  const updated = await scopedStore.moveTask(task.id, "triage");
84302
- const { rm: rm5 } = await import("node:fs/promises");
84556
+ const { rm: rm6 } = await import("node:fs/promises");
84303
84557
  const { join: join65 } = await import("node:path");
84304
84558
  const promptPath = join65(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
84305
- await rm5(promptPath, { force: true });
84559
+ await rm6(promptPath, { force: true });
84306
84560
  await scopedStore.updateTask(task.id, { status: "needs-replan" });
84307
84561
  res.json(updated);
84308
84562
  } catch (err) {
@@ -85582,6 +85836,11 @@ async function ensureEngineReady5() {
85582
85836
  } catch {
85583
85837
  }
85584
85838
  }
85839
+ function formatAttachmentSize(size) {
85840
+ if (size < 1024) return `${size}B`;
85841
+ if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}KB`;
85842
+ return `${(size / (1024 * 1024)).toFixed(1)}MB`;
85843
+ }
85585
85844
  function validateFilePath(basePath, filePath) {
85586
85845
  if (filePath.includes("\0")) {
85587
85846
  throw new Error(`Access denied: Invalid characters in path`);
@@ -85911,7 +86170,7 @@ var init_chat = __esm({
85911
86170
  * @param modelProvider - Optional model provider override
85912
86171
  * @param modelId - Optional model ID override
85913
86172
  */
85914
- async sendMessage(sessionId, content, modelProvider, modelId) {
86173
+ async sendMessage(sessionId, content, modelProvider, modelId, attachments) {
85915
86174
  const abortController = new AbortController();
85916
86175
  this.activeGenerations.set(sessionId, { abortController });
85917
86176
  const session = this.chatStore.getSession(sessionId);
@@ -85935,7 +86194,8 @@ var init_chat = __esm({
85935
86194
  this.chatStore.addMessage(sessionId, {
85936
86195
  role: "user",
85937
86196
  content,
85938
- metadata: mentions.length > 0 ? { mentions } : void 0
86197
+ metadata: mentions.length > 0 ? { mentions } : void 0,
86198
+ attachments
85939
86199
  });
85940
86200
  } catch (err) {
85941
86201
  chatStreamManager.broadcast(sessionId, {
@@ -86012,6 +86272,7 @@ ${mentionContext}`;
86012
86272
  (message) => message.role === "user" || message.role === "assistant"
86013
86273
  );
86014
86274
  const resolvedContent = await resolveFileReferences(content, this.rootDir);
86275
+ const attachmentSummary = attachments && attachments.length > 0 ? `[User attached: ${attachments.map((attachment) => `${attachment.originalName} (${attachment.mimeType}, ${formatAttachmentSize(attachment.size)})`).join(", ")}]` : "";
86015
86276
  const promptContent = conversationMessages.length > 0 ? [
86016
86277
  "## Previous Conversation",
86017
86278
  "",
@@ -86022,8 +86283,9 @@ ${mentionContext}`;
86022
86283
  "",
86023
86284
  "## Current Message",
86024
86285
  "",
86286
+ attachmentSummary,
86025
86287
  resolvedContent
86026
- ].join("\n") : resolvedContent;
86288
+ ].filter(Boolean).join("\n") : [attachmentSummary, resolvedContent].filter(Boolean).join("\n\n");
86027
86289
  agentResult = await createFnAgent8({
86028
86290
  cwd: this.rootDir,
86029
86291
  systemPrompt,
@@ -86100,7 +86362,7 @@ ${mentionContext}`;
86100
86362
  });
86101
86363
  chatStreamManager.broadcast(sessionId, {
86102
86364
  type: "done",
86103
- data: { messageId: assistantMessage.id }
86365
+ data: { messageId: assistantMessage.id, attachments }
86104
86366
  });
86105
86367
  } catch (err) {
86106
86368
  if (abortController.signal.aborted) {
@@ -86166,9 +86428,36 @@ ${mentionContext}`;
86166
86428
  });
86167
86429
 
86168
86430
  // ../dashboard/src/routes/register-chat-routes.ts
86431
+ import { randomUUID as randomUUID15 } from "node:crypto";
86432
+ import { createReadStream as createReadStream2 } from "node:fs";
86433
+ import { mkdir as mkdir12, rm as rm2, writeFile as writeFile12 } from "node:fs/promises";
86434
+ import { basename as basename9, join as join37, resolve as resolve17 } from "node:path";
86435
+ function resolveAttachmentPath(rootDir, sessionId, filename) {
86436
+ const sessionDir = resolve17(rootDir, ".fusion", "chat-attachments", sessionId);
86437
+ const safeName = basename9(filename);
86438
+ const filePath = resolve17(sessionDir, safeName);
86439
+ if (!filePath.startsWith(`${sessionDir}/`) && filePath !== sessionDir) {
86440
+ throw badRequest("Invalid attachment path");
86441
+ }
86442
+ return { sessionDir, filePath };
86443
+ }
86169
86444
  function registerChatRoutes(ctx, deps) {
86170
86445
  const { router, options, getProjectContext: getProjectContext3, chatLogger, rethrowAsApiError: rethrowAsApiError7 } = ctx;
86171
- const { parseLastEventId: parseLastEventId3, validateOptionalModelField: validateOptionalModelField2 } = deps;
86446
+ const { parseLastEventId: parseLastEventId3, validateOptionalModelField: validateOptionalModelField2, upload: upload2 } = deps;
86447
+ const uploadChatAttachment = (req, res, next) => {
86448
+ upload2.single("file")(req, res, (err) => {
86449
+ if (!err) {
86450
+ next();
86451
+ return;
86452
+ }
86453
+ const multerError = err;
86454
+ if (multerError?.code === "LIMIT_FILE_SIZE") {
86455
+ next(badRequest(`File too large. Maximum: ${CHAT_MAX_ATTACHMENT_SIZE} bytes (5MB)`));
86456
+ return;
86457
+ }
86458
+ next(err);
86459
+ });
86460
+ };
86172
86461
  router.get("/chat/sessions", rateLimit(RATE_LIMITS.api), async (req, res) => {
86173
86462
  try {
86174
86463
  const chatStore = options?.chatStore;
@@ -86368,6 +86657,84 @@ function registerChatRoutes(ctx, deps) {
86368
86657
  rethrowAsApiError7(err, "Failed to get chat messages");
86369
86658
  }
86370
86659
  });
86660
+ router.post("/chat/sessions/:id/attachments", rateLimit(RATE_LIMITS.mutation), uploadChatAttachment, async (req, res) => {
86661
+ try {
86662
+ const chatStore = options?.chatStore;
86663
+ if (!chatStore) {
86664
+ throw internalError("Chat store not available");
86665
+ }
86666
+ const sessionId = String(req.params.id);
86667
+ const session = chatStore.getSession(sessionId);
86668
+ if (!session) {
86669
+ throw notFound(`Chat session ${sessionId} not found`);
86670
+ }
86671
+ const file = req.file;
86672
+ if (!file) {
86673
+ throw badRequest("file is required");
86674
+ }
86675
+ if (!CHAT_ALLOWED_MIME_TYPES.has(file.mimetype)) {
86676
+ throw badRequest(`Invalid mime type '${file.mimetype}'`);
86677
+ }
86678
+ if (file.size > CHAT_MAX_ATTACHMENT_SIZE) {
86679
+ throw badRequest(`File too large (${file.size} bytes). Maximum: ${CHAT_MAX_ATTACHMENT_SIZE} bytes (5MB)`);
86680
+ }
86681
+ const { store: scopedStore } = await getProjectContext3(req);
86682
+ const rootDir = scopedStore.getRootDir();
86683
+ const sessionDir = resolve17(rootDir, ".fusion", "chat-attachments", sessionId);
86684
+ await mkdir12(sessionDir, { recursive: true });
86685
+ const sanitizedFilename = (file.originalname || "attachment").replace(/[^a-zA-Z0-9._-]/g, "_");
86686
+ const filename = `${Date.now()}-${sanitizedFilename}`;
86687
+ const filePath = join37(sessionDir, filename);
86688
+ await writeFile12(filePath, file.buffer);
86689
+ const attachment = {
86690
+ id: `att-${randomUUID15().slice(0, 8)}`,
86691
+ filename,
86692
+ originalName: file.originalname,
86693
+ mimeType: file.mimetype,
86694
+ size: file.size,
86695
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
86696
+ };
86697
+ res.status(201).json({ attachment });
86698
+ } catch (err) {
86699
+ if (err instanceof ApiError) throw err;
86700
+ rethrowAsApiError7(err, "Failed to upload chat attachment");
86701
+ }
86702
+ });
86703
+ router.get("/chat/sessions/:id/attachments/:filename", async (req, res) => {
86704
+ try {
86705
+ const { store: scopedStore } = await getProjectContext3(req);
86706
+ const rootDir = scopedStore.getRootDir();
86707
+ const { filePath } = resolveAttachmentPath(rootDir, String(req.params.id), String(req.params.filename));
86708
+ const stream = createReadStream2(filePath);
86709
+ stream.on("error", () => {
86710
+ if (!res.headersSent) {
86711
+ res.status(404).json({ error: "Attachment not found" });
86712
+ } else {
86713
+ res.end();
86714
+ }
86715
+ });
86716
+ res.setHeader("Content-Type", "application/octet-stream");
86717
+ stream.pipe(res);
86718
+ } catch (err) {
86719
+ if (err instanceof ApiError) throw err;
86720
+ rethrowAsApiError7(err, "Failed to fetch chat attachment");
86721
+ }
86722
+ });
86723
+ router.delete("/chat/sessions/:id/attachments/:filename", rateLimit(RATE_LIMITS.mutation), async (req, res) => {
86724
+ try {
86725
+ const { store: scopedStore } = await getProjectContext3(req);
86726
+ const rootDir = scopedStore.getRootDir();
86727
+ const { filePath } = resolveAttachmentPath(rootDir, String(req.params.id), String(req.params.filename));
86728
+ await rm2(filePath);
86729
+ res.json({ success: true });
86730
+ } catch (err) {
86731
+ if (err?.code === "ENOENT") {
86732
+ throw notFound("Attachment not found");
86733
+ }
86734
+ if (err instanceof ApiError) throw err;
86735
+ rethrowAsApiError7(err, "Failed to delete chat attachment");
86736
+ }
86737
+ });
86371
86738
  router.post("/chat/sessions/:id/messages", rateLimit(RATE_LIMITS.sse), async (req, res) => {
86372
86739
  try {
86373
86740
  const chatStore = options?.chatStore;
@@ -86375,7 +86742,7 @@ function registerChatRoutes(ctx, deps) {
86375
86742
  if (!chatStore || !chatManager) {
86376
86743
  throw internalError("Chat store or manager not available");
86377
86744
  }
86378
- const { content, modelProvider, modelId } = req.body;
86745
+ const { content, modelProvider, modelId, attachments } = req.body;
86379
86746
  const sessionId = String(req.params.id);
86380
86747
  if (!content || typeof content !== "string" || !content.trim()) {
86381
86748
  throw badRequest("content is required and must be a non-empty string");
@@ -86449,7 +86816,8 @@ function registerChatRoutes(ctx, deps) {
86449
86816
  sessionId,
86450
86817
  content.trim(),
86451
86818
  normalizedProvider,
86452
- normalizedModelId
86819
+ normalizedModelId,
86820
+ Array.isArray(attachments) ? attachments : void 0
86453
86821
  ).catch((err) => {
86454
86822
  chatLogger.error("Error in sendMessage", {
86455
86823
  error: err.message
@@ -86518,6 +86886,9 @@ function registerChatRoutes(ctx, deps) {
86518
86886
  "PATCH /chat/sessions/:id",
86519
86887
  "DELETE /chat/sessions/:id",
86520
86888
  "GET /chat/sessions/:id/messages",
86889
+ "POST /chat/sessions/:id/attachments",
86890
+ "GET /chat/sessions/:id/attachments/:filename",
86891
+ "DELETE /chat/sessions/:id/attachments/:filename",
86521
86892
  "POST /chat/sessions/:id/messages",
86522
86893
  "POST /chat/sessions/:id/cancel",
86523
86894
  "DELETE /chat/sessions/:id/messages/:messageId"
@@ -86525,12 +86896,26 @@ function registerChatRoutes(ctx, deps) {
86525
86896
  chatLogger.info("routes registered", { chatRoutes });
86526
86897
  }
86527
86898
  }
86899
+ var CHAT_ALLOWED_MIME_TYPES, CHAT_MAX_ATTACHMENT_SIZE;
86528
86900
  var init_register_chat_routes = __esm({
86529
86901
  "../dashboard/src/routes/register-chat-routes.ts"() {
86530
86902
  "use strict";
86531
86903
  init_api_error();
86532
86904
  init_rate_limit();
86533
86905
  init_sse_buffer();
86906
+ CHAT_ALLOWED_MIME_TYPES = /* @__PURE__ */ new Set([
86907
+ "image/png",
86908
+ "image/jpeg",
86909
+ "image/gif",
86910
+ "image/webp",
86911
+ "text/plain",
86912
+ "application/json",
86913
+ "text/yaml",
86914
+ "text/x-toml",
86915
+ "text/csv",
86916
+ "application/xml"
86917
+ ]);
86918
+ CHAT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
86534
86919
  }
86535
86920
  });
86536
86921
 
@@ -87879,7 +88264,7 @@ import * as os3 from "os";
87879
88264
  import * as path2 from "path";
87880
88265
  import * as fs from "node:fs";
87881
88266
  import { createRequire as createRequire3 } from "node:module";
87882
- import { join as join37, dirname as dirname10 } from "node:path";
88267
+ import { join as join38, dirname as dirname10 } from "node:path";
87883
88268
  function getNativePrebuildName() {
87884
88269
  const platform3 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
87885
88270
  const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
@@ -87889,12 +88274,12 @@ function findInstalledNodePtyNativeDir() {
87889
88274
  try {
87890
88275
  const packageJsonPath = require2.resolve("node-pty/package.json");
87891
88276
  const pkgRoot = dirname10(packageJsonPath);
87892
- const releaseDir = join37(pkgRoot, "build", "Release");
87893
- if (fs.existsSync(join37(releaseDir, "pty.node"))) {
88277
+ const releaseDir = join38(pkgRoot, "build", "Release");
88278
+ if (fs.existsSync(join38(releaseDir, "pty.node"))) {
87894
88279
  return releaseDir;
87895
88280
  }
87896
- const prebuildDir = join37(pkgRoot, "prebuilds", getNativePrebuildName());
87897
- if (fs.existsSync(join37(prebuildDir, "pty.node"))) {
88281
+ const prebuildDir = join38(pkgRoot, "prebuilds", getNativePrebuildName());
88282
+ if (fs.existsSync(join38(prebuildDir, "pty.node"))) {
87898
88283
  return prebuildDir;
87899
88284
  }
87900
88285
  return null;
@@ -87920,8 +88305,8 @@ function ensureNodePtyNativePermissions() {
87920
88305
  candidateDirs.add(installedNativeDir);
87921
88306
  }
87922
88307
  for (const nativeDir of candidateDirs) {
87923
- const helperPath = join37(nativeDir, "spawn-helper");
87924
- const nativeModulePath = join37(nativeDir, "pty.node");
88308
+ const helperPath = join38(nativeDir, "spawn-helper");
88309
+ const nativeModulePath = join38(nativeDir, "pty.node");
87925
88310
  try {
87926
88311
  fs.chmodSync(helperPath, 493);
87927
88312
  } catch {
@@ -87939,14 +88324,14 @@ function ensureNodePtyNativePermissions() {
87939
88324
  function findStagedNativeDir() {
87940
88325
  const prebuildName = getNativePrebuildName();
87941
88326
  if (process.env.FUSION_RUNTIME_DIR) {
87942
- const envPath = join37(process.env.FUSION_RUNTIME_DIR, prebuildName);
87943
- if (fs.existsSync(join37(envPath, "pty.node"))) {
88327
+ const envPath = join38(process.env.FUSION_RUNTIME_DIR, prebuildName);
88328
+ if (fs.existsSync(join38(envPath, "pty.node"))) {
87944
88329
  return envPath;
87945
88330
  }
87946
88331
  }
87947
88332
  const execDir = dirname10(process.execPath);
87948
- const nextToBinary = join37(execDir, "runtime", prebuildName);
87949
- if (fs.existsSync(join37(nextToBinary, "pty.node"))) {
88333
+ const nextToBinary = join38(execDir, "runtime", prebuildName);
88334
+ if (fs.existsSync(join38(nextToBinary, "pty.node"))) {
87950
88335
  return nextToBinary;
87951
88336
  }
87952
88337
  return null;
@@ -87966,7 +88351,7 @@ async function loadPtyModule() {
87966
88351
  process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
87967
88352
  }
87968
88353
  process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
87969
- const nativePath = join37(nativeDir, "pty.node");
88354
+ const nativePath = join38(nativeDir, "pty.node");
87970
88355
  if (fs.existsSync(nativePath)) {
87971
88356
  try {
87972
88357
  const nativeModule = { exports: {} };
@@ -88943,7 +89328,7 @@ var init_register_messaging_scripts = __esm({
88943
89328
 
88944
89329
  // ../dashboard/src/github.ts
88945
89330
  function delay(ms) {
88946
- return new Promise((resolve36) => setTimeout(resolve36, ms));
89331
+ return new Promise((resolve39) => setTimeout(resolve39, ms));
88947
89332
  }
88948
89333
  function normalizeCheckState(state) {
88949
89334
  switch ((state ?? "").toLowerCase()) {
@@ -93302,7 +93687,7 @@ var init_register_git_github = __esm({
93302
93687
 
93303
93688
  // ../dashboard/src/terminal.ts
93304
93689
  import { spawn as spawn8 } from "node:child_process";
93305
- import { randomUUID as randomUUID15 } from "node:crypto";
93690
+ import { randomUUID as randomUUID16 } from "node:crypto";
93306
93691
  import { EventEmitter as EventEmitter31 } from "node:events";
93307
93692
  function extractBaseCommand(command) {
93308
93693
  let trimmed = command.trim();
@@ -93462,7 +93847,7 @@ var init_terminal = __esm({
93462
93847
  if (!validation.valid) {
93463
93848
  return { sessionId: "", error: validation.error };
93464
93849
  }
93465
- const sessionId = randomUUID15();
93850
+ const sessionId = randomUUID16();
93466
93851
  const childProcess = spawn8(command, [], {
93467
93852
  cwd,
93468
93853
  shell: true,
@@ -93587,20 +93972,20 @@ var init_terminal = __esm({
93587
93972
  });
93588
93973
 
93589
93974
  // ../dashboard/src/file-service.ts
93590
- import { join as join38, resolve as resolve18, relative as relative9, dirname as dirname11, basename as basename10 } from "node:path";
93591
- import { readdir as readdir8, readFile as fsReadFile, writeFile as fsWriteFile, stat as stat7, copyFile as fsCopyFile, rename as fsRename, rm as fsRm, mkdir as mkdir12, access as access4 } from "node:fs/promises";
93975
+ import { join as join39, resolve as resolve19, relative as relative9, dirname as dirname11, basename as basename11 } from "node:path";
93976
+ import { readdir as readdir8, readFile as fsReadFile, writeFile as fsWriteFile, stat as stat7, copyFile as fsCopyFile, rename as fsRename, rm as fsRm, mkdir as mkdir13, access as access4 } from "node:fs/promises";
93592
93977
  async function getTaskBasePath(store, taskId) {
93593
93978
  try {
93594
93979
  const task = await store.getTask(taskId);
93595
93980
  if (task.worktree) {
93596
93981
  try {
93597
93982
  await access4(task.worktree);
93598
- return resolve18(task.worktree);
93983
+ return resolve19(task.worktree);
93599
93984
  } catch {
93600
93985
  }
93601
93986
  }
93602
93987
  const rootDir = store.getRootDir();
93603
- return resolve18(join38(rootDir, ".fusion", "tasks", taskId));
93988
+ return resolve19(join39(rootDir, ".fusion", "tasks", taskId));
93604
93989
  } catch (err) {
93605
93990
  const error = err;
93606
93991
  if (error.code === "ENOENT" || error.message && error.message.includes("not found")) {
@@ -93610,7 +93995,7 @@ async function getTaskBasePath(store, taskId) {
93610
93995
  }
93611
93996
  }
93612
93997
  function getProjectBasePath(store) {
93613
- return resolve18(store.getRootDir());
93998
+ return resolve19(store.getRootDir());
93614
93999
  }
93615
94000
  async function getWorkspaceBasePath(store, workspace) {
93616
94001
  if (workspace === "project") {
@@ -93626,8 +94011,8 @@ function validatePath(basePath, filePath) {
93626
94011
  if (decodedPath.startsWith("/") || decodedPath.match(/^[a-zA-Z]:/)) {
93627
94012
  throw new FileServiceError(`Access denied: Absolute paths not allowed`, "EINVAL");
93628
94013
  }
93629
- const resolvedBase = resolve18(basePath);
93630
- const resolvedPath = resolve18(join38(resolvedBase, decodedPath));
94014
+ const resolvedBase = resolve19(basePath);
94015
+ const resolvedPath = resolve19(join39(resolvedBase, decodedPath));
93631
94016
  const relativePath = relative9(resolvedBase, resolvedPath);
93632
94017
  if (relativePath.startsWith("..") || relativePath.startsWith("../") || relativePath === "..") {
93633
94018
  throw new FileServiceError(`Access denied: Path traversal detected`, "EINVAL");
@@ -93656,7 +94041,7 @@ async function listFilesForBasePath(basePath, subPath) {
93656
94041
  const entries = await readdir8(targetPath, { withFileTypes: true });
93657
94042
  const fileNodes = [];
93658
94043
  for (const entry of entries) {
93659
- const entryPath = join38(targetPath, entry.name);
94044
+ const entryPath = join39(targetPath, entry.name);
93660
94045
  const entryStats = await stat7(entryPath);
93661
94046
  fileNodes.push({
93662
94047
  name: entry.name,
@@ -93786,7 +94171,7 @@ async function readFile18(store, taskId, filePath) {
93786
94171
  const taskBase = await getTaskBasePath(store, taskId);
93787
94172
  return readFileForBasePath(taskBase, filePath);
93788
94173
  }
93789
- async function writeFile12(store, taskId, filePath, content) {
94174
+ async function writeFile13(store, taskId, filePath, content) {
93790
94175
  const taskBase = await getTaskBasePath(store, taskId);
93791
94176
  return writeFileForBasePath(taskBase, filePath, content);
93792
94177
  }
@@ -93805,7 +94190,7 @@ async function writeWorkspaceFile(store, workspace, filePath, content) {
93805
94190
  function validateSourceAndDestination(basePath, sourcePath, destinationPath) {
93806
94191
  const resolvedSource = validatePath(basePath, sourcePath);
93807
94192
  const resolvedDest = validatePath(basePath, destinationPath);
93808
- const sourceRelative = relative9(resolve18(basePath), resolvedSource);
94193
+ const sourceRelative = relative9(resolve19(basePath), resolvedSource);
93809
94194
  if (!sourceRelative || sourceRelative === "." || sourceRelative === "") {
93810
94195
  throw new FileServiceError("Cannot operate on workspace root directory", "EINVAL");
93811
94196
  }
@@ -93929,7 +94314,7 @@ async function deleteWorkspaceFile(store, workspace, filePath) {
93929
94314
  }
93930
94315
  const workspaceBase = await getWorkspaceBasePath(store, workspace);
93931
94316
  const resolvedPath = validatePath(workspaceBase, filePath);
93932
- const relativePath = relative9(resolve18(workspaceBase), resolvedPath);
94317
+ const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
93933
94318
  if (!relativePath || relativePath === "." || relativePath === "") {
93934
94319
  throw new FileServiceError("Cannot delete workspace root directory", "EINVAL");
93935
94320
  }
@@ -93970,7 +94355,7 @@ async function renameWorkspaceFile(store, workspace, filePath, newName) {
93970
94355
  }
93971
94356
  const workspaceBase = await getWorkspaceBasePath(store, workspace);
93972
94357
  const resolvedPath = validatePath(workspaceBase, filePath);
93973
- const relativePath = relative9(resolve18(workspaceBase), resolvedPath);
94358
+ const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
93974
94359
  if (!relativePath || relativePath === "." || relativePath === "") {
93975
94360
  throw new FileServiceError("Cannot rename workspace root directory", "EINVAL");
93976
94361
  }
@@ -93983,12 +94368,12 @@ async function renameWorkspaceFile(store, workspace, filePath, newName) {
93983
94368
  }
93984
94369
  throw err;
93985
94370
  }
93986
- const destPath = join38(dirname11(resolvedPath), newName);
93987
- const destRelative = relative9(resolve18(workspaceBase), destPath);
94371
+ const destPath = join39(dirname11(resolvedPath), newName);
94372
+ const destRelative = relative9(resolve19(workspaceBase), destPath);
93988
94373
  if (destRelative.startsWith("..") || destRelative.startsWith("../") || destRelative === "..") {
93989
94374
  throw new FileServiceError("Destination would be outside workspace", "EINVAL");
93990
94375
  }
93991
- if (!destPath.startsWith(resolve18(workspaceBase))) {
94376
+ if (!destPath.startsWith(resolve19(workspaceBase))) {
93992
94377
  throw new FileServiceError("Destination would be outside workspace", "EINVAL");
93993
94378
  }
93994
94379
  try {
@@ -94017,7 +94402,7 @@ async function getWorkspaceFileForDownload(store, workspace, filePath) {
94017
94402
  }
94018
94403
  const workspaceBase = await getWorkspaceBasePath(store, workspace);
94019
94404
  const resolvedPath = validatePath(workspaceBase, filePath);
94020
- const relativePath = relative9(resolve18(workspaceBase), resolvedPath);
94405
+ const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
94021
94406
  if (!relativePath || relativePath === "." || relativePath === "") {
94022
94407
  throw new FileServiceError("Cannot download workspace root", "EINVAL");
94023
94408
  }
@@ -94041,7 +94426,7 @@ async function getWorkspaceFileForDownload(store, workspace, filePath) {
94041
94426
  mtime: stats.mtime,
94042
94427
  isFile: true
94043
94428
  },
94044
- fileName: basename10(resolvedPath)
94429
+ fileName: basename11(resolvedPath)
94045
94430
  };
94046
94431
  }
94047
94432
  async function getWorkspaceFolderForZip(store, workspace, dirPath) {
@@ -94050,7 +94435,7 @@ async function getWorkspaceFolderForZip(store, workspace, dirPath) {
94050
94435
  }
94051
94436
  const workspaceBase = await getWorkspaceBasePath(store, workspace);
94052
94437
  const resolvedPath = validatePath(workspaceBase, dirPath);
94053
- const relativePath = relative9(resolve18(workspaceBase), resolvedPath);
94438
+ const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
94054
94439
  if (!relativePath || relativePath === "." || relativePath === "") {
94055
94440
  throw new FileServiceError("Cannot download workspace root as ZIP", "EINVAL");
94056
94441
  }
@@ -94069,14 +94454,14 @@ async function getWorkspaceFolderForZip(store, workspace, dirPath) {
94069
94454
  }
94070
94455
  return {
94071
94456
  absolutePath: resolvedPath,
94072
- dirName: basename10(resolvedPath)
94457
+ dirName: basename11(resolvedPath)
94073
94458
  };
94074
94459
  }
94075
94460
  function isHiddenPathSegment(name) {
94076
94461
  return name.startsWith(".");
94077
94462
  }
94078
94463
  async function walkDirForMarkdown(basePath, currentRelative, results, options) {
94079
- const currentPath = currentRelative ? join38(basePath, currentRelative) : basePath;
94464
+ const currentPath = currentRelative ? join39(basePath, currentRelative) : basePath;
94080
94465
  let entries;
94081
94466
  try {
94082
94467
  entries = await readdir8(currentPath, { withFileTypes: true });
@@ -94084,7 +94469,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
94084
94469
  return;
94085
94470
  }
94086
94471
  for (const entry of entries) {
94087
- const entryRelativePath = currentRelative ? join38(currentRelative, entry.name) : entry.name;
94472
+ const entryRelativePath = currentRelative ? join39(currentRelative, entry.name) : entry.name;
94088
94473
  if (entry.isDirectory()) {
94089
94474
  if (MARKDOWN_SCAN_EXCLUDED_DIRS.has(entry.name)) {
94090
94475
  continue;
@@ -94101,7 +94486,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
94101
94486
  if (!options.showHidden && isHiddenPathSegment(entry.name)) {
94102
94487
  continue;
94103
94488
  }
94104
- const fullPath = join38(basePath, entryRelativePath);
94489
+ const fullPath = join39(basePath, entryRelativePath);
94105
94490
  let fileStats;
94106
94491
  try {
94107
94492
  fileStats = await stat7(fullPath);
@@ -94151,7 +94536,7 @@ async function scanMarkdownFiles(store, options) {
94151
94536
  return;
94152
94537
  }
94153
94538
  for (const entry of entries) {
94154
- const entryRelativePath = relativeDir ? join38(relativeDir, entry.name) : entry.name;
94539
+ const entryRelativePath = relativeDir ? join39(relativeDir, entry.name) : entry.name;
94155
94540
  let shouldRecurse = entry.isDirectory();
94156
94541
  if (!shouldRecurse && typeof entry.isSymbolicLink === "function" && entry.isSymbolicLink()) {
94157
94542
  let symlinkPath;
@@ -94241,8 +94626,8 @@ async function searchWorkspaceFiles(store, workspace, query) {
94241
94626
  if (entry.isDirectory() && EXCLUDED_DIRS.has(entry.name)) {
94242
94627
  continue;
94243
94628
  }
94244
- const fullPath = join38(dir2, entry.name);
94245
- const relPath = join38(relativeDir, entry.name);
94629
+ const fullPath = join39(dir2, entry.name);
94630
+ const relPath = join39(relativeDir, entry.name);
94246
94631
  if (entry.isFile()) {
94247
94632
  if (entry.name.toLowerCase().includes(lowerQuery)) {
94248
94633
  results.push({
@@ -94260,11 +94645,11 @@ async function searchWorkspaceFiles(store, workspace, query) {
94260
94645
  return { files: results };
94261
94646
  }
94262
94647
  async function copyDirectoryRecursive(source, destination) {
94263
- await mkdir12(destination, { recursive: true });
94648
+ await mkdir13(destination, { recursive: true });
94264
94649
  const entries = await readdir8(source, { withFileTypes: true });
94265
94650
  for (const entry of entries) {
94266
- const sourcePath = join38(source, entry.name);
94267
- const destPath = join38(destination, entry.name);
94651
+ const sourcePath = join39(source, entry.name);
94652
+ const destPath = join39(destination, entry.name);
94268
94653
  if (entry.isDirectory()) {
94269
94654
  await copyDirectoryRecursive(sourcePath, destPath);
94270
94655
  } else {
@@ -95181,9 +95566,9 @@ var require_readdir_glob = __commonJS({
95181
95566
  var fs2 = __require("fs");
95182
95567
  var { EventEmitter: EventEmitter35 } = __require("events");
95183
95568
  var { Minimatch } = require_minimatch();
95184
- var { resolve: resolve36 } = __require("path");
95569
+ var { resolve: resolve39 } = __require("path");
95185
95570
  function readdir12(dir2, strict) {
95186
- return new Promise((resolve37, reject2) => {
95571
+ return new Promise((resolve40, reject2) => {
95187
95572
  fs2.readdir(dir2, { withFileTypes: true }, (err, files) => {
95188
95573
  if (err) {
95189
95574
  switch (err.code) {
@@ -95191,7 +95576,7 @@ var require_readdir_glob = __commonJS({
95191
95576
  if (strict) {
95192
95577
  reject2(err);
95193
95578
  } else {
95194
- resolve37([]);
95579
+ resolve40([]);
95195
95580
  }
95196
95581
  break;
95197
95582
  case "ENOTSUP":
@@ -95201,7 +95586,7 @@ var require_readdir_glob = __commonJS({
95201
95586
  case "ENAMETOOLONG":
95202
95587
  // Filename too long
95203
95588
  case "UNKNOWN":
95204
- resolve37([]);
95589
+ resolve40([]);
95205
95590
  break;
95206
95591
  case "ELOOP":
95207
95592
  // Too many levels of symbolic links
@@ -95210,30 +95595,30 @@ var require_readdir_glob = __commonJS({
95210
95595
  break;
95211
95596
  }
95212
95597
  } else {
95213
- resolve37(files);
95598
+ resolve40(files);
95214
95599
  }
95215
95600
  });
95216
95601
  });
95217
95602
  }
95218
95603
  function stat12(file, followSymlinks) {
95219
- return new Promise((resolve37, reject2) => {
95604
+ return new Promise((resolve40, reject2) => {
95220
95605
  const statFunc = followSymlinks ? fs2.stat : fs2.lstat;
95221
95606
  statFunc(file, (err, stats) => {
95222
95607
  if (err) {
95223
95608
  switch (err.code) {
95224
95609
  case "ENOENT":
95225
95610
  if (followSymlinks) {
95226
- resolve37(stat12(file, false));
95611
+ resolve40(stat12(file, false));
95227
95612
  } else {
95228
- resolve37(null);
95613
+ resolve40(null);
95229
95614
  }
95230
95615
  break;
95231
95616
  default:
95232
- resolve37(null);
95617
+ resolve40(null);
95233
95618
  break;
95234
95619
  }
95235
95620
  } else {
95236
- resolve37(stats);
95621
+ resolve40(stats);
95237
95622
  }
95238
95623
  });
95239
95624
  });
@@ -95323,7 +95708,7 @@ var require_readdir_glob = __commonJS({
95323
95708
  (skip) => new Minimatch(skip, { dot: true })
95324
95709
  );
95325
95710
  }
95326
- this.iterator = explore(resolve36(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
95711
+ this.iterator = explore(resolve39(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
95327
95712
  this.paused = false;
95328
95713
  this.inactive = false;
95329
95714
  this.aborted = false;
@@ -95577,10 +95962,10 @@ function awaitify(asyncFn, arity) {
95577
95962
  if (typeof args[arity - 1] === "function") {
95578
95963
  return asyncFn.apply(this, args);
95579
95964
  }
95580
- return new Promise((resolve36, reject2) => {
95965
+ return new Promise((resolve39, reject2) => {
95581
95966
  args[arity - 1] = (err, ...cbArgs) => {
95582
95967
  if (err) return reject2(err);
95583
- resolve36(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
95968
+ resolve39(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
95584
95969
  };
95585
95970
  asyncFn.apply(this, args);
95586
95971
  });
@@ -95762,13 +96147,13 @@ function mapSeries(coll, iteratee, callback) {
95762
96147
  return _asyncMap(eachOfSeries$1, coll, iteratee, callback);
95763
96148
  }
95764
96149
  function promiseCallback() {
95765
- let resolve36, reject2;
96150
+ let resolve39, reject2;
95766
96151
  function callback(err, ...args) {
95767
96152
  if (err) return reject2(err);
95768
- resolve36(args.length > 1 ? args : args[0]);
96153
+ resolve39(args.length > 1 ? args : args[0]);
95769
96154
  }
95770
96155
  callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
95771
- resolve36 = res, reject2 = rej;
96156
+ resolve39 = res, reject2 = rej;
95772
96157
  });
95773
96158
  return callback;
95774
96159
  }
@@ -96041,8 +96426,8 @@ function queue$1(worker, concurrency, payload) {
96041
96426
  });
96042
96427
  }
96043
96428
  if (rejectOnError || !callback) {
96044
- return new Promise((resolve36, reject2) => {
96045
- res = resolve36;
96429
+ return new Promise((resolve39, reject2) => {
96430
+ res = resolve39;
96046
96431
  rej = reject2;
96047
96432
  });
96048
96433
  }
@@ -96081,10 +96466,10 @@ function queue$1(worker, concurrency, payload) {
96081
96466
  }
96082
96467
  const eventMethod = (name) => (handler) => {
96083
96468
  if (!handler) {
96084
- return new Promise((resolve36, reject2) => {
96469
+ return new Promise((resolve39, reject2) => {
96085
96470
  once3(name, (err, data) => {
96086
96471
  if (err) return reject2(err);
96087
- resolve36(data);
96472
+ resolve39(data);
96088
96473
  });
96089
96474
  });
96090
96475
  }
@@ -97745,7 +98130,7 @@ var require_graceful_fs = __commonJS({
97745
98130
  function patch(fs3) {
97746
98131
  polyfills(fs3);
97747
98132
  fs3.gracefulify = patch;
97748
- fs3.createReadStream = createReadStream3;
98133
+ fs3.createReadStream = createReadStream4;
97749
98134
  fs3.createWriteStream = createWriteStream2;
97750
98135
  var fs$readFile = fs3.readFile;
97751
98136
  fs3.readFile = readFile24;
@@ -97765,8 +98150,8 @@ var require_graceful_fs = __commonJS({
97765
98150
  }
97766
98151
  }
97767
98152
  var fs$writeFile = fs3.writeFile;
97768
- fs3.writeFile = writeFile17;
97769
- function writeFile17(path5, data, options, cb) {
98153
+ fs3.writeFile = writeFile18;
98154
+ function writeFile18(path5, data, options, cb) {
97770
98155
  if (typeof options === "function")
97771
98156
  cb = options, options = null;
97772
98157
  return go$writeFile(path5, data, options, cb);
@@ -97955,7 +98340,7 @@ var require_graceful_fs = __commonJS({
97955
98340
  }
97956
98341
  });
97957
98342
  }
97958
- function createReadStream3(path5, options) {
98343
+ function createReadStream4(path5, options) {
97959
98344
  return new fs3.ReadStream(path5, options);
97960
98345
  }
97961
98346
  function createWriteStream2(path5, options) {
@@ -102090,25 +102475,25 @@ var require_util2 = __commonJS({
102090
102475
  };
102091
102476
  },
102092
102477
  createDeferredPromise: function() {
102093
- let resolve36;
102478
+ let resolve39;
102094
102479
  let reject2;
102095
102480
  const promise = new Promise((res, rej) => {
102096
- resolve36 = res;
102481
+ resolve39 = res;
102097
102482
  reject2 = rej;
102098
102483
  });
102099
102484
  return {
102100
102485
  promise,
102101
- resolve: resolve36,
102486
+ resolve: resolve39,
102102
102487
  reject: reject2
102103
102488
  };
102104
102489
  },
102105
102490
  promisify(fn) {
102106
- return new Promise((resolve36, reject2) => {
102491
+ return new Promise((resolve39, reject2) => {
102107
102492
  fn((err, ...args) => {
102108
102493
  if (err) {
102109
102494
  return reject2(err);
102110
102495
  }
102111
- return resolve36(...args);
102496
+ return resolve39(...args);
102112
102497
  });
102113
102498
  });
102114
102499
  },
@@ -102900,7 +103285,7 @@ var require_end_of_stream2 = __commonJS({
102900
103285
  validateBoolean3(opts.cleanup, "cleanup");
102901
103286
  autoCleanup = opts.cleanup;
102902
103287
  }
102903
- return new Promise2((resolve36, reject2) => {
103288
+ return new Promise2((resolve39, reject2) => {
102904
103289
  const cleanup = eos(stream, opts, (err) => {
102905
103290
  if (autoCleanup) {
102906
103291
  cleanup();
@@ -102908,7 +103293,7 @@ var require_end_of_stream2 = __commonJS({
102908
103293
  if (err) {
102909
103294
  reject2(err);
102910
103295
  } else {
102911
- resolve36();
103296
+ resolve39();
102912
103297
  }
102913
103298
  });
102914
103299
  });
@@ -104075,7 +104460,7 @@ var require_readable2 = __commonJS({
104075
104460
  error = this.readableEnded ? null : new AbortError();
104076
104461
  this.destroy(error);
104077
104462
  }
104078
- return new Promise2((resolve36, reject2) => eos(this, (err) => err && err !== error ? reject2(err) : resolve36(null)));
104463
+ return new Promise2((resolve39, reject2) => eos(this, (err) => err && err !== error ? reject2(err) : resolve39(null)));
104079
104464
  };
104080
104465
  Readable2.prototype.push = function(chunk, encoding) {
104081
104466
  return readableAddChunk(this, chunk, encoding, false);
@@ -104619,12 +105004,12 @@ var require_readable2 = __commonJS({
104619
105004
  }
104620
105005
  async function* createAsyncIterator(stream, options) {
104621
105006
  let callback = nop;
104622
- function next(resolve36) {
105007
+ function next(resolve39) {
104623
105008
  if (this === stream) {
104624
105009
  callback();
104625
105010
  callback = nop;
104626
105011
  } else {
104627
- callback = resolve36;
105012
+ callback = resolve39;
104628
105013
  }
104629
105014
  }
104630
105015
  stream.on("readable", next);
@@ -105677,7 +106062,7 @@ var require_duplexify = __commonJS({
105677
106062
  );
105678
106063
  };
105679
106064
  function fromAsyncGen(fn) {
105680
- let { promise, resolve: resolve36 } = createDeferredPromise();
106065
+ let { promise, resolve: resolve39 } = createDeferredPromise();
105681
106066
  const ac = new AbortController2();
105682
106067
  const signal = ac.signal;
105683
106068
  const value = fn(
@@ -105692,7 +106077,7 @@ var require_duplexify = __commonJS({
105692
106077
  throw new AbortError(void 0, {
105693
106078
  cause: signal.reason
105694
106079
  });
105695
- ({ promise, resolve: resolve36 } = createDeferredPromise());
106080
+ ({ promise, resolve: resolve39 } = createDeferredPromise());
105696
106081
  yield chunk;
105697
106082
  }
105698
106083
  })(),
@@ -105703,8 +106088,8 @@ var require_duplexify = __commonJS({
105703
106088
  return {
105704
106089
  value,
105705
106090
  write(chunk, encoding, cb) {
105706
- const _resolve = resolve36;
105707
- resolve36 = null;
106091
+ const _resolve = resolve39;
106092
+ resolve39 = null;
105708
106093
  _resolve({
105709
106094
  chunk,
105710
106095
  done: false,
@@ -105712,8 +106097,8 @@ var require_duplexify = __commonJS({
105712
106097
  });
105713
106098
  },
105714
106099
  final(cb) {
105715
- const _resolve = resolve36;
105716
- resolve36 = null;
106100
+ const _resolve = resolve39;
106101
+ resolve39 = null;
105717
106102
  _resolve({
105718
106103
  done: true,
105719
106104
  cb
@@ -106165,7 +106550,7 @@ var require_pipeline = __commonJS({
106165
106550
  callback();
106166
106551
  }
106167
106552
  };
106168
- const wait = () => new Promise2((resolve36, reject2) => {
106553
+ const wait = () => new Promise2((resolve39, reject2) => {
106169
106554
  if (error) {
106170
106555
  reject2(error);
106171
106556
  } else {
@@ -106173,7 +106558,7 @@ var require_pipeline = __commonJS({
106173
106558
  if (error) {
106174
106559
  reject2(error);
106175
106560
  } else {
106176
- resolve36();
106561
+ resolve39();
106177
106562
  }
106178
106563
  };
106179
106564
  }
@@ -106817,8 +107202,8 @@ var require_operators = __commonJS({
106817
107202
  next = null;
106818
107203
  }
106819
107204
  if (!done && (queue2.length >= highWaterMark2 || cnt >= concurrency)) {
106820
- await new Promise2((resolve36) => {
106821
- resume = resolve36;
107205
+ await new Promise2((resolve39) => {
107206
+ resume = resolve39;
106822
107207
  });
106823
107208
  }
106824
107209
  }
@@ -106852,8 +107237,8 @@ var require_operators = __commonJS({
106852
107237
  queue2.shift();
106853
107238
  maybeResume();
106854
107239
  }
106855
- await new Promise2((resolve36) => {
106856
- next = resolve36;
107240
+ await new Promise2((resolve39) => {
107241
+ next = resolve39;
106857
107242
  });
106858
107243
  }
106859
107244
  } finally {
@@ -107111,7 +107496,7 @@ var require_promises = __commonJS({
107111
107496
  var { finished } = require_end_of_stream2();
107112
107497
  require_stream2();
107113
107498
  function pipeline(...streams) {
107114
- return new Promise2((resolve36, reject2) => {
107499
+ return new Promise2((resolve39, reject2) => {
107115
107500
  let signal;
107116
107501
  let end;
107117
107502
  const lastArg = streams[streams.length - 1];
@@ -107126,7 +107511,7 @@ var require_promises = __commonJS({
107126
107511
  if (err) {
107127
107512
  reject2(err);
107128
107513
  } else {
107129
- resolve36(value);
107514
+ resolve39(value);
107130
107515
  }
107131
107516
  },
107132
107517
  {
@@ -111899,10 +112284,10 @@ var require_commonjs3 = __commonJS({
111899
112284
  * Return a void Promise that resolves once the stream ends.
111900
112285
  */
111901
112286
  async promise() {
111902
- return new Promise((resolve36, reject2) => {
112287
+ return new Promise((resolve39, reject2) => {
111903
112288
  this.on(DESTROYED, () => reject2(new Error("stream destroyed")));
111904
112289
  this.on("error", (er) => reject2(er));
111905
- this.on("end", () => resolve36());
112290
+ this.on("end", () => resolve39());
111906
112291
  });
111907
112292
  }
111908
112293
  /**
@@ -111926,7 +112311,7 @@ var require_commonjs3 = __commonJS({
111926
112311
  return Promise.resolve({ done: false, value: res });
111927
112312
  if (this[EOF])
111928
112313
  return stop();
111929
- let resolve36;
112314
+ let resolve39;
111930
112315
  let reject2;
111931
112316
  const onerr = (er) => {
111932
112317
  this.off("data", ondata);
@@ -111940,19 +112325,19 @@ var require_commonjs3 = __commonJS({
111940
112325
  this.off("end", onend);
111941
112326
  this.off(DESTROYED, ondestroy);
111942
112327
  this.pause();
111943
- resolve36({ value, done: !!this[EOF] });
112328
+ resolve39({ value, done: !!this[EOF] });
111944
112329
  };
111945
112330
  const onend = () => {
111946
112331
  this.off("error", onerr);
111947
112332
  this.off("data", ondata);
111948
112333
  this.off(DESTROYED, ondestroy);
111949
112334
  stop();
111950
- resolve36({ done: true, value: void 0 });
112335
+ resolve39({ done: true, value: void 0 });
111951
112336
  };
111952
112337
  const ondestroy = () => onerr(new Error("stream destroyed"));
111953
112338
  return new Promise((res2, rej) => {
111954
112339
  reject2 = rej;
111955
- resolve36 = res2;
112340
+ resolve39 = res2;
111956
112341
  this.once(DESTROYED, ondestroy);
111957
112342
  this.once("error", onerr);
111958
112343
  this.once("end", onend);
@@ -112968,9 +113353,9 @@ var require_commonjs4 = __commonJS({
112968
113353
  if (this.#asyncReaddirInFlight) {
112969
113354
  await this.#asyncReaddirInFlight;
112970
113355
  } else {
112971
- let resolve36 = () => {
113356
+ let resolve39 = () => {
112972
113357
  };
112973
- this.#asyncReaddirInFlight = new Promise((res) => resolve36 = res);
113358
+ this.#asyncReaddirInFlight = new Promise((res) => resolve39 = res);
112974
113359
  try {
112975
113360
  for (const e of await this.#fs.promises.readdir(fullpath, {
112976
113361
  withFileTypes: true
@@ -112983,7 +113368,7 @@ var require_commonjs4 = __commonJS({
112983
113368
  children.provisional = 0;
112984
113369
  }
112985
113370
  this.#asyncReaddirInFlight = void 0;
112986
- resolve36();
113371
+ resolve39();
112987
113372
  }
112988
113373
  return children.slice(0, children.provisional);
112989
113374
  }
@@ -115756,11 +116141,11 @@ var require_core = __commonJS({
115756
116141
  this._finalize();
115757
116142
  }
115758
116143
  var self2 = this;
115759
- return new Promise(function(resolve36, reject2) {
116144
+ return new Promise(function(resolve39, reject2) {
115760
116145
  var errored;
115761
116146
  self2._module.on("end", function() {
115762
116147
  if (!errored) {
115763
- resolve36();
116148
+ resolve39();
115764
116149
  }
115765
116150
  });
115766
116151
  self2._module.on("error", function(err) {
@@ -118200,8 +118585,8 @@ var require_streamx = __commonJS({
118200
118585
  return this;
118201
118586
  },
118202
118587
  next() {
118203
- return new Promise(function(resolve36, reject2) {
118204
- promiseResolve = resolve36;
118588
+ return new Promise(function(resolve39, reject2) {
118589
+ promiseResolve = resolve39;
118205
118590
  promiseReject = reject2;
118206
118591
  const data = stream.read();
118207
118592
  if (data !== null) ondata(data);
@@ -118231,11 +118616,11 @@ var require_streamx = __commonJS({
118231
118616
  }
118232
118617
  function destroy(err) {
118233
118618
  stream.destroy(err);
118234
- return new Promise((resolve36, reject2) => {
118235
- if (stream._duplexState & DESTROYED) return resolve36({ value: void 0, done: true });
118619
+ return new Promise((resolve39, reject2) => {
118620
+ if (stream._duplexState & DESTROYED) return resolve39({ value: void 0, done: true });
118236
118621
  stream.once("close", function() {
118237
118622
  if (err) reject2(err);
118238
- else resolve36({ value: void 0, done: true });
118623
+ else resolve39({ value: void 0, done: true });
118239
118624
  });
118240
118625
  });
118241
118626
  }
@@ -118279,8 +118664,8 @@ var require_streamx = __commonJS({
118279
118664
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
118280
118665
  if (writes === 0) return Promise.resolve(true);
118281
118666
  if (state.drains === null) state.drains = [];
118282
- return new Promise((resolve36) => {
118283
- state.drains.push({ writes, resolve: resolve36 });
118667
+ return new Promise((resolve39) => {
118668
+ state.drains.push({ writes, resolve: resolve39 });
118284
118669
  });
118285
118670
  }
118286
118671
  write(data) {
@@ -118385,10 +118770,10 @@ var require_streamx = __commonJS({
118385
118770
  cb(null);
118386
118771
  }
118387
118772
  function pipelinePromise(...streams) {
118388
- return new Promise((resolve36, reject2) => {
118773
+ return new Promise((resolve39, reject2) => {
118389
118774
  return pipeline(...streams, (err) => {
118390
118775
  if (err) return reject2(err);
118391
- resolve36();
118776
+ resolve39();
118392
118777
  });
118393
118778
  });
118394
118779
  }
@@ -119045,16 +119430,16 @@ var require_extract = __commonJS({
119045
119430
  entryCallback = null;
119046
119431
  cb(err);
119047
119432
  }
119048
- function onnext(resolve36, reject2) {
119433
+ function onnext(resolve39, reject2) {
119049
119434
  if (error) {
119050
119435
  return reject2(error);
119051
119436
  }
119052
119437
  if (entryStream) {
119053
- resolve36({ value: entryStream, done: false });
119438
+ resolve39({ value: entryStream, done: false });
119054
119439
  entryStream = null;
119055
119440
  return;
119056
119441
  }
119057
- promiseResolve = resolve36;
119442
+ promiseResolve = resolve39;
119058
119443
  promiseReject = reject2;
119059
119444
  consumeCallback(null);
119060
119445
  if (extract._finished && promiseResolve) {
@@ -119082,11 +119467,11 @@ var require_extract = __commonJS({
119082
119467
  function destroy(err) {
119083
119468
  extract.destroy(err);
119084
119469
  consumeCallback(err);
119085
- return new Promise((resolve36, reject2) => {
119086
- if (extract.destroyed) return resolve36({ value: void 0, done: true });
119470
+ return new Promise((resolve39, reject2) => {
119471
+ if (extract.destroyed) return resolve39({ value: void 0, done: true });
119087
119472
  extract.once("close", function() {
119088
119473
  if (err) reject2(err);
119089
- else resolve36({ value: void 0, done: true });
119474
+ else resolve39({ value: void 0, done: true });
119090
119475
  });
119091
119476
  });
119092
119477
  }
@@ -119857,7 +120242,7 @@ var require_archiver = __commonJS({
119857
120242
 
119858
120243
  // ../dashboard/src/routes/register-file-workspace-routes.ts
119859
120244
  import { access as access5 } from "node:fs/promises";
119860
- import { createReadStream as createReadStream2 } from "node:fs";
120245
+ import { createReadStream as createReadStream3 } from "node:fs";
119861
120246
  function extractFileParams(req) {
119862
120247
  const filePath = Array.isArray(req.params.filepath) ? req.params.filepath[0] : req.params.filepath ?? "";
119863
120248
  const workspace = typeof req.query.workspace === "string" && req.query.workspace.length > 0 ? req.query.workspace : "project";
@@ -119908,7 +120293,7 @@ function registerFileWorkspaceRoutes(ctx) {
119908
120293
  if (typeof content !== "string") {
119909
120294
  throw badRequest("content is required and must be a string");
119910
120295
  }
119911
- const result = await writeFile12(scopedStore, req.params.id, filePath, content);
120296
+ const result = await writeFile13(scopedStore, req.params.id, filePath, content);
119912
120297
  res.json(result);
119913
120298
  } catch (err) {
119914
120299
  if (err instanceof ApiError) {
@@ -120119,7 +120504,7 @@ function registerFileWorkspaceRoutes(ctx) {
120119
120504
  res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
120120
120505
  res.setHeader("Content-Length", stats.size);
120121
120506
  res.setHeader("Last-Modified", stats.mtime.toUTCString());
120122
- const stream = createReadStream2(absolutePath);
120507
+ const stream = createReadStream3(absolutePath);
120123
120508
  stream.pipe(res);
120124
120509
  } catch (err) {
120125
120510
  if (err instanceof ApiError) {
@@ -120866,8 +121251,8 @@ var init_exec_file = __esm({
120866
121251
 
120867
121252
  // ../dashboard/src/routes/register-project-routes.ts
120868
121253
  import * as fsPromises from "node:fs/promises";
120869
- import { dirname as dirname12, isAbsolute as isAbsolute14, join as join39 } from "node:path";
120870
- var access7, stat8, mkdir13, readdir9, rm2, registerProjectRoutes;
121254
+ import { dirname as dirname12, isAbsolute as isAbsolute14, join as join40 } from "node:path";
121255
+ var access7, stat8, mkdir14, readdir9, rm3, registerProjectRoutes;
120871
121256
  var init_register_project_routes = __esm({
120872
121257
  "../dashboard/src/routes/register-project-routes.ts"() {
120873
121258
  "use strict";
@@ -120878,9 +121263,9 @@ var init_register_project_routes = __esm({
120878
121263
  ({
120879
121264
  access: access7,
120880
121265
  stat: stat8,
120881
- mkdir: mkdir13,
121266
+ mkdir: mkdir14,
120882
121267
  readdir: readdir9,
120883
- rm: rm2
121268
+ rm: rm3
120884
121269
  } = fsPromises);
120885
121270
  registerProjectRoutes = (ctx) => {
120886
121271
  const { router, options, runtimeLogger, prioritizeProjectsForCurrentDirectory, rethrowAsApiError: rethrowAsApiError7 } = ctx;
@@ -121031,7 +121416,7 @@ var init_register_project_routes = __esm({
121031
121416
  throw badRequest("Clone destination must be empty");
121032
121417
  }
121033
121418
  } else {
121034
- await mkdir13(normalizedPath, { recursive: false });
121419
+ await mkdir14(normalizedPath, { recursive: false });
121035
121420
  destinationCreatedForClone = true;
121036
121421
  }
121037
121422
  const cloneSource = normalizedCloneUrl;
@@ -121047,7 +121432,7 @@ var init_register_project_routes = __esm({
121047
121432
  } catch (cloneError) {
121048
121433
  if (destinationCreatedForClone) {
121049
121434
  try {
121050
- await rm2(normalizedPath, { recursive: true, force: true });
121435
+ await rm3(normalizedPath, { recursive: true, force: true });
121051
121436
  } catch {
121052
121437
  }
121053
121438
  }
@@ -121057,7 +121442,7 @@ var init_register_project_routes = __esm({
121057
121442
  }
121058
121443
  }
121059
121444
  let hasFusionDir = false;
121060
- const fusionDirPath = join39(normalizedPath, ".fusion");
121445
+ const fusionDirPath = join40(normalizedPath, ".fusion");
121061
121446
  try {
121062
121447
  await access7(fusionDirPath);
121063
121448
  hasFusionDir = true;
@@ -121119,18 +121504,18 @@ var init_register_project_routes = __esm({
121119
121504
  const entries = await readdir9(searchPath, { withFileTypes: true });
121120
121505
  for (const entry of entries) {
121121
121506
  if (!entry.isDirectory()) continue;
121122
- const dirPath = join39(searchPath, entry.name);
121507
+ const dirPath = join40(searchPath, entry.name);
121123
121508
  let hasKbDb = false;
121124
121509
  let hasFusionDir = false;
121125
121510
  try {
121126
- await access7(join39(dirPath, ".fusion", "fusion.db"));
121511
+ await access7(join40(dirPath, ".fusion", "fusion.db"));
121127
121512
  hasKbDb = true;
121128
121513
  } catch {
121129
121514
  hasKbDb = false;
121130
121515
  }
121131
121516
  if (!hasKbDb) {
121132
121517
  try {
121133
- await access7(join39(dirPath, ".fusion"));
121518
+ await access7(join40(dirPath, ".fusion"));
121134
121519
  hasFusionDir = true;
121135
121520
  } catch {
121136
121521
  hasFusionDir = false;
@@ -124134,7 +124519,7 @@ var init_register_agent_reflection_rating_routes = __esm({
124134
124519
  });
124135
124520
 
124136
124521
  // ../dashboard/src/agent-generation.ts
124137
- import { randomUUID as randomUUID16 } from "node:crypto";
124522
+ import { randomUUID as randomUUID17 } from "node:crypto";
124138
124523
  async function initPromptCatalog() {
124139
124524
  if (promptCatalogReady) return;
124140
124525
  try {
@@ -124340,7 +124725,7 @@ async function startAgentGeneration(ip, roleDescription) {
124340
124725
  `Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR4} generation sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
124341
124726
  );
124342
124727
  }
124343
- const sessionId = randomUUID16();
124728
+ const sessionId = randomUUID17();
124344
124729
  const session = {
124345
124730
  id: sessionId,
124346
124731
  ip,
@@ -124518,7 +124903,7 @@ You MUST respond with ONLY valid JSON (no markdown, no explanation):
124518
124903
  import { createWriteStream } from "node:fs";
124519
124904
  import * as fsPromises2 from "node:fs/promises";
124520
124905
  import { tmpdir as tmpdir3 } from "node:os";
124521
- import { join as join40, resolve as resolve19 } from "node:path";
124906
+ import { join as join41, resolve as resolve20 } from "node:path";
124522
124907
  import { Readable } from "node:stream";
124523
124908
  import { pipeline as streamPipeline } from "node:stream/promises";
124524
124909
  function registerAgentImportExportRoutes(ctx) {
@@ -124555,11 +124940,11 @@ function registerAgentImportExportRoutes(ctx) {
124555
124940
  }
124556
124941
  let resolvedOutputDir;
124557
124942
  if (typeof outputDir === "string" && outputDir.trim().length > 0) {
124558
- resolvedOutputDir = resolve19(outputDir.trim());
124943
+ resolvedOutputDir = resolve20(outputDir.trim());
124559
124944
  } else if (typeof outputDir === "string") {
124560
124945
  throw badRequest("outputDir cannot be empty");
124561
124946
  } else {
124562
- resolvedOutputDir = await mkdtemp(join40(tmpdir3(), "fusion-agent-export-"));
124947
+ resolvedOutputDir = await mkdtemp(join41(tmpdir3(), "fusion-agent-export-"));
124563
124948
  }
124564
124949
  const result = await exportAgentsToDirectory2(agentsToExport, resolvedOutputDir, {
124565
124950
  companyName: typeof companyName === "string" ? companyName : void 0,
@@ -124686,7 +125071,7 @@ ${body}`;
124686
125071
  return result;
124687
125072
  }
124688
125073
  const safeCompanySlug = companySlug ? slugifyPathSegment2(companySlug, "unknown-company") : "unknown-company";
124689
- const skillsBaseDir = join40(projectRoot, "skills", "imported", safeCompanySlug);
125074
+ const skillsBaseDir = join41(projectRoot, "skills", "imported", safeCompanySlug);
124690
125075
  const usedSlugs = /* @__PURE__ */ new Set();
124691
125076
  for (const skill of skills) {
124692
125077
  const name = typeof skill.name === "string" && skill.name.trim().length > 0 ? skill.name.trim() : null;
@@ -124703,8 +125088,8 @@ ${body}`;
124703
125088
  skillSlug = `${skillSlug}-${counter}`;
124704
125089
  }
124705
125090
  usedSlugs.add(skillSlug);
124706
- const skillDir = join40(skillsBaseDir, skillSlug);
124707
- const skillPath = join40(skillDir, "SKILL.md");
125091
+ const skillDir = join41(skillsBaseDir, skillSlug);
125092
+ const skillPath = join41(skillDir, "SKILL.md");
124708
125093
  try {
124709
125094
  await access8(skillPath);
124710
125095
  result.skipped.push(name);
@@ -124740,7 +125125,7 @@ ${body}`;
124740
125125
 
124741
125126
  <!-- Add skill instructions here. -->`;
124742
125127
  try {
124743
- await mkdir14(skillDir, { recursive: true });
125128
+ await mkdir15(skillDir, { recursive: true });
124744
125129
  const content = toSkillMarkdown2(frontmatter, body);
124745
125130
  await fsWriteFile2(skillPath, content, "utf-8");
124746
125131
  result.imported.push({ name, path: `skills/imported/${safeCompanySlug}/${skillSlug}/SKILL.md` });
@@ -124790,7 +125175,7 @@ ${body}`;
124790
125175
  tasks: []
124791
125176
  };
124792
125177
  } else if (typeof source === "string" && source.trim()) {
124793
- const sourcePath = resolve19(source);
125178
+ const sourcePath = resolve20(source);
124794
125179
  const isArchive = sourcePath.endsWith(".tar.gz") || sourcePath.endsWith(".tgz") || sourcePath.endsWith(".zip");
124795
125180
  if (isArchive) {
124796
125181
  try {
@@ -124874,8 +125259,8 @@ ${body}`;
124874
125259
  const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/main.tar.gz`;
124875
125260
  let tempDir = null;
124876
125261
  try {
124877
- tempDir = await mkdtemp(join40(tmpdir3(), `fn-agent-import-${importCompanySlug}-`));
124878
- const archivePath = join40(tempDir, "archive.tar.gz");
125262
+ tempDir = await mkdtemp(join41(tmpdir3(), `fn-agent-import-${importCompanySlug}-`));
125263
+ const archivePath = join41(tempDir, "archive.tar.gz");
124879
125264
  const downloadController = new AbortController();
124880
125265
  const downloadTimeout = setTimeout(() => downloadController.abort(), 3e4);
124881
125266
  let archiveResponse;
@@ -124919,7 +125304,7 @@ ${body}`;
124919
125304
  } finally {
124920
125305
  if (tempDir) {
124921
125306
  try {
124922
- await rm3(tempDir, { recursive: true, force: true });
125307
+ await rm4(tempDir, { recursive: true, force: true });
124923
125308
  } catch {
124924
125309
  }
124925
125310
  }
@@ -125127,14 +125512,14 @@ function registerAgentGenerationRoutes(ctx) {
125127
125512
  }
125128
125513
  });
125129
125514
  }
125130
- var mkdtemp, access8, stat9, mkdir14, rm3, fsWriteFile2;
125515
+ var mkdtemp, access8, stat9, mkdir15, rm4, fsWriteFile2;
125131
125516
  var init_register_agent_import_export_generation_routes = __esm({
125132
125517
  "../dashboard/src/routes/register-agent-import-export-generation-routes.ts"() {
125133
125518
  "use strict";
125134
125519
  init_api_error();
125135
125520
  init_ai_session_diagnostics();
125136
125521
  init_agent_generation();
125137
- ({ mkdtemp, access: access8, stat: stat9, mkdir: mkdir14, rm: rm3, writeFile: fsWriteFile2 } = fsPromises2);
125522
+ ({ mkdtemp, access: access8, stat: stat9, mkdir: mkdir15, rm: rm4, writeFile: fsWriteFile2 } = fsPromises2);
125138
125523
  }
125139
125524
  });
125140
125525
 
@@ -125591,9 +125976,9 @@ function registerProxyRoutes(router, deps) {
125591
125976
  if (req.rawBody && req.rawBody.length > 0) {
125592
125977
  body = req.rawBody;
125593
125978
  } else {
125594
- await new Promise((resolve36, reject2) => {
125979
+ await new Promise((resolve39, reject2) => {
125595
125980
  req.on("data", (chunk) => chunks.push(chunk));
125596
- req.on("end", resolve36);
125981
+ req.on("end", resolve39);
125597
125982
  req.on("error", reject2);
125598
125983
  });
125599
125984
  if (chunks.length > 0) {
@@ -125789,13 +126174,13 @@ import { readFile as readFile19 } from "node:fs/promises";
125789
126174
  import * as https from "node:https";
125790
126175
  import * as child_process from "node:child_process";
125791
126176
  function execFileAsync4(file, args, options) {
125792
- return new Promise((resolve36, reject2) => {
126177
+ return new Promise((resolve39, reject2) => {
125793
126178
  child_process.execFile(file, args, options, (error, stdout, stderr) => {
125794
126179
  if (error) {
125795
126180
  reject2(error);
125796
126181
  return;
125797
126182
  }
125798
- resolve36({ stdout: String(stdout), stderr: String(stderr) });
126183
+ resolve39({ stdout: String(stdout), stderr: String(stderr) });
125799
126184
  });
125800
126185
  });
125801
126186
  }
@@ -125854,7 +126239,7 @@ function formatDuration(ms) {
125854
126239
  return remHours > 0 ? `${days}d ${remHours}h` : `${days}d`;
125855
126240
  }
125856
126241
  function httpsRequest(url, options) {
125857
- return new Promise((resolve36, reject2) => {
126242
+ return new Promise((resolve39, reject2) => {
125858
126243
  const parsed = new URL(url);
125859
126244
  const req = https.request(
125860
126245
  {
@@ -125874,7 +126259,7 @@ function httpsRequest(url, options) {
125874
126259
  if (typeof v === "string") hdrs[k.toLowerCase()] = v;
125875
126260
  else if (Array.isArray(v)) hdrs[k.toLowerCase()] = v.join(", ");
125876
126261
  }
125877
- resolve36({
126262
+ resolve39({
125878
126263
  status: res.statusCode || 0,
125879
126264
  headers: hdrs,
125880
126265
  body: Buffer.concat(chunks).toString("utf-8")
@@ -126121,7 +126506,7 @@ async function fetchClaudeUsageViaCli() {
126121
126506
  env: { ...process.env, TERM: "xterm-256color" }
126122
126507
  };
126123
126508
  if (isWindows) ptyOptions.useConpty = false;
126124
- const output = await new Promise((resolve36, reject2) => {
126509
+ const output = await new Promise((resolve39, reject2) => {
126125
126510
  let buf = "";
126126
126511
  let settled = false;
126127
126512
  let sentCommand = false;
@@ -126137,7 +126522,7 @@ async function fetchClaudeUsageViaCli() {
126137
126522
  }
126138
126523
  const clean = _stripClaudeAnsi(buf);
126139
126524
  if (clean.includes("Current session") || clean.includes("% left") || clean.includes("% used")) {
126140
- resolve36(buf);
126525
+ resolve39(buf);
126141
126526
  } else {
126142
126527
  reject2(new Error("Claude CLI timed out after 60s \u2014 got output but no usage data. Try running `claude /usage` manually."));
126143
126528
  }
@@ -126188,7 +126573,7 @@ async function fetchClaudeUsageViaCli() {
126188
126573
  ptyProcess.kill();
126189
126574
  } catch {
126190
126575
  }
126191
- resolve36(buf);
126576
+ resolve39(buf);
126192
126577
  }
126193
126578
  }, 2e3);
126194
126579
  }
@@ -126199,7 +126584,7 @@ async function fetchClaudeUsageViaCli() {
126199
126584
  if (settled) return;
126200
126585
  settled = true;
126201
126586
  clearTimeout(timeout2);
126202
- resolve36(buf);
126587
+ resolve39(buf);
126203
126588
  });
126204
126589
  });
126205
126590
  const cleanOutput = _stripClaudeAnsi(output);
@@ -126867,9 +127252,9 @@ async function fetchGitHubCopilotUsage() {
126867
127252
  return usage;
126868
127253
  }
126869
127254
  function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_TIMEOUT_MS) {
126870
- return new Promise((resolve36) => {
127255
+ return new Promise((resolve39) => {
126871
127256
  const timer = setTimeout(() => {
126872
- resolve36({
127257
+ resolve39({
126873
127258
  name: providerName,
126874
127259
  icon: "\u23F1\uFE0F",
126875
127260
  status: "error",
@@ -126879,10 +127264,10 @@ function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_T
126879
127264
  }, timeoutMs);
126880
127265
  providerPromise.then((result) => {
126881
127266
  clearTimeout(timer);
126882
- resolve36(result);
127267
+ resolve39(result);
126883
127268
  }).catch((err) => {
126884
127269
  clearTimeout(timer);
126885
- resolve36({
127270
+ resolve39({
126886
127271
  name: providerName,
126887
127272
  icon: "\u23F1\uFE0F",
126888
127273
  status: "error",
@@ -126937,7 +127322,7 @@ var init_usage = __esm({
126937
127322
  ANTHROPIC_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
126938
127323
  ANTHROPIC_OAUTH_BETA = "oauth-2025-04-20";
126939
127324
  CLAUDE_USAGE_USER_AGENT = "claude-code-fusion-dashboard";
126940
- _sleep = (ms) => new Promise((resolve36) => setTimeout(resolve36, ms));
127325
+ _sleep = (ms) => new Promise((resolve39) => setTimeout(resolve39, ms));
126941
127326
  sleepFn = _sleep;
126942
127327
  PROVIDER_FETCH_TIMEOUT_MS = 1e4;
126943
127328
  CLAUDE_FETCH_TIMEOUT_MS = 75e3;
@@ -127251,8 +127636,8 @@ var init_register_auth_routes = __esm({
127251
127636
  loginInProgress.set(provider, abortController);
127252
127637
  let authResolve;
127253
127638
  let authReject;
127254
- const authUrlPromise = new Promise((resolve36, reject2) => {
127255
- authResolve = resolve36;
127639
+ const authUrlPromise = new Promise((resolve39, reject2) => {
127640
+ authResolve = resolve39;
127256
127641
  authReject = reject2;
127257
127642
  });
127258
127643
  const loginPromise = storage.login(provider, {
@@ -127678,7 +128063,7 @@ async function mintAgentApiKeyViaCli(opts) {
127678
128063
  args.push("--data-dir", opts.dataDir);
127679
128064
  }
127680
128065
  const timeoutMs = opts.cliTimeoutMs ?? 3e4;
127681
- return new Promise((resolve36, reject2) => {
128066
+ return new Promise((resolve39, reject2) => {
127682
128067
  let child;
127683
128068
  try {
127684
128069
  child = spawn15(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
@@ -127752,7 +128137,7 @@ async function mintAgentApiKeyViaCli(opts) {
127752
128137
  const apiBase = (typeof r.apiBase === "string" ? r.apiBase : void 0) ?? (typeof r.api_base === "string" ? r.api_base : void 0);
127753
128138
  const agentId = (typeof r.agentId === "string" ? r.agentId : void 0) ?? (typeof r.id === "string" ? r.id : void 0);
127754
128139
  const companyId = typeof r.companyId === "string" ? r.companyId : void 0;
127755
- resolve36({ apiKey, apiBase, agentId, companyId, raw: parsed });
128140
+ resolve39({ apiKey, apiBase, agentId, companyId, raw: parsed });
127756
128141
  });
127757
128142
  });
127758
128143
  }
@@ -127772,7 +128157,7 @@ async function spawnPaperclipCliJson(args, opts) {
127772
128157
  }
127773
128158
  const timeoutMs = opts.cliTimeoutMs ?? 15e3;
127774
128159
  const label = ["paperclipai", ...args].join(" ");
127775
- return new Promise((resolve36, reject2) => {
128160
+ return new Promise((resolve39, reject2) => {
127776
128161
  let child;
127777
128162
  try {
127778
128163
  child = spawn15(bin, fullArgs, { stdio: ["ignore", "pipe", "pipe"] });
@@ -127818,7 +128203,7 @@ async function spawnPaperclipCliJson(args, opts) {
127818
128203
  return;
127819
128204
  }
127820
128205
  try {
127821
- resolve36(JSON.parse(cleaned));
128206
+ resolve39(JSON.parse(cleaned));
127822
128207
  } catch {
127823
128208
  reject2(new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`));
127824
128209
  }
@@ -127945,9 +128330,9 @@ var init_paperclip_client = __esm({
127945
128330
  });
127946
128331
 
127947
128332
  // ../../plugins/fusion-plugin-paperclip-runtime/dist/runtime-adapter.js
127948
- import { randomUUID as randomUUID17 } from "node:crypto";
128333
+ import { randomUUID as randomUUID18 } from "node:crypto";
127949
128334
  function sleep3(ms) {
127950
- return new Promise((resolve36) => setTimeout(resolve36, ms));
128335
+ return new Promise((resolve39) => setTimeout(resolve39, ms));
127951
128336
  }
127952
128337
  function asString2(value) {
127953
128338
  return typeof value === "string" ? value : void 0;
@@ -128064,7 +128449,7 @@ var init_runtime_adapter3 = __esm({
128064
128449
  apiKey: effectiveApiKey,
128065
128450
  agentId,
128066
128451
  companyId,
128067
- sessionId: randomUUID17(),
128452
+ sessionId: randomUUID18(),
128068
128453
  systemPrompt: options.systemPrompt,
128069
128454
  cwd: options.cwd,
128070
128455
  mode: normalizeMode(this.config.mode),
@@ -128590,8 +128975,8 @@ var init_register_runtime_provider_routes = __esm({
128590
128975
 
128591
128976
  // ../dashboard/src/update-check.ts
128592
128977
  import { readFileSync as readFileSync8 } from "node:fs";
128593
- import { mkdir as mkdir15, rm as rm4, writeFile as writeFile13 } from "node:fs/promises";
128594
- import { join as join42 } from "node:path";
128978
+ import { mkdir as mkdir16, rm as rm5, writeFile as writeFile14 } from "node:fs/promises";
128979
+ import { join as join43 } from "node:path";
128595
128980
  function ttlForFrequency(frequency) {
128596
128981
  switch (frequency) {
128597
128982
  case "manual":
@@ -128605,7 +128990,7 @@ function ttlForFrequency(frequency) {
128605
128990
  }
128606
128991
  }
128607
128992
  function getCachePath(fusionDir) {
128608
- return join42(fusionDir, CACHE_FILENAME);
128993
+ return join43(fusionDir, CACHE_FILENAME);
128609
128994
  }
128610
128995
  function parseVersion(version) {
128611
128996
  return version.split(".").slice(0, 3).map((part) => Number.parseInt(part, 10)).map((value) => Number.isFinite(value) ? value : 0);
@@ -128637,7 +129022,7 @@ function readCachedUpdateCheck(fusionDir) {
128637
129022
  }
128638
129023
  }
128639
129024
  async function clearUpdateCheckCache(fusionDir) {
128640
- await rm4(getCachePath(fusionDir), { force: true });
129025
+ await rm5(getCachePath(fusionDir), { force: true });
128641
129026
  }
128642
129027
  async function performUpdateCheck(fusionDir, currentVersion, options = {}) {
128643
129028
  const now = Date.now();
@@ -128669,8 +129054,8 @@ async function performUpdateCheck(fusionDir, currentVersion, options = {}) {
128669
129054
  updateAvailable,
128670
129055
  lastChecked: now
128671
129056
  };
128672
- await mkdir15(fusionDir, { recursive: true });
128673
- await writeFile13(getCachePath(fusionDir), JSON.stringify(result, null, 2), "utf-8");
129057
+ await mkdir16(fusionDir, { recursive: true });
129058
+ await writeFile14(getCachePath(fusionDir), JSON.stringify(result, null, 2), "utf-8");
128674
129059
  hasRefreshedThisProcess = true;
128675
129060
  return result;
128676
129061
  } catch (error) {
@@ -128696,22 +129081,29 @@ var init_update_check = __esm({
128696
129081
  });
128697
129082
 
128698
129083
  // ../dashboard/src/routes/register-update-check-routes.ts
128699
- import { readFileSync as readFileSync9 } from "node:fs";
128700
- import { dirname as dirname13, join as join43 } from "node:path";
129084
+ import { existsSync as existsSync29, readFileSync as readFileSync9 } from "node:fs";
129085
+ import { dirname as dirname13, resolve as resolve21 } from "node:path";
128701
129086
  import { fileURLToPath as fileURLToPath3 } from "node:url";
128702
- var __dirname, CLI_PACKAGE_VERSION, registerUpdateCheckRoutes;
129087
+ var CLI_PACKAGE_VERSION, registerUpdateCheckRoutes;
128703
129088
  var init_register_update_check_routes = __esm({
128704
129089
  "../dashboard/src/routes/register-update-check-routes.ts"() {
128705
129090
  "use strict";
128706
129091
  init_src();
128707
129092
  init_update_check();
128708
- __dirname = dirname13(fileURLToPath3(import.meta.url));
128709
129093
  CLI_PACKAGE_VERSION = (() => {
128710
129094
  try {
128711
- const packageJsonPath = join43(__dirname, "..", "..", "..", "cli", "package.json");
128712
- const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
128713
- if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
128714
- return packageJson.version;
129095
+ let cur = dirname13(fileURLToPath3(import.meta.url));
129096
+ for (let i = 0; i < 8; i++) {
129097
+ const pkgPath = resolve21(cur, "package.json");
129098
+ if (existsSync29(pkgPath)) {
129099
+ const parsed = JSON.parse(readFileSync9(pkgPath, "utf-8"));
129100
+ if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string" && parsed.version.length > 0) {
129101
+ return parsed.version;
129102
+ }
129103
+ }
129104
+ const parent2 = resolve21(cur, "..");
129105
+ if (parent2 === cur) break;
129106
+ cur = parent2;
128715
129107
  }
128716
129108
  } catch {
128717
129109
  }
@@ -132693,7 +133085,7 @@ var init_todo_routes = __esm({
132693
133085
 
132694
133086
  // ../dashboard/src/dev-server-detect.ts
132695
133087
  import { glob, readFile as readFile20 } from "node:fs/promises";
132696
- import { dirname as dirname14, join as join44, relative as relative10, resolve as resolve20 } from "node:path";
133088
+ import { dirname as dirname14, join as join44, relative as relative10, resolve as resolve22 } from "node:path";
132697
133089
  async function readPackageJson(filePath) {
132698
133090
  try {
132699
133091
  const raw = await readFile20(filePath, "utf-8");
@@ -132743,7 +133135,7 @@ async function collectWorkspacePackageJsons(projectRoot) {
132743
133135
  try {
132744
133136
  for await (const match of glob(pattern, { cwd: projectRoot })) {
132745
133137
  if (typeof match === "string") {
132746
- discovered.add(resolve20(projectRoot, match));
133138
+ discovered.add(resolve22(projectRoot, match));
132747
133139
  }
132748
133140
  }
132749
133141
  } catch {
@@ -132768,7 +133160,7 @@ function toSource(projectRoot, packageJsonPath) {
132768
133160
  return rel.length > 0 ? rel : "root";
132769
133161
  }
132770
133162
  async function detectDevServerScripts(projectRoot) {
132771
- const root = resolve20(projectRoot);
133163
+ const root = resolve22(projectRoot);
132772
133164
  const candidates = [];
132773
133165
  const rootPackagePath = join44(root, "package.json");
132774
133166
  const rootPackage = await readPackageJson(rootPackagePath);
@@ -132836,10 +133228,10 @@ var init_dev_server_detect = __esm({
132836
133228
  });
132837
133229
 
132838
133230
  // ../dashboard/src/dev-server-store.ts
132839
- import { mkdir as mkdir16, readFile as readFile21, writeFile as writeFile14 } from "node:fs/promises";
132840
- import { dirname as dirname15, join as join45, resolve as resolve21 } from "node:path";
133231
+ import { mkdir as mkdir17, readFile as readFile21, writeFile as writeFile15 } from "node:fs/promises";
133232
+ import { dirname as dirname15, join as join45, resolve as resolve23 } from "node:path";
132841
133233
  function devServerFilePath(projectDir) {
132842
- return join45(resolve21(projectDir), ".fusion", "dev-server.json");
133234
+ return join45(resolve23(projectDir), ".fusion", "dev-server.json");
132843
133235
  }
132844
133236
  function normalizeState(candidate) {
132845
133237
  const defaults = DEV_SERVER_DEFAULT_STATE();
@@ -132874,7 +133266,7 @@ function normalizeConfig(candidate) {
132874
133266
  };
132875
133267
  }
132876
133268
  async function loadDevServerStore(projectDir) {
132877
- const storeKey = resolve21(projectDir);
133269
+ const storeKey = resolve23(projectDir);
132878
133270
  let store = storeInstances.get(storeKey);
132879
133271
  if (!store) {
132880
133272
  store = new DevServerStore(projectDir);
@@ -132933,7 +133325,7 @@ var init_dev_server_store = __esm({
132933
133325
  return error.code === "ENOENT";
132934
133326
  };
132935
133327
  try {
132936
- await mkdir16(dir2, { recursive: true });
133328
+ await mkdir17(dir2, { recursive: true });
132937
133329
  } catch (error) {
132938
133330
  if (isMissingPathError(error)) {
132939
133331
  return;
@@ -132941,13 +133333,13 @@ var init_dev_server_store = __esm({
132941
133333
  throw error;
132942
133334
  }
132943
133335
  try {
132944
- await writeFile14(this.filePath, serializedPayload, "utf-8");
133336
+ await writeFile15(this.filePath, serializedPayload, "utf-8");
132945
133337
  } catch (error) {
132946
133338
  if (!isMissingPathError(error)) {
132947
133339
  throw error;
132948
133340
  }
132949
133341
  try {
132950
- await mkdir16(dir2, { recursive: true });
133342
+ await mkdir17(dir2, { recursive: true });
132951
133343
  } catch (retryMkdirError) {
132952
133344
  if (isMissingPathError(retryMkdirError)) {
132953
133345
  return;
@@ -132955,7 +133347,7 @@ var init_dev_server_store = __esm({
132955
133347
  throw retryMkdirError;
132956
133348
  }
132957
133349
  try {
132958
- await writeFile14(this.filePath, serializedPayload, "utf-8");
133350
+ await writeFile15(this.filePath, serializedPayload, "utf-8");
132959
133351
  } catch (retryWriteError) {
132960
133352
  if (isMissingPathError(retryWriteError)) {
132961
133353
  return;
@@ -133152,7 +133544,7 @@ function detectPortFromLogLine(line) {
133152
133544
  return detectViteLine(cleanLine) ?? detectNextLine(cleanLine) ?? detectStorybookLine(cleanLine) ?? detectAngularLine(cleanLine) ?? detectGenericUrl(cleanLine) ?? detectGenericPortLine(cleanLine);
133153
133545
  }
133154
133546
  function probePort(host, port, timeoutMs) {
133155
- return new Promise((resolve36) => {
133547
+ return new Promise((resolve39) => {
133156
133548
  let settled = false;
133157
133549
  const socket = createConnection({ host, port });
133158
133550
  const settle = (isOpen) => {
@@ -133166,7 +133558,7 @@ function probePort(host, port, timeoutMs) {
133166
133558
  } else {
133167
133559
  socket.destroy();
133168
133560
  }
133169
- resolve36(isOpen);
133561
+ resolve39(isOpen);
133170
133562
  };
133171
133563
  socket.setTimeout(timeoutMs);
133172
133564
  socket.once("connect", () => settle(true));
@@ -133293,8 +133685,8 @@ var init_dev_server_process = __esm({
133293
133685
  stdio: ["pipe", "pipe", "pipe"]
133294
133686
  });
133295
133687
  this.childProcess = child;
133296
- this.closePromise = new Promise((resolve36) => {
133297
- this.resolveClosePromise = resolve36;
133688
+ this.closePromise = new Promise((resolve39) => {
133689
+ this.resolveClosePromise = resolve39;
133298
133690
  });
133299
133691
  const runningState = await this.store.updateState({
133300
133692
  pid: child.pid,
@@ -134091,7 +134483,7 @@ Your job is to refine task descriptions based on the user's selected refinement
134091
134483
 
134092
134484
  // ../dashboard/src/routes.ts
134093
134485
  import multer from "multer";
134094
- import { resolve as resolve22, sep as sep6, join as join46, isAbsolute as isAbsolute15 } from "node:path";
134486
+ import { resolve as resolve24, sep as sep6, join as join46, isAbsolute as isAbsolute15 } from "node:path";
134095
134487
  import * as nodeFs from "node:fs";
134096
134488
  import os5 from "node:os";
134097
134489
  import v8 from "node:v8";
@@ -134123,7 +134515,7 @@ function getPiPackageManagerAgentDir() {
134123
134515
  return nodeFs.existsSync(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
134124
134516
  }
134125
134517
  function packageExtensionName(extensionPath, source) {
134126
- const base = resolve22(extensionPath).split(sep6).pop()?.replace(/\.(ts|js)$/i, "") || source;
134518
+ const base = resolve24(extensionPath).split(sep6).pop()?.replace(/\.(ts|js)$/i, "") || source;
134127
134519
  if (base !== "index") {
134128
134520
  return base;
134129
134521
  }
@@ -134131,7 +134523,7 @@ function packageExtensionName(extensionPath, source) {
134131
134523
  }
134132
134524
  async function discoverDashboardPiExtensions(cwd) {
134133
134525
  const settings = discoverPiExtensions(cwd);
134134
- const disabled = new Set(settings.disabledIds.map((id) => resolve22(id)));
134526
+ const disabled = new Set(settings.disabledIds.map((id) => resolve24(id)));
134135
134527
  const byPath = new Map(settings.extensions.map((entry) => [entry.id, entry]));
134136
134528
  try {
134137
134529
  const { DefaultPackageManager: DefaultPackageManager5 } = await import("@mariozechner/pi-coding-agent");
@@ -134153,7 +134545,7 @@ async function discoverDashboardPiExtensions(cwd) {
134153
134545
  });
134154
134546
  const resolved = await packageManager.resolve(async () => "skip");
134155
134547
  for (const extension2 of resolved.extensions) {
134156
- const id = resolve22(extension2.path);
134548
+ const id = resolve24(extension2.path);
134157
134549
  const source = extension2.metadata?.source || "package";
134158
134550
  byPath.set(id, {
134159
134551
  id,
@@ -134543,7 +134935,8 @@ function createApiRoutes(store, options) {
134543
134935
  });
134544
134936
  registerChatRoutes(routeContext, {
134545
134937
  parseLastEventId: parseLastEventId2,
134546
- validateOptionalModelField
134938
+ validateOptionalModelField,
134939
+ upload
134547
134940
  });
134548
134941
  registerMessagingScriptRoutes(routeContext);
134549
134942
  registerGitGitHubRoutes(routeContext);
@@ -134555,8 +134948,8 @@ function createApiRoutes(store, options) {
134555
134948
  function isHeartbeatMonitorForProject(scopedStore) {
134556
134949
  if (!heartbeatMonitor?.rootDir) return true;
134557
134950
  try {
134558
- const monitorRoot = resolve22(heartbeatMonitor.rootDir);
134559
- const storeRoot = resolve22(scopedStore.getRootDir());
134951
+ const monitorRoot = resolve24(heartbeatMonitor.rootDir);
134952
+ const storeRoot = resolve24(scopedStore.getRootDir());
134560
134953
  return monitorRoot === storeRoot;
134561
134954
  } catch {
134562
134955
  return true;
@@ -136478,15 +136871,15 @@ Description: ${step.description}`
136478
136871
  return;
136479
136872
  }
136480
136873
  }
136481
- const { resolve: resolve36, dirname: dirname28, join: join65 } = await import("node:path");
136874
+ const { resolve: resolve39, dirname: dirname28, join: join65 } = await import("node:path");
136482
136875
  const { readdir: readdir12, stat: stat12 } = await import("node:fs/promises");
136483
136876
  const rawPath = req.query.path || process.env.HOME || process.env.USERPROFILE || "/";
136484
136877
  const showHidden = req.query.showHidden === "true";
136485
- const resolvedPath = resolve36(rawPath);
136878
+ const resolvedPath = resolve39(rawPath);
136486
136879
  if (rawPath.includes("..")) {
136487
136880
  throw badRequest("Path must not contain '..' traversal");
136488
136881
  }
136489
- if (resolvedPath !== resolve36(resolvedPath)) {
136882
+ if (resolvedPath !== resolve39(resolvedPath)) {
136490
136883
  throw badRequest("Path must be absolute");
136491
136884
  }
136492
136885
  let pathStat;
@@ -141813,7 +142206,7 @@ var init_badge_pubsub = __esm({
141813
142206
  });
141814
142207
 
141815
142208
  // ../dashboard/src/terminal-websocket-diagnostics.ts
141816
- import { basename as basename11, normalize as normalize4, sep as sep7 } from "node:path";
142209
+ import { basename as basename12, normalize as normalize4, sep as sep7 } from "node:path";
141817
142210
  function toSessionTag(sessionId) {
141818
142211
  const normalized = sessionId.trim();
141819
142212
  if (normalized.length <= 8) {
@@ -141860,8 +142253,8 @@ function createTerminalWebSocketDiagnostics(runtimeLogger) {
141860
142253
  projectId,
141861
142254
  sessionCwdHint: toRedactedPathHint(sessionCwd),
141862
142255
  scopedRootHint: toRedactedPathHint(scopedRootDir),
141863
- sessionCwdBase: basename11(sessionCwd),
141864
- scopedRootBase: basename11(scopedRootDir)
142256
+ sessionCwdBase: basename12(sessionCwd),
142257
+ scopedRootBase: basename12(scopedRootDir)
141865
142258
  });
141866
142259
  },
141867
142260
  staleReconnect({ sessionId, idleMs, staleThresholdMs }) {
@@ -142003,9 +142396,9 @@ var init_auth_middleware = __esm({
142003
142396
 
142004
142397
  // ../dashboard/src/server.ts
142005
142398
  import express from "express";
142006
- import { randomUUID as randomUUID18 } from "node:crypto";
142007
- import { join as join47, dirname as dirname16 } from "node:path";
142008
- import { existsSync as existsSync30, readFileSync as readFileSync11 } from "node:fs";
142399
+ import { randomUUID as randomUUID19 } from "node:crypto";
142400
+ import { join as join47, dirname as dirname16, resolve as resolve25 } from "node:path";
142401
+ import { existsSync as existsSync31, readFileSync as readFileSync11 } from "node:fs";
142009
142402
  import { fileURLToPath as fileURLToPath4 } from "node:url";
142010
142403
  import { createSecureServer as createHttp2SecureServer } from "node:http2";
142011
142404
  function parseVersion2(version) {
@@ -142186,7 +142579,7 @@ function createServer(store, options) {
142186
142579
  getTerminalService(store.getRootDir());
142187
142580
  const isHeadless = options?.headless === true;
142188
142581
  const execDir = dirname16(process.execPath);
142189
- const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync30(join47(execDir, "client", "index.html")) ? join47(execDir, "client") : existsSync30(join47(__dirname2, "..", "dist", "client")) ? join47(__dirname2, "..", "dist", "client") : join47(__dirname2, "..", "client");
142582
+ const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync31(join47(execDir, "client", "index.html")) ? join47(execDir, "client") : existsSync31(join47(__dirname, "..", "dist", "client")) ? join47(__dirname, "..", "dist", "client") : join47(__dirname, "..", "client");
142190
142583
  if (!isHeadless) {
142191
142584
  app.get("/version.json", (_req, res) => {
142192
142585
  res.setHeader("Cache-Control", "no-store, max-age=0");
@@ -142849,7 +143242,7 @@ function setupBadgeWebSocket(app, server, store, options) {
142849
143242
  const dashboardApp = app;
142850
143243
  const wsManager = new WebSocketManager();
142851
143244
  const badgeSnapshots = /* @__PURE__ */ new Map();
142852
- const serverId = randomUUID18();
143245
+ const serverId = randomUUID19();
142853
143246
  const badgePubSub = options?.badgePubSub ?? createBadgePubSub({ sourceId: serverId });
142854
143247
  void badgePubSub.start();
142855
143248
  const scopedStores = /* @__PURE__ */ new Map();
@@ -142983,7 +143376,7 @@ function setupBadgeWebSocket(app, server, store, options) {
142983
143376
  const url = new URL(req.url || "", `http://${req.headers.host}`);
142984
143377
  const projectId = url.searchParams.get("projectId") ?? "default";
142985
143378
  void ensureScopedListeners(projectId);
142986
- wsManager.addClient(ws, randomUUID18(), projectId);
143379
+ wsManager.addClient(ws, randomUUID19(), projectId);
142987
143380
  });
142988
143381
  server.once("close", () => {
142989
143382
  for (const cleanup of scopedCleanups.values()) {
@@ -143023,7 +143416,7 @@ function snapshotsEqual(a, b) {
143023
143416
  if (a.issueInfo?.title !== b.issueInfo?.title) return false;
143024
143417
  return true;
143025
143418
  }
143026
- var __dirname2, PACKAGE_VERSION, CLI_PACKAGE_VERSION2, DEFAULT_AI_SESSION_TTL_MS, MIN_AI_SESSION_TTL_MS, MAX_AI_SESSION_TTL_MS, DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS, MIN_AI_SESSION_CLEANUP_INTERVAL_MS, MAX_AI_SESSION_CLEANUP_INTERVAL_MS, aiSessionCleanupIntervalHandle;
143419
+ var __dirname, PACKAGE_VERSION, CLI_PACKAGE_VERSION2, DEFAULT_AI_SESSION_TTL_MS, MIN_AI_SESSION_TTL_MS, MAX_AI_SESSION_TTL_MS, DEFAULT_AI_SESSION_CLEANUP_INTERVAL_MS, MIN_AI_SESSION_CLEANUP_INTERVAL_MS, MAX_AI_SESSION_CLEANUP_INTERVAL_MS, aiSessionCleanupIntervalHandle;
143027
143420
  var init_server = __esm({
143028
143421
  "../dashboard/src/server.ts"() {
143029
143422
  "use strict";
@@ -143049,10 +143442,10 @@ var init_server = __esm({
143049
143442
  init_dev_server_routes();
143050
143443
  init_auth_middleware();
143051
143444
  init_remote_auth();
143052
- __dirname2 = dirname16(fileURLToPath4(import.meta.url));
143445
+ __dirname = dirname16(fileURLToPath4(import.meta.url));
143053
143446
  PACKAGE_VERSION = (() => {
143054
143447
  try {
143055
- const packageJsonPath = join47(__dirname2, "..", "package.json");
143448
+ const packageJsonPath = join47(__dirname, "..", "package.json");
143056
143449
  const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
143057
143450
  if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
143058
143451
  return packageJson.version;
@@ -143063,10 +143456,18 @@ var init_server = __esm({
143063
143456
  })();
143064
143457
  CLI_PACKAGE_VERSION2 = (() => {
143065
143458
  try {
143066
- const packageJsonPath = join47(__dirname2, "..", "..", "cli", "package.json");
143067
- const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
143068
- if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
143069
- return packageJson.version;
143459
+ let cur = __dirname;
143460
+ for (let i = 0; i < 8; i++) {
143461
+ const pkgPath = resolve25(cur, "package.json");
143462
+ if (existsSync31(pkgPath)) {
143463
+ const parsed = JSON.parse(readFileSync11(pkgPath, "utf-8"));
143464
+ if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string" && parsed.version.length > 0) {
143465
+ return parsed.version;
143466
+ }
143467
+ }
143468
+ const parent2 = resolve25(cur, "..");
143469
+ if (parent2 === cur) break;
143470
+ cur = parent2;
143070
143471
  }
143071
143472
  } catch {
143072
143473
  }
@@ -143085,7 +143486,7 @@ var init_server = __esm({
143085
143486
  });
143086
143487
 
143087
143488
  // ../dashboard/src/skills-adapter.ts
143088
- import { access as access9, readFile as readFile22, writeFile as writeFile15, mkdir as mkdir17, readdir as readdir10, stat as stat10 } from "node:fs/promises";
143489
+ import { access as access9, readFile as readFile22, writeFile as writeFile16, mkdir as mkdir18, readdir as readdir10, stat as stat10 } from "node:fs/promises";
143089
143490
  import { join as join48, relative as relative11, dirname as dirname17 } from "node:path";
143090
143491
  async function pathExists(path5) {
143091
143492
  try {
@@ -143184,7 +143585,7 @@ function createSkillsAdapter(options) {
143184
143585
  const settingsPath = options.getSettingsPath(rootDir);
143185
143586
  const settingsDir = dirname17(settingsPath);
143186
143587
  if (!await pathExists(settingsDir)) {
143187
- await mkdir17(settingsDir, { recursive: true });
143588
+ await mkdir18(settingsDir, { recursive: true });
143188
143589
  }
143189
143590
  let settings = {};
143190
143591
  if (await pathExists(settingsPath)) {
@@ -143213,7 +143614,7 @@ function createSkillsAdapter(options) {
143213
143614
  }
143214
143615
  skills.push(`${prefix}${skillPath}`);
143215
143616
  settings.skills = skills;
143216
- await writeFile15(settingsPath, JSON.stringify(settings, null, 2));
143617
+ await writeFile16(settingsPath, JSON.stringify(settings, null, 2));
143217
143618
  return {
143218
143619
  settingsPath: "skills",
143219
143620
  pattern: `${prefix}${skillPath}`,
@@ -143250,7 +143651,7 @@ function createSkillsAdapter(options) {
143250
143651
  }
143251
143652
  pkgEntry.skills.push(`${prefix}${skillPath}`);
143252
143653
  settings.packages = packages;
143253
- await writeFile15(settingsPath, JSON.stringify(settings, null, 2));
143654
+ await writeFile16(settingsPath, JSON.stringify(settings, null, 2));
143254
143655
  return {
143255
143656
  settingsPath: "packages[].skills",
143256
143657
  pattern: `${prefix}${skillPath}`,
@@ -143725,7 +144126,7 @@ var init_task_lifecycle = __esm({
143725
144126
  // src/commands/port-prompt.ts
143726
144127
  import { createInterface } from "node:readline";
143727
144128
  function promptForPort(defaultPort = 4040, input = process.stdin) {
143728
- return new Promise((resolve36, reject2) => {
144129
+ return new Promise((resolve39, reject2) => {
143729
144130
  const rl = createInterface({
143730
144131
  input,
143731
144132
  output: process.stdout
@@ -143742,7 +144143,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
143742
144143
  if (trimmed === "") {
143743
144144
  process.removeListener("SIGINT", sigintHandler);
143744
144145
  rl.close();
143745
- resolve36(defaultPort);
144146
+ resolve39(defaultPort);
143746
144147
  return;
143747
144148
  }
143748
144149
  const port = parseInt(trimmed, 10);
@@ -143758,7 +144159,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
143758
144159
  }
143759
144160
  process.removeListener("SIGINT", sigintHandler);
143760
144161
  rl.close();
143761
- resolve36(port);
144162
+ resolve39(port);
143762
144163
  });
143763
144164
  };
143764
144165
  ask();
@@ -143771,16 +144172,16 @@ var init_port_prompt = __esm({
143771
144172
  });
143772
144173
 
143773
144174
  // src/commands/provider-settings.ts
143774
- import { existsSync as existsSync31, readFileSync as readFileSync12, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "node:fs";
143775
- import { join as join49, dirname as dirname18, basename as basename12 } from "node:path";
144175
+ import { existsSync as existsSync32, readFileSync as readFileSync12, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "node:fs";
144176
+ import { join as join49, dirname as dirname18, basename as basename13 } from "node:path";
143776
144177
  function siblingAgentDir2(agentDir, siblingRoot) {
143777
- if (basename12(agentDir) !== "agent") {
144178
+ if (basename13(agentDir) !== "agent") {
143778
144179
  return void 0;
143779
144180
  }
143780
144181
  return join49(dirname18(dirname18(agentDir)), siblingRoot, "agent");
143781
144182
  }
143782
144183
  function readJsonObject4(path5) {
143783
- if (!existsSync31(path5)) {
144184
+ if (!existsSync32(path5)) {
143784
144185
  return {};
143785
144186
  }
143786
144187
  try {
@@ -143812,7 +144213,7 @@ var init_provider_settings = __esm({
143812
144213
  });
143813
144214
 
143814
144215
  // src/commands/provider-auth.ts
143815
- import { existsSync as existsSync32, readFileSync as readFileSync13 } from "node:fs";
144216
+ import { existsSync as existsSync33, readFileSync as readFileSync13 } from "node:fs";
143816
144217
  import { getOAuthProvider as getOAuthProvider2 } from "@mariozechner/pi-ai/oauth";
143817
144218
  function getProviderDisplayName(providerId) {
143818
144219
  const knownProviderNames = new Map(
@@ -143941,7 +144342,7 @@ function createReadOnlyAuthFileStorage(authPaths) {
143941
144342
  const reload = () => {
143942
144343
  const nextCredentials = {};
143943
144344
  for (const authPath of authPaths) {
143944
- if (!existsSync32(authPath)) {
144345
+ if (!existsSync33(authPath)) {
143945
144346
  continue;
143946
144347
  }
143947
144348
  try {
@@ -143982,7 +144383,7 @@ var init_provider_auth = __esm({
143982
144383
 
143983
144384
  // src/commands/auth-paths.ts
143984
144385
  import { homedir as homedir7 } from "node:os";
143985
- import { existsSync as existsSync33, readFileSync as readFileSync14 } from "node:fs";
144386
+ import { existsSync as existsSync34, readFileSync as readFileSync14 } from "node:fs";
143986
144387
  import { join as join50 } from "node:path";
143987
144388
  function getFusionAgentDir3(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
143988
144389
  return join50(home, ".fusion", "agent");
@@ -144010,13 +144411,13 @@ function getLegacyModelsPaths2(home = process.env.HOME || process.env.USERPROFIL
144010
144411
  }
144011
144412
  function getModelRegistryModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
144012
144413
  const fusionModelsPath = getFusionModelsPath2(home);
144013
- if (existsSync33(fusionModelsPath)) {
144414
+ if (existsSync34(fusionModelsPath)) {
144014
144415
  return fusionModelsPath;
144015
144416
  }
144016
- return getLegacyModelsPaths2(home).find((modelsPath) => existsSync33(modelsPath)) ?? fusionModelsPath;
144417
+ return getLegacyModelsPaths2(home).find((modelsPath) => existsSync34(modelsPath)) ?? fusionModelsPath;
144017
144418
  }
144018
144419
  function readJsonObject5(path5) {
144019
- if (!existsSync33(path5)) {
144420
+ if (!existsSync34(path5)) {
144020
144421
  return {};
144021
144422
  }
144022
144423
  try {
@@ -144034,13 +144435,13 @@ function getPackageManagerAgentDir2(home = process.env.HOME || process.env.USERP
144034
144435
  const legacyAgentDir = getLegacyAgentDir(home);
144035
144436
  const fusionSettings = readJsonObject5(join50(fusionAgentDir, "settings.json"));
144036
144437
  const legacySettings = readJsonObject5(join50(legacyAgentDir, "settings.json"));
144037
- if (hasPackageManagerSettings3(fusionSettings) || !existsSync33(legacyAgentDir)) {
144438
+ if (hasPackageManagerSettings3(fusionSettings) || !existsSync34(legacyAgentDir)) {
144038
144439
  return fusionAgentDir;
144039
144440
  }
144040
144441
  if (hasPackageManagerSettings3(legacySettings)) {
144041
144442
  return legacyAgentDir;
144042
144443
  }
144043
- return existsSync33(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
144444
+ return existsSync34(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
144044
144445
  }
144045
144446
  var init_auth_paths2 = __esm({
144046
144447
  "src/commands/auth-paths.ts"() {
@@ -144049,8 +144450,8 @@ var init_auth_paths2 = __esm({
144049
144450
  });
144050
144451
 
144051
144452
  // src/project-context.ts
144052
- import { resolve as resolve23, dirname as dirname19 } from "node:path";
144053
- import { existsSync as existsSync34 } from "node:fs";
144453
+ import { resolve as resolve26, dirname as dirname19 } from "node:path";
144454
+ import { existsSync as existsSync35 } from "node:fs";
144054
144455
  async function resolveProject(projectNameFlag, cwd = process.cwd(), globalDir) {
144055
144456
  const central = new CentralCore(globalDir);
144056
144457
  await central.init();
@@ -144141,10 +144542,10 @@ async function clearDefaultProject(globalDir) {
144141
144542
  await globalStore.updateSettings(rest);
144142
144543
  }
144143
144544
  async function detectProjectFromCwd(cwd, central) {
144144
- let currentDir = resolve23(cwd);
144545
+ let currentDir = resolve26(cwd);
144145
144546
  while (true) {
144146
- const kbPath = resolve23(currentDir, ".fusion", "fusion.db");
144147
- if (existsSync34(kbPath)) {
144547
+ const kbPath = resolve26(currentDir, ".fusion", "fusion.db");
144548
+ if (existsSync35(kbPath)) {
144148
144549
  const project = await central.getProjectByPath(currentDir);
144149
144550
  if (project) {
144150
144551
  return project;
@@ -144199,7 +144600,7 @@ var init_project_context = __esm({
144199
144600
  // src/commands/claude-skills.ts
144200
144601
  import {
144201
144602
  cpSync,
144202
- existsSync as existsSync35,
144603
+ existsSync as existsSync36,
144203
144604
  lstatSync as lstatSync2,
144204
144605
  mkdirSync as mkdirSync7,
144205
144606
  readlinkSync,
@@ -144207,7 +144608,7 @@ import {
144207
144608
  symlinkSync,
144208
144609
  unlinkSync
144209
144610
  } from "node:fs";
144210
- import { dirname as dirname20, join as join51, resolve as resolve24 } from "node:path";
144611
+ import { dirname as dirname20, join as join51, resolve as resolve27 } from "node:path";
144211
144612
  import { fileURLToPath as fileURLToPath5 } from "node:url";
144212
144613
  function isPiClaudeCliConfigured(globalSettings) {
144213
144614
  if (!globalSettings || typeof globalSettings !== "object") {
@@ -144227,8 +144628,8 @@ function isPiClaudeCliConfigured(globalSettings) {
144227
144628
  }
144228
144629
  function resolveFusionSkillSource() {
144229
144630
  const here = fileURLToPath5(import.meta.url);
144230
- const candidate = resolve24(dirname20(here), "..", "..", "skill", FUSION_SKILL_NAME);
144231
- return existsSync35(candidate) ? candidate : null;
144631
+ const candidate = resolve27(dirname20(here), "..", "..", "skill", FUSION_SKILL_NAME);
144632
+ return existsSync36(candidate) ? candidate : null;
144232
144633
  }
144233
144634
  function installFusionSkillIntoProject(projectPath, options = {}) {
144234
144635
  const target = join51(projectPath, ".claude", "skills", FUSION_SKILL_NAME);
@@ -144246,18 +144647,18 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
144246
144647
  try {
144247
144648
  mkdirSync7(dirname20(target), { recursive: true });
144248
144649
  let replaced = false;
144249
- if (existsSync35(target) || isBrokenSymlink(target)) {
144650
+ if (existsSync36(target) || isBrokenSymlink(target)) {
144250
144651
  const stat12 = lstatSync2(target);
144251
144652
  if (stat12.isSymbolicLink()) {
144252
144653
  const current = safeReadlink(target);
144253
- if (current && resolve24(dirname20(target), current) === resolve24(source)) {
144654
+ if (current && resolve27(dirname20(target), current) === resolve27(source)) {
144254
144655
  return { outcome: "already-installed", target, source };
144255
144656
  }
144256
144657
  unlinkSync(target);
144257
144658
  replaced = true;
144258
144659
  } else {
144259
144660
  const skillMd = join51(target, "SKILL.md");
144260
- if (!existsSync35(skillMd)) {
144661
+ if (!existsSync36(skillMd)) {
144261
144662
  return {
144262
144663
  outcome: "failed",
144263
144664
  target,
@@ -144316,7 +144717,7 @@ function isBrokenSymlink(path5) {
144316
144717
  try {
144317
144718
  const stat12 = lstatSync2(path5);
144318
144719
  if (!stat12.isSymbolicLink()) return false;
144319
- return !existsSync35(path5);
144720
+ return !existsSync36(path5);
144320
144721
  } catch {
144321
144722
  return false;
144322
144723
  }
@@ -144413,16 +144814,16 @@ var init_claude_skills_runner = __esm({
144413
144814
  });
144414
144815
 
144415
144816
  // src/commands/claude-cli-extension.ts
144416
- import { existsSync as existsSync36, readFileSync as readFileSync15 } from "node:fs";
144817
+ import { existsSync as existsSync37, readFileSync as readFileSync15 } from "node:fs";
144417
144818
  import { createRequire as createRequire4 } from "node:module";
144418
- import { dirname as dirname21, resolve as resolve25 } from "node:path";
144819
+ import { dirname as dirname21, resolve as resolve28 } from "node:path";
144419
144820
  import { fileURLToPath as fileURLToPath6 } from "node:url";
144420
144821
  function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
144421
144822
  let pkgJsonPath;
144422
144823
  const here = dirname21(fileURLToPath6(moduleUrl));
144423
144824
  for (const rel of ["pi-claude-cli", "../pi-claude-cli", "../../pi-claude-cli"]) {
144424
- const candidate = resolve25(here, rel, "package.json");
144425
- if (existsSync36(candidate)) {
144825
+ const candidate = resolve28(here, rel, "package.json");
144826
+ if (existsSync37(candidate)) {
144426
144827
  pkgJsonPath = candidate;
144427
144828
  break;
144428
144829
  }
@@ -144457,8 +144858,8 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
144457
144858
  reason: "@fusion/pi-claude-cli pi.extensions[0] is not a valid path string"
144458
144859
  };
144459
144860
  }
144460
- const entryPath = resolve25(dirname21(pkgJsonPath), rawEntry);
144461
- if (!existsSync36(entryPath)) {
144861
+ const entryPath = resolve28(dirname21(pkgJsonPath), rawEntry);
144862
+ if (!existsSync37(entryPath)) {
144462
144863
  return {
144463
144864
  status: "missing-entry",
144464
144865
  reason: `@fusion/pi-claude-cli extension file not found at ${entryPath}`
@@ -144542,17 +144943,17 @@ var init_update_cache = __esm({
144542
144943
  });
144543
144944
 
144544
144945
  // src/commands/self-extension.ts
144545
- import { existsSync as existsSync37, readFileSync as readFileSync17 } from "node:fs";
144546
- import { dirname as dirname22, resolve as resolve26 } from "node:path";
144946
+ import { existsSync as existsSync38, readFileSync as readFileSync17 } from "node:fs";
144947
+ import { dirname as dirname22, resolve as resolve29 } from "node:path";
144547
144948
  import { fileURLToPath as fileURLToPath7 } from "node:url";
144548
144949
  function resolveSelfExtension() {
144549
144950
  const here = dirname22(fileURLToPath7(import.meta.url));
144550
144951
  let pkgDir;
144551
144952
  let cur = here;
144552
144953
  for (let i = 0; i < 5; i++) {
144553
- if (existsSync37(resolve26(cur, "package.json"))) {
144954
+ if (existsSync38(resolve29(cur, "package.json"))) {
144554
144955
  try {
144555
- const parsed = JSON.parse(readFileSync17(resolve26(cur, "package.json"), "utf-8"));
144956
+ const parsed = JSON.parse(readFileSync17(resolve29(cur, "package.json"), "utf-8"));
144556
144957
  if (parsed.name === "@runfusion/fusion") {
144557
144958
  pkgDir = cur;
144558
144959
  break;
@@ -144560,7 +144961,7 @@ function resolveSelfExtension() {
144560
144961
  } catch {
144561
144962
  }
144562
144963
  }
144563
- const parent2 = resolve26(cur, "..");
144964
+ const parent2 = resolve29(cur, "..");
144564
144965
  if (parent2 === cur) break;
144565
144966
  cur = parent2;
144566
144967
  }
@@ -144569,12 +144970,12 @@ function resolveSelfExtension() {
144569
144970
  }
144570
144971
  let pkgJson;
144571
144972
  try {
144572
- pkgJson = JSON.parse(readFileSync17(resolve26(pkgDir, "package.json"), "utf-8"));
144973
+ pkgJson = JSON.parse(readFileSync17(resolve29(pkgDir, "package.json"), "utf-8"));
144573
144974
  } catch (err) {
144574
144975
  return { status: "missing", reason: `Failed to read @runfusion/fusion package.json: ${err instanceof Error ? err.message : String(err)}` };
144575
144976
  }
144576
- const srcEntry = resolve26(pkgDir, "src", "extension.ts");
144577
- if (existsSync37(srcEntry)) {
144977
+ const srcEntry = resolve29(pkgDir, "src", "extension.ts");
144978
+ if (existsSync38(srcEntry)) {
144578
144979
  return { status: "ok", path: srcEntry, packageVersion: pkgJson.version ?? "unknown" };
144579
144980
  }
144580
144981
  const extensions = pkgJson.pi?.extensions;
@@ -144585,8 +144986,8 @@ function resolveSelfExtension() {
144585
144986
  if (typeof rawEntry !== "string" || rawEntry.length === 0) {
144586
144987
  return { status: "missing", reason: "@runfusion/fusion pi.extensions[0] is not a valid path string" };
144587
144988
  }
144588
- const entryPath = resolve26(pkgDir, rawEntry);
144589
- if (!existsSync37(entryPath)) {
144989
+ const entryPath = resolve29(pkgDir, rawEntry);
144990
+ if (!existsSync38(entryPath)) {
144590
144991
  return { status: "missing", reason: `@runfusion/fusion extension file not found at ${entryPath}` };
144591
144992
  }
144592
144993
  return { status: "ok", path: entryPath, packageVersion: pkgJson.version ?? "unknown" };
@@ -144645,21 +145046,21 @@ var init_state = __esm({
144645
145046
  });
144646
145047
 
144647
145048
  // src/commands/dashboard-tui/logo.ts
144648
- import { existsSync as existsSync38, readFileSync as readFileSync18 } from "node:fs";
144649
- import { dirname as dirname23, resolve as resolve27 } from "node:path";
145049
+ import { existsSync as existsSync39, readFileSync as readFileSync18 } from "node:fs";
145050
+ import { dirname as dirname23, resolve as resolve30 } from "node:path";
144650
145051
  import { fileURLToPath as fileURLToPath8 } from "node:url";
144651
145052
  function readFusionVersion() {
144652
145053
  try {
144653
145054
  let cur = dirname23(fileURLToPath8(import.meta.url));
144654
145055
  for (let i = 0; i < 6; i++) {
144655
- const pkgPath = resolve27(cur, "package.json");
144656
- if (existsSync38(pkgPath)) {
145056
+ const pkgPath = resolve30(cur, "package.json");
145057
+ if (existsSync39(pkgPath)) {
144657
145058
  const parsed = JSON.parse(readFileSync18(pkgPath, "utf-8"));
144658
145059
  if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {
144659
145060
  return parsed.version;
144660
145061
  }
144661
145062
  }
144662
- const parent2 = resolve27(cur, "..");
145063
+ const parent2 = resolve30(cur, "..");
144663
145064
  if (parent2 === cur) break;
144664
145065
  cur = parent2;
144665
145066
  }
@@ -144764,14 +145165,14 @@ async function copyToClipboard(text) {
144764
145165
  { cmd: "xsel", args: ["--clipboard", "--input"] }
144765
145166
  ];
144766
145167
  for (const { cmd, args } of candidates) {
144767
- const ok = await new Promise((resolve36) => {
145168
+ const ok = await new Promise((resolve39) => {
144768
145169
  try {
144769
145170
  const child = spawn11(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
144770
- child.once("error", () => resolve36(false));
144771
- child.once("close", (code) => resolve36(code === 0));
145171
+ child.once("error", () => resolve39(false));
145172
+ child.once("close", (code) => resolve39(code === 0));
144772
145173
  child.stdin.end(text);
144773
145174
  } catch {
144774
- resolve36(false);
145175
+ resolve39(false);
144775
145176
  }
144776
145177
  });
144777
145178
  if (ok) return true;
@@ -144932,9 +145333,9 @@ function SystemPanel({ state, isFocused }) {
144932
145333
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Uptime" }),
144933
145334
  /* @__PURE__ */ jsx(Text, { children: formatUptime(Date.now() - info.startTimeMs) })
144934
145335
  ] }),
144935
- info.authToken && /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, flexShrink: 1, children: [
145336
+ info.authToken && /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, flexShrink: 0, children: [
144936
145337
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Token" }),
144937
- /* @__PURE__ */ jsx(Text, { wrap: "truncate-end", color: "yellow", children: info.authToken })
145338
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: info.authToken })
144938
145339
  ] })
144939
145340
  ] }) });
144940
145341
  }
@@ -145275,7 +145676,7 @@ function StatusModeGrid({
145275
145676
  const rows = stdout?.rows ?? 24;
145276
145677
  const cols = stdout?.columns ?? 80;
145277
145678
  const middleHeight = Math.max(1, rows - 2);
145278
- const SYSTEM_HEIGHT = 4;
145679
+ const SYSTEM_HEIGHT = state.systemInfo?.authToken ? 5 : 4;
145279
145680
  const bottomShare = Math.min(10, Math.max(6, Math.floor(middleHeight * 0.35)));
145280
145681
  const logsShare = Math.max(1, middleHeight - SYSTEM_HEIGHT - bottomShare);
145281
145682
  const logsAvailableRows = Math.max(1, logsShare - 4);
@@ -145284,7 +145685,7 @@ function StatusModeGrid({
145284
145685
  tuiDebug("StatusModeGrid", { cols, rows, middleHeight, logsShare, bottomShare, focused, wideLayout });
145285
145686
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [
145286
145687
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children: [
145287
- /* @__PURE__ */ jsx(Box, { height: 4, flexShrink: 0, overflow: "hidden", children: /* @__PURE__ */ jsx(SystemPanel, { state, isFocused: focused === "system" }) }),
145688
+ /* @__PURE__ */ jsx(Box, { height: SYSTEM_HEIGHT, flexShrink: 0, overflow: "hidden", children: /* @__PURE__ */ jsx(SystemPanel, { state, isFocused: focused === "system" }) }),
145288
145689
  wideLayout ? /* @__PURE__ */ jsxs(Fragment, { children: [
145289
145690
  /* @__PURE__ */ jsxs(Box, { flexGrow: 1, flexShrink: 0, flexDirection: "row", overflow: "hidden", children: [
145290
145691
  /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: "30%", flexShrink: 0, overflow: "hidden", children: /* @__PURE__ */ jsx(StatsPanel, { state, isFocused: focused === "stats" }) }),
@@ -149904,8 +150305,8 @@ async function runDashboard(port, opts = {}) {
149904
150305
  try {
149905
150306
  const updateCheckEnabled = await Promise.race([
149906
150307
  isUpdateCheckEnabled(),
149907
- new Promise((resolve36) => {
149908
- setTimeout(() => resolve36(false), 3e3);
150308
+ new Promise((resolve39) => {
150309
+ setTimeout(() => resolve39(false), 3e3);
149909
150310
  })
149910
150311
  ]);
149911
150312
  if (!updateCheckEnabled) {
@@ -151300,8 +151701,8 @@ async function runServe(port, opts = {}) {
151300
151701
  https: loadTlsCredentialsFromEnv()
151301
151702
  });
151302
151703
  const server = app.listen(selectedPort, selectedHost);
151303
- await new Promise((resolve36, reject2) => {
151304
- server.once("listening", resolve36);
151704
+ await new Promise((resolve39, reject2) => {
151705
+ server.once("listening", resolve39);
151305
151706
  server.once("error", reject2);
151306
151707
  });
151307
151708
  const actualPort = server.address().port;
@@ -151819,8 +152220,8 @@ async function runDaemon(opts = {}) {
151819
152220
  https: loadTlsCredentialsFromEnv()
151820
152221
  });
151821
152222
  const server = app.listen(selectedPort, selectedHost);
151822
- await new Promise((resolve36, reject2) => {
151823
- server.once("listening", resolve36);
152223
+ await new Promise((resolve39, reject2) => {
152224
+ server.once("listening", resolve39);
151824
152225
  server.once("error", reject2);
151825
152226
  });
151826
152227
  const actualPort = server.address().port;
@@ -151934,7 +152335,7 @@ import { once as once2 } from "node:events";
151934
152335
  import { join as join56 } from "node:path";
151935
152336
  import { createRequire as createRequire5 } from "node:module";
151936
152337
  function runCommand(command, args, cwd) {
151937
- return new Promise((resolve36, reject2) => {
152338
+ return new Promise((resolve39, reject2) => {
151938
152339
  const child = spawn13(command, args, {
151939
152340
  cwd,
151940
152341
  stdio: "inherit",
@@ -151943,7 +152344,7 @@ function runCommand(command, args, cwd) {
151943
152344
  child.on("error", (error) => reject2(error));
151944
152345
  child.on("exit", (code) => {
151945
152346
  if (code === 0) {
151946
- resolve36();
152347
+ resolve39();
151947
152348
  return;
151948
152349
  }
151949
152350
  reject2(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
@@ -151986,8 +152387,8 @@ async function startDashboardRuntime(rootDir, paused) {
151986
152387
  };
151987
152388
  }
151988
152389
  async function closeDashboardRuntime(runtime) {
151989
- await new Promise((resolve36) => {
151990
- runtime.server.close(() => resolve36());
152390
+ await new Promise((resolve39) => {
152391
+ runtime.server.close(() => resolve39());
151991
152392
  });
151992
152393
  runtime.store.close();
151993
152394
  }
@@ -152095,7 +152496,7 @@ __export(task_exports, {
152095
152496
  runTaskUpdate: () => runTaskUpdate
152096
152497
  });
152097
152498
  import { createInterface as createInterface3 } from "node:readline/promises";
152098
- import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync39, readFileSync as readFileSync19 } from "node:fs";
152499
+ import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync40, readFileSync as readFileSync19 } from "node:fs";
152099
152500
  import { join as join57 } from "node:path";
152100
152501
  function asLocalProjectContext(store) {
152101
152502
  const cwd = process.cwd();
@@ -152216,10 +152617,10 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
152216
152617
  console.log(` Path: .fusion/tasks/${task.id}/`);
152217
152618
  if (attachFiles && attachFiles.length > 0) {
152218
152619
  const { readFile: readFile24 } = await import("node:fs/promises");
152219
- const { basename: basename16, extname: extname2, resolve: resolve36 } = await import("node:path");
152620
+ const { basename: basename17, extname: extname2, resolve: resolve39 } = await import("node:path");
152220
152621
  for (const filePath of attachFiles) {
152221
- const resolvedPath = resolve36(filePath);
152222
- const filename = basename16(resolvedPath);
152622
+ const resolvedPath = resolve39(filePath);
152623
+ const filename = basename17(resolvedPath);
152223
152624
  const ext = extname2(filename).toLowerCase();
152224
152625
  const mimeType = MIME_TYPES[ext];
152225
152626
  if (!mimeType) {
@@ -152353,7 +152754,7 @@ async function runTaskLogs(id, options = {}, projectName) {
152353
152754
  if (options.follow) {
152354
152755
  const projectPath = projectContext?.projectPath ?? process.cwd();
152355
152756
  const logPath = join57(projectPath, ".fusion", "tasks", id, "agent.log");
152356
- if (!existsSync39(logPath)) {
152757
+ if (!existsSync40(logPath)) {
152357
152758
  console.log(`
152358
152759
  Waiting for log file to be created...`);
152359
152760
  }
@@ -152511,10 +152912,10 @@ async function runTaskMerge(id, projectName) {
152511
152912
  }
152512
152913
  async function runTaskAttach(id, filePath, projectName) {
152513
152914
  const { readFile: readFile24 } = await import("node:fs/promises");
152514
- const { basename: basename16, extname: extname2 } = await import("node:path");
152515
- const { resolve: resolve36 } = await import("node:path");
152516
- const resolvedPath = resolve36(filePath);
152517
- const filename = basename16(resolvedPath);
152915
+ const { basename: basename17, extname: extname2 } = await import("node:path");
152916
+ const { resolve: resolve39 } = await import("node:path");
152917
+ const resolvedPath = resolve39(filePath);
152918
+ const filename = basename17(resolvedPath);
152518
152919
  const ext = extname2(filename).toLowerCase();
152519
152920
  const mimeType = MIME_TYPES[ext];
152520
152921
  if (!mimeType) {
@@ -153044,12 +153445,12 @@ async function promptText(question) {
153044
153445
  console.log(" (Enter your response. Type DONE on its own line when finished):\n");
153045
153446
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
153046
153447
  const lines = [];
153047
- return new Promise((resolve36) => {
153448
+ return new Promise((resolve39) => {
153048
153449
  const askLine = () => {
153049
153450
  rl.question(" ").then((line) => {
153050
153451
  if (line.trim() === "DONE") {
153051
153452
  rl.close();
153052
- resolve36(lines.join("\n"));
153453
+ resolve39(lines.join("\n"));
153053
153454
  } else {
153054
153455
  lines.push(line);
153055
153456
  askLine();
@@ -153616,8 +154017,8 @@ var settings_export_exports = {};
153616
154017
  __export(settings_export_exports, {
153617
154018
  runSettingsExport: () => runSettingsExport
153618
154019
  });
153619
- import { writeFile as writeFile16 } from "node:fs/promises";
153620
- import { resolve as resolve28, join as join58 } from "node:path";
154020
+ import { writeFile as writeFile17 } from "node:fs/promises";
154021
+ import { resolve as resolve31, join as join58 } from "node:path";
153621
154022
  async function runSettingsExport(options = {}) {
153622
154023
  const scope = options.scope ?? "both";
153623
154024
  const project = options.projectName ? await resolveProject(options.projectName) : void 0;
@@ -153628,13 +154029,13 @@ async function runSettingsExport(options = {}) {
153628
154029
  const exportData = await exportSettings(store, { scope });
153629
154030
  let targetPath;
153630
154031
  if (outputPath) {
153631
- targetPath = resolve28(outputPath);
154032
+ targetPath = resolve31(outputPath);
153632
154033
  } else {
153633
154034
  const filename = generateExportFilename();
153634
154035
  targetPath = join58(process.cwd(), filename);
153635
154036
  }
153636
154037
  const jsonContent = JSON.stringify(exportData, null, 2);
153637
- await writeFile16(targetPath, jsonContent);
154038
+ await writeFile17(targetPath, jsonContent);
153638
154039
  console.log();
153639
154040
  console.log(` \u2713 Settings exported to ${targetPath}`);
153640
154041
  const parts = [];
@@ -153677,8 +154078,8 @@ var settings_import_exports = {};
153677
154078
  __export(settings_import_exports, {
153678
154079
  runSettingsImport: () => runSettingsImport
153679
154080
  });
153680
- import { existsSync as existsSync40 } from "node:fs";
153681
- import { resolve as resolve29 } from "node:path";
154081
+ import { existsSync as existsSync41 } from "node:fs";
154082
+ import { resolve as resolve32 } from "node:path";
153682
154083
  async function runSettingsImport(filePath, options = {}) {
153683
154084
  const scope = options.scope ?? "both";
153684
154085
  const project = options.projectName ? await resolveProject(options.projectName) : void 0;
@@ -153687,8 +154088,8 @@ async function runSettingsImport(filePath, options = {}) {
153687
154088
  const merge = options.merge ?? true;
153688
154089
  const skipConfirm = options.yes ?? false;
153689
154090
  try {
153690
- const resolvedPath = resolve29(filePath);
153691
- if (!existsSync40(resolvedPath)) {
154091
+ const resolvedPath = resolve32(filePath);
154092
+ if (!existsSync41(resolvedPath)) {
153692
154093
  console.error(`Error: File not found: ${filePath}`);
153693
154094
  process.exit(1);
153694
154095
  }
@@ -154161,8 +154562,8 @@ var init_backup2 = __esm({
154161
154562
  });
154162
154563
 
154163
154564
  // src/project-resolver.ts
154164
- import { existsSync as existsSync41, statSync as statSync7 } from "node:fs";
154165
- import { dirname as dirname24, resolve as resolve30, normalize as normalize5 } from "node:path";
154565
+ import { existsSync as existsSync42, statSync as statSync7 } from "node:fs";
154566
+ import { dirname as dirname24, resolve as resolve33, normalize as normalize5 } from "node:path";
154166
154567
  import { createInterface as createInterface5 } from "node:readline/promises";
154167
154568
  async function getCentralCore() {
154168
154569
  if (!centralCoreInstance) {
@@ -154179,10 +154580,10 @@ async function getProjectManager() {
154179
154580
  return projectManagerInstance;
154180
154581
  }
154181
154582
  function findKbDir(startPath) {
154182
- let current = resolve30(startPath);
154583
+ let current = resolve33(startPath);
154183
154584
  for (let i = 0; i < 100; i++) {
154184
- const kbPath = resolve30(current, ".fusion");
154185
- if (existsSync41(kbPath) && statSync7(kbPath).isDirectory()) {
154585
+ const kbPath = resolve33(current, ".fusion");
154586
+ if (existsSync42(kbPath) && statSync7(kbPath).isDirectory()) {
154186
154587
  return current;
154187
154588
  }
154188
154589
  const parent2 = dirname24(current);
@@ -154237,7 +154638,7 @@ async function resolveProject2(options = {}) {
154237
154638
  { searchedName: options.project, availableProjects: projects.map((p) => p.name) }
154238
154639
  );
154239
154640
  }
154240
- if (!existsSync41(match.path)) {
154641
+ if (!existsSync42(match.path)) {
154241
154642
  throw new ProjectResolutionError(
154242
154643
  `Project "${match.name}" is registered but the directory no longer exists: ${match.path}
154243
154644
 
@@ -154248,14 +154649,14 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
154248
154649
  }
154249
154650
  return createResolvedProject(match);
154250
154651
  }
154251
- const cwd = options.cwd ? resolve30(options.cwd) : process.cwd();
154652
+ const cwd = options.cwd ? resolve33(options.cwd) : process.cwd();
154252
154653
  const fusionDir = findKbDir(cwd);
154253
154654
  if (fusionDir) {
154254
154655
  const allProjects2 = await central.listProjects();
154255
154656
  const normalizedKbDir = normalize5(fusionDir);
154256
154657
  const match = allProjects2.find((p) => normalize5(p.path) === normalizedKbDir);
154257
154658
  if (match) {
154258
- if (!existsSync41(match.path)) {
154659
+ if (!existsSync42(match.path)) {
154259
154660
  throw new ProjectResolutionError(
154260
154661
  `Project "${match.name}" is registered but the directory no longer exists: ${match.path}
154261
154662
 
@@ -154320,7 +154721,7 @@ Run \`fn project add ` + fusionDir + "` to register it, or use --project <name>.
154320
154721
  }
154321
154722
  if (allProjects.length === 1) {
154322
154723
  const project = allProjects[0];
154323
- if (!existsSync41(project.path)) {
154724
+ if (!existsSync42(project.path)) {
154324
154725
  throw new ProjectResolutionError(
154325
154726
  `The only registered project "${project.name}" has a missing directory: ${project.path}
154326
154727
 
@@ -154760,15 +155161,15 @@ __export(project_exports, {
154760
155161
  runProjectSetDefault: () => runProjectSetDefault,
154761
155162
  runProjectShow: () => runProjectShow
154762
155163
  });
154763
- import { resolve as resolve31, isAbsolute as isAbsolute16, relative as relative12, basename as basename13 } from "node:path";
154764
- import { existsSync as existsSync42, statSync as statSync8 } from "node:fs";
155164
+ import { resolve as resolve34, isAbsolute as isAbsolute16, relative as relative12, basename as basename14 } from "node:path";
155165
+ import { existsSync as existsSync43, statSync as statSync8 } from "node:fs";
154765
155166
  import { createInterface as createInterface7 } from "node:readline/promises";
154766
155167
  function formatDisplayPath(projectPath) {
154767
155168
  const rel = relative12(process.cwd(), projectPath);
154768
155169
  if (rel && !rel.startsWith("..") && rel !== "") {
154769
155170
  return rel;
154770
155171
  }
154771
- return basename13(projectPath) || ".";
155172
+ return basename14(projectPath) || ".";
154772
155173
  }
154773
155174
  function formatLastActivity2(timestamp) {
154774
155175
  if (!timestamp) return "never";
@@ -154889,8 +155290,8 @@ async function runProjectAdd(name, path5, options = {}) {
154889
155290
  const pathInput = await rl.question(` Project path [${defaultPath}]: `);
154890
155291
  projectPath = pathInput.trim() || defaultPath;
154891
155292
  }
154892
- const absolutePath2 = isAbsolute16(projectPath) ? projectPath : resolve31(process.cwd(), projectPath);
154893
- if (!existsSync42(absolutePath2)) {
155293
+ const absolutePath2 = isAbsolute16(projectPath) ? projectPath : resolve34(process.cwd(), projectPath);
155294
+ if (!existsSync43(absolutePath2)) {
154894
155295
  console.error(`
154895
155296
  \u2717 Path does not exist: ${projectPath}`);
154896
155297
  rl.close();
@@ -154902,8 +155303,8 @@ async function runProjectAdd(name, path5, options = {}) {
154902
155303
  rl.close();
154903
155304
  process.exit(1);
154904
155305
  }
154905
- const kbDbPath2 = resolve31(absolutePath2, ".fusion", "fusion.db");
154906
- if (!existsSync42(kbDbPath2) && !options.force) {
155306
+ const kbDbPath2 = resolve34(absolutePath2, ".fusion", "fusion.db");
155307
+ if (!existsSync43(kbDbPath2) && !options.force) {
154907
155308
  console.log(`
154908
155309
  No fn project found at ${formatDisplayPath(absolutePath2)}`);
154909
155310
  const init = await rl.question(" Initialize fn here first? [Y/n] ");
@@ -154918,7 +155319,7 @@ async function runProjectAdd(name, path5, options = {}) {
154918
155319
  }
154919
155320
  }
154920
155321
  if (!projectName) {
154921
- const suggested = basename13(absolutePath2);
155322
+ const suggested = basename14(absolutePath2);
154922
155323
  projectName = await rl.question(` Project name [${suggested}]: `);
154923
155324
  projectName = projectName.trim() || suggested;
154924
155325
  }
@@ -154934,8 +155335,8 @@ async function runProjectAdd(name, path5, options = {}) {
154934
155335
  console.error(" Name must be 1-64 characters and contain only: a-z, A-Z, 0-9, _, -\n");
154935
155336
  process.exit(1);
154936
155337
  }
154937
- const absolutePath = isAbsolute16(projectPath) ? projectPath : resolve31(process.cwd(), projectPath);
154938
- if (!existsSync42(absolutePath)) {
155338
+ const absolutePath = isAbsolute16(projectPath) ? projectPath : resolve34(process.cwd(), projectPath);
155339
+ if (!existsSync43(absolutePath)) {
154939
155340
  console.error(`
154940
155341
  \u2717 Path does not exist: ${projectPath}
154941
155342
  `);
@@ -154947,8 +155348,8 @@ async function runProjectAdd(name, path5, options = {}) {
154947
155348
  `);
154948
155349
  process.exit(1);
154949
155350
  }
154950
- const kbDbPath = resolve31(absolutePath, ".fusion", "fusion.db");
154951
- if (!existsSync42(kbDbPath) && !options.force) {
155351
+ const kbDbPath = resolve34(absolutePath, ".fusion", "fusion.db");
155352
+ if (!existsSync43(kbDbPath) && !options.force) {
154952
155353
  console.error(`
154953
155354
  \u2717 No fn project found at ${formatDisplayPath(absolutePath)}`);
154954
155355
  console.error(" Run `fn init` first to initialize the project.\n");
@@ -155204,9 +155605,9 @@ var init_project = __esm({
155204
155605
  });
155205
155606
 
155206
155607
  // src/commands/skill-installation.ts
155207
- import { cpSync as cpSync2, existsSync as existsSync43, mkdirSync as mkdirSync8 } from "node:fs";
155608
+ import { cpSync as cpSync2, existsSync as existsSync44, mkdirSync as mkdirSync8 } from "node:fs";
155208
155609
  import { homedir as homedir8 } from "node:os";
155209
- import { dirname as dirname25, join as join59, resolve as resolve32 } from "node:path";
155610
+ import { dirname as dirname25, join as join59, resolve as resolve35 } from "node:path";
155210
155611
  import { fileURLToPath as fileURLToPath9 } from "node:url";
155211
155612
  function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.env.USERPROFILE || homedir8()) {
155212
155613
  return [
@@ -155217,8 +155618,8 @@ function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.e
155217
155618
  }
155218
155619
  function resolveBundledFusionSkillSource() {
155219
155620
  const here = fileURLToPath9(import.meta.url);
155220
- const source = resolve32(dirname25(here), "..", "..", "skill", FUSION_SKILL_NAME2);
155221
- return existsSync43(source) ? source : null;
155621
+ const source = resolve35(dirname25(here), "..", "..", "skill", FUSION_SKILL_NAME2);
155622
+ return existsSync44(source) ? source : null;
155222
155623
  }
155223
155624
  function installBundledFusionSkill(options = {}) {
155224
155625
  const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource();
@@ -155236,7 +155637,7 @@ function installBundledFusionSkill(options = {}) {
155236
155637
  }
155237
155638
  const results = targets.map((target) => {
155238
155639
  try {
155239
- if (existsSync43(target.targetDir)) {
155640
+ if (existsSync44(target.targetDir)) {
155240
155641
  return {
155241
155642
  client: target.client,
155242
155643
  targetDir: target.targetDir,
@@ -155275,15 +155676,15 @@ var init_exports = {};
155275
155676
  __export(init_exports, {
155276
155677
  runInit: () => runInit
155277
155678
  });
155278
- import { existsSync as existsSync44, mkdirSync as mkdirSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync20 } from "node:fs";
155279
- import { join as join60, resolve as resolve33, basename as basename14 } from "node:path";
155679
+ import { existsSync as existsSync45, mkdirSync as mkdirSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync20 } from "node:fs";
155680
+ import { join as join60, resolve as resolve36, basename as basename15 } from "node:path";
155280
155681
  import { exec as exec11 } from "node:child_process";
155281
155682
  import { promisify as promisify16 } from "node:util";
155282
155683
  async function runInit(options = {}) {
155283
- const cwd = options.path ? resolve33(options.path) : process.cwd();
155684
+ const cwd = options.path ? resolve36(options.path) : process.cwd();
155284
155685
  const fusionDir = join60(cwd, ".fusion");
155285
155686
  const dbPath = join60(fusionDir, "fusion.db");
155286
- if (existsSync44(fusionDir) && existsSync44(dbPath)) {
155687
+ if (existsSync45(fusionDir) && existsSync45(dbPath)) {
155287
155688
  const central2 = new CentralCore();
155288
155689
  await central2.init();
155289
155690
  const existing = await central2.getProjectByPath(cwd);
@@ -155308,7 +155709,7 @@ async function runInit(options = {}) {
155308
155709
  const projectName = options.name ?? await detectProjectName(cwd);
155309
155710
  console.log(`Initializing fn project: "${projectName}"`);
155310
155711
  console.log(` Path: ${cwd}`);
155311
- if (!existsSync44(fusionDir)) {
155712
+ if (!existsSync45(fusionDir)) {
155312
155713
  mkdirSync9(fusionDir, { recursive: true });
155313
155714
  console.log(` \u2713 Created .fusion/ directory`);
155314
155715
  }
@@ -155321,7 +155722,7 @@ async function runInit(options = {}) {
155321
155722
  }
155322
155723
  await addLocalStorageToGitignore(cwd);
155323
155724
  await warnIfQmdMissing();
155324
- if (!existsSync44(dbPath)) {
155725
+ if (!existsSync45(dbPath)) {
155325
155726
  const sqliteHeader = Buffer.from([
155326
155727
  83,
155327
155728
  81,
@@ -155389,8 +155790,8 @@ async function runInit(options = {}) {
155389
155790
  }
155390
155791
  }
155391
155792
  async function detectProjectName(dir2) {
155392
- if (!existsSync44(join60(dir2, ".git"))) {
155393
- return basename14(dir2) || "my-project";
155793
+ if (!existsSync45(join60(dir2, ".git"))) {
155794
+ return basename15(dir2) || "my-project";
155394
155795
  }
155395
155796
  try {
155396
155797
  const { stdout: remoteUrl } = await execAsync11("git remote get-url origin", {
@@ -155406,12 +155807,12 @@ async function detectProjectName(dir2) {
155406
155807
  }
155407
155808
  } catch {
155408
155809
  }
155409
- return basename14(dir2) || "my-project";
155810
+ return basename15(dir2) || "my-project";
155410
155811
  }
155411
155812
  async function addLocalStorageToGitignore(cwd) {
155412
155813
  const gitignorePath = join60(cwd, ".gitignore");
155413
155814
  let content = "";
155414
- if (existsSync44(gitignorePath)) {
155815
+ if (existsSync45(gitignorePath)) {
155415
155816
  try {
155416
155817
  content = readFileSync20(gitignorePath, "utf-8");
155417
155818
  } catch {
@@ -155453,7 +155854,7 @@ async function initializeGitRepo(cwd) {
155453
155854
  await ensureGitConfig(cwd, "user.name", "Fusion");
155454
155855
  await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
155455
155856
  const gitkeepPath = join60(cwd, ".gitkeep");
155456
- if (!existsSync44(gitkeepPath)) {
155857
+ if (!existsSync45(gitkeepPath)) {
155457
155858
  writeFileSync3(gitkeepPath, "\n");
155458
155859
  }
155459
155860
  await execAsync11("git add .gitkeep", { cwd, timeout: 1e4 });
@@ -155591,8 +155992,8 @@ var agent_import_exports = {};
155591
155992
  __export(agent_import_exports, {
155592
155993
  runAgentImport: () => runAgentImport
155593
155994
  });
155594
- import { existsSync as existsSync45, mkdirSync as mkdirSync10, readFileSync as readFileSync21, statSync as statSync9, writeFileSync as writeFileSync4 } from "node:fs";
155595
- import { resolve as resolve34 } from "node:path";
155995
+ import { existsSync as existsSync46, mkdirSync as mkdirSync10, readFileSync as readFileSync21, statSync as statSync9, writeFileSync as writeFileSync4 } from "node:fs";
155996
+ import { resolve as resolve37 } from "node:path";
155596
155997
  function slugifyPathSegment(input) {
155597
155998
  if (!input || typeof input !== "string") {
155598
155999
  return "unnamed";
@@ -155641,16 +156042,16 @@ async function importSkillsToProject(projectPath, skills, companySlug, dryRun) {
155641
156042
  errors: []
155642
156043
  };
155643
156044
  const companyDir = slugifyPathSegment(companySlug ?? "unknown-company");
155644
- const baseSkillsDir = resolve34(projectPath, "skills", "imported", companyDir);
156045
+ const baseSkillsDir = resolve37(projectPath, "skills", "imported", companyDir);
155645
156046
  for (const skill of skills) {
155646
156047
  if (!skill.name || typeof skill.name !== "string" || skill.name.trim().length === 0) {
155647
156048
  result.errors.push({ name: "(unnamed)", error: "Skill is missing required 'name' field" });
155648
156049
  continue;
155649
156050
  }
155650
156051
  const skillSlug = slugifyPathSegment(skill.name);
155651
- const skillDir = resolve34(baseSkillsDir, skillSlug);
155652
- const skillPath = resolve34(skillDir, "SKILL.md");
155653
- if (existsSync45(skillPath)) {
156052
+ const skillDir = resolve37(baseSkillsDir, skillSlug);
156053
+ const skillPath = resolve37(skillDir, "SKILL.md");
156054
+ if (existsSync46(skillPath)) {
155654
156055
  result.skipped.push(skill.name);
155655
156056
  continue;
155656
156057
  }
@@ -155722,8 +156123,8 @@ function isArchivePath(path5) {
155722
156123
  async function runAgentImport(source, options) {
155723
156124
  const dryRun = options?.dryRun ?? false;
155724
156125
  const skipExisting = options?.skipExisting ?? false;
155725
- const sourcePath = resolve34(source);
155726
- if (!existsSync45(sourcePath)) {
156126
+ const sourcePath = resolve37(source);
156127
+ if (!existsSync46(sourcePath)) {
155727
156128
  console.error(`Path not found: ${sourcePath}`);
155728
156129
  process.exit(1);
155729
156130
  }
@@ -155861,7 +156262,7 @@ var agent_export_exports = {};
155861
156262
  __export(agent_export_exports, {
155862
156263
  runAgentExport: () => runAgentExport
155863
156264
  });
155864
- import { resolve as resolve35 } from "node:path";
156265
+ import { resolve as resolve38 } from "node:path";
155865
156266
  async function getProjectPath4(projectName) {
155866
156267
  if (projectName) {
155867
156268
  const context = await resolveProject(projectName);
@@ -155899,7 +156300,7 @@ async function runAgentExport(outputDir, options) {
155899
156300
  console.error("No agents found to export");
155900
156301
  process.exit(1);
155901
156302
  }
155902
- const result = await exportAgentsToDirectory(agents, resolve35(outputDir), {
156303
+ const result = await exportAgentsToDirectory(agents, resolve38(outputDir), {
155903
156304
  companyName: options?.companyName,
155904
156305
  companySlug: options?.companySlug
155905
156306
  });
@@ -156118,7 +156519,7 @@ __export(plugin_exports, {
156118
156519
  runPluginList: () => runPluginList,
156119
156520
  runPluginUninstall: () => runPluginUninstall
156120
156521
  });
156121
- import { existsSync as existsSync46 } from "node:fs";
156522
+ import { existsSync as existsSync47 } from "node:fs";
156122
156523
  import { join as join61 } from "node:path";
156123
156524
  import { readFile as readFile23 } from "node:fs/promises";
156124
156525
  import * as readline from "node:readline";
@@ -156158,7 +156559,7 @@ async function createPluginLoader(pluginStore, projectName) {
156158
156559
  }
156159
156560
  async function loadManifestFromPath(pluginPath) {
156160
156561
  const manifestPath = join61(pluginPath, "manifest.json");
156161
- if (!existsSync46(manifestPath)) {
156562
+ if (!existsSync47(manifestPath)) {
156162
156563
  throw new Error(`Plugin manifest not found at: ${manifestPath}`);
156163
156564
  }
156164
156565
  const content = await readFile23(manifestPath, "utf-8");
@@ -156216,7 +156617,7 @@ async function runPluginInstall(source, options) {
156216
156617
  console.error("Please provide a local path to the plugin directory.");
156217
156618
  process.exit(1);
156218
156619
  }
156219
- if (!existsSync46(source)) {
156620
+ if (!existsSync47(source)) {
156220
156621
  console.error(`Plugin path does not exist: ${source}`);
156221
156622
  process.exit(1);
156222
156623
  }
@@ -156261,14 +156662,14 @@ async function runPluginUninstall(id, options) {
156261
156662
  console.log(` Uninstall "${plugin4.name}"?`);
156262
156663
  console.log(` This will stop and remove the plugin.`);
156263
156664
  console.log();
156264
- const response = await new Promise((resolve36) => {
156665
+ const response = await new Promise((resolve39) => {
156265
156666
  const rl = readline.createInterface({
156266
156667
  input: process.stdin,
156267
156668
  output: process.stdout
156268
156669
  });
156269
156670
  rl.question(" Continue? [y/N] ", (answer) => {
156270
156671
  rl.close();
156271
- resolve36(answer.toLowerCase());
156672
+ resolve39(answer.toLowerCase());
156272
156673
  });
156273
156674
  });
156274
156675
  if (response !== "y" && response !== "yes") {
@@ -156348,7 +156749,7 @@ var plugin_scaffold_exports = {};
156348
156749
  __export(plugin_scaffold_exports, {
156349
156750
  runPluginCreate: () => runPluginCreate
156350
156751
  });
156351
- import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as existsSync47 } from "node:fs";
156752
+ import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as existsSync48 } from "node:fs";
156352
156753
  import { join as join62 } from "node:path";
156353
156754
  function toTitleCase(str) {
156354
156755
  return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
@@ -156483,7 +156884,7 @@ async function runPluginCreate(name, options) {
156483
156884
  }
156484
156885
  const targetDir = options?.output ?? name;
156485
156886
  const targetPath = join62(process.cwd(), targetDir);
156486
- if (existsSync47(targetPath)) {
156887
+ if (existsSync48(targetPath)) {
156487
156888
  console.error(`Error: Directory '${targetDir}' already exists.`);
156488
156889
  console.error("Please choose a different name or remove the existing directory.");
156489
156890
  process.exit(1);
@@ -156616,9 +157017,9 @@ async function runSkillsInstall(args, options) {
156616
157017
  stdio: "inherit",
156617
157018
  shell: true
156618
157019
  });
156619
- const exitCode = await new Promise((resolve36, reject2) => {
157020
+ const exitCode = await new Promise((resolve39, reject2) => {
156620
157021
  child.on("exit", (code) => {
156621
- resolve36(code ?? 1);
157022
+ resolve39(code ?? 1);
156622
157023
  });
156623
157024
  child.on("error", (err) => {
156624
157025
  reject2(err);
@@ -156649,8 +157050,8 @@ __export(native_patch_exports, {
156649
157050
  isTerminalAvailable: () => isTerminalAvailable,
156650
157051
  setupNativeResolution: () => setupNativeResolution
156651
157052
  });
156652
- import { join as join63, basename as basename15, dirname as dirname26 } from "node:path";
156653
- import { existsSync as existsSync48, copyFileSync, mkdirSync as mkdirSync12, symlinkSync as symlinkSync2, rmSync as rmSync5, lstatSync as lstatSync3, readlinkSync as readlinkSync2 } from "node:fs";
157053
+ import { join as join63, basename as basename16, dirname as dirname26 } from "node:path";
157054
+ import { existsSync as existsSync49, copyFileSync, mkdirSync as mkdirSync12, symlinkSync as symlinkSync2, rmSync as rmSync5, lstatSync as lstatSync3, readlinkSync as readlinkSync2 } from "node:fs";
156654
157055
  import { tmpdir as tmpdir4 } from "node:os";
156655
157056
  function findStagedNativeDir2() {
156656
157057
  const platform3 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
@@ -156658,12 +157059,12 @@ function findStagedNativeDir2() {
156658
157059
  const prebuildName = `${platform3}-${arch}`;
156659
157060
  const execDir = dirname26(process.execPath);
156660
157061
  const nextToBinary = join63(execDir, "runtime", prebuildName);
156661
- if (existsSync48(join63(nextToBinary, "pty.node"))) {
157062
+ if (existsSync49(join63(nextToBinary, "pty.node"))) {
156662
157063
  return nextToBinary;
156663
157064
  }
156664
157065
  if (process.env.FUSION_RUNTIME_DIR) {
156665
157066
  const envPath = join63(process.env.FUSION_RUNTIME_DIR, prebuildName);
156666
- if (existsSync48(join63(envPath, "pty.node"))) {
157067
+ if (existsSync49(join63(envPath, "pty.node"))) {
156667
157068
  return envPath;
156668
157069
  }
156669
157070
  }
@@ -156673,11 +157074,11 @@ function cleanupStaleBunfsLinks() {
156673
157074
  if (process.platform === "win32") return;
156674
157075
  const bunfsRoot = "/$bunfs/root";
156675
157076
  try {
156676
- if (existsSync48(bunfsRoot)) {
157077
+ if (existsSync49(bunfsRoot)) {
156677
157078
  const stats = lstatSync3(bunfsRoot);
156678
157079
  if (stats.isSymbolicLink()) {
156679
157080
  const target = readlinkSync2(bunfsRoot);
156680
- if (target.includes("fn-bunfs-") && !existsSync48(target)) {
157081
+ if (target.includes("fn-bunfs-") && !existsSync49(target)) {
156681
157082
  rmSync5(bunfsRoot);
156682
157083
  console.log("[fn-native-patch] Cleaned up stale /$bunfs/root symlink");
156683
157084
  }
@@ -156699,20 +157100,20 @@ function setupNativeResolution() {
156699
157100
  const tmpRoot = join63(tmpdir4(), `fn-bunfs-${process.pid}`);
156700
157101
  const fnDir = join63(tmpRoot, "fn");
156701
157102
  const prebuildsDir = join63(fnDir, "prebuilds");
156702
- const platformDir = join63(prebuildsDir, basename15(nativeDir));
157103
+ const platformDir = join63(prebuildsDir, basename16(nativeDir));
156703
157104
  try {
156704
157105
  cleanupStaleBunfsLinks();
156705
157106
  mkdirSync12(platformDir, { recursive: true });
156706
157107
  const ptyNodeDest = join63(platformDir, "pty.node");
156707
157108
  copyFileSync(join63(nativeDir, "pty.node"), ptyNodeDest);
156708
- if (existsSync48(join63(nativeDir, "spawn-helper"))) {
157109
+ if (existsSync49(join63(nativeDir, "spawn-helper"))) {
156709
157110
  copyFileSync(join63(nativeDir, "spawn-helper"), join63(platformDir, "spawn-helper"));
156710
157111
  }
156711
157112
  process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
156712
157113
  if (process.platform !== "win32") {
156713
157114
  const bunfsRoot = "/$bunfs/root";
156714
157115
  try {
156715
- if (existsSync48(bunfsRoot)) {
157116
+ if (existsSync49(bunfsRoot)) {
156716
157117
  const stats = lstatSync3(bunfsRoot);
156717
157118
  if (stats.isSymbolicLink()) {
156718
157119
  rmSync5(bunfsRoot);
@@ -156735,7 +157136,7 @@ function setupNativeResolution() {
156735
157136
  function cleanupNativeResolution() {
156736
157137
  if (bunfsSymlinkPath && process.platform !== "win32") {
156737
157138
  try {
156738
- if (existsSync48(bunfsSymlinkPath)) {
157139
+ if (existsSync49(bunfsSymlinkPath)) {
156739
157140
  const stats = lstatSync3(bunfsSymlinkPath);
156740
157141
  if (stats.isSymbolicLink()) {
156741
157142
  rmSync5(bunfsSymlinkPath);
@@ -156781,7 +157182,7 @@ var init_native_patch = __esm({
156781
157182
  });
156782
157183
 
156783
157184
  // src/bin.ts
156784
- import { existsSync as existsSync49, mkdtempSync as mkdtempSync2, readFileSync as readFileSync22, symlinkSync as symlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
157185
+ import { existsSync as existsSync50, mkdtempSync as mkdtempSync2, readFileSync as readFileSync22, symlinkSync as symlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
156785
157186
  import { createRequire as createRequire6 } from "node:module";
156786
157187
  import { join as join64, dirname as dirname27 } from "node:path";
156787
157188
  import { tmpdir as tmpdir5 } from "node:os";
@@ -156804,7 +157205,7 @@ function configurePiPackage() {
156804
157205
  packageJson = JSON.parse(readFileSync22(piPackagePath, "utf-8"));
156805
157206
  for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
156806
157207
  const source = join64(piPackageDir, entry);
156807
- if (existsSync49(source)) {
157208
+ if (existsSync50(source)) {
156808
157209
  symlinkSync3(source, join64(tmp, entry));
156809
157210
  }
156810
157211
  }
@@ -156823,7 +157224,7 @@ setInterval(() => {
156823
157224
  performance3.clearMarks();
156824
157225
  }, 3e4).unref();
156825
157226
  function loadEnvFile(path5) {
156826
- if (!existsSync49(path5)) return;
157227
+ if (!existsSync50(path5)) return;
156827
157228
  const contents = readFileSync22(path5, "utf-8");
156828
157229
  for (const rawLine of contents.split(/\r?\n/)) {
156829
157230
  const line = rawLine.trim();
@@ -157076,9 +157477,6 @@ Options:
157076
157477
 
157077
157478
  Columns: triage, todo, in-progress, in-review, done, archived
157078
157479
  Supported file types: png, jpg, gif, webp, txt, log, json, yaml, yml, toml, csv, xml
157079
-
157080
- The AI engine uses pi (github.com/badlogic/pi-mono) for agent sessions.
157081
- Requires configured API keys \u2014 run "pi" first to set up authentication.
157082
157480
  `.trim();
157083
157481
  function extractGlobalProjectFlag(argv) {
157084
157482
  const cleanedArgs = [];
@@ -157126,10 +157524,8 @@ async function main() {
157126
157524
  console.log(HELP);
157127
157525
  process.exit(0);
157128
157526
  }
157129
- if (args.length === 0) {
157130
- const { runDashboard: runDashboard3 } = await Promise.resolve().then(() => (init_dashboard(), dashboard_exports));
157131
- await runDashboard3(4040);
157132
- return;
157527
+ if (args.length === 0 || args[0].startsWith("-")) {
157528
+ args.unshift("dashboard");
157133
157529
  }
157134
157530
  const command = args[0];
157135
157531
  const {