rea-agents 0.5.0 → 1.0.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/README.md +12 -0
- package/dist/application/EnhancedTools.js +44 -36
- package/dist/application/Upgrade.js +106 -0
- package/dist/cli.js +5 -0
- package/dist/contracts/toolContracts.js +3 -3
- package/dist/contracts/toolOutputSchemas.js +48 -10
- package/dist/domain/errors.js +26 -0
- package/dist/domain/hopperValues.js +2 -0
- package/dist/native/NativeMacOSProvider.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,6 +120,17 @@ rea doctor
|
|
|
120
120
|
rea analyze /Applications/Notes.app
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
+
Update that global installation in place:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
rea upgrade
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
REA checks npm for the latest release and verifies that the running package is
|
|
130
|
+
the global installation it will replace. Source, local, and `npx` copies report
|
|
131
|
+
the manual `npm install --global rea-agents@latest` command instead of updating
|
|
132
|
+
an unrelated global package.
|
|
133
|
+
|
|
123
134
|
Choose either the no-install commands or the global installation. You do not need both.
|
|
124
135
|
|
|
125
136
|
### Requirements
|
|
@@ -343,6 +354,7 @@ Or install the `rea` command globally:
|
|
|
343
354
|
```bash
|
|
344
355
|
npm install --global rea-agents
|
|
345
356
|
rea --help
|
|
357
|
+
rea upgrade
|
|
346
358
|
rea mcp
|
|
347
359
|
```
|
|
348
360
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { enhancedInputSchemas } from "../contracts/enhancedInputs.js";
|
|
2
|
-
import { AnalysisInputError, AnalysisCancelledError, AnalysisOutputError, } from "../domain/errors.js";
|
|
3
|
-
import { parseDocuments, parseFunctionDossier, parseAddressedPage, parseListCount, parseRelatedAddresses, parseSegments, } from "../domain/hopperValues.js";
|
|
2
|
+
import { AnalysisInputError, AnalysisCancelledError, AnalysisOutputError, projectAnalysisError, } from "../domain/errors.js";
|
|
3
|
+
import { addressDistance, parseDocuments, parseFunctionDossier, parseAddressedPage, parseListCount, parseRelatedAddresses, parseSegments, } from "../domain/hopperValues.js";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
5
|
import { categorizeSwiftTypes, discoverObjcClasses, discoverObjcProtocols, discoverSwiftClasses, } from "../domain/symbolAnalysis.js";
|
|
6
6
|
/**
|
|
@@ -89,20 +89,29 @@ export class EnhancedTools {
|
|
|
89
89
|
return names.ok ? ok(discoverObjcProtocols(names.value)) : names;
|
|
90
90
|
}
|
|
91
91
|
async #batchDecompile(addresses, signal) {
|
|
92
|
-
|
|
93
|
-
return ok({ error: "No addresses provided" });
|
|
94
|
-
const entries = await Promise.all(addresses.map(async (address) => {
|
|
92
|
+
const items = await Promise.all(addresses.map(async (address) => {
|
|
95
93
|
const result = await this.#call("procedure_pseudo_code", { procedure: address }, signal);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
if (!result.ok)
|
|
95
|
+
return {
|
|
96
|
+
address,
|
|
97
|
+
status: "error",
|
|
98
|
+
error: projectAnalysisError(result.error),
|
|
99
|
+
};
|
|
100
|
+
if (typeof result.value !== "string" || result.value.length === 0)
|
|
101
|
+
return {
|
|
102
|
+
address,
|
|
103
|
+
status: "error",
|
|
104
|
+
error: projectAnalysisError(new AnalysisOutputError("procedure_pseudo_code", "provider returned empty pseudocode")),
|
|
105
|
+
};
|
|
106
|
+
return { address, status: "ok", pseudocode: result.value };
|
|
104
107
|
}));
|
|
105
|
-
|
|
108
|
+
const succeeded = items.filter(({ status }) => status === "ok").length;
|
|
109
|
+
return ok({
|
|
110
|
+
items,
|
|
111
|
+
total: items.length,
|
|
112
|
+
succeeded,
|
|
113
|
+
failed: items.length - succeeded,
|
|
114
|
+
});
|
|
106
115
|
}
|
|
107
116
|
async #callGraph(input, signal) {
|
|
108
117
|
const relation = input.direction === "forward" ? "callees" : "callers";
|
|
@@ -124,7 +133,8 @@ export class EnhancedTools {
|
|
|
124
133
|
if (!result.ok) {
|
|
125
134
|
graph[level].push({
|
|
126
135
|
address: current.address,
|
|
127
|
-
|
|
136
|
+
status: "error",
|
|
137
|
+
error: projectAnalysisError(result.error),
|
|
128
138
|
});
|
|
129
139
|
continue;
|
|
130
140
|
}
|
|
@@ -132,12 +142,14 @@ export class EnhancedTools {
|
|
|
132
142
|
if (!related.ok) {
|
|
133
143
|
graph[level].push({
|
|
134
144
|
address: current.address,
|
|
135
|
-
|
|
145
|
+
status: "error",
|
|
146
|
+
error: projectAnalysisError(related.error),
|
|
136
147
|
});
|
|
137
148
|
continue;
|
|
138
149
|
}
|
|
139
150
|
graph[level].push({
|
|
140
151
|
address: current.address,
|
|
152
|
+
status: "ok",
|
|
141
153
|
calls: [...related.value],
|
|
142
154
|
});
|
|
143
155
|
if (current.depth + 1 < input.depth) {
|
|
@@ -158,16 +170,24 @@ export class EnhancedTools {
|
|
|
158
170
|
: procedures;
|
|
159
171
|
}
|
|
160
172
|
async #findXrefs(name, signal) {
|
|
161
|
-
const
|
|
162
|
-
if (!
|
|
163
|
-
return
|
|
164
|
-
const
|
|
165
|
-
if (
|
|
166
|
-
return ok({
|
|
167
|
-
const xrefs = await this.#call("xrefs", { address }, signal);
|
|
173
|
+
const names = await this.#allAddressed("list_names", signal);
|
|
174
|
+
if (!names.ok)
|
|
175
|
+
return names;
|
|
176
|
+
const resolved = names.value.find((entry) => entry.name === name);
|
|
177
|
+
if (resolved === undefined)
|
|
178
|
+
return ok({ status: "unresolved", name, reason: "name_not_found" });
|
|
179
|
+
const xrefs = await this.#call("xrefs", { address: resolved.address }, signal);
|
|
168
180
|
if (!xrefs.ok)
|
|
169
181
|
return xrefs;
|
|
170
|
-
|
|
182
|
+
if (!Array.isArray(xrefs.value) ||
|
|
183
|
+
xrefs.value.some((xref) => typeof xref !== "string"))
|
|
184
|
+
return err(new AnalysisOutputError("xrefs", "provider returned an invalid address list"));
|
|
185
|
+
return ok({
|
|
186
|
+
status: "resolved",
|
|
187
|
+
name,
|
|
188
|
+
address: resolved.address,
|
|
189
|
+
xrefs: xrefs.value,
|
|
190
|
+
});
|
|
171
191
|
}
|
|
172
192
|
async #binaryOverview(input, signal) {
|
|
173
193
|
const [segmentsResult, documentsResult, procedures, stringsResult] = await Promise.all([
|
|
@@ -346,15 +366,3 @@ export class EnhancedTools {
|
|
|
346
366
|
const invalidInput = (name, cause) => Promise.resolve(err(new AnalysisInputError(name, {
|
|
347
367
|
cause,
|
|
348
368
|
})));
|
|
349
|
-
const resolveAddress = (value) => {
|
|
350
|
-
if (typeof value === "string" && value.length > 0)
|
|
351
|
-
return value;
|
|
352
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
353
|
-
return undefined;
|
|
354
|
-
}
|
|
355
|
-
const candidate = value.address ?? value.name;
|
|
356
|
-
return typeof candidate === "string" && candidate.length > 0
|
|
357
|
-
? candidate
|
|
358
|
-
: undefined;
|
|
359
|
-
};
|
|
360
|
-
const addressDistance = (start, end) => Math.max(0, Number.parseInt(end, 16) - Number.parseInt(start, 16));
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { basename, dirname, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { PRODUCT_IDENTITY } from "../identity.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
const registryResponseSchema = z.object({ version: z.string().min(1) });
|
|
10
|
+
const UPGRADE_COMMAND = "npm install --global rea-agents@latest";
|
|
11
|
+
/** Check the npm registry and update the same global REA installation. */
|
|
12
|
+
export const runUpgrade = async (currentVersion, host = systemUpgradeHost(), output = "human") => {
|
|
13
|
+
const latestVersion = await host.latestVersion();
|
|
14
|
+
if (latestVersion === currentVersion)
|
|
15
|
+
return {
|
|
16
|
+
status: "current",
|
|
17
|
+
currentVersion,
|
|
18
|
+
latestVersion,
|
|
19
|
+
installMethod: "npm",
|
|
20
|
+
};
|
|
21
|
+
const installation = await host.installation();
|
|
22
|
+
if (installation === undefined)
|
|
23
|
+
return {
|
|
24
|
+
status: "failed",
|
|
25
|
+
currentVersion,
|
|
26
|
+
latestVersion: latestVersion ?? null,
|
|
27
|
+
reason: "unknown-install-method",
|
|
28
|
+
remediation: `Update manually with: ${UPGRADE_COMMAND}`,
|
|
29
|
+
};
|
|
30
|
+
if (!(await host.installLatest(installation, output)))
|
|
31
|
+
return {
|
|
32
|
+
status: "failed",
|
|
33
|
+
currentVersion,
|
|
34
|
+
latestVersion: latestVersion ?? null,
|
|
35
|
+
reason: "install",
|
|
36
|
+
remediation: `${UPGRADE_COMMAND} failed.`,
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
status: "upgraded",
|
|
40
|
+
previousVersion: currentVersion,
|
|
41
|
+
latestVersion: latestVersion ?? null,
|
|
42
|
+
versionCheck: latestVersion === undefined ? "unavailable" : "available",
|
|
43
|
+
installMethod: "npm",
|
|
44
|
+
command: UPGRADE_COMMAND,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/** Create the npm registry and subprocess effects for a production upgrade. */
|
|
48
|
+
export const systemUpgradeHost = () => ({
|
|
49
|
+
latestVersion: async () => {
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(`https://registry.npmjs.org/${PRODUCT_IDENTITY.packageName}/latest`, { signal: AbortSignal.timeout(10_000) });
|
|
52
|
+
if (!response.ok)
|
|
53
|
+
return undefined;
|
|
54
|
+
const parsed = registryResponseSchema.safeParse(await response.json());
|
|
55
|
+
return parsed.success ? parsed.data.version : undefined;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
installation: () => detectNpmInstallation(fileURLToPath(new URL("../..", import.meta.url)), systemNpmInstallationHost),
|
|
62
|
+
installLatest: ({ prefix }, output) => runCommand("npm", [
|
|
63
|
+
"install",
|
|
64
|
+
"--global",
|
|
65
|
+
"--prefix",
|
|
66
|
+
prefix,
|
|
67
|
+
`${PRODUCT_IDENTITY.packageName}@latest`,
|
|
68
|
+
], output),
|
|
69
|
+
});
|
|
70
|
+
const systemNpmInstallationHost = {
|
|
71
|
+
canonicalPath: realpath,
|
|
72
|
+
globalRoot: async () => (await execFileAsync("npm", ["root", "--global"])).stdout.trim(),
|
|
73
|
+
globalPrefix: async () => (await execFileAsync("npm", ["prefix", "--global"])).stdout.trim(),
|
|
74
|
+
};
|
|
75
|
+
/** Identify the npm prefix only when it owns the running package. */
|
|
76
|
+
export const detectNpmInstallation = async (packageRoot, host) => {
|
|
77
|
+
try {
|
|
78
|
+
const canonicalPackageRoot = await host.canonicalPath(packageRoot);
|
|
79
|
+
const npmRoot = await host.globalRoot();
|
|
80
|
+
const globalPackageRoot = await host.canonicalPath(resolve(npmRoot, PRODUCT_IDENTITY.packageName));
|
|
81
|
+
if (canonicalPackageRoot === globalPackageRoot) {
|
|
82
|
+
const prefix = await host.globalPrefix();
|
|
83
|
+
return prefix.length === 0 ? undefined : { prefix };
|
|
84
|
+
}
|
|
85
|
+
return inferUnixGlobalPrefix(canonicalPackageRoot);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return inferUnixGlobalPrefix(packageRoot);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const inferUnixGlobalPrefix = (packageRoot) => {
|
|
92
|
+
const nodeModules = dirname(packageRoot);
|
|
93
|
+
const library = dirname(nodeModules);
|
|
94
|
+
if (basename(packageRoot) !== PRODUCT_IDENTITY.packageName ||
|
|
95
|
+
basename(nodeModules) !== "node_modules" ||
|
|
96
|
+
basename(library) !== "lib")
|
|
97
|
+
return undefined;
|
|
98
|
+
return { prefix: dirname(library) };
|
|
99
|
+
};
|
|
100
|
+
const runCommand = (command, arguments_, output) => new Promise((resolveResult) => {
|
|
101
|
+
const child = spawn(command, [...arguments_], {
|
|
102
|
+
stdio: output === "human" ? "inherit" : ["inherit", process.stderr, "inherit"],
|
|
103
|
+
});
|
|
104
|
+
child.once("error", () => resolveResult(false));
|
|
105
|
+
child.once("exit", (code) => resolveResult(code === 0));
|
|
106
|
+
});
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { runDoctor } from "./application/Doctor.js";
|
|
|
4
4
|
import { runDirectAnalysis, runProviderAnalysis, runSessionStatus, } from "./application/DirectAnalysis.js";
|
|
5
5
|
import { runSetup } from "./application/Setup.js";
|
|
6
6
|
import { runUninstall } from "./application/Uninstall.js";
|
|
7
|
+
import { runUpgrade, systemUpgradeHost } from "./application/Upgrade.js";
|
|
7
8
|
import { PRODUCT_IDENTITY } from "./identity.js";
|
|
8
9
|
import { createLogger, parseLogLevel } from "./logger.js";
|
|
9
10
|
import { logCliCommand } from "./cliLogging.js";
|
|
@@ -82,6 +83,10 @@ const registerCoreCommands = (cli, logger) => {
|
|
|
82
83
|
alias: { purgeData: "purge-data" },
|
|
83
84
|
run: ({ options }) => logCliCommand(logger, "uninstall", () => runUninstall(options.purgeData)),
|
|
84
85
|
});
|
|
86
|
+
cli.command("upgrade", {
|
|
87
|
+
description: "Upgrade a global npm installation to the latest REA release",
|
|
88
|
+
run: ({ formatExplicit }) => logCliCommand(logger, "upgrade", () => runUpgrade(process.env.REA_PACKAGE_VERSION ?? "0.0.0-development", systemUpgradeHost(), formatExplicit ? "structured" : "human")),
|
|
89
|
+
});
|
|
85
90
|
cli.command("analyze", {
|
|
86
91
|
description: "Get an overview of an app",
|
|
87
92
|
args: z.object({
|
|
@@ -146,10 +146,10 @@ export const ENHANCED_TOOL_CONTRACTS = [
|
|
|
146
146
|
enhanced("swift_classes", "Discover legacy-mangled Swift class procedures after exhaustively paging analyzed procedures. Returns at most 100 entries and scans at most 5,000 symbols; use analyze_swift_types for other Swift kinds.", enhancedInputSchemas.swift_classes),
|
|
147
147
|
enhanced("get_objc_classes", "Discover and deduplicate Objective-C class labels after exhaustively paging names, optionally filtering by literal substring. Returns at most 100 classes; inspect matching metadata and references next.", enhancedInputSchemas.get_objc_classes),
|
|
148
148
|
enhanced("get_objc_protocols", "Discover and deduplicate Objective-C and Swift protocol labels after exhaustively paging names. Returns at most 100 entries; use xrefs or analyze_function to connect a protocol to implementations.", enhancedInputSchemas.get_objc_protocols),
|
|
149
|
-
enhanced("batch_decompile", "Decompile up to 20 explicit procedure symbols or addresses concurrently.
|
|
150
|
-
enhanced("get_call_graph", "Traverse Hopper's caller or callee relationships from one symbol or address for at most five levels.
|
|
149
|
+
enhanced("batch_decompile", "Decompile up to 20 explicit procedure symbols or addresses concurrently. Returns ordered per-item ok/error variants and aggregate counts; use analyze_function for a richer single-function dossier.", enhancedInputSchemas.batch_decompile),
|
|
150
|
+
enhanced("get_call_graph", "Traverse Hopper's caller or callee relationships from one symbol or address for at most five levels. Every node has an ok/error status and failures use safe typed projections; indirect calls may be missing and results are not a whole-program CFG.", enhancedInputSchemas.get_call_graph),
|
|
151
151
|
enhanced("analyze_swift_types", "Categorize exhaustively paged procedure names into Swift classes, structs, enums, protocols, extensions, and other symbols. Scans at most 5,000 names and returns at most 50 entries per category.", enhancedInputSchemas.analyze_swift_types),
|
|
152
|
-
enhanced("find_xrefs_to_name", "Resolve
|
|
152
|
+
enhanced("find_xrefs_to_name", "Resolve an exact name through Hopper's exhaustively paged name inventory and return a resolved or unresolved result. Unresolved names use the stable name_not_found reason; xrefs remain untyped.", enhancedInputSchemas.find_xrefs_to_name),
|
|
153
153
|
enhanced("binary_overview", "Use immediately after opening a target to summarize document, exhaustive procedure/string counts, and a bounded segment sample. detail controls segment fields and limit controls only the returned segment sample.", enhancedInputSchemas.binary_overview),
|
|
154
154
|
enhanced("analyze_function", "Preferred bounded analysis for one procedure symbol or address. Returns identity, pseudocode, optional assembly, comments, calls, incoming references, and blocks; unsupported outgoing references and CFG edges carry explicit unavailable metadata.", enhancedInputSchemas.analyze_function),
|
|
155
155
|
enhanced("trace_feature", "Trace a bounded literal feature query through matching strings and procedures, xrefs, and truthful containing-procedure resolution. Returns the operation budget, truncation, and residual unknowns; unknown_registry_approved: true records them durably without inferring reference kinds.", enhancedInputSchemas.trace_feature),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { ANALYSIS_ERROR_TAGS } from "../domain/errors.js";
|
|
2
3
|
import { evidenceSchema } from "../domain/evidence.js";
|
|
3
4
|
import { processCaptureComparisonSchema, processCaptureSchema, } from "../domain/processCapture.js";
|
|
4
5
|
import { evidenceBundleSchema } from "../domain/evidenceBundle.js";
|
|
@@ -149,9 +150,24 @@ const symbolDiscoveryOutput = (property) => resultOf(z.object({
|
|
|
149
150
|
count: z.number().int().min(0),
|
|
150
151
|
[property]: z.array(addressedEntry),
|
|
151
152
|
}));
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
const analysisErrorProjectionSchema = z
|
|
154
|
+
.object({
|
|
155
|
+
tag: z.enum(ANALYSIS_ERROR_TAGS),
|
|
156
|
+
message: z.string(),
|
|
157
|
+
details: z.record(z.string(), z.union([z.string(), z.number(), z.null()])),
|
|
158
|
+
})
|
|
159
|
+
.strict();
|
|
160
|
+
const graphNode = z.discriminatedUnion("status", [
|
|
161
|
+
z.object({
|
|
162
|
+
address: z.string(),
|
|
163
|
+
status: z.literal("ok"),
|
|
164
|
+
calls: z.array(z.string()),
|
|
165
|
+
}),
|
|
166
|
+
z.object({
|
|
167
|
+
address: z.string(),
|
|
168
|
+
status: z.literal("error"),
|
|
169
|
+
error: analysisErrorProjectionSchema,
|
|
170
|
+
}),
|
|
155
171
|
]);
|
|
156
172
|
const functionDossierOutput = resultOf(functionDossierSchema);
|
|
157
173
|
/** Exact structured-content schemas for the direct Hopper operations. */
|
|
@@ -207,10 +223,23 @@ export const enhancedOutputSchemas = {
|
|
|
207
223
|
swift_classes: symbolDiscoveryOutput("classes"),
|
|
208
224
|
get_objc_classes: symbolDiscoveryOutput("classes"),
|
|
209
225
|
get_objc_protocols: symbolDiscoveryOutput("protocols"),
|
|
210
|
-
batch_decompile: resultOf(z.
|
|
211
|
-
z.
|
|
212
|
-
|
|
213
|
-
|
|
226
|
+
batch_decompile: resultOf(z.object({
|
|
227
|
+
items: z.array(z.discriminatedUnion("status", [
|
|
228
|
+
z.object({
|
|
229
|
+
address: z.string(),
|
|
230
|
+
status: z.literal("ok"),
|
|
231
|
+
pseudocode: z.string().min(1),
|
|
232
|
+
}),
|
|
233
|
+
z.object({
|
|
234
|
+
address: z.string(),
|
|
235
|
+
status: z.literal("error"),
|
|
236
|
+
error: analysisErrorProjectionSchema,
|
|
237
|
+
}),
|
|
238
|
+
])),
|
|
239
|
+
total: z.number().int().min(0),
|
|
240
|
+
succeeded: z.number().int().min(0),
|
|
241
|
+
failed: z.number().int().min(0),
|
|
242
|
+
})),
|
|
214
243
|
get_call_graph: resultOf(z.record(z.string(), z.array(graphNode))),
|
|
215
244
|
analyze_swift_types: resultOf(z.object({
|
|
216
245
|
total: z.number().int().min(0),
|
|
@@ -219,9 +248,18 @@ export const enhancedOutputSchemas = {
|
|
|
219
248
|
items: z.array(addressedEntry),
|
|
220
249
|
})),
|
|
221
250
|
})),
|
|
222
|
-
find_xrefs_to_name: resultOf(z.
|
|
223
|
-
z.object({
|
|
224
|
-
|
|
251
|
+
find_xrefs_to_name: resultOf(z.discriminatedUnion("status", [
|
|
252
|
+
z.object({
|
|
253
|
+
status: z.literal("resolved"),
|
|
254
|
+
name: z.string(),
|
|
255
|
+
address: z.string(),
|
|
256
|
+
xrefs: addressList,
|
|
257
|
+
}),
|
|
258
|
+
z.object({
|
|
259
|
+
status: z.literal("unresolved"),
|
|
260
|
+
name: z.string(),
|
|
261
|
+
reason: z.literal("name_not_found"),
|
|
262
|
+
}),
|
|
225
263
|
])),
|
|
226
264
|
binary_overview: resultOf(z.object({
|
|
227
265
|
document: z.string(),
|
package/dist/domain/errors.js
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
/** Stable tags exposed by safe analysis-error projections. */
|
|
2
|
+
export const ANALYSIS_ERROR_TAGS = [
|
|
3
|
+
"AnalysisProtocolError",
|
|
4
|
+
"AnalysisInputError",
|
|
5
|
+
"AnalysisOutputError",
|
|
6
|
+
"AnalysisCapabilityUnavailableError",
|
|
7
|
+
"AnalysisCancelledError",
|
|
8
|
+
"AnalysisTimeoutError",
|
|
9
|
+
"ProviderSelectionError",
|
|
10
|
+
"ProviderAdapterError",
|
|
11
|
+
"ArtifactOperationError",
|
|
12
|
+
"ProcessCaptureError",
|
|
13
|
+
"EvidenceIntegrityError",
|
|
14
|
+
"EvidenceLimitError",
|
|
15
|
+
"EvidenceFileError",
|
|
16
|
+
"UnknownRegistryError",
|
|
17
|
+
"HopperTimeoutError",
|
|
18
|
+
"HopperCancelledError",
|
|
19
|
+
"HopperProtocolError",
|
|
20
|
+
"HopperRemoteError",
|
|
21
|
+
"HopperProcessError",
|
|
22
|
+
"HopperStartError",
|
|
23
|
+
"ConfigurationError",
|
|
24
|
+
"NoBinaryOpenError",
|
|
25
|
+
"BinaryTargetError",
|
|
26
|
+
];
|
|
1
27
|
/** Base class for expected analysis, provider, and session failures. */
|
|
2
28
|
export class AnalysisError extends Error {
|
|
3
29
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AnalysisOutputError, HopperProtocolError } from "./errors.js";
|
|
3
3
|
import { err, ok } from "./result.js";
|
|
4
|
+
/** Return the non-negative byte distance between hexadecimal addresses. */
|
|
5
|
+
export const addressDistance = (start, end) => Math.max(0, Number.parseInt(end, 16) - Number.parseInt(start, 16));
|
|
4
6
|
const procedureMapSchema = z.record(z.string(), z.string());
|
|
5
7
|
const addressedNamesSchema = z.array(z.object({ address: z.string(), name: z.string() }));
|
|
6
8
|
const addressedNameMapSchema = z.record(z.string(), z.string());
|
|
@@ -81,6 +81,8 @@ class NativeMacOSClient {
|
|
|
81
81
|
this.runner = runner;
|
|
82
82
|
}
|
|
83
83
|
async execute(operation, parameters, options) {
|
|
84
|
+
if (options?.signal?.aborted === true)
|
|
85
|
+
return err(new AnalysisCancelledError(operation));
|
|
84
86
|
if (operation === "health")
|
|
85
87
|
return ok(createAnalysisExecution(null, IDENTITY));
|
|
86
88
|
if (!isNativeOperation(operation))
|