@gracker/smartperfetto 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agents/base/baseAgent.d.ts.map +1 -1
- package/dist/agent/agents/base/baseAgent.js +5 -1
- package/dist/agent/agents/base/baseAgent.js.map +1 -1
- package/dist/agent/context/enhancedSessionContext.d.ts +5 -0
- package/dist/agent/context/enhancedSessionContext.d.ts.map +1 -1
- package/dist/agent/context/enhancedSessionContext.js +13 -0
- package/dist/agent/context/enhancedSessionContext.js.map +1 -1
- package/dist/agent/core/conclusionContract.d.ts +23 -1
- package/dist/agent/core/conclusionContract.d.ts.map +1 -1
- package/dist/agent/core/conclusionGenerator.d.ts.map +1 -1
- package/dist/agent/core/conclusionGenerator.js +223 -27
- package/dist/agent/core/conclusionGenerator.js.map +1 -1
- package/dist/agent/core/executors/directSkillExecutor.d.ts.map +1 -1
- package/dist/agent/core/executors/directSkillExecutor.js +6 -12
- package/dist/agent/core/executors/directSkillExecutor.js.map +1 -1
- package/dist/agent/core/orchestratorTypes.d.ts +6 -0
- package/dist/agent/core/orchestratorTypes.d.ts.map +1 -1
- package/dist/agent/core/orchestratorTypes.js.map +1 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.d.ts.map +1 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.js +4 -1
- package/dist/agent/experts/crossDomain/moduleExpertInvoker.js.map +1 -1
- package/dist/agent/scene/sceneStage1Runner.d.ts +1 -1
- package/dist/agent/scene/sceneStage1Runner.d.ts.map +1 -1
- package/dist/agent/scene/sceneStage1Runner.js +1 -1
- package/dist/agent/scene/sceneStage1Runner.js.map +1 -1
- package/dist/agent/scene/sceneStoryService.d.ts +1 -1
- package/dist/agent/scene/sceneStoryService.d.ts.map +1 -1
- package/dist/agent/scene/sceneStoryService.js +4 -1
- package/dist/agent/scene/sceneStoryService.js.map +1 -1
- package/dist/agent/types/agentProtocol.d.ts.map +1 -1
- package/dist/agent/types/agentProtocol.js +4 -1
- package/dist/agent/types/agentProtocol.js.map +1 -1
- package/dist/agent/types.d.ts +7 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/agentOpenAI/openAiConfig.d.ts +2 -0
- package/dist/agentOpenAI/openAiConfig.d.ts.map +1 -1
- package/dist/agentOpenAI/openAiConfig.js +3 -0
- package/dist/agentOpenAI/openAiConfig.js.map +1 -1
- package/dist/agentOpenAI/openAiRuntime.d.ts +8 -0
- package/dist/agentOpenAI/openAiRuntime.d.ts.map +1 -1
- package/dist/agentOpenAI/openAiRuntime.js +293 -58
- package/dist/agentOpenAI/openAiRuntime.js.map +1 -1
- package/dist/agentRuntime/runtimeHealth.d.ts +1 -0
- package/dist/agentRuntime/runtimeHealth.d.ts.map +1 -1
- package/dist/agentv3/artifactStore.d.ts +5 -0
- package/dist/agentv3/artifactStore.d.ts.map +1 -1
- package/dist/agentv3/artifactStore.js +3 -0
- package/dist/agentv3/artifactStore.js.map +1 -1
- package/dist/agentv3/claudeMcpServer.d.ts.map +1 -1
- package/dist/agentv3/claudeMcpServer.js +125 -86
- package/dist/agentv3/claudeMcpServer.js.map +1 -1
- package/dist/agentv3/claudeRuntime.d.ts.map +1 -1
- package/dist/agentv3/claudeRuntime.js +147 -65
- package/dist/agentv3/claudeRuntime.js.map +1 -1
- package/dist/agentv3/claudeSseBridge.d.ts +6 -0
- package/dist/agentv3/claudeSseBridge.d.ts.map +1 -1
- package/dist/agentv3/claudeSseBridge.js +1 -0
- package/dist/agentv3/claudeSseBridge.js.map +1 -1
- package/dist/agentv3/sessionStateSnapshot.d.ts +23 -0
- package/dist/agentv3/sessionStateSnapshot.d.ts.map +1 -1
- package/dist/assistant/application/agentAnalyzeSessionService.d.ts +6 -0
- package/dist/assistant/application/agentAnalyzeSessionService.d.ts.map +1 -1
- package/dist/assistant/application/agentAnalyzeSessionService.js +9 -3
- package/dist/assistant/application/agentAnalyzeSessionService.js.map +1 -1
- package/dist/assistant/application/assistantApplicationService.d.ts.map +1 -1
- package/dist/assistant/application/assistantApplicationService.js +3 -1
- package/dist/assistant/application/assistantApplicationService.js.map +1 -1
- package/dist/cli-user/commands/report.js +64 -0
- package/dist/cli-user/commands/report.js.map +1 -1
- package/dist/cli-user/io/paths.d.ts +3 -0
- package/dist/cli-user/io/paths.d.ts.map +1 -1
- package/dist/cli-user/io/paths.js +6 -0
- package/dist/cli-user/io/paths.js.map +1 -1
- package/dist/cli-user/io/sessionStore.d.ts +1 -0
- package/dist/cli-user/io/sessionStore.d.ts.map +1 -1
- package/dist/cli-user/io/sessionStore.js +5 -0
- package/dist/cli-user/io/sessionStore.js.map +1 -1
- package/dist/cli-user/repl/renderer.d.ts +8 -0
- package/dist/cli-user/repl/renderer.d.ts.map +1 -1
- package/dist/cli-user/repl/renderer.js.map +1 -1
- package/dist/cli-user/services/cliAnalyzeService.d.ts +3 -0
- package/dist/cli-user/services/cliAnalyzeService.d.ts.map +1 -1
- package/dist/cli-user/services/cliAnalyzeService.js +103 -1
- package/dist/cli-user/services/cliAnalyzeService.js.map +1 -1
- package/dist/cli-user/services/turnPersistence.d.ts +0 -10
- package/dist/cli-user/services/turnPersistence.d.ts.map +1 -1
- package/dist/cli-user/services/turnPersistence.js +62 -0
- package/dist/cli-user/services/turnPersistence.js.map +1 -1
- package/dist/routes/agentReportRoutes.d.ts +1 -0
- package/dist/routes/agentReportRoutes.d.ts.map +1 -1
- package/dist/routes/agentReportRoutes.js +13 -2
- package/dist/routes/agentReportRoutes.js.map +1 -1
- package/dist/routes/agentResumeRoutes.d.ts.map +1 -1
- package/dist/routes/agentResumeRoutes.js +51 -5
- package/dist/routes/agentResumeRoutes.js.map +1 -1
- package/dist/routes/agentRoutes.d.ts.map +1 -1
- package/dist/routes/agentRoutes.js +524 -130
- package/dist/routes/agentRoutes.js.map +1 -1
- package/dist/scripts/verifyAgentSseScrolling.js +142 -2
- package/dist/scripts/verifyAgentSseScrolling.js.map +1 -1
- package/dist/services/agentEventStore.d.ts.map +1 -1
- package/dist/services/agentEventStore.js +13 -3
- package/dist/services/agentEventStore.js.map +1 -1
- package/dist/services/agentReportData.d.ts +3 -0
- package/dist/services/agentReportData.d.ts.map +1 -1
- package/dist/services/agentReportData.js.map +1 -1
- package/dist/services/agentResultNormalizer.d.ts +15 -3
- package/dist/services/agentResultNormalizer.d.ts.map +1 -1
- package/dist/services/agentResultNormalizer.js +344 -6
- package/dist/services/agentResultNormalizer.js.map +1 -1
- package/dist/services/analysisResultSnapshotPipeline.d.ts +3 -0
- package/dist/services/analysisResultSnapshotPipeline.d.ts.map +1 -1
- package/dist/services/analysisResultSnapshotPipeline.js +3 -0
- package/dist/services/analysisResultSnapshotPipeline.js.map +1 -1
- package/dist/services/analysisResultSnapshotStore.d.ts.map +1 -1
- package/dist/services/analysisResultSnapshotStore.js +34 -2
- package/dist/services/analysisResultSnapshotStore.js.map +1 -1
- package/dist/services/enterpriseSchema.d.ts.map +1 -1
- package/dist/services/enterpriseSchema.js +11 -0
- package/dist/services/enterpriseSchema.js.map +1 -1
- package/dist/services/evidence/evidenceContractBuilder.d.ts +11 -0
- package/dist/services/evidence/evidenceContractBuilder.d.ts.map +1 -0
- package/dist/services/evidence/evidenceContractBuilder.js +546 -0
- package/dist/services/evidence/evidenceContractBuilder.js.map +1 -0
- package/dist/services/finalResultQualityGate.d.ts +18 -0
- package/dist/services/finalResultQualityGate.d.ts.map +1 -0
- package/dist/services/finalResultQualityGate.js +283 -0
- package/dist/services/finalResultQualityGate.js.map +1 -0
- package/dist/services/htmlReportGenerator.d.ts +8 -1
- package/dist/services/htmlReportGenerator.d.ts.map +1 -1
- package/dist/services/htmlReportGenerator.js +129 -42
- package/dist/services/htmlReportGenerator.js.map +1 -1
- package/dist/services/persistAgentSession.d.ts +2 -0
- package/dist/services/persistAgentSession.d.ts.map +1 -1
- package/dist/services/persistAgentSession.js +17 -1
- package/dist/services/persistAgentSession.js.map +1 -1
- package/dist/services/processIdentity/identityContractMapper.d.ts +14 -0
- package/dist/services/processIdentity/identityContractMapper.d.ts.map +1 -0
- package/dist/services/processIdentity/identityContractMapper.js +135 -0
- package/dist/services/processIdentity/identityContractMapper.js.map +1 -0
- package/dist/services/processIdentity/types.d.ts +5 -0
- package/dist/services/processIdentity/types.d.ts.map +1 -1
- package/dist/services/processIdentity/types.js.map +1 -1
- package/dist/services/skillEngine/skillExecutor.d.ts +14 -2
- package/dist/services/skillEngine/skillExecutor.d.ts.map +1 -1
- package/dist/services/skillEngine/skillExecutor.js +133 -13
- package/dist/services/skillEngine/skillExecutor.js.map +1 -1
- package/dist/services/skillEngine/types.d.ts +2 -0
- package/dist/services/skillEngine/types.d.ts.map +1 -1
- package/dist/services/verifier/claimVerificationRunner.d.ts +20 -0
- package/dist/services/verifier/claimVerificationRunner.d.ts.map +1 -0
- package/dist/services/verifier/claimVerificationRunner.js +88 -0
- package/dist/services/verifier/claimVerificationRunner.js.map +1 -0
- package/dist/services/verifier/deterministicClaimVerifier.d.ts +8 -0
- package/dist/services/verifier/deterministicClaimVerifier.d.ts.map +1 -0
- package/dist/services/verifier/deterministicClaimVerifier.js +178 -0
- package/dist/services/verifier/deterministicClaimVerifier.js.map +1 -0
- package/dist/types/claimVerification.d.ts +38 -0
- package/dist/types/claimVerification.d.ts.map +1 -0
- package/dist/types/claimVerification.js +6 -0
- package/dist/types/claimVerification.js.map +1 -0
- package/dist/types/dataContract.d.ts +32 -0
- package/dist/types/dataContract.d.ts.map +1 -1
- package/dist/types/dataContract.js +7 -0
- package/dist/types/dataContract.js.map +1 -1
- package/dist/types/evidenceContract.d.ts +100 -0
- package/dist/types/evidenceContract.d.ts.map +1 -0
- package/dist/types/evidenceContract.js +6 -0
- package/dist/types/evidenceContract.js.map +1 -0
- package/dist/types/identityContract.d.ts +57 -0
- package/dist/types/identityContract.d.ts.map +1 -0
- package/dist/types/identityContract.js +6 -0
- package/dist/types/identityContract.js.map +1 -0
- package/dist/types/multiTraceComparison.d.ts +3 -0
- package/dist/types/multiTraceComparison.d.ts.map +1 -1
- package/package.json +3 -2
- package/skills/atomic/process_identity_resolver.skill.yaml +130 -1
- package/skills/atomic/process_slice_cpu_hotspots.skill.yaml +321 -0
- package/skills/atomic/startup_slow_reasons.skill.yaml +102 -17
- package/skills/composite/startup_analysis.skill.yaml +16 -0
- package/strategies/anr.strategy.md +2 -2
- package/strategies/game.strategy.md +1 -1
- package/strategies/general.strategy.md +1 -1
- package/strategies/prompt-openai-final-report-continuation-en.template.md +12 -0
- package/strategies/prompt-openai-final-report-continuation-zh.template.md +12 -0
- package/strategies/prompt-output-format.template.md +1 -1
- package/strategies/scrolling.strategy.md +1 -0
- package/strategies/startup.strategy.md +4 -1
|
@@ -18,6 +18,7 @@ const architectureDetector_1 = require("../agent/detectors/architectureDetector"
|
|
|
18
18
|
const enhancedSessionContext_1 = require("../agent/context/enhancedSessionContext");
|
|
19
19
|
const claudeMcpServer_1 = require("../agentv3/claudeMcpServer");
|
|
20
20
|
const claudeSystemPrompt_1 = require("../agentv3/claudeSystemPrompt");
|
|
21
|
+
const strategyLoader_1 = require("../agentv3/strategyLoader");
|
|
21
22
|
const claudeFindingExtractor_1 = require("../agentv3/claudeFindingExtractor");
|
|
22
23
|
const focusAppDetector_1 = require("../agentv3/focusAppDetector");
|
|
23
24
|
const sceneClassifier_1 = require("../agentv3/sceneClassifier");
|
|
@@ -35,8 +36,10 @@ const toolNarration_1 = require("../agentv3/toolNarration");
|
|
|
35
36
|
const openAiConfig_1 = require("./openAiConfig");
|
|
36
37
|
const mimoReasoningCompat_1 = require("./mimoReasoningCompat");
|
|
37
38
|
const openAiToolAdapter_1 = require("./openAiToolAdapter");
|
|
39
|
+
const finalResultQualityGate_1 = require("../services/finalResultQualityGate");
|
|
38
40
|
const OPENAI_SESSION_FRESHNESS_MS = 4 * 60 * 60 * 1000;
|
|
39
41
|
const OPENAI_MAX_PLAN_CONTINUATIONS = 3;
|
|
42
|
+
const OPENAI_MAX_FINAL_REPORT_CONTINUATIONS = 1;
|
|
40
43
|
const OPENAI_PLAN_COMPLETE_IDLE_ABORT_MS = 8000;
|
|
41
44
|
function hasAdequateClosedPhaseSummary(phase) {
|
|
42
45
|
if (phase.status !== 'completed' && phase.status !== 'skipped')
|
|
@@ -173,13 +176,49 @@ function looksLikeProcessNarrationParagraph(paragraph) {
|
|
|
173
176
|
if (!compact)
|
|
174
177
|
return false;
|
|
175
178
|
return /^(?:我来|我需要|我将|我会|现在|接下来|下一步|首先[,,]?.*提交|调用\s*`?[\w-]+`?|记录关键发现|数据量充足|非常丰富的数据|让我|为了完成|I need\b|I will\b|Now I\b|Next\b|Let me\b)/i.test(compact)
|
|
176
|
-
||
|
|
179
|
+
|| /现在进入\s*Phase|Phase\s*\d+(?:\.\d+)?.*返回|关键概览|阶段状态更新|执行剩余阶段|继续执行剩余阶段|update_plan_phase|submit_plan|resolve_hypothesis|provider 未主动结束 stream|plan 未完成|plan 已完成/i.test(compact);
|
|
177
180
|
}
|
|
178
181
|
function hasReportMarkers(text) {
|
|
179
182
|
return /(^|\n)\s{0,3}#{1,3}\s+\S/.test(text)
|
|
180
183
|
|| /(^|\n)\s{0,3}\*\*[^*\n]{2,80}\*\*/.test(text)
|
|
181
184
|
|| /(^|\n)\s{0,3}\|/.test(text);
|
|
182
185
|
}
|
|
186
|
+
function normalizeConclusionForComparison(text) {
|
|
187
|
+
return text.trim().replace(/\s+/g, ' ');
|
|
188
|
+
}
|
|
189
|
+
function isSameConclusionText(a, b) {
|
|
190
|
+
const normalizedA = normalizeConclusionForComparison(a || '');
|
|
191
|
+
const normalizedB = normalizeConclusionForComparison(b || '');
|
|
192
|
+
return normalizedA.length > 0 && normalizedA === normalizedB;
|
|
193
|
+
}
|
|
194
|
+
function cleanPlanSummaryForFinalReport(summary) {
|
|
195
|
+
return summary
|
|
196
|
+
.trim()
|
|
197
|
+
.replace(/^(?:完成综合结论输出|完整结构化报告已(?:输出|生成))[。::\s]*/i, '')
|
|
198
|
+
.replace(/^核心发现[::\s]*/i, '')
|
|
199
|
+
.replace(/^所有关键artifact已在Phase\s*\d+(?:\.\d+)?中获取完毕[::。\s]*/i, '')
|
|
200
|
+
.trim();
|
|
201
|
+
}
|
|
202
|
+
function isSubstantialReportText(text) {
|
|
203
|
+
const trimmed = text.trim();
|
|
204
|
+
if (trimmed.length < 200 || !(0, finalResultQualityGate_1.hasDeliverableFinalReportHeading)(trimmed))
|
|
205
|
+
return false;
|
|
206
|
+
if (looksLikeProcessNarrationParagraph(trimmed))
|
|
207
|
+
return false;
|
|
208
|
+
return !looksLikeProcessNarrationParagraph(trimmed.split(/\n{2,}/)[0] || '');
|
|
209
|
+
}
|
|
210
|
+
function isRicherReportCandidate(candidate, baseline) {
|
|
211
|
+
const candidateTrimmed = candidate.trim();
|
|
212
|
+
const baselineTrimmed = baseline.trim();
|
|
213
|
+
if (!isSubstantialReportText(candidateTrimmed))
|
|
214
|
+
return false;
|
|
215
|
+
if (!baselineTrimmed || !isSubstantialReportText(baselineTrimmed))
|
|
216
|
+
return true;
|
|
217
|
+
return candidateTrimmed.length > Math.max(200, baselineTrimmed.length * 1.25);
|
|
218
|
+
}
|
|
219
|
+
function selectOpenAiRecoveryAnswer(input) {
|
|
220
|
+
return input.runAnswer.trim() ? input.runAnswer : input.accumulatedAnswer;
|
|
221
|
+
}
|
|
183
222
|
function findEmbeddedFinalReportStart(text) {
|
|
184
223
|
const match = /#{1,3}\s*(?:[\w\u4e00-\u9fff` .::_-]{0,40})?(?:分析报告|综合结论|最终结论|最终报告|Final Report|Analysis Report)(?=\s|$|[::。.!!?\n])/i.exec(text);
|
|
185
224
|
return match?.index ?? -1;
|
|
@@ -216,12 +255,13 @@ function sanitizeOpenAiConclusionText(conclusion, options = {}) {
|
|
|
216
255
|
? paragraphs.slice(firstReportParagraph).join('\n\n').trim()
|
|
217
256
|
: trimmed;
|
|
218
257
|
const strippedStillProcess = looksLikeProcessNarrationParagraph(stripped.split(/\n{2,}/)[0] || '');
|
|
219
|
-
|
|
258
|
+
const strippedHasProcessNarration = looksLikeProcessNarrationParagraph(stripped);
|
|
259
|
+
if (firstReportParagraph > 0 && stripped.length >= 80 && !strippedStillProcess && !strippedHasProcessNarration) {
|
|
220
260
|
return stripped;
|
|
221
261
|
}
|
|
222
262
|
if (fallback &&
|
|
223
263
|
(options.completedByPlanIdle || options.planComplete) &&
|
|
224
|
-
(firstReportParagraph > 0 || strippedStillProcess || !hasReportMarkers(trimmed))) {
|
|
264
|
+
(firstReportParagraph > 0 || strippedStillProcess || strippedHasProcessNarration || !hasReportMarkers(trimmed))) {
|
|
225
265
|
return fallback;
|
|
226
266
|
}
|
|
227
267
|
return trimmed;
|
|
@@ -234,14 +274,28 @@ function chooseOpenAiConclusionText(input) {
|
|
|
234
274
|
});
|
|
235
275
|
const fallback = input.fallbackConclusion?.trim();
|
|
236
276
|
const accumulated = input.accumulatedAnswer.trim();
|
|
237
|
-
|
|
277
|
+
const selectedIsFallback = fallback ? isSameConclusionText(selected, fallback) : false;
|
|
278
|
+
const selectedNeedsRecovery = selectedIsFallback ||
|
|
279
|
+
(0, finalResultQualityGate_1.looksLikePhaseSummaryFallback)(selected) ||
|
|
280
|
+
!isSubstantialReportText(selected) ||
|
|
281
|
+
looksLikeProcessNarrationParagraph(selected.split(/\n{2,}/)[0] || '');
|
|
282
|
+
const mayRecoverAccumulated = accumulated.length > 0 &&
|
|
283
|
+
!isSameConclusionText(accumulated, input.candidate) &&
|
|
284
|
+
(input.completedByPlanIdle || (input.planComplete && selectedNeedsRecovery));
|
|
285
|
+
if (!mayRecoverAccumulated)
|
|
238
286
|
return selected;
|
|
287
|
+
const recovered = sanitizeOpenAiConclusionText(accumulated, {
|
|
288
|
+
completedByPlanIdle: input.completedByPlanIdle,
|
|
289
|
+
planComplete: input.planComplete,
|
|
290
|
+
fallbackConclusion: input.fallbackConclusion,
|
|
291
|
+
});
|
|
292
|
+
if (isRicherReportCandidate(recovered, selected)) {
|
|
293
|
+
return recovered;
|
|
239
294
|
}
|
|
240
|
-
|
|
241
|
-
if (hasReportMarkers(recovered) && recovered.length > Math.max(200, selected.length * 1.25)) {
|
|
295
|
+
if ((0, finalResultQualityGate_1.hasDeliverableFinalReportHeading)(recovered) && recovered.length > Math.max(200, selected.length * 1.25)) {
|
|
242
296
|
return recovered;
|
|
243
297
|
}
|
|
244
|
-
if (fallback &&
|
|
298
|
+
if (fallback && selectedIsFallback && (0, finalResultQualityGate_1.hasDeliverableFinalReportHeading)(recovered) && recovered.length > selected.length) {
|
|
245
299
|
return recovered;
|
|
246
300
|
}
|
|
247
301
|
return selected;
|
|
@@ -251,6 +305,7 @@ exports.__testing = {
|
|
|
251
305
|
readCompletedStreamFinalOutput,
|
|
252
306
|
sanitizeOpenAiConclusionText,
|
|
253
307
|
chooseOpenAiConclusionText,
|
|
308
|
+
selectOpenAiRecoveryAnswer,
|
|
254
309
|
isRecoverableOpenAIStreamTermination,
|
|
255
310
|
compactProviderErrorMessage,
|
|
256
311
|
};
|
|
@@ -392,16 +447,18 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
392
447
|
tools: context.tools,
|
|
393
448
|
toolUseBehavior: 'run_llm_again',
|
|
394
449
|
modelSettings: {
|
|
450
|
+
maxTokens: config.maxOutputTokens,
|
|
395
451
|
parallelToolCalls: false,
|
|
396
452
|
},
|
|
397
453
|
});
|
|
398
|
-
|
|
454
|
+
let activeController;
|
|
399
455
|
const timeoutMs = (quickMode ? config.quickPathPerTurnMs : config.fullPathPerTurnMs)
|
|
400
456
|
* (quickMode ? config.quickMaxTurns : config.maxTurns);
|
|
457
|
+
const deadlineAt = Date.now() + timeoutMs;
|
|
401
458
|
let timedOut = false;
|
|
402
459
|
const timeout = setTimeout(() => {
|
|
403
460
|
timedOut = true;
|
|
404
|
-
|
|
461
|
+
activeController?.abort();
|
|
405
462
|
}, timeoutMs);
|
|
406
463
|
this.emitUpdate({
|
|
407
464
|
type: 'progress',
|
|
@@ -423,7 +480,32 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
423
480
|
let partial = false;
|
|
424
481
|
let terminationReason;
|
|
425
482
|
let terminationMessage;
|
|
483
|
+
let finalReportContinuations = 0;
|
|
484
|
+
const markTimeoutPartial = (planStatus) => {
|
|
485
|
+
partial = true;
|
|
486
|
+
terminationReason = 'timeout';
|
|
487
|
+
terminationMessage = (0, outputLanguage_1.localize)(config.outputLanguage, `OpenAI 分析超过 ${Math.round(timeoutMs / 1000)} 秒超时,结果可能不完整。`, `OpenAI analysis timed out after ${Math.round(timeoutMs / 1000)} seconds; the result may be incomplete.`);
|
|
488
|
+
conclusion = this.withIncompletePlanWarning(conclusion, planStatus, config.outputLanguage);
|
|
489
|
+
this.emitUpdate({
|
|
490
|
+
type: 'degraded',
|
|
491
|
+
content: {
|
|
492
|
+
module: 'openAiRuntime',
|
|
493
|
+
fallback: 'partial_result_after_timeout',
|
|
494
|
+
partial: true,
|
|
495
|
+
terminationReason,
|
|
496
|
+
message: terminationMessage,
|
|
497
|
+
},
|
|
498
|
+
timestamp: Date.now(),
|
|
499
|
+
});
|
|
500
|
+
};
|
|
426
501
|
for (let continuation = 0;; continuation++) {
|
|
502
|
+
if (timedOut || Date.now() >= deadlineAt) {
|
|
503
|
+
timedOut = true;
|
|
504
|
+
markTimeoutPartial(this.getPlanCompletionStatus(sessionId, quickMode));
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
const controller = new AbortController();
|
|
508
|
+
activeController = controller;
|
|
427
509
|
let runAnswer = '';
|
|
428
510
|
let runTurns = 0;
|
|
429
511
|
let completedByPlanIdle = false;
|
|
@@ -485,6 +567,9 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
485
567
|
}
|
|
486
568
|
finally {
|
|
487
569
|
clearPlanCompleteIdleTimer();
|
|
570
|
+
if (activeController === controller) {
|
|
571
|
+
activeController = undefined;
|
|
572
|
+
}
|
|
488
573
|
}
|
|
489
574
|
rounds += runTurns || stream.currentTurn || 0;
|
|
490
575
|
const streamFinalOutput = readCompletedStreamFinalOutput(stream, {
|
|
@@ -497,13 +582,14 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
497
582
|
: (streamFinalOutput ? JSON.stringify(streamFinalOutput) : runAnswer);
|
|
498
583
|
const planStatus = this.getPlanCompletionStatus(sessionId, quickMode);
|
|
499
584
|
const fallbackConclusion = this.buildCompletedPlanFallbackConclusion(sessionId, quickMode, config.outputLanguage);
|
|
585
|
+
const recoveryAnswer = selectOpenAiRecoveryAnswer({ runAnswer, accumulatedAnswer });
|
|
500
586
|
conclusion = chooseOpenAiConclusionText({
|
|
501
587
|
candidate: finalOutput ||
|
|
502
588
|
runAnswer ||
|
|
503
589
|
accumulatedAnswer ||
|
|
504
590
|
fallbackConclusion ||
|
|
505
591
|
'',
|
|
506
|
-
accumulatedAnswer,
|
|
592
|
+
accumulatedAnswer: recoveryAnswer,
|
|
507
593
|
completedByPlanIdle,
|
|
508
594
|
planComplete: planStatus.complete,
|
|
509
595
|
fallbackConclusion,
|
|
@@ -514,25 +600,43 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
514
600
|
finalRunState = this.safeSerializeRunState(stream.state);
|
|
515
601
|
}
|
|
516
602
|
if (timedOut && !completedByPlanIdle) {
|
|
517
|
-
|
|
518
|
-
terminationReason = 'timeout';
|
|
519
|
-
terminationMessage = (0, outputLanguage_1.localize)(config.outputLanguage, `OpenAI 分析超过 ${Math.round(timeoutMs / 1000)} 秒超时,结果可能不完整。`, `OpenAI analysis timed out after ${Math.round(timeoutMs / 1000)} seconds; the result may be incomplete.`);
|
|
520
|
-
conclusion = this.withIncompletePlanWarning(conclusion, planStatus, config.outputLanguage);
|
|
521
|
-
this.emitUpdate({
|
|
522
|
-
type: 'degraded',
|
|
523
|
-
content: {
|
|
524
|
-
module: 'openAiRuntime',
|
|
525
|
-
fallback: 'partial_result_after_timeout',
|
|
526
|
-
partial: true,
|
|
527
|
-
terminationReason,
|
|
528
|
-
message: terminationMessage,
|
|
529
|
-
},
|
|
530
|
-
timestamp: Date.now(),
|
|
531
|
-
});
|
|
603
|
+
markTimeoutPartial(planStatus);
|
|
532
604
|
break;
|
|
533
605
|
}
|
|
534
|
-
if (planStatus.complete)
|
|
606
|
+
if (planStatus.complete) {
|
|
607
|
+
const streamHistory = Array.isArray(stream.history)
|
|
608
|
+
? stream.history
|
|
609
|
+
: [];
|
|
610
|
+
if (this.shouldRequestFinalReportAfterPlanComplete({
|
|
611
|
+
quickMode,
|
|
612
|
+
planStatus,
|
|
613
|
+
conclusion,
|
|
614
|
+
fallbackConclusion,
|
|
615
|
+
completedByPlanIdle,
|
|
616
|
+
timedOut,
|
|
617
|
+
finalReportContinuations,
|
|
618
|
+
}) && streamHistory.length > 0) {
|
|
619
|
+
finalReportContinuations++;
|
|
620
|
+
this.emitUpdate({
|
|
621
|
+
type: 'progress',
|
|
622
|
+
content: {
|
|
623
|
+
phase: 'concluding',
|
|
624
|
+
message: this.formatPlanCompleteReportContinuationMessage(config.outputLanguage),
|
|
625
|
+
},
|
|
626
|
+
timestamp: Date.now(),
|
|
627
|
+
});
|
|
628
|
+
currentInput = [
|
|
629
|
+
...streamHistory,
|
|
630
|
+
{
|
|
631
|
+
role: 'user',
|
|
632
|
+
content: this.buildFinalReportAfterPlanCompletePrompt(config.outputLanguage),
|
|
633
|
+
},
|
|
634
|
+
];
|
|
635
|
+
currentPreviousResponseId = undefined;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
535
638
|
break;
|
|
639
|
+
}
|
|
536
640
|
if (continuation >= OPENAI_MAX_PLAN_CONTINUATIONS) {
|
|
537
641
|
partial = true;
|
|
538
642
|
terminationReason = 'plan_incomplete';
|
|
@@ -572,10 +676,54 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
572
676
|
if (options.codeAwareMode && options.codeAwareMode !== 'off') {
|
|
573
677
|
conclusion = (0, codeAwareOutputRegistry_1.sanitizeCodeAwareText)(sessionId, conclusion);
|
|
574
678
|
}
|
|
679
|
+
const finalFallbackConclusion = this.buildCompletedPlanFallbackConclusion(sessionId, quickMode, config.outputLanguage);
|
|
680
|
+
if (finalFallbackConclusion &&
|
|
681
|
+
(isSameConclusionText(conclusion, finalFallbackConclusion) ||
|
|
682
|
+
(0, finalResultQualityGate_1.looksLikePhaseSummaryFallback)(conclusion)) &&
|
|
683
|
+
!partial) {
|
|
684
|
+
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.');
|
|
686
|
+
this.emitUpdate({
|
|
687
|
+
type: 'degraded',
|
|
688
|
+
content: {
|
|
689
|
+
module: 'openAiRuntime',
|
|
690
|
+
fallback: 'completed_plan_summary_fallback',
|
|
691
|
+
partial: true,
|
|
692
|
+
message: terminationMessage,
|
|
693
|
+
},
|
|
694
|
+
timestamp: Date.now(),
|
|
695
|
+
});
|
|
696
|
+
}
|
|
575
697
|
const findings = (0, claudeFindingExtractor_1.extractFindingsFromText)(conclusion);
|
|
576
698
|
const confidence = partial
|
|
577
699
|
? Math.min(0.55, this.estimateConfidence(findings, conclusion))
|
|
578
700
|
: this.estimateConfidence(findings, conclusion);
|
|
701
|
+
const result = {
|
|
702
|
+
sessionId,
|
|
703
|
+
success: true,
|
|
704
|
+
findings,
|
|
705
|
+
hypotheses: context.hypotheses.map(h => this.toProtocolHypothesis(h)),
|
|
706
|
+
conclusion,
|
|
707
|
+
confidence,
|
|
708
|
+
rounds,
|
|
709
|
+
totalDurationMs: Date.now() - startTime,
|
|
710
|
+
partial: partial || undefined,
|
|
711
|
+
terminationReason,
|
|
712
|
+
terminationMessage,
|
|
713
|
+
};
|
|
714
|
+
const gateIssue = (0, finalResultQualityGate_1.applyFinalResultQualityGate)({ result, query });
|
|
715
|
+
if (gateIssue) {
|
|
716
|
+
this.emitUpdate({
|
|
717
|
+
type: 'degraded',
|
|
718
|
+
content: {
|
|
719
|
+
module: 'openAiRuntime',
|
|
720
|
+
fallback: gateIssue.code,
|
|
721
|
+
partial: true,
|
|
722
|
+
message: gateIssue.message,
|
|
723
|
+
},
|
|
724
|
+
timestamp: Date.now(),
|
|
725
|
+
});
|
|
726
|
+
}
|
|
579
727
|
this.sessionMap.set(context.sessionMapKey, {
|
|
580
728
|
history: finalHistory,
|
|
581
729
|
lastResponseId: finalLastResponseId,
|
|
@@ -585,37 +733,23 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
585
733
|
this.recordTurn({
|
|
586
734
|
query,
|
|
587
735
|
sessionId,
|
|
588
|
-
|
|
589
|
-
findings,
|
|
590
|
-
confidence,
|
|
736
|
+
result,
|
|
591
737
|
sessionContext: context.sessionContext,
|
|
592
738
|
previousTurnCount: context.previousTurns.length,
|
|
593
739
|
quickMode,
|
|
594
740
|
});
|
|
595
741
|
this.emitUpdate({
|
|
596
742
|
type: 'conclusion',
|
|
597
|
-
content: { conclusion, durationMs: Date.now() - startTime, turns: rounds },
|
|
743
|
+
content: { conclusion: result.conclusion, durationMs: Date.now() - startTime, turns: rounds },
|
|
598
744
|
timestamp: Date.now(),
|
|
599
745
|
});
|
|
600
746
|
this.emitUpdate({
|
|
601
747
|
type: 'answer_token',
|
|
602
|
-
content: { done: true, totalChars: conclusion.length },
|
|
748
|
+
content: { done: true, totalChars: result.conclusion.length },
|
|
603
749
|
timestamp: Date.now(),
|
|
604
750
|
});
|
|
605
751
|
await provider.close().catch(() => undefined);
|
|
606
|
-
return
|
|
607
|
-
sessionId,
|
|
608
|
-
success: true,
|
|
609
|
-
findings,
|
|
610
|
-
hypotheses: context.hypotheses.map(h => this.toProtocolHypothesis(h)),
|
|
611
|
-
conclusion,
|
|
612
|
-
confidence,
|
|
613
|
-
rounds,
|
|
614
|
-
totalDurationMs: Date.now() - startTime,
|
|
615
|
-
partial: partial || undefined,
|
|
616
|
-
terminationReason,
|
|
617
|
-
terminationMessage,
|
|
618
|
-
};
|
|
752
|
+
return result;
|
|
619
753
|
}
|
|
620
754
|
catch (error) {
|
|
621
755
|
clearTimeout(timeout);
|
|
@@ -1113,6 +1247,42 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
1113
1247
|
fallbackAnswer.trim().length > 0 ||
|
|
1114
1248
|
this.buildCompletedPlanFallbackConclusion(sessionId, quickMode, outputLanguage_1.DEFAULT_OUTPUT_LANGUAGE) !== undefined;
|
|
1115
1249
|
}
|
|
1250
|
+
shouldRequestFinalReportAfterPlanComplete(input) {
|
|
1251
|
+
if (input.quickMode ||
|
|
1252
|
+
!input.planStatus.complete ||
|
|
1253
|
+
input.timedOut ||
|
|
1254
|
+
input.finalReportContinuations >= OPENAI_MAX_FINAL_REPORT_CONTINUATIONS) {
|
|
1255
|
+
return false;
|
|
1256
|
+
}
|
|
1257
|
+
const conclusion = input.conclusion.trim();
|
|
1258
|
+
const fallback = input.fallbackConclusion?.trim();
|
|
1259
|
+
if (!fallback)
|
|
1260
|
+
return false;
|
|
1261
|
+
if (!conclusion)
|
|
1262
|
+
return true;
|
|
1263
|
+
if (isSameConclusionText(conclusion, fallback))
|
|
1264
|
+
return true;
|
|
1265
|
+
if ((0, finalResultQualityGate_1.looksLikePhaseSummaryFallback)(conclusion))
|
|
1266
|
+
return true;
|
|
1267
|
+
if (!(0, finalResultQualityGate_1.hasDeliverableFinalReportHeading)(conclusion))
|
|
1268
|
+
return true;
|
|
1269
|
+
if (looksLikeProcessNarrationParagraph(conclusion))
|
|
1270
|
+
return true;
|
|
1271
|
+
return looksLikeProcessNarrationParagraph(conclusion.split(/\n{2,}/)[0] || '');
|
|
1272
|
+
}
|
|
1273
|
+
buildFinalReportAfterPlanCompletePrompt(outputLanguage) {
|
|
1274
|
+
const templateName = outputLanguage === 'en'
|
|
1275
|
+
? 'prompt-openai-final-report-continuation-en'
|
|
1276
|
+
: 'prompt-openai-final-report-continuation-zh';
|
|
1277
|
+
const template = (0, strategyLoader_1.loadPromptTemplate)(templateName);
|
|
1278
|
+
if (!template) {
|
|
1279
|
+
throw new Error(`Missing OpenAI final-report continuation prompt template: ${templateName}`);
|
|
1280
|
+
}
|
|
1281
|
+
return template;
|
|
1282
|
+
}
|
|
1283
|
+
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
|
+
}
|
|
1116
1286
|
buildCompletedPlanFallbackConclusion(sessionId, quickMode, outputLanguage) {
|
|
1117
1287
|
if (quickMode)
|
|
1118
1288
|
return undefined;
|
|
@@ -1121,20 +1291,70 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
1121
1291
|
return undefined;
|
|
1122
1292
|
if (!this.getPlanCompletionStatus(sessionId, quickMode).complete)
|
|
1123
1293
|
return undefined;
|
|
1294
|
+
const isFinalReportPhase = (phase) => /(综合结论|最终结论|结论|报告|conclusion|final report)/i.test(`${phase.name} ${phase.goal}`);
|
|
1124
1295
|
const summaries = plan.phases
|
|
1125
1296
|
.filter(hasAdequateClosedPhaseSummary)
|
|
1126
1297
|
.map(phase => {
|
|
1127
1298
|
const name = phase.name || phase.id;
|
|
1128
|
-
return `- ${name}: ${phase.summary
|
|
1299
|
+
return `- ${name}: ${cleanPlanSummaryForFinalReport(phase.summary || '')}`;
|
|
1129
1300
|
});
|
|
1130
1301
|
if (summaries.length === 0)
|
|
1131
1302
|
return undefined;
|
|
1132
1303
|
const finalPhase = [...plan.phases]
|
|
1133
1304
|
.reverse()
|
|
1134
1305
|
.find(phase => hasAdequateClosedPhaseSummary(phase) &&
|
|
1135
|
-
|
|
1136
|
-
const finalSummary = finalPhase?.summary?.trim() || summaries[summaries.length - 1]?.replace(/^-\s*[^:]+:\s*/, '') || '';
|
|
1137
|
-
|
|
1306
|
+
isFinalReportPhase(phase));
|
|
1307
|
+
const finalSummary = cleanPlanSummaryForFinalReport(finalPhase?.summary?.trim() || summaries[summaries.length - 1]?.replace(/^-\s*[^:]+:\s*/, '') || '');
|
|
1308
|
+
const evidenceBullets = plan.phases
|
|
1309
|
+
.filter(phase => hasAdequateClosedPhaseSummary(phase) && !isFinalReportPhase(phase))
|
|
1310
|
+
.map(phase => {
|
|
1311
|
+
const name = phase.name || phase.id;
|
|
1312
|
+
return `- ${name}: ${cleanPlanSummaryForFinalReport(phase.summary || '')}`;
|
|
1313
|
+
})
|
|
1314
|
+
.filter(line => line.trim().length > 4)
|
|
1315
|
+
.slice(0, 8)
|
|
1316
|
+
.join('\n');
|
|
1317
|
+
return (0, outputLanguage_1.localize)(outputLanguage, [
|
|
1318
|
+
'## 综合结论',
|
|
1319
|
+
'',
|
|
1320
|
+
finalSummary || '分析计划已完成,以下结论基于已采集的结构化证据收敛。',
|
|
1321
|
+
'',
|
|
1322
|
+
'## 关键证据链',
|
|
1323
|
+
'',
|
|
1324
|
+
evidenceBullets || '- 已完成的计划阶段均有结构化证据支撑。',
|
|
1325
|
+
'',
|
|
1326
|
+
'## 根因拆解',
|
|
1327
|
+
'',
|
|
1328
|
+
'- 以上证据按阶段产出、关键指标、已确认假设和已排除因素归并;优化优先级以已验证且可执行的瓶颈为准。',
|
|
1329
|
+
'',
|
|
1330
|
+
'## 优化建议',
|
|
1331
|
+
'',
|
|
1332
|
+
'- 优先处理证据支持的可操作瓶颈;对已排除但风险较高的因素保留必要监控。',
|
|
1333
|
+
'',
|
|
1334
|
+
'## 置信度/限制',
|
|
1335
|
+
'',
|
|
1336
|
+
'- 结论基于已完成计划阶段的结构化证据收敛;若需要代码级 owner 定位,应结合源码符号继续分析。',
|
|
1337
|
+
].join('\n'), [
|
|
1338
|
+
'## Final Conclusion',
|
|
1339
|
+
'',
|
|
1340
|
+
finalSummary || 'The analysis plan completed; this conclusion is synthesized from the collected structured evidence.',
|
|
1341
|
+
'',
|
|
1342
|
+
'## Key Evidence',
|
|
1343
|
+
'',
|
|
1344
|
+
evidenceBullets || '- Completed plan phases contain structured evidence.',
|
|
1345
|
+
'',
|
|
1346
|
+
'## Root Cause Breakdown',
|
|
1347
|
+
'',
|
|
1348
|
+
'- The evidence is grouped by phase outputs, key metrics, confirmed hypotheses, and excluded factors; optimization priority should follow verified and actionable bottlenecks.',
|
|
1349
|
+
'',
|
|
1350
|
+
'## Recommendations',
|
|
1351
|
+
'',
|
|
1352
|
+
'- Prioritize actionable bottlenecks supported by evidence; keep monitoring excluded factors that still carry residual risk.',
|
|
1353
|
+
'',
|
|
1354
|
+
'## Confidence / Limits',
|
|
1355
|
+
'',
|
|
1356
|
+
'- This conclusion is synthesized from structured evidence collected by the completed plan phases. Use source-code symbol lookup for owner-level fixes.',
|
|
1357
|
+
].join('\n'));
|
|
1138
1358
|
}
|
|
1139
1359
|
buildPlanPhaseSummaryFallbackConclusion(sessionId, quickMode, outputLanguage) {
|
|
1140
1360
|
if (quickMode)
|
|
@@ -1195,9 +1415,19 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
1195
1415
|
this.recordTurn({
|
|
1196
1416
|
query: params.query,
|
|
1197
1417
|
sessionId: params.sessionId,
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1418
|
+
result: {
|
|
1419
|
+
sessionId: params.sessionId,
|
|
1420
|
+
success: true,
|
|
1421
|
+
findings,
|
|
1422
|
+
hypotheses: params.context.hypotheses.map(h => this.toProtocolHypothesis(h)),
|
|
1423
|
+
conclusion,
|
|
1424
|
+
confidence,
|
|
1425
|
+
rounds: params.rounds,
|
|
1426
|
+
totalDurationMs: Date.now() - params.startTime,
|
|
1427
|
+
partial: true,
|
|
1428
|
+
terminationReason,
|
|
1429
|
+
terminationMessage,
|
|
1430
|
+
},
|
|
1201
1431
|
sessionContext: params.context.sessionContext,
|
|
1202
1432
|
previousTurnCount: params.context.previousTurns.length,
|
|
1203
1433
|
quickMode: params.quickMode,
|
|
@@ -1337,16 +1567,21 @@ class OpenAIRuntime extends events_1.EventEmitter {
|
|
|
1337
1567
|
followUpType: input.previousTurnCount > 0 ? 'extend' : 'initial',
|
|
1338
1568
|
}, {
|
|
1339
1569
|
agentId: 'openai-agent',
|
|
1340
|
-
success:
|
|
1341
|
-
findings: input.findings,
|
|
1342
|
-
confidence: input.confidence,
|
|
1343
|
-
message: input.conclusion,
|
|
1344
|
-
|
|
1570
|
+
success: input.result.success,
|
|
1571
|
+
findings: input.result.findings,
|
|
1572
|
+
confidence: input.result.confidence,
|
|
1573
|
+
message: input.result.conclusion,
|
|
1574
|
+
partial: input.result.partial,
|
|
1575
|
+
terminationReason: input.result.terminationReason,
|
|
1576
|
+
terminationMessage: input.result.terminationMessage,
|
|
1577
|
+
}, input.result.findings);
|
|
1578
|
+
if (input.result.partial === true)
|
|
1579
|
+
return;
|
|
1345
1580
|
input.sessionContext.updateWorkingMemoryFromConclusion({
|
|
1346
1581
|
turnIndex: input.previousTurnCount,
|
|
1347
1582
|
query: input.query,
|
|
1348
|
-
conclusion: input.conclusion,
|
|
1349
|
-
confidence: input.confidence,
|
|
1583
|
+
conclusion: input.result.conclusion,
|
|
1584
|
+
confidence: input.result.confidence,
|
|
1350
1585
|
});
|
|
1351
1586
|
}
|
|
1352
1587
|
captureEntitiesFromSkillDisplayResults(displayResults, entityStore) {
|