@ottocode/web-sdk 0.1.267 → 0.1.269

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.
Files changed (51) hide show
  1. package/dist/components/file-browser/FileViewerPanel.d.ts +5 -1
  2. package/dist/components/file-browser/FileViewerPanel.d.ts.map +1 -1
  3. package/dist/components/git/GitDiffPanel.d.ts +5 -1
  4. package/dist/components/git/GitDiffPanel.d.ts.map +1 -1
  5. package/dist/components/git/GitDiffViewer.d.ts.map +1 -1
  6. package/dist/components/index.js +2246 -1962
  7. package/dist/components/index.js.map +58 -56
  8. package/dist/components/mcp/MCPSidebar.d.ts.map +1 -1
  9. package/dist/components/messages/ActionToolBox.d.ts.map +1 -1
  10. package/dist/components/messages/CompactActivityGroup.d.ts.map +1 -1
  11. package/dist/components/messages/MessagePartItem.d.ts.map +1 -1
  12. package/dist/components/messages/MessageThread.d.ts.map +1 -1
  13. package/dist/components/messages/UserMessageGroup.d.ts.map +1 -1
  14. package/dist/components/messages/renderers/BashRenderer.d.ts.map +1 -1
  15. package/dist/components/messages/renderers/DiffView.d.ts.map +1 -1
  16. package/dist/components/messages/threadDensity.d.ts +9 -0
  17. package/dist/components/messages/threadDensity.d.ts.map +1 -0
  18. package/dist/components/onboarding/OnboardingModal.d.ts +2 -0
  19. package/dist/components/onboarding/OnboardingModal.d.ts.map +1 -1
  20. package/dist/components/session-files/SessionFilesDiffPanel.d.ts +5 -1
  21. package/dist/components/session-files/SessionFilesDiffPanel.d.ts.map +1 -1
  22. package/dist/components/sessions/LeanHeader.d.ts.map +1 -1
  23. package/dist/components/sessions/SessionHeader.d.ts.map +1 -1
  24. package/dist/components/settings/SettingsSidebar.d.ts.map +1 -1
  25. package/dist/components/skills/SkillViewerPanel.d.ts +5 -1
  26. package/dist/components/skills/SkillViewerPanel.d.ts.map +1 -1
  27. package/dist/components/skills/SkillsSidebar.d.ts.map +1 -1
  28. package/dist/components/ui/Toaster.d.ts.map +1 -1
  29. package/dist/hooks/index.d.ts +2 -0
  30. package/dist/hooks/index.d.ts.map +1 -1
  31. package/dist/hooks/index.js +439 -121
  32. package/dist/hooks/index.js.map +11 -7
  33. package/dist/hooks/useAuthStatus.d.ts.map +1 -1
  34. package/dist/hooks/useClientEvents.d.ts +2 -0
  35. package/dist/hooks/useClientEvents.d.ts.map +1 -0
  36. package/dist/hooks/useContainerWidth.d.ts +7 -0
  37. package/dist/hooks/useContainerWidth.d.ts.map +1 -0
  38. package/dist/hooks/usePreferences.d.ts.map +1 -1
  39. package/dist/index.js +2511 -1981
  40. package/dist/index.js.map +60 -56
  41. package/dist/lib/index.d.ts +1 -0
  42. package/dist/lib/index.d.ts.map +1 -1
  43. package/dist/lib/index.js +54 -1
  44. package/dist/lib/index.js.map +5 -4
  45. package/dist/lib/open-url.d.ts.map +1 -1
  46. package/dist/lib/platform.d.ts +14 -0
  47. package/dist/lib/platform.d.ts.map +1 -0
  48. package/dist/stores/index.js.map +2 -2
  49. package/dist/stores/toastStore.d.ts +5 -2
  50. package/dist/stores/toastStore.d.ts.map +1 -1
  51. package/package.json +3 -3
@@ -1007,6 +1007,55 @@ function useUpdateDefaults() {
1007
1007
  }
1008
1008
  // src/hooks/usePreferences.ts
1009
1009
  import { useCallback, useMemo, useSyncExternalStore } from "react";
1010
+
1011
+ // src/lib/platform.ts
1012
+ function getPlatformWindow() {
1013
+ if (typeof window === "undefined")
1014
+ return null;
1015
+ return window;
1016
+ }
1017
+ function openPlatformUrl(url) {
1018
+ const win = getPlatformWindow();
1019
+ if (!win?.OTTO_OPEN_URL)
1020
+ return false;
1021
+ win.OTTO_OPEN_URL(url);
1022
+ return true;
1023
+ }
1024
+ function showPlatformNotification(notification) {
1025
+ const win = getPlatformWindow();
1026
+ if (!win?.OTTO_SHOW_NOTIFICATION)
1027
+ return false;
1028
+ win.OTTO_SHOW_NOTIFICATION(notification);
1029
+ return true;
1030
+ }
1031
+ function listPlatformSystemFonts() {
1032
+ const win = getPlatformWindow();
1033
+ if (!win?.OTTO_LIST_SYSTEM_FONTS)
1034
+ return null;
1035
+ return win.OTTO_LIST_SYSTEM_FONTS();
1036
+ }
1037
+ function notifyPlatformFontFamilyChanged(fontFamily) {
1038
+ const win = getPlatformWindow();
1039
+ if (!win?.OTTO_SET_DESKTOP_FONT)
1040
+ return false;
1041
+ win.OTTO_SET_DESKTOP_FONT(fontFamily);
1042
+ return true;
1043
+ }
1044
+ function openPlatformSession(sessionId) {
1045
+ const win = getPlatformWindow();
1046
+ if (!win?.OTTO_OPEN_SESSION)
1047
+ return false;
1048
+ win.OTTO_OPEN_SESSION(sessionId);
1049
+ return true;
1050
+ }
1051
+ function hasPlatformOpenUrl() {
1052
+ return !!getPlatformWindow()?.OTTO_OPEN_URL;
1053
+ }
1054
+ function hasPlatformSystemFonts() {
1055
+ return !!getPlatformWindow()?.OTTO_LIST_SYSTEM_FONTS;
1056
+ }
1057
+
1058
+ // src/hooks/usePreferences.ts
1010
1059
  var STORAGE_KEY = "otto-preferences";
1011
1060
  var DEFAULT_FONT_FAMILY = "IBM Plex Mono";
