Skip to content

refactor: sync session runtime lane#140

Merged
Astro-Han merged 6 commits into
devfrom
codex/refactor-i92-session-sync
Apr 22, 2026
Merged

refactor: sync session runtime lane#140
Astro-Han merged 6 commits into
devfrom
codex/refactor-i92-session-sync

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Sync the [Feature] Sync OpenCode upstream v1.14.20 intake #92 Session lane for retained recent turns during compaction, including tail_start_id on compaction parts and compacted message filtering for successful summaries and pending compactions.
  • Make tool-output pruning explicit opt-in via compaction.prune, and update config, SDK, and OpenAPI metadata.
  • Fix v2 session entry reduction so interleaved tool events route by callID, retry attempts are recorded with structured error context, and session error schema access is deferred with z.lazy.

Why

Part of #92. This lands the session runtime slice after the Base PR #102, while keeping Runtime Resource and Desktop work out of scope.

Compatibility Notes

  • Existing configs that still want automatic old tool-output pruning should set compaction.prune: true.
  • v2 retried events now store structured retry errors, and legacy string retry errors are still accepted and normalized while reducing session entries.

Related Issue

Part of #92.

How To Verify

bun test test/session/compaction.test.ts test/session/messages-pagination.test.ts test/session/session-entry.test.ts test/session/session.test.ts
cd packages/opencode && bun run typecheck
cd packages/sdk/js && bun run typecheck

Latest local results after autosquash:

  • Focused session tests: 115 pass, 0 fail
  • packages/opencode typecheck: pass
  • packages/sdk/js typecheck: pass
  • git diff --check origin/dev...HEAD: pass

Note: full bun turbo typecheck currently fails in @opencode-ai/desktop-electron on @opencode-ai/util/file-extensions module resolution. This is outside this PR diff, which does not touch packages/desktop-electron or packages/util.

Screenshots or Recordings

Not applicable. No visible UI changes.

Checklist

  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I listed the relevant verification steps, including tests when behavior changed
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, or generated/local file changes when relevant
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • New Features

    • Intelligent tail-budgeting during compaction to preserve recent conversation turns.
    • Added structured assistant retry records with attempt counts and rich error details.
    • Compaction parts can mark a tail boundary (tail_start_id) to retain recent messages verbatim.
  • Bug Fixes

    • Fixed tool state routing for interleaved concurrent tool calls.
    • Corrected overflow/headroom calculation for content management.
  • Configuration

    • compaction.prune now defaults to false; set true to enable pruning.
  • Tests

    • Added comprehensive compaction, pagination, retry, and schema validation tests.

@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority upstream Tracked upstream or vendor behavior labels Apr 22, 2026
@gemini-code-assist

Copy link
Copy Markdown

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 26 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 26 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9917da8f-63f5-415c-b6d3-9fdae013481f

📥 Commits

Reviewing files that changed from the base of the PR and between 4089f23 and 21beb25.

⛔ Files ignored due to path filters (1)
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (12)
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/message-v2.ts
  • packages/opencode/src/session/overflow.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/src/v2/session-entry.ts
  • packages/opencode/src/v2/session-event.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/opencode/test/session/messages-pagination.test.ts
  • packages/opencode/test/session/session-entry.test.ts
  • packages/opencode/test/session/session.test.ts
  • packages/sdk/openapi.json
📝 Walkthrough

Walkthrough

Added tail-preserving compaction that splits history into head+tail using token budgets and preserves a tail boundary (tail_start_id); compaction now only prunes when explicitly enabled. Also introduced structured retry-error types and assistant retry recording, adjusted related tests and OpenAPI config description.

Changes

