feat(tokenless): add WorkBuddy (Tencent CodeBuddy) adapter - #2532
feat(tokenless): add WorkBuddy (Tencent CodeBuddy) adapter#2532Forrest-ly wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
[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 Qoder • View workflow run
| ### 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: |
There was a problem hiding this comment.
[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 Qoder • Fix in Qoder
There was a problem hiding this comment.
已采纳。已在 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。
| bash "$OPENCODE_SCRIPT" || true | ||
| fi | ||
|
|
||
| # --- WorkBuddy hooks cleanup --- |
There was a problem hiding this comment.
[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 Qoder • Fix in Qoder
There was a problem hiding this comment.
已采纳。考虑到仓库文档规范规定 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 |
There was a problem hiding this comment.
[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 Qoder • Fix in Qoder
There was a problem hiding this comment.
不采纳(保留现有代码行为),理由:workbuddy detect.sh 对 tokenless/rtk 二进制的前置条件判定与现有 qwencode detect.sh 的约定完全一致(均按前置条件缺失报退出码 2);弱化为 install-missing 属于语义变更,且意见中提到的“仅服务器侧 Tokenless”场景目前并不存在,不宜提前引入 adapter 间的行为分歧,留待该场景真正出现时再统一评估。意见中“在文档中明确当前限制”的替代方案已落实:本次文档更新已写明“本版本中缺少 tokenless 或 rtk 二进制按前置条件缺失(退出码 2)上报”。见 cc39b59。
There was a problem hiding this comment.
💡 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": { |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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 enabledriver 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 inanolisa adapterscan/enable flows and produce "no built-in driver for framework" reports. - The documented staging paths install the adapter directory explicitly: RPM
%installandmake -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.
| ### 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)). |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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.
9a94a40 to
1a94473
Compare
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>
cc39b59 to
387d2ca
Compare
Summary
Add a
workbuddyadapter for WorkBuddy (Tencent CodeBuddy product family), closing #2524.WorkBuddy desktop, CodeBuddy Code CLI and WorkBuddy Enterprise share the
.codebuddysettings protocol — a Claude Code-shapedhookskey insettings.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: PreToolUseBash→rewrite_hook.py, catch-all PreToolUse group →tool_ready_hook.sh, PostToolUse negative-lookahead group (skipsRead|Glob|NotebookRead) →compress_response_hook.py. WorkBuddy matchers alias CLI/IDE tool names (Bash↔execute_command), so CC-style matchers carry overhooks/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~/.codebuddyis absentscripts/uninstall.sh— removes only tokenless-owned entries (TOKENLESS_AGENT_ID=workbuddymarker)scripts/detect.sh— tri-state report aligned with claude-code/qwencode conventionscommon/hooks/rewrite_hook.py— emit WorkBuddy'smodifiedInputpartial field override (its documented PreToolUse input-rewrite field) whenTOKENLESS_AGENT_ID=workbuddy, alongside the existingtool_input/updatedInputformatsmanifest.json.in—workbuddytarget (hooks: rewrite / compress-response / compress-toon / tool-ready)workbuddy-install/workbuddy-uninstalltargets wired intoadapter-install/adapter-uninstall, help text, installer test intest-adaptersworkbuddy/hooks/run-hook.shsymlink; test fixture updated accordingly%preuncleanup hookanolisa adapter enableRust driver set is maintained outside this component), QUICKSTART table; changelog entriesrewrite_hookunit tests formodifiedInputdialect behavior,compress_response_hookunit test pinning the additive deliveryResponse compression is delivered via
additionalContextper the issue scope. Note: the current CodeBuddy CLI hook reference documents PostToolUseupdatedToolOutputfor 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 upgradeworkbuddyto the replacement dispatch incompress_response_hook.pyonce 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:
tests/test-workbuddy-adapter-install.sh(new)run-hook.shsymlink →rewrite_hook.pymodifiedInput+ compat fields with a real rewritetests/test_rewrite_hook.pyworkbuddy cases (new)modifiedInputemitted for workbuddy, omitted for other agentstests/test_compress_response_hook.pyworkbuddy case (new)updatedToolOutput)tests/test-run-hook-install-scope.shtests/test-tool-ready-readable-fixer.shtests/run-all-tests.shenv-check hard bypassfailures, reproduced identically on the unmodified base treetests/test_compress_response_hook.py/test_compress_schema_hook.py/test_resolve_agent_id.py/test_agentscope_middleware.py(py3.11)tests/test-qoder-adapter-install.sh(regression)tests/test-opencode-adapter-install.sh(regression)tests/test-package-raw.shmake stamp-adapter-templates+ manifest inspectionworkbuddytarget present with capabilities/actionsmake -n workbuddy-install/make -n workbuddy-uninstallbash -nsyntax check on all new scriptsPre-existing failures (verified identical on the unmodified base tree, unrelated to this change):
tests/test_rewrite_hook.py— 11 anchor-test failures: a system-installedrtkin 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'sXDG_DATA_HOMEsandbox.test_agentscope_middleware.pycannot import (StrEnumneeds 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-adaptersfull target — itsbuild-openclaw-pluginprerequisite performs an npm dependency build not needed for this change; the individual installer tests above were run directly instead.rpmbuildoftokenless.spec.in— a full RPM build requires the complete native build chain; the spec additions mirror the existing qwencode entries line-for-line./hookspanel review flow and per-productupdatedToolOutputsupport) needs verification on a machine with the product installed.