Skip to content

fix(ai): bypass v2 SDK session methods for structured output (#110)#140

Draft
kumar-shivang wants to merge 1 commit into
tickernelz:mainfrom
kumar-shivang:fix/issue-110-raw-fetch-structured-output
Draft

fix(ai): bypass v2 SDK session methods for structured output (#110)#140
kumar-shivang wants to merge 1 commit into
tickernelz:mainfrom
kumar-shivang:fix/issue-110-raw-fetch-structured-output

Conversation

@kumar-shivang

Copy link
Copy Markdown

Summary

PR #101 switched structured-output generation in opencode-provider.ts to
client.session.create / client.session.prompt / client.session.delete on
@opencode-ai/sdk v2. On @opencode-ai/sdk@1.14.48 this regresses auto-capture
100% of the time: the only Session class the published bundle exposes at
client.session has shifted across releases (in v1.14.48 it is a thin
experimental class with only list(); the real create/prompt/delete live
on a differently-named class reachable via a different property path), so the
client.session.create(...) call returns undefined and
created?.data?.id is undefined, triggering:

Error: opencode-mem: session.create returned no session id; cannot generate structured output

on every idle event. See #110.

Fix

Stop using the SDK's session methods for these three calls. Hit the
documented server endpoints directly with raw fetch:

action endpoint
create POST /session
prompt POST /session/{id}/message
delete DELETE /session/{id}

These paths are stable across server versions and match exactly what
tests/opencode-provider.test.ts already mocks, so the existing test suite
is preserved.

The base URL is captured when createV2Client(serverUrl) is called and
cached in a module-level _v2BaseUrl; the client argument on
StructuredOutputOptions is retained for API compatibility but is no
longer used. The setV2Client / getV2Client / createV2Client exports
are preserved so the rest of the codebase (e.g. src/index.ts,
src/services/auto-capture.ts, src/services/user-memory-learning.ts) is
unaffected.

Tests

  • bun run typecheck — clean
  • bun test — 162 pass / 0 fail (was 154 baseline; +8 new tests)
  • bunx prettier --check on changed files — clean

New tests in tests/opencode-provider.test.ts (the
generateStructuredOutput regression tests (issue #110) block) cover what
the previous suite did not:

  1. directory is forwarded as a percent-encoded query param on all three
    calls (create, prompt, delete).
  2. directory is omitted (no empty ?directory=) when not provided.
  3. Base URL with a trailing slash is normalized — no //session double
    slash.
  4. createV2Client accepts a URL object (not just a string).
  5. Non-2xx response from POST /session surfaces a clear error and skips
    prompt/delete.
  6. Non-2xx response from POST /session/{id}/message surfaces the error
    and still runs the best-effort DELETE.
  7. Network error (fetch rejection) from POST /session propagates and
    skips prompt/delete.
  8. Public API surface (generateStructuredOutput, createV2Client) is
    preserved.

Notes

  • The previous implementation happened to pass the existing tests because
    they stub globalThis.fetch, and the v2 SDK's underlying hey-api client
    ultimately calls globalThis.fetch. So the test suite stayed green even
    though the production call path was broken — the fix here is verified
    by reproducing the same globalThis.fetch mock in new tests.
  • The issue's suggested fix (option 2: fall back to raw fetch) is what
    this PR implements. Option 1 (wait for the SDK to publish the methods)
    is unnecessary once we talk to the server directly.

Refs

…ickernelz#110)

PR tickernelz#101 switched structured-output generation to client.session.create /
client.session.prompt / client.session.delete on @opencode-ai/sdk v2.
That broke auto-capture on @opencode-ai/sdk v1.14.48: client.session
has shifted class layouts across releases (the only-with-list() class
in v1.14.48 vs. the real one as a renamed class on a different
property path), so callers see 'session.create returned no session id'
on every idle event.

Switch to raw fetch against the documented server endpoints, which
are stable across server versions: POST /session, POST /session/{id}/
message, DELETE /session/{id}. The base URL is captured when
createV2Client(serverUrl) is called, so callers do not need to change.
The wire format (body shape, query params, error parsing) matches
what tests/opencode-provider.test.ts already mocked, and we add new
regression tests covering directory forwarding, trailing-slash
normalization, URL-object base URL, non-2xx responses, and network
errors.

Ref: tickernelz#110
@kumar-shivang kumar-shivang marked this pull request as ready for review June 26, 2026 11:11
@kumar-shivang kumar-shivang marked this pull request as draft June 26, 2026 11:11
@kumar-shivang kumar-shivang marked this pull request as ready for review June 26, 2026 11:14
@kumar-shivang kumar-shivang marked this pull request as draft June 26, 2026 11:23
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.

Auto-capture broken: SDK v1.14.48 has no session.create method

1 participant