Skip to content

feat(tokenless): add WorkBuddy (Tencent CodeBuddy) adapter - #2532

Open
Forrest-ly wants to merge 3 commits into
alibaba:mainfrom
Forrest-ly:feat/tokenless-workbuddy-adapter
Open

feat(tokenless): add WorkBuddy (Tencent CodeBuddy) adapter#2532
Forrest-ly wants to merge 3 commits into
alibaba:mainfrom
Forrest-ly:feat/tokenless-workbuddy-adapter

Conversation

@Forrest-ly

Copy link
Copy Markdown
Collaborator

Summary

Add a workbuddy adapter for WorkBuddy (Tencent CodeBuddy product family), closing #2524.

WorkBuddy desktop, CodeBuddy Code CLI and WorkBuddy Enterprise share the .codebuddy settings protocol — a Claude Code-shaped hooks key in settings.json — but expose no plugin system, so the adapter merges the tokenless hook groups into the user-level ~/.codebuddy/settings.json.

Changes

  • adapters/tokenless/workbuddy/
    • hooks/hooks.json — template with @TOKENLESS_ADAPTER_DIR@ placeholder: PreToolUse Bashrewrite_hook.py, catch-all PreToolUse group → tool_ready_hook.sh, PostToolUse negative-lookahead group (skips Read|Glob|NotebookRead) → compress_response_hook.py. WorkBuddy matchers alias CLI/IDE tool names (Bashexecute_command), so CC-style matchers carry over
    • hooks/run-hook.sh — symlink to the shared dispatcher (same convention as qoder/qwencode)
    • scripts/install.sh — idempotent merge into ~/.codebuddy/settings.json; stamps the absolute adapter directory (no plugin-root substitution); preserves user-configured hooks and every other settings key; refuses invalid JSON without clobbering; graceful no-op when ~/.codebuddy is absent
    • scripts/uninstall.sh — removes only tokenless-owned entries (TOKENLESS_AGENT_ID=workbuddy marker)
    • scripts/detect.sh — tri-state report aligned with claude-code/qwencode conventions
  • common/hooks/rewrite_hook.py — emit WorkBuddy's modifiedInput partial field override (its documented PreToolUse input-rewrite field) when TOKENLESS_AGENT_ID=workbuddy, alongside the existing tool_input/updatedInput formats
  • manifest.json.inworkbuddy target (hooks: rewrite / compress-response / compress-toon / tool-ready)
  • Makefile — workbuddy-install / workbuddy-uninstall targets wired into adapter-install / adapter-uninstall, help text, installer test in test-adapters
  • Raw packager — materialize the workbuddy/hooks/run-hook.sh symlink; test fixture updated accordingly
  • RPM spec — package the adapter files, %preun cleanup hook
  • Docs (EN/ZH) — support-matrix row, activation notes (lifecycle script, same treatment as OpenCode since the anolisa adapter enable Rust driver set is maintained outside this component), QUICKSTART table; changelog entries
  • Tests — installer lifecycle script (10 cases), rewrite_hook unit tests for modifiedInput dialect behavior, compress_response_hook unit test pinning the additive delivery

Response compression is delivered via additionalContext per the issue scope. Note: the current CodeBuddy CLI hook reference documents PostToolUse updatedToolOutput for all tools (its stated typical use is exactly compression-style hooks), which could enable full replacement; since the issue explicitly scopes replacement as a follow-up pending per-product verification (WorkBuddy desktop / CodeBuddy CLI / WorkBuddy Enterprise are distinct products), this PR keeps the conservative additive path. A follow-up can upgrade workbuddy to the replacement dispatch in compress_response_hook.py once confirmed on the target surface.

测试情况 (Test report)

Environment: Linux x86_64; GNU bash 4.4.20; system Python 3.8.17 and user-local Python 3.11.14; GNU Make 4.2.1; Node v22.21.1.

Executed:

