Skip to content

Commit ce57560

Browse files
committed
fix: initialize storage path in authorize to fix account persistence (#19)
Accounts were being saved to the wrong location when perProjectAccounts was enabled (default). The issue was that setStoragePath() was only called in the loader function, but authorize runs before loader. Now both authorize methods (browser OAuth and manual URL paste) initialize the storage path before calling persistAccountPool(). Also includes: - Test coverage improvements (89% coverage, 1498 tests) - Various code quality improvements from audit
1 parent 6e53f46 commit ce57560

90 files changed

Lines changed: 15635 additions & 1472 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "npm"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
day: "monday"
8+
open-pull-requests-limit: 5
9+
labels:
10+
- "dependencies"
11+
- "npm"
12+
commit-message:
13+
prefix: "deps"
14+
groups:
15+
dev-dependencies:
16+
dependency-type: "development"
17+
update-types:
18+
- "minor"
19+
- "patch"
20+
21+
- package-ecosystem: "github-actions"
22+
directory: "/"
23+
schedule:
24+
interval: "weekly"
25+
day: "monday"
26+
open-pull-requests-limit: 5
27+
labels:
28+
- "dependencies"
29+
- "github-actions"
30+
commit-message:
31+
prefix: "ci"

.github/workflows/ci.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,20 @@ jobs:
2828
- name: Install dependencies
2929
run: npm ci
3030

31+
- name: Security audit
32+
run: npm audit --audit-level=high
33+
3134
- name: Run type check
3235
run: npm run typecheck
3336

34-
- name: Run tests
35-
run: npm test
37+
- name: Run tests with coverage
38+
run: npm run coverage
3639

3740
- name: Build
3841
run: npm run build
3942

4043
lint:
41-
name: Type Check
44+
name: Lint
4245

4346
runs-on: ubuntu-latest
4447

@@ -55,5 +58,5 @@ jobs:
5558
- name: Install dependencies
5659
run: npm ci
5760

58-
- name: Run type check
59-
run: npm run typecheck
61+
- name: Run ESLint
62+
run: npm run lint

.github/workflows/codeql.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: "CodeQL"
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: '0 3 * * 0'
10+
11+
jobs:
12+
analyze:
13+
name: Analyze
14+
runs-on: ubuntu-latest
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Initialize CodeQL
25+
uses: github/codeql-action/init@v3
26+
with:
27+
languages: javascript-typescript
28+
queries: security-extended
29+
30+
- name: Autobuild
31+
uses: github/codeql-action/autobuild@v3
32+
33+
- name: Perform CodeQL Analysis
34+
uses: github/codeql-action/analyze@v3

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ opencode.json
88
.opencode/
99
tmp
1010
.codex-cache
11-
.sisyphus/
11+
.sisyphus/
12+
coverage/

AGENTS.md

Lines changed: 100 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,124 @@
11
# PROJECT KNOWLEDGE BASE
22

3-
Generated: 2026-01-29
4-
Commit: 693b0cc
3+
Generated: 2026-01-30
4+
Commit: 6e53f46
55
Branch: main
66

77
## OVERVIEW
8-
OpenCode plugin that swaps OpenAI SDK calls to the ChatGPT Codex backend with multi-account OAuth.
8+
OpenCode plugin: intercepts OpenAI SDK calls, routes through ChatGPT Codex backend with multi-account OAuth rotation.
99

1010
## STRUCTURE
1111
```
1212
./
13-
├── index.ts # plugin entry point (not under src/)
14-
├── lib/ # main source (auth, request, prompts, config)
15-
├── test/ # vitest suites
16-
├── scripts/ # install + build helpers
17-
├── assets/ # static assets
18-
├── config/ # OpenCode config examples
19-
├── docs/ # architecture docs/diagrams
20-
├── dist/ # build output (generated)
21-
└── SECURITY.md # vuln reporting rules
13+
├── index.ts # plugin entry (7-step fetch pipeline, tool registration)
14+
├── lib/ # core logic (see lib/AGENTS.md)
15+
├── test/ # vitest suites (see test/AGENTS.md)
16+
├── scripts/ # install + build helpers
17+
├── config/ # opencode.json examples (legacy/modern)
18+
├── docs/ # architecture + user docs
19+
├── assets/ # static assets
20+
├── dist/ # build output (generated, do not edit)
21+
└── winston/ # vendored logging (do not modify)
2222
```
2323

2424
## WHERE TO LOOK
2525
| Task | Location | Notes |
2626
| --- | --- | --- |
27-
| Fetch flow orchestration | `index.ts` | 7-step request pipeline
28-
| OAuth flow + tokens | `lib/auth/auth.ts` | PKCE, refresh, JWT decode
29-
| OAuth callback server | `lib/auth/server.ts` | binds port 1455
30-
| Request mutation | `lib/request/request-transformer.ts` | model normalization + prompts
31-
| Request helpers | `lib/request/fetch-helpers.ts` | headers, rate limit handling
32-
| SSE response handling | `lib/request/response-handler.ts` | SSE to JSON
33-
| Prompt fetching/cache | `lib/prompts/codex.ts` | GitHub release ETag cache
34-
| Config parsing | `lib/config.ts` | CODEX_MODE + options
35-
| Tests | `test/` | vitest globals enabled
27+
| Plugin orchestration | `index.ts` | 7-step request pipeline, tool registration |
28+
| OAuth flow + PKCE | `lib/auth/auth.ts` | token refresh, JWT decode |
29+
| OAuth callback server | `lib/auth/server.ts` | binds port 1455 |
30+
| Multi-account rotation | `lib/accounts.ts` | health scoring, cooldown, selection |
31+
| Account storage | `lib/storage.ts` | V3 format, per-project/global paths |
32+
| Request transformation | `lib/request/request-transformer.ts` | model normalization, prompt injection |
33+
| Headers + rate limits | `lib/request/fetch-helpers.ts` | Codex headers, error mapping |
34+
| SSE to JSON | `lib/request/response-handler.ts` | stream parsing |
35+
| Prompt templates | `lib/prompts/codex.ts` | model-family detection, GitHub ETag cache |
36+
| Config parsing | `lib/config.ts` | CODEX_MODE, plugin options |
37+
| Session recovery | `lib/recovery/` | conversation state persistence |
38+
| Graceful shutdown | `lib/shutdown.ts` | cleanup on process exit |
39+
| Health monitoring | `lib/health.ts` | account health status |
40+
| Circuit breaker | `lib/circuit-breaker.ts` | failure isolation |
41+
| Tests | `test/` | vitest globals, 80% coverage threshold |
3642

3743
## CONVENTIONS
38-
- Source lives in `index.ts` and `lib/`; `dist/` is generated.
39-
- ESLint flat config: no `any`, unused args must be prefixed with `_`.
40-
- Test files relax lint rules; see `eslint.config.js`.
41-
- Build must copy `lib/oauth-success.html` into `dist/lib/` (see `scripts/copy-oauth-success.js`).
44+
- Source: root `index.ts` + `lib/`; `dist/` is generated output.
45+
- ESLint flat config: `no-explicit-any` enforced, unused args prefixed `_`.
46+
- Tests relax lint rules (see `eslint.config.js`).
47+
- Build copies `lib/oauth-success.html` to `dist/lib/` via `scripts/copy-oauth-success.js`.
48+
- ESM only (`"type": "module"`), Node >= 18.
4249

4350
## ANTI-PATTERNS (THIS PROJECT)
44-
- Do not edit `dist/` outputs or `tmp*` directories.
45-
- Do not open public security issues; follow `SECURITY.md` for reporting.
51+
- Do not edit `dist/`, `tmp*`, or `winston/` directories.
52+
- Do not use `as any`, `@ts-ignore`, `@ts-expect-error`.
53+
- Do not open public security issues; see `SECURITY.md`.
54+
- Do not hardcode ports other than 1455 for OAuth server.
4655

4756
## COMMANDS
4857
```bash
49-
npm run build
50-
npm run typecheck
51-
npm test
52-
npm run lint
58+
npm run build # tsc + copy oauth-success.html
59+
npm run typecheck # type checking only
60+
npm test # vitest once
61+
npm run test:watch # vitest watch mode
62+
npm run lint # eslint
5363
```
5464

5565
## NOTES
56-
- OAuth callback server binds `http://127.0.0.1:1455/auth/callback`.
57-
- ChatGPT backend requires stateless requests (`store: false`, include encrypted reasoning).
66+
- OAuth callback: `http://127.0.0.1:1455/auth/callback`.
67+
- ChatGPT backend requires `store: false`, include `reasoning.encrypted_content`.
68+
- Per-project accounts: `.opencode/openai-codex-accounts.json` (walks up to find project root).
69+
- Global accounts: `~/.opencode/openai-codex-accounts.json`.
70+
- Prompt templates synced from Codex CLI GitHub releases with ETag caching.
71+
- 5xx server errors trigger account rotation and health penalty (same as network errors).
72+
- API deprecation/sunset headers (RFC 8594) are logged as warnings.
73+
- StorageError preserves original stack traces via `cause` parameter.
74+
- saveToDiskDebounced errors are logged but don't crash the plugin.
75+
76+
## SKILL MAPPING (for delegate_task)
77+
78+
Skills to load when delegating tasks in this codebase.
79+
80+
### Core Skills (load on most tasks)
81+
82+
| Skill | Justification |
83+
|-------|---------------|
84+
| `typescript-senior` | Strict mode, template literal types (`QuotaKey`), discriminated unions (`TokenResult`), Zod inference |
85+
| `node-backend` | ESM-first, `node:crypto`, Buffer API, async patterns |
86+
| `testing-js` | Vitest with 80% coverage threshold, `vi.mock`, `vi.useFakeTimers` |
87+
| `mcp-builder` | Uses `@opencode-ai/plugin/tool` pattern for tool registration |
88+
89+
### Domain-Specific Skills (load when touching these areas)
90+
91+
| Skill | When to Load | Key Files |
92+
|-------|--------------|-----------|
93+
| `auth-patterns` | OAuth flow, PKCE, JWT, token refresh | `lib/auth/auth.ts`, `lib/refresh-queue.ts` |
94+
| `secrets-management` | Token storage, credential handling | `lib/storage.ts`, account JSON files |
95+
| `api-design` | Request transformation, headers, SSE | `lib/request/` directory |
96+
| `error-observability` | Circuit breaker, health scoring, logging | `lib/circuit-breaker.ts`, `lib/logger.ts`, `lib/health.ts` |
97+
| `git-master` | Any git operations | - |
98+
| `github` | PRs, GitHub API (ETag caching) | `lib/prompts/codex.ts` |
99+
100+
### Situational Skills
101+
102+
| Skill | When to Load |
103+
|-------|--------------|
104+
| `clean-architecture` | Refactoring, new module design |
105+
| `property-based-testing` | Testing rotation logic, rate-limit edge cases |
106+
107+
### Quick Reference
108+
109+
```typescript
110+
// Auth work
111+
delegate_task(category="...", load_skills=["typescript-senior", "node-backend", "auth-patterns", "secrets-management"])
112+
113+
// Request pipeline work
114+
delegate_task(category="...", load_skills=["typescript-senior", "node-backend", "api-design", "error-observability"])
115+
116+
// Testing
117+
delegate_task(category="...", load_skills=["typescript-senior", "node-backend", "testing-js"])
118+
119+
// Plugin architecture
120+
delegate_task(category="...", load_skills=["typescript-senior", "node-backend", "mcp-builder"])
121+
122+
// Git/GitHub operations
123+
delegate_task(category="quick", load_skills=["git-master", "github"])
124+
```

CODEOWNERS

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Default owner for everything
2+
* @ndycode
3+
4+
# Core library code
5+
/lib/ @ndycode
6+
7+
# Authentication
8+
/lib/auth/ @ndycode
9+
10+
# Tests
11+
/test/ @ndycode
12+
13+
# CI/CD and configuration
14+
/.github/ @ndycode

CUsersAdministratorDevToolsoc-chatgpt-multi-authfirst_fail.txt

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)