Skip to content

Commit ed0ce07

Browse files
committed
feat(cli): make kimi web and rotate-token access URLs clickable
1 parent 66f611a commit ed0ce07

4 files changed

Lines changed: 21 additions & 7 deletions

File tree

.changeset/clickable-web-urls.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@moonshot-ai/kimi-code": patch
3+
---
4+
5+
Make `kimi web` and `kimi web rotate-token` access URLs clickable in supported terminals.

apps/kimi-code/src/cli/sub/web/rotate-token.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type { Command } from 'commander';
1212

1313
import { darkColors } from '#/tui/theme/colors';
1414
import { getDataDir } from '#/utils/paths';
15+
import { toTerminalHyperlink } from '#/utils/terminal-hyperlink';
1516

1617
import { accessUrlLines, splitTokenFragment } from './access-urls';
1718

@@ -39,13 +40,15 @@ export function registerRotateTokenCommand(server: Command): void {
3940
const instance = await getLiveServerInstance();
4041
if (instance !== undefined) {
4142
for (const { label, url: href } of accessUrlLines(instance.host, instance.port, token)) {
42-
// De-emphasize the `#token=…` fragment so the host/port stands out.
43+
// De-emphasize the `#token=…` fragment so the host/port stands out,
44+
// and wrap the whole URL in an OSC 8 terminal hyperlink for
45+
// click-to-open support in supported terminals.
4346
const [base, frag] = splitTokenFragment(href);
44-
const rendered =
47+
const display =
4548
frag === ''
4649
? chalk.hex(darkColors.accent)(base)
4750
: chalk.hex(darkColors.accent)(base) + chalk.hex(darkColors.textDim)(frag);
48-
process.stdout.write(` ${chalk.dim(label)}${rendered}\n`);
51+
process.stdout.write(` ${chalk.dim(label)}${toTerminalHyperlink(display, href)}\n`);
4952
}
5053
}
5154
} catch (error) {

apps/kimi-code/src/cli/sub/web/run.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getNativeWebAssetsDir } from '#/native/web-assets';
2121
import { darkColors } from '#/tui/theme/colors';
2222
import { openUrl as defaultOpenUrl } from '#/utils/open-url';
2323
import { getDataDir } from '#/utils/paths';
24+
import { toTerminalHyperlink } from '#/utils/terminal-hyperlink';
2425

2526
import { initializeServerTelemetry } from '../../telemetry';
2627
import {
@@ -200,7 +201,8 @@ function formatReadyLine(
200201
const notice = dangerousBypassAuth
201202
? `${formatDangerNoticeLines().join('\n')}\n`
202203
: '';
203-
return `${notice}Kimi server: ${buildOpenableUrl(origin, token)}\n`;
204+
const href = buildOpenableUrl(origin, token);
205+
return `${notice}Kimi server: ${toTerminalHyperlink(href, href)}\n`;
204206
}
205207

206208
/**
@@ -342,10 +344,12 @@ export function formatReadyBanner(
342344
const label = (text: string): string => chalk.bold.hex(darkColors.textDim)(text);
343345
const url = (text: string): string => chalk.hex(darkColors.accent)(text);
344346
// Render the `#token=…` fragment in a de-emphasized gray so the host/port
345-
// stands out while the full URL stays selectable for copying.
347+
// stands out while the full URL stays selectable for copying. Wrap the whole
348+
// line in an OSC 8 terminal hyperlink so supported terminals can click to open.
346349
const urlWithDimToken = (href: string): string => {
347350
const [base, frag] = splitTokenFragment(href);
348-
return frag === '' ? url(base) : url(base) + dim(frag);
351+
const display = frag === '' ? url(base) : url(base) + dim(frag);
352+
return toTerminalHyperlink(display, href);
349353
};
350354

351355
const port = Number(new URL(origin).port);

apps/kimi-code/test/cli/web/web.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ vi.mock('node:child_process', async (importOriginal) => {
2727
});
2828

2929
function stripAnsi(text: string): string {
30-
return text.replaceAll(/\[[0-9;]*m/g, '');
30+
return text
31+
.replaceAll(/\[[0-9;]*m/g, '')
32+
.replaceAll(/]8;[^]*/g, '');
3133
}
3234

3335
function makeProgram(): Command {

0 commit comments

Comments
 (0)