@nomad-e/bluma-cli 0.1.57 → 0.1.59

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.
@@ -3,7 +3,7 @@ Merge multiple PDF files into a single output PDF.
3
3
 
4
4
  Usage:
5
5
  python merge_pdfs.py --output merged.pdf file1.pdf file2.pdf file3.pdf
6
- python merge_pdfs.py --output ./artifacts/combined.pdf *.pdf
6
+ python merge_pdfs.py --output ./.bluma/artifacts/combined.pdf *.pdf
7
7
  """
8
8
  import argparse
9
9
  import sys
@@ -193,7 +193,7 @@ Example script header:
193
193
  {description of what this script does}
194
194
 
195
195
  Usage:
196
- python {script_name}.py --input data.csv --output ./artifacts/result.pdf
196
+ python {script_name}.py --input data.csv --output ./.bluma/artifacts/result.pdf
197
197
  """
198
198
  import argparse
199
199
  ```
package/dist/main.js CHANGED
@@ -113,6 +113,20 @@ function isPathInsideWorkspace(targetPath, policy = getSandboxPolicy()) {
113
113
  const relative = path6.relative(policy.workspaceRoot, resolved);
114
114
  return relative === "" || !relative.startsWith("..") && !path6.isAbsolute(relative);
115
115
  }
116
+ function redirectTopLevelArtifactsPath(resolvedAbsolute, workspaceRoot) {
117
+ const wr = path6.resolve(workspaceRoot);
118
+ const abs = path6.resolve(resolvedAbsolute);
119
+ const rel = path6.relative(wr, abs);
120
+ if (rel.startsWith("..") || path6.isAbsolute(rel)) {
121
+ return abs;
122
+ }
123
+ const segments = rel.split(path6.sep).filter((s) => s.length > 0);
124
+ if (segments.length === 0 || segments[0] !== "artifacts") {
125
+ return abs;
126
+ }
127
+ const tail = segments.slice(1);
128
+ return tail.length > 0 ? path6.join(wr, ".bluma", "artifacts", ...tail) : path6.join(wr, ".bluma", "artifacts");
129
+ }
116
130
  function resolveWorkspacePath(inputPath, policy = getSandboxPolicy()) {
117
131
  const candidate = path6.isAbsolute(inputPath) ? path6.resolve(inputPath) : path6.resolve(policy.workspaceRoot, inputPath);
118
132
  if (policy.isSandbox && !isPathInsideWorkspace(candidate, policy)) {
@@ -120,7 +134,7 @@ function resolveWorkspacePath(inputPath, policy = getSandboxPolicy()) {
120
134
  `Path "${inputPath}" escapes the sandbox workspace root ${policy.workspaceRoot}`
121
135
  );
122
136
  }
123
- return candidate;
137
+ return redirectTopLevelArtifactsPath(candidate, policy.workspaceRoot);
124
138
  }
125
139
  function resolveCommandCwd(cwd, policy = getSandboxPolicy()) {
126
140
  const base = cwd ? path6.resolve(cwd) : policy.workspaceRoot;
@@ -8519,10 +8533,16 @@ var AdvancedFeedbackSystem = class {
8519
8533
  score: penalty,
8520
8534
  message: "You are attempting a direct message without a tool_call. All replies must contain tool_call.",
8521
8535
  correction: `
8522
- ## PROTOCOL VIOLATION \u2014 SERIOUS
8523
- You are sending a direct response without tool_call, which is strictly prohibited.
8524
- PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
8525
- You MUST always use tool_call without exception.
8536
+ ## PROTOCOL VIOLATION \u2014 STOP WRITING PLAIN ASSISTANT TEXT
8537
+
8538
+ You streamed or returned **user-visible markdown as assistant content** instead of using the **\`message\` tool**. That is prohibited and **does not end the turn** \u2014 the runtime will loop until timeout.
8539
+
8540
+ Do this **immediately** in your next step (single tool call, no prose outside tools):
8541
+
8542
+ - Call **\`message\`** with **\`message_type\`: \`"result"\`**, put the user-facing summary in **\`content\`**, and put deliverable paths in **\`attachments\`** (absolute paths).
8543
+
8544
+ Do **not** repeat the same summary as plain assistant text again.
8545
+ PENALTY APPLIED: ${penalty.toFixed(1)} points deducted.
8526
8546
  `.trim()
8527
8547
  };
8528
8548
  }
