@ottocode/web-sdk 0.1.270 → 0.1.272

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 (82) hide show
  1. package/dist/components/chat/ChatInput.d.ts.map +1 -1
  2. package/dist/components/chat/InputQueueBar.d.ts +6 -0
  3. package/dist/components/chat/InputQueueBar.d.ts.map +1 -0
  4. package/dist/components/chat/InputTodosBar.d.ts +6 -0
  5. package/dist/components/chat/InputTodosBar.d.ts.map +1 -0
  6. package/dist/components/chat/ShortcutsModal.d.ts.map +1 -1
  7. package/dist/components/file-browser/FileBrowserSidebar.d.ts.map +1 -1
  8. package/dist/components/file-browser/FileBrowserSidebarToggle.d.ts.map +1 -1
  9. package/dist/components/file-browser/FileViewerPanel.d.ts +3 -0
  10. package/dist/components/file-browser/FileViewerPanel.d.ts.map +1 -1
  11. package/dist/components/file-browser/QuickFilePicker.d.ts.map +1 -1
  12. package/dist/components/git/GitDiffPanel.d.ts +4 -0
  13. package/dist/components/git/GitDiffPanel.d.ts.map +1 -1
  14. package/dist/components/git/GitDiffViewer.d.ts.map +1 -1
  15. package/dist/components/git/GitFileItem.d.ts.map +1 -1
  16. package/dist/components/git/GitSidebarToggle.d.ts.map +1 -1
  17. package/dist/components/index.d.ts +3 -0
  18. package/dist/components/index.d.ts.map +1 -1
  19. package/dist/components/index.js +4942 -3723
  20. package/dist/components/index.js.map +55 -49
  21. package/dist/components/mcp/MCPSidebarToggle.d.ts.map +1 -1
  22. package/dist/components/messages/ActionToolBox.d.ts +2 -1
  23. package/dist/components/messages/ActionToolBox.d.ts.map +1 -1
  24. package/dist/components/messages/AssistantMessageGroup.d.ts.map +1 -1
  25. package/dist/components/messages/CompactActivityGroup.d.ts +2 -1
  26. package/dist/components/messages/CompactActivityGroup.d.ts.map +1 -1
  27. package/dist/components/messages/MessagePartItem.d.ts.map +1 -1
  28. package/dist/components/messages/MessageThread.d.ts.map +1 -1
  29. package/dist/components/messages/UserMessageGroup.d.ts.map +1 -1
  30. package/dist/components/messages/renderers/ProgressUpdateRenderer.d.ts.map +1 -1
  31. package/dist/components/messages/renderers/index.d.ts.map +1 -1
  32. package/dist/components/session-files/SessionFilesDiffPanel.d.ts +7 -0
  33. package/dist/components/session-files/SessionFilesDiffPanel.d.ts.map +1 -1
  34. package/dist/components/session-files/SessionFilesSidebar.d.ts.map +1 -1
  35. package/dist/components/session-files/SessionFilesSidebarToggle.d.ts.map +1 -1
  36. package/dist/components/sessions/SessionItem.d.ts.map +1 -1
  37. package/dist/components/sessions/SessionListContainer.d.ts.map +1 -1
  38. package/dist/components/sessions/session-time.d.ts.map +1 -1
  39. package/dist/components/settings/SettingsSidebarToggle.d.ts.map +1 -1
  40. package/dist/components/sidebar/SidebarShortcutBadge.d.ts +6 -0
  41. package/dist/components/sidebar/SidebarShortcutBadge.d.ts.map +1 -0
  42. package/dist/components/skills/SkillViewerPanel.d.ts +4 -0
  43. package/dist/components/skills/SkillViewerPanel.d.ts.map +1 -1
  44. package/dist/components/skills/SkillsSidebarToggle.d.ts.map +1 -1
  45. package/dist/components/tunnel/TunnelSidebarToggle.d.ts.map +1 -1
  46. package/dist/components/workspace/ViewerTabs.d.ts +2 -0
  47. package/dist/components/workspace/ViewerTabs.d.ts.map +1 -0
  48. package/dist/hooks/index.js +321 -61
  49. package/dist/hooks/index.js.map +17 -15
  50. package/dist/hooks/useClientEvents.d.ts.map +1 -1
  51. package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -1
  52. package/dist/hooks/useMessages.d.ts.map +1 -1
  53. package/dist/hooks/useQueueState.d.ts.map +1 -1
  54. package/dist/hooks/useSessions.d.ts +1 -0
  55. package/dist/hooks/useSessions.d.ts.map +1 -1
  56. package/dist/hooks/useShortcutHintsVisible.d.ts +5 -0
  57. package/dist/hooks/useShortcutHintsVisible.d.ts.map +1 -0
  58. package/dist/index.js +5048 -3761
  59. package/dist/index.js.map +57 -51
  60. package/dist/lib/api-client/index.d.ts +1 -0
  61. package/dist/lib/api-client/index.d.ts.map +1 -1
  62. package/dist/lib/api-client/sessions.d.ts +1 -0
  63. package/dist/lib/api-client/sessions.d.ts.map +1 -1
  64. package/dist/lib/api-client/utils.d.ts.map +1 -1
  65. package/dist/lib/index.js +11 -2
  66. package/dist/lib/index.js.map +5 -5
  67. package/dist/stores/fileBrowserStore.d.ts +1 -0
  68. package/dist/stores/fileBrowserStore.d.ts.map +1 -1
  69. package/dist/stores/gitStore.d.ts.map +1 -1
  70. package/dist/stores/index.d.ts +2 -0
  71. package/dist/stores/index.d.ts.map +1 -1
  72. package/dist/stores/index.js +201 -60
  73. package/dist/stores/index.js.map +9 -7
  74. package/dist/stores/sessionFilesStore.d.ts.map +1 -1
  75. package/dist/stores/skillsStore.d.ts.map +1 -1
  76. package/dist/stores/todoStore.d.ts +18 -0
  77. package/dist/stores/todoStore.d.ts.map +1 -0
  78. package/dist/stores/viewerTabsStore.d.ts +41 -0
  79. package/dist/stores/viewerTabsStore.d.ts.map +1 -0
  80. package/dist/types/api.d.ts +7 -0
  81. package/dist/types/api.d.ts.map +1 -1
  82. package/package.json +3 -3
