feat(local-agent): read unified cmds[] from sync response - #261
Merged
Conversation
Migrate the reporter's sync parsing to the unified cmds[] array (slug / version / handle_type / event / cmd) per clawpro spec ch.7, falling back to the legacy commands[] for older backends. Add handle_type-based resource classification and safely skip the not-yet-implemented types (install_hook_rule / uninstall_hook_rule / uninstall_teamai) before the suffix logic can misfire — uninstall_hook_rule ends in _rule and would otherwise be treated as a destructive rule uninstall. The skip guard also matches any hook command (handle_type === 'hook'), so a future hook type outside the known set still skips silently instead of being acked as a failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
m0Nst3r873
added a commit
to m0Nst3r873/teamai-cli
that referenced
this pull request
Jul 30, 2026
Add a `type: "cmd"` one-shot command to the HTTP source sync channel so the backend can push a single teamai subcommand (e.g. `teamai uninstall --agent claude`) to run once on the client, with the result reported via the existing ack channel. Delivery, ack, and retry semantics are reused unchanged. Security boundary: - teamai subcommands only — argv[0] must strictly equal `teamai`; anything else is rejected (acked failed) and never executed. - No shell — execFile(process.execPath, [entry, ...args]); shell metacharacters are literal, no PATH dependency (works in bundled-node sandboxes). - 120s timeout, 4 MiB maxBuffer, error detail capped at 200 chars. - TEAMAI_DISABLE_REMOTE_CMD=1 kill switch (acked failed). Route uninstall_teamai through the same cmd path: PR Tencent#261 landed it in UNIMPLEMENTED_COMMAND_TYPES (silently skipped, no execution path existed). Now that runCmdCommand exists, remove uninstall_teamai from that set and dispatch it (alongside type:"cmd") to runCmdCommand, so the clawpro three-phase uninstall (cmd = "teamai uninstall --force --agent <tool>") actually executes under the same teamai-only boundary and acks. Hook rule types stay skipped. Replaces the stale "skips uninstall_teamai" test with an execution test and adds a kill-switch test for uninstall_teamai. Also change the CloudStudio sandbox guard from "skip report + sync" to "skip report, still run sync + processCommands", so sandboxed agents can receive pushed commands. Report-side bookkeeping (plugin reconcile, binding prune, config save) stays gated behind the report path to avoid pruning host bindings not mounted in the container. Docs updated in both languages; unit tests cover the tokenizer, rejection, kill switch, subcommand failure, uninstall_teamai execution, and the sandbox no-prune guarantee. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 30, 2026
m0Nst3r873
added a commit
to m0Nst3r873/teamai-cli
that referenced
this pull request
Jul 30, 2026
Implement the clawpro three-phase uninstall_teamai command in the HTTP source sync channel. The backend pushes an uninstall_teamai command carrying a `cmd` string (e.g. "teamai uninstall --force --agent codebuddy"); the local agent runs it once and reports the result via the existing ack channel. Delivery, ack, and retry semantics are reused unchanged. PR Tencent#261 landed uninstall_teamai in UNIMPLEMENTED_COMMAND_TYPES (silently skipped, no execution path existed). This adds the execution path and removes it from that set; hook rule types stay skipped. Execution (runCmdCommand) security boundary: - teamai subcommands only — argv[0] must strictly equal `teamai`; anything else is rejected (acked failed) and never executed. - No shell — execFile(process.execPath, [entry, ...args]); shell metacharacters are literal, no PATH dependency (works in bundled-node sandboxes). - 120s timeout, 4 MiB maxBuffer, error detail capped at 200 chars. - TEAMAI_DISABLE_REMOTE_CMD=1 kill switch (acked failed). Converged to the clawpro ch.7 unified contract: the interface defines uninstall_teamai as the type that carries a one-shot `cmd`, so this drops the earlier generic `type:"cmd"` dispatch branch (not in the ch.7 type enum) and routes only uninstall_teamai. Commands flow through the unified cmds[] parser from Tencent#261. Also change the CloudStudio sandbox guard from "skip report + sync" to "skip report, still run sync + processCommands", so sandboxed agents can receive the pushed uninstall. Report-side bookkeeping (plugin reconcile, binding prune, config save) stays gated behind the report path to avoid pruning host bindings not mounted in the container. Docs updated in both languages; unit tests cover the tokenizer, rejection, kill switch, subcommand failure, uninstall_teamai execution, and the sandbox no-prune guarantee. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jeff-r2026
pushed a commit
that referenced
this pull request
Jul 30, 2026
…249) Implement the clawpro three-phase uninstall_teamai command in the HTTP source sync channel. The backend pushes an uninstall_teamai command carrying a `cmd` string (e.g. "teamai uninstall --force --agent codebuddy"); the local agent runs it once and reports the result via the existing ack channel. Delivery, ack, and retry semantics are reused unchanged. PR #261 landed uninstall_teamai in UNIMPLEMENTED_COMMAND_TYPES (silently skipped, no execution path existed). This adds the execution path and removes it from that set; hook rule types stay skipped. Execution (runCmdCommand) security boundary: - teamai subcommands only — argv[0] must strictly equal `teamai`; anything else is rejected (acked failed) and never executed. - No shell — execFile(process.execPath, [entry, ...args]); shell metacharacters are literal, no PATH dependency (works in bundled-node sandboxes). - 120s timeout, 4 MiB maxBuffer, error detail capped at 200 chars. - TEAMAI_DISABLE_REMOTE_CMD=1 kill switch (acked failed). Converged to the clawpro ch.7 unified contract: the interface defines uninstall_teamai as the type that carries a one-shot `cmd`, so this drops the earlier generic `type:"cmd"` dispatch branch (not in the ch.7 type enum) and routes only uninstall_teamai. Commands flow through the unified cmds[] parser from #261. Also change the CloudStudio sandbox guard from "skip report + sync" to "skip report, still run sync + processCommands", so sandboxed agents can receive the pushed uninstall. Report-side bookkeeping (plugin reconcile, binding prune, config save) stays gated behind the report path to avoid pruning host bindings not mounted in the container. Docs updated in both languages; unit tests cover the tokenizer, rejection, kill switch, subcommand failure, uninstall_teamai execution, and the sandbox no-prune guarantee. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
commands[]array to the unifiedcmds[]array (slug/version/handle_type/event/cmd), per the clawpro spec ch.7. No new commands or routes — a format unification with backward compatibility.commands[]for older backends (emptycmds[]is treated as "cmds not available" and also falls back — the backend sends identical data in both arrays, so this only affects old backends).handle_type-based classification (prompt→claudemd,rule→rule) while retaining the legacyrule_type/suffix logic as thecommands[]fallback.install_hook_rule/uninstall_hook_rule/uninstall_teamai) before the suffix logic can misfire —uninstall_hook_ruleends in_ruleand would otherwise be treated as a destructive rule uninstall. The skip guard also matches anyhandle_type === 'hook', so a future hook type outside the known set still skips silently instead of being acked as a failure.Test Plan
npx tsc --noEmit— cleannpx vitest run— 1837 tests pass (10 new tests for the cmds[] migration)npm run build— successteamai hook-dispatch session-start --tool codebuddyagainst a mock backend returning both arrays.cmds[]install ran (skill on disk, manifest version, acksuccess);install_hook_rule/uninstall_teamai/ a poisoned legacycommands[]uninstall were all skipped with no ack.🤖 Generated with Claude Code