Files
rea/src/application/AnalysisProvider.ts
T
N0zoM1z0andN0zoM1z0 21da71ec6d refactor(domain): remove provider-specific target and snapshot state
Move Hopper loader derivation and compatibility projection into the Hopper adapter so BinaryTarget carries only provider-neutral identity and format metadata.

Introduce bounded canonical analysis-profile commitments, exact provider/profile snapshot v2 bindings, legacy snapshot rejection guidance, and backward-compatible profiled Evidence v2 records. Partition cache and replay behavior by target, concrete provider build, and profile while preserving custom Hopper loader overrides.

Propagate profiles consistently through CLI, MCP, composed workflows, and session lifecycle; preserve the 78-tool contract and legacy loaderArgs response projection. Add migration documentation, generated API updates, property regressions, package verification, and real Hopper coverage.
2026-07-15 20:31:56 +09:00

140 lines
4.8 KiB
TypeScript

import type { BinaryTarget } from "../domain/binaryTarget.js";
import type { OfficialToolName } from "../contracts/toolContracts.js";
import type { EnhancedToolName } from "../contracts/enhancedInputs.js";
import type { NativeToolName } from "../contracts/nativeToolContracts.js";
import type { ArtifactToolName } from "../contracts/artifactToolContracts.js";
import type { AnalysisError } from "../domain/errors.js";
import type { AnalysisProfileCommitment } from "../domain/analysisProfile.js";
import type { JsonValue } from "../domain/jsonValue.js";
import type { Result } from "../domain/result.js";
import type { EvidenceLocation } from "../domain/evidence.js";
import type { EvidenceSubjectTarget } from "../domain/evidence.js";
import { jsonValueSchema } from "../domain/jsonValue.js";
import type { ProgressReporter } from "./ProgressReporter.js";
export interface ExecutionOptions {
readonly signal?: AbortSignal;
readonly progress?: ProgressReporter;
}
/** Closed operations accepted by provider-backed analysis sessions. */
export type AnalysisOperation =
| OfficialToolName
| EnhancedToolName
| NativeToolName
| ArtifactToolName
| "health";
/** Atomic successful provider observation with exact producing provenance. */
export interface AnalysisExecution {
readonly result: JsonValue;
readonly rawResult: JsonValue | null;
readonly provider: ProviderIdentity;
readonly analysisProfile?: AnalysisProfileCommitment;
readonly limitations: readonly string[];
readonly locations: readonly EvidenceLocation[];
readonly subject: EvidenceSubjectTarget | null;
}
/** Build a validated atomic provider observation at an adapter boundary. */
export const createAnalysisExecution = (
result: unknown,
provider: ProviderIdentity,
options: {
readonly rawResult?: unknown;
readonly analysisProfile?: AnalysisProfileCommitment;
readonly limitations?: readonly string[];
readonly locations?: readonly EvidenceLocation[];
readonly subject?: EvidenceSubjectTarget;
} = {},
): AnalysisExecution => ({
result: jsonValueSchema.parse(result),
rawResult:
options.rawResult === undefined
? jsonValueSchema.parse(result)
: jsonValueSchema.parse(options.rawResult),
provider,
...(options.analysisProfile === undefined
? {}
: { analysisProfile: structuredClone(options.analysisProfile) }),
limitations: [...(options.limitations ?? [])],
locations: [...(options.locations ?? [])],
subject: options.subject ?? null,
});
/** Provider-neutral application capability for one analysis operation. */
export interface AnalysisOperationPort {
execute(
operation: AnalysisOperation,
parameters: Readonly<Record<string, JsonValue>>,
options?: ExecutionOptions,
): Promise<Result<AnalysisExecution, AnalysisError>>;
}
/** Provider session bound to exactly one parsed artifact. */
export interface AnalysisClient extends AnalysisOperationPort {
close(): Promise<void>;
}
export type AnalysisClientFactory = (
target: BinaryTarget,
profile?: AnalysisProfileCommitment,
) => AnalysisClient;
export interface ProviderIdentity {
readonly id: string;
readonly name: string;
readonly version: string | null;
}
/** Profile plus opaque compatibility output resolved before provider startup. */
export interface AnalysisProfileResolution {
readonly profile: AnalysisProfileCommitment | null;
readonly compatibility: Readonly<Record<string, JsonValue>>;
}
interface CapabilityEffects {
readonly mutatesArtifact: boolean;
readonly launchesProcess: boolean;
readonly mayShowUi: boolean;
readonly mayAccessNetwork: boolean;
readonly mayWriteFilesystem: boolean;
readonly changesPermissions: boolean;
readonly requiresRoot: boolean;
}
type CapabilityAvailability =
| { readonly available: true; readonly reason: null }
| { readonly available: false; readonly reason: string };
interface CapabilityLimits {
readonly maxResults: number | null;
readonly maxPayloadBytes: number | null;
readonly timeoutMs: number | null;
}
export type CapabilityDescriptor = CapabilityAvailability & {
readonly provider: ProviderIdentity;
readonly operation: Exclude<AnalysisOperation, "health">;
readonly inputContractVersion: number;
readonly outputContractVersion: number;
readonly pagination: "none" | "offset" | "cursor";
readonly exhaustive: boolean;
readonly effects: CapabilityEffects;
readonly limits: CapabilityLimits;
readonly limitations: readonly string[];
};
/** Factory and capability declaration for an analysis implementation. */
export interface AnalysisProvider {
identity(): ProviderIdentity;
capabilities(): readonly CapabilityDescriptor[];
resolveAnalysisProfile?(
target: BinaryTarget,
): Promise<Result<AnalysisProfileResolution, AnalysisError>>;
createClient(
target: BinaryTarget,
profile?: AnalysisProfileCommitment,
): AnalysisClient;
}