diff --git a/frontend/src/components/CodeBlock.tsx b/frontend/src/components/CodeBlock.tsx
index e9ad6549..45b5932a 100644
--- a/frontend/src/components/CodeBlock.tsx
+++ b/frontend/src/components/CodeBlock.tsx
@@ -7,14 +7,19 @@ import { CopyButton } from './CopyButton';
// IMPORTANT: Keep in sync with EXT_MAP in packages/protocol/src/language.ts
import bash from 'highlight.js/lib/languages/bash';
import c from 'highlight.js/lib/languages/c';
+import clojure from 'highlight.js/lib/languages/clojure';
import cmake from 'highlight.js/lib/languages/cmake';
import cpp from 'highlight.js/lib/languages/cpp';
import csharp from 'highlight.js/lib/languages/csharp';
import css from 'highlight.js/lib/languages/css';
+import dart from 'highlight.js/lib/languages/dart';
import diff from 'highlight.js/lib/languages/diff';
import dockerfile from 'highlight.js/lib/languages/dockerfile';
+import elixir from 'highlight.js/lib/languages/elixir';
+import erlang from 'highlight.js/lib/languages/erlang';
import go from 'highlight.js/lib/languages/go';
import graphql from 'highlight.js/lib/languages/graphql';
+import haskell from 'highlight.js/lib/languages/haskell';
import ini from 'highlight.js/lib/languages/ini';
import java from 'highlight.js/lib/languages/java';
import javascript from 'highlight.js/lib/languages/javascript';
@@ -25,30 +30,42 @@ import less from 'highlight.js/lib/languages/less';
import lua from 'highlight.js/lib/languages/lua';
import makefile from 'highlight.js/lib/languages/makefile';
import markdown from 'highlight.js/lib/languages/markdown';
+import nginx from 'highlight.js/lib/languages/nginx';
+import nix from 'highlight.js/lib/languages/nix';
+import objectivec from 'highlight.js/lib/languages/objectivec';
+import ocaml from 'highlight.js/lib/languages/ocaml';
import perl from 'highlight.js/lib/languages/perl';
import php from 'highlight.js/lib/languages/php';
+import powershell from 'highlight.js/lib/languages/powershell';
import protobuf from 'highlight.js/lib/languages/protobuf';
import python from 'highlight.js/lib/languages/python';
import r from 'highlight.js/lib/languages/r';
import ruby from 'highlight.js/lib/languages/ruby';
import rust from 'highlight.js/lib/languages/rust';
+import scala from 'highlight.js/lib/languages/scala';
import scss from 'highlight.js/lib/languages/scss';
import sql from 'highlight.js/lib/languages/sql';
import swift from 'highlight.js/lib/languages/swift';
import typescript from 'highlight.js/lib/languages/typescript';
+import wasm from 'highlight.js/lib/languages/wasm';
import xml from 'highlight.js/lib/languages/xml';
import yaml from 'highlight.js/lib/languages/yaml';
hljs.registerLanguage('bash', bash);
hljs.registerLanguage('c', c);
+hljs.registerLanguage('clojure', clojure);
hljs.registerLanguage('cmake', cmake);
hljs.registerLanguage('cpp', cpp);
hljs.registerLanguage('csharp', csharp);
hljs.registerLanguage('css', css);
+hljs.registerLanguage('dart', dart);
hljs.registerLanguage('diff', diff);
hljs.registerLanguage('dockerfile', dockerfile);
+hljs.registerLanguage('elixir', elixir);
+hljs.registerLanguage('erlang', erlang);
hljs.registerLanguage('go', go);
hljs.registerLanguage('graphql', graphql);
+hljs.registerLanguage('haskell', haskell);
hljs.registerLanguage('ini', ini);
hljs.registerLanguage('java', java);
hljs.registerLanguage('javascript', javascript);
@@ -59,17 +76,24 @@ hljs.registerLanguage('less', less);
hljs.registerLanguage('lua', lua);
hljs.registerLanguage('makefile', makefile);
hljs.registerLanguage('markdown', markdown);
+hljs.registerLanguage('nginx', nginx);
+hljs.registerLanguage('nix', nix);
+hljs.registerLanguage('objectivec', objectivec);
+hljs.registerLanguage('ocaml', ocaml);
hljs.registerLanguage('perl', perl);
hljs.registerLanguage('php', php);
+hljs.registerLanguage('powershell', powershell);
hljs.registerLanguage('protobuf', protobuf);
hljs.registerLanguage('python', python);
hljs.registerLanguage('r', r);
hljs.registerLanguage('ruby', ruby);
hljs.registerLanguage('rust', rust);
+hljs.registerLanguage('scala', scala);
hljs.registerLanguage('scss', scss);
hljs.registerLanguage('sql', sql);
hljs.registerLanguage('swift', swift);
hljs.registerLanguage('typescript', typescript);
+hljs.registerLanguage('wasm', wasm);
hljs.registerLanguage('xml', xml);
hljs.registerLanguage('yaml', yaml);
diff --git a/frontend/src/components/ToolPill.tsx b/frontend/src/components/ToolPill.tsx
index 4cb6e5f2..8d59038c 100644
--- a/frontend/src/components/ToolPill.tsx
+++ b/frontend/src/components/ToolPill.tsx
@@ -76,7 +76,7 @@ function RawInputDetail({
return null;
}
-/** Render tool result — syntax-highlighted for read/write tools, plain for others. */
+/** Render tool result with syntax highlighting when language is known. */
function ToolResult({
block,
onPopOut,
@@ -87,25 +87,17 @@ function ToolResult({
if (block.toolResult === undefined) return null;
const raw = block.rawInput;
- // For Read tool results, show the file content with syntax highlighting
- if (raw?.type === 'read' && block.toolResult) {
- return (
-
- onPopOut(raw.path!) : undefined}
- />
-
- );
- }
+ const isRead = raw?.type === 'read';
return (
-
Result
-
{block.toolResult}
+
onPopOut(raw.path!) : undefined}
+ />
);
}
diff --git a/frontend/src/components/__tests__/ToolPill.test.tsx b/frontend/src/components/__tests__/ToolPill.test.tsx
index 19bb74f3..eb31a287 100644
--- a/frontend/src/components/__tests__/ToolPill.test.tsx
+++ b/frontend/src/components/__tests__/ToolPill.test.tsx
@@ -174,7 +174,7 @@ describe('ToolPill', () => {
expect(container.querySelector('.code-block-highlight')).toBeTruthy();
});
- it('renders plain pre for non-read tools', () => {
+ it('renders CodeBlock for non-read tools', () => {
const block: FinishedBlock = {
blockId: 'b1',
blockType: 'tool_use',
@@ -187,8 +187,49 @@ describe('ToolPill', () => {
fireEvent.click(screen.getByRole('button'));
expect(screen.getByText('Result')).toBeTruthy();
- expect(container.querySelector('.tool-pill-pre')).toBeTruthy();
- expect(container.querySelector('.code-block-highlight')).toBeNull();
+ expect(container.querySelector('.code-block-highlight')).toBeTruthy();
+ });
+
+ it('renders bash-highlighted result for command tools', () => {
+ const block: FinishedBlock = {
+ blockId: 'b1',
+ blockType: 'tool_use',
+ content: '',
+ toolName: 'Bash',
+ toolInput: 'echo hello',
+ toolResult: 'hello',
+ rawInput: { type: 'command', command: 'echo hello', language: 'bash' },
+ };
+ const { container } = render(wrap());
+ fireEvent.click(screen.getByRole('button'));
+
+ // Result section uses CodeBlock with bash language
+ const codeBlocks = container.querySelectorAll('.code-block-highlight');
+ expect(codeBlocks.length).toBeGreaterThanOrEqual(2); // command input + result
+ expect(screen.getByText('Result')).toBeTruthy();
+ });
+
+ it('renders file-language-highlighted result for write tools', () => {
+ const block: FinishedBlock = {
+ blockId: 'b1',
+ blockType: 'tool_use',
+ content: '',
+ toolName: 'Write',
+ toolInput: 'test.ts',
+ toolResult: 'Wrote 50 chars',
+ rawInput: {
+ type: 'write',
+ path: '/src/test.ts',
+ contents: 'const x = 1;',
+ language: 'typescript',
+ },
+ };
+ const { container } = render(wrap());
+ fireEvent.click(screen.getByRole('button'));
+
+ // Both input and result render via CodeBlock
+ const codeBlocks = container.querySelectorAll('.code-block-highlight');
+ expect(codeBlocks.length).toBeGreaterThanOrEqual(2);
});
it('returns null when no toolResult', () => {
diff --git a/packages/protocol/__tests__/language.test.ts b/packages/protocol/__tests__/language.test.ts
index d5e89d4b..20a1438e 100644
--- a/packages/protocol/__tests__/language.test.ts
+++ b/packages/protocol/__tests__/language.test.ts
@@ -73,4 +73,57 @@ describe('languageFromPath', () => {
it('handles dotfiles with known extension', () => {
expect(languageFromPath('.bashrc')).toBeUndefined(); // no ext after dot
});
+
+ // New language coverage
+ it('detects Objective-C from .m', () => {
+ expect(languageFromPath('AppDelegate.m')).toBe('objectivec');
+ });
+
+ it('detects Dart from .dart', () => {
+ expect(languageFromPath('lib/main.dart')).toBe('dart');
+ });
+
+ it('detects Scala from .scala', () => {
+ expect(languageFromPath('src/Main.scala')).toBe('scala');
+ });
+
+ it('detects Haskell from .hs', () => {
+ expect(languageFromPath('src/Main.hs')).toBe('haskell');
+ });
+
+ it('detects OCaml from .ml', () => {
+ expect(languageFromPath('lib/parser.ml')).toBe('ocaml');
+ });
+
+ it('detects Clojure from .clj', () => {
+ expect(languageFromPath('src/core.clj')).toBe('clojure');
+ });
+
+ it('detects ClojureScript from .cljs', () => {
+ expect(languageFromPath('src/app.cljs')).toBe('clojure');
+ });
+
+ it('detects Elixir from .ex', () => {
+ expect(languageFromPath('lib/app.ex')).toBe('elixir');
+ });
+
+ it('detects Erlang from .erl', () => {
+ expect(languageFromPath('src/server.erl')).toBe('erlang');
+ });
+
+ it('detects PowerShell from .ps1', () => {
+ expect(languageFromPath('scripts/deploy.ps1')).toBe('powershell');
+ });
+
+ it('detects Nix from .nix', () => {
+ expect(languageFromPath('flake.nix')).toBe('nix');
+ });
+
+ it('detects WASM text from .wat', () => {
+ expect(languageFromPath('module.wat')).toBe('wasm');
+ });
+
+ it('detects nginx from .conf', () => {
+ expect(languageFromPath('/etc/nginx/nginx.conf')).toBe('nginx');
+ });
});
diff --git a/packages/protocol/src/language.ts b/packages/protocol/src/language.ts
index 46706fb1..22a72ba7 100644
--- a/packages/protocol/src/language.ts
+++ b/packages/protocol/src/language.ts
@@ -56,6 +56,25 @@ const EXT_MAP: Record = {
kts: 'kotlin',
swift: 'swift',
cs: 'csharp',
+ m: 'objectivec',
+ mm: 'objectivec',
+ dart: 'dart',
+ scala: 'scala',
+ sbt: 'scala',
+
+ // Functional
+ hs: 'haskell',
+ lhs: 'haskell',
+ ml: 'ocaml',
+ mli: 'ocaml',
+ clj: 'clojure',
+ cljs: 'clojure',
+ cljc: 'clojure',
+ edn: 'clojure',
+ ex: 'elixir',
+ exs: 'elixir',
+ erl: 'erlang',
+ hrl: 'erlang',
// Scripting
rb: 'ruby',
@@ -64,13 +83,21 @@ const EXT_MAP: Record = {
php: 'php',
r: 'r',
R: 'r',
+ ps1: 'powershell',
+ psm1: 'powershell',
+ psd1: 'powershell',
// Markup / Docs
md: 'markdown',
mdx: 'markdown',
tex: 'latex',
+
// Infrastructure
dockerfile: 'dockerfile',
+ conf: 'nginx',
+ nix: 'nix',
+ wat: 'wasm',
+ wast: 'wasm',
// SQL
sql: 'sql',