@nomad-e/bluma-cli 0.0.104 → 0.0.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # BluMa CLI
1
+ # BluMa — Base Language Unit · Model Agent
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/bluma.svg?style=flat-square)](https://www.npmjs.com/package/bluma)
4
4
  [![License: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat-square)](LICENSE)
@@ -8,16 +8,18 @@
8
8
  <img src="https://pharmaseedevsa.blob.core.windows.net/pharmassee-dev-storage/bluma.png" alt="Screenshot BluMa CLI" width="1000"/>
9
9
  </p>
10
10
 
11
- BluMa CLI is an independent agent for automation and advanced software engineering. The project is a conversational assistant that interacts via terminal (CLI), built with React/Ink, supporting smart agents (LLM, OpenAI Azure), tool execution, persistent history, session management, and extensibility through external plugins/tools.
11
+ BluMa is a CLI-based model agent responsible for language-level code generation, refactoring and semantic transformations in the Factor AI stack. The project is a conversational assistant that interacts via terminal (CLI), built with React/Ink, supporting smart agents (LLM via OpenRouter), tool execution, persistent history, session management, and extensibility through external plugins/tools.
12
12
 
13
13
  ---
14
14
 
15
15
  ## Table of Contents
16
16
  - [Overview](#overview)
17
+ - [Why BluMa?](#why-bluma)
17
18
  - [Key Features](#key-features)
18
19
  - [Requirements](#requirements)
19
- - [Architecture Diagram](#-architecture-diagram)
20
+ - [Quick Start](#quick-start)
20
21
  - [Installation](#installation)
22
+ - [Screenshots](#screenshots)
21
23
  - [Usage](#usage)
22
24
  - [Examples](#-usage-examples)
23
25
  - [Configuration and Environment Variables](#configuration-and-environment-variables)
@@ -33,14 +35,27 @@ BluMa CLI is an independent agent for automation and advanced software engineeri
33
35
  ---
34
36
 
35
37
  ## <a name="overview"></a>Overview
36
- BluMa CLI is a modular conversational agent and task automation framework focused on advanced software engineering workflows. It runs entirely in the terminal using React (via Ink) for a rich interactive UI, and is architected around a **UI layer** (`main.ts` + `App.tsx`) and an **agent layer** (`Agent` orchestrator + `BluMaAgent` core). It enables LLM-powered automation, documentation, refactoring, running complex development tasks, and integrating with both native and external tools. The system features persistent sessions, contextual reasoning, smart feedback, and an interactive confirmation system for controlled execution.
38
+ BluMa is a CLI-based model agent responsible for language-level code generation, refactoring and semantic transformations in the Factor AI stack. It is a modular conversational agent and task automation framework focused on advanced software engineering workflows. It runs entirely in the terminal using React (via Ink) for a rich interactive UI, and is architected around a **UI layer** (`main.ts` + `App.tsx`) and an **agent layer** (`Agent` orchestrator + `BluMaAgent` core). It enables LLM-powered automation, documentation, refactoring, running complex development tasks, and integrating with both native and external tools. The system features persistent sessions, contextual reasoning, smart feedback, and an interactive confirmation system for controlled execution.
39
+
40
+ ---
41
+
42
+ ## Why BluMa?
43
+ BluMa stands out as the premier CLI-based model agent for software engineering:
44
+
45
+ - **Language-Level Expertise:** Specializes in code generation, refactoring, and semantic transformations, making it ideal for Factor AI stack development.
46
+ - **Conversational Automation:** Interact naturally with an AI that understands context, history, and your project's needs.
47
+ - **Secure & Controlled:** Built-in confirmations and whitelists ensure safe execution of powerful tools.
48
+ - **Extensible & Modular:** Easily add tools and plugins to adapt to your workflow.
49
+ - **Real-Time Collaboration:** Live overlays allow pair-programming style guidance during processing.
50
+
51
+ Choose BluMa for intelligent, efficient, and collaborative software engineering automation.
37
52
 
38
53
  ---
39
54
 
40
55
  ## <a name="key-features"></a>Key Features
41
56
  - **Rich CLI interface** using React/Ink 5, with interactive prompts and custom components.
42
57
  - **Session management:** automatic persistence of conversation and tool history via files.
43
- - **Central agent (LLM):** orchestrated by Azure OpenAI (or compatible), enabling natural language-driven automation.
58
+ - **Central agent (LLM):** orchestrated by OpenRouter, enabling natural language-driven automation.
44
59
  - **Tool invocation:** native and via MCP SDK for running commands, code manipulation, file management, and more.
45
60
  - **Dynamic prompts:** builds live conversational context, behavioral rules, and technical history.
46
61
  - **Smart feedback component** with technical suggestions and checks.
@@ -52,7 +67,7 @@ BluMa CLI is a modular conversational agent and task automation framework focuse
52
67
  ## <a name="requirements"></a>Requirements
53
68
  - Node.js >= 18
54
69
  - npm >= 9
55
- - Account (with key) for Azure OpenAI (or equivalent variables for OpenAI-compatible endpoints)
70
+ - OpenRouter API key (get one at [openrouter.ai](https://openrouter.ai))
56
71
 
57
72
  ---
58
73
 
@@ -82,27 +97,17 @@ If you get permission errors, EXAMPLES:
82
97
  > Only use sudo to install, never to run the CLI.
83
98
 
84
99
  ### Setting Up Environment Variables
85
- For BluMa CLI to operate with OpenAI/Azure, GitHub, and Notion, set the following environment variables globally in your system.
100
+ For BluMa CLI to operate, set the following environment variable globally in your system.
86
101
 
87
102
  **Required:**
88
- - `AZURE_OPENAI_ENDPOINT`
89
- - `AZURE_OPENAI_API_KEY`
90
- - `AZURE_OPENAI_API_VERSION`
91
- - `AZURE_OPENAI_DEPLOYMENT`
92
- - `GITHUB_PERSONAL_ACCESS_TOKEN` (if you'll use GitHub)
93
- - `NOTION_API_TOKEN` (if you'll use Notion)
103
+ - `OPENROUTER_API_KEY` (get your key at [openrouter.ai](https://openrouter.ai))
94
104
 
95
105
  #### How to set environment variables globally:
96
106
 
97
107
  **Linux/macOS:**
98
108
  Add to your `~/.bashrc`, `~/.zshrc`, or equivalent:
99
109
  ```sh
100
- export AZURE_OPENAI_ENDPOINT="https://..."
101
- export AZURE_OPENAI_API_KEY="your_key"
102
- export AZURE_OPENAI_API_VERSION="2025-01-01-preview"
103
- export AZURE_OPENAI_DEPLOYMENT="bluma-gpt"
104
- export GITHUB_PERSONAL_ACCESS_TOKEN="..."
105
- export NOTION_API_TOKEN="..."
110
+ export OPENROUTER_API_KEY="your_openrouter_key"
106
111
  ```
107
112
  Then run:
108
113
  ```sh
@@ -111,23 +116,13 @@ source ~/.bashrc # or whichever file you edited
111
116
 
112
117
  **Windows (CMD):**
113
118
  ```cmd
114
- setx AZURE_OPENAI_ENDPOINT "https://..."
115
- setx AZURE_OPENAI_API_KEY "your_key"
116
- setx AZURE_OPENAI_API_VERSION "2025-01-01-preview"
117
- setx AZURE_OPENAI_DEPLOYMENT "bluma-gpt"
118
- setx GITHUB_PERSONAL_ACCESS_TOKEN "..."
119
- setx NOTION_API_TOKEN "..."
119
+ setx OPENROUTER_API_KEY "your_openrouter_key"
120
120
  ```
121
121
  (Only needs to be run once per variable. Restart the terminal after.)
122
122
 
123
123
  **Windows (PowerShell):**
124
124
  ```powershell
125
- [Environment]::SetEnvironmentVariable("AZURE_OPENAI_ENDPOINT", "https://...", "Machine")
126
- [Environment]::SetEnvironmentVariable("AZURE_OPENAI_API_KEY", "your_key", "Machine")
127
- [Environment]::SetEnvironmentVariable("AZURE_OPENAI_API_VERSION", "2025-01-01-preview", "Machine")
128
- [Environment]::SetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT", "bluma-gpt", "Machine")
129
- [Environment]::SetEnvironmentVariable("GITHUB_PERSONAL_ACCESS_TOKEN", "...", "Machine")
130
- [Environment]::SetEnvironmentVariable("NOTION_API_TOKEN", "...", "Machine")
125
+ [Environment]::SetEnvironmentVariable("OPENROUTER_API_KEY", "your_openrouter_key", "Machine")
131
126
  ```
132
127
 
133
128
  ### ℹ️ Global Installation of npm Packages in PowerShell (Windows)
@@ -160,6 +155,40 @@ npx bluma
160
155
 
161
156
  ---
162
157
 
158
+ ## Quick Start
159
+
160
+ Get up and running with BluMa in minutes:
161
+
162
+ 1. **Install BluMa:**
163
+ ```bash
164
+ npm install -g @nomad-e/bluma-cli
165
+ ```
166
+
167
+ 2. **Configure Environment:**
168
+ Set your OpenRouter API key (see [Configuration](#configuration-and-environment-variables)).
169
+
170
+ 3. **Launch BluMa:**
171
+ ```bash
172
+ bluma
173
+ ```
174
+
175
+ 4. **Interact:**
176
+ Start a conversation! Try commands like "Help me refactor this code" or "Run tests for my project."
177
+
178
+ For full installation details, see [Installation](#installation).
179
+
180
+ ---
181
+
182
+ ## Screenshots
183
+
184
+ Here's BluMa in action:
185
+
186
+ ![BluMa CLI Interface](https://pharmaseedevsa.blob.core.windows.net/pharmassee-dev-storage/bluma.png)
187
+
188
+ *BluMa's interactive CLI interface for conversational software engineering.*
189
+
190
+ ---
191
+
163
192
  ## <a name="project-structure"></a>Project Structure
164
193
  ```
165
194
  bluma-engineer/
@@ -240,15 +269,10 @@ Notes
240
269
  ---
241
270
 
242
271
  ## <a name="configuration-and-environment-variables"></a>Configuration and Environment Variables
243
- You must create a `.env` file (copy if needed from `.env.example`) with the following variables:
244
- - `AZURE_OPENAI_ENDPOINT`
245
- - `AZURE_OPENAI_API_KEY`
246
- - `AZURE_OPENAI_API_VERSION`
247
- - `AZURE_OPENAI_DEPLOYMENT`
248
- - `GITHUB_PERSONAL_ACCESS_TOKEN` (optional; required for GitHub integrations)
249
- - `NOTION_API_TOKEN` (optional; required for Notion integrations)
272
+ You must create a `.env` file (copy if needed from `.env.example`) with the following variable:
273
+ - `OPENROUTER_API_KEY` (required; get from [openrouter.ai](https://openrouter.ai))
250
274
 
251
- And others required by your agent/context or Azure setup.
275
+ And others required by your agent/context.
252
276
 
253
277
  Advanced config files are located in `src/app/agent/config/`.
254
278
 
@@ -261,7 +285,7 @@ Advanced config files are located in `src/app/agent/config/`.
261
285
  - Bundler: esbuild, with `esbuild-plugin-node-externals`
262
286
  - Test Runner: Jest 30 + babel-jest
263
287
  - Transpilers: Babel presets (env, react, typescript)
264
- - LLM/Agent: Azure OpenAI via `openai` SDK; MCP via `@modelcontextprotocol/sdk`
288
+ - LLM/Agent: OpenRouter via API; MCP via `@modelcontextprotocol/sdk`
265
289
  - Config loading: dotenv
266
290
  - Utilities: uuid, diff, react-devtools-core
267
291
 
@@ -385,9 +409,7 @@ stateDiagram-v2
385
409
  ```mermaid
386
410
  graph TD
387
411
  CLI["CLI (BluMa)"] --> LocalFS[("Local File System")]
388
- CLI --> AzureOpenAI[("Azure OpenAI API")]
389
- CLI --> GitHubAPI[("GitHub API")]
390
- CLI --> NotionAPI[("Notion API")]
412
+ CLI --> OpenRouter[("OpenRouter API")]
391
413
  CLI --> OtherAPIs[("Other External APIs")]
392
414
  CLI --> MCPServer[("MCP Server / Plugins")]
393
415
  ```
@@ -472,7 +494,7 @@ We welcome contributions! For full details, read [CONTRIBUTING.md](CONTRIBUTING.
472
494
  ---
473
495
 
474
496
  ## ⚠️ Limitations / Next Steps
475
- - Current LLM integration optimised for Azure OpenAI; add more providers.
497
+ - Current LLM integration uses OpenRouter; add more providers.
476
498
  - Logging verbosity could be made configurable.
477
499
  - Potential for richer plugin lifecycle (install/remove at runtime).
478
500
  - Improve error reporting in subagents.
@@ -526,6 +526,49 @@
526
526
  }
527
527
  }
528
528
  },
529
+ {
530
+ "type": "function",
531
+ "function": {
532
+ "name": "create_artifact",
533
+ "description": "Create or update an artifact file in the artifacts directory (~/.bluma/artifacts/). Use this to save implementation plans, walkthroughs, notes, or any document the user should review. Supports markdown files.",
534
+ "parameters": {
535
+ "type": "object",
536
+ "properties": {
537
+ "filename": {
538
+ "type": "string",
539
+ "description": "Name of the artifact file to create. Examples: 'implementation_plan.md', 'walkthrough.md', 'notes.md'."
540
+ },
541
+ "content": {
542
+ "type": "string",
543
+ "description": "Content to write to the artifact file. Supports markdown formatting."
544
+ }
545
+ },
546
+ "required": [
547
+ "filename",
548
+ "content"
549
+ ]
550
+ }
551
+ }
552
+ },
553
+ {
554
+ "type": "function",
555
+ "function": {
556
+ "name": "read_artifact",
557
+ "description": "Read an existing artifact file from the artifacts directory. Use this to retrieve previously saved plans, walkthroughs, or notes.",
558
+ "parameters": {
559
+ "type": "object",
560
+ "properties": {
561
+ "filename": {
562
+ "type": "string",
563
+ "description": "Name of the artifact file to read. Examples: 'implementation_plan.md', 'task.md'."
564
+ }
565
+ },
566
+ "required": [
567
+ "filename"
568
+ ]
569
+ }
570
+ }
571
+ },
529
572
  {
530
573
  "type": "function",
531
574
  "function": {
package/dist/main.js CHANGED
@@ -180,7 +180,7 @@ var HeaderComponent = ({
180
180
  const dirName = workdir.split("/").pop() || workdir;
181
181
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
182
182
  /* @__PURE__ */ jsxs(Box, { children: [
183
- /* @__PURE__ */ jsx(Text, { bold: true, color: "magenta", children: "bluma" }),
183
+ /* @__PURE__ */ jsx(Text, { color: "magenta", bold: true, children: "bluma \u2014 coding agent" }),
184
184
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
185
185
  " ",
186
186
  VERSION
@@ -1336,6 +1336,7 @@ import { spawn } from "child_process";
1336
1336
  var MAX_OUTPUT_SIZE = 1e5;
1337
1337
  var OUTPUT_TRUNCATION_MESSAGE = "\n\n[OUTPUT TRUNCATED - exceeded 100KB limit. Use pagination or redirect to file for full output.]";
1338
1338
  var DANGEROUS_PATTERNS = [
1339
+ // === ELEVAÇÃO DE PRIVILÉGIOS ===
1339
1340
  /^sudo\s+/i,
1340
1341
  // sudo commands
1341
1342
  /^doas\s+/i,
@@ -1348,20 +1349,57 @@ var DANGEROUS_PATTERNS = [
1348
1349
  // piped to sudo
1349
1350
  /;\s*sudo\s+/i,
1350
1351
  // chained with sudo
1351
- /&&\s*sudo\s+/i
1352
+ /&&\s*sudo\s+/i,
1352
1353
  // AND chained with sudo
1354
+ // === COMANDOS DESTRUTIVOS ===
1355
+ /\brm\s+(-[rf]+\s+)*[\/~]/i,
1356
+ // rm com paths perigosos (/, ~)
1357
+ /\brm\s+-[rf]*\s+\*/i,
1358
+ // rm -rf *
1359
+ /\bchmod\s+(777|666)\s+\//i,
1360
+ // chmod 777/666 em paths root
1361
+ /\bchown\s+.*\s+\//i,
1362
+ // chown em paths root
1363
+ /\bdd\s+.*of=\/dev\/(sd|hd|nvme)/i,
1364
+ // dd para discos
1365
+ /\bmkfs\./i,
1366
+ // format filesystem
1367
+ />\s*\/dev\/(sd|hd|nvme)/i,
1368
+ // redirect para disco
1369
+ /\bshred\s+/i,
1370
+ // secure delete
1371
+ // === FORK BOMB / RESOURCE EXHAUSTION ===
1372
+ /:\(\)\s*\{\s*:\|:&\s*\}\s*;:/,
1373
+ // fork bomb clássico
1374
+ /\bwhile\s+true\s*;\s*do/i,
1375
+ // infinite loop
1376
+ /\byes\s+\|/i,
1377
+ // yes piped (resource exhaustion)
1378
+ // === NETWORK PERIGOSO ===
1379
+ /\bcurl\s+.*\|\s*(ba)?sh/i,
1380
+ // curl | bash (remote code exec)
1381
+ /\bwget\s+.*\|\s*(ba)?sh/i,
1382
+ // wget | bash
1383
+ /\bnc\s+-[el]/i
1384
+ // netcat listener (backdoor)
1353
1385
  ];
1354
1386
  var INTERACTIVE_PATTERNS = [
1355
- /^(vim|vi|nano|emacs|less|more)\s*/i,
1356
- // editors/pagers
1357
- /^(top|htop|btop)\s*/i,
1387
+ /^(vim|vi|nano|emacs|pico)\s*/i,
1388
+ // editors
1389
+ /^(less|more|most)\s*/i,
1390
+ // pagers
1391
+ /^(top|htop|btop|atop|nmon)\s*/i,
1358
1392
  // monitoring tools
1359
- /^(ssh|telnet|ftp)\s+/i,
1393
+ /^(ssh|telnet|ftp|sftp)\s+/i,
1360
1394
  // remote connections
1361
- /^(mysql|psql|redis-cli|mongo)\s*/i,
1362
- // database CLIs
1363
- /^(python|node|ruby|irb)\s*$/i
1364
- // REPLs without script
1395
+ /^(mysql|psql|redis-cli|mongo|mongosh)\s*$/i,
1396
+ // database CLIs (sem script)
1397
+ /^(python|python3|node|ruby|irb|lua)\s*$/i,
1398
+ // REPLs sem script
1399
+ /^(gdb|lldb)\s*/i,
1400
+ // debuggers
1401
+ /^(bc|dc)\s*$/i
1402
+ // calculators
1365
1403
  ];
1366
1404
  function shellCommand(args) {
1367
1405
  const {
@@ -3345,6 +3383,49 @@ async function taskBoundary(args) {
3345
3383
  };
3346
3384
  }
3347
3385
  }
3386
+ async function createArtifact(args) {
3387
+ try {
3388
+ const { filename, content } = args;
3389
+ if (!filename || typeof filename !== "string") {
3390
+ return { success: false, error: "filename is required" };
3391
+ }
3392
+ if (content === void 0 || content === null) {
3393
+ return { success: false, error: "content is required" };
3394
+ }
3395
+ const dir = await getArtifactsDir();
3396
+ const filepath = path9.join(dir, filename);
3397
+ await fs7.writeFile(filepath, content, "utf-8");
3398
+ return {
3399
+ success: true,
3400
+ path: filepath
3401
+ };
3402
+ } catch (error) {
3403
+ return {
3404
+ success: false,
3405
+ error: error.message
3406
+ };
3407
+ }
3408
+ }
3409
+ async function readArtifact(args) {
3410
+ try {
3411
+ const { filename } = args;
3412
+ if (!filename || typeof filename !== "string") {
3413
+ return { success: false, error: "filename is required" };
3414
+ }
3415
+ const dir = await getArtifactsDir();
3416
+ const filepath = path9.join(dir, filename);
3417
+ const content = await fs7.readFile(filepath, "utf-8");
3418
+ return {
3419
+ success: true,
3420
+ content
3421
+ };
3422
+ } catch (error) {
3423
+ return {
3424
+ success: false,
3425
+ error: error.message
3426
+ };
3427
+ }
3428
+ }
3348
3429
 
3349
3430
  // src/app/agent/tools/natives/search_web.ts
3350
3431
  import https from "https";
@@ -3581,6 +3662,8 @@ var ToolInvoker = class {
3581
3662
  this.toolImplementations.set("message_notify_user", messageNotifyuser);
3582
3663
  this.toolImplementations.set("todo", todo);
3583
3664
  this.toolImplementations.set("task_boundary", taskBoundary);
3665
+ this.toolImplementations.set("create_artifact", createArtifact);
3666
+ this.toolImplementations.set("read_artifact", readArtifact);
3584
3667
  this.toolImplementations.set("search_web", searchWeb);
3585
3668
  this.toolImplementations.set("agent_end_turn", async () => ({ success: true, message: "Task ended by agent." }));
3586
3669
  }
@@ -4047,17 +4130,19 @@ function getTestCommand(dir) {
4047
4130
  }
4048
4131
  var SYSTEM_PROMPT = `
4049
4132
  <identity>
4050
- You are BluMa, an autonomous coding agent developed by NomadEngenuity.
4051
- You are a **senior peer engineer** working alongside {username} - technical, proactive, and collaborative.
4052
- You know this machine better than anyone. You understand the project structure, dependencies, and conventions.
4053
- You are not just an assistant - you are a **teammate** who takes ownership of tasks.
4054
-
4055
- Key traits:
4056
- - Think like a senior developer who has been on this project for years
4057
- - Suggest improvements proactively, don't just follow orders blindly
4058
- - Spot bugs and issues before they become problems
4059
- - Write tests as naturally as you write code
4060
- - Always communicate your reasoning and progress
4133
+ You are BluMa, an autonomous coding agent developed by NomadEngenuity.
4134
+ BluMa \u2014 Base Language Unit \xB7 Model Agent
4135
+ A CLI-based model agent responsible for language-level code generation, refactoring and semantic transformations in the Factor AI stack.
4136
+ You are a **senior peer engineer** working alongside {username} - technical, proactive, and collaborative.
4137
+ You know this machine better than anyone. You understand the project structure, dependencies, and conventions.
4138
+ You are not just an assistant - you are a **teammate** who takes ownership of tasks.
4139
+
4140
+ Key traits:
4141
+ - Think like a senior developer who has been on this project for years
4142
+ - Suggest improvements proactively, don't just follow orders blindly
4143
+ - Spot bugs and issues before they become problems
4144
+ - Write tests as naturally as you write code
4145
+ - Always communicate your reasoning and progress
4061
4146
  </identity>
4062
4147
 
4063
4148
  ---
@@ -5272,8 +5357,8 @@ var renderShellCommand2 = ({ args }) => {
5272
5357
  const parsed = parseArgs(args);
5273
5358
  const command = parsed.command || "[no command]";
5274
5359
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5275
- /* @__PURE__ */ jsx8(Text8, { color: "cyan", bold: true, children: "$" }),
5276
- /* @__PURE__ */ jsxs8(Text8, { color: "cyan", children: [
5360
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "$" }),
5361
+ /* @__PURE__ */ jsxs8(Text8, { color: "white", children: [
5277
5362
  " ",
5278
5363
  truncate(command, 70)
5279
5364
  ] })
@@ -5283,7 +5368,7 @@ var renderLsTool2 = ({ args }) => {
5283
5368
  const parsed = parseArgs(args);
5284
5369
  const path17 = parsed.directory_path || ".";
5285
5370
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5286
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "ls" }),
5371
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "ls" }),
5287
5372
  /* @__PURE__ */ jsxs8(Text8, { children: [
5288
5373
  " ",
5289
5374
  path17
@@ -5294,7 +5379,7 @@ var renderCountFilesLines = ({ args }) => {
5294
5379
  const parsed = parseArgs(args);
5295
5380
  const filepath = parsed.filepath || "[no file]";
5296
5381
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5297
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "wc -l" }),
5382
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "wc -l" }),
5298
5383
  /* @__PURE__ */ jsxs8(Text8, { children: [
5299
5384
  " ",
5300
5385
  getBasename(filepath)
@@ -5307,12 +5392,12 @@ var renderReadFileLines2 = ({ args }) => {
5307
5392
  const start = parsed.start_line || 1;
5308
5393
  const end = parsed.end_line || start;
5309
5394
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5310
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "cat" }),
5395
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "cat" }),
5311
5396
  /* @__PURE__ */ jsxs8(Text8, { children: [
5312
5397
  " ",
5313
5398
  getBasename(filepath)
5314
5399
  ] }),
5315
- /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
5400
+ /* @__PURE__ */ jsxs8(Text8, { color: "white", children: [
5316
5401
  " :",
5317
5402
  start,
5318
5403
  "-",
@@ -5325,7 +5410,7 @@ var renderBlumaNotebook = ({ args }) => {
5325
5410
  const thought = parsed.thought || parsed.content?.thought || "[thinking...]";
5326
5411
  const truncated = truncate(thought, 100);
5327
5412
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, children: [
5328
- /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsx8(Text8, { color: "magenta", dimColor: true, children: "thinking" }) }),
5413
+ /* @__PURE__ */ jsx8(Box8, { children: /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "thinking" }) }),
5329
5414
  /* @__PURE__ */ jsx8(Box8, { paddingLeft: 2, children: /* @__PURE__ */ jsx8(Text8, { dimColor: true, italic: true, children: truncated }) })
5330
5415
  ] });
5331
5416
  };
@@ -5336,7 +5421,7 @@ var renderEditToolCall = ({ args, preview }) => {
5336
5421
  const newStr = parsed.new_string || "";
5337
5422
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, children: [
5338
5423
  /* @__PURE__ */ jsxs8(Box8, { children: [
5339
- /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "edit" }),
5424
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "edit" }),
5340
5425
  /* @__PURE__ */ jsxs8(Text8, { children: [
5341
5426
  " ",
5342
5427
  getBasename(filepath)
@@ -5347,7 +5432,7 @@ var renderEditToolCall = ({ args, preview }) => {
5347
5432
  "- ",
5348
5433
  truncate(oldStr, 50)
5349
5434
  ] }),
5350
- /* @__PURE__ */ jsxs8(Text8, { color: "green", dimColor: true, children: [
5435
+ /* @__PURE__ */ jsxs8(Text8, { color: "green", bold: true, children: [
5351
5436
  "+ ",
5352
5437
  truncate(newStr, 50)
5353
5438
  ] })
@@ -5365,8 +5450,8 @@ var renderTodoTool2 = ({ args }) => {
5365
5450
  const bar = "=".repeat(filled) + " ".repeat(barWidth - filled);
5366
5451
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: 1, children: [
5367
5452
  /* @__PURE__ */ jsxs8(Box8, { children: [
5368
- /* @__PURE__ */ jsx8(Text8, { color: "magenta", children: "todo" }),
5369
- /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
5453
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "todo" }),
5454
+ /* @__PURE__ */ jsxs8(Text8, { children: [
5370
5455
  " [",
5371
5456
  bar,
5372
5457
  "] ",
@@ -5402,8 +5487,8 @@ var renderFindByName = ({ args }) => {
5402
5487
  const pattern = parsed.pattern || "*";
5403
5488
  const dir = parsed.directory || ".";
5404
5489
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5405
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "find" }),
5406
- /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
5490
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "find" }),
5491
+ /* @__PURE__ */ jsxs8(Text8, { color: "white", children: [
5407
5492
  ' "',
5408
5493
  pattern,
5409
5494
  '"'
@@ -5419,8 +5504,8 @@ var renderGrepSearch = ({ args }) => {
5419
5504
  const query = parsed.query || "";
5420
5505
  const path17 = parsed.path || ".";
5421
5506
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5422
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "grep" }),
5423
- /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
5507
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "grep" }),
5508
+ /* @__PURE__ */ jsxs8(Text8, { color: "white", children: [
5424
5509
  ' "',
5425
5510
  truncate(query, 30),
5426
5511
  '"'
@@ -5435,7 +5520,7 @@ var renderViewFileOutline = ({ args }) => {
5435
5520
  const parsed = parseArgs(args);
5436
5521
  const filepath = parsed.file_path || "[no file]";
5437
5522
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5438
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "outline" }),
5523
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "outline" }),
5439
5524
  /* @__PURE__ */ jsxs8(Text8, { children: [
5440
5525
  " ",
5441
5526
  getBasename(filepath)
@@ -5446,8 +5531,8 @@ var renderRunCommandAsync = ({ args }) => {
5446
5531
  const parsed = parseArgs(args);
5447
5532
  const command = parsed.command || "[no command]";
5448
5533
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5449
- /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "async" }),
5450
- /* @__PURE__ */ jsx8(Text8, { color: "cyan", children: " $" }),
5534
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "async" }),
5535
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: " $" }),
5451
5536
  /* @__PURE__ */ jsxs8(Text8, { children: [
5452
5537
  " ",
5453
5538
  truncate(command, 50)
@@ -5458,7 +5543,7 @@ var renderCommandStatus = ({ args }) => {
5458
5543
  const parsed = parseArgs(args);
5459
5544
  const id = parsed.command_id || "[no id]";
5460
5545
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5461
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "status" }),
5546
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "status" }),
5462
5547
  /* @__PURE__ */ jsxs8(Text8, { children: [
5463
5548
  " #",
5464
5549
  id
@@ -5499,8 +5584,8 @@ var renderSearchWeb = ({ args }) => {
5499
5584
  const parsed = parseArgs(args);
5500
5585
  const query = parsed.query || "[no query]";
5501
5586
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5502
- /* @__PURE__ */ jsx8(Text8, { color: "blue", children: "search" }),
5503
- /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
5587
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: "search" }),
5588
+ /* @__PURE__ */ jsxs8(Text8, { color: "white", children: [
5504
5589
  ' "',
5505
5590
  truncate(query, 40),
5506
5591
  '"'
@@ -5511,8 +5596,8 @@ var renderGeneric2 = ({ toolName, args }) => {
5511
5596
  const parsed = parseArgs(args);
5512
5597
  const keys = Object.keys(parsed).slice(0, 2);
5513
5598
  return /* @__PURE__ */ jsxs8(Box8, { paddingX: 1, children: [
5514
- /* @__PURE__ */ jsx8(Text8, { color: "gray", children: toolName }),
5515
- keys.length > 0 && /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
5599
+ /* @__PURE__ */ jsx8(Text8, { color: "white", bold: true, children: toolName }),
5600
+ keys.length > 0 && /* @__PURE__ */ jsxs8(Text8, { children: [
5516
5601
  " ",
5517
5602
  keys.map((k) => `${k}:${truncate(String(parsed[k]), 20)}`).join(" ")
5518
5603
  ] })
@@ -6138,15 +6223,8 @@ var ReasoningDisplayComponent = ({
6138
6223
  const maxLines = 5;
6139
6224
  const lines = reasoning.split("\n");
6140
6225
  const displayText = isExpanded ? reasoning : lines.slice(0, maxLines).join("\n") + (lines.length > maxLines ? "..." : "");
6141
- return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
6142
- /* @__PURE__ */ jsxs14(Box15, { children: [
6143
- /* @__PURE__ */ jsx15(Text14, { color: "white", children: " Thinking" }),
6144
- lines.length > maxLines && /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
6145
- " [",
6146
- lines.length,
6147
- " lines]"
6148
- ] })
6149
- ] }),
6226
+ return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", paddingX: 1, marginBottom: 1, marginTop: 1, children: [
6227
+ /* @__PURE__ */ jsx15(Box15, { children: /* @__PURE__ */ jsx15(Text14, { color: "white", bold: true, children: "Thinking" }) }),
6150
6228
  /* @__PURE__ */ jsx15(Box15, { paddingLeft: 2, flexDirection: "column", children: displayText.split("\n").map((line, i) => /* @__PURE__ */ jsx15(Text14, { color: "gray", dimColor: true, children: line }, i)) })
6151
6229
  ] });
6152
6230
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomad-e/bluma-cli",
3
- "version": "0.0.104",
3
+ "version": "0.0.105",
4
4
  "description": "BluMa independent agent for automation and advanced software engineering.",
5
5
  "author": "Alex Fonseca",
6
6
  "license": "Apache-2.0",