Cohort / File(s) Summary
Config / OpenAPI
packages/opencode/src/config/config.ts, packages/sdk/openapi.json
Updated compaction.prune description to indicate default false. Added optional CompactionPart.tail_start_id to OpenAPI schema.
Compaction implementation
packages/opencode/src/session/compaction.ts, packages/opencode/src/session/overflow.ts
Added tail-budgeting helpers (usable, tailBudget, estimate, select), changed compaction to summarize only head while preserving tail_start_id; compaction pruning now runs only when cfg.compaction?.prune === true; simplified usable calc in overflow.
Message model / filtering
packages/opencode/src/session/message-v2.ts
Extended CompactionPart with optional tail_start_id and updated filterCompacted to detect the newest tail boundary while iterating and slice output to retain messages at/after that boundary.
Retry types & session entry
packages/opencode/src/v2/session-event.ts, packages/opencode/src/v2/session-entry.ts
Added SessionEvent.RetryError schema and union-typed Retried.error (supports structured or legacy string) with optional attempt; added SessionEntry.AssistantRetry and appended retry tracking to assistant entries; tool matching updated to use callID.
Session schema lazy load
packages/opencode/src/session/session.ts
Changed Event.Error schema to lazily evaluate nested MessageV2.Assistant.shape.error via z.lazy().
Tests — compaction & messages
packages/opencode/test/session/compaction.test.ts, packages/opencode/test/session/messages-pagination.test.ts
Added helpers and deterministic LLM test utilities; new tests for tail selection, summarization input scoping, pending vs finalized compaction boundaries, and default vs explicit pruning behavior.
Tests — retries & session
packages/opencode/test/session/session-entry.test.ts, packages/opencode/test/session/session.test.ts
Added tests for retry recording (including legacy-string normalization and interleaved callID handling) and a test validating lazy error schema parsing.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Session
    participant MessageStore as Message\nHistory
    participant Estimator as Token\nEstimator
    participant LLM as LLM\nSummarizer

    Client->>Session: step() with long history
    Session->>MessageStore: filterCompacted()
    MessageStore-->>Session: active messages
    Session->>Estimator: estimate(recent turns)
    Estimator-->>Session: token counts
    Session->>Session: select(head, tail_start_id) based on budget
    alt tail preserved
        Session->>LLM: summarize(head only)
        LLM-->>Session: summary
        Session->>MessageStore: store CompactionPart (summary, tail_start_id)
    else fallback (no tail fit)
        Session->>LLM: summarize full history
        LLM-->>Session: summary
        Session->>MessageStore: store CompactionPart (no tail_start_id)
    end
    Session-->>Client: next state includes summary + retained tail
Loading
sequenceDiagram
    participant Client
    participant EventBus
    participant Session
    participant AssistantState

    Client->>EventBus: emit SessionEvent.Retried(attempt?, error)
    EventBus->>Session: deliver retried event
    Session->>Session: normalize error (string → RetryError if needed)
    Session->>AssistantState: append AssistantRetry (attempt, error)
    AssistantState-->>Client: updated assistant entry with retries
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 I nibbled tokens, found a trail,

I kept the tail and trimmed the tale.
Retries logged neat, errors tamed,
Summaries hummed while tails remained.
Hop—compaction gifts a carrot named! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'refactor: sync session runtime lane' uses vague terminology ('lane', 'sync') that doesn't clearly convey the main changes (compaction tail retention, pruning opt-in, retry error handling). Use a more descriptive title that highlights key changes, such as 'refactor: add tail retention for compaction and make tool pruning opt-in' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description includes all required template sections: Summary (describing changes), Why (linking to #92 and #102), Related Issue, How To Verify (with test commands), Screenshots (N/A noted), and a complete checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/refactor-i92-session-sync

Comment @coderabbitai help to get the list of available commands and usage tips.

@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch from add7de7 to c1c0dcc Compare April 22, 2026 11:28
@Astro-Han Astro-Han marked this pull request as ready for review April 22, 2026 11:29
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/session/message-v2.ts Outdated
Comment thread packages/opencode/src/v2/session-entry.ts
Comment thread packages/opencode/src/v2/session-event.ts
Comment thread packages/opencode/src/config/config.ts
Comment thread packages/opencode/test/session/compaction.test.ts Outdated
Comment thread packages/opencode/test/session/compaction.test.ts
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/session/message-v2.ts
@Astro-Han

Copy link
Copy Markdown
Owner Author

Review Summary

This PR introduces significant changes to the compaction system with retained recent turns and interleaved tool routing. Overall the implementation appears sound, but I have several nitpick-level concerns:

