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.
Files changed (190) hide show
  1. package/CODEX_INSTALLATION.md +69 -0
  2. package/COPILOT_INSTALLATION.md +77 -0
  3. package/LICENSE +21 -0
  4. package/README.md +314 -0
  5. package/bin/windows-exe-decompiler-mcp-server.js +3 -0
  6. package/dist/analysis-provenance.d.ts +184 -0
  7. package/dist/analysis-provenance.js +74 -0
  8. package/dist/analysis-task-runner.d.ts +31 -0
  9. package/dist/analysis-task-runner.js +160 -0
  10. package/dist/artifact-inventory.d.ts +23 -0
  11. package/dist/artifact-inventory.js +175 -0
  12. package/dist/cache-manager.d.ts +128 -0
  13. package/dist/cache-manager.js +454 -0
  14. package/dist/confidence-semantics.d.ts +66 -0
  15. package/dist/confidence-semantics.js +122 -0
  16. package/dist/config.d.ts +335 -0
  17. package/dist/config.js +193 -0
  18. package/dist/database.d.ts +227 -0
  19. package/dist/database.js +601 -0
  20. package/dist/decompiler-worker.d.ts +441 -0
  21. package/dist/decompiler-worker.js +1962 -0
  22. package/dist/dynamic-trace.d.ts +95 -0
  23. package/dist/dynamic-trace.js +629 -0
  24. package/dist/env-validator.d.ts +15 -0
  25. package/dist/env-validator.js +249 -0
  26. package/dist/error-handler.d.ts +28 -0
  27. package/dist/error-handler.example.d.ts +22 -0
  28. package/dist/error-handler.example.js +141 -0
  29. package/dist/error-handler.js +139 -0
  30. package/dist/ghidra-analysis-status.d.ts +49 -0
  31. package/dist/ghidra-analysis-status.js +178 -0
  32. package/dist/ghidra-config.d.ts +134 -0
  33. package/dist/ghidra-config.js +464 -0
  34. package/dist/index.d.ts +9 -0
  35. package/dist/index.js +200 -0
  36. package/dist/job-queue.d.ts +169 -0
  37. package/dist/job-queue.js +407 -0
  38. package/dist/logger.d.ts +106 -0
  39. package/dist/logger.js +176 -0
  40. package/dist/policy-guard.d.ts +115 -0
  41. package/dist/policy-guard.js +243 -0
  42. package/dist/process-output.d.ts +15 -0
  43. package/dist/process-output.js +90 -0
  44. package/dist/prompts/function-explanation-review.d.ts +5 -0
  45. package/dist/prompts/function-explanation-review.js +64 -0
  46. package/dist/prompts/semantic-name-review.d.ts +5 -0
  47. package/dist/prompts/semantic-name-review.js +63 -0
  48. package/dist/runtime-correlation.d.ts +34 -0
  49. package/dist/runtime-correlation.js +279 -0
  50. package/dist/runtime-paths.d.ts +3 -0
  51. package/dist/runtime-paths.js +11 -0
  52. package/dist/selection-diff.d.ts +667 -0
  53. package/dist/selection-diff.js +53 -0
  54. package/dist/semantic-name-suggestion-artifacts.d.ts +116 -0
  55. package/dist/semantic-name-suggestion-artifacts.js +314 -0
  56. package/dist/server.d.ts +129 -0
  57. package/dist/server.js +578 -0
  58. package/dist/tools/artifact-read.d.ts +235 -0
  59. package/dist/tools/artifact-read.js +317 -0
  60. package/dist/tools/artifacts-diff.d.ts +728 -0
  61. package/dist/tools/artifacts-diff.js +304 -0
  62. package/dist/tools/artifacts-list.d.ts +515 -0
  63. package/dist/tools/artifacts-list.js +389 -0
  64. package/dist/tools/attack-map.d.ts +290 -0
  65. package/dist/tools/attack-map.js +519 -0
  66. package/dist/tools/cache-observability.d.ts +4 -0
  67. package/dist/tools/cache-observability.js +36 -0
  68. package/dist/tools/code-function-cfg.d.ts +50 -0
  69. package/dist/tools/code-function-cfg.js +102 -0
  70. package/dist/tools/code-function-decompile.d.ts +55 -0
  71. package/dist/tools/code-function-decompile.js +103 -0
  72. package/dist/tools/code-function-disassemble.d.ts +43 -0
  73. package/dist/tools/code-function-disassemble.js +185 -0
  74. package/dist/tools/code-function-explain-apply.d.ts +255 -0
  75. package/dist/tools/code-function-explain-apply.js +225 -0
  76. package/dist/tools/code-function-explain-prepare.d.ts +535 -0
  77. package/dist/tools/code-function-explain-prepare.js +276 -0
  78. package/dist/tools/code-function-explain-review.d.ts +397 -0
  79. package/dist/tools/code-function-explain-review.js +589 -0
  80. package/dist/tools/code-function-rename-apply.d.ts +248 -0
  81. package/dist/tools/code-function-rename-apply.js +220 -0
  82. package/dist/tools/code-function-rename-prepare.d.ts +506 -0
  83. package/dist/tools/code-function-rename-prepare.js +279 -0
  84. package/dist/tools/code-function-rename-review.d.ts +574 -0
  85. package/dist/tools/code-function-rename-review.js +761 -0
  86. package/dist/tools/code-functions-list.d.ts +37 -0
  87. package/dist/tools/code-functions-list.js +91 -0
  88. package/dist/tools/code-functions-rank.d.ts +34 -0
  89. package/dist/tools/code-functions-rank.js +90 -0
  90. package/dist/tools/code-functions-reconstruct.d.ts +2725 -0
  91. package/dist/tools/code-functions-reconstruct.js +2807 -0
  92. package/dist/tools/code-functions-search.d.ts +39 -0
  93. package/dist/tools/code-functions-search.js +90 -0
  94. package/dist/tools/code-reconstruct-export.d.ts +1212 -0
  95. package/dist/tools/code-reconstruct-export.js +4002 -0
  96. package/dist/tools/code-reconstruct-plan.d.ts +274 -0
  97. package/dist/tools/code-reconstruct-plan.js +342 -0
  98. package/dist/tools/dotnet-metadata-extract.d.ts +541 -0
  99. package/dist/tools/dotnet-metadata-extract.js +355 -0
  100. package/dist/tools/dotnet-reconstruct-export.d.ts +567 -0
  101. package/dist/tools/dotnet-reconstruct-export.js +1151 -0
  102. package/dist/tools/dotnet-types-list.d.ts +325 -0
  103. package/dist/tools/dotnet-types-list.js +201 -0
  104. package/dist/tools/dynamic-dependencies.d.ts +115 -0
  105. package/dist/tools/dynamic-dependencies.js +213 -0
  106. package/dist/tools/dynamic-memory-import.d.ts +10 -0
  107. package/dist/tools/dynamic-memory-import.js +567 -0
  108. package/dist/tools/dynamic-trace-import.d.ts +10 -0
  109. package/dist/tools/dynamic-trace-import.js +235 -0
  110. package/dist/tools/entrypoint-fallback-disasm.d.ts +30 -0
  111. package/dist/tools/entrypoint-fallback-disasm.js +89 -0
  112. package/dist/tools/ghidra-analyze.d.ts +88 -0
  113. package/dist/tools/ghidra-analyze.js +208 -0
  114. package/dist/tools/ghidra-health.d.ts +37 -0
  115. package/dist/tools/ghidra-health.js +212 -0
  116. package/dist/tools/ioc-export.d.ts +209 -0
  117. package/dist/tools/ioc-export.js +542 -0
  118. package/dist/tools/packer-detect.d.ts +165 -0
  119. package/dist/tools/packer-detect.js +284 -0
  120. package/dist/tools/pe-exports-extract.d.ts +175 -0
  121. package/dist/tools/pe-exports-extract.js +253 -0
  122. package/dist/tools/pe-fingerprint.d.ts +234 -0
  123. package/dist/tools/pe-fingerprint.js +269 -0
  124. package/dist/tools/pe-imports-extract.d.ts +105 -0
  125. package/dist/tools/pe-imports-extract.js +245 -0
  126. package/dist/tools/report-generate.d.ts +157 -0
  127. package/dist/tools/report-generate.js +457 -0
  128. package/dist/tools/report-summarize.d.ts +2131 -0
  129. package/dist/tools/report-summarize.js +596 -0
  130. package/dist/tools/runtime-detect.d.ts +135 -0
  131. package/dist/tools/runtime-detect.js +247 -0
  132. package/dist/tools/sample-ingest.d.ts +94 -0
  133. package/dist/tools/sample-ingest.js +327 -0
  134. package/dist/tools/sample-profile-get.d.ts +183 -0
  135. package/dist/tools/sample-profile-get.js +121 -0
  136. package/dist/tools/sandbox-execute.d.ts +441 -0
  137. package/dist/tools/sandbox-execute.js +392 -0
  138. package/dist/tools/strings-extract.d.ts +375 -0
  139. package/dist/tools/strings-extract.js +314 -0
  140. package/dist/tools/strings-floss-decode.d.ts +143 -0
  141. package/dist/tools/strings-floss-decode.js +259 -0
  142. package/dist/tools/system-health.d.ts +434 -0
  143. package/dist/tools/system-health.js +446 -0
  144. package/dist/tools/task-cancel.d.ts +21 -0
  145. package/dist/tools/task-cancel.js +70 -0
  146. package/dist/tools/task-status.d.ts +27 -0
  147. package/dist/tools/task-status.js +106 -0
  148. package/dist/tools/task-sweep.d.ts +22 -0
  149. package/dist/tools/task-sweep.js +77 -0
  150. package/dist/tools/tool-help.d.ts +340 -0
  151. package/dist/tools/tool-help.js +261 -0
  152. package/dist/tools/yara-scan.d.ts +554 -0
  153. package/dist/tools/yara-scan.js +313 -0
  154. package/dist/types.d.ts +266 -0
  155. package/dist/types.js +41 -0
  156. package/dist/worker-pool.d.ts +204 -0
  157. package/dist/worker-pool.js +650 -0
  158. package/dist/workflows/deep-static.d.ts +104 -0
  159. package/dist/workflows/deep-static.js +276 -0
  160. package/dist/workflows/function-explanation-review.d.ts +655 -0
  161. package/dist/workflows/function-explanation-review.js +440 -0
  162. package/dist/workflows/reconstruct.d.ts +2053 -0
  163. package/dist/workflows/reconstruct.js +666 -0
  164. package/dist/workflows/semantic-name-review.d.ts +2418 -0
  165. package/dist/workflows/semantic-name-review.js +521 -0
  166. package/dist/workflows/triage.d.ts +659 -0
  167. package/dist/workflows/triage.js +1374 -0
  168. package/dist/workspace-manager.d.ts +150 -0
  169. package/dist/workspace-manager.js +411 -0
  170. package/ghidra_scripts/DecompileFunction.java +487 -0
  171. package/ghidra_scripts/DecompileFunction.py +150 -0
  172. package/ghidra_scripts/ExtractCFG.java +256 -0
  173. package/ghidra_scripts/ExtractCFG.py +233 -0
  174. package/ghidra_scripts/ExtractFunctions.java +442 -0
  175. package/ghidra_scripts/ExtractFunctions.py +101 -0
  176. package/ghidra_scripts/README.md +125 -0
  177. package/ghidra_scripts/SearchFunctionReferences.java +380 -0
  178. package/helpers/DotNetMetadataProbe/DotNetMetadataProbe.csproj +9 -0
  179. package/helpers/DotNetMetadataProbe/Program.cs +566 -0
  180. package/install-to-codex.ps1 +178 -0
  181. package/install-to-copilot.ps1 +303 -0
  182. package/package.json +101 -0
  183. package/requirements.txt +9 -0
  184. package/workers/requirements-dynamic.txt +11 -0
  185. package/workers/requirements.txt +8 -0
  186. package/workers/speakeasy_compat.py +175 -0
  187. package/workers/static_worker.py +5183 -0
  188. package/workers/yara_rules/default.yar +33 -0
  189. package/workers/yara_rules/malware_families.yar +93 -0
  190. package/workers/yara_rules/packers.yar +80 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * strings.floss.decode tool implementation
