mirror of
https://github.com/morluto/rea.git
synced 2026-11-10 08:47:00 +00:00
109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
import { permitsCapabilityFallback } from "../CapabilityFallback.js";
|
|
import { nativeInventoryRowsSchemas } from "../../domain/native/nativeInventory.js";
|
|
import {
|
|
nativeDispatchMetadataResultSchema,
|
|
inspectNativeDispatchMetadata,
|
|
} from "../../domain/native/objcSwiftMetadata.js";
|
|
import { AnalysisOutputError } from "../../domain/analysisErrorCore.js";
|
|
import { jsonValueSchema } from "../../domain/jsonValue.js";
|
|
import { err, ok } from "../../domain/result.js";
|
|
import type { AnalysisOperationPort } from "../AnalysisProvider.js";
|
|
import type { EnhancedResult } from "../EnhancedToolTypes.js";
|
|
|
|
const dispatchNameInventorySchema = nativeInventoryRowsSchemas.names.element
|
|
.strict()
|
|
.array();
|
|
|
|
/** Source operations for this workflow, shared with capability discovery. */
|
|
export const NATIVE_DISPATCH_METADATA_SOURCES = {
|
|
binary: "inspect_native_dispatch_metadata",
|
|
symbols: "list_names",
|
|
} as const;
|
|
|
|
/** Prefer validated binary metadata, otherwise preserve the bound provider's symbol-only coverage. */
|
|
export const inspectNativeDispatch = async (
|
|
analysis: AnalysisOperationPort,
|
|
maxRecords: number,
|
|
options: {
|
|
readonly signal?: AbortSignal | undefined;
|
|
readonly objcClassImportAddresses?: readonly string[] | undefined;
|
|
readonly objcClassImportAddressesComplete?: boolean | undefined;
|
|
/** Binary metadata input budget; symbol-only inventories ignore it. */
|
|
readonly maxInputBytes?: number | undefined;
|
|
} = {},
|
|
): EnhancedResult => {
|
|
const {
|
|
signal,
|
|
objcClassImportAddresses,
|
|
objcClassImportAddressesComplete,
|
|
maxInputBytes,
|
|
} = options;
|
|
const input = {
|
|
max_records: maxRecords,
|
|
...(maxInputBytes === undefined ? {} : { max_input_bytes: maxInputBytes }),
|
|
...(objcClassImportAddresses === undefined
|
|
? {}
|
|
: {
|
|
objc_class_import_addresses: [...objcClassImportAddresses],
|
|
objc_class_import_addresses_complete:
|
|
objcClassImportAddressesComplete ?? true,
|
|
}),
|
|
};
|
|
const binaryMetadata = await analysis.execute(
|
|
NATIVE_DISPATCH_METADATA_SOURCES.binary,
|
|
input,
|
|
signal === undefined ? {} : { signal },
|
|
);
|
|
if (binaryMetadata.ok)
|
|
return ok(
|
|
jsonValueSchema.parse(
|
|
nativeDispatchMetadataResultSchema.parse(binaryMetadata.value.result),
|
|
),
|
|
);
|
|
if (!permitsCapabilityFallback(binaryMetadata.error))
|
|
return err(binaryMetadata.error);
|
|
const execution = await analysis.execute(
|
|
NATIVE_DISPATCH_METADATA_SOURCES.symbols,
|
|
{},
|
|
signal === undefined ? {} : { signal },
|
|
);
|
|
if (!execution.ok) return err(execution.error);
|
|
const names = dispatchNameInventorySchema.safeParse(execution.value.result);
|
|
if (!names.success)
|
|
return err(
|
|
new AnalysisOutputError(
|
|
NATIVE_DISPATCH_METADATA_SOURCES.symbols,
|
|
"provider returned an invalid inventory",
|
|
),
|
|
);
|
|
const result = inspectNativeDispatchMetadata(
|
|
names.data.map((entry) => ({
|
|
address: entry.address,
|
|
name: entry.value,
|
|
})),
|
|
maxRecords,
|
|
);
|
|
if (objcClassImportAddresses !== undefined) {
|
|
result.objc_class_import_bindings = [];
|
|
result.objc_class_import_binding_coverage = {
|
|
facet: "objc_class_import_bindings",
|
|
status: "unsupported",
|
|
reason: "Native Mach-O pointer binding inspection is unavailable.",
|
|
examined: 0,
|
|
decoded: 0,
|
|
};
|
|
}
|
|
return ok(
|
|
jsonValueSchema.parse(
|
|
nativeDispatchMetadataResultSchema.parse({
|
|
target_sha256: execution.value.subject?.sha256 ?? null,
|
|
target_architecture: execution.value.subject?.architecture ?? null,
|
|
provider: execution.value.provider,
|
|
analysis_profile_digest:
|
|
execution.value.analysisProfile?.digest ?? null,
|
|
result,
|
|
}),
|
|
),
|
|
);
|
|
};
|