@nomad-e/bluma-cli 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +416 -264
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -3204,8 +3204,8 @@ __export(exportConversation_exports, {
3204
3204
  formatConversationMarkdown: () => formatConversationMarkdown,
3205
3205
  resolveExportOutputPath: () => resolveExportOutputPath
3206
3206
  });
3207
- import { promises as fs48 } from "fs";
3208
- import path54 from "path";
3207
+ import { promises as fs49 } from "fs";
3208
+ import path55 from "path";
3209
3209
  function extractTextParts2(content) {
3210
3210
  if (typeof content === "string") {
3211
3211
  const trimmed = content.trim();
@@ -3363,12 +3363,12 @@ function resolveExportOutputPath(sessionId, options) {
3363
3363
  const { outputPath, defaultExportDir } = options ?? {};
3364
3364
  if (outputPath?.trim()) {
3365
3365
  const raw = outputPath.trim();
3366
- return path54.isAbsolute(raw) ? raw : path54.resolve(process.cwd(), raw);
3366
+ return path55.isAbsolute(raw) ? raw : path55.resolve(process.cwd(), raw);
3367
3367
  }
3368
3368
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
3369
3369
  const safeId = sessionId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 48) || "session";
3370
3370
  const baseDir = defaultExportDir ?? getSandboxPolicy().workspaceRoot;
3371
- return path54.join(baseDir, `bluma-export-${safeId}-${stamp}.md`);
3371
+ return path55.join(baseDir, `bluma-export-${safeId}-${stamp}.md`);
3372
3372
  }
3373
3373
  async function resolveHistory(sessionId, fallbackHistory) {
3374
3374
  const loaded2 = await loadSession(sessionId);
@@ -3390,8 +3390,8 @@ async function exportConversationToFile(options) {
3390
3390
  }
3391
3391
  const markdown = formatConversationMarkdown(sessionId, history);
3392
3392
  const filePath = resolveExportOutputPath(sessionId, { outputPath, defaultExportDir });
3393
- await fs48.mkdir(path54.dirname(filePath), { recursive: true });
3394
- await fs48.writeFile(filePath, markdown, "utf-8");
3393
+ await fs49.mkdir(path55.dirname(filePath), { recursive: true });
3394
+ await fs49.writeFile(filePath, markdown, "utf-8");
3395
3395
  return {
3396
3396
  success: true,
3397
3397
  filePath,
@@ -3916,11 +3916,11 @@ var NodeFsOperations = {
3916
3916
  if (fd) fs.closeSync(fd);
3917
3917
  }
3918
3918
  },
3919
- appendFileSync(path59, data, options) {
3920
- const _ = slowLogging`fs.appendFileSync(${path59}, ${data.length} chars)`;
3919
+ appendFileSync(path60, data, options) {
3920
+ const _ = slowLogging`fs.appendFileSync(${path60}, ${data.length} chars)`;
3921
3921
  if (options?.mode !== void 0) {
3922
3922
  try {
3923
- const fd = fs.openSync(path59, "ax", options.mode);
3923
+ const fd = fs.openSync(path60, "ax", options.mode);
3924
3924
  try {
3925
3925
  fs.appendFileSync(fd, data);
3926
3926
  } finally {
@@ -3931,35 +3931,35 @@ var NodeFsOperations = {
3931
3931
  if (getErrnoCode(e) !== "EEXIST") throw e;
3932
3932
  }
3933
3933
  }
3934
- fs.appendFileSync(path59, data);
3934
+ fs.appendFileSync(path60, data);
3935
3935
  },
3936
3936
  copyFileSync(src, dest) {
3937
3937
  const _ = slowLogging`fs.copyFileSync(${src} → ${dest})`;
3938
3938
  fs.copyFileSync(src, dest);
3939
3939
  },
3940
- unlinkSync(path59) {
3941
- const _ = slowLogging`fs.unlinkSync(${path59})`;
3942
- fs.unlinkSync(path59);
3940
+ unlinkSync(path60) {
3941
+ const _ = slowLogging`fs.unlinkSync(${path60})`;
3942
+ fs.unlinkSync(path60);
3943
3943
  },
3944
3944
  renameSync(oldPath, newPath) {
3945
3945
  const _ = slowLogging`fs.renameSync(${oldPath} → ${newPath})`;
3946
3946
  fs.renameSync(oldPath, newPath);
3947
3947
  },
3948
- linkSync(target, path59) {
3949
- const _ = slowLogging`fs.linkSync(${target} → ${path59})`;
3950
- fs.linkSync(target, path59);
3948
+ linkSync(target, path60) {
3949
+ const _ = slowLogging`fs.linkSync(${target} → ${path60})`;
3950
+ fs.linkSync(target, path60);
3951
3951
  },
3952
- symlinkSync(target, path59, type) {
3953
- const _ = slowLogging`fs.symlinkSync(${target} → ${path59})`;
3954
- fs.symlinkSync(target, path59, type);
3952
+ symlinkSync(target, path60, type) {
3953
+ const _ = slowLogging`fs.symlinkSync(${target} → ${path60})`;
3954
+ fs.symlinkSync(target, path60, type);
3955
3955
  },
3956
- readlinkSync(path59) {
3957
- const _ = slowLogging`fs.readlinkSync(${path59})`;
3958
- return fs.readlinkSync(path59);
3956
+ readlinkSync(path60) {
3957
+ const _ = slowLogging`fs.readlinkSync(${path60})`;
3958
+ return fs.readlinkSync(path60);
3959
3959
  },
3960
- realpathSync(path59) {
3961
- const _ = slowLogging`fs.realpathSync(${path59})`;
3962
- return fs.realpathSync(path59).normalize("NFC");
3960
+ realpathSync(path60) {
3961
+ const _ = slowLogging`fs.realpathSync(${path60})`;
3962
+ return fs.realpathSync(path60).normalize("NFC");
3963
3963
  },
3964
3964
  mkdirSync(dirPath, options) {
3965
3965
  const _ = slowLogging`fs.mkdirSync(${dirPath})`;
@@ -3992,12 +3992,12 @@ var NodeFsOperations = {
3992
3992
  const _ = slowLogging`fs.rmdirSync(${dirPath})`;
3993
3993
  fs.rmdirSync(dirPath);
3994
3994
  },
3995
- rmSync(path59, options) {
3996
- const _ = slowLogging`fs.rmSync(${path59})`;
3997
- fs.rmSync(path59, options);
3995
+ rmSync(path60, options) {
3996
+ const _ = slowLogging`fs.rmSync(${path60})`;
3997
+ fs.rmSync(path60, options);
3998
3998
  },
3999
- createWriteStream(path59) {
4000
- return fs.createWriteStream(path59);
3999
+ createWriteStream(path60) {
4000
+ return fs.createWriteStream(path60);
4001
4001
  },
4002
4002
  async readFileBytes(fsPath, maxBytes) {
4003
4003
  if (maxBytes === void 0) {
@@ -4104,12 +4104,12 @@ function shouldLogDebugMessage(message2) {
4104
4104
  var hasFormattedOutput = false;
4105
4105
  var debugWriter = null;
4106
4106
  var pendingWrite = Promise.resolve();
4107
- async function appendAsync(needMkdir, dir, path59, content) {
4107
+ async function appendAsync(needMkdir, dir, path60, content) {
4108
4108
  if (needMkdir) {
4109
4109
  await mkdir(dir, { recursive: true }).catch(() => {
4110
4110
  });
4111
4111
  }
4112
- await appendFile(path59, content);
4112
+ await appendFile(path60, content);
4113
4113
  void updateLatestDebugLogSymlink();
4114
4114
  }
4115
4115
  function noop() {
@@ -4119,8 +4119,8 @@ function getDebugWriter() {
4119
4119
  let ensuredDir = null;
4120
4120
  debugWriter = createBufferedWriter({
4121
4121
  writeFn: (content) => {
4122
- const path59 = getDebugLogPath();
4123
- const dir = dirname(path59);
4122
+ const path60 = getDebugLogPath();
4123
+ const dir = dirname(path60);
4124
4124
  const needMkdir = ensuredDir !== dir;
4125
4125
  ensuredDir = dir;
4126
4126
  if (isDebugMode()) {
@@ -4130,11 +4130,11 @@ function getDebugWriter() {
4130
4130
  } catch {
4131
4131
  }
4132
4132
  }
4133
- getFsImplementation().appendFileSync(path59, content);
4133
+ getFsImplementation().appendFileSync(path60, content);
4134
4134
  void updateLatestDebugLogSymlink();
4135
4135
  return;
4136
4136
  }
4137
- pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir, path59, content)).catch(noop);
4137
+ pendingWrite = pendingWrite.then(appendAsync.bind(null, needMkdir, dir, path60, content)).catch(noop);
4138
4138
  },
4139
4139
  flushIntervalMs: 1e3,
4140
4140
  maxBufferSize: 100,
@@ -10321,8 +10321,8 @@ import codeExcerpt from "code-excerpt";
10321
10321
  import { readFileSync as readFileSync2 } from "fs";
10322
10322
  import StackUtils from "stack-utils";
10323
10323
  import { jsx as jsx6, jsxs } from "react/jsx-runtime";
10324
- var cleanupPath = (path59) => {
10325
- return path59?.replace(`file://${process.cwd()}/`, "");
10324
+ var cleanupPath = (path60) => {
10325
+ return path60?.replace(`file://${process.cwd()}/`, "");
10326
10326
  };
10327
10327
  var stackUtils;
10328
10328
  function getStackUtils() {
@@ -14299,8 +14299,8 @@ var getInstance = (stdout, createInstance) => {
14299
14299
 
14300
14300
  // src/main.ts
14301
14301
  import { EventEmitter as EventEmitter7 } from "events";
14302
- import fs52 from "fs";
14303
- import path58 from "path";
14302
+ import fs53 from "fs";
14303
+ import path59 from "path";
14304
14304
  import { fileURLToPath as fileURLToPath8 } from "url";
14305
14305
  import { spawn as spawn6 } from "child_process";
14306
14306
  import { v4 as uuidv412 } from "uuid";
@@ -14979,7 +14979,7 @@ function cancelSlashSubmenu() {
14979
14979
 
14980
14980
  // src/app/agent/agent.ts
14981
14981
  import * as dotenv from "dotenv";
14982
- import path48 from "path";
14982
+ import path49 from "path";
14983
14983
  import os30 from "os";
14984
14984
 
14985
14985
  // src/app/agent/tool_invoker.ts
@@ -22028,14 +22028,14 @@ PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
22028
22028
 
22029
22029
  // src/app/agent/bluma/core/bluma.ts
22030
22030
  init_session_manager();
22031
- import path45 from "path";
22032
- import fs40 from "fs";
22031
+ import path46 from "path";
22032
+ import fs41 from "fs";
22033
22033
  import { v4 as uuidv48 } from "uuid";
22034
22034
 
22035
22035
  // src/app/agent/core/prompt/prompt_builder.ts
22036
22036
  import os23 from "os";
22037
- import fs36 from "fs";
22038
- import path39 from "path";
22037
+ import fs37 from "fs";
22038
+ import path40 from "path";
22039
22039
  import { execSync as execSync3 } from "child_process";
22040
22040
 
22041
22041
  // src/app/agent/skills/skill_loader.ts
@@ -23892,12 +23892,12 @@ init_session_memory_paths();
23892
23892
  import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
23893
23893
  async function loadSessionMemoryForPrompt(sessionId, cwd2 = process.cwd()) {
23894
23894
  if (!sessionId?.trim()) return "";
23895
- const path59 = getSessionMemoryPath(sessionId, cwd2);
23895
+ const path60 = getSessionMemoryPath(sessionId, cwd2);
23896
23896
  try {
23897
- const content = await readFile3(path59, "utf-8");
23897
+ const content = await readFile3(path60, "utf-8");
23898
23898
  if (!content.trim()) return "";
23899
23899
  return `<session_memory>
23900
- Notes for this conversation (${path59}):
23900
+ Notes for this conversation (${path60}):
23901
23901
 
23902
23902
  ${content.trim()}
23903
23903
  </session_memory>`;
@@ -23907,11 +23907,11 @@ ${content.trim()}
23907
23907
  }
23908
23908
  async function initSessionMemoryFile(sessionId, cwd2 = process.cwd()) {
23909
23909
  await ensureSessionMemoryDir(sessionId, cwd2);
23910
- const path59 = getSessionMemoryPath(sessionId, cwd2);
23910
+ const path60 = getSessionMemoryPath(sessionId, cwd2);
23911
23911
  try {
23912
- await readFile3(path59, "utf-8");
23912
+ await readFile3(path60, "utf-8");
23913
23913
  } catch {
23914
- await writeFile2(path59, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
23914
+ await writeFile2(path60, `${DEFAULT_SESSION_MEMORY_TEMPLATE}
23915
23915
  `, "utf-8");
23916
23916
  }
23917
23917
  }
@@ -23923,14 +23923,14 @@ var FACTORAI_SH_SECTION = `
23923
23923
 
23924
23924
  **When to load full checklist:** \`load_skill("factorai-sh")\` before any create/deploy/edit/redeploy task.
23925
23925
 
23926
- ### Backend URL (already in your environment)
23926
+ ### Backend URL (see also \`<sandbox_runtime>\` table)
23927
23927
  | Variable | Used by |
23928
23928
  |----------|---------|
23929
23929
  | \`FACTORAI_BASE_URL\` | \`factorai.sh.get_app_status\`, \`factorai.sh.apply_app_changes\`, \`factorai.sh.redeploy_app\` |
23930
23930
  | \`SEVERINO_URL\` | \`factorai.sh.deploy_app\` (ZIP upload to \`/api/v1/deploy\`) |
23931
23931
  | \`FACTORAI_API_KEY\` / \`SEVERINO_API_KEY\` | Optional Bearer on write endpoints |
23932
23932
 
23933
- The orchestrator configures these \u2014 **use the values already set**. Do not invent hosts or assume prod vs dev; tools call whatever base URL the environment provides.
23933
+ The orchestrator configures these \u2014 **use the values in \`<sandbox_runtime>\`**, not invented hosts. Autonomous loop: \`tsc --noEmit\` locally \u2192 \`deploy_app\` \u2192 \`get_app_status({ wait: true })\` \u2192 fix on \`failed\` \u2192 only then \`message(result)\`.
23934
23934
 
23935
23935
  ### Source of truth: \`factorai.sh.json\`
23936
23936
  - Written/updated by \`factorai.sh.deploy_app\` and FactorAI tools \u2014 **read with normal file tools**, never a separate manifest tool.
@@ -24013,6 +24013,146 @@ function isFactorAiShPromptEnabled() {
24013
24013
  return isSandbox && Boolean(baseUrl);
24014
24014
  }
24015
24015
 
24016
+ // src/app/agent/core/prompt/sandbox_autonomy_prompt.ts
24017
+ var SANDBOX_AUTONOMY_SECTION = `
24018
+ <sandbox_autonomy>
24019
+ ## Modo aut\xF3nomo (como Manus / agente de engenharia)
24020
+
24021
+ Tu **n\xE3o** est\xE1s num chat interativo com humano ao teclado. Est\xE1s num **worker** com um objetivo, ferramentas, e um prazo. Comportamento esperado:
24022
+
24023
+ ### 1. Orientar-te (sempre primeiro)
24024
+ - L\xEA \`<sandbox_runtime>\` \u2014 session, cwd, URLs, pedido, \`factorai.sh.json\` se existir.
24025
+ - Se o pedido envolve Next.js / site / deploy: \`load_skill("factorai-sh")\`.
24026
+ - Lista o diret\xF3rio relevante (\`ls_tool\`) antes de assumir estrutura de ficheiros.
24027
+
24028
+ ### 2. Planear em sil\xEAncio \xFAtil
24029
+ - Usa \`todo\` ou \`task_create\` para 3\u20138 passos concretos (n\xE3o gen\xE9ricos).
24030
+ - \`message({ message_type: "info" })\` a cada fase importante \u2014 o orquestrador v\xEA progresso.
24031
+
24032
+ ### 3. Implementar como humano s\xE9nior
24033
+ - Edita com \`edit_tool\` / \`file_write\`; l\xEA ficheiros completos antes de patch grande.
24034
+ - UI Next: \`@/components/ui/*\` do scaffold; n\xE3o reinventar componentes.
24035
+ - Subtarefas paralelas: \`spawn_agent\` + \`wait_agent\` quando fizer sentido.
24036
+
24037
+ ### 4. Verificar **antes** de deploy (obrigat\xF3rio para apps Next)
24038
+ No diret\xF3rio do projeto (ex. \`./my-app\`):
24039
+ 1. \`npx tsc --noEmit\` \u2014 corrige todos os erros TypeScript.
24040
+ 2. Opcional: \`npm run lint\` se existir script.
24041
+ 3. **Evita** \`npm run build\` local **antes do primeiro** \`deploy_app\` (cria \`.next/\` e incha o ZIP). O build de produ\xE7\xE3o corre no FactorAI.sh.
24042
+
24043
+ ### 5. Deploy e valida\xE7\xE3o remota
24044
+ 1. \`factorai.sh.deploy_app({ projectDir, name })\` \u2014 primeiro deploy.
24045
+ 2. \`factorai.sh.get_app_status({ appId, wait: true })\` \u2014 espera \`ready\` ou \`failed\`.
24046
+ 3. Se \`failed\`: l\xEA \`typescriptErrors\`, \`buildLogTail\`, \`summary\` no resultado; corrige c\xF3digo; \`apply_app_changes\` ou novo deploy; **nunca** digas que est\xE1 online.
24047
+ 4. S\xF3 depois de \`ready\`: confirma URL (curl ou l\xF3gica) e \`message(result)\` com \`factor-sh-url-app\`.
24048
+
24049
+ ### 6. Edi\xE7\xF5es em app j\xE1 online (esta sess\xE3o)
24050
+ - \`factorai.sh.apply_app_changes\` com ficheiro **completo** em cada \`files[].content\`.
24051
+ - Volta a \`get_app_status({ wait: true })\` ap\xF3s rebuild.
24052
+
24053
+ ### 7. Entregar como produto acabado
24054
+ - Ficheiros: \`message(result)\` + \`attachments\` em \`.bluma/artifacts/\`.
24055
+ - App live: \`factor-sh-url-app\` com URL absoluta.
24056
+ - Resumo em portugu\xEAs claro: o que fizeste, URL, pr\xF3ximos passos se falhou.
24057
+
24058
+ ### Proibido no sandbox worker
24059
+ - Pedir confirma\xE7\xE3o ao utilizador (\`ask_user_question\`) salvo bloqueio real de credencial em falta no env.
24060
+ - Inventar URLs, appIds, ou hosts \u2014 usa s\xF3 \`<sandbox_runtime>\` e \`factorai.sh.json\`.
24061
+ - \`message(result)\` com sucesso se deploy/build falhou.
24062
+ - Ignorar erros de compila\xE7\xE3o (\u201Cvou deploy na mesma\u201D).
24063
+ </sandbox_autonomy>
24064
+ `;
24065
+
24066
+ // src/app/agent/runtime/sandbox_runtime_context.ts
24067
+ import fs36 from "fs";
24068
+ import path39 from "path";
24069
+ function env2(key) {
24070
+ return String(process.env[key] ?? "").trim();
24071
+ }
24072
+ function listWorkspaceTopLevel(cwd2, max = 24) {
24073
+ try {
24074
+ return fs36.readdirSync(cwd2, { withFileTypes: true }).filter((e) => !e.name.startsWith(".")).slice(0, max).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
24075
+ } catch {
24076
+ return [];
24077
+ }
24078
+ }
24079
+ function buildSandboxRuntimeContextBlock(cwd2) {
24080
+ const sessionId = env2("BLUMA_SESSION_ID") || "unknown";
24081
+ const sandboxName = env2("BLUMA_SANDBOX_NAME") || "sandbox-api";
24082
+ const fromAgent = env2("BLUMA_FROM_AGENT") || "orchestrator";
24083
+ const action = env2("BLUMA_ACTION") || "unknown";
24084
+ const severinoUrl = env2("SEVERINO_URL");
24085
+ const factoraiUrl = env2("FACTORAI_BASE_URL") || env2("FACTORAI_URL") || severinoUrl;
24086
+ const userRequest = env2("BLUMA_USER_REQUEST");
24087
+ const factoraiEnabled = isFactorAiShPromptEnabled();
24088
+ const top = listWorkspaceTopLevel(cwd2);
24089
+ const lines = [
24090
+ "<sandbox_runtime>",
24091
+ "## Ambiente atual (factos reais \u2014 usa isto para te orientares)",
24092
+ "",
24093
+ "Operas como **agente aut\xF3nomo** (estilo Manus): n\xE3o h\xE1 utilizador no terminal a responder. O orquestrador (Severino / sandbox-api) envia o pedido, observa o teu progresso via `message(info)` e s\xF3 encerra o job com `message(result)`.",
24094
+ "",
24095
+ "| Campo | Valor |",
24096
+ "|-------|-------|",
24097
+ `| sandbox | ${sandboxName} |`,
24098
+ `| session_id | ${sessionId} |`,
24099
+ `| workspace (cwd) | ${cwd2} |`,
24100
+ `| delegado por | ${fromAgent} |`,
24101
+ `| action | ${action} |`,
24102
+ `| node | ${process.version} |`,
24103
+ `| auto_approve_tools | sim (sandbox isolado) |`
24104
+ ];
24105
+ if (severinoUrl) {
24106
+ lines.push(`| SEVERINO_URL (deploy ZIP) | ${severinoUrl} |`);
24107
+ }
24108
+ if (factoraiUrl) {
24109
+ lines.push(`| FACTORAI_BASE_URL (status/apply/redeploy) | ${factoraiUrl} |`);
24110
+ }
24111
+ if (severinoUrl && factoraiUrl && severinoUrl !== factoraiUrl) {
24112
+ lines.push("");
24113
+ lines.push(
24114
+ "\u26A0\uFE0F SEVERINO_URL e FACTORAI_BASE_URL diferem \u2014 confirma qual backend falhou se `get_app_status` der 404 ap\xF3s deploy."
24115
+ );
24116
+ }
24117
+ if (factoraiEnabled) {
24118
+ lines.push("");
24119
+ lines.push("**FactorAI.sh:** ativo nesta sess\xE3o (`factorai.sh.*` tools dispon\xEDveis).");
24120
+ } else {
24121
+ lines.push("");
24122
+ lines.push(
24123
+ "**FactorAI.sh:** n\xE3o configurado (falta `FACTORAI_BASE_URL` ou `BLUMA_SANDBOX`). Hosting Next.js via factorai.sh indispon\xEDvel at\xE9 o orquestrador definir env."
24124
+ );
24125
+ }
24126
+ if (top.length > 0) {
24127
+ lines.push("");
24128
+ lines.push(`**Raiz do workspace:** ${top.join(", ")}`);
24129
+ }
24130
+ const manifest = readFactorAiWorkspaceManifest(cwd2);
24131
+ if (manifest) {
24132
+ const ctx = manifest.appContext;
24133
+ const appId = ctx?.appId;
24134
+ const liveUrl = resolveFactorShAppLiveUrl(cwd2);
24135
+ lines.push("");
24136
+ lines.push("**App FactorAI nesta sess\xE3o (factorai.sh.json):**");
24137
+ if (appId) lines.push(`- appId: ${appId}`);
24138
+ if (liveUrl) lines.push(`- appUrl: ${liveUrl}`);
24139
+ const appDir = typeof manifest.app === "object" && manifest.app && typeof manifest.app.name === "string" ? manifest.app.name : null;
24140
+ if (appDir) {
24141
+ const projectPath = path39.join(cwd2, appDir);
24142
+ if (fs36.existsSync(projectPath)) {
24143
+ lines.push(`- project_dir: ${projectPath}`);
24144
+ }
24145
+ }
24146
+ }
24147
+ if (userRequest) {
24148
+ lines.push("");
24149
+ lines.push("**Pedido deste turno (resumo):**");
24150
+ lines.push(userRequest.length > 2500 ? `${userRequest.slice(0, 2500)}\u2026` : userRequest);
24151
+ }
24152
+ lines.push("</sandbox_runtime>");
24153
+ return lines.join("\n");
24154
+ }
24155
+
24016
24156
  // src/app/agent/core/prompt/prompt_builder.ts
24017
24157
  function getNodeVersion() {
24018
24158
  return process.version;
@@ -24044,17 +24184,17 @@ function getGitBranch(dir) {
24044
24184
  }
24045
24185
  }
24046
24186
  function getPackageManager(dir) {
24047
- if (fs36.existsSync(path39.join(dir, "pnpm-lock.yaml"))) return "pnpm";
24048
- if (fs36.existsSync(path39.join(dir, "yarn.lock"))) return "yarn";
24049
- if (fs36.existsSync(path39.join(dir, "bun.lockb"))) return "bun";
24050
- if (fs36.existsSync(path39.join(dir, "package-lock.json"))) return "npm";
24187
+ if (fs37.existsSync(path40.join(dir, "pnpm-lock.yaml"))) return "pnpm";
24188
+ if (fs37.existsSync(path40.join(dir, "yarn.lock"))) return "yarn";
24189
+ if (fs37.existsSync(path40.join(dir, "bun.lockb"))) return "bun";
24190
+ if (fs37.existsSync(path40.join(dir, "package-lock.json"))) return "npm";
24051
24191
  return "unknown";
24052
24192
  }
24053
24193
  function getProjectType(dir) {
24054
24194
  try {
24055
- const files = fs36.readdirSync(dir);
24195
+ const files = fs37.readdirSync(dir);
24056
24196
  if (files.includes("package.json")) {
24057
- const pkg = JSON.parse(fs36.readFileSync(path39.join(dir, "package.json"), "utf-8"));
24197
+ const pkg = JSON.parse(fs37.readFileSync(path40.join(dir, "package.json"), "utf-8"));
24058
24198
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
24059
24199
  if (deps.next) return "Next.js";
24060
24200
  if (deps.react) return "React";
@@ -24074,9 +24214,9 @@ function getProjectType(dir) {
24074
24214
  }
24075
24215
  function getTestFramework(dir) {
24076
24216
  try {
24077
- const pkgPath = path39.join(dir, "package.json");
24078
- if (fs36.existsSync(pkgPath)) {
24079
- const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
24217
+ const pkgPath = path40.join(dir, "package.json");
24218
+ if (fs37.existsSync(pkgPath)) {
24219
+ const pkg = JSON.parse(fs37.readFileSync(pkgPath, "utf-8"));
24080
24220
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
24081
24221
  if (deps.jest) return "jest";
24082
24222
  if (deps.vitest) return "vitest";
@@ -24085,7 +24225,7 @@ function getTestFramework(dir) {
24085
24225
  if (deps["@playwright/test"]) return "playwright";
24086
24226
  if (deps.cypress) return "cypress";
24087
24227
  }
24088
- if (fs36.existsSync(path39.join(dir, "pytest.ini")) || fs36.existsSync(path39.join(dir, "conftest.py"))) return "pytest";
24228
+ if (fs37.existsSync(path40.join(dir, "pytest.ini")) || fs37.existsSync(path40.join(dir, "conftest.py"))) return "pytest";
24089
24229
  return "unknown";
24090
24230
  } catch {
24091
24231
  return "unknown";
@@ -24093,9 +24233,9 @@ function getTestFramework(dir) {
24093
24233
  }
24094
24234
  function getTestCommand(dir) {
24095
24235
  try {
24096
- const pkgPath = path39.join(dir, "package.json");
24097
- if (fs36.existsSync(pkgPath)) {
24098
- const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf-8"));
24236
+ const pkgPath = path40.join(dir, "package.json");
24237
+ if (fs37.existsSync(pkgPath)) {
24238
+ const pkg = JSON.parse(fs37.readFileSync(pkgPath, "utf-8"));
24099
24239
  if (pkg.scripts?.test) return "npm test";
24100
24240
  if (pkg.scripts?.["test:unit"]) return "npm run test:unit";
24101
24241
  }
@@ -24110,8 +24250,8 @@ function getTestCommand(dir) {
24110
24250
  }
24111
24251
  function isGitRepo(dir) {
24112
24252
  try {
24113
- const p = path39.join(dir, ".git");
24114
- return fs36.existsSync(p) && fs36.lstatSync(p).isDirectory();
24253
+ const p = path40.join(dir, ".git");
24254
+ return fs37.existsSync(p) && fs37.lstatSync(p).isDirectory();
24115
24255
  } catch {
24116
24256
  return false;
24117
24257
  }
@@ -24322,7 +24462,7 @@ async function getUnifiedSystemPrompt(availableSkills, options) {
24322
24462
  const runtimeConfig = getRuntimeConfig();
24323
24463
  const cwd2 = process.cwd();
24324
24464
  const isSandbox = process.env.BLUMA_SANDBOX === "true";
24325
- const env2 = {
24465
+ const env3 = {
24326
24466
  os_type: os23.type(),
24327
24467
  os_version: os23.release(),
24328
24468
  architecture: os23.arch(),
@@ -24347,7 +24487,7 @@ async function getUnifiedSystemPrompt(availableSkills, options) {
24347
24487
  session_id: process.env.BLUMA_SESSION_ID || "unknown",
24348
24488
  workspace_root: cwd2
24349
24489
  };
24350
- const interpolate = (template) => Object.entries(env2).reduce((s, [k, v]) => s.replaceAll(`{${k}}`, v), template);
24490
+ const interpolate = (template) => Object.entries(env3).reduce((s, [k, v]) => s.replaceAll(`{${k}}`, v), template);
24351
24491
  let prompt = interpolate(SYSTEM_PROMPT).replace(
24352
24492
  "<<<BLUMA_WORKSPACE_SNAPSHOT_BODY>>>",
24353
24493
  buildWorkspaceSnapshot(cwd2)
@@ -24366,6 +24506,12 @@ async function getUnifiedSystemPrompt(availableSkills, options) {
24366
24506
  prompt += `
24367
24507
 
24368
24508
  ${SUBJECT_MACHINE_MODEL_XML}`;
24509
+ prompt += `
24510
+
24511
+ ${buildSandboxRuntimeContextBlock(cwd2)}`;
24512
+ prompt += `
24513
+
24514
+ ${SANDBOX_AUTONOMY_SECTION}`;
24369
24515
  prompt += interpolate(SANDBOX_SECTION);
24370
24516
  if (isFactorAiShPromptEnabled()) {
24371
24517
  prompt += `
@@ -25545,9 +25691,9 @@ var LLMService = class {
25545
25691
  };
25546
25692
 
25547
25693
  // src/app/agent/utils/user_message_images.ts
25548
- import fs37 from "fs";
25694
+ import fs38 from "fs";
25549
25695
  import os25 from "os";
25550
- import path40 from "path";
25696
+ import path41 from "path";
25551
25697
  import { fileURLToPath as fileURLToPath5 } from "url";
25552
25698
  var IMAGE_EXT = /\.(png|jpe?g|gif|webp|bmp)$/i;
25553
25699
  var MAX_IMAGE_BYTES = 4 * 1024 * 1024;
@@ -25563,22 +25709,22 @@ var MIME = {
25563
25709
  function expandUserPath(p) {
25564
25710
  const t = p.trim();
25565
25711
  if (t.startsWith("~")) {
25566
- return path40.join(os25.homedir(), t.slice(1).replace(/^\//, ""));
25712
+ return path41.join(os25.homedir(), t.slice(1).replace(/^\//, ""));
25567
25713
  }
25568
25714
  return t;
25569
25715
  }
25570
25716
  function isPathAllowed(absResolved, cwd2) {
25571
- const resolved = path40.normalize(path40.resolve(absResolved));
25572
- const cwdR = path40.normalize(path40.resolve(cwd2));
25573
- const homeR = path40.normalize(path40.resolve(os25.homedir()));
25574
- const tmpR = path40.normalize(path40.resolve(os25.tmpdir()));
25575
- const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path40.sep);
25576
- const underHome = resolved === homeR || resolved.startsWith(homeR + path40.sep);
25577
- const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path40.sep);
25717
+ const resolved = path41.normalize(path41.resolve(absResolved));
25718
+ const cwdR = path41.normalize(path41.resolve(cwd2));
25719
+ const homeR = path41.normalize(path41.resolve(os25.homedir()));
25720
+ const tmpR = path41.normalize(path41.resolve(os25.tmpdir()));
25721
+ const underCwd = resolved === cwdR || resolved.startsWith(cwdR + path41.sep);
25722
+ const underHome = resolved === homeR || resolved.startsWith(homeR + path41.sep);
25723
+ const underTmp = resolved === tmpR || resolved.startsWith(tmpR + path41.sep);
25578
25724
  return underCwd || underHome || underTmp;
25579
25725
  }
25580
25726
  function mimeFor(abs) {
25581
- const ext = path40.extname(abs).toLowerCase();
25727
+ const ext = path41.extname(abs).toLowerCase();
25582
25728
  return MIME[ext] || "application/octet-stream";
25583
25729
  }
25584
25730
  var IMAGE_EXT_SRC = String.raw`(?:png|jpe?g|gif|webp|bmp)`;
@@ -25622,10 +25768,10 @@ function collectImagePathStrings(raw) {
25622
25768
  }
25623
25769
  function resolveImagePath(candidate, cwd2) {
25624
25770
  const expanded = expandUserPath(candidate);
25625
- const abs = path40.isAbsolute(expanded) ? path40.normalize(expanded) : path40.normalize(path40.resolve(cwd2, expanded));
25771
+ const abs = path41.isAbsolute(expanded) ? path41.normalize(expanded) : path41.normalize(path41.resolve(cwd2, expanded));
25626
25772
  if (!isPathAllowed(abs, cwd2)) return null;
25627
25773
  try {
25628
- if (!fs37.existsSync(abs) || !fs37.statSync(abs).isFile()) return null;
25774
+ if (!fs38.existsSync(abs) || !fs38.statSync(abs).isFile()) return null;
25629
25775
  } catch {
25630
25776
  return null;
25631
25777
  }
@@ -25645,11 +25791,11 @@ function trySingleLineFileUriOrBareImagePath(line, cwd2) {
25645
25791
  if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
25646
25792
  s = s.slice(1, -1).trim();
25647
25793
  }
25648
- if (!IMAGE_EXT.test(path40.extname(s))) return null;
25794
+ if (!IMAGE_EXT.test(path41.extname(s))) return null;
25649
25795
  const abs = resolveImagePath(s, cwd2);
25650
25796
  if (!abs) return null;
25651
25797
  try {
25652
- const st = fs37.statSync(abs);
25798
+ const st = fs38.statSync(abs);
25653
25799
  if (!st.isFile() || st.size > MAX_IMAGE_BYTES) {
25654
25800
  return null;
25655
25801
  }
@@ -25684,7 +25830,7 @@ function tryPasteChunkAsSingleImagePath(chunk, cwd2) {
25684
25830
  return null;
25685
25831
  }
25686
25832
  try {
25687
- const st = fs37.statSync(abs);
25833
+ const st = fs38.statSync(abs);
25688
25834
  if (!st.isFile() || st.size > MAX_IMAGE_BYTES) {
25689
25835
  return null;
25690
25836
  }
@@ -25713,7 +25859,7 @@ function buildUserMessageContent(raw, cwd2) {
25713
25859
  const abs = resolveImagePath(c, cwd2);
25714
25860
  if (!abs) continue;
25715
25861
  try {
25716
- const st = fs37.statSync(abs);
25862
+ const st = fs38.statSync(abs);
25717
25863
  if (st.size > MAX_IMAGE_BYTES) continue;
25718
25864
  } catch {
25719
25865
  continue;
@@ -25730,7 +25876,7 @@ function buildUserMessageContent(raw, cwd2) {
25730
25876
  }
25731
25877
  const parts = [{ type: "text", text: textPart }];
25732
25878
  for (const abs of resolvedAbs) {
25733
- const buf = fs37.readFileSync(abs);
25879
+ const buf = fs38.readFileSync(abs);
25734
25880
  const b64 = buf.toString("base64");
25735
25881
  const mime = mimeFor(abs);
25736
25882
  parts.push({
@@ -25748,7 +25894,7 @@ function buildUserMessageContent(raw, cwd2) {
25748
25894
  init_sandbox_policy();
25749
25895
  init_runtime_config();
25750
25896
  init_permission_rules();
25751
- import path41 from "path";
25897
+ import path42 from "path";
25752
25898
  var LOCAL_EDIT_TOOL_NAMES = /* @__PURE__ */ new Set(["edit_tool", "file_write", "notebook_edit"]);
25753
25899
  function getToolPermissionLayer(metadata) {
25754
25900
  if (metadata.riskLevel === "safe") return "read";
@@ -25763,11 +25909,11 @@ function checkFilePermissionRules(toolName, filePath, policy) {
25763
25909
  if (!filePath) {
25764
25910
  return { allowed: false, reason: "No file path provided for permission check." };
25765
25911
  }
25766
- const resolvedPath = path41.resolve(filePath);
25912
+ const resolvedPath = path42.resolve(filePath);
25767
25913
  if (!isPathInsideWorkspace(resolvedPath, policy)) {
25768
25914
  return { allowed: false, reason: `File path "${filePath}" is outside workspace root.` };
25769
25915
  }
25770
- const relativePath = path41.relative(policy.workspaceRoot, resolvedPath);
25916
+ const relativePath = path42.relative(policy.workspaceRoot, resolvedPath);
25771
25917
  const toolPattern = `${toolName}(${relativePath})`;
25772
25918
  const ruleDecision = permissionRulesEngine.checkPermission(toolPattern, { filepath: filePath });
25773
25919
  if (ruleDecision === "deny") {
@@ -25776,7 +25922,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
25776
25922
  if (ruleDecision === "allow") {
25777
25923
  return { allowed: true, reason: `File "${filePath}" allowed by permission rules.` };
25778
25924
  }
25779
- const dirPath = path41.dirname(relativePath);
25925
+ const dirPath = path42.dirname(relativePath);
25780
25926
  const dirPattern = `${toolName}(${dirPath}/**)`;
25781
25927
  const dirRuleDecision = permissionRulesEngine.checkPermission(dirPattern, { filepath: filePath });
25782
25928
  if (dirRuleDecision === "allow") {
@@ -25993,11 +26139,11 @@ function effectiveToolAutoApprove(toolCall, sessionId, options) {
25993
26139
  }
25994
26140
 
25995
26141
  // src/app/agent/tools/CodingMemoryTool/CodingMemoryConsolidate.ts
25996
- import * as fs38 from "fs";
25997
- import * as path42 from "path";
26142
+ import * as fs39 from "fs";
26143
+ import * as path43 from "path";
25998
26144
  import os26 from "os";
25999
26145
  function memoryPath2() {
26000
- return path42.join(process.env.HOME || os26.homedir(), ".bluma", "coding_memory.json");
26146
+ return path43.join(process.env.HOME || os26.homedir(), ".bluma", "coding_memory.json");
26001
26147
  }
26002
26148
  function normalizeNote2(note) {
26003
26149
  return note.trim().toLowerCase().replace(/\s+/g, " ");
@@ -26007,18 +26153,18 @@ function uniqTags(a, b) {
26007
26153
  }
26008
26154
  function consolidateCodingMemoryFile() {
26009
26155
  const p = memoryPath2();
26010
- if (!fs38.existsSync(p)) {
26156
+ if (!fs39.existsSync(p)) {
26011
26157
  return { success: true, removedDuplicates: 0, message: "no coding_memory.json" };
26012
26158
  }
26013
26159
  const bak = `${p}.bak`;
26014
26160
  try {
26015
- fs38.copyFileSync(p, bak);
26161
+ fs39.copyFileSync(p, bak);
26016
26162
  } catch (e) {
26017
26163
  return { success: false, removedDuplicates: 0, message: `backup failed: ${e.message}` };
26018
26164
  }
26019
26165
  let data;
26020
26166
  try {
26021
- data = JSON.parse(fs38.readFileSync(p, "utf-8"));
26167
+ data = JSON.parse(fs39.readFileSync(p, "utf-8"));
26022
26168
  } catch (e) {
26023
26169
  return { success: false, removedDuplicates: 0, message: `invalid json: ${e.message}` };
26024
26170
  }
@@ -26053,7 +26199,7 @@ function consolidateCodingMemoryFile() {
26053
26199
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
26054
26200
  };
26055
26201
  try {
26056
- fs38.writeFileSync(p, JSON.stringify(out, null, 2), "utf-8");
26202
+ fs39.writeFileSync(p, JSON.stringify(out, null, 2), "utf-8");
26057
26203
  } catch (e) {
26058
26204
  return { success: false, removedDuplicates: 0, message: `write failed: ${e.message}` };
26059
26205
  }
@@ -26559,18 +26705,18 @@ var BluMaToolRunner = class {
26559
26705
 
26560
26706
  // src/app/agent/session_manager/session_archive.ts
26561
26707
  init_bluma_app_dir();
26562
- import path43 from "path";
26563
- import { promises as fs39 } from "fs";
26708
+ import path44 from "path";
26709
+ import { promises as fs40 } from "fs";
26564
26710
  async function archivePrunedConversationMessages(sessionId, messages) {
26565
26711
  if (!sessionId || messages.length === 0) {
26566
26712
  return null;
26567
26713
  }
26568
26714
  const appDir = getPreferredAppDir();
26569
- const dir = path43.join(appDir, "sessions", "archive", sessionId);
26570
- await fs39.mkdir(dir, { recursive: true });
26571
- const archiveFile = path43.join(dir, `${Date.now()}.jsonl`);
26715
+ const dir = path44.join(appDir, "sessions", "archive", sessionId);
26716
+ await fs40.mkdir(dir, { recursive: true });
26717
+ const archiveFile = path44.join(dir, `${Date.now()}.jsonl`);
26572
26718
  const lines = messages.map((m) => JSON.stringify(m)).join("\n") + "\n";
26573
- await fs39.appendFile(archiveFile, lines, "utf-8");
26719
+ await fs40.appendFile(archiveFile, lines, "utf-8");
26574
26720
  return archiveFile;
26575
26721
  }
26576
26722
 
@@ -27431,7 +27577,7 @@ Update existing files instead of duplicating.` : "";
27431
27577
 
27432
27578
  // src/app/agent/memory/memory_tool_policy.ts
27433
27579
  init_paths();
27434
- import path44 from "path";
27580
+ import path45 from "path";
27435
27581
  var MEMORY_READ_TOOLS = /* @__PURE__ */ new Set([
27436
27582
  "read_file_lines",
27437
27583
  "grep_search",
@@ -27458,7 +27604,7 @@ function isReadOnlyShellCommand(command) {
27458
27604
  return READ_ONLY_SHELL.test(trimmed);
27459
27605
  }
27460
27606
  function createAutoMemToolGate(memoryDir) {
27461
- const memRoot = memoryDir.endsWith(path44.sep) ? memoryDir : memoryDir + path44.sep;
27607
+ const memRoot = memoryDir.endsWith(path45.sep) ? memoryDir : memoryDir + path45.sep;
27462
27608
  return (toolName, args) => {
27463
27609
  if (MEMORY_READ_TOOLS.has(toolName)) {
27464
27610
  return { allowed: true };
@@ -27471,7 +27617,7 @@ function createAutoMemToolGate(memoryDir) {
27471
27617
  }
27472
27618
  if (MEMORY_WRITE_TOOLS.has(toolName)) {
27473
27619
  const fp = extractFilePath(args);
27474
- if (fp && isAutoMemPath(path44.resolve(fp))) {
27620
+ if (fp && isAutoMemPath(path45.resolve(fp))) {
27475
27621
  return { allowed: true };
27476
27622
  }
27477
27623
  return { allowed: false, reason: `Writes must stay under ${memRoot}` };
@@ -27480,18 +27626,18 @@ function createAutoMemToolGate(memoryDir) {
27480
27626
  };
27481
27627
  }
27482
27628
  function createSessionMemoryToolGate(sessionMemoryPath) {
27483
- const resolvedTarget = path44.resolve(sessionMemoryPath);
27629
+ const resolvedTarget = path45.resolve(sessionMemoryPath);
27484
27630
  return (toolName, args) => {
27485
27631
  if (toolName === "read_file_lines") {
27486
27632
  const fp = extractFilePath(args);
27487
- if (fp && path44.resolve(fp) === resolvedTarget) {
27633
+ if (fp && path45.resolve(fp) === resolvedTarget) {
27488
27634
  return { allowed: true };
27489
27635
  }
27490
27636
  return { allowed: false, reason: "Session memory subagent may only read the session summary file" };
27491
27637
  }
27492
27638
  if (toolName === "edit_tool") {
27493
27639
  const fp = extractFilePath(args);
27494
- if (fp && path44.resolve(fp) === resolvedTarget) {
27640
+ if (fp && path45.resolve(fp) === resolvedTarget) {
27495
27641
  return { allowed: true };
27496
27642
  }
27497
27643
  return { allowed: false, reason: "Session memory subagent may only edit the session summary file" };
@@ -27518,7 +27664,7 @@ function hasAutoMemWritesSinceHistory(history, sinceIndex) {
27518
27664
  continue;
27519
27665
  }
27520
27666
  const fp = extractFilePath(args);
27521
- if (fp && isAutoMemPath(path44.resolve(fp))) {
27667
+ if (fp && isAutoMemPath(path45.resolve(fp))) {
27522
27668
  return true;
27523
27669
  }
27524
27670
  }
@@ -27986,13 +28132,13 @@ var BluMaAgent = class {
27986
28132
  if (!this.sessionFile) return;
27987
28133
  try {
27988
28134
  const sessionData = {
27989
- session_id: path45.basename(this.sessionFile, ".json"),
28135
+ session_id: path46.basename(this.sessionFile, ".json"),
27990
28136
  created_at: (/* @__PURE__ */ new Date()).toISOString(),
27991
28137
  conversation_history: this.history,
27992
28138
  last_updated: (/* @__PURE__ */ new Date()).toISOString(),
27993
28139
  ...this.compressor.getSnapshot()
27994
28140
  };
27995
- fs40.writeFileSync(this.sessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
28141
+ fs41.writeFileSync(this.sessionFile, JSON.stringify(sessionData, null, 2), "utf-8");
27996
28142
  } catch (error) {
27997
28143
  console.error("[Bluma] Failed to persist session synchronously:", error);
27998
28144
  }
@@ -28198,7 +28344,7 @@ var BluMaAgent = class {
28198
28344
 
28199
28345
  ${editData.error.display}`;
28200
28346
  }
28201
- const filename = path45.basename(toolArgs.file_path);
28347
+ const filename = path46.basename(toolArgs.file_path);
28202
28348
  return createDiff(filename, editData.currentContent || "", editData.newContent);
28203
28349
  } catch (e) {
28204
28350
  return `An unexpected error occurred while generating the edit preview: ${e.message}`;
@@ -28933,16 +29079,16 @@ async function fullCompact(messages, targetTokens, summarizer, llmClient) {
28933
29079
  }
28934
29080
 
28935
29081
  // src/app/agent/core/memory/session_memory.ts
28936
- import fs41 from "fs";
29082
+ import fs42 from "fs";
28937
29083
  import os29 from "os";
28938
- import path46 from "path";
29084
+ import path47 from "path";
28939
29085
  import { v4 as uuidv49 } from "uuid";
28940
29086
  var SessionMemoryExtractor = class {
28941
29087
  llmClient;
28942
29088
  memoryFile;
28943
29089
  constructor(options = {}) {
28944
29090
  this.llmClient = options.llmClient;
28945
- this.memoryFile = options.memoryFile || path46.join(os29.homedir(), ".bluma", "session_memory.json");
29091
+ this.memoryFile = options.memoryFile || path47.join(os29.homedir(), ".bluma", "session_memory.json");
28946
29092
  }
28947
29093
  /**
28948
29094
  * Extract memories from conversation using LLM
@@ -28999,15 +29145,15 @@ ${messages.slice(-50).map((m) => `${m.role}: ${m.content.slice(0, 500)}`).join("
28999
29145
  );
29000
29146
  unique.sort((a, b) => b.accessCount - a.accessCount);
29001
29147
  const trimmed = unique.slice(0, 200);
29002
- fs41.writeFileSync(this.memoryFile, JSON.stringify(trimmed, null, 2));
29148
+ fs42.writeFileSync(this.memoryFile, JSON.stringify(trimmed, null, 2));
29003
29149
  }
29004
29150
  /**
29005
29151
  * Load memories from disk
29006
29152
  */
29007
29153
  async loadMemories() {
29008
29154
  try {
29009
- if (!fs41.existsSync(this.memoryFile)) return [];
29010
- const data = fs41.readFileSync(this.memoryFile, "utf-8");
29155
+ if (!fs42.existsSync(this.memoryFile)) return [];
29156
+ const data = fs42.readFileSync(this.memoryFile, "utf-8");
29011
29157
  return JSON.parse(data);
29012
29158
  } catch {
29013
29159
  return [];
@@ -29551,14 +29697,14 @@ var RouteManager = class {
29551
29697
  this.subAgents = subAgents;
29552
29698
  this.core = core;
29553
29699
  }
29554
- registerRoute(path59, handler) {
29555
- this.routeHandlers.set(path59, handler);
29700
+ registerRoute(path60, handler) {
29701
+ this.routeHandlers.set(path60, handler);
29556
29702
  }
29557
29703
  async handleRoute(payload) {
29558
29704
  const inputText = String(payload.content || "").trim();
29559
29705
  const { userContext, options } = payload;
29560
- for (const [path59, handler] of this.routeHandlers) {
29561
- if (inputText === path59 || inputText.startsWith(`${path59} `)) {
29706
+ for (const [path60, handler] of this.routeHandlers) {
29707
+ if (inputText === path60 || inputText.startsWith(`${path60} `)) {
29562
29708
  return handler({ content: inputText, userContext });
29563
29709
  }
29564
29710
  }
@@ -29567,13 +29713,13 @@ var RouteManager = class {
29567
29713
  };
29568
29714
 
29569
29715
  // src/app/agent/runtime/plugin_runtime.ts
29570
- import path47 from "path";
29716
+ import path48 from "path";
29571
29717
  import { pathToFileURL as pathToFileURL2 } from "url";
29572
29718
  async function loadPluginsAtStartup() {
29573
29719
  for (const p of listPlugins()) {
29574
29720
  const entry = p.manifest.entry?.trim();
29575
29721
  if (!entry) continue;
29576
- const abs = path47.resolve(p.root, entry);
29722
+ const abs = path48.resolve(p.root, entry);
29577
29723
  try {
29578
29724
  const href = pathToFileURL2(abs).href;
29579
29725
  const mod = await import(href);
@@ -29594,7 +29740,7 @@ async function loadPluginsAtStartup() {
29594
29740
  }
29595
29741
 
29596
29742
  // src/app/agent/agent.ts
29597
- var globalEnvPath = path48.join(os30.homedir(), ".bluma", ".env");
29743
+ var globalEnvPath = path49.join(os30.homedir(), ".bluma", ".env");
29598
29744
  dotenv.config({ path: globalEnvPath });
29599
29745
  var Agent = class {
29600
29746
  sessionId;
@@ -31450,10 +31596,10 @@ function resolveToolPayload(result) {
31450
31596
 
31451
31597
  // src/app/ui/components/FilePathLink.tsx
31452
31598
  import { pathToFileURL as pathToFileURL3 } from "node:url";
31453
- import path50 from "node:path";
31599
+ import path51 from "node:path";
31454
31600
 
31455
31601
  // src/app/ui/utils/pathDisplay.ts
31456
- import path49 from "node:path";
31602
+ import path50 from "node:path";
31457
31603
  import os31 from "node:os";
31458
31604
  function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
31459
31605
  let s = String(pathInput ?? "").trim();
@@ -31461,17 +31607,17 @@ function formatPathForDisplay(pathInput, cwd2 = process.cwd()) {
31461
31607
  s = s.replace(/[/\\]+$/, "");
31462
31608
  }
31463
31609
  if (!s) return "";
31464
- const abs = path49.isAbsolute(s) ? path49.normalize(s) : path49.resolve(cwd2, s);
31465
- const resolvedCwd = path49.resolve(cwd2);
31466
- const rel = path49.relative(resolvedCwd, abs);
31467
- if (rel === "" || !rel.startsWith("..") && !path49.isAbsolute(rel)) {
31610
+ const abs = path50.isAbsolute(s) ? path50.normalize(s) : path50.resolve(cwd2, s);
31611
+ const resolvedCwd = path50.resolve(cwd2);
31612
+ const rel = path50.relative(resolvedCwd, abs);
31613
+ if (rel === "" || !rel.startsWith("..") && !path50.isAbsolute(rel)) {
31468
31614
  return rel === "" ? "." : rel;
31469
31615
  }
31470
- const home = path49.normalize(os31.homedir());
31471
- if (abs === home || abs.startsWith(home + path49.sep)) {
31616
+ const home = path50.normalize(os31.homedir());
31617
+ if (abs === home || abs.startsWith(home + path50.sep)) {
31472
31618
  return "~" + abs.slice(home.length);
31473
31619
  }
31474
- return path49.basename(abs);
31620
+ return path50.basename(abs);
31475
31621
  }
31476
31622
 
31477
31623
  // src/app/ui/components/FilePathLink.tsx
@@ -31481,7 +31627,7 @@ function FilePathLink({ filePath, children, cwd: cwd2 = process.cwd(), color })
31481
31627
  if (!raw) {
31482
31628
  return null;
31483
31629
  }
31484
- const abs = path50.isAbsolute(raw) ? path50.normalize(raw) : path50.resolve(cwd2, raw);
31630
+ const abs = path51.isAbsolute(raw) ? path51.normalize(raw) : path51.resolve(cwd2, raw);
31485
31631
  const href = pathToFileURL3(abs).href;
31486
31632
  const label = formatPathForDisplay(abs, cwd2);
31487
31633
  const text = typeof children === "string" ? children : label;
@@ -32102,16 +32248,16 @@ function supportsHyperlinks(options) {
32102
32248
  if (stdoutSupported) {
32103
32249
  return true;
32104
32250
  }
32105
- const env2 = options?.env ?? process.env;
32106
- const termProgram = env2["TERM_PROGRAM"];
32251
+ const env3 = options?.env ?? process.env;
32252
+ const termProgram = env3["TERM_PROGRAM"];
32107
32253
  if (termProgram && ADDITIONAL_HYPERLINK_TERMINALS.includes(termProgram)) {
32108
32254
  return true;
32109
32255
  }
32110
- const lcTerminal = env2["LC_TERMINAL"];
32256
+ const lcTerminal = env3["LC_TERMINAL"];
32111
32257
  if (lcTerminal && ADDITIONAL_HYPERLINK_TERMINALS.includes(lcTerminal)) {
32112
32258
  return true;
32113
32259
  }
32114
- const term = env2["TERM"];
32260
+ const term = env3["TERM"];
32115
32261
  if (term?.includes("kitty")) {
32116
32262
  return true;
32117
32263
  }
@@ -33433,12 +33579,12 @@ function patchToUnifiedDiffText(filePath, patch) {
33433
33579
  }
33434
33580
 
33435
33581
  // src/app/ui/utils/readEditContext.ts
33436
- import { promises as fs42 } from "fs";
33582
+ import { promises as fs43 } from "fs";
33437
33583
  var CHUNK_SIZE = 64 * 1024;
33438
33584
  var CONTEXT_LINES2 = 3;
33439
33585
  async function openForScan(filePath) {
33440
33586
  try {
33441
- return await fs42.open(filePath, "r");
33587
+ return await fs43.open(filePath, "r");
33442
33588
  } catch (e) {
33443
33589
  if (e.code === "ENOENT") return null;
33444
33590
  throw e;
@@ -34116,13 +34262,13 @@ function EditToolDiffPanel({
34116
34262
  newString,
34117
34263
  replaceAll = false
34118
34264
  }) {
34119
- const path59 = filePath.trim() || "unknown file";
34265
+ const path60 = filePath.trim() || "unknown file";
34120
34266
  const hasPreviewArgs = oldString !== void 0 && newString !== void 0;
34121
34267
  const hasDiffText = diffText && diffText.trim().length > 0;
34122
34268
  return /* @__PURE__ */ jsx43(Box_default, { flexDirection: "column", children: hasPreviewArgs ? /* @__PURE__ */ jsx43(Box_default, { marginTop: 0, children: /* @__PURE__ */ jsx43(
34123
34269
  FileEditToolDiff,
34124
34270
  {
34125
- filePath: path59,
34271
+ filePath: path60,
34126
34272
  oldString,
34127
34273
  newString,
34128
34274
  replaceAll,
@@ -34160,7 +34306,7 @@ function renderToolUseMessage12({ args }) {
34160
34306
  return /* @__PURE__ */ jsx44(Text, { color: BLUMA_TERMINAL.blue, children: p });
34161
34307
  }
34162
34308
  function renderToolHeader12({ args }) {
34163
- const path59 = args?.file_path ?? ".";
34309
+ const path60 = args?.file_path ?? ".";
34164
34310
  const oldText = typeof args?.old_string === "string" ? args.old_string : "";
34165
34311
  const newText = typeof args?.new_string === "string" ? args.new_string : "";
34166
34312
  const counts = countLineDiff(oldText, newText);
@@ -34170,7 +34316,7 @@ function renderToolHeader12({ args }) {
34170
34316
  action,
34171
34317
  /* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
34172
34318
  " ",
34173
- /* @__PURE__ */ jsx44(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
34319
+ /* @__PURE__ */ jsx44(FilePathLink, { filePath: path60, color: BLUMA_TERMINAL.dim })
34174
34320
  ] })
34175
34321
  ] }),
34176
34322
  /* @__PURE__ */ jsxs27(Text, { dimColor: true, children: [
@@ -34562,11 +34708,11 @@ function userFacingName13() {
34562
34708
  }
34563
34709
  function renderToolUseMessage14({ args }) {
34564
34710
  const q = args?.query ? `"${args.query}"` : "...";
34565
- const path59 = args?.path || ".";
34711
+ const path60 = args?.path || ".";
34566
34712
  return /* @__PURE__ */ jsxs30(Box_default, { flexDirection: "row", flexWrap: "wrap", alignItems: "flex-end", children: [
34567
34713
  /* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.blue, children: q }),
34568
34714
  /* @__PURE__ */ jsx47(Text, { color: BLUMA_TERMINAL.dim, children: " " }),
34569
- /* @__PURE__ */ jsx47(FilePathLink, { filePath: path59, color: BLUMA_TERMINAL.dim })
34715
+ /* @__PURE__ */ jsx47(FilePathLink, { filePath: path60, color: BLUMA_TERMINAL.dim })
34570
34716
  ] });
34571
34717
  }
34572
34718
  function renderToolHeader14({ args }) {
@@ -35088,7 +35234,7 @@ var loadSkillTool = createTool({
35088
35234
  });
35089
35235
 
35090
35236
  // src/app/agent/tools/FileWriteTool/UI.tsx
35091
- import fs43 from "fs";
35237
+ import fs44 from "fs";
35092
35238
  import { diffLines as diffLines3 } from "diff";
35093
35239
  import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
35094
35240
  function getFilePath(args) {
@@ -35103,7 +35249,7 @@ function getFilePath(args) {
35103
35249
  function readExistingFileText(filePath) {
35104
35250
  if (!filePath) return "";
35105
35251
  try {
35106
- return fs43.readFileSync(filePath, "utf-8");
35252
+ return fs44.readFileSync(filePath, "utf-8");
35107
35253
  } catch {
35108
35254
  return "";
35109
35255
  }
@@ -38045,8 +38191,8 @@ import {
38045
38191
 
38046
38192
  // src/app/ui/hooks/useAtCompletion.ts
38047
38193
  import { useEffect as useEffect11, useRef as useRef4, useState as useState13 } from "react";
38048
- import fs44 from "fs";
38049
- import path51 from "path";
38194
+ import fs45 from "fs";
38195
+ import path52 from "path";
38050
38196
  var MAX_RESULTS3 = 50;
38051
38197
  var DEFAULT_RECURSIVE_DEPTH = 2;
38052
38198
  function listPathSuggestions(baseDir, pattern) {
@@ -38054,7 +38200,7 @@ function listPathSuggestions(baseDir, pattern) {
38054
38200
  const patternEndsWithSlash = raw.endsWith("/");
38055
38201
  const relDir = raw.replace(/^\/+|\/+$/g, "");
38056
38202
  const filterPrefix = patternEndsWithSlash ? "" : relDir.split("/").slice(-1)[0] || "";
38057
- const listDir = path51.resolve(baseDir, relDir || ".");
38203
+ const listDir = path52.resolve(baseDir, relDir || ".");
38058
38204
  const results = [];
38059
38205
  const IGNORED_DIRS = ["node_modules", ".git", ".venv", "dist", "build"];
38060
38206
  const IGNORED_EXTS = [".pyc", ".class", ".o", ".map", ".log", ".tmp"];
@@ -38071,7 +38217,7 @@ function listPathSuggestions(baseDir, pattern) {
38071
38217
  }
38072
38218
  function pushEntry(entryPath, label, isDir) {
38073
38219
  if (results.length >= MAX_RESULTS3) return;
38074
- const clean = label.split(path51.sep).join("/").replace(/[]+/g, "");
38220
+ const clean = label.split(path52.sep).join("/").replace(/[]+/g, "");
38075
38221
  results.push({ label: clean + (isDir ? "/" : ""), fullPath: entryPath, isDir });
38076
38222
  }
38077
38223
  try {
@@ -38080,11 +38226,11 @@ function listPathSuggestions(baseDir, pattern) {
38080
38226
  while (queue.length && results.length < MAX_RESULTS3) {
38081
38227
  const node = queue.shift();
38082
38228
  try {
38083
- const entries = fs44.readdirSync(node.dir, { withFileTypes: true });
38229
+ const entries = fs45.readdirSync(node.dir, { withFileTypes: true });
38084
38230
  for (const entry of entries) {
38085
38231
  if (isIgnoredName(entry.name)) continue;
38086
- const entryAbs = path51.join(node.dir, entry.name);
38087
- const entryRel = node.rel ? path51.posix.join(node.rel, entry.name) : entry.name;
38232
+ const entryAbs = path52.join(node.dir, entry.name);
38233
+ const entryRel = node.rel ? path52.posix.join(node.rel, entry.name) : entry.name;
38088
38234
  if (entryRel.split("/").includes("node_modules")) continue;
38089
38235
  if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
38090
38236
  pushEntry(entryAbs, entryRel, entry.isDirectory());
@@ -38097,13 +38243,13 @@ function listPathSuggestions(baseDir, pattern) {
38097
38243
  }
38098
38244
  }
38099
38245
  } else {
38100
- const entries = fs44.readdirSync(listDir, { withFileTypes: true });
38246
+ const entries = fs45.readdirSync(listDir, { withFileTypes: true });
38101
38247
  for (const entry of entries) {
38102
38248
  if (filterPrefix && !entry.name.startsWith(filterPrefix)) continue;
38103
38249
  if (isIgnoredName(entry.name)) continue;
38104
38250
  if (!entry.isDirectory() && isIgnoredFile(entry.name)) continue;
38105
- const entryAbs = path51.join(listDir, entry.name);
38106
- const label = relDir ? path51.posix.join(relDir, entry.name) : entry.name;
38251
+ const entryAbs = path52.join(listDir, entry.name);
38252
+ const label = relDir ? path52.posix.join(relDir, entry.name) : entry.name;
38107
38253
  pushEntry(entryAbs, label, entry.isDirectory());
38108
38254
  if (results.length >= MAX_RESULTS3) break;
38109
38255
  }
@@ -38304,9 +38450,9 @@ var SlashSubmenuInlineComponent = ({ menu }) => {
38304
38450
  var SlashSubmenuInline = memo15(SlashSubmenuInlineComponent);
38305
38451
 
38306
38452
  // src/app/ui/utils/clipboardImage.ts
38307
- import fs45 from "fs";
38453
+ import fs46 from "fs";
38308
38454
  import os32 from "os";
38309
- import path52 from "path";
38455
+ import path53 from "path";
38310
38456
  import { spawn as spawn5, execFile as execFileCb, execSync as execSync4 } from "child_process";
38311
38457
  import { promisify as promisify2 } from "util";
38312
38458
 
@@ -38435,8 +38581,8 @@ function commandOnPath(cmd) {
38435
38581
  function unixClipboardHelperDirs() {
38436
38582
  const h = os32.homedir();
38437
38583
  return [
38438
- path52.join(h, ".local", "bin"),
38439
- path52.join(h, "bin"),
38584
+ path53.join(h, ".local", "bin"),
38585
+ path53.join(h, "bin"),
38440
38586
  "/usr/bin",
38441
38587
  "/usr/local/bin",
38442
38588
  "/bin",
@@ -38454,16 +38600,16 @@ function resolveHelperBinary(cmd) {
38454
38600
  return cmd;
38455
38601
  }
38456
38602
  for (const dir of unixClipboardHelperDirs()) {
38457
- const full = path52.join(dir, cmd);
38603
+ const full = path53.join(dir, cmd);
38458
38604
  try {
38459
- fs45.accessSync(full, fs45.constants.X_OK);
38605
+ fs46.accessSync(full, fs46.constants.X_OK);
38460
38606
  return full;
38461
38607
  } catch {
38462
38608
  }
38463
38609
  }
38464
38610
  for (const dir of unixClipboardHelperDirs()) {
38465
- const full = path52.join(dir, cmd);
38466
- if (fs45.existsSync(full)) {
38611
+ const full = path53.join(dir, cmd);
38612
+ if (fs46.existsSync(full)) {
38467
38613
  return full;
38468
38614
  }
38469
38615
  }
@@ -38504,17 +38650,17 @@ function writeBufferIfImage(baseDir, buf) {
38504
38650
  if (!ext) {
38505
38651
  return null;
38506
38652
  }
38507
- const out = path52.join(
38653
+ const out = path53.join(
38508
38654
  baseDir,
38509
38655
  `clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
38510
38656
  );
38511
- fs45.writeFileSync(out, buf);
38657
+ fs46.writeFileSync(out, buf);
38512
38658
  return out;
38513
38659
  }
38514
38660
  function unlinkQuiet(p) {
38515
38661
  try {
38516
- if (fs45.existsSync(p)) {
38517
- fs45.unlinkSync(p);
38662
+ if (fs46.existsSync(p)) {
38663
+ fs46.unlinkSync(p);
38518
38664
  }
38519
38665
  } catch {
38520
38666
  }
@@ -38531,25 +38677,25 @@ async function tryDarwinClipboardy(baseDir) {
38531
38677
  return null;
38532
38678
  }
38533
38679
  for (const src of tmpPaths) {
38534
- if (!src || !fs45.existsSync(src)) {
38680
+ if (!src || !fs46.existsSync(src)) {
38535
38681
  continue;
38536
38682
  }
38537
38683
  let st;
38538
38684
  try {
38539
- st = fs45.statSync(src);
38685
+ st = fs46.statSync(src);
38540
38686
  } catch {
38541
38687
  continue;
38542
38688
  }
38543
38689
  if (st.size < 80 || st.size > CLIPBOARD_MAX_BYTES) {
38544
38690
  continue;
38545
38691
  }
38546
- const ext = path52.extname(src).toLowerCase();
38692
+ const ext = path53.extname(src).toLowerCase();
38547
38693
  const safeExt = ext && /^\.(png|jpe?g|gif|webp)$/i.test(ext) ? ext : ".png";
38548
- const out = path52.join(
38694
+ const out = path53.join(
38549
38695
  baseDir,
38550
38696
  `clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${safeExt}`
38551
38697
  );
38552
- fs45.copyFileSync(src, out);
38698
+ fs46.copyFileSync(src, out);
38553
38699
  for (const p of tmpPaths) {
38554
38700
  unlinkQuiet(p);
38555
38701
  }
@@ -38563,14 +38709,14 @@ async function tryDarwinClipboardy(baseDir) {
38563
38709
  return null;
38564
38710
  }
38565
38711
  async function tryWindowsPowerShell(outFile) {
38566
- const ps = process.env.SystemRoot != null ? path52.join(
38712
+ const ps = process.env.SystemRoot != null ? path53.join(
38567
38713
  process.env.SystemRoot,
38568
38714
  "System32",
38569
38715
  "WindowsPowerShell",
38570
38716
  "v1.0",
38571
38717
  "powershell.exe"
38572
38718
  ) : "powershell.exe";
38573
- if (!fs45.existsSync(ps)) {
38719
+ if (!fs46.existsSync(ps)) {
38574
38720
  return false;
38575
38721
  }
38576
38722
  const script = "$ErrorActionPreference='Stop';Add-Type -AssemblyName System.Windows.Forms;Add-Type -AssemblyName System.Drawing;$img=[System.Windows.Forms.Clipboard]::GetImage();if($null -eq $img){exit 2};$img.Save($env:BLUMA_CLIP_OUT,[System.Drawing.Imaging.ImageFormat]::Png);exit 0";
@@ -38592,7 +38738,7 @@ async function tryWindowsPowerShell(outFile) {
38592
38738
  return false;
38593
38739
  }
38594
38740
  try {
38595
- const st = fs45.statSync(outFile);
38741
+ const st = fs46.statSync(outFile);
38596
38742
  return st.size >= 80 && st.size <= CLIPBOARD_MAX_BYTES;
38597
38743
  } catch {
38598
38744
  return false;
@@ -38664,8 +38810,8 @@ function parseClipboardTextAsImagePath(raw) {
38664
38810
  s = s.slice(1, -1);
38665
38811
  }
38666
38812
  s = s.trim();
38667
- if (!CLIPBOARD_PATH_IMAGE_EXT.test(path52.extname(s))) return null;
38668
- const abs = path52.isAbsolute(s) ? path52.normalize(s) : path52.resolve(process.cwd(), s);
38813
+ if (!CLIPBOARD_PATH_IMAGE_EXT.test(path53.extname(s))) return null;
38814
+ const abs = path53.isAbsolute(s) ? path53.normalize(s) : path53.resolve(process.cwd(), s);
38669
38815
  return abs;
38670
38816
  }
38671
38817
  async function tryClipboardTextAsImageFile(baseDir) {
@@ -38679,19 +38825,19 @@ async function tryClipboardTextAsImageFile(baseDir) {
38679
38825
  const abs = parseClipboardTextAsImagePath(t);
38680
38826
  if (!abs) return null;
38681
38827
  try {
38682
- if (!fs45.existsSync(abs)) return null;
38683
- const st = fs45.statSync(abs);
38828
+ if (!fs46.existsSync(abs)) return null;
38829
+ const st = fs46.statSync(abs);
38684
38830
  if (!st.isFile() || st.size > CLIPBOARD_MAX_BYTES || st.size < 20) return null;
38685
38831
  } catch {
38686
38832
  return null;
38687
38833
  }
38688
- const ext = path52.extname(abs).toLowerCase();
38689
- const out = path52.join(
38834
+ const ext = path53.extname(abs).toLowerCase();
38835
+ const out = path53.join(
38690
38836
  baseDir,
38691
38837
  `clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
38692
38838
  );
38693
38839
  try {
38694
- fs45.copyFileSync(abs, out);
38840
+ fs46.copyFileSync(abs, out);
38695
38841
  return out;
38696
38842
  } catch {
38697
38843
  return null;
@@ -38701,7 +38847,7 @@ async function tryLinuxShellPipelineSave(baseDir) {
38701
38847
  if (process.platform !== "linux" && process.platform !== "freebsd") {
38702
38848
  return null;
38703
38849
  }
38704
- const outPath = path52.join(
38850
+ const outPath = path53.join(
38705
38851
  baseDir,
38706
38852
  `clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.tmp`
38707
38853
  );
@@ -38723,11 +38869,11 @@ printf '%s' "$OUT"
38723
38869
  maxBuffer: 4096
38724
38870
  });
38725
38871
  const written = String(stdout ?? "").trim();
38726
- if (written !== outPath || !fs45.existsSync(outPath)) {
38872
+ if (written !== outPath || !fs46.existsSync(outPath)) {
38727
38873
  unlinkQuiet(outPath);
38728
38874
  return null;
38729
38875
  }
38730
- const buf = fs45.readFileSync(outPath);
38876
+ const buf = fs46.readFileSync(outPath);
38731
38877
  unlinkQuiet(outPath);
38732
38878
  return writeBufferIfImage(baseDir, buf);
38733
38879
  } catch {
@@ -38748,8 +38894,8 @@ async function tryNativeClipboardImage() {
38748
38894
  }
38749
38895
  try {
38750
38896
  const result = readClipboardImageNative();
38751
- if (fs45.existsSync(result.path)) {
38752
- const st = fs45.statSync(result.path);
38897
+ if (fs46.existsSync(result.path)) {
38898
+ const st = fs46.statSync(result.path);
38753
38899
  if (st.size >= 80 && st.size <= CLIPBOARD_MAX_BYTES) {
38754
38900
  return result.path;
38755
38901
  }
@@ -38759,8 +38905,8 @@ async function tryNativeClipboardImage() {
38759
38905
  return null;
38760
38906
  }
38761
38907
  async function readClipboardImageToTempFile() {
38762
- const baseDir = path52.join(os32.homedir(), ".cache", "bluma", "clipboard");
38763
- fs45.mkdirSync(baseDir, { recursive: true });
38908
+ const baseDir = path53.join(os32.homedir(), ".cache", "bluma", "clipboard");
38909
+ fs46.mkdirSync(baseDir, { recursive: true });
38764
38910
  const nativeResult = await tryNativeClipboardImage();
38765
38911
  if (nativeResult) {
38766
38912
  return nativeResult;
@@ -38778,7 +38924,7 @@ async function readClipboardImageToTempFile() {
38778
38924
  }
38779
38925
  }
38780
38926
  if (process.platform === "win32") {
38781
- const outFile = path52.join(
38927
+ const outFile = path53.join(
38782
38928
  baseDir,
38783
38929
  `clip-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.png`
38784
38930
  );
@@ -38819,7 +38965,7 @@ function expandLargePastePlaceholder(value, pending) {
38819
38965
  }
38820
38966
 
38821
38967
  // src/app/ui/components/InputPrompt.tsx
38822
- import fs46 from "fs";
38968
+ import fs47 from "fs";
38823
38969
  import { Fragment as Fragment7, jsx as jsx79, jsxs as jsxs62 } from "react/jsx-runtime";
38824
38970
  var persistedInputState = { text: "", cursorPosition: 0 };
38825
38971
  var StaticCursor = () => /* @__PURE__ */ jsx79(Box_default, { flexDirection: "row", flexWrap: "nowrap", children: /* @__PURE__ */ jsx79(Text, { bold: true, color: BLUMA_TERMINAL.m3OnSurface, children: "\u2588 " }) });
@@ -38986,7 +39132,7 @@ var InputPrompt = memo16(({
38986
39132
  return;
38987
39133
  }
38988
39134
  if (routeText.startsWith("/")) {
38989
- const isFilePath = map.size > 0 && fs46.existsSync(routeText.split(/\s+/)[0]);
39135
+ const isFilePath = map.size > 0 && fs47.existsSync(routeText.split(/\s+/)[0]);
38990
39136
  if (isFilePath) {
38991
39137
  uiEventBus.emit("user_overlay", {
38992
39138
  kind: "message",
@@ -41154,8 +41300,8 @@ var renderSettingsEditUsage = () => {
41154
41300
 
41155
41301
  // src/app/agent/core/thread/thread_store.ts
41156
41302
  init_bluma_app_dir();
41157
- import path53 from "path";
41158
- import { promises as fs47 } from "fs";
41303
+ import path54 from "path";
41304
+ import { promises as fs48 } from "fs";
41159
41305
  import { randomUUID as randomUUID2 } from "crypto";
41160
41306
  var INDEX_VERSION = 1;
41161
41307
  var fileLocks2 = /* @__PURE__ */ new Map();
@@ -41180,9 +41326,9 @@ var ThreadStore = class {
41180
41326
  packageVersion;
41181
41327
  constructor() {
41182
41328
  const appDir = getPreferredAppDir();
41183
- this.threadsDir = path53.join(appDir, "threads");
41184
- this.archiveDir = path53.join(this.threadsDir, "archive");
41185
- this.indexPath = path53.join(this.threadsDir, "index.json");
41329
+ this.threadsDir = path54.join(appDir, "threads");
41330
+ this.archiveDir = path54.join(this.threadsDir, "archive");
41331
+ this.indexPath = path54.join(this.threadsDir, "index.json");
41186
41332
  this.packageVersion = process.env.npm_package_version || "0.0.0";
41187
41333
  }
41188
41334
  // ==================== Inicialização ====================
@@ -41190,10 +41336,10 @@ var ThreadStore = class {
41190
41336
  * Inicializa o diretório de threads
41191
41337
  */
41192
41338
  async initialize() {
41193
- await fs47.mkdir(this.threadsDir, { recursive: true });
41194
- await fs47.mkdir(this.archiveDir, { recursive: true });
41339
+ await fs48.mkdir(this.threadsDir, { recursive: true });
41340
+ await fs48.mkdir(this.archiveDir, { recursive: true });
41195
41341
  try {
41196
- await fs47.access(this.indexPath);
41342
+ await fs48.access(this.indexPath);
41197
41343
  } catch {
41198
41344
  await this.saveIndex({ version: INDEX_VERSION, threads: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() });
41199
41345
  }
@@ -41222,7 +41368,7 @@ var ThreadStore = class {
41222
41368
  async loadIndex() {
41223
41369
  return withFileLock2(this.indexPath, async () => {
41224
41370
  try {
41225
- const content = await fs47.readFile(this.indexPath, "utf-8");
41371
+ const content = await fs48.readFile(this.indexPath, "utf-8");
41226
41372
  return JSON.parse(content);
41227
41373
  } catch {
41228
41374
  return { version: INDEX_VERSION, threads: [], lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
@@ -41233,8 +41379,8 @@ var ThreadStore = class {
41233
41379
  return withFileLock2(this.indexPath, async () => {
41234
41380
  index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
41235
41381
  const tempPath = `${this.indexPath}.${Date.now()}.tmp`;
41236
- await fs47.writeFile(tempPath, JSON.stringify(index, null, 2), "utf-8");
41237
- await fs47.rename(tempPath, this.indexPath);
41382
+ await fs48.writeFile(tempPath, JSON.stringify(index, null, 2), "utf-8");
41383
+ await fs48.rename(tempPath, this.indexPath);
41238
41384
  });
41239
41385
  }
41240
41386
  // ==================== Git Info ====================
@@ -41304,7 +41450,7 @@ var ThreadStore = class {
41304
41450
  messages: params.initialMessages || []
41305
41451
  };
41306
41452
  const historyPath = this.buildDatedThreadHistoryPath(threadId);
41307
- await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
41453
+ await fs48.mkdir(path54.dirname(historyPath), { recursive: true });
41308
41454
  await this.saveHistoryAtPath(historyPath, history);
41309
41455
  const index = await this.loadIndex();
41310
41456
  index.threads.unshift({
@@ -41359,7 +41505,7 @@ var ThreadStore = class {
41359
41505
  compressedSliceCount: source.history.compressedSliceCount
41360
41506
  };
41361
41507
  const historyPath = this.buildDatedThreadHistoryPath(newThreadId);
41362
- await fs47.mkdir(path53.dirname(historyPath), { recursive: true });
41508
+ await fs48.mkdir(path54.dirname(historyPath), { recursive: true });
41363
41509
  await this.saveHistoryAtPath(historyPath, history);
41364
41510
  const index = await this.loadIndex();
41365
41511
  index.threads.unshift({
@@ -41432,9 +41578,9 @@ var ThreadStore = class {
41432
41578
  const entry = index.threads[entryIndex];
41433
41579
  if (entry.status === "archived") return true;
41434
41580
  const oldPath = entry.historyPath || this.getLegacyHistoryPath(threadId);
41435
- const newPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
41581
+ const newPath = path54.join(this.archiveDir, `${threadId}.jsonl`);
41436
41582
  try {
41437
- await fs47.rename(oldPath, newPath);
41583
+ await fs48.rename(oldPath, newPath);
41438
41584
  } catch (e) {
41439
41585
  if (e.code !== "ENOENT") throw e;
41440
41586
  }
@@ -41455,11 +41601,11 @@ var ThreadStore = class {
41455
41601
  if (entryIndex === -1) return false;
41456
41602
  const entry = index.threads[entryIndex];
41457
41603
  if (entry.status === "active") return true;
41458
- const oldPath = path53.join(this.archiveDir, `${threadId}.jsonl`);
41604
+ const oldPath = path54.join(this.archiveDir, `${threadId}.jsonl`);
41459
41605
  const newPath = this.buildDatedThreadHistoryPath(threadId);
41460
- await fs47.mkdir(path53.dirname(newPath), { recursive: true });
41606
+ await fs48.mkdir(path54.dirname(newPath), { recursive: true });
41461
41607
  try {
41462
- await fs47.rename(oldPath, newPath);
41608
+ await fs48.rename(oldPath, newPath);
41463
41609
  } catch (e) {
41464
41610
  if (e.code !== "ENOENT") throw e;
41465
41611
  }
@@ -41480,7 +41626,7 @@ var ThreadStore = class {
41480
41626
  if (entryIndex === -1) return false;
41481
41627
  const entry = index.threads[entryIndex];
41482
41628
  try {
41483
- await fs47.unlink(entry.historyPath);
41629
+ await fs48.unlink(entry.historyPath);
41484
41630
  } catch {
41485
41631
  }
41486
41632
  index.threads.splice(entryIndex, 1);
@@ -41490,28 +41636,28 @@ var ThreadStore = class {
41490
41636
  }
41491
41637
  // ==================== Histórico ====================
41492
41638
  getLegacyHistoryPath(threadId) {
41493
- return path53.join(this.threadsDir, `${threadId}.jsonl`);
41639
+ return path54.join(this.threadsDir, `${threadId}.jsonl`);
41494
41640
  }
41495
41641
  /** ~/.bluma/threads/YYYY/MM/DD/<threadId>.jsonl (data local de criação). */
41496
41642
  buildDatedThreadHistoryPath(threadId, at = /* @__PURE__ */ new Date()) {
41497
41643
  const y = String(at.getFullYear());
41498
41644
  const mo = String(at.getMonth() + 1).padStart(2, "0");
41499
41645
  const d = String(at.getDate()).padStart(2, "0");
41500
- return path53.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
41646
+ return path54.join(this.threadsDir, y, mo, d, `${threadId}.jsonl`);
41501
41647
  }
41502
41648
  async resolveHistoryPath(threadId) {
41503
41649
  const index = await this.loadIndex();
41504
41650
  const entry = index.threads.find((t) => t.threadId === threadId);
41505
41651
  if (entry?.historyPath) {
41506
41652
  try {
41507
- await fs47.access(entry.historyPath);
41653
+ await fs48.access(entry.historyPath);
41508
41654
  return entry.historyPath;
41509
41655
  } catch {
41510
41656
  }
41511
41657
  }
41512
41658
  const legacy = this.getLegacyHistoryPath(threadId);
41513
41659
  try {
41514
- await fs47.access(legacy);
41660
+ await fs48.access(legacy);
41515
41661
  return legacy;
41516
41662
  } catch {
41517
41663
  return entry?.historyPath ?? legacy;
@@ -41528,9 +41674,9 @@ var ThreadStore = class {
41528
41674
  for (const msg of history.messages) {
41529
41675
  lines.push(JSON.stringify({ type: "message", ...msg }));
41530
41676
  }
41531
- await fs47.mkdir(path53.dirname(historyPath), { recursive: true }).catch(() => {
41677
+ await fs48.mkdir(path54.dirname(historyPath), { recursive: true }).catch(() => {
41532
41678
  });
41533
- await fs47.writeFile(historyPath, lines.join("\n") + "\n", "utf-8");
41679
+ await fs48.writeFile(historyPath, lines.join("\n") + "\n", "utf-8");
41534
41680
  }
41535
41681
  /**
41536
41682
  * Guarda o histórico de uma thread
@@ -41552,7 +41698,7 @@ var ThreadStore = class {
41552
41698
  ].filter((p, i, arr) => Boolean(p) && arr.indexOf(p) === i);
41553
41699
  for (const historyPath of pathsToTry) {
41554
41700
  try {
41555
- const content = await fs47.readFile(historyPath, "utf-8");
41701
+ const content = await fs48.readFile(historyPath, "utf-8");
41556
41702
  const lines = content.split("\n").filter(Boolean);
41557
41703
  const history = {
41558
41704
  threadId,
@@ -41587,7 +41733,7 @@ var ThreadStore = class {
41587
41733
  const entry = index.threads.find((t) => t.threadId === threadId);
41588
41734
  if (!entry) throw new Error(`Thread not found: ${threadId}`);
41589
41735
  const lines = messages.map((msg) => JSON.stringify({ type: "message", ...msg }));
41590
- await fs47.appendFile(entry.historyPath, lines.join("\n") + "\n", "utf-8");
41736
+ await fs48.appendFile(entry.historyPath, lines.join("\n") + "\n", "utf-8");
41591
41737
  entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
41592
41738
  await this.saveIndex(index);
41593
41739
  }
@@ -44024,16 +44170,16 @@ import latestVersion from "latest-version";
44024
44170
  import semverGt from "semver/functions/gt.js";
44025
44171
  import semverValid from "semver/functions/valid.js";
44026
44172
  import { fileURLToPath as fileURLToPath7 } from "url";
44027
- import path55 from "path";
44028
- import fs49 from "fs";
44173
+ import path56 from "path";
44174
+ import fs50 from "fs";
44029
44175
  var BLUMA_PACKAGE_NAME = "@nomad-e/bluma-cli";
44030
44176
  function findBlumaPackageJson(startDir) {
44031
44177
  let dir = startDir;
44032
44178
  for (let i = 0; i < 12; i++) {
44033
- const candidate = path55.join(dir, "package.json");
44034
- if (fs49.existsSync(candidate)) {
44179
+ const candidate = path56.join(dir, "package.json");
44180
+ if (fs50.existsSync(candidate)) {
44035
44181
  try {
44036
- const raw = fs49.readFileSync(candidate, "utf8");
44182
+ const raw = fs50.readFileSync(candidate, "utf8");
44037
44183
  const parsed = JSON.parse(raw);
44038
44184
  if (parsed?.name === BLUMA_PACKAGE_NAME && parsed?.version) {
44039
44185
  return { name: parsed.name, version: String(parsed.version) };
@@ -44041,7 +44187,7 @@ function findBlumaPackageJson(startDir) {
44041
44187
  } catch {
44042
44188
  }
44043
44189
  }
44044
- const parent = path55.dirname(dir);
44190
+ const parent = path56.dirname(dir);
44045
44191
  if (parent === dir) break;
44046
44192
  dir = parent;
44047
44193
  }
@@ -44050,13 +44196,13 @@ function findBlumaPackageJson(startDir) {
44050
44196
  function resolveInstalledBlumaPackage() {
44051
44197
  const tried = /* @__PURE__ */ new Set();
44052
44198
  const tryFrom = (dir) => {
44053
- const abs = path55.resolve(dir);
44199
+ const abs = path56.resolve(dir);
44054
44200
  if (tried.has(abs)) return null;
44055
44201
  tried.add(abs);
44056
44202
  return findBlumaPackageJson(abs);
44057
44203
  };
44058
44204
  try {
44059
- const fromBundle = tryFrom(path55.dirname(fileURLToPath7(import.meta.url)));
44205
+ const fromBundle = tryFrom(path56.dirname(fileURLToPath7(import.meta.url)));
44060
44206
  if (fromBundle) return fromBundle;
44061
44207
  } catch {
44062
44208
  }
@@ -44064,12 +44210,12 @@ function resolveInstalledBlumaPackage() {
44064
44210
  if (argv1 && !argv1.startsWith("-")) {
44065
44211
  try {
44066
44212
  let resolved = argv1;
44067
- if (path55.isAbsolute(argv1) && fs49.existsSync(argv1)) {
44068
- resolved = fs49.realpathSync(argv1);
44213
+ if (path56.isAbsolute(argv1) && fs50.existsSync(argv1)) {
44214
+ resolved = fs50.realpathSync(argv1);
44069
44215
  } else {
44070
- resolved = path55.resolve(process.cwd(), argv1);
44216
+ resolved = path56.resolve(process.cwd(), argv1);
44071
44217
  }
44072
- const fromArgv = tryFrom(path55.dirname(resolved));
44218
+ const fromArgv = tryFrom(path56.dirname(resolved));
44073
44219
  if (fromArgv) return fromArgv;
44074
44220
  } catch {
44075
44221
  }
@@ -44888,16 +45034,16 @@ function usePlanMode() {
44888
45034
 
44889
45035
  // src/app/hooks/useAgentMode.ts
44890
45036
  import { useState as useState22, useEffect as useEffect21, useCallback as useCallback9 } from "react";
44891
- import * as fs50 from "fs";
44892
- import * as path56 from "path";
45037
+ import * as fs51 from "fs";
45038
+ import * as path57 from "path";
44893
45039
  import { homedir as homedir4 } from "os";
44894
- var SETTINGS_PATH = path56.join(homedir4(), ".bluma", "settings.json");
45040
+ var SETTINGS_PATH = path57.join(homedir4(), ".bluma", "settings.json");
44895
45041
  function readAgentModeFromFile() {
44896
45042
  try {
44897
- if (!fs50.existsSync(SETTINGS_PATH)) {
45043
+ if (!fs51.existsSync(SETTINGS_PATH)) {
44898
45044
  return "default";
44899
45045
  }
44900
- const content = fs50.readFileSync(SETTINGS_PATH, "utf-8");
45046
+ const content = fs51.readFileSync(SETTINGS_PATH, "utf-8");
44901
45047
  const settings = JSON.parse(content);
44902
45048
  return settings.agentMode || "default";
44903
45049
  } catch (error) {
@@ -44916,16 +45062,16 @@ function useAgentMode() {
44916
45062
  }, []);
44917
45063
  const updateAgentMode = useCallback9((mode) => {
44918
45064
  try {
44919
- if (!fs50.existsSync(SETTINGS_PATH)) {
44920
- fs50.mkdirSync(path56.dirname(SETTINGS_PATH), { recursive: true });
45065
+ if (!fs51.existsSync(SETTINGS_PATH)) {
45066
+ fs51.mkdirSync(path57.dirname(SETTINGS_PATH), { recursive: true });
44921
45067
  }
44922
45068
  let settings = {};
44923
- if (fs50.existsSync(SETTINGS_PATH)) {
44924
- const content = fs50.readFileSync(SETTINGS_PATH, "utf-8");
45069
+ if (fs51.existsSync(SETTINGS_PATH)) {
45070
+ const content = fs51.readFileSync(SETTINGS_PATH, "utf-8");
44925
45071
  settings = JSON.parse(content);
44926
45072
  }
44927
45073
  settings.agentMode = mode;
44928
- fs50.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2), "utf-8");
45074
+ fs51.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2), "utf-8");
44929
45075
  setAgentMode(mode);
44930
45076
  } catch (error) {
44931
45077
  console.error("Failed to update agent mode:", error);
@@ -46189,10 +46335,10 @@ import { memo as memo26, useCallback as useCallback11, useEffect as useEffect23,
46189
46335
 
46190
46336
  // src/app/agent/session_manager/session_resume_browser.ts
46191
46337
  init_bluma_app_dir();
46192
- import path57 from "path";
46193
- import { promises as fs51 } from "fs";
46338
+ import path58 from "path";
46339
+ import { promises as fs52 } from "fs";
46194
46340
  function getSessionsRoot() {
46195
- return path57.join(getPreferredAppDir(), "sessions");
46341
+ return path58.join(getPreferredAppDir(), "sessions");
46196
46342
  }
46197
46343
  function normalizeSessionsCwd(cwd2) {
46198
46344
  return cwd2.replace(/\\/g, "/").split("/").filter((p) => p && p !== "." && p !== "..").join("/");
@@ -46213,9 +46359,9 @@ async function sessionEntryFromFile(absPath, sessionId) {
46213
46359
  let preview = "(no messages)";
46214
46360
  let lastActivityMs = Date.now();
46215
46361
  try {
46216
- const st = await fs51.stat(absPath);
46362
+ const st = await fs52.stat(absPath);
46217
46363
  lastActivityMs = st.mtimeMs;
46218
- const raw = await fs51.readFile(absPath, "utf-8");
46364
+ const raw = await fs52.readFile(absPath, "utf-8");
46219
46365
  const data = JSON.parse(raw);
46220
46366
  preview = previewFromHistory(data.conversation_history);
46221
46367
  const iso = data.last_updated || data.created_at;
@@ -46243,15 +46389,15 @@ function compareDirNames(a, b) {
46243
46389
  async function listSessionBrowserEntries(cwdRel) {
46244
46390
  const cwd2 = normalizeSessionsCwd(cwdRel);
46245
46391
  const root = getSessionsRoot();
46246
- const absDir = cwd2 ? path57.join(root, ...cwd2.split("/")) : root;
46392
+ const absDir = cwd2 ? path58.join(root, ...cwd2.split("/")) : root;
46247
46393
  const out = [];
46248
46394
  if (cwd2) {
46249
46395
  out.push({ kind: "up", label: ".." });
46250
46396
  }
46251
46397
  let dirents;
46252
46398
  try {
46253
- await fs51.mkdir(absDir, { recursive: true });
46254
- dirents = await fs51.readdir(absDir, { withFileTypes: true });
46399
+ await fs52.mkdir(absDir, { recursive: true });
46400
+ dirents = await fs52.readdir(absDir, { withFileTypes: true });
46255
46401
  } catch {
46256
46402
  return out;
46257
46403
  }
@@ -46260,7 +46406,7 @@ async function listSessionBrowserEntries(cwdRel) {
46260
46406
  for (const e of dirents) {
46261
46407
  const name = String(e.name);
46262
46408
  if (name.startsWith(".")) continue;
46263
- const full = path57.join(absDir, name);
46409
+ const full = path58.join(absDir, name);
46264
46410
  if (e.isDirectory()) {
46265
46411
  dirNames.push(name);
46266
46412
  } else if (e.isFile() && name.endsWith(".json") && !name.includes(".tmp")) {
@@ -46270,7 +46416,7 @@ async function listSessionBrowserEntries(cwdRel) {
46270
46416
  dirNames.sort(compareDirNames);
46271
46417
  const sessions = [];
46272
46418
  for (const { name, full } of sessionFiles) {
46273
- const sessionId = path57.basename(name, ".json");
46419
+ const sessionId = path58.basename(name, ".json");
46274
46420
  sessions.push(await sessionEntryFromFile(full, sessionId));
46275
46421
  }
46276
46422
  sessions.sort((a, b) => {
@@ -46635,9 +46781,9 @@ async function runAgentMode() {
46635
46781
  try {
46636
46782
  if (inputFileIndex !== -1 && args[inputFileIndex + 1]) {
46637
46783
  const filePath = args[inputFileIndex + 1];
46638
- rawPayload = fs52.readFileSync(filePath, "utf-8");
46784
+ rawPayload = fs53.readFileSync(filePath, "utf-8");
46639
46785
  } else {
46640
- rawPayload = fs52.readFileSync(0, "utf-8");
46786
+ rawPayload = fs53.readFileSync(0, "utf-8");
46641
46787
  }
46642
46788
  } catch (err) {
46643
46789
  writeAgentEvent(registrySessionId, {
@@ -46689,6 +46835,12 @@ async function runAgentMode() {
46689
46835
  if (envelopeUserRequest.trim()) {
46690
46836
  process.env.BLUMA_USER_REQUEST = envelopeUserRequest.trim();
46691
46837
  }
46838
+ if (envelope.from_agent?.trim()) {
46839
+ process.env.BLUMA_FROM_AGENT = envelope.from_agent.trim();
46840
+ }
46841
+ if (envelope.action?.trim()) {
46842
+ process.env.BLUMA_ACTION = envelope.action.trim();
46843
+ }
46692
46844
  const eventBus = new EventEmitter7();
46693
46845
  const sessionId = registrySessionId || envelope.session_id || envelope.message_id || uuidv412();
46694
46846
  process.env.BLUMA_SESSION_ID = sessionId;
@@ -46878,9 +47030,9 @@ async function runAgentMode() {
46878
47030
  }
46879
47031
  function readCliPackageVersion() {
46880
47032
  try {
46881
- const base = path58.dirname(fileURLToPath8(import.meta.url));
46882
- const pkgPath = path58.join(base, "..", "package.json");
46883
- const j = JSON.parse(fs52.readFileSync(pkgPath, "utf8"));
47033
+ const base = path59.dirname(fileURLToPath8(import.meta.url));
47034
+ const pkgPath = path59.join(base, "..", "package.json");
47035
+ const j = JSON.parse(fs53.readFileSync(pkgPath, "utf8"));
46884
47036
  return String(j.version || "0.0.0");
46885
47037
  } catch {
46886
47038
  return "0.0.0";
@@ -47006,7 +47158,7 @@ function startBackgroundAgent() {
47006
47158
  process.exit(1);
47007
47159
  }
47008
47160
  const filePath = args[inputFileIndex + 1];
47009
- const rawPayload = fs52.readFileSync(filePath, "utf-8");
47161
+ const rawPayload = fs53.readFileSync(filePath, "utf-8");
47010
47162
  const envelope = JSON.parse(rawPayload);
47011
47163
  const sessionId = envelope.session_id || envelope.message_id || uuidv412();
47012
47164
  registerSession({