nanobot/desktop/src/preload.cts
Xubin Ren ab9f49970d
feat(desktop): polish desktop shell and shared WebUI surfaces (#4195)
* feat(desktop): add native host scaffold

* feat(webui): track turns and usage in gateway

* feat(webui): polish desktop chat experience

* feat(apps): add ArcGIS and Joplin logos

* feat(desktop): polish shell and shared surfaces

* fix(webui): avoid preview chips for glob references

* test: align CI expectations for token fallback

* feat(webui): preview prompt rail entries

* feat(webui): add prompt navigator drawer

* style(webui): refine prompt navigator placement

* style(webui): align prompt navigator with header actions

* style(webui): simplify prompt navigator header

* refactor(webui): clean thread resource refresh

* feat(desktop): add native reply notifications

* fix(webui): preserve desktop restart and replay state

* fix(desktop): harden gateway proxy startup

* fix(web): fall back when readability is unavailable

* fix(desktop): hide window instead of closing on macos

* fix(webui): unify desktop header actions

* fix(webui): simplify prompt history rows

* fix(desktop): log notification delivery failures

* chore(desktop): clean source package artifacts

* fix(cron): support one-time relative reminders

* fix(webui): reveal scroll button in place

* Revert "fix(cron): support one-time relative reminders"

This reverts commit 4c4661da120a3c7283e0768412bae48604e7390b.

* refactor(webui): extract token usage heatmap

* docs(desktop): clarify contributor guides

---------

Co-authored-by: chengyongru <2755839590@qq.com>
2026-06-06 19:49:33 +08:00

56 lines
2.2 KiB
TypeScript

import { contextBridge, ipcRenderer } from "electron";
type HostRuntimeInfo = {
surface: "native";
app_version: string;
engine_status: "starting" | "ready" | "restarting" | "stopped" | "crashed";
data_dir: string;
logs_dir: string;
config_path: string;
workspace_path: string;
python: string;
engine_transport?: "unix_socket";
};
type HostSocketEvent =
| { id: string; type: "open" }
| { data: string; id: string; type: "message" }
| { id: string; message: string; type: "error" }
| { code?: number; id: string; reason?: string; type: "close" };
contextBridge.exposeInMainWorld("nanobotHost", {
getRuntimeInfo: (): Promise<HostRuntimeInfo> =>
ipcRenderer.invoke("nanobot:get-runtime-info"),
restartEngine: (): Promise<void> => ipcRenderer.invoke("nanobot:restart-engine"),
pickFolder: (): Promise<string | null> => ipcRenderer.invoke("nanobot:pick-folder"),
openLogs: (): Promise<void> => ipcRenderer.invoke("nanobot:open-logs"),
exportDiagnostics: (): Promise<string> =>
ipcRenderer.invoke("nanobot:export-diagnostics"),
checkForUpdates: (): Promise<{ supported: boolean; message?: string }> =>
ipcRenderer.invoke("nanobot:check-for-updates"),
openSocket: (url: string): Promise<string> =>
ipcRenderer.invoke("nanobot:ws-connect", url),
sendSocket: (id: string, data: string): Promise<void> =>
ipcRenderer.invoke("nanobot:ws-send", id, data),
closeSocket: (id: string): Promise<void> =>
ipcRenderer.invoke("nanobot:ws-close", id),
onSocketEvent: (
listener: (event: HostSocketEvent) => void,
): (() => void) => {
const handler = (_event: Electron.IpcRendererEvent, payload: HostSocketEvent) => {
listener(payload);
};
ipcRenderer.on("nanobot:ws-event", handler);
return () => ipcRenderer.removeListener("nanobot:ws-event", handler);
},
onRuntimeStatus: (
listener: (status: HostRuntimeInfo["engine_status"]) => void,
): (() => void) => {
const handler = (_event: Electron.IpcRendererEvent, status: HostRuntimeInfo["engine_status"]) => {
listener(status);
};
ipcRenderer.on("nanobot:runtime-status", handler);
return () => ipcRenderer.removeListener("nanobot:runtime-status", handler);
},
});