@@ -9945,6 +9965,7 @@ The \\\`message\\\` tool has TWO types \u2014 use them CORRECTLY:
9945
9965
  - **Use when**: Task is complete, artifacts ready for delivery
9946
9966
  - **Use ONCE per turn** \u2014 only at the very end
9947
9967
  - **Ends the turn** \u2014 agent waits for next input
9968
+ - **CRITICAL:** Plain assistant markdown (streaming or not) **does not** end the worker or close the HTTP job \u2014 only a \\\`message\\\` tool call with \\\`message_type: "result"\\\` does. If you only write text in chat, the process loops until **timeout** (e.g. 300s).
9948
9969
 
9949
9970
  #### \u274C WRONG: Using "info" to ask questions
9950
9971
  \\\`\\\`\\\`typescript
@@ -10063,6 +10084,7 @@ You (Bluma):
10063
10084
 
10064
10085
  - **Sandbox is safe** - You can't break the host system
10065
10086
  - **But workspace matters** - Don't pollute /workspace with junk files
10087
+ - **Deliverables path** - Never use a top-level \`./artifacts/\` folder in the job root; use \`./.bluma/artifacts/\` (or the \`artifacts_dir\` from \`task_boundary\`). Shell redirects must use that path \u2014 \`file_write\` remaps \`artifacts/...\` to \`.bluma/artifacts/...\` automatically.
10066
10088
  - **Clean up after yourself** - Remove temporary files when done
10067
10089
  - **Respect session boundaries** - Stay in your session workspace
10068
10090
 
@@ -10288,6 +10310,10 @@ Auto-generated map (may be stale after pull/install). Confirm with tools before
10288
10310
  <<<BLUMA_WORKSPACE_SNAPSHOT_BODY>>>
10289
10311
  </workspace_snapshot>
10290
10312
 
10313
+ <deliverables>
10314
+ **Local and sandbox:** generated artifacts (reports, PDFs, exports, plans you attach) must live under \`<workdir>/.bluma/\` \u2014 use \`.bluma/artifacts/\` (or the \`artifacts_dir\` path returned by \`task_boundary\` after starting a task). Do **not** create a top-level \`./artifacts/\` folder in the project root. \`file_write\` / \`edit_tool\` / \`read_file_lines\` automatically remap \`artifacts/...\` \u2192 \`.bluma/artifacts/...\`. For \`shell_command\` redirects (\`>\` / \`>>\`), target \`.bluma/artifacts/...\` explicitly.
10315
+ </deliverables>
10316
+
10291
10317
  <coding_memory>
10292
10318
  Persistent store (~/.bluma/coding_memory.json). Do not invent entries: \`list\` / \`search\` if unsure. \`<coding_memory_snapshot>\` is bootstrap only \u2014 after add/update/remove, list or search again. Operations: add | list | search | update (id) | remove (id), one mutating call at a time.
10293
10319
  </coding_memory>
@@ -10313,7 +10339,7 @@ Output is truncated (~30KB / ~200 lines); use head/tail or write to a file. Use
10313
10339
  The user **only** sees chat content you send through the \`message\` tool (\`content\` as Markdown). Bare assistant text is **not** a substitute \u2014 **you should use \`message\` liberally**.
10314
10340
 
10315
10341
  **Types**
10316
- - \`message_type: "result"\` \u2014 **ends the turn**: final answer, deliverable, or a **question** that needs a user reply; then the agent waits for the user.
10342
+ - \`message_type: "result"\` \u2014 **ends the turn**: final answer, deliverable, or a **question** that needs a user reply; then the agent waits for the user. **Sandbox/worker:** only this stops the job; writing markdown as normal assistant output does **not** finish the task and can cause a **timeout loop**.
10317
10343
  - \`message_type: "info"\` \u2014 **non-terminal**: shown in chat, does **not** end the turn. **Expected behavior:** call \`info\` **multiple times** in a single turn whenever there is something worth saying (even briefly). Under-using \`info\` is a **mistake** in this product.
10318
10344
 
10319
10345
  **\u26A0\uFE0F CRITICAL: "info" is for INFORMATION ONLY \u2014 NEVER for asking questions**
@@ -11449,6 +11475,8 @@ var BluMaAgent = class {
11449
11475
  factorRouterTurnClosed = false;
11450
11476
  /** Passos seguidos sem tool_calls nem texto visível (só raciocínio) — evita loop lento no mesmo turno. */
11451
11477
  emptyAssistantReplySteps = 0;
11478
+ /** Passos seguidos com texto do assistente sem tool_calls (violação de protocolo) — evita loop até timeout do job. */
11479
+ directTextProtocolSteps = 0;
11452
11480
  constructor(sessionId, eventBus, llm, mcpClient, feedbackSystem) {
11453
11481
  this.sessionId = sessionId;
11454
11482
  this.eventBus = eventBus;
@@ -11592,6 +11620,7 @@ var BluMaAgent = class {
11592
11620
  const userContent = buildUserMessageContent(inputText, process.cwd());
11593
11621
  this.history.push({ role: "user", content: userContent });
11594
11622
  this.emptyAssistantReplySteps = 0;
11623
+ this.directTextProtocolSteps = 0;
11595
11624
  this.eventBus.emit(
11596
11625
  "backend_message",
11597
11626
  buildTurnStartBackendMessage({
@@ -12149,6 +12178,7 @@ ${editData.error.display}`;
12149
12178
  this.history.push(normalizedMessage);
