Skip to content

fix: prefer opencode.jsonc when loading OpenCode config#118

Merged
kargnas merged 4 commits intoopgginc:mainfrom
Daltonganger:feat/prefer-opencode-jsonc
Apr 3, 2026
Merged

fix: prefer opencode.jsonc when loading OpenCode config#118
kargnas merged 4 commits intoopgginc:mainfrom
Daltonganger:feat/prefer-opencode-jsonc

Conversation

@Daltonganger
Copy link
Copy Markdown
Contributor

Summary

  • prefer opencode.jsonc before opencode.json when OpenCode Bar reads OpenCode config
  • align Swift config discovery with OpenCode/copilothydra JSONC-first behavior
  • add TokenManager tests for JSONC-first path ordering and JSONC comment parsing

@op-gg-ai-devops
Copy link
Copy Markdown
Contributor

op-gg-ai-devops bot commented Apr 1, 2026

✅ AI Code Review Completed

Status Task Result
Read repo AGENTS.md, resolved issues, and repo context Got the ground rules and context sorted.
Read full diff and changed files in context Scanned the whole diff.
Analyze code changes for bugs, security, correctness, edge cases Verified logic and edge cases.
Run smoke tests (build/typecheck/lint) Build and lint are all green.
Check CI status and existing reviews Checked CI and previous comments.
Write review_payload.json and update status comment Review posted successfully.

Reviewed with anthropic/claude-opus-4-6


📋 View Full Logs

Copy link
Copy Markdown
Contributor

@op-gg-ai-devops op-gg-ai-devops bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Clean, focused PR — adds .jsonc preference ahead of .json when resolving OpenCode config paths, matching the copilothydra behavior. The zip + flatMap interleave is elegant and produces the correct [dir/jsonc, dir/json, dir/jsonc, dir/json, ...] ordering. Tests are thorough and cover ordering invariants, extension counts, directory coverage, and end-to-end JSONC parsing.

What's good

  • The zip(jsoncPaths, jsonPaths).flatMap { [$0, $1] } pattern is clever — it keeps the per-directory jsonc-before-json priority without duplicating the fallback directory list. Nice.
  • Test coverage is solid. testOpenCodeConfigFilePathsReturnsJSONCBeforeJSONForEachLocation is exactly the right structural test for this kind of interleaving logic.
  • The stripJSONComments visibility change to internal for test access is the correct approach — @testable import + internal is idiomatic Swift testing.
  • Doc comments updated accurately with the new 8-path priority order.

One defensive note (not blocking)

The zip approach silently drops elements if the two arrays ever differ in length. Right now they can't — both calls to buildOpenCodeFilePaths use the same directory structure with only the filename differing, so dedup always removes/keeps the same indices. But if someone later adds a fallback directory to only one call, zip would silently swallow it. A debug assert could catch that:

assert(jsoncPaths.count == jsonPaths.count, "jsonc/json path arrays must be equal length for correct interleaving")

Not a blocker at all — just a defensive thought for future-proofing.

CI Status

  • Lint: ✅ passed
  • Build / Test / CI: still running at time of review

Smoke tests (build, typecheck) could not be run locally — this is a macOS Swift project and the review runner is Linux.


🤖 This bot reviews every push to this branch automatically. You can also trigger a review with specific focus by mentioning @op-gg-ai-devops in a PR comment. Examples:

  • @op-gg-ai-devops review typos
  • @op-gg-ai-devops focus on edge cases in the zip logic
  • @op-gg-ai-devops check test coverage

@op-gg-ai-devops
Copy link
Copy Markdown
Contributor

op-gg-ai-devops bot commented Apr 1, 2026

✅ AI Code Review Completed

Review finished. Check the PR for inline comments.


📋 View Logs | 🤖 Model: anthropic/claude-opus-4-6

@kargnas
Copy link
Copy Markdown
Member

kargnas commented Apr 2, 2026

@op-gg-ai-devops

@op-gg-ai-devops
Copy link
Copy Markdown
Contributor

op-gg-ai-devops bot commented Apr 2, 2026

✅ AI Code Review Completed

Review posted successfully — APPROVED with summary and notes.

Status Task Result
Read repo AGENTS.md, resolved issues, and repo context Got the ground rules and context sorted.
Read full diff and changed files in context Scanned the whole diff — both commits.
Analyze code changes for bugs, security, correctness, edge cases Verified logic and edge cases.
Run smoke tests (build/typecheck/lint) macOS Swift project — CI all green (Lint, Build, CI, Test).
Check CI status and existing reviews Checked CI and previous bot review.
Write review_payload.json and update status comment Payload written.
Post review to PR Review posted — APPROVED.

Reviewed with anthropic/claude-opus-4-6


📋 View Full Logs

Copy link
Copy Markdown
Contributor

@op-gg-ai-devops op-gg-ai-devops bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

New commit since last review: 16a4080 adds openaiAPIKey fallback support for when openai in auth.json is stored as an API key object instead of OAuth. This is a clean extension of the existing lossy decoding pattern — the decoder tries OAuth first, falls back to APIKey, and everything flows through correctly.