1012
1061
  var DEFAULT_STORED_PREFERENCES = {
@@ -1027,6 +1076,9 @@ function applyFontFamily(fontFamily) {
1027
1076
  }
1028
1077
  document.documentElement.style.setProperty("--otto-font-family", cssFontFamily(fontFamily));
1029
1078
  document.documentElement.dataset.ottoFontFamily = fontFamily;
1079
+ if (notifyPlatformFontFamilyChanged(fontFamily)) {
1080
+ return;
1081
+ }
1030
1082
  if (window.self !== window.top) {
1031
1083
  window.parent.postMessage({ type: "otto-font-family-changed", fontFamily }, "*");
1032
1084
  }
@@ -2656,8 +2708,294 @@ function useSessionStream(sessionId, enabled = true) {
2656
2708
  updatePendingApproval
2657
2709
  ]);
2658
2710
  }
2711
+ // src/hooks/useClientEvents.ts
2712
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
2713
+ import { useQueryClient as useQueryClient6 } from "@tanstack/react-query";
2714
+ import {
2715
+ buildClientEventsStreamUrl,
2716
+ createClientEventsStream
2717
+ } from "@ottocode/api";
2718
+
2719
+ // src/stores/toastStore.ts
2720
+ import { create as create10 } from "zustand";
2721
+ var toastId = 0;
2722
+ var useToastStore = create10((set) => ({
2723
+ toasts: [],
2724
+ addToast: (toast) => {
2725
+ const id = `toast-${++toastId}`;
2726
+ set((state) => ({
2727
+ toasts: [...state.toasts, { ...toast, id }]
2728
+ }));
2729
+ return id;
2730
+ },
2731
+ removeToast: (id) => set((state) => ({
2732
+ toasts: state.toasts.filter((t) => t.id !== id)
2733
+ })),
2734
+ updateToast: (id, updates) => set((state) => ({
2735
+ toasts: state.toasts.map((t) => t.id === id ? { ...t, ...updates } : t)
2736
+ })),
2737
+ clearToasts: () => set({ toasts: [] })
2738
+ }));
2739
+ function toast(message, type = "default", duration = 4000) {
2740
+ const id = useToastStore.getState().addToast({ message, type, duration });
2741
+ if (duration > 0) {
2742
+ setTimeout(() => {
2743
+ useToastStore.getState().removeToast(id);
2744
+ }, duration);
2745
+ }
2746
+ return id;
2747
+ }
2748
+ toast.success = (message, duration = 4000) => toast(message, "success", duration);
2749
+ toast.error = (message, duration = 5000) => toast(message, "error", duration);
2750
+ toast.info = (message, duration = 4000) => toast(message, "default", duration);
2751
+ toast.loading = (message) => toast(message, "loading", 0);
2752
+ toast.successWithAction = (message, action, duration = 6000) => {
2753
+ const id = useToastStore.getState().addToast({
2754
+ message,
2755
+ type: "success",
2756
+ duration,
2757
+ action
2758
+ });
2759
+ if (duration > 0) {
2760
+ setTimeout(() => {
2761
+ useToastStore.getState().removeToast(id);
2762
+ }, duration);
2763
+ }
2764
+ return id;
2765
+ };
2766
+
2767
+ // src/lib/open-url.ts
2768
+ function openUrl(url) {
2769
+ if (openPlatformUrl(url)) {
2770
+ return;
2771
+ }
2772
+ if (window.self !== window.top) {
2773
+ window.parent.postMessage({ type: "otto-open-url", url }, "*");
2774
+ } else {
2775
+ window.open(url, "_blank", "noopener,noreferrer");
2776
+ }
2777
+ }
2778
+
2779
+ // src/hooks/useClientEvents.ts
2780
+ function toastTypeForLevel(level) {
2781
+ if (level === "success")
2782
+ return "success";
2783
+ if (level === "error")
2784
+ return "error";
2785
+ return "default";
2786
+ }
2787
+ function notificationTargetHref(notification) {
2788
+ return notification.action?.href ?? (notification.sessionId ? `/sessions/${encodeURIComponent(notification.sessionId)}` : undefined);
2789
+ }
2790
+ function openNotificationTarget(notification) {
2791
+ const href = notificationTargetHref(notification);
2792
+ if (!href || typeof window === "undefined")
2793
+ return;
2794
+ if (notification.sessionId && openPlatformSession(notification.sessionId)) {
2795
+ return;
2796
+ }
2797
+ if (href.startsWith("/")) {
2798
+ window.location.href = href;
2799
+ return;
2800
+ }
2801
+ openUrl(href);
2802
+ }
2803
+ function requestNotificationPermission() {
2804
+ return new Promise((resolve) => {
2805
+ let settled = false;
2806
+ const finish = (permission) => {
2807
+ if (settled)
2808
+ return;
2809
+ settled = true;
2810
+ setTimeout(() => resolve(permission ?? Notification.permission), 100);
2811
+ };
2812
+ try {
2813
+ const result = Notification.requestPermission(finish);
2814
+ if (result && typeof result.then === "function") {
2815
+ result.then(finish).catch(() => finish());
2816
+ }
2817
+ } catch {
2818
+ finish();
2819
+ }
2820
+ setTimeout(() => finish(), 1500);
2821
+ });
2822
+ }
2823
+ function showInAppNotification(notification) {
2824
+ const message = notification.body ? `${notification.title}: ${notification.body}` : notification.title;
2825
+ const targetHref = notificationTargetHref(notification);
2826
+ if (targetHref) {
2827
+ const id = toast(message, toastTypeForLevel(notification.level), 6000);
2828
+ useToastStore.getState().updateToast(id, {
2829
+ activateActionOnClick: true,
2830
+ action: notification.action ? {
2831
+ ...notification.action,
2832
+ onClick: () => openNotificationTarget(notification)
2833
+ } : {
2834
+ label: "Open session",
2835
+ onClick: () => openNotificationTarget(notification)
2836
+ }
2837
+ });
2838
+ return;
2839
+ }
2840
+ toast(message, toastTypeForLevel(notification.level), 5000);
2841
+ }
2842
+ function sendBrowserNotification(notification) {
2843
+ if (typeof window === "undefined")
2844
+ return false;
2845
+ if (showPlatformNotification(notification))
2846
+ return true;
2847
+ if (window.parent && window.parent !== window) {
2848
+ const message = {
2849
+ type: "otto-notification",
2850
+ notification
2851
+ };
2852
+ window.parent.postMessage(message, "*");
2853
+ return true;
2854
+ }
2855
+ if (!("Notification" in window) || Notification.permission !== "granted")
2856
+ return false;
2857
+ const browserNotification = new Notification(notification.title, {
2858
+ body: notification.body,
2859
+ tag: notification.id,
2860
+ data: { href: notificationTargetHref(notification) }
2861
+ });
2862
+ browserNotification.onclick = () => {
2863
+ window.focus();
2864
+ openNotificationTarget(notification);
2865
+ browserNotification.close();
2866
+ };
2867
+ return true;
2868
+ }
2869
+ function updateSessionStatusInCache(queryClient, status) {
2870
+ queryClient.setQueryData(sessionsQueryKey, (old) => {
2871
+ if (!old)
2872
+ return old;
2873
+ return {
2874
+ ...old,
2875
+ pages: old.pages.map((page) => ({
2876
+ ...page,
2877
+ items: page.items.map((session) => session.id === status.sessionId ? {
2878
+ ...session,
2879
+ isRunning: status.status === "running"
2880
+ } : session)
2881
+ }))
2882
+ };
2883
+ });
2884
+ }
2885
+ function isLocalApiUrl(baseUrl) {
2886
+ try {
2887
+ const { hostname } = new URL(baseUrl);
2888
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname.startsWith("192.168.") || hostname.startsWith("10.") || /^172\.(1[6-9]|2\d|3[01])\./.test(hostname);
2889
+ } catch {
2890
+ return false;
2891
+ }
2892
+ }
2893
+ async function requestLocalhostAccess(baseUrl) {
2894
+ const response = await fetch(new URL("/openapi.json", baseUrl), {
2895
+ cache: "no-store",
2896
+ credentials: "include"
2897
+ });
2898
+ if (!response.ok) {
2899
+ throw new Error(`Local API returned ${response.status}`);
2900
+ }
2901
+ }
2902
+ function useClientEvents(activeSessionId) {
2903
+ const queryClient = useQueryClient6();
2904
+ const activeSessionIdRef = useRef2(activeSessionId);
2905
+ useEffect2(() => {
2906
+ activeSessionIdRef.current = activeSessionId;
2907
+ }, [activeSessionId]);
2908
+ useEffect2(() => {
2909
+ if (typeof window === "undefined" || window.parent !== window)
2910
+ return;
2911
+ if (!("Notification" in window))
2912
+ return;
2913
+ if (Notification.permission !== "default")
2914
+ return;
2915
+ if (window.localStorage.getItem("otto-notification-permission-prompted")) {
2916
+ return;
2917
+ }
2918
+ window.localStorage.setItem("otto-notification-permission-prompted", "1");
2919
+ const id = toast("Enable browser notifications for background session updates.", "default", 0);
2920
+ useToastStore.getState().updateToast(id, {
2921
+ action: {
2922
+ label: "Enable",
2923
+ onClick: async () => {
2924
+ const permission = await requestNotificationPermission();
2925
+ const currentPermission = Notification.permission;
2926
+ if (permission === "granted" || currentPermission === "granted") {
2927
+ toast.success("Browser notifications enabled.");
2928
+ } else {
2929
+ toast.info("Browser notifications were not enabled.");
2930
+ }
2931
+ }
2932
+ }
2933
+ });
2934
+ }, []);
2935
+ useEffect2(() => {
2936
+ const controller = new AbortController;
2937
+ let hasShownLocalAccessToast = false;
2938
+ const baseUrl = getBaseUrl();
2939
+ createClientEventsStream({
2940
+ baseUrl,
2941
+ onEvent: (event) => {
2942
+ if (event.event === "heartbeat")
2943
+ return;
2944
+ let payload;
2945
+ try {
2946
+ payload = JSON.parse(event.data);
2947
+ } catch (error) {
2948
+ console.error("[client-events] Failed to parse event:", error);
2949
+ return;
2950
+ }
2951
+ if (event.event === "session.status") {
2952
+ const status = payload;
2953
+ updateSessionStatusInCache(queryClient, status);
2954
+ if (status.status !== "running") {
2955
+ queryClient.invalidateQueries({
2956
+ queryKey: sessionsQueryKey
2957
+ });
2958
+ }
2959
+ return;
2960
+ }
2961
+ if (event.event === "notification") {
2962
+ const notification = payload;
2963
+ const isActiveVisibleSession = notification.sessionId === activeSessionIdRef.current && document.visibilityState === "visible";
2964
+ const isSessionNotification = notification.source === "session" || !!notification.sessionId;
2965
+ let sentSystemNotification = false;
2966
+ if (!isActiveVisibleSession) {
2967
+ sentSystemNotification = sendBrowserNotification(notification);
2968
+ }
2969
+ if (!isSessionNotification || !sentSystemNotification && !isActiveVisibleSession) {
2970
+ showInAppNotification(notification);
2971
+ }
2972
+ }
2973
+ },
2974
+ onError: (error) => {
2975
+ if (!controller.signal.aborted) {
2976
+ console.error("[client-events] Stream error:", error);
2977
+ if (!hasShownLocalAccessToast && isLocalApiUrl(baseUrl)) {
2978
+ hasShownLocalAccessToast = true;
2979
+ const id = toast("Safari may need permission to access the local otto server.", "default", 0);
2980
+ useToastStore.getState().updateToast(id, {
2981
+ action: {
2982
+ label: "Allow access",
2983
+ onClick: async () => {
2984
+ await requestLocalhostAccess(baseUrl);
2985
+ toast.success("Local otto server access confirmed.");
2986
+ }
2987
+ }
2988
+ });
2989
+ }
2990
+ }
2991
+ }
2992
+ }, controller.signal);
2993
+ return () => controller.abort();
2994
+ }, [queryClient]);
2995
+ return buildClientEventsStreamUrl({ baseUrl: getBaseUrl() });
2996
+ }
2659
2997
  // src/hooks/useTheme.ts