12150
12179
  if (normalizedMessage.tool_calls && normalizedMessage.tool_calls.length > 0) {
12151
12180
  this.emptyAssistantReplySteps = 0;
12181
+ this.directTextProtocolSteps = 0;
12152
12182
  const validToolCalls = normalizedMessage.tool_calls.filter(
12153
12183
  (call) => ToolCallNormalizer.isValidToolCall(call)
12154
12184
  );
@@ -12188,9 +12218,20 @@ ${editData.error.display}`;
12188
12218
  }
12189
12219
  } else if (trimmedText) {
12190
12220
  this.emptyAssistantReplySteps = 0;
12221
+ this.directTextProtocolSteps += 1;
12222
+ const MAX_DIRECT_TEXT_PROTOCOL = 3;
12191
12223
  if (!hasEmittedStart) {
12192
12224
  this.eventBus.emit("backend_message", { type: "assistant_message", content: accumulatedContent });
12193
12225
  }
12226
+ if (this.directTextProtocolSteps >= MAX_DIRECT_TEXT_PROTOCOL) {
12227
+ this.eventBus.emit("backend_message", {
12228
+ type: "error",
12229
+ message: 'Agent kept answering with plain assistant text instead of the `message` tool with message_type "result". Turn forcibly closed to avoid job timeout; fix prompts or model routing.'
12230
+ });
12231
+ await this.notifyFactorTurnEndIfNeeded("protocol_direct_text_exhausted");
12232
+ this.emitTurnCompleted();
12233
+ return;
12234
+ }
12194
12235
  const feedback = this.feedbackSystem.generateFeedback({
12195
12236
  event: "protocol_violation_direct_text",
12196
12237
  details: { violationContent: accumulatedContent }
@@ -12226,6 +12267,7 @@ ${editData.error.display}`;
12226
12267
  this.history.push(message2);
12227
12268
  if (message2.tool_calls && message2.tool_calls.length > 0) {
12228
12269
  this.emptyAssistantReplySteps = 0;
12270
+ this.directTextProtocolSteps = 0;
12229
12271
  const validToolCalls = message2.tool_calls.filter(
12230
12272
  (call) => ToolCallNormalizer.isValidToolCall(call)
12231
12273
  );
@@ -12265,7 +12307,18 @@ ${editData.error.display}`;
12265
12307
  }
12266
12308
  } else if (typeof message2.content === "string" && message2.content.trim()) {
12267
12309
  this.emptyAssistantReplySteps = 0;
12310
+ this.directTextProtocolSteps += 1;
12311
+ const MAX_DIRECT_TEXT_PROTOCOL = 3;
12268
12312
  this.eventBus.emit("backend_message", { type: "assistant_message", content: message2.content });
12313
+ if (this.directTextProtocolSteps >= MAX_DIRECT_TEXT_PROTOCOL) {
12314
+ this.eventBus.emit("backend_message", {
12315
+ type: "error",
12316
+ message: 'Agent kept answering with plain assistant text instead of the `message` tool with message_type "result". Turn forcibly closed to avoid job timeout.'
12317
+ });
12318
+ await this.notifyFactorTurnEndIfNeeded("protocol_direct_text_exhausted");
12319
+ this.emitTurnCompleted();
12320
+ return;
12321
+ }
12269
12322
  const feedback = this.feedbackSystem.generateFeedback({
12270
12323
  event: "protocol_violation_direct_text",
12271
12324
  details: { violationContent: message2.content }
@@ -15990,12 +16043,11 @@ Run: npm i -g ${BLUMA_PACKAGE_NAME} to update.`;
15990
16043
  }
15991
16044
  }
