Skip to content

Fix opencode-local adapter tests and behavior - #240

Merged
cryppadotta merged 3 commits into
paperclipai:masterfrom
aaaaron:fix-opencode-local-adapter-tests
Mar 7, 2026
Merged

cryppadotta merged 3 commits into
paperclipai:masterfrom
aaaaron:fix-opencode-local-adapter-tests

Conversation

@aaaaron

@aaaaron aaaaron commented Mar 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Parser: Move costUsd to top-level return field in parseOpenCodeJsonl (was incorrectly nested inside usage), and fix session-not-found regex that failed to match "Session not found" patterns
  • UI stdout parser: Use callID for toolUseId (was using part.id), add status/metadata header to tool result content
  • CLI formatter: Fix tool event formatting to separate tool_call/tool_result lines, split step_finish into reason and tokens lines, trim trailing whitespace from output
  • Environment diagnostics: Enable createIfMissing for cwd validation, add empty OPENAI_API_KEY override detection, classify ProviderModelNotFoundError as warning during model discovery, make model discovery best-effort when no model is configured

Test plan

  • All 203 tests pass across 41 test files (npm test)
  • Previously failing opencode-local adapter tests now pass
  • Previously failing suite-level import errors resolved (intermittent vite caching)

🤖 Generated with Claude Code

- Move costUsd to top-level return field in parseOpenCodeJsonl (out of usage)
- Fix session-not-found regex to match "Session not found" pattern
- Use callID for toolUseId in UI stdout parser, add status/metadata header
- Fix CLI formatter: separate tool_call/tool_result lines, split step_finish
- Enable createIfMissing for cwd validation in environment tests
- Add empty OPENAI_API_KEY override detection
- Classify ProviderModelNotFoundError as warning during model discovery
- Make model discovery best-effort when no model is configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes several bugs in the opencode-local adapter: moving costUsd to a top-level parse result field (was incorrectly nested inside usage), fixing the session-not-found regex to match "Session not found" with word boundaries, using callID for toolUseId in the UI stdout parser, and improving the CLI formatter output. It also reworks environment diagnostics in test.ts to handle ProviderModelNotFoundError as a warning and make model discovery best-effort when no model is configured.

Key changes:

  • parse.ts / execute.ts: costUsd promoted to top-level; session regex fixed from \s+.*\s+ to \b.*\b to match "Session not found"
  • ui/parse-stdout.ts: toolUseId now prefers part.callID over part.id; status/metadata header prepended to tool result content
  • cli/format-event.ts: tool_call/tool_result split to separate lines; step_finish split into reason and tokens lines
  • server/test.ts: ProviderModelNotFoundError downgraded to warning; best-effort model discovery branch added for unconfigured models; empty OPENAI_API_KEY override now warns

Issues found:

  • createIfMissing: true in testEnvironment gives a diagnostic function a side effect — it creates directories on disk during validation rather than just reporting whether the cwd is valid. This diverges from the expected read-only nature of an environment check.
  • In the best-effort model discovery path (!configuredModel), non-ProviderModelNotFoundError exceptions are silently swallowed with no user-visible check or warning, meaning auth failures or binary errors would be invisible to the user.

Confidence Score: 3/5

  • Safe to merge with minor caveats — the core bug fixes are correct, but test.ts introduces a diagnostic side effect and silent error swallowing that could confuse users.
  • The parser, executor, UI parser, and CLI formatter fixes are all straightforward and correct. The test.ts changes carry two behavioral concerns: createIfMissing: true in a validation function silently mutates the filesystem, and the best-effort discovery branch drops non-ProviderModelNotFoundError failures without any user feedback. Neither is a critical runtime blocker (they only affect environment diagnostics, not execution), but they lower confidence in the diagnostic quality.
  • packages/adapters/opencode-local/src/server/test.ts — review the createIfMissing: true side effect and the silent error swallowing in the best-effort model discovery catch block.

Important Files Changed

