@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.
@@ -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: () => setCreatingWorkspace(false)
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 copy = () => writeClipboardText(invite.token).then((ok) => {
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: () => setUrlIndex(index),
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
- function TerminalKeyBar({ ctrl, onToggleCtrl, onBytes }) {
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: [/* @__PURE__ */ jsx("button", {
3388
- type: "button",
3389
- tabIndex: -1,
3390
- "aria-pressed": ctrl,
3391
- className: ctrl ? "is-armed" : "",
3392
- onPointerDown: keepKeyboardOpen,
3393
- onClick: onToggleCtrl,
3394
- children: "Ctrl"
3395
- }), keys.map(({ label, key, name }) => /* @__PURE__ */ jsx("button", {
3396
- type: "button",
3397
- tabIndex: -1,
3398
- "aria-label": name ?? key,
3399
- onPointerDown: keepKeyboardOpen,
3400
- onClick: () => {
3401
- const bytes = terminalKeyBytes({
3402
- key,
3403
- ctrlKey: false,
3404
- altKey: false
3405
- });
3406
- if (bytes) onBytes(bytes);
3407
- },
3408
- children: label
3409
- }, key))]
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
- const sync = () => {
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
- root.style.removeProperty("--app-height");
3430
- root.style.removeProperty("--app-top");
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: 16 })
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(Search, { size: 16 })
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 "./App_C1XnVbA2.mjs";
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 "./App_C1XnVbA2.mjs";
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 "./App_C1XnVbA2.mjs";
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 "./App_C1XnVbA2.mjs";
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,
@@ -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/new_BfRTqcQ4.mjs");
2431
- var _page2 = () => import("./chunks/_tab__BJ-ULrm_.mjs");
2432
- var _page3 = () => import("./chunks/settings_BD_xdLnR.mjs");
2433
- var _page4 = () => import("./chunks/_id__CAx6DC51.mjs");
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.DijFEuO0.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.DijFEuO0.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.DijFEuO0.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.DijFEuO0.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__CAx6DC51.mjs","\u0000virtual:astro:page:src/pages/sessions/[session]/tabs/[tab]@_@astro":"chunks/_tab__BJ-ULrm_.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_BfRTqcQ4.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_BD_xdLnR.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.Z2LzeAW7.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.Z2LzeAW7.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.DijFEuO0.css","/_astro/jetbrains-mono.CFJaiWaY.woff2","/_astro/symbols-nerd.CEdkKAK8.woff2"],"buildFormat":"directory","checkOrigin":true,"actionBodySizeLimit":1048576,"serverIslandBodySizeLimit":1048576,"allowedDomains":[],"key":"SdLQO/gzpqcLAntfdRcrf7WtBDiQy1OYy4Y4ew2Wto8=","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
+ 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.7",
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
  }