15992
16045
 
15993
- // src/app/ui/components/StartupUpdateGate.tsx
16046
+ // src/app/ui/components/UpdateNotice.tsx
15994
16047
  import { Box as Box17, Text as Text16 } from "ink";
15995
-
15996
- // src/app/ui/utils/update_message.ts
16048
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
15997
16049
  function parseUpdateMessage(msg) {
15998
- const lines = String(msg ?? "").split(/\r?\n/).map((l) => l.trim());
16050
+ const lines = msg.split(/\r?\n/).map((l) => l.trim());
15999
16051
  const first = lines[0] || "";
16000
16052
  const hintLine = lines.slice(1).join(" ") || "";
16001
16053
  const nameMatch = first.match(/Update available for\s+([^!]+)!/i);
@@ -16007,38 +16059,19 @@ function parseUpdateMessage(msg) {
16007
16059
  hint: hintLine || void 0
16008
16060
  };
16009
16061
  }
16010
- function extractInstallCommand(hint) {
16011
- if (!hint) return null;
16012
- const match = hint.match(/Run:\s*(.+?)(?:\s+to update\.?)?$/i);
16013
- return match?.[1]?.trim() || null;
16014
- }
16015
-
16016
- // src/app/ui/components/StartupUpdateGate.tsx
16017
- import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
16018
- var StartupUpdateGate = ({
16019
- message: message2
16020
- }) => {
16062
+ var UpdateNotice = ({ message: message2 }) => {
16021
16063
  const { name, current, latest: latest2, hint } = parseUpdateMessage(message2);
16022
- const command = extractInstallCommand(hint);
16023
- return /* @__PURE__ */ jsx18(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
16024
- /* @__PURE__ */ jsxs16(Box17, { marginBottom: 1, children: [
16025
- /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.orange, children: "\u273B " }),
16026
- /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.blue, bold: true, children: "Blu" }),
16027
- /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.magenta, bold: true, children: "Ma" }),
16028
- /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: " update gate" })
16029
- ] }),
16030
- /* @__PURE__ */ jsx18(Text16, { bold: true, color: BLUMA_TERMINAL.claude, children: name || "New BluMa version available" }),
16031
- current && latest2 ? /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
16064
+ return /* @__PURE__ */ jsx18(ChatBlock, { marginBottom: 1, children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", paddingLeft: 2, children: [
16065
+ name && current && latest2 ? /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.claude, bold: true, children: name }) : null,
16066
+ name && current && latest2 ? /* @__PURE__ */ jsxs16(Text16, { dimColor: true, children: [
16032
16067
  current,
16033
16068
  " \u2192 ",
16034
16069
  latest2
16035
- ] }) : null,
16036
- /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true, wrap: "wrap", children: command ? `Run this command to update:
16037
- ${command}` : hint || "An update is available for BluMa CLI." }) }),
16038
- /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { color: BLUMA_TERMINAL.warn, bold: true, children: "Press Enter to continue" }) })
16070
+ ] }) : /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: message2 }),
16071
+ hint ? /* @__PURE__ */ jsx18(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: hint }) }) : null
16039
16072
  ] }) });
16040
16073
  };
16041
- var StartupUpdateGate_default = StartupUpdateGate;
16074
+ var UpdateNotice_default = UpdateNotice;
16042
16075
 
16043
16076
  // src/app/ui/components/ErrorMessage.tsx
16044
16077
  import { Box as Box18, Text as Text17 } from "ink";
@@ -16630,10 +16663,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
16630
16663
  "Initializing agent..."
16631
16664
  );
16632
16665
  const [toolsCount, setToolsCount] = useState11(null);
16633
- const [startupPhase, setStartupPhase] = useState11("checking");
16634
- const [startupUpdateMessage, setStartupUpdateMessage] = useState11(
16635
- null
16636
- );
16637
16666
  const [mcpStatus, setMcpStatus] = useState11(
16638
16667
  "connecting"
16639
16668
  );
@@ -16647,12 +16676,23 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
16647
16676
  const [pendingAskUserQuestions, setPendingAskUserQuestions] = useState11(null);
16648
16677
  const [showWorkers, setShowWorkers] = useState11(false);
16649
16678
  const [zoomedWorkerSession, setZoomedWorkerSession] = useState11(null);
