@nomad-e/bluma-cli 0.6.1 β 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 +201 -198
- 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
|
@@ -396,6 +396,118 @@ var init_sandbox_policy = __esm({
|
|
|
396
396
|
}
|
|
397
397
|
});
|
|
398
398
|
|
|
399
|
+
// src/app/agent/runtime/task_store.ts
|
|
400
|
+
import fs12 from "fs";
|
|
401
|
+
import path10 from "path";
|
|
402
|
+
function getStorePath() {
|
|
403
|
+
const policy = getSandboxPolicy();
|
|
404
|
+
return path10.join(policy.workspaceRoot, ".bluma", "task_state.json");
|
|
405
|
+
}
|
|
406
|
+
function getDefaultState() {
|
|
407
|
+
return {
|
|
408
|
+
tasks: [],
|
|
409
|
+
nextId: 1,
|
|
410
|
+
activeTask: null,
|
|
411
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function ensureLoaded() {
|
|
415
|
+
const storePath = getStorePath();
|
|
416
|
+
if (cache2 && cachePath === storePath) {
|
|
417
|
+
return cache2;
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
if (fs12.existsSync(storePath)) {
|
|
421
|
+
const raw = fs12.readFileSync(storePath, "utf-8");
|
|
422
|
+
const parsed = JSON.parse(raw);
|
|
423
|
+
cache2 = {
|
|
424
|
+
tasks: Array.isArray(parsed.tasks) ? parsed.tasks : [],
|
|
425
|
+
nextId: typeof parsed.nextId === "number" ? parsed.nextId : 1,
|
|
426
|
+
activeTask: parsed.activeTask ?? null,
|
|
427
|
+
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
428
|
+
};
|
|
429
|
+
cachePath = storePath;
|
|
430
|
+
return cache2;
|
|
431
|
+
}
|
|
432
|
+
} catch {
|
|
433
|
+
}
|
|
434
|
+
cache2 = getDefaultState();
|
|
435
|
+
cachePath = storePath;
|
|
436
|
+
return cache2;
|
|
437
|
+
}
|
|
438
|
+
function persist(state2) {
|
|
439
|
+
const storePath = getStorePath();
|
|
440
|
+
fs12.mkdirSync(path10.dirname(storePath), { recursive: true });
|
|
441
|
+
state2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
442
|
+
fs12.writeFileSync(storePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
443
|
+
cache2 = state2;
|
|
444
|
+
cachePath = storePath;
|
|
445
|
+
}
|
|
446
|
+
function updateTaskStore(mutator) {
|
|
447
|
+
const current = ensureLoaded();
|
|
448
|
+
const clone = {
|
|
449
|
+
tasks: current.tasks.map((task) => ({ ...task })),
|
|
450
|
+
nextId: current.nextId,
|
|
451
|
+
activeTask: current.activeTask ? { ...current.activeTask } : null,
|
|
452
|
+
updatedAt: current.updatedAt
|
|
453
|
+
};
|
|
454
|
+
mutator(clone);
|
|
455
|
+
persist(clone);
|
|
456
|
+
return clone;
|
|
457
|
+
}
|
|
458
|
+
function calculateTaskStats(tasks) {
|
|
459
|
+
const total = tasks.length;
|
|
460
|
+
const pending = tasks.filter((t) => t.status === "pending").length;
|
|
461
|
+
const inProgress = tasks.filter((t) => t.status === "in_progress").length;
|
|
462
|
+
const completed = tasks.filter((t) => t.status === "completed").length;
|
|
463
|
+
const progress = total > 0 ? Math.round(completed / total * 100) : 0;
|
|
464
|
+
return { total, pending, inProgress, completed, progress };
|
|
465
|
+
}
|
|
466
|
+
function buildTaskSnapshot() {
|
|
467
|
+
const state2 = ensureLoaded();
|
|
468
|
+
return {
|
|
469
|
+
tasks: state2.tasks.map((task) => ({ ...task })),
|
|
470
|
+
activeTask: state2.activeTask ? { ...state2.activeTask } : null,
|
|
471
|
+
stats: calculateTaskStats(state2.tasks),
|
|
472
|
+
updatedAt: state2.updatedAt
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function registerWorker(worker) {
|
|
476
|
+
activeWorkers.set(worker.id, worker);
|
|
477
|
+
}
|
|
478
|
+
function completeWorker(workerId) {
|
|
479
|
+
const worker = activeWorkers.get(workerId);
|
|
480
|
+
if (worker) {
|
|
481
|
+
worker.status = "completed";
|
|
482
|
+
worker.endTime = Date.now();
|
|
483
|
+
worker.progress = {
|
|
484
|
+
...worker.progress,
|
|
485
|
+
completed: true,
|
|
486
|
+
statusText: "Done"
|
|
487
|
+
};
|
|
488
|
+
worker.evictAfter = Date.now() + 3e4;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
function evictWorkerTask(workerId) {
|
|
492
|
+
activeWorkers.delete(workerId);
|
|
493
|
+
}
|
|
494
|
+
function getVisibleWorkers() {
|
|
495
|
+
const now2 = Date.now();
|
|
496
|
+
return Array.from(activeWorkers.values()).filter(
|
|
497
|
+
(w) => (w.evictAfter ?? Infinity) > now2
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
var cache2, cachePath, activeWorkers;
|
|
501
|
+
var init_task_store = __esm({
|
|
502
|
+
"src/app/agent/runtime/task_store.ts"() {
|
|
503
|
+
"use strict";
|
|
504
|
+
init_sandbox_policy();
|
|
505
|
+
cache2 = null;
|
|
506
|
+
cachePath = null;
|
|
507
|
+
activeWorkers = /* @__PURE__ */ new Map();
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
|
|
399
511
|
// src/app/agent/tools/CommandStatusTool/CommandStatusTool.ts
|
|
400
512
|
var CommandStatusTool_exports = {};
|
|
401
513
|
__export(CommandStatusTool_exports, {
|
|
@@ -1364,12 +1476,33 @@ async function spawnAgent(args) {
|
|
|
1364
1476
|
);
|
|
1365
1477
|
child.unref();
|
|
1366
1478
|
updateSession(sessionId, { pid: child.pid });
|
|
1367
|
-
|
|
1479
|
+
const workerTask = {
|
|
1480
|
+
id: sessionId,
|
|
1481
|
+
title,
|
|
1482
|
+
description: args.task,
|
|
1483
|
+
status: "running",
|
|
1484
|
+
task: args.task,
|
|
1485
|
+
progress: {
|
|
1486
|
+
step: 1,
|
|
1487
|
+
totalSteps: 10,
|
|
1488
|
+
currentTask: args.task?.slice(0, 100) || "Initializing...",
|
|
1489
|
+
statusText: "Running",
|
|
1490
|
+
lastActivity: Date.now()
|
|
1491
|
+
},
|
|
1492
|
+
startTime: Date.now(),
|
|
1493
|
+
endTime: void 0,
|
|
1494
|
+
evictAfter: void 0,
|
|
1495
|
+
agentType: args.agent_type || "general",
|
|
1496
|
+
parentSessionId: parentSessionId || void 0
|
|
1497
|
+
};
|
|
1498
|
+
registerWorker(workerTask);
|
|
1499
|
+
spawnLog.info("Worker spawned and registered", {
|
|
1368
1500
|
sessionId,
|
|
1369
1501
|
pid: child.pid,
|
|
1370
1502
|
title,
|
|
1371
1503
|
timeoutMs,
|
|
1372
|
-
sandbox: true
|
|
1504
|
+
sandbox: true,
|
|
1505
|
+
workerTaskId: sessionId
|
|
1373
1506
|
});
|
|
1374
1507
|
return {
|
|
1375
1508
|
success: true,
|
|
@@ -1411,6 +1544,19 @@ async function waitAgent(args) {
|
|
|
1411
1544
|
}
|
|
1412
1545
|
if (session.status !== "running") {
|
|
1413
1546
|
waitLog.info("Agent completed", { sessionId, status: session.status });
|
|
1547
|
+
if (session.status === "completed") {
|
|
1548
|
+
completeWorker(sessionId);
|
|
1549
|
+
} else if (session.status === "cancelled") {
|
|
1550
|
+
const workerTask = {
|
|
1551
|
+
id: sessionId,
|
|
1552
|
+
title: session.title,
|
|
1553
|
+
description: session.title,
|
|
1554
|
+
status: "killed",
|
|
1555
|
+
startTime: Date.now(),
|
|
1556
|
+
endTime: Date.now()
|
|
1557
|
+
};
|
|
1558
|
+
registerWorker(workerTask);
|
|
1559
|
+
}
|
|
1414
1560
|
return {
|
|
1415
1561
|
success: true,
|
|
1416
1562
|
completed: true,
|
|
@@ -1501,6 +1647,7 @@ var init_AgentCoordinationTool = __esm({
|
|
|
1501
1647
|
"src/app/agent/tools/AgentCoordinationTool/AgentCoordinationTool.ts"() {
|
|
1502
1648
|
"use strict";
|
|
1503
1649
|
init_session_registry();
|
|
1650
|
+
init_task_store();
|
|
1504
1651
|
init_logger();
|
|
1505
1652
|
init_errors();
|
|
1506
1653
|
init_worker_context();
|
|
@@ -15596,97 +15743,8 @@ async function countLines(args) {
|
|
|
15596
15743
|
}
|
|
15597
15744
|
}
|
|
15598
15745
|
|
|
15599
|
-
// src/app/agent/runtime/task_store.ts
|
|
15600
|
-
init_sandbox_policy();
|
|
15601
|
-
import fs12 from "fs";
|
|
15602
|
-
import path10 from "path";
|
|
15603
|
-
var cache2 = null;
|
|
15604
|
-
var cachePath = null;
|
|
15605
|
-
function getStorePath() {
|
|
15606
|
-
const policy = getSandboxPolicy();
|
|
15607
|
-
return path10.join(policy.workspaceRoot, ".bluma", "task_state.json");
|
|
15608
|
-
}
|
|
15609
|
-
function getDefaultState() {
|
|
15610
|
-
return {
|
|
15611
|
-
tasks: [],
|
|
15612
|
-
nextId: 1,
|
|
15613
|
-
activeTask: null,
|
|
15614
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
15615
|
-
};
|
|
15616
|
-
}
|
|
15617
|
-
function ensureLoaded() {
|
|
15618
|
-
const storePath = getStorePath();
|
|
15619
|
-
if (cache2 && cachePath === storePath) {
|
|
15620
|
-
return cache2;
|
|
15621
|
-
}
|
|
15622
|
-
try {
|
|
15623
|
-
if (fs12.existsSync(storePath)) {
|
|
15624
|
-
const raw = fs12.readFileSync(storePath, "utf-8");
|
|
15625
|
-
const parsed = JSON.parse(raw);
|
|
15626
|
-
cache2 = {
|
|
15627
|
-
tasks: Array.isArray(parsed.tasks) ? parsed.tasks : [],
|
|
15628
|
-
nextId: typeof parsed.nextId === "number" ? parsed.nextId : 1,
|
|
15629
|
-
activeTask: parsed.activeTask ?? null,
|
|
15630
|
-
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
15631
|
-
};
|
|
15632
|
-
cachePath = storePath;
|
|
15633
|
-
return cache2;
|
|
15634
|
-
}
|
|
15635
|
-
} catch {
|
|
15636
|
-
}
|
|
15637
|
-
cache2 = getDefaultState();
|
|
15638
|
-
cachePath = storePath;
|
|
15639
|
-
return cache2;
|
|
15640
|
-
}
|
|
15641
|
-
function persist(state2) {
|
|
15642
|
-
const storePath = getStorePath();
|
|
15643
|
-
fs12.mkdirSync(path10.dirname(storePath), { recursive: true });
|
|
15644
|
-
state2.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15645
|
-
fs12.writeFileSync(storePath, JSON.stringify(state2, null, 2), "utf-8");
|
|
15646
|
-
cache2 = state2;
|
|
15647
|
-
cachePath = storePath;
|
|
15648
|
-
}
|
|
15649
|
-
function updateTaskStore(mutator) {
|
|
15650
|
-
const current = ensureLoaded();
|
|
15651
|
-
const clone = {
|
|
15652
|
-
tasks: current.tasks.map((task) => ({ ...task })),
|
|
15653
|
-
nextId: current.nextId,
|
|
15654
|
-
activeTask: current.activeTask ? { ...current.activeTask } : null,
|
|
15655
|
-
updatedAt: current.updatedAt
|
|
15656
|
-
};
|
|
15657
|
-
mutator(clone);
|
|
15658
|
-
persist(clone);
|
|
15659
|
-
return clone;
|
|
15660
|
-
}
|
|
15661
|
-
function calculateTaskStats(tasks) {
|
|
15662
|
-
const total = tasks.length;
|
|
15663
|
-
const pending = tasks.filter((t) => t.status === "pending").length;
|
|
15664
|
-
const inProgress = tasks.filter((t) => t.status === "in_progress").length;
|
|
15665
|
-
const completed = tasks.filter((t) => t.status === "completed").length;
|
|
15666
|
-
const progress = total > 0 ? Math.round(completed / total * 100) : 0;
|
|
15667
|
-
return { total, pending, inProgress, completed, progress };
|
|
15668
|
-
}
|
|
15669
|
-
function buildTaskSnapshot() {
|
|
15670
|
-
const state2 = ensureLoaded();
|
|
15671
|
-
return {
|
|
15672
|
-
tasks: state2.tasks.map((task) => ({ ...task })),
|
|
15673
|
-
activeTask: state2.activeTask ? { ...state2.activeTask } : null,
|
|
15674
|
-
stats: calculateTaskStats(state2.tasks),
|
|
15675
|
-
updatedAt: state2.updatedAt
|
|
15676
|
-
};
|
|
15677
|
-
}
|
|
15678
|
-
var activeWorkers = /* @__PURE__ */ new Map();
|
|
15679
|
-
function evictWorkerTask(workerId) {
|
|
15680
|
-
activeWorkers.delete(workerId);
|
|
15681
|
-
}
|
|
15682
|
-
function getVisibleWorkers() {
|
|
15683
|
-
const now2 = Date.now();
|
|
15684
|
-
return Array.from(activeWorkers.values()).filter(
|
|
15685
|
-
(w) => (w.evictAfter ?? Infinity) > now2
|
|
15686
|
-
);
|
|
15687
|
-
}
|
|
15688
|
-
|
|
15689
15746
|
// src/app/agent/tools/TodoTool/TodoTool.ts
|
|
15747
|
+
init_task_store();
|
|
15690
15748
|
function validateDescription(desc) {
|
|
15691
15749
|
if (!desc || typeof desc !== "string") return "Description is required";
|
|
15692
15750
|
if (desc.trim().length === 0) return "Description cannot be empty";
|
|
@@ -16527,6 +16585,7 @@ init_CommandStatusTool();
|
|
|
16527
16585
|
|
|
16528
16586
|
// src/app/agent/tools/TaskBoundaryTool/TaskBoundaryTool.ts
|
|
16529
16587
|
init_sandbox_policy();
|
|
16588
|
+
init_task_store();
|
|
16530
16589
|
import path14 from "path";
|
|
16531
16590
|
import { promises as fs13 } from "fs";
|
|
16532
16591
|
var artifactsDir = null;
|
|
@@ -16558,31 +16617,26 @@ async function updateTaskFile(task) {
|
|
|
16558
16617
|
async function taskBoundary(args) {
|
|
16559
16618
|
try {
|
|
16560
16619
|
const { task_name, mode, task_status, task_summary } = args;
|
|
16620
|
+
const missingFields = [];
|
|
16561
16621
|
if (!task_name || typeof task_name !== "string") {
|
|
16562
|
-
|
|
16563
|
-
success: false,
|
|
16564
|
-
task_name: "",
|
|
16565
|
-
mode: "EXECUTION",
|
|
16566
|
-
status: "",
|
|
16567
|
-
message: "task_name is required"
|
|
16568
|
-
};
|
|
16622
|
+
missingFields.push("task_name");
|
|
16569
16623
|
}
|
|
16570
|
-
if (!["PLANNING", "EXECUTION", "VERIFICATION"].includes(mode)) {
|
|
16571
|
-
|
|
16572
|
-
success: false,
|
|
16573
|
-
task_name,
|
|
16574
|
-
mode: "EXECUTION",
|
|
16575
|
-
status: "",
|
|
16576
|
-
message: `Invalid mode: ${mode}. Must be PLANNING, EXECUTION, or VERIFICATION`
|
|
16577
|
-
};
|
|
16624
|
+
if (!mode || !["PLANNING", "EXECUTION", "VERIFICATION"].includes(mode)) {
|
|
16625
|
+
missingFields.push("mode");
|
|
16578
16626
|
}
|
|
16579
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) {
|
|
16580
16634
|
return {
|
|
16581
16635
|
success: false,
|
|
16582
|
-
task_name,
|
|
16583
|
-
mode,
|
|
16584
|
-
status: "",
|
|
16585
|
-
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`
|
|
16586
16640
|
};
|
|
16587
16641
|
}
|
|
16588
16642
|
const now2 = Date.now();
|
|
@@ -23483,53 +23537,6 @@ function disableCoordinatorMode() {
|
|
|
23483
23537
|
delete process.env.BLUMA_COORDINATOR_MODE;
|
|
23484
23538
|
}
|
|
23485
23539
|
|
|
23486
|
-
// src/app/agent/core/prompt/tool_guidance.ts
|
|
23487
|
-
var TOOL_GUIDANCE_RULES = [
|
|
23488
|
-
{
|
|
23489
|
-
toolName: "read_file_lines",
|
|
23490
|
-
guidance: "To read files use `read_file_lines` instead of cat, head, tail, or sed"
|
|
23491
|
-
},
|
|
23492
|
-
{
|
|
23493
|
-
toolName: "edit_tool",
|
|
23494
|
-
guidance: "To edit files use `edit_tool` instead of sed or awk"
|
|
23495
|
-
},
|
|
23496
|
-
{
|
|
23497
|
-
toolName: "file_write",
|
|
23498
|
-
guidance: "To create files use `file_write` instead of cat with heredoc or echo redirection"
|
|
23499
|
-
},
|
|
23500
|
-
{
|
|
23501
|
-
toolName: "grep_search",
|
|
23502
|
-
guidance: "To search file content use `grep_search` instead of grep or rg"
|
|
23503
|
-
},
|
|
23504
|
-
{
|
|
23505
|
-
toolName: "find_by_name",
|
|
23506
|
-
guidance: "To search for files use `find_by_name` instead of find or ls"
|
|
23507
|
-
},
|
|
23508
|
-
{
|
|
23509
|
-
toolName: "view_file_outline",
|
|
23510
|
-
guidance: "To understand file structure use `view_file_outline` instead of opening the whole file"
|
|
23511
|
-
}
|
|
23512
|
-
];
|
|
23513
|
-
var ALWAYS_INCLUDED = [
|
|
23514
|
-
"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.",
|
|
23515
|
-
"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.",
|
|
23516
|
-
"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."
|
|
23517
|
-
];
|
|
23518
|
-
function buildToolGuidanceSection(availableTools) {
|
|
23519
|
-
const toolSet = new Set(availableTools);
|
|
23520
|
-
const activeRules = TOOL_GUIDANCE_RULES.filter((rule) => toolSet.has(rule.toolName)).map((rule) => rule.guidance);
|
|
23521
|
-
if (activeRules.length === 0) {
|
|
23522
|
-
return "";
|
|
23523
|
-
}
|
|
23524
|
-
const lines = [
|
|
23525
|
-
"# Using your tools",
|
|
23526
|
-
"",
|
|
23527
|
-
...activeRules.map((r) => `- ${r}`),
|
|
23528
|
-
...ALWAYS_INCLUDED.map((r) => `- ${r}`)
|
|
23529
|
-
];
|
|
23530
|
-
return lines.join("\n");
|
|
23531
|
-
}
|
|
23532
|
-
|
|
23533
23540
|
// src/app/agent/core/prompt/model_info.ts
|
|
23534
23541
|
var KNOWLEDGE_CUTOFFS = [
|
|
23535
23542
|
{ match: "claude-sonnet-4-6", cutoff: "August 2025" },
|
|
@@ -23752,16 +23759,6 @@ function isAutoMemoryEnabled() {
|
|
|
23752
23759
|
}
|
|
23753
23760
|
|
|
23754
23761
|
// src/app/agent/core/prompt/prompt_builder.ts
|
|
23755
|
-
var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
|
|
23756
|
-
"spawn_agent",
|
|
23757
|
-
"wait_agent",
|
|
23758
|
-
"list_agents",
|
|
23759
|
-
"send_message",
|
|
23760
|
-
"list_mailbox_messages",
|
|
23761
|
-
"poll_mailbox",
|
|
23762
|
-
"signal_mailbox",
|
|
23763
|
-
"kill_agent"
|
|
23764
|
-
]);
|
|
23765
23762
|
function getNodeVersion() {
|
|
23766
23763
|
return process.version;
|
|
23767
23764
|
}
|
|
@@ -24108,14 +24105,6 @@ ${formatFactorAiAppContextSummary(appContext)}
|
|
|
24108
24105
|
if (modelInfo) prompt += `
|
|
24109
24106
|
|
|
24110
24107
|
${modelInfo}`;
|
|
24111
|
-
const allToolNames = options?.availableToolNames ?? [];
|
|
24112
|
-
if (allToolNames.length > 0) {
|
|
24113
|
-
const visibleTools = isSandbox ? allToolNames : allToolNames.filter((n) => !INTERNAL_TOOLS.has(n));
|
|
24114
|
-
const guidance = buildToolGuidanceSection(visibleTools);
|
|
24115
|
-
if (guidance) prompt += `
|
|
24116
|
-
|
|
24117
|
-
${guidance}`;
|
|
24118
|
-
}
|
|
24119
24108
|
prompt += `
|
|
24120
24109
|
|
|
24121
24110
|
${buildSystemRemindersSection()}`;
|
|
@@ -25220,6 +25209,9 @@ var ToolCallNormalizer = class {
|
|
|
25220
25209
|
}
|
|
25221
25210
|
/**
|
|
25222
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
|
|
25223
25215
|
*/
|
|
25224
25216
|
static isValidToolCall(call) {
|
|
25225
25217
|
if (!(call.id && call.type === "function" && call.function?.name && typeof call.function.arguments === "string")) {
|
|
@@ -25227,10 +25219,14 @@ var ToolCallNormalizer = class {
|
|
|
25227
25219
|
}
|
|
25228
25220
|
try {
|
|
25229
25221
|
JSON.parse(call.function.arguments);
|
|
25230
|
-
return true;
|
|
25231
25222
|
} catch {
|
|
25232
25223
|
return false;
|
|
25233
25224
|
}
|
|
25225
|
+
const toolMetadata = getNativeToolMetadata(call.function.name);
|
|
25226
|
+
if (!toolMetadata) {
|
|
25227
|
+
return false;
|
|
25228
|
+
}
|
|
25229
|
+
return true;
|
|
25234
25230
|
}
|
|
25235
25231
|
};
|
|
25236
25232
|
|
|
@@ -25277,7 +25273,7 @@ function checkFilePermissionRules(toolName, filePath, policy) {
|
|
|
25277
25273
|
}
|
|
25278
25274
|
return { allowed: false, reason: `No permission rule found for file "${filePath}".` };
|
|
25279
25275
|
}
|
|
25280
|
-
function decideToolExecution(toolName, args) {
|
|
25276
|
+
function decideToolExecution(toolName, args, sessionId) {
|
|
25281
25277
|
const policy = getSandboxPolicy();
|
|
25282
25278
|
const metadata = getNativeToolMetadata(toolName);
|
|
25283
25279
|
if (!metadata) {
|
|
@@ -25288,6 +25284,15 @@ function decideToolExecution(toolName, args) {
|
|
|
25288
25284
|
reason: "Unknown tool metadata; require confirmation by default."
|
|
25289
25285
|
};
|
|
25290
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
|
+
}
|
|
25291
25296
|
const ruleDecision = permissionRulesEngine.checkPermission(toolName, args);
|
|
25292
25297
|
if (ruleDecision === "deny") {
|
|
25293
25298
|
return {
|
|
@@ -25560,10 +25565,10 @@ var PARALLEL_SAFE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
25560
25565
|
"read_mcp_resource",
|
|
25561
25566
|
"todo"
|
|
25562
25567
|
]);
|
|
25563
|
-
function toolEligibleForParallelRead(toolName) {
|
|
25568
|
+
function toolEligibleForParallelRead(toolName, sessionId) {
|
|
25564
25569
|
const name = String(toolName || "").trim();
|
|
25565
25570
|
if (!name || !PARALLEL_SAFE_TOOL_NAMES.has(name)) return false;
|
|
25566
|
-
if (!decideToolExecution(name).autoApprove) return false;
|
|
25571
|
+
if (!decideToolExecution(name, void 0, sessionId).autoApprove) return false;
|
|
25567
25572
|
const meta = getNativeToolMetadata(name);
|
|
25568
25573
|
return meta?.riskLevel === "safe";
|
|
25569
25574
|
}
|
|
@@ -25869,7 +25874,7 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
25869
25874
|
}
|
|
25870
25875
|
/** PolΓtica mostrada na UI: combina metadata base com auto-approve efectivo (incl. permission_ml). */
|
|
25871
25876
|
buildToolPolicyForUi(toolName, toolArgs) {
|
|
25872
|
-
const base = decideToolExecution(toolName);
|
|
25877
|
+
const base = decideToolExecution(toolName, void 0, this.sessionId);
|
|
25873
25878
|
const argsStr = typeof toolArgs === "string" ? toolArgs : JSON.stringify(toolArgs ?? {});
|
|
25874
25879
|
const synthetic = { function: { name: toolName, arguments: argsStr } };
|
|
25875
25880
|
const auto = effectiveToolAutoApprove(synthetic, this.sessionId, { logClassifier: false });
|
|
@@ -25929,10 +25934,6 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
25929
25934
|
role: "system",
|
|
25930
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.`
|
|
25931
25936
|
});
|
|
25932
|
-
this.eventBus.emit("backend_message", {
|
|
25933
|
-
type: "error",
|
|
25934
|
-
message: `Tool "${toolName}" does not exist in the agent catalog.`
|
|
25935
|
-
});
|
|
25936
25937
|
this.persistSession();
|
|
25937
25938
|
return true;
|
|
25938
25939
|
}
|
|
@@ -26119,10 +26120,6 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
26119
26120
|
role: "system",
|
|
26120
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.`
|
|
26121
26122
|
});
|
|
26122
|
-
this.eventBus.emit("backend_message", {
|
|
26123
|
-
type: "error",
|
|
26124
|
-
message: `Tool "${toolName}" does not exist in the agent catalog.`
|
|
26125
|
-
});
|
|
26126
26123
|
this.persistSession();
|
|
26127
26124
|
return true;
|
|
26128
26125
|
}
|
|
@@ -26271,13 +26268,13 @@ var BluMaAgent = class _BluMaAgent {
|
|
|
26271
26268
|
let i = 0;
|
|
26272
26269
|
while (i < calls.length && shouldContinue && !this.isInterrupted) {
|
|
26273
26270
|
const name = calls[i].function.name;
|
|
26274
|
-
if (!toolEligibleForParallelRead(name)) {
|
|
26271
|
+
if (!toolEligibleForParallelRead(name, this.sessionId)) {
|
|
26275
26272
|
shouldContinue = await this.executeApprovedToolInvocation(calls[i], decisionData);
|
|
26276
26273
|
i += 1;
|
|
26277
26274
|
continue;
|
|
26278
26275
|
}
|
|
26279
26276
|
let j = i;
|
|
26280
|
-
while (j < calls.length && toolEligibleForParallelRead(calls[j].function.name)) {
|
|
26277
|
+
while (j < calls.length && toolEligibleForParallelRead(calls[j].function.name, this.sessionId)) {
|
|
26281
26278
|
j += 1;
|
|
26282
26279
|
}
|
|
26283
26280
|
const slice = calls.slice(i, j);
|
|
@@ -26565,7 +26562,7 @@ ${editData.error.display}`;
|
|
|
26565
26562
|
}
|
|
26566
26563
|
if (confirmationToolCalls.length > 0) {
|
|
26567
26564
|
const toolToCall = confirmationToolCalls[0];
|
|
26568
|
-
const decision = decideToolExecution(toolToCall.function.name);
|
|
26565
|
+
const decision = decideToolExecution(toolToCall.function.name, void 0, this.sessionId);
|
|
26569
26566
|
const toolName = toolToCall.function.name;
|
|
26570
26567
|
let previewContent;
|
|
26571
26568
|
if (toolName === "edit_tool") {
|
|
@@ -26640,7 +26637,7 @@ ${editData.error.display}`;
|
|
|
26640
26637
|
}
|
|
26641
26638
|
if (confirmationToolCalls.length > 0) {
|
|
26642
26639
|
const toolToCall = confirmationToolCalls[0];
|
|
26643
|
-
const decision = decideToolExecution(toolToCall.function.name);
|
|
26640
|
+
const decision = decideToolExecution(toolToCall.function.name, void 0, this.sessionId);
|
|
26644
26641
|
const toolName = toolToCall.function.name;
|
|
26645
26642
|
let previewContent;
|
|
26646
26643
|
if (toolName === "edit_tool") {
|
|
@@ -27588,7 +27585,7 @@ var BaseLLMSubAgent = class {
|
|
|
27588
27585
|
break;
|
|
27589
27586
|
}
|
|
27590
27587
|
if (message2.tool_calls) {
|
|
27591
|
-
const decision = decideToolExecution(message2.tool_calls[0].function.name);
|
|
27588
|
+
const decision = decideToolExecution(message2.tool_calls[0].function.name, void 0, `${this.id}`);
|
|
27592
27589
|
if (!decision.autoApprove) {
|
|
27593
27590
|
this.emitEvent("error", {
|
|
27594
27591
|
message: `Subagent tool "${message2.tool_calls[0].function.name}" requires confirmation outside sandbox mode.`
|
|
@@ -27712,7 +27709,7 @@ ${editData.error.display}`;
|
|
|
27712
27709
|
}
|
|
27713
27710
|
}
|
|
27714
27711
|
if (message2.tool_calls) {
|
|
27715
|
-
const decision = decideToolExecution(message2.tool_calls[0].function.name);
|
|
27712
|
+
const decision = decideToolExecution(message2.tool_calls[0].function.name, void 0, `${this.id}`);
|
|
27716
27713
|
if (!decision.autoApprove) {
|
|
27717
27714
|
this.emitEvent("error", {
|
|
27718
27715
|
message: `Subagent tool "${message2.tool_calls[0].function.name}" requires confirmation outside sandbox mode.`
|
|
@@ -27762,7 +27759,7 @@ ${editData.error.display}`;
|
|
|
27762
27759
|
tool_name: toolName,
|
|
27763
27760
|
arguments: toolArgs,
|
|
27764
27761
|
preview: previewContent,
|
|
27765
|
-
tool_policy: decideToolExecution(toolName)
|
|
27762
|
+
tool_policy: decideToolExecution(toolName, void 0, `${this.id}`)
|
|
27766
27763
|
});
|
|
27767
27764
|
try {
|
|
27768
27765
|
if (this.isInterrupted) {
|
|
@@ -35533,6 +35530,9 @@ function useTerminalSize() {
|
|
|
35533
35530
|
return size;
|
|
35534
35531
|
}
|
|
35535
35532
|
|
|
35533
|
+
// src/app/ui/components/CoordinatorTaskPanel.tsx
|
|
35534
|
+
init_task_store();
|
|
35535
|
+
|
|
35536
35536
|
// src/utils/format.ts
|
|
35537
35537
|
function formatDuration2(ms, options) {
|
|
35538
35538
|
if (ms < 6e4) {
|
|
@@ -36110,6 +36110,7 @@ var renderBridgePanel = () => {
|
|
|
36110
36110
|
};
|
|
36111
36111
|
|
|
36112
36112
|
// src/app/ui/components/slash-commands/renderers/taskRenderers.tsx
|
|
36113
|
+
init_task_store();
|
|
36113
36114
|
import { Fragment as Fragment13, jsx as jsx87, jsxs as jsxs72 } from "react/jsx-runtime";
|
|
36114
36115
|
var renderMasonSnapshot = () => {
|
|
36115
36116
|
const snapshot = buildTaskSnapshot();
|
|
@@ -36227,6 +36228,7 @@ var runTasksClear = (agentRef) => {
|
|
|
36227
36228
|
init_runtime_config();
|
|
36228
36229
|
init_sessionPermissionState();
|
|
36229
36230
|
init_sandbox_policy();
|
|
36231
|
+
init_task_store();
|
|
36230
36232
|
import { Fragment as Fragment14, jsx as jsx88, jsxs as jsxs73 } from "react/jsx-runtime";
|
|
36231
36233
|
var renderStatusline = () => {
|
|
36232
36234
|
const cfg = getRuntimeConfig();
|
|
@@ -36420,10 +36422,10 @@ var runWorktreeSet = (_agentRef, _path, _setIsProcessing, _markTurnStarted) => {
|
|
|
36420
36422
|
var runPermissionSet = (_agentRef, mode, _setIsProcessing, _markTurnStarted, sessionId) => {
|
|
36421
36423
|
if (mode === "full") {
|
|
36422
36424
|
if (sessionId) {
|
|
36423
|
-
setSessionPermissionMode(sessionId, "
|
|
36425
|
+
setSessionPermissionMode(sessionId, "full");
|
|
36424
36426
|
return usageBox("Permission", "Set to full");
|
|
36425
36427
|
} else {
|
|
36426
|
-
setRuntimeConfig({ permissionMode: "
|
|
36428
|
+
setRuntimeConfig({ permissionMode: "full", sandboxEnabled: false });
|
|
36427
36429
|
return usageBox("Permission", "Set to full (global)");
|
|
36428
36430
|
}
|
|
36429
36431
|
}
|
|
@@ -36474,6 +36476,7 @@ var renderPermissionsSnapshot = (sessionId) => {
|
|
|
36474
36476
|
};
|
|
36475
36477
|
|
|
36476
36478
|
// src/app/agent/runtime/diagnostics.ts
|
|
36479
|
+
init_task_store();
|
|
36477
36480
|
init_runtime_config();
|
|
36478
36481
|
init_sandbox_policy();
|
|
36479
36482
|
init_session_registry();
|