Skip to content

Conversation

@britannio
Copy link
Collaborator

@britannio britannio commented Oct 18, 2025

Closes #1004, Closes #889, Closes #985

  • File MCP issue
  • File "type":"error","source":"cli" issue
  • The autonomy dropdown is resetting to 'medium' after being saved
  • Update docs
  • Display file writes correctly?
  • Show model being used (as we do for Codex)
  • Correlate errors correctly there's an insufficient permissions error
  • Remove temporary files (tasks/*, droid-json/*)

<droid-docs>
# Overview

> Non-interactive execution mode for CI/CD pipelines and automation scripts.

# Droid Exec (Headless CLI)

Droid Exec is Factory's headless execution mode designed for automation workflows. Unlike the interactive CLI, `droid exec` runs as a one-shot command that completes a task and exits, making it ideal for CI/CD pipelines, shell scripts, and batch processing.

## Summary and goals

Droid Exec is a one-shot task runner designed to:

* Produce readable logs, and structured artifacts when requested
* Enforce opt-in for mutations/command execution (secure-by-default)
* Fail fast on permission violations with clear errors
* Support simple composition for batch and parallel work

<CardGroup cols={2}>
  <Card title="Non-Interactive" icon="terminal">
    Single run execution that writes to stdout/stderr for CI/CD integration
  </Card>

  <Card title="Secure by Default" icon="lock">
    Read-only by default with explicit opt-in for mutations via autonomy levels
  </Card>

  <Card title="Composable" icon="puzzle">
    Designed for shell scripting, parallel execution, and pipeline integration
  </Card>

  <Card title="Clean Output" icon="file-export">
    Structured output formats and artifacts for automated processing
  </Card>
</CardGroup>

## Execution model

* Non-interactive single run that writes to stdout/stderr.
* Default is spec-mode: the agent is only allowed to execute read-only operations.
* Add `--auto` to enable edits and commands; risk tiers gate what can run.

CLI help (excerpt):

```
Usage: droid exec [options] [prompt]

Execute a single command (non-interactive mode)

Arguments:
  prompt                          The prompt to execute

Options:
  -o, --output-format <format>    Output format (default: "text")
  -f, --file <path>               Read prompt from file
  --auto <level>                  Autonomy level: low|medium|high
  --skip-permissions-unsafe       Skip ALL permission checks (unsafe)
  -s, --session-id <id>           Existing session to continue (requires a prompt)
  -m, --model <id>                Model ID to use
  -r, --reasoning-effort <level>  Reasoning effort: off|low|medium|high
  --cwd <path>                    Working directory path
  -h, --help                      display help for command
```

Supported models (examples):

* gpt-5-codex (default)
* gpt-5-2025-08-07
* claude-sonnet-4-20250514
* claude-opus-4-1-20250805

## Installation

<Steps>
  <Step title="Install Droid CLI">
    <CodeGroup>
      ```bash macOS/Linux theme={null}
      curl -fsSL https://app.factory.ai/cli | sh
      ```

      ```powershell Windows theme={null}
      irm https://app.factory.ai/cli/windows | iex
      ```
    </CodeGroup>
  </Step>

  <Step title="Get Factory API Key">
    Generate your API key from the [Factory Settings Page](https://app.factory.ai/settings/api-keys)
  </Step>

  <Step title="Set Environment Variable">
    Export your API key as an environment variable:

    ```bash  theme={null}
    export FACTORY_API_KEY=fk-...
    ```
  </Step>
</Steps>

## Quickstart

* Direct prompt:
  * `droid exec "analyze code quality"`
  * `droid exec "fix the bug in src/main.js" --auto low`
* From file:
  * `droid exec -f prompt.md`
* Pipe:
  * `echo "summarize repo structure" | droid exec`
* Session continuation:
  * `droid exec --session-id <session-id> "continue with next steps"`

## Autonomy Levels

Droid exec uses a tiered autonomy system to control what operations the agent can perform. By default, it runs in read-only mode, requiring explicit flags to enable modifications.

### DEFAULT (no flags) - Read-only Mode

The safest mode for reviewing planned changes without execution:

* ✅ Reading files or logs: cat, less, head, tail, systemctl status
* ✅ Display commands: echo, pwd
* ✅ Information gathering: whoami, date, uname, ps, top
* ✅ Git read operations: git status, git log, git diff
* ✅ Directory listing: ls, find (without -delete or -exec)
* ❌ No modifications to files or system
* **Use case:** Safe for reviewing what changes would be made

```bash  theme={null}
# Analyze and plan refactoring without making changes
droid exec "Analyze the authentication system and create a detailed plan for migrating from session-based auth to OAuth2. List all files that would need changes and describe the modifications required."

# Review code quality and generate report
droid exec "Review the codebase for security vulnerabilities, performance issues, and code smells. Generate a prioritized list of improvements needed."

# Understand project structure
droid exec "Analyze the project architecture and create a dependency graph showing how modules interact with each other."
```

### `--auto low` - Low-risk Operations

Enables basic file operations while blocking system changes:

* ✅ File creation/editing in project directories
* ❌ No system modifications or package installations
* **Use case:** Documentation updates, code formatting, adding comments

```bash  theme={null}
# Safe file operations
droid exec --auto low "add JSDoc comments to all functions"
droid exec --auto low "fix typos in README.md"
```

### `--auto medium` - Development Operations

Operations that may have significant side effects, but these side effects are typically harmless and straightforward to recover from.
Adds common development tasks to low-risk operations:

* Installing packages from trusted sources: npm install, pip install (without sudo)
* Network requests to trusted endpoints: curl, wget to known APIs
* Git operations that modify local repositories: git commit, git checkout, git pull (but not git push)
* Building code with tools like make, npm run build, mvn compile
* ❌ No git push, sudo commands, or production changes
* **Use case:** Local development, testing, dependency management

```bash  theme={null}
# Development tasks
droid exec --auto medium "install deps, run tests, fix issues"
droid exec --auto medium "update packages and resolve conflicts"
```

### `--auto high` - Production Operations

Commands that may have security implications such as data transfers between untrusted sources or execution of unknown code, or major side effects such as irreversible data loss or modifications of production systems/deployments.

* Running arbitrary/untrusted code: curl | bash, eval, executing downloaded scripts
* Exposing ports or modifying firewall rules that could allow external access
* Git push operations that modify remote repositories: git push, git push --force
* Irreversible actions to production deployments, database migrations, or other sensitive operations
* Commands that access or modify sensitive information like passwords or keys
* ❌ Still blocks: sudo rm -rf /, system-wide changes
* **Use case:** CI/CD pipelines, automated deployments

```bash  theme={null}
# Full workflow automation
droid exec --auto high "fix bug, test, commit, and push to main"
droid exec --auto high "deploy to staging after running tests"
```

### `--skip-permissions-unsafe` - Bypass All Checks

<Warning>
  DANGEROUS: This mode allows ALL operations without confirmation. Only use in completely isolated environments like Docker containers or throwaway VMs.
</Warning>

* ⚠️ Allows ALL operations without confirmation
* ⚠️ Can execute irreversible operations
* Cannot be combined with --auto flags
* **Use case:** Isolated environments

```bash  theme={null}
# In a disposable Docker container for CI testing
docker run --rm -v $(pwd):/workspace alpine:latest sh -c "
  apk add curl bash &&
  curl -fsSL https://app.factory.ai/cli | sh &&
  droid exec --skip-permissions-unsafe 'Install all system dependencies, modify system configs, run integration tests that require root access, and clean up test databases'
"

# In ephemeral GitHub Actions runner for rapid iteration
# where the runner is destroyed after each job
droid exec --skip-permissions-unsafe "Modify /etc/hosts for test domains, install custom kernel modules, run privileged container tests, and reset network interfaces"

# In a temporary VM for security testing
droid exec --skip-permissions-unsafe "Run penetration testing tools, modify firewall rules, test privilege escalation scenarios, and generate security audit reports"
```

### Fail-fast Behavior

If a requested action exceeds the current autonomy level, droid exec will:

1. Stop immediately with a clear error message
2. Return a non-zero exit code
3. Not perform any partial changes

This ensures predictable behavior in automation scripts and CI/CD pipelines.

## Output formats and artifacts

Droid exec supports three output formats for different use cases:

### text (default)

Human-readable output for direct consumption or logs:

```bash  theme={null}
$ droid exec --auto low "create a python file that prints 'hello world'"
Perfect! I've created a Python file named `hello_world.py` in your home directory that prints 'hello world' when executed.
```

### json

Structured JSON output for parsing in scripts and automation:

```bash  theme={null}
$ droid exec "summarize this repository" --output-format json
{
  "type": "result",
  "subtype": "success",
  "is_error": false,
  "duration_ms": 5657,
  "num_turns": 1,
  "result": "This is a Factory documentation repository containing guides for CLI tools, web platform features, and onboarding procedures...",
  "session_id": "8af22e0a-d222-42c6-8c7e-7a059e391b0b"
}
```

Use JSON format when you need to:

* Parse the result in a script
* Check success/failure programmatically
* Extract session IDs for continuation
* Process results in a pipeline

### debug

Streaming messages showing the agent's execution in real-time:

```bash  theme={null}
$ droid exec "run ls command" --output-format debug
{"type":"message","role":"user","text":"run ls command"}
{"type":"message","role":"assistant","text":"I'll run the ls command to list the contents..."}
{"type":"tool_call","toolName":"Execute","parameters":{"command":"ls -la"}}
{"type":"tool_result","value":"total 16\ndrwxr-xr-x@ 8 user staff..."}
{"type":"message","role":"assistant","text":"The ls command has been executed successfully..."}
```

Debug format is useful for:

* Monitoring agent behavior
* Troubleshooting execution issues
* Understanding tool usage patterns
* Real-time progress tracking

For automated pipelines, you can also direct the agent to write specific artifacts:

```bash  theme={null}
droid exec --auto low "Analyze dependencies and write to deps.json"
droid exec --auto low "Generate metrics report in CSV format to metrics.csv"
```

## Working directory

* Use `--cwd` to scope execution:

```
droid exec --cwd /home/runner/work/repo "Map internal packages and dump graphviz DOT to deps.dot"
```

## Models and reasoning effort

* Choose a model with `-m` and adjust reasoning with `-r`:

```
droid exec -m claude-sonnet-4-20250514 -r medium -f plan.md
```

## Batch and parallel patterns

Shell loops (bounded concurrency):

```bash  theme={null}
# Process files in parallel (GNU xargs -P)
find src -name "*.ts" -print0 | xargs -0 -P 4 -I {} \
  droid exec --auto low "Refactor file: {} to use modern TS patterns"
```

Background job parallelization:

```bash  theme={null}
# Process multiple directories in parallel with job control
for path in packages/ui packages/models apps/factory-app; do
  (
    cd "$path" &&
    droid exec --auto low "Run targeted analysis and write report.md"
  ) &
done
wait  # Wait for all background jobs to complete
```

Chunked inputs:

```bash  theme={null}
# Split large file lists into manageable chunks
git diff --name-only origin/main...HEAD | split -l 50 - /tmp/files_
for f in /tmp/files_*; do
  list=$(tr '\n' ' ' < "$f")
  droid exec --auto low "Review changed files: $list and write to review.json"
done
rm /tmp/files_*  # Clean up temporary files
```

Workflow Automation (CI/CD):

```yaml  theme={null}
# Dead code detection and cleanup suggestions
name: Code Cleanup Analysis
on:
  schedule:
    - cron: '0 1 * * 0' # Weekly on Sundays
  workflow_dispatch:
jobs:
  cleanup-analysis:
    strategy:
      matrix:
        module: ['src/components', 'src/services', 'src/utils', 'src/hooks']
    steps:
      - uses: actions/checkout@v4
      - run: droid exec --cwd "${{ matrix.module }}" --auto low "Identify unused exports, dead code, and deprecated patterns. Generate cleanup recommendations in cleanup-report.md"
```

## Unique usage examples

License header enforcer:

```bash  theme={null}
git ls-files "*.ts" | xargs -I {} \
  droid exec --auto low "Ensure {} begins with the Apache-2.0 header; add it if missing"
```

API contract drift check (read-only):

```bash  theme={null}
droid exec "Compare openapi.yaml operations to our TypeScript client methods and write drift.md with any mismatches"
```

Security sweep:

```bash  theme={null}
droid exec --auto low "Run a quick audit for sync child_process usage and propose fixes; write findings to sec-audit.csv"
```

## Exit behavior

* 0: success
* Non-zero: failure (permission violation, tool error, unmet objective). Treat non-zero as failed in CI.

## Best practices

* Favor `--auto low`; keep mutations minimal and commit/push in scripted steps.
* Avoid `--skip-permissions-unsafe` unless fully sandboxed.
* Ask the agent to emit artifacts your pipeline can verify.
* Use `--cwd` to constrain scope in monorepos.

</droid-docs>

Use the oracle to research how we support custom executors.
AMP and Claude Code would likely be good references here as I believe that they both operate via JSON.

Save your findings in a single markdown file.
Read tasks/droid-agent/plan.md and execute the plan.
we have introduced a new coding agent

Installation instructions are at https://factory.ai/product/cli

We expect that users have the `droid` cli installed and that they have logged in.

docs/supported-coding-agents.mdx
There may also be other docs or references.
Run cargo fmt --all -- --check
  cargo fmt --all -- --check
  npm run generate-types:check
  cargo test --workspace
  cargo clippy --all --all-targets -- -D warnings

the checks step is failing, can you see what's up with the rust codebase and resolve it?
We have a new coding agent called Droid and it has a variety of different settings including the autonomy level and we default this to medium and users can update this by going to settings and then using the drop down to change it and then hitting the save button. And this works, however, when users return back to settings the displayed autonomy level is reset to medium rather than the correct level. So can you investigate why this is happening and plan how we can improve it, how we can verify it, do we need to introduce some logging, other things to consider. Write up your plan in a new markdown file.
droid.rs has `fn map_tool_to_action`

The problem is that we're doing a poor job at displaying these tool calls e.g. glob. In `claude.rs`, we use `ClaudeToolData`, a struct that matches the real JSON data. Once we do that, we have a type safe way to map tool calls to the `ActionType` struct.

You can run `droid exec --output-format=stream-json --auto medium "YOUR MESSAGE MERE"` in a temporary directory to instruct the agent to generate custom outputs in case you need more sample data.

I just added glob.jsonl under droid-json, there are other json files in there too.

I recommend using sub agents as some of these files (e.g. claude.rs) are large.

cursor.rs might also be a useful reference.

You're done once we properly handle these tools.
The first JSON object emitted from the droid executor is a system message with a `model` field. We should capture and display this.

I believe that we're already doing something similar with Codex.

Here's a sample system message:
{"type":"system","subtype":"init","cwd":"/Users/britannio/projects/vibe-kanban","session_id":"59a75629-c0c4-451f-a3c7-8e9eab05484a","tools":["Read","LS","Execute","Edit","MultiEdit","ApplyPatch","Grep","Glob","Create","ExitSpecMode","WebSearch","TodoWrite","FetchUrl","slack_post_message"],"model":"gpt-5-codex"}
The crates/executors/src/executors/droid.rs ApplyPatch tool call contains an `input` string which isn't very helpful, but the tool call result is a JSON object with a `value` object with the fields success, content, diff, and file_path.

Here's a parsed example of `value`:
{
  "success": true,
  "content": "def bubble_sort(arr):\n    \"\"\"\n    Bubble Sort Algorithm\n    Time Complexity: O(n^2)\n    Space Complexity: O(1)\n\n    Repeatedly steps through the list, compares adjacent elements and swaps them\n    if they are in the wrong order.\n    \"\"\"\n    n = len(arr)\n    arr = arr.copy()  # Create a copy to avoid modifying the original\n\n    for i in range(n):\n        # Flag to optimize by stopping if no swaps occur\n        swapped = False\n\n        for j in range(0, n - i - 1):\n            if arr[j] > arr[j + 1]:\n                arr[j], arr[j + 1] = arr[j + 1], arr[j]\n                swapped = True\n\n        # If no swaps occurred, array is already sorted\n        if not swapped:\n            break\n\n    return arr\n\n\ndef insertion_sort(arr):\n    \"\"\"\n    Insertion Sort Algorithm\n    Time Complexity: O(n^2)\n    Space Complexity: O(1)\n\n    Builds the sorted portion of the array one element at a time by inserting\n    each element into its correct position.\n    \"\"\"\n    arr = arr.copy()  # Create a copy to avoid modifying the original\n\n    for i in range(1, len(arr)):\n        key = arr[i]\n        j = i - 1\n\n        while j >= 0 and arr[j] > key:\n            arr[j + 1] = arr[j]\n            j -= 1\n\n        arr[j + 1] = key\n\n    return arr\n\n\nif __name__ == \"__main__\":\n    # Example usage\n    test_array = [64, 34, 25, 12, 22, 11, 90]\n\n    print(\"Original array:\", test_array)\n    print(\"\\nBubble Sort result:\", bubble_sort(test_array))\n    print(\"Insertion Sort result:\", insertion_sort(test_array))\n\n    # Test with different arrays\n    print(\"\\n--- Additional Tests ---\")\n    test_cases = {\n        \"Reverse sorted\": [5, 4, 3, 2, 1],\n        \"Empty array\": [],\n        \"Already sorted\": [1, 2, 3, 4, 5],\n    }\n\n    for description, case in test_cases.items():\n        print(f\"{description} (Bubble):\", bubble_sort(case))\n        print(f\"{description} (Insertion):\", insertion_sort(case))\n",
  "diff": "--- previous\t\n+++ current\t\n@@ -26,14 +26,46 @@\n     return arr\n \n \n+def insertion_sort(arr):\n+    \"\"\"\n+    Insertion Sort Algorithm\n+    Time Complexity: O(n^2)\n+    Space Complexity: O(1)\n+\n+    Builds the sorted portion of the array one element at a time by inserting\n+    each element into its correct position.\n+    \"\"\"\n+    arr = arr.copy()  # Create a copy to avoid modifying the original\n+\n+    for i in range(1, len(arr)):\n+        key = arr[i]\n+        j = i - 1\n+\n+        while j >= 0 and arr[j] > key:\n+            arr[j + 1] = arr[j]\n+            j -= 1\n+\n+        arr[j + 1] = key\n+\n+    return arr\n+\n+\n if __name__ == \"__main__\":\n     # Example usage\n     test_array = [64, 34, 25, 12, 22, 11, 90]\n \n     print(\"Original array:\", test_array)\n     print(\"\\nBubble Sort result:\", bubble_sort(test_array))\n+    print(\"Insertion Sort result:\", insertion_sort(test_array))\n \n     # Test with different arrays\n     print(\"\\n--- Additional Tests ---\")\n-    print(\"Reverse sorted:\", bubble_sort([5, 4, 3, 2, 1]))\n-    print(\"Empty array:\", bubble_sort([]))\n+    test_cases = {\n+        \"Reverse sorted\": [5, 4, 3, 2, 1],\n+        \"Empty array\": [],\n+        \"Already sorted\": [1, 2, 3, 4, 5],\n+    }\n+\n+    for description, case in test_cases.items():\n+        print(f\"{description} (Bubble):\", bubble_sort(case))\n+        print(f\"{description} (Insertion):\", insertion_sort(case))",
  "file_path": "/Users/britannio/projects/droid-simple/sorting_algorithms.py"
}

This formatting should be deterministic and thus we can use it to show more informative tool call data.

The first thing to understand is if this will naturally fit with the current architecture, as we only reliably know how the file has changed (and what the target file was) after receiving the tool call result.
crates/executors/src/executors/droid.rs
droid-json/insufficient-perms.jsonl

the insufficient-perms file contains the JSON output log of a run where it runs a command to create a file but the tool call fails due to a permission error.

I'd expect that the failed tool result would be correlated with the tool call and thus i'd see an ARGS block and a RESULTS block within the tool call on the front-end.

Instead, I see the tool call only with the ARGS block, then I see a separate UI element with the JSON tool result as if it failed to be correlated.

Firstly, I want to follow TDD by creating a failing test that confirms this behaviour. It might be hard though because we haven't designed the code in droid.rs with testability in mind.

Lets first analyse the code to consider if it's already testable or if we need to do any refactoring & introduce harnesses etc.

My perspective of the coding agent is that we send it a command, and it streams JSON objects one by one so some form of reducer pattern seems natural (previous list of json objects + previous state + new json object => new state). Either 'new state' or 'new delta'.

When we resume a session, it will emit a system message object, then a message object with role user (repeating what we sent it), then the new actions that it takes.
the default autonomy level is currently medium. Lets change it to the highest (unsafe)
See droid-json/glob.jsonl
Notice the `patterns` field. Unfortunately, we seems to not be using this data as glob tool calls are being rendered exclusively via a file name of some sort rather than `Globbing README.md, readme.md,docs/**,*.md`

Use the oracle to investigate this.
Use the text 'TODO list updated' for the droid agent when it makes a change to the todo list.
See how claude.rs uses worktree_path (from normalize_logs).
We should be doing the same for the droid executor so that the tool calls we generate have relative paths.
Quick fix: Filter that agent from the dropdown in the frontend.

// In McpSettings.tsx, line 282-289
<SelectContent>
  {profiles &&
    Object.entries(profiles)
      .filter(([key]) => key !== 'DROID') // or whatever the agent name is
      .sort((a, b) => a[0].localeCompare(b[0]))
      .map(([profileKey]) => (
        <SelectItem key={profileKey} value={profileKey}>
          {profileKey}
        </SelectItem>
      ))}
</SelectContent>

we need to temporarily hide droid as it doesn't support mcp yet.
remove all references to 'britannio' from the droid module.
We added Droid to crates/services/src/services/config/versions/v1.rs but presumably we should've used the latest reasonable version. See what we used for Copilot.

Delete docs/adr-droid-architecture.md
Delete docs/droid-improvements-summary.md

docs/supported-coding-agents.mdx the default was medium, it's now skip-permissions-unsafe

Delete the tasks/ folder
crates/executors/src/executors/droid/types.rs

Valid model IDs are:
  gpt-5-codex                  OpenAI GPT-5-Codex (Auto)
  claude-sonnet-4-5-20250929   Claude Sonnet 4.5
  gpt-5-2025-08-07             OpenAI GPT-5
  claude-opus-4-1-20250805     Claude Opus 4.1
  claude-haiku-4-5-20251001    Claude Haiku 4.5
  glm-4.6                      Droid Core (GLM-4.6)

We currently mention gpt-5-codex, claude-sonnet-4
lets start brainstorming this, starting with tests in crates/executors/src/executors/droid/types.rs to ensure that we correctly generate a command
Add tracing logging (warn/error) to error paths in `crates/executors/src/executors/droid/action_mapper.rs` following existing logging patterns in the codebase.

Key locations:
- Line 32-35: DroidToolData parsing failure (currently silent)
- Any other error paths that swallow errors

Use `tracing::warn!` with structured fields for context (tool_name, error details, etc.)
…f325d24)

We have example agent from /Users/britannio/Downloads/droid-json

Read crates/executors/src/executors/droid/events.rs

Use the oracle to plan tests that we could introduce.
in settings, we're showing a dropdown for the droid autonomy level. We should be doing the same for the reasoning level. It should default to being empty if possible.
Droid file edits (presumably ApplyPatch?) aren't using relative paths. E.g. i'm seeing `/private/var/folders/5q/5vgq75y92dz0k7n62z93299r0000gn/T/vibe-kanban-dev/worktrees/11dc-setup/next.config.mjs`
@britannio britannio marked this pull request as ready for review October 21, 2025 12:46
@britannio britannio requested review from LSRCT and Copilot October 22, 2025 17:41
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for Factory AI's Droid coding agent to Vibe Kanban, enabling users to configure and run Droid as an executor option alongside existing agents like Claude Code, Amp, and Codex.

Key changes:

  • Added Droid agent type with configuration support for autonomy levels, models, and reasoning effort
  • Implemented JSON streaming parser to process Droid's output format
  • Added comprehensive test coverage with snapshot tests for various execution scenarios

Reviewed Changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
shared/types.ts Added DROID enum variant and Droid configuration types
shared/schemas/droid.json JSON schema defining Droid's configuration options
frontend/src/pages/settings/AgentSettings.tsx Fixed state management bug causing autonomy dropdown resets
frontend/src/pages/settings/McpSettings.tsx Filtered DROID from MCP server profile selection
frontend/src/components/rjsf/widgets/SelectWidget.tsx Improved nullable field handling in dropdowns
docs/*.mdx Added documentation for Droid installation, configuration, and usage
crates/executors/src/executors/droid/* Core Droid executor implementation with event processing
crates/executors/tests/droid_snapshots.rs Snapshot tests validating Droid's output parsing

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Contributor

@abcpro1 abcpro1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the existing code pattern of executors by

  • merging the 4 modules related to log normalization into one.
  • removing tests.
  • centralizing basic processing into the main line processing loop with match.

}

pub fn process_event(
state: ProcessorState,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
state: ProcessorState,
state: &mut ProcessorState,


let changes = if let Some(diff_text) = diff {
vec![FileChange::Edit {
unified_diff: diff_text,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalize the diff using diff::extract_unified_diff_hunks

<SelectContent>
{profiles &&
Object.entries(profiles)
.filter(([key]) => key !== 'DROID')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain this filter.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Droid's MCP support isn't working until they push an update.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, you can use the existing backend method for this

    pub fn supports_mcp(&self) -> bool {
        self.default_mcp_config_path().is_some()
    }

just return None here until they fix it

    fn default_mcp_config_path(&self) -> Option<std::path::PathBuf> {
        dirs::home_dir().map(|home| home.join(".factory").join("mcp.json"))
    }

Comment on lines 135 to 136
let stream = msg_store.history_plus_stream();
let lines = lines_from_stream(stream);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let stream = msg_store.history_plus_stream();
let lines = lines_from_stream(stream);
let stream = msg_store.stdout_lines_stream();

@britannio
Copy link
Collaborator Author

The current version of the droid CLI is no longer providing tool call result ids to correlate with the tool call request: Factory-AI/factory#258

The CLI has an auto updater as well so there's no easy way to pin to a specific version.

britannio and others added 11 commits October 24, 2025 23:02
DroidJson mapping tests removed in favour of snapshot testing delete
emit_patches (now redundant) update match syntax in
compute_updated_action_type make process_event a member of
ProcessorState
rename patch_emitter -> patch_converter
remove ParsedLine indirection from processor.rs
handle Edit, MultiEdit, and Create tool calls (only used by some models like claude)
move action mapper logic to log_event_converter
introduce a claude snapshot
update snapshots
- Change &String to &str in extract_path_from_patch
- Rename to_patch to process_event for correct self convention

Amp-Thread-ID: https://ampcode.com/threads/T-81d4f5ac-6d3a-4da5-9799-de724f3df1e3
Co-authored-by: Amp <[email protected]>
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.

[Must Add] Support Droid agent Support droid any plans to integrate droid as executor anytime soon?

2 participants