16679
+ useInput6((input, key) => {
16680
+ if (key.ctrl && key.shift && input.toLowerCase() === "w") {
16681
+ setShowWorkers((prev) => !prev);
16682
+ }
16683
+ if (key.escape && showWorkers) {
16684
+ if (zoomedWorkerSession) {
16685
+ setZoomedWorkerSession(null);
16686
+ } else {
16687
+ setShowWorkers(false);
16688
+ }
16689
+ }
16690
+ });
16650
16691
  const [isInitAgentActive, setIsInitAgentActive] = useState11(false);
16651
16692
  const [liveToolName, setLiveToolName] = useState11(null);
16652
16693
  const [liveToolArgs, setLiveToolArgs] = useState11(void 0);
16653
16694
  const [isReasoning, setIsReasoning] = useState11(false);
16654
16695
  const alwaysAcceptList = useRef6([]);
16655
- const agentInitializationStartedRef = useRef6(false);
16656
16696
  const workdir = process.cwd();
16657
16697
  const turnStartedAtRef = useRef6(null);
16658
16698
  const [processingStartMs, setProcessingStartMs] = useState11(null);
@@ -16686,33 +16726,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
16686
16726
  ];
16687
16727
  });
16688
16728
  }, []);
16689
- const startAgentInitialization = useCallback4(async () => {
16690
- if (agentInitializationStartedRef.current) return;
16691
- agentInitializationStartedRef.current = true;
16692
- try {
16693
- agentInstance.current = new Agent(sessionId, eventBus);
16694
- await agentInstance.current.initialize();
16695
- appendHookEvent({
16696
- type: "session:init",
16697
- sessionId,
16698
- summary: "agent initialized"
16699
- });
16700
- eventBus.emit("backend_message", {
16701
- type: "status",
16702
- status: "mcp_connected",
16703
- tools: agentInstance.current.getAvailableTools().length
16704
- });
16705
- setStartupPhase("ready");
16706
- } catch (error) {
16707
- const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
16708
- setStartupPhase("failed");
16709
- setStatusMessage(errorMessage);
16710
- eventBus.emit("backend_message", {
16711
- type: "error",
16712
- message: errorMessage
16713
- });
16714
- }
16715
- }, [eventBus, sessionId]);
16716
16729
  useEffect11(() => {
16717
16730
  expandPreviewHotkeyBus.on("expand", appendExpandPreviewToHistory);
16718
16731
  return () => {
@@ -16720,24 +16733,22 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
16720
16733
  };
16721
16734
  }, [appendExpandPreviewToHistory]);
16722
16735
  useEffect11(() => {
16723
- if (process.env.CI || blumaUpdateRegistryCheckStarted) {
16724
- setStartupPhase("starting-agent");
16725
- void startAgentInitialization();
16726
- return;
16727
- }
16736
+ if (process.env.CI || blumaUpdateRegistryCheckStarted) return;
16728
16737
  blumaUpdateRegistryCheckStarted = true;
16729
- setStatusMessage("Checking for updates...");
16730
16738
  void checkForUpdates().then((msg) => {
16731
- if (!msg) {
16732
- setStartupPhase("starting-agent");
16733
- void startAgentInitialization();
16734
- return;
16735
- }
16736
- setStartupUpdateMessage(msg);
16737
- setStartupPhase("update-available");
16738
- setStatusMessage("Update available");
16739
+ if (!msg) return;
16740
+ setHistory((prev) => {
16741
+ const nextId2 = prev.length === 0 ? 1 : Math.max(...prev.map((h) => h.id), HEADER_PANEL_HISTORY_ID) + 1;
16742
+ return [
16743
+ ...prev,
16744
+ {
16745
+ id: nextId2,
16746
+ component: /* @__PURE__ */ jsx27(UpdateNotice_default, { message: msg })
16747
+ }
16748
+ ];
16749
+ });
16739
16750
  });
16740
- }, [startAgentInitialization]);
16751
+ }, []);
16741
16752
  useEffect11(() => {
16742
16753
  setHistory((prev) => {
16743
16754
  const tail = prev.filter((h) => h.id !== HEADER_PANEL_HISTORY_ID);
@@ -16767,28 +16778,6 @@ var AppComponent = ({ eventBus, sessionId, cliVersion }) => {
16767
16778
  ];
16768
16779
  });
16769
16780
  }, [isProcessing, eventBus]);
