@open330/oac 2026.3.1 → 2026.3.3

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.
package/README.md ADDED
@@ -0,0 +1,454 @@
1
+ <div align="center">
2
+
3
+ ```
4
+ ___ _ ____
5
+ / _ \ / \ / ___|
6
+ | | | |/ _ \| |
7
+ | |_| / ___ \ |___
8
+ \___/_/ \_\____|
9
+
10
+ O P E N A G E N T C O N T R I B U T I O N
11
+ ```
12
+
13
+ **Put your spare AI tokens to work. Contribute to open source — automatically.**
14
+
15
+ [![npm](https://img.shields.io/npm/v/@open330/oac?label=npm&color=CB3837&logo=npm)](https://www.npmjs.com/package/@open330/oac)
16
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
17
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
18
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.7+-3178C6?logo=typescript&logoColor=white)](https://typescriptlang.org/)
19
+
20
+ [Getting Started](#-getting-started) · [How It Works](#-how-it-works) · [Commands](#-commands) · [Architecture](#-architecture) · [Contributing](#-contributing)
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## The Problem
27
+
28
+ You pay for AI agent tokens every month. Claude Code, Codex, OpenCode — they all come with token budgets. But most days, you don't use them all. Those leftover tokens? **Wasted.**
29
+
30
+ Meanwhile, thousands of open source repos have TODOs nobody finishes, lint warnings nobody fixes, tests nobody writes, and issues nobody picks up.
31
+
32
+ ## The Solution
33
+
34
+ **OAC** bridges the gap. Point it at a repo, and it will:
35
+
36
+ 1. **Scan** the codebase for actionable tasks (TODOs, lint issues, missing tests, open GitHub issues)
37
+ 2. **Estimate** token costs and pick tasks that fit your remaining budget
38
+ 3. **Execute** the work using your AI agent of choice — in parallel, sandboxed environments
39
+ 4. **Submit** pull requests, link issues, and track every contribution
40
+
41
+ ```bash
42
+ # Install globally
43
+ npm install -g @open330/oac
44
+
45
+ # That's it. One command.
46
+ oac run --repo facebook/react --tokens 50000
47
+
48
+ # Or run without installing
49
+ npx @open330/oac run --repo facebook/react --tokens unlimited
50
+ ```
51
+
52
+ ```
53
+ Scanning facebook/react...
54
+ Found 23 tasks (12 lint fixes, 6 TODOs, 5 test gaps)
55
+
56
+ Budget: 50,000 tokens
57
+ Selected: 8 tasks (est. 42,300 tokens)
58
+ Reserve: 5,000 tokens (10%)
59
+
60
+ [Claude] ████████░░ 4/8 tasks completed
61
+ [Claude] ✔ PR #1847: Fix unused imports in scheduler
62
+ [Claude] ✔ PR #1848: Add tests for reconciler edge case
63
+ [Claude] ⠋ Resolving TODO in ReactFiberHooks.js...
64
+
65
+ ─────────────────────────────────────
66
+ Done! 7/8 tasks succeeded
67
+ PRs created: 7
68
+ Tokens used: 38,420 / 50,000
69
+ Contribution logged to .oac/contributions/
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Features
75
+
76
+ | | Feature | Description |
77
+ |---|---------|-------------|
78
+ | **Scan** | Task Discovery | Finds TODOs, lint issues, test gaps, dead code, and open GitHub issues |
79
+ | **Budget** | Token Estimation | Per-provider token counting with knapsack-optimized task selection |
80
+ | **Run** | Parallel Execution | Run 2-3 agents simultaneously in isolated git worktrees |
81
+ | **Ship** | PR Automation | Creates PRs, links issues, notifies Linear/Jira via webhooks |
82
+ | **Track** | Contribution Logs | Git-native audit trail in `.oac/` — who contributed what, with how many tokens |
83
+ | **Rank** | Leaderboard | See who's recycling the most tokens across your team |
84
+
85
+ ---
86
+
87
+ ## Quick Start
88
+
89
+ ### Prerequisites
90
+
91
+ - **Node.js** >= 22
92
+ - **git** installed
93
+ - At least one AI agent CLI: [Claude Code](https://claude.ai/code), [Codex](https://github.com/openai/codex), or [OpenCode](https://github.com/opencode-ai/opencode)
94
+
95
+ ### Install
96
+
97
+ ```bash
98
+ # From npm (recommended)
99
+ npm install -g @open330/oac
100
+
101
+ # Or use without installing
102
+ npx @open330/oac --help
103
+
104
+ # From source (for contributors)
105
+ git clone https://github.com/Open330/open-agent-contribution.git
106
+ cd open-agent-contribution
107
+ pnpm install
108
+ pnpm build
109
+ ```
110
+
111
+ ### Setup
112
+
113
+ ```bash
114
+ # Interactive setup wizard
115
+ oac init
116
+ ```
117
+
118
+ ```
119
+ ___ _ ____
120
+ / _ \ / \ / ___|
121
+ | | | |/ _ \| |
122
+ | |_| / ___ \ |___
123
+ \___/_/ \_\____|
124
+
125
+ Welcome to Open Agent Contribution.
126
+ Let's put your spare tokens to work.
127
+
128
+ ? Select your AI providers: › Claude Code, Codex CLI
129
+ ? Monthly token budget for OAC: › 100000
130
+ ? Add your first repo (owner/repo): › facebook/react
131
+
132
+ ✔ Config written to oac.config.ts
133
+ ✔ Created .oac/ tracking directory
134
+ Ready! Run 'oac doctor' to verify or 'oac run' to start.
135
+ ```
136
+
137
+ ### Verify
138
+
139
+ ```bash
140
+ oac doctor
141
+ ```
142
+
143
+ ```
144
+ Environment Check
145
+ ─────────────────
146
+ [✔] Node.js v24.0.0
147
+ [✔] git v2.43.0
148
+ [✔] GitHub Auth gh authenticated as @jiun
149
+ [✔] Claude CLI v1.0.16
150
+ [✘] Codex CLI not found
151
+
152
+ 4/5 checks passed
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Commands
158
+
159
+ | Command | Description |
160
+ |---------|-------------|
161
+ | `oac init` | Interactive setup wizard — creates `oac.config.ts` |
162
+ | `oac doctor` | Verify environment (Node, git, agents, auth) |
163
+ | `oac scan` | Discover tasks in a repo without executing |
164
+ | `oac plan` | Show execution plan with token budget breakdown |
165
+ | `oac run` | Full pipeline: scan → estimate → execute → PR → track |
166
+ | `oac status` | Show running/recent job status |
167
+ | `oac log` | View contribution history |
168
+ | `oac leaderboard` | Show contribution rankings |
169
+ | `oac dashboard` | Launch localhost web dashboard |
170
+
171
+ ### `oac run` — The Main Event
172
+
173
+ ```bash
174
+ oac run \
175
+ --repo owner/repo \ # Target repository
176
+ --tokens 50000 \ # Token budget (or "unlimited")
177
+ --provider claude-code \ # AI agent to use
178
+ --concurrency 2 \ # Parallel agents (default: 2)
179
+ --mode new-pr \ # Create PRs (or: direct-commit)
180
+ --dry-run # Preview without executing
181
+
182
+ # Run with unlimited budget (keeps going until rate-limited)
183
+ oac run --repo owner/repo --tokens unlimited --concurrency 3
184
+ ```
185
+
186
+ ### `oac scan` — See What's Out There
187
+
188
+ ```bash
189
+ oac scan --repo owner/repo --format table
190
+ ```
191
+
192
+ ```
193
+ ┌─────────┬──────────────────────────────────┬────────┬──────────┬────────────┐
194
+ │ ID │ Title │ Source │ Priority │ Complexity │
195
+ ├─────────┼──────────────────────────────────┼────────┼──────────┼────────────┤
196
+ │ a1b2c3 │ Fix unused import in utils.ts │ lint │ 85 │ trivial │
197
+ │ d4e5f6 │ TODO: Add input validation │ todo │ 72 │ simple │
198
+ │ g7h8i9 │ Missing tests for Parser class │ test │ 68 │ moderate │
199
+ │ j0k1l2 │ Remove dead code in legacy/ │ dead │ 45 │ simple │
200
+ │ #142 │ Fix date formatting bug │ issue │ 91 │ moderate │
201
+ └─────────┴──────────────────────────────────┴────────┴──────────┴────────────┘
202
+ 5 tasks discovered
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Configuration
208
+
209
+ OAC uses a TypeScript config file:
210
+
211
+ ```typescript
212
+ // oac.config.ts
213
+ export default {
214
+ repos: ['facebook/react', 'vercel/next.js'],
215
+
216
+ provider: {
217
+ id: 'claude-code',
218
+ options: { model: 'opus' },
219
+ },
220
+
221
+ budget: {
222
+ totalTokens: 100_000,
223
+ reservePercent: 0.10,
224
+ },
225
+
226
+ discovery: {
227
+ scanners: {
228
+ lint: true,
229
+ todo: true,
230
+ testGap: true,
231
+ deadCode: false,
232
+ githubIssues: true,
233
+ },
234
+ issueLabels: ['good-first-issue', 'help-wanted', 'bug'],
235
+ },
236
+
237
+ execution: {
238
+ concurrency: 2,
239
+ mode: 'new-pr',
240
+ taskTimeout: 300,
241
+ },
242
+ };
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Architecture
248
+
249
+ ```
250
+ ┌─────────────────────────────────────────────────────┐
251
+ │ oac CLI / Dashboard │
252
+ └────────────────────────┬────────────────────────────┘
253
+
254
+ ┌──────────▼──────────┐
255
+ │ Core Engine │
256
+ │ (Event Bus + Config)│
257
+ └──┬──┬──┬──┬──┬──┬──┘
258
+ │ │ │ │ │ │
259
+ ┌────────────┘ │ │ │ │ └────────────┐
260
+ │ │ │ │ │ │
261
+ ┌───▼───┐ ┌───────▼──▼──▼───────┐ ┌───────▼───────┐
262
+ │ Repo │ │ Discovery → Budget │ │ Tracking │
263
+ │Select │ │ → Execution │ │ (.oac/ logs) │
264
+ └───────┘ └─────────┬───────────┘ └───────────────┘
265
+
266
+ ┌──────▼──────┐
267
+ │ Completion │
268
+ │ (PR + Issue) │
269
+ └──────┬──────┘
270
+
271
+ ┌─────────▼─────────┐
272
+ │ GitHub / Linear │
273
+ │ / Jira │
274
+ └───────────────────┘
275
+ ```
276
+
277
+ ### Packages
278
+
279
+ All packages are published under the `@open330` scope on npm:
280
+
281
+ | Package | npm | Description |
282
+ |---------|-----|-------------|
283
+ | [`@open330/oac`](packages/cli) | [![npm](https://img.shields.io/npm/v/@open330/oac?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac) | CLI — the main entry point |
284
+ | [`@open330/oac-core`](packages/core) | [![npm](https://img.shields.io/npm/v/@open330/oac-core?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-core) | Event bus, config, types, errors |
285
+ | [`@open330/oac-repo`](packages/repo) | [![npm](https://img.shields.io/npm/v/@open330/oac-repo?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-repo) | GitHub repo resolution, cloning, metadata |
286
+ | [`@open330/oac-discovery`](packages/discovery) | [![npm](https://img.shields.io/npm/v/@open330/oac-discovery?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-discovery) | Task scanners (lint, TODO, test-gap, issues) |
287
+ | [`@open330/oac-budget`](packages/budget) | [![npm](https://img.shields.io/npm/v/@open330/oac-budget?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-budget) | Token estimation, complexity analysis, planning |
288
+ | [`@open330/oac-execution`](packages/execution) | [![npm](https://img.shields.io/npm/v/@open330/oac-execution?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-execution) | Agent pool, job queue, worktree sandbox |
289
+ | [`@open330/oac-completion`](packages/completion) | [![npm](https://img.shields.io/npm/v/@open330/oac-completion?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-completion) | PR creation, issue linking |
290
+ | [`@open330/oac-tracking`](packages/tracking) | [![npm](https://img.shields.io/npm/v/@open330/oac-tracking?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-tracking) | Contribution logs, leaderboard |
291
+ | [`@open330/oac-dashboard`](packages/dashboard) | [![npm](https://img.shields.io/npm/v/@open330/oac-dashboard?label=&color=CB3837)](https://www.npmjs.com/package/@open330/oac-dashboard) | Fastify web dashboard with SSE streaming |
292
+
293
+ ### Tech Stack
294
+
295
+ | Layer | Technology |
296
+ |-------|-----------|
297
+ | Runtime | Node.js 22+, TypeScript 5.7+, ESM |
298
+ | Build | pnpm workspaces, Turborepo, tsup |
299
+ | CLI | Commander.js, chalk, ora, cli-table3 |
300
+ | Git | simple-git, git worktrees for isolation |
301
+ | GitHub | @octokit/rest |
302
+ | AI Agents | Claude Code (`claude-code`), Codex CLI (`codex`) — pluggable via `AgentProvider` |
303
+ | Dashboard | Fastify + embedded SPA with SSE streaming |
304
+ | Quality | Vitest, Biome |
305
+
306
+ ---
307
+
308
+ ## Contribution Tracking
309
+
310
+ Every run creates a JSON log in `.oac/contributions/`:
311
+
312
+ ```
313
+ .oac/
314
+ ├── contributions/
315
+ │ ├── 2026-02-17-143052-jiun.json
316
+ │ ├── 2026-02-17-151023-jiun.json
317
+ │ └── 2026-02-18-091500-alice.json
318
+ └── leaderboard.json
319
+ ```
320
+
321
+ Each log records: who contributed, which tasks, tokens used, PRs created, and execution metrics. The leaderboard aggregates across all contributors.
322
+
323
+ ```bash
324
+ oac leaderboard
325
+ ```
326
+
327
+ ```
328
+ Contribution Leaderboard
329
+ ────────────────────────
330
+ #1 jiun 42 tasks 284,000 tokens 38 PRs merged
331
+ #2 alice 31 tasks 195,000 tokens 27 PRs merged
332
+ #3 bob 18 tasks 122,000 tokens 15 PRs merged
333
+ ```
334
+
335
+ ---
336
+
337
+ ## How It Works
338
+
339
+ ```
340
+ You run `oac run`
341
+
342
+
343
+ ┌─────────┐ Shallow clone, cache metadata
344
+ │ Repo │────────────────────────────────────┐
345
+ │ Select │ │
346
+ └────┬─────┘ │
347
+ │ │
348
+ ▼ ▼
349
+ ┌─────────┐ TODO, lint, test-gap, ┌──────────┐
350
+ │ Scan │──── GitHub issues ──────────▶│ Tasks │
351
+ └────┬────┘ └────┬─────┘
352
+ │ │
353
+ ▼ ▼
354
+ ┌─────────┐ tiktoken counting, ┌──────────┐
355
+ │ Budget │──── knapsack selection ─────▶│ Plan │
356
+ └────┬────┘ (10% reserve) └────┬─────┘
357
+ │ │
358
+ ▼ ▼
359
+ ┌─────────┐ git worktree per agent ┌──────────┐
360
+ │Execute │──── parallel sandboxes ─────▶│ Results │
361
+ └────┬────┘ └────┬─────┘
362
+ │ │
363
+ ▼ ▼
364
+ ┌─────────┐ Validate diff, ┌──────────┐
365
+ │Complete │──── create PR, link issue ──▶│ PRs │
366
+ └────┬────┘ └────┬─────┘
367
+ │ │
368
+ ▼ ▼
369
+ ┌─────────┐ .oac/contributions/ ┌──────────┐
370
+ │ Track │──── JSON audit log ─────────▶│ Done! │
371
+ └─────────┘ └──────────┘
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Supported AI Agents
377
+
378
+ | Agent | Status | Provider ID |
379
+ |-------|--------|-------------|
380
+ | [Claude Code](https://claude.ai/code) | Supported | `claude-code` |
381
+ | [Codex CLI](https://github.com/openai/codex) | Supported | `codex` |
382
+ | [OpenCode](https://github.com/opencode-ai/opencode) | Planned | `opencode` |
383
+ | Custom | Implement `AgentProvider` interface | any string |
384
+
385
+ ### Adding a Custom Agent
386
+
387
+ ```typescript
388
+ import type { AgentProvider } from '@open330/oac-execution';
389
+
390
+ export class MyAgentAdapter implements AgentProvider {
391
+ readonly id = 'my-agent';
392
+ readonly name = 'My Custom Agent';
393
+
394
+ async checkAvailability() { /* ... */ }
395
+ execute(params) { /* ... */ }
396
+ async estimateTokens(params) { /* ... */ }
397
+ async abort(executionId) { /* ... */ }
398
+ }
399
+ ```
400
+
401
+ ---
402
+
403
+ ## Roadmap
404
+
405
+ - [x] **2026.2.17** — Core engine, CLI, 5 scanners, parallel execution, dashboard, npm publish
406
+ - [x] **2026.3.x** — Claude Code + Codex CLI adapters (both supported)
407
+ - [ ] **Next** — OpenCode adapter, multi-agent routing (run multiple agents simultaneously)
408
+ - [ ] **Future** — Linear/Jira webhooks, plugin system, sparse checkout for monorepos
409
+
410
+ ---
411
+
412
+ ## Contributing
413
+
414
+ We welcome contributions! OAC is designed to contribute to repos — and it can contribute to itself too.
415
+
416
+ ```bash
417
+ # Clone and setup
418
+ git clone https://github.com/Open330/open-agent-contribution.git
419
+ cd open-agent-contribution
420
+ pnpm install
421
+ pnpm build
422
+
423
+ # Run tests
424
+ pnpm test
425
+
426
+ # Lint and format
427
+ pnpm lint
428
+ pnpm format
429
+
430
+ # Or just let OAC contribute to itself
431
+ npx @open330/oac run --repo Open330/open-agent-contribution --tokens unlimited
432
+ ```
433
+
434
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
435
+
436
+ ---
437
+
438
+ ## Philosophy
439
+
440
+ > **"Don't let your tokens go to waste."**
441
+
442
+ Every month, developers around the world leave millions of AI tokens on the table. OAC turns that idle capacity into real open source contributions — automatically, safely, and transparently.
443
+
444
+ No hosted services. No data collection. No lock-in. Just your machine, your tokens, and your repos.
445
+
446
+ ---
447
+
448
+ <div align="center">
449
+
450
+ **Built with spare tokens by the [Open330](https://github.com/Open330) community.**
451
+
452
+ [Report Bug](https://github.com/Open330/open-agent-contribution/issues) · [Request Feature](https://github.com/Open330/open-agent-contribution/issues) · [Discussions](https://github.com/Open330/open-agent-contribution/discussions)
453
+
454
+ </div>
@@ -13,7 +13,7 @@ function createDoctorCommand() {
13
13
  const globalOptions = getGlobalOptions(cmd);
14
14
  const ui = createUi(globalOptions);
15
15
  const checks = await runDoctorChecks();
16
- const allPassed = checks.every((check) => check.status === "pass");
16
+ const allPassed = checks.every((check) => check.status !== "fail");
17
17
  if (globalOptions.json) {
18
18
  console.log(
19
19
  JSON.stringify(
@@ -70,7 +70,7 @@ async function runDoctorChecks() {
70
70
  const codexResult = await runCommand("codex", ["--version"]);
71
71
  const codexVersion = extractVersion(codexResult.stdout) ?? "--";
72
72
  checks.push({
73
- id: "codex-cli",
73
+ id: "codex",
74
74
  name: "Codex CLI",
75
75
  requirement: "installed",
76
76
  value: codexVersion,
@@ -92,12 +92,14 @@ async function checkGithubAuth() {
92
92
  }
93
93
  const authResult = await runCommand("gh", ["auth", "status"]);
94
94
  if (authResult.ok) {
95
+ const hasRepoScope = authResult.stdout.includes("repo");
95
96
  return {
96
97
  id: "github-auth",
97
98
  name: "GitHub auth",
98
99
  requirement: "gh auth status or GITHUB_TOKEN",
99
100
  value: "gh auth status",
100
- status: "pass"
101
+ status: hasRepoScope ? "pass" : "warn",
102
+ message: hasRepoScope ? void 0 : "Missing 'repo' scope \u2014 private repos won't work. Run: gh auth refresh -s repo"
101
103
  };
102
104
  }
103
105
  return {
@@ -127,8 +129,10 @@ function renderDoctorOutput(ui, checks, allPassed) {
127
129
  console.log("Checking environment...");
128
130
  console.log("");
129
131
  for (const check of checks) {
130
- const icon = check.status === "pass" ? ui.green("[OK]") : ui.red("[X]");
131
- const status = check.status === "pass" ? ui.green("PASS") : ui.red("FAIL");
132
+ const iconMap = { pass: ui.green("[OK]"), warn: ui.yellow("[!]"), fail: ui.red("[X]") };
133
+ const statusMap = { pass: ui.green("PASS"), warn: ui.yellow("WARN"), fail: ui.red("FAIL") };
134
+ const icon = iconMap[check.status];
135
+ const status = statusMap[check.status];
132
136
  const name = check.name.padEnd(12, " ");
133
137
  const requirement = check.requirement.padEnd(30, " ");
134
138
  const value = check.value.padEnd(14, " ");
@@ -136,6 +140,9 @@ function renderDoctorOutput(ui, checks, allPassed) {
136
140
  if (check.status === "fail" && check.message) {
137
141
  console.log(` ${ui.red(check.message)}`);
138
142
  }
143
+ if (check.status === "warn" && check.message) {
144
+ console.log(` ${ui.yellow(check.message)}`);
145
+ }
139
146
  }
140
147
  console.log("");
141
148
  if (allPassed) {
@@ -260,8 +267,8 @@ function createInitCommand() {
260
267
  message: "Select AI provider(s):",
261
268
  choices: [
262
269
  { name: "Claude Code", value: "claude-code", checked: true },
263
- { name: "Codex CLI", value: "codex-cli" },
264
- { name: "OpenCode", value: "opencode" }
270
+ { name: "Codex CLI", value: "codex" },
271
+ { name: "OpenCode (coming soon)", value: "opencode", disabled: true }
265
272
  ],
266
273
  validate: (value) => value.length > 0 ? true : "Select at least one provider to continue."
267
274
  });
@@ -784,6 +791,21 @@ function ensureGitHubAuth() {
784
791
  }
785
792
  return void 0;
786
793
  }
794
+ function checkGitHubScopes(required = ["repo"]) {
795
+ try {
796
+ const output = execFileSync("gh", ["auth", "status"], {
797
+ timeout: 5e3,
798
+ encoding: "utf-8",
799
+ stdio: ["ignore", "pipe", "pipe"]
800
+ });
801
+ const scopeMatch = output.match(/Token scopes:\s*'([^']+)'/);
802
+ if (!scopeMatch) return [];
803
+ const scopes = scopeMatch[1].split(",").map((s) => s.trim().replace(/^'|'$/g, ""));
804
+ return required.filter((r) => !scopes.includes(r));
805
+ } catch {
806
+ return [];
807
+ }
808
+ }
787
809
 
788
810
  // src/commands/plan.ts
789
811
  import chalk3, { Chalk as Chalk3 } from "chalk";
@@ -1089,6 +1111,7 @@ import {
1089
1111
  rankTasks as rankTasks2
1090
1112
  } from "@open330/oac-discovery";
1091
1113
  import {
1114
+ ClaudeCodeAdapter,
1092
1115
  CodexAdapter,
1093
1116
  createSandbox,
1094
1117
  executeTask as workerExecuteTask
@@ -1125,9 +1148,28 @@ function createRunCommand() {
1125
1148
  if (!ghToken && !outputJson) {
1126
1149
  console.log(
1127
1150
  ui.yellow(
1128
- "[oac] Warning: GitHub auth not detected. Run `gh auth login` first to enable PR creation."
1151
+ "[oac] Warning: GitHub auth not detected. Run `gh auth login` first."
1152
+ )
1153
+ );
1154
+ console.log(
1155
+ ui.yellow(
1156
+ "[oac] For private repos, ensure the 'repo' scope: gh auth refresh -s repo"
1129
1157
  )
1130
1158
  );
1159
+ } else if (ghToken && !outputJson) {
1160
+ const missingScopes = checkGitHubScopes(["repo"]);
1161
+ if (missingScopes.length > 0) {
1162
+ console.log(
1163
+ ui.yellow(
1164
+ `[oac] Warning: GitHub token missing scope(s): ${missingScopes.join(", ")}. Private repos may fail.`
1165
+ )
1166
+ );
1167
+ console.log(
1168
+ ui.yellow(
1169
+ "[oac] Fix with: gh auth refresh -s repo"
1170
+ )
1171
+ );
1172
+ }
1131
1173
  }
1132
1174
  if (!outputJson) {
1133
1175
  console.log(
@@ -1219,18 +1261,17 @@ function createRunCommand() {
1219
1261
  }
1220
1262
  return;
1221
1263
  }
1222
- const codexAdapter = new CodexAdapter();
1223
- const codexAvailability = await codexAdapter.checkAvailability();
1224
- const useRealExecution = providerId.includes("codex") && codexAvailability.available;
1264
+ const { adapter, useRealExecution } = await resolveAdapter(providerId);
1225
1265
  if (!outputJson && globalOptions.verbose) {
1226
- if (useRealExecution) {
1266
+ if (useRealExecution && adapter) {
1267
+ const avail = await adapter.checkAvailability();
1227
1268
  console.log(
1228
1269
  ui.green(
1229
- `[oac] Using Codex CLI v${codexAvailability.version ?? "unknown"} for execution.`
1270
+ `[oac] Using ${adapter.name} v${avail.version ?? "unknown"} for execution.`
1230
1271
  )
1231
1272
  );
1232
1273
  } else {
1233
- console.log(ui.yellow("[oac] Codex CLI not available. Using simulated execution."));
1274
+ console.log(ui.yellow("[oac] No agent CLI available. Using simulated execution."));
1234
1275
  }
1235
1276
  }
1236
1277
  const executionSpinner = createSpinner2(
@@ -1244,11 +1285,11 @@ function createRunCommand() {
1244
1285
  async (entry) => {
1245
1286
  let execution;
1246
1287
  let sandbox;
1247
- if (useRealExecution) {
1248
- const result = await executeWithCodex({
1288
+ if (useRealExecution && adapter) {
1289
+ const result = await executeWithAgent({
1249
1290
  task: entry.task,
1250
1291
  estimate: entry.estimate,
1251
- codexAdapter,
1292
+ adapter,
1252
1293
  repoPath: resolvedRepo.localPath,
1253
1294
  baseBranch: resolvedRepo.meta.defaultBranch,
1254
1295
  timeoutSeconds
@@ -1447,6 +1488,20 @@ function resolveRepoInput2(repoOption, config) {
1447
1488
  }
1448
1489
  throw new Error("No repository specified. Use --repo or configure repos in oac.config.ts.");
1449
1490
  }
1491
+ async function resolveAdapter(providerId) {
1492
+ const normalizedId = providerId === "codex-cli" ? "codex" : providerId;
1493
+ const adapters = {
1494
+ codex: () => new CodexAdapter(),
1495
+ "claude-code": () => new ClaudeCodeAdapter()
1496
+ };
1497
+ const factory = adapters[normalizedId];
1498
+ if (!factory) {
1499
+ return { adapter: null, useRealExecution: false };
1500
+ }
1501
+ const adapter = factory();
1502
+ const availability = await adapter.checkAvailability();
1503
+ return { adapter: availability.available ? adapter : null, useRealExecution: availability.available };
1504
+ }
1450
1505
  function resolveProviderId2(providerOption, config) {
1451
1506
  const fromFlag = providerOption?.trim();
1452
1507
  if (fromFlag) {
@@ -1516,7 +1571,7 @@ async function estimateTaskMap2(tasks, providerId) {
1516
1571
  );
1517
1572
  return new Map(entries);
1518
1573
  }
1519
- async function executeWithCodex(input2) {
1574
+ async function executeWithAgent(input2) {
1520
1575
  const startedAt = Date.now();
1521
1576
  const taskSlug = input2.task.id.replace(/[^a-zA-Z0-9-]/g, "-").replace(/-+/g, "-").slice(0, 30);
1522
1577
  const branchName = `oac/${Date.now()}-${taskSlug}`;
@@ -1528,7 +1583,7 @@ async function executeWithCodex(input2) {
1528
1583
  cleanup: sandbox.cleanup
1529
1584
  };
1530
1585
  try {
1531
- const result = await workerExecuteTask(input2.codexAdapter, input2.task, sandbox, eventBus, {
1586
+ const result = await workerExecuteTask(input2.adapter, input2.task, sandbox, eventBus, {
1532
1587
  tokenBudget: input2.estimate.totalEstimatedTokens,
1533
1588
  timeoutMs: input2.timeoutSeconds * 1e3
1534
1589
  });
@@ -2282,4 +2337,4 @@ export {
2282
2337
  createCliProgram,
2283
2338
  runCli
2284
2339
  };
2285
- //# sourceMappingURL=chunk-PYSJFMKA.js.map
2340
+ //# sourceMappingURL=chunk-GII2GWGO.js.map