2660
- import { useEffect as useEffect2, useState, useCallback as useCallback2, useMemo as useMemo3 } from "react";
2998
+ import { useEffect as useEffect3, useState, useCallback as useCallback2, useMemo as useMemo3 } from "react";
2661
2999
  var STORAGE_KEY2 = "otto-theme";
2662
3000
  function resolveInitialTheme() {
2663
3001
  if (typeof window === "undefined") {
@@ -2674,7 +3012,7 @@ function resolveInitialTheme() {
2674
3012
  }
2675
3013
  function useTheme() {
2676
3014
  const [theme, setTheme] = useState(() => resolveInitialTheme());
2677
- useEffect2(() => {
3015
+ useEffect3(() => {
2678
3016
  if (typeof document === "undefined")
2679
3017
  return;
2680
3018
  const root = document.documentElement;
@@ -2692,7 +3030,7 @@ function useTheme() {
2692
3030
  window.parent.postMessage({ type: "otto-set-theme", theme }, "*");
2693
3031
  }
2694
3032
  }, [theme]);
2695
- useEffect2(() => {
3033
+ useEffect3(() => {
2696
3034
  if (typeof window === "undefined")
2697
3035
  return;
2698
3036
  const handler = (e) => {
@@ -2709,11 +3047,11 @@ function useTheme() {
2709
3047
  return useMemo3(() => ({ theme, setTheme, toggleTheme }), [theme, toggleTheme]);
2710
3048
  }
2711
3049
  // src/hooks/useWorkingDirectory.ts
2712
- import { useEffect as useEffect3, useState as useState2 } from "react";
3050
+ import { useEffect as useEffect4, useState as useState2 } from "react";
2713
3051
  import { getCwd } from "@ottocode/api";
2714
3052
  function useWorkingDirectory() {
2715
3053
  const [dirName, setDirName] = useState2(null);
2716
- useEffect3(() => {
3054
+ useEffect4(() => {
2717
3055
  const fetchWorkingDirectory = async () => {
2718
3056
  try {
2719
3057
  const response = await getCwd({ baseURL: getBaseUrl() });
@@ -2737,11 +3075,11 @@ function useWorkingDirectory() {
2737
3075
  return dirName;
2738
3076
  }
2739
3077
  // src/hooks/useKeyboardShortcuts.ts
2740
- import { useEffect as useEffect4, useCallback as useCallback3 } from "react";
3078
+ import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
2741
3079
 
2742
3080
  // src/stores/focusStore.ts
2743
- import { create as create10 } from "zustand";
2744
- var useFocusStore = create10((set) => ({
3081
+ import { create as create11 } from "zustand";
3082
+ var useFocusStore = create11((set) => ({
2745
3083
  currentFocus: null,
2746
3084
  sessionIndex: 0,
2747
3085
  gitFileIndex: 0,
@@ -2753,9 +3091,9 @@ var useFocusStore = create10((set) => ({
2753
3091
  }));
2754
3092
 
2755
3093
  // src/stores/sidebarStore.ts
2756
- import { create as create11 } from "zustand";
3094
+ import { create as create12 } from "zustand";
2757
3095
  import { persist } from "zustand/middleware";
2758
- var useSidebarStore = create11()(persist((set) => ({
3096
+ var useSidebarStore = create12()(persist((set) => ({
2759
3097
  isCollapsed: false,
2760
3098
  toggleCollapse: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
2761
3099
  setCollapsed: (collapsed) => set({ isCollapsed: collapsed })
@@ -2764,8 +3102,8 @@ var useSidebarStore = create11()(persist((set) => ({
2764
3102
  }));
2765
3103
 
2766
3104
  // src/stores/filePickerStore.ts
2767
- import { create as create12 } from "zustand";
2768
- var useFilePickerStore = create12((set) => ({
3105
+ import { create as create13 } from "zustand";
3106
+ var useFilePickerStore = create13((set) => ({
2769
3107
  isOpen: false,
2770
3108
  open: () => set({ isOpen: true }),
2771
3109
  close: () => set({ isOpen: false }),
@@ -3004,7 +3342,7 @@ function useKeyboardShortcuts({
3004
3342
  onReturnToInput,
3005
3343
  closeDiff
3006
3344
  ]);
3007
- useEffect4(() => {
3345
+ useEffect5(() => {
3008
3346
  window.addEventListener("keydown", handleKeyDown);
3009
3347
  return () => window.removeEventListener("keydown", handleKeyDown);
3010
3348
  }, [handleKeyDown]);
@@ -3018,7 +3356,7 @@ function useKeyboardShortcuts({
3018
3356
  import {
3019
3357
  useState as useState3,
3020
3358
  useCallback as useCallback4,
3021
- useEffect as useEffect5
3359
+ useEffect as useEffect6
3022
3360
  } from "react";
3023
3361
  var SUPPORTED_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
3024
3362
  function generateId() {
@@ -3154,7 +3492,7 @@ function useImageUpload(options = {}) {
3154
3492
  addImages(imageFiles);
3155
3493
  }
3156
3494
  }, [addImages]);
3157
- useEffect5(() => {
3495
+ useEffect6(() => {
3158
3496
  if (!pageWide)
3159
3497
  return;
3160
3498
  let dragCounter = 0;
@@ -3218,7 +3556,7 @@ function useImageUpload(options = {}) {
3218
3556
  import {
3219
3557
  useState as useState4,
3220
3558
  useCallback as useCallback5,
3221
- useEffect as useEffect6
3559
+ useEffect as useEffect7
3222
3560
  } from "react";
3223
3561
  var IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
3224
3562
  var PDF_TYPES = ["application/pdf"];
@@ -3475,7 +3813,7 @@ function useFileUpload(options = {}) {
3475
3813
  addFiles(pastedFiles);
3476
3814
  }
3477
3815
  }, [addFiles]);
3478
- useEffect6(() => {
3816
+ useEffect7(() => {
3479
3817
  if (!pageWide)
3480
3818
  return;
3481
3819
  let dragCounter = 0;
@@ -3581,9 +3919,9 @@ function useMessageQueuePosition(sessionId, messageId) {
3581
3919
  return { isQueued: false, isRunning: false, position: null };
3582
3920
  }
3583
3921
  // src/hooks/useBranch.ts
3584
- import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
3922
+ import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3585
3923
  function useCreateBranch(sessionId) {
3586
- const queryClient = useQueryClient6();
3924
+ const queryClient = useQueryClient7();
3587
3925
  return useMutation5({
3588
3926
  mutationFn: (data) => {
3589
3927
  if (!sessionId)
@@ -3623,7 +3961,7 @@ function useParentSession(sessionId) {
3623
3961
  });
3624
3962
  }
3625
3963
  // src/hooks/useResearch.ts
3626
- import { useQuery as useQuery8, useMutation as useMutation6, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3964
+ import { useQuery as useQuery8, useMutation as useMutation6, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
3627
3965
  import {
3628
3966
  createResearchSession as apiCreateResearchSession,
3629
3967
  deleteResearchSession as apiDeleteResearchSession,
@@ -3633,8 +3971,8 @@ import {
3633
3971
  } from "@ottocode/api";
3634
3972
 
3635
3973
  // src/stores/pendingResearchStore.ts
3636
- import { create as create13 } from "zustand";
3637
- var usePendingResearchStore = create13((set, get) => ({
3974
+ import { create as create14 } from "zustand";
3975
+ var usePendingResearchStore = create14((set, get) => ({
3638
3976
  pendingContexts: new Map,
3639
3977
  addContext: (parentSessionId, context) => {
3640
3978
  set((state) => {
@@ -3727,7 +4065,7 @@ function useResearchSessions(parentSessionId, enabled = true) {
3727
4065
  });
3728
4066
  }
3729
4067
  function useCreateResearchSession() {
3730
- const queryClient = useQueryClient7();
4068
+ const queryClient = useQueryClient8();
3731
4069
  return useMutation6({
3732
4070
  mutationFn: ({
3733
4071
  parentSessionId,
@@ -3741,7 +4079,7 @@ function useCreateResearchSession() {
3741
4079
  });
3742
4080
  }
3743
4081
  function useDeleteResearchSession() {
3744
- const queryClient = useQueryClient7();
4082
+ const queryClient = useQueryClient8();
3745
4083
  return useMutation6({
3746
4084
  mutationFn: (researchId) => researchApi.deleteResearchSession(researchId),
3747
4085
  onSuccess: () => {
@@ -3768,7 +4106,7 @@ function useInjectContext() {
3768
4106
  });
3769
4107
  }
3770
4108
  function useExportToSession() {
3771
- const queryClient = useQueryClient7();
4109
+ const queryClient = useQueryClient8();
3772
4110
  return useMutation6({
3773
4111
  mutationFn: ({
3774
4112
  researchId,
@@ -3780,55 +4118,7 @@ function useExportToSession() {
3780
4118
  });
3781
4119
  }
3782
4120
  // src/hooks/useSetuPayments.ts
3783
- import { useEffect as useEffect7, useRef as useRef2 } from "react";
3784
-
3785
- // src/stores/toastStore.ts
3786
- import { create as create14 } from "zustand";
3787
- var toastId = 0;
3788
- var useToastStore = create14((set) => ({
3789
- toasts: [],
3790
- addToast: (toast) => {
3791
- const id = `toast-${++toastId}`;
3792
- set((state) => ({
3793
- toasts: [...state.toasts, { ...toast, id }]
3794
- }));
3795
- return id;
3796
- },
3797
- removeToast: (id) => set((state) => ({
3798
- toasts: state.toasts.filter((t) => t.id !== id)
3799
- })),
3800
- updateToast: (id, updates) => set((state) => ({
3801
- toasts: state.toasts.map((t) => t.id === id ? { ...t, ...updates } : t)
3802
- })),
3803
- clearToasts: () => set({ toasts: [] })
3804
- }));
3805
- function toast(message, type = "default", duration = 4000) {
3806
- const id = useToastStore.getState().addToast({ message, type, duration });
3807
- if (duration > 0) {
3808
- setTimeout(() => {
3809
- useToastStore.getState().removeToast(id);
3810
- }, duration);
3811
- }
3812
- return id;
3813
- }
3814
- toast.success = (message, duration = 4000) => toast(message, "success", duration);
3815
- toast.error = (message, duration = 5000) => toast(message, "error", duration);
3816
- toast.info = (message, duration = 4000) => toast(message, "default", duration);
3817
- toast.loading = (message) => toast(message, "loading", 0);
3818
- toast.successWithAction = (message, action, duration = 6000) => {
3819
- const id = useToastStore.getState().addToast({
3820
- message,
3821
- type: "success",
3822
- duration,
3823
- action
3824
- });
3825
- if (duration > 0) {
3826
- setTimeout(() => {
3827
- useToastStore.getState().removeToast(id);
3828
- }, duration);
3829
- }
3830
- return id;
3831
- };
4121
+ import { useEffect as useEffect8, useRef as useRef3 } from "react";
3832
4122
 
3833
4123
  // src/stores/ottorouterStore.ts
3834
4124
  import { create as create15 } from "zustand";
@@ -3874,15 +4164,15 @@ var useTopupApprovalStore = create16((set) => ({
3874
4164
 
3875
4165
  // src/hooks/useSetuPayments.ts
3876
4166
  function useSetuPayments(sessionId) {
3877
- const clientRef = useRef2(null);
3878
- const loadingToastIdRef = useRef2(null);
4167
+ const clientRef = useRef3(null);
4168
+ const loadingToastIdRef = useRef3(null);
3879
4169
  const setBalance = useOttoRouterStore((s) => s.setBalance);
3880
4170
  const setPaymentPending = useOttoRouterStore((s) => s.setPaymentPending);
3881
4171
  const removeToast = useToastStore((s) => s.removeToast);
3882
4172
  const updateToast = useToastStore((s) => s.updateToast);
3883
4173
  const setPendingTopup = useTopupApprovalStore((s) => s.setPendingTopup);
3884
4174
  const clearPendingTopup = useTopupApprovalStore((s) => s.clearPendingTopup);
3885
- useEffect7(() => {
4175
+ useEffect8(() => {
3886
4176
  if (!sessionId)
3887
4177
  return;
3888
4178
  const client2 = new SSEClient;
@@ -4012,7 +4302,7 @@ function useSetuPayments(sessionId) {
4012
4302
  ]);
4013
4303
  }
4014
4304
  // src/hooks/useOttoRouterBalance.ts
4015
- import { useEffect as useEffect8, useCallback as useCallback6 } from "react";
4305
+ import { useEffect as useEffect9, useCallback as useCallback6 } from "react";
4016
4306
 
4017
4307
  // src/stores/usageStore.ts
4018
4308
  import { create as create17 } from "zustand";
@@ -4106,7 +4396,7 @@ function useOttoRouterBalance(providerName) {
4106
4396
  setUsage
4107
4397
  ]);
4108
4398
  const needsUsageWindows = subscription?.active && !subscription.usageWindows;
4109
- useEffect8(() => {
4399
+ useEffect9(() => {
4110
4400
  if (providerName === "ottorouter" && (balance === null || usdcBalance === null || needsUsageWindows)) {
4111
4401
  fetchBalance();
4112
4402
  }
@@ -4127,7 +4417,7 @@ function useShareStatus(sessionId) {
4127
4417
  return { data, isLoading, error };
4128
4418
  }
4129
4419
  // src/hooks/useToolApprovalShortcuts.ts
4130
- import { useEffect as useEffect9, useCallback as useCallback7 } from "react";
4420
+ import { useEffect as useEffect10, useCallback as useCallback7 } from "react";
4131
4421
  function useToolApprovalShortcuts(sessionId) {
4132
4422
  const { pendingApprovals, removePendingApproval } = useToolApprovalStore();
4133
4423
  const sessionPendingApprovals = pendingApprovals;
@@ -4163,7 +4453,7 @@ function useToolApprovalShortcuts(sessionId) {
4163
4453
  console.error("Failed to approve all tool calls:", error);
4164
4454
  }
4165
4455
  }, [sessionId, sessionPendingApprovals, removePendingApproval]);
4166
- useEffect9(() => {
4456
+ useEffect10(() => {
4167
4457
  if (!sessionId || sessionPendingApprovals.length === 0)
4168
4458
  return;
4169
4459
  const handleKeyDown = (e) => {
@@ -4193,14 +4483,14 @@ function useToolApprovalShortcuts(sessionId) {
4193
4483
  ]);
4194
4484
  }
4195
4485
  // src/hooks/useTopupCallback.ts
4196
- import { useEffect as useEffect10, useRef as useRef3 } from "react";
4486
+ import { useEffect as useEffect11, useRef as useRef4 } from "react";
4197
4487
  var STORAGE_KEY3 = "pendingPolarCheckout";
4198
4488
  function useTopupCallback() {
4199
- const hasHandled = useRef3(false);
4200
- const loadingToastId = useRef3(null);
4489
+ const hasHandled = useRef4(false);
4490
+ const loadingToastId = useRef4(null);
4201
4491
  const setBalance = useOttoRouterStore((s) => s.setBalance);
4202
4492
  const removeToast = useToastStore((s) => s.removeToast);
4203
- useEffect10(() => {
4493
+ useEffect11(() => {
4204
4494
  if (hasHandled.current)
4205
4495
  return;
4206
4496
  const params = new URLSearchParams(window.location.search);
@@ -4261,8 +4551,8 @@ function useTopupCallback() {
4261
4551
  }, [setBalance, removeToast]);
4262
4552
  }
4263
4553
  // src/hooks/useAuthStatus.ts
4264
- import { useEffect as useEffect11, useCallback as useCallback8, useState as useState5, useRef as useRef4 } from "react";
4265
- import { useQueryClient as useQueryClient8 } from "@tanstack/react-query";
4554
+ import { useEffect as useEffect12, useCallback as useCallback8, useState as useState5, useRef as useRef5 } from "react";
4555
+ import { useQueryClient as useQueryClient9 } from "@tanstack/react-query";
4266
4556
 
4267
4557
  // src/stores/onboardingStore.ts
4268
4558
  import { create as create18 } from "zustand";
@@ -4312,11 +4602,11 @@ function useAuthStatus() {
4312
4602
  const setError = useOnboardingStore((s) => s.setError);
4313
4603
  const authStatus = useOnboardingStore((s) => s.authStatus);
4314
4604
  const isOpen = useOnboardingStore((s) => s.isOpen);
4315
- const queryClient = useQueryClient8();
4605
+ const queryClient = useQueryClient9();
4316
4606
  const [initialized, setInitialized] = useState5(false);
4317
4607
  const [oauthPolling, setOauthPolling] = useState5(false);
4318
- const oauthPollingRef = useRef4(null);
4319
- const preOauthProvidersRef = useRef4(new Set);
4608
+ const oauthPollingRef = useRef5(null);
4609
+ const preOauthProvidersRef = useRef5(new Set);
4320
4610
  const fetchAuthStatus = useCallback8(async () => {
4321
4611
  setLoading(true);
4322
4612
  setError(null);
@@ -4453,6 +4743,11 @@ function useAuthStatus() {
4453
4743
  }, []);
4454
4744
  const startOAuth = useCallback8((provider, mode) => {
4455
4745
  const url = apiClient.getOAuthStartUrl(provider, mode);
4746
+ if (openPlatformUrl(url)) {
4747
+ snapshotConfiguredProviders();
4748
+ setOauthPolling(true);
4749
+ return null;
4750
+ }
4456
4751
  if (isInIframe) {
4457
4752
  snapshotConfiguredProviders();
4458
4753
  window.parent.postMessage({ type: "otto-open-url", url }, "*");
@@ -4468,6 +4763,11 @@ function useAuthStatus() {
4468
4763
  }, [snapshotConfiguredProviders]);
4469
4764
  const startOAuthManual = useCallback8(async (provider, mode) => {
4470
4765
  const { url, sessionId } = await apiClient.getOAuthUrl(provider, mode);
4766
+ if (openPlatformUrl(url)) {
4767
+ snapshotConfiguredProviders();
4768
+ setOauthPolling(true);
4769
+ return { popup: null, sessionId };
4770
+ }
4471
4771
  if (isInIframe) {
4472
4772
  snapshotConfiguredProviders();
4473
4773
  window.parent.postMessage({ type: "otto-open-url", url }, "*");
@@ -4496,7 +4796,7 @@ function useAuthStatus() {
4496
4796
  setLoading(false);
4497
4797
  }
4498
4798
  }, [fetchAuthStatus, setLoading, setError]);
4499
- useEffect11(() => {
4799
+ useEffect12(() => {
4500
4800
  if (!oauthPolling || !isInIframe)
4501
4801
  return;
4502
4802
  oauthPollingRef.current = setInterval(() => {
@@ -4510,7 +4810,7 @@ function useAuthStatus() {
4510
4810
  clearTimeout(timeout);
4511
4811
  };
4512
4812
  }, [oauthPolling, fetchAuthStatus]);
4513
- useEffect11(() => {
4813
+ useEffect12(() => {
4514
4814
  if (!oauthPolling || !authStatus)
4515
4815
  return;
4516
4816
  const currentConfigured = Object.entries(authStatus.providers).filter(([, p]) => p.configured);
@@ -4519,7 +4819,7 @@ function useAuthStatus() {
4519
4819
  setOauthPolling(false);
4520
4820
  }
4521
4821
  }, [authStatus, oauthPolling]);
4522
- useEffect11(() => {
4822
+ useEffect12(() => {
4523
4823
  const handleOAuthMessage = (event) => {
4524
4824
  if (event.data?.type === "oauth-success") {
4525
4825
  fetchAuthStatus();
@@ -4589,8 +4889,8 @@ function useAuthStatus() {
4589
4889
  };
4590
4890
  }
4591
4891
  // src/hooks/useTunnel.ts
4592
- import { useQuery as useQuery10, useMutation as useMutation7, useQueryClient as useQueryClient9 } from "@tanstack/react-query";
4593
- import { useEffect as useEffect12, useCallback as useCallback9, useRef as useRef5 } from "react";
4892
+ import { useQuery as useQuery10, useMutation as useMutation7, useQueryClient as useQueryClient10 } from "@tanstack/react-query";
4893
+ import { useEffect as useEffect13, useCallback as useCallback9, useRef as useRef6 } from "react";
4594
4894
  import {
4595
4895
  client as client2,
4596
4896
  getTunnelQr,
@@ -4633,7 +4933,7 @@ function useTunnelStatus() {
4633
4933
  queryFn: fetchTunnelStatus,
4634
4934
  refetchInterval: 3000
4635
4935
  });
4636
- useEffect12(() => {
4936
+ useEffect13(() => {
4637
4937
  if (query.data) {
4638
4938
  setStatus(query.data.status);
4639
4939
  setUrl(query.data.url);
@@ -4643,7 +4943,7 @@ function useTunnelStatus() {
4643
4943
  return query;
4644
4944
  }
4645
4945
  function useStartTunnel() {
4646
- const queryClient = useQueryClient9();
4946
+ const queryClient = useQueryClient10();
4647
4947
  const setStatus = useTunnelStore((s) => s.setStatus);
4648
4948
  const setUrl = useTunnelStore((s) => s.setUrl);
4649
4949
  const setError = useTunnelStore((s) => s.setError);
@@ -4675,7 +4975,7 @@ function useStartTunnel() {
4675
4975
  });
4676
4976
  }
4677
4977
  function useStopTunnel() {
4678
- const queryClient = useQueryClient9();
4978
+ const queryClient = useQueryClient10();
4679
4979
  const reset = useTunnelStore((s) => s.reset);
4680
4980
  return useMutation7({
4681
4981
  mutationFn: stopTunnel,
@@ -4693,7 +4993,7 @@ function useTunnelQr() {
4693
4993
  queryFn: fetchTunnelQr,
4694
4994
  enabled: !!url
4695
4995
  });
4696
- useEffect12(() => {
4996
+ useEffect13(() => {
4697
4997
  if (query.data?.ok && query.data.qrCode) {
4698
4998
  setQrCode(query.data.qrCode);
4699
4999
  }
@@ -4706,7 +5006,7 @@ function useTunnelStream() {
4706
5006
  const setError = useTunnelStore((s) => s.setError);
4707
5007
  const setProgress = useTunnelStore((s) => s.setProgress);
4708
5008
  const isExpanded = useTunnelStore((s) => s.isExpanded);
4709
- const eventSourceRef = useRef5(null);
5009
+ const eventSourceRef = useRef6(null);
4710
5010
  const connect = useCallback9(() => {
4711
5011
  if (eventSourceRef.current) {
4712
5012
  eventSourceRef.current.close();
@@ -4733,7 +5033,7 @@ function useTunnelStream() {
4733
5033
  eventSourceRef.current = null;
4734
5034
  };
4735
5035
  }, [setStatus, setUrl, setError, setProgress]);
4736
- useEffect12(() => {
5036
+ useEffect13(() => {
4737
5037
  if (isExpanded) {
4738
5038
  const cleanup = connect();
4739
5039
  return cleanup;
@@ -4748,7 +5048,7 @@ function useTunnelStream() {
4748
5048
  return { connect };
4749
5049
  }
4750
5050
  // src/hooks/useProviderUsage.ts
4751
- import { useEffect as useEffect13, useCallback as useCallback10, useRef as useRef6 } from "react";
5051
+ import { useEffect as useEffect14, useCallback as useCallback10, useRef as useRef7 } from "react";
4752
5052
  var POLL_INTERVAL = 60000;
4753
5053
  var STALE_THRESHOLD = 30000;
4754
5054
  var inflight = new Set;
@@ -4777,9 +5077,9 @@ function useProviderUsage(provider, authType) {
4777
5077
  inflight.delete(provider);
4778
5078
  }
4779
5079
  }, [provider, isOAuthProvider, setUsage, setLoading, setLastFetched]);
4780
- const fetchRef = useRef6(fetchUsage);
5080
+ const fetchRef = useRef7(fetchUsage);
4781
5081
  fetchRef.current = fetchUsage;
4782
- useEffect13(() => {
5082
+ useEffect14(() => {
4783
5083
  if (!provider || !isOAuthProvider)
4784
5084
  return;
4785
5085
  fetchRef.current();
@@ -4822,8 +5122,8 @@ function useGitDiffFullFile(file, staged = false, enabled = false) {
4822
5122
  });
4823
5123
  }
4824
5124
  // src/hooks/useMCP.ts
4825
- import { useQuery as useQuery12, useMutation as useMutation8, useQueryClient as useQueryClient10 } from "@tanstack/react-query";
4826
- import { useEffect as useEffect14, useRef as useRef7, useCallback as useCallback11 } from "react";
5125
+ import { useQuery as useQuery12, useMutation as useMutation8, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
5126
+ import { useEffect as useEffect15, useRef as useRef8, useCallback as useCallback11 } from "react";
4827
5127
  import {
4828
5128
  listMcpServers,
4829
5129
  startMcpServer,
@@ -4845,7 +5145,7 @@ function useMCPServers() {
4845
5145
  },
4846
5146
  refetchInterval: 1e4
4847
5147
  });
4848
- useEffect14(() => {
5148
+ useEffect15(() => {
4849
5149
  if (query.data?.servers) {
4850
5150
  setServers(query.data.servers);
4851
5151
  }
@@ -4853,7 +5153,7 @@ function useMCPServers() {
4853
5153
  return query;
4854
5154
  }
4855
5155
  function useStartMCPServer() {
4856
- const queryClient = useQueryClient10();
5156
+ const queryClient = useQueryClient11();
4857
5157
  return useMutation8({
4858
5158
  mutationFn: async (name) => {
4859
5159
  const { data, error } = await startMcpServer({
@@ -4872,7 +5172,7 @@ function useStartMCPServer() {
4872
5172
  });
4873
5173
  }
4874
5174
  function useStopMCPServer() {
4875
- const queryClient = useQueryClient10();
5175
+ const queryClient = useQueryClient11();
4876
5176
  const setLoading = useMCPStore((s) => s.setLoading);
4877
5177
  return useMutation8({
4878
5178
  mutationFn: async (name) => {
@@ -4894,7 +5194,7 @@ function useStopMCPServer() {
4894
5194
  });
4895
5195
  }
4896
5196
  function useAddMCPServer() {
4897
- const queryClient = useQueryClient10();
5197
+ const queryClient = useQueryClient11();
4898
5198
  return useMutation8({
4899
5199
  mutationFn: async (params) => {
4900
5200
  const { data, error } = await addMcpServer({
@@ -4913,7 +5213,7 @@ function useAddMCPServer() {
4913
5213
  });
4914
5214
  }
4915
5215
  function useRemoveMCPServer() {
4916
- const queryClient = useQueryClient10();
5216
+ const queryClient = useQueryClient11();
4917
5217
  return useMutation8({
4918
5218
  mutationFn: async (name) => {
4919
5219
  const { data, error } = await removeMcpServer({
@@ -4932,7 +5232,7 @@ function useRemoveMCPServer() {
4932
5232
  });
4933
5233
  }
4934
5234
  function useAuthenticateMCPServer() {
4935
- const queryClient = useQueryClient10();
5235
+ const queryClient = useQueryClient11();
4936
5236
  return useMutation8({
4937
5237
  mutationFn: async (name) => {
4938
5238
  const { data, error } = await initiateMcpAuth({
@@ -4951,7 +5251,7 @@ function useAuthenticateMCPServer() {
4951
5251
  });
4952
5252
  }
4953
5253
  function useRevokeMCPAuth() {
4954
- const queryClient = useQueryClient10();
5254
+ const queryClient = useQueryClient11();
4955
5255
  return useMutation8({
4956
5256
  mutationFn: async (name) => {
4957
5257
  const { data, error } = await revokeMcpAuth({
@@ -4988,15 +5288,15 @@ function useCopilotDevicePoller() {
4988
5288
  const copilotDevice = useMCPStore((s) => s.copilotDevice);
4989
5289
  const setCopilotDevice = useMCPStore((s) => s.setCopilotDevice);
4990
5290
  const setLoading = useMCPStore((s) => s.setLoading);
4991
- const queryClient = useQueryClient10();
4992
- const timerRef = useRef7(null);
5291
+ const queryClient = useQueryClient11();
5292
+ const timerRef = useRef8(null);
4993
5293
  const stopPolling = useCallback11(() => {
4994
5294
  if (timerRef.current) {
4995
5295
  clearInterval(timerRef.current);
4996
5296
  timerRef.current = null;
4997
5297
  }
4998
5298
  }, []);
4999
- useEffect14(() => {
5299
+ useEffect15(() => {
5000
5300
  if (!copilotDevice) {
5001
5301
  stopPolling();
5002
5302
  return;
@@ -5031,8 +5331,8 @@ function useCopilotDevicePoller() {
5031
5331
  return copilotDevice;
5032
5332
  }
5033
5333
  // src/hooks/useSkills.ts
5034
- import { useMutation as useMutation9, useQuery as useQuery13, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
5035
- import { useEffect as useEffect15 } from "react";
5334
+ import { useMutation as useMutation9, useQuery as useQuery13, useQueryClient as useQueryClient12 } from "@tanstack/react-query";
5335
+ import { useEffect as useEffect16 } from "react";
5036
5336
  function useSkills() {
5037
5337
  const setSkillsConfig = useSkillsStore((s) => s.setSkillsConfig);
5038
5338
  const query = useQuery13({
@@ -5042,7 +5342,7 @@ function useSkills() {
5042
5342
  },
5043
5343
  refetchInterval: 30000
5044
5344
  });
5045
- useEffect15(() => {
5345
+ useEffect16(() => {
5046
5346
  if (query.data?.items) {
5047
5347
  setSkillsConfig({
5048
5348
  skills: query.data.items,
@@ -5055,7 +5355,7 @@ function useSkills() {
5055
5355
  return query;
5056
5356
  }
5057
5357
  function useUpdateSkillsConfig() {
5058
- const queryClient = useQueryClient11();
5358
+ const queryClient = useQueryClient12();
5059
5359
  const setSkillsConfig = useSkillsStore((s) => s.setSkillsConfig);
5060
5360
  return useMutation9({
5061
5361
  mutationFn: (input) => apiClient.updateSkillsConfig(input),
@@ -5103,6 +5403,22 @@ function useSkillFileContent(name, filePath) {
5103
5403
  enabled: !!name && !!filePath
5104
5404
  });
5105
5405
  }
5406
+ // src/hooks/useContainerWidth.ts
5407
+ import { useEffect as useEffect17, useState as useState6 } from "react";
5408
+ function useContainerWidth(ref) {
5409
+ const [width, setWidth] = useState6(0);
5410
+ useEffect17(() => {
5411
+ const el = ref.current;
5412
+ if (!el)
5413
+ return;
5414
+ const update = () => setWidth(el.clientWidth);
5415
+ update();
5416
+ const observer = new ResizeObserver(() => update());
5417
+ observer.observe(el);
5418
+ return () => observer.disconnect();
5419
+ }, [ref]);
5420
+ return width;
5421
+ }
5106
5422
  export {
5107
5423
  useWorkingDirectory,
5108
5424
  useUpdateSkillsConfig,
@@ -5171,8 +5487,10 @@ export {
5171
5487
  useCreateResearchSession,
5172
5488
  useCreateBranch,
5173
5489
  useCopilotDevicePoller,
5490
+ useContainerWidth,
5174
5491
  useConfig,
5175
5492
  useCommitChanges,
5493
+ useClientEvents,
5176
5494
  useBranches,
5177
5495
  useAuthenticateMCPServer,
5178
5496
  useAuthStatus,
@@ -5182,4 +5500,4 @@ export {
5182
5500
  sessionsQueryKey
5183
5501
  };
5184
5502
 
5185
- //# debugId=2FC62A50D828F41864756E2164756E21
5503
+ //# debugId=5F8DA6B0D961E4EF64756E2164756E21