16770
- const continuePastUpdateGate = useCallback4(() => {
16771
- if (startupPhase !== "update-available") return;
16772
- setStartupPhase("starting-agent");
16773
- setStatusMessage("Connecting to MCP...");
16774
- void startAgentInitialization();
16775
- }, [startupPhase, startAgentInitialization]);
16776
- useInput6((input, key) => {
16777
- if (startupPhase === "update-available" && (key.return || input === "\n" || input === "\r")) {
16778
- continuePastUpdateGate();
16779
- return;
16780
- }
16781
- if (key.ctrl && key.shift && input.toLowerCase() === "w") {
16782
- setShowWorkers((prev) => !prev);
16783
- }
16784
- if (key.escape && showWorkers) {
16785
- if (zoomedWorkerSession) {
16786
- setZoomedWorkerSession(null);
16787
- } else {
16788
- setShowWorkers(false);
16789
- }
16790
- }
16791
- });
16792
16781
  const handleSubmit = useCallback4(
16793
16782
  (text) => {
16794
16783
  if (!text || !agentInstance.current) return;
@@ -17044,6 +17033,28 @@ Please use command_status to check the result and report back to the user.`;
17044
17033
  }
17045
17034
  }, [history.length]);
17046
17035
  useEffect11(() => {
17036
+ const initializeAgent = async () => {
17037
+ try {
17038
+ agentInstance.current = new Agent(sessionId, eventBus);
17039
+ await agentInstance.current.initialize();
17040
+ appendHookEvent({
17041
+ type: "session:init",
17042
+ sessionId,
17043
+ summary: "agent initialized"
17044
+ });
17045
+ eventBus.emit("backend_message", {
17046
+ type: "status",
17047
+ status: "mcp_connected",
17048
+ tools: agentInstance.current.getAvailableTools().length
17049
+ });
17050
+ } catch (error) {
17051
+ const errorMessage = error instanceof Error ? error.message : "Unknown error during Agent initialization.";
17052
+ eventBus.emit("backend_message", {
17053
+ type: "error",
17054
+ message: errorMessage
17055
+ });
17056
+ }
17057
+ };
17047
17058
  const handleBackendMessage = (parsed) => {
17048
17059
  try {
17049
17060
  const appendTurnDurationIfAny = () => {
@@ -17298,6 +17309,7 @@ Please use command_status to check the result and report back to the user.`;
17298
17309
  uiEventBus.on("user_overlay", handleUiOverlay);
17299
17310
  uiEventBus.on("input_notice", handleInputNotice);
17300
17311
  eventBus.on("backend_message", handleBackendMessage);
17312
+ initializeAgent();
17301
17313
  return () => {
17302
17314
  uiEventBus.off("user_overlay", handleUiOverlay);
17303
17315
  uiEventBus.off("input_notice", handleInputNotice);
@@ -17305,27 +17317,6 @@ Please use command_status to check the result and report back to the user.`;
17305
17317
  };
17306
17318
  }, [eventBus, sessionId, handleConfirmation]);
17307
17319
  const renderInteractiveComponent = () => {
17308
- if (startupPhase === "checking") {
17309
- return /* @__PURE__ */ jsx27(
17310
- SessionInfoConnectingMCP_default,
17311
- {
17312
- workdir,
17313
- statusMessage: statusMessage || "Checking for updates..."
17314
- }
17315
- );
17316
- }
17317
- if (startupPhase === "update-available" && startupUpdateMessage) {
17318
- return /* @__PURE__ */ jsx27(StartupUpdateGate_default, { message: startupUpdateMessage });
17319
- }
17320
- if (startupPhase === "failed") {
17321
- return /* @__PURE__ */ jsx27(Box26, { flexDirection: "column", children: /* @__PURE__ */ jsx27(
17322
- ErrorMessage_default,
17323
- {
17324
- message: statusMessage || "Startup failed",
17325
- hint: "Fix the error above and restart BluMa."
17326
- }
17327
- ) });
17328
- }
17329
17320
  if (mcpStatus !== "connected") {
17330
17321
  return /* @__PURE__ */ jsx27(
17331
17322
  SessionInfoConnectingMCP_default,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomad-e/bluma-cli",
3
- "version": "0.1.57",
3
+ "version": "0.1.59",
4
4
  "description": "BluMa independent agent for automation and advanced software engineering.",
5
5
  "author": "Alex Fonseca",
6
6
  "license": "Apache-2.0",