diff --git a/ui-tui/src/app.tsx b/ui-tui/src/app.tsx
index b6ecf42e71..6cd3775d39 100644
--- a/ui-tui/src/app.tsx
+++ b/ui-tui/src/app.tsx
@@ -14,6 +14,7 @@ import { Thinking } from './components/thinking.js'
import { COMMANDS, HOTKEYS, INTERPOLATION_RE, MAX_CTX, PLACEHOLDERS, TOOL_VERBS, ZERO } from './constants.js'
import { type GatewayClient, type GatewayEvent } from './gatewayClient.js'
import * as inputHistory from './lib/history.js'
+import { writeOsc52Clipboard } from './lib/osc52.js'
import { upsert } from './lib/messages.js'
import { estimateRows, flat, fmtK, hasInterpolation, pick, userDisplay } from './lib/text.js'
import { DEFAULT_THEME, fromSkin, type Theme } from './theme.js'
@@ -661,7 +662,7 @@ export function App({ gw }: { gw: GatewayClient }) {
return true
}
- process.stdout.write(`\x1b]52;c;${Buffer.from(target.text).toString('base64')}\x07`)
+ writeOsc52Clipboard(target.text)
sys('copied to clipboard')
return true
diff --git a/ui-tui/src/components/markdown.tsx b/ui-tui/src/components/markdown.tsx
index 99f24a59b1..adee83ad28 100644
--- a/ui-tui/src/components/markdown.tsx
+++ b/ui-tui/src/components/markdown.tsx
@@ -8,50 +8,51 @@ function MdInline({ t, text }: { t: Theme; text: string }) {
const re = /(\[(.+?)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|`([^`]+)`|\*(.+?)\*|(https?:\/\/[^\s]+))/g
let last = 0
- let match: RegExpExecArray | null
- while ((match = re.exec(text)) !== null) {
- if (match.index > last) {
+ for (const m of text.matchAll(re)) {
+ const i = m.index ?? 0
+
+ if (i > last) {
parts.push(
- {text.slice(last, match.index)}
+ {text.slice(last, i)}
)
}
- if (match[2] && match[3]) {
+ if (m[2] && m[3]) {
parts.push(
- {match[2]}
+ {m[2]}
)
- } else if (match[4]) {
+ } else if (m[4]) {
parts.push(
- {match[4]}
+ {m[4]}
)
- } else if (match[5]) {
+ } else if (m[5]) {
parts.push(
- {match[5]}
+ {m[5]}
)
- } else if (match[6]) {
+ } else if (m[6]) {
parts.push(
- {match[6]}
+ {m[6]}
)
- } else if (match[7]) {
+ } else if (m[7]) {
parts.push(
- {match[7]}
+ {m[7]}
)
}
- last = match.index + match[0].length
+ last = i + m[0].length
}
if (last < text.length) {
diff --git a/ui-tui/src/lib/osc52.ts b/ui-tui/src/lib/osc52.ts
new file mode 100644
index 0000000000..01688aca6a
--- /dev/null
+++ b/ui-tui/src/lib/osc52.ts
@@ -0,0 +1,3 @@
+export function writeOsc52Clipboard(s: string): void {
+ process.stdout.write('\x1b]52;c;' + Buffer.from(s, 'utf8').toString('base64') + '\x07')
+}