@ottocode/web-sdk 0.1.267 → 0.1.268

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.
@@ -2656,8 +2656,229 @@ function useSessionStream(sessionId, enabled = true) {
2656
2656
  updatePendingApproval
2657
2657
  ]);
2658
2658
  }
2659
+ // src/hooks/useClientEvents.ts
2660
+ import { useEffect as useEffect2, useRef as useRef2 } from "react";
2661
+ import { useQueryClient as useQueryClient6 } from "@tanstack/react-query";
2662
+ import {
2663
+ buildClientEventsStreamUrl,
2664
+ createClientEventsStream
2665
+ } from "@ottocode/api";
2666
+
2667
+ // src/stores/toastStore.ts
2668
+ import { create as create10 } from "zustand";
2669
+ var toastId = 0;
2670
+ var useToastStore = create10((set) => ({
2671
+ toasts: [],
2672
+ addToast: (toast) => {
2673
+ const id = `toast-${++toastId}`;
2674
+ set((state) => ({
2675
+ toasts: [...state.toasts, { ...toast, id }]
2676
+ }));
2677
+ return id;
2678
+ },
2679
+ removeToast: (id) => set((state) => ({
2680
+ toasts: state.toasts.filter((t) => t.id !== id)
2681
+ })),
2682
+ updateToast: (id, updates) => set((state) => ({
2683
+ toasts: state.toasts.map((t) => t.id === id ? { ...t, ...updates } : t)
2684
+ })),
2685
+ clearToasts: () => set({ toasts: [] })
2686
+ }));
2687
+ function toast(message, type = "default", duration = 4000) {
2688
+ const id = useToastStore.getState().addToast({ message, type, duration });
2689
+ if (duration > 0) {
2690
+ setTimeout(() => {
2691
+ useToastStore.getState().removeToast(id);
2692
+ }, duration);
2693
+ }
2694
+ return id;
2695
+ }
2696
+ toast.success = (message, duration = 4000) => toast(message, "success", duration);
2697
+ toast.error = (message, duration = 5000) => toast(message, "error", duration);
2698
+ toast.info = (message, duration = 4000) => toast(message, "default", duration);
2699
+ toast.loading = (message) => toast(message, "loading", 0);
2700
+ toast.successWithAction = (message, action, duration = 6000) => {
2701
+ const id = useToastStore.getState().addToast({
2702
+ message,
2703
+ type: "success",
2704
+ duration,
2705
+ action
2706
+ });
2707
+ if (duration > 0) {
2708
+ setTimeout(() => {
2709
+ useToastStore.getState().removeToast(id);
2710
+ }, duration);
2711
+ }
2712
+ return id;
2713
+ };
2714
+
2715
+ // src/hooks/useClientEvents.ts
2716
+ function toastTypeForLevel(level) {
2717
+ if (level === "success")
2718
+ return "success";
2719
+ if (level === "error")
2720
+ return "error";
2721
+ return "default";
2722
+ }
2723
+ function showInAppNotification(notification) {
2724
+ const message = notification.body ? `${notification.title}: ${notification.body}` : notification.title;
2725
+ if (notification.action) {
2726
+ const id = toast(message, toastTypeForLevel(notification.level), 6000);
2727
+ useToastStore.getState().updateToast(id, { action: notification.action });
2728
+ return;
2729
+ }
2730
+ toast(message, toastTypeForLevel(notification.level), 5000);
2731
+ }
2732
+ function sendBrowserNotification(notification) {
2733
+ if (typeof window === "undefined")
2734
+ return;
2735
+ if (window.parent && window.parent !== window) {
2736
+ const message = {
2737
+ type: "otto-notification",
2738
+ notification
2739
+ };
2740
+ window.parent.postMessage(message, "*");
2741
+ return;
2742
+ }
2743
+ if (!("Notification" in window) || Notification.permission !== "granted")
2744
+ return;
2745
+ const browserNotification = new Notification(notification.title, {
2746
+ body: notification.body,
2747
+ tag: notification.id
2748
+ });
2749
+ browserNotification.onclick = () => {
2750
+ window.focus();
2751
+ if (notification.sessionId) {
2752
+ window.location.href = `/sessions/${notification.sessionId}`;
2753
+ }
2754
+ browserNotification.close();
2755
+ };
2756
+ }
2757
+ function updateSessionStatusInCache(queryClient, status) {
2758
+ queryClient.setQueryData(sessionsQueryKey, (old) => {
2759
+ if (!old)
2760
+ return old;
2761
+ return {
2762
+ ...old,
2763
+ pages: old.pages.map((page) => ({
2764
+ ...page,
2765
+ items: page.items.map((session) => session.id === status.sessionId ? {
2766
+ ...session,
2767
+ isRunning: status.status === "running"
2768
+ } : session)
2769
+ }))
2770
+ };
2771
+ });
2772
+ }
2773
+ function isLocalApiUrl(baseUrl) {
2774
+ try {
2775
+ const { hostname } = new URL(baseUrl);
2776
+ 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);
2777
+ } catch {
2778
+ return false;
2779
+ }
2780
+ }
2781
+ async function requestLocalhostAccess(baseUrl) {
2782
+ const response = await fetch(new URL("/openapi.json", baseUrl), {
2783
+ cache: "no-store",
2784
+ credentials: "include"
2785
+ });
2786
+ if (!response.ok) {
2787
+ throw new Error(`Local API returned ${response.status}`);
2788
+ }
2789
+ }
2790
+ function useClientEvents(activeSessionId) {
2791
+ const queryClient = useQueryClient6();
2792
+ const activeSessionIdRef = useRef2(activeSessionId);
2793
+ useEffect2(() => {
2794
+ activeSessionIdRef.current = activeSessionId;
2795
+ }, [activeSessionId]);
2796
+ useEffect2(() => {
2797
+ if (typeof window === "undefined" || window.parent !== window)
2798
+ return;
2799
+ if (!("Notification" in window))
2800
+ return;
2801
+ if (Notification.permission !== "default")
2802
+ return;
2803
+ if (window.localStorage.getItem("otto-notification-permission-prompted")) {
2804
+ return;
2805
+ }
2806
+ window.localStorage.setItem("otto-notification-permission-prompted", "1");
2807
+ const id = toast("Enable browser notifications for background session updates.", "default", 0);
2808
+ useToastStore.getState().updateToast(id, {
2809
+ action: {
2810
+ label: "Enable",
2811
+ onClick: async () => {
2812
+ const permission = await Notification.requestPermission();
2813
+ if (permission === "granted") {
2814
+ toast.success("Browser notifications enabled.");
2815
+ } else {
2816
+ toast.info("Browser notifications were not enabled.");
2817
+ }
2818
+ }
2819
+ }
2820
+ });
2821
+ }, []);
2822
+ useEffect2(() => {
2823
+ const controller = new AbortController;
2824
+ let hasShownLocalAccessToast = false;
2825
+ const baseUrl = getBaseUrl();
2826
+ createClientEventsStream({
2827
+ baseUrl,
2828
+ onEvent: (event) => {
2829
+ if (event.event === "heartbeat")
2830
+ return;
2831
+ let payload;
2832
+ try {
2833
+ payload = JSON.parse(event.data);
2834
+ } catch (error) {
2835
+ console.error("[client-events] Failed to parse event:", error);
2836
+ return;
2837
+ }
2838
+ if (event.event === "session.status") {
2839
+ const status = payload;
2840
+ updateSessionStatusInCache(queryClient, status);
2841
+ if (status.status !== "running") {
2842
+ queryClient.invalidateQueries({
2843
+ queryKey: sessionsQueryKey
2844
+ });
2845
+ }
2846
+ return;
2847
+ }
2848
+ if (event.event === "notification") {
2849
+ const notification = payload;
2850
+ showInAppNotification(notification);
2851
+ const isActiveVisibleSession = notification.sessionId === activeSessionIdRef.current && document.visibilityState === "visible";
2852
+ if (!isActiveVisibleSession) {
2853
+ sendBrowserNotification(notification);
2854
+ }
2855
+ }
2856
+ },
2857
+ onError: (error) => {
2858
+ if (!controller.signal.aborted) {
2859
+ console.error("[client-events] Stream error:", error);
2860
+ if (!hasShownLocalAccessToast && isLocalApiUrl(baseUrl)) {
2861
+ hasShownLocalAccessToast = true;
2862
+ const id = toast("Safari may need permission to access the local otto server.", "default", 0);
2863
+ useToastStore.getState().updateToast(id, {
2864
+ action: {
2865
+ label: "Allow access",
2866
+ onClick: async () => {
2867
+ await requestLocalhostAccess(baseUrl);
2868
+ toast.success("Local otto server access confirmed.");
2869
+ }
2870
+ }
2871
+ });
2872
+ }
2873
+ }
2874
+ }
2875
+ }, controller.signal);
2876
+ return () => controller.abort();
2877
+ }, [queryClient]);
2878
+ return buildClientEventsStreamUrl({ baseUrl: getBaseUrl() });
2879
+ }
2659
2880
  // src/hooks/useTheme.ts
