Skip to content

feat(local-agent): execute uninstall_teamai commands via sync + ack (sandbox-safe) - #249

Merged
jeff-r2026 merged 1 commit into
Tencent:mainfrom
m0Nst3r873:feat/http-source-cmd
Jul 30, 2026
Merged

feat(local-agent): execute uninstall_teamai commands via sync + ack (sandbox-safe)#249
jeff-r2026 merged 1 commit into
Tencent:mainfrom
m0Nst3r873:feat/http-source-cmd

Conversation

@m0Nst3r873

@m0Nst3r873 m0Nst3r873 commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

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 (a single teamai subcommand); the local agent runs it once and reports the result via the existing ack channel. Delivery, ack, and retry semantics are reused unchanged.

{ "id": 42, "type": "uninstall_teamai", "cmd": "teamai uninstall --force --agent codebuddy" }

Resolves #235. Converged to the clawpro ch.7 unified cmds[] contract (implemented in #261): the interface models "push a one-shot teamai command" as the specific type uninstall_teamai, so this PR routes only that type and does not add a generic type:"cmd" (which is not in the ch.7 enum and the backend does not send). Commands flow through the unified cmds[] parser from #261 (falls back to legacy commands[]).

Behavior

  • feat(local-agent): read unified cmds[] from sync response #261 skipped uninstall_teamai (placed it in UNIMPLEMENTED_COMMAND_TYPES, since no execution path existed). This PR adds the execution path and removes it from that set. Hook rule types (install_hook_rule / uninstall_hook_rule) stay skipped — out of scope.
  • Execution goes through runCmdCommand.

Security boundary (runCmdCommand)

  • teamai subcommands onlyargv[0] must strictly equal teamai; anything else is rejected (acked failed) and never executed. No arbitrary-shell surface.
  • No shellexecFile(process.execPath, [entry, ...args]); shell metacharacters are literal, no PATH dependency (works in bundled-node sandboxes).
  • Timeout / limits — 120s timeout, 4 MiB maxBuffer, error detail capped at 200 chars.
  • Kill switchTEAMAI_DISABLE_REMOTE_CMD=1 short-circuits and acks failed with remote cmd disabled by client.

Sandbox delivery

Changes 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. TEAMAI_ALLOW_SANDBOX_REPORT=1 keeps its original meaning.

Test Plan

  • npx tsc --noEmit — clean
  • npx vitest run — full suite green (1844 tests); new/updated tests cover the parseTeamaiCmd tokenizer, non-teamai rejection, TEAMAI_DISABLE_REMOTE_CMD kill switch, subcommand non-zero exit, uninstall_teamai execution + success ack, and the sandbox no-prune guarantee.
  • npm run build — success
  • End-to-end: drove the built binary via teamai hook-dispatch session-start --tool codebuddy against a mock backend returning an uninstall_teamai command in cmds[] — the cmd actually executed and acked success (previously, under feat(local-agent): read unified cmds[] from sync response #261 alone, it was silently skipped).

🤖 Generated with Claude Code

@m0Nst3r873
m0Nst3r873 force-pushed the feat/http-source-cmd branch from b02365e to 5ff02f0 Compare July 30, 2026 03:30
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>
@m0Nst3r873 m0Nst3r873 changed the title feat(http-source): push one-shot commands (type: "cmd") via sync + ack, sandbox-safe feat(local-agent): execute uninstall_teamai commands via sync + ack (sandbox-safe) Jul 30, 2026
@m0Nst3r873
m0Nst3r873 force-pushed the feat/http-source-cmd branch from 5ff02f0 to 3b89fee Compare July 30, 2026 06:53
@jeff-r2026
jeff-r2026 merged commit 5d468e7 into Tencent:main Jul 30, 2026
7 checks passed
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.

feat(http-source): push one-shot commands (type: "cmd") via sync + ack, sandbox-safe

2 participants