@runfusion/fusion 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +526 -157
- package/dist/client/assets/{AgentDetailView-B20ApPe1.js → AgentDetailView-B7j297GT.js} +4 -4
- package/dist/client/assets/AgentsView-Dvf_xUkx.js +522 -0
- package/dist/client/assets/{AgentsView-Bkk-uBij.css → AgentsView-V5GhlBYu.css} +1 -1
- package/dist/client/assets/{ChatView-oPMFwmoc.js → ChatView-BgUt38ty.js} +1 -1
- package/dist/client/assets/{DevServerView-DQrVLbK5.js → DevServerView-C2qTJch7.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DVmy6sLM.js → DirectoryPicker-DRfhg9zz.js} +1 -1
- package/dist/client/assets/{DocumentsView-DHEv-Q2a.js → DocumentsView-j8ic1xUw.js} +1 -1
- package/dist/client/assets/{InsightsView-ByyY7GX7.js → InsightsView-CpAz3o0i.js} +3 -3
- package/dist/client/assets/{MemoryView-Udiu0u8R.js → MemoryView-BcQsi_JK.js} +2 -2
- package/dist/client/assets/{NodesView-CupS-GGc.js → NodesView-Bo_Yhr4N.js} +4 -4
- package/dist/client/assets/{PiExtensionsManager-DXs2xI8K.js → PiExtensionsManager-DHt2zFg8.js} +3 -3
- package/dist/client/assets/PluginManager-BQhBHWrB.js +1 -0
- package/dist/client/assets/{ResearchView-BG9Feaeb.js → ResearchView-CLyyqAWE.js} +1 -1
- package/dist/client/assets/{RoadmapsView-BTJtmBnF.js → RoadmapsView-tG7IdOoc.js} +2 -2
- package/dist/client/assets/{SettingsModal-eNCZiHa6.js → SettingsModal-CXUGeZ0_.js} +1 -1
- package/dist/client/assets/{SettingsModal-DZ_LaEhd.js → SettingsModal-UziTDnLh.js} +3 -3
- package/dist/client/assets/{SetupWizardModal-yf79TN1L.js → SetupWizardModal-BMJL6eNR.js} +1 -1
- package/dist/client/assets/{SkillMultiselect-DOj5vX4U.js → SkillMultiselect-ILMft-Kz.js} +1 -1
- package/dist/client/assets/{SkillsView-CgnCnikX.js → SkillsView-x4_YwBz6.js} +1 -1
- package/dist/client/assets/{TodoView-67BMyICY.js → TodoView-BBYcMbXE.js} +2 -2
- package/dist/client/assets/{folder-open-D11gjHGK.js → folder-open-DDdJt8aE.js} +1 -1
- package/dist/client/assets/index-B15xwijw.css +1 -0
- package/dist/client/assets/index-DmSs2FGE.js +661 -0
- package/dist/client/assets/{list-checks-CBzPc3GA.js → list-checks-DFxQ9biT.js} +1 -1
- package/dist/client/assets/{star-BWcRk8nt.js → star-BKs1bgJN.js} +1 -1
- package/dist/client/assets/{upload-91TM4ljC.js → upload-Bb5Pidne.js} +1 -1
- package/dist/client/assets/{users-BAsI___L.js → users-BImNn91Q.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +70 -23
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/pi-claude-cli/src/__tests__/prompt-builder.test.ts +36 -0
- package/dist/pi-claude-cli/src/prompt-builder.ts +19 -28
- package/package.json +1 -1
- package/dist/client/assets/AgentsView-ChN1tgQ0.js +0 -522
- package/dist/client/assets/PluginManager-BCpiZf4_.js +0 -1
- package/dist/client/assets/index-BLn1R7Ob.css +0 -1
- package/dist/client/assets/index-CLAHcGnI.js +0 -656
package/dist/bin.js
CHANGED
|
@@ -81,6 +81,7 @@ var init_settings_schema = __esm({
|
|
|
81
81
|
showGitHubStarButton: true,
|
|
82
82
|
modelOnboardingComplete: void 0,
|
|
83
83
|
useClaudeCli: void 0,
|
|
84
|
+
useDroidCli: void 0,
|
|
84
85
|
// Global baseline lanes for per-role model selection
|
|
85
86
|
executionGlobalProvider: void 0,
|
|
86
87
|
executionGlobalModelId: void 0,
|
|
@@ -2706,7 +2707,7 @@ var init_db = __esm({
|
|
|
2706
2707
|
"use strict";
|
|
2707
2708
|
init_sqlite_adapter();
|
|
2708
2709
|
init_types();
|
|
2709
|
-
SCHEMA_VERSION =
|
|
2710
|
+
SCHEMA_VERSION = 57;
|
|
2710
2711
|
SCHEMA_SQL = `
|
|
2711
2712
|
-- Tasks table with JSON columns for nested data
|
|
2712
2713
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
@@ -4390,6 +4391,23 @@ CREATE INDEX IF NOT EXISTS idxTodoItemsSortOrder ON todo_items(listId, sortOrder
|
|
|
4390
4391
|
this.db.exec(`CREATE INDEX IF NOT EXISTS idxResearchExportsRunId ON research_exports(runId)`);
|
|
4391
4392
|
});
|
|
4392
4393
|
}
|
|
4394
|
+
if (version < 56) {
|
|
4395
|
+
this.applyMigration(56, () => {
|
|
4396
|
+
if (this.hasTable("chat_sessions")) {
|
|
4397
|
+
this.addColumnIfMissing("chat_sessions", "cliSessionFile", "TEXT");
|
|
4398
|
+
}
|
|
4399
|
+
});
|
|
4400
|
+
}
|
|
4401
|
+
if (version < 57) {
|
|
4402
|
+
this.applyMigration(57, () => {
|
|
4403
|
+
if (this.hasTable("ai_sessions")) {
|
|
4404
|
+
this.addColumnIfMissing("ai_sessions", "archived", "INTEGER DEFAULT 0");
|
|
4405
|
+
this.db.exec(
|
|
4406
|
+
"CREATE INDEX IF NOT EXISTS idxAiSessionsArchived ON ai_sessions(archived)"
|
|
4407
|
+
);
|
|
4408
|
+
}
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4393
4411
|
}
|
|
4394
4412
|
/**
|
|
4395
4413
|
* Run a single migration step inside a transaction and bump the version.
|
|
@@ -38006,7 +38024,7 @@ function sanitizeTitle(raw) {
|
|
|
38006
38024
|
const firstLine = raw.split(/\r?\n/).map((l) => l.trim()).find((l) => l.length > 0);
|
|
38007
38025
|
if (!firstLine) return null;
|
|
38008
38026
|
let title = firstLine.replace(/^[-*]\s+/, "").replace(/^["'`]+|["'`]+$/g, "").trim();
|
|
38009
|
-
title = title.replace(/^(?:title|subject|here(?:'s| is)(?: the)? title|generated title)\s*[
|
|
38027
|
+
title = title.replace(/^(?:title|subject|here(?:'s| is)(?: the)? title|generated title)\s*[:-]\s*/i, "").trim();
|
|
38010
38028
|
title = title.replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/(?<![*\w])\*([^*]+)\*(?![*\w])/g, "$1").replace(/(?<![_\w])_([^_]+)_(?![_\w])/g, "$1");
|
|
38011
38029
|
title = title.replace(/[.!?,;:]+$/, "").trim();
|
|
38012
38030
|
if (!title) return null;
|
|
@@ -49954,7 +49972,8 @@ var init_chat_store = __esm({
|
|
|
49954
49972
|
modelProvider: row.modelProvider ?? null,
|
|
49955
49973
|
modelId: row.modelId ?? null,
|
|
49956
49974
|
createdAt: row.createdAt,
|
|
49957
|
-
updatedAt: row.updatedAt
|
|
49975
|
+
updatedAt: row.updatedAt,
|
|
49976
|
+
cliSessionFile: row.cliSessionFile ?? null
|
|
49958
49977
|
};
|
|
49959
49978
|
}
|
|
49960
49979
|
/**
|
|
@@ -49991,7 +50010,8 @@ var init_chat_store = __esm({
|
|
|
49991
50010
|
modelProvider: input.modelProvider ?? null,
|
|
49992
50011
|
modelId: input.modelId ?? null,
|
|
49993
50012
|
createdAt: now,
|
|
49994
|
-
updatedAt: now
|
|
50013
|
+
updatedAt: now,
|
|
50014
|
+
cliSessionFile: null
|
|
49995
50015
|
};
|
|
49996
50016
|
this.db.prepare(`
|
|
49997
50017
|
INSERT INTO chat_sessions (id, agentId, title, status, projectId, modelProvider, modelId, createdAt, updatedAt)
|
|
@@ -50149,6 +50169,21 @@ var init_chat_store = __esm({
|
|
|
50149
50169
|
archiveSession(id) {
|
|
50150
50170
|
return this.updateSession(id, { status: "archived" });
|
|
50151
50171
|
}
|
|
50172
|
+
/**
|
|
50173
|
+
* Persist the pi/Claude CLI session file path for a chat. Called once,
|
|
50174
|
+
* after the SessionManager for the chat first creates its on-disk file,
|
|
50175
|
+
* so subsequent turns can reopen it via SessionManager.open.
|
|
50176
|
+
*
|
|
50177
|
+
* Does not bump updatedAt or emit events — this is internal plumbing,
|
|
50178
|
+
* not a user-visible state change.
|
|
50179
|
+
*
|
|
50180
|
+
* @param id - Session ID
|
|
50181
|
+
* @param cliSessionFile - Absolute path to the session file, or null to clear
|
|
50182
|
+
*/
|
|
50183
|
+
setCliSessionFile(id, cliSessionFile) {
|
|
50184
|
+
this.db.prepare("UPDATE chat_sessions SET cliSessionFile = ? WHERE id = ?").run(cliSessionFile, id);
|
|
50185
|
+
this.db.bumpLastModified();
|
|
50186
|
+
}
|
|
50152
50187
|
/**
|
|
50153
50188
|
* Delete a chat session and all its messages.
|
|
50154
50189
|
* Messages are cascade-deleted via foreign key constraint.
|
|
@@ -50982,7 +51017,8 @@ function toSummary(session, updatedAt) {
|
|
|
50982
51017
|
title: session.title,
|
|
50983
51018
|
projectId: session.projectId,
|
|
50984
51019
|
lockedByTab: session.lockedByTab ?? null,
|
|
50985
|
-
updatedAt
|
|
51020
|
+
updatedAt,
|
|
51021
|
+
archived: Number(session.archived ?? 0) === 1
|
|
50986
51022
|
};
|
|
50987
51023
|
}
|
|
50988
51024
|
var MAX_THINKING_BYTES, THINKING_DEBOUNCE_MS, SESSION_CLEANUP_DEFAULT_MAX_AGE_MS, SESSION_CLEANUP_INTERVAL_MS, diagnostics, AiSessionStore;
|
|
@@ -51107,17 +51143,80 @@ var init_ai_session_store = __esm({
|
|
|
51107
51143
|
listActive(projectId) {
|
|
51108
51144
|
if (projectId) {
|
|
51109
51145
|
return this.db.prepare(
|
|
51110
|
-
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt FROM ai_sessions
|
|
51111
|
-
WHERE status IN ('generating', 'awaiting_input', 'error')
|
|
51146
|
+
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt, archived FROM ai_sessions
|
|
51147
|
+
WHERE status IN ('generating', 'awaiting_input', 'error')
|
|
51148
|
+
AND COALESCE(archived, 0) = 0
|
|
51149
|
+
AND projectId = ?
|
|
51112
51150
|
ORDER BY updatedAt DESC`
|
|
51113
51151
|
).all(projectId);
|
|
51114
51152
|
}
|
|
51115
51153
|
return this.db.prepare(
|
|
51116
|
-
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt FROM ai_sessions
|
|
51154
|
+
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt, archived FROM ai_sessions
|
|
51117
51155
|
WHERE status IN ('generating', 'awaiting_input', 'error')
|
|
51156
|
+
AND COALESCE(archived, 0) = 0
|
|
51118
51157
|
ORDER BY updatedAt DESC`
|
|
51119
51158
|
).all();
|
|
51120
51159
|
}
|
|
51160
|
+
/**
|
|
51161
|
+
* List sessions regardless of status (including `complete`).
|
|
51162
|
+
* Used by the planning sidebar so previously completed sessions remain
|
|
51163
|
+
* selectable on refresh — `listActive` filters them out, which would
|
|
51164
|
+
* otherwise hide a session that finished while the modal was closed.
|
|
51165
|
+
* By default archived sessions are excluded; pass `includeArchived` to
|
|
51166
|
+
* surface them too. Completed sessions are pruned by `cleanupOld` after
|
|
51167
|
+
* the configured TTL, so this list does not grow unbounded.
|
|
51168
|
+
*/
|
|
51169
|
+
listAll(projectId, options) {
|
|
51170
|
+
const archivedClause = options?.includeArchived ? "" : " WHERE COALESCE(archived, 0) = 0";
|
|
51171
|
+
if (projectId) {
|
|
51172
|
+
const where = options?.includeArchived ? "WHERE projectId = ?" : "WHERE projectId = ? AND COALESCE(archived, 0) = 0";
|
|
51173
|
+
return this.db.prepare(
|
|
51174
|
+
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt, archived FROM ai_sessions
|
|
51175
|
+
${where}
|
|
51176
|
+
ORDER BY updatedAt DESC`
|
|
51177
|
+
).all(projectId);
|
|
51178
|
+
}
|
|
51179
|
+
return this.db.prepare(
|
|
51180
|
+
`SELECT id, type, status, title, projectId, lockedByTab, updatedAt, archived FROM ai_sessions
|
|
51181
|
+
${archivedClause}
|
|
51182
|
+
ORDER BY updatedAt DESC`
|
|
51183
|
+
).all();
|
|
51184
|
+
}
|
|
51185
|
+
/**
|
|
51186
|
+
* Mark a session as archived (hidden from planning sidebar). Only
|
|
51187
|
+
* terminal sessions (`complete` or `error`) are archivable — archiving
|
|
51188
|
+
* an in-flight session would orphan the live agent. Returns true when
|
|
51189
|
+
* the row was updated. Emits `ai_session:updated` so other tabs sync.
|
|
51190
|
+
*/
|
|
51191
|
+
archive(id) {
|
|
51192
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
51193
|
+
const result = this.db.prepare(
|
|
51194
|
+
`UPDATE ai_sessions
|
|
51195
|
+
SET archived = 1, updatedAt = ?
|
|
51196
|
+
WHERE id = ? AND status IN ('complete', 'error')`
|
|
51197
|
+
).run(now, id);
|
|
51198
|
+
const changed = Number(result.changes ?? 0) > 0;
|
|
51199
|
+
if (changed) {
|
|
51200
|
+
const row = this.get(id);
|
|
51201
|
+
if (row) this.emit("ai_session:updated", toSummary(row, row.updatedAt));
|
|
51202
|
+
}
|
|
51203
|
+
return changed;
|
|
51204
|
+
}
|
|
51205
|
+
/** Restore an archived session so it reappears in the sidebar. */
|
|
51206
|
+
unarchive(id) {
|
|
51207
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
51208
|
+
const result = this.db.prepare(
|
|
51209
|
+
`UPDATE ai_sessions
|
|
51210
|
+
SET archived = 0, updatedAt = ?
|
|
51211
|
+
WHERE id = ?`
|
|
51212
|
+
).run(now, id);
|
|
51213
|
+
const changed = Number(result.changes ?? 0) > 0;
|
|
51214
|
+
if (changed) {
|
|
51215
|
+
const row = this.get(id);
|
|
51216
|
+
if (row) this.emit("ai_session:updated", toSummary(row, row.updatedAt));
|
|
51217
|
+
}
|
|
51218
|
+
return changed;
|
|
51219
|
+
}
|
|
51121
51220
|
/**
|
|
51122
51221
|
* List recoverable sessions for in-memory rehydration.
|
|
51123
51222
|
* Returns full rows for sessions still in progress.
|
|
@@ -84287,25 +84386,21 @@ async function ensureNtfyHelpersReady() {
|
|
|
84287
84386
|
if (planningNtfyHelpers) {
|
|
84288
84387
|
return;
|
|
84289
84388
|
}
|
|
84290
|
-
|
|
84291
|
-
|
|
84292
|
-
|
|
84293
|
-
|
|
84294
|
-
|
|
84295
|
-
|
|
84296
|
-
|
|
84297
|
-
|
|
84298
|
-
|
|
84299
|
-
|
|
84300
|
-
|
|
84301
|
-
|
|
84302
|
-
|
|
84303
|
-
|
|
84304
|
-
|
|
84305
|
-
{ operation: "notification-service-detection" }
|
|
84306
|
-
);
|
|
84307
|
-
}
|
|
84308
|
-
} catch {
|
|
84389
|
+
const hasNotificationService = "NotificationService" in src_exports2 && typeof NotificationService === "function";
|
|
84390
|
+
const hasAllHelpers = "isNtfyEventEnabled" in src_exports2 && "buildNtfyClickUrl" in src_exports2 && "sendNtfyNotification" in src_exports2 && typeof isNtfyEventEnabled === "function" && typeof buildNtfyClickUrl === "function" && typeof sendNtfyNotification === "function";
|
|
84391
|
+
if (!hasAllHelpers) {
|
|
84392
|
+
return;
|
|
84393
|
+
}
|
|
84394
|
+
planningNtfyHelpers = {
|
|
84395
|
+
isNtfyEventEnabled,
|
|
84396
|
+
buildNtfyClickUrl,
|
|
84397
|
+
sendNtfyNotification
|
|
84398
|
+
};
|
|
84399
|
+
if (hasNotificationService) {
|
|
84400
|
+
diagnostics2.info(
|
|
84401
|
+
"NotificationService abstraction detected in engine",
|
|
84402
|
+
{ operation: "notification-service-detection" }
|
|
84403
|
+
);
|
|
84309
84404
|
}
|
|
84310
84405
|
}
|
|
84311
84406
|
function safeParseJson(text, fallback2, options) {
|
|
@@ -85338,6 +85433,7 @@ var init_planning = __esm({
|
|
|
85338
85433
|
init_sse_buffer();
|
|
85339
85434
|
init_ai_session_diagnostics();
|
|
85340
85435
|
init_src2();
|
|
85436
|
+
init_src2();
|
|
85341
85437
|
createFnAgent4 = createFnAgent2;
|
|
85342
85438
|
diagnostics2 = createSessionDiagnostics("planning");
|
|
85343
85439
|
PLANNING_SYSTEM_PROMPT = `You are a planning assistant for the fn task board system.
|
|
@@ -91748,7 +91844,9 @@ __export(chat_exports, {
|
|
|
91748
91844
|
resolveFileReferences: () => resolveFileReferences
|
|
91749
91845
|
});
|
|
91750
91846
|
import { EventEmitter as EventEmitter29 } from "node:events";
|
|
91847
|
+
import { existsSync as existsSync30 } from "node:fs";
|
|
91751
91848
|
import { join as join40, resolve as resolve18, relative as relative9 } from "node:path";
|
|
91849
|
+
import { SessionManager as SessionManager3 } from "@mariozechner/pi-coding-agent";
|
|
91752
91850
|
function __getChatDiagnostics() {
|
|
91753
91851
|
return _diagnostics;
|
|
91754
91852
|
}
|
|
@@ -91759,12 +91857,8 @@ async function ensureEngineReady5() {
|
|
|
91759
91857
|
if (buildAgentChatPromptFn) {
|
|
91760
91858
|
return;
|
|
91761
91859
|
}
|
|
91762
|
-
|
|
91763
|
-
|
|
91764
|
-
if ("buildAgentChatPrompt" in engine && typeof engine.buildAgentChatPrompt === "function") {
|
|
91765
|
-
buildAgentChatPromptFn = engine.buildAgentChatPrompt;
|
|
91766
|
-
}
|
|
91767
|
-
} catch {
|
|
91860
|
+
if ("buildAgentChatPrompt" in src_exports2 && typeof buildAgentChatPrompt === "function") {
|
|
91861
|
+
buildAgentChatPromptFn = buildAgentChatPrompt;
|
|
91768
91862
|
}
|
|
91769
91863
|
}
|
|
91770
91864
|
function formatAttachmentSize(size) {
|
|
@@ -91874,6 +91968,7 @@ var init_chat = __esm({
|
|
|
91874
91968
|
init_src();
|
|
91875
91969
|
init_sse_buffer();
|
|
91876
91970
|
init_src2();
|
|
91971
|
+
init_src2();
|
|
91877
91972
|
createFnAgent8 = createFnAgent2;
|
|
91878
91973
|
defaultDiagnostics = {
|
|
91879
91974
|
log(message, ...args) {
|
|
@@ -92000,6 +92095,48 @@ var init_chat = __esm({
|
|
|
92000
92095
|
}
|
|
92001
92096
|
agentStoreReady;
|
|
92002
92097
|
activeGenerations = /* @__PURE__ */ new Map();
|
|
92098
|
+
/**
|
|
92099
|
+
* Resolve the per-chat pi/Claude CLI SessionManager.
|
|
92100
|
+
*
|
|
92101
|
+
* - If the chat has a recorded session file that still exists on disk,
|
|
92102
|
+
* reopen it so the CLI --resume sees the full prior transcript.
|
|
92103
|
+
* - Otherwise, create a fresh file-backed session and persist its path
|
|
92104
|
+
* on the chat row. The path is computed synchronously by SessionManager
|
|
92105
|
+
* on construction, so we can store it before the first prompt() call.
|
|
92106
|
+
* - If a recorded path has gone missing (manual cleanup, disk wipe), fall
|
|
92107
|
+
* through to "create" and overwrite the stale pointer.
|
|
92108
|
+
*
|
|
92109
|
+
* Note: we deliberately use file-backed sessions even though pi's history
|
|
92110
|
+
* is also tracked in chat_messages. The file is what the Claude CLI's
|
|
92111
|
+
* --resume reads, and its session id is what pi-claude-cli passes as
|
|
92112
|
+
* `--session-id`. Pinning both via SessionManager.open is the only way to
|
|
92113
|
+
* keep the CLI session stable across user messages.
|
|
92114
|
+
*/
|
|
92115
|
+
resolveCliSessionManager(session) {
|
|
92116
|
+
if (session.cliSessionFile && existsSync30(session.cliSessionFile)) {
|
|
92117
|
+
try {
|
|
92118
|
+
return SessionManager3.open(session.cliSessionFile);
|
|
92119
|
+
} catch (err) {
|
|
92120
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
92121
|
+
diagnostics6.warn(
|
|
92122
|
+
`Failed to reopen chat ${session.id} CLI session at ${session.cliSessionFile} (${message}); starting fresh`
|
|
92123
|
+
);
|
|
92124
|
+
}
|
|
92125
|
+
}
|
|
92126
|
+
const manager = SessionManager3.create(this.rootDir);
|
|
92127
|
+
const sessionFile = manager.getSessionFile();
|
|
92128
|
+
if (sessionFile) {
|
|
92129
|
+
try {
|
|
92130
|
+
this.chatStore.setCliSessionFile(session.id, sessionFile);
|
|
92131
|
+
} catch (err) {
|
|
92132
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
92133
|
+
diagnostics6.warn(
|
|
92134
|
+
`Failed to persist CLI session file for chat ${session.id}: ${message}`
|
|
92135
|
+
);
|
|
92136
|
+
}
|
|
92137
|
+
}
|
|
92138
|
+
return manager;
|
|
92139
|
+
}
|
|
92003
92140
|
async listAgentsForMentions() {
|
|
92004
92141
|
if (!this.agentStore) {
|
|
92005
92142
|
return [];
|
|
@@ -92197,30 +92334,15 @@ var init_chat = __esm({
|
|
|
92197
92334
|
${mentionContext}`;
|
|
92198
92335
|
}
|
|
92199
92336
|
}
|
|
92200
|
-
const allMessages = this.chatStore.getMessages(sessionId, { limit: 1e4 }) ?? [];
|
|
92201
|
-
const previousMessages = allMessages.slice(-51, -1);
|
|
92202
|
-
const conversationMessages = previousMessages.filter(
|
|
92203
|
-
(message) => message.role === "user" || message.role === "assistant"
|
|
92204
|
-
);
|
|
92205
92337
|
const resolvedContent = await resolveFileReferences(content, this.rootDir);
|
|
92206
92338
|
const attachmentSummary = attachments && attachments.length > 0 ? `[User attached: ${attachments.map((attachment) => `${attachment.originalName} (${attachment.mimeType}, ${formatAttachmentSize(attachment.size)})`).join(", ")}]` : "";
|
|
92207
|
-
const promptContent =
|
|
92208
|
-
|
|
92209
|
-
"",
|
|
92210
|
-
...conversationMessages.map((message) => {
|
|
92211
|
-
const speaker = message.role === "user" ? "User" : "Assistant";
|
|
92212
|
-
return `[${speaker}]: ${message.content}`;
|
|
92213
|
-
}),
|
|
92214
|
-
"",
|
|
92215
|
-
"## Current Message",
|
|
92216
|
-
"",
|
|
92217
|
-
attachmentSummary,
|
|
92218
|
-
resolvedContent
|
|
92219
|
-
].filter(Boolean).join("\n") : [attachmentSummary, resolvedContent].filter(Boolean).join("\n\n");
|
|
92339
|
+
const promptContent = [attachmentSummary, resolvedContent].filter(Boolean).join("\n\n");
|
|
92340
|
+
const sessionManager = this.resolveCliSessionManager(session);
|
|
92220
92341
|
agentResult = await createFnAgent8({
|
|
92221
92342
|
cwd: this.rootDir,
|
|
92222
92343
|
systemPrompt,
|
|
92223
92344
|
tools: "coding",
|
|
92345
|
+
sessionManager,
|
|
92224
92346
|
...effectiveModelProvider && effectiveModelId ? {
|
|
92225
92347
|
defaultProvider: effectiveModelProvider,
|
|
92226
92348
|
defaultModelId: effectiveModelId
|
|
@@ -98688,6 +98810,12 @@ function registerSettingsMemoryRoutes(ctx, deps) {
|
|
|
98688
98810
|
prevUseClaudeCli = priorGlobal.useClaudeCli === true;
|
|
98689
98811
|
} catch {
|
|
98690
98812
|
}
|
|
98813
|
+
let prevUseDroidCli = false;
|
|
98814
|
+
try {
|
|
98815
|
+
const priorGlobal = await store.getGlobalSettingsStore().getSettings();
|
|
98816
|
+
prevUseDroidCli = priorGlobal.useDroidCli === true;
|
|
98817
|
+
} catch {
|
|
98818
|
+
}
|
|
98691
98819
|
const settings = await store.updateGlobalSettings(req.body);
|
|
98692
98820
|
invalidateAllGlobalSettingsCaches();
|
|
98693
98821
|
const engineManager = options?.engineManager;
|
|
@@ -98706,6 +98834,16 @@ function registerSettingsMemoryRoutes(ctx, deps) {
|
|
|
98706
98834
|
);
|
|
98707
98835
|
}
|
|
98708
98836
|
}
|
|
98837
|
+
const nextUseDroidCli = settings.useDroidCli === true;
|
|
98838
|
+
if (options?.onUseDroidCliToggled && prevUseDroidCli !== nextUseDroidCli) {
|
|
98839
|
+
try {
|
|
98840
|
+
options.onUseDroidCliToggled(prevUseDroidCli, nextUseDroidCli);
|
|
98841
|
+
} catch (hookErr) {
|
|
98842
|
+
runtimeLogger.warn(
|
|
98843
|
+
`onUseDroidCliToggled callback threw: ${hookErr instanceof Error ? hookErr.message : String(hookErr)}`
|
|
98844
|
+
);
|
|
98845
|
+
}
|
|
98846
|
+
}
|
|
98709
98847
|
res.json(settings);
|
|
98710
98848
|
} catch (err) {
|
|
98711
98849
|
if (err instanceof ApiError) {
|
|
@@ -133696,8 +133834,7 @@ function registerAgentCoreListCreateRoutes(ctx, deps) {
|
|
|
133696
133834
|
const expectedDefaultPath = getDefaultHeartbeatProcedurePath(agent.id);
|
|
133697
133835
|
if (agent.heartbeatProcedurePath === expectedDefaultPath) {
|
|
133698
133836
|
try {
|
|
133699
|
-
|
|
133700
|
-
await ensureDefaultHeartbeatProcedureFile2(scopedStore.getRootDir(), expectedDefaultPath, HEARTBEAT_PROCEDURE2);
|
|
133837
|
+
await ensureDefaultHeartbeatProcedureFile(scopedStore.getRootDir(), expectedDefaultPath, HEARTBEAT_PROCEDURE);
|
|
133701
133838
|
} catch {
|
|
133702
133839
|
}
|
|
133703
133840
|
}
|
|
@@ -133953,11 +134090,10 @@ function registerAgentCoreRoutes(ctx, deps) {
|
|
|
133953
134090
|
throw notFound(`agent ${req.params.id} not found`);
|
|
133954
134091
|
}
|
|
133955
134092
|
const targetPath = getDefaultHeartbeatProcedurePath(req.params.id);
|
|
133956
|
-
const
|
|
133957
|
-
const filePath = await ensureDefaultHeartbeatProcedureFile2(
|
|
134093
|
+
const filePath = await ensureDefaultHeartbeatProcedureFile(
|
|
133958
134094
|
scopedStore.getRootDir(),
|
|
133959
134095
|
targetPath,
|
|
133960
|
-
|
|
134096
|
+
HEARTBEAT_PROCEDURE
|
|
133961
134097
|
);
|
|
133962
134098
|
const updated = await agentStore.updateAgent(req.params.id, {
|
|
133963
134099
|
heartbeatProcedurePath: targetPath
|
|
@@ -134046,6 +134182,7 @@ var init_register_agent_core_routes = __esm({
|
|
|
134046
134182
|
"use strict";
|
|
134047
134183
|
init_src();
|
|
134048
134184
|
init_api_error();
|
|
134185
|
+
init_src2();
|
|
134049
134186
|
}
|
|
134050
134187
|
});
|
|
134051
134188
|
|
|
@@ -135116,7 +135253,6 @@ function registerAgentReflectionRatingRoutes(ctx) {
|
|
|
135116
135253
|
try {
|
|
135117
135254
|
const { store: taskStore } = await getProjectContext3(req);
|
|
135118
135255
|
const { AgentStore: AgentStore2, ReflectionStore: ReflectionStore2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
135119
|
-
const { AgentReflectionService: AgentReflectionService2 } = await Promise.resolve().then(() => (init_src2(), src_exports2));
|
|
135120
135256
|
const agentStore = new AgentStore2({ rootDir: taskStore.getFusionDir() });
|
|
135121
135257
|
const reflectionStore = new ReflectionStore2({ rootDir: taskStore.getFusionDir() });
|
|
135122
135258
|
await agentStore.init();
|
|
@@ -135129,6 +135265,11 @@ function registerAgentReflectionRatingRoutes(ctx) {
|
|
|
135129
135265
|
if (!agent) {
|
|
135130
135266
|
throw notFound("Agent not found");
|
|
135131
135267
|
}
|
|
135268
|
+
const AgentReflectionService2 = AgentReflectionServiceBinding;
|
|
135269
|
+
if (!AgentReflectionService2) {
|
|
135270
|
+
res.status(503).json({ error: "Reflection service not available" });
|
|
135271
|
+
return;
|
|
135272
|
+
}
|
|
135132
135273
|
const reflectionService = new AgentReflectionService2({
|
|
135133
135274
|
agentStore,
|
|
135134
135275
|
taskStore,
|
|
@@ -135190,14 +135331,7 @@ function registerAgentReflectionRatingRoutes(ctx) {
|
|
|
135190
135331
|
if (!agent) {
|
|
135191
135332
|
throw notFound("Agent not found");
|
|
135192
135333
|
}
|
|
135193
|
-
|
|
135194
|
-
try {
|
|
135195
|
-
const engine = await Promise.resolve().then(() => (init_src2(), src_exports2));
|
|
135196
|
-
AgentReflectionService2 = engine.AgentReflectionService;
|
|
135197
|
-
} catch {
|
|
135198
|
-
res.status(503).json({ error: "Reflection service not available" });
|
|
135199
|
-
return;
|
|
135200
|
-
}
|
|
135334
|
+
const AgentReflectionService2 = AgentReflectionServiceBinding;
|
|
135201
135335
|
if (!AgentReflectionService2) {
|
|
135202
135336
|
res.status(503).json({ error: "Reflection service not available" });
|
|
135203
135337
|
return;
|
|
@@ -135311,10 +135445,13 @@ function registerAgentReflectionRatingRoutes(ctx) {
|
|
|
135311
135445
|
}
|
|
135312
135446
|
});
|
|
135313
135447
|
}
|
|
135448
|
+
var AgentReflectionServiceBinding;
|
|
135314
135449
|
var init_register_agent_reflection_rating_routes = __esm({
|
|
135315
135450
|
"../dashboard/src/routes/register-agent-reflection-rating-routes.ts"() {
|
|
135316
135451
|
"use strict";
|
|
135317
135452
|
init_api_error();
|
|
135453
|
+
init_src2();
|
|
135454
|
+
AgentReflectionServiceBinding = "AgentReflectionService" in src_exports2 && typeof AgentReflectionService === "function" ? AgentReflectionService : void 0;
|
|
135318
135455
|
}
|
|
135319
135456
|
});
|
|
135320
135457
|
|
|
@@ -138898,6 +139035,99 @@ var init_claude_cli_probe = __esm({
|
|
|
138898
139035
|
}
|
|
138899
139036
|
});
|
|
138900
139037
|
|
|
139038
|
+
// ../dashboard/src/droid-cli-probe.ts
|
|
139039
|
+
import { spawn as spawn11 } from "node:child_process";
|
|
139040
|
+
async function probeDroidCli(options = {}) {
|
|
139041
|
+
const startedAt = Date.now();
|
|
139042
|
+
const timeoutMs = options.timeoutMs ?? PROBE_TIMEOUT_MS2;
|
|
139043
|
+
const binaryPath = await tryResolveBinaryPath4("droid");
|
|
139044
|
+
return new Promise((resolvePromise) => {
|
|
139045
|
+
const finish = (result) => {
|
|
139046
|
+
resolvePromise({ ...result, probeDurationMs: Date.now() - startedAt });
|
|
139047
|
+
};
|
|
139048
|
+
let settled = false;
|
|
139049
|
+
const child = spawn11(binaryPath ?? "droid", ["--version"], {
|
|
139050
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
139051
|
+
});
|
|
139052
|
+
const timer = setTimeout(() => {
|
|
139053
|
+
if (settled) return;
|
|
139054
|
+
settled = true;
|
|
139055
|
+
try {
|
|
139056
|
+
child.kill("SIGKILL");
|
|
139057
|
+
} catch {
|
|
139058
|
+
}
|
|
139059
|
+
finish({
|
|
139060
|
+
available: false,
|
|
139061
|
+
binaryPath,
|
|
139062
|
+
reason: `Probe timed out after ${timeoutMs}ms`
|
|
139063
|
+
});
|
|
139064
|
+
}, timeoutMs);
|
|
139065
|
+
let stdout = "";
|
|
139066
|
+
let stderr = "";
|
|
139067
|
+
child.stdout?.on("data", (chunk) => {
|
|
139068
|
+
stdout += chunk.toString("utf-8");
|
|
139069
|
+
});
|
|
139070
|
+
child.stderr?.on("data", (chunk) => {
|
|
139071
|
+
stderr += chunk.toString("utf-8");
|
|
139072
|
+
});
|
|
139073
|
+
child.on("error", (err) => {
|
|
139074
|
+
if (settled) return;
|
|
139075
|
+
settled = true;
|
|
139076
|
+
clearTimeout(timer);
|
|
139077
|
+
const isNotFound = err.code === "ENOENT";
|
|
139078
|
+
finish({
|
|
139079
|
+
available: false,
|
|
139080
|
+
binaryPath,
|
|
139081
|
+
reason: isNotFound ? "`droid` not found on PATH" : err.message
|
|
139082
|
+
});
|
|
139083
|
+
});
|
|
139084
|
+
child.on("close", (code) => {
|
|
139085
|
+
if (settled) return;
|
|
139086
|
+
settled = true;
|
|
139087
|
+
clearTimeout(timer);
|
|
139088
|
+
if (code === 0) {
|
|
139089
|
+
finish({
|
|
139090
|
+
available: true,
|
|
139091
|
+
version: stdout.trim() || void 0,
|
|
139092
|
+
binaryPath
|
|
139093
|
+
});
|
|
139094
|
+
} else {
|
|
139095
|
+
finish({
|
|
139096
|
+
available: false,
|
|
139097
|
+
binaryPath,
|
|
139098
|
+
reason: stderr.trim() || `droid --version exited with code ${String(code)}`
|
|
139099
|
+
});
|
|
139100
|
+
}
|
|
139101
|
+
});
|
|
139102
|
+
});
|
|
139103
|
+
}
|
|
139104
|
+
async function tryResolveBinaryPath4(binary) {
|
|
139105
|
+
return new Promise((resolvePromise) => {
|
|
139106
|
+
const which = process.platform === "win32" ? "where" : "which";
|
|
139107
|
+
const child = spawn11(which, [binary], { stdio: ["ignore", "pipe", "ignore"] });
|
|
139108
|
+
let out = "";
|
|
139109
|
+
child.stdout?.on("data", (chunk) => {
|
|
139110
|
+
out += chunk.toString("utf-8");
|
|
139111
|
+
});
|
|
139112
|
+
child.on("error", () => resolvePromise(void 0));
|
|
139113
|
+
child.on("close", (code) => {
|
|
139114
|
+
if (code === 0) {
|
|
139115
|
+
const first = out.trim().split(/\r?\n/)[0];
|
|
139116
|
+
resolvePromise(first?.length ? first : void 0);
|
|
139117
|
+
} else {
|
|
139118
|
+
resolvePromise(void 0);
|
|
139119
|
+
}
|
|
139120
|
+
});
|
|
139121
|
+
});
|
|
139122
|
+
}
|
|
139123
|
+
var PROBE_TIMEOUT_MS2;
|
|
139124
|
+
var init_droid_cli_probe = __esm({
|
|
139125
|
+
"../dashboard/src/droid-cli-probe.ts"() {
|
|
139126
|
+
"use strict";
|
|
139127
|
+
PROBE_TIMEOUT_MS2 = 2e3;
|
|
139128
|
+
}
|
|
139129
|
+
});
|
|
139130
|
+
|
|
138901
139131
|
// ../dashboard/src/routes/register-auth-routes.ts
|
|
138902
139132
|
var registerAuthRoutes;
|
|
138903
139133
|
var init_register_auth_routes = __esm({
|
|
@@ -138905,6 +139135,7 @@ var init_register_auth_routes = __esm({
|
|
|
138905
139135
|
"use strict";
|
|
138906
139136
|
init_src();
|
|
138907
139137
|
init_claude_cli_probe();
|
|
139138
|
+
init_droid_cli_probe();
|
|
138908
139139
|
init_api_error();
|
|
138909
139140
|
init_usage();
|
|
138910
139141
|
init_project_store_resolver();
|
|
@@ -139032,6 +139263,23 @@ var init_register_auth_routes = __esm({
|
|
|
139032
139263
|
type: "cli"
|
|
139033
139264
|
});
|
|
139034
139265
|
}
|
|
139266
|
+
if (store) {
|
|
139267
|
+
let droidEnabled = false;
|
|
139268
|
+
try {
|
|
139269
|
+
const globalSettings = await store.getGlobalSettingsStore().getSettings();
|
|
139270
|
+
droidEnabled = globalSettings.useDroidCli === true;
|
|
139271
|
+
} catch {
|
|
139272
|
+
}
|
|
139273
|
+
const droidExtension = options?.getDroidCliExtensionStatus?.() ?? null;
|
|
139274
|
+
const droidBinary = await probeDroidCli();
|
|
139275
|
+
const droidExtensionOk = droidExtension === null || droidExtension.status === "ok";
|
|
139276
|
+
providers.push({
|
|
139277
|
+
id: "droid-cli",
|
|
139278
|
+
name: "Factory AI \u2014 via Droid CLI",
|
|
139279
|
+
authenticated: droidEnabled && droidBinary.available && droidExtensionOk,
|
|
139280
|
+
type: "cli"
|
|
139281
|
+
});
|
|
139282
|
+
}
|
|
139035
139283
|
const ghCli = {
|
|
139036
139284
|
available: isGhAvailable(),
|
|
139037
139285
|
authenticated: isGhAuthenticated()
|
|
@@ -139100,6 +139348,61 @@ var init_register_auth_routes = __esm({
|
|
|
139100
139348
|
rethrowAsApiError8(err);
|
|
139101
139349
|
}
|
|
139102
139350
|
});
|
|
139351
|
+
router.post("/auth/droid-cli", async (req, res) => {
|
|
139352
|
+
try {
|
|
139353
|
+
if (!store) {
|
|
139354
|
+
throw new ApiError(500, "Settings store unavailable");
|
|
139355
|
+
}
|
|
139356
|
+
const enabled = req.body?.enabled;
|
|
139357
|
+
if (typeof enabled !== "boolean") {
|
|
139358
|
+
throw badRequest("enabled must be a boolean");
|
|
139359
|
+
}
|
|
139360
|
+
if (enabled) {
|
|
139361
|
+
const binary = await probeDroidCli();
|
|
139362
|
+
if (!binary.available) {
|
|
139363
|
+
throw new ApiError(
|
|
139364
|
+
400,
|
|
139365
|
+
`Cannot enable Droid CLI routing: ${binary.reason ?? "droid binary not available"}`
|
|
139366
|
+
);
|
|
139367
|
+
}
|
|
139368
|
+
}
|
|
139369
|
+
let prev = false;
|
|
139370
|
+
try {
|
|
139371
|
+
const priorGlobal = await store.getGlobalSettingsStore().getSettings();
|
|
139372
|
+
prev = priorGlobal.useDroidCli === true;
|
|
139373
|
+
} catch {
|
|
139374
|
+
}
|
|
139375
|
+
const settings = await store.updateGlobalSettings({ useDroidCli: enabled });
|
|
139376
|
+
invalidateAllGlobalSettingsCaches();
|
|
139377
|
+
const engineManager = options?.engineManager;
|
|
139378
|
+
if (engineManager) {
|
|
139379
|
+
for (const engine of engineManager.getAllEngines().values()) {
|
|
139380
|
+
engine.getTaskStore().getGlobalSettingsStore().invalidateCache();
|
|
139381
|
+
}
|
|
139382
|
+
}
|
|
139383
|
+
const next = settings.useDroidCli === true;
|
|
139384
|
+
if (options?.onUseDroidCliToggled && prev !== next) {
|
|
139385
|
+
try {
|
|
139386
|
+
options.onUseDroidCliToggled(prev, next);
|
|
139387
|
+
} catch (hookErr) {
|
|
139388
|
+
console.warn(
|
|
139389
|
+
`[auth/droid-cli] onUseDroidCliToggled callback threw: ${hookErr instanceof Error ? hookErr.message : String(hookErr)}`
|
|
139390
|
+
);
|
|
139391
|
+
}
|
|
139392
|
+
}
|
|
139393
|
+
res.json({
|
|
139394
|
+
enabled: next,
|
|
139395
|
+
// The droid-cli provider toggle flips provider routing state and takes
|
|
139396
|
+
// effect immediately for new model selections. No restart needed.
|
|
139397
|
+
restartRequired: false
|
|
139398
|
+
});
|
|
139399
|
+
} catch (err) {
|
|
139400
|
+
if (err instanceof ApiError) {
|
|
139401
|
+
throw err;
|
|
139402
|
+
}
|
|
139403
|
+
rethrowAsApiError8(err);
|
|
139404
|
+
}
|
|
139405
|
+
});
|
|
139103
139406
|
router.get("/providers/claude-cli/status", async (_req, res) => {
|
|
139104
139407
|
try {
|
|
139105
139408
|
const binary = await probeClaudeCli();
|
|
@@ -139129,6 +139432,31 @@ var init_register_auth_routes = __esm({
|
|
|
139129
139432
|
rethrowAsApiError8(err);
|
|
139130
139433
|
}
|
|
139131
139434
|
});
|
|
139435
|
+
router.get("/providers/droid-cli/status", async (_req, res) => {
|
|
139436
|
+
try {
|
|
139437
|
+
const binary = await probeDroidCli();
|
|
139438
|
+
let enabled = false;
|
|
139439
|
+
if (store) {
|
|
139440
|
+
try {
|
|
139441
|
+
const globalSettings = await store.getGlobalSettingsStore().getSettings();
|
|
139442
|
+
enabled = globalSettings.useDroidCli === true;
|
|
139443
|
+
} catch {
|
|
139444
|
+
}
|
|
139445
|
+
}
|
|
139446
|
+
const extension2 = options?.getDroidCliExtensionStatus?.() ?? null;
|
|
139447
|
+
res.json({
|
|
139448
|
+
binary,
|
|
139449
|
+
enabled,
|
|
139450
|
+
extension: extension2,
|
|
139451
|
+
ready: binary.available && enabled && (extension2 === null || extension2.status === "ok")
|
|
139452
|
+
});
|
|
139453
|
+
} catch (err) {
|
|
139454
|
+
if (err instanceof ApiError) {
|
|
139455
|
+
throw err;
|
|
139456
|
+
}
|
|
139457
|
+
rethrowAsApiError8(err);
|
|
139458
|
+
}
|
|
139459
|
+
});
|
|
139132
139460
|
router.post("/auth/login", async (req, res) => {
|
|
139133
139461
|
try {
|
|
139134
139462
|
const { provider, origin } = req.body;
|
|
@@ -139620,7 +139948,7 @@ function stripAnsi2(str) {
|
|
|
139620
139948
|
return str.replace(/\x1B\[[0-9;]*[mGKJHFABCDSTsu]/g, "");
|
|
139621
139949
|
}
|
|
139622
139950
|
async function mintAgentApiKeyViaCli(opts) {
|
|
139623
|
-
const { spawn:
|
|
139951
|
+
const { spawn: spawn17 } = await import("node:child_process");
|
|
139624
139952
|
const bin = opts.cliBinaryPath ?? "paperclipai";
|
|
139625
139953
|
const args = [
|
|
139626
139954
|
"agent",
|
|
@@ -139644,7 +139972,7 @@ async function mintAgentApiKeyViaCli(opts) {
|
|
|
139644
139972
|
return new Promise((resolve40, reject2) => {
|
|
139645
139973
|
let child;
|
|
139646
139974
|
try {
|
|
139647
|
-
child =
|
|
139975
|
+
child = spawn17(bin, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
139648
139976
|
} catch (err) {
|
|
139649
139977
|
const code = err.code;
|
|
139650
139978
|
if (code === "ENOENT") {
|
|
@@ -139727,7 +140055,7 @@ function remapSpawnError(err, bin) {
|
|
|
139727
140055
|
return err instanceof Error ? err : new Error(String(err));
|
|
139728
140056
|
}
|
|
139729
140057
|
async function spawnPaperclipCliJson(args, opts) {
|
|
139730
|
-
const { spawn:
|
|
140058
|
+
const { spawn: spawn17 } = await import("node:child_process");
|
|
139731
140059
|
const bin = opts.cliBinaryPath ?? "paperclipai";
|
|
139732
140060
|
const fullArgs = [...args, "--json"];
|
|
139733
140061
|
if (opts.cliConfigPath) {
|
|
@@ -139738,7 +140066,7 @@ async function spawnPaperclipCliJson(args, opts) {
|
|
|
139738
140066
|
return new Promise((resolve40, reject2) => {
|
|
139739
140067
|
let child;
|
|
139740
140068
|
try {
|
|
139741
|
-
child =
|
|
140069
|
+
child = spawn17(bin, fullArgs, { stdio: ["ignore", "pipe", "pipe"] });
|
|
139742
140070
|
} catch (err) {
|
|
139743
140071
|
reject2(remapSpawnError(err, bin));
|
|
139744
140072
|
return;
|
|
@@ -140660,11 +140988,11 @@ var init_update_check = __esm({
|
|
|
140660
140988
|
});
|
|
140661
140989
|
|
|
140662
140990
|
// ../dashboard/src/cli-package-version.ts
|
|
140663
|
-
import { existsSync as
|
|
140991
|
+
import { existsSync as existsSync32, readFileSync as readFileSync11 } from "node:fs";
|
|
140664
140992
|
import { dirname as dirname15, resolve as resolve23 } from "node:path";
|
|
140665
140993
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
140666
140994
|
function readCliPackageVersion(pkgPath) {
|
|
140667
|
-
if (!
|
|
140995
|
+
if (!existsSync32(pkgPath)) {
|
|
140668
140996
|
return null;
|
|
140669
140997
|
}
|
|
140670
140998
|
try {
|
|
@@ -144301,9 +144629,8 @@ function createInsightsRouter(store) {
|
|
|
144301
144629
|
}
|
|
144302
144630
|
const existingInsights = await readInsightsMemory2(rootDir);
|
|
144303
144631
|
try {
|
|
144304
|
-
const { createFnAgent: createFnAgent13, promptWithFallback: promptWithFallback2 } = await Promise.resolve().then(() => (init_src2(), src_exports2));
|
|
144305
144632
|
let responseText = "";
|
|
144306
|
-
const { session } = await
|
|
144633
|
+
const { session } = await createFnAgent2({
|
|
144307
144634
|
cwd: rootDir,
|
|
144308
144635
|
systemPrompt: [
|
|
144309
144636
|
"You extract durable project insights from working memory notes.",
|
|
@@ -144317,7 +144644,7 @@ function createInsightsRouter(store) {
|
|
|
144317
144644
|
});
|
|
144318
144645
|
try {
|
|
144319
144646
|
const prompt = buildInsightExtractionPrompt2(workingMemory, existingInsights);
|
|
144320
|
-
await
|
|
144647
|
+
await promptWithFallback(session, prompt);
|
|
144321
144648
|
} finally {
|
|
144322
144649
|
try {
|
|
144323
144650
|
session.dispose();
|
|
@@ -144491,6 +144818,7 @@ var init_insights_routes = __esm({
|
|
|
144491
144818
|
"../dashboard/src/insights-routes.ts"() {
|
|
144492
144819
|
"use strict";
|
|
144493
144820
|
init_api_error();
|
|
144821
|
+
init_src2();
|
|
144494
144822
|
VALID_CATEGORIES = [
|
|
144495
144823
|
"quality",
|
|
144496
144824
|
"performance",
|
|
@@ -145551,7 +145879,7 @@ var init_dev_server_port_detect = __esm({
|
|
|
145551
145879
|
|
|
145552
145880
|
// ../dashboard/src/dev-server-process.ts
|
|
145553
145881
|
import { EventEmitter as EventEmitter34 } from "node:events";
|
|
145554
|
-
import { spawn as
|
|
145882
|
+
import { spawn as spawn12 } from "node:child_process";
|
|
145555
145883
|
function killManagedProcess2(child, signal) {
|
|
145556
145884
|
if (typeof child.pid !== "number") {
|
|
145557
145885
|
return;
|
|
@@ -145630,7 +145958,7 @@ var init_dev_server_process = __esm({
|
|
|
145630
145958
|
detectedUrl: void 0,
|
|
145631
145959
|
detectedPort: void 0
|
|
145632
145960
|
});
|
|
145633
|
-
const child =
|
|
145961
|
+
const child = spawn12(safeCommand, [], {
|
|
145634
145962
|
cwd: safeCwd,
|
|
145635
145963
|
detached: process.platform !== "win32",
|
|
145636
145964
|
shell: true,
|
|
@@ -148641,7 +148969,9 @@ Description: ${step.description}`
|
|
|
148641
148969
|
return;
|
|
148642
148970
|
}
|
|
148643
148971
|
const projectId = typeof req.query.projectId === "string" ? req.query.projectId : void 0;
|
|
148644
|
-
const
|
|
148972
|
+
const includeCompleted = req.query.includeCompleted === "1" || req.query.includeCompleted === "true";
|
|
148973
|
+
const includeArchived = req.query.includeArchived === "1" || req.query.includeArchived === "true";
|
|
148974
|
+
const sessions7 = includeCompleted ? aiSessionStore.listAll(projectId, { includeArchived }) : aiSessionStore.listActive(projectId);
|
|
148645
148975
|
res.json({ sessions: sessions7 });
|
|
148646
148976
|
});
|
|
148647
148977
|
router.delete("/ai-sessions/cleanup", (req, res) => {
|
|
@@ -148674,6 +149004,32 @@ Description: ${step.description}`
|
|
|
148674
149004
|
}
|
|
148675
149005
|
res.json(session);
|
|
148676
149006
|
});
|
|
149007
|
+
router.post("/ai-sessions/:id/archive", (req, res) => {
|
|
149008
|
+
if (!aiSessionStore) {
|
|
149009
|
+
throw notFound("AI sessions not available");
|
|
149010
|
+
}
|
|
149011
|
+
const session = aiSessionStore.get(req.params.id);
|
|
149012
|
+
if (!session) {
|
|
149013
|
+
throw notFound("Session not found");
|
|
149014
|
+
}
|
|
149015
|
+
if (session.status !== "complete" && session.status !== "error") {
|
|
149016
|
+
throw badRequest("Only completed or errored sessions can be archived");
|
|
149017
|
+
}
|
|
149018
|
+
aiSessionStore.archive(req.params.id);
|
|
149019
|
+
const after = aiSessionStore.get(req.params.id);
|
|
149020
|
+
res.json({ archived: Number(after?.archived ?? 0) === 1 });
|
|
149021
|
+
});
|
|
149022
|
+
router.post("/ai-sessions/:id/unarchive", (req, res) => {
|
|
149023
|
+
if (!aiSessionStore) {
|
|
149024
|
+
throw notFound("AI sessions not available");
|
|
149025
|
+
}
|
|
149026
|
+
if (!aiSessionStore.get(req.params.id)) {
|
|
149027
|
+
throw notFound("Session not found");
|
|
149028
|
+
}
|
|
149029
|
+
aiSessionStore.unarchive(req.params.id);
|
|
149030
|
+
const after = aiSessionStore.get(req.params.id);
|
|
149031
|
+
res.json({ archived: Number(after?.archived ?? 0) === 1 });
|
|
149032
|
+
});
|
|
148677
149033
|
router.post("/ai-sessions/:id/lock", (req, res) => {
|
|
148678
149034
|
if (!aiSessionStore) {
|
|
148679
149035
|
throw notFound("AI sessions not available");
|
|
@@ -149038,7 +149394,7 @@ Description: ${step.description}`
|
|
|
149038
149394
|
}
|
|
149039
149395
|
});
|
|
149040
149396
|
registerIntegratedDevServerRouter({ router, store });
|
|
149041
|
-
router.use((err,
|
|
149397
|
+
router.use((err, _req, res, next) => {
|
|
149042
149398
|
if (res.headersSent) {
|
|
149043
149399
|
next(err);
|
|
149044
149400
|
return;
|
|
@@ -149148,7 +149504,20 @@ async function executeAiPromptStep(step, timeoutMs, startedAt, taskStore) {
|
|
|
149148
149504
|
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
149149
149505
|
};
|
|
149150
149506
|
}
|
|
149151
|
-
const
|
|
149507
|
+
const createFnAgent13 = createFnAgentForRefine;
|
|
149508
|
+
const promptWithFallback2 = promptWithFallback;
|
|
149509
|
+
if (!createFnAgent13) {
|
|
149510
|
+
return {
|
|
149511
|
+
stepId: step.id,
|
|
149512
|
+
stepName: step.name,
|
|
149513
|
+
stepIndex: 0,
|
|
149514
|
+
success: false,
|
|
149515
|
+
output: "",
|
|
149516
|
+
error: "AI agent not available",
|
|
149517
|
+
startedAt,
|
|
149518
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
149519
|
+
};
|
|
149520
|
+
}
|
|
149152
149521
|
const settings = await taskStore.getSettings();
|
|
149153
149522
|
const defaultModel = resolveProjectDefaultModel(settings);
|
|
149154
149523
|
const modelProvider = step.modelProvider?.trim() || defaultModel.provider;
|
|
@@ -154393,7 +154762,7 @@ var init_auth_middleware = __esm({
|
|
|
154393
154762
|
import express from "express";
|
|
154394
154763
|
import { randomUUID as randomUUID21 } from "node:crypto";
|
|
154395
154764
|
import { join as join51, dirname as dirname18 } from "node:path";
|
|
154396
|
-
import { existsSync as
|
|
154765
|
+
import { existsSync as existsSync34, readFileSync as readFileSync13 } from "node:fs";
|
|
154397
154766
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
154398
154767
|
import { createSecureServer as createHttp2SecureServer } from "node:http2";
|
|
154399
154768
|
function parseVersion2(version) {
|
|
@@ -154575,7 +154944,7 @@ function createServer(store, options) {
|
|
|
154575
154944
|
getTerminalService(store.getRootDir());
|
|
154576
154945
|
const isHeadless = options?.headless === true;
|
|
154577
154946
|
const execDir = dirname18(process.execPath);
|
|
154578
|
-
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR :
|
|
154947
|
+
const clientDir = process.env.FUSION_CLIENT_DIR ? process.env.FUSION_CLIENT_DIR : existsSync34(join51(execDir, "client", "index.html")) ? join51(execDir, "client") : existsSync34(join51(__dirname, "..", "dist", "client")) ? join51(__dirname, "..", "dist", "client") : join51(__dirname, "..", "client");
|
|
154579
154948
|
if (!isHeadless) {
|
|
154580
154949
|
app.get("/version.json", (_req, res) => {
|
|
154581
154950
|
res.setHeader("Cache-Control", "no-store, max-age=0");
|
|
@@ -156161,7 +156530,7 @@ var init_port_prompt = __esm({
|
|
|
156161
156530
|
});
|
|
156162
156531
|
|
|
156163
156532
|
// src/commands/provider-settings.ts
|
|
156164
|
-
import { existsSync as
|
|
156533
|
+
import { existsSync as existsSync35, readFileSync as readFileSync14, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "node:fs";
|
|
156165
156534
|
import { join as join53, dirname as dirname20, basename as basename15 } from "node:path";
|
|
156166
156535
|
function siblingAgentDir2(agentDir, siblingRoot) {
|
|
156167
156536
|
if (basename15(agentDir) !== "agent") {
|
|
@@ -156170,7 +156539,7 @@ function siblingAgentDir2(agentDir, siblingRoot) {
|
|
|
156170
156539
|
return join53(dirname20(dirname20(agentDir)), siblingRoot, "agent");
|
|
156171
156540
|
}
|
|
156172
156541
|
function readJsonObject4(path5) {
|
|
156173
|
-
if (!
|
|
156542
|
+
if (!existsSync35(path5)) {
|
|
156174
156543
|
return {};
|
|
156175
156544
|
}
|
|
156176
156545
|
try {
|
|
@@ -156202,7 +156571,7 @@ var init_provider_settings = __esm({
|
|
|
156202
156571
|
});
|
|
156203
156572
|
|
|
156204
156573
|
// src/commands/provider-auth.ts
|
|
156205
|
-
import { existsSync as
|
|
156574
|
+
import { existsSync as existsSync36, readFileSync as readFileSync15 } from "node:fs";
|
|
156206
156575
|
import { getOAuthProvider as getOAuthProvider2 } from "@mariozechner/pi-ai/oauth";
|
|
156207
156576
|
function getProviderDisplayName(providerId) {
|
|
156208
156577
|
const knownProviderNames = new Map(
|
|
@@ -156331,7 +156700,7 @@ function createReadOnlyAuthFileStorage(authPaths) {
|
|
|
156331
156700
|
const reload = () => {
|
|
156332
156701
|
const nextCredentials = {};
|
|
156333
156702
|
for (const authPath of authPaths) {
|
|
156334
|
-
if (!
|
|
156703
|
+
if (!existsSync36(authPath)) {
|
|
156335
156704
|
continue;
|
|
156336
156705
|
}
|
|
156337
156706
|
try {
|
|
@@ -156368,13 +156737,13 @@ var init_provider_auth = __esm({
|
|
|
156368
156737
|
{ id: "tavily", name: "Tavily" },
|
|
156369
156738
|
{ id: "zai", name: "Zai" }
|
|
156370
156739
|
];
|
|
156371
|
-
CLI_PROVIDER_IDS = /* @__PURE__ */ new Set(["pi-claude-cli"]);
|
|
156740
|
+
CLI_PROVIDER_IDS = /* @__PURE__ */ new Set(["pi-claude-cli", "droid-cli"]);
|
|
156372
156741
|
}
|
|
156373
156742
|
});
|
|
156374
156743
|
|
|
156375
156744
|
// src/commands/auth-paths.ts
|
|
156376
156745
|
import { homedir as homedir9 } from "node:os";
|
|
156377
|
-
import { existsSync as
|
|
156746
|
+
import { existsSync as existsSync37, readFileSync as readFileSync16 } from "node:fs";
|
|
156378
156747
|
import { join as join54 } from "node:path";
|
|
156379
156748
|
function getFusionAgentDir3(home = process.env.HOME || process.env.USERPROFILE || homedir9()) {
|
|
156380
156749
|
return join54(home, ".fusion", "agent");
|
|
@@ -156402,13 +156771,13 @@ function getLegacyModelsPaths2(home = process.env.HOME || process.env.USERPROFIL
|
|
|
156402
156771
|
}
|
|
156403
156772
|
function getModelRegistryModelsPath2(home = process.env.HOME || process.env.USERPROFILE || homedir9()) {
|
|
156404
156773
|
const fusionModelsPath = getFusionModelsPath2(home);
|
|
156405
|
-
if (
|
|
156774
|
+
if (existsSync37(fusionModelsPath)) {
|
|
156406
156775
|
return fusionModelsPath;
|
|
156407
156776
|
}
|
|
156408
|
-
return getLegacyModelsPaths2(home).find((modelsPath) =>
|
|
156777
|
+
return getLegacyModelsPaths2(home).find((modelsPath) => existsSync37(modelsPath)) ?? fusionModelsPath;
|
|
156409
156778
|
}
|
|
156410
156779
|
function readJsonObject5(path5) {
|
|
156411
|
-
if (!
|
|
156780
|
+
if (!existsSync37(path5)) {
|
|
156412
156781
|
return {};
|
|
156413
156782
|
}
|
|
156414
156783
|
try {
|
|
@@ -156426,13 +156795,13 @@ function getPackageManagerAgentDir2(home = process.env.HOME || process.env.USERP
|
|
|
156426
156795
|
const legacyAgentDir = getLegacyAgentDir(home);
|
|
156427
156796
|
const fusionSettings = readJsonObject5(join54(fusionAgentDir, "settings.json"));
|
|
156428
156797
|
const legacySettings = readJsonObject5(join54(legacyAgentDir, "settings.json"));
|
|
156429
|
-
if (hasPackageManagerSettings3(fusionSettings) || !
|
|
156798
|
+
if (hasPackageManagerSettings3(fusionSettings) || !existsSync37(legacyAgentDir)) {
|
|
156430
156799
|
return fusionAgentDir;
|
|
156431
156800
|
}
|
|
156432
156801
|
if (hasPackageManagerSettings3(legacySettings)) {
|
|
156433
156802
|
return legacyAgentDir;
|
|
156434
156803
|
}
|
|
156435
|
-
return
|
|
156804
|
+
return existsSync37(fusionAgentDir) ? fusionAgentDir : legacyAgentDir;
|
|
156436
156805
|
}
|
|
156437
156806
|
var init_auth_paths2 = __esm({
|
|
156438
156807
|
"src/commands/auth-paths.ts"() {
|
|
@@ -156590,7 +156959,7 @@ var init_project_context = __esm({
|
|
|
156590
156959
|
// src/commands/claude-skills.ts
|
|
156591
156960
|
import {
|
|
156592
156961
|
cpSync,
|
|
156593
|
-
existsSync as
|
|
156962
|
+
existsSync as existsSync38,
|
|
156594
156963
|
lstatSync as lstatSync2,
|
|
156595
156964
|
mkdirSync as mkdirSync7,
|
|
156596
156965
|
readlinkSync,
|
|
@@ -156619,7 +156988,7 @@ function isPiClaudeCliConfigured(globalSettings) {
|
|
|
156619
156988
|
function resolveFusionSkillSource() {
|
|
156620
156989
|
const here = fileURLToPath6(import.meta.url);
|
|
156621
156990
|
const candidate = resolve28(dirname22(here), "..", "..", "skill", FUSION_SKILL_NAME);
|
|
156622
|
-
return
|
|
156991
|
+
return existsSync38(candidate) ? candidate : null;
|
|
156623
156992
|
}
|
|
156624
156993
|
function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
156625
156994
|
const target = join55(projectPath, ".claude", "skills", FUSION_SKILL_NAME);
|
|
@@ -156637,7 +157006,7 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
|
156637
157006
|
try {
|
|
156638
157007
|
mkdirSync7(dirname22(target), { recursive: true });
|
|
156639
157008
|
let replaced = false;
|
|
156640
|
-
if (
|
|
157009
|
+
if (existsSync38(target) || isBrokenSymlink(target)) {
|
|
156641
157010
|
const stat12 = lstatSync2(target);
|
|
156642
157011
|
if (stat12.isSymbolicLink()) {
|
|
156643
157012
|
const current = safeReadlink(target);
|
|
@@ -156648,7 +157017,7 @@ function installFusionSkillIntoProject(projectPath, options = {}) {
|
|
|
156648
157017
|
replaced = true;
|
|
156649
157018
|
} else {
|
|
156650
157019
|
const skillMd = join55(target, "SKILL.md");
|
|
156651
|
-
if (!
|
|
157020
|
+
if (!existsSync38(skillMd)) {
|
|
156652
157021
|
return {
|
|
156653
157022
|
outcome: "failed",
|
|
156654
157023
|
target,
|
|
@@ -156707,7 +157076,7 @@ function isBrokenSymlink(path5) {
|
|
|
156707
157076
|
try {
|
|
156708
157077
|
const stat12 = lstatSync2(path5);
|
|
156709
157078
|
if (!stat12.isSymbolicLink()) return false;
|
|
156710
|
-
return !
|
|
157079
|
+
return !existsSync38(path5);
|
|
156711
157080
|
} catch {
|
|
156712
157081
|
return false;
|
|
156713
157082
|
}
|
|
@@ -156804,7 +157173,7 @@ var init_claude_skills_runner = __esm({
|
|
|
156804
157173
|
});
|
|
156805
157174
|
|
|
156806
157175
|
// src/commands/claude-cli-extension.ts
|
|
156807
|
-
import { existsSync as
|
|
157176
|
+
import { existsSync as existsSync39, readFileSync as readFileSync17 } from "node:fs";
|
|
156808
157177
|
import { createRequire as createRequire4 } from "node:module";
|
|
156809
157178
|
import { dirname as dirname23, resolve as resolve29 } from "node:path";
|
|
156810
157179
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
@@ -156813,7 +157182,7 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
|
|
|
156813
157182
|
const here = dirname23(fileURLToPath7(moduleUrl));
|
|
156814
157183
|
for (const rel of ["pi-claude-cli", "../pi-claude-cli", "../../pi-claude-cli"]) {
|
|
156815
157184
|
const candidate = resolve29(here, rel, "package.json");
|
|
156816
|
-
if (
|
|
157185
|
+
if (existsSync39(candidate)) {
|
|
156817
157186
|
pkgJsonPath = candidate;
|
|
156818
157187
|
break;
|
|
156819
157188
|
}
|
|
@@ -156849,7 +157218,7 @@ function resolveClaudeCliExtensionFromModuleUrl(moduleUrl) {
|
|
|
156849
157218
|
};
|
|
156850
157219
|
}
|
|
156851
157220
|
const entryPath = resolve29(dirname23(pkgJsonPath), rawEntry);
|
|
156852
|
-
if (!
|
|
157221
|
+
if (!existsSync39(entryPath)) {
|
|
156853
157222
|
return {
|
|
156854
157223
|
status: "missing-entry",
|
|
156855
157224
|
reason: `@fusion/pi-claude-cli extension file not found at ${entryPath}`
|
|
@@ -156936,7 +157305,7 @@ var init_update_cache = __esm({
|
|
|
156936
157305
|
});
|
|
156937
157306
|
|
|
156938
157307
|
// src/commands/self-extension.ts
|
|
156939
|
-
import { existsSync as
|
|
157308
|
+
import { existsSync as existsSync40, readFileSync as readFileSync19 } from "node:fs";
|
|
156940
157309
|
import { dirname as dirname24, resolve as resolve30 } from "node:path";
|
|
156941
157310
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
156942
157311
|
function resolveSelfExtension() {
|
|
@@ -156944,7 +157313,7 @@ function resolveSelfExtension() {
|
|
|
156944
157313
|
let pkgDir;
|
|
156945
157314
|
let cur = here;
|
|
156946
157315
|
for (let i = 0; i < 5; i++) {
|
|
156947
|
-
if (
|
|
157316
|
+
if (existsSync40(resolve30(cur, "package.json"))) {
|
|
156948
157317
|
try {
|
|
156949
157318
|
const parsed = JSON.parse(readFileSync19(resolve30(cur, "package.json"), "utf-8"));
|
|
156950
157319
|
if (parsed.name === "@runfusion/fusion") {
|
|
@@ -156968,7 +157337,7 @@ function resolveSelfExtension() {
|
|
|
156968
157337
|
return { status: "missing", reason: `Failed to read @runfusion/fusion package.json: ${err instanceof Error ? err.message : String(err)}` };
|
|
156969
157338
|
}
|
|
156970
157339
|
const srcEntry = resolve30(pkgDir, "src", "extension.ts");
|
|
156971
|
-
if (
|
|
157340
|
+
if (existsSync40(srcEntry)) {
|
|
156972
157341
|
return { status: "ok", path: srcEntry, packageVersion: pkgJson.version ?? "unknown" };
|
|
156973
157342
|
}
|
|
156974
157343
|
const extensions = pkgJson.pi?.extensions;
|
|
@@ -156980,7 +157349,7 @@ function resolveSelfExtension() {
|
|
|
156980
157349
|
return { status: "missing", reason: "@runfusion/fusion pi.extensions[0] is not a valid path string" };
|
|
156981
157350
|
}
|
|
156982
157351
|
const entryPath = resolve30(pkgDir, rawEntry);
|
|
156983
|
-
if (!
|
|
157352
|
+
if (!existsSync40(entryPath)) {
|
|
156984
157353
|
return { status: "missing", reason: `@runfusion/fusion extension file not found at ${entryPath}` };
|
|
156985
157354
|
}
|
|
156986
157355
|
return { status: "ok", path: entryPath, packageVersion: pkgJson.version ?? "unknown" };
|
|
@@ -157192,7 +157561,7 @@ var init_use_projects = __esm({
|
|
|
157192
157561
|
});
|
|
157193
157562
|
|
|
157194
157563
|
// src/commands/dashboard-tui/utils.ts
|
|
157195
|
-
import { spawn as
|
|
157564
|
+
import { spawn as spawn13 } from "node:child_process";
|
|
157196
157565
|
function isTTYAvailable() {
|
|
157197
157566
|
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
157198
157567
|
}
|
|
@@ -157205,7 +157574,7 @@ async function copyToClipboard(text) {
|
|
|
157205
157574
|
for (const { cmd, args } of candidates) {
|
|
157206
157575
|
const ok = await new Promise((resolve40) => {
|
|
157207
157576
|
try {
|
|
157208
|
-
const child =
|
|
157577
|
+
const child = spawn13(cmd, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
157209
157578
|
child.once("error", () => resolve40(false));
|
|
157210
157579
|
child.once("close", (code) => resolve40(code === 0));
|
|
157211
157580
|
child.stdin.end(text);
|
|
@@ -157232,7 +157601,7 @@ import { useState as useState2, useSyncExternalStore, useCallback as useCallback
|
|
|
157232
157601
|
import { Box, Text, useInput, useApp, useStdout } from "ink";
|
|
157233
157602
|
import Spinner from "ink-spinner";
|
|
157234
157603
|
import TextInput from "ink-text-input";
|
|
157235
|
-
import { spawn as
|
|
157604
|
+
import { spawn as spawn14 } from "node:child_process";
|
|
157236
157605
|
import { appendFileSync } from "node:fs";
|
|
157237
157606
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
157238
157607
|
function tuiDebug(tag, data) {
|
|
@@ -157258,7 +157627,7 @@ function openInBrowser(url) {
|
|
|
157258
157627
|
args = [url];
|
|
157259
157628
|
}
|
|
157260
157629
|
try {
|
|
157261
|
-
const child =
|
|
157630
|
+
const child = spawn14(cmd, args, { detached: true, stdio: "ignore" });
|
|
157262
157631
|
child.unref();
|
|
157263
157632
|
} catch {
|
|
157264
157633
|
}
|
|
@@ -164575,13 +164944,13 @@ var desktop_exports = {};
|
|
|
164575
164944
|
__export(desktop_exports, {
|
|
164576
164945
|
runDesktop: () => runDesktop
|
|
164577
164946
|
});
|
|
164578
|
-
import { spawn as
|
|
164947
|
+
import { spawn as spawn15 } from "node:child_process";
|
|
164579
164948
|
import { once as once2 } from "node:events";
|
|
164580
164949
|
import { join as join60 } from "node:path";
|
|
164581
164950
|
import { createRequire as createRequire5 } from "node:module";
|
|
164582
164951
|
function runCommand(command, args, cwd) {
|
|
164583
164952
|
return new Promise((resolve40, reject2) => {
|
|
164584
|
-
const child =
|
|
164953
|
+
const child = spawn15(command, args, {
|
|
164585
164954
|
cwd,
|
|
164586
164955
|
stdio: "inherit",
|
|
164587
164956
|
env: process.env
|
|
@@ -164666,7 +165035,7 @@ async function runDesktop(options = {}) {
|
|
|
164666
165035
|
electronEnv.FUSION_DASHBOARD_URL = process.env.FUSION_DASHBOARD_URL ?? "http://localhost:5173";
|
|
164667
165036
|
electronEnv.NODE_ENV = "development";
|
|
164668
165037
|
}
|
|
164669
|
-
const electronProcess =
|
|
165038
|
+
const electronProcess = spawn15(electronBinary, electronArgs, {
|
|
164670
165039
|
cwd: rootDir,
|
|
164671
165040
|
stdio: "inherit",
|
|
164672
165041
|
env: electronEnv
|
|
@@ -164741,7 +165110,7 @@ __export(task_exports, {
|
|
|
164741
165110
|
runTaskUpdate: () => runTaskUpdate
|
|
164742
165111
|
});
|
|
164743
165112
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
164744
|
-
import { watchFile, unwatchFile, statSync as statSync6, existsSync as
|
|
165113
|
+
import { watchFile, unwatchFile, statSync as statSync6, existsSync as existsSync41, readFileSync as readFileSync20 } from "node:fs";
|
|
164745
165114
|
import { basename as basename17, join as join61 } from "node:path";
|
|
164746
165115
|
function getGitHubIssueUrl(sourceMetadata) {
|
|
164747
165116
|
if (!sourceMetadata || typeof sourceMetadata !== "object") return void 0;
|
|
@@ -165043,7 +165412,7 @@ async function runTaskLogs(id, options = {}, projectName) {
|
|
|
165043
165412
|
if (options.follow) {
|
|
165044
165413
|
const projectPath = projectContext?.projectPath ?? process.cwd();
|
|
165045
165414
|
const logPath = join61(projectPath, ".fusion", "tasks", id, "agent.log");
|
|
165046
|
-
if (!
|
|
165415
|
+
if (!existsSync41(logPath)) {
|
|
165047
165416
|
console.log(`
|
|
165048
165417
|
Waiting for log file to be created...`);
|
|
165049
165418
|
}
|
|
@@ -166380,7 +166749,7 @@ var settings_import_exports = {};
|
|
|
166380
166749
|
__export(settings_import_exports, {
|
|
166381
166750
|
runSettingsImport: () => runSettingsImport
|
|
166382
166751
|
});
|
|
166383
|
-
import { existsSync as
|
|
166752
|
+
import { existsSync as existsSync42 } from "node:fs";
|
|
166384
166753
|
import { resolve as resolve32 } from "node:path";
|
|
166385
166754
|
async function runSettingsImport(filePath, options = {}) {
|
|
166386
166755
|
const scope = options.scope ?? "both";
|
|
@@ -166391,7 +166760,7 @@ async function runSettingsImport(filePath, options = {}) {
|
|
|
166391
166760
|
const skipConfirm = options.yes ?? false;
|
|
166392
166761
|
try {
|
|
166393
166762
|
const resolvedPath = resolve32(filePath);
|
|
166394
|
-
if (!
|
|
166763
|
+
if (!existsSync42(resolvedPath)) {
|
|
166395
166764
|
console.error(`Error: File not found: ${filePath}`);
|
|
166396
166765
|
process.exit(1);
|
|
166397
166766
|
}
|
|
@@ -166864,7 +167233,7 @@ var init_backup2 = __esm({
|
|
|
166864
167233
|
});
|
|
166865
167234
|
|
|
166866
167235
|
// src/project-resolver.ts
|
|
166867
|
-
import { existsSync as
|
|
167236
|
+
import { existsSync as existsSync43, statSync as statSync7 } from "node:fs";
|
|
166868
167237
|
import { basename as basename18, dirname as dirname25, resolve as resolve33, normalize as normalize5 } from "node:path";
|
|
166869
167238
|
import { createInterface as createInterface5 } from "node:readline/promises";
|
|
166870
167239
|
async function getCentralCore() {
|
|
@@ -166940,7 +167309,7 @@ async function resolveProject2(options = {}) {
|
|
|
166940
167309
|
{ searchedName: options.project, availableProjects: projects.map((p) => p.name) }
|
|
166941
167310
|
);
|
|
166942
167311
|
}
|
|
166943
|
-
if (!
|
|
167312
|
+
if (!existsSync43(match.path)) {
|
|
166944
167313
|
throw new ProjectResolutionError(
|
|
166945
167314
|
`Project "${match.name}" is registered but the directory no longer exists: ${match.path}
|
|
166946
167315
|
|
|
@@ -166958,7 +167327,7 @@ Run \`fn project remove ` + match.name + "` to clean up the registry entry.",
|
|
|
166958
167327
|
const normalizedKbDir = normalize5(fusionDir);
|
|
166959
167328
|
const match = allProjects2.find((p) => normalize5(p.path) === normalizedKbDir);
|
|
166960
167329
|
if (match) {
|
|
166961
|
-
if (!
|
|
167330
|
+
if (!existsSync43(match.path)) {
|
|
166962
167331
|
throw new ProjectResolutionError(
|
|
166963
167332
|
`Project "${match.name}" is registered but the directory no longer exists: ${match.path}
|
|
166964
167333
|
|
|
@@ -167023,7 +167392,7 @@ Run \`fn project add ` + fusionDir + "` to register it, or use --project <name>.
|
|
|
167023
167392
|
}
|
|
167024
167393
|
if (allProjects.length === 1) {
|
|
167025
167394
|
const project = allProjects[0];
|
|
167026
|
-
if (!
|
|
167395
|
+
if (!existsSync43(project.path)) {
|
|
167027
167396
|
throw new ProjectResolutionError(
|
|
167028
167397
|
`The only registered project "${project.name}" has a missing directory: ${project.path}
|
|
167029
167398
|
|
|
@@ -167464,7 +167833,7 @@ __export(project_exports, {
|
|
|
167464
167833
|
runProjectShow: () => runProjectShow
|
|
167465
167834
|
});
|
|
167466
167835
|
import { resolve as resolve34, isAbsolute as isAbsolute19, relative as relative14, basename as basename19 } from "node:path";
|
|
167467
|
-
import { existsSync as
|
|
167836
|
+
import { existsSync as existsSync44, statSync as statSync8 } from "node:fs";
|
|
167468
167837
|
import { createInterface as createInterface7 } from "node:readline/promises";
|
|
167469
167838
|
function formatDisplayPath(projectPath) {
|
|
167470
167839
|
const rel = relative14(process.cwd(), projectPath);
|
|
@@ -167593,7 +167962,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167593
167962
|
projectPath = pathInput.trim() || defaultPath;
|
|
167594
167963
|
}
|
|
167595
167964
|
const absolutePath2 = isAbsolute19(projectPath) ? projectPath : resolve34(process.cwd(), projectPath);
|
|
167596
|
-
if (!
|
|
167965
|
+
if (!existsSync44(absolutePath2)) {
|
|
167597
167966
|
console.error(`
|
|
167598
167967
|
\u2717 Path does not exist: ${projectPath}`);
|
|
167599
167968
|
rl.close();
|
|
@@ -167606,7 +167975,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167606
167975
|
process.exit(1);
|
|
167607
167976
|
}
|
|
167608
167977
|
const kbDbPath2 = resolve34(absolutePath2, ".fusion", "fusion.db");
|
|
167609
|
-
if (!
|
|
167978
|
+
if (!existsSync44(kbDbPath2) && !options.force) {
|
|
167610
167979
|
console.log(`
|
|
167611
167980
|
No fn project found at ${formatDisplayPath(absolutePath2)}`);
|
|
167612
167981
|
const init = await rl.question(" Initialize fn here first? [Y/n] ");
|
|
@@ -167638,7 +168007,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167638
168007
|
process.exit(1);
|
|
167639
168008
|
}
|
|
167640
168009
|
const absolutePath = isAbsolute19(projectPath) ? projectPath : resolve34(process.cwd(), projectPath);
|
|
167641
|
-
if (!
|
|
168010
|
+
if (!existsSync44(absolutePath)) {
|
|
167642
168011
|
console.error(`
|
|
167643
168012
|
\u2717 Path does not exist: ${projectPath}
|
|
167644
168013
|
`);
|
|
@@ -167651,7 +168020,7 @@ async function runProjectAdd(name, path5, options = {}) {
|
|
|
167651
168020
|
process.exit(1);
|
|
167652
168021
|
}
|
|
167653
168022
|
const kbDbPath = resolve34(absolutePath, ".fusion", "fusion.db");
|
|
167654
|
-
if (!
|
|
168023
|
+
if (!existsSync44(kbDbPath) && !options.force) {
|
|
167655
168024
|
console.error(`
|
|
167656
168025
|
\u2717 No fn project found at ${formatDisplayPath(absolutePath)}`);
|
|
167657
168026
|
console.error(" Run `fn init` first to initialize the project.\n");
|
|
@@ -167907,7 +168276,7 @@ var init_project = __esm({
|
|
|
167907
168276
|
});
|
|
167908
168277
|
|
|
167909
168278
|
// src/commands/skill-installation.ts
|
|
167910
|
-
import { cpSync as cpSync2, existsSync as
|
|
168279
|
+
import { cpSync as cpSync2, existsSync as existsSync45, mkdirSync as mkdirSync8 } from "node:fs";
|
|
167911
168280
|
import { homedir as homedir10 } from "node:os";
|
|
167912
168281
|
import { dirname as dirname26, join as join63, resolve as resolve35 } from "node:path";
|
|
167913
168282
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
@@ -167921,7 +168290,7 @@ function getSupportedSkillInstallTargets(homeDir = process.env.HOME || process.e
|
|
|
167921
168290
|
function resolveBundledFusionSkillSource() {
|
|
167922
168291
|
const here = fileURLToPath9(import.meta.url);
|
|
167923
168292
|
const source = resolve35(dirname26(here), "..", "..", "skill", FUSION_SKILL_NAME2);
|
|
167924
|
-
return
|
|
168293
|
+
return existsSync45(source) ? source : null;
|
|
167925
168294
|
}
|
|
167926
168295
|
function installBundledFusionSkill(options = {}) {
|
|
167927
168296
|
const sourceDir = options.sourceDir ?? resolveBundledFusionSkillSource();
|
|
@@ -167939,7 +168308,7 @@ function installBundledFusionSkill(options = {}) {
|
|
|
167939
168308
|
}
|
|
167940
168309
|
const results = targets.map((target) => {
|
|
167941
168310
|
try {
|
|
167942
|
-
if (
|
|
168311
|
+
if (existsSync45(target.targetDir)) {
|
|
167943
168312
|
return {
|
|
167944
168313
|
client: target.client,
|
|
167945
168314
|
targetDir: target.targetDir,
|
|
@@ -167978,7 +168347,7 @@ var init_exports = {};
|
|
|
167978
168347
|
__export(init_exports, {
|
|
167979
168348
|
runInit: () => runInit
|
|
167980
168349
|
});
|
|
167981
|
-
import { existsSync as
|
|
168350
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync9, writeFileSync as writeFileSync3, readFileSync as readFileSync21 } from "node:fs";
|
|
167982
168351
|
import { join as join64, resolve as resolve36, basename as basename20 } from "node:path";
|
|
167983
168352
|
import { exec as exec12 } from "node:child_process";
|
|
167984
168353
|
import { promisify as promisify17 } from "node:util";
|
|
@@ -167986,9 +168355,9 @@ async function runInit(options = {}) {
|
|
|
167986
168355
|
const cwd = options.path ? resolve36(options.path) : process.cwd();
|
|
167987
168356
|
const fusionDir = join64(cwd, ".fusion");
|
|
167988
168357
|
const dbPath = join64(fusionDir, "fusion.db");
|
|
167989
|
-
const hasDbPath =
|
|
168358
|
+
const hasDbPath = existsSync46(dbPath);
|
|
167990
168359
|
const hasValidDb = hasDbPath && isValidSqliteDatabaseFile(dbPath);
|
|
167991
|
-
if (
|
|
168360
|
+
if (existsSync46(fusionDir) && hasDbPath && hasValidDb) {
|
|
167992
168361
|
const central2 = new CentralCore();
|
|
167993
168362
|
await central2.init();
|
|
167994
168363
|
const existing = await central2.getProjectByPath(cwd);
|
|
@@ -168010,7 +168379,7 @@ async function runInit(options = {}) {
|
|
|
168010
168379
|
await central2.close();
|
|
168011
168380
|
return;
|
|
168012
168381
|
}
|
|
168013
|
-
if (
|
|
168382
|
+
if (existsSync46(fusionDir) && hasDbPath && !hasValidDb) {
|
|
168014
168383
|
throw new Error(
|
|
168015
168384
|
`Existing database at ${dbPath} is not a valid SQLite database. Restore it from .fusion/backups or move it aside before re-running fn init.`
|
|
168016
168385
|
);
|
|
@@ -168018,7 +168387,7 @@ async function runInit(options = {}) {
|
|
|
168018
168387
|
const projectName = options.name ?? await detectProjectName(cwd);
|
|
168019
168388
|
console.log(`Initializing fn project: "${projectName}"`);
|
|
168020
168389
|
console.log(` Path: ${cwd}`);
|
|
168021
|
-
if (!
|
|
168390
|
+
if (!existsSync46(fusionDir)) {
|
|
168022
168391
|
mkdirSync9(fusionDir, { recursive: true });
|
|
168023
168392
|
console.log(` \u2713 Created .fusion/ directory`);
|
|
168024
168393
|
}
|
|
@@ -168031,7 +168400,7 @@ async function runInit(options = {}) {
|
|
|
168031
168400
|
}
|
|
168032
168401
|
await addLocalStorageToGitignore(cwd);
|
|
168033
168402
|
await warnIfQmdMissing();
|
|
168034
|
-
if (!
|
|
168403
|
+
if (!existsSync46(dbPath)) {
|
|
168035
168404
|
writeFileSync3(dbPath, "");
|
|
168036
168405
|
console.log(` \u2713 Created fusion.db`);
|
|
168037
168406
|
}
|
|
@@ -168081,7 +168450,7 @@ async function runInit(options = {}) {
|
|
|
168081
168450
|
}
|
|
168082
168451
|
}
|
|
168083
168452
|
async function detectProjectName(dir2) {
|
|
168084
|
-
if (!
|
|
168453
|
+
if (!existsSync46(join64(dir2, ".git"))) {
|
|
168085
168454
|
return basename20(dir2) || "my-project";
|
|
168086
168455
|
}
|
|
168087
168456
|
try {
|
|
@@ -168103,7 +168472,7 @@ async function detectProjectName(dir2) {
|
|
|
168103
168472
|
async function addLocalStorageToGitignore(cwd) {
|
|
168104
168473
|
const gitignorePath = join64(cwd, ".gitignore");
|
|
168105
168474
|
let content = "";
|
|
168106
|
-
if (
|
|
168475
|
+
if (existsSync46(gitignorePath)) {
|
|
168107
168476
|
try {
|
|
168108
168477
|
content = readFileSync21(gitignorePath, "utf-8");
|
|
168109
168478
|
} catch {
|
|
@@ -168145,7 +168514,7 @@ async function initializeGitRepo(cwd) {
|
|
|
168145
168514
|
await ensureGitConfig(cwd, "user.name", "Fusion");
|
|
168146
168515
|
await ensureGitConfig(cwd, "user.email", "noreply@runfusion.ai");
|
|
168147
168516
|
const gitkeepPath = join64(cwd, ".gitkeep");
|
|
168148
|
-
if (!
|
|
168517
|
+
if (!existsSync46(gitkeepPath)) {
|
|
168149
168518
|
writeFileSync3(gitkeepPath, "\n");
|
|
168150
168519
|
}
|
|
168151
168520
|
await execAsync11("git add .gitkeep", { cwd, timeout: 1e4 });
|
|
@@ -168283,7 +168652,7 @@ var agent_import_exports = {};
|
|
|
168283
168652
|
__export(agent_import_exports, {
|
|
168284
168653
|
runAgentImport: () => runAgentImport
|
|
168285
168654
|
});
|
|
168286
|
-
import { existsSync as
|
|
168655
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync10, readFileSync as readFileSync22, statSync as statSync9, writeFileSync as writeFileSync4 } from "node:fs";
|
|
168287
168656
|
import { resolve as resolve37 } from "node:path";
|
|
168288
168657
|
function slugifyPathSegment(input) {
|
|
168289
168658
|
if (!input || typeof input !== "string") {
|
|
@@ -168342,7 +168711,7 @@ async function importSkillsToProject(projectPath, skills, companySlug, dryRun) {
|
|
|
168342
168711
|
const skillSlug = slugifyPathSegment(skill.name);
|
|
168343
168712
|
const skillDir = resolve37(baseSkillsDir, skillSlug);
|
|
168344
168713
|
const skillPath = resolve37(skillDir, "SKILL.md");
|
|
168345
|
-
if (
|
|
168714
|
+
if (existsSync47(skillPath)) {
|
|
168346
168715
|
result.skipped.push(skill.name);
|
|
168347
168716
|
continue;
|
|
168348
168717
|
}
|
|
@@ -168415,7 +168784,7 @@ async function runAgentImport(source, options) {
|
|
|
168415
168784
|
const dryRun = options?.dryRun ?? false;
|
|
168416
168785
|
const skipExisting = options?.skipExisting ?? false;
|
|
168417
168786
|
const sourcePath = resolve37(source);
|
|
168418
|
-
if (!
|
|
168787
|
+
if (!existsSync47(sourcePath)) {
|
|
168419
168788
|
console.error(`Path not found: ${sourcePath}`);
|
|
168420
168789
|
process.exit(1);
|
|
168421
168790
|
}
|
|
@@ -168810,7 +169179,7 @@ __export(plugin_exports, {
|
|
|
168810
169179
|
runPluginList: () => runPluginList,
|
|
168811
169180
|
runPluginUninstall: () => runPluginUninstall
|
|
168812
169181
|
});
|
|
168813
|
-
import { existsSync as
|
|
169182
|
+
import { existsSync as existsSync48 } from "node:fs";
|
|
168814
169183
|
import { join as join65 } from "node:path";
|
|
168815
169184
|
import { readFile as readFile23 } from "node:fs/promises";
|
|
168816
169185
|
import * as readline from "node:readline";
|
|
@@ -168850,7 +169219,7 @@ async function createPluginLoader(pluginStore, projectName) {
|
|
|
168850
169219
|
}
|
|
168851
169220
|
async function loadManifestFromPath(pluginPath) {
|
|
168852
169221
|
const manifestPath = join65(pluginPath, "manifest.json");
|
|
168853
|
-
if (!
|
|
169222
|
+
if (!existsSync48(manifestPath)) {
|
|
168854
169223
|
throw new Error(`Plugin manifest not found at: ${manifestPath}`);
|
|
168855
169224
|
}
|
|
168856
169225
|
const content = await readFile23(manifestPath, "utf-8");
|
|
@@ -168908,7 +169277,7 @@ async function runPluginInstall(source, options) {
|
|
|
168908
169277
|
console.error("Please provide a local path to the plugin directory.");
|
|
168909
169278
|
process.exit(1);
|
|
168910
169279
|
}
|
|
168911
|
-
if (!
|
|
169280
|
+
if (!existsSync48(source)) {
|
|
168912
169281
|
console.error(`Plugin path does not exist: ${source}`);
|
|
168913
169282
|
process.exit(1);
|
|
168914
169283
|
}
|
|
@@ -169040,7 +169409,7 @@ var plugin_scaffold_exports = {};
|
|
|
169040
169409
|
__export(plugin_scaffold_exports, {
|
|
169041
169410
|
runPluginCreate: () => runPluginCreate
|
|
169042
169411
|
});
|
|
169043
|
-
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as
|
|
169412
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync5, existsSync as existsSync49 } from "node:fs";
|
|
169044
169413
|
import { join as join66 } from "node:path";
|
|
169045
169414
|
function toTitleCase(str) {
|
|
169046
169415
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -169175,7 +169544,7 @@ async function runPluginCreate(name, options) {
|
|
|
169175
169544
|
}
|
|
169176
169545
|
const targetDir = options?.output ?? name;
|
|
169177
169546
|
const targetPath = join66(process.cwd(), targetDir);
|
|
169178
|
-
if (
|
|
169547
|
+
if (existsSync49(targetPath)) {
|
|
169179
169548
|
console.error(`Error: Directory '${targetDir}' already exists.`);
|
|
169180
169549
|
console.error("Please choose a different name or remove the existing directory.");
|
|
169181
169550
|
process.exit(1);
|
|
@@ -169225,7 +169594,7 @@ __export(skills_exports, {
|
|
|
169225
169594
|
runSkillsSearch: () => runSkillsSearch,
|
|
169226
169595
|
searchSkills: () => searchSkills
|
|
169227
169596
|
});
|
|
169228
|
-
import { spawn as
|
|
169597
|
+
import { spawn as spawn16 } from "node:child_process";
|
|
169229
169598
|
async function searchSkills(query, limit = 10) {
|
|
169230
169599
|
const url = `${SKILLS_API_BASE}/api/search?q=${encodeURIComponent(query)}&limit=${limit}`;
|
|
169231
169600
|
try {
|
|
@@ -169303,7 +169672,7 @@ async function runSkillsInstall(args, options) {
|
|
|
169303
169672
|
npxArgs.push("--skill", options.skill);
|
|
169304
169673
|
}
|
|
169305
169674
|
npxArgs.push("-y", "-a", "pi");
|
|
169306
|
-
const child =
|
|
169675
|
+
const child = spawn16("npx", npxArgs, {
|
|
169307
169676
|
cwd: process.cwd(),
|
|
169308
169677
|
stdio: "inherit",
|
|
169309
169678
|
shell: true
|
|
@@ -169565,7 +169934,7 @@ __export(native_patch_exports, {
|
|
|
169565
169934
|
setupNativeResolution: () => setupNativeResolution
|
|
169566
169935
|
});
|
|
169567
169936
|
import { join as join68, basename as basename21, dirname as dirname27 } from "node:path";
|
|
169568
|
-
import { existsSync as
|
|
169937
|
+
import { existsSync as existsSync50, copyFileSync, mkdirSync as mkdirSync12, symlinkSync as symlinkSync2, rmSync as rmSync5, lstatSync as lstatSync3, readlinkSync as readlinkSync2 } from "node:fs";
|
|
169569
169938
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
169570
169939
|
function findStagedNativeDir2() {
|
|
169571
169940
|
const platform3 = process.platform === "darwin" ? "darwin" : process.platform === "linux" ? "linux" : process.platform === "win32" ? "win32" : "unknown";
|
|
@@ -169573,12 +169942,12 @@ function findStagedNativeDir2() {
|
|
|
169573
169942
|
const prebuildName = `${platform3}-${arch}`;
|
|
169574
169943
|
const execDir = dirname27(process.execPath);
|
|
169575
169944
|
const nextToBinary = join68(execDir, "runtime", prebuildName);
|
|
169576
|
-
if (
|
|
169945
|
+
if (existsSync50(join68(nextToBinary, "pty.node"))) {
|
|
169577
169946
|
return nextToBinary;
|
|
169578
169947
|
}
|
|
169579
169948
|
if (process.env.FUSION_RUNTIME_DIR) {
|
|
169580
169949
|
const envPath = join68(process.env.FUSION_RUNTIME_DIR, prebuildName);
|
|
169581
|
-
if (
|
|
169950
|
+
if (existsSync50(join68(envPath, "pty.node"))) {
|
|
169582
169951
|
return envPath;
|
|
169583
169952
|
}
|
|
169584
169953
|
}
|
|
@@ -169588,11 +169957,11 @@ function cleanupStaleBunfsLinks() {
|
|
|
169588
169957
|
if (process.platform === "win32") return;
|
|
169589
169958
|
const bunfsRoot = "/$bunfs/root";
|
|
169590
169959
|
try {
|
|
169591
|
-
if (
|
|
169960
|
+
if (existsSync50(bunfsRoot)) {
|
|
169592
169961
|
const stats = lstatSync3(bunfsRoot);
|
|
169593
169962
|
if (stats.isSymbolicLink()) {
|
|
169594
169963
|
const target = readlinkSync2(bunfsRoot);
|
|
169595
|
-
if (target.includes("fn-bunfs-") && !
|
|
169964
|
+
if (target.includes("fn-bunfs-") && !existsSync50(target)) {
|
|
169596
169965
|
rmSync5(bunfsRoot);
|
|
169597
169966
|
console.log("[fn-native-patch] Cleaned up stale /$bunfs/root symlink");
|
|
169598
169967
|
}
|
|
@@ -169620,14 +169989,14 @@ function setupNativeResolution() {
|
|
|
169620
169989
|
mkdirSync12(platformDir, { recursive: true });
|
|
169621
169990
|
const ptyNodeDest = join68(platformDir, "pty.node");
|
|
169622
169991
|
copyFileSync(join68(nativeDir, "pty.node"), ptyNodeDest);
|
|
169623
|
-
if (
|
|
169992
|
+
if (existsSync50(join68(nativeDir, "spawn-helper"))) {
|
|
169624
169993
|
copyFileSync(join68(nativeDir, "spawn-helper"), join68(platformDir, "spawn-helper"));
|
|
169625
169994
|
}
|
|
169626
169995
|
process.env.FUSION_FAKE_BUNFS_ROOT = tmpRoot;
|
|
169627
169996
|
if (process.platform !== "win32") {
|
|
169628
169997
|
const bunfsRoot = "/$bunfs/root";
|
|
169629
169998
|
try {
|
|
169630
|
-
if (
|
|
169999
|
+
if (existsSync50(bunfsRoot)) {
|
|
169631
170000
|
const stats = lstatSync3(bunfsRoot);
|
|
169632
170001
|
if (stats.isSymbolicLink()) {
|
|
169633
170002
|
rmSync5(bunfsRoot);
|
|
@@ -169650,7 +170019,7 @@ function setupNativeResolution() {
|
|
|
169650
170019
|
function cleanupNativeResolution() {
|
|
169651
170020
|
if (bunfsSymlinkPath && process.platform !== "win32") {
|
|
169652
170021
|
try {
|
|
169653
|
-
if (
|
|
170022
|
+
if (existsSync50(bunfsSymlinkPath)) {
|
|
169654
170023
|
const stats = lstatSync3(bunfsSymlinkPath);
|
|
169655
170024
|
if (stats.isSymbolicLink()) {
|
|
169656
170025
|
rmSync5(bunfsSymlinkPath);
|
|
@@ -169696,7 +170065,7 @@ var init_native_patch = __esm({
|
|
|
169696
170065
|
});
|
|
169697
170066
|
|
|
169698
170067
|
// src/bin.ts
|
|
169699
|
-
import { existsSync as
|
|
170068
|
+
import { existsSync as existsSync51, mkdtempSync as mkdtempSync2, readFileSync as readFileSync23, symlinkSync as symlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
169700
170069
|
import { createRequire as createRequire6 } from "node:module";
|
|
169701
170070
|
import { join as join69, dirname as dirname28 } from "node:path";
|
|
169702
170071
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
@@ -169719,7 +170088,7 @@ function configurePiPackage() {
|
|
|
169719
170088
|
packageJson = JSON.parse(readFileSync23(piPackagePath, "utf-8"));
|
|
169720
170089
|
for (const entry of ["dist", "docs", "examples", "README.md", "CHANGELOG.md"]) {
|
|
169721
170090
|
const source = join69(piPackageDir, entry);
|
|
169722
|
-
if (
|
|
170091
|
+
if (existsSync51(source)) {
|
|
169723
170092
|
symlinkSync3(source, join69(tmp, entry));
|
|
169724
170093
|
}
|
|
169725
170094
|
}
|
|
@@ -169738,7 +170107,7 @@ setInterval(() => {
|
|
|
169738
170107
|
performance3.clearMarks();
|
|
169739
170108
|
}, 3e4).unref();
|
|
169740
170109
|
function loadEnvFile(path5) {
|
|
169741
|
-
if (!
|
|
170110
|
+
if (!existsSync51(path5)) return;
|
|
169742
170111
|
const contents = readFileSync23(path5, "utf-8");
|
|
169743
170112
|
for (const rawLine of contents.split(/\r?\n/)) {
|
|
169744
170113
|
const line = rawLine.trim();
|