@@ -9,6 +9,7 @@ import {
9
9
  createMessage as apiCreateMessage,
10
10
  abortSession as apiAbortSession,
11
11
  deleteSession as apiDeleteSession,
12
+ markSessionViewed as apiMarkSessionViewed,
12
13
  updateSession as apiUpdateSession,
13
14
  getSessionQueue as apiGetSessionQueue,
14
15
  removeFromQueue as apiRemoveFromQueue,
@@ -95,7 +96,8 @@ function convertSession(apiSession) {
95
96
  ...apiSession,
96
97
  title: apiSession.title ?? null,
97
98
  createdAt: typeof apiSession.createdAt === "string" ? new Date(apiSession.createdAt).getTime() : apiSession.createdAt,
98
- lastActiveAt: typeof apiSession.lastActiveAt === "string" ? new Date(apiSession.lastActiveAt).getTime() : apiSession.lastActiveAt
99
+ lastActiveAt: typeof apiSession.lastActiveAt === "string" ? new Date(apiSession.lastActiveAt).getTime() : apiSession.lastActiveAt,
100
+ lastViewedAt: typeof apiSession.lastViewedAt === "string" ? new Date(apiSession.lastViewedAt).getTime() : apiSession.lastViewedAt
99
101
  };
100
102
  }
101
103
  function convertMessage(apiMessage) {
@@ -145,6 +147,12 @@ var sessionsMixin = {
145
147
  throw new Error(extractErrorMessage(response.error));
146
148
  return convertSession(response.data);
147
149
  },
150
+ async markSessionViewed(sessionId) {
151
+ const response = await apiMarkSessionViewed({ path: { sessionId } });
152
+ if (response.error)
153
+ throw new Error(extractErrorMessage(response.error));
154
+ return convertSession(response.data);
155
+ },
148
156
  async deleteSession(sessionId) {
149
157
  const response = await apiDeleteSession({ path: { sessionId } });
150
158
  if (response.error)
@@ -872,6 +880,7 @@ class ApiClient {
872
880
  getSessionsPage = sessionsMixin.getSessionsPage;
873
881
  createSession = sessionsMixin.createSession;
874
882
  updateSession = sessionsMixin.updateSession;
883
+ markSessionViewed = sessionsMixin.markSessionViewed;
875
884
  deleteSession = sessionsMixin.deleteSession;
876
885
  abortSession = sessionsMixin.abortSession;
877
886
  abortMessage = sessionsMixin.abortMessage;
@@ -1184,29 +1193,117 @@ function useFiles(options = {}) {
1184
1193
  import { useQuery as useQuery3, useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1185
1194
 
1186
1195
  // src/stores/gitStore.ts
1187
- import { create as create8 } from "zustand";
1196
+ import { create as create9 } from "zustand";
1188
1197
 
1189
1198
  // src/stores/sessionFilesStore.ts
1190
- import { create as create7 } from "zustand";
1199
+ import { create as create8 } from "zustand";
1191
1200
 
1192
1201
  // src/stores/researchStore.ts
1193
- import { create as create6 } from "zustand";
1202
+ import { create as create7 } from "zustand";
1194
1203
 
1195
1204
  // src/stores/settingsStore.ts
1196
- import { create as create5 } from "zustand";
1205
+ import { create as create6 } from "zustand";
1197
1206
 
1198
1207
  // src/stores/tunnelStore.ts
1199
- import { create as create4 } from "zustand";
1208
+ import { create as create5 } from "zustand";
1200
1209
 
1201
1210
  // src/stores/fileBrowserStore.ts
1202
- import { create as create3 } from "zustand";
1211
+ import { create as create4 } from "zustand";
1203
1212
 
1204
1213
  // src/stores/mcpStore.ts
1205
- import { create as create2 } from "zustand";
1214
+ import { create as create3 } from "zustand";
1206
1215
 
1207
1216
  // src/stores/skillsStore.ts
1217
+ import { create as create2 } from "zustand";
1218
+
1219
+ // src/stores/viewerTabsStore.ts
1208
1220
  import { create } from "zustand";
1209
- var useSkillsStore = create((set) => ({
1221
+ function titleFromPath(path) {
1222
+ return path.split("/").pop() || path;
1223
+ }
1224
+ function upsertTab(tabs, tab) {
1225
+ const existingIndex = tabs.findIndex((item) => item.id === tab.id);
1226
+ if (existingIndex === -1) {
1227
+ return [...tabs, tab];
1228
+ }
1229
+ const next = [...tabs];
1230
+ next[existingIndex] = tab;
1231
+ return next;
1232
+ }
1233
+ var useViewerTabsStore = create((set) => ({
1234
+ tabs: [],
1235
+ activeTabId: null,
1236
+ openGitDiffTab: (path, staged) => {
1237
+ const id = `git-diff:${staged ? "staged" : "unstaged"}:${path}`;
1238
+ set((state) => ({
1239
+ tabs: upsertTab(state.tabs, {
1240
+ id,
1241
+ type: "git-diff",
1242
+ title: titleFromPath(path),
1243
+ path,
1244
+ staged
1245
+ }),
1246
+ activeTabId: id
1247
+ }));
1248
+ },
1249
+ openSessionFileDiffTab: (path, operations) => {
1250
+ const id = `session-file-diff:${path}`;
1251
+ set((state) => ({
1252
+ tabs: upsertTab(state.tabs, {
1253
+ id,
1254
+ type: "session-file-diff",
1255
+ title: titleFromPath(path),
1256
+ path,
1257
+ operations,
1258
+ selectedOperationIndex: Math.max(0, operations.length - 1)
1259
+ }),
1260
+ activeTabId: id
1261
+ }));
1262
+ },
1263
+ openFileTab: (path) => {
1264
+ const id = `file:${path}`;
1265
+ set((state) => ({
1266
+ tabs: upsertTab(state.tabs, {
1267
+ id,
1268
+ type: "file",
1269
+ title: titleFromPath(path),
1270
+ path
1271
+ }),
1272
+ activeTabId: id
1273
+ }));
1274
+ },
1275
+ openSkillFileTab: (skill, file) => {
1276
+ const displayFile = file ?? "SKILL.md";
1277
+ const id = `skill-file:${skill}:${displayFile}`;
1278
+ set((state) => ({
1279
+ tabs: upsertTab(state.tabs, {
1280
+ id,
1281
+ type: "skill-file",
1282
+ title: titleFromPath(displayFile),
1283
+ skill,
1284
+ file
1285
+ }),
1286
+ activeTabId: id
1287
+ }));
1288
+ },
1289
+ setActiveTab: (id) => set({ activeTabId: id }),
1290
+ closeTab: (id) => set((state) => {
1291
+ const closingIndex = state.tabs.findIndex((tab) => tab.id === id);
1292
+ const tabs = state.tabs.filter((tab) => tab.id !== id);
1293
+ let activeTabId = state.activeTabId;
1294
+ if (state.activeTabId === id) {
1295
+ activeTabId = tabs[closingIndex]?.id ?? tabs[closingIndex - 1]?.id ?? null;
1296
+ }
1297
+ return { tabs, activeTabId };
1298
+ }),
1299
+ updateSessionFileOperationIndex: (id, index) => set((state) => ({
1300
+ tabs: state.tabs.map((tab) => tab.id === id && tab.type === "session-file-diff" ? { ...tab, selectedOperationIndex: index } : tab)
1301
+ })),
1302
+ closeAllTabs: () => set({ tabs: [], activeTabId: null })
1303
+ }));
1304
+
1305
+ // src/stores/skillsStore.ts
1306
+ var useSkillsStore = create2((set, get) => ({
1210
1307
  isExpanded: false,
1211
1308
  skills: [],
1212
1309
  globalEnabled: true,
@@ -1244,12 +1341,18 @@ var useSkillsStore = create((set) => ({
1244
1341
  setSkills: (skills) => set({ skills }),
1245
1342
  setSkillsConfig: ({ skills, globalEnabled, totalCount, enabledCount }) => set({ skills, globalEnabled, totalCount, enabledCount }),
1246
1343
  selectSkill: (name) => set({ selectedSkill: name, isViewerOpen: false, viewingFile: null }),
1247
- openViewer: (file) => set({ isViewerOpen: true, viewingFile: file }),
1344
+ openViewer: (file) => {
1345
+ const selectedSkill = get().selectedSkill;
1346
+ if (selectedSkill) {
1347
+ useViewerTabsStore.getState().openSkillFileTab(selectedSkill, file);
1348
+ }
1349
+ set({ isViewerOpen: true, viewingFile: file });
1350
+ },
1248
1351
  closeViewer: () => set({ isViewerOpen: false, viewingFile: null })
1249
1352
  }));
1250
1353
 
1251
1354
  // src/stores/mcpStore.ts
1252
- var useMCPStore = create2((set) => ({
1355
+ var useMCPStore = create3((set) => ({
1253
1356
  isExpanded: false,
1254
1357
  servers: [],
1255
1358
  loading: new Set,
@@ -1305,7 +1408,22 @@ var useMCPStore = create2((set) => ({
1305
1408
  }));
1306
1409
 
1307
1410
  // src/stores/fileBrowserStore.ts
1308
- var useFileBrowserStore = create3((set) => ({
1411
+ function getAncestorDirs(path) {
1412
+ const normalizedPath = path.replace(/\\/g, "/").replace(/^\.\//, "");
1413
+ const parts = normalizedPath.split("/").filter(Boolean);
1414
+ return parts.slice(0, -1).map((_, index) => parts.slice(0, index + 1).join("/"));
1415
+ }
1416
+ function revealFileState(state, path) {
1417
+ const expandedDirs = new Set(state.expandedDirs);
1418
+ for (const dir of getAncestorDirs(path)) {
1419
+ expandedDirs.add(dir);
1420
+ }
1421
+ return {
1422
+ selectedFile: path,
1423
+ expandedDirs
1424
+ };
1425
+ }
1426
+ var useFileBrowserStore = create4((set) => ({
1309
1427
  isExpanded: false,
1310
1428
  selectedFile: null,
1311
1429
  isViewerOpen: false,
@@ -1340,10 +1458,14 @@ var useFileBrowserStore = create3((set) => ({
1340
1458
  isViewerOpen: false,
1341
1459
  selectedFile: null
1342
1460
  }),
1343
- openFile: (path) => set({
1344
- selectedFile: path,
1345
- isViewerOpen: true
1346
- }),
1461
+ openFile: (path) => {
1462
+ useViewerTabsStore.getState().openFileTab(path);
1463
+ set((state) => ({
1464
+ ...revealFileState(state, path),
1465
+ isViewerOpen: true
1466
+ }));
1467
+ },
1468
+ revealFile: (path) => set((state) => revealFileState(state, path)),
1347
1469
  closeViewer: () => set({
1348
1470
  isViewerOpen: false,
1349
1471
  selectedFile: null
@@ -1360,7 +1482,7 @@ var useFileBrowserStore = create3((set) => ({
1360
1482
  }));
1361
1483
 
1362
1484
  // src/stores/tunnelStore.ts
1363
- var useTunnelStore = create4((set) => ({
1485
+ var useTunnelStore = create5((set) => ({
1364
1486
  isExpanded: false,
1365
1487
  status: "idle",
1366
1488
  url: null,
@@ -1408,7 +1530,7 @@ var useTunnelStore = create4((set) => ({
1408
1530
  }));
1409
1531
 
1410
1532
  // src/stores/settingsStore.ts
1411
- var useSettingsStore = create5((set) => ({
1533
+ var useSettingsStore = create6((set) => ({
1412
1534
  isExpanded: false,
1413
1535
  toggleSidebar: () => {
1414
1536
  set((state) => {
@@ -1430,7 +1552,7 @@ var useSettingsStore = create5((set) => ({
1430
1552
  }));
1431
1553
 
1432
1554
  // src/stores/researchStore.ts
1433
- var useResearchStore = create6((set, get) => ({
1555
+ var useResearchStore = create7((set, get) => ({
1434
1556
  isExpanded: false,
1435
1557
  activeResearchSessionId: null,
1436
1558
  parentSessionId: null,
@@ -1477,7 +1599,7 @@ var useResearchStore = create6((set, get) => ({
1477
1599
  }));
1478
1600
 
1479
1601
  // src/stores/sessionFilesStore.ts
1480
- var useSessionFilesStore = create7((set) => ({
1602
+ var useSessionFilesStore = create8((set) => ({
1481
1603
  isExpanded: false,
1482
1604
  selectedFile: null,
1483
1605
  allOperations: [],
@@ -1515,13 +1637,16 @@ var useSessionFilesStore = create7((set) => ({
1515
1637
  allOperations: [],
1516
1638
  selectedOperationIndex: 0
1517
1639
  }),
1518
- openDiff: (file, operations) => set({
1519
- selectedFile: file,
1520
- allOperations: operations,
1521
- selectedOperationIndex: operations.length - 1,
1522
- isDiffOpen: true,
1523
- isExpanded: true
1524
- }),
1640
+ openDiff: (file, operations) => {
1641
+ useViewerTabsStore.getState().openSessionFileDiffTab(file, operations);
1642
+ set({
1643
+ selectedFile: file,
1644
+ allOperations: operations,
1645
+ selectedOperationIndex: operations.length - 1,
1646
+ isDiffOpen: true,
1647
+ isExpanded: true
1648
+ });
1649
+ },
1525
1650
  selectOperation: (index) => set({ selectedOperationIndex: index }),
1526
1651
  closeDiff: () => set({
1527
1652
  isDiffOpen: false,
@@ -1532,7 +1657,7 @@ var useSessionFilesStore = create7((set) => ({
1532
1657
  }));
1533
1658
 
1534
1659
  // src/stores/gitStore.ts
1535
- var useGitStore = create8((set) => ({
1660
+ var useGitStore = create9((set) => ({
1536
1661
  isExpanded: false,
1537
1662
  activeSessionId: null,
1538
1663
  selectedFile: null,
@@ -1558,12 +1683,15 @@ var useGitStore = create8((set) => ({
1558
1683
  },
1559
1684
  expandSidebar: () => set({ isExpanded: true }),
1560
1685
  collapseSidebar: () => set({ isExpanded: false, isDiffOpen: false, selectedFile: null }),
1561
- openDiff: (file, staged) => set({
1562
- selectedFile: file,
1563
- selectedFileStaged: staged,
1564
- isDiffOpen: true,
1565
- isExpanded: true
1566
- }),
1686
+ openDiff: (file, staged) => {
1687
+ useViewerTabsStore.getState().openGitDiffTab(file, staged);
1688
+ set({
1689
+ selectedFile: file,
1690
+ selectedFileStaged: staged,
1691
+ isDiffOpen: true,
1692
+ isExpanded: true
1693
+ });
1694
+ },
1567
1695
  closeDiff: () => set({
1568
1696
  isDiffOpen: false,
1569
1697
  selectedFile: null
@@ -1803,6 +1931,25 @@ function useUpdateSession(sessionId) {
1803
1931
  }
1804
1932
  });
1805
1933
  }
1934
+ function useMarkSessionViewed() {
1935
+ const queryClient = useQueryClient3();
1936
+ return useMutation3({
1937
+ mutationFn: (sessionId) => apiClient.markSessionViewed(sessionId),
1938
+ onSuccess: (updatedSession) => {
1939
+ queryClient.setQueryData(sessionsQueryKey, (old) => {
1940
+ if (!old)
1941
+ return old;
1942
+ return {
1943
+ ...old,
1944
+ pages: old.pages.map((page) => ({
1945
+ ...page,
1946
+ items: page.items.map((session) => session.id === updatedSession.id ? { ...session, ...updatedSession } : session)
1947
+ }))
1948
+ };
1949
+ });
1950
+ }
1951
+ });
1952
+ }
1806
1953
  function useDeleteSession() {
1807
1954
  const queryClient = useQueryClient3();
1808
1955
  return useMutation3({
@@ -1832,7 +1979,12 @@ function useMessages(sessionId, options = {}) {
1832
1979
  function useSendMessage(sessionId) {
1833
1980
  const queryClient = useQueryClient4();
1834
1981
  return useMutation4({
1835
- mutationFn: (data) => apiClient.sendMessage(sessionId, data),
1982
+ mutationFn: async (data) => {
1983
+ await apiClient.markSessionViewed(sessionId).catch(() => {
1984
+ return;
1985
+ });
1986
+ return apiClient.sendMessage(sessionId, data);
1987
+ },
1836
1988
  onSuccess: () => {
1837
1989
  queryClient.invalidateQueries({ queryKey: ["messages", sessionId] });
1838
1990
  queryClient.invalidateQueries({ queryKey: sessionsQueryKey });
@@ -1956,8 +2108,8 @@ class SSEClient {
1956
2108
  }
1957
2109
 
1958
2110
  // src/stores/toolApprovalStore.ts
1959
- import { create as create9 } from "zustand";
1960
- var useToolApprovalStore = create9((set) => ({
2111
+ import { create as create10 } from "zustand";
2112
+ var useToolApprovalStore = create10((set) => ({
1961
2113
  pendingApprovals: [],
1962
2114
  addPendingApproval: (approval) => set((state) => ({
1963
2115
  pendingApprovals: [...state.pendingApprovals, approval]
@@ -2717,9 +2869,9 @@ import {
2717
2869
  } from "@ottocode/api";
2718
2870
 
2719
2871
  // src/stores/toastStore.ts
2720
- import { create as create10 } from "zustand";
2872
+ import { create as create11 } from "zustand";
2721
2873
  var toastId = 0;
2722
- var useToastStore = create10((set) => ({
2874
+ var useToastStore = create11((set) => ({
2723
2875
  toasts: [],
2724
2876
  addToast: (toast) => {
2725
2877
  const id = `toast-${++toastId}`;
@@ -2803,6 +2955,7 @@ function openNotificationTarget(notification) {
2803
2955
  function requestNotificationPermission() {
2804
2956
  return new Promise((resolve) => {
2805
2957
  let settled = false;
2958
+ let hasNativeRequest = false;
2806
2959
  const finish = (permission) => {
2807
2960
  if (settled)
2808
2961
  return;
@@ -2812,12 +2965,15 @@ function requestNotificationPermission() {
2812
2965
  try {
2813
2966
  const result = Notification.requestPermission(finish);
2814
2967
  if (result && typeof result.then === "function") {
2968
+ hasNativeRequest = true;
2815
2969
  result.then(finish).catch(() => finish());
2816
2970
  }
2817
2971
  } catch {
2818
2972
  finish();
2819
2973
  }
2820
- setTimeout(() => finish(), 1500);
2974
+ if (!hasNativeRequest) {
2975
+ setTimeout(() => finish(), 60000);
2976
+ }
2821
2977
  });
2822
2978
  }
2823
2979
  function showInAppNotification(notification) {
@@ -2975,6 +3131,8 @@ function useClientEvents(activeSessionId) {
2975
3131
  const currentPermission = Notification.permission;
2976
3132
  if (permission === "granted" || currentPermission === "granted") {
2977
3133
  toast.success("Browser notifications enabled.");
3134
+ } else if (permission === "default" && currentPermission === "default") {
3135
+ return;
2978
3136
  } else {
2979
3137
  toast.info("Browser notifications were not enabled.");
2980
3138
  }
@@ -3115,8 +3273,8 @@ function useWorkingDirectory() {
3115
3273
  import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
3116
3274
 
3117
3275
  // src/stores/focusStore.ts
3118
- import { create as create11 } from "zustand";
3119
- var useFocusStore = create11((set) => ({
3276
+ import { create as create12 } from "zustand";
3277
+ var useFocusStore = create12((set) => ({
3120
3278
  currentFocus: null,
3121
3279
  sessionIndex: 0,
3122
3280
  gitFileIndex: 0,
@@ -3128,9 +3286,9 @@ var useFocusStore = create11((set) => ({
3128
3286
  }));
3129
3287
 
3130
3288
  // src/stores/sidebarStore.ts
3131
- import { create as create12 } from "zustand";
3289
+ import { create as create13 } from "zustand";
3132
3290
  import { persist } from "zustand/middleware";
3133
- var useSidebarStore = create12()(persist((set) => ({
3291
+ var useSidebarStore = create13()(persist((set) => ({
3134
3292
  isCollapsed: false,
3135
3293
  toggleCollapse: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
3136
3294
  setCollapsed: (collapsed) => set({ isCollapsed: collapsed })
@@ -3139,14 +3297,47 @@ var useSidebarStore = create12()(persist((set) => ({
3139
3297
  }));
3140
3298
 
3141
3299
  // src/stores/filePickerStore.ts
3142
- import { create as create13 } from "zustand";
3143
- var useFilePickerStore = create13((set) => ({
3300
+ import { create as create14 } from "zustand";
3301
+ var useFilePickerStore = create14((set) => ({
3144
3302
  isOpen: false,
3145
3303
  open: () => set({ isOpen: true }),
3146
3304
  close: () => set({ isOpen: false }),
3147
3305
  toggle: () => set((state) => ({ isOpen: !state.isOpen }))
3148
3306
  }));
3149
3307
 
3308
+ // src/stores/terminalStore.ts
3309
+ import { create as create15 } from "zustand";
3310
+ var DEFAULT_HEIGHT = 300;
3311
+ var MIN_HEIGHT = 150;
3312
+ var useTerminalStore = create15((set) => ({
3313
+ isOpen: false,
3314
+ panelHeight: DEFAULT_HEIGHT,
3315
+ activeTabId: null,
3316
+ isMaximized: false,
3317
+ get isExpanded() {
3318
+ return this.isOpen;
3319
+ },
3320
+ get selectedTerminalId() {
3321
+ return this.activeTabId;
3322
+ },
3323
+ openPanel: () => set({ isOpen: true }),
3324
+ closePanel: () => set({ isOpen: false, isMaximized: false }),
3325
+ togglePanel: () => set((s) => ({
3326
+ isOpen: !s.isOpen,
3327
+ isMaximized: !s.isOpen ? s.isMaximized : false
3328
+ })),
3329
+ setPanelHeight: (height) => set({ panelHeight: Math.max(MIN_HEIGHT, height) }),
3330
+ selectTab: (id) => set({ activeTabId: id, isOpen: true }),
3331
+ toggleMaximize: () => set((s) => ({ isMaximized: !s.isMaximized })),
3332
+ expandSidebar: () => set({ isOpen: true }),
3333
+ collapseSidebar: () => set({ isOpen: false, activeTabId: null, isMaximized: false }),
3334
+ toggleSidebar: () => set((s) => ({
3335
+ isOpen: !s.isOpen,
3336
+ isMaximized: !s.isOpen ? s.isMaximized : false
3337
+ })),
3338
+ selectTerminal: (id) => set({ activeTabId: id, isOpen: true })
3339
+ }));
3340
+
3150
3341
  // src/hooks/useKeyboardShortcuts.ts
3151
3342
  function useKeyboardShortcuts({
3152
3343
  sessionIds,
@@ -3179,12 +3370,59 @@ function useKeyboardShortcuts({
3179
3370
  } = useSidebarStore();
3180
3371
  const { isExpanded: isGitExpanded, toggleSidebar: toggleGit } = useGitStore();
3181
3372
  const closeDiff = useGitStore((state) => state.closeDiff);
3373
+ const toggleSessionFiles = useSessionFilesStore((state) => state.toggleSidebar);
3374
+ const toggleFileBrowser = useFileBrowserStore((state) => state.toggleSidebar);
3375
+ const toggleTunnel = useTunnelStore((state) => state.toggleSidebar);
3376
+ const toggleMCP = useMCPStore((state) => state.toggleSidebar);
3377
+ const toggleSkills = useSkillsStore((state) => state.toggleSidebar);
3378
+ const toggleSettings = useSettingsStore((state) => state.toggleSidebar);
3182
3379
  const toggleResearch = useResearchStore((state) => state.toggleSidebar);
3380
+ const toggleTerminalPanel = useTerminalStore((state) => state.togglePanel);
3183
3381
  const currentSessionIndex = sessionIds.indexOf(activeSessionId || "");
3184
3382
  const handleKeyDown = useCallback3((e) => {
3185
3383
  const target = e.target;
3186
3384
  const isInInput = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
3187
3385
  const isInTerminal = !!target.closest("[data-terminal-viewer]");
3386
+ const isShortcutModifierPressed = e.ctrlKey || e.metaKey;
3387
+ if (isShortcutModifierPressed && !e.shiftKey && !e.altKey && e.key >= "1" && e.key <= "7") {
3388
+ e.preventDefault();
3389
+ switch (e.key) {
3390
+ case "1":
3391
+ toggleGit();
3392
+ if (isGitExpanded && currentFocus === "git") {
3393
+ setFocus("input");
3394
+ } else {
3395
+ setFocus("git");
3396
+ resetGitFileIndex();
3397
+ }
3398
+ break;
3399
+ case "2":
3400
+ toggleSessionFiles();
3401
+ setFocus("input");
3402
+ break;
3403
+ case "3":
3404
+ toggleFileBrowser();
3405
+ setFocus("input");
3406
+ break;
3407
+ case "4":
3408
+ toggleTunnel();
3409
+ setFocus("input");
3410
+ break;
3411
+ case "5":
3412
+ toggleMCP();
3413
+ setFocus("input");
3414
+ break;
3415
+ case "6":
3416
+ toggleSkills();
3417
+ setFocus("input");
3418
+ break;
3419
+ case "7":
3420
+ toggleSettings();
3421
+ setFocus("input");
3422
+ break;
3423
+ }
3424
+ return;
3425
+ }
3188
3426
  if ((e.ctrlKey || e.metaKey) && e.key === "h") {
3189
3427
  e.preventDefault();
3190
3428
  if (currentFocus === "sessions") {
@@ -3241,6 +3479,11 @@ function useKeyboardShortcuts({
3241
3479
  toggleGit();
3242
3480
  return;
3243
3481
  }
3482
+ if ((e.ctrlKey || e.metaKey) && e.key === "j") {
3483
+ e.preventDefault();
3484
+ toggleTerminalPanel();
3485
+ return;
3486
+ }
3244
3487
  if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "r") {
3245
3488
  e.preventDefault();
3246
3489
  toggleResearch();
@@ -3364,6 +3607,13 @@ function useKeyboardShortcuts({
3364
3607
  resetGitFileIndex,
3365
3608
  setSessionListCollapsed,
3366
3609
  toggleGit,
3610
+ toggleSessionFiles,
3611
+ toggleFileBrowser,
3612
+ toggleTunnel,
3613
+ toggleMCP,
3614
+ toggleSkills,
3615
+ toggleSettings,
3616
+ toggleTerminalPanel,
3367
3617
  toggleResearch,
3368
3618
  toggleSessionList,
3369
3619
  onSelectSession,
@@ -3380,8 +3630,8 @@ function useKeyboardShortcuts({
3380
3630
  closeDiff
3381
3631
  ]);
3382
3632
  useEffect5(() => {
3383
- window.addEventListener("keydown", handleKeyDown);
3384
- return () => window.removeEventListener("keydown", handleKeyDown);
3633
+ window.addEventListener("keydown", handleKeyDown, true);
3634
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
3385
3635
  }, [handleKeyDown]);
3386
3636
  return {
3387
3637
  currentFocus,
@@ -3934,9 +4184,18 @@ var defaultQueueState = {
3934
4184
  function useQueueState(sessionId) {
3935
4185
  const { data } = useQuery6({
3936
4186
  queryKey: ["queueState", sessionId],
3937
- queryFn: () => defaultQueueState,
4187
+ queryFn: async () => {
4188
+ if (!sessionId)
4189
+ return defaultQueueState;
4190
+ const queueState = await apiClient.getQueueState(sessionId);
4191
+ return {
4192
+ currentMessageId: queueState.currentMessageId,
4193
+ queuedMessages: queueState.queuedMessages,
4194
+ queueLength: queueState.queuedMessages.length
4195
+ };
4196
+ },
3938
4197
  enabled: !!sessionId,
3939
- initialData: defaultQueueState,
4198
+ placeholderData: defaultQueueState,
3940
4199
  staleTime: Infinity
3941
4200
  });
3942
4201
  return data ?? defaultQueueState;
@@ -4008,8 +4267,8 @@ import {
4008
4267
  } from "@ottocode/api";
4009
4268
 
4010
4269
  // src/stores/pendingResearchStore.ts
4011
- import { create as create14 } from "zustand";
4012
- var usePendingResearchStore = create14((set, get) => ({
4270
+ import { create as create16 } from "zustand";
4271
+ var usePendingResearchStore = create16((set, get) => ({
4013
4272
  pendingContexts: new Map,
4014
4273
  addContext: (parentSessionId, context) => {
4015
4274
  set((state) => {
@@ -4158,8 +4417,8 @@ function useExportToSession() {
4158
4417
  import { useEffect as useEffect8, useRef as useRef3 } from "react";
4159
4418
 
4160
4419
  // src/stores/ottorouterStore.ts
4161
- import { create as create15 } from "zustand";
4162
- var useOttoRouterStore = create15((set) => ({
4420
+ import { create as create17 } from "zustand";
4421
+ var useOttoRouterStore = create17((set) => ({
4163
4422
  balance: null,
4164
4423
  usdcBalance: null,
4165
4424
  network: "mainnet",
@@ -4188,8 +4447,8 @@ var useOttoRouterStore = create15((set) => ({
4188
4447
  }));
4189
4448
 
4190
4449
  // src/stores/topupApprovalStore.ts
4191
- import { create as create16 } from "zustand";
4192
- var useTopupApprovalStore = create16((set) => ({
4450
+ import { create as create18 } from "zustand";
4451
+ var useTopupApprovalStore = create18((set) => ({
4193
4452
  pendingTopup: null,
4194
4453
  isProcessing: false,
4195
4454
  selectedMethod: null,
@@ -4342,8 +4601,8 @@ function useSetuPayments(sessionId) {
4342
4601
  import { useEffect as useEffect9, useCallback as useCallback6 } from "react";
4343
4602
 
4344
4603
  // src/stores/usageStore.ts
4345
- import { create as create17 } from "zustand";
4346
- var useUsageStore = create17((set) => ({
4604
+ import { create as create19 } from "zustand";
4605
+ var useUsageStore = create19((set) => ({
4347
4606
  usage: {},
4348
4607
  isLoading: {},
4349
4608
  lastFetched: {},
@@ -4592,9 +4851,9 @@ import { useEffect as useEffect12, useCallback as useCallback8, useState as useS
4592
4851
  import { useQueryClient as useQueryClient9 } from "@tanstack/react-query";
4593
4852
 
4594
4853
  // src/stores/onboardingStore.ts
4595
- import { create as create18 } from "zustand";
4854
+ import { create as create20 } from "zustand";
4596
4855
  var STEPS = ["wallet", "defaults"];
4597
- var useOnboardingStore = create18((set, get) => ({
4856
+ var useOnboardingStore = create20((set, get) => ({
4598
4857
  isOpen: false,
4599
4858
  currentStep: "wallet",
4600
4859
  manageMode: false,
@@ -5500,6 +5759,7 @@ export {
5500
5759
  useModels,
5501
5760
  useMessages,
5502
5761
  useMessageQueuePosition,
5762
+ useMarkSessionViewed,
5503
5763
  useMCPServers,
5504
5764
  useMCPAuthStatus,
5505
5765
  useKeyboardShortcuts,
@@ -5537,4 +5797,4 @@ export {
5537
5797
  sessionsQueryKey
5538
5798
  };
5539
5799
 
5540
- //# debugId=8234074EBB3B7D1264756E2164756E21
5800
+ //# debugId=AFCFC55375F9489664756E2164756E21