2660
- import { useEffect as useEffect2, useState, useCallback as useCallback2, useMemo as useMemo3 } from "react";
2881
+ import { useEffect as useEffect3, useState, useCallback as useCallback2, useMemo as useMemo3 } from "react";
2661
2882
  var STORAGE_KEY2 = "otto-theme";
2662
2883
  function resolveInitialTheme() {
2663
2884
  if (typeof window === "undefined") {
@@ -2674,7 +2895,7 @@ function resolveInitialTheme() {
2674
2895
  }
2675
2896
  function useTheme() {
2676
2897
  const [theme, setTheme] = useState(() => resolveInitialTheme());
2677
- useEffect2(() => {
2898
+ useEffect3(() => {
2678
2899
  if (typeof document === "undefined")
2679
2900
  return;
2680
2901
  const root = document.documentElement;
@@ -2692,7 +2913,7 @@ function useTheme() {
2692
2913
  window.parent.postMessage({ type: "otto-set-theme", theme }, "*");
2693
2914
  }
2694
2915
  }, [theme]);
2695
- useEffect2(() => {
2916
+ useEffect3(() => {
2696
2917
  if (typeof window === "undefined")
2697
2918
  return;
2698
2919
  const handler = (e) => {
@@ -2709,11 +2930,11 @@ function useTheme() {
2709
2930
  return useMemo3(() => ({ theme, setTheme, toggleTheme }), [theme, toggleTheme]);
2710
2931
  }
2711
2932
  // src/hooks/useWorkingDirectory.ts
2712
- import { useEffect as useEffect3, useState as useState2 } from "react";
2933
+ import { useEffect as useEffect4, useState as useState2 } from "react";
2713
2934
  import { getCwd } from "@ottocode/api";
2714
2935
  function useWorkingDirectory() {
2715
2936
  const [dirName, setDirName] = useState2(null);
2716
- useEffect3(() => {
2937
+ useEffect4(() => {
2717
2938
  const fetchWorkingDirectory = async () => {
2718
2939
  try {
2719
2940
  const response = await getCwd({ baseURL: getBaseUrl() });
@@ -2737,11 +2958,11 @@ function useWorkingDirectory() {
2737
2958
  return dirName;
2738
2959
  }
2739
2960
  // src/hooks/useKeyboardShortcuts.ts
2740
- import { useEffect as useEffect4, useCallback as useCallback3 } from "react";
2961
+ import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
2741
2962
 
2742
2963
  // src/stores/focusStore.ts
2743
- import { create as create10 } from "zustand";
2744
- var useFocusStore = create10((set) => ({
2964
+ import { create as create11 } from "zustand";
2965
+ var useFocusStore = create11((set) => ({
2745
2966
  currentFocus: null,
2746
2967
  sessionIndex: 0,
2747
2968
  gitFileIndex: 0,
@@ -2753,9 +2974,9 @@ var useFocusStore = create10((set) => ({
2753
2974
  }));
2754
2975
 
2755
2976
  // src/stores/sidebarStore.ts
2756
- import { create as create11 } from "zustand";
2977
+ import { create as create12 } from "zustand";
2757
2978
  import { persist } from "zustand/middleware";
2758
- var useSidebarStore = create11()(persist((set) => ({
2979
+ var useSidebarStore = create12()(persist((set) => ({
2759
2980
  isCollapsed: false,
2760
2981
  toggleCollapse: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
2761
2982
  setCollapsed: (collapsed) => set({ isCollapsed: collapsed })
@@ -2764,8 +2985,8 @@ var useSidebarStore = create11()(persist((set) => ({
2764
2985
  }));
2765
2986
 
2766
2987
  // src/stores/filePickerStore.ts
2767
- import { create as create12 } from "zustand";
2768
- var useFilePickerStore = create12((set) => ({
2988
+ import { create as create13 } from "zustand";
2989
+ var useFilePickerStore = create13((set) => ({
2769
2990
  isOpen: false,
2770
2991
  open: () => set({ isOpen: true }),
2771
2992
  close: () => set({ isOpen: false }),
@@ -3004,7 +3225,7 @@ function useKeyboardShortcuts({
3004
3225
  onReturnToInput,
3005
3226
  closeDiff
3006
3227
  ]);
3007
- useEffect4(() => {
3228
+ useEffect5(() => {
3008
3229
  window.addEventListener("keydown", handleKeyDown);
3009
3230
  return () => window.removeEventListener("keydown", handleKeyDown);
3010
3231
  }, [handleKeyDown]);
@@ -3018,7 +3239,7 @@ function useKeyboardShortcuts({
3018
3239
  import {
3019
3240
  useState as useState3,
3020
3241
  useCallback as useCallback4,
3021
- useEffect as useEffect5
3242
+ useEffect as useEffect6
3022
3243
  } from "react";
3023
3244
  var SUPPORTED_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
3024
3245
  function generateId() {
@@ -3154,7 +3375,7 @@ function useImageUpload(options = {}) {
3154
3375
  addImages(imageFiles);
3155
3376
  }
3156
3377
  }, [addImages]);
3157
- useEffect5(() => {
3378
+ useEffect6(() => {
3158
3379
  if (!pageWide)
3159
3380
  return;
3160
3381
  let dragCounter = 0;
@@ -3218,7 +3439,7 @@ function useImageUpload(options = {}) {
3218
3439
  import {
3219
3440
  useState as useState4,
3220
3441
  useCallback as useCallback5,
3221
- useEffect as useEffect6
3442
+ useEffect as useEffect7
3222
3443
  } from "react";
3223
3444
  var IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"];
3224
3445
  var PDF_TYPES = ["application/pdf"];
@@ -3475,7 +3696,7 @@ function useFileUpload(options = {}) {
3475
3696
  addFiles(pastedFiles);
3476
3697
  }
3477
3698
  }, [addFiles]);
3478
- useEffect6(() => {
3699
+ useEffect7(() => {
3479
3700
  if (!pageWide)
3480
3701
  return;
3481
3702
  let dragCounter = 0;
@@ -3581,9 +3802,9 @@ function useMessageQueuePosition(sessionId, messageId) {
3581
3802
  return { isQueued: false, isRunning: false, position: null };
3582
3803
  }
3583
3804
  // src/hooks/useBranch.ts
3584
- import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
3805
+ import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3585
3806
  function useCreateBranch(sessionId) {
3586
- const queryClient = useQueryClient6();
3807
+ const queryClient = useQueryClient7();
3587
3808
  return useMutation5({
3588
3809
  mutationFn: (data) => {
3589
3810
  if (!sessionId)
@@ -3623,7 +3844,7 @@ function useParentSession(sessionId) {
3623
3844
  });
3624
3845
  }
3625
3846
  // src/hooks/useResearch.ts
3626
- import { useQuery as useQuery8, useMutation as useMutation6, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
3847
+ import { useQuery as useQuery8, useMutation as useMutation6, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
3627
3848
  import {
3628
3849
  createResearchSession as apiCreateResearchSession,
3629
3850
  deleteResearchSession as apiDeleteResearchSession,
@@ -3633,8 +3854,8 @@ import {
3633
3854
  } from "@ottocode/api";
3634
3855
 
3635
3856
  // src/stores/pendingResearchStore.ts
3636
- import { create as create13 } from "zustand";
3637
- var usePendingResearchStore = create13((set, get) => ({
3857
+ import { create as create14 } from "zustand";
3858
+ var usePendingResearchStore = create14((set, get) => ({
3638
3859
  pendingContexts: new Map,
3639
3860
  addContext: (parentSessionId, context) => {
3640
3861
  set((state) => {
@@ -3727,7 +3948,7 @@ function useResearchSessions(parentSessionId, enabled = true) {
3727
3948
  });
3728
3949
  }
3729
3950
  function useCreateResearchSession() {
3730
- const queryClient = useQueryClient7();
3951
+ const queryClient = useQueryClient8();
3731
3952
  return useMutation6({
3732
3953
  mutationFn: ({
3733
3954
  parentSessionId,
@@ -3741,7 +3962,7 @@ function useCreateResearchSession() {
3741
3962
  });
3742
3963
  }
3743
3964
  function useDeleteResearchSession() {
3744
- const queryClient = useQueryClient7();
3965
+ const queryClient = useQueryClient8();
3745
3966
  return useMutation6({
3746
3967
  mutationFn: (researchId) => researchApi.deleteResearchSession(researchId),
3747
3968
  onSuccess: () => {
@@ -3768,7 +3989,7 @@ function useInjectContext() {
3768
3989
  });
3769
3990
  }
3770
3991
  function useExportToSession() {
3771
- const queryClient = useQueryClient7();
3992
+ const queryClient = useQueryClient8();
3772
3993
  return useMutation6({
3773
3994
  mutationFn: ({
3774
3995
  researchId,
@@ -3780,55 +4001,7 @@ function useExportToSession() {
3780
4001
  });
3781
4002
  }
3782
4003
  // 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
- };
4004
+ import { useEffect as useEffect8, useRef as useRef3 } from "react";
3832
4005
 
3833
4006
  // src/stores/ottorouterStore.ts
3834
4007
  import { create as create15 } from "zustand";
@@ -3874,15 +4047,15 @@ var useTopupApprovalStore = create16((set) => ({
3874
4047
 
3875
4048
  // src/hooks/useSetuPayments.ts
3876
4049
  function useSetuPayments(sessionId) {
3877
- const clientRef = useRef2(null);
3878
- const loadingToastIdRef = useRef2(null);
4050
+ const clientRef = useRef3(null);
4051
+ const loadingToastIdRef = useRef3(null);
3879
4052
  const setBalance = useOttoRouterStore((s) => s.setBalance);
3880
4053
  const setPaymentPending = useOttoRouterStore((s) => s.setPaymentPending);
3881
4054
  const removeToast = useToastStore((s) => s.removeToast);
3882
4055
  const updateToast = useToastStore((s) => s.updateToast);
3883
4056
  const setPendingTopup = useTopupApprovalStore((s) => s.setPendingTopup);
3884
4057
  const clearPendingTopup = useTopupApprovalStore((s) => s.clearPendingTopup);
3885
- useEffect7(() => {
4058
+ useEffect8(() => {
3886
4059
  if (!sessionId)
3887
4060
  return;
3888
4061
  const client2 = new SSEClient;
@@ -4012,7 +4185,7 @@ function useSetuPayments(sessionId) {
4012
4185
  ]);
4013
4186
  }
4014
4187
  // src/hooks/useOttoRouterBalance.ts
4015
- import { useEffect as useEffect8, useCallback as useCallback6 } from "react";
4188
+ import { useEffect as useEffect9, useCallback as useCallback6 } from "react";
4016
4189
 
4017
4190
  // src/stores/usageStore.ts
4018
4191
  import { create as create17 } from "zustand";
@@ -4106,7 +4279,7 @@ function useOttoRouterBalance(providerName) {
4106
4279
  setUsage
4107
4280
  ]);
4108
4281
  const needsUsageWindows = subscription?.active && !subscription.usageWindows;
4109
- useEffect8(() => {
4282
+ useEffect9(() => {
4110
4283
  if (providerName === "ottorouter" && (balance === null || usdcBalance === null || needsUsageWindows)) {
4111
4284
  fetchBalance();
4112
4285
  }
@@ -4127,7 +4300,7 @@ function useShareStatus(sessionId) {
4127
4300
  return { data, isLoading, error };
4128
4301
  }
4129
4302
  // src/hooks/useToolApprovalShortcuts.ts
4130
- import { useEffect as useEffect9, useCallback as useCallback7 } from "react";
4303
+ import { useEffect as useEffect10, useCallback as useCallback7 } from "react";
4131
4304
  function useToolApprovalShortcuts(sessionId) {
4132
4305
  const { pendingApprovals, removePendingApproval } = useToolApprovalStore();
4133
4306
  const sessionPendingApprovals = pendingApprovals;
@@ -4163,7 +4336,7 @@ function useToolApprovalShortcuts(sessionId) {
4163
4336
  console.error("Failed to approve all tool calls:", error);
4164
4337
  }
4165
4338
  }, [sessionId, sessionPendingApprovals, removePendingApproval]);
4166
- useEffect9(() => {
4339
+ useEffect10(() => {
4167
4340
  if (!sessionId || sessionPendingApprovals.length === 0)
4168
4341
  return;
4169
4342
  const handleKeyDown = (e) => {
@@ -4193,14 +4366,14 @@ function useToolApprovalShortcuts(sessionId) {
4193
4366
  ]);
4194
4367
  }
4195
4368
  // src/hooks/useTopupCallback.ts
4196
- import { useEffect as useEffect10, useRef as useRef3 } from "react";
4369
+ import { useEffect as useEffect11, useRef as useRef4 } from "react";
4197
4370
  var STORAGE_KEY3 = "pendingPolarCheckout";
4198
4371
  function useTopupCallback() {
4199
- const hasHandled = useRef3(false);
4200
- const loadingToastId = useRef3(null);
4372
+ const hasHandled = useRef4(false);
4373
+ const loadingToastId = useRef4(null);
4201
4374
  const setBalance = useOttoRouterStore((s) => s.setBalance);
4202
4375
  const removeToast = useToastStore((s) => s.removeToast);
4203
- useEffect10(() => {
4376
+ useEffect11(() => {
4204
4377
  if (hasHandled.current)
4205
4378
  return;
4206
4379
  const params = new URLSearchParams(window.location.search);
@@ -4261,8 +4434,8 @@ function useTopupCallback() {
4261
4434
  }, [setBalance, removeToast]);
4262
4435
  }
4263
4436
  // 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";
4437
+ import { useEffect as useEffect12, useCallback as useCallback8, useState as useState5, useRef as useRef5 } from "react";
4438
+ import { useQueryClient as useQueryClient9 } from "@tanstack/react-query";
4266
4439
 
4267
4440
  // src/stores/onboardingStore.ts
4268
4441
  import { create as create18 } from "zustand";
@@ -4312,11 +4485,11 @@ function useAuthStatus() {
4312
4485
  const setError = useOnboardingStore((s) => s.setError);
4313
4486
  const authStatus = useOnboardingStore((s) => s.authStatus);
4314
4487
  const isOpen = useOnboardingStore((s) => s.isOpen);
4315
- const queryClient = useQueryClient8();
4488
+ const queryClient = useQueryClient9();
4316
4489
  const [initialized, setInitialized] = useState5(false);
4317
4490
  const [oauthPolling, setOauthPolling] = useState5(false);
4318
- const oauthPollingRef = useRef4(null);
4319
- const preOauthProvidersRef = useRef4(new Set);
4491
+ const oauthPollingRef = useRef5(null);
4492
+ const preOauthProvidersRef = useRef5(new Set);
4320
4493
  const fetchAuthStatus = useCallback8(async () => {
4321
4494
  setLoading(true);
4322
4495
  setError(null);
@@ -4496,7 +4669,7 @@ function useAuthStatus() {
4496
4669
  setLoading(false);
4497
4670
  }
4498
4671
  }, [fetchAuthStatus, setLoading, setError]);
4499
- useEffect11(() => {
4672
+ useEffect12(() => {
4500
4673
  if (!oauthPolling || !isInIframe)
4501
4674
  return;
4502
4675
  oauthPollingRef.current = setInterval(() => {
@@ -4510,7 +4683,7 @@ function useAuthStatus() {
4510
4683
  clearTimeout(timeout);
4511
4684
  };
4512
4685
  }, [oauthPolling, fetchAuthStatus]);
4513
- useEffect11(() => {
4686
+ useEffect12(() => {
4514
4687
  if (!oauthPolling || !authStatus)
4515
4688
  return;
4516
4689
  const currentConfigured = Object.entries(authStatus.providers).filter(([, p]) => p.configured);
@@ -4519,7 +4692,7 @@ function useAuthStatus() {
4519
4692
  setOauthPolling(false);
4520
4693
  }
4521
4694
  }, [authStatus, oauthPolling]);
4522
- useEffect11(() => {
4695
+ useEffect12(() => {
4523
4696
  const handleOAuthMessage = (event) => {
4524
4697
  if (event.data?.type === "oauth-success") {
4525
4698
  fetchAuthStatus();
@@ -4589,8 +4762,8 @@ function useAuthStatus() {
4589
4762
  };
4590
4763
  }
4591
4764
  // 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";
4765
+ import { useQuery as useQuery10, useMutation as useMutation7, useQueryClient as useQueryClient10 } from "@tanstack/react-query";
4766
+ import { useEffect as useEffect13, useCallback as useCallback9, useRef as useRef6 } from "react";
4594
4767
  import {
4595
4768
  client as client2,
4596
4769
  getTunnelQr,
@@ -4633,7 +4806,7 @@ function useTunnelStatus() {
4633
4806
  queryFn: fetchTunnelStatus,
4634
4807
  refetchInterval: 3000
4635
4808
  });
4636
- useEffect12(() => {
4809
+ useEffect13(() => {
4637
4810
  if (query.data) {
4638
4811
  setStatus(query.data.status);
4639
4812
  setUrl(query.data.url);
@@ -4643,7 +4816,7 @@ function useTunnelStatus() {
4643
4816
  return query;
4644
4817
  }
4645
4818
  function useStartTunnel() {
4646
- const queryClient = useQueryClient9();
4819
+ const queryClient = useQueryClient10();
4647
4820
  const setStatus = useTunnelStore((s) => s.setStatus);
4648
4821
  const setUrl = useTunnelStore((s) => s.setUrl);
4649
4822
  const setError = useTunnelStore((s) => s.setError);
@@ -4675,7 +4848,7 @@ function useStartTunnel() {
4675
4848
  });
4676
4849
  }
4677
4850
  function useStopTunnel() {
4678
- const queryClient = useQueryClient9();
4851
+ const queryClient = useQueryClient10();
4679
4852
  const reset = useTunnelStore((s) => s.reset);
4680
4853
  return useMutation7({
4681
4854
  mutationFn: stopTunnel,
@@ -4693,7 +4866,7 @@ function useTunnelQr() {
4693
4866
  queryFn: fetchTunnelQr,
4694
4867
  enabled: !!url
4695
4868
  });
4696
- useEffect12(() => {
4869
+ useEffect13(() => {
4697
4870
  if (query.data?.ok && query.data.qrCode) {
4698
4871
  setQrCode(query.data.qrCode);
4699
4872
  }
@@ -4706,7 +4879,7 @@ function useTunnelStream() {
4706
4879
  const setError = useTunnelStore((s) => s.setError);
4707
4880
  const setProgress = useTunnelStore((s) => s.setProgress);
4708
4881
  const isExpanded = useTunnelStore((s) => s.isExpanded);
4709
- const eventSourceRef = useRef5(null);
4882
+ const eventSourceRef = useRef6(null);
4710
4883
  const connect = useCallback9(() => {
4711
4884
  if (eventSourceRef.current) {
4712
4885
  eventSourceRef.current.close();
@@ -4733,7 +4906,7 @@ function useTunnelStream() {
4733
4906
  eventSourceRef.current = null;
4734
4907
  };
4735
4908
  }, [setStatus, setUrl, setError, setProgress]);
4736
- useEffect12(() => {
4909
+ useEffect13(() => {
4737
4910
  if (isExpanded) {
4738
4911
  const cleanup = connect();
4739
4912
  return cleanup;
@@ -4748,7 +4921,7 @@ function useTunnelStream() {
4748
4921
  return { connect };
4749
4922
  }
4750
4923
  // src/hooks/useProviderUsage.ts
4751
- import { useEffect as useEffect13, useCallback as useCallback10, useRef as useRef6 } from "react";
4924
+ import { useEffect as useEffect14, useCallback as useCallback10, useRef as useRef7 } from "react";
4752
4925
  var POLL_INTERVAL = 60000;
4753
4926
  var STALE_THRESHOLD = 30000;
4754
4927
  var inflight = new Set;
@@ -4777,9 +4950,9 @@ function useProviderUsage(provider, authType) {
4777
4950
  inflight.delete(provider);
4778
4951
  }
4779
4952
  }, [provider, isOAuthProvider, setUsage, setLoading, setLastFetched]);
4780
- const fetchRef = useRef6(fetchUsage);
4953
+ const fetchRef = useRef7(fetchUsage);
4781
4954
  fetchRef.current = fetchUsage;
4782
- useEffect13(() => {
4955
+ useEffect14(() => {
4783
4956
  if (!provider || !isOAuthProvider)
4784
4957
  return;
4785
4958
  fetchRef.current();
@@ -4822,8 +4995,8 @@ function useGitDiffFullFile(file, staged = false, enabled = false) {
4822
4995
  });
4823
4996
  }
4824
4997
  // 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";
4998
+ import { useQuery as useQuery12, useMutation as useMutation8, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
4999
+ import { useEffect as useEffect15, useRef as useRef8, useCallback as useCallback11 } from "react";
4827
5000
  import {
4828
5001
  listMcpServers,
4829
5002
  startMcpServer,
@@ -4845,7 +5018,7 @@ function useMCPServers() {
4845
5018
  },
4846
5019
  refetchInterval: 1e4
4847
5020
  });
4848
- useEffect14(() => {
5021
+ useEffect15(() => {
4849
5022
  if (query.data?.servers) {
4850
5023
  setServers(query.data.servers);
4851
5024
  }
@@ -4853,7 +5026,7 @@ function useMCPServers() {
4853
5026
  return query;
4854
5027
  }
4855
5028
  function useStartMCPServer() {
4856
- const queryClient = useQueryClient10();
5029
+ const queryClient = useQueryClient11();
4857
5030
  return useMutation8({
4858
5031
  mutationFn: async (name) => {
4859
5032
  const { data, error } = await startMcpServer({
@@ -4872,7 +5045,7 @@ function useStartMCPServer() {
4872
5045
  });
4873
5046
  }
4874
5047
  function useStopMCPServer() {
4875
- const queryClient = useQueryClient10();
5048
+ const queryClient = useQueryClient11();
4876
5049
  const setLoading = useMCPStore((s) => s.setLoading);
4877
5050
  return useMutation8({
4878
5051
  mutationFn: async (name) => {
@@ -4894,7 +5067,7 @@ function useStopMCPServer() {
4894
5067
  });
4895
5068
  }
4896
5069
  function useAddMCPServer() {
4897
- const queryClient = useQueryClient10();
5070
+ const queryClient = useQueryClient11();
4898
5071
  return useMutation8({
4899
5072
  mutationFn: async (params) => {
4900
5073
  const { data, error } = await addMcpServer({
@@ -4913,7 +5086,7 @@ function useAddMCPServer() {
4913
5086
  });
4914
5087
  }
4915
5088
  function useRemoveMCPServer() {
4916
- const queryClient = useQueryClient10();
5089
+ const queryClient = useQueryClient11();
4917
5090
  return useMutation8({
4918
5091
  mutationFn: async (name) => {
4919
5092
  const { data, error } = await removeMcpServer({
@@ -4932,7 +5105,7 @@ function useRemoveMCPServer() {
4932
5105
  });
4933
5106
  }
4934
5107
  function useAuthenticateMCPServer() {
4935
- const queryClient = useQueryClient10();
5108
+ const queryClient = useQueryClient11();
4936
5109
  return useMutation8({
4937
5110
  mutationFn: async (name) => {
4938
5111
  const { data, error } = await initiateMcpAuth({
@@ -4951,7 +5124,7 @@ function useAuthenticateMCPServer() {
4951
5124
  });
4952
5125
  }
4953
5126
  function useRevokeMCPAuth() {
4954
- const queryClient = useQueryClient10();
5127
+ const queryClient = useQueryClient11();
4955
5128
  return useMutation8({
4956
5129
  mutationFn: async (name) => {
4957
5130
  const { data, error } = await revokeMcpAuth({
@@ -4988,15 +5161,15 @@ function useCopilotDevicePoller() {
4988
5161
  const copilotDevice = useMCPStore((s) => s.copilotDevice);
4989
5162
  const setCopilotDevice = useMCPStore((s) => s.setCopilotDevice);
4990
5163
  const setLoading = useMCPStore((s) => s.setLoading);
4991
- const queryClient = useQueryClient10();
4992
- const timerRef = useRef7(null);
5164
+ const queryClient = useQueryClient11();
5165
+ const timerRef = useRef8(null);
4993
5166
  const stopPolling = useCallback11(() => {
4994
5167
  if (timerRef.current) {
4995
5168
  clearInterval(timerRef.current);
4996
5169
  timerRef.current = null;
4997
5170
  }
4998
5171
  }, []);
4999
- useEffect14(() => {
5172
+ useEffect15(() => {
5000
5173
  if (!copilotDevice) {
5001
5174
  stopPolling();
5002
5175
  return;
@@ -5031,8 +5204,8 @@ function useCopilotDevicePoller() {
5031
5204
  return copilotDevice;
5032
5205
  }
5033
5206
  // 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";
5207
+ import { useMutation as useMutation9, useQuery as useQuery13, useQueryClient as useQueryClient12 } from "@tanstack/react-query";
5208
+ import { useEffect as useEffect16 } from "react";
5036
5209
  function useSkills() {
5037
5210
  const setSkillsConfig = useSkillsStore((s) => s.setSkillsConfig);
5038
5211
  const query = useQuery13({
@@ -5042,7 +5215,7 @@ function useSkills() {
5042
5215
  },
5043
5216
  refetchInterval: 30000
5044
5217
  });
5045
- useEffect15(() => {
5218
+ useEffect16(() => {
5046
5219
  if (query.data?.items) {
5047
5220
  setSkillsConfig({
5048
5221
  skills: query.data.items,
@@ -5055,7 +5228,7 @@ function useSkills() {
5055
5228
  return query;
5056
5229
  }
5057
5230
  function useUpdateSkillsConfig() {
5058
- const queryClient = useQueryClient11();
5231
+ const queryClient = useQueryClient12();
5059
5232
  const setSkillsConfig = useSkillsStore((s) => s.setSkillsConfig);
5060
5233
  return useMutation9({
5061
5234
  mutationFn: (input) => apiClient.updateSkillsConfig(input),
@@ -5173,6 +5346,7 @@ export {
5173
5346
  useCopilotDevicePoller,
5174
5347
  useConfig,
5175
5348
  useCommitChanges,
5349
+ useClientEvents,
5176
5350
  useBranches,
5177
5351
  useAuthenticateMCPServer,
5178
5352
  useAuthStatus,
@@ -5182,4 +5356,4 @@ export {
5182
5356
  sessionsQueryKey
5183
5357
  };
5184
5358
 
5185
- //# debugId=2FC62A50D828F41864756E2164756E21
5359
+ //# debugId=45CFEFDB9295F3FD64756E2164756E21