@nomad-e/bluma-cli 0.15.0 → 0.16.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 +305 -400
- 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
|
|
@@ -20113,7 +20113,7 @@ async function createNextApp(args) {
|
|
|
20113
20113
|
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
20114
20114
|
init_sandbox_policy();
|
|
20115
20115
|
import { promises as fs25 } from "fs";
|
|
20116
|
-
import
|
|
20116
|
+
import path28 from "path";
|
|
20117
20117
|
|
|
20118
20118
|
// src/app/agent/tools/DeployAppTool/createDeployProjectZip.ts
|
|
20119
20119
|
import { lstat, readdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
@@ -20211,91 +20211,6 @@ async function createDeployProjectZip(projectDir, zipPath) {
|
|
|
20211
20211
|
return zipPath;
|
|
20212
20212
|
}
|
|
20213
20213
|
|
|
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
20214
|
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
20300
20215
|
async function uploadToSeverino(zipPath, severinoUrl, name, apiKey, appId) {
|
|
20301
20216
|
const deployUrl = `${severinoUrl.replace(/\/$/, "")}/api/v1/deploy`;
|
|
@@ -20304,7 +20219,7 @@ async function uploadToSeverino(zipPath, severinoUrl, name, apiKey, appId) {
|
|
|
20304
20219
|
form.append(
|
|
20305
20220
|
"file",
|
|
20306
20221
|
new Blob([zipBytes], { type: "application/zip" }),
|
|
20307
|
-
|
|
20222
|
+
path28.basename(zipPath)
|
|
20308
20223
|
);
|
|
20309
20224
|
if (name) form.append("name", name);
|
|
20310
20225
|
if (appId) form.append("appId", appId);
|
|
@@ -20413,7 +20328,7 @@ function buildFactorAiManifest(appContext, deployResult, appName) {
|
|
|
20413
20328
|
}
|
|
20414
20329
|
async function writeFactorAiManifest(projectDir, appContext, deployResult, appName) {
|
|
20415
20330
|
const manifest = buildFactorAiManifest(appContext, deployResult, appName);
|
|
20416
|
-
const manifestPath =
|
|
20331
|
+
const manifestPath = path28.join(projectDir, "factorai.sh.json");
|
|
20417
20332
|
await fs25.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
20418
20333
|
`, "utf-8");
|
|
20419
20334
|
return manifest;
|
|
@@ -20441,7 +20356,7 @@ async function deployApp(args) {
|
|
|
20441
20356
|
error: `Project directory not found: ${resolvedProjectDir}`
|
|
20442
20357
|
};
|
|
20443
20358
|
}
|
|
20444
|
-
const packageJsonPath =
|
|
20359
|
+
const packageJsonPath = path28.join(resolvedProjectDir, "package.json");
|
|
20445
20360
|
try {
|
|
20446
20361
|
await fs25.access(packageJsonPath);
|
|
20447
20362
|
} catch {
|
|
@@ -20459,20 +20374,10 @@ async function deployApp(args) {
|
|
|
20459
20374
|
error: "Not a Next.js project: next not found in dependencies"
|
|
20460
20375
|
};
|
|
20461
20376
|
}
|
|
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");
|
|
20377
|
+
const appName = name || packageJson.name || path28.basename(resolvedProjectDir);
|
|
20378
|
+
const tempDir = path28.join(resolvedProjectDir, ".tmp");
|
|
20474
20379
|
await fs25.mkdir(tempDir, { recursive: true });
|
|
20475
|
-
const zipPath =
|
|
20380
|
+
const zipPath = path28.join(tempDir, `${appName}-${Date.now()}.zip`);
|
|
20476
20381
|
console.log(`[deploy-app] Creating ZIP: ${zipPath}`);
|
|
20477
20382
|
await createDeployProjectZip(resolvedProjectDir, zipPath);
|
|
20478
20383
|
const zipStats = await fs25.stat(zipPath);
|
|
@@ -20505,7 +20410,7 @@ async function deployApp(args) {
|
|
|
20505
20410
|
appName
|
|
20506
20411
|
);
|
|
20507
20412
|
deployResult.factoraiManifest = manifest;
|
|
20508
|
-
deployResult.factoraiManifestPath =
|
|
20413
|
+
deployResult.factoraiManifestPath = path28.join(resolvedProjectDir, "factorai.sh.json");
|
|
20509
20414
|
}
|
|
20510
20415
|
console.log(`[deploy-app] Deploy iniciado: ${deployResult.appId}`);
|
|
20511
20416
|
}
|
|
@@ -21586,8 +21491,8 @@ var ToolInvoker = class {
|
|
|
21586
21491
|
async initialize() {
|
|
21587
21492
|
try {
|
|
21588
21493
|
const currentFilePath = fileURLToPath2(import.meta.url);
|
|
21589
|
-
const currentDirPath =
|
|
21590
|
-
const configPath =
|
|
21494
|
+
const currentDirPath = path29.dirname(currentFilePath);
|
|
21495
|
+
const configPath = path29.resolve(currentDirPath, "config", "native_tools.json");
|
|
21591
21496
|
const fileContent = await fs26.readFile(configPath, "utf-8");
|
|
21592
21497
|
const config3 = JSON.parse(fileContent);
|
|
21593
21498
|
this.toolDefinitions = applyMetadataToToolDefinitions(config3.nativeTools);
|
|
@@ -21636,7 +21541,7 @@ var ToolInvoker = class {
|
|
|
21636
21541
|
|
|
21637
21542
|
// src/app/agent/tools/mcp/mcp_client.ts
|
|
21638
21543
|
import { promises as fs27 } from "fs";
|
|
21639
|
-
import
|
|
21544
|
+
import path30 from "path";
|
|
21640
21545
|
import os19 from "os";
|
|
21641
21546
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
21642
21547
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -21664,9 +21569,9 @@ var MCPClient = class {
|
|
|
21664
21569
|
});
|
|
21665
21570
|
}
|
|
21666
21571
|
const __filename = fileURLToPath3(import.meta.url);
|
|
21667
|
-
const __dirname2 =
|
|
21668
|
-
const defaultConfigPath =
|
|
21669
|
-
const userConfigPath =
|
|
21572
|
+
const __dirname2 = path30.dirname(__filename);
|
|
21573
|
+
const defaultConfigPath = path30.resolve(__dirname2, "config", "bluma-mcp.json");
|
|
21574
|
+
const userConfigPath = path30.join(os19.homedir(), ".bluma", "bluma-mcp.json");
|
|
21670
21575
|
const defaultConfig = await this.loadMcpConfig(defaultConfigPath, "Default");
|
|
21671
21576
|
const userConfig = await this.loadMcpConfig(userConfigPath, "User");
|
|
21672
21577
|
const mergedConfig = {
|
|
@@ -21913,19 +21818,19 @@ PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
|
|
|
21913
21818
|
|
|
21914
21819
|
// src/app/agent/bluma/core/bluma.ts
|
|
21915
21820
|
init_session_manager();
|
|
21916
|
-
import
|
|
21821
|
+
import path45 from "path";
|
|
21917
21822
|
import fs40 from "fs";
|
|
21918
21823
|
import { v4 as uuidv48 } from "uuid";
|
|
21919
21824
|
|
|
21920
21825
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
21921
21826
|
import os23 from "os";
|
|
21922
21827
|
import fs36 from "fs";
|
|
21923
|
-
import
|
|
21828
|
+
import path39 from "path";
|
|
21924
21829
|
import { execSync as execSync3 } from "child_process";
|
|
21925
21830
|
|
|
21926
21831
|
// src/app/agent/skills/skill_loader.ts
|
|
21927
21832
|
import fs31 from "fs";
|
|
21928
|
-
import
|
|
21833
|
+
import path34 from "path";
|
|
21929
21834
|
import os20 from "os";
|
|
21930
21835
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
21931
21836
|
var SkillLoader = class _SkillLoader {
|
|
@@ -21935,8 +21840,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
21935
21840
|
cache = /* @__PURE__ */ new Map();
|
|
21936
21841
|
conflicts = [];
|
|
21937
21842
|
constructor(projectRoot, bundledDir) {
|
|
21938
|
-
this.projectSkillsDir =
|
|
21939
|
-
this.globalSkillsDir =
|
|
21843
|
+
this.projectSkillsDir = path34.join(projectRoot, ".bluma", "skills");
|
|
21844
|
+
this.globalSkillsDir = path34.join(os20.homedir(), ".bluma", "skills");
|
|
21940
21845
|
this.bundledSkillsDir = bundledDir || _SkillLoader.resolveBundledDir();
|
|
21941
21846
|
}
|
|
21942
21847
|
/**
|
|
@@ -21945,32 +21850,32 @@ var SkillLoader = class _SkillLoader {
|
|
|
21945
21850
|
*/
|
|
21946
21851
|
static resolveBundledDir() {
|
|
21947
21852
|
if (process.env.JEST_WORKER_ID !== void 0 || process.env.NODE_ENV === "test") {
|
|
21948
|
-
return
|
|
21853
|
+
return path34.join(process.cwd(), "dist", "config", "skills");
|
|
21949
21854
|
}
|
|
21950
21855
|
const candidates = [];
|
|
21951
21856
|
const push = (p) => {
|
|
21952
|
-
const abs =
|
|
21857
|
+
const abs = path34.resolve(p);
|
|
21953
21858
|
if (!candidates.includes(abs)) {
|
|
21954
21859
|
candidates.push(abs);
|
|
21955
21860
|
}
|
|
21956
21861
|
};
|
|
21957
21862
|
let argvBundled = null;
|
|
21958
21863
|
try {
|
|
21959
|
-
const bundleDir =
|
|
21960
|
-
push(
|
|
21864
|
+
const bundleDir = path34.dirname(fileURLToPath4(import.meta.url));
|
|
21865
|
+
push(path34.join(bundleDir, "config", "skills"));
|
|
21961
21866
|
} catch {
|
|
21962
21867
|
}
|
|
21963
21868
|
const argv1 = process.argv[1];
|
|
21964
21869
|
if (argv1 && !argv1.startsWith("-")) {
|
|
21965
21870
|
try {
|
|
21966
21871
|
let resolved = argv1;
|
|
21967
|
-
if (
|
|
21872
|
+
if (path34.isAbsolute(argv1) && fs31.existsSync(argv1)) {
|
|
21968
21873
|
resolved = fs31.realpathSync(argv1);
|
|
21969
|
-
} else if (!
|
|
21970
|
-
resolved =
|
|
21874
|
+
} else if (!path34.isAbsolute(argv1)) {
|
|
21875
|
+
resolved = path34.resolve(process.cwd(), argv1);
|
|
21971
21876
|
}
|
|
21972
|
-
const scriptDir =
|
|
21973
|
-
argvBundled =
|
|
21877
|
+
const scriptDir = path34.dirname(resolved);
|
|
21878
|
+
argvBundled = path34.join(scriptDir, "config", "skills");
|
|
21974
21879
|
push(argvBundled);
|
|
21975
21880
|
} catch {
|
|
21976
21881
|
}
|
|
@@ -21981,12 +21886,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
21981
21886
|
}
|
|
21982
21887
|
}
|
|
21983
21888
|
try {
|
|
21984
|
-
return
|
|
21889
|
+
return path34.join(path34.dirname(fileURLToPath4(import.meta.url)), "config", "skills");
|
|
21985
21890
|
} catch {
|
|
21986
21891
|
if (argvBundled) {
|
|
21987
21892
|
return argvBundled;
|
|
21988
21893
|
}
|
|
21989
|
-
return
|
|
21894
|
+
return path34.join(os20.homedir(), ".bluma", "__bundled_skills_unresolved__");
|
|
21990
21895
|
}
|
|
21991
21896
|
}
|
|
21992
21897
|
/**
|
|
@@ -22015,8 +21920,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
22015
21920
|
this.conflicts.push({
|
|
22016
21921
|
name: skill.name,
|
|
22017
21922
|
userSource: source,
|
|
22018
|
-
userPath:
|
|
22019
|
-
bundledPath:
|
|
21923
|
+
userPath: path34.join(dir, skill.name, "SKILL.md"),
|
|
21924
|
+
bundledPath: path34.join(this.bundledSkillsDir, skill.name, "SKILL.md")
|
|
22020
21925
|
});
|
|
22021
21926
|
continue;
|
|
22022
21927
|
}
|
|
@@ -22027,9 +21932,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22027
21932
|
if (!fs31.existsSync(dir)) return [];
|
|
22028
21933
|
try {
|
|
22029
21934
|
return fs31.readdirSync(dir).filter((d) => {
|
|
22030
|
-
const fullPath =
|
|
22031
|
-
return fs31.statSync(fullPath).isDirectory() && fs31.existsSync(
|
|
22032
|
-
}).map((d) => this.loadMetadataFromPath(
|
|
21935
|
+
const fullPath = path34.join(dir, d);
|
|
21936
|
+
return fs31.statSync(fullPath).isDirectory() && fs31.existsSync(path34.join(fullPath, "SKILL.md"));
|
|
21937
|
+
}).map((d) => this.loadMetadataFromPath(path34.join(dir, d, "SKILL.md"), d, source)).filter((m) => m !== null);
|
|
22033
21938
|
} catch {
|
|
22034
21939
|
return [];
|
|
22035
21940
|
}
|
|
@@ -22059,9 +21964,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22059
21964
|
*/
|
|
22060
21965
|
load(name) {
|
|
22061
21966
|
if (this.cache.has(name)) return this.cache.get(name);
|
|
22062
|
-
const bundledPath =
|
|
22063
|
-
const projectPath =
|
|
22064
|
-
const globalPath =
|
|
21967
|
+
const bundledPath = path34.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
21968
|
+
const projectPath = path34.join(this.projectSkillsDir, name, "SKILL.md");
|
|
21969
|
+
const globalPath = path34.join(this.globalSkillsDir, name, "SKILL.md");
|
|
22065
21970
|
const existsBundled = fs31.existsSync(bundledPath);
|
|
22066
21971
|
const existsProject = fs31.existsSync(projectPath);
|
|
22067
21972
|
const existsGlobal = fs31.existsSync(globalPath);
|
|
@@ -22105,7 +22010,7 @@ var SkillLoader = class _SkillLoader {
|
|
|
22105
22010
|
try {
|
|
22106
22011
|
const raw = fs31.readFileSync(skillPath, "utf-8");
|
|
22107
22012
|
const parsed = this.parseFrontmatter(raw);
|
|
22108
|
-
const skillDir =
|
|
22013
|
+
const skillDir = path34.dirname(skillPath);
|
|
22109
22014
|
return {
|
|
22110
22015
|
name: parsed.name || name,
|
|
22111
22016
|
description: parsed.description || "",
|
|
@@ -22114,8 +22019,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
22114
22019
|
version: parsed.version,
|
|
22115
22020
|
author: parsed.author,
|
|
22116
22021
|
license: parsed.license,
|
|
22117
|
-
references: this.scanAssets(
|
|
22118
|
-
scripts: this.scanAssets(
|
|
22022
|
+
references: this.scanAssets(path34.join(skillDir, "references")),
|
|
22023
|
+
scripts: this.scanAssets(path34.join(skillDir, "scripts"))
|
|
22119
22024
|
};
|
|
22120
22025
|
} catch {
|
|
22121
22026
|
return null;
|
|
@@ -22125,11 +22030,11 @@ var SkillLoader = class _SkillLoader {
|
|
|
22125
22030
|
if (!fs31.existsSync(dir)) return [];
|
|
22126
22031
|
try {
|
|
22127
22032
|
return fs31.readdirSync(dir).filter((f) => {
|
|
22128
|
-
const fp =
|
|
22033
|
+
const fp = path34.join(dir, f);
|
|
22129
22034
|
return fs31.statSync(fp).isFile();
|
|
22130
22035
|
}).map((f) => ({
|
|
22131
22036
|
name: f,
|
|
22132
|
-
path:
|
|
22037
|
+
path: path34.resolve(dir, f)
|
|
22133
22038
|
}));
|
|
22134
22039
|
} catch {
|
|
22135
22040
|
return [];
|
|
@@ -22186,9 +22091,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
22186
22091
|
this.cache.clear();
|
|
22187
22092
|
}
|
|
22188
22093
|
exists(name) {
|
|
22189
|
-
const bundledPath =
|
|
22190
|
-
const projectPath =
|
|
22191
|
-
const globalPath =
|
|
22094
|
+
const bundledPath = path34.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
22095
|
+
const projectPath = path34.join(this.projectSkillsDir, name, "SKILL.md");
|
|
22096
|
+
const globalPath = path34.join(this.globalSkillsDir, name, "SKILL.md");
|
|
22192
22097
|
return fs31.existsSync(bundledPath) || fs31.existsSync(projectPath) || fs31.existsSync(globalPath);
|
|
22193
22098
|
}
|
|
22194
22099
|
/**
|
|
@@ -22222,12 +22127,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
22222
22127
|
|
|
22223
22128
|
// src/app/agent/core/prompt/workspace_snapshot.ts
|
|
22224
22129
|
import fs33 from "fs";
|
|
22225
|
-
import
|
|
22130
|
+
import path36 from "path";
|
|
22226
22131
|
import { execSync as execSync2 } from "child_process";
|
|
22227
22132
|
|
|
22228
22133
|
// src/app/agent/utils/blumamd.ts
|
|
22229
22134
|
import fs32 from "fs";
|
|
22230
|
-
import
|
|
22135
|
+
import path35 from "path";
|
|
22231
22136
|
import os21 from "os";
|
|
22232
22137
|
import { execSync } from "child_process";
|
|
22233
22138
|
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 +22262,12 @@ var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
22357
22262
|
function expandIncludePath(includePath, baseDir) {
|
|
22358
22263
|
const cleanPath = includePath.startsWith("@") ? includePath.slice(1) : includePath;
|
|
22359
22264
|
if (cleanPath.startsWith("~")) {
|
|
22360
|
-
return
|
|
22265
|
+
return path35.join(os21.homedir(), cleanPath.slice(1));
|
|
22361
22266
|
}
|
|
22362
|
-
if (
|
|
22267
|
+
if (path35.isAbsolute(cleanPath)) {
|
|
22363
22268
|
return cleanPath;
|
|
22364
22269
|
}
|
|
22365
|
-
return
|
|
22270
|
+
return path35.resolve(baseDir, cleanPath);
|
|
22366
22271
|
}
|
|
22367
22272
|
function processIncludes(content, baseDir, processedFiles) {
|
|
22368
22273
|
const lines = content.split("\n");
|
|
@@ -22371,12 +22276,12 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
22371
22276
|
const includeMatch = line.match(/^@\s*([^\s]+)/);
|
|
22372
22277
|
if (includeMatch) {
|
|
22373
22278
|
const includePath = expandIncludePath(includeMatch[1], baseDir);
|
|
22374
|
-
const normalizedPath =
|
|
22279
|
+
const normalizedPath = path35.normalize(includePath);
|
|
22375
22280
|
if (processedFiles.has(normalizedPath)) {
|
|
22376
22281
|
result.push(`<!-- Circular include prevented: ${includeMatch[1]} -->`);
|
|
22377
22282
|
continue;
|
|
22378
22283
|
}
|
|
22379
|
-
const ext =
|
|
22284
|
+
const ext = path35.extname(includePath).toLowerCase();
|
|
22380
22285
|
if (!TEXT_FILE_EXTENSIONS.has(ext)) {
|
|
22381
22286
|
result.push(`<!-- Include skipped (unsupported extension): ${includeMatch[1]} -->`);
|
|
22382
22287
|
continue;
|
|
@@ -22384,7 +22289,7 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
22384
22289
|
try {
|
|
22385
22290
|
const includedContent = fs32.readFileSync(includePath, "utf-8");
|
|
22386
22291
|
processedFiles.add(normalizedPath);
|
|
22387
|
-
const processedContent = processIncludes(includedContent,
|
|
22292
|
+
const processedContent = processIncludes(includedContent, path35.dirname(includePath), processedFiles);
|
|
22388
22293
|
result.push(`
|
|
22389
22294
|
<!-- BEGIN INCLUDE ${includeMatch[1]} -->
|
|
22390
22295
|
`);
|
|
@@ -22431,8 +22336,8 @@ function parseFrontmatterPaths(paths2) {
|
|
|
22431
22336
|
function readMemoryFile(filePath, type, includeBasePath) {
|
|
22432
22337
|
try {
|
|
22433
22338
|
const rawContent = fs32.readFileSync(filePath, "utf-8");
|
|
22434
|
-
const baseDir = includeBasePath ||
|
|
22435
|
-
const processedFiles = /* @__PURE__ */ new Set([
|
|
22339
|
+
const baseDir = includeBasePath || path35.dirname(filePath);
|
|
22340
|
+
const processedFiles = /* @__PURE__ */ new Set([path35.normalize(filePath)]);
|
|
22436
22341
|
const { frontmatter, content: withoutFrontmatter } = parseFrontmatter(rawContent);
|
|
22437
22342
|
const globs = parseFrontmatterPaths(frontmatter.paths);
|
|
22438
22343
|
const processedContent = processIncludes(withoutFrontmatter, baseDir, processedFiles);
|
|
@@ -22454,15 +22359,15 @@ function readMemoryFile(filePath, type, includeBasePath) {
|
|
|
22454
22359
|
}
|
|
22455
22360
|
function findGitRoot(startDir) {
|
|
22456
22361
|
let current = startDir;
|
|
22457
|
-
while (current !==
|
|
22458
|
-
const gitPath =
|
|
22362
|
+
while (current !== path35.dirname(current)) {
|
|
22363
|
+
const gitPath = path35.join(current, ".git");
|
|
22459
22364
|
try {
|
|
22460
22365
|
if (fs32.existsSync(gitPath)) {
|
|
22461
22366
|
return current;
|
|
22462
22367
|
}
|
|
22463
22368
|
} catch {
|
|
22464
22369
|
}
|
|
22465
|
-
current =
|
|
22370
|
+
current = path35.dirname(current);
|
|
22466
22371
|
}
|
|
22467
22372
|
return null;
|
|
22468
22373
|
}
|
|
@@ -22493,11 +22398,11 @@ function processRulesDirectory(rulesDir, type, processedPaths, conditionalRule =
|
|
|
22493
22398
|
try {
|
|
22494
22399
|
const entries = fs32.readdirSync(rulesDir, { withFileTypes: true });
|
|
22495
22400
|
for (const entry of entries) {
|
|
22496
|
-
const entryPath =
|
|
22401
|
+
const entryPath = path35.join(rulesDir, entry.name);
|
|
22497
22402
|
if (entry.isDirectory()) {
|
|
22498
22403
|
result.push(...processRulesDirectory(entryPath, type, processedPaths, conditionalRule));
|
|
22499
22404
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22500
|
-
const normalizedPath =
|
|
22405
|
+
const normalizedPath = path35.normalize(entryPath);
|
|
22501
22406
|
if (processedPaths.has(normalizedPath)) {
|
|
22502
22407
|
continue;
|
|
22503
22408
|
}
|
|
@@ -22533,13 +22438,13 @@ function loadManagedMemory() {
|
|
|
22533
22438
|
function loadUserMemory() {
|
|
22534
22439
|
const files = [];
|
|
22535
22440
|
const homeDir = os21.homedir();
|
|
22536
|
-
const userBlumaDir =
|
|
22537
|
-
const userBlumaMd =
|
|
22441
|
+
const userBlumaDir = path35.join(homeDir, ".bluma");
|
|
22442
|
+
const userBlumaMd = path35.join(userBlumaDir, "BLUMA.md");
|
|
22538
22443
|
const userFile = readMemoryFile(userBlumaMd, "User");
|
|
22539
22444
|
if (userFile && userFile.content.trim()) {
|
|
22540
22445
|
files.push(userFile);
|
|
22541
22446
|
}
|
|
22542
|
-
const userRulesDir =
|
|
22447
|
+
const userRulesDir = path35.join(userBlumaDir, "rules");
|
|
22543
22448
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22544
22449
|
files.push(...processRulesDirectory(userRulesDir, "User", processedPaths, false));
|
|
22545
22450
|
return files;
|
|
@@ -22551,10 +22456,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22551
22456
|
let currentDir = cwd2;
|
|
22552
22457
|
const MAX_TRAVERSAL_DEPTH = 20;
|
|
22553
22458
|
let depth = 0;
|
|
22554
|
-
const normalizedGitRoot =
|
|
22555
|
-
while (currentDir !==
|
|
22459
|
+
const normalizedGitRoot = path35.resolve(gitRoot);
|
|
22460
|
+
while (currentDir !== path35.dirname(currentDir) && path35.resolve(currentDir).startsWith(normalizedGitRoot) && depth < MAX_TRAVERSAL_DEPTH) {
|
|
22556
22461
|
dirs.push(currentDir);
|
|
22557
|
-
currentDir =
|
|
22462
|
+
currentDir = path35.dirname(currentDir);
|
|
22558
22463
|
depth++;
|
|
22559
22464
|
}
|
|
22560
22465
|
if (!dirs.includes(gitRoot)) {
|
|
@@ -22562,7 +22467,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22562
22467
|
}
|
|
22563
22468
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22564
22469
|
for (const dir of dirs.reverse()) {
|
|
22565
|
-
const projectBlumaMd =
|
|
22470
|
+
const projectBlumaMd = path35.join(dir, "BLUMA.md");
|
|
22566
22471
|
if (!processedPaths.has(projectBlumaMd)) {
|
|
22567
22472
|
processedPaths.add(projectBlumaMd);
|
|
22568
22473
|
const projectFile = readMemoryFile(projectBlumaMd, "Project");
|
|
@@ -22570,7 +22475,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22570
22475
|
files.push(projectFile);
|
|
22571
22476
|
}
|
|
22572
22477
|
}
|
|
22573
|
-
const blumaDirBlumaMd =
|
|
22478
|
+
const blumaDirBlumaMd = path35.join(dir, ".bluma", "BLUMA.md");
|
|
22574
22479
|
if (!processedPaths.has(blumaDirBlumaMd)) {
|
|
22575
22480
|
processedPaths.add(blumaDirBlumaMd);
|
|
22576
22481
|
const blumaDirFile = readMemoryFile(blumaDirBlumaMd, "Project");
|
|
@@ -22578,10 +22483,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22578
22483
|
files.push(blumaDirFile);
|
|
22579
22484
|
}
|
|
22580
22485
|
}
|
|
22581
|
-
const rulesDir =
|
|
22486
|
+
const rulesDir = path35.join(dir, ".bluma", "rules");
|
|
22582
22487
|
files.push(...processRulesDirectory(rulesDir, "Project", processedPaths, false));
|
|
22583
22488
|
}
|
|
22584
|
-
const localBlumaMd =
|
|
22489
|
+
const localBlumaMd = path35.join(cwd2, "BLUMA.local.md");
|
|
22585
22490
|
if (!processedPaths.has(localBlumaMd)) {
|
|
22586
22491
|
processedPaths.add(localBlumaMd);
|
|
22587
22492
|
const localFile = readMemoryFile(localBlumaMd, "Local");
|
|
@@ -22682,7 +22587,7 @@ function safeReadFile(filePath, maxChars) {
|
|
|
22682
22587
|
}
|
|
22683
22588
|
function tryReadReadme(cwd2) {
|
|
22684
22589
|
for (const name of ["README.md", "README.MD", "readme.md", "Readme.md"]) {
|
|
22685
|
-
const c = safeReadFile(
|
|
22590
|
+
const c = safeReadFile(path36.join(cwd2, name), LIMITS.readme);
|
|
22686
22591
|
if (c) return `(${name})
|
|
22687
22592
|
${c}`;
|
|
22688
22593
|
}
|
|
@@ -22690,14 +22595,14 @@ ${c}`;
|
|
|
22690
22595
|
}
|
|
22691
22596
|
function tryReadBluMaMd(cwd2) {
|
|
22692
22597
|
const paths2 = [
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22598
|
+
path36.join(cwd2, "BluMa.md"),
|
|
22599
|
+
path36.join(cwd2, "BLUMA.md"),
|
|
22600
|
+
path36.join(cwd2, ".bluma", "BluMa.md")
|
|
22696
22601
|
];
|
|
22697
22602
|
for (const p of paths2) {
|
|
22698
22603
|
const c = safeReadFile(p, LIMITS.blumaMd);
|
|
22699
22604
|
if (c) {
|
|
22700
|
-
const rel =
|
|
22605
|
+
const rel = path36.relative(cwd2, p) || p;
|
|
22701
22606
|
return `(${rel})
|
|
22702
22607
|
${c}`;
|
|
22703
22608
|
}
|
|
@@ -22705,7 +22610,7 @@ ${c}`;
|
|
|
22705
22610
|
return null;
|
|
22706
22611
|
}
|
|
22707
22612
|
function summarizePackageJson(cwd2) {
|
|
22708
|
-
const p =
|
|
22613
|
+
const p = path36.join(cwd2, "package.json");
|
|
22709
22614
|
try {
|
|
22710
22615
|
if (!fs33.existsSync(p)) return null;
|
|
22711
22616
|
const pkg = JSON.parse(fs33.readFileSync(p, "utf8"));
|
|
@@ -22799,7 +22704,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22799
22704
|
parts.push(pkg);
|
|
22800
22705
|
parts.push("```\n");
|
|
22801
22706
|
}
|
|
22802
|
-
const py = safeReadFile(
|
|
22707
|
+
const py = safeReadFile(path36.join(cwd2, "pyproject.toml"), LIMITS.pyproject);
|
|
22803
22708
|
if (py) {
|
|
22804
22709
|
parts.push("### pyproject.toml (excerpt)\n```toml");
|
|
22805
22710
|
parts.push(py);
|
|
@@ -22817,15 +22722,15 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22817
22722
|
parts.push(bluma);
|
|
22818
22723
|
parts.push("```\n");
|
|
22819
22724
|
}
|
|
22820
|
-
const contrib = safeReadFile(
|
|
22725
|
+
const contrib = safeReadFile(path36.join(cwd2, "CONTRIBUTING.md"), LIMITS.contributing);
|
|
22821
22726
|
if (contrib) {
|
|
22822
22727
|
parts.push("### CONTRIBUTING.md (excerpt)\n```markdown");
|
|
22823
22728
|
parts.push(contrib);
|
|
22824
22729
|
parts.push("```\n");
|
|
22825
22730
|
}
|
|
22826
|
-
const chlog = safeReadFile(
|
|
22731
|
+
const chlog = safeReadFile(path36.join(cwd2, "CHANGELOG.md"), LIMITS.changelog);
|
|
22827
22732
|
if (!chlog) {
|
|
22828
|
-
const alt = safeReadFile(
|
|
22733
|
+
const alt = safeReadFile(path36.join(cwd2, "CHANGES.md"), LIMITS.changelog);
|
|
22829
22734
|
if (alt) {
|
|
22830
22735
|
parts.push("### CHANGES.md (excerpt)\n```markdown");
|
|
22831
22736
|
parts.push(alt);
|
|
@@ -22861,14 +22766,14 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22861
22766
|
} else {
|
|
22862
22767
|
parts.push("### Git\n(not a git work tree, or `git` unavailable)\n");
|
|
22863
22768
|
}
|
|
22864
|
-
const tsconfig = safeReadFile(
|
|
22769
|
+
const tsconfig = safeReadFile(path36.join(cwd2, "tsconfig.json"), LIMITS.tsconfig);
|
|
22865
22770
|
if (tsconfig) {
|
|
22866
22771
|
parts.push("### tsconfig.json (excerpt)\n```json");
|
|
22867
22772
|
parts.push(tsconfig);
|
|
22868
22773
|
parts.push("```\n");
|
|
22869
22774
|
}
|
|
22870
22775
|
for (const name of ["Dockerfile", "dockerfile", "Dockerfile.prod", "Dockerfile.dev"]) {
|
|
22871
|
-
const df = safeReadFile(
|
|
22776
|
+
const df = safeReadFile(path36.join(cwd2, name), LIMITS.dockerfile);
|
|
22872
22777
|
if (df) {
|
|
22873
22778
|
parts.push(`### ${name} (excerpt)
|
|
22874
22779
|
`);
|
|
@@ -22878,7 +22783,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22878
22783
|
}
|
|
22879
22784
|
}
|
|
22880
22785
|
for (const name of ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"]) {
|
|
22881
|
-
const dc = safeReadFile(
|
|
22786
|
+
const dc = safeReadFile(path36.join(cwd2, name), LIMITS.dockerfile);
|
|
22882
22787
|
if (dc) {
|
|
22883
22788
|
parts.push(`### ${name} (excerpt)
|
|
22884
22789
|
`);
|
|
@@ -22893,7 +22798,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22893
22798
|
".circleci/config.yml",
|
|
22894
22799
|
"Jenkinsfile"
|
|
22895
22800
|
]) {
|
|
22896
|
-
const ciFile =
|
|
22801
|
+
const ciFile = path36.join(cwd2, ciPath);
|
|
22897
22802
|
if (fs33.existsSync(ciFile)) {
|
|
22898
22803
|
const st = fs33.statSync(ciFile);
|
|
22899
22804
|
if (st.isDirectory()) {
|
|
@@ -22909,7 +22814,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22909
22814
|
} else {
|
|
22910
22815
|
const ci = safeReadFile(ciFile, LIMITS.ciConfig);
|
|
22911
22816
|
if (ci) {
|
|
22912
|
-
parts.push(`### CI config (${
|
|
22817
|
+
parts.push(`### CI config (${path36.basename(ciPath)})
|
|
22913
22818
|
`);
|
|
22914
22819
|
parts.push(ci);
|
|
22915
22820
|
parts.push("\n");
|
|
@@ -22918,7 +22823,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22918
22823
|
}
|
|
22919
22824
|
}
|
|
22920
22825
|
for (const depFile of ["requirements.txt", "Pipfile", "poetry.lock", "Gemfile", "go.sum", "Cargo.lock"]) {
|
|
22921
|
-
const depPath =
|
|
22826
|
+
const depPath = path36.join(cwd2, depFile);
|
|
22922
22827
|
if (fs33.existsSync(depPath)) {
|
|
22923
22828
|
const depContent = safeReadFile(depPath, 1500);
|
|
22924
22829
|
if (depContent) {
|
|
@@ -22932,7 +22837,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22932
22837
|
}
|
|
22933
22838
|
}
|
|
22934
22839
|
for (const envFile of [".env.example", ".env.sample", ".env.template"]) {
|
|
22935
|
-
const envPath =
|
|
22840
|
+
const envPath = path36.join(cwd2, envFile);
|
|
22936
22841
|
if (fs33.existsSync(envPath)) {
|
|
22937
22842
|
try {
|
|
22938
22843
|
const raw = fs33.readFileSync(envPath, "utf-8");
|
|
@@ -22960,13 +22865,13 @@ init_runtime_config();
|
|
|
22960
22865
|
init_sandbox_policy();
|
|
22961
22866
|
import fs34 from "fs";
|
|
22962
22867
|
import os22 from "os";
|
|
22963
|
-
import
|
|
22868
|
+
import path37 from "path";
|
|
22964
22869
|
function getProjectPluginsDir() {
|
|
22965
22870
|
const policy = getSandboxPolicy();
|
|
22966
|
-
return
|
|
22871
|
+
return path37.join(policy.workspaceRoot, ".bluma", "plugins");
|
|
22967
22872
|
}
|
|
22968
22873
|
function getGlobalPluginsDir() {
|
|
22969
|
-
return
|
|
22874
|
+
return path37.join(process.env.HOME || os22.homedir(), ".bluma", "plugins");
|
|
22970
22875
|
}
|
|
22971
22876
|
function getPluginDirs() {
|
|
22972
22877
|
return {
|
|
@@ -22992,8 +22897,8 @@ function readManifest(manifestPath, fallbackName) {
|
|
|
22992
22897
|
}
|
|
22993
22898
|
function findManifestPath(pluginDir) {
|
|
22994
22899
|
const candidates = [
|
|
22995
|
-
|
|
22996
|
-
|
|
22900
|
+
path37.join(pluginDir, ".codex-plugin", "plugin.json"),
|
|
22901
|
+
path37.join(pluginDir, "plugin.json")
|
|
22997
22902
|
];
|
|
22998
22903
|
for (const candidate of candidates) {
|
|
22999
22904
|
if (fs34.existsSync(candidate)) {
|
|
@@ -23007,7 +22912,7 @@ function listFromDir(baseDir, source) {
|
|
|
23007
22912
|
return [];
|
|
23008
22913
|
}
|
|
23009
22914
|
return fs34.readdirSync(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).flatMap((entry) => {
|
|
23010
|
-
const pluginDir =
|
|
22915
|
+
const pluginDir = path37.join(baseDir, entry.name);
|
|
23011
22916
|
const manifestPath = findManifestPath(pluginDir);
|
|
23012
22917
|
if (!manifestPath) {
|
|
23013
22918
|
return [];
|
|
@@ -23453,7 +23358,7 @@ function buildModelInfoSection(modelId) {
|
|
|
23453
23358
|
// src/app/agent/runtime/hook_registry.ts
|
|
23454
23359
|
init_sandbox_policy();
|
|
23455
23360
|
import fs35 from "fs";
|
|
23456
|
-
import
|
|
23361
|
+
import path38 from "path";
|
|
23457
23362
|
var DEFAULT_STATE = {
|
|
23458
23363
|
enabled: true,
|
|
23459
23364
|
maxEvents: 120,
|
|
@@ -23464,7 +23369,7 @@ var cache3 = null;
|
|
|
23464
23369
|
var cachePath2 = null;
|
|
23465
23370
|
function getStatePath() {
|
|
23466
23371
|
const policy = getSandboxPolicy();
|
|
23467
|
-
return
|
|
23372
|
+
return path38.join(policy.workspaceRoot, ".bluma", "hooks.json");
|
|
23468
23373
|
}
|
|
23469
23374
|
function getHookStatePath() {
|
|
23470
23375
|
return getStatePath();
|
|
@@ -23510,7 +23415,7 @@ function ensureLoaded2() {
|
|
|
23510
23415
|
}
|
|
23511
23416
|
function persist2(state2) {
|
|
23512
23417
|
const statePath = getStatePath();
|
|
23513
|
-
fs35.mkdirSync(
|
|
23418
|
+
fs35.mkdirSync(path38.dirname(statePath), { recursive: true });
|
|
23514
23419
|
state2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23515
23420
|
fs35.writeFileSync(statePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
23516
23421
|
cache3 = state2;
|
|
@@ -23774,15 +23679,15 @@ init_memdir();
|
|
|
23774
23679
|
|
|
23775
23680
|
// src/app/agent/memory/session_memory_context.ts
|
|
23776
23681
|
init_session_memory_paths();
|
|
23777
|
-
import { readFile as
|
|
23682
|
+
import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
|
|
23778
23683
|
async function loadSessionMemoryForPrompt(sessionId, cwd2 = process.cwd()) {
|
|
23779
23684
|
if (!sessionId?.trim()) return "";
|
|
23780
|
-
const
|
|
23685
|
+
const path59 = getSessionMemoryPath(sessionId, cwd2);
|
|
23781
23686
|
try {
|
|
23782
|
-
const content = await
|
|
23687
|
+
const content = await readFile3(path59, "utf-8");
|
|
23783
23688
|
if (!content.trim()) return "";
|
|
23784
23689
|
return `<session_memory>
|
|
23785
|
-
Notes for this conversation (${
|
|
23690
|
+
Notes for this conversation (${path59}):
|
|
23786
23691
|
|
|
23787
23692
|
${content.trim()}
|
|
23788
23693
|
</session_memory>`;
|
|
@@ -23792,11 +23697,11 @@ ${content.trim()}
|
|
|
23792
23697
|
}
|
|
23793
23698
|
async function initSessionMemoryFile(sessionId, cwd2 = process.cwd()) {
|
|
23794
23699
|
await ensureSessionMemoryDir(sessionId, cwd2);
|
|
23795
|
-
const
|
|
23700
|
+
const path59 = getSessionMemoryPath(sessionId, cwd2);
|
|
23796
23701
|
try {
|
|
23797
|
-
await
|
|
23702
|
+
await readFile3(path59, "utf-8");
|
|
23798
23703
|
} catch {
|
|
23799
|
-
await
|
|
23704
|
+
await writeFile2(path59, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
|
|
23800
23705
|
`, "utf-8");
|
|
23801
23706
|
}
|
|
23802
23707
|
}
|
|
@@ -23878,7 +23783,7 @@ Use \`factorai.sh.redeploy_app({ appId })\` only when sources on the server are
|
|
|
23878
23783
|
|
|
23879
23784
|
## Deploy constraints (first deploy)
|
|
23880
23785
|
|
|
23881
|
-
- \`next.config.js\` must
|
|
23786
|
+
- \`next.config.js\` must keep \`output: 'standalone'\` (included in scaffold).
|
|
23882
23787
|
- ZIP max ~50MB \u2014 source only; Severino runs \`npm install\` + \`next build\` on the server.
|
|
23883
23788
|
- shadcn components in scaffold must compile (no missing Radix imports).
|
|
23884
23789
|
|
|
@@ -23929,17 +23834,17 @@ function getGitBranch(dir) {
|
|
|
23929
23834
|
}
|
|
23930
23835
|
}
|
|
23931
23836
|
function getPackageManager(dir) {
|
|
23932
|
-
if (fs36.existsSync(
|
|
23933
|
-
if (fs36.existsSync(
|
|
23934
|
-
if (fs36.existsSync(
|
|
23935
|
-
if (fs36.existsSync(
|
|
23837
|
+
if (fs36.existsSync(path39.join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
23838
|
+
if (fs36.existsSync(path39.join(dir, "yarn.lock"))) return "yarn";
|
|
23839
|
+
if (fs36.existsSync(path39.join(dir, "bun.lockb"))) return "bun";
|
|
23840
|
+
if (fs36.existsSync(path39.join(dir, "package-lock.json"))) return "npm";
|
|
23936
23841
|
return "unknown";
|
|
23937
23842
|
}
|
|
23938
23843
|
function getProjectType(dir) {
|
|
23939
23844
|
try {
|
|
23940
23845
|
const files = fs36.readdirSync(dir);
|
|
23941
23846
|
if (files.includes("package.json")) {
|
|
23942
|
-
const pkg = JSON.parse(fs36.readFileSync(
|
|
23847
|
+
const pkg = JSON.parse(fs36.readFileSync(path39.join(dir, "package.json"), "utf-8"));
|
|
23943
23848
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
23944
23849
|
if (deps.next) return "Next.js";
|
|
23945
23850
|
if (deps.react) return "React";
|
|
@@ -23959,7 +23864,7 @@ function getProjectType(dir) {
|
|
|
23959
23864
|
}
|
|
23960
23865
|
function getTestFramework(dir) {
|
|
23961
23866
|
try {
|
|
23962
|
-
const pkgPath =
|
|
23867
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23963
23868
|
if (fs36.existsSync(pkgPath)) {
|
|
23964
23869
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23965
23870
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -23970,7 +23875,7 @@ function getTestFramework(dir) {
|
|
|
23970
23875
|
if (deps["@playwright/test"]) return "playwright";
|
|
23971
23876
|
if (deps.cypress) return "cypress";
|
|
23972
23877
|
}
|
|
23973
|
-
if (fs36.existsSync(
|
|
23878
|
+
if (fs36.existsSync(path39.join(dir, "pytest.ini")) || fs36.existsSync(path39.join(dir, "conftest.py"))) return "pytest";
|
|
23974
23879
|
return "unknown";
|
|
23975
23880
|
} catch {
|
|
23976
23881
|
return "unknown";
|
|
@@ -23978,7 +23883,7 @@ function getTestFramework(dir) {
|
|
|
23978
23883
|
}
|
|
23979
23884
|
function getTestCommand(dir) {
|
|
23980
23885
|
try {
|
|
23981
|
-
const pkgPath =
|
|
23886
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23982
23887
|
if (fs36.existsSync(pkgPath)) {
|
|
23983
23888
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23984
23889
|
if (pkg.scripts?.test) return "npm test";
|
|
@@ -23995,7 +23900,7 @@ function getTestCommand(dir) {
|
|
|
23995
23900
|
}
|
|
23996
23901
|
function isGitRepo(dir) {
|
|
23997
23902
|
try {
|
|
23998
|
-
const p =
|
|
23903
|
+
const p = path39.join(dir, ".git");
|
|
23999
23904
|
return fs36.existsSync(p) && fs36.lstatSync(p).isDirectory();
|
|
24000
23905
|
} catch {
|
|
24001
23906
|
return false;
|
|
@@ -25432,7 +25337,7 @@ var LLMService = class {
|
|
|
25432
25337
|
// src/app/agent/utils/user_message_images.ts
|
|
25433
25338
|
import fs37 from "fs";
|
|
25434
25339
|
import os25 from "os";
|
|
25435
|
-
import
|
|
25340
|
+
import path40 from "path";
|
|
25436
25341
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
25437
25342
|
var IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp)$/i;
|
|
25438
25343
|
var MAX_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
@@ -25448,22 +25353,22 @@ var MIME = {
|
|
|
25448
25353
|
function expandUserPath(p) {
|
|
25449
25354
|
const t = p.trim();
|
|
25450
25355
|
if (t.startsWith("~")) {
|
|
25451
|
-
return
|
|
25356
|
+
return path40.join(os25.homedir(), t.slice(1).replace(/^\//, ""));
|
|
25452
25357
|
}
|
|
25453
25358
|
return t;
|
|
25454
25359
|
}
|
|
25455
25360
|
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 +
|
|
25361
|
+
const resolved = path40.normalize(path40.resolve(absResolved));
|
|
25362
|
+
const cwdR = path40.normalize(path40.resolve(cwd2));
|
|
25363
|
+
const homeR = path40.normalize(path40.resolve(os25.homedir()));
|
|
25364
|
+
const tmpR = path40.normalize(path40.resolve(os25.tmpdir()));
|
|
25365
|
+
const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path40.sep);
|
|
25366
|
+
const underHome = resolved === homeR || resolved.startsWith(homeR + path40.sep);
|
|
25367
|
+
const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path40.sep);
|
|
25463
25368
|
return underCwd || underHome || underTmp;
|
|
25464
25369
|
}
|
|
25465
25370
|
function mimeFor(abs) {
|
|
25466
|
-
const ext =
|
|
25371
|
+
const ext = path40.extname(abs).toLowerCase();
|
|
25467
25372
|
return MIME[ext] || "application/octet-stream";
|
|
25468
25373
|
}
|
|
25469
25374
|
var IMAGE_EXT_SRC = String.raw`(?:png|jpe?g|gif|webp|bmp)`;
|
|
@@ -25507,7 +25412,7 @@ function collectImagePathStrings(raw) {
|
|
|
25507
25412
|
}
|
|
25508
25413
|
function resolveImagePath(candidate, cwd2) {
|
|
25509
25414
|
const expanded = expandUserPath(candidate);
|
|
25510
|
-
const abs =
|
|
25415
|
+
const abs = path40.isAbsolute(expanded) ? path40.normalize(expanded) : path40.normalize(path40.resolve(cwd2, expanded));
|
|
25511
25416
|
if (!isPathAllowed(abs, cwd2)) return null;
|
|
25512
25417
|
try {
|
|
25513
25418
|
if (!fs37.existsSync(abs) || !fs37.statSync(abs).isFile()) return null;
|
|
@@ -25530,7 +25435,7 @@ function trySingleLineFileUriOrBareImagePath(line, cwd2) {
|
|
|
25530
25435
|
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
25531
25436
|
s = s.slice(1, -1).trim();
|
|
25532
25437
|
}
|
|
25533
|
-
if (!IMAGE_EXT.test(
|
|
25438
|
+
if (!IMAGE_EXT.test(path40.extname(s))) return null;
|
|
25534
25439
|
const abs = resolveImagePath(s, cwd2);
|
|
25535
25440
|
if (!abs) return null;
|
|
25536
25441
|
try {
|
|
@@ -25633,7 +25538,7 @@ function buildUserMessageContent(raw, cwd2) {
|
|
|
25633
25538
|
init_sandbox_policy();
|
|
25634
25539
|
init_runtime_config();
|
|
25635
25540
|
init_permission_rules();
|
|
25636
|
-
import
|
|
25541
|
+
import path41 from "path";
|
|
25637
25542
|
var LOCAL_EDIT_TOOL_NAMES = /* @__PURE__ */ new Set(["edit_tool", "file_write", "notebook_edit"]);
|
|
25638
25543
|
function getToolPermissionLayer(metadata) {
|
|
25639
25544
|
if (metadata.riskLevel === "safe") return "read";
|
|
@@ -25648,11 +25553,11 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25648
25553
|
if (!filePath) {
|
|
25649
25554
|
return { allowed: false, reason: "No file path provided for permission check." };
|
|
25650
25555
|
}
|
|
25651
|
-
const resolvedPath =
|
|
25556
|
+
const resolvedPath = path41.resolve(filePath);
|
|
25652
25557
|
if (!isPathInsideWorkspace(resolvedPath, policy)) {
|
|
25653
25558
|
return { allowed: false, reason: `File path "${filePath}" is outside workspace root.` };
|
|
25654
25559
|
}
|
|
25655
|
-
const relativePath =
|
|
25560
|
+
const relativePath = path41.relative(policy.workspaceRoot, resolvedPath);
|
|
25656
25561
|
const toolPattern = `${toolName}(${relativePath})`;
|
|
25657
25562
|
const ruleDecision = permissionRulesEngine.checkPermission(toolPattern, { filepath: filePath });
|
|
25658
25563
|
if (ruleDecision === "deny") {
|
|
@@ -25661,7 +25566,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25661
25566
|
if (ruleDecision === "allow") {
|
|
25662
25567
|
return { allowed: true, reason: `File "${filePath}" allowed by permission rules.` };
|
|
25663
25568
|
}
|
|
25664
|
-
const dirPath =
|
|
25569
|
+
const dirPath = path41.dirname(relativePath);
|
|
25665
25570
|
const dirPattern = `${toolName}(${dirPath}/**)`;
|
|
25666
25571
|
const dirRuleDecision = permissionRulesEngine.checkPermission(dirPattern, { filepath: filePath });
|
|
25667
25572
|
if (dirRuleDecision === "allow") {
|
|
@@ -25879,10 +25784,10 @@ function effectiveToolAutoApprove(toolCall, sessionId, options) {
|
|
|
25879
25784
|
|
|
25880
25785
|
// src/app/agent/tools/CodingMemoryTool/CodingMemoryConsolidate.ts
|
|
25881
25786
|
import * as fs38 from "fs";
|
|
25882
|
-
import * as
|
|
25787
|
+
import * as path42 from "path";
|
|
25883
25788
|
import os26 from "os";
|
|
25884
25789
|
function memoryPath2() {
|
|
25885
|
-
return
|
|
25790
|
+
return path42.join(process.env.HOME || os26.homedir(), ".bluma", "coding_memory.json");
|
|
25886
25791
|
}
|
|
25887
25792
|
function normalizeNote2(note) {
|
|
25888
25793
|
return note.trim().toLowerCase().replace(/\s+/g, " ");
|
|
@@ -26444,16 +26349,16 @@ var BluMaToolRunner = class {
|
|
|
26444
26349
|
|
|
26445
26350
|
// src/app/agent/session_manager/session_archive.ts
|
|
26446
26351
|
init_bluma_app_dir();
|
|
26447
|
-
import
|
|
26352
|
+
import path43 from "path";
|
|
26448
26353
|
import { promises as fs39 } from "fs";
|
|
26449
26354
|
async function archivePrunedConversationMessages(sessionId, messages) {
|
|
26450
26355
|
if (!sessionId || messages.length === 0) {
|
|
26451
26356
|
return null;
|
|
26452
26357
|
}
|
|
26453
26358
|
const appDir = getPreferredAppDir();
|
|
26454
|
-
const dir =
|
|
26359
|
+
const dir = path43.join(appDir, "sessions", "archive", sessionId);
|
|
26455
26360
|
await fs39.mkdir(dir, { recursive: true });
|
|
26456
|
-
const archiveFile =
|
|
26361
|
+
const archiveFile = path43.join(dir, `${Date.now()}.jsonl`);
|
|
26457
26362
|
const lines = messages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
26458
26363
|
await fs39.appendFile(archiveFile, lines, "utf-8");
|
|
26459
26364
|
return archiveFile;
|
|
@@ -27207,7 +27112,7 @@ init_paths();
|
|
|
27207
27112
|
|
|
27208
27113
|
// src/app/agent/memory/memdir/memory_scan.ts
|
|
27209
27114
|
init_memoryTypes();
|
|
27210
|
-
import { readdir as readdir2, readFile as
|
|
27115
|
+
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
27211
27116
|
import { join as join12 } from "path";
|
|
27212
27117
|
var MAX_MEMORY_FILES = 200;
|
|
27213
27118
|
var FRONTMATTER_MAX_LINES = 30;
|
|
@@ -27249,7 +27154,7 @@ async function scanMemoryFiles(memoryDir, _signal) {
|
|
|
27249
27154
|
for (const relativePath of mdFiles) {
|
|
27250
27155
|
const filePath = join12(memoryDir, relativePath);
|
|
27251
27156
|
try {
|
|
27252
|
-
const raw = await
|
|
27157
|
+
const raw = await readFile4(filePath, "utf-8");
|
|
27253
27158
|
const head = raw.split("\n").slice(0, FRONTMATTER_MAX_LINES).join("\n");
|
|
27254
27159
|
const frontmatter = parseSimpleFrontmatter(head);
|
|
27255
27160
|
const st = await stat(filePath);
|
|
@@ -27316,7 +27221,7 @@ Update existing files instead of duplicating.` : "";
|
|
|
27316
27221
|
|
|
27317
27222
|
// src/app/agent/memory/memory_tool_policy.ts
|
|
27318
27223
|
init_paths();
|
|
27319
|
-
import
|
|
27224
|
+
import path44 from "path";
|
|
27320
27225
|
var MEMORY_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
27321
27226
|
"read_file_lines",
|
|
27322
27227
|
"grep_search",
|
|
@@ -27343,7 +27248,7 @@ function isReadOnlyShellCommand(command) {
|
|
|
27343
27248
|
return READ_ONLY_SHELL.test(trimmed);
|
|
27344
27249
|
}
|
|
27345
27250
|
function createAutoMemToolGate(memoryDir) {
|
|
27346
|
-
const memRoot = memoryDir.endsWith(
|
|
27251
|
+
const memRoot = memoryDir.endsWith(path44.sep) ? memoryDir : memoryDir + path44.sep;
|
|
27347
27252
|
return (toolName, args) => {
|
|
27348
27253
|
if (MEMORY_READ_TOOLS.has(toolName)) {
|
|
27349
27254
|
return { allowed: true };
|
|
@@ -27356,7 +27261,7 @@ function createAutoMemToolGate(memoryDir) {
|
|
|
27356
27261
|
}
|
|
27357
27262
|
if (MEMORY_WRITE_TOOLS.has(toolName)) {
|
|
27358
27263
|
const fp = extractFilePath(args);
|
|
27359
|
-
if (fp && isAutoMemPath(
|
|
27264
|
+
if (fp && isAutoMemPath(path44.resolve(fp))) {
|
|
27360
27265
|
return { allowed: true };
|
|
27361
27266
|
}
|
|
27362
27267
|
return { allowed: false, reason: `Writes must stay under ${memRoot}` };
|
|
@@ -27365,18 +27270,18 @@ function createAutoMemToolGate(memoryDir) {
|
|
|
27365
27270
|
};
|
|
27366
27271
|
}
|
|
27367
27272
|
function createSessionMemoryToolGate(sessionMemoryPath) {
|
|
27368
|
-
const resolvedTarget =
|
|
27273
|
+
const resolvedTarget = path44.resolve(sessionMemoryPath);
|
|
27369
27274
|
return (toolName, args) => {
|
|
27370
27275
|
if (toolName === "read_file_lines") {
|
|
27371
27276
|
const fp = extractFilePath(args);
|
|
27372
|
-
if (fp &&
|
|
27277
|
+
if (fp && path44.resolve(fp) === resolvedTarget) {
|
|
27373
27278
|
return { allowed: true };
|
|
27374
27279
|
}
|
|
27375
27280
|
return { allowed: false, reason: "Session memory subagent may only read the session summary file" };
|
|
27376
27281
|
}
|
|
27377
27282
|
if (toolName === "edit_tool") {
|
|
27378
27283
|
const fp = extractFilePath(args);
|
|
27379
|
-
if (fp &&
|
|
27284
|
+
if (fp && path44.resolve(fp) === resolvedTarget) {
|
|
27380
27285
|
return { allowed: true };
|
|
27381
27286
|
}
|
|
27382
27287
|
return { allowed: false, reason: "Session memory subagent may only edit the session summary file" };
|
|
@@ -27403,7 +27308,7 @@ function hasAutoMemWritesSinceHistory(history, sinceIndex) {
|
|
|
27403
27308
|
continue;
|
|
27404
27309
|
}
|
|
27405
27310
|
const fp = extractFilePath(args);
|
|
27406
|
-
if (fp && isAutoMemPath(
|
|
27311
|
+
if (fp && isAutoMemPath(path44.resolve(fp))) {
|
|
27407
27312
|
return true;
|
|
27408
27313
|
}
|
|
27409
27314
|
}
|
|
@@ -27622,7 +27527,7 @@ function scheduleExtractMemories(deps) {
|
|
|
27622
27527
|
|
|
27623
27528
|
// src/app/agent/memory/session_memory_update.ts
|
|
27624
27529
|
init_session_memory_paths();
|
|
27625
|
-
import { readFile as
|
|
27530
|
+
import { readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
27626
27531
|
|
|
27627
27532
|
// src/app/agent/memory/session_memory_prompts.ts
|
|
27628
27533
|
init_session_memory_paths();
|
|
@@ -27734,9 +27639,9 @@ async function runSessionMemoryUpdate(deps) {
|
|
|
27734
27639
|
const memoryPath3 = getSessionMemoryPath(sessionId);
|
|
27735
27640
|
let currentMemory = "";
|
|
27736
27641
|
try {
|
|
27737
|
-
currentMemory = await
|
|
27642
|
+
currentMemory = await readFile5(memoryPath3, "utf-8");
|
|
27738
27643
|
} catch {
|
|
27739
|
-
await
|
|
27644
|
+
await writeFile3(memoryPath3, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
|
|
27740
27645
|
`, "utf-8");
|
|
27741
27646
|
currentMemory = DEFAULT_SESSION_MEMORY_TEMPLATE;
|
|
27742
27647
|
}
|
|
@@ -27871,7 +27776,7 @@ var BluMaAgent = class {
|
|
|
27871
27776
|
if (!this.sessionFile) return;
|
|
27872
27777
|
try {
|
|
27873
27778
|
const sessionData = {
|
|
27874
|
-
session_id:
|
|
27779
|
+
session_id: path45.basename(this.sessionFile, ".json"),
|
|
27875
27780
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27876
27781
|
conversation_history: this.history,
|
|
27877
27782
|
last_updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -28083,7 +27988,7 @@ var BluMaAgent = class {
|
|
|
28083
27988
|
|
|
28084
27989
|
${editData.error.display}`;
|
|
28085
27990
|
}
|
|
28086
|
-
const filename =
|
|
27991
|
+
const filename = path45.basename(toolArgs.file_path);
|
|
28087
27992
|
return createDiff(filename, editData.currentContent || "", editData.newContent);
|
|
28088
27993
|
} catch (e) {
|
|
28089
27994
|
return `An unexpected error occurred while generating the edit preview: ${e.message}`;
|
|
@@ -28820,14 +28725,14 @@ async function fullCompact(messages, targetTokens, summarizer, llmClient) {
|
|
|
28820
28725
|
// src/app/agent/core/memory/session_memory.ts
|
|
28821
28726
|
import fs41 from "fs";
|
|
28822
28727
|
import os29 from "os";
|
|
28823
|
-
import
|
|
28728
|
+
import path46 from "path";
|
|
28824
28729
|
import { v4 as uuidv49 } from "uuid";
|
|
28825
28730
|
var SessionMemoryExtractor = class {
|
|
28826
28731
|
llmClient;
|
|
28827
28732
|
memoryFile;
|
|
28828
28733
|
constructor(options = {}) {
|
|
28829
28734
|
this.llmClient = options.llmClient;
|
|
28830
|
-
this.memoryFile = options.memoryFile ||
|
|
28735
|
+
this.memoryFile = options.memoryFile || path46.join(os29.homedir(), ".bluma", "session_memory.json");
|
|
28831
28736
|
}
|
|
28832
28737
|
/**
|
|
28833
28738
|
* Extract memories from conversation using LLM
|
|
@@ -29436,14 +29341,14 @@ var RouteManager = class {
|
|
|
29436
29341
|
this.subAgents = subAgents;
|
|
29437
29342
|
this.core = core;
|
|
29438
29343
|
}
|
|
29439
|
-
registerRoute(
|
|
29440
|
-
this.routeHandlers.set(
|
|
29344
|
+
registerRoute(path59, handler) {
|
|
29345
|
+
this.routeHandlers.set(path59, handler);
|
|
29441
29346
|
}
|
|
29442
29347
|
async handleRoute(payload) {
|
|
29443
29348
|
const inputText = String(payload.content || "").trim();
|
|
29444
29349
|
const { userContext, options } = payload;
|
|
29445
|
-
for (const [
|
|
29446
|
-
if (inputText ===
|
|
29350
|
+
for (const [path59, handler] of this.routeHandlers) {
|
|
29351
|
+
if (inputText === path59 || inputText.startsWith(`${path59} `)) {
|
|
29447
29352
|
return handler({ content: inputText, userContext });
|
|
29448
29353
|
}
|
|
29449
29354
|
}
|
|
@@ -29452,13 +29357,13 @@ var RouteManager = class {
|
|
|
29452
29357
|
};
|
|
29453
29358
|
|
|
29454
29359
|
// src/app/agent/runtime/plugin_runtime.ts
|
|
29455
|
-
import
|
|
29360
|
+
import path47 from "path";
|
|
29456
29361
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
29457
29362
|
async function loadPluginsAtStartup() {
|
|
29458
29363
|
for (const p of listPlugins()) {
|
|
29459
29364
|
const entry = p.manifest.entry?.trim();
|
|
29460
29365
|
if (!entry) continue;
|
|
29461
|
-
const abs =
|
|
29366
|
+
const abs = path47.resolve(p.root, entry);
|
|
29462
29367
|
try {
|
|
29463
29368
|
const href = pathToFileURL2(abs).href;
|
|
29464
29369
|
const mod = await import(href);
|
|
@@ -29479,7 +29384,7 @@ async function loadPluginsAtStartup() {
|
|
|
29479
29384
|
}
|
|
29480
29385
|
|
|
29481
29386
|
// src/app/agent/agent.ts
|
|
29482
|
-
var globalEnvPath =
|
|
29387
|
+
var globalEnvPath = path48.join(os30.homedir(), ".bluma", ".env");
|
|
29483
29388
|
dotenv.config({ path: globalEnvPath });
|
|
29484
29389
|
var Agent = class {
|
|
29485
29390
|
sessionId;
|
|
@@ -31335,10 +31240,10 @@ function resolveToolPayload(result) {
|
|
|
31335
31240
|
|
|
31336
31241
|
// src/app/ui/components/FilePathLink.tsx
|
|
31337
31242
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
31338
|
-
import
|
|
31243
|
+
import path50 from "node:path";
|
|
31339
31244
|
|
|
31340
31245
|
// src/app/ui/utils/pathDisplay.ts
|
|
31341
|
-
import
|
|
31246
|
+
import path49 from "node:path";
|
|
31342
31247
|
import os31 from "node:os";
|
|
31343
31248
|
function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
31344
31249
|
let s = String(pathInput ?? "").trim();
|
|
@@ -31346,17 +31251,17 @@ function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
|
31346
31251
|
s = s.replace(/[/\\]+$/, "");
|
|
31347
31252
|
}
|
|
31348
31253
|
if (!s) return "";
|
|
31349
|
-
const abs =
|
|
31350
|
-
const resolvedCwd =
|
|
31351
|
-
const rel =
|
|
31352
|
-
if (rel === "" || !rel.startsWith("..") && !
|
|
31254
|
+
const abs = path49.isAbsolute(s) ? path49.normalize(s) : path49.resolve(cwd2, s);
|
|
31255
|
+
const resolvedCwd = path49.resolve(cwd2);
|
|
31256
|
+
const rel = path49.relative(resolvedCwd, abs);
|
|
31257
|
+
if (rel === "" || !rel.startsWith("..") && !path49.isAbsolute(rel)) {
|
|
31353
31258
|
return rel === "" ? "." : rel;
|
|
31354
31259
|
}
|
|
31355
|
-
const home =
|
|
31356
|
-
if (abs === home || abs.startsWith(home +
|
|
31260
|
+
const home = path49.normalize(os31.homedir());
|
|
31261
|
+
if (abs === home || abs.startsWith(home + path49.sep)) {
|
|
31357
31262
|
return "~" + abs.slice(home.length);
|
|
31358
31263
|
}
|
|
31359
|
-
return
|
|
31264
|
+
return path49.basename(abs);
|
|
31360
31265
|
}
|
|
31361
31266
|
|
|
31362
31267
|
// src/app/ui/components/FilePathLink.tsx
|
|
@@ -31366,7 +31271,7 @@ function FilePathLink({ filePath, children, cwd: cwd2 = process.cwd(), color })
|
|
|
31366
31271
|
if (!raw) {
|
|
31367
31272
|
return null;
|
|
31368
31273
|
}
|
|
31369
|
-
const abs =
|
|
31274
|
+
const abs = path50.isAbsolute(raw) ? path50.normalize(raw) : path50.resolve(cwd2, raw);
|
|
31370
31275
|
const href = pathToFileURL3(abs).href;
|
|
31371
31276
|
const label = formatPathForDisplay(abs, cwd2);
|
|
31372
31277
|
const text = typeof children === "string" ? children : label;
|
|
@@ -34001,13 +33906,13 @@ function EditToolDiffPanel({
|
|
|
34001
33906
|
newString,
|
|
34002
33907
|
replaceAll = false
|
|
34003
33908
|
}) {
|
|
34004
|
-
const
|
|
33909
|
+
const path59 = filePath.trim() || "unknown file";
|
|
34005
33910
|
const hasPreviewArgs = oldString !== void 0 && newString !== void 0;
|
|
34006
33911
|
const hasDiffText = diffText && diffText.trim().length > 0;
|
|
34007
33912
|
return /* @__PURE__ */ jsx43(Box_default, { flexDirection: "column", children: hasPreviewArgs ? /* @__PURE__ */ jsx43(Box_default, { marginTop: 0, children: /* @__PURE__ */ jsx43(
|
|
34008
33913
|
FileEditToolDiff,
|
|
34009
33914
|
{
|
|
34010
|
-
filePath:
|
|
33915
|
+
filePath: path59,
|
|
34011
33916
|
oldString,
|
|
34012
33917
|
newString,
|
|
34013
33918
|
replaceAll,
|
|
@@ -34045,7 +33950,7 @@ function renderToolUseMessage12({ args }) {
|
|
|
34045
33950
|
return /* @__PURE__ */ jsx44(Text, { color: BLUMA_TERMINAL.blue, children: p });
|
|
34046
33951
|
}
|
|
34047
33952
|
function renderToolHeader12({ args }) {
|
|
34048
|
-
const
|
|
33953
|
+
const path59 = args?.file_path ?? ".";
|
|
34049
33954
|
const oldText = typeof args?.old_string === "string" ? args.old_string : "";
|
|
34050
33955
|
const newText = typeof args?.new_string === "string" ? args.new_string : "";
|
|
34051
33956
|
const counts = countLineDiff(oldText, newText);
|
|
@@ -34055,7 +33960,7 @@ function renderToolHeader12({ args }) {
|
|
|
34055
33960
|
action,
|
|
34056
33961
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
34057
33962
|
" ",
|
|
34058
|
-
/* @__PURE__ */ jsx44(FilePathLink, { filePath:
|
|
33963
|
+
/* @__PURE__ */ jsx44(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
|
|
34059
33964
|
] })
|
|
34060
33965
|
] }),
|
|
34061
33966
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
@@ -34447,11 +34352,11 @@ function userFacingName13() {
|
|
|
34447
34352
|
}
|
|
34448
34353
|
function renderToolUseMessage14({ args }) {
|
|
34449
34354
|
const q = args?.query ? `"${args.query}"` : "...";
|
|
34450
|
-
const
|
|
34355
|
+
const path59 = args?.path || ".";
|
|
34451
34356
|
return /* @__PURE__ */ jsxs30(Box_default, { flexDirection: "row", flexWrap: "wrap", alignItems: "flex-end", children: [
|
|
34452
34357
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.blue, children: q }),
|
|
34453
34358
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.dim, children: " " }),
|
|
34454
|
-
/* @__PURE__ */ jsx47(FilePathLink, { filePath:
|
|
34359
|
+
/* @__PURE__ */ jsx47(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
|
|
34455
34360
|
] });
|
|
34456
34361
|
}
|
|
34457
34362
|
function renderToolHeader14({ args }) {
|
|
@@ -37931,7 +37836,7 @@ import {
|
|
|
37931
37836
|
// src/app/ui/hooks/useAtCompletion.ts
|
|
37932
37837
|
import { useEffect as useEffect11, useRef as useRef4, useState as useState13 } from "react";
|
|
37933
37838
|
import fs44 from "fs";
|
|
37934
|
-
import
|
|
37839
|
+
import path51 from "path";
|
|
37935
37840
|
var MAX_RESULTS3 = 50;
|
|
37936
37841
|
var DEFAULT_RECURSIVE_DEPTH = 2;
|
|
37937
37842
|
function listPathSuggestions(baseDir, pattern) {
|
|
@@ -37939,7 +37844,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37939
37844
|
const patternEndsWithSlash = raw.endsWith("/");
|
|
37940
37845
|
const relDir = raw.replace(/^\/+|\/+$/g, "");
|
|
37941
37846
|
const filterPrefix = patternEndsWithSlash ? "" : relDir.split("/").slice(-1)[0] || "";
|
|
37942
|
-
const listDir =
|
|
37847
|
+
const listDir = path51.resolve(baseDir, relDir || ".");
|
|
37943
37848
|
const results = [];
|
|
37944
37849
|
const IGNORED_DIRS = ["node_modules", ".git", ".venv", "dist", "build"];
|
|
37945
37850
|
const IGNORED_EXTS = [".pyc", ".class", ".o", ".map", ".log", ".tmp"];
|
|
@@ -37956,7 +37861,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37956
37861
|
}
|
|
37957
37862
|
function pushEntry(entryPath, label, isDir) {
|
|
37958
37863
|
if (results.length >= MAX_RESULTS3) return;
|
|
37959
|
-
const clean = label.split(
|
|
37864
|
+
const clean = label.split(path51.sep).join("/").replace(/[]+/g, "");
|
|
37960
37865
|
results.push({ label: clean + (isDir ? "/" : ""), fullPath: entryPath, isDir });
|
|
37961
37866
|
}
|
|
37962
37867
|
try {
|
|
@@ -37968,8 +37873,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37968
37873
|
const entries = fs44.readdirSync(node.dir, { withFileTypes: true });
|
|
37969
37874
|
for (const entry of entries) {
|
|
37970
37875
|
if (isIgnoredName(entry.name)) continue;
|
|
37971
|
-
const entryAbs =
|
|
37972
|
-
const entryRel = node.rel ?
|
|
37876
|
+
const entryAbs = path51.join(node.dir, entry.name);
|
|
37877
|
+
const entryRel = node.rel ? path51.posix.join(node.rel, entry.name) : entry.name;
|
|
37973
37878
|
if (entryRel.split("/").includes("node_modules")) continue;
|
|
37974
37879
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
37975
37880
|
pushEntry(entryAbs, entryRel, entry.isDirectory());
|
|
@@ -37987,8 +37892,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
37987
37892
|
if (filterPrefix && !entry.name.startsWith(filterPrefix)) continue;
|
|
37988
37893
|
if (isIgnoredName(entry.name)) continue;
|
|
37989
37894
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
37990
|
-
const entryAbs =
|
|
37991
|
-
const label = relDir ?
|
|
37895
|
+
const entryAbs = path51.join(listDir, entry.name);
|
|
37896
|
+
const label = relDir ? path51.posix.join(relDir, entry.name) : entry.name;
|
|
37992
37897
|
pushEntry(entryAbs, label, entry.isDirectory());
|
|
37993
37898
|
if (results.length >= MAX_RESULTS3) break;
|
|
37994
37899
|
}
|
|
@@ -38191,7 +38096,7 @@ var SlashSubmenuInline = memo15(SlashSubmenuInlineComponent);
|
|
|
38191
38096
|
// src/app/ui/utils/clipboardImage.ts
|
|
38192
38097
|
import fs45 from "fs";
|
|
38193
38098
|
import os32 from "os";
|
|
38194
|
-
import
|
|
38099
|
+
import path52 from "path";
|
|
38195
38100
|
import { spawn as spawn5, execFile as execFileCb, execSync as execSync4 } from "child_process";
|
|
38196
38101
|
import { promisify as promisify2 } from "util";
|
|
38197
38102
|
|
|
@@ -38320,8 +38225,8 @@ function commandOnPath(cmd) {
|
|
|
38320
38225
|
function unixClipboardHelperDirs() {
|
|
38321
38226
|
const h = os32.homedir();
|
|
38322
38227
|
return [
|
|
38323
|
-
|
|
38324
|
-
|
|
38228
|
+
path52.join(h, ".local", "bin"),
|
|
38229
|
+
path52.join(h, "bin"),
|
|
38325
38230
|
"/usr/bin",
|
|
38326
38231
|
"/usr/local/bin",
|
|
38327
38232
|
"/bin",
|
|
@@ -38339,7 +38244,7 @@ function resolveHelperBinary(cmd) {
|
|
|
38339
38244
|
return cmd;
|
|
38340
38245
|
}
|
|
38341
38246
|
for (const dir of unixClipboardHelperDirs()) {
|
|
38342
|
-
const full =
|
|
38247
|
+
const full = path52.join(dir, cmd);
|
|
38343
38248
|
try {
|
|
38344
38249
|
fs45.accessSync(full, fs45.constants.X_OK);
|
|
38345
38250
|
return full;
|
|
@@ -38347,7 +38252,7 @@ function resolveHelperBinary(cmd) {
|
|
|
38347
38252
|
}
|
|
38348
38253
|
}
|
|
38349
38254
|
for (const dir of unixClipboardHelperDirs()) {
|
|
38350
|
-
const full =
|
|
38255
|
+
const full = path52.join(dir, cmd);
|
|
38351
38256
|
if (fs45.existsSync(full)) {
|
|
38352
38257
|
return full;
|
|
38353
38258
|
}
|
|
@@ -38389,7 +38294,7 @@ function writeBufferIfImage(baseDir, buf) {
|
|
|
38389
38294
|
if (!ext) {
|
|
38390
38295
|
return null;
|
|
38391
38296
|
}
|
|
38392
|
-
const out =
|
|
38297
|
+
const out = path52.join(
|
|
38393
38298
|
baseDir,
|
|
38394
38299
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
38395
38300
|
);
|
|
@@ -38428,9 +38333,9 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
38428
38333
|
if (st.size < 80 || st.size > CLIPBOARD_MAX_BYTES) {
|
|
38429
38334
|
continue;
|
|
38430
38335
|
}
|
|
38431
|
-
const ext =
|
|
38336
|
+
const ext = path52.extname(src).toLowerCase();
|
|
38432
38337
|
const safeExt = ext && /^\.(png|jpe?g|gif|webp)$/i.test(ext) ? ext : ".png";
|
|
38433
|
-
const out =
|
|
38338
|
+
const out = path52.join(
|
|
38434
38339
|
baseDir,
|
|
38435
38340
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${safeExt}`
|
|
38436
38341
|
);
|
|
@@ -38448,7 +38353,7 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
38448
38353
|
return null;
|
|
38449
38354
|
}
|
|
38450
38355
|
async function tryWindowsPowerShell(outFile) {
|
|
38451
|
-
const ps = process.env.SystemRoot != null ?
|
|
38356
|
+
const ps = process.env.SystemRoot != null ? path52.join(
|
|
38452
38357
|
process.env.SystemRoot,
|
|
38453
38358
|
"System32",
|
|
38454
38359
|
"WindowsPowerShell",
|
|
@@ -38549,8 +38454,8 @@ function parseClipboardTextAsImagePath(raw) {
|
|
|
38549
38454
|
s = s.slice(1, -1);
|
|
38550
38455
|
}
|
|
38551
38456
|
s = s.trim();
|
|
38552
|
-
if (!CLIPBOARD_PATH_IMAGE_EXT.test(
|
|
38553
|
-
const abs =
|
|
38457
|
+
if (!CLIPBOARD_PATH_IMAGE_EXT.test(path52.extname(s))) return null;
|
|
38458
|
+
const abs = path52.isAbsolute(s) ? path52.normalize(s) : path52.resolve(process.cwd(), s);
|
|
38554
38459
|
return abs;
|
|
38555
38460
|
}
|
|
38556
38461
|
async function tryClipboardTextAsImageFile(baseDir) {
|
|
@@ -38570,8 +38475,8 @@ async function tryClipboardTextAsImageFile(baseDir) {
|
|
|
38570
38475
|
} catch {
|
|
38571
38476
|
return null;
|
|
38572
38477
|
}
|
|
38573
|
-
const ext =
|
|
38574
|
-
const out =
|
|
38478
|
+
const ext = path52.extname(abs).toLowerCase();
|
|
38479
|
+
const out = path52.join(
|
|
38575
38480
|
baseDir,
|
|
38576
38481
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
38577
38482
|
);
|
|
@@ -38586,7 +38491,7 @@ async function tryLinuxShellPipelineSave(baseDir) {
|
|
|
38586
38491
|
if (process.platform !== "linux" && process.platform !== "freebsd") {
|
|
38587
38492
|
return null;
|
|
38588
38493
|
}
|
|
38589
|
-
const outPath =
|
|
38494
|
+
const outPath = path52.join(
|
|
38590
38495
|
baseDir,
|
|
38591
38496
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
38592
38497
|
);
|
|
@@ -38644,7 +38549,7 @@ async function tryNativeClipboardImage() {
|
|
|
38644
38549
|
return null;
|
|
38645
38550
|
}
|
|
38646
38551
|
async function readClipboardImageToTempFile() {
|
|
38647
|
-
const baseDir =
|
|
38552
|
+
const baseDir = path52.join(os32.homedir(), ".cache", "bluma", "clipboard");
|
|
38648
38553
|
fs45.mkdirSync(baseDir, { recursive: true });
|
|
38649
38554
|
const nativeResult = await tryNativeClipboardImage();
|
|
38650
38555
|
if (nativeResult) {
|
|
@@ -38663,7 +38568,7 @@ async function readClipboardImageToTempFile() {
|
|
|
38663
38568
|
}
|
|
38664
38569
|
}
|
|
38665
38570
|
if (process.platform === "win32") {
|
|
38666
|
-
const outFile =
|
|
38571
|
+
const outFile = path52.join(
|
|
38667
38572
|
baseDir,
|
|
38668
38573
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.png`
|
|
38669
38574
|
);
|
|
@@ -41039,7 +40944,7 @@ var renderSettingsEditUsage = () => {
|
|
|
41039
40944
|
|
|
41040
40945
|
// src/app/agent/core/thread/thread_store.ts
|
|
41041
40946
|
init_bluma_app_dir();
|
|
41042
|
-
import
|
|
40947
|
+
import path53 from "path";
|
|
41043
40948
|
import { promises as fs47 } from "fs";
|
|
41044
40949
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
41045
40950
|
var INDEX_VERSION = 1;
|
|
@@ -41065,9 +40970,9 @@ var ThreadStore = class {
|
|
|
41065
40970
|
packageVersion;
|
|
41066
40971
|
constructor() {
|
|
41067
40972
|
const appDir = getPreferredAppDir();
|
|
41068
|
-
this.threadsDir =
|
|
41069
|
-
this.archiveDir =
|
|
41070
|
-
this.indexPath =
|
|
40973
|
+
this.threadsDir = path53.join(appDir, "threads");
|
|
40974
|
+
this.archiveDir = path53.join(this.threadsDir, "archive");
|
|
40975
|
+
this.indexPath = path53.join(this.threadsDir, "index.json");
|
|
41071
40976
|
this.packageVersion = process.env.npm_package_version || "0.0.0";
|
|
41072
40977
|
}
|
|
41073
40978
|
// ==================== Inicialização ====================
|
|
@@ -41189,7 +41094,7 @@ var ThreadStore = class {
|
|
|
41189
41094
|
messages: params.initialMessages || []
|
|
41190
41095
|
};
|
|
41191
41096
|
const historyPath = this.buildDatedThreadHistoryPath(threadId);
|
|
41192
|
-
await fs47.mkdir(
|
|
41097
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
|
|
41193
41098
|
await this.saveHistoryAtPath(historyPath, history);
|
|
41194
41099
|
const index = await this.loadIndex();
|
|
41195
41100
|
index.threads.unshift({
|
|
@@ -41244,7 +41149,7 @@ var ThreadStore = class {
|
|
|
41244
41149
|
compressedSliceCount: source.history.compressedSliceCount
|
|
41245
41150
|
};
|
|
41246
41151
|
const historyPath = this.buildDatedThreadHistoryPath(newThreadId);
|
|
41247
|
-
await fs47.mkdir(
|
|
41152
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
|
|
41248
41153
|
await this.saveHistoryAtPath(historyPath, history);
|
|
41249
41154
|
const index = await this.loadIndex();
|
|
41250
41155
|
index.threads.unshift({
|
|
@@ -41317,7 +41222,7 @@ var ThreadStore = class {
|
|
|
41317
41222
|
const entry = index.threads[entryIndex];
|
|
41318
41223
|
if (entry.status === "archived") return true;
|
|
41319
41224
|
const oldPath = entry.historyPath || this.getLegacyHistoryPath(threadId);
|
|
41320
|
-
const newPath =
|
|
41225
|
+
const newPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
|
|
41321
41226
|
try {
|
|
41322
41227
|
await fs47.rename(oldPath, newPath);
|
|
41323
41228
|
} catch (e) {
|
|
@@ -41340,9 +41245,9 @@ var ThreadStore = class {
|
|
|
41340
41245
|
if (entryIndex === -1) return false;
|
|
41341
41246
|
const entry = index.threads[entryIndex];
|
|
41342
41247
|
if (entry.status === "active") return true;
|
|
41343
|
-
const oldPath =
|
|
41248
|
+
const oldPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
|
|
41344
41249
|
const newPath = this.buildDatedThreadHistoryPath(threadId);
|
|
41345
|
-
await fs47.mkdir(
|
|
41250
|
+
await fs47.mkdir(path53.dirname(newPath), { recursive: true });
|
|
41346
41251
|
try {
|
|
41347
41252
|
await fs47.rename(oldPath, newPath);
|
|
41348
41253
|
} catch (e) {
|
|
@@ -41375,14 +41280,14 @@ var ThreadStore = class {
|
|
|
41375
41280
|
}
|
|
41376
41281
|
// ==================== Histórico ====================
|
|
41377
41282
|
getLegacyHistoryPath(threadId) {
|
|
41378
|
-
return
|
|
41283
|
+
return path53.join(this.threadsDir, `${threadId}.jsonl`);
|
|
41379
41284
|
}
|
|
41380
41285
|
/** ~/.bluma/threads/YYYY/MM/DD/<threadId>.jsonl (data local de criação). */
|
|
41381
41286
|
buildDatedThreadHistoryPath(threadId, at = /* @__PURE__ */ new Date()) {
|
|
41382
41287
|
const y = String(at.getFullYear());
|
|
41383
41288
|
const mo = String(at.getMonth() + 1).padStart(2, "0");
|
|
41384
41289
|
const d = String(at.getDate()).padStart(2, "0");
|
|
41385
|
-
return
|
|
41290
|
+
return path53.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
|
|
41386
41291
|
}
|
|
41387
41292
|
async resolveHistoryPath(threadId) {
|
|
41388
41293
|
const index = await this.loadIndex();
|
|
@@ -41413,7 +41318,7 @@ var ThreadStore = class {
|
|
|
41413
41318
|
for (const msg of history.messages) {
|
|
41414
41319
|
lines.push(JSON.stringify({ type: "message", ...msg }));
|
|
41415
41320
|
}
|
|
41416
|
-
await fs47.mkdir(
|
|
41321
|
+
await fs47.mkdir(path53.dirname(historyPath), { recursive: true }).catch(() => {
|
|
41417
41322
|
});
|
|
41418
41323
|
await fs47.writeFile(historyPath, lines.join("\n") + "\n", "utf-8");
|
|
41419
41324
|
}
|
|
@@ -43909,13 +43814,13 @@ import latestVersion from "latest-version";
|
|
|
43909
43814
|
import semverGt from "semver/functions/gt.js";
|
|
43910
43815
|
import semverValid from "semver/functions/valid.js";
|
|
43911
43816
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
43912
|
-
import
|
|
43817
|
+
import path55 from "path";
|
|
43913
43818
|
import fs49 from "fs";
|
|
43914
43819
|
var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
|
|
43915
43820
|
function findBlumaPackageJson(startDir) {
|
|
43916
43821
|
let dir = startDir;
|
|
43917
43822
|
for (let i = 0; i < 12; i++) {
|
|
43918
|
-
const candidate =
|
|
43823
|
+
const candidate = path55.join(dir, "package.json");
|
|
43919
43824
|
if (fs49.existsSync(candidate)) {
|
|
43920
43825
|
try {
|
|
43921
43826
|
const raw = fs49.readFileSync(candidate, "utf8");
|
|
@@ -43926,7 +43831,7 @@ function findBlumaPackageJson(startDir) {
|
|
|
43926
43831
|
} catch {
|
|
43927
43832
|
}
|
|
43928
43833
|
}
|
|
43929
|
-
const parent =
|
|
43834
|
+
const parent = path55.dirname(dir);
|
|
43930
43835
|
if (parent === dir) break;
|
|
43931
43836
|
dir = parent;
|
|
43932
43837
|
}
|
|
@@ -43935,13 +43840,13 @@ function findBlumaPackageJson(startDir) {
|
|
|
43935
43840
|
function resolveInstalledBlumaPackage() {
|
|
43936
43841
|
const tried = /* @__PURE__ */ new Set();
|
|
43937
43842
|
const tryFrom = (dir) => {
|
|
43938
|
-
const abs =
|
|
43843
|
+
const abs = path55.resolve(dir);
|
|
43939
43844
|
if (tried.has(abs)) return null;
|
|
43940
43845
|
tried.add(abs);
|
|
43941
43846
|
return findBlumaPackageJson(abs);
|
|
43942
43847
|
};
|
|
43943
43848
|
try {
|
|
43944
|
-
const fromBundle = tryFrom(
|
|
43849
|
+
const fromBundle = tryFrom(path55.dirname(fileURLToPath7(import.meta.url)));
|
|
43945
43850
|
if (fromBundle) return fromBundle;
|
|
43946
43851
|
} catch {
|
|
43947
43852
|
}
|
|
@@ -43949,12 +43854,12 @@ function resolveInstalledBlumaPackage() {
|
|
|
43949
43854
|
if (argv1 && !argv1.startsWith("-")) {
|
|
43950
43855
|
try {
|
|
43951
43856
|
let resolved = argv1;
|
|
43952
|
-
if (
|
|
43857
|
+
if (path55.isAbsolute(argv1) && fs49.existsSync(argv1)) {
|
|
43953
43858
|
resolved = fs49.realpathSync(argv1);
|
|
43954
43859
|
} else {
|
|
43955
|
-
resolved =
|
|
43860
|
+
resolved = path55.resolve(process.cwd(), argv1);
|
|
43956
43861
|
}
|
|
43957
|
-
const fromArgv = tryFrom(
|
|
43862
|
+
const fromArgv = tryFrom(path55.dirname(resolved));
|
|
43958
43863
|
if (fromArgv) return fromArgv;
|
|
43959
43864
|
} catch {
|
|
43960
43865
|
}
|
|
@@ -44774,9 +44679,9 @@ function usePlanMode() {
|
|
|
44774
44679
|
// src/app/hooks/useAgentMode.ts
|
|
44775
44680
|
import { useState as useState22, useEffect as useEffect21, useCallback as useCallback9 } from "react";
|
|
44776
44681
|
import * as fs50 from "fs";
|
|
44777
|
-
import * as
|
|
44682
|
+
import * as path56 from "path";
|
|
44778
44683
|
import { homedir as homedir4 } from "os";
|
|
44779
|
-
var SETTINGS_PATH =
|
|
44684
|
+
var SETTINGS_PATH = path56.join(homedir4(), ".bluma", "settings.json");
|
|
44780
44685
|
function readAgentModeFromFile() {
|
|
44781
44686
|
try {
|
|
44782
44687
|
if (!fs50.existsSync(SETTINGS_PATH)) {
|
|
@@ -44802,7 +44707,7 @@ function useAgentMode() {
|
|
|
44802
44707
|
const updateAgentMode = useCallback9((mode) => {
|
|
44803
44708
|
try {
|
|
44804
44709
|
if (!fs50.existsSync(SETTINGS_PATH)) {
|
|
44805
|
-
fs50.mkdirSync(
|
|
44710
|
+
fs50.mkdirSync(path56.dirname(SETTINGS_PATH), { recursive: true });
|
|
44806
44711
|
}
|
|
44807
44712
|
let settings = {};
|
|
44808
44713
|
if (fs50.existsSync(SETTINGS_PATH)) {
|
|
@@ -46074,10 +45979,10 @@ import { memo as memo26, useCallback as useCallback11, useEffect as useEffect23,
|
|
|
46074
45979
|
|
|
46075
45980
|
// src/app/agent/session_manager/session_resume_browser.ts
|
|
46076
45981
|
init_bluma_app_dir();
|
|
46077
|
-
import
|
|
45982
|
+
import path57 from "path";
|
|
46078
45983
|
import { promises as fs51 } from "fs";
|
|
46079
45984
|
function getSessionsRoot() {
|
|
46080
|
-
return
|
|
45985
|
+
return path57.join(getPreferredAppDir(), "sessions");
|
|
46081
45986
|
}
|
|
46082
45987
|
function normalizeSessionsCwd(cwd2) {
|
|
46083
45988
|
return cwd2.replace(/\\/g, "/").split("/").filter((p) => p && p !== "." && p !== "..").join("/");
|
|
@@ -46128,7 +46033,7 @@ function compareDirNames(a, b) {
|
|
|
46128
46033
|
async function listSessionBrowserEntries(cwdRel) {
|
|
46129
46034
|
const cwd2 = normalizeSessionsCwd(cwdRel);
|
|
46130
46035
|
const root = getSessionsRoot();
|
|
46131
|
-
const absDir = cwd2 ?
|
|
46036
|
+
const absDir = cwd2 ? path57.join(root, ...cwd2.split("/")) : root;
|
|
46132
46037
|
const out = [];
|
|
46133
46038
|
if (cwd2) {
|
|
46134
46039
|
out.push({ kind: "up", label: ".." });
|
|
@@ -46145,7 +46050,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
46145
46050
|
for (const e of dirents) {
|
|
46146
46051
|
const name = String(e.name);
|
|
46147
46052
|
if (name.startsWith(".")) continue;
|
|
46148
|
-
const full =
|
|
46053
|
+
const full = path57.join(absDir, name);
|
|
46149
46054
|
if (e.isDirectory()) {
|
|
46150
46055
|
dirNames.push(name);
|
|
46151
46056
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -46155,7 +46060,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
46155
46060
|
dirNames.sort(compareDirNames);
|
|
46156
46061
|
const sessions = [];
|
|
46157
46062
|
for (const { name, full } of sessionFiles) {
|
|
46158
|
-
const sessionId =
|
|
46063
|
+
const sessionId = path57.basename(name, ".json");
|
|
46159
46064
|
sessions.push(await sessionEntryFromFile(full, sessionId));
|
|
46160
46065
|
}
|
|
46161
46066
|
sessions.sort((a, b) => {
|
|
@@ -46763,8 +46668,8 @@ async function runAgentMode() {
|
|
|
46763
46668
|
}
|
|
46764
46669
|
function readCliPackageVersion() {
|
|
46765
46670
|
try {
|
|
46766
|
-
const base =
|
|
46767
|
-
const pkgPath =
|
|
46671
|
+
const base = path58.dirname(fileURLToPath8(import.meta.url));
|
|
46672
|
+
const pkgPath = path58.join(base, "..", "package.json");
|
|
46768
46673
|
const j = JSON.parse(fs52.readFileSync(pkgPath, "utf8"));
|
|
46769
46674
|
return String(j.version || "0.0.0");
|
|
46770
46675
|
} catch {
|