Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
"@xterm/addon-webgl": "0.20.0-beta.194",
"@xterm/headless": "6.1.0-beta.195",
"@xterm/xterm": "6.1.0-beta.195",
"@xyflow/react": "^12.10.2",
"@xyflow/react": "^12.10.0",
"ai": "^6.0.0",
"ansi_up": "^6.0.6",
"better-auth": "1.5.6",
Expand Down Expand Up @@ -183,6 +183,7 @@
"graphql": "^16.13.2",
"graphql-language-service-cli": "^3.5.0",
"highlight.js": "^11.11.1",
"html-to-image": "^1.11.13",
"http-proxy": "^1.18.1",
"idb": "^8.0.3",
"idb-keyval": "^6.2.2",
Expand Down Expand Up @@ -225,6 +226,7 @@
"semver": "^7.7.3",
"shell-env": "^4.0.3",
"shell-quote": "^1.8.3",
"shiki": "^3.21.0",
"simple-git": "^3.30.0",
"streamdown": "2.5.0",
"strip-ansi": "^7.1.2",
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/src/main/lib/vscode-shim/api/terminal-shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ function getTerminalManager() {
try {
// Use dynamic import path that the bundler can resolve
// eslint-disable-next-line @typescript-eslint/no-var-requires
// biome-ignore lint: dynamic require for bundler compat
const mod = require("../../terminal") as {
// biome-ignore lint/suspicious/noExplicitAny: dynamic require for bundler compat
getDaemonTerminalManager: () => any;
};
// biome-ignore lint/suspicious/noExplicitAny: dynamic require for bundler compat
return mod.getDaemonTerminalManager() as any;
Comment thread
MocA-Love marked this conversation as resolved.
} catch {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ describe("ChatMessageList", () => {
});

expect(html).toContain("INLINE_SUBAGENT_EXECUTION_MESSAGE");
expect(html).not.toContain("SUBAGENT_EXECUTION_MESSAGE");
// Ensure non-inline variant is not rendered (INLINE_ prefix distinguishes them)
expect(html).not.toMatch(/(?<!INLINE_)SUBAGENT_EXECUTION_MESSAGE/);
expect(html).not.toContain("PENDING_PLAN_APPROVAL_MESSAGE");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function ChatSearch({
style={{ width: `min(${width}px, calc(100% - 4rem))` }}
>
{/* Left resize handle */}
{/* biome-ignore lint/a11y/noStaticElementInteractions: resize handle */}
<div
onMouseDown={handleResizeMouseDown}
className="absolute left-0 top-0 h-full w-1 cursor-ew-resize rounded-l opacity-0 transition-opacity hover:opacity-100 hover:bg-blue-500/40"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1284,13 +1284,20 @@ export const SETTINGS_ITEMS: SettingsItem[] = [
export function searchSettings(query: string): SettingsItem[] {
if (!query.trim()) return SETTINGS_ITEMS;

const q = query.toLowerCase();
return SETTINGS_ITEMS.filter(
(item) =>
item.title.toLowerCase().includes(q) ||
item.description.toLowerCase().includes(q) ||
item.keywords.some((kw) => kw.toLowerCase().includes(q)),
);
const words = query
.toLowerCase()
.split(/\s+/)
.filter((w) => w.length > 0);
if (words.length === 0) return SETTINGS_ITEMS;

return SETTINGS_ITEMS.filter((item) => {
const haystack = [
item.title.toLowerCase(),
item.description.toLowerCase(),
...item.keywords.map((kw) => kw.toLowerCase()),
].join(" ");
return words.every((word) => haystack.includes(word));
});
}

export function getMatchCountBySection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ export function PersistentTabRenderer({
if (
paneIds.some((id) => {
const type = panes[id]?.type;
return type === "webview" || type === "vscode-extension";
return (
type === "webview" ||
type === "vscode-extension" ||
type === "reference-graph"
);
})
) {
ids.add(tab.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function ChatSearch({
style={{ width: `min(${width}px, calc(100% - 4rem))` }}
>
{/* Left resize handle */}
{/* biome-ignore lint/a11y/noStaticElementInteractions: resize handle */}
<div
onMouseDown={handleResizeMouseDown}
className="absolute left-0 top-0 h-full w-1 cursor-ew-resize rounded-l opacity-0 transition-opacity hover:opacity-100 hover:bg-blue-500/40"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ export function CodeMirrorDiffViewer({
: [],
),
});
// biome-ignore lint/correctness/useExhaustiveDependencies: intentionally only track whether the request is available, not the callback reference itself, to avoid re-creating the plugin on every render
}, [inlineCompletionCompartmentB, hasInlineCompletionRequest]);

return <div ref={containerRef} className="h-full w-full overflow-auto" />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export function DiffViewerContextMenu({
setValue(_value: string) {},
revealPosition(_line: number, _column?: number) {},
getSelectionLines,
getCursorPosition() {
const sel = getSelectionLines();
return sel ? { line: sel.startLine, column: 1 } : null;
},
selectAll() {
const selection = window.getSelection();
if (!selection) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export function MarkdownSearch({
style={{ width: `min(${width}px, calc(100% - 0.5rem))` }}
>
{/* Left resize handle */}
{/* biome-ignore lint/a11y/noStaticElementInteractions: resize handle */}
<div
onMouseDown={handleResizeMouseDown}
className="absolute left-0 top-0 h-full w-1 cursor-ew-resize rounded-l opacity-0 transition-opacity hover:opacity-100 hover:bg-blue-500/40"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { memo, useEffect, useState } from "react";
import { highlightCode } from "./lib/highlighter";

interface CodePreviewProps {
code: string;
language: string;
startLine: number;
shikiTheme?: {
name: string;
type: string;
colors: object;
tokenColors: object[];
};
}

export const CodePreview = memo(function CodePreview({
code,
language,
startLine,
shikiTheme,
}: CodePreviewProps) {
const [highlightedHtml, setHighlightedHtml] = useState<string | null>(null);

useEffect(() => {
let cancelled = false;

async function highlight() {
try {
const html = await highlightCode(
code,
language || "typescript",
shikiTheme,
);
if (!cancelled) {
setHighlightedHtml(html);
}
} catch {
if (!cancelled) {
setHighlightedHtml(null);
}
}
}

highlight();

return () => {
cancelled = true;
};
}, [code, language, shikiTheme]);

const lines = code.split("\n");

if (highlightedHtml) {
return (
<div className="ref-graph-code-preview">
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: shiki output */}
<div dangerouslySetInnerHTML={{ __html: highlightedHtml }} />
</div>
);
}

// Fallback: plain text with line numbers
return (
<div className="ref-graph-code-preview">
<pre>
<code>
{lines.map((line, index) => {
const lineNum = startLine + index;
return (
<div key={`${lineNum}:${line}`} className="ref-graph-code-line">
<span className="ref-graph-code-line-number">{lineNum}</span>
<span className="ref-graph-code-line-content">
{line || " "}
</span>
</div>
);
})}
</code>
</pre>
</div>
);
});
Loading
Loading