Test Result
tests/test-workbuddy-adapter-install.sh (new) ✅ 10/10 passed — merge/idempotency/user-hook & settings-key preservation/uninstall/fresh settings.json creation/no-WorkBuddy no-op/invalid-JSON refusal/detect tri-state
End-to-end dispatch smoke: stamped hooks.json command → run-hook.sh symlink → rewrite_hook.py ✅ emits modifiedInput + compat fields with a real rewrite
tests/test_rewrite_hook.py workbuddy cases (new) modifiedInput emitted for workbuddy, omitted for other agents
tests/test_compress_response_hook.py workbuddy case (new) ✅ additionalContext delivery pinned (no updatedToolOutput)
tests/test-run-hook-install-scope.sh ✅ passed
tests/test-tool-ready-readable-fixer.sh ✅ passed
tests/run-all-tests.sh 69/72 — the 3 failures are the pre-existing env-check hard bypass failures, reproduced identically on the unmodified base tree
tests/test_compress_response_hook.py / test_compress_schema_hook.py / test_resolve_agent_id.py / test_agentscope_middleware.py (py3.11) ✅ OK
tests/test-qoder-adapter-install.sh (regression) ✅ 17/17
tests/test-opencode-adapter-install.sh (regression) ✅ 13/13
tests/test-package-raw.sh ✅ passed after adding the workbuddy fixture hook
make stamp-adapter-templates + manifest inspection workbuddy target present with capabilities/actions
make -n workbuddy-install / make -n workbuddy-uninstall ✅ resolve to the new scripts
bash -n syntax check on all new scripts

Pre-existing failures (verified identical on the unmodified base tree, unrelated to this change):

  • tests/test_rewrite_hook.py — 11 anchor-test failures: a system-installed rtk in a hardcoded fallback path shadows the sandboxed fake rtk the test stages (my 2 new tests are path-independent and pass).
  • tests/test_hermes_plugin_import.py — 1 failure: a system-installed adapter tree under /usr/local/share/... shadows the test's XDG_DATA_HOME sandbox.
  • On system Python 3.8, test_agentscope_middleware.py cannot import (StrEnum needs 3.11) — same on the base tree.

Not run (with reasons):

  • cargo build / cargo test — no Rust code is touched by this PR.
  • make test-adapters full target — its build-openclaw-plugin prerequisite performs an npm dependency build not needed for this change; the individual installer tests above were run directly instead.
  • rpmbuild of tokenless.spec.in — a full RPM build requires the complete native build chain; the spec additions mirror the existing qwencode entries line-for-line.
  • Live WorkBuddy/CodeBuddy runtime verification — no WorkBuddy/CodeBuddy product is installed in the test environment; hook behavior against a running product (including the /hooks panel review flow and per-product updatedToolOutput support) needs verification on a machine with the product installed.

