@pablopunk/webr 0.1.7 → 0.2.1
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/README.md +29 -0
- package/dist/client/_astro/App.1VFY1ClT.css +1 -0
- package/dist/client/_astro/App.CGyf2WDA.js +4 -0
- package/dist/server/chunks/{App_C1XnVbA2.mjs → App_C2vmjHiY.mjs} +330 -34
- package/dist/server/chunks/{_id__CAx6DC51.mjs → _id__BimjoFCd.mjs} +1 -1
- package/dist/server/chunks/{_tab__BJ-ULrm_.mjs → _tab__WmsbMlfC.mjs} +1 -1
- package/dist/server/chunks/{new_BfRTqcQ4.mjs → new_bTXSW7C3.mjs} +1 -1
- package/dist/server/chunks/{settings_BD_xdLnR.mjs → settings_DwzWmJBe.mjs} +1 -1
- package/dist/server/entry.mjs +5 -5
- package/package.json +4 -1
- package/server/cli.ts +14 -6
- package/server/plugin/stop.ts +10 -1
- package/server/rebuilt-restart.ts +26 -0
- package/server/run.ts +14 -3
- package/server/ssr.ts +4 -3
- package/server/update/index.ts +4 -2
- package/src/server/auth/access.ts +1 -1
- package/src/server/auth/auth.ts +12 -4
- package/src/server/dev-hmr-proxy.ts +16 -0
- package/src/server/host.ts +7 -2
- package/src/server/tailscale-serve.ts +42 -0
- package/src/server/voice/model.ts +35 -0
- package/src/server/voice/routes.ts +29 -0
- package/src/server/voice/transcriber.ts +80 -0
- package/src/server/voice/worker.mjs +23 -0
- package/dist/client/_astro/App.DijFEuO0.css +0 -1
- package/dist/client/_astro/App.Z2LzeAW7.js +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
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_CnGYDmxV.mjs";
|
|
2
2
|
import { t as createComponent } from "./compiler_BiU10Vds.mjs";
|
|
3
3
|
import { createContext, memo, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { Archive, ArchiveRestore, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Check, ChevronDown, ChevronRight, Circle, CircleAlert, CircleCheck, CircleHelp, Copy, Cpu, Folder, FolderTree, GitBranch, ImagePlus, LayoutList, LoaderCircle, MessageCircleQuestion, Monitor, Moon, PanelBottom, PanelLeft, PanelLeftClose, PanelLeftOpen, PanelRight, Pencil, Plus, Search, Server, Settings2, SquarePen, SquareTerminal, Sun, TerminalSquare, Trash2, TriangleAlert, X } from "lucide-react";
|
|
4
|
+
import { Archive, ArchiveRestore, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Check, ChevronDown, ChevronRight, Circle, CircleAlert, CircleCheck, CircleHelp, Command, Copy, Cpu, Folder, FolderTree, GitBranch, ImagePlus, LayoutList, LoaderCircle, MessageCircleQuestion, Mic, Monitor, Moon, PanelBottom, PanelLeft, PanelLeftClose, PanelLeftOpen, PanelRight, 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";
|
|
@@ -680,6 +680,10 @@ async function listAuditEvents() {
|
|
|
680
680
|
if (!response.ok) throw new Error("Webr could not load recent activity.");
|
|
681
681
|
return response.json();
|
|
682
682
|
}
|
|
683
|
+
async function tailscaleStatus() {
|
|
684
|
+
const response = await fetch("/api/remote/tailscale");
|
|
685
|
+
return response.ok ? (await response.json()).status : "unavailable";
|
|
686
|
+
}
|
|
683
687
|
var revokeDevice = (id) => post(`/api/devices/${encodeURIComponent(id)}/revoke`);
|
|
684
688
|
var decidePairRequest = (id, decision) => post(`/api/pair/${encodeURIComponent(id)}/${decision}`);
|
|
685
689
|
async function fetchPending() {
|
|
@@ -1403,6 +1407,7 @@ function NewThreadView({ projects, machines, selectedProjectId, onOpenSidebar })
|
|
|
1403
1407
|
const [busy, setBusy] = useState(false);
|
|
1404
1408
|
const [error, setError] = useState("");
|
|
1405
1409
|
const [creatingWorkspace, setCreatingWorkspace] = useState(false);
|
|
1410
|
+
const projectIdsBeforeCreate = useRef(null);
|
|
1406
1411
|
const operation = useRef(null);
|
|
1407
1412
|
const images = usePromptImages({ machineId });
|
|
1408
1413
|
const baseMachine = machines.find((machine) => machine.id === machineId) ?? {
|
|
@@ -1452,6 +1457,14 @@ function NewThreadView({ projects, machines, selectedProjectId, onOpenSidebar })
|
|
|
1452
1457
|
projectId,
|
|
1453
1458
|
catalog.data
|
|
1454
1459
|
]);
|
|
1460
|
+
useEffect(() => {
|
|
1461
|
+
const known = projectIdsBeforeCreate.current;
|
|
1462
|
+
const added = known && machineProjects.find((project) => !known.has(project.id));
|
|
1463
|
+
if (added) {
|
|
1464
|
+
projectIdsBeforeCreate.current = null;
|
|
1465
|
+
changeProject(added.id);
|
|
1466
|
+
}
|
|
1467
|
+
}, [machineProjects]);
|
|
1455
1468
|
useEffect(() => {
|
|
1456
1469
|
if (!machineId && machines.length) setMachineId(machines.find((machine) => machine.id === "local")?.id ?? machines[0].id);
|
|
1457
1470
|
if (!projectId && machineProjects.length) setProjectId(machineProjects[0].id);
|
|
@@ -1531,7 +1544,10 @@ function NewThreadView({ projects, machines, selectedProjectId, onOpenSidebar })
|
|
|
1531
1544
|
/* @__PURE__ */ jsx("p", { children: !machineProjects.length ? "This Herdr session has no projects yet." : "Add a project to this Herdr session." }),
|
|
1532
1545
|
/* @__PURE__ */ jsx(CreateWorkspace, {
|
|
1533
1546
|
machineId: machine.id,
|
|
1534
|
-
onCreated: () =>
|
|
1547
|
+
onCreated: () => {
|
|
1548
|
+
projectIdsBeforeCreate.current = new Set(machineProjects.map((project) => project.id));
|
|
1549
|
+
setCreatingWorkspace(false);
|
|
1550
|
+
}
|
|
1535
1551
|
}),
|
|
1536
1552
|
!!machineProjects.length && /* @__PURE__ */ jsx("button", {
|
|
1537
1553
|
className: "workspace-cancel",
|
|
@@ -1783,11 +1799,16 @@ function InviteDialog({ invite, onClose }) {
|
|
|
1783
1799
|
const [urlIndex, setUrlIndex] = useState(0);
|
|
1784
1800
|
const [copied, setCopied] = useState(false);
|
|
1785
1801
|
const url = invite.urls[urlIndex];
|
|
1786
|
-
const
|
|
1802
|
+
const copyText = (text) => writeClipboardText(text).then((ok) => {
|
|
1787
1803
|
if (!ok) return;
|
|
1788
1804
|
setCopied(true);
|
|
1789
1805
|
setTimeout(() => setCopied(false), 1500);
|
|
1790
1806
|
});
|
|
1807
|
+
const copy = () => copyText(invite.token);
|
|
1808
|
+
const selectAndCopyAddress = (index) => {
|
|
1809
|
+
setUrlIndex(index);
|
|
1810
|
+
copyText(invite.urls[index]);
|
|
1811
|
+
};
|
|
1791
1812
|
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
1792
1813
|
open: true,
|
|
1793
1814
|
onOpenChange: (open) => {
|
|
@@ -1817,7 +1838,7 @@ function InviteDialog({ invite, onClose }) {
|
|
|
1817
1838
|
type: "button",
|
|
1818
1839
|
"aria-pressed": index === urlIndex,
|
|
1819
1840
|
className: index === urlIndex ? "theme-option is-selected" : "theme-option",
|
|
1820
|
-
onClick: () =>
|
|
1841
|
+
onClick: () => selectAndCopyAddress(index),
|
|
1821
1842
|
children: new URL(address).host
|
|
1822
1843
|
}, address))
|
|
1823
1844
|
})
|
|
@@ -1854,6 +1875,21 @@ function InviteDialog({ invite, onClose }) {
|
|
|
1854
1875
|
})] })
|
|
1855
1876
|
});
|
|
1856
1877
|
}
|
|
1878
|
+
var TAILSCALE_CALLOUTS = {
|
|
1879
|
+
unavailable: "Install Tailscale on this computer and your other devices to get a private, secure HTTPS address for Webr. HTTPS unlocks features browsers only allow on secure pages, such as the microphone.",
|
|
1880
|
+
"https-disabled": "Tailscale is installed, but HTTPS certificates are off. Turn them on in the Tailscale admin console under DNS, then restart Webr to unlock features that need a secure address, such as the microphone."
|
|
1881
|
+
};
|
|
1882
|
+
function TailscaleCallout() {
|
|
1883
|
+
const [status, setStatus] = useState("ready");
|
|
1884
|
+
useEffect(() => {
|
|
1885
|
+
tailscaleStatus().then(setStatus, () => void 0);
|
|
1886
|
+
}, []);
|
|
1887
|
+
return status === "ready" ? null : /* @__PURE__ */ jsx("p", {
|
|
1888
|
+
className: "tailscale-callout",
|
|
1889
|
+
role: "note",
|
|
1890
|
+
children: TAILSCALE_CALLOUTS[status]
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1857
1893
|
function RemoteAccess() {
|
|
1858
1894
|
const [devices, setDevices] = useState([]);
|
|
1859
1895
|
const [invite, setInvite] = useState();
|
|
@@ -1886,6 +1922,7 @@ function RemoteAccess() {
|
|
|
1886
1922
|
className: "settings-note",
|
|
1887
1923
|
children: "Other devices ask to connect and you approve them here. This computer never needs a code."
|
|
1888
1924
|
}),
|
|
1925
|
+
/* @__PURE__ */ jsx(TailscaleCallout, {}),
|
|
1889
1926
|
/* @__PURE__ */ jsxs("div", {
|
|
1890
1927
|
className: "settings-row",
|
|
1891
1928
|
children: [/* @__PURE__ */ jsx("span", { children: "Connect a device" }), /* @__PURE__ */ jsx("button", {
|
|
@@ -3379,55 +3416,122 @@ var keys = [
|
|
|
3379
3416
|
}
|
|
3380
3417
|
];
|
|
3381
3418
|
var keepKeyboardOpen = (event) => event.preventDefault();
|
|
3382
|
-
|
|
3419
|
+
var pressOnTouchDown = (action) => ({
|
|
3420
|
+
onPointerDown: (event) => {
|
|
3421
|
+
keepKeyboardOpen(event);
|
|
3422
|
+
action();
|
|
3423
|
+
},
|
|
3424
|
+
onMouseDown: keepKeyboardOpen,
|
|
3425
|
+
onTouchStart: keepKeyboardOpen,
|
|
3426
|
+
onClick: (event) => {
|
|
3427
|
+
if (event.detail === 0) action();
|
|
3428
|
+
}
|
|
3429
|
+
});
|
|
3430
|
+
var voiceLabels = {
|
|
3431
|
+
idle: "Dictate",
|
|
3432
|
+
preparing: "Preparing voice input",
|
|
3433
|
+
recording: "Stop dictation",
|
|
3434
|
+
transcribing: "Transcribing"
|
|
3435
|
+
};
|
|
3436
|
+
var voiceIcon = (phase) => phase === "recording" ? /* @__PURE__ */ jsx(Square, {
|
|
3437
|
+
size: 14,
|
|
3438
|
+
fill: "currentColor"
|
|
3439
|
+
}) : phase === "idle" ? /* @__PURE__ */ jsx(Mic, { size: 16 }) : /* @__PURE__ */ jsx(LoaderCircle, {
|
|
3440
|
+
size: 16,
|
|
3441
|
+
className: "is-spinning"
|
|
3442
|
+
});
|
|
3443
|
+
function VoiceButton({ voice }) {
|
|
3444
|
+
return /* @__PURE__ */ jsx("button", {
|
|
3445
|
+
type: "button",
|
|
3446
|
+
tabIndex: -1,
|
|
3447
|
+
"aria-label": voiceLabels[voice.phase],
|
|
3448
|
+
"aria-pressed": voice.phase === "recording",
|
|
3449
|
+
className: `terminal-voice is-${voice.phase}`,
|
|
3450
|
+
...pressOnTouchDown(voice.toggle),
|
|
3451
|
+
children: voiceIcon(voice.phase)
|
|
3452
|
+
});
|
|
3453
|
+
}
|
|
3454
|
+
function TerminalKeyBar({ ctrl, onToggleCtrl, onBytes, voice }) {
|
|
3383
3455
|
return /* @__PURE__ */ jsxs("div", {
|
|
3384
3456
|
className: "terminal-key-bar",
|
|
3385
3457
|
role: "toolbar",
|
|
3386
3458
|
"aria-label": "Terminal keys",
|
|
3387
|
-
children: [
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3459
|
+
children: [
|
|
3460
|
+
/* @__PURE__ */ jsx("button", {
|
|
3461
|
+
type: "button",
|
|
3462
|
+
tabIndex: -1,
|
|
3463
|
+
"aria-pressed": ctrl,
|
|
3464
|
+
className: ctrl ? "is-armed" : "",
|
|
3465
|
+
...pressOnTouchDown(onToggleCtrl),
|
|
3466
|
+
children: "Ctrl"
|
|
3467
|
+
}),
|
|
3468
|
+
keys.map(({ label, key, name }) => /* @__PURE__ */ jsx("button", {
|
|
3469
|
+
type: "button",
|
|
3470
|
+
tabIndex: -1,
|
|
3471
|
+
"aria-label": name ?? key,
|
|
3472
|
+
...pressOnTouchDown(() => {
|
|
3473
|
+
const bytes = terminalKeyBytes({
|
|
3474
|
+
key,
|
|
3475
|
+
ctrlKey: false,
|
|
3476
|
+
altKey: false
|
|
3477
|
+
});
|
|
3478
|
+
if (bytes) onBytes(bytes);
|
|
3479
|
+
}),
|
|
3480
|
+
children: label
|
|
3481
|
+
}, key)),
|
|
3482
|
+
voice?.available && /* @__PURE__ */ jsx(VoiceButton, { voice })
|
|
3483
|
+
]
|
|
3410
3484
|
});
|
|
3411
3485
|
}
|
|
3412
3486
|
//#endregion
|
|
3413
3487
|
//#region src/client/visual-viewport.ts
|
|
3414
3488
|
var COARSE_POINTER = "(pointer: coarse)";
|
|
3489
|
+
var KEYBOARD_MIN_HEIGHT = 120;
|
|
3490
|
+
var KEYBOARD_ANIMATION_MS = 350;
|
|
3415
3491
|
function trackVisualViewport() {
|
|
3416
3492
|
const viewport = window.visualViewport;
|
|
3417
3493
|
if (!viewport || !matchMedia(COARSE_POINTER).matches) return () => {};
|
|
3418
3494
|
const root = document.documentElement;
|
|
3419
|
-
|
|
3495
|
+
let tallestViewport = viewport.height;
|
|
3496
|
+
const fitToKeyboard = () => {
|
|
3420
3497
|
root.style.setProperty("--app-height", `${viewport.height}px`);
|
|
3421
3498
|
root.style.setProperty("--app-top", `${viewport.offsetTop}px`);
|
|
3422
3499
|
};
|
|
3500
|
+
const fillScreen = () => {
|
|
3501
|
+
root.style.removeProperty("--app-height");
|
|
3502
|
+
root.style.removeProperty("--app-top");
|
|
3503
|
+
};
|
|
3504
|
+
const sync = () => {
|
|
3505
|
+
tallestViewport = Math.max(tallestViewport, viewport.height, window.innerHeight);
|
|
3506
|
+
const keyboardOpen = tallestViewport - viewport.height > KEYBOARD_MIN_HEIGHT;
|
|
3507
|
+
if (keyboardOpen) fitToKeyboard();
|
|
3508
|
+
else fillScreen();
|
|
3509
|
+
root.toggleAttribute("data-keyboard-open", keyboardOpen);
|
|
3510
|
+
};
|
|
3423
3511
|
sync();
|
|
3512
|
+
let settle;
|
|
3513
|
+
const syncAfterKeyboardAnimation = () => {
|
|
3514
|
+
clearTimeout(settle);
|
|
3515
|
+
settle = setTimeout(sync, KEYBOARD_ANIMATION_MS);
|
|
3516
|
+
};
|
|
3517
|
+
const forgetTallestViewport = () => {
|
|
3518
|
+
tallestViewport = 0;
|
|
3519
|
+
sync();
|
|
3520
|
+
};
|
|
3424
3521
|
viewport.addEventListener("resize", sync);
|
|
3425
3522
|
viewport.addEventListener("scroll", sync);
|
|
3523
|
+
window.addEventListener("orientationchange", forgetTallestViewport);
|
|
3524
|
+
window.addEventListener("focusout", syncAfterKeyboardAnimation);
|
|
3525
|
+
window.addEventListener("focusin", syncAfterKeyboardAnimation);
|
|
3426
3526
|
return () => {
|
|
3527
|
+
clearTimeout(settle);
|
|
3528
|
+
window.removeEventListener("focusout", syncAfterKeyboardAnimation);
|
|
3529
|
+
window.removeEventListener("focusin", syncAfterKeyboardAnimation);
|
|
3530
|
+
window.removeEventListener("orientationchange", forgetTallestViewport);
|
|
3427
3531
|
viewport.removeEventListener("resize", sync);
|
|
3428
3532
|
viewport.removeEventListener("scroll", sync);
|
|
3429
|
-
|
|
3430
|
-
root.
|
|
3533
|
+
fillScreen();
|
|
3534
|
+
root.removeAttribute("data-keyboard-open");
|
|
3431
3535
|
};
|
|
3432
3536
|
}
|
|
3433
3537
|
function matchesCoarsePointer() {
|
|
@@ -3601,6 +3705,188 @@ function useTerminalNotice() {
|
|
|
3601
3705
|
};
|
|
3602
3706
|
}
|
|
3603
3707
|
//#endregion
|
|
3708
|
+
//#region src/client/voice-recorder.ts
|
|
3709
|
+
var TARGET_SAMPLE_RATE = 16e3;
|
|
3710
|
+
var CAPTURE_PROCESSOR = `registerProcessor('webr-capture', class extends AudioWorkletProcessor {
|
|
3711
|
+
process([input]) { if (input?.[0]) this.port.postMessage(input[0].slice()); return true; }
|
|
3712
|
+
});`;
|
|
3713
|
+
var canRecordAudio = () => typeof window !== "undefined" && window.isSecureContext && !!navigator.mediaDevices?.getUserMedia && typeof AudioWorkletNode !== "undefined";
|
|
3714
|
+
var createAudioContext = () => {
|
|
3715
|
+
try {
|
|
3716
|
+
return new AudioContext({ sampleRate: TARGET_SAMPLE_RATE });
|
|
3717
|
+
} catch {
|
|
3718
|
+
return new AudioContext();
|
|
3719
|
+
}
|
|
3720
|
+
};
|
|
3721
|
+
function toInt16Pcm(chunks) {
|
|
3722
|
+
const pcm = new Int16Array(chunks.reduce((total, chunk) => total + chunk.length, 0));
|
|
3723
|
+
let offset = 0;
|
|
3724
|
+
for (const chunk of chunks) for (const sample of chunk) pcm[offset++] = Math.max(-1, Math.min(1, sample)) * 32767;
|
|
3725
|
+
return pcm.buffer;
|
|
3726
|
+
}
|
|
3727
|
+
async function loadCaptureProcessor(context) {
|
|
3728
|
+
const url = URL.createObjectURL(new Blob([CAPTURE_PROCESSOR], { type: "text/javascript" }));
|
|
3729
|
+
try {
|
|
3730
|
+
await context.audioWorklet.addModule(url);
|
|
3731
|
+
} finally {
|
|
3732
|
+
URL.revokeObjectURL(url);
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
async function startRecording() {
|
|
3736
|
+
const context = createAudioContext();
|
|
3737
|
+
context.resume();
|
|
3738
|
+
const release = (stream) => {
|
|
3739
|
+
stream?.getTracks().forEach((track) => track.stop());
|
|
3740
|
+
context.close();
|
|
3741
|
+
};
|
|
3742
|
+
let stream;
|
|
3743
|
+
try {
|
|
3744
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: {
|
|
3745
|
+
channelCount: 1,
|
|
3746
|
+
echoCancellation: true,
|
|
3747
|
+
noiseSuppression: true,
|
|
3748
|
+
autoGainControl: true
|
|
3749
|
+
} });
|
|
3750
|
+
await loadCaptureProcessor(context);
|
|
3751
|
+
await context.resume();
|
|
3752
|
+
} catch (error) {
|
|
3753
|
+
release(stream);
|
|
3754
|
+
throw error;
|
|
3755
|
+
}
|
|
3756
|
+
const chunks = [];
|
|
3757
|
+
const source = context.createMediaStreamSource(stream);
|
|
3758
|
+
const capture = new AudioWorkletNode(context, "webr-capture");
|
|
3759
|
+
capture.port.onmessage = (event) => chunks.push(event.data);
|
|
3760
|
+
source.connect(capture);
|
|
3761
|
+
const finish = () => {
|
|
3762
|
+
source.disconnect();
|
|
3763
|
+
capture.disconnect();
|
|
3764
|
+
release(stream);
|
|
3765
|
+
};
|
|
3766
|
+
return {
|
|
3767
|
+
stop: async () => {
|
|
3768
|
+
const sampleRate = context.sampleRate;
|
|
3769
|
+
finish();
|
|
3770
|
+
return {
|
|
3771
|
+
pcm: toInt16Pcm(chunks),
|
|
3772
|
+
sampleRate
|
|
3773
|
+
};
|
|
3774
|
+
},
|
|
3775
|
+
cancel: finish
|
|
3776
|
+
};
|
|
3777
|
+
}
|
|
3778
|
+
//#endregion
|
|
3779
|
+
//#region src/client/voice.ts
|
|
3780
|
+
var voiceErrors = {
|
|
3781
|
+
voice_unavailable: "Voice input is not available on this Webr server.",
|
|
3782
|
+
image_too_large: "The recording is too long."
|
|
3783
|
+
};
|
|
3784
|
+
async function voiceState() {
|
|
3785
|
+
const response = await fetch("/api/voice").catch(() => void 0);
|
|
3786
|
+
return response?.ok ? (await response.json()).state : "unavailable";
|
|
3787
|
+
}
|
|
3788
|
+
async function warmVoice() {
|
|
3789
|
+
const response = await fetch("/api/voice/warm", {
|
|
3790
|
+
method: "POST",
|
|
3791
|
+
headers: { "Content-Type": "application/json" },
|
|
3792
|
+
body: "{}"
|
|
3793
|
+
}).catch(() => void 0);
|
|
3794
|
+
return response?.ok ? (await response.json()).state : "unavailable";
|
|
3795
|
+
}
|
|
3796
|
+
async function transcribe(pcm, sampleRate) {
|
|
3797
|
+
const response = await fetch(`/api/voice/transcribe?sampleRate=${sampleRate}`, {
|
|
3798
|
+
method: "POST",
|
|
3799
|
+
headers: { "Content-Type": "audio/l16" },
|
|
3800
|
+
body: pcm
|
|
3801
|
+
});
|
|
3802
|
+
const result = await response.json().catch(() => ({}));
|
|
3803
|
+
if (!response.ok || result.text === void 0) throw new Error(voiceErrors[result.error ?? ""] ?? "The recording could not be transcribed.");
|
|
3804
|
+
return result.text;
|
|
3805
|
+
}
|
|
3806
|
+
//#endregion
|
|
3807
|
+
//#region src/components/useVoiceInput.ts
|
|
3808
|
+
var DOWNLOAD_POLL_MS = 2e3;
|
|
3809
|
+
var DOWNLOADING = "Downloading the voice model (670 MB, one time). The mic works when it finishes.";
|
|
3810
|
+
var isDownloadPending = (state) => state === "needs-download" || state === "downloading";
|
|
3811
|
+
var microphoneError = (error) => error instanceof DOMException && error.name === "NotAllowedError" ? "Allow microphone access for Webr in your browser settings." : "The microphone could not start.";
|
|
3812
|
+
function useVoiceInput({ send, show }) {
|
|
3813
|
+
const [state, setState] = useState("unavailable");
|
|
3814
|
+
const [phase, setPhase] = useState("idle");
|
|
3815
|
+
const recorder = useRef(void 0);
|
|
3816
|
+
const sendRef = useRef(send);
|
|
3817
|
+
sendRef.current = send;
|
|
3818
|
+
useEffect(() => {
|
|
3819
|
+
if (!canRecordAudio()) return;
|
|
3820
|
+
let cancelled = false;
|
|
3821
|
+
voiceState().then((current) => {
|
|
3822
|
+
if (!cancelled) setState(current);
|
|
3823
|
+
});
|
|
3824
|
+
return () => {
|
|
3825
|
+
cancelled = true;
|
|
3826
|
+
recorder.current?.cancel();
|
|
3827
|
+
};
|
|
3828
|
+
}, []);
|
|
3829
|
+
useEffect(() => {
|
|
3830
|
+
if (phase !== "preparing") return;
|
|
3831
|
+
const poll = setInterval(() => void voiceState().then((current) => {
|
|
3832
|
+
if (isDownloadPending(current)) return;
|
|
3833
|
+
setState(current);
|
|
3834
|
+
setPhase("idle");
|
|
3835
|
+
show(current === "ready" ? "Voice input is ready. Tap the mic to talk." : "The voice model could not be downloaded.", current === "ready" ? "info" : "error", 4e3);
|
|
3836
|
+
}), DOWNLOAD_POLL_MS);
|
|
3837
|
+
return () => clearInterval(poll);
|
|
3838
|
+
}, [phase, show]);
|
|
3839
|
+
const prepare = useCallback(() => {
|
|
3840
|
+
warmVoice();
|
|
3841
|
+
setPhase("preparing");
|
|
3842
|
+
show(DOWNLOADING, "info");
|
|
3843
|
+
}, [show]);
|
|
3844
|
+
const record = useCallback(async () => {
|
|
3845
|
+
setPhase("recording");
|
|
3846
|
+
const starting = startRecording();
|
|
3847
|
+
warmVoice();
|
|
3848
|
+
try {
|
|
3849
|
+
recorder.current = await starting;
|
|
3850
|
+
} catch (error) {
|
|
3851
|
+
setPhase("idle");
|
|
3852
|
+
show(microphoneError(error), "error", 5e3);
|
|
3853
|
+
}
|
|
3854
|
+
}, [show]);
|
|
3855
|
+
const finish = useCallback(async () => {
|
|
3856
|
+
const active = recorder.current;
|
|
3857
|
+
recorder.current = void 0;
|
|
3858
|
+
if (!active) return;
|
|
3859
|
+
setPhase("transcribing");
|
|
3860
|
+
try {
|
|
3861
|
+
const { pcm, sampleRate } = await active.stop();
|
|
3862
|
+
const text = await transcribe(pcm, sampleRate);
|
|
3863
|
+
if (text) sendRef.current(text);
|
|
3864
|
+
else show("No speech was heard.", "info", 2500);
|
|
3865
|
+
} catch (error) {
|
|
3866
|
+
show(error instanceof Error ? error.message : "The recording could not be transcribed.", "error", 5e3);
|
|
3867
|
+
} finally {
|
|
3868
|
+
setPhase("idle");
|
|
3869
|
+
}
|
|
3870
|
+
}, [show]);
|
|
3871
|
+
const toggle = useCallback(() => {
|
|
3872
|
+
if (phase === "idle") {
|
|
3873
|
+
if (isDownloadPending(state)) prepare();
|
|
3874
|
+
else record();
|
|
3875
|
+
} else if (phase === "recording") finish();
|
|
3876
|
+
}, [
|
|
3877
|
+
phase,
|
|
3878
|
+
state,
|
|
3879
|
+
prepare,
|
|
3880
|
+
record,
|
|
3881
|
+
finish
|
|
3882
|
+
]);
|
|
3883
|
+
return {
|
|
3884
|
+
available: state !== "unavailable",
|
|
3885
|
+
phase,
|
|
3886
|
+
toggle
|
|
3887
|
+
};
|
|
3888
|
+
}
|
|
3889
|
+
//#endregion
|
|
3604
3890
|
//#region src/components/TerminalPane.tsx
|
|
3605
3891
|
function themeColors() {
|
|
3606
3892
|
const styles = getComputedStyle(document.documentElement);
|
|
@@ -3659,6 +3945,12 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
3659
3945
|
control.current?.input(text, true);
|
|
3660
3946
|
}
|
|
3661
3947
|
});
|
|
3948
|
+
const voice = useVoiceInput({
|
|
3949
|
+
show,
|
|
3950
|
+
send: (text) => {
|
|
3951
|
+
control.current?.input(text, true);
|
|
3952
|
+
}
|
|
3953
|
+
});
|
|
3662
3954
|
const showCopyResult = useRef((copied) => {});
|
|
3663
3955
|
showCopyResult.current = (copied) => copied ? show("Copied to clipboard", "info", 1200) : show("The browser blocked clipboard access.", "error", 4e3);
|
|
3664
3956
|
useEffect(() => {
|
|
@@ -3917,7 +4209,8 @@ function TerminalPane({ pane, machineId, threadId, active, canControl, onFocus }
|
|
|
3917
4209
|
canControl && active && touch && inputFocused && /* @__PURE__ */ jsx(TerminalKeyBar, {
|
|
3918
4210
|
ctrl,
|
|
3919
4211
|
onToggleCtrl: () => setCtrl((armed) => !armed),
|
|
3920
|
-
onBytes: (bytes) => control.current?.input(bytes)
|
|
4212
|
+
onBytes: (bytes) => control.current?.input(bytes),
|
|
4213
|
+
voice
|
|
3921
4214
|
})
|
|
3922
4215
|
]
|
|
3923
4216
|
});
|
|
@@ -4153,6 +4446,7 @@ function useClearDoneOnVisit(thread, paneId, enabled) {
|
|
|
4153
4446
|
}
|
|
4154
4447
|
//#endregion
|
|
4155
4448
|
//#region src/components/App.tsx
|
|
4449
|
+
var keepTerminalFocus = (event) => event.preventDefault();
|
|
4156
4450
|
function App(props) {
|
|
4157
4451
|
return /* @__PURE__ */ jsx(CrashReport, { children: /* @__PURE__ */ jsx(RuntimeProvider, {
|
|
4158
4452
|
bootstrap: props.bootstrap,
|
|
@@ -4353,12 +4647,14 @@ function RuntimeApp({ page, bootstrap, threadId, projectId }) {
|
|
|
4353
4647
|
className: "mobile-controls",
|
|
4354
4648
|
children: [/* @__PURE__ */ jsx("button", {
|
|
4355
4649
|
"aria-label": "Open sidebar",
|
|
4650
|
+
onPointerDown: keepTerminalFocus,
|
|
4356
4651
|
onClick: toggleSidebar,
|
|
4357
|
-
children: /* @__PURE__ */ jsx(PanelLeft, { size:
|
|
4652
|
+
children: /* @__PURE__ */ jsx(PanelLeft, { size: 22 })
|
|
4358
4653
|
}), /* @__PURE__ */ jsx("button", {
|
|
4359
4654
|
"aria-label": "Open command palette",
|
|
4655
|
+
onPointerDown: keepTerminalFocus,
|
|
4360
4656
|
onClick: () => setPaletteOpen(true),
|
|
4361
|
-
children: /* @__PURE__ */ jsx(
|
|
4657
|
+
children: /* @__PURE__ */ jsx(Command, { size: 22 })
|
|
4362
4658
|
})]
|
|
4363
4659
|
}),
|
|
4364
4660
|
false,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
|
|
2
2
|
import { S as createAstro, i as renderComponent, u as renderTemplate } from "./server_CnGYDmxV.mjs";
|
|
3
3
|
import { t as createComponent } from "./compiler_BiU10Vds.mjs";
|
|
4
|
-
import { n as $$Base, t as App } from "./
|
|
4
|
+
import { n as $$Base, t as App } from "./App_C2vmjHiY.mjs";
|
|
5
5
|
//#region src/pages/threads/[id].astro
|
|
6
6
|
var _id__exports = /* @__PURE__ */ __exportAll({
|
|
7
7
|
default: () => $$Id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
|
|
2
2
|
import { S as createAstro, i as renderComponent, u as renderTemplate } from "./server_CnGYDmxV.mjs";
|
|
3
3
|
import { t as createComponent } from "./compiler_BiU10Vds.mjs";
|
|
4
|
-
import { n as $$Base, t as App } from "./
|
|
4
|
+
import { n as $$Base, t as App } from "./App_C2vmjHiY.mjs";
|
|
5
5
|
//#region src/pages/sessions/[session]/tabs/[tab].astro
|
|
6
6
|
var _tab__exports = /* @__PURE__ */ __exportAll({
|
|
7
7
|
default: () => $$Tab,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
|
|
2
2
|
import { S as createAstro, i as renderComponent, u as renderTemplate } from "./server_CnGYDmxV.mjs";
|
|
3
3
|
import { t as createComponent } from "./compiler_BiU10Vds.mjs";
|
|
4
|
-
import { n as $$Base, t as App } from "./
|
|
4
|
+
import { n as $$Base, t as App } from "./App_C2vmjHiY.mjs";
|
|
5
5
|
//#region src/pages/new.astro
|
|
6
6
|
var new_exports = /* @__PURE__ */ __exportAll({
|
|
7
7
|
default: () => $$New,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as __exportAll } from "./rolldown-runtime_BMI-E3GI.mjs";
|
|
2
2
|
import { S as createAstro, i as renderComponent, u as renderTemplate } from "./server_CnGYDmxV.mjs";
|
|
3
3
|
import { t as createComponent } from "./compiler_BiU10Vds.mjs";
|
|
4
|
-
import { n as $$Base, t as App } from "./
|
|
4
|
+
import { n as $$Base, t as App } from "./App_C2vmjHiY.mjs";
|
|
5
5
|
//#region src/pages/settings.astro
|
|
6
6
|
var settings_exports = /* @__PURE__ */ __exportAll({
|
|
7
7
|
default: () => $$Settings,
|
package/dist/server/entry.mjs
CHANGED
|
@@ -2427,10 +2427,10 @@ var renderers = [Object.assign({
|
|
|
2427
2427
|
//#endregion
|
|
2428
2428
|
//#region \0virtual:astro:pages
|
|
2429
2429
|
var _page0 = () => import("./chunks/node_BcIF-BVp.mjs").then((n) => n.t);
|
|
2430
|
-
var _page1 = () => import("./chunks/
|
|
2431
|
-
var _page2 = () => import("./chunks/
|
|
2432
|
-
var _page3 = () => import("./chunks/
|
|
2433
|
-
var _page4 = () => import("./chunks/
|
|
2430
|
+
var _page1 = () => import("./chunks/new_bTXSW7C3.mjs");
|
|
2431
|
+
var _page2 = () => import("./chunks/_tab__WmsbMlfC.mjs");
|
|
2432
|
+
var _page3 = () => import("./chunks/settings_DwzWmJBe.mjs");
|
|
2433
|
+
var _page4 = () => import("./chunks/_id__BimjoFCd.mjs");
|
|
2434
2434
|
var _page5 = () => import("./chunks/index_DRfLd22k.mjs");
|
|
2435
2435
|
var pageMap = /* @__PURE__ */ new Map([
|
|
2436
2436
|
["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],
|
|
@@ -2442,7 +2442,7 @@ var pageMap = /* @__PURE__ */ new Map([
|
|
|
2442
2442
|
]);
|
|
2443
2443
|
//#endregion
|
|
2444
2444
|
//#region \0virtual:astro:manifest
|
|
2445
|
-
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.
|
|
2445
|
+
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.1VFY1ClT.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.1VFY1ClT.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.1VFY1ClT.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.1VFY1ClT.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__BimjoFCd.mjs","\u0000virtual:astro:page:src/pages/sessions/[session]/tabs/[tab]@_@astro":"chunks/_tab__WmsbMlfC.mjs","/home/runner/work/webr/webr/node_modules/.pnpm/sharp@0.35.5_@types+node@22.20.4/node_modules/sharp/dist/index.mjs":"chunks/dist_CpTFMtqT.mjs","\u0000virtual:astro:page:src/pages/index@_@astro":"chunks/index_DRfLd22k.mjs","\u0000virtual:astro:page:src/pages/new@_@astro":"chunks/new_bTXSW7C3.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_BcIF-BVp.mjs","\u0000virtual:astro:page:src/pages/settings@_@astro":"chunks/settings_DwzWmJBe.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_qIaxzsTp.mjs","/home/runner/work/webr/webr/src/components/App.tsx":"_astro/App.CGyf2WDA.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+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.CGyf2WDA.js","/_astro/ClientRouter.astro_astro_type_script_index_0_lang.CTgtIFyY.js","/_astro/addon-fit.jgKqzwky.js","/_astro/addon-web-links.C9lyQRxI.js","/_astro/client.BDkzSRUN.js","/_astro/client.Bbg9OBwT.js","/_astro/client.CLSsMr2g.js","/_astro/xterm.B-l5AIf6.js","/_astro/App.1VFY1ClT.css","/_astro/jetbrains-mono.CFJaiWaY.woff2","/_astro/symbols-nerd.CEdkKAK8.woff2"],"buildFormat":"directory","checkOrigin":true,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"SJv9JtyI4XxX0MOJWloaFJbCKvVL0wyh+LMju9Wv/1o=","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});
|
|
2446
2446
|
var manifestRoutes = _manifest.routes;
|
|
2447
2447
|
var manifest = Object.assign(_manifest, {
|
|
2448
2448
|
renderers,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pablopunk/webr",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Control your Herdr agents from anywhere.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"herdr",
|
|
@@ -84,5 +84,8 @@
|
|
|
84
84
|
"typescript": "5.9.3",
|
|
85
85
|
"vitest": "5.0.3",
|
|
86
86
|
"ws": "8.22.0"
|
|
87
|
+
},
|
|
88
|
+
"optionalDependencies": {
|
|
89
|
+
"sherpa-onnx-node": "^1.13.8"
|
|
87
90
|
}
|
|
88
91
|
}
|