Filename Overview
packages/adapters/opencode-local/src/server/test.ts Significant rework of environment diagnostics: adds OPENAI_API_KEY empty-override warning, splits model discovery into two paths (model configured vs. not configured), and classifies ProviderModelNotFoundError as a warning. Two issues: createIfMissing: true causes unexpected directory creation during a diagnostic-only call, and non-ProviderModelNotFoundError failures in the "no model configured" discovery branch are silently dropped.
packages/adapters/opencode-local/src/server/parse.ts Correctly moves costUsd out of the usage object to a top-level field, and fixes the session-not-found regex so that "Session not found" (single space, no extra words) is properly matched via word boundaries instead of the broken \s+.*\s+ pattern.
packages/adapters/opencode-local/src/server/execute.ts One-line fix: updates costUsd access from attempt.parsed.usage.costUsd to attempt.parsed.costUsd to match the restructured parse result. Change is correct and consistent.
packages/adapters/opencode-local/src/server/parse.test.ts Test updated to assert parsed.costUsd at the top level using toBeCloseTo, matching the new parse.ts structure. No issues.
packages/adapters/opencode-local/src/ui/parse-stdout.ts Correctly prefers part.callID over part.id for toolUseId, and prepends a status/metadata header to tool result content. Logic is clean and the fallback chain is safe.
packages/adapters/opencode-local/src/cli/format-event.ts CLI formatter updated to print tool_call and tool_result on separate lines with metadata, split step_finish into reason and token lines, and trim trailing whitespace from tool output. No issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[testEnvironment called] --> B{cwd exists?}
    B -->|createIfMissing=true\nnow creates dir| C[opencode_cwd_valid ✅]
    B -->|Error| D[opencode_cwd_invalid ❌]
    C --> E{OPENAI_API_KEY override empty?}
    E -->|Yes| F[opencode_openai_api_key_missing ⚠️]
    E -->|No| G[Resolve command]
    F --> G
    G --> H{canRunProbe?}
    H -->|No| I[Skip model discovery]
    H -->|configuredModel set| J[discoverOpenCodeModels]
    H -->|no configuredModel| K[discoverOpenCodeModels\nbest-effort]
    J -->|success| L[opencode_models_discovered ✅]
    J -->|ProviderModelNotFoundError| M[opencode_hello_probe_model_unavailable ⚠️]
    J -->|other error| N[opencode_models_discovery_failed ❌]
    K -->|success| O[opencode_models_discovered ✅]
    K -->|ProviderModelNotFoundError| P[opencode_hello_probe_model_unavailable ⚠️]
    K -->|other error| Q[🚫 silently dropped]
    L --> R{configuredModel & canRunProbe?}
    M --> R
    R -->|Yes| S[ensureOpenCodeModelConfiguredAndAvailable]
    S -->|success| T[modelValidationPassed=true]
    S -->|fail| U[opencode_model_invalid ❌]
    T --> V[Run hello probe]
    V -->|timedOut| W[opencode_hello_probe_timed_out ⚠️]
    V -->|exit=0 & no error| X{summary has 'hello'?}
    V -->|ProviderModelNotFoundError| Y[opencode_hello_probe_model_unavailable ⚠️]
    V -->|auth error| Z[opencode_hello_probe_auth_required ⚠️]
    V -->|other fail| AA[opencode_hello_probe_failed ❌]
    X -->|Yes| AB[opencode_hello_probe_passed ✅]
    X -->|No| AC[opencode_hello_probe_unexpected_output ⚠️]
Loading

Last reviewed commit: 17058dd

Comment thread packages/adapters/opencode-local/src/server/test.ts Outdated
Comment on lines +173 to 184
} catch (err) {
const errMsg = err instanceof Error ? err.message : String(err);
if (/ProviderModelNotFoundError/i.test(errMsg)) {
checks.push({
code: "opencode_hello_probe_model_unavailable",
level: "warn",
message: "The configured model was not found by the provider.",
detail: errMsg,
hint: "Run `opencode models` and choose an available provider/model ID.",
});
}
}

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.

Non-ProviderModelNotFoundError failures silently swallowed

When !configuredModel, errors from discoverOpenCodeModels that are not ProviderModelNotFoundError are silently discarded — no check is pushed at any level. This means authentication errors, binary-not-found errors, network failures, or any other unexpected errors during best-effort model discovery produce zero user-visible feedback. The user would see the environment test pass with no indication that something went wrong during model discovery.

At a minimum, unexpected errors here should be downgraded to a "warn" check rather than dropped entirely:

Suggested change
} catch (err) {
const errMsg = err instanceof Error ? err.message : String(err);
if (/ProviderModelNotFoundError/i.test(errMsg)) {
checks.push({
code: "opencode_hello_probe_model_unavailable",
level: "warn",
message: "The configured model was not found by the provider.",
detail: errMsg,
hint: "Run `opencode models` and choose an available provider/model ID.",
});
}
}
} catch (err) {
const errMsg = err instanceof Error ? err.message : String(err);
if (/ProviderModelNotFoundError/i.test(errMsg)) {
checks.push({
code: "opencode_hello_probe_model_unavailable",
level: "warn",
message: "The configured model was not found by the provider.",
detail: errMsg,
hint: "Run `opencode models` and choose an available provider/model ID.",
});
} else {
checks.push({
code: "opencode_models_discovery_failed",
level: "warn",
message: errMsg || "OpenCode model discovery failed (best-effort, no model configured).",
hint: "Run `opencode models` manually to verify provider auth and config.",
});
}
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed — adopted your suggestion. Non-ProviderModelNotFoundError failures during best-effort model discovery now emit a warn-level opencode_models_discovery_failed check instead of being silently swallowed. Fixed in 672d769.

aaaaron and others added 2 commits March 7, 2026 14:12
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
…allowed errors

- Update cwd test to expect an error for missing directories (matches
  createIfMissing: false accepted from review)
- Add warn-level check for non-ProviderModelNotFoundError failures
  during best-effort model discovery when no model is configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cryppadotta
cryppadotta merged commit 3bde21b into paperclipai:master Mar 7, 2026
1 of 2 checks passed
tmartin2113 pushed a commit to tmartin2113/paperclip that referenced this pull request Mar 15, 2026
…apter-tests

Fix opencode-local adapter tests and behavior
nydamon added a commit to nydamon/paperclip-1 that referenced this pull request Apr 19, 2026
p4w4n pushed a commit to p4w4n/paperclip that referenced this pull request May 8, 2026
…apter-tests

Fix opencode-local adapter tests and behavior
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