Skip to content

Private Repo Refactor & Test — Fully Local An agentic coding workflow powered by GitHub Copilot SDK + Foundry Local. Scans code, detects bugs, applies safe refactors, runs tests, and produces a PR-style summary — all on-device, no cloud model required.

License

Notifications You must be signed in to change notification settings

leestott/copilotsdk_foundrylocal

Repository files navigation

GitHub Copilot SDK Foundry Local Node.js 18+ MIT License 100% Local

🛠️ Local Repo Patch Agent

Private Repo Refactor & Test — Fully Local
An agentic coding workflow powered by GitHub Copilot SDK + Foundry Local.
Scans code, detects bugs, applies safe refactors, runs tests, and produces a PR-style summary —
all on-device, no cloud model required.

Getting StartedWeb DashboardWhat Does It Do?ArchitectureTroubleshootingContributing


What Is This?

This is a working demo of an AI-powered coding agent that can:

  • Read your repository files
  • Find bugs and code smells
  • Fix them automatically
  • Run your tests to verify the fixes
  • Write a PR-style summary of what it changed

The twist? Everything runs on your machine. No code is sent to the cloud. No API keys to OpenAI or Anthropic. Just your laptop, a local AI model, and two open-source SDKs wired together.

Who is this for?

  • Developers exploring agentic coding workflows
  • Teams who need AI assistance but can't send code to external services
  • Anyone curious about GitHub Copilot SDK and Foundry Local

What technologies does it use?

Technology What it does
GitHub Copilot SDK Provides the agent runtime — handles planning, tool invocation, streaming, and the orchestration loop
Foundry Local Runs an AI model on your device — exposes an OpenAI-compatible API on a dynamic localhost port (auto-detected by the SDK)
BYOK (Bring Your Own Key) A single config object that routes all SDK inference to Foundry Local instead of the cloud
Node.js + TypeScript The application language — modern ESM, fully typed

Prerequisites

Before you start, make sure these three things are installed on your machine:

1. Node.js (version 18 or higher)

Download from nodejs.org. Pick the LTS version.

Verify it's installed:

node --version
# Should print v18.x.x or higher

2. Foundry Local (on-device AI runtime)

Foundry Local is Microsoft's tool for running AI models locally.

Windows:

winget install Microsoft.FoundryLocal

macOS:

brew install foundrylocal

Verify it's installed:

foundry --version

📖 Full install guide: Foundry Local — Get Started

3. GitHub Copilot CLI

The GitHub Copilot SDK communicates with the GitHub Copilot CLI in server mode.

Install it by following the GitHub Copilot CLI install guide.

Verify it's installed:

copilot --version

Note: You need a GitHub Copilot subscription (Individual, Business, or Enterprise) or you can use BYOK mode.


Getting Started

Option A: One-command setup (recommended)

We provide setup scripts that install dependencies, start Foundry Local, and download the AI model for you.

Windows (PowerShell):

.\setup.ps1

macOS / Linux:

chmod +x setup.sh
./setup.sh

When setup finishes, you'll see:

