@ottocode/web-sdk 0.1.309 → 0.1.311

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/components/chat/ChatInput.d.ts +4 -0
  2. package/dist/components/chat/ChatInput.d.ts.map +1 -1
  3. package/dist/components/chat/ChatInputContainer.d.ts +4 -0
  4. package/dist/components/chat/ChatInputContainer.d.ts.map +1 -1
  5. package/dist/components/chat/ConfigModal.d.ts +3 -1
  6. package/dist/components/chat/ConfigModal.d.ts.map +1 -1
  7. package/dist/components/chat/ConfigSelector.d.ts.map +1 -1
  8. package/dist/components/chat/InputApprovalBar.d.ts.map +1 -1
  9. package/dist/components/chat/InputSecureInputBar.d.ts.map +1 -1
  10. package/dist/components/chat/InputSubagentsBar.d.ts.map +1 -1
  11. package/dist/components/chat/InputTodosBar.d.ts.map +1 -1
  12. package/dist/components/chat/NewSessionLanding.d.ts +4 -0
  13. package/dist/components/chat/NewSessionLanding.d.ts.map +1 -1
  14. package/dist/components/chat/input-bar-chrome.d.ts +24 -0
  15. package/dist/components/chat/input-bar-chrome.d.ts.map +1 -0
  16. package/dist/components/common/OttoOIcon.d.ts +8 -0
  17. package/dist/components/common/OttoOIcon.d.ts.map +1 -0
  18. package/dist/components/index.d.ts +3 -2
  19. package/dist/components/index.d.ts.map +1 -1
  20. package/dist/components/index.js +4462 -3514
  21. package/dist/components/index.js.map +40 -30
  22. package/dist/components/messages/MessageThreadContainer.d.ts +6 -0
  23. package/dist/components/messages/MessageThreadContainer.d.ts.map +1 -1
  24. package/dist/components/messages/OttoKickoffNotice.d.ts +15 -0
  25. package/dist/components/messages/OttoKickoffNotice.d.ts.map +1 -0
  26. package/dist/components/messages/OttoWakeupNotice.d.ts +12 -0
  27. package/dist/components/messages/OttoWakeupNotice.d.ts.map +1 -0
  28. package/dist/components/messages/UserMessageGroup.d.ts.map +1 -1
  29. package/dist/components/messages/compactActivity.d.ts.map +1 -1
  30. package/dist/components/messages/otto-notice-parsing.d.ts +43 -0
  31. package/dist/components/messages/otto-notice-parsing.d.ts.map +1 -0
  32. package/dist/components/messages/renderers/GoalToolRenderer.d.ts.map +1 -1
  33. package/dist/components/otto/OttoGoalBar.d.ts +18 -0
  34. package/dist/components/otto/OttoGoalBar.d.ts.map +1 -0
  35. package/dist/components/otto/OttoSessionRail.d.ts +15 -0
  36. package/dist/components/otto/OttoSessionRail.d.ts.map +1 -0
  37. package/dist/components/otto/OttoSessionView.d.ts +14 -0
  38. package/dist/components/otto/OttoSessionView.d.ts.map +1 -0
  39. package/dist/components/otto/OttoTabBar.d.ts +20 -0
  40. package/dist/components/otto/OttoTabBar.d.ts.map +1 -0
  41. package/dist/components/otto/OttoWorkspace.d.ts +20 -0
  42. package/dist/components/otto/OttoWorkspace.d.ts.map +1 -0
  43. package/dist/components/otto/index.d.ts +7 -0
  44. package/dist/components/otto/index.d.ts.map +1 -0
  45. package/dist/components/sessions/SessionListContainer.d.ts +8 -0
  46. package/dist/components/sessions/SessionListContainer.d.ts.map +1 -1
  47. package/dist/components/subagents/SubagentFloatingViewer.d.ts +3 -2
  48. package/dist/components/subagents/SubagentFloatingViewer.d.ts.map +1 -1
  49. package/dist/components/titlebar/TitleBar.d.ts +48 -0
  50. package/dist/components/titlebar/TitleBar.d.ts.map +1 -0
  51. package/dist/hooks/index.d.ts +1 -0
  52. package/dist/hooks/index.d.ts.map +1 -1
  53. package/dist/hooks/index.js +240 -70
  54. package/dist/hooks/index.js.map +11 -10
  55. package/dist/hooks/useAgents.d.ts.map +1 -1
  56. package/dist/hooks/useChatComposer.d.ts.map +1 -1
  57. package/dist/hooks/useEdgeHover.d.ts +26 -0
  58. package/dist/hooks/useEdgeHover.d.ts.map +1 -0
  59. package/dist/hooks/useGoals.d.ts +34 -6
  60. package/dist/hooks/useGoals.d.ts.map +1 -1
  61. package/dist/hooks/useSessionStream.d.ts.map +1 -1
  62. package/dist/hooks/useSessions.d.ts +9 -2
  63. package/dist/hooks/useSessions.d.ts.map +1 -1
  64. package/dist/index.js +4608 -3571
  65. package/dist/index.js.map +42 -32
  66. package/dist/lib/api-client/goals.d.ts +9 -1
  67. package/dist/lib/api-client/goals.d.ts.map +1 -1
  68. package/dist/lib/api-client/index.d.ts +8 -0
  69. package/dist/lib/api-client/index.d.ts.map +1 -1
  70. package/dist/lib/api-client/sessions.d.ts +2 -0
  71. package/dist/lib/api-client/sessions.d.ts.map +1 -1
  72. package/dist/lib/index.js +27 -3
  73. package/dist/lib/index.js.map +5 -5
  74. package/dist/stores/index.d.ts +1 -1
  75. package/dist/stores/index.d.ts.map +1 -1
  76. package/dist/stores/index.js +57 -56
  77. package/dist/stores/index.js.map +6 -6
  78. package/dist/stores/subagentViewerStore.d.ts +20 -5
  79. package/dist/stores/subagentViewerStore.d.ts.map +1 -1
  80. package/dist/stores/workspaceTabStore.d.ts +14 -0
  81. package/dist/stores/workspaceTabStore.d.ts.map +1 -0
  82. package/dist/types/api.d.ts +2 -2
  83. package/dist/types/api.d.ts.map +1 -1
  84. package/package.json +3 -3
  85. package/dist/components/goals/GoalsSidebar.d.ts +0 -6
  86. package/dist/components/goals/GoalsSidebar.d.ts.map +0 -1
  87. package/dist/components/goals/GoalsSidebarToggle.d.ts +0 -6
  88. package/dist/components/goals/GoalsSidebarToggle.d.ts.map +0 -1
  89. package/dist/components/goals/index.d.ts +0 -3
  90. package/dist/components/goals/index.d.ts.map +0 -1
  91. package/dist/stores/goalsPanelStore.d.ts +0 -9
  92. package/dist/stores/goalsPanelStore.d.ts.map +0 -1
