@pablopunk/webr 0.3.17 → 0.3.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/_astro/{App.L92siqEU.css → App.DroHhgBz.css} +1 -1
- package/dist/client/_astro/App.Ho8QFCCQ.js +4 -0
- package/dist/server/chunks/{App_HQFrnQj9.mjs → App_Ch7GmWXO.mjs} +230 -60
- package/dist/server/chunks/{_id__Bhub9N4a.mjs → _id__Ba8WQNWp.mjs} +1 -1
- package/dist/server/chunks/{_tab__DJZZZJmr.mjs → _tab__BEI4cb-5.mjs} +1 -1
- package/dist/server/chunks/{new_BWEe2CpA.mjs → new_CM9fzfm6.mjs} +1 -1
- package/dist/server/chunks/{settings_D6oHTDVP.mjs → settings_D4hVr2qz.mjs} +1 -1
- package/dist/server/entry.mjs +5 -5
- package/package.json +1 -1
- package/server/update/service.ts +5 -0
- package/src/server/host.ts +1 -0
- package/src/shared/update.ts +1 -1
- package/dist/client/_astro/App.D4o88FA4.js +0 -4
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { S as createAstro, f as renderHead, i as renderComponent, m as createRenderInstruction, p as addAttribute, s as renderSlot, u as renderTemplate } from "./server_dfdLOyV2.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BnrQvXXD.mjs";
|
|
3
3
|
import { ViewTransition, createContext, memo, useCallback, useContext, useDeferredValue, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
-
import { Archive, ArchiveRestore, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bot, Check, ChevronDown, ChevronRight, Circle, CircleAlert, CircleArrowUp, CircleCheck, CircleHelp, Command, Copy, Cpu, FileText, Folder, FolderTree, GitBranch, ImagePlus, ImageUp, LayoutList, LoaderCircle, MessageCircleQuestion, Mic, Monitor, Moon, PanelLeft, PanelLeftClose, PanelLeftOpen, Pencil, Plus, Search, Server, Settings2, Square, SquarePen, SquareTerminal, Sun, TerminalSquare, Trash2, TriangleAlert, X } from "lucide-react";
|
|
4
|
+
import { Archive, ArchiveRestore, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bot, Check, ChevronDown, ChevronRight, Circle, CircleAlert, CircleArrowUp, CircleCheck, CircleHelp, Command, Copy, Cpu, ExternalLink, FileText, Folder, FolderTree, GitBranch, ImagePlus, ImageUp, LayoutList, LoaderCircle, MessageCircleQuestion, Mic, Monitor, Moon, PanelLeft, PanelLeftClose, PanelLeftOpen, Pencil, Plus, Search, Server, Settings2, Square, SquarePen, SquareTerminal, Sun, TerminalSquare, Trash2, TriangleAlert, X } from "lucide-react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
7
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { Tooltip } from "@base-ui/react/tooltip";
|
|
9
9
|
import { BotAvatar, botAvatarTypes } from "bot-avatars";
|
|
10
10
|
import { Combobox } from "@base-ui/react/combobox";
|
|
11
|
-
import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query";
|
|
11
|
+
import { QueryClient, QueryClientProvider, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
12
12
|
import { Dialog } from "@base-ui/react/dialog";
|
|
13
13
|
import { encode } from "uqr";
|
|
14
14
|
import { ContextMenu } from "@base-ui/react/context-menu";
|
|
@@ -1817,24 +1817,40 @@ var hasOwnTextSelection = (target) => {
|
|
|
1817
1817
|
return !!document.getSelection()?.toString();
|
|
1818
1818
|
};
|
|
1819
1819
|
function bindTerminalClipboard(host, terminal, canWriteFromTerminalOutput, onCopied) {
|
|
1820
|
+
const reportCopy = (copied) => onCopied(copied ? "copied" : "blocked");
|
|
1821
|
+
let textWaitingForClick;
|
|
1822
|
+
const copyWaitingTextOnUserGesture = () => {
|
|
1823
|
+
const text = textWaitingForClick;
|
|
1824
|
+
textWaitingForClick = void 0;
|
|
1825
|
+
if (text !== void 0) writeClipboardText(text).then(reportCopy);
|
|
1826
|
+
};
|
|
1827
|
+
const copyFromTerminalOutput = (text) => void writeClipboardText(text).then((copied) => {
|
|
1828
|
+
if (copied) return reportCopy(true);
|
|
1829
|
+
textWaitingForClick = text;
|
|
1830
|
+
onCopied("waiting-for-click");
|
|
1831
|
+
});
|
|
1820
1832
|
const copySelectionOnRelease = () => {
|
|
1821
|
-
if (terminal.hasSelection()) writeClipboardText(terminal.getSelection()).then(
|
|
1833
|
+
if (terminal.hasSelection()) writeClipboardText(terminal.getSelection()).then(reportCopy);
|
|
1822
1834
|
};
|
|
1823
1835
|
const copySelectionOnShortcut = (event) => {
|
|
1824
1836
|
if (event.defaultPrevented || !terminal.hasSelection() || hasOwnTextSelection(event.target)) return;
|
|
1825
1837
|
event.clipboardData?.setData("text/plain", terminal.getSelection());
|
|
1826
1838
|
event.preventDefault();
|
|
1827
|
-
|
|
1839
|
+
reportCopy(true);
|
|
1828
1840
|
};
|
|
1829
1841
|
const osc52 = terminal.parser.registerOscHandler(OSC_CLIPBOARD, (data) => {
|
|
1830
1842
|
const text = decodeOsc52ClipboardWrite(data);
|
|
1831
|
-
if (text !== void 0 && canWriteFromTerminalOutput())
|
|
1843
|
+
if (text !== void 0 && canWriteFromTerminalOutput()) copyFromTerminalOutput(text);
|
|
1832
1844
|
return true;
|
|
1833
1845
|
});
|
|
1834
1846
|
host.addEventListener("mouseup", copySelectionOnRelease);
|
|
1835
1847
|
window.addEventListener("copy", copySelectionOnShortcut);
|
|
1848
|
+
window.addEventListener("pointerdown", copyWaitingTextOnUserGesture, true);
|
|
1849
|
+
window.addEventListener("keydown", copyWaitingTextOnUserGesture, true);
|
|
1836
1850
|
return () => {
|
|
1837
1851
|
osc52.dispose();
|
|
1852
|
+
window.removeEventListener("pointerdown", copyWaitingTextOnUserGesture, true);
|
|
1853
|
+
window.removeEventListener("keydown", copyWaitingTextOnUserGesture, true);
|
|
1838
1854
|
host.removeEventListener("mouseup", copySelectionOnRelease);
|
|
1839
1855
|
window.removeEventListener("copy", copySelectionOnShortcut);
|
|
1840
1856
|
};
|
|
@@ -2082,6 +2098,98 @@ function RemoteAccess() {
|
|
|
2082
2098
|
});
|
|
2083
2099
|
}
|
|
2084
2100
|
//#endregion
|
|
2101
|
+
//#region src/client/update.ts
|
|
2102
|
+
var CHECK_MS = 9e5;
|
|
2103
|
+
var POLL_MS = 2e3;
|
|
2104
|
+
var GIVE_UP_MS = 18e4;
|
|
2105
|
+
var fetchStatus = async (signal) => {
|
|
2106
|
+
const response = await fetch("/api/update", { signal });
|
|
2107
|
+
if (!response.ok) throw new Error("Updates are not available.");
|
|
2108
|
+
return await response.json();
|
|
2109
|
+
};
|
|
2110
|
+
var postCheck = async () => {
|
|
2111
|
+
const response = await fetch("/api/update/check", { method: "POST" });
|
|
2112
|
+
if (!response.ok) throw new Error("Updates are not available.");
|
|
2113
|
+
return await response.json();
|
|
2114
|
+
};
|
|
2115
|
+
var confirmationMessage = ({ current, latest }) => `Update Webr from ${current} to ${latest}? Webr restarts and this page reloads. Running agents keep working.`;
|
|
2116
|
+
function useUpdate() {
|
|
2117
|
+
const [updatingFrom, setUpdatingFrom] = useState();
|
|
2118
|
+
const data = useQuery({
|
|
2119
|
+
queryKey: ["update"],
|
|
2120
|
+
queryFn: ({ signal }) => fetchStatus(signal),
|
|
2121
|
+
refetchInterval: updatingFrom ? POLL_MS : CHECK_MS,
|
|
2122
|
+
refetchOnWindowFocus: !updatingFrom
|
|
2123
|
+
}).data;
|
|
2124
|
+
const stopWaiting = useCallback((message) => {
|
|
2125
|
+
setUpdatingFrom(void 0);
|
|
2126
|
+
alertDialog(message);
|
|
2127
|
+
}, []);
|
|
2128
|
+
useEffect(() => {
|
|
2129
|
+
if (!updatingFrom || !data) return;
|
|
2130
|
+
if (data.current !== updatingFrom) window.location.reload();
|
|
2131
|
+
else if (data.state === "failed") stopWaiting(data.error ?? "The update failed.");
|
|
2132
|
+
}, [
|
|
2133
|
+
updatingFrom,
|
|
2134
|
+
data,
|
|
2135
|
+
stopWaiting
|
|
2136
|
+
]);
|
|
2137
|
+
useEffect(() => {
|
|
2138
|
+
if (!updatingFrom) return;
|
|
2139
|
+
const timer = setTimeout(() => stopWaiting("Webr did not come back after the update. Reload this page, or restart Herdr."), GIVE_UP_MS);
|
|
2140
|
+
return () => clearTimeout(timer);
|
|
2141
|
+
}, [updatingFrom, stopWaiting]);
|
|
2142
|
+
const queryClient = useQueryClient();
|
|
2143
|
+
const [checking, setChecking] = useState(false);
|
|
2144
|
+
const checkNow = useCallback(async () => {
|
|
2145
|
+
setChecking(true);
|
|
2146
|
+
try {
|
|
2147
|
+
queryClient.setQueryData(["update"], await postCheck());
|
|
2148
|
+
} catch {
|
|
2149
|
+
await alertDialog("Webr could not check for updates.");
|
|
2150
|
+
} finally {
|
|
2151
|
+
setChecking(false);
|
|
2152
|
+
}
|
|
2153
|
+
}, [queryClient]);
|
|
2154
|
+
const requestUpdate = useCallback(async () => {
|
|
2155
|
+
if (!data || !await confirmDialog(confirmationMessage(data), { confirmLabel: "Update" })) return;
|
|
2156
|
+
if ((await fetch("/api/update", { method: "POST" }).catch(() => void 0))?.status === 202) setUpdatingFrom(data.current);
|
|
2157
|
+
else await alertDialog("Webr could not start the update.");
|
|
2158
|
+
}, [data]);
|
|
2159
|
+
return {
|
|
2160
|
+
status: data,
|
|
2161
|
+
updating: !!updatingFrom,
|
|
2162
|
+
checking,
|
|
2163
|
+
checkNow,
|
|
2164
|
+
requestUpdate
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
2167
|
+
//#endregion
|
|
2168
|
+
//#region src/components/UpdateSetting.tsx
|
|
2169
|
+
function UpdateSetting() {
|
|
2170
|
+
const { status, updating, checking, checkNow, requestUpdate } = useUpdate();
|
|
2171
|
+
const upToDate = status && !status.available;
|
|
2172
|
+
return /* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", { children: "Updates" }), /* @__PURE__ */ jsxs("div", {
|
|
2173
|
+
className: "settings-row",
|
|
2174
|
+
children: [/* @__PURE__ */ jsxs("span", { children: [status ? `Webr ${status.current}` : "Webr", /* @__PURE__ */ jsx("small", {
|
|
2175
|
+
className: "device-meta",
|
|
2176
|
+
children: status?.available ? `Version ${status.latest} is available.` : upToDate ? "You are on the latest version." : "Checking for updates…"
|
|
2177
|
+
})] }), status?.available ? /* @__PURE__ */ jsx("button", {
|
|
2178
|
+
type: "button",
|
|
2179
|
+
className: "dialog-button is-primary",
|
|
2180
|
+
disabled: updating,
|
|
2181
|
+
onClick: () => void requestUpdate(),
|
|
2182
|
+
children: updating ? "Updating…" : `Update to ${status.latest}`
|
|
2183
|
+
}) : /* @__PURE__ */ jsx("button", {
|
|
2184
|
+
type: "button",
|
|
2185
|
+
className: "dialog-button",
|
|
2186
|
+
disabled: checking || !status,
|
|
2187
|
+
onClick: () => void checkNow(),
|
|
2188
|
+
children: checking ? "Checking…" : "Check for updates"
|
|
2189
|
+
})]
|
|
2190
|
+
})] });
|
|
2191
|
+
}
|
|
2192
|
+
//#endregion
|
|
2085
2193
|
//#region src/components/SettingsView.tsx
|
|
2086
2194
|
function SettingsView({ onOpenSidebar }) {
|
|
2087
2195
|
const [behavior, setBehavior] = useState("worktree");
|
|
@@ -2128,6 +2236,7 @@ function SettingsView({ onOpenSidebar }) {
|
|
|
2128
2236
|
children: "Threads"
|
|
2129
2237
|
}),
|
|
2130
2238
|
/* @__PURE__ */ jsx("h1", { children: "Settings" }),
|
|
2239
|
+
/* @__PURE__ */ jsx(UpdateSetting, {}),
|
|
2131
2240
|
/* @__PURE__ */ jsxs("section", { children: [/* @__PURE__ */ jsx("h2", { children: "Appearance" }), /* @__PURE__ */ jsxs("div", {
|
|
2132
2241
|
className: "settings-row",
|
|
2133
2242
|
children: [/* @__PURE__ */ jsx("span", { children: "Theme" }), /* @__PURE__ */ jsx(ThemeControl, { expanded: true })]
|
|
@@ -3036,54 +3145,6 @@ function Sidebar({ projects, threads, archived = [], machines, currentId, mode,
|
|
|
3036
3145
|
})] });
|
|
3037
3146
|
}
|
|
3038
3147
|
//#endregion
|
|
3039
|
-
//#region src/client/update.ts
|
|
3040
|
-
var CHECK_MS = 9e5;
|
|
3041
|
-
var POLL_MS = 2e3;
|
|
3042
|
-
var GIVE_UP_MS = 18e4;
|
|
3043
|
-
var fetchStatus = async (signal) => {
|
|
3044
|
-
const response = await fetch("/api/update", { signal });
|
|
3045
|
-
if (!response.ok) throw new Error("Updates are not available.");
|
|
3046
|
-
return await response.json();
|
|
3047
|
-
};
|
|
3048
|
-
var confirmationMessage = ({ current, latest }) => `Update Webr from ${current} to ${latest}? Webr restarts and this page reloads. Running agents keep working.`;
|
|
3049
|
-
function useUpdate() {
|
|
3050
|
-
const [updatingFrom, setUpdatingFrom] = useState();
|
|
3051
|
-
const data = useQuery({
|
|
3052
|
-
queryKey: ["update"],
|
|
3053
|
-
queryFn: ({ signal }) => fetchStatus(signal),
|
|
3054
|
-
refetchInterval: updatingFrom ? POLL_MS : CHECK_MS,
|
|
3055
|
-
refetchOnWindowFocus: !updatingFrom
|
|
3056
|
-
}).data;
|
|
3057
|
-
const stopWaiting = useCallback((message) => {
|
|
3058
|
-
setUpdatingFrom(void 0);
|
|
3059
|
-
alertDialog(message);
|
|
3060
|
-
}, []);
|
|
3061
|
-
useEffect(() => {
|
|
3062
|
-
if (!updatingFrom || !data) return;
|
|
3063
|
-
if (data.current !== updatingFrom) window.location.reload();
|
|
3064
|
-
else if (data.state === "failed") stopWaiting(data.error ?? "The update failed.");
|
|
3065
|
-
}, [
|
|
3066
|
-
updatingFrom,
|
|
3067
|
-
data,
|
|
3068
|
-
stopWaiting
|
|
3069
|
-
]);
|
|
3070
|
-
useEffect(() => {
|
|
3071
|
-
if (!updatingFrom) return;
|
|
3072
|
-
const timer = setTimeout(() => stopWaiting("Webr did not come back after the update. Reload this page, or restart Herdr."), GIVE_UP_MS);
|
|
3073
|
-
return () => clearTimeout(timer);
|
|
3074
|
-
}, [updatingFrom, stopWaiting]);
|
|
3075
|
-
const requestUpdate = useCallback(async () => {
|
|
3076
|
-
if (!data || !await confirmDialog(confirmationMessage(data), { confirmLabel: "Update" })) return;
|
|
3077
|
-
if ((await fetch("/api/update", { method: "POST" }).catch(() => void 0))?.status === 202) setUpdatingFrom(data.current);
|
|
3078
|
-
else await alertDialog("Webr could not start the update.");
|
|
3079
|
-
}, [data]);
|
|
3080
|
-
return {
|
|
3081
|
-
status: data,
|
|
3082
|
-
updating: !!updatingFrom,
|
|
3083
|
-
requestUpdate
|
|
3084
|
-
};
|
|
3085
|
-
}
|
|
3086
|
-
//#endregion
|
|
3087
3148
|
//#region src/components/UpdateButton.tsx
|
|
3088
3149
|
function UpdateButton() {
|
|
3089
3150
|
const { status, updating, requestUpdate } = useUpdate();
|
|
@@ -4020,9 +4081,88 @@ function useImageAttachments({ machineId, active, writable, send, show }) {
|
|
|
4020
4081
|
}
|
|
4021
4082
|
//#endregion
|
|
4022
4083
|
//#region src/client/terminal-links.ts
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4084
|
+
var URL_PATTERN = /https?:\/\/[^\s"'<>`]+/g;
|
|
4085
|
+
var TRAILING_PUNCTUATION = /[.,;:!?)\]}]+$/;
|
|
4086
|
+
var hasOpenModifier = (event) => event.metaKey || event.ctrlKey;
|
|
4087
|
+
function logicalLineAt(terminal, row) {
|
|
4088
|
+
const buffer = terminal.buffer.active;
|
|
4089
|
+
let first = row;
|
|
4090
|
+
while (first > 0 && buffer.getLine(first)?.isWrapped) first--;
|
|
4091
|
+
let text = "";
|
|
4092
|
+
let last = first;
|
|
4093
|
+
for (let index = first; buffer.getLine(index) && (index === first || buffer.getLine(index).isWrapped); index++) {
|
|
4094
|
+
text += buffer.getLine(index).translateToString(false, 0, terminal.cols);
|
|
4095
|
+
last = index;
|
|
4096
|
+
}
|
|
4097
|
+
return {
|
|
4098
|
+
text,
|
|
4099
|
+
offset: (row - first) * terminal.cols,
|
|
4100
|
+
last
|
|
4101
|
+
};
|
|
4102
|
+
}
|
|
4103
|
+
function urlAtCell(terminal, column, row) {
|
|
4104
|
+
const { text, offset } = logicalLineAt(terminal, row);
|
|
4105
|
+
const position = offset + column;
|
|
4106
|
+
for (const match of text.matchAll(URL_PATTERN)) {
|
|
4107
|
+
const url = match[0].replace(TRAILING_PUNCTUATION, "");
|
|
4108
|
+
if (position >= match.index && position < match.index + url.length) return url;
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
var trimmedLines = (text) => text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
4112
|
+
var WHOLE_URL = /^https?:\/\/[^\s"'<>`]+$/;
|
|
4113
|
+
function urlFromSelection(selection) {
|
|
4114
|
+
const joined = trimmedLines(selection).join("").replace(TRAILING_PUNCTUATION, "");
|
|
4115
|
+
return WHOLE_URL.test(joined) ? joined : void 0;
|
|
4116
|
+
}
|
|
4117
|
+
var openUrlInNewTab = (url) => {
|
|
4118
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
4119
|
+
};
|
|
4120
|
+
function openLinkUnderModifierClick(terminal, event) {
|
|
4121
|
+
const rect = (terminal.element?.querySelector(".xterm-screen"))?.getBoundingClientRect();
|
|
4122
|
+
if (!hasOpenModifier(event) || !rect?.width || !rect.height) return;
|
|
4123
|
+
const url = urlAtCell(terminal, Math.floor((event.clientX - rect.left) / rect.width * terminal.cols), Math.floor((event.clientY - rect.top) / rect.height * terminal.rows) + terminal.buffer.active.viewportY);
|
|
4124
|
+
if (url) openUrlInNewTab(url);
|
|
4125
|
+
}
|
|
4126
|
+
//#endregion
|
|
4127
|
+
//#region src/components/TerminalUrlActions.tsx
|
|
4128
|
+
var keepSelection = (event) => {
|
|
4129
|
+
event.preventDefault();
|
|
4130
|
+
event.stopPropagation();
|
|
4131
|
+
};
|
|
4132
|
+
function TerminalUrlActions({ selected, onDone, onCopied }) {
|
|
4133
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4134
|
+
className: "terminal-url-actions",
|
|
4135
|
+
role: "toolbar",
|
|
4136
|
+
"aria-label": "Selected link",
|
|
4137
|
+
style: {
|
|
4138
|
+
left: selected.x,
|
|
4139
|
+
top: selected.y
|
|
4140
|
+
},
|
|
4141
|
+
onMouseDown: keepSelection,
|
|
4142
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
4143
|
+
onClick: (event) => event.stopPropagation(),
|
|
4144
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
4145
|
+
type: "button",
|
|
4146
|
+
onClick: () => {
|
|
4147
|
+
openUrlInNewTab(selected.url);
|
|
4148
|
+
onDone();
|
|
4149
|
+
},
|
|
4150
|
+
children: [/* @__PURE__ */ jsx(ExternalLink, {
|
|
4151
|
+
size: 14,
|
|
4152
|
+
strokeWidth: 1.8
|
|
4153
|
+
}), "Open link"]
|
|
4154
|
+
}), /* @__PURE__ */ jsxs("button", {
|
|
4155
|
+
type: "button",
|
|
4156
|
+
onClick: () => {
|
|
4157
|
+
writeClipboardText(selected.url).then(onCopied);
|
|
4158
|
+
onDone();
|
|
4159
|
+
},
|
|
4160
|
+
children: [/* @__PURE__ */ jsx(Copy, {
|
|
4161
|
+
size: 14,
|
|
4162
|
+
strokeWidth: 1.8
|
|
4163
|
+
}), "Copy link"]
|
|
4164
|
+
})]
|
|
4165
|
+
});
|
|
4026
4166
|
}
|
|
4027
4167
|
//#endregion
|
|
4028
4168
|
//#region src/components/useTerminalNotice.ts
|
|
@@ -4281,6 +4421,7 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4281
4421
|
const [inputFocused, setInputFocused] = useState(false);
|
|
4282
4422
|
const [ctrl, setCtrl] = useState(false);
|
|
4283
4423
|
const [touch, setTouch] = useState(false);
|
|
4424
|
+
const [selectedUrl, setSelectedUrl] = useState(null);
|
|
4284
4425
|
useEffect(() => setTouch(matchesCoarsePointer()), []);
|
|
4285
4426
|
const { notice, show } = useTerminalNotice();
|
|
4286
4427
|
const images = useImageAttachments({
|
|
@@ -4298,8 +4439,8 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4298
4439
|
control.current?.input(text, true);
|
|
4299
4440
|
}
|
|
4300
4441
|
});
|
|
4301
|
-
const showCopyResult = useRef((
|
|
4302
|
-
showCopyResult.current = (
|
|
4442
|
+
const showCopyResult = useRef((outcome) => {});
|
|
4443
|
+
showCopyResult.current = (outcome) => outcome === "copied" ? show("Copied to clipboard", "info", 1200) : outcome === "waiting-for-click" ? show("Click or press a key to finish copying.", "info", 6e3) : show("The browser blocked clipboard access.", "error", 4e3);
|
|
4303
4444
|
useEffect(() => {
|
|
4304
4445
|
if (!host.current) return;
|
|
4305
4446
|
let disposed = false;
|
|
@@ -4333,7 +4474,7 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4333
4474
|
if (writableRef.current) host.current?.parentElement?.querySelector(".terminal-input-capture")?.focus();
|
|
4334
4475
|
};
|
|
4335
4476
|
terminal.textarea?.addEventListener("focus", redirectFocus);
|
|
4336
|
-
const clipboard = bindTerminalClipboard(host.current, terminal, () => writableRef.current, (
|
|
4477
|
+
const clipboard = bindTerminalClipboard(host.current, terminal, () => writableRef.current, (outcome) => showCopyResult.current(outcome));
|
|
4337
4478
|
const links = terminal.parser.registerOscHandler(8, () => true);
|
|
4338
4479
|
if (!pane.terminalId) {
|
|
4339
4480
|
clipboard();
|
|
@@ -4342,7 +4483,24 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4342
4483
|
}
|
|
4343
4484
|
const fit = new FitAddon();
|
|
4344
4485
|
terminal.loadAddon(fit);
|
|
4345
|
-
terminal.loadAddon(new WebLinksAddon(
|
|
4486
|
+
terminal.loadAddon(new WebLinksAddon(() => {}));
|
|
4487
|
+
const openLink = (event) => openLinkUnderModifierClick(terminal, event);
|
|
4488
|
+
const hostElement = host.current;
|
|
4489
|
+
hostElement.addEventListener("mouseup", openLink);
|
|
4490
|
+
const offerSelectedUrl = (event) => {
|
|
4491
|
+
const url = terminal.hasSelection() ? urlFromSelection(terminal.getSelection()) : void 0;
|
|
4492
|
+
const origin = section.current?.getBoundingClientRect();
|
|
4493
|
+
setSelectedUrl(url && origin ? {
|
|
4494
|
+
url,
|
|
4495
|
+
x: event.clientX - origin.left,
|
|
4496
|
+
y: event.clientY - origin.top
|
|
4497
|
+
} : null);
|
|
4498
|
+
};
|
|
4499
|
+
const withdrawUrlOffer = () => {
|
|
4500
|
+
if (!terminal.hasSelection()) setSelectedUrl(null);
|
|
4501
|
+
};
|
|
4502
|
+
hostElement.addEventListener("mouseup", offerSelectedUrl);
|
|
4503
|
+
const selection = terminal.onSelectionChange(withdrawUrlOffer);
|
|
4346
4504
|
const estimatedViewport = () => ({
|
|
4347
4505
|
cols: Math.floor((host.current?.clientWidth ?? 640) / 8),
|
|
4348
4506
|
rows: Math.floor((host.current?.clientHeight ?? 400) / 20)
|
|
@@ -4414,6 +4572,10 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4414
4572
|
document.removeEventListener("visibilitychange", claimSize);
|
|
4415
4573
|
terminal.textarea?.removeEventListener("focus", redirectFocus);
|
|
4416
4574
|
clipboard();
|
|
4575
|
+
hostElement.removeEventListener("mouseup", openLink);
|
|
4576
|
+
hostElement.removeEventListener("mouseup", offerSelectedUrl);
|
|
4577
|
+
selection.dispose();
|
|
4578
|
+
setSelectedUrl(null);
|
|
4417
4579
|
links.dispose();
|
|
4418
4580
|
resize.disconnect();
|
|
4419
4581
|
colorObserver.disconnect();
|
|
@@ -4545,6 +4707,14 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
4545
4707
|
strokeWidth: 1.6
|
|
4546
4708
|
}), /* @__PURE__ */ jsx("span", { children: "Drop image to attach" })]
|
|
4547
4709
|
}),
|
|
4710
|
+
selectedUrl && /* @__PURE__ */ jsx(TerminalUrlActions, {
|
|
4711
|
+
selected: selectedUrl,
|
|
4712
|
+
onDone: () => {
|
|
4713
|
+
setSelectedUrl(null);
|
|
4714
|
+
term.current?.clearSelection();
|
|
4715
|
+
},
|
|
4716
|
+
onCopied: (copied) => showCopyResult.current(copied ? "copied" : "blocked")
|
|
4717
|
+
}),
|
|
4548
4718
|
notice && /* @__PURE__ */ jsx("div", {
|
|
4549
4719
|
className: `terminal-attach-notice is-${notice.tone}`,
|
|
4550
4720
|
role: notice.tone === "error" ? "alert" : "status",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as createAstro, V as __exportAll, i as renderComponent, u as renderTemplate } from "./server_dfdLOyV2.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BnrQvXXD.mjs";
|
|
3
|
-
import { n as $$Base, t as App } from "./
|
|
3
|
+
import { n as $$Base, t as App } from "./App_Ch7GmWXO.mjs";
|
|
4
4
|
//#region src/pages/threads/[id].astro
|
|
5
5
|
var _id__exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
default: () => $$Id,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as createAstro, V as __exportAll, i as renderComponent, u as renderTemplate } from "./server_dfdLOyV2.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BnrQvXXD.mjs";
|
|
3
|
-
import { n as $$Base, t as App } from "./
|
|
3
|
+
import { n as $$Base, t as App } from "./App_Ch7GmWXO.mjs";
|
|
4
4
|
//#region src/pages/sessions/[session]/tabs/[tab].astro
|
|
5
5
|
var _tab__exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
default: () => $$Tab,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as createAstro, V as __exportAll, i as renderComponent, u as renderTemplate } from "./server_dfdLOyV2.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BnrQvXXD.mjs";
|
|
3
|
-
import { n as $$Base, t as App } from "./
|
|
3
|
+
import { n as $$Base, t as App } from "./App_Ch7GmWXO.mjs";
|
|
4
4
|
//#region src/pages/new.astro
|
|
5
5
|
var new_exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
default: () => $$New,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as createAstro, V as __exportAll, i as renderComponent, u as renderTemplate } from "./server_dfdLOyV2.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BnrQvXXD.mjs";
|
|
3
|
-
import { n as $$Base, t as App } from "./
|
|
3
|
+
import { n as $$Base, t as App } from "./App_Ch7GmWXO.mjs";
|
|
4
4
|
//#region src/pages/settings.astro
|
|
5
5
|
var settings_exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
default: () => $$Settings,
|
package/dist/server/entry.mjs
CHANGED
|
@@ -2426,10 +2426,10 @@ var renderers = [Object.assign({
|
|
|
2426
2426
|
//#endregion
|
|
2427
2427
|
//#region \0virtual:astro:pages
|
|
2428
2428
|
var _page0 = () => import("./chunks/node_C8FqXy_n.mjs").then((n) => n.t);
|
|
2429
|
-
var _page1 = () => import("./chunks/
|
|
2430
|
-
var _page2 = () => import("./chunks/
|
|
2431
|
-
var _page3 = () => import("./chunks/
|
|
2432
|
-
var _page4 = () => import("./chunks/
|
|
2429
|
+
var _page1 = () => import("./chunks/new_CM9fzfm6.mjs");
|
|
2430
|
+
var _page2 = () => import("./chunks/_tab__BEI4cb-5.mjs");
|
|
2431
|
+
var _page3 = () => import("./chunks/settings_D4hVr2qz.mjs");
|
|
2432
|
+
var _page4 = () => import("./chunks/_id__Ba8WQNWp.mjs");
|
|
2433
2433
|
var _page5 = () => import("./chunks/index_Bvv1gpI0.mjs");
|
|
2434
2434
|
var pageMap = /* @__PURE__ */ new Map([
|
|
2435
2435
|
["node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node.js", _page0],
|
|
@@ -2441,7 +2441,7 @@ var pageMap = /* @__PURE__ */ new Map([
|
|
|
2441
2441
|
]);
|
|
2442
2442
|
//#endregion
|
|
2443
2443
|
//#region \0virtual:astro:manifest
|
|
2444
|
-
var _manifest = deserializeManifest({"rootDir":"file:///home/runner/work/webr/webr/","cacheDir":"file:///home/runner/work/webr/webr/node_modules/.astro/","outDir":"file:///home/runner/work/webr/webr/dist/","srcDir":"file:///home/runner/work/webr/webr/src/","publicDir":"file:///home/runner/work/webr/webr/public/","buildClientDir":"file:///home/runner/work/webr/webr/dist/client/","buildServerDir":"file:///home/runner/work/webr/webr/dist/server/","adapterName":"@astrojs/node","assetsDir":"_astro","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","component":"_server-islands.astro","params":["name"],"segments":[[{"content":"_server-islands","dynamic":false,"spread":false}],[{"content":"name","dynamic":true,"spread":false}]],"pattern":"^\\/_server-islands\\/([^/]+?)\\/?$","prerender":false,"isIndex":false,"fallbackRoutes":[],"route":"/_server-islands/[name]","origin":"internal","distURL":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/_image","component":"node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node.js","params":[],"pathname":"/_image","pattern":"^\\/_image\\/?$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"type":"endpoint","prerender":false,"fallbackRoutes":[],"distURL":[],"isIndex":false,"origin":"internal","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.
|
|
2444
|
+
var _manifest = deserializeManifest({"rootDir":"file:///home/runner/work/webr/webr/","cacheDir":"file:///home/runner/work/webr/webr/node_modules/.astro/","outDir":"file:///home/runner/work/webr/webr/dist/","srcDir":"file:///home/runner/work/webr/webr/src/","publicDir":"file:///home/runner/work/webr/webr/public/","buildClientDir":"file:///home/runner/work/webr/webr/dist/client/","buildServerDir":"file:///home/runner/work/webr/webr/dist/server/","adapterName":"@astrojs/node","assetsDir":"_astro","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"page","component":"_server-islands.astro","params":["name"],"segments":[[{"content":"_server-islands","dynamic":false,"spread":false}],[{"content":"name","dynamic":true,"spread":false}]],"pattern":"^\\/_server-islands\\/([^/]+?)\\/?$","prerender":false,"isIndex":false,"fallbackRoutes":[],"route":"/_server-islands/[name]","origin":"internal","distURL":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/_image","component":"node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node.js","params":[],"pathname":"/_image","pattern":"^\\/_image\\/?$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"type":"endpoint","prerender":false,"fallbackRoutes":[],"distURL":[],"isIndex":false,"origin":"internal","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.DroHhgBz.css"}],"routeData":{"route":"/new","isIndex":false,"type":"page","pattern":"^\\/new\\/?$","segments":[[{"content":"new","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/new.astro","pathname":"/new","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.DroHhgBz.css"}],"routeData":{"route":"/sessions/[session]/tabs/[tab]","isIndex":false,"type":"page","pattern":"^\\/sessions\\/([^/]+?)\\/tabs\\/([^/]+?)\\/?$","segments":[[{"content":"sessions","dynamic":false,"spread":false}],[{"content":"session","dynamic":true,"spread":false}],[{"content":"tabs","dynamic":false,"spread":false}],[{"content":"tab","dynamic":true,"spread":false}]],"params":["session","tab"],"component":"src/pages/sessions/[session]/tabs/[tab].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.DroHhgBz.css"}],"routeData":{"route":"/settings","isIndex":false,"type":"page","pattern":"^\\/settings\\/?$","segments":[[{"content":"settings","dynamic":false,"spread":false}]],"params":[],"component":"src/pages/settings.astro","pathname":"/settings","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[{"type":"external","src":"_astro/App.DroHhgBz.css"}],"routeData":{"route":"/threads/[id]","isIndex":false,"type":"page","pattern":"^\\/threads\\/([^/]+?)\\/?$","segments":[[{"content":"threads","dynamic":false,"spread":false}],[{"content":"id","dynamic":true,"spread":false}]],"params":["id"],"component":"src/pages/threads/[id].astro","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"route":"/","isIndex":true,"type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":false,"fallbackRoutes":[],"distURL":[],"origin":"project","_meta":{"trailingSlash":"ignore"}}}],"serverLike":true,"middlewareMode":"classic","base":"/","trailingSlash":"ignore","compressHTML":"jsx","componentMetadata":[["/home/runner/work/webr/webr/src/pages/new.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/sessions/[session]/tabs/[tab].astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/settings.astro",{"propagation":"none","containsHead":true}],["/home/runner/work/webr/webr/src/pages/threads/[id].astro",{"propagation":"none","containsHead":true}]],"renderers":[],"clientDirectives":[["idle","(()=>{var l=(n,t)=>{let i=async()=>{await(await n())()},e=typeof t.value==\"object\"?t.value:void 0,s={timeout:e==null?void 0:e.timeout};\"requestIdleCallback\"in window?window.requestIdleCallback(i,s):setTimeout(i,s.timeout||200)};(self.Astro||(self.Astro={})).idle=l;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var n=(a,t)=>{let i=async()=>{await(await a())()};if(t.value){let e=matchMedia(t.value);e.matches?i():e.addEventListener(\"change\",i,{once:!0})}};(self.Astro||(self.Astro={})).media=n;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value==\"object\"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event(\"astro:visible\"));})();"]],"entryModules":{"\u0000noop-middleware":"virtual_astro_middleware.mjs","\u0000virtual:astro:server-island-manifest":"chunks/_virtual_astro_server-island-manifest_C1Q2srgE.mjs","\u0000virtual:astro:session-driver":"chunks/_virtual_astro_session-driver_Dp7RXjOf.mjs","\u0000virtual:astro:actions/noop-entrypoint":"chunks/noop-entrypoint_Z3zFhrGC.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/@astrojs+react@7.0.0_@types+node@22.20.4_@types+react-dom@19.3.0_@types+react@19.3.0__@_02aa85dceaccf3d763325676dd8540a8/node_modules/@astrojs/react/dist/vnode-children.js":"chunks/vnode-children_BSi0H4PL.mjs","@astrojs/node/server.js":"entry.mjs","\u0000virtual:astro:page:src/pages/threads/[id]@_@astro":"chunks/_id__Ba8WQNWp.mjs","\u0000virtual:astro:page:src/pages/sessions/[session]/tabs/[tab]@_@astro":"chunks/_tab__BEI4cb-5.mjs","\u0000virtual:astro:page:src/pages/index@_@astro":"chunks/index_Bvv1gpI0.mjs","\u0000virtual:astro:page:src/pages/new@_@astro":"chunks/new_CM9fzfm6.mjs","\u0000virtual:astro:page:node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/endpoint/node@_@js":"chunks/node_C8FqXy_n.mjs","\u0000virtual:astro:page:src/pages/settings@_@astro":"chunks/settings_D4hVr2qz.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/dist/assets/services/sharp.js":"chunks/sharp_8J8zk4Wd.mjs","/home/runner/work/webr/webr/src/components/App.tsx":"_astro/App.Ho8QFCCQ.js","/home/runner/work/webr/webr/node_modules/.pnpm/astro@7.3.5_@types+node@22.20.4_tsx@4.23.15_yaml@2.9.1/node_modules/astro/components/ClientRouter.astro?astro&type=script&index=0&lang.ts":"_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","@astrojs/react/client.js":"_astro/client.BDkzSRUN.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-fit@0.10.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-fit/lib/addon-fit.js":"_astro/addon-fit.jgKqzwky.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-web-links@0.11.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-web-links/lib/addon-web-links.js":"_astro/addon-web-links.C9lyQRxI.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+addon-webgl@0.18.0_@xterm+xterm@5.5.0/node_modules/@xterm/addon-webgl/lib/addon-webgl.js":"_astro/addon-webgl.Bd5ox92E.js","/home/runner/work/webr/webr/node_modules/.pnpm/@xterm+xterm@5.5.0/node_modules/@xterm/xterm/lib/xterm.js":"_astro/xterm.B-l5AIf6.js","astro:scripts/before-hydration.js":""},"inlinedScripts":[],"assets":["/apple-touch-icon.png","/brand-mark.png","/favicon-16.png","/favicon-32.png","/favicon.ico","/icon-192.png","/icon-512.png","/icon-maskable-512.png","/manifest.webmanifest","/_astro/App.Ho8QFCCQ.js","/_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","/_astro/addon-fit.jgKqzwky.js","/_astro/addon-web-links.C9lyQRxI.js","/_astro/addon-webgl.Bd5ox92E.js","/_astro/client.BDkzSRUN.js","/_astro/client.Bbg9OBwT.js","/_astro/client.CLSsMr2g.js","/_astro/xterm.B-l5AIf6.js","/_astro/App.DroHhgBz.css","/_astro/jetbrains-mono.CFJaiWaY.woff2","/_astro/symbols-nerd.CEdkKAK8.woff2"],"buildFormat":"directory","checkOrigin":true,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"MindeMlzE0aK1tV4qZ1g2UuMX9PGXHBF6/QvgWI+3fE=","sessionConfig":{"driver":"unstorage/drivers/fs-lite","options":{"base":"/home/runner/work/webr/webr/node_modules/.astro/sessions"}},"image":{},"devToolbar":{"enabled":false,"debugInfoOutput":""},"logLevel":"info","shouldInjectCspMetaTags":false});
|
|
2445
2445
|
var manifestRoutes = _manifest.routes;
|
|
2446
2446
|
var manifest = Object.assign(_manifest, {
|
|
2447
2447
|
renderers,
|
package/package.json
CHANGED
package/server/update/service.ts
CHANGED
|
@@ -72,6 +72,11 @@ export class UpdateService implements Updates {
|
|
|
72
72
|
if (latest) writeCachedLatest(latest, this.env);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
async check(): Promise<UpdateStatus> {
|
|
76
|
+
await this.refresh();
|
|
77
|
+
return this.status();
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
status(): UpdateStatus {
|
|
76
81
|
const { version: current } = packageInfo();
|
|
77
82
|
const latest = readCachedLatest(this.env)?.latest ?? current;
|
package/src/server/host.ts
CHANGED
|
@@ -56,6 +56,7 @@ export async function createHost(manager: RuntimeManager, origin: string, ssr?:
|
|
|
56
56
|
if (transcriber) registerVoiceRoutes(app, transcriber);
|
|
57
57
|
if (updates) {
|
|
58
58
|
app.get('/api/update', async () => updates.status());
|
|
59
|
+
app.post('/api/update/check', async () => updates.check());
|
|
59
60
|
app.post('/api/update', async (_request, reply) => { const status = updates.start(); return reply.code(status.state === 'updating' ? 202 : 409).send(status); });
|
|
60
61
|
}
|
|
61
62
|
app.get('/api/catalog/machines', async () => manager.bootstrap().machines);
|
package/src/shared/update.ts
CHANGED
|
@@ -2,4 +2,4 @@ export type UpdateState = 'idle' | 'updating' | 'failed';
|
|
|
2
2
|
|
|
3
3
|
export type UpdateStatus = { current: string; latest: string; available: boolean; state: UpdateState; error?: string };
|
|
4
4
|
|
|
5
|
-
export type Updates = { status: () => UpdateStatus; start: () => UpdateStatus };
|
|
5
|
+
export type Updates = { status: () => UpdateStatus; check: () => Promise<UpdateStatus>; start: () => UpdateStatus };
|