@shuyhere/bb-agent 0.0.11 → 0.0.14

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/CHANGELOG.md CHANGED
@@ -5,18 +5,75 @@ All notable changes to BB-Agent will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.14] - 2026-04-12
9
+
10
+ ### Added
11
+
12
+ - fullscreen now supports extension-driven workflows and structured slash-command outcomes, including menus, hidden dispatches, and richer command result handling
13
+ - `/settings` in fullscreen now exposes compaction controls for `Auto-compact`, `Reserve tokens`, and `Keep recent tokens`
14
+ - skills can now be listed, disabled, and re-enabled from the CLI without deleting their installed files
15
+ - startup model selection now prefers configured provider/model defaults more consistently, with better OpenAI startup fallback behavior
16
+ - added a parity test script against installed pi compaction logic to keep BB token accounting aligned with upstream behavior
17
+
18
+ ### Fixed
19
+
20
+ - session resume now restores the prior model and thinking level instead of starting with mismatched runtime defaults
21
+ - fullscreen/TUI terminal rendering now sanitizes terminal control text more reliably and avoids ANSI leakage into the UI
22
+ - auto-compaction token estimation now matches pi more closely by using the last successful assistant usage plus trailing estimates, using ceil-based token heuristics, computing `tokens_before` from rebuilt context instead of raw payload size, and ignoring assistant usage from before the latest compaction boundary
23
+ - fullscreen compaction behavior and status reporting are more consistent after auto-compaction and manual compaction events, and local fullscreen actions now show an animated elapsed-time status while they run
24
+
25
+ ### Changed
26
+
27
+ - fullscreen extension workflows and session compaction support are now merged into the main interaction path on `master`
28
+
29
+ ## [0.0.13] - 2026-04-09
30
+
31
+ ### Added
32
+
33
+ - fullscreen screenshot and image clipboard paste now works on the normal paste path, with macOS clipboard fallbacks and Codex image preservation so pasted images reach image-capable models correctly
34
+ - model registry metadata now tracks image input capability, making `/models` truthful about image support and allowing runtime warnings when users attach images to text-only models
35
+
36
+ ### Fixed
37
+
38
+ - fullscreen clipboard image attach no longer leaks helper `true` / `false` output or stray follow-up paste text into the input block
39
+ - attached image chips can now be removed with `Backspace`, image-only prompts can be submitted, and optimistic user messages keep attachment chip previews in the transcript
40
+ - rebuilt fullscreen session transcripts now preserve user image attachment markers instead of silently dropping image blocks
41
+ - managed `bb-clipboard-*.png` temp files are now cleaned up after removal or ingestion instead of lingering in `/tmp`
42
+ - the fullscreen input block now hides raw `@file` tokens when the corresponding attachment chip is already shown, preventing duplicated `@file` text in the editor
43
+ - fullscreen tool-header regression tests now match the intended live bash-header rendering and running-dot animation behavior
44
+
45
+ ## [0.0.12] - 2026-04-06
46
+
47
+ ### Fixed
48
+
49
+ - direct `@image` references in print mode and fullscreen now attach real image inputs instead of falling back to UTF-8 read warnings
50
+ - `@path with spaces` parsing now correctly keeps the full file path before trailing prompt text, including whole-message forms
51
+ - image tool results are now preserved through provider conversion so models can actually see images returned by tools instead of responding as if no image was provided
52
+ - fullscreen `@` folder navigation now keeps the completion menu open when you select a directory and immediately shows the next level, including directories with spaces
53
+ - the fullscreen input block now shows attached files as `[name, sizeKB]`, keeps those chips visible, and places the cursor below them so typing starts after the attachments
54
+
55
+ ### Changed
56
+
57
+ - binary office/document inputs (`pdf`, `docx`, `pptx`, `xlsx`) now degrade to format-aware metadata notes instead of misleading invalid-UTF-8 errors
58
+
8
59
  ## [0.0.11] - 2026-04-07
9
60
 
10
61
  ### Added
11
62
 
12
63
  - startup update notices in the fullscreen transcript are now highlighted so available updates stand out clearly during startup
13
64
  - read-tool line ranges in fullscreen tool activity now highlight the requested span, so values like `2148-2267/5006` stand out while the model is using tools
65
+ - fullscreen footer and `/session` info now show the active execution posture so safety vs yolo is visible during a run
14
66
 
15
67
  ### Improved
16
68
 
17
69
  - npm install now caches verified native binaries by version/platform and reuses them on reinstall instead of re-downloading every time
18
70
  - npm install now shows more frequent download progress with transfer rate information to make slow installs easier to understand
19
71
  - npm install now avoids unnecessary re-verification on cache hits, making repeat installs faster