Key Issues

  1. Breaking Change - Retried Event Schema: The error field changed from Schema.String to RetryError object. This may break existing persisted session data. Please confirm that Retried events are transient and not stored long-term, or document a migration strategy.

  2. Behavior Change - prune Default: Changing from true to false affects existing users. Consider documenting this in release notes.

Missing Documentation

Several complex logic blocks lack comments explaining their rationale:

  • The select function's fallback behavior when first turn exceeds budget
  • The start === 0 edge case in tail selection
  • The history calculation for re-compaction scenarios
  • The filterCompacted two-phase logic (forward capture + reverse slice)

Test Concerns

  • Token budget boundary conditions not tested
  • JSON.stringify verification is fragile

The inline comments above detail each concern.

@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch 2 times, most recently from f36ca2d to f88df74 Compare April 22, 2026 13:03
@Astro-Han

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/session/compaction.ts`:
- Around line 369-375: The guard currently prevents clearing a persisted tail
because it requires selected.tail_start_id to be truthy; remove that truthiness
check so we compare and persist changes even when selected.tail_start_id is
undefined. Update the condition around compactionPart and the call to
session.updatePart (referencing compactionPart, selected.tail_start_id, and
session.updatePart) to simply check compactionPart &&
compactionPart.tail_start_id !== selected.tail_start_id and then call
session.updatePart with tail_start_id: selected.tail_start_id (allowing
undefined to clear the stored boundary).

In `@packages/opencode/src/session/message-v2.ts`:
- Around line 934-951: The loop currently only assigns tailStartID from
compaction parts on messages that are marked completed, which lets an older
completed compaction override a newer pending one; change the logic in the
newest→oldest scan (the block that inspects compactionPart and completed) so
that the first compactionPart you encounter with a defined tail_start_id
immediately sets tailStartID (regardless of msg.info.complete status) and stops
the scan (break/continue as appropriate), so the newest seen tail_start_id wins;
keep the existing fallback that scans result.flatMap(...).find(...) but ensure
it only runs if tailStartID is still unset.

In `@packages/opencode/test/session/compaction.test.ts`:
- Around line 695-702: The new tests create ManagedRuntime instances via
runtime("continue", Plugin.defaultLayer, ProviderTest.fake(), cfg({ prune: true
})) but never call .dispose(), leaking scoped resources; wrap each runtime usage
in a try/finally and call rt.dispose() in the finally (or use a helper that
auto-disposes) for the occurrences around the SessionCompaction.Service.use
calls (also fix the other two spans noted near the 825–840 and 882–897 regions)
to ensure each runtime is disposed after the test completes.

In `@packages/opencode/test/session/messages-pagination.test.ts`:
- Around line 714-742: Replace the raw Jest test declaration and manual Effect
runtime plumbing with the Effect test harness: change the top-level test("keeps
retained tail messages after a compaction part with tail_start_id", ...) to use
testEffect(...) (or it.live(...) as used in this file) from test/lib/effect.ts,
and lift the async body into the Effect test body so you no longer call
Instance.provide manually; keep the same interactions with svc.create,
svc.updatePart, MessageV2.stream/filterCompacted and the same assertions
(expect(ids).toContain(retained) / not.toContain(old)), and remove the explicit
Instance.provide/Instance cleanup plumbing so the harness manages the Effect
runtime and lifecycle.
- Around line 714-742: The test currently only asserts the retained user message
ID is preserved, but must also assert that its associated assistant/tool reply
is retained to ensure full-turn preservation; change the addAssistant call that
follows the retained user to capture its returned ID (e.g., const
retainedAssistant = await addAssistant(session.id, retained)) and add an
assertion expect(ids).toContain(retainedAssistant). Apply the same change for
the other similar test block (the one also noted at 744-780) so both user and
their assistant/tool message IDs are asserted present when using
MessageV2.filterCompacted(MessageV2.stream(session.id)).

In `@packages/sdk/openapi.json`:
- Around line 8918-8921: Add a clear description for the public OpenAPI schema
field "tail_start_id" so generated SDK docs are self-explanatory; update the
schema for "tail_start_id" (the property with "type": "string" and "pattern":
"^msg.*") to include a concise description like "Optional message ID (must start
with 'msg') to begin tailing events from the specified message onward" and
mention its behavior (e.g., inclusive/exclusive) if applicable.
- Around line 11545-11546: Update the OpenAPI description for the
compaction.prune property to explicitly state the behavior when set to false:
clarify that true enables pruning of old tool outputs, false disables pruning
(no automatic pruning), and omission defaults to no automatic pruning; modify
the description string for the "compaction.prune" schema entry accordingly so
generated docs and UIs unambiguously show true = prune, false = do not prune,
omitted = no automatic pruning.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a9f64f91-a276-4a71-b8f8-1b2fe2021d3b

📥 Commits

Reviewing files that changed from the base of the PR and between b3b9f45 and f88df74.

⛔ Files ignored due to path filters (1)
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (11)
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/message-v2.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/src/v2/session-entry.ts
  • packages/opencode/src/v2/session-event.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/opencode/test/session/messages-pagination.test.ts
  • packages/opencode/test/session/session-entry.test.ts
  • packages/opencode/test/session/session.test.ts
  • packages/sdk/openapi.json

Comment thread packages/opencode/src/session/compaction.ts Outdated
Comment thread packages/opencode/src/session/message-v2.ts Outdated
Comment thread packages/opencode/test/session/compaction.test.ts Outdated
Comment thread packages/opencode/test/session/messages-pagination.test.ts Outdated
Comment thread packages/sdk/openapi.json
Comment thread packages/sdk/openapi.json Outdated
@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch from f88df74 to c021977 Compare April 22, 2026 14:01
@Astro-Han

Copy link
Copy Markdown
Owner Author

Code Review Comments

1. packages/opencode/src/session/compaction.ts:35 — Constants lack documentation

The constants DEFAULT_TAIL_TURNS, MIN_TAIL_TOKENS, and MAX_TAIL_TOKENS define defaults for the retained tail behavior but lack documentation explaining why these specific values were chosen. Consider adding brief comments explaining the rationale—for example, why 2 turns is the default, and how the 2,000–8,000 token range balances typical context windows.

2. packages/opencode/src/v2/session-event.ts:402 — Type mismatch in Retried.create

The Retried.create factory method signature declares error: RetryError, but the schema accepts RetryEventError (union of RetryError and legacy string). This means create cannot directly construct events from legacy string errors, even though Schema.decodeUnknownSync handles them correctly when deserializing. The AssistantRetry.fromEvent helper normalizes both cases, so callers constructing events directly should use that pattern. Consider aligning the create signature to match the schema or documenting the limitation.

3. packages/opencode/src/session/compaction.ts:120 — Token estimation approximation

The estimate function uses JSON.stringify(msgs) to approximate token count. This approach counts JSON syntax characters (quotes, brackets, commas) as tokens, which inflates the estimate compared to actual model tokenization. For compaction budgeting this is acceptable as a rough heuristic, but consider documenting this approximation or using a model-specific tokenizer if precision matters for edge cases near budget boundaries.

4. packages/opencode/test/session/compaction.test.ts:837 — Edge case test value

The test uses preserve_recent_tokens: 1 which means the tail budget is just 1 token. While valid, this is an extreme edge case. Consider whether a slightly larger value (e.g., 10 or 50) would more realistically test the budget exceeded scenario without depending on JSON serialization quirks that might inflate estimates.

5. packages/opencode/src/session/message-v2.ts:944 — Two-stage fallback logic

The fallback scans result (chronological order) for any compaction part with tail_start_id. Since the forward iteration already captures the newest compaction's marker via tailStartID ??= compactionPart?.tail_start_id, this fallback only runs for truly pending compactions without a completed summary. The comment explains this, but the two-stage logic (forward capture + reverse fallback) could be clearer with a brief note explaining why pending compactions require the reverse scan (they lack completed summaries in the completed set).

Comment thread packages/opencode/src/session/compaction.ts

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Overall the implementation is solid and the changes align well with the #92 session sync requirements. Below are a few minor nitpicks and documentation suggestions.

Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/session/compaction.ts

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Additional nitpicks.

Comment thread packages/opencode/src/v2/session-event.ts
Comment thread packages/opencode/src/session/message-v2.ts

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Test nitpicks.

Comment thread packages/opencode/test/session/compaction.test.ts
Comment thread packages/opencode/src/v2/session-event.ts
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/test/session/messages-pagination.test.ts Outdated
Comment thread packages/opencode/test/session/compaction.test.ts

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Code Review Summary

This PR introduces significant changes to session compaction behavior with a new tail retention mechanism and retry event tracking. Overall the implementation is solid, but there are several issues requiring attention.

P1 Issues (Suggest Fixing)

  1. Prune semantics change (compaction.ts:133) - The shift from prune === false to prune !== true silently changes default behavior for existing users without migration guidance.

  2. Silent tail_turns edge case (compaction.ts:158) - Negative/zero values silently disable tail retention without logging.

  3. Compaction part position assumption (compaction.ts:267) - Logic assumes compaction part is always at array end, may fail under race conditions.

  4. filterCompacted iteration complexity (message-v2.ts:936) - The interaction between tail markers and compaction logic is subtle; needs explicit edge case tests.

  5. z.lazy missing explanation (session.ts:261) - Circular reference fix lacks comment explaining necessity.

  6. callID assumption unverified (session-entry.ts:169) - Tool routing assumes callID always exists; needs schema verification.

  7. Config description lacks migration note (config.ts:258) - Users won't know behavior changed from default-enabled to opt-in.

P2 Issues (Record Only)

  • Magic constants need rationale documentation
  • Budget overflow may leave insufficient tail
  • Re-compaction boundary update potential race
  • Schema description style inconsistency
  • RetryError normalization assumption questionable
  • Test helper verbose type checks
  • Test .live annotation possibly unnecessary
  • Test title style inconsistency

P3 Issues (Optional)

  • Fallback logic duplication
  • RetryError optional fields lack documentation

Recommendation

Address P1 issues before merge, particularly:

  1. Add migration note/changelog for prune behavior change
  2. Add logging for edge case configurations
  3. Verify callID schema guarantees or add fallback handling
  4. Add comment explaining z.lazy necessity

@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch from 6481ffe to f486dd1 Compare April 22, 2026 15:27

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Nitpick review. Logic works, but a few places look worth tightening. P2 items could bite on upgrade; P3 items are clarity/dead-code.

Comment thread packages/opencode/src/session/compaction.ts Outdated
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/src/v2/session-event.ts Outdated
Comment thread packages/opencode/src/v2/session-entry.ts Outdated
Comment thread packages/opencode/src/session/message-v2.ts Outdated
Comment thread packages/opencode/src/session/compaction.ts Outdated
Comment thread packages/opencode/src/session/compaction.ts
Comment thread packages/opencode/test/session/session.test.ts
@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch 2 times, most recently from 60eb047 to d982d71 Compare April 22, 2026 16:17

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/session/overflow.ts`:
- Around line 18-19: The current overflow check computes usable =
(input.model.limit.input ?? context) - reserved which can be negative when
input.model.limit.input is 0, causing count >= usable to always be true; update
the calculation in overflow.ts to clamp usable to a minimum of 0 (e.g., use
Math.max(0, ...)) so usable = Math.max(0, (input.model.limit.input ?? context) -
reserved) and then perform the existing comparison with count, referencing the
variables usable, input.model.limit.input, context, reserved and the return that
checks count >= usable.