@github-actions github-actions Bot added component:tokenless src/tokenless/ scope:documentation ./docs/|./*.md|./NOTICE labels Aug 14, 2026

@qoderai qoderai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] WorkBuddy 文档与 detect.sh 三态语义略有偏差:QUICKSTART 与 framework-integration 强调“无 WorkBuddy 时生命周期脚本优雅跳过”,但 detect.sh 在 ~/.codebuddy 缺失时按约定返回 2(缺前置条件)。建议在 WorkBuddy 章节中补充说明 detect.sh 的 0/1/2 语义及“缺 ~/.codebuddy 时视为未安装”的判定逻辑,以免用户混淆。

[P2] WorkBuddy detect.sh 对 tokenless/rtk 二进制的前置条件判定在未来“仅 CLI 压缩”或远程 Tokenless 场景下可能偏严:当前缺少本地 tokenless/rtk 即归入 PREREQ_MISSING 并返回 2,合理但值得在后续扩展时评估是否弱化为 install-missing 或在文档中明确现有限制。

[P2] tokenless.spec.in 中 %preun 仅清理 root 家目录的 WorkBuddy hooks,多用户主机上其他用户需自行运行 uninstall.sh。当前注释已有提示,建议在 docs/CHANGELOG 中也增加一句“非 root 用户需自行运行 uninstall.sh”以对齐 OpenCode/Qwen Code 的卸载说明,减少管理员误解。


🤖 Generated by QoderView workflow run

Comment on lines +205 to +207
### WorkBuddy

WorkBuddy (Tencent CodeBuddy) has no plugin system for hooks. The bundled lifecycle script merges the Tokenless hook groups into the user-level `~/.codebuddy/settings.json`, whose `hooks` key follows the Claude Code matcher-group shape:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] detect.sh 在无 WorkBuddy 时返回 2 与文档“无 WorkBuddy 时优雅 no-op”略有偏差,建议在文档中补充说明三态含义。

当前 docs/QUICKSTART 与 framework-integration 中对 WorkBuddy 的描述强调“无 WorkBuddy 时生命周期脚本优雅跳过”,而 scripts/detect.sh 在 ~/.codebuddy 缺失时按约定返回 2(缺前置条件)。为了避免用户误解,可在 WorkBuddy 章节中简要说明 detect.sh 的 0/1/2 语义及“缺 ~/.codebuddy 时视为未安装”的判定逻辑。


🤖 Generated by QoderFix in Qoder

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已采纳。已在 docs/user-guide/en|zh/token-saving/tokenless/framework-integration.md 的 WorkBuddy 章节补充 detect.sh 的三态退出码语义:0 = 已检测到 WorkBuddy/CodeBuddy 且 Tokenless Hook 已安装;1 = 已检测到但 Hook 尚未安装;2 = 缺少前置条件。同时说明了“缺 ~/.codebuddy 视为未安装”的判定逻辑(detect.sh 返回 2,而 install.sh 对同一情况优雅跳过并以 0 退出,二者语义差异已在文档中讲明)。见 cc39b59

Comment on lines 451 to +468
bash "$OPENCODE_SCRIPT" || true
fi

# --- WorkBuddy hooks cleanup ---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] tokenless.spec.in 中 %preun 针对 root 家目录的 WorkBuddy hooks 清理逻辑需要用户文档提示以避免“多用户环境”误解。

%preun 仅调用 /usr/share/anolisa/adapters/tokenless/workbuddy/scripts/uninstall.sh,这在注释中也说明只触及 root 的 ~/.codebuddy/settings.json。为避免管理员误以为卸载 RPM 即会自动清理所有用户的 WorkBuddy hooks,建议在 docs 或 CHANGELOG 中增加一句“在多用户主机上,非 root 用户需自行运行 uninstall.sh”提示,与 OpenCode/Qwen Code 的清理说明保持一致。


🤖 Generated by QoderFix in Qoder

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已采纳。考虑到仓库文档规范规定 CHANGELOG 仅在 release version bump PR 中修改,提示改为写入用户文档:已在 docs/user-guide/en|zh/token-saving/tokenless/framework-integration.md 的 WorkBuddy 章节补充“RPM %preun 以 root 运行,仅清理 root 用户的 ~/.codebuddy/settings.json;多用户主机上其他用户需自行运行 uninstall.sh”。见 cc39b59

note_prereq_missing "shared hooks dir"
fi

if [ ${#PREREQ_MISSING[@]} -gt 0 ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] WorkBuddy detect.sh 对 tokenless/rtk 二进制的前置条件判定可能在“仅 CLI 压缩”场景下过于严格。

scripts/detect.sh 一旦找不到 tokenless 或 rtk 即将其归入 PREREQ_MISSING 并返回 2,这与“无 WorkBuddy 时优雅 no-op”的整体叙述一致,但在未来如果存在纯 CodeBuddy/WorkBuddy runtime 使用场景(例如仅依赖服务器侧 Tokenless),本地缺少这些二进制并不必然意味着“无法安装”。建议在后续扩展时评估是否需要单独弱化这两项为 install-missing 或在文档中明确当前限制。


🤖 Generated by QoderFix in Qoder

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不采纳(保留现有代码行为),理由:workbuddy detect.sh 对 tokenless/rtk 二进制的前置条件判定与现有 qwencode detect.sh 的约定完全一致(均按前置条件缺失报退出码 2);弱化为 install-missing 属于语义变更,且意见中提到的“仅服务器侧 Tokenless”场景目前并不存在,不宜提前引入 adapter 间的行为分歧,留待该场景真正出现时再统一评估。意见中“在文档中明确当前限制”的替代方案已落实:本次文档更新已写明“本版本中缺少 tokenless 或 rtk 二进制按前置条件缺失(退出码 2)上报”。见 cc39b59

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 45bd8d8191

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

"uninstall": "qwencode/scripts/uninstall.sh"
}
},
"workbuddy": {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add WorkBuddy to the install contract

This declares the WorkBuddy target in the adapter manifest, but anolisa install lays adapter directories from the component contract's [[adapters]] entries, not from manifest.json. Since src/tokenless/.anolisa/component.toml.in still ends at qwencode, raw/anolisa installs will not copy {datadir}/adapters/tokenless/workbuddy, so the documented lifecycle script is missing on the primary install path; add a matching WorkBuddy adapter entry to the component contract and synced built-in manifest.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not adopting this one — the omission is intentional and matches the established OpenCode pattern:

  • WorkBuddy (like OpenCode) is a lifecycle-script adapter; the user guide states explicitly that both "are not registered with the anolisa adapter enable driver set in this release" (framework-integration.md, QUICKSTART.md).
  • The component contract's [[adapters]] list declares adapters that ship a built-in CLI framework driver. That convention was set by 0f48bd3 ("Declare every shipped driver ... Keep qwencode unlisted until a built-in driver is available"), and qwencode was only added after its driver landed. The closed DriverRegistry in anolisa-core has no opencode or workbuddy driver.
  • A driver-less [[adapters]] entry would surface workbuddy in anolisa adapter scan/enable flows and produce "no built-in driver for framework" reports.
  • The documented staging paths install the adapter directory explicitly: RPM %install and make -C src/tokenless install (the docs' bash block references exactly that staging), and the raw tarball ships the full adapter tree via packaging/raw/package.sh.
  • The synced built-in manifest (src/anolisa/manifests/components/tokenless/component.toml) belongs to the anolisa component; this tokenless PR does not modify it.

If a built-in workbuddy driver lands later, adding the contract entry (both copies) should come with that driver PR, same as qwencode did.

Comment thread src/tokenless/CHANGELOG.md Outdated
Comment on lines +12 to +14
### Added

- WorkBuddy (Tencent CodeBuddy) adapter: hook groups are merged into the user-level `~/.codebuddy/settings.json`, command rewriting emits WorkBuddy's `modifiedInput` partial field override, and response compression is delivered via `additionalContext` ([#2524](https://github.com/alibaba/anolisa/issues/2524)).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the daily changelog entry

This feature commit adds an Unreleased changelog entry, but the repository documentation standard reserves CHANGELOG edits for release version bump PRs; daily feature/fix PRs should update the README/user-guide only. Keeping this here makes the docs change non-compliant for a non-release commit, so move it to the release bump instead.

AGENTS.md reference: AGENTS.md:L337-L343

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopted — removed the Unreleased entry this PR added from both CHANGELOG.md and CHANGELOG_zh.md, restoring the section to its state on main. Per specs/documentation-standard.md ("CHANGELOG is written exclusively in release version bump PRs"), the entry will be aggregated into the next release bump PR instead. See cc39b59.

@Forrest-ly
Forrest-ly force-pushed the feat/tokenless-workbuddy-adapter branch from 9a94a40 to 1a94473 Compare August 14, 2026 06:21
Forrest-ly and others added 3 commits August 17, 2026 16:38
WorkBuddy desktop, CodeBuddy Code CLI and WorkBuddy Enterprise share the
.codebuddy settings protocol (Claude Code-shaped hooks key) but expose no
plugin system, so the adapter merges the tokenless hook groups into the
user-level ~/.codebuddy/settings.json:

- hooks.json template with Bash rewrite matcher, catch-all tool-ready
  group, and PostToolUse compression group; install.sh stamps the absolute
  adapter directory because WorkBuddy has no plugin-root substitution
- idempotent merge preserving user-configured hooks and every other
  settings key; uninstall.sh removes only tokenless-owned entries
  (TOKENLESS_AGENT_ID=workbuddy marker); graceful no-op without .codebuddy
- rewrite_hook.py emits WorkBuddy's modifiedInput partial field override
  (its PreToolUse input-rewrite field) in addition to the existing formats
- response compression stays on the additionalContext path per the issue
  scope; full updatedToolOutput replacement is a documented follow-up
- detect.sh tri-state report, run-hook.sh shared dispatcher symlink
- Makefile workbuddy-install/workbuddy-uninstall targets and test wiring
- raw packager materializes the run-hook symlink; RPM packages the adapter
- bilingual docs and changelog entries

Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
…hangelog entry

Address bot review feedback on the WorkBuddy adapter PR:

- framework-integration.md (en/zh): document detect.sh tri-state exit
  semantics (0 ready / 1 not installed / 2 missing prerequisites), the
  'missing ~/.codebuddy counts as not installed' decision, and that a
  missing tokenless/rtk binary is treated as a missing prerequisite in
  this release; note install.sh no-ops gracefully on the same condition
- framework-integration.md (en/zh): note that RPM %preun runs as root
  and only cleans root's ~/.codebuddy/settings.json, so non-root users
  on multi-user hosts must run uninstall.sh themselves
- CHANGELOG.md / CHANGELOG_zh.md: drop the Unreleased WorkBuddy entry;
  documentation-standard.md reserves CHANGELOG edits for release
  version bump PRs

Co-authored-by: multica-agent <github@multica.ai>
@Forrest-ly
Forrest-ly force-pushed the feat/tokenless-workbuddy-adapter branch from cc39b59 to 387d2ca Compare August 17, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:tokenless src/tokenless/ scope:documentation ./docs/|./*.md|./NOTICE

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant