elasticdash-sdk 0.2.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/LICENSE +21 -0
- package/README.md +775 -0
- package/dist/browser-ui.d.ts +43 -0
- package/dist/browser-ui.d.ts.map +1 -0
- package/dist/browser-ui.js +246 -0
- package/dist/browser-ui.js.map +1 -0
- package/dist/capture/event.d.ts +33 -0
- package/dist/capture/event.d.ts.map +1 -0
- package/dist/capture/event.js +2 -0
- package/dist/capture/event.js.map +1 -0
- package/dist/capture/index.d.ts +4 -0
- package/dist/capture/index.d.ts.map +1 -0
- package/dist/capture/index.js +4 -0
- package/dist/capture/index.js.map +1 -0
- package/dist/capture/recorder.d.ts +24 -0
- package/dist/capture/recorder.d.ts.map +1 -0
- package/dist/capture/recorder.js +46 -0
- package/dist/capture/recorder.js.map +1 -0
- package/dist/capture/replay.d.ts +20 -0
- package/dist/capture/replay.d.ts.map +1 -0
- package/dist/capture/replay.js +47 -0
- package/dist/capture/replay.js.map +1 -0
- package/dist/ci/api-client.d.ts +38 -0
- package/dist/ci/api-client.d.ts.map +1 -0
- package/dist/ci/api-client.js +96 -0
- package/dist/ci/api-client.js.map +1 -0
- package/dist/ci/benchmark.d.ts +33 -0
- package/dist/ci/benchmark.d.ts.map +1 -0
- package/dist/ci/benchmark.js +213 -0
- package/dist/ci/benchmark.js.map +1 -0
- package/dist/ci/ed-runner.d.ts +48 -0
- package/dist/ci/ed-runner.d.ts.map +1 -0
- package/dist/ci/ed-runner.js +260 -0
- package/dist/ci/ed-runner.js.map +1 -0
- package/dist/ci/executor.d.ts +13 -0
- package/dist/ci/executor.d.ts.map +1 -0
- package/dist/ci/executor.js +542 -0
- package/dist/ci/executor.js.map +1 -0
- package/dist/ci/git-info.d.ts +17 -0
- package/dist/ci/git-info.d.ts.map +1 -0
- package/dist/ci/git-info.js +102 -0
- package/dist/ci/git-info.js.map +1 -0
- package/dist/ci/index.d.ts +6 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +4 -0
- package/dist/ci/index.js.map +1 -0
- package/dist/ci/measurement.d.ts +9 -0
- package/dist/ci/measurement.d.ts.map +1 -0
- package/dist/ci/measurement.js +15 -0
- package/dist/ci/measurement.js.map +1 -0
- package/dist/ci/replay.d.ts +31 -0
- package/dist/ci/replay.d.ts.map +1 -0
- package/dist/ci/replay.js +96 -0
- package/dist/ci/replay.js.map +1 -0
- package/dist/ci/reporters/default.d.ts +8 -0
- package/dist/ci/reporters/default.d.ts.map +1 -0
- package/dist/ci/reporters/default.js +46 -0
- package/dist/ci/reporters/default.js.map +1 -0
- package/dist/ci/reporters/index.d.ts +8 -0
- package/dist/ci/reporters/index.d.ts.map +1 -0
- package/dist/ci/reporters/index.js +14 -0
- package/dist/ci/reporters/index.js.map +1 -0
- package/dist/ci/reporters/json.d.ts +8 -0
- package/dist/ci/reporters/json.d.ts.map +1 -0
- package/dist/ci/reporters/json.js +14 -0
- package/dist/ci/reporters/json.js.map +1 -0
- package/dist/ci/reporters/junit.d.ts +8 -0
- package/dist/ci/reporters/junit.d.ts.map +1 -0
- package/dist/ci/reporters/junit.js +48 -0
- package/dist/ci/reporters/junit.js.map +1 -0
- package/dist/ci/runner.d.ts +3 -0
- package/dist/ci/runner.d.ts.map +1 -0
- package/dist/ci/runner.js +187 -0
- package/dist/ci/runner.js.map +1 -0
- package/dist/ci/test-discovery.d.ts +5 -0
- package/dist/ci/test-discovery.d.ts.map +1 -0
- package/dist/ci/test-discovery.js +11 -0
- package/dist/ci/test-discovery.js.map +1 -0
- package/dist/ci/test-loader.d.ts +19 -0
- package/dist/ci/test-loader.d.ts.map +1 -0
- package/dist/ci/test-loader.js +149 -0
- package/dist/ci/test-loader.js.map +1 -0
- package/dist/ci/test-registry.d.ts +42 -0
- package/dist/ci/test-registry.d.ts.map +1 -0
- package/dist/ci/test-registry.js +18 -0
- package/dist/ci/test-registry.js.map +1 -0
- package/dist/ci/trace-schema.d.ts +30 -0
- package/dist/ci/trace-schema.d.ts.map +1 -0
- package/dist/ci/trace-schema.js +66 -0
- package/dist/ci/trace-schema.js.map +1 -0
- package/dist/ci/trace-writer.d.ts +16 -0
- package/dist/ci/trace-writer.d.ts.map +1 -0
- package/dist/ci/trace-writer.js +108 -0
- package/dist/ci/trace-writer.js.map +1 -0
- package/dist/ci/types.d.ts +108 -0
- package/dist/ci/types.d.ts.map +1 -0
- package/dist/ci/types.js +3 -0
- package/dist/ci/types.js.map +1 -0
- package/dist/ci/upload-client.d.ts +74 -0
- package/dist/ci/upload-client.d.ts.map +1 -0
- package/dist/ci/upload-client.js +195 -0
- package/dist/ci/upload-client.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +716 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/agent-state.d.ts +47 -0
- package/dist/core/agent-state.d.ts.map +1 -0
- package/dist/core/agent-state.js +137 -0
- package/dist/core/agent-state.js.map +1 -0
- package/dist/core/judge-utils.d.ts +22 -0
- package/dist/core/judge-utils.d.ts.map +1 -0
- package/dist/core/judge-utils.js +211 -0
- package/dist/core/judge-utils.js.map +1 -0
- package/dist/core/registry.d.ts +28 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +52 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/dashboard-server.d.ts +65 -0
- package/dist/dashboard-server.d.ts.map +1 -0
- package/dist/dashboard-server.js +3940 -0
- package/dist/dashboard-server.js.map +1 -0
- package/dist/execution/tool-runner.d.ts +26 -0
- package/dist/execution/tool-runner.d.ts.map +1 -0
- package/dist/execution/tool-runner.js +316 -0
- package/dist/execution/tool-runner.js.map +1 -0
- package/dist/html/dashboard.html +2218 -0
- package/dist/http.d.ts +14 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +13 -0
- package/dist/http.js.map +1 -0
- package/dist/index.cjs +8102 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptors/ai-interceptor.d.ts +26 -0
- package/dist/interceptors/ai-interceptor.d.ts.map +1 -0
- package/dist/interceptors/ai-interceptor.js +756 -0
- package/dist/interceptors/ai-interceptor.js.map +1 -0
- package/dist/interceptors/db-auto.d.ts +8 -0
- package/dist/interceptors/db-auto.d.ts.map +1 -0
- package/dist/interceptors/db-auto.js +217 -0
- package/dist/interceptors/db-auto.js.map +1 -0
- package/dist/interceptors/db.d.ts +23 -0
- package/dist/interceptors/db.d.ts.map +1 -0
- package/dist/interceptors/db.js +137 -0
- package/dist/interceptors/db.js.map +1 -0
- package/dist/interceptors/http.d.ts +28 -0
- package/dist/interceptors/http.d.ts.map +1 -0
- package/dist/interceptors/http.js +356 -0
- package/dist/interceptors/http.js.map +1 -0
- package/dist/interceptors/side-effects.d.ts +7 -0
- package/dist/interceptors/side-effects.d.ts.map +1 -0
- package/dist/interceptors/side-effects.js +72 -0
- package/dist/interceptors/side-effects.js.map +1 -0
- package/dist/interceptors/telemetry-push.d.ts +142 -0
- package/dist/interceptors/telemetry-push.d.ts.map +1 -0
- package/dist/interceptors/telemetry-push.js +463 -0
- package/dist/interceptors/telemetry-push.js.map +1 -0
- package/dist/interceptors/tool.d.ts +2 -0
- package/dist/interceptors/tool.d.ts.map +1 -0
- package/dist/interceptors/tool.js +274 -0
- package/dist/interceptors/tool.js.map +1 -0
- package/dist/interceptors/workflow-ai.d.ts +5 -0
- package/dist/interceptors/workflow-ai.d.ts.map +1 -0
- package/dist/interceptors/workflow-ai.js +382 -0
- package/dist/interceptors/workflow-ai.js.map +1 -0
- package/dist/internals/conditional-recorder.d.ts +21 -0
- package/dist/internals/conditional-recorder.d.ts.map +1 -0
- package/dist/internals/conditional-recorder.js +54 -0
- package/dist/internals/conditional-recorder.js.map +1 -0
- package/dist/internals/mock-resolver.d.ts +146 -0
- package/dist/internals/mock-resolver.d.ts.map +1 -0
- package/dist/internals/mock-resolver.js +427 -0
- package/dist/internals/mock-resolver.js.map +1 -0
- package/dist/matchers/index.d.ts +96 -0
- package/dist/matchers/index.d.ts.map +1 -0
- package/dist/matchers/index.js +668 -0
- package/dist/matchers/index.js.map +1 -0
- package/dist/observability.d.ts +82 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +471 -0
- package/dist/observability.js.map +1 -0
- package/dist/portal-executor.d.ts +30 -0
- package/dist/portal-executor.d.ts.map +1 -0
- package/dist/portal-executor.js +324 -0
- package/dist/portal-executor.js.map +1 -0
- package/dist/portal-server.d.ts +3 -0
- package/dist/portal-server.d.ts.map +1 -0
- package/dist/portal-server.js +279 -0
- package/dist/portal-server.js.map +1 -0
- package/dist/proxy/llm-capture.d.ts +14 -0
- package/dist/proxy/llm-capture.d.ts.map +1 -0
- package/dist/proxy/llm-capture.js +264 -0
- package/dist/proxy/llm-capture.js.map +1 -0
- package/dist/reporter.d.ts +3 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +72 -0
- package/dist/reporter.js.map +1 -0
- package/dist/runWorkflowSubprocess.d.ts +14 -0
- package/dist/runWorkflowSubprocess.d.ts.map +1 -0
- package/dist/runWorkflowSubprocess.js +66 -0
- package/dist/runWorkflowSubprocess.js.map +1 -0
- package/dist/runner.d.ts +16 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +138 -0
- package/dist/runner.js.map +1 -0
- package/dist/socket-connector.d.ts +22 -0
- package/dist/socket-connector.d.ts.map +1 -0
- package/dist/socket-connector.js +104 -0
- package/dist/socket-connector.js.map +1 -0
- package/dist/telemetry-batcher.d.ts +56 -0
- package/dist/telemetry-batcher.d.ts.map +1 -0
- package/dist/telemetry-batcher.js +143 -0
- package/dist/telemetry-batcher.js.map +1 -0
- package/dist/test-setup.d.ts +12 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +13 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/tool-registry.d.ts +31 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +73 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tool-runner-worker.d.ts +2 -0
- package/dist/tool-runner-worker.d.ts.map +1 -0
- package/dist/tool-runner-worker.js +215 -0
- package/dist/tool-runner-worker.js.map +1 -0
- package/dist/trace-adapter/context.d.ts +72 -0
- package/dist/trace-adapter/context.d.ts.map +1 -0
- package/dist/trace-adapter/context.js +80 -0
- package/dist/trace-adapter/context.js.map +1 -0
- package/dist/tracing.d.ts +2 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +59 -0
- package/dist/tracing.js.map +1 -0
- package/dist/trigger-executor.d.ts +12 -0
- package/dist/trigger-executor.d.ts.map +1 -0
- package/dist/trigger-executor.js +130 -0
- package/dist/trigger-executor.js.map +1 -0
- package/dist/types/portal.d.ts +76 -0
- package/dist/types/portal.d.ts.map +1 -0
- package/dist/types/portal.js +2 -0
- package/dist/types/portal.js.map +1 -0
- package/dist/utils/debug.d.ts +3 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +8 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/license-error.d.ts +23 -0
- package/dist/utils/license-error.d.ts.map +1 -0
- package/dist/utils/license-error.js +42 -0
- package/dist/utils/license-error.js.map +1 -0
- package/dist/utils/redact.d.ts +7 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +26 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/workflow-runner-worker.d.ts +2 -0
- package/dist/workflow-runner-worker.d.ts.map +1 -0
- package/dist/workflow-runner-worker.js +329 -0
- package/dist/workflow-runner-worker.js.map +1 -0
- package/dist/workflow-runner.d.ts +14 -0
- package/dist/workflow-runner.d.ts.map +1 -0
- package/dist/workflow-runner.js +34 -0
- package/dist/workflow-runner.js.map +1 -0
- package/docs/agent-coding-instructions.md +138 -0
- package/docs/agent-integration-guide.md +564 -0
- package/docs/agents.md +140 -0
- package/docs/dashboard.md +394 -0
- package/docs/deno.md +69 -0
- package/docs/instrumentation.md +424 -0
- package/docs/langfuse-trace-structure.md +145 -0
- package/docs/matchers.md +173 -0
- package/docs/observability_contract.md +192 -0
- package/docs/observability_mode.md +195 -0
- package/docs/quickstart.md +621 -0
- package/docs/security-compliance.md +566 -0
- package/docs/test-writing-guidelines.md +444 -0
- package/docs/tools.md +165 -0
- package/docs/workflow-modes.md +253 -0
- package/package.json +76 -0
- package/src/browser-ui.ts +281 -0
- package/src/capture/event.ts +30 -0
- package/src/capture/index.ts +3 -0
- package/src/capture/recorder.ts +62 -0
- package/src/capture/replay.ts +55 -0
- package/src/ci/api-client.ts +136 -0
- package/src/ci/benchmark.ts +257 -0
- package/src/ci/ed-runner.ts +351 -0
- package/src/ci/executor.ts +671 -0
- package/src/ci/git-info.ts +127 -0
- package/src/ci/index.ts +5 -0
- package/src/ci/measurement.ts +25 -0
- package/src/ci/replay.ts +127 -0
- package/src/ci/reporters/default.ts +50 -0
- package/src/ci/reporters/index.ts +21 -0
- package/src/ci/reporters/json.ts +18 -0
- package/src/ci/reporters/junit.ts +61 -0
- package/src/ci/runner.ts +208 -0
- package/src/ci/test-discovery.ts +16 -0
- package/src/ci/test-loader.ts +187 -0
- package/src/ci/test-registry.ts +62 -0
- package/src/ci/trace-schema.ts +96 -0
- package/src/ci/trace-writer.ts +107 -0
- package/src/ci/types.ts +115 -0
- package/src/ci/upload-client.ts +300 -0
- package/src/cli.ts +811 -0
- package/src/core/agent-state.ts +162 -0
- package/src/core/judge-utils.ts +232 -0
- package/src/core/registry.ts +92 -0
- package/src/dashboard-server.ts +2047 -0
- package/src/execution/tool-runner.ts +352 -0
- package/src/html/dashboard.html +2218 -0
- package/src/http.ts +13 -0
- package/src/index.ts +138 -0
- package/src/interceptors/ai-interceptor.ts +798 -0
- package/src/interceptors/db-auto.ts +243 -0
- package/src/interceptors/db.ts +156 -0
- package/src/interceptors/http.ts +393 -0
- package/src/interceptors/side-effects.ts +83 -0
- package/src/interceptors/telemetry-push.ts +537 -0
- package/src/interceptors/tool.ts +287 -0
- package/src/interceptors/workflow-ai.ts +419 -0
- package/src/internals/conditional-recorder.ts +63 -0
- package/src/internals/mock-resolver.ts +492 -0
- package/src/matchers/index.ts +824 -0
- package/src/observability.ts +501 -0
- package/src/portal-executor.ts +355 -0
- package/src/portal-server.ts +304 -0
- package/src/proxy/llm-capture.ts +301 -0
- package/src/reporter.ts +81 -0
- package/src/runWorkflowSubprocess.ts +74 -0
- package/src/runner.ts +178 -0
- package/src/socket-connector.ts +117 -0
- package/src/telemetry-batcher.ts +191 -0
- package/src/test-setup.ts +16 -0
- package/src/tool-registry.ts +94 -0
- package/src/tool-runner-worker.ts +244 -0
- package/src/trace-adapter/context.ts +156 -0
- package/src/tracing.ts +62 -0
- package/src/trigger-executor.ts +171 -0
- package/src/types/agent.d.ts +63 -0
- package/src/types/expect.d.ts +81 -0
- package/src/types/modules.d.ts +2 -0
- package/src/types/portal.ts +69 -0
- package/src/utils/debug.ts +8 -0
- package/src/utils/license-error.ts +43 -0
- package/src/utils/redact.ts +25 -0
- package/src/workflow-runner-worker.ts +386 -0
- package/src/workflow-runner.ts +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-runner-worker.d.ts","sourceRoot":"","sources":["../src/tool-runner-worker.ts"],"names":[],"mappings":"AAIA,OAAO,eAAe,CAAA"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Mark this process as an Elasticdash worker before anything else runs
|
|
2
|
+
;
|
|
3
|
+
globalThis.__ELASTICDASH_WORKER__ = true;
|
|
4
|
+
// Ensure .env is loaded in the worker subprocess
|
|
5
|
+
import 'dotenv/config';
|
|
6
|
+
/**
|
|
7
|
+
* tool-runner-worker.ts
|
|
8
|
+
*
|
|
9
|
+
* Subprocess entry point for running a single tool function in an isolated
|
|
10
|
+
* Node.js process, guaranteeing no stale ESM/tsx module cache.
|
|
11
|
+
*
|
|
12
|
+
* Protocol (via stdin/stdout):
|
|
13
|
+
* stdin — one JSON line: { toolsModulePath, toolName, args, frozenEvents? }
|
|
14
|
+
* stdout — prefixed result line: __ELASTICDASH_RESULT__:{...json...}
|
|
15
|
+
*
|
|
16
|
+
* When frozenEvents are provided, sets up an HttpRunContext so that all
|
|
17
|
+
* freezable actions within the tool (wrapAI, wrapDB, and fetch-intercepted
|
|
18
|
+
* HTTP calls) will replay from frozen data instead of hitting real services.
|
|
19
|
+
*/
|
|
20
|
+
import { pathToFileURL } from 'node:url';
|
|
21
|
+
const RESULT_PREFIX = '__ELASTICDASH_RESULT__:';
|
|
22
|
+
function writeResult(result) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
process.stdout.write(RESULT_PREFIX + JSON.stringify(result) + '\n', (err) => err ? reject(err) : resolve());
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Set up frozen event replay context.
|
|
29
|
+
*
|
|
30
|
+
* For HTTP events: uses **URL-based matching** via a fetch wrapper, which is
|
|
31
|
+
* robust against ID counter drift.
|
|
32
|
+
*
|
|
33
|
+
* For AI and DB events: uses the HttpRunContext frozen map with sequential
|
|
34
|
+
* ID-based matching. All freezable event types (AI + DB) are included in the
|
|
35
|
+
* map and re-indexed in original execution order, so the shared nextId()
|
|
36
|
+
* counter stays aligned across interleaved wrapAI and wrapDB calls.
|
|
37
|
+
*/
|
|
38
|
+
async function setupFrozenContext(frozenEvents) {
|
|
39
|
+
if (frozenEvents.length === 0)
|
|
40
|
+
return;
|
|
41
|
+
// Always install URL-based fetch replay for HTTP events — this is the
|
|
42
|
+
// reliable matching strategy for tool reruns in subprocesses.
|
|
43
|
+
installFrozenFetchFallback(frozenEvents);
|
|
44
|
+
// Set up HttpRunContext for all freezable event types (AI + DB).
|
|
45
|
+
// Both wrapAI and wrapDB call httpCtx.nextId() sequentially, so we must
|
|
46
|
+
// include all freezable types in the frozen map, re-indexed in original
|
|
47
|
+
// execution order, to keep the sequential counter aligned.
|
|
48
|
+
const freezableEvents = frozenEvents
|
|
49
|
+
.filter(e => e.type === 'ai' || e.type === 'db')
|
|
50
|
+
.sort((a, b) => a.id - b.id); // preserve original execution order
|
|
51
|
+
if (freezableEvents.length > 0) {
|
|
52
|
+
try {
|
|
53
|
+
const telemetryPush = await import('./interceptors/telemetry-push.js');
|
|
54
|
+
const workflowEvents = freezableEvents.map((e, i) => ({
|
|
55
|
+
id: i + 1,
|
|
56
|
+
type: e.type,
|
|
57
|
+
name: e.name,
|
|
58
|
+
input: e.input,
|
|
59
|
+
output: e.output,
|
|
60
|
+
timestamp: e.timestamp,
|
|
61
|
+
durationMs: e.durationMs ?? 0,
|
|
62
|
+
streamed: e.streamed,
|
|
63
|
+
streamRaw: e.streamRaw,
|
|
64
|
+
}));
|
|
65
|
+
telemetryPush.setHttpRunContext('frozen-rerun', '');
|
|
66
|
+
const ctx = telemetryPush.getHttpRunContext();
|
|
67
|
+
if (ctx) {
|
|
68
|
+
for (const e of workflowEvents) {
|
|
69
|
+
ctx.frozenEvents.set(e.id, e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Frozen replay not available — tool will hit real services
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Saved original fetch so we can restore after the tool runs. */
|
|
79
|
+
let savedOriginalFetch = null;
|
|
80
|
+
function restoreFrozenFetch() {
|
|
81
|
+
if (savedOriginalFetch) {
|
|
82
|
+
globalThis.fetch = savedOriginalFetch;
|
|
83
|
+
savedOriginalFetch = null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Intercept fetch for HTTP frozen events using URL-based matching.
|
|
88
|
+
* This is the primary replay mechanism for tool reruns — it matches
|
|
89
|
+
* by request URL rather than sequential ID, which is robust against
|
|
90
|
+
* ID counter drift from wrapTool/wrapAI consuming IDs.
|
|
91
|
+
*/
|
|
92
|
+
function installFrozenFetchFallback(frozenEvents) {
|
|
93
|
+
const httpEvents = frozenEvents.filter(e => e.type === 'http');
|
|
94
|
+
const frozenUrls = httpEvents.map(e => {
|
|
95
|
+
const inp = e.input;
|
|
96
|
+
return inp && typeof inp === 'object' && typeof inp.url === 'string' ? inp.url : '(no url)';
|
|
97
|
+
});
|
|
98
|
+
process.stderr.write(`[elasticdash-worker] Frozen HTTP events: ${httpEvents.length}, URLs: ${JSON.stringify(frozenUrls)}\n`);
|
|
99
|
+
savedOriginalFetch = globalThis.fetch;
|
|
100
|
+
const originalFetch = globalThis.fetch;
|
|
101
|
+
const usageCounts = new Map();
|
|
102
|
+
globalThis.fetch = async (input, init) => {
|
|
103
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
|
|
104
|
+
const matches = httpEvents.filter(e => {
|
|
105
|
+
const frozenUrl = (e.input && typeof e.input === 'object' && 'url' in e.input)
|
|
106
|
+
? e.input.url
|
|
107
|
+
: null;
|
|
108
|
+
return frozenUrl === url;
|
|
109
|
+
});
|
|
110
|
+
if (matches.length > 0) {
|
|
111
|
+
const callCount = usageCounts.get(url) || 0;
|
|
112
|
+
const match = matches[Math.min(callCount, matches.length - 1)];
|
|
113
|
+
usageCounts.set(url, callCount + 1);
|
|
114
|
+
process.stderr.write(`[elasticdash-worker] Frozen replay: ${url}\n`);
|
|
115
|
+
const body = typeof match.output === 'string' ? match.output : JSON.stringify(match.output);
|
|
116
|
+
return new Response(body, {
|
|
117
|
+
status: 200,
|
|
118
|
+
headers: { 'Content-Type': 'application/json', 'X-Frozen': 'true' }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
process.stderr.write(`[elasticdash-worker] Fetch pass-through (no frozen match): ${url}\n`);
|
|
122
|
+
try {
|
|
123
|
+
return await originalFetch(input, init);
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
process.stderr.write(`[elasticdash-worker] Fetch FAILED for ${url}: ${e.stack || e.message || String(e)}\n`);
|
|
127
|
+
throw e;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
async function main() {
|
|
132
|
+
const originalExit = process.exit.bind(process);
|
|
133
|
+
// Prevent the SDK's tryAutoInitHttpContext from triggering full observability
|
|
134
|
+
// or dashboard-mode initialization in this subprocess. The subprocess should
|
|
135
|
+
// only execute the tool — observability/dashboard contexts are set up
|
|
136
|
+
// explicitly via setupFrozenContext when frozen events are provided.
|
|
137
|
+
// Without this, inherited env vars cause initObservability() to install
|
|
138
|
+
// interceptors, socket connections, and heartbeats that conflict with
|
|
139
|
+
// the frozen replay setup and can cause "Invalid URL" errors from
|
|
140
|
+
// Langfuse/OTel trying to connect to servers during tool execution.
|
|
141
|
+
delete process.env.ELASTICDASH_API_URL;
|
|
142
|
+
delete process.env.ELASTICDASH_SERVER;
|
|
143
|
+
let raw = '';
|
|
144
|
+
for await (const chunk of process.stdin) {
|
|
145
|
+
raw += chunk;
|
|
146
|
+
}
|
|
147
|
+
let payload;
|
|
148
|
+
try {
|
|
149
|
+
payload = JSON.parse(raw);
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
await writeResult({ ok: false, error: `Invalid JSON input: ${e.message}` });
|
|
153
|
+
originalExit(1);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const { toolsModulePath, toolName, args, frozenEvents } = payload;
|
|
157
|
+
// Set up frozen event context before running the tool.
|
|
158
|
+
// Uses URL-based matching for HTTP events (reliable for observability reruns)
|
|
159
|
+
// and ID-based matching for DB events.
|
|
160
|
+
const hasFrozen = frozenEvents && frozenEvents.length > 0;
|
|
161
|
+
if (hasFrozen) {
|
|
162
|
+
await setupFrozenContext(frozenEvents);
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
let mod;
|
|
166
|
+
try {
|
|
167
|
+
mod = await import(pathToFileURL(toolsModulePath).href);
|
|
168
|
+
}
|
|
169
|
+
catch (importErr) {
|
|
170
|
+
const ie = importErr;
|
|
171
|
+
await writeResult({ ok: false, error: `Failed to import tool module: ${ie.stack || ie.message}` });
|
|
172
|
+
originalExit(1);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Registry first: covers tools defined via edTool() anywhere in the project,
|
|
176
|
+
// as long as their containing module is reachable from toolsModulePath's
|
|
177
|
+
// import graph. Falls back to ed_tools-style module export lookup.
|
|
178
|
+
let fn;
|
|
179
|
+
try {
|
|
180
|
+
const reg = await import('./tool-registry.js');
|
|
181
|
+
const registered = reg.getRegisteredTool(toolName);
|
|
182
|
+
if (registered)
|
|
183
|
+
fn = registered.wrapped;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Registry module not available (older SDK build); fall through to export lookup.
|
|
187
|
+
}
|
|
188
|
+
if (!fn) {
|
|
189
|
+
const exported = mod[toolName];
|
|
190
|
+
if (typeof exported === 'function')
|
|
191
|
+
fn = exported;
|
|
192
|
+
}
|
|
193
|
+
if (typeof fn !== 'function') {
|
|
194
|
+
await writeResult({ ok: false, error: `"${toolName}" not found via edTool() registry or as an exported function in the module.` });
|
|
195
|
+
originalExit(1);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const currentOutput = await fn(...args);
|
|
199
|
+
await writeResult({ ok: true, currentOutput });
|
|
200
|
+
originalExit(0);
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
const err = e;
|
|
204
|
+
const errorMsg = err.stack || err.message || String(e);
|
|
205
|
+
process.stderr.write(`[elasticdash-worker] Tool execution failed:\n${errorMsg}\n`);
|
|
206
|
+
await writeResult({ ok: false, error: errorMsg });
|
|
207
|
+
originalExit(1);
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
if (hasFrozen)
|
|
211
|
+
restoreFrozenFetch();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
main();
|
|
215
|
+
//# sourceMappingURL=tool-runner-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-runner-worker.js","sourceRoot":"","sources":["../src/tool-runner-worker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export interface LLMStep {
|
|
2
|
+
model: string;
|
|
3
|
+
provider?: string;
|
|
4
|
+
prompt?: string;
|
|
5
|
+
completion?: string;
|
|
6
|
+
contains?: string;
|
|
7
|
+
workflowEventId?: number;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ToolCall {
|
|
11
|
+
name: string;
|
|
12
|
+
args?: Record<string, unknown>;
|
|
13
|
+
result?: unknown;
|
|
14
|
+
workflowEventId?: number;
|
|
15
|
+
durationMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export type CustomStepKind = 'rag' | 'code' | 'fixed' | 'custom';
|
|
18
|
+
export interface CustomStep {
|
|
19
|
+
kind: CustomStepKind;
|
|
20
|
+
name?: string;
|
|
21
|
+
tags?: string[];
|
|
22
|
+
payload?: unknown;
|
|
23
|
+
result?: unknown;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
25
|
+
contains?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface TraceStep {
|
|
28
|
+
type: 'llm' | 'tool' | 'custom';
|
|
29
|
+
timestamp: number;
|
|
30
|
+
durationMs: number;
|
|
31
|
+
data: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
export interface TraceHandle {
|
|
34
|
+
/** All recorded steps in this trace session */
|
|
35
|
+
getSteps(): TraceStep[];
|
|
36
|
+
/** Only LLM inference steps */
|
|
37
|
+
getLLMSteps(): LLMStep[];
|
|
38
|
+
/** Only tool-call steps */
|
|
39
|
+
getToolCalls(): ToolCall[];
|
|
40
|
+
/** Only custom steps (RAG, code, fixed, etc.) */
|
|
41
|
+
getCustomSteps(): CustomStep[];
|
|
42
|
+
/** Record an LLM step (used by stubs / real adapter) */
|
|
43
|
+
recordLLMStep(step: LLMStep): void;
|
|
44
|
+
/** Record a tool call (used by stubs / real adapter) */
|
|
45
|
+
recordToolCall(call: ToolCall): void;
|
|
46
|
+
/** Record a custom step (e.g., RAG, code) */
|
|
47
|
+
recordCustomStep(step: CustomStep): void;
|
|
48
|
+
}
|
|
49
|
+
export interface AITestContext {
|
|
50
|
+
trace: TraceHandle;
|
|
51
|
+
}
|
|
52
|
+
export declare function setCurrentTrace(trace: TraceHandle | undefined): void;
|
|
53
|
+
export declare function getCurrentTrace(): TraceHandle | undefined;
|
|
54
|
+
/** Extension points for runner hooks (scaffold for future backend integration) */
|
|
55
|
+
export interface RunnerHooks {
|
|
56
|
+
onTestStart?(name: string): void | Promise<void>;
|
|
57
|
+
onTestFinish?(name: string, passed: boolean, durationMs: number, error?: Error): void | Promise<void>;
|
|
58
|
+
onTraceComplete?(name: string, trace: TraceHandle): void | Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Create a stubbed trace handle for a single test execution.
|
|
62
|
+
* Later this can be replaced with a real ElasticDash backend call.
|
|
63
|
+
*/
|
|
64
|
+
export declare function createTraceHandle(): TraceHandle;
|
|
65
|
+
/**
|
|
66
|
+
* Start a trace session before a test and return the context + a finalise fn.
|
|
67
|
+
*/
|
|
68
|
+
export declare function startTraceSession(): {
|
|
69
|
+
context: AITestContext;
|
|
70
|
+
finalise: () => void;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/trace-adapter/context.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEhE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,QAAQ,IAAI,SAAS,EAAE,CAAA;IACvB,+BAA+B;IAC/B,WAAW,IAAI,OAAO,EAAE,CAAA;IACxB,2BAA2B;IAC3B,YAAY,IAAI,QAAQ,EAAE,CAAA;IAC1B,iDAAiD;IACjD,cAAc,IAAI,UAAU,EAAE,CAAA;IAC9B,wDAAwD;IACxD,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IAClC,wDAAwD;IACxD,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACpC,6CAA6C;IAC7C,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,CAAA;CACnB;AAaD,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,SAAS,CAEzD;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrG,eAAe,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAqD/C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;CAAE,CASpF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// --- AsyncLocalStorage-backed current trace (parallel-safe) ---
|
|
2
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
import { rawDateNow } from '../interceptors/side-effects.js';
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
const TRACE_ALS_KEY = '__elasticdash_trace_als__';
|
|
6
|
+
const traceAls = g[TRACE_ALS_KEY] ??
|
|
7
|
+
new AsyncLocalStorage();
|
|
8
|
+
if (!g[TRACE_ALS_KEY])
|
|
9
|
+
g[TRACE_ALS_KEY] = traceAls;
|
|
10
|
+
export function setCurrentTrace(trace) {
|
|
11
|
+
traceAls.enterWith(trace);
|
|
12
|
+
}
|
|
13
|
+
export function getCurrentTrace() {
|
|
14
|
+
return traceAls.getStore();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a stubbed trace handle for a single test execution.
|
|
18
|
+
* Later this can be replaced with a real ElasticDash backend call.
|
|
19
|
+
*/
|
|
20
|
+
export function createTraceHandle() {
|
|
21
|
+
const steps = [];
|
|
22
|
+
const llmSteps = [];
|
|
23
|
+
const toolCalls = [];
|
|
24
|
+
const customSteps = [];
|
|
25
|
+
return {
|
|
26
|
+
getSteps() {
|
|
27
|
+
return steps;
|
|
28
|
+
},
|
|
29
|
+
getLLMSteps() {
|
|
30
|
+
return llmSteps;
|
|
31
|
+
},
|
|
32
|
+
getToolCalls() {
|
|
33
|
+
return toolCalls;
|
|
34
|
+
},
|
|
35
|
+
getCustomSteps() {
|
|
36
|
+
return customSteps;
|
|
37
|
+
},
|
|
38
|
+
recordLLMStep(step) {
|
|
39
|
+
llmSteps.push(step);
|
|
40
|
+
steps.push({
|
|
41
|
+
type: 'llm',
|
|
42
|
+
timestamp: rawDateNow(),
|
|
43
|
+
durationMs: step.durationMs ?? 0,
|
|
44
|
+
data: step,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
recordToolCall(call) {
|
|
48
|
+
toolCalls.push(call);
|
|
49
|
+
steps.push({
|
|
50
|
+
type: 'tool',
|
|
51
|
+
timestamp: rawDateNow(),
|
|
52
|
+
durationMs: call.durationMs ?? 0,
|
|
53
|
+
data: call,
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
recordCustomStep(step) {
|
|
57
|
+
customSteps.push(step);
|
|
58
|
+
steps.push({
|
|
59
|
+
type: 'custom',
|
|
60
|
+
timestamp: rawDateNow(),
|
|
61
|
+
durationMs: 0,
|
|
62
|
+
data: step,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Start a trace session before a test and return the context + a finalise fn.
|
|
69
|
+
*/
|
|
70
|
+
export function startTraceSession() {
|
|
71
|
+
const trace = createTraceHandle();
|
|
72
|
+
const context = { trace };
|
|
73
|
+
return {
|
|
74
|
+
context,
|
|
75
|
+
finalise() {
|
|
76
|
+
// Placeholder: flush / send to ElasticDash backend here in the future
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/trace-adapter/context.ts"],"names":[],"mappings":"AA0DA,iEAAiE;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAE5D,MAAM,CAAC,GAAG,UAAqC,CAAA;AAC/C,MAAM,aAAa,GAAG,2BAA2B,CAAA;AACjD,MAAM,QAAQ,GACX,CAAC,CAAC,aAAa,CAAgD;IAChE,IAAI,iBAAiB,EAA2B,CAAA;AAClD,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC;IAAE,CAAC,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAA;AAElD,MAAM,UAAU,eAAe,CAAC,KAA8B;IAC5D,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,QAAQ,CAAC,QAAQ,EAAE,CAAA;AAC5B,CAAC;AASD;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAgB,EAAE,CAAA;IAC7B,MAAM,QAAQ,GAAc,EAAE,CAAA;IAC9B,MAAM,SAAS,GAAe,EAAE,CAAA;IAChC,MAAM,WAAW,GAAiB,EAAE,CAAA;IAEpC,OAAO;QACL,QAAQ;YACN,OAAO,KAAK,CAAA;QACd,CAAC;QAED,WAAW;YACT,OAAO,QAAQ,CAAA;QACjB,CAAC;QAED,YAAY;YACV,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,cAAc;YACZ,OAAO,WAAW,CAAA;QACpB,CAAC;QAED,aAAa,CAAC,IAAa;YACzB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACnB,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,KAAK;gBACX,SAAS,EAAE,UAAU,EAAE;gBACvB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;gBAChC,IAAI,EAAE,IAA0C;aACjD,CAAC,CAAA;QACJ,CAAC;QAED,cAAc,CAAC,IAAc;YAC3B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACpB,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,MAAM;gBACZ,SAAS,EAAE,UAAU,EAAE;gBACvB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;gBAChC,IAAI,EAAE,IAA0C;aACjD,CAAC,CAAA;QACJ,CAAC;QAED,gBAAgB,CAAC,IAAgB;YAC/B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACtB,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,UAAU,EAAE;gBACvB,UAAU,EAAE,CAAC;gBACb,IAAI,EAAE,IAA0C;aACjD,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,KAAK,GAAG,iBAAiB,EAAE,CAAA;IACjC,MAAM,OAAO,GAAkB,EAAE,KAAK,EAAE,CAAA;IACxC,OAAO;QACL,OAAO;QACP,QAAQ;YACN,sEAAsE;QACxE,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAqBA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,SAAI,QAwClF"}
|
package/dist/tracing.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/tracing.ts
|
|
2
|
+
// ElasticDash tool call recording utility
|
|
3
|
+
/**
|
|
4
|
+
* Records a tool call for workflow tracing. Safe to call in any environment.
|
|
5
|
+
* If not running inside the ElasticDash runner, this is a no-op.
|
|
6
|
+
*
|
|
7
|
+
* @param name - The tool name
|
|
8
|
+
* @param args - The tool arguments (object or array)
|
|
9
|
+
* @param result - The tool result (or error)
|
|
10
|
+
*/
|
|
11
|
+
import { getCurrentTrace } from './trace-adapter/context.js';
|
|
12
|
+
import { getCaptureContext } from './capture/recorder.js';
|
|
13
|
+
import { rawDateNow } from './interceptors/side-effects.js';
|
|
14
|
+
const TOOL_WRAPPER_ACTIVE_KEY = '__elasticdash_tool_wrapper_active__';
|
|
15
|
+
function wrapperRecordingActive() {
|
|
16
|
+
return globalThis[TOOL_WRAPPER_ACTIVE_KEY] === true;
|
|
17
|
+
}
|
|
18
|
+
export function recordToolCall(name, args, result, durationMs = 0) {
|
|
19
|
+
if (!globalThis.__ELASTICDASH_WORKER__)
|
|
20
|
+
return;
|
|
21
|
+
try {
|
|
22
|
+
// Avoid double-recording when a replay-aware tool wrapper is already active.
|
|
23
|
+
if (wrapperRecordingActive())
|
|
24
|
+
return;
|
|
25
|
+
const trace = getCurrentTrace();
|
|
26
|
+
if (!trace || typeof trace.recordToolCall !== 'function')
|
|
27
|
+
return;
|
|
28
|
+
const ctx = getCaptureContext();
|
|
29
|
+
if (!ctx) {
|
|
30
|
+
trace.recordToolCall({ name, args, result, durationMs });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const { recorder, replay } = ctx;
|
|
34
|
+
const id = recorder.nextId();
|
|
35
|
+
if (replay.shouldReplay(id)) {
|
|
36
|
+
const historical = replay.getRecordedEvent(id);
|
|
37
|
+
if (historical)
|
|
38
|
+
recorder.record(historical);
|
|
39
|
+
const replayed = replay.getRecordedResult(id);
|
|
40
|
+
trace.recordToolCall({ name, args, result: replayed, workflowEventId: id });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const output = result instanceof Error ? { error: String(result) } : result;
|
|
44
|
+
recorder.record({
|
|
45
|
+
id,
|
|
46
|
+
type: 'tool',
|
|
47
|
+
name,
|
|
48
|
+
input: args,
|
|
49
|
+
output,
|
|
50
|
+
timestamp: rawDateNow(),
|
|
51
|
+
durationMs,
|
|
52
|
+
});
|
|
53
|
+
trace.recordToolCall({ name, args, result: output, workflowEventId: id, durationMs });
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Never throw, always swallow errors
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=tracing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.js","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,0CAA0C;AAE1C;;;;;;;GAOG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAE3D,MAAM,uBAAuB,GAAG,qCAAqC,CAAA;AAErE,SAAS,sBAAsB;IAC7B,OAAQ,UAAsC,CAAC,uBAAuB,CAAC,KAAK,IAAI,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAS,EAAE,MAAW,EAAE,UAAU,GAAG,CAAC;IACjF,IAAI,CAAE,UAAkB,CAAC,sBAAsB;QAAE,OAAM;IACvD,IAAI,CAAC;QACH,6EAA6E;QAC7E,IAAI,sBAAsB,EAAE;YAAE,OAAM;QAEpC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAA;QAC/B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,cAAc,KAAK,UAAU;YAAE,OAAM;QAEhE,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAA;QAC/B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,KAAK,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAA;YACxD,OAAM;QACR,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;QAChC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAA;QAE5B,IAAI,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;YAC9C,IAAI,UAAU;gBAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;YAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;YAC7C,KAAK,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAA;YAC3E,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;QAC3E,QAAQ,CAAC,MAAM,CAAC;YACd,EAAE;YACF,IAAI,EAAE,MAAM;YACZ,IAAI;YACJ,KAAK,EAAE,IAAI;YACX,MAAM;YACN,SAAS,EAAE,UAAU,EAAE;YACvB,UAAU;SACX,CAAC,CAAA;QACF,KAAK,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAA;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;IACvC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { TriggerSignal } from './telemetry-batcher.js';
|
|
2
|
+
/**
|
|
3
|
+
* Executes a trigger received from the backend's event batch response.
|
|
4
|
+
*
|
|
5
|
+
* For each step:
|
|
6
|
+
* 1. Pre-validates availability (tool exists? API key set?)
|
|
7
|
+
* 2. If unavailable: reports `available: false` with reason, skips execution
|
|
8
|
+
* 3. If available: re-executes `runCount` times, collects results
|
|
9
|
+
* 4. POSTs each step's result individually to avoid payload size limits
|
|
10
|
+
*/
|
|
11
|
+
export declare function executeTrigger(serverUrl: string, apiKey: string | undefined, trigger: TriggerSignal): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=trigger-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-executor.d.ts","sourceRoot":"","sources":["../src/trigger-executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAA;AA8BxE;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CA8Hf"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { executePortalTask, checkToolAvailability, checkAIAvailability } from './portal-executor.js';
|
|
2
|
+
import { getOriginalFetch } from './interceptors/http.js';
|
|
3
|
+
import { getObservabilityContext } from './interceptors/telemetry-push.js';
|
|
4
|
+
import { scanTools } from './execution/tool-runner.js';
|
|
5
|
+
import { debugLog } from './utils/debug.js';
|
|
6
|
+
/** Track trigger IDs that are currently executing or already completed to prevent duplicate execution. */
|
|
7
|
+
const handledTriggers = new Set();
|
|
8
|
+
/**
|
|
9
|
+
* Executes a trigger received from the backend's event batch response.
|
|
10
|
+
*
|
|
11
|
+
* For each step:
|
|
12
|
+
* 1. Pre-validates availability (tool exists? API key set?)
|
|
13
|
+
* 2. If unavailable: reports `available: false` with reason, skips execution
|
|
14
|
+
* 3. If available: re-executes `runCount` times, collects results
|
|
15
|
+
* 4. POSTs each step's result individually to avoid payload size limits
|
|
16
|
+
*/
|
|
17
|
+
export async function executeTrigger(serverUrl, apiKey, trigger) {
|
|
18
|
+
// Feature flag: allow users to disable rerun acceptance per project
|
|
19
|
+
const acceptReruns = process.env.ELASTICDASH_ACCEPT_RERUNS;
|
|
20
|
+
if (acceptReruns !== undefined && ['false', '0', 'no'].includes(acceptReruns.toLowerCase())) {
|
|
21
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} rejected: ELASTICDASH_ACCEPT_RERUNS=${acceptReruns}`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Dedup guard: skip if this trigger is already being handled
|
|
25
|
+
if (handledTriggers.has(trigger.triggerId)) {
|
|
26
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} already handled, skipping duplicate`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
handledTriggers.add(trigger.triggerId);
|
|
30
|
+
// Mark observability context as rerun so captured events are flagged
|
|
31
|
+
const obsCtx = getObservabilityContext();
|
|
32
|
+
if (obsCtx)
|
|
33
|
+
obsCtx.isRerun = true;
|
|
34
|
+
const cwd = process.cwd();
|
|
35
|
+
const tools = scanTools(cwd);
|
|
36
|
+
const frozenEvents = trigger.frozenEvents || [];
|
|
37
|
+
const totalSteps = trigger.steps.length;
|
|
38
|
+
debugLog(`[elasticdash] Executing trigger ${trigger.triggerId}: ${totalSteps} steps × ${trigger.runCount} runs, ${frozenEvents.length} frozenEvents`);
|
|
39
|
+
if (!serverUrl) {
|
|
40
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} aborted: serverUrl is empty`);
|
|
41
|
+
if (obsCtx)
|
|
42
|
+
obsCtx.isRerun = false;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const baseUrl = serverUrl.replace(/\/$/, '');
|
|
46
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
47
|
+
if (apiKey)
|
|
48
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
49
|
+
for (let stepIndex = 0; stepIndex < totalSteps; stepIndex++) {
|
|
50
|
+
const step = trigger.steps[stepIndex];
|
|
51
|
+
// Pre-validate availability
|
|
52
|
+
const availability = step.eventType === 'ai'
|
|
53
|
+
? checkAIAvailability(step.provider, step.model ?? step.eventName)
|
|
54
|
+
: checkToolAvailability(step.eventName, cwd, tools);
|
|
55
|
+
let stepResult;
|
|
56
|
+
if (!availability.available) {
|
|
57
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step=${step.eventName} unavailable: ${availability.reason}`);
|
|
58
|
+
stepResult = {
|
|
59
|
+
originalEventDbId: step.originalEventDbId,
|
|
60
|
+
eventType: step.eventType,
|
|
61
|
+
eventName: step.eventName,
|
|
62
|
+
available: false,
|
|
63
|
+
unavailableReason: availability.reason,
|
|
64
|
+
runs: [],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Execute runs
|
|
69
|
+
const runs = [];
|
|
70
|
+
for (let i = 0; i < trigger.runCount; i++) {
|
|
71
|
+
const result = await executePortalTask({
|
|
72
|
+
taskId: `trigger-${trigger.triggerId}-${step.eventName}-${i}`,
|
|
73
|
+
type: step.eventType === 'ai' ? 'ai' : 'tool',
|
|
74
|
+
name: step.eventName,
|
|
75
|
+
input: step.input,
|
|
76
|
+
model: step.eventType === 'ai' ? (step.model ?? step.eventName) : undefined,
|
|
77
|
+
provider: step.provider,
|
|
78
|
+
frozenEvents,
|
|
79
|
+
}, cwd, tools);
|
|
80
|
+
if (!result.ok) {
|
|
81
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step=${step.eventName} run=${i} FAILED:\n${result.error}`);
|
|
82
|
+
}
|
|
83
|
+
runs.push({
|
|
84
|
+
runIndex: i,
|
|
85
|
+
input: step.input,
|
|
86
|
+
output: result.output,
|
|
87
|
+
durationMs: result.durationMs,
|
|
88
|
+
error: result.error,
|
|
89
|
+
usageInputTokens: result.usage?.inputTokens,
|
|
90
|
+
usageOutputTokens: result.usage?.outputTokens,
|
|
91
|
+
usageTotalTokens: result.usage?.totalTokens,
|
|
92
|
+
});
|
|
93
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step=${step.eventName} run=${i} ok=${result.ok}`);
|
|
94
|
+
}
|
|
95
|
+
stepResult = {
|
|
96
|
+
originalEventDbId: step.originalEventDbId,
|
|
97
|
+
eventType: step.eventType,
|
|
98
|
+
eventName: step.eventName,
|
|
99
|
+
available: true,
|
|
100
|
+
runs,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// POST rerun results directly under the original event record
|
|
104
|
+
const url = `${baseUrl}/api/observability/events/${step.originalEventDbId}/reruns`;
|
|
105
|
+
try {
|
|
106
|
+
const res = await getOriginalFetch()(url, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers,
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
triggerId: trigger.triggerId,
|
|
111
|
+
eventType: stepResult.eventType,
|
|
112
|
+
eventName: stepResult.eventName,
|
|
113
|
+
available: stepResult.available,
|
|
114
|
+
unavailableReason: stepResult.unavailableReason,
|
|
115
|
+
runs: stepResult.runs,
|
|
116
|
+
stepIndex,
|
|
117
|
+
totalSteps,
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step ${stepIndex + 1}/${totalSteps} posted to event ${step.originalEventDbId} (status ${res.status})`);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
debugLog(`[elasticdash] Trigger ${trigger.triggerId} step ${stepIndex + 1}/${totalSteps} POST to event ${step.originalEventDbId} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Restore context after rerun execution
|
|
127
|
+
if (obsCtx)
|
|
128
|
+
obsCtx.isRerun = false;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=trigger-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger-executor.js","sourceRoot":"","sources":["../src/trigger-executor.ts"],"names":[],"mappings":"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"}
|