@nomad-e/bluma-cli 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +393 -337
- package/package.json +2 -1
package/dist/main.js
CHANGED
|
@@ -2201,11 +2201,11 @@ var NodeFsOperations = {
|
|
|
2201
2201
|
if (fd) fs.closeSync(fd);
|
|
2202
2202
|
}
|
|
2203
2203
|
},
|
|
2204
|
-
appendFileSync(
|
|
2205
|
-
const _ = slowLogging`fs.appendFileSync(${
|
|
2204
|
+
appendFileSync(path57, data, options) {
|
|
2205
|
+
const _ = slowLogging`fs.appendFileSync(${path57}, ${data.length} chars)`;
|
|
2206
2206
|
if (options?.mode !== void 0) {
|
|
2207
2207
|
try {
|
|
2208
|
-
const fd = fs.openSync(
|
|
2208
|
+
const fd = fs.openSync(path57, "ax", options.mode);
|
|
2209
2209
|
try {
|
|
2210
2210
|
fs.appendFileSync(fd, data);
|
|
2211
2211
|
} finally {
|
|
@@ -2216,35 +2216,35 @@ var NodeFsOperations = {
|
|
|
2216
2216
|
if (getErrnoCode(e) !== "EEXIST") throw e;
|
|
2217
2217
|
}
|
|
2218
2218
|
}
|
|
2219
|
-
fs.appendFileSync(
|
|
2219
|
+
fs.appendFileSync(path57, data);
|
|
2220
2220
|
},
|
|
2221
2221
|
copyFileSync(src, dest) {
|
|
2222
2222
|
const _ = slowLogging`fs.copyFileSync(${src} → ${dest})`;
|
|
2223
2223
|
fs.copyFileSync(src, dest);
|
|
2224
2224
|
},
|
|
2225
|
-
unlinkSync(
|
|
2226
|
-
const _ = slowLogging`fs.unlinkSync(${
|
|
2227
|
-
fs.unlinkSync(
|
|
2225
|
+
unlinkSync(path57) {
|
|
2226
|
+
const _ = slowLogging`fs.unlinkSync(${path57})`;
|
|
2227
|
+
fs.unlinkSync(path57);
|
|
2228
2228
|
},
|
|
2229
2229
|
renameSync(oldPath, newPath) {
|
|
2230
2230
|
const _ = slowLogging`fs.renameSync(${oldPath} → ${newPath})`;
|
|
2231
2231
|
fs.renameSync(oldPath, newPath);
|
|
2232
2232
|
},
|
|
2233
|
-
linkSync(target,
|
|
2234
|
-
const _ = slowLogging`fs.linkSync(${target} → ${
|
|
2235
|
-
fs.linkSync(target,
|
|
2233
|
+
linkSync(target, path57) {
|
|
2234
|
+
const _ = slowLogging`fs.linkSync(${target} → ${path57})`;
|
|
2235
|
+
fs.linkSync(target, path57);
|
|
2236
2236
|
},
|
|
2237
|
-
symlinkSync(target,
|
|
2238
|
-
const _ = slowLogging`fs.symlinkSync(${target} → ${
|
|
2239
|
-
fs.symlinkSync(target,
|
|
2237
|
+
symlinkSync(target, path57, type) {
|
|
2238
|
+
const _ = slowLogging`fs.symlinkSync(${target} → ${path57})`;
|
|
2239
|
+
fs.symlinkSync(target, path57, type);
|
|
2240
2240
|
},
|
|
2241
|
-
readlinkSync(
|
|
2242
|
-
const _ = slowLogging`fs.readlinkSync(${
|
|
2243
|
-
return fs.readlinkSync(
|
|
2241
|
+
readlinkSync(path57) {
|
|
2242
|
+
const _ = slowLogging`fs.readlinkSync(${path57})`;
|
|
2243
|
+
return fs.readlinkSync(path57);
|
|
2244
2244
|
},
|
|
2245
|
-
realpathSync(
|
|
2246
|
-
const _ = slowLogging`fs.realpathSync(${
|
|
2247
|
-
return fs.realpathSync(
|
|
2245
|
+
realpathSync(path57) {
|
|
2246
|
+
const _ = slowLogging`fs.realpathSync(${path57})`;
|
|
2247
|
+
return fs.realpathSync(path57).normalize("NFC");
|
|
2248
2248
|
},
|
|
2249
2249
|
mkdirSync(dirPath, options) {
|
|
2250
2250
|
const _ = slowLogging`fs.mkdirSync(${dirPath})`;
|
|
@@ -2277,12 +2277,12 @@ var NodeFsOperations = {
|
|
|
2277
2277
|
const _ = slowLogging`fs.rmdirSync(${dirPath})`;
|
|
2278
2278
|
fs.rmdirSync(dirPath);
|
|
2279
2279
|
},
|
|
2280
|
-
rmSync(
|
|
2281
|
-
const _ = slowLogging`fs.rmSync(${
|
|
2282
|
-
fs.rmSync(
|
|
2280
|
+
rmSync(path57, options) {
|
|
2281
|
+
const _ = slowLogging`fs.rmSync(${path57})`;
|
|
2282
|
+
fs.rmSync(path57, options);
|
|
2283
2283
|
},
|
|
2284
|
-
createWriteStream(
|
|
2285
|
-
return fs.createWriteStream(
|
|
2284
|
+
createWriteStream(path57) {
|
|
2285
|
+
return fs.createWriteStream(path57);
|
|
2286
2286
|
},
|
|
2287
2287
|
async readFileBytes(fsPath, maxBytes) {
|
|
2288
2288
|
if (maxBytes === void 0) {
|
|
@@ -2389,12 +2389,12 @@ function shouldLogDebugMessage(message2) {
|
|
|
2389
2389
|
var hasFormattedOutput = false;
|
|
2390
2390
|
var debugWriter = null;
|
|
2391
2391
|
var pendingWrite = Promise.resolve();
|
|
2392
|
-
async function appendAsync(needMkdir, dir,
|
|
2392
|
+
async function appendAsync(needMkdir, dir, path57, content) {
|
|
2393
2393
|
if (needMkdir) {
|
|
2394
2394
|
await mkdir(dir, { recursive: true }).catch(() => {
|
|
2395
2395
|
});
|
|
2396
2396
|
}
|
|
2397
|
-
await appendFile(
|
|
2397
|
+
await appendFile(path57, content);
|
|
2398
2398
|
void updateLatestDebugLogSymlink();
|
|
2399
2399
|
}
|
|
2400
2400
|
function noop() {
|
|
@@ -2404,8 +2404,8 @@ function getDebugWriter() {
|
|
|
2404
2404
|
let ensuredDir = null;
|
|
2405
2405
|
debugWriter = createBufferedWriter({
|
|
2406
2406
|
writeFn: (content) => {
|
|
2407
|
-
const
|
|
2408
|
-
const dir = dirname(
|
|
2407
|
+
const path57 = getDebugLogPath();
|
|
2408
|
+
const dir = dirname(path57);
|
|
2409
2409
|
const needMkdir = ensuredDir !== dir;
|
|
2410
2410
|
ensuredDir = dir;
|
|
2411
2411
|
if (isDebugMode()) {
|
|
@@ -2415,11 +2415,11 @@ function getDebugWriter() {
|
|
|
2415
2415
|
} catch {
|
|
2416
2416
|
}
|
|
2417
2417
|
}
|
|
2418
|
-
getFsImplementation().appendFileSync(
|
|
2418
|
+
getFsImplementation().appendFileSync(path57, content);
|
|
2419
2419
|
void updateLatestDebugLogSymlink();
|
|
2420
2420
|
return;
|
|
2421
2421
|
}
|
|
2422
|
-
pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir,
|
|
2422
|
+
pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir, path57, content)).catch(noop);
|
|
2423
2423
|
},
|
|
2424
2424
|
flushIntervalMs: 1e3,
|
|
2425
2425
|
maxBufferSize: 100,
|
|
@@ -8606,8 +8606,8 @@ import codeExcerpt from "code-excerpt";
|
|
|
8606
8606
|
import { readFileSync as readFileSync2 } from "fs";
|
|
8607
8607
|
import StackUtils from "stack-utils";
|
|
8608
8608
|
import { jsx as jsx6, jsxs } from "react/jsx-runtime";
|
|
8609
|
-
var cleanupPath = (
|
|
8610
|
-
return
|
|
8609
|
+
var cleanupPath = (path57) => {
|
|
8610
|
+
return path57?.replace(`file://${process.cwd()}/`, "");
|
|
8611
8611
|
};
|
|
8612
8612
|
var stackUtils;
|
|
8613
8613
|
function getStackUtils() {
|
|
@@ -12585,7 +12585,7 @@ var getInstance = (stdout, createInstance) => {
|
|
|
12585
12585
|
// src/main.ts
|
|
12586
12586
|
import { EventEmitter as EventEmitter7 } from "events";
|
|
12587
12587
|
import fs51 from "fs";
|
|
12588
|
-
import
|
|
12588
|
+
import path56 from "path";
|
|
12589
12589
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
12590
12590
|
import { spawn as spawn6 } from "child_process";
|
|
12591
12591
|
import { v4 as uuidv412 } from "uuid";
|
|
@@ -13479,12 +13479,12 @@ function cancelSlashSubmenu() {
|
|
|
13479
13479
|
|
|
13480
13480
|
// src/app/agent/agent.ts
|
|
13481
13481
|
import * as dotenv from "dotenv";
|
|
13482
|
-
import
|
|
13482
|
+
import path47 from "path";
|
|
13483
13483
|
import os31 from "os";
|
|
13484
13484
|
|
|
13485
13485
|
// src/app/agent/tool_invoker.ts
|
|
13486
13486
|
import { promises as fs25 } from "fs";
|
|
13487
|
-
import
|
|
13487
|
+
import path27 from "path";
|
|
13488
13488
|
import { fileURLToPath } from "url";
|
|
13489
13489
|
|
|
13490
13490
|
// src/app/agent/tools/EditTool/EditTool.ts
|
|
@@ -19066,11 +19066,13 @@ async function createNextApp(args) {
|
|
|
19066
19066
|
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
19067
19067
|
init_sandbox_policy();
|
|
19068
19068
|
import { promises as fs24 } from "fs";
|
|
19069
|
+
import path26 from "path";
|
|
19070
|
+
|
|
19071
|
+
// src/app/agent/tools/DeployAppTool/createDeployProjectZip.ts
|
|
19072
|
+
import { lstat, readdir, readFile, writeFile } from "fs/promises";
|
|
19069
19073
|
import path25 from "path";
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
}
|
|
19073
|
-
var EXCLUDE_PATTERNS = [
|
|
19074
|
+
import { minimatch as minimatch2 } from "minimatch";
|
|
19075
|
+
var DEPLOY_ZIP_EXCLUDE_PATTERNS = [
|
|
19074
19076
|
"node_modules",
|
|
19075
19077
|
".next",
|
|
19076
19078
|
".git",
|
|
@@ -19083,62 +19085,116 @@ var EXCLUDE_PATTERNS = [
|
|
|
19083
19085
|
".env*.local",
|
|
19084
19086
|
"coverage",
|
|
19085
19087
|
".vercel",
|
|
19086
|
-
".turbo"
|
|
19088
|
+
".turbo",
|
|
19089
|
+
".tmp"
|
|
19087
19090
|
];
|
|
19088
|
-
function
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
19093
|
-
|
|
19094
|
-
|
|
19095
|
-
const
|
|
19096
|
-
const
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19091
|
+
function pathSegments(relativePosix) {
|
|
19092
|
+
return relativePosix.split("/").filter(Boolean);
|
|
19093
|
+
}
|
|
19094
|
+
function shouldExcludeFromDeployZip(relativePosix, isDirectory) {
|
|
19095
|
+
const rel = relativePosix.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
19096
|
+
if (!rel) return false;
|
|
19097
|
+
const segments = pathSegments(rel);
|
|
19098
|
+
const baseName = path25.posix.basename(rel);
|
|
19099
|
+
for (const pattern of DEPLOY_ZIP_EXCLUDE_PATTERNS) {
|
|
19100
|
+
if (pattern.includes("*")) {
|
|
19101
|
+
if (minimatch2(rel, pattern) || minimatch2(baseName, pattern)) {
|
|
19102
|
+
return true;
|
|
19103
|
+
}
|
|
19104
|
+
continue;
|
|
19105
|
+
}
|
|
19106
|
+
if (segments.includes(pattern)) {
|
|
19107
|
+
return true;
|
|
19108
|
+
}
|
|
19109
|
+
if (!isDirectory && baseName === pattern) {
|
|
19110
|
+
return true;
|
|
19111
|
+
}
|
|
19106
19112
|
}
|
|
19113
|
+
return false;
|
|
19114
|
+
}
|
|
19115
|
+
async function collectDeployZipEntries(projectDir, files) {
|
|
19116
|
+
const base = path25.resolve(projectDir);
|
|
19117
|
+
async function walk(currentDir) {
|
|
19118
|
+
let entries;
|
|
19119
|
+
try {
|
|
19120
|
+
entries = await readdir(currentDir, { withFileTypes: true });
|
|
19121
|
+
} catch {
|
|
19122
|
+
return;
|
|
19123
|
+
}
|
|
19124
|
+
for (const entry of entries) {
|
|
19125
|
+
const fullPath = path25.join(currentDir, entry.name);
|
|
19126
|
+
const rel = path25.relative(base, fullPath).replace(/\\/g, "/");
|
|
19127
|
+
if (shouldExcludeFromDeployZip(rel, entry.isDirectory())) {
|
|
19128
|
+
continue;
|
|
19129
|
+
}
|
|
19130
|
+
if (entry.isSymbolicLink()) {
|
|
19131
|
+
try {
|
|
19132
|
+
const st = await lstat(fullPath);
|
|
19133
|
+
if (st.isDirectory()) continue;
|
|
19134
|
+
} catch {
|
|
19135
|
+
continue;
|
|
19136
|
+
}
|
|
19137
|
+
}
|
|
19138
|
+
if (entry.isDirectory()) {
|
|
19139
|
+
await walk(fullPath);
|
|
19140
|
+
continue;
|
|
19141
|
+
}
|
|
19142
|
+
if (!entry.isFile()) {
|
|
19143
|
+
continue;
|
|
19144
|
+
}
|
|
19145
|
+
try {
|
|
19146
|
+
const content = await readFile(fullPath);
|
|
19147
|
+
files[rel] = new Uint8Array(content);
|
|
19148
|
+
} catch {
|
|
19149
|
+
}
|
|
19150
|
+
}
|
|
19151
|
+
}
|
|
19152
|
+
await walk(base);
|
|
19153
|
+
}
|
|
19154
|
+
async function createDeployProjectZip(projectDir, zipPath) {
|
|
19155
|
+
const files = {};
|
|
19156
|
+
await collectDeployZipEntries(projectDir, files);
|
|
19157
|
+
const fileCount = Object.keys(files).length;
|
|
19158
|
+
if (fileCount === 0) {
|
|
19159
|
+
throw new Error("No files to include in deploy ZIP (check project directory and exclusions)");
|
|
19160
|
+
}
|
|
19161
|
+
const { zipSync } = await import("fflate");
|
|
19162
|
+
const zipData = zipSync(files, { level: 6 });
|
|
19163
|
+
await writeFile(zipPath, zipData);
|
|
19107
19164
|
return zipPath;
|
|
19108
19165
|
}
|
|
19166
|
+
|
|
19167
|
+
// src/app/agent/tools/DeployAppTool/DeployAppTool.ts
|
|
19109
19168
|
async function uploadToSeverino(zipPath, severinoUrl, name, apiKey, appId) {
|
|
19110
19169
|
const deployUrl = `${severinoUrl.replace(/\/$/, "")}/api/v1/deploy`;
|
|
19111
|
-
const
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
"
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
if (
|
|
19120
|
-
|
|
19121
|
-
}
|
|
19122
|
-
if (appId) {
|
|
19123
|
-
curlArgs.push("-F", `appId=${appId}`);
|
|
19124
|
-
}
|
|
19170
|
+
const zipBytes = await fs24.readFile(zipPath);
|
|
19171
|
+
const form = new FormData();
|
|
19172
|
+
form.append(
|
|
19173
|
+
"file",
|
|
19174
|
+
new Blob([zipBytes], { type: "application/zip" }),
|
|
19175
|
+
path26.basename(zipPath)
|
|
19176
|
+
);
|
|
19177
|
+
if (name) form.append("name", name);
|
|
19178
|
+
if (appId) form.append("appId", appId);
|
|
19179
|
+
const headers = { Accept: "application/json" };
|
|
19125
19180
|
if (apiKey) {
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
}
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
19133
|
-
|
|
19134
|
-
// 1 minuto para upload
|
|
19181
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
19182
|
+
headers["X-API-Key"] = apiKey;
|
|
19183
|
+
}
|
|
19184
|
+
const httpResponse = await fetch(deployUrl, {
|
|
19185
|
+
method: "POST",
|
|
19186
|
+
body: form,
|
|
19187
|
+
headers,
|
|
19188
|
+
signal: AbortSignal.timeout(12e4)
|
|
19135
19189
|
});
|
|
19136
|
-
const
|
|
19137
|
-
if (
|
|
19138
|
-
throw new Error(
|
|
19190
|
+
const responseText = await httpResponse.text();
|
|
19191
|
+
if (!httpResponse.ok) {
|
|
19192
|
+
throw new Error(
|
|
19193
|
+
`Upload failed (${httpResponse.status}): ${responseText.slice(0, 500)}`
|
|
19194
|
+
);
|
|
19139
19195
|
}
|
|
19140
19196
|
try {
|
|
19141
|
-
const response = JSON.parse(
|
|
19197
|
+
const response = JSON.parse(responseText);
|
|
19142
19198
|
if (response.success === false || response.error) {
|
|
19143
19199
|
const errorMsg = typeof response.error === "string" ? response.error : response.error?.message || "Deploy failed";
|
|
19144
19200
|
return {
|
|
@@ -19225,7 +19281,7 @@ function buildFactorAiManifest(appContext, deployResult, appName) {
|
|
|
19225
19281
|
}
|
|
19226
19282
|
async function writeFactorAiManifest(projectDir, appContext, deployResult, appName) {
|
|
19227
19283
|
const manifest = buildFactorAiManifest(appContext, deployResult, appName);
|
|
19228
|
-
const manifestPath =
|
|
19284
|
+
const manifestPath = path26.join(projectDir, "factorai.sh.json");
|
|
19229
19285
|
await fs24.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
19230
19286
|
`, "utf-8");
|
|
19231
19287
|
return manifest;
|
|
@@ -19253,7 +19309,7 @@ async function deployApp(args) {
|
|
|
19253
19309
|
error: `Project directory not found: ${resolvedProjectDir}`
|
|
19254
19310
|
};
|
|
19255
19311
|
}
|
|
19256
|
-
const packageJsonPath =
|
|
19312
|
+
const packageJsonPath = path26.join(resolvedProjectDir, "package.json");
|
|
19257
19313
|
try {
|
|
19258
19314
|
await fs24.access(packageJsonPath);
|
|
19259
19315
|
} catch {
|
|
@@ -19271,12 +19327,12 @@ async function deployApp(args) {
|
|
|
19271
19327
|
error: "Not a Next.js project: next not found in dependencies"
|
|
19272
19328
|
};
|
|
19273
19329
|
}
|
|
19274
|
-
const appName = name || packageJson.name ||
|
|
19275
|
-
const tempDir =
|
|
19330
|
+
const appName = name || packageJson.name || path26.basename(resolvedProjectDir);
|
|
19331
|
+
const tempDir = path26.join(resolvedProjectDir, ".tmp");
|
|
19276
19332
|
await fs24.mkdir(tempDir, { recursive: true });
|
|
19277
|
-
const zipPath =
|
|
19333
|
+
const zipPath = path26.join(tempDir, `${appName}-${Date.now()}.zip`);
|
|
19278
19334
|
console.log(`[deploy-app] Creating ZIP: ${zipPath}`);
|
|
19279
|
-
await
|
|
19335
|
+
await createDeployProjectZip(resolvedProjectDir, zipPath);
|
|
19280
19336
|
const zipStats = await fs24.stat(zipPath);
|
|
19281
19337
|
const zipSizeMB = zipStats.size / 1024 / 1024;
|
|
19282
19338
|
if (zipSizeMB > 50) {
|
|
@@ -19307,7 +19363,7 @@ async function deployApp(args) {
|
|
|
19307
19363
|
appName
|
|
19308
19364
|
);
|
|
19309
19365
|
deployResult.factoraiManifest = manifest;
|
|
19310
|
-
deployResult.factoraiManifestPath =
|
|
19366
|
+
deployResult.factoraiManifestPath = path26.join(resolvedProjectDir, "factorai.sh.json");
|
|
19311
19367
|
}
|
|
19312
19368
|
console.log(`[deploy-app] Deploy iniciado: ${deployResult.appId}`);
|
|
19313
19369
|
}
|
|
@@ -20389,8 +20445,8 @@ var ToolInvoker = class {
|
|
|
20389
20445
|
async initialize() {
|
|
20390
20446
|
try {
|
|
20391
20447
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
20392
|
-
const currentDirPath =
|
|
20393
|
-
const configPath =
|
|
20448
|
+
const currentDirPath = path27.dirname(currentFilePath);
|
|
20449
|
+
const configPath = path27.resolve(currentDirPath, "config", "native_tools.json");
|
|
20394
20450
|
const fileContent = await fs25.readFile(configPath, "utf-8");
|
|
20395
20451
|
const config2 = JSON.parse(fileContent);
|
|
20396
20452
|
this.toolDefinitions = applyMetadataToToolDefinitions(config2.nativeTools);
|
|
@@ -20439,7 +20495,7 @@ var ToolInvoker = class {
|
|
|
20439
20495
|
|
|
20440
20496
|
// src/app/agent/tools/mcp/mcp_client.ts
|
|
20441
20497
|
import { promises as fs26 } from "fs";
|
|
20442
|
-
import
|
|
20498
|
+
import path28 from "path";
|
|
20443
20499
|
import os18 from "os";
|
|
20444
20500
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20445
20501
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -20467,9 +20523,9 @@ var MCPClient = class {
|
|
|
20467
20523
|
});
|
|
20468
20524
|
}
|
|
20469
20525
|
const __filename = fileURLToPath2(import.meta.url);
|
|
20470
|
-
const __dirname2 =
|
|
20471
|
-
const defaultConfigPath =
|
|
20472
|
-
const userConfigPath =
|
|
20526
|
+
const __dirname2 = path28.dirname(__filename);
|
|
20527
|
+
const defaultConfigPath = path28.resolve(__dirname2, "config", "bluma-mcp.json");
|
|
20528
|
+
const userConfigPath = path28.join(os18.homedir(), ".bluma", "bluma-mcp.json");
|
|
20473
20529
|
const defaultConfig = await this.loadMcpConfig(defaultConfigPath, "Default");
|
|
20474
20530
|
const userConfig = await this.loadMcpConfig(userConfigPath, "User");
|
|
20475
20531
|
const mergedConfig = {
|
|
@@ -20715,39 +20771,39 @@ PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
|
|
|
20715
20771
|
};
|
|
20716
20772
|
|
|
20717
20773
|
// src/app/agent/bluma/core/bluma.ts
|
|
20718
|
-
import
|
|
20774
|
+
import path44 from "path";
|
|
20719
20775
|
import fs40 from "fs";
|
|
20720
20776
|
import { v4 as uuidv48 } from "uuid";
|
|
20721
20777
|
|
|
20722
20778
|
// src/app/agent/session_manager/session_manager.ts
|
|
20723
|
-
import
|
|
20779
|
+
import path32 from "path";
|
|
20724
20780
|
import { promises as fs29 } from "fs";
|
|
20725
20781
|
|
|
20726
20782
|
// src/app/agent/session_manager/agent_session_paths.ts
|
|
20727
|
-
import
|
|
20783
|
+
import path31 from "path";
|
|
20728
20784
|
import { promises as fs28 } from "fs";
|
|
20729
20785
|
|
|
20730
20786
|
// src/app/agent/session_manager/bluma_app_dir.ts
|
|
20731
|
-
import
|
|
20787
|
+
import path29 from "path";
|
|
20732
20788
|
import os19 from "os";
|
|
20733
20789
|
function expandHome(p) {
|
|
20734
20790
|
if (!p) return p;
|
|
20735
20791
|
if (p.startsWith("~")) {
|
|
20736
|
-
return
|
|
20792
|
+
return path29.join(os19.homedir(), p.slice(1));
|
|
20737
20793
|
}
|
|
20738
20794
|
return p;
|
|
20739
20795
|
}
|
|
20740
20796
|
function getPreferredAppDir() {
|
|
20741
20797
|
const fromEnv = process.env.BLUMA_HOME?.trim();
|
|
20742
20798
|
if (fromEnv) {
|
|
20743
|
-
return
|
|
20799
|
+
return path29.resolve(expandHome(fromEnv));
|
|
20744
20800
|
}
|
|
20745
|
-
const fixed =
|
|
20746
|
-
return
|
|
20801
|
+
const fixed = path29.join(os19.homedir(), ".bluma");
|
|
20802
|
+
return path29.resolve(expandHome(fixed));
|
|
20747
20803
|
}
|
|
20748
20804
|
|
|
20749
20805
|
// src/app/agent/session_manager/session_index_db.ts
|
|
20750
|
-
import
|
|
20806
|
+
import path30 from "path";
|
|
20751
20807
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
20752
20808
|
import { promises as fs27 } from "fs";
|
|
20753
20809
|
import { createRequire } from "module";
|
|
@@ -20762,10 +20818,10 @@ function loadSqlite() {
|
|
|
20762
20818
|
return nodeRequire("better-sqlite3");
|
|
20763
20819
|
}
|
|
20764
20820
|
function getSessionDbPath(appDir = getPreferredAppDir()) {
|
|
20765
|
-
return
|
|
20821
|
+
return path30.join(appDir, BLUMA_SESSION_DB_FILE);
|
|
20766
20822
|
}
|
|
20767
20823
|
function normalizeRelativePath(relativePath) {
|
|
20768
|
-
return relativePath.split(
|
|
20824
|
+
return relativePath.split(path30.sep).join("/");
|
|
20769
20825
|
}
|
|
20770
20826
|
async function walkSessionJsonFiles(dir, onFile) {
|
|
20771
20827
|
let entries;
|
|
@@ -20776,7 +20832,7 @@ async function walkSessionJsonFiles(dir, onFile) {
|
|
|
20776
20832
|
}
|
|
20777
20833
|
for (const e of entries) {
|
|
20778
20834
|
const name = String(e.name);
|
|
20779
|
-
const full =
|
|
20835
|
+
const full = path30.join(dir, name);
|
|
20780
20836
|
if (e.isDirectory()) {
|
|
20781
20837
|
await walkSessionJsonFiles(full, onFile);
|
|
20782
20838
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -20786,7 +20842,7 @@ async function walkSessionJsonFiles(dir, onFile) {
|
|
|
20786
20842
|
}
|
|
20787
20843
|
async function loadJsonlEntries(appDir) {
|
|
20788
20844
|
const map = /* @__PURE__ */ new Map();
|
|
20789
|
-
const indexFile =
|
|
20845
|
+
const indexFile = path30.join(appDir, AGENT_SESSION_PATHS_JSONL);
|
|
20790
20846
|
let raw;
|
|
20791
20847
|
try {
|
|
20792
20848
|
raw = await fs27.readFile(indexFile, "utf-8");
|
|
@@ -20866,7 +20922,7 @@ async function runMigrationV1(db, appDir) {
|
|
|
20866
20922
|
const insertFromPath = async (sessionId, absPath, jsonlUpdatedAt) => {
|
|
20867
20923
|
let rel;
|
|
20868
20924
|
try {
|
|
20869
|
-
rel = normalizeRelativePath(
|
|
20925
|
+
rel = normalizeRelativePath(path30.relative(appDir, absPath));
|
|
20870
20926
|
} catch {
|
|
20871
20927
|
return;
|
|
20872
20928
|
}
|
|
@@ -20881,7 +20937,7 @@ async function runMigrationV1(db, appDir) {
|
|
|
20881
20937
|
});
|
|
20882
20938
|
};
|
|
20883
20939
|
for (const [sessionId, entry] of jsonl) {
|
|
20884
|
-
const full =
|
|
20940
|
+
const full = path30.join(appDir, entry.relativePath.replace(/\//g, path30.sep));
|
|
20885
20941
|
try {
|
|
20886
20942
|
await fs27.access(full);
|
|
20887
20943
|
await insertFromPath(sessionId, full, entry.updatedAt);
|
|
@@ -20895,11 +20951,11 @@ async function runMigrationV1(db, appDir) {
|
|
|
20895
20951
|
});
|
|
20896
20952
|
}
|
|
20897
20953
|
}
|
|
20898
|
-
const sessionsRoot =
|
|
20954
|
+
const sessionsRoot = path30.join(appDir, "sessions");
|
|
20899
20955
|
const existing = db.prepare("SELECT session_id FROM agent_sessions").all();
|
|
20900
20956
|
const seen = new Set(existing.map((r) => r.session_id));
|
|
20901
20957
|
await walkSessionJsonFiles(sessionsRoot, async (absPath) => {
|
|
20902
|
-
const sessionId =
|
|
20958
|
+
const sessionId = path30.basename(absPath, ".json");
|
|
20903
20959
|
if (!sessionId || seen.has(sessionId)) return;
|
|
20904
20960
|
seen.add(sessionId);
|
|
20905
20961
|
await insertFromPath(sessionId, absPath);
|
|
@@ -20934,7 +20990,7 @@ async function ensureSessionIndexDb(appDir = getPreferredAppDir()) {
|
|
|
20934
20990
|
}
|
|
20935
20991
|
const BetterSqlite3 = loadSqlite();
|
|
20936
20992
|
const dbPath = getSessionDbPath(appDir);
|
|
20937
|
-
mkdirSync3(
|
|
20993
|
+
mkdirSync3(path30.dirname(dbPath), { recursive: true });
|
|
20938
20994
|
const db = new BetterSqlite3(dbPath);
|
|
20939
20995
|
db.pragma("journal_mode = WAL");
|
|
20940
20996
|
applySchema(db);
|
|
@@ -20970,7 +21026,7 @@ async function upsertSessionIndexRow(row, appDir = getPreferredAppDir()) {
|
|
|
20970
21026
|
async function getSessionPathFromIndex(sessionId, appDir = getPreferredAppDir()) {
|
|
20971
21027
|
const db = await ensureSessionIndexDb(appDir);
|
|
20972
21028
|
const row = db.prepare("SELECT relative_path FROM agent_sessions WHERE session_id = ?").get(sessionId);
|
|
20973
|
-
return row?.relative_path?.replace(/\//g,
|
|
21029
|
+
return row?.relative_path?.replace(/\//g, path30.sep) ?? null;
|
|
20974
21030
|
}
|
|
20975
21031
|
async function listSessionsFromIndex(limit = 50, appDir = getPreferredAppDir()) {
|
|
20976
21032
|
const db = await ensureSessionIndexDb(appDir);
|
|
@@ -20982,7 +21038,7 @@ async function listSessionsFromIndex(limit = 50, appDir = getPreferredAppDir())
|
|
|
20982
21038
|
).all(limit);
|
|
20983
21039
|
return rows.map((r) => ({
|
|
20984
21040
|
sessionId: r.session_id,
|
|
20985
|
-
relativePath: r.relative_path.replace(/\//g,
|
|
21041
|
+
relativePath: r.relative_path.replace(/\//g, path30.sep),
|
|
20986
21042
|
createdAt: r.created_at,
|
|
20987
21043
|
updatedAt: r.updated_at,
|
|
20988
21044
|
preview: r.preview
|
|
@@ -20994,7 +21050,7 @@ var AGENT_SESSION_PATHS_JSONL2 = "agent_session_paths.jsonl";
|
|
|
20994
21050
|
async function appendAgentSessionPath(sessionId, relativePath) {
|
|
20995
21051
|
const app = getPreferredAppDir();
|
|
20996
21052
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
20997
|
-
const rel = relativePath.split(
|
|
21053
|
+
const rel = relativePath.split(path31.sep).join("/");
|
|
20998
21054
|
await upsertSessionIndexRow({
|
|
20999
21055
|
sessionId,
|
|
21000
21056
|
relativePath: rel,
|
|
@@ -21004,7 +21060,7 @@ async function appendAgentSessionPath(sessionId, relativePath) {
|
|
|
21004
21060
|
});
|
|
21005
21061
|
}
|
|
21006
21062
|
async function resolveSessionRelativePathFromJsonl(sessionId) {
|
|
21007
|
-
const indexFile =
|
|
21063
|
+
const indexFile = path31.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
|
|
21008
21064
|
let raw;
|
|
21009
21065
|
try {
|
|
21010
21066
|
raw = await fs28.readFile(indexFile, "utf-8");
|
|
@@ -21016,7 +21072,7 @@ async function resolveSessionRelativePathFromJsonl(sessionId) {
|
|
|
21016
21072
|
try {
|
|
21017
21073
|
const row = JSON.parse(lines[i]);
|
|
21018
21074
|
if (row.sessionId === sessionId && typeof row.relativePath === "string") {
|
|
21019
|
-
return row.relativePath.replace(/\//g,
|
|
21075
|
+
return row.relativePath.replace(/\//g, path31.sep);
|
|
21020
21076
|
}
|
|
21021
21077
|
} catch {
|
|
21022
21078
|
}
|
|
@@ -21037,7 +21093,7 @@ async function walkSessionJsonFiles2(dir, onFile) {
|
|
|
21037
21093
|
}
|
|
21038
21094
|
for (const e of entries) {
|
|
21039
21095
|
const name = String(e.name);
|
|
21040
|
-
const full =
|
|
21096
|
+
const full = path31.join(dir, name);
|
|
21041
21097
|
if (e.isDirectory()) {
|
|
21042
21098
|
await walkSessionJsonFiles2(full, onFile);
|
|
21043
21099
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -21046,10 +21102,10 @@ async function walkSessionJsonFiles2(dir, onFile) {
|
|
|
21046
21102
|
}
|
|
21047
21103
|
}
|
|
21048
21104
|
async function findSessionFileGlobFallback(sessionId) {
|
|
21049
|
-
const sessionsRoot =
|
|
21105
|
+
const sessionsRoot = path31.join(getPreferredAppDir(), "sessions");
|
|
21050
21106
|
const state2 = { best: null };
|
|
21051
21107
|
await walkSessionJsonFiles2(sessionsRoot, async (abs) => {
|
|
21052
|
-
if (
|
|
21108
|
+
if (path31.basename(abs, ".json") !== sessionId) return;
|
|
21053
21109
|
try {
|
|
21054
21110
|
const st = await fs28.stat(abs);
|
|
21055
21111
|
if (!st.isFile()) return;
|
|
@@ -21062,7 +21118,7 @@ async function findSessionFileGlobFallback(sessionId) {
|
|
|
21062
21118
|
return state2.best !== null ? state2.best.p : null;
|
|
21063
21119
|
}
|
|
21064
21120
|
async function loadLatestIndexEntriesBySessionId() {
|
|
21065
|
-
const indexFile =
|
|
21121
|
+
const indexFile = path31.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
|
|
21066
21122
|
const map = /* @__PURE__ */ new Map();
|
|
21067
21123
|
let raw;
|
|
21068
21124
|
try {
|
|
@@ -21102,11 +21158,11 @@ function dateFolderFromRelativePath(relativePath) {
|
|
|
21102
21158
|
async function enrichCandidateFromFile(absPath, sessionId, lastMtimeMs, opts) {
|
|
21103
21159
|
let rel;
|
|
21104
21160
|
try {
|
|
21105
|
-
rel =
|
|
21161
|
+
rel = path31.relative(getPreferredAppDir(), absPath);
|
|
21106
21162
|
} catch {
|
|
21107
21163
|
rel = absPath;
|
|
21108
21164
|
}
|
|
21109
|
-
const dateFolder = dateFolderFromRelativePath(rel.split(
|
|
21165
|
+
const dateFolder = dateFolderFromRelativePath(rel.split(path31.sep).join("/"));
|
|
21110
21166
|
let preview = opts?.preview ?? "(no messages)";
|
|
21111
21167
|
let lastActivityMs = lastMtimeMs;
|
|
21112
21168
|
if (opts?.updatedAtIso) {
|
|
@@ -21145,7 +21201,7 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
21145
21201
|
const fromIndex = await listSessionsFromIndex(limit * 2, appDir);
|
|
21146
21202
|
const map = /* @__PURE__ */ new Map();
|
|
21147
21203
|
for (const row of fromIndex) {
|
|
21148
|
-
const full =
|
|
21204
|
+
const full = path31.join(appDir, row.relativePath);
|
|
21149
21205
|
try {
|
|
21150
21206
|
const st = await fs28.stat(full);
|
|
21151
21207
|
if (!st.isFile()) continue;
|
|
@@ -21158,9 +21214,9 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
21158
21214
|
} catch {
|
|
21159
21215
|
}
|
|
21160
21216
|
}
|
|
21161
|
-
const sessionsRoot =
|
|
21217
|
+
const sessionsRoot = path31.join(appDir, "sessions");
|
|
21162
21218
|
await walkSessionJsonFiles2(sessionsRoot, async (absPath) => {
|
|
21163
|
-
const id =
|
|
21219
|
+
const id = path31.basename(absPath, ".json");
|
|
21164
21220
|
if (!id) return;
|
|
21165
21221
|
try {
|
|
21166
21222
|
const st = await fs28.stat(absPath);
|
|
@@ -21175,7 +21231,7 @@ async function listAgentSessionsForResume(limit = 50) {
|
|
|
21175
21231
|
const index = await loadLatestIndexEntriesBySessionId();
|
|
21176
21232
|
for (const [sessionId, entry] of index) {
|
|
21177
21233
|
if (map.has(sessionId)) continue;
|
|
21178
|
-
const full =
|
|
21234
|
+
const full = path31.join(appDir, entry.relativePath.replace(/\//g, path31.sep));
|
|
21179
21235
|
try {
|
|
21180
21236
|
const st = await fs28.stat(full);
|
|
21181
21237
|
if (st.isFile()) {
|
|
@@ -21234,7 +21290,7 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
21234
21290
|
const isWin = process.platform === "win32";
|
|
21235
21291
|
while (attempt <= maxRetries) {
|
|
21236
21292
|
try {
|
|
21237
|
-
const dir =
|
|
21293
|
+
const dir = path32.dirname(dest);
|
|
21238
21294
|
await fs29.mkdir(dir, { recursive: true }).catch(() => {
|
|
21239
21295
|
});
|
|
21240
21296
|
await fs29.rename(src, dest);
|
|
@@ -21252,7 +21308,7 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
21252
21308
|
try {
|
|
21253
21309
|
await fs29.access(src);
|
|
21254
21310
|
const data = await fs29.readFile(src);
|
|
21255
|
-
const dir =
|
|
21311
|
+
const dir = path32.dirname(dest);
|
|
21256
21312
|
await fs29.mkdir(dir, { recursive: true }).catch(() => {
|
|
21257
21313
|
});
|
|
21258
21314
|
await fs29.writeFile(dest, data);
|
|
@@ -21269,13 +21325,13 @@ async function safeRenameWithRetry(src, dest, maxRetries = 6) {
|
|
|
21269
21325
|
}
|
|
21270
21326
|
async function ensureSessionDir() {
|
|
21271
21327
|
const appDir = getPreferredAppDir();
|
|
21272
|
-
const sessionDir =
|
|
21328
|
+
const sessionDir = path32.join(appDir, "sessions");
|
|
21273
21329
|
await fs29.mkdir(sessionDir, { recursive: true });
|
|
21274
21330
|
return sessionDir;
|
|
21275
21331
|
}
|
|
21276
21332
|
async function resolveAgentSessionFilePath(sessionId) {
|
|
21277
21333
|
const appDir = getPreferredAppDir();
|
|
21278
|
-
const legacy =
|
|
21334
|
+
const legacy = path32.join(appDir, "sessions", `${sessionId}.json`);
|
|
21279
21335
|
try {
|
|
21280
21336
|
await fs29.access(legacy);
|
|
21281
21337
|
return legacy;
|
|
@@ -21283,7 +21339,7 @@ async function resolveAgentSessionFilePath(sessionId) {
|
|
|
21283
21339
|
}
|
|
21284
21340
|
const rel = await resolveSessionRelativePathFromIndex(sessionId);
|
|
21285
21341
|
if (rel) {
|
|
21286
|
-
const full =
|
|
21342
|
+
const full = path32.join(appDir, rel);
|
|
21287
21343
|
try {
|
|
21288
21344
|
await fs29.access(full);
|
|
21289
21345
|
return full;
|
|
@@ -21319,16 +21375,16 @@ async function loadOrcreateSession(sessionId) {
|
|
|
21319
21375
|
const y = String(now2.getFullYear());
|
|
21320
21376
|
const mo = String(now2.getMonth() + 1).padStart(2, "0");
|
|
21321
21377
|
const d = String(now2.getDate()).padStart(2, "0");
|
|
21322
|
-
const datedDir =
|
|
21378
|
+
const datedDir = path32.join(sessionsRoot, y, mo, d);
|
|
21323
21379
|
await fs29.mkdir(datedDir, { recursive: true });
|
|
21324
|
-
const sessionFile =
|
|
21380
|
+
const sessionFile = path32.join(datedDir, `${sessionId}.json`);
|
|
21325
21381
|
const newSessionData = {
|
|
21326
21382
|
session_id: sessionId,
|
|
21327
21383
|
created_at: now2.toISOString(),
|
|
21328
21384
|
conversation_history: []
|
|
21329
21385
|
};
|
|
21330
21386
|
await fs29.writeFile(sessionFile, JSON.stringify(newSessionData, null, 2), "utf-8");
|
|
21331
|
-
const relToApp =
|
|
21387
|
+
const relToApp = path32.relative(getPreferredAppDir(), sessionFile);
|
|
21332
21388
|
await appendAgentSessionPath(sessionId, relToApp);
|
|
21333
21389
|
const emptyMemory = {
|
|
21334
21390
|
historyAnchor: null,
|
|
@@ -21340,7 +21396,7 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
21340
21396
|
await withFileLock(sessionFile, async () => {
|
|
21341
21397
|
let sessionData;
|
|
21342
21398
|
try {
|
|
21343
|
-
const dir =
|
|
21399
|
+
const dir = path32.dirname(sessionFile);
|
|
21344
21400
|
await fs29.mkdir(dir, { recursive: true });
|
|
21345
21401
|
} catch {
|
|
21346
21402
|
}
|
|
@@ -21356,7 +21412,7 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
21356
21412
|
console.warn(`An unknown error occurred while reading ${sessionFile}. Re-initializing.`, error);
|
|
21357
21413
|
}
|
|
21358
21414
|
}
|
|
21359
|
-
const sessionId =
|
|
21415
|
+
const sessionId = path32.basename(sessionFile, ".json");
|
|
21360
21416
|
sessionData = {
|
|
21361
21417
|
session_id: sessionId,
|
|
21362
21418
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -21381,12 +21437,12 @@ async function doSaveSessionHistory(sessionFile, history, memory) {
|
|
|
21381
21437
|
try {
|
|
21382
21438
|
await fs29.writeFile(tempSessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
|
|
21383
21439
|
await safeRenameWithRetry(tempSessionFile, sessionFile);
|
|
21384
|
-
const sessionId = sessionData.session_id ??
|
|
21440
|
+
const sessionId = sessionData.session_id ?? path32.basename(sessionFile, ".json");
|
|
21385
21441
|
const updatedAt = sessionData.last_updated ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
21386
21442
|
const createdAt = sessionData.created_at ?? updatedAt;
|
|
21387
21443
|
let relToApp;
|
|
21388
21444
|
try {
|
|
21389
|
-
relToApp =
|
|
21445
|
+
relToApp = path32.relative(getPreferredAppDir(), sessionFile);
|
|
21390
21446
|
} catch {
|
|
21391
21447
|
relToApp = sessionFile;
|
|
21392
21448
|
}
|
|
@@ -21439,12 +21495,12 @@ async function saveSessionHistoryNow(sessionFile, history, memory) {
|
|
|
21439
21495
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
21440
21496
|
import os24 from "os";
|
|
21441
21497
|
import fs36 from "fs";
|
|
21442
|
-
import
|
|
21498
|
+
import path39 from "path";
|
|
21443
21499
|
import { execSync as execSync3 } from "child_process";
|
|
21444
21500
|
|
|
21445
21501
|
// src/app/agent/skills/skill_loader.ts
|
|
21446
21502
|
import fs30 from "fs";
|
|
21447
|
-
import
|
|
21503
|
+
import path33 from "path";
|
|
21448
21504
|
import os20 from "os";
|
|
21449
21505
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
21450
21506
|
var SkillLoader = class _SkillLoader {
|
|
@@ -21454,8 +21510,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
21454
21510
|
cache = /* @__PURE__ */ new Map();
|
|
21455
21511
|
conflicts = [];
|
|
21456
21512
|
constructor(projectRoot, bundledDir) {
|
|
21457
|
-
this.projectSkillsDir =
|
|
21458
|
-
this.globalSkillsDir =
|
|
21513
|
+
this.projectSkillsDir = path33.join(projectRoot, ".bluma", "skills");
|
|
21514
|
+
this.globalSkillsDir = path33.join(os20.homedir(), ".bluma", "skills");
|
|
21459
21515
|
this.bundledSkillsDir = bundledDir || _SkillLoader.resolveBundledDir();
|
|
21460
21516
|
}
|
|
21461
21517
|
/**
|
|
@@ -21464,32 +21520,32 @@ var SkillLoader = class _SkillLoader {
|
|
|
21464
21520
|
*/
|
|
21465
21521
|
static resolveBundledDir() {
|
|
21466
21522
|
if (process.env.JEST_WORKER_ID !== void 0 || process.env.NODE_ENV === "test") {
|
|
21467
|
-
return
|
|
21523
|
+
return path33.join(process.cwd(), "dist", "config", "skills");
|
|
21468
21524
|
}
|
|
21469
21525
|
const candidates = [];
|
|
21470
21526
|
const push = (p) => {
|
|
21471
|
-
const abs =
|
|
21527
|
+
const abs = path33.resolve(p);
|
|
21472
21528
|
if (!candidates.includes(abs)) {
|
|
21473
21529
|
candidates.push(abs);
|
|
21474
21530
|
}
|
|
21475
21531
|
};
|
|
21476
21532
|
let argvBundled = null;
|
|
21477
21533
|
try {
|
|
21478
|
-
const bundleDir =
|
|
21479
|
-
push(
|
|
21534
|
+
const bundleDir = path33.dirname(fileURLToPath3(import.meta.url));
|
|
21535
|
+
push(path33.join(bundleDir, "config", "skills"));
|
|
21480
21536
|
} catch {
|
|
21481
21537
|
}
|
|
21482
21538
|
const argv1 = process.argv[1];
|
|
21483
21539
|
if (argv1 && !argv1.startsWith("-")) {
|
|
21484
21540
|
try {
|
|
21485
21541
|
let resolved = argv1;
|
|
21486
|
-
if (
|
|
21542
|
+
if (path33.isAbsolute(argv1) && fs30.existsSync(argv1)) {
|
|
21487
21543
|
resolved = fs30.realpathSync(argv1);
|
|
21488
|
-
} else if (!
|
|
21489
|
-
resolved =
|
|
21544
|
+
} else if (!path33.isAbsolute(argv1)) {
|
|
21545
|
+
resolved = path33.resolve(process.cwd(), argv1);
|
|
21490
21546
|
}
|
|
21491
|
-
const scriptDir =
|
|
21492
|
-
argvBundled =
|
|
21547
|
+
const scriptDir = path33.dirname(resolved);
|
|
21548
|
+
argvBundled = path33.join(scriptDir, "config", "skills");
|
|
21493
21549
|
push(argvBundled);
|
|
21494
21550
|
} catch {
|
|
21495
21551
|
}
|
|
@@ -21500,12 +21556,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
21500
21556
|
}
|
|
21501
21557
|
}
|
|
21502
21558
|
try {
|
|
21503
|
-
return
|
|
21559
|
+
return path33.join(path33.dirname(fileURLToPath3(import.meta.url)), "config", "skills");
|
|
21504
21560
|
} catch {
|
|
21505
21561
|
if (argvBundled) {
|
|
21506
21562
|
return argvBundled;
|
|
21507
21563
|
}
|
|
21508
|
-
return
|
|
21564
|
+
return path33.join(os20.homedir(), ".bluma", "__bundled_skills_unresolved__");
|
|
21509
21565
|
}
|
|
21510
21566
|
}
|
|
21511
21567
|
/**
|
|
@@ -21534,8 +21590,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
21534
21590
|
this.conflicts.push({
|
|
21535
21591
|
name: skill.name,
|
|
21536
21592
|
userSource: source,
|
|
21537
|
-
userPath:
|
|
21538
|
-
bundledPath:
|
|
21593
|
+
userPath: path33.join(dir, skill.name, "SKILL.md"),
|
|
21594
|
+
bundledPath: path33.join(this.bundledSkillsDir, skill.name, "SKILL.md")
|
|
21539
21595
|
});
|
|
21540
21596
|
continue;
|
|
21541
21597
|
}
|
|
@@ -21546,9 +21602,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
21546
21602
|
if (!fs30.existsSync(dir)) return [];
|
|
21547
21603
|
try {
|
|
21548
21604
|
return fs30.readdirSync(dir).filter((d) => {
|
|
21549
|
-
const fullPath =
|
|
21550
|
-
return fs30.statSync(fullPath).isDirectory() && fs30.existsSync(
|
|
21551
|
-
}).map((d) => this.loadMetadataFromPath(
|
|
21605
|
+
const fullPath = path33.join(dir, d);
|
|
21606
|
+
return fs30.statSync(fullPath).isDirectory() && fs30.existsSync(path33.join(fullPath, "SKILL.md"));
|
|
21607
|
+
}).map((d) => this.loadMetadataFromPath(path33.join(dir, d, "SKILL.md"), d, source)).filter((m) => m !== null);
|
|
21552
21608
|
} catch {
|
|
21553
21609
|
return [];
|
|
21554
21610
|
}
|
|
@@ -21578,9 +21634,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
21578
21634
|
*/
|
|
21579
21635
|
load(name) {
|
|
21580
21636
|
if (this.cache.has(name)) return this.cache.get(name);
|
|
21581
|
-
const bundledPath =
|
|
21582
|
-
const projectPath =
|
|
21583
|
-
const globalPath =
|
|
21637
|
+
const bundledPath = path33.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
21638
|
+
const projectPath = path33.join(this.projectSkillsDir, name, "SKILL.md");
|
|
21639
|
+
const globalPath = path33.join(this.globalSkillsDir, name, "SKILL.md");
|
|
21584
21640
|
const existsBundled = fs30.existsSync(bundledPath);
|
|
21585
21641
|
const existsProject = fs30.existsSync(projectPath);
|
|
21586
21642
|
const existsGlobal = fs30.existsSync(globalPath);
|
|
@@ -21624,7 +21680,7 @@ var SkillLoader = class _SkillLoader {
|
|
|
21624
21680
|
try {
|
|
21625
21681
|
const raw = fs30.readFileSync(skillPath, "utf-8");
|
|
21626
21682
|
const parsed = this.parseFrontmatter(raw);
|
|
21627
|
-
const skillDir =
|
|
21683
|
+
const skillDir = path33.dirname(skillPath);
|
|
21628
21684
|
return {
|
|
21629
21685
|
name: parsed.name || name,
|
|
21630
21686
|
description: parsed.description || "",
|
|
@@ -21633,8 +21689,8 @@ var SkillLoader = class _SkillLoader {
|
|
|
21633
21689
|
version: parsed.version,
|
|
21634
21690
|
author: parsed.author,
|
|
21635
21691
|
license: parsed.license,
|
|
21636
|
-
references: this.scanAssets(
|
|
21637
|
-
scripts: this.scanAssets(
|
|
21692
|
+
references: this.scanAssets(path33.join(skillDir, "references")),
|
|
21693
|
+
scripts: this.scanAssets(path33.join(skillDir, "scripts"))
|
|
21638
21694
|
};
|
|
21639
21695
|
} catch {
|
|
21640
21696
|
return null;
|
|
@@ -21644,11 +21700,11 @@ var SkillLoader = class _SkillLoader {
|
|
|
21644
21700
|
if (!fs30.existsSync(dir)) return [];
|
|
21645
21701
|
try {
|
|
21646
21702
|
return fs30.readdirSync(dir).filter((f) => {
|
|
21647
|
-
const fp =
|
|
21703
|
+
const fp = path33.join(dir, f);
|
|
21648
21704
|
return fs30.statSync(fp).isFile();
|
|
21649
21705
|
}).map((f) => ({
|
|
21650
21706
|
name: f,
|
|
21651
|
-
path:
|
|
21707
|
+
path: path33.resolve(dir, f)
|
|
21652
21708
|
}));
|
|
21653
21709
|
} catch {
|
|
21654
21710
|
return [];
|
|
@@ -21705,9 +21761,9 @@ var SkillLoader = class _SkillLoader {
|
|
|
21705
21761
|
this.cache.clear();
|
|
21706
21762
|
}
|
|
21707
21763
|
exists(name) {
|
|
21708
|
-
const bundledPath =
|
|
21709
|
-
const projectPath =
|
|
21710
|
-
const globalPath =
|
|
21764
|
+
const bundledPath = path33.join(this.bundledSkillsDir, name, "SKILL.md");
|
|
21765
|
+
const projectPath = path33.join(this.projectSkillsDir, name, "SKILL.md");
|
|
21766
|
+
const globalPath = path33.join(this.globalSkillsDir, name, "SKILL.md");
|
|
21711
21767
|
return fs30.existsSync(bundledPath) || fs30.existsSync(projectPath) || fs30.existsSync(globalPath);
|
|
21712
21768
|
}
|
|
21713
21769
|
/**
|
|
@@ -21741,12 +21797,12 @@ var SkillLoader = class _SkillLoader {
|
|
|
21741
21797
|
|
|
21742
21798
|
// src/app/agent/core/prompt/workspace_snapshot.ts
|
|
21743
21799
|
import fs32 from "fs";
|
|
21744
|
-
import
|
|
21800
|
+
import path35 from "path";
|
|
21745
21801
|
import { execSync as execSync2 } from "child_process";
|
|
21746
21802
|
|
|
21747
21803
|
// src/app/agent/utils/blumamd.ts
|
|
21748
21804
|
import fs31 from "fs";
|
|
21749
|
-
import
|
|
21805
|
+
import path34 from "path";
|
|
21750
21806
|
import os21 from "os";
|
|
21751
21807
|
import { execSync } from "child_process";
|
|
21752
21808
|
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.";
|
|
@@ -21876,12 +21932,12 @@ var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
21876
21932
|
function expandIncludePath(includePath, baseDir) {
|
|
21877
21933
|
const cleanPath = includePath.startsWith("@") ? includePath.slice(1) : includePath;
|
|
21878
21934
|
if (cleanPath.startsWith("~")) {
|
|
21879
|
-
return
|
|
21935
|
+
return path34.join(os21.homedir(), cleanPath.slice(1));
|
|
21880
21936
|
}
|
|
21881
|
-
if (
|
|
21937
|
+
if (path34.isAbsolute(cleanPath)) {
|
|
21882
21938
|
return cleanPath;
|
|
21883
21939
|
}
|
|
21884
|
-
return
|
|
21940
|
+
return path34.resolve(baseDir, cleanPath);
|
|
21885
21941
|
}
|
|
21886
21942
|
function processIncludes(content, baseDir, processedFiles) {
|
|
21887
21943
|
const lines = content.split("\n");
|
|
@@ -21890,12 +21946,12 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
21890
21946
|
const includeMatch = line.match(/^@\s*([^\s]+)/);
|
|
21891
21947
|
if (includeMatch) {
|
|
21892
21948
|
const includePath = expandIncludePath(includeMatch[1], baseDir);
|
|
21893
|
-
const normalizedPath =
|
|
21949
|
+
const normalizedPath = path34.normalize(includePath);
|
|
21894
21950
|
if (processedFiles.has(normalizedPath)) {
|
|
21895
21951
|
result.push(`<!-- Circular include prevented: ${includeMatch[1]} -->`);
|
|
21896
21952
|
continue;
|
|
21897
21953
|
}
|
|
21898
|
-
const ext =
|
|
21954
|
+
const ext = path34.extname(includePath).toLowerCase();
|
|
21899
21955
|
if (!TEXT_FILE_EXTENSIONS.has(ext)) {
|
|
21900
21956
|
result.push(`<!-- Include skipped (unsupported extension): ${includeMatch[1]} -->`);
|
|
21901
21957
|
continue;
|
|
@@ -21903,7 +21959,7 @@ function processIncludes(content, baseDir, processedFiles) {
|
|
|
21903
21959
|
try {
|
|
21904
21960
|
const includedContent = fs31.readFileSync(includePath, "utf-8");
|
|
21905
21961
|
processedFiles.add(normalizedPath);
|
|
21906
|
-
const processedContent = processIncludes(includedContent,
|
|
21962
|
+
const processedContent = processIncludes(includedContent, path34.dirname(includePath), processedFiles);
|
|
21907
21963
|
result.push(`
|
|
21908
21964
|
<!-- BEGIN INCLUDE ${includeMatch[1]} -->
|
|
21909
21965
|
`);
|
|
@@ -21950,8 +22006,8 @@ function parseFrontmatterPaths(paths2) {
|
|
|
21950
22006
|
function readMemoryFile(filePath, type, includeBasePath) {
|
|
21951
22007
|
try {
|
|
21952
22008
|
const rawContent = fs31.readFileSync(filePath, "utf-8");
|
|
21953
|
-
const baseDir = includeBasePath ||
|
|
21954
|
-
const processedFiles = /* @__PURE__ */ new Set([
|
|
22009
|
+
const baseDir = includeBasePath || path34.dirname(filePath);
|
|
22010
|
+
const processedFiles = /* @__PURE__ */ new Set([path34.normalize(filePath)]);
|
|
21955
22011
|
const { frontmatter, content: withoutFrontmatter } = parseFrontmatter(rawContent);
|
|
21956
22012
|
const globs = parseFrontmatterPaths(frontmatter.paths);
|
|
21957
22013
|
const processedContent = processIncludes(withoutFrontmatter, baseDir, processedFiles);
|
|
@@ -21973,15 +22029,15 @@ function readMemoryFile(filePath, type, includeBasePath) {
|
|
|
21973
22029
|
}
|
|
21974
22030
|
function findGitRoot(startDir) {
|
|
21975
22031
|
let current = startDir;
|
|
21976
|
-
while (current !==
|
|
21977
|
-
const gitPath =
|
|
22032
|
+
while (current !== path34.dirname(current)) {
|
|
22033
|
+
const gitPath = path34.join(current, ".git");
|
|
21978
22034
|
try {
|
|
21979
22035
|
if (fs31.existsSync(gitPath)) {
|
|
21980
22036
|
return current;
|
|
21981
22037
|
}
|
|
21982
22038
|
} catch {
|
|
21983
22039
|
}
|
|
21984
|
-
current =
|
|
22040
|
+
current = path34.dirname(current);
|
|
21985
22041
|
}
|
|
21986
22042
|
return null;
|
|
21987
22043
|
}
|
|
@@ -22012,11 +22068,11 @@ function processRulesDirectory(rulesDir, type, processedPaths, conditionalRule =
|
|
|
22012
22068
|
try {
|
|
22013
22069
|
const entries = fs31.readdirSync(rulesDir, { withFileTypes: true });
|
|
22014
22070
|
for (const entry of entries) {
|
|
22015
|
-
const entryPath =
|
|
22071
|
+
const entryPath = path34.join(rulesDir, entry.name);
|
|
22016
22072
|
if (entry.isDirectory()) {
|
|
22017
22073
|
result.push(...processRulesDirectory(entryPath, type, processedPaths, conditionalRule));
|
|
22018
22074
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
22019
|
-
const normalizedPath =
|
|
22075
|
+
const normalizedPath = path34.normalize(entryPath);
|
|
22020
22076
|
if (processedPaths.has(normalizedPath)) {
|
|
22021
22077
|
continue;
|
|
22022
22078
|
}
|
|
@@ -22052,13 +22108,13 @@ function loadManagedMemory() {
|
|
|
22052
22108
|
function loadUserMemory() {
|
|
22053
22109
|
const files = [];
|
|
22054
22110
|
const homeDir = os21.homedir();
|
|
22055
|
-
const userBlumaDir =
|
|
22056
|
-
const userBlumaMd =
|
|
22111
|
+
const userBlumaDir = path34.join(homeDir, ".bluma");
|
|
22112
|
+
const userBlumaMd = path34.join(userBlumaDir, "BLUMA.md");
|
|
22057
22113
|
const userFile = readMemoryFile(userBlumaMd, "User");
|
|
22058
22114
|
if (userFile && userFile.content.trim()) {
|
|
22059
22115
|
files.push(userFile);
|
|
22060
22116
|
}
|
|
22061
|
-
const userRulesDir =
|
|
22117
|
+
const userRulesDir = path34.join(userBlumaDir, "rules");
|
|
22062
22118
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22063
22119
|
files.push(...processRulesDirectory(userRulesDir, "User", processedPaths, false));
|
|
22064
22120
|
return files;
|
|
@@ -22070,10 +22126,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22070
22126
|
let currentDir = cwd2;
|
|
22071
22127
|
const MAX_TRAVERSAL_DEPTH = 20;
|
|
22072
22128
|
let depth = 0;
|
|
22073
|
-
const normalizedGitRoot =
|
|
22074
|
-
while (currentDir !==
|
|
22129
|
+
const normalizedGitRoot = path34.resolve(gitRoot);
|
|
22130
|
+
while (currentDir !== path34.dirname(currentDir) && path34.resolve(currentDir).startsWith(normalizedGitRoot) && depth < MAX_TRAVERSAL_DEPTH) {
|
|
22075
22131
|
dirs.push(currentDir);
|
|
22076
|
-
currentDir =
|
|
22132
|
+
currentDir = path34.dirname(currentDir);
|
|
22077
22133
|
depth++;
|
|
22078
22134
|
}
|
|
22079
22135
|
if (!dirs.includes(gitRoot)) {
|
|
@@ -22081,7 +22137,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22081
22137
|
}
|
|
22082
22138
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
22083
22139
|
for (const dir of dirs.reverse()) {
|
|
22084
|
-
const projectBlumaMd =
|
|
22140
|
+
const projectBlumaMd = path34.join(dir, "BLUMA.md");
|
|
22085
22141
|
if (!processedPaths.has(projectBlumaMd)) {
|
|
22086
22142
|
processedPaths.add(projectBlumaMd);
|
|
22087
22143
|
const projectFile = readMemoryFile(projectBlumaMd, "Project");
|
|
@@ -22089,7 +22145,7 @@ function loadProjectMemory(cwd2) {
|
|
|
22089
22145
|
files.push(projectFile);
|
|
22090
22146
|
}
|
|
22091
22147
|
}
|
|
22092
|
-
const blumaDirBlumaMd =
|
|
22148
|
+
const blumaDirBlumaMd = path34.join(dir, ".bluma", "BLUMA.md");
|
|
22093
22149
|
if (!processedPaths.has(blumaDirBlumaMd)) {
|
|
22094
22150
|
processedPaths.add(blumaDirBlumaMd);
|
|
22095
22151
|
const blumaDirFile = readMemoryFile(blumaDirBlumaMd, "Project");
|
|
@@ -22097,10 +22153,10 @@ function loadProjectMemory(cwd2) {
|
|
|
22097
22153
|
files.push(blumaDirFile);
|
|
22098
22154
|
}
|
|
22099
22155
|
}
|
|
22100
|
-
const rulesDir =
|
|
22156
|
+
const rulesDir = path34.join(dir, ".bluma", "rules");
|
|
22101
22157
|
files.push(...processRulesDirectory(rulesDir, "Project", processedPaths, false));
|
|
22102
22158
|
}
|
|
22103
|
-
const localBlumaMd =
|
|
22159
|
+
const localBlumaMd = path34.join(cwd2, "BLUMA.local.md");
|
|
22104
22160
|
if (!processedPaths.has(localBlumaMd)) {
|
|
22105
22161
|
processedPaths.add(localBlumaMd);
|
|
22106
22162
|
const localFile = readMemoryFile(localBlumaMd, "Local");
|
|
@@ -22201,7 +22257,7 @@ function safeReadFile(filePath, maxChars) {
|
|
|
22201
22257
|
}
|
|
22202
22258
|
function tryReadReadme(cwd2) {
|
|
22203
22259
|
for (const name of ["README.md", "README.MD", "readme.md", "Readme.md"]) {
|
|
22204
|
-
const c = safeReadFile(
|
|
22260
|
+
const c = safeReadFile(path35.join(cwd2, name), LIMITS.readme);
|
|
22205
22261
|
if (c) return `(${name})
|
|
22206
22262
|
${c}`;
|
|
22207
22263
|
}
|
|
@@ -22209,14 +22265,14 @@ ${c}`;
|
|
|
22209
22265
|
}
|
|
22210
22266
|
function tryReadBluMaMd(cwd2) {
|
|
22211
22267
|
const paths2 = [
|
|
22212
|
-
|
|
22213
|
-
|
|
22214
|
-
|
|
22268
|
+
path35.join(cwd2, "BluMa.md"),
|
|
22269
|
+
path35.join(cwd2, "BLUMA.md"),
|
|
22270
|
+
path35.join(cwd2, ".bluma", "BluMa.md")
|
|
22215
22271
|
];
|
|
22216
22272
|
for (const p of paths2) {
|
|
22217
22273
|
const c = safeReadFile(p, LIMITS.blumaMd);
|
|
22218
22274
|
if (c) {
|
|
22219
|
-
const rel =
|
|
22275
|
+
const rel = path35.relative(cwd2, p) || p;
|
|
22220
22276
|
return `(${rel})
|
|
22221
22277
|
${c}`;
|
|
22222
22278
|
}
|
|
@@ -22224,7 +22280,7 @@ ${c}`;
|
|
|
22224
22280
|
return null;
|
|
22225
22281
|
}
|
|
22226
22282
|
function summarizePackageJson(cwd2) {
|
|
22227
|
-
const p =
|
|
22283
|
+
const p = path35.join(cwd2, "package.json");
|
|
22228
22284
|
try {
|
|
22229
22285
|
if (!fs32.existsSync(p)) return null;
|
|
22230
22286
|
const pkg = JSON.parse(fs32.readFileSync(p, "utf8"));
|
|
@@ -22318,7 +22374,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22318
22374
|
parts.push(pkg);
|
|
22319
22375
|
parts.push("```\n");
|
|
22320
22376
|
}
|
|
22321
|
-
const py = safeReadFile(
|
|
22377
|
+
const py = safeReadFile(path35.join(cwd2, "pyproject.toml"), LIMITS.pyproject);
|
|
22322
22378
|
if (py) {
|
|
22323
22379
|
parts.push("### pyproject.toml (excerpt)\n```toml");
|
|
22324
22380
|
parts.push(py);
|
|
@@ -22336,15 +22392,15 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22336
22392
|
parts.push(bluma);
|
|
22337
22393
|
parts.push("```\n");
|
|
22338
22394
|
}
|
|
22339
|
-
const contrib = safeReadFile(
|
|
22395
|
+
const contrib = safeReadFile(path35.join(cwd2, "CONTRIBUTING.md"), LIMITS.contributing);
|
|
22340
22396
|
if (contrib) {
|
|
22341
22397
|
parts.push("### CONTRIBUTING.md (excerpt)\n```markdown");
|
|
22342
22398
|
parts.push(contrib);
|
|
22343
22399
|
parts.push("```\n");
|
|
22344
22400
|
}
|
|
22345
|
-
const chlog = safeReadFile(
|
|
22401
|
+
const chlog = safeReadFile(path35.join(cwd2, "CHANGELOG.md"), LIMITS.changelog);
|
|
22346
22402
|
if (!chlog) {
|
|
22347
|
-
const alt = safeReadFile(
|
|
22403
|
+
const alt = safeReadFile(path35.join(cwd2, "CHANGES.md"), LIMITS.changelog);
|
|
22348
22404
|
if (alt) {
|
|
22349
22405
|
parts.push("### CHANGES.md (excerpt)\n```markdown");
|
|
22350
22406
|
parts.push(alt);
|
|
@@ -22380,14 +22436,14 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22380
22436
|
} else {
|
|
22381
22437
|
parts.push("### Git\n(not a git work tree, or `git` unavailable)\n");
|
|
22382
22438
|
}
|
|
22383
|
-
const tsconfig = safeReadFile(
|
|
22439
|
+
const tsconfig = safeReadFile(path35.join(cwd2, "tsconfig.json"), LIMITS.tsconfig);
|
|
22384
22440
|
if (tsconfig) {
|
|
22385
22441
|
parts.push("### tsconfig.json (excerpt)\n```json");
|
|
22386
22442
|
parts.push(tsconfig);
|
|
22387
22443
|
parts.push("```\n");
|
|
22388
22444
|
}
|
|
22389
22445
|
for (const name of ["Dockerfile", "dockerfile", "Dockerfile.prod", "Dockerfile.dev"]) {
|
|
22390
|
-
const df = safeReadFile(
|
|
22446
|
+
const df = safeReadFile(path35.join(cwd2, name), LIMITS.dockerfile);
|
|
22391
22447
|
if (df) {
|
|
22392
22448
|
parts.push(`### ${name} (excerpt)
|
|
22393
22449
|
`);
|
|
@@ -22397,7 +22453,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22397
22453
|
}
|
|
22398
22454
|
}
|
|
22399
22455
|
for (const name of ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"]) {
|
|
22400
|
-
const dc = safeReadFile(
|
|
22456
|
+
const dc = safeReadFile(path35.join(cwd2, name), LIMITS.dockerfile);
|
|
22401
22457
|
if (dc) {
|
|
22402
22458
|
parts.push(`### ${name} (excerpt)
|
|
22403
22459
|
`);
|
|
@@ -22412,7 +22468,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22412
22468
|
".circleci/config.yml",
|
|
22413
22469
|
"Jenkinsfile"
|
|
22414
22470
|
]) {
|
|
22415
|
-
const ciFile =
|
|
22471
|
+
const ciFile = path35.join(cwd2, ciPath);
|
|
22416
22472
|
if (fs32.existsSync(ciFile)) {
|
|
22417
22473
|
const st = fs32.statSync(ciFile);
|
|
22418
22474
|
if (st.isDirectory()) {
|
|
@@ -22428,7 +22484,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22428
22484
|
} else {
|
|
22429
22485
|
const ci = safeReadFile(ciFile, LIMITS.ciConfig);
|
|
22430
22486
|
if (ci) {
|
|
22431
|
-
parts.push(`### CI config (${
|
|
22487
|
+
parts.push(`### CI config (${path35.basename(ciPath)})
|
|
22432
22488
|
`);
|
|
22433
22489
|
parts.push(ci);
|
|
22434
22490
|
parts.push("\n");
|
|
@@ -22437,7 +22493,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22437
22493
|
}
|
|
22438
22494
|
}
|
|
22439
22495
|
for (const depFile of ["requirements.txt", "Pipfile", "poetry.lock", "Gemfile", "go.sum", "Cargo.lock"]) {
|
|
22440
|
-
const depPath =
|
|
22496
|
+
const depPath = path35.join(cwd2, depFile);
|
|
22441
22497
|
if (fs32.existsSync(depPath)) {
|
|
22442
22498
|
const depContent = safeReadFile(depPath, 1500);
|
|
22443
22499
|
if (depContent) {
|
|
@@ -22451,7 +22507,7 @@ function buildWorkspaceSnapshot(cwd2) {
|
|
|
22451
22507
|
}
|
|
22452
22508
|
}
|
|
22453
22509
|
for (const envFile of [".env.example", ".env.sample", ".env.template"]) {
|
|
22454
|
-
const envPath =
|
|
22510
|
+
const envPath = path35.join(cwd2, envFile);
|
|
22455
22511
|
if (fs32.existsSync(envPath)) {
|
|
22456
22512
|
try {
|
|
22457
22513
|
const raw = fs32.readFileSync(envPath, "utf-8");
|
|
@@ -22479,13 +22535,13 @@ init_runtime_config();
|
|
|
22479
22535
|
init_sandbox_policy();
|
|
22480
22536
|
import fs33 from "fs";
|
|
22481
22537
|
import os22 from "os";
|
|
22482
|
-
import
|
|
22538
|
+
import path36 from "path";
|
|
22483
22539
|
function getProjectPluginsDir() {
|
|
22484
22540
|
const policy = getSandboxPolicy();
|
|
22485
|
-
return
|
|
22541
|
+
return path36.join(policy.workspaceRoot, ".bluma", "plugins");
|
|
22486
22542
|
}
|
|
22487
22543
|
function getGlobalPluginsDir() {
|
|
22488
|
-
return
|
|
22544
|
+
return path36.join(process.env.HOME || os22.homedir(), ".bluma", "plugins");
|
|
22489
22545
|
}
|
|
22490
22546
|
function getPluginDirs() {
|
|
22491
22547
|
return {
|
|
@@ -22511,8 +22567,8 @@ function readManifest(manifestPath, fallbackName) {
|
|
|
22511
22567
|
}
|
|
22512
22568
|
function findManifestPath(pluginDir) {
|
|
22513
22569
|
const candidates = [
|
|
22514
|
-
|
|
22515
|
-
|
|
22570
|
+
path36.join(pluginDir, ".codex-plugin", "plugin.json"),
|
|
22571
|
+
path36.join(pluginDir, "plugin.json")
|
|
22516
22572
|
];
|
|
22517
22573
|
for (const candidate of candidates) {
|
|
22518
22574
|
if (fs33.existsSync(candidate)) {
|
|
@@ -22526,7 +22582,7 @@ function listFromDir(baseDir, source) {
|
|
|
22526
22582
|
return [];
|
|
22527
22583
|
}
|
|
22528
22584
|
return fs33.readdirSync(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).flatMap((entry) => {
|
|
22529
|
-
const pluginDir =
|
|
22585
|
+
const pluginDir = path36.join(baseDir, entry.name);
|
|
22530
22586
|
const manifestPath = findManifestPath(pluginDir);
|
|
22531
22587
|
if (!manifestPath) {
|
|
22532
22588
|
return [];
|
|
@@ -22972,7 +23028,7 @@ function buildModelInfoSection(modelId) {
|
|
|
22972
23028
|
// src/app/agent/runtime/hook_registry.ts
|
|
22973
23029
|
init_sandbox_policy();
|
|
22974
23030
|
import fs34 from "fs";
|
|
22975
|
-
import
|
|
23031
|
+
import path37 from "path";
|
|
22976
23032
|
var DEFAULT_STATE = {
|
|
22977
23033
|
enabled: true,
|
|
22978
23034
|
maxEvents: 120,
|
|
@@ -22983,7 +23039,7 @@ var cache3 = null;
|
|
|
22983
23039
|
var cachePath2 = null;
|
|
22984
23040
|
function getStatePath() {
|
|
22985
23041
|
const policy = getSandboxPolicy();
|
|
22986
|
-
return
|
|
23042
|
+
return path37.join(policy.workspaceRoot, ".bluma", "hooks.json");
|
|
22987
23043
|
}
|
|
22988
23044
|
function getHookStatePath() {
|
|
22989
23045
|
return getStatePath();
|
|
@@ -23029,7 +23085,7 @@ function ensureLoaded2() {
|
|
|
23029
23085
|
}
|
|
23030
23086
|
function persist2(state2) {
|
|
23031
23087
|
const statePath = getStatePath();
|
|
23032
|
-
fs34.mkdirSync(
|
|
23088
|
+
fs34.mkdirSync(path37.dirname(statePath), { recursive: true });
|
|
23033
23089
|
state2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23034
23090
|
fs34.writeFileSync(statePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
23035
23091
|
cache3 = state2;
|
|
@@ -23282,9 +23338,9 @@ Usa s\xF3 facts do pedido; campos em falta \u2192 "n\xE3o fornecido" \u2014 nunc
|
|
|
23282
23338
|
|
|
23283
23339
|
// src/app/agent/core/prompt/auto_memory.ts
|
|
23284
23340
|
import fs35 from "fs";
|
|
23285
|
-
import
|
|
23341
|
+
import path38 from "path";
|
|
23286
23342
|
import os23 from "os";
|
|
23287
|
-
var AUTO_MEMORY_FILE =
|
|
23343
|
+
var AUTO_MEMORY_FILE = path38.join(os23.homedir(), ".bluma", "auto_memory.md");
|
|
23288
23344
|
var MAX_AUTO_MEMORY_CHARS = 25e3;
|
|
23289
23345
|
var MAX_AUTO_MEMORY_LINES = 200;
|
|
23290
23346
|
function getAutoMemoryForPrompt() {
|
|
@@ -23446,17 +23502,17 @@ function getGitBranch(dir) {
|
|
|
23446
23502
|
}
|
|
23447
23503
|
}
|
|
23448
23504
|
function getPackageManager(dir) {
|
|
23449
|
-
if (fs36.existsSync(
|
|
23450
|
-
if (fs36.existsSync(
|
|
23451
|
-
if (fs36.existsSync(
|
|
23452
|
-
if (fs36.existsSync(
|
|
23505
|
+
if (fs36.existsSync(path39.join(dir, "pnpm-lock.yaml"))) return "pnpm";
|
|
23506
|
+
if (fs36.existsSync(path39.join(dir, "yarn.lock"))) return "yarn";
|
|
23507
|
+
if (fs36.existsSync(path39.join(dir, "bun.lockb"))) return "bun";
|
|
23508
|
+
if (fs36.existsSync(path39.join(dir, "package-lock.json"))) return "npm";
|
|
23453
23509
|
return "unknown";
|
|
23454
23510
|
}
|
|
23455
23511
|
function getProjectType(dir) {
|
|
23456
23512
|
try {
|
|
23457
23513
|
const files = fs36.readdirSync(dir);
|
|
23458
23514
|
if (files.includes("package.json")) {
|
|
23459
|
-
const pkg = JSON.parse(fs36.readFileSync(
|
|
23515
|
+
const pkg = JSON.parse(fs36.readFileSync(path39.join(dir, "package.json"), "utf-8"));
|
|
23460
23516
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
23461
23517
|
if (deps.next) return "Next.js";
|
|
23462
23518
|
if (deps.react) return "React";
|
|
@@ -23476,7 +23532,7 @@ function getProjectType(dir) {
|
|
|
23476
23532
|
}
|
|
23477
23533
|
function getTestFramework(dir) {
|
|
23478
23534
|
try {
|
|
23479
|
-
const pkgPath =
|
|
23535
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23480
23536
|
if (fs36.existsSync(pkgPath)) {
|
|
23481
23537
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23482
23538
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
@@ -23487,7 +23543,7 @@ function getTestFramework(dir) {
|
|
|
23487
23543
|
if (deps["@playwright/test"]) return "playwright";
|
|
23488
23544
|
if (deps.cypress) return "cypress";
|
|
23489
23545
|
}
|
|
23490
|
-
if (fs36.existsSync(
|
|
23546
|
+
if (fs36.existsSync(path39.join(dir, "pytest.ini")) || fs36.existsSync(path39.join(dir, "conftest.py"))) return "pytest";
|
|
23491
23547
|
return "unknown";
|
|
23492
23548
|
} catch {
|
|
23493
23549
|
return "unknown";
|
|
@@ -23495,7 +23551,7 @@ function getTestFramework(dir) {
|
|
|
23495
23551
|
}
|
|
23496
23552
|
function getTestCommand(dir) {
|
|
23497
23553
|
try {
|
|
23498
|
-
const pkgPath =
|
|
23554
|
+
const pkgPath = path39.join(dir, "package.json");
|
|
23499
23555
|
if (fs36.existsSync(pkgPath)) {
|
|
23500
23556
|
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
|
|
23501
23557
|
if (pkg.scripts?.test) return "npm test";
|
|
@@ -23512,7 +23568,7 @@ function getTestCommand(dir) {
|
|
|
23512
23568
|
}
|
|
23513
23569
|
function isGitRepo(dir) {
|
|
23514
23570
|
try {
|
|
23515
|
-
const p =
|
|
23571
|
+
const p = path39.join(dir, ".git");
|
|
23516
23572
|
return fs36.existsSync(p) && fs36.lstatSync(p).isDirectory();
|
|
23517
23573
|
} catch {
|
|
23518
23574
|
return false;
|
|
@@ -24936,7 +24992,7 @@ var LLMService = class {
|
|
|
24936
24992
|
// src/app/agent/utils/user_message_images.ts
|
|
24937
24993
|
import fs37 from "fs";
|
|
24938
24994
|
import os26 from "os";
|
|
24939
|
-
import
|
|
24995
|
+
import path40 from "path";
|
|
24940
24996
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
24941
24997
|
var IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp)$/i;
|
|
24942
24998
|
var MAX_IMAGE_BYTES = 4 * 1024 * 1024;
|
|
@@ -24952,22 +25008,22 @@ var MIME = {
|
|
|
24952
25008
|
function expandUserPath(p) {
|
|
24953
25009
|
const t = p.trim();
|
|
24954
25010
|
if (t.startsWith("~")) {
|
|
24955
|
-
return
|
|
25011
|
+
return path40.join(os26.homedir(), t.slice(1).replace(/^\//, ""));
|
|
24956
25012
|
}
|
|
24957
25013
|
return t;
|
|
24958
25014
|
}
|
|
24959
25015
|
function isPathAllowed(absResolved, cwd2) {
|
|
24960
|
-
const resolved =
|
|
24961
|
-
const cwdR =
|
|
24962
|
-
const homeR =
|
|
24963
|
-
const tmpR =
|
|
24964
|
-
const underCwd = resolved === cwdR || resolved.startsWith(cwdR +
|
|
24965
|
-
const underHome = resolved === homeR || resolved.startsWith(homeR +
|
|
24966
|
-
const underTmp = resolved === tmpR || resolved.startsWith(tmpR +
|
|
25016
|
+
const resolved = path40.normalize(path40.resolve(absResolved));
|
|
25017
|
+
const cwdR = path40.normalize(path40.resolve(cwd2));
|
|
25018
|
+
const homeR = path40.normalize(path40.resolve(os26.homedir()));
|
|
25019
|
+
const tmpR = path40.normalize(path40.resolve(os26.tmpdir()));
|
|
25020
|
+
const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path40.sep);
|
|
25021
|
+
const underHome = resolved === homeR || resolved.startsWith(homeR + path40.sep);
|
|
25022
|
+
const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path40.sep);
|
|
24967
25023
|
return underCwd || underHome || underTmp;
|
|
24968
25024
|
}
|
|
24969
25025
|
function mimeFor(abs) {
|
|
24970
|
-
const ext =
|
|
25026
|
+
const ext = path40.extname(abs).toLowerCase();
|
|
24971
25027
|
return MIME[ext] || "application/octet-stream";
|
|
24972
25028
|
}
|
|
24973
25029
|
var IMAGE_EXT_SRC = String.raw`(?:png|jpe?g|gif|webp|bmp)`;
|
|
@@ -25011,7 +25067,7 @@ function collectImagePathStrings(raw) {
|
|
|
25011
25067
|
}
|
|
25012
25068
|
function resolveImagePath(candidate, cwd2) {
|
|
25013
25069
|
const expanded = expandUserPath(candidate);
|
|
25014
|
-
const abs =
|
|
25070
|
+
const abs = path40.isAbsolute(expanded) ? path40.normalize(expanded) : path40.normalize(path40.resolve(cwd2, expanded));
|
|
25015
25071
|
if (!isPathAllowed(abs, cwd2)) return null;
|
|
25016
25072
|
try {
|
|
25017
25073
|
if (!fs37.existsSync(abs) || !fs37.statSync(abs).isFile()) return null;
|
|
@@ -25034,7 +25090,7 @@ function trySingleLineFileUriOrBareImagePath(line, cwd2) {
|
|
|
25034
25090
|
if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
|
|
25035
25091
|
s = s.slice(1, -1).trim();
|
|
25036
25092
|
}
|
|
25037
|
-
if (!IMAGE_EXT.test(
|
|
25093
|
+
if (!IMAGE_EXT.test(path40.extname(s))) return null;
|
|
25038
25094
|
const abs = resolveImagePath(s, cwd2);
|
|
25039
25095
|
if (!abs) return null;
|
|
25040
25096
|
try {
|
|
@@ -25137,7 +25193,7 @@ function buildUserMessageContent(raw, cwd2) {
|
|
|
25137
25193
|
init_sandbox_policy();
|
|
25138
25194
|
init_runtime_config();
|
|
25139
25195
|
init_permission_rules();
|
|
25140
|
-
import
|
|
25196
|
+
import path41 from "path";
|
|
25141
25197
|
var LOCAL_EDIT_TOOL_NAMES = /* @__PURE__ */ new Set(["edit_tool", "file_write", "notebook_edit"]);
|
|
25142
25198
|
function getToolPermissionLayer(metadata) {
|
|
25143
25199
|
if (metadata.riskLevel === "safe") return "read";
|
|
@@ -25152,11 +25208,11 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25152
25208
|
if (!filePath) {
|
|
25153
25209
|
return { allowed: false, reason: "No file path provided for permission check." };
|
|
25154
25210
|
}
|
|
25155
|
-
const resolvedPath =
|
|
25211
|
+
const resolvedPath = path41.resolve(filePath);
|
|
25156
25212
|
if (!isPathInsideWorkspace(resolvedPath, policy)) {
|
|
25157
25213
|
return { allowed: false, reason: `File path "${filePath}" is outside workspace root.` };
|
|
25158
25214
|
}
|
|
25159
|
-
const relativePath =
|
|
25215
|
+
const relativePath = path41.relative(policy.workspaceRoot, resolvedPath);
|
|
25160
25216
|
const toolPattern = `${toolName}(${relativePath})`;
|
|
25161
25217
|
const ruleDecision = permissionRulesEngine.checkPermission(toolPattern, { filepath: filePath });
|
|
25162
25218
|
if (ruleDecision === "deny") {
|
|
@@ -25165,7 +25221,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25165
25221
|
if (ruleDecision === "allow") {
|
|
25166
25222
|
return { allowed: true, reason: `File "${filePath}" allowed by permission rules.` };
|
|
25167
25223
|
}
|
|
25168
|
-
const dirPath =
|
|
25224
|
+
const dirPath = path41.dirname(relativePath);
|
|
25169
25225
|
const dirPattern = `${toolName}(${dirPath}/**)`;
|
|
25170
25226
|
const dirRuleDecision = permissionRulesEngine.checkPermission(dirPattern, { filepath: filePath });
|
|
25171
25227
|
if (dirRuleDecision === "allow") {
|
|
@@ -25383,10 +25439,10 @@ function effectiveToolAutoApprove(toolCall, sessionId, options) {
|
|
|
25383
25439
|
|
|
25384
25440
|
// src/app/agent/tools/CodingMemoryTool/CodingMemoryConsolidate.ts
|
|
25385
25441
|
import * as fs38 from "fs";
|
|
25386
|
-
import * as
|
|
25442
|
+
import * as path42 from "path";
|
|
25387
25443
|
import os27 from "os";
|
|
25388
25444
|
function memoryPath2() {
|
|
25389
|
-
return
|
|
25445
|
+
return path42.join(process.env.HOME || os27.homedir(), ".bluma", "coding_memory.json");
|
|
25390
25446
|
}
|
|
25391
25447
|
function normalizeNote2(note) {
|
|
25392
25448
|
return note.trim().toLowerCase().replace(/\s+/g, " ");
|
|
@@ -25947,16 +26003,16 @@ var BluMaToolRunner = class {
|
|
|
25947
26003
|
};
|
|
25948
26004
|
|
|
25949
26005
|
// src/app/agent/session_manager/session_archive.ts
|
|
25950
|
-
import
|
|
26006
|
+
import path43 from "path";
|
|
25951
26007
|
import { promises as fs39 } from "fs";
|
|
25952
26008
|
async function archivePrunedConversationMessages(sessionId, messages) {
|
|
25953
26009
|
if (!sessionId || messages.length === 0) {
|
|
25954
26010
|
return null;
|
|
25955
26011
|
}
|
|
25956
26012
|
const appDir = getPreferredAppDir();
|
|
25957
|
-
const dir =
|
|
26013
|
+
const dir = path43.join(appDir, "sessions", "archive", sessionId);
|
|
25958
26014
|
await fs39.mkdir(dir, { recursive: true });
|
|
25959
|
-
const archiveFile =
|
|
26015
|
+
const archiveFile = path43.join(dir, `${Date.now()}.jsonl`);
|
|
25960
26016
|
const lines = messages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
25961
26017
|
await fs39.appendFile(archiveFile, lines, "utf-8");
|
|
25962
26018
|
return archiveFile;
|
|
@@ -26793,7 +26849,7 @@ var BluMaAgent = class {
|
|
|
26793
26849
|
if (!this.sessionFile) return;
|
|
26794
26850
|
try {
|
|
26795
26851
|
const sessionData = {
|
|
26796
|
-
session_id:
|
|
26852
|
+
session_id: path44.basename(this.sessionFile, ".json"),
|
|
26797
26853
|
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26798
26854
|
conversation_history: this.history,
|
|
26799
26855
|
last_updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -27005,7 +27061,7 @@ var BluMaAgent = class {
|
|
|
27005
27061
|
|
|
27006
27062
|
${editData.error.display}`;
|
|
27007
27063
|
}
|
|
27008
|
-
const filename =
|
|
27064
|
+
const filename = path44.basename(toolArgs.file_path);
|
|
27009
27065
|
return createDiff(filename, editData.currentContent || "", editData.newContent);
|
|
27010
27066
|
} catch (e) {
|
|
27011
27067
|
return `An unexpected error occurred while generating the edit preview: ${e.message}`;
|
|
@@ -27733,14 +27789,14 @@ async function fullCompact(messages, targetTokens, summarizer, llmClient) {
|
|
|
27733
27789
|
// src/app/agent/core/memory/session_memory.ts
|
|
27734
27790
|
import fs41 from "fs";
|
|
27735
27791
|
import os30 from "os";
|
|
27736
|
-
import
|
|
27792
|
+
import path45 from "path";
|
|
27737
27793
|
import { v4 as uuidv49 } from "uuid";
|
|
27738
27794
|
var SessionMemoryExtractor = class {
|
|
27739
27795
|
llmClient;
|
|
27740
27796
|
memoryFile;
|
|
27741
27797
|
constructor(options = {}) {
|
|
27742
27798
|
this.llmClient = options.llmClient;
|
|
27743
|
-
this.memoryFile = options.memoryFile ||
|
|
27799
|
+
this.memoryFile = options.memoryFile || path45.join(os30.homedir(), ".bluma", "session_memory.json");
|
|
27744
27800
|
}
|
|
27745
27801
|
/**
|
|
27746
27802
|
* Extract memories from conversation using LLM
|
|
@@ -28349,14 +28405,14 @@ var RouteManager = class {
|
|
|
28349
28405
|
this.subAgents = subAgents;
|
|
28350
28406
|
this.core = core;
|
|
28351
28407
|
}
|
|
28352
|
-
registerRoute(
|
|
28353
|
-
this.routeHandlers.set(
|
|
28408
|
+
registerRoute(path57, handler) {
|
|
28409
|
+
this.routeHandlers.set(path57, handler);
|
|
28354
28410
|
}
|
|
28355
28411
|
async handleRoute(payload) {
|
|
28356
28412
|
const inputText = String(payload.content || "").trim();
|
|
28357
28413
|
const { userContext, options } = payload;
|
|
28358
|
-
for (const [
|
|
28359
|
-
if (inputText ===
|
|
28414
|
+
for (const [path57, handler] of this.routeHandlers) {
|
|
28415
|
+
if (inputText === path57 || inputText.startsWith(`${path57} `)) {
|
|
28360
28416
|
return handler({ content: inputText, userContext });
|
|
28361
28417
|
}
|
|
28362
28418
|
}
|
|
@@ -28365,13 +28421,13 @@ var RouteManager = class {
|
|
|
28365
28421
|
};
|
|
28366
28422
|
|
|
28367
28423
|
// src/app/agent/runtime/plugin_runtime.ts
|
|
28368
|
-
import
|
|
28424
|
+
import path46 from "path";
|
|
28369
28425
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
28370
28426
|
async function loadPluginsAtStartup() {
|
|
28371
28427
|
for (const p of listPlugins()) {
|
|
28372
28428
|
const entry = p.manifest.entry?.trim();
|
|
28373
28429
|
if (!entry) continue;
|
|
28374
|
-
const abs =
|
|
28430
|
+
const abs = path46.resolve(p.root, entry);
|
|
28375
28431
|
try {
|
|
28376
28432
|
const href = pathToFileURL2(abs).href;
|
|
28377
28433
|
const mod = await import(href);
|
|
@@ -28392,7 +28448,7 @@ async function loadPluginsAtStartup() {
|
|
|
28392
28448
|
}
|
|
28393
28449
|
|
|
28394
28450
|
// src/app/agent/agent.ts
|
|
28395
|
-
var globalEnvPath =
|
|
28451
|
+
var globalEnvPath = path47.join(os31.homedir(), ".bluma", ".env");
|
|
28396
28452
|
dotenv.config({ path: globalEnvPath });
|
|
28397
28453
|
var Agent = class {
|
|
28398
28454
|
sessionId;
|
|
@@ -30248,10 +30304,10 @@ function resolveToolPayload(result) {
|
|
|
30248
30304
|
|
|
30249
30305
|
// src/app/ui/components/FilePathLink.tsx
|
|
30250
30306
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
30251
|
-
import
|
|
30307
|
+
import path49 from "node:path";
|
|
30252
30308
|
|
|
30253
30309
|
// src/app/ui/utils/pathDisplay.ts
|
|
30254
|
-
import
|
|
30310
|
+
import path48 from "node:path";
|
|
30255
30311
|
import os32 from "node:os";
|
|
30256
30312
|
function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
30257
30313
|
let s = String(pathInput ?? "").trim();
|
|
@@ -30259,17 +30315,17 @@ function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
|
|
|
30259
30315
|
s = s.replace(/[/\\]+$/, "");
|
|
30260
30316
|
}
|
|
30261
30317
|
if (!s) return "";
|
|
30262
|
-
const abs =
|
|
30263
|
-
const resolvedCwd =
|
|
30264
|
-
const rel =
|
|
30265
|
-
if (rel === "" || !rel.startsWith("..") && !
|
|
30318
|
+
const abs = path48.isAbsolute(s) ? path48.normalize(s) : path48.resolve(cwd2, s);
|
|
30319
|
+
const resolvedCwd = path48.resolve(cwd2);
|
|
30320
|
+
const rel = path48.relative(resolvedCwd, abs);
|
|
30321
|
+
if (rel === "" || !rel.startsWith("..") && !path48.isAbsolute(rel)) {
|
|
30266
30322
|
return rel === "" ? "." : rel;
|
|
30267
30323
|
}
|
|
30268
|
-
const home =
|
|
30269
|
-
if (abs === home || abs.startsWith(home +
|
|
30324
|
+
const home = path48.normalize(os32.homedir());
|
|
30325
|
+
if (abs === home || abs.startsWith(home + path48.sep)) {
|
|
30270
30326
|
return "~" + abs.slice(home.length);
|
|
30271
30327
|
}
|
|
30272
|
-
return
|
|
30328
|
+
return path48.basename(abs);
|
|
30273
30329
|
}
|
|
30274
30330
|
|
|
30275
30331
|
// src/app/ui/components/FilePathLink.tsx
|
|
@@ -30279,7 +30335,7 @@ function FilePathLink({ filePath, children, cwd: cwd2 = process.cwd(), color })
|
|
|
30279
30335
|
if (!raw) {
|
|
30280
30336
|
return null;
|
|
30281
30337
|
}
|
|
30282
|
-
const abs =
|
|
30338
|
+
const abs = path49.isAbsolute(raw) ? path49.normalize(raw) : path49.resolve(cwd2, raw);
|
|
30283
30339
|
const href = pathToFileURL3(abs).href;
|
|
30284
30340
|
const label = formatPathForDisplay(abs, cwd2);
|
|
30285
30341
|
const text = typeof children === "string" ? children : label;
|
|
@@ -32914,13 +32970,13 @@ function EditToolDiffPanel({
|
|
|
32914
32970
|
newString,
|
|
32915
32971
|
replaceAll = false
|
|
32916
32972
|
}) {
|
|
32917
|
-
const
|
|
32973
|
+
const path57 = filePath.trim() || "unknown file";
|
|
32918
32974
|
const hasPreviewArgs = oldString !== void 0 && newString !== void 0;
|
|
32919
32975
|
const hasDiffText = diffText && diffText.trim().length > 0;
|
|
32920
32976
|
return /* @__PURE__ */ jsx43(Box_default, { flexDirection: "column", children: hasPreviewArgs ? /* @__PURE__ */ jsx43(Box_default, { marginTop: 0, children: /* @__PURE__ */ jsx43(
|
|
32921
32977
|
FileEditToolDiff,
|
|
32922
32978
|
{
|
|
32923
|
-
filePath:
|
|
32979
|
+
filePath: path57,
|
|
32924
32980
|
oldString,
|
|
32925
32981
|
newString,
|
|
32926
32982
|
replaceAll,
|
|
@@ -32958,7 +33014,7 @@ function renderToolUseMessage12({ args }) {
|
|
|
32958
33014
|
return /* @__PURE__ */ jsx44(Text, { color: BLUMA_TERMINAL.blue, children: p });
|
|
32959
33015
|
}
|
|
32960
33016
|
function renderToolHeader12({ args }) {
|
|
32961
|
-
const
|
|
33017
|
+
const path57 = args?.file_path ?? ".";
|
|
32962
33018
|
const oldText = typeof args?.old_string === "string" ? args.old_string : "";
|
|
32963
33019
|
const newText = typeof args?.new_string === "string" ? args.new_string : "";
|
|
32964
33020
|
const counts = countLineDiff(oldText, newText);
|
|
@@ -32968,7 +33024,7 @@ function renderToolHeader12({ args }) {
|
|
|
32968
33024
|
action,
|
|
32969
33025
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
32970
33026
|
" ",
|
|
32971
|
-
/* @__PURE__ */ jsx44(FilePathLink, { filePath:
|
|
33027
|
+
/* @__PURE__ */ jsx44(FilePathLink, { filePath: path57, color: BLUMA_TERMINAL.dim })
|
|
32972
33028
|
] })
|
|
32973
33029
|
] }),
|
|
32974
33030
|
/* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
|
|
@@ -33360,11 +33416,11 @@ function userFacingName13() {
|
|
|
33360
33416
|
}
|
|
33361
33417
|
function renderToolUseMessage14({ args }) {
|
|
33362
33418
|
const q = args?.query ? `"${args.query}"` : "...";
|
|
33363
|
-
const
|
|
33419
|
+
const path57 = args?.path || ".";
|
|
33364
33420
|
return /* @__PURE__ */ jsxs30(Box_default, { flexDirection: "row", flexWrap: "wrap", alignItems: "flex-end", children: [
|
|
33365
33421
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.blue, children: q }),
|
|
33366
33422
|
/* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.dim, children: " " }),
|
|
33367
|
-
/* @__PURE__ */ jsx47(FilePathLink, { filePath:
|
|
33423
|
+
/* @__PURE__ */ jsx47(FilePathLink, { filePath: path57, color: BLUMA_TERMINAL.dim })
|
|
33368
33424
|
] });
|
|
33369
33425
|
}
|
|
33370
33426
|
function renderToolHeader14({ args }) {
|
|
@@ -36832,7 +36888,7 @@ import {
|
|
|
36832
36888
|
// src/app/ui/hooks/useAtCompletion.ts
|
|
36833
36889
|
import { useEffect as useEffect11, useRef as useRef4, useState as useState13 } from "react";
|
|
36834
36890
|
import fs44 from "fs";
|
|
36835
|
-
import
|
|
36891
|
+
import path50 from "path";
|
|
36836
36892
|
var MAX_RESULTS3 = 50;
|
|
36837
36893
|
var DEFAULT_RECURSIVE_DEPTH = 2;
|
|
36838
36894
|
function listPathSuggestions(baseDir, pattern) {
|
|
@@ -36840,7 +36896,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
36840
36896
|
const patternEndsWithSlash = raw.endsWith("/");
|
|
36841
36897
|
const relDir = raw.replace(/^\/+|\/+$/g, "");
|
|
36842
36898
|
const filterPrefix = patternEndsWithSlash ? "" : relDir.split("/").slice(-1)[0] || "";
|
|
36843
|
-
const listDir =
|
|
36899
|
+
const listDir = path50.resolve(baseDir, relDir || ".");
|
|
36844
36900
|
const results = [];
|
|
36845
36901
|
const IGNORED_DIRS = ["node_modules", ".git", ".venv", "dist", "build"];
|
|
36846
36902
|
const IGNORED_EXTS = [".pyc", ".class", ".o", ".map", ".log", ".tmp"];
|
|
@@ -36857,7 +36913,7 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
36857
36913
|
}
|
|
36858
36914
|
function pushEntry(entryPath, label, isDir) {
|
|
36859
36915
|
if (results.length >= MAX_RESULTS3) return;
|
|
36860
|
-
const clean = label.split(
|
|
36916
|
+
const clean = label.split(path50.sep).join("/").replace(/[]+/g, "");
|
|
36861
36917
|
results.push({ label: clean + (isDir ? "/" : ""), fullPath: entryPath, isDir });
|
|
36862
36918
|
}
|
|
36863
36919
|
try {
|
|
@@ -36869,8 +36925,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
36869
36925
|
const entries = fs44.readdirSync(node.dir, { withFileTypes: true });
|
|
36870
36926
|
for (const entry of entries) {
|
|
36871
36927
|
if (isIgnoredName(entry.name)) continue;
|
|
36872
|
-
const entryAbs =
|
|
36873
|
-
const entryRel = node.rel ?
|
|
36928
|
+
const entryAbs = path50.join(node.dir, entry.name);
|
|
36929
|
+
const entryRel = node.rel ? path50.posix.join(node.rel, entry.name) : entry.name;
|
|
36874
36930
|
if (entryRel.split("/").includes("node_modules")) continue;
|
|
36875
36931
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
36876
36932
|
pushEntry(entryAbs, entryRel, entry.isDirectory());
|
|
@@ -36888,8 +36944,8 @@ function listPathSuggestions(baseDir, pattern) {
|
|
|
36888
36944
|
if (filterPrefix && !entry.name.startsWith(filterPrefix)) continue;
|
|
36889
36945
|
if (isIgnoredName(entry.name)) continue;
|
|
36890
36946
|
if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
|
|
36891
|
-
const entryAbs =
|
|
36892
|
-
const label = relDir ?
|
|
36947
|
+
const entryAbs = path50.join(listDir, entry.name);
|
|
36948
|
+
const label = relDir ? path50.posix.join(relDir, entry.name) : entry.name;
|
|
36893
36949
|
pushEntry(entryAbs, label, entry.isDirectory());
|
|
36894
36950
|
if (results.length >= MAX_RESULTS3) break;
|
|
36895
36951
|
}
|
|
@@ -37092,7 +37148,7 @@ var SlashSubmenuInline = memo15(SlashSubmenuInlineComponent);
|
|
|
37092
37148
|
// src/app/ui/utils/clipboardImage.ts
|
|
37093
37149
|
import fs45 from "fs";
|
|
37094
37150
|
import os33 from "os";
|
|
37095
|
-
import
|
|
37151
|
+
import path51 from "path";
|
|
37096
37152
|
import { spawn as spawn5, execFile as execFileCb, execSync as execSync4 } from "child_process";
|
|
37097
37153
|
import { promisify as promisify2 } from "util";
|
|
37098
37154
|
|
|
@@ -37221,8 +37277,8 @@ function commandOnPath(cmd) {
|
|
|
37221
37277
|
function unixClipboardHelperDirs() {
|
|
37222
37278
|
const h = os33.homedir();
|
|
37223
37279
|
return [
|
|
37224
|
-
|
|
37225
|
-
|
|
37280
|
+
path51.join(h, ".local", "bin"),
|
|
37281
|
+
path51.join(h, "bin"),
|
|
37226
37282
|
"/usr/bin",
|
|
37227
37283
|
"/usr/local/bin",
|
|
37228
37284
|
"/bin",
|
|
@@ -37240,7 +37296,7 @@ function resolveHelperBinary(cmd) {
|
|
|
37240
37296
|
return cmd;
|
|
37241
37297
|
}
|
|
37242
37298
|
for (const dir of unixClipboardHelperDirs()) {
|
|
37243
|
-
const full =
|
|
37299
|
+
const full = path51.join(dir, cmd);
|
|
37244
37300
|
try {
|
|
37245
37301
|
fs45.accessSync(full, fs45.constants.X_OK);
|
|
37246
37302
|
return full;
|
|
@@ -37248,7 +37304,7 @@ function resolveHelperBinary(cmd) {
|
|
|
37248
37304
|
}
|
|
37249
37305
|
}
|
|
37250
37306
|
for (const dir of unixClipboardHelperDirs()) {
|
|
37251
|
-
const full =
|
|
37307
|
+
const full = path51.join(dir, cmd);
|
|
37252
37308
|
if (fs45.existsSync(full)) {
|
|
37253
37309
|
return full;
|
|
37254
37310
|
}
|
|
@@ -37290,7 +37346,7 @@ function writeBufferIfImage(baseDir, buf) {
|
|
|
37290
37346
|
if (!ext) {
|
|
37291
37347
|
return null;
|
|
37292
37348
|
}
|
|
37293
|
-
const out =
|
|
37349
|
+
const out = path51.join(
|
|
37294
37350
|
baseDir,
|
|
37295
37351
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
37296
37352
|
);
|
|
@@ -37329,9 +37385,9 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
37329
37385
|
if (st.size < 80 || st.size > CLIPBOARD_MAX_BYTES) {
|
|
37330
37386
|
continue;
|
|
37331
37387
|
}
|
|
37332
|
-
const ext =
|
|
37388
|
+
const ext = path51.extname(src).toLowerCase();
|
|
37333
37389
|
const safeExt = ext && /^\.(png|jpe?g|gif|webp)$/i.test(ext) ? ext : ".png";
|
|
37334
|
-
const out =
|
|
37390
|
+
const out = path51.join(
|
|
37335
37391
|
baseDir,
|
|
37336
37392
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${safeExt}`
|
|
37337
37393
|
);
|
|
@@ -37349,7 +37405,7 @@ async function tryDarwinClipboardy(baseDir) {
|
|
|
37349
37405
|
return null;
|
|
37350
37406
|
}
|
|
37351
37407
|
async function tryWindowsPowerShell(outFile) {
|
|
37352
|
-
const ps = process.env.SystemRoot != null ?
|
|
37408
|
+
const ps = process.env.SystemRoot != null ? path51.join(
|
|
37353
37409
|
process.env.SystemRoot,
|
|
37354
37410
|
"System32",
|
|
37355
37411
|
"WindowsPowerShell",
|
|
@@ -37450,8 +37506,8 @@ function parseClipboardTextAsImagePath(raw) {
|
|
|
37450
37506
|
s = s.slice(1, -1);
|
|
37451
37507
|
}
|
|
37452
37508
|
s = s.trim();
|
|
37453
|
-
if (!CLIPBOARD_PATH_IMAGE_EXT.test(
|
|
37454
|
-
const abs =
|
|
37509
|
+
if (!CLIPBOARD_PATH_IMAGE_EXT.test(path51.extname(s))) return null;
|
|
37510
|
+
const abs = path51.isAbsolute(s) ? path51.normalize(s) : path51.resolve(process.cwd(), s);
|
|
37455
37511
|
return abs;
|
|
37456
37512
|
}
|
|
37457
37513
|
async function tryClipboardTextAsImageFile(baseDir) {
|
|
@@ -37471,8 +37527,8 @@ async function tryClipboardTextAsImageFile(baseDir) {
|
|
|
37471
37527
|
} catch {
|
|
37472
37528
|
return null;
|
|
37473
37529
|
}
|
|
37474
|
-
const ext =
|
|
37475
|
-
const out =
|
|
37530
|
+
const ext = path51.extname(abs).toLowerCase();
|
|
37531
|
+
const out = path51.join(
|
|
37476
37532
|
baseDir,
|
|
37477
37533
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
|
|
37478
37534
|
);
|
|
@@ -37487,7 +37543,7 @@ async function tryLinuxShellPipelineSave(baseDir) {
|
|
|
37487
37543
|
if (process.platform !== "linux" && process.platform !== "freebsd") {
|
|
37488
37544
|
return null;
|
|
37489
37545
|
}
|
|
37490
|
-
const outPath =
|
|
37546
|
+
const outPath = path51.join(
|
|
37491
37547
|
baseDir,
|
|
37492
37548
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
37493
37549
|
);
|
|
@@ -37545,7 +37601,7 @@ async function tryNativeClipboardImage() {
|
|
|
37545
37601
|
return null;
|
|
37546
37602
|
}
|
|
37547
37603
|
async function readClipboardImageToTempFile() {
|
|
37548
|
-
const baseDir =
|
|
37604
|
+
const baseDir = path51.join(os33.homedir(), ".cache", "bluma", "clipboard");
|
|
37549
37605
|
fs45.mkdirSync(baseDir, { recursive: true });
|
|
37550
37606
|
const nativeResult = await tryNativeClipboardImage();
|
|
37551
37607
|
if (nativeResult) {
|
|
@@ -37564,7 +37620,7 @@ async function readClipboardImageToTempFile() {
|
|
|
37564
37620
|
}
|
|
37565
37621
|
}
|
|
37566
37622
|
if (process.platform === "win32") {
|
|
37567
|
-
const outFile =
|
|
37623
|
+
const outFile = path51.join(
|
|
37568
37624
|
baseDir,
|
|
37569
37625
|
`clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.png`
|
|
37570
37626
|
);
|
|
@@ -40052,7 +40108,7 @@ var renderCode = () => {
|
|
|
40052
40108
|
};
|
|
40053
40109
|
|
|
40054
40110
|
// src/app/agent/core/thread/thread_store.ts
|
|
40055
|
-
import
|
|
40111
|
+
import path52 from "path";
|
|
40056
40112
|
import { promises as fs47 } from "fs";
|
|
40057
40113
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
40058
40114
|
var INDEX_VERSION = 1;
|
|
@@ -40078,9 +40134,9 @@ var ThreadStore = class {
|
|
|
40078
40134
|
packageVersion;
|
|
40079
40135
|
constructor() {
|
|
40080
40136
|
const appDir = getPreferredAppDir();
|
|
40081
|
-
this.threadsDir =
|
|
40082
|
-
this.archiveDir =
|
|
40083
|
-
this.indexPath =
|
|
40137
|
+
this.threadsDir = path52.join(appDir, "threads");
|
|
40138
|
+
this.archiveDir = path52.join(this.threadsDir, "archive");
|
|
40139
|
+
this.indexPath = path52.join(this.threadsDir, "index.json");
|
|
40084
40140
|
this.packageVersion = process.env.npm_package_version || "0.0.0";
|
|
40085
40141
|
}
|
|
40086
40142
|
// ==================== Inicialização ====================
|
|
@@ -40202,7 +40258,7 @@ var ThreadStore = class {
|
|
|
40202
40258
|
messages: params.initialMessages || []
|
|
40203
40259
|
};
|
|
40204
40260
|
const historyPath = this.buildDatedThreadHistoryPath(threadId);
|
|
40205
|
-
await fs47.mkdir(
|
|
40261
|
+
await fs47.mkdir(path52.dirname(historyPath), { recursive: true });
|
|
40206
40262
|
await this.saveHistoryAtPath(historyPath, history);
|
|
40207
40263
|
const index = await this.loadIndex();
|
|
40208
40264
|
index.threads.unshift({
|
|
@@ -40257,7 +40313,7 @@ var ThreadStore = class {
|
|
|
40257
40313
|
compressedSliceCount: source.history.compressedSliceCount
|
|
40258
40314
|
};
|
|
40259
40315
|
const historyPath = this.buildDatedThreadHistoryPath(newThreadId);
|
|
40260
|
-
await fs47.mkdir(
|
|
40316
|
+
await fs47.mkdir(path52.dirname(historyPath), { recursive: true });
|
|
40261
40317
|
await this.saveHistoryAtPath(historyPath, history);
|
|
40262
40318
|
const index = await this.loadIndex();
|
|
40263
40319
|
index.threads.unshift({
|
|
@@ -40330,7 +40386,7 @@ var ThreadStore = class {
|
|
|
40330
40386
|
const entry = index.threads[entryIndex];
|
|
40331
40387
|
if (entry.status === "archived") return true;
|
|
40332
40388
|
const oldPath = entry.historyPath || this.getLegacyHistoryPath(threadId);
|
|
40333
|
-
const newPath =
|
|
40389
|
+
const newPath = path52.join(this.archiveDir, `${threadId}.jsonl`);
|
|
40334
40390
|
try {
|
|
40335
40391
|
await fs47.rename(oldPath, newPath);
|
|
40336
40392
|
} catch (e) {
|
|
@@ -40353,9 +40409,9 @@ var ThreadStore = class {
|
|
|
40353
40409
|
if (entryIndex === -1) return false;
|
|
40354
40410
|
const entry = index.threads[entryIndex];
|
|
40355
40411
|
if (entry.status === "active") return true;
|
|
40356
|
-
const oldPath =
|
|
40412
|
+
const oldPath = path52.join(this.archiveDir, `${threadId}.jsonl`);
|
|
40357
40413
|
const newPath = this.buildDatedThreadHistoryPath(threadId);
|
|
40358
|
-
await fs47.mkdir(
|
|
40414
|
+
await fs47.mkdir(path52.dirname(newPath), { recursive: true });
|
|
40359
40415
|
try {
|
|
40360
40416
|
await fs47.rename(oldPath, newPath);
|
|
40361
40417
|
} catch (e) {
|
|
@@ -40388,14 +40444,14 @@ var ThreadStore = class {
|
|
|
40388
40444
|
}
|
|
40389
40445
|
// ==================== Histórico ====================
|
|
40390
40446
|
getLegacyHistoryPath(threadId) {
|
|
40391
|
-
return
|
|
40447
|
+
return path52.join(this.threadsDir, `${threadId}.jsonl`);
|
|
40392
40448
|
}
|
|
40393
40449
|
/** ~/.bluma/threads/YYYY/MM/DD/<threadId>.jsonl (data local de criação). */
|
|
40394
40450
|
buildDatedThreadHistoryPath(threadId, at = /* @__PURE__ */ new Date()) {
|
|
40395
40451
|
const y = String(at.getFullYear());
|
|
40396
40452
|
const mo = String(at.getMonth() + 1).padStart(2, "0");
|
|
40397
40453
|
const d = String(at.getDate()).padStart(2, "0");
|
|
40398
|
-
return
|
|
40454
|
+
return path52.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
|
|
40399
40455
|
}
|
|
40400
40456
|
async resolveHistoryPath(threadId) {
|
|
40401
40457
|
const index = await this.loadIndex();
|
|
@@ -40426,7 +40482,7 @@ var ThreadStore = class {
|
|
|
40426
40482
|
for (const msg of history.messages) {
|
|
40427
40483
|
lines.push(JSON.stringify({ type: "message", ...msg }));
|
|
40428
40484
|
}
|
|
40429
|
-
await fs47.mkdir(
|
|
40485
|
+
await fs47.mkdir(path52.dirname(historyPath), { recursive: true }).catch(() => {
|
|
40430
40486
|
});
|
|
40431
40487
|
await fs47.writeFile(historyPath, lines.join("\n") + "\n", "utf-8");
|
|
40432
40488
|
}
|
|
@@ -43358,13 +43414,13 @@ import latestVersion from "latest-version";
|
|
|
43358
43414
|
import semverGt from "semver/functions/gt.js";
|
|
43359
43415
|
import semverValid from "semver/functions/valid.js";
|
|
43360
43416
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
43361
|
-
import
|
|
43417
|
+
import path53 from "path";
|
|
43362
43418
|
import fs48 from "fs";
|
|
43363
43419
|
var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
|
|
43364
43420
|
function findBlumaPackageJson(startDir) {
|
|
43365
43421
|
let dir = startDir;
|
|
43366
43422
|
for (let i = 0; i < 12; i++) {
|
|
43367
|
-
const candidate =
|
|
43423
|
+
const candidate = path53.join(dir, "package.json");
|
|
43368
43424
|
if (fs48.existsSync(candidate)) {
|
|
43369
43425
|
try {
|
|
43370
43426
|
const raw = fs48.readFileSync(candidate, "utf8");
|
|
@@ -43375,7 +43431,7 @@ function findBlumaPackageJson(startDir) {
|
|
|
43375
43431
|
} catch {
|
|
43376
43432
|
}
|
|
43377
43433
|
}
|
|
43378
|
-
const parent =
|
|
43434
|
+
const parent = path53.dirname(dir);
|
|
43379
43435
|
if (parent === dir) break;
|
|
43380
43436
|
dir = parent;
|
|
43381
43437
|
}
|
|
@@ -43384,13 +43440,13 @@ function findBlumaPackageJson(startDir) {
|
|
|
43384
43440
|
function resolveInstalledBlumaPackage() {
|
|
43385
43441
|
const tried = /* @__PURE__ */ new Set();
|
|
43386
43442
|
const tryFrom = (dir) => {
|
|
43387
|
-
const abs =
|
|
43443
|
+
const abs = path53.resolve(dir);
|
|
43388
43444
|
if (tried.has(abs)) return null;
|
|
43389
43445
|
tried.add(abs);
|
|
43390
43446
|
return findBlumaPackageJson(abs);
|
|
43391
43447
|
};
|
|
43392
43448
|
try {
|
|
43393
|
-
const fromBundle = tryFrom(
|
|
43449
|
+
const fromBundle = tryFrom(path53.dirname(fileURLToPath6(import.meta.url)));
|
|
43394
43450
|
if (fromBundle) return fromBundle;
|
|
43395
43451
|
} catch {
|
|
43396
43452
|
}
|
|
@@ -43398,12 +43454,12 @@ function resolveInstalledBlumaPackage() {
|
|
|
43398
43454
|
if (argv1 && !argv1.startsWith("-")) {
|
|
43399
43455
|
try {
|
|
43400
43456
|
let resolved = argv1;
|
|
43401
|
-
if (
|
|
43457
|
+
if (path53.isAbsolute(argv1) && fs48.existsSync(argv1)) {
|
|
43402
43458
|
resolved = fs48.realpathSync(argv1);
|
|
43403
43459
|
} else {
|
|
43404
|
-
resolved =
|
|
43460
|
+
resolved = path53.resolve(process.cwd(), argv1);
|
|
43405
43461
|
}
|
|
43406
|
-
const fromArgv = tryFrom(
|
|
43462
|
+
const fromArgv = tryFrom(path53.dirname(resolved));
|
|
43407
43463
|
if (fromArgv) return fromArgv;
|
|
43408
43464
|
} catch {
|
|
43409
43465
|
}
|
|
@@ -44223,9 +44279,9 @@ function usePlanMode() {
|
|
|
44223
44279
|
// src/app/hooks/useAgentMode.ts
|
|
44224
44280
|
import { useState as useState22, useEffect as useEffect21, useCallback as useCallback9 } from "react";
|
|
44225
44281
|
import * as fs49 from "fs";
|
|
44226
|
-
import * as
|
|
44282
|
+
import * as path54 from "path";
|
|
44227
44283
|
import { homedir as homedir3 } from "os";
|
|
44228
|
-
var SETTINGS_PATH =
|
|
44284
|
+
var SETTINGS_PATH = path54.join(homedir3(), ".bluma", "settings.json");
|
|
44229
44285
|
function readAgentModeFromFile() {
|
|
44230
44286
|
try {
|
|
44231
44287
|
if (!fs49.existsSync(SETTINGS_PATH)) {
|
|
@@ -44251,7 +44307,7 @@ function useAgentMode() {
|
|
|
44251
44307
|
const updateAgentMode = useCallback9((mode) => {
|
|
44252
44308
|
try {
|
|
44253
44309
|
if (!fs49.existsSync(SETTINGS_PATH)) {
|
|
44254
|
-
fs49.mkdirSync(
|
|
44310
|
+
fs49.mkdirSync(path54.dirname(SETTINGS_PATH), { recursive: true });
|
|
44255
44311
|
}
|
|
44256
44312
|
let settings = {};
|
|
44257
44313
|
if (fs49.existsSync(SETTINGS_PATH)) {
|
|
@@ -45522,10 +45578,10 @@ import React39 from "react";
|
|
|
45522
45578
|
import { memo as memo26, useCallback as useCallback11, useEffect as useEffect23, useMemo as useMemo8, useState as useState25 } from "react";
|
|
45523
45579
|
|
|
45524
45580
|
// src/app/agent/session_manager/session_resume_browser.ts
|
|
45525
|
-
import
|
|
45581
|
+
import path55 from "path";
|
|
45526
45582
|
import { promises as fs50 } from "fs";
|
|
45527
45583
|
function getSessionsRoot() {
|
|
45528
|
-
return
|
|
45584
|
+
return path55.join(getPreferredAppDir(), "sessions");
|
|
45529
45585
|
}
|
|
45530
45586
|
function normalizeSessionsCwd(cwd2) {
|
|
45531
45587
|
return cwd2.replace(/\\/g, "/").split("/").filter((p) => p && p !== "." && p !== "..").join("/");
|
|
@@ -45576,7 +45632,7 @@ function compareDirNames(a, b) {
|
|
|
45576
45632
|
async function listSessionBrowserEntries(cwdRel) {
|
|
45577
45633
|
const cwd2 = normalizeSessionsCwd(cwdRel);
|
|
45578
45634
|
const root = getSessionsRoot();
|
|
45579
|
-
const absDir = cwd2 ?
|
|
45635
|
+
const absDir = cwd2 ? path55.join(root, ...cwd2.split("/")) : root;
|
|
45580
45636
|
const out = [];
|
|
45581
45637
|
if (cwd2) {
|
|
45582
45638
|
out.push({ kind: "up", label: ".." });
|
|
@@ -45593,7 +45649,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
45593
45649
|
for (const e of dirents) {
|
|
45594
45650
|
const name = String(e.name);
|
|
45595
45651
|
if (name.startsWith(".")) continue;
|
|
45596
|
-
const full =
|
|
45652
|
+
const full = path55.join(absDir, name);
|
|
45597
45653
|
if (e.isDirectory()) {
|
|
45598
45654
|
dirNames.push(name);
|
|
45599
45655
|
} else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
|
|
@@ -45603,7 +45659,7 @@ async function listSessionBrowserEntries(cwdRel) {
|
|
|
45603
45659
|
dirNames.sort(compareDirNames);
|
|
45604
45660
|
const sessions = [];
|
|
45605
45661
|
for (const { name, full } of sessionFiles) {
|
|
45606
|
-
const sessionId =
|
|
45662
|
+
const sessionId = path55.basename(name, ".json");
|
|
45607
45663
|
sessions.push(await sessionEntryFromFile(full, sessionId));
|
|
45608
45664
|
}
|
|
45609
45665
|
sessions.sort((a, b) => {
|
|
@@ -46211,8 +46267,8 @@ async function runAgentMode() {
|
|
|
46211
46267
|
}
|
|
46212
46268
|
function readCliPackageVersion() {
|
|
46213
46269
|
try {
|
|
46214
|
-
const base =
|
|
46215
|
-
const pkgPath =
|
|
46270
|
+
const base = path56.dirname(fileURLToPath7(import.meta.url));
|
|
46271
|
+
const pkgPath = path56.join(base, "..", "package.json");
|
|
46216
46272
|
const j = JSON.parse(fs51.readFileSync(pkgPath, "utf8"));
|
|
46217
46273
|
return String(j.version || "0.0.0");
|
|
46218
46274
|
} catch {
|