Commit Graph
73 Commits
Author SHA1 Message Date
925a9a7bf2 fix(buzz-acp): accept id-keyed config options when resolving model switch (#2795)
## Summary

Fixes #2794. Related: #2692.

`resolve_model_switch_method()` reads the `configId` key from each
`session/new` `configOptions` entry and skips entries that lack it.
`claude-agent-acp` (v0.61.0) keys its entries with `id`, so every
model-category entry was skipped, the desired model never matched, and
Claude Code sessions fell back to the CLI default from the user's
`~/.claude/settings.json`. The only trace was a `pool::model` WARN that
never reaches the per-agent log files.

This is the ACP-side half of the symptom reported in #2692. The open
desktop-side PRs (#2695, #2701, #2696) inject `ANTHROPIC_MODEL` at
spawn, which masks the problem for spawn-time selection but leaves the
config-option switch path broken.

## Changes

- `resolve_model_switch_method()` accepts either `configId` or `id` when
extracting the config id. The set request is unchanged: the ACP SDK
schema takes `configId` as the request param and the adapter resolves it
against its `id`-keyed entries, so only the read side needed fixing.
- Regression test with an `id`-keyed `configOptions` payload mirroring
the real adapter response (including `models: null`, so the unstable
fallback path cannot rescue the match).
- Doc comment on `extract_model_config_options()` notes the key drift.

## Testing

`cargo test -p buzz-acp --lib`: 599 passed, 0 failed. The new test fails
on main and passes with this change.

Verified against the real adapter: a stdio JSON-RPC probe of the bundled
`claude-agent-acp` 0.61.0 confirms `session/new` returns `id`-keyed
config options with `opus[1m]` present as a value, and the SDK's
`SetSessionConfigOptionRequest` schema accepts `{sessionId, configId,
value}` as sent by `session_set_config_option()`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: chillerno1 <gh.chiller@pm.me>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 02:27:44 +00:00
Will PflegerandGitHub f2fe3b63c2 feat(acp): title agent sessions from the agent and channel name (#3028)
ACP harnesses that name a session from the first text they receive all
land in the same place: every managed Buzz agent opens with the
identical `[Base] You are operating inside the Buzz platform…` framing,
so the harness session list shows a wall of indistinguishable rows.
Because sessions are keyed per channel, one agent active in several
channels produces several of them.

This sends the name out of band instead. `session/new` carries
`_meta.sessionTitle` with `Agent · #channel`, composed from the agent's
`display_name` (or its unique `name` handle) and the channel it is
serving. The prompt is untouched — no tokens spent, no perturbation of
the prompt contract, and nothing new for the desktop observer's section
parsing to handle.

The mechanism is harness-agnostic: Buzz sends the field on every ACP
`session/new` regardless of which harness is behind it, and adapters
that don't read it ignore it per spec.

## Inert until a consuming adapter ships

ACP adapters ignore `_meta` members they do not recognize, so against an
adapter with no reader a Buzz session gets no title and nothing else
changes. Three adapter halves consume it — Codex, Goose, and Claude Code
(linked below); this half and each reader are only useful together, and
each reader lands independently.

No version floor is added. `codex_adapter_is_outdated_with_path` already
gates codex-acp on major version `>= 1`
(`desktop/src-tauri/src/managed_agents/discovery.rs:1276-1284`) and this
feature needs nothing above that — an older adapter is not broken by the
extra member, it simply ignores it.

## What changes

**`crates/buzz-acp`** owns sanitization and composition.
`sanitize_session_title` collapses whitespace, drops control characters,
and caps at `SESSION_TITLE_MAX_CHARS` (80) by character, not byte, so a
multi-byte character cannot be split. `compose_session_title` truncates
only the channel part against that cap, so the agent name always
survives; when the agent name alone fills the cap the channel is dropped
rather than the name. `session_new_full` sets `_meta.sessionTitle` when
a title exists and omits `_meta` entirely when it does not, since an
adapter may distinguish an absent member from a null one.

**`desktop/src-tauri`** only resolves and exports.
`resolve_session_title` picks `display_name` or falls back to `name`,
and `spawn_agent_child` writes it to `BUZZ_ACP_SESSION_TITLE` — or
removes the variable when neither candidate yields anything printable.

DMs, unresolved channels, and heartbeat sessions get the bare agent name
with no channel suffix.

## Four properties that are easy to remove by accident

**Control characters are stripped at the desktop boundary, not in the
harness.** An interior NUL cannot cross the environment boundary at all
— `Command::env` fails the entire spawn rather than passing it through.
Deferring the strip to `buzz-acp` would let a corrupted display name
turn display chrome into a spawn failure. A display name that is *only*
control characters falls back to `name`.

**The title is hashed into `spawn_config_hash`.** Without it, renaming
an agent left the running process with a stale title and no restart
badge. The hash runs the same `resolve_session_title` the spawn writes,
and skips it when a user env override shadows `BUZZ_ACP_SESSION_TITLE` —
spawn writes the title *before* the layered user env, so the override is
what actually runs, and it already reaches the hash through
`descriptor.env`. Hashing the record-derived value under an override
would badge a rename that changes nothing.

**One channel resolve serves both consumers.**
`resolve_new_session_channel_context` returns `(is_dm, title_channel)`
from a single metadata lookup, feeding both the canvas block's DM check
and the title. `ChannelInfoResolver` caches only `Some`, so two
independent calls against an unresolvable channel pay the full
`fetch_channel_info` retry sequence twice — two timeouts plus a retry
delay each — directly in front of `session/new`, precisely when the
relay is already degraded.

**The `"unknown"` channel name is treated as absent.**
`fetch_channel_info` substitutes the literal `"unknown"` for a metadata
event with no `name` tag. Composing that sentinel would title every
unnamed channel `Agent · #unknown`, reintroducing the exact collision
the suffix exists to remove while naming a channel something it isn't.
The startup cache already refuses `channel_type == "unknown"` for the
same reason.

Closes #2334

Related — the adapter halves that consume `_meta.sessionTitle`:

-
[codex-acp#338](https://github.com/agentclientprotocol/codex-acp/pull/338)
— Codex
-
[aaif-goose/goose#10712](https://github.com/aaif-goose/goose/pull/10712)
— Goose
-
[claude-agent-acp#920](https://github.com/agentclientprotocol/claude-agent-acp/pull/920)
— Claude Code

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
2026-07-27 12:46:43 -04:00
18eef633d8 feat(git): use agent display name as git author name (#3040)
Agent commits were authored by a raw 63-character npub, which makes `git
log`, `git blame`, and GitHub's author column effectively unreadable.
This uses the agent's display name for `user.name` instead, while
leaving the pubkey where it does real work.

## What changes

`build_git_env` in `crates/buzz-dev-mcp/src/shim.rs` now reads
`BUZZ_ACP_DISPLAY_NAME`, sanitizes it, and uses the result as
`user.name`. When the variable is absent or unusable it falls back to
`info.npub` — byte-identical to today's behavior.

`user.email`, `user.signingkey`, and the whole credential/signing block
are untouched. The pubkey is what NIP-98 auth, NIP-GS signing, and
contributor matching key on, and it stays in the email verbatim.

`crates/buzz-acp/src/lib.rs` forwards the variable into the dev-mcp
server's declared env, mirroring the existing `BUZZ_AUTH_TAG` block. It
reads `std::env::var` directly rather than going through `Config`, so
the variable is picked up whenever the process has it.
`crates/buzz-agent/src/mcp.rs` adds one `PASSTHROUGH_ENV` entry so ACP
clients that spawn `buzz-agent` without declaring the variable on the
wire still propagate it.

## Why a dedicated variable

`BUZZ_ACP_DISPLAY_NAME` is its own contract rather than a reuse of the
ACP session title. Commits outlive sessions: a session title is
per-session UI chrome and may be composed downstream into `Agent ·
#channel`, and if that composed form ever reached the env var, git
attribution would change silently with no test able to catch it. Git
identity gets a variable whose contract is "bare agent display name,
never channel-qualified."

Nothing writes it yet — a one-line Desktop write lands as a follow-up.
Until then `std::env::var` returns `Err`, the npub fallback fires, and
behavior is byte-for-byte current `main`.

## Sanitizing

Strip control characters, Unicode format characters, and angle brackets;
collapse whitespace runs, trim, cap at 80 characters (by `chars()`, so a
multi-byte name is never split mid-UTF-8).

Angle brackets go because git drops them silently rather than erroring:
`Duncan <evil@x.com>` renders as `Duncan evil@x.com <hex@relay>`. It
forges nothing, but it reads as though it might.

The empty result also has to cover more than literal emptiness. git's
`ident.c` treats a set of characters as "crud" — stripped from both
ends, and fatal when a name is *nothing but* those characters:

```
$ git -c user.name=';;' commit -m t
fatal: name consists only of disallowed characters: ;;
```

Verified against git 2.54.0 by committing with each ASCII byte 32..=126
as the entire `user.name`: exactly space, `"`, `'`, `,`, `:`, `;`, `<`,
`>`, `\` abort, plus all control characters (the predicate is `c <=
32`). `.` is not crud in this version, despite older lore. Names that
merely *contain* crud are fine — `O'Brien` and `Smith, Jr.` both commit
cleanly — so the check is "at least one non-crud character survives,"
not "no crud present." Without it, a display name of `;;` or `""` would
abort every commit that agent makes.

## Unicode format characters

`char::is_control` covers only category `Cc`. Category `Cf` — zero-width
spaces and joiners, bidi embedding and override marks, invisible math
operators, tag characters — is neither control, nor whitespace, nor git
crud, so those characters survived every one of the checks above. A
display name of nothing but U+200B ZERO WIDTH SPACE therefore satisfied
"at least one non-crud character survives" and git accepted the commit
with a visually blank author:

```
# pre-fix, BUZZ_ACP_DISPLAY_NAME set to two U+200B
$ git log -1 --format='%an' | xxd -p
e2808be2808b0a
```

Embedded marks were the other half: a trailing U+202E RIGHT-TO-LEFT
OVERRIDE reorders everything after it, so a stored author line renders
as something other than what it stores — the same confusion class the
angle-bracket filtering exists to prevent.

`is_unicode_format` rejects the whole `Cf` category rather than the
known-bad marks, because the boundary that matters is "invisible or
reorders text", not "the codepoint someone thought of". The 21 ranges
come from the UCD's `DerivedGeneralCategory.txt` (17.0.0), cross-checked
against Python's `unicodedata` (16.0.0); both yield exactly the same
set. They are inlined as a `matches!` rather than pulling in a
Unicode-tables crate for one predicate, and a test asserts both
endpoints of every range plus the codepoints immediately outside them —
including U+2065, which sits inside the U+2060 block but is unassigned
rather than `Cf`.

Filtering happens inside the existing per-word filter, so a format-only
name collapses to empty and falls out through the same `None` → npub
path as a crud-only name. No new fallback logic. And because filtering
precedes truncation, invisible padding cannot eat the 80-character
budget.

## NUL is handled one layer up

An interior NUL is a sibling constraint that cannot be fixed here: it
makes `Command::env` fail the entire spawn before this code runs, so it
has to die at the writer. #3028 establishes that pattern for the session
title in `resolve_session_title` via `filter(|c| !c.is_control())`, and
the Desktop follow-up that writes `BUZZ_ACP_DISPLAY_NAME` inherits it.
The shim sanitizer is a second line of defense for values that arrive
from somewhere other than Desktop.

## Verified end to end

Driving the real `buzz-dev-mcp` binary over stdio MCP and committing
inside its shimmed environment:

```
# BUZZ_ACP_DISPLAY_NAME="Duncan Idaho"
Duncan Idaho <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0

# BUZZ_ACP_DISPLAY_NAME unset
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0

# BUZZ_ACP_DISPLAY_NAME=";;"  (crud-only; would otherwise be fatal)
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0

# BUZZ_ACP_DISPLAY_NAME=U+200B U+200B  (format-only; would otherwise be blank)
npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0

# BUZZ_ACP_DISPLAY_NAME="Duncan" + U+202E  (bidi override stripped)
Duncan <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0

# BUZZ_ACP_DISPLAY_NAME="Dun" + U+200B + "can"  (zero-width removed, word not split)
Duncan <dcfd242e...0f95@buzz.block.builderlab.xyz>
verify_exit=0
```

Signature verification passes in every case — the signing identity is
unchanged.

`Related: #3028` — it establishes the Desktop-side env plumbing this
builds beside; the one-line Desktop follow-up that writes
`BUZZ_ACP_DISPLAY_NAME` alongside the session title ships after it
merges. Not a dependency: with the variable absent, `std::env::var`
returns `Err` and the npub fallback keeps current behavior exactly.

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-27 12:28:32 -04:00
0a9c26ee8c fix(acp): dead-letter auth errors immediately with re-auth hint (#2751)
## Problem

Auth-class errors (expired OAuth token, HTTP 401) are non-retryable: the
token won't self-repair between attempts. Today, `PromptOutcome::Error`
for an application-class error falls into the generic `queue.requeue()`
path, burning up to 10 retry slots over a long backoff window before
dead-lettering. Will's canary run observed the 401 message being retried
repeatedly.

## Solution

Add `is_auth_error()` that classifies `AcpError::AgentError` messages
matching two narrow patterns observed in the field:

- `"Re-authenticate"` — emitted by the Claude CLI for expired OAuth
tokens
- `"API Error: 401"` — present in Claude/Codex HTTP-401 responses

Conservative matching is intentional: a false positive (misclassifying a
transient error as non-retryable) silently drops a user message, which
is worse than a false negative (extra retries on an auth error).

In `handle_prompt_result`, a new branch intercepts the failing batch
before `queue.requeue()` for auth-class errors and dead-letters
immediately, posting a user-visible notice to re-authenticate the CLI
(e.g. `claude /login` or `codex login`).

The transport/application split in `PromptOutcome::Error` is untouched —
this only changes batch fate after an application-class auth error.

## Tests

6 new tests in `error_outcome_emission_tests`:
1. `is_auth_error` matches `Re-authenticate` message
2. `is_auth_error` matches `API Error: 401` message
3. `is_auth_error` rejects other `AgentError` messages (usage credits,
etc.)
4. `is_auth_error` rejects transport errors (I/O, WriteTimeout)
5. Auth error dead-letters immediately — 0 pending channels after
`handle_prompt_result`
6. Non-auth application error still requeued — 1 pending channel after
`handle_prompt_result`

Full `cargo test -p buzz-acp`: 598/598 passing.

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-24 17:20:24 -04:00
thomaspblockandGitHub 9081ab0ec9 feat(desktop): make pull request reviews actionable (#2510) 2026-07-24 11:34:25 -04:00
5afa16157a fix(desktop): suppress Windows console flashes and reject WSL bash alias (#2587)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-23 18:27:40 -04:00
cb42c8d5b6 fix(acp): restrict DM turns to owner and verified siblings (#2591)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
2026-07-23 13:39:59 -07:00
+2 61cc738ee8 feat(desktop+acp): spawn a harness per (agent, community) pair at GUI startup — warm sockets, lazy LLM pool (#2122)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Matt Toohey <contact@matttoohey.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: npub1hwqy0rnujtl25dzmlhn8qwux4kr8sjhas3ugltx9j5dm5dwkp2dsqjhytw <bb80478e7c92feaa345bfde6703b86ad86784afd84788facc5951bba35d60a9b@buzz.block.builderlab.xyz>
2026-07-22 13:24:46 -07:00
9a788c7aee fix(acp): pace relay observer frames (6/s + 90/min, zero burst) (#2217)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
2026-07-21 09:57:23 -07:00
4de3e04119 fix(acp): honor relay rate limits and pace resubscribes on bad links (#2199)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1067mpdna4vy22u9eltmmhtdfw56kww6ve2aze025dtfm4pxg07nqztjfhm <7ebdb0b67dab08a570b9faf7bbada97535673b4ccaba2cbd546ad3ba84c87fa6@sprout-oss.stage.blox.sqprod.co>
2026-07-21 03:21:23 -04:00
cd6b573f8d fix(buzz-acp,buzz-agent): surface stall duration and fate (#2204)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-21 01:10:28 -04:00
Will PflegerandGitHub 0791fff8d2 chore(acp): strip stale finding-number references from comments (#2202) 2026-07-20 23:28:47 -04:00
Will PflegerandGitHub 0f86a608b9 fix(timeout): unified turn-timeout fix — cap inheritance, steer renewal, activity-aware requeue, LLM stall surfacing (#2175) 2026-07-20 18:20:57 -04:00
klopez4212andGitHub 2b0f5e9f80 Improve agent runtime settings (#2026) 2026-07-19 19:01:38 +00:00
e25ed00248 docs(buzz-acp): fold hard-earned operating learnings into base prompt (#2129)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
2026-07-19 14:05:17 -04:00
75069650a3 fix(acp): teach agents to send real newlines (#2121)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-19 09:56:16 -07:00
284a76c1c7 fix(agents): stop the reply loop and the premature kickoff closer (#2094)
Co-authored-by: Claude <noreply@anthropic.com>
2026-07-18 16:29:17 -07:00
a30d525155 fix(dev-mcp): remove buzz_send_message tool in favor of buzz CLI send path (#2043)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-17 17:36:13 -04:00
4be5c6ae32 fix(agents): anchor active-turn timer to authoritative start time (#2033)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-17 16:21:58 -04:00
c19e0ce2d4 Add preferred runtime onboarding (#2040)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-17 14:19:29 -06:00
64b8fea6dc Bug-bash round 2: table scroll, Goose instructions, workflow mention wake (#2034)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-17 14:49:54 -04:00
morgmartandGitHub 85fc64835e Welcome new users with a live agent team kickoff (#1998)
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
2026-07-17 07:39:03 -04:00
44359f635a feat(acp): retry initial relay connection with terminal/transient error classification (#1922)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-16 14:40:11 -04:00
8d3666c5f8 Guide CLI installation and subscription sign-in (#1980)
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
2026-07-16 14:21:03 -04:00
c5996e13a4 fix(buzz-acp): distinguish cancel-drain expiry from real hard-cap timeout (#1893)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-15 10:03:44 -07:00
morgmartandGitHub 54e174b5e1 Chat-first agent creation via portable buzz CLI drafts (#1878) 2026-07-15 09:24:57 -07:00
Michael NealeandGitHub 54638ff4bb mesh: upgrade runtime, enforce membership, add shared compute provider (#1656) 2026-07-15 10:10:29 -04:00
1950eb114f fix(acp): sort flushed batch events chronologically so replies thread under the right message (#1872)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:37:38 -07:00
448baeef77 feat(teams): unify team model, snapshot sharing, and PNG memory parity (#1846)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-14 17:10:51 -04:00
Will PflegerandGitHub 276072f683 fix(buzz-acp): distinguish idle vs hard-cap timeout, dead-letter hard kills immediately (#1844) 2026-07-14 10:35:24 -04:00
020ac7f405 fix(desktop): resolve Git Bash for Windows shell tool via PATH/git/registry fallback (#1821)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-13 16:53:02 -04:00
6d1a77e492 fix(codex): swap to @agentclientprotocol/codex-acp 1.x + detect outdated adapter (#1750)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-12 16:52:04 -04:00
3b9b371f87 feat(acp): surface channel canvas metadata in agent system context (#1755)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-11 12:11:18 -04:00
ec37625522 fix(desktop): surface codex config-parse failures and -32603 internal errors clearly (#1745)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-10 21:25:52 -04:00
Will PflegerandGitHub fc8a17445a fix(agents): harden structured error-code classification edge cases (#1663) 2026-07-08 18:18:44 -04:00
Will PflegerandGitHub 9b244ff22b fix(agents): surface provider errors structurally instead of raw dumps (#1653) 2026-07-08 17:32:48 -04:00
4f1a487ab4 feat(config-nudge): distinguish install/auth state in cli_login nudge cards (#1633)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-08 16:00:03 -04:00
Will PflegerandGitHub 3c6c0d4478 feat(acp,desktop): identify and reap stale agent harness processes (#1582) 2026-07-07 12:49:16 -04:00
08e707eb57 feat(acp,buzz-agent): thread model name through NIP-AM kind 44200 emit path (#1564)
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-06 21:12:42 -04:00
d8355d3188 feat(desktop,buzz-acp): add harness-agnostic config bridge and setup-listener mode (#1411)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-06 18:23:38 -04:00
cfa2089831 refactor(shell): drop bundled PortableGit, add BUZZ_SHELL override + dialect hint (#1536)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-06 12:54:50 -04:00
71265ca361 feat(nips,relay,acp): NIP-AM durable encrypted agent turn metrics (kind 44200) (#1441)
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw <4a1bfa0013bc6d14a8d600d8bf6392efefbd2a26ac3c96c9b2a106b0d12297ca@sprout-oss.stage.blox.sqprod.co>
2026-07-06 16:35:10 +00:00
4a09510429 fix(agent): make stop-hook rejection budget per-prompt, fix stale hook docs (#1503)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
2026-07-03 09:21:18 -07:00
1c297d2f26 fix(agent): honor stop hook retry budget (#1501)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
2026-07-03 15:50:22 +00:00
d9c4e4aa7f fix: agent reliability — no restart on channel-add, visible dead-letter notice (#1468)
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
2026-07-02 11:16:50 -07:00
9f2a11b338 feat(buzz-agent): emit agent_thought_chunk for reasoning content (#1436)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-07-01 14:57:05 -04:00
10aaa72f01 fix(buzz-acp): clear steer_rx on all run_prompt_task exit paths (#1391)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-06-30 11:41:17 -04:00
c65989a61b feat(desktop): harness-agnostic config bridge (#887)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <wpfleger@block.xyz>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-06-29 16:51:32 -04:00
401bb51bf2 fix(acp): enable sandbox network access for Codex MCP subprocesses (#1363)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
2026-06-29 16:35:15 -04:00
e567491a19 feat(buzz-acp): steering as the default mid-turn mention delivery (#1160)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1fgdl5qqnh3k3f2xkqrvt7cujalhm623x4s7fdjdj5yrtp5fzjl9qrjpucw <4a1bfa0013bc6d14a8d600d8bf6392efefbd2a26ac3c96c9b2a106b0d12297ca@sprout-oss.stage.blox.sqprod.co>
2026-06-29 13:18:56 -04:00