* fix(gateway): sanitize unsupported regex lookarounds
* fix(cli): sanitize tool schemas across providers
* fix(cli): use direct schema type dependency
The Google AI Studio API keys page (aistudio.google.com/api-keys)
redirects to Google account sign-in for unauthenticated requests, so
lychee sees a 302 and fails the link check. The URL is correct and is
the one Google's own Gemini API key documentation links to, so exclude
it from the link checker like the already-excluded console.cloud.google.com.
The hardcoded team list in packages/script/src/index.ts (Script.team)
and its duplicate in script/changelog-github.cjs had drifted apart and
both included accounts no longer in the Kilo-Org. This list is consumed
by script/raw-changelog.ts to strip 'Thanks @user!' attribution for
internal members, so stale entries let departed contributors keep
receiving credit while active ones still get thanked.
Reconcile both copies against the live org-member and repo-collaborator
rosters: remove departed humans, add missing active accounts, keep all
bot/CI accounts, and alphabetize for parity between the two files.
McpTool's formattedOutput() only fences output when it parses as JSON;
non-JSON output (the common case for a tool returning prose or
markdown) is fed straight into the real Markdown renderer, which does
parse [label](url) into a link, hiding the URL half. toolText() was
treating all non-bash tool output the same as bash's (never stripped),
which reintroduced the exact mismatch this PR fixes for JSON-shaped
output on plain-text results. Now mirrors McpTool's own JSON.parse-or-
fallback branching: JSON output stays raw (rendered fenced, literal),
non-JSON output gets the same link stripping as text/reasoning chunks.
(cherry picked from commit e33a1a7ebc)
WARNING: stripMarkdownLinkUrls was applied to tool/bash chunks too.
Bash output is rendered via escapeHtml + syntax highlighting -- never
through Markdown -- and the generic/MCP fallback renderer wraps its
output in a fenced code block before it ever reaches Markdown. Both
show link-like `[x](y)` text literally, so stripping it searched text
that no longer matched what's on screen (e.g. a shell command that
echoes/cats a markdown link, or JSON with bracket+paren sequences).
Stripping is now only applied to text/reasoning chunks, which do go
through the real Markdown renderer.
Reverted the auto-load-history cap/opt-in from the previous commit: a
partial match count while some history remains unsearched can actively
mislead a user into the wrong conclusion, which outweighs the cost of
loading a long session's full history. Search now simply auto-loads
the entire session before reporting a final count/"No results", same
as originally requested. Revisit with a cap or lazy/incremental search
strategy in a follow-up PR if this proves too slow/expensive in
practice on very long sessions.
(cherry picked from commit f0ff4d3066)
User messages render via UserMessageDisplay/HighlightedText
(message-part.tsx), which never parses markdown at all -- [label](url)
always shows literally, brackets and all, unlike assistant text/
reasoning/tool content which goes through the real Markdown renderer.
Stripping link URLs there collapsed two genuinely visible literal
occurrences into one. Stripping now only applies to non-user rows.
(cherry picked from commit 097124d7ed)
High: visible tool content (e.g. a todowrite checklist) could be
highlighted in the DOM while the counter still reported "No results"
and navigation was disabled. toolText() previously only indexed
state.title for non-bash tools, independently of what
transcript-search-highlight.ts actually scans in the DOM. Rewrote it
to recursively collect every string leaf from state.input/state.metadata
plus state.output for any tool, so matching and highlighting draw from
one canonical, much more comprehensive notion of "the tool's text"
instead of two divergent ones. read/glob/grep/list remain excluded --
kilo-ui's context-tool-results.tsx confirmed they never render raw
input/output text, even expanded, so including it there would
reintroduce the same class of mismatch for those tools.
High: search only covered the initially-loaded message page (80
messages), silently missing older history in long sessions. MessageList
now auto-requests older pages (session.loadOlderMessages()) while a
search is active with a non-empty query, looping via reactivity on
hasOlderMessages()/loadingOlderMessages() until history is exhausted.
A new searchingHistory state surfaces this to the widget, which shows
"Searching earlier messages..." and withholds a final "No results"
until the whole session has actually been searched (a live match count
still updates progressively as pages load).
Medium: whole-word matching used plain \b, which only treats ASCII
letters/digits/underscore as word characters and silently breaks for
Cyrillic, Arabic, CJK, and similar text. Replaced with Unicode-aware
boundary lookarounds using \p{L}/\p{M}/\p{N} property escapes, with the
`u` flag applied to every compiled pattern.
New chat.search.searchingHistory i18n key added across all 20 locales.
(cherry picked from commit 47d4ebd73b)
errorText() previously only matched ErrorDisplay.tsx's default card body
(unwrapped error.data.message). It now mirrors the component's full
Switch/Match classification (parseAssistantError/parseProviderAuthError,
isUnauthorizedPaidModelError/isUnauthorizedPromotionLimitError, and the
same canAuth() gate used to decide whether the provider-auth prompt or
the default card renders), so search text matches whichever variant is
actually shown: paid-model, promotion-limit, provider-auth (including
the ChatGPT oauth copy), or the default unwrapped message.
(cherry picked from commit 7e9a984f08)
- Wrap StoryProviders in TranscriptSearchProvider - fixes the failing
Visual Regression check (5 stories threw because TaskHeader/MessageList
call useTranscriptSearch() unconditionally with no fallback context).
- Reset the whole search widget when the current session changes so
stale query/matches don't linger across a session switch.
- Search error rows via the same unwrapped error.data.message shown by
ErrorDisplay, instead of the internal, never-rendered error.name.
- Reorder bash tool search text to description -> command -> output,
matching the actual DOM order in shell-rolling-results.tsx, so
occurrence numbering lines up with what gets highlighted.
- Surface invalid regular expressions explicitly instead of leaving them
indistinguishable from "no matches".
- Track both legs of the chained highlight rAF so cleanup can cancel
either one, preventing a stray callback from touching state after
unmount.
- Widen Escape/Enter handling to the whole search widget, not just the
text input.
- Add an aria-label to the search input and type the search provider's
children as ParentComponent instead of any.
New chat.search.invalidRegex i18n key added across all 20 locales.
(cherry picked from commit 64dd8e3a2b)
Add a search widget to the VS Code sidebar and editor-tab chat header.
Clicking the header search icon opens an inline, VS Code-style find bar
with match case, whole word, and regular expression options. Matches are
highlighted across the transcript via the CSS Custom Highlight API, and
next/previous controls step through each occurrence, recentering only
when a match drifts near the viewport edge.
All user-facing strings are localized across the 20 supported locales.
(cherry picked from commit 3f8b4443c3)
The hardcoded team list in packages/script/src/index.ts (Script.team)
and its duplicate in script/changelog-github.cjs had drifted apart and
both included accounts no longer in the Kilo-Org. This list is consumed
by script/raw-changelog.ts to strip 'Thanks @user!' attribution for
internal members, so stale entries let departed contributors keep
receiving credit while active ones still get thanked.
Reconcile both copies against the live org-member and repo-collaborator
rosters: remove departed humans, add missing active accounts, keep all
bot/CI accounts, and alphabetize for parity between the two files.
* fix(cli): resolve latest CLI release when install script hits non-CLI tag
The GitHub releases/latest endpoint can point to non-CLI releases
(e.g., jetbrains/v7.0.4), whose tag prefix doesn't match the existing
version regex. Query the paginated releases endpoint, pick the first
tag starting with 'v', and use that version for both display and the
download URL instead of trusting releases/latest.
Closes#12125
* fix(cli): select stable installer release
---------
Co-authored-by: marius-kilocode <marius@kilocode.ai>
Move the five legacy-migration webview message cases out of the large
onDidReceiveMessage switch into an early-return handler, matching the
existing routeEarlyMessage/handleMemoryMessage pattern. The switch's
async arrow function exceeded the complexity cap of 150 after the
recent main merge; extracting these cases lowers it below the cap.
Gemma 4 models (gemma-4-31b-it, gemma-4-26b-a4b-it) don't support the
thinkingLevel parameter. When models.dev metadata reports reasoning
capability for these models, the variants function generates
thinkingConfig with thinkingLevel entries that cause 400
INVALID_ARGUMENT errors from the Google AI Studio API.
Add an early return for gemma model IDs before the thinkingLevel default
branch, matching the pattern used by grok (line 728) and other
non-reasoning models.
Closes#12063