diff --git a/packages/coding-agent/src/modes/interactive/interactive-mode.ts b/packages/coding-agent/src/modes/interactive/interactive-mode.ts index cf8444f6..8d9a261d 100644 --- a/packages/coding-agent/src/modes/interactive/interactive-mode.ts +++ b/packages/coding-agent/src/modes/interactive/interactive-mode.ts @@ -1988,7 +1988,7 @@ export class InteractiveMode { return; } if (text === "/copy") { - this.handleCopyCommand(); + await this.handleCopyCommand(); this.editor.setText(""); return; } @@ -4064,7 +4064,7 @@ export class InteractiveMode { } } - private handleCopyCommand(): void { + private async handleCopyCommand(): Promise { const text = this.session.getLastAssistantText(); if (!text) { this.showError("No agent messages to copy yet."); @@ -4072,7 +4072,7 @@ export class InteractiveMode { } try { - copyToClipboard(text); + await copyToClipboard(text); this.showStatus("Copied last agent message to clipboard"); } catch (error) { this.showError(error instanceof Error ? error.message : String(error)); diff --git a/packages/coding-agent/src/utils/clipboard-native.ts b/packages/coding-agent/src/utils/clipboard-native.ts index e176d47c..bcdbdfa8 100644 --- a/packages/coding-agent/src/utils/clipboard-native.ts +++ b/packages/coding-agent/src/utils/clipboard-native.ts @@ -1,6 +1,7 @@ import { createRequire } from "module"; export type ClipboardModule = { + setText: (text: string) => Promise; hasImage: () => boolean; getImageBinary: () => Promise>; }; diff --git a/packages/coding-agent/src/utils/clipboard.ts b/packages/coding-agent/src/utils/clipboard.ts index 4c64b65d..eedcb0d5 100644 --- a/packages/coding-agent/src/utils/clipboard.ts +++ b/packages/coding-agent/src/utils/clipboard.ts @@ -1,6 +1,7 @@ import { execSync, spawn } from "child_process"; import { platform } from "os"; import { isWaylandSession } from "./clipboard-image.js"; +import { clipboard } from "./clipboard-native.js"; type NativeClipboardExecOptions = { input: string; @@ -16,11 +17,20 @@ function copyToX11Clipboard(options: NativeClipboardExecOptions): void { } } -export function copyToClipboard(text: string): void { +export async function copyToClipboard(text: string): Promise { // Always emit OSC 52 - works over SSH/mosh, harmless locally const encoded = Buffer.from(text).toString("base64"); process.stdout.write(`\x1b]52;c;${encoded}\x07`); + try { + if (clipboard) { + await clipboard.setText(text); + return; + } + } catch { + // Fall through to platform-specific clipboard tools. + } + // Also try native tools (best effort for local sessions) const p = platform(); const options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: ["pipe", "ignore", "ignore"] };