The Markdown renderer began wrapping rendered blocks in div[data-markdown-block]
containers with display: contents, which collapsed the annotation layer's
bounding-box lookups and broke list/table special-case comment handling.
Flatten renderer-owned block wrappers to their actual rendered children while
preserving legacy top-level Markdown DOM and filtering inserted annotation
elements.
Regression introduced in PR #12460 (a776bd4d29, refactor: kilo compat for v1.17.9).
Add a Retry-state reflow test (isBusy() == true but not SessionState.Busy):
it must keep restarting the settle window toward the idle budget rather than
collapsing to REFLOW_PASSES. This is the only case that distinguishes
`is SessionState.Busy` from the old `isBusy()` predicate — verified it fails
(7 passes) if the gate is reverted to isBusy().
isBusy() is true for awaiting-permission/question, retry, and offline —
states recoverPending() can seed right after history load, where no deltas
arrive and a moving height genuinely means the panes are still settling.
Gating the settle-window shortcut on those states cut the reflow chain to
REFLOW_PASSES and reintroduced the crop-until-resize bug on exactly that
path. Gate only on SessionState.Busy (the streaming state) so the runaway
fix stays while blocked/retry/offline sessions keep their full settle window.
Add a Busy-state test that fails if the term is dropped or inverted.
invalidateCacheAndRepaint is UI-scoped, so firing it from the expansion
listener on every row made expand/collapse-all O(rows^2) to re-measure on
large branch diffs. Suppress the listener during bulk toggles and invalidate
once at the end, and register it after the initial expandAll. Per-row user
toggles still invalidate immediately.
Only treat a moving preferred height as an unsettled layout while the session
is idle. During streaming the height just tracks incoming content, so the
chain now counts its passes down instead of restarting the settle window,
settling in REFLOW_PASSES and handing off to the per-turn forgetTurn path
rather than risking a narrow crop-until-resize when the hard budget trips
mid-stream. Keep the budget as the idle backstop and cover it with a test
that drives an ever-growing child so the chain would spin without the cap.
A folder row hides its rolled-up badge while expanded, so its preferred
width now depends on expansion state. JTree only invalidates cached path
bounds on model changes, not on expand/collapse, so a collapsed folder could
keep its narrower expanded-state bounds and let the re-shown badge squeeze
the file name until an unrelated re-measure. Add a TreeExpansionListener that
invalidates the layout cache on toggle so the row re-measures immediately.
The reflow chain restarted its pass budget on every height change, so a
session that keeps streaming after open reset the budget each EDT cycle and
held the panel in a perpetual forgetAll()/re-measure loop, defeating the
width-keyed height cache. Add a hard total-pass budget that never resets so
the layout can still settle across a few height changes while capping the
work a streaming session can trigger. Covers the doLayout re-arm path with a
test that latches pendingReflow via a real turn at zero width.
Expanded folders already reveal child file badges, so showing the rolled-up folder total duplicates the visible counts. Keep aggregate badges only on collapsed folders while preserving file badges.
Opening a session could pin the transcript to a bottom computed from a zero-width measurement, cropping the last content until a toolwindow resize forced a re-measure. Reflow now no-ops until the panel has a real width and re-arms from doLayout once it does, so the transcript is always measured on-screen. The streaming path is untouched: pendingReflow is only set by a rebuild/clear that ran before layout, so the added doLayout check short-circuits during live updates.
- Replace generic 'multi-model API gateway' opening with punchier
differentiators: native Claude protocol, verifiable routing, one-key access
- Reviewer feedback: opening sentence didn't differentiate from other gateways
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(opencode): remote create_session fields, rename adoption, title sync
Extend create_session wire with optional agent/model/orgId (strict v1,
old-CLI degrade via client retry); claim org via session metadata
(metadata > KILO_ORG_ID > auth); adopt system session.renamed via
setTitle with consume-on-failure adoption marks; POST generation-aware
title changes through readiness (auto-titles marked by ensureTitle,
same-title Updated consumes pending adoptions).
* test(opencode): prove cancel→reprompt reaches idle; lock exit survivor
Item 14 CLI prove-it at SessionPrompt level: cancel-when-idle,
mid-stream, mid-tool, queued follow-up (deterministic queue wait), and
abortIntakes all settle to idle and reprompt completes — no production
hang found, no src change. Item 8: lock survivor session send_message
after sibling exit_cli.
* test(opencode): drop AppRuntime spy from create_session default test
Satisfies check-opencode-promise-facades while still proving the
production default forwards {agent, model, metadata} into
Session.Service.create.
* fix(opencode): bound rename marks, wire title report path, harden title tests
Kilobot review on #12704: adoption/auto-title maps now carry timestamps,
prune on write (60s TTL), and clear on Session.Event.Deleted (exported
clear/clearAll); the Updated watcher calls the interface
reportSessionTitle and fullSync passes preloaded info into meta();
ensureTitle's Kilo logic lives in kilocode/session/prompt.ts behind one
kilocode_change call site; title tests poll instead of sleeping and lock
mark-before-write plus clear-on-failure for real; meta() get-failure
org fallback covered via the _metaForTests seam.
* fix(kilo-sessions): mark bookkeeping before ingest sync, AppRuntime, test cleanup
Kilobot round 2 on #12704: consume rename/auto-title marks before the
ingest.sync network hop so the 60s TTL spans only the in-process hop;
call reportSessionTitle via AppRuntime.runPromise; auth cleanup back
under Effect.ensuring; restore the upstream blank line in prompt.ts so
the fork diff is only the kilocode_change call site.
* fix(kilo-sessions): keep title report self-healing if ingest.sync fails
Advance knownTitles only after successful sync; restore consumed rename/
auto-title marks on failure so the next Updated can re-POST. IIFE keeps
const-style outcome derivation.
* fix(kilo-sessions): optimistic knownTitles with full title-path rollback
Advance knownTitles before the network hop so concurrent Updated handlers
see sameTitle and cannot POST the same title with a wrong generated flag.
Restore prev + consumed marks when ingest.sync throws or reportSessionTitle
returns not-ok, so the next Updated retries the full self-healing path.
* style(kilo-sessions): prettier title Updated handler
* fix(kilo-sessions): preserve newer title state
* refactor(kilo-sessions): simplify title reporting tests
* fix(kilo-sessions): report unseeded title updates
* fix(kilo-sessions): consume unseeded title marks
* test(kilo-sessions): cover unseeded title marks
* test(kilo-sessions): unique ids for unseeded title tests
Thread a distinct session id through unseededMockSessionLayer so
session_share Storage records do not couple the three unseeded cases.
AI SDK 6 logs a console.warn when system messages appear in the
messages array. OpenCode prepends trusted system prompts to messages
in session/llm/request.ts, so the warning fires on every turn and
bleeds into the TUI frame.
Set allowSystemInMessages: true on the streamText call to acknowledge
the trusted internal system messages and prevent the warning from
corrupting terminal output. This also future-proofs against AI SDK 7,
which rejects system messages by default.