In `@packages/opencode/src/v2/session-event.ts`:
- Around line 399-406: Change Retried.create to accept an optional attempt so
legacy callers can omit it: update the input type from BaseInput & { attempt:
number; error: RetryError | string } to BaseInput & { attempt?: number; error:
RetryError | string }, and in the factory set attempt to a safe default (e.g.
attempt: input.attempt ?? 0) when constructing the new Retried instance; update
references in the Retried.create implementation accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2a42a16d-4be5-4ddd-883e-14c6bc35f486

📥 Commits

Reviewing files that changed from the base of the PR and between f88df74 and d982d71.

⛔ Files ignored due to path filters (1)
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (12)
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/message-v2.ts
  • packages/opencode/src/session/overflow.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/src/v2/session-entry.ts
  • packages/opencode/src/v2/session-event.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/opencode/test/session/messages-pagination.test.ts
  • packages/opencode/test/session/session-entry.test.ts
  • packages/opencode/test/session/session.test.ts
  • packages/sdk/openapi.json

Comment thread packages/opencode/src/session/overflow.ts Outdated
Comment thread packages/opencode/src/v2/session-event.ts Outdated
@Astro-Han Astro-Han force-pushed the codex/refactor-i92-session-sync branch from d982d71 to 4089f23 Compare April 22, 2026 16:39

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/opencode/src/session/compaction.ts (1)