What's good

  • The dual-decode approach is elegant: try .openai as OAuth, and if that fails, try it as APIKey. KeyedDecodingContainer allows re-reading the same key, so this works perfectly.
  • The encoder guard (if openai == nil { try container.encodeIfPresent(openaiAPIKey, forKey: .openai) }) prevents duplicate JSON keys during round-trip encoding. Solid.
  • getOpenAIAccounts() and getOpenAIAccessToken() both gain API key fallback paths, maintaining the existing priority chain (OAuth → API Key → Codex native auth).
  • Test updates are well-placed — the OpenCodeAuthDecodingTests now assert both the positive case (openaiAPIKey?.key == "sk-test-openai") and the mutual exclusion case (openaiAPIKey is nil when OAuth succeeds).
  • Status/debug display updates are thorough — token status, debug info, and the ChatGPT section all account for the new API key variant.
  • All CI checks passing: Lint ✅, Build ✅, CI ✅, Test ✅.

One thought (not blocking)

The getOpenAIAccounts() API key account creation path (lines 2833-2848) doesn't have a dedicated unit test. The decoding is covered, but there's no test verifying that getOpenAIAccounts() returns an account with source: .opencodeAuth and sourceLabels: ["OpenCode (API Key)"] when auth.json has an API key entry. Might be worth adding if you're in the neighborhood — but CI is green and the path is straightforward, so not blocking.

@op-gg-ai-devops
Copy link
Copy Markdown
Contributor

op-gg-ai-devops bot commented Apr 2, 2026

✅ AI Code Review Completed

Review has been posted — 1 inline comment, approval granted. all done.

Status Task Result
Read repo AGENTS.md, resolved issues, and repo context Got the ground rules and context sorted.
Read full diff and changed files in context Scanned the whole diff — both new commits.
Analyze code changes for bugs, security, correctness, edge cases Verified logic and edge cases.
Run smoke tests (build/typecheck/lint) macOS Swift project — CI checks: SwiftLint ✅, GHA Lint ✅, Build/Test 🔄
Check CI status and existing reviews Checked CI and previous bot reviews.
Write review_payload.json and update status comment Payload written.
Post review to PR Review posted successfully.

Reviewed with anthropic/claude-opus-4-6


📋 View Full Logs

Copy link
Copy Markdown
Contributor

@op-gg-ai-devops op-gg-ai-devops bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Solid follow-up — both suggestions from the previous review are implemented cleanly. The assert guard catches future interleave mismatches, and the new testGetOpenAIAccountsIncludesOpenCodeAPIKeyAccount test covers the end-to-end API key account discovery path that was missing.

What's good

  • clearOpenCodeAuthCacheForTesting() is the right approach — wraps all three cache fields in a queue.sync block, no shortcuts. Clean test helper.
  • The test itself is thorough: creates a temp directory, overrides XDG_DATA_HOME, writes a minimal auth.json with API key format, verifies all account fields (accessToken, authSource, sourceLabels, source), and properly cleans up via defer. nice.
  • The assert guard on the zip interleaving is exactly the defensive check that prevents silent data loss if someone adds a directory to only one of the two buildOpenCodeFilePaths calls later.

One nit (not blocking)

Lines 117–122 in testGetOpenAIAccountsIncludesOpenCodeAPIKeyAccount save the original XDG_DATA_HOME and immediately set/unset it back — this is a no-op. The actual restore happens in the defer block (lines 123–130), which is correct. The pre-defer block is dead code that just reads the value and writes it right back. Harmless but a bit confusing to read.

CI Status

  • SwiftLint: ✅ passed
  • GitHub Actions Lint: ✅ passed
  • Build & Test: 🔄 still running at time of review

Smoke tests (build, typecheck) could not be run locally — this is a macOS Swift project and the review runner is Linux.

Comment on lines +117 to +122
let originalXDGDataHome = ProcessInfo.processInfo.environment["XDG_DATA_HOME"]
if let originalXDGDataHome {
setenv("XDG_DATA_HOME", originalXDGDataHome, 1)
} else {
unsetenv("XDG_DATA_HOME")
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Style Dead code before defer: no-op env var set/unset

This block (lines 117–122) reads the current XDG_DATA_HOME value and immediately sets it back to the same value — it's a no-op. The real restore logic is in the defer block below, which is correct. You can safely remove this pre-defer block to reduce confusion:

Suggested change
let originalXDGDataHome = ProcessInfo.processInfo.environment["XDG_DATA_HOME"]
if let originalXDGDataHome {
setenv("XDG_DATA_HOME", originalXDGDataHome, 1)
} else {
unsetenv("XDG_DATA_HOME")
}
let originalXDGDataHome = ProcessInfo.processInfo.environment["XDG_DATA_HOME"]
defer {

@kargnas kargnas merged commit 90fb9e5 into opgginc:main Apr 3, 2026
9 checks passed
@kargnas
Copy link
Copy Markdown
Member

kargnas commented Apr 3, 2026

this is so cool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants