@jshookmcp/jshook 0.2.9 → 0.3.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 +2 -2
- package/README.zh.md +2 -2
- package/dist/{AntiCheatDetector-BNk-EoBt.mjs → AntiCheatDetector-CqGDXmfc.mjs} +159 -53
- package/dist/{CodeInjector-Cq8q01kp.mjs → CodeInjector-BdjRfNx7.mjs} +5 -5
- package/dist/{ConsoleMonitor-CPVQW1Y-.mjs → ConsoleMonitor-DykL3IAw.mjs} +85 -17
- package/dist/{DetailedDataManager-BQQcxh64.mjs → DetailedDataManager-HT49OrvF.mjs} +1 -1
- package/dist/{ExtensionManager-CWYgw0YW.mjs → ExtensionManager-BDMsY2Dz.mjs} +15 -8
- package/dist/{HardwareBreakpoint-B9gZCdFP.mjs → HardwareBreakpoint-Cc2AFq1Y.mjs} +3 -3
- package/dist/{HeapAnalyzer-BLDH0dCv.mjs → HeapAnalyzer-DruMgsgj.mjs} +20 -20
- package/dist/{HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs → HookGeneratorBuilders.core.generators.storage-CTbB4Lcx.mjs} +1 -74
- package/dist/{InstrumentationSession-CvPC7Jwy.mjs → InstrumentationSession-DLH0vd-z.mjs} +2 -2
- package/dist/{MemoryController-CbVdCIJF.mjs → MemoryController-CMtviNW_.mjs} +3 -3
- package/dist/{MemoryScanSession-BsDZbLYm.mjs → MemoryScanSession-ITgb_NMi.mjs} +2 -2
- package/dist/{MemoryScanner-Bcpml6II.mjs → MemoryScanner-CiL7Z3ey.mjs} +12 -9
- package/dist/{NativeMemoryManager.impl-dZtA1ZGn.mjs → NativeMemoryManager.impl-D9Lkovvn.mjs} +13 -10
- package/dist/{NativeMemoryManager.utils-B-FjA2mJ.mjs → NativeMemoryManager.utils-BBlAixF5.mjs} +1 -1
- package/dist/{PEAnalyzer-D1lzJ_VG.mjs → PEAnalyzer-DMQ44gen.mjs} +15 -15
- package/dist/{PageController-Bqm2kZ_X.mjs → PageController-BPJNqqBN.mjs} +18 -4
- package/dist/{PointerChainEngine-BOhyVsjx.mjs → PointerChainEngine-K7wN8Z-w.mjs} +10 -7
- package/dist/ProcessRegistry-zGg12QbE.mjs +74 -0
- package/dist/{ResponseBuilder-D3iFYx2N.mjs → ResponseBuilder-CJXWmWNw.mjs} +10 -10
- package/dist/{ScriptManager-aHHq0X7U.mjs → ScriptManager-ZuWD-0Jg.mjs} +195 -192
- package/dist/{Speedhack-CqdIFlQl.mjs → Speedhack-D-z0umeT.mjs} +2 -2
- package/dist/{StructureAnalyzer-DhFaPvRO.mjs → StructureAnalyzer-Cav5AVSL.mjs} +9 -6
- package/dist/{ToolCatalog-C0JGZoOm.mjs → ToolCatalog-5OJdMiF0.mjs} +81 -81
- package/dist/{ToolProbe-oC7aPrkv.mjs → ToolProbe-DbCFGyrg.mjs} +1 -1
- package/dist/{ToolRegistry-BjaF4oNz.mjs → ToolRegistry-B9krbTtI.mjs} +51 -2
- package/dist/{ToolRouter.policy-BWV67ZK-.mjs → ToolRouter.policy-BGDAGyeH.mjs} +60 -20
- package/dist/TraceRecorder-B41Z5XBj.mjs +1286 -0
- package/dist/{Win32API-CePkipZY.mjs → Win32API-C2kjj0ze.mjs} +18 -12
- package/dist/{Win32Debug-BvKs-gxc.mjs → Win32Debug-CKrGOTpo.mjs} +2 -2
- package/dist/{WorkflowEngine-CuvkZtWu.mjs → WorkflowEngine-DJ6M4opp.mjs} +226 -255
- package/dist/analysis-BHeJW2Nb.mjs +1234 -0
- package/dist/{antidebug-CqDTB_uk.mjs → antidebug-BRKeyt27.mjs} +3 -3
- package/dist/{artifactRetention-CFEprwPw.mjs → artifactRetention-CPXkUJXp.mjs} +13 -6
- package/dist/{artifacts-Bk2-_uPq.mjs → artifacts-DkfosXH3.mjs} +1 -1
- package/dist/authorization-schema-DRqyJMSk.mjs +31 -0
- package/dist/{binary-instrument-CXfpx6fT.mjs → binary-instrument--V3MAhJ4.mjs} +19 -27
- package/dist/bind-helpers-ClV34xdn.mjs +42 -0
- package/dist/{boringssl-inspector-BH2D3VKc.mjs → boringssl-inspector-Bo_LOLaS.mjs} +1 -1
- package/dist/{browser-BpOr5PEx.mjs → browser-Dx3_S2cG.mjs} +324 -37
- package/dist/capabilities-CcHlvWgK.mjs +33 -0
- package/dist/{constants-B0OANIBL.mjs → constants-CDZLOoVv.mjs} +18 -3
- package/dist/{coordination-qUbyF8KU.mjs → coordination-DgItD9DL.mjs} +2 -2
- package/dist/{debugger-gnKxRSN0.mjs → debugger-RS3RSAqs.mjs} +30 -13
- package/dist/definitions-BEoYofW5.mjs +47 -0
- package/dist/{definitions-bAhHQJq9.mjs → definitions-BRaefg3u.mjs} +11 -5
- package/dist/{definitions-DVGfrn7y.mjs → definitions-BbkvZkiv.mjs} +2 -2
- package/dist/definitions-BtWSHJ3o.mjs +17 -0
- package/dist/{definitions-BMfYXoNC.mjs → definitions-C1gCHO0i.mjs} +1 -1
- package/dist/{definitions-C1UvM5Iy.mjs → definitions-CDOg_b-l.mjs} +14 -2
- package/dist/definitions-CVPD9hzZ.mjs +54 -0
- package/dist/{definitions-Cke7zEb8.mjs → definitions-Cea8Lgl7.mjs} +1 -1
- package/dist/definitions-DAgIyjxM.mjs +10 -0
- package/dist/{definitions-B4rAvHNZ.mjs → definitions-DJA27nsL.mjs} +12 -9
- package/dist/{definitions-ClJLzsJQ.mjs → definitions-DKPFU3LW.mjs} +1 -1
- package/dist/{definitions-D3VsGcvz.mjs → definitions-DPRpZQ96.mjs} +7 -7
- package/dist/{definitions-B18eyf0B.mjs → definitions-DUE5gmdn.mjs} +1 -1
- package/dist/definitions-DYVjOtxa.mjs +26 -0
- package/dist/{definitions-BB_4jnmy.mjs → definitions-DcYLVLCo.mjs} +1 -1
- package/dist/{definitions-Beid2EB3.mjs → definitions-Pp5LI2H4.mjs} +1 -1
- package/dist/definitions-j9KdHVNR.mjs +14 -0
- package/dist/definitions-uzkjBwa7.mjs +258 -0
- package/dist/{definitions-Cq-zroAU.mjs → definitions-va-AnLuQ.mjs} +4 -4
- package/dist/{encoding-Bvz5jLRv.mjs → encoding-DJeqHmpd.mjs} +18 -4
- package/dist/{evidence-graph-bridge-C_fv9PuC.mjs → evidence-graph-bridge-DcYizFk2.mjs} +1 -0
- package/dist/{factory-DxlGh9Xf.mjs → factory-C90tBff6.mjs} +6 -6
- package/dist/flat-target-session-Dgax2Cy3.mjs +29 -0
- package/dist/{graphql-DYWzJ29s.mjs → graphql-CoHrhweh.mjs} +205 -34
- package/dist/{handlers-C67ktuRN.mjs → handlers-4jmR0nMs.mjs} +220 -32
- package/dist/{handlers-DlCJN4Td.mjs → handlers-BAHPxcch.mjs} +122 -90
- package/dist/{handlers-9sAbfIg-.mjs → handlers-BOs9b907.mjs} +849 -801
- package/dist/{handlers-DxGIq15_2.mjs → handlers-BWXEy6ef.mjs} +16 -16
- package/dist/{handlers-tB9Mp9ZK.mjs → handlers-Bndn6QvE.mjs} +31 -4
- package/dist/{handlers-CTsDAO6p.mjs → handlers-BqC4bD4s.mjs} +1 -1
- package/dist/{handlers-C87g8oCe.mjs → handlers-BtYq60bM2.mjs} +1 -1
- package/dist/{handlers-DeLOCd5m.mjs → handlers-BzgcB4iv.mjs} +17 -17
- package/dist/{handlers-Cgyg6c0U.mjs → handlers-CRyRWj2b.mjs} +237 -23
- package/dist/{handlers-U6L4xhuF.mjs → handlers-CVv2H1uq.mjs} +24 -17
- package/dist/{handlers-tiy7EIBp.mjs → handlers-Dl5a7JS4.mjs} +3 -3
- package/dist/{handlers-D6j6yka7.mjs → handlers-Dx2d7jt7.mjs} +1893 -1480
- package/dist/{handlers-Bl8zkwz1.mjs → handlers-Dz9PYsCa.mjs} +95 -6
- package/dist/handlers-HujRKC3b.mjs +661 -0
- package/dist/{handlers.impl-DS0d9fUw.mjs → handlers.impl-XWXkQfyi.mjs} +70 -24
- package/dist/{hooks-CzCWByww.mjs → hooks-B1B8NRHL.mjs} +3 -3
- package/dist/index.mjs +154 -144
- package/dist/{maintenance-P7ePRXQC.mjs → maintenance-PRMkLVRW.mjs} +35 -30
- package/dist/manifest-67Bok-Si.mjs +58 -0
- package/dist/{manifest-B3QVVeBS.mjs → manifest-6lNTMZAB2.mjs} +33 -28
- package/dist/manifest-B2duEHiH.mjs +90 -0
- package/dist/manifest-B6EY9Vm8.mjs +57 -0
- package/dist/{manifest-gZ4s_UtG.mjs → manifest-B6nKSbyY.mjs} +32 -33
- package/dist/{manifest-2ToTpjv8.mjs → manifest-BL8AQNPF.mjs} +31 -31
- package/dist/{manifest-DzwvxPJX.mjs → manifest-BSZvJJmV.mjs} +23 -14
- package/dist/{manifest-Sc_0JQ13.mjs → manifest-BU7qzUyX.mjs} +23 -23
- package/dist/{manifest-CT7zZBV1.mjs → manifest-Bl62e8WK.mjs} +24 -23
- package/dist/manifest-Bo5cXjdt.mjs +82 -0
- package/dist/manifest-BpS4gtUK.mjs +1347 -0
- package/dist/manifest-Bv65_e2W.mjs +101 -0
- package/dist/manifest-BytNIF4Z.mjs +117 -0
- package/dist/{manifest-BqrQ4Tpj.mjs → manifest-C-xtsjS3.mjs} +23 -23
- package/dist/{manifest-NXctwWQq.mjs → manifest-CDYl7OhA.mjs} +36 -38
- package/dist/manifest-CRZ3xmkD.mjs +61 -0
- package/dist/manifest-CoW6u4Tp.mjs +132 -0
- package/dist/manifest-Cq5zN_8A.mjs +50 -0
- package/dist/{manifest-CAhOuvSl.mjs → manifest-D7YZM_2e.mjs} +75 -85
- package/dist/{manifest-DCyjf4n2.mjs → manifest-DE_VrAeQ.mjs} +27 -7
- package/dist/manifest-DGsXSCpT.mjs +39 -0
- package/dist/{manifest-BB2J8IMJ.mjs → manifest-DJ2vfEuW.mjs} +48 -41
- package/dist/{manifest-3g71z6Bg.mjs → manifest-DPXDYhEu.mjs} +26 -25
- package/dist/manifest-Dd4fQb0a.mjs +322 -0
- package/dist/{manifest-CXsRWjjI.mjs → manifest-Deq6opGg.mjs} +95 -96
- package/dist/{manifest-C9RT5nk32.mjs → manifest-DfJTafJK.mjs} +14 -11
- package/dist/manifest-DgOdgN_j.mjs +50 -0
- package/dist/{manifest-BmtZzQiQ2.mjs → manifest-DlbMW4v4.mjs} +17 -15
- package/dist/{manifest-DrbmZcFl2.mjs → manifest-DmVfbH0w.mjs} +212 -91
- package/dist/manifest-Dog6Ddjr.mjs +109 -0
- package/dist/manifest-DvgU5FWb.mjs +58 -0
- package/dist/manifest-HsfDBs7j.mjs +50 -0
- package/dist/manifest-I8oQHvCG.mjs +186 -0
- package/dist/manifest-NvH_a-av.mjs +786 -0
- package/dist/{manifest-Dh8WBmEW.mjs → manifest-cEJU1v0Z.mjs} +24 -24
- package/dist/manifest-wOl5XLB12.mjs +112 -0
- package/dist/{modules-C184v-S9.mjs → modules-tZozf0LQ.mjs} +130 -860
- package/dist/{mojo-ipc-B_H61Afw.mjs → mojo-ipc-DXNEXEqb.mjs} +141 -26
- package/dist/{network-671Cw6hV.mjs → network-CPVvwvFg.mjs} +1329 -823
- package/dist/{outputPaths-B1uGmrWZ.mjs → outputPaths-um7lCRY3.mjs} +4 -8
- package/dist/{platform-WmNn8Sxb.mjs → platform-CYeFoTWp.mjs} +101 -10
- package/dist/{process-QcbIy5Zq.mjs → process-BTbgcVc6.mjs} +251 -346
- package/dist/{proxy-DqNs0bAd.mjs → proxy-r8YN6nP1.mjs} +30 -8
- package/dist/{registry-D-6e18lB.mjs → registry-Bl8ZQW61.mjs} +3 -3
- package/dist/{response-BQVP-xUn.mjs → response-CWhh2aLo.mjs} +7 -1
- package/dist/{shared-state-board-DV-dpHFJ.mjs → shared-state-board-BoZnSoj-.mjs} +2 -2
- package/dist/{sourcemap-Dq8ez8vS.mjs → sourcemap-BIDHUVXy.mjs} +350 -66
- package/dist/{streaming-BUQ0VJsg.mjs → streaming-Dal6utPp.mjs} +13 -13
- package/dist/{tool-builder-DCbIC5Eo.mjs → tool-builder-BHJp32mV.mjs} +1 -1
- package/dist/{transform-CiYJfNX0.mjs → transform-DRVgGG90.mjs} +18 -14
- package/dist/wasm-BYx5UOeG.mjs +1044 -0
- package/dist/webcrack-Be0_FccV.mjs +747 -0
- package/dist/{workflow-f3xJOcjx.mjs → workflow-BpuKEtvn.mjs} +8 -8
- package/package.json +76 -43
- package/dist/TraceRecorder-DgxyVbdQ.mjs +0 -519
- package/dist/analysis-CL9uACt9.mjs +0 -463
- package/dist/bind-helpers-xFfRF-qm.mjs +0 -22
- package/dist/definitions-6M-eejaT.mjs +0 -53
- package/dist/definitions-B3QdlrHv.mjs +0 -34
- package/dist/definitions-CXEI7QC72.mjs +0 -216
- package/dist/definitions-C_4r7Fo-2.mjs +0 -14
- package/dist/definitions-CkFDALoa.mjs +0 -26
- package/dist/definitions-Cy3Sl6gV.mjs +0 -34
- package/dist/definitions-LKpC3-nL.mjs +0 -9
- package/dist/handlers-DdFzXLvF.mjs +0 -446
- package/dist/manifest-82baTv4U.mjs +0 -45
- package/dist/manifest-BKbgbSiY.mjs +0 -60
- package/dist/manifest-Bcf-TJzH.mjs +0 -848
- package/dist/manifest-Bnd7kqEY.mjs +0 -55
- package/dist/manifest-BqQX6OQC2.mjs +0 -65
- package/dist/manifest-Br4RPFt5.mjs +0 -370
- package/dist/manifest-C5qDjysN.mjs +0 -107
- package/dist/manifest-CBYWCUBJ.mjs +0 -51
- package/dist/manifest-CFADCRa1.mjs +0 -37
- package/dist/manifest-CQVhavRF.mjs +0 -114
- package/dist/manifest-CV12bcrF.mjs +0 -121
- package/dist/manifest-CZLUCfG02.mjs +0 -95
- package/dist/manifest-D6phHKFd.mjs +0 -131
- package/dist/manifest-DHsnKgP6.mjs +0 -60
- package/dist/manifest-Df_dliIe.mjs +0 -55
- package/dist/manifest-DhKRAT8_.mjs +0 -92
- package/dist/manifest-DlpTj4ic2.mjs +0 -193
- package/dist/manifest-DuwHjUa5.mjs +0 -70
- package/dist/manifest-qSleDqdO.mjs +0 -1023
- package/dist/wasm-DQTnHDs4.mjs +0 -531
- /package/dist/{CacheAdapters-CDe5WPSV.mjs → CacheAdapters-jJFy20G-.mjs} +0 -0
- /package/dist/{DarwinAPI-BNPxu0RH.mjs → DarwinAPI-ETyy0xyo.mjs} +0 -0
- /package/dist/{EventBus-DgPmwpeu.mjs → EventBus-DFKvADm3.mjs} +0 -0
- /package/dist/{EvidenceGraphBridge-SFesNera.mjs → EvidenceGraphBridge-318Oi0Lf.mjs} +0 -0
- /package/dist/{FingerprintManager-gzWtkKuf.mjs → FingerprintManager-BN4UQWnX.mjs} +0 -0
- /package/dist/{PrerequisiteError-Dl33Svkz.mjs → PrerequisiteError-TuyZIs6n.mjs} +0 -0
- /package/dist/{ReverseEvidenceGraph-Dlsk94LC.mjs → ReverseEvidenceGraph-C02-gXOh.mjs} +0 -0
- /package/dist/{StealthVerifier-Bo4T3bz8.mjs → StealthVerifier-BWmPgQsv.mjs} +0 -0
- /package/dist/{VersionDetector-CwVLVdDM.mjs → VersionDetector-K3V4vGsw.mjs} +0 -0
- /package/dist/{betterSqlite3-0pqusHHH.mjs → betterSqlite3-DLSBZodi.mjs} +0 -0
- /package/dist/{concurrency-Bt0yv1kJ.mjs → concurrency-Drev_Vz9.mjs} +0 -0
- /package/dist/{formatAddress-DVkj9kpI.mjs → formatAddress-nnMvEohD.mjs} +0 -0
- /package/dist/{parse-args-BlRjqlkL.mjs → parse-args-B4cY5Vx5.mjs} +0 -0
- /package/dist/{ssrf-policy-ZaUfvhq7.mjs → ssrf-policy-Dsqd-DTX.mjs} +0 -0
- /package/dist/{types-CPhOReNX.mjs → types-DDBWs9UP.mjs} +0 -0
|
@@ -139,11 +139,17 @@ function getPsapi() {
|
|
|
139
139
|
}
|
|
140
140
|
return psapi;
|
|
141
141
|
}
|
|
142
|
+
function toPointerBigInt(value) {
|
|
143
|
+
if (value === null || value === void 0) return 0n;
|
|
144
|
+
if (typeof value === "bigint") return value;
|
|
145
|
+
if (typeof value === "number") return BigInt(value);
|
|
146
|
+
return koffi.address(value);
|
|
147
|
+
}
|
|
142
148
|
/**
|
|
143
149
|
* Open a process handle
|
|
144
150
|
*/
|
|
145
151
|
function OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId) {
|
|
146
|
-
return getKernel32().func("void * OpenProcess(uint32, int, uint32)")(dwDesiredAccess, bInheritHandle ? 1 : 0, dwProcessId);
|
|
152
|
+
return toPointerBigInt(getKernel32().func("void * OpenProcess(uint32, int, uint32)")(dwDesiredAccess, bInheritHandle ? 1 : 0, dwProcessId));
|
|
147
153
|
}
|
|
148
154
|
/**
|
|
149
155
|
* Close a handle
|
|
@@ -155,7 +161,7 @@ function CloseHandle(hObject) {
|
|
|
155
161
|
* Read process memory - returns buffer directly
|
|
156
162
|
*/
|
|
157
163
|
function ReadProcessMemory(hProcess, lpBaseAddress, size) {
|
|
158
|
-
const fn = getKernel32().func("int ReadProcessMemory(void *, void *, _Out_ uint8_t
|
|
164
|
+
const fn = getKernel32().func("int ReadProcessMemory(void *, void *, _Out_ uint8_t *, size_t, _Out_ size_t *)");
|
|
159
165
|
const buffer = Buffer.alloc(size);
|
|
160
166
|
const bytesReadBuf = Buffer.alloc(8);
|
|
161
167
|
if (fn(hProcess, lpBaseAddress, buffer, BigInt(size), bytesReadBuf) === 0) {
|
|
@@ -168,7 +174,7 @@ function ReadProcessMemory(hProcess, lpBaseAddress, size) {
|
|
|
168
174
|
* Write process memory
|
|
169
175
|
*/
|
|
170
176
|
function WriteProcessMemory(hProcess, lpBaseAddress, data) {
|
|
171
|
-
const fn = getKernel32().func("int WriteProcessMemory(void *, void *, uint8_t
|
|
177
|
+
const fn = getKernel32().func("int WriteProcessMemory(void *, void *, uint8_t *, size_t, _Out_ size_t *)");
|
|
172
178
|
const bytesWrittenBuf = Buffer.alloc(8);
|
|
173
179
|
if (fn(hProcess, lpBaseAddress, data, BigInt(data.length), bytesWrittenBuf) === 0) {
|
|
174
180
|
const error = GetLastError();
|
|
@@ -181,7 +187,7 @@ function WriteProcessMemory(hProcess, lpBaseAddress, data) {
|
|
|
181
187
|
* Uses Buffer parsing to avoid koffi struct registration issues
|
|
182
188
|
*/
|
|
183
189
|
function VirtualQueryEx(hProcess, lpAddress) {
|
|
184
|
-
const fn = getKernel32().func("size_t VirtualQueryEx(void *, void *, _Out_ uint8_t
|
|
190
|
+
const fn = getKernel32().func("size_t VirtualQueryEx(void *, void *, _Out_ uint8_t *, size_t)");
|
|
185
191
|
const structSize = 48;
|
|
186
192
|
const buffer = Buffer.alloc(structSize);
|
|
187
193
|
const result = fn(hProcess, lpAddress, buffer, BigInt(structSize));
|
|
@@ -217,7 +223,7 @@ function VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect) {
|
|
|
217
223
|
* Allocate memory in another process
|
|
218
224
|
*/
|
|
219
225
|
function VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect) {
|
|
220
|
-
return getKernel32().func("void * VirtualAllocEx(void *, void *, size_t, uint32, uint32)")(hProcess, lpAddress, BigInt(dwSize), flAllocationType, flProtect);
|
|
226
|
+
return toPointerBigInt(getKernel32().func("void * VirtualAllocEx(void *, void *, size_t, uint32, uint32)")(hProcess, lpAddress, BigInt(dwSize), flAllocationType, flProtect));
|
|
221
227
|
}
|
|
222
228
|
/**
|
|
223
229
|
* Free memory in another process
|
|
@@ -232,7 +238,7 @@ function CreateRemoteThread(hProcess, lpStartAddress, lpParameter) {
|
|
|
232
238
|
const fn = getKernel32().func("void * CreateRemoteThread(void *, void *, size_t, void *, void *, uint32, _Out_ uint32 *)");
|
|
233
239
|
const threadIdBuf = Buffer.alloc(4);
|
|
234
240
|
return {
|
|
235
|
-
handle: fn(hProcess, null, 0n, lpStartAddress, lpParameter, 0, threadIdBuf),
|
|
241
|
+
handle: toPointerBigInt(fn(hProcess, null, 0n, lpStartAddress, lpParameter, 0, threadIdBuf)),
|
|
236
242
|
threadId: threadIdBuf.readUInt32LE(0)
|
|
237
243
|
};
|
|
238
244
|
}
|
|
@@ -240,13 +246,13 @@ function CreateRemoteThread(hProcess, lpStartAddress, lpParameter) {
|
|
|
240
246
|
* Get module handle by name
|
|
241
247
|
*/
|
|
242
248
|
function GetModuleHandle(lpModuleName) {
|
|
243
|
-
return getKernel32().func("void * GetModuleHandleA(char *)")(lpModuleName);
|
|
249
|
+
return toPointerBigInt(getKernel32().func("void * GetModuleHandleA(char *)")(lpModuleName));
|
|
244
250
|
}
|
|
245
251
|
/**
|
|
246
252
|
* Get function address from module
|
|
247
253
|
*/
|
|
248
254
|
function GetProcAddress(hModule, lpProcName) {
|
|
249
|
-
return getKernel32().func("void * GetProcAddress(void *, char *)")(hModule, lpProcName);
|
|
255
|
+
return toPointerBigInt(getKernel32().func("void * GetProcAddress(void *, char *)")(hModule, lpProcName));
|
|
250
256
|
}
|
|
251
257
|
/**
|
|
252
258
|
* Get last error code
|
|
@@ -269,7 +275,7 @@ function NtQueryInformationProcess(hProcess, processInformationClass) {
|
|
|
269
275
|
* Enumerate process modules
|
|
270
276
|
*/
|
|
271
277
|
function EnumProcessModules(hProcess, maxModules = 1024) {
|
|
272
|
-
const fn = getPsapi().func("int EnumProcessModules(void *, _Out_ void
|
|
278
|
+
const fn = getPsapi().func("int EnumProcessModules(void *, _Out_ void *, uint32, _Out_ uint32 *)");
|
|
273
279
|
const moduleBuf = Buffer.alloc(maxModules * 8);
|
|
274
280
|
const neededBuf = Buffer.alloc(4);
|
|
275
281
|
const result = fn(hProcess, moduleBuf, maxModules * 8, neededBuf);
|
|
@@ -287,7 +293,7 @@ function EnumProcessModules(hProcess, maxModules = 1024) {
|
|
|
287
293
|
* Get module base name
|
|
288
294
|
*/
|
|
289
295
|
function GetModuleBaseName(hProcess, hModule, maxSize = 260) {
|
|
290
|
-
const fn = getPsapi().func("uint32 GetModuleBaseNameA(void *, void *, _Out_ char
|
|
296
|
+
const fn = getPsapi().func("uint32 GetModuleBaseNameA(void *, void *, _Out_ char *, uint32)");
|
|
291
297
|
const buffer = Buffer.alloc(maxSize);
|
|
292
298
|
fn(hProcess, hModule, buffer, maxSize);
|
|
293
299
|
let len = 0;
|
|
@@ -299,7 +305,7 @@ function GetModuleBaseName(hProcess, hModule, maxSize = 260) {
|
|
|
299
305
|
* Returns null when the API is unavailable or the module path cannot be resolved.
|
|
300
306
|
*/
|
|
301
307
|
function GetModuleFileNameEx(hProcess, hModule, maxSize = 32768) {
|
|
302
|
-
const fn = getPsapi().func("uint32 GetModuleFileNameExA(void *, void *, _Out_ char
|
|
308
|
+
const fn = getPsapi().func("uint32 GetModuleFileNameExA(void *, void *, _Out_ char *, uint32)");
|
|
303
309
|
const buffer = Buffer.alloc(maxSize);
|
|
304
310
|
const result = fn(hProcess, hModule, buffer, maxSize);
|
|
305
311
|
if (typeof result !== "number" || result <= 0) return null;
|
|
@@ -312,7 +318,7 @@ function GetModuleFileNameEx(hProcess, hModule, maxSize = 32768) {
|
|
|
312
318
|
* Uses Buffer parsing to avoid koffi struct registration issues
|
|
313
319
|
*/
|
|
314
320
|
function GetModuleInformation(hProcess, hModule) {
|
|
315
|
-
const fn = getPsapi().func("int GetModuleInformation(void *, void *, _Out_ uint8_t
|
|
321
|
+
const fn = getPsapi().func("int GetModuleInformation(void *, void *, _Out_ uint8_t *, uint32)");
|
|
316
322
|
const buffer = Buffer.alloc(24);
|
|
317
323
|
const result = fn(hProcess, hModule, buffer, 24);
|
|
318
324
|
const info = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as logger } from "./logger-Dh_xb7_2.mjs";
|
|
2
|
-
import { r as GetLastError, t as CloseHandle } from "./Win32API-
|
|
2
|
+
import { r as GetLastError, t as CloseHandle } from "./Win32API-C2kjj0ze.mjs";
|
|
3
3
|
import koffi from "koffi";
|
|
4
4
|
//#region src/native/Win32Debug.ts
|
|
5
5
|
/**
|
|
@@ -156,7 +156,7 @@ function DebugSetProcessKillOnExit(killOnExit) {
|
|
|
156
156
|
getKernel32().func("int DebugSetProcessKillOnExit(int)")(killOnExit ? 1 : 0);
|
|
157
157
|
}
|
|
158
158
|
function WaitForDebugEvent(timeoutMs) {
|
|
159
|
-
const fn = getKernel32().func("int WaitForDebugEvent(_Out_ uint8_t
|
|
159
|
+
const fn = getKernel32().func("int WaitForDebugEvent(_Out_ uint8_t *, uint32)");
|
|
160
160
|
const buf = Buffer.alloc(176);
|
|
161
161
|
if (fn(buf, timeoutMs) === 0) return null;
|
|
162
162
|
const info = {
|
|
@@ -1,59 +1,10 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-CjcI7cDX.mjs";
|
|
2
2
|
import { t as logger } from "./logger-Dh_xb7_2.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { l as getRoutingState, o as getEffectivePrerequisites } from "./ToolRouter.policy-BGDAGyeH.mjs";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
-
//#region src/server/workflows/
|
|
6
|
-
var WorkflowRunStore = class {
|
|
7
|
-
runs = /* @__PURE__ */ new Map();
|
|
8
|
-
lastSuccess = /* @__PURE__ */ new Map();
|
|
9
|
-
recordSuccess(result) {
|
|
10
|
-
const entry = {
|
|
11
|
-
workflowId: result.workflowId,
|
|
12
|
-
runId: result.runId,
|
|
13
|
-
startedAt: result.startedAt,
|
|
14
|
-
finishedAt: result.finishedAt,
|
|
15
|
-
durationMs: result.durationMs,
|
|
16
|
-
status: "success",
|
|
17
|
-
stepResultKeys: Object.keys(result.stepResults)
|
|
18
|
-
};
|
|
19
|
-
this.runs.set(result.runId, entry);
|
|
20
|
-
this.lastSuccess.set(result.workflowId, result);
|
|
21
|
-
logger.debug(`workflow run recorded: ${result.runId} (${result.workflowId})`);
|
|
22
|
-
}
|
|
23
|
-
recordError(workflowId, runId, startedAt, error) {
|
|
24
|
-
const entry = {
|
|
25
|
-
workflowId,
|
|
26
|
-
runId,
|
|
27
|
-
startedAt,
|
|
28
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29
|
-
durationMs: Date.now() - new Date(startedAt).getTime(),
|
|
30
|
-
status: "error",
|
|
31
|
-
stepResultKeys: []
|
|
32
|
-
};
|
|
33
|
-
this.runs.set(runId, entry);
|
|
34
|
-
logger.debug(`workflow run error: ${runId} (${workflowId}): ${error}`);
|
|
35
|
-
}
|
|
36
|
-
getRun(runId) {
|
|
37
|
-
return this.runs.get(runId);
|
|
38
|
-
}
|
|
39
|
-
getLastSuccess(workflowId) {
|
|
40
|
-
return this.lastSuccess.get(workflowId);
|
|
41
|
-
}
|
|
42
|
-
listRuns(workflowId) {
|
|
43
|
-
const entries = [...this.runs.values()];
|
|
44
|
-
if (workflowId) return entries.filter((e) => e.workflowId === workflowId);
|
|
45
|
-
return entries;
|
|
46
|
-
}
|
|
47
|
-
clear() {
|
|
48
|
-
this.runs.clear();
|
|
49
|
-
this.lastSuccess.clear();
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
//#endregion
|
|
53
|
-
//#region src/server/workflows/WorkflowEngine.ts
|
|
54
|
-
var WorkflowEngine_exports = /* @__PURE__ */ __exportAll({ executeExtensionWorkflow: () => executeExtensionWorkflow });
|
|
5
|
+
//#region src/server/workflows/WorkflowDataBus.ts
|
|
55
6
|
/**
|
|
56
|
-
*
|
|
7
|
+
* Cross-node data bus for dynamic parameter passing.
|
|
57
8
|
*
|
|
58
9
|
* Supports expression templates like "${get-requests.scriptId}" to reference
|
|
59
10
|
* outputs from previous steps.
|
|
@@ -66,11 +17,6 @@ var WorkflowDataBus = class {
|
|
|
66
17
|
get(key) {
|
|
67
18
|
return this.store.get(key);
|
|
68
19
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Get a value at a specific path within a stored object.
|
|
71
|
-
* @param key - The key in the store
|
|
72
|
-
* @param path - Dot-separated path (e.g., "content.0.text")
|
|
73
|
-
*/
|
|
74
20
|
getValueAtPath(key, path) {
|
|
75
21
|
const value = this.store.get(key);
|
|
76
22
|
if (!value || typeof value !== "object") return value;
|
|
@@ -83,58 +29,19 @@ var WorkflowDataBus = class {
|
|
|
83
29
|
}
|
|
84
30
|
}, obj);
|
|
85
31
|
}
|
|
86
|
-
/**
|
|
87
|
-
* Resolve expression templates like "${stepId.fieldPath}".
|
|
88
|
-
* If the value is not an expression, returns it as-is.
|
|
89
|
-
*/
|
|
90
32
|
resolve(template) {
|
|
91
33
|
const match = template.match(/^\$\{(.+)\}$/);
|
|
92
34
|
if (!match || !match[1]) return template;
|
|
93
35
|
const ref = match[1];
|
|
94
36
|
const dotIndex = ref.indexOf(".");
|
|
95
37
|
if (dotIndex === -1) return this.store.get(ref);
|
|
96
|
-
|
|
97
|
-
const fieldPath = ref.slice(dotIndex + 1);
|
|
98
|
-
return this.getValueAtPath(stepId, fieldPath);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
var PreflightError = class extends Error {
|
|
102
|
-
constructor(warnings) {
|
|
103
|
-
super(`Workflow preflight failed with ${warnings.length} unsatisfied prerequisite(s)`);
|
|
104
|
-
this.warnings = warnings;
|
|
105
|
-
this.name = "PreflightError";
|
|
38
|
+
return this.getValueAtPath(ref.slice(0, dotIndex), ref.slice(dotIndex + 1));
|
|
106
39
|
}
|
|
107
40
|
};
|
|
108
|
-
const globalRunStore = new WorkflowRunStore();
|
|
109
|
-
function extractConfigValue(config, path, fallback) {
|
|
110
|
-
const segments = path.split(".").filter(Boolean);
|
|
111
|
-
let current = config;
|
|
112
|
-
for (const segment of segments) {
|
|
113
|
-
if (!current || typeof current !== "object") return fallback;
|
|
114
|
-
current = current[segment];
|
|
115
|
-
}
|
|
116
|
-
return current ?? fallback;
|
|
117
|
-
}
|
|
118
|
-
function sleep(ms) {
|
|
119
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
120
|
-
}
|
|
121
|
-
async function withTimeout(promise, timeoutMs, label) {
|
|
122
|
-
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return promise;
|
|
123
|
-
return new Promise((resolve, reject) => {
|
|
124
|
-
const timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
125
|
-
promise.then((value) => {
|
|
126
|
-
clearTimeout(timeoutId);
|
|
127
|
-
resolve(value);
|
|
128
|
-
}, (error) => {
|
|
129
|
-
clearTimeout(timeoutId);
|
|
130
|
-
reject(error);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
41
|
function parseToolPayload(response) {
|
|
135
|
-
if (!response || typeof response !== "object") return
|
|
42
|
+
if (!response || typeof response !== "object") return;
|
|
136
43
|
const text = response.content?.find((item) => item.type === "text")?.text;
|
|
137
|
-
if (typeof text !== "string") return
|
|
44
|
+
if (typeof text !== "string") return;
|
|
138
45
|
try {
|
|
139
46
|
const parsed = JSON.parse(text);
|
|
140
47
|
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
@@ -143,7 +50,7 @@ function parseToolPayload(response) {
|
|
|
143
50
|
}
|
|
144
51
|
}
|
|
145
52
|
function responseIndicatesFailure(response) {
|
|
146
|
-
if (!response || typeof response !== "object") return
|
|
53
|
+
if (!response || typeof response !== "object") return;
|
|
147
54
|
if (response.isError) return "Tool returned MCP error response";
|
|
148
55
|
const payload = parseToolPayload(response);
|
|
149
56
|
if (payload?.success === false) return typeof payload.error === "string" ? payload.error : "Tool reported success=false";
|
|
@@ -182,7 +89,7 @@ function collectSuccessStats(value) {
|
|
|
182
89
|
success: 0,
|
|
183
90
|
failure: 1
|
|
184
91
|
};
|
|
185
|
-
if ("error" in
|
|
92
|
+
if ("error" in obj) return {
|
|
186
93
|
success: 0,
|
|
187
94
|
failure: 1
|
|
188
95
|
};
|
|
@@ -199,10 +106,6 @@ function resolveInputFrom(mapping, dataBus) {
|
|
|
199
106
|
}
|
|
200
107
|
return resolved;
|
|
201
108
|
}
|
|
202
|
-
/**
|
|
203
|
-
* Recursively resolve expression templates in input values.
|
|
204
|
-
* Handles nested objects and arrays.
|
|
205
|
-
*/
|
|
206
109
|
function resolveInputValues(input, dataBus) {
|
|
207
110
|
if (!input) return {};
|
|
208
111
|
const resolved = {};
|
|
@@ -214,11 +117,228 @@ function resolveValue(value, dataBus) {
|
|
|
214
117
|
if (Array.isArray(value)) return value.map((item) => resolveValue(item, dataBus));
|
|
215
118
|
if (value && typeof value === "object") {
|
|
216
119
|
const resolved = {};
|
|
217
|
-
for (const [
|
|
120
|
+
for (const [key, nestedValue] of Object.entries(value)) resolved[key] = resolveValue(nestedValue, dataBus);
|
|
218
121
|
return resolved;
|
|
219
122
|
}
|
|
220
123
|
return value;
|
|
221
124
|
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/server/workflows/WorkflowPredicates.ts
|
|
127
|
+
function getWorkflowVariable(stepResults, keyPath) {
|
|
128
|
+
if (stepResults.has(keyPath)) return stepResults.get(keyPath);
|
|
129
|
+
const [stepId, ...fieldSegments] = keyPath.split(".");
|
|
130
|
+
if (!stepId || !stepResults.has(stepId)) return;
|
|
131
|
+
let current = stepResults.get(stepId);
|
|
132
|
+
if (current && typeof current === "object") {
|
|
133
|
+
const payload = parseToolPayload(current);
|
|
134
|
+
if (payload) current = payload;
|
|
135
|
+
}
|
|
136
|
+
for (const segment of fieldSegments) {
|
|
137
|
+
if (current && typeof current === "object") {
|
|
138
|
+
const arrayMatch = segment.match(/^(\d+)$/);
|
|
139
|
+
if (arrayMatch && Array.isArray(current)) {
|
|
140
|
+
current = current[Number(arrayMatch[1])];
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
current = current[segment];
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
return current;
|
|
149
|
+
}
|
|
150
|
+
function deepEquals(left, right) {
|
|
151
|
+
if (left === right) return true;
|
|
152
|
+
if (typeof left !== typeof right) return false;
|
|
153
|
+
if (left && right && typeof left === "object" && typeof right === "object") {
|
|
154
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
155
|
+
if (Array.isArray(left)) {
|
|
156
|
+
const leftArray = left;
|
|
157
|
+
const rightArray = right;
|
|
158
|
+
return leftArray.length === rightArray.length && leftArray.every((value, index) => deepEquals(value, rightArray[index]));
|
|
159
|
+
}
|
|
160
|
+
const leftKeys = Object.keys(left);
|
|
161
|
+
const rightKeys = Object.keys(right);
|
|
162
|
+
if (leftKeys.length !== rightKeys.length) return false;
|
|
163
|
+
return leftKeys.every((key) => deepEquals(left[key], right[key]));
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
async function evaluatePredicate(node, ctx) {
|
|
168
|
+
if (node.predicateFn) return await node.predicateFn(ctx);
|
|
169
|
+
if (node.predicateId === "always_true") return true;
|
|
170
|
+
if (node.predicateId === "always_false") return false;
|
|
171
|
+
if (node.predicateId === "any_step_failed") return [...ctx.stepResults.values()].some((value) => collectSuccessStats(value).failure > 0);
|
|
172
|
+
const successRateMatch = node.predicateId.match(/success_rate_gte_(\d+)/i);
|
|
173
|
+
if (successRateMatch?.[1]) {
|
|
174
|
+
const threshold = Number(successRateMatch[1]);
|
|
175
|
+
const aggregate = [...ctx.stepResults.values()].reduce((acc, value) => {
|
|
176
|
+
const next = collectSuccessStats(value);
|
|
177
|
+
acc.success += next.success;
|
|
178
|
+
acc.failure += next.failure;
|
|
179
|
+
return acc;
|
|
180
|
+
}, {
|
|
181
|
+
success: 0,
|
|
182
|
+
failure: 0
|
|
183
|
+
});
|
|
184
|
+
const total = aggregate.success + aggregate.failure;
|
|
185
|
+
return total > 0 && aggregate.success / total >= threshold / 100;
|
|
186
|
+
}
|
|
187
|
+
const equalsMatch = node.predicateId.match(/^variable_equals_(.+?)_(.+)$/);
|
|
188
|
+
if (equalsMatch?.[1] && equalsMatch[2]) return deepEquals(getWorkflowVariable(ctx.stepResults, equalsMatch[1]), equalsMatch[2]);
|
|
189
|
+
const containsMatch = node.predicateId.match(/^variable_contains_(.+?)_(.+)$/);
|
|
190
|
+
if (containsMatch?.[1] && containsMatch[2]) {
|
|
191
|
+
const value = getWorkflowVariable(ctx.stepResults, containsMatch[1]);
|
|
192
|
+
if (typeof value !== "string" && !Array.isArray(value)) return false;
|
|
193
|
+
return String(value).includes(containsMatch[2]);
|
|
194
|
+
}
|
|
195
|
+
const matchesMatch = node.predicateId.match(/^variable_matches_(.+?)_(.+)$/);
|
|
196
|
+
if (matchesMatch?.[1] && matchesMatch[2]) {
|
|
197
|
+
const value = getWorkflowVariable(ctx.stepResults, matchesMatch[1]);
|
|
198
|
+
if (typeof value !== "string") return false;
|
|
199
|
+
try {
|
|
200
|
+
return new RegExp(matchesMatch[2]).test(value);
|
|
201
|
+
} catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
throw new Error(`Unknown workflow predicateId "${node.predicateId}"`);
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/server/workflows/WorkflowPreflight.ts
|
|
209
|
+
function collectToolNodes(node) {
|
|
210
|
+
switch (node.kind) {
|
|
211
|
+
case "tool": return [node];
|
|
212
|
+
case "sequence":
|
|
213
|
+
case "parallel": return node.steps.flatMap((step) => collectToolNodes(step));
|
|
214
|
+
case "branch": return [...collectToolNodes(node.whenTrue), ...node.whenFalse ? collectToolNodes(node.whenFalse) : []];
|
|
215
|
+
case "fallback": return [...collectToolNodes(node.primary), ...collectToolNodes(node.fallback)];
|
|
216
|
+
default: return [];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function getEvidenceState(ctx) {
|
|
220
|
+
try {
|
|
221
|
+
const evidenceGraph = ctx.getDomainInstance("evidenceGraph");
|
|
222
|
+
return evidenceGraph ? {
|
|
223
|
+
hasGraph: true,
|
|
224
|
+
nodeCount: evidenceGraph.nodeCount,
|
|
225
|
+
edgeCount: evidenceGraph.edgeCount
|
|
226
|
+
} : {
|
|
227
|
+
hasGraph: false,
|
|
228
|
+
nodeCount: 0,
|
|
229
|
+
edgeCount: 0
|
|
230
|
+
};
|
|
231
|
+
} catch {
|
|
232
|
+
return {
|
|
233
|
+
hasGraph: false,
|
|
234
|
+
nodeCount: 0,
|
|
235
|
+
edgeCount: 0
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function collectUnsatisfiedPrerequisites(graph, routingState) {
|
|
240
|
+
const prerequisites = getEffectivePrerequisites();
|
|
241
|
+
const warnings = [];
|
|
242
|
+
for (const toolNode of collectToolNodes(graph)) {
|
|
243
|
+
const toolPrerequisites = prerequisites[toolNode.toolName] ?? [];
|
|
244
|
+
for (const prerequisite of toolPrerequisites) {
|
|
245
|
+
if (prerequisite.check(routingState)) continue;
|
|
246
|
+
warnings.push({
|
|
247
|
+
nodeId: toolNode.id,
|
|
248
|
+
toolName: toolNode.toolName,
|
|
249
|
+
condition: prerequisite.condition,
|
|
250
|
+
fix: prerequisite.fix
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return warnings;
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/server/workflows/WorkflowRunStore.ts
|
|
258
|
+
var WorkflowRunStore = class {
|
|
259
|
+
runs = /* @__PURE__ */ new Map();
|
|
260
|
+
lastSuccess = /* @__PURE__ */ new Map();
|
|
261
|
+
recordSuccess(result) {
|
|
262
|
+
const entry = {
|
|
263
|
+
workflowId: result.workflowId,
|
|
264
|
+
runId: result.runId,
|
|
265
|
+
startedAt: result.startedAt,
|
|
266
|
+
finishedAt: result.finishedAt,
|
|
267
|
+
durationMs: result.durationMs,
|
|
268
|
+
status: "success",
|
|
269
|
+
stepResultKeys: Object.keys(result.stepResults)
|
|
270
|
+
};
|
|
271
|
+
this.runs.set(result.runId, entry);
|
|
272
|
+
this.lastSuccess.set(result.workflowId, result);
|
|
273
|
+
logger.debug(`workflow run recorded: ${result.runId} (${result.workflowId})`);
|
|
274
|
+
}
|
|
275
|
+
recordError(workflowId, runId, startedAt, error) {
|
|
276
|
+
const entry = {
|
|
277
|
+
workflowId,
|
|
278
|
+
runId,
|
|
279
|
+
startedAt,
|
|
280
|
+
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
281
|
+
durationMs: Date.now() - new Date(startedAt).getTime(),
|
|
282
|
+
status: "error",
|
|
283
|
+
stepResultKeys: []
|
|
284
|
+
};
|
|
285
|
+
this.runs.set(runId, entry);
|
|
286
|
+
logger.debug(`workflow run error: ${runId} (${workflowId}): ${error}`);
|
|
287
|
+
}
|
|
288
|
+
getRun(runId) {
|
|
289
|
+
return this.runs.get(runId);
|
|
290
|
+
}
|
|
291
|
+
getLastSuccess(workflowId) {
|
|
292
|
+
return this.lastSuccess.get(workflowId);
|
|
293
|
+
}
|
|
294
|
+
listRuns(workflowId) {
|
|
295
|
+
const entries = [...this.runs.values()];
|
|
296
|
+
if (workflowId) return entries.filter((e) => e.workflowId === workflowId);
|
|
297
|
+
return entries;
|
|
298
|
+
}
|
|
299
|
+
clear() {
|
|
300
|
+
this.runs.clear();
|
|
301
|
+
this.lastSuccess.clear();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/server/workflows/WorkflowEngine.types.ts
|
|
306
|
+
var PreflightError = class extends Error {
|
|
307
|
+
constructor(warnings) {
|
|
308
|
+
super(`Workflow preflight failed with ${warnings.length} unsatisfied prerequisite(s)`);
|
|
309
|
+
this.warnings = warnings;
|
|
310
|
+
this.name = "PreflightError";
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/server/workflows/WorkflowEngine.ts
|
|
315
|
+
var WorkflowEngine_exports = /* @__PURE__ */ __exportAll({ executeExtensionWorkflow: () => executeExtensionWorkflow });
|
|
316
|
+
const globalRunStore = new WorkflowRunStore();
|
|
317
|
+
function extractConfigValue(config, path, fallback) {
|
|
318
|
+
const segments = path.split(".").filter(Boolean);
|
|
319
|
+
let current = config;
|
|
320
|
+
for (const segment of segments) {
|
|
321
|
+
if (!current || typeof current !== "object") return fallback;
|
|
322
|
+
current = current[segment];
|
|
323
|
+
}
|
|
324
|
+
return current ?? fallback;
|
|
325
|
+
}
|
|
326
|
+
function sleep(ms) {
|
|
327
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
328
|
+
}
|
|
329
|
+
async function withTimeout(promise, timeoutMs, label) {
|
|
330
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return promise;
|
|
331
|
+
return new Promise((resolve, reject) => {
|
|
332
|
+
const timeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error(`${label} timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
333
|
+
promise.then((value) => {
|
|
334
|
+
clearTimeout(timeoutId);
|
|
335
|
+
resolve(value);
|
|
336
|
+
}, (error) => {
|
|
337
|
+
clearTimeout(timeoutId);
|
|
338
|
+
reject(error);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
}
|
|
222
342
|
async function runToolNode(ctx, node, overrides, executionContext) {
|
|
223
343
|
const fromResolved = node.inputFrom ? resolveInputFrom(node.inputFrom, executionContext.dataBus) : {};
|
|
224
344
|
const mergedInput = {
|
|
@@ -281,100 +401,6 @@ async function runParallelNode(ctx, node, executionContext, options) {
|
|
|
281
401
|
await Promise.all(Array.from({ length: Math.min(concurrency, node.steps.length) }, () => worker()));
|
|
282
402
|
return keyedResults;
|
|
283
403
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Get a variable value from workflow context by key path.
|
|
286
|
-
* Supports dot notation for nested access within step results.
|
|
287
|
-
*/
|
|
288
|
-
function getWorkflowVariable(stepResults, keyPath) {
|
|
289
|
-
if (stepResults.has(keyPath)) return stepResults.get(keyPath);
|
|
290
|
-
const segments = keyPath.split(".");
|
|
291
|
-
const stepId = segments[0];
|
|
292
|
-
const fieldSegments = segments.slice(1);
|
|
293
|
-
if (!stepId || !stepResults.has(stepId)) return;
|
|
294
|
-
let current = stepResults.get(stepId);
|
|
295
|
-
if (current && typeof current === "object") {
|
|
296
|
-
const payload = parseToolPayload(current);
|
|
297
|
-
if (payload) current = payload;
|
|
298
|
-
}
|
|
299
|
-
for (const segment of fieldSegments) if (current && typeof current === "object") {
|
|
300
|
-
const arrayMatch = segment.match(/^(\d+)$/);
|
|
301
|
-
if (arrayMatch && Array.isArray(current)) {
|
|
302
|
-
current = current[Number(arrayMatch[1])];
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
current = current[segment];
|
|
306
|
-
} else return;
|
|
307
|
-
return current;
|
|
308
|
-
}
|
|
309
|
-
async function evaluatePredicate(node, ctx) {
|
|
310
|
-
if (node.predicateFn) return await node.predicateFn(ctx);
|
|
311
|
-
if (node.predicateId === "always_true") return true;
|
|
312
|
-
if (node.predicateId === "always_false") return false;
|
|
313
|
-
if (node.predicateId === "any_step_failed") return [...ctx.stepResults.values()].some((value) => collectSuccessStats(value).failure > 0);
|
|
314
|
-
const successRateMatch = node.predicateId.match(/success_rate_gte_(\d+)/i);
|
|
315
|
-
if (successRateMatch) {
|
|
316
|
-
const threshold = Number(successRateMatch[1]);
|
|
317
|
-
const aggregate = [...ctx.stepResults.values()].reduce((acc, value) => {
|
|
318
|
-
const next = collectSuccessStats(value);
|
|
319
|
-
acc.success += next.success;
|
|
320
|
-
acc.failure += next.failure;
|
|
321
|
-
return acc;
|
|
322
|
-
}, {
|
|
323
|
-
success: 0,
|
|
324
|
-
failure: 0
|
|
325
|
-
});
|
|
326
|
-
const total = aggregate.success + aggregate.failure;
|
|
327
|
-
if (total === 0) return false;
|
|
328
|
-
return aggregate.success / total >= threshold / 100;
|
|
329
|
-
}
|
|
330
|
-
const equalsMatch = node.predicateId.match(/^variable_equals_(.+?)_(.+)$/);
|
|
331
|
-
if (equalsMatch && equalsMatch[1] && equalsMatch[2]) {
|
|
332
|
-
const keyPath = equalsMatch[1];
|
|
333
|
-
const expectedValue = equalsMatch[2];
|
|
334
|
-
return deepEquals(getWorkflowVariable(ctx.stepResults, keyPath), expectedValue);
|
|
335
|
-
}
|
|
336
|
-
const containsMatch = node.predicateId.match(/^variable_contains_(.+?)_(.+)$/);
|
|
337
|
-
if (containsMatch && containsMatch[1] && containsMatch[2]) {
|
|
338
|
-
const keyPath = containsMatch[1];
|
|
339
|
-
const substring = containsMatch[2];
|
|
340
|
-
const value = getWorkflowVariable(ctx.stepResults, keyPath);
|
|
341
|
-
if (typeof value !== "string" && !Array.isArray(value)) return false;
|
|
342
|
-
return String(value).includes(substring);
|
|
343
|
-
}
|
|
344
|
-
const matchesMatch = node.predicateId.match(/^variable_matches_(.+?)_(.+)$/);
|
|
345
|
-
if (matchesMatch && matchesMatch[1] && matchesMatch[2]) {
|
|
346
|
-
const keyPath = matchesMatch[1];
|
|
347
|
-
const pattern = matchesMatch[2];
|
|
348
|
-
const value = getWorkflowVariable(ctx.stepResults, keyPath);
|
|
349
|
-
if (typeof value !== "string") return false;
|
|
350
|
-
try {
|
|
351
|
-
return new RegExp(pattern).test(value);
|
|
352
|
-
} catch {
|
|
353
|
-
return false;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
throw new Error(`Unknown workflow predicateId "${node.predicateId}"`);
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Deep equality check for two values.
|
|
360
|
-
*/
|
|
361
|
-
function deepEquals(a, b) {
|
|
362
|
-
if (a === b) return true;
|
|
363
|
-
if (typeof a !== typeof b) return false;
|
|
364
|
-
if (a && b && typeof a === "object" && typeof b === "object") {
|
|
365
|
-
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
366
|
-
if (Array.isArray(a)) {
|
|
367
|
-
const arrA = a;
|
|
368
|
-
const arrB = b;
|
|
369
|
-
return arrA.length === arrB.length && arrA.every((v, i) => deepEquals(v, arrB[i]));
|
|
370
|
-
}
|
|
371
|
-
const keysA = Object.keys(a);
|
|
372
|
-
const keysB = Object.keys(b);
|
|
373
|
-
if (keysA.length !== keysB.length) return false;
|
|
374
|
-
return keysA.every((key) => deepEquals(a[key], b[key]));
|
|
375
|
-
}
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
404
|
async function executeNode(ctx, node, executionContext, options) {
|
|
379
405
|
executionContext.emitSpan("workflow.node.start", {
|
|
380
406
|
nodeId: node.id,
|
|
@@ -426,61 +452,6 @@ async function executeNode(ctx, node, executionContext, options) {
|
|
|
426
452
|
});
|
|
427
453
|
return result;
|
|
428
454
|
}
|
|
429
|
-
/** Recursively collect all ToolNode instances from a workflow graph. */
|
|
430
|
-
function collectToolNodes(node) {
|
|
431
|
-
switch (node.kind) {
|
|
432
|
-
case "tool": return [node];
|
|
433
|
-
case "sequence":
|
|
434
|
-
case "parallel": return node.steps.flatMap((step) => collectToolNodes(step));
|
|
435
|
-
case "branch": return [...collectToolNodes(node.whenTrue), ...node.whenFalse ? collectToolNodes(node.whenFalse) : []];
|
|
436
|
-
case "fallback": {
|
|
437
|
-
const fallbackNode = node;
|
|
438
|
-
return [...collectToolNodes(fallbackNode.primary), ...collectToolNodes(fallbackNode.fallback)];
|
|
439
|
-
}
|
|
440
|
-
default: return [];
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Collect unsatisfied prerequisites for all tool nodes in the workflow graph.
|
|
445
|
-
* Returns an array of warnings (not errors — preflight is warn-only mode).
|
|
446
|
-
*/
|
|
447
|
-
function getEvidenceState(ctx) {
|
|
448
|
-
try {
|
|
449
|
-
const evidenceGraph = ctx.getDomainInstance("evidenceGraph");
|
|
450
|
-
return evidenceGraph ? {
|
|
451
|
-
hasGraph: true,
|
|
452
|
-
nodeCount: evidenceGraph.nodeCount,
|
|
453
|
-
edgeCount: evidenceGraph.edgeCount
|
|
454
|
-
} : {
|
|
455
|
-
hasGraph: false,
|
|
456
|
-
nodeCount: 0,
|
|
457
|
-
edgeCount: 0
|
|
458
|
-
};
|
|
459
|
-
} catch {
|
|
460
|
-
return {
|
|
461
|
-
hasGraph: false,
|
|
462
|
-
nodeCount: 0,
|
|
463
|
-
edgeCount: 0
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
function collectUnsatisfiedPrerequisites(graph, routingState) {
|
|
468
|
-
const prerequisites = getEffectivePrerequisites();
|
|
469
|
-
const warnings = [];
|
|
470
|
-
for (const toolNode of collectToolNodes(graph)) {
|
|
471
|
-
const toolPrerequisites = prerequisites[toolNode.toolName] ?? [];
|
|
472
|
-
for (const prerequisite of toolPrerequisites) {
|
|
473
|
-
if (prerequisite.check(routingState)) continue;
|
|
474
|
-
warnings.push({
|
|
475
|
-
nodeId: toolNode.id,
|
|
476
|
-
toolName: toolNode.toolName,
|
|
477
|
-
condition: prerequisite.condition,
|
|
478
|
-
fix: prerequisite.fix
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
return warnings;
|
|
483
|
-
}
|
|
484
455
|
async function executeExtensionWorkflow(ctx, workflow, options = {}) {
|
|
485
456
|
const runId = randomUUID();
|
|
486
457
|
const profile = options.profile ?? String(ctx.baseTier ?? "workflow");
|