rea-agents 3.0.0 → 3.1.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 +14 -16
- package/dist/application/AnalysisContextQueries.js +21 -9
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
- package/dist/application/ArtifactInventory/policy.js +17 -0
- package/dist/application/ArtifactInventory/reader.js +1 -4
- package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
- package/dist/application/ArtifactInventory/scanReader.js +7 -7
- package/dist/application/ArtifactInventory/types.js +1 -5
- package/dist/application/BinarySession.js +14 -16
- package/dist/application/BinarySessionRecords.js +31 -5
- package/dist/application/BinarySessionStatus.js +11 -5
- package/dist/application/BrowserEvidence.js +3 -5
- package/dist/application/CapabilityClientRequirements.js +26 -0
- package/dist/application/CapabilityInventory.js +134 -63
- package/dist/application/CrossVersionInventory.js +7 -6
- package/dist/application/ElectronActiveEvidence.js +55 -0
- package/dist/application/ElectronActiveObservationPort.js +1 -0
- package/dist/application/ElectronActiveObservationService.js +81 -0
- package/dist/application/EnhancedTools.js +22 -20
- package/dist/application/EvidenceBundleCommands.js +5 -1
- package/dist/application/EvidenceLedger.js +8 -1
- package/dist/application/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayService.js +23 -15
- package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
- package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
- package/dist/application/ProcessCaptureLifecycle.js +5 -0
- package/dist/application/ProcessCli.js +2 -1
- package/dist/application/ProcessHarness.js +8 -3
- package/dist/application/ProcessNormalization.js +2 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReferenceSourceImport.js +2 -2
- package/dist/application/SetupClientConfiguration.js +6 -1
- package/dist/application/WindowsCapabilities.js +5 -4
- package/dist/artifacts/ArtifactProvider.js +8 -10
- package/dist/artifacts/SafeOutputTree.js +7 -8
- package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
- package/dist/browser/CdpElectronInspection.js +3 -1
- package/dist/browser/JavaScriptRuntimeScope.js +5 -0
- package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
- package/dist/browser/PlaywrightScenarioSession.js +4 -4
- package/dist/browser/SensitiveTextCapture.js +1 -1
- package/dist/browser/V8InspectorCaptureProjection.js +1 -0
- package/dist/browser/V8InspectorProvider.js +3 -3
- package/dist/catalogIdentity.js +12 -6
- package/dist/cli/managedCommands.js +1 -1
- package/dist/cliApplicationCommands.js +2 -2
- package/dist/cliBrowserAdvancedCommands.js +11 -5
- package/dist/cliBrowserCommands.js +14 -7
- package/dist/cliCommandNames.js +1 -0
- package/dist/cliElectronCommands.js +46 -4
- package/dist/cliJavaScriptRuntimeCommands.js +14 -6
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/browserScenario.js +77 -0
- package/dist/config/electronAutomation.js +35 -0
- package/dist/config/environment.js +6 -0
- package/dist/config/javascriptReplay.js +41 -0
- package/dist/config/managedRuntime.js +25 -0
- package/dist/config/parseConfig.js +56 -200
- package/dist/config/parsers.js +10 -1
- package/dist/config/passiveObservation.js +157 -0
- package/dist/config/processCapture.js +47 -0
- package/dist/contracts/applicationToolContracts.js +2 -5
- package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
- package/dist/contracts/artifactToolContracts.js +27 -34
- package/dist/contracts/browserToolContracts.js +2 -2
- package/dist/contracts/electronToolContracts.js +30 -1
- package/dist/contracts/enhancedInputs.js +13 -29
- package/dist/contracts/functionWorkflowToolContracts.js +2 -3
- package/dist/contracts/managedToolContracts.js +4 -9
- package/dist/contracts/managedWorkflowExamples.js +12 -9
- package/dist/contracts/managedWorkflowToolContracts.js +30 -27
- package/dist/contracts/nativeToolContracts.js +2 -3
- package/dist/contracts/sessionToolSchemas.js +61 -0
- package/dist/contracts/toolContractExamples.js +1 -0
- package/dist/contracts/toolContractHelpers.js +23 -0
- package/dist/contracts/toolContracts.js +5 -77
- package/dist/contracts/toolEffects.js +15 -0
- package/dist/contracts/toolOutputSchemaGroups.js +17 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
- package/dist/contracts/toolSchemaMetadata.js +128 -0
- package/dist/doctorRuntime.js +1 -1
- package/dist/domain/androidApplication.js +2 -0
- package/dist/domain/appleApplication.js +2 -0
- package/dist/domain/binaryTarget.js +7 -5
- package/dist/domain/binaryTargetTypes.js +1 -0
- package/dist/domain/browserCaptureComparison.js +21 -69
- package/dist/domain/browserObservation.js +22 -9
- package/dist/domain/bytecodeProvider.js +33 -35
- package/dist/domain/callPath.js +3 -2
- package/dist/domain/conformanceReplay.js +3 -3
- package/dist/domain/conformanceTrustGate.js +151 -16
- package/dist/domain/customProtocolCapture.js +3 -3
- package/dist/domain/electronActiveObservation.js +277 -0
- package/dist/domain/electronObservation.js +15 -11
- package/dist/domain/electronStaticAnalysisValues.js +4 -1
- package/dist/domain/eventProcessTree.js +82 -79
- package/dist/domain/functionComparisonNormalization.js +15 -8
- package/dist/domain/functionDossierEvidence.js +9 -4
- package/dist/domain/hopperValues.js +68 -71
- package/dist/domain/inputIssueProjection.js +4 -1
- package/dist/domain/investigationWorkspace.js +16 -15
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
- package/dist/domain/javascriptReplay.js +79 -63
- package/dist/domain/javascriptRuntimeObservation.js +1 -0
- package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
- package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/knownPageCoverage.js +15 -7
- package/dist/domain/nativeApiBoundary.js +15 -7
- package/dist/domain/nodeRuntimeCharacterization.js +14 -13
- package/dist/domain/processCaptureReactiveValidation.js +8 -3
- package/dist/domain/processCaptureValidation.js +7 -3
- package/dist/domain/processComparison.js +12 -7
- package/dist/domain/processObservation.js +5 -6
- package/dist/domain/processReactiveMatching.js +14 -7
- package/dist/domain/processReactiveTransition.js +9 -3
- package/dist/domain/processScenario.js +6 -3
- package/dist/domain/processTraceComparison.js +3 -2
- package/dist/domain/protocolCapture.js +8 -6
- package/dist/domain/reconstructionReadinessSchemas.js +30 -2
- package/dist/domain/referenceSourceImportParsing.js +2 -2
- package/dist/domain/replayMachineRuntime.js +5 -3
- package/dist/domain/sourceToBundleComparison.js +2 -2
- package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
- package/dist/domain/sourceToBundleSignals.js +7 -1
- package/dist/domain/staticRuntimeCorrelation.js +7 -5
- package/dist/domain/webBundleAnalysis.js +14 -14
- package/dist/domain/webCaptureDiff.js +15 -12
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +1 -1
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +17 -15
- package/dist/ghidra/GhidraInventoryValues.js +57 -47
- package/dist/ghidra/GhidraProvider.js +18 -10
- package/dist/ghidra/GhidraProviderCapabilities.js +5 -1
- package/dist/ghidra/GhidraSocketConnection.js +1 -1
- package/dist/ghidra/protocol.js +19 -42
- package/dist/hopper/BridgeLauncher.js +3 -1
- package/dist/hopper/HopperAnalysisProfile.js +2 -4
- package/dist/hopper/HopperCleanup.js +5 -6
- package/dist/hopper/HopperClient.js +1 -1
- package/dist/hopper/HopperProvider.js +0 -14
- package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
- package/dist/main/reload.js +1 -6
- package/dist/main/state.js +0 -14
- package/dist/main/transport.js +30 -37
- package/dist/main.js +17 -15
- package/dist/mcpDoctor.js +2 -24
- package/dist/process/PrivateRuntimeRoot.js +17 -0
- package/dist/process/ProcessOwnership.js +64 -128
- package/dist/process/ProcessOwnershipIdentity.js +13 -0
- package/dist/process/ProcessOwnershipObservation.js +88 -0
- package/dist/process/ProcessOwnershipProcessTree.js +22 -0
- package/dist/process/ProviderDeadline.js +8 -12
- package/dist/process/WindowsAuthority.js +32 -0
- package/dist/reference/ReferenceSourceReader.js +3 -3
- package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
- package/dist/replay/JavaScriptReplayWorker.js +95 -11
- package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
- package/dist/replay/ReplayOutcome.js +26 -15
- package/dist/replay/ReplayWorkerProtocol.js +34 -29
- package/dist/server/createServer.js +158 -94
- package/dist/server/mcpClientMetadata.js +32 -0
- package/dist/server/registerApplicationTools/characterization.js +6 -13
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
- package/dist/server/registerApplicationTools/compareVersions.js +3 -8
- package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
- package/dist/server/registerApplicationTools/coverage.js +13 -19
- package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
- package/dist/server/registerApplicationTools/readiness.js +1 -6
- package/dist/server/registerApplicationTools/traceFeature.js +3 -8
- package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
- package/dist/server/registerArtifactComparisonTool.js +12 -16
- package/dist/server/registerBrowserScenarioTool.js +1 -6
- package/dist/server/registerBrowserTools.js +37 -79
- package/dist/server/registerBundleComparisonTool.js +10 -14
- package/dist/server/registerCloseLifecycleTool.js +6 -14
- package/dist/server/registerElectronTools.js +30 -47
- package/dist/server/registerEnhancedTools.js +114 -122
- package/dist/server/registerEvidenceTools.js +5 -9
- package/dist/server/registerFunctionComparisonTool.js +11 -15
- package/dist/server/registerInvestigationTools.js +41 -57
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
- package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
- package/dist/server/registerOfficialTools.js +8 -9
- package/dist/server/registerProcessComparisonTool.js +19 -24
- package/dist/server/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +69 -40
- package/dist/server/registerSessionStatusTool.js +13 -28
- package/dist/server/registerSessionTools.js +36 -52
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/sessionToolPolicies.js +1 -5
- package/dist/server/toolRegistrationOptions.js +4 -192
- package/dist/server/toolResult.js +2 -18
- package/package.json +22 -14
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +501 -0
- package/scripts/rea.mjs +1 -11
- package/skills/reverse-engineer-anything/SKILL.md +2 -2
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/LazyToolCatalog.js +0 -134
- package/dist/server/hydrateServerTools.js +0 -191
- package/dist/server/toolInputValidation.js +0 -77
- package/scripts/package-runner-bootstrap.mjs +0 -72
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const absolutePathSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.min(1)
|
|
6
|
+
.max(16_384)
|
|
7
|
+
.refine(isAbsolute, "path must be absolute");
|
|
8
|
+
const windowIndexSchema = z.number().int().min(0).max(99);
|
|
9
|
+
const deepLinkUrlSchema = z
|
|
10
|
+
.string()
|
|
11
|
+
.min(1)
|
|
12
|
+
.max(4_096)
|
|
13
|
+
.refine((value) => {
|
|
14
|
+
try {
|
|
15
|
+
return new URL(value).protocol.length > 0;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}, "deep-link url must be an absolute URL");
|
|
21
|
+
const actionSchema = z.discriminatedUnion("kind", [
|
|
22
|
+
z.strictObject({
|
|
23
|
+
step_id: z.string().min(1).max(128),
|
|
24
|
+
kind: z.literal("click"),
|
|
25
|
+
selector: z.string().min(1).max(512),
|
|
26
|
+
window_index: windowIndexSchema.default(0),
|
|
27
|
+
}),
|
|
28
|
+
z.strictObject({
|
|
29
|
+
step_id: z.string().min(1).max(128),
|
|
30
|
+
kind: z.literal("wait"),
|
|
31
|
+
duration_ms: z.number().int().min(0).max(10_000),
|
|
32
|
+
window_index: windowIndexSchema.optional(),
|
|
33
|
+
}),
|
|
34
|
+
z.strictObject({
|
|
35
|
+
step_id: z.string().min(1).max(128),
|
|
36
|
+
kind: z.literal("renderer-reload"),
|
|
37
|
+
window_index: windowIndexSchema.default(0),
|
|
38
|
+
}),
|
|
39
|
+
z.strictObject({
|
|
40
|
+
step_id: z.string().min(1).max(128),
|
|
41
|
+
kind: z.literal("renderer-crash"),
|
|
42
|
+
window_index: windowIndexSchema.default(0),
|
|
43
|
+
}),
|
|
44
|
+
z.strictObject({
|
|
45
|
+
step_id: z.string().min(1).max(128),
|
|
46
|
+
kind: z.literal("deep-link"),
|
|
47
|
+
delivery: z.enum(["open-url", "second-instance"]),
|
|
48
|
+
url: deepLinkUrlSchema,
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
const limitsSchema = z.strictObject({
|
|
52
|
+
max_duration_ms: z.number().int().min(1).max(120_000).default(60_000),
|
|
53
|
+
action_timeout_ms: z.number().int().min(1).max(30_000).default(5_000),
|
|
54
|
+
max_actions: z.number().int().min(1).max(100).default(20),
|
|
55
|
+
max_ipc_events: z.number().int().min(1).max(10_000).default(2_000),
|
|
56
|
+
max_runtime_events: z.number().int().min(1).max(20_000).default(5_000),
|
|
57
|
+
max_processes: z.number().int().min(1).max(100).default(32),
|
|
58
|
+
max_windows: z.number().int().min(1).max(100).default(32),
|
|
59
|
+
});
|
|
60
|
+
/** Input for one explicit, provider-owned Electron runtime experiment. */
|
|
61
|
+
export const electronActiveObservationInputSchema = z
|
|
62
|
+
.strictObject({
|
|
63
|
+
schema_version: z.literal(1),
|
|
64
|
+
executable_path: absolutePathSchema,
|
|
65
|
+
application_path: absolutePathSchema,
|
|
66
|
+
application_root: absolutePathSchema,
|
|
67
|
+
args: z.array(z.string().max(4_096)).max(32).default([]),
|
|
68
|
+
actions: z.array(actionSchema).max(100).default([]),
|
|
69
|
+
limits: limitsSchema.default({
|
|
70
|
+
max_duration_ms: 60_000,
|
|
71
|
+
action_timeout_ms: 5_000,
|
|
72
|
+
max_actions: 20,
|
|
73
|
+
max_ipc_events: 2_000,
|
|
74
|
+
max_runtime_events: 5_000,
|
|
75
|
+
max_processes: 32,
|
|
76
|
+
max_windows: 32,
|
|
77
|
+
}),
|
|
78
|
+
approved: z.literal(true),
|
|
79
|
+
})
|
|
80
|
+
.superRefine((input, context) => {
|
|
81
|
+
if (input.actions.length > input.limits.max_actions)
|
|
82
|
+
context.addIssue({
|
|
83
|
+
code: "custom",
|
|
84
|
+
path: ["actions"],
|
|
85
|
+
message: "actions exceed the configured max_actions limit",
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
const ipcEventSchema = z.strictObject({
|
|
89
|
+
sequence: z.number().int().min(1),
|
|
90
|
+
correlation_id: z.string().max(256).nullable().default(null),
|
|
91
|
+
kind: z.enum([
|
|
92
|
+
"main-handler-invocation",
|
|
93
|
+
"main-event-invocation",
|
|
94
|
+
"utility-process-fork",
|
|
95
|
+
"utility-process-message",
|
|
96
|
+
"ipc-main-to-renderer",
|
|
97
|
+
"ipc-utility-to-main",
|
|
98
|
+
"ipc-renderer-send",
|
|
99
|
+
"ipc-renderer-invoke",
|
|
100
|
+
"ipc-renderer-post-message",
|
|
101
|
+
]),
|
|
102
|
+
event: z.string().max(128).nullable().optional(),
|
|
103
|
+
phase: z
|
|
104
|
+
.enum(["attempted", "completed", "blocked", "failed", "observed"])
|
|
105
|
+
.nullable()
|
|
106
|
+
.optional(),
|
|
107
|
+
channel: z.string().max(1_024).nullable(),
|
|
108
|
+
channel_truncated: z.boolean().default(false),
|
|
109
|
+
direction: z
|
|
110
|
+
.enum([
|
|
111
|
+
"renderer-to-main",
|
|
112
|
+
"main-to-renderer",
|
|
113
|
+
"main-to-utility",
|
|
114
|
+
"utility-to-main",
|
|
115
|
+
])
|
|
116
|
+
.nullable()
|
|
117
|
+
.optional(),
|
|
118
|
+
sender: z.string().max(256).nullable().optional(),
|
|
119
|
+
receiver: z.string().max(256).nullable().optional(),
|
|
120
|
+
frame: z.string().max(256).nullable().default(null),
|
|
121
|
+
target: z.string().max(256).nullable().optional(),
|
|
122
|
+
argument_shapes: z.array(z.string().max(64)).max(32),
|
|
123
|
+
argument_shapes_truncated: z.boolean().default(false),
|
|
124
|
+
result_shape: z.string().max(64).nullable(),
|
|
125
|
+
process_type: z.string().max(128).nullable(),
|
|
126
|
+
source: z.string().max(64).default("electron-active-hook"),
|
|
127
|
+
capture_method: z
|
|
128
|
+
.enum(["api-wrapper", "event-emitter", "process-hook"])
|
|
129
|
+
.default("api-wrapper"),
|
|
130
|
+
artifact_path: z.string().max(16_384).nullable().default(null),
|
|
131
|
+
artifact_sha256: z
|
|
132
|
+
.string()
|
|
133
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
134
|
+
.nullable()
|
|
135
|
+
.default(null),
|
|
136
|
+
error: z.boolean(),
|
|
137
|
+
});
|
|
138
|
+
const timelineEventSchema = z.strictObject({
|
|
139
|
+
sequence: z.number().int().min(1),
|
|
140
|
+
correlation_id: z.string().max(256).nullable().default(null),
|
|
141
|
+
kind: z.enum([
|
|
142
|
+
"main-handler-invocation",
|
|
143
|
+
"main-event-invocation",
|
|
144
|
+
"utility-process-fork",
|
|
145
|
+
"utility-process-message",
|
|
146
|
+
"ipc-main-to-renderer",
|
|
147
|
+
"ipc-utility-to-main",
|
|
148
|
+
"ipc-renderer-send",
|
|
149
|
+
"ipc-renderer-invoke",
|
|
150
|
+
"ipc-renderer-post-message",
|
|
151
|
+
"app-lifecycle",
|
|
152
|
+
"window-lifecycle",
|
|
153
|
+
"web-contents-lifecycle",
|
|
154
|
+
"navigation",
|
|
155
|
+
"shell-attempt",
|
|
156
|
+
"process-lifecycle",
|
|
157
|
+
"permission",
|
|
158
|
+
"popup-attempt",
|
|
159
|
+
"download",
|
|
160
|
+
"protocol",
|
|
161
|
+
"preload",
|
|
162
|
+
"native-addon",
|
|
163
|
+
"updater",
|
|
164
|
+
"error",
|
|
165
|
+
]),
|
|
166
|
+
event: z.string().max(128).nullable(),
|
|
167
|
+
phase: z.enum(["attempted", "completed", "blocked", "failed", "observed"]),
|
|
168
|
+
channel: z.string().max(1_024).nullable(),
|
|
169
|
+
channel_truncated: z.boolean(),
|
|
170
|
+
direction: z
|
|
171
|
+
.enum([
|
|
172
|
+
"renderer-to-main",
|
|
173
|
+
"main-to-renderer",
|
|
174
|
+
"main-to-utility",
|
|
175
|
+
"utility-to-main",
|
|
176
|
+
])
|
|
177
|
+
.nullable(),
|
|
178
|
+
sender: z.string().max(256).nullable(),
|
|
179
|
+
receiver: z.string().max(256).nullable(),
|
|
180
|
+
frame: z.string().max(256).nullable(),
|
|
181
|
+
target: z.string().max(256).nullable(),
|
|
182
|
+
argument_shapes: z.array(z.string().max(64)).max(32),
|
|
183
|
+
argument_shapes_truncated: z.boolean(),
|
|
184
|
+
result_shape: z.string().max(64).nullable(),
|
|
185
|
+
process_type: z.string().max(128).nullable(),
|
|
186
|
+
source: z.string().max(64),
|
|
187
|
+
capture_method: z.enum(["api-wrapper", "event-emitter", "process-hook"]),
|
|
188
|
+
artifact_path: z.string().max(16_384).nullable(),
|
|
189
|
+
artifact_sha256: z
|
|
190
|
+
.string()
|
|
191
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
192
|
+
.nullable(),
|
|
193
|
+
error: z.boolean(),
|
|
194
|
+
});
|
|
195
|
+
const processMetricSchema = z.strictObject({
|
|
196
|
+
pid: z.number().int().min(1),
|
|
197
|
+
type: z.string().min(1).max(128),
|
|
198
|
+
name: z.string().max(256).nullable(),
|
|
199
|
+
service_name: z.string().max(256).nullable(),
|
|
200
|
+
});
|
|
201
|
+
const windowResultSchema = z.strictObject({
|
|
202
|
+
window_id: z.string().max(256),
|
|
203
|
+
web_contents_id: z.string().max(256),
|
|
204
|
+
url: z.string().max(65_536),
|
|
205
|
+
title: z.string().max(16_384),
|
|
206
|
+
visible: z.boolean().nullable(),
|
|
207
|
+
destroyed: z.boolean(),
|
|
208
|
+
});
|
|
209
|
+
const coverageSchema = z.strictObject({
|
|
210
|
+
status: z.enum([
|
|
211
|
+
"complete",
|
|
212
|
+
"partial_attach",
|
|
213
|
+
"capture_truncated",
|
|
214
|
+
"hook_conflict",
|
|
215
|
+
"target_exited",
|
|
216
|
+
"cleanup_failed",
|
|
217
|
+
]),
|
|
218
|
+
observed_event_families: z.array(z.string().max(128)).max(32),
|
|
219
|
+
unavailable_event_families: z.array(z.string().max(128)).max(32),
|
|
220
|
+
observed_roles: z.array(z.string().max(128)).max(16),
|
|
221
|
+
pre_capture_activity: z.literal("unavailable"),
|
|
222
|
+
});
|
|
223
|
+
const actionResultSchema = z.strictObject({
|
|
224
|
+
step_id: z.string().min(1).max(128),
|
|
225
|
+
kind: z.enum([
|
|
226
|
+
"click",
|
|
227
|
+
"wait",
|
|
228
|
+
"renderer-reload",
|
|
229
|
+
"renderer-crash",
|
|
230
|
+
"deep-link",
|
|
231
|
+
]),
|
|
232
|
+
window_index: windowIndexSchema.nullable(),
|
|
233
|
+
target: z.string().max(256).nullable(),
|
|
234
|
+
status: z.enum(["completed", "failed", "cancelled"]),
|
|
235
|
+
elapsed_ms: z.number().int().min(0),
|
|
236
|
+
error: z.string().nullable(),
|
|
237
|
+
});
|
|
238
|
+
/** Bounded result of a provider-owned Electron runtime experiment. */
|
|
239
|
+
export const electronActiveObservationResultSchema = z.strictObject({
|
|
240
|
+
schema_version: z.literal(1),
|
|
241
|
+
application: z.strictObject({
|
|
242
|
+
executable_path: absolutePathSchema,
|
|
243
|
+
application_path: absolutePathSchema,
|
|
244
|
+
electron_version: z.string().min(1).max(256),
|
|
245
|
+
process_ownership: z.literal("provider-owned"),
|
|
246
|
+
cleanup: z.literal("terminated-owned-process"),
|
|
247
|
+
}),
|
|
248
|
+
actions: z.array(actionResultSchema).max(100),
|
|
249
|
+
windows: z.array(windowResultSchema).max(100),
|
|
250
|
+
windows_truncated: z.boolean(),
|
|
251
|
+
processes: z.strictObject({
|
|
252
|
+
items: z.array(processMetricSchema).max(100),
|
|
253
|
+
truncated: z.boolean(),
|
|
254
|
+
}),
|
|
255
|
+
ipc: z.strictObject({
|
|
256
|
+
events: z.array(ipcEventSchema).max(10_000),
|
|
257
|
+
observed: z.number().int().min(0),
|
|
258
|
+
retained: z.number().int().min(0),
|
|
259
|
+
truncated: z.boolean(),
|
|
260
|
+
}),
|
|
261
|
+
timeline: z
|
|
262
|
+
.strictObject({
|
|
263
|
+
events: z.array(timelineEventSchema).max(20_000),
|
|
264
|
+
observed: z.number().int().min(0),
|
|
265
|
+
retained: z.number().int().min(0),
|
|
266
|
+
truncated: z.boolean(),
|
|
267
|
+
})
|
|
268
|
+
.default({ events: [], observed: 0, retained: 0, truncated: false }),
|
|
269
|
+
coverage: coverageSchema.default({
|
|
270
|
+
status: "partial_attach",
|
|
271
|
+
observed_event_families: [],
|
|
272
|
+
unavailable_event_families: [],
|
|
273
|
+
observed_roles: [],
|
|
274
|
+
pre_capture_activity: "unavailable",
|
|
275
|
+
}),
|
|
276
|
+
limitations: z.array(z.string().max(4_096)).max(100),
|
|
277
|
+
});
|
|
@@ -25,13 +25,10 @@ export const listElectronTargetsInputSchema = z.object({
|
|
|
25
25
|
limit: z.number().int().min(1).max(200).default(100),
|
|
26
26
|
});
|
|
27
27
|
/** Input for passive structural inspection of one Electron file page. */
|
|
28
|
-
|
|
29
|
-
.object({
|
|
28
|
+
const inspectElectronPageFacts = {
|
|
30
29
|
...approvedElectronInput,
|
|
31
30
|
target_id: z.string().trim().min(1).max(256),
|
|
32
31
|
observation_ms: z.number().int().min(0).max(10_000).default(100),
|
|
33
|
-
include_script_sources: z.boolean().default(false),
|
|
34
|
-
source_capture_approved: z.boolean().default(false),
|
|
35
32
|
limits: z
|
|
36
33
|
.object({
|
|
37
34
|
max_frames: z.number().int().min(1).max(1_000).default(200),
|
|
@@ -61,14 +58,21 @@ export const inspectElectronPageInputSchema = z
|
|
|
61
58
|
max_script_source_bytes: 1_024 * 1_024,
|
|
62
59
|
max_total_script_source_bytes: 4 * 1_024 * 1_024,
|
|
63
60
|
}),
|
|
64
|
-
}
|
|
61
|
+
};
|
|
62
|
+
export const inspectElectronPageInputSchema = z
|
|
63
|
+
.union([
|
|
64
|
+
z.object({
|
|
65
|
+
...inspectElectronPageFacts,
|
|
66
|
+
include_script_sources: z.literal(false).default(false),
|
|
67
|
+
source_capture_approved: z.literal(false).default(false),
|
|
68
|
+
}),
|
|
69
|
+
z.object({
|
|
70
|
+
...inspectElectronPageFacts,
|
|
71
|
+
include_script_sources: z.literal(true),
|
|
72
|
+
source_capture_approved: z.literal(true),
|
|
73
|
+
}),
|
|
74
|
+
])
|
|
65
75
|
.superRefine((input, context) => {
|
|
66
|
-
if (input.include_script_sources && !input.source_capture_approved)
|
|
67
|
-
context.addIssue({
|
|
68
|
-
code: "custom",
|
|
69
|
-
path: ["source_capture_approved"],
|
|
70
|
-
message: "Electron script source capture requires separate approval",
|
|
71
|
-
});
|
|
72
76
|
if (input.limits.max_script_source_bytes >
|
|
73
77
|
input.limits.max_total_script_source_bytes)
|
|
74
78
|
context.addIssue({
|
|
@@ -51,7 +51,10 @@ export const collectContextBridgeMembers = (node, maximum = 128) => {
|
|
|
51
51
|
unknown: 1,
|
|
52
52
|
omitted: 0,
|
|
53
53
|
};
|
|
54
|
-
const state = {
|
|
54
|
+
const state = {
|
|
55
|
+
members: [],
|
|
56
|
+
unknown: 0,
|
|
57
|
+
};
|
|
55
58
|
collectMembersAt(node, "", 0, state);
|
|
56
59
|
const members = [...new Set(state.members)].sort(compareCodePoints);
|
|
57
60
|
return {
|
|
@@ -71,89 +71,90 @@ export const processTreeReconstructionSchema = z.strictObject({
|
|
|
71
71
|
/** Whether any reparenting was detected. */
|
|
72
72
|
has_reparenting: z.boolean().default(false),
|
|
73
73
|
});
|
|
74
|
+
const applyProcessTreeEvent = (event, state) => {
|
|
75
|
+
let node = state.nodes.get(event.pid);
|
|
76
|
+
switch (event.type) {
|
|
77
|
+
case "spawn": {
|
|
78
|
+
if (!node) {
|
|
79
|
+
node = {
|
|
80
|
+
pid: event.pid,
|
|
81
|
+
ppid: event.ppid,
|
|
82
|
+
process_name: event.process_name,
|
|
83
|
+
executable: event.executable,
|
|
84
|
+
arguments: event.arguments,
|
|
85
|
+
children: [],
|
|
86
|
+
spawn_time_ms: event.at_ms,
|
|
87
|
+
exit_time_ms: null,
|
|
88
|
+
exit_code: null,
|
|
89
|
+
is_re_exec: false,
|
|
90
|
+
is_reparented: false,
|
|
91
|
+
previous_ppid: null,
|
|
92
|
+
};
|
|
93
|
+
state.nodes.set(event.pid, node);
|
|
94
|
+
}
|
|
95
|
+
if (event.ppid !== null) {
|
|
96
|
+
const parentChildren = state.children.get(event.ppid) ?? [];
|
|
97
|
+
parentChildren.push(event.pid);
|
|
98
|
+
state.children.set(event.ppid, parentChildren);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "exit":
|
|
103
|
+
if (node) {
|
|
104
|
+
node.exit_time_ms = event.at_ms;
|
|
105
|
+
node.exit_code = event.exit_code;
|
|
106
|
+
if (node.spawn_time_ms !== null &&
|
|
107
|
+
event.at_ms - node.spawn_time_ms < 100)
|
|
108
|
+
state.shortLivedDescendants++;
|
|
109
|
+
}
|
|
110
|
+
else
|
|
111
|
+
state.eventsUnmatched++;
|
|
112
|
+
break;
|
|
113
|
+
case "re_exec":
|
|
114
|
+
if (node) {
|
|
115
|
+
node.is_re_exec = true;
|
|
116
|
+
node.executable = event.executable ?? node.executable;
|
|
117
|
+
node.arguments = event.arguments;
|
|
118
|
+
state.hasReExec = true;
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
state.eventsUnmatched++;
|
|
122
|
+
break;
|
|
123
|
+
case "reparent":
|
|
124
|
+
if (node) {
|
|
125
|
+
node.previous_ppid = node.ppid;
|
|
126
|
+
node.ppid = event.ppid;
|
|
127
|
+
node.is_reparented = true;
|
|
128
|
+
state.hasReparenting = true;
|
|
129
|
+
}
|
|
130
|
+
else
|
|
131
|
+
state.eventsUnmatched++;
|
|
132
|
+
break;
|
|
133
|
+
case "signal":
|
|
134
|
+
case "name_change":
|
|
135
|
+
case "thread_create":
|
|
136
|
+
case "thread_exit":
|
|
137
|
+
// These events are recorded but don't modify the tree structure.
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
74
141
|
/** Reconstruct a process tree from event-backed capture. */
|
|
75
142
|
export function reconstructProcessTree(events, rootPid) {
|
|
76
143
|
const nodes = new Map();
|
|
77
144
|
const children = new Map();
|
|
78
145
|
let eventsConsumed = 0;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
146
|
+
const state = {
|
|
147
|
+
nodes,
|
|
148
|
+
children,
|
|
149
|
+
eventsUnmatched: 0,
|
|
150
|
+
hasReExec: false,
|
|
151
|
+
hasReparenting: false,
|
|
152
|
+
shortLivedDescendants: 0,
|
|
153
|
+
};
|
|
83
154
|
const sorted = [...events].sort((a, b) => a.at_ms - b.at_ms);
|
|
84
155
|
for (const event of sorted) {
|
|
85
156
|
eventsConsumed++;
|
|
86
|
-
|
|
87
|
-
switch (event.type) {
|
|
88
|
-
case "spawn": {
|
|
89
|
-
if (!node) {
|
|
90
|
-
node = {
|
|
91
|
-
pid: event.pid,
|
|
92
|
-
ppid: event.ppid,
|
|
93
|
-
process_name: event.process_name,
|
|
94
|
-
executable: event.executable,
|
|
95
|
-
arguments: event.arguments,
|
|
96
|
-
children: [],
|
|
97
|
-
spawn_time_ms: event.at_ms,
|
|
98
|
-
exit_time_ms: null,
|
|
99
|
-
exit_code: null,
|
|
100
|
-
is_re_exec: false,
|
|
101
|
-
is_reparented: false,
|
|
102
|
-
previous_ppid: null,
|
|
103
|
-
};
|
|
104
|
-
nodes.set(event.pid, node);
|
|
105
|
-
}
|
|
106
|
-
if (event.ppid !== null) {
|
|
107
|
-
const parentChildren = children.get(event.ppid) ?? [];
|
|
108
|
-
parentChildren.push(event.pid);
|
|
109
|
-
children.set(event.ppid, parentChildren);
|
|
110
|
-
}
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
case "exit": {
|
|
114
|
-
if (node) {
|
|
115
|
-
node.exit_time_ms = event.at_ms;
|
|
116
|
-
node.exit_code = event.exit_code;
|
|
117
|
-
if (node.spawn_time_ms !== null &&
|
|
118
|
-
event.at_ms - node.spawn_time_ms < 100)
|
|
119
|
-
shortLivedDescendants++;
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
eventsUnmatched++;
|
|
123
|
-
}
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
case "re_exec": {
|
|
127
|
-
if (node) {
|
|
128
|
-
node.is_re_exec = true;
|
|
129
|
-
node.executable = event.executable ?? node.executable;
|
|
130
|
-
node.arguments = event.arguments;
|
|
131
|
-
hasReExec = true;
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
eventsUnmatched++;
|
|
135
|
-
}
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
case "reparent": {
|
|
139
|
-
if (node) {
|
|
140
|
-
node.previous_ppid = node.ppid;
|
|
141
|
-
node.ppid = event.ppid;
|
|
142
|
-
node.is_reparented = true;
|
|
143
|
-
hasReparenting = true;
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
eventsUnmatched++;
|
|
147
|
-
}
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
case "signal":
|
|
151
|
-
case "name_change":
|
|
152
|
-
case "thread_create":
|
|
153
|
-
case "thread_exit":
|
|
154
|
-
// These events are recorded but don't modify the tree structure
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
+
applyProcessTreeEvent(event, state);
|
|
157
158
|
}
|
|
158
159
|
// Attach children to nodes
|
|
159
160
|
for (const [pid, childPids] of children) {
|
|
@@ -165,10 +166,10 @@ export function reconstructProcessTree(events, rootPid) {
|
|
|
165
166
|
root_pid: rootPid,
|
|
166
167
|
processes: [...nodes.values()],
|
|
167
168
|
events_consumed: eventsConsumed,
|
|
168
|
-
events_unmatched: eventsUnmatched,
|
|
169
|
-
short_lived_descendants: shortLivedDescendants,
|
|
170
|
-
has_re_exec: hasReExec,
|
|
171
|
-
has_reparenting: hasReparenting,
|
|
169
|
+
events_unmatched: state.eventsUnmatched,
|
|
170
|
+
short_lived_descendants: state.shortLivedDescendants,
|
|
171
|
+
has_re_exec: state.hasReExec,
|
|
172
|
+
has_reparenting: state.hasReparenting,
|
|
172
173
|
};
|
|
173
174
|
}
|
|
174
175
|
/** Get all descendant PIDs of a given root PID. */
|
|
@@ -179,6 +180,8 @@ export function getDescendants(processes, rootPid) {
|
|
|
179
180
|
const queue = [rootPid];
|
|
180
181
|
while (queue.length > 0) {
|
|
181
182
|
const pid = queue.shift();
|
|
183
|
+
if (pid === undefined)
|
|
184
|
+
break;
|
|
182
185
|
if (visited.has(pid))
|
|
183
186
|
continue;
|
|
184
187
|
visited.add(pid);
|
|
@@ -123,14 +123,21 @@ export const stringAndNameProjection = (snapshot) => {
|
|
|
123
123
|
: sorted(values);
|
|
124
124
|
};
|
|
125
125
|
export const sorted = (values) => [...values].sort((left, right) => canonicalJson(left).localeCompare(canonicalJson(right)));
|
|
126
|
-
export const combineCoverage = (left, right) =>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
126
|
+
export const combineCoverage = (left, right) => {
|
|
127
|
+
const base = {
|
|
128
|
+
items: [...left.items, ...right.items],
|
|
129
|
+
total: left.total === null || right.total === null
|
|
130
|
+
? null
|
|
131
|
+
: left.total + right.total,
|
|
132
|
+
};
|
|
133
|
+
return left.complete && right.complete
|
|
134
|
+
? { ...base, complete: true, truncated: false }
|
|
135
|
+
: {
|
|
136
|
+
...base,
|
|
137
|
+
complete: false,
|
|
138
|
+
truncated: left.truncated || right.truncated,
|
|
139
|
+
};
|
|
140
|
+
};
|
|
134
141
|
export const project = (collection, mapper) => collection.items.map(mapper);
|
|
135
142
|
export const isAutoName = (name) => /^(?:sub_[0-9a-f]+|fcn\.)/iu.test(name);
|
|
136
143
|
const parseAddress = (value) => /^0x[0-9a-f]+$/iu.test(value) ? BigInt(value) : null;
|
|
@@ -109,8 +109,9 @@ const mergePseudocode = (pages) => {
|
|
|
109
109
|
return {
|
|
110
110
|
text: orderedValues(characters).join(""),
|
|
111
111
|
total,
|
|
112
|
-
complete
|
|
113
|
-
|
|
112
|
+
...(complete
|
|
113
|
+
? { complete: true, truncated: false }
|
|
114
|
+
: { complete: false, truncated: true }),
|
|
114
115
|
};
|
|
115
116
|
};
|
|
116
117
|
const mergeCollection = (pages, field) => {
|
|
@@ -140,8 +141,12 @@ const mergeCollection = (pages, field) => {
|
|
|
140
141
|
return {
|
|
141
142
|
items: orderedValues(items),
|
|
142
143
|
total,
|
|
143
|
-
complete
|
|
144
|
-
|
|
144
|
+
...(complete
|
|
145
|
+
? { complete: true, truncated: false }
|
|
146
|
+
: {
|
|
147
|
+
complete: false,
|
|
148
|
+
truncated: scanLimited || !unavailable,
|
|
149
|
+
}),
|
|
145
150
|
};
|
|
146
151
|
};
|
|
147
152
|
const collectionOffset = (page, field) => field === "assembly"
|