Merge pull request #2 from htekdev/copilot/add-github-copilot-cli-integration
Add GitHub Copilot CLI as a built-in CLI backend
This commit is contained in:
commit
b55b7315a4
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ docker-compose.extra.yml
|
||||
dist
|
||||
*.bun-build
|
||||
pnpm-lock.yaml
|
||||
package-lock.json
|
||||
bun.lock
|
||||
bun.lockb
|
||||
coverage
|
||||
|
||||
@ -6,6 +6,7 @@ Docs: https://docs.molt.bot
|
||||
Status: beta.
|
||||
|
||||
### Changes
|
||||
- Agents: add GitHub Copilot CLI (`copilot-cli`) as a built-in CLI backend for text-only fallback.
|
||||
- Rebrand: rename the npm package/CLI to `moltbot`, add a `moltbot` compatibility shim, and move extensions to the `@moltbot/*` scope.
|
||||
- Commands: group /help and /commands output with Telegram paging. (#2504) Thanks @hougangdev.
|
||||
- macOS: limit project-local `node_modules/.bin` PATH preference to debug builds (reduce PATH hijacking risk).
|
||||
|
||||
@ -1008,6 +1008,8 @@
|
||||
"providers/models",
|
||||
"providers/openai",
|
||||
"providers/anthropic",
|
||||
"providers/github-copilot",
|
||||
"providers/github-copilot-cli",
|
||||
"bedrock",
|
||||
"providers/moonshot",
|
||||
"providers/minimax",
|
||||
|
||||
@ -32,6 +32,12 @@ Codex CLI also works out of the box:
|
||||
moltbot agent --message "hi" --model codex-cli/gpt-5.2-codex
|
||||
```
|
||||
|
||||
GitHub Copilot CLI works the same way (requires GitHub CLI auth):
|
||||
|
||||
```bash
|
||||
moltbot agent --message "hi" --model copilot-cli/gpt-4.1
|
||||
```
|
||||
|
||||
If your gateway runs under launchd/systemd and PATH is minimal, add just the
|
||||
command path:
|
||||
|
||||
@ -200,6 +206,18 @@ Moltbot also ships a default for `codex-cli`:
|
||||
- `imageArg: "--image"`
|
||||
- `sessionMode: "existing"`
|
||||
|
||||
Moltbot also ships a default for `copilot-cli`:
|
||||
|
||||
- `command: "copilot"`
|
||||
- `args: ["-p"]`
|
||||
- `resumeArgs: ["-p", "--resume", "{sessionId}"]`
|
||||
- `output: "text"`
|
||||
- `modelArg: "--model"`
|
||||
- `sessionMode: "existing"`
|
||||
|
||||
Note: Copilot CLI uses GitHub CLI (`gh`) for authentication and currently outputs
|
||||
text only (JSON output is not yet supported).
|
||||
|
||||
Override only if needed (common: absolute `command` path).
|
||||
|
||||
## Limitations
|
||||
|
||||
@ -1668,6 +1668,9 @@ Example:
|
||||
"claude-cli": {
|
||||
command: "/opt/homebrew/bin/claude"
|
||||
},
|
||||
"copilot-cli": {
|
||||
command: "/opt/homebrew/bin/copilot"
|
||||
},
|
||||
"my-cli": {
|
||||
command: "my-cli",
|
||||
args: ["--json"],
|
||||
|
||||
189
docs/providers/github-copilot-cli.md
Normal file
189
docs/providers/github-copilot-cli.md
Normal file
@ -0,0 +1,189 @@
|
||||
---
|
||||
summary: "Use GitHub Copilot CLI as a text-only fallback backend"
|
||||
read_when:
|
||||
- You want to use GitHub Copilot CLI as a model provider
|
||||
- You need a fallback when API providers fail
|
||||
- You already have GitHub Copilot CLI installed
|
||||
---
|
||||
# GitHub Copilot CLI
|
||||
|
||||
GitHub Copilot CLI (`copilot`) is GitHub's terminal-based AI assistant. Moltbot can use it as a
|
||||
**CLI backend** for text-only fallback when API providers are unavailable.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **GitHub account** (free tier works for `gpt-4.1`)
|
||||
- **GitHub CLI** (`gh`) authenticated with your GitHub account
|
||||
|
||||
Note: `gpt-4.1` is available on the free GitHub tier. Other models like `gpt-4o`, `claude-sonnet-4-5`,
|
||||
and `claude-opus-4-5` require a paid GitHub Copilot subscription.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the Copilot CLI via npm:
|
||||
|
||||
```bash
|
||||
npm install -g @github/copilot
|
||||
```
|
||||
|
||||
Or via Homebrew:
|
||||
|
||||
```bash
|
||||
brew install github/copilot/copilot
|
||||
```
|
||||
|
||||
Verify installation:
|
||||
|
||||
```bash
|
||||
copilot --help
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
Use Copilot CLI directly with Moltbot:
|
||||
|
||||
```bash
|
||||
moltbot agent --message "hi" --model copilot-cli/gpt-4.1
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Minimal config (custom command path)
|
||||
|
||||
If your gateway runs under launchd/systemd with a minimal PATH, specify the full path:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
cliBackends: {
|
||||
"copilot-cli": {
|
||||
command: "/opt/homebrew/bin/copilot"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using as a fallback
|
||||
|
||||
Add `copilot-cli` to your fallback list so it only runs when primary models fail:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: "github-copilot/gpt-4.1",
|
||||
fallbacks: [
|
||||
"copilot-cli/gpt-4.1"
|
||||
]
|
||||
},
|
||||
models: {
|
||||
"github-copilot/gpt-4.1": { alias: "Copilot" },
|
||||
"copilot-cli/gpt-4.1": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Supported models
|
||||
|
||||
Copilot CLI supports these models (availability depends on your GitHub plan):
|
||||
|
||||
**Free tier (GitHub Free):**
|
||||
- `gpt-4.1` ← recommended default
|
||||
- `gpt-4.1-mini`
|
||||
|
||||
**Paid tier (GitHub Copilot subscription):**
|
||||
- `gpt-4o`
|
||||
- `gpt-4-turbo`
|
||||
- `claude-sonnet-4-5`
|
||||
- `claude-opus-4-5`
|
||||
|
||||
Example model refs:
|
||||
|
||||
```
|
||||
copilot-cli/gpt-4.1
|
||||
copilot-cli/gpt-4.1-mini
|
||||
copilot-cli/gpt-4o
|
||||
copilot-cli/claude-sonnet-4-5
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
Copilot CLI uses GitHub CLI authentication. Ensure you're logged in:
|
||||
|
||||
```bash
|
||||
gh auth status
|
||||
```
|
||||
|
||||
If not logged in:
|
||||
|
||||
```bash
|
||||
gh auth login
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Text output only**: Copilot CLI does not support JSON output, so responses are plain text.
|
||||
- **Tools disabled**: CLI backends never receive tool calls. The CLI may still run its own agent tooling internally.
|
||||
- **No streaming**: CLI output is collected then returned.
|
||||
- **Session resume**: Uses `--resume` flag with session ID when available.
|
||||
|
||||
## Differences from the API provider
|
||||
|
||||
| Aspect | `github-copilot` (API) | `copilot-cli` (CLI backend) |
|
||||
|--------|------------------------|----------------------------|
|
||||
| Output format | JSON (structured) | Text only |
|
||||
| Tools | Moltbot tools work | Tools disabled |
|
||||
| Streaming | Supported | Not supported |
|
||||
| Auth | Device flow / token exchange | GitHub CLI (`gh auth`) |
|
||||
|
||||
Choose the API provider (`github-copilot`) for full functionality. Use `copilot-cli` as a
|
||||
fallback when you want "always works" text responses.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### CLI not found
|
||||
|
||||
Set the full command path in your config:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
cliBackends: {
|
||||
"copilot-cli": {
|
||||
command: "/usr/local/bin/copilot"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Authentication errors
|
||||
|
||||
Re-authenticate with GitHub CLI:
|
||||
|
||||
```bash
|
||||
gh auth login
|
||||
gh auth status
|
||||
```
|
||||
|
||||
### Model not available
|
||||
|
||||
Model availability depends on your GitHub Copilot plan. Try a different model:
|
||||
|
||||
```bash
|
||||
moltbot agent --message "hi" --model copilot-cli/gpt-4.1
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [GitHub Copilot (API provider)](/providers/github-copilot)
|
||||
- [CLI backends](/gateway/cli-backends)
|
||||
- [Configuration](/gateway/configuration)
|
||||
@ -50,21 +50,21 @@ moltbot models auth login-github-copilot --yes
|
||||
## Set a default model
|
||||
|
||||
```bash
|
||||
moltbot models set github-copilot/gpt-4o
|
||||
moltbot models set github-copilot/gpt-4.1
|
||||
```
|
||||
|
||||
### Config snippet
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: { defaults: { model: { primary: "github-copilot/gpt-4o" } } }
|
||||
agents: { defaults: { model: { primary: "github-copilot/gpt-4.1" } } }
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Requires an interactive TTY; run it directly in a terminal.
|
||||
- Copilot model availability depends on your plan; if a model is rejected, try
|
||||
another ID (for example `github-copilot/gpt-4.1`).
|
||||
- `gpt-4.1` is available on the free GitHub tier. Other models like `gpt-4o` and
|
||||
Claude models require a paid GitHub Copilot subscription.
|
||||
- The login stores a GitHub token in the auth profile store and exchanges it for a
|
||||
Copilot API token when Moltbot runs.
|
||||
|
||||
@ -35,6 +35,7 @@ See [Venice AI](/providers/venice).
|
||||
|
||||
- [OpenAI (API + Codex)](/providers/openai)
|
||||
- [Anthropic (API + Claude Code CLI)](/providers/anthropic)
|
||||
- [GitHub Copilot (API + CLI)](/providers/github-copilot)
|
||||
- [Qwen (OAuth)](/providers/qwen)
|
||||
- [OpenRouter](/providers/openrouter)
|
||||
- [Vercel AI Gateway](/providers/vercel-ai-gateway)
|
||||
|
||||
@ -188,6 +188,7 @@ CLAWDBOT_LIVE_SETUP_TOKEN=1 CLAWDBOT_LIVE_SETUP_TOKEN_PROFILE=anthropic:setup-to
|
||||
- Overrides (optional):
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-opus-4-5"`
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_MODEL="codex-cli/gpt-5.2-codex"`
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_MODEL="copilot-cli/gpt-4.1"`
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"`
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'`
|
||||
- `CLAWDBOT_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'`
|
||||
@ -205,6 +206,17 @@ CLAWDBOT_LIVE_CLI_BACKEND=1 \
|
||||
pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
|
||||
```
|
||||
|
||||
### Copilot CLI
|
||||
|
||||
```bash
|
||||
CLAWDBOT_LIVE_CLI_BACKEND=1 \
|
||||
CLAWDBOT_LIVE_CLI_BACKEND_MODEL="copilot-cli/gpt-4.1" \
|
||||
pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
|
||||
```
|
||||
|
||||
Note: Copilot CLI requires GitHub CLI auth (`gh auth status`). Output is text-only (no JSON).
|
||||
`gpt-4.1` is available on the GitHub Free tier; other models require a paid subscription.
|
||||
|
||||
### Recommended live recipes
|
||||
|
||||
Narrow, explicit allowlists are fastest and least flaky:
|
||||
|
||||
@ -25,6 +25,15 @@ const CLAUDE_MODEL_ALIASES: Record<string, string> = {
|
||||
"claude-haiku-3-5": "haiku",
|
||||
};
|
||||
|
||||
const COPILOT_CLI_MODEL_ALIASES: Record<string, string> = {
|
||||
"gpt-4o": "gpt-4o",
|
||||
"gpt-4.1": "gpt-4.1",
|
||||
"gpt-4.1-mini": "gpt-4.1-mini",
|
||||
"gpt-4-turbo": "gpt-4-turbo",
|
||||
"claude-sonnet-4-5": "claude-sonnet-4-5",
|
||||
"claude-opus-4-5": "claude-opus-4-5",
|
||||
};
|
||||
|
||||
const DEFAULT_CLAUDE_BACKEND: CliBackendConfig = {
|
||||
command: "claude",
|
||||
args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"],
|
||||
@ -74,6 +83,20 @@ const DEFAULT_CODEX_BACKEND: CliBackendConfig = {
|
||||
serialize: true,
|
||||
};
|
||||
|
||||
const DEFAULT_COPILOT_CLI_BACKEND: CliBackendConfig = {
|
||||
command: "copilot",
|
||||
args: ["--allow-all-tools"],
|
||||
resumeArgs: ["--allow-all-tools", "--resume", "{sessionId}"],
|
||||
output: "text",
|
||||
input: "arg",
|
||||
promptArg: "-p",
|
||||
modelArg: "--model",
|
||||
modelAliases: COPILOT_CLI_MODEL_ALIASES,
|
||||
sessionIdFields: ["session_id", "sessionId"],
|
||||
sessionMode: "existing",
|
||||
serialize: true,
|
||||
};
|
||||
|
||||
function normalizeBackendKey(key: string): string {
|
||||
return normalizeProviderId(key);
|
||||
}
|
||||
@ -107,6 +130,7 @@ export function resolveCliBackendIds(cfg?: MoltbotConfig): Set<string> {
|
||||
const ids = new Set<string>([
|
||||
normalizeBackendKey("claude-cli"),
|
||||
normalizeBackendKey("codex-cli"),
|
||||
normalizeBackendKey("copilot-cli"),
|
||||
]);
|
||||
const configured = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||
for (const key of Object.keys(configured)) {
|
||||
@ -135,6 +159,12 @@ export function resolveCliBackendConfig(
|
||||
if (!command) return null;
|
||||
return { id: normalized, config: { ...merged, command } };
|
||||
}
|
||||
if (normalized === "copilot-cli") {
|
||||
const merged = mergeBackendConfig(DEFAULT_COPILOT_CLI_BACKEND, override);
|
||||
const command = merged.command?.trim();
|
||||
if (!command) return null;
|
||||
return { id: normalized, config: { ...merged, command } };
|
||||
}
|
||||
|
||||
if (!override) return null;
|
||||
const command = override.command?.trim();
|
||||
|
||||
@ -445,7 +445,11 @@ export function buildCliArgs(params: {
|
||||
}
|
||||
}
|
||||
if (params.promptArg !== undefined) {
|
||||
args.push(params.promptArg);
|
||||
if (params.backend.promptArg) {
|
||||
args.push(params.backend.promptArg, params.promptArg);
|
||||
} else {
|
||||
args.push(params.promptArg);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ export function isCliProvider(provider: string, cfg?: MoltbotConfig): boolean {
|
||||
const normalized = normalizeProviderId(provider);
|
||||
if (normalized === "claude-cli") return true;
|
||||
if (normalized === "codex-cli") return true;
|
||||
if (normalized === "copilot-cli") return true;
|
||||
const backends = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||
return Object.keys(backends).some((key) => normalizeProviderId(key) === normalized);
|
||||
}
|
||||
|
||||
@ -87,6 +87,8 @@ export type CliBackendConfig = {
|
||||
imageArg?: string;
|
||||
/** How to pass multiple images. */
|
||||
imageMode?: "repeat" | "list";
|
||||
/** Flag used to pass the prompt (e.g. -p, --prompt). */
|
||||
promptArg?: string;
|
||||
/** Serialize runs for this CLI. */
|
||||
serialize?: boolean;
|
||||
};
|
||||
|
||||
@ -29,6 +29,7 @@ const DEFAULT_CODEX_ARGS = [
|
||||
"read-only",
|
||||
"--skip-git-repo-check",
|
||||
];
|
||||
const DEFAULT_COPILOT_CLI_ARGS = ["-p"];
|
||||
const DEFAULT_CLEAR_ENV = ["ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD"];
|
||||
|
||||
function randomImageProbeCode(len = 6): string {
|
||||
@ -216,7 +217,9 @@ describeLive("gateway live (cli backend)", () => {
|
||||
? { command: "claude", args: DEFAULT_CLAUDE_ARGS }
|
||||
: providerId === "codex-cli"
|
||||
? { command: "codex", args: DEFAULT_CODEX_ARGS }
|
||||
: null;
|
||||
: providerId === "copilot-cli"
|
||||
? { command: "copilot", args: DEFAULT_COPILOT_CLI_ARGS }
|
||||
: null;
|
||||
|
||||
const cliCommand = process.env.CLAWDBOT_LIVE_CLI_BACKEND_COMMAND ?? providerDefaults?.command;
|
||||
if (!cliCommand) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user