@runfusion/fusion 0.74.0-beta.2 → 0.74.0-beta.3
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 +847 -655
- package/dist/child-process-worker.js +414 -231
- package/dist/client/.vite/manifest.json +268 -268
- package/dist/client/assets/{AgentDetailView-DH4Cn5iG.js → AgentDetailView-D0J_GDct.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-BycC7HhP.js → AgentPermissionPolicyEditor-BBAwprvO.js} +1 -1
- package/dist/client/assets/{AgentsView-Dkij8Sm8.js → AgentsView-DTY5DIav.js} +3 -3
- package/dist/client/assets/{ChatView-DAsZY1We.js → ChatView-CRoW2tRJ.js} +1 -1
- package/dist/client/assets/{CommandCenter-jTzBo-pg.js → CommandCenter-BieyKvKb.js} +1 -1
- package/dist/client/assets/{DevServerView-CxlacYJp.js → DevServerView-CLR1LmhK.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DsCk3Nsw.js → DirectoryPicker-B-olNAvT.js} +1 -1
- package/dist/client/assets/{DocumentsView-8EI6KNBY.js → DocumentsView-CG_-pnXU.js} +1 -1
- package/dist/client/assets/{EvalsView-kYnaIk11.js → EvalsView-Xp0zCUlr.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-ce6DROKD.js → ExperimentalAgentOnboardingModal-z8m5V5yv.js} +1 -1
- package/dist/client/assets/{GoalsView-BVlTtw-u.js → GoalsView-Bd-4g949.js} +1 -1
- package/dist/client/assets/{InsightsView-BKQeROkb.js → InsightsView-tCgg66wJ.js} +1 -1
- package/dist/client/assets/{MemoryView-DCzTnxsV.js → MemoryView-Dqgsd_0E.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-C94HwDz5.js → PiExtensionsManager-GzGoWgb5.js} +1 -1
- package/dist/client/assets/{PluginManager-C3DegklW.js → PluginManager-BWdqEqr9.js} +1 -1
- package/dist/client/assets/{PullRequestView-CrE89UL7.js → PullRequestView-CQq1G1kY.js} +1 -1
- package/dist/client/assets/{ReportModal-BD1ZUDdV.js → ReportModal-C-3rBFhw.js} +1 -1
- package/dist/client/assets/{ResearchView-eMiRw1EM.js → ResearchView-CS1HwDg_.js} +1 -1
- package/dist/client/assets/{SecretsView-6qK8Idb7.js → SecretsView-C6RP9Rkw.js} +1 -1
- package/dist/client/assets/{SessionTerminal-DtFLyUaK.js → SessionTerminal-C9nCSefk.js} +1 -1
- package/dist/client/assets/SettingsModal-C1oEklYy.css +1 -0
- package/dist/client/assets/{SettingsModal-BkOSlfyr.js → SettingsModal-D3DCvCfP.js} +1 -1
- package/dist/client/assets/{SettingsModal-DSq-_qwo.js → SettingsModal-D4mjT8hw.js} +3 -3
- package/dist/client/assets/{SettingsTextareaRow-Btyx5kaR.js → SettingsTextareaRow-zBVXQbcC.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-Blhx-dRt.js → SetupWizardModal-C9r1dd-h.js} +2 -2
- package/dist/client/assets/{SkillsView-DGE5kYc3.js → SkillsView-DFyUBWd8.js} +1 -1
- package/dist/client/assets/{TodoView-YSGI7ATd.js → TodoView-BC8f952m.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-CZiEThu2.js → WorkflowNodeEditor-UTX757WH.js} +1 -1
- package/dist/client/assets/{agent-import-generation-DQeNZMAm.js → agent-import-generation-DN0q1xEo.js} +1 -1
- package/dist/client/assets/{app-DJIiVHdA.js → app-BP57l_5h.js} +1 -1
- package/dist/client/assets/{app-hQw_x2KJ.js → app-D4frL0Ka.js} +1 -1
- package/dist/client/assets/{app-DaikOPcV.js → app-niWDkeV8.js} +3 -3
- package/dist/client/assets/{app-Dn1u7zJ9.js → app-sLOwmHAE.js} +1 -1
- package/dist/client/assets/{app-DMZ_RusZ.js → app-vRWwM-aD.js} +1 -1
- package/dist/client/assets/{app-DxTbBEMH.js → app-zPyey_fg.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DhaJNKa4.js → architectureDiagram-3BPJPVTR-D-nqJ95-.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-pKpg7gJU.js → blockDiagram-GPEHLZMM--OlkXlyS.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-DVPXKJnr.js → c4Diagram-AAUBKEIU-CH7PaWgs.js} +1 -1
- package/dist/client/assets/channel-FJNMzlkv.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CHt90T5z.js → chunk-2J33WTMH-CpHDwqg2.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DsWFYy0a.js → chunk-4BX2VUAB-BdW4tdnc.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-D8XiXEo8.js → chunk-55IACEB6-b3tBFiuH.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DlUYBn_Y.js → chunk-727SXJPM-DifknEtv.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-BSdPOr9q.js → chunk-AQP2D5EJ-DHIZNZ4Z.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-B9IAeBld.js → chunk-FMBD7UC4-BLRLYW2y.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-CmxnYQrR.js → chunk-ND2GUHAM-Dh8f06Ld.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Dxp6Po_j.js → chunk-QZHKN3VN-CpzUiemt.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BOenhjVP.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BOenhjVP.js +1 -0
- package/dist/client/assets/common-13IRj_PO.js +1 -0
- package/dist/client/assets/common-BBynATth.js +1 -0
- package/dist/client/assets/common-BG-vw0tL.js +1 -0
- package/dist/client/assets/common-DSo46rnH.js +1 -0
- package/dist/client/assets/common-DbOCE-0i.js +1 -0
- package/dist/client/assets/common-DnXF4Jmj.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BNl3bhpS.js → cose-bilkent-S5V4N54A-CE2RJ_k0.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-DFs7WCcz.js → dagre-BM42HDAG-CCs_xlYw.js} +1 -1
- package/dist/client/assets/{dashboard-view-vc8kgLMs.js → dashboard-view-D5qv61fP.js} +1 -1
- package/dist/client/assets/{dashboard-view-ZGxLEL9r.js → dashboard-view-Eg7Jyvnm.js} +1 -1
- package/dist/client/assets/{dashboard-view-DnoTcnIo.js → dashboard-view-Z6H-k0uR.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-C2PVozvu.js → diagram-2AECGRRQ-CF60Q-de.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-DFJ5b9H8.js → diagram-5GNKFQAL-DDcGMlua.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-D335CW-c.js → diagram-KO2AKTUF-YgvJ4DQf.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DSfhroAW.js → diagram-LMA3HP47-Bi-j9nGw.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-8iGveM-Z.js → diagram-OG6HWLK6-DEmMqnwc.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Xc56MEEi.js → erDiagram-TEJ5UH35-DwmZwhiW.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DjCU9WbD.js → flowDiagram-I6XJVG4X-B5ITa_HJ.js} +1 -1
- package/dist/client/assets/{folder-open-BRrB44UX.js → folder-open-BVxA7YtM.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CXQE1bea.js → ganttDiagram-6RSMTGT7-BgAPwh9w.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII--mrSABLC.js → gitGraphDiagram-PVQCEYII-DTtGzZFj.js} +1 -1
- package/dist/client/assets/{index-C2xsZoNG.js → index-idkERMsE.js} +289 -289
- package/dist/client/assets/{infoDiagram-5YYISTIA-CTS_nljP.js → infoDiagram-5YYISTIA-CkSnTje1.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CpV5x3gk.js → ishikawaDiagram-YF4QCWOH-jn5VNpMh.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BK2QCMnt.js → journeyDiagram-JHISSGLW-BpaqoXaI.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-B4srpspY.js → kanban-definition-UN3LZRKU-CpfjJoBN.js} +1 -1
- package/dist/client/assets/{mermaid.core-B8DVAt21.js → mermaid.core-DZNGPQzF.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CsmmiPpA.js → mindmap-definition-RKZ34NQL-BdbX1EJa.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BahLDqf4.js → pieDiagram-4H26LBE5-Xn0322tJ.js} +1 -1
- package/dist/client/assets/{puzzle-BFPQsuIa.js → puzzle-CPx1RP2g.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Bo3u0wTU.js → quadrantDiagram-W4KKPZXB-OOHqqw5y.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DYkYsz7d.js → requirementDiagram-4Y6WPE33-Dvj6zvaB.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BCbh0BSY.js → sankeyDiagram-5OEKKPKP-DEkEqthK.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-C2AP9GlE.js → sequenceDiagram-3UESZ5HK-BPc9ncPj.js} +1 -1
- package/dist/client/assets/{shield-alert-tlZOi02c.js → shield-alert-baoKRyU6.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-C0Rzv9Mr.js → standing-instructions-template-CkqsGC1L.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CARkH0ug.js → stateDiagram-AJRCARHV-DywhjHIx.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-C2He043y.js → stateDiagram-v2-BHNVJYJU-D7t7x4uT.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-MvbYneEM.js → timeline-definition-PNZ67QCA-BH3CKgrg.js} +1 -1
- package/dist/client/assets/{upload-DWK0F17Z.js → upload-DtIvOGwM.js} +1 -1
- package/dist/client/assets/{users-1AkDfM14.js → users-DcxsxPlj.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DOjzzLqc.js → vennDiagram-CIIHVFJN-CCDllBgJ.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-Di70vhu2.js → wardley-L42UT6IY-C43hFLXh.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-nK6ARhDv.js → wardleyDiagram-YWT4CUSO-__f9rI8w.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-C7_y76B7.js → xychartDiagram-2RQKCTM6-DY-fpQ_x.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/client/version.json +1 -1
- package/dist/extension.js +551 -368
- package/package.json +1 -1
- package/skill/fusion/references/engine-tools.md +1 -1
- package/dist/client/assets/SettingsModal-BTfZlghk.css +0 -1
- package/dist/client/assets/channel-xFBfK0sX.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BFBVD968.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BFBVD968.js +0 -1
- package/dist/client/assets/common-BDp2y6CF.js +0 -1
- package/dist/client/assets/common-BnEo5fLN.js +0 -1
- package/dist/client/assets/common-Bzr_Y8h4.js +0 -1
- package/dist/client/assets/common-CvwyFzfv.js +0 -1
- package/dist/client/assets/common-CztCXRkz.js +0 -1
- package/dist/client/assets/common-DPe2mbb7.js +0 -1
package/dist/bin.js
CHANGED
|
@@ -5605,7 +5605,7 @@ var init_sql = __esm({
|
|
|
5605
5605
|
return new SQL([new StringChunk(str)]);
|
|
5606
5606
|
}
|
|
5607
5607
|
sql2.raw = raw;
|
|
5608
|
-
function
|
|
5608
|
+
function join156(chunks, separator) {
|
|
5609
5609
|
const result2 = [];
|
|
5610
5610
|
for (const [i, chunk] of chunks.entries()) {
|
|
5611
5611
|
if (i > 0 && separator !== void 0) {
|
|
@@ -5615,7 +5615,7 @@ var init_sql = __esm({
|
|
|
5615
5615
|
}
|
|
5616
5616
|
return new SQL(result2);
|
|
5617
5617
|
}
|
|
5618
|
-
sql2.join =
|
|
5618
|
+
sql2.join = join156;
|
|
5619
5619
|
function identifier(value) {
|
|
5620
5620
|
return new Name(value);
|
|
5621
5621
|
}
|
|
@@ -10263,7 +10263,7 @@ var init_select2 = __esm({
|
|
|
10263
10263
|
const baseTableName = this.tableName;
|
|
10264
10264
|
const tableName = getTableLikeName(table);
|
|
10265
10265
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
10266
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
10266
|
+
if (typeof tableName === "string" && this.config.joins?.some((join156) => join156.alias === tableName)) {
|
|
10267
10267
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
10268
10268
|
}
|
|
10269
10269
|
if (!this.isPartialSelect) {
|
|
@@ -11798,7 +11798,7 @@ var init_update = __esm({
|
|
|
11798
11798
|
createJoin(joinType) {
|
|
11799
11799
|
return (table, on) => {
|
|
11800
11800
|
const tableName = getTableLikeName(table);
|
|
11801
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
11801
|
+
if (typeof tableName === "string" && this.config.joins.some((join156) => join156.alias === tableName)) {
|
|
11802
11802
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
11803
11803
|
}
|
|
11804
11804
|
if (typeof on === "function") {
|
|
@@ -11894,10 +11894,10 @@ var init_update = __esm({
|
|
|
11894
11894
|
const fromFields = this.getTableLikeFields(this.config.from);
|
|
11895
11895
|
fields[tableName] = fromFields;
|
|
11896
11896
|
}
|
|
11897
|
-
for (const
|
|
11898
|
-
const tableName2 = getTableLikeName(
|
|
11899
|
-
if (typeof tableName2 === "string" && !is(
|
|
11900
|
-
const fromFields = this.getTableLikeFields(
|
|
11897
|
+
for (const join156 of this.config.joins) {
|
|
11898
|
+
const tableName2 = getTableLikeName(join156.table);
|
|
11899
|
+
if (typeof tableName2 === "string" && !is(join156.table, SQL)) {
|
|
11900
|
+
const fromFields = this.getTableLikeFields(join156.table);
|
|
11901
11901
|
fields[tableName2] = fromFields;
|
|
11902
11902
|
}
|
|
11903
11903
|
}
|
|
@@ -20501,26 +20501,26 @@ function validateParallelism(nodes2, outgoing, nodesById) {
|
|
|
20501
20501
|
}
|
|
20502
20502
|
const joinsReached = /* @__PURE__ */ new Set();
|
|
20503
20503
|
for (const edge of branchEdges) {
|
|
20504
|
-
const
|
|
20505
|
-
if (!
|
|
20504
|
+
const join157 = walkBranchToJoin(edge.to, split.id, outgoing, nodesById);
|
|
20505
|
+
if (!join157) {
|
|
20506
20506
|
throw new WorkflowIrError(`split '${split.id}' has a branch with no reachable matching join`);
|
|
20507
20507
|
}
|
|
20508
|
-
joinsReached.add(
|
|
20508
|
+
joinsReached.add(join157);
|
|
20509
20509
|
}
|
|
20510
20510
|
if (joinsReached.size !== 1) {
|
|
20511
20511
|
throw new WorkflowIrError(`split '${split.id}' branches converge on more than one join`);
|
|
20512
20512
|
}
|
|
20513
20513
|
const joinId = [...joinsReached][0];
|
|
20514
|
-
const
|
|
20515
|
-
const mode =
|
|
20514
|
+
const join156 = nodesById.get(joinId);
|
|
20515
|
+
const mode = join156.config?.mode;
|
|
20516
20516
|
if (mode && typeof mode === "object" && "quorum" in mode) {
|
|
20517
20517
|
const n = mode.quorum;
|
|
20518
20518
|
if (typeof n !== "number" || !Number.isInteger(n) || n < 1) {
|
|
20519
|
-
throw new WorkflowIrError(`join '${
|
|
20519
|
+
throw new WorkflowIrError(`join '${join156.id}' quorum must be a positive integer`);
|
|
20520
20520
|
}
|
|
20521
20521
|
if (n > branchEdges.length) {
|
|
20522
20522
|
throw new WorkflowIrError(
|
|
20523
|
-
`join '${
|
|
20523
|
+
`join '${join156.id}' quorum(${n}) exceeds the split's ${branchEdges.length} branches`
|
|
20524
20524
|
);
|
|
20525
20525
|
}
|
|
20526
20526
|
}
|
|
@@ -24076,14 +24076,14 @@ async function detectWorkspaceRepos(dir2, runner = runGitCommand, timeout2 = DEF
|
|
|
24076
24076
|
return [];
|
|
24077
24077
|
}
|
|
24078
24078
|
const { stat: stat20 } = await import("node:fs/promises");
|
|
24079
|
-
const { join:
|
|
24079
|
+
const { join: join156 } = await import("node:path");
|
|
24080
24080
|
const found = [];
|
|
24081
24081
|
const EXCLUDED_ENTRIES = /* @__PURE__ */ new Set(["node_modules", ".fusion", ".git", ".pi"]);
|
|
24082
24082
|
for (const entry of entries) {
|
|
24083
24083
|
if (EXCLUDED_ENTRIES.has(entry)) continue;
|
|
24084
|
-
const childDir =
|
|
24084
|
+
const childDir = join156(dir2, entry);
|
|
24085
24085
|
try {
|
|
24086
|
-
const s3 = await stat20(
|
|
24086
|
+
const s3 = await stat20(join156(childDir, ".git"));
|
|
24087
24087
|
if (!s3.isDirectory() && !s3.isFile()) continue;
|
|
24088
24088
|
} catch {
|
|
24089
24089
|
continue;
|
|
@@ -24096,9 +24096,9 @@ async function detectWorkspaceRepos(dir2, runner = runGitCommand, timeout2 = DEF
|
|
|
24096
24096
|
}
|
|
24097
24097
|
async function isWorkspaceModeExplicitlyDisabled(projectPath) {
|
|
24098
24098
|
try {
|
|
24099
|
-
const { readFile:
|
|
24100
|
-
const { join:
|
|
24101
|
-
const raw = await
|
|
24099
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
24100
|
+
const { join: join156 } = await import("node:path");
|
|
24101
|
+
const raw = await readFile64(join156(projectPath, ".fusion", "config.json"), "utf-8");
|
|
24102
24102
|
const config3 = JSON.parse(raw);
|
|
24103
24103
|
return config3.settings?.workspaceMode === false;
|
|
24104
24104
|
} catch {
|
|
@@ -24106,12 +24106,12 @@ async function isWorkspaceModeExplicitlyDisabled(projectPath) {
|
|
|
24106
24106
|
}
|
|
24107
24107
|
}
|
|
24108
24108
|
async function setWorkspaceModeInConfig(projectPath, value) {
|
|
24109
|
-
const { readFile:
|
|
24110
|
-
const { join:
|
|
24111
|
-
const configPath =
|
|
24109
|
+
const { readFile: readFile64, writeFile: writeFile44, mkdir: mkdir42 } = await import("node:fs/promises");
|
|
24110
|
+
const { join: join156 } = await import("node:path");
|
|
24111
|
+
const configPath = join156(projectPath, ".fusion", "config.json");
|
|
24112
24112
|
let config3 = {};
|
|
24113
24113
|
try {
|
|
24114
|
-
config3 = JSON.parse(await
|
|
24114
|
+
config3 = JSON.parse(await readFile64(configPath, "utf-8"));
|
|
24115
24115
|
} catch (err) {
|
|
24116
24116
|
if (err?.code !== "ENOENT") throw err;
|
|
24117
24117
|
}
|
|
@@ -24120,7 +24120,7 @@ async function setWorkspaceModeInConfig(projectPath, value) {
|
|
|
24120
24120
|
}
|
|
24121
24121
|
const settings = config3.settings;
|
|
24122
24122
|
settings.workspaceMode = value;
|
|
24123
|
-
await mkdir42(
|
|
24123
|
+
await mkdir42(join156(projectPath, ".fusion"), { recursive: true });
|
|
24124
24124
|
await writeFile44(configPath, JSON.stringify(config3, null, 2), "utf-8");
|
|
24125
24125
|
}
|
|
24126
24126
|
function isInRootRelativePath(entry, pathMod) {
|
|
@@ -24133,12 +24133,12 @@ function isInRootRelativePath(entry, pathMod) {
|
|
|
24133
24133
|
return true;
|
|
24134
24134
|
}
|
|
24135
24135
|
async function loadWorkspaceConfig(rootDir) {
|
|
24136
|
-
const { readFile:
|
|
24136
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
24137
24137
|
const pathMod = await import("node:path");
|
|
24138
|
-
const { join:
|
|
24139
|
-
const configPath =
|
|
24138
|
+
const { join: join156 } = pathMod;
|
|
24139
|
+
const configPath = join156(rootDir, ".fusion", WORKSPACE_CONFIG_FILENAME);
|
|
24140
24140
|
try {
|
|
24141
|
-
const raw = await
|
|
24141
|
+
const raw = await readFile64(configPath, "utf-8");
|
|
24142
24142
|
const parsed = JSON.parse(raw);
|
|
24143
24143
|
if (parsed !== null && typeof parsed === "object" && "repos" in parsed && Array.isArray(parsed.repos) && parsed.repos.every((r) => typeof r === "string")) {
|
|
24144
24144
|
const rawRepos = parsed.repos;
|
|
@@ -24152,11 +24152,11 @@ async function loadWorkspaceConfig(rootDir) {
|
|
|
24152
24152
|
}
|
|
24153
24153
|
async function saveWorkspaceConfig(rootDir, config3) {
|
|
24154
24154
|
const { mkdir: mkdir42, writeFile: writeFile44 } = await import("node:fs/promises");
|
|
24155
|
-
const { join:
|
|
24156
|
-
const fusionDir =
|
|
24155
|
+
const { join: join156 } = await import("node:path");
|
|
24156
|
+
const fusionDir = join156(rootDir, ".fusion");
|
|
24157
24157
|
await mkdir42(fusionDir, { recursive: true });
|
|
24158
24158
|
await writeFile44(
|
|
24159
|
-
|
|
24159
|
+
join156(fusionDir, WORKSPACE_CONFIG_FILENAME),
|
|
24160
24160
|
JSON.stringify(config3, null, 2),
|
|
24161
24161
|
"utf-8"
|
|
24162
24162
|
);
|
|
@@ -38985,11 +38985,11 @@ async function rekeyFallbackProjectPartition(db, fallbackProjectId, registeredPr
|
|
|
38985
38985
|
const parentKey = `${fk.parentSchema}.${fk.parentTable}`;
|
|
38986
38986
|
if (!targetKeys.has(parentKey)) continue;
|
|
38987
38987
|
const childTarget = targetKeys.has(`${fk.childSchema}.${fk.childTable}`);
|
|
38988
|
-
const
|
|
38988
|
+
const join156 = fk.childColumns.map((column, index3) => `child.${quoteIdentifier(column)} IS NOT DISTINCT FROM parent.${quoteIdentifier(fk.parentColumns[index3])}`).join(" AND ");
|
|
38989
38989
|
const registeredChildScope = childTarget ? ` AND child.${quoteIdentifier("project_id")} = ${quoteLiteral(registeredProjectId)}` : "";
|
|
38990
38990
|
const unreplaced = await tx.execute(sql.raw(`SELECT EXISTS (
|
|
38991
38991
|
SELECT 1 FROM ${relationName({ schema: fk.childSchema, table: fk.childTable })} child
|
|
38992
|
-
JOIN ${relationName({ schema: fk.parentSchema, table: fk.parentTable })} parent ON ${
|
|
38992
|
+
JOIN ${relationName({ schema: fk.parentSchema, table: fk.parentTable })} parent ON ${join156}
|
|
38993
38993
|
JOIN fusion_rekey_conflict_candidates parent_candidate
|
|
38994
38994
|
ON parent_candidate.schema_name = ${quoteLiteral(fk.parentSchema)}
|
|
38995
38995
|
AND parent_candidate.table_name = ${quoteLiteral(fk.parentTable)}
|
|
@@ -49826,8 +49826,8 @@ var require_CronFileParser = __commonJS({
|
|
|
49826
49826
|
* @throws If file cannot be read
|
|
49827
49827
|
*/
|
|
49828
49828
|
static async parseFile(filePath) {
|
|
49829
|
-
const { readFile:
|
|
49830
|
-
const data = await
|
|
49829
|
+
const { readFile: readFile64 } = await Promise.resolve().then(() => __importStar(__require("fs/promises")));
|
|
49830
|
+
const data = await readFile64(filePath, "utf8");
|
|
49831
49831
|
return _CronFileParser.#parseContent(data);
|
|
49832
49832
|
}
|
|
49833
49833
|
/**
|
|
@@ -133433,8 +133433,8 @@ var require_graceful_fs = __commonJS({
|
|
|
133433
133433
|
fs11.createReadStream = createReadStream6;
|
|
133434
133434
|
fs11.createWriteStream = createWriteStream2;
|
|
133435
133435
|
var fs$readFile = fs11.readFile;
|
|
133436
|
-
fs11.readFile =
|
|
133437
|
-
function
|
|
133436
|
+
fs11.readFile = readFile64;
|
|
133437
|
+
function readFile64(path14, options, cb) {
|
|
133438
133438
|
if (typeof options === "function")
|
|
133439
133439
|
cb = options, options = null;
|
|
133440
133440
|
return go$readFile(path14, options, cb);
|
|
@@ -136150,10 +136150,10 @@ async function runHoldReleaseSweep(store, deps) {
|
|
|
136150
136150
|
}
|
|
136151
136151
|
return result2;
|
|
136152
136152
|
}
|
|
136153
|
-
async function issueRelease(store, deps, task, target, ir2) {
|
|
136153
|
+
async function issueRelease(store, deps, task, target, ir2, options = {}) {
|
|
136154
136154
|
const targetColumn = findColumn2(ir2, target);
|
|
136155
136155
|
const targetIsProcessing = targetColumn ? resolveColumnFlags(targetColumn).countsTowardWip === true : false;
|
|
136156
|
-
if (targetIsProcessing && await isUnplannedForExecution(store, task, ir2)) {
|
|
136156
|
+
if (targetIsProcessing && !options.allowUnplanned && await isUnplannedForExecution(store, task, ir2)) {
|
|
136157
136157
|
schedulerLog.log(`Hold release for ${task.id} blocked \u2014 card is unplanned and cannot enter processing column ${target}`);
|
|
136158
136158
|
return false;
|
|
136159
136159
|
}
|
|
@@ -136195,7 +136195,7 @@ async function issueRelease(store, deps, task, target, ir2) {
|
|
|
136195
136195
|
return false;
|
|
136196
136196
|
}
|
|
136197
136197
|
}
|
|
136198
|
-
async function promoteHeldTask(store, taskId, deps = {}) {
|
|
136198
|
+
async function promoteHeldTask(store, taskId, deps = {}, options = {}) {
|
|
136199
136199
|
const task = await store.getTask(taskId);
|
|
136200
136200
|
if (!task) return { released: false, rejection: "task-not-found" };
|
|
136201
136201
|
const ir2 = await resolveWorkflowIrForTask(store, taskId);
|
|
@@ -136206,17 +136206,50 @@ async function promoteHeldTask(store, taskId, deps = {}) {
|
|
|
136206
136206
|
if (!target) return { released: false, rejection: "no-release-target" };
|
|
136207
136207
|
const targetColumn = findColumn2(ir2, target);
|
|
136208
136208
|
const targetIsProcessing = targetColumn ? resolveColumnFlags(targetColumn).countsTowardWip === true : false;
|
|
136209
|
-
|
|
136209
|
+
const unplanned = targetIsProcessing && await isUnplannedForExecution(store, task, ir2);
|
|
136210
|
+
if (unplanned && options.force !== true) {
|
|
136210
136211
|
return { released: false, rejection: "unplanned-for-execution", toColumn: target };
|
|
136211
136212
|
}
|
|
136213
|
+
let promoted = task;
|
|
136214
|
+
if (unplanned) {
|
|
136215
|
+
if (task.status === "needs-replan" || task.status === "plan-review-unavailable") {
|
|
136216
|
+
try {
|
|
136217
|
+
await store.updateTask(task.id, { status: null });
|
|
136218
|
+
promoted = { ...task, status: void 0 };
|
|
136219
|
+
} catch (error3) {
|
|
136220
|
+
schedulerLog.warn(
|
|
136221
|
+
`Force-promote for ${task.id} could not clear replan status: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
136222
|
+
);
|
|
136223
|
+
}
|
|
136224
|
+
}
|
|
136225
|
+
if (typeof store.recordRunAuditEvent === "function") {
|
|
136226
|
+
try {
|
|
136227
|
+
await store.recordRunAuditEvent({
|
|
136228
|
+
domain: "database",
|
|
136229
|
+
mutationType: "task:promote-forced-unplanned",
|
|
136230
|
+
target: task.id,
|
|
136231
|
+
taskId: task.id,
|
|
136232
|
+
agentId: "system",
|
|
136233
|
+
runId: `promote-force-${task.id}`,
|
|
136234
|
+
metadata: { fromColumn: task.column, toColumn: target, priorStatus: task.status ?? null }
|
|
136235
|
+
});
|
|
136236
|
+
} catch {
|
|
136237
|
+
}
|
|
136238
|
+
}
|
|
136239
|
+
schedulerLog.log(`Force-promote for ${task.id} bypassing unplanned gate into ${target} (operator override)`);
|
|
136240
|
+
}
|
|
136212
136241
|
const released = await issueRelease(
|
|
136213
136242
|
store,
|
|
136214
136243
|
{ now: () => Date.now(), reserveSlot: deps.reserveSlot, allocateWorktree: deps.allocateWorktree },
|
|
136215
|
-
|
|
136244
|
+
promoted,
|
|
136216
136245
|
target,
|
|
136217
|
-
ir2
|
|
136246
|
+
ir2,
|
|
136247
|
+
{ allowUnplanned: unplanned }
|
|
136218
136248
|
);
|
|
136219
|
-
|
|
136249
|
+
if (!released) {
|
|
136250
|
+
return { released: false, rejection: "capacity-exhausted-or-no-slot" };
|
|
136251
|
+
}
|
|
136252
|
+
return { released: true, toColumn: target, forcedUnplanned: unplanned || void 0 };
|
|
136220
136253
|
}
|
|
136221
136254
|
async function releaseHeldTaskByEvent(store, taskId, eventTag, deps = {}) {
|
|
136222
136255
|
const task = await store.getTask(taskId);
|
|
@@ -162389,6 +162422,86 @@ var init_research_step_runner = __esm({
|
|
|
162389
162422
|
}
|
|
162390
162423
|
});
|
|
162391
162424
|
|
|
162425
|
+
// ../engine/src/plan-artifact-writeback.ts
|
|
162426
|
+
import { readFile as readFile29 } from "node:fs/promises";
|
|
162427
|
+
import { join as join61 } from "node:path";
|
|
162428
|
+
function relativePromptPath(taskId) {
|
|
162429
|
+
return `.fusion/tasks/${taskId}/PROMPT.md`;
|
|
162430
|
+
}
|
|
162431
|
+
async function readIfPresent(path14) {
|
|
162432
|
+
try {
|
|
162433
|
+
return await readFile29(path14, "utf-8");
|
|
162434
|
+
} catch {
|
|
162435
|
+
return null;
|
|
162436
|
+
}
|
|
162437
|
+
}
|
|
162438
|
+
async function reconcileWorktreePlanArtifact(options) {
|
|
162439
|
+
const { store, taskId, rootDir, planningCwd, logger: logger3 } = options;
|
|
162440
|
+
const relPath = relativePromptPath(taskId);
|
|
162441
|
+
const rootContent = await readIfPresent(join61(rootDir, relPath));
|
|
162442
|
+
if (planningCwd === rootDir) {
|
|
162443
|
+
return { outcome: "not-worktree", content: rootContent ?? void 0 };
|
|
162444
|
+
}
|
|
162445
|
+
const worktreeContent = await readIfPresent(join61(planningCwd, relPath));
|
|
162446
|
+
if (worktreeContent === null) {
|
|
162447
|
+
return { outcome: "no-worktree-artifact", content: rootContent ?? void 0 };
|
|
162448
|
+
}
|
|
162449
|
+
if (worktreeContent.trim().length === 0) {
|
|
162450
|
+
return { outcome: "worktree-artifact-empty", content: rootContent ?? void 0 };
|
|
162451
|
+
}
|
|
162452
|
+
if (rootContent === worktreeContent) {
|
|
162453
|
+
return { outcome: "already-authoritative", content: rootContent };
|
|
162454
|
+
}
|
|
162455
|
+
try {
|
|
162456
|
+
await store.updateTask(taskId, { prompt: worktreeContent });
|
|
162457
|
+
logger3?.log?.(
|
|
162458
|
+
`${taskId}: recovered a worktree-local PROMPT.md into the project .fusion folder (${planningCwd})`
|
|
162459
|
+
);
|
|
162460
|
+
return { outcome: "recovered", content: worktreeContent };
|
|
162461
|
+
} catch (error3) {
|
|
162462
|
+
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
162463
|
+
logger3?.warn?.(
|
|
162464
|
+
`${taskId}: failed to copy the worktree-local PROMPT.md back into the project .fusion folder: ${message}`
|
|
162465
|
+
);
|
|
162466
|
+
return { outcome: "recovery-failed", content: rootContent ?? void 0 };
|
|
162467
|
+
}
|
|
162468
|
+
}
|
|
162469
|
+
async function mirrorPlanToProjectDb(store, taskId, content, options = {}) {
|
|
162470
|
+
if (content.trim().length === 0) return false;
|
|
162471
|
+
if (typeof store.upsertTaskDocument !== "function") return false;
|
|
162472
|
+
try {
|
|
162473
|
+
if (typeof store.getTaskDocument === "function") {
|
|
162474
|
+
const existing = await store.getTaskDocument(taskId, PLAN_DOCUMENT_KEY);
|
|
162475
|
+
if (typeof existing?.content === "string" && existing.content === content) return false;
|
|
162476
|
+
}
|
|
162477
|
+
await store.upsertTaskDocument(taskId, {
|
|
162478
|
+
key: PLAN_DOCUMENT_KEY,
|
|
162479
|
+
content,
|
|
162480
|
+
author: options.author ?? "agent"
|
|
162481
|
+
});
|
|
162482
|
+
return true;
|
|
162483
|
+
} catch (error3) {
|
|
162484
|
+
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
162485
|
+
options.logger?.warn?.(`${taskId}: failed to mirror the plan into the project database: ${message}`);
|
|
162486
|
+
return false;
|
|
162487
|
+
}
|
|
162488
|
+
}
|
|
162489
|
+
async function persistPlanArtifact(options) {
|
|
162490
|
+
const result2 = await reconcileWorktreePlanArtifact(options);
|
|
162491
|
+
const mirrored = result2.content ? await mirrorPlanToProjectDb(options.store, options.taskId, result2.content, {
|
|
162492
|
+
author: options.author,
|
|
162493
|
+
logger: options.logger
|
|
162494
|
+
}) : false;
|
|
162495
|
+
return { ...result2, mirrored };
|
|
162496
|
+
}
|
|
162497
|
+
var PLAN_DOCUMENT_KEY;
|
|
162498
|
+
var init_plan_artifact_writeback = __esm({
|
|
162499
|
+
"../engine/src/plan-artifact-writeback.ts"() {
|
|
162500
|
+
"use strict";
|
|
162501
|
+
PLAN_DOCUMENT_KEY = "plan";
|
|
162502
|
+
}
|
|
162503
|
+
});
|
|
162504
|
+
|
|
162392
162505
|
// ../engine/src/auto-recovery-handlers/message-delivery.ts
|
|
162393
162506
|
import { setTimeout as delay2 } from "node:timers/promises";
|
|
162394
162507
|
var baseLog, MessageDeliveryAutoRecoveryHandler;
|
|
@@ -164398,7 +164511,7 @@ var init_worktree_prune = __esm({
|
|
|
164398
164511
|
|
|
164399
164512
|
// ../engine/src/worktree-stale-lock.ts
|
|
164400
164513
|
import { exec as exec8 } from "node:child_process";
|
|
164401
|
-
import { readFile as
|
|
164514
|
+
import { readFile as readFile31, stat as stat8, unlink as unlink9 } from "node:fs/promises";
|
|
164402
164515
|
import { dirname as dirname23, resolve as resolve26 } from "node:path";
|
|
164403
164516
|
import { promisify as promisify12 } from "node:util";
|
|
164404
164517
|
function parseIndexLockPath(stderr) {
|
|
@@ -164423,7 +164536,7 @@ async function resolveOwningWorktreePath(input) {
|
|
|
164423
164536
|
if (!worktreeName) return void 0;
|
|
164424
164537
|
const gitdirFile = resolve26(dirname23(input.lockPath), "gitdir");
|
|
164425
164538
|
try {
|
|
164426
|
-
const gitdirRef = (await
|
|
164539
|
+
const gitdirRef = (await readFile31(gitdirFile, "utf-8")).trim();
|
|
164427
164540
|
if (gitdirRef) {
|
|
164428
164541
|
const resolvedGitdirRef = resolve26(dirname23(gitdirFile), gitdirRef);
|
|
164429
164542
|
if (resolvedGitdirRef.endsWith("/.git") || resolvedGitdirRef.endsWith("\\.git")) {
|
|
@@ -165802,7 +165915,7 @@ import { exec as exec11, execFile as execFile9 } from "node:child_process";
|
|
|
165802
165915
|
import { promisify as promisify15 } from "node:util";
|
|
165803
165916
|
import { existsSync as existsSync47, lstatSync as lstatSync2, readdirSync as readdirSync7, readFileSync as readFileSync16, rmSync as rmSync5, realpathSync as realpathSync6 } from "node:fs";
|
|
165804
165917
|
import { mkdir as mkdir24 } from "node:fs/promises";
|
|
165805
|
-
import { basename as basename15, dirname as dirname24, join as
|
|
165918
|
+
import { basename as basename15, dirname as dirname24, join as join62, relative as relative8, resolve as resolve29, isAbsolute as isAbsolute9 } from "node:path";
|
|
165806
165919
|
async function getWorktrunkBinary(settings) {
|
|
165807
165920
|
const cacheKey = `${process.env.HOME ?? ""}::${settings.binaryPath ?? ""}`;
|
|
165808
165921
|
const cached2 = _worktrunkBinaryCache.get(cacheKey);
|
|
@@ -165953,7 +166066,7 @@ async function isRegisteredGitWorktree2(rootDir, worktreePath) {
|
|
|
165953
166066
|
return (await getRegisteredWorktreePaths(rootDir)).has(canonicalizePath(worktreePath));
|
|
165954
166067
|
}
|
|
165955
166068
|
function hasRequiredWorktreeFiles(worktreePath) {
|
|
165956
|
-
return existsSync47(
|
|
166069
|
+
return existsSync47(join62(worktreePath, ".git"));
|
|
165957
166070
|
}
|
|
165958
166071
|
async function isInsideGitWorkTree2(worktreePath) {
|
|
165959
166072
|
try {
|
|
@@ -166086,7 +166199,7 @@ async function scanIdleWorktrees(rootDir, store, settings) {
|
|
|
166086
166199
|
let dirs;
|
|
166087
166200
|
try {
|
|
166088
166201
|
const entries = readdirSync7(worktreesDir, { withFileTypes: true });
|
|
166089
|
-
dirs = entries.filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) =>
|
|
166202
|
+
dirs = entries.filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) => join62(worktreesDir, e.name));
|
|
166090
166203
|
} catch (err) {
|
|
166091
166204
|
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
166092
166205
|
worktreePoolLog.warn(`Failed to read .worktrees/ directory: ${errorMessage4}`);
|
|
@@ -166118,7 +166231,7 @@ async function cleanupOrphanedWorktrees(rootDir, store, settings) {
|
|
|
166118
166231
|
let dirs = [];
|
|
166119
166232
|
if (existsSync47(worktreesDir)) {
|
|
166120
166233
|
try {
|
|
166121
|
-
dirs = readdirSync7(worktreesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) =>
|
|
166234
|
+
dirs = readdirSync7(worktreesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) => join62(worktreesDir, e.name));
|
|
166122
166235
|
} catch (err) {
|
|
166123
166236
|
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
166124
166237
|
worktreePoolLog.warn(`Failed to read .worktrees/ directory for cleanup: ${errorMessage4}`);
|
|
@@ -166196,11 +166309,11 @@ async function reapOrphanWorktrees(projectRoot, settings) {
|
|
|
166196
166309
|
entries = readdirSync7(worktreesDir, { withFileTypes: true }).filter((e) => {
|
|
166197
166310
|
if (!e.isDirectory() || isAiMergeContainerDir(e.name)) return false;
|
|
166198
166311
|
try {
|
|
166199
|
-
return lstatSync2(
|
|
166312
|
+
return lstatSync2(join62(worktreesDir, e.name)).isDirectory() && !lstatSync2(join62(worktreesDir, e.name)).isSymbolicLink();
|
|
166200
166313
|
} catch {
|
|
166201
166314
|
return false;
|
|
166202
166315
|
}
|
|
166203
|
-
}).map((e) => ({ name: e.name, fullPath:
|
|
166316
|
+
}).map((e) => ({ name: e.name, fullPath: join62(worktreesDir, e.name) }));
|
|
166204
166317
|
} catch (err) {
|
|
166205
166318
|
const msg = err instanceof Error ? err.message : String(err);
|
|
166206
166319
|
worktreePoolLog.warn(`reapOrphanWorktrees: failed to read .worktrees/ \u2014 ${msg}`);
|
|
@@ -166219,7 +166332,7 @@ async function reapOrphanWorktrees(projectRoot, settings) {
|
|
|
166219
166332
|
if (registered2.has(resolvedFull)) {
|
|
166220
166333
|
continue;
|
|
166221
166334
|
}
|
|
166222
|
-
const dotGit =
|
|
166335
|
+
const dotGit = join62(resolvedFull, ".git");
|
|
166223
166336
|
if (existsSync47(dotGit)) {
|
|
166224
166337
|
if (!dotGitPointerIsDangling(dotGit)) {
|
|
166225
166338
|
worktreePoolLog.log(`reapOrphanWorktrees: skipping ${name2} (has .git entry but not in registered list \u2014 may be partially registered)`);
|
|
@@ -166585,27 +166698,27 @@ var init_worktree_pool = __esm({
|
|
|
166585
166698
|
|
|
166586
166699
|
// ../engine/src/worktree-paths.ts
|
|
166587
166700
|
import { homedir as homedir10 } from "node:os";
|
|
166588
|
-
import { basename as basename16, isAbsolute as isAbsolute10, join as
|
|
166701
|
+
import { basename as basename16, isAbsolute as isAbsolute10, join as join63, relative as relative9, resolve as resolve30 } from "node:path";
|
|
166589
166702
|
function isAiMergeContainerDir(name2) {
|
|
166590
166703
|
return name2 === AI_MERGE_DIRNAME;
|
|
166591
166704
|
}
|
|
166592
166705
|
function resolveAiMergeRootPath(rootDir, settings) {
|
|
166593
|
-
return
|
|
166706
|
+
return join63(resolveWorktreesDir(rootDir, settings), AI_MERGE_DIRNAME);
|
|
166594
166707
|
}
|
|
166595
166708
|
function resolveLegacyAiMergeRootPath(rootDir) {
|
|
166596
|
-
return
|
|
166709
|
+
return join63(rootDir, ".fusion", "ai-merge");
|
|
166597
166710
|
}
|
|
166598
166711
|
function resolveWorktreesDir(rootDir, settings) {
|
|
166599
166712
|
const configured = settings?.worktreesDir;
|
|
166600
166713
|
if (!configured) {
|
|
166601
|
-
return
|
|
166714
|
+
return join63(rootDir, ".worktrees");
|
|
166602
166715
|
}
|
|
166603
166716
|
const expandedHome = configured.replace(/^~(?=$|[\\/])/, homedir10());
|
|
166604
166717
|
const expandedRepo = expandedHome.replaceAll("{repo}", basename16(rootDir));
|
|
166605
166718
|
return resolve30(rootDir, expandedRepo);
|
|
166606
166719
|
}
|
|
166607
166720
|
function resolveTaskWorktreePath(rootDir, settings, worktreeName) {
|
|
166608
|
-
return
|
|
166721
|
+
return join63(resolveWorktreesDir(rootDir, settings), worktreeName);
|
|
166609
166722
|
}
|
|
166610
166723
|
async function resolveTaskWorktreePathForBackend(rootDir, worktreeName, settings, backend, branch) {
|
|
166611
166724
|
if (backend.kind === "worktrunk" && backend.resolveWorktreePath) {
|
|
@@ -167719,9 +167832,9 @@ function assertInRootRepoRelPath(repoRelPath, sep23, isAbsolute36, normalize10)
|
|
|
167719
167832
|
async function acquireWorkspaceRepoWorktree(opts) {
|
|
167720
167833
|
const { repoRelPath, workspaceRootDir, task, store, settings, logger: logger3, secretsStore, audit, runContext, runConfiguredCommand: runConfiguredCommand2, taskEnv } = opts;
|
|
167721
167834
|
const registry3 = opts.registry ?? activeSessionRegistry;
|
|
167722
|
-
const { join:
|
|
167835
|
+
const { join: join156, isAbsolute: isAbsolute36, normalize: normalize10, sep: sep23 } = await import("node:path");
|
|
167723
167836
|
assertInRootRepoRelPath(repoRelPath, sep23, isAbsolute36, normalize10);
|
|
167724
|
-
const repoAbsPath =
|
|
167837
|
+
const repoAbsPath = join156(workspaceRootDir, repoRelPath);
|
|
167725
167838
|
const existing = task.workspaceWorktrees?.[repoRelPath];
|
|
167726
167839
|
if (existing) {
|
|
167727
167840
|
let live = existsSync49(existing.worktreePath);
|
|
@@ -169445,7 +169558,7 @@ import { execFile as execFile11 } from "node:child_process";
|
|
|
169445
169558
|
import { createRequire as createRequire6 } from "node:module";
|
|
169446
169559
|
import { mkdtemp, rm as rm7, writeFile as writeFile24 } from "node:fs/promises";
|
|
169447
169560
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
169448
|
-
import { join as
|
|
169561
|
+
import { join as join64 } from "node:path";
|
|
169449
169562
|
function getTransformSync() {
|
|
169450
169563
|
if (!cachedTransformSync) {
|
|
169451
169564
|
const req = createRequire6(import.meta.url);
|
|
@@ -169532,9 +169645,9 @@ function readStdin() {
|
|
|
169532
169645
|
async function runCodeNode(opts) {
|
|
169533
169646
|
const timeoutMs = resolveCodeNodeTimeout(opts.timeoutMs);
|
|
169534
169647
|
const compiled = await compileCodeNodeSource(opts.source);
|
|
169535
|
-
const dir2 = await mkdtemp(
|
|
169536
|
-
const userModuleFile =
|
|
169537
|
-
const harnessFile =
|
|
169648
|
+
const dir2 = await mkdtemp(join64(tmpdir4(), "fusion-code-node-"));
|
|
169649
|
+
const userModuleFile = join64(dir2, "user.mjs");
|
|
169650
|
+
const harnessFile = join64(dir2, "harness.mjs");
|
|
169538
169651
|
try {
|
|
169539
169652
|
await writeFile24(userModuleFile, compiled, "utf8");
|
|
169540
169653
|
await writeFile24(harnessFile, buildChildHarness(userModuleFile), "utf8");
|
|
@@ -169762,11 +169875,11 @@ var init_code_node_runner = __esm({
|
|
|
169762
169875
|
});
|
|
169763
169876
|
|
|
169764
169877
|
// ../engine/src/agent-tools.ts
|
|
169765
|
-
import { appendFile as appendFile3, mkdir as mkdir26, readFile as
|
|
169878
|
+
import { appendFile as appendFile3, mkdir as mkdir26, readFile as readFile32, readdir as readdir9, realpath, stat as stat9, writeFile as writeFile25 } from "node:fs/promises";
|
|
169766
169879
|
import { existsSync as existsSync50 } from "node:fs";
|
|
169767
169880
|
import { createHash as createHash16, randomUUID as randomUUID46 } from "node:crypto";
|
|
169768
169881
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
169769
|
-
import { extname as extname3, isAbsolute as isAbsolute12, join as
|
|
169882
|
+
import { extname as extname3, isAbsolute as isAbsolute12, join as join65, relative as relative11, resolve as resolve32, sep as sep9 } from "node:path";
|
|
169770
169883
|
import { Type as Type2 } from "@earendil-works/pi-ai";
|
|
169771
169884
|
function sanitizeAgentMemoryId(agentId) {
|
|
169772
169885
|
return agentId.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
|
|
@@ -169778,16 +169891,16 @@ function agentDreamsDisplayPath(agentId) {
|
|
|
169778
169891
|
return `${AGENT_MEMORY_ROOT3}/${sanitizeAgentMemoryId(agentId)}/${AGENT_DREAMS_FILENAME2}`;
|
|
169779
169892
|
}
|
|
169780
169893
|
function agentMemoryDirectory(rootDir, agentId) {
|
|
169781
|
-
return
|
|
169894
|
+
return join65(rootDir, AGENT_MEMORY_ROOT3, sanitizeAgentMemoryId(agentId));
|
|
169782
169895
|
}
|
|
169783
169896
|
function agentMemoryFilePath(rootDir, agentId) {
|
|
169784
|
-
return
|
|
169897
|
+
return join65(agentMemoryDirectory(rootDir, agentId), AGENT_MEMORY_FILENAME2);
|
|
169785
169898
|
}
|
|
169786
169899
|
function agentDreamsFilePath(rootDir, agentId) {
|
|
169787
|
-
return
|
|
169900
|
+
return join65(agentMemoryDirectory(rootDir, agentId), AGENT_DREAMS_FILENAME2);
|
|
169788
169901
|
}
|
|
169789
169902
|
function agentDailyFilePath(rootDir, agentId, date5 = /* @__PURE__ */ new Date()) {
|
|
169790
|
-
return
|
|
169903
|
+
return join65(agentMemoryDirectory(rootDir, agentId), `${date5.toISOString().slice(0, 10)}.md`);
|
|
169791
169904
|
}
|
|
169792
169905
|
async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
169793
169906
|
const safeRoot = typeof rootDir === "string" ? rootDir.trim() : "";
|
|
@@ -169801,7 +169914,7 @@ async function readAgentMemoryWorkspaceLongTerm(rootDir, agentId) {
|
|
|
169801
169914
|
if (!fileStat.isFile()) {
|
|
169802
169915
|
return "";
|
|
169803
169916
|
}
|
|
169804
|
-
const content = await
|
|
169917
|
+
const content = await readFile32(filePath, "utf-8");
|
|
169805
169918
|
return typeof content === "string" ? content.trim() : "";
|
|
169806
169919
|
} catch {
|
|
169807
169920
|
return "";
|
|
@@ -169880,7 +169993,7 @@ async function listAgentMemoryFiles2(rootDir, agentMemory) {
|
|
|
169880
169993
|
}
|
|
169881
169994
|
for (const entry of entries) {
|
|
169882
169995
|
if (!DAILY_AGENT_MEMORY_RE2.test(entry)) continue;
|
|
169883
|
-
const absPath =
|
|
169996
|
+
const absPath = join65(dir2, entry);
|
|
169884
169997
|
const fileStat = await stat9(absPath);
|
|
169885
169998
|
if (fileStat.isFile()) {
|
|
169886
169999
|
files.push({
|
|
@@ -169903,7 +170016,7 @@ async function searchAgentMemoryFile(rootDir, agentMemory, query, limit) {
|
|
|
169903
170016
|
}
|
|
169904
170017
|
const results = [];
|
|
169905
170018
|
for (const file of await listAgentMemoryFiles2(rootDir, agentMemory)) {
|
|
169906
|
-
const content = await
|
|
170019
|
+
const content = await readFile32(file.absPath, "utf-8");
|
|
169907
170020
|
const lines = content.split("\n");
|
|
169908
170021
|
for (let index3 = 0; index3 < lines.length; index3 += 8) {
|
|
169909
170022
|
const chunk = lines.slice(index3, index3 + 12).join("\n").trim();
|
|
@@ -170049,7 +170162,7 @@ function resolveAgentMemoryPath(rootDir, agentId, path14) {
|
|
|
170049
170162
|
return null;
|
|
170050
170163
|
}
|
|
170051
170164
|
return {
|
|
170052
|
-
absPath:
|
|
170165
|
+
absPath: join65(agentMemoryDirectory(rootDir, agentId), filename),
|
|
170053
170166
|
displayPath: `${prefix}${filename}`
|
|
170054
170167
|
};
|
|
170055
170168
|
}
|
|
@@ -170059,7 +170172,7 @@ async function getAgentMemoryWindow(rootDir, agentMemory, path14, startLine = 1,
|
|
|
170059
170172
|
return null;
|
|
170060
170173
|
}
|
|
170061
170174
|
await syncAgentMemoryFile(rootDir, agentMemory);
|
|
170062
|
-
const content = await
|
|
170175
|
+
const content = await readFile32(resolved.absPath, "utf-8");
|
|
170063
170176
|
const lines = content.split("\n");
|
|
170064
170177
|
const start = Math.max(1, Math.floor(startLine));
|
|
170065
170178
|
const count2 = Math.max(1, Math.min(Math.floor(lineCount), 200));
|
|
@@ -170718,6 +170831,9 @@ function createTaskPromptWriteTool(store, taskId, runContext) {
|
|
|
170718
170831
|
if (persisted?.prompt !== params.content) {
|
|
170719
170832
|
throw new Error("authoritative PROMPT.md read-back did not match the requested content; persistence could not be verified");
|
|
170720
170833
|
}
|
|
170834
|
+
await mirrorPlanToProjectDb(store, taskId, params.content, {
|
|
170835
|
+
author: runContext?.agentId ?? "agent"
|
|
170836
|
+
});
|
|
170721
170837
|
return {
|
|
170722
170838
|
content: [{ type: "text", text: `Updated PROMPT.md for ${taskId}.` }],
|
|
170723
170839
|
details: {}
|
|
@@ -171006,7 +171122,7 @@ async function readArtifactFileFromPath(params, baseDir) {
|
|
|
171006
171122
|
if (!mimeType) {
|
|
171007
171123
|
throw new Error(`Could not infer a MIME type from ${resolvedPath}; pass mimeType explicitly.`);
|
|
171008
171124
|
}
|
|
171009
|
-
const data = await
|
|
171125
|
+
const data = await readFile32(canonicalPath);
|
|
171010
171126
|
if (params.type === "image") {
|
|
171011
171127
|
if (!mimeType.startsWith("image/")) {
|
|
171012
171128
|
throw new Error(`image artifacts require an image/* mimeType, got ${mimeType}.`);
|
|
@@ -171349,25 +171465,33 @@ function createTaskPromoteTool(store, currentTaskId) {
|
|
|
171349
171465
|
return {
|
|
171350
171466
|
name: "fn_task_promote",
|
|
171351
171467
|
label: "Promote Held Task",
|
|
171352
|
-
description: "Manually promote a held task out of its hold column, releasing it regardless of the hold's release kind (the explicit operator action a 'manual' hold waits for). Defaults to the current task. Returns the destination column, or a rejection reason when the task is not held or the destination is full.",
|
|
171468
|
+
description: "Manually promote a held task out of its hold column, releasing it regardless of the hold's release kind (the explicit operator action a 'manual' hold waits for). Defaults to the current task. Returns the destination column, or a rejection reason when the task is not held or the destination is full. Pass force:true to start execution even when planning or plan review is still outstanding (that waives the plan gate and cancels the pending replan; capacity still applies).",
|
|
171353
171469
|
parameters: taskPromoteParams,
|
|
171354
171470
|
execute: async (_id, params) => {
|
|
171355
171471
|
const taskId = params.task_id?.trim() || currentTaskId;
|
|
171472
|
+
const force = params.force === true;
|
|
171356
171473
|
try {
|
|
171357
|
-
const outcome = await promoteHeldTask(store, taskId);
|
|
171474
|
+
const outcome = await promoteHeldTask(store, taskId, {}, { force });
|
|
171358
171475
|
if (outcome.released) {
|
|
171476
|
+
const forcedNote = outcome.forcedUnplanned ? " Forced past the outstanding planning/plan review \u2014 the pending replan was cancelled." : "";
|
|
171359
171477
|
return {
|
|
171360
171478
|
content: [{
|
|
171361
171479
|
type: "text",
|
|
171362
|
-
text: `Promoted ${taskId} to column '${outcome.toColumn}'
|
|
171480
|
+
text: `Promoted ${taskId} to column '${outcome.toColumn}'.${forcedNote}`
|
|
171363
171481
|
}],
|
|
171364
|
-
details: {
|
|
171482
|
+
details: {
|
|
171483
|
+
taskId,
|
|
171484
|
+
released: true,
|
|
171485
|
+
toColumn: outcome.toColumn,
|
|
171486
|
+
forcedUnplanned: outcome.forcedUnplanned === true
|
|
171487
|
+
}
|
|
171365
171488
|
};
|
|
171366
171489
|
}
|
|
171490
|
+
const forceHint = outcome.rejection === "unplanned-for-execution" ? " Pass force:true to start execution anyway." : "";
|
|
171367
171491
|
return {
|
|
171368
171492
|
content: [{
|
|
171369
171493
|
type: "text",
|
|
171370
|
-
text: `ERROR: Could not promote ${taskId}: ${outcome.rejection ?? "unknown"}
|
|
171494
|
+
text: `ERROR: Could not promote ${taskId}: ${outcome.rejection ?? "unknown"}.${forceHint}`
|
|
171371
171495
|
}],
|
|
171372
171496
|
details: { taskId, released: false, rejection: outcome.rejection },
|
|
171373
171497
|
isError: true
|
|
@@ -173591,6 +173715,7 @@ var init_agent_tools = __esm({
|
|
|
173591
173715
|
init_provider_registry();
|
|
173592
173716
|
init_research_step_runner();
|
|
173593
173717
|
init_logger3();
|
|
173718
|
+
init_plan_artifact_writeback();
|
|
173594
173719
|
init_web_fetch();
|
|
173595
173720
|
init_agent_action_gate();
|
|
173596
173721
|
init_message_delivery();
|
|
@@ -173770,6 +173895,19 @@ var init_agent_tools = __esm({
|
|
|
173770
173895
|
taskPromoteParams = Type2.Object({
|
|
173771
173896
|
task_id: Type2.Optional(
|
|
173772
173897
|
Type2.String({ description: "Held task to promote. Defaults to the current task." })
|
|
173898
|
+
),
|
|
173899
|
+
/*
|
|
173900
|
+
FNXC:WorkflowScheduling 2026-07-25-05:40:
|
|
173901
|
+
Agent-native parity with the dashboard's force-promote override: an agent that
|
|
173902
|
+
has read the card and judged the pending replan / Plan Review not worth waiting
|
|
173903
|
+
for can start execution anyway. Opt-in per call and never defaulted on — the
|
|
173904
|
+
automatic surfaces (hold-release sweep, webhook release) still cannot force, so
|
|
173905
|
+
FN-7648 holds for everything that is not an explicit promote request.
|
|
173906
|
+
*/
|
|
173907
|
+
force: Type2.Optional(
|
|
173908
|
+
Type2.Boolean({
|
|
173909
|
+
description: "Start execution even when the task is still waiting on planning or plan review (rejection 'unplanned-for-execution'). Waives ONLY that gate \u2014 hold membership and downstream capacity still apply \u2014 and cancels the pending replan. Default false."
|
|
173910
|
+
})
|
|
173773
173911
|
)
|
|
173774
173912
|
});
|
|
173775
173913
|
workflowCreateParams = Type2.Object({
|
|
@@ -178078,7 +178216,7 @@ Follow instructions precisely and avoid unrelated changes.`,
|
|
|
178078
178216
|
|
|
178079
178217
|
// ../engine/src/spec-validation/task-document-references.ts
|
|
178080
178218
|
import { access as access7 } from "node:fs/promises";
|
|
178081
|
-
import { join as
|
|
178219
|
+
import { join as join66 } from "node:path";
|
|
178082
178220
|
function normalizePathToken(token) {
|
|
178083
178221
|
return token.replace(/^[`([{"']+/, "").replace(/[`),.;:!?\]}'"]+$/, "");
|
|
178084
178222
|
}
|
|
@@ -178166,7 +178304,7 @@ async function detectDanglingTaskDocReferences(promptContent, opts) {
|
|
|
178166
178304
|
}
|
|
178167
178305
|
const dangling = [];
|
|
178168
178306
|
for (const [path14, sections] of references.entries()) {
|
|
178169
|
-
const absPath =
|
|
178307
|
+
const absPath = join66(opts.rootDir, path14);
|
|
178170
178308
|
if (await existsImpl(absPath)) continue;
|
|
178171
178309
|
dangling.push({ path: path14, sections: Array.from(sections).sort() });
|
|
178172
178310
|
}
|
|
@@ -178427,8 +178565,8 @@ var init_session_skill_context = __esm({
|
|
|
178427
178565
|
});
|
|
178428
178566
|
|
|
178429
178567
|
// ../engine/src/agent-memory-index.ts
|
|
178430
|
-
import { readFile as
|
|
178431
|
-
import { join as
|
|
178568
|
+
import { readFile as readFile33 } from "node:fs/promises";
|
|
178569
|
+
import { join as join67 } from "node:path";
|
|
178432
178570
|
function clampUtf8(input, maxBytes) {
|
|
178433
178571
|
if (Buffer.byteLength(input, "utf8") <= maxBytes) return input;
|
|
178434
178572
|
let out = "";
|
|
@@ -178460,7 +178598,7 @@ function parseHeadings(content) {
|
|
|
178460
178598
|
}
|
|
178461
178599
|
async function buildFileSection(sectionHeader, displayPath, fsPath) {
|
|
178462
178600
|
try {
|
|
178463
|
-
const content = await
|
|
178601
|
+
const content = await readFile33(fsPath, "utf-8");
|
|
178464
178602
|
const headings = parseHeadings(content);
|
|
178465
178603
|
const lines = [sectionHeader, `- ${displayPath}`];
|
|
178466
178604
|
for (const entry of headings) {
|
|
@@ -178476,9 +178614,9 @@ async function buildFileSection(sectionHeader, displayPath, fsPath) {
|
|
|
178476
178614
|
async function buildMemoryIndex({ rootDir, agentId }) {
|
|
178477
178615
|
const safeAgentId = agentId.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
|
|
178478
178616
|
const agentDisplayPath = `.fusion/agent-memory/${safeAgentId}/MEMORY.md`;
|
|
178479
|
-
const agentFsPath =
|
|
178617
|
+
const agentFsPath = join67(rootDir, ".fusion", "agent-memory", safeAgentId, "MEMORY.md");
|
|
178480
178618
|
const projectDisplayPath = ".fusion/memory/MEMORY.md";
|
|
178481
|
-
const projectFsPath =
|
|
178619
|
+
const projectFsPath = join67(rootDir, ".fusion", "memory", "MEMORY.md");
|
|
178482
178620
|
const [agentSection, projectSection] = await Promise.all([
|
|
178483
178621
|
buildFileSection("## Agent Memory Index (use fn_memory_search / fn_memory_get to read)", agentDisplayPath, agentFsPath),
|
|
178484
178622
|
buildFileSection("## Project Memory Index", projectDisplayPath, projectFsPath)
|
|
@@ -178497,7 +178635,7 @@ var init_agent_memory_index = __esm({
|
|
|
178497
178635
|
});
|
|
178498
178636
|
|
|
178499
178637
|
// ../engine/src/agent-instructions.ts
|
|
178500
|
-
import { readFile as
|
|
178638
|
+
import { readFile as readFile34, writeFile as writeFile26, mkdir as mkdir27, access as access8 } from "node:fs/promises";
|
|
178501
178639
|
import { constants as fsConstants3 } from "node:fs";
|
|
178502
178640
|
import { isAbsolute as isAbsolute13, resolve as resolve33, relative as relative12, normalize as normalize7, sep as sep10, dirname as dirname28 } from "node:path";
|
|
178503
178641
|
function trimAndClamp(value, maxLength, label, agentId) {
|
|
@@ -178559,7 +178697,7 @@ async function resolveAgentHeartbeatProcedure(agent, rootDir) {
|
|
|
178559
178697
|
return null;
|
|
178560
178698
|
}
|
|
178561
178699
|
try {
|
|
178562
|
-
const content = await
|
|
178700
|
+
const content = await readFile34(filePath, "utf-8");
|
|
178563
178701
|
const normalized = trimAndClamp(
|
|
178564
178702
|
content,
|
|
178565
178703
|
MAX_INSTRUCTIONS_TEXT_LENGTH2,
|
|
@@ -178705,7 +178843,7 @@ async function resolveAgentInstructions(agent, rootDir, ratingSummary, inclusion
|
|
|
178705
178843
|
const filePath = resolveValidatedInstructionsPath(agent.instructionsPath, rootDir, agent.id);
|
|
178706
178844
|
if (filePath) {
|
|
178707
178845
|
try {
|
|
178708
|
-
const content = await
|
|
178846
|
+
const content = await readFile34(filePath, "utf-8");
|
|
178709
178847
|
const normalizedContent = trimAndClamp(
|
|
178710
178848
|
content,
|
|
178711
178849
|
MAX_INSTRUCTIONS_TEXT_LENGTH2,
|
|
@@ -186712,8 +186850,8 @@ var init_mission_symbol_admission = __esm({
|
|
|
186712
186850
|
|
|
186713
186851
|
// ../engine/src/scheduler.ts
|
|
186714
186852
|
import { existsSync as existsSync54 } from "node:fs";
|
|
186715
|
-
import { readFile as
|
|
186716
|
-
import { join as
|
|
186853
|
+
import { readFile as readFile35 } from "node:fs/promises";
|
|
186854
|
+
import { join as join68 } from "node:path";
|
|
186717
186855
|
function logTaskRouting(taskId, node) {
|
|
186718
186856
|
const message = `Task ${taskId} routed to node=${node.nodeId ?? "local"} (source=${node.source})`;
|
|
186719
186857
|
if (node.nodeId === void 0) {
|
|
@@ -187346,16 +187484,16 @@ var init_scheduler = __esm({
|
|
|
187346
187484
|
if (typeof this.store.getTasksDir !== "function") {
|
|
187347
187485
|
return { valid: true };
|
|
187348
187486
|
}
|
|
187349
|
-
const taskDir =
|
|
187487
|
+
const taskDir = join68(this.store.getTasksDir(), id);
|
|
187350
187488
|
if (!existsSync54(taskDir)) {
|
|
187351
187489
|
return { valid: false, reason: "missing directory" };
|
|
187352
187490
|
}
|
|
187353
|
-
const promptPath =
|
|
187491
|
+
const promptPath = join68(taskDir, "PROMPT.md");
|
|
187354
187492
|
if (!existsSync54(promptPath)) {
|
|
187355
187493
|
return { valid: false, reason: "missing or empty PROMPT.md" };
|
|
187356
187494
|
}
|
|
187357
187495
|
try {
|
|
187358
|
-
const content = await
|
|
187496
|
+
const content = await readFile35(promptPath, "utf-8");
|
|
187359
187497
|
if (!content || content.trim().length === 0) {
|
|
187360
187498
|
return { valid: false, reason: "missing or empty PROMPT.md" };
|
|
187361
187499
|
}
|
|
@@ -187725,7 +187863,7 @@ var init_scheduler = __esm({
|
|
|
187725
187863
|
todo = (await Promise.all(
|
|
187726
187864
|
todo.map(async (t) => {
|
|
187727
187865
|
try {
|
|
187728
|
-
const content = await
|
|
187866
|
+
const content = await readFile35(getPromptPath(this.store.getTasksDir(), t.id), "utf-8");
|
|
187729
187867
|
if (isUnplannedSeedPrompt(content, t.id, t.title, t.description)) return null;
|
|
187730
187868
|
} catch {
|
|
187731
187869
|
}
|
|
@@ -191292,10 +191430,10 @@ var init_verification_utils = __esm({
|
|
|
191292
191430
|
import { exec as exec23 } from "node:child_process";
|
|
191293
191431
|
import { createHash as createHash18 } from "node:crypto";
|
|
191294
191432
|
import { existsSync as existsSync55, readFileSync as readFileSync18, writeFileSync as writeFileSync7 } from "node:fs";
|
|
191295
|
-
import { join as
|
|
191433
|
+
import { join as join69 } from "node:path";
|
|
191296
191434
|
import { promisify as promisify32 } from "node:util";
|
|
191297
191435
|
function hasInstallState(rootDir) {
|
|
191298
|
-
return existsSync55(
|
|
191436
|
+
return existsSync55(join69(rootDir, "node_modules")) || existsSync55(join69(rootDir, ".pnp.cjs"));
|
|
191299
191437
|
}
|
|
191300
191438
|
function getConfiguredWorktreeInitCommand(settings) {
|
|
191301
191439
|
const trimmed = settings?.worktreeInitCommand?.trim();
|
|
@@ -191304,17 +191442,17 @@ function getConfiguredWorktreeInitCommand(settings) {
|
|
|
191304
191442
|
function getDependencySyncCommand(rootDir, settings) {
|
|
191305
191443
|
const configuredCommand = getConfiguredWorktreeInitCommand(settings);
|
|
191306
191444
|
if (configuredCommand) return configuredCommand;
|
|
191307
|
-
if (existsSync55(
|
|
191308
|
-
if (existsSync55(
|
|
191309
|
-
if (existsSync55(
|
|
191310
|
-
if (existsSync55(
|
|
191445
|
+
if (existsSync55(join69(rootDir, "pnpm-lock.yaml"))) return "pnpm install --frozen-lockfile";
|
|
191446
|
+
if (existsSync55(join69(rootDir, "package-lock.json"))) return "npm install";
|
|
191447
|
+
if (existsSync55(join69(rootDir, "yarn.lock"))) return "yarn install --frozen-lockfile";
|
|
191448
|
+
if (existsSync55(join69(rootDir, "bun.lock")) || existsSync55(join69(rootDir, "bun.lockb"))) {
|
|
191311
191449
|
return "bun install --frozen-lockfile";
|
|
191312
191450
|
}
|
|
191313
191451
|
return null;
|
|
191314
191452
|
}
|
|
191315
191453
|
function computeLockfileHash(rootDir) {
|
|
191316
191454
|
for (const name2 of LOCKFILE_CANDIDATES) {
|
|
191317
|
-
const p2 =
|
|
191455
|
+
const p2 = join69(rootDir, name2);
|
|
191318
191456
|
if (existsSync55(p2)) {
|
|
191319
191457
|
try {
|
|
191320
191458
|
return createHash18("sha256").update(readFileSync18(p2)).digest("hex");
|
|
@@ -191327,7 +191465,7 @@ function computeLockfileHash(rootDir) {
|
|
|
191327
191465
|
}
|
|
191328
191466
|
function readInstallMarker(rootDir) {
|
|
191329
191467
|
try {
|
|
191330
|
-
const value = readFileSync18(
|
|
191468
|
+
const value = readFileSync18(join69(rootDir, INSTALL_MARKER_RELPATH), "utf-8").trim();
|
|
191331
191469
|
return value || null;
|
|
191332
191470
|
} catch {
|
|
191333
191471
|
return null;
|
|
@@ -191335,7 +191473,7 @@ function readInstallMarker(rootDir) {
|
|
|
191335
191473
|
}
|
|
191336
191474
|
function writeInstallMarker(rootDir, hash) {
|
|
191337
191475
|
try {
|
|
191338
|
-
writeFileSync7(
|
|
191476
|
+
writeFileSync7(join69(rootDir, INSTALL_MARKER_RELPATH), hash);
|
|
191339
191477
|
} catch {
|
|
191340
191478
|
}
|
|
191341
191479
|
}
|
|
@@ -191426,7 +191564,7 @@ var init_merge_dependency_sync = __esm({
|
|
|
191426
191564
|
"../engine/src/merge-dependency-sync.ts"() {
|
|
191427
191565
|
"use strict";
|
|
191428
191566
|
execAsync21 = promisify32(exec23);
|
|
191429
|
-
INSTALL_MARKER_RELPATH =
|
|
191567
|
+
INSTALL_MARKER_RELPATH = join69("node_modules", ".fusion-install-marker");
|
|
191430
191568
|
LOCKFILE_CANDIDATES = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb", "bun.lock"];
|
|
191431
191569
|
INSTALL_TIMEOUT_MS = 3e5;
|
|
191432
191570
|
}
|
|
@@ -191803,7 +191941,7 @@ var init_merger_glob = __esm({
|
|
|
191803
191941
|
|
|
191804
191942
|
// ../engine/src/merger-workspace-test-commands.ts
|
|
191805
191943
|
import { existsSync as existsSync56, readdirSync as readdirSync9, readFileSync as readFileSync19 } from "node:fs";
|
|
191806
|
-
import { basename as basename18, dirname as dirname31, join as
|
|
191944
|
+
import { basename as basename18, dirname as dirname31, join as join70 } from "node:path";
|
|
191807
191945
|
import { execSync as execSync4 } from "node:child_process";
|
|
191808
191946
|
function quoteArg2(value) {
|
|
191809
191947
|
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
@@ -191834,14 +191972,14 @@ function resolveWorkspacePackageRoots(rootDir, globs) {
|
|
|
191834
191972
|
for (const glob2 of globs) {
|
|
191835
191973
|
const starIdx = glob2.indexOf("*");
|
|
191836
191974
|
if (starIdx === -1) {
|
|
191837
|
-
const candidate =
|
|
191838
|
-
if (existsSync56(
|
|
191975
|
+
const candidate = join70(rootDir, glob2);
|
|
191976
|
+
if (existsSync56(join70(candidate, "package.json"))) {
|
|
191839
191977
|
roots.push(glob2);
|
|
191840
191978
|
}
|
|
191841
191979
|
continue;
|
|
191842
191980
|
}
|
|
191843
191981
|
const prefix = glob2.slice(0, starIdx);
|
|
191844
|
-
const parentDir =
|
|
191982
|
+
const parentDir = join70(rootDir, prefix.replace(/\/$/, ""));
|
|
191845
191983
|
let entries;
|
|
191846
191984
|
try {
|
|
191847
191985
|
entries = readdirSync9(parentDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -191850,8 +191988,8 @@ function resolveWorkspacePackageRoots(rootDir, globs) {
|
|
|
191850
191988
|
}
|
|
191851
191989
|
for (const entry of entries) {
|
|
191852
191990
|
const relPath = `${prefix.replace(/\/$/, "")}/${entry}`;
|
|
191853
|
-
const absPath =
|
|
191854
|
-
if (existsSync56(
|
|
191991
|
+
const absPath = join70(rootDir, relPath);
|
|
191992
|
+
if (existsSync56(join70(absPath, "package.json"))) {
|
|
191855
191993
|
roots.push(relPath);
|
|
191856
191994
|
}
|
|
191857
191995
|
}
|
|
@@ -191874,7 +192012,7 @@ function mapChangedFilesToPackageNames(changedFiles, packageRoots, rootDir) {
|
|
|
191874
192012
|
}
|
|
191875
192013
|
if (bestRoot !== null) {
|
|
191876
192014
|
try {
|
|
191877
|
-
const pkgJsonPath =
|
|
192015
|
+
const pkgJsonPath = join70(rootDir, bestRoot, "package.json");
|
|
191878
192016
|
const raw = readFileSync19(pkgJsonPath, "utf-8");
|
|
191879
192017
|
const parsed = JSON.parse(raw);
|
|
191880
192018
|
if (parsed.name) {
|
|
@@ -191891,7 +192029,7 @@ function packageNamesForFiles(rootDir, files) {
|
|
|
191891
192029
|
if (files.length === 0) return [];
|
|
191892
192030
|
let workspaceContent;
|
|
191893
192031
|
try {
|
|
191894
|
-
workspaceContent = readFileSync19(
|
|
192032
|
+
workspaceContent = readFileSync19(join70(rootDir, "pnpm-workspace.yaml"), "utf-8");
|
|
191895
192033
|
} catch {
|
|
191896
192034
|
return [];
|
|
191897
192035
|
}
|
|
@@ -191902,7 +192040,7 @@ function packageNamesForFiles(rootDir, files) {
|
|
|
191902
192040
|
return mapChangedFilesToPackageNames(files, packageRoots, rootDir);
|
|
191903
192041
|
}
|
|
191904
192042
|
function deriveScopedPnpmTestCommand(rootDir, baseBranch, branch) {
|
|
191905
|
-
const workspacePath =
|
|
192043
|
+
const workspacePath = join70(rootDir, "pnpm-workspace.yaml");
|
|
191906
192044
|
let workspaceContent;
|
|
191907
192045
|
try {
|
|
191908
192046
|
workspaceContent = readFileSync19(workspacePath, "utf-8");
|
|
@@ -191940,7 +192078,7 @@ function deriveScopedPnpmTestCommand(rootDir, baseBranch, branch) {
|
|
|
191940
192078
|
function deriveFileScopedPnpmTestCommand(rootDir, baseBranch, branch) {
|
|
191941
192079
|
let workspaceContent;
|
|
191942
192080
|
try {
|
|
191943
|
-
workspaceContent = readFileSync19(
|
|
192081
|
+
workspaceContent = readFileSync19(join70(rootDir, "pnpm-workspace.yaml"), "utf-8");
|
|
191944
192082
|
} catch {
|
|
191945
192083
|
return null;
|
|
191946
192084
|
}
|
|
@@ -191982,7 +192120,7 @@ function deriveFileScopedPnpmTestCommand(rootDir, baseBranch, branch) {
|
|
|
191982
192120
|
];
|
|
191983
192121
|
for (const candidate of candidates) {
|
|
191984
192122
|
const normalized = candidate.startsWith("./") ? candidate.slice(2) : candidate;
|
|
191985
|
-
if (existsSync56(
|
|
192123
|
+
if (existsSync56(join70(rootDir, normalized))) {
|
|
191986
192124
|
resolvedTests.add(normalized);
|
|
191987
192125
|
}
|
|
191988
192126
|
}
|
|
@@ -192010,7 +192148,7 @@ function deriveFileScopedPnpmTestCommand(rootDir, baseBranch, branch) {
|
|
|
192010
192148
|
let name2 = bestRoot;
|
|
192011
192149
|
try {
|
|
192012
192150
|
const parsed = JSON.parse(
|
|
192013
|
-
readFileSync19(
|
|
192151
|
+
readFileSync19(join70(rootDir, bestRoot, "package.json"), "utf-8")
|
|
192014
192152
|
);
|
|
192015
192153
|
if (parsed.name) name2 = parsed.name;
|
|
192016
192154
|
} catch {
|
|
@@ -192054,8 +192192,8 @@ function inferDefaultTestCommand(rootDir, explicitTestCommand, explicitBuildComm
|
|
|
192054
192192
|
};
|
|
192055
192193
|
}
|
|
192056
192194
|
const buildSource = explicitBuildCommand?.trim() ? "explicit" : void 0;
|
|
192057
|
-
if (existsSync56(
|
|
192058
|
-
if (existsSync56(
|
|
192195
|
+
if (existsSync56(join70(rootDir, "pnpm-lock.yaml"))) {
|
|
192196
|
+
if (existsSync56(join70(rootDir, "pnpm-workspace.yaml"))) {
|
|
192059
192197
|
if (baseBranch?.trim() && branch?.trim()) {
|
|
192060
192198
|
try {
|
|
192061
192199
|
const scoped = deriveScopedPnpmTestCommand(rootDir, baseBranch.trim(), branch.trim());
|
|
@@ -192074,13 +192212,13 @@ function inferDefaultTestCommand(rootDir, explicitTestCommand, explicitBuildComm
|
|
|
192074
192212
|
}
|
|
192075
192213
|
return { command: "pnpm test", testSource: "inferred", buildSource };
|
|
192076
192214
|
}
|
|
192077
|
-
if (existsSync56(
|
|
192215
|
+
if (existsSync56(join70(rootDir, "yarn.lock"))) {
|
|
192078
192216
|
return { command: "yarn test", testSource: "inferred", buildSource };
|
|
192079
192217
|
}
|
|
192080
|
-
if (existsSync56(
|
|
192218
|
+
if (existsSync56(join70(rootDir, "bun.lock")) || existsSync56(join70(rootDir, "bun.lockb"))) {
|
|
192081
192219
|
return { command: "bun test", testSource: "inferred", buildSource };
|
|
192082
192220
|
}
|
|
192083
|
-
if (existsSync56(
|
|
192221
|
+
if (existsSync56(join70(rootDir, "package-lock.json"))) {
|
|
192084
192222
|
return { command: "npm test", testSource: "inferred", buildSource };
|
|
192085
192223
|
}
|
|
192086
192224
|
return null;
|
|
@@ -194357,7 +194495,7 @@ var init_merger_integration_worktree = __esm({
|
|
|
194357
194495
|
import { execFile as execFile23, spawn as spawn7 } from "node:child_process";
|
|
194358
194496
|
import { promisify as promisify43 } from "node:util";
|
|
194359
194497
|
import { copyFileSync, existsSync as existsSync57, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, readFileSync as readFileSync20, rmSync as rmSync7, writeFileSync as writeFileSync8 } from "node:fs";
|
|
194360
|
-
import { dirname as dirname32, join as
|
|
194498
|
+
import { dirname as dirname32, join as join71 } from "node:path";
|
|
194361
194499
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
194362
194500
|
async function runGit4(args, cwd, timeoutMs) {
|
|
194363
194501
|
const result2 = await execFileAsync16("git", ["-c", "core.quotePath=false", ...args], {
|
|
@@ -194443,9 +194581,9 @@ async function syncWorktreeToHead(input) {
|
|
|
194443
194581
|
if (mode === "ff-only") {
|
|
194444
194582
|
return { kind: "skipped-dirty", fromSha: previousSha, reason: "ff-only-mode-requires-clean-tree", dirtyFiles, untrackedFiles };
|
|
194445
194583
|
}
|
|
194446
|
-
const stageDir = mkdtempSync2(
|
|
194447
|
-
const patchPath =
|
|
194448
|
-
const untrackedDir =
|
|
194584
|
+
const stageDir = mkdtempSync2(join71(tmpdir6(), "fusion-worktree-sync-"));
|
|
194585
|
+
const patchPath = join71(stageDir, "edits.patch");
|
|
194586
|
+
const untrackedDir = join71(stageDir, "untracked");
|
|
194449
194587
|
let preserveStageDir = false;
|
|
194450
194588
|
try {
|
|
194451
194589
|
mkdirSync9(untrackedDir, { recursive: true });
|
|
@@ -194465,8 +194603,8 @@ async function syncWorktreeToHead(input) {
|
|
|
194465
194603
|
}
|
|
194466
194604
|
}
|
|
194467
194605
|
for (const rel of untrackedFiles) {
|
|
194468
|
-
const src =
|
|
194469
|
-
const dst =
|
|
194606
|
+
const src = join71(worktreePath, rel);
|
|
194607
|
+
const dst = join71(untrackedDir, rel);
|
|
194470
194608
|
try {
|
|
194471
194609
|
mkdirSync9(dirname32(dst), { recursive: true });
|
|
194472
194610
|
copyFileSync(src, dst);
|
|
@@ -194529,13 +194667,13 @@ async function syncWorktreeToHead(input) {
|
|
|
194529
194667
|
const restored = [];
|
|
194530
194668
|
const untrackedSkippedAsTracked = [];
|
|
194531
194669
|
for (const rel of untrackedFiles) {
|
|
194532
|
-
const src =
|
|
194670
|
+
const src = join71(untrackedDir, rel);
|
|
194533
194671
|
if (!existsSync57(src)) continue;
|
|
194534
194672
|
if (trackedAtHead.has(rel)) {
|
|
194535
194673
|
untrackedSkippedAsTracked.push(rel);
|
|
194536
194674
|
continue;
|
|
194537
194675
|
}
|
|
194538
|
-
const dst =
|
|
194676
|
+
const dst = join71(worktreePath, rel);
|
|
194539
194677
|
try {
|
|
194540
194678
|
mkdirSync9(dirname32(dst), { recursive: true });
|
|
194541
194679
|
const data = readFileSync20(src);
|
|
@@ -194604,8 +194742,8 @@ var init_worktree_ref_sync = __esm({
|
|
|
194604
194742
|
|
|
194605
194743
|
// ../engine/src/merger-scope-auto-widen.ts
|
|
194606
194744
|
import { exec as exec30 } from "node:child_process";
|
|
194607
|
-
import { readFile as
|
|
194608
|
-
import { join as
|
|
194745
|
+
import { readFile as readFile36, writeFile as writeFile27 } from "node:fs/promises";
|
|
194746
|
+
import { join as join72 } from "node:path";
|
|
194609
194747
|
import { promisify as promisify44 } from "node:util";
|
|
194610
194748
|
function quoteArg4(value) {
|
|
194611
194749
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -194744,8 +194882,8 @@ function parseScopeEntries(section) {
|
|
|
194744
194882
|
async function appendAutoWidenedScopeToPrompt(params) {
|
|
194745
194883
|
const { store, taskId, files } = params;
|
|
194746
194884
|
if (files.length === 0) return [];
|
|
194747
|
-
const promptPath =
|
|
194748
|
-
const prompt = await
|
|
194885
|
+
const promptPath = join72(store.getTaskDir(taskId), "PROMPT.md");
|
|
194886
|
+
const prompt = await readFile36(promptPath, "utf-8");
|
|
194749
194887
|
const { before, section, after } = splitPromptSections(prompt);
|
|
194750
194888
|
const existing = parseScopeEntries(section);
|
|
194751
194889
|
const toAdd = files.filter((file) => !existing.has(file));
|
|
@@ -194901,7 +195039,7 @@ import * as childProcess4 from "node:child_process";
|
|
|
194901
195039
|
import { promisify as promisify45 } from "node:util";
|
|
194902
195040
|
import { existsSync as existsSync58, readFileSync as readFileSync21, writeFileSync as writeFileSync9, unlinkSync as unlinkSync3, renameSync as renameSync5 } from "node:fs";
|
|
194903
195041
|
import { createHash as createHash20 } from "node:crypto";
|
|
194904
|
-
import { join as
|
|
195042
|
+
import { join as join73, resolve as resolve36 } from "node:path";
|
|
194905
195043
|
import { hostname as hostname2 } from "node:os";
|
|
194906
195044
|
import { Type as Type4 } from "typebox";
|
|
194907
195045
|
function mergerCommitEnv() {
|
|
@@ -195214,7 +195352,7 @@ async function runDeterministicVerification(store, rootDir, taskId, testCommand,
|
|
|
195214
195352
|
const deterministicVerificationMessage = "Running deterministic merge verification" + (hasTestCommand ? ` (test${testSourceDisplayLabel}: ${normalizedTestCommand})` : "") + (hasBuildCommand ? ` (build${buildSource === "inferred" ? " [inferred]" : ""}: ${normalizedBuildCommand})` : "");
|
|
195215
195353
|
await store.logEntry(taskId, deterministicVerificationMessage);
|
|
195216
195354
|
await store.appendAgentLog(taskId, deterministicVerificationMessage, "status", void 0, "merger");
|
|
195217
|
-
const bootstrapScriptPath =
|
|
195355
|
+
const bootstrapScriptPath = join73(rootDir, "scripts/ensure-test-artifacts.mjs");
|
|
195218
195356
|
if (hasTestCommand || hasBuildCommand) {
|
|
195219
195357
|
if (!existsSync58(bootstrapScriptPath)) {
|
|
195220
195358
|
const bootstrapMissingMessage = `${taskId}: [verification:bootstrap] script missing at scripts/ensure-test-artifacts.mjs \u2014 skipping preamble`;
|
|
@@ -195713,7 +195851,7 @@ async function stashTreesEqual(rootDir, aSha, bSha) {
|
|
|
195713
195851
|
}
|
|
195714
195852
|
function writeActiveMergerStatus(rootDir, taskId) {
|
|
195715
195853
|
try {
|
|
195716
|
-
const statusPath =
|
|
195854
|
+
const statusPath = join73(rootDir, ".git", ACTIVE_MERGER_STATUS_FILENAME);
|
|
195717
195855
|
const payload = {
|
|
195718
195856
|
taskId,
|
|
195719
195857
|
pid: process.pid,
|
|
@@ -195742,7 +195880,7 @@ function clearActiveMergerStatus(statusPath, taskId) {
|
|
|
195742
195880
|
}
|
|
195743
195881
|
function readActiveMergerStatus(rootDir) {
|
|
195744
195882
|
try {
|
|
195745
|
-
const statusPath =
|
|
195883
|
+
const statusPath = join73(rootDir, ".git", ACTIVE_MERGER_STATUS_FILENAME);
|
|
195746
195884
|
if (!existsSync58(statusPath)) return null;
|
|
195747
195885
|
const raw = readFileSync21(statusPath, "utf-8");
|
|
195748
195886
|
const parsed = JSON.parse(raw);
|
|
@@ -196315,7 +196453,7 @@ async function findFilesWithConflictMarkers(rootDir, files) {
|
|
|
196315
196453
|
const stillConflicted = [];
|
|
196316
196454
|
for (const file of files) {
|
|
196317
196455
|
try {
|
|
196318
|
-
const fullPath =
|
|
196456
|
+
const fullPath = join73(rootDir, file);
|
|
196319
196457
|
if (!existsSync58(fullPath)) continue;
|
|
196320
196458
|
const { stdout } = await execAsync29(
|
|
196321
196459
|
`git grep -l -e "^<<<<<<< " -e "^=======$" -e "^>>>>>>> " --no-index -- ${quoteArg3(fullPath)}`,
|
|
@@ -196342,7 +196480,7 @@ async function tryRecoverHardFailApply(params) {
|
|
|
196342
196480
|
if (!patchText.trim()) {
|
|
196343
196481
|
mergerLog.warn(`${taskId}: autostash ${sha.slice(0, 7)} produced empty patch; cannot 3-way recover`);
|
|
196344
196482
|
} else {
|
|
196345
|
-
const patchPath =
|
|
196483
|
+
const patchPath = join73(rootDir, ".git", `fusion-autostash-${sha.slice(0, 7)}.patch`);
|
|
196346
196484
|
writeFileSync9(patchPath, patchText, "utf-8");
|
|
196347
196485
|
try {
|
|
196348
196486
|
await execAsync29(`git apply --3way --whitespace=nowarn ${quoteArg3(patchPath)}`, { cwd: rootDir });
|
|
@@ -197830,13 +197968,13 @@ async function isCherryPickInProgress(rootDir) {
|
|
|
197830
197968
|
cwd: rootDir,
|
|
197831
197969
|
encoding: "utf-8"
|
|
197832
197970
|
});
|
|
197833
|
-
const cherryPickHeadPath =
|
|
197971
|
+
const cherryPickHeadPath = join73(rootDir, cherryPickHeadPathOut.trim());
|
|
197834
197972
|
if (existsSync58(cherryPickHeadPath)) return true;
|
|
197835
197973
|
const { stdout: sequencerPathOut } = await execAsync29("git rev-parse --git-path sequencer", {
|
|
197836
197974
|
cwd: rootDir,
|
|
197837
197975
|
encoding: "utf-8"
|
|
197838
197976
|
});
|
|
197839
|
-
const sequencerPath =
|
|
197977
|
+
const sequencerPath = join73(rootDir, sequencerPathOut.trim());
|
|
197840
197978
|
return existsSync58(sequencerPath);
|
|
197841
197979
|
} catch {
|
|
197842
197980
|
return false;
|
|
@@ -202879,7 +203017,7 @@ import { promisify as promisify46 } from "node:util";
|
|
|
202879
203017
|
import { setImmediate as setImmediateCb2 } from "node:timers";
|
|
202880
203018
|
import { existsSync as existsSync59, mkdirSync as mkdirSync10, readdirSync as readdirSync10, readFileSync as readFileSync22, realpathSync as realpathSync7, rmSync as rmSync8, statSync as statSync10, writeFileSync as writeFileSync10 } from "node:fs";
|
|
202881
203019
|
import { tmpdir as tmpdir7 } from "node:os";
|
|
202882
|
-
import { isAbsolute as isAbsolute14, join as
|
|
203020
|
+
import { isAbsolute as isAbsolute14, join as join74, relative as relative13, resolve as resolve37 } from "node:path";
|
|
202883
203021
|
function resolveRepoLocalAiMergeRoot(rootDir, settings) {
|
|
202884
203022
|
return resolveAiMergeRootPath(rootDir, settings);
|
|
202885
203023
|
}
|
|
@@ -202912,9 +203050,9 @@ async function preserveWorktreeChanges(repoDir, worktreePath, taskId) {
|
|
|
202912
203050
|
return null;
|
|
202913
203051
|
}
|
|
202914
203052
|
const diff = (await execAsync30("git diff HEAD --binary", { cwd: worktreePath, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 })).stdout;
|
|
202915
|
-
const recoveryDir =
|
|
203053
|
+
const recoveryDir = join74(repoDir, ".fusion", "recovery");
|
|
202916
203054
|
mkdirSync10(recoveryDir, { recursive: true });
|
|
202917
|
-
const patchPath =
|
|
203055
|
+
const patchPath = join74(recoveryDir, `${taskId.toLowerCase()}-${formatRecoveryTimestamp()}.patch`);
|
|
202918
203056
|
writeFileSync10(patchPath, diff, "utf-8");
|
|
202919
203057
|
return patchPath;
|
|
202920
203058
|
} catch (error3) {
|
|
@@ -204347,6 +204485,35 @@ var init_self_healing = __esm({
|
|
|
204347
204485
|
}
|
|
204348
204486
|
return false;
|
|
204349
204487
|
}
|
|
204488
|
+
/**
|
|
204489
|
+
* FNXC:WorkflowRecovery 2026-07-25-09:40:
|
|
204490
|
+
* Single shared decision for "is this branch tip's foreign `Fusion-Task-Id`/`Fusion-Task-Lineage` trailer real
|
|
204491
|
+
* evidence of cross-task contamination, or just an inherited start point?"
|
|
204492
|
+
*
|
|
204493
|
+
* A task branch cut from the integration branch points at whatever landed last. When the task has not committed
|
|
204494
|
+
* anything of its own (planning aborted, spec revise, operator move back to `todo`), the branch tip IS that
|
|
204495
|
+
* previous task's commit — a foreign trailer with zero foreign intent. FN-1406 hit exactly this: `fusion/fn-1406`
|
|
204496
|
+
* was cut from `main` at FN-1401's landed commit, planning ended without a commit, and the reclaim sweep logged
|
|
204497
|
+
* `already-merged rejected ... owner=FN-1401 reason=foreign-task-tip` every pass instead of clearing the stale
|
|
204498
|
+
* worktree/branch metadata.
|
|
204499
|
+
*
|
|
204500
|
+
* Merge-base-to-tip diff proof separates the two: no unique diff means the branch carries no task content, so the
|
|
204501
|
+
* foreign trailer is inherited and the caller may treat the row as stale metadata. The one exception is when the
|
|
204502
|
+
* base ALREADY has an explicit commit for this task — then the branch should have been sitting on the task's own
|
|
204503
|
+
* landed commit, and a foreign tip is genuine misbinding worth rejecting.
|
|
204504
|
+
*
|
|
204505
|
+
* Callers: already-merged recovery (`branchTipForeignOwnership`), branch-misbound recovery
|
|
204506
|
+
* (`isBranchTipMisboundToTask`), and the self-owned-branch reclaim sweep's `tip-already-merged` arm. Keeping the
|
|
204507
|
+
* three on one helper is the point — the reclaim arm drifted without the diff proof and that was the bug.
|
|
204508
|
+
*/
|
|
204509
|
+
async foreignTipRejection(input) {
|
|
204510
|
+
const { taskId, lineageId, branchTip, baseBranch, ownership } = input;
|
|
204511
|
+
if (ownership.rejectionReason !== "foreign-task" && ownership.rejectionReason !== "foreign-lineage") return null;
|
|
204512
|
+
const hasNoUniqueDiff = await this.branchHasNoUniqueDiff(branchTip, baseBranch).catch(() => false);
|
|
204513
|
+
const baseAlreadyHasCurrentTask = hasNoUniqueDiff ? await this.baseHasExplicitTaskOwnership(taskId, lineageId, baseBranch).catch(() => false) : false;
|
|
204514
|
+
if (hasNoUniqueDiff && !baseAlreadyHasCurrentTask) return null;
|
|
204515
|
+
return ownership.rejectionReason === "foreign-task" ? { reason: "foreign-task-tip", owner: ownership.ownerTaskId } : { reason: "foreign-lineage-tip", owner: ownership.ownerLineageId };
|
|
204516
|
+
}
|
|
204350
204517
|
async rejectForeignAlreadyMergedCandidate(input) {
|
|
204351
204518
|
const { task, candidateSha, candidateOwner, taskBranch, baseBranch, reason, phase } = input;
|
|
204352
204519
|
await this.store.logEntry(
|
|
@@ -204388,20 +204555,14 @@ var init_self_healing = __esm({
|
|
|
204388
204555
|
}
|
|
204389
204556
|
const sha = stdout.trim();
|
|
204390
204557
|
if (!sha) return null;
|
|
204391
|
-
const hasNoUniqueDiff = await this.branchHasNoUniqueDiff(sha, baseBranch).catch(() => false);
|
|
204392
204558
|
let ownership;
|
|
204393
204559
|
try {
|
|
204394
204560
|
ownership = await this.readCommitTaskOwnership(sha, taskId, lineageId);
|
|
204395
204561
|
} catch {
|
|
204396
204562
|
return { sha, reason: "ownership-unverifiable" };
|
|
204397
204563
|
}
|
|
204398
|
-
const
|
|
204399
|
-
if (
|
|
204400
|
-
return { sha, owner: ownership.ownerTaskId, reason: "foreign-task-tip" };
|
|
204401
|
-
}
|
|
204402
|
-
if ((!hasNoUniqueDiff || baseAlreadyHasCurrentTask) && ownership.rejectionReason === "foreign-lineage") {
|
|
204403
|
-
return { sha, owner: ownership.ownerLineageId, reason: "foreign-lineage-tip" };
|
|
204404
|
-
}
|
|
204564
|
+
const rejection = await this.foreignTipRejection({ taskId, lineageId, branchTip: sha, baseBranch, ownership });
|
|
204565
|
+
if (rejection) return { sha, owner: rejection.owner, reason: rejection.reason };
|
|
204405
204566
|
return null;
|
|
204406
204567
|
}
|
|
204407
204568
|
async resolveSelfHealingMergeTarget(task, settings, phase) {
|
|
@@ -205617,14 +205778,21 @@ var init_self_healing = __esm({
|
|
|
205617
205778
|
if (!ownership) {
|
|
205618
205779
|
continue;
|
|
205619
205780
|
}
|
|
205620
|
-
|
|
205781
|
+
const foreignRejection = await this.foreignTipRejection({
|
|
205782
|
+
taskId: task.id,
|
|
205783
|
+
lineageId: task.lineageId,
|
|
205784
|
+
branchTip: inspection.tipSha,
|
|
205785
|
+
baseBranch: inspection.integrationRef,
|
|
205786
|
+
ownership
|
|
205787
|
+
});
|
|
205788
|
+
if (foreignRejection) {
|
|
205621
205789
|
await this.rejectForeignAlreadyMergedCandidate({
|
|
205622
205790
|
task,
|
|
205623
205791
|
candidateSha: inspection.tipSha,
|
|
205624
|
-
candidateOwner:
|
|
205792
|
+
candidateOwner: foreignRejection.owner,
|
|
205625
205793
|
taskBranch: branchName,
|
|
205626
205794
|
baseBranch: inspection.integrationRef,
|
|
205627
|
-
reason:
|
|
205795
|
+
reason: foreignRejection.reason,
|
|
205628
205796
|
phase: "tip-already-merged"
|
|
205629
205797
|
});
|
|
205630
205798
|
continue;
|
|
@@ -209564,7 +209732,7 @@ var init_self_healing = __esm({
|
|
|
209564
209732
|
const unrecoverableRepos = [];
|
|
209565
209733
|
for (const repoRel of repoKeys) {
|
|
209566
209734
|
const entry = workspaceWorktrees[repoRel];
|
|
209567
|
-
const repoRootDir =
|
|
209735
|
+
const repoRootDir = join74(this.options.rootDir, repoRel);
|
|
209568
209736
|
let integrationBranch;
|
|
209569
209737
|
try {
|
|
209570
209738
|
integrationBranch = await resolveIntegrationBranch(
|
|
@@ -209858,7 +210026,7 @@ var init_self_healing = __esm({
|
|
|
209858
210026
|
if ((this.orphanWorktreeRemovalFailures.get(worktreePath) ?? 0) >= MAX_STARVATION_DROPS) {
|
|
209859
210027
|
continue;
|
|
209860
210028
|
}
|
|
209861
|
-
const repoRootDir =
|
|
210029
|
+
const repoRootDir = join74(this.options.rootDir, repoRel);
|
|
209862
210030
|
let success = false;
|
|
209863
210031
|
let reason = "removed";
|
|
209864
210032
|
try {
|
|
@@ -210779,7 +210947,7 @@ var init_self_healing = __esm({
|
|
|
210779
210947
|
if (testWorkerRoot) {
|
|
210780
210948
|
try {
|
|
210781
210949
|
for (const entry of readdirSync10(testWorkerRoot)) {
|
|
210782
|
-
if (entry.startsWith("redir-")) roots.push(
|
|
210950
|
+
if (entry.startsWith("redir-")) roots.push(join74(testWorkerRoot, entry));
|
|
210783
210951
|
}
|
|
210784
210952
|
} catch {
|
|
210785
210953
|
}
|
|
@@ -210793,7 +210961,7 @@ var init_self_healing = __esm({
|
|
|
210793
210961
|
} catch {
|
|
210794
210962
|
continue;
|
|
210795
210963
|
}
|
|
210796
|
-
for (const entry of entries) paths2.push(
|
|
210964
|
+
for (const entry of entries) paths2.push(join74(root, entry));
|
|
210797
210965
|
}
|
|
210798
210966
|
return paths2;
|
|
210799
210967
|
}
|
|
@@ -211029,14 +211197,10 @@ var init_self_healing = __esm({
|
|
|
211029
211197
|
maxBuffer: 1024 * 1024
|
|
211030
211198
|
});
|
|
211031
211199
|
const branchTip = tipOut.trim();
|
|
211032
|
-
const hasNoUniqueDiff = await this.branchHasNoUniqueDiff(branchTip, baseBranch).catch(() => false);
|
|
211033
211200
|
const ownership = await this.readCommitTaskOwnership(branchTip, taskId, lineageId);
|
|
211034
|
-
const
|
|
211035
|
-
if (
|
|
211036
|
-
return { misbound: false, branchTip, landed: null, rejection
|
|
211037
|
-
}
|
|
211038
|
-
if ((!hasNoUniqueDiff || baseAlreadyHasCurrentTask) && ownership.rejectionReason === "foreign-lineage") {
|
|
211039
|
-
return { misbound: false, branchTip, landed: null, rejection: { reason: "foreign-lineage-tip", owner: ownership.ownerLineageId } };
|
|
211201
|
+
const rejection = await this.foreignTipRejection({ taskId, lineageId, branchTip, baseBranch, ownership });
|
|
211202
|
+
if (rejection) {
|
|
211203
|
+
return { misbound: false, branchTip, landed: null, rejection };
|
|
211040
211204
|
}
|
|
211041
211205
|
const hasTaskId = ownership.ownerTaskId === taskId;
|
|
211042
211206
|
const hasLineage = lineageId ? ownership.ownerLineageId === lineageId : false;
|
|
@@ -212698,7 +212862,7 @@ var init_self_healing = __esm({
|
|
|
212698
212862
|
let processedMarkers = 0;
|
|
212699
212863
|
for (const task of candidates) {
|
|
212700
212864
|
try {
|
|
212701
|
-
const promptPath =
|
|
212865
|
+
const promptPath = join74(this.options.rootDir, ".fusion", "tasks", task.id, "PROMPT.md");
|
|
212702
212866
|
if (!existsSync59(promptPath)) {
|
|
212703
212867
|
continue;
|
|
212704
212868
|
}
|
|
@@ -213085,7 +213249,7 @@ var init_self_healing = __esm({
|
|
|
213085
213249
|
if (!existsSync59(worktreesDir)) return 0;
|
|
213086
213250
|
let dirs;
|
|
213087
213251
|
try {
|
|
213088
|
-
dirs = readdirSync10(worktreesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) =>
|
|
213252
|
+
dirs = readdirSync10(worktreesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && !isAiMergeContainerDir(e.name)).map((e) => join74(worktreesDir, e.name));
|
|
213089
213253
|
} catch (err) {
|
|
213090
213254
|
log28.warn(`Failed to read .worktrees/ for unregistered orphan reap: ${err instanceof Error ? err.message : String(err)}`);
|
|
213091
213255
|
return 0;
|
|
@@ -213155,7 +213319,7 @@ var init_self_healing = __esm({
|
|
|
213155
213319
|
}
|
|
213156
213320
|
if (entries.length === 0) continue;
|
|
213157
213321
|
for (const entry of entries) {
|
|
213158
|
-
const path14 =
|
|
213322
|
+
const path14 = join74(tempRoot, entry);
|
|
213159
213323
|
let canonicalPath = path14;
|
|
213160
213324
|
let cleanupReason = "stale";
|
|
213161
213325
|
try {
|
|
@@ -213393,8 +213557,8 @@ var init_self_healing = __esm({
|
|
|
213393
213557
|
// ../engine/src/triage.ts
|
|
213394
213558
|
import { Type as Type5 } from "@earendil-works/pi-ai";
|
|
213395
213559
|
import { exec as exec33 } from "node:child_process";
|
|
213396
|
-
import { readFile as
|
|
213397
|
-
import { join as
|
|
213560
|
+
import { readFile as readFile37, writeFile as writeFile28, rm as rm9 } from "node:fs/promises";
|
|
213561
|
+
import { join as join75 } from "node:path";
|
|
213398
213562
|
import { promisify as promisify47 } from "node:util";
|
|
213399
213563
|
function inlineTaskListFallback(lines, opts = {}) {
|
|
213400
213564
|
const maxChars = Math.max(1, Math.floor(opts.maxChars ?? MAX_TASK_LIST_TEXT_CHARS));
|
|
@@ -213445,10 +213609,10 @@ async function readAttachmentContents(rootDir, taskId, attachments) {
|
|
|
213445
213609
|
if (!attachments || attachments.length === 0) {
|
|
213446
213610
|
return { attachmentContents, imageContents };
|
|
213447
213611
|
}
|
|
213448
|
-
const { readFile:
|
|
213449
|
-
const { join:
|
|
213612
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
213613
|
+
const { join: join156 } = await import("node:path");
|
|
213450
213614
|
for (const att of attachments) {
|
|
213451
|
-
const filePath =
|
|
213615
|
+
const filePath = join156(
|
|
213452
213616
|
rootDir,
|
|
213453
213617
|
".fusion",
|
|
213454
213618
|
"tasks",
|
|
@@ -213458,7 +213622,7 @@ async function readAttachmentContents(rootDir, taskId, attachments) {
|
|
|
213458
213622
|
);
|
|
213459
213623
|
try {
|
|
213460
213624
|
if (IMAGE_MIME_TYPES.has(att.mimeType)) {
|
|
213461
|
-
const data = await
|
|
213625
|
+
const data = await readFile64(filePath);
|
|
213462
213626
|
const detectedMimeType = detectImageMimeFromBytes(data);
|
|
213463
213627
|
const imageMimeType2 = detectedMimeType ?? att.mimeType;
|
|
213464
213628
|
if (detectedMimeType && detectedMimeType !== att.mimeType) {
|
|
@@ -213475,7 +213639,7 @@ async function readAttachmentContents(rootDir, taskId, attachments) {
|
|
|
213475
213639
|
text: null
|
|
213476
213640
|
});
|
|
213477
213641
|
} else {
|
|
213478
|
-
const data = await
|
|
213642
|
+
const data = await readFile64(filePath, "utf-8");
|
|
213479
213643
|
const text3 = data.length > TEXT_INLINE_LIMIT ? data.slice(0, TEXT_INLINE_LIMIT) + "\n... (truncated at 50KB)" : data;
|
|
213480
213644
|
attachmentContents.push({
|
|
213481
213645
|
originalName: att.originalName,
|
|
@@ -213716,6 +213880,7 @@ var init_triage = __esm({
|
|
|
213716
213880
|
init_prompt_layers();
|
|
213717
213881
|
init_fallback_model_observer();
|
|
213718
213882
|
init_logger3();
|
|
213883
|
+
init_plan_artifact_writeback();
|
|
213719
213884
|
init_mcp_resolution();
|
|
213720
213885
|
init_usage_limit_detector();
|
|
213721
213886
|
init_transient_error_detector();
|
|
@@ -214272,8 +214437,8 @@ var init_triage = __esm({
|
|
|
214272
214437
|
}
|
|
214273
214438
|
const settings = await mergeEffectiveSettings(this.store, task, await this.store.getSettings());
|
|
214274
214439
|
const approvalRequired = resolvePlanApprovalRequired(settings);
|
|
214275
|
-
const promptPath =
|
|
214276
|
-
const written = await
|
|
214440
|
+
const promptPath = join75(this.rootDir, ".fusion", "tasks", task.id, "PROMPT.md");
|
|
214441
|
+
const written = await readFile37(promptPath, "utf-8").catch((err) => {
|
|
214277
214442
|
const msg = err instanceof Error ? err.message : String(err);
|
|
214278
214443
|
planLog.warn(`${task.id}: failed to read PROMPT.md during planning recovery (${promptPath}): ${msg}`);
|
|
214279
214444
|
return "";
|
|
@@ -214311,8 +214476,8 @@ var init_triage = __esm({
|
|
|
214311
214476
|
return true;
|
|
214312
214477
|
}
|
|
214313
214478
|
async readNonEmptyPromptDraft(taskId, context) {
|
|
214314
|
-
const promptPath =
|
|
214315
|
-
const written = await
|
|
214479
|
+
const promptPath = join75(this.rootDir, ".fusion", "tasks", taskId, "PROMPT.md");
|
|
214480
|
+
const written = await readFile37(promptPath, "utf-8").catch((err) => {
|
|
214316
214481
|
const msg = err instanceof Error ? err.message : String(err);
|
|
214317
214482
|
planLog.warn(`${taskId}: failed to read PROMPT.md during ${context} (${promptPath}): ${msg}`);
|
|
214318
214483
|
return "";
|
|
@@ -214476,8 +214641,8 @@ var init_triage = __esm({
|
|
|
214476
214641
|
continue;
|
|
214477
214642
|
}
|
|
214478
214643
|
try {
|
|
214479
|
-
const promptPath =
|
|
214480
|
-
const content = await
|
|
214644
|
+
const promptPath = join75(this.rootDir, ".fusion", "tasks", todoTask.id, "PROMPT.md");
|
|
214645
|
+
const content = await readFile37(promptPath, "utf-8");
|
|
214481
214646
|
if (isUnplannedSeedPrompt(content, todoTask.id, todoTask.title, todoTask.description)) {
|
|
214482
214647
|
eligibleTodoTasks.push(todoTask);
|
|
214483
214648
|
}
|
|
@@ -214688,7 +214853,7 @@ var init_triage = __esm({
|
|
|
214688
214853
|
const detail = await this.store.getTask(task.id);
|
|
214689
214854
|
const currentTask = detail ?? task;
|
|
214690
214855
|
const settings = await mergeEffectiveSettings(this.store, currentTask, await this.store.getSettings());
|
|
214691
|
-
const promptPath =
|
|
214856
|
+
const promptPath = relativePromptPath(task.id);
|
|
214692
214857
|
const isFast = task.executionMode === "fast";
|
|
214693
214858
|
const leanPlanning = settings.leanPlanning === true || isFast;
|
|
214694
214859
|
const agentWork = async () => {
|
|
@@ -215024,8 +215189,22 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
215024
215189
|
}
|
|
215025
215190
|
return;
|
|
215026
215191
|
}
|
|
215027
|
-
const
|
|
215028
|
-
|
|
215192
|
+
const planPersistence = await persistPlanArtifact({
|
|
215193
|
+
store: this.store,
|
|
215194
|
+
taskId: task.id,
|
|
215195
|
+
rootDir: this.rootDir,
|
|
215196
|
+
planningCwd,
|
|
215197
|
+
author: "triage",
|
|
215198
|
+
logger: { log: (m2) => planLog.log(m2), warn: (m2) => planLog.warn(m2) }
|
|
215199
|
+
});
|
|
215200
|
+
if (planPersistence.outcome === "recovered") {
|
|
215201
|
+
await this.store.logEntry(
|
|
215202
|
+
task.id,
|
|
215203
|
+
"Recovered the plan written inside the task worktree into the project .fusion folder"
|
|
215204
|
+
).catch(() => void 0);
|
|
215205
|
+
}
|
|
215206
|
+
const written = await readFile37(
|
|
215207
|
+
join75(this.rootDir, promptPath),
|
|
215029
215208
|
"utf-8"
|
|
215030
215209
|
).catch((err) => {
|
|
215031
215210
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -215642,7 +215821,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215642
215821
|
if (isNearDuplicateCanonicalInactive(canonicalTask ?? void 0)) {
|
|
215643
215822
|
if (canClearInactiveMarker) {
|
|
215644
215823
|
if (!await this.runIfStillPlanningUnderTaskLock(task, async () => {
|
|
215645
|
-
await rm9(
|
|
215824
|
+
await rm9(join75(this.rootDir, ".fusion", "tasks", task.id, "PROMPT.md"), { force: true });
|
|
215646
215825
|
})) return;
|
|
215647
215826
|
await this.updatePlanningStateIfStillCurrent(task, { paused: false, pausedReason: null, status: null });
|
|
215648
215827
|
}
|
|
@@ -215653,7 +215832,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215653
215832
|
if (resolution === "prompt" && keepAcknowledged) {
|
|
215654
215833
|
if (canClearInactiveMarker) {
|
|
215655
215834
|
if (!await this.runIfStillPlanningUnderTaskLock(task, async () => {
|
|
215656
|
-
await rm9(
|
|
215835
|
+
await rm9(join75(this.rootDir, ".fusion", "tasks", task.id, "PROMPT.md"), { force: true });
|
|
215657
215836
|
})) return;
|
|
215658
215837
|
await this.updatePlanningStateIfStillCurrent(task, {
|
|
215659
215838
|
paused: false,
|
|
@@ -215694,7 +215873,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215694
215873
|
return;
|
|
215695
215874
|
}
|
|
215696
215875
|
if (!await this.runIfStillPlanningUnderTaskLock(task, async () => {
|
|
215697
|
-
await rm9(
|
|
215876
|
+
await rm9(join75(this.rootDir, ".fusion", "tasks", task.id, "PROMPT.md"), { force: true });
|
|
215698
215877
|
})) return;
|
|
215699
215878
|
if (!await this.updatePlanningStateIfStillCurrent(task, {
|
|
215700
215879
|
paused: false,
|
|
@@ -215759,7 +215938,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215759
215938
|
let nextPrompt = applyOriginalDescription(written, originalDescription);
|
|
215760
215939
|
nextPrompt = applyFrontendUxCriteria(nextPrompt, parsedFileScope);
|
|
215761
215940
|
if (nextPrompt !== written) {
|
|
215762
|
-
const promptPath =
|
|
215941
|
+
const promptPath = join75(this.rootDir, ".fusion", "tasks", task.id, "PROMPT.md");
|
|
215763
215942
|
try {
|
|
215764
215943
|
if (!await this.runIfStillPlanningUnderTaskLock(task, async () => {
|
|
215765
215944
|
await writeFile28(promptPath, nextPrompt, "utf-8");
|
|
@@ -215771,6 +215950,10 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215771
215950
|
}
|
|
215772
215951
|
}
|
|
215773
215952
|
}
|
|
215953
|
+
await mirrorPlanToProjectDb(this.store, task.id, written, {
|
|
215954
|
+
author: "triage",
|
|
215955
|
+
logger: { warn: (m2) => planLog.warn(m2) }
|
|
215956
|
+
});
|
|
215774
215957
|
let taskIntentSignature = {
|
|
215775
215958
|
routePaths: [],
|
|
215776
215959
|
filePaths: [],
|
|
@@ -216017,10 +216200,10 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
216017
216200
|
});
|
|
216018
216201
|
|
|
216019
216202
|
// ../engine/src/review-artifacts/feature-video.ts
|
|
216020
|
-
import { access as access9, mkdtemp as mkdtemp2, readFile as
|
|
216203
|
+
import { access as access9, mkdtemp as mkdtemp2, readFile as readFile38, rm as rm10 } from "node:fs/promises";
|
|
216021
216204
|
import { constants as constants2 } from "node:fs";
|
|
216022
216205
|
import { tmpdir as tmpdir8 } from "node:os";
|
|
216023
|
-
import { join as
|
|
216206
|
+
import { join as join76 } from "node:path";
|
|
216024
216207
|
function shouldGenerateReviewArtifacts(task, settings) {
|
|
216025
216208
|
return isReviewArtifactGenerationEligible(settings, task.prompt);
|
|
216026
216209
|
}
|
|
@@ -216046,7 +216229,7 @@ async function generateFeatureVideo(options) {
|
|
|
216046
216229
|
let browser;
|
|
216047
216230
|
let context;
|
|
216048
216231
|
try {
|
|
216049
|
-
recordingDir = await mkdtemp2(
|
|
216232
|
+
recordingDir = await mkdtemp2(join76(tmpdir8(), "fusion-feature-video-"));
|
|
216050
216233
|
try {
|
|
216051
216234
|
browser = await client.launch({ executablePath, headless: true });
|
|
216052
216235
|
} catch {
|
|
@@ -216064,7 +216247,7 @@ async function generateFeatureVideo(options) {
|
|
|
216064
216247
|
await (options.sleep ?? defaultSleep)(Math.min(Math.max(options.durationMs ?? DEFAULT_DURATION_MS, 0), MAX_DURATION_MS));
|
|
216065
216248
|
await context.close();
|
|
216066
216249
|
context = void 0;
|
|
216067
|
-
const data = await
|
|
216250
|
+
const data = await readFile38(await video.path());
|
|
216068
216251
|
if (data.byteLength > (options.maxBytes ?? DEFAULT_MAX_BYTES2)) {
|
|
216069
216252
|
return { status: "failed", reason: "size-cap-exceeded" };
|
|
216070
216253
|
}
|
|
@@ -216213,16 +216396,16 @@ async function persistBranchState(persistence, state) {
|
|
|
216213
216396
|
);
|
|
216214
216397
|
}
|
|
216215
216398
|
}
|
|
216216
|
-
function resolveJoinConfig(
|
|
216217
|
-
const rawMode =
|
|
216399
|
+
function resolveJoinConfig(join156) {
|
|
216400
|
+
const rawMode = join156.config?.mode;
|
|
216218
216401
|
let mode = "all";
|
|
216219
216402
|
if (rawMode === "all" || rawMode === "any") mode = rawMode;
|
|
216220
216403
|
else if (rawMode && typeof rawMode === "object" && "quorum" in rawMode) {
|
|
216221
216404
|
const n = rawMode.quorum;
|
|
216222
216405
|
if (typeof n === "number" && Number.isInteger(n) && n > 0) mode = { quorum: n };
|
|
216223
|
-
else throw new WorkflowIrError(`join '${
|
|
216406
|
+
else throw new WorkflowIrError(`join '${join156.id}' quorum must be a positive integer`);
|
|
216224
216407
|
}
|
|
216225
|
-
const rawFail =
|
|
216408
|
+
const rawFail = join156.config?.onBranchFailure;
|
|
216226
216409
|
const onBranchFailure = rawFail === "collect" ? "collect" : "fail-fast";
|
|
216227
216410
|
return { mode, onBranchFailure };
|
|
216228
216411
|
}
|
|
@@ -216238,9 +216421,9 @@ async function runSplitJoin(split, env) {
|
|
|
216238
216421
|
if (branchEdges.length === 0) {
|
|
216239
216422
|
throw new WorkflowIrError(`split '${split.id}' has no traversable branches`);
|
|
216240
216423
|
}
|
|
216241
|
-
const
|
|
216242
|
-
if (!
|
|
216243
|
-
const joinConfig = resolveJoinConfig(env.nodeMap.get(
|
|
216424
|
+
const join156 = findMatchingJoin(branchEdges[0].to, env);
|
|
216425
|
+
if (!join156) throw new WorkflowIrError(`split '${split.id}' has no reachable matching join`);
|
|
216426
|
+
const joinConfig = resolveJoinConfig(env.nodeMap.get(join156));
|
|
216244
216427
|
const controller = new AbortController();
|
|
216245
216428
|
const branchCount = branchEdges.length;
|
|
216246
216429
|
const required2 = requiredCompletions(joinConfig.mode, branchCount);
|
|
@@ -216276,7 +216459,7 @@ async function runSplitJoin(split, env) {
|
|
|
216276
216459
|
};
|
|
216277
216460
|
const branchPromises = branchEdges.map((edge) => {
|
|
216278
216461
|
const branchId = edge.to;
|
|
216279
|
-
return walkBranch(branchId,
|
|
216462
|
+
return walkBranch(branchId, join156, env, controller.signal, visitedNodeIds).then((result2) => {
|
|
216280
216463
|
branchOutcomes.push({ branchId, outcome: result2.outcome, nodeId: result2.lastNodeId });
|
|
216281
216464
|
if (result2.outcome === "success") succeeded += 1;
|
|
216282
216465
|
else failed += 1;
|
|
@@ -216294,7 +216477,7 @@ async function runSplitJoin(split, env) {
|
|
|
216294
216477
|
});
|
|
216295
216478
|
const outcome = await joinReached;
|
|
216296
216479
|
await Promise.allSettled(branchPromises);
|
|
216297
|
-
return { joinNodeId:
|
|
216480
|
+
return { joinNodeId: join156, outcome, branchOutcomes, visitedNodeIds };
|
|
216298
216481
|
}
|
|
216299
216482
|
async function walkBranch(startNodeId, joinId, env, signal, visitedNodeIds) {
|
|
216300
216483
|
let currentId = startNodeId;
|
|
@@ -219710,7 +219893,7 @@ var init_workspace_paths = __esm({
|
|
|
219710
219893
|
|
|
219711
219894
|
// ../engine/src/cli-agent/hook-scripts.ts
|
|
219712
219895
|
import { mkdir as mkdir28, rm as rm11, writeFile as writeFile29 } from "node:fs/promises";
|
|
219713
|
-
import { join as
|
|
219896
|
+
import { join as join77 } from "node:path";
|
|
219714
219897
|
function shellSingleQuote(value) {
|
|
219715
219898
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
219716
219899
|
}
|
|
@@ -219782,8 +219965,8 @@ exit 0
|
|
|
219782
219965
|
async function writeSessionHookScripts(opts) {
|
|
219783
219966
|
const { sessionId, token, endpointUrl, dir: dir2 } = opts;
|
|
219784
219967
|
await mkdir28(dir2, { recursive: true, mode: 448 });
|
|
219785
|
-
const hookScriptPath =
|
|
219786
|
-
const notifyScriptPath =
|
|
219968
|
+
const hookScriptPath = join77(dir2, HOOK_SCRIPT_NAMES.hook);
|
|
219969
|
+
const notifyScriptPath = join77(dir2, HOOK_SCRIPT_NAMES.notify);
|
|
219787
219970
|
await writeFile29(hookScriptPath, buildHookScriptContent({ sessionId, token, endpointUrl }), {
|
|
219788
219971
|
mode: 448
|
|
219789
219972
|
});
|
|
@@ -219942,7 +220125,7 @@ var init_autonomy = __esm({
|
|
|
219942
220125
|
// ../engine/src/cli-agent/task-session.ts
|
|
219943
220126
|
import { mkdtemp as mkdtemp3, rm as rm12 } from "node:fs/promises";
|
|
219944
220127
|
import { tmpdir as tmpdir9 } from "node:os";
|
|
219945
|
-
import { join as
|
|
220128
|
+
import { join as join78 } from "node:path";
|
|
219946
220129
|
function launchCliTaskSession(opts) {
|
|
219947
220130
|
return CliTaskSession.launch(opts);
|
|
219948
220131
|
}
|
|
@@ -220008,9 +220191,9 @@ var init_task_session = __esm({
|
|
|
220008
220191
|
isApproved: opts.isAutonomyApproved ?? (() => false)
|
|
220009
220192
|
});
|
|
220010
220193
|
const root = opts.hookDirRoot ?? tmpdir9();
|
|
220011
|
-
const hookDir = await mkdtemp3(
|
|
220012
|
-
const hookScriptPath =
|
|
220013
|
-
const settingsPath =
|
|
220194
|
+
const hookDir = await mkdtemp3(join78(root, "fusion-cli-hooks-"));
|
|
220195
|
+
const hookScriptPath = join78(hookDir, HOOK_SCRIPT_NAMES.hook);
|
|
220196
|
+
const settingsPath = join78(hookDir, "settings.json");
|
|
220014
220197
|
const cliAgentSettings = opts.config.cliAgentSettings ?? null;
|
|
220015
220198
|
const operatorEnvAdditions = (cliAgentSettings?.envAdditions ?? []).filter(
|
|
220016
220199
|
(k2) => !/^FUSION_/i.test(k2)
|
|
@@ -220252,7 +220435,7 @@ var init_task_session = __esm({
|
|
|
220252
220435
|
// ../engine/src/pty-native.ts
|
|
220253
220436
|
import * as fs7 from "node:fs";
|
|
220254
220437
|
import { createRequire as createRequire7 } from "node:module";
|
|
220255
|
-
import { join as
|
|
220438
|
+
import { join as join79, dirname as dirname33 } from "node:path";
|
|
220256
220439
|
function getNativePrebuildName() {
|
|
220257
220440
|
const platform6 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
220258
220441
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
@@ -220262,12 +220445,12 @@ function findInstalledNodePtyNativeDir() {
|
|
|
220262
220445
|
try {
|
|
220263
220446
|
const packageJsonPath = require4.resolve("node-pty/package.json");
|
|
220264
220447
|
const pkgRoot = dirname33(packageJsonPath);
|
|
220265
|
-
const releaseDir =
|
|
220266
|
-
if (fs7.existsSync(
|
|
220448
|
+
const releaseDir = join79(pkgRoot, "build", "Release");
|
|
220449
|
+
if (fs7.existsSync(join79(releaseDir, "pty.node"))) {
|
|
220267
220450
|
return releaseDir;
|
|
220268
220451
|
}
|
|
220269
|
-
const prebuildDir =
|
|
220270
|
-
if (fs7.existsSync(
|
|
220452
|
+
const prebuildDir = join79(pkgRoot, "prebuilds", getNativePrebuildName());
|
|
220453
|
+
if (fs7.existsSync(join79(prebuildDir, "pty.node"))) {
|
|
220271
220454
|
return prebuildDir;
|
|
220272
220455
|
}
|
|
220273
220456
|
return null;
|
|
@@ -220278,14 +220461,14 @@ function findInstalledNodePtyNativeDir() {
|
|
|
220278
220461
|
function findStagedNativeDir() {
|
|
220279
220462
|
const prebuildName = getNativePrebuildName();
|
|
220280
220463
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
220281
|
-
const envPath =
|
|
220282
|
-
if (fs7.existsSync(
|
|
220464
|
+
const envPath = join79(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
220465
|
+
if (fs7.existsSync(join79(envPath, "pty.node"))) {
|
|
220283
220466
|
return envPath;
|
|
220284
220467
|
}
|
|
220285
220468
|
}
|
|
220286
220469
|
const execDir = dirname33(process.execPath);
|
|
220287
|
-
const nextToBinary =
|
|
220288
|
-
if (fs7.existsSync(
|
|
220470
|
+
const nextToBinary = join79(execDir, "runtime", prebuildName);
|
|
220471
|
+
if (fs7.existsSync(join79(nextToBinary, "pty.node"))) {
|
|
220289
220472
|
return nextToBinary;
|
|
220290
220473
|
}
|
|
220291
220474
|
return null;
|
|
@@ -220308,8 +220491,8 @@ function ensureNodePtyNativePermissions() {
|
|
|
220308
220491
|
candidateDirs.add(installedNativeDir);
|
|
220309
220492
|
}
|
|
220310
220493
|
for (const nativeDir of candidateDirs) {
|
|
220311
|
-
const helperPath =
|
|
220312
|
-
const nativeModulePath =
|
|
220494
|
+
const helperPath = join79(nativeDir, "spawn-helper");
|
|
220495
|
+
const nativeModulePath = join79(nativeDir, "pty.node");
|
|
220313
220496
|
try {
|
|
220314
220497
|
fs7.chmodSync(helperPath, 493);
|
|
220315
220498
|
} catch {
|
|
@@ -220339,7 +220522,7 @@ async function loadPtyModule() {
|
|
|
220339
220522
|
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
|
220340
220523
|
}
|
|
220341
220524
|
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
|
220342
|
-
const nativePath =
|
|
220525
|
+
const nativePath = join79(nativeDir, "pty.node");
|
|
220343
220526
|
if (fs7.existsSync(nativePath)) {
|
|
220344
220527
|
try {
|
|
220345
220528
|
const nativeModule = { exports: {} };
|
|
@@ -221878,7 +222061,7 @@ var init_file_scope2 = __esm({
|
|
|
221878
222061
|
|
|
221879
222062
|
// ../engine/src/run-verification-tool.ts
|
|
221880
222063
|
import { existsSync as existsSync64, readdirSync as readdirSync11, readFileSync as readFileSync23 } from "node:fs";
|
|
221881
|
-
import { isAbsolute as isAbsolute16, join as
|
|
222064
|
+
import { isAbsolute as isAbsolute16, join as join80, relative as relative14 } from "node:path";
|
|
221882
222065
|
import { Type as Type6 } from "@earendil-works/pi-ai";
|
|
221883
222066
|
function shellSplit(input) {
|
|
221884
222067
|
const tokens = [];
|
|
@@ -221993,7 +222176,7 @@ function findWorkspacePackageDir(rootDir, packageName) {
|
|
|
221993
222176
|
for (const candidate of candidates) {
|
|
221994
222177
|
if (!candidate) continue;
|
|
221995
222178
|
try {
|
|
221996
|
-
const pkg = JSON.parse(readFileSync23(
|
|
222179
|
+
const pkg = JSON.parse(readFileSync23(join80(rootDir, candidate, "package.json"), "utf8"));
|
|
221997
222180
|
if (pkg.name === packageName) {
|
|
221998
222181
|
packageDirCache.set(cacheKey, candidate);
|
|
221999
222182
|
return candidate;
|
|
@@ -222008,7 +222191,7 @@ function findWorkspacePackageDir(rootDir, packageName) {
|
|
|
222008
222191
|
while (queue2.length > 0) {
|
|
222009
222192
|
const current = queue2.shift();
|
|
222010
222193
|
if (!current) break;
|
|
222011
|
-
const abs =
|
|
222194
|
+
const abs = join80(rootDir, current.dir);
|
|
222012
222195
|
let entries;
|
|
222013
222196
|
try {
|
|
222014
222197
|
entries = readdirSync11(abs, { withFileTypes: true });
|
|
@@ -222018,9 +222201,9 @@ function findWorkspacePackageDir(rootDir, packageName) {
|
|
|
222018
222201
|
for (const entry of entries) {
|
|
222019
222202
|
if (!entry.isDirectory()) continue;
|
|
222020
222203
|
if (entry.name === "node_modules" || entry.name === "dist") continue;
|
|
222021
|
-
const child =
|
|
222204
|
+
const child = join80(current.dir, entry.name);
|
|
222022
222205
|
try {
|
|
222023
|
-
const pkg = JSON.parse(readFileSync23(
|
|
222206
|
+
const pkg = JSON.parse(readFileSync23(join80(rootDir, child, "package.json"), "utf8"));
|
|
222024
222207
|
if (pkg.name === packageName) {
|
|
222025
222208
|
packageDirCache.set(cacheKey, child);
|
|
222026
222209
|
return child;
|
|
@@ -222040,7 +222223,7 @@ function toPackageRelativeFilter(token, rootDir, packageDir) {
|
|
|
222040
222223
|
return normalized.slice(normalizedPackageDir.length + 1);
|
|
222041
222224
|
}
|
|
222042
222225
|
if (isAbsolute16(token)) {
|
|
222043
|
-
const rel = relative14(
|
|
222226
|
+
const rel = relative14(join80(rootDir, packageDir), token).replace(/\\/g, "/");
|
|
222044
222227
|
if (!rel.startsWith("../") && rel !== "..") return rel;
|
|
222045
222228
|
}
|
|
222046
222229
|
return token;
|
|
@@ -222297,7 +222480,7 @@ function createRunVerificationTool(opts) {
|
|
|
222297
222480
|
if (params.cwd && isAbsolute16(params.cwd)) {
|
|
222298
222481
|
resolvedCwd = params.cwd;
|
|
222299
222482
|
} else if (params.cwd) {
|
|
222300
|
-
resolvedCwd =
|
|
222483
|
+
resolvedCwd = join80(worktreePath, params.cwd);
|
|
222301
222484
|
} else {
|
|
222302
222485
|
resolvedCwd = worktreePath;
|
|
222303
222486
|
}
|
|
@@ -222330,7 +222513,7 @@ function createRunVerificationTool(opts) {
|
|
|
222330
222513
|
warnings.push(...normalized.warnings);
|
|
222331
222514
|
}
|
|
222332
222515
|
if (effectiveCommand.trimStart().startsWith("pnpm --filter")) {
|
|
222333
|
-
const modulesYaml =
|
|
222516
|
+
const modulesYaml = join80(rootDir, "node_modules", ".modules.yaml");
|
|
222334
222517
|
if (!existsSync64(modulesYaml)) {
|
|
222335
222518
|
const installCmd = "pnpm install --prefer-offline";
|
|
222336
222519
|
const msg = `node_modules/.modules.yaml not found in workspace root \u2014 auto-prepending \`${installCmd}\` before running the command.`;
|
|
@@ -222675,9 +222858,9 @@ var init_pseudo_pause = __esm({
|
|
|
222675
222858
|
import { exec as exec38, execFile as execFile26, execSync as execSync7 } from "node:child_process";
|
|
222676
222859
|
import { promisify as promisify53 } from "node:util";
|
|
222677
222860
|
import { setImmediate as setImmediateCb3 } from "node:timers";
|
|
222678
|
-
import { basename as basename19, delimiter as delimiter2, isAbsolute as isAbsolute18, join as
|
|
222861
|
+
import { basename as basename19, delimiter as delimiter2, isAbsolute as isAbsolute18, join as join81, relative as relative16, resolve as resolvePath3 } from "node:path";
|
|
222679
222862
|
import { existsSync as existsSync65, lstatSync as lstatSync3, realpathSync as realpathSync9 } from "node:fs";
|
|
222680
|
-
import { readFile as
|
|
222863
|
+
import { readFile as readFile39, rm as rm13, writeFile as writeFile30 } from "node:fs/promises";
|
|
222681
222864
|
import { Type as Type7 } from "@earendil-works/pi-ai";
|
|
222682
222865
|
import { SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
|
|
222683
222866
|
function mergeAdditionalSkillPaths2(...pathGroups) {
|
|
@@ -222691,7 +222874,7 @@ function isWorkflowStepSkillDiscoverable(skillName, additionalSkillPaths, ceSkil
|
|
|
222691
222874
|
return false;
|
|
222692
222875
|
}
|
|
222693
222876
|
return (additionalSkillPaths ?? []).some(
|
|
222694
|
-
(skillPath) => basename19(skillPath) === bareSkillName2 && existsSync65(
|
|
222877
|
+
(skillPath) => basename19(skillPath) === bareSkillName2 && existsSync65(join81(skillPath, "SKILL.md")) || existsSync65(join81(skillPath, bareSkillName2, "SKILL.md"))
|
|
222695
222878
|
);
|
|
222696
222879
|
}
|
|
222697
222880
|
function getPromptSection(prompt, heading) {
|
|
@@ -223000,7 +223183,7 @@ function normalizeWorktreePath(pathValue) {
|
|
|
223000
223183
|
}
|
|
223001
223184
|
async function extractPersistedSessionWorktreePath(sessionFile, rootDir, settings) {
|
|
223002
223185
|
try {
|
|
223003
|
-
const content = await
|
|
223186
|
+
const content = await readFile39(sessionFile, "utf-8");
|
|
223004
223187
|
const matches = content.match(buildSessionWorktreePathRegex(rootDir, settings)) ?? [];
|
|
223005
223188
|
if (matches.length === 0) return null;
|
|
223006
223189
|
const normalizedCounts = /* @__PURE__ */ new Map();
|
|
@@ -226448,7 +226631,7 @@ ${info.feedback}`, revisionKey),
|
|
|
226448
226631
|
const authoritativeAgentLayer = this.store.getAsyncLayer();
|
|
226449
226632
|
if (!this.authoritativeAssignedAgentStore || authoritativeAgentLayer && !this.authoritativeAssignedAgentStore.backendMode) {
|
|
226450
226633
|
this.authoritativeAssignedAgentStore = new AgentStore({
|
|
226451
|
-
rootDir:
|
|
226634
|
+
rootDir: join81(this.rootDir, ".fusion"),
|
|
226452
226635
|
taskStore: this.store,
|
|
226453
226636
|
...authoritativeAgentLayer ? { asyncLayer: authoritativeAgentLayer } : {}
|
|
226454
226637
|
});
|
|
@@ -230908,7 +231091,7 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
230908
231091
|
const activeMergeStatuses = /* @__PURE__ */ new Set(["merging", "merging-pr", "merging-fix"]);
|
|
230909
231092
|
const isActiveTask = activeColumns.has(task.column) || activeMergeStatuses.has(task.status ?? "");
|
|
230910
231093
|
if (!isActiveTask) {
|
|
230911
|
-
const tasksDir =
|
|
231094
|
+
const tasksDir = join81(this.store.getFusionDir(), "tasks");
|
|
230912
231095
|
const promptPath = getPromptPath(tasksDir, task.id);
|
|
230913
231096
|
const staleness = await evaluateSpecStaleness({ settings, promptPath, task });
|
|
230914
231097
|
if (staleness.isStale) {
|
|
@@ -234769,10 +234952,10 @@ Please fix the issues so the verification can pass on the next attempt.`,
|
|
|
234769
234952
|
* The section is replaced entirely to avoid accumulation of old feedback.
|
|
234770
234953
|
*/
|
|
234771
234954
|
async injectWorkflowStepFailureInstructions(task, failureFeedback, stepName, retry2) {
|
|
234772
|
-
const promptPath =
|
|
234955
|
+
const promptPath = join81(this.store.getFusionDir(), "tasks", task.id, "PROMPT.md");
|
|
234773
234956
|
let content;
|
|
234774
234957
|
try {
|
|
234775
|
-
content = await
|
|
234958
|
+
content = await readFile39(promptPath, "utf-8");
|
|
234776
234959
|
} catch {
|
|
234777
234960
|
executorLog.warn(`${task.id}: PROMPT.md not found at ${promptPath}, skipping workflow failure injection`);
|
|
234778
234961
|
return;
|
|
@@ -241311,7 +241494,7 @@ import { execFile as execFile27 } from "node:child_process";
|
|
|
241311
241494
|
import { appendFileSync as appendFileSync2, existsSync as existsSync66, mkdirSync as mkdirSync11, readdirSync as readdirSync12, readFileSync as readFileSync24, realpathSync as realpathSync10, rmSync as rmSync9, statSync as statSync13 } from "node:fs";
|
|
241312
241495
|
import { rm as rm14 } from "node:fs/promises";
|
|
241313
241496
|
import { tmpdir as tmpdir10 } from "node:os";
|
|
241314
|
-
import { isAbsolute as isAbsolute19, join as
|
|
241497
|
+
import { isAbsolute as isAbsolute19, join as join82, relative as relative17 } from "node:path";
|
|
241315
241498
|
import { promisify as promisify56 } from "node:util";
|
|
241316
241499
|
async function git4(args, cwd, opts = {}) {
|
|
241317
241500
|
const { stdout } = await execFileAsync20("git", args, {
|
|
@@ -241342,7 +241525,7 @@ function isBenignAbsentWorktreeError(err) {
|
|
|
241342
241525
|
return /is not a working tree|No such file or directory|spawn\s+.*\bENOENT\b/i.test(description);
|
|
241343
241526
|
}
|
|
241344
241527
|
function ensureAiMergeRootIgnored(projectRootDir, settings) {
|
|
241345
|
-
const excludePath =
|
|
241528
|
+
const excludePath = join82(projectRootDir, ".git", "info", "exclude");
|
|
241346
241529
|
if (!existsSync66(excludePath)) return;
|
|
241347
241530
|
try {
|
|
241348
241531
|
const current = readFileSync24(excludePath, "utf-8");
|
|
@@ -241374,7 +241557,7 @@ function getAiMergeTempSearchRoots(projectRootDir, settings) {
|
|
|
241374
241557
|
if (testWorkerRoot) {
|
|
241375
241558
|
try {
|
|
241376
241559
|
for (const entry of readdirSync12(testWorkerRoot)) {
|
|
241377
|
-
if (entry.startsWith("redir-")) roots.push(
|
|
241560
|
+
if (entry.startsWith("redir-")) roots.push(join82(testWorkerRoot, entry));
|
|
241378
241561
|
}
|
|
241379
241562
|
} catch {
|
|
241380
241563
|
}
|
|
@@ -241397,7 +241580,7 @@ async function pruneExistingAiMergeWorktrees(taskId, projectRootDir, audit, log3
|
|
|
241397
241580
|
continue;
|
|
241398
241581
|
}
|
|
241399
241582
|
for (const entry of entries) {
|
|
241400
|
-
const candidatePath =
|
|
241583
|
+
const candidatePath = join82(tempRoot, entry);
|
|
241401
241584
|
let canonicalPath = candidatePath;
|
|
241402
241585
|
try {
|
|
241403
241586
|
canonicalPath = realpathSync10(candidatePath);
|
|
@@ -241820,7 +242003,7 @@ import { promisify as promisify57 } from "node:util";
|
|
|
241820
242003
|
import { realpathSync as realpathSync11, readdirSync as readdirSync13 } from "node:fs";
|
|
241821
242004
|
import { mkdtemp as mkdtemp4 } from "node:fs/promises";
|
|
241822
242005
|
import { tmpdir as tmpdir11 } from "node:os";
|
|
241823
|
-
import { join as
|
|
242006
|
+
import { join as join83 } from "node:path";
|
|
241824
242007
|
async function git5(args, cwd, opts = {}) {
|
|
241825
242008
|
const { stdout } = await execFileAsync21("git", args, {
|
|
241826
242009
|
cwd,
|
|
@@ -241892,7 +242075,7 @@ function listAiMergeWorktreeCandidates(taskId, projectRootDir, settings) {
|
|
|
241892
242075
|
if (testWorkerRoot) {
|
|
241893
242076
|
try {
|
|
241894
242077
|
for (const entry of readdirSync13(testWorkerRoot)) {
|
|
241895
|
-
if (entry.startsWith("redir-")) roots.push(
|
|
242078
|
+
if (entry.startsWith("redir-")) roots.push(join83(testWorkerRoot, entry));
|
|
241896
242079
|
}
|
|
241897
242080
|
} catch {
|
|
241898
242081
|
}
|
|
@@ -241905,7 +242088,7 @@ function listAiMergeWorktreeCandidates(taskId, projectRootDir, settings) {
|
|
|
241905
242088
|
} catch {
|
|
241906
242089
|
continue;
|
|
241907
242090
|
}
|
|
241908
|
-
for (const entry of entries) candidates.push(
|
|
242091
|
+
for (const entry of entries) candidates.push(join83(root, entry));
|
|
241909
242092
|
}
|
|
241910
242093
|
return candidates;
|
|
241911
242094
|
}
|
|
@@ -242239,7 +242422,7 @@ async function landOneRepo(repoRootDir, branch, integrationBranch, ctx) {
|
|
|
242239
242422
|
registeredMergePaths.add(pathToRegister);
|
|
242240
242423
|
};
|
|
242241
242424
|
try {
|
|
242242
|
-
mergeRoot = await mkdtemp4(
|
|
242425
|
+
mergeRoot = await mkdtemp4(join83(resolveAiMergeRoot(repoRootDir, settings), `fusion-ai-merge-${taskId.toLowerCase()}-`));
|
|
242243
242426
|
registerMergeRoot(mergeRoot);
|
|
242244
242427
|
await git5(["worktree", "add", "--detach", mergeRoot, tipSha], repoRootDir);
|
|
242245
242428
|
worktreeAdded = true;
|
|
@@ -242735,7 +242918,7 @@ async function landWorkspaceTask(store, task, workspaceRootDir, options = {}, de
|
|
|
242735
242918
|
for (const repoRel of repoKeys) {
|
|
242736
242919
|
throwIfAborted2(options.signal, taskId);
|
|
242737
242920
|
const entry = workspaceWorktrees[repoRel];
|
|
242738
|
-
const repoRootDir =
|
|
242921
|
+
const repoRootDir = join83(workspaceRootDir, repoRel);
|
|
242739
242922
|
let integrationBranch;
|
|
242740
242923
|
try {
|
|
242741
242924
|
integrationBranch = await resolveIntegrationBranch(
|
|
@@ -243052,7 +243235,7 @@ async function pushAfterMergeToRemote(input) {
|
|
|
243052
243235
|
let worktreeAdded = false;
|
|
243053
243236
|
const registeredPaths = /* @__PURE__ */ new Set();
|
|
243054
243237
|
try {
|
|
243055
|
-
pushRoot = await mkdtemp4(
|
|
243238
|
+
pushRoot = await mkdtemp4(join83(resolveAiMergeRoot(projectRootDir, settings), `fusion-ai-merge-push-${taskId.toLowerCase()}-`));
|
|
243056
243239
|
for (const p2 of [pushRoot]) {
|
|
243057
243240
|
activeSessionRegistry.registerPath(p2, { taskId, kind: "ai-merge", ownerKey: `ai-merge-push:${taskId}` });
|
|
243058
243241
|
registeredPaths.add(p2);
|
|
@@ -243359,7 +243542,7 @@ var init_merger_ai = __esm({
|
|
|
243359
243542
|
|
|
243360
243543
|
// ../engine/src/task-revert.ts
|
|
243361
243544
|
import { exec as exec41 } from "node:child_process";
|
|
243362
|
-
import { join as
|
|
243545
|
+
import { join as join84 } from "node:path";
|
|
243363
243546
|
import { promisify as promisify58 } from "node:util";
|
|
243364
243547
|
function quoteShellArg7(value) {
|
|
243365
243548
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -243809,7 +243992,7 @@ async function resolveWorkspaceTaskRevertCommits(task, opts) {
|
|
|
243809
243992
|
const result2 = {};
|
|
243810
243993
|
for (const repoRel of repoKeys) {
|
|
243811
243994
|
const entry = workspaceWorktrees[repoRel];
|
|
243812
|
-
const repoRootDir =
|
|
243995
|
+
const repoRootDir = join84(opts.workspaceRootDir, repoRel);
|
|
243813
243996
|
const landedSha = workspaceLandedShas[repoRel] ?? entry?.landedSha;
|
|
243814
243997
|
if (landedSha && !entry?.baseCommitSha) {
|
|
243815
243998
|
result2[repoRel] = { commits: [landedSha], source: "squash" };
|
|
@@ -243876,7 +244059,7 @@ async function revertWorkspaceTask(opts) {
|
|
|
243876
244059
|
});
|
|
243877
244060
|
const contexts = [];
|
|
243878
244061
|
for (const repoRel of repoKeys) {
|
|
243879
|
-
const repoRootDir =
|
|
244062
|
+
const repoRootDir = join84(workspaceRootDir, repoRel);
|
|
243880
244063
|
let integrationBranch;
|
|
243881
244064
|
try {
|
|
243882
244065
|
integrationBranch = await resolveIntegrationBranch(repoRootDir, { ...opts.settings, integrationBranch: void 0, baseBranch: void 0 });
|
|
@@ -244001,7 +244184,7 @@ async function prepareWorkspaceRevertPrBranches(opts) {
|
|
|
244001
244184
|
});
|
|
244002
244185
|
const contexts = [];
|
|
244003
244186
|
for (const repoRel of repoKeys) {
|
|
244004
|
-
const repoRootDir =
|
|
244187
|
+
const repoRootDir = join84(workspaceRootDir, repoRel);
|
|
244005
244188
|
let integrationBranch;
|
|
244006
244189
|
try {
|
|
244007
244190
|
integrationBranch = await resolveIntegrationBranch(repoRootDir, { ...opts.settings, integrationBranch: void 0, baseBranch: void 0 });
|
|
@@ -244342,7 +244525,7 @@ async function readOptionalTextFile(filePath) {
|
|
|
244342
244525
|
}
|
|
244343
244526
|
async function discoverMcpServers(opts) {
|
|
244344
244527
|
const homeDir = opts.homeDir ?? process.env.HOME ?? process.env.USERPROFILE ?? osHomedir();
|
|
244345
|
-
const
|
|
244528
|
+
const readFile64 = opts.readFile ?? readOptionalTextFile;
|
|
244346
244529
|
const sources = getMcpDiscoverySources({
|
|
244347
244530
|
homeDir,
|
|
244348
244531
|
platform: osPlatform(),
|
|
@@ -244353,7 +244536,7 @@ async function discoverMcpServers(opts) {
|
|
|
244353
244536
|
for (const source of sources) {
|
|
244354
244537
|
let contents;
|
|
244355
244538
|
try {
|
|
244356
|
-
contents = await
|
|
244539
|
+
contents = await readFile64(source.path);
|
|
244357
244540
|
} catch (error3) {
|
|
244358
244541
|
errors.push(`${source.label}: ${error3 instanceof Error ? error3.message : String(error3)}`);
|
|
244359
244542
|
continue;
|
|
@@ -244903,7 +245086,7 @@ var agent_reflection_exports = {};
|
|
|
244903
245086
|
__export(agent_reflection_exports, {
|
|
244904
245087
|
AgentReflectionService: () => AgentReflectionService
|
|
244905
245088
|
});
|
|
244906
|
-
import { readFile as
|
|
245089
|
+
import { readFile as readFile40 } from "node:fs/promises";
|
|
244907
245090
|
import { isAbsolute as isAbsolute20, resolve as resolve38 } from "node:path";
|
|
244908
245091
|
var reflectionLog, REFLECTION_SYSTEM_PROMPT, DEFAULT_OUTCOME_LIMIT, AgentReflectionService;
|
|
244909
245092
|
var init_agent_reflection = __esm({
|
|
@@ -245462,7 +245645,7 @@ Rules:
|
|
|
245462
245645
|
if (agent.instructionsPath?.trim()) {
|
|
245463
245646
|
const resolvedPath = isAbsolute20(agent.instructionsPath) ? agent.instructionsPath : resolve38(this.rootDir, agent.instructionsPath);
|
|
245464
245647
|
try {
|
|
245465
|
-
const content = await
|
|
245648
|
+
const content = await readFile40(resolvedPath, "utf-8");
|
|
245466
245649
|
if (content.trim()) {
|
|
245467
245650
|
pieces.push(content.trim());
|
|
245468
245651
|
}
|
|
@@ -247570,7 +247753,7 @@ The note must be specific (what/where/why). Prefer citing File Scope, PROMPT, a
|
|
|
247570
247753
|
|
|
247571
247754
|
// ../engine/src/overseer-watchdog.ts
|
|
247572
247755
|
import { existsSync as existsSync67, readFileSync as readFileSync25 } from "node:fs";
|
|
247573
|
-
import { dirname as dirname34, join as
|
|
247756
|
+
import { dirname as dirname34, join as join85, relative as relative18, resolve as resolve39, sep as sep11 } from "node:path";
|
|
247574
247757
|
import { homedir as homedir11 } from "node:os";
|
|
247575
247758
|
function defaultReadText(path14) {
|
|
247576
247759
|
try {
|
|
@@ -247599,7 +247782,7 @@ function discoverOverseerWatchdogFiles(options) {
|
|
|
247599
247782
|
};
|
|
247600
247783
|
if (agentDir) {
|
|
247601
247784
|
for (const name2 of WATCHDOG_FILENAMES) {
|
|
247602
|
-
tryAdd(
|
|
247785
|
+
tryAdd(join85(agentDir, name2), "user", 999);
|
|
247603
247786
|
}
|
|
247604
247787
|
}
|
|
247605
247788
|
let current = cwd;
|
|
@@ -247607,9 +247790,9 @@ function discoverOverseerWatchdogFiles(options) {
|
|
|
247607
247790
|
for (let hop = 0; hop < 64; hop++) {
|
|
247608
247791
|
const depth = relative18(cwd, current) === "" ? 0 : relative18(cwd, current).split(sep11).filter(Boolean).length;
|
|
247609
247792
|
for (const name2 of WATCHDOG_FILENAMES) {
|
|
247610
|
-
tryAdd(
|
|
247611
|
-
tryAdd(
|
|
247612
|
-
tryAdd(
|
|
247793
|
+
tryAdd(join85(current, name2), "project", depth);
|
|
247794
|
+
tryAdd(join85(current, ".fusion", name2), "project", depth);
|
|
247795
|
+
tryAdd(join85(current, ".omp", name2), "project", depth);
|
|
247613
247796
|
}
|
|
247614
247797
|
if (current === stopAt) break;
|
|
247615
247798
|
const parent2 = dirname34(current);
|
|
@@ -255912,7 +256095,7 @@ __export(child_process_runtime_exports, {
|
|
|
255912
256095
|
import { EventEmitter as EventEmitter29 } from "node:events";
|
|
255913
256096
|
import { fork } from "node:child_process";
|
|
255914
256097
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
255915
|
-
import { dirname as dirname35, join as
|
|
256098
|
+
import { dirname as dirname35, join as join86 } from "node:path";
|
|
255916
256099
|
var HealthMonitor, ChildProcessRuntime;
|
|
255917
256100
|
var init_child_process_runtime = __esm({
|
|
255918
256101
|
"../engine/src/runtimes/child-process-runtime.ts"() {
|
|
@@ -256074,7 +256257,7 @@ var init_child_process_runtime = __esm({
|
|
|
256074
256257
|
const isCompiled = !import.meta.url.endsWith(".ts");
|
|
256075
256258
|
const currentDir = dirname35(fileURLToPath4(import.meta.url));
|
|
256076
256259
|
const workerFile = isCompiled ? "child-process-worker.js" : "child-process-worker.ts";
|
|
256077
|
-
return
|
|
256260
|
+
return join86(currentDir, workerFile);
|
|
256078
256261
|
}
|
|
256079
256262
|
/**
|
|
256080
256263
|
* Set up event forwarding from IPC host to runtime listeners.
|
|
@@ -262341,7 +262524,7 @@ import { mkdirSync as mkdirSync12 } from "node:fs";
|
|
|
262341
262524
|
import { access as access10, unlink as unlink10, writeFile as writeFile32 } from "node:fs/promises";
|
|
262342
262525
|
import net2 from "node:net";
|
|
262343
262526
|
import { platform as platform3, tmpdir as tmpdir12 } from "node:os";
|
|
262344
|
-
import { join as
|
|
262527
|
+
import { join as join87 } from "node:path";
|
|
262345
262528
|
import { createHash as createHash24 } from "node:crypto";
|
|
262346
262529
|
function projectHash(projectId) {
|
|
262347
262530
|
return createHash24("sha1").update(projectId).digest("hex").slice(0, 16);
|
|
@@ -262351,10 +262534,10 @@ function computeEngineSocketPath(projectId) {
|
|
|
262351
262534
|
if (platform3() === "win32") {
|
|
262352
262535
|
return `\\\\.\\pipe\\fusion-engine-${hash}`;
|
|
262353
262536
|
}
|
|
262354
|
-
return
|
|
262537
|
+
return join87(tmpdir12(), `fusion-engine-${hash}.sock`);
|
|
262355
262538
|
}
|
|
262356
262539
|
function computeEngineLockFilePath(workingDir) {
|
|
262357
|
-
return
|
|
262540
|
+
return join87(workingDir, ".fusion", "engine.lock");
|
|
262358
262541
|
}
|
|
262359
262542
|
async function ensureLockTargetExists(lockPath) {
|
|
262360
262543
|
try {
|
|
@@ -262364,7 +262547,7 @@ async function ensureLockTargetExists(lockPath) {
|
|
|
262364
262547
|
}
|
|
262365
262548
|
}
|
|
262366
262549
|
async function acquireLockfile(workingDir, onCompromised) {
|
|
262367
|
-
const dir2 =
|
|
262550
|
+
const dir2 = join87(workingDir, ".fusion");
|
|
262368
262551
|
mkdirSync12(dir2, { recursive: true });
|
|
262369
262552
|
const path14 = computeEngineLockFilePath(workingDir);
|
|
262370
262553
|
await ensureLockTargetExists(path14);
|
|
@@ -272048,8 +272231,8 @@ var init_project_store_resolver = __esm({
|
|
|
272048
272231
|
|
|
272049
272232
|
// ../dashboard/src/plugin-routes.ts
|
|
272050
272233
|
import { Router } from "express";
|
|
272051
|
-
import { access as access11, stat as stat10, readFile as
|
|
272052
|
-
import { join as
|
|
272234
|
+
import { access as access11, stat as stat10, readFile as readFile41 } from "node:fs/promises";
|
|
272235
|
+
import { join as join88, isAbsolute as isAbsolute22, dirname as dirname36, basename as basename21 } from "node:path";
|
|
272053
272236
|
function isPluginRouteResponse(result2) {
|
|
272054
272237
|
if (!result2 || typeof result2 !== "object" || Array.isArray(result2)) {
|
|
272055
272238
|
return false;
|
|
@@ -272062,7 +272245,7 @@ async function loadRegistryManifest() {
|
|
|
272062
272245
|
return cachedRegistryManifest;
|
|
272063
272246
|
}
|
|
272064
272247
|
try {
|
|
272065
|
-
const raw = await
|
|
272248
|
+
const raw = await readFile41(registryManifestUrl, "utf-8");
|
|
272066
272249
|
cachedRegistryManifest = JSON.parse(raw);
|
|
272067
272250
|
return cachedRegistryManifest;
|
|
272068
272251
|
} catch (error3) {
|
|
@@ -272159,7 +272342,7 @@ async function resolvePluginManifest(sourcePath) {
|
|
|
272159
272342
|
if (!sourceStat.isDirectory()) {
|
|
272160
272343
|
throw badRequest(`Path is not a directory: ${sourcePath}`);
|
|
272161
272344
|
}
|
|
272162
|
-
const directManifestPath =
|
|
272345
|
+
const directManifestPath = join88(sourcePath, "manifest.json");
|
|
272163
272346
|
try {
|
|
272164
272347
|
await access11(directManifestPath);
|
|
272165
272348
|
const manifest = await readAndValidateManifest(directManifestPath);
|
|
@@ -272170,7 +272353,7 @@ async function resolvePluginManifest(sourcePath) {
|
|
|
272170
272353
|
const dirName = basename21(sourcePath).toLowerCase();
|
|
272171
272354
|
if (DIST_DIR_NAMES.has(dirName)) {
|
|
272172
272355
|
const parentDir = dirname36(sourcePath);
|
|
272173
|
-
const parentManifestPath =
|
|
272356
|
+
const parentManifestPath = join88(parentDir, "manifest.json");
|
|
272174
272357
|
try {
|
|
272175
272358
|
await access11(parentManifestPath);
|
|
272176
272359
|
const manifest = await readAndValidateManifest(parentManifestPath);
|
|
@@ -272186,7 +272369,7 @@ async function resolvePluginManifest(sourcePath) {
|
|
|
272186
272369
|
async function readAndValidateManifest(manifestPath) {
|
|
272187
272370
|
let content;
|
|
272188
272371
|
try {
|
|
272189
|
-
content = await
|
|
272372
|
+
content = await readFile41(manifestPath, "utf-8");
|
|
272190
272373
|
} catch (err) {
|
|
272191
272374
|
throw badRequest(`Cannot read manifest at ${manifestPath}: ${err.message}`);
|
|
272192
272375
|
}
|
|
@@ -273255,7 +273438,7 @@ var init_issue_image_attachments = __esm({
|
|
|
273255
273438
|
import { exec as exec45 } from "node:child_process";
|
|
273256
273439
|
import { mkdtemp as mkdtemp6, rm as rm15 } from "node:fs/promises";
|
|
273257
273440
|
import { tmpdir as tmpdir13 } from "node:os";
|
|
273258
|
-
import { join as
|
|
273441
|
+
import { join as join89 } from "node:path";
|
|
273259
273442
|
import { promisify as promisify65 } from "node:util";
|
|
273260
273443
|
function resolveCommentAuthor(input) {
|
|
273261
273444
|
const login = input.login || "unknown";
|
|
@@ -274501,8 +274684,8 @@ var init_github = __esm({
|
|
|
274501
274684
|
{ timeout: 3e4, maxBuffer: 10 * 1024 * 1024 }
|
|
274502
274685
|
);
|
|
274503
274686
|
const mergeBase = mergeBaseStdout.trim();
|
|
274504
|
-
const indexDir = await mkdtemp6(
|
|
274505
|
-
const indexPath =
|
|
274687
|
+
const indexDir = await mkdtemp6(join89(tmpdir13(), "fn-pr-conflict-"));
|
|
274688
|
+
const indexPath = join89(indexDir, "index");
|
|
274506
274689
|
const gitEnv = { ...process.env, GIT_INDEX_FILE: indexPath };
|
|
274507
274690
|
try {
|
|
274508
274691
|
await execAsync40(`git -C ${quoteGitArg(opts.repoRoot)} read-tree -m ${quoteGitArg(mergeBase)} ${quoteGitArg(baseRef)} ${quoteGitArg(headRef)}`, {
|
|
@@ -276717,7 +276900,7 @@ var init_github = __esm({
|
|
|
276717
276900
|
});
|
|
276718
276901
|
|
|
276719
276902
|
// ../dashboard/src/artifact-media.ts
|
|
276720
|
-
import { readFile as
|
|
276903
|
+
import { readFile as readFile42 } from "node:fs/promises";
|
|
276721
276904
|
import { resolve as resolve41, sep as sep13 } from "node:path";
|
|
276722
276905
|
function resolveArtifactMediaPath(scopedStore, artifact) {
|
|
276723
276906
|
if (!artifact.uri) return null;
|
|
@@ -276733,7 +276916,7 @@ function resolveArtifactMediaPath(scopedStore, artifact) {
|
|
|
276733
276916
|
async function readArtifactMediaBytes(scopedStore, artifact) {
|
|
276734
276917
|
const mediaPath = resolveArtifactMediaPath(scopedStore, artifact);
|
|
276735
276918
|
if (!mediaPath) throw badRequest("Artifact has no stored media");
|
|
276736
|
-
return
|
|
276919
|
+
return readFile42(mediaPath);
|
|
276737
276920
|
}
|
|
276738
276921
|
var init_artifact_media = __esm({
|
|
276739
276922
|
"../dashboard/src/artifact-media.ts"() {
|
|
@@ -279758,8 +279941,8 @@ var init_knowledge_index_refresh = __esm({
|
|
|
279758
279941
|
// ../dashboard/src/pr-metadata-generator.ts
|
|
279759
279942
|
import { promisify as promisify66 } from "node:util";
|
|
279760
279943
|
import { exec as execCb } from "node:child_process";
|
|
279761
|
-
import { access as access12, readFile as
|
|
279762
|
-
import { join as
|
|
279944
|
+
import { access as access12, readFile as readFile43 } from "node:fs/promises";
|
|
279945
|
+
import { join as join90 } from "node:path";
|
|
279763
279946
|
function buildFallbackPrMetadata(task) {
|
|
279764
279947
|
return {
|
|
279765
279948
|
title: task.title ?? task.id,
|
|
@@ -279959,14 +280142,14 @@ async function generatePrMetadata(input) {
|
|
|
279959
280142
|
]), combinedSignal);
|
|
279960
280143
|
let promptContent = "";
|
|
279961
280144
|
try {
|
|
279962
|
-
const promptPath =
|
|
279963
|
-
promptContent = (await raceWithAbort(
|
|
280145
|
+
const promptPath = join90(repoRoot, ".fusion", "tasks", task.id, "PROMPT.md");
|
|
280146
|
+
promptContent = (await raceWithAbort(readFile43(promptPath, "utf8"), combinedSignal)).trim();
|
|
279964
280147
|
} catch {
|
|
279965
280148
|
promptContent = "";
|
|
279966
280149
|
}
|
|
279967
|
-
const templatePath =
|
|
280150
|
+
const templatePath = join90(repoRoot, ".github", "pull_request_template.md");
|
|
279968
280151
|
const templateExists = await raceWithAbort(access12(templatePath).then(() => true).catch(() => false), combinedSignal);
|
|
279969
|
-
const template = templateExists ? await raceWithAbort(
|
|
280152
|
+
const template = templateExists ? await raceWithAbort(readFile43(templatePath, "utf8"), combinedSignal) : "";
|
|
279970
280153
|
const model = resolveTitleSummarizerSettingsModel(settings);
|
|
279971
280154
|
const systemPrompt = [PR_METADATA_SYSTEM_PROMPT];
|
|
279972
280155
|
const titleGuidance = settings.prTitlePromptInstructions?.trim();
|
|
@@ -280151,8 +280334,8 @@ var init_resolve_diff_base = __esm({
|
|
|
280151
280334
|
});
|
|
280152
280335
|
|
|
280153
280336
|
// ../dashboard/src/pr-conflict-resolver.ts
|
|
280154
|
-
import { access as access13, mkdir as mkdir29, readFile as
|
|
280155
|
-
import { join as
|
|
280337
|
+
import { access as access13, mkdir as mkdir29, readFile as readFile44, rm as rm16 } from "node:fs/promises";
|
|
280338
|
+
import { join as join91, resolve as resolve43 } from "node:path";
|
|
280156
280339
|
function asSessionPluginRunner(runner) {
|
|
280157
280340
|
if (!runner) return void 0;
|
|
280158
280341
|
if (typeof runner.getRuntimeById === "function") {
|
|
@@ -280201,7 +280384,7 @@ async function findFilesWithConflictMarkers2(rootDir, files) {
|
|
|
280201
280384
|
const conflicted = [];
|
|
280202
280385
|
for (const file of files) {
|
|
280203
280386
|
try {
|
|
280204
|
-
const contents = await
|
|
280387
|
+
const contents = await readFile44(join91(rootDir, file), "utf8");
|
|
280205
280388
|
if (/^<<<<<<< /m.test(contents) || /^=======$/m.test(contents) || /^>>>>>>> /m.test(contents)) {
|
|
280206
280389
|
conflicted.push(file);
|
|
280207
280390
|
}
|
|
@@ -280286,11 +280469,11 @@ async function resolvePrConflicts(input) {
|
|
|
280286
280469
|
const task = await store.getTask(taskId);
|
|
280287
280470
|
const branchName = getHeadBranch(taskId);
|
|
280288
280471
|
const reusableWorktree = await resolveUsableWorktree(task.worktree, branchName);
|
|
280289
|
-
const tempWorktreePath =
|
|
280472
|
+
const tempWorktreePath = join91(rootDir, ".fusion", "worktrees", `conflict-${taskId.toLowerCase()}`);
|
|
280290
280473
|
const cwd = reusableWorktree ?? tempWorktreePath;
|
|
280291
280474
|
const createdTemporaryWorktree = !reusableWorktree;
|
|
280292
280475
|
if (createdTemporaryWorktree) {
|
|
280293
|
-
await mkdir29(
|
|
280476
|
+
await mkdir29(join91(rootDir, ".fusion", "worktrees"), { recursive: true });
|
|
280294
280477
|
await rm16(tempWorktreePath, { recursive: true, force: true });
|
|
280295
280478
|
await runGitCommand2(["worktree", "add", "--force", tempWorktreePath, branchName], rootDir, GIT_TIMEOUT_MS10);
|
|
280296
280479
|
}
|
|
@@ -288118,7 +288301,7 @@ var init_auth_middleware = __esm({
|
|
|
288118
288301
|
// ../dashboard/src/routes/register-task-workflow-routes.ts
|
|
288119
288302
|
import { createReadStream } from "node:fs";
|
|
288120
288303
|
import { stat as stat11 } from "node:fs/promises";
|
|
288121
|
-
import { join as
|
|
288304
|
+
import { join as join92 } from "node:path";
|
|
288122
288305
|
async function clearRebuiltSpecWorkflowPins(store, taskId) {
|
|
288123
288306
|
const maybeStore = store;
|
|
288124
288307
|
try {
|
|
@@ -289301,13 +289484,16 @@ ${normalizedDescription}`;
|
|
|
289301
289484
|
const existing = await scopedStore.getTask(req.params.id);
|
|
289302
289485
|
const rootDir = scopedStore.getRootDir();
|
|
289303
289486
|
const allocateWorktree = existing ? (task2, reservedNames) => planTaskWorktreePath(task2, rootDir, settings.worktreeNaming, reservedNames, settings) : void 0;
|
|
289304
|
-
const
|
|
289487
|
+
const force = req.body?.force === true;
|
|
289488
|
+
const result2 = await promoteHeldTask(scopedStore, req.params.id, { allocateWorktree }, { force });
|
|
289305
289489
|
if (!result2.released) {
|
|
289306
289490
|
if (result2.rejection === "unplanned-for-execution") {
|
|
289307
289491
|
throw new ApiError(409, "Task is not ready for execution (plan review or planning still outstanding)", {
|
|
289308
289492
|
code: "unplanned-for-execution",
|
|
289309
289493
|
messageKey: "board.rejection.unplannedForExecution",
|
|
289310
|
-
retryable: true
|
|
289494
|
+
retryable: true,
|
|
289495
|
+
// Tells the board this rejection has an operator override available.
|
|
289496
|
+
forceable: true
|
|
289311
289497
|
});
|
|
289312
289498
|
}
|
|
289313
289499
|
if (result2.rejection === "capacity-exhausted-or-no-slot") {
|
|
@@ -289449,14 +289635,14 @@ ${normalizedDescription}`;
|
|
|
289449
289635
|
}
|
|
289450
289636
|
const cleanupPreparedBranches = async () => {
|
|
289451
289637
|
for (const repoBranch of prepared.repos) {
|
|
289452
|
-
const repoRootDir =
|
|
289638
|
+
const repoRootDir = join92(rootDir, repoBranch.repo);
|
|
289453
289639
|
await runGitCommand3(["checkout", repoBranch.integrationBranch], repoRootDir, 1e4).catch(() => void 0);
|
|
289454
289640
|
await runGitCommand3(["branch", "-D", revertBranch], repoRootDir, 1e4).catch(() => void 0);
|
|
289455
289641
|
}
|
|
289456
289642
|
};
|
|
289457
289643
|
const targets = [];
|
|
289458
289644
|
for (const repoBranch of prepared.repos) {
|
|
289459
|
-
const gitRepo = getCurrentRepo(
|
|
289645
|
+
const gitRepo = getCurrentRepo(join92(rootDir, repoBranch.repo));
|
|
289460
289646
|
if (!gitRepo) {
|
|
289461
289647
|
await cleanupPreparedBranches();
|
|
289462
289648
|
res.json({
|
|
@@ -289499,7 +289685,7 @@ ${normalizedDescription}`;
|
|
|
289499
289685
|
resultRepos.push({ repo: target.repoBranch.repo, revertBranch, prUrl: prInfo2.url, prNumber: prInfo2.number, existingPr: true });
|
|
289500
289686
|
continue;
|
|
289501
289687
|
}
|
|
289502
|
-
await runGitCommand3(["push", "-u", "origin", revertBranch],
|
|
289688
|
+
await runGitCommand3(["push", "-u", "origin", revertBranch], join92(rootDir, target.repoBranch.repo), 6e4);
|
|
289503
289689
|
const prTitle = `revert(${task.id}): undo landed work (${target.repoBranch.repo})`;
|
|
289504
289690
|
const prBody = `This PR reverts the work landed by task ${task.id} in sub-repo \`${target.repoBranch.repo}\`.
|
|
289505
289691
|
|
|
@@ -289813,8 +289999,8 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
289813
289999
|
});
|
|
289814
290000
|
if (retrySpecification) {
|
|
289815
290001
|
const { rm: rm23 } = await import("node:fs/promises");
|
|
289816
|
-
const { join:
|
|
289817
|
-
const promptPath =
|
|
290002
|
+
const { join: join156 } = await import("node:path");
|
|
290003
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
289818
290004
|
await rm23(promptPath, { force: true });
|
|
289819
290005
|
await scopedStore.logEntry(req.params.id, "Retry requested from dashboard (planning retry budget reset)");
|
|
289820
290006
|
const updated2 = await scopedStore.getTask(req.params.id);
|
|
@@ -290526,10 +290712,10 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
290526
290712
|
await scopedStore.logEntry(task.id, "Plan approved by user");
|
|
290527
290713
|
let approvedPlanFingerprint;
|
|
290528
290714
|
try {
|
|
290529
|
-
const { readFile:
|
|
290530
|
-
const { join:
|
|
290531
|
-
const promptPath =
|
|
290532
|
-
const promptText2 = await
|
|
290715
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
290716
|
+
const { join: join156 } = await import("node:path");
|
|
290717
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
290718
|
+
const promptText2 = await readFile64(promptPath, "utf8");
|
|
290533
290719
|
approvedPlanFingerprint = computePlanApprovalFingerprint(promptText2);
|
|
290534
290720
|
} catch {
|
|
290535
290721
|
}
|
|
@@ -290562,8 +290748,8 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
290562
290748
|
await scopedStore.logEntry(task.id, "Plan rejected by user", "Specification will be regenerated");
|
|
290563
290749
|
await scopedStore.updateTask(task.id, { status: void 0, approvedPlanFingerprint: null });
|
|
290564
290750
|
const { rm: rm23 } = await import("node:fs/promises");
|
|
290565
|
-
const { join:
|
|
290566
|
-
const promptPath =
|
|
290751
|
+
const { join: join156 } = await import("node:path");
|
|
290752
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
290567
290753
|
await rm23(promptPath, { force: true });
|
|
290568
290754
|
const updated = await scopedStore.getTask(task.id);
|
|
290569
290755
|
res.json(updated);
|
|
@@ -290586,7 +290772,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
290586
290772
|
router.get("/tasks/:id/stranded-refinement", async (req, res) => {
|
|
290587
290773
|
try {
|
|
290588
290774
|
const { existsSync: existsSync118 } = await import("node:fs");
|
|
290589
|
-
const { join:
|
|
290775
|
+
const { join: join156 } = await import("node:path");
|
|
290590
290776
|
const { store: scopedStore } = await getProjectContext2(req);
|
|
290591
290777
|
const task = await scopedStore.getTask(req.params.id);
|
|
290592
290778
|
if (task.sourceType !== "task_refine") {
|
|
@@ -290602,7 +290788,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
290602
290788
|
nextRecoveryAt: task.nextRecoveryAt,
|
|
290603
290789
|
ageMs: Math.max(0, Date.now() - Date.parse(task.createdAt))
|
|
290604
290790
|
};
|
|
290605
|
-
const promptPath =
|
|
290791
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
290606
290792
|
const promptExists = existsSync118(promptPath);
|
|
290607
290793
|
const dependencyDetails = await Promise.all((task.dependencies ?? []).map(async (dependencyId) => {
|
|
290608
290794
|
try {
|
|
@@ -291221,8 +291407,8 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
291221
291407
|
if (task.column === "triage" || task.column === respecifyTarget) {
|
|
291222
291408
|
await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
|
|
291223
291409
|
const { rm: rm24 } = await import("node:fs/promises");
|
|
291224
|
-
const { join:
|
|
291225
|
-
const promptPath2 =
|
|
291410
|
+
const { join: join157 } = await import("node:path");
|
|
291411
|
+
const promptPath2 = join157(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
291226
291412
|
await rm24(promptPath2, { force: true });
|
|
291227
291413
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
291228
291414
|
const updated2 = await scopedStore.getTask(task.id);
|
|
@@ -291238,8 +291424,8 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
291238
291424
|
await scopedStore.logEntry(task.id, "AI spec revision requested", feedback);
|
|
291239
291425
|
const updated = await scopedStore.moveTask(task.id, respecifyTarget);
|
|
291240
291426
|
const { rm: rm23 } = await import("node:fs/promises");
|
|
291241
|
-
const { join:
|
|
291242
|
-
const promptPath =
|
|
291427
|
+
const { join: join156 } = await import("node:path");
|
|
291428
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
291243
291429
|
await rm23(promptPath, { force: true });
|
|
291244
291430
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
291245
291431
|
res.json(updated);
|
|
@@ -291272,8 +291458,8 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
291272
291458
|
});
|
|
291273
291459
|
}
|
|
291274
291460
|
const { rm: rm23 } = await import("node:fs/promises");
|
|
291275
|
-
const { join:
|
|
291276
|
-
const promptPath =
|
|
291461
|
+
const { join: join156 } = await import("node:path");
|
|
291462
|
+
const promptPath = join156(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md");
|
|
291277
291463
|
await rm23(promptPath, { force: true });
|
|
291278
291464
|
await scopedStore.updateTask(task.id, { status: "needs-replan" });
|
|
291279
291465
|
const updated = await scopedStore.getTask(task.id);
|
|
@@ -291659,7 +291845,7 @@ See \`GET /api/tasks/${task.id}/diff\` for the landed diff being reverted.
|
|
|
291659
291845
|
const task = await scopedStore.updateTask(req.params.id, updates);
|
|
291660
291846
|
if (dismissNearDuplicate === true && task.sourceMetadata?.duplicateSource === "triage-marker") {
|
|
291661
291847
|
const { rm: rm23 } = await import("node:fs/promises");
|
|
291662
|
-
await rm23(
|
|
291848
|
+
await rm23(join92(scopedStore.getRootDir(), ".fusion", "tasks", task.id, "PROMPT.md"), { force: true });
|
|
291663
291849
|
}
|
|
291664
291850
|
const manualUnlinkRequested = hasBodyField("githubTracking") && validatedGithubTracking !== null && typeof validatedGithubTracking === "object" && validatedGithubTracking.issue === null;
|
|
291665
291851
|
const disableRequested = hasBodyField("githubTracking") && validatedGithubTracking !== null && typeof validatedGithubTracking === "object" && validatedGithubTracking.enabled === false;
|
|
@@ -294524,7 +294710,7 @@ var init_chat_attachment_config = __esm({
|
|
|
294524
294710
|
});
|
|
294525
294711
|
|
|
294526
294712
|
// ../dashboard/src/chat-attachment-content.ts
|
|
294527
|
-
import { readFile as
|
|
294713
|
+
import { readFile as readFile45 } from "node:fs/promises";
|
|
294528
294714
|
import { basename as basename22, resolve as resolve46 } from "node:path";
|
|
294529
294715
|
function getAttachmentDirectory(rootDir, scope) {
|
|
294530
294716
|
if (scope.kind === "session") {
|
|
@@ -294570,7 +294756,7 @@ async function readChatAttachmentContents(rootDir, scope, attachments, diagnosti
|
|
|
294570
294756
|
const filePath = resolve46(attachmentDir, safeName);
|
|
294571
294757
|
try {
|
|
294572
294758
|
if (IMAGE_MIME_TYPES2.has(attachment.mimeType)) {
|
|
294573
|
-
const data2 = await
|
|
294759
|
+
const data2 = await readFile45(filePath);
|
|
294574
294760
|
const detectedMimeType = detectImageMimeFromBytes(data2);
|
|
294575
294761
|
const imageMimeType2 = detectedMimeType ?? attachment.mimeType;
|
|
294576
294762
|
if (detectedMimeType && detectedMimeType !== attachment.mimeType) {
|
|
@@ -294594,7 +294780,7 @@ async function readChatAttachmentContents(rootDir, scope, attachments, diagnosti
|
|
|
294594
294780
|
diagnostics9?.warn(`Skipping non-inlineable chat attachment '${attachment.filename}' (${attachment.mimeType}) for ${getScopeLabel(scope)}`);
|
|
294595
294781
|
continue;
|
|
294596
294782
|
}
|
|
294597
|
-
const data = await
|
|
294783
|
+
const data = await readFile45(filePath, "utf-8");
|
|
294598
294784
|
const text3 = data.length > CHAT_TEXT_INLINE_LIMIT ? `${data.slice(0, CHAT_TEXT_INLINE_LIMIT)}${TRUNCATION_SUFFIX}` : data;
|
|
294599
294785
|
attachmentContents.push({
|
|
294600
294786
|
originalName: attachment.originalName,
|
|
@@ -295253,7 +295439,7 @@ __export(chat_exports, {
|
|
|
295253
295439
|
import { EventEmitter as EventEmitter40 } from "node:events";
|
|
295254
295440
|
import { randomUUID as randomUUID53 } from "node:crypto";
|
|
295255
295441
|
import { existsSync as existsSync70 } from "node:fs";
|
|
295256
|
-
import { join as
|
|
295442
|
+
import { join as join93, resolve as resolve47, relative as relative20 } from "node:path";
|
|
295257
295443
|
import { SessionManager as SessionManager3 } from "@earendil-works/pi-coding-agent";
|
|
295258
295444
|
function __getChatDiagnostics() {
|
|
295259
295445
|
return _diagnostics;
|
|
@@ -295788,7 +295974,7 @@ function validateFilePath(basePath, filePath) {
|
|
|
295788
295974
|
throw new Error(`Access denied: Absolute paths not allowed`);
|
|
295789
295975
|
}
|
|
295790
295976
|
const resolvedBase = resolve47(basePath);
|
|
295791
|
-
const resolvedPath = resolve47(
|
|
295977
|
+
const resolvedPath = resolve47(join93(resolvedBase, decodedPath));
|
|
295792
295978
|
const relativePath = relative20(resolvedBase, resolvedPath);
|
|
295793
295979
|
if (relativePath.startsWith("..") || relativePath.startsWith("../") || relativePath === "..") {
|
|
295794
295980
|
throw new Error(`Access denied: Path traversal detected`);
|
|
@@ -297583,7 +297769,7 @@ var init_rate_limit = __esm({
|
|
|
297583
297769
|
import { randomUUID as randomUUID54 } from "node:crypto";
|
|
297584
297770
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
297585
297771
|
import { mkdir as mkdir30, rm as rm17, writeFile as writeFile33 } from "node:fs/promises";
|
|
297586
|
-
import { basename as basename23, join as
|
|
297772
|
+
import { basename as basename23, join as join94, resolve as resolve48 } from "node:path";
|
|
297587
297773
|
function resolveAttachmentPath(rootDir, sessionId, filename) {
|
|
297588
297774
|
const sessionDir = resolve48(rootDir, ".fusion", "chat-attachments", sessionId);
|
|
297589
297775
|
const safeName = basename23(filename);
|
|
@@ -297636,7 +297822,7 @@ function registerChatRoutes(ctx, deps) {
|
|
|
297636
297822
|
await mkdir30(sessionDir, { recursive: true });
|
|
297637
297823
|
const sanitizedFilename = (file.originalname || "attachment").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
297638
297824
|
const filename = `${Date.now()}-${sanitizedFilename}`;
|
|
297639
|
-
const filePath =
|
|
297825
|
+
const filePath = join94(sessionDir, filename);
|
|
297640
297826
|
await writeFile33(filePath, file.buffer);
|
|
297641
297827
|
return {
|
|
297642
297828
|
id: `att-${randomUUID54().slice(0, 8)}`,
|
|
@@ -298408,7 +298594,7 @@ var init_register_chat_routes = __esm({
|
|
|
298408
298594
|
import { randomUUID as randomUUID55 } from "node:crypto";
|
|
298409
298595
|
import { createReadStream as createReadStream3 } from "node:fs";
|
|
298410
298596
|
import { mkdir as mkdir31, writeFile as writeFile34 } from "node:fs/promises";
|
|
298411
|
-
import { basename as basename24, join as
|
|
298597
|
+
import { basename as basename24, join as join95, resolve as resolve49 } from "node:path";
|
|
298412
298598
|
function isSlugCollisionError(err) {
|
|
298413
298599
|
const message = err instanceof Error ? err.message.toLowerCase() : String(err).toLowerCase();
|
|
298414
298600
|
return message.includes("slug") || message.includes("exists");
|
|
@@ -298743,7 +298929,7 @@ function registerChatRoomRoutes(ctx, deps) {
|
|
|
298743
298929
|
await mkdir31(roomDir, { recursive: true });
|
|
298744
298930
|
const sanitizedFilename = (file.originalname || "attachment").replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
298745
298931
|
const filename = `${Date.now()}-${sanitizedFilename}`;
|
|
298746
|
-
const filePath =
|
|
298932
|
+
const filePath = join95(roomDir, filename);
|
|
298747
298933
|
await writeFile34(filePath, file.buffer);
|
|
298748
298934
|
const attachment = {
|
|
298749
298935
|
id: `att-${randomUUID55().slice(0, 8)}`,
|
|
@@ -307323,7 +307509,7 @@ var init_terminal = __esm({
|
|
|
307323
307509
|
});
|
|
307324
307510
|
|
|
307325
307511
|
// ../dashboard/src/file-service.ts
|
|
307326
|
-
import { join as
|
|
307512
|
+
import { join as join96, resolve as resolve52, relative as relative21, dirname as dirname38, basename as basename26 } from "node:path";
|
|
307327
307513
|
import { readdir as readdir10, readFile as fsReadFile2, writeFile as fsWriteFile, stat as stat13, copyFile as fsCopyFile, rename as fsRename, rm as fsRm, mkdir as mkdir33, access as access14 } from "node:fs/promises";
|
|
307328
307514
|
async function getTaskBasePath(store, taskId) {
|
|
307329
307515
|
try {
|
|
@@ -307336,7 +307522,7 @@ async function getTaskBasePath(store, taskId) {
|
|
|
307336
307522
|
}
|
|
307337
307523
|
}
|
|
307338
307524
|
const rootDir = store.getRootDir();
|
|
307339
|
-
return resolve52(
|
|
307525
|
+
return resolve52(join96(rootDir, ".fusion", "tasks", taskId));
|
|
307340
307526
|
} catch (err) {
|
|
307341
307527
|
const error3 = err;
|
|
307342
307528
|
if (error3.code === "ENOENT" || error3.message && error3.message.includes("not found")) {
|
|
@@ -307368,7 +307554,7 @@ function validatePath(basePath, filePath, options = {}) {
|
|
|
307368
307554
|
throw new FileServiceError(`Access denied: Absolute paths not allowed`, "EINVAL");
|
|
307369
307555
|
}
|
|
307370
307556
|
const resolvedBase = resolve52(basePath);
|
|
307371
|
-
const resolvedPath = resolve52(
|
|
307557
|
+
const resolvedPath = resolve52(join96(resolvedBase, filePath));
|
|
307372
307558
|
const relativePath = relative21(resolvedBase, resolvedPath);
|
|
307373
307559
|
if (relativePath.startsWith("..") || relativePath.startsWith("../") || relativePath === "..") {
|
|
307374
307560
|
throw new FileServiceError(`Access denied: Path traversal detected`, "EINVAL");
|
|
@@ -307409,7 +307595,7 @@ async function listFilesForBasePath(basePath, subPath, options = {}) {
|
|
|
307409
307595
|
const entries = await readdir10(targetPath, { withFileTypes: true });
|
|
307410
307596
|
const fileNodes = [];
|
|
307411
307597
|
for (const entry of entries) {
|
|
307412
|
-
const entryPath =
|
|
307598
|
+
const entryPath = join96(targetPath, entry.name);
|
|
307413
307599
|
const entryStats = await stat13(entryPath);
|
|
307414
307600
|
fileNodes.push({
|
|
307415
307601
|
name: entry.name,
|
|
@@ -307535,7 +307721,7 @@ async function listFiles2(store, taskId, subPath) {
|
|
|
307535
307721
|
const taskBase = await getTaskBasePath(store, taskId);
|
|
307536
307722
|
return listFilesForBasePath(taskBase, subPath);
|
|
307537
307723
|
}
|
|
307538
|
-
async function
|
|
307724
|
+
async function readFile46(store, taskId, filePath) {
|
|
307539
307725
|
const taskBase = await getTaskBasePath(store, taskId);
|
|
307540
307726
|
return readFileForBasePath(taskBase, filePath);
|
|
307541
307727
|
}
|
|
@@ -307790,7 +307976,7 @@ async function renameWorkspaceFile(store, workspace, filePath, newName) {
|
|
|
307790
307976
|
}
|
|
307791
307977
|
throw err;
|
|
307792
307978
|
}
|
|
307793
|
-
const destPath =
|
|
307979
|
+
const destPath = join96(dirname38(resolvedPath), newName);
|
|
307794
307980
|
if (pathOptions.allowAbsolutePaths !== true || !filePath.startsWith("/")) {
|
|
307795
307981
|
const destRelative = relative21(resolve52(workspaceBase), destPath);
|
|
307796
307982
|
if (destRelative.startsWith("..") || destRelative.startsWith("../") || destRelative === "..") {
|
|
@@ -307887,7 +308073,7 @@ function isHiddenPathSegment(name2) {
|
|
|
307887
308073
|
return name2.startsWith(".");
|
|
307888
308074
|
}
|
|
307889
308075
|
async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
307890
|
-
const currentPath = currentRelative ?
|
|
308076
|
+
const currentPath = currentRelative ? join96(basePath, currentRelative) : basePath;
|
|
307891
308077
|
let entries;
|
|
307892
308078
|
try {
|
|
307893
308079
|
entries = await readdir10(currentPath, { withFileTypes: true });
|
|
@@ -307895,7 +308081,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
|
307895
308081
|
return;
|
|
307896
308082
|
}
|
|
307897
308083
|
for (const entry of entries) {
|
|
307898
|
-
const entryRelativePath = currentRelative ?
|
|
308084
|
+
const entryRelativePath = currentRelative ? join96(currentRelative, entry.name) : entry.name;
|
|
307899
308085
|
if (entry.isDirectory()) {
|
|
307900
308086
|
if (MARKDOWN_SCAN_EXCLUDED_DIRS.has(entry.name)) {
|
|
307901
308087
|
continue;
|
|
@@ -307912,7 +308098,7 @@ async function walkDirForMarkdown(basePath, currentRelative, results, options) {
|
|
|
307912
308098
|
if (!options.showHidden && isHiddenPathSegment(entry.name)) {
|
|
307913
308099
|
continue;
|
|
307914
308100
|
}
|
|
307915
|
-
const fullPath =
|
|
308101
|
+
const fullPath = join96(basePath, entryRelativePath);
|
|
307916
308102
|
let fileStats;
|
|
307917
308103
|
try {
|
|
307918
308104
|
fileStats = await stat13(fullPath);
|
|
@@ -307962,7 +308148,7 @@ async function scanMarkdownFiles(store, options) {
|
|
|
307962
308148
|
return;
|
|
307963
308149
|
}
|
|
307964
308150
|
for (const entry of entries) {
|
|
307965
|
-
const entryRelativePath = relativeDir ?
|
|
308151
|
+
const entryRelativePath = relativeDir ? join96(relativeDir, entry.name) : entry.name;
|
|
307966
308152
|
let shouldRecurse = entry.isDirectory();
|
|
307967
308153
|
if (!shouldRecurse && typeof entry.isSymbolicLink === "function" && entry.isSymbolicLink()) {
|
|
307968
308154
|
let symlinkPath;
|
|
@@ -308052,8 +308238,8 @@ async function searchWorkspaceFiles(store, workspace, query) {
|
|
|
308052
308238
|
if (entry.isDirectory() && EXCLUDED_DIRS.has(entry.name)) {
|
|
308053
308239
|
continue;
|
|
308054
308240
|
}
|
|
308055
|
-
const fullPath =
|
|
308056
|
-
const relPath =
|
|
308241
|
+
const fullPath = join96(dir2, entry.name);
|
|
308242
|
+
const relPath = join96(relativeDir, entry.name);
|
|
308057
308243
|
if (entry.isFile()) {
|
|
308058
308244
|
if (entry.name.toLowerCase().includes(lowerQuery)) {
|
|
308059
308245
|
results.push({
|
|
@@ -308074,8 +308260,8 @@ async function copyDirectoryRecursive(source, destination) {
|
|
|
308074
308260
|
await mkdir33(destination, { recursive: true });
|
|
308075
308261
|
const entries = await readdir10(source, { withFileTypes: true });
|
|
308076
308262
|
for (const entry of entries) {
|
|
308077
|
-
const sourcePath =
|
|
308078
|
-
const destPath =
|
|
308263
|
+
const sourcePath = join96(source, entry.name);
|
|
308264
|
+
const destPath = join96(destination, entry.name);
|
|
308079
308265
|
if (entry.isDirectory()) {
|
|
308080
308266
|
await copyDirectoryRecursive(sourcePath, destPath);
|
|
308081
308267
|
} else {
|
|
@@ -311364,7 +311550,7 @@ var require_BufferList = __commonJS({
|
|
|
311364
311550
|
this.head = this.tail = null;
|
|
311365
311551
|
this.length = 0;
|
|
311366
311552
|
};
|
|
311367
|
-
BufferList.prototype.join = function
|
|
311553
|
+
BufferList.prototype.join = function join156(s3) {
|
|
311368
311554
|
if (this.length === 0) return "";
|
|
311369
311555
|
var p2 = this.head;
|
|
311370
311556
|
var ret = "" + p2.data;
|
|
@@ -332924,7 +333110,7 @@ function registerFileWorkspaceRoutes(ctx) {
|
|
|
332924
333110
|
try {
|
|
332925
333111
|
const { store: scopedStore } = await getProjectContext2(req);
|
|
332926
333112
|
const filePath = Array.isArray(req.params.filepath) ? req.params.filepath[0] : req.params.filepath ?? "";
|
|
332927
|
-
const result2 = await
|
|
333113
|
+
const result2 = await readFile46(scopedStore, req.params.id, filePath);
|
|
332928
333114
|
res.json(result2);
|
|
332929
333115
|
} catch (err) {
|
|
332930
333116
|
if (err instanceof ApiError) {
|
|
@@ -333393,7 +333579,7 @@ var init_attribute_done_range_files = __esm({
|
|
|
333393
333579
|
|
|
333394
333580
|
// ../dashboard/src/routes/register-session-diff-routes.ts
|
|
333395
333581
|
import { access as access16 } from "node:fs/promises";
|
|
333396
|
-
import { join as
|
|
333582
|
+
import { join as join97 } from "node:path";
|
|
333397
333583
|
async function worktreeStillBelongsToTask(worktree, expectedBranch) {
|
|
333398
333584
|
if (!expectedBranch) return true;
|
|
333399
333585
|
try {
|
|
@@ -333711,7 +333897,7 @@ async function computeWorkspaceTaskFiles(task, rootDir, timeoutMs) {
|
|
|
333711
333897
|
}
|
|
333712
333898
|
}
|
|
333713
333899
|
if (repoFiles.length === 0 && entry.baseCommitSha && entry.landedSha) {
|
|
333714
|
-
const repoRootDir =
|
|
333900
|
+
const repoRootDir = join97(rootDir, repoRel);
|
|
333715
333901
|
try {
|
|
333716
333902
|
const rangeFiles = await collectDoneRangeFiles(`${entry.baseCommitSha}..${entry.landedSha}`, repoRootDir);
|
|
333717
333903
|
repoFiles = rangeFiles.map((file) => ({
|
|
@@ -334658,7 +334844,7 @@ var init_exec_file = __esm({
|
|
|
334658
334844
|
|
|
334659
334845
|
// ../dashboard/src/lib/codebase-metrics.ts
|
|
334660
334846
|
import { spawn as spawn12 } from "node:child_process";
|
|
334661
|
-
import { lstat as lstat2, readdir as readdir11, readFile as
|
|
334847
|
+
import { lstat as lstat2, readdir as readdir11, readFile as readFile47, realpath as realpath2 } from "node:fs/promises";
|
|
334662
334848
|
import { basename as basename27, resolve as resolve53, sep as sep14 } from "node:path";
|
|
334663
334849
|
function countPreTokenPieces(text3) {
|
|
334664
334850
|
let pieces = 0;
|
|
@@ -334808,7 +334994,7 @@ async function computeCodebaseMetrics(rootDir, options = {}) {
|
|
|
334808
334994
|
truncated = true;
|
|
334809
334995
|
break;
|
|
334810
334996
|
}
|
|
334811
|
-
const contents = await
|
|
334997
|
+
const contents = await readFile47(candidate);
|
|
334812
334998
|
if (isBinary(contents)) continue;
|
|
334813
334999
|
sourceByteCount += contents.length;
|
|
334814
335000
|
sourceFileCount++;
|
|
@@ -334875,7 +335061,7 @@ var init_codebase_metrics = __esm({
|
|
|
334875
335061
|
|
|
334876
335062
|
// ../dashboard/src/routes/register-project-routes.ts
|
|
334877
335063
|
import * as fsPromises from "node:fs/promises";
|
|
334878
|
-
import { dirname as dirname39, isAbsolute as isAbsolute26, join as
|
|
335064
|
+
import { dirname as dirname39, isAbsolute as isAbsolute26, join as join98 } from "node:path";
|
|
334879
335065
|
var access17, stat14, mkdir34, readdir12, rm18, registerProjectRoutes;
|
|
334880
335066
|
var init_register_project_routes = __esm({
|
|
334881
335067
|
"../dashboard/src/routes/register-project-routes.ts"() {
|
|
@@ -335149,7 +335335,7 @@ var init_register_project_routes = __esm({
|
|
|
335149
335335
|
}
|
|
335150
335336
|
}
|
|
335151
335337
|
let hasFusionDir = false;
|
|
335152
|
-
const fusionDirPath =
|
|
335338
|
+
const fusionDirPath = join98(normalizedPath, ".fusion");
|
|
335153
335339
|
try {
|
|
335154
335340
|
await access17(fusionDirPath);
|
|
335155
335341
|
hasFusionDir = true;
|
|
@@ -335264,9 +335450,9 @@ var init_register_project_routes = __esm({
|
|
|
335264
335450
|
const entries = await readdir12(searchPath, { withFileTypes: true });
|
|
335265
335451
|
for (const entry of entries) {
|
|
335266
335452
|
if (!entry.isDirectory()) continue;
|
|
335267
|
-
const dirPath =
|
|
335268
|
-
const fusionDir =
|
|
335269
|
-
if (readProjectIdentity(fusionDir) !== null || isValidSqliteDatabaseFile(
|
|
335453
|
+
const dirPath = join98(searchPath, entry.name);
|
|
335454
|
+
const fusionDir = join98(dirPath, ".fusion");
|
|
335455
|
+
if (readProjectIdentity(fusionDir) !== null || isValidSqliteDatabaseFile(join98(fusionDir, "fusion.db"))) {
|
|
335270
335456
|
detected.push({
|
|
335271
335457
|
path: dirPath,
|
|
335272
335458
|
suggestedName: entry.name,
|
|
@@ -342633,7 +342819,7 @@ var init_register_secrets_sync_inbound_routes = __esm({
|
|
|
342633
342819
|
});
|
|
342634
342820
|
|
|
342635
342821
|
// ../dashboard/src/routes/register-agent-core-routes.ts
|
|
342636
|
-
import { mkdir as mkdir35, readdir as readdir13, readFile as
|
|
342822
|
+
import { mkdir as mkdir35, readdir as readdir13, readFile as readFile48, rm as rm19, writeFile as writeFile36 } from "node:fs/promises";
|
|
342637
342823
|
import path8 from "node:path";
|
|
342638
342824
|
function parsePermissionsInput(input) {
|
|
342639
342825
|
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
@@ -343068,7 +343254,7 @@ function registerAgentCoreRoutes(ctx, deps) {
|
|
|
343068
343254
|
if (!mimeType) {
|
|
343069
343255
|
throw notFound("Avatar not found");
|
|
343070
343256
|
}
|
|
343071
|
-
const fileBuffer = await
|
|
343257
|
+
const fileBuffer = await readFile48(path8.join(agentDir, avatarFile));
|
|
343072
343258
|
res.setHeader("Content-Type", mimeType);
|
|
343073
343259
|
res.setHeader("Cache-Control", "public, max-age=3600");
|
|
343074
343260
|
res.send(fileBuffer);
|
|
@@ -345723,7 +345909,7 @@ Rules:
|
|
|
345723
345909
|
import { createWriteStream } from "node:fs";
|
|
345724
345910
|
import * as fsPromises2 from "node:fs/promises";
|
|
345725
345911
|
import { tmpdir as tmpdir14 } from "node:os";
|
|
345726
|
-
import { join as
|
|
345912
|
+
import { join as join99, resolve as resolve54 } from "node:path";
|
|
345727
345913
|
import { Readable } from "node:stream";
|
|
345728
345914
|
import { pipeline as streamPipeline } from "node:stream/promises";
|
|
345729
345915
|
function registerAgentImportExportRoutes(ctx) {
|
|
@@ -345764,7 +345950,7 @@ function registerAgentImportExportRoutes(ctx) {
|
|
|
345764
345950
|
} else if (typeof outputDir === "string") {
|
|
345765
345951
|
throw badRequest("outputDir cannot be empty");
|
|
345766
345952
|
} else {
|
|
345767
|
-
resolvedOutputDir = await mkdtemp7(
|
|
345953
|
+
resolvedOutputDir = await mkdtemp7(join99(tmpdir14(), "fusion-agent-export-"));
|
|
345768
345954
|
}
|
|
345769
345955
|
const result2 = await exportAgentsToDirectory2(agentsToExport, resolvedOutputDir, {
|
|
345770
345956
|
companyName: typeof companyName === "string" ? companyName : void 0,
|
|
@@ -345923,7 +346109,7 @@ ${body}`;
|
|
|
345923
346109
|
return result2;
|
|
345924
346110
|
}
|
|
345925
346111
|
const safeCompanySlug = companySlug ? slugifyPathSegment2(companySlug, "unknown-company") : "unknown-company";
|
|
345926
|
-
const skillsBaseDir =
|
|
346112
|
+
const skillsBaseDir = join99(projectRoot, "skills", "imported", safeCompanySlug);
|
|
345927
346113
|
const usedSlugs = /* @__PURE__ */ new Set();
|
|
345928
346114
|
for (const skill of skills) {
|
|
345929
346115
|
const name2 = typeof skill.name === "string" && skill.name.trim().length > 0 ? skill.name.trim() : null;
|
|
@@ -345940,8 +346126,8 @@ ${body}`;
|
|
|
345940
346126
|
skillSlug = `${skillSlug}-${counter2}`;
|
|
345941
346127
|
}
|
|
345942
346128
|
usedSlugs.add(skillSlug);
|
|
345943
|
-
const skillDir =
|
|
345944
|
-
const skillPath =
|
|
346129
|
+
const skillDir = join99(skillsBaseDir, skillSlug);
|
|
346130
|
+
const skillPath = join99(skillDir, "SKILL.md");
|
|
345945
346131
|
try {
|
|
345946
346132
|
await access18(skillPath);
|
|
345947
346133
|
result2.skipped.push(name2);
|
|
@@ -346115,8 +346301,8 @@ ${body}`;
|
|
|
346115
346301
|
const archiveUrl = `https://github.com/${repoOwner}/${repoName}/archive/refs/heads/${preferredBranch}.tar.gz`;
|
|
346116
346302
|
let tempDir = null;
|
|
346117
346303
|
try {
|
|
346118
|
-
tempDir = await mkdtemp7(
|
|
346119
|
-
const archivePath =
|
|
346304
|
+
tempDir = await mkdtemp7(join99(tmpdir14(), `fn-agent-import-${importCompanySlug}-`));
|
|
346305
|
+
const archivePath = join99(tempDir, "archive.tar.gz");
|
|
346120
346306
|
const downloadController = new AbortController();
|
|
346121
346307
|
const downloadTimeout = setTimeout(() => downloadController.abort(), 3e4);
|
|
346122
346308
|
let archiveResponse;
|
|
@@ -347755,12 +347941,12 @@ import {
|
|
|
347755
347941
|
unlinkSync as unlinkSync4
|
|
347756
347942
|
} from "node:fs";
|
|
347757
347943
|
import { homedir as homedir14 } from "node:os";
|
|
347758
|
-
import { basename as basename29, dirname as dirname40, join as
|
|
347944
|
+
import { basename as basename29, dirname as dirname40, join as join100, resolve as resolve55 } from "node:path";
|
|
347759
347945
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
347760
347946
|
function resolveHermesHome(profile) {
|
|
347761
|
-
const base = process.env.HERMES_HOME ??
|
|
347947
|
+
const base = process.env.HERMES_HOME ?? join100(homedir14(), ".hermes");
|
|
347762
347948
|
if (!profile || profile === "default") return base;
|
|
347763
|
-
return
|
|
347949
|
+
return join100(base, "profiles", profile);
|
|
347764
347950
|
}
|
|
347765
347951
|
function getFusionSkillSourceCandidates(moduleUrl = import.meta.url) {
|
|
347766
347952
|
const here = fileURLToPath6(moduleUrl);
|
|
@@ -347775,13 +347961,13 @@ function getFusionSkillSourceCandidates(moduleUrl = import.meta.url) {
|
|
|
347775
347961
|
function resolveBundledFusionSkillSource() {
|
|
347776
347962
|
const candidates = getFusionSkillSourceCandidates();
|
|
347777
347963
|
for (const candidate of candidates) {
|
|
347778
|
-
if (existsSync72(
|
|
347964
|
+
if (existsSync72(join100(candidate, "SKILL.md"))) return candidate;
|
|
347779
347965
|
}
|
|
347780
347966
|
return null;
|
|
347781
347967
|
}
|
|
347782
347968
|
function installFusionSkillIntoHermesHome(options = {}) {
|
|
347783
347969
|
const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource();
|
|
347784
|
-
const targetDir =
|
|
347970
|
+
const targetDir = join100(resolveHermesHome(options.profile), "skills", FUSION_SKILL_NAME);
|
|
347785
347971
|
if (!sourceDir) {
|
|
347786
347972
|
return {
|
|
347787
347973
|
outcome: "warning",
|
|
@@ -347870,7 +348056,7 @@ function isBrokenSymlink(path14) {
|
|
|
347870
348056
|
}
|
|
347871
348057
|
}
|
|
347872
348058
|
function looksLikePriorFusionInstall(path14) {
|
|
347873
|
-
const skillMd =
|
|
348059
|
+
const skillMd = join100(path14, "SKILL.md");
|
|
347874
348060
|
if (!existsSync72(skillMd)) return false;
|
|
347875
348061
|
try {
|
|
347876
348062
|
const body = readFileSync28(skillMd, "utf-8");
|
|
@@ -347882,7 +348068,7 @@ function looksLikePriorFusionInstall(path14) {
|
|
|
347882
348068
|
function looksLikeFusionSkillTarget(path14) {
|
|
347883
348069
|
if (!path14) return false;
|
|
347884
348070
|
if (basename29(path14).toLowerCase() === FUSION_SKILL_NAME) return true;
|
|
347885
|
-
return existsSync72(
|
|
348071
|
+
return existsSync72(join100(path14, "SKILL.md"));
|
|
347886
348072
|
}
|
|
347887
348073
|
var FUSION_SKILL_NAME;
|
|
347888
348074
|
var init_fusion_skill_install = __esm({
|
|
@@ -348150,7 +348336,7 @@ var init_src8 = __esm({
|
|
|
348150
348336
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/pi-module.ts
|
|
348151
348337
|
import { spawn as spawn15 } from "node:child_process";
|
|
348152
348338
|
import { randomUUID as randomUUID60 } from "node:crypto";
|
|
348153
|
-
import { readFile as
|
|
348339
|
+
import { readFile as readFile49 } from "node:fs/promises";
|
|
348154
348340
|
function asString2(v2) {
|
|
348155
348341
|
return typeof v2 === "string" && v2.trim() !== "" ? v2.trim() : void 0;
|
|
348156
348342
|
}
|
|
@@ -348221,7 +348407,7 @@ function createCliSession(opts) {
|
|
|
348221
348407
|
};
|
|
348222
348408
|
}
|
|
348223
348409
|
async function configureOpenClawMcpServer(opts) {
|
|
348224
|
-
const serverValue = await
|
|
348410
|
+
const serverValue = await readFile49(opts.serverConfigPath, "utf-8");
|
|
348225
348411
|
await new Promise((resolve103, reject2) => {
|
|
348226
348412
|
const child = spawn15(opts.binaryPath, ["--no-color", "--profile", opts.profile, "mcp", "set", opts.serverName, serverValue], {
|
|
348227
348413
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -348365,7 +348551,7 @@ var init_pi_module = __esm({
|
|
|
348365
348551
|
// ../../plugins/fusion-plugin-openclaw-runtime/src/mcp-config.ts
|
|
348366
348552
|
import { writeFileSync as writeFileSync13 } from "node:fs";
|
|
348367
348553
|
import { tmpdir as tmpdir15 } from "node:os";
|
|
348368
|
-
import { join as
|
|
348554
|
+
import { join as join101 } from "node:path";
|
|
348369
348555
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
348370
348556
|
import { dirname as dirname41 } from "node:path";
|
|
348371
348557
|
function toolsToMcpToolDefs(tools) {
|
|
@@ -348378,16 +348564,16 @@ function toolsToMcpToolDefs(tools) {
|
|
|
348378
348564
|
}
|
|
348379
348565
|
function writeOpenClawMcpBridgeFiles(toolDefs, cacheKey) {
|
|
348380
348566
|
const suffix = cacheKey ? `${process.pid}-${cacheKey}` : `${process.pid}`;
|
|
348381
|
-
const schemaPath =
|
|
348567
|
+
const schemaPath = join101(tmpdir15(), `openclaw-runtime-mcp-schemas-${suffix}.json`);
|
|
348382
348568
|
writeFileSync13(schemaPath, JSON.stringify(toolDefs));
|
|
348383
348569
|
const __filename = fileURLToPath7(import.meta.url);
|
|
348384
348570
|
const __dirname3 = dirname41(__filename);
|
|
348385
|
-
const serverPath =
|
|
348571
|
+
const serverPath = join101(__dirname3, "mcp-schema-server.cjs");
|
|
348386
348572
|
const serverConfig = {
|
|
348387
348573
|
command: "node",
|
|
348388
348574
|
args: [serverPath, schemaPath]
|
|
348389
348575
|
};
|
|
348390
|
-
const serverConfigPath =
|
|
348576
|
+
const serverConfigPath = join101(tmpdir15(), `openclaw-runtime-mcp-server-${suffix}.json`);
|
|
348391
348577
|
writeFileSync13(serverConfigPath, JSON.stringify(serverConfig));
|
|
348392
348578
|
return {
|
|
348393
348579
|
schemaPath,
|
|
@@ -348619,7 +348805,7 @@ var init_src9 = __esm({
|
|
|
348619
348805
|
});
|
|
348620
348806
|
|
|
348621
348807
|
// ../dashboard/src/routes/plugin-bundled-runtimes.ts
|
|
348622
|
-
import { resolve as resolve56, join as
|
|
348808
|
+
import { resolve as resolve56, join as join102 } from "node:path";
|
|
348623
348809
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
348624
348810
|
import * as nodeFs from "node:fs";
|
|
348625
348811
|
function extractBundledPluginId(pathInput) {
|
|
@@ -348638,12 +348824,12 @@ function resolveBundledPluginDirInDashboard(pluginId) {
|
|
|
348638
348824
|
const moduleDir = resolve56(fileURLToPath8(import.meta.url), "..");
|
|
348639
348825
|
const dashboardPackageRoot = resolve56(moduleDir, "..");
|
|
348640
348826
|
const candidates = [
|
|
348641
|
-
|
|
348642
|
-
|
|
348643
|
-
|
|
348827
|
+
join102(dashboardPackageRoot, "dist", "plugins", pluginId),
|
|
348828
|
+
join102(dashboardPackageRoot, "plugins", pluginId),
|
|
348829
|
+
join102(dashboardPackageRoot, "..", "..", "plugins", pluginId)
|
|
348644
348830
|
];
|
|
348645
348831
|
for (const candidate of candidates) {
|
|
348646
|
-
if (nodeFs.existsSync(
|
|
348832
|
+
if (nodeFs.existsSync(join102(candidate, "manifest.json"))) {
|
|
348647
348833
|
return candidate;
|
|
348648
348834
|
}
|
|
348649
348835
|
}
|
|
@@ -350735,9 +350921,9 @@ var init_cli_spawn3 = __esm({
|
|
|
350735
350921
|
});
|
|
350736
350922
|
|
|
350737
350923
|
// ../../plugins/fusion-plugin-grok-runtime/src/probe.ts
|
|
350738
|
-
import { readFile as
|
|
350924
|
+
import { readFile as readFile50 } from "node:fs/promises";
|
|
350739
350925
|
import { homedir as homedir15 } from "node:os";
|
|
350740
|
-
import { join as
|
|
350926
|
+
import { join as join103 } from "node:path";
|
|
350741
350927
|
function buildCandidates2(binaryPath) {
|
|
350742
350928
|
const configuredBinaryPath = binaryPath?.trim() || void 0;
|
|
350743
350929
|
const ordered = configuredBinaryPath ? [configuredBinaryPath, ...CANDIDATES3] : [...CANDIDATES3];
|
|
@@ -350754,10 +350940,10 @@ async function probeGrokApiKeyPresence() {
|
|
|
350754
350940
|
if (typeof envKey === "string" && envKey.trim().length > 0) {
|
|
350755
350941
|
return { detected: true };
|
|
350756
350942
|
}
|
|
350757
|
-
const settingsPath =
|
|
350943
|
+
const settingsPath = join103(homedir15(), ".grok", "user-settings.json");
|
|
350758
350944
|
let raw;
|
|
350759
350945
|
try {
|
|
350760
|
-
raw = await
|
|
350946
|
+
raw = await readFile50(settingsPath, "utf-8");
|
|
350761
350947
|
} catch {
|
|
350762
350948
|
return { detected: false, reason: "No Grok API key detected by Fusion (GROK_API_KEY unset, ~/.grok/user-settings.json not found); the CLI will use its own credentials." };
|
|
350763
350949
|
}
|
|
@@ -350906,7 +351092,7 @@ var init_provider2 = __esm({
|
|
|
350906
351092
|
|
|
350907
351093
|
// ../../plugins/fusion-plugin-grok-runtime/src/acp/cli-spawn.ts
|
|
350908
351094
|
import { existsSync as existsSync74 } from "node:fs";
|
|
350909
|
-
import { dirname as dirname42, isAbsolute as isAbsolute28, join as
|
|
351095
|
+
import { dirname as dirname42, isAbsolute as isAbsolute28, join as join104, resolve as resolve58 } from "node:path";
|
|
350910
351096
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
350911
351097
|
function asTrimmedString(value) {
|
|
350912
351098
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
@@ -350924,7 +351110,7 @@ function pluginRootDir() {
|
|
|
350924
351110
|
}
|
|
350925
351111
|
function bundledClaudeBridgeBinPath(pluginRoot = pluginRootDir()) {
|
|
350926
351112
|
const extension = process.platform === "win32" ? ".cmd" : "";
|
|
350927
|
-
return
|
|
351113
|
+
return join104(pluginRoot, "node_modules", ".bin", `${CLAUDE_CODE_CLI_ACP_BINARY}${extension}`);
|
|
350928
351114
|
}
|
|
350929
351115
|
function resolveBundledClaudeBridgeBinary(options = {}) {
|
|
350930
351116
|
const root = options.pluginRoot ?? pluginRootDir();
|
|
@@ -352287,10 +352473,10 @@ import {
|
|
|
352287
352473
|
} from "node:fs";
|
|
352288
352474
|
import { createRequire as createRequire8 } from "node:module";
|
|
352289
352475
|
import { tmpdir as tmpdir16 } from "node:os";
|
|
352290
|
-
import { basename as basename31, dirname as dirname44, join as
|
|
352476
|
+
import { basename as basename31, dirname as dirname44, join as join106, resolve as resolve60 } from "node:path";
|
|
352291
352477
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
352292
352478
|
function isSkillDir(dir2) {
|
|
352293
|
-
return existsSync75(
|
|
352479
|
+
return existsSync75(join106(dir2, "SKILL.md"));
|
|
352294
352480
|
}
|
|
352295
352481
|
function pushUnique(out, candidate) {
|
|
352296
352482
|
if (!candidate) return;
|
|
@@ -352298,8 +352484,8 @@ function pushUnique(out, candidate) {
|
|
|
352298
352484
|
if (!out.includes(resolved)) out.push(resolved);
|
|
352299
352485
|
}
|
|
352300
352486
|
function pushSkillLayoutsAtRoot(out, root) {
|
|
352301
|
-
pushUnique(out,
|
|
352302
|
-
pushUnique(out,
|
|
352487
|
+
pushUnique(out, join106(root, "skill", FUSION_SKILL_NAME2));
|
|
352488
|
+
pushUnique(out, join106(root, "packages", "cli", "skill", FUSION_SKILL_NAME2));
|
|
352303
352489
|
}
|
|
352304
352490
|
function walkAncestorSkillCandidates(out, startDir, maxParents = 8) {
|
|
352305
352491
|
let dir2 = startDir;
|
|
@@ -352314,7 +352500,7 @@ function pushPackageRequireCandidates(out, from) {
|
|
|
352314
352500
|
try {
|
|
352315
352501
|
const require6 = createRequire8(from);
|
|
352316
352502
|
const pkgJson = require6.resolve("@runfusion/fusion/package.json");
|
|
352317
|
-
pushUnique(out,
|
|
352503
|
+
pushUnique(out, join106(dirname44(pkgJson), "skill", FUSION_SKILL_NAME2));
|
|
352318
352504
|
} catch {
|
|
352319
352505
|
}
|
|
352320
352506
|
}
|
|
@@ -352382,21 +352568,21 @@ function collectSkillsFromRoot(root, out) {
|
|
|
352382
352568
|
return;
|
|
352383
352569
|
}
|
|
352384
352570
|
for (const entry of entries) {
|
|
352385
|
-
const child =
|
|
352571
|
+
const child = join106(root, entry);
|
|
352386
352572
|
if (isSkillDir(child)) {
|
|
352387
352573
|
out.set(entry, child);
|
|
352388
352574
|
}
|
|
352389
352575
|
}
|
|
352390
352576
|
}
|
|
352391
352577
|
function stageGrokSessionSkills(options = {}) {
|
|
352392
|
-
const pluginDir = mkdtempSync3(
|
|
352393
|
-
const skillsDir =
|
|
352578
|
+
const pluginDir = mkdtempSync3(join106(tmpdir16(), "fusion-grok-plugin-"));
|
|
352579
|
+
const skillsDir = join106(pluginDir, "skills");
|
|
352394
352580
|
mkdirSync14(skillsDir, { recursive: true });
|
|
352395
352581
|
const installed = /* @__PURE__ */ new Map();
|
|
352396
352582
|
const includeFusion = options.includeFusionSkill !== false;
|
|
352397
352583
|
if (includeFusion) {
|
|
352398
352584
|
const fusionSource = resolveBundledFusionSkillSource2();
|
|
352399
|
-
if (fusionSource && installSkillDir(fusionSource,
|
|
352585
|
+
if (fusionSource && installSkillDir(fusionSource, join106(skillsDir, FUSION_SKILL_NAME2))) {
|
|
352400
352586
|
installed.set(FUSION_SKILL_NAME2, fusionSource);
|
|
352401
352587
|
}
|
|
352402
352588
|
}
|
|
@@ -352406,15 +352592,15 @@ function stageGrokSessionSkills(options = {}) {
|
|
|
352406
352592
|
}
|
|
352407
352593
|
for (const [name2, source] of installed) {
|
|
352408
352594
|
if (name2 === FUSION_SKILL_NAME2 && includeFusion) continue;
|
|
352409
|
-
installSkillDir(source,
|
|
352595
|
+
installSkillDir(source, join106(skillsDir, name2));
|
|
352410
352596
|
}
|
|
352411
352597
|
for (const [name2, source] of installed) {
|
|
352412
|
-
if (!existsSync75(
|
|
352413
|
-
installSkillDir(source,
|
|
352598
|
+
if (!existsSync75(join106(skillsDir, name2))) {
|
|
352599
|
+
installSkillDir(source, join106(skillsDir, name2));
|
|
352414
352600
|
}
|
|
352415
352601
|
}
|
|
352416
352602
|
writeFileSync14(
|
|
352417
|
-
|
|
352603
|
+
join106(pluginDir, "plugin.json"),
|
|
352418
352604
|
JSON.stringify(
|
|
352419
352605
|
{
|
|
352420
352606
|
name: "fusion-session-skills",
|
|
@@ -352480,7 +352666,7 @@ var init_skill_loader = __esm({
|
|
|
352480
352666
|
import { createServer as createServer2 } from "node:http";
|
|
352481
352667
|
import { existsSync as existsSync76, writeFileSync as writeFileSync15 } from "node:fs";
|
|
352482
352668
|
import { tmpdir as tmpdir17 } from "node:os";
|
|
352483
|
-
import { dirname as dirname45, join as
|
|
352669
|
+
import { dirname as dirname45, join as join107 } from "node:path";
|
|
352484
352670
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
352485
352671
|
import { randomUUID as randomUUID62 } from "node:crypto";
|
|
352486
352672
|
function toolsToMcpToolDefs2(tools) {
|
|
@@ -352492,7 +352678,7 @@ function toolsToMcpToolDefs2(tools) {
|
|
|
352492
352678
|
}));
|
|
352493
352679
|
}
|
|
352494
352680
|
function fusionToolsMcpServerPath() {
|
|
352495
|
-
return
|
|
352681
|
+
return join107(dirname45(fileURLToPath11(import.meta.url)), "mcp-schema-server.cjs");
|
|
352496
352682
|
}
|
|
352497
352683
|
function missingMcpSchemaServerError(serverPath) {
|
|
352498
352684
|
const error3 = new Error(`Fusion MCP schema server is missing: ${serverPath}`);
|
|
@@ -352533,7 +352719,7 @@ async function startFusionToolBridge(tools) {
|
|
|
352533
352719
|
byName.set(tool.name, tool);
|
|
352534
352720
|
}
|
|
352535
352721
|
}
|
|
352536
|
-
const schemaPath =
|
|
352722
|
+
const schemaPath = join107(tmpdir17(), `fusion-grok-mcp-schemas-${process.pid}-${randomUUID62()}.json`);
|
|
352537
352723
|
writeFileSync15(schemaPath, JSON.stringify(defs));
|
|
352538
352724
|
const server = createServer2(async (req, res) => {
|
|
352539
352725
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -352966,7 +353152,7 @@ var init_src11 = __esm({
|
|
|
352966
353152
|
|
|
352967
353153
|
// ../../plugins/fusion-plugin-claude-runtime/src/acp/cli-spawn.ts
|
|
352968
353154
|
import { existsSync as existsSync77 } from "node:fs";
|
|
352969
|
-
import { dirname as dirname46, isAbsolute as isAbsolute29, join as
|
|
353155
|
+
import { dirname as dirname46, isAbsolute as isAbsolute29, join as join108, resolve as resolve61 } from "node:path";
|
|
352970
353156
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
352971
353157
|
function asTrimmedString2(value) {
|
|
352972
353158
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
@@ -352984,7 +353170,7 @@ function pluginRootDir2() {
|
|
|
352984
353170
|
}
|
|
352985
353171
|
function bundledClaudeBridgeBinPath2(pluginRoot = pluginRootDir2()) {
|
|
352986
353172
|
const extension = process.platform === "win32" ? ".cmd" : "";
|
|
352987
|
-
return
|
|
353173
|
+
return join108(pluginRoot, "node_modules", ".bin", `${CLAUDE_CODE_CLI_ACP_BINARY2}${extension}`);
|
|
352988
353174
|
}
|
|
352989
353175
|
function resolveBundledClaudeBridgeBinary2(options = {}) {
|
|
352990
353176
|
const root = options.pluginRoot ?? pluginRootDir2();
|
|
@@ -354224,14 +354410,14 @@ var init_acp2 = __esm({
|
|
|
354224
354410
|
// ../../plugins/fusion-plugin-claude-runtime/src/cli-spawn.ts
|
|
354225
354411
|
import { spawn as spawn21 } from "node:child_process";
|
|
354226
354412
|
import { existsSync as existsSync78 } from "node:fs";
|
|
354227
|
-
import { basename as basename33, dirname as dirname48, isAbsolute as isAbsolute30, join as
|
|
354413
|
+
import { basename as basename33, dirname as dirname48, isAbsolute as isAbsolute30, join as join110, resolve as resolve63 } from "node:path";
|
|
354228
354414
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
354229
354415
|
function pluginRootDir3() {
|
|
354230
354416
|
const moduleDir = dirname48(fileURLToPath13(import.meta.url));
|
|
354231
354417
|
return ["src", "dist"].includes(basename33(moduleDir)) ? resolve63(moduleDir, "..") : moduleDir;
|
|
354232
354418
|
}
|
|
354233
354419
|
function bundledClaudeBridgeBinPath3(pluginRoot = pluginRootDir3()) {
|
|
354234
|
-
return
|
|
354420
|
+
return join110(pluginRoot, "bridge", `${CLAUDE_CODE_CLI_ACP_BINARY3}${process.platform === "win32" ? ".cmd" : ""}`);
|
|
354235
354421
|
}
|
|
354236
354422
|
function resolveBundledClaudeBridgeBinary3(options = {}) {
|
|
354237
354423
|
const candidate = bundledClaudeBridgeBinPath3(options.pluginRoot ?? pluginRootDir3());
|
|
@@ -354408,10 +354594,10 @@ import {
|
|
|
354408
354594
|
} from "node:fs";
|
|
354409
354595
|
import { createRequire as createRequire9 } from "node:module";
|
|
354410
354596
|
import { tmpdir as tmpdir18 } from "node:os";
|
|
354411
|
-
import { basename as basename34, dirname as dirname49, join as
|
|
354597
|
+
import { basename as basename34, dirname as dirname49, join as join111, resolve as resolve64 } from "node:path";
|
|
354412
354598
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
354413
354599
|
function isSkillDir2(dir2) {
|
|
354414
|
-
return existsSync79(
|
|
354600
|
+
return existsSync79(join111(dir2, "SKILL.md"));
|
|
354415
354601
|
}
|
|
354416
354602
|
function pushUnique2(out, candidate) {
|
|
354417
354603
|
if (!candidate) return;
|
|
@@ -354419,8 +354605,8 @@ function pushUnique2(out, candidate) {
|
|
|
354419
354605
|
if (!out.includes(resolved)) out.push(resolved);
|
|
354420
354606
|
}
|
|
354421
354607
|
function pushSkillLayoutsAtRoot2(out, root) {
|
|
354422
|
-
pushUnique2(out,
|
|
354423
|
-
pushUnique2(out,
|
|
354608
|
+
pushUnique2(out, join111(root, "skill", FUSION_SKILL_NAME3));
|
|
354609
|
+
pushUnique2(out, join111(root, "packages", "cli", "skill", FUSION_SKILL_NAME3));
|
|
354424
354610
|
}
|
|
354425
354611
|
function walkAncestorSkillCandidates2(out, startDir, maxParents = 8) {
|
|
354426
354612
|
let dir2 = startDir;
|
|
@@ -354435,7 +354621,7 @@ function pushPackageRequireCandidates2(out, from) {
|
|
|
354435
354621
|
try {
|
|
354436
354622
|
const require6 = createRequire9(from);
|
|
354437
354623
|
const pkgJson = require6.resolve("@runfusion/fusion/package.json");
|
|
354438
|
-
pushUnique2(out,
|
|
354624
|
+
pushUnique2(out, join111(dirname49(pkgJson), "skill", FUSION_SKILL_NAME3));
|
|
354439
354625
|
} catch {
|
|
354440
354626
|
}
|
|
354441
354627
|
}
|
|
@@ -354503,21 +354689,21 @@ function collectSkillsFromRoot2(root, out) {
|
|
|
354503
354689
|
return;
|
|
354504
354690
|
}
|
|
354505
354691
|
for (const entry of entries) {
|
|
354506
|
-
const child =
|
|
354692
|
+
const child = join111(root, entry);
|
|
354507
354693
|
if (isSkillDir2(child)) {
|
|
354508
354694
|
out.set(entry, child);
|
|
354509
354695
|
}
|
|
354510
354696
|
}
|
|
354511
354697
|
}
|
|
354512
354698
|
function stageClaudeSessionSkills(options = {}) {
|
|
354513
|
-
const pluginDir = mkdtempSync4(
|
|
354514
|
-
const skillsDir =
|
|
354699
|
+
const pluginDir = mkdtempSync4(join111(tmpdir18(), "fusion-claude-plugin-"));
|
|
354700
|
+
const skillsDir = join111(pluginDir, "skills");
|
|
354515
354701
|
mkdirSync15(skillsDir, { recursive: true });
|
|
354516
354702
|
const installed = /* @__PURE__ */ new Map();
|
|
354517
354703
|
const includeFusion = options.includeFusionSkill !== false;
|
|
354518
354704
|
if (includeFusion) {
|
|
354519
354705
|
const fusionSource = resolveBundledFusionSkillSource3();
|
|
354520
|
-
if (fusionSource && installSkillDir2(fusionSource,
|
|
354706
|
+
if (fusionSource && installSkillDir2(fusionSource, join111(skillsDir, FUSION_SKILL_NAME3))) {
|
|
354521
354707
|
installed.set(FUSION_SKILL_NAME3, fusionSource);
|
|
354522
354708
|
}
|
|
354523
354709
|
}
|
|
@@ -354527,15 +354713,15 @@ function stageClaudeSessionSkills(options = {}) {
|
|
|
354527
354713
|
}
|
|
354528
354714
|
for (const [name2, source] of installed) {
|
|
354529
354715
|
if (name2 === FUSION_SKILL_NAME3 && includeFusion) continue;
|
|
354530
|
-
installSkillDir2(source,
|
|
354716
|
+
installSkillDir2(source, join111(skillsDir, name2));
|
|
354531
354717
|
}
|
|
354532
354718
|
for (const [name2, source] of installed) {
|
|
354533
|
-
if (!existsSync79(
|
|
354534
|
-
installSkillDir2(source,
|
|
354719
|
+
if (!existsSync79(join111(skillsDir, name2))) {
|
|
354720
|
+
installSkillDir2(source, join111(skillsDir, name2));
|
|
354535
354721
|
}
|
|
354536
354722
|
}
|
|
354537
354723
|
writeFileSync16(
|
|
354538
|
-
|
|
354724
|
+
join111(pluginDir, "plugin.json"),
|
|
354539
354725
|
JSON.stringify(
|
|
354540
354726
|
{
|
|
354541
354727
|
name: "fusion-session-skills",
|
|
@@ -354601,7 +354787,7 @@ var init_skill_loader2 = __esm({
|
|
|
354601
354787
|
import { createServer as createServer3 } from "node:http";
|
|
354602
354788
|
import { existsSync as existsSync80, rmSync as rmSync13, writeFileSync as writeFileSync17 } from "node:fs";
|
|
354603
354789
|
import { tmpdir as tmpdir19 } from "node:os";
|
|
354604
|
-
import { dirname as dirname50, join as
|
|
354790
|
+
import { dirname as dirname50, join as join112 } from "node:path";
|
|
354605
354791
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
354606
354792
|
import { randomBytes as randomBytes8, randomUUID as randomUUID63 } from "node:crypto";
|
|
354607
354793
|
function toolsToMcpToolDefs3(tools) {
|
|
@@ -354613,7 +354799,7 @@ function toolsToMcpToolDefs3(tools) {
|
|
|
354613
354799
|
}));
|
|
354614
354800
|
}
|
|
354615
354801
|
function fusionToolsMcpServerPath2() {
|
|
354616
|
-
return
|
|
354802
|
+
return join112(dirname50(fileURLToPath15(import.meta.url)), "mcp-schema-server.cjs");
|
|
354617
354803
|
}
|
|
354618
354804
|
function missingMcpSchemaServerError2(serverPath) {
|
|
354619
354805
|
const error3 = new Error(`Fusion MCP schema server is missing: ${serverPath}`);
|
|
@@ -354654,7 +354840,7 @@ async function startFusionToolBridge2(tools, options = {}) {
|
|
|
354654
354840
|
byName.set(tool.name, tool);
|
|
354655
354841
|
}
|
|
354656
354842
|
}
|
|
354657
|
-
const schemaPath =
|
|
354843
|
+
const schemaPath = join112(tmpdir19(), `fusion-claude-mcp-schemas-${process.pid}-${randomUUID63()}.json`);
|
|
354658
354844
|
writeFileSync17(schemaPath, JSON.stringify(defs));
|
|
354659
354845
|
const capabilityToken = randomBytes8(32).toString("base64url");
|
|
354660
354846
|
const server = createServer3(async (req, res) => {
|
|
@@ -355458,7 +355644,7 @@ var init_provider6 = __esm({
|
|
|
355458
355644
|
|
|
355459
355645
|
// ../../plugins/fusion-plugin-omp-runtime/src/acp/cli-spawn.ts
|
|
355460
355646
|
import { existsSync as existsSync81 } from "node:fs";
|
|
355461
|
-
import { dirname as dirname51, isAbsolute as isAbsolute31, join as
|
|
355647
|
+
import { dirname as dirname51, isAbsolute as isAbsolute31, join as join113, resolve as resolve65 } from "node:path";
|
|
355462
355648
|
import { fileURLToPath as fileURLToPath16 } from "node:url";
|
|
355463
355649
|
function asTrimmedString3(value) {
|
|
355464
355650
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
@@ -355476,7 +355662,7 @@ function pluginRootDir4() {
|
|
|
355476
355662
|
}
|
|
355477
355663
|
function bundledClaudeBridgeBinPath4(pluginRoot = pluginRootDir4()) {
|
|
355478
355664
|
const extension = process.platform === "win32" ? ".cmd" : "";
|
|
355479
|
-
return
|
|
355665
|
+
return join113(pluginRoot, "node_modules", ".bin", `${CLAUDE_CODE_CLI_ACP_BINARY4}${extension}`);
|
|
355480
355666
|
}
|
|
355481
355667
|
function resolveBundledClaudeBridgeBinary4(options = {}) {
|
|
355482
355668
|
const root = options.pluginRoot ?? pluginRootDir4();
|
|
@@ -356794,7 +356980,7 @@ var init_mcp_forwarding3 = __esm({
|
|
|
356794
356980
|
import { createServer as createServer4 } from "node:http";
|
|
356795
356981
|
import { existsSync as existsSync82, unlinkSync as unlinkSync5, writeFileSync as writeFileSync18 } from "node:fs";
|
|
356796
356982
|
import { tmpdir as tmpdir20 } from "node:os";
|
|
356797
|
-
import { dirname as dirname53, join as
|
|
356983
|
+
import { dirname as dirname53, join as join115 } from "node:path";
|
|
356798
356984
|
import { fileURLToPath as fileURLToPath17 } from "node:url";
|
|
356799
356985
|
import { randomUUID as randomUUID64 } from "node:crypto";
|
|
356800
356986
|
function toolsToMcpToolDefs4(tools) {
|
|
@@ -356811,12 +356997,12 @@ function fusionToolsMcpServerPath3() {
|
|
|
356811
356997
|
const here = dirname53(fileURLToPath17(import.meta.url));
|
|
356812
356998
|
const candidates = [
|
|
356813
356999
|
// Packaged CLI / same-dir as bundled.js or tool-bridge source.
|
|
356814
|
-
|
|
357000
|
+
join115(here, "mcp-schema-server.cjs"),
|
|
356815
357001
|
// Source layout when running from dist/ that still has ../src assets.
|
|
356816
|
-
|
|
356817
|
-
|
|
357002
|
+
join115(here, "src", "mcp-schema-server.cjs"),
|
|
357003
|
+
join115(here, "..", "src", "mcp-schema-server.cjs"),
|
|
356818
357004
|
// Monorepo plugin root relative to src/ or dist/plugins/.../bundled.js.
|
|
356819
|
-
|
|
357005
|
+
join115(here, "..", "mcp-schema-server.cjs")
|
|
356820
357006
|
];
|
|
356821
357007
|
for (const candidate of candidates) {
|
|
356822
357008
|
if (existsSync82(candidate)) return candidate;
|
|
@@ -356853,7 +357039,7 @@ async function startFusionToolBridge3(tools) {
|
|
|
356853
357039
|
byName.set(tool.name, tool);
|
|
356854
357040
|
}
|
|
356855
357041
|
}
|
|
356856
|
-
const schemaPath =
|
|
357042
|
+
const schemaPath = join115(tmpdir20(), `fusion-omp-mcp-schemas-${process.pid}-${randomUUID64()}.json`);
|
|
356857
357043
|
writeFileSync18(schemaPath, JSON.stringify(defs));
|
|
356858
357044
|
const server = createServer4(async (req, res) => {
|
|
356859
357045
|
if (req.method !== "POST" || req.url !== "/tool-call") {
|
|
@@ -358805,9 +358991,9 @@ var init_hermes_model_cache = __esm({
|
|
|
358805
358991
|
});
|
|
358806
358992
|
|
|
358807
358993
|
// ../dashboard/src/routes/register-model-routes.ts
|
|
358808
|
-
import { access as access19, readFile as
|
|
358994
|
+
import { access as access19, readFile as readFile51 } from "node:fs/promises";
|
|
358809
358995
|
import { homedir as homedir16 } from "node:os";
|
|
358810
|
-
import { join as
|
|
358996
|
+
import { join as join116 } from "node:path";
|
|
358811
358997
|
function isRawAnthropicApiKeyCredential(credential) {
|
|
358812
358998
|
return Boolean(
|
|
358813
358999
|
credential && typeof credential === "object" && credential.type === "api_key" && typeof credential.key === "string" && credential.key.length > 0
|
|
@@ -358848,14 +359034,14 @@ async function getConfiguredProviderNames(authStorage) {
|
|
|
358848
359034
|
const providers = /* @__PURE__ */ new Set();
|
|
358849
359035
|
addAuthStorageConfiguredProviders(authStorage, providers);
|
|
358850
359036
|
const authPaths = [
|
|
358851
|
-
|
|
358852
|
-
|
|
358853
|
-
|
|
359037
|
+
join116(home, ".fusion", "agent", "auth.json"),
|
|
359038
|
+
join116(home, ".pi", "agent", "auth.json"),
|
|
359039
|
+
join116(home, ".pi", "auth.json")
|
|
358854
359040
|
];
|
|
358855
359041
|
for (const authPath of authPaths) {
|
|
358856
359042
|
try {
|
|
358857
359043
|
await access19(authPath);
|
|
358858
|
-
const parsed = JSON.parse(await
|
|
359044
|
+
const parsed = JSON.parse(await readFile51(authPath, "utf-8"));
|
|
358859
359045
|
for (const [key, credential] of Object.entries(parsed)) {
|
|
358860
359046
|
if (key === ANTHROPIC_SUBSCRIPTION_PROVIDER_ID4) {
|
|
358861
359047
|
providers.add(ANTHROPIC_PROVIDER_ID3);
|
|
@@ -358877,14 +359063,14 @@ async function getConfiguredProviderNames(authStorage) {
|
|
|
358877
359063
|
providers.add(ANTHROPIC_PROVIDER_ID3);
|
|
358878
359064
|
}
|
|
358879
359065
|
const modelsPaths = [
|
|
358880
|
-
|
|
358881
|
-
|
|
358882
|
-
|
|
359066
|
+
join116(home, ".fusion", "agent", "models.json"),
|
|
359067
|
+
join116(home, ".pi", "agent", "models.json"),
|
|
359068
|
+
join116(home, ".pi", "models.json")
|
|
358883
359069
|
];
|
|
358884
359070
|
for (const modelsPath of modelsPaths) {
|
|
358885
359071
|
try {
|
|
358886
359072
|
await access19(modelsPath);
|
|
358887
|
-
const parsed = JSON.parse(await
|
|
359073
|
+
const parsed = JSON.parse(await readFile51(modelsPath, "utf-8"));
|
|
358888
359074
|
const provs = parsed?.providers;
|
|
358889
359075
|
if (provs) {
|
|
358890
359076
|
for (const [providerId, config3] of Object.entries(provs)) {
|
|
@@ -359634,7 +359820,7 @@ var init_register_custom_provider_routes = __esm({
|
|
|
359634
359820
|
// ../dashboard/src/usage.ts
|
|
359635
359821
|
import * as os11 from "node:os";
|
|
359636
359822
|
import * as path13 from "node:path";
|
|
359637
|
-
import { readFile as
|
|
359823
|
+
import { readFile as readFile52 } from "node:fs/promises";
|
|
359638
359824
|
import * as https from "node:https";
|
|
359639
359825
|
import * as child_process from "node:child_process";
|
|
359640
359826
|
function getHomeDir6() {
|
|
@@ -359755,7 +359941,7 @@ function decodeJwtPayload(token) {
|
|
|
359755
359941
|
}
|
|
359756
359942
|
async function readAuthKeyFromFile(authPath, provider) {
|
|
359757
359943
|
try {
|
|
359758
|
-
const auth2 = JSON.parse(await
|
|
359944
|
+
const auth2 = JSON.parse(await readFile52(authPath, "utf-8"));
|
|
359759
359945
|
const entry = auth2?.[provider];
|
|
359760
359946
|
if (entry && (entry.type === "api_key" || entry.type === "key") && entry.key) {
|
|
359761
359947
|
return entry.key;
|
|
@@ -360173,7 +360359,7 @@ async function fetchClaudeUsage(authStorage) {
|
|
|
360173
360359
|
];
|
|
360174
360360
|
for (const p2 of credPaths) {
|
|
360175
360361
|
try {
|
|
360176
|
-
creds = JSON.parse(await
|
|
360362
|
+
creds = JSON.parse(await readFile52(p2, "utf-8"));
|
|
360177
360363
|
break;
|
|
360178
360364
|
} catch {
|
|
360179
360365
|
}
|
|
@@ -360366,7 +360552,7 @@ async function loadCodexCredential() {
|
|
|
360366
360552
|
const authPath = path13.join(codexHome, "auth.json");
|
|
360367
360553
|
let auth2 = null;
|
|
360368
360554
|
try {
|
|
360369
|
-
auth2 = JSON.parse(await
|
|
360555
|
+
auth2 = JSON.parse(await readFile52(authPath, "utf-8"));
|
|
360370
360556
|
} catch {
|
|
360371
360557
|
auth2 = null;
|
|
360372
360558
|
}
|
|
@@ -360486,7 +360672,7 @@ async function fetchGeminiUsage() {
|
|
|
360486
360672
|
const oauthPath = path13.join(getHomeDir6(), ".gemini", "oauth_creds.json");
|
|
360487
360673
|
let oauthCreds = null;
|
|
360488
360674
|
try {
|
|
360489
|
-
oauthCreds = JSON.parse(await
|
|
360675
|
+
oauthCreds = JSON.parse(await readFile52(oauthPath, "utf-8"));
|
|
360490
360676
|
} catch {
|
|
360491
360677
|
usage.error = "No Gemini credentials \u2014 run 'gemini' to login";
|
|
360492
360678
|
return usage;
|
|
@@ -360501,7 +360687,7 @@ async function fetchGeminiUsage() {
|
|
|
360501
360687
|
}
|
|
360502
360688
|
const settingsPath = path13.join(getHomeDir6(), ".gemini", "settings.json");
|
|
360503
360689
|
try {
|
|
360504
|
-
const settings = JSON.parse(await
|
|
360690
|
+
const settings = JSON.parse(await readFile52(settingsPath, "utf-8"));
|
|
360505
360691
|
const authType = settings?.security?.auth?.selectedType;
|
|
360506
360692
|
if (authType === "api-key" || authType === "vertex-ai") {
|
|
360507
360693
|
usage.status = "no-auth";
|
|
@@ -360689,7 +360875,7 @@ async function fetchMinimaxUsage(authStorage) {
|
|
|
360689
360875
|
async function readGrokUserSettingsApiKey2() {
|
|
360690
360876
|
try {
|
|
360691
360877
|
const settingsPath = path13.join(getHomeDir6(), ".grok", "user-settings.json");
|
|
360692
|
-
const raw = await
|
|
360878
|
+
const raw = await readFile52(settingsPath, "utf-8");
|
|
360693
360879
|
const parsed = JSON.parse(raw);
|
|
360694
360880
|
return typeof parsed?.apiKey === "string" && parsed.apiKey.trim().length > 0 ? parsed.apiKey.trim() : null;
|
|
360695
360881
|
} catch {
|
|
@@ -360698,7 +360884,7 @@ async function readGrokUserSettingsApiKey2() {
|
|
|
360698
360884
|
}
|
|
360699
360885
|
async function readGrokCliOidcToken() {
|
|
360700
360886
|
try {
|
|
360701
|
-
const raw = await
|
|
360887
|
+
const raw = await readFile52(path13.join(getHomeDir6(), ".grok", "auth.json"), "utf-8");
|
|
360702
360888
|
const parsed = JSON.parse(raw);
|
|
360703
360889
|
for (const entry of Object.values(parsed)) {
|
|
360704
360890
|
if (entry && typeof entry.key === "string" && entry.key.trim().length > 0) {
|
|
@@ -363823,11 +364009,11 @@ var init_droid_cli_probe = __esm({
|
|
|
363823
364009
|
});
|
|
363824
364010
|
|
|
363825
364011
|
// ../dashboard/src/llama-cpp-probe.ts
|
|
363826
|
-
import { readFile as
|
|
363827
|
-
import { join as
|
|
364012
|
+
import { readFile as readFile53 } from "node:fs/promises";
|
|
364013
|
+
import { join as join118 } from "node:path";
|
|
363828
364014
|
async function readJson(path14) {
|
|
363829
364015
|
try {
|
|
363830
|
-
const raw = await
|
|
364016
|
+
const raw = await readFile53(path14, "utf-8");
|
|
363831
364017
|
return JSON.parse(raw);
|
|
363832
364018
|
} catch {
|
|
363833
364019
|
return null;
|
|
@@ -363837,18 +364023,18 @@ function normalizeUrl(url2) {
|
|
|
363837
364023
|
return url2.trim().replace(/\/+$/, "");
|
|
363838
364024
|
}
|
|
363839
364025
|
async function resolveLlamaServerUrl(cwd) {
|
|
363840
|
-
const projectCfg = await readJson(
|
|
364026
|
+
const projectCfg = await readJson(join118(cwd, ".pi", "llama-server.json"));
|
|
363841
364027
|
if (projectCfg?.url) return normalizeUrl(projectCfg.url);
|
|
363842
364028
|
const envUrl = process.env.LLAMA_SERVER_URL;
|
|
363843
364029
|
if (envUrl) return normalizeUrl(envUrl);
|
|
363844
364030
|
const globalCfg = await readJson(
|
|
363845
|
-
|
|
364031
|
+
join118(process.env.HOME ?? ".", ".pi", "agent", "settings.json")
|
|
363846
364032
|
);
|
|
363847
364033
|
if (globalCfg?.llamaServerUrl) return normalizeUrl(globalCfg.llamaServerUrl);
|
|
363848
364034
|
return DEFAULT_LLAMA_SERVER_URL;
|
|
363849
364035
|
}
|
|
363850
364036
|
async function resolveLlamaServerApiKey() {
|
|
363851
|
-
const authCfg = await readJson(
|
|
364037
|
+
const authCfg = await readJson(join118(process.env.HOME ?? ".", ".pi", "agent", "auth.json"));
|
|
363852
364038
|
const key = authCfg?.["llama-server"]?.key?.trim();
|
|
363853
364039
|
return key ? key : void 0;
|
|
363854
364040
|
}
|
|
@@ -363929,7 +364115,7 @@ var init_auth_provider_catalog = __esm({
|
|
|
363929
364115
|
|
|
363930
364116
|
// ../dashboard/src/routes/register-auth-routes.ts
|
|
363931
364117
|
import { tmpdir as tmpdir21 } from "node:os";
|
|
363932
|
-
import { join as
|
|
364118
|
+
import { join as join119 } from "node:path";
|
|
363933
364119
|
import { existsSync as existsSync84, readFileSync as readFileSync29 } from "node:fs";
|
|
363934
364120
|
function parseGitHubCopilotDeviceCode(instructions) {
|
|
363935
364121
|
const match = instructions.match(/Enter code:\s*([A-Z0-9-]+)\b/i);
|
|
@@ -364594,7 +364780,7 @@ var init_register_auth_routes = __esm({
|
|
|
364594
364780
|
let acpAuthFailed = false;
|
|
364595
364781
|
let acpAuthReason;
|
|
364596
364782
|
try {
|
|
364597
|
-
const signalPath =
|
|
364783
|
+
const signalPath = join119(tmpdir21(), "fusion-acp-bridge-auth.json");
|
|
364598
364784
|
if (existsSync84(signalPath)) {
|
|
364599
364785
|
const sig = JSON.parse(readFileSync29(signalPath, "utf8"));
|
|
364600
364786
|
if (sig?.authFailed) {
|
|
@@ -365619,7 +365805,7 @@ var init_register_fn_binary_routes = __esm({
|
|
|
365619
365805
|
import { exec as exec46 } from "node:child_process";
|
|
365620
365806
|
import { readFileSync as readFileSync30, realpathSync as realpathSync14 } from "node:fs";
|
|
365621
365807
|
import { mkdir as mkdir37, rm as rm21, writeFile as writeFile37 } from "node:fs/promises";
|
|
365622
|
-
import { join as
|
|
365808
|
+
import { join as join120 } from "node:path";
|
|
365623
365809
|
import { promisify as promisify71 } from "node:util";
|
|
365624
365810
|
function ttlForFrequency(frequency) {
|
|
365625
365811
|
switch (frequency) {
|
|
@@ -365634,7 +365820,7 @@ function ttlForFrequency(frequency) {
|
|
|
365634
365820
|
}
|
|
365635
365821
|
}
|
|
365636
365822
|
function getCachePath(fusionDir) {
|
|
365637
|
-
return
|
|
365823
|
+
return join120(fusionDir, CACHE_FILENAME);
|
|
365638
365824
|
}
|
|
365639
365825
|
function buildInstallCommand(version3, force = false) {
|
|
365640
365826
|
if (!SAFE_VERSION_RE.test(version3)) {
|
|
@@ -365959,8 +366145,8 @@ var init_types6 = __esm({
|
|
|
365959
366145
|
|
|
365960
366146
|
// ../dashboard/src/stt/model-manager.ts
|
|
365961
366147
|
import { createHash as createHash27, randomUUID as randomUUID67 } from "node:crypto";
|
|
365962
|
-
import { mkdir as mkdir38, open as open4, readFile as
|
|
365963
|
-
import { join as
|
|
366148
|
+
import { mkdir as mkdir38, open as open4, readFile as readFile54, readdir as readdir14, rename as rename10, rm as rm22, stat as stat16, writeFile as writeFile38 } from "node:fs/promises";
|
|
366149
|
+
import { join as join121, relative as relative22, resolve as resolve67, sep as sep18 } from "node:path";
|
|
365964
366150
|
function parseSafeTarListing(listing) {
|
|
365965
366151
|
for (const line2 of listing.split("\n").filter(Boolean)) {
|
|
365966
366152
|
const type = line2[0];
|
|
@@ -365975,8 +366161,8 @@ function parseSafeTarListing(listing) {
|
|
|
365975
366161
|
function createVoiceModelManager(options = {}) {
|
|
365976
366162
|
const asset = options.asset ?? PARAKEET_V3_ASSET;
|
|
365977
366163
|
let configuredCacheDir = options.cacheDir;
|
|
365978
|
-
const cacheDir = () => configuredCacheDir ??=
|
|
365979
|
-
const finalDir = () =>
|
|
366164
|
+
const cacheDir = () => configuredCacheDir ??= join121(resolveGlobalDir(), "models", "parakeet-v3");
|
|
366165
|
+
const finalDir = () => join121(cacheDir(), "model");
|
|
365980
366166
|
let state = { status: "not-installed" };
|
|
365981
366167
|
let generation = 0;
|
|
365982
366168
|
let cleanupBarrier = Promise.resolve();
|
|
@@ -366039,8 +366225,8 @@ function createVoiceModelManager(options = {}) {
|
|
|
366039
366225
|
if (!current(g2, signal)) return state;
|
|
366040
366226
|
await mkdir38(cacheDir(), { recursive: true });
|
|
366041
366227
|
if (!current(g2, signal)) return state;
|
|
366042
|
-
partial2 =
|
|
366043
|
-
staging =
|
|
366228
|
+
partial2 = join121(cacheDir(), `.partial-${g2}-${randomUUID67()}`);
|
|
366229
|
+
staging = join121(cacheDir(), `.staging-${g2}-${randomUUID67()}`);
|
|
366044
366230
|
const file = await open4(partial2, "wx");
|
|
366045
366231
|
try {
|
|
366046
366232
|
const response = await (options.fetch ?? globalThis.fetch)(asset.url, { signal });
|
|
@@ -366085,10 +366271,10 @@ function createVoiceModelManager(options = {}) {
|
|
|
366085
366271
|
}
|
|
366086
366272
|
}
|
|
366087
366273
|
if (!current(g2, signal)) return state;
|
|
366088
|
-
await writeFile38(
|
|
366274
|
+
await writeFile38(join121(staging, "manifest.json"), JSON.stringify({ filename: asset.filename, sha256: asset.sha256, installedAt: (/* @__PURE__ */ new Date()).toISOString(), expectedFiles: asset.expectedFiles }));
|
|
366089
366275
|
await options.beforePromote?.(signal);
|
|
366090
366276
|
if (!current(g2, signal)) return state;
|
|
366091
|
-
const backup =
|
|
366277
|
+
const backup = join121(cacheDir(), `.backup-${g2}-${randomUUID67()}`);
|
|
366092
366278
|
let movedPrevious = false;
|
|
366093
366279
|
try {
|
|
366094
366280
|
try {
|
|
@@ -366168,9 +366354,9 @@ function createVoiceModelManager(options = {}) {
|
|
|
366168
366354
|
publish(absent);
|
|
366169
366355
|
return absent;
|
|
366170
366356
|
}
|
|
366171
|
-
const manifest = JSON.parse(await
|
|
366357
|
+
const manifest = JSON.parse(await readFile54(join121(finalDir(), "manifest.json"), "utf8"));
|
|
366172
366358
|
if (manifest.sha256 !== asset.sha256) throw new Error("stale manifest digest");
|
|
366173
|
-
for (const expected of asset.expectedFiles) if (!await existsFile(
|
|
366359
|
+
for (const expected of asset.expectedFiles) if (!await existsFile(join121(finalDir(), expected))) throw new Error("missing expected model file");
|
|
366174
366360
|
const installed = { status: "installed", checksumVerified: true, installedPath: finalDir() };
|
|
366175
366361
|
publish(installed);
|
|
366176
366362
|
return installed;
|
|
@@ -366182,7 +366368,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
366182
366368
|
try {
|
|
366183
366369
|
for (const entry of await readdir14(cacheDir())) {
|
|
366184
366370
|
const own = /^\.(partial|staging|backup)-(\d+)-/.exec(entry);
|
|
366185
|
-
if (own && Number(own[2]) !== active?.generation) await rm22(
|
|
366371
|
+
if (own && Number(own[2]) !== active?.generation) await rm22(join121(cacheDir(), entry), { recursive: true, force: true });
|
|
366186
366372
|
}
|
|
366187
366373
|
} catch {
|
|
366188
366374
|
}
|
|
@@ -366204,7 +366390,7 @@ function createVoiceModelManager(options = {}) {
|
|
|
366204
366390
|
try {
|
|
366205
366391
|
for (const entry of await readdir14(cacheDir())) {
|
|
366206
366392
|
const match = /^\.(partial|staging|backup)-(\d+)-/.exec(entry);
|
|
366207
|
-
if (match && Number(match[2]) <= g2) await rm22(
|
|
366393
|
+
if (match && Number(match[2]) <= g2) await rm22(join121(cacheDir(), entry), { recursive: true, force: true });
|
|
366208
366394
|
}
|
|
366209
366395
|
} catch {
|
|
366210
366396
|
}
|
|
@@ -366582,16 +366768,16 @@ import {
|
|
|
366582
366768
|
unlinkSync as unlinkSync6
|
|
366583
366769
|
} from "node:fs";
|
|
366584
366770
|
import { homedir as homedir18 } from "node:os";
|
|
366585
|
-
import { dirname as dirname54, join as
|
|
366771
|
+
import { dirname as dirname54, join as join122, resolve as resolve68 } from "node:path";
|
|
366586
366772
|
function resolveFnBinaryLocalPaths(home = homedir18()) {
|
|
366587
|
-
const installDir =
|
|
366588
|
-
const binDir =
|
|
366773
|
+
const installDir = join122(home, ".local", "share", "fusion");
|
|
366774
|
+
const binDir = join122(home, ".local", "bin");
|
|
366589
366775
|
return {
|
|
366590
366776
|
installDir,
|
|
366591
366777
|
binDir,
|
|
366592
|
-
binaryPath:
|
|
366593
|
-
fnShimPath:
|
|
366594
|
-
fusionShimPath:
|
|
366778
|
+
binaryPath: join122(installDir, "fn"),
|
|
366779
|
+
fnShimPath: join122(binDir, "fn"),
|
|
366780
|
+
fusionShimPath: join122(binDir, "fusion")
|
|
366595
366781
|
};
|
|
366596
366782
|
}
|
|
366597
366783
|
function runStreamingCommand(command, args, options) {
|
|
@@ -366687,17 +366873,17 @@ function runStreamingCommand(command, args, options) {
|
|
|
366687
366873
|
}
|
|
366688
366874
|
function resolveBunExecutable() {
|
|
366689
366875
|
if (process.env.BUN_INSTALL) {
|
|
366690
|
-
const candidate =
|
|
366876
|
+
const candidate = join122(process.env.BUN_INSTALL, "bin", process.platform === "win32" ? "bun.exe" : "bun");
|
|
366691
366877
|
if (existsSync85(candidate)) return candidate;
|
|
366692
366878
|
}
|
|
366693
|
-
const homeBun =
|
|
366879
|
+
const homeBun = join122(homedir18(), ".bun", "bin", process.platform === "win32" ? "bun.exe" : "bun");
|
|
366694
366880
|
if (existsSync85(homeBun)) return homeBun;
|
|
366695
366881
|
return "bun";
|
|
366696
366882
|
}
|
|
366697
366883
|
function installLocalFnBinary(distDir, onLog, paths2 = resolveFnBinaryLocalPaths()) {
|
|
366698
|
-
const srcBinary =
|
|
366699
|
-
const srcClient =
|
|
366700
|
-
const srcRuntime =
|
|
366884
|
+
const srcBinary = join122(distDir, process.platform === "win32" ? "fn.exe" : "fn");
|
|
366885
|
+
const srcClient = join122(distDir, "client");
|
|
366886
|
+
const srcRuntime = join122(distDir, "runtime");
|
|
366701
366887
|
if (!existsSync85(srcBinary)) {
|
|
366702
366888
|
throw new Error(`Built binary missing at ${srcBinary}. Did the Bun compile step fail?`);
|
|
366703
366889
|
}
|
|
@@ -366712,13 +366898,13 @@ function installLocalFnBinary(distDir, onLog, paths2 = resolveFnBinaryLocalPaths
|
|
|
366712
366898
|
chmodSync4(paths2.binaryPath, 493);
|
|
366713
366899
|
} catch {
|
|
366714
366900
|
}
|
|
366715
|
-
onLog("system", `Installing client assets \u2192 ${
|
|
366716
|
-
rmSync14(
|
|
366717
|
-
cpSync5(srcClient,
|
|
366901
|
+
onLog("system", `Installing client assets \u2192 ${join122(paths2.installDir, "client")}`);
|
|
366902
|
+
rmSync14(join122(paths2.installDir, "client"), { recursive: true, force: true });
|
|
366903
|
+
cpSync5(srcClient, join122(paths2.installDir, "client"), { recursive: true });
|
|
366718
366904
|
if (existsSync85(srcRuntime)) {
|
|
366719
|
-
onLog("system", `Installing runtime assets \u2192 ${
|
|
366720
|
-
rmSync14(
|
|
366721
|
-
cpSync5(srcRuntime,
|
|
366905
|
+
onLog("system", `Installing runtime assets \u2192 ${join122(paths2.installDir, "runtime")}`);
|
|
366906
|
+
rmSync14(join122(paths2.installDir, "runtime"), { recursive: true, force: true });
|
|
366907
|
+
cpSync5(srcRuntime, join122(paths2.installDir, "runtime"), { recursive: true });
|
|
366722
366908
|
}
|
|
366723
366909
|
for (const shim of [paths2.fnShimPath, paths2.fusionShimPath]) {
|
|
366724
366910
|
try {
|
|
@@ -366773,9 +366959,9 @@ function removeLocalFnShims(onLog, paths2 = resolveFnBinaryLocalPaths()) {
|
|
|
366773
366959
|
return { removed };
|
|
366774
366960
|
}
|
|
366775
366961
|
async function runLinkLocalFnBinary(sourceRoot, onLog) {
|
|
366776
|
-
const buildScript =
|
|
366777
|
-
const cliBuild =
|
|
366778
|
-
const distDir =
|
|
366962
|
+
const buildScript = join122(sourceRoot, "scripts", "build-workspace.mjs");
|
|
366963
|
+
const cliBuild = join122(sourceRoot, "packages", "cli", "build.ts");
|
|
366964
|
+
const distDir = join122(sourceRoot, "packages", "cli", "dist");
|
|
366779
366965
|
if (!existsSync85(buildScript)) {
|
|
366780
366966
|
return { success: false, error: `Build script missing: ${buildScript}` };
|
|
366781
366967
|
}
|
|
@@ -366856,7 +367042,7 @@ var init_fn_binary_local_install = __esm({
|
|
|
366856
367042
|
// ../dashboard/src/routes/register-system-routes.ts
|
|
366857
367043
|
import { randomUUID as randomUUID69 } from "node:crypto";
|
|
366858
367044
|
import { existsSync as existsSync86 } from "node:fs";
|
|
366859
|
-
import { join as
|
|
367045
|
+
import { join as join123 } from "node:path";
|
|
366860
367046
|
function rejectCrossOrigin(req, res) {
|
|
366861
367047
|
const origin = req.headers.origin;
|
|
366862
367048
|
if (typeof origin !== "string" || origin.length === 0) return false;
|
|
@@ -367046,7 +367232,7 @@ function registerSystemRoutes(ctx, deps) {
|
|
|
367046
367232
|
}
|
|
367047
367233
|
const restartAfter = body.restart !== false && scope !== "plugins";
|
|
367048
367234
|
const { args, label } = rebuildScopes[scope];
|
|
367049
|
-
const scriptPath =
|
|
367235
|
+
const scriptPath = join123(root, args[0]);
|
|
367050
367236
|
if (!existsSync86(scriptPath)) {
|
|
367051
367237
|
throw new ApiError(409, `Build script missing: ${scriptPath}`);
|
|
367052
367238
|
}
|
|
@@ -372392,11 +372578,11 @@ var init_roadmap_routes3 = __esm({
|
|
|
372392
372578
|
});
|
|
372393
372579
|
|
|
372394
372580
|
// ../dashboard/src/dev-server-detect.ts
|
|
372395
|
-
import { glob, readFile as
|
|
372396
|
-
import { dirname as dirname55, join as
|
|
372581
|
+
import { glob, readFile as readFile55 } from "node:fs/promises";
|
|
372582
|
+
import { dirname as dirname55, join as join124, relative as relative23, resolve as resolve69 } from "node:path";
|
|
372397
372583
|
async function readPackageJson(filePath) {
|
|
372398
372584
|
try {
|
|
372399
|
-
const raw = await
|
|
372585
|
+
const raw = await readFile55(filePath, "utf-8");
|
|
372400
372586
|
return JSON.parse(raw);
|
|
372401
372587
|
} catch {
|
|
372402
372588
|
return null;
|
|
@@ -372436,7 +372622,7 @@ function scoreCandidate(scriptName, pkg) {
|
|
|
372436
372622
|
async function collectWorkspacePackageJsons(projectRoot) {
|
|
372437
372623
|
const discovered = /* @__PURE__ */ new Set();
|
|
372438
372624
|
try {
|
|
372439
|
-
await
|
|
372625
|
+
await readFile55(join124(projectRoot, "pnpm-workspace.yaml"), "utf-8");
|
|
372440
372626
|
} catch {
|
|
372441
372627
|
}
|
|
372442
372628
|
for (const pattern of ["packages/*/package.json", "apps/*/package.json"]) {
|
|
@@ -372470,7 +372656,7 @@ function toSource(projectRoot, packageJsonPath) {
|
|
|
372470
372656
|
async function detectDevServerScripts(projectRoot) {
|
|
372471
372657
|
const root = resolve69(projectRoot);
|
|
372472
372658
|
const candidates = [];
|
|
372473
|
-
const rootPackagePath =
|
|
372659
|
+
const rootPackagePath = join124(root, "package.json");
|
|
372474
372660
|
const rootPackage = await readPackageJson(rootPackagePath);
|
|
372475
372661
|
if (rootPackage) {
|
|
372476
372662
|
for (const script of extractScripts(rootPackage)) {
|
|
@@ -372536,10 +372722,10 @@ var init_dev_server_detect = __esm({
|
|
|
372536
372722
|
});
|
|
372537
372723
|
|
|
372538
372724
|
// ../dashboard/src/dev-server-store.ts
|
|
372539
|
-
import { mkdir as mkdir39, readFile as
|
|
372540
|
-
import { dirname as dirname56, join as
|
|
372725
|
+
import { mkdir as mkdir39, readFile as readFile56, writeFile as writeFile39 } from "node:fs/promises";
|
|
372726
|
+
import { dirname as dirname56, join as join125, resolve as resolve70 } from "node:path";
|
|
372541
372727
|
function devServerFilePath(projectDir) {
|
|
372542
|
-
return
|
|
372728
|
+
return join125(resolve70(projectDir), ".fusion", "dev-server.json");
|
|
372543
372729
|
}
|
|
372544
372730
|
function normalizeState(candidate) {
|
|
372545
372731
|
const defaults = DEV_SERVER_DEFAULT_STATE();
|
|
@@ -372614,7 +372800,7 @@ var init_dev_server_store = __esm({
|
|
|
372614
372800
|
}
|
|
372615
372801
|
async load() {
|
|
372616
372802
|
try {
|
|
372617
|
-
const content = await
|
|
372803
|
+
const content = await readFile56(this.filePath, "utf-8");
|
|
372618
372804
|
const parsed = JSON.parse(content);
|
|
372619
372805
|
this.state = normalizeState(parsed?.state);
|
|
372620
372806
|
this.config = normalizeConfig(parsed?.config);
|
|
@@ -375261,7 +375447,7 @@ var init_register_config_mcp_pi_settings_routes = __esm({
|
|
|
375261
375447
|
|
|
375262
375448
|
// ../dashboard/src/routes.ts
|
|
375263
375449
|
import multer from "multer";
|
|
375264
|
-
import { resolve as resolve71, sep as sep19, join as
|
|
375450
|
+
import { resolve as resolve71, sep as sep19, join as join126, isAbsolute as isAbsolute32 } from "node:path";
|
|
375265
375451
|
import * as nodeFs3 from "node:fs";
|
|
375266
375452
|
async function readJsonObject3(path14) {
|
|
375267
375453
|
try {
|
|
@@ -375287,8 +375473,8 @@ async function getPiPackageManagerAgentDir() {
|
|
|
375287
375473
|
const fusionAgentDir = getFusionAgentDir();
|
|
375288
375474
|
const legacyAgentDir = getLegacyPiAgentDir();
|
|
375289
375475
|
const [fusionSettings, legacySettings, legacyExists, fusionExists] = await Promise.all([
|
|
375290
|
-
readJsonObject3(
|
|
375291
|
-
readJsonObject3(
|
|
375476
|
+
readJsonObject3(join126(fusionAgentDir, "settings.json")),
|
|
375477
|
+
readJsonObject3(join126(legacyAgentDir, "settings.json")),
|
|
375292
375478
|
pathExists2(legacyAgentDir),
|
|
375293
375479
|
pathExists2(fusionAgentDir)
|
|
375294
375480
|
]);
|
|
@@ -375315,9 +375501,9 @@ async function discoverDashboardPiExtensions(cwd) {
|
|
|
375315
375501
|
const { DefaultPackageManager: DefaultPackageManager5 } = await import("@earendil-works/pi-coding-agent");
|
|
375316
375502
|
const [agentDir, legacyGlobalSettings, fusionGlobalSettings, projectSettings] = await Promise.all([
|
|
375317
375503
|
getPiPackageManagerAgentDir(),
|
|
375318
|
-
readJsonObject3(
|
|
375319
|
-
readJsonObject3(
|
|
375320
|
-
readJsonObject3(
|
|
375504
|
+
readJsonObject3(join126(getLegacyPiAgentDir(), "settings.json")),
|
|
375505
|
+
readJsonObject3(join126(getFusionAgentDir(), "settings.json")),
|
|
375506
|
+
readJsonObject3(join126(cwd, ".fusion", "settings.json"))
|
|
375321
375507
|
]);
|
|
375322
375508
|
const globalSettings = { ...legacyGlobalSettings, ...fusionGlobalSettings };
|
|
375323
375509
|
const mergedSettings = { ...globalSettings, ...projectSettings };
|
|
@@ -376246,7 +376432,7 @@ function createApiRoutes(store, options) {
|
|
|
376246
376432
|
return;
|
|
376247
376433
|
}
|
|
376248
376434
|
}
|
|
376249
|
-
const { resolve: resolve103, dirname: dirname76, join:
|
|
376435
|
+
const { resolve: resolve103, dirname: dirname76, join: join156 } = await import("node:path");
|
|
376250
376436
|
const { readdir: readdir17, stat: stat20 } = await import("node:fs/promises");
|
|
376251
376437
|
const rawPath = req.query.path || process.env.HOME || process.env.USERPROFILE || "/";
|
|
376252
376438
|
const showHidden = req.query.showHidden === "true";
|
|
@@ -376271,7 +376457,7 @@ function createApiRoutes(store, options) {
|
|
|
376271
376457
|
for (const entry of dirEntries) {
|
|
376272
376458
|
if (!entry.isDirectory()) continue;
|
|
376273
376459
|
if (!showHidden && entry.name.startsWith(".")) continue;
|
|
376274
|
-
const entryPath =
|
|
376460
|
+
const entryPath = join156(resolvedPath, entry.name);
|
|
376275
376461
|
let hasChildren = false;
|
|
376276
376462
|
try {
|
|
376277
376463
|
const subEntries = await readdir17(entryPath, { withFileTypes: true });
|
|
@@ -377988,7 +378174,7 @@ var init_reliability_metrics = __esm({
|
|
|
377988
378174
|
|
|
377989
378175
|
// ../dashboard/src/view-chunk-manifest.ts
|
|
377990
378176
|
import { existsSync as existsSync87, readFileSync as readFileSync31, statSync as statSync15 } from "node:fs";
|
|
377991
|
-
import { join as
|
|
378177
|
+
import { join as join127, resolve as resolve72 } from "node:path";
|
|
377992
378178
|
function warnOnce(set, key, message) {
|
|
377993
378179
|
if (set.has(key)) {
|
|
377994
378180
|
return;
|
|
@@ -377998,7 +378184,7 @@ function warnOnce(set, key, message) {
|
|
|
377998
378184
|
}
|
|
377999
378185
|
function loadViewChunkManifest(clientDir) {
|
|
378000
378186
|
const cacheKey = resolve72(clientDir);
|
|
378001
|
-
const manifestPath =
|
|
378187
|
+
const manifestPath = join127(cacheKey, ".vite", "manifest.json");
|
|
378002
378188
|
let mtimeMs = null;
|
|
378003
378189
|
try {
|
|
378004
378190
|
mtimeMs = statSync15(manifestPath).mtimeMs;
|
|
@@ -378584,7 +378770,7 @@ var init_provider_health_monitor = __esm({
|
|
|
378584
378770
|
// ../dashboard/src/server.ts
|
|
378585
378771
|
import express3 from "express";
|
|
378586
378772
|
import { randomUUID as randomUUID70 } from "node:crypto";
|
|
378587
|
-
import { join as
|
|
378773
|
+
import { join as join128, dirname as dirname57 } from "node:path";
|
|
378588
378774
|
import { existsSync as existsSync88, readFileSync as readFileSync32, statSync as statSync16 } from "node:fs";
|
|
378589
378775
|
import { fileURLToPath as fileURLToPath18 } from "node:url";
|
|
378590
378776
|
import { createSecureServer as createHttp2SecureServer } from "node:http2";
|
|
@@ -378907,14 +379093,14 @@ function createServer5(store, options) {
|
|
|
378907
379093
|
getTerminalService(store.getRootDir());
|
|
378908
379094
|
const isHeadless = options?.headless === true;
|
|
378909
379095
|
const execDir = dirname57(process.execPath);
|
|
378910
|
-
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync88(
|
|
379096
|
+
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync88(join128(execDir, "client", "index.html")) ? join128(execDir, "client") : existsSync88(join128(__dirname2, "..", "dist", "client")) ? join128(__dirname2, "..", "dist", "client") : join128(__dirname2, "..", "client");
|
|
378911
379097
|
let cachedIndexClientDir = null;
|
|
378912
379098
|
let cachedIndexHtml = null;
|
|
378913
379099
|
let cachedIndexMtimeMs = null;
|
|
378914
379100
|
let cachedTemplatedIndexHtml = null;
|
|
378915
379101
|
const renderIndexHtml = () => {
|
|
378916
379102
|
const resolvedClientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : clientDir;
|
|
378917
|
-
const indexPath =
|
|
379103
|
+
const indexPath = join128(resolvedClientDir, "index.html");
|
|
378918
379104
|
let indexMtimeMs = null;
|
|
378919
379105
|
try {
|
|
378920
379106
|
indexMtimeMs = statSync16(indexPath).mtimeMs;
|
|
@@ -378956,13 +379142,13 @@ ${injection}`) : cachedIndexHtml.replace("</head>", `${injection}</head>`);
|
|
|
378956
379142
|
if (!isHeadless) {
|
|
378957
379143
|
app.get("/version.json", (_req, res) => {
|
|
378958
379144
|
res.setHeader("Cache-Control", "no-store, max-age=0");
|
|
378959
|
-
res.sendFile(
|
|
379145
|
+
res.sendFile(join128(clientDir, "version.json"), (err) => {
|
|
378960
379146
|
if (err) {
|
|
378961
379147
|
res.status(404).json({ version: null });
|
|
378962
379148
|
}
|
|
378963
379149
|
});
|
|
378964
379150
|
});
|
|
378965
|
-
if (existsSync88(
|
|
379151
|
+
if (existsSync88(join128(clientDir, "index.html"))) {
|
|
378966
379152
|
app.get(["/", "/index.html"], serveIndexHtml);
|
|
378967
379153
|
app.use(express3.static(clientDir, { index: false }));
|
|
378968
379154
|
}
|
|
@@ -380292,8 +380478,8 @@ var init_server2 = __esm({
|
|
|
380292
380478
|
});
|
|
380293
380479
|
|
|
380294
380480
|
// ../dashboard/src/skills-adapter.ts
|
|
380295
|
-
import { access as access20, readFile as
|
|
380296
|
-
import { join as
|
|
380481
|
+
import { access as access20, readFile as readFile57, writeFile as writeFile40, mkdir as mkdir40, readdir as readdir15, stat as stat17 } from "node:fs/promises";
|
|
380482
|
+
import { join as join129, relative as relative24, dirname as dirname58, resolve as resolve73, sep as sep21 } from "node:path";
|
|
380297
380483
|
async function pathExists3(path14) {
|
|
380298
380484
|
try {
|
|
380299
380485
|
await access20(path14);
|
|
@@ -380343,7 +380529,7 @@ function createSkillsAdapter(options) {
|
|
|
380343
380529
|
let settings = {};
|
|
380344
380530
|
if (await pathExists3(settingsPath)) {
|
|
380345
380531
|
try {
|
|
380346
|
-
settings = JSON.parse(await
|
|
380532
|
+
settings = JSON.parse(await readFile57(settingsPath, "utf-8"));
|
|
380347
380533
|
} catch {
|
|
380348
380534
|
}
|
|
380349
380535
|
}
|
|
@@ -380423,7 +380609,7 @@ function createSkillsAdapter(options) {
|
|
|
380423
380609
|
let settings = {};
|
|
380424
380610
|
if (await pathExists3(settingsPath)) {
|
|
380425
380611
|
try {
|
|
380426
|
-
settings = JSON.parse(await
|
|
380612
|
+
settings = JSON.parse(await readFile57(settingsPath, "utf-8"));
|
|
380427
380613
|
} catch {
|
|
380428
380614
|
}
|
|
380429
380615
|
}
|
|
@@ -380623,10 +380809,10 @@ function createSkillsAdapter(options) {
|
|
|
380623
380809
|
} catch {
|
|
380624
380810
|
skillDir = dirname58(skill.path);
|
|
380625
380811
|
}
|
|
380626
|
-
const skillMdPath =
|
|
380812
|
+
const skillMdPath = join129(skillDir, "SKILL.md");
|
|
380627
380813
|
let skillMd = "";
|
|
380628
380814
|
try {
|
|
380629
|
-
skillMd = await
|
|
380815
|
+
skillMd = await readFile57(skillMdPath, "utf-8");
|
|
380630
380816
|
} catch (error3) {
|
|
380631
380817
|
const err = error3;
|
|
380632
380818
|
if (err.code !== "ENOENT") {
|
|
@@ -380686,7 +380872,7 @@ function createSkillsAdapter(options) {
|
|
|
380686
380872
|
if (fileStat.size > MAX_PREVIEW_BYTES) {
|
|
380687
380873
|
return { name: name2, relativePath: normalizedRelative, content: "", isText: false };
|
|
380688
380874
|
}
|
|
380689
|
-
const buffer2 = await
|
|
380875
|
+
const buffer2 = await readFile57(targetPath);
|
|
380690
380876
|
const sample = buffer2.subarray(0, Math.min(buffer2.length, 8e3));
|
|
380691
380877
|
const isBinary2 = sample.includes(0);
|
|
380692
380878
|
if (isBinary2) {
|
|
@@ -380885,7 +381071,7 @@ function normalizeEntry(entry) {
|
|
|
380885
381071
|
};
|
|
380886
381072
|
}
|
|
380887
381073
|
function getProjectSettingsPath(rootDir) {
|
|
380888
|
-
return
|
|
381074
|
+
return join129(rootDir, ".fusion", "settings.json");
|
|
380889
381075
|
}
|
|
380890
381076
|
var MIN_PUBLIC_SEARCH_QUERY_LENGTH;
|
|
380891
381077
|
var init_skills_adapter = __esm({
|
|
@@ -380986,7 +381172,7 @@ var init_src15 = __esm({
|
|
|
380986
381172
|
// src/extension.ts
|
|
380987
381173
|
import { Type as Type9 } from "typebox";
|
|
380988
381174
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
380989
|
-
import { resolve as resolve74, relative as relative25, isAbsolute as isAbsolute33, sep as sep22, basename as basename37, extname as extname5, join as
|
|
381175
|
+
import { resolve as resolve74, relative as relative25, isAbsolute as isAbsolute33, sep as sep22, basename as basename37, extname as extname5, join as join130 } from "node:path";
|
|
380990
381176
|
import { existsSync as existsSync89 } from "node:fs";
|
|
380991
381177
|
import { AsyncLocalStorage as AsyncLocalStorage8 } from "node:async_hooks";
|
|
380992
381178
|
function resolveProjectRoot2(cwd) {
|
|
@@ -380995,12 +381181,12 @@ function resolveProjectRoot2(cwd) {
|
|
|
380995
381181
|
warnedMissingProjectRootResolver = true;
|
|
380996
381182
|
console.warn("[fusion-extension] @fusion/core.getProjectRootFromWorktree is unavailable; using filesystem fallback resolution.");
|
|
380997
381183
|
}
|
|
380998
|
-
if (worktreeProjectRoot && existsSync89(
|
|
381184
|
+
if (worktreeProjectRoot && existsSync89(join130(worktreeProjectRoot, ".fusion"))) {
|
|
380999
381185
|
return worktreeProjectRoot;
|
|
381000
381186
|
}
|
|
381001
381187
|
let current = resolve74(cwd);
|
|
381002
381188
|
while (true) {
|
|
381003
|
-
if (existsSync89(
|
|
381189
|
+
if (existsSync89(join130(current, ".fusion"))) {
|
|
381004
381190
|
return current;
|
|
381005
381191
|
}
|
|
381006
381192
|
const parent2 = resolve74(current, "..");
|
|
@@ -381866,11 +382052,11 @@ var init_migration_holding_server = __esm({
|
|
|
381866
382052
|
// src/commands/ensure-project-registered.ts
|
|
381867
382053
|
import { exec as exec48 } from "node:child_process";
|
|
381868
382054
|
import { existsSync as existsSync90, mkdirSync as mkdirSync17 } from "node:fs";
|
|
381869
|
-
import { basename as basename38, join as
|
|
382055
|
+
import { basename as basename38, join as join131 } from "node:path";
|
|
381870
382056
|
import { promisify as promisify73 } from "node:util";
|
|
381871
382057
|
function stampProjectIdentityBestEffort(cwd, project, logPrefix) {
|
|
381872
382058
|
try {
|
|
381873
|
-
writeProjectIdentity(
|
|
382059
|
+
writeProjectIdentity(join131(cwd, ".fusion"), {
|
|
381874
382060
|
id: project.id,
|
|
381875
382061
|
createdAt: project.createdAt
|
|
381876
382062
|
});
|
|
@@ -381892,7 +382078,7 @@ async function ensureCwdProjectRegistered(options) {
|
|
|
381892
382078
|
return null;
|
|
381893
382079
|
}
|
|
381894
382080
|
try {
|
|
381895
|
-
const fusionDir =
|
|
382081
|
+
const fusionDir = join131(cwd, ".fusion");
|
|
381896
382082
|
if (!existsSync90(fusionDir)) {
|
|
381897
382083
|
mkdirSync17(fusionDir, { recursive: true });
|
|
381898
382084
|
}
|
|
@@ -381923,7 +382109,7 @@ async function ensureCwdProjectRegistered(options) {
|
|
|
381923
382109
|
}
|
|
381924
382110
|
}
|
|
381925
382111
|
async function detectProjectName(dir2) {
|
|
381926
|
-
if (!existsSync90(
|
|
382112
|
+
if (!existsSync90(join131(dir2, ".git"))) {
|
|
381927
382113
|
return basename38(dir2) || "my-project";
|
|
381928
382114
|
}
|
|
381929
382115
|
try {
|
|
@@ -381956,12 +382142,12 @@ var init_ensure_project_registered = __esm({
|
|
|
381956
382142
|
|
|
381957
382143
|
// src/commands/provider-settings.ts
|
|
381958
382144
|
import { existsSync as existsSync91, readFileSync as readFileSync33, writeFileSync as writeFileSync19, mkdirSync as mkdirSync18 } from "node:fs";
|
|
381959
|
-
import { join as
|
|
382145
|
+
import { join as join132, dirname as dirname59, basename as basename39 } from "node:path";
|
|
381960
382146
|
function siblingAgentDir2(agentDir, siblingRoot) {
|
|
381961
382147
|
if (basename39(agentDir) !== "agent") {
|
|
381962
382148
|
return void 0;
|
|
381963
382149
|
}
|
|
381964
|
-
return
|
|
382150
|
+
return join132(dirname59(dirname59(agentDir)), siblingRoot, "agent");
|
|
381965
382151
|
}
|
|
381966
382152
|
function readJsonObject4(path14) {
|
|
381967
382153
|
if (!existsSync91(path14)) {
|
|
@@ -381975,13 +382161,13 @@ function readJsonObject4(path14) {
|
|
|
381975
382161
|
}
|
|
381976
382162
|
}
|
|
381977
382163
|
function createReadOnlyProviderSettingsView(cwd, agentDir) {
|
|
381978
|
-
const fusionAgentDir = agentDir.includes(`${
|
|
381979
|
-
const legacyAgentDir = agentDir.includes(`${
|
|
381980
|
-
const legacyGlobalSettings = legacyAgentDir ? readJsonObject4(
|
|
381981
|
-
const fusionGlobalSettings = fusionAgentDir ? readJsonObject4(
|
|
381982
|
-
const directGlobalSettings = readJsonObject4(
|
|
382164
|
+
const fusionAgentDir = agentDir.includes(`${join132(".fusion", "agent")}`) ? agentDir : siblingAgentDir2(agentDir, ".fusion");
|
|
382165
|
+
const legacyAgentDir = agentDir.includes(`${join132(".pi", "agent")}`) ? agentDir : siblingAgentDir2(agentDir, ".pi");
|
|
382166
|
+
const legacyGlobalSettings = legacyAgentDir ? readJsonObject4(join132(legacyAgentDir, "settings.json")) : {};
|
|
382167
|
+
const fusionGlobalSettings = fusionAgentDir ? readJsonObject4(join132(fusionAgentDir, "settings.json")) : {};
|
|
382168
|
+
const directGlobalSettings = readJsonObject4(join132(agentDir, "settings.json"));
|
|
381983
382169
|
const globalSettings = { ...legacyGlobalSettings, ...directGlobalSettings, ...fusionGlobalSettings };
|
|
381984
|
-
const fusionProjectSettings = readJsonObject4(
|
|
382170
|
+
const fusionProjectSettings = readJsonObject4(join132(cwd, ".fusion", "settings.json"));
|
|
381985
382171
|
const mergedSettings = { ...globalSettings, ...fusionProjectSettings };
|
|
381986
382172
|
return {
|
|
381987
382173
|
getGlobalSettings: () => structuredClone(globalSettings),
|
|
@@ -382010,20 +382196,20 @@ var init_provider_auth2 = __esm({
|
|
|
382010
382196
|
// src/commands/auth-paths.ts
|
|
382011
382197
|
import { homedir as homedir19 } from "node:os";
|
|
382012
382198
|
import { existsSync as existsSync92, readFileSync as readFileSync34 } from "node:fs";
|
|
382013
|
-
import { join as
|
|
382199
|
+
import { join as join133 } from "node:path";
|
|
382014
382200
|
function getFusionAgentDir2(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
382015
|
-
return
|
|
382201
|
+
return join133(home, ".fusion", "agent");
|
|
382016
382202
|
}
|
|
382017
382203
|
function getLegacyAgentDir(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
382018
|
-
return
|
|
382204
|
+
return join133(home, ".pi", "agent");
|
|
382019
382205
|
}
|
|
382020
382206
|
function getFusionModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
382021
|
-
return
|
|
382207
|
+
return join133(getFusionAgentDir2(home), "models.json");
|
|
382022
382208
|
}
|
|
382023
382209
|
function getLegacyModelsPaths2(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
382024
382210
|
return [
|
|
382025
|
-
|
|
382026
|
-
|
|
382211
|
+
join133(home, ".pi", "agent", "models.json"),
|
|
382212
|
+
join133(home, ".pi", "models.json")
|
|
382027
382213
|
];
|
|
382028
382214
|
}
|
|
382029
382215
|
function getModelRegistryModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
@@ -382050,8 +382236,8 @@ function hasPackageManagerSettings3(settings) {
|
|
|
382050
382236
|
function getPackageManagerAgentDir2(home = process.env.HOME || process.env.USERPROFILE || homedir19()) {
|
|
382051
382237
|
const fusionAgentDir = getFusionAgentDir2(home);
|
|
382052
382238
|
const legacyAgentDir = getLegacyAgentDir(home);
|
|
382053
|
-
const fusionSettings = readJsonObject5(
|
|
382054
|
-
const legacySettings = readJsonObject5(
|
|
382239
|
+
const fusionSettings = readJsonObject5(join133(fusionAgentDir, "settings.json"));
|
|
382240
|
+
const legacySettings = readJsonObject5(join133(legacyAgentDir, "settings.json"));
|
|
382055
382241
|
if (hasPackageManagerSettings3(fusionSettings) || !existsSync92(legacyAgentDir)) {
|
|
382056
382242
|
return fusionAgentDir;
|
|
382057
382243
|
}
|
|
@@ -382308,7 +382494,7 @@ import {
|
|
|
382308
382494
|
symlinkSync as symlinkSync6,
|
|
382309
382495
|
unlinkSync as unlinkSync7
|
|
382310
382496
|
} from "node:fs";
|
|
382311
|
-
import { dirname as dirname61, join as
|
|
382497
|
+
import { dirname as dirname61, join as join134, resolve as resolve76 } from "node:path";
|
|
382312
382498
|
import { fileURLToPath as fileURLToPath19 } from "node:url";
|
|
382313
382499
|
function isPiClaudeCliConfigured(globalSettings) {
|
|
382314
382500
|
if (!globalSettings || typeof globalSettings !== "object") {
|
|
@@ -382332,7 +382518,7 @@ function resolveFusionSkillSource() {
|
|
|
382332
382518
|
return existsSync93(candidate) ? candidate : null;
|
|
382333
382519
|
}
|
|
382334
382520
|
function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
382335
|
-
const target =
|
|
382521
|
+
const target = join134(projectPath, ".claude", "skills", FUSION_SKILL_NAME4);
|
|
382336
382522
|
if (options.enabled === false) {
|
|
382337
382523
|
return { outcome: "skipped", target, reason: "pi-claude-cli not configured" };
|
|
382338
382524
|
}
|
|
@@ -382357,7 +382543,7 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
|
382357
382543
|
unlinkSync7(target);
|
|
382358
382544
|
replaced = true;
|
|
382359
382545
|
} else {
|
|
382360
|
-
const skillMd =
|
|
382546
|
+
const skillMd = join134(target, "SKILL.md");
|
|
382361
382547
|
if (!existsSync93(skillMd)) {
|
|
382362
382548
|
return {
|
|
382363
382549
|
outcome: "failed",
|
|
@@ -382404,7 +382590,7 @@ function ensureFusionSkillForProjects(projects2, options = { enabled: false }) {
|
|
|
382404
382590
|
if (!options.enabled) {
|
|
382405
382591
|
return projects2.map((p2) => ({
|
|
382406
382592
|
outcome: "skipped",
|
|
382407
|
-
target:
|
|
382593
|
+
target: join134(p2.path, ".claude", "skills", FUSION_SKILL_NAME4),
|
|
382408
382594
|
reason: "pi-claude-cli not configured"
|
|
382409
382595
|
}));
|
|
382410
382596
|
}
|
|
@@ -382797,10 +382983,10 @@ var init_llama_cpp_extension = __esm({
|
|
|
382797
382983
|
|
|
382798
382984
|
// src/update-cache.ts
|
|
382799
382985
|
import { readFileSync as readFileSync38 } from "node:fs";
|
|
382800
|
-
import { join as
|
|
382986
|
+
import { join as join135 } from "node:path";
|
|
382801
382987
|
function getCachedUpdateStatus(currentVersion) {
|
|
382802
382988
|
try {
|
|
382803
|
-
const cachePath =
|
|
382989
|
+
const cachePath = join135(resolveGlobalDir(), "update-check.json");
|
|
382804
382990
|
const raw = readFileSync38(cachePath, "utf-8");
|
|
382805
382991
|
const parsed = JSON.parse(raw);
|
|
382806
382992
|
if (parsed.updateAvailable === true && typeof parsed.latestVersion === "string" && parsed.latestVersion.length > 0 && typeof parsed.currentVersion === "string" && parsed.currentVersion.length > 0) {
|
|
@@ -382906,7 +383092,7 @@ var init_self_extension = __esm({
|
|
|
382906
383092
|
});
|
|
382907
383093
|
|
|
382908
383094
|
// src/plugins/bundled-plugin-install.ts
|
|
382909
|
-
import { dirname as dirname66, join as
|
|
383095
|
+
import { dirname as dirname66, join as join136, resolve as resolve81 } from "node:path";
|
|
382910
383096
|
import { fileURLToPath as fileURLToPath24 } from "node:url";
|
|
382911
383097
|
function getCandidatePluginDirs(pluginId) {
|
|
382912
383098
|
const moduleDir = dirname66(fileURLToPath24(import.meta.url));
|
|
@@ -382914,13 +383100,13 @@ function getCandidatePluginDirs(pluginId) {
|
|
|
382914
383100
|
return [
|
|
382915
383101
|
// Bundled/global runtime: moduleDir is typically <cli>/dist, and plugins are
|
|
382916
383102
|
// staged under <cli>/dist/plugins/<id>. Keep first for the global-install regression.
|
|
382917
|
-
|
|
383103
|
+
join136(moduleDir, "plugins", pluginId),
|
|
382918
383104
|
// Source checkout: prefer the live workspace plugin (freshness-checked by
|
|
382919
383105
|
// resolvePluginEntryPath) over the stale staged tsup bundle below.
|
|
382920
|
-
|
|
383106
|
+
join136(cliPackageRoot, "..", "..", "plugins", pluginId),
|
|
382921
383107
|
// Source/dev fallbacks.
|
|
382922
|
-
|
|
382923
|
-
|
|
383108
|
+
join136(cliPackageRoot, "dist", "plugins", pluginId),
|
|
383109
|
+
join136(cliPackageRoot, "plugins", pluginId)
|
|
382924
383110
|
];
|
|
382925
383111
|
}
|
|
382926
383112
|
async function ensureBundledPluginInstalled2(pluginStore, pluginLoader, pluginId) {
|
|
@@ -386972,6 +387158,7 @@ var init_common2 = __esm({
|
|
|
386972
387158
|
guardRejected: "This move is not allowed by the workflow.",
|
|
386973
387159
|
mergeBlocked: "This task is blocked from completing until its merge step finishes.",
|
|
386974
387160
|
unknownColumn: "That column doesn't exist in this task's workflow.",
|
|
387161
|
+
unplannedForExecution: "This task isn't ready for execution yet \u2014 planning or plan review is still outstanding.",
|
|
386975
387162
|
workflowMismatch: "Drag can't move a card between workflows. Use the workflow switcher instead."
|
|
386976
387163
|
}
|
|
386977
387164
|
},
|
|
@@ -387463,6 +387650,7 @@ var init_common3 = __esm({
|
|
|
387463
387650
|
guardRejected: "",
|
|
387464
387651
|
mergeBlocked: "",
|
|
387465
387652
|
unknownColumn: "",
|
|
387653
|
+
unplannedForExecution: "",
|
|
387466
387654
|
workflowMismatch: ""
|
|
387467
387655
|
}
|
|
387468
387656
|
},
|
|
@@ -387954,6 +388142,7 @@ var init_common4 = __esm({
|
|
|
387954
388142
|
guardRejected: "",
|
|
387955
388143
|
mergeBlocked: "",
|
|
387956
388144
|
unknownColumn: "",
|
|
388145
|
+
unplannedForExecution: "",
|
|
387957
388146
|
workflowMismatch: ""
|
|
387958
388147
|
}
|
|
387959
388148
|
},
|
|
@@ -388445,6 +388634,7 @@ var init_common5 = __esm({
|
|
|
388445
388634
|
guardRejected: "",
|
|
388446
388635
|
mergeBlocked: "",
|
|
388447
388636
|
unknownColumn: "",
|
|
388637
|
+
unplannedForExecution: "",
|
|
388448
388638
|
workflowMismatch: ""
|
|
388449
388639
|
}
|
|
388450
388640
|
},
|
|
@@ -388936,6 +389126,7 @@ var init_common6 = __esm({
|
|
|
388936
389126
|
guardRejected: "",
|
|
388937
389127
|
mergeBlocked: "",
|
|
388938
389128
|
unknownColumn: "",
|
|
389129
|
+
unplannedForExecution: "",
|
|
388939
389130
|
workflowMismatch: ""
|
|
388940
389131
|
}
|
|
388941
389132
|
},
|
|
@@ -389427,6 +389618,7 @@ var init_common7 = __esm({
|
|
|
389427
389618
|
guardRejected: "",
|
|
389428
389619
|
mergeBlocked: "",
|
|
389429
389620
|
unknownColumn: "",
|
|
389621
|
+
unplannedForExecution: "",
|
|
389430
389622
|
workflowMismatch: ""
|
|
389431
389623
|
}
|
|
389432
389624
|
},
|
|
@@ -391344,7 +391536,7 @@ __export(dashboard_exports, {
|
|
|
391344
391536
|
runDashboardSupervised: () => runDashboardSupervised,
|
|
391345
391537
|
shouldSuperviseDashboard: () => shouldSuperviseDashboard
|
|
391346
391538
|
});
|
|
391347
|
-
import { join as
|
|
391539
|
+
import { join as join137, resolve as pathResolve2 } from "node:path";
|
|
391348
391540
|
import { execFile as execFileCb, spawn as spawn31 } from "node:child_process";
|
|
391349
391541
|
import { promisify as promisify74 } from "node:util";
|
|
391350
391542
|
import { stat as stat18, readdir as readdir16, readFile as fsReadFile4 } from "node:fs/promises";
|
|
@@ -391686,7 +391878,7 @@ async function buildFileListDirectory(projectPath, relativePath) {
|
|
|
391686
391878
|
let size2 = 0;
|
|
391687
391879
|
let modifiedAt = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
391688
391880
|
try {
|
|
391689
|
-
const s3 = await stat18(
|
|
391881
|
+
const s3 = await stat18(join137(absDir, d.name));
|
|
391690
391882
|
size2 = d.isDirectory() ? 0 : s3.size;
|
|
391691
391883
|
modifiedAt = s3.mtime.toISOString();
|
|
391692
391884
|
} catch {
|
|
@@ -392374,7 +392566,7 @@ async function runDashboard(port, opts = {}) {
|
|
|
392374
392566
|
...llamaCppPaths
|
|
392375
392567
|
],
|
|
392376
392568
|
cwd,
|
|
392377
|
-
|
|
392569
|
+
join137(cwd, ".fusion", "disabled-auto-extension-discovery")
|
|
392378
392570
|
), logPhase);
|
|
392379
392571
|
for (const { path: path14, error: error3 } of extensionsResult.errors) {
|
|
392380
392572
|
logSink.log(`Failed to load ${path14}: ${error3}`, "extensions");
|
|
@@ -393642,9 +393834,9 @@ function resolveFusionSourceWorkspaceRoot() {
|
|
|
393642
393834
|
try {
|
|
393643
393835
|
let dir2 = pathResolve2(fileURLToPath25(import.meta.url), "..");
|
|
393644
393836
|
for (let i = 0; i < 10; i++) {
|
|
393645
|
-
if (existsSync98(
|
|
393837
|
+
if (existsSync98(join137(dir2, "pnpm-workspace.yaml"))) {
|
|
393646
393838
|
try {
|
|
393647
|
-
const pkg = JSON.parse(readFileSync40(
|
|
393839
|
+
const pkg = JSON.parse(readFileSync40(join137(dir2, "package.json"), "utf8"));
|
|
393648
393840
|
return pkg?.name === "fusion-workspace" ? dir2 : void 0;
|
|
393649
393841
|
} catch {
|
|
393650
393842
|
return void 0;
|
|
@@ -394349,7 +394541,7 @@ var serve_exports = {};
|
|
|
394349
394541
|
__export(serve_exports, {
|
|
394350
394542
|
runServe: () => runServe
|
|
394351
394543
|
});
|
|
394352
|
-
import { join as
|
|
394544
|
+
import { join as join138, resolve as pathResolve3 } from "node:path";
|
|
394353
394545
|
import {
|
|
394354
394546
|
DefaultPackageManager as DefaultPackageManager3,
|
|
394355
394547
|
discoverAndLoadExtensions as discoverAndLoadExtensions3,
|
|
@@ -394809,7 +395001,7 @@ async function runServe(port, opts = {}) {
|
|
|
394809
395001
|
...llamaCppPaths
|
|
394810
395002
|
],
|
|
394811
395003
|
primaryCwd,
|
|
394812
|
-
|
|
395004
|
+
join138(primaryCwd, ".fusion", "disabled-auto-extension-discovery")
|
|
394813
395005
|
);
|
|
394814
395006
|
for (const { path: path14, error: error3 } of extensionsResult.errors) {
|
|
394815
395007
|
console.log(`[extensions] Failed to load ${path14}: ${error3}`);
|
|
@@ -395234,7 +395426,7 @@ var daemon_exports = {};
|
|
|
395234
395426
|
__export(daemon_exports, {
|
|
395235
395427
|
runDaemon: () => runDaemon
|
|
395236
395428
|
});
|
|
395237
|
-
import { join as
|
|
395429
|
+
import { join as join139, resolve as pathResolve4 } from "node:path";
|
|
395238
395430
|
import {
|
|
395239
395431
|
DefaultPackageManager as DefaultPackageManager4,
|
|
395240
395432
|
discoverAndLoadExtensions as discoverAndLoadExtensions4,
|
|
@@ -395658,7 +395850,7 @@ async function runDaemon(opts = {}) {
|
|
|
395658
395850
|
const extensionsResult = await discoverAndLoadExtensions4(
|
|
395659
395851
|
[...reconciledExtensionPaths, ...droidCliPaths, ...llamaCppPaths],
|
|
395660
395852
|
primaryCwd,
|
|
395661
|
-
|
|
395853
|
+
join139(primaryCwd, ".fusion", "disabled-auto-extension-discovery")
|
|
395662
395854
|
);
|
|
395663
395855
|
for (const { path: path14, error: error3 } of extensionsResult.errors) {
|
|
395664
395856
|
console.log(`[extensions] Failed to load ${path14}: ${error3}`);
|
|
@@ -396005,7 +396197,7 @@ __export(desktop_exports, {
|
|
|
396005
396197
|
import { spawn as spawn32 } from "node:child_process";
|
|
396006
396198
|
import { once as once2 } from "node:events";
|
|
396007
396199
|
import { existsSync as existsSync99 } from "node:fs";
|
|
396008
|
-
import { dirname as dirname67, isAbsolute as isAbsolute34, join as
|
|
396200
|
+
import { dirname as dirname67, isAbsolute as isAbsolute34, join as join140, resolve as resolve82 } from "node:path";
|
|
396009
396201
|
import { createRequire as createRequire13 } from "node:module";
|
|
396010
396202
|
import { fileURLToPath as fileURLToPath26 } from "node:url";
|
|
396011
396203
|
import * as os14 from "node:os";
|
|
@@ -396112,7 +396304,7 @@ function terminateProcess(child, signal = "SIGTERM") {
|
|
|
396112
396304
|
child.kill(signal);
|
|
396113
396305
|
}
|
|
396114
396306
|
function resolveDevDesktopEntry(rootDir) {
|
|
396115
|
-
const desktopEntry =
|
|
396307
|
+
const desktopEntry = join140(rootDir, "packages", "desktop", "dist", "main.js");
|
|
396116
396308
|
if (existsSync99(desktopEntry)) {
|
|
396117
396309
|
return desktopEntry;
|
|
396118
396310
|
}
|
|
@@ -396749,7 +396941,7 @@ __export(task_exports, {
|
|
|
396749
396941
|
});
|
|
396750
396942
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
396751
396943
|
import { watchFile, unwatchFile, statSync as statSync17, existsSync as existsSync100, readFileSync as readFileSync41 } from "node:fs";
|
|
396752
|
-
import { basename as basename41, join as
|
|
396944
|
+
import { basename as basename41, join as join141 } from "node:path";
|
|
396753
396945
|
function columnLabel2(column) {
|
|
396754
396946
|
return COLUMN_LABELS[column] ?? column;
|
|
396755
396947
|
}
|
|
@@ -397107,7 +397299,7 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
|
|
|
397107
397299
|
}
|
|
397108
397300
|
console.log(` Path: .fusion/tasks/${resolvedTask.id}/`);
|
|
397109
397301
|
if (attachFiles && attachFiles.length > 0) {
|
|
397110
|
-
const { readFile:
|
|
397302
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
397111
397303
|
const { basename: basename46, extname: extname7, resolve: resolve103 } = await import("node:path");
|
|
397112
397304
|
for (const filePath of attachFiles) {
|
|
397113
397305
|
const resolvedPath = resolve103(filePath);
|
|
@@ -397120,7 +397312,7 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName,
|
|
|
397120
397312
|
}
|
|
397121
397313
|
let content;
|
|
397122
397314
|
try {
|
|
397123
|
-
content = await
|
|
397315
|
+
content = await readFile64(resolvedPath);
|
|
397124
397316
|
} catch {
|
|
397125
397317
|
console.error(` \u2717 Cannot read file: ${filePath}`);
|
|
397126
397318
|
continue;
|
|
@@ -397291,7 +397483,7 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
397291
397483
|
printEntries(filteredEntries);
|
|
397292
397484
|
if (options.follow) {
|
|
397293
397485
|
const projectPath = context.projectPath ?? process.cwd();
|
|
397294
|
-
const logPath =
|
|
397486
|
+
const logPath = join141(projectPath, ".fusion", "tasks", id, "agent.log");
|
|
397295
397487
|
if (!existsSync100(logPath)) {
|
|
397296
397488
|
console.log(`
|
|
397297
397489
|
Waiting for log file to be created...`);
|
|
@@ -397496,7 +397688,7 @@ async function runTaskMerge(id, projectName) {
|
|
|
397496
397688
|
}
|
|
397497
397689
|
}
|
|
397498
397690
|
async function runTaskAttach(id, filePath, projectName) {
|
|
397499
|
-
const { readFile:
|
|
397691
|
+
const { readFile: readFile64 } = await import("node:fs/promises");
|
|
397500
397692
|
const { basename: basename46, extname: extname7 } = await import("node:path");
|
|
397501
397693
|
const { resolve: resolve103 } = await import("node:path");
|
|
397502
397694
|
const resolvedPath = resolve103(filePath);
|
|
@@ -397510,7 +397702,7 @@ async function runTaskAttach(id, filePath, projectName) {
|
|
|
397510
397702
|
}
|
|
397511
397703
|
let content;
|
|
397512
397704
|
try {
|
|
397513
|
-
content = await
|
|
397705
|
+
content = await readFile64(resolvedPath);
|
|
397514
397706
|
} catch {
|
|
397515
397707
|
console.error(`Cannot read file: ${filePath}`);
|
|
397516
397708
|
process.exit(1);
|
|
@@ -398882,7 +399074,7 @@ __export(settings_export_exports, {
|
|
|
398882
399074
|
runSettingsExport: () => runSettingsExport
|
|
398883
399075
|
});
|
|
398884
399076
|
import { writeFile as writeFile41 } from "node:fs/promises";
|
|
398885
|
-
import { resolve as resolve83, join as
|
|
399077
|
+
import { resolve as resolve83, join as join142 } from "node:path";
|
|
398886
399078
|
async function runSettingsExport(options = {}) {
|
|
398887
399079
|
const scope = options.scope ?? "both";
|
|
398888
399080
|
let project;
|
|
@@ -398912,7 +399104,7 @@ async function runSettingsExport(options = {}) {
|
|
|
398912
399104
|
targetPath = resolve83(outputPath);
|
|
398913
399105
|
} else {
|
|
398914
399106
|
const filename = generateExportFilename();
|
|
398915
|
-
targetPath =
|
|
399107
|
+
targetPath = join142(process.cwd(), filename);
|
|
398916
399108
|
}
|
|
398917
399109
|
const jsonContent = JSON.stringify(exportData, null, 2);
|
|
398918
399110
|
await writeFile41(targetPath, jsonContent);
|
|
@@ -399086,7 +399278,7 @@ __export(mcp_exports, {
|
|
|
399086
399278
|
runMcpValidate: () => runMcpValidate
|
|
399087
399279
|
});
|
|
399088
399280
|
import { existsSync as existsSync102 } from "node:fs";
|
|
399089
|
-
import { readFile as
|
|
399281
|
+
import { readFile as readFile58, writeFile as writeFile42 } from "node:fs/promises";
|
|
399090
399282
|
import { resolve as resolve85 } from "node:path";
|
|
399091
399283
|
async function createGlobalSettingsStore() {
|
|
399092
399284
|
const store = new GlobalSettingsStore();
|
|
@@ -399424,7 +399616,7 @@ async function runMcpImport(filePath, opts = {}) {
|
|
|
399424
399616
|
context = await loadContext(opts.projectName, scope === "project");
|
|
399425
399617
|
const resolvedPath = resolve85(filePath);
|
|
399426
399618
|
if (!existsSync102(resolvedPath)) throw new Error(`File not found: ${filePath}`);
|
|
399427
|
-
const imported = importMcpServersJson(await
|
|
399619
|
+
const imported = importMcpServersJson(await readFile58(resolvedPath, "utf-8"), { scope });
|
|
399428
399620
|
if (imported.errors.length > 0) throw new Error(`Invalid MCP import file:
|
|
399429
399621
|
${imported.errors.map((error3) => ` - ${error3}`).join("\n")}`);
|
|
399430
399622
|
console.log();
|
|
@@ -399541,7 +399733,7 @@ var init_mcp = __esm({
|
|
|
399541
399733
|
|
|
399542
399734
|
// src/project-resolver.ts
|
|
399543
399735
|
import { existsSync as existsSync103, statSync as statSync18 } from "node:fs";
|
|
399544
|
-
import { basename as basename42, dirname as dirname68, join as
|
|
399736
|
+
import { basename as basename42, dirname as dirname68, join as join143, normalize as normalize9, resolve as resolve86 } from "node:path";
|
|
399545
399737
|
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
399546
399738
|
async function getCentralCore() {
|
|
399547
399739
|
if (!centralCoreInstance) {
|
|
@@ -399655,7 +399847,7 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
|
|
|
399655
399847
|
if (interactive) {
|
|
399656
399848
|
console.log(`
|
|
399657
399849
|
Found fn project at ${fusionDir} but it's not registered.`);
|
|
399658
|
-
const projectFusionDir =
|
|
399850
|
+
const projectFusionDir = join143(fusionDir, ".fusion");
|
|
399659
399851
|
const identity = readProjectIdentity(projectFusionDir);
|
|
399660
399852
|
if (identity) {
|
|
399661
399853
|
const recover = await promptConfirm2(
|
|
@@ -399900,7 +400092,7 @@ var workflow_exports = {};
|
|
|
399900
400092
|
__export(workflow_exports, {
|
|
399901
400093
|
runWorkflowValidate: () => runWorkflowValidate
|
|
399902
400094
|
});
|
|
399903
|
-
import { readFile as
|
|
400095
|
+
import { readFile as readFile59 } from "node:fs/promises";
|
|
399904
400096
|
import { resolve as resolve87 } from "node:path";
|
|
399905
400097
|
async function resolveStore(projectName) {
|
|
399906
400098
|
try {
|
|
@@ -399939,7 +400131,7 @@ async function runWorkflowValidate(opts) {
|
|
|
399939
400131
|
if (opts.file) {
|
|
399940
400132
|
const filePath = resolve87(opts.file);
|
|
399941
400133
|
try {
|
|
399942
|
-
ir2 = JSON.parse(await
|
|
400134
|
+
ir2 = JSON.parse(await readFile59(filePath, "utf8"));
|
|
399943
400135
|
} catch (error3) {
|
|
399944
400136
|
const message = `Failed to read or parse workflow IR file '${opts.file}': ${error3 instanceof Error ? error3.message : String(error3)}`;
|
|
399945
400137
|
if (opts.json) return await exitWithStore({ valid: false, error: message }, 2);
|
|
@@ -400759,7 +400951,7 @@ __export(db_exports, {
|
|
|
400759
400951
|
});
|
|
400760
400952
|
import { existsSync as existsSync104 } from "node:fs";
|
|
400761
400953
|
import { copyFile as copyFile3, mkdir as mkdir41 } from "node:fs/promises";
|
|
400762
|
-
import { join as
|
|
400954
|
+
import { join as join144 } from "node:path";
|
|
400763
400955
|
function formatBytes9(bytes) {
|
|
400764
400956
|
if (bytes <= 0) return "0 B";
|
|
400765
400957
|
const units = ["B", "KB", "MB", "GB"];
|
|
@@ -400835,7 +401027,7 @@ async function runDbMigrate(projectName, opts = {}) {
|
|
|
400835
401027
|
} catch {
|
|
400836
401028
|
projectRoot = process.cwd();
|
|
400837
401029
|
}
|
|
400838
|
-
const fusionDir =
|
|
401030
|
+
const fusionDir = join144(projectRoot, ".fusion");
|
|
400839
401031
|
const globalDir = resolveGlobalDir();
|
|
400840
401032
|
const sources = defaultMigrationSources(fusionDir, globalDir);
|
|
400841
401033
|
const presentSources = sources.filter((s3) => existsSync104(s3.sqlitePath));
|
|
@@ -400962,11 +401154,11 @@ function describeBackendSafe(backend) {
|
|
|
400962
401154
|
}
|
|
400963
401155
|
async function createPreMigrationBackup(fusionDir, globalDir, sources) {
|
|
400964
401156
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
400965
|
-
const backupDir =
|
|
401157
|
+
const backupDir = join144(globalDir, "migration-backups", `pre-migrate-${ts2}`);
|
|
400966
401158
|
await mkdir41(backupDir, { recursive: true });
|
|
400967
401159
|
for (const s3 of sources) {
|
|
400968
401160
|
if (existsSync104(s3.sqlitePath)) {
|
|
400969
|
-
const dest =
|
|
401161
|
+
const dest = join144(backupDir, s3.sqlitePath.split("/").pop() ?? "source.db");
|
|
400970
401162
|
await copyFile3(s3.sqlitePath, dest);
|
|
400971
401163
|
}
|
|
400972
401164
|
}
|
|
@@ -401860,7 +402052,7 @@ __export(project_exports2, {
|
|
|
401860
402052
|
runProjectSetDefault: () => runProjectSetDefault,
|
|
401861
402053
|
runProjectShow: () => runProjectShow
|
|
401862
402054
|
});
|
|
401863
|
-
import { resolve as resolve88, isAbsolute as isAbsolute35, relative as relative26, basename as basename43, join as
|
|
402055
|
+
import { resolve as resolve88, isAbsolute as isAbsolute35, relative as relative26, basename as basename43, join as join145 } from "node:path";
|
|
401864
402056
|
import { existsSync as existsSync105, statSync as statSync19 } from "node:fs";
|
|
401865
402057
|
import { createInterface as createInterface8 } from "node:readline/promises";
|
|
401866
402058
|
function formatDisplayPath(projectPath) {
|
|
@@ -402105,7 +402297,7 @@ async function runProjectAdd(name2, path14, options = {}) {
|
|
|
402105
402297
|
const project = ensured.project;
|
|
402106
402298
|
await central.updateProject(project.id, { status: "active" });
|
|
402107
402299
|
try {
|
|
402108
|
-
writeProjectIdentity(
|
|
402300
|
+
writeProjectIdentity(join145(absolutePath, ".fusion"), {
|
|
402109
402301
|
id: project.id,
|
|
402110
402302
|
createdAt: project.createdAt
|
|
402111
402303
|
});
|
|
@@ -402348,13 +402540,13 @@ var init_project2 = __esm({
|
|
|
402348
402540
|
// src/commands/skill-installation.ts
|
|
402349
402541
|
import { cpSync as cpSync7, existsSync as existsSync106, mkdirSync as mkdirSync20 } from "node:fs";
|
|
402350
402542
|
import { homedir as homedir20 } from "node:os";
|
|
402351
|
-
import { dirname as dirname69, join as
|
|
402543
|
+
import { dirname as dirname69, join as join146, resolve as resolve89 } from "node:path";
|
|
402352
402544
|
import { fileURLToPath as fileURLToPath27 } from "node:url";
|
|
402353
402545
|
function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.env.USERPROFILE || homedir20()) {
|
|
402354
402546
|
return [
|
|
402355
|
-
{ client: "claude", targetDir:
|
|
402356
|
-
{ client: "codex", targetDir:
|
|
402357
|
-
{ client: "gemini", targetDir:
|
|
402547
|
+
{ client: "claude", targetDir: join146(homeDir, ".claude", "skills", FUSION_SKILL_NAME5) },
|
|
402548
|
+
{ client: "codex", targetDir: join146(homeDir, ".codex", "skills", FUSION_SKILL_NAME5) },
|
|
402549
|
+
{ client: "gemini", targetDir: join146(homeDir, ".gemini", "skills", FUSION_SKILL_NAME5) }
|
|
402358
402550
|
];
|
|
402359
402551
|
}
|
|
402360
402552
|
function resolveBundledFusionSkillSource4() {
|
|
@@ -402418,13 +402610,13 @@ __export(init_exports, {
|
|
|
402418
402610
|
runInit: () => runInit
|
|
402419
402611
|
});
|
|
402420
402612
|
import { existsSync as existsSync107, mkdirSync as mkdirSync21, writeFileSync as writeFileSync20, readFileSync as readFileSync42 } from "node:fs";
|
|
402421
|
-
import { join as
|
|
402613
|
+
import { join as join147, resolve as resolve90, basename as basename44 } from "node:path";
|
|
402422
402614
|
import { exec as exec50 } from "node:child_process";
|
|
402423
402615
|
import { promisify as promisify76 } from "node:util";
|
|
402424
402616
|
async function runInit(options = {}) {
|
|
402425
402617
|
const cwd = options.path ? resolve90(options.path) : process.cwd();
|
|
402426
|
-
const fusionDir =
|
|
402427
|
-
const dbPath =
|
|
402618
|
+
const fusionDir = join147(cwd, ".fusion");
|
|
402619
|
+
const dbPath = join147(fusionDir, "fusion.db");
|
|
402428
402620
|
const hasDbPath = existsSync107(dbPath);
|
|
402429
402621
|
const hasValidDb = hasDbPath && isValidSqliteDatabaseFile(dbPath);
|
|
402430
402622
|
const hasIdentity = hasProjectIdentity(fusionDir);
|
|
@@ -402434,7 +402626,7 @@ async function runInit(options = {}) {
|
|
|
402434
402626
|
const existing = await central2.getProjectByPath(cwd);
|
|
402435
402627
|
if (existing) {
|
|
402436
402628
|
try {
|
|
402437
|
-
writeProjectIdentity(
|
|
402629
|
+
writeProjectIdentity(join147(cwd, ".fusion"), {
|
|
402438
402630
|
id: existing.id,
|
|
402439
402631
|
createdAt: existing.createdAt
|
|
402440
402632
|
});
|
|
@@ -402511,7 +402703,7 @@ async function runInit(options = {}) {
|
|
|
402511
402703
|
const project = ensured.project;
|
|
402512
402704
|
await central.updateProject(project.id, { status: "active" });
|
|
402513
402705
|
try {
|
|
402514
|
-
writeProjectIdentity(
|
|
402706
|
+
writeProjectIdentity(join147(cwd, ".fusion"), {
|
|
402515
402707
|
id: project.id,
|
|
402516
402708
|
createdAt: project.createdAt
|
|
402517
402709
|
});
|
|
@@ -402546,7 +402738,7 @@ async function runInit(options = {}) {
|
|
|
402546
402738
|
}
|
|
402547
402739
|
}
|
|
402548
402740
|
async function detectProjectName2(dir2) {
|
|
402549
|
-
if (!existsSync107(
|
|
402741
|
+
if (!existsSync107(join147(dir2, ".git"))) {
|
|
402550
402742
|
return basename44(dir2) || "my-project";
|
|
402551
402743
|
}
|
|
402552
402744
|
try {
|
|
@@ -402566,7 +402758,7 @@ async function detectProjectName2(dir2) {
|
|
|
402566
402758
|
return basename44(dir2) || "my-project";
|
|
402567
402759
|
}
|
|
402568
402760
|
async function addLocalStorageToGitignore(cwd) {
|
|
402569
|
-
const gitignorePath =
|
|
402761
|
+
const gitignorePath = join147(cwd, ".gitignore");
|
|
402570
402762
|
let content = "";
|
|
402571
402763
|
if (existsSync107(gitignorePath)) {
|
|
402572
402764
|
try {
|
|
@@ -402609,7 +402801,7 @@ async function initializeGitRepo(cwd) {
|
|
|
402609
402801
|
}
|
|
402610
402802
|
await ensureGitConfig(cwd, "user.name", "Fusion");
|
|
402611
402803
|
await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
|
|
402612
|
-
const gitkeepPath =
|
|
402804
|
+
const gitkeepPath = join147(cwd, ".gitkeep");
|
|
402613
402805
|
if (!existsSync107(gitkeepPath)) {
|
|
402614
402806
|
writeFileSync20(gitkeepPath, "\n");
|
|
402615
402807
|
}
|
|
@@ -403539,11 +403731,11 @@ var org_import_exports = {};
|
|
|
403539
403731
|
__export(org_import_exports, {
|
|
403540
403732
|
runOrgImport: () => runOrgImport
|
|
403541
403733
|
});
|
|
403542
|
-
import { readFile as
|
|
403734
|
+
import { readFile as readFile60 } from "node:fs/promises";
|
|
403543
403735
|
import { resolve as resolve94 } from "node:path";
|
|
403544
403736
|
async function runOrgImport(file, options = {}) {
|
|
403545
403737
|
const rootDir = options.project ? await resolveProjectPathOnly(options.project) : process.cwd();
|
|
403546
|
-
const bundle = JSON.parse(await
|
|
403738
|
+
const bundle = JSON.parse(await readFile60(resolve94(file), "utf8"));
|
|
403547
403739
|
const boot = await createTaskStoreForBackend({ rootDir });
|
|
403548
403740
|
const agents2 = new AgentStore({ rootDir: `${rootDir}/.fusion`, asyncLayer: boot.taskStore.asyncLayer });
|
|
403549
403741
|
try {
|
|
@@ -404157,8 +404349,8 @@ __export(plugin_exports2, {
|
|
|
404157
404349
|
runPluginUninstall: () => runPluginUninstall
|
|
404158
404350
|
});
|
|
404159
404351
|
import { existsSync as existsSync110 } from "node:fs";
|
|
404160
|
-
import { dirname as dirname71, extname as extname6, join as
|
|
404161
|
-
import { readFile as
|
|
404352
|
+
import { dirname as dirname71, extname as extname6, join as join148, resolve as resolve95 } from "node:path";
|
|
404353
|
+
import { readFile as readFile61, stat as stat19 } from "node:fs/promises";
|
|
404162
404354
|
import * as readline from "node:readline";
|
|
404163
404355
|
async function getProjectPath(projectName) {
|
|
404164
404356
|
if (projectName) {
|
|
@@ -404249,10 +404441,10 @@ async function resolvePluginEntryFile(pluginDir) {
|
|
|
404249
404441
|
}
|
|
404250
404442
|
throw new Error(`Plugin entry file must end with .js, .mjs, or .cjs: ${absoluteInputPath}`);
|
|
404251
404443
|
}
|
|
404252
|
-
const packageJsonPath =
|
|
404444
|
+
const packageJsonPath = join148(absoluteInputPath, "package.json");
|
|
404253
404445
|
let selectedCandidate;
|
|
404254
404446
|
if (existsSync110(packageJsonPath)) {
|
|
404255
|
-
const packageJson = JSON.parse(await
|
|
404447
|
+
const packageJson = JSON.parse(await readFile61(packageJsonPath, "utf-8"));
|
|
404256
404448
|
const exportsRecord = asRecord6(packageJson.exports);
|
|
404257
404449
|
const dotExport = exportsRecord?.["."];
|
|
404258
404450
|
const dotExportRecord = asRecord6(dotExport);
|
|
@@ -404299,11 +404491,11 @@ async function loadManifestFromPath(pluginPath) {
|
|
|
404299
404491
|
const absoluteInputPath = resolve95(pluginPath);
|
|
404300
404492
|
const inputStats = await statPath(absoluteInputPath);
|
|
404301
404493
|
const manifestDir = inputStats?.isFile() ? dirname71(absoluteInputPath) : absoluteInputPath;
|
|
404302
|
-
const manifestPath =
|
|
404494
|
+
const manifestPath = join148(manifestDir, "manifest.json");
|
|
404303
404495
|
if (!existsSync110(manifestPath)) {
|
|
404304
404496
|
throw new Error(`Plugin manifest not found at: ${manifestPath}`);
|
|
404305
404497
|
}
|
|
404306
|
-
const content = await
|
|
404498
|
+
const content = await readFile61(manifestPath, "utf-8");
|
|
404307
404499
|
const manifest = JSON.parse(content);
|
|
404308
404500
|
const validation = validatePluginManifest(manifest);
|
|
404309
404501
|
if (!validation.valid) {
|
|
@@ -404682,7 +404874,7 @@ __export(plugin_scaffold_exports, {
|
|
|
404682
404874
|
runPluginNew: () => runPluginNew
|
|
404683
404875
|
});
|
|
404684
404876
|
import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync23, existsSync as existsSync111, readFileSync as readFileSync45 } from "node:fs";
|
|
404685
|
-
import { join as
|
|
404877
|
+
import { join as join149, dirname as dirname72, resolve as resolve96 } from "node:path";
|
|
404686
404878
|
import { fileURLToPath as fileURLToPath28 } from "node:url";
|
|
404687
404879
|
function toTitleCase(str) {
|
|
404688
404880
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -405004,16 +405196,16 @@ async function runPluginCreate(name2, options) {
|
|
|
405004
405196
|
ensureTargetPathAvailable(targetDir, targetPath);
|
|
405005
405197
|
try {
|
|
405006
405198
|
mkdirSync24(targetPath, { recursive: true });
|
|
405007
|
-
mkdirSync24(
|
|
405008
|
-
writeFileSync23(
|
|
405009
|
-
writeFileSync23(
|
|
405010
|
-
writeFileSync23(
|
|
405011
|
-
writeFileSync23(
|
|
405199
|
+
mkdirSync24(join149(targetPath, "src", "__tests__"), { recursive: true });
|
|
405200
|
+
writeFileSync23(join149(targetPath, "package.json"), generatePackageJson(name2));
|
|
405201
|
+
writeFileSync23(join149(targetPath, "tsconfig.json"), generateTsconfig());
|
|
405202
|
+
writeFileSync23(join149(targetPath, "vitest.config.ts"), generateVitestConfig());
|
|
405203
|
+
writeFileSync23(join149(targetPath, "src", "index.ts"), generateIndexTs(name2));
|
|
405012
405204
|
writeFileSync23(
|
|
405013
|
-
|
|
405205
|
+
join149(targetPath, "src", "__tests__", "index.test.ts"),
|
|
405014
405206
|
generateTestTs(name2)
|
|
405015
405207
|
);
|
|
405016
|
-
writeFileSync23(
|
|
405208
|
+
writeFileSync23(join149(targetPath, "README.md"), generateReadme(name2));
|
|
405017
405209
|
} catch (err) {
|
|
405018
405210
|
console.error(
|
|
405019
405211
|
`Error creating plugin files: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -405038,14 +405230,14 @@ async function runPluginNew(name2, options) {
|
|
|
405038
405230
|
ensureTargetPathAvailable(targetDir, targetPath);
|
|
405039
405231
|
try {
|
|
405040
405232
|
mkdirSync24(targetPath, { recursive: true });
|
|
405041
|
-
mkdirSync24(
|
|
405042
|
-
writeFileSync23(
|
|
405043
|
-
writeFileSync23(
|
|
405044
|
-
writeFileSync23(
|
|
405045
|
-
writeFileSync23(
|
|
405046
|
-
writeFileSync23(
|
|
405047
|
-
writeFileSync23(
|
|
405048
|
-
writeFileSync23(
|
|
405233
|
+
mkdirSync24(join149(targetPath, "src", "__tests__"), { recursive: true });
|
|
405234
|
+
writeFileSync23(join149(targetPath, "package.json"), generateStandalonePackageJson(name2, options?.scope));
|
|
405235
|
+
writeFileSync23(join149(targetPath, "tsconfig.json"), generateStandaloneTsconfig());
|
|
405236
|
+
writeFileSync23(join149(targetPath, "vitest.config.ts"), generateVitestConfig());
|
|
405237
|
+
writeFileSync23(join149(targetPath, "manifest.json"), generateManifest(name2));
|
|
405238
|
+
writeFileSync23(join149(targetPath, "src", "index.ts"), generateStandaloneIndexTs(name2));
|
|
405239
|
+
writeFileSync23(join149(targetPath, "src", "__tests__", "index.test.ts"), generateStandaloneTestTs(name2));
|
|
405240
|
+
writeFileSync23(join149(targetPath, "README.md"), generateStandaloneReadme(name2));
|
|
405049
405241
|
} catch (err) {
|
|
405050
405242
|
console.error(
|
|
405051
405243
|
`Error creating plugin files: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -405080,7 +405272,7 @@ __export(plugin_dev_exports, {
|
|
|
405080
405272
|
runPluginDev: () => runPluginDev
|
|
405081
405273
|
});
|
|
405082
405274
|
import { existsSync as existsSync112, watch as watch3 } from "node:fs";
|
|
405083
|
-
import { join as
|
|
405275
|
+
import { join as join150, resolve as resolve97 } from "node:path";
|
|
405084
405276
|
async function runSupervisedCommand(command, cwd, timeoutMs = 12e4) {
|
|
405085
405277
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
405086
405278
|
const child = superviseSpawn(command, [], {
|
|
@@ -405125,7 +405317,7 @@ async function defaultBuildFn(pluginDir) {
|
|
|
405125
405317
|
await runSupervisedCommand("npm run build", pluginDir);
|
|
405126
405318
|
}
|
|
405127
405319
|
function defaultWatchFn(pluginDir, onChange) {
|
|
405128
|
-
const watchPath = existsSync112(
|
|
405320
|
+
const watchPath = existsSync112(join150(pluginDir, "src")) ? join150(pluginDir, "src") : pluginDir;
|
|
405129
405321
|
try {
|
|
405130
405322
|
const watcher = watch3(watchPath, { recursive: true }, onChange);
|
|
405131
405323
|
return { close: () => watcher.close() };
|
|
@@ -405262,8 +405454,8 @@ __export(plugin_publish_exports, {
|
|
|
405262
405454
|
runPluginPublish: () => runPluginPublish
|
|
405263
405455
|
});
|
|
405264
405456
|
import { existsSync as existsSync113 } from "node:fs";
|
|
405265
|
-
import { readFile as
|
|
405266
|
-
import { join as
|
|
405457
|
+
import { readFile as readFile62 } from "node:fs/promises";
|
|
405458
|
+
import { join as join151, resolve as resolve98 } from "node:path";
|
|
405267
405459
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
405268
405460
|
function classifyVersionBump(previous, next) {
|
|
405269
405461
|
const previousMatch = STRICT_SEMVER.exec(previous);
|
|
@@ -405288,8 +405480,8 @@ function asRecord7(value) {
|
|
|
405288
405480
|
return value && typeof value === "object" ? value : void 0;
|
|
405289
405481
|
}
|
|
405290
405482
|
async function readPackageJsonVersion(pluginDir) {
|
|
405291
|
-
const packageJsonPath =
|
|
405292
|
-
const packageJson = JSON.parse(await
|
|
405483
|
+
const packageJsonPath = join151(pluginDir, "package.json");
|
|
405484
|
+
const packageJson = JSON.parse(await readFile62(packageJsonPath, "utf-8"));
|
|
405293
405485
|
return typeof packageJson.version === "string" ? packageJson.version : void 0;
|
|
405294
405486
|
}
|
|
405295
405487
|
function collectDeclaredFunctionHooks(value, prefix, checks) {
|
|
@@ -405592,7 +405784,7 @@ __export(research_exports, {
|
|
|
405592
405784
|
runResearchShow: () => runResearchShow
|
|
405593
405785
|
});
|
|
405594
405786
|
import { writeFile as writeFile43 } from "node:fs/promises";
|
|
405595
|
-
import { join as
|
|
405787
|
+
import { join as join152, resolve as resolve99 } from "node:path";
|
|
405596
405788
|
async function withResolvedStore(projectName, fn2) {
|
|
405597
405789
|
const owned = await getStore2(projectName);
|
|
405598
405790
|
try {
|
|
@@ -405792,7 +405984,7 @@ async function runResearchExport(options) {
|
|
|
405792
405984
|
}
|
|
405793
405985
|
const content = format === "json" ? JSON.stringify(run2, null, 2) : renderMarkdown(run2);
|
|
405794
405986
|
const ext = format === "json" ? "json" : "md";
|
|
405795
|
-
const outputPath = options.output ? resolve99(options.output) :
|
|
405987
|
+
const outputPath = options.output ? resolve99(options.output) : join152(process.cwd(), `research-${run2.id.toLowerCase()}.${ext}`);
|
|
405796
405988
|
await writeFile43(outputPath, content, "utf8");
|
|
405797
405989
|
await retryOnLock(
|
|
405798
405990
|
async () => store.getResearchStore().createExport(run2.id, format, content),
|
|
@@ -405870,7 +406062,7 @@ var experiment_finalize_exports = {};
|
|
|
405870
406062
|
__export(experiment_finalize_exports, {
|
|
405871
406063
|
runExperimentFinalize: () => runExperimentFinalize
|
|
405872
406064
|
});
|
|
405873
|
-
import { readFile as
|
|
406065
|
+
import { readFile as readFile63 } from "node:fs/promises";
|
|
405874
406066
|
import { resolve as resolve100 } from "node:path";
|
|
405875
406067
|
function printJson(payload) {
|
|
405876
406068
|
result(JSON.stringify(payload, null, 2) + "\n");
|
|
@@ -405883,7 +406075,7 @@ function printPlan(plan) {
|
|
|
405883
406075
|
}
|
|
405884
406076
|
}
|
|
405885
406077
|
async function parsePlanOverride(path14) {
|
|
405886
|
-
const content = await
|
|
406078
|
+
const content = await readFile63(resolve100(path14), "utf8");
|
|
405887
406079
|
return JSON.parse(content);
|
|
405888
406080
|
}
|
|
405889
406081
|
async function exitWithError(error3, shutdown) {
|
|
@@ -406336,7 +406528,7 @@ __export(onboard_autolaunch_exports, {
|
|
|
406336
406528
|
shouldAutoLaunchOnboarding: () => shouldAutoLaunchOnboarding
|
|
406337
406529
|
});
|
|
406338
406530
|
import { existsSync as existsSync115 } from "node:fs";
|
|
406339
|
-
import { join as
|
|
406531
|
+
import { join as join153 } from "node:path";
|
|
406340
406532
|
function shouldAutoLaunchOnboarding(input) {
|
|
406341
406533
|
const env = input.env ?? process.env;
|
|
406342
406534
|
if (input.command === "serve" || input.command === "daemon") {
|
|
@@ -406403,8 +406595,8 @@ async function maybeAutoLaunchOnboarding(deps) {
|
|
|
406403
406595
|
const pathExists4 = deps.pathExists ?? existsSync115;
|
|
406404
406596
|
const centralDbPath = deps.centralDbPath ?? getDefaultCentralDbPath();
|
|
406405
406597
|
const cwd = deps.cwd ?? process.cwd();
|
|
406406
|
-
const projectMarkerPath =
|
|
406407
|
-
const legacyProjectDbPath =
|
|
406598
|
+
const projectMarkerPath = join153(cwd, ".fusion", "project.json");
|
|
406599
|
+
const legacyProjectDbPath = join153(cwd, ".fusion", "fusion.db");
|
|
406408
406600
|
centralDbExists = pathExists4(centralDbPath);
|
|
406409
406601
|
projectInitialized = deps.projectInitialized ?? (pathExists4(projectMarkerPath) || pathExists4(legacyProjectDbPath));
|
|
406410
406602
|
} catch (error3) {
|
|
@@ -406460,7 +406652,7 @@ __export(native_patch_exports, {
|
|
|
406460
406652
|
isTerminalAvailable: () => isTerminalAvailable,
|
|
406461
406653
|
setupNativeResolution: () => setupNativeResolution
|
|
406462
406654
|
});
|
|
406463
|
-
import { join as
|
|
406655
|
+
import { join as join154, basename as basename45, dirname as dirname74 } from "node:path";
|
|
406464
406656
|
import { existsSync as existsSync116, copyFileSync as copyFileSync2, mkdirSync as mkdirSync25, symlinkSync as symlinkSync7, rmSync as rmSync16, lstatSync as lstatSync7, readlinkSync as readlinkSync5 } from "node:fs";
|
|
406465
406657
|
import { tmpdir as tmpdir22 } from "node:os";
|
|
406466
406658
|
function findStagedNativeDir2() {
|
|
@@ -406468,13 +406660,13 @@ function findStagedNativeDir2() {
|
|
|
406468
406660
|
const arch = process.arch === "arm64" ? "arm64" : process.arch === "x64" ? "x64" : "unknown";
|
|
406469
406661
|
const prebuildName = `${platform6}-${arch}`;
|
|
406470
406662
|
const execDir = dirname74(process.execPath);
|
|
406471
|
-
const nextToBinary =
|
|
406472
|
-
if (existsSync116(
|
|
406663
|
+
const nextToBinary = join154(execDir, "runtime", prebuildName);
|
|
406664
|
+
if (existsSync116(join154(nextToBinary, "pty.node"))) {
|
|
406473
406665
|
return nextToBinary;
|
|
406474
406666
|
}
|
|
406475
406667
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
406476
|
-
const envPath =
|
|
406477
|
-
if (existsSync116(
|
|
406668
|
+
const envPath = join154(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
406669
|
+
if (existsSync116(join154(envPath, "pty.node"))) {
|
|
406478
406670
|
return envPath;
|
|
406479
406671
|
}
|
|
406480
406672
|
}
|
|
@@ -406507,17 +406699,17 @@ function setupNativeResolution() {
|
|
|
406507
406699
|
process.env.NODE_PTY_SPAWN_HELPER_DIR = nativeDir;
|
|
406508
406700
|
}
|
|
406509
406701
|
process.env.FUSION_NATIVE_ASSETS_PATH = nativeDir;
|
|
406510
|
-
const tmpRoot =
|
|
406511
|
-
const fnDir =
|
|
406512
|
-
const prebuildsDir =
|
|
406513
|
-
const platformDir =
|
|
406702
|
+
const tmpRoot = join154(tmpdir22(), `fn-bunfs-${process.pid}`);
|
|
406703
|
+
const fnDir = join154(tmpRoot, "fn");
|
|
406704
|
+
const prebuildsDir = join154(fnDir, "prebuilds");
|
|
406705
|
+
const platformDir = join154(prebuildsDir, basename45(nativeDir));
|
|
406514
406706
|
try {
|
|
406515
406707
|
cleanupStaleBunfsLinks();
|
|
406516
406708
|
mkdirSync25(platformDir, { recursive: true });
|
|
406517
|
-
const ptyNodeDest =
|
|
406518
|
-
copyFileSync2(
|
|
406519
|
-
if (existsSync116(
|
|
406520
|
-
copyFileSync2(
|
|
406709
|
+
const ptyNodeDest = join154(platformDir, "pty.node");
|
|
406710
|
+
copyFileSync2(join154(nativeDir, "pty.node"), ptyNodeDest);
|
|
406711
|
+
if (existsSync116(join154(nativeDir, "spawn-helper"))) {
|
|
406712
|
+
copyFileSync2(join154(nativeDir, "spawn-helper"), join154(platformDir, "spawn-helper"));
|
|
406521
406713
|
}
|
|
406522
406714
|
process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
|
|
406523
406715
|
if (process.platform !== "win32") {
|
|
@@ -406595,7 +406787,7 @@ var init_native_patch = __esm({
|
|
|
406595
406787
|
init_output();
|
|
406596
406788
|
import { existsSync as existsSync117, mkdtempSync as mkdtempSync5, readFileSync as readFileSync47, symlinkSync as symlinkSync8, writeFileSync as writeFileSync24 } from "node:fs";
|
|
406597
406789
|
import { createRequire as createRequire14 } from "node:module";
|
|
406598
|
-
import { join as
|
|
406790
|
+
import { join as join155, dirname as dirname75, resolve as resolve102 } from "node:path";
|
|
406599
406791
|
import { tmpdir as tmpdir23 } from "node:os";
|
|
406600
406792
|
import { performance as performance4 } from "node:perf_hooks";
|
|
406601
406793
|
import { Readable as Readable5 } from "node:stream";
|
|
@@ -406605,7 +406797,7 @@ function configurePiPackage() {
|
|
|
406605
406797
|
if (process.env.PI_PACKAGE_DIR) {
|
|
406606
406798
|
return;
|
|
406607
406799
|
}
|
|
406608
|
-
const tmp = mkdtempSync5(
|
|
406800
|
+
const tmp = mkdtempSync5(join155(tmpdir23(), "fn-pkg-"));
|
|
406609
406801
|
let packageJson = {
|
|
406610
406802
|
name: "pi",
|
|
406611
406803
|
version: "0.1.0",
|
|
@@ -406617,9 +406809,9 @@ function configurePiPackage() {
|
|
|
406617
406809
|
const piPackageDir = dirname75(piPackagePath);
|
|
406618
406810
|
packageJson = JSON.parse(readFileSync47(piPackagePath, "utf-8"));
|
|
406619
406811
|
for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
|
|
406620
|
-
const source =
|
|
406812
|
+
const source = join155(piPackageDir, entry);
|
|
406621
406813
|
if (existsSync117(source)) {
|
|
406622
|
-
symlinkSync8(source,
|
|
406814
|
+
symlinkSync8(source, join155(tmp, entry));
|
|
406623
406815
|
}
|
|
406624
406816
|
}
|
|
406625
406817
|
} catch {
|
|
@@ -406628,7 +406820,7 @@ function configurePiPackage() {
|
|
|
406628
406820
|
...packageJson.piConfig ?? {},
|
|
406629
406821
|
configDir: ".fusion"
|
|
406630
406822
|
};
|
|
406631
|
-
writeFileSync24(
|
|
406823
|
+
writeFileSync24(join155(tmp, "package.json"), JSON.stringify(packageJson, null, 2) + "\n");
|
|
406632
406824
|
process.env.PI_PACKAGE_DIR = tmp;
|
|
406633
406825
|
}
|
|
406634
406826
|
configurePiPackage();
|
|
@@ -406657,8 +406849,8 @@ function loadEnvFile(path14) {
|
|
|
406657
406849
|
}
|
|
406658
406850
|
function loadLocalEnv() {
|
|
406659
406851
|
const cwd = process.cwd();
|
|
406660
|
-
loadEnvFile(
|
|
406661
|
-
loadEnvFile(
|
|
406852
|
+
loadEnvFile(join155(cwd, ".env"));
|
|
406853
|
+
loadEnvFile(join155(cwd, ".env.local"));
|
|
406662
406854
|
}
|
|
406663
406855
|
loadLocalEnv();
|
|
406664
406856
|
async function loadCommandHandlers() {
|