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>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
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);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user