@gracker/smartperfetto 1.0.20 → 1.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/agent/config/domainManifest.d.ts +5 -3
  2. package/dist/agent/config/domainManifest.d.ts.map +1 -1
  3. package/dist/agent/config/domainManifest.js +120 -5
  4. package/dist/agent/config/domainManifest.js.map +1 -1
  5. package/dist/agent/core/orchestratorTypes.d.ts +5 -0
  6. package/dist/agent/core/orchestratorTypes.d.ts.map +1 -1
  7. package/dist/agent/core/orchestratorTypes.js.map +1 -1
  8. package/dist/agent/scene/buildSmartChatReport.d.ts +13 -0
  9. package/dist/agent/scene/buildSmartChatReport.d.ts.map +1 -0
  10. package/dist/agent/scene/buildSmartChatReport.js +333 -0
  11. package/dist/agent/scene/buildSmartChatReport.js.map +1 -0
  12. package/dist/agent/scene/sceneAnalysisJobRunner.d.ts +8 -4
  13. package/dist/agent/scene/sceneAnalysisJobRunner.d.ts.map +1 -1
  14. package/dist/agent/scene/sceneAnalysisJobRunner.js +78 -3
  15. package/dist/agent/scene/sceneAnalysisJobRunner.js.map +1 -1
  16. package/dist/agent/scene/sceneIntervalBuilder.d.ts +14 -5
  17. package/dist/agent/scene/sceneIntervalBuilder.d.ts.map +1 -1
  18. package/dist/agent/scene/sceneIntervalBuilder.js +578 -1
  19. package/dist/agent/scene/sceneIntervalBuilder.js.map +1 -1
  20. package/dist/agent/scene/sceneStage1Verifier.d.ts +8 -0
  21. package/dist/agent/scene/sceneStage1Verifier.d.ts.map +1 -0
  22. package/dist/agent/scene/sceneStage1Verifier.js +245 -0
  23. package/dist/agent/scene/sceneStage1Verifier.js.map +1 -0
  24. package/dist/agent/scene/sceneStoryService.d.ts +20 -2
  25. package/dist/agent/scene/sceneStoryService.d.ts.map +1 -1
  26. package/dist/agent/scene/sceneStoryService.js +238 -25
  27. package/dist/agent/scene/sceneStoryService.js.map +1 -1
  28. package/dist/agent/scene/smartCancelBridge.d.ts +13 -0
  29. package/dist/agent/scene/smartCancelBridge.d.ts.map +1 -0
  30. package/dist/agent/scene/smartCancelBridge.js +44 -0
  31. package/dist/agent/scene/smartCancelBridge.js.map +1 -0
  32. package/dist/agent/scene/smartDeepDiveDispatch.d.ts +15 -0
  33. package/dist/agent/scene/smartDeepDiveDispatch.d.ts.map +1 -0
  34. package/dist/agent/scene/smartDeepDiveDispatch.js +170 -0
  35. package/dist/agent/scene/smartDeepDiveDispatch.js.map +1 -0
  36. package/dist/agent/scene/types.d.ts +97 -6
  37. package/dist/agent/scene/types.d.ts.map +1 -1
  38. package/dist/agent/types.d.ts +1 -1
  39. package/dist/agent/types.d.ts.map +1 -1
  40. package/dist/agent/types.js.map +1 -1
  41. package/dist/agentv3/claudeMcpServer.d.ts.map +1 -1
  42. package/dist/agentv3/claudeMcpServer.js +3 -2
  43. package/dist/agentv3/claudeMcpServer.js.map +1 -1
  44. package/dist/agentv3/claudeSystemPrompt.d.ts.map +1 -1
  45. package/dist/agentv3/claudeSystemPrompt.js +8 -0
  46. package/dist/agentv3/claudeSystemPrompt.js.map +1 -1
  47. package/dist/agentv3/queryComplexityClassifier.d.ts +1 -1
  48. package/dist/agentv3/queryComplexityClassifier.d.ts.map +1 -1
  49. package/dist/agentv3/queryComplexityClassifier.js +20 -7
  50. package/dist/agentv3/queryComplexityClassifier.js.map +1 -1
  51. package/dist/agentv3/strategyLoader.d.ts +3 -0
  52. package/dist/agentv3/strategyLoader.d.ts.map +1 -1
  53. package/dist/agentv3/strategyLoader.js +17 -4
  54. package/dist/agentv3/strategyLoader.js.map +1 -1
  55. package/dist/agentv3/types.d.ts +5 -1
  56. package/dist/agentv3/types.d.ts.map +1 -1
  57. package/dist/agentv3/types.js.map +1 -1
  58. package/dist/config/index.d.ts +12 -0
  59. package/dist/config/index.d.ts.map +1 -1
  60. package/dist/config/index.js +6 -0
  61. package/dist/config/index.js.map +1 -1
  62. package/dist/routes/agent/finalizeAgentDrivenSession.d.ts +67 -0
  63. package/dist/routes/agent/finalizeAgentDrivenSession.d.ts.map +1 -0
  64. package/dist/routes/agent/finalizeAgentDrivenSession.js +103 -0
  65. package/dist/routes/agent/finalizeAgentDrivenSession.js.map +1 -0
  66. package/dist/routes/agent/normalizeAnalyzeOptions.d.ts +42 -0
  67. package/dist/routes/agent/normalizeAnalyzeOptions.d.ts.map +1 -0
  68. package/dist/routes/agent/normalizeAnalyzeOptions.js +185 -0
  69. package/dist/routes/agent/normalizeAnalyzeOptions.js.map +1 -0
  70. package/dist/routes/agentRoutes.d.ts.map +1 -1
  71. package/dist/routes/agentRoutes.js +285 -125
  72. package/dist/routes/agentRoutes.js.map +1 -1
  73. package/dist/scripts/verifyAgentSseScrolling.js +131 -8
  74. package/dist/scripts/verifyAgentSseScrolling.js.map +1 -1
  75. package/dist/services/sceneReport/sceneJobArtifactStore.d.ts +22 -0
  76. package/dist/services/sceneReport/sceneJobArtifactStore.d.ts.map +1 -0
  77. package/dist/services/sceneReport/sceneJobArtifactStore.js +65 -0
  78. package/dist/services/sceneReport/sceneJobArtifactStore.js.map +1 -0
  79. package/dist/services/sceneReport/sceneReportMemoryCache.d.ts +5 -3
  80. package/dist/services/sceneReport/sceneReportMemoryCache.d.ts.map +1 -1
  81. package/dist/services/sceneReport/sceneReportMemoryCache.js +15 -10
  82. package/dist/services/sceneReport/sceneReportMemoryCache.js.map +1 -1
  83. package/dist/services/sceneReport/sceneReportStore.d.ts +9 -4
  84. package/dist/services/sceneReport/sceneReportStore.d.ts.map +1 -1
  85. package/dist/services/sceneReport/sceneReportStore.js +27 -7
  86. package/dist/services/sceneReport/sceneReportStore.js.map +1 -1
  87. package/dist/services/traceProcessor/sqlSemaphore.d.ts +16 -0
  88. package/dist/services/traceProcessor/sqlSemaphore.d.ts.map +1 -0
  89. package/dist/services/traceProcessor/sqlSemaphore.js +63 -0
  90. package/dist/services/traceProcessor/sqlSemaphore.js.map +1 -0
  91. package/dist/types/dataContract.d.ts +1 -1
  92. package/dist/types/dataContract.d.ts.map +1 -1
  93. package/dist/types/dataContract.js +2 -0
  94. package/dist/types/dataContract.js.map +1 -1
  95. package/package.json +1 -1
  96. package/skills/README.md +13 -5
  97. package/skills/composite/device_state_snapshot.skill.yaml +204 -0
  98. package/skills/composite/scene_reconstruction.skill.yaml +5 -1
  99. package/skills/composite/selection_range_cpu_sched_summary.skill.yaml +428 -0
  100. package/strategies/scene-reconstruction-verifier.template.md +18 -0
  101. package/strategies/scrolling.strategy.md +5 -1
  102. package/strategies/selection-area.template.md +24 -9
  103. package/strategies/smart.strategy.md +53 -0
  104. package/skills/atomic/device_state_snapshot.skill.yaml +0 -171
