Skip to content

fix(session): plumb offset through v1 list, fix v2 archived encode - #30217

Closed
lexlian wants to merge 1 commit into
anomalyco:devfrom
lexlian:fix/session-list-30109
Closed

fix(session): plumb offset through v1 list, fix v2 archived encode#30217
lexlian wants to merge 1 commit into
anomalyco:devfrom
lexlian:fix/session-list-30109

Conversation

@lexlian

@lexlianlexlian commented Jun 1, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#30109

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Two unrelated bugs in the session list surfaced together.

Bug 1 — "Load More" is stuck. The v1 GET /session endpoint ignored the offset query parameter at every layer (ListQuery, ListInput, the handler, and the drizzle query in listByProject). When directory= was specified, the response was capped at the directory's total row count regardless of the requested offset and limit, so the frontend's "Load More" button could only ever re-fetch the same first page. Plumbed offset through all four layers.

Bug 2 — /api/session?roots=true 500. The v2 Info.time.archived field was declared as optionalOmitUndefined(V2Schema.DateTimeUtcFromMillis), which inverted the type direction of the inner decodeTo transform: the encoder saw the encoded form (a number) but expected the decoded type (DateTime.Utc). The result was a 500 crash on any query that returned an archived root session, with Expected DateTime.Utc, got 1780160907969 at the offending field. Replaced with plain Schema.optional(...), which matches the convention already used for time.completed/time.ran/time.pruned in packages/core/src/session/message.ts. The wire format is now identical to the bare DateTimeUtcFromMillis (key omitted when undefined, present-with-number when set).

The v1 omit-when-undefined wire-format contract is preserved because the v1 schema uses optionalOmitUndefined(ArchivedTimestamp = Schema.Finite) with no decodeTo transform — that path was never affected.

How did you verify your code works?

  • cd packages/opencode && bun typecheck — clean
  • cd packages/core && bun typecheck — clean
  • cd packages/core && bun test ./test/session-v2-schema.test.ts — 4 new round-trip tests on the archived field schema (the canary for fix 2)
  • cd packages/opencode && bun test ./test/server/session-list.test.ts — 2 new unit tests for offset pagination, plus the 9 pre-existing tests
  • cd packages/opencode && bun test ./test/server/httpapi-session.test.ts — 1 new HTTP-level test for offset through every layer, plus the 15 pre-existing tests that pass (2 unrelated timeouts in pre-existing tests reproduce on the branch without my changes)
  • cd packages/opencode && bun test ./test/session/session-schema.test.ts ./test/session/schema-decoding.test.ts — 28 pre-existing v1 schema tests still pass; the v1 omit-when-undefined contract is preserved

Screenshots / recordings

N/A — backend fix, no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…nomalyco#30109)
Two related bugs in the session list surfaced together:
1. GET /session?directory=...&limit=N ignored the offset query
parameter at every layer, capping the response at the directory's
total row count and breaking the frontend's "Load More" button.
Plumbed offset through ListQuery, ListInput, the list handler,
and the drizzle query in listByProject.
2. GET /api/session?roots=true crashed with
"Expected DateTime.Utc, got 1780160907969" at items[i].time.archived
whenever an archived root session was in the result. The v2 Info
schema declared the field as
`optionalOmitUndefined(V2Schema.DateTimeUtcFromMillis)`, which
inverted the type direction of the inner decodeTo transform: the
encoder saw the encoded form (a number) but expected the decoded
type (DateTime.Utc). Replaced with plain `Schema.optional(...)`
to match the convention already used in
packages/core/src/session/message.ts for completed/ran/pruned.
The wire format is now identical to the bare DateTimeUtcFromMillis
field (key omitted when undefined, present-with-number when set).
Tests:
- packages/core/test/session-v2-schema.test.ts — 4 round-trip
assertions on the archived field schema, the canary for fix 2.
- packages/opencode/test/server/session-list.test.ts — 2 new tests
for offset pagination and offset past total.
- packages/opencode/test/server/httpapi-session.test.ts — 1 new
HTTP-level test for offset through every layer.
The v1 omit-when-undefined contract is preserved (v1 uses
optionalOmitUndefined(Schema.Finite) with no decodeTo transform).
All 28 pre-existing v1 schema tests still pass.
Closesanomalyco#30109
@github-actionsgithub-actionsBot added the needs:compliance This means the issue will auto-close after 2 hours. label Jun 1, 2026
@lexlianlexlian changed the title fix(session): plumb offset through v1 list, fix v2 archived encode (#30109)fix(session): plumb offset through v1 list, fix v2 archived encodeJun 1, 2026
@github-actionsgithub-actionsBot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jun 1, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session list "Load More" pagination broken when filtering by directory

1 participant

@lexlian