72
+ - safety mode now restricts built-in `write` and `edit` to the active workspace, while `yolo` keeps unrestricted file mutation behavior
73
+
74
+ ### Migration
75
+
76
+ - `execution_mode` now defaults to `safety`; set `"execution_mode": "yolo"` if your workflow intentionally edits files outside the current workspace
20
77
 
21
78
  ## [0.0.10] - 2026-04-07
22
79
 
@@ -71,6 +128,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
71
128
 
72
129
  - latest published package includes the post-0.0.7 startup, auth, model-default, and update-notice improvements
73
130
 
131
+ [0.0.14]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.14
132
+ [0.0.13]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.13
133
+ [0.0.12]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.12
74
134
  [0.0.11]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.11
75
135
  [0.0.10]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.10
76
136
  [0.0.9]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.9
package/README.md CHANGED
@@ -101,6 +101,7 @@ bb --list-models # List all available models
101
101
  - **Fullscreen TUI** — rich terminal interface with streaming output, markdown rendering, syntax highlighting
102
102
  - **Multi-provider** — Anthropic (Claude), OpenAI, Google (Gemini), Groq, xAI, OpenRouter, and custom OpenAI-compatible endpoints
103
103
  - **Built-in tools** — `read`, `write`, `edit`, `bash`, `find`, `grep`, `ls`, `web_search`, `web_fetch`, `browser_fetch`
104
+ - **Safety and yolo execution modes** — default safety posture restricts built-in `write` and `edit` to the active workspace; yolo removes that guard
104
105
  - **Session persistence** — SQLite-backed sessions with branching, forking, and tree navigation
105
106
  - **Extensions** — JS/TS plugin system for custom tools, commands, and hooks
106
107
  - **Skills** — markdown-based instruction files that auto-load contextual knowledge
@@ -144,9 +145,11 @@ BB-Agent uses layered configuration:
144
145
 
145
146
  ```json
146
147
  {
148
+ "execution_mode": "safety",
147
149
  "default_model": "claude-sonnet-4-20250514",
148
150
  "default_provider": "anthropic",
149
151
  "default_thinking": "medium",
152
+ "execution_mode": "safety",
150
153
  "models": [
151
154
  {
152
155
  "id": "my-local-model",
@@ -160,6 +163,21 @@ BB-Agent uses layered configuration:
160
163
  }
161
164
  ```
162
165
 
166
+ ### Execution Modes
167
+
168
+ BB-Agent exposes the active permission posture in fullscreen and `/session`.
169
+
170
+ - `safety` is the default. Built-in `write` and `edit` stay inside the current workspace, and bash commands use the safer approval/sandboxed posture.
171
+ - `yolo` is the opt-in less-restrictive mode.
172
+
173
+ Example:
174
+
175
+ ```json
176
+ {
177
+ "execution_mode": "yolo"
178
+ }
179
+ ```
180
+
163
181
  ## Keyboard Shortcuts
164
182
 
165
183
  | Key | Action |
@@ -228,7 +246,6 @@ Or set this in `~/.bb-agent/settings.json`:
228
246
  - [Development Guide](docs/development.md) — build from source, dev workflow, project structure, debugging
229
247
  - [Contributing](CONTRIBUTING.md) — code style, PR process
230
248
  - [Changelog](CHANGELOG.md) — release history
231
- - [Security](SECURITY.md) — vulnerability reporting, security model
232
249
 
233
250
  ## Development
234
251
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuyhere/bb-agent",
3
- "version": "0.0.11",
3
+ "version": "0.0.14",
4
4
  "description": "BB-Agent — a Rust-native AI coding agent for the terminal",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,141 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import * as pi from '/home/shuyhere/projects/tako/node_modules/@mariozechner/pi-coding-agent/dist/core/compaction/compaction.js';
