@ottocode/web-sdk 0.1.275 → 0.1.276
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/ChatInputContainer.d.ts.map +1 -1
- package/dist/components/file-browser/FileViewerPanel.d.ts +2 -1
- package/dist/components/file-browser/FileViewerPanel.d.ts.map +1 -1
- package/dist/components/index.js +884 -292
- package/dist/components/index.js.map +18 -18
- package/dist/components/messages/MessagePartItem.d.ts.map +1 -1
- package/dist/components/messages/renderers/DiffView.d.ts.map +1 -1
- package/dist/components/ui/Toaster.d.ts.map +1 -1
- package/dist/components/workspace/ToolPreviewPanel.d.ts.map +1 -1
- package/dist/components/workspace/ViewerTabs.d.ts.map +1 -1
- package/dist/hooks/index.js +301 -60
- package/dist/hooks/index.js.map +8 -8
- package/dist/hooks/useProviderUsage.d.ts +1 -1
- package/dist/hooks/useProviderUsage.d.ts.map +1 -1
- package/dist/hooks/useQueueState.d.ts +9 -0
- package/dist/hooks/useQueueState.d.ts.map +1 -1
- package/dist/hooks/useSessionStream.d.ts.map +1 -1
- package/dist/index.js +885 -292
- package/dist/index.js.map +18 -18
- package/dist/lib/api-client/index.d.ts +6 -0
- package/dist/lib/api-client/index.d.ts.map +1 -1
- package/dist/lib/api-client/sessions.d.ts +6 -0
- package/dist/lib/api-client/sessions.d.ts.map +1 -1
- package/dist/lib/commands.d.ts.map +1 -1
- package/dist/lib/index.js +17 -1
- package/dist/lib/index.js.map +4 -4
- package/dist/stores/index.js +77 -16
- package/dist/stores/index.js.map +3 -3
- package/dist/stores/viewerTabsStore.d.ts +9 -0
- package/dist/stores/viewerTabsStore.d.ts.map +1 -1
- package/dist/types/api.d.ts +1 -1
- package/dist/types/api.d.ts.map +1 -1
- package/package.json +5 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessagePartItem.d.ts","sourceRoot":"","sources":["../../../src/components/messages/MessagePartItem.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAI1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAwInD,UAAU,oBAAoB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"MessagePartItem.d.ts","sourceRoot":"","sources":["../../../src/components/messages/MessagePartItem.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAI1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAwInD,UAAU,oBAAoB;IAC7B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,4DAif3B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiffView.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/renderers/DiffView.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"DiffView.d.ts","sourceRoot":"","sources":["../../../../src/components/messages/renderers/DiffView.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;CACd;AAwKD,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,aAAa,2CAyHhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Toaster.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Toaster.tsx"],"names":[],"mappings":"AAsKA,wBAAgB,OAAO,4CAYtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolPreviewPanel.d.ts","sourceRoot":"","sources":["../../../src/components/workspace/ToolPreviewPanel.tsx"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,SAAS,EAEd,MAAM,8BAA8B,CAAC;AAGtC,UAAU,qBAAqB;IAC9B,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE;QAAE,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;CAClD;AAOD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"ToolPreviewPanel.d.ts","sourceRoot":"","sources":["../../../src/components/workspace/ToolPreviewPanel.tsx"],"names":[],"mappings":"AAGA,OAAO,EACN,KAAK,SAAS,EAEd,MAAM,8BAA8B,CAAC;AAGtC,UAAU,qBAAqB;IAC9B,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE;QAAE,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;CAClD;AAOD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAujBD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,UAAU,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CAsGzB;AAmFD,wBAAgB,gBAAgB,CAAC,EAAE,GAAG,EAAE,EAAE,qBAAqB,2CA0P9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewerTabs.d.ts","sourceRoot":"","sources":["../../../src/components/workspace/ViewerTabs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ViewerTabs.d.ts","sourceRoot":"","sources":["../../../src/components/workspace/ViewerTabs.tsx"],"names":[],"mappings":"AAyVA,eAAO,MAAM,UAAU,8CAkFrB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -159,6 +159,21 @@ var sessionsMixin = {
|
|
|
159
159
|
throw new Error(extractErrorMessage(response.error));
|
|
160
160
|
return response.data;
|
|
161
161
|
},
|
|
162
|
+
async createHandoff(sessionId) {
|
|
163
|
+
const response = await fetch(`${getBaseUrl()}/v1/sessions/${encodeURIComponent(sessionId)}/handoff`, { method: "POST" });
|
|
164
|
+
const data = await response.json().catch(() => null);
|
|
165
|
+
if (!response.ok)
|
|
166
|
+
throw new Error(extractErrorMessage(data));
|
|
167
|
+
if (!data?.session || !data?.sessionId) {
|
|
168
|
+
throw new Error("No data returned from handoff");
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
session: convertSession(data.session),
|
|
172
|
+
sessionId: String(data.sessionId),
|
|
173
|
+
sourceSessionId: String(data.sourceSessionId),
|
|
174
|
+
message: String(data.message ?? "")
|
|
175
|
+
};
|
|
176
|
+
},
|
|
162
177
|
async abortSession(sessionId) {
|
|
163
178
|
const response = await apiAbortSession({ path: { sessionId } });
|
|
164
179
|
if (response.error)
|
|
@@ -893,6 +908,7 @@ class ApiClient {
|
|
|
893
908
|
updateSession = sessionsMixin.updateSession;
|
|
894
909
|
markSessionViewed = sessionsMixin.markSessionViewed;
|
|
895
910
|
deleteSession = sessionsMixin.deleteSession;
|
|
911
|
+
createHandoff = sessionsMixin.createHandoff;
|
|
896
912
|
abortSession = sessionsMixin.abortSession;
|
|
897
913
|
abortMessage = sessionsMixin.abortMessage;
|
|
898
914
|
getQueueState = sessionsMixin.getQueueState;
|
|
@@ -1279,6 +1295,53 @@ function mergeChangedLines(existing, incoming) {
|
|
|
1279
1295
|
return existing;
|
|
1280
1296
|
return [...new Set([...existing, ...incoming])].sort((a, b) => a - b);
|
|
1281
1297
|
}
|
|
1298
|
+
function countContentLines(content) {
|
|
1299
|
+
return content.length === 0 ? 1 : content.split(`
|
|
1300
|
+
`).length;
|
|
1301
|
+
}
|
|
1302
|
+
function annotationId(preview, targetPath) {
|
|
1303
|
+
return `${preview.toolName}:${preview.callId ?? `${normalizeViewerPath(targetPath)}:${preview.patch ?? preview.content ?? ""}`}`;
|
|
1304
|
+
}
|
|
1305
|
+
function buildAnnotation(preview, targetPath, existing) {
|
|
1306
|
+
if (preview.status === "error")
|
|
1307
|
+
return existing;
|
|
1308
|
+
const id = annotationId(preview, targetPath);
|
|
1309
|
+
if (preview.toolName === "write") {
|
|
1310
|
+
const content = preview.content;
|
|
1311
|
+
if (content === undefined)
|
|
1312
|
+
return existing;
|
|
1313
|
+
return {
|
|
1314
|
+
id,
|
|
1315
|
+
reason: "write",
|
|
1316
|
+
callId: preview.callId,
|
|
1317
|
+
status: preview.status,
|
|
1318
|
+
lineTones: Array.from({ length: countContentLines(content) }, (_, index) => [index + 1, "add"]),
|
|
1319
|
+
createdAt: existing?.createdAt ?? Date.now()
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
const lineTones = preview.previewLineTones?.length ? preview.previewLineTones : preview.changedLines?.length ? preview.changedLines.map((line) => [line, "add"]) : existing?.lineTones;
|
|
1323
|
+
if (!lineTones?.length)
|
|
1324
|
+
return existing;
|
|
1325
|
+
return {
|
|
1326
|
+
id,
|
|
1327
|
+
reason: "apply_patch",
|
|
1328
|
+
callId: preview.callId,
|
|
1329
|
+
status: preview.status,
|
|
1330
|
+
lineTones,
|
|
1331
|
+
createdAt: existing?.createdAt ?? Date.now()
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
function upsertAnnotation(annotations, annotation) {
|
|
1335
|
+
if (!annotation)
|
|
1336
|
+
return annotations;
|
|
1337
|
+
const existing = annotations ?? [];
|
|
1338
|
+
const index = existing.findIndex((item) => item.id === annotation.id);
|
|
1339
|
+
if (index === -1)
|
|
1340
|
+
return [...existing, annotation];
|
|
1341
|
+
const next = [...existing];
|
|
1342
|
+
next[index] = annotation;
|
|
1343
|
+
return next;
|
|
1344
|
+
}
|
|
1282
1345
|
var useViewerTabsStore = create((set) => ({
|
|
1283
1346
|
tabs: [],
|
|
1284
1347
|
activeTabId: null,
|
|
@@ -1325,7 +1388,11 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1325
1388
|
id: targetId,
|
|
1326
1389
|
type: "file",
|
|
1327
1390
|
title: existingFile?.title ?? titleFromPath(targetPath),
|
|
1328
|
-
path: targetPath
|
|
1391
|
+
path: targetPath,
|
|
1392
|
+
highlight: existingFile?.highlight,
|
|
1393
|
+
annotations: existingFile?.annotations,
|
|
1394
|
+
patchPreview: existingFile?.patchPreview,
|
|
1395
|
+
writePreview: existingFile?.writePreview
|
|
1329
1396
|
}),
|
|
1330
1397
|
activeTabId: targetId
|
|
1331
1398
|
};
|
|
@@ -1346,6 +1413,7 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1346
1413
|
title: existingFile?.title ?? titleFromPath(targetPath),
|
|
1347
1414
|
path: targetPath,
|
|
1348
1415
|
highlight,
|
|
1416
|
+
annotations: existingFile?.annotations,
|
|
1349
1417
|
patchPreview: undefined,
|
|
1350
1418
|
writePreview: undefined
|
|
1351
1419
|
}),
|
|
@@ -1367,6 +1435,12 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1367
1435
|
const samePatchCall = isSamePatchCall(existingPatchPreview, preview);
|
|
1368
1436
|
const baseContent = preview.baseContent ?? (samePatchCall ? existingPatchPreview?.baseContent : existingPatchPreview?.resultContent ?? existingPatchPreview?.baseContent);
|
|
1369
1437
|
const changedLines = samePatchCall ? preview.changedLines ?? existingPatchPreview?.changedLines : mergeChangedLines(existingPatchPreview?.changedLines, preview.changedLines);
|
|
1438
|
+
const annotationPreview = {
|
|
1439
|
+
...preview,
|
|
1440
|
+
changedLines: preview.changedLines
|
|
1441
|
+
};
|
|
1442
|
+
const existingAnnotation = existingFile?.annotations?.find((annotation2) => annotation2.id === annotationId(annotationPreview, targetPath));
|
|
1443
|
+
const annotations = upsertAnnotation(existingFile?.annotations, buildAnnotation(annotationPreview, targetPath, existingAnnotation));
|
|
1370
1444
|
return {
|
|
1371
1445
|
tabs: upsertTab(tabs, {
|
|
1372
1446
|
id: targetId,
|
|
@@ -1374,6 +1448,7 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1374
1448
|
title: existingFile?.title ?? titleFromPath(targetPath),
|
|
1375
1449
|
path: targetPath,
|
|
1376
1450
|
highlight: undefined,
|
|
1451
|
+
annotations,
|
|
1377
1452
|
writePreview: undefined,
|
|
1378
1453
|
patchPreview: {
|
|
1379
1454
|
path: targetPath,
|
|
@@ -1396,10 +1471,13 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1396
1471
|
}
|
|
1397
1472
|
if (existingFile) {
|
|
1398
1473
|
const existingWritePreview = existingFile.writePreview;
|
|
1474
|
+
const existingAnnotation = existingFile.annotations?.find((annotation2) => annotation2.id === annotationId(preview, targetPath));
|
|
1475
|
+
const annotations = upsertAnnotation(existingFile.annotations, buildAnnotation(preview, targetPath, existingAnnotation));
|
|
1399
1476
|
return {
|
|
1400
1477
|
tabs: upsertTab(tabs, {
|
|
1401
1478
|
...existingFile,
|
|
1402
1479
|
highlight: undefined,
|
|
1480
|
+
annotations,
|
|
1403
1481
|
patchPreview: undefined,
|
|
1404
1482
|
writePreview: {
|
|
1405
1483
|
path: targetPath,
|
|
@@ -1414,25 +1492,24 @@ var useViewerTabsStore = create((set) => ({
|
|
|
1414
1492
|
};
|
|
1415
1493
|
}
|
|
1416
1494
|
const existingWrite = existing?.toolName === "write" ? existing : undefined;
|
|
1495
|
+
const annotation = buildAnnotation(preview, preview.path);
|
|
1417
1496
|
return {
|
|
1418
1497
|
tabs: upsertTab(tabs, {
|
|
1419
1498
|
id,
|
|
1420
|
-
type: "
|
|
1499
|
+
type: "file",
|
|
1421
1500
|
title: titleFromPath(preview.path),
|
|
1422
1501
|
path: preview.path,
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
status: preview.status,
|
|
1435
|
-
error: preview.error ?? existingWrite?.error
|
|
1502
|
+
highlight: undefined,
|
|
1503
|
+
annotations: annotation ? [annotation] : undefined,
|
|
1504
|
+
patchPreview: undefined,
|
|
1505
|
+
writePreview: {
|
|
1506
|
+
path: preview.path,
|
|
1507
|
+
toolName: "write",
|
|
1508
|
+
callId: preview.callId,
|
|
1509
|
+
content: preview.content ?? existingWrite?.content,
|
|
1510
|
+
status: preview.status,
|
|
1511
|
+
error: preview.error ?? existingWrite?.error
|
|
1512
|
+
}
|
|
1436
1513
|
}),
|
|
1437
1514
|
activeTabId: id
|
|
1438
1515
|
};
|
|
@@ -2035,14 +2112,26 @@ import { useQuery as useQuery4 } from "@tanstack/react-query";
|
|
|
2035
2112
|
var defaultQueueState = {
|
|
2036
2113
|
currentMessageId: null,
|
|
2037
2114
|
queuedMessages: [],
|
|
2038
|
-
queueLength: 0
|
|
2115
|
+
queueLength: 0,
|
|
2116
|
+
isRunning: false
|
|
2039
2117
|
};
|
|
2118
|
+
function normalizeQueueState(state) {
|
|
2119
|
+
const isRunning = state.isRunning ?? Boolean(state.currentMessageId);
|
|
2120
|
+
const currentMessageId = isRunning ? state.currentMessageId : null;
|
|
2121
|
+
const hasActiveTurn = Boolean(currentMessageId);
|
|
2122
|
+
const queuedMessages = hasActiveTurn ? state.queuedMessages : [];
|
|
2123
|
+
return {
|
|
2124
|
+
currentMessageId,
|
|
2125
|
+
queuedMessages,
|
|
2126
|
+
queueLength: queuedMessages.length,
|
|
2127
|
+
isRunning: hasActiveTurn
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2040
2130
|
function optimisticallyQueueMessage(queryClient, sessionId, messageId) {
|
|
2041
2131
|
queryClient.setQueryData(["queueState", sessionId], (current) => {
|
|
2042
2132
|
if (!current)
|
|
2043
2133
|
return current;
|
|
2044
|
-
|
|
2045
|
-
if (!isBusy)
|
|
2134
|
+
if (!current.isRunning || !current.currentMessageId)
|
|
2046
2135
|
return current;
|
|
2047
2136
|
if (current.currentMessageId === messageId)
|
|
2048
2137
|
return current;
|
|
@@ -2067,11 +2156,7 @@ function useQueueState(sessionId) {
|
|
|
2067
2156
|
if (!sessionId)
|
|
2068
2157
|
return defaultQueueState;
|
|
2069
2158
|
const queueState = await apiClient.getQueueState(sessionId);
|
|
2070
|
-
return
|
|
2071
|
-
currentMessageId: queueState.currentMessageId,
|
|
2072
|
-
queuedMessages: queueState.queuedMessages,
|
|
2073
|
-
queueLength: queueState.queuedMessages.length
|
|
2074
|
-
};
|
|
2159
|
+
return normalizeQueueState(queueState);
|
|
2075
2160
|
},
|
|
2076
2161
|
enabled: !!sessionId,
|
|
2077
2162
|
placeholderData: defaultQueueState,
|
|
@@ -2654,22 +2739,30 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2654
2739
|
return;
|
|
2655
2740
|
let changeLines = 0;
|
|
2656
2741
|
let stableChangeLength = 0;
|
|
2742
|
+
let lineDirectiveCount = 0;
|
|
2657
2743
|
for (const line of stablePatch.split(`
|
|
2658
2744
|
`)) {
|
|
2659
2745
|
if (line.startsWith("+") && !line.startsWith("+++") || line.startsWith("-") && !line.startsWith("---")) {
|
|
2660
2746
|
changeLines += 1;
|
|
2661
2747
|
stableChangeLength += line.length;
|
|
2748
|
+
} else if (/^\*\*\* (?:Delete Lines in|Replace Lines in|Insert Before in|Insert After in): /.test(line) || line.startsWith("*** Lines:") || line.startsWith("*** Line:") || line.startsWith("*** With:")) {
|
|
2749
|
+
lineDirectiveCount += 1;
|
|
2662
2750
|
}
|
|
2663
2751
|
}
|
|
2664
|
-
|
|
2752
|
+
if (changeLines > 0)
|
|
2753
|
+
return `${changeLines}:${stableChangeLength}`;
|
|
2754
|
+
return lineDirectiveCount > 0 ? `lines:${lineDirectiveCount}:${stablePatch.length}` : undefined;
|
|
2665
2755
|
};
|
|
2666
2756
|
const extractPathsFromPatch = (patch) => {
|
|
2667
2757
|
const paths = new Set;
|
|
2668
2758
|
for (const line of patch.split(`
|
|
2669
2759
|
`)) {
|
|
2670
2760
|
const directive = line.match(/^\*\*\* (?:Update|Add|Delete) File: (.+)$/);
|
|
2671
|
-
|
|
2672
|
-
|
|
2761
|
+
const replaceDirective = line.match(/^\*\*\* Replace in: (.+)$/);
|
|
2762
|
+
const lineDirective = line.match(/^\*\*\* (?:Delete Lines in|Replace Lines in|Insert Before in|Insert After in): (.+)$/);
|
|
2763
|
+
const path = directive?.[1] ?? replaceDirective?.[1] ?? lineDirective?.[1];
|
|
2764
|
+
if (path) {
|
|
2765
|
+
paths.add(path.trim());
|
|
2673
2766
|
continue;
|
|
2674
2767
|
}
|
|
2675
2768
|
const unified = line.match(/^\+\+\+ (?:b\/)?(.+)$/);
|
|
@@ -2679,6 +2772,47 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2679
2772
|
}
|
|
2680
2773
|
return [...paths];
|
|
2681
2774
|
};
|
|
2775
|
+
const getExtension = (path) => path.split(".").pop()?.toLowerCase() ?? "";
|
|
2776
|
+
const updateFileContentCache = (path, content) => {
|
|
2777
|
+
queryClient.setQueryData(["files", "read", path], {
|
|
2778
|
+
content,
|
|
2779
|
+
path,
|
|
2780
|
+
extension: getExtension(path),
|
|
2781
|
+
lineCount: content.split(`
|
|
2782
|
+
`).length
|
|
2783
|
+
});
|
|
2784
|
+
};
|
|
2785
|
+
const mergeReadResultIntoFileCache = (path, result, startLine, endLine) => {
|
|
2786
|
+
if (typeof result?.content !== "string")
|
|
2787
|
+
return;
|
|
2788
|
+
const readContent = result.content;
|
|
2789
|
+
if (!startLine || !endLine) {
|
|
2790
|
+
updateFileContentCache(path, readContent);
|
|
2791
|
+
return;
|
|
2792
|
+
}
|
|
2793
|
+
queryClient.setQueryData(["files", "read", path], (current) => {
|
|
2794
|
+
if (!current?.content)
|
|
2795
|
+
return current;
|
|
2796
|
+
const lines = current.content.split(`
|
|
2797
|
+
`);
|
|
2798
|
+
if (lines.at(-1) === "")
|
|
2799
|
+
lines.pop();
|
|
2800
|
+
const readLines = readContent.split(`
|
|
2801
|
+
`);
|
|
2802
|
+
lines.splice(startLine - 1, endLine - startLine + 1, ...readLines);
|
|
2803
|
+
const content = `${lines.join(`
|
|
2804
|
+
`)}
|
|
2805
|
+
`;
|
|
2806
|
+
return {
|
|
2807
|
+
...current,
|
|
2808
|
+
content,
|
|
2809
|
+
lineCount: typeof result.totalLines === "number" ? result.totalLines : lines.length
|
|
2810
|
+
};
|
|
2811
|
+
});
|
|
2812
|
+
};
|
|
2813
|
+
const invalidateFileContentCache = (path) => {
|
|
2814
|
+
queryClient.invalidateQueries({ queryKey: ["files", "read", path] });
|
|
2815
|
+
};
|
|
2682
2816
|
const getChangedLinesForPath = (result, path) => {
|
|
2683
2817
|
const changes = Array.isArray(result?.changes) ? result.changes : [];
|
|
2684
2818
|
const lines = new Set;
|
|
@@ -2708,9 +2842,6 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2708
2842
|
return lines.size > 0 ? [...lines] : undefined;
|
|
2709
2843
|
};
|
|
2710
2844
|
const handleReadToolActivity = (eventType, payload, delta) => {
|
|
2711
|
-
const viewerStore = useViewerTabsStore.getState();
|
|
2712
|
-
if (!viewerStore.followToolActivity)
|
|
2713
|
-
return;
|
|
2714
2845
|
const name = getToolEventName(payload);
|
|
2715
2846
|
if (name !== "read")
|
|
2716
2847
|
return;
|
|
@@ -2723,6 +2854,12 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2723
2854
|
const startLine = normalizeLineNumber(args.startLine) ?? normalizeLineNumber(args.start_line) ?? rangeFromResult.startLine;
|
|
2724
2855
|
const endLine = normalizeLineNumber(args.endLine) ?? normalizeLineNumber(args.end_line) ?? rangeFromResult.endLine ?? startLine;
|
|
2725
2856
|
const failed = result?.ok === false || eventType === "error";
|
|
2857
|
+
if (eventType === "tool.result" && !failed) {
|
|
2858
|
+
mergeReadResultIntoFileCache(path, result, startLine, endLine);
|
|
2859
|
+
}
|
|
2860
|
+
const viewerStore = useViewerTabsStore.getState();
|
|
2861
|
+
if (!viewerStore.followToolActivity)
|
|
2862
|
+
return;
|
|
2726
2863
|
viewerStore.openToolReadTab(path, {
|
|
2727
2864
|
startLine,
|
|
2728
2865
|
endLine,
|
|
@@ -2732,9 +2869,6 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2732
2869
|
});
|
|
2733
2870
|
};
|
|
2734
2871
|
const handleWriteToolActivity = (eventType, payload, delta) => {
|
|
2735
|
-
const viewerStore = useViewerTabsStore.getState();
|
|
2736
|
-
if (!viewerStore.followToolActivity)
|
|
2737
|
-
return;
|
|
2738
2872
|
const name = getToolEventName(payload);
|
|
2739
2873
|
if (name !== "write")
|
|
2740
2874
|
return;
|
|
@@ -2748,6 +2882,15 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2748
2882
|
const callId = getToolEventCallId(payload) ?? undefined;
|
|
2749
2883
|
const status = failed ? "error" : eventType === "tool.result" ? "success" : "streaming";
|
|
2750
2884
|
const content = status === "streaming" ? getStreamingWritePreviewContent(args, buffer) : getStringArg(args, buffer, "content");
|
|
2885
|
+
if (status === "success") {
|
|
2886
|
+
if (content !== undefined)
|
|
2887
|
+
updateFileContentCache(path, content);
|
|
2888
|
+
else
|
|
2889
|
+
invalidateFileContentCache(path);
|
|
2890
|
+
}
|
|
2891
|
+
const viewerStore = useViewerTabsStore.getState();
|
|
2892
|
+
if (!viewerStore.followToolActivity)
|
|
2893
|
+
return;
|
|
2751
2894
|
if (status === "streaming" && content !== undefined && content.length >= TOOL_PREVIEW_THROTTLE_MIN_CHARS) {
|
|
2752
2895
|
const previewKey = callId ?? path;
|
|
2753
2896
|
const now = Date.now();
|
|
@@ -2771,9 +2914,6 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2771
2914
|
});
|
|
2772
2915
|
};
|
|
2773
2916
|
const handleApplyPatchToolActivity = (eventType, payload, delta) => {
|
|
2774
|
-
const viewerStore = useViewerTabsStore.getState();
|
|
2775
|
-
if (!viewerStore.followToolActivity)
|
|
2776
|
-
return;
|
|
2777
2917
|
const name = getToolEventName(payload);
|
|
2778
2918
|
if (name !== "apply_patch")
|
|
2779
2919
|
return;
|
|
@@ -2797,6 +2937,13 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2797
2937
|
const patchPaths = extractPathsFromPatch(patch);
|
|
2798
2938
|
if (patchPaths.length === 0)
|
|
2799
2939
|
return;
|
|
2940
|
+
if (status === "success") {
|
|
2941
|
+
for (const path of patchPaths)
|
|
2942
|
+
invalidateFileContentCache(path);
|
|
2943
|
+
}
|
|
2944
|
+
const viewerStore = useViewerTabsStore.getState();
|
|
2945
|
+
if (!viewerStore.followToolActivity)
|
|
2946
|
+
return;
|
|
2800
2947
|
const matchingFileTabs = viewerStore.tabs.filter((tab) => tab.type === "file" && patchPaths.some((path) => patchPathMayReferToTarget(path, tab.path)));
|
|
2801
2948
|
const activeMatchingFileTab = matchingFileTabs.find((tab) => tab.id === viewerStore.activeTabId);
|
|
2802
2949
|
const fallbackPath = patchPaths.find(isLikelyCompletePatchPath);
|
|
@@ -2902,6 +3049,11 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2902
3049
|
const applyMessageDelta = (payload) => {
|
|
2903
3050
|
const messageId = typeof payload?.messageId === "string" ? payload.messageId : null;
|
|
2904
3051
|
const partId = typeof payload?.partId === "string" ? payload.partId : null;
|
|
3052
|
+
const payloadType = typeof payload?.type === "string" ? payload.type : undefined;
|
|
3053
|
+
if (payloadType === "error") {
|
|
3054
|
+
upsertErrorPart(payload);
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
2905
3057
|
const delta = typeof payload?.delta === "string" ? payload.delta : null;
|
|
2906
3058
|
if (!messageId || !partId || delta === null)
|
|
2907
3059
|
return;
|
|
@@ -2952,6 +3104,90 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
2952
3104
|
return nextMessages;
|
|
2953
3105
|
});
|
|
2954
3106
|
};
|
|
3107
|
+
const toRecord = (value) => {
|
|
3108
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
3109
|
+
return value;
|
|
3110
|
+
}
|
|
3111
|
+
return null;
|
|
3112
|
+
};
|
|
3113
|
+
const parseErrorContent = (payload) => {
|
|
3114
|
+
const contentRecord = toRecord(payload.content);
|
|
3115
|
+
if (contentRecord)
|
|
3116
|
+
return contentRecord;
|
|
3117
|
+
if (typeof payload.content === "string") {
|
|
3118
|
+
try {
|
|
3119
|
+
const parsed = JSON.parse(payload.content);
|
|
3120
|
+
const parsedRecord = toRecord(parsed);
|
|
3121
|
+
if (parsedRecord)
|
|
3122
|
+
return parsedRecord;
|
|
3123
|
+
} catch {}
|
|
3124
|
+
}
|
|
3125
|
+
const message = typeof payload.error === "string" ? payload.error : typeof payload.message === "string" ? payload.message : "Assistant run failed";
|
|
3126
|
+
return {
|
|
3127
|
+
message,
|
|
3128
|
+
type: typeof payload.errorType === "string" ? payload.errorType : "error",
|
|
3129
|
+
details: toRecord(payload.details) ?? undefined,
|
|
3130
|
+
isAborted: payload.isAborted === true,
|
|
3131
|
+
autoCompacted: payload.autoCompacted === true
|
|
3132
|
+
};
|
|
3133
|
+
};
|
|
3134
|
+
const upsertErrorPart = (payload) => {
|
|
3135
|
+
const messageId = typeof payload?.messageId === "string" ? payload.messageId : null;
|
|
3136
|
+
if (!payload || !messageId)
|
|
3137
|
+
return;
|
|
3138
|
+
const contentJson = parseErrorContent(payload);
|
|
3139
|
+
const content = JSON.stringify(contentJson);
|
|
3140
|
+
const errorMessage = typeof contentJson.message === "string" ? contentJson.message : typeof payload.error === "string" ? payload.error : "Assistant run failed";
|
|
3141
|
+
const stepIndex = typeof payload.stepIndex === "number" ? payload.stepIndex : null;
|
|
3142
|
+
const partId = typeof payload.partId === "string" ? payload.partId : `error-${messageId}`;
|
|
3143
|
+
queryClient.setQueryData(["messages", sessionId], (oldMessages) => {
|
|
3144
|
+
if (!oldMessages)
|
|
3145
|
+
return oldMessages;
|
|
3146
|
+
const nextMessages = [...oldMessages];
|
|
3147
|
+
const messageIndex = nextMessages.findIndex((message) => message.id === messageId);
|
|
3148
|
+
if (messageIndex === -1)
|
|
3149
|
+
return oldMessages;
|
|
3150
|
+
const targetMessage = nextMessages[messageIndex];
|
|
3151
|
+
const parts = targetMessage.parts ? [...targetMessage.parts] : [];
|
|
3152
|
+
const partIndex = parts.findIndex((part) => part.id === partId);
|
|
3153
|
+
if (partIndex === -1) {
|
|
3154
|
+
const newPart = {
|
|
3155
|
+
id: partId,
|
|
3156
|
+
messageId,
|
|
3157
|
+
index: getOptimisticPartIndex(parts, stepIndex),
|
|
3158
|
+
stepIndex,
|
|
3159
|
+
type: "error",
|
|
3160
|
+
content,
|
|
3161
|
+
contentJson,
|
|
3162
|
+
agent: targetMessage.agent,
|
|
3163
|
+
provider: targetMessage.provider,
|
|
3164
|
+
model: targetMessage.model,
|
|
3165
|
+
startedAt: Date.now(),
|
|
3166
|
+
completedAt: Date.now(),
|
|
3167
|
+
toolName: null,
|
|
3168
|
+
toolCallId: null,
|
|
3169
|
+
toolDurationMs: null
|
|
3170
|
+
};
|
|
3171
|
+
parts.push(newPart);
|
|
3172
|
+
} else {
|
|
3173
|
+
parts[partIndex] = {
|
|
3174
|
+
...parts[partIndex],
|
|
3175
|
+
content,
|
|
3176
|
+
contentJson,
|
|
3177
|
+
stepIndex: stepIndex ?? parts[partIndex].stepIndex ?? null,
|
|
3178
|
+
completedAt: Date.now()
|
|
3179
|
+
};
|
|
3180
|
+
}
|
|
3181
|
+
nextMessages[messageIndex] = {
|
|
3182
|
+
...targetMessage,
|
|
3183
|
+
status: "error",
|
|
3184
|
+
completedAt: targetMessage.completedAt ?? Date.now(),
|
|
3185
|
+
error: errorMessage,
|
|
3186
|
+
parts
|
|
3187
|
+
};
|
|
3188
|
+
return nextMessages;
|
|
3189
|
+
});
|
|
3190
|
+
};
|
|
2955
3191
|
const upsertEphemeralToolCall = (payload) => {
|
|
2956
3192
|
if (!payload)
|
|
2957
3193
|
return;
|
|
@@ -3381,6 +3617,17 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
3381
3617
|
}
|
|
3382
3618
|
markMessageCompleted(payload);
|
|
3383
3619
|
clearEphemeralForMessage(id);
|
|
3620
|
+
if (id) {
|
|
3621
|
+
queryClient.setQueryData(["queueState", sessionId], (current) => {
|
|
3622
|
+
if (!current || current.currentMessageId !== id)
|
|
3623
|
+
return current;
|
|
3624
|
+
return normalizeQueueState({
|
|
3625
|
+
currentMessageId: null,
|
|
3626
|
+
queuedMessages: [],
|
|
3627
|
+
isRunning: false
|
|
3628
|
+
});
|
|
3629
|
+
});
|
|
3630
|
+
}
|
|
3384
3631
|
queryClient.invalidateQueries({ queryKey: ["messages", sessionId] });
|
|
3385
3632
|
queryClient.invalidateQueries({ queryKey: sessionsQueryKey });
|
|
3386
3633
|
break;
|
|
@@ -3454,22 +3701,7 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
3454
3701
|
assistantMessageIdRef.current = null;
|
|
3455
3702
|
}
|
|
3456
3703
|
clearEphemeralForMessage(messageId);
|
|
3457
|
-
|
|
3458
|
-
queryClient.setQueryData(["messages", sessionId], (oldMessages) => {
|
|
3459
|
-
if (!oldMessages)
|
|
3460
|
-
return oldMessages;
|
|
3461
|
-
const idx = oldMessages.findIndex((m) => m.id === messageId);
|
|
3462
|
-
if (idx === -1)
|
|
3463
|
-
return oldMessages;
|
|
3464
|
-
const next = [...oldMessages];
|
|
3465
|
-
next[idx] = {
|
|
3466
|
-
...next[idx],
|
|
3467
|
-
status: "error",
|
|
3468
|
-
completedAt: next[idx].completedAt ?? Date.now(),
|
|
3469
|
-
error: errorMessage
|
|
3470
|
-
};
|
|
3471
|
-
return next;
|
|
3472
|
-
});
|
|
3704
|
+
upsertErrorPart(payload);
|
|
3473
3705
|
}
|
|
3474
3706
|
queryClient.invalidateQueries({ queryKey: ["messages", sessionId] });
|
|
3475
3707
|
break;
|
|
@@ -3504,11 +3736,11 @@ ${bestEffortUnescapeJsonString(rawTail)}`;
|
|
|
3504
3736
|
break;
|
|
3505
3737
|
}
|
|
3506
3738
|
case "queue.updated": {
|
|
3507
|
-
const queueState = {
|
|
3739
|
+
const queueState = normalizeQueueState({
|
|
3508
3740
|
currentMessageId: payload?.currentMessageId,
|
|
3509
3741
|
queuedMessages: payload?.queuedMessages ?? [],
|
|
3510
|
-
|
|
3511
|
-
};
|
|
3742
|
+
isRunning: typeof payload?.isRunning === "boolean" ? payload.isRunning : undefined
|
|
3743
|
+
});
|
|
3512
3744
|
queryClient.setQueryData(["queueState", sessionId], queueState);
|
|
3513
3745
|
break;
|
|
3514
3746
|
}
|
|
@@ -5986,21 +6218,23 @@ function useTunnelStream() {
|
|
|
5986
6218
|
// src/hooks/useProviderUsage.ts
|
|
5987
6219
|
import { useEffect as useEffect14, useCallback as useCallback10, useRef as useRef7 } from "react";
|
|
5988
6220
|
var POLL_INTERVAL = 60000;
|
|
5989
|
-
var STALE_THRESHOLD =
|
|
6221
|
+
var STALE_THRESHOLD = 60000;
|
|
5990
6222
|
var inflight = new Set;
|
|
5991
6223
|
function useProviderUsage(provider, authType) {
|
|
5992
6224
|
const setUsage = useUsageStore((s) => s.setUsage);
|
|
5993
6225
|
const setLoading = useUsageStore((s) => s.setLoading);
|
|
5994
6226
|
const setLastFetched = useUsageStore((s) => s.setLastFetched);
|
|
6227
|
+
const isModalOpen = useUsageStore((s) => s.isModalOpen);
|
|
6228
|
+
const modalProvider = useUsageStore((s) => s.modalProvider);
|
|
5995
6229
|
const usage = useUsageStore((s) => provider ? s.usage[provider] : undefined);
|
|
5996
6230
|
const isOAuthProvider = authType === "oauth" && (provider === "anthropic" || provider === "openai");
|
|
5997
|
-
const fetchUsage = useCallback10(async () => {
|
|
6231
|
+
const fetchUsage = useCallback10(async (force = false) => {
|
|
5998
6232
|
if (!provider || !isOAuthProvider)
|
|
5999
6233
|
return;
|
|
6000
6234
|
if (inflight.has(provider))
|
|
6001
6235
|
return;
|
|
6002
6236
|
const last = useUsageStore.getState().lastFetched[provider] ?? 0;
|
|
6003
|
-
if (last && Date.now() - last < STALE_THRESHOLD)
|
|
6237
|
+
if (!force && last && Date.now() - last < STALE_THRESHOLD)
|
|
6004
6238
|
return;
|
|
6005
6239
|
inflight.add(provider);
|
|
6006
6240
|
setLoading(provider, true);
|
|
@@ -6019,9 +6253,15 @@ function useProviderUsage(provider, authType) {
|
|
|
6019
6253
|
if (!provider || !isOAuthProvider)
|
|
6020
6254
|
return;
|
|
6021
6255
|
fetchRef.current();
|
|
6256
|
+
}, [isOAuthProvider, provider]);
|
|
6257
|
+
useEffect14(() => {
|
|
6258
|
+
if (!provider || !isOAuthProvider || !isModalOpen || modalProvider !== provider) {
|
|
6259
|
+
return;
|
|
6260
|
+
}
|
|
6261
|
+
fetchRef.current(true);
|
|
6022
6262
|
const interval = setInterval(() => fetchRef.current(), POLL_INTERVAL);
|
|
6023
6263
|
return () => clearInterval(interval);
|
|
6024
|
-
}, [isOAuthProvider, provider]);
|
|
6264
|
+
}, [isModalOpen, isOAuthProvider, modalProvider, provider]);
|
|
6025
6265
|
return {
|
|
6026
6266
|
usage,
|
|
6027
6267
|
fetchUsage,
|
|
@@ -6436,7 +6676,8 @@ export {
|
|
|
6436
6676
|
useAddRemote,
|
|
6437
6677
|
useAddMCPServer,
|
|
6438
6678
|
sessionsQueryKey,
|
|
6439
|
-
optimisticallyQueueMessage
|
|
6679
|
+
optimisticallyQueueMessage,
|
|
6680
|
+
normalizeQueueState
|
|
6440
6681
|
};
|
|
6441
6682
|
|
|
6442
|
-
//# debugId=
|
|
6683
|
+
//# debugId=289696F18C6536EA64756E2164756E21
|