@nomad-e/bluma-cli 0.6.2 β 0.6.3
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 +195 -11
- package/dist/config/native_tools.json +8 -5
- package/dist/main.js +44 -106
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
**BluMa** is an independent AI agent CLI for automation and advanced software engineering. It combines powerful tool orchestration, multi-agent coordination, and intelligent context management to help you build software faster and with higher quality.
|
|
15
15
|
|
|
16
|
+
**Latest Version:** v0.6.2 (2026-05-09) β Modular tool architecture, native clipboard, thread management, bidirectional mailbox IPC, enhanced multi-agent orchestration, and professional release engineering.
|
|
17
|
+
|
|
16
18
|
---
|
|
17
19
|
|
|
18
20
|
## π Quick Start
|
|
@@ -75,18 +77,104 @@ Tools are now modularly structured in `src/app/agent/tools/` with separate UI co
|
|
|
75
77
|
### π§ **Multi-Agent Orchestration**
|
|
76
78
|
- **Coordinator Mode**: Product Owner + Engineering Manager hybrid that delegates to specialist workers
|
|
77
79
|
- **Parallel Execution**: Launch multiple workers concurrently for research, implementation, and verification
|
|
78
|
-
- **Mailbox IPC**: Bidirectional communication between coordinator and workers
|
|
80
|
+
- **Mailbox IPC**: **Bidirectional file-based communication** between coordinator and workers
|
|
81
|
+
- **send_message**: Send follow-ups to running workers without re-spawning
|
|
82
|
+
- **list_mailbox_messages**: Read progress updates, permission requests, and results
|
|
83
|
+
- **poll_mailbox**: Poll for new messages from workers
|
|
84
|
+
- **signal_mailbox**: Send ack/nack/progress/heartbeat signals
|
|
85
|
+
- **File-based storage**: `~/.bluma/mailboxes/{session_id}.in/out/sig` (JSONL format)
|
|
79
86
|
- **Worker Types**: Researchers, implementers, verifiers with specialized roles
|
|
80
87
|
- **Session Registry**: Track and manage agent sessions with lifecycle events
|
|
88
|
+
- **Task Boundary Tracking**: Use `task_boundary` to track orchestration phases (PLANNING, EXECUTION, VERIFICATION)
|
|
81
89
|
|
|
82
90
|
### π **Slash Commands** (80+ commands)
|
|
83
91
|
Quick access to common operations across 5 categories:
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
93
|
+
**Session Commands** (25+):
|
|
94
|
+
- `/clear` - Clear current session
|
|
95
|
+
- `/sessions` - List all sessions
|
|
96
|
+
- `/attach` - Attach to existing session
|
|
97
|
+
- `/follow` - Follow session output
|
|
98
|
+
- `/bridge` - Bridge multiple sessions
|
|
99
|
+
- `/status` - Show session status
|
|
100
|
+
- `/logs` - View session logs
|
|
101
|
+
- `/resume` - Resume previous session
|
|
102
|
+
- `/kill` - Terminate session
|
|
103
|
+
- `/compact` - Compress context
|
|
104
|
+
- `/export` - Export session
|
|
105
|
+
- `/summarize` - Summarize conversation
|
|
106
|
+
- `/history` - Command history
|
|
107
|
+
- `/share` - Share session
|
|
108
|
+
- `/copy` - Copy output to clipboard
|
|
109
|
+
- `/commit` - Create git commit
|
|
110
|
+
- `/pr` - Create pull request
|
|
111
|
+
- `/release` - Professional release engineering
|
|
112
|
+
- `/snip` - Extract conversation snippets
|
|
113
|
+
- `/collapse` - Collapse context
|
|
114
|
+
- `/brief` - Generate brief
|
|
115
|
+
- `/undo` - Undo last action
|
|
116
|
+
- `/redo` - Redo undone action
|
|
117
|
+
- `/thread` - Thread management (list/new/resume/fork/rename/archive/delete)
|
|
118
|
+
|
|
119
|
+
**Inspect Commands** (30+):
|
|
120
|
+
- `/plugins` - List plugins
|
|
121
|
+
- `/plugin` - Plugin details
|
|
122
|
+
- `/diagnostics` - Run diagnostics
|
|
123
|
+
- `/permissions` - Show permissions
|
|
124
|
+
- `/features` - List features
|
|
125
|
+
- `/hooks` - Hook registry
|
|
126
|
+
- `/model` - Model info
|
|
127
|
+
- `/effort` - Effort estimation
|
|
128
|
+
- `/style` - Code style
|
|
129
|
+
- `/sandbox` - Sandbox status
|
|
130
|
+
- `/worktree` - Worktree info
|
|
131
|
+
- `/statusline` - Status line config
|
|
132
|
+
- `/skills` - List skills
|
|
133
|
+
- `/tools` - List tools
|
|
134
|
+
- `/mcp` - MCP resources
|
|
135
|
+
- `/debug-workers` - Worker debug
|
|
136
|
+
- `/cost` - Cost tracking
|
|
137
|
+
- `/memory` - Memory usage
|
|
138
|
+
- `/stats` - Session stats
|
|
139
|
+
- `/theme` - Theme config
|
|
140
|
+
- `/keybindings` - Key bindings
|
|
141
|
+
- `/vim` - Vim mode
|
|
142
|
+
- `/ctx` - Context inspector
|
|
143
|
+
- `/dream` - Dream engine status
|
|
144
|
+
- `/diff` - Show recent changes
|
|
145
|
+
- `/editor` - Open in editor
|
|
146
|
+
- `/config` - Runtime config
|
|
147
|
+
- `/file` - File operations
|
|
148
|
+
- `/search` - Search codebase
|
|
149
|
+
- `/context` - Context management
|
|
150
|
+
- `/token` - Token usage
|
|
151
|
+
- `/settings` - Runtime settings
|
|
152
|
+
- `/alias` - Manage aliases
|
|
153
|
+
- `/macro` - Execute macros
|
|
154
|
+
- `/thread stats` - Thread statistics
|
|
155
|
+
|
|
156
|
+
**Agent Commands** (15+):
|
|
157
|
+
- `/agent` - Agent info
|
|
158
|
+
- `/agents` - List agents
|
|
159
|
+
- `/img` / `/image` - Image handling
|
|
160
|
+
- `/init` - Initialize project
|
|
161
|
+
- `/review` - Code review
|
|
162
|
+
- `/explain` - Explain code
|
|
163
|
+
- `/fix` - Fix errors
|
|
164
|
+
- `/debug` - Debug issues
|
|
165
|
+
- `/bug` - Report bug
|
|
166
|
+
- `/test` - Run tests
|
|
167
|
+
- `/optimize` - Optimize code
|
|
168
|
+
- `/refactor` - Refactor code
|
|
169
|
+
- `/document` - Generate docs
|
|
170
|
+
- `/chat` - Chat mode
|
|
171
|
+
- `/code` - Code mode
|
|
172
|
+
- `/terminal` - Terminal placeholder
|
|
173
|
+
- `/template` - Create from template
|
|
174
|
+
|
|
175
|
+
**Input Methods**:
|
|
176
|
+
- `Ctrl+V` / `Cmd+V` - Paste image/text/file
|
|
177
|
+
- `Ctrl+Shift+I` - Same as Ctrl+V
|
|
90
178
|
|
|
91
179
|
### π― **Intelligent Context Management**
|
|
92
180
|
- **Auto Memory**: Persistent coding notes across sessions (`coding_memory`)
|
|
@@ -102,15 +190,29 @@ Structured problem-solving workflow with 3 phases:
|
|
|
102
190
|
2. **EXECUTION**: Implementation
|
|
103
191
|
3. **VERIFICATION**: Testing and validation
|
|
104
192
|
|
|
105
|
-
### π§ **Skills System**
|
|
106
|
-
Extendable expertise modules with progressive disclosure:
|
|
193
|
+
### π§ **Skills System** (6 skills)
|
|
194
|
+
Extendable expertise modules with **progressive disclosure** β load only when needed:
|
|
195
|
+
|
|
196
|
+
**Available Skills:**
|
|
107
197
|
- **git-commit**: Conventional commits automation with BluMa watermark
|
|
108
|
-
- **git-pr**: Pull request creation and management
|
|
109
|
-
- **git-release**: Full release engineering
|
|
198
|
+
- **git-pr**: Pull request creation and management (descriptions, reviewers, draft mode)
|
|
199
|
+
- **git-release**: Full release engineering (version bumps, changelog, tags, npm publish, GitHub releases)
|
|
110
200
|
- **pdf**: PDF generation and manipulation (reports, merge, forms, OCR)
|
|
111
201
|
- **xlsx**: Spreadsheet processing (create, edit, formulas, charting, cleaning)
|
|
112
202
|
- **skill-creator**: Create custom skills
|
|
113
203
|
|
|
204
|
+
**How Skills Work:**
|
|
205
|
+
1. **Discovery**: Skills loaded from `dist/config/skills/`, `{cwd}/.bluma/skills/`, `~/.bluma/skills/`
|
|
206
|
+
2. **Progressive Disclosure**:
|
|
207
|
+
- Level 1: One-line description (always visible)
|
|
208
|
+
- Level 2: Full instructions (loaded on activation)
|
|
209
|
+
- Level 3: References and scripts (loaded on demand)
|
|
210
|
+
3. **Triggering**: Agent auto-detects when to load skills based on task context
|
|
211
|
+
4. **Priority**: Native > Project > Global (native skills cannot be overridden)
|
|
212
|
+
|
|
213
|
+
**Create Custom Skills:**
|
|
214
|
+
See [docs/SKILLS.md](docs/SKILLS.md) for complete guide on authoring skills.
|
|
215
|
+
|
|
114
216
|
### π¨ **Modern UI**
|
|
115
217
|
- Built with **Ink** (React for CLI)
|
|
116
218
|
- **Shimmer effects** for working states (WorkingShimmerText, Spinner with ShimmerChar/FlashingChar)
|
|
@@ -132,6 +234,17 @@ Extendable expertise modules with progressive disclosure:
|
|
|
132
234
|
- **ES Modules**: Modern module system with bundler resolution
|
|
133
235
|
- **React 19**: Latest React with concurrent features
|
|
134
236
|
- **Optimized rendering**: Memoized message blocks, offscreen freeze, expandable previews
|
|
237
|
+
- **Parallel tests**: Up to 8 workers for faster test execution
|
|
238
|
+
- **Native modules**: Rust-based clipboard and layout engine for critical paths
|
|
239
|
+
|
|
240
|
+
### π **Hooks & Plugins**
|
|
241
|
+
Extensible architecture with hook registry and plugin system:
|
|
242
|
+
|
|
243
|
+
- **Hook Registry**: Execute custom scripts on events (pre-commit, post-build, etc.)
|
|
244
|
+
- **Plugin System**: Extend BluMa with custom plugins
|
|
245
|
+
- **Event-driven**: Hooks triggered by tool execution, session events, and lifecycle hooks
|
|
246
|
+
|
|
247
|
+
See [docs/BLUMA_DEVELOPER_GUIDE.md](docs/BLUMA_DEVELOPER_GUIDE.md) for plugin development.
|
|
135
248
|
|
|
136
249
|
### π **MCP Support**
|
|
137
250
|
- **Model Context Protocol**: Connect to external MCP servers
|
|
@@ -143,6 +256,28 @@ Extendable expertise modules with progressive disclosure:
|
|
|
143
256
|
- **Thread stats**: View thread metadata and statistics
|
|
144
257
|
- **Codex-style interface**: Familiar thread management commands
|
|
145
258
|
|
|
259
|
+
### π¦ **Native Modules** (Rust)
|
|
260
|
+
High-performance native extensions for critical operations:
|
|
261
|
+
|
|
262
|
+
- **bluma-clipboard**: Cross-platform clipboard with image support
|
|
263
|
+
- Built with Rust (arboard crate)
|
|
264
|
+
- No dependencies on wl-paste/xclip
|
|
265
|
+
- Native image reading for terminal paste
|
|
266
|
+
- **yoga-layout**: High-performance layout engine for Ink
|
|
267
|
+
- Facebook's Yoga layout library
|
|
268
|
+
- Optimized for terminal UI rendering
|
|
269
|
+
|
|
270
|
+
### π¦ **VS Code Extension**
|
|
271
|
+
Full BluMa capabilities integrated into VS Code:
|
|
272
|
+
|
|
273
|
+
- **Chat Panel**: Interactive chat interface with full BluMa capabilities
|
|
274
|
+
- **Session Sync**: Real-time synchronization with terminal sessions
|
|
275
|
+
- **Image Support**: Paste and view images directly in VS Code
|
|
276
|
+
- **File Integration**: Open and edit files from within the chat
|
|
277
|
+
- **Streaming**: Real-time response streaming with markdown rendering
|
|
278
|
+
|
|
279
|
+
See [vscode-extension/README.md](vscode-extension/README.md) for setup instructions.
|
|
280
|
+
|
|
146
281
|
---
|
|
147
282
|
|
|
148
283
|
## ποΈ Architecture
|
|
@@ -207,7 +342,12 @@ This modular design enables:
|
|
|
207
342
|
- **`src/ink/`**: Ink renderer shims and compatibility layer
|
|
208
343
|
- **`src/shims/`**: Build-time shims for react-compiler-runtime and bidi-js
|
|
209
344
|
- **`native/`**: Rust-based native modules (clipboard, yoga-layout)
|
|
345
|
+
- **bluma-clipboard**: Cross-platform clipboard with image support
|
|
346
|
+
- **yoga-layout**: High-performance layout engine for Ink
|
|
210
347
|
- **`vscode-extension/`**: VS Code extension for chat integration
|
|
348
|
+
- Chat panel with full BluMa capabilities
|
|
349
|
+
- Real-time session sync
|
|
350
|
+
- Image and file support
|
|
211
351
|
|
|
212
352
|
---
|
|
213
353
|
|
|
@@ -352,6 +492,24 @@ bluma
|
|
|
352
492
|
/pr "feat: add new authentication" # Create PR with conventional commit
|
|
353
493
|
```
|
|
354
494
|
|
|
495
|
+
### 5. **Web Integration**
|
|
496
|
+
```bash
|
|
497
|
+
# Use the embeddable React chat widget
|
|
498
|
+
import { useChatWidget } from '@nomad-e/bluma-cli/chat-widget';
|
|
499
|
+
|
|
500
|
+
// Embed BluMa capabilities in your web app
|
|
501
|
+
const { messages, streamResponse } = useChatWidget();
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### 6. **VS Code Integration**
|
|
505
|
+
```bash
|
|
506
|
+
# Install the VS Code extension
|
|
507
|
+
# Access full BluMa capabilities from within VS Code
|
|
508
|
+
- Chat panel with session sync
|
|
509
|
+
- Image and file support
|
|
510
|
+
- Real-time streaming
|
|
511
|
+
```
|
|
512
|
+
|
|
355
513
|
---
|
|
356
514
|
|
|
357
515
|
## π License
|
|
@@ -366,4 +524,30 @@ Apache 2.0 β see [LICENSE](LICENSE) for details.
|
|
|
366
524
|
|
|
367
525
|
---
|
|
368
526
|
|
|
369
|
-
|
|
527
|
+
## π° Changelog
|
|
528
|
+
|
|
529
|
+
See [CHANGELOG.md](CHANGELOG.md) for detailed release notes.
|
|
530
|
+
|
|
531
|
+
### What's New in v0.6.2 (2026-05-09)
|
|
532
|
+
|
|
533
|
+
**Major Features:**
|
|
534
|
+
- **Modular Tool Architecture**: All 45+ tools now have dedicated directories with separate logic, UI, and types
|
|
535
|
+
- **Native Clipboard Support**: Rust-based clipboard implementation for cross-platform image handling
|
|
536
|
+
- **Thread Management**: Full thread lifecycle with create, resume, fork, rename, archive, delete operations
|
|
537
|
+
- **Enhanced Multi-Agent Orchestration**: Improved coordinator-worker communication with bidirectional mailbox IPC
|
|
538
|
+
- **Chat Widget**: Embeddable React chat component for web integration
|
|
539
|
+
|
|
540
|
+
**Improvements:**
|
|
541
|
+
- 27 new slash commands for session management, inspection, and agent control
|
|
542
|
+
- Performance optimizations in UI rendering and context management
|
|
543
|
+
- Enhanced sandbox security with improved policy enforcement
|
|
544
|
+
- Better error handling and user-friendly error messages
|
|
545
|
+
|
|
546
|
+
**Fixes:**
|
|
547
|
+
- Resolved circular dependency in tool metadata
|
|
548
|
+
- Fixed worker registration for UI visibility
|
|
549
|
+
- Improved session persistence on LLM errors
|
|
550
|
+
|
|
551
|
+
---
|
|
552
|
+
|
|
553
|
+
*BluMa CLI v0.6.2 β Built with TypeScript, React 19, Ink, and ES modules.*
|
|
@@ -570,13 +570,14 @@
|
|
|
570
570
|
"type": "function",
|
|
571
571
|
"function": {
|
|
572
572
|
"name": "task_boundary",
|
|
573
|
-
"description": "Indicate the start of a task or make an update to the current task. Use this to organize complex work into phases (PLANNING, EXECUTION, VERIFICATION). The UI will show this as a structured task view with progress tracking.",
|
|
573
|
+
"description": "Indicate the start of a task or make an update to the current task. Use this to organize complex work into phases (PLANNING, EXECUTION, VERIFICATION). The UI will show this as a structured task view with progress tracking. **IMPORTANT: All 4 fields are required and must not be empty.**",
|
|
574
574
|
"parameters": {
|
|
575
575
|
"type": "object",
|
|
576
576
|
"properties": {
|
|
577
577
|
"task_name": {
|
|
578
578
|
"type": "string",
|
|
579
|
-
"
|
|
579
|
+
"minLength": 1,
|
|
580
|
+
"description": "Name of the task, e.g. 'Implementing Authentication'. Use the same name to update an existing task. **REQUIRED: Must not be empty.**"
|
|
580
581
|
},
|
|
581
582
|
"mode": {
|
|
582
583
|
"type": "string",
|
|
@@ -585,15 +586,17 @@
|
|
|
585
586
|
"EXECUTION",
|
|
586
587
|
"VERIFICATION"
|
|
587
588
|
],
|
|
588
|
-
"description": "Current mode: PLANNING (research/design), EXECUTION (implementing), VERIFICATION (testing)."
|
|
589
|
+
"description": "Current mode: PLANNING (research/design), EXECUTION (implementing), VERIFICATION (testing). **REQUIRED.**"
|
|
589
590
|
},
|
|
590
591
|
"task_status": {
|
|
591
592
|
"type": "string",
|
|
592
|
-
"
|
|
593
|
+
"minLength": 1,
|
|
594
|
+
"description": "Current activity, e.g. 'Creating authentication middleware'. Describes what you are about to do. **REQUIRED: Must not be empty.**"
|
|
593
595
|
},
|
|
594
596
|
"task_summary": {
|
|
595
597
|
"type": "string",
|
|
596
|
-
"
|
|
598
|
+
"minLength": 1,
|
|
599
|
+
"description": "Summary of what has been accomplished so far. Should be concise but comprehensive. **REQUIRED: Must not be empty.**"
|
|
597
600
|
}
|
|
598
601
|
},
|
|
599
602
|
"required": [
|
package/dist/main.js
CHANGED
|
@@ -16617,31 +16617,26 @@ async function updateTaskFile(task) {
|
|
|
16617
16617
|
async function taskBoundary(args) {
|
|
16618
16618
|
try {
|
|
16619
16619
|
const { task_name, mode, task_status, task_summary } = args;
|
|
16620
|
+
const missingFields = [];
|
|
16620
16621
|
if (!task_name || typeof task_name !== "string") {
|
|
16621
|
-
|
|
16622
|
-
success: false,
|
|
16623
|
-
task_name: "",
|
|
16624
|
-
mode: "EXECUTION",
|
|
16625
|
-
status: "",
|
|
16626
|
-
message: "task_name is required"
|
|
16627
|
-
};
|
|
16622
|
+
missingFields.push("task_name");
|
|
16628
16623
|
}
|
|
16629
|
-
if (!["PLANNING", "EXECUTION", "VERIFICATION"].includes(mode)) {
|
|
16630
|
-
|
|
16631
|
-
success: false,
|
|
16632
|
-
task_name,
|
|
16633
|
-
mode: "EXECUTION",
|
|
16634
|
-
status: "",
|
|
16635
|
-
message: `Invalid mode: ${mode}. Must be PLANNING, EXECUTION, or VERIFICATION`
|
|
16636
|
-
};
|
|
16624
|
+
if (!mode || !["PLANNING", "EXECUTION", "VERIFICATION"].includes(mode)) {
|
|
16625
|
+
missingFields.push("mode");
|
|
16637
16626
|
}
|
|
16638
16627
|
if (!task_status || typeof task_status !== "string") {
|
|
16628
|
+
missingFields.push("task_status");
|
|
16629
|
+
}
|
|
16630
|
+
if (!task_summary || typeof task_summary !== "string") {
|
|
16631
|
+
missingFields.push("task_summary");
|
|
16632
|
+
}
|
|
16633
|
+
if (missingFields.length > 0) {
|
|
16639
16634
|
return {
|
|
16640
16635
|
success: false,
|
|
16641
|
-
task_name,
|
|
16642
|
-
mode,
|
|
16643
|
-
status: "",
|
|
16644
|
-
message: "
|
|
16636
|
+
task_name: task_name || "",
|
|
16637
|
+
mode: mode || "EXECUTION",
|
|
16638
|
+
status: task_status || "",
|
|
16639
|
+
message: `Missing required fields: ${missingFields.join(", ")}. All 4 fields are required: task_name, mode, task_status, task_summary`
|
|
16645
16640
|
};
|
|
16646
16641
|
}
|
|
16647
16642
|
const now2 = Date.now();
|
|
@@ -23542,53 +23537,6 @@ function disableCoordinatorMode() {
|
|
|
23542
23537
|
delete process.env.BLUMA_COORDINATOR_MODE;
|
|
23543
23538
|
}
|
|
23544
23539
|
|
|
23545
|
-
// src/app/agent/core/prompt/tool_guidance.ts
|
|
23546
|
-
var TOOL_GUIDANCE_RULES = [
|
|
23547
|
-
{
|
|
23548
|
-
toolName: "read_file_lines",
|
|
23549
|
-
guidance: "To read files use `read_file_lines` instead of cat, head, tail, or sed"
|
|
23550
|
-
},
|
|
23551
|
-
{
|
|
23552
|
-
toolName: "edit_tool",
|
|
23553
|
-
guidance: "To edit files use `edit_tool` instead of sed or awk"
|
|
23554
|
-
},
|
|
23555
|
-
{
|
|
23556
|
-
toolName: "file_write",
|
|
23557
|
-
guidance: "To create files use `file_write` instead of cat with heredoc or echo redirection"
|
|
23558
|
-
},
|
|
23559
|
-
{
|
|
23560
|
-
toolName: "grep_search",
|
|
23561
|
-
guidance: "To search file content use `grep_search` instead of grep or rg"
|
|
23562
|
-
},
|
|
23563
|
-
{
|
|
23564
|
-
toolName: "find_by_name",
|
|
23565
|
-
guidance: "To search for files use `find_by_name` instead of find or ls"
|
|
23566
|
-
},
|
|
23567
|
-
{
|
|
23568
|
-
toolName: "view_file_outline",
|
|
23569
|
-
guidance: "To understand file structure use `view_file_outline` instead of opening the whole file"
|
|
23570
|
-
}
|
|
23571
|
-
];
|
|
23572
|
-
var ALWAYS_INCLUDED = [
|
|
23573
|
-
"Reserve using `shell_command` exclusively for system commands and terminal operations that require shell execution. If you are unsure and there is a relevant dedicated tool, default to using the dedicated tool.",
|
|
23574
|
-
"You can call multiple tools in a single response. If you intend to call multiple tools and there are no dependencies between them, make all independent tool calls in parallel. Maximize use of parallel tool calls where possible to increase efficiency.",
|
|
23575
|
-
"Do NOT use `shell_command` to run commands when a relevant dedicated tool is provided. Using dedicated tools allows the user to better understand and review your work."
|
|
23576
|
-
];
|
|
23577
|
-
function buildToolGuidanceSection(availableTools) {
|
|
23578
|
-
const toolSet = new Set(availableTools);
|
|
23579
|
-
const activeRules = TOOL_GUIDANCE_RULES.filter((rule) => toolSet.has(rule.toolName)).map((rule) => rule.guidance);
|
|
23580
|
-
if (activeRules.length === 0) {
|
|
23581
|
-
return "";
|
|
23582
|
-
}
|
|
23583
|
-
const lines = [
|
|
23584
|
-
"# Using your tools",
|
|
23585
|
-
"",
|
|
23586
|
-
...activeRules.map((r) => `- ${r}`),
|
|
23587
|
-
...ALWAYS_INCLUDED.map((r) => `- ${r}`)
|
|
23588
|
-
];
|
|
23589
|
-
return lines.join("\n");
|
|
23590
|
-
}
|
|
23591
|
-
|
|
23592
23540
|
// src/app/agent/core/prompt/model_info.ts
|
|
23593
23541
|
var KNOWLEDGE_CUTOFFS = [
|
|
23594
23542
|
{ match: "claude-sonnet-4-6", cutoff: "August 2025" },
|
|
@@ -23811,16 +23759,6 @@ function isAutoMemoryEnabled() {
|
|
|
23811
23759
|
}
|
|
23812
23760
|
|
|
23813
23761
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
23814
|
-
var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
|
|
23815
|
-
"spawn_agent",
|
|
23816
|
-
"wait_agent",
|
|
23817
|
-
"list_agents",
|
|
23818
|
-
"send_message",
|
|
23819
|
-
"list_mailbox_messages",
|
|
23820
|
-
"poll_mailbox",
|
|
23821
|
-
"signal_mailbox",
|
|
23822
|
-
"kill_agent"
|
|
23823
|
-
]);
|
|
23824
23762
|
function getNodeVersion() {
|
|
23825
23763
|
return process.version;
|
|
23826
23764
|
}
|
|
@@ -24167,14 +24105,6 @@ ${formatFactorAiAppContextSummary(appContext)}
|
|
|
24167
24105
|
if (modelInfo) prompt += `
|
|
24168
24106
|
|
|
24169
24107
|
${modelInfo}`;
|
|
24170
|
-
const allToolNames = options?.availableToolNames ?? [];
|
|
24171
|
-
if (allToolNames.length > 0) {
|
|
24172
|
-
const visibleTools = isSandbox ? allToolNames : allToolNames.filter((n) => !INTERNAL_TOOLS.has(n));
|
|
24173
|
-
const guidance = buildToolGuidanceSection(visibleTools);
|
|
24174
|
-
if (guidance) prompt += `
|
|
24175
|
-
|
|
24176
|
-
${guidance}`;
|
|
24177
|
-
}
|
|
24178
24108
|
prompt += `
|
|
24179
24109
|
|
|
24180
24110
|
${buildSystemRemindersSection()}`;
|
|
@@ -25279,6 +25209,9 @@ var ToolCallNormalizer = class {
|
|
|
25279
25209
|
}
|
|
25280
25210
|
/**
|
|
25281
25211
|
* Valida se um tool call normalizado Γ© vΓ‘lido
|
|
25212
|
+
* ValidaΓ§Γ£o dupla:
|
|
25213
|
+
* 1. JSON dos argumentos Γ© vΓ‘lido
|
|
25214
|
+
* 2. A ferramenta existe no catΓ‘logo de ferramentas nativas
|
|
25282
25215
|
*/
|
|
25283
25216
|
static isValidToolCall(call) {
|
|
25284
25217
|
if (!(call.id && call.type === "function" && call.function?.name && typeof call.function.arguments === "string")) {
|
|
@@ -25286,10 +25219,14 @@ var ToolCallNormalizer = class {
|
|
|
25286
25219
|
}
|
|
25287
25220
|
try {
|
|
25288
25221
|
JSON.parse(call.function.arguments);
|
|
25289
|
-
return true;
|
|
25290
25222
|
} catch {
|
|
25291
25223
|
return false;
|
|
25292
25224
|
}
|
|
25225
|
+
const toolMetadata = getNativeToolMetadata(call.function.name);
|
|
25226
|
+
if (!toolMetadata) {
|
|
25227
|
+
return false;
|
|
25228
|
+
}
|
|
25229
|
+
return true;
|
|
25293
25230
|
}
|
|
25294
25231
|
};
|
|
25295
25232
|
|
|
@@ -25336,7 +25273,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25336
25273
|
}
|
|
25337
25274
|
return { allowed: false, reason: `No permission rule found for file "${filePath}".` };
|
|
25338
25275
|
}
|
|
25339
|
-
function decideToolExecution(toolName, args) {
|
|
25276
|
+
function decideToolExecution(toolName, args, sessionId) {
|
|
25340
25277
|
const policy = getSandboxPolicy();
|
|
25341
25278
|
const metadata = getNativeToolMetadata(toolName);
|
|
25342
25279
|
if (!metadata) {
|
|
@@ -25347,6 +25284,15 @@ function decideToolExecution(toolName, args) {
|
|
|
25347
25284
|
reason: "Unknown tool metadata; require confirmation by default."
|
|
25348
25285
|
};
|
|
25349
25286
|
}
|
|
25287
|
+
if (sessionId && getEffectivePermissionMode(sessionId) === "full") {
|
|
25288
|
+
return {
|
|
25289
|
+
toolName,
|
|
25290
|
+
metadata,
|
|
25291
|
+
autoApprove: true,
|
|
25292
|
+
requiresConfirmation: false,
|
|
25293
|
+
reason: "Full permission mode: ALL tools auto-approved. User explicitly enabled unrestricted mode."
|
|
25294
|
+
};
|
|
25295
|
+
}
|
|
25350
25296
|
const ruleDecision = permissionRulesEngine.checkPermission(toolName, args);
|
|
25351
25297
|
if (ruleDecision === "deny") {
|
|
25352
25298
|
return {
|
|
@@ -25619,10 +25565,10 @@ var PARALLEL_SAFE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
25619
25565
|
"read_mcp_resource",
|
|
25620
25566
|
"todo"
|
|
25621
25567
|
]);
|
|
25622
|
-
function toolEligibleForParallelRead(toolName) {
|
|
25568
|
+
function toolEligibleForParallelRead(toolName, sessionId) {
|
|
25623
25569
|
const name = String(toolName || "").trim();
|
|
25624
25570
|
if (!name || !PARALLEL_SAFE_TOOL_NAMES.has(name)) return false;
|
|
25625
|
-
if (!decideToolExecution(name).autoApprove) return false;
|
|
25571
|
+
if (!decideToolExecution(name, void 0, sessionId).autoApprove) return false;
|
|
25626
25572
|
const meta = getNativeToolMetadata(name);
|
|
25627
25573
|
return meta?.riskLevel === "safe";
|
|
25628
25574
|
}
|
|
@@ -25928,7 +25874,7 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
25928
25874
|
}
|
|
25929
25875
|
/** PolΓtica mostrada na UI: combina metadata base com auto-approve efectivo (incl. permission_ml). */
|
|
25930
25876
|
buildToolPolicyForUi(toolName, toolArgs) {
|
|
25931
|
-
const base = decideToolExecution(toolName);
|
|
25877
|
+
const base = decideToolExecution(toolName, void 0, this.sessionId);
|
|
25932
25878
|
const argsStr = typeof toolArgs === "string" ? toolArgs : JSON.stringify(toolArgs ?? {});
|
|
25933
25879
|
const synthetic = { function: { name: toolName, arguments: argsStr } };
|
|
25934
25880
|
const auto = effectiveToolAutoApprove(synthetic, this.sessionId, { logClassifier: false });
|
|
@@ -25988,10 +25934,6 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
25988
25934
|
role: "system",
|
|
25989
25935
|
content: `[SYSTEM] Tool "${toolName}" is not found in the agent's available tools. Please use only tools that are listed in your tool catalog.`
|
|
25990
25936
|
});
|
|
25991
|
-
this.eventBus.emit("backend_message", {
|
|
25992
|
-
type: "error",
|
|
25993
|
-
message: `Tool "${toolName}" does not exist in the agent catalog.`
|
|
25994
|
-
});
|
|
25995
25937
|
this.persistSession();
|
|
25996
25938
|
return true;
|
|
25997
25939
|
}
|
|
@@ -26178,10 +26120,6 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
26178
26120
|
role: "system",
|
|
26179
26121
|
content: `[SYSTEM] Tool "${toolName}" is not found in the agent's available tools. Please use only tools that are listed in your tool catalog.`
|
|
26180
26122
|
});
|
|
26181
|
-
this.eventBus.emit("backend_message", {
|
|
26182
|
-
type: "error",
|
|
26183
|
-
message: `Tool "${toolName}" does not exist in the agent catalog.`
|
|
26184
|
-
});
|
|
26185
26123
|
this.persistSession();
|
|
26186
26124
|
return true;
|
|
26187
26125
|
}
|
|
@@ -26330,13 +26268,13 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
26330
26268
|
let i = 0;
|
|
26331
26269
|
while (i < calls.length && shouldContinue && !this.isInterrupted) {
|
|
26332
26270
|
const name = calls[i].function.name;
|
|
26333
|
-
if (!toolEligibleForParallelRead(name)) {
|
|
26271
|
+
if (!toolEligibleForParallelRead(name, this.sessionId)) {
|
|
26334
26272
|
shouldContinue = await this.executeApprovedToolInvocation(calls[i], decisionData);
|
|
26335
26273
|
i += 1;
|
|
26336
26274
|
continue;
|
|
26337
26275
|
}
|
|
26338
26276
|
let j = i;
|
|
26339
|
-
while (j < calls.length && toolEligibleForParallelRead(calls[j].function.name)) {
|
|
26277
|
+
while (j < calls.length && toolEligibleForParallelRead(calls[j].function.name, this.sessionId)) {
|
|
26340
26278
|
j += 1;
|
|
26341
26279
|
}
|
|
26342
26280
|
const slice = calls.slice(i, j);
|
|
@@ -26624,7 +26562,7 @@ ${editData.error.display}`;
|
|
|
26624
26562
|
}
|
|
26625
26563
|
if (confirmationToolCalls.length > 0) {
|
|
26626
26564
|
const toolToCall = confirmationToolCalls[0];
|
|
26627
|
-
const decision = decideToolExecution(toolToCall.function.name);
|
|
26565
|
+
const decision = decideToolExecution(toolToCall.function.name, void 0, this.sessionId);
|
|
26628
26566
|
const toolName = toolToCall.function.name;
|
|
26629
26567
|
let previewContent;
|
|
26630
26568
|
if (toolName === "edit_tool") {
|
|
@@ -26699,7 +26637,7 @@ ${editData.error.display}`;
|
|
|
26699
26637
|
}
|
|
26700
26638
|
if (confirmationToolCalls.length > 0) {
|
|
26701
26639
|
const toolToCall = confirmationToolCalls[0];
|
|
26702
|
-
const decision = decideToolExecution(toolToCall.function.name);
|
|
26640
|
+
const decision = decideToolExecution(toolToCall.function.name, void 0, this.sessionId);
|
|
26703
26641
|
const toolName = toolToCall.function.name;
|
|
26704
26642
|
let previewContent;
|
|
26705
26643
|
if (toolName === "edit_tool") {
|
|
@@ -27647,7 +27585,7 @@ var BaseLLMSubAgent = class {
|
|
|
27647
27585
|
break;
|
|
27648
27586
|
}
|
|
27649
27587
|
if (message2.tool_calls) {
|
|
27650
|
-
const decision = decideToolExecution(message2.tool_calls[0].function.name);
|
|
27588
|
+
const decision = decideToolExecution(message2.tool_calls[0].function.name, void 0, `${this.id}`);
|
|
27651
27589
|
if (!decision.autoApprove) {
|
|
27652
27590
|
this.emitEvent("error", {
|
|
27653
27591
|
message: `Subagent tool "${message2.tool_calls[0].function.name}" requires confirmation outside sandbox mode.`
|
|
@@ -27771,7 +27709,7 @@ ${editData.error.display}`;
|
|
|
27771
27709
|
}
|
|
27772
27710
|
}
|
|
27773
27711
|
if (message2.tool_calls) {
|
|
27774
|
-
const decision = decideToolExecution(message2.tool_calls[0].function.name);
|
|
27712
|
+
const decision = decideToolExecution(message2.tool_calls[0].function.name, void 0, `${this.id}`);
|
|
27775
27713
|
if (!decision.autoApprove) {
|
|
27776
27714
|
this.emitEvent("error", {
|
|
27777
27715
|
message: `Subagent tool "${message2.tool_calls[0].function.name}" requires confirmation outside sandbox mode.`
|
|
@@ -27821,7 +27759,7 @@ ${editData.error.display}`;
|
|
|
27821
27759
|
tool_name: toolName,
|
|
27822
27760
|
arguments: toolArgs,
|
|
27823
27761
|
preview: previewContent,
|
|
27824
|
-
tool_policy: decideToolExecution(toolName)
|
|
27762
|
+
tool_policy: decideToolExecution(toolName, void 0, `${this.id}`)
|
|
27825
27763
|
});
|
|
27826
27764
|
try {
|
|
27827
27765
|
if (this.isInterrupted) {
|
|
@@ -36484,10 +36422,10 @@ var runWorktreeSet = (_agentRef, _path, _setIsProcessing, _markTurnStarted) => {
|
|
|
36484
36422
|
var runPermissionSet = (_agentRef, mode, _setIsProcessing, _markTurnStarted, sessionId) => {
|
|
36485
36423
|
if (mode === "full") {
|
|
36486
36424
|
if (sessionId) {
|
|
36487
|
-
setSessionPermissionMode(sessionId, "
|
|
36425
|
+
setSessionPermissionMode(sessionId, "full");
|
|
36488
36426
|
return usageBox("Permission", "Set to full");
|
|
36489
36427
|
} else {
|
|
36490
|
-
setRuntimeConfig({ permissionMode: "
|
|
36428
|
+
setRuntimeConfig({ permissionMode: "full", sandboxEnabled: false });
|
|
36491
36429
|
return usageBox("Permission", "Set to full (global)");
|
|
36492
36430
|
}
|
|
36493
36431
|
}
|