@runfusion/fusion 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +809 -533
- package/dist/client/assets/{AgentDetailView-C3Xcrxnp.js → AgentDetailView-CLzxf6Z7.js} +1 -1
- package/dist/client/assets/{AgentsView-EjE4y4rM.js → AgentsView-CXaYJX_G.js} +3 -3
- package/dist/client/assets/{ChatView-DQLvKCYj.js → ChatView-iXxGAaN1.js} +1 -1
- package/dist/client/assets/{DevServerView-CX7paFRQ.js → DevServerView-BeXfFkF4.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-_cBPx6Nx.js → DirectoryPicker-BMn5fjn9.js} +1 -1
- package/dist/client/assets/{DocumentsView-Wz33aYqp.js → DocumentsView-CjrtI3TX.js} +1 -1
- package/dist/client/assets/{InsightsView-C7YPnS92.js → InsightsView-BkfQ-TV1.js} +1 -1
- package/dist/client/assets/{MemoryView-DKQtFzFQ.js → MemoryView-1G0zWu1i.js} +1 -1
- package/dist/client/assets/{NodesView-CI4rUQC4.js → NodesView-Bn_1R73N.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BFmdKgHZ.js → PiExtensionsManager-CqGOtQnR.js} +1 -1
- package/dist/client/assets/{PluginManager-BGQU1IIw.js → PluginManager-CM5QGvSG.js} +1 -1
- package/dist/client/assets/{RoadmapsView-Cts3hoIS.js → RoadmapsView-B4VnQP83.js} +1 -1
- package/dist/client/assets/{SettingsModal-DvRd0ZOE.js → SettingsModal-BiLA-BeG.js} +4 -4
- package/dist/client/assets/{SettingsModal-DXvBGZHf.js → SettingsModal-C3LckzfT.js} +1 -1
- package/dist/client/assets/SetupWizardModal-Bk_8HfLm.js +1 -0
- package/dist/client/assets/{SkillsView-BXvrHzEZ.js → SkillsView-CRvqF8P1.js} +1 -1
- package/dist/client/assets/{TodoView-NZHkv9YQ.js → TodoView-Vzui5Eha.js} +1 -1
- package/dist/client/assets/{folder-open-Kh0ScTc5.js → folder-open-CMF89prE.js} +1 -1
- package/dist/client/assets/{index-D1gavMG-.js → index-B8kH5y4Q.js} +3 -3
- package/dist/client/assets/{index-CWz44REw.css → index-D2fXOwWF.css} +1 -1
- package/dist/client/assets/{list-checks-CvoT0bwU.js → list-checks-M95d1uAy.js} +1 -1
- package/dist/client/assets/{star-BdfwSLBU.js → star-DHhJD6ow.js} +1 -1
- package/dist/client/assets/{upload-Bx8Yk_7Q.js → upload-CEq8jic8.js} +1 -1
- package/dist/client/assets/{users-DgVaFEsz.js → users-CUA8Tv-d.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +187 -41
- package/dist/pi-claude-cli/package.json +4 -1
- package/dist/pi-claude-cli/src/process-manager.ts +1 -1
- package/package.json +1 -1
- package/dist/client/assets/SetupWizardModal-Y2ewEE8Y.js +0 -1
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 =
|
|
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
|
|
6489
|
+
let resolve37;
|
|
6483
6490
|
const next = new Promise((r) => {
|
|
6484
|
-
|
|
6491
|
+
resolve37 = 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
|
-
|
|
6499
|
+
resolve37();
|
|
6493
6500
|
}
|
|
6494
6501
|
});
|
|
6495
6502
|
}
|
|
@@ -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
|
|
27795
|
+
let resolve37;
|
|
27789
27796
|
const next = new Promise((r) => {
|
|
27790
|
-
|
|
27797
|
+
resolve37 = 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
|
-
|
|
27807
|
+
resolve37();
|
|
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((
|
|
29595
|
+
return new Promise((resolve37) => {
|
|
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
|
-
|
|
29654
|
+
resolve37({
|
|
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
|
-
|
|
29672
|
+
resolve37({
|
|
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
|
|
30822
|
+
let resolve37;
|
|
30816
30823
|
const next = new Promise((r) => {
|
|
30817
|
-
|
|
30824
|
+
resolve37 = 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
|
-
|
|
30832
|
+
resolve37();
|
|
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
|
|
30842
|
+
let resolve37;
|
|
30836
30843
|
const next = new Promise((r) => {
|
|
30837
|
-
|
|
30844
|
+
resolve37 = 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
|
-
|
|
30854
|
+
resolve37();
|
|
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:
|
|
32506
|
-
await
|
|
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:
|
|
32842
|
-
await
|
|
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((
|
|
33009
|
+
await new Promise((resolve37) => setImmediate(resolve37));
|
|
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((
|
|
33029
|
+
await new Promise((resolve37) => setImmediate(resolve37));
|
|
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:
|
|
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
|
|
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:
|
|
33836
|
-
await
|
|
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((
|
|
34855
|
+
return new Promise((resolve37, 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
|
-
|
|
34906
|
+
resolve37(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
|
|
35194
|
+
let resolve37;
|
|
35188
35195
|
const next = new Promise((r) => {
|
|
35189
|
-
|
|
35196
|
+
resolve37 = 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
|
-
|
|
35206
|
+
resolve37();
|
|
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((
|
|
35805
|
+
return new Promise((resolve37, 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
|
-
|
|
35811
|
+
resolve37(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((
|
|
39018
|
+
await new Promise((resolve37, 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
|
-
|
|
39030
|
+
resolve37();
|
|
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((
|
|
40324
|
+
return new Promise((resolve37, 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
|
-
|
|
40333
|
+
resolve37();
|
|
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
|
|
47777
|
-
if (
|
|
47778
|
-
aliases.add(
|
|
47779
|
-
const basenameSlug = slugifyAgentReference(
|
|
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((
|
|
51075
|
+
return new Promise((resolve37) => {
|
|
51044
51076
|
this._waiters.push({
|
|
51045
51077
|
priority,
|
|
51046
51078
|
resolve: () => {
|
|
51047
51079
|
this._active++;
|
|
51048
|
-
|
|
51080
|
+
resolve37();
|
|
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((
|
|
53501
|
+
return new Promise((resolve37, reject2) => {
|
|
53470
53502
|
if (signal?.aborted) {
|
|
53471
53503
|
reject2(signal.reason ?? new Error("Aborted"));
|
|
53472
53504
|
return;
|
|
53473
53505
|
}
|
|
53474
|
-
const timer = setTimeout(
|
|
53506
|
+
const timer = setTimeout(resolve37, 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 =
|
|
53482
|
-
|
|
53513
|
+
const origResolve = resolve37;
|
|
53514
|
+
resolve37 = () => {
|
|
53483
53515
|
signal.removeEventListener("abort", onAbort);
|
|
53484
53516
|
origResolve();
|
|
53485
53517
|
};
|
|
@@ -53559,9 +53591,9 @@ async function readAttachmentContents(rootDir, taskId, attachments) {
|
|
|
53559
53591
|
return { attachmentContents, imageContents };
|
|
53560
53592
|
}
|
|
53561
53593
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
53562
|
-
const { join:
|
|
53594
|
+
const { join: join66 } = await import("node:path");
|
|
53563
53595
|
for (const att of attachments) {
|
|
53564
|
-
const filePath =
|
|
53596
|
+
const filePath = join66(
|
|
53565
53597
|
rootDir,
|
|
53566
53598
|
".fusion",
|
|
53567
53599
|
"tasks",
|
|
@@ -55075,9 +55107,9 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
55075
55107
|
}
|
|
55076
55108
|
try {
|
|
55077
55109
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
55078
|
-
const { join:
|
|
55110
|
+
const { join: join66 } = await import("node:path");
|
|
55079
55111
|
const promptContent = await readFile24(
|
|
55080
|
-
|
|
55112
|
+
join66(rootDir, promptPath),
|
|
55081
55113
|
"utf-8"
|
|
55082
55114
|
).catch((err) => {
|
|
55083
55115
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -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((
|
|
55481
|
+
return new Promise((resolve37, 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
|
-
|
|
55574
|
+
resolve37({ 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
|
-
|
|
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)
|
|
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
|
-
|
|
56146
|
-
|
|
56147
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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((
|
|
59543
|
+
return new Promise((resolve37) => setTimeout(resolve37, 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()\`.
|
|
@@ -60434,6 +60577,7 @@ If the task's PROMPT.md includes a "Documentation Requirements" section listing
|
|
|
60434
60577
|
## Git discipline
|
|
60435
60578
|
- Commit after completing each step (not after every file change)
|
|
60436
60579
|
- Use conventional commit messages prefixed with the task ID
|
|
60580
|
+
- When the task has a GitHub issue reference, include \`Ref: owner/repo#N\` in the commit body
|
|
60437
60581
|
- Do NOT commit broken or half-implemented code
|
|
60438
60582
|
|
|
60439
60583
|
## Worktree Boundaries
|
|
@@ -63407,7 +63551,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
|
|
|
63407
63551
|
);
|
|
63408
63552
|
}
|
|
63409
63553
|
const delay2 = this.WORKTREE_RETRY_DELAYS[attempt] || 1e3;
|
|
63410
|
-
await new Promise((
|
|
63554
|
+
await new Promise((resolve37) => setTimeout(resolve37, delay2));
|
|
63411
63555
|
}
|
|
63412
63556
|
}
|
|
63413
63557
|
throw new Error("Unexpected exit from worktree creation retry loop");
|
|
@@ -72731,13 +72875,13 @@ var init_plugin_runner = __esm({
|
|
|
72731
72875
|
* Returns the result on success, throws on timeout.
|
|
72732
72876
|
*/
|
|
72733
72877
|
withTimeout(promise, ms, timeoutMessage) {
|
|
72734
|
-
return new Promise((
|
|
72878
|
+
return new Promise((resolve37, reject2) => {
|
|
72735
72879
|
const timer = setTimeout(() => {
|
|
72736
72880
|
reject2(new Error(timeoutMessage));
|
|
72737
72881
|
}, ms);
|
|
72738
72882
|
promise.then((result) => {
|
|
72739
72883
|
clearTimeout(timer);
|
|
72740
|
-
|
|
72884
|
+
resolve37(result);
|
|
72741
72885
|
}).catch((err) => {
|
|
72742
72886
|
clearTimeout(timer);
|
|
72743
72887
|
reject2(err);
|
|
@@ -73406,7 +73550,7 @@ var init_in_process_runtime = __esm({
|
|
|
73406
73550
|
runtimeLog.log(
|
|
73407
73551
|
`Waiting for ${metrics.inFlightTasks} in-flight tasks to complete...`
|
|
73408
73552
|
);
|
|
73409
|
-
await new Promise((
|
|
73553
|
+
await new Promise((resolve37) => setTimeout(resolve37, 1e3));
|
|
73410
73554
|
}
|
|
73411
73555
|
const finalMetrics = this.getMetrics();
|
|
73412
73556
|
if (finalMetrics.inFlightTasks > 0) {
|
|
@@ -73803,13 +73947,13 @@ var init_ipc_host = __esm({
|
|
|
73803
73947
|
}
|
|
73804
73948
|
const id = generateCorrelationId();
|
|
73805
73949
|
const message = { type, id, payload };
|
|
73806
|
-
return new Promise((
|
|
73950
|
+
return new Promise((resolve37, reject2) => {
|
|
73807
73951
|
const timeout2 = setTimeout(() => {
|
|
73808
73952
|
this.pendingCommands.delete(id);
|
|
73809
73953
|
reject2(new Error(`Command ${type} timed out after ${timeoutMs ?? this.commandTimeoutMs}ms`));
|
|
73810
73954
|
}, timeoutMs ?? this.commandTimeoutMs);
|
|
73811
73955
|
this.pendingCommands.set(id, {
|
|
73812
|
-
resolve:
|
|
73956
|
+
resolve: resolve37,
|
|
73813
73957
|
reject: reject2,
|
|
73814
73958
|
timeout: timeout2,
|
|
73815
73959
|
type
|
|
@@ -74618,8 +74762,8 @@ var init_remote_node_client = __esm({
|
|
|
74618
74762
|
return error instanceof TypeError;
|
|
74619
74763
|
}
|
|
74620
74764
|
async sleep(ms) {
|
|
74621
|
-
await new Promise((
|
|
74622
|
-
setTimeout(
|
|
74765
|
+
await new Promise((resolve37) => {
|
|
74766
|
+
setTimeout(resolve37, ms);
|
|
74623
74767
|
});
|
|
74624
74768
|
}
|
|
74625
74769
|
};
|
|
@@ -74883,14 +75027,14 @@ var init_remote_node_runtime = __esm({
|
|
|
74883
75027
|
return error instanceof Error ? error : new Error(String(error));
|
|
74884
75028
|
}
|
|
74885
75029
|
async sleep(ms, signal) {
|
|
74886
|
-
await new Promise((
|
|
75030
|
+
await new Promise((resolve37) => {
|
|
74887
75031
|
const timeout2 = setTimeout(() => {
|
|
74888
75032
|
cleanup();
|
|
74889
|
-
|
|
75033
|
+
resolve37();
|
|
74890
75034
|
}, ms);
|
|
74891
75035
|
const onAbort = () => {
|
|
74892
75036
|
cleanup();
|
|
74893
|
-
|
|
75037
|
+
resolve37();
|
|
74894
75038
|
};
|
|
74895
75039
|
const cleanup = () => {
|
|
74896
75040
|
clearTimeout(timeout2);
|
|
@@ -75777,10 +75921,10 @@ var init_tunnel_process_manager = __esm({
|
|
|
75777
75921
|
lastError: null
|
|
75778
75922
|
});
|
|
75779
75923
|
this.emitLog("info", "manager", `Stopping ${currentHandle.provider} tunnel (pid=${currentHandle.child.pid ?? "n/a"})`);
|
|
75780
|
-
this.activeStopPromise = new Promise((
|
|
75924
|
+
this.activeStopPromise = new Promise((resolve37) => {
|
|
75781
75925
|
const onClose = () => {
|
|
75782
75926
|
currentHandle.child.removeListener("close", onClose);
|
|
75783
|
-
|
|
75927
|
+
resolve37();
|
|
75784
75928
|
};
|
|
75785
75929
|
currentHandle.child.once("close", onClose);
|
|
75786
75930
|
killManagedProcess(currentHandle.child, "SIGTERM");
|
|
@@ -76336,12 +76480,12 @@ ${detail}`
|
|
|
76336
76480
|
*/
|
|
76337
76481
|
async onMerge(taskId) {
|
|
76338
76482
|
if (this.mergeActive.has(taskId)) {
|
|
76339
|
-
return new Promise((
|
|
76340
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
76483
|
+
return new Promise((resolve37, reject2) => {
|
|
76484
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve37, reject: reject2 });
|
|
76341
76485
|
});
|
|
76342
76486
|
}
|
|
76343
|
-
return new Promise((
|
|
76344
|
-
this.manualMergeResolvers.set(taskId, { resolve:
|
|
76487
|
+
return new Promise((resolve37, reject2) => {
|
|
76488
|
+
this.manualMergeResolvers.set(taskId, { resolve: resolve37, reject: reject2 });
|
|
76345
76489
|
this.internalEnqueueMerge(taskId);
|
|
76346
76490
|
});
|
|
76347
76491
|
}
|
|
@@ -82211,7 +82355,7 @@ function hermesProfileHome(profileName) {
|
|
|
82211
82355
|
async function listHermesProfiles(opts) {
|
|
82212
82356
|
const binary = resolveBinaryForSpawn(opts?.binaryPath ?? "hermes");
|
|
82213
82357
|
const timeoutMs = opts?.timeoutMs ?? 5e3;
|
|
82214
|
-
return new Promise((
|
|
82358
|
+
return new Promise((resolve37, reject2) => {
|
|
82215
82359
|
let settled = false;
|
|
82216
82360
|
const child = spawn4(binary, ["profile", "list"], {
|
|
82217
82361
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -82254,7 +82398,7 @@ async function listHermesProfiles(opts) {
|
|
|
82254
82398
|
${combined}`));
|
|
82255
82399
|
return;
|
|
82256
82400
|
}
|
|
82257
|
-
|
|
82401
|
+
resolve37(parseProfileListOutput(stdout));
|
|
82258
82402
|
});
|
|
82259
82403
|
});
|
|
82260
82404
|
}
|
|
@@ -82331,7 +82475,7 @@ function buildHermesArgs(prompt, settings, resumeSessionId) {
|
|
|
82331
82475
|
async function invokeHermesCli(prompt, settings, resumeSessionId, signal) {
|
|
82332
82476
|
const args = buildHermesArgs(prompt, settings, resumeSessionId);
|
|
82333
82477
|
const binary = resolveBinaryForSpawn(settings.binaryPath);
|
|
82334
|
-
return new Promise((
|
|
82478
|
+
return new Promise((resolve37, reject2) => {
|
|
82335
82479
|
let settled = false;
|
|
82336
82480
|
const spawnEnv = { ...process.env, PYTHONUNBUFFERED: "1" };
|
|
82337
82481
|
if (settings.profile) {
|
|
@@ -82399,7 +82543,7 @@ ${combined}`));
|
|
|
82399
82543
|
return;
|
|
82400
82544
|
}
|
|
82401
82545
|
try {
|
|
82402
|
-
|
|
82546
|
+
resolve37(parseHermesOutput(stdout, stderr));
|
|
82403
82547
|
} catch (parseErr) {
|
|
82404
82548
|
reject2(parseErr);
|
|
82405
82549
|
}
|
|
@@ -82717,7 +82861,7 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
82717
82861
|
const args = buildOpenClawArgs(config, session.sessionId, message);
|
|
82718
82862
|
const cb = { ...session.callbacks, ...callbacks };
|
|
82719
82863
|
cb.onToolStart?.("openclaw.agent", { sessionId: session.sessionId });
|
|
82720
|
-
return new Promise((
|
|
82864
|
+
return new Promise((resolve37, reject2) => {
|
|
82721
82865
|
let settled = false;
|
|
82722
82866
|
const child = spawn6(config.binaryPath, args, {
|
|
82723
82867
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -82810,7 +82954,7 @@ async function promptCli(session, message, config, callbacks, signal) {
|
|
|
82810
82954
|
...metaError ? { error: metaError } : {},
|
|
82811
82955
|
...errorText.length > 0 ? { toolErrors: errorText } : {}
|
|
82812
82956
|
});
|
|
82813
|
-
|
|
82957
|
+
resolve37();
|
|
82814
82958
|
});
|
|
82815
82959
|
});
|
|
82816
82960
|
}
|
|
@@ -83552,10 +83696,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
83552
83696
|
nextRecoveryAt: null
|
|
83553
83697
|
});
|
|
83554
83698
|
if (retrySpecification) {
|
|
83555
|
-
const { rm:
|
|
83556
|
-
const { join:
|
|
83557
|
-
const promptPath =
|
|
83558
|
-
await
|
|
83699
|
+
const { rm: rm6 } = await import("node:fs/promises");
|
|
83700
|
+
const { join: join66 } = await import("node:path");
|
|
83701
|
+
const promptPath = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
83702
|
+
await rm6(promptPath, { force: true });
|
|
83559
83703
|
await scopedStore.logEntry(req.params.id, "Retry requested from dashboard (planning retry budget reset)");
|
|
83560
83704
|
const updated2 = await scopedStore.getTask(req.params.id);
|
|
83561
83705
|
res.json(updated2);
|
|
@@ -83975,10 +84119,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
83975
84119
|
}
|
|
83976
84120
|
await scopedStore.logEntry(task.id, "Plan rejected by user", "Specification will be regenerated");
|
|
83977
84121
|
await scopedStore.updateTask(task.id, { status: void 0 });
|
|
83978
|
-
const { rm:
|
|
83979
|
-
const { join:
|
|
83980
|
-
const promptPath =
|
|
83981
|
-
await
|
|
84122
|
+
const { rm: rm6 } = await import("node:fs/promises");
|
|
84123
|
+
const { join: join66 } = await import("node:path");
|
|
84124
|
+
const promptPath = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
84125
|
+
await rm6(promptPath, { force: true });
|
|
83982
84126
|
const updated = await scopedStore.getTask(task.id);
|
|
83983
84127
|
res.json(updated);
|
|
83984
84128
|
} catch (err) {
|
|
@@ -84246,10 +84390,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
84246
84390
|
const task = await scopedStore.getTask(req.params.id);
|
|
84247
84391
|
if (task.column === "triage") {
|
|
84248
84392
|
await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
|
|
84249
|
-
const { rm:
|
|
84250
|
-
const { join:
|
|
84251
|
-
const promptPath2 =
|
|
84252
|
-
await
|
|
84393
|
+
const { rm: rm7 } = await import("node:fs/promises");
|
|
84394
|
+
const { join: join67 } = await import("node:path");
|
|
84395
|
+
const promptPath2 = join67(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
84396
|
+
await rm7(promptPath2, { force: true });
|
|
84253
84397
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
84254
84398
|
const updated2 = await scopedStore.getTask(task.id);
|
|
84255
84399
|
res.json(updated2);
|
|
@@ -84263,10 +84407,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
84263
84407
|
}
|
|
84264
84408
|
await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
|
|
84265
84409
|
const updated = await scopedStore.moveTask(task.id, "triage");
|
|
84266
|
-
const { rm:
|
|
84267
|
-
const { join:
|
|
84268
|
-
const promptPath =
|
|
84269
|
-
await
|
|
84410
|
+
const { rm: rm6 } = await import("node:fs/promises");
|
|
84411
|
+
const { join: join66 } = await import("node:path");
|
|
84412
|
+
const promptPath = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
84413
|
+
await rm6(promptPath, { force: true });
|
|
84270
84414
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
84271
84415
|
res.json(updated);
|
|
84272
84416
|
} catch (err) {
|
|
@@ -84284,10 +84428,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
84284
84428
|
const task = await scopedStore.getTask(req.params.id);
|
|
84285
84429
|
if (task.column === "triage") {
|
|
84286
84430
|
await scopedStore.logEntry(task.id, "Specification rebuild requested by user");
|
|
84287
|
-
const { rm:
|
|
84288
|
-
const { join:
|
|
84289
|
-
const promptPath2 =
|
|
84290
|
-
await
|
|
84431
|
+
const { rm: rm7 } = await import("node:fs/promises");
|
|
84432
|
+
const { join: join67 } = await import("node:path");
|
|
84433
|
+
const promptPath2 = join67(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
84434
|
+
await rm7(promptPath2, { force: true });
|
|
84291
84435
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
84292
84436
|
const updated2 = await scopedStore.getTask(task.id);
|
|
84293
84437
|
res.json(updated2);
|
|
@@ -84299,10 +84443,10 @@ function registerTaskWorkflowRoutes(ctx, deps) {
|
|
|
84299
84443
|
}
|
|
84300
84444
|
await scopedStore.logEntry(task.id, "Specification rebuild requested by user");
|
|
84301
84445
|
const updated = await scopedStore.moveTask(task.id, "triage");
|
|
84302
|
-
const { rm:
|
|
84303
|
-
const { join:
|
|
84304
|
-
const promptPath =
|
|
84305
|
-
await
|
|
84446
|
+
const { rm: rm6 } = await import("node:fs/promises");
|
|
84447
|
+
const { join: join66 } = await import("node:path");
|
|
84448
|
+
const promptPath = join66(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
84449
|
+
await rm6(promptPath, { force: true });
|
|
84306
84450
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
84307
84451
|
res.json(updated);
|
|
84308
84452
|
} catch (err) {
|
|
@@ -85582,6 +85726,11 @@ async function ensureEngineReady5() {
|
|
|
85582
85726
|
} catch {
|
|
85583
85727
|
}
|
|
85584
85728
|
}
|
|
85729
|
+
function formatAttachmentSize(size) {
|
|
85730
|
+
if (size < 1024) return `${size}B`;
|
|
85731
|
+
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}KB`;
|
|
85732
|
+
return `${(size / (1024 * 1024)).toFixed(1)}MB`;
|
|
85733
|
+
}
|
|
85585
85734
|
function validateFilePath(basePath, filePath) {
|
|
85586
85735
|
if (filePath.includes("\0")) {
|
|
85587
85736
|
throw new Error(`Access denied: Invalid characters in path`);
|
|
@@ -85911,7 +86060,7 @@ var init_chat = __esm({
|
|
|
85911
86060
|
* @param modelProvider - Optional model provider override
|
|
85912
86061
|
* @param modelId - Optional model ID override
|
|
85913
86062
|
*/
|
|
85914
|
-
async sendMessage(sessionId, content, modelProvider, modelId) {
|
|
86063
|
+
async sendMessage(sessionId, content, modelProvider, modelId, attachments) {
|
|
85915
86064
|
const abortController = new AbortController();
|
|
85916
86065
|
this.activeGenerations.set(sessionId, { abortController });
|
|
85917
86066
|
const session = this.chatStore.getSession(sessionId);
|
|
@@ -85935,7 +86084,8 @@ var init_chat = __esm({
|
|
|
85935
86084
|
this.chatStore.addMessage(sessionId, {
|
|
85936
86085
|
role: "user",
|
|
85937
86086
|
content,
|
|
85938
|
-
metadata: mentions.length > 0 ? { mentions } : void 0
|
|
86087
|
+
metadata: mentions.length > 0 ? { mentions } : void 0,
|
|
86088
|
+
attachments
|
|
85939
86089
|
});
|
|
85940
86090
|
} catch (err) {
|
|
85941
86091
|
chatStreamManager.broadcast(sessionId, {
|
|
@@ -86012,6 +86162,7 @@ ${mentionContext}`;
|
|
|
86012
86162
|
(message) => message.role === "user" || message.role === "assistant"
|
|
86013
86163
|
);
|
|
86014
86164
|
const resolvedContent = await resolveFileReferences(content, this.rootDir);
|
|
86165
|
+
const attachmentSummary = attachments && attachments.length > 0 ? `[User attached: ${attachments.map((attachment) => `${attachment.originalName} (${attachment.mimeType}, ${formatAttachmentSize(attachment.size)})`).join(", ")}]` : "";
|
|
86015
86166
|
const promptContent = conversationMessages.length > 0 ? [
|
|
86016
86167
|
"## Previous Conversation",
|
|
86017
86168
|
"",
|
|
@@ -86022,8 +86173,9 @@ ${mentionContext}`;
|
|
|
86022
86173
|
"",
|
|
86023
86174
|
"## Current Message",
|
|
86024
86175
|
"",
|
|
86176
|
+
attachmentSummary,
|
|
86025
86177
|
resolvedContent
|
|
86026
|
-
].join("\n") : resolvedContent;
|
|
86178
|
+
].filter(Boolean).join("\n") : [attachmentSummary, resolvedContent].filter(Boolean).join("\n\n");
|
|
86027
86179
|
agentResult = await createFnAgent8({
|
|
86028
86180
|
cwd: this.rootDir,
|
|
86029
86181
|
systemPrompt,
|
|
@@ -86100,7 +86252,7 @@ ${mentionContext}`;
|
|
|
86100
86252
|
});
|
|
86101
86253
|
chatStreamManager.broadcast(sessionId, {
|
|
86102
86254
|
type: "done",
|
|
86103
|
-
data: { messageId: assistantMessage.id }
|
|
86255
|
+
data: { messageId: assistantMessage.id, attachments }
|
|
86104
86256
|
});
|
|
86105
86257
|
} catch (err) {
|
|
86106
86258
|
if (abortController.signal.aborted) {
|
|
@@ -86166,9 +86318,36 @@ ${mentionContext}`;
|
|
|
86166
86318
|
});
|
|
86167
86319
|
|
|
86168
86320
|
// ../dashboard/src/routes/register-chat-routes.ts
|
|
86321
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
86322
|
+
import { createReadStream as createReadStream2 } from "node:fs";
|
|
86323
|
+
import { mkdir as mkdir12, rm as rm2, writeFile as writeFile12 } from "node:fs/promises";
|
|
86324
|
+
import { basename as basename9, join as join37, resolve as resolve17 } from "node:path";
|
|
86325
|
+
function resolveAttachmentPath(rootDir, sessionId, filename) {
|
|
86326
|
+
const sessionDir = resolve17(rootDir, ".fusion", "chat-attachments", sessionId);
|
|
86327
|
+
const safeName = basename9(filename);
|
|
86328
|
+
const filePath = resolve17(sessionDir, safeName);
|
|
86329
|
+
if (!filePath.startsWith(`${sessionDir}/`) && filePath !== sessionDir) {
|
|
86330
|
+
throw badRequest("Invalid attachment path");
|
|
86331
|
+
}
|
|
86332
|
+
return { sessionDir, filePath };
|
|
86333
|
+
}
|
|
86169
86334
|
function registerChatRoutes(ctx, deps) {
|
|
86170
86335
|
const { router, options, getProjectContext: getProjectContext3, chatLogger, rethrowAsApiError: rethrowAsApiError7 } = ctx;
|
|
86171
|
-
const { parseLastEventId: parseLastEventId3, validateOptionalModelField: validateOptionalModelField2 } = deps;
|
|
86336
|
+
const { parseLastEventId: parseLastEventId3, validateOptionalModelField: validateOptionalModelField2, upload: upload2 } = deps;
|
|
86337
|
+
const uploadChatAttachment = (req, res, next) => {
|
|
86338
|
+
upload2.single("file")(req, res, (err) => {
|
|
86339
|
+
if (!err) {
|
|
86340
|
+
next();
|
|
86341
|
+
return;
|
|
86342
|
+
}
|
|
86343
|
+
const multerError = err;
|
|
86344
|
+
if (multerError?.code === "LIMIT_FILE_SIZE") {
|
|
86345
|
+
next(badRequest(`File too large. Maximum: ${CHAT_MAX_ATTACHMENT_SIZE} bytes (5MB)`));
|
|
86346
|
+
return;
|
|
86347
|
+
}
|
|
86348
|
+
next(err);
|
|
86349
|
+
});
|
|
86350
|
+
};
|
|
86172
86351
|
router.get("/chat/sessions", rateLimit(RATE_LIMITS.api), async (req, res) => {
|
|
86173
86352
|
try {
|
|
86174
86353
|
const chatStore = options?.chatStore;
|
|
@@ -86368,6 +86547,84 @@ function registerChatRoutes(ctx, deps) {
|
|
|
86368
86547
|
rethrowAsApiError7(err, "Failed to get chat messages");
|
|
86369
86548
|
}
|
|
86370
86549
|
});
|
|
86550
|
+
router.post("/chat/sessions/:id/attachments", rateLimit(RATE_LIMITS.mutation), uploadChatAttachment, async (req, res) => {
|
|
86551
|
+
try {
|
|
86552
|
+
const chatStore = options?.chatStore;
|
|
86553
|
+
if (!chatStore) {
|
|
86554
|
+
throw internalError("Chat store not available");
|
|
86555
|
+
}
|
|
86556
|
+
const sessionId = String(req.params.id);
|
|
86557
|
+
const session = chatStore.getSession(sessionId);
|
|
86558
|
+
if (!session) {
|
|
86559
|
+
throw notFound(`Chat session ${sessionId} not found`);
|
|
86560
|
+
}
|
|
86561
|
+
const file = req.file;
|
|
86562
|
+
if (!file) {
|
|
86563
|
+
throw badRequest("file is required");
|
|
86564
|
+
}
|
|
86565
|
+
if (!CHAT_ALLOWED_MIME_TYPES.has(file.mimetype)) {
|
|
86566
|
+
throw badRequest(`Invalid mime type '${file.mimetype}'`);
|
|
86567
|
+
}
|
|
86568
|
+
if (file.size > CHAT_MAX_ATTACHMENT_SIZE) {
|
|
86569
|
+
throw badRequest(`File too large (${file.size} bytes). Maximum: ${CHAT_MAX_ATTACHMENT_SIZE} bytes (5MB)`);
|
|
86570
|
+
}
|
|
86571
|
+
const { store: scopedStore } = await getProjectContext3(req);
|
|
86572
|
+
const rootDir = scopedStore.getRootDir();
|
|
86573
|
+
const sessionDir = resolve17(rootDir, ".fusion", "chat-attachments", sessionId);
|
|
86574
|
+
await mkdir12(sessionDir, { recursive: true });
|
|
86575
|
+
const sanitizedFilename = (file.originalname || "attachment").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
86576
|
+
const filename = `${Date.now()}-${sanitizedFilename}`;
|
|
86577
|
+
const filePath = join37(sessionDir, filename);
|
|
86578
|
+
await writeFile12(filePath, file.buffer);
|
|
86579
|
+
const attachment = {
|
|
86580
|
+
id: `att-${randomUUID15().slice(0, 8)}`,
|
|
86581
|
+
filename,
|
|
86582
|
+
originalName: file.originalname,
|
|
86583
|
+
mimeType: file.mimetype,
|
|
86584
|
+
size: file.size,
|
|
86585
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
86586
|
+
};
|
|
86587
|
+
res.status(201).json({ attachment });
|
|
86588
|
+
} catch (err) {
|
|
86589
|
+
if (err instanceof ApiError) throw err;
|
|
86590
|
+
rethrowAsApiError7(err, "Failed to upload chat attachment");
|
|
86591
|
+
}
|
|
86592
|
+
});
|
|
86593
|
+
router.get("/chat/sessions/:id/attachments/:filename", async (req, res) => {
|
|
86594
|
+
try {
|
|
86595
|
+
const { store: scopedStore } = await getProjectContext3(req);
|
|
86596
|
+
const rootDir = scopedStore.getRootDir();
|
|
86597
|
+
const { filePath } = resolveAttachmentPath(rootDir, String(req.params.id), String(req.params.filename));
|
|
86598
|
+
const stream = createReadStream2(filePath);
|
|
86599
|
+
stream.on("error", () => {
|
|
86600
|
+
if (!res.headersSent) {
|
|
86601
|
+
res.status(404).json({ error: "Attachment not found" });
|
|
86602
|
+
} else {
|
|
86603
|
+
res.end();
|
|
86604
|
+
}
|
|
86605
|
+
});
|
|
86606
|
+
res.setHeader("Content-Type", "application/octet-stream");
|
|
86607
|
+
stream.pipe(res);
|
|
86608
|
+
} catch (err) {
|
|
86609
|
+
if (err instanceof ApiError) throw err;
|
|
86610
|
+
rethrowAsApiError7(err, "Failed to fetch chat attachment");
|
|
86611
|
+
}
|
|
86612
|
+
});
|
|
86613
|
+
router.delete("/chat/sessions/:id/attachments/:filename", rateLimit(RATE_LIMITS.mutation), async (req, res) => {
|
|
86614
|
+
try {
|
|
86615
|
+
const { store: scopedStore } = await getProjectContext3(req);
|
|
86616
|
+
const rootDir = scopedStore.getRootDir();
|
|
86617
|
+
const { filePath } = resolveAttachmentPath(rootDir, String(req.params.id), String(req.params.filename));
|
|
86618
|
+
await rm2(filePath);
|
|
86619
|
+
res.json({ success: true });
|
|
86620
|
+
} catch (err) {
|
|
86621
|
+
if (err?.code === "ENOENT") {
|
|
86622
|
+
throw notFound("Attachment not found");
|
|
86623
|
+
}
|
|
86624
|
+
if (err instanceof ApiError) throw err;
|
|
86625
|
+
rethrowAsApiError7(err, "Failed to delete chat attachment");
|
|
86626
|
+
}
|
|
86627
|
+
});
|
|
86371
86628
|
router.post("/chat/sessions/:id/messages", rateLimit(RATE_LIMITS.sse), async (req, res) => {
|
|
86372
86629
|
try {
|
|
86373
86630
|
const chatStore = options?.chatStore;
|
|
@@ -86375,7 +86632,7 @@ function registerChatRoutes(ctx, deps) {
|
|
|
86375
86632
|
if (!chatStore || !chatManager) {
|
|
86376
86633
|
throw internalError("Chat store or manager not available");
|
|
86377
86634
|
}
|
|
86378
|
-
const { content, modelProvider, modelId } = req.body;
|
|
86635
|
+
const { content, modelProvider, modelId, attachments } = req.body;
|
|
86379
86636
|
const sessionId = String(req.params.id);
|
|
86380
86637
|
if (!content || typeof content !== "string" || !content.trim()) {
|
|
86381
86638
|
throw badRequest("content is required and must be a non-empty string");
|
|
@@ -86449,7 +86706,8 @@ function registerChatRoutes(ctx, deps) {
|
|
|
86449
86706
|
sessionId,
|
|
86450
86707
|
content.trim(),
|
|
86451
86708
|
normalizedProvider,
|
|
86452
|
-
normalizedModelId
|
|
86709
|
+
normalizedModelId,
|
|
86710
|
+
Array.isArray(attachments) ? attachments : void 0
|
|
86453
86711
|
).catch((err) => {
|
|
86454
86712
|
chatLogger.error("Error in sendMessage", {
|
|
86455
86713
|
error: err.message
|
|
@@ -86518,6 +86776,9 @@ function registerChatRoutes(ctx, deps) {
|
|
|
86518
86776
|
"PATCH /chat/sessions/:id",
|
|
86519
86777
|
"DELETE /chat/sessions/:id",
|
|
86520
86778
|
"GET /chat/sessions/:id/messages",
|
|
86779
|
+
"POST /chat/sessions/:id/attachments",
|
|
86780
|
+
"GET /chat/sessions/:id/attachments/:filename",
|
|
86781
|
+
"DELETE /chat/sessions/:id/attachments/:filename",
|
|
86521
86782
|
"POST /chat/sessions/:id/messages",
|
|
86522
86783
|
"POST /chat/sessions/:id/cancel",
|
|
86523
86784
|
"DELETE /chat/sessions/:id/messages/:messageId"
|
|
@@ -86525,12 +86786,26 @@ function registerChatRoutes(ctx, deps) {
|
|
|
86525
86786
|
chatLogger.info("routes registered", { chatRoutes });
|
|
86526
86787
|
}
|
|
86527
86788
|
}
|
|
86789
|
+
var CHAT_ALLOWED_MIME_TYPES, CHAT_MAX_ATTACHMENT_SIZE;
|
|
86528
86790
|
var init_register_chat_routes = __esm({
|
|
86529
86791
|
"../dashboard/src/routes/register-chat-routes.ts"() {
|
|
86530
86792
|
"use strict";
|
|
86531
86793
|
init_api_error();
|
|
86532
86794
|
init_rate_limit();
|
|
86533
86795
|
init_sse_buffer();
|
|
86796
|
+
CHAT_ALLOWED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
86797
|
+
"image/png",
|
|
86798
|
+
"image/jpeg",
|
|
86799
|
+
"image/gif",
|
|
86800
|
+
"image/webp",
|
|
86801
|
+
"text/plain",
|
|
86802
|
+
"application/json",
|
|
86803
|
+
"text/yaml",
|
|
86804
|
+
"text/x-toml",
|
|
86805
|
+
"text/csv",
|
|
86806
|
+
"application/xml"
|
|
86807
|
+
]);
|
|
86808
|
+
CHAT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
|
|
86534
86809
|
}
|
|
86535
86810
|
});
|
|
86536
86811
|
|
|
@@ -87879,7 +88154,7 @@ import * as os3 from "os";
|
|
|
87879
88154
|
import * as path2 from "path";
|
|
87880
88155
|
import * as fs from "node:fs";
|
|
87881
88156
|
import { createRequire as createRequire3 } from "node:module";
|
|
87882
|
-
import { join as
|
|
88157
|
+
import { join as join38, dirname as dirname10 } from "node:path";
|
|
87883
88158
|
function getNativePrebuildName() {
|
|
87884
88159
|
const platform3 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
87885
88160
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
@@ -87889,12 +88164,12 @@ function findInstalledNodePtyNativeDir() {
|
|
|
87889
88164
|
try {
|
|
87890
88165
|
const packageJsonPath = require2.resolve("node-pty/package.json");
|
|
87891
88166
|
const pkgRoot = dirname10(packageJsonPath);
|
|
87892
|
-
const releaseDir =
|
|
87893
|
-
if (fs.existsSync(
|
|
88167
|
+
const releaseDir = join38(pkgRoot, "build", "Release");
|
|
88168
|
+
if (fs.existsSync(join38(releaseDir, "pty.node"))) {
|
|
87894
88169
|
return releaseDir;
|
|
87895
88170
|
}
|
|
87896
|
-
const prebuildDir =
|
|
87897
|
-
if (fs.existsSync(
|
|
88171
|
+
const prebuildDir = join38(pkgRoot, "prebuilds", getNativePrebuildName());
|
|
88172
|
+
if (fs.existsSync(join38(prebuildDir, "pty.node"))) {
|
|
87898
88173
|
return prebuildDir;
|
|
87899
88174
|
}
|
|
87900
88175
|
return null;
|
|
@@ -87920,8 +88195,8 @@ function ensureNodePtyNativePermissions() {
|
|
|
87920
88195
|
candidateDirs.add(installedNativeDir);
|
|
87921
88196
|
}
|
|
87922
88197
|
for (const nativeDir of candidateDirs) {
|
|
87923
|
-
const helperPath =
|
|
87924
|
-
const nativeModulePath =
|
|
88198
|
+
const helperPath = join38(nativeDir, "spawn-helper");
|
|
88199
|
+
const nativeModulePath = join38(nativeDir, "pty.node");
|
|
87925
88200
|
try {
|
|
87926
88201
|
fs.chmodSync(helperPath, 493);
|
|
87927
88202
|
} catch {
|
|
@@ -87939,14 +88214,14 @@ function ensureNodePtyNativePermissions() {
|
|
|
87939
88214
|
function findStagedNativeDir() {
|
|
87940
88215
|
const prebuildName = getNativePrebuildName();
|
|
87941
88216
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
87942
|
-
const envPath =
|
|
87943
|
-
if (fs.existsSync(
|
|
88217
|
+
const envPath = join38(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
88218
|
+
if (fs.existsSync(join38(envPath, "pty.node"))) {
|
|
87944
88219
|
return envPath;
|
|
87945
88220
|
}
|
|
87946
88221
|
}
|
|
87947
88222
|
const execDir = dirname10(process.execPath);
|
|
87948
|
-
const nextToBinary =
|
|
87949
|
-
if (fs.existsSync(
|
|
88223
|
+
const nextToBinary = join38(execDir, "runtime", prebuildName);
|
|
88224
|
+
if (fs.existsSync(join38(nextToBinary, "pty.node"))) {
|
|
87950
88225
|
return nextToBinary;
|
|
87951
88226
|
}
|
|
87952
88227
|
return null;
|
|
@@ -87966,7 +88241,7 @@ async function loadPtyModule() {
|
|
|
87966
88241
|
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
|
87967
88242
|
}
|
|
87968
88243
|
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
|
87969
|
-
const nativePath =
|
|
88244
|
+
const nativePath = join38(nativeDir, "pty.node");
|
|
87970
88245
|
if (fs.existsSync(nativePath)) {
|
|
87971
88246
|
try {
|
|
87972
88247
|
const nativeModule = { exports: {} };
|
|
@@ -88943,7 +89218,7 @@ var init_register_messaging_scripts = __esm({
|
|
|
88943
89218
|
|
|
88944
89219
|
// ../dashboard/src/github.ts
|
|
88945
89220
|
function delay(ms) {
|
|
88946
|
-
return new Promise((
|
|
89221
|
+
return new Promise((resolve37) => setTimeout(resolve37, ms));
|
|
88947
89222
|
}
|
|
88948
89223
|
function normalizeCheckState(state) {
|
|
88949
89224
|
switch ((state ?? "").toLowerCase()) {
|
|
@@ -93302,7 +93577,7 @@ var init_register_git_github = __esm({
|
|
|
93302
93577
|
|
|
93303
93578
|
// ../dashboard/src/terminal.ts
|
|
93304
93579
|
import { spawn as spawn8 } from "node:child_process";
|
|
93305
|
-
import { randomUUID as
|
|
93580
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
93306
93581
|
import { EventEmitter as EventEmitter31 } from "node:events";
|
|
93307
93582
|
function extractBaseCommand(command) {
|
|
93308
93583
|
let trimmed = command.trim();
|
|
@@ -93462,7 +93737,7 @@ var init_terminal = __esm({
|
|
|
93462
93737
|
if (!validation.valid) {
|
|
93463
93738
|
return { sessionId: "", error: validation.error };
|
|
93464
93739
|
}
|
|
93465
|
-
const sessionId =
|
|
93740
|
+
const sessionId = randomUUID16();
|
|
93466
93741
|
const childProcess = spawn8(command, [], {
|
|
93467
93742
|
cwd,
|
|
93468
93743
|
shell: true,
|
|
@@ -93587,20 +93862,20 @@ var init_terminal = __esm({
|
|
|
93587
93862
|
});
|
|
93588
93863
|
|
|
93589
93864
|
// ../dashboard/src/file-service.ts
|
|
93590
|
-
import { join as
|
|
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
|
|
93865
|
+
import { join as join39, resolve as resolve19, relative as relative9, dirname as dirname11, basename as basename11 } from "node:path";
|
|
93866
|
+
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
93867
|
async function getTaskBasePath(store, taskId) {
|
|
93593
93868
|
try {
|
|
93594
93869
|
const task = await store.getTask(taskId);
|
|
93595
93870
|
if (task.worktree) {
|
|
93596
93871
|
try {
|
|
93597
93872
|
await access4(task.worktree);
|
|
93598
|
-
return
|
|
93873
|
+
return resolve19(task.worktree);
|
|
93599
93874
|
} catch {
|
|
93600
93875
|
}
|
|
93601
93876
|
}
|
|
93602
93877
|
const rootDir = store.getRootDir();
|
|
93603
|
-
return
|
|
93878
|
+
return resolve19(join39(rootDir, ".fusion", "tasks", taskId));
|
|
93604
93879
|
} catch (err) {
|
|
93605
93880
|
const error = err;
|
|
93606
93881
|
if (error.code === "ENOENT" || error.message && error.message.includes("not found")) {
|
|
@@ -93610,7 +93885,7 @@ async function getTaskBasePath(store, taskId) {
|
|
|
93610
93885
|
}
|
|
93611
93886
|
}
|
|
93612
93887
|
function getProjectBasePath(store) {
|
|
93613
|
-
return
|
|
93888
|
+
return resolve19(store.getRootDir());
|
|
93614
93889
|
}
|
|
93615
93890
|
async function getWorkspaceBasePath(store, workspace) {
|
|
93616
93891
|
if (workspace === "project") {
|
|
@@ -93626,8 +93901,8 @@ function validatePath(basePath, filePath) {
|
|
|
93626
93901
|
if (decodedPath.startsWith("/") || decodedPath.match(/^[a-zA-Z]:/)) {
|
|
93627
93902
|
throw new FileServiceError(`Access denied: Absolute paths not allowed`, "EINVAL");
|
|
93628
93903
|
}
|
|
93629
|
-
const resolvedBase =
|
|
93630
|
-
const resolvedPath =
|
|
93904
|
+
const resolvedBase = resolve19(basePath);
|
|
93905
|
+
const resolvedPath = resolve19(join39(resolvedBase, decodedPath));
|
|
93631
93906
|
const relativePath = relative9(resolvedBase, resolvedPath);
|
|
93632
93907
|
if (relativePath.startsWith("..") || relativePath.startsWith("../") || relativePath === "..") {
|
|
93633
93908
|
throw new FileServiceError(`Access denied: Path traversal detected`, "EINVAL");
|
|
@@ -93656,7 +93931,7 @@ async function listFilesForBasePath(basePath, subPath) {
|
|
|
93656
93931
|
const entries = await readdir8(targetPath, { withFileTypes: true });
|
|
93657
93932
|
const fileNodes = [];
|
|
93658
93933
|
for (const entry of entries) {
|
|
93659
|
-
const entryPath =
|
|
93934
|
+
const entryPath = join39(targetPath, entry.name);
|
|
93660
93935
|
const entryStats = await stat7(entryPath);
|
|
93661
93936
|
fileNodes.push({
|
|
93662
93937
|
name: entry.name,
|
|
@@ -93786,7 +94061,7 @@ async function readFile18(store, taskId, filePath) {
|
|
|
93786
94061
|
const taskBase = await getTaskBasePath(store, taskId);
|
|
93787
94062
|
return readFileForBasePath(taskBase, filePath);
|
|
93788
94063
|
}
|
|
93789
|
-
async function
|
|
94064
|
+
async function writeFile13(store, taskId, filePath, content) {
|
|
93790
94065
|
const taskBase = await getTaskBasePath(store, taskId);
|
|
93791
94066
|
return writeFileForBasePath(taskBase, filePath, content);
|
|
93792
94067
|
}
|
|
@@ -93805,7 +94080,7 @@ async function writeWorkspaceFile(store, workspace, filePath, content) {
|
|
|
93805
94080
|
function validateSourceAndDestination(basePath, sourcePath, destinationPath) {
|
|
93806
94081
|
const resolvedSource = validatePath(basePath, sourcePath);
|
|
93807
94082
|
const resolvedDest = validatePath(basePath, destinationPath);
|
|
93808
|
-
const sourceRelative = relative9(
|
|
94083
|
+
const sourceRelative = relative9(resolve19(basePath), resolvedSource);
|
|
93809
94084
|
if (!sourceRelative || sourceRelative === "." || sourceRelative === "") {
|
|
93810
94085
|
throw new FileServiceError("Cannot operate on workspace root directory", "EINVAL");
|
|
93811
94086
|
}
|
|
@@ -93929,7 +94204,7 @@ async function deleteWorkspaceFile(store, workspace, filePath) {
|
|
|
93929
94204
|
}
|
|
93930
94205
|
const workspaceBase = await getWorkspaceBasePath(store, workspace);
|
|
93931
94206
|
const resolvedPath = validatePath(workspaceBase, filePath);
|
|
93932
|
-
const relativePath = relative9(
|
|
94207
|
+
const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
|
|
93933
94208
|
if (!relativePath || relativePath === "." || relativePath === "") {
|
|
93934
94209
|
throw new FileServiceError("Cannot delete workspace root directory", "EINVAL");
|
|
93935
94210
|
}
|
|
@@ -93970,7 +94245,7 @@ async function renameWorkspaceFile(store, workspace, filePath, newName) {
|
|
|
93970
94245
|
}
|
|
93971
94246
|
const workspaceBase = await getWorkspaceBasePath(store, workspace);
|
|
93972
94247
|
const resolvedPath = validatePath(workspaceBase, filePath);
|
|
93973
|
-
const relativePath = relative9(
|
|
94248
|
+
const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
|
|
93974
94249
|
if (!relativePath || relativePath === "." || relativePath === "") {
|
|
93975
94250
|
throw new FileServiceError("Cannot rename workspace root directory", "EINVAL");
|
|
93976
94251
|
}
|
|
@@ -93983,12 +94258,12 @@ async function renameWorkspaceFile(store, workspace, filePath, newName) {
|
|
|
93983
94258
|
}
|
|
93984
94259
|
throw err;
|
|
93985
94260
|
}
|
|
93986
|
-
const destPath =
|
|
93987
|
-
const destRelative = relative9(
|
|
94261
|
+
const destPath = join39(dirname11(resolvedPath), newName);
|
|
94262
|
+
const destRelative = relative9(resolve19(workspaceBase), destPath);
|
|
93988
94263
|
if (destRelative.startsWith("..") || destRelative.startsWith("../") || destRelative === "..") {
|
|
93989
94264
|
throw new FileServiceError("Destination would be outside workspace", "EINVAL");
|
|
93990
94265
|
}
|
|
93991
|
-
if (!destPath.startsWith(
|
|
94266
|
+
if (!destPath.startsWith(resolve19(workspaceBase))) {
|
|
93992
94267
|
throw new FileServiceError("Destination would be outside workspace", "EINVAL");
|
|
93993
94268
|
}
|
|
93994
94269
|
try {
|
|
@@ -94017,7 +94292,7 @@ async function getWorkspaceFileForDownload(store, workspace, filePath) {
|
|
|
94017
94292
|
}
|
|
94018
94293
|
const workspaceBase = await getWorkspaceBasePath(store, workspace);
|
|
94019
94294
|
const resolvedPath = validatePath(workspaceBase, filePath);
|
|
94020
|
-
const relativePath = relative9(
|
|
94295
|
+
const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
|
|
94021
94296
|
if (!relativePath || relativePath === "." || relativePath === "") {
|
|
94022
94297
|
throw new FileServiceError("Cannot download workspace root", "EINVAL");
|
|
94023
94298
|
}
|
|
@@ -94041,7 +94316,7 @@ async function getWorkspaceFileForDownload(store, workspace, filePath) {
|
|
|
94041
94316
|
mtime: stats.mtime,
|
|
94042
94317
|
isFile: true
|
|
94043
94318
|
},
|
|
94044
|
-
fileName:
|
|
94319
|
+
fileName: basename11(resolvedPath)
|
|
94045
94320
|
};
|
|
94046
94321
|
}
|
|
94047
94322
|
async function getWorkspaceFolderForZip(store, workspace, dirPath) {
|
|
@@ -94050,7 +94325,7 @@ async function getWorkspaceFolderForZip(store, workspace, dirPath) {
|
|
|
94050
94325
|
}
|
|
94051
94326
|
const workspaceBase = await getWorkspaceBasePath(store, workspace);
|
|
94052
94327
|
const resolvedPath = validatePath(workspaceBase, dirPath);
|
|
94053
|
-
const relativePath = relative9(
|
|
94328
|
+
const relativePath = relative9(resolve19(workspaceBase), resolvedPath);
|
|
94054
94329
|
if (!relativePath || relativePath === "." || relativePath === "") {
|
|
94055
94330
|
throw new FileServiceError("Cannot download workspace root as ZIP", "EINVAL");
|
|
94056
94331
|
}
|
|
@@ -94069,14 +94344,14 @@ async function getWorkspaceFolderForZip(store, workspace, dirPath) {
|
|
|
94069
94344
|
}
|
|
94070
94345
|
return {
|
|
94071
94346
|
absolutePath: resolvedPath,
|
|
94072
|
-
dirName:
|
|
94347
|
+
dirName: basename11(resolvedPath)
|
|
94073
94348
|
};
|
|
94074
94349
|
}
|
|
94075
94350
|
function isHiddenPathSegment(name) {
|
|
94076
94351
|
return name.startsWith(".");
|
|
94077
94352
|
}
|
|
94078
94353
|
async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
94079
|
-
const currentPath = currentRelative ?
|
|
94354
|
+
const currentPath = currentRelative ? join39(basePath, currentRelative) : basePath;
|
|
94080
94355
|
let entries;
|
|
94081
94356
|
try {
|
|
94082
94357
|
entries = await readdir8(currentPath, { withFileTypes: true });
|
|
@@ -94084,7 +94359,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
|
94084
94359
|
return;
|
|
94085
94360
|
}
|
|
94086
94361
|
for (const entry of entries) {
|
|
94087
|
-
const entryRelativePath = currentRelative ?
|
|
94362
|
+
const entryRelativePath = currentRelative ? join39(currentRelative, entry.name) : entry.name;
|
|
94088
94363
|
if (entry.isDirectory()) {
|
|
94089
94364
|
if (MARKDOWN_SCAN_EXCLUDED_DIRS.has(entry.name)) {
|
|
94090
94365
|
continue;
|
|
@@ -94101,7 +94376,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
|
94101
94376
|
if (!options.showHidden && isHiddenPathSegment(entry.name)) {
|
|
94102
94377
|
continue;
|
|
94103
94378
|
}
|
|
94104
|
-
const fullPath =
|
|
94379
|
+
const fullPath = join39(basePath, entryRelativePath);
|
|
94105
94380
|
let fileStats;
|
|
94106
94381
|
try {
|
|
94107
94382
|
fileStats = await stat7(fullPath);
|
|
@@ -94151,7 +94426,7 @@ async function scanMarkdownFiles(store, options) {
|
|
|
94151
94426
|
return;
|
|
94152
94427
|
}
|
|
94153
94428
|
for (const entry of entries) {
|
|
94154
|
-
const entryRelativePath = relativeDir ?
|
|
94429
|
+
const entryRelativePath = relativeDir ? join39(relativeDir, entry.name) : entry.name;
|
|
94155
94430
|
let shouldRecurse = entry.isDirectory();
|
|
94156
94431
|
if (!shouldRecurse && typeof entry.isSymbolicLink === "function" && entry.isSymbolicLink()) {
|
|
94157
94432
|
let symlinkPath;
|
|
@@ -94241,8 +94516,8 @@ async function searchWorkspaceFiles(store, workspace, query) {
|
|
|
94241
94516
|
if (entry.isDirectory() && EXCLUDED_DIRS.has(entry.name)) {
|
|
94242
94517
|
continue;
|
|
94243
94518
|
}
|
|
94244
|
-
const fullPath =
|
|
94245
|
-
const relPath =
|
|
94519
|
+
const fullPath = join39(dir2, entry.name);
|
|
94520
|
+
const relPath = join39(relativeDir, entry.name);
|
|
94246
94521
|
if (entry.isFile()) {
|
|
94247
94522
|
if (entry.name.toLowerCase().includes(lowerQuery)) {
|
|
94248
94523
|
results.push({
|
|
@@ -94260,11 +94535,11 @@ async function searchWorkspaceFiles(store, workspace, query) {
|
|
|
94260
94535
|
return { files: results };
|
|
94261
94536
|
}
|
|
94262
94537
|
async function copyDirectoryRecursive(source, destination) {
|
|
94263
|
-
await
|
|
94538
|
+
await mkdir13(destination, { recursive: true });
|
|
94264
94539
|
const entries = await readdir8(source, { withFileTypes: true });
|
|
94265
94540
|
for (const entry of entries) {
|
|
94266
|
-
const sourcePath =
|
|
94267
|
-
const destPath =
|
|
94541
|
+
const sourcePath = join39(source, entry.name);
|
|
94542
|
+
const destPath = join39(destination, entry.name);
|
|
94268
94543
|
if (entry.isDirectory()) {
|
|
94269
94544
|
await copyDirectoryRecursive(sourcePath, destPath);
|
|
94270
94545
|
} else {
|
|
@@ -95181,9 +95456,9 @@ var require_readdir_glob = __commonJS({
|
|
|
95181
95456
|
var fs2 = __require("fs");
|
|
95182
95457
|
var { EventEmitter: EventEmitter35 } = __require("events");
|
|
95183
95458
|
var { Minimatch } = require_minimatch();
|
|
95184
|
-
var { resolve:
|
|
95459
|
+
var { resolve: resolve37 } = __require("path");
|
|
95185
95460
|
function readdir12(dir2, strict) {
|
|
95186
|
-
return new Promise((
|
|
95461
|
+
return new Promise((resolve38, reject2) => {
|
|
95187
95462
|
fs2.readdir(dir2, { withFileTypes: true }, (err, files) => {
|
|
95188
95463
|
if (err) {
|
|
95189
95464
|
switch (err.code) {
|
|
@@ -95191,7 +95466,7 @@ var require_readdir_glob = __commonJS({
|
|
|
95191
95466
|
if (strict) {
|
|
95192
95467
|
reject2(err);
|
|
95193
95468
|
} else {
|
|
95194
|
-
|
|
95469
|
+
resolve38([]);
|
|
95195
95470
|
}
|
|
95196
95471
|
break;
|
|
95197
95472
|
case "ENOTSUP":
|
|
@@ -95201,7 +95476,7 @@ var require_readdir_glob = __commonJS({
|
|
|
95201
95476
|
case "ENAMETOOLONG":
|
|
95202
95477
|
// Filename too long
|
|
95203
95478
|
case "UNKNOWN":
|
|
95204
|
-
|
|
95479
|
+
resolve38([]);
|
|
95205
95480
|
break;
|
|
95206
95481
|
case "ELOOP":
|
|
95207
95482
|
// Too many levels of symbolic links
|
|
@@ -95210,30 +95485,30 @@ var require_readdir_glob = __commonJS({
|
|
|
95210
95485
|
break;
|
|
95211
95486
|
}
|
|
95212
95487
|
} else {
|
|
95213
|
-
|
|
95488
|
+
resolve38(files);
|
|
95214
95489
|
}
|
|
95215
95490
|
});
|
|
95216
95491
|
});
|
|
95217
95492
|
}
|
|
95218
95493
|
function stat12(file, followSymlinks) {
|
|
95219
|
-
return new Promise((
|
|
95494
|
+
return new Promise((resolve38, reject2) => {
|
|
95220
95495
|
const statFunc = followSymlinks ? fs2.stat : fs2.lstat;
|
|
95221
95496
|
statFunc(file, (err, stats) => {
|
|
95222
95497
|
if (err) {
|
|
95223
95498
|
switch (err.code) {
|
|
95224
95499
|
case "ENOENT":
|
|
95225
95500
|
if (followSymlinks) {
|
|
95226
|
-
|
|
95501
|
+
resolve38(stat12(file, false));
|
|
95227
95502
|
} else {
|
|
95228
|
-
|
|
95503
|
+
resolve38(null);
|
|
95229
95504
|
}
|
|
95230
95505
|
break;
|
|
95231
95506
|
default:
|
|
95232
|
-
|
|
95507
|
+
resolve38(null);
|
|
95233
95508
|
break;
|
|
95234
95509
|
}
|
|
95235
95510
|
} else {
|
|
95236
|
-
|
|
95511
|
+
resolve38(stats);
|
|
95237
95512
|
}
|
|
95238
95513
|
});
|
|
95239
95514
|
});
|
|
@@ -95323,7 +95598,7 @@ var require_readdir_glob = __commonJS({
|
|
|
95323
95598
|
(skip) => new Minimatch(skip, { dot: true })
|
|
95324
95599
|
);
|
|
95325
95600
|
}
|
|
95326
|
-
this.iterator = explore(
|
|
95601
|
+
this.iterator = explore(resolve37(cwd || "."), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this));
|
|
95327
95602
|
this.paused = false;
|
|
95328
95603
|
this.inactive = false;
|
|
95329
95604
|
this.aborted = false;
|
|
@@ -95577,10 +95852,10 @@ function awaitify(asyncFn, arity) {
|
|
|
95577
95852
|
if (typeof args[arity - 1] === "function") {
|
|
95578
95853
|
return asyncFn.apply(this, args);
|
|
95579
95854
|
}
|
|
95580
|
-
return new Promise((
|
|
95855
|
+
return new Promise((resolve37, reject2) => {
|
|
95581
95856
|
args[arity - 1] = (err, ...cbArgs) => {
|
|
95582
95857
|
if (err) return reject2(err);
|
|
95583
|
-
|
|
95858
|
+
resolve37(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
|
|
95584
95859
|
};
|
|
95585
95860
|
asyncFn.apply(this, args);
|
|
95586
95861
|
});
|
|
@@ -95762,13 +96037,13 @@ function mapSeries(coll, iteratee, callback) {
|
|
|
95762
96037
|
return _asyncMap(eachOfSeries$1, coll, iteratee, callback);
|
|
95763
96038
|
}
|
|
95764
96039
|
function promiseCallback() {
|
|
95765
|
-
let
|
|
96040
|
+
let resolve37, reject2;
|
|
95766
96041
|
function callback(err, ...args) {
|
|
95767
96042
|
if (err) return reject2(err);
|
|
95768
|
-
|
|
96043
|
+
resolve37(args.length > 1 ? args : args[0]);
|
|
95769
96044
|
}
|
|
95770
96045
|
callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
|
|
95771
|
-
|
|
96046
|
+
resolve37 = res, reject2 = rej;
|
|
95772
96047
|
});
|
|
95773
96048
|
return callback;
|
|
95774
96049
|
}
|
|
@@ -96041,8 +96316,8 @@ function queue$1(worker, concurrency, payload) {
|
|
|
96041
96316
|
});
|
|
96042
96317
|
}
|
|
96043
96318
|
if (rejectOnError || !callback) {
|
|
96044
|
-
return new Promise((
|
|
96045
|
-
res =
|
|
96319
|
+
return new Promise((resolve37, reject2) => {
|
|
96320
|
+
res = resolve37;
|
|
96046
96321
|
rej = reject2;
|
|
96047
96322
|
});
|
|
96048
96323
|
}
|
|
@@ -96081,10 +96356,10 @@ function queue$1(worker, concurrency, payload) {
|
|
|
96081
96356
|
}
|
|
96082
96357
|
const eventMethod = (name) => (handler) => {
|
|
96083
96358
|
if (!handler) {
|
|
96084
|
-
return new Promise((
|
|
96359
|
+
return new Promise((resolve37, reject2) => {
|
|
96085
96360
|
once3(name, (err, data) => {
|
|
96086
96361
|
if (err) return reject2(err);
|
|
96087
|
-
|
|
96362
|
+
resolve37(data);
|
|
96088
96363
|
});
|
|
96089
96364
|
});
|
|
96090
96365
|
}
|
|
@@ -97745,7 +98020,7 @@ var require_graceful_fs = __commonJS({
|
|
|
97745
98020
|
function patch(fs3) {
|
|
97746
98021
|
polyfills(fs3);
|
|
97747
98022
|
fs3.gracefulify = patch;
|
|
97748
|
-
fs3.createReadStream =
|
|
98023
|
+
fs3.createReadStream = createReadStream4;
|
|
97749
98024
|
fs3.createWriteStream = createWriteStream2;
|
|
97750
98025
|
var fs$readFile = fs3.readFile;
|
|
97751
98026
|
fs3.readFile = readFile24;
|
|
@@ -97765,8 +98040,8 @@ var require_graceful_fs = __commonJS({
|
|
|
97765
98040
|
}
|
|
97766
98041
|
}
|
|
97767
98042
|
var fs$writeFile = fs3.writeFile;
|
|
97768
|
-
fs3.writeFile =
|
|
97769
|
-
function
|
|
98043
|
+
fs3.writeFile = writeFile18;
|
|
98044
|
+
function writeFile18(path5, data, options, cb) {
|
|
97770
98045
|
if (typeof options === "function")
|
|
97771
98046
|
cb = options, options = null;
|
|
97772
98047
|
return go$writeFile(path5, data, options, cb);
|
|
@@ -97955,7 +98230,7 @@ var require_graceful_fs = __commonJS({
|
|
|
97955
98230
|
}
|
|
97956
98231
|
});
|
|
97957
98232
|
}
|
|
97958
|
-
function
|
|
98233
|
+
function createReadStream4(path5, options) {
|
|
97959
98234
|
return new fs3.ReadStream(path5, options);
|
|
97960
98235
|
}
|
|
97961
98236
|
function createWriteStream2(path5, options) {
|
|
@@ -98333,7 +98608,7 @@ var require_BufferList = __commonJS({
|
|
|
98333
98608
|
this.head = this.tail = null;
|
|
98334
98609
|
this.length = 0;
|
|
98335
98610
|
};
|
|
98336
|
-
BufferList.prototype.join = function
|
|
98611
|
+
BufferList.prototype.join = function join66(s) {
|
|
98337
98612
|
if (this.length === 0) return "";
|
|
98338
98613
|
var p = this.head;
|
|
98339
98614
|
var ret = "" + p.data;
|
|
@@ -102090,25 +102365,25 @@ var require_util2 = __commonJS({
|
|
|
102090
102365
|
};
|
|
102091
102366
|
},
|
|
102092
102367
|
createDeferredPromise: function() {
|
|
102093
|
-
let
|
|
102368
|
+
let resolve37;
|
|
102094
102369
|
let reject2;
|
|
102095
102370
|
const promise = new Promise((res, rej) => {
|
|
102096
|
-
|
|
102371
|
+
resolve37 = res;
|
|
102097
102372
|
reject2 = rej;
|
|
102098
102373
|
});
|
|
102099
102374
|
return {
|
|
102100
102375
|
promise,
|
|
102101
|
-
resolve:
|
|
102376
|
+
resolve: resolve37,
|
|
102102
102377
|
reject: reject2
|
|
102103
102378
|
};
|
|
102104
102379
|
},
|
|
102105
102380
|
promisify(fn) {
|
|
102106
|
-
return new Promise((
|
|
102381
|
+
return new Promise((resolve37, reject2) => {
|
|
102107
102382
|
fn((err, ...args) => {
|
|
102108
102383
|
if (err) {
|
|
102109
102384
|
return reject2(err);
|
|
102110
102385
|
}
|
|
102111
|
-
return
|
|
102386
|
+
return resolve37(...args);
|
|
102112
102387
|
});
|
|
102113
102388
|
});
|
|
102114
102389
|
},
|
|
@@ -102900,7 +103175,7 @@ var require_end_of_stream2 = __commonJS({
|
|
|
102900
103175
|
validateBoolean3(opts.cleanup, "cleanup");
|
|
102901
103176
|
autoCleanup = opts.cleanup;
|
|
102902
103177
|
}
|
|
102903
|
-
return new Promise2((
|
|
103178
|
+
return new Promise2((resolve37, reject2) => {
|
|
102904
103179
|
const cleanup = eos(stream, opts, (err) => {
|
|
102905
103180
|
if (autoCleanup) {
|
|
102906
103181
|
cleanup();
|
|
@@ -102908,7 +103183,7 @@ var require_end_of_stream2 = __commonJS({
|
|
|
102908
103183
|
if (err) {
|
|
102909
103184
|
reject2(err);
|
|
102910
103185
|
} else {
|
|
102911
|
-
|
|
103186
|
+
resolve37();
|
|
102912
103187
|
}
|
|
102913
103188
|
});
|
|
102914
103189
|
});
|
|
@@ -104075,7 +104350,7 @@ var require_readable2 = __commonJS({
|
|
|
104075
104350
|
error = this.readableEnded ? null : new AbortError();
|
|
104076
104351
|
this.destroy(error);
|
|
104077
104352
|
}
|
|
104078
|
-
return new Promise2((
|
|
104353
|
+
return new Promise2((resolve37, reject2) => eos(this, (err) => err && err !== error ? reject2(err) : resolve37(null)));
|
|
104079
104354
|
};
|
|
104080
104355
|
Readable2.prototype.push = function(chunk, encoding) {
|
|
104081
104356
|
return readableAddChunk(this, chunk, encoding, false);
|
|
@@ -104619,12 +104894,12 @@ var require_readable2 = __commonJS({
|
|
|
104619
104894
|
}
|
|
104620
104895
|
async function* createAsyncIterator(stream, options) {
|
|
104621
104896
|
let callback = nop;
|
|
104622
|
-
function next(
|
|
104897
|
+
function next(resolve37) {
|
|
104623
104898
|
if (this === stream) {
|
|
104624
104899
|
callback();
|
|
104625
104900
|
callback = nop;
|
|
104626
104901
|
} else {
|
|
104627
|
-
callback =
|
|
104902
|
+
callback = resolve37;
|
|
104628
104903
|
}
|
|
104629
104904
|
}
|
|
104630
104905
|
stream.on("readable", next);
|
|
@@ -105677,7 +105952,7 @@ var require_duplexify = __commonJS({
|
|
|
105677
105952
|
);
|
|
105678
105953
|
};
|
|
105679
105954
|
function fromAsyncGen(fn) {
|
|
105680
|
-
let { promise, resolve:
|
|
105955
|
+
let { promise, resolve: resolve37 } = createDeferredPromise();
|
|
105681
105956
|
const ac = new AbortController2();
|
|
105682
105957
|
const signal = ac.signal;
|
|
105683
105958
|
const value = fn(
|
|
@@ -105692,7 +105967,7 @@ var require_duplexify = __commonJS({
|
|
|
105692
105967
|
throw new AbortError(void 0, {
|
|
105693
105968
|
cause: signal.reason
|
|
105694
105969
|
});
|
|
105695
|
-
({ promise, resolve:
|
|
105970
|
+
({ promise, resolve: resolve37 } = createDeferredPromise());
|
|
105696
105971
|
yield chunk;
|
|
105697
105972
|
}
|
|
105698
105973
|
})(),
|
|
@@ -105703,8 +105978,8 @@ var require_duplexify = __commonJS({
|
|
|
105703
105978
|
return {
|
|
105704
105979
|
value,
|
|
105705
105980
|
write(chunk, encoding, cb) {
|
|
105706
|
-
const _resolve =
|
|
105707
|
-
|
|
105981
|
+
const _resolve = resolve37;
|
|
105982
|
+
resolve37 = null;
|
|
105708
105983
|
_resolve({
|
|
105709
105984
|
chunk,
|
|
105710
105985
|
done: false,
|
|
@@ -105712,8 +105987,8 @@ var require_duplexify = __commonJS({
|
|
|
105712
105987
|
});
|
|
105713
105988
|
},
|
|
105714
105989
|
final(cb) {
|
|
105715
|
-
const _resolve =
|
|
105716
|
-
|
|
105990
|
+
const _resolve = resolve37;
|
|
105991
|
+
resolve37 = null;
|
|
105717
105992
|
_resolve({
|
|
105718
105993
|
done: true,
|
|
105719
105994
|
cb
|
|
@@ -106165,7 +106440,7 @@ var require_pipeline = __commonJS({
|
|
|
106165
106440
|
callback();
|
|
106166
106441
|
}
|
|
106167
106442
|
};
|
|
106168
|
-
const wait = () => new Promise2((
|
|
106443
|
+
const wait = () => new Promise2((resolve37, reject2) => {
|
|
106169
106444
|
if (error) {
|
|
106170
106445
|
reject2(error);
|
|
106171
106446
|
} else {
|
|
@@ -106173,7 +106448,7 @@ var require_pipeline = __commonJS({
|
|
|
106173
106448
|
if (error) {
|
|
106174
106449
|
reject2(error);
|
|
106175
106450
|
} else {
|
|
106176
|
-
|
|
106451
|
+
resolve37();
|
|
106177
106452
|
}
|
|
106178
106453
|
};
|
|
106179
106454
|
}
|
|
@@ -106817,8 +107092,8 @@ var require_operators = __commonJS({
|
|
|
106817
107092
|
next = null;
|
|
106818
107093
|
}
|
|
106819
107094
|
if (!done && (queue2.length >= highWaterMark2 || cnt >= concurrency)) {
|
|
106820
|
-
await new Promise2((
|
|
106821
|
-
resume =
|
|
107095
|
+
await new Promise2((resolve37) => {
|
|
107096
|
+
resume = resolve37;
|
|
106822
107097
|
});
|
|
106823
107098
|
}
|
|
106824
107099
|
}
|
|
@@ -106852,8 +107127,8 @@ var require_operators = __commonJS({
|
|
|
106852
107127
|
queue2.shift();
|
|
106853
107128
|
maybeResume();
|
|
106854
107129
|
}
|
|
106855
|
-
await new Promise2((
|
|
106856
|
-
next =
|
|
107130
|
+
await new Promise2((resolve37) => {
|
|
107131
|
+
next = resolve37;
|
|
106857
107132
|
});
|
|
106858
107133
|
}
|
|
106859
107134
|
} finally {
|
|
@@ -107111,7 +107386,7 @@ var require_promises = __commonJS({
|
|
|
107111
107386
|
var { finished } = require_end_of_stream2();
|
|
107112
107387
|
require_stream2();
|
|
107113
107388
|
function pipeline(...streams) {
|
|
107114
|
-
return new Promise2((
|
|
107389
|
+
return new Promise2((resolve37, reject2) => {
|
|
107115
107390
|
let signal;
|
|
107116
107391
|
let end;
|
|
107117
107392
|
const lastArg = streams[streams.length - 1];
|
|
@@ -107126,7 +107401,7 @@ var require_promises = __commonJS({
|
|
|
107126
107401
|
if (err) {
|
|
107127
107402
|
reject2(err);
|
|
107128
107403
|
} else {
|
|
107129
|
-
|
|
107404
|
+
resolve37(value);
|
|
107130
107405
|
}
|
|
107131
107406
|
},
|
|
107132
107407
|
{
|
|
@@ -111899,10 +112174,10 @@ var require_commonjs3 = __commonJS({
|
|
|
111899
112174
|
* Return a void Promise that resolves once the stream ends.
|
|
111900
112175
|
*/
|
|
111901
112176
|
async promise() {
|
|
111902
|
-
return new Promise((
|
|
112177
|
+
return new Promise((resolve37, reject2) => {
|
|
111903
112178
|
this.on(DESTROYED, () => reject2(new Error("stream destroyed")));
|
|
111904
112179
|
this.on("error", (er) => reject2(er));
|
|
111905
|
-
this.on("end", () =>
|
|
112180
|
+
this.on("end", () => resolve37());
|
|
111906
112181
|
});
|
|
111907
112182
|
}
|
|
111908
112183
|
/**
|
|
@@ -111926,7 +112201,7 @@ var require_commonjs3 = __commonJS({
|
|
|
111926
112201
|
return Promise.resolve({ done: false, value: res });
|
|
111927
112202
|
if (this[EOF])
|
|
111928
112203
|
return stop();
|
|
111929
|
-
let
|
|
112204
|
+
let resolve37;
|
|
111930
112205
|
let reject2;
|
|
111931
112206
|
const onerr = (er) => {
|
|
111932
112207
|
this.off("data", ondata);
|
|
@@ -111940,19 +112215,19 @@ var require_commonjs3 = __commonJS({
|
|
|
111940
112215
|
this.off("end", onend);
|
|
111941
112216
|
this.off(DESTROYED, ondestroy);
|
|
111942
112217
|
this.pause();
|
|
111943
|
-
|
|
112218
|
+
resolve37({ value, done: !!this[EOF] });
|
|
111944
112219
|
};
|
|
111945
112220
|
const onend = () => {
|
|
111946
112221
|
this.off("error", onerr);
|
|
111947
112222
|
this.off("data", ondata);
|
|
111948
112223
|
this.off(DESTROYED, ondestroy);
|
|
111949
112224
|
stop();
|
|
111950
|
-
|
|
112225
|
+
resolve37({ done: true, value: void 0 });
|
|
111951
112226
|
};
|
|
111952
112227
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
111953
112228
|
return new Promise((res2, rej) => {
|
|
111954
112229
|
reject2 = rej;
|
|
111955
|
-
|
|
112230
|
+
resolve37 = res2;
|
|
111956
112231
|
this.once(DESTROYED, ondestroy);
|
|
111957
112232
|
this.once("error", onerr);
|
|
111958
112233
|
this.once("end", onend);
|
|
@@ -112968,9 +113243,9 @@ var require_commonjs4 = __commonJS({
|
|
|
112968
113243
|
if (this.#asyncReaddirInFlight) {
|
|
112969
113244
|
await this.#asyncReaddirInFlight;
|
|
112970
113245
|
} else {
|
|
112971
|
-
let
|
|
113246
|
+
let resolve37 = () => {
|
|
112972
113247
|
};
|
|
112973
|
-
this.#asyncReaddirInFlight = new Promise((res) =>
|
|
113248
|
+
this.#asyncReaddirInFlight = new Promise((res) => resolve37 = res);
|
|
112974
113249
|
try {
|
|
112975
113250
|
for (const e of await this.#fs.promises.readdir(fullpath, {
|
|
112976
113251
|
withFileTypes: true
|
|
@@ -112983,7 +113258,7 @@ var require_commonjs4 = __commonJS({
|
|
|
112983
113258
|
children.provisional = 0;
|
|
112984
113259
|
}
|
|
112985
113260
|
this.#asyncReaddirInFlight = void 0;
|
|
112986
|
-
|
|
113261
|
+
resolve37();
|
|
112987
113262
|
}
|
|
112988
113263
|
return children.slice(0, children.provisional);
|
|
112989
113264
|
}
|
|
@@ -115756,11 +116031,11 @@ var require_core = __commonJS({
|
|
|
115756
116031
|
this._finalize();
|
|
115757
116032
|
}
|
|
115758
116033
|
var self2 = this;
|
|
115759
|
-
return new Promise(function(
|
|
116034
|
+
return new Promise(function(resolve37, reject2) {
|
|
115760
116035
|
var errored;
|
|
115761
116036
|
self2._module.on("end", function() {
|
|
115762
116037
|
if (!errored) {
|
|
115763
|
-
|
|
116038
|
+
resolve37();
|
|
115764
116039
|
}
|
|
115765
116040
|
});
|
|
115766
116041
|
self2._module.on("error", function(err) {
|
|
@@ -118200,8 +118475,8 @@ var require_streamx = __commonJS({
|
|
|
118200
118475
|
return this;
|
|
118201
118476
|
},
|
|
118202
118477
|
next() {
|
|
118203
|
-
return new Promise(function(
|
|
118204
|
-
promiseResolve =
|
|
118478
|
+
return new Promise(function(resolve37, reject2) {
|
|
118479
|
+
promiseResolve = resolve37;
|
|
118205
118480
|
promiseReject = reject2;
|
|
118206
118481
|
const data = stream.read();
|
|
118207
118482
|
if (data !== null) ondata(data);
|
|
@@ -118231,11 +118506,11 @@ var require_streamx = __commonJS({
|
|
|
118231
118506
|
}
|
|
118232
118507
|
function destroy(err) {
|
|
118233
118508
|
stream.destroy(err);
|
|
118234
|
-
return new Promise((
|
|
118235
|
-
if (stream._duplexState & DESTROYED) return
|
|
118509
|
+
return new Promise((resolve37, reject2) => {
|
|
118510
|
+
if (stream._duplexState & DESTROYED) return resolve37({ value: void 0, done: true });
|
|
118236
118511
|
stream.once("close", function() {
|
|
118237
118512
|
if (err) reject2(err);
|
|
118238
|
-
else
|
|
118513
|
+
else resolve37({ value: void 0, done: true });
|
|
118239
118514
|
});
|
|
118240
118515
|
});
|
|
118241
118516
|
}
|
|
@@ -118279,8 +118554,8 @@ var require_streamx = __commonJS({
|
|
|
118279
118554
|
const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
|
|
118280
118555
|
if (writes === 0) return Promise.resolve(true);
|
|
118281
118556
|
if (state.drains === null) state.drains = [];
|
|
118282
|
-
return new Promise((
|
|
118283
|
-
state.drains.push({ writes, resolve:
|
|
118557
|
+
return new Promise((resolve37) => {
|
|
118558
|
+
state.drains.push({ writes, resolve: resolve37 });
|
|
118284
118559
|
});
|
|
118285
118560
|
}
|
|
118286
118561
|
write(data) {
|
|
@@ -118385,10 +118660,10 @@ var require_streamx = __commonJS({
|
|
|
118385
118660
|
cb(null);
|
|
118386
118661
|
}
|
|
118387
118662
|
function pipelinePromise(...streams) {
|
|
118388
|
-
return new Promise((
|
|
118663
|
+
return new Promise((resolve37, reject2) => {
|
|
118389
118664
|
return pipeline(...streams, (err) => {
|
|
118390
118665
|
if (err) return reject2(err);
|
|
118391
|
-
|
|
118666
|
+
resolve37();
|
|
118392
118667
|
});
|
|
118393
118668
|
});
|
|
118394
118669
|
}
|
|
@@ -119045,16 +119320,16 @@ var require_extract = __commonJS({
|
|
|
119045
119320
|
entryCallback = null;
|
|
119046
119321
|
cb(err);
|
|
119047
119322
|
}
|
|
119048
|
-
function onnext(
|
|
119323
|
+
function onnext(resolve37, reject2) {
|
|
119049
119324
|
if (error) {
|
|
119050
119325
|
return reject2(error);
|
|
119051
119326
|
}
|
|
119052
119327
|
if (entryStream) {
|
|
119053
|
-
|
|
119328
|
+
resolve37({ value: entryStream, done: false });
|
|
119054
119329
|
entryStream = null;
|
|
119055
119330
|
return;
|
|
119056
119331
|
}
|
|
119057
|
-
promiseResolve =
|
|
119332
|
+
promiseResolve = resolve37;
|
|
119058
119333
|
promiseReject = reject2;
|
|
119059
119334
|
consumeCallback(null);
|
|
119060
119335
|
if (extract._finished && promiseResolve) {
|
|
@@ -119082,11 +119357,11 @@ var require_extract = __commonJS({
|
|
|
119082
119357
|
function destroy(err) {
|
|
119083
119358
|
extract.destroy(err);
|
|
119084
119359
|
consumeCallback(err);
|
|
119085
|
-
return new Promise((
|
|
119086
|
-
if (extract.destroyed) return
|
|
119360
|
+
return new Promise((resolve37, reject2) => {
|
|
119361
|
+
if (extract.destroyed) return resolve37({ value: void 0, done: true });
|
|
119087
119362
|
extract.once("close", function() {
|
|
119088
119363
|
if (err) reject2(err);
|
|
119089
|
-
else
|
|
119364
|
+
else resolve37({ value: void 0, done: true });
|
|
119090
119365
|
});
|
|
119091
119366
|
});
|
|
119092
119367
|
}
|
|
@@ -119857,7 +120132,7 @@ var require_archiver = __commonJS({
|
|
|
119857
120132
|
|
|
119858
120133
|
// ../dashboard/src/routes/register-file-workspace-routes.ts
|
|
119859
120134
|
import { access as access5 } from "node:fs/promises";
|
|
119860
|
-
import { createReadStream as
|
|
120135
|
+
import { createReadStream as createReadStream3 } from "node:fs";
|
|
119861
120136
|
function extractFileParams(req) {
|
|
119862
120137
|
const filePath = Array.isArray(req.params.filepath) ? req.params.filepath[0] : req.params.filepath ?? "";
|
|
119863
120138
|
const workspace = typeof req.query.workspace === "string" && req.query.workspace.length > 0 ? req.query.workspace : "project";
|
|
@@ -119908,7 +120183,7 @@ function registerFileWorkspaceRoutes(ctx) {
|
|
|
119908
120183
|
if (typeof content !== "string") {
|
|
119909
120184
|
throw badRequest("content is required and must be a string");
|
|
119910
120185
|
}
|
|
119911
|
-
const result = await
|
|
120186
|
+
const result = await writeFile13(scopedStore, req.params.id, filePath, content);
|
|
119912
120187
|
res.json(result);
|
|
119913
120188
|
} catch (err) {
|
|
119914
120189
|
if (err instanceof ApiError) {
|
|
@@ -120119,7 +120394,7 @@ function registerFileWorkspaceRoutes(ctx) {
|
|
|
120119
120394
|
res.setHeader("Content-Disposition", `attachment; filename="${fileName}"`);
|
|
120120
120395
|
res.setHeader("Content-Length", stats.size);
|
|
120121
120396
|
res.setHeader("Last-Modified", stats.mtime.toUTCString());
|
|
120122
|
-
const stream =
|
|
120397
|
+
const stream = createReadStream3(absolutePath);
|
|
120123
120398
|
stream.pipe(res);
|
|
120124
120399
|
} catch (err) {
|
|
120125
120400
|
if (err instanceof ApiError) {
|
|
@@ -120866,8 +121141,8 @@ var init_exec_file = __esm({
|
|
|
120866
121141
|
|
|
120867
121142
|
// ../dashboard/src/routes/register-project-routes.ts
|
|
120868
121143
|
import * as fsPromises from "node:fs/promises";
|
|
120869
|
-
import { dirname as dirname12, isAbsolute as isAbsolute14, join as
|
|
120870
|
-
var access7, stat8,
|
|
121144
|
+
import { dirname as dirname12, isAbsolute as isAbsolute14, join as join40 } from "node:path";
|
|
121145
|
+
var access7, stat8, mkdir14, readdir9, rm3, registerProjectRoutes;
|
|
120871
121146
|
var init_register_project_routes = __esm({
|
|
120872
121147
|
"../dashboard/src/routes/register-project-routes.ts"() {
|
|
120873
121148
|
"use strict";
|
|
@@ -120878,9 +121153,9 @@ var init_register_project_routes = __esm({
|
|
|
120878
121153
|
({
|
|
120879
121154
|
access: access7,
|
|
120880
121155
|
stat: stat8,
|
|
120881
|
-
mkdir:
|
|
121156
|
+
mkdir: mkdir14,
|
|
120882
121157
|
readdir: readdir9,
|
|
120883
|
-
rm:
|
|
121158
|
+
rm: rm3
|
|
120884
121159
|
} = fsPromises);
|
|
120885
121160
|
registerProjectRoutes = (ctx) => {
|
|
120886
121161
|
const { router, options, runtimeLogger, prioritizeProjectsForCurrentDirectory, rethrowAsApiError: rethrowAsApiError7 } = ctx;
|
|
@@ -121031,7 +121306,7 @@ var init_register_project_routes = __esm({
|
|
|
121031
121306
|
throw badRequest("Clone destination must be empty");
|
|
121032
121307
|
}
|
|
121033
121308
|
} else {
|
|
121034
|
-
await
|
|
121309
|
+
await mkdir14(normalizedPath, { recursive: false });
|
|
121035
121310
|
destinationCreatedForClone = true;
|
|
121036
121311
|
}
|
|
121037
121312
|
const cloneSource = normalizedCloneUrl;
|
|
@@ -121047,7 +121322,7 @@ var init_register_project_routes = __esm({
|
|
|
121047
121322
|
} catch (cloneError) {
|
|
121048
121323
|
if (destinationCreatedForClone) {
|
|
121049
121324
|
try {
|
|
121050
|
-
await
|
|
121325
|
+
await rm3(normalizedPath, { recursive: true, force: true });
|
|
121051
121326
|
} catch {
|
|
121052
121327
|
}
|
|
121053
121328
|
}
|
|
@@ -121057,7 +121332,7 @@ var init_register_project_routes = __esm({
|
|
|
121057
121332
|
}
|
|
121058
121333
|
}
|
|
121059
121334
|
let hasFusionDir = false;
|
|
121060
|
-
const fusionDirPath =
|
|
121335
|
+
const fusionDirPath = join40(normalizedPath, ".fusion");
|
|
121061
121336
|
try {
|
|
121062
121337
|
await access7(fusionDirPath);
|
|
121063
121338
|
hasFusionDir = true;
|
|
@@ -121119,18 +121394,18 @@ var init_register_project_routes = __esm({
|
|
|
121119
121394
|
const entries = await readdir9(searchPath, { withFileTypes: true });
|
|
121120
121395
|
for (const entry of entries) {
|
|
121121
121396
|
if (!entry.isDirectory()) continue;
|
|
121122
|
-
const dirPath =
|
|
121397
|
+
const dirPath = join40(searchPath, entry.name);
|
|
121123
121398
|
let hasKbDb = false;
|
|
121124
121399
|
let hasFusionDir = false;
|
|
121125
121400
|
try {
|
|
121126
|
-
await access7(
|
|
121401
|
+
await access7(join40(dirPath, ".fusion", "fusion.db"));
|
|
121127
121402
|
hasKbDb = true;
|
|
121128
121403
|
} catch {
|
|
121129
121404
|
hasKbDb = false;
|
|
121130
121405
|
}
|
|
121131
121406
|
if (!hasKbDb) {
|
|
121132
121407
|
try {
|
|
121133
|
-
await access7(
|
|
121408
|
+
await access7(join40(dirPath, ".fusion"));
|
|
121134
121409
|
hasFusionDir = true;
|
|
121135
121410
|
} catch {
|
|
121136
121411
|
hasFusionDir = false;
|
|
@@ -124134,7 +124409,7 @@ var init_register_agent_reflection_rating_routes = __esm({
|
|
|
124134
124409
|
});
|
|
124135
124410
|
|
|
124136
124411
|
// ../dashboard/src/agent-generation.ts
|
|
124137
|
-
import { randomUUID as
|
|
124412
|
+
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
124138
124413
|
async function initPromptCatalog() {
|
|
124139
124414
|
if (promptCatalogReady) return;
|
|
124140
124415
|
try {
|
|
@@ -124340,7 +124615,7 @@ async function startAgentGeneration(ip, roleDescription) {
|
|
|
124340
124615
|
`Rate limit exceeded. Maximum ${MAX_SESSIONS_PER_IP_PER_HOUR4} generation sessions per hour. Reset at ${resetTime?.toISOString() || "unknown"}`
|
|
124341
124616
|
);
|
|
124342
124617
|
}
|
|
124343
|
-
const sessionId =
|
|
124618
|
+
const sessionId = randomUUID17();
|
|
124344
124619
|
const session = {
|
|
124345
124620
|
id: sessionId,
|
|
124346
124621
|
ip,
|
|
@@ -124518,7 +124793,7 @@ You MUST respond with ONLY valid JSON (no markdown, no explanation):
|
|
|
124518
124793
|
import { createWriteStream } from "node:fs";
|
|
124519
124794
|
import * as fsPromises2 from "node:fs/promises";
|
|
124520
124795
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
124521
|
-
import { join as
|
|
124796
|
+
import { join as join41, resolve as resolve20 } from "node:path";
|
|
124522
124797
|
import { Readable } from "node:stream";
|
|
124523
124798
|
import { pipeline as streamPipeline } from "node:stream/promises";
|
|
124524
124799
|
function registerAgentImportExportRoutes(ctx) {
|
|
@@ -124555,11 +124830,11 @@ function registerAgentImportExportRoutes(ctx) {
|
|
|
124555
124830
|
}
|
|
124556
124831
|
let resolvedOutputDir;
|
|
124557
124832
|
if (typeof outputDir === "string" && outputDir.trim().length > 0) {
|
|
124558
|
-
resolvedOutputDir =
|
|
124833
|
+
resolvedOutputDir = resolve20(outputDir.trim());
|
|
124559
124834
|
} else if (typeof outputDir === "string") {
|
|
124560
124835
|
throw badRequest("outputDir cannot be empty");
|
|
124561
124836
|
} else {
|
|
124562
|
-
resolvedOutputDir = await mkdtemp(
|
|
124837
|
+
resolvedOutputDir = await mkdtemp(join41(tmpdir3(), "fusion-agent-export-"));
|
|
124563
124838
|
}
|
|
124564
124839
|
const result = await exportAgentsToDirectory2(agentsToExport, resolvedOutputDir, {
|
|
124565
124840
|
companyName: typeof companyName === "string" ? companyName : void 0,
|
|
@@ -124686,7 +124961,7 @@ ${body}`;
|
|
|
124686
124961
|
return result;
|
|
124687
124962
|
}
|
|
124688
124963
|
const safeCompanySlug = companySlug ? slugifyPathSegment2(companySlug, "unknown-company") : "unknown-company";
|
|
124689
|
-
const skillsBaseDir =
|
|
124964
|
+
const skillsBaseDir = join41(projectRoot, "skills", "imported", safeCompanySlug);
|
|
124690
124965
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
124691
124966
|
for (const skill of skills) {
|
|
124692
124967
|
const name = typeof skill.name === "string" && skill.name.trim().length > 0 ? skill.name.trim() : null;
|
|
@@ -124703,8 +124978,8 @@ ${body}`;
|
|
|
124703
124978
|
skillSlug = `${skillSlug}-${counter}`;
|
|
124704
124979
|
}
|
|
124705
124980
|
usedSlugs.add(skillSlug);
|
|
124706
|
-
const skillDir =
|
|
124707
|
-
const skillPath =
|
|
124981
|
+
const skillDir = join41(skillsBaseDir, skillSlug);
|
|
124982
|
+
const skillPath = join41(skillDir, "SKILL.md");
|
|
124708
124983
|
try {
|
|
124709
124984
|
await access8(skillPath);
|
|
124710
124985
|
result.skipped.push(name);
|
|
@@ -124740,7 +125015,7 @@ ${body}`;
|
|
|
124740
125015
|
|
|
124741
125016
|
<!-- Add skill instructions here. -->`;
|
|
124742
125017
|
try {
|
|
124743
|
-
await
|
|
125018
|
+
await mkdir15(skillDir, { recursive: true });
|
|
124744
125019
|
const content = toSkillMarkdown2(frontmatter, body);
|
|
124745
125020
|
await fsWriteFile2(skillPath, content, "utf-8");
|
|
124746
125021
|
result.imported.push({ name, path: `skills/imported/${safeCompanySlug}/${skillSlug}/SKILL.md` });
|
|
@@ -124790,7 +125065,7 @@ ${body}`;
|
|
|
124790
125065
|
tasks: []
|
|
124791
125066
|
};
|
|
124792
125067
|
} else if (typeof source === "string" && source.trim()) {
|
|
124793
|
-
const sourcePath =
|
|
125068
|
+
const sourcePath = resolve20(source);
|
|
124794
125069
|
const isArchive = sourcePath.endsWith(".tar.gz") || sourcePath.endsWith(".tgz") || sourcePath.endsWith(".zip");
|
|
124795
125070
|
if (isArchive) {
|
|
124796
125071
|
try {
|
|
@@ -124874,8 +125149,8 @@ ${body}`;
|
|
|
124874
125149
|
const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/main.tar.gz`;
|
|
124875
125150
|
let tempDir = null;
|
|
124876
125151
|
try {
|
|
124877
|
-
tempDir = await mkdtemp(
|
|
124878
|
-
const archivePath =
|
|
125152
|
+
tempDir = await mkdtemp(join41(tmpdir3(), `fn-agent-import-${importCompanySlug}-`));
|
|
125153
|
+
const archivePath = join41(tempDir, "archive.tar.gz");
|
|
124879
125154
|
const downloadController = new AbortController();
|
|
124880
125155
|
const downloadTimeout = setTimeout(() => downloadController.abort(), 3e4);
|
|
124881
125156
|
let archiveResponse;
|
|
@@ -124919,7 +125194,7 @@ ${body}`;
|
|
|
124919
125194
|
} finally {
|
|
124920
125195
|
if (tempDir) {
|
|
124921
125196
|
try {
|
|
124922
|
-
await
|
|
125197
|
+
await rm4(tempDir, { recursive: true, force: true });
|
|
124923
125198
|
} catch {
|
|
124924
125199
|
}
|
|
124925
125200
|
}
|
|
@@ -125127,14 +125402,14 @@ function registerAgentGenerationRoutes(ctx) {
|
|
|
125127
125402
|
}
|
|
125128
125403
|
});
|
|
125129
125404
|
}
|
|
125130
|
-
var mkdtemp, access8, stat9,
|
|
125405
|
+
var mkdtemp, access8, stat9, mkdir15, rm4, fsWriteFile2;
|
|
125131
125406
|
var init_register_agent_import_export_generation_routes = __esm({
|
|
125132
125407
|
"../dashboard/src/routes/register-agent-import-export-generation-routes.ts"() {
|
|
125133
125408
|
"use strict";
|
|
125134
125409
|
init_api_error();
|
|
125135
125410
|
init_ai_session_diagnostics();
|
|
125136
125411
|
init_agent_generation();
|
|
125137
|
-
({ mkdtemp, access: access8, stat: stat9, mkdir:
|
|
125412
|
+
({ mkdtemp, access: access8, stat: stat9, mkdir: mkdir15, rm: rm4, writeFile: fsWriteFile2 } = fsPromises2);
|
|
125138
125413
|
}
|
|
125139
125414
|
});
|
|
125140
125415
|
|
|
@@ -125591,9 +125866,9 @@ function registerProxyRoutes(router, deps) {
|
|
|
125591
125866
|
if (req.rawBody && req.rawBody.length > 0) {
|
|
125592
125867
|
body = req.rawBody;
|
|
125593
125868
|
} else {
|
|
125594
|
-
await new Promise((
|
|
125869
|
+
await new Promise((resolve37, reject2) => {
|
|
125595
125870
|
req.on("data", (chunk) => chunks.push(chunk));
|
|
125596
|
-
req.on("end",
|
|
125871
|
+
req.on("end", resolve37);
|
|
125597
125872
|
req.on("error", reject2);
|
|
125598
125873
|
});
|
|
125599
125874
|
if (chunks.length > 0) {
|
|
@@ -125789,13 +126064,13 @@ import { readFile as readFile19 } from "node:fs/promises";
|
|
|
125789
126064
|
import * as https from "node:https";
|
|
125790
126065
|
import * as child_process from "node:child_process";
|
|
125791
126066
|
function execFileAsync4(file, args, options) {
|
|
125792
|
-
return new Promise((
|
|
126067
|
+
return new Promise((resolve37, reject2) => {
|
|
125793
126068
|
child_process.execFile(file, args, options, (error, stdout, stderr) => {
|
|
125794
126069
|
if (error) {
|
|
125795
126070
|
reject2(error);
|
|
125796
126071
|
return;
|
|
125797
126072
|
}
|
|
125798
|
-
|
|
126073
|
+
resolve37({ stdout: String(stdout), stderr: String(stderr) });
|
|
125799
126074
|
});
|
|
125800
126075
|
});
|
|
125801
126076
|
}
|
|
@@ -125854,7 +126129,7 @@ function formatDuration(ms) {
|
|
|
125854
126129
|
return remHours > 0 ? `${days}d ${remHours}h` : `${days}d`;
|
|
125855
126130
|
}
|
|
125856
126131
|
function httpsRequest(url, options) {
|
|
125857
|
-
return new Promise((
|
|
126132
|
+
return new Promise((resolve37, reject2) => {
|
|
125858
126133
|
const parsed = new URL(url);
|
|
125859
126134
|
const req = https.request(
|
|
125860
126135
|
{
|
|
@@ -125874,7 +126149,7 @@ function httpsRequest(url, options) {
|
|
|
125874
126149
|
if (typeof v === "string") hdrs[k.toLowerCase()] = v;
|
|
125875
126150
|
else if (Array.isArray(v)) hdrs[k.toLowerCase()] = v.join(", ");
|
|
125876
126151
|
}
|
|
125877
|
-
|
|
126152
|
+
resolve37({
|
|
125878
126153
|
status: res.statusCode || 0,
|
|
125879
126154
|
headers: hdrs,
|
|
125880
126155
|
body: Buffer.concat(chunks).toString("utf-8")
|
|
@@ -126121,7 +126396,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
126121
126396
|
env: { ...process.env, TERM: "xterm-256color" }
|
|
126122
126397
|
};
|
|
126123
126398
|
if (isWindows) ptyOptions.useConpty = false;
|
|
126124
|
-
const output = await new Promise((
|
|
126399
|
+
const output = await new Promise((resolve37, reject2) => {
|
|
126125
126400
|
let buf = "";
|
|
126126
126401
|
let settled = false;
|
|
126127
126402
|
let sentCommand = false;
|
|
@@ -126137,7 +126412,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
126137
126412
|
}
|
|
126138
126413
|
const clean = _stripClaudeAnsi(buf);
|
|
126139
126414
|
if (clean.includes("Current session") || clean.includes("% left") || clean.includes("% used")) {
|
|
126140
|
-
|
|
126415
|
+
resolve37(buf);
|
|
126141
126416
|
} else {
|
|
126142
126417
|
reject2(new Error("Claude CLI timed out after 60s \u2014 got output but no usage data. Try running `claude /usage` manually."));
|
|
126143
126418
|
}
|
|
@@ -126188,7 +126463,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
126188
126463
|
ptyProcess.kill();
|
|
126189
126464
|
} catch {
|
|
126190
126465
|
}
|
|
126191
|
-
|
|
126466
|
+
resolve37(buf);
|
|
126192
126467
|
}
|
|
126193
126468
|
}, 2e3);
|
|
126194
126469
|
}
|
|
@@ -126199,7 +126474,7 @@ async function fetchClaudeUsageViaCli() {
|
|
|
126199
126474
|
if (settled) return;
|
|
126200
126475
|
settled = true;
|
|
126201
126476
|
clearTimeout(timeout2);
|
|
126202
|
-
|
|
126477
|
+
resolve37(buf);
|
|
126203
126478
|
});
|
|
126204
126479
|
});
|
|
126205
126480
|
const cleanOutput = _stripClaudeAnsi(output);
|
|
@@ -126867,9 +127142,9 @@ async function fetchGitHubCopilotUsage() {
|
|
|
126867
127142
|
return usage;
|
|
126868
127143
|
}
|
|
126869
127144
|
function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_TIMEOUT_MS) {
|
|
126870
|
-
return new Promise((
|
|
127145
|
+
return new Promise((resolve37) => {
|
|
126871
127146
|
const timer = setTimeout(() => {
|
|
126872
|
-
|
|
127147
|
+
resolve37({
|
|
126873
127148
|
name: providerName,
|
|
126874
127149
|
icon: "\u23F1\uFE0F",
|
|
126875
127150
|
status: "error",
|
|
@@ -126879,10 +127154,10 @@ function withTimeout(providerPromise, providerName, timeoutMs = PROVIDER_FETCH_T
|
|
|
126879
127154
|
}, timeoutMs);
|
|
126880
127155
|
providerPromise.then((result) => {
|
|
126881
127156
|
clearTimeout(timer);
|
|
126882
|
-
|
|
127157
|
+
resolve37(result);
|
|
126883
127158
|
}).catch((err) => {
|
|
126884
127159
|
clearTimeout(timer);
|
|
126885
|
-
|
|
127160
|
+
resolve37({
|
|
126886
127161
|
name: providerName,
|
|
126887
127162
|
icon: "\u23F1\uFE0F",
|
|
126888
127163
|
status: "error",
|
|
@@ -126937,7 +127212,7 @@ var init_usage = __esm({
|
|
|
126937
127212
|
ANTHROPIC_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
126938
127213
|
ANTHROPIC_OAUTH_BETA = "oauth-2025-04-20";
|
|
126939
127214
|
CLAUDE_USAGE_USER_AGENT = "claude-code-fusion-dashboard";
|
|
126940
|
-
_sleep = (ms) => new Promise((
|
|
127215
|
+
_sleep = (ms) => new Promise((resolve37) => setTimeout(resolve37, ms));
|
|
126941
127216
|
sleepFn = _sleep;
|
|
126942
127217
|
PROVIDER_FETCH_TIMEOUT_MS = 1e4;
|
|
126943
127218
|
CLAUDE_FETCH_TIMEOUT_MS = 75e3;
|
|
@@ -127251,8 +127526,8 @@ var init_register_auth_routes = __esm({
|
|
|
127251
127526
|
loginInProgress.set(provider, abortController);
|
|
127252
127527
|
let authResolve;
|
|
127253
127528
|
let authReject;
|
|
127254
|
-
const authUrlPromise = new Promise((
|
|
127255
|
-
authResolve =
|
|
127529
|
+
const authUrlPromise = new Promise((resolve37, reject2) => {
|
|
127530
|
+
authResolve = resolve37;
|
|
127256
127531
|
authReject = reject2;
|
|
127257
127532
|
});
|
|
127258
127533
|
const loginPromise = storage.login(provider, {
|
|
@@ -127678,7 +127953,7 @@ async function mintAgentApiKeyViaCli(opts) {
|
|
|
127678
127953
|
args.push("--data-dir", opts.dataDir);
|
|
127679
127954
|
}
|
|
127680
127955
|
const timeoutMs = opts.cliTimeoutMs ?? 3e4;
|
|
127681
|
-
return new Promise((
|
|
127956
|
+
return new Promise((resolve37, reject2) => {
|
|
127682
127957
|
let child;
|
|
127683
127958
|
try {
|
|
127684
127959
|
child = spawn15(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -127752,7 +128027,7 @@ async function mintAgentApiKeyViaCli(opts) {
|
|
|
127752
128027
|
const apiBase = (typeof r.apiBase === "string" ? r.apiBase : void 0) ?? (typeof r.api_base === "string" ? r.api_base : void 0);
|
|
127753
128028
|
const agentId = (typeof r.agentId === "string" ? r.agentId : void 0) ?? (typeof r.id === "string" ? r.id : void 0);
|
|
127754
128029
|
const companyId = typeof r.companyId === "string" ? r.companyId : void 0;
|
|
127755
|
-
|
|
128030
|
+
resolve37({ apiKey, apiBase, agentId, companyId, raw: parsed });
|
|
127756
128031
|
});
|
|
127757
128032
|
});
|
|
127758
128033
|
}
|
|
@@ -127772,7 +128047,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
127772
128047
|
}
|
|
127773
128048
|
const timeoutMs = opts.cliTimeoutMs ?? 15e3;
|
|
127774
128049
|
const label = ["paperclipai", ...args].join(" ");
|
|
127775
|
-
return new Promise((
|
|
128050
|
+
return new Promise((resolve37, reject2) => {
|
|
127776
128051
|
let child;
|
|
127777
128052
|
try {
|
|
127778
128053
|
child = spawn15(bin, fullArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -127818,7 +128093,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
127818
128093
|
return;
|
|
127819
128094
|
}
|
|
127820
128095
|
try {
|
|
127821
|
-
|
|
128096
|
+
resolve37(JSON.parse(cleaned));
|
|
127822
128097
|
} catch {
|
|
127823
128098
|
reject2(new Error(`${label} returned non-JSON output: ${cleaned.slice(0, 200)}`));
|
|
127824
128099
|
}
|
|
@@ -127945,9 +128220,9 @@ var init_paperclip_client = __esm({
|
|
|
127945
128220
|
});
|
|
127946
128221
|
|
|
127947
128222
|
// ../../plugins/fusion-plugin-paperclip-runtime/dist/runtime-adapter.js
|
|
127948
|
-
import { randomUUID as
|
|
128223
|
+
import { randomUUID as randomUUID18 } from "node:crypto";
|
|
127949
128224
|
function sleep3(ms) {
|
|
127950
|
-
return new Promise((
|
|
128225
|
+
return new Promise((resolve37) => setTimeout(resolve37, ms));
|
|
127951
128226
|
}
|
|
127952
128227
|
function asString2(value) {
|
|
127953
128228
|
return typeof value === "string" ? value : void 0;
|
|
@@ -128064,7 +128339,7 @@ var init_runtime_adapter3 = __esm({
|
|
|
128064
128339
|
apiKey: effectiveApiKey,
|
|
128065
128340
|
agentId,
|
|
128066
128341
|
companyId,
|
|
128067
|
-
sessionId:
|
|
128342
|
+
sessionId: randomUUID18(),
|
|
128068
128343
|
systemPrompt: options.systemPrompt,
|
|
128069
128344
|
cwd: options.cwd,
|
|
128070
128345
|
mode: normalizeMode(this.config.mode),
|
|
@@ -128590,8 +128865,8 @@ var init_register_runtime_provider_routes = __esm({
|
|
|
128590
128865
|
|
|
128591
128866
|
// ../dashboard/src/update-check.ts
|
|
128592
128867
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
128593
|
-
import { mkdir as
|
|
128594
|
-
import { join as
|
|
128868
|
+
import { mkdir as mkdir16, rm as rm5, writeFile as writeFile14 } from "node:fs/promises";
|
|
128869
|
+
import { join as join43 } from "node:path";
|
|
128595
128870
|
function ttlForFrequency(frequency) {
|
|
128596
128871
|
switch (frequency) {
|
|
128597
128872
|
case "manual":
|
|
@@ -128605,7 +128880,7 @@ function ttlForFrequency(frequency) {
|
|
|
128605
128880
|
}
|
|
128606
128881
|
}
|
|
128607
128882
|
function getCachePath(fusionDir) {
|
|
128608
|
-
return
|
|
128883
|
+
return join43(fusionDir, CACHE_FILENAME);
|
|
128609
128884
|
}
|
|
128610
128885
|
function parseVersion(version) {
|
|
128611
128886
|
return version.split(".").slice(0, 3).map((part) => Number.parseInt(part, 10)).map((value) => Number.isFinite(value) ? value : 0);
|
|
@@ -128637,7 +128912,7 @@ function readCachedUpdateCheck(fusionDir) {
|
|
|
128637
128912
|
}
|
|
128638
128913
|
}
|
|
128639
128914
|
async function clearUpdateCheckCache(fusionDir) {
|
|
128640
|
-
await
|
|
128915
|
+
await rm5(getCachePath(fusionDir), { force: true });
|
|
128641
128916
|
}
|
|
128642
128917
|
async function performUpdateCheck(fusionDir, currentVersion, options = {}) {
|
|
128643
128918
|
const now = Date.now();
|
|
@@ -128669,8 +128944,8 @@ async function performUpdateCheck(fusionDir, currentVersion, options = {}) {
|
|
|
128669
128944
|
updateAvailable,
|
|
128670
128945
|
lastChecked: now
|
|
128671
128946
|
};
|
|
128672
|
-
await
|
|
128673
|
-
await
|
|
128947
|
+
await mkdir16(fusionDir, { recursive: true });
|
|
128948
|
+
await writeFile14(getCachePath(fusionDir), JSON.stringify(result, null, 2), "utf-8");
|
|
128674
128949
|
hasRefreshedThisProcess = true;
|
|
128675
128950
|
return result;
|
|
128676
128951
|
} catch (error) {
|
|
@@ -128697,7 +128972,7 @@ var init_update_check = __esm({
|
|
|
128697
128972
|
|
|
128698
128973
|
// ../dashboard/src/routes/register-update-check-routes.ts
|
|
128699
128974
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
128700
|
-
import { dirname as dirname13, join as
|
|
128975
|
+
import { dirname as dirname13, join as join44 } from "node:path";
|
|
128701
128976
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
128702
128977
|
var __dirname, CLI_PACKAGE_VERSION, registerUpdateCheckRoutes;
|
|
128703
128978
|
var init_register_update_check_routes = __esm({
|
|
@@ -128708,7 +128983,7 @@ var init_register_update_check_routes = __esm({
|
|
|
128708
128983
|
__dirname = dirname13(fileURLToPath3(import.meta.url));
|
|
128709
128984
|
CLI_PACKAGE_VERSION = (() => {
|
|
128710
128985
|
try {
|
|
128711
|
-
const packageJsonPath =
|
|
128986
|
+
const packageJsonPath = join44(__dirname, "..", "..", "..", "cli", "package.json");
|
|
128712
128987
|
const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
128713
128988
|
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
128714
128989
|
return packageJson.version;
|
|
@@ -132693,7 +132968,7 @@ var init_todo_routes = __esm({
|
|
|
132693
132968
|
|
|
132694
132969
|
// ../dashboard/src/dev-server-detect.ts
|
|
132695
132970
|
import { glob, readFile as readFile20 } from "node:fs/promises";
|
|
132696
|
-
import { dirname as dirname14, join as
|
|
132971
|
+
import { dirname as dirname14, join as join45, relative as relative10, resolve as resolve21 } from "node:path";
|
|
132697
132972
|
async function readPackageJson(filePath) {
|
|
132698
132973
|
try {
|
|
132699
132974
|
const raw = await readFile20(filePath, "utf-8");
|
|
@@ -132736,14 +133011,14 @@ function scoreCandidate(scriptName, pkg) {
|
|
|
132736
133011
|
async function collectWorkspacePackageJsons(projectRoot) {
|
|
132737
133012
|
const discovered = /* @__PURE__ */ new Set();
|
|
132738
133013
|
try {
|
|
132739
|
-
await readFile20(
|
|
133014
|
+
await readFile20(join45(projectRoot, "pnpm-workspace.yaml"), "utf-8");
|
|
132740
133015
|
} catch {
|
|
132741
133016
|
}
|
|
132742
133017
|
for (const pattern of ["packages/*/package.json", "apps/*/package.json"]) {
|
|
132743
133018
|
try {
|
|
132744
133019
|
for await (const match of glob(pattern, { cwd: projectRoot })) {
|
|
132745
133020
|
if (typeof match === "string") {
|
|
132746
|
-
discovered.add(
|
|
133021
|
+
discovered.add(resolve21(projectRoot, match));
|
|
132747
133022
|
}
|
|
132748
133023
|
}
|
|
132749
133024
|
} catch {
|
|
@@ -132768,9 +133043,9 @@ function toSource(projectRoot, packageJsonPath) {
|
|
|
132768
133043
|
return rel.length > 0 ? rel : "root";
|
|
132769
133044
|
}
|
|
132770
133045
|
async function detectDevServerScripts(projectRoot) {
|
|
132771
|
-
const root =
|
|
133046
|
+
const root = resolve21(projectRoot);
|
|
132772
133047
|
const candidates = [];
|
|
132773
|
-
const rootPackagePath =
|
|
133048
|
+
const rootPackagePath = join45(root, "package.json");
|
|
132774
133049
|
const rootPackage = await readPackageJson(rootPackagePath);
|
|
132775
133050
|
if (rootPackage) {
|
|
132776
133051
|
for (const script of extractScripts(rootPackage)) {
|
|
@@ -132836,10 +133111,10 @@ var init_dev_server_detect = __esm({
|
|
|
132836
133111
|
});
|
|
132837
133112
|
|
|
132838
133113
|
// ../dashboard/src/dev-server-store.ts
|
|
132839
|
-
import { mkdir as
|
|
132840
|
-
import { dirname as dirname15, join as
|
|
133114
|
+
import { mkdir as mkdir17, readFile as readFile21, writeFile as writeFile15 } from "node:fs/promises";
|
|
133115
|
+
import { dirname as dirname15, join as join46, resolve as resolve22 } from "node:path";
|
|
132841
133116
|
function devServerFilePath(projectDir) {
|
|
132842
|
-
return
|
|
133117
|
+
return join46(resolve22(projectDir), ".fusion", "dev-server.json");
|
|
132843
133118
|
}
|
|
132844
133119
|
function normalizeState(candidate) {
|
|
132845
133120
|
const defaults = DEV_SERVER_DEFAULT_STATE();
|
|
@@ -132874,7 +133149,7 @@ function normalizeConfig(candidate) {
|
|
|
132874
133149
|
};
|
|
132875
133150
|
}
|
|
132876
133151
|
async function loadDevServerStore(projectDir) {
|
|
132877
|
-
const storeKey =
|
|
133152
|
+
const storeKey = resolve22(projectDir);
|
|
132878
133153
|
let store = storeInstances.get(storeKey);
|
|
132879
133154
|
if (!store) {
|
|
132880
133155
|
store = new DevServerStore(projectDir);
|
|
@@ -132933,7 +133208,7 @@ var init_dev_server_store = __esm({
|
|
|
132933
133208
|
return error.code === "ENOENT";
|
|
132934
133209
|
};
|
|
132935
133210
|
try {
|
|
132936
|
-
await
|
|
133211
|
+
await mkdir17(dir2, { recursive: true });
|
|
132937
133212
|
} catch (error) {
|
|
132938
133213
|
if (isMissingPathError(error)) {
|
|
132939
133214
|
return;
|
|
@@ -132941,13 +133216,13 @@ var init_dev_server_store = __esm({
|
|
|
132941
133216
|
throw error;
|
|
132942
133217
|
}
|
|
132943
133218
|
try {
|
|
132944
|
-
await
|
|
133219
|
+
await writeFile15(this.filePath, serializedPayload, "utf-8");
|
|
132945
133220
|
} catch (error) {
|
|
132946
133221
|
if (!isMissingPathError(error)) {
|
|
132947
133222
|
throw error;
|
|
132948
133223
|
}
|
|
132949
133224
|
try {
|
|
132950
|
-
await
|
|
133225
|
+
await mkdir17(dir2, { recursive: true });
|
|
132951
133226
|
} catch (retryMkdirError) {
|
|
132952
133227
|
if (isMissingPathError(retryMkdirError)) {
|
|
132953
133228
|
return;
|
|
@@ -132955,7 +133230,7 @@ var init_dev_server_store = __esm({
|
|
|
132955
133230
|
throw retryMkdirError;
|
|
132956
133231
|
}
|
|
132957
133232
|
try {
|
|
132958
|
-
await
|
|
133233
|
+
await writeFile15(this.filePath, serializedPayload, "utf-8");
|
|
132959
133234
|
} catch (retryWriteError) {
|
|
132960
133235
|
if (isMissingPathError(retryWriteError)) {
|
|
132961
133236
|
return;
|
|
@@ -133152,7 +133427,7 @@ function detectPortFromLogLine(line) {
|
|
|
133152
133427
|
return detectViteLine(cleanLine) ?? detectNextLine(cleanLine) ?? detectStorybookLine(cleanLine) ?? detectAngularLine(cleanLine) ?? detectGenericUrl(cleanLine) ?? detectGenericPortLine(cleanLine);
|
|
133153
133428
|
}
|
|
133154
133429
|
function probePort(host, port, timeoutMs) {
|
|
133155
|
-
return new Promise((
|
|
133430
|
+
return new Promise((resolve37) => {
|
|
133156
133431
|
let settled = false;
|
|
133157
133432
|
const socket = createConnection({ host, port });
|
|
133158
133433
|
const settle = (isOpen) => {
|
|
@@ -133166,7 +133441,7 @@ function probePort(host, port, timeoutMs) {
|
|
|
133166
133441
|
} else {
|
|
133167
133442
|
socket.destroy();
|
|
133168
133443
|
}
|
|
133169
|
-
|
|
133444
|
+
resolve37(isOpen);
|
|
133170
133445
|
};
|
|
133171
133446
|
socket.setTimeout(timeoutMs);
|
|
133172
133447
|
socket.once("connect", () => settle(true));
|
|
@@ -133293,8 +133568,8 @@ var init_dev_server_process = __esm({
|
|
|
133293
133568
|
stdio: ["pipe", "pipe", "pipe"]
|
|
133294
133569
|
});
|
|
133295
133570
|
this.childProcess = child;
|
|
133296
|
-
this.closePromise = new Promise((
|
|
133297
|
-
this.resolveClosePromise =
|
|
133571
|
+
this.closePromise = new Promise((resolve37) => {
|
|
133572
|
+
this.resolveClosePromise = resolve37;
|
|
133298
133573
|
});
|
|
133299
133574
|
const runningState = await this.store.updateState({
|
|
133300
133575
|
pid: child.pid,
|
|
@@ -134091,7 +134366,7 @@ Your job is to refine task descriptions based on the user's selected refinement
|
|
|
134091
134366
|
|
|
134092
134367
|
// ../dashboard/src/routes.ts
|
|
134093
134368
|
import multer from "multer";
|
|
134094
|
-
import { resolve as
|
|
134369
|
+
import { resolve as resolve23, sep as sep6, join as join47, isAbsolute as isAbsolute15 } from "node:path";
|
|
134095
134370
|
import * as nodeFs from "node:fs";
|
|
134096
134371
|
import os5 from "node:os";
|
|
134097
134372
|
import v8 from "node:v8";
|
|
@@ -134112,8 +134387,8 @@ function hasPackageManagerSettings2(settings) {
|
|
|
134112
134387
|
function getPiPackageManagerAgentDir() {
|
|
134113
134388
|
const fusionAgentDir = getFusionAgentDir();
|
|
134114
134389
|
const legacyAgentDir = getLegacyPiAgentDir();
|
|
134115
|
-
const fusionSettings = readJsonObject3(
|
|
134116
|
-
const legacySettings = readJsonObject3(
|
|
134390
|
+
const fusionSettings = readJsonObject3(join47(fusionAgentDir, "settings.json"));
|
|
134391
|
+
const legacySettings = readJsonObject3(join47(legacyAgentDir, "settings.json"));
|
|
134117
134392
|
if (hasPackageManagerSettings2(fusionSettings) || !nodeFs.existsSync(legacyAgentDir)) {
|
|
134118
134393
|
return fusionAgentDir;
|
|
134119
134394
|
}
|
|
@@ -134123,7 +134398,7 @@ function getPiPackageManagerAgentDir() {
|
|
|
134123
134398
|
return nodeFs.existsSync(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
|
|
134124
134399
|
}
|
|
134125
134400
|
function packageExtensionName(extensionPath, source) {
|
|
134126
|
-
const base =
|
|
134401
|
+
const base = resolve23(extensionPath).split(sep6).pop()?.replace(/\.(ts|js)$/i, "") || source;
|
|
134127
134402
|
if (base !== "index") {
|
|
134128
134403
|
return base;
|
|
134129
134404
|
}
|
|
@@ -134131,15 +134406,15 @@ function packageExtensionName(extensionPath, source) {
|
|
|
134131
134406
|
}
|
|
134132
134407
|
async function discoverDashboardPiExtensions(cwd) {
|
|
134133
134408
|
const settings = discoverPiExtensions(cwd);
|
|
134134
|
-
const disabled = new Set(settings.disabledIds.map((id) =>
|
|
134409
|
+
const disabled = new Set(settings.disabledIds.map((id) => resolve23(id)));
|
|
134135
134410
|
const byPath = new Map(settings.extensions.map((entry) => [entry.id, entry]));
|
|
134136
134411
|
try {
|
|
134137
134412
|
const { DefaultPackageManager: DefaultPackageManager5 } = await import("@mariozechner/pi-coding-agent");
|
|
134138
134413
|
const agentDir = getPiPackageManagerAgentDir();
|
|
134139
|
-
const legacyGlobalSettings = readJsonObject3(
|
|
134140
|
-
const fusionGlobalSettings = readJsonObject3(
|
|
134414
|
+
const legacyGlobalSettings = readJsonObject3(join47(getLegacyPiAgentDir(), "settings.json"));
|
|
134415
|
+
const fusionGlobalSettings = readJsonObject3(join47(getFusionAgentDir(), "settings.json"));
|
|
134141
134416
|
const globalSettings = { ...legacyGlobalSettings, ...fusionGlobalSettings };
|
|
134142
|
-
const projectSettings = readJsonObject3(
|
|
134417
|
+
const projectSettings = readJsonObject3(join47(cwd, ".fusion", "settings.json"));
|
|
134143
134418
|
const mergedSettings = { ...globalSettings, ...projectSettings };
|
|
134144
134419
|
const packageManager = new DefaultPackageManager5({
|
|
134145
134420
|
cwd,
|
|
@@ -134153,7 +134428,7 @@ async function discoverDashboardPiExtensions(cwd) {
|
|
|
134153
134428
|
});
|
|
134154
134429
|
const resolved = await packageManager.resolve(async () => "skip");
|
|
134155
134430
|
for (const extension2 of resolved.extensions) {
|
|
134156
|
-
const id =
|
|
134431
|
+
const id = resolve23(extension2.path);
|
|
134157
134432
|
const source = extension2.metadata?.source || "package";
|
|
134158
134433
|
byPath.set(id, {
|
|
134159
134434
|
id,
|
|
@@ -134543,7 +134818,8 @@ function createApiRoutes(store, options) {
|
|
|
134543
134818
|
});
|
|
134544
134819
|
registerChatRoutes(routeContext, {
|
|
134545
134820
|
parseLastEventId: parseLastEventId2,
|
|
134546
|
-
validateOptionalModelField
|
|
134821
|
+
validateOptionalModelField,
|
|
134822
|
+
upload
|
|
134547
134823
|
});
|
|
134548
134824
|
registerMessagingScriptRoutes(routeContext);
|
|
134549
134825
|
registerGitGitHubRoutes(routeContext);
|
|
@@ -134555,8 +134831,8 @@ function createApiRoutes(store, options) {
|
|
|
134555
134831
|
function isHeartbeatMonitorForProject(scopedStore) {
|
|
134556
134832
|
if (!heartbeatMonitor?.rootDir) return true;
|
|
134557
134833
|
try {
|
|
134558
|
-
const monitorRoot =
|
|
134559
|
-
const storeRoot =
|
|
134834
|
+
const monitorRoot = resolve23(heartbeatMonitor.rootDir);
|
|
134835
|
+
const storeRoot = resolve23(scopedStore.getRootDir());
|
|
134560
134836
|
return monitorRoot === storeRoot;
|
|
134561
134837
|
} catch {
|
|
134562
134838
|
return true;
|
|
@@ -136478,15 +136754,15 @@ Description: ${step.description}`
|
|
|
136478
136754
|
return;
|
|
136479
136755
|
}
|
|
136480
136756
|
}
|
|
136481
|
-
const { resolve:
|
|
136757
|
+
const { resolve: resolve37, dirname: dirname28, join: join66 } = await import("node:path");
|
|
136482
136758
|
const { readdir: readdir12, stat: stat12 } = await import("node:fs/promises");
|
|
136483
136759
|
const rawPath = req.query.path || process.env.HOME || process.env.USERPROFILE || "/";
|
|
136484
136760
|
const showHidden = req.query.showHidden === "true";
|
|
136485
|
-
const resolvedPath =
|
|
136761
|
+
const resolvedPath = resolve37(rawPath);
|
|
136486
136762
|
if (rawPath.includes("..")) {
|
|
136487
136763
|
throw badRequest("Path must not contain '..' traversal");
|
|
136488
136764
|
}
|
|
136489
|
-
if (resolvedPath !==
|
|
136765
|
+
if (resolvedPath !== resolve37(resolvedPath)) {
|
|
136490
136766
|
throw badRequest("Path must be absolute");
|
|
136491
136767
|
}
|
|
136492
136768
|
let pathStat;
|
|
@@ -136503,7 +136779,7 @@ Description: ${step.description}`
|
|
|
136503
136779
|
for (const entry of dirEntries) {
|
|
136504
136780
|
if (!entry.isDirectory()) continue;
|
|
136505
136781
|
if (!showHidden && entry.name.startsWith(".")) continue;
|
|
136506
|
-
const entryPath =
|
|
136782
|
+
const entryPath = join66(resolvedPath, entry.name);
|
|
136507
136783
|
let hasChildren = false;
|
|
136508
136784
|
try {
|
|
136509
136785
|
const subEntries = await readdir12(entryPath, { withFileTypes: true });
|
|
@@ -141813,7 +142089,7 @@ var init_badge_pubsub = __esm({
|
|
|
141813
142089
|
});
|
|
141814
142090
|
|
|
141815
142091
|
// ../dashboard/src/terminal-websocket-diagnostics.ts
|
|
141816
|
-
import { basename as
|
|
142092
|
+
import { basename as basename12, normalize as normalize4, sep as sep7 } from "node:path";
|
|
141817
142093
|
function toSessionTag(sessionId) {
|
|
141818
142094
|
const normalized = sessionId.trim();
|
|
141819
142095
|
if (normalized.length <= 8) {
|
|
@@ -141860,8 +142136,8 @@ function createTerminalWebSocketDiagnostics(runtimeLogger) {
|
|
|
141860
142136
|
projectId,
|
|
141861
142137
|
sessionCwdHint: toRedactedPathHint(sessionCwd),
|
|
141862
142138
|
scopedRootHint: toRedactedPathHint(scopedRootDir),
|
|
141863
|
-
sessionCwdBase:
|
|
141864
|
-
scopedRootBase:
|
|
142139
|
+
sessionCwdBase: basename12(sessionCwd),
|
|
142140
|
+
scopedRootBase: basename12(scopedRootDir)
|
|
141865
142141
|
});
|
|
141866
142142
|
},
|
|
141867
142143
|
staleReconnect({ sessionId, idleMs, staleThresholdMs }) {
|
|
@@ -142003,8 +142279,8 @@ var init_auth_middleware = __esm({
|
|
|
142003
142279
|
|
|
142004
142280
|
// ../dashboard/src/server.ts
|
|
142005
142281
|
import express from "express";
|
|
142006
|
-
import { randomUUID as
|
|
142007
|
-
import { join as
|
|
142282
|
+
import { randomUUID as randomUUID19 } from "node:crypto";
|
|
142283
|
+
import { join as join48, dirname as dirname16 } from "node:path";
|
|
142008
142284
|
import { existsSync as existsSync30, readFileSync as readFileSync11 } from "node:fs";
|
|
142009
142285
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
142010
142286
|
import { createSecureServer as createHttp2SecureServer } from "node:http2";
|
|
@@ -142186,11 +142462,11 @@ function createServer(store, options) {
|
|
|
142186
142462
|
getTerminalService(store.getRootDir());
|
|
142187
142463
|
const isHeadless = options?.headless === true;
|
|
142188
142464
|
const execDir = dirname16(process.execPath);
|
|
142189
|
-
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync30(
|
|
142465
|
+
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync30(join48(execDir, "client", "index.html")) ? join48(execDir, "client") : existsSync30(join48(__dirname2, "..", "dist", "client")) ? join48(__dirname2, "..", "dist", "client") : join48(__dirname2, "..", "client");
|
|
142190
142466
|
if (!isHeadless) {
|
|
142191
142467
|
app.get("/version.json", (_req, res) => {
|
|
142192
142468
|
res.setHeader("Cache-Control", "no-store, max-age=0");
|
|
142193
|
-
res.sendFile(
|
|
142469
|
+
res.sendFile(join48(clientDir, "version.json"), (err) => {
|
|
142194
142470
|
if (err) {
|
|
142195
142471
|
res.status(404).json({ version: null });
|
|
142196
142472
|
}
|
|
@@ -142610,7 +142886,7 @@ data: ${JSON.stringify({ type: event.type, data: event.data })}
|
|
|
142610
142886
|
});
|
|
142611
142887
|
if (!isHeadless) {
|
|
142612
142888
|
app.get("/{*splat}", (_req, res) => {
|
|
142613
|
-
res.sendFile(
|
|
142889
|
+
res.sendFile(join48(clientDir, "index.html"));
|
|
142614
142890
|
});
|
|
142615
142891
|
}
|
|
142616
142892
|
const dashboardApp = app;
|
|
@@ -142849,7 +143125,7 @@ function setupBadgeWebSocket(app, server, store, options) {
|
|
|
142849
143125
|
const dashboardApp = app;
|
|
142850
143126
|
const wsManager = new WebSocketManager();
|
|
142851
143127
|
const badgeSnapshots = /* @__PURE__ */ new Map();
|
|
142852
|
-
const serverId =
|
|
143128
|
+
const serverId = randomUUID19();
|
|
142853
143129
|
const badgePubSub = options?.badgePubSub ?? createBadgePubSub({ sourceId: serverId });
|
|
142854
143130
|
void badgePubSub.start();
|
|
142855
143131
|
const scopedStores = /* @__PURE__ */ new Map();
|
|
@@ -142983,7 +143259,7 @@ function setupBadgeWebSocket(app, server, store, options) {
|
|
|
142983
143259
|
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
142984
143260
|
const projectId = url.searchParams.get("projectId") ?? "default";
|
|
142985
143261
|
void ensureScopedListeners(projectId);
|
|
142986
|
-
wsManager.addClient(ws,
|
|
143262
|
+
wsManager.addClient(ws, randomUUID19(), projectId);
|
|
142987
143263
|
});
|
|
142988
143264
|
server.once("close", () => {
|
|
142989
143265
|
for (const cleanup of scopedCleanups.values()) {
|
|
@@ -143052,7 +143328,7 @@ var init_server = __esm({
|
|
|
143052
143328
|
__dirname2 = dirname16(fileURLToPath4(import.meta.url));
|
|
143053
143329
|
PACKAGE_VERSION = (() => {
|
|
143054
143330
|
try {
|
|
143055
|
-
const packageJsonPath =
|
|
143331
|
+
const packageJsonPath = join48(__dirname2, "..", "package.json");
|
|
143056
143332
|
const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
|
|
143057
143333
|
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
143058
143334
|
return packageJson.version;
|
|
@@ -143063,7 +143339,7 @@ var init_server = __esm({
|
|
|
143063
143339
|
})();
|
|
143064
143340
|
CLI_PACKAGE_VERSION2 = (() => {
|
|
143065
143341
|
try {
|
|
143066
|
-
const packageJsonPath =
|
|
143342
|
+
const packageJsonPath = join48(__dirname2, "..", "..", "cli", "package.json");
|
|
143067
143343
|
const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
|
|
143068
143344
|
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
143069
143345
|
return packageJson.version;
|
|
@@ -143085,8 +143361,8 @@ var init_server = __esm({
|
|
|
143085
143361
|
});
|
|
143086
143362
|
|
|
143087
143363
|
// ../dashboard/src/skills-adapter.ts
|
|
143088
|
-
import { access as access9, readFile as readFile22, writeFile as
|
|
143089
|
-
import { join as
|
|
143364
|
+
import { access as access9, readFile as readFile22, writeFile as writeFile16, mkdir as mkdir18, readdir as readdir10, stat as stat10 } from "node:fs/promises";
|
|
143365
|
+
import { join as join49, relative as relative11, dirname as dirname17 } from "node:path";
|
|
143090
143366
|
async function pathExists(path5) {
|
|
143091
143367
|
try {
|
|
143092
143368
|
await access9(path5);
|
|
@@ -143184,7 +143460,7 @@ function createSkillsAdapter(options) {
|
|
|
143184
143460
|
const settingsPath = options.getSettingsPath(rootDir);
|
|
143185
143461
|
const settingsDir = dirname17(settingsPath);
|
|
143186
143462
|
if (!await pathExists(settingsDir)) {
|
|
143187
|
-
await
|
|
143463
|
+
await mkdir18(settingsDir, { recursive: true });
|
|
143188
143464
|
}
|
|
143189
143465
|
let settings = {};
|
|
143190
143466
|
if (await pathExists(settingsPath)) {
|
|
@@ -143213,7 +143489,7 @@ function createSkillsAdapter(options) {
|
|
|
143213
143489
|
}
|
|
143214
143490
|
skills.push(`${prefix}${skillPath}`);
|
|
143215
143491
|
settings.skills = skills;
|
|
143216
|
-
await
|
|
143492
|
+
await writeFile16(settingsPath, JSON.stringify(settings, null, 2));
|
|
143217
143493
|
return {
|
|
143218
143494
|
settingsPath: "skills",
|
|
143219
143495
|
pattern: `${prefix}${skillPath}`,
|
|
@@ -143250,7 +143526,7 @@ function createSkillsAdapter(options) {
|
|
|
143250
143526
|
}
|
|
143251
143527
|
pkgEntry.skills.push(`${prefix}${skillPath}`);
|
|
143252
143528
|
settings.packages = packages;
|
|
143253
|
-
await
|
|
143529
|
+
await writeFile16(settingsPath, JSON.stringify(settings, null, 2));
|
|
143254
143530
|
return {
|
|
143255
143531
|
settingsPath: "packages[].skills",
|
|
143256
143532
|
pattern: `${prefix}${skillPath}`,
|
|
@@ -143342,7 +143618,7 @@ function createSkillsAdapter(options) {
|
|
|
143342
143618
|
} catch {
|
|
143343
143619
|
skillDir = dirname17(skill.path);
|
|
143344
143620
|
}
|
|
143345
|
-
const skillMdPath =
|
|
143621
|
+
const skillMdPath = join49(skillDir, "SKILL.md");
|
|
143346
143622
|
let skillMd = "";
|
|
143347
143623
|
try {
|
|
143348
143624
|
skillMd = await readFile22(skillMdPath, "utf-8");
|
|
@@ -143550,7 +143826,7 @@ function normalizeEntry(entry) {
|
|
|
143550
143826
|
};
|
|
143551
143827
|
}
|
|
143552
143828
|
function getProjectSettingsPath(rootDir) {
|
|
143553
|
-
return
|
|
143829
|
+
return join49(rootDir, ".fusion", "settings.json");
|
|
143554
143830
|
}
|
|
143555
143831
|
var MIN_PUBLIC_SEARCH_QUERY_LENGTH;
|
|
143556
143832
|
var init_skills_adapter = __esm({
|
|
@@ -143725,7 +144001,7 @@ var init_task_lifecycle = __esm({
|
|
|
143725
144001
|
// src/commands/port-prompt.ts
|
|
143726
144002
|
import { createInterface } from "node:readline";
|
|
143727
144003
|
function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
143728
|
-
return new Promise((
|
|
144004
|
+
return new Promise((resolve37, reject2) => {
|
|
143729
144005
|
const rl = createInterface({
|
|
143730
144006
|
input,
|
|
143731
144007
|
output: process.stdout
|
|
@@ -143742,7 +144018,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
|
143742
144018
|
if (trimmed === "") {
|
|
143743
144019
|
process.removeListener("SIGINT", sigintHandler);
|
|
143744
144020
|
rl.close();
|
|
143745
|
-
|
|
144021
|
+
resolve37(defaultPort);
|
|
143746
144022
|
return;
|
|
143747
144023
|
}
|
|
143748
144024
|
const port = parseInt(trimmed, 10);
|
|
@@ -143758,7 +144034,7 @@ function promptForPort(defaultPort = 4040, input = process.stdin) {
|
|
|
143758
144034
|
}
|
|
143759
144035
|
process.removeListener("SIGINT", sigintHandler);
|
|
143760
144036
|
rl.close();
|
|
143761
|
-
|
|
144037
|
+
resolve37(port);
|
|
143762
144038
|
});
|
|
143763
144039
|
};
|
|
143764
144040
|
ask();
|
|
@@ -143772,12 +144048,12 @@ var init_port_prompt = __esm({
|
|
|
143772
144048
|
|
|
143773
144049
|
// src/commands/provider-settings.ts
|
|
143774
144050
|
import { existsSync as existsSync31, readFileSync as readFileSync12, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "node:fs";
|
|
143775
|
-
import { join as
|
|
144051
|
+
import { join as join50, dirname as dirname18, basename as basename13 } from "node:path";
|
|
143776
144052
|
function siblingAgentDir2(agentDir, siblingRoot) {
|
|
143777
|
-
if (
|
|
144053
|
+
if (basename13(agentDir) !== "agent") {
|
|
143778
144054
|
return void 0;
|
|
143779
144055
|
}
|
|
143780
|
-
return
|
|
144056
|
+
return join50(dirname18(dirname18(agentDir)), siblingRoot, "agent");
|
|
143781
144057
|
}
|
|
143782
144058
|
function readJsonObject4(path5) {
|
|
143783
144059
|
if (!existsSync31(path5)) {
|
|
@@ -143791,13 +144067,13 @@ function readJsonObject4(path5) {
|
|
|
143791
144067
|
}
|
|
143792
144068
|
}
|
|
143793
144069
|
function createReadOnlyProviderSettingsView(cwd, agentDir) {
|
|
143794
|
-
const fusionAgentDir = agentDir.includes(`${
|
|
143795
|
-
const legacyAgentDir = agentDir.includes(`${
|
|
143796
|
-
const legacyGlobalSettings = legacyAgentDir ? readJsonObject4(
|
|
143797
|
-
const fusionGlobalSettings = fusionAgentDir ? readJsonObject4(
|
|
143798
|
-
const directGlobalSettings = readJsonObject4(
|
|
144070
|
+
const fusionAgentDir = agentDir.includes(`${join50(".fusion", "agent")}`) ? agentDir : siblingAgentDir2(agentDir, ".fusion");
|
|
144071
|
+
const legacyAgentDir = agentDir.includes(`${join50(".pi", "agent")}`) ? agentDir : siblingAgentDir2(agentDir, ".pi");
|
|
144072
|
+
const legacyGlobalSettings = legacyAgentDir ? readJsonObject4(join50(legacyAgentDir, "settings.json")) : {};
|
|
144073
|
+
const fusionGlobalSettings = fusionAgentDir ? readJsonObject4(join50(fusionAgentDir, "settings.json")) : {};
|
|
144074
|
+
const directGlobalSettings = readJsonObject4(join50(agentDir, "settings.json"));
|
|
143799
144075
|
const globalSettings = { ...legacyGlobalSettings, ...directGlobalSettings, ...fusionGlobalSettings };
|
|
143800
|
-
const fusionProjectSettings = readJsonObject4(
|
|
144076
|
+
const fusionProjectSettings = readJsonObject4(join50(cwd, ".fusion", "settings.json"));
|
|
143801
144077
|
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
|
|
143802
144078
|
return {
|
|
143803
144079
|
getGlobalSettings: () => structuredClone(globalSettings),
|
|
@@ -143983,29 +144259,29 @@ var init_provider_auth = __esm({
|
|
|
143983
144259
|
// src/commands/auth-paths.ts
|
|
143984
144260
|
import { homedir as homedir7 } from "node:os";
|
|
143985
144261
|
import { existsSync as existsSync33, readFileSync as readFileSync14 } from "node:fs";
|
|
143986
|
-
import { join as
|
|
144262
|
+
import { join as join51 } from "node:path";
|
|
143987
144263
|
function getFusionAgentDir3(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
143988
|
-
return
|
|
144264
|
+
return join51(home, ".fusion", "agent");
|
|
143989
144265
|
}
|
|
143990
144266
|
function getLegacyAgentDir(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
143991
|
-
return
|
|
144267
|
+
return join51(home, ".pi", "agent");
|
|
143992
144268
|
}
|
|
143993
144269
|
function getFusionAuthPath3(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
143994
|
-
return
|
|
144270
|
+
return join51(getFusionAgentDir3(home), "auth.json");
|
|
143995
144271
|
}
|
|
143996
144272
|
function getLegacyAuthPaths2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
143997
144273
|
return [
|
|
143998
|
-
|
|
143999
|
-
|
|
144274
|
+
join51(home, ".pi", "agent", "auth.json"),
|
|
144275
|
+
join51(home, ".pi", "auth.json")
|
|
144000
144276
|
];
|
|
144001
144277
|
}
|
|
144002
144278
|
function getFusionModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
144003
|
-
return
|
|
144279
|
+
return join51(getFusionAgentDir3(home), "models.json");
|
|
144004
144280
|
}
|
|
144005
144281
|
function getLegacyModelsPaths2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
144006
144282
|
return [
|
|
144007
|
-
|
|
144008
|
-
|
|
144283
|
+
join51(home, ".pi", "agent", "models.json"),
|
|
144284
|
+
join51(home, ".pi", "models.json")
|
|
144009
144285
|
];
|
|
144010
144286
|
}
|
|
144011
144287
|
function getModelRegistryModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
@@ -144032,8 +144308,8 @@ function hasPackageManagerSettings3(settings) {
|
|
|
144032
144308
|
function getPackageManagerAgentDir2(home = process.env.HOME || process.env.USERPROFILE || homedir7()) {
|
|
144033
144309
|
const fusionAgentDir = getFusionAgentDir3(home);
|
|
144034
144310
|
const legacyAgentDir = getLegacyAgentDir(home);
|
|
144035
|
-
const fusionSettings = readJsonObject5(
|
|
144036
|
-
const legacySettings = readJsonObject5(
|
|
144311
|
+
const fusionSettings = readJsonObject5(join51(fusionAgentDir, "settings.json"));
|
|
144312
|
+
const legacySettings = readJsonObject5(join51(legacyAgentDir, "settings.json"));
|
|
144037
144313
|
if (hasPackageManagerSettings3(fusionSettings) || !existsSync33(legacyAgentDir)) {
|
|
144038
144314
|
return fusionAgentDir;
|
|
144039
144315
|
}
|
|
@@ -144049,7 +144325,7 @@ var init_auth_paths2 = __esm({
|
|
|
144049
144325
|
});
|
|
144050
144326
|
|
|
144051
144327
|
// src/project-context.ts
|
|
144052
|
-
import { resolve as
|
|
144328
|
+
import { resolve as resolve24, dirname as dirname19 } from "node:path";
|
|
144053
144329
|
import { existsSync as existsSync34 } from "node:fs";
|
|
144054
144330
|
async function resolveProject(projectNameFlag, cwd = process.cwd(), globalDir) {
|
|
144055
144331
|
const central = new CentralCore(globalDir);
|
|
@@ -144141,9 +144417,9 @@ async function clearDefaultProject(globalDir) {
|
|
|
144141
144417
|
await globalStore.updateSettings(rest);
|
|
144142
144418
|
}
|
|
144143
144419
|
async function detectProjectFromCwd(cwd, central) {
|
|
144144
|
-
let currentDir =
|
|
144420
|
+
let currentDir = resolve24(cwd);
|
|
144145
144421
|
while (true) {
|
|
144146
|
-
const kbPath =
|
|
144422
|
+
const kbPath = resolve24(currentDir, ".fusion", "fusion.db");
|
|
144147
144423
|
if (existsSync34(kbPath)) {
|
|
144148
144424
|
const project = await central.getProjectByPath(currentDir);
|
|
144149
144425
|
if (project) {
|
|
@@ -144207,7 +144483,7 @@ import {
|
|
|
144207
144483
|
symlinkSync,
|
|
144208
144484
|
unlinkSync
|
|
144209
144485
|
} from "node:fs";
|
|
144210
|
-
import { dirname as dirname20, join as
|
|
144486
|
+
import { dirname as dirname20, join as join52, resolve as resolve25 } from "node:path";
|
|
144211
144487
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
144212
144488
|
function isPiClaudeCliConfigured(globalSettings) {
|
|
144213
144489
|
if (!globalSettings || typeof globalSettings !== "object") {
|
|
@@ -144227,11 +144503,11 @@ function isPiClaudeCliConfigured(globalSettings) {
|
|
|
144227
144503
|
}
|
|
144228
144504
|
function resolveFusionSkillSource() {
|
|
144229
144505
|
const here = fileURLToPath5(import.meta.url);
|
|
144230
|
-
const candidate =
|
|
144506
|
+
const candidate = resolve25(dirname20(here), "..", "..", "skill", FUSION_SKILL_NAME);
|
|
144231
144507
|
return existsSync35(candidate) ? candidate : null;
|
|
144232
144508
|
}
|
|
144233
144509
|
function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
144234
|
-
const target =
|
|
144510
|
+
const target = join52(projectPath, ".claude", "skills", FUSION_SKILL_NAME);
|
|
144235
144511
|
if (options.enabled === false) {
|
|
144236
144512
|
return { outcome: "skipped", target, reason: "pi-claude-cli not configured" };
|
|
144237
144513
|
}
|
|
@@ -144250,13 +144526,13 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
|
144250
144526
|
const stat12 = lstatSync2(target);
|
|
144251
144527
|
if (stat12.isSymbolicLink()) {
|
|
144252
144528
|
const current = safeReadlink(target);
|
|
144253
|
-
if (current &&
|
|
144529
|
+
if (current && resolve25(dirname20(target), current) === resolve25(source)) {
|
|
144254
144530
|
return { outcome: "already-installed", target, source };
|
|
144255
144531
|
}
|
|
144256
144532
|
unlinkSync(target);
|
|
144257
144533
|
replaced = true;
|
|
144258
144534
|
} else {
|
|
144259
|
-
const skillMd =
|
|
144535
|
+
const skillMd = join52(target, "SKILL.md");
|
|
144260
144536
|
if (!existsSync35(skillMd)) {
|
|
144261
144537
|
return {
|
|
144262
144538
|
outcome: "failed",
|
|
@@ -144303,7 +144579,7 @@ function ensureFusionSkillForProjects(projects, options = { enabled: false }) {
|
|
|
144303
144579
|
if (!options.enabled) {
|
|
144304
144580
|
return projects.map((p) => ({
|
|
144305
144581
|
outcome: "skipped",
|
|
144306
|
-
target:
|
|
144582
|
+
target: join52(p.path, ".claude", "skills", FUSION_SKILL_NAME),
|
|
144307
144583
|
reason: "pi-claude-cli not configured"
|
|
144308
144584
|
}));
|
|
144309
144585
|
}
|
|
@@ -144415,13 +144691,13 @@ var init_claude_skills_runner = __esm({
|
|
|
144415
144691
|
// src/commands/claude-cli-extension.ts
|
|
144416
144692
|
import { existsSync as existsSync36, readFileSync as readFileSync15 } from "node:fs";
|
|
144417
144693
|
import { createRequire as createRequire4 } from "node:module";
|
|
144418
|
-
import { dirname as dirname21, resolve as
|
|
144694
|
+
import { dirname as dirname21, resolve as resolve26 } from "node:path";
|
|
144419
144695
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
144420
144696
|
function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
|
|
144421
144697
|
let pkgJsonPath;
|
|
144422
144698
|
const here = dirname21(fileURLToPath6(moduleUrl));
|
|
144423
144699
|
for (const rel of ["pi-claude-cli", "../pi-claude-cli", "../../pi-claude-cli"]) {
|
|
144424
|
-
const candidate =
|
|
144700
|
+
const candidate = resolve26(here, rel, "package.json");
|
|
144425
144701
|
if (existsSync36(candidate)) {
|
|
144426
144702
|
pkgJsonPath = candidate;
|
|
144427
144703
|
break;
|
|
@@ -144457,7 +144733,7 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
|
|
|
144457
144733
|
reason: "@fusion/pi-claude-cli pi.extensions[0] is not a valid path string"
|
|
144458
144734
|
};
|
|
144459
144735
|
}
|
|
144460
|
-
const entryPath =
|
|
144736
|
+
const entryPath = resolve26(dirname21(pkgJsonPath), rawEntry);
|
|
144461
144737
|
if (!existsSync36(entryPath)) {
|
|
144462
144738
|
return {
|
|
144463
144739
|
status: "missing-entry",
|
|
@@ -144510,10 +144786,10 @@ var init_claude_cli_extension = __esm({
|
|
|
144510
144786
|
|
|
144511
144787
|
// src/update-cache.ts
|
|
144512
144788
|
import { readFileSync as readFileSync16 } from "node:fs";
|
|
144513
|
-
import { join as
|
|
144789
|
+
import { join as join53 } from "node:path";
|
|
144514
144790
|
function getCachedUpdateStatus() {
|
|
144515
144791
|
try {
|
|
144516
|
-
const cachePath =
|
|
144792
|
+
const cachePath = join53(resolveGlobalDir(), "update-check.json");
|
|
144517
144793
|
const raw = readFileSync16(cachePath, "utf-8");
|
|
144518
144794
|
const parsed = JSON.parse(raw);
|
|
144519
144795
|
if (parsed.updateAvailable === true && typeof parsed.latestVersion === "string" && parsed.latestVersion.length > 0 && typeof parsed.currentVersion === "string" && parsed.currentVersion.length > 0) {
|
|
@@ -144543,16 +144819,16 @@ var init_update_cache = __esm({
|
|
|
144543
144819
|
|
|
144544
144820
|
// src/commands/self-extension.ts
|
|
144545
144821
|
import { existsSync as existsSync37, readFileSync as readFileSync17 } from "node:fs";
|
|
144546
|
-
import { dirname as dirname22, resolve as
|
|
144822
|
+
import { dirname as dirname22, resolve as resolve27 } from "node:path";
|
|
144547
144823
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
144548
144824
|
function resolveSelfExtension() {
|
|
144549
144825
|
const here = dirname22(fileURLToPath7(import.meta.url));
|
|
144550
144826
|
let pkgDir;
|
|
144551
144827
|
let cur = here;
|
|
144552
144828
|
for (let i = 0; i < 5; i++) {
|
|
144553
|
-
if (existsSync37(
|
|
144829
|
+
if (existsSync37(resolve27(cur, "package.json"))) {
|
|
144554
144830
|
try {
|
|
144555
|
-
const parsed = JSON.parse(readFileSync17(
|
|
144831
|
+
const parsed = JSON.parse(readFileSync17(resolve27(cur, "package.json"), "utf-8"));
|
|
144556
144832
|
if (parsed.name === "@runfusion/fusion") {
|
|
144557
144833
|
pkgDir = cur;
|
|
144558
144834
|
break;
|
|
@@ -144560,7 +144836,7 @@ function resolveSelfExtension() {
|
|
|
144560
144836
|
} catch {
|
|
144561
144837
|
}
|
|
144562
144838
|
}
|
|
144563
|
-
const parent2 =
|
|
144839
|
+
const parent2 = resolve27(cur, "..");
|
|
144564
144840
|
if (parent2 === cur) break;
|
|
144565
144841
|
cur = parent2;
|
|
144566
144842
|
}
|
|
@@ -144569,11 +144845,11 @@ function resolveSelfExtension() {
|
|
|
144569
144845
|
}
|
|
144570
144846
|
let pkgJson;
|
|
144571
144847
|
try {
|
|
144572
|
-
pkgJson = JSON.parse(readFileSync17(
|
|
144848
|
+
pkgJson = JSON.parse(readFileSync17(resolve27(pkgDir, "package.json"), "utf-8"));
|
|
144573
144849
|
} catch (err) {
|
|
144574
144850
|
return { status: "missing", reason: `Failed to read @runfusion/fusion package.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
144575
144851
|
}
|
|
144576
|
-
const srcEntry =
|
|
144852
|
+
const srcEntry = resolve27(pkgDir, "src", "extension.ts");
|
|
144577
144853
|
if (existsSync37(srcEntry)) {
|
|
144578
144854
|
return { status: "ok", path: srcEntry, packageVersion: pkgJson.version ?? "unknown" };
|
|
144579
144855
|
}
|
|
@@ -144585,7 +144861,7 @@ function resolveSelfExtension() {
|
|
|
144585
144861
|
if (typeof rawEntry !== "string" || rawEntry.length === 0) {
|
|
144586
144862
|
return { status: "missing", reason: "@runfusion/fusion pi.extensions[0] is not a valid path string" };
|
|
144587
144863
|
}
|
|
144588
|
-
const entryPath =
|
|
144864
|
+
const entryPath = resolve27(pkgDir, rawEntry);
|
|
144589
144865
|
if (!existsSync37(entryPath)) {
|
|
144590
144866
|
return { status: "missing", reason: `@runfusion/fusion extension file not found at ${entryPath}` };
|
|
144591
144867
|
}
|
|
@@ -144646,20 +144922,20 @@ var init_state = __esm({
|
|
|
144646
144922
|
|
|
144647
144923
|
// src/commands/dashboard-tui/logo.ts
|
|
144648
144924
|
import { existsSync as existsSync38, readFileSync as readFileSync18 } from "node:fs";
|
|
144649
|
-
import { dirname as dirname23, resolve as
|
|
144925
|
+
import { dirname as dirname23, resolve as resolve28 } from "node:path";
|
|
144650
144926
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
144651
144927
|
function readFusionVersion() {
|
|
144652
144928
|
try {
|
|
144653
144929
|
let cur = dirname23(fileURLToPath8(import.meta.url));
|
|
144654
144930
|
for (let i = 0; i < 6; i++) {
|
|
144655
|
-
const pkgPath =
|
|
144931
|
+
const pkgPath = resolve28(cur, "package.json");
|
|
144656
144932
|
if (existsSync38(pkgPath)) {
|
|
144657
144933
|
const parsed = JSON.parse(readFileSync18(pkgPath, "utf-8"));
|
|
144658
144934
|
if (parsed.name === "@runfusion/fusion" && typeof parsed.version === "string") {
|
|
144659
144935
|
return parsed.version;
|
|
144660
144936
|
}
|
|
144661
144937
|
}
|
|
144662
|
-
const parent2 =
|
|
144938
|
+
const parent2 = resolve28(cur, "..");
|
|
144663
144939
|
if (parent2 === cur) break;
|
|
144664
144940
|
cur = parent2;
|
|
144665
144941
|
}
|
|
@@ -144764,14 +145040,14 @@ async function copyToClipboard(text) {
|
|
|
144764
145040
|
{ cmd: "xsel", args: ["--clipboard", "--input"] }
|
|
144765
145041
|
];
|
|
144766
145042
|
for (const { cmd, args } of candidates) {
|
|
144767
|
-
const ok = await new Promise((
|
|
145043
|
+
const ok = await new Promise((resolve37) => {
|
|
144768
145044
|
try {
|
|
144769
145045
|
const child = spawn11(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
144770
|
-
child.once("error", () =>
|
|
144771
|
-
child.once("close", (code) =>
|
|
145046
|
+
child.once("error", () => resolve37(false));
|
|
145047
|
+
child.once("close", (code) => resolve37(code === 0));
|
|
144772
145048
|
child.stdin.end(text);
|
|
144773
145049
|
} catch {
|
|
144774
|
-
|
|
145050
|
+
resolve37(false);
|
|
144775
145051
|
}
|
|
144776
145052
|
});
|
|
144777
145053
|
if (ok) return true;
|
|
@@ -148687,7 +148963,7 @@ __export(dashboard_exports, {
|
|
|
148687
148963
|
promptForPort: () => promptForPort,
|
|
148688
148964
|
runDashboard: () => runDashboard
|
|
148689
148965
|
});
|
|
148690
|
-
import { join as
|
|
148966
|
+
import { join as join54, resolve as pathResolve } from "node:path";
|
|
148691
148967
|
import { execFile as execFileCb } from "node:child_process";
|
|
148692
148968
|
import { promisify as promisify14 } from "node:util";
|
|
148693
148969
|
import { stat as stat11, readdir as readdir11, readFile as fsReadFile3 } from "node:fs/promises";
|
|
@@ -148994,7 +149270,7 @@ async function buildFileListDirectory(projectPath, relativePath) {
|
|
|
148994
149270
|
let size = 0;
|
|
148995
149271
|
let modifiedAt = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
148996
149272
|
try {
|
|
148997
|
-
const s = await stat11(
|
|
149273
|
+
const s = await stat11(join54(absDir, d.name));
|
|
148998
149274
|
size = d.isDirectory() ? 0 : s.size;
|
|
148999
149275
|
modifiedAt = s.mtime.toISOString();
|
|
149000
149276
|
} catch {
|
|
@@ -149423,7 +149699,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
149423
149699
|
...claudeCliPaths
|
|
149424
149700
|
],
|
|
149425
149701
|
cwd,
|
|
149426
|
-
|
|
149702
|
+
join54(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
149427
149703
|
);
|
|
149428
149704
|
for (const { path: path5, error } of extensionsResult.errors) {
|
|
149429
149705
|
logSink.log(`Failed to load ${path5}: ${error}`, "extensions");
|
|
@@ -149904,8 +150180,8 @@ async function runDashboard(port, opts = {}) {
|
|
|
149904
150180
|
try {
|
|
149905
150181
|
const updateCheckEnabled = await Promise.race([
|
|
149906
150182
|
isUpdateCheckEnabled(),
|
|
149907
|
-
new Promise((
|
|
149908
|
-
setTimeout(() =>
|
|
150183
|
+
new Promise((resolve37) => {
|
|
150184
|
+
setTimeout(() => resolve37(false), 3e3);
|
|
149909
150185
|
})
|
|
149910
150186
|
]);
|
|
149911
150187
|
if (!updateCheckEnabled) {
|
|
@@ -150874,7 +151150,7 @@ var serve_exports = {};
|
|
|
150874
151150
|
__export(serve_exports, {
|
|
150875
151151
|
runServe: () => runServe
|
|
150876
151152
|
});
|
|
150877
|
-
import { join as
|
|
151153
|
+
import { join as join55 } from "node:path";
|
|
150878
151154
|
import {
|
|
150879
151155
|
AuthStorage as AuthStorage3,
|
|
150880
151156
|
DefaultPackageManager as DefaultPackageManager3,
|
|
@@ -151146,7 +151422,7 @@ async function runServe(port, opts = {}) {
|
|
|
151146
151422
|
...claudeCliPaths
|
|
151147
151423
|
],
|
|
151148
151424
|
cwd,
|
|
151149
|
-
|
|
151425
|
+
join55(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
151150
151426
|
);
|
|
151151
151427
|
for (const { path: path5, error } of extensionsResult.errors) {
|
|
151152
151428
|
console.log(`[extensions] Failed to load ${path5}: ${error}`);
|
|
@@ -151300,8 +151576,8 @@ async function runServe(port, opts = {}) {
|
|
|
151300
151576
|
https: loadTlsCredentialsFromEnv()
|
|
151301
151577
|
});
|
|
151302
151578
|
const server = app.listen(selectedPort, selectedHost);
|
|
151303
|
-
await new Promise((
|
|
151304
|
-
server.once("listening",
|
|
151579
|
+
await new Promise((resolve37, reject2) => {
|
|
151580
|
+
server.once("listening", resolve37);
|
|
151305
151581
|
server.once("error", reject2);
|
|
151306
151582
|
});
|
|
151307
151583
|
const actualPort = server.address().port;
|
|
@@ -151458,7 +151734,7 @@ var daemon_exports = {};
|
|
|
151458
151734
|
__export(daemon_exports, {
|
|
151459
151735
|
runDaemon: () => runDaemon
|
|
151460
151736
|
});
|
|
151461
|
-
import { join as
|
|
151737
|
+
import { join as join56 } from "node:path";
|
|
151462
151738
|
import {
|
|
151463
151739
|
AuthStorage as AuthStorage4,
|
|
151464
151740
|
DefaultPackageManager as DefaultPackageManager4,
|
|
@@ -151728,7 +152004,7 @@ async function runDaemon(opts = {}) {
|
|
|
151728
152004
|
const extensionsResult = await discoverAndLoadExtensions4(
|
|
151729
152005
|
reconciledExtensionPaths,
|
|
151730
152006
|
cwd,
|
|
151731
|
-
|
|
152007
|
+
join56(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
151732
152008
|
);
|
|
151733
152009
|
for (const { path: path5, error } of extensionsResult.errors) {
|
|
151734
152010
|
console.log(`[extensions] Failed to load ${path5}: ${error}`);
|
|
@@ -151819,8 +152095,8 @@ async function runDaemon(opts = {}) {
|
|
|
151819
152095
|
https: loadTlsCredentialsFromEnv()
|
|
151820
152096
|
});
|
|
151821
152097
|
const server = app.listen(selectedPort, selectedHost);
|
|
151822
|
-
await new Promise((
|
|
151823
|
-
server.once("listening",
|
|
152098
|
+
await new Promise((resolve37, reject2) => {
|
|
152099
|
+
server.once("listening", resolve37);
|
|
151824
152100
|
server.once("error", reject2);
|
|
151825
152101
|
});
|
|
151826
152102
|
const actualPort = server.address().port;
|
|
@@ -151931,10 +152207,10 @@ __export(desktop_exports, {
|
|
|
151931
152207
|
});
|
|
151932
152208
|
import { spawn as spawn13 } from "node:child_process";
|
|
151933
152209
|
import { once as once2 } from "node:events";
|
|
151934
|
-
import { join as
|
|
152210
|
+
import { join as join57 } from "node:path";
|
|
151935
152211
|
import { createRequire as createRequire5 } from "node:module";
|
|
151936
152212
|
function runCommand(command, args, cwd) {
|
|
151937
|
-
return new Promise((
|
|
152213
|
+
return new Promise((resolve37, reject2) => {
|
|
151938
152214
|
const child = spawn13(command, args, {
|
|
151939
152215
|
cwd,
|
|
151940
152216
|
stdio: "inherit",
|
|
@@ -151943,7 +152219,7 @@ function runCommand(command, args, cwd) {
|
|
|
151943
152219
|
child.on("error", (error) => reject2(error));
|
|
151944
152220
|
child.on("exit", (code) => {
|
|
151945
152221
|
if (code === 0) {
|
|
151946
|
-
|
|
152222
|
+
resolve37();
|
|
151947
152223
|
return;
|
|
151948
152224
|
}
|
|
151949
152225
|
reject2(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "unknown"}`));
|
|
@@ -151986,8 +152262,8 @@ async function startDashboardRuntime(rootDir, paused) {
|
|
|
151986
152262
|
};
|
|
151987
152263
|
}
|
|
151988
152264
|
async function closeDashboardRuntime(runtime) {
|
|
151989
|
-
await new Promise((
|
|
151990
|
-
runtime.server.close(() =>
|
|
152265
|
+
await new Promise((resolve37) => {
|
|
152266
|
+
runtime.server.close(() => resolve37());
|
|
151991
152267
|
});
|
|
151992
152268
|
runtime.store.close();
|
|
151993
152269
|
}
|
|
@@ -152010,7 +152286,7 @@ async function runDesktop(options = {}) {
|
|
|
152010
152286
|
}
|
|
152011
152287
|
const runtime = await startDashboardRuntime(rootDir, Boolean(options.paused));
|
|
152012
152288
|
const electronBinary = resolveElectronBinary();
|
|
152013
|
-
const desktopEntry =
|
|
152289
|
+
const desktopEntry = join57(rootDir, "packages", "desktop", "dist", "main.js");
|
|
152014
152290
|
const electronArgs = ["--enable-source-maps", desktopEntry, ...options.dev ? ["--dev"] : []];
|
|
152015
152291
|
const electronEnv = {
|
|
152016
152292
|
...process.env,
|
|
@@ -152096,7 +152372,7 @@ __export(task_exports, {
|
|
|
152096
152372
|
});
|
|
152097
152373
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
152098
152374
|
import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync39, readFileSync as readFileSync19 } from "node:fs";
|
|
152099
|
-
import { join as
|
|
152375
|
+
import { join as join58 } from "node:path";
|
|
152100
152376
|
function asLocalProjectContext(store) {
|
|
152101
152377
|
const cwd = process.cwd();
|
|
152102
152378
|
return {
|
|
@@ -152216,10 +152492,10 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
|
|
|
152216
152492
|
console.log(` Path: .fusion/tasks/${task.id}/`);
|
|
152217
152493
|
if (attachFiles && attachFiles.length > 0) {
|
|
152218
152494
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
152219
|
-
const { basename:
|
|
152495
|
+
const { basename: basename17, extname: extname2, resolve: resolve37 } = await import("node:path");
|
|
152220
152496
|
for (const filePath of attachFiles) {
|
|
152221
|
-
const resolvedPath =
|
|
152222
|
-
const filename =
|
|
152497
|
+
const resolvedPath = resolve37(filePath);
|
|
152498
|
+
const filename = basename17(resolvedPath);
|
|
152223
152499
|
const ext = extname2(filename).toLowerCase();
|
|
152224
152500
|
const mimeType = MIME_TYPES[ext];
|
|
152225
152501
|
if (!mimeType) {
|
|
@@ -152352,7 +152628,7 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
152352
152628
|
printEntries(filteredEntries);
|
|
152353
152629
|
if (options.follow) {
|
|
152354
152630
|
const projectPath = projectContext?.projectPath ?? process.cwd();
|
|
152355
|
-
const logPath =
|
|
152631
|
+
const logPath = join58(projectPath, ".fusion", "tasks", id, "agent.log");
|
|
152356
152632
|
if (!existsSync39(logPath)) {
|
|
152357
152633
|
console.log(`
|
|
152358
152634
|
Waiting for log file to be created...`);
|
|
@@ -152511,10 +152787,10 @@ async function runTaskMerge(id, projectName) {
|
|
|
152511
152787
|
}
|
|
152512
152788
|
async function runTaskAttach(id, filePath, projectName) {
|
|
152513
152789
|
const { readFile: readFile24 } = await import("node:fs/promises");
|
|
152514
|
-
const { basename:
|
|
152515
|
-
const { resolve:
|
|
152516
|
-
const resolvedPath =
|
|
152517
|
-
const filename =
|
|
152790
|
+
const { basename: basename17, extname: extname2 } = await import("node:path");
|
|
152791
|
+
const { resolve: resolve37 } = await import("node:path");
|
|
152792
|
+
const resolvedPath = resolve37(filePath);
|
|
152793
|
+
const filename = basename17(resolvedPath);
|
|
152518
152794
|
const ext = extname2(filename).toLowerCase();
|
|
152519
152795
|
const mimeType = MIME_TYPES[ext];
|
|
152520
152796
|
if (!mimeType) {
|
|
@@ -153044,12 +153320,12 @@ async function promptText(question) {
|
|
|
153044
153320
|
console.log(" (Enter your response. Type DONE on its own line when finished):\n");
|
|
153045
153321
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
153046
153322
|
const lines = [];
|
|
153047
|
-
return new Promise((
|
|
153323
|
+
return new Promise((resolve37) => {
|
|
153048
153324
|
const askLine = () => {
|
|
153049
153325
|
rl.question(" ").then((line) => {
|
|
153050
153326
|
if (line.trim() === "DONE") {
|
|
153051
153327
|
rl.close();
|
|
153052
|
-
|
|
153328
|
+
resolve37(lines.join("\n"));
|
|
153053
153329
|
} else {
|
|
153054
153330
|
lines.push(line);
|
|
153055
153331
|
askLine();
|
|
@@ -153616,8 +153892,8 @@ var settings_export_exports = {};
|
|
|
153616
153892
|
__export(settings_export_exports, {
|
|
153617
153893
|
runSettingsExport: () => runSettingsExport
|
|
153618
153894
|
});
|
|
153619
|
-
import { writeFile as
|
|
153620
|
-
import { resolve as
|
|
153895
|
+
import { writeFile as writeFile17 } from "node:fs/promises";
|
|
153896
|
+
import { resolve as resolve29, join as join59 } from "node:path";
|
|
153621
153897
|
async function runSettingsExport(options = {}) {
|
|
153622
153898
|
const scope = options.scope ?? "both";
|
|
153623
153899
|
const project = options.projectName ? await resolveProject(options.projectName) : void 0;
|
|
@@ -153628,13 +153904,13 @@ async function runSettingsExport(options = {}) {
|
|
|
153628
153904
|
const exportData = await exportSettings(store, { scope });
|
|
153629
153905
|
let targetPath;
|
|
153630
153906
|
if (outputPath) {
|
|
153631
|
-
targetPath =
|
|
153907
|
+
targetPath = resolve29(outputPath);
|
|
153632
153908
|
} else {
|
|
153633
153909
|
const filename = generateExportFilename();
|
|
153634
|
-
targetPath =
|
|
153910
|
+
targetPath = join59(process.cwd(), filename);
|
|
153635
153911
|
}
|
|
153636
153912
|
const jsonContent = JSON.stringify(exportData, null, 2);
|
|
153637
|
-
await
|
|
153913
|
+
await writeFile17(targetPath, jsonContent);
|
|
153638
153914
|
console.log();
|
|
153639
153915
|
console.log(` \u2713 Settings exported to ${targetPath}`);
|
|
153640
153916
|
const parts = [];
|
|
@@ -153678,7 +153954,7 @@ __export(settings_import_exports, {
|
|
|
153678
153954
|
runSettingsImport: () => runSettingsImport
|
|
153679
153955
|
});
|
|
153680
153956
|
import { existsSync as existsSync40 } from "node:fs";
|
|
153681
|
-
import { resolve as
|
|
153957
|
+
import { resolve as resolve30 } from "node:path";
|
|
153682
153958
|
async function runSettingsImport(filePath, options = {}) {
|
|
153683
153959
|
const scope = options.scope ?? "both";
|
|
153684
153960
|
const project = options.projectName ? await resolveProject(options.projectName) : void 0;
|
|
@@ -153687,7 +153963,7 @@ async function runSettingsImport(filePath, options = {}) {
|
|
|
153687
153963
|
const merge = options.merge ?? true;
|
|
153688
153964
|
const skipConfirm = options.yes ?? false;
|
|
153689
153965
|
try {
|
|
153690
|
-
const resolvedPath =
|
|
153966
|
+
const resolvedPath = resolve30(filePath);
|
|
153691
153967
|
if (!existsSync40(resolvedPath)) {
|
|
153692
153968
|
console.error(`Error: File not found: ${filePath}`);
|
|
153693
153969
|
process.exit(1);
|
|
@@ -154162,7 +154438,7 @@ var init_backup2 = __esm({
|
|
|
154162
154438
|
|
|
154163
154439
|
// src/project-resolver.ts
|
|
154164
154440
|
import { existsSync as existsSync41, statSync as statSync7 } from "node:fs";
|
|
154165
|
-
import { dirname as dirname24, resolve as
|
|
154441
|
+
import { dirname as dirname24, resolve as resolve31, normalize as normalize5 } from "node:path";
|
|
154166
154442
|
import { createInterface as createInterface5 } from "node:readline/promises";
|
|
154167
154443
|
async function getCentralCore() {
|
|
154168
154444
|
if (!centralCoreInstance) {
|
|
@@ -154179,9 +154455,9 @@ async function getProjectManager() {
|
|
|
154179
154455
|
return projectManagerInstance;
|
|
154180
154456
|
}
|
|
154181
154457
|
function findKbDir(startPath) {
|
|
154182
|
-
let current =
|
|
154458
|
+
let current = resolve31(startPath);
|
|
154183
154459
|
for (let i = 0; i < 100; i++) {
|
|
154184
|
-
const kbPath =
|
|
154460
|
+
const kbPath = resolve31(current, ".fusion");
|
|
154185
154461
|
if (existsSync41(kbPath) && statSync7(kbPath).isDirectory()) {
|
|
154186
154462
|
return current;
|
|
154187
154463
|
}
|
|
@@ -154248,7 +154524,7 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
|
|
|
154248
154524
|
}
|
|
154249
154525
|
return createResolvedProject(match);
|
|
154250
154526
|
}
|
|
154251
|
-
const cwd = options.cwd ?
|
|
154527
|
+
const cwd = options.cwd ? resolve31(options.cwd) : process.cwd();
|
|
154252
154528
|
const fusionDir = findKbDir(cwd);
|
|
154253
154529
|
if (fusionDir) {
|
|
154254
154530
|
const allProjects2 = await central.listProjects();
|
|
@@ -154760,7 +155036,7 @@ __export(project_exports, {
|
|
|
154760
155036
|
runProjectSetDefault: () => runProjectSetDefault,
|
|
154761
155037
|
runProjectShow: () => runProjectShow
|
|
154762
155038
|
});
|
|
154763
|
-
import { resolve as
|
|
155039
|
+
import { resolve as resolve32, isAbsolute as isAbsolute16, relative as relative12, basename as basename14 } from "node:path";
|
|
154764
155040
|
import { existsSync as existsSync42, statSync as statSync8 } from "node:fs";
|
|
154765
155041
|
import { createInterface as createInterface7 } from "node:readline/promises";
|
|
154766
155042
|
function formatDisplayPath(projectPath) {
|
|
@@ -154768,7 +155044,7 @@ function formatDisplayPath(projectPath) {
|
|
|
154768
155044
|
if (rel && !rel.startsWith("..") && rel !== "") {
|
|
154769
155045
|
return rel;
|
|
154770
155046
|
}
|
|
154771
|
-
return
|
|
155047
|
+
return basename14(projectPath) || ".";
|
|
154772
155048
|
}
|
|
154773
155049
|
function formatLastActivity2(timestamp) {
|
|
154774
155050
|
if (!timestamp) return "never";
|
|
@@ -154889,7 +155165,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
154889
155165
|
const pathInput = await rl.question(` Project path [${defaultPath}]: `);
|
|
154890
155166
|
projectPath = pathInput.trim() || defaultPath;
|
|
154891
155167
|
}
|
|
154892
|
-
const absolutePath2 = isAbsolute16(projectPath) ? projectPath :
|
|
155168
|
+
const absolutePath2 = isAbsolute16(projectPath) ? projectPath : resolve32(process.cwd(), projectPath);
|
|
154893
155169
|
if (!existsSync42(absolutePath2)) {
|
|
154894
155170
|
console.error(`
|
|
154895
155171
|
\u2717 Path does not exist: ${projectPath}`);
|
|
@@ -154902,7 +155178,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
154902
155178
|
rl.close();
|
|
154903
155179
|
process.exit(1);
|
|
154904
155180
|
}
|
|
154905
|
-
const kbDbPath2 =
|
|
155181
|
+
const kbDbPath2 = resolve32(absolutePath2, ".fusion", "fusion.db");
|
|
154906
155182
|
if (!existsSync42(kbDbPath2) && !options.force) {
|
|
154907
155183
|
console.log(`
|
|
154908
155184
|
No fn project found at ${formatDisplayPath(absolutePath2)}`);
|
|
@@ -154918,7 +155194,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
154918
155194
|
}
|
|
154919
155195
|
}
|
|
154920
155196
|
if (!projectName) {
|
|
154921
|
-
const suggested =
|
|
155197
|
+
const suggested = basename14(absolutePath2);
|
|
154922
155198
|
projectName = await rl.question(` Project name [${suggested}]: `);
|
|
154923
155199
|
projectName = projectName.trim() || suggested;
|
|
154924
155200
|
}
|
|
@@ -154934,7 +155210,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
154934
155210
|
console.error(" Name must be 1-64 characters and contain only: a-z, A-Z, 0-9, _, -\n");
|
|
154935
155211
|
process.exit(1);
|
|
154936
155212
|
}
|
|
154937
|
-
const absolutePath = isAbsolute16(projectPath) ? projectPath :
|
|
155213
|
+
const absolutePath = isAbsolute16(projectPath) ? projectPath : resolve32(process.cwd(), projectPath);
|
|
154938
155214
|
if (!existsSync42(absolutePath)) {
|
|
154939
155215
|
console.error(`
|
|
154940
155216
|
\u2717 Path does not exist: ${projectPath}
|
|
@@ -154947,7 +155223,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
154947
155223
|
`);
|
|
154948
155224
|
process.exit(1);
|
|
154949
155225
|
}
|
|
154950
|
-
const kbDbPath =
|
|
155226
|
+
const kbDbPath = resolve32(absolutePath, ".fusion", "fusion.db");
|
|
154951
155227
|
if (!existsSync42(kbDbPath) && !options.force) {
|
|
154952
155228
|
console.error(`
|
|
154953
155229
|
\u2717 No fn project found at ${formatDisplayPath(absolutePath)}`);
|
|
@@ -155206,18 +155482,18 @@ var init_project = __esm({
|
|
|
155206
155482
|
// src/commands/skill-installation.ts
|
|
155207
155483
|
import { cpSync as cpSync2, existsSync as existsSync43, mkdirSync as mkdirSync8 } from "node:fs";
|
|
155208
155484
|
import { homedir as homedir8 } from "node:os";
|
|
155209
|
-
import { dirname as dirname25, join as
|
|
155485
|
+
import { dirname as dirname25, join as join60, resolve as resolve33 } from "node:path";
|
|
155210
155486
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
155211
155487
|
function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.env.USERPROFILE || homedir8()) {
|
|
155212
155488
|
return [
|
|
155213
|
-
{ client: "claude", targetDir:
|
|
155214
|
-
{ client: "codex", targetDir:
|
|
155215
|
-
{ client: "gemini", targetDir:
|
|
155489
|
+
{ client: "claude", targetDir: join60(homeDir, ".claude", "skills", FUSION_SKILL_NAME2) },
|
|
155490
|
+
{ client: "codex", targetDir: join60(homeDir, ".codex", "skills", FUSION_SKILL_NAME2) },
|
|
155491
|
+
{ client: "gemini", targetDir: join60(homeDir, ".gemini", "skills", FUSION_SKILL_NAME2) }
|
|
155216
155492
|
];
|
|
155217
155493
|
}
|
|
155218
155494
|
function resolveBundledFusionSkillSource() {
|
|
155219
155495
|
const here = fileURLToPath9(import.meta.url);
|
|
155220
|
-
const source =
|
|
155496
|
+
const source = resolve33(dirname25(here), "..", "..", "skill", FUSION_SKILL_NAME2);
|
|
155221
155497
|
return existsSync43(source) ? source : null;
|
|
155222
155498
|
}
|
|
155223
155499
|
function installBundledFusionSkill(options = {}) {
|
|
@@ -155276,13 +155552,13 @@ __export(init_exports, {
|
|
|
155276
155552
|
runInit: () => runInit
|
|
155277
155553
|
});
|
|
155278
155554
|
import { existsSync as existsSync44, mkdirSync as mkdirSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync20 } from "node:fs";
|
|
155279
|
-
import { join as
|
|
155555
|
+
import { join as join61, resolve as resolve34, basename as basename15 } from "node:path";
|
|
155280
155556
|
import { exec as exec11 } from "node:child_process";
|
|
155281
155557
|
import { promisify as promisify16 } from "node:util";
|
|
155282
155558
|
async function runInit(options = {}) {
|
|
155283
|
-
const cwd = options.path ?
|
|
155284
|
-
const fusionDir =
|
|
155285
|
-
const dbPath =
|
|
155559
|
+
const cwd = options.path ? resolve34(options.path) : process.cwd();
|
|
155560
|
+
const fusionDir = join61(cwd, ".fusion");
|
|
155561
|
+
const dbPath = join61(fusionDir, "fusion.db");
|
|
155286
155562
|
if (existsSync44(fusionDir) && existsSync44(dbPath)) {
|
|
155287
155563
|
const central2 = new CentralCore();
|
|
155288
155564
|
await central2.init();
|
|
@@ -155389,8 +155665,8 @@ async function runInit(options = {}) {
|
|
|
155389
155665
|
}
|
|
155390
155666
|
}
|
|
155391
155667
|
async function detectProjectName(dir2) {
|
|
155392
|
-
if (!existsSync44(
|
|
155393
|
-
return
|
|
155668
|
+
if (!existsSync44(join61(dir2, ".git"))) {
|
|
155669
|
+
return basename15(dir2) || "my-project";
|
|
155394
155670
|
}
|
|
155395
155671
|
try {
|
|
155396
155672
|
const { stdout: remoteUrl } = await execAsync11("git remote get-url origin", {
|
|
@@ -155406,10 +155682,10 @@ async function detectProjectName(dir2) {
|
|
|
155406
155682
|
}
|
|
155407
155683
|
} catch {
|
|
155408
155684
|
}
|
|
155409
|
-
return
|
|
155685
|
+
return basename15(dir2) || "my-project";
|
|
155410
155686
|
}
|
|
155411
155687
|
async function addLocalStorageToGitignore(cwd) {
|
|
155412
|
-
const gitignorePath =
|
|
155688
|
+
const gitignorePath = join61(cwd, ".gitignore");
|
|
155413
155689
|
let content = "";
|
|
155414
155690
|
if (existsSync44(gitignorePath)) {
|
|
155415
155691
|
try {
|
|
@@ -155452,7 +155728,7 @@ async function initializeGitRepo(cwd) {
|
|
|
155452
155728
|
}
|
|
155453
155729
|
await ensureGitConfig(cwd, "user.name", "Fusion");
|
|
155454
155730
|
await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
|
|
155455
|
-
const gitkeepPath =
|
|
155731
|
+
const gitkeepPath = join61(cwd, ".gitkeep");
|
|
155456
155732
|
if (!existsSync44(gitkeepPath)) {
|
|
155457
155733
|
writeFileSync3(gitkeepPath, "\n");
|
|
155458
155734
|
}
|
|
@@ -155592,7 +155868,7 @@ __export(agent_import_exports, {
|
|
|
155592
155868
|
runAgentImport: () => runAgentImport
|
|
155593
155869
|
});
|
|
155594
155870
|
import { existsSync as existsSync45, mkdirSync as mkdirSync10, readFileSync as readFileSync21, statSync as statSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
155595
|
-
import { resolve as
|
|
155871
|
+
import { resolve as resolve35 } from "node:path";
|
|
155596
155872
|
function slugifyPathSegment(input) {
|
|
155597
155873
|
if (!input || typeof input !== "string") {
|
|
155598
155874
|
return "unnamed";
|
|
@@ -155641,15 +155917,15 @@ async function importSkillsToProject(projectPath, skills, companySlug, dryRun) {
|
|
|
155641
155917
|
errors: []
|
|
155642
155918
|
};
|
|
155643
155919
|
const companyDir = slugifyPathSegment(companySlug ?? "unknown-company");
|
|
155644
|
-
const baseSkillsDir =
|
|
155920
|
+
const baseSkillsDir = resolve35(projectPath, "skills", "imported", companyDir);
|
|
155645
155921
|
for (const skill of skills) {
|
|
155646
155922
|
if (!skill.name || typeof skill.name !== "string" || skill.name.trim().length === 0) {
|
|
155647
155923
|
result.errors.push({ name: "(unnamed)", error: "Skill is missing required 'name' field" });
|
|
155648
155924
|
continue;
|
|
155649
155925
|
}
|
|
155650
155926
|
const skillSlug = slugifyPathSegment(skill.name);
|
|
155651
|
-
const skillDir =
|
|
155652
|
-
const skillPath =
|
|
155927
|
+
const skillDir = resolve35(baseSkillsDir, skillSlug);
|
|
155928
|
+
const skillPath = resolve35(skillDir, "SKILL.md");
|
|
155653
155929
|
if (existsSync45(skillPath)) {
|
|
155654
155930
|
result.skipped.push(skill.name);
|
|
155655
155931
|
continue;
|
|
@@ -155722,7 +155998,7 @@ function isArchivePath(path5) {
|
|
|
155722
155998
|
async function runAgentImport(source, options) {
|
|
155723
155999
|
const dryRun = options?.dryRun ?? false;
|
|
155724
156000
|
const skipExisting = options?.skipExisting ?? false;
|
|
155725
|
-
const sourcePath =
|
|
156001
|
+
const sourcePath = resolve35(source);
|
|
155726
156002
|
if (!existsSync45(sourcePath)) {
|
|
155727
156003
|
console.error(`Path not found: ${sourcePath}`);
|
|
155728
156004
|
process.exit(1);
|
|
@@ -155861,7 +156137,7 @@ var agent_export_exports = {};
|
|
|
155861
156137
|
__export(agent_export_exports, {
|
|
155862
156138
|
runAgentExport: () => runAgentExport
|
|
155863
156139
|
});
|
|
155864
|
-
import { resolve as
|
|
156140
|
+
import { resolve as resolve36 } from "node:path";
|
|
155865
156141
|
async function getProjectPath4(projectName) {
|
|
155866
156142
|
if (projectName) {
|
|
155867
156143
|
const context = await resolveProject(projectName);
|
|
@@ -155899,7 +156175,7 @@ async function runAgentExport(outputDir, options) {
|
|
|
155899
156175
|
console.error("No agents found to export");
|
|
155900
156176
|
process.exit(1);
|
|
155901
156177
|
}
|
|
155902
|
-
const result = await exportAgentsToDirectory(agents,
|
|
156178
|
+
const result = await exportAgentsToDirectory(agents, resolve36(outputDir), {
|
|
155903
156179
|
companyName: options?.companyName,
|
|
155904
156180
|
companySlug: options?.companySlug
|
|
155905
156181
|
});
|
|
@@ -156119,7 +156395,7 @@ __export(plugin_exports, {
|
|
|
156119
156395
|
runPluginUninstall: () => runPluginUninstall
|
|
156120
156396
|
});
|
|
156121
156397
|
import { existsSync as existsSync46 } from "node:fs";
|
|
156122
|
-
import { join as
|
|
156398
|
+
import { join as join62 } from "node:path";
|
|
156123
156399
|
import { readFile as readFile23 } from "node:fs/promises";
|
|
156124
156400
|
import * as readline from "node:readline";
|
|
156125
156401
|
async function getProjectPath6(projectName) {
|
|
@@ -156157,7 +156433,7 @@ async function createPluginLoader(pluginStore, projectName) {
|
|
|
156157
156433
|
return { store: pluginStore, loader };
|
|
156158
156434
|
}
|
|
156159
156435
|
async function loadManifestFromPath(pluginPath) {
|
|
156160
|
-
const manifestPath =
|
|
156436
|
+
const manifestPath = join62(pluginPath, "manifest.json");
|
|
156161
156437
|
if (!existsSync46(manifestPath)) {
|
|
156162
156438
|
throw new Error(`Plugin manifest not found at: ${manifestPath}`);
|
|
156163
156439
|
}
|
|
@@ -156261,14 +156537,14 @@ async function runPluginUninstall(id, options) {
|
|
|
156261
156537
|
console.log(` Uninstall "${plugin4.name}"?`);
|
|
156262
156538
|
console.log(` This will stop and remove the plugin.`);
|
|
156263
156539
|
console.log();
|
|
156264
|
-
const response = await new Promise((
|
|
156540
|
+
const response = await new Promise((resolve37) => {
|
|
156265
156541
|
const rl = readline.createInterface({
|
|
156266
156542
|
input: process.stdin,
|
|
156267
156543
|
output: process.stdout
|
|
156268
156544
|
});
|
|
156269
156545
|
rl.question(" Continue? [y/N] ", (answer) => {
|
|
156270
156546
|
rl.close();
|
|
156271
|
-
|
|
156547
|
+
resolve37(answer.toLowerCase());
|
|
156272
156548
|
});
|
|
156273
156549
|
});
|
|
156274
156550
|
if (response !== "y" && response !== "yes") {
|
|
@@ -156349,7 +156625,7 @@ __export(plugin_scaffold_exports, {
|
|
|
156349
156625
|
runPluginCreate: () => runPluginCreate
|
|
156350
156626
|
});
|
|
156351
156627
|
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as existsSync47 } from "node:fs";
|
|
156352
|
-
import { join as
|
|
156628
|
+
import { join as join63 } from "node:path";
|
|
156353
156629
|
function toTitleCase(str) {
|
|
156354
156630
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
156355
156631
|
}
|
|
@@ -156482,7 +156758,7 @@ async function runPluginCreate(name, options) {
|
|
|
156482
156758
|
process.exit(1);
|
|
156483
156759
|
}
|
|
156484
156760
|
const targetDir = options?.output ?? name;
|
|
156485
|
-
const targetPath =
|
|
156761
|
+
const targetPath = join63(process.cwd(), targetDir);
|
|
156486
156762
|
if (existsSync47(targetPath)) {
|
|
156487
156763
|
console.error(`Error: Directory '${targetDir}' already exists.`);
|
|
156488
156764
|
console.error("Please choose a different name or remove the existing directory.");
|
|
@@ -156490,16 +156766,16 @@ async function runPluginCreate(name, options) {
|
|
|
156490
156766
|
}
|
|
156491
156767
|
try {
|
|
156492
156768
|
mkdirSync11(targetPath, { recursive: true });
|
|
156493
|
-
mkdirSync11(
|
|
156494
|
-
writeFileSync5(
|
|
156495
|
-
writeFileSync5(
|
|
156496
|
-
writeFileSync5(
|
|
156497
|
-
writeFileSync5(
|
|
156769
|
+
mkdirSync11(join63(targetPath, "src", "__tests__"), { recursive: true });
|
|
156770
|
+
writeFileSync5(join63(targetPath, "package.json"), generatePackageJson(name));
|
|
156771
|
+
writeFileSync5(join63(targetPath, "tsconfig.json"), generateTsconfig());
|
|
156772
|
+
writeFileSync5(join63(targetPath, "vitest.config.ts"), generateVitestConfig());
|
|
156773
|
+
writeFileSync5(join63(targetPath, "src", "index.ts"), generateIndexTs(name));
|
|
156498
156774
|
writeFileSync5(
|
|
156499
|
-
|
|
156775
|
+
join63(targetPath, "src", "__tests__", "index.test.ts"),
|
|
156500
156776
|
generateTestTs(name)
|
|
156501
156777
|
);
|
|
156502
|
-
writeFileSync5(
|
|
156778
|
+
writeFileSync5(join63(targetPath, "README.md"), generateReadme(name));
|
|
156503
156779
|
} catch (err) {
|
|
156504
156780
|
console.error(
|
|
156505
156781
|
`Error creating plugin files: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -156616,9 +156892,9 @@ async function runSkillsInstall(args, options) {
|
|
|
156616
156892
|
stdio: "inherit",
|
|
156617
156893
|
shell: true
|
|
156618
156894
|
});
|
|
156619
|
-
const exitCode = await new Promise((
|
|
156895
|
+
const exitCode = await new Promise((resolve37, reject2) => {
|
|
156620
156896
|
child.on("exit", (code) => {
|
|
156621
|
-
|
|
156897
|
+
resolve37(code ?? 1);
|
|
156622
156898
|
});
|
|
156623
156899
|
child.on("error", (err) => {
|
|
156624
156900
|
reject2(err);
|
|
@@ -156649,7 +156925,7 @@ __export(native_patch_exports, {
|
|
|
156649
156925
|
isTerminalAvailable: () => isTerminalAvailable,
|
|
156650
156926
|
setupNativeResolution: () => setupNativeResolution
|
|
156651
156927
|
});
|
|
156652
|
-
import { join as
|
|
156928
|
+
import { join as join64, basename as basename16, dirname as dirname26 } from "node:path";
|
|
156653
156929
|
import { existsSync as existsSync48, copyFileSync, mkdirSync as mkdirSync12, symlinkSync as symlinkSync2, rmSync as rmSync5, lstatSync as lstatSync3, readlinkSync as readlinkSync2 } from "node:fs";
|
|
156654
156930
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
156655
156931
|
function findStagedNativeDir2() {
|
|
@@ -156657,13 +156933,13 @@ function findStagedNativeDir2() {
|
|
|
156657
156933
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
156658
156934
|
const prebuildName = `${platform3}-${arch}`;
|
|
156659
156935
|
const execDir = dirname26(process.execPath);
|
|
156660
|
-
const nextToBinary =
|
|
156661
|
-
if (existsSync48(
|
|
156936
|
+
const nextToBinary = join64(execDir, "runtime", prebuildName);
|
|
156937
|
+
if (existsSync48(join64(nextToBinary, "pty.node"))) {
|
|
156662
156938
|
return nextToBinary;
|
|
156663
156939
|
}
|
|
156664
156940
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
156665
|
-
const envPath =
|
|
156666
|
-
if (existsSync48(
|
|
156941
|
+
const envPath = join64(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
156942
|
+
if (existsSync48(join64(envPath, "pty.node"))) {
|
|
156667
156943
|
return envPath;
|
|
156668
156944
|
}
|
|
156669
156945
|
}
|
|
@@ -156696,17 +156972,17 @@ function setupNativeResolution() {
|
|
|
156696
156972
|
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
|
156697
156973
|
}
|
|
156698
156974
|
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
|
156699
|
-
const tmpRoot =
|
|
156700
|
-
const fnDir =
|
|
156701
|
-
const prebuildsDir =
|
|
156702
|
-
const platformDir =
|
|
156975
|
+
const tmpRoot = join64(tmpdir4(), `fn-bunfs-${process.pid}`);
|
|
156976
|
+
const fnDir = join64(tmpRoot, "fn");
|
|
156977
|
+
const prebuildsDir = join64(fnDir, "prebuilds");
|
|
156978
|
+
const platformDir = join64(prebuildsDir, basename16(nativeDir));
|
|
156703
156979
|
try {
|
|
156704
156980
|
cleanupStaleBunfsLinks();
|
|
156705
156981
|
mkdirSync12(platformDir, { recursive: true });
|
|
156706
|
-
const ptyNodeDest =
|
|
156707
|
-
copyFileSync(
|
|
156708
|
-
if (existsSync48(
|
|
156709
|
-
copyFileSync(
|
|
156982
|
+
const ptyNodeDest = join64(platformDir, "pty.node");
|
|
156983
|
+
copyFileSync(join64(nativeDir, "pty.node"), ptyNodeDest);
|
|
156984
|
+
if (existsSync48(join64(nativeDir, "spawn-helper"))) {
|
|
156985
|
+
copyFileSync(join64(nativeDir, "spawn-helper"), join64(platformDir, "spawn-helper"));
|
|
156710
156986
|
}
|
|
156711
156987
|
process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
|
|
156712
156988
|
if (process.platform !== "win32") {
|
|
@@ -156783,7 +157059,7 @@ var init_native_patch = __esm({
|
|
|
156783
157059
|
// src/bin.ts
|
|
156784
157060
|
import { existsSync as existsSync49, mkdtempSync as mkdtempSync2, readFileSync as readFileSync22, symlinkSync as symlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
156785
157061
|
import { createRequire as createRequire6 } from "node:module";
|
|
156786
|
-
import { join as
|
|
157062
|
+
import { join as join65, dirname as dirname27 } from "node:path";
|
|
156787
157063
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
156788
157064
|
import { performance as performance3 } from "node:perf_hooks";
|
|
156789
157065
|
var isBunBinary3 = typeof Bun !== "undefined" && !!Bun.embeddedFiles;
|
|
@@ -156791,7 +157067,7 @@ function configurePiPackage() {
|
|
|
156791
157067
|
if (process.env.PI_PACKAGE_DIR) {
|
|
156792
157068
|
return;
|
|
156793
157069
|
}
|
|
156794
|
-
const tmp = mkdtempSync2(
|
|
157070
|
+
const tmp = mkdtempSync2(join65(tmpdir5(), "fn-pkg-"));
|
|
156795
157071
|
let packageJson = {
|
|
156796
157072
|
name: "pi",
|
|
156797
157073
|
version: "0.1.0",
|
|
@@ -156803,9 +157079,9 @@ function configurePiPackage() {
|
|
|
156803
157079
|
const piPackageDir = dirname27(piPackagePath);
|
|
156804
157080
|
packageJson = JSON.parse(readFileSync22(piPackagePath, "utf-8"));
|
|
156805
157081
|
for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
|
|
156806
|
-
const source =
|
|
157082
|
+
const source = join65(piPackageDir, entry);
|
|
156807
157083
|
if (existsSync49(source)) {
|
|
156808
|
-
symlinkSync3(source,
|
|
157084
|
+
symlinkSync3(source, join65(tmp, entry));
|
|
156809
157085
|
}
|
|
156810
157086
|
}
|
|
156811
157087
|
} catch {
|
|
@@ -156814,7 +157090,7 @@ function configurePiPackage() {
|
|
|
156814
157090
|
...packageJson.piConfig ?? {},
|
|
156815
157091
|
configDir: ".fusion"
|
|
156816
157092
|
};
|
|
156817
|
-
writeFileSync6(
|
|
157093
|
+
writeFileSync6(join65(tmp, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
|
|
156818
157094
|
process.env.PI_PACKAGE_DIR = tmp;
|
|
156819
157095
|
}
|
|
156820
157096
|
configurePiPackage();
|
|
@@ -156842,8 +157118,8 @@ function loadEnvFile(path5) {
|
|
|
156842
157118
|
}
|
|
156843
157119
|
function loadLocalEnv() {
|
|
156844
157120
|
const cwd = process.cwd();
|
|
156845
|
-
loadEnvFile(
|
|
156846
|
-
loadEnvFile(
|
|
157121
|
+
loadEnvFile(join65(cwd, ".env"));
|
|
157122
|
+
loadEnvFile(join65(cwd, ".env.local"));
|
|
156847
157123
|
}
|
|
156848
157124
|
loadLocalEnv();
|
|
156849
157125
|
async function loadCommandHandlers() {
|