Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Buzz Qwen Code Harness

Run Qwen Code as a custom ACP harness in Buzz, using an OpenAI-compatible model endpoint on the same computer, another machine, a GPU cluster, a container platform, or a hosted service.

This repository also provides a narrow workaround for model servers that reject Qwen Code's tool grammar when a tool schema contains a large maxLength. The patcher caps only maxLength values above 2000 that are reachable from actual Qwen Code tool definitions. It does not rewrite JSON Schema libraries or arbitrary bundled code.

Status: Qwen Code 0.22.3 is the currently tested release. Patching another release requires an explicit override and should begin with a dry run.

What this repository provides

  • A Buzz ACP launcher for Qwen Code.
  • Optional fail-open, metadata-only ACP telemetry for Buzz Agent Observability.
  • A syntax-aware tool-schema auditor that understands decimal values, scientific notation such as 1e4, and imported constants.
  • A backup-first patch and restore workflow.
  • A secret-free Buzz manifest generator.
  • Synthetic regression tests; no Qwen Code bundles are redistributed here.

It does not install Qwen Code, run a model server, select a model for you, or alter Qwen Code user settings. In particular, it never changes ~/.qwen/settings.json, API tokens, model configuration, or server configuration.

Architecture

Buzz chat window
      │ ACP over stdin/stdout
      ▼
codex-acp launcher ──► Qwen Code
                           │ OpenAI-compatible HTTP (/v1)
                           ▼
                    model-serving endpoint
             local │ LAN │ cluster │ cloud

The client and model-serving layers are independent:

  • Buzz and this harness run where the user works.
  • Qwen Code supplies the coding-agent loop and tools.
  • The model endpoint can run anywhere reachable from the client.
  • The endpoint must implement the OpenAI-compatible behavior required by Qwen Code, including streaming and tool calls.

The launcher is intentionally named codex-acp. Some Buzz releases attach their authenticated reply MCP sidecar only to recognized ACP harness command names. Keeping this basename lets Qwen Code receive that integration without pretending that the underlying runtime is Codex.

Deployment choices

Model location Base URL example Best for Important consideration
Same machine http://127.0.0.1:8000/v1 Simple development and single-GPU systems Buzz must be able to reach the listening port
LAN server http://model-host.example:8000/v1 Workstations and dedicated inference servers Bind intentionally and restrict the network
Multi-node cluster http://cluster-gateway.example:8000/v1 Models spread across several accelerators Expose one stable gateway; cluster internals are the server's concern
Container platform http://inference.example:8000/v1 Reproducible or shared deployments Publish the endpoint and persist model caches as needed
Hosted API https://provider.example/v1 No local inference administration Use TLS and inject the provider key at runtime

This project is hardware-neutral. CPU, CUDA, ROCm, Apple Silicon, distributed inference, and cloud accelerators are all valid behind the endpoint. Performance and model fit are properties of the serving stack, not the ACP bridge.

Requirements

  • Buzz with custom ACP harness support.
  • Node.js 22 or newer.
  • Qwen Code installed separately.
  • An OpenAI-compatible model endpoint.
  • A coding model whose chat template and tool-calling behavior work with that endpoint.

Confirm the basics before changing anything:

node --version
qwen --version
curl http://model-host.example:8000/v1/models

For an authenticated endpoint:

curl -H "Authorization: Bearer $MODEL_API_KEY" \
  https://provider.example/v1/models

Never paste a real key into a repository file or command history.

Install the utility

git clone https://github.com/Bostonvex/buzz-qwen-code-harness.git
cd buzz-qwen-code-harness
npm ci
npm run check

The project is currently source-installed. Run commands as node bin/buzz-qwen-code.mjs …, or use npm link if you want the buzz-qwen-code command on your PATH.

Audit and patch Qwen Code

1. Audit without changing anything

The default standalone installation path is ~/.local/lib/qwen-code:

node bin/buzz-qwen-code.mjs audit

Use an explicit path for a different installation:

node bin/buzz-qwen-code.mjs audit \
  --qwen-root /opt/qwen-code

Exit status 0 means no offending tool-schema value remains. Exit status 2 means the audit found one or more tool-schema maxLength values above the cap.

2. Review a dry run

node bin/buzz-qwen-code.mjs patch --dry-run

Each proposed edit is printed as:

lib/chunks/example.js:123:24 [ExampleTool] 1e4 (10000) -> 2000

The report identifies the file, line, column, tool class, source expression, evaluated value, and replacement.

3. Apply the patch

node bin/buzz-qwen-code.mjs patch

