rea-agents 2.2.0 → 2.4.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 +57 -10
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +162 -0
- package/dist/application/ArtifactExtraction.js +5 -1
- package/dist/application/ArtifactGraphConstruction.js +3 -15
- package/dist/application/ArtifactInventory/classify.js +5 -1
- package/dist/application/ArtifactInventory/reader.js +2 -0
- package/dist/application/BinarySession.js +9 -2
- package/dist/application/BinarySessionStatus.js +40 -1
- package/dist/application/CapabilityInventory.js +26 -3
- package/dist/application/CommandShimReplay.js +6 -3
- package/dist/application/CompositeProvider.js +5 -2
- package/dist/application/DirectAnalysis.js +1 -20
- package/dist/application/DirectAnalysisStatus.js +83 -0
- package/dist/application/Doctor.js +34 -25
- package/dist/application/DoctorDiagnostics.js +1 -4
- package/dist/application/DoctorProjection.js +43 -0
- package/dist/application/DoctorScope.js +102 -0
- package/dist/application/EvidenceReferenceResolver.js +26 -0
- package/dist/application/JavaScriptApplicationEvidence.js +1 -1
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +10 -1
- package/dist/application/JavaScriptApplicationService.js +3 -2
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +49 -1
- package/dist/application/JavaScriptArtifactReconstruction.js +7 -0
- package/dist/application/JavaScriptModuleRelationships.js +25 -1
- package/dist/application/JavaScriptReturnShapeProjection.js +111 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +294 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +144 -0
- package/dist/application/JavaScriptSemanticGraphEvidence.js +86 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +72 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +33 -0
- package/dist/application/JavaScriptSemanticTraceService.js +45 -0
- package/dist/application/LoopbackReplay.js +277 -133
- package/dist/application/LoopbackReplayRecorder.js +101 -0
- package/dist/application/PermissionAuthority.js +7 -3
- package/dist/application/ProcessCaptureEnvironment.js +26 -0
- package/dist/application/ProcessCaptureJournal.js +95 -0
- package/dist/application/ProcessCaptureLifecycle.js +25 -13
- package/dist/application/ProcessCheckpoints.js +35 -4
- package/dist/application/ProcessCli.js +26 -4
- package/dist/application/ProcessHarness.js +64 -83
- package/dist/application/ProcessNormalization.js +9 -2
- package/dist/application/ProcessReactiveCoordinator.js +225 -0
- package/dist/application/ProcessReactiveEffects.js +141 -0
- package/dist/application/ProcessReactiveHarness.js +85 -0
- package/dist/application/ProcessReactiveObservations.js +105 -0
- package/dist/application/ProcessSampling.js +2 -0
- package/dist/application/SessionProviderRouter.js +7 -6
- package/dist/application/Setup.js +11 -10
- package/dist/application/SetupPlan.js +1 -1
- package/dist/application/SetupRegistrationEnvironment.js +12 -0
- package/dist/application/TerminalRenderer.js +3 -1
- package/dist/browser/CdpEndpoint.js +37 -4
- package/dist/catalogIdentity.js +16 -7
- package/dist/cli/coreAnalysisCommands.js +34 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -0
- package/dist/cli/setupCommands.js +81 -32
- package/dist/cli/utilityCommands.js +10 -2
- package/dist/cliApplicationCommands.js +79 -16
- package/dist/cliCommandNames.js +3 -0
- package/dist/cliElectronCommands.js +23 -33
- package/dist/cliObservationOptions.js +1 -1
- package/dist/cliOutput.js +56 -0
- package/dist/cliProcessCommands.js +32 -1
- package/dist/cliSetup.js +30 -21
- package/dist/contracts/applicationToolContracts.js +54 -7
- package/dist/contracts/applicationWorkflowInputContracts.js +119 -0
- package/dist/contracts/electronToolContracts.js +53 -32
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +32 -9
- package/dist/contracts/processCaptureExample.js +1 -0
- package/dist/contracts/replayMachineExample.js +37 -0
- package/dist/contracts/toolContractExamples.js +2 -0
- package/dist/contracts/toolContracts.js +5 -1
- package/dist/contracts/toolEffects.js +3 -0
- package/dist/contracts/toolOutputSchemaGroups.js +2 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +43 -0
- package/dist/doctorRuntime.js +41 -0
- package/dist/domain/analysisErrorPresentation.js +5 -3
- package/dist/domain/analysisErrorProjection.js +7 -1
- package/dist/domain/analysisSnapshot.js +2 -0
- package/dist/domain/artifactGraph.js +2 -0
- package/dist/domain/binaryTarget.js +3 -6
- package/dist/domain/changedBehavior.js +5 -4
- package/dist/domain/completionLedgerGeneration.js +190 -0
- package/dist/domain/errors.js +4 -2
- package/dist/domain/evidence.js +2 -0
- package/dist/domain/evidenceCompletionLedger.js +113 -0
- package/dist/domain/hopperStartupFailure.js +9 -0
- package/dist/domain/javascriptApplicationAnalysis.js +44 -2
- package/dist/domain/javascriptExportShapeComparison.js +145 -0
- package/dist/domain/javascriptExportShapeComparisonIdentity.js +11 -0
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +277 -0
- package/dist/domain/javascriptExportShapeSelection.js +132 -0
- package/dist/domain/javascriptExportShapeVariants.js +272 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +2 -2
- package/dist/domain/javascriptSemanticAnalysis.js +17 -36
- package/dist/domain/javascriptSemanticCallResolution.js +129 -0
- package/dist/domain/javascriptSemanticCalls.js +269 -0
- package/dist/domain/javascriptSemanticGraph.js +356 -0
- package/dist/domain/javascriptSemanticGraphSchemas.js +329 -0
- package/dist/domain/javascriptSemanticGraphSerialization.js +23 -0
- package/dist/domain/javascriptSemanticIr.js +14 -1
- package/dist/domain/javascriptSemanticPrimitives.js +36 -0
- package/dist/domain/javascriptSemanticProjection.js +36 -4
- package/dist/domain/javascriptSemanticProvenance.js +29 -0
- package/dist/domain/javascriptSemanticQuery.js +294 -0
- package/dist/domain/javascriptSemanticQueryAssessment.js +74 -0
- package/dist/domain/javascriptSemanticQueryIdentity.js +86 -0
- package/dist/domain/javascriptSemanticQueryRelations.js +15 -0
- package/dist/domain/javascriptSemanticQuerySchemas.js +188 -0
- package/dist/domain/javascriptSemanticReturns.js +187 -0
- package/dist/domain/javascriptSemanticState.js +32 -0
- package/dist/domain/javascriptSemanticTraceSchemas.js +14 -0
- package/dist/domain/javascriptSemanticValues.js +54 -70
- package/dist/domain/processCapture.js +100 -0
- package/dist/domain/processCaptureReactiveValidation.js +175 -0
- package/dist/domain/processCaptureValidation.js +103 -12
- package/dist/domain/processComparison.js +78 -25
- package/dist/domain/processObservation.js +162 -0
- package/dist/domain/processReactiveCheckpointDataflow.js +32 -0
- package/dist/domain/processReactiveMatching.js +210 -0
- package/dist/domain/processReactiveRuntime.js +120 -0
- package/dist/domain/processReactiveScenario.js +361 -0
- package/dist/domain/processReactiveScenarioPreflight.js +120 -0
- package/dist/domain/processReactiveTransition.js +161 -0
- package/dist/domain/processScenario.js +33 -0
- package/dist/domain/processTraceComparison.js +43 -0
- package/dist/domain/processTraceDimensionProjection.js +50 -0
- package/dist/domain/processTraceEvaluation.js +312 -0
- package/dist/domain/processTraceSpecification.js +373 -0
- package/dist/domain/reconstructionVerification.js +5 -4
- package/dist/domain/replayMachine.js +18 -2
- package/dist/domain/replayMachineRun.js +216 -0
- package/dist/domain/replayMachineRuntime.js +88 -9
- package/dist/domain/staticRuntimeCorrelation.js +4 -2
- package/dist/domain/zipPackageFormat.js +20 -0
- package/dist/evaluation/CodexAgentEval.js +24 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +13 -2
- package/dist/ghidra/GhidraDiagnostics.js +1 -0
- package/dist/ghidra/GhidraLauncher.js +7 -3
- package/dist/ghidra/GhidraProvider.js +8 -1
- package/dist/hopper/BridgeLauncher.js +56 -14
- package/dist/hopper/HopperClient.js +23 -10
- package/dist/hopper/HopperDiagnostics.js +14 -0
- package/dist/hopper/HopperProcessDiagnostic.js +14 -0
- package/dist/hopper/HopperProvider.js +8 -1
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +72 -0
- package/dist/hopper/LinuxPrivateDisplayProbe.js +217 -0
- package/dist/main/transport.js +2 -0
- package/dist/mcpDoctor.js +310 -0
- package/dist/native/NativeMacOSProvider.js +1 -0
- package/dist/process/ProcessOwnership.js +200 -53
- package/dist/process/ProviderRunLineage.js +21 -0
- package/dist/server/createServer.js +4 -1
- package/dist/server/javascriptApplicationResult.js +22 -1
- package/dist/server/registerApplicationTools/characterization.js +3 -3
- package/dist/server/registerApplicationTools/compareExportShapes.js +37 -0
- package/dist/server/registerApplicationTools/compareVersions.js +12 -6
- package/dist/server/registerApplicationTools/controlledReplay.js +2 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -3
- package/dist/server/registerApplicationTools/helpers.js +37 -25
- package/dist/server/registerApplicationTools/traceFeature.js +9 -5
- package/dist/server/registerApplicationTools/traceSemantics.js +30 -0
- package/dist/server/registerApplicationTools.js +4 -0
- package/dist/server/registerEvidenceResources.js +5 -1
- package/dist/server/registerProcessComparisonTool.js +17 -7
- package/dist/server/registerReplayMachineTool.js +20 -0
- package/dist/server/registerSessionTools.js +12 -7
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/serverIdentity.js +19 -0
- package/package.json +62 -30
- package/scripts/hopper-demo-x11.py +459 -61
- package/scripts/prepack.mjs +55 -0
- package/scripts/prepare.mjs +28 -0
- package/scripts/rea.mjs +26 -5
- package/skills/reverse-engineer-anything/SKILL.md +4 -3
- package/skills/reverse-engineer-anything/references/javascript-applications.md +10 -0
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +2 -2
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ProcessCaptureError } from "./ProcessCaptureError.js";
|
|
2
|
+
import { ProcessReactiveCoordinator } from "./ProcessReactiveCoordinator.js";
|
|
3
|
+
import { executeProcessReactiveEffects, unsupportedProcessReactiveFeatures, } from "./ProcessReactiveEffects.js";
|
|
4
|
+
import { subscribeProcessReactiveObservations } from "./ProcessReactiveObservations.js";
|
|
5
|
+
import { normalizeProcessSamples, normalizeProcessShimEvent, redactProtocolEvents, } from "./ProcessNormalization.js";
|
|
6
|
+
const controlKind = (input) => input.kind === "observation" ? undefined : input.kind;
|
|
7
|
+
/** Reject reactive declarations the current process adapter cannot execute. */
|
|
8
|
+
export const assertSupportedReactiveScenario = (scenario) => {
|
|
9
|
+
if (scenario.reactive === null)
|
|
10
|
+
return;
|
|
11
|
+
const unsupported = unsupportedProcessReactiveFeatures(scenario.reactive);
|
|
12
|
+
if (unsupported.length === 0)
|
|
13
|
+
return;
|
|
14
|
+
throw new ProcessCaptureError(`reactive scenario requests unsupported features: ${unsupported.join(", ")}`);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Attach the serialized reactive runtime once the target PID is available.
|
|
18
|
+
*
|
|
19
|
+
* Subscription replays journal entries admitted during launcher startup before
|
|
20
|
+
* observing new records, so PID-dependent normalization cannot drop them.
|
|
21
|
+
*/
|
|
22
|
+
export const startProcessReactiveHarness = (options) => {
|
|
23
|
+
if (options.scenario.reactive === null)
|
|
24
|
+
return undefined;
|
|
25
|
+
const controls = [];
|
|
26
|
+
const coordinator = new ProcessReactiveCoordinator({
|
|
27
|
+
scenario: options.scenario.reactive,
|
|
28
|
+
executor: {
|
|
29
|
+
execute: (actions, signal) => executeProcessReactiveEffects({
|
|
30
|
+
terminal: options.terminal,
|
|
31
|
+
renderer: options.renderer,
|
|
32
|
+
checkpoints: options.checkpoints,
|
|
33
|
+
interactions: options.capture.interactions,
|
|
34
|
+
journal: options.capture.journal,
|
|
35
|
+
startedAtMs: options.started,
|
|
36
|
+
now: Date.now,
|
|
37
|
+
}, actions, signal),
|
|
38
|
+
},
|
|
39
|
+
onDecision: (decision, input) => {
|
|
40
|
+
const kind = controlKind(input);
|
|
41
|
+
if (kind === undefined || decision.kind !== "finished")
|
|
42
|
+
return;
|
|
43
|
+
controls.push({
|
|
44
|
+
sequence: controls.length,
|
|
45
|
+
kind,
|
|
46
|
+
after_capture_order: decision.snapshot.observations.at(-1)?.capture_order ?? -1,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
coordinator,
|
|
52
|
+
controls,
|
|
53
|
+
unsubscribe: subscribeProcessReactiveObservations({
|
|
54
|
+
journal: options.capture.journal,
|
|
55
|
+
frames: options.capture.frames,
|
|
56
|
+
interactions: options.capture.interactions,
|
|
57
|
+
checkpointAt: (index) => options.checkpoints.at(index),
|
|
58
|
+
processSampleAt: (index) => {
|
|
59
|
+
const rootPid = options.terminal()?.pid;
|
|
60
|
+
return rootPid === undefined
|
|
61
|
+
? undefined
|
|
62
|
+
: normalizeProcessSamples(options.capture.processSamples, options.scenario, rootPid)[index];
|
|
63
|
+
},
|
|
64
|
+
protocolEventAt: (index) => redactProtocolEvents(options.capture.protocolEvents().slice(index, index + 1), options.scenario)[0],
|
|
65
|
+
shimEventAt: (index) => {
|
|
66
|
+
const event = options.shimReplay.events[index];
|
|
67
|
+
const rootPid = options.terminal()?.pid;
|
|
68
|
+
return event === undefined || rootPid === undefined
|
|
69
|
+
? undefined
|
|
70
|
+
: normalizeProcessShimEvent(event, options.scenario, options.capture.temporaryRoot, rootPid);
|
|
71
|
+
},
|
|
72
|
+
sink: coordinator,
|
|
73
|
+
}),
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
/** Project internal reducer state into the stable Process Capture shape. */
|
|
77
|
+
export const projectProcessReactiveRun = (harness) => harness === undefined
|
|
78
|
+
? null
|
|
79
|
+
: {
|
|
80
|
+
status: harness.coordinator.snapshot.status,
|
|
81
|
+
outcome: harness.coordinator.snapshot.outcome,
|
|
82
|
+
active_state: harness.coordinator.snapshot.active_state,
|
|
83
|
+
transitions: harness.coordinator.snapshot.transitions,
|
|
84
|
+
controls: harness.controls,
|
|
85
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createProcessObservation, processObservationSubject, } from "../domain/processObservation.js";
|
|
2
|
+
const terminalObservation = (options, entry) => {
|
|
3
|
+
const value = options.frames[entry.index];
|
|
4
|
+
return value === undefined
|
|
5
|
+
? undefined
|
|
6
|
+
: createProcessObservation({
|
|
7
|
+
source: "terminal_raw",
|
|
8
|
+
source_sequence: value.sequence,
|
|
9
|
+
captured_at_ms: value.at_ms,
|
|
10
|
+
subject_id: null,
|
|
11
|
+
location: entry,
|
|
12
|
+
payload: value,
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const interactionObservation = (options, entry) => {
|
|
16
|
+
const value = options.interactions[entry.index];
|
|
17
|
+
return value === undefined
|
|
18
|
+
? undefined
|
|
19
|
+
: createProcessObservation({
|
|
20
|
+
source: "interaction",
|
|
21
|
+
source_sequence: value.sequence,
|
|
22
|
+
captured_at_ms: value.dispatched_at_ms,
|
|
23
|
+
subject_id: null,
|
|
24
|
+
location: entry,
|
|
25
|
+
payload: value,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const filesystemObservation = (options, entry) => {
|
|
29
|
+
const value = options.checkpointAt(entry.index);
|
|
30
|
+
return value === undefined
|
|
31
|
+
? undefined
|
|
32
|
+
: createProcessObservation({
|
|
33
|
+
source: "filesystem",
|
|
34
|
+
source_sequence: entry.index,
|
|
35
|
+
captured_at_ms: value.at_ms,
|
|
36
|
+
subject_id: processObservationSubject("filesystem", value),
|
|
37
|
+
location: entry,
|
|
38
|
+
payload: value,
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const processObservation = (options, entry) => {
|
|
42
|
+
const value = options.processSampleAt(entry.index);
|
|
43
|
+
return value === undefined
|
|
44
|
+
? undefined
|
|
45
|
+
: createProcessObservation({
|
|
46
|
+
source: "process",
|
|
47
|
+
source_sequence: entry.index,
|
|
48
|
+
captured_at_ms: value.at_ms,
|
|
49
|
+
subject_id: processObservationSubject("process", value),
|
|
50
|
+
location: entry,
|
|
51
|
+
payload: value,
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
const protocolObservation = (options, entry) => {
|
|
55
|
+
const value = options.protocolEventAt(entry.index);
|
|
56
|
+
return value === undefined
|
|
57
|
+
? undefined
|
|
58
|
+
: createProcessObservation({
|
|
59
|
+
source: value.protocol,
|
|
60
|
+
source_sequence: value.sequence,
|
|
61
|
+
captured_at_ms: value.at_ms,
|
|
62
|
+
subject_id: processObservationSubject(value.protocol, value),
|
|
63
|
+
location: entry,
|
|
64
|
+
payload: value,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
const shimObservation = (options, entry) => {
|
|
68
|
+
const normalized = options.shimEventAt(entry.index);
|
|
69
|
+
if (normalized === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
return createProcessObservation({
|
|
72
|
+
source: "shim",
|
|
73
|
+
source_sequence: normalized.sequence,
|
|
74
|
+
captured_at_ms: normalized.at_ms,
|
|
75
|
+
subject_id: processObservationSubject("shim", normalized),
|
|
76
|
+
location: entry,
|
|
77
|
+
payload: normalized,
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
const observationFor = (options, entry) => {
|
|
81
|
+
if (entry.collection === "frames")
|
|
82
|
+
return terminalObservation(options, entry);
|
|
83
|
+
if (entry.collection === "interaction_events")
|
|
84
|
+
return interactionObservation(options, entry);
|
|
85
|
+
if (entry.collection === "filesystem_checkpoints")
|
|
86
|
+
return filesystemObservation(options, entry);
|
|
87
|
+
if (entry.collection === "process_samples")
|
|
88
|
+
return processObservation(options, entry);
|
|
89
|
+
if (entry.collection === "protocol_events")
|
|
90
|
+
return protocolObservation(options, entry);
|
|
91
|
+
if (entry.collection === "shim_events")
|
|
92
|
+
return shimObservation(options, entry);
|
|
93
|
+
return undefined;
|
|
94
|
+
};
|
|
95
|
+
/** Subscribe the reactive coordinator to admitted normalized journal records. */
|
|
96
|
+
export const subscribeProcessReactiveObservations = (options) => {
|
|
97
|
+
const enqueue = (entry) => {
|
|
98
|
+
const observation = observationFor(options, entry);
|
|
99
|
+
if (observation !== undefined)
|
|
100
|
+
options.sink.enqueue({ kind: "observation", observation });
|
|
101
|
+
};
|
|
102
|
+
for (const entry of options.journal.entries)
|
|
103
|
+
enqueue(entry);
|
|
104
|
+
return options.journal.subscribe(enqueue);
|
|
105
|
+
};
|
|
@@ -366,7 +366,9 @@ export const startProcessSampler = (options) => {
|
|
|
366
366
|
continue;
|
|
367
367
|
}
|
|
368
368
|
lastObservations.set(value.pid, observation);
|
|
369
|
+
const index = samples.length;
|
|
369
370
|
samples.push(value);
|
|
371
|
+
options.recordEvent?.("process_samples", index);
|
|
370
372
|
}
|
|
371
373
|
})
|
|
372
374
|
.catch((cause) => {
|
|
@@ -86,7 +86,7 @@ export class SessionProviderRouter {
|
|
|
86
86
|
compatibility: {},
|
|
87
87
|
binding: null,
|
|
88
88
|
selection: undefined,
|
|
89
|
-
createClient: (target) => createLegacyClient(runtime, target, undefined),
|
|
89
|
+
createClient: (target, context) => createLegacyClient(runtime, target, undefined, context),
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
/** Resolve target routes before any provider client is created. */
|
|
@@ -122,7 +122,7 @@ export class SessionProviderRouter {
|
|
|
122
122
|
compatibility: normalized.value.compatibility,
|
|
123
123
|
binding: null,
|
|
124
124
|
selection: undefined,
|
|
125
|
-
createClient: (openedTarget) => createLegacyClient(runtime, openedTarget, normalized.value.profile ?? undefined),
|
|
125
|
+
createClient: (openedTarget, context) => createLegacyClient(runtime, openedTarget, normalized.value.profile ?? undefined, context),
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
/** Candidate status authoritative for the active or target-free route. */
|
|
@@ -156,12 +156,13 @@ const selectableRoute = (auxiliaryProviders, selection) => {
|
|
|
156
156
|
compatibility: structuredClone(binding?.compatibility ?? {}),
|
|
157
157
|
binding,
|
|
158
158
|
selection,
|
|
159
|
-
createClient: (target) => provider?.createClient(target, binding?.profile) ??
|
|
159
|
+
createClient: (target, context) => provider?.createClient(target, binding?.profile, context) ??
|
|
160
|
+
emptyClient(identity),
|
|
160
161
|
};
|
|
161
162
|
};
|
|
162
|
-
const createLegacyClient = (runtime, target, profile) => typeof runtime.provider === "function"
|
|
163
|
-
? runtime.provider(target, profile)
|
|
164
|
-
: runtime.provider.createClient(target, profile);
|
|
163
|
+
const createLegacyClient = (runtime, target, profile, context) => typeof runtime.provider === "function"
|
|
164
|
+
? runtime.provider(target, profile, context)
|
|
165
|
+
: runtime.provider.createClient(target, profile, context);
|
|
165
166
|
const emptyClient = (identity) => ({
|
|
166
167
|
execute: (operation) => operation === "health"
|
|
167
168
|
? Promise.resolve(ok({
|
|
@@ -13,6 +13,8 @@ import { discoverSetupActions } from "./SetupPlan.js";
|
|
|
13
13
|
import { clientConfigurationAligned, configureJsonClient, configureTomlClient, inspectClientConfiguration, } from "./SetupClientConfiguration.js";
|
|
14
14
|
export { configureJsonClient, configureTomlClient };
|
|
15
15
|
import { setupInstallFailure, } from "./SetupInstallFailure.js";
|
|
16
|
+
import { providerRegistrationEnvironment, registrationPermissionEnvironment, } from "./SetupRegistrationEnvironment.js";
|
|
17
|
+
export { registrationPermissionEnvironment } from "./SetupRegistrationEnvironment.js";
|
|
16
18
|
export { canonicalSkillNeedsInstall, installCanonicalSkill };
|
|
17
19
|
const registrationCommand = () => process.env.npm_command === "exec"
|
|
18
20
|
? PRODUCT_IDENTITY.mcpCommand.split(" ")
|
|
@@ -22,7 +24,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
22
24
|
const appliedActions = [];
|
|
23
25
|
let plannedActions = [];
|
|
24
26
|
const clients = {};
|
|
25
|
-
const fail = (remediation) => setupFailure(remediation, [host, plannedActions, appliedActions, clients]);
|
|
27
|
+
const fail = (remediation) => setupFailure(remediation, [host, plannedActions, appliedActions, clients], options.readinessScope);
|
|
26
28
|
const unsupported = await hostRemediation(host, options.installHopper);
|
|
27
29
|
if (unsupported !== undefined)
|
|
28
30
|
return fail(unsupported);
|
|
@@ -36,6 +38,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
36
38
|
proposeHopper: options.proposeHopper ?? true,
|
|
37
39
|
selectedClientIds: options.clientIds,
|
|
38
40
|
installSkillSelection: options.installSkill,
|
|
41
|
+
doctorScope: options.readinessScope,
|
|
39
42
|
});
|
|
40
43
|
if (discovery.blocker !== undefined)
|
|
41
44
|
return fail(discovery.blocker);
|
|
@@ -61,6 +64,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
61
64
|
clients,
|
|
62
65
|
detectedClients,
|
|
63
66
|
providerEnvironment,
|
|
67
|
+
doctorScope: options.readinessScope,
|
|
64
68
|
});
|
|
65
69
|
if ("failure" in install)
|
|
66
70
|
return install.failure;
|
|
@@ -82,7 +86,7 @@ export const runSetup = async (options, host = systemSetupHost(), confirm) => {
|
|
|
82
86
|
if (selection.installSkill &&
|
|
83
87
|
!(await installSkillAction(host, options, appliedActions)))
|
|
84
88
|
return fail("REA analysis skill could not be installed or verified. Check permissions for `~/.agents/skills`, then rerun setup.");
|
|
85
|
-
const doctor = await host.doctor();
|
|
89
|
+
const doctor = await host.doctor(options.readinessScope);
|
|
86
90
|
const remediation = finalSetupRemediation(host.platform, appliedActions.includes("installed_hopper"), doctor.healthy, hopperPath);
|
|
87
91
|
return {
|
|
88
92
|
status: remediation === undefined ? "ready" : "needs_human",
|
|
@@ -143,7 +147,7 @@ const installHopperAction = async (input) => {
|
|
|
143
147
|
plannedActions: input.plannedActions,
|
|
144
148
|
appliedActions: input.appliedActions,
|
|
145
149
|
clients: input.clients,
|
|
146
|
-
doctor: await input.host.doctor(),
|
|
150
|
+
doctor: await input.host.doctor(input.doctorScope),
|
|
147
151
|
code: installed.code,
|
|
148
152
|
remediation: installed.remediation,
|
|
149
153
|
},
|
|
@@ -192,12 +196,12 @@ const installSkillAction = async (host, options, appliedActions) => {
|
|
|
192
196
|
});
|
|
193
197
|
return true;
|
|
194
198
|
};
|
|
195
|
-
const setupFailure = async (remediation, [host, plannedActions, appliedActions, clients]) => ({
|
|
199
|
+
const setupFailure = async (remediation, [host, plannedActions, appliedActions, clients], scope) => ({
|
|
196
200
|
status: "needs_human",
|
|
197
201
|
plannedActions,
|
|
198
202
|
appliedActions,
|
|
199
203
|
clients,
|
|
200
|
-
doctor: await host.doctor(),
|
|
204
|
+
doctor: await host.doctor(scope),
|
|
201
205
|
remediation,
|
|
202
206
|
});
|
|
203
207
|
const emitProgress = (options, event) => options.onProgress?.(event);
|
|
@@ -250,6 +254,7 @@ export const systemSetupHost = (doctorHost = systemDoctorHost()) => {
|
|
|
250
254
|
const diagnosis = await runDoctor(undefined, doctorHost);
|
|
251
255
|
return {
|
|
252
256
|
...providerRegistrationEnvironment(diagnosis.providerInspections ?? []),
|
|
257
|
+
...registrationPermissionEnvironment(process.env),
|
|
253
258
|
...(diagnosis.hopperPath === undefined
|
|
254
259
|
? {}
|
|
255
260
|
: { HOPPER_LAUNCHER_PATH: diagnosis.hopperPath }),
|
|
@@ -273,7 +278,7 @@ export const systemSetupHost = (doctorHost = systemDoctorHost()) => {
|
|
|
273
278
|
inspectClientConfiguration: inspectClientConfiguration,
|
|
274
279
|
skillNeedsInstall: () => canonicalSkillNeedsInstall(homedir()),
|
|
275
280
|
installSkill: () => installCanonicalSkill(homedir()),
|
|
276
|
-
doctor: () => runDoctor(undefined, doctorHost),
|
|
281
|
+
doctor: (scope) => runDoctor(undefined, doctorHost, scope),
|
|
277
282
|
};
|
|
278
283
|
};
|
|
279
284
|
/** Detect supported agents from stable per-user installation markers. */
|
|
@@ -294,7 +299,3 @@ const exists = async (path) => {
|
|
|
294
299
|
return false;
|
|
295
300
|
}
|
|
296
301
|
};
|
|
297
|
-
const providerRegistrationEnvironment = (inspections) => Object.fromEntries(inspections
|
|
298
|
-
.filter(({ available }) => available)
|
|
299
|
-
.flatMap(({ registrationEnvironment }) => Object.entries(registrationEnvironment))
|
|
300
|
-
.sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -59,7 +59,7 @@ const setupPlan = (input) => [
|
|
|
59
59
|
/** Discover and preflight the complete set of selectable setup actions. */
|
|
60
60
|
export const discoverSetupActions = async (input) => {
|
|
61
61
|
const { host, providerEnvironment, command } = input;
|
|
62
|
-
const initialDoctor = await host.doctor();
|
|
62
|
+
const initialDoctor = await host.doctor(input.doctorScope);
|
|
63
63
|
const linuxHopperRepairNeeded = initialDoctor.checks.some(({ name, ok, detail }) => !ok &&
|
|
64
64
|
(name === "hopper-demo-runtime" ||
|
|
65
65
|
(name === "hopper-version" && detail === "/opt/hopper/bin/Hopper")));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Select explicit non-secret permission settings safe for managed MCP registrations. */
|
|
2
|
+
export const registrationPermissionEnvironment = (environment) => {
|
|
3
|
+
const investigationRoots = environment.REA_INVESTIGATION_INPUT_ROOTS_JSON;
|
|
4
|
+
return investigationRoots === undefined
|
|
5
|
+
? {}
|
|
6
|
+
: { REA_INVESTIGATION_INPUT_ROOTS_JSON: investigationRoots };
|
|
7
|
+
};
|
|
8
|
+
/** Select exact non-secret settings published by available providers. */
|
|
9
|
+
export const providerRegistrationEnvironment = (inspections) => Object.fromEntries(inspections
|
|
10
|
+
.filter(({ available }) => available)
|
|
11
|
+
.flatMap(({ registrationEnvironment }) => Object.entries(registrationEnvironment))
|
|
12
|
+
.sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -77,8 +77,9 @@ export class TerminalRenderer {
|
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
this.#capturedBytes += bytes;
|
|
80
|
+
const sequence = this.#frames.length;
|
|
80
81
|
this.#frames.push({
|
|
81
|
-
sequence
|
|
82
|
+
sequence,
|
|
82
83
|
at_ms: atMs,
|
|
83
84
|
columns: this.#terminal.cols,
|
|
84
85
|
rows: this.#terminal.rows,
|
|
@@ -88,5 +89,6 @@ export class TerminalRenderer {
|
|
|
88
89
|
lines,
|
|
89
90
|
serialized_state: serializedState,
|
|
90
91
|
});
|
|
92
|
+
this.options.recordEvent?.("rendered_frames", sequence);
|
|
91
93
|
}
|
|
92
94
|
}
|
|
@@ -40,25 +40,58 @@ export const discoverCdpEndpoint = async (endpoint, operation, signal) => {
|
|
|
40
40
|
targets: targets.map((target) => ({
|
|
41
41
|
id: target.id,
|
|
42
42
|
type: target.type,
|
|
43
|
-
title: sanitizeTargetTitle(target.title),
|
|
43
|
+
title: sanitizeTargetTitle(target.title, target.url),
|
|
44
44
|
url: target.url,
|
|
45
45
|
attached: target.attached,
|
|
46
46
|
...targetWebSocket(endpoint, target, operation),
|
|
47
47
|
})),
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
|
-
const sanitizeTargetTitle = (value) => {
|
|
50
|
+
const sanitizeTargetTitle = (value, targetUrl) => {
|
|
51
51
|
let url;
|
|
52
52
|
try {
|
|
53
53
|
url = new URL(value);
|
|
54
54
|
}
|
|
55
55
|
catch {
|
|
56
|
-
return value;
|
|
56
|
+
return sanitizeTargetUrlAlias(value, targetUrl);
|
|
57
57
|
}
|
|
58
58
|
return url.protocol === "http:" || url.protocol === "https:"
|
|
59
59
|
? sanitizeBrowserUrl(value).url.slice(0, 16_384)
|
|
60
|
-
: value;
|
|
60
|
+
: sanitizeTargetUrlAlias(value, targetUrl);
|
|
61
|
+
};
|
|
62
|
+
const sanitizeTargetUrlAlias = (value, targetUrl) => {
|
|
63
|
+
let parsed;
|
|
64
|
+
try {
|
|
65
|
+
parsed = new URL(targetUrl);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
const markers = [parsed.origin, `//${parsed.host}`, parsed.host];
|
|
71
|
+
if (parsed.pathname !== "/")
|
|
72
|
+
markers.push(parsed.pathname);
|
|
73
|
+
const candidatePattern = new RegExp(`(?:${markers.map(escapeRegExp).join("|")})[^\\s<>"']*`, "gu");
|
|
74
|
+
return value
|
|
75
|
+
.replace(candidatePattern, (candidate) => sanitizeSameOriginTitleUrl(candidate, parsed))
|
|
76
|
+
.slice(0, 16_384);
|
|
77
|
+
};
|
|
78
|
+
const sanitizeSameOriginTitleUrl = (candidate, target) => {
|
|
79
|
+
let parsed;
|
|
80
|
+
try {
|
|
81
|
+
parsed = candidate.startsWith("//")
|
|
82
|
+
? new URL(`${target.protocol}${candidate}`)
|
|
83
|
+
: candidate.startsWith(target.host)
|
|
84
|
+
? new URL(`${target.protocol}//${candidate}`)
|
|
85
|
+
: new URL(candidate, target.origin);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return candidate;
|
|
89
|
+
}
|
|
90
|
+
return parsed.origin === target.origin && parsed.search !== ""
|
|
91
|
+
? sanitizeBrowserUrl(parsed.href).url
|
|
92
|
+
: candidate;
|
|
61
93
|
};
|
|
94
|
+
const escapeRegExp = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
62
95
|
/** Select a browser attachment socket or a direct socket for one page target. */
|
|
63
96
|
export const cdpTargetWebSocket = (discovery, target, operation) => {
|
|
64
97
|
const webSocket = availableCdpTargetWebSocket(discovery, target);
|
package/dist/catalogIdentity.js
CHANGED
|
@@ -26,11 +26,13 @@ const promptCatalog = PROMPT_CONTRACTS.map((contract) => ({
|
|
|
26
26
|
arguments: contract.arguments,
|
|
27
27
|
steps: contract.steps,
|
|
28
28
|
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
29
|
-
|
|
29
|
+
/** Canonical fixed resources exposed by every target-free MCP session. */
|
|
30
|
+
export const MCP_RESOURCE_CATALOG = [
|
|
30
31
|
{ name: "server-identity", uri: "rea://server/identity" },
|
|
31
32
|
{ name: "active-residual-unknowns", uri: "rea://unknowns/active" },
|
|
32
33
|
];
|
|
33
|
-
|
|
34
|
+
/** Canonical resource templates exposed by every target-free MCP session. */
|
|
35
|
+
export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
34
36
|
{ name: "session-evidence", uri_template: "rea://evidence/{evidenceId}" },
|
|
35
37
|
{
|
|
36
38
|
name: "evidence-section",
|
|
@@ -57,6 +59,10 @@ const resourceTemplateCatalog = [
|
|
|
57
59
|
name: "reconstruction-coverage-revision",
|
|
58
60
|
uri_template: "rea://reconstruction-coverage/{workspaceId}/revision/{revision}",
|
|
59
61
|
},
|
|
62
|
+
{
|
|
63
|
+
name: "javascript-application-graph-page",
|
|
64
|
+
uri_template: "rea://evidence/{evidenceId}/application-graph/{collection}/offset/{offset}/limit/{limit}",
|
|
65
|
+
},
|
|
60
66
|
];
|
|
61
67
|
const digest = (value) => {
|
|
62
68
|
const encoded = canonicalize(value);
|
|
@@ -70,19 +76,22 @@ export const CATALOG_IDENTITY = {
|
|
|
70
76
|
cli_commands: CLI_COMMAND_NAMES.length,
|
|
71
77
|
mcp_tools: toolCatalog.length,
|
|
72
78
|
mcp_prompts: promptCatalog.length,
|
|
73
|
-
mcp_resources:
|
|
74
|
-
mcp_resource_templates:
|
|
79
|
+
mcp_resources: MCP_RESOURCE_CATALOG.length,
|
|
80
|
+
mcp_resource_templates: MCP_RESOURCE_TEMPLATE_CATALOG.length,
|
|
75
81
|
},
|
|
76
82
|
digests: {
|
|
77
83
|
tools_sha256: digest(toolCatalog),
|
|
78
84
|
prompts_sha256: digest(promptCatalog),
|
|
79
|
-
resources_sha256: digest({
|
|
85
|
+
resources_sha256: digest({
|
|
86
|
+
resourceCatalog: MCP_RESOURCE_CATALOG,
|
|
87
|
+
resourceTemplateCatalog: MCP_RESOURCE_TEMPLATE_CATALOG,
|
|
88
|
+
}),
|
|
80
89
|
combined_sha256: digest({
|
|
81
90
|
cli: CLI_COMMAND_NAMES,
|
|
82
91
|
tools: toolCatalog,
|
|
83
92
|
prompts: promptCatalog,
|
|
84
|
-
resources:
|
|
85
|
-
resource_templates:
|
|
93
|
+
resources: MCP_RESOURCE_CATALOG,
|
|
94
|
+
resource_templates: MCP_RESOURCE_TEMPLATE_CATALOG,
|
|
86
95
|
}),
|
|
87
96
|
},
|
|
88
97
|
tools: toolCatalog.map(({ name, surface, effects, annotations }) => ({
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { z } from "incur";
|
|
2
|
+
import { stat } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
2
4
|
import { runDirectAnalysis } from "../application/DirectAnalysis.js";
|
|
3
5
|
import { CLI_COMMANDS } from "../cliCommandNames.js";
|
|
4
6
|
import { logCliCommand } from "../cliLogging.js";
|
|
5
7
|
import { directAnalysisOptions, providerSelectionOption } from "./options.js";
|
|
8
|
+
import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnalysis.js";
|
|
6
9
|
export const registerCoreAnalysisCommands = (cli, logger) => {
|
|
7
10
|
registerCoreCommands(cli, logger);
|
|
8
11
|
registerFunctionCommand(cli, logger);
|
|
@@ -30,13 +33,19 @@ const registerCoreCommands = (cli, logger) => {
|
|
|
30
33
|
.describe("Load and update a local analysis snapshot"),
|
|
31
34
|
provider: providerSelectionOption,
|
|
32
35
|
});
|
|
36
|
+
const analyzeOptions = overviewOptions.extend({
|
|
37
|
+
approved: z
|
|
38
|
+
.boolean()
|
|
39
|
+
.default(false)
|
|
40
|
+
.describe("Approve static analysis when the path is a JavaScript directory or ASAR"),
|
|
41
|
+
});
|
|
33
42
|
cli.command(CLI_COMMANDS.analyze, {
|
|
34
43
|
description: "Get an overview of an app",
|
|
35
44
|
args: z.object({
|
|
36
45
|
path: z.string().describe("App, program, or analysis database path"),
|
|
37
46
|
}),
|
|
38
|
-
options:
|
|
39
|
-
run: ({ args, options }) => logCliCommand(logger, "analyze", () =>
|
|
47
|
+
options: analyzeOptions,
|
|
48
|
+
run: ({ args, options }) => logCliCommand(logger, "analyze", () => runRoutedOverview(args.path, options, logger)),
|
|
40
49
|
});
|
|
41
50
|
cli.command(CLI_COMMANDS.inspect, {
|
|
42
51
|
description: "Inspect an app overview with evidence",
|
|
@@ -63,6 +72,29 @@ const registerCoreCommands = (cli, logger) => {
|
|
|
63
72
|
run: ({ args, options }) => logCliCommand(logger, "decompile", () => runDirectAnalysis(args.path, "procedure_pseudo_code", { procedure: args.address }, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
64
73
|
});
|
|
65
74
|
};
|
|
75
|
+
const runRoutedOverview = async (path, options, logger) => {
|
|
76
|
+
if (options.provider === undefined &&
|
|
77
|
+
options.snapshot === undefined &&
|
|
78
|
+
(await isJavaScriptApplicationPath(path)))
|
|
79
|
+
return runCliJavaScriptApplicationAnalysis({
|
|
80
|
+
input_path: resolve(path),
|
|
81
|
+
approved: options.approved,
|
|
82
|
+
});
|
|
83
|
+
return runDirectAnalysis(path, "binary_overview", { detail: options.detail, limit: options.limit }, directAnalysisOptions(logger, options.snapshot, options.provider));
|
|
84
|
+
};
|
|
85
|
+
const isJavaScriptApplicationPath = async (path) => {
|
|
86
|
+
const lower = path.toLowerCase();
|
|
87
|
+
if (lower.endsWith(".asar"))
|
|
88
|
+
return true;
|
|
89
|
+
if (lower.endsWith(".app"))
|
|
90
|
+
return false;
|
|
91
|
+
try {
|
|
92
|
+
return (await stat(path)).isDirectory();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
66
98
|
const registerXrefsCommand = (cli, logger) => {
|
|
67
99
|
cli.command(CLI_COMMANDS.xrefs, {
|
|
68
100
|
description: "List bounded references to an analyzed address",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { analyzeJavaScriptApplication } from "../application/JavaScriptApplicationService.js";
|
|
2
|
+
import { loadConfiguredPermissionAuthority } from "../application/PermissionConfiguration.js";
|
|
3
|
+
import { parseConfig } from "../config.js";
|
|
4
|
+
import { projectAnalysisError } from "../domain/errors.js";
|
|
5
|
+
/** Execute the shared one-shot CLI boundary for static JavaScript analysis. */
|
|
6
|
+
export const runCliJavaScriptApplicationAnalysis = async (input) => {
|
|
7
|
+
const config = parseConfig(process.env);
|
|
8
|
+
if (!config.ok)
|
|
9
|
+
return cliError(config.error);
|
|
10
|
+
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
11
|
+
if (!authority.ok)
|
|
12
|
+
return cliError(authority.error);
|
|
13
|
+
const result = await analyzeJavaScriptApplication(authority.value, input);
|
|
14
|
+
return result.ok ? result.value : cliError(result.error);
|
|
15
|
+
};
|
|
16
|
+
const cliError = (error) => ({
|
|
17
|
+
error: "JavaScript application analysis failed",
|
|
18
|
+
...projectAnalysisError(error),
|
|
19
|
+
});
|