426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
191 lines
14 KiB
Markdown
191 lines
14 KiB
Markdown
# @elizaos/plugin-coding-tools
|
|
|
|
Native Claude-Code-style coding tools (FILE, SHELL, WORKTREE) for Eliza agents running in code/terminal/automation contexts.
|
|
|
|
## Purpose / role
|
|
|
|
Adds filesystem operations, shell command execution, and git worktree management to an Eliza agent. The plugin is **opt-in**: it auto-enables when `config.features.codingTools` (or legacy `config.features["coding-agent"]`) is truthy and the runtime environment supports a terminal (disabled on `ELIZA_BUILD_VARIANT=store` and on iOS; Android only when `ELIZA_RUNTIME_MODE=local-yolo`). All actions are gated to `contexts: ["code", "terminal", "automation"]`. FILE and WORKTREE require `roleGate: minRole=ADMIN`; SHELL requires `roleGate: minRole=OWNER`.
|
|
|
|
## Plugin surface
|
|
|
|
### Actions
|
|
|
|
- **FILE** — umbrella for `read/write/edit/grep/glob/ls`. Dispatches to per-operation handlers. Supports `target=device` for `read/write/ls` through a `device_filesystem` bridge service (mobile). Similes: `FILE_OPERATION`, `FILE_IO`.
|
|
- **SHELL** — `action=run` executes a command via `/bin/bash -c`; `action=view_history`/`clear_history` read or clear per-conversation command history (backed by an external `shell` service when present). Per-call `timeout` (ms) is clamped to `[100, 600000]`, default `CODING_TOOLS_SHELL_TIMEOUT_MS` (120000). Similes: `BASH`, `EXEC`, `RUN_COMMAND`.
|
|
- **WORKTREE** — umbrella for `enter/exit` git worktrees. On enter, registers new root in `SandboxService` and pushes to `SessionCwdService` stack. On exit, pops. Similes: `GIT_WORKTREE`.
|
|
|
|
### Provider
|
|
|
|
- **AVAILABLE_CODING_TOOLS** — injects the list of available tool names (`FILE`, `SHELL`, `WORKTREE`) into agent state at position `-10`. Stable/agent-scoped cache.
|
|
|
|
### Services
|
|
|
|
| Service | `serviceType` constant | Purpose |
|
|
|---|---|---|
|
|
| `SandboxService` | `CODING_TOOLS_SANDBOX` | Path-blocklist policy. Validates every path before read/write. Defaults block `~/pvt`, `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.docker`, `~/.kube`, `~/.netrc`, `~/Library`, plus per-OS system paths. Optional allow-roots via `CODING_TOOLS_WORKSPACE_ROOTS`. |
|
|
| `FileStateService` | `CODING_TOOLS_FILE_STATE` | Per-(conversation, file) mtime tracking. Write/Edit check that the file was not externally modified since the last Read. |
|
|
| `SessionCwdService` | `CODING_TOOLS_SESSION_CWD` | Per-conversation working directory. Defaults to `process.cwd()`. Glob/Grep/LS/Shell use this when no explicit `path`/`cwd` is given. Worktree push/pop mutates it. |
|
|
| `RipgrepService` | `CODING_TOOLS_RIPGREP` | Wraps `@vscode/ripgrep` binary. Used by `grep` operation. Always excludes VCS dirs. 30 s hard cap. |
|
|
|
|
### Other exports
|
|
|
|
- `CodingTaskExecutor` — task executor that maps task specs matching coding-related keywords into agent actions. Consumed externally by orchestration plugins.
|
|
- `coding-agent-context` (Zod schemas) — `FileOperationSchema`, `CommandResultSchema`, `CapturedErrorSchema`, etc. Used to validate structured outputs from coding loops.
|
|
|
|
## Layout
|
|
|
|
```
|
|
plugins/plugin-coding-tools/
|
|
src/
|
|
index.ts Plugin entry — exports codingToolsPlugin, all services, types
|
|
types.ts Service-type constants, ToolFailure/ToolResult types, CODING_TOOLS_CONTEXTS
|
|
actions/
|
|
file.ts FILE umbrella action — routes to per-op handlers
|
|
bash.ts SHELL action implementation
|
|
worktree.ts WORKTREE umbrella action
|
|
read.ts / write.ts / edit.ts FILE sub-handlers for read/write/edit
|
|
grep.ts / glob.ts / ls.ts FILE sub-handlers for grep/glob/ls
|
|
enter-worktree.ts / exit-worktree.ts WORKTREE sub-handlers
|
|
index.ts Re-exports all action handlers
|
|
providers/
|
|
available-tools.ts AVAILABLE_CODING_TOOLS provider
|
|
services/
|
|
sandbox-service.ts Path policy (blocklist + allow-roots)
|
|
file-state-service.ts Per-conversation file mtime tracking
|
|
session-cwd-service.ts Per-conversation working directory + worktree stack
|
|
ripgrep-service.ts @vscode/ripgrep wrapper
|
|
coding-task-executor.ts CodingTaskExecutor (external task delegation)
|
|
coding-agent-context.ts Zod schemas for coding-agent context types
|
|
index.ts Re-exports all services
|
|
lib/
|
|
format.ts Param readers (readStringParam, readNumberParam), successActionResult, failureToActionResult
|
|
path-utils.ts isAbsolutePath, isWithin, resolveRealPath, isUncPath
|
|
run-shell.ts runShell helper (child_process wrapper with timeout/streaming)
|
|
run-git-command.ts runGitCommand helper
|
|
terminal-capabilities.ts Platform capability detection
|
|
secrets.ts detectSecrets — flags AWS/GitHub/OpenAI/etc. tokens to gate WRITE/EDIT
|
|
auto-enable.ts Lightweight auto-enable module (env reads only; no plugin runtime imports)
|
|
AGENT_CONTRACT.md Implementation brief for action-writing agents
|
|
build.ts build script (Bun.build + tsc d.ts emit)
|
|
```
|
|
|
|
## Commands
|
|
|
|
Scripts are defined in `package.json`; run them from the repo root with `bun run --cwd`:
|
|
|
|
```bash
|
|
bun run --cwd plugins/plugin-coding-tools clean # remove build output
|
|
bun run --cwd plugins/plugin-coding-tools build # build package artifacts
|
|
bun run --cwd plugins/plugin-coding-tools dev # development build/watch lane
|
|
bun run --cwd plugins/plugin-coding-tools typecheck # TypeScript typecheck
|
|
bun run --cwd plugins/plugin-coding-tools check # package check alias
|
|
bun run --cwd plugins/plugin-coding-tools lint # mutating Biome check
|
|
bun run --cwd plugins/plugin-coding-tools lint:check # read-only Biome check
|
|
bun run --cwd plugins/plugin-coding-tools format # write formatting
|
|
bun run --cwd plugins/plugin-coding-tools format:check # read-only formatting check
|
|
bun run --cwd plugins/plugin-coding-tools test # run package tests
|
|
```
|
|
|
|
## Config / env vars
|
|
|
|
All settings are read via `runtime.getSetting(key)` or `process.env`. None are required.
|
|
|
|
| Env var | Default | Description |
|
|
|---|---|---|
|
|
| `CODING_TOOLS_WORKSPACE_ROOTS` | `process.cwd()` | Comma-separated absolute paths the tools may access. When set, paths outside these roots are rejected. |
|
|
| `CODING_TOOLS_BLOCKED_PATHS` | (built-in list) | Comma-separated absolute paths — **replaces** the default blocklist. |
|
|
| `CODING_TOOLS_BLOCKED_PATHS_ADD` | — | Comma-separated paths to **add** to the default blocklist. |
|
|
| `CODING_TOOLS_SHELL` | (auto-detected) | Override the shell binary used by SHELL action. Takes priority over `SHELL`. Useful on Android/AOSP where the default shell path may not be executable. |
|
|
| `CODING_TOOLS_SHELL_TIMEOUT_MS` | `120000` | Default SHELL timeout (ms); per-call `timeout` clamps to `[100, 600000]`. |
|
|
| `CODING_TOOLS_MAX_READ_LINES` | `2000` | Max lines returned by FILE action=read before truncation. |
|
|
| `CODING_TOOLS_MAX_FILE_SIZE_BYTES` | `262144` | Pre-stat byte cap on FILE action=read. Larger files are rejected. |
|
|
| `CODING_TOOLS_GREP_HEAD_LIMIT` | `250` | Default `head_limit` for GREP output. Set to 0 to disable. |
|
|
|
|
Auto-enable keys (in agent `config.features`):
|
|
- `config.features.codingTools` (canonical) — `true` or `{ enabled: true }`.
|
|
- `config.features["coding-agent"]` (legacy alias).
|
|
|
|
Runtime gating env vars (read by `auto-enable.ts` and `index.ts`):
|
|
- `ELIZA_BUILD_VARIANT` — if `store`, plugin is disabled.
|
|
- `ELIZA_PLATFORM` — `android`/`ios` disables unless local-yolo mode.
|
|
- `ELIZA_RUNTIME_MODE` / `RUNTIME_MODE` / `LOCAL_RUNTIME_MODE` — `local-yolo` enables on Android.
|
|
|
|
## How to extend
|
|
|
|
### Add a new FILE sub-operation
|
|
|
|
1. Create `src/actions/<op>.ts` exporting a `<op>Handler` function with the `FileHandler` signature (`(runtime, message, state, options, callback) => Promise<ActionResult>`).
|
|
2. Export it from `src/actions/index.ts`.
|
|
3. Add the op name to `FILE_OPERATIONS` in `src/actions/file.ts` and wire it into `FILE_ACTIONS`.
|
|
4. Validate paths through `SandboxService.validatePath` before any filesystem access.
|
|
5. Record reads via `FileStateService.recordRead` and check writability via `FileStateService.assertWritable` before write/edit ops.
|
|
|
|
### Add a new top-level action
|
|
|
|
1. Create `src/actions/<action>.ts` exporting a `const <name>Action: Action`.
|
|
2. Export from `src/actions/index.ts`.
|
|
3. Import and add to the `actions` array in `src/index.ts`.
|
|
4. Use `contexts: [...CODING_TOOLS_CONTEXTS]` and `contextGate: { anyOf: [...CODING_TOOLS_CONTEXTS] }` so the action only fires in coding contexts.
|
|
5. Use `roleGate: { minRole: "ADMIN" }` for FILE/WORKTREE actions, or `roleGate: { minRole: "OWNER" }` for SHELL-equivalent actions — match the role of the existing action you are most similar to.
|
|
|
|
### Add a new service
|
|
|
|
1. Extend `Service` from `@elizaos/core`. Implement `static async start(runtime)` and `async stop()`.
|
|
2. Assign a string constant as `serviceType` in `src/types.ts`.
|
|
3. Export from `src/services/index.ts`.
|
|
4. Add to `services` array in `src/index.ts` and handle `stop()` in the `dispose` hook.
|
|
|
|
## Conventions / gotchas
|
|
|
|
- **All file paths must be absolute** for READ/WRITE/EDIT operations. GLOB/GREP/LS accept absolute or default to `SessionCwdService.getCwd(message.roomId)`.
|
|
- **Always validate paths through `SandboxService.validatePath`** before any filesystem access. Never bypass this.
|
|
- **Read before write**: `FileStateService.assertWritable` will reject a write if the file was modified externally since the last read. The agent must re-read first.
|
|
- **`conversationId` = `message.roomId`** (string-coerced). Missing `roomId` is a hard failure.
|
|
- **Never throw from a handler** — return `failureToActionResult({ reason, message })` instead.
|
|
- The `@vscode/ripgrep` binary is resolved at `RipgrepService` start time; if that import fails it falls back to a system `rg` on `PATH`.
|
|
- The `device_filesystem` bridge (`target=device` on FILE) is provided by a separate service (`device_filesystem` service type) registered by a platform plugin (e.g. mobile). The coding-tools plugin does not register it — it only consumes it when present.
|
|
- Tests are co-located `*.test.ts` files beside their source in `src/actions/`, `src/services/`, and `src/lib/`. Integration tests live in `__tests__/plugin-integration.test.ts` at the package root. See `AGENT_CONTRACT.md` for the action implementation brief.
|
|
- Import paths must use the `.js` extension on relative imports (ESM requirement).
|
|
|
|
<!-- BEGIN: evidence-and-e2e-mandate (managed; canonical standard = repo-root AGENTS.md) -->
|
|
## ⛔ NON-NEGOTIABLE — evidence, trajectories & real end-to-end tests
|
|
|
|
> The binding, repo-wide standard is **[AGENTS.md](../../AGENTS.md)**. Read it.
|
|
> Nothing in this package is *done* until it is *proven* done — a reviewer must confirm it
|
|
> works **without reading the code**, from the artifacts you attach. This applies to **every**
|
|
> feature, fix, refactor, and chore here. "Tests pass" is not proof; "CI is green" is not proof.
|
|
|
|
- **Record AND read model trajectories.** Capture the *actual* inputs and outputs of the model
|
|
from a **live** LLM — not the deterministic proxy, not a mock: the prompt, the
|
|
providers/context, the raw model output, every tool/action call, and the result. Then **open
|
|
the trajectory and review it by hand.** A captured-but-unread trajectory is not evidence
|
|
(`packages/scenario-runner/bin/eliza-scenarios run <scenario> --report <out>`).
|
|
- **Real, full-featured E2E — no larp.** Every feature ships detailed end-to-end tests that
|
|
drive the *real* path end to end. Not the happy "front door" only: cover error paths,
|
|
edge/empty/invalid input, concurrency, roles/permissions, and adversarial input. A test that
|
|
asserts against a mock/stub/fixture standing in for the thing under test **does not count**.
|
|
If the real model/device/chain/connector/account is hard to reach, **make it reachable — that
|
|
is the work**, not an excuse to mock. If the existing tests here are shallow or mocked, fixing
|
|
them is part of your change.
|
|
- **Screenshots + logs at every phase**, plus a **complete walkthrough video/run-through** of
|
|
the entire feature or view, start to finish (`bun run test:e2e:record`).
|
|
- **Manually review every artifact the change touches** — never just the green check: client
|
|
logs (console + network), server logs (`[ClassName] …`), the model trajectories in and out,
|
|
before/after full-page screenshots, **and the domain artifacts listed below for this package.**
|
|
- **No residuals. No shortcuts.** The goal is not "done" — it is *everything* done. Clear every
|
|
blocker by the **hard path**: build the real architecture, stand up the real
|
|
model/device/service, actually test it. Never leave a TODO, a stub, a stepping-stone, or a
|
|
"follow-up." When unsure, research thoroughly, weigh the options, and ship the best,
|
|
highest-effort, production-ready version. Keep going until every possibility is exhausted.
|
|
|
|
Artifacts → attached inline in the PR (MP4 video, JPG screenshots, logs in `<details>`); attach each evidence type **or**
|
|
explicitly mark it N/A with a reason — never leave it blank. If `develop` moved and changed
|
|
behavior, **re-capture** evidence; stale proof is worse than none.
|
|
|
|
**Capture & manually review for this package — CLI / tooling:**
|
|
- The real command/flow invocation transcript (args in, stdout/stderr, exit code) and the artifacts it generated (files, scaffolds, manifests, screenshots/recordings).
|
|
- Failure paths: bad args, missing deps, partial state, permission/network errors.
|
|
- A recording/log of the actual run end to end — not a unit test of one helper.
|
|
- Any model interaction captured as a live trajectory and reviewed.
|
|
<!-- END: evidence-and-e2e-mandate -->
|