Skip to content

Add agent suite (chat UI, ACP integration, skills, sync CLI)#2511

Draft
Jameswlepage wants to merge 21 commits intotrunkfrom
add/agent-suite
Draft

Add agent suite (chat UI, ACP integration, skills, sync CLI)#2511
Jameswlepage wants to merge 21 commits intotrunkfrom
add/agent-suite

Conversation

@Jameswlepage
Copy link

Summary

  • Introduce the agent chat UI and ACP-backed workflows inside Studio.
  • Add agent skills discovery/install and instruction management.
  • Expand CLI sync workflows (connect/pull/push/status) and related UX updates.

Key features

  • Agent chat experience with model selection, tool results, and UI polish.
  • ACP session management, agent detection, and permissions flows.
  • Agent skills discovery/install and instruction templating.
  • Sync CLI workflows for connecting sites and pushing/pulling content.

Security & safety

  • Guard ACP file access with path traversal checks.
  • Prompt on agent permission requests.
  • Restrict agent server CORS to trusted origins.

Testing

  • npm run lint
  • npm run test

Notes

  • Tests emit React act(...) warnings in assistant UI tests.
  • jsdom CSS parse warnings from @wordpress/ui styles.
  • npm warns about engine/config mismatch (node/npm versions).

- Filter available agents to show only wpcom, anthropic-builtin, claude-code-acp, opencode, and codex-acp
- Add --yes --quiet flags to npx commands to suppress install prompts
- Add npx fallback for codex-acp when binary not installed
- Combine stdout/stderr for JSON-RPC stream (codex-acp writes to stderr)
- Filter echoed requests from stream to prevent SDK confusion
- Remove TTY requirement for codex-acp (ACP wrapper uses stdio, not interactive mode)
- Change Install All button from primary to link variant
- Simplify description text to 'Install instructions so agents know how to use Studio'
- Interactive mode: studio chat
- Single-shot mode: studio chat "message"
- Requires WordPress.com authentication
Implements full WordPress.com sync capabilities in the CLI with database export/import and automatic site detection from working directory.

Features:
- Pull: Downloads backup from WordPress.com, extracts, imports wp-content and database
- Push: Exports database (split by table), creates tar.gz, uploads via TUS, triggers remote import
- Smart site detection: Site ID now optional when running from site directory
- Full database operations via WP-CLI integration
- Progress tracking with real-time updates
- Resumable uploads with TUS protocol
- Size validation and error handling
Enhances the default AGENTS.md template with complete guidelines for AI assistants working in WordPress Studio sites.

Key additions:
- SQLite database documentation (not MySQL/MariaDB)
- Complete sync command reference (pull, push, connect, disconnect)
- Auto-detect site ID information for commands
- Telex CLI documentation
- Best practices for AI agents
- Common workflow examples
- Environment details and architecture notes

This provides AI assistants with the context they need to effectively work with Studio sites, including database operations, WP-CLI access, and WordPress.com sync capabilities.
- Add 30s timeout to initialize() and newSession() calls
- Wrap initialization in try-catch with detailed error logging
- Prevents indefinite hanging when agents don't respond
- Add AGENT_ARGS map for agent-specific arguments
- Configure opencode to use 'acp' subcommand to start ACP server
- Fixes initialization timeout issue
- Add enableHotReload field to site details
- Add toggle in Edit Site modal with experimental label
- Display current status in site settings
- Includes helpful description about automatic reloading
- Save enableHotReload directly to storage (not a CLI option)
- Update server details to reflect the change
- Now properly persists when toggled in Edit Site modal
- Add --hot-reload flag to 'studio site set' command
- Enable/disable hot reload from command line
- Update agent instructions template with hot reload info
- Document in site management commands and best practices
- New command: studio site open [path]
- Automatically starts site if not running
- Auto-login enabled by default (--no-login to skip)
- Navigate to specific paths: studio site open /wp-admin
- Perfect for AI agents to build + test in one workflow
- Updated agent instructions with examples
- Add AGENT_INSTRUCTIONS_VERSION constant (YYYYMMDD.revision format)
- Embed version in template as HTML comment
- Extract and compare versions from installed files
- Show 'Update Available' badge for outdated files
- Change button text to 'Update' when file is outdated
- Show 'Update All' when any files are outdated
- Help users stay current with latest Studio CLI commands
- Change DEFAULT_SKILLS_REPO to WordPress/agent-skills
- Update all GitHub URLs and references
- Update comments and documentation
- Agent skills now fetched from WordPress org
return ptyProc as unknown as ChildProcess;
}