Before writing a bundle file, the command copies the complete installation to a timestamped sibling directory such as:

~/.local/lib/qwen-code.backup-20260830T120000Z

It then:

  1. groups edits by actual tool bundle;
  2. changes only offending maxLength expressions to 2000;
  3. parses and audits the installation again;
  4. rolls changed files back if verification fails; and
  5. records original and patched SHA-256 hashes in buzz-qwen-code-patch.json inside the backup.

The patch is intentionally version-gated. For an untested release, first inspect a dry run and then opt in explicitly:

node bin/buzz-qwen-code.mjs patch \
  --allow-untested-version \
  --dry-run

Do not assume that a patch validated for one Qwen Code bundle layout is safe for another release.

Restore a patched installation

Use the exact backup path printed by patch:

node bin/buzz-qwen-code.mjs restore \
  --backup ~/.local/lib/qwen-code.backup-20260830T120000Z

Restore checks that every current file still has the patched hash. It refuses to overwrite a file changed by a later upgrade or manual edit. --force exists for an operator who has reviewed that conflict.

Install the Buzz harness

Stop Buzz before changing its harness manifests. Then run:

node bin/buzz-qwen-code.mjs install-buzz \
  --qwen-bin ~/.local/bin/qwen \
  --base-url http://model-host.example:8000/v1 \
  --model coding-model

The command writes custom_harnesses/qwen-code.json under the platform's Buzz data directory. Existing manifests are renamed to timestamped backups instead of being overwritten.

Default Buzz data locations are:

Platform Default
macOS ~/Library/Application Support/Buzz
Linux $XDG_CONFIG_HOME/Buzz or ~/.config/Buzz
Windows %APPDATA%\Buzz

If your Buzz build uses another location, pass it explicitly:

node bin/buzz-qwen-code.mjs install-buzz \
  --buzz-data-dir /path/to/Buzz \
  --base-url https://provider.example/v1 \
  --model coding-model \
  --api-key-env MODEL_API_KEY

The manifest stores only the environment-variable name, not its value. Make that variable available to the Buzz process before starting Buzz:

export MODEL_API_KEY='replace-with-your-provider-key'
open -a Buzz                       # macOS example

Use your desktop session manager, keychain, secrets manager, or service configuration in production. For endpoints that accept any non-empty placeholder, the launcher defaults to the non-secret value local when the named variable is absent.

Restart Buzz after installing the manifest. Add a new agent and select Qwen Code as its harness. Agent-level model selection and harness registration are separate: edit the harness when the executable or endpoint changes; edit the individual agent when its role, prompt, or other seat-specific behavior changes.

Configuration reference

Harness variable Meaning Secret?
QWEN_CODE_BIN Absolute path to the Qwen Code executable No
QWEN_BASE_URL OpenAI-compatible API root, normally ending in /v1 Usually no; private hostnames may still be sensitive
QWEN_MODEL_ID Model identifier sent to the endpoint No
QWEN_MODEL_API_KEY_ENV Name of the inherited variable holding the key No
Named API-key variable Actual model endpoint credential Yes; inject at runtime
QWEN_UNAUTHENTICATED_API_KEY Optional non-secret placeholder for an unauthenticated server No
BUZZ_TELEMETRY_ENABLED Explicitly enable local metadata-only observation No
BUZZ_TELEMETRY_TOKEN_FILE Path to the collector's private ingest-token file Sensitive path; file contents are secret
BUZZ_TELEMETRY_IDENTITY_SALT_FILE Path to the collector's private identity-salt file Sensitive path; file contents are secret

The launcher maps these settings to Qwen Code's OPENAI_API_KEY, OPENAI_BASE_URL, and OPENAI_MODEL variables, then starts:

qwen --acp --model <model-id>

Additional arguments supplied by Buzz are forwarded unchanged.

Optional local observability

The launcher can observe the real ACP byte streams without modifying them. It uses native piped backpressure, caps the amount retained for line inspection, and sends only timing, lifecycle, tool kind/status, usage semantics, and hashed identity metadata to the loopback collector. Telemetry is disabled by default.

The launcher declares ACP-update tool coverage, so a terminal 0 means no live tool notification was observed. If that observation path is unavailable, the collector displays an unavailable value instead of a false zero.

BUZZ_TELEMETRY_ENABLED=1
BUZZ_TELEMETRY_URL=http://127.0.0.1:7900/api/v1/events
BUZZ_TELEMETRY_TOKEN_FILE=~/.config/buzz-agent-observability/ingest-token
BUZZ_TELEMETRY_IDENTITY_SALT_FILE=~/.config/buzz-agent-observability/identity-salt
BUZZ_TELEMETRY_ENDPOINT_ID=local-model-primary

