@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.
- package/dist/components/index.js +185 -182
- package/dist/components/index.js.map +7 -7
- package/dist/components/messages/renderers/BashRenderer.d.ts.map +1 -1
- package/dist/components/ui/Toaster.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +295 -121
- package/dist/hooks/index.js.map +5 -4
- package/dist/hooks/useClientEvents.d.ts +2 -0
- package/dist/hooks/useClientEvents.d.ts.map +1 -0
- package/dist/index.js +370 -195
- package/dist/index.js.map +8 -7
- package/dist/stores/index.js.map +2 -2
- package/dist/stores/toastStore.d.ts +4 -2
- package/dist/stores/toastStore.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/hooks/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
2961
|
+
import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
|
|
2741
2962
|
|
|
2742
2963
|
// src/stores/focusStore.ts
|
|
2743
|
-
import { create as
|
|
2744
|
-
var useFocusStore =
|
|
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
|
|
2977
|
+
import { create as create12 } from "zustand";
|
|
2757
2978
|
import { persist } from "zustand/middleware";
|
|
2758
|
-
var useSidebarStore =
|
|
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
|
|
2768
|
-
var useFilePickerStore =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
3805
|
+
import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
|
|
3585
3806
|
function useCreateBranch(sessionId) {
|
|
3586
|
-
const queryClient =
|
|
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
|
|
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
|
|
3637
|
-
var usePendingResearchStore =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
3878
|
-
const loadingToastIdRef =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
4369
|
+
import { useEffect as useEffect11, useRef as useRef4 } from "react";
|
|
4197
4370
|
var STORAGE_KEY3 = "pendingPolarCheckout";
|
|
4198
4371
|
function useTopupCallback() {
|
|
4199
|
-
const hasHandled =
|
|
4200
|
-
const loadingToastId =
|
|
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
|
-
|
|
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
|
|
4265
|
-
import { useQueryClient as
|
|
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 =
|
|
4488
|
+
const queryClient = useQueryClient9();
|
|
4316
4489
|
const [initialized, setInitialized] = useState5(false);
|
|
4317
4490
|
const [oauthPolling, setOauthPolling] = useState5(false);
|
|
4318
|
-
const oauthPollingRef =
|
|
4319
|
-
const preOauthProvidersRef =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
4593
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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 =
|
|
4953
|
+
const fetchRef = useRef7(fetchUsage);
|
|
4781
4954
|
fetchRef.current = fetchUsage;
|
|
4782
|
-
|
|
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
|
|
4826
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4992
|
-
const timerRef =
|
|
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
|
-
|
|
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
|
|
5035
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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=
|
|
5359
|
+
//# debugId=45CFEFDB9295F3FD64756E2164756E21
|