@@ -68,8 +68,12 @@ const conclusionSceneTemplates_1 = require("../agent/core/conclusionSceneTemplat
68
68
  const analysisNarrative_1 = require("../utils/analysisNarrative");
69
69
  const agentSceneReconstructRoutes_1 = require("./agentSceneReconstructRoutes");
70
70
  const sceneStoryService_1 = require("../agent/scene/sceneStoryService");
71
+ const buildSmartChatReport_1 = require("../agent/scene/buildSmartChatReport");
72
+ const smartDeepDiveDispatch_1 = require("../agent/scene/smartDeepDiveDispatch");
73
+ const smartCancelBridge_1 = require("../agent/scene/smartCancelBridge");
71
74
  const sceneReportStore_1 = require("../services/sceneReport/sceneReportStore");
72
75
  const sceneReportMemoryCache_1 = require("../services/sceneReport/sceneReportMemoryCache");
76
+ const sceneJobArtifactStore_1 = require("../services/sceneReport/sceneJobArtifactStore");
73
77
  const traceHash_1 = require("../agent/scene/traceHash");
74
78
  const sceneTraceDurationProbe_1 = require("../agent/scene/sceneTraceDurationProbe");
75
79
  const config_1 = require("../config");
@@ -85,6 +89,8 @@ const agentReportRoutes_1 = require("./agentReportRoutes");
85
89
  const agentResumeRoutes_1 = require("./agentResumeRoutes");
86
90
  const agentSessionCatalogRoutes_1 = require("./agentSessionCatalogRoutes");
87
91
  const agentTeachingRoutes_1 = require("./agentTeachingRoutes");
92
+ const normalizeAnalyzeOptions_1 = require("./agent/normalizeAnalyzeOptions");
93
+ const finalizeAgentDrivenSession_1 = require("./agent/finalizeAgentDrivenSession");
88
94
  const assistantApplicationService_1 = require("../assistant/application/assistantApplicationService");
89
95
  const streamProjector_1 = require("../assistant/stream/streamProjector");
90
96
  const sessionSseReplay_1 = require("../assistant/stream/sessionSseReplay");
@@ -271,6 +277,7 @@ router.use((req, res, next) => {
271
277
  router.use(auth_1.authenticate);
272
278
  const assistantAppService = new assistantApplicationService_1.AssistantApplicationService();
273
279
  const streamProjector = new streamProjector_1.StreamProjector();
280
+ const smartCancelBridge = new smartCancelBridge_1.SmartCancelBridge();
274
281
  function agentEventScopeFromSession(session) {
275
282
  const run = session.activeRun || session.lastRun;
276
283
  if (!(0, config_1.resolveFeatureConfig)().enterprise ||
@@ -903,7 +910,7 @@ async function handleAnalyzeRequest(req, res, requestedSessionIdOverride) {
903
910
  try {
904
911
  const requestId = getRequestId(req);
905
912
  const requestContext = (0, auth_1.requireRequestContext)(req);
906
- const { traceId, query, sessionId: bodyRequestedSessionId, options = {}, selectionContext: rawSelectionContext, referenceTraceId, traceContext: rawTraceContext, providerId, } = req.body;
913
+ const { traceId, query, sessionId: bodyRequestedSessionId, options: rawOptions = {}, selectionContext: rawSelectionContext, referenceTraceId, traceContext: rawTraceContext, providerId, } = req.body;
907
914
  const requestedSessionId = requestedSessionIdOverride || bodyRequestedSessionId;
908
915
  if (!(0, rbac_1.hasRbacPermission)(requestContext, 'agent:run')) {
909
916
  (0, rbac_1.sendForbidden)(res, 'Starting analysis requires agent:run permission');
@@ -937,6 +944,24 @@ async function handleAnalyzeRequest(req, res, requestedSessionIdOverride) {
937
944
  });
938
945
  return;
939
946
  }
947
+ let options;
948
+ try {
949
+ options = (0, normalizeAnalyzeOptions_1.normalizeAnalyzeOptions)(rawOptions, {
950
+ endpoint: requestedSessionIdOverride ? '/sessions/:id/runs' : '/analyze',
951
+ hasReferenceTraceId: !!referenceTraceId,
952
+ });
953
+ }
954
+ catch (error) {
955
+ if (error instanceof normalizeAnalyzeOptions_1.AnalyzeOptionsError) {
956
+ res.status(error.httpStatus).json({
957
+ success: false,
958
+ error: error.message,
959
+ code: error.code,
960
+ });
961
+ return;
962
+ }
963
+ throw error;
964
+ }
940
965
  if (requestedSessionId && !requestedSessionIsVisible(requestedSessionId, requestContext)) {
941
966
  (0, resourceOwnership_1.sendResourceNotFound)(res, 'Session not found');
942
967
  return;
@@ -1080,6 +1105,49 @@ async function handleAnalyzeRequest(req, res, requestedSessionIdOverride) {
1080
1105
  runId: runContext.runId,
1081
1106
  runSequence: runContext.sequence,
1082
1107
  });
1108
+ if (options.preset === 'smart') {
1109
+ runSmartAnalysis(sessionId, query, traceId, {
1110
+ runContext,
1111
+ traceProcessorService,
1112
+ smartAction: options.smartAction ?? 'preview',
1113
+ smartSelection: options.smartSelection,
1114
+ forceRefresh: options.forceRefresh === true,
1115
+ analysisMode: options.analysisMode,
1116
+ blockedStrategyIds,
1117
+ owner: (0, resourceOwnership_1.ownerFieldsFromContext)(requestContext),
1118
+ }).catch((error) => {
1119
+ const session = assistantAppService.getSession(sessionId);
1120
+ if (session) {
1121
+ session.logger.error('AgentRoutes', 'Smart analysis failed', error);
1122
+ session.status = 'failed';
1123
+ session.error = error.message;
1124
+ markSessionRunStatus(session, 'failed', error.message);
1125
+ broadcastToAgentDrivenClients(sessionId, {
1126
+ type: 'error',
1127
+ content: { message: error.message, error: error.message },
1128
+ timestamp: Date.now(),
1129
+ });
1130
+ }
1131
+ });
1132
+ res.json({
1133
+ success: true,
1134
+ sessionId,
1135
+ message: isNewSession ? 'Smart analysis started' : 'Smart analysis started',
1136
+ isNewSession,
1137
+ providerSnapshotChanged: preparedSession?.providerSnapshotChanged || undefined,
1138
+ architecture: 'agent-driven',
1139
+ preset: 'smart',
1140
+ runId: runContext.runId,
1141
+ requestId: runContext.requestId,
1142
+ runSequence: runContext.sequence,
1143
+ observability: {
1144
+ runId: runContext.runId,
1145
+ requestId: runContext.requestId,
1146
+ runSequence: runContext.sequence,
1147
+ },
1148
+ });
1149
+ return;
1150
+ }
1083
1151
  let agentRunLease = null;
1084
1152
  let referenceAgentRunLease = null;
1085
1153
  let agentRunLeaseDecision = null;
@@ -1840,6 +1908,10 @@ router.post('/:sessionId/cancel', (req, res) => {
1840
1908
  return;
1841
1909
  // Mark session as failed/cancelled
1842
1910
  if (session.status === 'running' || session.status === 'pending') {
1911
+ const smartCancelled = smartCancelBridge.cancel(sessionId);
1912
+ if (smartCancelled)
1913
+ smartCancelBridge.tryClaimTerminal(sessionId);
1914
+ const sceneCancelled = sceneStoryService.cancel(sessionId);
1843
1915
  session.status = 'failed';
1844
1916
  session.error = 'Cancelled by user';
1845
1917
  markSessionRunStatus(session, 'failed', 'Cancelled by user');
@@ -1857,7 +1929,11 @@ router.post('/:sessionId/cancel', (req, res) => {
1857
1929
  catch { /* client may already be closed */ }
1858
1930
  }
1859
1931
  session.sseClients = [];
1860
- session.logger.info('AgentRoutes', 'Session cancelled by user', { sessionId });
1932
+ session.logger.info('AgentRoutes', 'Session cancelled by user', {
1933
+ sessionId,
1934
+ smartCancelled,
1935
+ sceneCancelled,
1936
+ });
1861
1937
  }
1862
1938
  return res.json({ success: true, sessionId, status: session.status });
1863
1939
  });
@@ -2000,6 +2076,7 @@ router.get('/:sessionId/focus', (req, res) => {
2000
2076
  // traces (no content hash, so they live for the lifetime of the backend).
2001
2077
  const sceneReportStore = new sceneReportStore_1.FileSystemSceneReportStore(config_1.sceneStoryConfig.reportDir);
2002
2078
  const sceneReportMemoryCache = new sceneReportMemoryCache_1.SceneReportMemoryCache(config_1.sceneStoryConfig.memoryCacheMaxSize);
2079
+ const sceneJobArtifactStore = new sceneJobArtifactStore_1.FileSystemSceneJobArtifactStore(config_1.sceneStoryConfig.jobArtifactDir);
2003
2080
  // Singleton — sceneStoryService holds per-session JobRunner state for cancel
2004
2081
  // lookup, so it must outlive a single request. SkillExecutor is still created
2005
2082
  // per-request inside the route handler.
@@ -2008,6 +2085,7 @@ const sceneStoryService = new sceneStoryService_1.SceneStoryService({
2008
2085
  getSession: (id) => assistantAppService.getSession(id),
2009
2086
  reportStore: sceneReportStore,
2010
2087
  memoryCache: sceneReportMemoryCache,
2088
+ jobArtifactStore: sceneJobArtifactStore,
2011
2089
  computeHash: (traceId) => (0, traceHash_1.computeTraceContentHash)((0, traceProcessorService_1.getTraceProcessorService)(), traceId),
2012
2090
  probeDuration: (traceId) => (0, sceneTraceDurationProbe_1.probeTraceDuration)((0, traceProcessorService_1.getTraceProcessorService)(), traceId),
2013
2091
  });
@@ -2043,6 +2121,196 @@ const SCENE_EXTRACTION_STEP_IDS = new Set([
2043
2121
  'jank_events',
2044
2122
  'clean_timeline',
2045
2123
  ]);
2124
+ async function runSmartAnalysis(sessionId, query, traceId, options) {
2125
+ const session = assistantAppService.getSession(sessionId);
2126
+ if (!session)
2127
+ return;
2128
+ const startedAt = Date.now();
2129
+ session.activeRun = {
2130
+ ...options.runContext,
2131
+ query,
2132
+ status: 'running',
2133
+ startedAt: options.runContext.startedAt || startedAt,
2134
+ };
2135
+ session.lastRun = { ...session.activeRun };
2136
+ session.status = 'running';
2137
+ session.lastActivityAt = Date.now();
2138
+ persistSessionRunState(session, 'running');
2139
+ const runHeartbeatInterval = startSessionRunHeartbeat(session);
2140
+ const cancelToken = smartCancelBridge.create(sessionId);
2141
+ let dispatchedToAgentDeepDive = false;
2142
+ session.logger.info('SmartAnalysis', 'Starting smart analysis', {
2143
+ query,
2144
+ traceId,
2145
+ smartAction: options.smartAction,
2146
+ smartSelection: options.smartSelection,
2147
+ runId: session.activeRun?.runId,
2148
+ requestId: session.activeRun?.requestId,
2149
+ });
2150
+ try {
2151
+ await (0, skillLoader_1.ensureSkillRegistryInitialized)();
2152
+ const skillExecutor = new skillExecutor_1.SkillExecutor(options.traceProcessorService);
2153
+ skillExecutor.registerSkills(skillLoader_1.skillRegistry.getAllSkills());
2154
+ let report = null;
2155
+ if (options.smartAction === 'analyze') {
2156
+ report = await resolveSmartPreviewReportForSelection({
2157
+ session,
2158
+ selection: options.smartSelection,
2159
+ traceId,
2160
+ owner: options.owner,
2161
+ });
2162
+ }
2163
+ if (!report) {
2164
+ report = await sceneStoryService.start({
2165
+ sessionId,
2166
+ traceId,
2167
+ skillExecutor,
2168
+ owner: options.owner,
2169
+ options: {
2170
+ routeProfile: 'smart',
2171
+ previewOnly: true,
2172
+ forceRefresh: options.smartAction === 'preview'
2173
+ ? true
2174
+ : options.forceRefresh,
2175
+ cancelToken,
2176
+ },
2177
+ });
2178
+ }
2179
+ if (!report) {
2180
+ throw new Error(session.error || 'Smart analysis failed before report finalization');
2181
+ }
2182
+ if (options.smartAction === 'preview') {
2183
+ const result = (0, buildSmartChatReport_1.buildSmartSceneSelectionReport)({
2184
+ sessionId,
2185
+ report,
2186
+ totalDurationMs: Date.now() - startedAt,
2187
+ });
2188
+ if (!smartCancelBridge.tryClaimTerminal(sessionId)) {
2189
+ session.logger.warn('SmartAnalysis', 'Skipping late smart preview terminal', {
2190
+ sessionId,
2191
+ runId: session.activeRun?.runId,
2192
+ });
2193
+ return;
2194
+ }
2195
+ completeAgentDrivenSessionWithResult({
2196
+ sessionId,
2197
+ query,
2198
+ traceId,
2199
+ session,
2200
+ result,
2201
+ logComponent: 'SmartAnalysis',
2202
+ });
2203
+ return;
2204
+ }
2205
+ const dispatch = (0, smartDeepDiveDispatch_1.buildSmartDeepDiveDispatch)({
2206
+ report,
2207
+ selection: options.smartSelection ?? { scope: 'all' },
2208
+ });
2209
+ if (!dispatch) {
2210
+ throw new Error('所选范围没有匹配到可深钻场景,请返回场景盘点后重新选择。');
2211
+ }
2212
+ session.logger.info('SmartAnalysis', 'Dispatching smart selection to agent deep dive', {
2213
+ query: dispatch.query,
2214
+ selectedSceneCount: dispatch.selectedScenes.length,
2215
+ packageName: dispatch.packageName,
2216
+ previewReportId: report.reportId,
2217
+ runId: session.activeRun?.runId,
2218
+ requestId: session.activeRun?.requestId,
2219
+ });
2220
+ broadcastToAgentDrivenClients(sessionId, {
2221
+ type: 'progress',
2222
+ content: {
2223
+ phase: 'smart_deep_dive_dispatch',
2224
+ message: `已选中 ${dispatch.selectedScenes.length} 个场景,进入详细分析`,
2225
+ },
2226
+ timestamp: Date.now(),
2227
+ });
2228
+ dispatchedToAgentDeepDive = true;
2229
+ await runAgentDrivenAnalysis(sessionId, dispatch.query, traceId, {
2230
+ traceProcessorService: options.traceProcessorService,
2231
+ runContext: options.runContext,
2232
+ blockedStrategyIds: options.blockedStrategyIds,
2233
+ selectionContext: dispatch.selectionContext,
2234
+ traceContext: dispatch.traceContext,
2235
+ packageName: dispatch.packageName,
2236
+ analysisMode: resolveSmartDeepDiveAnalysisMode(options.analysisMode),
2237
+ generateTracks: false,
2238
+ });
2239
+ }
2240
+ catch (error) {
2241
+ session.status = 'failed';
2242
+ session.error = error.message || String(error);
2243
+ markSessionRunStatus(session, 'failed', session.error);
2244
+ session.logger.error('SmartAnalysis', 'Smart analysis failed', error);
2245
+ if (!dispatchedToAgentDeepDive && smartCancelBridge.tryClaimTerminal(sessionId)) {
2246
+ broadcastToAgentDrivenClients(sessionId, {
2247
+ type: 'error',
2248
+ content: { message: session.error, error: session.error },
2249
+ timestamp: Date.now(),
2250
+ });
2251
+ }
2252
+ }
2253
+ finally {
2254
+ smartCancelBridge.release(sessionId);
2255
+ if (runHeartbeatInterval) {
2256
+ clearInterval(runHeartbeatInterval);
2257
+ }
2258
+ }
2259
+ }
2260
+ function resolveSmartDeepDiveAnalysisMode(mode) {
2261
+ return mode === 'fast' ? 'fast' : 'full';
2262
+ }
2263
+ async function resolveSmartPreviewReportForSelection(input) {
2264
+ const requestedReportId = input.selection?.reportId || input.selection?.sceneSnapshotId;
2265
+ const sessionReport = input.session.sceneStoryReport;
2266
+ if (isUsableSmartPreviewReport(sessionReport, input.traceId, input.owner, requestedReportId)) {
2267
+ return sessionReport;
2268
+ }
2269
+ if (!requestedReportId)
2270
+ return null;
2271
+ const persisted = await sceneStoryService.getReport(requestedReportId);
2272
+ if (isUsableSmartPreviewReport(persisted, input.traceId, input.owner, requestedReportId)) {
2273
+ return persisted;
2274
+ }
2275
+ return null;
2276
+ }
2277
+ function isUsableSmartPreviewReport(report, traceId, owner, requestedReportId) {
2278
+ if (!report)
2279
+ return false;
2280
+ if (requestedReportId && report.reportId !== requestedReportId)
2281
+ return false;
2282
+ if (report.traceId !== traceId)
2283
+ return false;
2284
+ return (0, resourceOwnership_1.ownersMatch)(report, owner);
2285
+ }
2286
+ function completeAgentDrivenSessionWithResult(input) {
2287
+ (0, finalizeAgentDrivenSession_1.finalizeAgentDrivenSession)(input, {
2288
+ applyFinalResultQualityGate: finalResultQualityGate_1.applyFinalResultQualityGate,
2289
+ broadcast: broadcastToAgentDrivenClients,
2290
+ buildConversationStepUpdate,
2291
+ appendConversationStep,
2292
+ annotateLatestCompletedTurn: (sessionId, traceId, result) => {
2293
+ enhancedSessionContext_1.sessionContextManager.get(sessionId, traceId)?.annotateLatestCompletedTurn({
2294
+ success: result.success,
2295
+ findings: result.findings,
2296
+ message: result.conclusion,
2297
+ confidence: result.confidence,
2298
+ partial: result.partial,
2299
+ terminationReason: result.terminationReason,
2300
+ terminationMessage: result.terminationMessage,
2301
+ conclusionContract: result.conclusionContract,
2302
+ claimSupport: result.claimSupport,
2303
+ claimVerificationResult: result.claimVerificationResult,
2304
+ identityResolutions: result.identityResolutions,
2305
+ });
2306
+ },
2307
+ terminalRunStatusForResult,
2308
+ markSessionRunStatus,
2309
+ persistAgentTurn: persistAgentSession_1.persistAgentTurn,
2310
+ ensureCompletedAnalysisSseEvents,
2311
+ sendAgentDrivenResult,
2312
+ });
2313
+ }
2046
2314
  function objectRowsToEnvelopePayload(rows) {
2047
2315
  if (!Array.isArray(rows) || rows.length === 0) {
2048
2316
  return { columns: [], rows: [] };
@@ -2640,33 +2908,6 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2640
2908
  return runWithTraceProcessorLease(analyze);
2641
2909
  });
2642
2910
  console.log('[AgentRoutes.AgentDriven] analyze completed, success:', result.success);
2643
- session.result = result;
2644
- delete session.completedAnalysisFinalArtifacts;
2645
- // Accumulate hypotheses across turns (deduplicate by id)
2646
- const existingIds = new Set(session.hypotheses.map(h => h.id));
2647
- for (const h of result.hypotheses) {
2648
- if (!existingIds.has(h.id)) {
2649
- session.hypotheses.push(h);
2650
- }
2651
- else {
2652
- // Update existing hypothesis with latest status
2653
- const idx = session.hypotheses.findIndex(eh => eh.id === h.id);
2654
- if (idx >= 0)
2655
- session.hypotheses[idx] = h;
2656
- }
2657
- }
2658
- const terminalRunStatus = terminalRunStatusForResult(result);
2659
- // Record conclusion in cross-turn history
2660
- if (!session.conclusionHistory)
2661
- session.conclusionHistory = [];
2662
- if (result.conclusion) {
2663
- session.conclusionHistory.push({
2664
- turn: session.runSequence || 1,
2665
- conclusion: result.conclusion,
2666
- confidence: result.confidence ?? 0,
2667
- timestamp: Date.now(),
2668
- });
2669
- }
2670
2911
  // Ensure trackEvents/scenes are computed for completed sessions (even without SSE clients)
2671
2912
  if (shouldGenerateTracks) {
2672
2913
  updateSceneReconstructionArtifactsFromEnvelopes(session, session.dataEnvelopes);
@@ -2709,101 +2950,16 @@ async function runAgentDrivenAnalysis(sessionId, query, traceId, options = {}) {
2709
2950
  if (normalizedConclusionContract) {
2710
2951
  result.conclusionContract = normalizedConclusionContract;
2711
2952
  }
2712
- ensureAnalysisQualityArtifacts(session, normalizedConclusionContract);
2713
- }
2714
- const finalQualityIssue = (0, finalResultQualityGate_1.applyFinalResultQualityGate)({ result, query });
2715
- if (finalQualityIssue) {
2716
- const message = result.terminationMessage || finalQualityIssue.message;
2717
- logger.warn('AgentDrivenAnalysis', 'Final result quality gate marked result partial', {
2718
- code: finalQualityIssue.code,
2719
- conclusionChars: result.conclusion.length,
2720
- findingsCount: result.findings.length,
2721
- hasConclusionContract: !!result.conclusionContract,
2722
- claimVerifierStatus: result.claimVerificationResult?.status,
2723
- runId: session.activeRun?.runId,
2724
- requestId: session.activeRun?.requestId,
2725
- });
2726
- const update = {
2727
- type: 'degraded',
2728
- content: {
2729
- module: 'agentRoutes',
2730
- fallback: 'final_result_quality_gate',
2731
- code: finalQualityIssue.code,
2732
- partial: true,
2733
- message,
2734
- },
2735
- timestamp: Date.now(),
2736
- };
2737
- broadcastToAgentDrivenClients(sessionId, update);
2738
- const conversationStep = buildConversationStepUpdate(session, update);
2739
- if (conversationStep) {
2740
- appendConversationStep(session, conversationStep);
2741
- broadcastToAgentDrivenClients(sessionId, conversationStep);
2742
- }
2953
+ ensureAnalysisQualityArtifacts(session, normalizedConclusionContract, result);
2743
2954
  }
2744
- const currentTurn = session.runSequence || 1;
2745
- const latestConclusionHistory = session.conclusionHistory?.[session.conclusionHistory.length - 1];
2746
- if (latestConclusionHistory?.turn === currentTurn) {
2747
- latestConclusionHistory.confidence = result.confidence ?? latestConclusionHistory.confidence;
2748
- }
2749
- enhancedSessionContext_1.sessionContextManager.get(sessionId, traceId)?.annotateLatestCompletedTurn({
2750
- success: result.success,
2751
- findings: result.findings,
2752
- message: result.conclusion,
2753
- confidence: result.confidence,
2754
- partial: result.partial,
2755
- terminationReason: result.terminationReason,
2756
- terminationMessage: result.terminationMessage,
2757
- conclusionContract: result.conclusionContract,
2758
- claimSupport: result.claimSupport,
2759
- claimVerificationResult: result.claimVerificationResult,
2760
- identityResolutions: result.identityResolutions,
2761
- });
2762
- session.status = terminalRunStatus === 'quota_exceeded'
2763
- ? 'quota_exceeded'
2764
- : result.success ? 'completed' : 'failed';
2765
- markSessionRunStatus(session, terminalRunStatus);
2766
- // Log completion details
2767
- logger.info('AgentDrivenAnalysis', 'Agent-driven analysis completed', {
2768
- confidence: result.confidence,
2769
- rounds: result.rounds,
2770
- findingsCount: result.findings.length,
2771
- hypothesesCount: result.hypotheses.length,
2772
- claimSupportCount: result.claimSupport?.length || 0,
2773
- claimVerifierStatus: result.claimVerificationResult?.status,
2774
- partial: result.partial,
2775
- terminationReason: result.terminationReason,
2776
- runId: session.activeRun?.runId,
2777
- requestId: session.activeRun?.requestId,
2778
- runSequence: session.activeRun?.sequence,
2779
- });
2780
- // Persist session state via shared helper — see services/persistAgentSession.ts.
2781
- // CLI's cliAnalyzeService routes through the same function.
2782
- (0, persistAgentSession_1.persistAgentTurn)({
2783
- session,
2955
+ completeAgentDrivenSessionWithResult({
2784
2956
  sessionId,
2785
- traceId,
2786
2957
  query,
2787
- result: { conclusion: result.conclusion, totalDurationMs: result.totalDurationMs },
2788
- logger,
2789
- // Preserve the legacy component label so any log filters / alerts keyed
2790
- // on 'AgentDrivenAnalysis' keep matching persist-related events.
2958
+ traceId,
2959
+ session,
2960
+ result,
2791
2961
  logComponent: 'AgentDrivenAnalysis',
2792
2962
  });
2793
- // Send final result
2794
- const clientCount = session.sseClients.length;
2795
- logger.info('AgentRoutes', 'Sending agent-driven result', { clientCount });
2796
- ensureCompletedAnalysisSseEvents(session);
2797
- session.sseClients.forEach((client, index) => {
2798
- try {
2799
- logger.info('AgentRoutes', `Sending agent-driven result to client ${index + 1}/${clientCount}`);
2800
- sendAgentDrivenResult(client, session);
2801
- }
2802
- catch (e) {
2803
- logger.error('AgentRoutes', `Error sending agent-driven result to client ${index + 1}`, e);
2804
- }
2805
- });
2806
- logger.close();
2807
2963
  }
2808
2964
  catch (error) {
2809
2965
  session.status = 'failed';
@@ -4488,6 +4644,7 @@ function ensureCompletedAnalysisResultPayload(session) {
4488
4644
  return undefined;
4489
4645
  const replayOnlyScene = isSceneReplayOnlyQuery(session.query);
4490
4646
  const hasEvidenceBackedConclusion = result.success || result.partial === true;
4647
+ const isSmartResult = result.conclusionContract?.metadata?.sceneId === 'smart';
4491
4648
  const normalizedConclusion = replayOnlyScene
4492
4649
  ? buildSceneReplayNarrative(session.scenes || [])
4493
4650
  : hasEvidenceBackedConclusion ? appendEvidenceIndexIfMissing(normalizeNarrativeForClient(result.conclusion), session.dataEnvelopes || []) : normalizeNarrativeForClient(result.conclusion);
@@ -4500,12 +4657,14 @@ function ensureCompletedAnalysisResultPayload(session) {
4500
4657
  });
4501
4658
  const normalizedConclusionContract = replayOnlyScene
4502
4659
  ? undefined
4503
- : hasEvidenceBackedConclusion ? ((0, agentResultNormalizer_1.deriveEvidenceBackedConclusionContractForNarrative)(result.conclusion, session.dataEnvelopes || [], {
4504
- existingContract: result.conclusionContract,
4505
- mode: result.rounds > 1 ? 'focused_answer' : 'initial_report',
4506
- sceneId: sceneIdHint,
4507
- }) ||
4508
- undefined) : undefined;
4660
+ : isSmartResult
4661
+ ? result.conclusionContract
4662
+ : hasEvidenceBackedConclusion ? ((0, agentResultNormalizer_1.deriveEvidenceBackedConclusionContractForNarrative)(result.conclusion, session.dataEnvelopes || [], {
4663
+ existingContract: result.conclusionContract,
4664
+ mode: result.rounds > 1 ? 'focused_answer' : 'initial_report',
4665
+ sceneId: sceneIdHint,
4666
+ }) ||
4667
+ undefined) : undefined;
4509
4668
  const qualityArtifacts = hasEvidenceBackedConclusion && !replayOnlyScene
4510
4669
  ? ensureAnalysisQualityArtifacts(session, normalizedConclusionContract)
4511
4670
  : {};
@@ -4613,6 +4772,7 @@ function ensureCompletedAnalysisSseEvents(session) {
4613
4772
  partial: result.partial,
4614
4773
  terminationReason: result.terminationReason,
4615
4774
  terminationMessage: result.terminationMessage,
4775
+ smartScenePreview: result.smartScenePreview,
4616
4776
  findings: clientFindings,
4617
4777
  resultContract,
4618
4778
  hypotheses: result.hypotheses.map((h) => ({