An unavailable collector, invalid telemetry configuration, send timeout, or observer error cannot reject an ACP request. Exit delivery has a 50 millisecond deadline. Protocol stdout remains byte-for-byte Qwen output; telemetry never writes there. BUZZ_TELEMETRY_MAX_ACP_LINE_BYTES may lower or raise the inspection limit from its 1 MiB default within the enforced 1 KiB–16 MiB range. Oversized lines still pass through unchanged and are reported only by byte count.

Test outside Buzz

First verify the model path through Qwen Code itself:

OPENAI_API_KEY=local \
OPENAI_BASE_URL=http://model-host.example:8000/v1 \
OPENAI_MODEL=coding-model \
qwen --model coding-model \
  --max-tool-calls -1 \
  -p "Reply with exactly: Qwen Code tool grammar initialized successfully."

Then inspect the integration:

node bin/buzz-qwen-code.mjs doctor

doctor reports the Qwen installation and version, whether the release is tested, remaining tool-schema violations, and the active Buzz model and endpoint. It never prints an API-key value.

Why the grammar patch exists

Some llama.cpp-compatible servers convert JSON tool schemas into a constrained grammar. Large string bounds can make that conversion fail before generation begins, producing an error similar to:

Failed to initialize samplers: failed to parse grammar

The failure is server- and grammar-converter-dependent; Qwen Code is not necessarily invalid. Reducing tool-string bounds is a compatibility workaround with a tradeoff: affected tool arguments cannot exceed 2,000 characters.

The auditor avoids a broad search-and-replace. It parses every JavaScript chunk and starts only from classes extending Qwen Code's BaseDeclarativeTool. It follows nested schema objects and resolvable local or imported numeric constants. A maxLength in an unrelated parser, linkifier, validator, or other bundled dependency is outside that graph and is left untouched.

Troubleshooting

Failed to initialize samplers: failed to parse grammar

node bin/buzz-qwen-code.mjs audit

If the audit is clean, the remaining incompatibility is probably another part of the generated grammar, the model's tool-call template, or the serving stack. Inspect the model-server log at the matching request time. Do not keep lowering unrelated bundle constants.

Buzz reports no models

Confirm that:

  • curl <base-url>/models succeeds from the Buzz machine;
  • the configured model ID exactly matches a returned or accepted identifier;
  • Qwen Code starts from the same desktop environment as Buzz; and
  • the API-key variable is available to the Buzz process, not only an unrelated terminal.

Buzz sends a prompt but displays no response

Run the command-line test above, then check Buzz and Qwen Code logs for the same timestamp. A healthy model HTTP response does not prove that the ACP client received a terminal turn event. Also confirm the manifest uses this repository's bin/codex-acp launcher and restart Buzz after replacing a manifest.

The model loops on a tool

This is usually model behavior or a mismatch between the model's tool template and the server. Use a model trained for tool calling, confirm the server applies its expected chat template, and test one simple file-writing request outside Buzz. The schema cap fixes grammar construction; it does not improve a model's tool-use judgment.

Qwen Code was upgraded

Upgrades normally replace bundled chunks and therefore remove this patch. Do not copy old chunks into a new release. Run audit, review patch --dry-run, and wait for this project to list the new release as tested before patching without the override.

Remove the Buzz manifest

node bin/buzz-qwen-code.mjs uninstall-buzz

The manifest is renamed to a recoverable timestamped file. Qwen Code and the model server are not uninstalled.

Security and operations

  • Bind unauthenticated model servers to loopback unless other clients truly need access.
  • Put authentication and TLS in front of endpoints crossing untrusted networks.
  • Restrict Buzz manifests and logs because endpoints, prompts, and file paths may be sensitive.
  • Give coding agents access only to intended workspaces.
  • Treat model-generated tool arguments as untrusted input.
  • Keep Qwen Code backups until the patched installation has passed a real workflow.
  • Never publish the generated Buzz manifest if it contains a private hostname, even though it contains no API-key value.

Project boundaries and upstream attribution

This is an independent integration project. It does not vendor or redistribute Qwen Code. Install Qwen Code from its official distribution and review its Apache-2.0 license.

This repository's original integration code is MIT-licensed. Contributions should arrive through forks and pull requests; direct repository write access remains limited to the owner.

About

Backup-safe Qwen Code grammar compatibility patcher and Buzz ACP harness

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages