acdev 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,9 @@
13
13
  # An API key takes precedence over subscription login:
14
14
  # ANTHROPIC_API_KEY=sk-ant-your-key-here
15
15
  #
16
+ # OpenRouter (only when llmProvider is "openrouter" in Settings / config.json):
17
+ # OPENROUTER_API_KEY=sk-or-your-openrouter-key
18
+ #
16
19
  # Jira Cloud (only when ticketSource is "jira" in Settings / config.json):
17
20
  # JIRA_BASE_URL=https://your-domain.atlassian.net
18
21
  # JIRA_EMAIL=you@company.com
package/README.md CHANGED
@@ -15,9 +15,9 @@ You do **not** need GitHub or Claude tokens before starting `acdev`. The server
15
15
  ## Install
16
16
 
17
17
  ```bash
18
- npm i -g @giangarcia14/acdev
18
+ npm i -g acdev
19
19
  # or
20
- npx @giangarcia14/acdev
20
+ npx acdev
21
21
  ```
22
22
 
23
23
  From a local clone (development):
@@ -29,9 +29,9 @@ npm link # optional — makes `acdev` available globally
29
29
 
30
30
  ## Authentication
31
31
 
32
- `acdev` starts even when auth is missing and prints a warning. Configure GitHub and Claude from **Settings → Authentication** in the web UI (tokens are written to `.acdev/.env`, gitignored) or by editing that file directly. Leave a Settings field blank to keep the current secret. Shell environment variables override `.env` on startup; saving in Settings updates the running process immediately so status refreshes without a restart.
32
+ `acdev` starts even when auth is missing and prints a warning. Configure GitHub and your LLM provider (Claude or OpenRouter) from **Settings → Authentication** in the web UI (tokens are written to `.acdev/.env`, gitignored) or by editing that file directly. Leave a Settings field blank to keep the current secret. Shell environment variables override `.env` on startup; saving in Settings updates the running process immediately so status refreshes without a restart.
33
33
 
34
- Enqueueing issues, retrying jobs, and applying review feedback require Claude (unless `--stub-agent`). Opening a PR always requires GitHub auth. The Overview banner prompts you when auth is incomplete.
34
+ Enqueueing issues, retrying jobs, and applying review feedback require the configured LLM provider to be authenticated (Claude or OpenRouter, unless `--stub-agent`). Opening a PR always requires GitHub auth. The Overview banner prompts you when auth is incomplete.
35
35
 
36
36
  `.env` is optional when you already use `gh auth login` and `claude auth login` on the machine.
37
37
 
@@ -92,6 +92,12 @@ acdev
92
92
 
93
93
  A Claude.ai browser-only subscription does **not** give you an API key. API keys come from the [Claude Console](https://platform.claude.com/) and are billed separately from Pro/Max. To switch back to subscription login, clear the saved API key in Settings (or omit it from `.env`).
94
94
 
95
+ ### OpenRouter (optional LLM provider)
96
+
97
+ In **Settings → Configuration**, set **LLM provider** to **OpenRouter**, then add your API key under **Settings → Authentication → OpenRouter authentication** (or set `OPENROUTER_API_KEY` in `.acdev/.env`). Agent runs still use the Claude Agent SDK, routed through OpenRouter’s Anthropic-compatible API (`ANTHROPIC_BASE_URL=https://openrouter.ai/api`). Choose any model from the OpenRouter dropdown (e.g. `anthropic/claude-sonnet-4`).
98
+
99
+ **Note:** OpenRouter works best with Anthropic models on OpenRouter. Some SDK versions send Anthropic-only beta headers that OpenRouter may reject; if agent runs fail with a `context-management` error, use Claude provider directly or an Anthropic model slug on OpenRouter.
100
+
95
101
  ## Jira ticket source
96
102
 
97
103
  Tickets can come from **GitHub Issues** or **Jira Cloud**. Switch in **Settings → Ticket source**. The server still requires `gh` auth (PRs); Jira credentials are only required when enqueueing Jira issues.
@@ -211,14 +217,19 @@ On first run, creates `.acdev/config.json`:
211
217
  | `close_issue` | Transitions to a Done-category status, or else a Done/Closed/Resolved-like name | Closes the GitHub issue |
212
218
 
213
219
  Legacy Jira configs that only had `enabled` + `targetStatus` (no `action`) still work: when enabled, they migrate to `action: "set_status"`.
214
- Supported `model` values are Claude Agent SDK / Claude Code model ids (aliases like `claude-sonnet-5` / `claude-opus-5` / `sonnet`, or Anthropic API model ids). The Settings dropdown is populated by `GET /api/models`:
220
+ Supported `model` values depend on the selected LLM provider (`llmProvider` in config):
221
+
222
+ - **Claude** (`llmProvider: "claude"`, default) — Claude Agent SDK / Claude Code model ids (aliases like `claude-sonnet-5` / `claude-opus-5` / `sonnet`, or Anthropic API model ids).
223
+ - **OpenRouter** (`llmProvider: "openrouter"`) — OpenRouter model slugs (e.g. `anthropic/claude-sonnet-4`, `openai/gpt-4o`).
224
+
225
+ The Settings model dropdown is populated by `GET /api/models?provider=claude|openrouter`:
215
226
 
216
- 1. When `ANTHROPIC_API_KEY` (or `ANTHROPIC_AUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN`) is set — or Claude Code browser login credentials are readable from the local store — acdev calls Anthropic’s Models API (`GET /v1/models`) and merges results with curated Claude Code aliases.
217
- 2. Otherwise (or if the live fetch fails), the UI falls back to a curated list (Sonnet/Opus/Fable/Haiku generations + common Code aliases such as `sonnet` / `opus`) so the dropdown stays useful without an API key. The Settings hint notes when the list is static (`source: "fallback"`).
227
+ 1. **Claude** — When `ANTHROPIC_API_KEY` (or `ANTHROPIC_AUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN`) is set — or Claude Code browser login credentials are readable — acdev calls Anthropic’s Models API and merges results with curated Claude Code aliases. Otherwise falls back to a curated list (`source: "fallback"`).
228
+ 2. **OpenRouter** When `OPENROUTER_API_KEY` is set, acdev calls `GET https://openrouter.ai/api/v1/models` and merges with curated OpenRouter defaults. Without a key, shows curated OpenRouter models only.
218
229
 
219
- Empty or malformed model IDs in an existing config are migrated to `claude-sonnet-5` on load. Other valid ids are kept as-is.
230
+ Empty or malformed model IDs in an existing config are migrated to the provider default on load (`claude-sonnet-5` or `anthropic/claude-sonnet-4`). Switching providers in Settings resets the model when the current id is not in the new provider’s curated list.
220
231
 
221
- Change via **Settings → Configuration** (`PATCH /api/config`) or `--model`. Takes effect for the next agent run without restart.
232
+ Change provider/model via **Settings → Configuration** (`PATCH /api/config`) or `--model`. Takes effect for the next agent run without restart.
222
233
 
223
234
  Job state is persisted in `.acdev/state.json`.
224
235
 
@@ -234,11 +245,12 @@ npm test
234
245
 
235
246
  - `bin/acdev.js` — CLI entry; soft-checks `gh` / Claude auth (warns, does not exit). Tokens in `.acdev/.env` are loaded before auth checks. Job APIs reject until auth is OK.
236
247
  - `src/claude-auth.js` — Anthropic API key / Claude Code subscription auth detection
248
+ - `src/openrouter-auth.js` — OpenRouter API key detection
237
249
  - `src/gh-auth.js` — GitHub CLI auth (`gh auth login` or `GH_TOKEN`)
238
250
  - `src/server.js` — Express API, SSE logs, job queue, config + Jira test endpoints
239
251
  - `src/git.js` — Worktree lifecycle (`issue-<id>` paths), `feat/`/`fix/` branch naming, diff, push
240
- - `src/agent.js` — Claude Agent SDK integration (`options.model`); GitHub vs Jira prompts
241
- - `src/models.js` — `GET /api/models` list (Anthropic Models API + curated fallback)
252
+ - `src/agent.js` — Claude Agent SDK integration; OpenRouter via Anthropic-compatible routing when `llmProvider` is `openrouter`
253
+ - `src/models.js` — `GET /api/models` list (Anthropic or OpenRouter APIs + curated fallback)
242
254
  - `src/github.js` — Issue URL parsing, issue fetch via `gh`, `createPr({ draft })`
243
255
  - `src/jira.js` — Jira Cloud parse/fetch/test + issuetype → feat/fix
244
256
  - `src/config.js` — Load/save `.acdev/config.json` including ticket source
@@ -259,8 +271,8 @@ npm test
259
271
  | `DELETE` | `/api/jobs/:id` | Clear job from history (worktree best-effort); 409 if in-flight |
260
272
  | `POST` | `/api/jobs/:id/retry` | Re-queue failed/discarded |
261
273
  | `GET` | `/api/config` | Editable config + curated models + Jira status (token masked) |
262
- | `GET` | `/api/models` | `{ models, selected, source }` — live Anthropic list or curated fallback |
263
- | `PATCH` | `/api/config` | Partial update including `ticketSource`, `jiraBaseUrl`; `jiraEmail` / `jiraApiToken` → `.env` |
274
+ | `GET` | `/api/models` | `{ models, selected, source, provider }` — live provider list or curated fallback (`?provider=claude\|openrouter`) |
275
+ | `PATCH` | `/api/config` | Partial update including `llmProvider`, `ticketSource`, `jiraBaseUrl`; secrets (`openrouterApiKey`, `jiraEmail`, etc.) → `.env` |
264
276
  | `POST` | `/api/jira/test` | Test Jira credentials (`GET /rest/api/3/myself`) |
265
277
 
266
278
  ### Branch naming
package/bin/acdev.js CHANGED
@@ -4,6 +4,8 @@ import { execSync } from 'node:child_process';
4
4
  import http from 'node:http';
5
5
  import open from 'open';
6
6
  import { checkClaudeAuth, formatClaudeAuthError } from '../src/claude-auth.js';
7
+ import { checkOpenRouterAuth, formatOpenRouterAuthError } from '../src/openrouter-auth.js';
8
+ import { isValidLlmProvider } from '../src/models.js';
7
9
  import { checkGhAuth, formatGhAuthError } from '../src/gh-auth.js';
8
10
  import { loadConfig } from '../src/config.js';
9
11
  import { loadEnv } from '../src/env.js';
@@ -58,7 +60,7 @@ async function main() {
58
60
  migrateLegacyWorktreesDir(repoRoot);
59
61
  loadEnv(repoRoot);
60
62
 
61
- // Soft auth: never exit for missing GitHub/Claude credentials.
63
+ // Soft auth: never exit for missing GitHub/LLM credentials.
62
64
  // Always start the server so Settings can add tokens; job endpoints
63
65
  // reject with a clear 4xx until auth is configured.
64
66
  const ghAuth = checkGhAuth();
@@ -66,15 +68,6 @@ async function main() {
66
68
  console.warn(formatGhAuthError(ghAuth));
67
69
  }
68
70
 
69
- if (!opts.stubAgent) {
70
- const claudeAuth = checkClaudeAuth();
71
- if (!claudeAuth.ok) {
72
- console.warn(formatClaudeAuthError(claudeAuth));
73
- }
74
- } else {
75
- console.log('✓ Stub agent enabled (Claude auth not required)');
76
- }
77
-
78
71
  const config = loadConfig(repoRoot);
79
72
  if (opts.baseBranch) {
80
73
  config.baseBranch = opts.baseBranch;
@@ -83,6 +76,23 @@ async function main() {
83
76
  config.model = opts.model;
84
77
  }
85
78
 
79
+ if (!opts.stubAgent) {
80
+ const provider = isValidLlmProvider(config.llmProvider) ? config.llmProvider : 'claude';
81
+ if (provider === 'openrouter') {
82
+ const openrouterAuth = checkOpenRouterAuth();
83
+ if (!openrouterAuth.ok) {
84
+ console.warn(formatOpenRouterAuthError(openrouterAuth));
85
+ }
86
+ } else {
87
+ const claudeAuth = checkClaudeAuth();
88
+ if (!claudeAuth.ok) {
89
+ console.warn(formatClaudeAuthError(claudeAuth));
90
+ }
91
+ }
92
+ } else {
93
+ console.log('✓ Stub agent enabled (LLM auth not required)');
94
+ }
95
+
86
96
  const store = new Store(repoRoot);
87
97
  store.reconcileStaleJobs();
88
98
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acdev",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "Local CLI + web UI for running AI agents on GitHub issues via git worktrees",
5
5
  "type": "module",
6
6
  "bin": {