windows-exe-decompiler-mcp-server 0.1.0
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/CODEX_INSTALLATION.md +69 -0
- package/COPILOT_INSTALLATION.md +77 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/bin/windows-exe-decompiler-mcp-server.js +3 -0
- package/dist/analysis-provenance.d.ts +184 -0
- package/dist/analysis-provenance.js +74 -0
- package/dist/analysis-task-runner.d.ts +31 -0
- package/dist/analysis-task-runner.js +160 -0
- package/dist/artifact-inventory.d.ts +23 -0
- package/dist/artifact-inventory.js +175 -0
- package/dist/cache-manager.d.ts +128 -0
- package/dist/cache-manager.js +454 -0
- package/dist/confidence-semantics.d.ts +66 -0
- package/dist/confidence-semantics.js +122 -0
- package/dist/config.d.ts +335 -0
- package/dist/config.js +193 -0
- package/dist/database.d.ts +227 -0
- package/dist/database.js +601 -0
- package/dist/decompiler-worker.d.ts +441 -0
- package/dist/decompiler-worker.js +1962 -0
- package/dist/dynamic-trace.d.ts +95 -0
- package/dist/dynamic-trace.js +629 -0
- package/dist/env-validator.d.ts +15 -0
- package/dist/env-validator.js +249 -0
- package/dist/error-handler.d.ts +28 -0
- package/dist/error-handler.example.d.ts +22 -0
- package/dist/error-handler.example.js +141 -0
- package/dist/error-handler.js +139 -0
- package/dist/ghidra-analysis-status.d.ts +49 -0
- package/dist/ghidra-analysis-status.js +178 -0
- package/dist/ghidra-config.d.ts +134 -0
- package/dist/ghidra-config.js +464 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +200 -0
- package/dist/job-queue.d.ts +169 -0
- package/dist/job-queue.js +407 -0
- package/dist/logger.d.ts +106 -0
- package/dist/logger.js +176 -0
- package/dist/policy-guard.d.ts +115 -0
- package/dist/policy-guard.js +243 -0
- package/dist/process-output.d.ts +15 -0
- package/dist/process-output.js +90 -0
- package/dist/prompts/function-explanation-review.d.ts +5 -0
- package/dist/prompts/function-explanation-review.js +64 -0
- package/dist/prompts/semantic-name-review.d.ts +5 -0
- package/dist/prompts/semantic-name-review.js +63 -0
- package/dist/runtime-correlation.d.ts +34 -0
- package/dist/runtime-correlation.js +279 -0
- package/dist/runtime-paths.d.ts +3 -0
- package/dist/runtime-paths.js +11 -0
- package/dist/selection-diff.d.ts +667 -0
- package/dist/selection-diff.js +53 -0
- package/dist/semantic-name-suggestion-artifacts.d.ts +116 -0
- package/dist/semantic-name-suggestion-artifacts.js +314 -0
- package/dist/server.d.ts +129 -0
- package/dist/server.js +578 -0
- package/dist/tools/artifact-read.d.ts +235 -0
- package/dist/tools/artifact-read.js +317 -0
- package/dist/tools/artifacts-diff.d.ts +728 -0
- package/dist/tools/artifacts-diff.js +304 -0
- package/dist/tools/artifacts-list.d.ts +515 -0
- package/dist/tools/artifacts-list.js +389 -0
- package/dist/tools/attack-map.d.ts +290 -0
- package/dist/tools/attack-map.js +519 -0
- package/dist/tools/cache-observability.d.ts +4 -0
- package/dist/tools/cache-observability.js +36 -0
- package/dist/tools/code-function-cfg.d.ts +50 -0
- package/dist/tools/code-function-cfg.js +102 -0
- package/dist/tools/code-function-decompile.d.ts +55 -0
- package/dist/tools/code-function-decompile.js +103 -0
- package/dist/tools/code-function-disassemble.d.ts +43 -0
- package/dist/tools/code-function-disassemble.js +185 -0
- package/dist/tools/code-function-explain-apply.d.ts +255 -0
- package/dist/tools/code-function-explain-apply.js +225 -0
- package/dist/tools/code-function-explain-prepare.d.ts +535 -0
- package/dist/tools/code-function-explain-prepare.js +276 -0
- package/dist/tools/code-function-explain-review.d.ts +397 -0
- package/dist/tools/code-function-explain-review.js +589 -0
- package/dist/tools/code-function-rename-apply.d.ts +248 -0
- package/dist/tools/code-function-rename-apply.js +220 -0
- package/dist/tools/code-function-rename-prepare.d.ts +506 -0
- package/dist/tools/code-function-rename-prepare.js +279 -0
- package/dist/tools/code-function-rename-review.d.ts +574 -0
- package/dist/tools/code-function-rename-review.js +761 -0
- package/dist/tools/code-functions-list.d.ts +37 -0
- package/dist/tools/code-functions-list.js +91 -0
- package/dist/tools/code-functions-rank.d.ts +34 -0
- package/dist/tools/code-functions-rank.js +90 -0
- package/dist/tools/code-functions-reconstruct.d.ts +2725 -0
- package/dist/tools/code-functions-reconstruct.js +2807 -0
- package/dist/tools/code-functions-search.d.ts +39 -0
- package/dist/tools/code-functions-search.js +90 -0
- package/dist/tools/code-reconstruct-export.d.ts +1212 -0
- package/dist/tools/code-reconstruct-export.js +4002 -0
- package/dist/tools/code-reconstruct-plan.d.ts +274 -0
- package/dist/tools/code-reconstruct-plan.js +342 -0
- package/dist/tools/dotnet-metadata-extract.d.ts +541 -0
- package/dist/tools/dotnet-metadata-extract.js +355 -0
- package/dist/tools/dotnet-reconstruct-export.d.ts +567 -0
- package/dist/tools/dotnet-reconstruct-export.js +1151 -0
- package/dist/tools/dotnet-types-list.d.ts +325 -0
- package/dist/tools/dotnet-types-list.js +201 -0
- package/dist/tools/dynamic-dependencies.d.ts +115 -0
- package/dist/tools/dynamic-dependencies.js +213 -0
- package/dist/tools/dynamic-memory-import.d.ts +10 -0
- package/dist/tools/dynamic-memory-import.js +567 -0
- package/dist/tools/dynamic-trace-import.d.ts +10 -0
- package/dist/tools/dynamic-trace-import.js +235 -0
- package/dist/tools/entrypoint-fallback-disasm.d.ts +30 -0
- package/dist/tools/entrypoint-fallback-disasm.js +89 -0
- package/dist/tools/ghidra-analyze.d.ts +88 -0
- package/dist/tools/ghidra-analyze.js +208 -0
- package/dist/tools/ghidra-health.d.ts +37 -0
- package/dist/tools/ghidra-health.js +212 -0
- package/dist/tools/ioc-export.d.ts +209 -0
- package/dist/tools/ioc-export.js +542 -0
- package/dist/tools/packer-detect.d.ts +165 -0
- package/dist/tools/packer-detect.js +284 -0
- package/dist/tools/pe-exports-extract.d.ts +175 -0
- package/dist/tools/pe-exports-extract.js +253 -0
- package/dist/tools/pe-fingerprint.d.ts +234 -0
- package/dist/tools/pe-fingerprint.js +269 -0
- package/dist/tools/pe-imports-extract.d.ts +105 -0
- package/dist/tools/pe-imports-extract.js +245 -0
- package/dist/tools/report-generate.d.ts +157 -0
- package/dist/tools/report-generate.js +457 -0
- package/dist/tools/report-summarize.d.ts +2131 -0
- package/dist/tools/report-summarize.js +596 -0
- package/dist/tools/runtime-detect.d.ts +135 -0
- package/dist/tools/runtime-detect.js +247 -0
- package/dist/tools/sample-ingest.d.ts +94 -0
- package/dist/tools/sample-ingest.js +327 -0
- package/dist/tools/sample-profile-get.d.ts +183 -0
- package/dist/tools/sample-profile-get.js +121 -0
- package/dist/tools/sandbox-execute.d.ts +441 -0
- package/dist/tools/sandbox-execute.js +392 -0
- package/dist/tools/strings-extract.d.ts +375 -0
- package/dist/tools/strings-extract.js +314 -0
- package/dist/tools/strings-floss-decode.d.ts +143 -0
- package/dist/tools/strings-floss-decode.js +259 -0
- package/dist/tools/system-health.d.ts +434 -0
- package/dist/tools/system-health.js +446 -0
- package/dist/tools/task-cancel.d.ts +21 -0
- package/dist/tools/task-cancel.js +70 -0
- package/dist/tools/task-status.d.ts +27 -0
- package/dist/tools/task-status.js +106 -0
- package/dist/tools/task-sweep.d.ts +22 -0
- package/dist/tools/task-sweep.js +77 -0
- package/dist/tools/tool-help.d.ts +340 -0
- package/dist/tools/tool-help.js +261 -0
- package/dist/tools/yara-scan.d.ts +554 -0
- package/dist/tools/yara-scan.js +313 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.js +41 -0
- package/dist/worker-pool.d.ts +204 -0
- package/dist/worker-pool.js +650 -0
- package/dist/workflows/deep-static.d.ts +104 -0
- package/dist/workflows/deep-static.js +276 -0
- package/dist/workflows/function-explanation-review.d.ts +655 -0
- package/dist/workflows/function-explanation-review.js +440 -0
- package/dist/workflows/reconstruct.d.ts +2053 -0
- package/dist/workflows/reconstruct.js +666 -0
- package/dist/workflows/semantic-name-review.d.ts +2418 -0
- package/dist/workflows/semantic-name-review.js +521 -0
- package/dist/workflows/triage.d.ts +659 -0
- package/dist/workflows/triage.js +1374 -0
- package/dist/workspace-manager.d.ts +150 -0
- package/dist/workspace-manager.js +411 -0
- package/ghidra_scripts/DecompileFunction.java +487 -0
- package/ghidra_scripts/DecompileFunction.py +150 -0
- package/ghidra_scripts/ExtractCFG.java +256 -0
- package/ghidra_scripts/ExtractCFG.py +233 -0
- package/ghidra_scripts/ExtractFunctions.java +442 -0
- package/ghidra_scripts/ExtractFunctions.py +101 -0
- package/ghidra_scripts/README.md +125 -0
- package/ghidra_scripts/SearchFunctionReferences.java +380 -0
- package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -0
- package/helpers/DotNetMetadataProbe/Program.cs +566 -0
- package/install-to-codex.ps1 +178 -0
- package/install-to-copilot.ps1 +303 -0
- package/package.json +101 -0
- package/requirements.txt +9 -0
- package/workers/requirements-dynamic.txt +11 -0
- package/workers/requirements.txt +8 -0
- package/workers/speakeasy_compat.py +175 -0
- package/workers/static_worker.py +5183 -0
- package/workers/yara_rules/default.yar +33 -0
- package/workers/yara_rules/malware_families.yar +93 -0
- package/workers/yara_rules/packers.yar +80 -0
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCodeFunctionRenamePrepareHandler } from './code-function-rename-prepare.js';
|
|
3
|
+
import { createCodeFunctionRenameApplyHandler } from './code-function-rename-apply.js';
|
|
4
|
+
import { createCodeFunctionsReconstructHandler } from './code-functions-reconstruct.js';
|
|
5
|
+
const TOOL_NAME = 'code.function.rename.review';
|
|
6
|
+
const ReviewSuggestionSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
address_or_function: z.string().optional(),
|
|
9
|
+
address: z.string().optional(),
|
|
10
|
+
function: z.string().optional(),
|
|
11
|
+
candidate_name: z.string().min(1).max(160),
|
|
12
|
+
confidence: z.number().min(0).max(1),
|
|
13
|
+
why: z.string().min(1).max(1000),
|
|
14
|
+
required_assumptions: z.array(z.string()).optional().default([]),
|
|
15
|
+
evidence_used: z.array(z.string()).optional().default([]),
|
|
16
|
+
})
|
|
17
|
+
.refine((value) => Boolean(value.address_or_function?.trim()) ||
|
|
18
|
+
Boolean(value.address?.trim()) ||
|
|
19
|
+
Boolean(value.function?.trim()), {
|
|
20
|
+
message: 'Each suggestion must provide address_or_function, address, or function.',
|
|
21
|
+
});
|
|
22
|
+
const ReviewSuggestionPayloadSchema = z.object({
|
|
23
|
+
suggestions: z.array(ReviewSuggestionSchema).min(1),
|
|
24
|
+
});
|
|
25
|
+
export const codeFunctionRenameReviewInputSchema = z.object({
|
|
26
|
+
sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
|
|
27
|
+
address: z.string().optional().describe('Optional specific function address'),
|
|
28
|
+
symbol: z.string().optional().describe('Optional specific function symbol'),
|
|
29
|
+
topk: z
|
|
30
|
+
.number()
|
|
31
|
+
.int()
|
|
32
|
+
.min(1)
|
|
33
|
+
.max(20)
|
|
34
|
+
.default(6)
|
|
35
|
+
.describe('When address/symbol not provided, review up to top-K reconstructed functions'),
|
|
36
|
+
max_functions: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(1)
|
|
40
|
+
.max(20)
|
|
41
|
+
.default(6)
|
|
42
|
+
.describe('Maximum number of functions included in the review bundle'),
|
|
43
|
+
include_resolved: z
|
|
44
|
+
.boolean()
|
|
45
|
+
.default(false)
|
|
46
|
+
.describe('Include functions that already have validated names in the initial review request'),
|
|
47
|
+
auto_include_resolved_on_empty: z
|
|
48
|
+
.boolean()
|
|
49
|
+
.default(true)
|
|
50
|
+
.describe('When unresolved selection is empty, automatically retry in audit mode with include_resolved=true'),
|
|
51
|
+
analysis_goal: z
|
|
52
|
+
.string()
|
|
53
|
+
.min(1)
|
|
54
|
+
.max(400)
|
|
55
|
+
.default('Reverse-engineer the prepared functions and propose precise human-readable semantic names.')
|
|
56
|
+
.describe('Human-readable analysis goal injected into the MCP prompt and sampling request'),
|
|
57
|
+
session_tag: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe('Optional semantic naming session tag used for artifact grouping'),
|
|
61
|
+
evidence_scope: z
|
|
62
|
+
.enum(['all', 'latest', 'session'])
|
|
63
|
+
.default('all')
|
|
64
|
+
.describe('Runtime evidence scope forwarded to prepare and reconstruct passes'),
|
|
65
|
+
evidence_session_tag: z
|
|
66
|
+
.string()
|
|
67
|
+
.optional()
|
|
68
|
+
.describe('Optional runtime evidence session selector used when evidence_scope=session or to narrow all/latest results'),
|
|
69
|
+
semantic_scope: z
|
|
70
|
+
.enum(['all', 'latest', 'session'])
|
|
71
|
+
.default('all')
|
|
72
|
+
.describe('Semantic naming artifact scope used for prepare and rerun reconstruct passes'),
|
|
73
|
+
semantic_session_tag: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.describe('Optional semantic naming session selector used when semantic_scope=session or to narrow all/latest results'),
|
|
77
|
+
persist_artifact: z
|
|
78
|
+
.boolean()
|
|
79
|
+
.default(true)
|
|
80
|
+
.describe('Persist the prepare bundle artifact before requesting external semantic review'),
|
|
81
|
+
auto_apply: z
|
|
82
|
+
.boolean()
|
|
83
|
+
.default(true)
|
|
84
|
+
.describe('Persist accepted suggestions automatically via code.function.rename.apply'),
|
|
85
|
+
rerun_reconstruct: z
|
|
86
|
+
.boolean()
|
|
87
|
+
.default(true)
|
|
88
|
+
.describe('Rerun code.functions.reconstruct after apply to materialize llm/hybrid validated names'),
|
|
89
|
+
temperature: z
|
|
90
|
+
.number()
|
|
91
|
+
.min(0)
|
|
92
|
+
.max(1)
|
|
93
|
+
.default(0.2)
|
|
94
|
+
.describe('Sampling temperature passed to the connected MCP client'),
|
|
95
|
+
max_tokens: z
|
|
96
|
+
.number()
|
|
97
|
+
.int()
|
|
98
|
+
.min(200)
|
|
99
|
+
.max(8000)
|
|
100
|
+
.default(1800)
|
|
101
|
+
.describe('Maximum sampling tokens requested from the connected MCP client'),
|
|
102
|
+
include_context: z
|
|
103
|
+
.enum(['none', 'thisServer', 'allServers'])
|
|
104
|
+
.default('none')
|
|
105
|
+
.describe('Requested MCP sampling context scope; clients may ignore this preference'),
|
|
106
|
+
model_hint: z
|
|
107
|
+
.string()
|
|
108
|
+
.min(1)
|
|
109
|
+
.max(120)
|
|
110
|
+
.optional()
|
|
111
|
+
.describe('Optional advisory model-family hint for client-mediated MCP sampling'),
|
|
112
|
+
cost_priority: z
|
|
113
|
+
.number()
|
|
114
|
+
.min(0)
|
|
115
|
+
.max(1)
|
|
116
|
+
.default(0.1)
|
|
117
|
+
.describe('Advisory model selection preference for sampling cost'),
|
|
118
|
+
speed_priority: z
|
|
119
|
+
.number()
|
|
120
|
+
.min(0)
|
|
121
|
+
.max(1)
|
|
122
|
+
.default(0.2)
|
|
123
|
+
.describe('Advisory model selection preference for sampling latency'),
|
|
124
|
+
intelligence_priority: z
|
|
125
|
+
.number()
|
|
126
|
+
.min(0)
|
|
127
|
+
.max(1)
|
|
128
|
+
.default(0.95)
|
|
129
|
+
.describe('Advisory model selection preference for reasoning quality'),
|
|
130
|
+
system_prompt: z
|
|
131
|
+
.string()
|
|
132
|
+
.min(1)
|
|
133
|
+
.max(800)
|
|
134
|
+
.optional()
|
|
135
|
+
.describe('Optional extra system prompt for the client-mediated semantic naming review'),
|
|
136
|
+
})
|
|
137
|
+
.refine((value) => value.evidence_scope !== 'session' || Boolean(value.evidence_session_tag?.trim()), {
|
|
138
|
+
message: 'evidence_session_tag is required when evidence_scope=session',
|
|
139
|
+
path: ['evidence_session_tag'],
|
|
140
|
+
})
|
|
141
|
+
.refine((value) => value.semantic_scope !== 'session' || Boolean(value.semantic_session_tag?.trim()), {
|
|
142
|
+
message: 'semantic_session_tag is required when semantic_scope=session',
|
|
143
|
+
path: ['semantic_session_tag'],
|
|
144
|
+
});
|
|
145
|
+
export const codeFunctionRenameReviewOutputSchema = z.object({
|
|
146
|
+
ok: z.boolean(),
|
|
147
|
+
data: z
|
|
148
|
+
.object({
|
|
149
|
+
sample_id: z.string(),
|
|
150
|
+
review_status: z.enum([
|
|
151
|
+
'sampled_and_applied',
|
|
152
|
+
'sampled_only',
|
|
153
|
+
'prompt_contract_only',
|
|
154
|
+
'no_targets',
|
|
155
|
+
'sampling_parse_failed',
|
|
156
|
+
]),
|
|
157
|
+
prompt_name: z.literal('reverse.semantic_name_review'),
|
|
158
|
+
prompt_arguments: z.object({
|
|
159
|
+
analysis_goal: z.string(),
|
|
160
|
+
prepared_bundle_json: z.string(),
|
|
161
|
+
}),
|
|
162
|
+
task_prompt: z.string(),
|
|
163
|
+
client: z.object({
|
|
164
|
+
name: z.string().nullable(),
|
|
165
|
+
version: z.string().nullable(),
|
|
166
|
+
sampling_available: z.boolean(),
|
|
167
|
+
}),
|
|
168
|
+
prepare: z.object({
|
|
169
|
+
prepared_count: z.number().int().nonnegative(),
|
|
170
|
+
unresolved_count: z.number().int().nonnegative(),
|
|
171
|
+
include_resolved: z.boolean(),
|
|
172
|
+
artifact_id: z.string().nullable(),
|
|
173
|
+
}),
|
|
174
|
+
sampling: z.object({
|
|
175
|
+
attempted: z.boolean(),
|
|
176
|
+
model: z.string().nullable(),
|
|
177
|
+
stop_reason: z.string().nullable(),
|
|
178
|
+
response_text: z.string().nullable(),
|
|
179
|
+
parsed_suggestion_count: z.number().int().nonnegative(),
|
|
180
|
+
}),
|
|
181
|
+
apply: z.object({
|
|
182
|
+
attempted: z.boolean(),
|
|
183
|
+
accepted_count: z.number().int().nonnegative(),
|
|
184
|
+
rejected_count: z.number().int().nonnegative(),
|
|
185
|
+
artifact_id: z.string().nullable(),
|
|
186
|
+
}),
|
|
187
|
+
reconstruct: z.object({
|
|
188
|
+
attempted: z.boolean(),
|
|
189
|
+
reconstructed_count: z.number().int().nonnegative(),
|
|
190
|
+
llm_or_hybrid_count: z.number().int().nonnegative(),
|
|
191
|
+
functions: z.array(z.object({
|
|
192
|
+
function: z.string(),
|
|
193
|
+
address: z.string(),
|
|
194
|
+
validated_name: z.string().nullable(),
|
|
195
|
+
resolution_source: z.string().nullable(),
|
|
196
|
+
})),
|
|
197
|
+
}),
|
|
198
|
+
confidence_policy: z.object({
|
|
199
|
+
calibrated: z.boolean(),
|
|
200
|
+
rule_priority_over_llm: z.boolean(),
|
|
201
|
+
llm_acceptance_threshold: z.number().min(0).max(1),
|
|
202
|
+
meaning: z.string(),
|
|
203
|
+
}),
|
|
204
|
+
next_steps: z.array(z.string()),
|
|
205
|
+
})
|
|
206
|
+
.optional(),
|
|
207
|
+
warnings: z.array(z.string()).optional(),
|
|
208
|
+
errors: z.array(z.string()).optional(),
|
|
209
|
+
artifacts: z.array(z.any()).optional(),
|
|
210
|
+
metrics: z
|
|
211
|
+
.object({
|
|
212
|
+
elapsed_ms: z.number(),
|
|
213
|
+
tool: z.string(),
|
|
214
|
+
})
|
|
215
|
+
.optional(),
|
|
216
|
+
});
|
|
217
|
+
export const codeFunctionRenameReviewToolDefinition = {
|
|
218
|
+
name: TOOL_NAME,
|
|
219
|
+
description: 'Use MCP client-mediated sampling to request an external LLM semantic naming review, then optionally persist and materialize the resulting suggestions.',
|
|
220
|
+
inputSchema: codeFunctionRenameReviewInputSchema,
|
|
221
|
+
outputSchema: codeFunctionRenameReviewOutputSchema,
|
|
222
|
+
};
|
|
223
|
+
function extractTextBlocks(result) {
|
|
224
|
+
const blocks = Array.isArray(result.content) ? result.content : [result.content];
|
|
225
|
+
return blocks
|
|
226
|
+
.filter((block) => block?.type === 'text')
|
|
227
|
+
.map((block) => block.text || '')
|
|
228
|
+
.join('\n')
|
|
229
|
+
.trim();
|
|
230
|
+
}
|
|
231
|
+
function normalizeSuggestionIdentifier(suggestion) {
|
|
232
|
+
const normalizedAddress = suggestion.address?.trim();
|
|
233
|
+
const normalizedFunction = suggestion.function?.trim();
|
|
234
|
+
if (normalizedAddress || normalizedFunction) {
|
|
235
|
+
return {
|
|
236
|
+
address: normalizedAddress || undefined,
|
|
237
|
+
function: normalizedFunction || undefined,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const identifier = suggestion.address_or_function?.trim();
|
|
241
|
+
if (!identifier) {
|
|
242
|
+
return {};
|
|
243
|
+
}
|
|
244
|
+
if (/^(0x)?[0-9a-f]+$/i.test(identifier)) {
|
|
245
|
+
return { address: identifier };
|
|
246
|
+
}
|
|
247
|
+
return { function: identifier };
|
|
248
|
+
}
|
|
249
|
+
function extractJsonCandidates(rawText) {
|
|
250
|
+
const candidates = [];
|
|
251
|
+
const trimmed = rawText.trim();
|
|
252
|
+
if (trimmed.length > 0) {
|
|
253
|
+
candidates.push(trimmed);
|
|
254
|
+
}
|
|
255
|
+
const fencedMatch = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
256
|
+
if (fencedMatch?.[1]) {
|
|
257
|
+
candidates.push(fencedMatch[1].trim());
|
|
258
|
+
}
|
|
259
|
+
const firstBrace = trimmed.indexOf('{');
|
|
260
|
+
const lastBrace = trimmed.lastIndexOf('}');
|
|
261
|
+
if (firstBrace >= 0 && lastBrace > firstBrace) {
|
|
262
|
+
candidates.push(trimmed.slice(firstBrace, lastBrace + 1));
|
|
263
|
+
}
|
|
264
|
+
const firstBracket = trimmed.indexOf('[');
|
|
265
|
+
const lastBracket = trimmed.lastIndexOf(']');
|
|
266
|
+
if (firstBracket >= 0 && lastBracket > firstBracket) {
|
|
267
|
+
candidates.push(trimmed.slice(firstBracket, lastBracket + 1));
|
|
268
|
+
}
|
|
269
|
+
return Array.from(new Set(candidates.filter((item) => item.length > 0)));
|
|
270
|
+
}
|
|
271
|
+
function parseSamplingSuggestions(rawText) {
|
|
272
|
+
const candidates = extractJsonCandidates(rawText);
|
|
273
|
+
for (const candidate of candidates) {
|
|
274
|
+
try {
|
|
275
|
+
const parsed = JSON.parse(candidate);
|
|
276
|
+
if (Array.isArray(parsed)) {
|
|
277
|
+
return ReviewSuggestionPayloadSchema.parse({ suggestions: parsed }).suggestions;
|
|
278
|
+
}
|
|
279
|
+
return ReviewSuggestionPayloadSchema.parse(parsed).suggestions;
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
throw new Error('Sampling response could not be parsed as strict JSON suggestions. Return {"suggestions":[...]} only.');
|
|
286
|
+
}
|
|
287
|
+
async function runPrepare(prepareHandler, input, includeResolved) {
|
|
288
|
+
return prepareHandler({
|
|
289
|
+
sample_id: input.sample_id,
|
|
290
|
+
address: input.address,
|
|
291
|
+
symbol: input.symbol,
|
|
292
|
+
topk: input.topk,
|
|
293
|
+
max_functions: input.max_functions,
|
|
294
|
+
include_resolved: includeResolved,
|
|
295
|
+
analysis_goal: input.analysis_goal,
|
|
296
|
+
persist_artifact: input.persist_artifact,
|
|
297
|
+
session_tag: input.session_tag,
|
|
298
|
+
evidence_scope: input.evidence_scope,
|
|
299
|
+
evidence_session_tag: input.evidence_session_tag,
|
|
300
|
+
semantic_scope: input.semantic_scope,
|
|
301
|
+
semantic_session_tag: input.semantic_session_tag,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function buildSamplingRequest(input, taskPrompt) {
|
|
305
|
+
return {
|
|
306
|
+
messages: [
|
|
307
|
+
{
|
|
308
|
+
role: 'user',
|
|
309
|
+
content: {
|
|
310
|
+
type: 'text',
|
|
311
|
+
text: taskPrompt,
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
systemPrompt: input.system_prompt ||
|
|
316
|
+
'You are an evidence-grounded reverse-engineering assistant. Return strict JSON only.',
|
|
317
|
+
includeContext: input.include_context,
|
|
318
|
+
maxTokens: input.max_tokens,
|
|
319
|
+
temperature: input.temperature,
|
|
320
|
+
modelPreferences: {
|
|
321
|
+
hints: input.model_hint ? [{ name: input.model_hint }] : undefined,
|
|
322
|
+
costPriority: input.cost_priority,
|
|
323
|
+
speedPriority: input.speed_priority,
|
|
324
|
+
intelligencePriority: input.intelligence_priority,
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function buildNamingConfidencePolicy() {
|
|
329
|
+
return {
|
|
330
|
+
calibrated: false,
|
|
331
|
+
rule_priority_over_llm: true,
|
|
332
|
+
llm_acceptance_threshold: 0.62,
|
|
333
|
+
meaning: 'Naming confidence values are heuristic support scores. Rule-based names take priority, and pure LLM suggestions are promoted only when llm_confidence >= 0.62.',
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
export function createCodeFunctionRenameReviewHandler(workspaceManager, database, cacheManager, mcpServer, dependencies) {
|
|
337
|
+
const prepareHandler = dependencies?.prepareHandler ||
|
|
338
|
+
createCodeFunctionRenamePrepareHandler(workspaceManager, database, cacheManager);
|
|
339
|
+
const applyHandler = dependencies?.applyHandler ||
|
|
340
|
+
createCodeFunctionRenameApplyHandler(workspaceManager, database);
|
|
341
|
+
const reconstructHandler = dependencies?.reconstructHandler ||
|
|
342
|
+
createCodeFunctionsReconstructHandler(workspaceManager, database, cacheManager);
|
|
343
|
+
const samplingRequester = dependencies?.samplingRequester ||
|
|
344
|
+
(mcpServer ? (params) => mcpServer.createMessage(params) : undefined);
|
|
345
|
+
const clientCapabilitiesProvider = dependencies?.clientCapabilitiesProvider ||
|
|
346
|
+
(mcpServer ? () => mcpServer.getClientCapabilities() : undefined);
|
|
347
|
+
const clientVersionProvider = dependencies?.clientVersionProvider ||
|
|
348
|
+
(mcpServer ? () => mcpServer.getClientVersion() : undefined);
|
|
349
|
+
return async (args) => {
|
|
350
|
+
const startTime = Date.now();
|
|
351
|
+
const warnings = [];
|
|
352
|
+
const artifacts = [];
|
|
353
|
+
try {
|
|
354
|
+
const input = codeFunctionRenameReviewInputSchema.parse(args);
|
|
355
|
+
let usedIncludeResolved = input.include_resolved;
|
|
356
|
+
let prepareResult = await runPrepare(prepareHandler, input, usedIncludeResolved);
|
|
357
|
+
if (prepareResult.ok &&
|
|
358
|
+
(prepareResult.data?.prepared_count || 0) === 0 &&
|
|
359
|
+
!usedIncludeResolved &&
|
|
360
|
+
input.auto_include_resolved_on_empty) {
|
|
361
|
+
warnings.push('Initial unresolved-only review set was empty; automatically retried in audit mode with include_resolved=true.');
|
|
362
|
+
usedIncludeResolved = true;
|
|
363
|
+
prepareResult = await runPrepare(prepareHandler, input, usedIncludeResolved);
|
|
364
|
+
}
|
|
365
|
+
if (!prepareResult.ok) {
|
|
366
|
+
return {
|
|
367
|
+
ok: false,
|
|
368
|
+
errors: prepareResult.errors || ['code.function.rename.prepare failed'],
|
|
369
|
+
warnings: prepareResult.warnings,
|
|
370
|
+
artifacts: prepareResult.artifacts,
|
|
371
|
+
metrics: {
|
|
372
|
+
elapsed_ms: Date.now() - startTime,
|
|
373
|
+
tool: TOOL_NAME,
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
warnings.push(...(prepareResult.warnings || []));
|
|
378
|
+
artifacts.push(...(prepareResult.artifacts || []));
|
|
379
|
+
const prepareData = (prepareResult.data || {});
|
|
380
|
+
const preparedCount = Number(prepareData.prepared_count || 0);
|
|
381
|
+
const unresolvedCount = Number(prepareData.unresolved_count || 0);
|
|
382
|
+
const taskPrompt = String(prepareData.task_prompt || '');
|
|
383
|
+
const promptArguments = prepareData.prompt_arguments || {
|
|
384
|
+
analysis_goal: input.analysis_goal,
|
|
385
|
+
prepared_bundle_json: '',
|
|
386
|
+
};
|
|
387
|
+
const prepareArtifactId = prepareData.artifact?.id || (prepareResult.artifacts || [])[0]?.id || null;
|
|
388
|
+
const clientVersion = clientVersionProvider?.();
|
|
389
|
+
const clientCapabilities = clientCapabilitiesProvider?.();
|
|
390
|
+
const samplingAvailable = Boolean(clientCapabilities?.sampling && samplingRequester);
|
|
391
|
+
if (preparedCount === 0) {
|
|
392
|
+
return {
|
|
393
|
+
ok: true,
|
|
394
|
+
data: {
|
|
395
|
+
sample_id: input.sample_id,
|
|
396
|
+
review_status: 'no_targets',
|
|
397
|
+
prompt_name: 'reverse.semantic_name_review',
|
|
398
|
+
prompt_arguments: promptArguments,
|
|
399
|
+
task_prompt: taskPrompt,
|
|
400
|
+
client: {
|
|
401
|
+
name: clientVersion?.name || null,
|
|
402
|
+
version: clientVersion?.version || null,
|
|
403
|
+
sampling_available: samplingAvailable,
|
|
404
|
+
},
|
|
405
|
+
prepare: {
|
|
406
|
+
prepared_count: preparedCount,
|
|
407
|
+
unresolved_count: unresolvedCount,
|
|
408
|
+
include_resolved: usedIncludeResolved,
|
|
409
|
+
artifact_id: prepareArtifactId,
|
|
410
|
+
},
|
|
411
|
+
sampling: {
|
|
412
|
+
attempted: false,
|
|
413
|
+
model: null,
|
|
414
|
+
stop_reason: null,
|
|
415
|
+
response_text: null,
|
|
416
|
+
parsed_suggestion_count: 0,
|
|
417
|
+
},
|
|
418
|
+
apply: {
|
|
419
|
+
attempted: false,
|
|
420
|
+
accepted_count: 0,
|
|
421
|
+
rejected_count: 0,
|
|
422
|
+
artifact_id: null,
|
|
423
|
+
},
|
|
424
|
+
reconstruct: {
|
|
425
|
+
attempted: false,
|
|
426
|
+
reconstructed_count: 0,
|
|
427
|
+
llm_or_hybrid_count: 0,
|
|
428
|
+
functions: [],
|
|
429
|
+
},
|
|
430
|
+
confidence_policy: buildNamingConfidencePolicy(),
|
|
431
|
+
next_steps: [
|
|
432
|
+
'increase topk or max_functions',
|
|
433
|
+
'set include_resolved=true to audit existing rule-based names',
|
|
434
|
+
'target a specific address or symbol for review',
|
|
435
|
+
],
|
|
436
|
+
},
|
|
437
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
438
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
439
|
+
metrics: {
|
|
440
|
+
elapsed_ms: Date.now() - startTime,
|
|
441
|
+
tool: TOOL_NAME,
|
|
442
|
+
},
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
if (!samplingAvailable) {
|
|
446
|
+
warnings.push('Connected MCP client did not advertise sampling support; returning prompt contract only.');
|
|
447
|
+
return {
|
|
448
|
+
ok: true,
|
|
449
|
+
data: {
|
|
450
|
+
sample_id: input.sample_id,
|
|
451
|
+
review_status: 'prompt_contract_only',
|
|
452
|
+
prompt_name: 'reverse.semantic_name_review',
|
|
453
|
+
prompt_arguments: promptArguments,
|
|
454
|
+
task_prompt: taskPrompt,
|
|
455
|
+
client: {
|
|
456
|
+
name: clientVersion?.name || null,
|
|
457
|
+
version: clientVersion?.version || null,
|
|
458
|
+
sampling_available: false,
|
|
459
|
+
},
|
|
460
|
+
prepare: {
|
|
461
|
+
prepared_count: preparedCount,
|
|
462
|
+
unresolved_count: unresolvedCount,
|
|
463
|
+
include_resolved: usedIncludeResolved,
|
|
464
|
+
artifact_id: prepareArtifactId,
|
|
465
|
+
},
|
|
466
|
+
sampling: {
|
|
467
|
+
attempted: false,
|
|
468
|
+
model: null,
|
|
469
|
+
stop_reason: null,
|
|
470
|
+
response_text: null,
|
|
471
|
+
parsed_suggestion_count: 0,
|
|
472
|
+
},
|
|
473
|
+
apply: {
|
|
474
|
+
attempted: false,
|
|
475
|
+
accepted_count: 0,
|
|
476
|
+
rejected_count: 0,
|
|
477
|
+
artifact_id: null,
|
|
478
|
+
},
|
|
479
|
+
reconstruct: {
|
|
480
|
+
attempted: false,
|
|
481
|
+
reconstructed_count: 0,
|
|
482
|
+
llm_or_hybrid_count: 0,
|
|
483
|
+
functions: [],
|
|
484
|
+
},
|
|
485
|
+
confidence_policy: buildNamingConfidencePolicy(),
|
|
486
|
+
next_steps: [
|
|
487
|
+
'call prompts/get for reverse.semantic_name_review with the returned prompt arguments',
|
|
488
|
+
'send the prompt to any MCP-capable tool-calling LLM client that supports sampling or manual prompt execution',
|
|
489
|
+
'pass the JSON result to code.function.rename.apply',
|
|
490
|
+
],
|
|
491
|
+
},
|
|
492
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
493
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
494
|
+
metrics: {
|
|
495
|
+
elapsed_ms: Date.now() - startTime,
|
|
496
|
+
tool: TOOL_NAME,
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
const samplingResult = await samplingRequester(buildSamplingRequest(input, taskPrompt));
|
|
501
|
+
const responseText = extractTextBlocks(samplingResult);
|
|
502
|
+
const samplingModel = samplingResult?.model || null;
|
|
503
|
+
const stopReason = samplingResult?.stopReason || null;
|
|
504
|
+
let parsedSuggestions = [];
|
|
505
|
+
try {
|
|
506
|
+
parsedSuggestions = parseSamplingSuggestions(responseText);
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
warnings.push(error instanceof Error ? error.message : String(error));
|
|
510
|
+
return {
|
|
511
|
+
ok: true,
|
|
512
|
+
data: {
|
|
513
|
+
sample_id: input.sample_id,
|
|
514
|
+
review_status: 'sampling_parse_failed',
|
|
515
|
+
prompt_name: 'reverse.semantic_name_review',
|
|
516
|
+
prompt_arguments: promptArguments,
|
|
517
|
+
task_prompt: taskPrompt,
|
|
518
|
+
client: {
|
|
519
|
+
name: clientVersion?.name || null,
|
|
520
|
+
version: clientVersion?.version || null,
|
|
521
|
+
sampling_available: true,
|
|
522
|
+
},
|
|
523
|
+
prepare: {
|
|
524
|
+
prepared_count: preparedCount,
|
|
525
|
+
unresolved_count: unresolvedCount,
|
|
526
|
+
include_resolved: usedIncludeResolved,
|
|
527
|
+
artifact_id: prepareArtifactId,
|
|
528
|
+
},
|
|
529
|
+
sampling: {
|
|
530
|
+
attempted: true,
|
|
531
|
+
model: samplingModel,
|
|
532
|
+
stop_reason: stopReason,
|
|
533
|
+
response_text: responseText || null,
|
|
534
|
+
parsed_suggestion_count: 0,
|
|
535
|
+
},
|
|
536
|
+
apply: {
|
|
537
|
+
attempted: false,
|
|
538
|
+
accepted_count: 0,
|
|
539
|
+
rejected_count: 0,
|
|
540
|
+
artifact_id: null,
|
|
541
|
+
},
|
|
542
|
+
reconstruct: {
|
|
543
|
+
attempted: false,
|
|
544
|
+
reconstructed_count: 0,
|
|
545
|
+
llm_or_hybrid_count: 0,
|
|
546
|
+
functions: [],
|
|
547
|
+
},
|
|
548
|
+
confidence_policy: buildNamingConfidencePolicy(),
|
|
549
|
+
next_steps: [
|
|
550
|
+
'inspect the sampling response text and ensure the client returned strict JSON',
|
|
551
|
+
'rerun code.function.rename.review or use code.function.rename.apply manually with corrected JSON',
|
|
552
|
+
],
|
|
553
|
+
},
|
|
554
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
555
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
556
|
+
metrics: {
|
|
557
|
+
elapsed_ms: Date.now() - startTime,
|
|
558
|
+
tool: TOOL_NAME,
|
|
559
|
+
},
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
if (!input.auto_apply) {
|
|
563
|
+
return {
|
|
564
|
+
ok: true,
|
|
565
|
+
data: {
|
|
566
|
+
sample_id: input.sample_id,
|
|
567
|
+
review_status: 'sampled_only',
|
|
568
|
+
prompt_name: 'reverse.semantic_name_review',
|
|
569
|
+
prompt_arguments: promptArguments,
|
|
570
|
+
task_prompt: taskPrompt,
|
|
571
|
+
client: {
|
|
572
|
+
name: clientVersion?.name || null,
|
|
573
|
+
version: clientVersion?.version || null,
|
|
574
|
+
sampling_available: true,
|
|
575
|
+
},
|
|
576
|
+
prepare: {
|
|
577
|
+
prepared_count: preparedCount,
|
|
578
|
+
unresolved_count: unresolvedCount,
|
|
579
|
+
include_resolved: usedIncludeResolved,
|
|
580
|
+
artifact_id: prepareArtifactId,
|
|
581
|
+
},
|
|
582
|
+
sampling: {
|
|
583
|
+
attempted: true,
|
|
584
|
+
model: samplingModel,
|
|
585
|
+
stop_reason: stopReason,
|
|
586
|
+
response_text: responseText || null,
|
|
587
|
+
parsed_suggestion_count: parsedSuggestions.length,
|
|
588
|
+
},
|
|
589
|
+
apply: {
|
|
590
|
+
attempted: false,
|
|
591
|
+
accepted_count: 0,
|
|
592
|
+
rejected_count: 0,
|
|
593
|
+
artifact_id: null,
|
|
594
|
+
},
|
|
595
|
+
reconstruct: {
|
|
596
|
+
attempted: false,
|
|
597
|
+
reconstructed_count: 0,
|
|
598
|
+
llm_or_hybrid_count: 0,
|
|
599
|
+
functions: [],
|
|
600
|
+
},
|
|
601
|
+
confidence_policy: buildNamingConfidencePolicy(),
|
|
602
|
+
next_steps: [
|
|
603
|
+
'pass the parsed JSON payload to code.function.rename.apply',
|
|
604
|
+
'rerun code.functions.reconstruct or code.reconstruct.export after apply',
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
608
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
609
|
+
metrics: {
|
|
610
|
+
elapsed_ms: Date.now() - startTime,
|
|
611
|
+
tool: TOOL_NAME,
|
|
612
|
+
},
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
const applySuggestions = parsedSuggestions.map((suggestion) => ({
|
|
616
|
+
...normalizeSuggestionIdentifier(suggestion),
|
|
617
|
+
candidate_name: suggestion.candidate_name,
|
|
618
|
+
confidence: suggestion.confidence,
|
|
619
|
+
why: suggestion.why,
|
|
620
|
+
required_assumptions: suggestion.required_assumptions || [],
|
|
621
|
+
evidence_used: suggestion.evidence_used || [],
|
|
622
|
+
}));
|
|
623
|
+
const applyResult = await applyHandler({
|
|
624
|
+
sample_id: input.sample_id,
|
|
625
|
+
suggestions: applySuggestions,
|
|
626
|
+
client_name: clientVersion?.name,
|
|
627
|
+
model_name: samplingModel || undefined,
|
|
628
|
+
prepare_artifact_id: prepareArtifactId || undefined,
|
|
629
|
+
session_tag: input.session_tag,
|
|
630
|
+
});
|
|
631
|
+
if (!applyResult.ok) {
|
|
632
|
+
return {
|
|
633
|
+
ok: false,
|
|
634
|
+
errors: applyResult.errors || ['code.function.rename.apply failed'],
|
|
635
|
+
warnings: [...warnings, ...(applyResult.warnings || [])],
|
|
636
|
+
artifacts: [...artifacts, ...(applyResult.artifacts || [])],
|
|
637
|
+
metrics: {
|
|
638
|
+
elapsed_ms: Date.now() - startTime,
|
|
639
|
+
tool: TOOL_NAME,
|
|
640
|
+
},
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
warnings.push(...(applyResult.warnings || []));
|
|
644
|
+
artifacts.push(...(applyResult.artifacts || []));
|
|
645
|
+
const applyData = (applyResult.data || {});
|
|
646
|
+
let reconstructData = {
|
|
647
|
+
attempted: false,
|
|
648
|
+
reconstructed_count: 0,
|
|
649
|
+
llm_or_hybrid_count: 0,
|
|
650
|
+
functions: [],
|
|
651
|
+
};
|
|
652
|
+
if (input.rerun_reconstruct) {
|
|
653
|
+
const rerunSemanticScope = input.semantic_scope === 'all' && input.session_tag ? 'session' : input.semantic_scope;
|
|
654
|
+
const rerunSemanticSessionTag = input.semantic_session_tag || input.session_tag;
|
|
655
|
+
const reconstructResult = await reconstructHandler({
|
|
656
|
+
sample_id: input.sample_id,
|
|
657
|
+
address: input.address,
|
|
658
|
+
symbol: input.symbol,
|
|
659
|
+
topk: input.topk,
|
|
660
|
+
include_xrefs: true,
|
|
661
|
+
max_pseudocode_lines: 80,
|
|
662
|
+
max_assembly_lines: 60,
|
|
663
|
+
timeout: 45,
|
|
664
|
+
evidence_scope: input.evidence_scope,
|
|
665
|
+
evidence_session_tag: input.evidence_session_tag,
|
|
666
|
+
semantic_scope: rerunSemanticScope,
|
|
667
|
+
semantic_session_tag: rerunSemanticSessionTag,
|
|
668
|
+
});
|
|
669
|
+
if (!reconstructResult.ok) {
|
|
670
|
+
return {
|
|
671
|
+
ok: false,
|
|
672
|
+
errors: reconstructResult.errors || ['code.functions.reconstruct failed after semantic name apply'],
|
|
673
|
+
warnings: [...warnings, ...(reconstructResult.warnings || [])],
|
|
674
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
675
|
+
metrics: {
|
|
676
|
+
elapsed_ms: Date.now() - startTime,
|
|
677
|
+
tool: TOOL_NAME,
|
|
678
|
+
},
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
warnings.push(...(reconstructResult.warnings || []));
|
|
682
|
+
const reconstructedFunctions = (reconstructResult.data?.functions || []).map((item) => ({
|
|
683
|
+
function: item.function,
|
|
684
|
+
address: item.address,
|
|
685
|
+
validated_name: item?.name_resolution?.validated_name || null,
|
|
686
|
+
resolution_source: item?.name_resolution?.resolution_source || null,
|
|
687
|
+
}));
|
|
688
|
+
reconstructData = {
|
|
689
|
+
attempted: true,
|
|
690
|
+
reconstructed_count: Number(reconstructResult.data?.reconstructed_count || reconstructedFunctions.length),
|
|
691
|
+
llm_or_hybrid_count: reconstructedFunctions.filter((item) => item.resolution_source === 'llm' || item.resolution_source === 'hybrid').length,
|
|
692
|
+
functions: reconstructedFunctions,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
return {
|
|
696
|
+
ok: true,
|
|
697
|
+
data: {
|
|
698
|
+
sample_id: input.sample_id,
|
|
699
|
+
review_status: 'sampled_and_applied',
|
|
700
|
+
prompt_name: 'reverse.semantic_name_review',
|
|
701
|
+
prompt_arguments: promptArguments,
|
|
702
|
+
task_prompt: taskPrompt,
|
|
703
|
+
client: {
|
|
704
|
+
name: clientVersion?.name || null,
|
|
705
|
+
version: clientVersion?.version || null,
|
|
706
|
+
sampling_available: true,
|
|
707
|
+
},
|
|
708
|
+
prepare: {
|
|
709
|
+
prepared_count: preparedCount,
|
|
710
|
+
unresolved_count: unresolvedCount,
|
|
711
|
+
include_resolved: usedIncludeResolved,
|
|
712
|
+
artifact_id: prepareArtifactId,
|
|
713
|
+
},
|
|
714
|
+
sampling: {
|
|
715
|
+
attempted: true,
|
|
716
|
+
model: samplingModel,
|
|
717
|
+
stop_reason: stopReason,
|
|
718
|
+
response_text: responseText || null,
|
|
719
|
+
parsed_suggestion_count: parsedSuggestions.length,
|
|
720
|
+
},
|
|
721
|
+
apply: {
|
|
722
|
+
attempted: true,
|
|
723
|
+
accepted_count: Number(applyData.accepted_count || 0),
|
|
724
|
+
rejected_count: Number(applyData.rejected_count || 0),
|
|
725
|
+
artifact_id: applyData.artifact?.id || null,
|
|
726
|
+
},
|
|
727
|
+
reconstruct: reconstructData,
|
|
728
|
+
confidence_policy: buildNamingConfidencePolicy(),
|
|
729
|
+
next_steps: input.rerun_reconstruct
|
|
730
|
+
? [
|
|
731
|
+
'inspect reconstructed functions for llm or hybrid validated names',
|
|
732
|
+
'rerun code.reconstruct.export to propagate validated names into rewrite output',
|
|
733
|
+
]
|
|
734
|
+
: [
|
|
735
|
+
'rerun code.functions.reconstruct to materialize llm or hybrid validated names',
|
|
736
|
+
'rerun code.reconstruct.export after reconstruct if you want updated rewrite output',
|
|
737
|
+
],
|
|
738
|
+
},
|
|
739
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
740
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
741
|
+
metrics: {
|
|
742
|
+
elapsed_ms: Date.now() - startTime,
|
|
743
|
+
tool: TOOL_NAME,
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
catch (error) {
|
|
748
|
+
return {
|
|
749
|
+
ok: false,
|
|
750
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
751
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
752
|
+
artifacts: artifacts.length > 0 ? artifacts : undefined,
|
|
753
|
+
metrics: {
|
|
754
|
+
elapsed_ms: Date.now() - startTime,
|
|
755
|
+
tool: TOOL_NAME,
|
|
756
|
+
},
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
//# sourceMappingURL=code-function-rename-review.js.map
|