@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.
Files changed (2) hide show
  1. package/dist/main.js +393 -337
  2. 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(path56, data, options) {
2205
- const _ = slowLogging`fs.appendFileSync(${path56}, ${data.length} chars)`;
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(path56, "ax", options.mode);
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(path56, data);
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(path56) {
2226
- const _ = slowLogging`fs.unlinkSync(${path56})`;
2227
- fs.unlinkSync(path56);
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, path56) {
2234
- const _ = slowLogging`fs.linkSync(${target} → ${path56})`;
2235
- fs.linkSync(target, path56);
2233
+ linkSync(target, path57) {
2234
+ const _ = slowLogging`fs.linkSync(${target} → ${path57})`;
2235
+ fs.linkSync(target, path57);
2236
2236
  },
2237
- symlinkSync(target, path56, type) {
2238
- const _ = slowLogging`fs.symlinkSync(${target} → ${path56})`;
2239
- fs.symlinkSync(target, path56, type);
2237
+ symlinkSync(target, path57, type) {
2238
+ const _ = slowLogging`fs.symlinkSync(${target} → ${path57})`;
2239
+ fs.symlinkSync(target, path57, type);
2240
2240
  },
2241
- readlinkSync(path56) {
2242
- const _ = slowLogging`fs.readlinkSync(${path56})`;
2243
- return fs.readlinkSync(path56);
2241
+ readlinkSync(path57) {
2242
+ const _ = slowLogging`fs.readlinkSync(${path57})`;
2243
+ return fs.readlinkSync(path57);
2244
2244
  },
2245
- realpathSync(path56) {
2246
- const _ = slowLogging`fs.realpathSync(${path56})`;
2247
- return fs.realpathSync(path56).normalize("NFC");
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(path56, options) {
2281
- const _ = slowLogging`fs.rmSync(${path56})`;
2282
- fs.rmSync(path56, options);
2280
+ rmSync(path57, options) {
2281
+ const _ = slowLogging`fs.rmSync(${path57})`;
2282
+ fs.rmSync(path57, options);
2283
2283
  },
2284
- createWriteStream(path56) {
2285
- return fs.createWriteStream(path56);
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, path56, content) {
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(path56, content);
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 path56 = getDebugLogPath();
2408
- const dir = dirname(path56);
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(path56, content);
2418
+ getFsImplementation().appendFileSync(path57, content);
2419
2419
  void updateLatestDebugLogSymlink();
2420
2420
  return;
2421
2421
  }
2422
- pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir, path56, content)).catch(noop);
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 = (path56) => {
8610
- return path56?.replace(`file://${process.cwd()}/`, "");
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 path55 from "path";
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 path46 from "path";
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 path26 from "path";
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
- function shQuote(value) {
19071
- return `'${value.replace(/'/g, `'"'"'`)}'`;
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 zipExcludeArg(pattern) {
19089
- if (pattern.includes("*") || pattern.startsWith(".")) {
19090
- return pattern;
19091
- }
19092
- return `${pattern}/*`;
19093
- }
19094
- async function createProjectZip(projectDir, zipPath) {
19095
- const excludeFlags = EXCLUDE_PATTERNS.flatMap((pattern) => ["-x", zipExcludeArg(pattern)]);
19096
- const zipCommand = ["zip", "-r", shQuote(zipPath), ".", ...excludeFlags.map(shQuote)].join(" ");
19097
- const result = await shellCommand({
19098
- command: zipCommand,
19099
- cwd: projectDir,
19100
- timeout: 120
19101
- // 2 minutos para zippar
19102
- });
19103
- const resultJson = JSON.parse(result);
19104
- if (resultJson.status !== "success") {
19105
- throw new Error(`Failed to create ZIP: ${resultJson.stderr}`);
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 curlArgs = [
19112
- "-sS",
19113
- "-X",
19114
- "POST",
19115
- deployUrl,
19116
- "-F",
19117
- `file=@${zipPath}`
19118
- ];
19119
- if (name) {
19120
- curlArgs.push("-F", `name=${name}`);
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
- curlArgs.push("-H", `Authorization: Bearer ${apiKey}`);
19127
- curlArgs.push("-H", `X-API-Key: ${apiKey}`);
19128
- }
19129
- curlArgs.push("-H", "Accept: application/json");
19130
- const curlCommand = `curl ${curlArgs.map(shQuote).join(" ")}`;
19131
- const result = await shellCommand({
19132
- command: curlCommand,
19133
- timeout: 60
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 resultJson = JSON.parse(result);
19137
- if (resultJson.status !== "success") {
19138
- throw new Error(`Upload failed: ${resultJson.stderr}`);
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(resultJson.stdout);
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 = path25.join(projectDir, "factorai.sh.json");
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 = path25.join(resolvedProjectDir, "package.json");
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 || path25.basename(resolvedProjectDir);
19275
- const tempDir = path25.join(resolvedProjectDir, ".tmp");
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 = path25.join(tempDir, `${appName}-${Date.now()}.zip`);
19333
+ const zipPath = path26.join(tempDir, `${appName}-${Date.now()}.zip`);
19278
19334
  console.log(`[deploy-app] Creating ZIP: ${zipPath}`);
19279
- await createProjectZip(resolvedProjectDir, zipPath);
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 = path25.join(resolvedProjectDir, "factorai.sh.json");
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 = path26.dirname(currentFilePath);
20393
- const configPath = path26.resolve(currentDirPath, "config", "native_tools.json");
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 path27 from "path";
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 = path27.dirname(__filename);
20471
- const defaultConfigPath = path27.resolve(__dirname2, "config", "bluma-mcp.json");
20472
- const userConfigPath = path27.join(os18.homedir(), ".bluma", "bluma-mcp.json");
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 path43 from "path";
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 path31 from "path";
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 path30 from "path";
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 path28 from "path";
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 path28.join(os19.homedir(), p.slice(1));
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 path28.resolve(expandHome(fromEnv));
20799
+ return path29.resolve(expandHome(fromEnv));
20744
20800
  }
20745
- const fixed = path28.join(os19.homedir(), ".bluma");
20746
- return path28.resolve(expandHome(fixed));
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 path29 from "path";
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 path29.join(appDir, BLUMA_SESSION_DB_FILE);
20821
+ return path30.join(appDir, BLUMA_SESSION_DB_FILE);
20766
20822
  }
20767
20823
  function normalizeRelativePath(relativePath) {
20768
- return relativePath.split(path29.sep).join("/");
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 = path29.join(dir, name);
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 = path29.join(appDir, AGENT_SESSION_PATHS_JSONL);
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(path29.relative(appDir, absPath));
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 = path29.join(appDir, entry.relativePath.replace(/\//g, path29.sep));
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 = path29.join(appDir, "sessions");
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 = path29.basename(absPath, ".json");
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(path29.dirname(dbPath), { recursive: true });
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, path29.sep) ?? null;
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, path29.sep),
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(path30.sep).join("/");
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 = path30.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
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, path30.sep);
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 = path30.join(dir, name);
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 = path30.join(getPreferredAppDir(), "sessions");
21105
+ const sessionsRoot = path31.join(getPreferredAppDir(), "sessions");
21050
21106
  const state2 = { best: null };
21051
21107
  await walkSessionJsonFiles2(sessionsRoot, async (abs) => {
21052
- if (path30.basename(abs, ".json") !== sessionId) return;
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 = path30.join(getPreferredAppDir(), AGENT_SESSION_PATHS_JSONL2);
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 = path30.relative(getPreferredAppDir(), absPath);
21161
+ rel = path31.relative(getPreferredAppDir(), absPath);
21106
21162
  } catch {
21107
21163
  rel = absPath;
21108
21164
  }
21109
- const dateFolder = dateFolderFromRelativePath(rel.split(path30.sep).join("/"));
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 = path30.join(appDir, row.relativePath);
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 = path30.join(appDir, "sessions");
21217
+ const sessionsRoot = path31.join(appDir, "sessions");
21162
21218
  await walkSessionJsonFiles2(sessionsRoot, async (absPath) => {
21163
- const id = path30.basename(absPath, ".json");
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 = path30.join(appDir, entry.relativePath.replace(/\//g, path30.sep));
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 = path31.dirname(dest);
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 = path31.dirname(dest);
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 = path31.join(appDir, "sessions");
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 = path31.join(appDir, "sessions", `${sessionId}.json`);
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 = path31.join(appDir, rel);
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 = path31.join(sessionsRoot, y, mo, d);
21378
+ const datedDir = path32.join(sessionsRoot, y, mo, d);
21323
21379
  await fs29.mkdir(datedDir, { recursive: true });
21324
- const sessionFile = path31.join(datedDir, `${sessionId}.json`);
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 = path31.relative(getPreferredAppDir(), sessionFile);
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 = path31.dirname(sessionFile);
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 = path31.basename(sessionFile, ".json");
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 ?? path31.basename(sessionFile, ".json");
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 = path31.relative(getPreferredAppDir(), sessionFile);
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 path38 from "path";
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 path32 from "path";
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 = path32.join(projectRoot, ".bluma", "skills");
21458
- this.globalSkillsDir = path32.join(os20.homedir(), ".bluma", "skills");
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 path32.join(process.cwd(), "dist", "config", "skills");
21523
+ return path33.join(process.cwd(), "dist", "config", "skills");
21468
21524
  }
21469
21525
  const candidates = [];
21470
21526
  const push = (p) => {
21471
- const abs = path32.resolve(p);
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 = path32.dirname(fileURLToPath3(import.meta.url));
21479
- push(path32.join(bundleDir, "config", "skills"));
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 (path32.isAbsolute(argv1) && fs30.existsSync(argv1)) {
21542
+ if (path33.isAbsolute(argv1) && fs30.existsSync(argv1)) {
21487
21543
  resolved = fs30.realpathSync(argv1);
21488
- } else if (!path32.isAbsolute(argv1)) {
21489
- resolved = path32.resolve(process.cwd(), argv1);
21544
+ } else if (!path33.isAbsolute(argv1)) {
21545
+ resolved = path33.resolve(process.cwd(), argv1);
21490
21546
  }
21491
- const scriptDir = path32.dirname(resolved);
21492
- argvBundled = path32.join(scriptDir, "config", "skills");
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 path32.join(path32.dirname(fileURLToPath3(import.meta.url)), "config", "skills");
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 path32.join(os20.homedir(), ".bluma", "__bundled_skills_unresolved__");
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: path32.join(dir, skill.name, "SKILL.md"),
21538
- bundledPath: path32.join(this.bundledSkillsDir, skill.name, "SKILL.md")
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 = path32.join(dir, d);
21550
- return fs30.statSync(fullPath).isDirectory() && fs30.existsSync(path32.join(fullPath, "SKILL.md"));
21551
- }).map((d) => this.loadMetadataFromPath(path32.join(dir, d, "SKILL.md"), d, source)).filter((m) => m !== null);
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 = path32.join(this.bundledSkillsDir, name, "SKILL.md");
21582
- const projectPath = path32.join(this.projectSkillsDir, name, "SKILL.md");
21583
- const globalPath = path32.join(this.globalSkillsDir, name, "SKILL.md");
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 = path32.dirname(skillPath);
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(path32.join(skillDir, "references")),
21637
- scripts: this.scanAssets(path32.join(skillDir, "scripts"))
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 = path32.join(dir, f);
21703
+ const fp = path33.join(dir, f);
21648
21704
  return fs30.statSync(fp).isFile();
21649
21705
  }).map((f) => ({
21650
21706
  name: f,
21651
- path: path32.resolve(dir, f)
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 = path32.join(this.bundledSkillsDir, name, "SKILL.md");
21709
- const projectPath = path32.join(this.projectSkillsDir, name, "SKILL.md");
21710
- const globalPath = path32.join(this.globalSkillsDir, name, "SKILL.md");
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 path34 from "path";
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 path33 from "path";
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 path33.join(os21.homedir(), cleanPath.slice(1));
21935
+ return path34.join(os21.homedir(), cleanPath.slice(1));
21880
21936
  }
21881
- if (path33.isAbsolute(cleanPath)) {
21937
+ if (path34.isAbsolute(cleanPath)) {
21882
21938
  return cleanPath;
21883
21939
  }
21884
- return path33.resolve(baseDir, cleanPath);
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 = path33.normalize(includePath);
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 = path33.extname(includePath).toLowerCase();
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, path33.dirname(includePath), processedFiles);
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 || path33.dirname(filePath);
21954
- const processedFiles = /* @__PURE__ */ new Set([path33.normalize(filePath)]);
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 !== path33.dirname(current)) {
21977
- const gitPath = path33.join(current, ".git");
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 = path33.dirname(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 = path33.join(rulesDir, entry.name);
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 = path33.normalize(entryPath);
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 = path33.join(homeDir, ".bluma");
22056
- const userBlumaMd = path33.join(userBlumaDir, "BLUMA.md");
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 = path33.join(userBlumaDir, "rules");
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 = path33.resolve(gitRoot);
22074
- while (currentDir !== path33.dirname(currentDir) && path33.resolve(currentDir).startsWith(normalizedGitRoot) && depth < MAX_TRAVERSAL_DEPTH) {
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 = path33.dirname(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 = path33.join(dir, "BLUMA.md");
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 = path33.join(dir, ".bluma", "BLUMA.md");
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 = path33.join(dir, ".bluma", "rules");
22156
+ const rulesDir = path34.join(dir, ".bluma", "rules");
22101
22157
  files.push(...processRulesDirectory(rulesDir, "Project", processedPaths, false));
22102
22158
  }
22103
- const localBlumaMd = path33.join(cwd2, "BLUMA.local.md");
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(path34.join(cwd2, name), LIMITS.readme);
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
- path34.join(cwd2, "BluMa.md"),
22213
- path34.join(cwd2, "BLUMA.md"),
22214
- path34.join(cwd2, ".bluma", "BluMa.md")
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 = path34.relative(cwd2, p) || p;
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 = path34.join(cwd2, "package.json");
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(path34.join(cwd2, "pyproject.toml"), LIMITS.pyproject);
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(path34.join(cwd2, "CONTRIBUTING.md"), LIMITS.contributing);
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(path34.join(cwd2, "CHANGELOG.md"), LIMITS.changelog);
22401
+ const chlog = safeReadFile(path35.join(cwd2, "CHANGELOG.md"), LIMITS.changelog);
22346
22402
  if (!chlog) {
22347
- const alt = safeReadFile(path34.join(cwd2, "CHANGES.md"), LIMITS.changelog);
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(path34.join(cwd2, "tsconfig.json"), LIMITS.tsconfig);
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(path34.join(cwd2, name), LIMITS.dockerfile);
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(path34.join(cwd2, name), LIMITS.dockerfile);
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 = path34.join(cwd2, ciPath);
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 (${path34.basename(ciPath)})
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 = path34.join(cwd2, depFile);
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 = path34.join(cwd2, envFile);
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 path35 from "path";
22538
+ import path36 from "path";
22483
22539
  function getProjectPluginsDir() {
22484
22540
  const policy = getSandboxPolicy();
22485
- return path35.join(policy.workspaceRoot, ".bluma", "plugins");
22541
+ return path36.join(policy.workspaceRoot, ".bluma", "plugins");
22486
22542
  }
22487
22543
  function getGlobalPluginsDir() {
22488
- return path35.join(process.env.HOME || os22.homedir(), ".bluma", "plugins");
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
- path35.join(pluginDir, ".codex-plugin", "plugin.json"),
22515
- path35.join(pluginDir, "plugin.json")
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 = path35.join(baseDir, entry.name);
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 path36 from "path";
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 path36.join(policy.workspaceRoot, ".bluma", "hooks.json");
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(path36.dirname(statePath), { recursive: true });
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 path37 from "path";
23341
+ import path38 from "path";
23286
23342
  import os23 from "os";
23287
- var AUTO_MEMORY_FILE = path37.join(os23.homedir(), ".bluma", "auto_memory.md");
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(path38.join(dir, "pnpm-lock.yaml"))) return "pnpm";
23450
- if (fs36.existsSync(path38.join(dir, "yarn.lock"))) return "yarn";
23451
- if (fs36.existsSync(path38.join(dir, "bun.lockb"))) return "bun";
23452
- if (fs36.existsSync(path38.join(dir, "package-lock.json"))) return "npm";
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(path38.join(dir, "package.json"), "utf-8"));
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 = path38.join(dir, "package.json");
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(path38.join(dir, "pytest.ini")) || fs36.existsSync(path38.join(dir, "conftest.py"))) return "pytest";
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 = path38.join(dir, "package.json");
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 = path38.join(dir, ".git");
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 path39 from "path";
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 path39.join(os26.homedir(), t.slice(1).replace(/^\//, ""));
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 = path39.normalize(path39.resolve(absResolved));
24961
- const cwdR = path39.normalize(path39.resolve(cwd2));
24962
- const homeR = path39.normalize(path39.resolve(os26.homedir()));
24963
- const tmpR = path39.normalize(path39.resolve(os26.tmpdir()));
24964
- const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path39.sep);
24965
- const underHome = resolved === homeR || resolved.startsWith(homeR + path39.sep);
24966
- const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path39.sep);
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 = path39.extname(abs).toLowerCase();
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 = path39.isAbsolute(expanded) ? path39.normalize(expanded) : path39.normalize(path39.resolve(cwd2, expanded));
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(path39.extname(s))) return null;
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 path40 from "path";
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 = path40.resolve(filePath);
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 = path40.relative(policy.workspaceRoot, resolvedPath);
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 = path40.dirname(relativePath);
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 path41 from "path";
25442
+ import * as path42 from "path";
25387
25443
  import os27 from "os";
25388
25444
  function memoryPath2() {
25389
- return path41.join(process.env.HOME || os27.homedir(), ".bluma", "coding_memory.json");
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 path42 from "path";
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 = path42.join(appDir, "sessions", "archive", sessionId);
26013
+ const dir = path43.join(appDir, "sessions", "archive", sessionId);
25958
26014
  await fs39.mkdir(dir, { recursive: true });
25959
- const archiveFile = path42.join(dir, `${Date.now()}.jsonl`);
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: path43.basename(this.sessionFile, ".json"),
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 = path43.basename(toolArgs.file_path);
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 path44 from "path";
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 || path44.join(os30.homedir(), ".bluma", "session_memory.json");
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(path56, handler) {
28353
- this.routeHandlers.set(path56, handler);
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 [path56, handler] of this.routeHandlers) {
28359
- if (inputText === path56 || inputText.startsWith(`${path56} `)) {
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 path45 from "path";
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 = path45.resolve(p.root, entry);
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 = path46.join(os31.homedir(), ".bluma", ".env");
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 path48 from "node:path";
30307
+ import path49 from "node:path";
30252
30308
 
30253
30309
  // src/app/ui/utils/pathDisplay.ts
30254
- import path47 from "node:path";
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 = path47.isAbsolute(s) ? path47.normalize(s) : path47.resolve(cwd2, s);
30263
- const resolvedCwd = path47.resolve(cwd2);
30264
- const rel = path47.relative(resolvedCwd, abs);
30265
- if (rel === "" || !rel.startsWith("..") && !path47.isAbsolute(rel)) {
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 = path47.normalize(os32.homedir());
30269
- if (abs === home || abs.startsWith(home + path47.sep)) {
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 path47.basename(abs);
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 = path48.isAbsolute(raw) ? path48.normalize(raw) : path48.resolve(cwd2, raw);
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 path56 = filePath.trim() || "unknown file";
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: path56,
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 path56 = args?.file_path ?? ".";
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: path56, color: BLUMA_TERMINAL.dim })
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 path56 = args?.path || ".";
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: path56, color: BLUMA_TERMINAL.dim })
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 path49 from "path";
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 = path49.resolve(baseDir, relDir || ".");
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(path49.sep).join("/").replace(/[]+/g, "");
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 = path49.join(node.dir, entry.name);
36873
- const entryRel = node.rel ? path49.posix.join(node.rel, entry.name) : entry.name;
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 = path49.join(listDir, entry.name);
36892
- const label = relDir ? path49.posix.join(relDir, entry.name) : entry.name;
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 path50 from "path";
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
- path50.join(h, ".local", "bin"),
37225
- path50.join(h, "bin"),
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 = path50.join(dir, cmd);
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 = path50.join(dir, cmd);
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 = path50.join(
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 = path50.extname(src).toLowerCase();
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 = path50.join(
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 ? path50.join(
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(path50.extname(s))) return null;
37454
- const abs = path50.isAbsolute(s) ? path50.normalize(s) : path50.resolve(process.cwd(), s);
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 = path50.extname(abs).toLowerCase();
37475
- const out = path50.join(
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 = path50.join(
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 = path50.join(os33.homedir(), ".cache", "bluma", "clipboard");
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 = path50.join(
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 path51 from "path";
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 = path51.join(appDir, "threads");
40082
- this.archiveDir = path51.join(this.threadsDir, "archive");
40083
- this.indexPath = path51.join(this.threadsDir, "index.json");
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(path51.dirname(historyPath), { recursive: true });
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(path51.dirname(historyPath), { recursive: true });
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 = path51.join(this.archiveDir, `${threadId}.jsonl`);
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 = path51.join(this.archiveDir, `${threadId}.jsonl`);
40412
+ const oldPath = path52.join(this.archiveDir, `${threadId}.jsonl`);
40357
40413
  const newPath = this.buildDatedThreadHistoryPath(threadId);
40358
- await fs47.mkdir(path51.dirname(newPath), { recursive: true });
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 path51.join(this.threadsDir, `${threadId}.jsonl`);
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 path51.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
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(path51.dirname(historyPath), { recursive: true }).catch(() => {
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 path52 from "path";
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 = path52.join(dir, "package.json");
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 = path52.dirname(dir);
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 = path52.resolve(dir);
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(path52.dirname(fileURLToPath6(import.meta.url)));
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 (path52.isAbsolute(argv1) && fs48.existsSync(argv1)) {
43457
+ if (path53.isAbsolute(argv1) && fs48.existsSync(argv1)) {
43402
43458
  resolved = fs48.realpathSync(argv1);
43403
43459
  } else {
43404
- resolved = path52.resolve(process.cwd(), argv1);
43460
+ resolved = path53.resolve(process.cwd(), argv1);
43405
43461
  }
43406
- const fromArgv = tryFrom(path52.dirname(resolved));
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 path53 from "path";
44282
+ import * as path54 from "path";
44227
44283
  import { homedir as homedir3 } from "os";
44228
- var SETTINGS_PATH = path53.join(homedir3(), ".bluma", "settings.json");
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(path53.dirname(SETTINGS_PATH), { recursive: true });
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 path54 from "path";
45581
+ import path55 from "path";
45526
45582
  import { promises as fs50 } from "fs";
45527
45583
  function getSessionsRoot() {
45528
- return path54.join(getPreferredAppDir(), "sessions");
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 ? path54.join(root, ...cwd2.split("/")) : root;
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 = path54.join(absDir, name);
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 = path54.basename(name, ".json");
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 = path55.dirname(fileURLToPath7(import.meta.url));
46215
- const pkgPath = path55.join(base, "..", "package.json");
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 {