@@ -5,6 +5,7 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
5
5
  import {
6
6
  createSession as apiCreateSession,
7
7
  listSessions as apiListSessions,
8
+ getSession as apiGetSession,
8
9
  listMessages as apiListMessages,
9
10
  createMessage as apiCreateMessage,
10
11
  abortSession as apiAbortSession,
@@ -243,9 +244,9 @@ var sessionsMixin = {
243
244
  return page.items;
244
245
  },
245
246
  async getSessionsPage(params = {}) {
246
- const { limit = 50, offset = 0 } = params;
247
+ const { limit = 50, offset = 0, sessionType } = params;
247
248
  const response = await apiListSessions({
248
- query: { limit, offset }
249
+ query: sessionType ? { limit, offset, sessionType } : { limit, offset }
249
250
  });
250
251
  if (response.error)
251
252
  throw new Error(extractErrorMessage(response.error));
@@ -266,6 +267,12 @@ var sessionsMixin = {
266
267
  throw new Error("No data returned from create session");
267
268
  return convertSession(response.data);
268
269
  },
270
+ async getSession(sessionId) {
271
+ const response = await apiGetSession({ path: { sessionId } });
272
+ if (response.error)
273
+ throw new Error(extractErrorMessage(response.error));
274
+ return convertSession(response.data);
275
+ },
269
276
  async updateSession(sessionId, data) {
270
277
  const response = await apiUpdateSession({
271
278
  path: { sessionId },
@@ -762,13 +769,21 @@ var branchesMixin = {
762
769
  import {
763
770
  getSessionGoal as apiGetSessionGoal,
764
771
  createSessionGoal as apiCreateSessionGoal,
772
+ listGoals as apiListGoals,
765
773
  updateGoal as apiUpdateGoal,
766
774
  addGoalTasks as apiAddGoalTasks,
767
775
  updateGoalTask as apiUpdateGoalTask,
776
+ deleteGoalTask as apiDeleteGoalTask,
768
777
  startGoal as apiStartGoal,
769
778
  listSessionSubagents as apiListSessionSubagents
770
779
  } from "@ottocode/api";
771
780
  var goalsMixin = {
781
+ async listGoals() {
782
+ const response = await apiListGoals();
783
+ if (response.error)
784
+ throw new Error(extractErrorMessage(response.error));
785
+ return response.data;
786
+ },
772
787
  async getSessionGoal(sessionId) {
773
788
  const response = await apiGetSessionGoal({ path: { sessionId } });
774
789
  if (response.error)
@@ -811,6 +826,12 @@ var goalsMixin = {
811
826
  throw new Error(extractErrorMessage(response.error));
812
827
  return response.data;
813
828
  },
829
+ async deleteGoalTask(goalId, taskId) {
830
+ const response = await apiDeleteGoalTask({ path: { goalId, taskId } });
831
+ if (response.error)
832
+ throw new Error(extractErrorMessage(response.error));
833
+ return response.data;
834
+ },
814
835
  async startGoal(goalId) {
815
836
  const response = await apiStartGoal({ path: { goalId } });
816
837
  if (response.error)
@@ -1327,6 +1348,7 @@ class ApiClient {
1327
1348
  getSessions = sessionsMixin.getSessions;
1328
1349
  getSessionsPage = sessionsMixin.getSessionsPage;
1329
1350
  createSession = sessionsMixin.createSession;
1351
+ getSession = sessionsMixin.getSession;
1330
1352
  updateSession = sessionsMixin.updateSession;
1331
1353
  markSessionViewed = sessionsMixin.markSessionViewed;
1332
1354
  deleteSession = sessionsMixin.deleteSession;
@@ -1384,10 +1406,12 @@ class ApiClient {
1384
1406
  shareSession = branchesMixin.shareSession;
1385
1407
  syncSession = branchesMixin.syncSession;
1386
1408
  getSessionGoal = goalsMixin.getSessionGoal;
1409
+ listGoals = goalsMixin.listGoals;
1387
1410
  createSessionGoal = goalsMixin.createSessionGoal;
1388
1411
  updateGoal = goalsMixin.updateGoal;
1389
1412
  addGoalTasks = goalsMixin.addGoalTasks;
1390
1413
  updateGoalTask = goalsMixin.updateGoalTask;
1414
+ deleteGoalTask = goalsMixin.deleteGoalTask;
1391
1415
  startGoal = goalsMixin.startGoal;
1392
1416
  listSessionSubagents = goalsMixin.listSessionSubagents;
1393
1417
  approveToolCall = approvalMixin.approveToolCall;
@@ -2685,7 +2709,7 @@ function useCreateGitBranch() {
2685
2709
  });
2686
2710
  }
2687
2711
  // src/hooks/useMessages.ts
2688
- import { useQuery as useQuery5, useMutation as useMutation4, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2712
+ import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2689
2713
 
2690
2714
  // src/hooks/useQueueState.ts
2691
2715
  import { useQuery as useQuery4 } from "@tanstack/react-query";
@@ -2763,17 +2787,19 @@ function useMessageQueuePosition(sessionId, messageId) {
2763
2787
  import {
2764
2788
  useInfiniteQuery,
2765
2789
  useMutation as useMutation3,
2790
+ useQuery as useQuery5,
2766
2791
  useQueryClient as useQueryClient3
2767
2792
  } from "@tanstack/react-query";
2768
2793
  import { useMemo as useMemo2 } from "react";
2769
2794
  var SESSIONS_PAGE_SIZE = 50;
2770
2795
  var sessionsQueryKey = ["sessions", "list"];
2771
- function useSessionsInfinite() {
2796
+ function useSessionsInfinite(sessionType) {
2772
2797
  return useInfiniteQuery({
2773
- queryKey: sessionsQueryKey,
2798
+ queryKey: sessionType ? [...sessionsQueryKey, sessionType] : sessionsQueryKey,
2774
2799
  queryFn: ({ pageParam = 0 }) => apiClient.getSessionsPage({
2775
2800
  limit: SESSIONS_PAGE_SIZE,
2776
- offset: pageParam
2801
+ offset: pageParam,
2802
+ sessionType
2777
2803
  }),
2778
2804
  getNextPageParam: (lastPage) => lastPage.nextOffset ?? undefined,
2779
2805
  initialPageParam: 0,
@@ -2782,8 +2808,8 @@ function useSessionsInfinite() {
2782
2808
  refetchOnWindowFocus: false
2783
2809
  });
2784
2810
  }
2785
- function useSessions() {
2786
- const query = useSessionsInfinite();
2811
+ function useSessions(sessionType) {
2812
+ const query = useSessionsInfinite(sessionType);
2787
2813
  const data = useMemo2(() => {
2788
2814
  if (!query.data?.pages)
2789
2815
  return [];
@@ -2801,7 +2827,14 @@ function useSessions() {
2801
2827
  }
2802
2828
  function useSession(sessionId) {
2803
2829
  const { data: sessions } = useSessions();
2804
- return sessions?.find((s) => s.id === sessionId);
2830
+ const listed = sessions?.find((s) => s.id === sessionId);
2831
+ const { data: detail } = useQuery5({
2832
+ queryKey: ["session", sessionId],
2833
+ queryFn: () => apiClient.getSession(sessionId),
2834
+ enabled: Boolean(sessionId) && !listed,
2835
+ staleTime: 15000
2836
+ });
2837
+ return listed ?? detail;
2805
2838
  }
2806
2839
  function useCreateSession() {
2807
2840
  const queryClient = useQueryClient3();
@@ -2894,7 +2927,7 @@ function useDeleteSession() {
2894
2927
  // src/hooks/useMessages.ts
2895
2928
  function useMessages(sessionId, options = {}) {
2896
2929
  const { enabled = true, staleTime = 15000 } = options;
2897
- return useQuery5({
2930
+ return useQuery6({
2898
2931
  queryKey: ["messages", sessionId],
2899
2932
  queryFn: () => {
2900
2933
  if (!sessionId) {
@@ -4405,7 +4438,9 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
4405
4438
  }
4406
4439
  queryClient.invalidateQueries({ queryKey: ["messages", sessionId] });
4407
4440
  queryClient.invalidateQueries({ queryKey: sessionsQueryKey });
4441
+ queryClient.invalidateQueries({ queryKey: ["session", sessionId] });
4408
4442
  queryClient.invalidateQueries({ queryKey: ["goal", sessionId] });
4443
+ queryClient.invalidateQueries({ queryKey: ["goals", "project"] });
4409
4444
  queryClient.invalidateQueries({ queryKey: ["subagents", sessionId] });
4410
4445
  break;
4411
4446
  }
@@ -4536,6 +4571,7 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
4536
4571
  }
4537
4572
  case "goal.updated": {
4538
4573
  queryClient.invalidateQueries({ queryKey: ["goal", sessionId] });
4574
+ queryClient.invalidateQueries({ queryKey: ["goals", "project"] });
4539
4575
  queryClient.invalidateQueries({
4540
4576
  queryKey: ["subagents", sessionId]
4541
4577
  });
@@ -4558,6 +4594,7 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
4558
4594
  if (now - lastSessionInvalidation >= 2000) {
4559
4595
  lastSessionInvalidation = now;
4560
4596
  queryClient.invalidateQueries({ queryKey: sessionsQueryKey });
4597
+ queryClient.invalidateQueries({ queryKey: ["session", sessionId] });
4561
4598
  }
4562
4599
  }
4563
4600
  });
@@ -5910,10 +5947,10 @@ function useFileUpload(options = {}) {
5910
5947
  };
5911
5948
  }
5912
5949
  // src/hooks/useSessionFiles.ts
5913
- import { useQuery as useQuery6 } from "@tanstack/react-query";
5950
+ import { useQuery as useQuery7 } from "@tanstack/react-query";
5914
5951
  function useSessionFiles(sessionId, enabled = true) {
5915
5952
  const isExpanded = useSessionFilesStore((state) => state.isExpanded);
5916
- return useQuery6({
5953
+ return useQuery7({
5917
5954
  queryKey: ["session", sessionId, "files"],
5918
5955
  queryFn: () => sessionId ? apiClient.getSessionFiles(sessionId) : null,
5919
5956
  enabled: !!sessionId && enabled,
@@ -5923,7 +5960,7 @@ function useSessionFiles(sessionId, enabled = true) {
5923
5960
  });
5924
5961
  }
5925
5962
  // src/hooks/useBranch.ts
5926
- import { useQuery as useQuery7, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
5963
+ import { useQuery as useQuery8, useMutation as useMutation5, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
5927
5964
  function useCreateBranch(sessionId) {
5928
5965
  const queryClient = useQueryClient7();
5929
5966
  return useMutation5({
@@ -5943,7 +5980,7 @@ function useCreateBranch(sessionId) {
5943
5980
  });
5944
5981
  }
5945
5982
  function useBranches(sessionId) {
5946
- return useQuery7({
5983
+ return useQuery8({
5947
5984
  queryKey: ["branches", sessionId],
5948
5985
  queryFn: () => {
5949
5986
  if (!sessionId)
@@ -5954,7 +5991,7 @@ function useBranches(sessionId) {
5954
5991
  });
5955
5992
  }
5956
5993
  function useParentSession(sessionId) {
5957
- return useQuery7({
5994
+ return useQuery8({
5958
5995
  queryKey: ["parentSession", sessionId],
5959
5996
  queryFn: () => {
5960
5997
  if (!sessionId)
@@ -5965,11 +6002,12 @@ function useParentSession(sessionId) {
5965
6002
  });
5966
6003
  }
5967
6004
  // src/hooks/useGoals.ts
5968
- import { useMutation as useMutation6, useQuery as useQuery8, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
6005
+ import { useMutation as useMutation6, useQuery as useQuery9, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
5969
6006
  var goalQueryKey = (sessionId) => [
5970
6007
  "goal",
5971
6008
  sessionId
5972
6009
  ];
6010
+ var projectGoalsQueryKey = ["goals", "project"];
5973
6011
  var subagentsQueryKey = (sessionId) => [
5974
6012
  "subagents",
5975
6013
  sessionId
@@ -5978,9 +6016,36 @@ function useOttoEnabled() {
5978
6016
  const { data: config2 } = useConfig();
5979
6017
  return config2?.defaults?.ottoEnabled ?? true;
5980
6018
  }
6019
+ function useProjectGoals() {
6020
+ const ottoEnabled = useOttoEnabled();
6021
+ return useQuery9({
6022
+ queryKey: projectGoalsQueryKey,
6023
+ queryFn: () => apiClient.listGoals(),
6024
+ enabled: ottoEnabled,
6025
+ refetchInterval: 1e4
6026
+ });
6027
+ }
6028
+ function applyGoalToProjectCache(queryClient, goal) {
6029
+ queryClient.setQueryData(projectGoalsQueryKey, (old) => old ? { goals: old.goals.map((g) => g.id === goal.id ? goal : g) } : old);
6030
+ queryClient.invalidateQueries({ queryKey: projectGoalsQueryKey });
6031
+ }
6032
+ function useAddProjectGoalTasks() {
6033
+ const queryClient = useQueryClient8();
6034
+ return useMutation6({
6035
+ mutationFn: (input) => apiClient.addGoalTasks(input.goalId, input.tasks),
6036
+ onSuccess: ({ goal }) => applyGoalToProjectCache(queryClient, goal)
6037
+ });
6038
+ }
6039
+ function useDeleteProjectGoalTask() {
6040
+ const queryClient = useQueryClient8();
6041
+ return useMutation6({
6042
+ mutationFn: (input) => apiClient.deleteGoalTask(input.goalId, input.taskId),
6043
+ onSuccess: ({ goal }) => applyGoalToProjectCache(queryClient, goal)
6044
+ });
6045
+ }
5981
6046
  function useSessionGoal(sessionId) {
5982
6047
  const ottoEnabled = useOttoEnabled();
5983
- return useQuery8({
6048
+ return useQuery9({
5984
6049
  queryKey: goalQueryKey(sessionId),
5985
6050
  queryFn: () => {
5986
6051
  if (!sessionId)
@@ -6013,6 +6078,7 @@ function useUpdateGoal(sessionId) {
6013
6078
  }),
6014
6079
  onSuccess: () => {
6015
6080
  queryClient.invalidateQueries({ queryKey: goalQueryKey(sessionId) });
6081
+ queryClient.invalidateQueries({ queryKey: projectGoalsQueryKey });
6016
6082
  }
6017
6083
  });
6018
6084
  }
@@ -6022,6 +6088,7 @@ function useAddGoalTasks(sessionId) {
6022
6088
  mutationFn: (input) => apiClient.addGoalTasks(input.goalId, input.tasks),
6023
6089
  onSuccess: () => {
6024
6090
  queryClient.invalidateQueries({ queryKey: goalQueryKey(sessionId) });
6091
+ queryClient.invalidateQueries({ queryKey: projectGoalsQueryKey });
6025
6092
  }
6026
6093
  });
6027
6094
  }
@@ -6035,11 +6102,12 @@ function useUpdateGoalTask(sessionId) {
6035
6102
  }),
6036
6103
  onSuccess: () => {
6037
6104
  queryClient.invalidateQueries({ queryKey: goalQueryKey(sessionId) });
6105
+ queryClient.invalidateQueries({ queryKey: projectGoalsQueryKey });
6038
6106
  }
6039
6107
  });
6040
6108
  }
6041
6109
  function useSessionSubagents(sessionId, status) {
6042
- return useQuery8({
6110
+ return useQuery9({
6043
6111
  queryKey: [...subagentsQueryKey(sessionId), status ?? "all"],
6044
6112
  queryFn: () => {
6045
6113
  if (!sessionId)
@@ -6059,6 +6127,8 @@ function useStartGoal(sessionId) {
6059
6127
  mutationFn: (input) => apiClient.startGoal(input.goalId),
6060
6128
  onSuccess: () => {
6061
6129
  queryClient.invalidateQueries({ queryKey: goalQueryKey(sessionId) });
6130
+ queryClient.invalidateQueries({ queryKey: projectGoalsQueryKey });
6131
+ queryClient.invalidateQueries({ queryKey: ["sessions", "list"] });
6062
6132
  if (sessionId) {
6063
6133
  queryClient.invalidateQueries({ queryKey: ["messages", sessionId] });
6064
6134
  }
@@ -6066,7 +6136,7 @@ function useStartGoal(sessionId) {
6066
6136
  });
6067
6137
  }
6068
6138
  // src/hooks/useResearch.ts
6069
- import { useQuery as useQuery9, useMutation as useMutation7, useQueryClient as useQueryClient9 } from "@tanstack/react-query";
6139
+ import { useQuery as useQuery10, useMutation as useMutation7, useQueryClient as useQueryClient9 } from "@tanstack/react-query";
6070
6140
  import {
6071
6141
  createResearchSession as apiCreateResearchSession,
6072
6142
  deleteResearchSession as apiDeleteResearchSession,
@@ -6162,7 +6232,7 @@ class ResearchApiClient {
6162
6232
  }
6163
6233
  var researchApi = new ResearchApiClient;
6164
6234
  function useResearchSessions(parentSessionId, enabled = true) {
6165
- return useQuery9({
6235
+ return useQuery10({
6166
6236
  queryKey: ["research", "sessions", parentSessionId],
6167
6237
  queryFn: () => researchApi.listResearchSessions(parentSessionId),
6168
6238
  enabled: !!parentSessionId && enabled,
@@ -6511,9 +6581,9 @@ function useOttoRouterBalance(providerName) {
6511
6581
  };
6512
6582
  }
6513
6583
  // src/hooks/useShareStatus.ts
6514
- import { useQuery as useQuery10 } from "@tanstack/react-query";
6584
+ import { useQuery as useQuery11 } from "@tanstack/react-query";
6515
6585
  function useShareStatus(sessionId) {
6516
- const { data, isLoading, error } = useQuery10({
6586
+ const { data, isLoading, error } = useQuery11({
6517
6587
  queryKey: ["share-status", sessionId],
6518
6588
  queryFn: () => apiClient.getShareStatus(sessionId),
6519
6589
  enabled: !!sessionId,
@@ -7003,7 +7073,7 @@ function useAuthStatus() {
7003
7073
  };
7004
7074
  }
7005
7075
  // src/hooks/useTunnel.ts
7006
- import { useQuery as useQuery11, useMutation as useMutation8, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
7076
+ import { useQuery as useQuery12, useMutation as useMutation8, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
7007
7077
  import { useEffect as useEffect14, useCallback as useCallback9, useRef as useRef6 } from "react";
7008
7078
  import {
7009
7079
  client as client2,
@@ -7051,7 +7121,7 @@ function useTunnelStatus() {
7051
7121
  const setStatus = useTunnelStore((s) => s.setStatus);
7052
7122
  const setUrl = useTunnelStore((s) => s.setUrl);
7053
7123
  const setError = useTunnelStore((s) => s.setError);
7054
- const query = useQuery11({
7124
+ const query = useQuery12({
7055
7125
  queryKey: ["tunnel", "status"],
7056
7126
  queryFn: fetchTunnelStatus,
7057
7127
  refetchInterval: 3000,
@@ -7114,7 +7184,7 @@ function useStopTunnel() {
7114
7184
  function useTunnelQr() {
7115
7185
  const url = useTunnelStore((s) => s.url);
7116
7186
  const setQrCode = useTunnelStore((s) => s.setQrCode);
7117
- const query = useQuery11({
7187
+ const query = useQuery12({
7118
7188
  queryKey: ["tunnel", "qr", url],
7119
7189
  queryFn: fetchTunnelQr,
7120
7190
  enabled: !!url
@@ -7227,9 +7297,9 @@ function useProviderUsage(provider, authType) {
7227
7297
  };
7228
7298
  }
7229
7299
  // src/hooks/useFileBrowser.ts
7230
- import { useQuery as useQuery12 } from "@tanstack/react-query";
7300
+ import { useQuery as useQuery13 } from "@tanstack/react-query";
7231
7301
  function useFileTree(dirPath, enabled = true) {
7232
- return useQuery12({
7302
+ return useQuery13({
7233
7303
  queryKey: ["files", "tree", dirPath],
7234
7304
  queryFn: () => apiClient.getFileTree(dirPath),
7235
7305
  enabled,
@@ -7238,7 +7308,7 @@ function useFileTree(dirPath, enabled = true) {
7238
7308
  });
7239
7309
  }
7240
7310
  function useFileContent(filePath) {
7241
- return useQuery12({
7311
+ return useQuery13({
7242
7312
  queryKey: ["files", "read", filePath],
7243
7313
  queryFn: () => filePath ? apiClient.readFileContent(filePath) : null,
7244
7314
  enabled: !!filePath,
@@ -7247,7 +7317,7 @@ function useFileContent(filePath) {
7247
7317
  });
7248
7318
  }
7249
7319
  function useGitDiffFullFile(file, staged = false, enabled = false) {
7250
- return useQuery12({
7320
+ return useQuery13({
7251
7321
  queryKey: ["git", "diff", "fullFile", file, staged],
7252
7322
  queryFn: () => file ? apiClient.getGitDiffFullFile(file, staged) : null,
7253
7323
  enabled: enabled && !!file,
@@ -7256,7 +7326,7 @@ function useGitDiffFullFile(file, staged = false, enabled = false) {
7256
7326
  });
7257
7327
  }
7258
7328
  // src/hooks/useMCP.ts
7259
- import { useQuery as useQuery13, useMutation as useMutation9, useQueryClient as useQueryClient12 } from "@tanstack/react-query";
7329
+ import { useQuery as useQuery14, useMutation as useMutation9, useQueryClient as useQueryClient12 } from "@tanstack/react-query";
7260
7330
  import { useEffect as useEffect16, useRef as useRef8, useCallback as useCallback11 } from "react";
7261
7331
  import {
7262
7332
  listMcpServers,
@@ -7271,7 +7341,7 @@ import {
7271
7341
  } from "@ottocode/api";
7272
7342
  function useMCPServers() {
7273
7343
  const setServers = useMCPStore((s) => s.setServers);
7274
- const query = useQuery13({
7344
+ const query = useQuery14({
7275
7345
  queryKey: ["mcp", "servers"],
7276
7346
  queryFn: async () => {
7277
7347
  const { data } = await listMcpServers();
@@ -7404,7 +7474,7 @@ function useRevokeMCPAuth() {
7404
7474
  });
7405
7475
  }
7406
7476
  function useMCPAuthStatus(name) {
7407
- return useQuery13({
7477
+ return useQuery14({
7408
7478
  queryKey: ["mcp", "auth", name],
7409
7479
  queryFn: async () => {
7410
7480
  if (!name)
@@ -7465,12 +7535,12 @@ function useCopilotDevicePoller() {
7465
7535
  return copilotDevice;
7466
7536
  }
7467
7537
  // src/hooks/useSkills.ts
7468
- import { useMutation as useMutation10, useQuery as useQuery14, useQueryClient as useQueryClient13 } from "@tanstack/react-query";
7538
+ import { useMutation as useMutation10, useQuery as useQuery15, useQueryClient as useQueryClient13 } from "@tanstack/react-query";
7469
7539
  import { useEffect as useEffect17 } from "react";
7470
7540
  function useSkills(options = {}) {
7471
7541
  const enabled = options.enabled ?? true;
7472
7542
  const setSkillsConfig = useSkillsStore((s) => s.setSkillsConfig);
7473
- const query = useQuery14({
7543
+ const query = useQuery15({
7474
7544
  queryKey: ["skills"],
7475
7545
  queryFn: async () => {
7476
7546
  return apiClient.getSkillsConfig();
@@ -7507,7 +7577,7 @@ function useUpdateSkillsConfig() {
7507
7577
  });
7508
7578
  }
7509
7579
  function useSkillDetail(name) {
7510
- return useQuery14({
7580
+ return useQuery15({
7511
7581
  queryKey: ["skills", name],
7512
7582
  queryFn: async () => {
7513
7583
  if (!name)
@@ -7518,7 +7588,7 @@ function useSkillDetail(name) {
7518
7588
  });
7519
7589
  }
7520
7590
  function useSkillFiles(name) {
7521
- return useQuery14({
7591
+ return useQuery15({
7522
7592
  queryKey: ["skills", name, "files"],
7523
7593
  queryFn: async () => {
7524
7594
  if (!name)
@@ -7529,7 +7599,7 @@ function useSkillFiles(name) {
7529
7599
  });
7530
7600
  }
7531
7601
  function useSkillFileContent(name, filePath) {
7532
- return useQuery14({
7602
+ return useQuery15({
7533
7603
  queryKey: ["skills", name, "files", filePath],
7534
7604
  queryFn: async () => {
7535
7605
  if (!name || !filePath)
@@ -7541,7 +7611,7 @@ function useSkillFileContent(name, filePath) {
7541
7611
  }
7542
7612
  // src/hooks/useAgents.ts
7543
7613
  import { useEffect as useEffect18 } from "react";
7544
- import { useMutation as useMutation11, useQuery as useQuery15, useQueryClient as useQueryClient14 } from "@tanstack/react-query";
7614
+ import { useMutation as useMutation11, useQuery as useQuery16, useQueryClient as useQueryClient14 } from "@tanstack/react-query";
7545
7615
 
7546
7616
  // src/stores/agentsStore.ts
7547
7617
  import { create as create22 } from "zustand";
@@ -7616,7 +7686,7 @@ function useAgentDetails(options = {}) {
7616
7686
  const setAgents = useAgentsStore((s) => s.setAgents);
7617
7687
  const selectedAgent = useAgentsStore((s) => s.selectedAgent);
7618
7688
  const selectAgent = useAgentsStore((s) => s.selectAgent);
7619
- const query = useQuery15({
7689
+ const query = useQuery16({
7620
7690
  queryKey: ["config", "agents"],
7621
7691
  queryFn: () => apiClient.getAgentDetails(),
7622
7692
  enabled,
@@ -7634,7 +7704,7 @@ function useAgentDetails(options = {}) {
7634
7704
  return query;
7635
7705
  }
7636
7706
  function useAgent(agentName) {
7637
- return useQuery15({
7707
+ return useQuery16({
7638
7708
  queryKey: ["config", "agents", agentName],
7639
7709
  queryFn: async () => {
7640
7710
  if (!agentName)
@@ -7646,7 +7716,7 @@ function useAgent(agentName) {
7646
7716
  });
7647
7717
  }
7648
7718
  function useMentionAgents(options = {}) {
7649
- return useQuery15({
7719
+ return useQuery16({
7650
7720
  queryKey: ["config", "agents"],
7651
7721
  queryFn: () => apiClient.getAgentDetails(),
7652
7722
  enabled: options.enabled ?? true,
@@ -7657,7 +7727,7 @@ function useConfigTools(options = {}) {
7657
7727
  const managerOpen = useAgentsStore((s) => s.isManagerOpen);
7658
7728
  const createOpen = useAgentsStore((s) => s.isCreateModalOpen);
7659
7729
  const enabled = options.enabled ?? (managerOpen || createOpen);
7660
- return useQuery15({
7730
+ return useQuery16({
7661
7731
  queryKey: ["config", "tools"],
7662
7732
  queryFn: () => apiClient.getConfigTools(),
7663
7733
  enabled,
@@ -7751,7 +7821,7 @@ function useChatComposer({
7751
7821
  setProvider(selectedAgent?.provider ?? config2.defaults.provider ?? "");
7752
7822
  setModel(selectedAgent?.model ?? config2.defaults.model ?? "");
7753
7823
  }, [sessionId, agentDetails?.agents, config2, defaultAgent]);
7754
- const agentNames = useMemo4(() => agentDetails?.agents.length ? agentDetails.agents.map((agentDetail) => agentDetail.name) : config2?.agents ?? [], [agentDetails?.agents, config2?.agents]);
7824
+ const agentNames = useMemo4(() => ((agentDetails?.agents.length) ? agentDetails.agents.map((agentDetail) => agentDetail.name) : config2?.agents ?? []).filter((name) => name !== "otto"), [agentDetails?.agents, config2?.agents]);
7755
7825
  const selectedModel = useMemo4(() => allModels?.[provider]?.models?.find((m) => m.id === model), [allModels, provider, model]);
7756
7826
  const persist2 = useCallback12(async (update) => {
7757
7827
  if (!sessionId)
@@ -7873,8 +7943,103 @@ function useContainerWidth(ref) {
7873
7943
  }, [ref]);
7874
7944
  return width;
7875
7945
  }
7946
+ // src/hooks/useEdgeHover.ts
7947
+ import { useEffect as useEffect21, useRef as useRef10, useState as useState9 } from "react";
7948
+ var HOVER_SHOW_DELAY_MS = 260;
7949
+ var HOVER_HIDE_DELAY_MS = 120;
7950
+ function useEdgeHover({
7951
+ side,
7952
+ enabled,
7953
+ hoverRatio,
7954
+ activeWidth,
7955
+ ignoreSelector
7956
+ }) {
7957
+ const [isVisible, setIsVisible] = useState9(false);
7958
+ const [isHoverPending, setIsHoverPending] = useState9(false);
7959
+ const isVisibleRef = useRef10(false);
7960
+ const showTimeoutRef = useRef10(null);
7961
+ const hideTimeoutRef = useRef10(null);
7962
+ useEffect21(() => {
7963
+ const setVisible = (visible) => {
7964
+ isVisibleRef.current = visible;
7965
+ setIsVisible(visible);
7966
+ };
7967
+ const clearHoverTimeouts = () => {
7968
+ if (showTimeoutRef.current !== null) {
7969
+ window.clearTimeout(showTimeoutRef.current);
7970
+ showTimeoutRef.current = null;
7971
+ }
7972
+ if (hideTimeoutRef.current !== null) {
7973
+ window.clearTimeout(hideTimeoutRef.current);
7974
+ hideTimeoutRef.current = null;
7975
+ }
7976
+ };
7977
+ const scheduleVisible = (visible) => {
7978
+ if (isVisibleRef.current === visible) {
7979
+ setIsHoverPending(false);
7980
+ return;
7981
+ }
7982
+ setIsHoverPending(visible);
7983
+ const delay = visible ? HOVER_SHOW_DELAY_MS : HOVER_HIDE_DELAY_MS;
7984
+ const targetRef = visible ? showTimeoutRef : hideTimeoutRef;
7985
+ const oppositeRef = visible ? hideTimeoutRef : showTimeoutRef;
7986
+ if (oppositeRef.current !== null) {
7987
+ window.clearTimeout(oppositeRef.current);
7988
+ oppositeRef.current = null;
7989
+ }
7990
+ if (targetRef.current !== null)
7991
+ return;
7992
+ targetRef.current = window.setTimeout(() => {
7993
+ setVisible(visible);
7994
+ setIsHoverPending(false);
7995
+ targetRef.current = null;
7996
+ }, delay);
7997
+ };
7998
+ if (!enabled) {
7999
+ clearHoverTimeouts();
8000
+ setIsHoverPending(false);
8001
+ setVisible(false);
8002
+ return;
8003
+ }
8004
+ const handleMouseMove = (event) => {
8005
+ const target = event.target;
8006
+ if (ignoreSelector && target instanceof Element && target.closest(ignoreSelector)) {
8007
+ clearHoverTimeouts();
8008
+ setIsHoverPending(false);
8009
+ setVisible(false);
8010
+ return;
8011
+ }
8012
+ const triggerWidth = window.innerWidth * hoverRatio;
8013
+ const zoneWidth = isVisibleRef.current && activeWidth ? Math.max(triggerWidth, activeWidth) : triggerWidth;
8014
+ const distance = side === "left" ? event.clientX : window.innerWidth - event.clientX;
8015
+ scheduleVisible(distance <= zoneWidth);
8016
+ };
8017
+ const handleMouseLeave = () => {
8018
+ clearHoverTimeouts();
8019
+ setIsHoverPending(false);
8020
+ setVisible(false);
8021
+ };
8022
+ const handleMouseOut = (event) => {
8023
+ if (!event.relatedTarget) {
8024
+ handleMouseLeave();
8025
+ }
8026
+ };
8027
+ window.addEventListener("mousemove", handleMouseMove);
8028
+ window.addEventListener("mouseout", handleMouseOut);
8029
+ window.addEventListener("blur", handleMouseLeave);
8030
+ document.documentElement.addEventListener("mouseleave", handleMouseLeave);
8031
+ return () => {
8032
+ clearHoverTimeouts();
8033
+ window.removeEventListener("mousemove", handleMouseMove);
8034
+ window.removeEventListener("mouseout", handleMouseOut);
8035
+ window.removeEventListener("blur", handleMouseLeave);
8036
+ document.documentElement.removeEventListener("mouseleave", handleMouseLeave);
8037
+ };
8038
+ }, [enabled, hoverRatio, activeWidth, ignoreSelector, side]);
8039
+ return { isVisible, isHoverPending };
8040
+ }
7876
8041
  // src/hooks/useVoiceInput.ts
7877
- import { useCallback as useCallback14, useEffect as useEffect21, useRef as useRef10, useState as useState9 } from "react";
8042
+ import { useCallback as useCallback14, useEffect as useEffect22, useRef as useRef11, useState as useState10 } from "react";
7878
8043
  var TARGET_SAMPLE_RATE = 16000;
7879
8044
  var PCM_FRAME_BYTES = 3200;
7880
8045
  function getAudioContextConstructor() {
@@ -7931,22 +8096,22 @@ function useVoiceInput({
7931
8096
  onNeedsInstall,
7932
8097
  lang = "en-US"
7933
8098
  } = {}) {
7934
- const [isListening, setIsListening] = useState9(false);
7935
- const [isTranscribing, setIsTranscribing] = useState9(false);
7936
- const [analyser, setAnalyser] = useState9(null);
7937
- const [error, setError] = useState9(null);
7938
- const streamRef = useRef10(null);
7939
- const audioContextRef = useRef10(null);
7940
- const processorRef = useRef10(null);
7941
- const sourceRef = useRef10(null);
7942
- const socketRef = useRef10(null);
7943
- const frameBufferRef = useRef10(new Uint8Array(0));
7944
- const stoppingRef = useRef10(false);
7945
- const sessionIdRef = useRef10(null);
7946
- const onTranscriptRef = useRef10(onTranscript);
7947
- const onErrorRef = useRef10(onError);
7948
- const onNeedsInstallRef = useRef10(onNeedsInstall);
7949
- useEffect21(() => {
8099
+ const [isListening, setIsListening] = useState10(false);
8100
+ const [isTranscribing, setIsTranscribing] = useState10(false);
8101
+ const [analyser, setAnalyser] = useState10(null);
8102
+ const [error, setError] = useState10(null);
8103
+ const streamRef = useRef11(null);
8104
+ const audioContextRef = useRef11(null);
8105
+ const processorRef = useRef11(null);
8106
+ const sourceRef = useRef11(null);
8107
+ const socketRef = useRef11(null);
8108
+ const frameBufferRef = useRef11(new Uint8Array(0));
8109
+ const stoppingRef = useRef11(false);
8110
+ const sessionIdRef = useRef11(null);
8111
+ const onTranscriptRef = useRef11(onTranscript);
8112
+ const onErrorRef = useRef11(onError);
8113
+ const onNeedsInstallRef = useRef11(onNeedsInstall);
8114
+ useEffect22(() => {
7950
8115
  onTranscriptRef.current = onTranscript;
7951
8116
  onErrorRef.current = onError;
7952
8117
  onNeedsInstallRef.current = onNeedsInstall;
@@ -8157,7 +8322,7 @@ function useVoiceInput({
8157
8322
  isSupported,
8158
8323
  lang
8159
8324
  ]);
8160
- useEffect21(() => cleanup, [cleanup]);
8325
+ useEffect22(() => cleanup, [cleanup]);
8161
8326
  return {
8162
8327
  isListening,
8163
8328
  isTranscribing,
@@ -8169,8 +8334,8 @@ function useVoiceInput({
8169
8334
  };
8170
8335
  }
8171
8336
  // src/hooks/useDictationModels.ts
8172
- import { useCallback as useCallback15, useEffect as useEffect22, useRef as useRef11, useState as useState10 } from "react";
8173
- import { useMutation as useMutation12, useQuery as useQuery16, useQueryClient as useQueryClient15 } from "@tanstack/react-query";
8337
+ import { useCallback as useCallback15, useEffect as useEffect23, useRef as useRef12, useState as useState11 } from "react";
8338
+ import { useMutation as useMutation12, useQuery as useQuery17, useQueryClient as useQueryClient15 } from "@tanstack/react-query";
8174
8339
  var DICTATION_STATUS_QUERY_KEY = ["dictation", "status"];
8175
8340
  function mergeModelState(current, model) {
8176
8341
  if (!current)
@@ -8192,11 +8357,11 @@ function parseInstallEvent(raw) {
8192
8357
  }
8193
8358
  function useDictationModels() {
8194
8359
  const queryClient = useQueryClient15();
8195
- const eventSourceRef = useRef11(null);
8196
- const [activeInstallModelId, setActiveInstallModelId] = useState10(null);
8197
- const [installProgress, setInstallProgress] = useState10(null);
8198
- const [installStreamError, setInstallStreamError] = useState10(null);
8199
- const statusQuery = useQuery16({
8360
+ const eventSourceRef = useRef12(null);
8361
+ const [activeInstallModelId, setActiveInstallModelId] = useState11(null);
8362
+ const [installProgress, setInstallProgress] = useState11(null);
8363
+ const [installStreamError, setInstallStreamError] = useState11(null);
8364
+ const statusQuery = useQuery17({
8200
8365
  queryKey: DICTATION_STATUS_QUERY_KEY,
8201
8366
  queryFn: () => apiClient.getDictationStatus(),
8202
8367
  refetchInterval: (query) => query.state.data?.models.some((model) => model.installing) ? 1000 : 30000
@@ -8238,7 +8403,7 @@ function useDictationModels() {
8238
8403
  });
8239
8404
  };
8240
8405
  }, [closeInstallStream, queryClient]);
8241
- useEffect22(() => closeInstallStream, [closeInstallStream]);
8406
+ useEffect23(() => closeInstallStream, [closeInstallStream]);
8242
8407
  const installMutation = useMutation12({
8243
8408
  mutationFn: (input) => apiClient.installDictationModel(input),
8244
8409
  onSuccess: (data) => {
@@ -8329,6 +8494,7 @@ export {
8329
8494
  usePushCommits,
8330
8495
  usePullChanges,
8331
8496
  useProviderUsage,
8497
+ useProjectGoals,
8332
8498
  usePreferences,
8333
8499
  useParentSession,
8334
8500
  useOttoRouterPayments,
@@ -8358,9 +8524,11 @@ export {
8358
8524
  useFileTree,
8359
8525
  useFileContent,
8360
8526
  useExportToSession,
8527
+ useEdgeHover,
8361
8528
  useDictationModels,
8362
8529
  useDeleteSession,
8363
8530
  useDeleteResearchSession,
8531
+ useDeleteProjectGoalTask,
8364
8532
  useDeleteFiles,
8365
8533
  useDeleteAgent,
8366
8534
  useCreateSessionGoal,
@@ -8384,14 +8552,16 @@ export {
8384
8552
  useAgentDetails,
8385
8553
  useAgent,
8386
8554
  useAddRemote,
8555
+ useAddProjectGoalTasks,
8387
8556
  useAddMCPServer,
8388
8557
  useAddGoalTasks,
8389
8558
  subagentsQueryKey,
8390
8559
  sessionsQueryKey,
8560
+ projectGoalsQueryKey,
8391
8561
  optimisticallyQueueMessage,
8392
8562
  normalizeQueueState,
8393
8563
  goalQueryKey,
8394
8564
  getAgentToolCount
8395
8565
  };
8396
8566
 
8397
- //# debugId=37EDDE4EE625A54D64756E2164756E21
8567
+ //# debugId=0CEC6E40D0E00EAC64756E2164756E21