@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.
- package/dist/components/file-browser/FileViewerPanel.d.ts +5 -1
- package/dist/components/file-browser/FileViewerPanel.d.ts.map +1 -1
- package/dist/components/git/GitDiffPanel.d.ts +5 -1
- package/dist/components/git/GitDiffPanel.d.ts.map +1 -1
- package/dist/components/git/GitDiffViewer.d.ts.map +1 -1
- package/dist/components/index.js +2246 -1962
- package/dist/components/index.js.map +58 -56
- package/dist/components/mcp/MCPSidebar.d.ts.map +1 -1
- package/dist/components/messages/ActionToolBox.d.ts.map +1 -1
- package/dist/components/messages/CompactActivityGroup.d.ts.map +1 -1
- package/dist/components/messages/MessagePartItem.d.ts.map +1 -1
- package/dist/components/messages/MessageThread.d.ts.map +1 -1
- package/dist/components/messages/UserMessageGroup.d.ts.map +1 -1
- package/dist/components/messages/renderers/BashRenderer.d.ts.map +1 -1
- package/dist/components/messages/renderers/DiffView.d.ts.map +1 -1
- package/dist/components/messages/threadDensity.d.ts +9 -0
- package/dist/components/messages/threadDensity.d.ts.map +1 -0
- package/dist/components/onboarding/OnboardingModal.d.ts +2 -0
- package/dist/components/onboarding/OnboardingModal.d.ts.map +1 -1
- package/dist/components/session-files/SessionFilesDiffPanel.d.ts +5 -1
- package/dist/components/session-files/SessionFilesDiffPanel.d.ts.map +1 -1
- package/dist/components/sessions/LeanHeader.d.ts.map +1 -1
- package/dist/components/sessions/SessionHeader.d.ts.map +1 -1
- package/dist/components/settings/SettingsSidebar.d.ts.map +1 -1
- package/dist/components/skills/SkillViewerPanel.d.ts +5 -1
- package/dist/components/skills/SkillViewerPanel.d.ts.map +1 -1
- package/dist/components/skills/SkillsSidebar.d.ts.map +1 -1
- package/dist/components/ui/Toaster.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +439 -121
- package/dist/hooks/index.js.map +11 -7
- package/dist/hooks/useAuthStatus.d.ts.map +1 -1
- package/dist/hooks/useClientEvents.d.ts +2 -0
- package/dist/hooks/useClientEvents.d.ts.map +1 -0
- package/dist/hooks/useContainerWidth.d.ts +7 -0
- package/dist/hooks/useContainerWidth.d.ts.map +1 -0
- package/dist/hooks/usePreferences.d.ts.map +1 -1
- package/dist/index.js +2511 -1981
- package/dist/index.js.map +60 -56
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +54 -1
- package/dist/lib/index.js.map +5 -4
- package/dist/lib/open-url.d.ts.map +1 -1
- package/dist/lib/platform.d.ts +14 -0
- package/dist/lib/platform.d.ts.map +1 -0
- package/dist/stores/index.js.map +2 -2
- package/dist/stores/toastStore.d.ts +5 -2
- package/dist/stores/toastStore.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/hooks/index.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
3078
|
+
import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
|
|
2741
3079
|
|
|
2742
3080
|
// src/stores/focusStore.ts
|
|
2743
|
-
import { create as
|
|
2744
|
-
var useFocusStore =
|
|
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
|
|
3094
|
+
import { create as create12 } from "zustand";
|
|
2757
3095
|
import { persist } from "zustand/middleware";
|
|
2758
|
-
var useSidebarStore =
|
|
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
|
|
2768
|
-
var useFilePickerStore =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
3922
|
+
import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
|
|
3585
3923
|
function useCreateBranch(sessionId) {
|
|
3586
|
-
const queryClient =
|
|
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
|
|
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
|
|
3637
|
-
var usePendingResearchStore =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
3878
|
-
const loadingToastIdRef =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
4486
|
+
import { useEffect as useEffect11, useRef as useRef4 } from "react";
|
|
4197
4487
|
var STORAGE_KEY3 = "pendingPolarCheckout";
|
|
4198
4488
|
function useTopupCallback() {
|
|
4199
|
-
const hasHandled =
|
|
4200
|
-
const loadingToastId =
|
|
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
|
-
|
|
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
|
|
4265
|
-
import { useQueryClient as
|
|
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 =
|
|
4605
|
+
const queryClient = useQueryClient9();
|
|
4316
4606
|
const [initialized, setInitialized] = useState5(false);
|
|
4317
4607
|
const [oauthPolling, setOauthPolling] = useState5(false);
|
|
4318
|
-
const oauthPollingRef =
|
|
4319
|
-
const preOauthProvidersRef =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
4593
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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 =
|
|
5080
|
+
const fetchRef = useRef7(fetchUsage);
|
|
4781
5081
|
fetchRef.current = fetchUsage;
|
|
4782
|
-
|
|
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
|
|
4826
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4992
|
-
const timerRef =
|
|
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
|
-
|
|
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
|
|
5035
|
-
import { useEffect as
|
|
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
|
-
|
|
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 =
|
|
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=
|
|
5503
|
+
//# debugId=5F8DA6B0D961E4EF64756E2164756E21
|