windows-exe-decompiler-mcp-server 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE_INSTALLATION.md +129 -0
- package/CODEX_INSTALLATION.md +25 -1
- package/COPILOT_INSTALLATION.md +29 -1
- package/LICENSE +21 -21
- package/README.md +232 -110
- package/dist/analysis-provenance.d.ts +50 -2
- package/dist/analysis-provenance.js +1 -0
- package/dist/analysis-task-runner.js +92 -0
- package/dist/config.d.ts +35 -16
- package/dist/config.js +37 -3
- package/dist/database.js +115 -115
- package/dist/decompiler-worker.d.ts +10 -5
- package/dist/decompiler-worker.js +240 -58
- package/dist/dynamic-trace.d.ts +6 -0
- package/dist/dynamic-trace.js +52 -1
- package/dist/ghidra-config.js +17 -1
- package/dist/index.js +38 -8
- package/dist/pe-runtime-functions.d.ts +90 -0
- package/dist/pe-runtime-functions.js +452 -0
- package/dist/prompts/module-reconstruction-review.d.ts +5 -0
- package/dist/prompts/module-reconstruction-review.js +65 -0
- package/dist/runtime-correlation.d.ts +5 -0
- package/dist/runtime-correlation.js +179 -2
- package/dist/sample-workspace.d.ts +28 -0
- package/dist/sample-workspace.js +186 -0
- package/dist/semantic-name-suggestion-artifacts.d.ts +56 -0
- package/dist/semantic-name-suggestion-artifacts.js +87 -0
- package/dist/server.js +1 -1
- package/dist/setup-guidance.d.ts +73 -0
- package/dist/setup-guidance.js +211 -0
- package/dist/tools/artifact-read.d.ts +10 -10
- package/dist/tools/artifacts-diff.d.ts +8 -8
- package/dist/tools/artifacts-list.d.ts +16 -16
- package/dist/tools/attack-map.d.ts +8 -8
- package/dist/tools/binary-role-profile.d.ts +1197 -0
- package/dist/tools/binary-role-profile.js +575 -0
- package/dist/tools/code-function-explain-apply.d.ts +12 -12
- package/dist/tools/code-function-explain-prepare.d.ts +12 -12
- package/dist/tools/code-function-explain-review.d.ts +58 -58
- package/dist/tools/code-function-rename-apply.d.ts +12 -12
- package/dist/tools/code-function-rename-prepare.d.ts +14 -14
- package/dist/tools/code-function-rename-review.d.ts +66 -66
- package/dist/tools/code-functions-define.d.ts +337 -0
- package/dist/tools/code-functions-define.js +337 -0
- package/dist/tools/code-functions-list.js +1 -1
- package/dist/tools/code-functions-rank.js +1 -1
- package/dist/tools/code-functions-reconstruct.d.ts +368 -58
- package/dist/tools/code-functions-reconstruct.js +130 -10
- package/dist/tools/code-functions-smart-recover.d.ts +352 -0
- package/dist/tools/code-functions-smart-recover.js +190 -0
- package/dist/tools/code-module-review-apply.d.ts +233 -0
- package/dist/tools/code-module-review-apply.js +209 -0
- package/dist/tools/code-module-review-prepare.d.ts +756 -0
- package/dist/tools/code-module-review-prepare.js +343 -0
- package/dist/tools/code-module-review.d.ts +474 -0
- package/dist/tools/code-module-review.js +566 -0
- package/dist/tools/code-reconstruct-export.d.ts +193 -21
- package/dist/tools/code-reconstruct-export.js +578 -21
- package/dist/tools/code-reconstruct-plan.d.ts +20 -20
- package/dist/tools/com-role-profile.d.ts +353 -0
- package/dist/tools/com-role-profile.js +186 -0
- package/dist/tools/dll-export-profile.d.ts +625 -0
- package/dist/tools/dll-export-profile.js +230 -0
- package/dist/tools/dotnet-metadata-extract.d.ts +122 -122
- package/dist/tools/dotnet-reconstruct-export.d.ts +49 -49
- package/dist/tools/dotnet-types-list.d.ts +66 -66
- package/dist/tools/dynamic-dependencies.d.ts +144 -8
- package/dist/tools/dynamic-dependencies.js +20 -1
- package/dist/tools/dynamic-memory-import.js +105 -2
- package/dist/tools/ghidra-analyze.d.ts +20 -0
- package/dist/tools/ghidra-analyze.js +10 -2
- package/dist/tools/ghidra-health.d.ts +177 -0
- package/dist/tools/ghidra-health.js +28 -0
- package/dist/tools/ioc-export.d.ts +8 -8
- package/dist/tools/packer-detect.d.ts +14 -14
- package/dist/tools/packer-detect.js +6 -9
- package/dist/tools/pe-exports-extract.d.ts +8 -8
- package/dist/tools/pe-exports-extract.js +6 -9
- package/dist/tools/pe-fingerprint.d.ts +36 -36
- package/dist/tools/pe-imports-extract.d.ts +8 -8
- package/dist/tools/pe-imports-extract.js +6 -9
- package/dist/tools/pe-pdata-extract.d.ts +448 -0
- package/dist/tools/pe-pdata-extract.js +219 -0
- package/dist/tools/pe-symbols-recover.d.ts +227 -0
- package/dist/tools/pe-symbols-recover.js +316 -0
- package/dist/tools/report-generate.d.ts +15 -1
- package/dist/tools/report-generate.js +139 -16
- package/dist/tools/report-summarize.d.ts +2242 -8
- package/dist/tools/report-summarize.js +246 -10
- package/dist/tools/runtime-detect.d.ts +8 -8
- package/dist/tools/runtime-detect.js +2 -12
- package/dist/tools/rust-binary-analyze.d.ts +2047 -0
- package/dist/tools/rust-binary-analyze.js +443 -0
- package/dist/tools/sample-profile-get.d.ts +135 -16
- package/dist/tools/sample-profile-get.js +35 -32
- package/dist/tools/sandbox-execute.d.ts +10 -10
- package/dist/tools/strings-extract.d.ts +8 -8
- package/dist/tools/strings-extract.js +2 -12
- package/dist/tools/strings-floss-decode.d.ts +8 -8
- package/dist/tools/system-health.d.ts +172 -36
- package/dist/tools/system-health.js +14 -0
- package/dist/tools/system-setup-guide.d.ts +179 -0
- package/dist/tools/system-setup-guide.js +62 -0
- package/dist/tools/tool-help.d.ts +16 -16
- package/dist/tools/tool-help.js +172 -0
- package/dist/tools/yara-scan.d.ts +8 -8
- package/dist/types.d.ts +2 -0
- package/dist/workflows/function-explanation-review.d.ts +3034 -76
- package/dist/workflows/function-explanation-review.js +172 -42
- package/dist/workflows/function-index-recover.d.ts +333 -0
- package/dist/workflows/function-index-recover.js +291 -0
- package/dist/workflows/module-reconstruction-review.d.ts +3537 -0
- package/dist/workflows/module-reconstruction-review.js +354 -0
- package/dist/workflows/reconstruct.d.ts +2182 -223
- package/dist/workflows/reconstruct.js +575 -32
- package/dist/workflows/semantic-name-review.d.ts +1436 -85
- package/dist/workflows/semantic-name-review.js +150 -58
- package/dist/workflows/triage.d.ts +8 -8
- package/ghidra_scripts/DecompileFunction.java +487 -487
- package/ghidra_scripts/ExtractCFG.java +256 -256
- package/ghidra_scripts/ExtractFunctions.java +442 -442
- package/ghidra_scripts/README.md +112 -112
- package/ghidra_scripts/SearchFunctionReferences.java +380 -380
- package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -9
- package/helpers/DotNetMetadataProbe/Program.cs +566 -566
- package/install-to-claude.ps1 +432 -0
- package/install-to-codex.ps1 +256 -178
- package/install-to-copilot.ps1 +389 -303
- package/package.json +4 -2
- package/requirements.txt +9 -9
- package/workers/requirements-dynamic.txt +11 -11
- package/workers/requirements.txt +8 -8
- package/workers/speakeasy_compat.py +175 -175
- package/workers/static_worker.py +3474 -3474
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createCodeFunctionsSmartRecoverHandler } from '../tools/code-functions-smart-recover.js';
|
|
3
|
+
import { createPESymbolsRecoverHandler } from '../tools/pe-symbols-recover.js';
|
|
4
|
+
import { createCodeFunctionsDefineHandler } from '../tools/code-functions-define.js';
|
|
5
|
+
import { DecompilerWorker } from '../decompiler-worker.js';
|
|
6
|
+
const TOOL_NAME = 'workflow.function_index_recover';
|
|
7
|
+
export const FunctionIndexRecoverWorkflowInputSchema = z.object({
|
|
8
|
+
sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
|
|
9
|
+
define_from: z
|
|
10
|
+
.enum(['auto', 'smart_recover', 'symbols_recover'])
|
|
11
|
+
.default('auto')
|
|
12
|
+
.describe('Which recovered source should be materialized into the function index'),
|
|
13
|
+
max_string_hints: z
|
|
14
|
+
.number()
|
|
15
|
+
.int()
|
|
16
|
+
.min(20)
|
|
17
|
+
.max(400)
|
|
18
|
+
.default(120)
|
|
19
|
+
.describe('Maximum strings inspected when pe.symbols.recover derives recovered names'),
|
|
20
|
+
replace_all: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.default(true)
|
|
23
|
+
.describe('Replace the existing function index before importing recovered boundaries'),
|
|
24
|
+
persist_artifact: z
|
|
25
|
+
.boolean()
|
|
26
|
+
.default(true)
|
|
27
|
+
.describe('Persist the materialized function-definition artifact'),
|
|
28
|
+
register_analysis: z
|
|
29
|
+
.boolean()
|
|
30
|
+
.default(true)
|
|
31
|
+
.describe('Insert a completed function_definition analysis row for the imported index'),
|
|
32
|
+
session_tag: z
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe('Optional session tag used when persisting recovered function-definition artifacts'),
|
|
36
|
+
include_rank_preview: z
|
|
37
|
+
.boolean()
|
|
38
|
+
.default(true)
|
|
39
|
+
.describe('Return a ranked preview after the recovered function index has been materialized'),
|
|
40
|
+
rank_topk: z
|
|
41
|
+
.number()
|
|
42
|
+
.int()
|
|
43
|
+
.min(1)
|
|
44
|
+
.max(40)
|
|
45
|
+
.default(12)
|
|
46
|
+
.describe('Number of ranked functions returned when include_rank_preview=true'),
|
|
47
|
+
force_refresh: z
|
|
48
|
+
.boolean()
|
|
49
|
+
.default(false)
|
|
50
|
+
.describe('Bypass cache in smart_recover and symbols_recover'),
|
|
51
|
+
});
|
|
52
|
+
const RankPreviewSchema = z.object({
|
|
53
|
+
address: z.string(),
|
|
54
|
+
name: z.string().nullable().optional(),
|
|
55
|
+
score: z.number().nullable().optional(),
|
|
56
|
+
tags: z.array(z.string()).optional(),
|
|
57
|
+
summary: z.string().nullable().optional(),
|
|
58
|
+
});
|
|
59
|
+
export const FunctionIndexRecoverWorkflowOutputSchema = z.object({
|
|
60
|
+
ok: z.boolean(),
|
|
61
|
+
data: z
|
|
62
|
+
.object({
|
|
63
|
+
sample_id: z.string(),
|
|
64
|
+
define_from: z.enum(['smart_recover', 'symbols_recover']),
|
|
65
|
+
recovered_function_count: z.number().int().nonnegative(),
|
|
66
|
+
recovered_symbol_count: z.number().int().nonnegative(),
|
|
67
|
+
imported_count: z.number().int().nonnegative(),
|
|
68
|
+
function_index_status: z.enum(['ready']),
|
|
69
|
+
decompile_status: z.enum(['missing']),
|
|
70
|
+
cfg_status: z.enum(['missing']),
|
|
71
|
+
recovery_strategy: z.array(z.string()),
|
|
72
|
+
imported_artifact: z
|
|
73
|
+
.object({
|
|
74
|
+
id: z.string(),
|
|
75
|
+
type: z.string(),
|
|
76
|
+
path: z.string(),
|
|
77
|
+
sha256: z.string(),
|
|
78
|
+
mime: z.string().optional(),
|
|
79
|
+
})
|
|
80
|
+
.optional(),
|
|
81
|
+
analysis_id: z.string().optional(),
|
|
82
|
+
imported_function_preview: z.array(z.object({
|
|
83
|
+
address: z.string(),
|
|
84
|
+
rva: z.number().nullable(),
|
|
85
|
+
size: z.number().nullable(),
|
|
86
|
+
name: z.string(),
|
|
87
|
+
is_entry_point: z.boolean(),
|
|
88
|
+
is_exported: z.boolean(),
|
|
89
|
+
})),
|
|
90
|
+
recovered_symbol_preview: z.array(z.object({
|
|
91
|
+
address: z.string(),
|
|
92
|
+
recovered_name: z.string(),
|
|
93
|
+
name_strategy: z.string(),
|
|
94
|
+
confidence: z.number(),
|
|
95
|
+
})),
|
|
96
|
+
rank_preview: z.array(RankPreviewSchema).optional(),
|
|
97
|
+
next_steps: z.array(z.string()),
|
|
98
|
+
})
|
|
99
|
+
.optional(),
|
|
100
|
+
warnings: z.array(z.string()).optional(),
|
|
101
|
+
errors: z.array(z.string()).optional(),
|
|
102
|
+
artifacts: z.array(z.any()).optional(),
|
|
103
|
+
metrics: z
|
|
104
|
+
.object({
|
|
105
|
+
elapsed_ms: z.number(),
|
|
106
|
+
tool: z.string(),
|
|
107
|
+
})
|
|
108
|
+
.optional(),
|
|
109
|
+
});
|
|
110
|
+
export const functionIndexRecoverWorkflowToolDefinition = {
|
|
111
|
+
name: TOOL_NAME,
|
|
112
|
+
description: 'Recover a non-Ghidra function index by chaining code.functions.smart_recover, pe.symbols.recover, and code.functions.define, then optionally return a ranked preview.',
|
|
113
|
+
inputSchema: FunctionIndexRecoverWorkflowInputSchema,
|
|
114
|
+
outputSchema: FunctionIndexRecoverWorkflowOutputSchema,
|
|
115
|
+
};
|
|
116
|
+
function normalizeRankPreview(items) {
|
|
117
|
+
return items.map((item) => ({
|
|
118
|
+
address: String(item.address),
|
|
119
|
+
name: item.name ? String(item.name) : null,
|
|
120
|
+
score: typeof item.score === 'number' ? item.score : null,
|
|
121
|
+
tags: Array.isArray(item.tags)
|
|
122
|
+
? item.tags.map((entry) => String(entry))
|
|
123
|
+
: undefined,
|
|
124
|
+
summary: item.summary ? String(item.summary) : null,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
export function createFunctionIndexRecoverWorkflowHandler(workspaceManager, database, cacheManager, dependencies = {}) {
|
|
128
|
+
const smartRecoverHandler = dependencies.smartRecoverHandler ||
|
|
129
|
+
createCodeFunctionsSmartRecoverHandler(workspaceManager, database, cacheManager);
|
|
130
|
+
const symbolsRecoverHandler = dependencies.symbolsRecoverHandler ||
|
|
131
|
+
createPESymbolsRecoverHandler(workspaceManager, database, cacheManager);
|
|
132
|
+
const defineHandler = dependencies.defineHandler || createCodeFunctionsDefineHandler(workspaceManager, database);
|
|
133
|
+
return async (args) => {
|
|
134
|
+
const startTime = Date.now();
|
|
135
|
+
try {
|
|
136
|
+
const input = FunctionIndexRecoverWorkflowInputSchema.parse(args);
|
|
137
|
+
const sample = database.findSample(input.sample_id);
|
|
138
|
+
if (!sample) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
errors: [`Sample not found: ${input.sample_id}`],
|
|
142
|
+
metrics: {
|
|
143
|
+
elapsed_ms: Date.now() - startTime,
|
|
144
|
+
tool: TOOL_NAME,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const warnings = [];
|
|
149
|
+
const [smartRecoverResult, symbolsRecoverResult] = await Promise.all([
|
|
150
|
+
smartRecoverHandler({
|
|
151
|
+
sample_id: input.sample_id,
|
|
152
|
+
force_refresh: input.force_refresh,
|
|
153
|
+
}),
|
|
154
|
+
symbolsRecoverHandler({
|
|
155
|
+
sample_id: input.sample_id,
|
|
156
|
+
max_string_hints: input.max_string_hints,
|
|
157
|
+
force_refresh: input.force_refresh,
|
|
158
|
+
}),
|
|
159
|
+
]);
|
|
160
|
+
if (!smartRecoverResult.ok || !smartRecoverResult.data) {
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
errors: [
|
|
164
|
+
`code.functions.smart_recover failed: ${(smartRecoverResult.errors || ['unknown error']).join('; ')}`,
|
|
165
|
+
],
|
|
166
|
+
warnings: [
|
|
167
|
+
...(smartRecoverResult.warnings || []),
|
|
168
|
+
...(symbolsRecoverResult.warnings || []),
|
|
169
|
+
],
|
|
170
|
+
metrics: {
|
|
171
|
+
elapsed_ms: Date.now() - startTime,
|
|
172
|
+
tool: TOOL_NAME,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const smartRecoverData = smartRecoverResult.data;
|
|
177
|
+
const symbolsRecoverData = symbolsRecoverResult.ok && symbolsRecoverResult.data
|
|
178
|
+
? symbolsRecoverResult.data
|
|
179
|
+
: undefined;
|
|
180
|
+
if (!symbolsRecoverResult.ok) {
|
|
181
|
+
warnings.push(`pe.symbols.recover unavailable: ${(symbolsRecoverResult.errors || ['unknown error']).join('; ')}`);
|
|
182
|
+
}
|
|
183
|
+
warnings.push(...(smartRecoverResult.warnings || []));
|
|
184
|
+
warnings.push(...(symbolsRecoverResult.warnings || []));
|
|
185
|
+
const symbolByAddress = new Map((symbolsRecoverData?.symbols || []).map((item) => [item.address.toLowerCase(), item]));
|
|
186
|
+
const symbolByRva = new Map((symbolsRecoverData?.symbols || []).map((item) => [item.rva, item]));
|
|
187
|
+
const defineFrom = input.define_from === 'auto'
|
|
188
|
+
? symbolsRecoverData && symbolsRecoverData.count > 0
|
|
189
|
+
? 'symbols_recover'
|
|
190
|
+
: 'smart_recover'
|
|
191
|
+
: input.define_from;
|
|
192
|
+
const definitions = smartRecoverData.functions.map((item) => {
|
|
193
|
+
const symbol = symbolByAddress.get(item.address.toLowerCase()) ||
|
|
194
|
+
symbolByRva.get(item.rva);
|
|
195
|
+
const useRecoveredName = defineFrom === 'symbols_recover' && symbol;
|
|
196
|
+
return {
|
|
197
|
+
address: item.address,
|
|
198
|
+
rva: item.rva,
|
|
199
|
+
size: item.size,
|
|
200
|
+
name: useRecoveredName ? symbol.recovered_name : item.name,
|
|
201
|
+
recovered_name: symbol?.recovered_name,
|
|
202
|
+
is_entry_point: item.is_entry_point,
|
|
203
|
+
is_exported: item.is_exported,
|
|
204
|
+
evidence: Array.from(new Set([...(item.evidence || []), ...(symbol?.evidence || [])])),
|
|
205
|
+
tags: Array.from(new Set([
|
|
206
|
+
`recovery:${item.name}`,
|
|
207
|
+
...(symbol ? [`symbol_strategy:${symbol.name_strategy}`] : []),
|
|
208
|
+
useRecoveredName ? 'name_source:recovered_symbol' : 'name_source:smart_recover',
|
|
209
|
+
])),
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
const defineResult = await defineHandler({
|
|
213
|
+
sample_id: input.sample_id,
|
|
214
|
+
definitions,
|
|
215
|
+
source: defineFrom,
|
|
216
|
+
replace_all: input.replace_all,
|
|
217
|
+
persist_artifact: input.persist_artifact,
|
|
218
|
+
register_analysis: input.register_analysis,
|
|
219
|
+
session_tag: input.session_tag,
|
|
220
|
+
});
|
|
221
|
+
if (!defineResult.ok || !defineResult.data) {
|
|
222
|
+
return {
|
|
223
|
+
ok: false,
|
|
224
|
+
errors: [
|
|
225
|
+
`code.functions.define failed: ${(defineResult.errors || ['unknown error']).join('; ')}`,
|
|
226
|
+
],
|
|
227
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
228
|
+
metrics: {
|
|
229
|
+
elapsed_ms: Date.now() - startTime,
|
|
230
|
+
tool: TOOL_NAME,
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const defineData = defineResult.data;
|
|
235
|
+
let rankPreview;
|
|
236
|
+
if (input.include_rank_preview) {
|
|
237
|
+
const decompilerWorker = new DecompilerWorker(database, workspaceManager);
|
|
238
|
+
const ranked = await decompilerWorker.rankFunctions(input.sample_id, input.rank_topk);
|
|
239
|
+
rankPreview = normalizeRankPreview(ranked);
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
ok: true,
|
|
243
|
+
data: {
|
|
244
|
+
sample_id: input.sample_id,
|
|
245
|
+
define_from: defineFrom,
|
|
246
|
+
recovered_function_count: smartRecoverData.count,
|
|
247
|
+
recovered_symbol_count: symbolsRecoverData?.count || 0,
|
|
248
|
+
imported_count: defineData.imported_count,
|
|
249
|
+
function_index_status: defineData.function_index_status,
|
|
250
|
+
decompile_status: defineData.decompile_status,
|
|
251
|
+
cfg_status: defineData.cfg_status,
|
|
252
|
+
recovery_strategy: smartRecoverData.strategy,
|
|
253
|
+
imported_artifact: defineData.artifact,
|
|
254
|
+
analysis_id: defineData.analysis_id,
|
|
255
|
+
imported_function_preview: defineData.imported_functions.slice(0, input.rank_topk),
|
|
256
|
+
recovered_symbol_preview: (symbolsRecoverData?.symbols || [])
|
|
257
|
+
.slice(0, input.rank_topk)
|
|
258
|
+
.map((item) => ({
|
|
259
|
+
address: item.address,
|
|
260
|
+
recovered_name: item.recovered_name,
|
|
261
|
+
name_strategy: item.name_strategy,
|
|
262
|
+
confidence: item.confidence,
|
|
263
|
+
})),
|
|
264
|
+
rank_preview: rankPreview,
|
|
265
|
+
next_steps: Array.from(new Set([
|
|
266
|
+
...defineData.next_steps,
|
|
267
|
+
'Use code.functions.list / code.functions.rank to inspect the recovered index.',
|
|
268
|
+
'Use code.functions.reconstruct or workflow.reconstruct after Ghidra decompile/CFG readiness improves.',
|
|
269
|
+
])),
|
|
270
|
+
},
|
|
271
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
272
|
+
artifacts: defineResult.artifacts,
|
|
273
|
+
metrics: {
|
|
274
|
+
elapsed_ms: Date.now() - startTime,
|
|
275
|
+
tool: TOOL_NAME,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
283
|
+
metrics: {
|
|
284
|
+
elapsed_ms: Date.now() - startTime,
|
|
285
|
+
tool: TOOL_NAME,
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=function-index-recover.js.map
|