@ottocode/web-sdk 0.1.269 → 0.1.271
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/chat/ChatInput.d.ts.map +1 -1
- package/dist/components/chat/InputQueueBar.d.ts +6 -0
- package/dist/components/chat/InputQueueBar.d.ts.map +1 -0
- package/dist/components/chat/InputTodosBar.d.ts +6 -0
- package/dist/components/chat/InputTodosBar.d.ts.map +1 -0
- package/dist/components/chat/ShortcutsModal.d.ts.map +1 -1
- package/dist/components/file-browser/FileBrowserSidebar.d.ts.map +1 -1
- package/dist/components/file-browser/FileBrowserSidebarToggle.d.ts.map +1 -1
- package/dist/components/file-browser/FileViewerPanel.d.ts +3 -0
- package/dist/components/file-browser/FileViewerPanel.d.ts.map +1 -1
- package/dist/components/file-browser/QuickFilePicker.d.ts.map +1 -1
- package/dist/components/git/GitDiffPanel.d.ts +4 -0
- package/dist/components/git/GitDiffPanel.d.ts.map +1 -1
- package/dist/components/git/GitDiffViewer.d.ts.map +1 -1
- package/dist/components/git/GitFileItem.d.ts.map +1 -1
- package/dist/components/git/GitSidebarToggle.d.ts.map +1 -1
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5092 -3747
- package/dist/components/index.js.map +61 -55
- package/dist/components/mcp/MCPSidebarToggle.d.ts.map +1 -1
- package/dist/components/messages/ActionToolBox.d.ts +2 -1
- package/dist/components/messages/ActionToolBox.d.ts.map +1 -1
- package/dist/components/messages/AssistantMessageGroup.d.ts.map +1 -1
- package/dist/components/messages/CompactActivityGroup.d.ts +2 -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/ProgressUpdateRenderer.d.ts.map +1 -1
- package/dist/components/messages/renderers/index.d.ts.map +1 -1
- package/dist/components/onboarding/OnboardingModal.d.ts.map +1 -1
- package/dist/components/onboarding/steps/ProviderSetupStep.d.ts.map +1 -1
- package/dist/components/session-files/SessionFilesDiffPanel.d.ts +7 -0
- package/dist/components/session-files/SessionFilesDiffPanel.d.ts.map +1 -1
- package/dist/components/session-files/SessionFilesSidebar.d.ts.map +1 -1
- package/dist/components/session-files/SessionFilesSidebarToggle.d.ts.map +1 -1
- package/dist/components/sessions/SessionItem.d.ts.map +1 -1
- package/dist/components/sessions/SessionListContainer.d.ts.map +1 -1
- package/dist/components/sessions/session-time.d.ts.map +1 -1
- package/dist/components/settings/SettingsSidebarToggle.d.ts.map +1 -1
- package/dist/components/sidebar/SidebarShortcutBadge.d.ts +6 -0
- package/dist/components/sidebar/SidebarShortcutBadge.d.ts.map +1 -0
- package/dist/components/skills/SkillViewerPanel.d.ts +4 -0
- package/dist/components/skills/SkillViewerPanel.d.ts.map +1 -1
- package/dist/components/skills/SkillsSidebarToggle.d.ts.map +1 -1
- package/dist/components/tunnel/TunnelSidebarToggle.d.ts.map +1 -1
- package/dist/components/ui/Modal.d.ts.map +1 -1
- package/dist/components/workspace/ViewerTabs.d.ts +2 -0
- package/dist/components/workspace/ViewerTabs.d.ts.map +1 -0
- package/dist/hooks/index.js +365 -74
- package/dist/hooks/index.js.map +17 -15
- package/dist/hooks/useClientEvents.d.ts.map +1 -1
- package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -1
- package/dist/hooks/useMessages.d.ts.map +1 -1
- package/dist/hooks/useQueueState.d.ts.map +1 -1
- package/dist/hooks/useSessions.d.ts +1 -0
- package/dist/hooks/useSessions.d.ts.map +1 -1
- package/dist/hooks/useShortcutHintsVisible.d.ts +5 -0
- package/dist/hooks/useShortcutHintsVisible.d.ts.map +1 -0
- package/dist/index.js +5287 -3843
- package/dist/index.js.map +63 -57
- package/dist/lib/api-client/index.d.ts +1 -0
- package/dist/lib/api-client/index.d.ts.map +1 -1
- package/dist/lib/api-client/sessions.d.ts +1 -0
- package/dist/lib/api-client/sessions.d.ts.map +1 -1
- package/dist/lib/api-client/utils.d.ts.map +1 -1
- package/dist/lib/index.js +11 -2
- package/dist/lib/index.js.map +5 -5
- package/dist/stores/fileBrowserStore.d.ts +1 -0
- package/dist/stores/fileBrowserStore.d.ts.map +1 -1
- package/dist/stores/gitStore.d.ts.map +1 -1
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +201 -60
- package/dist/stores/index.js.map +9 -7
- package/dist/stores/sessionFilesStore.d.ts.map +1 -1
- package/dist/stores/skillsStore.d.ts.map +1 -1
- package/dist/stores/todoStore.d.ts +18 -0
- package/dist/stores/todoStore.d.ts.map +1 -0
- package/dist/stores/viewerTabsStore.d.ts +41 -0
- package/dist/stores/viewerTabsStore.d.ts.map +1 -0
- package/dist/types/api.d.ts +7 -0
- package/dist/types/api.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/hooks/index.js
CHANGED
|
@@ -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
|
|
1196
|
+
import { create as create9 } from "zustand";
|
|
1188
1197
|
|
|
1189
1198
|
// src/stores/sessionFilesStore.ts
|
|
1190
|
-
import { create as
|
|
1199
|
+
import { create as create8 } from "zustand";
|
|
1191
1200
|
|
|
1192
1201
|
// src/stores/researchStore.ts
|
|
1193
|
-
import { create as
|
|
1202
|
+
import { create as create7 } from "zustand";
|
|
1194
1203
|
|
|
1195
1204
|
// src/stores/settingsStore.ts
|
|
1196
|
-
import { create as
|
|
1205
|
+
import { create as create6 } from "zustand";
|
|
1197
1206
|
|
|
1198
1207
|
// src/stores/tunnelStore.ts
|
|
1199
|
-
import { create as
|
|
1208
|
+
import { create as create5 } from "zustand";
|
|
1200
1209
|
|
|
1201
1210
|
// src/stores/fileBrowserStore.ts
|
|
1202
|
-
import { create as
|
|
1211
|
+
import { create as create4 } from "zustand";
|
|
1203
1212
|
|
|
1204
1213
|
// src/stores/mcpStore.ts
|
|
1205
|
-
import { create as
|
|
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
|
-
|
|
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) =>
|
|
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 =
|
|
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
|
-
|
|
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) =>
|
|
1344
|
-
|
|
1345
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
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 =
|
|
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) =>
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
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) =>
|
|
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
|
|
1960
|
-
var useToolApprovalStore =
|
|
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
|
|
2872
|
+
import { create as create11 } from "zustand";
|
|
2721
2873
|
var toastId = 0;
|
|
2722
|
-
var useToastStore =
|
|
2874
|
+
var useToastStore = create11((set) => ({
|
|
2723
2875
|
toasts: [],
|
|
2724
2876
|
addToast: (toast) => {
|
|
2725
2877
|
const id = `toast-${++toastId}`;
|
|
@@ -2899,6 +3051,56 @@ async function requestLocalhostAccess(baseUrl) {
|
|
|
2899
3051
|
throw new Error(`Local API returned ${response.status}`);
|
|
2900
3052
|
}
|
|
2901
3053
|
}
|
|
3054
|
+
var localAccessToastIds = new Map;
|
|
3055
|
+
var localAccessChecksInFlight = new Set;
|
|
3056
|
+
function localAccessStorageKey(baseUrl) {
|
|
3057
|
+
return `otto-local-access-confirmed:${baseUrl}`;
|
|
3058
|
+
}
|
|
3059
|
+
function hasConfirmedLocalAccess(baseUrl) {
|
|
3060
|
+
try {
|
|
3061
|
+
return window.localStorage.getItem(localAccessStorageKey(baseUrl)) === "1";
|
|
3062
|
+
} catch {
|
|
3063
|
+
return false;
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
function markLocalAccessConfirmed(baseUrl) {
|
|
3067
|
+
try {
|
|
3068
|
+
window.localStorage.setItem(localAccessStorageKey(baseUrl), "1");
|
|
3069
|
+
} catch {}
|
|
3070
|
+
}
|
|
3071
|
+
async function maybeShowLocalAccessToast(baseUrl) {
|
|
3072
|
+
if (hasPlatformOpenUrl())
|
|
3073
|
+
return;
|
|
3074
|
+
if (!isLocalApiUrl(baseUrl) || hasConfirmedLocalAccess(baseUrl))
|
|
3075
|
+
return;
|
|
3076
|
+
if (localAccessToastIds.has(baseUrl) || localAccessChecksInFlight.has(baseUrl)) {
|
|
3077
|
+
return;
|
|
3078
|
+
}
|
|
3079
|
+
localAccessChecksInFlight.add(baseUrl);
|
|
3080
|
+
try {
|
|
3081
|
+
await requestLocalhostAccess(baseUrl);
|
|
3082
|
+
markLocalAccessConfirmed(baseUrl);
|
|
3083
|
+
return;
|
|
3084
|
+
} catch {} finally {
|
|
3085
|
+
localAccessChecksInFlight.delete(baseUrl);
|
|
3086
|
+
}
|
|
3087
|
+
if (localAccessToastIds.has(baseUrl))
|
|
3088
|
+
return;
|
|
3089
|
+
const id = toast("Safari may need permission to access the local otto server.", "default", 0);
|
|
3090
|
+
localAccessToastIds.set(baseUrl, id);
|
|
3091
|
+
useToastStore.getState().updateToast(id, {
|
|
3092
|
+
action: {
|
|
3093
|
+
label: "Allow access",
|
|
3094
|
+
onClick: async () => {
|
|
3095
|
+
await requestLocalhostAccess(baseUrl);
|
|
3096
|
+
markLocalAccessConfirmed(baseUrl);
|
|
3097
|
+
useToastStore.getState().removeToast(id);
|
|
3098
|
+
localAccessToastIds.delete(baseUrl);
|
|
3099
|
+
toast.success("Local otto server access confirmed.");
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
});
|
|
3103
|
+
}
|
|
2902
3104
|
function useClientEvents(activeSessionId) {
|
|
2903
3105
|
const queryClient = useQueryClient6();
|
|
2904
3106
|
const activeSessionIdRef = useRef2(activeSessionId);
|
|
@@ -2934,7 +3136,6 @@ function useClientEvents(activeSessionId) {
|
|
|
2934
3136
|
}, []);
|
|
2935
3137
|
useEffect2(() => {
|
|
2936
3138
|
const controller = new AbortController;
|
|
2937
|
-
let hasShownLocalAccessToast = false;
|
|
2938
3139
|
const baseUrl = getBaseUrl();
|
|
2939
3140
|
createClientEventsStream({
|
|
2940
3141
|
baseUrl,
|
|
@@ -2974,19 +3175,7 @@ function useClientEvents(activeSessionId) {
|
|
|
2974
3175
|
onError: (error) => {
|
|
2975
3176
|
if (!controller.signal.aborted) {
|
|
2976
3177
|
console.error("[client-events] Stream error:", error);
|
|
2977
|
-
|
|
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
|
-
}
|
|
3178
|
+
maybeShowLocalAccessToast(baseUrl);
|
|
2990
3179
|
}
|
|
2991
3180
|
}
|
|
2992
3181
|
}, controller.signal);
|
|
@@ -3078,8 +3267,8 @@ function useWorkingDirectory() {
|
|
|
3078
3267
|
import { useEffect as useEffect5, useCallback as useCallback3 } from "react";
|
|
3079
3268
|
|
|
3080
3269
|
// src/stores/focusStore.ts
|
|
3081
|
-
import { create as
|
|
3082
|
-
var useFocusStore =
|
|
3270
|
+
import { create as create12 } from "zustand";
|
|
3271
|
+
var useFocusStore = create12((set) => ({
|
|
3083
3272
|
currentFocus: null,
|
|
3084
3273
|
sessionIndex: 0,
|
|
3085
3274
|
gitFileIndex: 0,
|
|
@@ -3091,9 +3280,9 @@ var useFocusStore = create11((set) => ({
|
|
|
3091
3280
|
}));
|
|
3092
3281
|
|
|
3093
3282
|
// src/stores/sidebarStore.ts
|
|
3094
|
-
import { create as
|
|
3283
|
+
import { create as create13 } from "zustand";
|
|
3095
3284
|
import { persist } from "zustand/middleware";
|
|
3096
|
-
var useSidebarStore =
|
|
3285
|
+
var useSidebarStore = create13()(persist((set) => ({
|
|
3097
3286
|
isCollapsed: false,
|
|
3098
3287
|
toggleCollapse: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
|
|
3099
3288
|
setCollapsed: (collapsed) => set({ isCollapsed: collapsed })
|
|
@@ -3102,14 +3291,47 @@ var useSidebarStore = create12()(persist((set) => ({
|
|
|
3102
3291
|
}));
|
|
3103
3292
|
|
|
3104
3293
|
// src/stores/filePickerStore.ts
|
|
3105
|
-
import { create as
|
|
3106
|
-
var useFilePickerStore =
|
|
3294
|
+
import { create as create14 } from "zustand";
|
|
3295
|
+
var useFilePickerStore = create14((set) => ({
|
|
3107
3296
|
isOpen: false,
|
|
3108
3297
|
open: () => set({ isOpen: true }),
|
|
3109
3298
|
close: () => set({ isOpen: false }),
|
|
3110
3299
|
toggle: () => set((state) => ({ isOpen: !state.isOpen }))
|
|
3111
3300
|
}));
|
|
3112
3301
|
|
|
3302
|
+
// src/stores/terminalStore.ts
|
|
3303
|
+
import { create as create15 } from "zustand";
|
|
3304
|
+
var DEFAULT_HEIGHT = 300;
|
|
3305
|
+
var MIN_HEIGHT = 150;
|
|
3306
|
+
var useTerminalStore = create15((set) => ({
|
|
3307
|
+
isOpen: false,
|
|
3308
|
+
panelHeight: DEFAULT_HEIGHT,
|
|
3309
|
+
activeTabId: null,
|
|
3310
|
+
isMaximized: false,
|
|
3311
|
+
get isExpanded() {
|
|
3312
|
+
return this.isOpen;
|
|
3313
|
+
},
|
|
3314
|
+
get selectedTerminalId() {
|
|
3315
|
+
return this.activeTabId;
|
|
3316
|
+
},
|
|
3317
|
+
openPanel: () => set({ isOpen: true }),
|
|
3318
|
+
closePanel: () => set({ isOpen: false, isMaximized: false }),
|
|
3319
|
+
togglePanel: () => set((s) => ({
|
|
3320
|
+
isOpen: !s.isOpen,
|
|
3321
|
+
isMaximized: !s.isOpen ? s.isMaximized : false
|
|
3322
|
+
})),
|
|
3323
|
+
setPanelHeight: (height) => set({ panelHeight: Math.max(MIN_HEIGHT, height) }),
|
|
3324
|
+
selectTab: (id) => set({ activeTabId: id, isOpen: true }),
|
|
3325
|
+
toggleMaximize: () => set((s) => ({ isMaximized: !s.isMaximized })),
|
|
3326
|
+
expandSidebar: () => set({ isOpen: true }),
|
|
3327
|
+
collapseSidebar: () => set({ isOpen: false, activeTabId: null, isMaximized: false }),
|
|
3328
|
+
toggleSidebar: () => set((s) => ({
|
|
3329
|
+
isOpen: !s.isOpen,
|
|
3330
|
+
isMaximized: !s.isOpen ? s.isMaximized : false
|
|
3331
|
+
})),
|
|
3332
|
+
selectTerminal: (id) => set({ activeTabId: id, isOpen: true })
|
|
3333
|
+
}));
|
|
3334
|
+
|
|
3113
3335
|
// src/hooks/useKeyboardShortcuts.ts
|
|
3114
3336
|
function useKeyboardShortcuts({
|
|
3115
3337
|
sessionIds,
|
|
@@ -3142,12 +3364,59 @@ function useKeyboardShortcuts({
|
|
|
3142
3364
|
} = useSidebarStore();
|
|
3143
3365
|
const { isExpanded: isGitExpanded, toggleSidebar: toggleGit } = useGitStore();
|
|
3144
3366
|
const closeDiff = useGitStore((state) => state.closeDiff);
|
|
3367
|
+
const toggleSessionFiles = useSessionFilesStore((state) => state.toggleSidebar);
|
|
3368
|
+
const toggleFileBrowser = useFileBrowserStore((state) => state.toggleSidebar);
|
|
3369
|
+
const toggleTunnel = useTunnelStore((state) => state.toggleSidebar);
|
|
3370
|
+
const toggleMCP = useMCPStore((state) => state.toggleSidebar);
|
|
3371
|
+
const toggleSkills = useSkillsStore((state) => state.toggleSidebar);
|
|
3372
|
+
const toggleSettings = useSettingsStore((state) => state.toggleSidebar);
|
|
3145
3373
|
const toggleResearch = useResearchStore((state) => state.toggleSidebar);
|
|
3374
|
+
const toggleTerminalPanel = useTerminalStore((state) => state.togglePanel);
|
|
3146
3375
|
const currentSessionIndex = sessionIds.indexOf(activeSessionId || "");
|
|
3147
3376
|
const handleKeyDown = useCallback3((e) => {
|
|
3148
3377
|
const target = e.target;
|
|
3149
3378
|
const isInInput = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
|
|
3150
3379
|
const isInTerminal = !!target.closest("[data-terminal-viewer]");
|
|
3380
|
+
const isShortcutModifierPressed = e.ctrlKey || e.metaKey;
|
|
3381
|
+
if (isShortcutModifierPressed && !e.shiftKey && !e.altKey && e.key >= "1" && e.key <= "7") {
|
|
3382
|
+
e.preventDefault();
|
|
3383
|
+
switch (e.key) {
|
|
3384
|
+
case "1":
|
|
3385
|
+
toggleGit();
|
|
3386
|
+
if (isGitExpanded && currentFocus === "git") {
|
|
3387
|
+
setFocus("input");
|
|
3388
|
+
} else {
|
|
3389
|
+
setFocus("git");
|
|
3390
|
+
resetGitFileIndex();
|
|
3391
|
+
}
|
|
3392
|
+
break;
|
|
3393
|
+
case "2":
|
|
3394
|
+
toggleSessionFiles();
|
|
3395
|
+
setFocus("input");
|
|
3396
|
+
break;
|
|
3397
|
+
case "3":
|
|
3398
|
+
toggleFileBrowser();
|
|
3399
|
+
setFocus("input");
|
|
3400
|
+
break;
|
|
3401
|
+
case "4":
|
|
3402
|
+
toggleTunnel();
|
|
3403
|
+
setFocus("input");
|
|
3404
|
+
break;
|
|
3405
|
+
case "5":
|
|
3406
|
+
toggleMCP();
|
|
3407
|
+
setFocus("input");
|
|
3408
|
+
break;
|
|
3409
|
+
case "6":
|
|
3410
|
+
toggleSkills();
|
|
3411
|
+
setFocus("input");
|
|
3412
|
+
break;
|
|
3413
|
+
case "7":
|
|
3414
|
+
toggleSettings();
|
|
3415
|
+
setFocus("input");
|
|
3416
|
+
break;
|
|
3417
|
+
}
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3151
3420
|
if ((e.ctrlKey || e.metaKey) && e.key === "h") {
|
|
3152
3421
|
e.preventDefault();
|
|
3153
3422
|
if (currentFocus === "sessions") {
|
|
@@ -3204,6 +3473,11 @@ function useKeyboardShortcuts({
|
|
|
3204
3473
|
toggleGit();
|
|
3205
3474
|
return;
|
|
3206
3475
|
}
|
|
3476
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "j") {
|
|
3477
|
+
e.preventDefault();
|
|
3478
|
+
toggleTerminalPanel();
|
|
3479
|
+
return;
|
|
3480
|
+
}
|
|
3207
3481
|
if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "r") {
|
|
3208
3482
|
e.preventDefault();
|
|
3209
3483
|
toggleResearch();
|
|
@@ -3327,6 +3601,13 @@ function useKeyboardShortcuts({
|
|
|
3327
3601
|
resetGitFileIndex,
|
|
3328
3602
|
setSessionListCollapsed,
|
|
3329
3603
|
toggleGit,
|
|
3604
|
+
toggleSessionFiles,
|
|
3605
|
+
toggleFileBrowser,
|
|
3606
|
+
toggleTunnel,
|
|
3607
|
+
toggleMCP,
|
|
3608
|
+
toggleSkills,
|
|
3609
|
+
toggleSettings,
|
|
3610
|
+
toggleTerminalPanel,
|
|
3330
3611
|
toggleResearch,
|
|
3331
3612
|
toggleSessionList,
|
|
3332
3613
|
onSelectSession,
|
|
@@ -3343,8 +3624,8 @@ function useKeyboardShortcuts({
|
|
|
3343
3624
|
closeDiff
|
|
3344
3625
|
]);
|
|
3345
3626
|
useEffect5(() => {
|
|
3346
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
3347
|
-
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
3627
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
3628
|
+
return () => window.removeEventListener("keydown", handleKeyDown, true);
|
|
3348
3629
|
}, [handleKeyDown]);
|
|
3349
3630
|
return {
|
|
3350
3631
|
currentFocus,
|
|
@@ -3897,9 +4178,18 @@ var defaultQueueState = {
|
|
|
3897
4178
|
function useQueueState(sessionId) {
|
|
3898
4179
|
const { data } = useQuery6({
|
|
3899
4180
|
queryKey: ["queueState", sessionId],
|
|
3900
|
-
queryFn: () =>
|
|
4181
|
+
queryFn: async () => {
|
|
4182
|
+
if (!sessionId)
|
|
4183
|
+
return defaultQueueState;
|
|
4184
|
+
const queueState = await apiClient.getQueueState(sessionId);
|
|
4185
|
+
return {
|
|
4186
|
+
currentMessageId: queueState.currentMessageId,
|
|
4187
|
+
queuedMessages: queueState.queuedMessages,
|
|
4188
|
+
queueLength: queueState.queuedMessages.length
|
|
4189
|
+
};
|
|
4190
|
+
},
|
|
3901
4191
|
enabled: !!sessionId,
|
|
3902
|
-
|
|
4192
|
+
placeholderData: defaultQueueState,
|
|
3903
4193
|
staleTime: Infinity
|
|
3904
4194
|
});
|
|
3905
4195
|
return data ?? defaultQueueState;
|
|
@@ -3971,8 +4261,8 @@ import {
|
|
|
3971
4261
|
} from "@ottocode/api";
|
|
3972
4262
|
|
|
3973
4263
|
// src/stores/pendingResearchStore.ts
|
|
3974
|
-
import { create as
|
|
3975
|
-
var usePendingResearchStore =
|
|
4264
|
+
import { create as create16 } from "zustand";
|
|
4265
|
+
var usePendingResearchStore = create16((set, get) => ({
|
|
3976
4266
|
pendingContexts: new Map,
|
|
3977
4267
|
addContext: (parentSessionId, context) => {
|
|
3978
4268
|
set((state) => {
|
|
@@ -4121,8 +4411,8 @@ function useExportToSession() {
|
|
|
4121
4411
|
import { useEffect as useEffect8, useRef as useRef3 } from "react";
|
|
4122
4412
|
|
|
4123
4413
|
// src/stores/ottorouterStore.ts
|
|
4124
|
-
import { create as
|
|
4125
|
-
var useOttoRouterStore =
|
|
4414
|
+
import { create as create17 } from "zustand";
|
|
4415
|
+
var useOttoRouterStore = create17((set) => ({
|
|
4126
4416
|
balance: null,
|
|
4127
4417
|
usdcBalance: null,
|
|
4128
4418
|
network: "mainnet",
|
|
@@ -4151,8 +4441,8 @@ var useOttoRouterStore = create15((set) => ({
|
|
|
4151
4441
|
}));
|
|
4152
4442
|
|
|
4153
4443
|
// src/stores/topupApprovalStore.ts
|
|
4154
|
-
import { create as
|
|
4155
|
-
var useTopupApprovalStore =
|
|
4444
|
+
import { create as create18 } from "zustand";
|
|
4445
|
+
var useTopupApprovalStore = create18((set) => ({
|
|
4156
4446
|
pendingTopup: null,
|
|
4157
4447
|
isProcessing: false,
|
|
4158
4448
|
selectedMethod: null,
|
|
@@ -4305,8 +4595,8 @@ function useSetuPayments(sessionId) {
|
|
|
4305
4595
|
import { useEffect as useEffect9, useCallback as useCallback6 } from "react";
|
|
4306
4596
|
|
|
4307
4597
|
// src/stores/usageStore.ts
|
|
4308
|
-
import { create as
|
|
4309
|
-
var useUsageStore =
|
|
4598
|
+
import { create as create19 } from "zustand";
|
|
4599
|
+
var useUsageStore = create19((set) => ({
|
|
4310
4600
|
usage: {},
|
|
4311
4601
|
isLoading: {},
|
|
4312
4602
|
lastFetched: {},
|
|
@@ -4555,9 +4845,9 @@ import { useEffect as useEffect12, useCallback as useCallback8, useState as useS
|
|
|
4555
4845
|
import { useQueryClient as useQueryClient9 } from "@tanstack/react-query";
|
|
4556
4846
|
|
|
4557
4847
|
// src/stores/onboardingStore.ts
|
|
4558
|
-
import { create as
|
|
4848
|
+
import { create as create20 } from "zustand";
|
|
4559
4849
|
var STEPS = ["wallet", "defaults"];
|
|
4560
|
-
var useOnboardingStore =
|
|
4850
|
+
var useOnboardingStore = create20((set, get) => ({
|
|
4561
4851
|
isOpen: false,
|
|
4562
4852
|
currentStep: "wallet",
|
|
4563
4853
|
manageMode: false,
|
|
@@ -5463,6 +5753,7 @@ export {
|
|
|
5463
5753
|
useModels,
|
|
5464
5754
|
useMessages,
|
|
5465
5755
|
useMessageQueuePosition,
|
|
5756
|
+
useMarkSessionViewed,
|
|
5466
5757
|
useMCPServers,
|
|
5467
5758
|
useMCPAuthStatus,
|
|
5468
5759
|
useKeyboardShortcuts,
|
|
@@ -5500,4 +5791,4 @@ export {
|
|
|
5500
5791
|
sessionsQueryKey
|
|
5501
5792
|
};
|
|
5502
5793
|
|
|
5503
|
-
//# debugId=
|
|
5794
|
+
//# debugId=26C8EA5B27C5271C64756E2164756E21
|