feat: add remote-acpx ACP runtime backend for node dispatch#1
feat: add remote-acpx ACP runtime backend for node dispatch#1
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances OpenClaw's capability to integrate with external execution environments by introducing a remote ACP backend. It enables the system to offload AI agent tasks, specifically Claude Code CLI operations, to dedicated Mac nodes. This architectural change facilitates distributed processing and expands the range of tools and environments OpenClaw can interact with, improving flexibility and performance for complex development tasks. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a remote ACP runtime backend for node dispatch, including a new claude-node extension. The changes are extensive, adding a pub/sub bridge for state sharing, a Mac-side ACP handler, and wiring everything through the gateway. The implementation is generally solid and robust. I have one suggestion regarding type consistency in the new claude-node tool to improve maintainability.
| ); | ||
|
|
||
| // Parse result | ||
| const payload = result?.payload ?? (result as NodeInvokeResult["payload"]); |
There was a problem hiding this comment.
The logic to extract payload from result is a bit confusing and suggests an inconsistent API response from callGatewayTool.
const payload = result?.payload ?? (result as NodeInvokeResult["payload"]);The type of result is NodeInvokeResult | null | undefined, where NodeInvokeResult is { payload?: ... }. The expression result?.payload should be sufficient to access the payload. The fallback (result as NodeInvokeResult["payload"]) implies that result itself might sometimes be the payload object, which is inconsistent with the NodeInvokeResult type.
This pattern can lead to confusion and potential runtime errors. For better maintainability and type safety, I recommend making the return type of callGatewayTool consistent.
If result is always NodeInvokeResult | null | undefined, this line could be simplified to:
const payload = result?.payload;If the current implementation is necessary due to the API's behavior, a comment explaining this would be very helpful for future maintainers.
f47e3ee to
bd58347
Compare
… token collectStatusIssues previously checked account.channelAccessToken directly, but this field is stripped by projectSafeChannelAccountSnapshotFields for security. This caused 'openclaw status' to always report WARN even when the token is valid and the LINE provider starts successfully. Use account.configured instead, which is already computed by buildChannelAccountSnapshot and correctly reflects whether credentials are present. This is consistent with how other channels (e.g. Telegram) implement their status checks. Fixes openclaw#45693
Webhook channels (LINE, Zalo, Nextcloud Talk, BlueBubbles) are incorrectly flagged as stale-socket during quiet periods because snapshot.mode is always undefined, making the mode !== "webhook" guard in evaluateChannelHealth dead code. Add mode: "webhook" to each webhook plugin's describeAccount and propagate described.mode in getRuntimeSnapshot. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The QMD memory system uses a fixed 4:1 chars-to-tokens ratio for chunk sizing, which severely underestimates CJK (Chinese/Japanese/Korean) text where each character is roughly 1 token. This causes oversized chunks for CJK users, degrading vector search quality and wasting context window space. Changes: - Add shared src/utils/cjk-chars.ts module with CJK-aware character counting (estimateStringChars) and token estimation helpers - Update chunkMarkdown() in src/memory/internal.ts to use weighted character lengths for chunk boundary decisions and overlap calculation - Replace hardcoded estimateTokensFromChars in the context report command with the shared utility - Add 13 unit tests for the CJK estimation module and 5 new tests for CJK-aware memory chunking behavior Backward compatible: pure ASCII/Latin text behavior is unchanged. Closes openclaw#39965 Related: openclaw#40216
- Use code-point length instead of UTF-16 length in estimateStringChars() so that CJK Extension B+ surrogate pairs (U+20000+) are counted as 1 character, not 2 (fixes ~25% overestimate for rare characters). - Change long-line split step from maxChars to chunking.tokens so that CJK lines are sliced into token-budget-sized segments instead of char-budget-sized segments that produce ~4x oversized chunks. - Add tests for both fixes: surrogate-pair handling and long CJK line splitting. Addresses review feedback from Greptile and Codex bots.
…nsistency - Two-pass line splitting: first slice at maxChars (unchanged for Latin), then re-split only CJK-heavy segments at chunking.tokens. This preserves the original ~800-char segments for ASCII lines while keeping CJK chunks within the token budget. - Narrow surrogate-pair adjustment to CJK Extension B+ range (D840–D87E) only, so emoji surrogate pairs are not affected. Mixed CJK+emoji text is now handled consistently regardless of composition. - Add tests: emoji handling (2), Latin backward-compat long-line (1). Addresses Codex P1 (oversized CJK segments) and P2s (Latin over-splitting, emoji surrogate inconsistency).
When re-splitting CJK-heavy segments at chunking.tokens, check whether the slice boundary falls on a high surrogate (0xD800–0xDBFF) and if so extend by one code unit to keep the pair intact. Prevents producing broken surrogate halves for CJK Extension B+ characters (U+20000+). Add test verifying no lone surrogates appear when splitting lines of surrogate-pair characters with an odd token budget. Addresses third-round Codex P2 review comment.
37febed to
2527807
Compare
Cherry-picked from bd58347, resolved conflicts for v2026.3.28 base.
…ntRuntimeAcpConfig Cherry-picked from 21b117e. Adapted for v2026.3.28 refactored session-utils: added acpCwd field to GatewaySessionRow (populated from SessionEntry.acp.cwd) since the intermediate entry object was removed in the single-pass buildGatewaySessionRow refactor.
AgentSummary now surfaces the runtime descriptor (type, acp.cwd, acp.nodeName, etc.) so that downstream consumers like the coding-assistant skill can resolve the correct remote working directory for ACP agents instead of getting the gateway-local workspace path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2527807 to
dd41b3a
Compare
Summary
acp-node-event-bridge) usingSymbol.forglobalThis for cross-module-loader state sharinginvoke-acp) that spawnsacpxsubprocess per turn, streaming ndjson back as eventsplugin-sdk/remote-acpxsurface for the remote-acpx extensionclaude-nodeextension with Claude Code CLI dispatch skillacp.*events through node-host runner and gateway event handler/acp spawnto resolveagents.listentries withruntime.type=acp@marxbiotech/openclawpackage name in version/update checksKey changes
src/gateway/acp-node-event-bridge.ts— Singleton pub/sub bridge (gateway ↔ extension)src/node-host/invoke-acp.ts— Mac-sideacp.spawn/acp.turn/acp.killhandlersrc/gateway/server-node-events.ts— Routeacp.spawned/acp.message/acp.exited/acp.errorto bridgesrc/auto-reply/reply/commands-acp/shared.ts— Resolveagents.listentries for spawnTest plan
@marxbiotech/openclaw@2026.3.12-2make nodeconnects Mac to remote gateway/acp spawn claudedispatches to Mac node via remote-acpxacp.turnexecutes acpx claude on Mac and streams response back🤖 Generated with Claude Code