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,443 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { generateCacheKey } from '../cache-manager.js';
|
|
3
|
+
import { lookupCachedResult, formatCacheWarning } from './cache-observability.js';
|
|
4
|
+
import { BinaryRoleProfileDataSchema, createBinaryRoleProfileHandler, } from './binary-role-profile.js';
|
|
5
|
+
import { createRuntimeDetectHandler } from './runtime-detect.js';
|
|
6
|
+
import { createStringsExtractHandler } from './strings-extract.js';
|
|
7
|
+
import { createCodeFunctionsSmartRecoverHandler } from './code-functions-smart-recover.js';
|
|
8
|
+
import { createPESymbolsRecoverHandler } from './pe-symbols-recover.js';
|
|
9
|
+
import { buildLibraryProfile } from '../workflows/triage.js';
|
|
10
|
+
const TOOL_NAME = 'rust_binary.analyze';
|
|
11
|
+
const TOOL_VERSION = '0.1.0';
|
|
12
|
+
const CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
13
|
+
const LIBRARY_HINT_PATTERNS = [
|
|
14
|
+
{ name: 'tokio', patterns: [/\btokio\b/i] },
|
|
15
|
+
{ name: 'goblin', patterns: [/\bgoblin\b/i] },
|
|
16
|
+
{ name: 'iced-x86', patterns: [/\biced[-_]?x86\b/i] },
|
|
17
|
+
{ name: 'clap', patterns: [/\bclap\b/i] },
|
|
18
|
+
{ name: 'sysinfo', patterns: [/\bsysinfo\b/i] },
|
|
19
|
+
{ name: 'reqwest', patterns: [/\breqwest\b/i] },
|
|
20
|
+
{ name: 'serde', patterns: [/\bserde\b/i] },
|
|
21
|
+
{ name: 'mio', patterns: [/\bmio\b/i] },
|
|
22
|
+
{ name: 'pelite', patterns: [/\bpelite\b/i] },
|
|
23
|
+
{ name: 'object', patterns: [/\bobject\b/i] },
|
|
24
|
+
{ name: 'winapi', patterns: [/\bwinapi\b/i] },
|
|
25
|
+
{ name: 'ntapi', patterns: [/\bntapi\b/i] },
|
|
26
|
+
{ name: 'windows-sys', patterns: [/\bwindows[-_]?sys\b/i] },
|
|
27
|
+
];
|
|
28
|
+
const RustLibraryProfileSchema = z.object({
|
|
29
|
+
ecosystems: z.array(z.string()),
|
|
30
|
+
top_crates: z.array(z.string()),
|
|
31
|
+
notable_libraries: z.array(z.string()),
|
|
32
|
+
evidence: z.array(z.string()),
|
|
33
|
+
});
|
|
34
|
+
export const rustBinaryAnalyzeInputSchema = z.object({
|
|
35
|
+
sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
|
|
36
|
+
max_strings: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(40)
|
|
40
|
+
.max(400)
|
|
41
|
+
.optional()
|
|
42
|
+
.default(160)
|
|
43
|
+
.describe('Maximum strings inspected for Rust crate, panic, and async/runtime markers'),
|
|
44
|
+
max_symbol_preview: z
|
|
45
|
+
.number()
|
|
46
|
+
.int()
|
|
47
|
+
.min(1)
|
|
48
|
+
.max(24)
|
|
49
|
+
.optional()
|
|
50
|
+
.default(8)
|
|
51
|
+
.describe('Maximum recovered symbols returned in the preview'),
|
|
52
|
+
force_refresh: z
|
|
53
|
+
.boolean()
|
|
54
|
+
.optional()
|
|
55
|
+
.default(false)
|
|
56
|
+
.describe('Bypass cache lookup and recompute from source sample'),
|
|
57
|
+
});
|
|
58
|
+
export const RustBinaryAnalyzeDataSchema = z.object({
|
|
59
|
+
sample_id: z.string(),
|
|
60
|
+
suspected_rust: z.boolean(),
|
|
61
|
+
confidence: z.number().min(0).max(1),
|
|
62
|
+
primary_runtime: z.string().nullable(),
|
|
63
|
+
runtime_hints: z.array(z.string()),
|
|
64
|
+
cargo_paths: z.array(z.string()),
|
|
65
|
+
rust_markers: z.array(z.string()),
|
|
66
|
+
async_runtime_markers: z.array(z.string()),
|
|
67
|
+
panic_markers: z.array(z.string()),
|
|
68
|
+
crate_hints: z.array(z.string()),
|
|
69
|
+
library_profile: RustLibraryProfileSchema.optional(),
|
|
70
|
+
binary_profile: BinaryRoleProfileDataSchema.optional(),
|
|
71
|
+
recovered_function_count: z.number().int().nonnegative(),
|
|
72
|
+
recovered_function_strategy: z.array(z.string()),
|
|
73
|
+
recovered_symbol_count: z.number().int().nonnegative(),
|
|
74
|
+
recovered_symbol_preview: z.array(z.object({
|
|
75
|
+
address: z.string(),
|
|
76
|
+
recovered_name: z.string(),
|
|
77
|
+
name_strategy: z.string(),
|
|
78
|
+
confidence: z.number(),
|
|
79
|
+
})),
|
|
80
|
+
components: z.object({
|
|
81
|
+
runtime_detect: z.object({
|
|
82
|
+
ok: z.boolean(),
|
|
83
|
+
warning_count: z.number().int().nonnegative(),
|
|
84
|
+
error_count: z.number().int().nonnegative(),
|
|
85
|
+
}),
|
|
86
|
+
strings_extract: z.object({
|
|
87
|
+
ok: z.boolean(),
|
|
88
|
+
warning_count: z.number().int().nonnegative(),
|
|
89
|
+
error_count: z.number().int().nonnegative(),
|
|
90
|
+
}),
|
|
91
|
+
smart_recover: z.object({
|
|
92
|
+
ok: z.boolean(),
|
|
93
|
+
warning_count: z.number().int().nonnegative(),
|
|
94
|
+
error_count: z.number().int().nonnegative(),
|
|
95
|
+
}),
|
|
96
|
+
symbols_recover: z.object({
|
|
97
|
+
ok: z.boolean(),
|
|
98
|
+
warning_count: z.number().int().nonnegative(),
|
|
99
|
+
error_count: z.number().int().nonnegative(),
|
|
100
|
+
}),
|
|
101
|
+
binary_role_profile: z.object({
|
|
102
|
+
ok: z.boolean(),
|
|
103
|
+
warning_count: z.number().int().nonnegative(),
|
|
104
|
+
error_count: z.number().int().nonnegative(),
|
|
105
|
+
}),
|
|
106
|
+
}),
|
|
107
|
+
importable_with_code_functions_define: z.boolean(),
|
|
108
|
+
evidence: z.array(z.string()),
|
|
109
|
+
analysis_priorities: z.array(z.string()),
|
|
110
|
+
next_steps: z.array(z.string()),
|
|
111
|
+
});
|
|
112
|
+
export const rustBinaryAnalyzeOutputSchema = z.object({
|
|
113
|
+
ok: z.boolean(),
|
|
114
|
+
data: RustBinaryAnalyzeDataSchema.optional(),
|
|
115
|
+
warnings: z.array(z.string()).optional(),
|
|
116
|
+
errors: z.array(z.string()).optional(),
|
|
117
|
+
metrics: z
|
|
118
|
+
.object({
|
|
119
|
+
elapsed_ms: z.number(),
|
|
120
|
+
tool: z.string(),
|
|
121
|
+
})
|
|
122
|
+
.optional(),
|
|
123
|
+
});
|
|
124
|
+
export const rustBinaryAnalyzeToolDefinition = {
|
|
125
|
+
name: TOOL_NAME,
|
|
126
|
+
description: 'Analyze Rust-oriented PE binaries by correlating runtime hints, crate/toolchain strings, smart function recovery, and recovered symbol names.',
|
|
127
|
+
inputSchema: rustBinaryAnalyzeInputSchema,
|
|
128
|
+
outputSchema: rustBinaryAnalyzeOutputSchema,
|
|
129
|
+
};
|
|
130
|
+
function uniqueStrings(values) {
|
|
131
|
+
const seen = new Set();
|
|
132
|
+
const output = [];
|
|
133
|
+
for (const value of values) {
|
|
134
|
+
const normalized = (value || '').trim();
|
|
135
|
+
if (!normalized || seen.has(normalized)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
seen.add(normalized);
|
|
139
|
+
output.push(normalized);
|
|
140
|
+
}
|
|
141
|
+
return output;
|
|
142
|
+
}
|
|
143
|
+
function clamp(value, min = 0, max = 1) {
|
|
144
|
+
if (!Number.isFinite(value)) {
|
|
145
|
+
return min;
|
|
146
|
+
}
|
|
147
|
+
return Math.min(max, Math.max(min, value));
|
|
148
|
+
}
|
|
149
|
+
function extractCrateNameFromCargoPath(input) {
|
|
150
|
+
const normalized = input.replace(/\//g, '\\');
|
|
151
|
+
const match = normalized.match(/cargo\\(?:registry\\src|git\\checkouts)\\[^\\]+\\([^\\]+)(?:\\|$)/i);
|
|
152
|
+
if (!match?.[1]) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
return match[1].replace(/-\d[\w.+-]*$/, '').toLowerCase();
|
|
156
|
+
}
|
|
157
|
+
function detectLibraryHints(str) {
|
|
158
|
+
return LIBRARY_HINT_PATTERNS.filter((hint) => hint.patterns.some((pattern) => pattern.test(str))).map((hint) => hint.name);
|
|
159
|
+
}
|
|
160
|
+
function analyzeRustStrings(strings) {
|
|
161
|
+
const cargoPaths = [];
|
|
162
|
+
const rustMarkers = [];
|
|
163
|
+
const asyncRuntimeMarkers = [];
|
|
164
|
+
const panicMarkers = [];
|
|
165
|
+
const crateNames = [];
|
|
166
|
+
const libraryHints = [];
|
|
167
|
+
for (const rawEntry of strings) {
|
|
168
|
+
const str = typeof rawEntry === 'string'
|
|
169
|
+
? rawEntry
|
|
170
|
+
: rawEntry && typeof rawEntry === 'object' && 'string' in rawEntry
|
|
171
|
+
? String(rawEntry.string || '')
|
|
172
|
+
: '';
|
|
173
|
+
if (!str) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const cargoMatch = str.match(/cargo[\\/](?:registry[\\/]src|git[\\/]checkouts)[^\r\n]*/i);
|
|
177
|
+
if (cargoMatch?.[0]) {
|
|
178
|
+
cargoPaths.push(cargoMatch[0]);
|
|
179
|
+
const crateName = extractCrateNameFromCargoPath(cargoMatch[0]);
|
|
180
|
+
if (crateName) {
|
|
181
|
+
crateNames.push(crateName);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (/rust_panic|core::panicking|panic_unwind|alloc::|std::rt|rustc|\\src\\main\.rs|\\src\\lib\.rs/i.test(str)) {
|
|
185
|
+
rustMarkers.push(str);
|
|
186
|
+
}
|
|
187
|
+
if (/tokio|async|futures|mio|spawn_blocking|joinhandle|reactor/i.test(str)) {
|
|
188
|
+
asyncRuntimeMarkers.push(str);
|
|
189
|
+
}
|
|
190
|
+
if (/panic|panicking|assertion failed|unwrap failed|expect failed/i.test(str)) {
|
|
191
|
+
panicMarkers.push(str);
|
|
192
|
+
}
|
|
193
|
+
libraryHints.push(...detectLibraryHints(str));
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
cargoPaths: uniqueStrings(cargoPaths),
|
|
197
|
+
rustMarkers: uniqueStrings(rustMarkers),
|
|
198
|
+
asyncRuntimeMarkers: uniqueStrings(asyncRuntimeMarkers),
|
|
199
|
+
panicMarkers: uniqueStrings(panicMarkers),
|
|
200
|
+
crateNames: uniqueStrings(crateNames),
|
|
201
|
+
libraryHints: uniqueStrings(libraryHints),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function buildRustConfidence(options) {
|
|
205
|
+
let score = 0.08;
|
|
206
|
+
if (options.runtimeHints.some((item) => item.toLowerCase().includes('rust')))
|
|
207
|
+
score += 0.28;
|
|
208
|
+
if (options.cargoPaths.length > 0)
|
|
209
|
+
score += 0.2;
|
|
210
|
+
if (options.rustMarkers.length > 0)
|
|
211
|
+
score += 0.17;
|
|
212
|
+
if (options.crateHints.length > 0)
|
|
213
|
+
score += 0.15;
|
|
214
|
+
if (options.recoveredFunctionCount > 0)
|
|
215
|
+
score += 0.06;
|
|
216
|
+
if (options.recoveredSymbolCount > 0)
|
|
217
|
+
score += 0.06;
|
|
218
|
+
return clamp(score);
|
|
219
|
+
}
|
|
220
|
+
export function createRustBinaryAnalyzeHandler(workspaceManager, database, cacheManager, dependencies = {}) {
|
|
221
|
+
const runtimeHandler = dependencies.runtimeHandler || createRuntimeDetectHandler(workspaceManager, database, cacheManager);
|
|
222
|
+
const stringsHandler = dependencies.stringsHandler || createStringsExtractHandler(workspaceManager, database, cacheManager);
|
|
223
|
+
const smartRecoverHandler = dependencies.smartRecoverHandler ||
|
|
224
|
+
createCodeFunctionsSmartRecoverHandler(workspaceManager, database, cacheManager);
|
|
225
|
+
const symbolsRecoverHandler = dependencies.symbolsRecoverHandler ||
|
|
226
|
+
createPESymbolsRecoverHandler(workspaceManager, database, cacheManager);
|
|
227
|
+
const binaryRoleHandler = dependencies.binaryRoleHandler ||
|
|
228
|
+
createBinaryRoleProfileHandler(workspaceManager, database, cacheManager);
|
|
229
|
+
return async (args) => {
|
|
230
|
+
const input = rustBinaryAnalyzeInputSchema.parse(args);
|
|
231
|
+
const startTime = Date.now();
|
|
232
|
+
try {
|
|
233
|
+
const sample = database.findSample(input.sample_id);
|
|
234
|
+
if (!sample) {
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
errors: [`Sample not found: ${input.sample_id}`],
|
|
238
|
+
metrics: {
|
|
239
|
+
elapsed_ms: Date.now() - startTime,
|
|
240
|
+
tool: TOOL_NAME,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const cacheKey = generateCacheKey({
|
|
245
|
+
sampleSha256: sample.sha256,
|
|
246
|
+
toolName: TOOL_NAME,
|
|
247
|
+
toolVersion: TOOL_VERSION,
|
|
248
|
+
args: {
|
|
249
|
+
max_strings: input.max_strings,
|
|
250
|
+
max_symbol_preview: input.max_symbol_preview,
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
if (!input.force_refresh) {
|
|
254
|
+
const cachedLookup = await lookupCachedResult(cacheManager, cacheKey);
|
|
255
|
+
if (cachedLookup) {
|
|
256
|
+
return {
|
|
257
|
+
ok: true,
|
|
258
|
+
data: cachedLookup.data,
|
|
259
|
+
warnings: ['Result from cache', formatCacheWarning(cachedLookup.metadata)],
|
|
260
|
+
metrics: {
|
|
261
|
+
elapsed_ms: Date.now() - startTime,
|
|
262
|
+
tool: TOOL_NAME,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const [runtimeResult, stringsResult, smartRecoverResult, symbolsRecoverResult, binaryRoleResult] = await Promise.all([
|
|
268
|
+
runtimeHandler({ sample_id: input.sample_id, force_refresh: input.force_refresh }),
|
|
269
|
+
stringsHandler({
|
|
270
|
+
sample_id: input.sample_id,
|
|
271
|
+
category_filter: 'all',
|
|
272
|
+
max_strings: input.max_strings,
|
|
273
|
+
force_refresh: input.force_refresh,
|
|
274
|
+
}),
|
|
275
|
+
smartRecoverHandler({ sample_id: input.sample_id, force_refresh: input.force_refresh }),
|
|
276
|
+
symbolsRecoverHandler({
|
|
277
|
+
sample_id: input.sample_id,
|
|
278
|
+
max_string_hints: input.max_strings,
|
|
279
|
+
force_refresh: input.force_refresh,
|
|
280
|
+
}),
|
|
281
|
+
binaryRoleHandler({ sample_id: input.sample_id, max_strings: input.max_strings, force_refresh: input.force_refresh }),
|
|
282
|
+
]);
|
|
283
|
+
const componentStatus = {
|
|
284
|
+
runtime_detect: {
|
|
285
|
+
ok: runtimeResult.ok,
|
|
286
|
+
warning_count: runtimeResult.warnings?.length || 0,
|
|
287
|
+
error_count: runtimeResult.errors?.length || 0,
|
|
288
|
+
},
|
|
289
|
+
strings_extract: {
|
|
290
|
+
ok: stringsResult.ok,
|
|
291
|
+
warning_count: stringsResult.warnings?.length || 0,
|
|
292
|
+
error_count: stringsResult.errors?.length || 0,
|
|
293
|
+
},
|
|
294
|
+
smart_recover: {
|
|
295
|
+
ok: smartRecoverResult.ok,
|
|
296
|
+
warning_count: smartRecoverResult.warnings?.length || 0,
|
|
297
|
+
error_count: smartRecoverResult.errors?.length || 0,
|
|
298
|
+
},
|
|
299
|
+
symbols_recover: {
|
|
300
|
+
ok: symbolsRecoverResult.ok,
|
|
301
|
+
warning_count: symbolsRecoverResult.warnings?.length || 0,
|
|
302
|
+
error_count: symbolsRecoverResult.errors?.length || 0,
|
|
303
|
+
},
|
|
304
|
+
binary_role_profile: {
|
|
305
|
+
ok: binaryRoleResult.ok,
|
|
306
|
+
warning_count: binaryRoleResult.warnings?.length || 0,
|
|
307
|
+
error_count: binaryRoleResult.errors?.length || 0,
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
const warnings = [
|
|
311
|
+
...(runtimeResult.warnings || []).map((item) => `runtime: ${item}`),
|
|
312
|
+
...(runtimeResult.ok ? [] : (runtimeResult.errors || []).map((item) => `runtime error: ${item}`)),
|
|
313
|
+
...(stringsResult.warnings || []).map((item) => `strings: ${item}`),
|
|
314
|
+
...(stringsResult.ok ? [] : (stringsResult.errors || []).map((item) => `strings error: ${item}`)),
|
|
315
|
+
...(smartRecoverResult.warnings || []).map((item) => `smart_recover: ${item}`),
|
|
316
|
+
...(smartRecoverResult.ok
|
|
317
|
+
? []
|
|
318
|
+
: (smartRecoverResult.errors || []).map((item) => `smart_recover error: ${item}`)),
|
|
319
|
+
...(symbolsRecoverResult.warnings || []).map((item) => `symbols_recover: ${item}`),
|
|
320
|
+
...(symbolsRecoverResult.ok
|
|
321
|
+
? []
|
|
322
|
+
: (symbolsRecoverResult.errors || []).map((item) => `symbols_recover error: ${item}`)),
|
|
323
|
+
...(binaryRoleResult.warnings || []).map((item) => `binary_role: ${item}`),
|
|
324
|
+
...(binaryRoleResult.ok
|
|
325
|
+
? []
|
|
326
|
+
: (binaryRoleResult.errors || []).map((item) => `binary_role error: ${item}`)),
|
|
327
|
+
];
|
|
328
|
+
const runtimeData = (runtimeResult.ok ? runtimeResult.data : undefined);
|
|
329
|
+
const stringsData = (stringsResult.ok ? stringsResult.data : undefined);
|
|
330
|
+
const smartRecoverData = (smartRecoverResult.ok ? smartRecoverResult.data : undefined);
|
|
331
|
+
const symbolsData = (symbolsRecoverResult.ok ? symbolsRecoverResult.data : undefined);
|
|
332
|
+
const binaryProfile = binaryRoleResult.ok ? binaryRoleResult.data : undefined;
|
|
333
|
+
const rawStrings = stringsData?.strings || [];
|
|
334
|
+
const stringAnalysis = analyzeRustStrings(rawStrings);
|
|
335
|
+
const libraryProfile = buildLibraryProfile({
|
|
336
|
+
cargoPaths: stringAnalysis.cargoPaths,
|
|
337
|
+
crateNames: stringAnalysis.crateNames,
|
|
338
|
+
libraryHints: stringAnalysis.libraryHints,
|
|
339
|
+
rustMarkers: stringAnalysis.rustMarkers,
|
|
340
|
+
}, runtimeData || {});
|
|
341
|
+
const runtimeHints = uniqueStrings([
|
|
342
|
+
...(runtimeData?.suspected || []).map((item) => item.runtime),
|
|
343
|
+
...(symbolsData?.runtime_hints || []),
|
|
344
|
+
...(libraryProfile?.ecosystems || []),
|
|
345
|
+
]);
|
|
346
|
+
const crateHints = uniqueStrings([
|
|
347
|
+
...(symbolsData?.crate_hints || []),
|
|
348
|
+
...stringAnalysis.crateNames,
|
|
349
|
+
...(libraryProfile?.top_crates || []),
|
|
350
|
+
]);
|
|
351
|
+
const recoveredFunctionCount = smartRecoverData?.count || 0;
|
|
352
|
+
const recoveredFunctionStrategy = smartRecoverData?.strategy || [];
|
|
353
|
+
const recoveredSymbolCount = symbolsData?.count || 0;
|
|
354
|
+
const recoveredSymbolPreview = (symbolsData?.symbols || []).slice(0, input.max_symbol_preview);
|
|
355
|
+
const confidence = buildRustConfidence({
|
|
356
|
+
runtimeHints,
|
|
357
|
+
cargoPaths: stringAnalysis.cargoPaths,
|
|
358
|
+
rustMarkers: stringAnalysis.rustMarkers,
|
|
359
|
+
crateHints,
|
|
360
|
+
recoveredFunctionCount,
|
|
361
|
+
recoveredSymbolCount,
|
|
362
|
+
});
|
|
363
|
+
const suspectedRust = confidence >= 0.42;
|
|
364
|
+
const evidence = uniqueStrings([
|
|
365
|
+
...(runtimeData?.suspected || [])
|
|
366
|
+
.filter((item) => item.runtime.toLowerCase().includes('rust'))
|
|
367
|
+
.flatMap((item) => item.evidence || []),
|
|
368
|
+
...stringAnalysis.cargoPaths.slice(0, 3).map((item) => `Cargo path: ${item}`),
|
|
369
|
+
...stringAnalysis.rustMarkers.slice(0, 3).map((item) => `Rust marker: ${item}`),
|
|
370
|
+
...stringAnalysis.asyncRuntimeMarkers.slice(0, 2).map((item) => `Async/runtime marker: ${item}`),
|
|
371
|
+
...stringAnalysis.panicMarkers.slice(0, 2).map((item) => `Panic marker: ${item}`),
|
|
372
|
+
...((libraryProfile?.evidence || []).slice(0, 3)),
|
|
373
|
+
...(recoveredSymbolPreview.slice(0, 3).map((item) => `Recovered symbol: ${item.recovered_name}`)),
|
|
374
|
+
]);
|
|
375
|
+
const analysisPriorities = uniqueStrings([
|
|
376
|
+
...(binaryProfile?.analysis_priorities || []),
|
|
377
|
+
recoveredFunctionCount > 0 ? 'feed_recovered_boundaries_into_code.functions.define' : '',
|
|
378
|
+
recoveredSymbolCount > 0 ? 'review_recovered_symbol_names_before_manual_validation' : '',
|
|
379
|
+
stringAnalysis.asyncRuntimeMarkers.length > 0 ? 'trace_async_runtime_and_scheduler_paths' : '',
|
|
380
|
+
stringAnalysis.panicMarkers.length > 0 ? 'separate_panic_paths_from_primary_business_logic' : '',
|
|
381
|
+
crateHints.includes('tokio') || crateHints.includes('mio')
|
|
382
|
+
? 'trace_runtime_bootstrap_and_async_task_dispatch'
|
|
383
|
+
: '',
|
|
384
|
+
crateHints.includes('goblin') || crateHints.includes('iced-x86')
|
|
385
|
+
? 'review_binary_parsing_and_disassembly_modules_first'
|
|
386
|
+
: '',
|
|
387
|
+
]).filter(Boolean);
|
|
388
|
+
const nextSteps = uniqueStrings([
|
|
389
|
+
recoveredFunctionCount > 0
|
|
390
|
+
? 'Use code.functions.define with source=smart_recover or symbols_recover to materialize the recovered function index.'
|
|
391
|
+
: 'Use pe.pdata.extract to inspect the PE exception directory directly if function recovery remains empty.',
|
|
392
|
+
'Run ghidra.analyze with options.language_id / options.cspec / options.script_paths when Rust auto-detection under-identifies functions.',
|
|
393
|
+
recoveredSymbolCount > 0
|
|
394
|
+
? 'Use code.functions.define with recovered_name values to preserve recovered symbol names before reconstruct/export.'
|
|
395
|
+
: 'Run pe.symbols.recover after strings extraction to derive more descriptive recovered names.',
|
|
396
|
+
]);
|
|
397
|
+
const payload = {
|
|
398
|
+
sample_id: input.sample_id,
|
|
399
|
+
suspected_rust: suspectedRust,
|
|
400
|
+
confidence,
|
|
401
|
+
primary_runtime: symbolsData?.primary_runtime || runtimeHints[0] || null,
|
|
402
|
+
runtime_hints: runtimeHints,
|
|
403
|
+
cargo_paths: stringAnalysis.cargoPaths,
|
|
404
|
+
rust_markers: stringAnalysis.rustMarkers,
|
|
405
|
+
async_runtime_markers: stringAnalysis.asyncRuntimeMarkers,
|
|
406
|
+
panic_markers: stringAnalysis.panicMarkers,
|
|
407
|
+
crate_hints: crateHints,
|
|
408
|
+
library_profile: libraryProfile,
|
|
409
|
+
binary_profile: binaryProfile,
|
|
410
|
+
recovered_function_count: recoveredFunctionCount,
|
|
411
|
+
recovered_function_strategy: recoveredFunctionStrategy,
|
|
412
|
+
recovered_symbol_count: recoveredSymbolCount,
|
|
413
|
+
recovered_symbol_preview: recoveredSymbolPreview,
|
|
414
|
+
components: componentStatus,
|
|
415
|
+
importable_with_code_functions_define: recoveredFunctionCount > 0 || recoveredSymbolCount > 0,
|
|
416
|
+
evidence,
|
|
417
|
+
analysis_priorities: analysisPriorities,
|
|
418
|
+
next_steps: nextSteps,
|
|
419
|
+
};
|
|
420
|
+
await cacheManager.setCachedResult(cacheKey, payload, CACHE_TTL_MS, sample.sha256);
|
|
421
|
+
return {
|
|
422
|
+
ok: true,
|
|
423
|
+
data: payload,
|
|
424
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
425
|
+
metrics: {
|
|
426
|
+
elapsed_ms: Date.now() - startTime,
|
|
427
|
+
tool: TOOL_NAME,
|
|
428
|
+
},
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
return {
|
|
433
|
+
ok: false,
|
|
434
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
435
|
+
metrics: {
|
|
436
|
+
elapsed_ms: Date.now() - startTime,
|
|
437
|
+
tool: TOOL_NAME,
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
//# sourceMappingURL=rust-binary-analyze.js.map
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* sample.profile.get tool implementation
|
|
3
|
-
* Retrieves sample profile including basic information
|
|
4
|
-
*
|
|
3
|
+
* Retrieves sample profile including basic information, completed analyses,
|
|
4
|
+
* and workspace/original integrity status.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import type { ToolDefinition, ToolArgs, WorkerResult } from '../types.js';
|
|
8
8
|
import type { DatabaseManager } from '../database.js';
|
|
9
|
-
|
|
10
|
-
* Input schema for sample.profile.get tool
|
|
11
|
-
*/
|
|
9
|
+
import type { WorkspaceManager } from '../workspace-manager.js';
|
|
12
10
|
export declare const SampleProfileGetInputSchema: z.ZodObject<{
|
|
13
11
|
sample_id: z.ZodString;
|
|
14
12
|
stale_running_ms: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
@@ -20,9 +18,6 @@ export declare const SampleProfileGetInputSchema: z.ZodObject<{
|
|
|
20
18
|
stale_running_ms?: number | null | undefined;
|
|
21
19
|
}>;
|
|
22
20
|
export type SampleProfileGetInput = z.infer<typeof SampleProfileGetInputSchema>;
|
|
23
|
-
/**
|
|
24
|
-
* Output schema for sample.profile.get tool
|
|
25
|
-
*/
|
|
26
21
|
export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
27
22
|
ok: z.ZodBoolean;
|
|
28
23
|
data: z.ZodOptional<z.ZodObject<{
|
|
@@ -79,6 +74,61 @@ export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
|
79
74
|
output_json?: string | undefined;
|
|
80
75
|
metrics_json?: string | undefined;
|
|
81
76
|
}>, "many">;
|
|
77
|
+
workspace: z.ZodOptional<z.ZodObject<{
|
|
78
|
+
status: z.ZodEnum<["ready", "workspace_missing", "original_dir_missing", "original_file_missing"]>;
|
|
79
|
+
workspace_root: z.ZodNullable<z.ZodString>;
|
|
80
|
+
original_dir: z.ZodNullable<z.ZodString>;
|
|
81
|
+
reports_dir: z.ZodNullable<z.ZodString>;
|
|
82
|
+
ghidra_dir: z.ZodNullable<z.ZodString>;
|
|
83
|
+
workspace_exists: z.ZodBoolean;
|
|
84
|
+
original_dir_exists: z.ZodBoolean;
|
|
85
|
+
reports_dir_exists: z.ZodBoolean;
|
|
86
|
+
ghidra_dir_exists: z.ZodBoolean;
|
|
87
|
+
original_present: z.ZodBoolean;
|
|
88
|
+
original_file_count: z.ZodNumber;
|
|
89
|
+
original_files: z.ZodArray<z.ZodString, "many">;
|
|
90
|
+
alternate_workspace_root: z.ZodNullable<z.ZodString>;
|
|
91
|
+
alternate_original_dir: z.ZodNullable<z.ZodString>;
|
|
92
|
+
alternate_original_present: z.ZodBoolean;
|
|
93
|
+
alternate_original_files: z.ZodArray<z.ZodString, "many">;
|
|
94
|
+
remediation: z.ZodArray<z.ZodString, "many">;
|
|
95
|
+
}, "strip", z.ZodTypeAny, {
|
|
96
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
97
|
+
workspace_root: string | null;
|
|
98
|
+
original_dir: string | null;
|
|
99
|
+
reports_dir: string | null;
|
|
100
|
+
ghidra_dir: string | null;
|
|
101
|
+
workspace_exists: boolean;
|
|
102
|
+
original_dir_exists: boolean;
|
|
103
|
+
reports_dir_exists: boolean;
|
|
104
|
+
ghidra_dir_exists: boolean;
|
|
105
|
+
original_file_count: number;
|
|
106
|
+
original_files: string[];
|
|
107
|
+
alternate_workspace_root: string | null;
|
|
108
|
+
alternate_original_dir: string | null;
|
|
109
|
+
alternate_original_files: string[];
|
|
110
|
+
original_present: boolean;
|
|
111
|
+
alternate_original_present: boolean;
|
|
112
|
+
remediation: string[];
|
|
113
|
+
}, {
|
|
114
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
115
|
+
workspace_root: string | null;
|
|
116
|
+
original_dir: string | null;
|
|
117
|
+
reports_dir: string | null;
|
|
118
|
+
ghidra_dir: string | null;
|
|
119
|
+
workspace_exists: boolean;
|
|
120
|
+
original_dir_exists: boolean;
|
|
121
|
+
reports_dir_exists: boolean;
|
|
122
|
+
ghidra_dir_exists: boolean;
|
|
123
|
+
original_file_count: number;
|
|
124
|
+
original_files: string[];
|
|
125
|
+
alternate_workspace_root: string | null;
|
|
126
|
+
alternate_original_dir: string | null;
|
|
127
|
+
alternate_original_files: string[];
|
|
128
|
+
original_present: boolean;
|
|
129
|
+
alternate_original_present: boolean;
|
|
130
|
+
remediation: string[];
|
|
131
|
+
}>>;
|
|
82
132
|
}, "strip", z.ZodTypeAny, {
|
|
83
133
|
sample: {
|
|
84
134
|
id: string;
|
|
@@ -99,6 +149,25 @@ export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
|
99
149
|
output_json?: string | undefined;
|
|
100
150
|
metrics_json?: string | undefined;
|
|
101
151
|
}[];
|
|
152
|
+
workspace?: {
|
|
153
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
154
|
+
workspace_root: string | null;
|
|
155
|
+
original_dir: string | null;
|
|
156
|
+
reports_dir: string | null;
|
|
157
|
+
ghidra_dir: string | null;
|
|
158
|
+
workspace_exists: boolean;
|
|
159
|
+
original_dir_exists: boolean;
|
|
160
|
+
reports_dir_exists: boolean;
|
|
161
|
+
ghidra_dir_exists: boolean;
|
|
162
|
+
original_file_count: number;
|
|
163
|
+
original_files: string[];
|
|
164
|
+
alternate_workspace_root: string | null;
|
|
165
|
+
alternate_original_dir: string | null;
|
|
166
|
+
alternate_original_files: string[];
|
|
167
|
+
original_present: boolean;
|
|
168
|
+
alternate_original_present: boolean;
|
|
169
|
+
remediation: string[];
|
|
170
|
+
} | undefined;
|
|
102
171
|
}, {
|
|
103
172
|
sample: {
|
|
104
173
|
id: string;
|
|
@@ -119,6 +188,25 @@ export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
|
119
188
|
output_json?: string | undefined;
|
|
120
189
|
metrics_json?: string | undefined;
|
|
121
190
|
}[];
|
|
191
|
+
workspace?: {
|
|
192
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
193
|
+
workspace_root: string | null;
|
|
194
|
+
original_dir: string | null;
|
|
195
|
+
reports_dir: string | null;
|
|
196
|
+
ghidra_dir: string | null;
|
|
197
|
+
workspace_exists: boolean;
|
|
198
|
+
original_dir_exists: boolean;
|
|
199
|
+
reports_dir_exists: boolean;
|
|
200
|
+
ghidra_dir_exists: boolean;
|
|
201
|
+
original_file_count: number;
|
|
202
|
+
original_files: string[];
|
|
203
|
+
alternate_workspace_root: string | null;
|
|
204
|
+
alternate_original_dir: string | null;
|
|
205
|
+
alternate_original_files: string[];
|
|
206
|
+
original_present: boolean;
|
|
207
|
+
alternate_original_present: boolean;
|
|
208
|
+
remediation: string[];
|
|
209
|
+
} | undefined;
|
|
122
210
|
}>>;
|
|
123
211
|
errors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
124
212
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -143,6 +231,25 @@ export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
|
143
231
|
output_json?: string | undefined;
|
|
144
232
|
metrics_json?: string | undefined;
|
|
145
233
|
}[];
|
|
234
|
+
workspace?: {
|
|
235
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
236
|
+
workspace_root: string | null;
|
|
237
|
+
original_dir: string | null;
|
|
238
|
+
reports_dir: string | null;
|
|
239
|
+
ghidra_dir: string | null;
|
|
240
|
+
workspace_exists: boolean;
|
|
241
|
+
original_dir_exists: boolean;
|
|
242
|
+
reports_dir_exists: boolean;
|
|
243
|
+
ghidra_dir_exists: boolean;
|
|
244
|
+
original_file_count: number;
|
|
245
|
+
original_files: string[];
|
|
246
|
+
alternate_workspace_root: string | null;
|
|
247
|
+
alternate_original_dir: string | null;
|
|
248
|
+
alternate_original_files: string[];
|
|
249
|
+
original_present: boolean;
|
|
250
|
+
alternate_original_present: boolean;
|
|
251
|
+
remediation: string[];
|
|
252
|
+
} | undefined;
|
|
146
253
|
} | undefined;
|
|
147
254
|
errors?: string[] | undefined;
|
|
148
255
|
}, {
|
|
@@ -167,17 +274,29 @@ export declare const SampleProfileGetOutputSchema: z.ZodObject<{
|
|
|
167
274
|
output_json?: string | undefined;
|
|
168
275
|
metrics_json?: string | undefined;
|
|
169
276
|
}[];
|
|
277
|
+
workspace?: {
|
|
278
|
+
status: "ready" | "workspace_missing" | "original_dir_missing" | "original_file_missing";
|
|
279
|
+
workspace_root: string | null;
|
|
280
|
+
original_dir: string | null;
|
|
281
|
+
reports_dir: string | null;
|
|
282
|
+
ghidra_dir: string | null;
|
|
283
|
+
workspace_exists: boolean;
|
|
284
|
+
original_dir_exists: boolean;
|
|
285
|
+
reports_dir_exists: boolean;
|
|
286
|
+
ghidra_dir_exists: boolean;
|
|
287
|
+
original_file_count: number;
|
|
288
|
+
original_files: string[];
|
|
289
|
+
alternate_workspace_root: string | null;
|
|
290
|
+
alternate_original_dir: string | null;
|
|
291
|
+
alternate_original_files: string[];
|
|
292
|
+
original_present: boolean;
|
|
293
|
+
alternate_original_present: boolean;
|
|
294
|
+
remediation: string[];
|
|
295
|
+
} | undefined;
|
|
170
296
|
} | undefined;
|
|
171
297
|
errors?: string[] | undefined;
|
|
172
298
|
}>;
|
|
173
299
|
export type SampleProfileGetOutput = z.infer<typeof SampleProfileGetOutputSchema>;
|
|
174
|
-
/**
|
|
175
|
-
* Tool definition for sample.profile.get
|
|
176
|
-
*/
|
|
177
300
|
export declare const sampleProfileGetToolDefinition: ToolDefinition;
|
|
178
|
-
|
|
179
|
-
* Create sample.profile.get tool handler
|
|
180
|
-
* Requirements: Data Model
|
|
181
|
-
*/
|
|
182
|
-
export declare function createSampleProfileGetHandler(database: DatabaseManager): (args: ToolArgs) => Promise<WorkerResult>;
|
|
301
|
+
export declare function createSampleProfileGetHandler(database: DatabaseManager, workspaceManager?: WorkspaceManager): (args: ToolArgs) => Promise<WorkerResult>;
|
|
183
302
|
//# sourceMappingURL=sample-profile-get.d.ts.map
|