feat: add GitHub Copilot CLI as a built-in CLI backend
Co-authored-by: htekdev <100806365+htekdev@users.noreply.github.com>
This commit is contained in:
parent
647cf2e177
commit
44ea06f36a
@ -6,6 +6,7 @@ Docs: https://docs.molt.bot
|
|||||||
Status: beta.
|
Status: beta.
|
||||||
|
|
||||||
### Changes
|
### 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.
|
- 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.
|
- 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).
|
- macOS: limit project-local `node_modules/.bin` PATH preference to debug builds (reduce PATH hijacking risk).
|
||||||
|
|||||||
@ -1008,6 +1008,8 @@
|
|||||||
"providers/models",
|
"providers/models",
|
||||||
"providers/openai",
|
"providers/openai",
|
||||||
"providers/anthropic",
|
"providers/anthropic",
|
||||||
|
"providers/github-copilot",
|
||||||
|
"providers/github-copilot-cli",
|
||||||
"bedrock",
|
"bedrock",
|
||||||
"providers/moonshot",
|
"providers/moonshot",
|
||||||
"providers/minimax",
|
"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
|
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-4o
|
||||||
|
```
|
||||||
|
|
||||||
If your gateway runs under launchd/systemd and PATH is minimal, add just the
|
If your gateway runs under launchd/systemd and PATH is minimal, add just the
|
||||||
command path:
|
command path:
|
||||||
|
|
||||||
@ -200,6 +206,18 @@ Moltbot also ships a default for `codex-cli`:
|
|||||||
- `imageArg: "--image"`
|
- `imageArg: "--image"`
|
||||||
- `sessionMode: "existing"`
|
- `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).
|
Override only if needed (common: absolute `command` path).
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|||||||
@ -1668,6 +1668,9 @@ Example:
|
|||||||
"claude-cli": {
|
"claude-cli": {
|
||||||
command: "/opt/homebrew/bin/claude"
|
command: "/opt/homebrew/bin/claude"
|
||||||
},
|
},
|
||||||
|
"copilot-cli": {
|
||||||
|
command: "/opt/homebrew/bin/copilot"
|
||||||
|
},
|
||||||
"my-cli": {
|
"my-cli": {
|
||||||
command: "my-cli",
|
command: "my-cli",
|
||||||
args: ["--json"],
|
args: ["--json"],
|
||||||
|
|||||||
191
docs/providers/github-copilot-cli.md
Normal file
191
docs/providers/github-copilot-cli.md
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
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 Copilot subscription** (Individual, Business, or Enterprise)
|
||||||
|
- **Node.js 22+**
|
||||||
|
- **GitHub CLI** (`gh`) authenticated with your GitHub account
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install the Copilot CLI via npm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g @github/copilot
|
||||||
|
```
|
||||||
|
|
||||||
|
Or via Homebrew:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install github/copilot/copilot
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use the `gh copilot` extension:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gh extension install github/gh-copilot
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
copilot --help
|
||||||
|
# or
|
||||||
|
gh copilot --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
Use Copilot CLI directly with Moltbot:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
moltbot agent --message "hi" --model copilot-cli/gpt-4o
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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-4o",
|
||||||
|
fallbacks: [
|
||||||
|
"copilot-cli/gpt-4o"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
models: {
|
||||||
|
"github-copilot/gpt-4o": { alias: "Copilot" },
|
||||||
|
"copilot-cli/gpt-4o": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported models
|
||||||
|
|
||||||
|
Copilot CLI supports these models (availability depends on your plan):
|
||||||
|
|
||||||
|
- `gpt-4o`
|
||||||
|
- `gpt-4.1`
|
||||||
|
- `gpt-4.1-mini`
|
||||||
|
- `gpt-4-turbo`
|
||||||
|
- `claude-sonnet-4-5`
|
||||||
|
- `claude-opus-4-5`
|
||||||
|
|
||||||
|
Example model refs:
|
||||||
|
|
||||||
|
```
|
||||||
|
copilot-cli/gpt-4o
|
||||||
|
copilot-cli/gpt-4.1
|
||||||
|
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)
|
||||||
@ -35,6 +35,7 @@ See [Venice AI](/providers/venice).
|
|||||||
|
|
||||||
- [OpenAI (API + Codex)](/providers/openai)
|
- [OpenAI (API + Codex)](/providers/openai)
|
||||||
- [Anthropic (API + Claude Code CLI)](/providers/anthropic)
|
- [Anthropic (API + Claude Code CLI)](/providers/anthropic)
|
||||||
|
- [GitHub Copilot (API + CLI)](/providers/github-copilot)
|
||||||
- [Qwen (OAuth)](/providers/qwen)
|
- [Qwen (OAuth)](/providers/qwen)
|
||||||
- [OpenRouter](/providers/openrouter)
|
- [OpenRouter](/providers/openrouter)
|
||||||
- [Vercel AI Gateway](/providers/vercel-ai-gateway)
|
- [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):
|
- Overrides (optional):
|
||||||
- `CLAWDBOT_LIVE_CLI_BACKEND_MODEL="claude-cli/claude-opus-4-5"`
|
- `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="codex-cli/gpt-5.2-codex"`
|
||||||
|
- `CLAWDBOT_LIVE_CLI_BACKEND_MODEL="copilot-cli/gpt-4o"`
|
||||||
- `CLAWDBOT_LIVE_CLI_BACKEND_COMMAND="/full/path/to/claude"`
|
- `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_ARGS='["-p","--output-format","json","--permission-mode","bypassPermissions"]'`
|
||||||
- `CLAWDBOT_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'`
|
- `CLAWDBOT_LIVE_CLI_BACKEND_CLEAR_ENV='["ANTHROPIC_API_KEY","ANTHROPIC_API_KEY_OLD"]'`
|
||||||
@ -205,6 +206,16 @@ CLAWDBOT_LIVE_CLI_BACKEND=1 \
|
|||||||
pnpm test:live src/gateway/gateway-cli-backend.live.test.ts
|
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-4o" \
|
||||||
|
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).
|
||||||
|
|
||||||
### Recommended live recipes
|
### Recommended live recipes
|
||||||
|
|
||||||
Narrow, explicit allowlists are fastest and least flaky:
|
Narrow, explicit allowlists are fastest and least flaky:
|
||||||
|
|||||||
13304
package-lock.json
generated
Normal file
13304
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,15 @@ const CLAUDE_MODEL_ALIASES: Record<string, string> = {
|
|||||||
"claude-haiku-3-5": "haiku",
|
"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 = {
|
const DEFAULT_CLAUDE_BACKEND: CliBackendConfig = {
|
||||||
command: "claude",
|
command: "claude",
|
||||||
args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"],
|
args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"],
|
||||||
@ -74,6 +83,19 @@ const DEFAULT_CODEX_BACKEND: CliBackendConfig = {
|
|||||||
serialize: true,
|
serialize: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DEFAULT_COPILOT_CLI_BACKEND: CliBackendConfig = {
|
||||||
|
command: "copilot",
|
||||||
|
args: ["-p"],
|
||||||
|
resumeArgs: ["-p", "--resume", "{sessionId}"],
|
||||||
|
output: "text",
|
||||||
|
input: "arg",
|
||||||
|
modelArg: "--model",
|
||||||
|
modelAliases: COPILOT_CLI_MODEL_ALIASES,
|
||||||
|
sessionIdFields: ["session_id", "sessionId"],
|
||||||
|
sessionMode: "existing",
|
||||||
|
serialize: true,
|
||||||
|
};
|
||||||
|
|
||||||
function normalizeBackendKey(key: string): string {
|
function normalizeBackendKey(key: string): string {
|
||||||
return normalizeProviderId(key);
|
return normalizeProviderId(key);
|
||||||
}
|
}
|
||||||
@ -107,6 +129,7 @@ export function resolveCliBackendIds(cfg?: MoltbotConfig): Set<string> {
|
|||||||
const ids = new Set<string>([
|
const ids = new Set<string>([
|
||||||
normalizeBackendKey("claude-cli"),
|
normalizeBackendKey("claude-cli"),
|
||||||
normalizeBackendKey("codex-cli"),
|
normalizeBackendKey("codex-cli"),
|
||||||
|
normalizeBackendKey("copilot-cli"),
|
||||||
]);
|
]);
|
||||||
const configured = cfg?.agents?.defaults?.cliBackends ?? {};
|
const configured = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||||
for (const key of Object.keys(configured)) {
|
for (const key of Object.keys(configured)) {
|
||||||
@ -135,6 +158,12 @@ export function resolveCliBackendConfig(
|
|||||||
if (!command) return null;
|
if (!command) return null;
|
||||||
return { id: normalized, config: { ...merged, command } };
|
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;
|
if (!override) return null;
|
||||||
const command = override.command?.trim();
|
const command = override.command?.trim();
|
||||||
|
|||||||
@ -29,6 +29,7 @@ const DEFAULT_CODEX_ARGS = [
|
|||||||
"read-only",
|
"read-only",
|
||||||
"--skip-git-repo-check",
|
"--skip-git-repo-check",
|
||||||
];
|
];
|
||||||
|
const DEFAULT_COPILOT_CLI_ARGS = ["-p"];
|
||||||
const DEFAULT_CLEAR_ENV = ["ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD"];
|
const DEFAULT_CLEAR_ENV = ["ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD"];
|
||||||
|
|
||||||
function randomImageProbeCode(len = 6): string {
|
function randomImageProbeCode(len = 6): string {
|
||||||
@ -216,7 +217,9 @@ describeLive("gateway live (cli backend)", () => {
|
|||||||
? { command: "claude", args: DEFAULT_CLAUDE_ARGS }
|
? { command: "claude", args: DEFAULT_CLAUDE_ARGS }
|
||||||
: providerId === "codex-cli"
|
: providerId === "codex-cli"
|
||||||
? { command: "codex", args: DEFAULT_CODEX_ARGS }
|
? { 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;
|
const cliCommand = process.env.CLAWDBOT_LIVE_CLI_BACKEND_COMMAND ?? providerDefaults?.command;
|
||||||
if (!cliCommand) {
|
if (!cliCommand) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user