rea-agents 2.4.0 → 3.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 +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +9 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +29 -2
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +13 -16
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -1,7 +1,134 @@
|
|
|
1
1
|
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
-
import {
|
|
2
|
+
import { sourceRangesEqual } from "../domain/javascriptStaticAnalysisHelpers.js";
|
|
3
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
4
|
import { inferredSemanticEvidenceAt, unknownSemanticEvidence, } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
5
|
import { semanticNodesWithinRange } from "./JavaScriptSemanticGraphProjection.js";
|
|
6
|
+
/** Find the retained call-site node at one exact semantic source range. */
|
|
7
|
+
export const semanticCallSiteAt = (context, location) => {
|
|
8
|
+
const call = context.ir.callSites.find(({ location: candidate }) => sourceRangesEqual(candidate, location));
|
|
9
|
+
return call === undefined
|
|
10
|
+
? undefined
|
|
11
|
+
: context.callSiteNodes.get(call.callSiteId);
|
|
12
|
+
};
|
|
13
|
+
/** Project explicit static Promise/task ownership without runtime claims. */
|
|
14
|
+
export const projectSemanticPromises = (context) => {
|
|
15
|
+
const promiseNodes = new Map(context.ir.promiseOperations.flatMap((operation) => {
|
|
16
|
+
const owner = operation.ownerCallableId === null
|
|
17
|
+
? undefined
|
|
18
|
+
: context.callableNodes.get(operation.ownerCallableId);
|
|
19
|
+
const node = addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
20
|
+
kind: operation.kind === "awaited-expression" ? "task" : "promise",
|
|
21
|
+
roleKey: operation.promiseId,
|
|
22
|
+
location: operation.location,
|
|
23
|
+
label: promiseLabel(operation),
|
|
24
|
+
functionNodeId: owner?.node_id ?? null,
|
|
25
|
+
properties: {
|
|
26
|
+
method: operation.method,
|
|
27
|
+
operation_kind: operation.kind,
|
|
28
|
+
ownership: operation.ownership,
|
|
29
|
+
source_resolution: operation.sourceResolution,
|
|
30
|
+
},
|
|
31
|
+
}, context.state));
|
|
32
|
+
return node === null ? [] : [[operation.promiseId, node]];
|
|
33
|
+
}));
|
|
34
|
+
for (const operation of context.ir.promiseOperations) {
|
|
35
|
+
const promise = promiseNodes.get(operation.promiseId);
|
|
36
|
+
if (promise === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
projectPromiseCreation(context, operation, promise);
|
|
39
|
+
projectPromiseSources(context, operation, promise, promiseNodes);
|
|
40
|
+
projectPromiseOwnership(context, operation, promise);
|
|
41
|
+
if (operation.sourceResolution !== "complete" &&
|
|
42
|
+
["chain", "aggregate", "awaited-expression"].includes(operation.kind))
|
|
43
|
+
addPromiseUnknown(context, operation, promise, promiseNodes);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const promiseLabel = (operation) => operation.kind === "awaited-expression"
|
|
47
|
+
? "awaited expression"
|
|
48
|
+
: `Promise.${operation.method}`;
|
|
49
|
+
const projectPromiseCreation = (context, operation, promise) => {
|
|
50
|
+
if (operation.kind === "awaited-expression")
|
|
51
|
+
return;
|
|
52
|
+
addSemanticGraphRelation(context.state, {
|
|
53
|
+
source: semanticCallSiteAt(context, operation.location),
|
|
54
|
+
target: promise,
|
|
55
|
+
relation: "creates-promise",
|
|
56
|
+
resolution: operation.kind === "chain" || operation.sourceResolution !== "complete"
|
|
57
|
+
? "candidate"
|
|
58
|
+
: "resolved",
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const projectPromiseSources = (context, operation, promise, promiseNodes) => {
|
|
62
|
+
for (const sourceId of operation.sourcePromiseIds) {
|
|
63
|
+
const source = promiseNodes.get(sourceId);
|
|
64
|
+
if (operation.kind === "aggregate")
|
|
65
|
+
addSemanticGraphRelation(context.state, {
|
|
66
|
+
source: promise,
|
|
67
|
+
target: source,
|
|
68
|
+
relation: "aggregates",
|
|
69
|
+
resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
|
|
70
|
+
});
|
|
71
|
+
else
|
|
72
|
+
addSemanticGraphRelation(context.state, {
|
|
73
|
+
source,
|
|
74
|
+
target: promise,
|
|
75
|
+
relation: "chains",
|
|
76
|
+
resolution: operation.sourceResolution === "complete" ? "resolved" : "candidate",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const projectPromiseOwnership = (context, operation, promise) => {
|
|
81
|
+
const owner = operation.ownerCallableId === null
|
|
82
|
+
? context.moduleNode
|
|
83
|
+
: context.callableNodes.get(operation.ownerCallableId);
|
|
84
|
+
if (operation.ownership === "awaited")
|
|
85
|
+
addSemanticGraphRelation(context.state, {
|
|
86
|
+
source: owner,
|
|
87
|
+
target: promise,
|
|
88
|
+
relation: "awaits",
|
|
89
|
+
resolution: "resolved",
|
|
90
|
+
});
|
|
91
|
+
else if (operation.ownership === "assigned")
|
|
92
|
+
addSemanticGraphRelation(context.state, {
|
|
93
|
+
source: operation.ownerBindingId === null
|
|
94
|
+
? undefined
|
|
95
|
+
: context.bindingNodes.get(operation.ownerBindingId),
|
|
96
|
+
target: promise,
|
|
97
|
+
relation: "owns",
|
|
98
|
+
resolution: "resolved",
|
|
99
|
+
});
|
|
100
|
+
else if (operation.ownership === "returned")
|
|
101
|
+
addSemanticGraphRelation(context.state, {
|
|
102
|
+
source: operation.returnSiteId === null
|
|
103
|
+
? undefined
|
|
104
|
+
: context.returnSiteNodes.get(operation.returnSiteId),
|
|
105
|
+
target: promise,
|
|
106
|
+
relation: "returns-task",
|
|
107
|
+
resolution: "resolved",
|
|
108
|
+
});
|
|
109
|
+
else if (operation.ownership === "detached")
|
|
110
|
+
addSemanticGraphRelation(context.state, {
|
|
111
|
+
source: owner,
|
|
112
|
+
target: promise,
|
|
113
|
+
relation: "detaches-task",
|
|
114
|
+
resolution: "resolved",
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
const addPromiseUnknown = (context, operation, promise, promiseNodes) => {
|
|
118
|
+
const relation = operation.kind === "aggregate" ? "aggregates" : "chains";
|
|
119
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
120
|
+
node_id: promise.node_id,
|
|
121
|
+
family: "promise-ownership",
|
|
122
|
+
relation_kinds: [relation],
|
|
123
|
+
reason: "ambiguous-target",
|
|
124
|
+
detail: `Static ${operation.method} source resolution was ${operation.sourceResolution}.`,
|
|
125
|
+
candidate_node_ids: operation.sourcePromiseIds.flatMap((identifier) => {
|
|
126
|
+
const candidate = promiseNodes.get(identifier);
|
|
127
|
+
return candidate === undefined ? [] : [candidate.node_id];
|
|
128
|
+
}),
|
|
129
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
130
|
+
}));
|
|
131
|
+
};
|
|
5
132
|
/** Link direct return expressions to their retained semantic references. */
|
|
6
133
|
export const projectSemanticReturnValues = (context) => {
|
|
7
134
|
for (const callable of context.ir.callables)
|
|
@@ -14,18 +141,12 @@ export const projectSemanticReturnValues = (context) => {
|
|
|
14
141
|
target: returnNode,
|
|
15
142
|
relation: "aliases",
|
|
16
143
|
resolution: site.identityReferenceLocation !== null &&
|
|
17
|
-
|
|
144
|
+
sourceRangesEqual(reference.identity.source_range, site.identityReferenceLocation)
|
|
18
145
|
? "resolved"
|
|
19
146
|
: "candidate",
|
|
20
147
|
});
|
|
21
148
|
}
|
|
22
149
|
};
|
|
23
|
-
const rangesEqual = (left, right) => left !== null &&
|
|
24
|
-
right !== null &&
|
|
25
|
-
left.start.line === right.start.line &&
|
|
26
|
-
left.start.column === right.start.column &&
|
|
27
|
-
left.end.line === right.end.line &&
|
|
28
|
-
left.end.column === right.end.column;
|
|
29
150
|
/** Link each captured binding to the callable at the exact reference site. */
|
|
30
151
|
export const projectSemanticClosureCaptures = (context) => {
|
|
31
152
|
for (const capture of context.ir.closureCaptures)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
|
+
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
|
+
import { semanticPropertySlot } from "./JavaScriptSemanticGraphValueProjection.js";
|
|
5
|
+
/** Project static object reads, writes, spreads, and destructuring. */
|
|
6
|
+
export const projectSemanticObjects = (context) => {
|
|
7
|
+
for (const operation of context.ir.objectOperations) {
|
|
8
|
+
const occurrence = addObjectOccurrence(context, operation);
|
|
9
|
+
const slot = operation.objectBindingId === null || operation.propertyName === null
|
|
10
|
+
? null
|
|
11
|
+
: semanticPropertySlot(context, operation.objectBindingId, operation.propertyName);
|
|
12
|
+
if (operation.kind === "read")
|
|
13
|
+
addSemanticGraphRelation(context.state, {
|
|
14
|
+
source: slot,
|
|
15
|
+
target: occurrence,
|
|
16
|
+
relation: "reads-property",
|
|
17
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
18
|
+
});
|
|
19
|
+
else if (operation.kind === "write")
|
|
20
|
+
addSemanticGraphRelation(context.state, {
|
|
21
|
+
source: occurrence,
|
|
22
|
+
target: slot,
|
|
23
|
+
relation: "writes-property",
|
|
24
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
25
|
+
});
|
|
26
|
+
else if (operation.kind === "destructure")
|
|
27
|
+
addSemanticGraphRelation(context.state, {
|
|
28
|
+
source: slot,
|
|
29
|
+
target: operation.targetBindingId === null
|
|
30
|
+
? undefined
|
|
31
|
+
: context.bindingNodes.get(operation.targetBindingId),
|
|
32
|
+
relation: "destructures",
|
|
33
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
34
|
+
});
|
|
35
|
+
else
|
|
36
|
+
addSemanticGraphRelation(context.state, {
|
|
37
|
+
source: operation.objectBindingId === null
|
|
38
|
+
? undefined
|
|
39
|
+
: context.bindingNodes.get(operation.objectBindingId),
|
|
40
|
+
target: occurrence,
|
|
41
|
+
relation: "spreads",
|
|
42
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
43
|
+
});
|
|
44
|
+
if (operation.resolution !== "complete")
|
|
45
|
+
addObjectUnknown(context, operation, slot ?? occurrence);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const addObjectOccurrence = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
49
|
+
kind: "expression",
|
|
50
|
+
roleKey: operation.objectOperationId,
|
|
51
|
+
location: operation.location,
|
|
52
|
+
label: operation.propertyName === null
|
|
53
|
+
? operation.kind
|
|
54
|
+
: `${operation.kind}:${operation.propertyName}`,
|
|
55
|
+
functionNodeId: operation.ownerCallableId === null
|
|
56
|
+
? null
|
|
57
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
58
|
+
null),
|
|
59
|
+
properties: {
|
|
60
|
+
operation_kind: operation.kind,
|
|
61
|
+
property_name: operation.propertyName,
|
|
62
|
+
},
|
|
63
|
+
}, context.state));
|
|
64
|
+
const addObjectUnknown = (context, operation, node) => {
|
|
65
|
+
const relation = operation.kind === "read"
|
|
66
|
+
? "reads-property"
|
|
67
|
+
: operation.kind === "write"
|
|
68
|
+
? "writes-property"
|
|
69
|
+
: operation.kind === "spread"
|
|
70
|
+
? "spreads"
|
|
71
|
+
: "destructures";
|
|
72
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
73
|
+
node_id: node?.node_id ?? null,
|
|
74
|
+
family: "object-flow",
|
|
75
|
+
relation_kinds: [relation],
|
|
76
|
+
reason: "ambiguous-target",
|
|
77
|
+
detail: `Static ${operation.kind} object identity is partial.`,
|
|
78
|
+
candidate_node_ids: [],
|
|
79
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
80
|
+
}));
|
|
81
|
+
};
|
|
@@ -15,18 +15,25 @@ export const semanticNodesWithinRange = (nodes, range) => nodes.filter((node) =>
|
|
|
15
15
|
contains(range, node.identity.source_range));
|
|
16
16
|
/** Report extractor support without treating missing families as absence. */
|
|
17
17
|
export const semanticFamilyStatus = (family, analysis, truncated) => {
|
|
18
|
-
if (![
|
|
18
|
+
if (![
|
|
19
|
+
"call-flow",
|
|
20
|
+
"boundary",
|
|
21
|
+
"child-process",
|
|
22
|
+
"closure",
|
|
23
|
+
"configuration",
|
|
24
|
+
"data-flow",
|
|
25
|
+
"event",
|
|
26
|
+
"object-flow",
|
|
27
|
+
"promise-ownership",
|
|
28
|
+
"request",
|
|
29
|
+
"resource-lifecycle",
|
|
30
|
+
"timer",
|
|
31
|
+
].includes(family))
|
|
19
32
|
return "unsupported";
|
|
20
33
|
if (truncated)
|
|
21
34
|
return "unknown";
|
|
22
35
|
return analysis.truncated_scopes === 0 ? "partial" : "unknown";
|
|
23
36
|
};
|
|
24
|
-
/** Compare two exact semantic source ranges. */
|
|
25
|
-
export const semanticRangesEqual = (left, right) => left !== null &&
|
|
26
|
-
left.start.line === right.start.line &&
|
|
27
|
-
left.start.column === right.start.column &&
|
|
28
|
-
left.end.line === right.end.line &&
|
|
29
|
-
left.end.column === right.end.column;
|
|
30
37
|
const contains = (outer, inner) => pointCompare(outer.start, inner.start) <= 0 &&
|
|
31
38
|
pointCompare(outer.end, inner.end) >= 0;
|
|
32
39
|
const pointCompare = (left, right) => left.line - right.line || left.column - right.column;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createJavaScriptSemanticGraphUnknown } from "../domain/javascriptSemanticGraph.js";
|
|
2
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, addSemanticGraphUnknown, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
3
|
+
import { unknownSemanticEvidence } from "./JavaScriptSemanticGraphEvidence.js";
|
|
4
|
+
import { semanticCallSiteAt, } from "./JavaScriptSemanticGraphFlowProjection.js";
|
|
5
|
+
/** Project built-in resource acquisition and exact local release handles. */
|
|
6
|
+
export const projectSemanticResources = (context) => {
|
|
7
|
+
const resourceNodes = new Map(context.ir.resourceOperations.flatMap((operation) => {
|
|
8
|
+
if (operation.kind !== "acquire")
|
|
9
|
+
return [];
|
|
10
|
+
const node = addResourceNode(context, operation);
|
|
11
|
+
return node === null ? [] : [[operation.resourceId, node]];
|
|
12
|
+
}));
|
|
13
|
+
for (const operation of context.ir.resourceOperations)
|
|
14
|
+
if (operation.kind === "acquire")
|
|
15
|
+
addSemanticGraphRelation(context.state, {
|
|
16
|
+
source: semanticCallSiteAt(context, operation.location),
|
|
17
|
+
target: resourceNodes.get(operation.resourceId),
|
|
18
|
+
relation: "acquires",
|
|
19
|
+
resolution: "resolved",
|
|
20
|
+
});
|
|
21
|
+
else
|
|
22
|
+
projectRelease(context, operation, resourceNodes);
|
|
23
|
+
};
|
|
24
|
+
const addResourceNode = (context, operation) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
25
|
+
kind: "resource",
|
|
26
|
+
roleKey: operation.resourceId,
|
|
27
|
+
location: operation.location,
|
|
28
|
+
label: operation.method,
|
|
29
|
+
functionNodeId: operation.ownerCallableId === null
|
|
30
|
+
? null
|
|
31
|
+
: (context.callableNodes.get(operation.ownerCallableId)?.node_id ??
|
|
32
|
+
null),
|
|
33
|
+
properties: { method: operation.method },
|
|
34
|
+
}, context.state));
|
|
35
|
+
const projectRelease = (context, operation, resourceNodes) => {
|
|
36
|
+
const callSite = semanticCallSiteAt(context, operation.location);
|
|
37
|
+
const resources = operation.linkedResourceIds.flatMap((identifier) => {
|
|
38
|
+
const resource = resourceNodes.get(identifier);
|
|
39
|
+
return resource === undefined ? [] : [resource];
|
|
40
|
+
});
|
|
41
|
+
for (const resource of resources)
|
|
42
|
+
addSemanticGraphRelation(context.state, {
|
|
43
|
+
source: callSite,
|
|
44
|
+
target: resource,
|
|
45
|
+
relation: "releases",
|
|
46
|
+
resolution: operation.resolution === "complete" ? "resolved" : "candidate",
|
|
47
|
+
});
|
|
48
|
+
if (operation.resolution === "complete")
|
|
49
|
+
return;
|
|
50
|
+
addSemanticGraphUnknown(context.state, createJavaScriptSemanticGraphUnknown({
|
|
51
|
+
node_id: callSite?.node_id ?? null,
|
|
52
|
+
family: "resource-lifecycle",
|
|
53
|
+
relation_kinds: ["releases"],
|
|
54
|
+
reason: "ambiguous-target",
|
|
55
|
+
detail: `Static ${operation.method} resource ownership is ambiguous.`,
|
|
56
|
+
candidate_node_ids: resources.map(({ node_id: identifier }) => identifier),
|
|
57
|
+
evidence: unknownSemanticEvidence(context.file, operation.location),
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { addSemanticGraphNode, addSemanticGraphRelation, constructSemanticGraphNode, } from "./JavaScriptSemanticGraphConstruction.js";
|
|
2
|
+
/** Project bounded literal values and object slots for exact query seeds. */
|
|
3
|
+
export const projectSemanticValues = (context) => {
|
|
4
|
+
for (const binding of context.ir.bindings) {
|
|
5
|
+
const bindingNode = context.bindingNodes.get(binding.bindingId);
|
|
6
|
+
if (bindingNode === undefined)
|
|
7
|
+
continue;
|
|
8
|
+
projectValue({
|
|
9
|
+
context,
|
|
10
|
+
binding,
|
|
11
|
+
value: binding.value,
|
|
12
|
+
target: bindingNode,
|
|
13
|
+
role: "binding",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const projectValue = (input) => {
|
|
18
|
+
const { context, binding, value, target, role } = input;
|
|
19
|
+
if (target === null)
|
|
20
|
+
return;
|
|
21
|
+
if (value.status === "literal") {
|
|
22
|
+
const literal = addLiteralNode(context, binding, value.value, role);
|
|
23
|
+
addSemanticGraphRelation(context.state, {
|
|
24
|
+
source: literal,
|
|
25
|
+
target,
|
|
26
|
+
relation: "defines",
|
|
27
|
+
resolution: "resolved",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else if (value.status === "union")
|
|
31
|
+
for (const primitive of value.values) {
|
|
32
|
+
const literal = addLiteralNode(context, binding, primitive, role);
|
|
33
|
+
addSemanticGraphRelation(context.state, {
|
|
34
|
+
source: literal,
|
|
35
|
+
target,
|
|
36
|
+
relation: "defines",
|
|
37
|
+
resolution: "candidate",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else if (value.status === "object")
|
|
41
|
+
for (const property of value.properties) {
|
|
42
|
+
const slot = semanticPropertySlot(context, binding.bindingId, property.name);
|
|
43
|
+
addSemanticGraphRelation(context.state, {
|
|
44
|
+
source: target,
|
|
45
|
+
target: slot,
|
|
46
|
+
relation: "writes-property",
|
|
47
|
+
resolution: value.unknownProperties ? "candidate" : "resolved",
|
|
48
|
+
});
|
|
49
|
+
projectValue({
|
|
50
|
+
context,
|
|
51
|
+
binding,
|
|
52
|
+
value: property.value,
|
|
53
|
+
target: slot,
|
|
54
|
+
role: `property:${property.name}`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const addLiteralNode = (context, binding, value, role) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
59
|
+
kind: "literal",
|
|
60
|
+
roleKey: `literal:${binding.bindingId}:${role}:${JSON.stringify(value)}`,
|
|
61
|
+
location: binding.definitions[0]?.location ?? null,
|
|
62
|
+
label: JSON.stringify(value),
|
|
63
|
+
functionNodeId: context.bindingNodes.get(binding.bindingId)?.function_node_id ?? null,
|
|
64
|
+
properties: { value },
|
|
65
|
+
}, context.state));
|
|
66
|
+
/** Create one canonical property slot for a binding/property identity. */
|
|
67
|
+
export const semanticPropertySlot = (context, objectBindingId, name) => addSemanticGraphNode(context.state, constructSemanticGraphNode(context.file, {
|
|
68
|
+
kind: "property-slot",
|
|
69
|
+
roleKey: `property:${objectBindingId}:${name}`,
|
|
70
|
+
location: null,
|
|
71
|
+
label: name,
|
|
72
|
+
functionNodeId: context.bindingNodes.get(objectBindingId)?.function_node_id ?? null,
|
|
73
|
+
properties: {
|
|
74
|
+
name,
|
|
75
|
+
object_binding_id: objectBindingId,
|
|
76
|
+
},
|
|
77
|
+
}, context.state));
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preserve synchronous provider discovery while loading implementation modules
|
|
3
|
+
* only when a target-bound client first executes.
|
|
4
|
+
*/
|
|
5
|
+
export class LazyAnalysisProvider {
|
|
6
|
+
#providerIdentity;
|
|
7
|
+
#capabilityDescriptors;
|
|
8
|
+
#loadProvider;
|
|
9
|
+
#provider;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.#providerIdentity = options.identity;
|
|
12
|
+
this.#capabilityDescriptors = options.capabilities;
|
|
13
|
+
this.#loadProvider = options.load;
|
|
14
|
+
}
|
|
15
|
+
/** Return generated provider identity without loading its implementation. */
|
|
16
|
+
identity() {
|
|
17
|
+
return this.#providerIdentity;
|
|
18
|
+
}
|
|
19
|
+
/** Return generated capability metadata without loading its implementation. */
|
|
20
|
+
capabilities() {
|
|
21
|
+
return this.#capabilityDescriptors;
|
|
22
|
+
}
|
|
23
|
+
/** Create a client whose implementation is loaded on first execution. */
|
|
24
|
+
createClient(target, profile, context) {
|
|
25
|
+
return new LazyAnalysisClient(async () => {
|
|
26
|
+
const provider = await this.#load();
|
|
27
|
+
return provider.createClient(target, profile, context);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async #load() {
|
|
31
|
+
this.#provider ??= this.#loadProvider().catch((cause) => {
|
|
32
|
+
this.#provider = undefined;
|
|
33
|
+
throw cause;
|
|
34
|
+
});
|
|
35
|
+
return this.#provider;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
class LazyAnalysisClient {
|
|
39
|
+
#loadClient;
|
|
40
|
+
#client;
|
|
41
|
+
#loading;
|
|
42
|
+
#closed = false;
|
|
43
|
+
constructor(loadClient) {
|
|
44
|
+
this.#loadClient = loadClient;
|
|
45
|
+
}
|
|
46
|
+
execute = async (operation, parameters, options) => {
|
|
47
|
+
const client = await this.#load();
|
|
48
|
+
return client.execute(operation, parameters, options);
|
|
49
|
+
};
|
|
50
|
+
runtimeLineageSnapshots() {
|
|
51
|
+
return this.#client?.runtimeLineageSnapshots?.() ?? [];
|
|
52
|
+
}
|
|
53
|
+
requestActivitySnapshots() {
|
|
54
|
+
return this.#client?.requestActivitySnapshots?.() ?? [];
|
|
55
|
+
}
|
|
56
|
+
async close() {
|
|
57
|
+
this.#closed = true;
|
|
58
|
+
if (this.#loading === undefined)
|
|
59
|
+
return;
|
|
60
|
+
const client = await this.#loading;
|
|
61
|
+
await client.close();
|
|
62
|
+
}
|
|
63
|
+
async #load() {
|
|
64
|
+
if (this.#closed)
|
|
65
|
+
throw new Error("Lazy analysis client is closed");
|
|
66
|
+
this.#loading ??= this.#loadClient()
|
|
67
|
+
.then((client) => {
|
|
68
|
+
this.#client = client;
|
|
69
|
+
return client;
|
|
70
|
+
})
|
|
71
|
+
.catch((cause) => {
|
|
72
|
+
this.#loading = undefined;
|
|
73
|
+
throw cause;
|
|
74
|
+
});
|
|
75
|
+
return this.#loading;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -374,11 +374,11 @@ export const startLoopbackReplay = async (scenario, recordEvent = () => undefine
|
|
|
374
374
|
async close() {
|
|
375
375
|
closePromise ??= (async () => {
|
|
376
376
|
recorder.stopMachineAdmission();
|
|
377
|
+
await recorder.drainMachine();
|
|
377
378
|
for (const client of websocket.clients)
|
|
378
379
|
client.terminate();
|
|
379
380
|
await new Promise((resolveClose) => websocket.close(() => resolveClose()));
|
|
380
381
|
await closeReplayServer(server);
|
|
381
|
-
await recorder.drainMachine();
|
|
382
382
|
})();
|
|
383
383
|
await closePromise;
|
|
384
384
|
},
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { nativeApiInspectionResultSchema, } from "../domain/nativeApiBoundary.js";
|
|
2
|
+
const unavailableBoundary = () => ({
|
|
3
|
+
available: false,
|
|
4
|
+
reason: "The selected provider did not expose a structured native API boundary model.",
|
|
5
|
+
residual_unknowns: [
|
|
6
|
+
"What are the function's return and parameter boundary types?",
|
|
7
|
+
"Does this function dispatch through a jump table with recoverable data addresses?",
|
|
8
|
+
],
|
|
9
|
+
});
|
|
10
|
+
/** Project one analyzed-function dossier into inspectable native API substeps. */
|
|
11
|
+
export const projectNativeApiInspection = (dossier) => {
|
|
12
|
+
const boundary = dossier.native_api ?? unavailableBoundary();
|
|
13
|
+
const unsupportedBranches = boundary.available
|
|
14
|
+
? []
|
|
15
|
+
: ["structured-boundary-types", "jump-table-data-mapping"];
|
|
16
|
+
const residualUnknowns = boundary.available
|
|
17
|
+
? availableResidualUnknowns(boundary)
|
|
18
|
+
: boundary.residual_unknowns;
|
|
19
|
+
return nativeApiInspectionResultSchema.parse({
|
|
20
|
+
schema_version: 1,
|
|
21
|
+
procedure: {
|
|
22
|
+
address: dossier.procedure.address,
|
|
23
|
+
name: dossier.procedure.name,
|
|
24
|
+
},
|
|
25
|
+
boundary,
|
|
26
|
+
substeps: [
|
|
27
|
+
{
|
|
28
|
+
operation: "analyze_function",
|
|
29
|
+
status: "completed",
|
|
30
|
+
observations: [
|
|
31
|
+
"provider function dossier",
|
|
32
|
+
"provider pseudocode classification",
|
|
33
|
+
"provider control-flow observations",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
operation: "project_native_api_boundary",
|
|
38
|
+
status: boundary.available ? "completed" : "unsupported",
|
|
39
|
+
observations: boundary.available
|
|
40
|
+
? [
|
|
41
|
+
"return and parameter boundary types",
|
|
42
|
+
"confidence and inference evidence",
|
|
43
|
+
"jump-table dispatch, data, and target addresses",
|
|
44
|
+
]
|
|
45
|
+
: [boundary.reason],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
operation: "preserve_residual_unknowns",
|
|
49
|
+
status: "completed",
|
|
50
|
+
observations: residualUnknowns.length === 0
|
|
51
|
+
? ["no additional structured-boundary unknowns"]
|
|
52
|
+
: residualUnknowns,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
unsupported_branches: unsupportedBranches,
|
|
56
|
+
residual_unknowns: residualUnknowns,
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
const availableResidualUnknowns = (boundary) => {
|
|
60
|
+
const unknowns = [];
|
|
61
|
+
if (boundary.parameters_truncated)
|
|
62
|
+
unknowns.push("Which additional parameters were omitted by the native API boundary limit?");
|
|
63
|
+
if (boundary.jump_tables_truncated)
|
|
64
|
+
unknowns.push("Which additional jump tables were omitted by the native API boundary limit?");
|
|
65
|
+
for (const table of boundary.jump_tables) {
|
|
66
|
+
if (table.data_sources_truncated || table.mappings_truncated)
|
|
67
|
+
unknowns.push(`Which additional data sources or targets were omitted for the jump table dispatched at ${table.dispatch_address}?`);
|
|
68
|
+
if (table.data_sources.length === 0)
|
|
69
|
+
unknowns.push(`What backing data address produced the jump table dispatched at ${table.dispatch_address}?`);
|
|
70
|
+
if (table.data_sources.some(({ entry_count: count, entry_size_bytes: size }) => count === null || size === null))
|
|
71
|
+
unknowns.push(`What are the exact entry size and count for candidate jump-table data dispatched at ${table.dispatch_address}?`);
|
|
72
|
+
if (table.mappings.some(({ case_value: value }) => value === null))
|
|
73
|
+
unknowns.push(`Which source-level case values correspond to every target dispatched at ${table.dispatch_address}?`);
|
|
74
|
+
}
|
|
75
|
+
for (const value of [boundary.return_type, ...boundary.parameters]) {
|
|
76
|
+
if (value.confidence === "low")
|
|
77
|
+
unknowns.push(`Can the inferred ${value.role} type ${value.data_type} be confirmed with imported metadata or an ABI probe?`);
|
|
78
|
+
}
|
|
79
|
+
return [...new Set(unknowns)];
|
|
80
|
+
};
|
|
@@ -7,6 +7,8 @@ const interactionData = (action) => {
|
|
|
7
7
|
: action.data;
|
|
8
8
|
if (action.type === "resize")
|
|
9
9
|
return `${String(action.columns)}x${String(action.rows)}`;
|
|
10
|
+
if (action.type === "close_stdin")
|
|
11
|
+
return "";
|
|
10
12
|
return action.signal;
|
|
11
13
|
};
|
|
12
14
|
const interactionType = (action) => {
|
|
@@ -14,6 +16,8 @@ const interactionType = (action) => {
|
|
|
14
16
|
return "input";
|
|
15
17
|
if (action.type === "resize")
|
|
16
18
|
return "resize";
|
|
19
|
+
if (action.type === "close_stdin")
|
|
20
|
+
return "stdin_close";
|
|
17
21
|
return "signal";
|
|
18
22
|
};
|
|
19
23
|
const performTerminalAction = (terminal, renderer, action, atMs) => {
|
|
@@ -23,6 +27,8 @@ const performTerminalAction = (terminal, renderer, action, atMs) => {
|
|
|
23
27
|
terminal.resize(action.columns, action.rows);
|
|
24
28
|
renderer.resize(action.columns, action.rows, atMs);
|
|
25
29
|
}
|
|
30
|
+
else if (action.type === "close_stdin")
|
|
31
|
+
terminal.closeInput();
|
|
26
32
|
else
|
|
27
33
|
terminal.kill(action.signal);
|
|
28
34
|
};
|
|
@@ -3,6 +3,21 @@ import { ProcessReactiveCoordinator } from "./ProcessReactiveCoordinator.js";
|
|
|
3
3
|
import { executeProcessReactiveEffects, unsupportedProcessReactiveFeatures, } from "./ProcessReactiveEffects.js";
|
|
4
4
|
import { subscribeProcessReactiveObservations } from "./ProcessReactiveObservations.js";
|
|
5
5
|
import { normalizeProcessSamples, normalizeProcessShimEvent, redactProtocolEvents, } from "./ProcessNormalization.js";
|
|
6
|
+
const reactiveTerminalFor = (terminal) => {
|
|
7
|
+
if (terminal === undefined)
|
|
8
|
+
return undefined;
|
|
9
|
+
return {
|
|
10
|
+
write: (data) => terminal.write(data),
|
|
11
|
+
resize: (columns, rows) => terminal.resize(columns, rows),
|
|
12
|
+
closeInput: () => {
|
|
13
|
+
const end = Reflect.get(terminal, "end");
|
|
14
|
+
if (typeof end !== "function")
|
|
15
|
+
throw new ProcessCaptureError("PTY backend does not expose an stdin-close operation");
|
|
16
|
+
Reflect.apply(end, terminal, []);
|
|
17
|
+
},
|
|
18
|
+
kill: (signal) => terminal.kill(signal),
|
|
19
|
+
};
|
|
20
|
+
};
|
|
6
21
|
const controlKind = (input) => input.kind === "observation" ? undefined : input.kind;
|
|
7
22
|
/** Reject reactive declarations the current process adapter cannot execute. */
|
|
8
23
|
export const assertSupportedReactiveScenario = (scenario) => {
|
|
@@ -27,7 +42,7 @@ export const startProcessReactiveHarness = (options) => {
|
|
|
27
42
|
scenario: options.scenario.reactive,
|
|
28
43
|
executor: {
|
|
29
44
|
execute: (actions, signal) => executeProcessReactiveEffects({
|
|
30
|
-
terminal: options.terminal,
|
|
45
|
+
terminal: () => reactiveTerminalFor(options.terminal()),
|
|
31
46
|
renderer: options.renderer,
|
|
32
47
|
checkpoints: options.checkpoints,
|
|
33
48
|
interactions: options.capture.interactions,
|