3
+ * Uses FLOSS tool to decode obfuscated strings from PE files
4
+ * Requirements: 4.4, 4.5
5
+ */
6
+ import { z } from 'zod';
7
+ import type { ToolDefinition, ToolArgs, WorkerResult } from '../types.js';
8
+ import type { WorkspaceManager } from '../workspace-manager.js';
9
+ import type { DatabaseManager } from '../database.js';
10
+ import type { CacheManager } from '../cache-manager.js';
11
+ /**
12
+ * Input schema for strings.floss.decode tool
13
+ * Requirements: 4.4, 4.5
14
+ */
15
+ export declare const StringsFlossDecodeInputSchema: z.ZodObject<{
16
+ sample_id: z.ZodString;
17
+ timeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
18
+ modes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodEnum<["static", "stack", "tight", "decoded"]>, "many">>>;
19
+ force_refresh: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ timeout: number;
22
+ sample_id: string;
23
+ force_refresh: boolean;
24
+ modes: ("static" | "stack" | "tight" | "decoded")[];
25
+ }, {
26
+ sample_id: string;
27
+ timeout?: number | undefined;
28
+ force_refresh?: boolean | undefined;
29
+ modes?: ("static" | "stack" | "tight" | "decoded")[] | undefined;
30
+ }>;
31
+ export type StringsFlossDecodeInput = z.infer<typeof StringsFlossDecodeInputSchema>;
32
+ /**
33
+ * Output schema for strings.floss.decode tool
34
+ * Requirements: 4.4, 4.5
35
+ */
36
+ export declare const StringsFlossDecodeOutputSchema: z.ZodObject<{
37
+ ok: z.ZodBoolean;
38
+ data: z.ZodOptional<z.ZodObject<{
39
+ decoded_strings: z.ZodArray<z.ZodObject<{
40
+ string: z.ZodString;
41
+ offset: z.ZodNumber;
42
+ type: z.ZodString;
43
+ decoding_method: z.ZodNullable<z.ZodString>;
44
+ }, "strip", z.ZodTypeAny, {
45
+ string: string;
46
+ type: string;
47
+ offset: number;
48
+ decoding_method: string | null;
49
+ }, {
50
+ string: string;
51
+ type: string;
52
+ offset: number;
53
+ decoding_method: string | null;
54
+ }>, "many">;
55
+ count: z.ZodNumber;
56
+ timeout_occurred: z.ZodBoolean;
57
+ partial_results: z.ZodBoolean;
58
+ }, "strip", z.ZodTypeAny, {
59
+ count: number;
60
+ decoded_strings: {
61
+ string: string;
62
+ type: string;
63
+ offset: number;
64
+ decoding_method: string | null;
65
+ }[];
66
+ timeout_occurred: boolean;
67
+ partial_results: boolean;
68
+ }, {
69
+ count: number;
70
+ decoded_strings: {
71
+ string: string;
72
+ type: string;
73
+ offset: number;
74
+ decoding_method: string | null;
75
+ }[];
76
+ timeout_occurred: boolean;
77
+ partial_results: boolean;
78
+ }>>;
79
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
80
+ errors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
81
+ artifacts: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
82
+ metrics: z.ZodOptional<z.ZodObject<{
83
+ elapsed_ms: z.ZodNumber;
84
+ tool: z.ZodString;
85
+ }, "strip", z.ZodTypeAny, {
86
+ elapsed_ms: number;
87
+ tool: string;
88
+ }, {
89
+ elapsed_ms: number;
90
+ tool: string;
91
+ }>>;
92
+ }, "strip", z.ZodTypeAny, {
93
+ ok: boolean;
94
+ metrics?: {
95
+ elapsed_ms: number;
96
+ tool: string;
97
+ } | undefined;
98
+ data?: {
99
+ count: number;
100
+ decoded_strings: {
101
+ string: string;
102
+ type: string;
103
+ offset: number;
104
+ decoding_method: string | null;
105
+ }[];
106
+ timeout_occurred: boolean;
107
+ partial_results: boolean;
108
+ } | undefined;
109
+ warnings?: string[] | undefined;
110
+ errors?: string[] | undefined;
111
+ artifacts?: any[] | undefined;
112
+ }, {
113
+ ok: boolean;
114
+ metrics?: {
115
+ elapsed_ms: number;
116
+ tool: string;
117
+ } | undefined;
118
+ data?: {
119
+ count: number;
120
+ decoded_strings: {
121
+ string: string;
122
+ type: string;
123
+ offset: number;
124
+ decoding_method: string | null;
125
+ }[];
126
+ timeout_occurred: boolean;
127
+ partial_results: boolean;
128
+ } | undefined;
129
+ warnings?: string[] | undefined;
130
+ errors?: string[] | undefined;
131
+ artifacts?: any[] | undefined;
132
+ }>;
133
+ export type StringsFlossDecodeOutput = z.infer<typeof StringsFlossDecodeOutputSchema>;
134
+ /**
135
+ * Tool definition for strings.floss.decode
136
+ */
137
+ export declare const stringsFlossDecodeToolDefinition: ToolDefinition;
138
+ /**
139
+ * Create strings.floss.decode tool handler
140
+ * Requirements: 4.4, 4.5
141
+ */
142
+ export declare function createStringsFlossDecodeHandler(workspaceManager: WorkspaceManager, database: DatabaseManager, cacheManager: CacheManager): (args: ToolArgs) => Promise<WorkerResult>;
143
+ //# sourceMappingURL=strings-floss-decode.d.ts.map
@@ -0,0 +1,259 @@
1
+ /**
2
+ * strings.floss.decode tool implementation
3
+ * Uses FLOSS tool to decode obfuscated strings from PE files
4
+ * Requirements: 4.4, 4.5
5
+ */
6
+ import { z } from 'zod';
7
+ import { spawn } from 'child_process';
8
+ import path from 'path';
9
+ import { v4 as uuidv4 } from 'uuid';
10
+ import { generateCacheKey } from '../cache-manager.js';
11
+ import { resolvePackagePath } from '../runtime-paths.js';
12
+ import { lookupCachedResult, formatCacheWarning } from './cache-observability.js';
13
+ // ============================================================================
14
+ // Constants
15
+ // ============================================================================
16
+ const TOOL_NAME = 'strings.floss.decode';
17
+ const TOOL_VERSION = '1.0.0';
18
+ const CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
19
+ const DEFAULT_TIMEOUT = 60; // seconds
20
+ // ============================================================================
21
+ // Input/Output Schemas
22
+ // ============================================================================
23
+ /**
24
+ * Input schema for strings.floss.decode tool
25
+ * Requirements: 4.4, 4.5
26
+ */
27
+ export const StringsFlossDecodeInputSchema = z.object({
28
+ sample_id: z.string().describe('Sample ID (format: sha256:<hex>)'),
29
+ timeout: z.number().int().min(1).optional().default(DEFAULT_TIMEOUT).describe('Timeout in seconds (default: 60)'),
30
+ modes: z.array(z.enum(['static', 'stack', 'tight', 'decoded'])).optional().default(['decoded']).describe('Decoding modes to use'),
31
+ force_refresh: z
32
+ .boolean()
33
+ .optional()
34
+ .default(false)
35
+ .describe('Bypass cache lookup and recompute from source sample'),
36
+ });
37
+ /**
38
+ * Output schema for strings.floss.decode tool
39
+ * Requirements: 4.4, 4.5
40
+ */
41
+ export const StringsFlossDecodeOutputSchema = z.object({
42
+ ok: z.boolean(),
43
+ data: z.object({
44
+ decoded_strings: z.array(z.object({
45
+ string: z.string(),
46
+ offset: z.number(),
47
+ type: z.string(),
48
+ decoding_method: z.string().nullable(),
49
+ })),
50
+ count: z.number(),
51
+ timeout_occurred: z.boolean(),
52
+ partial_results: z.boolean(),
53
+ }).optional(),
54
+ warnings: z.array(z.string()).optional(),
55
+ errors: z.array(z.string()).optional(),
56
+ artifacts: z.array(z.any()).optional(),
57
+ metrics: z.object({
58
+ elapsed_ms: z.number(),
59
+ tool: z.string(),
60
+ }).optional(),
61
+ });
62
+ // ============================================================================
63
+ // Tool Definition
64
+ // ============================================================================
65
+ /**
66
+ * Tool definition for strings.floss.decode
67
+ */
68
+ export const stringsFlossDecodeToolDefinition = {
69
+ name: TOOL_NAME,
70
+ description: '使用 FLOSS 工具解码混淆字符串,支持多种解码模式(static、stack、tight、decoded)',
71
+ inputSchema: StringsFlossDecodeInputSchema,
72
+ outputSchema: StringsFlossDecodeOutputSchema,
73
+ };
74
+ /**
75
+ * Spawn Python Static Worker and communicate via stdin/stdout JSON protocol
76
+ *
77
+ * Requirements: Worker communication
78
+ *
79
+ * @param request - Worker request object
80
+ * @returns Worker response object
81
+ */
82
+ async function callStaticWorker(request) {
83
+ return new Promise((resolve, reject) => {
84
+ // Get Python worker path
85
+ const workerPath = resolvePackagePath('workers', 'static_worker.py');
86
+ // Spawn Python process
87
+ const pythonCommand = process.platform === 'win32' ? 'python' : 'python3';
88
+ const pythonProcess = spawn(pythonCommand, [workerPath], {
89
+ stdio: ['pipe', 'pipe', 'pipe'],
90
+ });
91
+ let stdout = '';
92
+ let stderr = '';
93
+ // Collect stdout
94
+ pythonProcess.stdout.on('data', (data) => {
95
+ stdout += data.toString();
96
+ });
97
+ // Collect stderr
98
+ pythonProcess.stderr.on('data', (data) => {
99
+ stderr += data.toString();
100
+ });
101
+ // Handle process exit
102
+ pythonProcess.on('close', (code) => {
103
+ if (code !== 0) {
104
+ reject(new Error(`Python worker exited with code ${code}. stderr: ${stderr}`));
105
+ return;
106
+ }
107
+ // Parse response from stdout
108
+ try {
109
+ const lines = stdout.trim().split('\n');
110
+ const lastLine = lines[lines.length - 1];
111
+ const response = JSON.parse(lastLine);
112
+ resolve(response);
113
+ }
114
+ catch (error) {
115
+ reject(new Error(`Failed to parse worker response: ${error.message}. stdout: ${stdout}`));
116
+ }
117
+ });
118
+ // Handle process error
119
+ pythonProcess.on('error', (error) => {
120
+ reject(new Error(`Failed to spawn Python worker: ${error.message}`));
121
+ });
122
+ // Send request to worker via stdin
123
+ try {
124
+ pythonProcess.stdin.write(JSON.stringify(request) + '\n');
125
+ pythonProcess.stdin.end();
126
+ }
127
+ catch (error) {
128
+ reject(new Error(`Failed to write to worker stdin: ${error.message}`));
129
+ }
130
+ });
131
+ }
132
+ // ============================================================================
133
+ // Tool Handler
134
+ // ============================================================================
135
+ /**
136
+ * Create strings.floss.decode tool handler
137
+ * Requirements: 4.4, 4.5
138
+ */
139
+ export function createStringsFlossDecodeHandler(workspaceManager, database, cacheManager) {
140
+ return async (args) => {
141
+ const input = args;
142
+ const startTime = Date.now();
143
+ try {
144
+ // 1. Generate cache key
145
+ const sample = database.findSample(input.sample_id);
146
+ if (!sample) {
147
+ return {
148
+ ok: false,
149
+ errors: [`Sample not found: ${input.sample_id}`],
150
+ };
151
+ }
152
+ const cacheKey = generateCacheKey({
153
+ sampleSha256: sample.sha256,
154
+ toolName: TOOL_NAME,
155
+ toolVersion: TOOL_VERSION,
156
+ args: {
157
+ timeout: input.timeout,
158
+ modes: input.modes,
159
+ },
160
+ });
161
+ // 2. Check cache
162
+ if (!input.force_refresh) {
163
+ const cachedLookup = await lookupCachedResult(cacheManager, cacheKey);
164
+ if (cachedLookup) {
165
+ return {
166
+ ok: true,
167
+ data: cachedLookup.data,
168
+ warnings: ['Result from cache', formatCacheWarning(cachedLookup.metadata)],
169
+ metrics: {
170
+ elapsed_ms: Date.now() - startTime,
171
+ tool: TOOL_NAME,
172
+ cached: true,
173
+ cache_key: cachedLookup.metadata.key,
174
+ cache_tier: cachedLookup.metadata.tier,
175
+ cache_created_at: cachedLookup.metadata.createdAt,
176
+ cache_expires_at: cachedLookup.metadata.expiresAt,
177
+ cache_hit_at: cachedLookup.metadata.fetchedAt,
178
+ },
179
+ };
180
+ }
181
+ }
182
+ // 3. Get sample path from workspace
183
+ const workspace = await workspaceManager.getWorkspace(input.sample_id);
184
+ // Find the sample file in the original directory
185
+ const fs = await import('fs/promises');
186
+ const files = await fs.readdir(workspace.original);
187
+ if (files.length === 0) {
188
+ return {
189
+ ok: false,
190
+ errors: ['Sample file not found in workspace'],
191
+ };
192
+ }
193
+ const samplePath = path.join(workspace.original, files[0]);
194
+ // 4. Prepare worker request
195
+ const workerRequest = {
196
+ job_id: uuidv4(),
197
+ tool: TOOL_NAME,
198
+ sample: {
199
+ sample_id: input.sample_id,
200
+ path: samplePath,
201
+ },
202
+ args: {
203
+ timeout: input.timeout,
204
+ modes: input.modes,
205
+ },
206
+ context: {
207
+ request_time_utc: new Date().toISOString(),
208
+ policy: {
209
+ allow_dynamic: false,
210
+ allow_network: false,
211
+ },
212
+ versions: {
213
+ tool_version: TOOL_VERSION,
214
+ },
215
+ },
216
+ };
217
+ // 5. Call Static Worker
218
+ // Requirements: 4.4, 4.5
219
+ const workerResponse = await callStaticWorker(workerRequest);
220
+ if (!workerResponse.ok) {
221
+ return {
222
+ ok: false,
223
+ errors: workerResponse.errors,
224
+ warnings: workerResponse.warnings,
225
+ };
226
+ }
227
+ // 6. Cache result (only if not timeout or partial)
228
+ const responseData = workerResponse.data;
229
+ if (!responseData.timeout_occurred && !responseData.partial_results) {
230
+ await cacheManager.setCachedResult(cacheKey, workerResponse.data, CACHE_TTL_MS);
231
+ }
232
+ // 7. Return result
233
+ return {
234
+ ok: true,
235
+ data: workerResponse.data,
236
+ warnings: input.force_refresh
237
+ ? ['force_refresh=true; bypassed cache lookup', ...(workerResponse.warnings || [])]
238
+ : workerResponse.warnings,
239
+ errors: workerResponse.errors,
240
+ artifacts: workerResponse.artifacts,
241
+ metrics: {
242
+ ...workerResponse.metrics,
243
+ elapsed_ms: Date.now() - startTime,
244
+ },
245
+ };
246
+ }
247
+ catch (error) {
248
+ return {
249
+ ok: false,
250
+ errors: [error.message],
251
+ metrics: {
252
+ elapsed_ms: Date.now() - startTime,
253
+ tool: TOOL_NAME,
254
+ },
255
+ };
256
+ }
257
+ };
258
+ }
259
+ //# sourceMappingURL=strings-floss-decode.js.map