━━━ Setup complete! ━━━

  You're ready to go. Run one of these commands:

    npm run demo     CLI agent (terminal output)
    npm run ui       Web dashboard (http://localhost:3000)

Option B: Manual setup (step by step)

If you prefer to set things up yourself:

Step 1 — Install npm packages:

npm install
cd demo-repo && npm install --ignore-scripts && cd ..

Step 2 — Start Foundry Local and download the model:

foundry service start
foundry model run qwen2.5-coder-1.5b

The first model download takes a few minutes. After that it runs from cache — no internet needed.

Step 3 — Copy the environment file:

cp .env.example .env

Step 4 — Run the agent:

npm run demo

Quick-launch scripts

For convenience, you can also use the launcher scripts:

Command What it does
start.cmd (Windows) / ./start.sh (macOS/Linux) Run the CLI demo
start.cmd ui / ./start.sh ui Start the web dashboard
start.cmd setup / ./start.sh setup Run the full setup

Web Dashboard

A real-time web UI is included for a more visual experience.

npm run ui
# Open http://localhost:3000 in your browser

The dashboard shows:

  • Phase progress sidebar — which phase is running, completed, or errored
  • Live streaming output — model responses appear in real-time via WebSocket
  • Tool call log — every tool invocation logged with phase context
  • Phase timing table — how long each phase took
  • Environment info — model, endpoint, and repo path at a glance

Web Dashboard — idle

Web Dashboard — running

Web Dashboard — complete

Browser (http://localhost:3000)
    │
    │  WebSocket (real-time events)
    ▼
Express server (src/server.ts)
    │
    │  runAgent() callback
    ▼
web-agent.ts  →  GitHub Copilot SDK  →  Foundry Local (on-device)

What Does It Do?

The agent runs a four-phase loop on a small demo repository (demo-repo/) that contains an intentional bug and duplicated code.

The four phases

Phase What the agent does Tools used
1. PLAN Scans every source and test file. Identifies bugs, code smells, and duplication. Outputs a numbered fix plan. list_files, read_file
2. EDIT Applies each fix by rewriting the affected files. Corrects the bug, removes duplication. write_file
3. VERIFY Runs npm test and npm run lint. If tests fail, tries to fix and re-run. run_command
4. SUMMARY Produces a PR-style Markdown report: what changed, why, and what to do next. (none — text generation)

The intentional bugs it finds

The demo-repo/ is a tiny banking utility library. It has two problems:

  1. Calculation bugcalculateInterest() in account.js divides instead of multiplies:

    // BUG: should be principal * (annualRate / 100)
    return principal / annualRate;

    This causes 3 of 9 tests to fail.

  2. Code duplicationformatCurrency() is copy-pasted in account.js and transaction.js, even though a canonical version already exists in utils.js.

The agent finds both problems, fixes them, verifies all tests pass, and writes a summary.


Architecture

┌─────────────────────────────────────────────────────────┐
│                    Your Terminal / Web UI                │
│                    npm run demo / npm run ui             │
└──────────────┬──────────────────────────────────────────┘
               │
┌──────────────▼──────────────────────────────────────────┐
│          src/agent.ts  (this project)                    │
│                                                          │
│  ┌────────────────────────────┐   ┌──────────────────────────┐  │
│  │  GitHub Copilot SDK         │   │  Agent Tools              │  │
│  │  (CopilotClient)            │   │  list_files, read_file,   │  │
│  │  BYOK → Foundry             │   │  write_file, run_command  │  │
│  └────────┬───────────────────┘   └──────────────────────────┘  │
│            │                                             │
└────────────┼─────────────────────────────────────────────┘
             │ JSON-RPC
┌────────────▼─────────────────────────────────────────────┐
│          GitHub Copilot CLI  (server mode)                │
│          Agent orchestration layer                        │
└────────────┬─────────────────────────────────────────────┘
             │ POST /v1/chat/completions   (BYOK)
┌────────────▼─────────────────────────────────────────────┐
│          Foundry Local  (on-device inference)             │
│          Model: qwen2.5-coder-1.5b via ONNX Runtime      │
│          Endpoint: auto-detected (dynamic port)           │
└───────────────────────────────────────────────────────────┘

The streaming proxy

Foundry Local (as of v0.5) can hang on stream: true requests. The project includes a lightweight HTTP proxy (streaming-proxy.ts) that transparently converts streaming requests to non-streaming, then re-encodes the single response as SSE chunks — the format the OpenAI SDK expects. Non-streaming and non-chat-completions requests pass through unchanged.

Text-based tool call detection

Small on-device models (e.g. qwen2.5-coder-1.5b) often output tool calls as JSON text rather than using OpenAI-style function calling. The SDK won't fire tool.execution_start events for these, so both agent.ts and web-agent.ts include a regex-based detector that scans streamed text for tool-name patterns and emits tool_start events. This keeps the dashboard tool call counter and the CLI log accurate regardless of whether the model uses native function calling or text output.

The key integration — BYOK

The entire connection between the GitHub Copilot SDK and Foundry Local is one config object:

const session = await client.createSession({
  model: modelId,
  provider: {
    type: "openai",               // Foundry Local speaks OpenAI's API format
    baseUrl: proxyBaseUrl,        // streaming proxy → Foundry Local
    apiKey: manager.apiKey,
    wireApi: "completions",       // Chat Completions API
  },
  streaming: true,
  tools: [ /* your tools */ ],
});

This tells the GitHub Copilot SDK: "Don't call the cloud — send everything to my local model (via the streaming proxy)."


Configuration

All settings are via environment variables. Edit .env (or use the defaults):

Variable Default What it does
FOUNDRY_LOCAL_ENDPOINT auto-detected Override the Foundry Local API endpoint
FOUNDRY_LOCAL_API_KEY auto-detected Override the API key
FOUNDRY_MODEL qwen2.5-coder-1.5b Which model to use from the Foundry Local catalog
FOUNDRY_TIMEOUT_MS 180000 (3 min) How long each agent phase can run before timing out
FOUNDRY_NO_PROXY Set to 1 to disable the streaming proxy
PORT 3000 Port for the web dashboard

Using a different model

# Use a different model
FOUNDRY_MODEL=phi-3-mini npm run demo

Slower hardware?

Increase the timeout so the model has more time per phase:

# 5 minutes per phase
FOUNDRY_TIMEOUT_MS=300000 npm run demo

Project Structure

local-repo-patch-agent/
│
├── setup.ps1 / setup.sh      # One-command setup scripts
├── start.cmd / start.sh      # Quick-launch scripts
├── package.json               # npm scripts: demo, ui, setup, preflight
├── tsconfig.json              # TypeScript config
├── .env.example               # Environment variable template
├── LICENSE                    # MIT License
├── SECURITY.md                # Security policy
├── CONTRIBUTING.md            # How to contribute
├── blog_post.md               # Developer blog post / walkthrough
├── README.md                  # ← You are here
│
├── src/                       # Application source
│   ├── agent.ts               # CLI agent: 4-phase loop + GitHub Copilot SDK + BYOK
│   ├── web-agent.ts           # Web UI agent: same workflow, emits events via callback
│   ├── server.ts              # Express + WebSocket server for the dashboard
│   ├── streaming-proxy.ts     # Converts streaming requests to non-streaming + re-encodes as SSE
│   ├── tools.ts               # Agent tools: list_files, read_file, write_file, run_command
│   ├── helpers.ts             # sendMessage helper (handles Foundry Local streaming quirks)
│   └── tests/                 # Diagnostic scripts for debugging SDK / Foundry integration
│       └── README.md          # Describes each test script and how to run them
│
├── public/                    # Web dashboard static assets
│   ├── index.html             # Dashboard HTML
│   ├── styles.css             # GitHub-dark themed responsive styles
│   └── app.js                 # Client-side WebSocket + event rendering
│
├── docs/images/               # Dashboard screenshots (idle, running, complete)
│
└── demo-repo/                 # Toy repo the agent operates on
    ├── package.json           # Test/lint/build scripts
    ├── src/
    │   ├── account.js         # BUG: calculateInterest uses / instead of *
    │   ├── transaction.js     # CODE SMELL: duplicated formatCurrency
    │   └── utils.js           # Canonical formatCurrency (currently unused)
    └── test/
        ├── account.test.js    # 6 tests — 3 FAIL until the bug is fixed
        └── transaction.test.js # 3 tests — all pass

Security

This project was built with security in mind:

  • 100% local — No code, prompts, or responses leave your machine
  • Command allowlist — The agent can only run npm test, npm run lint, and npm run build
  • Path sandboxing — File tools are locked to demo-repo/ — path traversal is blocked
  • File size limitsread_file rejects files over 256 KB
  • Recursion limitslist_files caps directory depth at 20 levels

See SECURITY.md for the full security policy.


How to Talk About This (2-minute pitch)

  1. "GitHub Copilot SDK gives us an agent runtime" — Planning, tool invocation, file edits, and streaming out of the box. We define four simple tools and the SDK orchestrates everything.

  2. "Foundry Local runs the model on-device" — An OpenAI-compatible API on localhost (dynamic port, auto-detected). Privacy, compliance, offline — all handled.

  3. "BYOK wires them together" — One config object in createSession() routes inference to Foundry Local. That's the entire integration.

  4. "The result" — An agent that reads a repo, finds a real bug, fixes it, refactors duplicated code, runs tests, and produces a PR-ready summary — without a single byte leaving the machine.


Diagnostic Test Scripts

The src/tests/ folder contains standalone scripts for debugging SDK and Foundry Local integration issues. See src/tests/README.md for a full reference table.

Quick examples:

# Debug-level SDK event logging
npx tsx src/tests/test-debug.ts

# Test non-streaming inference
npx tsx src/tests/test-nostream.ts

# Raw fetch to Foundry Local (bypasses SDK)
npx tsx src/tests/test-stream-direct.ts

# Start the traffic-inspection proxy
npx tsx src/tests/test-proxy.ts

Troubleshooting

Problem Solution
foundry: command not found Install Foundry Local — see Prerequisites
copilot: command not found Install GitHub Copilot CLI — see Prerequisites
Agent times out on every phase Increase FOUNDRY_TIMEOUT_MS (e.g., 300000 for 5 min). CPU-only machines are slower.
Port 3000 already in use Set PORT=3001 npm run ui
Model download is slow First download can take 5-10 min depending on connection. Subsequent runs use the cache.
Cannot find module errors Run npm install again, then cd demo-repo && npm install --ignore-scripts
Tests still fail after agent runs The agent edits files in demo-repo/. Reset with git checkout demo-repo/ and run again.
PowerShell blocks setup.ps1 Run Set-ExecutionPolicy -Scope Process Bypass first, then .\setup.ps1

References

Resource Link
Foundry Local site https://www.foundrylocal.ai/
Foundry Local repo https://github.com/microsoft/Foundry-Local
Foundry Local get-started https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-local/get-started
Foundry Local SDK reference https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-local/reference/reference-sdk
GitHub Copilot SDK + Foundry Local sample https://github.com/microsoft/Foundry-Local/tree/main/samples/js/copilot-sdk-foundry-local
GitHub Copilot SDK https://github.com/github/copilot-sdk
GitHub Copilot SDK BYOK docs https://github.com/github/copilot-sdk/blob/main/docs/auth/byok.md
GitHub Copilot SDK getting started https://github.com/github/copilot-sdk/blob/main/docs/getting-started.md

License

MIT — see LICENSE for details.

About

Private Repo Refactor & Test — Fully Local An agentic coding workflow powered by GitHub Copilot SDK + Foundry Local. Scans code, detects bugs, applies safe refactors, runs tests, and produces a PR-style summary — all on-device, no cloud model required.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published