269-380: ⚠️ Potential issue | 🟠 Major

Persist tail_start_id before the summary starts.

filterCompacted() now honors tail_start_id for pending compactions, but this code only writes the marker after processor.process() finishes. While the summary is still streaming or retrying, the compaction part in storage has no boundary yet, so readers will keep showing the old head instead of the retained tail. Please persist the selected boundary before starting the processor, then clear or revert it if compaction ultimately fails.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/src/session/compaction.ts` around lines 269 - 380, Move the
logic that persists the tail_start_id boundary to occur before
processor.process() is called instead of after. Specifically, before invoking
processor.process(), check if compactionPart exists and if
compactionPart.tail_start_id differs from selected.tail_start_id, then call
session.updatePart() to persist the boundary. After this update, add revert
logic in the error handling section where result === "compact" to undo this
change by either clearing or reverting the tail_start_id on the compactionPart,
ensuring the storage boundary stays in sync with actual compaction progress.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/test/session/compaction.test.ts`:
- Around line 685-727: Replace the ad-hoc test harness in the "compacts old
completed tool output when prune is explicitly enabled" test (which uses
Instance.provide, runtime(...), rt.runPromise and manual disposal) with the
existing testEffect/it.live harness: convert the test(...) into it.live(...)
from the file's testEffect(env) setup, use provideTmpdirInstance(...) instead of
Instance.provide(...) to supply the tmpdir and Instance, and run
SessionCompaction.Service.use((compact) => compact.prune({ sessionID: session.id
})) within the effect runtime provided by it.live (removing manual runtime,
cfg/prune wiring and explicit rt.dispose). Keep assertions the same and ensure
you still create the Part via svc.updatePart and then fetch svc.messages to
assert updated.state.time.compacted is set.

In `@packages/opencode/test/session/messages-pagination.test.ts`:
- Around line 718-842: The three new it.live tests use Effect.promise(async ()
=> ...) and call svc directly, which spawns separate runtimes; change each to
use Effect.gen(function* () { ... }) and yield the shared service from
SessionNs.Service (e.g., const svc = yield* SessionNs.Service) so the test
harness manages lifecycle; replace the async svc calls with yielded usage inside
the generator and remove the Promise wrapper, keeping the same test logic and
references to svc, MessageV2.filterCompacted,
addUser/addAssistant/addAssistant(summary), svc.updatePart and svc.remove.

---

Outside diff comments:
In `@packages/opencode/src/session/compaction.ts`:
- Around line 269-380: Move the logic that persists the tail_start_id boundary
to occur before processor.process() is called instead of after. Specifically,
before invoking processor.process(), check if compactionPart exists and if
compactionPart.tail_start_id differs from selected.tail_start_id, then call
session.updatePart() to persist the boundary. After this update, add revert
logic in the error handling section where result === "compact" to undo this
change by either clearing or reverting the tail_start_id on the compactionPart,
ensuring the storage boundary stays in sync with actual compaction progress.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f035580d-5a96-4f8c-847d-d50da3d6baf6

📥 Commits

Reviewing files that changed from the base of the PR and between d982d71 and 4089f23.

⛔ Files ignored due to path filters (1)
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
📒 Files selected for processing (12)
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/message-v2.ts
  • packages/opencode/src/session/overflow.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/src/v2/session-entry.ts
  • packages/opencode/src/v2/session-event.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/opencode/test/session/messages-pagination.test.ts
  • packages/opencode/test/session/session-entry.test.ts
  • packages/opencode/test/session/session.test.ts
  • packages/sdk/openapi.json

Comment thread packages/opencode/test/session/compaction.test.ts Outdated
Comment thread packages/opencode/test/session/messages-pagination.test.ts
@Astro-Han

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Labels

enhancement New feature or request P2 Medium priority upstream Tracked upstream or vendor behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant