@gracker/smartperfetto 1.0.18 → 1.0.20

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 (163) hide show
  1. package/dist/agent/core/conclusionContract.d.ts +1 -0
  2. package/dist/agent/core/conclusionContract.d.ts.map +1 -1
  3. package/dist/agent/tools/frameAnalyzer.d.ts.map +1 -1
  4. package/dist/agent/tools/frameAnalyzer.js +1 -0
  5. package/dist/agent/tools/frameAnalyzer.js.map +1 -1
  6. package/dist/agentOpenAI/openAiRuntime.d.ts +24 -0
  7. package/dist/agentOpenAI/openAiRuntime.d.ts.map +1 -1
  8. package/dist/agentOpenAI/openAiRuntime.js +171 -195
  9. package/dist/agentOpenAI/openAiRuntime.js.map +1 -1
  10. package/dist/agentRuntime/index.d.ts +1 -0
  11. package/dist/agentRuntime/index.d.ts.map +1 -1
  12. package/dist/agentRuntime/index.js +16 -1
  13. package/dist/agentRuntime/index.js.map +1 -1
  14. package/dist/agentRuntime/runtimeCommon.d.ts +34 -0
  15. package/dist/agentRuntime/runtimeCommon.d.ts.map +1 -0
  16. package/dist/agentRuntime/runtimeCommon.js +231 -0
  17. package/dist/agentRuntime/runtimeCommon.js.map +1 -0
  18. package/dist/agentv3/claudeConfig.d.ts +6 -2
  19. package/dist/agentv3/claudeConfig.d.ts.map +1 -1
  20. package/dist/agentv3/claudeConfig.js +50 -48
  21. package/dist/agentv3/claudeConfig.js.map +1 -1
  22. package/dist/agentv3/claudeMcpServer.d.ts.map +1 -1
  23. package/dist/agentv3/claudeMcpServer.js +74 -66
  24. package/dist/agentv3/claudeMcpServer.js.map +1 -1
  25. package/dist/agentv3/claudeRuntime.d.ts +18 -2
  26. package/dist/agentv3/claudeRuntime.d.ts.map +1 -1
  27. package/dist/agentv3/claudeRuntime.js +201 -268
  28. package/dist/agentv3/claudeRuntime.js.map +1 -1
  29. package/dist/agentv3/claudeSseBridge.js +1 -1
  30. package/dist/agentv3/claudeSseBridge.js.map +1 -1
  31. package/dist/agentv3/claudeSystemPrompt.d.ts.map +1 -1
  32. package/dist/agentv3/claudeSystemPrompt.js +14 -1
  33. package/dist/agentv3/claudeSystemPrompt.js.map +1 -1
  34. package/dist/agentv3/claudeVerifier.d.ts +1 -1
  35. package/dist/agentv3/claudeVerifier.d.ts.map +1 -1
  36. package/dist/agentv3/claudeVerifier.js +42 -19
  37. package/dist/agentv3/claudeVerifier.js.map +1 -1
  38. package/dist/agentv3/strategyLoader.d.ts +28 -0
  39. package/dist/agentv3/strategyLoader.d.ts.map +1 -1
  40. package/dist/agentv3/strategyLoader.js +35 -0
  41. package/dist/agentv3/strategyLoader.js.map +1 -1
  42. package/dist/cli/commands/validate.d.ts.map +1 -1
  43. package/dist/cli/commands/validate.js +120 -10
  44. package/dist/cli/commands/validate.js.map +1 -1
  45. package/dist/cli-user/bin.js +83 -2
  46. package/dist/cli-user/bin.js.map +1 -1
  47. package/dist/cli-user/commands/analyze.d.ts +2 -0
  48. package/dist/cli-user/commands/analyze.d.ts.map +1 -1
  49. package/dist/cli-user/commands/analyze.js +1 -0
  50. package/dist/cli-user/commands/analyze.js.map +1 -1
  51. package/dist/cli-user/commands/capture.d.ts +37 -2
  52. package/dist/cli-user/commands/capture.d.ts.map +1 -1
  53. package/dist/cli-user/commands/capture.js +184 -95
  54. package/dist/cli-user/commands/capture.js.map +1 -1
  55. package/dist/cli-user/commands/codebase.js +4 -4
  56. package/dist/cli-user/commands/codebase.js.map +1 -1
  57. package/dist/cli-user/commands/compare.d.ts +2 -0
  58. package/dist/cli-user/commands/compare.d.ts.map +1 -1
  59. package/dist/cli-user/commands/compare.js +1 -0
  60. package/dist/cli-user/commands/compare.js.map +1 -1
  61. package/dist/cli-user/commands/doctor.js +4 -0
  62. package/dist/cli-user/commands/doctor.js.map +1 -1
  63. package/dist/cli-user/services/androidCapture.d.ts +59 -0
  64. package/dist/cli-user/services/androidCapture.d.ts.map +1 -0
  65. package/dist/cli-user/services/androidCapture.js +375 -0
  66. package/dist/cli-user/services/androidCapture.js.map +1 -0
  67. package/dist/cli-user/services/captureConfig.d.ts +38 -0
  68. package/dist/cli-user/services/captureConfig.d.ts.map +1 -0
  69. package/dist/cli-user/services/captureConfig.js +434 -0
  70. package/dist/cli-user/services/captureConfig.js.map +1 -0
  71. package/dist/cli-user/services/captureTools.d.ts +11 -0
  72. package/dist/cli-user/services/captureTools.d.ts.map +1 -0
  73. package/dist/cli-user/services/captureTools.js +247 -0
  74. package/dist/cli-user/services/captureTools.js.map +1 -0
  75. package/dist/cli-user/services/cliAnalyzeService.d.ts +2 -0
  76. package/dist/cli-user/services/cliAnalyzeService.d.ts.map +1 -1
  77. package/dist/cli-user/services/cliAnalyzeService.js +1 -0
  78. package/dist/cli-user/services/cliAnalyzeService.js.map +1 -1
  79. package/dist/cli-user/services/runtimeGuard.d.ts +10 -0
  80. package/dist/cli-user/services/runtimeGuard.d.ts.map +1 -1
  81. package/dist/cli-user/services/runtimeGuard.js +48 -0
  82. package/dist/cli-user/services/runtimeGuard.js.map +1 -1
  83. package/dist/cli-user/services/turnRunner.d.ts +3 -0
  84. package/dist/cli-user/services/turnRunner.d.ts.map +1 -1
  85. package/dist/cli-user/services/turnRunner.js +4 -0
  86. package/dist/cli-user/services/turnRunner.js.map +1 -1
  87. package/dist/cli-user/types.d.ts +57 -0
  88. package/dist/cli-user/types.d.ts.map +1 -1
  89. package/dist/perfetto-recording-tools-pin.env +24 -0
  90. package/dist/routes/ragAdminRoutes.js +7 -7
  91. package/dist/routes/ragAdminRoutes.js.map +1 -1
  92. package/dist/services/agentResultNormalizer.d.ts.map +1 -1
  93. package/dist/services/agentResultNormalizer.js +32 -4
  94. package/dist/services/agentResultNormalizer.js.map +1 -1
  95. package/dist/services/codebase/pathSecurityGate.d.ts +2 -2
  96. package/dist/services/codebase/pathSecurityGate.d.ts.map +1 -1
  97. package/dist/services/codebase/pathSecurityGate.js +33 -9
  98. package/dist/services/codebase/pathSecurityGate.js.map +1 -1
  99. package/dist/services/evidence/evidenceContractBuilder.d.ts.map +1 -1
  100. package/dist/services/evidence/evidenceContractBuilder.js +17 -3
  101. package/dist/services/evidence/evidenceContractBuilder.js.map +1 -1
  102. package/dist/services/finalReportContractGate.d.ts +13 -0
  103. package/dist/services/finalReportContractGate.d.ts.map +1 -0
  104. package/dist/services/finalReportContractGate.js +48 -0
  105. package/dist/services/finalReportContractGate.js.map +1 -0
  106. package/dist/services/finalResultQualityGate.d.ts +3 -1
  107. package/dist/services/finalResultQualityGate.d.ts.map +1 -1
  108. package/dist/services/finalResultQualityGate.js +18 -1
  109. package/dist/services/finalResultQualityGate.js.map +1 -1
  110. package/dist/services/htmlReportGenerator.d.ts +12 -0
  111. package/dist/services/htmlReportGenerator.d.ts.map +1 -1
  112. package/dist/services/htmlReportGenerator.js +286 -33
  113. package/dist/services/htmlReportGenerator.js.map +1 -1
  114. package/dist/services/perfettoSqlSkill.d.ts.map +1 -1
  115. package/dist/services/perfettoSqlSkill.js +1 -0
  116. package/dist/services/perfettoSqlSkill.js.map +1 -1
  117. package/dist/services/providerManager/connectionTester.d.ts.map +1 -1
  118. package/dist/services/providerManager/connectionTester.js +4 -68
  119. package/dist/services/providerManager/connectionTester.js.map +1 -1
  120. package/dist/services/providerManager/index.d.ts +1 -0
  121. package/dist/services/providerManager/index.d.ts.map +1 -1
  122. package/dist/services/providerManager/index.js +8 -1
  123. package/dist/services/providerManager/index.js.map +1 -1
  124. package/dist/services/providerManager/providerService.d.ts.map +1 -1
  125. package/dist/services/providerManager/providerService.js +37 -106
  126. package/dist/services/providerManager/providerService.js.map +1 -1
  127. package/dist/services/providerManager/providerSnapshot.d.ts.map +1 -1
  128. package/dist/services/providerManager/providerSnapshot.js +13 -12
  129. package/dist/services/providerManager/providerSnapshot.js.map +1 -1
  130. package/dist/services/providerManager/runtimeCapabilities.d.ts +9 -0
  131. package/dist/services/providerManager/runtimeCapabilities.d.ts.map +1 -0
  132. package/dist/services/providerManager/runtimeCapabilities.js +105 -0
  133. package/dist/services/providerManager/runtimeCapabilities.js.map +1 -0
  134. package/dist/services/rag/aospSourceIngester.d.ts +1 -1
  135. package/dist/services/rag/aospSourceIngester.d.ts.map +1 -1
  136. package/dist/services/rag/aospSourceIngester.js +6 -4
  137. package/dist/services/rag/aospSourceIngester.js.map +1 -1
  138. package/dist/services/rag/appSourceIngester.d.ts +1 -1
  139. package/dist/services/rag/appSourceIngester.d.ts.map +1 -1
  140. package/dist/services/rag/appSourceIngester.js +6 -4
  141. package/dist/services/rag/appSourceIngester.js.map +1 -1
  142. package/dist/services/rag/kernelSourceIngester.d.ts +1 -1
  143. package/dist/services/rag/kernelSourceIngester.d.ts.map +1 -1
  144. package/dist/services/rag/kernelSourceIngester.js +6 -4
  145. package/dist/services/rag/kernelSourceIngester.js.map +1 -1
  146. package/dist/services/ragStore.d.ts +2 -0
  147. package/dist/services/ragStore.d.ts.map +1 -1
  148. package/dist/services/ragStore.js +6 -1
  149. package/dist/services/ragStore.js.map +1 -1
  150. package/dist/services/skillEngine/skillExecutor.d.ts +1 -0
  151. package/dist/services/skillEngine/skillExecutor.d.ts.map +1 -1
  152. package/dist/services/skillEngine/skillExecutor.js +64 -12
  153. package/dist/services/skillEngine/skillExecutor.js.map +1 -1
  154. package/package.json +5 -5
  155. package/prebuilts/android-platform-tools/README.md +13 -0
  156. package/prebuilts/perfetto-recording-tools/README.md +17 -0
  157. package/skills/atomic/cpu_topology_detection.skill.yaml +105 -159
  158. package/skills/atomic/cpu_topology_view.skill.yaml +2 -0
  159. package/strategies/prompt-openai-final-report-continuation-en.template.md +5 -1
  160. package/strategies/prompt-openai-final-report-continuation-zh.template.md +5 -1
  161. package/strategies/prompt-output-format.template.md +1 -1
  162. package/strategies/scrolling.strategy.md +22 -0
  163. package/strategies/startup.strategy.md +27 -1
@@ -27,9 +27,7 @@ const queryComplexityClassifier_1 = require("../agentv3/queryComplexityClassifie
27
27
  const openAiComplexityClassifier_1 = require("./openAiComplexityClassifier");
28
28
  const artifactStore_1 = require("../agentv3/artifactStore");
29
29
  const analysisPatternMemory_1 = require("../agentv3/analysisPatternMemory");
30
- const skillNotesInjector_1 = require("../agentv3/selfImprove/skillNotesInjector");
31
30
  const traceCompletenessProber_1 = require("../agentv3/traceCompletenessProber");
32
- const entityCapture_1 = require("../agent/core/entityCapture");
33
31
  const outputLanguage_1 = require("../agentv3/outputLanguage");
34
32
  const codeAwareOutputRegistry_1 = require("../services/security/codeAwareOutputRegistry");
35
33
  const toolNarration_1 = require("../agentv3/toolNarration");
@@ -37,29 +35,17 @@ const openAiConfig_1 = require("./openAiConfig");
37
35
  const mimoReasoningCompat_1 = require("./mimoReasoningCompat");
38
36
  const openAiToolAdapter_1 = require("./openAiToolAdapter");
39
37
  const finalResultQualityGate_1 = require("../services/finalResultQualityGate");
40
- const OPENAI_SESSION_FRESHNESS_MS = 4 * 60 * 60 * 1000;
38
+ const finalReportContractGate_1 = require("../services/finalReportContractGate");
39
+ const runtimeCommon_1 = require("../agentRuntime/runtimeCommon");
40
+ const OPENAI_SESSION_FRESHNESS_MS = runtimeCommon_1.SDK_SESSION_FRESHNESS_MS;
41
41
  const OPENAI_MAX_PLAN_CONTINUATIONS = 3;
42
- const OPENAI_MAX_FINAL_REPORT_CONTINUATIONS = 1;
42
+ const OPENAI_MAX_FINAL_REPORT_CONTINUATIONS = 4;
43
43
  const OPENAI_PLAN_COMPLETE_IDLE_ABORT_MS = 8000;
44
44
  function hasAdequateClosedPhaseSummary(phase) {
45
45
  if (phase.status !== 'completed' && phase.status !== 'skipped')
46
46
  return false;
47
47
  return typeof phase.summary === 'string' && phase.summary.trim().length >= claudeMcpServer_1.MIN_PHASE_SUMMARY_CHARS;
48
48
  }
49
- function formatTraceContext(datasets, outputLanguage) {
50
- if (!datasets || datasets.length === 0)
51
- return '';
52
- const parts = datasets.map((d) => {
53
- const header = `| ${d.columns.join(' | ')} |`;
54
- const sep = `| ${d.columns.map(() => '---').join(' | ')} |`;
55
- const rows = d.rows.slice(0, 100).map((r) => `| ${r.map((v) => String(v ?? '-')).join(' | ')} |`);
56
- const truncNote = d.rows.length > 100
57
- ? (0, outputLanguage_1.localize)(outputLanguage, `\n*(前 100 行,共 ${d.rows.length} 行)*`, `\n*(first 100 rows out of ${d.rows.length})*`)
58
- : '';
59
- return `### ${d.label}\n${header}\n${sep}\n${rows.join('\n')}${truncNote}`;
60
- });
61
- return (0, outputLanguage_1.localize)(outputLanguage, `## 前端预查询 Trace 数据\n\n以下数据已由前端查询完毕,直接使用,无需重复 SQL 查询:\n\n${parts.join('\n\n')}`, `## Frontend Pre-queried Trace Data\n\nThe frontend has already queried the following data. Use it directly; do not repeat the same SQL query.\n\n${parts.join('\n\n')}`);
62
- }
63
49
  function parseJsonObject(value) {
64
50
  if (typeof value !== 'string')
65
51
  return undefined;
@@ -71,25 +57,6 @@ function parseJsonObject(value) {
71
57
  return undefined;
72
58
  }
73
59
  }
74
- function providerScopeFromOptions(options) {
75
- if (!options.tenantId || !options.workspaceId)
76
- return undefined;
77
- return {
78
- tenantId: options.tenantId,
79
- workspaceId: options.workspaceId,
80
- userId: options.userId,
81
- };
82
- }
83
- function knowledgeScopeFromOptions(options) {
84
- if (!options.tenantId || !options.workspaceId)
85
- return undefined;
86
- return {
87
- tenantId: options.tenantId,
88
- workspaceId: options.workspaceId,
89
- userId: options.userId,
90
- sourceRunId: options.runId,
91
- };
92
- }
93
60
  function summarizeToolOutput(value) {
94
61
  const text = typeof value === 'string' ? value : JSON.stringify(value);
95
62
  if (!text)
@@ -300,12 +267,54 @@ function chooseOpenAiConclusionText(input) {
300
267
  }
301
268
  return selected;
302
269
  }
270
+ function resolveOpenAIRunInput(params) {
271
+ let effectivePrompt = params.effectivePrompt;
272
+ if (params.quickMode) {
273
+ const quickConversationContext = (0, runtimeCommon_1.buildQuickConversationContext)(params.previousTurns, params.config.outputLanguage);
274
+ if (quickConversationContext) {
275
+ effectivePrompt = `${quickConversationContext}\n\n${effectivePrompt}`;
276
+ }
277
+ return {
278
+ input: effectivePrompt,
279
+ effectivePrompt,
280
+ shouldPersistRemoteSession: false,
281
+ };
282
+ }
283
+ const hasFreshSessionEntry = (0, runtimeCommon_1.isFreshRuntimeEntry)(params.sessionEntry, OPENAI_SESSION_FRESHNESS_MS, params.now ?? Date.now());
284
+ const freshSessionEntry = hasFreshSessionEntry ? params.sessionEntry : undefined;
285
+ const usePreviousResponse = params.config.protocol === 'responses'
286
+ && !!freshSessionEntry?.lastResponseId;
287
+ if (usePreviousResponse) {
288
+ return {
289
+ input: effectivePrompt,
290
+ effectivePrompt,
291
+ previousResponseId: freshSessionEntry.lastResponseId,
292
+ shouldPersistRemoteSession: true,
293
+ };
294
+ }
295
+ if (freshSessionEntry?.history) {
296
+ return {
297
+ input: [
298
+ ...freshSessionEntry.history,
299
+ { role: 'user', content: effectivePrompt },
300
+ ],
301
+ effectivePrompt,
302
+ shouldPersistRemoteSession: true,
303
+ };
304
+ }
305
+ return {
306
+ input: effectivePrompt,
307
+ effectivePrompt,
308
+ shouldPersistRemoteSession: true,
309
+ };
310
+ }
303
311
  exports.__testing = {
304
312
  isMissingOpenAIPreviousResponseError,
305
313
  readCompletedStreamFinalOutput,
306
314
  sanitizeOpenAiConclusionText,
307
315
  chooseOpenAiConclusionText,
308
316
  selectOpenAiRecoveryAnswer,
317
+ resolveOpenAIRunInput,
309
318
  isRecoverableOpenAIStreamTermination,
310
319
  compactProviderErrorMessage,
311
320
  };
@@ -326,11 +335,11 @@ class OpenAIRuntime extends events_1.EventEmitter {
326
335
  this.traceProcessorService = traceProcessorService;
327
336
  }
328
337
  buildSessionMapKey(sessionId, referenceTraceId) {
329
- return referenceTraceId ? `${sessionId}:ref:${referenceTraceId}` : sessionId;
338
+ return (0, runtimeCommon_1.buildRuntimeSessionMapKey)(sessionId, referenceTraceId);
330
339
  }
331
340
  getSdkSessionId(sessionId, referenceTraceId) {
332
341
  const entry = this.sessionMap.get(this.buildSessionMapKey(sessionId, referenceTraceId));
333
- return entry && Date.now() - (entry.updatedAt || 0) < OPENAI_SESSION_FRESHNESS_MS
342
+ return (0, runtimeCommon_1.isFreshRuntimeEntry)(entry, OPENAI_SESSION_FRESHNESS_MS)
334
343
  ? entry.lastResponseId
335
344
  : undefined;
336
345
  }
@@ -343,7 +352,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
343
352
  });
344
353
  }
345
354
  restoreArchitectureCache(traceId, architecture) {
346
- this.architectureCache.set(traceId, architecture);
355
+ (0, runtimeCommon_1.setLruCacheEntry)(this.architectureCache, traceId, architecture);
347
356
  }
348
357
  forgetOpenAILastResponseId(sessionMapKey, reason) {
349
358
  const existing = this.sessionMap.get(sessionMapKey);
@@ -393,7 +402,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
393
402
  const startTime = Date.now();
394
403
  let accumulatedAnswer = '';
395
404
  let rounds = 0;
396
- const config = (0, openAiConfig_1.loadOpenAIConfig)(options.providerId, providerScopeFromOptions(options));
405
+ const config = (0, openAiConfig_1.loadOpenAIConfig)(options.providerId, (0, runtimeCommon_1.providerScopeFromAnalysisOptions)(options));
397
406
  const sceneType = (0, sceneClassifier_1.classifyScene)(query);
398
407
  const quickMode = await this.classifyModeForRequest(query, sessionId, traceId, options, sceneType, config);
399
408
  try {
@@ -402,22 +411,17 @@ class OpenAIRuntime extends events_1.EventEmitter {
402
411
  sceneType,
403
412
  lightweight: quickMode,
404
413
  });
405
- const promptPrefix = formatTraceContext(options.traceContext, config.outputLanguage);
414
+ const promptPrefix = (0, runtimeCommon_1.formatTraceContext)(options.traceContext, config.outputLanguage);
406
415
  const effectivePrompt = promptPrefix ? `${promptPrefix}\n\n${query}` : query;
407
416
  const sessionEntry = this.sessionMap.get(context.sessionMapKey);
408
- const hasFreshHistory = !!sessionEntry?.history
409
- && Date.now() - sessionEntry.updatedAt < OPENAI_SESSION_FRESHNESS_MS;
410
- const usePreviousResponse = config.protocol === 'responses'
411
- && !!sessionEntry?.lastResponseId
412
- && Date.now() - sessionEntry.updatedAt < OPENAI_SESSION_FRESHNESS_MS;
413
- const input = usePreviousResponse
414
- ? effectivePrompt
415
- : hasFreshHistory
416
- ? [
417
- ...sessionEntry.history,
418
- { role: 'user', content: effectivePrompt },
419
- ]
420
- : effectivePrompt;
417
+ const runInput = resolveOpenAIRunInput({
418
+ quickMode,
419
+ config,
420
+ sessionEntry,
421
+ effectivePrompt,
422
+ previousTurns: context.previousTurns,
423
+ });
424
+ const input = runInput.input;
421
425
  (0, agents_1.setTracingDisabled)(true);
422
426
  const provider = (0, mimoReasoningCompat_1.shouldUseMimoReasoningContentCompat)(config)
423
427
  ? new agents_1.OpenAIProvider({
@@ -464,13 +468,13 @@ class OpenAIRuntime extends events_1.EventEmitter {
464
468
  type: 'progress',
465
469
  content: {
466
470
  phase: 'answering',
467
- message: (0, outputLanguage_1.localize)(config.outputLanguage, `OpenAI Agents SDK 分析中 (${agent.model})...`, `Analyzing with OpenAI Agents SDK (${agent.model})...`),
471
+ message: (0, outputLanguage_1.localize)(config.outputLanguage, `AI 分析引擎分析中 (${agent.model})...`, `AI analysis engine is running (${agent.model})...`),
468
472
  runtime: 'openai-agents-sdk',
469
473
  model: agent.model,
470
474
  },
471
475
  timestamp: Date.now(),
472
476
  });
473
- let currentPreviousResponseId = usePreviousResponse ? sessionEntry.lastResponseId : undefined;
477
+ let currentPreviousResponseId = runInput.previousResponseId;
474
478
  try {
475
479
  let currentInput = input;
476
480
  let conclusion = '';
@@ -527,7 +531,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
527
531
  type: 'progress',
528
532
  content: {
529
533
  phase: 'concluding',
530
- message: (0, outputLanguage_1.localize)(config.outputLanguage, 'OpenAI plan 已完成,provider 未主动结束 stream,按已完成计划收尾。', 'The OpenAI plan is complete; the provider did not close the stream, so finalizing from the completed plan.'),
534
+ message: (0, outputLanguage_1.localize)(config.outputLanguage, '分析阶段已完成,正在整理最终报告。', 'Analysis phases are complete; preparing the final report.'),
531
535
  },
532
536
  timestamp: Date.now(),
533
537
  });
@@ -615,6 +619,8 @@ class OpenAIRuntime extends events_1.EventEmitter {
615
619
  completedByPlanIdle,
616
620
  timedOut,
617
621
  finalReportContinuations,
622
+ query,
623
+ sceneType,
618
624
  }) && streamHistory.length > 0) {
619
625
  finalReportContinuations++;
620
626
  this.emitUpdate({
@@ -682,7 +688,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
682
688
  (0, finalResultQualityGate_1.looksLikePhaseSummaryFallback)(conclusion)) &&
683
689
  !partial) {
684
690
  partial = true;
685
- terminationMessage = (0, outputLanguage_1.localize)(config.outputLanguage, 'OpenAI plan 已完成,但 provider 没有输出独立最终报告;已退回到阶段摘要,结果信息密度可能不足。', 'The OpenAI plan completed, but the provider did not produce an independent final report; falling back to phase summaries, which may be less informative.');
691
+ terminationMessage = (0, outputLanguage_1.localize)(config.outputLanguage, '分析阶段已完成,但模型没有输出独立最终报告;已使用阶段摘要兜底,结果信息密度可能不足。', 'Analysis phases completed, but the model did not produce an independent final report; falling back to phase summaries, which may be less informative.');
686
692
  this.emitUpdate({
687
693
  type: 'degraded',
688
694
  content: {
@@ -711,7 +717,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
711
717
  terminationReason,
712
718
  terminationMessage,
713
719
  };
714
- const gateIssue = (0, finalResultQualityGate_1.applyFinalResultQualityGate)({ result, query });
720
+ const gateIssue = (0, finalResultQualityGate_1.applyFinalResultQualityGate)({ result, query, sceneType });
715
721
  if (gateIssue) {
716
722
  this.emitUpdate({
717
723
  type: 'degraded',
@@ -724,12 +730,14 @@ class OpenAIRuntime extends events_1.EventEmitter {
724
730
  timestamp: Date.now(),
725
731
  });
726
732
  }
727
- this.sessionMap.set(context.sessionMapKey, {
728
- history: finalHistory,
729
- lastResponseId: finalLastResponseId,
730
- runState: finalRunState,
731
- updatedAt: Date.now(),
732
- });
733
+ if (runInput.shouldPersistRemoteSession) {
734
+ this.sessionMap.set(context.sessionMapKey, {
735
+ history: finalHistory,
736
+ lastResponseId: finalLastResponseId,
737
+ runState: finalRunState,
738
+ updatedAt: Date.now(),
739
+ });
740
+ }
733
741
  this.recordTurn({
734
742
  query,
735
743
  sessionId,
@@ -766,33 +774,18 @@ class OpenAIRuntime extends events_1.EventEmitter {
766
774
  });
767
775
  }
768
776
  else if (error instanceof agents_1.MaxTurnsExceededError) {
769
- const partialConclusion = accumulatedAnswer || (0, outputLanguage_1.localize)(config.outputLanguage, '分析达到 OpenAI Agents SDK 轮次上限,尚未形成完整结论。', 'The OpenAI Agents SDK run reached the turn limit before a complete conclusion was produced.');
770
- const findings = (0, claudeFindingExtractor_1.extractFindingsFromText)(partialConclusion);
771
- const confidence = Math.min(0.55, this.estimateConfidence(findings, partialConclusion));
772
- this.emitUpdate({
773
- type: 'degraded',
774
- content: {
775
- module: 'openAiRuntime',
776
- fallback: 'partial_result_after_max_turns',
777
- partial: true,
778
- terminationReason: 'max_turns',
779
- message: (0, outputLanguage_1.localize)(config.outputLanguage, 'OpenAI 分析达到轮次上限,结果可能不完整', 'OpenAI analysis reached the turn limit; result may be incomplete'),
780
- },
781
- timestamp: Date.now(),
782
- });
783
- return {
777
+ return this.recordMaxTurnsPartialResult({
778
+ error,
779
+ query,
784
780
  sessionId,
785
- success: true,
786
- findings,
787
- hypotheses: context.hypotheses.map(h => this.toProtocolHypothesis(h)),
788
- conclusion: partialConclusion,
789
- confidence,
781
+ outputLanguage: config.outputLanguage,
782
+ accumulatedAnswer,
783
+ context,
784
+ startTime,
790
785
  rounds,
791
- totalDurationMs: Date.now() - startTime,
792
- partial: true,
793
- terminationReason: 'max_turns',
794
- terminationMessage: error.message,
795
- };
786
+ quickMode,
787
+ codeAwareMode: options.codeAwareMode,
788
+ });
796
789
  }
797
790
  const recoverablePartial = this.recoverPartialResultAfterStreamTermination({
798
791
  error,
@@ -804,6 +797,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
804
797
  query,
805
798
  startTime,
806
799
  rounds,
800
+ codeAwareMode: options.codeAwareMode,
807
801
  });
808
802
  if (recoverablePartial) {
809
803
  return recoverablePartial;
@@ -815,7 +809,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
815
809
  const message = compactProviderErrorMessage(error);
816
810
  this.emitUpdate({
817
811
  type: 'error',
818
- content: { message: `OpenAI Agents SDK analysis failed: ${message}` },
812
+ content: { message: `AI analysis failed: ${message}` },
819
813
  timestamp: Date.now(),
820
814
  });
821
815
  return {
@@ -823,7 +817,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
823
817
  success: false,
824
818
  findings: [],
825
819
  hypotheses: [],
826
- conclusion: (0, outputLanguage_1.localize)(config.outputLanguage, `OpenAI Agents SDK 分析失败:${message}`, `OpenAI Agents SDK analysis failed: ${message}`),
820
+ conclusion: (0, outputLanguage_1.localize)(config.outputLanguage, `AI 分析失败:${message}`, `AI analysis failed: ${message}`),
827
821
  confidence: 0,
828
822
  rounds,
829
823
  totalDurationMs: Date.now() - startTime,
@@ -866,7 +860,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
866
860
  const planState = this.sessionPlans.get(sessionId);
867
861
  const artifactStore = this.artifactStores.get(sessionId);
868
862
  const sessionEntry = this.sessionMap.get(this.buildSessionMapKey(sessionId, sessionFields.referenceTraceId));
869
- const freshSessionEntry = sessionEntry && Date.now() - (sessionEntry.updatedAt || 0) < OPENAI_SESSION_FRESHNESS_MS
863
+ const freshSessionEntry = (0, runtimeCommon_1.isFreshRuntimeEntry)(sessionEntry, OPENAI_SESSION_FRESHNESS_MS)
870
864
  ? sessionEntry
871
865
  : undefined;
872
866
  return {
@@ -987,12 +981,10 @@ class OpenAIRuntime extends events_1.EventEmitter {
987
981
  uncertaintyFlags.splice(0);
988
982
  let sqlErrors = this.sessionSqlErrors.get(sessionId);
989
983
  if (!sqlErrors) {
990
- sqlErrors = (0, claudeMcpServer_1.loadLearnedSqlFixPairs)(5, knowledgeScopeFromOptions(options));
984
+ sqlErrors = (0, claudeMcpServer_1.loadLearnedSqlFixPairs)(5, (0, runtimeCommon_1.knowledgeScopeFromAnalysisOptions)(options));
991
985
  this.sessionSqlErrors.set(sessionId, sqlErrors);
992
986
  }
993
- const skillNotesBudget = !lightweight && process.env.SELF_IMPROVE_NOTES_INJECT_ENABLED === '1'
994
- ? new skillNotesInjector_1.SkillNotesBudget({ mode: 'full' })
995
- : undefined;
987
+ const skillNotesBudget = (0, runtimeCommon_1.createRuntimeSkillNotesBudget)(lightweight);
996
988
  const { allowedTools, toolDefinitions } = (0, claudeMcpServer_1.createClaudeMcpServer)({
997
989
  sessionId,
998
990
  traceId,
@@ -1020,7 +1012,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
1020
1012
  lightweight,
1021
1013
  skillNotesBudget,
1022
1014
  outputLanguage: config.outputLanguage,
1023
- knowledgeScope: knowledgeScopeFromOptions(options),
1015
+ knowledgeScope: (0, runtimeCommon_1.knowledgeScopeFromAnalysisOptions)(options),
1024
1016
  codeAwareMode: options.codeAwareMode,
1025
1017
  codebaseIds: options.codebaseIds,
1026
1018
  });
@@ -1042,6 +1034,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
1042
1034
  .filter((e) => e.fixedSql)
1043
1035
  .slice(-3)
1044
1036
  .map((e) => ({ errorSql: e.errorSql, errorMessage: e.errorMessage, fixedSql: e.fixedSql }));
1037
+ const traceInfo = this.traceProcessorService.getTrace(traceId);
1045
1038
  const systemPrompt = lightweight
1046
1039
  ? (0, claudeSystemPrompt_1.buildQuickSystemPrompt)({
1047
1040
  architecture,
@@ -1072,6 +1065,8 @@ class OpenAIRuntime extends events_1.EventEmitter {
1072
1065
  selectionContext: options.selectionContext,
1073
1066
  comparison: comparisonContext,
1074
1067
  traceCompleteness,
1068
+ traceOs: traceInfo?.traceOs,
1069
+ traceFormat: traceInfo?.traceFormat,
1075
1070
  outputLanguage: config.outputLanguage,
1076
1071
  codeAwareMode: options.codeAwareMode,
1077
1072
  codebaseIds: options.codebaseIds,
@@ -1089,7 +1084,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
1089
1084
  };
1090
1085
  }
1091
1086
  async detectArchitecture(traceId, packageName) {
1092
- const cached = this.architectureCache.get(traceId);
1087
+ const cached = (0, runtimeCommon_1.getLruCacheEntry)(this.architectureCache, traceId);
1093
1088
  if (cached)
1094
1089
  return cached;
1095
1090
  try {
@@ -1100,7 +1095,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
1100
1095
  packageName,
1101
1096
  });
1102
1097
  if (architecture) {
1103
- this.architectureCache.set(traceId, architecture);
1098
+ (0, runtimeCommon_1.setLruCacheEntry)(this.architectureCache, traceId, architecture);
1104
1099
  this.emitUpdate({ type: 'architecture_detected', content: { architecture }, timestamp: Date.now() });
1105
1100
  }
1106
1101
  return architecture;
@@ -1158,15 +1153,16 @@ class OpenAIRuntime extends events_1.EventEmitter {
1158
1153
  };
1159
1154
  }
1160
1155
  async detectVendor(traceId) {
1161
- const cached = this.vendorCache.get(traceId);
1156
+ const cached = (0, runtimeCommon_1.getLruCacheEntry)(this.vendorCache, traceId);
1162
1157
  if (cached)
1163
1158
  return cached;
1164
1159
  try {
1165
1160
  const adapter = (0, skillAnalysisAdapter_1.getSkillAnalysisAdapter)(this.traceProcessorService);
1166
1161
  await adapter.ensureInitialized();
1167
1162
  const result = await adapter.detectVendor(traceId);
1168
- if (result.vendor && result.vendor !== 'aosp')
1169
- this.vendorCache.set(traceId, result.vendor);
1163
+ if (result.vendor && result.vendor !== 'aosp') {
1164
+ (0, runtimeCommon_1.setLruCacheEntry)(this.vendorCache, traceId, result.vendor);
1165
+ }
1170
1166
  return result.vendor;
1171
1167
  }
1172
1168
  catch (error) {
@@ -1175,12 +1171,12 @@ class OpenAIRuntime extends events_1.EventEmitter {
1175
1171
  }
1176
1172
  }
1177
1173
  async detectCompleteness(traceId, architecture) {
1178
- const cached = this.completenessCache.get(traceId);
1174
+ const cached = (0, runtimeCommon_1.getLruCacheEntry)(this.completenessCache, traceId);
1179
1175
  if (cached)
1180
1176
  return cached;
1181
1177
  try {
1182
1178
  const completeness = await (0, traceCompletenessProber_1.probeTraceCompleteness)(this.traceProcessorService, traceId, architecture?.type);
1183
- this.completenessCache.set(traceId, completeness);
1179
+ (0, runtimeCommon_1.setLruCacheEntry)(this.completenessCache, traceId, completeness);
1184
1180
  return completeness;
1185
1181
  }
1186
1182
  catch (error) {
@@ -1256,11 +1252,9 @@ class OpenAIRuntime extends events_1.EventEmitter {
1256
1252
  }
1257
1253
  const conclusion = input.conclusion.trim();
1258
1254
  const fallback = input.fallbackConclusion?.trim();
1259
- if (!fallback)
1260
- return false;
1261
1255
  if (!conclusion)
1262
1256
  return true;
1263
- if (isSameConclusionText(conclusion, fallback))
1257
+ if (fallback && isSameConclusionText(conclusion, fallback))
1264
1258
  return true;
1265
1259
  if ((0, finalResultQualityGate_1.looksLikePhaseSummaryFallback)(conclusion))
1266
1260
  return true;
@@ -1268,6 +1262,13 @@ class OpenAIRuntime extends events_1.EventEmitter {
1268
1262
  return true;
1269
1263
  if (looksLikeProcessNarrationParagraph(conclusion))
1270
1264
  return true;
1265
+ if ((0, finalReportContractGate_1.assessFinalReportContractCompleteness)({
1266
+ conclusion,
1267
+ query: input.query,
1268
+ sceneType: input.sceneType,
1269
+ })) {
1270
+ return true;
1271
+ }
1271
1272
  return looksLikeProcessNarrationParagraph(conclusion.split(/\n{2,}/)[0] || '');
1272
1273
  }
1273
1274
  buildFinalReportAfterPlanCompletePrompt(outputLanguage) {
@@ -1281,7 +1282,7 @@ class OpenAIRuntime extends events_1.EventEmitter {
1281
1282
  return template;
1282
1283
  }
1283
1284
  formatPlanCompleteReportContinuationMessage(outputLanguage) {
1284
- return (0, outputLanguage_1.localize)(outputLanguage, 'OpenAI plan 已完成,但最终正文仍是阶段摘要,继续请求完整最终报告。', 'The OpenAI plan is complete, but the final body is still a phase summary; requesting the complete final report.');
1285
+ return (0, outputLanguage_1.localize)(outputLanguage, '最终报告仍需补齐,继续整理完整结论。', 'The final report still needs completion; continuing to assemble the full conclusion.');
1285
1286
  }
1286
1287
  buildCompletedPlanFallbackConclusion(sessionId, quickMode, outputLanguage) {
1287
1288
  if (quickMode)
@@ -1396,7 +1397,9 @@ class OpenAIRuntime extends events_1.EventEmitter {
1396
1397
  let conclusion = planStatus.complete
1397
1398
  ? conclusionBase
1398
1399
  : this.withIncompletePlanWarning(conclusionBase, planStatus, params.outputLanguage);
1399
- conclusion = (0, codeAwareOutputRegistry_1.sanitizeCodeAwareText)(params.sessionId, conclusion);
1400
+ if (params.codeAwareMode && params.codeAwareMode !== 'off') {
1401
+ conclusion = (0, codeAwareOutputRegistry_1.sanitizeCodeAwareText)(params.sessionId, conclusion);
1402
+ }
1400
1403
  const findings = (0, claudeFindingExtractor_1.extractFindingsFromText)(conclusion);
1401
1404
  const confidence = Math.min(0.55, this.estimateConfidence(findings, conclusion));
1402
1405
  const terminationReason = planStatus.complete ? 'timeout' : 'plan_incomplete';
@@ -1456,12 +1459,63 @@ class OpenAIRuntime extends events_1.EventEmitter {
1456
1459
  terminationMessage,
1457
1460
  };
1458
1461
  }
1462
+ recordMaxTurnsPartialResult(params) {
1463
+ let partialConclusion = params.accumulatedAnswer || (0, outputLanguage_1.localize)(params.outputLanguage, '分析达到轮次上限,尚未形成完整结论。', 'The analysis reached the turn limit before a complete conclusion was produced.');
1464
+ if (params.codeAwareMode && params.codeAwareMode !== 'off') {
1465
+ partialConclusion = (0, codeAwareOutputRegistry_1.sanitizeCodeAwareText)(params.sessionId, partialConclusion);
1466
+ }
1467
+ const findings = (0, claudeFindingExtractor_1.extractFindingsFromText)(partialConclusion);
1468
+ const confidence = Math.min(0.55, this.estimateConfidence(findings, partialConclusion));
1469
+ const result = {
1470
+ sessionId: params.sessionId,
1471
+ success: true,
1472
+ findings,
1473
+ hypotheses: params.context.hypotheses.map(h => this.toProtocolHypothesis(h)),
1474
+ conclusion: partialConclusion,
1475
+ confidence,
1476
+ rounds: params.rounds,
1477
+ totalDurationMs: Date.now() - params.startTime,
1478
+ partial: true,
1479
+ terminationReason: 'max_turns',
1480
+ terminationMessage: params.error.message,
1481
+ };
1482
+ this.emitUpdate({
1483
+ type: 'degraded',
1484
+ content: {
1485
+ module: 'openAiRuntime',
1486
+ fallback: 'partial_result_after_max_turns',
1487
+ partial: true,
1488
+ terminationReason: 'max_turns',
1489
+ message: (0, outputLanguage_1.localize)(params.outputLanguage, 'OpenAI 分析达到轮次上限,结果可能不完整', 'OpenAI analysis reached the turn limit; result may be incomplete'),
1490
+ },
1491
+ timestamp: Date.now(),
1492
+ });
1493
+ this.recordTurn({
1494
+ query: params.query,
1495
+ sessionId: params.sessionId,
1496
+ result,
1497
+ sessionContext: params.context.sessionContext,
1498
+ previousTurnCount: params.context.previousTurns.length,
1499
+ quickMode: params.quickMode,
1500
+ });
1501
+ this.emitUpdate({
1502
+ type: 'conclusion',
1503
+ content: { conclusion: result.conclusion, durationMs: Date.now() - params.startTime, turns: params.rounds },
1504
+ timestamp: Date.now(),
1505
+ });
1506
+ this.emitUpdate({
1507
+ type: 'answer_token',
1508
+ content: { done: true, totalChars: result.conclusion.length },
1509
+ timestamp: Date.now(),
1510
+ });
1511
+ return result;
1512
+ }
1459
1513
  formatPlanContinuationMessage(status, outputLanguage) {
1460
1514
  if (!status.hasPlan) {
1461
- return (0, outputLanguage_1.localize)(outputLanguage, 'OpenAI 模型提前结束但尚未提交分析计划,继续执行...', 'The OpenAI model stopped before submitting an analysis plan; continuing...');
1515
+ return (0, outputLanguage_1.localize)(outputLanguage, '继续建立分析计划并补齐必要证据...', 'Continuing by creating the analysis plan and collecting required evidence...');
1462
1516
  }
1463
1517
  const phaseNames = status.pendingPhases.map(p => p.name || p.id).slice(0, 3).join('、');
1464
- return (0, outputLanguage_1.localize)(outputLanguage, `OpenAI 模型提前结束但 plan 未完成,继续执行剩余阶段:${phaseNames}`, `The OpenAI model stopped before the plan completed; continuing remaining phases: ${phaseNames}`);
1518
+ return (0, outputLanguage_1.localize)(outputLanguage, `继续补齐剩余分析阶段:${phaseNames}`, `Continuing the remaining analysis phases: ${phaseNames}`);
1465
1519
  }
1466
1520
  formatIncompletePlanMessage(status, outputLanguage) {
1467
1521
  if (!status.hasPlan) {
@@ -1585,94 +1639,16 @@ class OpenAIRuntime extends events_1.EventEmitter {
1585
1639
  });
1586
1640
  }
1587
1641
  captureEntitiesFromSkillDisplayResults(displayResults, entityStore) {
1588
- try {
1589
- const data = {};
1590
- for (const dr of displayResults) {
1591
- if (dr.stepId && dr.data)
1592
- data[dr.stepId] = dr.data;
1593
- }
1594
- const captured = (0, entityCapture_1.captureEntitiesFromResponses)([{
1595
- agentId: 'openai-agent',
1596
- success: true,
1597
- toolResults: [{ toolName: 'invoke_skill', data }],
1598
- }]);
1599
- (0, entityCapture_1.applyCapturedEntities)(entityStore, captured);
1600
- }
1601
- catch (error) {
1602
- console.warn('[OpenAIRuntime] Entity capture failed:', error.message);
1603
- }
1642
+ (0, runtimeCommon_1.captureSkillDisplayEntities)(displayResults, entityStore, 'openai-agent');
1604
1643
  }
1605
1644
  collectPreviousFindings(sessionContext, maxTurns = 3) {
1606
- try {
1607
- const turns = sessionContext.getAllTurns?.() || [];
1608
- return turns.slice(-maxTurns).flatMap((turn) => turn.findings || []).slice(0, 5);
1609
- }
1610
- catch {
1611
- return [];
1612
- }
1645
+ return (0, runtimeCommon_1.collectRecentFindings)(sessionContext, { maxTurns, maxFindings: 5 });
1613
1646
  }
1614
1647
  buildEntityContext(entityStore) {
1615
- try {
1616
- const lines = [];
1617
- const frames = entityStore.getAllFrames?.() || [];
1618
- if (frames.length > 0) {
1619
- lines.push(`**帧 (${frames.length})**:`);
1620
- for (const f of frames.slice(0, 15)) {
1621
- const parts = [`frame_id=${f.frame_id}`];
1622
- if (f.start_ts)
1623
- parts.push(`ts=${f.start_ts}`);
1624
- if (f.jank_type)
1625
- parts.push(`jank=${f.jank_type}`);
1626
- if (f.dur_ms)
1627
- parts.push(`dur=${f.dur_ms}ms`);
1628
- if (f.process_name)
1629
- parts.push(`proc=${f.process_name}`);
1630
- lines.push(`- ${parts.join(', ')}`);
1631
- }
1632
- }
1633
- const sessions = entityStore.getAllSessions?.() || [];
1634
- if (sessions.length > 0) {
1635
- lines.push(`**滑动会话 (${sessions.length})**:`);
1636
- for (const s of sessions.slice(0, 8)) {
1637
- const parts = [`session_id=${s.session_id}`];
1638
- if (s.start_ts)
1639
- parts.push(`ts=${s.start_ts}`);
1640
- if (s.jank_count)
1641
- parts.push(`janks=${s.jank_count}`);
1642
- if (s.process_name)
1643
- parts.push(`proc=${s.process_name}`);
1644
- lines.push(`- ${parts.join(', ')}`);
1645
- }
1646
- }
1647
- return lines.length > 0 ? lines.join('\n') : undefined;
1648
- }
1649
- catch {
1650
- return undefined;
1651
- }
1648
+ return (0, runtimeCommon_1.buildEntityContext)(entityStore);
1652
1649
  }
1653
1650
  toProtocolHypothesis(h) {
1654
- const statusMap = {
1655
- formed: 'proposed',
1656
- confirmed: 'confirmed',
1657
- rejected: 'rejected',
1658
- };
1659
- const confidenceMap = { formed: 0.5, confirmed: 0.85, rejected: 0.1 };
1660
- return {
1661
- id: h.id,
1662
- description: h.statement,
1663
- status: statusMap[h.status] || 'proposed',
1664
- confidence: confidenceMap[h.status] ?? 0.5,
1665
- supportingEvidence: h.evidence && h.status === 'confirmed'
1666
- ? [{ id: `${h.id}-ev`, type: 'observation', description: h.evidence, source: 'openai', strength: 0.8 }]
1667
- : [],
1668
- contradictingEvidence: h.evidence && h.status === 'rejected'
1669
- ? [{ id: `${h.id}-ev`, type: 'observation', description: h.evidence, source: 'openai', strength: 0.8 }]
1670
- : [],
1671
- proposedBy: 'openai',
1672
- relevantAgents: ['openai'],
1673
- createdAt: h.formedAt,
1674
- updatedAt: h.resolvedAt || h.formedAt,
1675
- };
1651
+ return (0, runtimeCommon_1.toProtocolHypothesis)(h, 'openai');
1676
1652
  }
1677
1653
  emitUpdate(update) {
1678
1654
  this.emit('update', update);