Skip to content

Comments

Device/stealth#20

Merged
riatzukiza merged 17 commits intostagingfrom
device/stealth
Nov 19, 2025
Merged

Device/stealth#20
riatzukiza merged 17 commits intostagingfrom
device/stealth

Conversation

@riatzukiza
Copy link
Collaborator

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added conversation compaction to automatically summarize and condense long chat histories, improving performance on extended conversations.
    • New configuration options to control compaction behavior including enablement, token limits, and message thresholds.
  • Chores

    • Updated documentation and test infrastructure to use pnpm.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds a Codex-driven conversation compaction pipeline and integrates it into request transformation, fetch handling, response finalization, and session storage; introduces fork-aware session/prompt keys, cloning and input-item utilities, new prompts/constants, CONFIG/type extensions, and comprehensive tests. (≤50 words)

Changes

Cohort / File(s) Summary
Compaction core
lib/compaction/codex-compaction.ts, lib/compaction/compaction-executor.ts
New compaction utilities and executor: token approximation, compaction command detection, conversation serialization/truncation, prompt-item builders, system-message collection, summary message creation, tail extraction, and finalizeCompactionResponse which rewrites responses, injects codex_compaction metadata, and optionally applies session updates.
Request pipeline
lib/request/request-transformer.ts, lib/request/fetch-helpers.ts, lib/request/codex-fetcher.ts
Propagates pluginConfig and compaction context through transforms/fetch; transformRequestBody / transformRequestForCodex signatures/returns now include optional compactionDecision; fetch flow may finalize compaction responses and records the handled response for session recording.
Session management & constants
lib/session/session-manager.ts, lib/constants.ts
Fork-aware session and prompt-cache key derivation; new SESSION_CONFIG, CONVERSATION_CONFIG, PERFORMANCE_CONFIG; SessionManager adds applyCompactionSummary and applyCompactedHistory to store/reapply summarized conversation state per fork.
Config & types
lib/config.ts, lib/types.ts
PluginConfig defaults extended and types updated (enableCodexCompaction, autoCompactMinMessages, autoCompactTokenLimit); SessionState adds compactionBaseSystem and compactionSummaryItem.
Prompts & utils
lib/prompts/codex-compaction.ts, lib/prompts/codex.ts, lib/utils/input-item-utils.ts, lib/utils/clone.ts
New CODEX_COMPACTION_PROMPT and CODEX_SUMMARY_PREFIX; input-item helpers for text extraction, role checks, turn counting; centralized deepClone, cloneInputItems, cloneInputItem; prompt module import/layout refinements.
Compaction tests
test/codex-compaction.test.ts, test/compaction-executor.test.ts, test/codex-fetcher.test.ts, test/fetch-helpers.test.ts
Tests validating compaction helpers, finalizeCompactionResponse behavior (auto vs command), pluginConfig/compactionDecision propagation, and edge cases.
Transformer & integration tests
test/request-transformer*.test.ts, test/request-transformer.test.ts, test/request-transformer-tools-normalization.test.ts
Tests updated to new transformRequestBody return shape; local wrappers added to examine result.body; compaction paths exercised.
Session tests
test/session-manager.test.ts, test/session-cache-evictions.test.ts
Tests updated for fork-scoped session behavior, per-fork compaction propagation, and use of SESSION_CONFIG.
Cache & misc utilities
lib/cache/*, lib/utils/*, lib/logger.ts, lib/cache/cache-metrics.ts
Minor formatting/import changes, added getMetrics in cache metrics, test-environment guard in logger, and other small refactors.
Docs & test infra
test/README.md, many test/* files
README switched to pnpm; many tests normalized (quoting, imports) and updated mocks/expectations to match new APIs and pluginConfig propagation.

Sequence Diagram

sequenceDiagram
    participant User
    participant Transform as Transform Layer
    participant Compaction as Compaction Workflow
    participant Codex as Codex API
    participant ResHandler as Response Handler
    participant Session as Session Manager

    User->>Transform: request (input items + pluginConfig)
    alt compaction enabled or command detected
        Transform->>Compaction: detect trigger, serialize conversation
        Compaction-->>Transform: compactionDecision + prompt items
        Transform->>Codex: send compaction prompt items
    else
        Transform->>Codex: send normal prompt items
    end

    Codex-->>ResHandler: response payload
    alt compactionDecision present
        ResHandler->>Compaction: extract assistant text -> create summary
        Compaction-->>ResHandler: finalized summary + codex_compaction metadata
        ResHandler->>Session: applyCompactionSummary(context, preservedSystem, summary)
        ResHandler-->>User: return updated payload (status/headers preserved)
    else
        ResHandler-->>User: return original payload
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Blockers / high-priority review points:

  • Ensure compactionDecision flows reliably from transform → fetch → finalize (not dropped or overwritten).
  • Verify callers that consume transformRequestBody / transformRequestForCodex handle the new return shape and optional compactionDecision.
  • Audit finalizeCompactionResponse rewriting to guarantee headers, status, non-assistant payload fields, and metadata are preserved and correct.
  • Confirm SessionManager.applyCompactionSummary() and applyCompactedHistory() are fork-scoped and idempotent to avoid cross-fork leakage.
  • Review token-estimation heuristic (approximateTokenCount) and auto-trigger thresholds for correctness.

Files/areas to inspect closely:

  • lib/request/request-transformer.ts
  • lib/request/fetch-helpers.ts
  • lib/request/codex-fetcher.ts
  • lib/session/session-manager.ts
  • lib/compaction/* (codex-compaction.ts, compaction-executor.ts)
  • Tests adapting to transform return-shape (test/request-transformer*.test.ts, test/fetch-helpers.test.ts)

Poem

A long thread whittled down to light,
Codex listens, folds the night—
Preserved systems, summaries spun,
Forks kept tidy, histories one—
Small notes hold what was begun. ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, making it difficult to understand intent and scope. Add a description explaining the purpose of the compaction feature, key changes across modules, and any breaking changes or migration steps for users.
Docstring Coverage ⚠️ Warning Docstring coverage is 47.92% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Device/stealth' is vague and does not clearly describe the main changes in this extensive pull request about Codex compaction functionality. Use a more descriptive title that conveys the primary change, such as 'Add Codex conversation compaction workflow' or 'Implement automatic conversation summarization via Codex'.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch device/stealth

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

- Create shared clone utility (lib/utils/clone.ts) to eliminate 3+ duplicate implementations
- Create InputItemUtils (lib/utils/input-item-utils.ts) for centralized text extraction
- Centralize magic numbers in constants with SESSION_CONFIG, CONVERSATION_CONFIG, PERFORMANCE_CONFIG
- Add ESLint cognitive complexity rules (max: 15) to prevent future issues
- Refactor large functions to use shared utilities, reducing complexity
- Update all modules to use centralized utilities and constants
- Remove dead code and unused imports
- All 123 tests pass, no regressions introduced

Code quality improved from B+ to A- with better maintainability.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

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

⚠️ Outside diff range comments (1)
test/plugin-config.test.ts (1)

90-141: Blocker: duplicated “file read errors” tests, stray assertions, and outdated expectations

This section has multiple problems that will break CI and/or fail assertions:

  1. Stray code outside any test (syntax error / CI blocker)
    Lines 124–126:

    • expect(consoleSpy).toHaveBeenCalled();
    • consoleSpy.mockRestore();
    • });
      These appear after the second it('should handle file read errors gracefully', ...) block and reference consoleSpy out of scope, leaving braces unbalanced. This matches the esbuild “Unexpected '}'” failure.
  2. Duplicate test names for file read errors
    There are two separate it('should handle file read errors gracefully', ...) blocks (lines 106–122 and 128–140) doing essentially the same thing with different error messages. That’s confusing and makes maintenance harder.

  3. Outdated expected config shape in the last test
    The last test (lines 128–140) still asserts:

    expect(config).toEqual({ codexMode: true, enablePromptCaching: true });

    but loadPluginConfig now returns default config including enableCodexCompaction and autoCompactMinMessages, so this will fail.

A minimal concrete fix would be:

  • Keep a single “file read errors gracefully” test with the new default config shape.
  • Move the expect(consoleSpy).toHaveBeenCalled() inside that test.
  • Remove the stray lines and the outdated duplicate test.

For example:

-		it('should handle invalid JSON gracefully', () => {
-      ...
-      expect(config).toEqual({
-        codexMode: true,
-        enablePromptCaching: true,
-        enableCodexCompaction: true,
-        autoCompactMinMessages: 8,
-      });
-      consoleSpy.mockRestore();
-    });
-
-    it('should handle file read errors gracefully', () => {
-      mockExistsSync.mockReturnValue(true);
-      mockReadFileSync.mockImplementation(() => {
-        throw new Error('Permission denied');
-      });
-
-      const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
-      const config = loadPluginConfig();
-
-      expect(config).toEqual({ codexMode: true, enablePromptCaching: true });
-      expect(consoleSpy).toHaveBeenCalled();
-      consoleSpy.mockRestore();
-    });
+    it('should handle invalid JSON gracefully', () => {
+      mockExistsSync.mockReturnValue(true);
+      mockReadFileSync.mockReturnValue('invalid json');
+
+      const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
+      const config = loadPluginConfig();
+
+      expect(config).toEqual({
+        codexMode: true,
+        enablePromptCaching: true,
+        enableCodexCompaction: true,
+        autoCompactMinMessages: 8,
+      });
+      expect(consoleSpy).toHaveBeenCalled();
+      consoleSpy.mockRestore();
+    });
+
+    it('should handle file read errors gracefully', () => {
+      mockExistsSync.mockReturnValue(true);
+      mockReadFileSync.mockImplementation(() => {
+        throw new Error('Permission denied');
+      });
+
+      const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
+      const config = loadPluginConfig();
+
+      expect(config).toEqual({
+        codexMode: true,
+        enablePromptCaching: true,
+        enableCodexCompaction: true,
+        autoCompactMinMessages: 8,
+      });
+      expect(consoleSpy).toHaveBeenCalled();
+      consoleSpy.mockRestore();
+    });

(Adjust the exact diff to match which of the two read-error variants you want to keep, but the key points are: remove stray lines, avoid duplicate it names, and update expectations to the extended PluginConfig defaults.)

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0adf4 and f56e506.

⛔ Files ignored due to path filters (14)
  • .github/workflows/main-merge-guard.yml is excluded by none and included by none
  • .github/workflows/opencode.yml is excluded by none and included by none
  • .github/workflows/pr-auto-base.yml is excluded by none and included by none
  • README.md is excluded by none and included by none
  • docs/configuration.md is excluded by none and included by none
  • docs/getting-started.md is excluded by none and included by none
  • docs/notes/2025.11.14.20.26.19.md is excluded by none and included by none
  • index.ts is excluded by none and included by none
  • release-analysis.json is excluded by none and included by none
  • spec/auto-compaction-summary.md is excluded by none and included by none
  • spec/codex-compaction.md is excluded by none and included by none
  • spec/issue-11-docs-package.md is excluded by none and included by none
  • spec/issue-4-prompt-cache-key.md is excluded by none and included by none
  • spec/open-issues-check.md is excluded by none and included by none
📒 Files selected for processing (17)
  • lib/compaction/codex-compaction.ts (1 hunks)
  • lib/compaction/compaction-executor.ts (1 hunks)
  • lib/config.ts (1 hunks)
  • lib/prompts/codex-compaction.ts (1 hunks)
  • lib/request/codex-fetcher.ts (4 hunks)
  • lib/request/fetch-helpers.ts (4 hunks)
  • lib/request/request-transformer.ts (10 hunks)
  • lib/session/session-manager.ts (2 hunks)
  • lib/types.ts (2 hunks)
  • test/README.md (1 hunks)
  • test/codex-compaction.test.ts (1 hunks)
  • test/codex-fetcher.test.ts (2 hunks)
  • test/fetch-helpers.test.ts (1 hunks)
  • test/plugin-config.test.ts (4 hunks)
  • test/request-transformer-tools-normalization.test.ts (5 hunks)
  • test/request-transformer.test.ts (58 hunks)
  • test/session-manager.test.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (12)
test/request-transformer-tools-normalization.test.ts (2)
lib/types.ts (2)
  • RequestBody (147-169)
  • UserConfig (40-47)
lib/request/request-transformer.ts (1)
  • transformRequestBody (1064-1236)
test/codex-compaction.test.ts (2)
lib/types.ts (1)
  • InputItem (136-142)
lib/compaction/codex-compaction.ts (6)
  • detectCompactionCommand (43-59)
  • serializeConversation (61-91)
  • buildCompactionPromptItems (93-105)
  • collectSystemMessages (107-112)
  • createSummaryMessage (114-124)
  • approximateTokenCount (32-41)
test/plugin-config.test.ts (1)
lib/config.ts (1)
  • loadPluginConfig (25-47)
lib/compaction/compaction-executor.ts (3)
lib/types.ts (2)
  • InputItem (136-142)
  • SessionContext (199-205)
lib/session/session-manager.ts (1)
  • SessionManager (123-402)
lib/compaction/codex-compaction.ts (1)
  • createSummaryMessage (114-124)
lib/session/session-manager.ts (1)
lib/types.ts (3)
  • InputItem (136-142)
  • SessionContext (199-205)
  • RequestBody (147-169)
test/request-transformer.test.ts (2)
lib/types.ts (3)
  • RequestBody (147-169)
  • UserConfig (40-47)
  • InputItem (136-142)
lib/request/request-transformer.ts (2)
  • transformRequestBody (1064-1236)
  • filterOpenCodeSystemPrompts (554-665)
lib/request/request-transformer.ts (4)
lib/types.ts (4)
  • InputItem (136-142)
  • RequestBody (147-169)
  • UserConfig (40-47)
  • SessionContext (199-205)
lib/compaction/compaction-executor.ts (1)
  • CompactionDecision (5-15)
lib/compaction/codex-compaction.ts (4)
  • approximateTokenCount (32-41)
  • serializeConversation (61-91)
  • buildCompactionPromptItems (93-105)
  • collectSystemMessages (107-112)
lib/logger.ts (1)
  • logWarn (75-77)
lib/request/codex-fetcher.ts (3)
lib/types.ts (1)
  • PluginConfig (6-35)
lib/request/fetch-helpers.ts (1)
  • handleSuccessResponse (337-355)
lib/compaction/compaction-executor.ts (1)
  • finalizeCompactionResponse (24-67)
test/session-manager.test.ts (1)
lib/types.ts (2)
  • SessionContext (199-205)
  • InputItem (136-142)
lib/compaction/codex-compaction.ts (2)
lib/types.ts (1)
  • InputItem (136-142)
lib/prompts/codex-compaction.ts (2)
  • CODEX_COMPACTION_PROMPT (1-9)
  • CODEX_SUMMARY_PREFIX (11-11)
test/fetch-helpers.test.ts (1)
lib/request/fetch-helpers.ts (1)
  • transformRequestForCodex (122-213)
lib/request/fetch-helpers.ts (6)
lib/types.ts (4)
  • InputItem (136-142)
  • PluginConfig (6-35)
  • RequestBody (147-169)
  • SessionContext (199-205)
lib/compaction/compaction-executor.ts (1)
  • CompactionDecision (5-15)
lib/compaction/codex-compaction.ts (1)
  • detectCompactionCommand (43-59)
lib/request/request-transformer.ts (1)
  • transformRequestBody (1064-1236)
lib/logger.ts (1)
  • logRequest (47-64)
lib/constants.ts (1)
  • LOG_STAGES (56-61)
🪛 GitHub Actions: CI
test/plugin-config.test.ts

[error] 213-213: Transform failed: Unexpected '}' detected by esbuild during transformation at line 213.

🔇 Additional comments (12)
lib/types.ts (1)

20-35: Compaction config and session fields look structurally sound

The new compaction-related fields on PluginConfig and SessionState are optional, backward compatible, and line up with how SessionManager/compaction are using them. No issues from a typing or lifecycle standpoint.

Also applies to: 183-194

lib/config.ts (1)

12-17: Confirm default-on compaction behavior and thresholds

Turning enableCodexCompaction on by default with autoCompactMinMessages: 8 changes existing behavior for all users. Please confirm this default-on rollout and threshold are intentional and acceptable from a UX/compat perspective (vs. starting disabled or with a higher floor).

lib/prompts/codex-compaction.ts (1)

1-11: Compaction prompts are well-scoped and safe

The new CODEX_COMPACTION_PROMPT and CODEX_SUMMARY_PREFIX constants are simple string exports with clear, constrained instructions. No technical issues here.

test/codex-fetcher.test.ts (1)

74-93: Good coverage of pluginConfig propagation into Codex fetch path

Adding pluginConfig to baseDeps and asserting it’s forwarded into transformRequestForCodex exercises the new dependency surface well. The shape (codexMode, enablePromptCaching, enableCodexCompaction, autoCompactMinMessages) matches the production PluginConfig expectations.

Also applies to: 107-120

test/session-manager.test.ts (1)

3-3: Compacted history test matches SessionManager behavior

The new test around applyCompactionSummary / applyCompactedHistory correctly captures the expected merged input layout (base system, summary, then latest user slice). Importing InputItem for the system message keeps the test type-safe. No issues here.

Also applies to: 180-201

lib/request/codex-fetcher.ts (1)

8-10: Compaction finalization wiring in codex-fetcher looks correct; verify all deps supply pluginConfig

The new flow—passing pluginConfig into transformRequestForCodex, then post-processing via finalizeCompactionResponse when transformation.compactionDecision is present—fits cleanly into the existing pipeline and keeps non-compaction behavior unchanged. Using the post-handleSuccessResponse handledResponse for both compaction finalization and recordSessionResponseFromHandledResponse is consistent with the compaction executor’s expectations.

Please double-check that every createCodexFetcher(...) call site has been updated to pass a pluginConfig object, since it’s now a required dependency in CodexFetcherDeps.

Also applies to: 21-30, 32-55, 86-101

test/fetch-helpers.test.ts (1)

253-283: Compaction options wiring in transformRequestForCodex test looks correct

The test now correctly mocks transformRequestBody to return { body }, passes pluginConfig, and verifies that optionsArg.compaction.originalInput is present and array-shaped before asserting the transformed body/updated init. This matches the new transformRequestForCodex contract and compaction integration.

Note: the main CI blocker in this PR is in test/plugin-config.test.ts (unbalanced braces / duplicate tests); see that file’s comments for details.

test/codex-compaction.test.ts (1)

1-67: New codex compaction helper tests cover the core behaviors well

These tests align with the helper implementations (command detection, transcript truncation, prompt structure, system/developer extraction, summary prefixing, and token heuristic). They give good coverage of the intended control flow without over-specifying internals.

lib/session/session-manager.ts (1)

34-39: Session compaction state handling and history rebuilding look consistent and safe

  • cloneInput and cloneValue centralize deep cloning, so SessionState doesn’t hold references to mutable request objects.
  • extractLatestUserSlice correctly finds the last user message and returns a cloned tail slice, or an empty array when there’s no user content; this matches the intent of “latest user-originated slice.”
  • applyCompactionSummary stores compactionBaseSystem and a synthesized compactionSummaryItem on the session, and applyCompactedHistory rebuilds body.input as [baseSystem..., summary, latestUserSlice...], guarded by context.enabled, opts?.skip, and presence of both base and summary.

Overall this is a clean, side-effect-safe implementation of the compaction history flow.

Also applies to: 47-58, 273-303

lib/compaction/compaction-executor.ts (1)

69-94: Assistant text extraction and rewrite logic is sound.

Scanning payload.output for the first assistant output_text block and rewriting only that entry is a reasonable, minimal intervention and degrades gracefully when the expected structure isn’t present (no assistant text → no rewrite, only metadata added).

lib/request/request-transformer.ts (1)

6-12: New compaction imports line up with usage.

The imports of approximateTokenCount, buildCompactionPromptItems, collectSystemMessages, serializeConversation, and CompactionDecision match how they’re used later in the file; no issues here.

lib/compaction/codex-compaction.ts (1)

32-41: Token estimation, command detection, and serialization are coherent and match usage.

approximateTokenCount and serializeConversation provide simple, cheap heuristics that are good enough for compaction triggering, and detectCompactionCommand correctly scopes to the last non‑empty user message with well‑defined triggers. Building the compaction prompt as [developer(CODEX_COMPACTION_PROMPT), user(transcript)] aligns with how the executor and transformer expect to work.

Also applies to: 43-59, 61-91, 93-105

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

♻️ Duplicate comments (3)
lib/request/fetch-helpers.ts (1)

140-155: Compaction “enabled” flag does not fully disable compaction reuse.

Even when pluginConfig.enableCodexCompaction === false, applyCompactedHistory will still run (because it’s only skipped when manualCommand is present), so previously stored compaction summaries can still be applied to new requests. That’s surprising for a flag named enableCodexCompaction and makes it impossible to fully turn off compaction behavior once summaries exist.

To make the flag authoritative, gate history application on compactionEnabled as well:

-		const sessionContext = sessionManager?.getContext(body);
-		if (!manualCommand) {
-			sessionManager?.applyCompactedHistory?.(body, sessionContext);
-		}
+		const sessionContext = sessionManager?.getContext(body);
+		if (compactionEnabled && !manualCommand) {
+			sessionManager?.applyCompactedHistory?.(body, sessionContext);
+		}
lib/request/request-transformer.ts (1)

896-905: Fallback hash computation can throw on non‑JSON‑serializable metadata.

computeFallbackHashForBody feeds body.metadata and a slice of body.input through stableStringify, which ultimately calls JSON.stringify on primitives. If callers ever pass non‑JSON‑serializable values (e.g., BigInt, or cyclic objects when transformRequestBody is used directly in-process rather than via JSON), this will throw and abort the transform, surfacing as a failed request.

To harden this, wrap the hashing in a try/catch and fall back to a simpler seed (e.g., just the model string) on error:

-function computeFallbackHashForBody(body: RequestBody): string {
-	const inputSlice = Array.isArray(body.input) ? body.input.slice(0, 3) : undefined;
-	const seed = stableStringify({
-		model: typeof body.model === "string" ? body.model : undefined,
-		metadata: body.metadata,
-		input: inputSlice,
-	});
-	return createHash("sha1").update(seed).digest("hex").slice(0, 12);
-}
+function computeFallbackHashForBody(body: RequestBody): string {
+	try {
+		const inputSlice = Array.isArray(body.input) ? body.input.slice(0, 3) : undefined;
+		const seed = stableStringify({
+			model: typeof body.model === "string" ? body.model : undefined,
+			metadata: body.metadata,
+			input: inputSlice,
+		});
+		return createHash("sha1").update(seed).digest("hex").slice(0, 12);
+	} catch {
+		const model = typeof body.model === "string" ? body.model : "unknown";
+		return createHash("sha1").update(model).digest("hex").slice(0, 12);
+	}
+}

Also applies to: 939-951

lib/compaction/codex-compaction.ts (1)

108-129: Tail extraction still treats any last role: "user" as the start; be aware of summary messages.

extractTailAfterSummary returns a cloned slice starting at the last role: "user" message, regardless of whether that item is a real user turn or a synthetic summary (e.g., from createSummaryMessage, which also uses role: "user"). If you ever feed conversations that already contain the summary message through this helper, the tail will start at the summary itself rather than “after summary,” which may not match your intended semantics.

Not urgent today, but future-proofing could look like marking summary items explicitly (e.g., a flag on InputItem) and teaching extractTailAfterSummary to skip those when searching for the last “real” user turn.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f56e506 and 8757e76.

⛔ Files ignored due to path filters (6)
  • .gitignore is excluded by none and included by none
  • biome.json is excluded by none and included by none
  • docs/code-cleanup-summary.md is excluded by none and included by none
  • docs/code-quality-analysis-report.md is excluded by none and included by none
  • spec/codex-compaction.md is excluded by none and included by none
  • vitest.config.ts is excluded by none and included by none
📒 Files selected for processing (12)
  • lib/compaction/codex-compaction.ts (1 hunks)
  • lib/constants.ts (1 hunks)
  • lib/logger.ts (2 hunks)
  • lib/request/fetch-helpers.ts (4 hunks)
  • lib/request/request-transformer.ts (14 hunks)
  • lib/session/session-manager.ts (10 hunks)
  • lib/utils/clone.ts (1 hunks)
  • lib/utils/input-item-utils.ts (1 hunks)
  • test/codex-compaction.test.ts (1 hunks)
  • test/compaction-executor.test.ts (1 hunks)
  • test/plugin-config.test.ts (5 hunks)
  • test/session-manager.test.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
test/codex-compaction.test.ts (2)
lib/types.ts (1)
  • InputItem (136-142)
lib/compaction/codex-compaction.ts (7)
  • detectCompactionCommand (37-53)
  • serializeConversation (55-85)
  • buildCompactionPromptItems (87-99)
  • collectSystemMessages (101-106)
  • createSummaryMessage (108-118)
  • approximateTokenCount (26-35)
  • extractTailAfterSummary (120-130)
test/compaction-executor.test.ts (3)
lib/compaction/compaction-executor.ts (2)
  • CompactionDecision (5-15)
  • finalizeCompactionResponse (24-67)
lib/types.ts (1)
  • SessionContext (199-205)
lib/prompts/codex-compaction.ts (1)
  • CODEX_SUMMARY_PREFIX (11-11)
test/plugin-config.test.ts (1)
lib/config.ts (1)
  • loadPluginConfig (25-47)
test/session-manager.test.ts (3)
lib/types.ts (3)
  • RequestBody (147-169)
  • SessionContext (199-205)
  • InputItem (136-142)
lib/session/session-manager.ts (1)
  • SessionManager (147-430)
lib/constants.ts (1)
  • SESSION_CONFIG (78-83)
lib/request/fetch-helpers.ts (4)
lib/types.ts (4)
  • InputItem (136-142)
  • PluginConfig (6-35)
  • RequestBody (147-169)
  • SessionContext (199-205)
lib/compaction/compaction-executor.ts (1)
  • CompactionDecision (5-15)
lib/compaction/codex-compaction.ts (1)
  • detectCompactionCommand (37-53)
lib/request/request-transformer.ts (1)
  • transformRequestBody (980-1152)
lib/request/request-transformer.ts (6)
lib/utils/input-item-utils.ts (2)
  • extractTextFromItem (16-27)
  • countConversationTurns (115-117)
lib/types.ts (4)
  • InputItem (136-142)
  • RequestBody (147-169)
  • UserConfig (40-47)
  • SessionContext (199-205)
lib/compaction/compaction-executor.ts (1)
  • CompactionDecision (5-15)
lib/utils/clone.ts (1)
  • cloneInputItems (26-31)
lib/compaction/codex-compaction.ts (4)
  • approximateTokenCount (26-35)
  • serializeConversation (55-85)
  • buildCompactionPromptItems (87-99)
  • collectSystemMessages (101-106)
lib/logger.ts (1)
  • logWarn (76-78)
lib/compaction/codex-compaction.ts (4)
lib/types.ts (1)
  • InputItem (136-142)
lib/utils/input-item-utils.ts (3)
  • extractTextFromItem (16-27)
  • formatRole (43-46)
  • formatEntry (54-56)
lib/prompts/codex-compaction.ts (2)
  • CODEX_COMPACTION_PROMPT (1-9)
  • CODEX_SUMMARY_PREFIX (11-11)
lib/utils/clone.ts (1)
  • deepClone (13-19)
lib/session/session-manager.ts (4)
lib/types.ts (3)
  • InputItem (136-142)
  • RequestBody (147-169)
  • SessionContext (199-205)
lib/utils/input-item-utils.ts (1)
  • isUserMessage (72-74)
lib/utils/clone.ts (2)
  • cloneInputItems (26-31)
  • deepClone (13-19)
lib/constants.ts (1)
  • SESSION_CONFIG (78-83)
lib/utils/input-item-utils.ts (1)
lib/types.ts (1)
  • InputItem (136-142)
🪛 GitHub Actions: CI
test/session-manager.test.ts

[warning] 131-131: lint/style/useConst: FIXABLE - Use 'const' instead of 'let' when variable is never reassigned.


[warning] 147-147: lint/style/useConst: FIXABLE - Use 'const' instead of 'let' when variable is never reassigned.


[warning] 156-156: lint/style/useConst: FIXABLE - Use 'const' instead of 'let' when variable is never reassigned.


[warning] 176-176: lint/style/useConst: FIXABLE - Use 'const' instead of 'let' when variable is never reassigned.


[warning] 1-1: assist/source/organizeImports: The imports and exports are not sorted. Suggested fix: organize imports.

🔇 Additional comments (6)
lib/logger.ts (1)

11-11: Test-only suppression of non-error logs looks correct

The IS_TEST_ENV flag combined with the guard in fallback cleanly prevents non-error console noise in Vitest/NODE_ENV=test while still always surfacing errors. Public behavior outside tests is unchanged since the short-circuit requires both logging flags to be false.

Also applies to: 103-106

test/compaction-executor.test.ts (1)

1-134: finalizeCompactionResponse behavior is well exercised

The tests cover the key branches of finalizeCompactionResponse:

  • Auto mode: rewritten assistant output with the meta note + CODEX_SUMMARY_PREFIX, correct codex_compaction metadata, and SessionManager.applyCompactionSummary invocation.
  • Payloads without assistant output: preserved HTTP status, empty output, and sane metadata defaults.
  • Command mode: no auto note, still prefixed summary, and reason left undefined.

This matches the executor’s responsibilities and should guard against regressions in the compaction pipeline.

lib/constants.ts (1)

77-103: Session/performance constants are clear and align with SessionManager usage

The new SESSION_CONFIG, CONVERSATION_CONFIG, and PERFORMANCE_CONFIG constants give a clean, centralized place for TTL and capacity tuning. Their shapes and values match how SessionManager and the related tests consume them (idle eviction and max session count), which should make future adjustments straightforward.

test/session-manager.test.ts (1)

2-28: Fork-aware sessions and compaction history behavior are well covered

The new helper (BodyOptions + createBody) and tests validate the key SessionManager behaviors:

  • Standard sessions: conversation_id-based keys, prefix matching, cache key regeneration on divergent prefixes, cached token recording, metrics snapshot, and prompt_cache_key fallback/reuse all line up with the SessionManager implementation.
  • Fork-specific flows: creates fork-specific sessions with derived cache keys correctly asserts the conv-fork::fork::<forkId> behavior for both session reuse and prompt_cache_key propagation across turns.
  • Compaction integration: scopes compaction summaries per fork session and applies compacted history when summary stored accurately model how applyCompactionSummary and applyCompactedHistory should combine baseSystem, the stored summary, and the latest user tail, and verify that summaries are isolated per fork.
  • TTL/capacity: tests that use SESSION_CONFIG.IDLE_TTL_MS and SESSION_CONFIG.MAX_ENTRIES confirm that idle pruning and capacity enforcement respect the centralized constants.

From a correctness perspective, this suite gives good confidence in the new session/fork/compaction behavior.

Also applies to: 39-160, 161-219, 221-271

lib/session/session-manager.ts (1)

301-331: Compaction summary application path looks safe and self-contained.

applyCompactionSummary and applyCompactedHistory correctly guard on context?.enabled, avoid mutating the original arrays via cloneInputItems/deepClone, and fall back to a no-op when compaction state is absent. The extractLatestUserSlice heuristic (last user turn + tail) is simple but coherent with the idea of keeping only the latest user slice plus the persisted summary.

No blocking issues from this compaction/session wiring.

lib/utils/input-item-utils.ts (1)

16-116: InputItem utility set is coherent and matches expected shapes.

The shared helpers for text extraction, role classification, and turn counting line up with the InputItem shape and existing usage patterns (e.g., compaction and request-transform paths), and they correctly treat non-text/empty content as empty. Centralizing these avoids further duplication; no functional issues detected here.

Copy link
Collaborator Author

@riatzukiza riatzukiza left a comment

Choose a reason for hiding this comment

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

Simple plan

Copy link
Collaborator Author

@riatzukiza riatzukiza left a comment

Choose a reason for hiding this comment

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

$Thanks for the thorough review. Here is the plan:\n1. Consolidate the loadPluginConfig error-handling tests so there is a single file read errors spec that checks the current defaults (codexMode, enablePromptCaching, enableCodexCompaction, autoCompactMinMessages) and keeps the warning/spy assertions together.\n2. Guard sessionManager?.applyCompactedHistory under pluginConfig.enableCodexCompaction !== false so the flag can truly disable compaction reuse (it already skips when a manual command is present).\n3. Wrap computeFallbackHashForBody in a try/catch and fall back to hashing just the model name when JSON serialization fails, preventing crashes on atypical metadata.\n\nI will also verify the default-on compaction ship is intentional and keep the new defaults, then run the related tests before pushing an update.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (4)
lib/prompts/codex.ts (2)

49-155: Blocker: getCodexInstructions exceeds linted cognitive complexity and needs decomposition

The getCodexInstructions function (lines 49–155) has grown into a large, multi-branch routine (session cache, file cache, TTL logic, GitHub fetch, 304/200 handling, error fallback). The CI failure (noExcessiveCognitiveComplexity at Line 49) means this must be refactored before merge.

Consider splitting responsibilities into smaller helpers, e.g.:

  • A “fast path” helper that returns from session cache if present.
  • A file‑cache helper that:
    • Reads metadata, computes isCacheFresh, and either returns cached content or null plus (cachedETag, cachedTag, cacheFileExists).
  • A network fetch helper that:
    • Resolves latestTag,
    • Handles the 304 vs 200 branches,
    • Updates disk metadata and session cache, and
    • Applies the GitHub/bundled fallbacks.

Then have getCodexInstructions orchestrate those helpers at a higher level, keeping its own branching very shallow. This should bring complexity under the configured limit while making the error paths easier to reason about.


79-88: TTL rate‑limit behavior doesn’t update on 304 responses (more GitHub calls than intended)

The comment says “Only checks GitHub if cache is older than 15 minutes”, but with the current logic:

  • isCacheFresh is based on metadata.lastChecked loaded from disk.
  • lastChecked is only updated in the response.ok (200) branch where you rewrite the meta file (lines 118–132).
  • In the response.status === 304 && cacheFileExists branch (lines 112–116), you return cached file content but never bump lastChecked.

Once the TTL window has elapsed, if GitHub keeps returning 304, every subsequent call to getCodexInstructions will re-hit GitHub because cachedTimestamp never advances, undermining the intended rate‑limit protection.

To align behavior with the docstring and avoid unnecessary GitHub traffic, you should update the cache metadata (at least lastChecked, and probably tag/url) in the 304 path as well. One straightforward option is to share a small helper that writes the meta file (etag, tag, lastChecked, url) and call it from both the 200 and 304 branches.

Also applies to: 112-132

lib/request/codex-fetcher.ts (1)

44-113: Refactor codexFetch to satisfy cognitive complexity lint

The codexFetch function now handles auth refresh, request transformation, in-band Codex commands, fetch, error/success handling, compaction finalization, and session recording. CI is flagging this with noExcessiveCognitiveComplexity (17 > 15), and it’s also getting dense to reason about.

You can reduce complexity by extracting the response-handling branch into a helper, leaving codexFetch focused on auth + request building:

+type CodexTransformationResult = Awaited<ReturnType<typeof transformRequestForCodex>>;
+
+interface ProcessResponseOptions {
+  response: Response;
+  hasTools: boolean;
+  transformation?: CodexTransformationResult;
+  sessionManager: SessionManager;
+  sessionContext?: SessionContext;
+}
+
+async function processCodexResponse({
+  response,
+  hasTools,
+  transformation,
+  sessionManager,
+  sessionContext,
+}: ProcessResponseOptions): Promise<Response> {
+  if (!response.ok) {
+    return await handleErrorResponse(response);
+  }
+
+  let handledResponse = await handleSuccessResponse(response, hasTools);
+
+  if (transformation?.compactionDecision) {
+    handledResponse = await finalizeCompactionResponse({
+      response: handledResponse,
+      decision: transformation.compactionDecision,
+      sessionManager,
+      sessionContext,
+    });
+  }
+
+  await recordSessionResponseFromHandledResponse({
+    sessionManager,
+    sessionContext,
+    handledResponse,
+  });
+
+  return handledResponse;
+}
@@
-    const response = await fetch(url, { ...requestInit, headers });
+    const response = await fetch(url, { ...requestInit, headers });
@@
-    if (!response.ok) {
-      return await handleErrorResponse(response);
-    }
-
-    let handledResponse = await handleSuccessResponse(response, hasTools);
-
-    if (transformation?.compactionDecision) {
-      handledResponse = await finalizeCompactionResponse({
-        response: handledResponse,
-        decision: transformation.compactionDecision,
-        sessionManager,
-        sessionContext,
-      });
-    }
-
-    await recordSessionResponseFromHandledResponse({
-      sessionManager,
-      sessionContext,
-      handledResponse,
-    });
-
-    return handledResponse;
+    return await processCodexResponse({
+      response,
+      hasTools,
+      transformation,
+      sessionManager,
+      sessionContext,
+    });

You’ll need to import SessionContext and adjust types to match your exact transformRequestForCodex return type, but this pattern should drop complexity under the configured threshold.

lib/session/session-manager.ts (1)

155-196: Fix explicit any in host prompt_cache_key fallback (lint blocker)

getContext’s host-cache-key fallback currently uses (body as any), which CI flags with lint/suspicious/noExplicitAny and is easy to avoid given the RequestBody index signature.

Consider this adjustment:

-    const conversationId = extractConversationId(body);
-    const forkId = extractForkIdentifier(body);
-    if (!conversationId) {
-      // Fall back to host-provided prompt_cache_key if no metadata ID is available
-      const hostCacheKey = (body as any).prompt_cache_key || (body as any).promptCacheKey;
-      if (hostCacheKey && typeof hostCacheKey === "string") {
+    const conversationId = extractConversationId(body);
+    const forkId = extractForkIdentifier(body);
+    if (!conversationId) {
+      // Fall back to host-provided prompt_cache_key if no metadata ID is available
+      const bodyAny = body as Record<string, unknown>;
+      const hostCacheKey =
+        typeof body.prompt_cache_key === "string"
+          ? body.prompt_cache_key
+          : typeof bodyAny.promptCacheKey === "string"
+            ? (bodyAny.promptCacheKey as string)
+            : undefined;
+      if (hostCacheKey) {
         // Use the existing cache key as session identifier to maintain continuity

This removes explicit any while preserving the same behavior.

♻️ Duplicate comments (5)
test/request-transformer-tools-normalization.test.ts (1)

5-14: The options?: any typing issue was already flagged.

The past review comment correctly identified that options should be typed as TransformRequestOptions instead of any.

Additionally, the helper doesn't expose the sessionContext parameter that transformRequestBody accepts (see line 965 in lib/request/request-transformer.ts). While not needed for current tool normalization tests, this may limit future test coverage if session-aware tool behavior is added.

Run the following script to check if any existing tests or upcoming scenarios require sessionContext for tool-related testing:

#!/bin/bash
# Search for sessionContext usage in test files and tool-related code
rg -n --type=ts -C3 'sessionContext' test/ lib/request/
lib/utils/clone.ts (1)

13-19: deepClone will throw on undefined and inefficiently handles primitives.

The past review comment remains valid: JSON.parse(JSON.stringify(undefined)) throws a SyntaxError, and primitives are unnecessarily serialized. This will cause runtime failures for valid generic inputs.

Apply the suggested fix from the past review to hoist the structuredClone reference and short-circuit non-object values:

-export function deepClone<T>(value: T): T {
-	const globalClone = (globalThis as { structuredClone?: <T>(value: T) => T }).structuredClone;
-	if (typeof globalClone === "function") {
-		return globalClone(value);
-	}
-	return JSON.parse(JSON.stringify(value)) as T;
-}
+const STRUCTURED_CLONE =
+	(globalThis as { structuredClone?: <U>(value: U) => U }).structuredClone;
+
+export function deepClone<T>(value: T): T {
+	// Fast path: primitives and null/undefined are already copy-safe.
+	if (value === null || typeof value !== "object") {
+		return value;
+	}
+	if (typeof STRUCTURED_CLONE === "function") {
+		return STRUCTURED_CLONE(value);
+	}
+	// Fallback: JSON-based deep clone for plain objects/arrays.
+	return JSON.parse(JSON.stringify(value)) as T;
+}

Based on learnings.

test/request-transformer.test.ts (1)

15-32: Align runTransform helper types with the real transformer signature

runTransform currently declares:

async function runTransform(
  body: RequestBody,
  codexInstructions: string,
  userConfig?: UserConfig,
  codexMode = true,
  options?: Record<string, unknown>,
  sessionContext?: any,
)

Given transformRequestBody already exposes concrete types for its options and last parameter, keeping this helper on Record<string, unknown> and any weakens type safety in a heavily-used test helper.

To keep tests aligned with the production API and catch mismatches early, consider:

  • Importing and using the real TransformRequestOptions type for options.
  • Narrowing sessionContext to the correct type (e.g., SessionContext | undefined or the corresponding parameter type from transformRequestBody).

This is non-blocking but will make these tests more robust against future API changes.

lib/session/session-manager.ts (1)

87-126: Fork identifier handling is narrower than prompt-cache fork hints

extractForkIdentifier only considers forkId, fork_id, branchId, and branch_id. Per earlier feedback, derivePromptCacheKeyFromBody in lib/request/request-transformer.ts also looks at other fork-hint keys (e.g. parentConversationId), so there’s a risk that session keys and prompt cache keys diverge for some fork sources.

If that’s not intentional, consider extending forkKeys to include the same set used in prompt cache derivation so session scoping and cache-key derivation stay in lockstep.

lib/compaction/codex-compaction.ts (1)

86-129: Prompt construction and tail extraction fit current flow; be aware of summary-as-user semantics

buildCompactionPromptItems and createSummaryMessage produce the expected developer/user pair and a summary message prefixed with CODEX_SUMMARY_PREFIX. extractTailAfterSummary then returns a cloned slice starting at the last role: "user" message, which matches the “latest user slice” semantics used by the session manager.

As previously noted in earlier reviews, if you later decide to keep injected summaries in the client-side conversation as role: "user" items, you may want to add an explicit summary marker (e.g. a flag on the item or in its metadata) and teach extractTailAfterSummary to skip those, so the tail always starts from a “real” user instruction.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f3e7e5 and ce75689.

⛔ Files ignored due to path filters (1)
  • biome.json is excluded by none and included by none
📒 Files selected for processing (47)
  • lib/auth/auth.ts (3 hunks)
  • lib/auth/browser.ts (1 hunks)
  • lib/auth/server.ts (1 hunks)
  • lib/cache/cache-metrics.ts (7 hunks)
  • lib/cache/cache-warming.ts (6 hunks)
  • lib/cache/prompt-fingerprinting.ts (7 hunks)
  • lib/cache/session-cache.ts (6 hunks)
  • lib/commands/codex-metrics.ts (1 hunks)
  • lib/compaction/codex-compaction.ts (1 hunks)
  • lib/compaction/compaction-executor.ts (1 hunks)
  • lib/config.ts (2 hunks)
  • lib/logger.ts (2 hunks)
  • lib/prompts/codex.ts (4 hunks)
  • lib/prompts/opencode-codex.ts (6 hunks)
  • lib/request/codex-fetcher.ts (4 hunks)
  • lib/request/response-handler.ts (5 hunks)
  • lib/session/response-recorder.ts (1 hunks)
  • lib/session/session-manager.ts (9 hunks)
  • lib/types.ts (4 hunks)
  • lib/utils/cache-config.ts (2 hunks)
  • lib/utils/clone.ts (1 hunks)
  • lib/utils/file-system-utils.ts (4 hunks)
  • lib/utils/input-item-utils.ts (1 hunks)
  • test/auth-constants.test.ts (1 hunks)
  • test/auth.test.ts (3 hunks)
  • test/browser.test.ts (1 hunks)
  • test/cache-metrics.test.ts (5 hunks)
  • test/cache-warming.test.ts (10 hunks)
  • test/codex-compaction.test.ts (1 hunks)
  • test/codex-fetcher.test.ts (5 hunks)
  • test/codex-metrics-command.test.ts (8 hunks)
  • test/compaction-executor.test.ts (1 hunks)
  • test/config.test.ts (2 hunks)
  • test/constants.test.ts (1 hunks)
  • test/fetch-helpers.test.ts (4 hunks)
  • test/index.test.ts (8 hunks)
  • test/logger.test.ts (3 hunks)
  • test/prompt-fingerprinting.test.ts (1 hunks)
  • test/prompts-codex.test.ts (4 hunks)
  • test/prompts-opencode-codex.test.ts (2 hunks)
  • test/request-transformer-tools-normalization.test.ts (1 hunks)
  • test/request-transformer.test.ts (1 hunks)
  • test/response-handler.test.ts (5 hunks)
  • test/response-recorder.test.ts (2 hunks)
  • test/server.test.ts (4 hunks)
  • test/session-cache-evictions.test.ts (1 hunks)
  • test/session-manager.test.ts (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (36)
test/compaction-executor.test.ts (4)
lib/compaction/compaction-executor.ts (2)
  • CompactionDecision (5-15)
  • finalizeCompactionResponse (24-66)
lib/session/session-manager.ts (1)
  • SessionManager (139-417)
lib/types.ts (1)
  • SessionContext (199-205)
lib/prompts/codex-compaction.ts (1)
  • CODEX_SUMMARY_PREFIX (11-11)
test/constants.test.ts (1)
lib/constants.ts (12)
  • PLUGIN_NAME (7-7)
  • PROVIDER_ID (16-16)
  • CODEX_BASE_URL (10-10)
  • DUMMY_API_KEY (13-13)
  • LOG_STAGES (56-61)
  • ERROR_MESSAGES (49-53)
  • HTTP_STATUS (19-22)
  • OPENAI_HEADERS (25-31)
  • OPENAI_HEADER_VALUES (34-37)
  • URL_PATHS (40-43)
  • JWT_CLAIM_PATH (46-46)
  • AUTH_LABELS (71-75)
test/response-recorder.test.ts (1)
lib/session/response-recorder.ts (1)
  • isCodexResponsePayload (5-24)
lib/logger.ts (1)
lib/utils/file-system-utils.ts (1)
  • getOpenCodePath (22-24)
test/response-handler.test.ts (1)
lib/request/response-handler.ts (2)
  • ensureContentType (94-102)
  • convertSseToJson (36-87)
test/codex-compaction.test.ts (2)
lib/types.ts (1)
  • InputItem (136-142)
lib/compaction/codex-compaction.ts (7)
  • detectCompactionCommand (36-52)
  • serializeConversation (54-84)
  • buildCompactionPromptItems (86-98)
  • collectSystemMessages (100-105)
  • createSummaryMessage (107-117)
  • approximateTokenCount (25-34)
  • extractTailAfterSummary (119-129)
lib/cache/session-cache.ts (1)
lib/cache/cache-metrics.ts (1)
  • recordCacheEviction (183-185)
test/browser.test.ts (2)
lib/auth/browser.ts (2)
  • getBrowserOpener (13-18)
  • openBrowserUrl (25-35)
lib/constants.ts (1)
  • PLATFORM_OPENERS (64-68)
test/server.test.ts (1)
lib/auth/server.ts (1)
  • startLocalOAuthServer (17-77)
test/request-transformer-tools-normalization.test.ts (2)
lib/types.ts (2)
  • RequestBody (147-169)
  • UserConfig (40-47)
lib/request/request-transformer.ts (1)
  • transformRequestBody (960-1123)
test/codex-fetcher.test.ts (2)
lib/request/codex-fetcher.ts (1)
  • createCodexFetcher (32-114)
lib/constants.ts (1)
  • LOG_STAGES (56-61)
test/auth-constants.test.ts (1)
lib/auth/auth.ts (4)
  • AUTHORIZE_URL (9-9)
  • CLIENT_ID (8-8)
  • REDIRECT_URI (11-11)
  • SCOPE (12-12)
lib/commands/codex-metrics.ts (4)
lib/session/session-manager.ts (2)
  • SessionManager (139-417)
  • SessionMetricsSnapshot (128-137)
lib/cache/cache-metrics.ts (1)
  • getCachePerformanceReport (224-252)
lib/cache/cache-warming.ts (2)
  • CacheWarmSnapshot (133-136)
  • getCacheWarmSnapshot (138-143)
lib/types.ts (1)
  • RequestBody (147-169)
test/session-manager.test.ts (3)
lib/types.ts (3)
  • RequestBody (147-169)
  • SessionContext (199-205)
  • InputItem (136-142)
lib/session/session-manager.ts (1)
  • SessionManager (139-417)
lib/constants.ts (1)
  • SESSION_CONFIG (78-83)
test/request-transformer.test.ts (2)
lib/types.ts (3)
  • RequestBody (147-169)
  • UserConfig (40-47)
  • InputItem (136-142)
lib/request/request-transformer.ts (9)
  • transformRequestBody (960-1123)
  • normalizeModel (221-254)
  • getReasoningConfig (286-344)
  • filterInput (368-401)
  • getModelConfig (263-272)
  • addToolRemapMessage (664-682)
  • isOpenCodeSystemPrompt (410-437)
  • filterOpenCodeSystemPrompts (447-549)
  • addCodexBridgeMessage (585-656)
test/prompt-fingerprinting.test.ts (1)
lib/cache/prompt-fingerprinting.ts (5)
  • generateContentHash (15-17)
  • hasBridgePromptInConversation (27-46)
  • generateInputHash (124-143)
  • cacheBridgeDecision (109-117)
  • getCachedBridgeDecision (88-101)
test/cache-warming.test.ts (2)
lib/cache/cache-warming.ts (3)
  • warmCachesOnStartup (32-102)
  • getCacheWarmingStats (145-156)
  • areCachesWarm (113-126)
lib/cache/session-cache.ts (2)
  • codexInstructionsCache (76-76)
  • openCodePromptCache (77-77)
test/index.test.ts (1)
lib/auth/auth.ts (1)
  • REDIRECT_URI (11-11)
test/prompts-opencode-codex.test.ts (2)
lib/cache/session-cache.ts (1)
  • openCodePromptCache (77-77)
lib/prompts/opencode-codex.ts (2)
  • getOpenCodeCodexPrompt (31-129)
  • getCachedPromptPrefix (136-146)
lib/session/session-manager.ts (5)
lib/types.ts (3)
  • InputItem (136-142)
  • RequestBody (147-169)
  • SessionContext (199-205)
lib/utils/input-item-utils.ts (1)
  • isUserMessage (80-82)
lib/utils/clone.ts (2)
  • cloneInputItems (26-31)
  • deepClone (13-19)
lib/constants.ts (1)
  • SESSION_CONFIG (78-83)
lib/logger.ts (1)
  • logDebug (66-69)
lib/cache/cache-warming.ts (2)
lib/logger.ts (2)
  • logWarn (75-77)
  • logDebug (66-69)
lib/cache/session-cache.ts (2)
  • codexInstructionsCache (76-76)
  • openCodePromptCache (77-77)
lib/compaction/codex-compaction.ts (4)
lib/types.ts (1)
  • InputItem (136-142)
lib/utils/input-item-utils.ts (3)
  • extractTextFromItem (16-27)
  • formatRole (43-54)
  • formatEntry (62-64)
lib/prompts/codex-compaction.ts (2)
  • CODEX_COMPACTION_PROMPT (1-9)
  • CODEX_SUMMARY_PREFIX (11-11)
lib/utils/clone.ts (1)
  • deepClone (13-19)
lib/request/response-handler.ts (1)
lib/types.ts (1)
  • SSEEventData (174-178)
lib/utils/input-item-utils.ts (1)
lib/types.ts (1)
  • InputItem (136-142)
test/fetch-helpers.test.ts (3)
lib/auth/auth.ts (1)
  • refreshAccessToken (124-166)
lib/request/fetch-helpers.ts (8)
  • shouldRefreshToken (29-31)
  • extractRequestUrl (82-86)
  • rewriteUrlForCodex (104-106)
  • createCodexHeaders (212-235)
  • refreshAndUpdateToken (39-75)
  • transformRequestForCodex (117-203)
  • handleErrorResponse (242-319)
  • handleSuccessResponse (328-343)
lib/constants.ts (2)
  • OPENAI_HEADERS (25-31)
  • OPENAI_HEADER_VALUES (34-37)
test/auth.test.ts (1)
lib/auth/auth.ts (10)
  • createState (19-21)
  • parseAuthorizationInput (28-52)
  • decodeJWT (107-117)
  • createAuthorizationFlow (172-189)
  • AUTHORIZE_URL (9-9)
  • CLIENT_ID (8-8)
  • REDIRECT_URI (11-11)
  • SCOPE (12-12)
  • exchangeAuthorizationCode (61-100)
  • refreshAccessToken (124-166)
lib/prompts/codex.ts (3)
lib/cache/cache-metrics.ts (2)
  • recordCacheHit (167-169)
  • recordCacheMiss (175-177)
lib/utils/file-system-utils.ts (1)
  • getOpenCodePath (22-24)
lib/utils/cache-config.ts (2)
  • CACHE_FILES (26-35)
  • CACHE_TTL_MS (11-11)
test/codex-metrics-command.test.ts (1)
lib/commands/codex-metrics.ts (1)
  • maybeHandleCodexCommand (36-93)
lib/compaction/compaction-executor.ts (2)
lib/types.ts (2)
  • InputItem (136-142)
  • SessionContext (199-205)
lib/compaction/codex-compaction.ts (1)
  • createSummaryMessage (107-117)
test/logger.test.ts (1)
lib/logger.ts (3)
  • LOGGING_ENABLED (7-7)
  • logRequest (47-64)
  • logWarn (75-77)
test/config.test.ts (1)
lib/request/request-transformer.ts (2)
  • getModelConfig (263-272)
  • getReasoningConfig (286-344)
lib/prompts/opencode-codex.ts (2)
lib/cache/cache-metrics.ts (2)
  • recordCacheHit (167-169)
  • recordCacheMiss (175-177)
lib/utils/cache-config.ts (1)
  • CACHE_TTL_MS (11-11)
test/session-cache-evictions.test.ts (2)
lib/cache/cache-metrics.ts (2)
  • resetCacheMetrics (206-208)
  • getCacheMetrics (191-193)
lib/cache/session-cache.ts (3)
  • codexInstructionsCache (76-76)
  • openCodePromptCache (77-77)
  • cleanupExpiredCaches (102-114)
test/cache-metrics.test.ts (1)
lib/cache/cache-metrics.ts (8)
  • recordCacheHit (167-169)
  • getCacheMetrics (191-193)
  • recordCacheMiss (175-177)
  • recordCacheEviction (183-185)
  • getCacheMetricsSummary (199-201)
  • resetCacheMetrics (206-208)
  • autoResetCacheMetrics (214-218)
  • getCachePerformanceReport (224-252)
lib/request/codex-fetcher.ts (3)
lib/types.ts (1)
  • PluginConfig (6-35)
lib/request/fetch-helpers.ts (1)
  • handleSuccessResponse (328-343)
lib/compaction/compaction-executor.ts (1)
  • finalizeCompactionResponse (24-66)
test/prompts-codex.test.ts (2)
lib/prompts/codex.ts (1)
  • getCodexInstructions (49-155)
lib/cache/session-cache.ts (2)
  • codexInstructionsCache (76-76)
  • getCodexCacheKey (85-87)
🪛 GitHub Actions: CI
lib/cache/prompt-fingerprinting.ts

[error] 27-27: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.


[error] 53-53: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.


[error] 124-124: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.

lib/commands/codex-metrics.ts

[warning] 300-300: lint/suspicious/useIterableCallbackReturn: This callback passed to forEach() should not return a value.

lib/session/session-manager.ts

[error] 159-159: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.

lib/cache/cache-warming.ts

[error] 32-32: lint/complexity/noExcessiveCognitiveComplexity: Excessive complexity of 28 detected (max: 15). Please refactor this function to reduce its complexity.

lib/prompts/codex.ts

[error] 49-49: lint/complexity/noExcessiveCognitiveComplexity: Excessive complexity of 29 detected (max: 15). Refactor to reduce complexity.

lib/compaction/compaction-executor.ts

[error] 31-31: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.


[error] 68-68: lint/suspicious/noExplicitAny: Unexpected any. Specify a different type.

lib/prompts/opencode-codex.ts

[error] 31-31: lint/complexity/noExcessiveCognitiveComplexity: Excessive complexity of 16 detected (max: 15). Refactor to reduce complexity.

lib/request/codex-fetcher.ts

[error] 44-44: lint/complexity/noExcessiveCognitiveComplexity: Excessive complexity of 17 detected (max: 15). Refactor to reduce complexity.

🪛 Gitleaks (8.29.0)
test/session-manager.test.ts

[high] 139-139: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (58)
lib/utils/cache-config.ts (1)

1-49: Clean and well-structured configuration module.

The changes are minimal and align with best practices: the added comment line improves readability in the JSDoc header, and the EOF newline ensures consistency with linting standards. All exports use as const for proper type narrowing, and the module is logically organized with clear sections for TTL, directories, files, and metadata fields.

test/request-transformer-tools-normalization.test.ts (4)

18-49: Test correctly verifies tool normalization for non-Codex models.

The test properly checks that:

  • Native Codex tools (shell, apply_patch) are passed as type-only entries
  • String tools are converted to function tools with default schema
  • Non-Codex models enable parallel_tool_calls=true (line 48)

This aligns with the implementation in lib/request/request-transformer.ts (lines 1050-1052).


51-102: Test correctly verifies Codex model tool behavior.

The test properly validates:

  • Direct function objects use their own fields (lines 86-92)
  • Nested function objects prefer nested fields (lines 95-97)
  • Codex models disable parallel tool calls (line 101)
  • Native Codex tools are preserved (line 83)

The parallel_tool_calls=false expectation for "gpt-5-codex" matches the implementation logic.


104-160: Test correctly verifies tool map and enabled flag handling.

The test properly validates:

  • Tools defined as object maps are normalized (line 113)
  • Disabled tools are filtered out (lines 150-151)
  • Boolean false values are treated as disabled (line 151)
  • Custom tool types with formats are preserved (lines 153-159)

The enabled flag logic and filtering behavior is correctly tested.


162-178: Test correctly verifies cleanup when no tools remain.

The test validates that when all tools are disabled, the implementation properly removes tools, tool_choice, and parallel_tool_calls fields (lines 175-177). This matches the cleanup logic in the transformer.

test/auth-constants.test.ts (1)

1-11: LGTM!

Formatting changes align with project standardization (double quotes, import ordering). No functional changes detected.

lib/utils/file-system-utils.ts (1)

1-76: LGTM!

Formatting changes only—import reorganization and function signature cleanup. No behavioral changes.

test/prompt-fingerprinting.test.ts (1)

1-134: LGTM!

Import centralization and double-quote standardization. Test logic remains unchanged.

test/constants.test.ts (1)

1-55: LGTM!

Formatting standardization (double quotes, import ordering). No functional changes.

test/config.test.ts (1)

1-151: LGTM!

String literal standardization to double quotes. Test logic unchanged.

test/index.test.ts (1)

1-451: LGTM!

Test mock expansion and double-quote standardization. Test coverage appropriately updated for the broader changes.

test/auth.test.ts (1)

1-325: LGTM!

Import expansion reflects extended public API surface. String literals standardized to double quotes. Test logic remains sound.

lib/config.ts (1)

15-16: Verification confirms proper typing and integration—no blockers.

Both fields are properly typed in the PluginConfig interface in lib/types.ts:

  • enableCodexCompaction?: boolean; (line 24, default: true via JSDoc)
  • autoCompactMinMessages?: number; (line 34)

They are actively consumed in lib/request/fetch-helpers.ts (lines 140 and 144) with sensible fallbacks, and comprehensive test coverage spans multiple test files. The config defaults in lib/config.ts (lines 15–16) align with the implementation.

lib/auth/browser.ts (1)

32-32: LGTM: Unused error parameter properly indicated.

The underscore prefix correctly signals that the error is intentionally ignored, aligning with the documented behavior of silent failure.

lib/session/response-recorder.ts (1)

33-33: LGTM: Guard condition formatting improved.

The single-line conditional is more concise while preserving the same logic.

lib/auth/server.ts (1)

2-2: LGTM: Import organization improved.

The import reordering enhances readability with no behavioral impact.

Also applies to: 6-6

test/browser.test.ts (1)

1-76: LGTM: Formatting standardized.

The changes improve style consistency (double quotes, import order) without altering test behavior.

test/session-cache-evictions.test.ts (1)

5-43: LGTM: Test formatting standardized.

Import organization and quote style updated for consistency without affecting test behavior.

lib/commands/codex-metrics.ts (1)

1-383: LGTM: Formatting standardized throughout.

The extensive formatting changes improve consistency (spacing, quotes, alignment) without altering functionality.

test/logger.test.ts (1)

1-134: LGTM: Test formatting standardized.

Quote style and spacing updated for consistency without affecting test logic.

lib/auth/auth.ts (1)

2-4: LGTM - Clean organizational improvements.

The import reordering and type-only imports improve code organization. The condensed conditionals maintain the same logic while being more concise.

Also applies to: 90-90, 150-150

test/response-recorder.test.ts (1)

2-7: LGTM - Test structure is correct.

The import updates and test assertions properly validate the payload structure with typed expectations.

Also applies to: 134-138

lib/logger.ts (1)

10-10: Good improvement - Test environment log suppression.

The IS_TEST_ENV guard effectively reduces noise in test output while preserving error logs. This is a practical enhancement to developer experience.

Also applies to: 103-105

test/server.test.ts (1)

1-119: LGTM - Consistent quote style applied.

The conversion to double quotes maintains consistency with the broader codebase style standards. No functional changes.

lib/cache/session-cache.ts (1)

21-21: LGTM - Quote style normalization.

String literals and type annotations consistently use double quotes, aligning with project conventions.

Also applies to: 48-48, 86-86, 95-95, 107-107, 113-113

test/prompts-codex.test.ts (1)

1-261: LGTM - Quote convention applied consistently.

All string literals updated to double quotes, maintaining consistency across the test suite.

test/prompts-opencode-codex.test.ts (1)

1-329: LGTM - Style consistency maintained.

Quote style updated throughout to align with project standards. Test logic remains intact.

lib/prompts/opencode-codex.ts (3)

10-13: LGTM - Import cleanup removes unused dependencies.

Removing unused imports (getOpenCodeCacheKey, file utility functions) improves code clarity.


41-146: Quote style updates applied consistently.

String literals updated to double quotes throughout, aligning with project conventions.


31-128: Review comment is factually incorrect—threshold mismatch undermines the claim.

The review states the complexity exceeds "16/15," but your Biome configuration sets maxAllowedComplexity: 25. The claimed threshold of 15 does not exist in your linting rules. Even if the function reaches the stated complexity of 16, it would fall well within the configured limit of 25 and would not trigger a pipeline failure.

The noExcessiveCognitiveComplexity rule is also set to "warn" level, not an error, so it wouldn't block the pipeline regardless.

Likely an incorrect or invalid review comment.

test/response-handler.test.ts (1)

1-112: LGTM! Formatting changes align with project style.

The conversion from single to double quotes throughout the test file is purely cosmetic and preserves all test logic.

lib/utils/clone.ts (2)

26-31: LGTM once deepClone is fixed.

This helper correctly handles edge cases and will inherit the safer semantics once the deepClone function is fixed.


38-40: LGTM once deepClone is fixed.

Simple wrapper that will inherit the safer behavior once deepClone is corrected.

test/codex-fetcher.test.ts (1)

1-278: LGTM! Test updates align with compaction integration.

The formatting changes and pluginConfig additions correctly reflect the broader PR changes. Test logic is preserved and expectations are properly updated.

lib/types.ts (2)

20-34: LGTM! Clean interface extensions for compaction.

The new optional fields for enabling and configuring compaction are well-documented and backward-compatible.


192-193: LGTM! Session state extensions for compaction.

The optional fields for compaction base system and summary items are appropriately scoped to session state.

lib/cache/cache-warming.ts (1)

1-156: Formatting changes look good; consider addressing complexity warning.

The formatting updates are clean. However, the pipeline flagged warmCachesOnStartup (line 32) with excessive cognitive complexity (28, max: 15). Consider extracting helper functions for cache warming attempts to improve maintainability.

test/cache-warming.test.ts (1)

1-242: LGTM! Test formatting and mock updates are consistent.

The quote style changes and logger mock enhancement align with the broader PR updates. All test logic is preserved.

test/codex-metrics-command.test.ts (1)

1-350: LGTM! Import refinements and formatting updates are sound.

The type-only import for RequestBody, addition of resetCacheMetrics, and quote style changes are all appropriate. Test logic is preserved.

test/codex-compaction.test.ts (1)

1-95: Solid test coverage; consider clarifying extractTailAfterSummary semantics.

The test suite provides comprehensive coverage of the compaction helpers. The past review comment about extractTailAfterSummary test naming remains relevant—the tests assert "tail after the last user message" rather than detection of a specific summary marker. If the implementation evolves to key off a summary prefix, updating the test names and expectations would improve clarity.

Based on learnings.

test/request-transformer.test.ts (1)

639-1314: Compaction, config, and ID-filtering integration tests are comprehensive and match transformer behavior

The new and expanded describe("compaction integration"), describe("CODEX_MODE parameter"), and “Integration: Complete Config Scenarios” blocks exercise:

  • Manual /codex-compact and auto-compaction decisions (modes, token thresholds, tools removal).
  • Prompt cache key derivation (host key vs metadata, fork-aware keys, deterministic fallbacks, metadata edge cases).
  • Model normalization, reasoning config defaults/overrides, text verbosity, and include logic for encrypted reasoning.
  • Message ID stripping vs preservation across single and multi-turn histories, including mixed/custom ID formats.
  • Tool remap vs Codex bridge behavior under codexMode=true/false, including OpenCode prompt filtering rules.
  • Numerous edge cases (empty/undefined input, malformed content arrays, odd tool arrays, unicode/long content).

These tests provide strong regression coverage for transformRequestBody’s most complex paths and match the production semantics shown in lib/request/request-transformer.ts. From a behavior standpoint, this suite looks solid.

lib/request/response-handler.ts (1)

9-87: SSE parsing and JSON conversion look consistent and safe for the intended stream format

parseSseStream and convertSseToJson now:

  • Consume the entire SSE stream, log it when enabled, and robustly scan for response.done / response.completed events.
  • Fall back to returning the original stream text (with original headers and status) when no final event is found, instead of throwing.
  • Set an explicit JSON content-type when a final payload is successfully extracted.

Within the constraints of the expected SSE format, this is a reasonable and resilient implementation.

test/cache-metrics.test.ts (1)

17-225: Cache metrics tests thoroughly cover recording, reset, auto-reset, and reporting

The updated suite:

  • Uses the public recordCacheHit/Miss/Eviction, resetCacheMetrics, autoResetCacheMetrics, and getCachePerformanceReport helpers as intended.
  • Validates per-cache and overall counters, hit rates, and evictions for hits/misses/evictions flows.
  • Exercises reset behavior (manual and auto via fake timers/system time), including “no reset when interval not passed”.
  • Asserts on performance report summaries and all three recommendation conditions, plus dedicated bridge-decision metrics.

This gives good confidence that the metrics collector and helper API behave correctly across normal and edge scenarios.

test/compaction-executor.test.ts (1)

10-132: Compaction executor tests correctly pin auto vs command behavior and session wiring

These tests verify that finalizeCompactionResponse:

  • Rewrites assistant output in auto mode with the “Auto compaction triggered (…)” note and CODEX_SUMMARY_PREFIX, while preserving HTTP status, status text, and headers.
  • Populates metadata.codex_compaction fields (mode, reason, total/dropped turns) correctly for both auto and command modes.
  • Gracefully handles payloads without assistant output (keeps output: [] while still writing compaction metadata).
  • Invokes SessionManager.applyCompactionSummary with the expected SessionContext and a summary that includes CODEX_SUMMARY_PREFIX.

This looks well aligned with the compaction executor implementation and should guard against regressions in the compaction finalization flow.

lib/utils/input-item-utils.ts (1)

16-125: InputItem helpers look correct and cohesive

The extraction, role predicates, and turn-counting helpers are consistent with the InputItem shape and will make downstream compaction/session logic clearer. No functional issues spotted here.

lib/request/codex-fetcher.ts (2)

21-42: pluginConfig integration and deps wiring look good

Adding pluginConfig to CodexFetcherDeps and threading it through to transformRequestForCodex is consistent with the new compaction-config options and keeps the public surface explicit. No issues here.


53-63: Compaction and session context handling is wired correctly

Using transformRequestForCodex to compute sessionContext and optional compactionDecision, then passing sessionContext through to header construction and later to finalizeCompactionResponse and recordSessionResponseFromHandledResponse, keeps session and compaction state aligned. The hasTools and requestInit derivation also handles the “no transform” case safely.

Also applies to: 72-75

test/session-manager.test.ts (5)

6-28: Session creation and prefix/prompt-cache tests match new behavior

The createBody helper and the initial tests (returns undefined when disabled, initializes session, maintains prefix across turns) exercise the fork‑agnostic path correctly:

  • conversation_id metadata drives sessionKey and prompt_cache_key.
  • applyRequest wiring to body.prompt_cache_key and state.lastInput is asserted.
  • Prefix reuse vs. regeneration is covered via the “regenerates cache key when prefix differs” test.

No changes needed here.

Also applies to: 30-69


99-159: Host prompt_cache_key fallback and reuse tests look correct

The falls back to prompt_cache_key when metadata missing and reuses session when prompt_cache_key matches existing tests now exercise the host‑cache‑key path explicitly, including reusing the same session when only prompt_cache_key is provided. This matches the updated getContext logic.


161-219: Fork‑specific sessions and compaction scoping are well covered

The fork tests do a good job of pinning the new semantics:

  • creates fork-specific sessions with derived cache keys verifies conv-fork::fork::<id> for both alpha and beta forks and shows reuse on repeat alpha requests.
  • scopes compaction summaries per fork session validates that summaries and compacted history are isolated per fork, and that the merge order (base system → summary → latest user tail) is as intended.

These tests should protect against regressions in fork keying and per‑fork compaction behavior.


221-248: TTL and capacity behavior tests align with SESSION_CONFIG

The eviction and capacity tests now rely on SESSION_CONFIG.IDLE_TTL_MS and SESSION_CONFIG.MAX_ENTRIES, matching the implementation:

  • TTL test directly manipulates lastUpdated to force eviction.
  • Capacity test ensures totalSessions never exceeds the configured max and that recentSessions is capped.

No functional issues here.


137-140: Gitleaks “generic API key” warning is a false positive

The hard‑coded "persistent_key_789" value is a synthetic test cache key, not a real credential. No change needed, but if you want to silence future scanners you could rename it to something like "test_cache_key_persistent" to avoid the “key” heuristic.

test/fetch-helpers.test.ts (1)

1-437: Fetch helper tests comprehensively cover new behavior

The updated tests:

  • Validate the URL helpers, header construction (including prompt cache key → conversation/session headers and x-api-key stripping), and token refresh paths.
  • Exercise transformRequestForCodex with and without body, invalid JSON, and the new compaction options (asserting compaction.originalInput and pluginConfig propagation).
  • Cover both response paths: SSE → JSON for non‑tool responses, passthrough for tool responses, and detailed handleErrorResponse enrichment branches.

This suite should give good confidence in the new compaction-aware request/response flow.

lib/session/session-manager.ts (4)

18-33: computeHash and extractLatestUserSlice match compaction needs

computeHash and extractLatestUserSlice provide consistent hashing and “latest user slice” extraction using cloneInputItems and isUserMessage. This aligns with how compaction later merges baseSystem + summary + tail, and avoids mutating original inputs.


195-227: Fork-aware session and prompt cache key derivation look consistent

Using buildSessionKey(conversationId, forkId) for SessionState.id and buildPromptCacheKey(conversationId, forkId) for promptCacheKey ensures:

  • Base sessions remain keyed by the conversation ID when no forkId is present.
  • Forked sessions get deterministic, namespaced keys (<conversation>::fork::<forkId>), matching expectations in the tests.

This matches the test semantics in test/session-manager.test.ts.


230-320: Compaction summary/history integration is correct and side-effect scoped

applyCompactionSummary and applyCompactedHistory:

  • Respect context?.enabled and an explicit opts?.skip flag.
  • Store a cloned base system and a deep-cloned summary as a user message.
  • Merge baseSystem + summary + latest-user-tail into body.input, using extractLatestUserSlice and cloneInputItems.

This matches the expectations in both compaction executor tests and test/session-manager.test.ts and correctly confines compaction state to the active session.


361-397: Pruning logic correctly uses SESSION_CONFIG and logs evictions

The updated pruneSessions:

  • Evicts sessions idle longer than SESSION_CONFIG.IDLE_TTL_MS.
  • Enforces SESSION_CONFIG.MAX_ENTRIES by evicting the oldest sessions, with clear debug/warn logs.

This matches the new tests and centralizes the limits via SESSION_CONFIG.

lib/compaction/codex-compaction.ts (1)

25-84: Compaction command detection and serialization logic look solid

approximateTokenCount, detectCompactionCommand, and serializeConversation behave coherently:

  • Token approximation via total text length / 4 is simple and safe.
  • Command detection only inspects the latest user turn, normalized (lowercased, optional / or ? stripped) against COMMAND_TRIGGERS.
  • Transcript serialization walks the conversation, filters to user/assistant, then truncates from the end up to DEFAULT_TRANSCRIPT_CHAR_LIMIT, preserving chronological order and tracking droppedTurns.

This aligns with the compaction behavior described in tests and is easy to reason about.

@riatzukiza
Copy link
Collaborator Author

Handling remaining CodeRabbit review comments:

With these follow-ups tracked, we are resolving the outstanding review threads from PR #20.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c8e1e1 and 4deeb6e.

📒 Files selected for processing (1)
  • test/README.md (5 hunks)
🔇 Additional comments (1)
test/README.md (1)

35-85: Well-organized test coverage documentation.

The expanded descriptions for each test file (auth, config, request-transformer, response-handler, logger) clearly communicate scope and coverage areas. The formatting is consistent and readable.

@riatzukiza
Copy link
Collaborator Author

/oc In test/README.md around lines 112 to 117, the docs reference
config/minimal-opencode.json and config/full-opencode.json which do not exist;
update the doc or add the files. Either create the two example configuration
files under test/config/ (minimal-opencode.json with the simplest valid defaults
and full-opencode.json demonstrating all options/variants), commit them, and
link to them from the README, or edit the README to point to existing example
files or remove the broken entries; ensure paths are correct and verify the
repository contains the referenced files before finalizing.

@riatzukiza
Copy link
Collaborator Author

/oc In test/README.md around lines 19 to 31 (and specifically update the Test
Coverage section at lines 36, 38, 56–57, 68–69, 78–79), the documented test
counts are stale; update the test headers to reflect the actual counts by
replacing the old counts with: "### auth.test.ts (27 tests)", "###
config.test.ts (16 tests)", "### logger.test.ts (7 tests)", and "###
request-transformer.test.ts (123 tests)"; ensure formatting matches existing
markdown headers and leave response-handler.test.ts as-is (10 tests).

…paths

- Update stale test counts to reflect actual numbers:
  * auth.test.ts: 16 → 27 tests
  * config.test.ts: 13 → 16 tests
  * request-transformer.test.ts: 30 → 123 tests
  * logger.test.ts: 5 → 7 tests
  * response-handler.test.ts: unchanged at 10 tests

- Fix broken configuration file paths:
  * config/minimal-opencode.json (was config/minimal-opencode.json)
  * config/full-opencode.json (was config/full-opencode.json)

Both configuration files exist in the config/ directory at repository root.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4deeb6e and 71fc782.

⛔ Files ignored due to path filters (6)
  • .github/workflows/ci.yml is excluded by none and included by none
  • .github/workflows/formatting.yml is excluded by none and included by none
  • .github/workflows/opencode.yml is excluded by none and included by none
  • eslint.config.mjs is excluded by none and included by none
  • package.json is excluded by none and included by none
  • spec/lint-warnings-nonfatal.md is excluded by none and included by none
📒 Files selected for processing (1)
  • test/README.md (4 hunks)
🔇 Additional comments (2)
test/README.md (2)

19-31: pnpm command alignment is complete and consistent.

All test running instructions and CI guidance have been successfully migrated from npm to pnpm. The replacements are consistent across all sections (Running Tests, Adding New Tests, CI/CD).

Also applies to: 109-110


35-35: Test count headers verified—all accurate.

Cross-check against actual test files confirms all documented counts are correct:

  • auth.test.ts: 27 tests ✓
  • config.test.ts: 16 tests ✓
  • request-transformer.test.ts: 123 tests ✓
  • response-handler.test.ts: 10 tests ✓
  • logger.test.ts: 7 tests ✓

The documentation is in sync with the test files.

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.

1 participant