4
+
5
+ const settings = { enabled: true, reserveTokens: 16384, keepRecentTokens: 20000 };
6
+
7
+ function bbEstimateContextTokens(messages) {
8
+ function calc(usage) {
9
+ return usage.total_tokens > 0
10
+ ? usage.total_tokens
11
+ : usage.input + usage.output + usage.cache_read + usage.cache_write;
12
+ }
13
+
14
+ function estimateText(text) {
15
+ return Math.ceil(text.length / 4);
16
+ }
17
+
18
+ function estimateMessage(message) {
19
+ switch (message.role) {
20
+ case 'user':
21
+ return message.content.reduce((sum, block) => sum + (block.type === 'text' ? estimateText(block.text) : 1200), 0);
22
+ case 'assistant':
23
+ return message.content.reduce((sum, block) => {
24
+ if (block.type === 'text') return sum + estimateText(block.text);
25
+ if (block.type === 'thinking') return sum + estimateText(block.thinking);
26
+ if (block.type === 'toolCall') return sum + estimateText(block.name) + estimateText(JSON.stringify(block.arguments ?? {}));
27
+ return sum;
28
+ }, 0);
29
+ case 'toolResult':
30
+ case 'custom':
31
+ return message.content.reduce((sum, block) => sum + (block.type === 'text' ? estimateText(block.text) : 1200), 0);
32
+ case 'bashExecution':
33
+ return estimateText(message.command) + estimateText(message.output);
34
+ case 'branchSummary':
35
+ case 'compactionSummary':
36
+ return estimateText(message.summary);
37
+ default:
38
+ return 0;
39
+ }
40
+ }
41
+
42
+ const lastUsageIndex = [...messages.keys()].reverse().find((i) => {
43
+ const m = messages[i];
44
+ return m.role === 'assistant' && m.stopReason !== 'aborted' && m.stopReason !== 'error' && calc(m.usage) > 0;
45
+ });
46
+
47
+ if (lastUsageIndex == null) {
48
+ const trailingTokens = messages.reduce((sum, m) => sum + estimateMessage(m), 0);
49
+ return { tokens: trailingTokens, usageTokens: 0, trailingTokens, lastUsageIndex: null };
50
+ }
51
+
52
+ const usageTokens = calc(messages[lastUsageIndex].usage);
53
+ const trailingTokens = messages.slice(lastUsageIndex + 1).reduce((sum, m) => sum + estimateMessage(m), 0);
54
+ return { tokens: usageTokens + trailingTokens, usageTokens, trailingTokens, lastUsageIndex };
55
+ }
56
+
57
+ test('bb estimator matches installed pi on shared fixtures', () => {
58
+ const fixtures = [
59
+ [
60
+ {
61
+ role: 'assistant',
62
+ content: [{ type: 'text', text: 'done' }],
63
+ provider: 'test',
64
+ model: 'test',
65
+ usage: { input: 100, output: 20, cacheRead: 10, cacheWrite: 5, totalTokens: 0 },
66
+ stopReason: 'stop',
67
+ timestamp: Date.now(),
68
+ },
69
+ { role: 'user', content: [{ type: 'text', text: '12345678' }], timestamp: Date.now() },
70
+ ],
71
+ [
72
+ {
73
+ role: 'assistant',
74
+ content: [{ type: 'text', text: 'aborted' }],
75
+ provider: 'test',
76
+ model: 'test',
77
+ usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 500 },
78
+ stopReason: 'aborted',
79
+ timestamp: Date.now(),
80
+ },
81
+ { role: 'user', content: [{ type: 'text', text: '12345678' }], timestamp: Date.now() },
82
+ ],
83
+ [
84
+ {
85
+ role: 'assistant',
86
+ content: [
87
+ { type: 'text', text: 'hello' },
88
+ { type: 'thinking', thinking: 'reasoning text' },
89
+ { type: 'toolCall', id: '1', name: 'read', arguments: { path: 'src/main.rs' } },
90
+ ],
91
+ provider: 'test',
92
+ model: 'test',
93
+ usage: { input: 300, output: 40, cacheRead: 50, cacheWrite: 0, totalTokens: 0 },
94
+ stopReason: 'stop',
95
+ timestamp: Date.now(),
96
+ },
97
+ {
98
+ role: 'toolResult',
99
+ toolCallId: '1',
100
+ toolName: 'read',
101
+ content: [{ type: 'text', text: 'fn main() {}' }],
102
+ isError: false,
103
+ timestamp: Date.now(),
104
+ },
105
+ {
106
+ role: 'bashExecution',
107
+ command: 'ls -la',
108
+ output: 'file1\nfile2\n',
109
+ cancelled: false,
110
+ truncated: false,
111
+ timestamp: Date.now(),
112
+ },
113
+ ],
114
+ ];
115
+
116
+ for (const messages of fixtures) {
117
+ const piEstimate = pi.estimateContextTokens(messages);
118
+ const bbEstimate = bbEstimateContextTokens(
119
+ JSON.parse(
120
+ JSON.stringify(messages)
121
+ .replace(/cacheRead/g, 'cache_read')
122
+ .replace(/cacheWrite/g, 'cache_write')
123
+ .replace(/totalTokens/g, 'total_tokens')
124
+ .replace(/stopReason/g, 'stopReason')
125
+ )
126
+ );
127
+
128
+ assert.deepEqual(bbEstimate, {
129
+ tokens: piEstimate.tokens,
130
+ usageTokens: piEstimate.usageTokens,
131
+ trailingTokens: piEstimate.trailingTokens,
132
+ lastUsageIndex: piEstimate.lastUsageIndex,
133
+ });
134
+
135
+ const contextWindow = 128000;
136
+ assert.equal(
137
+ bbEstimate.tokens > contextWindow - settings.reserveTokens,
138
+ pi.shouldCompact(piEstimate.tokens, contextWindow, settings)
139
+ );
140
+ }
141
+ });