Uh oh!
There was an error while loading. Please reload this page.
fix(session): plumb offset through v1 list, fix v2 archived encode - #30217
fix(session): plumb offset through v1 list, fix v2 archived encode#30217lexlian wants to merge 1 commit into
Conversation
…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
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
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:
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. |
Issue for this PR
Closes#30109
Type of change
What does this PR do?
Two unrelated bugs in the session list surfaced together.
Bug 1 — "Load More" is stuck. The v1
GET /sessionendpoint ignored theoffsetquery parameter at every layer (ListQuery,ListInput, the handler, and the drizzle query inlistByProject). Whendirectory=was specified, the response was capped at the directory's total row count regardless of the requestedoffsetandlimit, so the frontend's "Load More" button could only ever re-fetch the same first page. Plumbedoffsetthrough all four layers.Bug 2 —
/api/session?roots=true500. The v2Info.time.archivedfield was declared asoptionalOmitUndefined(V2Schema.DateTimeUtcFromMillis), which inverted the type direction of the innerdecodeTotransform: 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, withExpected DateTime.Utc, got 1780160907969at the offending field. Replaced with plainSchema.optional(...), which matches the convention already used fortime.completed/time.ran/time.prunedinpackages/core/src/session/message.ts. The wire format is now identical to the bareDateTimeUtcFromMillis(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 nodecodeTotransform — that path was never affected.How did you verify your code works?
cd packages/opencode && bun typecheck— cleancd packages/core && bun typecheck— cleancd 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 testscd 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 preservedScreenshots / recordings
N/A — backend fix, no UI change.
Checklist