const proc = spawn( command, args, {

Check failure

Code scanning / CodeQL

Uncontrolled command line Critical

This command line depends on a
user-provided value
.

Copilot Autofix

AI 15 days ago

In general terms, the safest fix is to ensure that the command passed to spawn is constrained to a strict allowlist of known‑good executables, rather than trusting arbitrary values from the remote registry. The code already has an ALLOWED_AGENT_COMMANDS map in acp-process-manager.ts and an ALTERNATIVE_BINARIES map in agent-detection.ts; we should align the registry‑derived commands with these allowlists so that tampering with the registry cannot introduce new executable names.

The single best way to fix this, without changing external behavior for legitimate registry data, is to sanitize the command derived from the registry in getAgentCommand. For known agents whose commands are later asserted by ALLOWED_AGENT_COMMANDS (e.g., codex-acp, claude-code-acp, opencode), we can override whatever binary name is supplied in the registry’s distribution.binary.*.cmd field with a hard‑coded, expected binary name. That way, even if the registry is compromised, the process manager will still only run the trusted binaries it already allows. Concretely:

  • In src/modules/acp/lib/acp-registry.ts, define a small BINARY_COMMAND_OVERRIDES map keyed by agent ID with the allowed executable name for that agent.
  • In getAgentCommand(agent), when using a binary distribution, compute binaryName from target.cmd as today, but then, if the agent ID exists in BINARY_COMMAND_OVERRIDES, replace binaryName with the override value.
  • Optionally, enforce a simple validation on the final binaryName (for example, disallowing path separators) to ensure it is just a bare executable name.

With this change, the command that reaches spawn for registry‑defined binary distributions is guaranteed to be a member of a hard‑coded set, consistent with the existing ALLOWED_AGENT_COMMANDS configuration, and CodeQL’s taint flow is effectively cut at the registry boundary.

Suggested changeset 1
src/modules/acp/lib/acp-registry.ts
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/modules/acp/lib/acp-registry.ts b/src/modules/acp/lib/acp-registry.ts
--- a/src/modules/acp/lib/acp-registry.ts
+++ b/src/modules/acp/lib/acp-registry.ts
@@ -13,6 +13,18 @@
 const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
 
 /**
+ * Hard-coded overrides for binary command names by agent ID.
+ * This ensures that even if the remote registry is compromised,
+ * we only execute known-good binaries for supported agents.
+ */
+const BINARY_COMMAND_OVERRIDES: Record< string, string > = {
+	// These should stay in sync with ALLOWED_AGENT_COMMANDS in acp-process-manager.ts
+	'codex-acp': 'codex-acp',
+	'claude-code-acp': 'claude-code-acp',
+	opencode: 'opencode',
+};
+
+/**
  * Distribution types for ACP agents.
  */
 export interface NpxDistribution {
@@ -253,8 +265,18 @@
 
 		// For now, assume the binary is installed and in PATH
 		// TODO: Implement binary download and management
-		const binaryName = path.basename( target.cmd ).replace( /^\.\//, '' );
+		let binaryName = path.basename( target.cmd ).replace( /^\.\//, '' );
 
+		// If we have a hard-coded override for this agent, use it instead of the registry value.
+		if ( BINARY_COMMAND_OVERRIDES[ agent.id ] ) {
+			binaryName = BINARY_COMMAND_OVERRIDES[ agent.id ];
+		}
+
+		// Basic safety: ensure we're not executing a path with separators.
+		if ( binaryName.includes( '/' ) || binaryName.includes( '\\' ) ) {
+			return null;
+		}
+
 		return {
 			command: binaryName,
 			args: target.args ?? [],
EOF
@@ -13,6 +13,18 @@
const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours

/**
* Hard-coded overrides for binary command names by agent ID.
* This ensures that even if the remote registry is compromised,
* we only execute known-good binaries for supported agents.
*/
const BINARY_COMMAND_OVERRIDES: Record< string, string > = {
// These should stay in sync with ALLOWED_AGENT_COMMANDS in acp-process-manager.ts
'codex-acp': 'codex-acp',
'claude-code-acp': 'claude-code-acp',
opencode: 'opencode',
};

/**
* Distribution types for ACP agents.
*/
export interface NpxDistribution {
@@ -253,8 +265,18 @@

// For now, assume the binary is installed and in PATH
// TODO: Implement binary download and management
const binaryName = path.basename( target.cmd ).replace( /^\.\//, '' );
let binaryName = path.basename( target.cmd ).replace( /^\.\//, '' );

// If we have a hard-coded override for this agent, use it instead of the registry value.
if ( BINARY_COMMAND_OVERRIDES[ agent.id ] ) {
binaryName = BINARY_COMMAND_OVERRIDES[ agent.id ];
}

// Basic safety: ensure we're not executing a path with separators.
if ( binaryName.includes( '/' ) || binaryName.includes( '\\' ) ) {
return null;
}

return {
command: binaryName,
args: target.args ?? [],
Copilot is powered by AI and may make mistakes. Always verify output.
@wojtekn
Copy link
Contributor

wojtekn commented Feb 11, 2026

@Jameswlepage, since it's a proof of concept, I'm adding the "do not merge" label to help us navigate the PR list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants