refactor: collapse the duplicate stacks (PR 3/3)#169
Merged
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
EtienneLescot
force-pushed
the
chore/ponytail-2-stdlib
branch
from
July 26, 2026 19:12
c5f501e to
af79e27
Compare
document.agent, .preview, .export and .history were declared, defaulted, seeded in every test fixture and written on every edit — and read by nothing. preview.revision in particular was bumped at eight sites and consumed only by tests asserting the bump happened. Removes those fields, the ten schemas behind them (pendingQuestion, preview, exportState, suggestion, agentState, operation, revision, plus the three input schemas with no callers) and their inferred types. timelineOperationSchema STAYS: the review called it dead, but AxcutTimelineOperation has 19 call sites. operationSchema only extended it with suggestion ops nothing dispatches, so that one does go. Old saved projects are unaffected: documentSchema is not strict, so zod strips the now-unknown keys on parse. schema/index.ts 709 -> 604 lines. tsc clean; 95 files / 1114 tests pass.
llm-call.ts opened with "no LangChain dependency" and hand-rolled a multi-provider fetch/SSE client — OpenAI-compat, Anthropic, Codex and Copilot dialects, 736 lines — while the live agent loop went through LangChain the whole time (chat-service.ts -> deep-agent/service.ts). Its only two remaining callers were one-shot prompt->text calls: chat compaction and caption translation. Both now use createOpenScreenChatModel(...).invoke(), which already knew every provider. Removes llm-call.ts, codex-session.ts (a bespoke chatgpt.com Responses dialect reachable only from it) and agent-provider-capabilities.ts, whose per-provider reasoning-effort matrix was duplicated inside deep-agent/. The Copilot runtime-token swap is preserved, and this fixes it rather than porting it: chat-model.ts previously used the PAT directly with a comment saying the refresh "can land as a follow-up", so the MAIN agent path was the broken one. It now exchanges the PAT for the short-lived runtime token, honours the base URL that exchange returns, and sends the editor-identifying headers the endpoint requires. Every caller benefits, not just the two being rerouted. extractDelta (MessageContent -> text) is exported from deep-agent/service rather than re-implemented. tsc clean; 93 files / 1082 tests pass (the delta is the two deleted test files, which covered the deleted code).
addClipBefore, addClipAfter, editClip, splitAndInsert, addTrimAt, updateTrimRange and clearClipSelection were defined, memoised and returned from useTimeline, and called by nothing. insertClipAt, setTrimEntries and updateClipSourceRange already cover every UI path. editClip had its own test suite, which is why it looked alive. The live Edit Clip modal does not use it: NewEditorShell.tsx:1316 calls tl.updateClipSourceRange + tl.updateClipCrop. The tests went with the action. Also removes RightPanes' TimelinePaneBody and the RightPaneId type, both exported and unreferenced — FloatingInspector's Facet union replaced the latter. useTimeline.ts 1192 -> 970 lines. tsc clean; 93 files / 1079 tests pass.
Review follow-ups on the llm-call.ts removal. The reroute to createOpenScreenChatModel was right, but three things did not survive it. `accountId` was threaded from both new call sites into OpenScreenChatModelConfig and then read by nobody. The deleted llm-call.ts set `chatgpt-account-id` from it and called the header required by chatgpt.com/backend-api, so caption translation and chat compaction were newly broken for Codex accounts — the same bug class the Copilot fix addressed, pointed the other way. tsc cannot see it: an optional field that nothing reads still typechecks. caption-translate built a model per batch. For Copilot that is a PAT -> runtime-token exchange against api.github.com on every iteration; at batch size 40 a 400-segment transcript paid for ten of them. Built once, above the loop, with the construction failure kept in the same result shape. extractDelta is now messageContentToText in chat-model.ts. It was exported from deep-agent/service.ts, whose top level pulls `langchain` and the whole agent-tools graph — a lot to import for ten lines of content flattening. chat-service.ts worked around it with a dynamic import; caption-translate.ts did not. Both now import it statically with nothing dragged along. Also normalizes the provider once at the createOpenScreenChatModel entry point. The deleted agent-provider-capabilities.ts resolved `claude` -> anthropic and `gemini` -> google and had tests for it; the surviving deep-agent copy compares raw strings, so those aliases stopped resolving and normalizeProviderId was left with no callers at all. And the surviving copy was not the equivalent duplicate the deletion assumed: isOpenRouterReasoningModel strips the `anthropic/` slug prefix but not `openai/`, and both vendor matchers are anchored at the start — so openrouter + openai/gpt-5 silently got no reasoning wiring. The deleted file stripped both and its deleted test asserted it. Adds the tests back for the module that survived, plus runtime checks for the account header and the alias routing.
migrate.ts still built `agent: {pendingQuestions, suggestions,
lastAppliedOperations}` on every migrated project. zod strips it, so it
was harmless — and it was in shipped code, not a fixture.
transcribe.test.ts still carried agent/preview/export, including a
`preview.playbackRate` that was never in the schema.
These survived because tsconfig.json excludes **/*.test.ts(x) and its
`include` is ["src", "electron"] — no test file and nothing under tests/
is typechecked, and vitest transpiles without checking. So the gate the
deletion leaned on could not see the fixtures it rewrote by hand.
Also drops the comments still describing `preview.revision`, a field that
no longer exists.
(The roadmap-coverage.spec.ts fixture this originally also fixed is gone:
release/1.8.0 deleted that spec in the v4-shell e2e retarget.)
The boolean was declared, defaulted, persisted, migrated and
history-tracked across five files and read by nothing. Its only UI was
RightPanes' TimelinePaneBody, which was already unreferenced before PR 3
deleted it — so the toggle had no way to be set and no effect if it was.
Removes it from EditorSettingsSnapshot, DEFAULT_EDITOR_SETTINGS,
LegacyShape, getEditorSettings, EditorSettingsPatch,
DEFAULT_EDITOR_APPEARANCE_SETTINGS, ProjectEditorState, the
projectPersistence parse branch, EditorState + INITIAL_EDITOR_STATE, and
the v2 migration's editor envelope.
The i18n keys go with it: settings.timeline.{title,waveform,help} in all
13 locales, not the 10 the note listed — vi, zh-CN and zh-TW were
missed. Those three keys were the whole `settings.timeline` namespace and
TimelinePaneBody was its only consumer; the separate top-level `timeline`
namespace (FloatingInspector, V4Timeline) is untouched.
Old projects keep working: migrate spreads input.editor wholesale into
legacyEditor, and legacyEditorSchema is z.object({}).passthrough(), so a
stored showTrimWaveform rides along inertly instead of failing the parse
— and getEditorSettings reads legacyEditor through a loose shape check
that ignores unknown keys. Pinned with a test rather than assumed, since
tsconfig excludes test files and would not have caught a regression here.
tsc clean; biome clean; 95 files / 1101 tests pass.
EtienneLescot
force-pushed
the
chore/ponytail-3-refactor
branch
from
July 26, 2026 20:04
8a40c81 to
b5a60d6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Last of three. #167 and #168 have merged, so this no longer stacks on anything — it has been rebased onto
release/1.8.0and stands alone. 55 files, −2,165 net.This is the behaviour-changing set, so every claim here was re-verified against the code rather than taken from the review.
Verification
tsc --noEmitbiome check src electronvitest --runOne provider stack, and two OAuth fixes
llm-call.tsopened with "no LangChain dependency" and hand-rolled a 736-line multi-provider fetch/SSE client — OpenAI-compat, Anthropic, Codex and Copilot dialects — while the live agent loop went through LangChain the entire time. Its only two remaining callers were one-shot prompt→text calls: chat compaction and caption translation. Both now usecreateOpenScreenChatModel(...).invoke(), which already knew every provider.Removes
llm-call.ts,codex-session.ts(a bespoke chatgpt.com Responses dialect reachable only from it) andagent-provider-capabilities.ts, whose reasoning-effort matrix was duplicated insidedeep-agent/.Copilot is fixed, not just preserved. I flagged this as the functional risk of deleting
llm-call.ts. On inspection the risk ran the other way:chat-model.tsused the PAT directly with a comment saying the runtime-token refresh "can land as a follow-up" — so the main agent path was the broken one, and only the two side-features had it right.chat-model.tsnow exchanges the PAT for the short-lived runtime token, honours the base URL that exchange returns, and sends the editor-identifying headers the endpoint requires.Codex had the same bug, pointed the other way — caught in review.
accountIdwas threaded from both new call sites intoOpenScreenChatModelConfigand then read by nobody, while the deletedllm-call.ts:542setchatgpt-account-idfrom it and called that header required by chatgpt.com/backend-api. So the reroute silently broke caption translation and compaction for Codex accounts.tsccannot see this: an optional field that nothing reads still typechecks. The header is now wired at the same shared factory, so every caller benefits.Two more review findings in the same area:
caption-translatebuilt a model per batch. For Copilot that is a PAT → runtime-token exchange against api.github.com on every iteration; at batch size 40 a 400-segment transcript paid for ten of them. Built once, above the loop.isOpenRouterReasoningModelstrips theanthropic/slug prefix but notopenai/, and both vendor matchers are anchored at the start — soopenrouter+openai/gpt-5silently got no reasoning wiring at all. The deleted file stripped both and its deleted test asserted it. Fixed, and the tests for the module that survived are added back.extractDeltabecamemessageContentToTextand moved tochat-model.ts: it was exported fromdeep-agent/service.ts, whose top level pullslangchainand the whole agent-tools graph — a lot to import for ten lines of content flattening. Provider aliases (claude→ anthropic,gemini→ google) are now normalized once at thecreateOpenScreenChatModelentry point, which also givesnormalizeProviderIda caller again instead of leaving it dead.Schema and store
Four document fields —
agent,preview,export,history— were declared, defaulted, seeded in every test fixture, written on every edit, and read by nothing.preview.revisionwas bumped at eight sites and consumed only by tests asserting the bump happened. Gone, along with the ten schemas behind them.timelineOperationSchemastays: the review called it dead, butAxcutTimelineOperationhas 19 call sites. OnlyoperationSchema, which extended it with suggestion ops nothing dispatches, goes.Old projects are unaffected —
documentSchemais not strict, so zod strips the now-unknown keys.Seven
useTimelineactions had no callers.editCliplooked alive because it had its own test suite; the live Edit Clip modal actually callstl.updateClipSourceRange+tl.updateClipCrop, so the action and its tests both went.useTimeline.tsdrops 1192 → 970 lines.A follow-up sweep caught what the first pass missed:
migrate.tsstill built theagentenvelope on every migrated project (shipped code, not a fixture), and two fixtures still carried the removed fields. They survived for a reason worth knowing when reading the gate table above:tsconfig.jsonexcludes**/*.test.ts(x)and itsincludeis["src", "electron"], so no test file and nothing undertests/is typechecked — and vitest transpiles without checking.showTrimWaveformRemoving
TimelinePaneBodyleft this boolean declared, defaulted, persisted, migrated and history-tracked across five files with no reader and no UI able to set it. Removed, along with thesettings.timeline.*keys in all 13 locales — the separate top-leveltimelinenamespace (FloatingInspector, V4Timeline) is untouched.Old projects keep working:
migratespreadsinput.editorwholesale intolegacyEditorandlegacyEditorSchemaisz.object({}).passthrough(), so a storedshowTrimWaveformrides along inertly rather than failing the parse. Pinned with a test rather than assumed.Deferred, with reasons
Three items from the review are not here. Each needs something this PR cannot provide.
live.rsInspectorParams+ 31setNativeParamcalls). My review saidRightPanes' panes were unmounted; that was wrong —FloatingInspector.tsx:45mounts them, so all 31 call sites are live. Removing the second write path means proving every one of those keys survives the scene push, which needs the app driven control-by-control. Not something to ship on a green typecheck.LeftPanel.tsx:108doesstyles[palette]— computed class access that static grep cannot see. No test would catch a wrong deletion; it would just silently break visuals. Pure styling is not worth that risk.ModalShell→ radix,LangButton→ Popover. Carried over from PR 2 for the same reason: replacing hand-rolled focus/Escape/outside-click on eight live dialogs needs visual verification.The remaining Rust cleanups (
app.rs, thecompositor.rsresize path,run_standalone,PreviewTransport) are mechanical andcargo check-verifiable, but belong with the inspector work since they touch the same files.