@shuyhere/bb-agent 0.0.15 → 0.0.17
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 +82 -23
- package/README.md +9 -9
- package/package.json +1 -1
- package/scripts/postinstall.js +112 -32
package/CHANGELOG.md
CHANGED
|
@@ -5,27 +5,83 @@ 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
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.0.17] - 2026-04-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- added the reusable `bb-monitor` backend crate and wired request metrics, session usage summaries, and cache provenance tracking through it
|
|
15
|
+
- added a dedicated under-input TUI cache monitor that shows cache source plus average and latest request hit rate
|
|
16
|
+
- added a profile-aware auth store with saved timestamps, active-profile tracking, and richer provider auth summaries in `/model`
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `/model` now supports choosing auth source/profile as part of model selection when a provider has multiple usable auth options
|
|
21
|
+
- `/login` now exposes concrete auth-option choosers instead of only coarse method picks, including switching among saved/env-backed auth and starting new provider logins from the same flow
|
|
22
|
+
- providers that support it can now keep multiple saved OAuth profiles and multiple saved API-key profiles side-by-side for the same provider, with safe labels to distinguish saved keys
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- OpenAI GPT-5 API-key requests now use the Responses API when tools/reasoning are involved instead of failing against chat completions with `reasoning_effort` errors
|
|
27
|
+
- `/session` now reports the live session auth override when auth was explicitly selected in-session instead of falling back to default provider resolution
|
|
28
|
+
- auth/profile menus now disambiguate saved API-key profiles even when labels would otherwise look too similar
|
|
29
|
+
|
|
30
|
+
### Improved
|
|
31
|
+
|
|
32
|
+
- footer, `/session`, `/login`, and `/model` now present provider auth state more consistently, including explicit auth method/source/account details and safer saved-profile switching flows
|
|
33
|
+
- cache monitor visibility and provider-metric provenance are clearer across session summaries, request tracking, and the TUI monitor line
|
|
34
|
+
|
|
35
|
+
## [0.0.16] - 2026-04-15
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- added `bb setup browser`, including platform-specific guidance and optional shell-profile persistence for configuring `BB_BROWSER`
|
|
40
|
+
- added a dedicated release-notes draft for `v0.0.16` under `docs/release-notes-0.0.16.md`
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
|
|
44
|
+
- user-facing terminology now consistently uses **TUI** instead of legacy `fullscreen` wording, including CLI/help/docs text and internal module/type naming
|
|
45
|
+
- markdown code blocks and bash tool previews in the TUI now render as raw fenced blocks for easier copying and pasting
|
|
46
|
+
- tool availability, advertised schemas, transcript validation, and tool execution now follow a shared architecture with a single CLI `ToolRegistry`, centralized provider transcript repair, explicit tool lifecycle phases, lifecycle hook events, and mutation-aware scheduling for real tool execution
|
|
47
|
+
- release builds and npm installs now prefer stripped/compressed native binaries, reducing download size and improving install/update behavior
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- `browser_fetch` now gives actionable missing-browser diagnostics and setup guidance instead of failing opaquely when no local browser is installed
|
|
52
|
+
- TUI footer context usage no longer gets stuck at misleading values like `0.0%/272k (auto)` after resume/rebuild/fork paths
|
|
53
|
+
- queued prompt previews no longer hide compaction/local-action status, and fast local actions no longer flash meaningless `0ms` / `0.0s` timing
|
|
54
|
+
- failed or interrupted tool calls no longer wedge later prompts with provider-side `No tool output found ...` errors; transcript repair and lifecycle finalization now guarantee a valid follow-up turn state
|
|
55
|
+
- join-timeout warnings no longer make an active TUI turn look finished before the runner actually completes
|
|
56
|
+
- clean `bb-cli` builds no longer emit dead-code warnings from the new tool registry surface, and secret-bearing auth/token structs now redact sensitive fields in debug output instead of exposing raw credentials
|
|
57
|
+
|
|
58
|
+
### Improved
|
|
59
|
+
|
|
60
|
+
- ongoing Rust audit cleanup significantly reduced boolean-heavy APIs, overexposed state, and hotspot modules across `bb-cli`, `bb-core`, `bb-tools`, `bb-session`, `bb-tui`, `bb-provider`, `bb-plugin-host`, and `bb-hooks`, with expanded focused regression coverage throughout
|
|
61
|
+
- npm install now prefers compressed `.gz` GitHub release assets when available, falling back to the legacy uncompressed binaries for older releases
|
|
62
|
+
- release builds now strip debug info before publishing, substantially reducing native binary download size for npm installs and updates
|
|
63
|
+
|
|
8
64
|
## [0.0.15] - 2026-04-12
|
|
9
65
|
|
|
10
66
|
### Fixed
|
|
11
67
|
|
|
12
|
-
-
|
|
68
|
+
- tui bash output now streams live stdout/stderr and keeps running, finished, historical, and expanded/collapsed tool blocks visually consistent with width-aware tail previews and elapsed/took footer hints
|
|
13
69
|
- bash tool titles now skip shell prelude lines like `set -e`, show configured timeout values in the UI, and validate invalid timeout arguments instead of accepting zero or non-finite values
|
|
14
70
|
- fixed the session getting stuck after interrupted or failed tool calls by flushing synthetic tool results before later prompts, preventing follow-up turns from failing with missing tool output
|
|
15
71
|
- Codex tool-call request handling is more robust: tool calls are serialized sequentially, orphan tool results are sanitized out of requests, and streamed/done function-call events are deduplicated more safely
|
|
16
72
|
- plain URLs and hyphenated text no longer trigger accidental markdown horizontal-rule rendering while explicit markdown rules and setext headings still render correctly
|
|
17
|
-
-
|
|
73
|
+
- tui resume menu handling now awaits the async resume path correctly instead of dropping back through the synchronous menu flow
|
|
18
74
|
|
|
19
75
|
### Added
|
|
20
76
|
|
|
21
|
-
- regression coverage for interrupted tool-call recovery, Codex orphan-tool sanitization, builtin tool-name normalization,
|
|
77
|
+
- regression coverage for interrupted tool-call recovery, Codex orphan-tool sanitization, builtin tool-name normalization, tui bash rendering consistency, and bash timeout validation/visibility
|
|
22
78
|
|
|
23
79
|
## [0.0.14] - 2026-04-12
|
|
24
80
|
|
|
25
81
|
### Added
|
|
26
82
|
|
|
27
|
-
-
|
|
28
|
-
- `/settings` in
|
|
83
|
+
- tui now supports extension-driven workflows and structured slash-command outcomes, including menus, hidden dispatches, and richer command result handling
|
|
84
|
+
- `/settings` in tui now exposes compaction controls for `Auto-compact`, `Reserve tokens`, and `Keep recent tokens`
|
|
29
85
|
- skills can now be listed, disabled, and re-enabled from the CLI without deleting their installed files
|
|
30
86
|
- startup model selection now prefers configured provider/model defaults more consistently, with better OpenAI startup fallback behavior
|
|
31
87
|
- added a parity test script against installed pi compaction logic to keep BB token accounting aligned with upstream behavior
|
|
@@ -33,39 +89,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
33
89
|
### Fixed
|
|
34
90
|
|
|
35
91
|
- session resume now restores the prior model and thinking level instead of starting with mismatched runtime defaults
|
|
36
|
-
-
|
|
92
|
+
- tui/TUI terminal rendering now sanitizes terminal control text more reliably and avoids ANSI leakage into the UI
|
|
37
93
|
- 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
|
|
38
|
-
-
|
|
94
|
+
- tui compaction behavior and status reporting are more consistent after auto-compaction and manual compaction events, and local tui actions now show an animated elapsed-time status while they run
|
|
39
95
|
|
|
40
96
|
### Changed
|
|
41
97
|
|
|
42
|
-
-
|
|
98
|
+
- tui extension workflows and session compaction support are now merged into the main interaction path on `master`
|
|
43
99
|
|
|
44
100
|
## [0.0.13] - 2026-04-09
|
|
45
101
|
|
|
46
102
|
### Added
|
|
47
103
|
|
|
48
|
-
-
|
|
104
|
+
- tui 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
|
|
49
105
|
- 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
|
|
50
106
|
|
|
51
107
|
### Fixed
|
|
52
108
|
|
|
53
|
-
-
|
|
109
|
+
- tui clipboard image attach no longer leaks helper `true` / `false` output or stray follow-up paste text into the input block
|
|
54
110
|
- 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
|
|
55
|
-
- rebuilt
|
|
111
|
+
- rebuilt tui session transcripts now preserve user image attachment markers instead of silently dropping image blocks
|
|
56
112
|
- managed `bb-clipboard-*.png` temp files are now cleaned up after removal or ingestion instead of lingering in `/tmp`
|
|
57
|
-
- the
|
|
58
|
-
-
|
|
113
|
+
- the tui input block now hides raw `@file` tokens when the corresponding attachment chip is already shown, preventing duplicated `@file` text in the editor
|
|
114
|
+
- tui tool-header regression tests now match the intended live bash-header rendering and running-dot animation behavior
|
|
59
115
|
|
|
60
116
|
## [0.0.12] - 2026-04-06
|
|
61
117
|
|
|
62
118
|
### Fixed
|
|
63
119
|
|
|
64
|
-
- direct `@image` references in print mode and
|
|
120
|
+
- direct `@image` references in print mode and tui now attach real image inputs instead of falling back to UTF-8 read warnings
|
|
65
121
|
- `@path with spaces` parsing now correctly keeps the full file path before trailing prompt text, including whole-message forms
|
|
66
122
|
- 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
|
|
67
|
-
-
|
|
68
|
-
- the
|
|
123
|
+
- tui `@` folder navigation now keeps the completion menu open when you select a directory and immediately shows the next level, including directories with spaces
|
|
124
|
+
- the tui 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
|
|
69
125
|
|
|
70
126
|
### Changed
|
|
71
127
|
|
|
@@ -75,9 +131,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
75
131
|
|
|
76
132
|
### Added
|
|
77
133
|
|
|
78
|
-
- startup update notices in the
|
|
79
|
-
- read-tool line ranges in
|
|
80
|
-
-
|
|
134
|
+
- startup update notices in the tui transcript are now highlighted so available updates stand out clearly during startup
|
|
135
|
+
- read-tool line ranges in tui tool activity now highlight the requested span, so values like `2148-2267/5006` stand out while the model is using tools
|
|
136
|
+
- tui footer and `/session` info now show the active execution posture so safety vs yolo is visible during a run
|
|
81
137
|
|
|
82
138
|
### Improved
|
|
83
139
|
|
|
@@ -96,7 +152,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
96
152
|
|
|
97
153
|
- npm install now uses a longer timeout, retries release-binary downloads, and reports real download errors instead of incorrectly saying no matching prebuilt binary exists
|
|
98
154
|
- npm install now shows progress logs during native binary download and verification so first-time installs on macOS/Linux are less confusing
|
|
99
|
-
-
|
|
155
|
+
- tui `/login` provider-family status now correctly shows OpenAI OAuth state after ChatGPT login instead of incorrectly showing the API key path as not authenticated
|
|
100
156
|
|
|
101
157
|
### Changed
|
|
102
158
|
|
|
@@ -112,9 +168,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
112
168
|
|
|
113
169
|
### Fixed
|
|
114
170
|
|
|
115
|
-
-
|
|
171
|
+
- tui paste in iTerm2/SSH no longer corrupts the input area after paste
|
|
116
172
|
- pasted file and image paths are normalized more reliably, including quoted paths and `file://` URLs
|
|
117
|
-
-
|
|
173
|
+
- tui prompt submission now expands `@file` references consistently
|
|
118
174
|
- running tool timers continue updating after `TurnEnd` while tools are still executing
|
|
119
175
|
- sub-second tool durations now display as `ms` instead of `0.0s`
|
|
120
176
|
- startup Skills/Prompts/Extensions note now only appears at startup or explicit `/reload`
|
|
@@ -122,7 +178,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
122
178
|
|
|
123
179
|
### Changed
|
|
124
180
|
|
|
125
|
-
-
|
|
181
|
+
- tui `Ctrl+V` now falls back to clipboard text when no clipboard image is available
|
|
126
182
|
- `@` autocomplete now inserts quoted file references when paths contain spaces
|
|
127
183
|
|
|
128
184
|
## [0.0.8] - 2026-04-06
|
|
@@ -143,6 +199,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
143
199
|
|
|
144
200
|
- latest published package includes the post-0.0.7 startup, auth, model-default, and update-notice improvements
|
|
145
201
|
|
|
202
|
+
[0.0.17]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.17
|
|
203
|
+
[0.0.16]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.16
|
|
204
|
+
[0.0.15]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.15
|
|
146
205
|
[0.0.14]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.14
|
|
147
206
|
[0.0.13]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.13
|
|
148
207
|
[0.0.12]: https://github.com/shuyhere/bb-agent/releases/tag/v0.0.12
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> BB means Bridge Baby in Death Stranding. I named this project that way because while building it, I was also enjoying Death Stranding and loved the idea of connecting everyone together.
|
|
6
6
|
|
|
7
|
-
A Rust-native AI coding agent for the terminal — featuring a
|
|
7
|
+
A Rust-native AI coding agent for the terminal — featuring a TUI, multi-provider support, tool use, session persistence, branching, extensions, and skills.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -17,7 +17,7 @@ npm install -g @shuyhere/bb-agent
|
|
|
17
17
|
npm install downloads a small wrapper package first, then fetches the matching native BB-Agent binary from the GitHub release for your platform.
|
|
18
18
|
|
|
19
19
|
What to expect:
|
|
20
|
-
- first install can take a bit because npm downloads
|
|
20
|
+
- first install can take a bit because npm downloads a compressed native binary, expands it locally, and verifies it
|
|
21
21
|
- the installer now prints progress and retry information while downloading
|
|
22
22
|
- after install, run `bb`
|
|
23
23
|
|
|
@@ -68,7 +68,7 @@ Inside the TUI, run:
|
|
|
68
68
|
/login
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
This opens the provider picker and auth flow directly in the
|
|
71
|
+
This opens the provider picker and auth flow directly in the TUI.
|
|
72
72
|
|
|
73
73
|
If you prefer, you can also log in from a normal terminal:
|
|
74
74
|
|
|
@@ -81,12 +81,12 @@ bb login google # Login to Google (API key)
|
|
|
81
81
|
|
|
82
82
|
Or set environment variables: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY`, etc.
|
|
83
83
|
|
|
84
|
-
That's it! Run `bb` to launch the
|
|
84
|
+
That's it! Run `bb` to launch the interactive TUI. Type your prompt and press Enter.
|
|
85
85
|
|
|
86
86
|
### More ways to use `bb`
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
|
-
bb # Launch the
|
|
89
|
+
bb # Launch the TUI
|
|
90
90
|
bb "Explain this codebase" # TUI with an initial prompt
|
|
91
91
|
bb -p "What is 2+2?" # Print mode (non-interactive, pipe-friendly)
|
|
92
92
|
bb -c # Continue your last session
|
|
@@ -98,7 +98,7 @@ bb --list-models # List all available models
|
|
|
98
98
|
|
|
99
99
|
## Features
|
|
100
100
|
|
|
101
|
-
- **
|
|
101
|
+
- **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
104
|
- **Safety and yolo execution modes** — default safety posture restricts built-in `write` and `edit` to the active workspace; yolo removes that guard
|
|
@@ -165,7 +165,7 @@ BB-Agent uses layered configuration:
|
|
|
165
165
|
|
|
166
166
|
### Execution Modes
|
|
167
167
|
|
|
168
|
-
BB-Agent exposes the active permission posture in
|
|
168
|
+
BB-Agent exposes the active permission posture in the TUI and `/session`.
|
|
169
169
|
|
|
170
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
171
|
- `yolo` is the opt-in less-restrictive mode.
|
|
@@ -202,14 +202,14 @@ Example:
|
|
|
202
202
|
| `bb-provider` | Model/provider integrations and streaming |
|
|
203
203
|
| `bb-hooks` | Hook event types for extensions |
|
|
204
204
|
| `bb-plugin-host` | Plugin discovery and host runtime |
|
|
205
|
-
| `bb-tui` | Terminal UI components and
|
|
205
|
+
| `bb-tui` | Terminal UI components and the interactive TUI experience |
|
|
206
206
|
| `bb-cli` | The `bb` command-line application |
|
|
207
207
|
|
|
208
208
|
## Troubleshooting
|
|
209
209
|
|
|
210
210
|
### Terminal & Font Compatibility
|
|
211
211
|
|
|
212
|
-
BB-Agent uses Unicode glyphs and ANSI color in the
|
|
212
|
+
BB-Agent uses Unicode glyphs and ANSI color in the TUI. For the best visual experience, use a modern terminal and a Unicode-capable monospace font such as:
|
|
213
213
|
|
|
214
214
|
- JetBrains Mono
|
|
215
215
|
- SF Mono / Menlo
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -8,6 +8,8 @@ const path = require("path");
|
|
|
8
8
|
const os = require("os");
|
|
9
9
|
const https = require("https");
|
|
10
10
|
const http = require("http");
|
|
11
|
+
const zlib = require("zlib");
|
|
12
|
+
const { pipeline } = require("stream/promises");
|
|
11
13
|
|
|
12
14
|
const packageJson = require("../package.json");
|
|
13
15
|
const BINARY_RELEASE_TAG = `v${packageJson.version}`;
|
|
@@ -51,6 +53,20 @@ function assetNameForTarget(target) {
|
|
|
51
53
|
return isWindows() ? `bb-${target}.exe` : `bb-${target}`;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
function assetCandidatesForTarget(target) {
|
|
57
|
+
const assetName = assetNameForTarget(target);
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
assetName: `${assetName}.gz`,
|
|
61
|
+
compressed: true,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
assetName,
|
|
65
|
+
compressed: false,
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
function logLine(message = "") {
|
|
55
71
|
try {
|
|
56
72
|
process.stderr.write(`${message}\n`);
|
|
@@ -189,8 +205,14 @@ function copyBinary(src, dest) {
|
|
|
189
205
|
function installFromVerifiedCache(target) {
|
|
190
206
|
const cached = cacheBinaryPath(target);
|
|
191
207
|
const meta = loadCacheMetadata(target);
|
|
192
|
-
if (!fs.existsSync(cached) || !meta)
|
|
193
|
-
|
|
208
|
+
if (!fs.existsSync(cached) || !meta) {
|
|
209
|
+
logLine(`No verified cached BB-Agent binary found for ${target} yet.`);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (meta.version !== packageJson.version || meta.target !== target) {
|
|
213
|
+
logLine(`Ignoring stale cache metadata for ${target}; expected ${packageJson.version}.`);
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
194
216
|
|
|
195
217
|
let stat;
|
|
196
218
|
try {
|
|
@@ -199,9 +221,13 @@ function installFromVerifiedCache(target) {
|
|
|
199
221
|
return false;
|
|
200
222
|
}
|
|
201
223
|
if (!stat.isFile() || stat.size <= 0) return false;
|
|
202
|
-
if (meta.size && stat.size !== meta.size)
|
|
224
|
+
if (meta.size && stat.size !== meta.size) {
|
|
225
|
+
logLine(`Cached BB-Agent binary for ${target} changed size; re-validating it.`);
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
203
228
|
|
|
204
229
|
logLine(`Using cached BB-Agent binary for ${target} (${formatBytes(stat.size)}).`);
|
|
230
|
+
logLine(`Installing cached binary to ${nativeBinaryPath()}.`);
|
|
205
231
|
copyBinary(cached, nativeBinaryPath());
|
|
206
232
|
return true;
|
|
207
233
|
}
|
|
@@ -230,8 +256,9 @@ function maybeRepairCache(target) {
|
|
|
230
256
|
}
|
|
231
257
|
}
|
|
232
258
|
|
|
233
|
-
logLine(`Checking cached BB-Agent binary for ${target}...`);
|
|
259
|
+
logLine(`Checking cached BB-Agent binary for ${target} at ${cached}...`);
|
|
234
260
|
if (!binaryMatchesCurrentVersion(cached)) {
|
|
261
|
+
logLine(`Cached binary for ${target} is stale or invalid; removing cached copy.`);
|
|
235
262
|
removeIfExists(cached);
|
|
236
263
|
removeIfExists(cacheMetadataPath(target));
|
|
237
264
|
return false;
|
|
@@ -370,7 +397,7 @@ function requestBinary(url, dest, redirects = 0) {
|
|
|
370
397
|
}
|
|
371
398
|
|
|
372
399
|
function verifyBinary(binaryPath) {
|
|
373
|
-
logLine(
|
|
400
|
+
logLine(`Verifying downloaded binary at ${binaryPath}...`);
|
|
374
401
|
const version = binaryVersion(binaryPath);
|
|
375
402
|
if (!version) {
|
|
376
403
|
return {
|
|
@@ -387,13 +414,31 @@ function verifyBinary(binaryPath) {
|
|
|
387
414
|
return { ok: true, version };
|
|
388
415
|
}
|
|
389
416
|
|
|
417
|
+
async function expandCompressedBinary(src, dest) {
|
|
418
|
+
logLine(`Decompressing downloaded BB-Agent binary from ${path.basename(src)}...`);
|
|
419
|
+
ensureParentDir(dest);
|
|
420
|
+
try {
|
|
421
|
+
await pipeline(fs.createReadStream(src), zlib.createGunzip(), fs.createWriteStream(dest));
|
|
422
|
+
const stat = fs.statSync(dest);
|
|
423
|
+
logLine(`Expanded compressed asset to ${formatBytes(stat.size)}.`);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
removeIfExists(dest);
|
|
426
|
+
throw makeDownloadError("decompress", `Failed to decompress ${path.basename(src)}: ${err.message}`);
|
|
427
|
+
} finally {
|
|
428
|
+
removeIfExists(src);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
390
432
|
async function tryDownloadPrebuilt(target) {
|
|
391
|
-
const
|
|
392
|
-
const url = `https://github.com/${REPO}/releases/download/${BINARY_RELEASE_TAG}/${assetName}`;
|
|
433
|
+
const assetCandidates = assetCandidatesForTarget(target);
|
|
393
434
|
|
|
394
435
|
fs.mkdirSync(NATIVE_DIR, { recursive: true });
|
|
395
436
|
const dest = nativeBinaryPath();
|
|
396
437
|
const tmpDest = `${dest}.tmp`;
|
|
438
|
+
const cachePath = cacheBinaryPath(target);
|
|
439
|
+
|
|
440
|
+
logLine(`Native binary destination: ${dest}`);
|
|
441
|
+
logLine(`Binary cache path: ${cachePath}`);
|
|
397
442
|
|
|
398
443
|
if (installFromVerifiedCache(target)) {
|
|
399
444
|
logLine("✓ BB-Agent binary installed successfully from cache.");
|
|
@@ -412,37 +457,70 @@ async function tryDownloadPrebuilt(target) {
|
|
|
412
457
|
`Downloading BB-Agent ${BINARY_RELEASE_TAG} for ${target} (attempt ${attempt}/${MAX_DOWNLOAD_ATTEMPTS})...`
|
|
413
458
|
);
|
|
414
459
|
logLine("This may take a little while on first install because npm downloads the native binary from the GitHub release.");
|
|
415
|
-
removeIfExists(tmpDest);
|
|
416
|
-
await requestBinary(url, tmpDest, 0);
|
|
417
|
-
if (!isWindows()) {
|
|
418
|
-
fs.chmodSync(tmpDest, 0o755);
|
|
419
|
-
}
|
|
420
460
|
|
|
421
|
-
|
|
422
|
-
|
|
461
|
+
let missingCompressedAsset = false;
|
|
462
|
+
for (const asset of assetCandidates) {
|
|
463
|
+
const url = `https://github.com/${REPO}/releases/download/${BINARY_RELEASE_TAG}/${asset.assetName}`;
|
|
464
|
+
const downloadDest = asset.compressed ? `${tmpDest}.gz` : tmpDest;
|
|
465
|
+
|
|
423
466
|
removeIfExists(tmpDest);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
467
|
+
removeIfExists(`${tmpDest}.gz`);
|
|
468
|
+
|
|
469
|
+
try {
|
|
470
|
+
if (asset.compressed) {
|
|
471
|
+
logLine(`Trying compressed release asset ${asset.assetName} first for a faster download.`);
|
|
472
|
+
} else {
|
|
473
|
+
logLine(`Trying uncompressed release asset ${asset.assetName}.`);
|
|
474
|
+
}
|
|
475
|
+
await requestBinary(url, downloadDest, 0);
|
|
476
|
+
if (asset.compressed) {
|
|
477
|
+
await expandCompressedBinary(downloadDest, tmpDest);
|
|
478
|
+
}
|
|
479
|
+
if (!isWindows()) {
|
|
480
|
+
fs.chmodSync(tmpDest, 0o755);
|
|
481
|
+
}
|
|
430
482
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
483
|
+
const verified = verifyBinary(tmpDest);
|
|
484
|
+
if (!verified.ok) {
|
|
485
|
+
removeIfExists(tmpDest);
|
|
486
|
+
return {
|
|
487
|
+
ok: false,
|
|
488
|
+
kind: "verify",
|
|
489
|
+
message: `Downloaded binary could not run: ${verified.message}`,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
fs.renameSync(tmpDest, dest);
|
|
494
|
+
logLine(`Installed BB-Agent binary to ${dest}.`);
|
|
495
|
+
refreshCacheFromExistingBinary(target, dest);
|
|
496
|
+
logLine(`Cached verified BB-Agent binary for future installs at ${cachePath}.`);
|
|
497
|
+
logLine("✓ BB-Agent binary installed successfully.");
|
|
498
|
+
return { ok: true, source: "download" };
|
|
499
|
+
} catch (err) {
|
|
500
|
+
lastError = err;
|
|
501
|
+
removeIfExists(tmpDest);
|
|
502
|
+
removeIfExists(`${tmpDest}.gz`);
|
|
503
|
+
if (err.kind === "not-found") {
|
|
504
|
+
if (asset.compressed) {
|
|
505
|
+
missingCompressedAsset = true;
|
|
506
|
+
logLine(`Compressed asset ${asset.assetName} not found; falling back to the uncompressed release binary.`);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
ok: false,
|
|
511
|
+
kind: "not-found",
|
|
512
|
+
message: missingCompressedAsset
|
|
513
|
+
? `No release asset named ${asset.assetName} or ${assetCandidates[0].assetName} was found for ${BINARY_RELEASE_TAG}.`
|
|
514
|
+
: `No release asset named ${asset.assetName} was found for ${BINARY_RELEASE_TAG}.`,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
throw err;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
436
520
|
} catch (err) {
|
|
437
521
|
lastError = err;
|
|
438
522
|
removeIfExists(tmpDest);
|
|
439
|
-
|
|
440
|
-
return {
|
|
441
|
-
ok: false,
|
|
442
|
-
kind: "not-found",
|
|
443
|
-
message: `No release asset named ${assetName} was found for ${BINARY_RELEASE_TAG}.`,
|
|
444
|
-
};
|
|
445
|
-
}
|
|
523
|
+
removeIfExists(`${tmpDest}.gz`);
|
|
446
524
|
if (attempt < MAX_DOWNLOAD_ATTEMPTS) {
|
|
447
525
|
logLine(`Download failed (${err.message}). Retrying...`);
|
|
448
526
|
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
|
|
@@ -501,7 +579,9 @@ async function main() {
|
|
|
501
579
|
const target = getTarget();
|
|
502
580
|
const platform = `${os.platform()}-${os.arch()}`;
|
|
503
581
|
|
|
582
|
+
logLine(`Resolved install platform: ${platform}.`);
|
|
504
583
|
if (target) {
|
|
584
|
+
logLine(`Resolved native target: ${target}.`);
|
|
505
585
|
const result = await tryDownloadPrebuilt(target);
|
|
506
586
|
if (result.ok) {
|
|
507
587
|
return;
|