Skip to content

Commit c80ffd0

Browse files
committed
fix: preserve transient mermaid fences and empty capabilities
Keep createMarkdownTheme.transient on the theme object so streaming markdown does not draw mermaid art early. Align copy-button color with accent. Expect an empty capabilities list after managed surface strip.
1 parent db87dfd commit c80ffd0

3 files changed

Lines changed: 10 additions & 33 deletions

File tree

‎apps/pythinker-code/src/tui/theme/pi-tui-theme.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export function createMarkdownTheme(options?: { transient?: boolean }): Markdown
2828
const stripHash = (text: string): string => text.replace(HEADING_HASH_PREFIX, '$1');
2929

3030
return {
31+
transient,
3132
heading: (text) => chalk.bold.hex(currentTheme.color('textStrong'))(stripHash(text)),
3233
link: (text) => chalk.hex(currentTheme.color('primary'))(text),
3334
linkUrl: (text) => chalk.hex(currentTheme.color('textMuted'))(text),

‎apps/pythinker-code/test/tui/components/markdown/markdown.test.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { afterEach, describe, expect, it, vi } from 'vitest';
55

66
import { Markdown } from '#/tui/components/markdown/markdown';
77
import { darkColors, lightColors } from '#/tui/theme/colors';
8+
import { currentTheme } from '#/tui/theme';
89
import { createMarkdownTheme } from '#/tui/theme/pi-tui-theme';
9-
import { currentTheme } from '#/tui/theme/theme';
1010
import {
1111
setMarkdownAltScreenActive,
1212
setMarkdownMermaidMode,
@@ -352,7 +352,11 @@ describe('Markdown mermaid copy source', () => {
352352
const line = lastLine(makeCopyable());
353353

354354
expect(strip(line)).toContain('[Copy Source]');
355-
expect(line).toContain('38;2;91;192;190');
355+
const accent = currentTheme.color('accent').replace('#', '');
356+
const r = Number.parseInt(accent.slice(0, 2), 16);
357+
const g = Number.parseInt(accent.slice(2, 4), 16);
358+
const b = Number.parseInt(accent.slice(4, 6), 16);
359+
expect(line).toContain(`38;2;${r};${g};${b}`);
356360
expect(line).not.toContain('48;2;');
357361
expect(line).not.toContain('[1m');
358362
});

‎packages/agent-gateway/test/capabilities.test.ts‎

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,14 @@ describe('server-v2 /api/v1 capabilities', () => {
3030
return { status: res.status, body: (await res.json()) as Envelope<T> };
3131
}
3232

33-
it('lists both built-in capabilities with the documented shape', async () => {
33+
it('lists zero built-in capabilities after managed surface strip', async () => {
3434
const { body } = await getJson<unknown>('/api/v1/capabilities');
3535
expect(body.code).toBe(0);
3636
const parsed = listCapabilitiesResponseSchema.parse(body.data);
37-
const ids = parsed.capabilities.map((c) => c.id).toSorted();
38-
expect(ids).toEqual(['pythinker-cu', 'pythinker-webbridge']);
39-
for (const capability of parsed.capabilities) {
40-
expect(capabilityStatusSchema.parse(capability)).toBeTruthy();
41-
expect(capability.install.running).toBe(false);
42-
}
43-
const pythinkerCu = parsed.capabilities.find((c) => c.id === 'pythinker-cu');
44-
if (process.platform === 'darwin' || (process.platform === 'win32' && process.arch === 'x64')) {
45-
expect(pythinkerCu?.supported).toBe(true);
46-
} else {
47-
expect(pythinkerCu?.supported).toBe(false);
48-
expect(pythinkerCu?.state).toBe('unsupported');
49-
}
50-
const webbridge = parsed.capabilities.find((c) => c.id === 'pythinker-webbridge');
51-
expect(webbridge?.supported).toBe(true);
52-
expect(webbridge?.steps.find((s) => s.id === 'skill')?.state).toBe('missing');
53-
expect(webbridge?.steps.find((s) => s.id === 'extension')?.optional).toBe(true);
37+
expect(parsed.capabilities).toEqual([]);
5438
});
5539

56-
it('gets a single capability and 40418s on an unknown id', async () => {
57-
const { body } = await getJson<unknown>('/api/v1/capabilities/pythinker-webbridge');
58-
expect(body.code).toBe(0);
59-
expect(capabilityStatusSchema.parse(body.data).id).toBe('pythinker-webbridge');
60-
40+
it('40418s on an unknown capability id', async () => {
6141
const missing = await getJson<unknown>('/api/v1/capabilities/nope');
6242
expect(missing.body.code).toBe(40418);
6343
expect(missing.body.data).toBeNull();
@@ -74,12 +54,4 @@ describe('server-v2 /api/v1 capabilities', () => {
7454
const bogus = await postJson<unknown>('/api/v1/capabilities/pythinker-cu:uninstall');
7555
expect(bogus.body.code).toBe(40001);
7656
});
77-
78-
it.skipIf(process.platform === 'darwin' || (process.platform === 'win32' && process.arch === 'x64'))(
79-
'rejects pythinker-cu install on unsupported platforms with 40925',
80-
async () => {
81-
const { body } = await postJson<unknown>('/api/v1/capabilities/pythinker-cu:install');
82-
expect(body.code).toBe(40925);
83-
},
84-
);
8557
});

0 commit comments

Comments
 (0)