Uh oh!
There was an error while loading. Please reload this page.
chore: sync upstream dev - #8
Conversation
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Brendan Allan <git@brendonovich.dev>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: Aiden Cline <rekram1-node@users.noreply.github.com>
Co-authored-by: Brendan Allan <git@brendonovich.dev>
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
There was a problem hiding this comment.
17 issues found across 179 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/web/src/content/docs/providers.mdx">
<violation number="1" location="packages/web/src/content/docs/providers.mdx:1518">
P3: The Modal section only documents the interactive `/connect` flow, but the `ModalPlugin` (`packages/opencode/src/plugin/modal/modal.ts`) also reads `process.env.MODAL_PROXY_TOKEN` directly, and Modal's own endpoint-integration docs explicitly show `export MODAL_PROXY_TOKEN=wk-<id>.ws-<secret>` for OpenCode. Other providers in this same document include an "Environment Variable" subsection. Consider adding a short note that the combined proxy token can alternatively be set via `MODAL_PROXY_TOKEN`, matching the surrounding provider sections.</violation>
</file>
<file name="packages/session-ui/src/components/message-part.tsx">
<violation number="1" location="packages/session-ui/src/components/message-part.tsx:587">
P2: Task error subtitles are no longer navigable when a host provides `onNavigateToSession` without `onSessionHref`: this change removes the pathname fallback, leaving `href` undefined, and `ToolErrorCard` never invokes the new click handler without an anchor. Retain a valid fallback href or update the error card to expose `onSubtitleClick` without requiring `href`.</violation>
</file>
<file name="packages/core/src/v1/config/provider.ts">
<violation number="1" location="packages/core/src/v1/config/provider.ts:24">
P2: Remote provider configurations using the newly accepted `interleaved` string or `false` values now parse successfully but are silently ignored, so custom reasoning fields cannot be configured and `false` cannot disable an inherited capability. Applying `config.interleaved` to `model.capabilities.interleaved` in the remote update/migration path would keep the widened schema contract effective.</violation>
</file>
<file name="packages/app/test-browser/prompt-attachments.test.ts">
<violation number="1" location="packages/app/test-browser/prompt-attachments.test.ts:127">
P3: Both V2 tests call dispose() only on the happy path, and `createPromptInputV2Attachments` registers global `document` dragover/dragleave/drop listeners via `makeEventListener` in onMount. If any assertion throws, the root is never disposed and these listeners leak into later tests; also test 1 awaits `duplicate.promise` before asserting, so if the duplicate path ever stops firing the test hangs instead of failing. Consider disposing the root in a finally/cleanup wrapper (and asserting before awaiting the resolver).</violation>
</file>
<file name="packages/app/src/pages/session/session-side-panel.tsx">
<violation number="1" location="packages/app/src/pages/session/session-side-panel.tsx:108">
P2: The new 240px minimum clamp on the file-tree width is applied to the side panel (panelWidth/treeWidth) but not to the session panel width, which still uses the raw layout.fileTree.width() (packages/app/src/pages/session.tsx:502, `calc(100% - ${layout.fileTree.width()}px)`). With the default width of 200 (DEFAULT_FILE_TREE_WIDTH) below the new min, the tree renders 240px wide while the chat content is sized as if only 200px are reserved, causing a ~40px overlap/overflow until the tree is actually dragged. Apply the same clamp in the session.tsx calc (or clamp once in layout) so both sides stay consistent.</violation>
<violation number="2" location="packages/app/src/pages/session/session-side-panel.tsx:108">
P3: The panel now renders the file tree at a minimum of 240px, but the persisted default/saved width (DEFAULT_FILE_TREE_WIDTH = 200 in context/layout.tsx) is still below that floor and is stored unclamped. For users on the default or an older saved width below 240, the displayed tree (240px) and the persisted width diverge until the next resize drag, where the stored value jumps to the new dragged position. Consider rounding the default/clamped width at the source (e.g., bumping DEFAULT_FILE_TREE_WIDTH to 240 or clamping inside `resize`) so the displayed and persisted widths stay consistent without requiring an extra resize.</violation>
</file>
<file name="packages/app/src/entry.tsx">
<violation number="1" location="packages/app/src/entry.tsx:82">
P2: External links stop working with a runtime `TypeError` in browsers that do not implement `URL.canParse`; using `new URL(value)` inside a `try/catch` (or guarding the method as the deep-link parser does) preserves the invalid-URL rejection without requiring this newer API.</violation>
</file>
<file name="packages/ui/src/v2/components/toast-v2.css">
<violation number="1" location="packages/ui/src/v2/components/toast-v2.css:10">
P2: Custom toasts composed with the exported `ToastV2.CloseButton` now lose their close-button layout and appearance because this grid layout only recognizes Sonner's `[data-close-button]`, while the component API emits `data-slot="toast-v2-close-button"`; retain a slot-compatible selector/layout (or emit the Sonner attribute) for the custom-toast path.</violation>
</file>
<file name="packages/ui/src/v2/components/toast-v2.tsx">
<violation number="1" location="packages/ui/src/v2/components/toast-v2.tsx:46">
P2: Toasts emitted before `ToastV2.Region` mounts are lost from the UI because the new `Toaster` does not replay entries already stored in solid-sonner's global queue. Mount the toaster before child effects can publish notifications or hydrate it from `toast.getToasts()` on mount.</violation>
<violation number="2" location="packages/ui/src/v2/components/toast-v2.tsx:108">
P2: Close-button consumers using Solid's tuple event-handler form (`onClick={[handler, data]}`) lose their callback because this wrapper only invokes function-valued handlers; forwarding the event through Solid or handling both `EventHandlerUnion` forms would preserve the button contract.</violation>
</file>
<file name="packages/console/app/src/routes/zen/util/provider/google.ts">
<violation number="1" location="packages/console/app/src/routes/zen/util/provider/google.ts:68">
P2: The console provider usage tests now fail for Gemini thinking responses because they still expect `outputTokens` to exclude the two reasoning tokens. The expectations should be updated to the normalized total and retain a regression case for the separate `reasoningTokens` field.</violation>
<violation number="2" location="packages/console/app/src/routes/zen/util/provider/google.ts:68">
P2: This change makes Google `outputTokens` include reasoning tokens (`candidatesTokenCount + thoughtsTokenCount`) while the helper also returns `reasoningTokens` separately. Downstream consumers assume outputTokens and reasoningTokens are disjoint: `trialLimiter.ts` sums `outputTokens + reasoningTokens`, and the usage breakdown in `usage-section.tsx` shows them as independent rows on top of the total output. As a result, reasoning/thinking tokens are now counted twice for Google models — inflating trial promo-token deductions and showing an inflated/duplicated output total in the usage UI. Consider keeping `outputTokens` as `candidatesTokenCount` (excluding thoughts) and reporting `reasoningTokens` separately, matching the anthropic convention and the consumers' expectations, rather than folding thoughts into outputTokens.</violation>
</file>
<file name="packages/session-ui/src/v2/components/session-review-v2.css">
<violation number="1" location="packages/session-ui/src/v2/components/session-review-v2.css:136">
P3: The new scroll-fade overlays use `position: absolute` on the tree slot's `::before`/`::after`, but the tree slot itself has no `position` set, so the containing block falls back to the nearest positioned ancestor, `[data-component="session-review-v2-sidebar-root"]` (`position: relative`, line 18). Consequence: `::before { top: 0 }` places the 16px top fade at the very top of the whole sidebar (over the header/filter) instead of the top of the scrollable tree, so the fade will render in the wrong spot once the tree is scrolled. Adding `position: relative` to the tree slot (mirroring the pattern already used at lines 330/357 in this file) would anchor both fades to the tree.</violation>
</file>
<file name="packages/session-ui/src/v2/components/session-review-v2.tsx">
<violation number="1" location="packages/session-ui/src/v2/components/session-review-v2.tsx:192">
P2: This switches the previously-documented global key handler from the rare `<`/`>` keys to `ArrowLeft`/`ArrowRight` on the whole `document`. Unlike the old keys, arrow keys are heavily used for horizontal scrolling (e.g. in horizontal diff panes), tree/combobox navigation, and widget focus movement. Because the handler calls `event.preventDefault()` and only skips `input, textarea, select`/contentEditable targets, pressing ArrowLeft/ArrowRight anywhere else in the app while the review pane is mounted and `hasDiffs`/files exist will switch the reviewed file and swallow the key press, potentially breaking horizontal scrolling and arrow-key navigation in the file tree and other tree/scroll widgets. Consider narrowing the trigger (e.g. only when the review pane or its tree has focus) or keeping the modifier-free behavior opt-in.</violation>
</file>
<file name="packages/desktop/src/main/windows.ts">
<violation number="1" location="packages/desktop/src/main/windows.ts:262">
P2: The new navigation policy only guards direct navigations and `window.open` calls. A full-page navigation that originates at the app's own URL but returns a server-side 302 redirect to an external http/https site is not caught by `will-navigate` (Electron does not emit that event for server redirects), so the app window could still be navigated away from the renderer origin to an external page instead of being routed through `openExternalURL`. Consider also guarding `will-redirect` (calling `event.preventDefault()` + `openExternalURL`) so redirect-based escapes are handled the same way.</violation>
</file>
<file name="packages/console/app/src/i18n/en.ts">
<violation number="1" location="packages/console/app/src/i18n/en.ts:344">
P3: The `go.faq.a5.used` and `go.faq.a5.noAgreement` translation keys were added to every locale dictionary but are never referenced in the code. The new model table only ever uses `go.faq.a5.notUsed` for the training column and `retention30`/`retention0` for retention, so these additions are currently dead. If they were meant for a future "used"/"agreement" state in the table, that's fine to keep, but the unused keys add translation debt across 18 files; consider wiring them up or dropping them until they're actually consumed.</violation>
</file>
<file name="packages/app/src/components/external-link.tsx">
<violation number="1" location="packages/app/src/components/external-link.tsx:13">
P2: The styling outcome for these external links is now nondeterministic. The component unconditionally prepends `text-text-strong` to every rendered link, while two callers in this change (dialog-connect-provider.tsx lines 841 and 970) intentionally pass `text-v2-text-text-base` to set the text color. Since both are Tailwind color utilities applied to the same element, the effective color depends on generated-CSS order rather than the caller's explicit class, so the intended muted/secondary color may not render. It would be more predictable to let the caller control the text color (e.g., only apply `underline`/`text-text-strong` when the caller does not supply its own text-color utility), or to provide a separate prop/bool for the base decoration instead of always injecting `text-text-strong`.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| return path.match(/\/session\/([^/?#]+)/)?.[1] | ||
| function sessionLink(id: string | undefined, href?: (id: string) => string | undefined) { | ||
| if (!id) return undefined | ||
| return href?.(id) |
There was a problem hiding this comment.
P2: Task error subtitles are no longer navigable when a host provides onNavigateToSession without onSessionHref: this change removes the pathname fallback, leaving href undefined, and ToolErrorCard never invokes the new click handler without an anchor. Retain a valid fallback href or update the error card to expose onSubtitleClick without requiring href.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/session-ui/src/components/message-part.tsx, line 587:
<comment>Task error subtitles are no longer navigable when a host provides `onNavigateToSession` without `onSessionHref`: this change removes the pathname fallback, leaving `href` undefined, and `ToolErrorCard` never invokes the new click handler without an anchor. Retain a valid fallback href or update the error card to expose `onSubtitleClick` without requiring `href`.</comment>
<file context>
@@ -583,29 +582,18 @@ function urls(text: string | undefined) {
- return path.match(/\/session\/([^/?#]+)/)?.[1]
+function sessionLink(id: string | undefined, href?: (id: string) => string | undefined) {
+ if (!id) return undefined
+ return href?.(id)
}
</file context>
| interleaved: Schema.optional( | ||
| Schema.Union([ | ||
| Schema.Literal(true), | ||
| Schema.Boolean, |
There was a problem hiding this comment.
P2: Remote provider configurations using the newly accepted interleaved string or false values now parse successfully but are silently ignored, so custom reasoning fields cannot be configured and false cannot disable an inherited capability. Applying config.interleaved to model.capabilities.interleaved in the remote update/migration path would keep the widened schema contract effective.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/v1/config/provider.ts, line 24:
<comment>Remote provider configurations using the newly accepted `interleaved` string or `false` values now parse successfully but are silently ignored, so custom reasoning fields cannot be configured and `false` cannot disable an inherited capability. Applying `config.interleaved` to `model.capabilities.interleaved` in the remote update/migration path would keep the widened schema contract effective.</comment>
<file context>
@@ -16,9 +21,10 @@ export const Model = Schema.Struct({
interleaved: Schema.optional(
Schema.Union([
- Schema.Literal(true),
+ Schema.Boolean,
+ InterleavedField,
Schema.Struct({
</file context>
| }), | ||
| ) | ||
| const open = createMemo(() => reviewOpen() || fileOpen()) | ||
| const fileTreeWidth = createMemo(() => Math.max(FILE_TREE_WIDTH_MIN, layout.fileTree.width())) |
There was a problem hiding this comment.
P2: The new 240px minimum clamp on the file-tree width is applied to the side panel (panelWidth/treeWidth) but not to the session panel width, which still uses the raw layout.fileTree.width() (packages/app/src/pages/session.tsx:502, calc(100% - ${layout.fileTree.width()}px)). With the default width of 200 (DEFAULT_FILE_TREE_WIDTH) below the new min, the tree renders 240px wide while the chat content is sized as if only 200px are reserved, causing a ~40px overlap/overflow until the tree is actually dragged. Apply the same clamp in the session.tsx calc (or clamp once in layout) so both sides stay consistent.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/src/pages/session/session-side-panel.tsx, line 108:
<comment>The new 240px minimum clamp on the file-tree width is applied to the side panel (panelWidth/treeWidth) but not to the session panel width, which still uses the raw layout.fileTree.width() (packages/app/src/pages/session.tsx:502, `calc(100% - ${layout.fileTree.width()}px)`). With the default width of 200 (DEFAULT_FILE_TREE_WIDTH) below the new min, the tree renders 240px wide while the chat content is sized as if only 200px are reserved, causing a ~40px overlap/overflow until the tree is actually dragged. Apply the same clamp in the session.tsx calc (or clamp once in layout) so both sides stay consistent.</comment>
<file context>
@@ -104,13 +105,14 @@ export function SessionSidePanel(props: {
}),
)
const open = createMemo(() => reviewOpen() || fileOpen())
+ const fileTreeWidth = createMemo(() => Math.max(FILE_TREE_WIDTH_MIN, layout.fileTree.width()))
const reviewTab = createMemo(() => isDesktop())
const panelWidth = createMemo(() => {
</file context>
| if (!URL.canParse(value)) return | ||
| const url = new URL(value) |
There was a problem hiding this comment.
P2: External links stop working with a runtime TypeError in browsers that do not implement URL.canParse; using new URL(value) inside a try/catch (or guarding the method as the deep-link parser does) preserves the invalid-URL rejection without requiring this newer API.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/src/entry.tsx, line 82:
<comment>External links stop working with a runtime `TypeError` in browsers that do not implement `URL.canParse`; using `new URL(value)` inside a `try/catch` (or guarding the method as the deep-link parser does) preserves the invalid-URL rejection without requiring this newer API.</comment>
<file context>
@@ -73,21 +72,17 @@ const notify: Platform["notify"] = async (title, description, href) => {
-const forward: Platform["forward"] = () => {
- window.history.forward()
+const openExternal: Platform["openExternal"] = (value) => {
+ if (!URL.canParse(value)) return
+ const url = new URL(value)
+ if (url.protocol !== "http:" && url.protocol !== "https:" && url.protocol !== "mailto:") return
</file context>
| if(!URL.canParse(value))return | |
| consturl=newURL(value) | |
| leturl: URL | |
| try{ | |
| url=newURL(value) | |
| }catch{ | |
| return | |
| } |
| flex-direction: column; | ||
| gap: 12px; | ||
| .toast-v2 { | ||
| display: grid; |
There was a problem hiding this comment.
P2: Custom toasts composed with the exported ToastV2.CloseButton now lose their close-button layout and appearance because this grid layout only recognizes Sonner's [data-close-button], while the component API emits data-slot="toast-v2-close-button"; retain a slot-compatible selector/layout (or emit the Sonner attribute) for the custom-toast path.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ui/src/v2/components/toast-v2.css, line 10:
<comment>Custom toasts composed with the exported `ToastV2.CloseButton` now lose their close-button layout and appearance because this grid layout only recognizes Sonner's `[data-close-button]`, while the component API emits `data-slot="toast-v2-close-button"`; retain a slot-compatible selector/layout (or emit the Sonner attribute) for the custom-toast path.</comment>
<file context>
@@ -1,114 +1,133 @@
- flex-direction: column;
- gap: 12px;
+.toast-v2 {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) 20px;
+ column-gap: 12px;
</file context>
| wk-<id>.ws-<secret> | ||
| ``` | ||
| 3. Run the `/connect` command, search for **Modal**, and enter the combined proxy token. |
There was a problem hiding this comment.
P3: The Modal section only documents the interactive /connect flow, but the ModalPlugin (packages/opencode/src/plugin/modal/modal.ts) also reads process.env.MODAL_PROXY_TOKEN directly, and Modal's own endpoint-integration docs explicitly show export MODAL_PROXY_TOKEN=wk-<id>.ws-<secret> for OpenCode. Other providers in this same document include an "Environment Variable" subsection. Consider adding a short note that the combined proxy token can alternatively be set via MODAL_PROXY_TOKEN, matching the surrounding provider sections.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/web/src/content/docs/providers.mdx, line 1518:
<comment>The Modal section only documents the interactive `/connect` flow, but the `ModalPlugin` (`packages/opencode/src/plugin/modal/modal.ts`) also reads `process.env.MODAL_PROXY_TOKEN` directly, and Modal's own endpoint-integration docs explicitly show `export MODAL_PROXY_TOKEN=wk-<id>.ws-<secret>` for OpenCode. Other providers in this same document include an "Environment Variable" subsection. Consider adding a short note that the combined proxy token can alternatively be set via `MODAL_PROXY_TOKEN`, matching the surrounding provider sections.</comment>
<file context>
@@ -1505,6 +1505,30 @@ To use Kimi K2 from Moonshot AI:
+ wk-<id>.ws-<secret>
+ ```
+
+3. Run the `/connect` command, search for **Modal**, and enter the combined proxy token.
+
+ ```txt
</file context>
| await duplicate.promise | ||
| expect(state.prompt).toHaveLength(1) | ||
| dispose() |
There was a problem hiding this comment.
P3: Both V2 tests call dispose() only on the happy path, and createPromptInputV2Attachments registers global document dragover/dragleave/drop listeners via makeEventListener in onMount. If any assertion throws, the root is never disposed and these listeners leak into later tests; also test 1 awaits duplicate.promise before asserting, so if the duplicate path ever stops firing the test hangs instead of failing. Consider disposing the root in a finally/cleanup wrapper (and asserting before awaiting the resolver).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/test-browser/prompt-attachments.test.ts, line 127:
<comment>Both V2 tests call dispose() only on the happy path, and `createPromptInputV2Attachments` registers global `document` dragover/dragleave/drop listeners via `makeEventListener` in onMount. If any assertion throws, the root is never disposed and these listeners leak into later tests; also test 1 awaits `duplicate.promise` before asserting, so if the duplicate path ever stops firing the test hangs instead of failing. Consider disposing the root in a finally/cleanup wrapper (and asserting before awaiting the resolver).</comment>
<file context>
@@ -85,6 +88,88 @@ describe("prompt attachment session ownership", () => {
+ await duplicate.promise
+
+ expect(state.prompt).toHaveLength(1)
+ dispose()
+ })
+})
</file context>
| [data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar-tree"]::before, | ||
| [data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar-tree"]::after { | ||
| content: ""; | ||
| position: absolute; |
There was a problem hiding this comment.
P3: The new scroll-fade overlays use position: absolute on the tree slot's ::before/::after, but the tree slot itself has no position set, so the containing block falls back to the nearest positioned ancestor, [data-component="session-review-v2-sidebar-root"] (position: relative, line 18). Consequence: ::before { top: 0 } places the 16px top fade at the very top of the whole sidebar (over the header/filter) instead of the top of the scrollable tree, so the fade will render in the wrong spot once the tree is scrolled. Adding position: relative to the tree slot (mirroring the pattern already used at lines 330/357 in this file) would anchor both fades to the tree.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/session-ui/src/v2/components/session-review-v2.css, line 136:
<comment>The new scroll-fade overlays use `position: absolute` on the tree slot's `::before`/`::after`, but the tree slot itself has no `position` set, so the containing block falls back to the nearest positioned ancestor, `[data-component="session-review-v2-sidebar-root"]` (`position: relative`, line 18). Consequence: `::before { top: 0 }` places the 16px top fade at the very top of the whole sidebar (over the header/filter) instead of the top of the scrollable tree, so the fade will render in the wrong spot once the tree is scrolled. Adding `position: relative` to the tree slot (mirroring the pattern already used at lines 330/357 in this file) would anchor both fades to the tree.</comment>
<file context>
@@ -109,10 +109,71 @@
+[data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar-tree"]::before,
+[data-component="session-review-v2-sidebar-root"] [data-slot="session-review-v2-sidebar-tree"]::after {
+ content: "";
+ position: absolute;
+ inset-inline: 0;
+ z-index: 10;
</file context>
| }), | ||
| ) | ||
| const open = createMemo(() => reviewOpen() || fileOpen()) | ||
| const fileTreeWidth = createMemo(() => Math.max(FILE_TREE_WIDTH_MIN, layout.fileTree.width())) |
There was a problem hiding this comment.
P3: The panel now renders the file tree at a minimum of 240px, but the persisted default/saved width (DEFAULT_FILE_TREE_WIDTH = 200 in context/layout.tsx) is still below that floor and is stored unclamped. For users on the default or an older saved width below 240, the displayed tree (240px) and the persisted width diverge until the next resize drag, where the stored value jumps to the new dragged position. Consider rounding the default/clamped width at the source (e.g., bumping DEFAULT_FILE_TREE_WIDTH to 240 or clamping inside resize) so the displayed and persisted widths stay consistent without requiring an extra resize.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/src/pages/session/session-side-panel.tsx, line 108:
<comment>The panel now renders the file tree at a minimum of 240px, but the persisted default/saved width (DEFAULT_FILE_TREE_WIDTH = 200 in context/layout.tsx) is still below that floor and is stored unclamped. For users on the default or an older saved width below 240, the displayed tree (240px) and the persisted width diverge until the next resize drag, where the stored value jumps to the new dragged position. Consider rounding the default/clamped width at the source (e.g., bumping DEFAULT_FILE_TREE_WIDTH to 240 or clamping inside `resize`) so the displayed and persisted widths stay consistent without requiring an extra resize.</comment>
<file context>
@@ -104,13 +105,14 @@ export function SessionSidePanel(props: {
}),
)
const open = createMemo(() => reviewOpen() || fileOpen())
+ const fileTreeWidth = createMemo(() => Math.max(FILE_TREE_WIDTH_MIN, layout.fileTree.width()))
const reviewTab = createMemo(() => isDesktop())
const panelWidth = createMemo(() => {
</file context>
| "go.faq.a5.retention": "Data retention", | ||
| "go.faq.a5.retention30": "30 days", | ||
| "go.faq.a5.retention0": "0 days", | ||
| "go.faq.a5.used": "Used", |
There was a problem hiding this comment.
P3: The go.faq.a5.used and go.faq.a5.noAgreement translation keys were added to every locale dictionary but are never referenced in the code. The new model table only ever uses go.faq.a5.notUsed for the training column and retention30/retention0 for retention, so these additions are currently dead. If they were meant for a future "used"/"agreement" state in the table, that's fine to keep, but the unused keys add translation debt across 18 files; consider wiring them up or dropping them until they're actually consumed.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/console/app/src/i18n/en.ts, line 344:
<comment>The `go.faq.a5.used` and `go.faq.a5.noAgreement` translation keys were added to every locale dictionary but are never referenced in the code. The new model table only ever uses `go.faq.a5.notUsed` for the training column and `retention30`/`retention0` for retention, so these additions are currently dead. If they were meant for a future "used"/"agreement" state in the table, that's fine to keep, but the unused keys add translation debt across 18 files; consider wiring them up or dropping them until they're actually consumed.</comment>
<file context>
@@ -336,8 +336,21 @@ export const dict = {
+ "go.faq.a5.retention": "Data retention",
+ "go.faq.a5.retention30": "30 days",
+ "go.faq.a5.retention0": "0 days",
+ "go.faq.a5.used": "Used",
+ "go.faq.a5.notUsed": "Not used",
+ "go.faq.a5.noAgreement": "No agreement",
</file context>
Issue for this PR
Closes#7
Type of change
What does this PR do?
Merges
upstream/devat1882c33827cf0ce5c948b69ab5a87ed8f6790cf8intointegration/opencode-devwithout rewriting upstream or fork commit history. This keeps the upstream synchronization separate from subsequent feature work.The merge completed without manual conflict resolution. The fork's six integration-only commits remain in history.
How did you verify your code works?
bun typecheckinpackages/core: passed.bun typecheckinpackages/opencode: passed.bun test test/config/provider.test.tsinpackages/core: 3 passed.bun test test/provider/provider.test.ts test/mcp/transport.test.tsinpackages/opencode: 101 passed.bun turbo typecheck: 30 participating packages passed.git diff --check HEAD^1..HEAD: passed.upstream/devrevision.Screenshots / recordings
Not applicable: repository history synchronization has no UI change.
Checklist