Skip to content

feat(local-agent): read unified cmds[] from sync response - #261

Merged
jeff-r2026 merged 1 commit into
Tencent:mainfrom
m0Nst3r873:feature/uninstall-agent
Jul 29, 2026
Merged

feat(local-agent): read unified cmds[] from sync response#261
jeff-r2026 merged 1 commit into
Tencent:mainfrom
m0Nst3r873:feature/uninstall-agent

Conversation

@m0Nst3r873

Copy link
Copy Markdown
Collaborator

Summary

  • Migrates the local-agent reporter's sync parsing from the legacy heterogeneous commands[] array to the unified cmds[] array (slug / version / handle_type / event / cmd), per the clawpro spec ch.7. No new commands or routes — a format unification with backward compatibility.
  • Falls back to commands[] for older backends (empty cmds[] is treated as "cmds not available" and also falls back — the backend sends identical data in both arrays, so this only affects old backends).
  • Adds handle_type-based classification (prompt→claudemd, rule→rule) while retaining the legacy rule_type/suffix logic as the commands[] fallback.
  • Safely skips 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 handle_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 — clean
  • npx vitest run — 1837 tests pass (10 new tests for the cmds[] migration)
  • npm run build — success
  • End-to-end: drove the built binary via teamai hook-dispatch session-start --tool codebuddy against a mock backend returning both arrays. cmds[] install ran (skill on disk, manifest version, ack success); install_hook_rule / uninstall_teamai / a poisoned legacy commands[] uninstall were all skipped with no ack.

🤖 Generated with Claude Code

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>
@jeff-r2026
jeff-r2026 merged commit 3f13422 into Tencent:main Jul 29, 2026
6 checks passed
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants