@tonyclaw/agent-inspector 3.0.6 → 3.0.8
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/.output/cli.js +245 -171
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-DsvO6QyJ.js → CompareDrawer-Bth_Ywyt.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-C73EU9Jq.js +106 -0
- package/.output/public/assets/ReplayDialog-C2YYAuTe.js +1 -0
- package/.output/public/assets/{RequestAnatomy-m1q-uVTl.js → RequestAnatomy-8k9dAX2j.js} +1 -1
- package/.output/public/assets/ResponseView-DEL6JcXm.js +3 -0
- package/.output/public/assets/StreamingChunkSequence-DngmoR9j.js +1 -0
- package/.output/public/assets/{_sessionId-CWP4pxOU.js → _sessionId-4vk9RMZ5.js} +1 -1
- package/.output/public/assets/index-DBEB1rHe.css +1 -0
- package/.output/public/assets/{index-zfZUz67K.js → index-DINLvnm9.js} +1 -1
- package/.output/public/assets/index-LPIGiUMP.js +1 -0
- package/.output/public/assets/{json-viewer-_4r1LBBE.js → json-viewer-CH5dvS2Y.js} +1 -1
- package/.output/public/assets/{main-C_nEHNUM.js → main-GWkZn4xy.js} +2 -2
- package/.output/server/{_sessionId-CTqCAmUF.mjs → _sessionId-EgsjdkN7.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-D6b6TZ-O.mjs → CompareDrawer-CaM8FYuD.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-Dp7Va9_T.mjs → ProxyViewerContainer-EJIogcGd.mjs} +580 -344
- package/.output/server/_ssr/{ReplayDialog-D_KWQ1GY.mjs → ReplayDialog-BPpJ2-q8.mjs} +58 -23
- package/.output/server/_ssr/{RequestAnatomy-CPubXjMX.mjs → RequestAnatomy-DeQAWnZx.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-CsTiNoOE.mjs → ResponseView-Dshm8iQ7.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-Bgbzt23U.mjs → StreamingChunkSequence-32yIU2hn.mjs} +30 -20
- package/.output/server/_ssr/{index-P1gSpuM5.mjs → index-XRcx9blU.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{json-viewer-10ciVGnc.mjs → json-viewer-C0aX5rqC.mjs} +2 -2
- package/.output/server/_ssr/{router-BJJ0VhsB.mjs → router-BI-Mvxz9.mjs} +441 -172
- package/.output/server/_tanstack-start-manifest_v-jKScklL_.mjs +4 -0
- package/.output/server/index.mjs +73 -73
- package/package.json +1 -1
- package/src/assets/IDE/opencode.svg +1 -1
- package/src/assets/IDE/xiaomimimo.svg +1 -1
- package/src/cli/detect-tools.ts +2 -27
- package/src/cli/templates/codex-skill-onboard.ts +1 -1
- package/src/cli/templates/skill-onboard.ts +2 -3
- package/src/cli.ts +9 -86
- package/src/components/ProxyViewer.tsx +68 -21
- package/src/components/ProxyViewerContainer.tsx +30 -19
- package/src/components/alerts/AlertsDialog.tsx +3 -3
- package/src/components/clients/ClientLogo.tsx +22 -2
- package/src/components/ecosystem/AgentLabDialog.tsx +215 -12
- package/src/components/groups/GroupsDialog.tsx +31 -43
- package/src/components/providers/ImportWizardDialog.tsx +52 -102
- package/src/components/providers/ProviderCard.tsx +4 -4
- package/src/components/providers/ProvidersPanel.tsx +82 -68
- package/src/components/providers/SettingsDialog.tsx +11 -12
- package/src/components/proxy-viewer/AgentTraceSummary.tsx +15 -23
- package/src/components/proxy-viewer/CompareDrawer.tsx +1 -1
- package/src/components/proxy-viewer/ConversationHeader.tsx +2 -2
- package/src/components/proxy-viewer/ReplayDialog.tsx +65 -22
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +33 -20
- package/src/lib/apiClient.ts +43 -10
- package/src/lib/ecosystemContract.ts +32 -0
- package/src/lib/export-logs.ts +37 -3
- package/src/proxy/ecosystemRegistry.ts +244 -0
- package/src/proxy/ecosystemTasks.ts +153 -0
- package/src/proxy/platformCommands.ts +212 -0
- package/src/proxy/socketTracker.ts +84 -143
- package/src/routes/api/ecosystem.packages.$packageId.help.ts +16 -0
- package/src/routes/api/ecosystem.packages.$packageId.install.ts +16 -0
- package/src/routes/api/ecosystem.packages.$packageId.runner-presets.ts +19 -0
- package/src/routes/api/ecosystem.packages.$packageId.upgrade.ts +16 -0
- package/src/routes/api/ecosystem.packages.ts +1 -248
- package/src/routes/api/ecosystem.tasks.$taskId.ts +16 -0
- package/src/routes/api/ecosystem.tasks.ts +12 -0
- package/.output/public/assets/ProxyViewerContainer-CfP-komD.js +0 -106
- package/.output/public/assets/ReplayDialog-CQlLX1Uo.js +0 -1
- package/.output/public/assets/ResponseView-DuLLeYSh.js +0 -3
- package/.output/public/assets/StreamingChunkSequence-CN4aRFBx.js +0 -1
- package/.output/public/assets/index-0pt1umWP.css +0 -1
- package/.output/public/assets/index-DSUEOPbC.js +0 -1
- package/.output/server/_tanstack-start-manifest_v-CltlYL3I.mjs +0 -4
package/.output/server/_ssr/{ProxyViewerContainer-Dp7Va9_T.mjs → ProxyViewerContainer-EJIogcGd.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as reactExports, j as jsxRuntimeExports, a as React } from "../_libs/react.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { C as CapturedLogSchema, D as DEFAULT_CAPTURE_MODE, a as DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS, b as DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS, c as DEFAULT_TIME_DISPLAY_FORMAT, d as RuntimeConfigSchema, p as packageJson, P as ProviderConfigSchema, i as apiFormatForPath, n as DeleteInspectorGroupsResponseSchema, o as GroupEvidenceExportResultSchema, q as DeleteInspectorGroupResponseSchema, l as AlertSummarySchema, m as AlertListResponseSchema, I as InspectorGroupsListResponseSchema, G as GroupEvidenceReadResponseSchema, z as createPendingProviderTestResults, B as ProviderTestResultsSchema, E as createFailedProviderTestResults, M as MAX_SLOW_RESPONSE_THRESHOLD_SECONDS, F as MAX_PROVIDER_TEST_TIMEOUT_SECONDS, T as TimeDisplayFormatSchema, t as maskApiKey, u as PATH_V1_MESSAGES, v as PATH_V1_CHAT_COMPLETIONS, w as PATH_V1_RESPONSES, r as providerHasContextMetadata, f as parseOpenAIResponse, g as parseOpenAIResponsesResponse, O as OpenAIRequestSchema, h as OpenAIResponsesRequestSchema, A as AnthropicResponseSchema$1, e as AnthropicRequestSchema, s as safeGetOwnProperty, H as resolveProviderContextWindow, j as getSessionPath, x as findProviderModelMetadata, y as previewUpstreamUrl, K as KnowledgeCandidateSchema, J as isPlainRecord, k as stripClaudeCodeBillingHeader, L as LogBodyChunkSchema } from "./router-BI-Mvxz9.mjs";
|
|
3
3
|
import { u as useSWR, a as useSWRConfig } from "../_libs/swr.mjs";
|
|
4
4
|
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
5
5
|
import { c as clsx } from "../_libs/clsx.mjs";
|
|
@@ -50,20 +50,42 @@ class ApiTimeoutError extends Error {
|
|
|
50
50
|
this.name = "ApiTimeoutError";
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
async function
|
|
53
|
+
async function fetchWithTimeout(input, timeoutMs, init) {
|
|
54
54
|
const controller = new AbortController();
|
|
55
|
-
|
|
55
|
+
let timedOut = false;
|
|
56
|
+
const timeout = setTimeout(() => {
|
|
57
|
+
timedOut = true;
|
|
58
|
+
controller.abort();
|
|
59
|
+
}, timeoutMs);
|
|
60
|
+
const callerSignal = init?.signal ?? void 0;
|
|
61
|
+
const abortFromCaller = () => controller.abort();
|
|
62
|
+
if (callerSignal !== void 0) {
|
|
63
|
+
if (callerSignal.aborted) {
|
|
64
|
+
controller.abort();
|
|
65
|
+
} else {
|
|
66
|
+
callerSignal.addEventListener("abort", abortFromCaller, { once: true });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
56
69
|
try {
|
|
57
|
-
return await
|
|
70
|
+
return await fetch(input, { ...init, signal: controller.signal });
|
|
58
71
|
} catch (error) {
|
|
59
|
-
if (error instanceof DOMException && error.name === "AbortError") {
|
|
72
|
+
if (timedOut && error instanceof DOMException && error.name === "AbortError") {
|
|
60
73
|
throw new ApiTimeoutError(timeoutMs);
|
|
61
74
|
}
|
|
62
75
|
throw error;
|
|
63
76
|
} finally {
|
|
64
77
|
clearTimeout(timeout);
|
|
78
|
+
callerSignal?.removeEventListener("abort", abortFromCaller);
|
|
65
79
|
}
|
|
66
80
|
}
|
|
81
|
+
async function fetchJsonWithTimeout(input, schema, timeoutMs, init, errorFallback) {
|
|
82
|
+
const response = await fetchWithTimeout(input, timeoutMs, init);
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const fallback = errorFallback?.(response) ?? `Request failed with status ${response.status}`;
|
|
85
|
+
throw new Error(await readApiError(response, fallback));
|
|
86
|
+
}
|
|
87
|
+
return parseJsonResponse$1(response, schema);
|
|
88
|
+
}
|
|
67
89
|
const ImportLogsResponseSchema = object({
|
|
68
90
|
sessionId: string(),
|
|
69
91
|
imported: number().int().nonnegative(),
|
|
@@ -321,6 +343,7 @@ const SECRET_TEXT_PATTERNS = [
|
|
|
321
343
|
const MAX_EXPORT_LOGS = 200;
|
|
322
344
|
const MAX_EXPORT_TEXT_CHARS = 25e6;
|
|
323
345
|
const MAX_STREAMING_CHUNK_EXPORTS = 50;
|
|
346
|
+
const STREAMING_CHUNK_EXPORT_TIMEOUT_MS = 1e4;
|
|
324
347
|
function formatApproxSize(chars) {
|
|
325
348
|
if (chars < 1024) return `${chars} chars`;
|
|
326
349
|
if (chars < 1024 * 1024) return `${Math.ceil(chars / 1024)} KB`;
|
|
@@ -346,9 +369,19 @@ function exportLimitMessage(logs) {
|
|
|
346
369
|
}
|
|
347
370
|
return null;
|
|
348
371
|
}
|
|
349
|
-
|
|
372
|
+
function exportCanceled(signal) {
|
|
373
|
+
if (signal?.aborted === true) {
|
|
374
|
+
return { ok: false, message: "Export canceled.", canceled: true };
|
|
375
|
+
}
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
async function fetchStreamingChunks(logId, signal) {
|
|
350
379
|
try {
|
|
351
|
-
const response = await
|
|
380
|
+
const response = await fetchWithTimeout(
|
|
381
|
+
`/api/logs/${logId}/chunks`,
|
|
382
|
+
STREAMING_CHUNK_EXPORT_TIMEOUT_MS,
|
|
383
|
+
{ signal }
|
|
384
|
+
);
|
|
352
385
|
if (!response.ok) return null;
|
|
353
386
|
const data = await response.json();
|
|
354
387
|
return JSON.stringify(data, null, 2);
|
|
@@ -409,7 +442,9 @@ function buildExportManifest(logs, mode, streamingLogs, exportedAt = (/* @__PURE
|
|
|
409
442
|
streamingChunkLogIds: streamingLogs.map((log) => log.id)
|
|
410
443
|
};
|
|
411
444
|
}
|
|
412
|
-
async function exportLogsAsZip(logs, mode = "redacted") {
|
|
445
|
+
async function exportLogsAsZip(logs, mode = "redacted", options = {}) {
|
|
446
|
+
const initialCancel = exportCanceled(options.signal);
|
|
447
|
+
if (initialCancel !== null) return initialCancel;
|
|
413
448
|
const limitMessage = exportLimitMessage(logs);
|
|
414
449
|
if (limitMessage !== null) return { ok: false, message: limitMessage };
|
|
415
450
|
const zip = new JSZip();
|
|
@@ -428,6 +463,8 @@ async function exportLogsAsZip(logs, mode = "redacted") {
|
|
|
428
463
|
)
|
|
429
464
|
);
|
|
430
465
|
for (const log of logs) {
|
|
466
|
+
const canceled2 = exportCanceled(options.signal);
|
|
467
|
+
if (canceled2 !== null) return canceled2;
|
|
431
468
|
if (log.rawRequestBody !== null) {
|
|
432
469
|
zip.file(`#${log.id}.Request.json`, exportText(log.rawRequestBody, mode));
|
|
433
470
|
}
|
|
@@ -436,12 +473,16 @@ async function exportLogsAsZip(logs, mode = "redacted") {
|
|
|
436
473
|
}
|
|
437
474
|
}
|
|
438
475
|
for (const log of streamingLogs) {
|
|
439
|
-
const
|
|
476
|
+
const canceled2 = exportCanceled(options.signal);
|
|
477
|
+
if (canceled2 !== null) return canceled2;
|
|
478
|
+
const chunks = await fetchStreamingChunks(log.id, options.signal);
|
|
440
479
|
if (chunks !== null) {
|
|
441
480
|
zip.file(`#${log.id}.SSE.Response.json`, exportText(chunks, mode));
|
|
442
481
|
}
|
|
443
482
|
}
|
|
444
483
|
const blob = await zip.generateAsync({ type: "blob" });
|
|
484
|
+
const canceled = exportCanceled(options.signal);
|
|
485
|
+
if (canceled !== null) return canceled;
|
|
445
486
|
const url = URL.createObjectURL(blob);
|
|
446
487
|
const anchor = document.createElement("a");
|
|
447
488
|
anchor.href = url;
|
|
@@ -849,8 +890,8 @@ function ConfirmDialog({
|
|
|
849
890
|
}
|
|
850
891
|
const ClaudeCodeLogoSvg = "data:image/svg+xml,%3csvg%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eClaude%20Code%3c/title%3e%3cpath%20clip-rule='evenodd'%20d='M20.998%2010.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6%2010.949h1.488V8.102H6v2.847zm10.51%200H18V8.102h-1.49v2.847z'%20fill='%23D97757'%20fill-rule='evenodd'%3e%3c/path%3e%3c/svg%3e";
|
|
851
892
|
const CodexLogoSvg = "data:image/svg+xml,%3csvg%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eCodex%3c/title%3e%3cpath%20d='M19.503%200H4.496A4.496%204.496%200%20000%204.496v15.007A4.496%204.496%200%20004.496%2024h15.007A4.496%204.496%200%200024%2019.503V4.496A4.496%204.496%200%200019.503%200z'%20fill='%23fff'%3e%3c/path%3e%3cpath%20d='M9.064%203.344a4.578%204.578%200%20012.285-.312c1%20.115%201.891.54%202.673%201.275.01.01.024.017.037.021a.09.09%200%2000.043%200%204.55%204.55%200%20013.046.275l.047.022.116.057a4.581%204.581%200%20012.188%202.399c.209.51.313%201.041.315%201.595a4.24%204.24%200%2001-.134%201.223.123.123%200%2000.03.115c.594.607.988%201.33%201.183%202.17.289%201.425-.007%202.71-.887%203.854l-.136.166a4.548%204.548%200%2001-2.201%201.388.123.123%200%2000-.081.076c-.191.551-.383%201.023-.74%201.494-.9%201.187-2.222%201.846-3.711%201.838-1.187-.006-2.239-.44-3.157-1.302a.107.107%200%2000-.105-.024c-.388.125-.78.143-1.204.138a4.441%204.441%200%2001-1.945-.466%204.544%204.544%200%2001-1.61-1.335c-.152-.202-.303-.392-.414-.617a5.81%205.81%200%2001-.37-.961%204.582%204.582%200%2001-.014-2.298.124.124%200%2000.006-.056.085.085%200%2000-.027-.048%204.467%204.467%200%2001-1.034-1.651%203.896%203.896%200%2001-.251-1.192%205.189%205.189%200%2001.141-1.6c.337-1.112.982-1.985%201.933-2.618.212-.141.413-.251.601-.33.215-.089.43-.164.646-.227a.098.098%200%2000.065-.066%204.51%204.51%200%2001.829-1.615%204.535%204.535%200%20011.837-1.388zm3.482%2010.565a.637.637%200%20000%201.272h3.636a.637.637%200%20100-1.272h-3.636zM8.462%209.23a.637.637%200%2000-1.106.631l1.272%202.224-1.266%202.136a.636.636%200%20101.095.649l1.454-2.455a.636.636%200%2000.005-.64L8.462%209.23z'%20fill='url(%23lobe-icons-codex-_R_0_)'%3e%3c/path%3e%3cdefs%3e%3clinearGradient%20gradientUnits='userSpaceOnUse'%20id='lobe-icons-codex-_R_0_'%20x1='12'%20x2='12'%20y1='3'%20y2='21'%3e%3cstop%20stop-color='%23B1A7FF'%3e%3c/stop%3e%3cstop%20offset='.5'%20stop-color='%237A9DFF'%3e%3c/stop%3e%3cstop%20offset='1'%20stop-color='%233941FF'%3e%3c/stop%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e";
|
|
852
|
-
const OpenCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='
|
|
853
|
-
const MiMoCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='
|
|
893
|
+
const OpenCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='%237dd3fc'%20fill-rule='evenodd'%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eOpenCode%3c/title%3e%3cpath%20d='M16%206H8v12h8V6zm4%2016H4V2h16v20z'%3e%3c/path%3e%3c/svg%3e";
|
|
894
|
+
const MiMoCodeLogoSvg = "data:image/svg+xml,%3csvg%20fill='%23ff6900'%20fill-rule='evenodd'%20height='1em'%20style='flex:none;line-height:1'%20viewBox='0%200%2024%2024'%20width='1em'%20xmlns='http://www.w3.org/2000/svg'%3e%3ctitle%3eMiMo%20Code%3c/title%3e%3cpath%20d='M.958%2015.936a.459.459%200%2001.459.44v2.729a.46.46%200%2001-.918%200v-2.729a.459.459%200%2001.459-.44zm4.814-2.035a.46.46%200%2001.553.45v4.754a.458.458%200%2011-.918%200V15.48L3.74%2017.202a.462.462%200%2001-.655.016.462.462%200%2001-.065-.082L.628%2014.67a.459.459%200%2001.658-.637l2.124%202.187%202.127-2.188a.46.46%200%2001.235-.13zm2.068.004a.46.46%200%2001.458.445v4.755a.46.46%200%2001-.458.458.459.459%200%2001-.458-.458V14.35a.459.459%200%2001.458-.445zm1.973%202.014a.46.46%200%2001.46.457v2.729a.46.46%200%2001-.784.324.46.46%200%2001-.134-.324v-2.729a.46.46%200%2001.458-.458zm.002-2.045a.458.458%200%2001.328.157l2.127%202.19%202.125-2.19a.459.459%200%2001.784.318v4.756a.46.46%200%2001-.455.458.46.46%200%2001-.458-.458V15.48l-1.667%201.723a.46.46%200%2001-.65.008l-.005-.005c0-.002-.002-.002-.004-.003l-2.455-2.534a.46.46%200%2001-.008-.667.461.461%200%2001.338-.128zm6.797%201.206a.46.46%200%2001.53.651A1.966%201.966%200%200019.81%2018.4a.462.462%200%2001.623.18.46.46%200%2001-.181.624%202.863%202.863%200%2001-1.38.353l-.142-.004a2.88%202.88%200%2001-2.393-4.263.461.461%200%2001.274-.21zm.864-.931a2.884%202.884%200%20013.915%203.914.46.46%200%2001-.402.24l-.057-.004a.458.458%200%2001-.164-.055.46.46%200%2001-.182-.622%201.967%201.967%200%2000-2.669-2.67.459.459%200%2011-.441-.803zM9.59%206.368c1.481%200%201.696%201.202%201.696%201.654v2.648h-.917v-.432c-.26.346-.792.535-1.36.535-.133%200-1.289-.03-1.384-1.136-.082-.932.675-1.61%202.053-1.61h.691c0-.563-.367-.886-.983-.886-.44.013-.864.174-1.2.458l-.36-.664c.484-.379%201.012-.567%201.764-.567zm4.427.1c1.263%200%202.082.97%202.083%202.15%200%201.181-.824%202.154-2.083%202.154-1.26%200-2.084-.972-2.084-2.152%200-1.18.82-2.153%202.084-2.153zm6.801.015c.68%200%201.202.465%201.197%201.548v2.642H21.1V8.29c0-.312-.002-.98-.63-.98s-.628.667-.628.838v2.524h-.89V8.148c0-.17-.001-.838-.63-.838-.628%200-.628.668-.628.98v2.383h-.917v-4.03h.917V7a1.22%201.22%200%2001.947-.516c.398%200%20.76.193.982.686a1.321%201.321%200%20011.195-.686zm-18.093.872l1.457-1.772H5.32L3.311%208.07l2.14%202.602H4.24L2.725%208.796%201.21%2010.672H0L2.138%208.07.13%205.583h1.138l1.458%201.772zm4.149%203.317h-.916V6.644h.916v4.028zm16.99%200h-.916V6.644h.916v4.028zM9.925%208.71c-1.055%200-1.359.412-1.326.742.032.329.324.537.757.537a1.013%201.013%200%20001.014-.968l.002-.31h-.447zM14.018%207.3c-.663%200-1.184.487-1.184%201.32%200%20.832.52%201.32%201.184%201.32.662%200%201.182-.49%201.182-1.32%200-.832-.52-1.32-1.182-1.32zM6.417%205.001a.568.568%200%2001.587.582.588.588%200%2001-1.175%200A.57.57%200%20016.417%205zm16.991%200a.57.57%200%2001.592.582.588.588%200%2001-1.174%200%20.57.57%200%2001.357-.542.572.572%200%2001.225-.04z'%3e%3c/path%3e%3c/svg%3e";
|
|
854
895
|
const CLIENT_LABELS = {
|
|
855
896
|
codex: "Codex",
|
|
856
897
|
opencode: "OpenCode",
|
|
@@ -897,6 +938,18 @@ const CLIENT_LOGOS = {
|
|
|
897
938
|
"mimo-code": MiMoCodeLogoSvg,
|
|
898
939
|
"claude-code": ClaudeCodeLogoSvg
|
|
899
940
|
};
|
|
941
|
+
const CLIENT_LOGO_FRAMES = {
|
|
942
|
+
codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
|
|
943
|
+
opencode: "border-sky-200/25 bg-sky-300/[0.12]",
|
|
944
|
+
"mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
|
|
945
|
+
"claude-code": "border-amber-100/20 bg-amber-300/[0.09]"
|
|
946
|
+
};
|
|
947
|
+
const CLIENT_LOGO_IMAGES = {
|
|
948
|
+
codex: "p-0.5",
|
|
949
|
+
opencode: "p-1 drop-shadow-[0_0_8px_rgba(125,211,252,0.35)]",
|
|
950
|
+
"mimo-code": "p-0.5 drop-shadow-[0_0_8px_rgba(255,105,0,0.35)]",
|
|
951
|
+
"claude-code": "p-0.5"
|
|
952
|
+
};
|
|
900
953
|
function ClientLogo({
|
|
901
954
|
client,
|
|
902
955
|
className
|
|
@@ -909,12 +962,21 @@ function ClientLogo({
|
|
|
909
962
|
"span",
|
|
910
963
|
{
|
|
911
964
|
className: cn(
|
|
912
|
-
"
|
|
965
|
+
"inline-flex size-6 shrink-0 items-center justify-center rounded-md border p-0 shadow-sm",
|
|
966
|
+
CLIENT_LOGO_FRAMES[client],
|
|
913
967
|
className
|
|
914
968
|
),
|
|
915
969
|
"aria-label": label,
|
|
916
970
|
title: label,
|
|
917
|
-
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
971
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
972
|
+
"img",
|
|
973
|
+
{
|
|
974
|
+
src: logoSrc,
|
|
975
|
+
alt: "",
|
|
976
|
+
className: cn("size-full object-contain", CLIENT_LOGO_IMAGES[client]),
|
|
977
|
+
"aria-hidden": "true"
|
|
978
|
+
}
|
|
979
|
+
)
|
|
918
980
|
}
|
|
919
981
|
);
|
|
920
982
|
}
|
|
@@ -1611,11 +1673,11 @@ function ConversationHeader({
|
|
|
1611
1673
|
showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
1612
1674
|
"span",
|
|
1613
1675
|
{
|
|
1614
|
-
className: "bg-white/[0.045] inline-flex h-6
|
|
1676
|
+
className: "bg-white/[0.045] inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-muted-foreground",
|
|
1615
1677
|
title: clientTooltip ?? clientDisplayLabel,
|
|
1616
1678
|
children: [
|
|
1617
1679
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: clientApp, className: "size-4 shrink-0" }),
|
|
1618
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
1680
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono leading-snug tabular-nums", children: clientDisplayLabel })
|
|
1619
1681
|
]
|
|
1620
1682
|
}
|
|
1621
1683
|
),
|
|
@@ -2306,27 +2368,27 @@ function useCopyFeedback(text) {
|
|
|
2306
2368
|
return { copied, copy };
|
|
2307
2369
|
}
|
|
2308
2370
|
const LazyCompareDrawer = reactExports.lazy(
|
|
2309
|
-
() => import("./CompareDrawer-
|
|
2371
|
+
() => import("./CompareDrawer-CaM8FYuD.mjs").then((m) => ({ default: m.CompareDrawer }))
|
|
2310
2372
|
);
|
|
2311
2373
|
const LazyReplayDialog = reactExports.lazy(
|
|
2312
|
-
() => import("./ReplayDialog-
|
|
2374
|
+
() => import("./ReplayDialog-BPpJ2-q8.mjs").then((m) => ({ default: m.ReplayDialog }))
|
|
2313
2375
|
);
|
|
2314
2376
|
const LazyRequestAnatomy = reactExports.lazy(
|
|
2315
|
-
() => import("./RequestAnatomy-
|
|
2377
|
+
() => import("./RequestAnatomy-DeQAWnZx.mjs").then((m) => ({ default: m.RequestAnatomy }))
|
|
2316
2378
|
);
|
|
2317
2379
|
const LazyResponseView = reactExports.lazy(
|
|
2318
|
-
() => import("./ResponseView-
|
|
2380
|
+
() => import("./ResponseView-Dshm8iQ7.mjs").then((m) => ({ default: m.ResponseView }))
|
|
2319
2381
|
);
|
|
2320
2382
|
const LazyStreamingChunkSequence = reactExports.lazy(
|
|
2321
|
-
() => import("./StreamingChunkSequence-
|
|
2383
|
+
() => import("./StreamingChunkSequence-32yIU2hn.mjs").then((m) => ({
|
|
2322
2384
|
default: m.StreamingChunkSequence
|
|
2323
2385
|
}))
|
|
2324
2386
|
);
|
|
2325
2387
|
const LazyJsonViewer = reactExports.lazy(
|
|
2326
|
-
() => import("./json-viewer-
|
|
2388
|
+
() => import("./json-viewer-C0aX5rqC.mjs").then((m) => ({ default: m.JsonViewer }))
|
|
2327
2389
|
);
|
|
2328
2390
|
const LazyJsonViewerFromString = reactExports.lazy(
|
|
2329
|
-
() => import("./json-viewer-
|
|
2391
|
+
() => import("./json-viewer-C0aX5rqC.mjs").then((m) => ({ default: m.JsonViewerFromString }))
|
|
2330
2392
|
);
|
|
2331
2393
|
const HIGHLIGHT_DURATION_MS = 1200;
|
|
2332
2394
|
const MAX_HIGHLIGHT_ATTEMPTS = 12;
|
|
@@ -5260,6 +5322,9 @@ const CandidatePromotionFailureResponseSchema = object({
|
|
|
5260
5322
|
const CandidateUpdateResponseSchema = object({
|
|
5261
5323
|
candidate: KnowledgeCandidateSchema
|
|
5262
5324
|
});
|
|
5325
|
+
const CANDIDATE_GENERATE_TIMEOUT_MS = 3e4;
|
|
5326
|
+
const CANDIDATE_PROMOTE_TIMEOUT_MS = 15e3;
|
|
5327
|
+
const CANDIDATE_UPDATE_TIMEOUT_MS = 15e3;
|
|
5263
5328
|
const CANDIDATE_STATUS_CLASSES = {
|
|
5264
5329
|
draft: "border-amber-500/30 bg-amber-500/10 text-amber-500",
|
|
5265
5330
|
promoted: "border-emerald-500/30 bg-emerald-500/10 text-emerald-500",
|
|
@@ -5765,19 +5830,13 @@ function AgentTraceSummary({
|
|
|
5765
5830
|
setCandidateState({ status: "loading", error: null });
|
|
5766
5831
|
void (async () => {
|
|
5767
5832
|
try {
|
|
5768
|
-
const
|
|
5833
|
+
const parsed = await fetchJsonWithTimeout(
|
|
5769
5834
|
`/api/knowledge/sessions/${encodeURIComponent(scopeId)}/candidates`,
|
|
5770
|
-
|
|
5835
|
+
CandidateResponseSchema,
|
|
5836
|
+
CANDIDATE_GENERATE_TIMEOUT_MS,
|
|
5837
|
+
{ method: "POST" },
|
|
5838
|
+
(response) => `Candidate generation failed with ${String(response.status)}`
|
|
5771
5839
|
);
|
|
5772
|
-
if (!response.ok) {
|
|
5773
|
-
const message = await readApiError(
|
|
5774
|
-
response,
|
|
5775
|
-
`Candidate generation failed with ${String(response.status)}`
|
|
5776
|
-
);
|
|
5777
|
-
setCandidateState({ status: "failed", error: message });
|
|
5778
|
-
return;
|
|
5779
|
-
}
|
|
5780
|
-
const parsed = await parseJsonResponse$1(response, CandidateResponseSchema);
|
|
5781
5840
|
setCandidates(parsed.candidates);
|
|
5782
5841
|
setCandidatesExpanded(parsed.candidates.length > 0);
|
|
5783
5842
|
setCandidateState(
|
|
@@ -5800,8 +5859,9 @@ function AgentTraceSummary({
|
|
|
5800
5859
|
});
|
|
5801
5860
|
void (async () => {
|
|
5802
5861
|
try {
|
|
5803
|
-
const response = await
|
|
5862
|
+
const response = await fetchWithTimeout(
|
|
5804
5863
|
`/api/knowledge/candidates/${encodeURIComponent(candidateId)}/promote`,
|
|
5864
|
+
CANDIDATE_PROMOTE_TIMEOUT_MS,
|
|
5805
5865
|
{ method: "POST" }
|
|
5806
5866
|
);
|
|
5807
5867
|
const raw = await response.json().catch(() => null);
|
|
@@ -5850,23 +5910,17 @@ function AgentTraceSummary({
|
|
|
5850
5910
|
return next;
|
|
5851
5911
|
});
|
|
5852
5912
|
try {
|
|
5853
|
-
const
|
|
5913
|
+
const parsed = await fetchJsonWithTimeout(
|
|
5854
5914
|
`/api/knowledge/candidates/${encodeURIComponent(candidateId)}`,
|
|
5915
|
+
CandidateUpdateResponseSchema,
|
|
5916
|
+
CANDIDATE_UPDATE_TIMEOUT_MS,
|
|
5855
5917
|
{
|
|
5856
5918
|
method: "PATCH",
|
|
5857
5919
|
headers: { "Content-Type": "application/json" },
|
|
5858
5920
|
body: JSON.stringify(update)
|
|
5859
|
-
}
|
|
5921
|
+
},
|
|
5922
|
+
(response) => `Candidate update failed with ${String(response.status)}`
|
|
5860
5923
|
);
|
|
5861
|
-
if (!response.ok) {
|
|
5862
|
-
const message = await readApiError(
|
|
5863
|
-
response,
|
|
5864
|
-
`Candidate update failed with ${String(response.status)}`
|
|
5865
|
-
);
|
|
5866
|
-
setCandidateState({ status: "failed", error: message });
|
|
5867
|
-
return false;
|
|
5868
|
-
}
|
|
5869
|
-
const parsed = await parseJsonResponse$1(response, CandidateUpdateResponseSchema);
|
|
5870
5924
|
setCandidates(
|
|
5871
5925
|
(current) => current.map(
|
|
5872
5926
|
(candidate) => candidate.id === parsed.candidate.id ? parsed.candidate : candidate
|
|
@@ -6556,7 +6610,7 @@ function AlertList({
|
|
|
6556
6610
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: cn("text-xs font-semibold", severityText(alert.severity)), children: severityLabel(alert.severity) }),
|
|
6557
6611
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-xs text-muted-foreground", children: categoryLabel(alert.category) })
|
|
6558
6612
|
] }),
|
|
6559
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1
|
|
6613
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 text-sm font-semibold leading-snug", children: alert.title }),
|
|
6560
6614
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 line-clamp-2 text-xs text-muted-foreground", children: alert.message })
|
|
6561
6615
|
] }),
|
|
6562
6616
|
alert.count > 1 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "outline", className: "shrink-0", children: [
|
|
@@ -6564,8 +6618,8 @@ function AlertList({
|
|
|
6564
6618
|
formatCount(alert.count)
|
|
6565
6619
|
] }) : null
|
|
6566
6620
|
] }),
|
|
6567
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex min-w-0 items-
|
|
6568
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
6621
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 flex min-w-0 items-start justify-between gap-2 text-[11px] text-muted-foreground", children: [
|
|
6622
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 leading-snug", children: providerModel$1(alert) }),
|
|
6569
6623
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0", children: formatTimestamp$1(alert.lastSeenAt) })
|
|
6570
6624
|
] })
|
|
6571
6625
|
]
|
|
@@ -6942,6 +6996,7 @@ function TransientToast({
|
|
|
6942
6996
|
}
|
|
6943
6997
|
);
|
|
6944
6998
|
}
|
|
6999
|
+
const GROUP_OPERATION_TIMEOUT_MS = 2e4;
|
|
6945
7000
|
function groupDeletePath(groupId, deleteEvidence) {
|
|
6946
7001
|
const path = `/api/groups/${encodeURIComponent(groupId)}`;
|
|
6947
7002
|
return deleteEvidence ? `${path}?deleteEvidence=1` : path;
|
|
@@ -7162,18 +7217,13 @@ function GroupsDialog() {
|
|
|
7162
7217
|
setDeleteError(null);
|
|
7163
7218
|
setExportError(null);
|
|
7164
7219
|
try {
|
|
7165
|
-
const
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
tone: "error"
|
|
7173
|
-
});
|
|
7174
|
-
return;
|
|
7175
|
-
}
|
|
7176
|
-
const parsed = await parseJsonResponse$1(response, DeleteInspectorGroupsResponseSchema);
|
|
7220
|
+
const parsed = await fetchJsonWithTimeout(
|
|
7221
|
+
groupsClearPath(false),
|
|
7222
|
+
DeleteInspectorGroupsResponseSchema,
|
|
7223
|
+
GROUP_OPERATION_TIMEOUT_MS,
|
|
7224
|
+
{ method: "DELETE" },
|
|
7225
|
+
(response) => `Clear failed with status ${String(response.status)}`
|
|
7226
|
+
);
|
|
7177
7227
|
setExportResult(null);
|
|
7178
7228
|
setSelectedGroupId(null);
|
|
7179
7229
|
await mutate();
|
|
@@ -7196,18 +7246,17 @@ function GroupsDialog() {
|
|
|
7196
7246
|
setExportingGroupId(group.id);
|
|
7197
7247
|
setExportError(null);
|
|
7198
7248
|
try {
|
|
7199
|
-
const
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
const parsed = await parseJsonResponse$1(response, GroupEvidenceExportResultSchema);
|
|
7249
|
+
const parsed = await fetchJsonWithTimeout(
|
|
7250
|
+
`/api/groups/${encodeURIComponent(group.id)}/evidence`,
|
|
7251
|
+
GroupEvidenceExportResultSchema,
|
|
7252
|
+
GROUP_OPERATION_TIMEOUT_MS,
|
|
7253
|
+
{
|
|
7254
|
+
method: "POST",
|
|
7255
|
+
headers: { "content-type": "application/json" },
|
|
7256
|
+
body: JSON.stringify({ latestLogLimit: 10 })
|
|
7257
|
+
},
|
|
7258
|
+
(response) => `Export failed with status ${String(response.status)}`
|
|
7259
|
+
);
|
|
7211
7260
|
setExportResult(parsed);
|
|
7212
7261
|
await mutate();
|
|
7213
7262
|
await mutateEvidence();
|
|
@@ -7242,16 +7291,13 @@ function GroupsDialog() {
|
|
|
7242
7291
|
setDeletingGroupId(group.id);
|
|
7243
7292
|
setDeleteError(null);
|
|
7244
7293
|
try {
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
return;
|
|
7253
|
-
}
|
|
7254
|
-
await parseJsonResponse$1(response, DeleteInspectorGroupResponseSchema);
|
|
7294
|
+
await fetchJsonWithTimeout(
|
|
7295
|
+
groupDeletePath(group.id, deleteEvidence),
|
|
7296
|
+
DeleteInspectorGroupResponseSchema,
|
|
7297
|
+
GROUP_OPERATION_TIMEOUT_MS,
|
|
7298
|
+
{ method: "DELETE" },
|
|
7299
|
+
(response) => `Delete failed with status ${String(response.status)}`
|
|
7300
|
+
);
|
|
7255
7301
|
setExportResult(
|
|
7256
7302
|
(current) => current !== null && current.group.id === group.id ? null : current
|
|
7257
7303
|
);
|
|
@@ -7380,7 +7426,7 @@ function GroupList({
|
|
|
7380
7426
|
),
|
|
7381
7427
|
children: [
|
|
7382
7428
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center justify-between gap-2", children: [
|
|
7383
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0
|
|
7429
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 text-sm font-medium leading-snug", children: group.title }),
|
|
7384
7430
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) })
|
|
7385
7431
|
] }),
|
|
7386
7432
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex items-center gap-2 text-muted-foreground", children: [
|
|
@@ -7429,7 +7475,7 @@ function GroupDetails({
|
|
|
7429
7475
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
7430
7476
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
7431
7477
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
7432
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "min-w-0
|
|
7478
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "min-w-0 text-base font-semibold leading-snug", children: group.title }),
|
|
7433
7479
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(group.status), children: statusLabel(group.status) }),
|
|
7434
7480
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", children: group.kind })
|
|
7435
7481
|
] }),
|
|
@@ -7787,7 +7833,7 @@ function MemberRow({
|
|
|
7787
7833
|
] }),
|
|
7788
7834
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-0.5 truncate text-[11px] text-muted-foreground", children: displayText(member.agent) })
|
|
7789
7835
|
] }),
|
|
7790
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "max-w-52 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block
|
|
7836
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "max-w-52 px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block whitespace-normal leading-snug", children: providerModel(member) }) }),
|
|
7791
7837
|
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: statusClassName(member.status), children: statusLabel(member.status) }) }),
|
|
7792
7838
|
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: requests === null ? "-" : formatNumber(requests) }),
|
|
7793
7839
|
/* @__PURE__ */ jsxRuntimeExports.jsx("td", { className: "px-3 py-2 font-mono", children: errors === null ? "-" : formatNumber(errors) }),
|
|
@@ -7934,70 +7980,6 @@ function MemberMetadata({ entries }) {
|
|
|
7934
7980
|
}) })
|
|
7935
7981
|
] });
|
|
7936
7982
|
}
|
|
7937
|
-
function ClaudeCodeIcon() {
|
|
7938
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
7939
|
-
"svg",
|
|
7940
|
-
{
|
|
7941
|
-
fill: "currentColor",
|
|
7942
|
-
fillRule: "evenodd",
|
|
7943
|
-
viewBox: "0 0 24 24",
|
|
7944
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
7945
|
-
className: "size-6 shrink-0",
|
|
7946
|
-
children: [
|
|
7947
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: "Claude Code" }),
|
|
7948
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
7949
|
-
"path",
|
|
7950
|
-
{
|
|
7951
|
-
clipRule: "evenodd",
|
|
7952
|
-
d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z"
|
|
7953
|
-
}
|
|
7954
|
-
)
|
|
7955
|
-
]
|
|
7956
|
-
}
|
|
7957
|
-
);
|
|
7958
|
-
}
|
|
7959
|
-
function OpenCodeIcon() {
|
|
7960
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
7961
|
-
"svg",
|
|
7962
|
-
{
|
|
7963
|
-
fill: "currentColor",
|
|
7964
|
-
fillRule: "evenodd",
|
|
7965
|
-
viewBox: "0 0 24 24",
|
|
7966
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
7967
|
-
className: "size-6 shrink-0",
|
|
7968
|
-
children: [
|
|
7969
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: "OpenCode" }),
|
|
7970
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M16 6H8v12h8V6zm4 16H4V2h16v20z" })
|
|
7971
|
-
]
|
|
7972
|
-
}
|
|
7973
|
-
);
|
|
7974
|
-
}
|
|
7975
|
-
function MiMoCodeIcon() {
|
|
7976
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
7977
|
-
"svg",
|
|
7978
|
-
{
|
|
7979
|
-
fill: "currentColor",
|
|
7980
|
-
viewBox: "0 0 24 24",
|
|
7981
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
7982
|
-
className: "size-6 shrink-0",
|
|
7983
|
-
children: [
|
|
7984
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: "MiMo Code" }),
|
|
7985
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
7986
|
-
"text",
|
|
7987
|
-
{
|
|
7988
|
-
x: "12",
|
|
7989
|
-
y: "18",
|
|
7990
|
-
textAnchor: "middle",
|
|
7991
|
-
fontSize: "16",
|
|
7992
|
-
fontWeight: "800",
|
|
7993
|
-
fontFamily: "system-ui, sans-serif",
|
|
7994
|
-
children: "M"
|
|
7995
|
-
}
|
|
7996
|
-
)
|
|
7997
|
-
]
|
|
7998
|
-
}
|
|
7999
|
-
);
|
|
8000
|
-
}
|
|
8001
7983
|
const ExternalProviderSchema = object({
|
|
8002
7984
|
name: string(),
|
|
8003
7985
|
apiKey: string(),
|
|
@@ -8019,11 +8001,7 @@ const ImportResponseSchema$1 = object({
|
|
|
8019
8001
|
message: string().optional(),
|
|
8020
8002
|
errors: array(string()).optional()
|
|
8021
8003
|
});
|
|
8022
|
-
const
|
|
8023
|
-
"claude-code": ClaudeCodeIcon,
|
|
8024
|
-
opencode: OpenCodeIcon,
|
|
8025
|
-
"mimo-code": MiMoCodeIcon
|
|
8026
|
-
};
|
|
8004
|
+
const PROVIDER_IMPORT_TIMEOUT_MS$1 = 2e4;
|
|
8027
8005
|
function ImportWizardDialog({
|
|
8028
8006
|
open,
|
|
8029
8007
|
onOpenChange,
|
|
@@ -8037,7 +8015,11 @@ function ImportWizardDialog({
|
|
|
8037
8015
|
const [importing, setImporting] = reactExports.useState(false);
|
|
8038
8016
|
const [importResult, setImportResult] = reactExports.useState(null);
|
|
8039
8017
|
const [importError, setImportError] = reactExports.useState(null);
|
|
8018
|
+
const scanRequestIdRef = reactExports.useRef(0);
|
|
8019
|
+
const importRequestIdRef = reactExports.useRef(0);
|
|
8040
8020
|
const scan = reactExports.useCallback(() => {
|
|
8021
|
+
const requestId = scanRequestIdRef.current + 1;
|
|
8022
|
+
scanRequestIdRef.current = requestId;
|
|
8041
8023
|
setScanning(true);
|
|
8042
8024
|
setScanError(null);
|
|
8043
8025
|
setWarnings([]);
|
|
@@ -8045,29 +8027,26 @@ function ImportWizardDialog({
|
|
|
8045
8027
|
setSelected(/* @__PURE__ */ new Set());
|
|
8046
8028
|
setImportResult(null);
|
|
8047
8029
|
setImportError(null);
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
}
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
setWarnings(parsed.data.warnings ?? []);
|
|
8062
|
-
const indices = /* @__PURE__ */ new Set();
|
|
8063
|
-
parsed.data.providers.forEach((p, i) => {
|
|
8064
|
-
if (!p.alreadyExists) indices.add(i);
|
|
8065
|
-
});
|
|
8066
|
-
setSelected(indices);
|
|
8030
|
+
void fetchJsonWithTimeout(
|
|
8031
|
+
"/api/providers/scan",
|
|
8032
|
+
ScanResponseSchema,
|
|
8033
|
+
PROVIDER_IMPORT_TIMEOUT_MS$1,
|
|
8034
|
+
void 0,
|
|
8035
|
+
(response) => `Scan failed (${String(response.status)})`
|
|
8036
|
+
).then((data) => {
|
|
8037
|
+
if (scanRequestIdRef.current !== requestId) return;
|
|
8038
|
+
setProviders(data.providers);
|
|
8039
|
+
setWarnings(data.warnings ?? []);
|
|
8040
|
+
const indices = /* @__PURE__ */ new Set();
|
|
8041
|
+
data.providers.forEach((provider, index) => {
|
|
8042
|
+
if (!provider.alreadyExists) indices.add(index);
|
|
8067
8043
|
});
|
|
8044
|
+
setSelected(indices);
|
|
8068
8045
|
}).catch((err) => {
|
|
8046
|
+
if (scanRequestIdRef.current !== requestId) return;
|
|
8069
8047
|
setScanError(err instanceof Error ? err.message : String(err));
|
|
8070
8048
|
}).finally(() => {
|
|
8049
|
+
if (scanRequestIdRef.current !== requestId) return;
|
|
8071
8050
|
setScanning(false);
|
|
8072
8051
|
});
|
|
8073
8052
|
}, []);
|
|
@@ -8076,6 +8055,13 @@ function ImportWizardDialog({
|
|
|
8076
8055
|
scan();
|
|
8077
8056
|
}
|
|
8078
8057
|
}, [open, scan]);
|
|
8058
|
+
reactExports.useEffect(() => {
|
|
8059
|
+
if (open) return;
|
|
8060
|
+
scanRequestIdRef.current += 1;
|
|
8061
|
+
importRequestIdRef.current += 1;
|
|
8062
|
+
setScanning(false);
|
|
8063
|
+
setImporting(false);
|
|
8064
|
+
}, [open]);
|
|
8079
8065
|
const toggleProvider = reactExports.useCallback((index) => {
|
|
8080
8066
|
setSelected((prev) => {
|
|
8081
8067
|
const next = new Set(prev);
|
|
@@ -8090,6 +8076,8 @@ function ImportWizardDialog({
|
|
|
8090
8076
|
const importSelected = reactExports.useCallback(() => {
|
|
8091
8077
|
const toImport = providers.filter((_, i) => selected.has(i));
|
|
8092
8078
|
if (toImport.length === 0) return;
|
|
8079
|
+
const requestId = importRequestIdRef.current + 1;
|
|
8080
|
+
importRequestIdRef.current = requestId;
|
|
8093
8081
|
setImporting(true);
|
|
8094
8082
|
setImportError(null);
|
|
8095
8083
|
setImportResult(null);
|
|
@@ -8106,17 +8094,18 @@ function ImportWizardDialog({
|
|
|
8106
8094
|
createdAt: now,
|
|
8107
8095
|
updatedAt: now
|
|
8108
8096
|
}));
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
}
|
|
8119
|
-
|
|
8097
|
+
void fetchJsonWithTimeout(
|
|
8098
|
+
"/api/providers/import",
|
|
8099
|
+
ImportResponseSchema$1,
|
|
8100
|
+
PROVIDER_IMPORT_TIMEOUT_MS$1,
|
|
8101
|
+
{
|
|
8102
|
+
method: "POST",
|
|
8103
|
+
headers: { "Content-Type": "application/json" },
|
|
8104
|
+
body: JSON.stringify({ providers: providersPayload })
|
|
8105
|
+
},
|
|
8106
|
+
(response) => `Import failed (${String(response.status)})`
|
|
8107
|
+
).then((result) => {
|
|
8108
|
+
if (importRequestIdRef.current !== requestId) return;
|
|
8120
8109
|
setProviders(
|
|
8121
8110
|
(prev) => prev.map((p, i) => selected.has(i) ? { ...p, alreadyExists: true } : p)
|
|
8122
8111
|
);
|
|
@@ -8128,8 +8117,10 @@ function ImportWizardDialog({
|
|
|
8128
8117
|
}
|
|
8129
8118
|
onImportComplete();
|
|
8130
8119
|
}).catch((err) => {
|
|
8120
|
+
if (importRequestIdRef.current !== requestId) return;
|
|
8131
8121
|
setImportError(err instanceof Error ? err.message : String(err));
|
|
8132
8122
|
}).finally(() => {
|
|
8123
|
+
if (importRequestIdRef.current !== requestId) return;
|
|
8133
8124
|
setImporting(false);
|
|
8134
8125
|
});
|
|
8135
8126
|
}, [providers, selected, onImportComplete]);
|
|
@@ -8170,14 +8161,10 @@ function ImportWizardDialog({
|
|
|
8170
8161
|
),
|
|
8171
8162
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
8172
8163
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
8173
|
-
(
|
|
8174
|
-
const LogoComponent = sourceLogoMap[p.sourceTool];
|
|
8175
|
-
if (LogoComponent === void 0) return null;
|
|
8176
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(LogoComponent, {});
|
|
8177
|
-
})(),
|
|
8164
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ClientLogo, { client: p.sourceTool, className: "size-7 rounded-[8px]" }),
|
|
8178
8165
|
p.alreadyExists && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] text-muted-foreground", children: "Already added" })
|
|
8179
8166
|
] }),
|
|
8180
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-muted-foreground
|
|
8167
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 text-xs leading-snug text-muted-foreground", children: [
|
|
8181
8168
|
p.models.slice(0, 4).join(", "),
|
|
8182
8169
|
p.models.length > 4 ? ` +${p.models.length - 4} more` : ""
|
|
8183
8170
|
] }),
|
|
@@ -8693,13 +8680,13 @@ function ProviderCard({
|
|
|
8693
8680
|
{
|
|
8694
8681
|
className: `flex flex-col gap-3 rounded-[8px] border border-border bg-card p-4 shadow-sm transition-all duration-500 ${isHighlighted === true ? "ring-2 ring-primary shadow-md" : ""}`,
|
|
8695
8682
|
children: [
|
|
8696
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
8683
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [
|
|
8697
8684
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 space-y-1", children: [
|
|
8698
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
8699
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
8685
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [
|
|
8686
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium leading-snug", children: provider.name }),
|
|
8700
8687
|
providerSourceBadge
|
|
8701
8688
|
] }),
|
|
8702
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "
|
|
8689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs leading-snug text-muted-foreground", children: compactModelLabel(provider) })
|
|
8703
8690
|
] }),
|
|
8704
8691
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
8705
8692
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -9848,6 +9835,13 @@ const ModelMetadataRefreshResponseSchema = object({
|
|
|
9848
9835
|
sourceUrl: string()
|
|
9849
9836
|
});
|
|
9850
9837
|
const NETWORK_ERROR_MESSAGE = "Network error: could not reach the server. Is the proxy running?";
|
|
9838
|
+
const CONFIG_PATH_FETCH_TIMEOUT_MS = 5e3;
|
|
9839
|
+
const PROVIDER_TEST_LOG_TIMEOUT_MS = 5e3;
|
|
9840
|
+
const PROVIDER_WRITE_TIMEOUT_MS = 15e3;
|
|
9841
|
+
const PROVIDER_DELETE_TIMEOUT_MS = 1e4;
|
|
9842
|
+
const PROVIDER_EXPORT_TIMEOUT_MS = 2e4;
|
|
9843
|
+
const PROVIDER_IMPORT_TIMEOUT_MS = 2e4;
|
|
9844
|
+
const PROVIDER_METADATA_TIMEOUT_MS = 3e4;
|
|
9851
9845
|
function createProviderPayload(data) {
|
|
9852
9846
|
return {
|
|
9853
9847
|
name: data.name,
|
|
@@ -9871,7 +9865,7 @@ async function persistProviderTestLog(providerId, results) {
|
|
|
9871
9865
|
return;
|
|
9872
9866
|
}
|
|
9873
9867
|
try {
|
|
9874
|
-
await
|
|
9868
|
+
await fetchWithTimeout(`/api/providers/${providerId}/test/log`, PROVIDER_TEST_LOG_TIMEOUT_MS, {
|
|
9875
9869
|
method: "POST",
|
|
9876
9870
|
headers: { "Content-Type": "application/json" },
|
|
9877
9871
|
body: JSON.stringify(results)
|
|
@@ -9939,11 +9933,12 @@ function ProvidersPanel({
|
|
|
9939
9933
|
reactExports.useEffect(() => {
|
|
9940
9934
|
void (async () => {
|
|
9941
9935
|
try {
|
|
9942
|
-
const
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9936
|
+
const data = await fetchJsonWithTimeout(
|
|
9937
|
+
"/api/config/paths",
|
|
9938
|
+
ConfigPathsResponseSchema,
|
|
9939
|
+
CONFIG_PATH_FETCH_TIMEOUT_MS
|
|
9940
|
+
);
|
|
9941
|
+
setConfigPath(data.providerConfig);
|
|
9947
9942
|
} catch {
|
|
9948
9943
|
}
|
|
9949
9944
|
})();
|
|
@@ -10017,30 +10012,31 @@ function ProvidersPanel({
|
|
|
10017
10012
|
}
|
|
10018
10013
|
}, 1e3);
|
|
10019
10014
|
try {
|
|
10020
|
-
const
|
|
10021
|
-
|
|
10022
|
-
|
|
10023
|
-
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
`HTTP ${res.status}: ${res.statusText}`,
|
|
10033
|
-
"server_error"
|
|
10034
|
-
)
|
|
10035
|
-
);
|
|
10036
|
-
}
|
|
10015
|
+
const results = await fetchJsonWithTimeout(
|
|
10016
|
+
`/api/providers/${providerId}/test`,
|
|
10017
|
+
ProviderTestResultsSchema,
|
|
10018
|
+
timeoutSeconds * 1e3 + 1e3,
|
|
10019
|
+
{
|
|
10020
|
+
method: "POST",
|
|
10021
|
+
signal: controller.signal
|
|
10022
|
+
},
|
|
10023
|
+
(response) => `HTTP ${response.status}: ${response.statusText}`
|
|
10024
|
+
);
|
|
10025
|
+
updateTestResults(providerId, results);
|
|
10026
|
+
await persistProviderTestLog(providerId, results);
|
|
10037
10027
|
} catch (err) {
|
|
10038
10028
|
const isAbort = err instanceof Error && err.name === "AbortError";
|
|
10039
|
-
|
|
10029
|
+
const isTimeout = err instanceof ApiTimeoutError;
|
|
10030
|
+
if (isAbort || isTimeout) {
|
|
10040
10031
|
updateTestResults(
|
|
10041
10032
|
providerId,
|
|
10042
10033
|
createFailedProviderTestResults("Request timed out", "timeout")
|
|
10043
10034
|
);
|
|
10035
|
+
} else if (err instanceof Error) {
|
|
10036
|
+
updateTestResults(
|
|
10037
|
+
providerId,
|
|
10038
|
+
createFailedProviderTestResults(err.message, "server_error")
|
|
10039
|
+
);
|
|
10044
10040
|
}
|
|
10045
10041
|
} finally {
|
|
10046
10042
|
clearInterval(intervalId);
|
|
@@ -10065,18 +10061,17 @@ function ProvidersPanel({
|
|
|
10065
10061
|
});
|
|
10066
10062
|
try {
|
|
10067
10063
|
const payload = url !== void 0 && url.trim() !== "" ? { url } : {};
|
|
10068
|
-
const
|
|
10069
|
-
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
}
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
const data = await parseJsonResponse$1(res, ModelMetadataRefreshResponseSchema);
|
|
10064
|
+
const data = await fetchJsonWithTimeout(
|
|
10065
|
+
`/api/providers/${providerId}/model-metadata`,
|
|
10066
|
+
ModelMetadataRefreshResponseSchema,
|
|
10067
|
+
PROVIDER_METADATA_TIMEOUT_MS,
|
|
10068
|
+
{
|
|
10069
|
+
method: "POST",
|
|
10070
|
+
headers: { "Content-Type": "application/json" },
|
|
10071
|
+
body: JSON.stringify(payload)
|
|
10072
|
+
},
|
|
10073
|
+
() => "Failed to refresh model metadata"
|
|
10074
|
+
);
|
|
10080
10075
|
if (data.imported === 0 && showError) {
|
|
10081
10076
|
setError("No matching model metadata found for this provider.");
|
|
10082
10077
|
} else {
|
|
@@ -10085,9 +10080,9 @@ function ProvidersPanel({
|
|
|
10085
10080
|
triggerHighlight(data.provider.id);
|
|
10086
10081
|
refreshProviders();
|
|
10087
10082
|
return data.imported > 0;
|
|
10088
|
-
} catch {
|
|
10083
|
+
} catch (err) {
|
|
10089
10084
|
if (showError) {
|
|
10090
|
-
setError(NETWORK_ERROR_MESSAGE);
|
|
10085
|
+
setError(err instanceof Error ? err.message : NETWORK_ERROR_MESSAGE);
|
|
10091
10086
|
}
|
|
10092
10087
|
return false;
|
|
10093
10088
|
} finally {
|
|
@@ -10103,16 +10098,17 @@ function ProvidersPanel({
|
|
|
10103
10098
|
function handleAddProvider(data) {
|
|
10104
10099
|
void (async () => {
|
|
10105
10100
|
try {
|
|
10106
|
-
const
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
|
|
10111
|
-
|
|
10112
|
-
|
|
10113
|
-
|
|
10114
|
-
|
|
10115
|
-
|
|
10101
|
+
const newProvider = await fetchJsonWithTimeout(
|
|
10102
|
+
"/api/providers",
|
|
10103
|
+
ProviderConfigSchema,
|
|
10104
|
+
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10105
|
+
{
|
|
10106
|
+
method: "POST",
|
|
10107
|
+
headers: { "Content-Type": "application/json" },
|
|
10108
|
+
body: JSON.stringify(createProviderPayload(data))
|
|
10109
|
+
},
|
|
10110
|
+
() => "Failed to add provider"
|
|
10111
|
+
);
|
|
10116
10112
|
setShowForm(false);
|
|
10117
10113
|
triggerHighlight(newProvider.id);
|
|
10118
10114
|
if (data.modelMetadataUrl !== void 0 && data.modelMetadataUrl.trim() !== "") {
|
|
@@ -10120,8 +10116,8 @@ function ProvidersPanel({
|
|
|
10120
10116
|
}
|
|
10121
10117
|
refreshProviders();
|
|
10122
10118
|
await runTest(newProvider.id);
|
|
10123
|
-
} catch {
|
|
10124
|
-
setError(NETWORK_ERROR_MESSAGE);
|
|
10119
|
+
} catch (err) {
|
|
10120
|
+
setError(err instanceof Error ? err.message : NETWORK_ERROR_MESSAGE);
|
|
10125
10121
|
}
|
|
10126
10122
|
})();
|
|
10127
10123
|
}
|
|
@@ -10129,16 +10125,17 @@ function ProvidersPanel({
|
|
|
10129
10125
|
if (!editingProvider) return;
|
|
10130
10126
|
void (async () => {
|
|
10131
10127
|
try {
|
|
10132
|
-
const
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10128
|
+
const updated = await fetchJsonWithTimeout(
|
|
10129
|
+
`/api/providers/${editingProvider.id}`,
|
|
10130
|
+
ProviderConfigSchema,
|
|
10131
|
+
PROVIDER_WRITE_TIMEOUT_MS,
|
|
10132
|
+
{
|
|
10133
|
+
method: "PUT",
|
|
10134
|
+
headers: { "Content-Type": "application/json" },
|
|
10135
|
+
body: JSON.stringify(createProviderPayload(data))
|
|
10136
|
+
},
|
|
10137
|
+
() => "Failed to update provider"
|
|
10138
|
+
);
|
|
10142
10139
|
setEditingProvider(void 0);
|
|
10143
10140
|
triggerHighlight(updated.id);
|
|
10144
10141
|
if (data.modelMetadataUrl !== void 0 && data.modelMetadataUrl.trim() !== "") {
|
|
@@ -10149,8 +10146,8 @@ function ProvidersPanel({
|
|
|
10149
10146
|
if (criticalFieldsChanged) {
|
|
10150
10147
|
await runTest(updated.id);
|
|
10151
10148
|
}
|
|
10152
|
-
} catch {
|
|
10153
|
-
setError(NETWORK_ERROR_MESSAGE);
|
|
10149
|
+
} catch (err) {
|
|
10150
|
+
setError(err instanceof Error ? err.message : NETWORK_ERROR_MESSAGE);
|
|
10154
10151
|
}
|
|
10155
10152
|
})();
|
|
10156
10153
|
}
|
|
@@ -10164,7 +10161,7 @@ function ProvidersPanel({
|
|
|
10164
10161
|
void (async () => {
|
|
10165
10162
|
let res;
|
|
10166
10163
|
try {
|
|
10167
|
-
res = await
|
|
10164
|
+
res = await fetchWithTimeout(`/api/providers/${providerId}`, PROVIDER_DELETE_TIMEOUT_MS, {
|
|
10168
10165
|
method: "DELETE"
|
|
10169
10166
|
});
|
|
10170
10167
|
} catch {
|
|
@@ -10183,7 +10180,7 @@ function ProvidersPanel({
|
|
|
10183
10180
|
const url = `/api/providers/export${""}`;
|
|
10184
10181
|
void (async () => {
|
|
10185
10182
|
try {
|
|
10186
|
-
const res = await
|
|
10183
|
+
const res = await fetchWithTimeout(url, PROVIDER_EXPORT_TIMEOUT_MS);
|
|
10187
10184
|
if (!res.ok) {
|
|
10188
10185
|
setError("Failed to export providers");
|
|
10189
10186
|
return;
|
|
@@ -10211,7 +10208,7 @@ function ProvidersPanel({
|
|
|
10211
10208
|
void (async () => {
|
|
10212
10209
|
try {
|
|
10213
10210
|
const text = await file.text();
|
|
10214
|
-
const res = await
|
|
10211
|
+
const res = await fetchWithTimeout("/api/providers/import", PROVIDER_IMPORT_TIMEOUT_MS, {
|
|
10215
10212
|
method: "POST",
|
|
10216
10213
|
headers: { "Content-Type": "application/json" },
|
|
10217
10214
|
body: JSON.stringify(text)
|
|
@@ -10511,6 +10508,7 @@ const LogStorageStatsSchema = object({
|
|
|
10511
10508
|
sessionArchiveFileCount: number(),
|
|
10512
10509
|
sessionArchiveBytes: number()
|
|
10513
10510
|
});
|
|
10511
|
+
const STORAGE_STATS_FETCH_TIMEOUT_MS = 1e4;
|
|
10514
10512
|
function formatBytes(bytes) {
|
|
10515
10513
|
if (bytes < 1024) return `${bytes} B`;
|
|
10516
10514
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
@@ -10526,18 +10524,14 @@ function StorageSettingsTab() {
|
|
|
10526
10524
|
setLoading(true);
|
|
10527
10525
|
setError(null);
|
|
10528
10526
|
try {
|
|
10529
|
-
const
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
setError("Storage stats response was not valid.");
|
|
10538
|
-
return;
|
|
10539
|
-
}
|
|
10540
|
-
setStats(parsed.data);
|
|
10527
|
+
const data = await fetchJsonWithTimeout(
|
|
10528
|
+
"/api/logs?stats=1",
|
|
10529
|
+
LogStorageStatsSchema,
|
|
10530
|
+
STORAGE_STATS_FETCH_TIMEOUT_MS,
|
|
10531
|
+
void 0,
|
|
10532
|
+
(response) => `Failed to load storage stats: HTTP ${String(response.status)}`
|
|
10533
|
+
);
|
|
10534
|
+
setStats(data);
|
|
10541
10535
|
} catch (err) {
|
|
10542
10536
|
setError(err instanceof Error ? err.message : String(err));
|
|
10543
10537
|
} finally {
|
|
@@ -11153,6 +11147,28 @@ const EcosystemPackagesResponseSchema = object({
|
|
|
11153
11147
|
packages: array(EcosystemPackageSchema),
|
|
11154
11148
|
runnerPresets: array(EcosystemRunnerPresetSchema)
|
|
11155
11149
|
});
|
|
11150
|
+
const EcosystemTaskActionSchema = _enum(["install", "upgrade", "help", "runner-presets"]);
|
|
11151
|
+
const EcosystemTaskStatusSchema = _enum(["queued", "running", "succeeded", "failed"]);
|
|
11152
|
+
const EcosystemTaskSchema = object({
|
|
11153
|
+
id: string(),
|
|
11154
|
+
packageId: string(),
|
|
11155
|
+
npmName: string(),
|
|
11156
|
+
action: EcosystemTaskActionSchema,
|
|
11157
|
+
status: EcosystemTaskStatusSchema,
|
|
11158
|
+
command: string(),
|
|
11159
|
+
output: string(),
|
|
11160
|
+
createdAt: string(),
|
|
11161
|
+
startedAt: string().nullable(),
|
|
11162
|
+
finishedAt: string().nullable(),
|
|
11163
|
+
exitCode: number().nullable(),
|
|
11164
|
+
error: string().nullable()
|
|
11165
|
+
});
|
|
11166
|
+
const EcosystemTaskResponseSchema = object({
|
|
11167
|
+
task: EcosystemTaskSchema
|
|
11168
|
+
});
|
|
11169
|
+
object({
|
|
11170
|
+
tasks: array(EcosystemTaskSchema)
|
|
11171
|
+
});
|
|
11156
11172
|
const WORKFLOWS = [
|
|
11157
11173
|
{
|
|
11158
11174
|
id: "observe",
|
|
@@ -11195,6 +11211,23 @@ async function fetchEcosystemPackages(url) {
|
|
|
11195
11211
|
(response) => `Failed to load ecosystem packages: ${String(response.status)}`
|
|
11196
11212
|
);
|
|
11197
11213
|
}
|
|
11214
|
+
async function fetchEcosystemTask(url) {
|
|
11215
|
+
return fetchJson(
|
|
11216
|
+
url,
|
|
11217
|
+
EcosystemTaskResponseSchema,
|
|
11218
|
+
void 0,
|
|
11219
|
+
(response) => `Failed to load ecosystem task: ${String(response.status)}`
|
|
11220
|
+
);
|
|
11221
|
+
}
|
|
11222
|
+
async function startEcosystemTask(packageId, action) {
|
|
11223
|
+
const response = await fetchJson(
|
|
11224
|
+
`/api/ecosystem/packages/${encodeURIComponent(packageId)}/${action}`,
|
|
11225
|
+
EcosystemTaskResponseSchema,
|
|
11226
|
+
{ method: "POST" },
|
|
11227
|
+
(result) => `Failed to start ecosystem task: ${String(result.status)}`
|
|
11228
|
+
);
|
|
11229
|
+
return response.task;
|
|
11230
|
+
}
|
|
11198
11231
|
function stateLabel(state) {
|
|
11199
11232
|
switch (state) {
|
|
11200
11233
|
case "installed":
|
|
@@ -11232,15 +11265,57 @@ function versionLabel(pkg) {
|
|
|
11232
11265
|
if (pkg.latestVersion !== null) return `latest v${pkg.latestVersion}`;
|
|
11233
11266
|
return "not published";
|
|
11234
11267
|
}
|
|
11235
|
-
function
|
|
11268
|
+
function taskActionLabel(action) {
|
|
11269
|
+
switch (action) {
|
|
11270
|
+
case "install":
|
|
11271
|
+
return "Install";
|
|
11272
|
+
case "upgrade":
|
|
11273
|
+
return "Upgrade";
|
|
11274
|
+
case "help":
|
|
11275
|
+
return "Help";
|
|
11276
|
+
case "runner-presets":
|
|
11277
|
+
return "Presets";
|
|
11278
|
+
}
|
|
11279
|
+
}
|
|
11280
|
+
function taskStatusLabel(task) {
|
|
11281
|
+
switch (task.status) {
|
|
11282
|
+
case "queued":
|
|
11283
|
+
return "Queued";
|
|
11284
|
+
case "running":
|
|
11285
|
+
return `${taskActionLabel(task.action)} running`;
|
|
11286
|
+
case "succeeded":
|
|
11287
|
+
return `${taskActionLabel(task.action)} complete`;
|
|
11288
|
+
case "failed":
|
|
11289
|
+
return `${taskActionLabel(task.action)} failed`;
|
|
11290
|
+
}
|
|
11291
|
+
}
|
|
11292
|
+
function packagePrimaryAction(pkg) {
|
|
11293
|
+
switch (pkg.state) {
|
|
11294
|
+
case "available":
|
|
11295
|
+
return "install";
|
|
11296
|
+
case "update-available":
|
|
11297
|
+
return "upgrade";
|
|
11298
|
+
case "installed":
|
|
11299
|
+
case "planned":
|
|
11300
|
+
case "unknown":
|
|
11301
|
+
return null;
|
|
11302
|
+
}
|
|
11303
|
+
}
|
|
11304
|
+
function PackageStatusCard({
|
|
11305
|
+
pkg,
|
|
11306
|
+
activeTask,
|
|
11307
|
+
onStartTask
|
|
11308
|
+
}) {
|
|
11309
|
+
const primaryAction = packagePrimaryAction(pkg);
|
|
11310
|
+
const packageTaskRunning = activeTask !== null && activeTask.packageId === pkg.id && activeTask.status === "running";
|
|
11236
11311
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg bg-white/[0.025] p-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]", children: [
|
|
11237
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
11312
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
11238
11313
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11239
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-
|
|
11314
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
|
|
11240
11315
|
/* @__PURE__ */ jsxRuntimeExports.jsx(PackageCheck, { className: "size-4 shrink-0 text-white/55" }),
|
|
11241
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "
|
|
11316
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold leading-snug", children: pkg.name })
|
|
11242
11317
|
] }),
|
|
11243
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1
|
|
11318
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-1 break-all font-mono text-[11px] leading-snug text-white/35", children: pkg.npmName })
|
|
11244
11319
|
] }),
|
|
11245
11320
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { className: cn("shrink-0", stateClassName(pkg.state)), variant: "outline", children: stateLabel(pkg.state) })
|
|
11246
11321
|
] }),
|
|
@@ -11249,16 +11324,88 @@ function PackageStatusCard({ pkg }) {
|
|
|
11249
11324
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-white/[0.035] px-2 py-1 font-mono text-white/50", children: versionLabel(pkg) }),
|
|
11250
11325
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-white/[0.035] px-2 py-1 text-white/45", children: pkg.capability }),
|
|
11251
11326
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-white/[0.035] px-2 py-1 font-mono text-white/35", children: pkg.installCommand })
|
|
11327
|
+
] }),
|
|
11328
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
|
|
11329
|
+
primaryAction !== null && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11330
|
+
Button,
|
|
11331
|
+
{
|
|
11332
|
+
type: "button",
|
|
11333
|
+
size: "sm",
|
|
11334
|
+
variant: "secondary",
|
|
11335
|
+
disabled: packageTaskRunning,
|
|
11336
|
+
onClick: () => onStartTask(pkg.id, primaryAction),
|
|
11337
|
+
children: [
|
|
11338
|
+
packageTaskRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "size-3.5" }),
|
|
11339
|
+
taskActionLabel(primaryAction)
|
|
11340
|
+
]
|
|
11341
|
+
}
|
|
11342
|
+
),
|
|
11343
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11344
|
+
Button,
|
|
11345
|
+
{
|
|
11346
|
+
type: "button",
|
|
11347
|
+
size: "sm",
|
|
11348
|
+
variant: "outline",
|
|
11349
|
+
disabled: packageTaskRunning || pkg.state === "planned",
|
|
11350
|
+
onClick: () => onStartTask(pkg.id, "help"),
|
|
11351
|
+
children: [
|
|
11352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-3.5" }),
|
|
11353
|
+
"Help"
|
|
11354
|
+
]
|
|
11355
|
+
}
|
|
11356
|
+
),
|
|
11357
|
+
pkg.id === "eval-harness" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11358
|
+
Button,
|
|
11359
|
+
{
|
|
11360
|
+
type: "button",
|
|
11361
|
+
size: "sm",
|
|
11362
|
+
variant: "ghost",
|
|
11363
|
+
disabled: packageTaskRunning || pkg.state === "planned",
|
|
11364
|
+
onClick: () => onStartTask(pkg.id, "runner-presets"),
|
|
11365
|
+
children: [
|
|
11366
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Beaker, { className: "size-3.5" }),
|
|
11367
|
+
"Presets"
|
|
11368
|
+
]
|
|
11369
|
+
}
|
|
11370
|
+
)
|
|
11252
11371
|
] })
|
|
11253
11372
|
] });
|
|
11254
11373
|
}
|
|
11374
|
+
function TaskConsole({ task }) {
|
|
11375
|
+
if (task === null) return null;
|
|
11376
|
+
const isRunning = task.status === "queued" || task.status === "running";
|
|
11377
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "mt-3 rounded-lg bg-white/[0.025] p-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]", children: [
|
|
11378
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
|
|
11379
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
11380
|
+
isRunning ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 animate-spin text-cyan-200/75" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Terminal, { className: "size-4 text-white/55" }),
|
|
11381
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11382
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: taskStatusLabel(task) }),
|
|
11383
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "break-all font-mono text-[11px] text-white/35", children: task.command })
|
|
11384
|
+
] })
|
|
11385
|
+
] }),
|
|
11386
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11387
|
+
Badge,
|
|
11388
|
+
{
|
|
11389
|
+
variant: "outline",
|
|
11390
|
+
className: cn(
|
|
11391
|
+
"shrink-0",
|
|
11392
|
+
task.status === "failed" ? "border-red-400/20 bg-red-400/8 text-red-100" : "border-cyan-300/20 bg-cyan-300/8 text-cyan-100"
|
|
11393
|
+
),
|
|
11394
|
+
children: task.status
|
|
11395
|
+
}
|
|
11396
|
+
)
|
|
11397
|
+
] }),
|
|
11398
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "mt-3 max-h-56 overflow-auto whitespace-pre-wrap rounded-md bg-black/30 p-3 font-mono text-[11px] leading-5 text-white/60 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.045)]", children: task.output.trim().length > 0 ? task.output : "Waiting for npm output..." }),
|
|
11399
|
+
task.error !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 text-xs text-red-100", children: task.error })
|
|
11400
|
+
] });
|
|
11401
|
+
}
|
|
11255
11402
|
function WorkflowTile({ workflow }) {
|
|
11256
11403
|
const Icon2 = workflow.icon;
|
|
11257
11404
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg bg-white/[0.025] p-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]", children: [
|
|
11258
11405
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
11259
11406
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
11260
11407
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Icon2, { className: "size-4 shrink-0 text-cyan-200/75" }),
|
|
11261
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "
|
|
11408
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold", children: workflow.title })
|
|
11262
11409
|
] }),
|
|
11263
11410
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "rounded bg-white/[0.04] px-2 py-0.5 font-mono text-[10px] text-white/45", children: workflow.label })
|
|
11264
11411
|
] }),
|
|
@@ -11274,13 +11421,13 @@ function buildSessionCommand(sessionId) {
|
|
|
11274
11421
|
}
|
|
11275
11422
|
function RunnerPresetCard({ preset }) {
|
|
11276
11423
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg bg-white/[0.025] p-3 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]", children: [
|
|
11277
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
11424
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
11278
11425
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
|
|
11279
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-
|
|
11426
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
|
|
11280
11427
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Rocket, { className: "size-4 shrink-0 text-cyan-200/75" }),
|
|
11281
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "
|
|
11428
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-semibold leading-snug", children: preset.name })
|
|
11282
11429
|
] }),
|
|
11283
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 font-mono text-[11px] text-white/35", children: [
|
|
11430
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 break-all font-mono text-[11px] leading-snug text-white/35", children: [
|
|
11284
11431
|
preset.binary,
|
|
11285
11432
|
" ",
|
|
11286
11433
|
preset.modelFlag,
|
|
@@ -11307,10 +11454,23 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
11307
11454
|
const [open, setOpen] = reactExports.useState(false);
|
|
11308
11455
|
const [copied, setCopied] = reactExports.useState(false);
|
|
11309
11456
|
const [copiedPresets, setCopiedPresets] = reactExports.useState(false);
|
|
11457
|
+
const [activeTaskId, setActiveTaskId] = reactExports.useState(null);
|
|
11458
|
+
const [taskError, setTaskError] = reactExports.useState(null);
|
|
11310
11459
|
const response = useSWR("/api/ecosystem/packages", fetchEcosystemPackages, {
|
|
11311
11460
|
revalidateOnFocus: false,
|
|
11312
11461
|
revalidateIfStale: false
|
|
11313
11462
|
});
|
|
11463
|
+
const activeTaskResponse = useSWR(
|
|
11464
|
+
activeTaskId === null ? null : `/api/ecosystem/tasks/${activeTaskId}`,
|
|
11465
|
+
fetchEcosystemTask,
|
|
11466
|
+
{
|
|
11467
|
+
refreshInterval: (taskResponse) => {
|
|
11468
|
+
const task = taskResponse?.task;
|
|
11469
|
+
return task !== void 0 && (task.status === "queued" || task.status === "running") ? 900 : 0;
|
|
11470
|
+
},
|
|
11471
|
+
revalidateOnFocus: false
|
|
11472
|
+
}
|
|
11473
|
+
);
|
|
11314
11474
|
const packages = response.data?.packages ?? [];
|
|
11315
11475
|
const runnerPresets = response.data?.runnerPresets ?? [];
|
|
11316
11476
|
const installedCount = reactExports.useMemo(
|
|
@@ -11331,6 +11491,21 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
11331
11491
|
window.setTimeout(() => setCopiedPresets(false), 1200);
|
|
11332
11492
|
});
|
|
11333
11493
|
};
|
|
11494
|
+
const activeTask = activeTaskResponse.data?.task ?? null;
|
|
11495
|
+
reactExports.useEffect(() => {
|
|
11496
|
+
if (activeTask === null) return;
|
|
11497
|
+
if (activeTask.status !== "succeeded") return;
|
|
11498
|
+
void response.mutate();
|
|
11499
|
+
}, [activeTask, response]);
|
|
11500
|
+
const handleStartTask = (packageId, action) => {
|
|
11501
|
+
setTaskError(null);
|
|
11502
|
+
void startEcosystemTask(packageId, action).then((task) => {
|
|
11503
|
+
setActiveTaskId(task.id);
|
|
11504
|
+
void activeTaskResponse.mutate({ task }, { revalidate: true });
|
|
11505
|
+
}).catch((error) => {
|
|
11506
|
+
setTaskError(error instanceof Error ? error.message : "Failed to start ecosystem task");
|
|
11507
|
+
});
|
|
11508
|
+
};
|
|
11334
11509
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(Dialog, { open, onOpenChange: setOpen, children: [
|
|
11335
11510
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
11336
11511
|
Button,
|
|
@@ -11418,7 +11593,15 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
11418
11593
|
] }),
|
|
11419
11594
|
response.error !== void 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-lg bg-red-500/8 p-3 text-xs text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: "Package status is temporarily unavailable." }),
|
|
11420
11595
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-3 md:grid-cols-3", children: [
|
|
11421
|
-
packages.map((pkg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11596
|
+
packages.map((pkg) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11597
|
+
PackageStatusCard,
|
|
11598
|
+
{
|
|
11599
|
+
pkg,
|
|
11600
|
+
activeTask,
|
|
11601
|
+
onStartTask: handleStartTask
|
|
11602
|
+
},
|
|
11603
|
+
pkg.id
|
|
11604
|
+
)),
|
|
11422
11605
|
response.isLoading && packages.length === 0 && [0, 1, 2].map((index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
11423
11606
|
"div",
|
|
11424
11607
|
{
|
|
@@ -11427,7 +11610,9 @@ function AgentLabDialog({ currentSessionId, logCount }) {
|
|
|
11427
11610
|
index
|
|
11428
11611
|
))
|
|
11429
11612
|
] })
|
|
11430
|
-
] })
|
|
11613
|
+
] }),
|
|
11614
|
+
taskError !== null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 rounded-lg bg-red-500/8 p-3 text-xs text-red-100 shadow-[inset_0_0_0_1px_rgba(248,113,113,0.16)]", children: taskError }),
|
|
11615
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(TaskConsole, { task: activeTask })
|
|
11431
11616
|
] })
|
|
11432
11617
|
] })
|
|
11433
11618
|
] });
|
|
@@ -13830,12 +14015,12 @@ function BrandHeader({
|
|
|
13830
14015
|
}) {
|
|
13831
14016
|
if (compact) {
|
|
13832
14017
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_16px_44px_rgba(0,0,0,0.18)] rounded-[8px] p-3", children: [
|
|
13833
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
13834
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-
|
|
14018
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
14019
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit items-start gap-2", children: [
|
|
13835
14020
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: true, entrancePhase: crabEntrancePhase }),
|
|
13836
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-
|
|
13837
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-
|
|
13838
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
14021
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-fit", children: [
|
|
14022
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex min-w-fit flex-wrap items-baseline gap-x-2 gap-y-0.5", children: [
|
|
14023
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-base font-bold", children: "Agent Inspector" }),
|
|
13839
14024
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "hidden shrink-0 font-mono text-[11px] font-semibold text-muted-foreground sm:inline", children: [
|
|
13840
14025
|
"v",
|
|
13841
14026
|
packageJson.version
|
|
@@ -13854,13 +14039,13 @@ function BrandHeader({
|
|
|
13854
14039
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-2 hidden sm:block", children: /* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {}) })
|
|
13855
14040
|
] });
|
|
13856
14041
|
}
|
|
13857
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
13858
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
|
|
13859
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-
|
|
13860
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-
|
|
14042
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-3 pb-6", children: [
|
|
14043
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-10 flex-1", "aria-hidden": "true" }),
|
|
14044
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { className: "flex min-w-fit flex-col items-center gap-2 text-center", children: [
|
|
14045
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex max-w-full flex-wrap items-end justify-center gap-x-2 gap-y-1", children: [
|
|
13861
14046
|
/* @__PURE__ */ jsxRuntimeExports.jsx(CrabFamily, { compact: false, entrancePhase: crabEntrancePhase }),
|
|
13862
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-
|
|
13863
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "
|
|
14047
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex min-w-fit flex-wrap items-baseline justify-center gap-x-2 gap-y-0.5 pl-1", children: [
|
|
14048
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "whitespace-nowrap text-lg font-bold", children: "Agent Inspector" }),
|
|
13864
14049
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "shrink-0 font-mono text-xs font-semibold text-muted-foreground", children: [
|
|
13865
14050
|
"v",
|
|
13866
14051
|
packageJson.version
|
|
@@ -13869,10 +14054,10 @@ function BrandHeader({
|
|
|
13869
14054
|
/* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-4 shrink-0 text-muted-foreground/70", "aria-hidden": "true" }),
|
|
13870
14055
|
/* @__PURE__ */ jsxRuntimeExports.jsx(McpLogo, { className: "size-10 shrink-0" })
|
|
13871
14056
|
] }),
|
|
13872
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-
|
|
14057
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "max-w-full text-sm font-semibold text-muted-foreground", children: "Local First. Evidence First." }),
|
|
13873
14058
|
/* @__PURE__ */ jsxRuntimeExports.jsx(McpReadyBadge, {})
|
|
13874
14059
|
] }),
|
|
13875
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "
|
|
14060
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 justify-end gap-1", children: [
|
|
13876
14061
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AlertsDialog, {}),
|
|
13877
14062
|
/* @__PURE__ */ jsxRuntimeExports.jsx(GroupsDialog, {}),
|
|
13878
14063
|
/* @__PURE__ */ jsxRuntimeExports.jsx(AgentLabDialog, { currentSessionId, logCount }),
|
|
@@ -14206,7 +14391,24 @@ function ProxyViewer({
|
|
|
14206
14391
|
const logListRef = reactExports.useRef(null);
|
|
14207
14392
|
const logListWrapperRef = reactExports.useRef(null);
|
|
14208
14393
|
const importInputRef = reactExports.useRef(null);
|
|
14394
|
+
const exportAbortRef = reactExports.useRef(null);
|
|
14395
|
+
const exportRequestIdRef = reactExports.useRef(0);
|
|
14209
14396
|
useKeyboardNavigation(logListRef, logListWrapperRef, { pageWide: true });
|
|
14397
|
+
const cancelTransientTasks = reactExports.useCallback(() => {
|
|
14398
|
+
exportRequestIdRef.current += 1;
|
|
14399
|
+
exportAbortRef.current?.abort();
|
|
14400
|
+
exportAbortRef.current = null;
|
|
14401
|
+
setExporting(null);
|
|
14402
|
+
setExportError(null);
|
|
14403
|
+
}, []);
|
|
14404
|
+
reactExports.useEffect(
|
|
14405
|
+
() => () => {
|
|
14406
|
+
exportRequestIdRef.current += 1;
|
|
14407
|
+
exportAbortRef.current?.abort();
|
|
14408
|
+
exportAbortRef.current = null;
|
|
14409
|
+
},
|
|
14410
|
+
[]
|
|
14411
|
+
);
|
|
14210
14412
|
reactExports.useEffect(() => {
|
|
14211
14413
|
const perCrabDuration = 400;
|
|
14212
14414
|
const startDelay = 50;
|
|
@@ -14228,11 +14430,18 @@ function ProxyViewer({
|
|
|
14228
14430
|
}, [logs.length, pinnedSessionId]);
|
|
14229
14431
|
const handleExport = reactExports.useCallback(
|
|
14230
14432
|
async (mode) => {
|
|
14433
|
+
exportAbortRef.current?.abort();
|
|
14434
|
+
const controller = new AbortController();
|
|
14435
|
+
exportAbortRef.current = controller;
|
|
14436
|
+
const requestId = exportRequestIdRef.current + 1;
|
|
14437
|
+
exportRequestIdRef.current = requestId;
|
|
14231
14438
|
setExporting(mode);
|
|
14232
14439
|
setExportError(null);
|
|
14233
14440
|
try {
|
|
14234
|
-
const result = await exportLogsAsZip(logs, mode);
|
|
14441
|
+
const result = await exportLogsAsZip(logs, mode, { signal: controller.signal });
|
|
14442
|
+
if (exportRequestIdRef.current !== requestId) return;
|
|
14235
14443
|
if (!result.ok) {
|
|
14444
|
+
if (result.canceled === true) return;
|
|
14236
14445
|
if (onNotify !== void 0) {
|
|
14237
14446
|
onNotify({ message: result.message, tone: "error" });
|
|
14238
14447
|
} else {
|
|
@@ -14240,7 +14449,10 @@ function ProxyViewer({
|
|
|
14240
14449
|
}
|
|
14241
14450
|
}
|
|
14242
14451
|
} finally {
|
|
14243
|
-
|
|
14452
|
+
if (exportRequestIdRef.current === requestId) {
|
|
14453
|
+
exportAbortRef.current = null;
|
|
14454
|
+
setExporting(null);
|
|
14455
|
+
}
|
|
14244
14456
|
}
|
|
14245
14457
|
},
|
|
14246
14458
|
[logs, onNotify]
|
|
@@ -14278,8 +14490,24 @@ function ProxyViewer({
|
|
|
14278
14490
|
[onImportLogs, onNotify]
|
|
14279
14491
|
);
|
|
14280
14492
|
reactExports.useEffect(() => {
|
|
14493
|
+
cancelTransientTasks();
|
|
14281
14494
|
setComparePair(null);
|
|
14282
|
-
}, [selectedSession, selectedModel]);
|
|
14495
|
+
}, [cancelTransientTasks, selectedSession, selectedModel]);
|
|
14496
|
+
const handleClearCurrentView = reactExports.useCallback(() => {
|
|
14497
|
+
cancelTransientTasks();
|
|
14498
|
+
setImportStatus(null);
|
|
14499
|
+
setImportError(null);
|
|
14500
|
+
setComparePair(null);
|
|
14501
|
+
onClearAll();
|
|
14502
|
+
}, [cancelTransientTasks, onClearAll]);
|
|
14503
|
+
const handleReloadCurrentSession = reactExports.useCallback(() => {
|
|
14504
|
+
if (onReloadSession === void 0) return;
|
|
14505
|
+
cancelTransientTasks();
|
|
14506
|
+
setImportStatus(null);
|
|
14507
|
+
setImportError(null);
|
|
14508
|
+
setComparePair(null);
|
|
14509
|
+
onReloadSession();
|
|
14510
|
+
}, [cancelTransientTasks, onReloadSession]);
|
|
14283
14511
|
const closeCompare = reactExports.useCallback(() => {
|
|
14284
14512
|
setComparePair(null);
|
|
14285
14513
|
}, []);
|
|
@@ -14376,7 +14604,7 @@ function ProxyViewer({
|
|
|
14376
14604
|
"button",
|
|
14377
14605
|
{
|
|
14378
14606
|
type: "button",
|
|
14379
|
-
onClick:
|
|
14607
|
+
onClick: handleReloadCurrentSession,
|
|
14380
14608
|
disabled: isLoading,
|
|
14381
14609
|
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14382
14610
|
title: "Load stored logs for this session",
|
|
@@ -14390,7 +14618,7 @@ function ProxyViewer({
|
|
|
14390
14618
|
"button",
|
|
14391
14619
|
{
|
|
14392
14620
|
type: "button",
|
|
14393
|
-
onClick:
|
|
14621
|
+
onClick: handleClearCurrentView,
|
|
14394
14622
|
disabled: !canClearCurrentView,
|
|
14395
14623
|
className: cn(
|
|
14396
14624
|
"bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 min-w-0 items-center justify-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
@@ -14547,7 +14775,7 @@ function ProxyViewer({
|
|
|
14547
14775
|
"button",
|
|
14548
14776
|
{
|
|
14549
14777
|
type: "button",
|
|
14550
|
-
onClick:
|
|
14778
|
+
onClick: handleReloadCurrentSession,
|
|
14551
14779
|
disabled: isLoading,
|
|
14552
14780
|
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14553
14781
|
title: "Reload this session from stored logs",
|
|
@@ -14561,7 +14789,7 @@ function ProxyViewer({
|
|
|
14561
14789
|
"button",
|
|
14562
14790
|
{
|
|
14563
14791
|
type: "button",
|
|
14564
|
-
onClick:
|
|
14792
|
+
onClick: handleClearCurrentView,
|
|
14565
14793
|
disabled: !canClearCurrentView,
|
|
14566
14794
|
className: "bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
14567
14795
|
title: "Clear the current view. Stored logs remain reloadable.",
|
|
@@ -14590,7 +14818,7 @@ function ProxyViewer({
|
|
|
14590
14818
|
"button",
|
|
14591
14819
|
{
|
|
14592
14820
|
type: "button",
|
|
14593
|
-
onClick:
|
|
14821
|
+
onClick: handleReloadCurrentSession,
|
|
14594
14822
|
className: "bg-white/[0.045] hover:bg-white/[0.075] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground",
|
|
14595
14823
|
children: [
|
|
14596
14824
|
/* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" }),
|
|
@@ -14732,6 +14960,8 @@ const HASH_HIGHLIGHT_MS = 1800;
|
|
|
14732
14960
|
const SESSION_PAGE_LIMIT = 100;
|
|
14733
14961
|
const SESSION_RELOAD_PAGE_LIMIT = 500;
|
|
14734
14962
|
const MAX_SESSION_RELOAD_PAGES = 200;
|
|
14963
|
+
const SESSION_LOGS_FETCH_TIMEOUT_MS = 2e4;
|
|
14964
|
+
const SESSION_MEMBERSHIP_FETCH_TIMEOUT_MS = 1e4;
|
|
14735
14965
|
function buildLogsStreamUrl(sessionId) {
|
|
14736
14966
|
const params = new URLSearchParams();
|
|
14737
14967
|
if (sessionId !== void 0) {
|
|
@@ -14769,6 +14999,13 @@ function buildLogIndex(logs) {
|
|
|
14769
14999
|
}
|
|
14770
15000
|
return idx;
|
|
14771
15001
|
}
|
|
15002
|
+
function fetchSessionLogsPage(sessionId, request, limit = SESSION_PAGE_LIMIT) {
|
|
15003
|
+
return fetchJsonWithTimeout(
|
|
15004
|
+
buildSessionLogsPageUrl(sessionId, request, limit),
|
|
15005
|
+
LogCursorPageSchema,
|
|
15006
|
+
SESSION_LOGS_FETCH_TIMEOUT_MS
|
|
15007
|
+
);
|
|
15008
|
+
}
|
|
14772
15009
|
function mergeLogsById(previousLogs, incomingLogs) {
|
|
14773
15010
|
if (incomingLogs.length === 0) return [...previousLogs];
|
|
14774
15011
|
const byId = /* @__PURE__ */ new Map();
|
|
@@ -14912,7 +15149,7 @@ function ProxyViewerContainer({
|
|
|
14912
15149
|
sessionPageRequestIdRef.current = requestId;
|
|
14913
15150
|
setSessionPageLoading(true);
|
|
14914
15151
|
dismissToast();
|
|
14915
|
-
void
|
|
15152
|
+
void fetchSessionLogsPage(initialSessionId, request).then((page) => {
|
|
14916
15153
|
if (sessionPageRequestIdRef.current !== requestId) return;
|
|
14917
15154
|
const nextLogs = page.logs;
|
|
14918
15155
|
logIndexRef.current = buildLogIndex(nextLogs);
|
|
@@ -14939,20 +15176,18 @@ function ProxyViewerContainer({
|
|
|
14939
15176
|
dismissToast();
|
|
14940
15177
|
void (async () => {
|
|
14941
15178
|
const collected = [];
|
|
14942
|
-
let page = await
|
|
14943
|
-
|
|
14944
|
-
|
|
15179
|
+
let page = await fetchSessionLogsPage(
|
|
15180
|
+
sessionId,
|
|
15181
|
+
{ kind: "oldest" },
|
|
15182
|
+
SESSION_RELOAD_PAGE_LIMIT
|
|
14945
15183
|
);
|
|
14946
15184
|
collected.push(...page.logs);
|
|
14947
15185
|
let loadedPages = 1;
|
|
14948
15186
|
while (page.hasNewer && page.newestLogId !== null && loadedPages < MAX_SESSION_RELOAD_PAGES) {
|
|
14949
|
-
page = await
|
|
14950
|
-
|
|
14951
|
-
|
|
14952
|
-
|
|
14953
|
-
SESSION_RELOAD_PAGE_LIMIT
|
|
14954
|
-
),
|
|
14955
|
-
LogCursorPageSchema
|
|
15187
|
+
page = await fetchSessionLogsPage(
|
|
15188
|
+
sessionId,
|
|
15189
|
+
{ kind: "newer", afterLogId: page.newestLogId },
|
|
15190
|
+
SESSION_RELOAD_PAGE_LIMIT
|
|
14956
15191
|
);
|
|
14957
15192
|
collected.push(...page.logs);
|
|
14958
15193
|
loadedPages += 1;
|
|
@@ -14987,12 +15222,11 @@ function ProxyViewerContainer({
|
|
|
14987
15222
|
return;
|
|
14988
15223
|
}
|
|
14989
15224
|
let cancelled = false;
|
|
14990
|
-
void
|
|
14991
|
-
|
|
14992
|
-
|
|
14993
|
-
|
|
14994
|
-
|
|
14995
|
-
}).then((groups) => {
|
|
15225
|
+
void fetchJsonWithTimeout(
|
|
15226
|
+
"/api/groups",
|
|
15227
|
+
InspectorGroupsListResponseSchema,
|
|
15228
|
+
SESSION_MEMBERSHIP_FETCH_TIMEOUT_MS
|
|
15229
|
+
).then((response) => response.groups).then((groups) => {
|
|
14996
15230
|
if (cancelled || groups === null) return;
|
|
14997
15231
|
setSessionMemberships(buildSessionMembershipEvidence(groups, initialSessionId));
|
|
14998
15232
|
}).catch(() => {
|
|
@@ -15219,13 +15453,15 @@ function ProxyViewerContainer({
|
|
|
15219
15453
|
] });
|
|
15220
15454
|
}
|
|
15221
15455
|
export {
|
|
15222
|
-
|
|
15456
|
+
ApiTimeoutError as A,
|
|
15223
15457
|
Badge as B,
|
|
15224
15458
|
CONTEXT_USAGE_THRESHOLDS as C,
|
|
15225
15459
|
Dialog as D,
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
|
|
15460
|
+
CollapsibleContent as E,
|
|
15461
|
+
ScrollArea as F,
|
|
15462
|
+
LazyJsonViewer as G,
|
|
15463
|
+
safeJsonValue as H,
|
|
15464
|
+
parseJsonText as I,
|
|
15229
15465
|
LazyJsonViewerFromString as L,
|
|
15230
15466
|
ProxyViewerContainer as P,
|
|
15231
15467
|
ROLE_COLOR_CLASSES as R,
|
|
@@ -15234,27 +15470,27 @@ export {
|
|
|
15234
15470
|
getConversationId as a,
|
|
15235
15471
|
copyTextToClipboard as b,
|
|
15236
15472
|
cn as c,
|
|
15237
|
-
|
|
15238
|
-
|
|
15473
|
+
fetchJsonWithTimeout as d,
|
|
15474
|
+
DialogContent as e,
|
|
15239
15475
|
formatTokens as f,
|
|
15240
15476
|
getLogFormatAdapter as g,
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15477
|
+
DialogHeader as h,
|
|
15478
|
+
DialogTitle as i,
|
|
15479
|
+
TabsList as j,
|
|
15480
|
+
TabsTrigger as k,
|
|
15481
|
+
TabsContent as l,
|
|
15482
|
+
Button as m,
|
|
15483
|
+
TooltipProvider as n,
|
|
15484
|
+
Tooltip as o,
|
|
15485
|
+
TooltipTrigger as p,
|
|
15486
|
+
TooltipContent as q,
|
|
15251
15487
|
resolveLogFormat as r,
|
|
15252
|
-
|
|
15253
|
-
|
|
15488
|
+
dispatchLogFocusRequest as s,
|
|
15489
|
+
analyzeContextIntelligence as t,
|
|
15254
15490
|
useProviders as u,
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15491
|
+
ANATOMY_ROLE_LABELS as v,
|
|
15492
|
+
formatContextWindowTokens as w,
|
|
15493
|
+
getStatusCategory as x,
|
|
15494
|
+
Collapsible as y,
|
|
15495
|
+
CollapsibleTrigger as z
|
|
15260
15496
|
};
|