f2f1cd9b6c
- Today's spend in the status bar and the Claude Code statusline is the
caller's own (`GET /api/pricing/cost?mine=1`, scope.ownSessionWhere), not
every user's sum for an admin or analyst.
- A screenshot pasted into a local claude pane is sent as Claude Code's own
image-paste key: Alt+V on Windows (Ctrl+V did nothing there), ^V elsewhere,
and only when the machine can read its clipboard (wl-paste/xclip + a
display on Linux), else it is uploaded (GET /api/run/native-paste {key}).
- A file manager's files pasted or dropped on a local browser go in by their
own paths, read from the OS clipboard or the file manager's selection
(server/lib/file-manager.js, POST /api/run/clipboard-files and
/selected-files): no upload, no size limit. A copied image file is pasted
by path, text that comes with a picture of it (spreadsheet cells) is
pasted as text, Windows paths go in as `C:/…` mentions.
- Tab titles for Snapshot, Artifacts, Files and Administration.
- An npm tool AgentHub installed under ~/.local is updated there, not by its
own updater into npm's global prefix.
72 lines
2.6 KiB
TypeScript
72 lines
2.6 KiB
TypeScript
/**
|
|
* @file nativePaste — Settings → Appearance → "Paste images natively": a
|
|
* per-browser preference in `localStorage` (`agenthub.terminal.nativePaste`,
|
|
* deliberately NOT synced to the account — it is about this browser's
|
|
* machine). On (the default), a `claude` pane in a local-mode dashboard opened
|
|
* from this machine's own browser gets an image paste as `^V`, so `claude`
|
|
* reads the desktop clipboard itself like a native terminal — nothing is
|
|
* uploaded or copied. Off, the image is uploaded like a remote browser's. An
|
|
* SSH tunnel's browser also reaches the dashboard by loopback, and its `^V`
|
|
* would read the SERVER's clipboard — that is what turning it off is for.
|
|
* The server must also be able to read its clipboard (`nativePasteWorks`: on
|
|
* Linux `wl-paste`/`xclip` and a display) — else the `^V` pasted nothing.
|
|
* On Windows Claude Code binds its image paste to Alt+V, not Ctrl+V
|
|
* (`nativePasteKey`): a `^V` there was silently ignored.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import { api } from "./api";
|
|
|
|
export const NATIVE_PASTE_KEY = "agenthub.terminal.nativePaste";
|
|
|
|
/** True unless this browser turned native image paste off. */
|
|
export function readNativePaste(): boolean {
|
|
try {
|
|
return window.localStorage.getItem(NATIVE_PASTE_KEY) !== "off";
|
|
} catch {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
export function writeNativePaste(on: boolean) {
|
|
try {
|
|
if (on) window.localStorage.removeItem(NATIVE_PASTE_KEY);
|
|
else window.localStorage.setItem(NATIVE_PASTE_KEY, "off");
|
|
} catch {
|
|
/* storage blocked — the default */
|
|
}
|
|
}
|
|
|
|
let works: boolean | null = null;
|
|
let asked: Promise<void> | null = null;
|
|
// Claude Code's image-paste chord on the dashboard's machine: Ctrl+V, but
|
|
// Alt+V on Windows, where a ^V reaches no binding and pastes nothing.
|
|
let key = "\x16";
|
|
|
|
/** Whether the dashboard's machine can hand a pane its clipboard, as last
|
|
* answered — false until it has (an upload then, which always works). The
|
|
* first call asks the server once per page. */
|
|
export function nativePasteWorks(): boolean {
|
|
asked ??= api.run
|
|
.nativePaste()
|
|
.then((r) => {
|
|
works = r.native === true;
|
|
key = r.key === "alt+v" ? "\x1bv" : "\x16";
|
|
})
|
|
.catch(() => void (works = false));
|
|
return works === true;
|
|
}
|
|
|
|
/** The bytes that make the pane's `claude` read its clipboard: ^V, or ESC v
|
|
* (Alt+V) on a Windows dashboard. */
|
|
export function nativePasteKey(): string {
|
|
return key;
|
|
}
|
|
|
|
/** Test seam: forget the server's answer. */
|
|
export function __resetNativePaste() {
|
|
works = null;
|
|
asked = null;
|
|
key = "\x16";
|
|
}
|