@tonyclaw/agent-inspector 4.0.1 → 4.0.3
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/backend/nitro.json +1 -1
- package/.output/cli.js +193 -110
- package/.output/server/_ssr/index.mjs +1 -1
- package/.output/server/_ssr/{router-CTHqmroT.mjs → router-ChILzhmz.mjs} +92 -4
- package/.output/server/index.mjs +1 -1
- package/.output/ui/assets/{CompareDrawer-L3n4J-Or.js → CompareDrawer-Co3cUF_I.js} +1 -1
- package/.output/ui/assets/{InspectorPet-D5o_3OZS.js → InspectorPet-jFcrL37X.js} +1 -1
- package/.output/ui/assets/{ProxyViewerContainer-Ocagx75S.js → ProxyViewerContainer-BPzt_VpM.js} +4 -4
- package/.output/ui/assets/{ReplayDialog-Bk7x1h-y.js → ReplayDialog-C6O_zuwI.js} +1 -1
- package/.output/ui/assets/{RequestAnatomy-U4lzL7Sc.js → RequestAnatomy-Ca6NvB7L.js} +1 -1
- package/.output/ui/assets/{ResponseView-LOWfvBLK.js → ResponseView-BzqKcveJ.js} +1 -1
- package/.output/ui/assets/{StreamingChunkSequence-DPfsrrXQ.js → StreamingChunkSequence-9pCZIsS_.js} +1 -1
- package/.output/ui/assets/{_sessionId-0MlWS-CO.js → _sessionId-BMP3KVGR.js} +1 -1
- package/.output/ui/assets/{_sessionId-OdX2Jvt1.js → _sessionId-y4eRoT1H.js} +1 -1
- package/.output/ui/assets/{index-Ea-c8hPg.js → index-CH5w-haG.js} +1 -1
- package/.output/ui/assets/{index-zVVS53Hd.js → index-CmocEhyU.js} +1 -1
- package/.output/ui/assets/{index-Du4qNOOt.js → index-DT8sMJ_n.js} +2 -2
- package/.output/ui/assets/{index-gvFj_9K6.js → index-bfsbIRZa.js} +1 -1
- package/.output/ui/assets/{json-viewer-C1WAMzg3.js → json-viewer-BfFOSDG5.js} +1 -1
- package/.output/ui/assets/{jszip.min-B8AKu2zm.js → jszip.min-BkbVkOsp.js} +1 -1
- package/.output/ui/index.html +1 -1
- package/package.json +5 -10
- package/src/assets/IDE/claudecode-color.svg +0 -1
- package/src/assets/IDE/codex-color.svg +0 -1
- package/src/assets/IDE/opencode.svg +0 -1
- package/src/assets/IDE/xiaomimimo.svg +0 -1
- package/src/assets/favicon.svg +0 -21
- package/src/assets/logos/alibaba.svg +0 -1
- package/src/assets/logos/anthropic.svg +0 -1
- package/src/assets/logos/claude-code.svg +0 -4
- package/src/assets/logos/deepseek.svg +0 -1
- package/src/assets/logos/minimax.jpeg +0 -0
- package/src/assets/logos/openai.svg +0 -1
- package/src/assets/logos/opencode.svg +0 -4
- package/src/assets/logos/qwen.webp +0 -0
- package/src/assets/logos/zhipuai.svg +0 -219
- package/src/backend/router.tsx +0 -36
- package/src/backend/routes/$.ts +0 -26
- package/src/backend/routes/__root.ts +0 -4
- package/src/backend/routes/api/-instances.ts +0 -7
- package/src/backend/routes/api/alerts.summary.ts +0 -28
- package/src/backend/routes/api/alerts.ts +0 -70
- package/src/backend/routes/api/config.paths.ts +0 -14
- package/src/backend/routes/api/config.ts +0 -73
- package/src/backend/routes/api/ecosystem.packages.$packageId.help.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.install.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.runner-presets.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.upgrade.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.ts +0 -21
- package/src/backend/routes/api/ecosystem.recipes.$recipeId.run.ts +0 -11
- package/src/backend/routes/api/ecosystem.tasks.$taskId.ts +0 -16
- package/src/backend/routes/api/ecosystem.tasks.ts +0 -12
- package/src/backend/routes/api/groups.$groupId.evidence.ts +0 -55
- package/src/backend/routes/api/groups.$groupId.sessions.ts +0 -50
- package/src/backend/routes/api/groups.$groupId.ts +0 -93
- package/src/backend/routes/api/groups.ts +0 -79
- package/src/backend/routes/api/health.ts +0 -22
- package/src/backend/routes/api/instances.$name.connection.ts +0 -12
- package/src/backend/routes/api/instances.$name.restart.ts +0 -23
- package/src/backend/routes/api/instances.$name.start.ts +0 -18
- package/src/backend/routes/api/instances.$name.stop.ts +0 -23
- package/src/backend/routes/api/instances.$name.ts +0 -12
- package/src/backend/routes/api/instances.ts +0 -16
- package/src/backend/routes/api/knowledge.candidates.$candidateId.promote.ts +0 -32
- package/src/backend/routes/api/knowledge.candidates.$candidateId.ts +0 -50
- package/src/backend/routes/api/knowledge.candidates.ts +0 -10
- package/src/backend/routes/api/knowledge.project-context.ts +0 -29
- package/src/backend/routes/api/knowledge.search.ts +0 -62
- package/src/backend/routes/api/knowledge.sessions.$sessionId.candidates.ts +0 -26
- package/src/backend/routes/api/logs.$id.body.ts +0 -58
- package/src/backend/routes/api/logs.$id.chunks.ts +0 -37
- package/src/backend/routes/api/logs.$id.replay.ts +0 -297
- package/src/backend/routes/api/logs.$id.ts +0 -23
- package/src/backend/routes/api/logs.import.ts +0 -39
- package/src/backend/routes/api/logs.stream.ts +0 -174
- package/src/backend/routes/api/logs.ts +0 -214
- package/src/backend/routes/api/mcp.ts +0 -25
- package/src/backend/routes/api/models.ts +0 -10
- package/src/backend/routes/api/pi-agent.ts +0 -29
- package/src/backend/routes/api/providers.$providerId.model-metadata.ts +0 -173
- package/src/backend/routes/api/providers.$providerId.test.log.ts +0 -342
- package/src/backend/routes/api/providers.$providerId.ts +0 -111
- package/src/backend/routes/api/providers.export.ts +0 -44
- package/src/backend/routes/api/providers.import.ts +0 -81
- package/src/backend/routes/api/providers.scan.ts +0 -28
- package/src/backend/routes/api/providers.ts +0 -102
- package/src/backend/routes/api/runs.$runId.evidence.ts +0 -55
- package/src/backend/routes/api/runs.$runId.ts +0 -50
- package/src/backend/routes/api/runs.ts +0 -62
- package/src/backend/routes/api/runtime.ts +0 -46
- package/src/backend/routes/api/sessions.ts +0 -51
- package/src/backend/routes/api/storage.ts +0 -56
- package/src/backend/routes/livez.ts +0 -13
- package/src/backend/routes/metrics.ts +0 -14
- package/src/backend/routes/proxy/$.ts +0 -15
- package/src/backend/routes/readyz.ts +0 -18
- package/src/backend/start.ts +0 -10
- package/src/cli/alias.ts +0 -431
- package/src/cli/detect-tools.ts +0 -123
- package/src/cli/doctor.ts +0 -836
- package/src/cli/instance.ts +0 -1071
- package/src/cli/instanceApi.ts +0 -213
- package/src/cli/instanceArgs.ts +0 -301
- package/src/cli/instanceControl.ts +0 -191
- package/src/cli/instanceModel.ts +0 -276
- package/src/cli/instanceRegistry.ts +0 -731
- package/src/cli/networkHints.ts +0 -170
- package/src/cli/onboard.ts +0 -1668
- package/src/cli/onboardTarget.ts +0 -228
- package/src/cli/rustBackendPackage.ts +0 -458
- package/src/cli/startupOutput.ts +0 -16
- package/src/cli/templates/codex-skill-onboard.ts +0 -320
- package/src/cli/templates/command-onboard.ts +0 -25
- package/src/cli/templates/skill-onboard.ts +0 -625
- package/src/cli.ts +0 -1433
- package/src/components/OnboardingBanner.tsx +0 -115
- package/src/components/ProxyViewer.tsx +0 -2259
- package/src/components/ProxyViewerContainer.tsx +0 -1076
- package/src/components/alerts/AlertsDialog.tsx +0 -615
- package/src/components/clients/ClientLogo.tsx +0 -175
- package/src/components/ecosystem/AgentLabDialog.tsx +0 -947
- package/src/components/errors/SafeErrorBoundary.tsx +0 -201
- package/src/components/groups/GroupsDialog.tsx +0 -1304
- package/src/components/inspector-pet/InspectorPet.tsx +0 -398
- package/src/components/inspector-pet/InspectorPetCrab3D.tsx +0 -455
- package/src/components/inspector-pet/inspectorPetLogic.ts +0 -272
- package/src/components/pi-agent/PiAgentPanel.tsx +0 -446
- package/src/components/pi-agent/piAgentChatLogic.ts +0 -273
- package/src/components/providers/ImportWizardDialog.tsx +0 -281
- package/src/components/providers/ProviderCard.tsx +0 -347
- package/src/components/providers/ProviderForm.tsx +0 -1183
- package/src/components/providers/ProviderLogo.tsx +0 -122
- package/src/components/providers/ProviderTestResultsView.tsx +0 -734
- package/src/components/providers/ProvidersPanel.tsx +0 -714
- package/src/components/providers/SettingsDialog.tsx +0 -1042
- package/src/components/providers/providerFormCapabilities.ts +0 -36
- package/src/components/proxy-viewer/AgentTraceSummary.tsx +0 -902
- package/src/components/proxy-viewer/AnswerMarkdown.tsx +0 -51
- package/src/components/proxy-viewer/ApplicationBar.tsx +0 -123
- package/src/components/proxy-viewer/CompareDrawer.tsx +0 -984
- package/src/components/proxy-viewer/ConversationGroup.tsx +0 -208
- package/src/components/proxy-viewer/ConversationGroupList.tsx +0 -652
- package/src/components/proxy-viewer/ConversationHeader.tsx +0 -429
- package/src/components/proxy-viewer/LiveConnectionStatus.tsx +0 -186
- package/src/components/proxy-viewer/LogEntry.tsx +0 -1419
- package/src/components/proxy-viewer/LogEntryHeader.tsx +0 -596
- package/src/components/proxy-viewer/ProviderLogoStack.tsx +0 -57
- package/src/components/proxy-viewer/RawExportWarning.tsx +0 -77
- package/src/components/proxy-viewer/ReplayDialog.tsx +0 -636
- package/src/components/proxy-viewer/RequestToolsPanel.tsx +0 -299
- package/src/components/proxy-viewer/ResponseView.tsx +0 -202
- package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +0 -61
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +0 -265
- package/src/components/proxy-viewer/ThreadConnector.tsx +0 -165
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +0 -64
- package/src/components/proxy-viewer/TurnGroup.tsx +0 -383
- package/src/components/proxy-viewer/TurnGroupList.tsx +0 -156
- package/src/components/proxy-viewer/accessibility.ts +0 -8
- package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +0 -887
- package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +0 -222
- package/src/components/proxy-viewer/anatomy/contextIntelligence.ts +0 -737
- package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +0 -268
- package/src/components/proxy-viewer/anatomy/tokenEstimate.ts +0 -53
- package/src/components/proxy-viewer/anatomy/types.ts +0 -41
- package/src/components/proxy-viewer/anatomy/useAnatomyJump.ts +0 -114
- package/src/components/proxy-viewer/bodyHydration.ts +0 -123
- package/src/components/proxy-viewer/cacheTrend.ts +0 -50
- package/src/components/proxy-viewer/diff/DiffView.tsx +0 -321
- package/src/components/proxy-viewer/diff/computeDiff.ts +0 -178
- package/src/components/proxy-viewer/diff/index.ts +0 -3
- package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +0 -194
- package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +0 -81
- package/src/components/proxy-viewer/formats/anthropic/thinkingExtract.ts +0 -21
- package/src/components/proxy-viewer/formats/index.tsx +0 -47
- package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +0 -442
- package/src/components/proxy-viewer/index.ts +0 -9
- package/src/components/proxy-viewer/lazy.ts +0 -41
- package/src/components/proxy-viewer/liveConnectionState.ts +0 -158
- package/src/components/proxy-viewer/log-formats/anthropic.ts +0 -191
- package/src/components/proxy-viewer/log-formats/index.ts +0 -23
- package/src/components/proxy-viewer/log-formats/openai.ts +0 -256
- package/src/components/proxy-viewer/log-formats/types.ts +0 -40
- package/src/components/proxy-viewer/log-formats/unknown.ts +0 -18
- package/src/components/proxy-viewer/logEntryVisibility.ts +0 -73
- package/src/components/proxy-viewer/logFocus.ts +0 -54
- package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +0 -124
- package/src/components/proxy-viewer/proxyViewerLogic.ts +0 -488
- package/src/components/proxy-viewer/replayComparison.ts +0 -131
- package/src/components/proxy-viewer/requestDiff.ts +0 -277
- package/src/components/proxy-viewer/requestTools.ts +0 -220
- package/src/components/proxy-viewer/useCopyFeedback.ts +0 -38
- package/src/components/proxy-viewer/useKeyboardNavigation.ts +0 -232
- package/src/components/proxy-viewer/viewerState.ts +0 -176
- package/src/components/ui/badge.tsx +0 -47
- package/src/components/ui/button.tsx +0 -47
- package/src/components/ui/collapsible.tsx +0 -21
- package/src/components/ui/confirm-dialog.tsx +0 -51
- package/src/components/ui/crab-logo.tsx +0 -45
- package/src/components/ui/crab-variants.tsx +0 -467
- package/src/components/ui/dialog.tsx +0 -130
- package/src/components/ui/icon-trigger.ts +0 -2
- package/src/components/ui/json-viewer-bulk.ts +0 -132
- package/src/components/ui/json-viewer.tsx +0 -508
- package/src/components/ui/scroll-area.tsx +0 -54
- package/src/components/ui/select.tsx +0 -178
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/tabs.tsx +0 -88
- package/src/components/ui/tooltip.tsx +0 -51
- package/src/components/ui/transient-toast.tsx +0 -105
- package/src/contracts/anthropic.ts +0 -230
- package/src/contracts/index.ts +0 -59
- package/src/contracts/json.ts +0 -37
- package/src/contracts/log.ts +0 -139
- package/src/contracts/openai.ts +0 -267
- package/src/index.css +0 -11
- package/src/knowledge/candidateStore.ts +0 -94
- package/src/knowledge/distiller.ts +0 -98
- package/src/knowledge/openclawClient.ts +0 -161
- package/src/knowledge/openclawGatewayClient.ts +0 -249
- package/src/knowledge/openclawMarkdown.ts +0 -146
- package/src/knowledge/redactor.ts +0 -80
- package/src/knowledge/types.ts +0 -83
- package/src/lib/alertContract.ts +0 -76
- package/src/lib/apiClient.ts +0 -166
- package/src/lib/apiFormat.ts +0 -29
- package/src/lib/backendImplementation.ts +0 -16
- package/src/lib/basePath.ts +0 -107
- package/src/lib/browserRuntimeContract.ts +0 -124
- package/src/lib/browserRuntimeResolver.ts +0 -333
- package/src/lib/chunkLoadRecovery.ts +0 -83
- package/src/lib/claudeCodeStrip.ts +0 -98
- package/src/lib/clipboard.ts +0 -67
- package/src/lib/codingAgentEndpoints.ts +0 -54
- package/src/lib/ecosystemContract.ts +0 -130
- package/src/lib/export-logs.ts +0 -287
- package/src/lib/groupContract.ts +0 -166
- package/src/lib/instanceContract.ts +0 -239
- package/src/lib/jsonFile.ts +0 -46
- package/src/lib/logImportContract.ts +0 -12
- package/src/lib/managedInstance.ts +0 -112
- package/src/lib/mask.ts +0 -4
- package/src/lib/objectUtils.ts +0 -22
- package/src/lib/piAgentContract.ts +0 -102
- package/src/lib/providerContract.ts +0 -125
- package/src/lib/providerImportContract.ts +0 -27
- package/src/lib/providerModelMetadata.ts +0 -458
- package/src/lib/providerTestContract.ts +0 -170
- package/src/lib/providerTestPrompt.ts +0 -100
- package/src/lib/publicBasePathContext.ts +0 -137
- package/src/lib/resourceLimits.ts +0 -345
- package/src/lib/runContract.ts +0 -164
- package/src/lib/runtimeConfig.ts +0 -43
- package/src/lib/safeDiagnostic.ts +0 -38
- package/src/lib/safeFetch.ts +0 -508
- package/src/lib/serverPort.ts +0 -47
- package/src/lib/sessionInfoContract.ts +0 -78
- package/src/lib/sessionUrl.ts +0 -46
- package/src/lib/ssrfGuard.ts +0 -133
- package/src/lib/stopReason.ts +0 -130
- package/src/lib/themeMode.ts +0 -41
- package/src/lib/timeDisplay.ts +0 -22
- package/src/lib/toolTrace.ts +0 -290
- package/src/lib/uiScale.ts +0 -117
- package/src/lib/unknown.ts +0 -27
- package/src/lib/upstreamUrl.ts +0 -150
- package/src/lib/useAlerts.ts +0 -82
- package/src/lib/useGroupEvidence.ts +0 -37
- package/src/lib/useGroups.ts +0 -32
- package/src/lib/useOnboarding.ts +0 -93
- package/src/lib/useProviders.ts +0 -30
- package/src/lib/useStripConfig.ts +0 -154
- package/src/lib/useThemeMode.ts +0 -40
- package/src/lib/useUiScale.ts +0 -52
- package/src/lib/utils.ts +0 -78
- package/src/mcp/currentContext.ts +0 -65
- package/src/mcp/instanceHandlers.ts +0 -151
- package/src/mcp/loopback.ts +0 -88
- package/src/mcp/mode.ts +0 -75
- package/src/mcp/previewExtractor.ts +0 -233
- package/src/mcp/server.ts +0 -2274
- package/src/mcp/toolHandlers.ts +0 -1533
- package/src/proxy/alerts.ts +0 -664
- package/src/proxy/chunkStorage.ts +0 -123
- package/src/proxy/config.ts +0 -218
- package/src/proxy/constants.ts +0 -66
- package/src/proxy/dataDir.ts +0 -147
- package/src/proxy/ecosystemExecutionConfirmation.ts +0 -114
- package/src/proxy/ecosystemExecutionRoute.ts +0 -116
- package/src/proxy/ecosystemRegistry.ts +0 -296
- package/src/proxy/ecosystemTasks.ts +0 -415
- package/src/proxy/evidenceAnalysis.ts +0 -526
- package/src/proxy/evidenceExporter.ts +0 -235
- package/src/proxy/formats/anthropic/anthropicProvider.ts +0 -75
- package/src/proxy/formats/anthropic/handler.ts +0 -75
- package/src/proxy/formats/anthropic/index.ts +0 -13
- package/src/proxy/formats/anthropic/register.ts +0 -4
- package/src/proxy/formats/anthropic/schemas.ts +0 -6
- package/src/proxy/formats/anthropic/stream.ts +0 -205
- package/src/proxy/formats/handler.ts +0 -46
- package/src/proxy/formats/index.ts +0 -13
- package/src/proxy/formats/jsonSchema.ts +0 -2
- package/src/proxy/formats/openai/alibabaProvider.ts +0 -34
- package/src/proxy/formats/openai/codexMetadata.ts +0 -61
- package/src/proxy/formats/openai/handler.ts +0 -133
- package/src/proxy/formats/openai/index.ts +0 -33
- package/src/proxy/formats/openai/provider.ts +0 -50
- package/src/proxy/formats/openai/register.ts +0 -4
- package/src/proxy/formats/openai/schemas.ts +0 -25
- package/src/proxy/formats/openai/stream.ts +0 -600
- package/src/proxy/formats/openai/zhipuProvider.ts +0 -31
- package/src/proxy/formats/providerAdapter.ts +0 -50
- package/src/proxy/formats/providerRegistry.ts +0 -51
- package/src/proxy/formats/providers/index.ts +0 -3
- package/src/proxy/formats/registry.ts +0 -65
- package/src/proxy/groupEvidenceExporter.ts +0 -371
- package/src/proxy/groupStore.ts +0 -336
- package/src/proxy/handler.ts +0 -729
- package/src/proxy/identityProxy.ts +0 -1842
- package/src/proxy/jsonlRecovery.ts +0 -554
- package/src/proxy/logBodyChunks.ts +0 -91
- package/src/proxy/logFinalizer.ts +0 -777
- package/src/proxy/logFinalizer.worker.ts +0 -24
- package/src/proxy/logImportUpload.ts +0 -128
- package/src/proxy/logImporter.ts +0 -813
- package/src/proxy/logIndex.ts +0 -663
- package/src/proxy/logSearch.ts +0 -122
- package/src/proxy/logger.ts +0 -537
- package/src/proxy/openaiOrphanToolStrip.ts +0 -142
- package/src/proxy/platformCommands.ts +0 -258
- package/src/proxy/privateDataPath.ts +0 -419
- package/src/proxy/providerImporters.ts +0 -578
- package/src/proxy/providerScanStore.ts +0 -87
- package/src/proxy/providerSecretStore.ts +0 -216
- package/src/proxy/providers.ts +0 -998
- package/src/proxy/rawStreamCapture.ts +0 -342
- package/src/proxy/runFailures.ts +0 -94
- package/src/proxy/runStore.ts +0 -214
- package/src/proxy/runtimeAdmission.ts +0 -55
- package/src/proxy/runtimeHealth.ts +0 -221
- package/src/proxy/runtimeMetrics.ts +0 -149
- package/src/proxy/runtimeShutdown.ts +0 -157
- package/src/proxy/schemas.ts +0 -112
- package/src/proxy/sessionArchive.ts +0 -479
- package/src/proxy/sessionInfo.ts +0 -266
- package/src/proxy/sessionProcess.ts +0 -194
- package/src/proxy/sessionRuntime.ts +0 -121
- package/src/proxy/sessionSupervisor.ts +0 -305
- package/src/proxy/sessionWorkerEntry.ts +0 -26
- package/src/proxy/shutdownCoordinator.ts +0 -90
- package/src/proxy/socketTracker.ts +0 -639
- package/src/proxy/sqliteLogIndex.ts +0 -733
- package/src/proxy/storageLifecycle.ts +0 -432
- package/src/proxy/store.ts +0 -1773
- package/src/proxy/streamTiming.ts +0 -31
- package/src/proxy/toolSchemaWarnings.ts +0 -529
- package/src/proxy/uiAssetServer.ts +0 -106
- package/src/proxy/upstream.ts +0 -127
- package/src/services/alerts.ts +0 -12
- package/src/services/groups.ts +0 -119
- package/src/services/piAgent.ts +0 -421
- package/src/services/piAgentRetrieval.ts +0 -1180
- package/src/services/result.ts +0 -17
- package/src/services/runs.ts +0 -76
- package/src/ui/bootstrap.ts +0 -167
- package/src/ui/index.html +0 -38
- package/src/ui/logsStreamClient.ts +0 -20
- package/src/ui/main.tsx +0 -13
- package/src/ui/public/runtime-config.js +0 -2
- package/src/ui/router.tsx +0 -13
- package/src/ui/routes/__root.tsx +0 -69
- package/src/ui/routes/index.tsx +0 -35
- package/src/ui/routes/session/$sessionId.tsx +0 -50
- package/src/ui/runtimeDiscovery.ts +0 -50
|
@@ -1,652 +0,0 @@
|
|
|
1
|
-
import { type JSX, useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
-
import { ChevronDown, ChevronRight, Cpu, FolderOpen, Loader2, Monitor } from "lucide-react";
|
|
3
|
-
import type { CapturedLog } from "../../contracts";
|
|
4
|
-
import { cn, formatTokens } from "../../lib/utils";
|
|
5
|
-
import {
|
|
6
|
-
ClientLogo,
|
|
7
|
-
clientAppLabel,
|
|
8
|
-
clientAppTypeLabel,
|
|
9
|
-
detectClientApp,
|
|
10
|
-
type ClientApp,
|
|
11
|
-
} from "../clients/ClientLogo";
|
|
12
|
-
import { ConversationGroup, type ConversationGroupProps } from "./ConversationGroup";
|
|
13
|
-
import type { ConversationGroupData } from "./ConversationHeader";
|
|
14
|
-
|
|
15
|
-
const VIRTUALIZE_GROUP_THRESHOLD = 30;
|
|
16
|
-
const COLLAPSED_CLIENTS_STORAGE_KEY = "agent-inspector.hierarchy.collapsedClients";
|
|
17
|
-
const COLLAPSED_PROCESSES_STORAGE_KEY = "agent-inspector.hierarchy.collapsedProcesses";
|
|
18
|
-
|
|
19
|
-
type ConversationGroupListProps = Omit<
|
|
20
|
-
ConversationGroupProps,
|
|
21
|
-
"group" | "expanded" | "onExpandedChange"
|
|
22
|
-
> & {
|
|
23
|
-
groups: ConversationGroupData[];
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type ProcessGroupData = {
|
|
27
|
-
id: string;
|
|
28
|
-
clientPid: number | null;
|
|
29
|
-
clientProjectFolder: string | null;
|
|
30
|
-
sessions: ConversationGroupData[];
|
|
31
|
-
logs: CapturedLog[];
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type ClientGroupData = {
|
|
35
|
-
id: string;
|
|
36
|
-
client: ClientApp;
|
|
37
|
-
label: string;
|
|
38
|
-
userAgent: string | null;
|
|
39
|
-
processes: ProcessGroupData[];
|
|
40
|
-
logs: CapturedLog[];
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
type MutableProcessGroup = {
|
|
44
|
-
id: string;
|
|
45
|
-
clientPid: number | null;
|
|
46
|
-
clientProjectFolder: string | null;
|
|
47
|
-
sessions: ConversationGroupData[];
|
|
48
|
-
logs: CapturedLog[];
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
type MutableClientGroup = {
|
|
52
|
-
id: string;
|
|
53
|
-
client: ClientApp;
|
|
54
|
-
label: string;
|
|
55
|
-
userAgent: string | null;
|
|
56
|
-
processes: Map<string, MutableProcessGroup>;
|
|
57
|
-
logs: CapturedLog[];
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export function shouldVirtualizeConversationGroups(groupCount: number): boolean {
|
|
61
|
-
return groupCount > VIRTUALIZE_GROUP_THRESHOLD;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function hasPendingLogs(logs: readonly CapturedLog[]): boolean {
|
|
65
|
-
return logs.some((log) => log.responseStatus === null);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function countPendingTurns(logs: readonly CapturedLog[]): number {
|
|
69
|
-
return logs.filter((log) => log.responseStatus === null).length;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function findConversationGroupIndexForLog(
|
|
73
|
-
groups: readonly ConversationGroupData[],
|
|
74
|
-
logId: number,
|
|
75
|
-
): number | null {
|
|
76
|
-
for (let index = 0; index < groups.length; index++) {
|
|
77
|
-
const group = groups[index];
|
|
78
|
-
if (group !== undefined && group.logs.some((log: CapturedLog) => log.id === logId)) {
|
|
79
|
-
return index;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function firstUserAgent(logs: readonly CapturedLog[]): string | null {
|
|
86
|
-
for (const log of logs) {
|
|
87
|
-
const userAgent = log.userAgent;
|
|
88
|
-
if (userAgent !== null && userAgent !== undefined && userAgent !== "") return userAgent;
|
|
89
|
-
}
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function firstClientPid(logs: readonly CapturedLog[]): number | null {
|
|
94
|
-
for (const log of logs) {
|
|
95
|
-
const clientPid = log.clientPid;
|
|
96
|
-
if (clientPid !== null && clientPid !== undefined) return clientPid;
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function firstClientProjectFolder(logs: readonly CapturedLog[]): string | null {
|
|
102
|
-
for (const log of logs) {
|
|
103
|
-
const projectFolder = log.clientProjectFolder;
|
|
104
|
-
if (projectFolder !== null && projectFolder !== undefined && projectFolder !== "") {
|
|
105
|
-
return projectFolder;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function groupClient(group: ConversationGroupData): ClientApp {
|
|
112
|
-
return detectClientApp({
|
|
113
|
-
userAgent: firstUserAgent(group.logs),
|
|
114
|
-
conversationId: group.conversationId,
|
|
115
|
-
clientProjectFolder: firstClientProjectFolder(group.logs),
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function fallbackClientLabel(userAgent: string | null): string {
|
|
120
|
-
if (userAgent === null || userAgent === "") return "Unknown client";
|
|
121
|
-
const firstToken = userAgent.split(/[ /;]/)[0] ?? "";
|
|
122
|
-
if (firstToken === "") return "Unknown client";
|
|
123
|
-
return firstToken;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function clientLabel(client: ClientApp, userAgent: string | null): string {
|
|
127
|
-
const knownLabel = clientAppLabel(client);
|
|
128
|
-
if (knownLabel !== null) return knownLabel;
|
|
129
|
-
return fallbackClientLabel(userAgent);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function bucketKey(value: string | number | null): string {
|
|
133
|
-
if (value === null || value === "") return "unknown";
|
|
134
|
-
return String(value);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function ideKey(client: ClientApp, userAgent: string | null, projectFolder: string | null): string {
|
|
138
|
-
if (client !== "unknown") return client;
|
|
139
|
-
return `unknown:${bucketKey(userAgent)}:${bucketKey(projectFolder)}`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function processKey(clientPid: number | null, projectFolder: string | null): string {
|
|
143
|
-
return `${bucketKey(clientPid)}:${bucketKey(projectFolder)}`;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function sortLogsByTimestamp(logs: readonly CapturedLog[]): CapturedLog[] {
|
|
147
|
-
return [...logs].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function latestTimestamp(logs: readonly CapturedLog[]): string {
|
|
151
|
-
let latest = "";
|
|
152
|
-
for (const log of logs) {
|
|
153
|
-
if (log.timestamp > latest) latest = log.timestamp;
|
|
154
|
-
}
|
|
155
|
-
return latest;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function operationalPriority(logs: readonly CapturedLog[]): number {
|
|
159
|
-
if (hasPendingLogs(logs)) return 0;
|
|
160
|
-
if (
|
|
161
|
-
logs.some(
|
|
162
|
-
(log) =>
|
|
163
|
-
(log.error !== null && log.error !== undefined) ||
|
|
164
|
-
(log.responseStatus !== null &&
|
|
165
|
-
log.responseStatus !== undefined &&
|
|
166
|
-
log.responseStatus >= 400),
|
|
167
|
-
)
|
|
168
|
-
) {
|
|
169
|
-
return 1;
|
|
170
|
-
}
|
|
171
|
-
return 2;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function sortByOperationalPriority<T extends { id: string; logs: readonly CapturedLog[] }>(
|
|
175
|
-
items: readonly T[],
|
|
176
|
-
): T[] {
|
|
177
|
-
return [...items].sort((left, right) => {
|
|
178
|
-
const priorityDifference = operationalPriority(left.logs) - operationalPriority(right.logs);
|
|
179
|
-
if (priorityDifference !== 0) return priorityDifference;
|
|
180
|
-
const recencyDifference = latestTimestamp(right.logs).localeCompare(latestTimestamp(left.logs));
|
|
181
|
-
if (recencyDifference !== 0) return recencyDifference;
|
|
182
|
-
return left.id.localeCompare(right.id);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export function buildConversationHierarchy(
|
|
187
|
-
groups: readonly ConversationGroupData[],
|
|
188
|
-
): ClientGroupData[] {
|
|
189
|
-
const clientGroups = new Map<string, MutableClientGroup>();
|
|
190
|
-
|
|
191
|
-
for (const group of groups) {
|
|
192
|
-
const userAgent = firstUserAgent(group.logs);
|
|
193
|
-
const projectFolder = firstClientProjectFolder(group.logs);
|
|
194
|
-
const client = groupClient(group);
|
|
195
|
-
const currentIdeKey = ideKey(client, userAgent, projectFolder);
|
|
196
|
-
let clientGroup = clientGroups.get(currentIdeKey);
|
|
197
|
-
|
|
198
|
-
if (clientGroup === undefined) {
|
|
199
|
-
clientGroup = {
|
|
200
|
-
id: currentIdeKey,
|
|
201
|
-
client,
|
|
202
|
-
label: clientLabel(client, userAgent),
|
|
203
|
-
userAgent,
|
|
204
|
-
processes: new Map(),
|
|
205
|
-
logs: [],
|
|
206
|
-
};
|
|
207
|
-
clientGroups.set(currentIdeKey, clientGroup);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
clientGroup.logs.push(...group.logs);
|
|
211
|
-
|
|
212
|
-
const clientPid = firstClientPid(group.logs);
|
|
213
|
-
const currentProcessKey = `${currentIdeKey}:${processKey(clientPid, projectFolder)}`;
|
|
214
|
-
let processGroup = clientGroup.processes.get(currentProcessKey);
|
|
215
|
-
|
|
216
|
-
if (processGroup === undefined) {
|
|
217
|
-
processGroup = {
|
|
218
|
-
id: currentProcessKey,
|
|
219
|
-
clientPid,
|
|
220
|
-
clientProjectFolder: projectFolder,
|
|
221
|
-
sessions: [],
|
|
222
|
-
logs: [],
|
|
223
|
-
};
|
|
224
|
-
clientGroup.processes.set(currentProcessKey, processGroup);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
processGroup.sessions.push(group);
|
|
228
|
-
processGroup.logs.push(...group.logs);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const hierarchy: ClientGroupData[] = [];
|
|
232
|
-
|
|
233
|
-
for (const clientGroup of clientGroups.values()) {
|
|
234
|
-
const processes: ProcessGroupData[] = sortByOperationalPriority(
|
|
235
|
-
[...clientGroup.processes.values()].map((processGroup) => ({
|
|
236
|
-
id: processGroup.id,
|
|
237
|
-
clientPid: processGroup.clientPid,
|
|
238
|
-
clientProjectFolder: processGroup.clientProjectFolder,
|
|
239
|
-
sessions: sortByOperationalPriority(processGroup.sessions),
|
|
240
|
-
logs: sortLogsByTimestamp(processGroup.logs),
|
|
241
|
-
})),
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
hierarchy.push({
|
|
245
|
-
id: clientGroup.id,
|
|
246
|
-
client: clientGroup.client,
|
|
247
|
-
label: clientGroup.label,
|
|
248
|
-
userAgent: clientGroup.userAgent,
|
|
249
|
-
processes,
|
|
250
|
-
logs: sortLogsByTimestamp(clientGroup.logs),
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return sortByOperationalPriority(hierarchy);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function formatTokenCount(count: number): string {
|
|
258
|
-
if (count <= 0) return "0";
|
|
259
|
-
return formatTokens(count);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function tokenTotals(logs: readonly CapturedLog[]): {
|
|
263
|
-
inputTokens: number;
|
|
264
|
-
outputTokens: number;
|
|
265
|
-
} {
|
|
266
|
-
let inputTokens = 0;
|
|
267
|
-
let outputTokens = 0;
|
|
268
|
-
|
|
269
|
-
for (const log of logs) {
|
|
270
|
-
if (log.inputTokens !== null && log.inputTokens !== undefined) inputTokens += log.inputTokens;
|
|
271
|
-
if (log.outputTokens !== null && log.outputTokens !== undefined) {
|
|
272
|
-
outputTokens += log.outputTokens;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
return { inputTokens, outputTokens };
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function countSessions(processes: readonly ProcessGroupData[]): number {
|
|
280
|
-
let sessions = 0;
|
|
281
|
-
for (const processGroup of processes) {
|
|
282
|
-
sessions += processGroup.sessions.length;
|
|
283
|
-
}
|
|
284
|
-
return sessions;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function readStoredIdSet(storageKey: string): ReadonlySet<string> | null {
|
|
288
|
-
if (typeof window === "undefined") return null;
|
|
289
|
-
try {
|
|
290
|
-
const storedValue = window.localStorage.getItem(storageKey);
|
|
291
|
-
if (storedValue === null) return null;
|
|
292
|
-
const parsed: unknown = JSON.parse(storedValue);
|
|
293
|
-
if (!Array.isArray(parsed)) return null;
|
|
294
|
-
return new Set(parsed.filter((value): value is string => typeof value === "string"));
|
|
295
|
-
} catch {
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function persistIdSet(storageKey: string, values: ReadonlySet<string>): void {
|
|
301
|
-
try {
|
|
302
|
-
window.localStorage.setItem(storageKey, JSON.stringify([...values]));
|
|
303
|
-
} catch {
|
|
304
|
-
// Local storage can be unavailable in hardened browser profiles.
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function removeIds(values: ReadonlySet<string>, ids: ReadonlySet<string>): ReadonlySet<string> {
|
|
309
|
-
let changed = false;
|
|
310
|
-
const next = new Set(values);
|
|
311
|
-
for (const id of ids) {
|
|
312
|
-
if (next.delete(id)) changed = true;
|
|
313
|
-
}
|
|
314
|
-
return changed ? next : values;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
export function buildDefaultCollapsedProcessIds(
|
|
318
|
-
hierarchy: readonly ClientGroupData[],
|
|
319
|
-
): ReadonlySet<string> {
|
|
320
|
-
const collapsedIds = new Set<string>();
|
|
321
|
-
for (const clientGroup of hierarchy) {
|
|
322
|
-
for (let index = 1; index < clientGroup.processes.length; index++) {
|
|
323
|
-
const processGroup = clientGroup.processes[index];
|
|
324
|
-
if (processGroup !== undefined && !hasPendingLogs(processGroup.logs)) {
|
|
325
|
-
collapsedIds.add(processGroup.id);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return collapsedIds;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
function shortProjectPath(projectFolder: string | null): string | null {
|
|
333
|
-
if (projectFolder === null || projectFolder === "") return null;
|
|
334
|
-
const parts = projectFolder
|
|
335
|
-
.replaceAll("\\", "/")
|
|
336
|
-
.split("/")
|
|
337
|
-
.filter((part) => part !== "");
|
|
338
|
-
const leaf = parts[parts.length - 1];
|
|
339
|
-
if (leaf === undefined) return projectFolder;
|
|
340
|
-
const parent = parts[parts.length - 2];
|
|
341
|
-
if (parent === undefined) return leaf;
|
|
342
|
-
return `${parent}/${leaf}`;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function SummaryChip({
|
|
346
|
-
label,
|
|
347
|
-
value,
|
|
348
|
-
className,
|
|
349
|
-
}: {
|
|
350
|
-
label: string;
|
|
351
|
-
value: string;
|
|
352
|
-
className?: string;
|
|
353
|
-
}): JSX.Element {
|
|
354
|
-
return (
|
|
355
|
-
<span
|
|
356
|
-
className={cn(
|
|
357
|
-
"inline-flex h-7 items-center gap-1 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
|
|
358
|
-
className,
|
|
359
|
-
)}
|
|
360
|
-
>
|
|
361
|
-
<span className="font-mono text-[10px] uppercase text-muted-foreground/70">{label}</span>
|
|
362
|
-
<span className="font-mono tabular-nums text-foreground">{value}</span>
|
|
363
|
-
</span>
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function AncestorActivityIndicator({ count }: { count: number }): JSX.Element {
|
|
368
|
-
const label = `${count} open turn${count === 1 ? "" : "s"}`;
|
|
369
|
-
return (
|
|
370
|
-
<span
|
|
371
|
-
className="relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-medium)] text-[var(--inspector-status-watch)] ring-1 ring-border/50"
|
|
372
|
-
aria-label={label}
|
|
373
|
-
title={label}
|
|
374
|
-
>
|
|
375
|
-
<Loader2 className="size-3 animate-spin" />
|
|
376
|
-
{count > 1 && (
|
|
377
|
-
<span className="absolute translate-x-2 -translate-y-2 rounded bg-card px-0.5 font-mono text-[8px] tabular-nums text-[var(--inspector-status-watch)]">
|
|
378
|
-
{count}
|
|
379
|
-
</span>
|
|
380
|
-
)}
|
|
381
|
-
</span>
|
|
382
|
-
);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export function ConversationGroupList({
|
|
386
|
-
groups,
|
|
387
|
-
...groupProps
|
|
388
|
-
}: ConversationGroupListProps): JSX.Element {
|
|
389
|
-
const hierarchy = useMemo(() => buildConversationHierarchy(groups), [groups]);
|
|
390
|
-
const [collapsedClientIds, setCollapsedClientIds] = useState<ReadonlySet<string>>(
|
|
391
|
-
() => new Set(),
|
|
392
|
-
);
|
|
393
|
-
const [collapsedProcessIds, setCollapsedProcessIds] = useState<ReadonlySet<string>>(() =>
|
|
394
|
-
buildDefaultCollapsedProcessIds(hierarchy),
|
|
395
|
-
);
|
|
396
|
-
const [storedCollapseStateLoaded, setStoredCollapseStateLoaded] = useState(false);
|
|
397
|
-
|
|
398
|
-
useEffect(() => {
|
|
399
|
-
const storedClientIds = readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY);
|
|
400
|
-
const storedProcessIds = readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY);
|
|
401
|
-
if (storedClientIds !== null) setCollapsedClientIds(storedClientIds);
|
|
402
|
-
if (storedProcessIds !== null) setCollapsedProcessIds(storedProcessIds);
|
|
403
|
-
setStoredCollapseStateLoaded(true);
|
|
404
|
-
}, []);
|
|
405
|
-
|
|
406
|
-
useEffect(() => {
|
|
407
|
-
if (!storedCollapseStateLoaded) return;
|
|
408
|
-
persistIdSet(COLLAPSED_CLIENTS_STORAGE_KEY, collapsedClientIds);
|
|
409
|
-
persistIdSet(COLLAPSED_PROCESSES_STORAGE_KEY, collapsedProcessIds);
|
|
410
|
-
}, [collapsedClientIds, collapsedProcessIds, storedCollapseStateLoaded]);
|
|
411
|
-
|
|
412
|
-
useEffect(() => {
|
|
413
|
-
const activeClientIds = new Set(
|
|
414
|
-
hierarchy.filter((group) => hasPendingLogs(group.logs)).map((group) => group.id),
|
|
415
|
-
);
|
|
416
|
-
const activeProcessIds = new Set(
|
|
417
|
-
hierarchy.flatMap((group) =>
|
|
418
|
-
group.processes
|
|
419
|
-
.filter((process) => hasPendingLogs(process.logs))
|
|
420
|
-
.map((process) => process.id),
|
|
421
|
-
),
|
|
422
|
-
);
|
|
423
|
-
setCollapsedClientIds((previous) => removeIds(previous, activeClientIds));
|
|
424
|
-
setCollapsedProcessIds((previous) => removeIds(previous, activeProcessIds));
|
|
425
|
-
}, [hierarchy]);
|
|
426
|
-
|
|
427
|
-
const toggleClient = useCallback((id: string) => {
|
|
428
|
-
setCollapsedClientIds((previous) => {
|
|
429
|
-
const next = new Set(previous);
|
|
430
|
-
if (next.has(id)) {
|
|
431
|
-
next.delete(id);
|
|
432
|
-
} else {
|
|
433
|
-
next.add(id);
|
|
434
|
-
}
|
|
435
|
-
return next;
|
|
436
|
-
});
|
|
437
|
-
}, []);
|
|
438
|
-
|
|
439
|
-
const toggleProcess = useCallback((id: string) => {
|
|
440
|
-
setCollapsedProcessIds((previous) => {
|
|
441
|
-
const next = new Set(previous);
|
|
442
|
-
if (next.has(id)) {
|
|
443
|
-
next.delete(id);
|
|
444
|
-
} else {
|
|
445
|
-
next.add(id);
|
|
446
|
-
}
|
|
447
|
-
return next;
|
|
448
|
-
});
|
|
449
|
-
}, []);
|
|
450
|
-
|
|
451
|
-
return (
|
|
452
|
-
<div className="space-y-2">
|
|
453
|
-
{hierarchy.map((clientGroup) => (
|
|
454
|
-
<ClientGroupSection
|
|
455
|
-
key={clientGroup.id}
|
|
456
|
-
group={clientGroup}
|
|
457
|
-
collapsed={collapsedClientIds.has(clientGroup.id)}
|
|
458
|
-
collapsedProcessIds={collapsedProcessIds}
|
|
459
|
-
onToggleClient={() => toggleClient(clientGroup.id)}
|
|
460
|
-
onToggleProcess={toggleProcess}
|
|
461
|
-
conversationProps={groupProps}
|
|
462
|
-
/>
|
|
463
|
-
))}
|
|
464
|
-
</div>
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
function ClientGroupSection({
|
|
469
|
-
group,
|
|
470
|
-
collapsed,
|
|
471
|
-
collapsedProcessIds,
|
|
472
|
-
onToggleClient,
|
|
473
|
-
onToggleProcess,
|
|
474
|
-
conversationProps,
|
|
475
|
-
}: {
|
|
476
|
-
group: ClientGroupData;
|
|
477
|
-
collapsed: boolean;
|
|
478
|
-
collapsedProcessIds: ReadonlySet<string>;
|
|
479
|
-
onToggleClient: () => void;
|
|
480
|
-
onToggleProcess: (id: string) => void;
|
|
481
|
-
conversationProps: Omit<ConversationGroupProps, "group" | "expanded" | "onExpandedChange">;
|
|
482
|
-
}): JSX.Element {
|
|
483
|
-
const totals = tokenTotals(group.logs);
|
|
484
|
-
const sessionCount = countSessions(group.processes);
|
|
485
|
-
const logCount = group.logs.length;
|
|
486
|
-
const pendingTurnCount = countPendingTurns(group.logs);
|
|
487
|
-
const isWorking = pendingTurnCount > 0;
|
|
488
|
-
|
|
489
|
-
return (
|
|
490
|
-
<section
|
|
491
|
-
className={cn(
|
|
492
|
-
"relative isolate overflow-hidden rounded-[8px] bg-card/65",
|
|
493
|
-
isWorking && "bg-card/80",
|
|
494
|
-
)}
|
|
495
|
-
data-ide-group={group.id}
|
|
496
|
-
>
|
|
497
|
-
<button
|
|
498
|
-
type="button"
|
|
499
|
-
className="grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-[var(--inspector-surface-low)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
500
|
-
onClick={onToggleClient}
|
|
501
|
-
aria-expanded={!collapsed}
|
|
502
|
-
>
|
|
503
|
-
{group.client === "unknown" ? (
|
|
504
|
-
<span className="inline-flex size-9 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground">
|
|
505
|
-
<Monitor className="size-4" />
|
|
506
|
-
</span>
|
|
507
|
-
) : (
|
|
508
|
-
<ClientLogo client={group.client} className="size-9 rounded-md" decorative={true} />
|
|
509
|
-
)}
|
|
510
|
-
|
|
511
|
-
<span className="min-w-0">
|
|
512
|
-
<span className="flex min-w-0 items-center gap-2">
|
|
513
|
-
<span
|
|
514
|
-
className="truncate text-sm font-semibold text-foreground"
|
|
515
|
-
title={group.userAgent ?? group.label}
|
|
516
|
-
>
|
|
517
|
-
{group.label}
|
|
518
|
-
</span>
|
|
519
|
-
<span className="rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground">
|
|
520
|
-
{clientAppTypeLabel(group.client)}
|
|
521
|
-
</span>
|
|
522
|
-
{isWorking && <AncestorActivityIndicator count={pendingTurnCount} />}
|
|
523
|
-
</span>
|
|
524
|
-
<span className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground">
|
|
525
|
-
<span>
|
|
526
|
-
{group.processes.length} process{group.processes.length !== 1 ? "es" : ""}
|
|
527
|
-
</span>
|
|
528
|
-
<span>
|
|
529
|
-
{sessionCount} session{sessionCount !== 1 ? "s" : ""}
|
|
530
|
-
</span>
|
|
531
|
-
<span>{logCount} req</span>
|
|
532
|
-
</span>
|
|
533
|
-
</span>
|
|
534
|
-
|
|
535
|
-
<span className="flex shrink-0 items-center gap-2">
|
|
536
|
-
{collapsed && (
|
|
537
|
-
<span className="hidden shrink-0 items-center gap-2 md:flex">
|
|
538
|
-
<SummaryChip label="IN" value={formatTokenCount(totals.inputTokens)} />
|
|
539
|
-
<SummaryChip label="OUT" value={formatTokenCount(totals.outputTokens)} />
|
|
540
|
-
</span>
|
|
541
|
-
)}
|
|
542
|
-
<span className="inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors group-hover:bg-[var(--inspector-surface-medium)]">
|
|
543
|
-
{collapsed ? <ChevronRight className="size-4" /> : <ChevronDown className="size-4" />}
|
|
544
|
-
</span>
|
|
545
|
-
</span>
|
|
546
|
-
</button>
|
|
547
|
-
|
|
548
|
-
{!collapsed && (
|
|
549
|
-
<div className="space-y-0.5 px-2 pb-2 pt-0.5">
|
|
550
|
-
{group.processes.map((processGroup) => (
|
|
551
|
-
<ProcessGroupSection
|
|
552
|
-
key={processGroup.id}
|
|
553
|
-
group={processGroup}
|
|
554
|
-
collapsed={collapsedProcessIds.has(processGroup.id)}
|
|
555
|
-
onToggle={() => onToggleProcess(processGroup.id)}
|
|
556
|
-
conversationProps={conversationProps}
|
|
557
|
-
/>
|
|
558
|
-
))}
|
|
559
|
-
</div>
|
|
560
|
-
)}
|
|
561
|
-
</section>
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function ProcessGroupSection({
|
|
566
|
-
group,
|
|
567
|
-
collapsed,
|
|
568
|
-
onToggle,
|
|
569
|
-
conversationProps,
|
|
570
|
-
}: {
|
|
571
|
-
group: ProcessGroupData;
|
|
572
|
-
collapsed: boolean;
|
|
573
|
-
onToggle: () => void;
|
|
574
|
-
conversationProps: Omit<ConversationGroupProps, "group" | "expanded" | "onExpandedChange">;
|
|
575
|
-
}): JSX.Element {
|
|
576
|
-
const totals = tokenTotals(group.logs);
|
|
577
|
-
const projectLabel = shortProjectPath(group.clientProjectFolder);
|
|
578
|
-
const sessionCount = group.sessions.length;
|
|
579
|
-
const logCount = group.logs.length;
|
|
580
|
-
const pendingTurnCount = countPendingTurns(group.logs);
|
|
581
|
-
const isWorking = pendingTurnCount > 0;
|
|
582
|
-
const processLabel =
|
|
583
|
-
group.clientPid !== null && group.clientPid !== undefined
|
|
584
|
-
? `PID ${group.clientPid}`
|
|
585
|
-
: "Process unavailable";
|
|
586
|
-
|
|
587
|
-
return (
|
|
588
|
-
<section className="relative pl-3">
|
|
589
|
-
<button
|
|
590
|
-
type="button"
|
|
591
|
-
className="grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md bg-[var(--inspector-surface-low)] px-2.5 py-2 text-left transition-colors hover:bg-[var(--inspector-surface-medium)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
|
|
592
|
-
onClick={onToggle}
|
|
593
|
-
aria-expanded={!collapsed}
|
|
594
|
-
>
|
|
595
|
-
<span className="inline-flex size-8 shrink-0 items-center justify-center text-[var(--inspector-status-watch)]">
|
|
596
|
-
<Cpu className="size-4" />
|
|
597
|
-
</span>
|
|
598
|
-
|
|
599
|
-
<span className="min-w-0">
|
|
600
|
-
<span className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
|
|
601
|
-
<span className="font-mono text-xs font-semibold tabular-nums text-foreground">
|
|
602
|
-
{processLabel}
|
|
603
|
-
</span>
|
|
604
|
-
{isWorking && <AncestorActivityIndicator count={pendingTurnCount} />}
|
|
605
|
-
{projectLabel !== null && (
|
|
606
|
-
<span
|
|
607
|
-
className="inline-flex min-w-0 items-center gap-1 text-[11px] text-muted-foreground"
|
|
608
|
-
title={group.clientProjectFolder ?? projectLabel}
|
|
609
|
-
>
|
|
610
|
-
<FolderOpen className="size-3 shrink-0" />
|
|
611
|
-
<span className="truncate font-mono">{projectLabel}</span>
|
|
612
|
-
</span>
|
|
613
|
-
)}
|
|
614
|
-
</span>
|
|
615
|
-
<span className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-[11px] text-muted-foreground">
|
|
616
|
-
<span>
|
|
617
|
-
{sessionCount} session{sessionCount !== 1 ? "s" : ""}
|
|
618
|
-
</span>
|
|
619
|
-
<span>{logCount} req</span>
|
|
620
|
-
</span>
|
|
621
|
-
</span>
|
|
622
|
-
|
|
623
|
-
<span className="flex shrink-0 items-center gap-2">
|
|
624
|
-
{collapsed && (
|
|
625
|
-
<span className="hidden shrink-0 items-center gap-2 md:flex">
|
|
626
|
-
<SummaryChip label="IN" value={formatTokenCount(totals.inputTokens)} />
|
|
627
|
-
<SummaryChip label="OUT" value={formatTokenCount(totals.outputTokens)} />
|
|
628
|
-
</span>
|
|
629
|
-
)}
|
|
630
|
-
<span className="inline-flex size-7 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)]">
|
|
631
|
-
{collapsed ? <ChevronRight className="size-4" /> : <ChevronDown className="size-4" />}
|
|
632
|
-
</span>
|
|
633
|
-
</span>
|
|
634
|
-
</button>
|
|
635
|
-
|
|
636
|
-
{!collapsed && (
|
|
637
|
-
<div className="space-y-1 pb-1 pl-3 pr-1 pt-1">
|
|
638
|
-
{group.sessions.map((session) => (
|
|
639
|
-
<ConversationGroup
|
|
640
|
-
key={session.id}
|
|
641
|
-
group={session}
|
|
642
|
-
{...conversationProps}
|
|
643
|
-
showClientIdentity={false}
|
|
644
|
-
showLogClientMetadata={false}
|
|
645
|
-
showProcessMetadata={false}
|
|
646
|
-
/>
|
|
647
|
-
))}
|
|
648
|
-
</div>
|
|
649
|
-
)}
|
|
650
|
-
</section>
|
|
651
|
-
);
|
|
652
|
-
}
|