@nomad-e/bluma-cli 0.15.0 → 0.17.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/main.js +362 -439
- package/dist/scaffold/.eslintrc.json +3 -0
- package/dist/scaffold/app/globals.css +46 -0
- package/dist/scaffold/app/layout.tsx +19 -0
- package/dist/scaffold/app/page.tsx +124 -0
- package/dist/scaffold/components/ui/README.md +12 -0
- package/dist/scaffold/components/ui/accordion.jsx +42 -0
- package/dist/scaffold/components/ui/alert-dialog.jsx +80 -0
- package/dist/scaffold/components/ui/alert.jsx +33 -0
- package/dist/scaffold/components/ui/aspect-ratio.jsx +5 -0
- package/dist/scaffold/components/ui/avatar.jsx +28 -0
- package/dist/scaffold/components/ui/badge.jsx +24 -0
- package/dist/scaffold/components/ui/breadcrumb.jsx +72 -0
- package/dist/scaffold/components/ui/button.jsx +40 -0
- package/dist/scaffold/components/ui/calendar.jsx +56 -0
- package/dist/scaffold/components/ui/card.jsx +38 -0
- package/dist/scaffold/components/ui/carousel.jsx +168 -0
- package/dist/scaffold/components/ui/chart.jsx +76 -0
- package/dist/scaffold/components/ui/checkbox.jsx +22 -0
- package/dist/scaffold/components/ui/collapsible.jsx +7 -0
- package/dist/scaffold/components/ui/command.jsx +100 -0
- package/dist/scaffold/components/ui/context-menu.jsx +137 -0
- package/dist/scaffold/components/ui/dialog.jsx +72 -0
- package/dist/scaffold/components/ui/drawer.jsx +68 -0
- package/dist/scaffold/components/ui/dropdown-menu.jsx +143 -0
- package/dist/scaffold/components/ui/form.jsx +88 -0
- package/dist/scaffold/components/ui/hover-card.jsx +22 -0
- package/dist/scaffold/components/ui/input-otp.jsx +49 -0
- package/dist/scaffold/components/ui/input.jsx +19 -0
- package/dist/scaffold/components/ui/label.jsx +15 -0
- package/dist/scaffold/components/ui/menubar.jsx +161 -0
- package/dist/scaffold/components/ui/navigation-menu.jsx +95 -0
- package/dist/scaffold/components/ui/pagination.jsx +77 -0
- package/dist/scaffold/components/ui/popover.jsx +25 -0
- package/dist/scaffold/components/ui/progress.jsx +19 -0
- package/dist/scaffold/components/ui/radio-group.jsx +29 -0
- package/dist/scaffold/components/ui/resizable.jsx +27 -0
- package/dist/scaffold/components/ui/scroll-area.jsx +31 -0
- package/dist/scaffold/components/ui/select.jsx +117 -0
- package/dist/scaffold/components/ui/separator.jsx +22 -0
- package/dist/scaffold/components/ui/sheet.jsx +81 -0
- package/dist/scaffold/components/ui/skeleton.jsx +7 -0
- package/dist/scaffold/components/ui/slider.jsx +19 -0
- package/dist/scaffold/components/ui/sonner.jsx +22 -0
- package/dist/scaffold/components/ui/switch.jsx +23 -0
- package/dist/scaffold/components/ui/table.jsx +61 -0
- package/dist/scaffold/components/ui/tabs.jsx +43 -0
- package/dist/scaffold/components/ui/textarea.jsx +18 -0
- package/dist/scaffold/components/ui/toast.jsx +85 -0
- package/dist/scaffold/components/ui/toaster.jsx +33 -0
- package/dist/scaffold/components/ui/toggle-group.jsx +41 -0
- package/dist/scaffold/components/ui/toggle.jsx +30 -0
- package/dist/scaffold/components/ui/tooltip.jsx +22 -0
- package/dist/scaffold/hooks/use-toast.ts +101 -0
- package/dist/scaffold/lib/utils.ts +6 -0
- package/dist/scaffold/next.config.js +5 -0
- package/dist/scaffold/next.config.mjs +15 -0
- package/dist/scaffold/next.config.ts +19 -0
- package/dist/scaffold/package.json +70 -0
- package/dist/scaffold/postcss.config.js +6 -0
- package/dist/scaffold/tailwind.config.ts +57 -0
- package/dist/scaffold/tsconfig.json +20 -0
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2479,7 +2479,7 @@ var init_CtxInspectTool = __esm({
|
|
|
2479
2479
|
});
|
|
2480
2480
|
|
|
2481
2481
|
// src/app/agent/session_manager/session_index_db.ts
|
|
2482
|
-
import
|
|
2482
|
+
import path31 from "path";
|
|
2483
2483
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
2484
2484
|
import { promises as fs28 } from "fs";
|
|
2485
2485
|
import { createRequire } from "module";
|
|
@@ -2488,10 +2488,10 @@ function loadSqlite() {
|
|
|
2488
2488
|
return nodeRequire("better-sqlite3");
|
|
2489
2489
|
}
|
|
2490
2490
|
function getSessionDbPath(appDir = getPreferredAppDir()) {
|
|
2491
|
-
return
|
|
2491
|
+
return path31.join(appDir, BLUMA_SESSION_DB_FILE);
|
|
2492
2492
|
}
|
|
2493
2493
|
function normalizeRelativePath(relativePath) {
|
|
2494
|
-
return relativePath.split(
|
|
2494
|
+
return relativePath.split(path31.sep).join("/");
|
|
2495
2495
|
}
|
|
2496
2496
|
async function walkSessionJsonFiles(dir, onFile) {
|
|
2497
2497
|
let entries;
|
|
@@ -2502,7 +2502,7 @@ async function walkSessionJsonFiles(dir, onFile) {
|
|
|
2502
2502
|
}
|
|
2503
2503
|
for (const e of entries) {
|
|
2504
2504
|
const name = String(e.name);
|
|
2505
|
-
const full =
|
|
2505
|
+
const full = path31.join(dir, name);
|
|
2506
2506
|
if (e.isDirectory()) {
|
|
2507
2507
|
await walkSessionJsonFiles(full, onFile);
|
|
2508
2508
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -2512,7 +2512,7 @@ async function walkSessionJsonFiles(dir, onFile) {
|
|
|
2512
2512
|
}
|
|
2513
2513
|
async function loadJsonlEntries(appDir) {
|
|
2514
2514
|
const map = /* @__PURE__ */ new Map();
|
|
2515
|
-
const indexFile =
|
|
2515
|
+
const indexFile = path31.join(appDir, AGENT_SESSION_PATHS_JSONL);
|
|
2516
2516
|
let raw;
|
|
2517
2517
|
try {
|
|
2518
2518
|
raw = await fs28.readFile(indexFile, "utf-8");
|
|
@@ -2592,7 +2592,7 @@ async function runMigrationV1(db, appDir) {
|
|
|
2592
2592
|
const insertFromPath = async (sessionId, absPath, jsonlUpdatedAt) => {
|
|
2593
2593
|
let rel;
|
|
2594
2594
|
try {
|
|
2595
|
-
rel = normalizeRelativePath(
|
|
2595
|
+
rel = normalizeRelativePath(path31.relative(appDir, absPath));
|
|
2596
2596
|
} catch {
|
|
2597
2597
|
return;
|
|
2598
2598
|
}
|
|
@@ -2607,7 +2607,7 @@ async function runMigrationV1(db, appDir) {
|
|
|
2607
2607
|
});
|
|
2608
2608
|
};
|
|
2609
2609
|
for (const [sessionId, entry] of jsonl) {
|
|
2610
|
-
const full =
|
|
2610
|
+
const full = path31.join(appDir, entry.relativePath.replace(/\//g, path31.sep));
|
|
2611
2611
|
try {
|
|
2612
2612
|
await fs28.access(full);
|
|
2613
2613
|
await insertFromPath(sessionId, full, entry.updatedAt);
|
|
@@ -2621,11 +2621,11 @@ async function runMigrationV1(db, appDir) {
|
|
|
2621
2621
|
});
|
|
2622
2622
|
}
|
|
2623
2623
|
}
|
|
2624
|
-
const sessionsRoot =
|
|
2624
|
+
const sessionsRoot = path31.join(appDir, "sessions");
|
|
2625
2625
|
const existing = db.prepare("SELECT session_id FROM agent_sessions").all();
|
|
2626
2626
|
const seen = new Set(existing.map((r) => r.session_id));
|
|
2627
2627
|
await walkSessionJsonFiles(sessionsRoot, async (absPath) => {
|
|
2628
|
-
const sessionId =
|
|
2628
|
+
const sessionId = path31.basename(absPath, ".json");
|
|
2629
2629
|
if (!sessionId || seen.has(sessionId)) return;
|
|
2630
2630
|
seen.add(sessionId);
|
|
2631
2631
|
await insertFromPath(sessionId, absPath);
|
|
@@ -2660,7 +2660,7 @@ async function ensureSessionIndexDb(appDir = getPreferredAppDir()) {
|
|
|
2660
2660
|
}
|
|
2661
2661
|
const BetterSqlite3 = loadSqlite();
|
|
2662
2662
|
const dbPath = getSessionDbPath(appDir);
|
|
2663
|
-
mkdirSync3(
|
|
2663
|
+
mkdirSync3(path31.dirname(dbPath), { recursive: true });
|
|
2664
2664
|
const db = new BetterSqlite3(dbPath);
|
|
2665
2665
|
db.pragma("journal_mode = WAL");
|
|
2666
2666
|
applySchema(db);
|
|
@@ -2696,7 +2696,7 @@ async function upsertSessionIndexRow(row, appDir = getPreferredAppDir()) {
|
|
|
2696
2696
|
async function getSessionPathFromIndex(sessionId, appDir = getPreferredAppDir()) {
|
|
2697
2697
|
const db = await ensureSessionIndexDb(appDir);
|
|
2698
2698
|
const row = db.prepare("SELECT relative_path FROM agent_sessions WHERE session_id = ?").get(sessionId);
|
|
2699
|
-
return row?.relative_path?.replace(/\//g,
|
|
2699
|
+
return row?.relative_path?.replace(/\//g, path31.sep) ?? null;
|
|
2700
2700
|
}
|
|
2701
2701
|
async function listSessionsFromIndex(limit = 50, appDir = getPreferredAppDir()) {
|
|
2702
2702
|
const db = await ensureSessionIndexDb(appDir);
|
|
@@ -2708,7 +2708,7 @@ async function listSessionsFromIndex(limit = 50, appDir = getPreferredAppDir())
|
|
|
2708
2708
|
).all(limit);
|
|
2709
2709
|
return rows.map((r) => ({
|
|
2710
2710
|
sessionId: r.session_id,
|
|
2711
|
-
relativePath: r.relative_path.replace(/\//g,
|
|
2711
|
+
relativePath: r.relative_path.replace(/\//g, path31.sep),
|
|
2712
2712
|
createdAt: r.created_at,
|
|
2713
2713
|
updatedAt: r.updated_at,
|
|
2714
2714
|
preview: r.preview
|
|
@@ -2729,12 +2729,12 @@ var init_session_index_db = __esm({
|
|
|
2729
2729
|
});
|
|
2730
2730
|
|
|
2731
2731
|
// src/app/agent/session_manager/agent_session_paths.ts
|
|
2732
|
-
import
|
|
2732
|
+
import path32 from "path";
|
|
2733
2733
|
import { promises as fs29 } from "fs";
|
|
2734
2734
|
async function appendAgentSessionPath(sessionId, relativePath) {
|
|
2735
2735
|
const app = getPreferredAppDir();
|
|
2736
2736
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
2737
|
-
const rel = relativePath.split(
|
|
2737
|
+
const rel = relativePath.split(path32.sep).join("/");
|
|
2738
2738
|
await upsertSessionIndexRow({
|
|
2739
2739
|
sessionId,
|
|
2740
2740
|
relativePath: rel,
|
|
@@ -2744,7 +2744,7 @@ async function appendAgentSessionPath(sessionId, relativePath) {
|
|
|
2744
2744
|
});
|
|
2745
2745
|
}
|
|
2746
2746
|
async function resolveSessionRelativePathFromJsonl(sessionId) {
|
|
2747
|
-
const indexFile =
|
|
2747
|
+
const indexFile = path32.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
|
|
2748
2748
|
let raw;
|
|
2749
2749
|
try {
|
|
2750
2750
|
raw = await fs29.readFile(indexFile, "utf-8");
|
|
@@ -2756,7 +2756,7 @@ async function resolveSessionRelativePathFromJsonl(sessionId) {
|
|
|
2756
2756
|
try {
|
|
2757
2757
|
const row = JSON.parse(lines[i]);
|
|
2758
2758
|
if (row.sessionId === sessionId && typeof row.relativePath === "string") {
|
|
2759
|
-
return row.relativePath.replace(/\//g,
|
|
2759
|
+
return row.relativePath.replace(/\//g, path32.sep);
|
|
2760
2760
|
}
|
|
2761
2761
|
} catch {
|
|
2762
2762
|
}
|
|
@@ -2777,7 +2777,7 @@ async function walkSessionJsonFiles2(dir, onFile) {
|
|
|
2777
2777
|
}
|
|
2778
2778
|
for (const e of entries) {
|
|
2779
2779
|
const name = String(e.name);
|
|
2780
|
-
const full =
|
|
2780
|
+
const full = path32.join(dir, name);
|
|
2781
2781
|
if (e.isDirectory()) {
|
|
2782
2782
|
await walkSessionJsonFiles2(full, onFile);
|
|
2783
2783
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -2786,10 +2786,10 @@ async function walkSessionJsonFiles2(dir, onFile) {
|
|
|
2786
2786
|
}
|
|
2787
2787
|
}
|
|
2788
2788
|
async function findSessionFileGlobFallback(sessionId) {
|
|
2789
|
-
const sessionsRoot =
|
|
2789
|
+
const sessionsRoot = path32.join(getPreferredAppDir(), "sessions");
|
|
2790
2790
|
const state2 = { best: null };
|
|
2791
2791
|
await walkSessionJsonFiles2(sessionsRoot, async (abs) => {
|
|
2792
|
-
if (
|
|
2792
|
+
if (path32.basename(abs, ".json") !== sessionId) return;
|
|
2793
2793
|
try {
|
|
2794
2794
|
const st = await fs29.stat(abs);
|
|
2795
2795
|
if (!st.isFile()) return;
|
|
@@ -2802,7 +2802,7 @@ async function findSessionFileGlobFallback(sessionId) {
|
|
|
2802
2802
|
return state2.best !== null ? state2.best.p : null;
|
|
2803
2803
|
}
|
|
2804
2804
|
async function loadLatestIndexEntriesBySessionId() {
|
|
2805
|
-
const indexFile =
|
|
2805
|
+
const indexFile = path32.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
|
|
2806
2806
|
const map = /* @__PURE__ */ new Map();
|
|
2807
2807
|
let raw;
|
|
2808
2808
|
try {
|
|
@@ -2842,11 +2842,11 @@ function dateFolderFromRelativePath(relativePath) {
|
|
|
2842
2842
|
async function enrichCandidateFromFile(absPath, sessionId, lastMtimeMs, opts) {
|
|
2843
2843
|
let rel;
|
|
2844
2844
|
try {
|
|
2845
|
-
rel =
|
|
2845
|
+
rel = path32.relative(getPreferredAppDir(), absPath);
|
|
2846
2846
|
} catch {
|
|
2847
2847
|
rel = absPath;
|
|
2848
2848
|
}
|
|
2849
|
-
const dateFolder = dateFolderFromRelativePath(rel.split(
|
|
2849
|
+
const dateFolder = dateFolderFromRelativePath(rel.split(path32.sep).join("/"));
|
|
2850
2850
|
let preview = opts?.preview ?? "(no messages)";
|
|
2851
2851
|
let lastActivityMs = lastMtimeMs;
|
|
2852
2852
|
if (opts?.updatedAtIso) {
|
|
@@ -2885,7 +2885,7 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
2885
2885
|
const fromIndex = await listSessionsFromIndex(limit * 2, appDir);
|
|
2886
2886
|
const map = /* @__PURE__ */ new Map();
|
|
2887
2887
|
for (const row of fromIndex) {
|
|
2888
|
-
const full =
|
|
2888
|
+
const full = path32.join(appDir, row.relativePath);
|
|
2889
2889
|
try {
|
|
2890
2890
|
const st = await fs29.stat(full);
|
|
2891
2891
|
if (!st.isFile()) continue;
|
|
@@ -2898,9 +2898,9 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
2898
2898
|
} catch {
|
|
2899
2899
|
}
|
|
2900
2900
|
}
|
|
2901
|
-
const sessionsRoot =
|
|
2901
|
+
const sessionsRoot = path32.join(appDir, "sessions");
|
|
2902
2902
|
await walkSessionJsonFiles2(sessionsRoot, async (absPath) => {
|
|
2903
|
-
const id =
|
|
2903
|
+
const id = path32.basename(absPath, ".json");
|
|
2904
2904
|
if (!id) return;
|
|
2905
2905
|
try {
|
|
2906
2906
|
const st = await fs29.stat(absPath);
|
|
@@ -2915,7 +2915,7 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
2915
2915
|
const index = await loadLatestIndexEntriesBySessionId();
|
|
2916
2916
|
for (const [sessionId, entry] of index) {
|
|
2917
2917
|
if (map.has(sessionId)) continue;
|
|
2918
|
-
const full =
|
|
2918
|
+
const full = path32.join(appDir, entry.relativePath.replace(/\//g, path32.sep));
|
|
2919
2919
|
try {
|
|
2920
2920
|
const st = await fs29.stat(full);
|
|
2921
2921
|
if (st.isFile()) {
|
|
@@ -2945,7 +2945,7 @@ var init_agent_session_paths = __esm({
|
|
|
2945
2945
|
});
|
|
2946
2946
|
|
|
2947
2947
|
// src/app/agent/session_manager/session_manager.ts
|
|
2948
|
-
import
|
|
2948
|
+
import path33 from "path";
|
|
2949
2949
|
import { promises as fs30 } from "fs";
|
|
2950
2950
|
async function withFileLock(file, fn) {
|
|
2951
2951
|
const prev = fileLocks.get(file) || Promise.resolve();
|
|
@@ -2982,7 +2982,7 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
2982
2982
|
const isWin = process.platform === "win32";
|
|
2983
2983
|
while (attempt <= maxRetries) {
|
|
2984
2984
|
try {
|
|
2985
|
-
const dir =
|
|
2985
|
+
const dir = path33.dirname(dest);
|
|
2986
2986
|
await fs30.mkdir(dir, { recursive: true }).catch(() => {
|
|
2987
2987
|
});
|
|
2988
2988
|
await fs30.rename(src, dest);
|
|
@@ -3000,7 +3000,7 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
3000
3000
|
try {
|
|
3001
3001
|
await fs30.access(src);
|
|
3002
3002
|
const data = await fs30.readFile(src);
|
|
3003
|
-
const dir =
|
|
3003
|
+
const dir = path33.dirname(dest);
|
|
3004
3004
|
await fs30.mkdir(dir, { recursive: true }).catch(() => {
|
|
3005
3005
|
});
|
|
3006
3006
|
await fs30.writeFile(dest, data);
|
|
@@ -3017,13 +3017,13 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
3017
3017
|
}
|
|
3018
3018
|
async function ensureSessionDir() {
|
|
3019
3019
|
const appDir = getPreferredAppDir();
|
|
3020
|
-
const sessionDir =
|
|
3020
|
+
const sessionDir = path33.join(appDir, "sessions");
|
|
3021
3021
|
await fs30.mkdir(sessionDir, { recursive: true });
|
|
3022
3022
|
return sessionDir;
|
|
3023
3023
|
}
|
|
3024
3024
|
async function resolveAgentSessionFilePath(sessionId) {
|
|
3025
3025
|
const appDir = getPreferredAppDir();
|
|
3026
|
-
const legacy =
|
|
3026
|
+
const legacy = path33.join(appDir, "sessions", `${sessionId}.json`);
|
|
3027
3027
|
try {
|
|
3028
3028
|
await fs30.access(legacy);
|
|
3029
3029
|
return legacy;
|
|
@@ -3031,7 +3031,7 @@ async function resolveAgentSessionFilePath(sessionId) {
|
|
|
3031
3031
|
}
|
|
3032
3032
|
const rel = await resolveSessionRelativePathFromIndex(sessionId);
|
|
3033
3033
|
if (rel) {
|
|
3034
|
-
const full =
|
|
3034
|
+
const full = path33.join(appDir, rel);
|
|
3035
3035
|
try {
|
|
3036
3036
|
await fs30.access(full);
|
|
3037
3037
|
return full;
|
|
@@ -3067,16 +3067,16 @@ async function loadOrcreateSession(sessionId) {
|
|
|
3067
3067
|
const y = String(now2.getFullYear());
|
|
3068
3068
|
const mo = String(now2.getMonth() + 1).padStart(2, "0");
|
|
3069
3069
|
const d = String(now2.getDate()).padStart(2, "0");
|
|
3070
|
-
const datedDir =
|
|
3070
|
+
const datedDir = path33.join(sessionsRoot, y, mo, d);
|
|
3071
3071
|
await fs30.mkdir(datedDir, { recursive: true });
|
|
3072
|
-
const sessionFile =
|
|
3072
|
+
const sessionFile = path33.join(datedDir, `${sessionId}.json`);
|
|
3073
3073
|
const newSessionData = {
|
|
3074
3074
|
session_id: sessionId,
|
|
3075
3075
|
created_at: now2.toISOString(),
|
|
3076
3076
|
conversation_history: []
|
|
3077
3077
|
};
|
|
3078
3078
|
await fs30.writeFile(sessionFile, JSON.stringify(newSessionData, null, 2), "utf-8");
|
|
3079
|
-
const relToApp =
|
|
3079
|
+
const relToApp = path33.relative(getPreferredAppDir(), sessionFile);
|
|
3080
3080
|
await appendAgentSessionPath(sessionId, relToApp);
|
|
3081
3081
|
const emptyMemory = {
|
|
3082
3082
|
historyAnchor: null,
|
|
@@ -3088,7 +3088,7 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
3088
3088
|
await withFileLock(sessionFile, async () => {
|
|
3089
3089
|
let sessionData;
|
|
3090
3090
|
try {
|
|
3091
|
-
const dir =
|
|
3091
|
+
const dir = path33.dirname(sessionFile);
|
|
3092
3092
|
await fs30.mkdir(dir, { recursive: true });
|
|
3093
3093
|
} catch {
|
|
3094
3094
|
}
|
|
@@ -3104,7 +3104,7 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
3104
3104
|
console.warn(`An unknown error occurred while reading ${sessionFile}. Re-initializing.`, error);
|
|
3105
3105
|
}
|
|
3106
3106
|
}
|
|
3107
|
-
const sessionId =
|
|
3107
|
+
const sessionId = path33.basename(sessionFile, ".json");
|
|
3108
3108
|
sessionData = {
|
|
3109
3109
|
session_id: sessionId,
|
|
3110
3110
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3129,12 +3129,12 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
3129
3129
|
try {
|
|
3130
3130
|
await fs30.writeFile(tempSessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
3131
3131
|
await safeRenameWithRetry(tempSessionFile, sessionFile);
|
|
3132
|
-
const sessionId = sessionData.session_id ??
|
|
3132
|
+
const sessionId = sessionData.session_id ?? path33.basename(sessionFile, ".json");
|
|
3133
3133
|
const updatedAt = sessionData.last_updated ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3134
3134
|
const createdAt = sessionData.created_at ?? updatedAt;
|
|
3135
3135
|
let relToApp;
|
|
3136
3136
|
try {
|
|
3137
|
-
relToApp =
|
|
3137
|
+
relToApp = path33.relative(getPreferredAppDir(), sessionFile);
|
|
3138
3138
|
} catch {
|
|
3139
3139
|
relToApp = sessionFile;
|
|
3140
3140
|
}
|
|
@@ -3205,7 +3205,7 @@ __export(exportConversation_exports, {
|
|
|
3205
3205
|
resolveExportOutputPath: () => resolveExportOutputPath
|
|
3206
3206
|
});
|
|
3207
3207
|
import { promises as fs48 } from "fs";
|
|
3208
|
-
import
|
|
3208
|
+
import path54 from "path";
|
|
3209
3209
|
function extractTextParts2(content) {
|
|
3210
3210
|
if (typeof content === "string") {
|
|
3211
3211
|
const trimmed = content.trim();
|
|
@@ -3363,12 +3363,12 @@ function resolveExportOutputPath(sessionId, options) {
|
|
|
3363
3363
|
const { outputPath, defaultExportDir } = options ?? {};
|
|
3364
3364
|
if (outputPath?.trim()) {
|
|
3365
3365
|
const raw = outputPath.trim();
|
|
3366
|
-
return
|
|
3366
|
+
return path54.isAbsolute(raw) ? raw : path54.resolve(process.cwd(), raw);
|
|
3367
3367
|
}
|
|
3368
3368
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
3369
3369
|
const safeId = sessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 48) || "session";
|
|
3370
3370
|
const baseDir = defaultExportDir ?? getSandboxPolicy().workspaceRoot;
|
|
3371
|
-
return
|
|
3371
|
+
return path54.join(baseDir, `bluma-export-${safeId}-${stamp}.md`);
|
|
3372
3372
|
}
|
|
3373
3373
|
async function resolveHistory(sessionId, fallbackHistory) {
|
|
3374
3374
|
const loaded2 = await loadSession(sessionId);
|
|
@@ -3390,7 +3390,7 @@ async function exportConversationToFile(options) {
|
|
|
3390
3390
|
}
|
|
3391
3391
|
const markdown = formatConversationMarkdown(sessionId, history);
|
|
3392
3392
|
const filePath = resolveExportOutputPath(sessionId, { outputPath, defaultExportDir });
|
|
3393
|
-
await fs48.mkdir(
|
|
3393
|
+
await fs48.mkdir(path54.dirname(filePath), { recursive: true });
|
|
3394
3394
|
await fs48.writeFile(filePath, markdown, "utf-8");
|
|
3395
3395
|
return {
|
|
3396
3396
|
success: true,
|
|
@@ -3916,11 +3916,11 @@ var NodeFsOperations = {
|
|
|
3916
3916
|
if (fd) fs.closeSync(fd);
|
|
3917
3917
|
}
|
|
3918
3918
|
},
|
|
3919
|
-
appendFileSync(
|
|
3920
|
-
const _ = slowLogging`fs.appendFileSync(${
|
|
3919
|
+
appendFileSync(path59, data, options) {
|
|
3920
|
+
const _ = slowLogging`fs.appendFileSync(${path59}, ${data.length} chars)`;
|
|
3921
3921
|
if (options?.mode !== void 0) {
|
|
3922
3922
|
try {
|
|
3923
|
-
const fd = fs.openSync(
|
|
3923
|
+
const fd = fs.openSync(path59, "ax", options.mode);
|
|
3924
3924
|
try {
|
|
3925
3925
|
fs.appendFileSync(fd, data);
|
|
3926
3926
|
} finally {
|
|
@@ -3931,35 +3931,35 @@ var NodeFsOperations = {
|
|
|
3931
3931
|
if (getErrnoCode(e) !== "EEXIST") throw e;
|
|
3932
3932
|
}
|
|
3933
3933
|
}
|
|
3934
|
-
fs.appendFileSync(
|
|
3934
|
+
fs.appendFileSync(path59, data);
|
|
3935
3935
|
},
|
|
3936
3936
|
copyFileSync(src, dest) {
|
|
3937
3937
|
const _ = slowLogging`fs.copyFileSync(${src} → ${dest})`;
|
|
3938
3938
|
fs.copyFileSync(src, dest);
|
|
3939
3939
|
},
|
|
3940
|
-
unlinkSync(
|
|
3941
|
-
const _ = slowLogging`fs.unlinkSync(${
|
|
3942
|
-
fs.unlinkSync(
|
|
3940
|
+
unlinkSync(path59) {
|
|
3941
|
+
const _ = slowLogging`fs.unlinkSync(${path59})`;
|
|
3942
|
+
fs.unlinkSync(path59);
|
|
3943
3943
|
},
|
|
3944
3944
|
renameSync(oldPath, newPath) {
|
|
3945
3945
|
const _ = slowLogging`fs.renameSync(${oldPath} → ${newPath})`;
|
|
3946
3946
|
fs.renameSync(oldPath, newPath);
|
|
3947
3947
|
},
|
|
3948
|
-
linkSync(target,
|
|
3949
|
-
const _ = slowLogging`fs.linkSync(${target} → ${
|
|
3950
|
-
fs.linkSync(target,
|
|
3948
|
+
linkSync(target, path59) {
|
|
3949
|
+
const _ = slowLogging`fs.linkSync(${target} → ${path59})`;
|
|
3950
|
+
fs.linkSync(target, path59);
|
|
3951
3951
|
},
|
|
3952
|
-
symlinkSync(target,
|
|
3953
|
-
const _ = slowLogging`fs.symlinkSync(${target} → ${
|
|
3954
|
-
fs.symlinkSync(target,
|
|
3952
|
+
symlinkSync(target, path59, type) {
|
|
3953
|
+
const _ = slowLogging`fs.symlinkSync(${target} → ${path59})`;
|
|
3954
|
+
fs.symlinkSync(target, path59, type);
|
|
3955
3955
|
},
|
|
3956
|
-
readlinkSync(
|
|
3957
|
-
const _ = slowLogging`fs.readlinkSync(${
|
|
3958
|
-
return fs.readlinkSync(
|
|
3956
|
+
readlinkSync(path59) {
|
|
3957
|
+
const _ = slowLogging`fs.readlinkSync(${path59})`;
|
|
3958
|
+
return fs.readlinkSync(path59);
|
|
3959
3959
|
},
|
|
3960
|
-
realpathSync(
|
|
3961
|
-
const _ = slowLogging`fs.realpathSync(${
|
|
3962
|
-
return fs.realpathSync(
|
|
3960
|
+
realpathSync(path59) {
|
|
3961
|
+
const _ = slowLogging`fs.realpathSync(${path59})`;
|
|
3962
|
+
return fs.realpathSync(path59).normalize("NFC");
|
|
3963
3963
|
},
|
|
3964
3964
|
mkdirSync(dirPath, options) {
|
|
3965
3965
|
const _ = slowLogging`fs.mkdirSync(${dirPath})`;
|
|
@@ -3992,12 +3992,12 @@ var NodeFsOperations = {
|
|
|
3992
3992
|
const _ = slowLogging`fs.rmdirSync(${dirPath})`;
|
|
3993
3993
|
fs.rmdirSync(dirPath);
|
|
3994
3994
|
},
|
|
3995
|
-
rmSync(
|
|
3996
|
-
const _ = slowLogging`fs.rmSync(${
|
|
3997
|
-
fs.rmSync(
|
|
3995
|
+
rmSync(path59, options) {
|
|
3996
|
+
const _ = slowLogging`fs.rmSync(${path59})`;
|
|
3997
|
+
fs.rmSync(path59, options);
|
|
3998
3998
|
},
|
|
3999
|
-
createWriteStream(
|
|
4000
|
-
return fs.createWriteStream(
|
|
3999
|
+
createWriteStream(path59) {
|
|
4000
|
+
return fs.createWriteStream(path59);
|
|
4001
4001
|
},
|
|
4002
4002
|
async readFileBytes(fsPath, maxBytes) {
|
|
4003
4003
|
if (maxBytes === void 0) {
|
|
@@ -4104,12 +4104,12 @@ function shouldLogDebugMessage(message2) {
|
|
|
4104
4104
|
var hasFormattedOutput = false;
|
|
4105
4105
|
var debugWriter = null;
|
|
4106
4106
|
var pendingWrite = Promise.resolve();
|
|
4107
|
-
async function appendAsync(needMkdir, dir,
|
|
4107
|
+
async function appendAsync(needMkdir, dir, path59, content) {
|
|
4108
4108
|
if (needMkdir) {
|
|
4109
4109
|
await mkdir(dir, { recursive: true }).catch(() => {
|
|
4110
4110
|
});
|
|
4111
4111
|
}
|
|
4112
|
-
await appendFile(
|
|
4112
|
+
await appendFile(path59, content);
|
|
4113
4113
|
void updateLatestDebugLogSymlink();
|
|
4114
4114
|
}
|
|
4115
4115
|
function noop() {
|
|
@@ -4119,8 +4119,8 @@ function getDebugWriter() {
|
|
|
4119
4119
|
let ensuredDir = null;
|
|
4120
4120
|
debugWriter = createBufferedWriter({
|
|
4121
4121
|
writeFn: (content) => {
|
|
4122
|
-
const
|
|
4123
|
-
const dir = dirname(
|
|
4122
|
+
const path59 = getDebugLogPath();
|
|
4123
|
+
const dir = dirname(path59);
|
|
4124
4124
|
const needMkdir = ensuredDir !== dir;
|
|
4125
4125
|
ensuredDir = dir;
|
|
4126
4126
|
if (isDebugMode()) {
|
|
@@ -4130,11 +4130,11 @@ function getDebugWriter() {
|
|
|
4130
4130
|
} catch {
|
|
4131
4131
|
}
|
|
4132
4132
|
}
|
|
4133
|
-
getFsImplementation().appendFileSync(
|
|
4133
|
+
getFsImplementation().appendFileSync(path59, content);
|
|
4134
4134
|
void updateLatestDebugLogSymlink();
|
|
4135
4135
|
return;
|
|
4136
4136
|
}
|
|
4137
|
-
pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir,
|
|
4137
|
+
pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir, path59, content)).catch(noop);
|
|
4138
4138
|
},
|
|
4139
4139
|
flushIntervalMs: 1e3,
|
|
4140
4140
|
maxBufferSize: 100,
|
|
@@ -10321,8 +10321,8 @@ import codeExcerpt from "code-excerpt";
|
|
|
10321
10321
|
import { readFileSync as readFileSync2 } from "fs";
|
|
10322
10322
|
import StackUtils from "stack-utils";
|
|
10323
10323
|
import { jsx as jsx6, jsxs } from "react/jsx-runtime";
|
|
10324
|
-
var cleanupPath = (
|
|
10325
|
-
return
|
|
10324
|
+
var cleanupPath = (path59) => {
|
|
10325
|
+
return path59?.replace(`file://${process.cwd()}/`, "");
|
|
10326
10326
|
};
|
|
10327
10327
|
var stackUtils;
|
|
10328
10328
|
function getStackUtils() {
|
|
@@ -14300,7 +14300,7 @@ var getInstance = (stdout, createInstance) => {
|
|
|
14300
14300
|
// src/main.ts
|
|
14301
14301
|
import { EventEmitter as EventEmitter7 } from "events";
|
|
14302
14302
|
import fs52 from "fs";
|
|
14303
|
-
import
|
|
14303
|
+
import path58 from "path";
|
|
14304
14304
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
14305
14305
|
import { spawn as spawn6 } from "child_process";
|
|
14306
14306
|
import { v4 as uuidv412 } from "uuid";
|
|
@@ -14979,12 +14979,12 @@ function cancelSlashSubmenu() {
|
|
|
14979
14979
|
|
|
14980
14980
|
// src/app/agent/agent.ts
|
|
14981
14981
|
import * as dotenv from "dotenv";
|
|
14982
|
-
import
|
|
14982
|
+
import path48 from "path";
|
|
14983
14983
|
import os30 from "os";
|
|
14984
14984
|
|
|
14985
14985
|
// src/app/agent/tool_invoker.ts
|
|
14986
14986
|
import { promises as fs26 } from "fs";
|
|
14987
|
-
import
|
|
14987
|
+
import path29 from "path";
|
|
14988
14988
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14989
14989
|
|
|
14990
14990
|
// src/app/agent/tools/EditTool/EditTool.ts
|
|
@@ -15549,20 +15549,6 @@ function normalizeContext(raw) {
|
|
|
15549
15549
|
appUrl: typeof raw.appUrl === "string" ? raw.appUrl : null
|
|
15550
15550
|
};
|
|
15551
15551
|
}
|
|
15552
|
-
function readJsonFile(filePath) {
|
|
15553
|
-
try {
|
|
15554
|
-
if (!fs5.existsSync(filePath)) {
|
|
15555
|
-
return null;
|
|
15556
|
-
}
|
|
15557
|
-
const parsed = JSON.parse(fs5.readFileSync(filePath, "utf8"));
|
|
15558
|
-
if (parsed && typeof parsed === "object") {
|
|
15559
|
-
return parsed.appContext && typeof parsed.appContext === "object" ? parsed.appContext : parsed;
|
|
15560
|
-
}
|
|
15561
|
-
} catch {
|
|
15562
|
-
return null;
|
|
15563
|
-
}
|
|
15564
|
-
return null;
|
|
15565
|
-
}
|
|
15566
15552
|
function readFactorAiWorkspaceManifest(projectDir = process.cwd()) {
|
|
15567
15553
|
const manifestPath = path6.join(projectDir, "factorai.sh.json");
|
|
15568
15554
|
try {
|
|
@@ -15575,17 +15561,20 @@ function readFactorAiWorkspaceManifest(projectDir = process.cwd()) {
|
|
|
15575
15561
|
return null;
|
|
15576
15562
|
}
|
|
15577
15563
|
}
|
|
15578
|
-
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
|
|
15564
|
+
var FACTORAI_APP_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
15565
|
+
function isFactorAiAppUuid(value) {
|
|
15566
|
+
return FACTORAI_APP_UUID_RE.test(String(value || "").trim());
|
|
15567
|
+
}
|
|
15568
|
+
function readContextFromWorkspace(projectDir = process.cwd()) {
|
|
15569
|
+
const manifest = readFactorAiWorkspaceManifest(projectDir);
|
|
15570
|
+
if (!manifest) {
|
|
15582
15571
|
return null;
|
|
15583
15572
|
}
|
|
15584
|
-
const
|
|
15585
|
-
return
|
|
15573
|
+
const raw = manifest.appContext && typeof manifest.appContext === "object" ? manifest.appContext : manifest;
|
|
15574
|
+
return normalizeContext(raw);
|
|
15586
15575
|
}
|
|
15587
|
-
function loadFactorAiAppContext() {
|
|
15588
|
-
return readContextFromWorkspace();
|
|
15576
|
+
function loadFactorAiAppContext(projectDir = process.cwd()) {
|
|
15577
|
+
return readContextFromWorkspace(projectDir);
|
|
15589
15578
|
}
|
|
15590
15579
|
var FACTOR_SH_URL_APP_FIELD = "factor-sh-url-app";
|
|
15591
15580
|
function resolveFactorShAppLiveUrl(projectDir = process.cwd()) {
|
|
@@ -20113,7 +20102,7 @@ async function createNextApp(args) {
|
|
|
20113
20102
|
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
20114
20103
|
init_sandbox_policy();
|
|
20115
20104
|
import { promises as fs25 } from "fs";
|
|
20116
|
-
import
|
|
20105
|
+
import path28 from "path";
|
|
20117
20106
|
|
|
20118
20107
|
// src/app/agent/tools/DeployAppTool/createDeployProjectZip.ts
|
|
20119
20108
|
import { lstat, readdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
@@ -20211,91 +20200,6 @@ async function createDeployProjectZip(projectDir, zipPath) {
|
|
|
20211
20200
|
return zipPath;
|
|
20212
20201
|
}
|
|
20213
20202
|
|
|
20214
|
-
// src/app/agent/tools/DeployAppTool/nextDeployConfig.ts
|
|
20215
|
-
import { access, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
20216
|
-
import path28 from "path";
|
|
20217
|
-
var FACTORAI_NEXT_CONFIG_JS = `/** @type {import('next').NextConfig} */
|
|
20218
|
-
module.exports = {
|
|
20219
|
-
output: "standalone",
|
|
20220
|
-
reactStrictMode: true,
|
|
20221
|
-
};
|
|
20222
|
-
`;
|
|
20223
|
-
var FACTORAI_NEXT_CONFIG_JSON = `${JSON.stringify(
|
|
20224
|
-
{
|
|
20225
|
-
output: "standalone",
|
|
20226
|
-
reactStrictMode: true
|
|
20227
|
-
},
|
|
20228
|
-
null,
|
|
20229
|
-
2
|
|
20230
|
-
)}
|
|
20231
|
-
`;
|
|
20232
|
-
var STANDALONE_RE = /output\s*:\s*["']standalone["']/;
|
|
20233
|
-
async function fileExists(filePath) {
|
|
20234
|
-
try {
|
|
20235
|
-
await access(filePath);
|
|
20236
|
-
return true;
|
|
20237
|
-
} catch {
|
|
20238
|
-
return false;
|
|
20239
|
-
}
|
|
20240
|
-
}
|
|
20241
|
-
function hasStandaloneInJs(source) {
|
|
20242
|
-
return STANDALONE_RE.test(source);
|
|
20243
|
-
}
|
|
20244
|
-
function hasStandaloneInJson(source) {
|
|
20245
|
-
try {
|
|
20246
|
-
const parsed = JSON.parse(source);
|
|
20247
|
-
return parsed.output === "standalone";
|
|
20248
|
-
} catch {
|
|
20249
|
-
return false;
|
|
20250
|
-
}
|
|
20251
|
-
}
|
|
20252
|
-
async function ensureNextStandaloneConfig(projectDir) {
|
|
20253
|
-
const warnings = [];
|
|
20254
|
-
const jsPath = path28.join(projectDir, "next.config.js");
|
|
20255
|
-
const jsonPath = path28.join(projectDir, "next.config.json");
|
|
20256
|
-
const mjsPath = path28.join(projectDir, "next.config.mjs");
|
|
20257
|
-
const hasJs = await fileExists(jsPath);
|
|
20258
|
-
const hasJson = await fileExists(jsonPath);
|
|
20259
|
-
const hasMjs = await fileExists(mjsPath);
|
|
20260
|
-
if (hasMjs) {
|
|
20261
|
-
const mjs = await readFile3(mjsPath, "utf-8");
|
|
20262
|
-
if (!hasStandaloneInJs(mjs)) {
|
|
20263
|
-
warnings.push('next.config.mjs missing output: "standalone" \u2014 update manually for FactorAI deploy');
|
|
20264
|
-
return { ok: false, warnings };
|
|
20265
|
-
}
|
|
20266
|
-
return { ok: true, warnings };
|
|
20267
|
-
}
|
|
20268
|
-
if (hasJs) {
|
|
20269
|
-
const js = await readFile3(jsPath, "utf-8");
|
|
20270
|
-
const directExport = /module\.exports\s*=\s*\{/.test(js) && hasStandaloneInJs(js);
|
|
20271
|
-
if (directExport) {
|
|
20272
|
-
return { ok: true, warnings };
|
|
20273
|
-
}
|
|
20274
|
-
if (hasStandaloneInJs(js)) {
|
|
20275
|
-
await writeFile2(jsPath, FACTORAI_NEXT_CONFIG_JS, "utf-8");
|
|
20276
|
-
warnings.push(
|
|
20277
|
-
"next.config.js reescrito em formato compat\xEDvel com o deploy FactorAI (module.exports direto)"
|
|
20278
|
-
);
|
|
20279
|
-
return { ok: true, warnings };
|
|
20280
|
-
}
|
|
20281
|
-
await writeFile2(jsPath, FACTORAI_NEXT_CONFIG_JS, "utf-8");
|
|
20282
|
-
warnings.push('next.config.js atualizado com output: "standalone"');
|
|
20283
|
-
return { ok: true, warnings };
|
|
20284
|
-
}
|
|
20285
|
-
if (hasJson) {
|
|
20286
|
-
const json = await readFile3(jsonPath, "utf-8");
|
|
20287
|
-
if (hasStandaloneInJson(json)) {
|
|
20288
|
-
return { ok: true, warnings };
|
|
20289
|
-
}
|
|
20290
|
-
await writeFile2(jsonPath, FACTORAI_NEXT_CONFIG_JSON, "utf-8");
|
|
20291
|
-
warnings.push('next.config.json atualizado com output: "standalone"');
|
|
20292
|
-
return { ok: true, warnings };
|
|
20293
|
-
}
|
|
20294
|
-
await writeFile2(jsonPath, FACTORAI_NEXT_CONFIG_JSON, "utf-8");
|
|
20295
|
-
warnings.push('Criado next.config.json com output: "standalone"');
|
|
20296
|
-
return { ok: true, warnings };
|
|
20297
|
-
}
|
|
20298
|
-
|
|
20299
20203
|
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
20300
20204
|
async function uploadToSeverino(zipPath, severinoUrl, name, apiKey, appId) {
|
|
20301
20205
|
const deployUrl = `${severinoUrl.replace(/\/$/, "")}/api/v1/deploy`;
|
|
@@ -20304,7 +20208,7 @@ async function uploadToSeverino(zipPath, severinoUrl, name, apiKey, appId) {
|
|
|
20304
20208
|
form.append(
|
|
20305
20209
|
"file",
|
|
20306
20210
|
new Blob([zipBytes], { type: "application/zip" }),
|
|
20307
|
-
|
|
20211
|
+
path28.basename(zipPath)
|
|
20308
20212
|
);
|
|
20309
20213
|
if (name) form.append("name", name);
|
|
20310
20214
|
if (appId) form.append("appId", appId);
|
|
@@ -20413,7 +20317,7 @@ function buildFactorAiManifest(appContext, deployResult, appName) {
|
|
|
20413
20317
|
}
|
|
20414
20318
|
async function writeFactorAiManifest(projectDir, appContext, deployResult, appName) {
|
|
20415
20319
|
const manifest = buildFactorAiManifest(appContext, deployResult, appName);
|
|
20416
|
-
const manifestPath =
|
|
20320
|
+
const manifestPath = path28.join(projectDir, "factorai.sh.json");
|
|
20417
20321
|
await fs25.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
20418
20322
|
`, "utf-8");
|
|
20419
20323
|
return manifest;
|
|
@@ -20441,7 +20345,7 @@ async function deployApp(args) {
|
|
|
20441
20345
|
error: `Project directory not found: ${resolvedProjectDir}`
|
|
20442
20346
|
};
|
|
20443
20347
|
}
|
|
20444
|
-
const packageJsonPath =
|
|
20348
|
+
const packageJsonPath = path28.join(resolvedProjectDir, "package.json");
|
|
20445
20349
|
try {
|
|
20446
20350
|
await fs25.access(packageJsonPath);
|
|
20447
20351
|
} catch {
|
|
@@ -20459,20 +20363,10 @@ async function deployApp(args) {
|
|
|
20459
20363
|
error: "Not a Next.js project: next not found in dependencies"
|
|
20460
20364
|
};
|
|
20461
20365
|
}
|
|
20462
|
-
const
|
|
20463
|
-
|
|
20464
|
-
return {
|
|
20465
|
-
success: false,
|
|
20466
|
-
error: `Next.js config invalid for FactorAI deploy: ${standaloneCheck.warnings.join("; ")}`
|
|
20467
|
-
};
|
|
20468
|
-
}
|
|
20469
|
-
for (const w of standaloneCheck.warnings) {
|
|
20470
|
-
console.warn(`[deploy-app] ${w}`);
|
|
20471
|
-
}
|
|
20472
|
-
const appName = name || packageJson.name || path29.basename(resolvedProjectDir);
|
|
20473
|
-
const tempDir = path29.join(resolvedProjectDir, ".tmp");
|
|
20366
|
+
const appName = name || packageJson.name || path28.basename(resolvedProjectDir);
|
|
20367
|
+
const tempDir = path28.join(resolvedProjectDir, ".tmp");
|
|
20474
20368
|
await fs25.mkdir(tempDir, { recursive: true });
|
|
20475
|
-
const zipPath =
|
|
20369
|
+
const zipPath = path28.join(tempDir, `${appName}-${Date.now()}.zip`);
|
|
20476
20370
|
console.log(`[deploy-app] Creating ZIP: ${zipPath}`);
|
|
20477
20371
|
await createDeployProjectZip(resolvedProjectDir, zipPath);
|
|
20478
20372
|
const zipStats = await fs25.stat(zipPath);
|
|
@@ -20505,7 +20399,7 @@ async function deployApp(args) {
|
|
|
20505
20399
|
appName
|
|
20506
20400
|
);
|
|
20507
20401
|
deployResult.factoraiManifest = manifest;
|
|
20508
|
-
deployResult.factoraiManifestPath =
|
|
20402
|
+
deployResult.factoraiManifestPath = path28.join(resolvedProjectDir, "factorai.sh.json");
|
|
20509
20403
|
}
|
|
20510
20404
|
console.log(`[deploy-app] Deploy iniciado: ${deployResult.appId}`);
|
|
20511
20405
|
}
|
|
@@ -20522,7 +20416,7 @@ async function deployApp(args) {
|
|
|
20522
20416
|
// src/app/agent/runtime/native_tool_catalog.ts
|
|
20523
20417
|
init_sandbox_policy();
|
|
20524
20418
|
function getFactorAiBaseUrl() {
|
|
20525
|
-
const value = process.env.FACTORAI_BASE_URL || process.env.FACTORAI_URL || "";
|
|
20419
|
+
const value = process.env.FACTORAI_BASE_URL || process.env.FACTORAI_URL || process.env.SEVERINO_URL || "";
|
|
20526
20420
|
const trimmed = value.trim();
|
|
20527
20421
|
return trimmed || void 0;
|
|
20528
20422
|
}
|
|
@@ -20560,23 +20454,52 @@ async function requestFactorAi(pathname, init = {}) {
|
|
|
20560
20454
|
}
|
|
20561
20455
|
}
|
|
20562
20456
|
if (!response.ok) {
|
|
20563
|
-
const message2 = payload?.error?.message || payload?.message || payload?.error || `FactorAI request failed with status ${response.status}`;
|
|
20564
|
-
|
|
20457
|
+
const message2 = payload?.error?.message || payload?.message || (typeof payload?.error === "string" ? payload.error : void 0) || `FactorAI request failed with status ${response.status}`;
|
|
20458
|
+
const base = getFactorAiBaseUrl();
|
|
20459
|
+
const hint = response.status === 404 && base ? ` (GET ${base}${pathname} \u2014 confirma que deploy_app usou o mesmo host; appIds antigos somem se o severino reiniciou)` : "";
|
|
20460
|
+
throw new Error(`${message2}${hint}`);
|
|
20565
20461
|
}
|
|
20566
20462
|
return payload;
|
|
20567
20463
|
}
|
|
20568
|
-
async function
|
|
20569
|
-
const
|
|
20570
|
-
if (
|
|
20571
|
-
return
|
|
20464
|
+
async function resolveFactorAiAppId(explicitAppId) {
|
|
20465
|
+
const trimmed = String(explicitAppId || "").trim();
|
|
20466
|
+
if (trimmed && isFactorAiAppUuid(trimmed)) {
|
|
20467
|
+
return trimmed;
|
|
20468
|
+
}
|
|
20469
|
+
const fromManifest = loadFactorAiAppContext();
|
|
20470
|
+
if (fromManifest?.appId) {
|
|
20471
|
+
if (!trimmed || trimmed === fromManifest.appId) {
|
|
20472
|
+
return fromManifest.appId;
|
|
20473
|
+
}
|
|
20474
|
+
}
|
|
20475
|
+
if (trimmed && !isFactorAiAppUuid(trimmed)) {
|
|
20476
|
+
const listPayload = await requestFactorAi("/api/v1/apps");
|
|
20477
|
+
const apps = listPayload?.data?.apps ?? listPayload?.apps ?? [];
|
|
20478
|
+
if (Array.isArray(apps)) {
|
|
20479
|
+
const match = apps.find(
|
|
20480
|
+
(app) => app?.slug === trimmed || app?.id === trimmed
|
|
20481
|
+
);
|
|
20482
|
+
if (match?.id && isFactorAiAppUuid(match.id)) {
|
|
20483
|
+
return match.id;
|
|
20484
|
+
}
|
|
20485
|
+
}
|
|
20486
|
+
throw new Error(
|
|
20487
|
+
`Invalid appId "${trimmed}": get_app_status exige UUID (ex: 23edf15f-70e3-4eeb-b607-9a6da250343c), n\xE3o o slug da URL. L\xEA factorai.sh.json \u2192 appContext.appId ou lista GET /api/v1/apps.`
|
|
20488
|
+
);
|
|
20489
|
+
}
|
|
20490
|
+
if (fromManifest?.appId) {
|
|
20491
|
+
return fromManifest.appId;
|
|
20572
20492
|
}
|
|
20493
|
+
throw new Error(
|
|
20494
|
+
"appId em falta: passa o UUID de factorai.sh.json (appContext.appId) ou faz deploy_app primeiro nesta sess\xE3o."
|
|
20495
|
+
);
|
|
20496
|
+
}
|
|
20497
|
+
async function factorAiGetAppStatus(args) {
|
|
20498
|
+
const appId = await resolveFactorAiAppId(args?.appId);
|
|
20573
20499
|
return requestFactorAi(`/api/v1/apps/${encodeURIComponent(appId)}`);
|
|
20574
20500
|
}
|
|
20575
20501
|
async function factorAiApplyAppChanges(args) {
|
|
20576
|
-
const appId =
|
|
20577
|
-
if (!appId) {
|
|
20578
|
-
return { error: "appId is required." };
|
|
20579
|
-
}
|
|
20502
|
+
const appId = await resolveFactorAiAppId(args?.appId);
|
|
20580
20503
|
const files = Array.isArray(args?.files) ? args.files : Array.isArray(args?.changes) ? args.changes : [];
|
|
20581
20504
|
if (files.length === 0) {
|
|
20582
20505
|
return { error: "files or changes must be a non-empty array." };
|
|
@@ -20592,10 +20515,7 @@ async function factorAiApplyAppChanges(args) {
|
|
|
20592
20515
|
return response;
|
|
20593
20516
|
}
|
|
20594
20517
|
async function factorAiRedeployApp(args) {
|
|
20595
|
-
const appId =
|
|
20596
|
-
if (!appId) {
|
|
20597
|
-
return { error: "appId is required." };
|
|
20598
|
-
}
|
|
20518
|
+
const appId = await resolveFactorAiAppId(args?.appId);
|
|
20599
20519
|
const response = await requestFactorAi(`/api/v1/apps/${encodeURIComponent(appId)}/redeploy`, {
|
|
20600
20520
|
method: "POST"
|
|
20601
20521
|
});
|
|
@@ -20691,9 +20611,12 @@ function getFactorAiSandboxToolDefinitions() {
|
|
|
20691
20611
|
parameters: {
|
|
20692
20612
|
type: "object",
|
|
20693
20613
|
properties: {
|
|
20694
|
-
appId: {
|
|
20614
|
+
appId: {
|
|
20615
|
+
type: "string",
|
|
20616
|
+
description: "UUID from factorai.sh.json (appContext.appId). Optional if manifest exists in cwd. Do not use URL slug."
|
|
20617
|
+
}
|
|
20695
20618
|
},
|
|
20696
|
-
required: [
|
|
20619
|
+
required: [],
|
|
20697
20620
|
additionalProperties: false
|
|
20698
20621
|
}
|
|
20699
20622
|
}
|
|
@@ -21586,8 +21509,8 @@ var ToolInvoker = class {
|
|
|
21586
21509
|
async initialize() {
|
|
21587
21510
|
try {
|
|
21588
21511
|
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
21589
|
-
const currentDirPath =
|
|
21590
|
-
const configPath =
|
|
21512
|
+
const currentDirPath = path29.dirname(currentFilePath);
|
|
21513
|
+
const configPath = path29.resolve(currentDirPath, "config", "native_tools.json");
|
|
21591
21514
|
const fileContent = await fs26.readFile(configPath, "utf-8");
|
|
21592
21515
|
const config3 = JSON.parse(fileContent);
|
|
21593
21516
|
this.toolDefinitions = applyMetadataToToolDefinitions(config3.nativeTools);
|
|
@@ -21636,7 +21559,7 @@ var ToolInvoker = class {
|
|
|
21636
21559
|
|
|
21637
21560
|
// src/app/agent/tools/mcp/mcp_client.ts
|
|
21638
21561
|
import { promises as fs27 } from "fs";
|
|
21639
|
-
import
|
|
21562
|
+
import path30 from "path";
|
|
21640
21563
|
import os19 from "os";
|
|
21641
21564
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
21642
21565
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -21664,9 +21587,9 @@ var MCPClient = class {
|
|
|
21664
21587
|
});
|
|
21665
21588
|
}
|
|
21666
21589
|
const __filename = fileURLToPath3(import.meta.url);
|
|
21667
|
-
const __dirname2 =
|
|
21668
|
-
const defaultConfigPath =
|
|
21669
|
-
const userConfigPath =
|
|
21590
|
+
const __dirname2 = path30.dirname(__filename);
|
|
21591
|
+
const defaultConfigPath = path30.resolve(__dirname2, "config", "bluma-mcp.json");
|
|
21592
|
+
const userConfigPath = path30.join(os19.homedir(), ".bluma", "bluma-mcp.json");
|
|
21670
21593
|
const defaultConfig = await this.loadMcpConfig(defaultConfigPath, "Default");
|
|
21671
21594
|
const userConfig = await this.loadMcpConfig(userConfigPath, "User");
|
|
21672
21595
|
const mergedConfig = {
|
|
@@ -21913,19 +21836,19 @@ PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
|
|
|
21913
21836
|
|
|
21914
21837
|
// src/app/agent/bluma/core/bluma.ts
|
|
21915
21838
|
init_session_manager();
|
|
21916
|
-
import
|
|
21839
|
+
import path45 from "path";
|
|
21917
21840
|
import fs40 from "fs";
|
|
21918
21841
|
import { v4 as uuidv48 } from "uuid";
|
|
21919
21842
|
|
|
21920
21843
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
21921
21844
|
import os23 from "os";
|
|
21922
21845
|
import fs36 from "fs";
|
|
21923
|
-
import
|
|
21846
|
+
import path39 from "path";
|
|
21924
21847
|
import { execSync as execSync3 } from "child_process";
|
|
21925
21848
|
|
|
21926
21849
|
// src/app/agent/skills/skill_loader.ts
|
|
21927
21850
|
import fs31 from "fs";
|
|
21928
|
-
import
|
|
21851
|
+
import path34 from "path";
|
|
21929
21852
|
import os20 from "os";
|
|
21930
21853
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
21931
21854
|
var SkillLoader = class _SkillLoader {
|
|
@@ -21935,8 +21858,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
21935
21858
|
cache = /* @__PURE__ */ new Map();
|
|
21936
21859
|
conflicts = [];
|
|
21937
21860
|
constructor(projectRoot, bundledDir) {
|
|
21938
|
-
this.projectSkillsDir =
|
|
21939
|
-
this.globalSkillsDir =
|
|
21861
|
+
this.projectSkillsDir = path34.join(projectRoot, ".bluma", "skills");
|
|
21862
|
+
this.globalSkillsDir = path34.join(os20.homedir(), ".bluma", "skills");
|
|
21940
21863
|
this.bundledSkillsDir = bundledDir || _SkillLoader.resolveBundledDir();
|
|
21941
21864
|
}
|
|
21942
21865
|
/**
|
|
@@ -21945,32 +21868,32 @@ var SkillLoader = class _SkillLoader {
|
|
|
21945
21868
|
*/
|
|
21946
21869
|
static resolveBundledDir() {
|
|
21947
21870
|
if (process.env.JEST_WORKER_ID !== void 0 || process.env.NODE_ENV === "test") {
|
|
21948
|
-
return
|
|
21871
|
+
return path34.join(process.cwd(), "dist", "config", "skills");
|
|
21949
21872
|
}
|
|
21950
21873
|
const candidates = [];
|
|
21951
21874
|
const push = (p) => {
|
|
21952
|
-
const abs =
|
|
21875
|
+
const abs = path34.resolve(p);
|
|
21953
21876
|
if (!candidates.includes(abs)) {
|
|
21954
21877
|
candidates.push(abs);
|
|
21955
21878
|
}
|
|
21956
21879
|
};
|
|
21957
21880
|
let argvBundled = null;
|
|
21958
21881
|
try {
|
|
21959
|
-
const bundleDir =
|
|
21960
|
-
push(
|
|
21882
|
+
const bundleDir = path34.dirname(fileURLToPath4(import.meta.url));
|
|
21883
|
+
push(path34.join(bundleDir, "config", "skills"));
|
|
21961
21884
|
} catch {
|
|
21962
21885
|
}
|
|
21963
21886
|
const argv1 = process.argv[1];
|
|
21964
21887
|
if (argv1 && !argv1.startsWith("-")) {
|
|
21965
21888
|
try {
|
|
21966
21889
|
let resolved = argv1;
|
|
21967
|
-
if (
|
|
21890
|
+
if (path34.isAbsolute(argv1) && fs31.existsSync(argv1)) {
|
|
21968
21891
|
resolved = fs31.realpathSync(argv1);
|
|
21969
|
-
} else if (!
|
|
21970
|
-
resolved =
|
|
21892
|
+
} else if (!path34.isAbsolute(argv1)) {
|
|
21893
|
+
resolved = path34.resolve(process.cwd(), argv1);
|
|
21971
21894
|
}
|
|
21972
|
-
const scriptDir =
|
|
21973
|
-
argvBundled =
|
|
21895
|
+
const scriptDir = path34.dirname(resolved);
|
|
21896
|
+
argvBundled = path34.join(scriptDir, "config", "skills");
|
|
21974
21897
|
push(argvBundled);
|
|
21975
21898
|
} catch {
|
|
21976
21899
|
}
|
|
@@ -21981,12 +21904,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
21981
21904
|
}
|
|
21982
21905
|
}
|
|
21983
21906
|
try {
|
|
21984
|
-
return
|
|
21907
|
+
return path34.join(path34.dirname(fileURLToPath4(import.meta.url)), "config", "skills");
|
|
21985
21908
|
} catch {
|
|
21986
21909
|
if (argvBundled) {
|
|
21987
21910
|
return argvBundled;
|
|
21988
21911
|
}
|
|
21989
|
-
return
|
|
21912
|
+
return path34.join(os20.homedir(), ".bluma", "__bundled_skills_unresolved__");
|
|
21990
21913
|
}
|
|
21991
21914
|
}
|
|
21992
21915
|
/**
|
|
@@ -22015,8 +21938,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
22015
21938
|
this.conflicts.push({
|
|
22016
21939
|
name: skill.name,
|
|
22017
21940
|
userSource: source,
|
|
22018
|
-
userPath:
|
|
22019
|
-
bundledPath:
|
|
21941
|
+
userPath: path34.join(dir, skill.name, "SKILL.md"),
|
|
21942
|
+
bundledPath: path34.join(this.bundledSkillsDir, skill.name, "SKILL.md")
|
|
22020
21943
|
});
|
|
22021
21944
|
continue;
|
|
22022
21945
|
}
|
|
@@ -22027,9 +21950,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22027
21950
|
if (!fs31.existsSync(dir)) return [];
|
|
22028
21951
|
try {
|
|
22029
21952
|
return fs31.readdirSync(dir).filter((d) => {
|
|
22030
|
-
const fullPath =
|
|
22031
|
-
return fs31.statSync(fullPath).isDirectory() && fs31.existsSync(
|
|
22032
|
-
}).map((d) => this.loadMetadataFromPath(
|
|
21953
|
+
const fullPath = path34.join(dir, d);
|
|
21954
|
+
return fs31.statSync(fullPath).isDirectory() && fs31.existsSync(path34.join(fullPath, "SKILL.md"));
|
|
21955
|
+
}).map((d) => this.loadMetadataFromPath(path34.join(dir, d, "SKILL.md"), d, source)).filter((m) => m !== null);
|
|
22033
21956
|
} catch {
|
|
22034
21957
|
return [];
|
|
22035
21958
|
}
|
|
@@ -22059,9 +21982,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22059
21982
|
*/
|
|
22060
21983
|
load(name) {
|
|
22061
21984
|
if (this.cache.has(name)) return this.cache.get(name);
|
|
22062
|
-
const bundledPath =
|
|
22063
|
-
const projectPath =
|
|
22064
|
-
const globalPath =
|
|
21985
|
+
const bundledPath = path34.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
21986
|
+
const projectPath = path34.join(this.projectSkillsDir, name, "SKILL.md");
|
|
21987
|
+
const globalPath = path34.join(this.globalSkillsDir, name, "SKILL.md");
|
|
22065
21988
|
const existsBundled = fs31.existsSync(bundledPath);
|
|
22066
21989
|
const existsProject = fs31.existsSync(projectPath);
|
|
22067
21990
|
const existsGlobal = fs31.existsSync(globalPath);
|
|
@@ -22105,7 +22028,7 @@ var SkillLoader = class _SkillLoader {
|
|
|
22105
22028
|
try {
|
|
22106
22029
|
const raw = fs31.readFileSync(skillPath, "utf-8");
|
|
22107
22030
|
const parsed = this.parseFrontmatter(raw);
|
|
22108
|
-
const skillDir =
|
|
22031
|
+
const skillDir = path34.dirname(skillPath);
|
|
22109
22032
|
return {
|
|
22110
22033
|
name: parsed.name || name,
|
|
22111
22034
|
description: parsed.description || "",
|
|
@@ -22114,8 +22037,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
22114
22037
|
version: parsed.version,
|
|
22115
22038
|
author: parsed.author,
|
|
22116
22039
|
license: parsed.license,
|
|
22117
|
-
references: this.scanAssets(
|
|
22118
|
-
scripts: this.scanAssets(
|
|
22040
|
+
references: this.scanAssets(path34.join(skillDir, "references")),
|
|
22041
|
+
scripts: this.scanAssets(path34.join(skillDir, "scripts"))
|
|
22119
22042
|
};
|
|
22120
22043
|
} catch {
|
|
22121
22044
|
return null;
|
|
@@ -22125,11 +22048,11 @@ var SkillLoader = class _SkillLoader {
|
|
|
22125
22048
|
if (!fs31.existsSync(dir)) return [];
|
|
22126
22049
|
try {
|
|
22127
22050
|
return fs31.readdirSync(dir).filter((f) => {
|
|
22128
|
-
const fp =
|
|
22051
|
+
const fp = path34.join(dir, f);
|
|
22129
22052
|
return fs31.statSync(fp).isFile();
|
|
22130
22053
|
}).map((f) => ({
|
|
22131
22054
|
name: f,
|
|
22132
|
-
path:
|
|
22055
|
+
path: path34.resolve(dir, f)
|
|
22133
22056
|
}));
|
|
22134
22057
|
} catch {
|
|
22135
22058
|
return [];
|
|
@@ -22186,9 +22109,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22186
22109
|
this.cache.clear();
|
|
22187
22110
|
}
|
|
22188
22111
|
exists(name) {
|
|
22189
|
-
const bundledPath =
|
|
22190
|
-
const projectPath =
|
|
22191
|
-
const globalPath =
|
|
22112
|
+
const bundledPath = path34.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
22113
|
+
const projectPath = path34.join(this.projectSkillsDir, name, "SKILL.md");
|
|
22114
|
+
const globalPath = path34.join(this.globalSkillsDir, name, "SKILL.md");
|
|
22192
22115
|
return fs31.existsSync(bundledPath) || fs31.existsSync(projectPath) || fs31.existsSync(globalPath);
|
|
22193
22116
|
}
|
|
22194
22117
|
/**
|
|
@@ -22222,12 +22145,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
22222
22145
|
|
|
22223
22146
|
// src/app/agent/core/prompt/workspace_snapshot.ts
|
|
22224
22147
|
import fs33 from "fs";
|
|
22225
|
-
import
|
|
22148
|
+
import path36 from "path";
|
|
22226
22149
|
import { execSync as execSync2 } from "child_process";
|
|
22227
22150
|
|
|
22228
22151
|
// src/app/agent/utils/blumamd.ts
|
|
22229
22152
|
import fs32 from "fs";
|
|
22230
|
-
import
|
|
22153
|
+
import path35 from "path";
|
|
22231
22154
|
import os21 from "os";
|
|
22232
22155
|
import { execSync } from "child_process";
|
|
22233
22156
|
var MEMORY_INSTRUCTION_PROMPT = "Instru\xE7\xF5es de mem\xF3ria do BluMa (BLUMA.md) est\xE3o abaixo. Siga estas instru\xE7\xF5es exatamente como escritas. Estas instru\xE7\xF5es OVERRIDE qualquer comportamento padr\xE3o.";
|
|
@@ -22357,12 +22280,12 @@ var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
22357
22280
|
function expandIncludePath(includePath, baseDir) {
|
|
22358
22281
|
const cleanPath = includePath.startsWith("@") ? includePath.slice(1) : includePath;
|
|
22359
22282
|
if (cleanPath.startsWith("~")) {
|
|
22360
|
-
return
|
|
22283
|
+
return path35.join(os21.homedir(), cleanPath.slice(1));
|
|
22361
22284
|
}
|
|
22362
|
-
if (
|
|
22285
|
+
if (path35.isAbsolute(cleanPath)) {
|
|
22363
22286
|
return cleanPath;
|
|
22364
22287
|
}
|
|
22365
|
-
return
|
|
22288
|
+
return path35.resolve(baseDir, cleanPath);
|
|
22366
22289
|
}
|
|
22367
22290
|
function processIncludes(content, baseDir, processedFiles) {
|
|
22368
22291
|
const lines = content.split("\n");
|
|
@@ -22371,12 +22294,12 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
22371
22294
|
const includeMatch = line.match(/^@\s*([^\s]+)/);
|
|
22372
22295
|
if (includeMatch) {
|
|
22373
22296
|
const includePath = expandIncludePath(includeMatch[1], baseDir);
|
|
22374
|
-
const normalizedPath =
|
|
22297
|
+
const normalizedPath = path35.normalize(includePath);
|
|
22375
22298
|
if (processedFiles.has(normalizedPath)) {
|
|
22376
22299
|
result.push(`<!-- Circular include prevented: ${includeMatch[1]} -->`);
|
|
22377
22300
|
continue;
|
|
22378
22301
|
}
|
|
22379
|
-
const ext =
|
|
22302
|
+
const ext = path35.extname(includePath).toLowerCase();
|
|
22380
22303
|
if (!TEXT_FILE_EXTENSIONS.has(ext)) {
|
|
22381
22304
|
result.push(`<!-- Include skipped (unsupported extension): ${includeMatch[1]} -->`);
|
|
22382
22305
|
continue;
|
|
@@ -22384,7 +22307,7 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
22384
22307
|
try {
|
|
22385
22308
|
const includedContent = fs32.readFileSync(includePath, "utf-8");
|
|
22386
22309
|
processedFiles.add(normalizedPath);
|
|
22387
|
-
const processedContent = processIncludes(includedContent,
|
|
22310
|
+
const processedContent = processIncludes(includedContent, path35.dirname(includePath), processedFiles);
|
|
22388
22311
|
result.push(`
|
|
22389
22312
|
<!-- BEGIN INCLUDE ${includeMatch[1]} -->
|
|
22390
22313
|
`);
|
|
@@ -22431,8 +22354,8 @@ function parseFrontmatterPaths(paths2) {
|
|
|
22431
22354
|
function readMemoryFile(filePath, type, includeBasePath) {
|
|
22432
22355
|
try {
|
|
22433
22356
|
const rawContent = fs32.readFileSync(filePath, "utf-8");
|
|
22434
|
-
const baseDir = includeBasePath ||
|
|
22435
|
-
const processedFiles = /* @__PURE__ */ new Set([
|
|
22357
|
+
const baseDir = includeBasePath || path35.dirname(filePath);
|
|
22358
|
+
const processedFiles = /* @__PURE__ */ new Set([path35.normalize(filePath)]);
|
|
22436
22359
|
const { frontmatter, content: withoutFrontmatter } = parseFrontmatter(rawContent);
|
|
22437
22360
|
const globs = parseFrontmatterPaths(frontmatter.paths);
|
|
22438
22361
|
const processedContent = processIncludes(withoutFrontmatter, baseDir, processedFiles);
|
|
@@ -22454,15 +22377,15 @@ function readMemoryFile(filePath, type, includeBasePath) {
|
|
|
22454
22377
|
}
|
|
22455
22378
|
function findGitRoot(startDir) {
|
|
22456
22379
|
let current = startDir;
|
|
22457
|
-
while (current !==
|
|
22458
|
-
const gitPath =
|
|
22380
|
+
while (current !== path35.dirname(current)) {
|
|
22381
|
+
const gitPath = path35.join(current, ".git");
|
|
22459
22382
|
try {
|
|
22460
22383
|
if (fs32.existsSync(gitPath)) {
|
|
22461
22384
|
return current;
|
|
22462
22385
|
}
|
|
22463
22386
|
} catch {
|
|
22464
22387
|
}
|
|
22465
|
-
current =
|
|
22388
|
+
current = path35.dirname(current);
|
|
22466
22389
|
}
|
|
22467
22390
|
return null;
|
|
22468
22391
|
}
|
|
@@ -22493,11 +22416,11 @@ function processRulesDirectory(rulesDir, type, processedPaths, conditionalRule =
|
|
|
22493
22416
|
try {
|
|
22494
22417
|
const entries = fs32.readdirSync(rulesDir, { withFileTypes: true });
|
|
22495
22418
|
for (const entry of entries) {
|
|
22496
|
-
const entryPath =
|
|
22419
|
+
const entryPath = path35.join(rulesDir, entry.name);
|
|
22497
22420
|
if (entry.isDirectory()) {
|
|
22498
22421
|
result.push(...processRulesDirectory(entryPath, type, processedPaths, conditionalRule));
|
|
22499
22422
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22500
|
-
const normalizedPath =
|
|
22423
|
+
const normalizedPath = path35.normalize(entryPath);
|
|
22501
22424
|
if (processedPaths.has(normalizedPath)) {
|
|
22502
22425
|
continue;
|
|
22503
22426
|
}
|
|
@@ -22533,13 +22456,13 @@ function loadManagedMemory() {
|
|
|
22533
22456
|
function loadUserMemory() {
|
|
22534
22457
|
const files = [];
|
|
22535
22458
|
const homeDir = os21.homedir();
|
|
22536
|
-
const userBlumaDir =
|
|
22537
|
-
const userBlumaMd =
|
|
22459
|
+
const userBlumaDir = path35.join(homeDir, ".bluma");
|
|
22460
|
+
const userBlumaMd = path35.join(userBlumaDir, "BLUMA.md");
|
|
22538
22461
|
const userFile = readMemoryFile(userBlumaMd, "User");
|
|
22539
22462
|
if (userFile && userFile.content.trim()) {
|
|
22540
22463
|
files.push(userFile);
|
|
22541
22464
|
}
|
|
22542
|
-
const userRulesDir =
|
|
22465
|
+
const userRulesDir = path35.join(userBlumaDir, "rules");
|
|
22543
22466
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22544
22467
|
files.push(...processRulesDirectory(userRulesDir, "User", processedPaths, false));
|
|
22545
22468
|
return files;
|
|
@@ -22551,10 +22474,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22551
22474
|
let currentDir = cwd2;
|
|
22552
22475
|
const MAX_TRAVERSAL_DEPTH = 20;
|
|
22553
22476
|
let depth = 0;
|
|
22554
|
-
const normalizedGitRoot =
|
|
22555
|
-
while (currentDir !==
|
|
22477
|
+
const normalizedGitRoot = path35.resolve(gitRoot);
|
|
22478
|
+
while (currentDir !== path35.dirname(currentDir) && path35.resolve(currentDir).startsWith(normalizedGitRoot) && depth < MAX_TRAVERSAL_DEPTH) {
|
|
22556
22479
|
dirs.push(currentDir);
|
|
22557
|
-
currentDir =
|
|
22480
|
+
currentDir = path35.dirname(currentDir);
|
|
22558
22481
|
depth++;
|
|
22559
22482
|
}
|
|
22560
22483
|
if (!dirs.includes(gitRoot)) {
|
|
@@ -22562,7 +22485,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22562
22485
|
}
|
|
22563
22486
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22564
22487
|
for (const dir of dirs.reverse()) {
|
|
22565
|
-
const projectBlumaMd =
|
|
22488
|
+
const projectBlumaMd = path35.join(dir, "BLUMA.md");
|
|
22566
22489
|
if (!processedPaths.has(projectBlumaMd)) {
|
|
22567
22490
|
processedPaths.add(projectBlumaMd);
|
|
22568
22491
|
const projectFile = readMemoryFile(projectBlumaMd, "Project");
|
|
@@ -22570,7 +22493,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22570
22493
|
files.push(projectFile);
|
|
22571
22494
|
}
|
|
22572
22495
|
}
|
|
22573
|
-
const blumaDirBlumaMd =
|
|
22496
|
+
const blumaDirBlumaMd = path35.join(dir, ".bluma", "BLUMA.md");
|
|
22574
22497
|
if (!processedPaths.has(blumaDirBlumaMd)) {
|
|
22575
22498
|
processedPaths.add(blumaDirBlumaMd);
|
|
22576
22499
|
const blumaDirFile = readMemoryFile(blumaDirBlumaMd, "Project");
|
|
@@ -22578,10 +22501,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22578
22501
|
files.push(blumaDirFile);
|
|
22579
22502
|
}
|
|
22580
22503
|
}
|
|
22581
|
-
const rulesDir =
|
|
22504
|
+
const rulesDir = path35.join(dir, ".bluma", "rules");
|
|
22582
22505
|
files.push(...processRulesDirectory(rulesDir, "Project", processedPaths, false));
|
|
22583
22506
|
}
|
|
22584
|
-
const localBlumaMd =
|
|
22507
|
+
const localBlumaMd = path35.join(cwd2, "BLUMA.local.md");
|
|
22585
22508
|
if (!processedPaths.has(localBlumaMd)) {
|
|
22586
22509
|
processedPaths.add(localBlumaMd);
|
|
22587
22510
|
const localFile = readMemoryFile(localBlumaMd, "Local");
|
|
@@ -22682,7 +22605,7 @@ function safeReadFile(filePath, maxChars) {
|
|
|
22682
22605
|
}
|
|
22683
22606
|
function tryReadReadme(cwd2) {
|
|
22684
22607
|
for (const name of ["README.md", "README.MD", "readme.md", "Readme.md"]) {
|
|
22685
|
-
const c = safeReadFile(
|
|
22608
|
+
const c = safeReadFile(path36.join(cwd2, name), LIMITS.readme);
|
|
22686
22609
|
if (c) return `(${name})
|
|
22687
22610
|
${c}`;
|
|
22688
22611
|
}
|
|
@@ -22690,14 +22613,14 @@ ${c}`;
|
|
|
22690
22613
|
}
|
|
22691
22614
|
function tryReadBluMaMd(cwd2) {
|
|
22692
22615
|
const paths2 = [
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22616
|
+
path36.join(cwd2, "BluMa.md"),
|
|
22617
|
+
path36.join(cwd2, "BLUMA.md"),
|
|
22618
|
+
path36.join(cwd2, ".bluma", "BluMa.md")
|
|
22696
22619
|
];
|
|
22697
22620
|
for (const p of paths2) {
|
|
22698
22621
|
const c = safeReadFile(p, LIMITS.blumaMd);
|
|
22699
22622
|
if (c) {
|
|
22700
|
-
const rel =
|
|
22623
|
+
const rel = path36.relative(cwd2, p) || p;
|
|
22701
22624
|
return `(${rel})
|
|
22702
22625
|
${c}`;
|
|
22703
22626
|
}
|
|
@@ -22705,7 +22628,7 @@ ${c}`;
|
|
|
22705
22628
|
return null;
|
|
22706
22629
|
}
|
|
22707
22630
|
function summarizePackageJson(cwd2) {
|
|
22708
|
-
const p =
|
|
22631
|
+
const p = path36.join(cwd2, "package.json");
|
|
22709
22632
|
try {
|
|
22710
22633
|
if (!fs33.existsSync(p)) return null;
|
|
22711
22634
|
const pkg = JSON.parse(fs33.readFileSync(p, "utf8"));
|
|
@@ -22799,7 +22722,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22799
22722
|
parts.push(pkg);
|
|
22800
22723
|
parts.push("```\n");
|
|
22801
22724
|
}
|
|
22802
|
-
const py = safeReadFile(
|
|
22725
|
+
const py = safeReadFile(path36.join(cwd2, "pyproject.toml"), LIMITS.pyproject);
|
|
22803
22726
|
if (py) {
|
|
22804
22727
|
parts.push("### pyproject.toml (excerpt)\n```toml");
|
|
22805
22728
|
parts.push(py);
|
|
@@ -22817,15 +22740,15 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22817
22740
|
parts.push(bluma);
|
|
22818
22741
|
parts.push("```\n");
|
|
22819
22742
|
}
|
|
22820
|
-
const contrib = safeReadFile(
|
|
22743
|
+
const contrib = safeReadFile(path36.join(cwd2, "CONTRIBUTING.md"), LIMITS.contributing);
|
|
22821
22744
|
if (contrib) {
|
|
22822
22745
|
parts.push("### CONTRIBUTING.md (excerpt)\n```markdown");
|
|
22823
22746
|
parts.push(contrib);
|
|
22824
22747
|
parts.push("```\n");
|
|
22825
22748
|
}
|
|
22826
|
-
const chlog = safeReadFile(
|
|
22749
|
+
const chlog = safeReadFile(path36.join(cwd2, "CHANGELOG.md"), LIMITS.changelog);
|
|
22827
22750
|
if (!chlog) {
|
|
22828
|
-
const alt = safeReadFile(
|
|
22751
|
+
const alt = safeReadFile(path36.join(cwd2, "CHANGES.md"), LIMITS.changelog);
|
|
22829
22752
|
if (alt) {
|
|
22830
22753
|
parts.push("### CHANGES.md (excerpt)\n```markdown");
|
|
22831
22754
|
parts.push(alt);
|
|
@@ -22861,14 +22784,14 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22861
22784
|
} else {
|
|
22862
22785
|
parts.push("### Git\n(not a git work tree, or `git` unavailable)\n");
|
|
22863
22786
|
}
|
|
22864
|
-
const tsconfig = safeReadFile(
|
|
22787
|
+
const tsconfig = safeReadFile(path36.join(cwd2, "tsconfig.json"), LIMITS.tsconfig);
|
|
22865
22788
|
if (tsconfig) {
|
|
22866
22789
|
parts.push("### tsconfig.json (excerpt)\n```json");
|
|
22867
22790
|
parts.push(tsconfig);
|
|
22868
22791
|
parts.push("```\n");
|
|
22869
22792
|
}
|
|
22870
22793
|
for (const name of ["Dockerfile", "dockerfile", "Dockerfile.prod", "Dockerfile.dev"]) {
|
|
22871
|
-
const df = safeReadFile(
|
|
22794
|
+
const df = safeReadFile(path36.join(cwd2, name), LIMITS.dockerfile);
|
|
22872
22795
|
if (df) {
|
|
22873
22796
|
parts.push(`### ${name} (excerpt)
|
|
22874
22797
|
`);
|
|
@@ -22878,7 +22801,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22878
22801
|
}
|
|
22879
22802
|
}
|
|
22880
22803
|
for (const name of ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"]) {
|
|
22881
|
-
const dc = safeReadFile(
|
|
22804
|
+
const dc = safeReadFile(path36.join(cwd2, name), LIMITS.dockerfile);
|
|
22882
22805
|
if (dc) {
|
|
22883
22806
|
parts.push(`### ${name} (excerpt)
|
|
22884
22807
|
`);
|
|
@@ -22893,7 +22816,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22893
22816
|
".circleci/config.yml",
|
|
22894
22817
|
"Jenkinsfile"
|
|
22895
22818
|
]) {
|
|
22896
|
-
const ciFile =
|
|
22819
|
+
const ciFile = path36.join(cwd2, ciPath);
|
|
22897
22820
|
if (fs33.existsSync(ciFile)) {
|
|
22898
22821
|
const st = fs33.statSync(ciFile);
|
|
22899
22822
|
if (st.isDirectory()) {
|
|
@@ -22909,7 +22832,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22909
22832
|
} else {
|
|
22910
22833
|
const ci = safeReadFile(ciFile, LIMITS.ciConfig);
|
|
22911
22834
|
if (ci) {
|
|
22912
|
-
parts.push(`### CI config (${
|
|
22835
|
+
parts.push(`### CI config (${path36.basename(ciPath)})
|
|
22913
22836
|
`);
|
|
22914
22837
|
parts.push(ci);
|
|
22915
22838
|
parts.push("\n");
|
|
@@ -22918,7 +22841,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22918
22841
|
}
|
|
22919
22842
|
}
|
|
22920
22843
|
for (const depFile of ["requirements.txt", "Pipfile", "poetry.lock", "Gemfile", "go.sum", "Cargo.lock"]) {
|
|
22921
|
-
const depPath =
|
|
22844
|
+
const depPath = path36.join(cwd2, depFile);
|
|
22922
22845
|
if (fs33.existsSync(depPath)) {
|
|
22923
22846
|
const depContent = safeReadFile(depPath, 1500);
|
|
22924
22847
|
if (depContent) {
|
|
@@ -22932,7 +22855,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22932
22855
|
}
|
|
22933
22856
|
}
|
|
22934
22857
|
for (const envFile of [".env.example", ".env.sample", ".env.template"]) {
|
|
22935
|
-
const envPath =
|
|
22858
|
+
const envPath = path36.join(cwd2, envFile);
|
|
22936
22859
|
if (fs33.existsSync(envPath)) {
|
|
22937
22860
|
try {
|
|
22938
22861
|
const raw = fs33.readFileSync(envPath, "utf-8");
|
|
@@ -22960,13 +22883,13 @@ init_runtime_config();
|
|
|
22960
22883
|
init_sandbox_policy();
|
|
22961
22884
|
import fs34 from "fs";
|
|
22962
22885
|
import os22 from "os";
|
|
22963
|
-
import
|
|
22886
|
+
import path37 from "path";
|
|
22964
22887
|
function getProjectPluginsDir() {
|
|
22965
22888
|
const policy = getSandboxPolicy();
|
|
22966
|
-
return
|
|
22889
|
+
return path37.join(policy.workspaceRoot, ".bluma", "plugins");
|
|
22967
22890
|
}
|
|
22968
22891
|
function getGlobalPluginsDir() {
|
|
22969
|
-
return
|
|
22892
|
+
return path37.join(process.env.HOME || os22.homedir(), ".bluma", "plugins");
|
|
22970
22893
|
}
|
|
22971
22894
|
function getPluginDirs() {
|
|
22972
22895
|
return {
|
|
@@ -22992,8 +22915,8 @@ function readManifest(manifestPath, fallbackName) {
|
|
|
22992
22915
|
}
|
|
22993
22916
|
function findManifestPath(pluginDir) {
|
|
22994
22917
|
const candidates = [
|
|
22995
|
-
|
|
22996
|
-
|
|
22918
|
+
path37.join(pluginDir, ".codex-plugin", "plugin.json"),
|
|
22919
|
+
path37.join(pluginDir, "plugin.json")
|
|
22997
22920
|
];
|
|
22998
22921
|
for (const candidate of candidates) {
|
|
22999
22922
|
if (fs34.existsSync(candidate)) {
|
|
@@ -23007,7 +22930,7 @@ function listFromDir(baseDir, source) {
|
|
|
23007
22930
|
return [];
|
|
23008
22931
|
}
|
|
23009
22932
|
return fs34.readdirSync(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).flatMap((entry) => {
|
|
23010
|
-
const pluginDir =
|
|
22933
|
+
const pluginDir = path37.join(baseDir, entry.name);
|
|
23011
22934
|
const manifestPath = findManifestPath(pluginDir);
|
|
23012
22935
|
if (!manifestPath) {
|
|
23013
22936
|
return [];
|
|
@@ -23453,7 +23376,7 @@ function buildModelInfoSection(modelId) {
|
|
|
23453
23376
|
// src/app/agent/runtime/hook_registry.ts
|
|
23454
23377
|
init_sandbox_policy();
|
|
23455
23378
|
import fs35 from "fs";
|
|
23456
|
-
import
|
|
23379
|
+
import path38 from "path";
|
|
23457
23380
|
var DEFAULT_STATE = {
|
|
23458
23381
|
enabled: true,
|
|
23459
23382
|
maxEvents: 120,
|
|
@@ -23464,7 +23387,7 @@ var cache3 = null;
|
|
|
23464
23387
|
var cachePath2 = null;
|
|
23465
23388
|
function getStatePath() {
|
|
23466
23389
|
const policy = getSandboxPolicy();
|
|
23467
|
-
return
|
|
23390
|
+
return path38.join(policy.workspaceRoot, ".bluma", "hooks.json");
|
|
23468
23391
|
}
|
|
23469
23392
|
function getHookStatePath() {
|
|
23470
23393
|
return getStatePath();
|
|
@@ -23510,7 +23433,7 @@ function ensureLoaded2() {
|
|
|
23510
23433
|
}
|
|
23511
23434
|
function persist2(state2) {
|
|
23512
23435
|
const statePath = getStatePath();
|
|
23513
|
-
fs35.mkdirSync(
|
|
23436
|
+
fs35.mkdirSync(path38.dirname(statePath), { recursive: true });
|
|
23514
23437
|
state2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23515
23438
|
fs35.writeFileSync(statePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
23516
23439
|
cache3 = state2;
|
|
@@ -23774,15 +23697,15 @@ init_memdir();
|
|
|
23774
23697
|
|
|
23775
23698
|
// src/app/agent/memory/session_memory_context.ts
|
|
23776
23699
|
init_session_memory_paths();
|
|
23777
|
-
import { readFile as
|
|
23700
|
+
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
23778
23701
|
async function loadSessionMemoryForPrompt(sessionId, cwd2 = process.cwd()) {
|
|
23779
23702
|
if (!sessionId?.trim()) return "";
|
|
23780
|
-
const
|
|
23703
|
+
const path59 = getSessionMemoryPath(sessionId, cwd2);
|
|
23781
23704
|
try {
|
|
23782
|
-
const content = await
|
|
23705
|
+
const content = await readFile3(path59, "utf-8");
|
|
23783
23706
|
if (!content.trim()) return "";
|
|
23784
23707
|
return `<session_memory>
|
|
23785
|
-
Notes for this conversation (${
|
|
23708
|
+
Notes for this conversation (${path59}):
|
|
23786
23709
|
|
|
23787
23710
|
${content.trim()}
|
|
23788
23711
|
</session_memory>`;
|
|
@@ -23792,11 +23715,11 @@ ${content.trim()}
|
|
|
23792
23715
|
}
|
|
23793
23716
|
async function initSessionMemoryFile(sessionId, cwd2 = process.cwd()) {
|
|
23794
23717
|
await ensureSessionMemoryDir(sessionId, cwd2);
|
|
23795
|
-
const
|
|
23718
|
+
const path59 = getSessionMemoryPath(sessionId, cwd2);
|
|
23796
23719
|
try {
|
|
23797
|
-
await
|
|
23720
|
+
await readFile3(path59, "utf-8");
|
|
23798
23721
|
} catch {
|
|
23799
|
-
await
|
|
23722
|
+
await writeFile2(path59, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
|
|
23800
23723
|
`, "utf-8");
|
|
23801
23724
|
}
|
|
23802
23725
|
}
|
|
@@ -23878,7 +23801,7 @@ Use \`factorai.sh.redeploy_app({ appId })\` only when sources on the server are
|
|
|
23878
23801
|
|
|
23879
23802
|
## Deploy constraints (first deploy)
|
|
23880
23803
|
|
|
23881
|
-
- \`next.config.js\` must
|
|
23804
|
+
- \`next.config.js\` must keep \`output: 'standalone'\` (included in scaffold).
|
|
23882
23805
|
- ZIP max ~50MB \u2014 source only; Severino runs \`npm install\` + \`next build\` on the server.
|
|
23883
23806
|
- shadcn components in scaffold must compile (no missing Radix imports).
|
|
23884
23807
|
|
|
@@ -23929,17 +23852,17 @@ function getGitBranch(dir) {
|
|
|
23929
23852
|
}
|
|
23930
23853
|
}
|
|
23931
23854
|
function getPackageManager(dir) {
|
|
23932
|
-
if (fs36.existsSync(
|
|
23933
|
-
if (fs36.existsSync(
|
|
23934
|
-
if (fs36.existsSync(
|
|
23935
|
-
if (fs36.existsSync(
|
|
23855
|
+
if (fs36.existsSync(path39.join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
23856
|
+
if (fs36.existsSync(path39.join(dir, "yarn.lock"))) return "yarn";
|
|
23857
|
+
if (fs36.existsSync(path39.join(dir, "bun.lockb"))) return "bun";
|
|
23858
|
+
if (fs36.existsSync(path39.join(dir, "package-lock.json"))) return "npm";
|
|
23936
23859
|
return "unknown";
|
|
23937
23860
|
}
|
|
23938
23861
|
function getProjectType(dir) {
|
|
23939
23862
|
try {
|
|
23940
23863
|
const files = fs36.readdirSync(dir);
|
|
23941
23864
|
if (files.includes("package.json")) {
|
|
23942
|
-
const pkg = JSON.parse(fs36.readFileSync(
|
|
23865
|
+
const pkg = JSON.parse(fs36.readFileSync(path39.join(dir, "package.json"), "utf-8"));
|
|
23943
23866
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
23944
23867
|
if (deps.next) return "Next.js";
|
|
23945
23868
|
if (deps.react) return "React";
|
|
@@ -23959,7 +23882,7 @@ function getProjectType(dir) {
|
|
|
23959
23882
|
}
|
|
23960
23883
|
function getTestFramework(dir) {
|
|
23961
23884
|
try {
|
|
23962
|
-
const pkgPath =
|
|
23885
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23963
23886
|
if (fs36.existsSync(pkgPath)) {
|
|
23964
23887
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23965
23888
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -23970,7 +23893,7 @@ function getTestFramework(dir) {
|
|
|
23970
23893
|
if (deps["@playwright/test"]) return "playwright";
|
|
23971
23894
|
if (deps.cypress) return "cypress";
|
|
23972
23895
|
}
|
|
23973
|
-
if (fs36.existsSync(
|
|
23896
|
+
if (fs36.existsSync(path39.join(dir, "pytest.ini")) || fs36.existsSync(path39.join(dir, "conftest.py"))) return "pytest";
|
|
23974
23897
|
return "unknown";
|
|
23975
23898
|
} catch {
|
|
23976
23899
|
return "unknown";
|
|
@@ -23978,7 +23901,7 @@ function getTestFramework(dir) {
|
|
|
23978
23901
|
}
|
|
23979
23902
|
function getTestCommand(dir) {
|
|
23980
23903
|
try {
|
|
23981
|
-
const pkgPath =
|
|
23904
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23982
23905
|
if (fs36.existsSync(pkgPath)) {
|
|
23983
23906
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23984
23907
|
if (pkg.scripts?.test) return "npm test";
|
|
@@ -23995,7 +23918,7 @@ function getTestCommand(dir) {
|
|
|
23995
23918
|
}
|
|
23996
23919
|
function isGitRepo(dir) {
|
|
23997
23920
|
try {
|
|
23998
|
-
const p =
|
|
23921
|
+
const p = path39.join(dir, ".git");
|
|
23999
23922
|
return fs36.existsSync(p) && fs36.lstatSync(p).isDirectory();
|
|
24000
23923
|
} catch {
|
|
24001
23924
|
return false;
|
|
@@ -25432,7 +25355,7 @@ var LLMService = class {
|
|
|
25432
25355
|
// src/app/agent/utils/user_message_images.ts
|
|
25433
25356
|
import fs37 from "fs";
|
|
25434
25357
|
import os25 from "os";
|
|
25435
|
-
import
|
|
25358
|
+
import path40 from "path";
|
|
25436
25359
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
25437
25360
|
var IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp)$/i;
|
|
25438
25361
|
var MAX_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
@@ -25448,22 +25371,22 @@ var MIME = {
|
|
|
25448
25371
|
function expandUserPath(p) {
|
|
25449
25372
|
const t = p.trim();
|
|
25450
25373
|
if (t.startsWith("~")) {
|
|
25451
|
-
return
|
|
25374
|
+
return path40.join(os25.homedir(), t.slice(1).replace(/^\//, ""));
|
|
25452
25375
|
}
|
|
25453
25376
|
return t;
|
|
25454
25377
|
}
|
|
25455
25378
|
function isPathAllowed(absResolved, cwd2) {
|
|
25456
|
-
const resolved =
|
|
25457
|
-
const cwdR =
|
|
25458
|
-
const homeR =
|
|
25459
|
-
const tmpR =
|
|
25460
|
-
const underCwd = resolved === cwdR || resolved.startsWith(cwdR +
|
|
25461
|
-
const underHome = resolved === homeR || resolved.startsWith(homeR +
|
|
25462
|
-
const underTmp = resolved === tmpR || resolved.startsWith(tmpR +
|
|
25379
|
+
const resolved = path40.normalize(path40.resolve(absResolved));
|
|
25380
|
+
const cwdR = path40.normalize(path40.resolve(cwd2));
|
|
25381
|
+
const homeR = path40.normalize(path40.resolve(os25.homedir()));
|
|
25382
|
+
const tmpR = path40.normalize(path40.resolve(os25.tmpdir()));
|
|
25383
|
+
const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path40.sep);
|
|
25384
|
+
const underHome = resolved === homeR || resolved.startsWith(homeR + path40.sep);
|
|
25385
|
+
const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path40.sep);
|
|
25463
25386
|
return underCwd || underHome || underTmp;
|
|
25464
25387
|
}
|
|
25465
25388
|
function mimeFor(abs) {
|
|
25466
|
-
const ext =
|
|
25389
|
+
const ext = path40.extname(abs).toLowerCase();
|
|
25467
25390
|
return MIME[ext] || "application/octet-stream";
|
|
25468
25391
|
}
|
|
25469
25392
|
var IMAGE_EXT_SRC = String.raw`(?:png|jpe?g|gif|webp|bmp)`;
|
|
@@ -25507,7 +25430,7 @@ function collectImagePathStrings(raw) {
|
|
|
25507
25430
|
}
|
|
25508
25431
|
function resolveImagePath(candidate, cwd2) {
|
|
25509
25432
|
const expanded = expandUserPath(candidate);
|
|
25510
|
-
const abs =
|
|
25433
|
+
const abs = path40.isAbsolute(expanded) ? path40.normalize(expanded) : path40.normalize(path40.resolve(cwd2, expanded));
|
|
25511
25434
|
if (!isPathAllowed(abs, cwd2)) return null;
|
|
25512
25435
|
try {
|
|
25513
25436
|
if (!fs37.existsSync(abs) || !fs37.statSync(abs).isFile()) return null;
|
|
@@ -25530,7 +25453,7 @@ function trySingleLineFileUriOrBareImagePath(line, cwd2) {
|
|
|
25530
25453
|
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
25531
25454
|
s = s.slice(1, -1).trim();
|
|
25532
25455
|
}
|
|
25533
|
-
if (!IMAGE_EXT.test(
|
|
25456
|
+
if (!IMAGE_EXT.test(path40.extname(s))) return null;
|
|
25534
25457
|
const abs = resolveImagePath(s, cwd2);
|
|
25535
25458
|
if (!abs) return null;
|
|
25536
25459
|
try {
|
|
@@ -25633,7 +25556,7 @@ function buildUserMessageContent(raw, cwd2) {
|
|
|
25633
25556
|
init_sandbox_policy();
|
|
25634
25557
|
init_runtime_config();
|
|
25635
25558
|
init_permission_rules();
|
|
25636
|
-
import
|
|
25559
|
+
import path41 from "path";
|
|
25637
25560
|
var LOCAL_EDIT_TOOL_NAMES = /* @__PURE__ */ new Set(["edit_tool", "file_write", "notebook_edit"]);
|
|
25638
25561
|
function getToolPermissionLayer(metadata) {
|
|
25639
25562
|
if (metadata.riskLevel === "safe") return "read";
|
|
@@ -25648,11 +25571,11 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25648
25571
|
if (!filePath) {
|
|
25649
25572
|
return { allowed: false, reason: "No file path provided for permission check." };
|
|
25650
25573
|
}
|
|
25651
|
-
const resolvedPath =
|
|
25574
|
+
const resolvedPath = path41.resolve(filePath);
|
|
25652
25575
|
if (!isPathInsideWorkspace(resolvedPath, policy)) {
|
|
25653
25576
|
return { allowed: false, reason: `File path "${filePath}" is outside workspace root.` };
|
|
25654
25577
|
}
|
|
25655
|
-
const relativePath =
|
|
25578
|
+
const relativePath = path41.relative(policy.workspaceRoot, resolvedPath);
|
|
25656
25579
|
const toolPattern = `${toolName}(${relativePath})`;
|
|
25657
25580
|
const ruleDecision = permissionRulesEngine.checkPermission(toolPattern, { filepath: filePath });
|
|
25658
25581
|
if (ruleDecision === "deny") {
|
|
@@ -25661,7 +25584,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25661
25584
|
if (ruleDecision === "allow") {
|
|
25662
25585
|
return { allowed: true, reason: `File "${filePath}" allowed by permission rules.` };
|
|
25663
25586
|
}
|
|
25664
|
-
const dirPath =
|
|
25587
|
+
const dirPath = path41.dirname(relativePath);
|
|
25665
25588
|
const dirPattern = `${toolName}(${dirPath}/**)`;
|
|
25666
25589
|
const dirRuleDecision = permissionRulesEngine.checkPermission(dirPattern, { filepath: filePath });
|
|
25667
25590
|
if (dirRuleDecision === "allow") {
|
|
@@ -25879,10 +25802,10 @@ function effectiveToolAutoApprove(toolCall, sessionId, options) {
|
|
|
25879
25802
|
|
|
25880
25803
|
// src/app/agent/tools/CodingMemoryTool/CodingMemoryConsolidate.ts
|
|
25881
25804
|
import * as fs38 from "fs";
|
|
25882
|
-
import * as
|
|
25805
|
+
import * as path42 from "path";
|
|
25883
25806
|
import os26 from "os";
|
|
25884
25807
|
function memoryPath2() {
|
|
25885
|
-
return
|
|
25808
|
+
return path42.join(process.env.HOME || os26.homedir(), ".bluma", "coding_memory.json");
|
|
25886
25809
|
}
|
|
25887
25810
|
function normalizeNote2(note) {
|
|
25888
25811
|
return note.trim().toLowerCase().replace(/\s+/g, " ");
|
|
@@ -26444,16 +26367,16 @@ var BluMaToolRunner = class {
|
|
|
26444
26367
|
|
|
26445
26368
|
// src/app/agent/session_manager/session_archive.ts
|
|
26446
26369
|
init_bluma_app_dir();
|
|
26447
|
-
import
|
|
26370
|
+
import path43 from "path";
|
|
26448
26371
|
import { promises as fs39 } from "fs";
|
|
26449
26372
|
async function archivePrunedConversationMessages(sessionId, messages) {
|
|
26450
26373
|
if (!sessionId || messages.length === 0) {
|
|
26451
26374
|
return null;
|
|
26452
26375
|
}
|
|
26453
26376
|
const appDir = getPreferredAppDir();
|
|
26454
|
-
const dir =
|
|
26377
|
+
const dir = path43.join(appDir, "sessions", "archive", sessionId);
|
|
26455
26378
|
await fs39.mkdir(dir, { recursive: true });
|
|
26456
|
-
const archiveFile =
|
|
26379
|
+
const archiveFile = path43.join(dir, `${Date.now()}.jsonl`);
|
|
26457
26380
|
const lines = messages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
26458
26381
|
await fs39.appendFile(archiveFile, lines, "utf-8");
|
|
26459
26382
|
return archiveFile;
|
|
@@ -27207,7 +27130,7 @@ init_paths();
|
|
|
27207
27130
|
|
|
27208
27131
|
// src/app/agent/memory/memdir/memory_scan.ts
|
|
27209
27132
|
init_memoryTypes();
|
|
27210
|
-
import { readdir as readdir2, readFile as
|
|
27133
|
+
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
27211
27134
|
import { join as join12 } from "path";
|
|
27212
27135
|
var MAX_MEMORY_FILES = 200;
|
|
27213
27136
|
var FRONTMATTER_MAX_LINES = 30;
|
|
@@ -27249,7 +27172,7 @@ async function scanMemoryFiles(memoryDir, _signal) {
|
|
|
27249
27172
|
for (const relativePath of mdFiles) {
|
|
27250
27173
|
const filePath = join12(memoryDir, relativePath);
|
|
27251
27174
|
try {
|
|
27252
|
-
const raw = await
|
|
27175
|
+
const raw = await readFile4(filePath, "utf-8");
|
|
27253
27176
|
const head = raw.split("\n").slice(0, FRONTMATTER_MAX_LINES).join("\n");
|
|
27254
27177
|
const frontmatter = parseSimpleFrontmatter(head);
|
|
27255
27178
|
const st = await stat(filePath);
|
|
@@ -27316,7 +27239,7 @@ Update existing files instead of duplicating.` : "";
|
|
|
27316
27239
|
|
|
27317
27240
|
// src/app/agent/memory/memory_tool_policy.ts
|
|
27318
27241
|
init_paths();
|
|
27319
|
-
import
|
|
27242
|
+
import path44 from "path";
|
|
27320
27243
|
var MEMORY_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
27321
27244
|
"read_file_lines",
|
|
27322
27245
|
"grep_search",
|
|
@@ -27343,7 +27266,7 @@ function isReadOnlyShellCommand(command) {
|
|
|
27343
27266
|
return READ_ONLY_SHELL.test(trimmed);
|
|
27344
27267
|
}
|
|
27345
27268
|
function createAutoMemToolGate(memoryDir) {
|
|
27346
|
-
const memRoot = memoryDir.endsWith(
|
|
27269
|
+
const memRoot = memoryDir.endsWith(path44.sep) ? memoryDir : memoryDir + path44.sep;
|
|
27347
27270
|
return (toolName, args) => {
|
|
27348
27271
|
if (MEMORY_READ_TOOLS.has(toolName)) {
|
|
27349
27272
|
return { allowed: true };
|
|
@@ -27356,7 +27279,7 @@ function createAutoMemToolGate(memoryDir) {
|
|
|
27356
27279
|
}
|
|
27357
27280
|
if (MEMORY_WRITE_TOOLS.has(toolName)) {
|
|
27358
27281
|
const fp = extractFilePath(args);
|
|
27359
|
-
if (fp && isAutoMemPath(
|
|
27282
|
+
if (fp && isAutoMemPath(path44.resolve(fp))) {
|
|
27360
27283
|
return { allowed: true };
|
|
27361
27284
|
}
|
|
27362
27285
|
return { allowed: false, reason: `Writes must stay under ${memRoot}` };
|
|
@@ -27365,18 +27288,18 @@ function createAutoMemToolGate(memoryDir) {
|
|
|
27365
27288
|
};
|
|
27366
27289
|
}
|
|
27367
27290
|
function createSessionMemoryToolGate(sessionMemoryPath) {
|
|
27368
|
-
const resolvedTarget =
|
|
27291
|
+
const resolvedTarget = path44.resolve(sessionMemoryPath);
|
|
27369
27292
|
return (toolName, args) => {
|
|
27370
27293
|
if (toolName === "read_file_lines") {
|
|
27371
27294
|
const fp = extractFilePath(args);
|
|
27372
|
-
if (fp &&
|
|
27295
|
+
if (fp && path44.resolve(fp) === resolvedTarget) {
|
|
27373
27296
|
return { allowed: true };
|
|
27374
27297
|
}
|
|
27375
27298
|
return { allowed: false, reason: "Session memory subagent may only read the session summary file" };
|
|
27376
27299
|
}
|
|
27377
27300
|
if (toolName === "edit_tool") {
|
|
27378
27301
|
const fp = extractFilePath(args);
|
|
27379
|
-
if (fp &&
|
|
27302
|
+
if (fp && path44.resolve(fp) === resolvedTarget) {
|
|
27380
27303
|
return { allowed: true };
|
|
27381
27304
|
}
|
|
27382
27305
|
return { allowed: false, reason: "Session memory subagent may only edit the session summary file" };
|
|
@@ -27403,7 +27326,7 @@ function hasAutoMemWritesSinceHistory(history, sinceIndex) {
|
|
|
27403
27326
|
continue;
|
|
27404
27327
|
}
|
|
27405
27328
|
const fp = extractFilePath(args);
|
|
27406
|
-
if (fp && isAutoMemPath(
|
|
27329
|
+
if (fp && isAutoMemPath(path44.resolve(fp))) {
|
|
27407
27330
|
return true;
|
|
27408
27331
|
}
|
|
27409
27332
|
}
|
|
@@ -27622,7 +27545,7 @@ function scheduleExtractMemories(deps) {
|
|
|
27622
27545
|
|
|
27623
27546
|
// src/app/agent/memory/session_memory_update.ts
|
|
27624
27547
|
init_session_memory_paths();
|
|
27625
|
-
import { readFile as
|
|
27548
|
+
import { readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
27626
27549
|
|
|
27627
27550
|
// src/app/agent/memory/session_memory_prompts.ts
|
|
27628
27551
|
init_session_memory_paths();
|
|
@@ -27734,9 +27657,9 @@ async function runSessionMemoryUpdate(deps) {
|
|
|
27734
27657
|
const memoryPath3 = getSessionMemoryPath(sessionId);
|
|
27735
27658
|
let currentMemory = "";
|
|
27736
27659
|
try {
|
|
27737
|
-
currentMemory = await
|
|
27660
|
+
currentMemory = await readFile5(memoryPath3, "utf-8");
|
|
27738
27661
|
} catch {
|
|
27739
|
-
await
|
|
27662
|
+
await writeFile3(memoryPath3, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
|
|
27740
27663
|
`, "utf-8");
|
|
27741
27664
|
currentMemory = DEFAULT_SESSION_MEMORY_TEMPLATE;
|
|
27742
27665
|
}
|
|
@@ -27871,7 +27794,7 @@ var BluMaAgent = class {
|
|
|
27871
27794
|
if (!this.sessionFile) return;
|
|
27872
27795
|
try {
|
|
27873
27796
|
const sessionData = {
|
|
27874
|
-
session_id:
|
|
27797
|
+
session_id: path45.basename(this.sessionFile, ".json"),
|
|
27875
27798
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27876
27799
|
conversation_history: this.history,
|
|
27877
27800
|
last_updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -28083,7 +28006,7 @@ var BluMaAgent = class {
|
|
|
28083
28006
|
|
|
28084
28007
|
${editData.error.display}`;
|
|
28085
28008
|
}
|
|
28086
|
-
const filename =
|
|
28009
|
+
const filename = path45.basename(toolArgs.file_path);
|
|
28087
28010
|
return createDiff(filename, editData.currentContent || "", editData.newContent);
|
|
28088
28011
|
} catch (e) {
|
|
28089
28012
|
return `An unexpected error occurred while generating the edit preview: ${e.message}`;
|
|
@@ -28820,14 +28743,14 @@ async function fullCompact(messages, targetTokens, summarizer, llmClient) {
|
|
|
28820
28743
|
// src/app/agent/core/memory/session_memory.ts
|
|
28821
28744
|
import fs41 from "fs";
|
|
28822
28745
|
import os29 from "os";
|
|
28823
|
-
import
|
|
28746
|
+
import path46 from "path";
|
|
28824
28747
|
import { v4 as uuidv49 } from "uuid";
|
|
28825
28748
|
var SessionMemoryExtractor = class {
|
|
28826
28749
|
llmClient;
|
|
28827
28750
|
memoryFile;
|
|
28828
28751
|
constructor(options = {}) {
|
|
28829
28752
|
this.llmClient = options.llmClient;
|
|
28830
|
-
this.memoryFile = options.memoryFile ||
|
|
28753
|
+
this.memoryFile = options.memoryFile || path46.join(os29.homedir(), ".bluma", "session_memory.json");
|
|
28831
28754
|
}
|
|
28832
28755
|
/**
|
|
28833
28756
|
* Extract memories from conversation using LLM
|
|
@@ -29436,14 +29359,14 @@ var RouteManager = class {
|
|
|
29436
29359
|
this.subAgents = subAgents;
|
|
29437
29360
|
this.core = core;
|
|
29438
29361
|
}
|
|
29439
|
-
registerRoute(
|
|
29440
|
-
this.routeHandlers.set(
|
|
29362
|
+
registerRoute(path59, handler) {
|
|
29363
|
+
this.routeHandlers.set(path59, handler);
|
|
29441
29364
|
}
|
|
29442
29365
|
async handleRoute(payload) {
|
|
29443
29366
|
const inputText = String(payload.content || "").trim();
|
|
29444
29367
|
const { userContext, options } = payload;
|
|
29445
|
-
for (const [
|
|
29446
|
-
if (inputText ===
|
|
29368
|
+
for (const [path59, handler] of this.routeHandlers) {
|
|
29369
|
+
if (inputText === path59 || inputText.startsWith(`${path59} `)) {
|
|
29447
29370
|
return handler({ content: inputText, userContext });
|
|
29448
29371
|
}
|
|
29449
29372
|
}
|
|
@@ -29452,13 +29375,13 @@ var RouteManager = class {
|
|
|
29452
29375
|
};
|
|
29453
29376
|
|
|
29454
29377
|
// src/app/agent/runtime/plugin_runtime.ts
|
|
29455
|
-
import
|
|
29378
|
+
import path47 from "path";
|
|
29456
29379
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
29457
29380
|
async function loadPluginsAtStartup() {
|
|
29458
29381
|
for (const p of listPlugins()) {
|
|
29459
29382
|
const entry = p.manifest.entry?.trim();
|
|
29460
29383
|
if (!entry) continue;
|
|
29461
|
-
const abs =
|
|
29384
|
+
const abs = path47.resolve(p.root, entry);
|
|
29462
29385
|
try {
|
|
29463
29386
|
const href = pathToFileURL2(abs).href;
|
|
29464
29387
|
const mod = await import(href);
|
|
@@ -29479,7 +29402,7 @@ async function loadPluginsAtStartup() {
|
|
|
29479
29402
|
}
|
|
29480
29403
|
|
|
29481
29404
|
// src/app/agent/agent.ts
|
|
29482
|
-
var globalEnvPath =
|
|
29405
|
+
var globalEnvPath = path48.join(os30.homedir(), ".bluma", ".env");
|
|
29483
29406
|
dotenv.config({ path: globalEnvPath });
|
|
29484
29407
|
var Agent = class {
|
|
29485
29408
|
sessionId;
|
|
@@ -31335,10 +31258,10 @@ function resolveToolPayload(result) {
|
|
|
31335
31258
|
|
|
31336
31259
|
// src/app/ui/components/FilePathLink.tsx
|
|
31337
31260
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
31338
|
-
import
|
|
31261
|
+
import path50 from "node:path";
|
|
31339
31262
|
|
|
31340
31263
|
// src/app/ui/utils/pathDisplay.ts
|
|
31341
|
-
import
|
|
31264
|
+
import path49 from "node:path";
|
|
31342
31265
|
import os31 from "node:os";
|
|
31343
31266
|
function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
31344
31267
|
let s = String(pathInput ?? "").trim();
|
|
@@ -31346,17 +31269,17 @@ function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
|
31346
31269
|
s = s.replace(/[/\\]+$/, "");
|
|
31347
31270
|
}
|
|
31348
31271
|
if (!s) return "";
|
|
31349
|
-
const abs =
|
|
31350
|
-
const resolvedCwd =
|
|
31351
|
-
const rel =
|
|
31352
|
-
if (rel === "" || !rel.startsWith("..") && !
|
|
31272
|
+
const abs = path49.isAbsolute(s) ? path49.normalize(s) : path49.resolve(cwd2, s);
|
|
31273
|
+
const resolvedCwd = path49.resolve(cwd2);
|
|
31274
|
+
const rel = path49.relative(resolvedCwd, abs);
|
|
31275
|
+
if (rel === "" || !rel.startsWith("..") && !path49.isAbsolute(rel)) {
|
|
31353
31276
|
return rel === "" ? "." : rel;
|
|
31354
31277
|
}
|
|
31355
|
-
const home =
|
|
31356
|
-
if (abs === home || abs.startsWith(home +
|
|
31278
|
+
const home = path49.normalize(os31.homedir());
|
|
31279
|
+
if (abs === home || abs.startsWith(home + path49.sep)) {
|
|
31357
31280
|
return "~" + abs.slice(home.length);
|
|
31358
31281
|
}
|
|
31359
|
-
return
|
|
31282
|
+
return path49.basename(abs);
|
|
31360
31283
|
}
|
|
31361
31284
|
|
|
31362
31285
|
// src/app/ui/components/FilePathLink.tsx
|
|
@@ -31366,7 +31289,7 @@ function FilePathLink({ filePath, children, cwd: cwd2 = process.cwd(), color })
|
|
|
31366
31289
|
if (!raw) {
|
|
31367
31290
|
return null;
|
|
31368
31291
|
}
|
|
31369
|
-
const abs =
|
|
31292
|
+
const abs = path50.isAbsolute(raw) ? path50.normalize(raw) : path50.resolve(cwd2, raw);
|
|
31370
31293
|
const href = pathToFileURL3(abs).href;
|
|
31371
31294
|
const label = formatPathForDisplay(abs, cwd2);
|
|
31372
31295
|
const text = typeof children === "string" ? children : label;
|
|
@@ -34001,13 +33924,13 @@ function EditToolDiffPanel({
|
|
|
34001
33924
|
newString,
|
|
34002
33925
|
replaceAll = false
|
|
34003
33926
|
}) {
|
|
34004
|
-
const
|
|
33927
|
+
const path59 = filePath.trim() || "unknown file";
|
|
34005
33928
|
const hasPreviewArgs = oldString !== void 0 && newString !== void 0;
|
|
34006
33929
|
const hasDiffText = diffText && diffText.trim().length > 0;
|
|
34007
33930
|
return /* @__PURE__ */ jsx43(Box_default, { flexDirection: "column", children: hasPreviewArgs ? /* @__PURE__ */ jsx43(Box_default, { marginTop: 0, children: /* @__PURE__ */ jsx43(
|
|
34008
33931
|
FileEditToolDiff,
|
|
34009
33932
|
{
|
|
34010
|
-
filePath:
|
|
33933
|
+
filePath: path59,
|
|
34011
33934
|
oldString,
|
|
34012
33935
|
newString,
|
|
34013
33936
|
replaceAll,
|
|
@@ -34045,7 +33968,7 @@ function renderToolUseMessage12({ args }) {
|
|
|
34045
33968
|
return /* @__PURE__ */ jsx44(Text, { color: BLUMA_TERMINAL.blue, children: p });
|
|
34046
33969
|
}
|
|
34047
33970
|
function renderToolHeader12({ args }) {
|
|
34048
|
-
const
|
|
33971
|
+
const path59 = args?.file_path ?? ".";
|
|
34049
33972
|
const oldText = typeof args?.old_string === "string" ? args.old_string : "";
|
|
34050
33973
|
const newText = typeof args?.new_string === "string" ? args.new_string : "";
|
|
34051
33974
|
const counts = countLineDiff(oldText, newText);
|
|
@@ -34055,7 +33978,7 @@ function renderToolHeader12({ args }) {
|
|
|
34055
33978
|
action,
|
|
34056
33979
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
34057
33980
|
" ",
|
|
34058
|
-
/* @__PURE__ */ jsx44(FilePathLink, { filePath:
|
|
33981
|
+
/* @__PURE__ */ jsx44(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
|
|
34059
33982
|
] })
|
|
34060
33983
|
] }),
|
|
34061
33984
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
@@ -34447,11 +34370,11 @@ function userFacingName13() {
|
|
|
34447
34370
|
}
|
|
34448
34371
|
function renderToolUseMessage14({ args }) {
|
|
34449
34372
|
const q = args?.query ? `"${args.query}"` : "...";
|
|
34450
|
-
const
|
|
34373
|
+
const path59 = args?.path || ".";
|
|
34451
34374
|
return /* @__PURE__ */ jsxs30(Box_default, { flexDirection: "row", flexWrap: "wrap", alignItems: "flex-end", children: [
|
|
34452
34375
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.blue, children: q }),
|
|
34453
34376
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.dim, children: " " }),
|
|
34454
|
-
/* @__PURE__ */ jsx47(FilePathLink, { filePath:
|
|
34377
|
+
/* @__PURE__ */ jsx47(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
|
|
34455
34378
|
] });
|
|
34456
34379
|
}
|
|
34457
34380
|
function renderToolHeader14({ args }) {
|
|
@@ -37931,7 +37854,7 @@ import {
|
|
|
37931
37854
|
// src/app/ui/hooks/useAtCompletion.ts
|
|
37932
37855
|
import { useEffect as useEffect11, useRef as useRef4, useState as useState13 } from "react";
|
|
37933
37856
|
import fs44 from "fs";
|
|
37934
|
-
import
|
|
37857
|
+
import path51 from "path";
|
|
37935
37858
|
var MAX_RESULTS3 = 50;
|
|
37936
37859
|
var DEFAULT_RECURSIVE_DEPTH = 2;
|
|
37937
37860
|
function listPathSuggestions(baseDir, pattern) {
|
|
@@ -37939,7 +37862,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37939
37862
|
const patternEndsWithSlash = raw.endsWith("/");
|
|
37940
37863
|
const relDir = raw.replace(/^\/+|\/+$/g, "");
|
|
37941
37864
|
const filterPrefix = patternEndsWithSlash ? "" : relDir.split("/").slice(-1)[0] || "";
|
|
37942
|
-
const listDir =
|
|
37865
|
+
const listDir = path51.resolve(baseDir, relDir || ".");
|
|
37943
37866
|
const results = [];
|
|
37944
37867
|
const IGNORED_DIRS = ["node_modules", ".git", ".venv", "dist", "build"];
|
|
37945
37868
|
const IGNORED_EXTS = [".pyc", ".class", ".o", ".map", ".log", ".tmp"];
|
|
@@ -37956,7 +37879,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37956
37879
|
}
|
|
37957
37880
|
function pushEntry(entryPath, label, isDir) {
|
|
37958
37881
|
if (results.length >= MAX_RESULTS3) return;
|
|
37959
|
-
const clean = label.split(
|
|
37882
|
+
const clean = label.split(path51.sep).join("/").replace(/[]+/g, "");
|
|
37960
37883
|
results.push({ label: clean + (isDir ? "/" : ""), fullPath: entryPath, isDir });
|
|
37961
37884
|
}
|
|
37962
37885
|
try {
|
|
@@ -37968,8 +37891,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37968
37891
|
const entries = fs44.readdirSync(node.dir, { withFileTypes: true });
|
|
37969
37892
|
for (const entry of entries) {
|
|
37970
37893
|
if (isIgnoredName(entry.name)) continue;
|
|
37971
|
-
const entryAbs =
|
|
37972
|
-
const entryRel = node.rel ?
|
|
37894
|
+
const entryAbs = path51.join(node.dir, entry.name);
|
|
37895
|
+
const entryRel = node.rel ? path51.posix.join(node.rel, entry.name) : entry.name;
|
|
37973
37896
|
if (entryRel.split("/").includes("node_modules")) continue;
|
|
37974
37897
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
37975
37898
|
pushEntry(entryAbs, entryRel, entry.isDirectory());
|
|
@@ -37987,8 +37910,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37987
37910
|
if (filterPrefix && !entry.name.startsWith(filterPrefix)) continue;
|
|
37988
37911
|
if (isIgnoredName(entry.name)) continue;
|
|
37989
37912
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
37990
|
-
const entryAbs =
|
|
37991
|
-
const label = relDir ?
|
|
37913
|
+
const entryAbs = path51.join(listDir, entry.name);
|
|
37914
|
+
const label = relDir ? path51.posix.join(relDir, entry.name) : entry.name;
|
|
37992
37915
|
pushEntry(entryAbs, label, entry.isDirectory());
|
|
37993
37916
|
if (results.length >= MAX_RESULTS3) break;
|
|
37994
37917
|
}
|
|
@@ -38191,7 +38114,7 @@ var SlashSubmenuInline = memo15(SlashSubmenuInlineComponent);
|
|
|
38191
38114
|
// src/app/ui/utils/clipboardImage.ts
|
|
38192
38115
|
import fs45 from "fs";
|
|
38193
38116
|
import os32 from "os";
|
|
38194
|
-
import
|
|
38117
|
+
import path52 from "path";
|
|
38195
38118
|
import { spawn as spawn5, execFile as execFileCb, execSync as execSync4 } from "child_process";
|
|
38196
38119
|
import { promisify as promisify2 } from "util";
|
|
38197
38120
|
|
|
@@ -38320,8 +38243,8 @@ function commandOnPath(cmd) {
|
|
|
38320
38243
|
function unixClipboardHelperDirs() {
|
|
38321
38244
|
const h = os32.homedir();
|
|
38322
38245
|
return [
|
|
38323
|
-
|
|
38324
|
-
|
|
38246
|
+
path52.join(h, ".local", "bin"),
|
|
38247
|
+
path52.join(h, "bin"),
|
|
38325
38248
|
"/usr/bin",
|
|
38326
38249
|
"/usr/local/bin",
|
|
38327
38250
|
"/bin",
|
|
@@ -38339,7 +38262,7 @@ function resolveHelperBinary(cmd) {
|
|
|
38339
38262
|
return cmd;
|
|
38340
38263
|
}
|
|
38341
38264
|
for (const dir of unixClipboardHelperDirs()) {
|
|
38342
|
-
const full =
|
|
38265
|
+
const full = path52.join(dir, cmd);
|
|
38343
38266
|
try {
|
|
38344
38267
|
fs45.accessSync(full, fs45.constants.X_OK);
|
|
38345
38268
|
return full;
|
|
@@ -38347,7 +38270,7 @@ function resolveHelperBinary(cmd) {
|
|
|
38347
38270
|
}
|
|
38348
38271
|
}
|
|
38349
38272
|
for (const dir of unixClipboardHelperDirs()) {
|
|
38350
|
-
const full =
|
|
38273
|
+
const full = path52.join(dir, cmd);
|
|
38351
38274
|
if (fs45.existsSync(full)) {
|
|
38352
38275
|
return full;
|
|
38353
38276
|
}
|
|
@@ -38389,7 +38312,7 @@ function writeBufferIfImage(baseDir, buf) {
|
|
|
38389
38312
|
if (!ext) {
|
|
38390
38313
|
return null;
|
|
38391
38314
|
}
|
|
38392
|
-
const out =
|
|
38315
|
+
const out = path52.join(
|
|
38393
38316
|
baseDir,
|
|
38394
38317
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
38395
38318
|
);
|
|
@@ -38428,9 +38351,9 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
38428
38351
|
if (st.size < 80 || st.size > CLIPBOARD_MAX_BYTES) {
|
|
38429
38352
|
continue;
|
|
38430
38353
|
}
|
|
38431
|
-
const ext =
|
|
38354
|
+
const ext = path52.extname(src).toLowerCase();
|
|
38432
38355
|
const safeExt = ext && /^\.(png|jpe?g|gif|webp)$/i.test(ext) ? ext : ".png";
|
|
38433
|
-
const out =
|
|
38356
|
+
const out = path52.join(
|
|
38434
38357
|
baseDir,
|
|
38435
38358
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${safeExt}`
|
|
38436
38359
|
);
|
|
@@ -38448,7 +38371,7 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
38448
38371
|
return null;
|
|
38449
38372
|
}
|
|
38450
38373
|
async function tryWindowsPowerShell(outFile) {
|
|
38451
|
-
const ps = process.env.SystemRoot != null ?
|
|
38374
|
+
const ps = process.env.SystemRoot != null ? path52.join(
|
|
38452
38375
|
process.env.SystemRoot,
|
|
38453
38376
|
"System32",
|
|
38454
38377
|
"WindowsPowerShell",
|
|
@@ -38549,8 +38472,8 @@ function parseClipboardTextAsImagePath(raw) {
|
|
|
38549
38472
|
s = s.slice(1, -1);
|
|
38550
38473
|
}
|
|
38551
38474
|
s = s.trim();
|
|
38552
|
-
if (!CLIPBOARD_PATH_IMAGE_EXT.test(
|
|
38553
|
-
const abs =
|
|
38475
|
+
if (!CLIPBOARD_PATH_IMAGE_EXT.test(path52.extname(s))) return null;
|
|
38476
|
+
const abs = path52.isAbsolute(s) ? path52.normalize(s) : path52.resolve(process.cwd(), s);
|
|
38554
38477
|
return abs;
|
|
38555
38478
|
}
|
|
38556
38479
|
async function tryClipboardTextAsImageFile(baseDir) {
|
|
@@ -38570,8 +38493,8 @@ async function tryClipboardTextAsImageFile(baseDir) {
|
|
|
38570
38493
|
} catch {
|
|
38571
38494
|
return null;
|
|
38572
38495
|
}
|
|
38573
|
-
const ext =
|
|
38574
|
-
const out =
|
|
38496
|
+
const ext = path52.extname(abs).toLowerCase();
|
|
38497
|
+
const out = path52.join(
|
|
38575
38498
|
baseDir,
|
|
38576
38499
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
38577
38500
|
);
|
|
@@ -38586,7 +38509,7 @@ async function tryLinuxShellPipelineSave(baseDir) {
|
|
|
38586
38509
|
if (process.platform !== "linux" && process.platform !== "freebsd") {
|
|
38587
38510
|
return null;
|
|
38588
38511
|
}
|
|
38589
|
-
const outPath =
|
|
38512
|
+
const outPath = path52.join(
|
|
38590
38513
|
baseDir,
|
|
38591
38514
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
38592
38515
|
);
|
|
@@ -38644,7 +38567,7 @@ async function tryNativeClipboardImage() {
|
|
|
38644
38567
|
return null;
|
|
38645
38568
|
}
|
|
38646
38569
|
async function readClipboardImageToTempFile() {
|
|
38647
|
-
const baseDir =
|
|
38570
|
+
const baseDir = path52.join(os32.homedir(), ".cache", "bluma", "clipboard");
|
|
38648
38571
|
fs45.mkdirSync(baseDir, { recursive: true });
|
|
38649
38572
|
const nativeResult = await tryNativeClipboardImage();
|
|
38650
38573
|
if (nativeResult) {
|
|
@@ -38663,7 +38586,7 @@ async function readClipboardImageToTempFile() {
|
|
|
38663
38586
|
}
|
|
38664
38587
|
}
|
|
38665
38588
|
if (process.platform === "win32") {
|
|
38666
|
-
const outFile =
|
|
38589
|
+
const outFile = path52.join(
|
|
38667
38590
|
baseDir,
|
|
38668
38591
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.png`
|
|
38669
38592
|
);
|
|
@@ -41039,7 +40962,7 @@ var renderSettingsEditUsage = () => {
|
|
|
41039
40962
|
|
|
41040
40963
|
// src/app/agent/core/thread/thread_store.ts
|
|
41041
40964
|
init_bluma_app_dir();
|
|
41042
|
-
import
|
|
40965
|
+
import path53 from "path";
|
|
41043
40966
|
import { promises as fs47 } from "fs";
|
|
41044
40967
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
41045
40968
|
var INDEX_VERSION = 1;
|
|
@@ -41065,9 +40988,9 @@ var ThreadStore = class {
|
|
|
41065
40988
|
packageVersion;
|
|
41066
40989
|
constructor() {
|
|
41067
40990
|
const appDir = getPreferredAppDir();
|
|
41068
|
-
this.threadsDir =
|
|
41069
|
-
this.archiveDir =
|
|
41070
|
-
this.indexPath =
|
|
40991
|
+
this.threadsDir = path53.join(appDir, "threads");
|
|
40992
|
+
this.archiveDir = path53.join(this.threadsDir, "archive");
|
|
40993
|
+
this.indexPath = path53.join(this.threadsDir, "index.json");
|
|
41071
40994
|
this.packageVersion = process.env.npm_package_version || "0.0.0";
|
|
41072
40995
|
}
|
|
41073
40996
|
// ==================== Inicialização ====================
|
|
@@ -41189,7 +41112,7 @@ var ThreadStore = class {
|
|
|
41189
41112
|
messages: params.initialMessages || []
|
|
41190
41113
|
};
|
|
41191
41114
|
const historyPath = this.buildDatedThreadHistoryPath(threadId);
|
|
41192
|
-
await fs47.mkdir(
|
|
41115
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
|
|
41193
41116
|
await this.saveHistoryAtPath(historyPath, history);
|
|
41194
41117
|
const index = await this.loadIndex();
|
|
41195
41118
|
index.threads.unshift({
|
|
@@ -41244,7 +41167,7 @@ var ThreadStore = class {
|
|
|
41244
41167
|
compressedSliceCount: source.history.compressedSliceCount
|
|
41245
41168
|
};
|
|
41246
41169
|
const historyPath = this.buildDatedThreadHistoryPath(newThreadId);
|
|
41247
|
-
await fs47.mkdir(
|
|
41170
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
|
|
41248
41171
|
await this.saveHistoryAtPath(historyPath, history);
|
|
41249
41172
|
const index = await this.loadIndex();
|
|
41250
41173
|
index.threads.unshift({
|
|
@@ -41317,7 +41240,7 @@ var ThreadStore = class {
|
|
|
41317
41240
|
const entry = index.threads[entryIndex];
|
|
41318
41241
|
if (entry.status === "archived") return true;
|
|
41319
41242
|
const oldPath = entry.historyPath || this.getLegacyHistoryPath(threadId);
|
|
41320
|
-
const newPath =
|
|
41243
|
+
const newPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
|
|
41321
41244
|
try {
|
|
41322
41245
|
await fs47.rename(oldPath, newPath);
|
|
41323
41246
|
} catch (e) {
|
|
@@ -41340,9 +41263,9 @@ var ThreadStore = class {
|
|
|
41340
41263
|
if (entryIndex === -1) return false;
|
|
41341
41264
|
const entry = index.threads[entryIndex];
|
|
41342
41265
|
if (entry.status === "active") return true;
|
|
41343
|
-
const oldPath =
|
|
41266
|
+
const oldPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
|
|
41344
41267
|
const newPath = this.buildDatedThreadHistoryPath(threadId);
|
|
41345
|
-
await fs47.mkdir(
|
|
41268
|
+
await fs47.mkdir(path53.dirname(newPath), { recursive: true });
|
|
41346
41269
|
try {
|
|
41347
41270
|
await fs47.rename(oldPath, newPath);
|
|
41348
41271
|
} catch (e) {
|
|
@@ -41375,14 +41298,14 @@ var ThreadStore = class {
|
|
|
41375
41298
|
}
|
|
41376
41299
|
// ==================== Histórico ====================
|
|
41377
41300
|
getLegacyHistoryPath(threadId) {
|
|
41378
|
-
return
|
|
41301
|
+
return path53.join(this.threadsDir, `${threadId}.jsonl`);
|
|
41379
41302
|
}
|
|
41380
41303
|
/** ~/.bluma/threads/YYYY/MM/DD/<threadId>.jsonl (data local de criação). */
|
|
41381
41304
|
buildDatedThreadHistoryPath(threadId, at = /* @__PURE__ */ new Date()) {
|
|
41382
41305
|
const y = String(at.getFullYear());
|
|
41383
41306
|
const mo = String(at.getMonth() + 1).padStart(2, "0");
|
|
41384
41307
|
const d = String(at.getDate()).padStart(2, "0");
|
|
41385
|
-
return
|
|
41308
|
+
return path53.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
|
|
41386
41309
|
}
|
|
41387
41310
|
async resolveHistoryPath(threadId) {
|
|
41388
41311
|
const index = await this.loadIndex();
|
|
@@ -41413,7 +41336,7 @@ var ThreadStore = class {
|
|
|
41413
41336
|
for (const msg of history.messages) {
|
|
41414
41337
|
lines.push(JSON.stringify({ type: "message", ...msg }));
|
|
41415
41338
|
}
|
|
41416
|
-
await fs47.mkdir(
|
|
41339
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true }).catch(() => {
|
|
41417
41340
|
});
|
|
41418
41341
|
await fs47.writeFile(historyPath, lines.join("\n") + "\n", "utf-8");
|
|
41419
41342
|
}
|
|
@@ -43909,13 +43832,13 @@ import latestVersion from "latest-version";
|
|
|
43909
43832
|
import semverGt from "semver/functions/gt.js";
|
|
43910
43833
|
import semverValid from "semver/functions/valid.js";
|
|
43911
43834
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
43912
|
-
import
|
|
43835
|
+
import path55 from "path";
|
|
43913
43836
|
import fs49 from "fs";
|
|
43914
43837
|
var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
|
|
43915
43838
|
function findBlumaPackageJson(startDir) {
|
|
43916
43839
|
let dir = startDir;
|
|
43917
43840
|
for (let i = 0; i < 12; i++) {
|
|
43918
|
-
const candidate =
|
|
43841
|
+
const candidate = path55.join(dir, "package.json");
|
|
43919
43842
|
if (fs49.existsSync(candidate)) {
|
|
43920
43843
|
try {
|
|
43921
43844
|
const raw = fs49.readFileSync(candidate, "utf8");
|
|
@@ -43926,7 +43849,7 @@ function findBlumaPackageJson(startDir) {
|
|
|
43926
43849
|
} catch {
|
|
43927
43850
|
}
|
|
43928
43851
|
}
|
|
43929
|
-
const parent =
|
|
43852
|
+
const parent = path55.dirname(dir);
|
|
43930
43853
|
if (parent === dir) break;
|
|
43931
43854
|
dir = parent;
|
|
43932
43855
|
}
|
|
@@ -43935,13 +43858,13 @@ function findBlumaPackageJson(startDir) {
|
|
|
43935
43858
|
function resolveInstalledBlumaPackage() {
|
|
43936
43859
|
const tried = /* @__PURE__ */ new Set();
|
|
43937
43860
|
const tryFrom = (dir) => {
|
|
43938
|
-
const abs =
|
|
43861
|
+
const abs = path55.resolve(dir);
|
|
43939
43862
|
if (tried.has(abs)) return null;
|
|
43940
43863
|
tried.add(abs);
|
|
43941
43864
|
return findBlumaPackageJson(abs);
|
|
43942
43865
|
};
|
|
43943
43866
|
try {
|
|
43944
|
-
const fromBundle = tryFrom(
|
|
43867
|
+
const fromBundle = tryFrom(path55.dirname(fileURLToPath7(import.meta.url)));
|
|
43945
43868
|
if (fromBundle) return fromBundle;
|
|
43946
43869
|
} catch {
|
|
43947
43870
|
}
|
|
@@ -43949,12 +43872,12 @@ function resolveInstalledBlumaPackage() {
|
|
|
43949
43872
|
if (argv1 && !argv1.startsWith("-")) {
|
|
43950
43873
|
try {
|
|
43951
43874
|
let resolved = argv1;
|
|
43952
|
-
if (
|
|
43875
|
+
if (path55.isAbsolute(argv1) && fs49.existsSync(argv1)) {
|
|
43953
43876
|
resolved = fs49.realpathSync(argv1);
|
|
43954
43877
|
} else {
|
|
43955
|
-
resolved =
|
|
43878
|
+
resolved = path55.resolve(process.cwd(), argv1);
|
|
43956
43879
|
}
|
|
43957
|
-
const fromArgv = tryFrom(
|
|
43880
|
+
const fromArgv = tryFrom(path55.dirname(resolved));
|
|
43958
43881
|
if (fromArgv) return fromArgv;
|
|
43959
43882
|
} catch {
|
|
43960
43883
|
}
|
|
@@ -44774,9 +44697,9 @@ function usePlanMode() {
|
|
|
44774
44697
|
// src/app/hooks/useAgentMode.ts
|
|
44775
44698
|
import { useState as useState22, useEffect as useEffect21, useCallback as useCallback9 } from "react";
|
|
44776
44699
|
import * as fs50 from "fs";
|
|
44777
|
-
import * as
|
|
44700
|
+
import * as path56 from "path";
|
|
44778
44701
|
import { homedir as homedir4 } from "os";
|
|
44779
|
-
var SETTINGS_PATH =
|
|
44702
|
+
var SETTINGS_PATH = path56.join(homedir4(), ".bluma", "settings.json");
|
|
44780
44703
|
function readAgentModeFromFile() {
|
|
44781
44704
|
try {
|
|
44782
44705
|
if (!fs50.existsSync(SETTINGS_PATH)) {
|
|
@@ -44802,7 +44725,7 @@ function useAgentMode() {
|
|
|
44802
44725
|
const updateAgentMode = useCallback9((mode) => {
|
|
44803
44726
|
try {
|
|
44804
44727
|
if (!fs50.existsSync(SETTINGS_PATH)) {
|
|
44805
|
-
fs50.mkdirSync(
|
|
44728
|
+
fs50.mkdirSync(path56.dirname(SETTINGS_PATH), { recursive: true });
|
|
44806
44729
|
}
|
|
44807
44730
|
let settings = {};
|
|
44808
44731
|
if (fs50.existsSync(SETTINGS_PATH)) {
|
|
@@ -46074,10 +45997,10 @@ import { memo as memo26, useCallback as useCallback11, useEffect as useEffect23,
|
|
|
46074
45997
|
|
|
46075
45998
|
// src/app/agent/session_manager/session_resume_browser.ts
|
|
46076
45999
|
init_bluma_app_dir();
|
|
46077
|
-
import
|
|
46000
|
+
import path57 from "path";
|
|
46078
46001
|
import { promises as fs51 } from "fs";
|
|
46079
46002
|
function getSessionsRoot() {
|
|
46080
|
-
return
|
|
46003
|
+
return path57.join(getPreferredAppDir(), "sessions");
|
|
46081
46004
|
}
|
|
46082
46005
|
function normalizeSessionsCwd(cwd2) {
|
|
46083
46006
|
return cwd2.replace(/\\/g, "/").split("/").filter((p) => p && p !== "." && p !== "..").join("/");
|
|
@@ -46128,7 +46051,7 @@ function compareDirNames(a, b) {
|
|
|
46128
46051
|
async function listSessionBrowserEntries(cwdRel) {
|
|
46129
46052
|
const cwd2 = normalizeSessionsCwd(cwdRel);
|
|
46130
46053
|
const root = getSessionsRoot();
|
|
46131
|
-
const absDir = cwd2 ?
|
|
46054
|
+
const absDir = cwd2 ? path57.join(root, ...cwd2.split("/")) : root;
|
|
46132
46055
|
const out = [];
|
|
46133
46056
|
if (cwd2) {
|
|
46134
46057
|
out.push({ kind: "up", label: ".." });
|
|
@@ -46145,7 +46068,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
46145
46068
|
for (const e of dirents) {
|
|
46146
46069
|
const name = String(e.name);
|
|
46147
46070
|
if (name.startsWith(".")) continue;
|
|
46148
|
-
const full =
|
|
46071
|
+
const full = path57.join(absDir, name);
|
|
46149
46072
|
if (e.isDirectory()) {
|
|
46150
46073
|
dirNames.push(name);
|
|
46151
46074
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -46155,7 +46078,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
46155
46078
|
dirNames.sort(compareDirNames);
|
|
46156
46079
|
const sessions = [];
|
|
46157
46080
|
for (const { name, full } of sessionFiles) {
|
|
46158
|
-
const sessionId =
|
|
46081
|
+
const sessionId = path57.basename(name, ".json");
|
|
46159
46082
|
sessions.push(await sessionEntryFromFile(full, sessionId));
|
|
46160
46083
|
}
|
|
46161
46084
|
sessions.sort((a, b) => {
|
|
@@ -46763,8 +46686,8 @@ async function runAgentMode() {
|
|
|
46763
46686
|
}
|
|
46764
46687
|
function readCliPackageVersion() {
|
|
46765
46688
|
try {
|
|
46766
|
-
const base =
|
|
46767
|
-
const pkgPath =
|
|
46689
|
+
const base = path58.dirname(fileURLToPath8(import.meta.url));
|
|
46690
|
+
const pkgPath = path58.join(base, "..", "package.json");
|
|
46768
46691
|
const j = JSON.parse(fs52.readFileSync(pkgPath, "utf8"));
|
|
46769
46692
|
return String(j.version || "0.0.0");
|
|
46770
46693
|
} catch {
|