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
package/docs/agents.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Agent Mid-Trace Replay
|
|
2
|
+
|
|
3
|
+
ElasticDash supports resuming long-running agents from any task in their plan — without re-executing already-completed steps.
|
|
4
|
+
|
|
5
|
+
## Use Cases
|
|
6
|
+
|
|
7
|
+
- **Resuming after failures**: If task 3 of 5 fails, fix the issue and re-run from task 3 only
|
|
8
|
+
- **Pausing for approval**: Capture state after task 2, get human sign-off, then continue
|
|
9
|
+
- **Debugging in isolation**: Re-run a single task with modified input to diagnose a problem
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
Agents are structured as an **AgentPlan** — an ordered list of **AgentTask** objects. When serialized with captured trace events, this forms an **AgentState** that can be saved and replayed later.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { plannerAgent, executorAgent, resumeAgentFromTrace } from './ed_agents'
|
|
19
|
+
import { serializeAgentState, deserializeAgentState } from 'elasticdash-sdk'
|
|
20
|
+
import fs from 'node:fs'
|
|
21
|
+
|
|
22
|
+
// 1. Generate a plan
|
|
23
|
+
const plan = await plannerAgent('Show me sales for Q1', { userToken: 'tok-abc' })
|
|
24
|
+
|
|
25
|
+
// 2. Execute the plan (runs all tasks sequentially)
|
|
26
|
+
const completedPlan = await executorAgent(plan)
|
|
27
|
+
|
|
28
|
+
// 3. Serialize and save state (e.g., after partial execution)
|
|
29
|
+
const state = serializeAgentState(completedPlan, [] /* pass recorder.events in worker context */)
|
|
30
|
+
fs.writeFileSync('agent-state.json', JSON.stringify(state, null, 2))
|
|
31
|
+
|
|
32
|
+
// 4. Later: load saved state and resume from task 2 (0-based index 1)
|
|
33
|
+
const savedState = JSON.parse(fs.readFileSync('agent-state.json', 'utf8'))
|
|
34
|
+
const stateToResume = deserializeAgentState({ ...savedState, resumeFromTaskIndex: 1 })
|
|
35
|
+
const resumedPlan = await resumeAgentFromTrace(stateToResume)
|
|
36
|
+
|
|
37
|
+
console.log('Resumed plan status:', resumedPlan.status)
|
|
38
|
+
console.log('Task outputs:', resumedPlan.tasks.map((t) => ({ id: t.id, status: t.status })))
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Data Structures
|
|
42
|
+
|
|
43
|
+
### AgentState
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
interface AgentState {
|
|
47
|
+
plan: AgentPlan // Full plan with all tasks (completed and pending)
|
|
48
|
+
trace: WorkflowEvent[] // Captured trace events from previous execution
|
|
49
|
+
resumeFromTaskIndex: number // Zero-based index — tasks before this are loaded from cache
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### AgentPlan
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
interface AgentPlan {
|
|
57
|
+
id: string
|
|
58
|
+
tasks: AgentTask[]
|
|
59
|
+
status: 'planning' | 'executing' | 'completed' | 'failed' | 'paused'
|
|
60
|
+
currentTaskIndex: number
|
|
61
|
+
context: Record<string, unknown>
|
|
62
|
+
metadata: Record<string, unknown>
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### AgentTask
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
interface AgentTask {
|
|
70
|
+
id: string
|
|
71
|
+
status: 'pending' | 'in-progress' | 'completed' | 'failed'
|
|
72
|
+
description: string
|
|
73
|
+
tool: string // Name of the tool function to invoke
|
|
74
|
+
input: unknown // May contain { $ref: "task-N.output.fieldName" } placeholders
|
|
75
|
+
output?: unknown // Populated after execution
|
|
76
|
+
error?: string
|
|
77
|
+
startedAt?: number
|
|
78
|
+
completedAt?: number
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Task Input Placeholders
|
|
83
|
+
|
|
84
|
+
Task inputs can reference previous task outputs using `{ $ref: "taskId.output.fieldPath" }`:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// task-2 uses the embedding produced by task-1
|
|
88
|
+
{
|
|
89
|
+
id: 'task-2',
|
|
90
|
+
tool: 'taskSelectorService',
|
|
91
|
+
input: {
|
|
92
|
+
queryEmbedding: { $ref: 'task-1.output.embedding' },
|
|
93
|
+
topK: 3,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Placeholders are resolved at execution time by `resolveTaskInput()`.
|
|
99
|
+
|
|
100
|
+
## Dashboard Integration
|
|
101
|
+
|
|
102
|
+
When running an agent workflow through the dashboard:
|
|
103
|
+
|
|
104
|
+
1. **Agent task observations** are visually highlighted with a purple background and left border
|
|
105
|
+
2. Each observation shows a **T1 / T2 / T3** badge indicating which task it belongs to
|
|
106
|
+
3. In the observation detail panel, a **"Resume from Task N"** button appears (agent steps only)
|
|
107
|
+
4. Clicking it calls `/api/resume-agent-from-task` with the serialized `AgentState` and chosen `taskIndex`
|
|
108
|
+
5. The resumed run is added as a new trace in the comparison table
|
|
109
|
+
|
|
110
|
+
## Best Practices
|
|
111
|
+
|
|
112
|
+
- **Keep tasks idempotent** where possible — if a task must be re-run, ensure it produces the same result
|
|
113
|
+
- **Store minimal outputs** — only record what downstream tasks need, not full API responses
|
|
114
|
+
- **Version your state schema** — if tool interfaces change, old states may need migration
|
|
115
|
+
- **Use sequential tasks** — the current implementation runs tasks one-by-one; parallel task support is planned
|
|
116
|
+
|
|
117
|
+
## Example: Debugging a Failed Task
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
// 1. Original execution fails at task 3
|
|
121
|
+
const plan = await plannerAgent('Process refund for order-123')
|
|
122
|
+
const result = await executorAgent(plan)
|
|
123
|
+
// Error: task 3 (calculateRefundAmount) failed
|
|
124
|
+
|
|
125
|
+
// 2. Save the state
|
|
126
|
+
const state = serializeAgentState(result, recorder.events)
|
|
127
|
+
fs.writeFileSync('failed-run.json', JSON.stringify(state))
|
|
128
|
+
|
|
129
|
+
// 3. Fix the issue in your tool/code
|
|
130
|
+
|
|
131
|
+
// 4. Resume from task 3 with corrected state
|
|
132
|
+
const savedState = JSON.parse(fs.readFileSync('failed-run.json'))
|
|
133
|
+
const fixed = await resumeAgentFromTrace({
|
|
134
|
+
...deserializeAgentState(savedState),
|
|
135
|
+
resumeFromTaskIndex: 2 // 0-based: task 3 = index 2
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
// Tasks 1-2 use cached results; task 3+ execute with fixes
|
|
139
|
+
console.log('Fixed plan:', fixed.status)
|
|
140
|
+
```
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# Workflows Dashboard
|
|
2
|
+
|
|
3
|
+
Browse, search, and run all available workflow and tool functions in your project.
|
|
4
|
+
|
|
5
|
+
## Starting the Dashboard
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx elasticdash dashboard # open dashboard at http://localhost:4573
|
|
9
|
+
npx elasticdash dashboard --port 4572 # use custom port
|
|
10
|
+
npx elasticdash dashboard --no-open # skip auto-opening browser
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Framework Runtime Compatibility (Next.js, TS Path Aliases)
|
|
14
|
+
|
|
15
|
+
If your project uses **TypeScript path aliases** (e.g., `@/lib/...`) or requires runtime TypeScript loading, you may need to configure Node.js loaders.
|
|
16
|
+
|
|
17
|
+
**Standard command (works for most projects):**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx elasticdash dashboard
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Advanced command (Next.js, mixed ESM/CJS, path aliases):**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
NODE_OPTIONS='--import tsx/esm --require tsx/cjs --require tsconfig-paths/register' npx elasticdash dashboard
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or add to `package.json`:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"scripts": {
|
|
34
|
+
"dashboard:ai": "NODE_OPTIONS='--import tsx/esm --require tsx/cjs --require tsconfig-paths/register' elasticdash dashboard"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Why this works:**
|
|
40
|
+
- `tsx/esm` and `tsx/cjs` handle mixed ESM/CJS module loading at runtime
|
|
41
|
+
- `tsconfig-paths/register` resolves path mappings from `tsconfig.json` (e.g., `@/services/*` → `./src/services/*`)
|
|
42
|
+
|
|
43
|
+
**How to check if you're using ESM or CJS:**
|
|
44
|
+
|
|
45
|
+
Look at your `package.json`:
|
|
46
|
+
- `"type": "module"` → ESM (uses `import`/`export`)
|
|
47
|
+
- No `type` field or `"type": "commonjs"` → CJS (uses `require`/`module.exports`)
|
|
48
|
+
|
|
49
|
+
**When you need the advanced setup:**
|
|
50
|
+
|
|
51
|
+
- **Any file in your project uses path aliases** (e.g., `@/lib/*`, `@/services/*`) instead of relative imports (`../`) - **this is the main reason**
|
|
52
|
+
- Your project mixes ESM (`import`) and CJS (`require`) in the same execution path
|
|
53
|
+
- You see errors like `Cannot find module '@/...'` or `ERR_UNKNOWN_FILE_EXTENSION`
|
|
54
|
+
|
|
55
|
+
**Important:** Path alias resolution is transitive. If your workflows import files that use `@/` aliases, you need the advanced setup even if `ed_workflows.ts` itself uses only relative imports.
|
|
56
|
+
|
|
57
|
+
**When you DON'T need it:**
|
|
58
|
+
- Plain JavaScript projects (`.js` files only)
|
|
59
|
+
- **Basic TypeScript projects using only relative imports** (`./`, `../`) - the dashboard handles standard TS transpilation automatically
|
|
60
|
+
- **Pure ESM or pure CJS projects without path aliases**
|
|
61
|
+
- Pre-built projects where workflows are already compiled to `.js`
|
|
62
|
+
|
|
63
|
+
## File Resolution
|
|
64
|
+
|
|
65
|
+
The dashboard automatically handles TypeScript transpilation:
|
|
66
|
+
|
|
67
|
+
| Scenario | File Used |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Only `ed_workflows.ts` | Transpiled `.ts` on the fly |
|
|
70
|
+
| Only `ed_workflows.js` | `.js` directly |
|
|
71
|
+
| Both `.ts` and `.js` exist | `.ts` (preferred) |
|
|
72
|
+
|
|
73
|
+
**No manual build step required** — write your workflows in TypeScript, and the dashboard handles the rest.
|
|
74
|
+
|
|
75
|
+
## What the Dashboard Shows
|
|
76
|
+
|
|
77
|
+
### Workflow Functions
|
|
78
|
+
- **Function names** — all exported functions from `ed_workflows.ts`
|
|
79
|
+
- **Signatures** — function parameters and return types
|
|
80
|
+
- **Async indicator** — marks async vs sync functions
|
|
81
|
+
- **Source module** — where the function is imported from (if re-exported)
|
|
82
|
+
- **File path** — location in your codebase
|
|
83
|
+
|
|
84
|
+
### Tool Functions
|
|
85
|
+
- All exported functions from `ed_tools.ts`
|
|
86
|
+
- Same display format as workflows
|
|
87
|
+
- Used for agent task execution
|
|
88
|
+
|
|
89
|
+
## Search and Filter
|
|
90
|
+
|
|
91
|
+
Use the search field to filter by:
|
|
92
|
+
- **Name** — find workflow by function name (e.g., `checkoutFlow`)
|
|
93
|
+
- **Source module** — find all workflows from a specific module (e.g., `app.workflows`)
|
|
94
|
+
- **File path** — filter by location in your codebase
|
|
95
|
+
|
|
96
|
+
## Running Workflows
|
|
97
|
+
|
|
98
|
+
The dashboard provides an interactive workflow debugger:
|
|
99
|
+
|
|
100
|
+
### Step 1: Select Workflow
|
|
101
|
+
Choose a workflow function to run
|
|
102
|
+
|
|
103
|
+
### Step 2: Import Failed Trace
|
|
104
|
+
Upload a JSON trace file from a failed workflow run
|
|
105
|
+
|
|
106
|
+
### Step 3: Mark Broken Step
|
|
107
|
+
Select which observations (AI calls, tool calls) need fixing
|
|
108
|
+
|
|
109
|
+
### Step 4: Validate Fixes
|
|
110
|
+
Edit inputs, re-run individual observations, and compare outputs
|
|
111
|
+
|
|
112
|
+
### Step 5: Validate with Live Data
|
|
113
|
+
Run the entire workflow with live API calls to verify your fixes work end-to-end
|
|
114
|
+
|
|
115
|
+
## Fetching Traces from Langfuse
|
|
116
|
+
|
|
117
|
+
To import a trace into the dashboard, you need to fetch observation data from Langfuse's API using the correct trace ID.
|
|
118
|
+
|
|
119
|
+
### API Endpoint
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
https://cloud.langfuse.com/api/public/v2/observations?traceId=<TRACE_ID>&fields=time,io,basic,model
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Required Parameters
|
|
126
|
+
|
|
127
|
+
| Parameter | Description |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `traceId` | The unique identifier for the trace (required) |
|
|
130
|
+
| `fields` | Comma-separated list of fields to include: `time,io,basic,model` (required) |
|
|
131
|
+
|
|
132
|
+
### Example Request
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
curl "https://cloud.langfuse.com/api/public/v2/observations?traceId=a1b2af2bc594eb816ab55a1d0c94fd47&fields=time,io,basic,model" \
|
|
136
|
+
-H "Authorization: Basic <BASE64_ENCODED_CREDENTIALS>"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Authentication
|
|
140
|
+
|
|
141
|
+
Use HTTP Basic Auth with a base64-encoded credential string:
|
|
142
|
+
|
|
143
|
+
1. **Create the credentials string:**
|
|
144
|
+
```
|
|
145
|
+
<LANGFUSE_PUBLIC_KEY>:<LANGFUSE_SECRET_KEY>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
2. **Encode to base64:**
|
|
149
|
+
```bash
|
|
150
|
+
# On macOS/Linux:
|
|
151
|
+
echo -n "<LANGFUSE_PUBLIC_KEY>:<LANGFUSE_SECRET_KEY>" | base64
|
|
152
|
+
|
|
153
|
+
# Result: abc123def456... (the base64 string)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
3. **Use in the Authorization header:**
|
|
157
|
+
```bash
|
|
158
|
+
-H "Authorization: Basic abc123def456..."
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Bearer token auth is not accepted for this API usage.
|
|
162
|
+
|
|
163
|
+
### Using Postman
|
|
164
|
+
|
|
165
|
+
To fetch traces using Postman:
|
|
166
|
+
|
|
167
|
+
1. **Create a new GET request**
|
|
168
|
+
- Set request type to `GET`
|
|
169
|
+
- URL: `https://cloud.langfuse.com/api/public/v2/observations`
|
|
170
|
+
|
|
171
|
+
2. **Add query parameters:**
|
|
172
|
+
- Click the "Params" tab
|
|
173
|
+
- Add `traceId` parameter: `a1b2af2bc594eb816ab55a1d0c94fd47`
|
|
174
|
+
- Add `fields` parameter: `time,io,basic,model`
|
|
175
|
+
|
|
176
|
+
3. **Add Authorization header:**
|
|
177
|
+
- Click the "Auth" tab
|
|
178
|
+
- Select `Basic Auth` from the Type dropdown
|
|
179
|
+
- Username: `<LANGFUSE_PUBLIC_KEY>`
|
|
180
|
+
- Password: `<LANGFUSE_SECRET_KEY>`
|
|
181
|
+
- Postman will automatically base64-encode your credentials
|
|
182
|
+
|
|
183
|
+
4. **Send the request**
|
|
184
|
+
- Click "Send"
|
|
185
|
+
- The response will show the array of observations for your trace
|
|
186
|
+
|
|
187
|
+
**Alternatively, manually add the header:**
|
|
188
|
+
- Go to "Headers" tab
|
|
189
|
+
- Add header: `Authorization`
|
|
190
|
+
- Value: `Basic <BASE64_ENCODED_CREDENTIALS>`
|
|
191
|
+
|
|
192
|
+
### Example Response
|
|
193
|
+
|
|
194
|
+
The API returns an array of observation objects. Note that `input` and `output` fields are **stringified JSON** (not objects):
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
[
|
|
198
|
+
{
|
|
199
|
+
"id": "1e31d1efb1aae8be",
|
|
200
|
+
"traceId": "a1b2af2bc594eb816ab55a1d0c94fd47",
|
|
201
|
+
"type": "GENERATION",
|
|
202
|
+
"name": "OpenAI.chat",
|
|
203
|
+
"startTime": "2026-03-01T10:02:06.132Z",
|
|
204
|
+
"endTime": "2026-03-01T10:02:07.212Z",
|
|
205
|
+
"model": "gpt-4o-2024-08-06",
|
|
206
|
+
"input": "{\"messages\":[{\"role\":\"user\",\"content\":\"What is the order status?\"}]}",
|
|
207
|
+
"output": "{\"role\":\"assistant\",\"content\":\"The order has been confirmed.\"}",
|
|
208
|
+
"modelParameters": {
|
|
209
|
+
"temperature": 0.7,
|
|
210
|
+
"maxTokens": 500
|
|
211
|
+
},
|
|
212
|
+
"latency": 1.08,
|
|
213
|
+
"level": "DEFAULT",
|
|
214
|
+
"statusMessage": "",
|
|
215
|
+
"parentObservationId": "40e8ae4d0f708886"
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"id": "dfe582e2934f570d",
|
|
219
|
+
"traceId": "a1b2af2bc594eb816ab55a1d0c94fd47",
|
|
220
|
+
"type": "TOOL",
|
|
221
|
+
"name": "chargeCard",
|
|
222
|
+
"startTime": "2026-03-01T10:02:07.215Z",
|
|
223
|
+
"endTime": "2026-03-01T10:02:07.457Z",
|
|
224
|
+
"model": "",
|
|
225
|
+
"input": "{\"amount\":99.99,\"cardToken\":\"tok_visa1234\"}",
|
|
226
|
+
"output": "{\"success\":true,\"transactionId\":\"txn-123\"}",
|
|
227
|
+
"modelParameters": {},
|
|
228
|
+
"latency": 0.242,
|
|
229
|
+
"level": "DEFAULT",
|
|
230
|
+
"statusMessage": "",
|
|
231
|
+
"parentObservationId": "40e8ae4d0f708886"
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Tip:** If you prefer not to manually encode, curl's `-u username:password` flag will automatically base64-encode your credentials, but the header format shown above is the official recommended approach.
|
|
237
|
+
|
|
238
|
+
**Reference:** See the [Langfuse Observations API documentation](https://langfuse.com/docs/api-and-data-platform/features/observations-api) for complete API details.
|
|
239
|
+
|
|
240
|
+
### Important Notes
|
|
241
|
+
|
|
242
|
+
**User Responsibility:** You must ensure that Langfuse correctly records the following fields for each observation:
|
|
243
|
+
|
|
244
|
+
- **`input`** — the input data for the observation (stringified JSON: messages for LLM calls, args for tool calls)
|
|
245
|
+
- **`output`** — the output/result from the observation (stringified JSON)
|
|
246
|
+
- **`model`** — the model name for AI calls (e.g., `gpt-4o-2024-08-06`, `gemini-pro`). Can be empty string for non-AI observations
|
|
247
|
+
- **`type`** — the observation type (`GENERATION` for LLM calls, `TOOL` or `SPAN` for tool calls)
|
|
248
|
+
|
|
249
|
+
**If these fields are missing or incorrect, the SDK dashboard may not function properly.** Verify your Langfuse instrumentation captures these fields before attempting to import traces.
|
|
250
|
+
|
|
251
|
+
**Note:** The `input` and `output` fields in Langfuse's API response are **stringified JSON strings**, not objects. The dashboard will parse these automatically.
|
|
252
|
+
|
|
253
|
+
### Uploading to Dashboard
|
|
254
|
+
|
|
255
|
+
Once you've fetched the JSON response from Langfuse:
|
|
256
|
+
|
|
257
|
+
1. Save the response to a `.json` file (e.g., `trace.json`)
|
|
258
|
+
2. Open the dashboard: `npx elasticdash dashboard`
|
|
259
|
+
3. Select a workflow to debug
|
|
260
|
+
4. Click "Import Failed Trace" and upload your JSON file
|
|
261
|
+
5. The dashboard will parse the observations and let you mark broken steps
|
|
262
|
+
|
|
263
|
+
## Configuration Files
|
|
264
|
+
|
|
265
|
+
Dashboard discovery uses `ed_workflows.ts` (workflow list) and `ed_tools.ts` (tool list). `ed_agents.ts` is used for agent-related dashboard flows. A project-specific `ed_workers.ts` file is optional and not consumed by dashboard discovery.
|
|
266
|
+
|
|
267
|
+
### `ed_workflows.ts`
|
|
268
|
+
|
|
269
|
+
Re-export workflow functions from your application:
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
// ed_workflows.ts
|
|
273
|
+
export { orderWorkflow, refundWorkflow } from './src/workflows'
|
|
274
|
+
export { userLookupFlow } from './src/user-flows'
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Important: Workflow Function Compatibility**
|
|
278
|
+
|
|
279
|
+
Dashboard replay executes exported workflow functions directly in a subprocess. Exported functions in `ed_workflows.ts/js` should:
|
|
280
|
+
|
|
281
|
+
- Be directly callable functions (not framework request handlers)
|
|
282
|
+
- Accept JSON-serializable input (object or array)
|
|
283
|
+
- Return JSON-serializable output (object or array)
|
|
284
|
+
|
|
285
|
+
Not directly compatible as workflow exports:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
// Next.js route handler style
|
|
289
|
+
export async function POST(req: NextRequest): Promise<NextResponse> {
|
|
290
|
+
return NextResponse.json({ ok: true })
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
If your app uses framework handlers, create a plain workflow function and call it from the handler.
|
|
295
|
+
|
|
296
|
+
### `ed_tools.ts`
|
|
297
|
+
|
|
298
|
+
Re-export tool functions that agents or workflows can invoke:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
// ed_tools.ts
|
|
302
|
+
import { runSelectQuery } from './src/services/dataService'
|
|
303
|
+
|
|
304
|
+
export const dataService = async (input: any) => {
|
|
305
|
+
const { query } = input as { query: string }
|
|
306
|
+
return await runSelectQuery(query)
|
|
307
|
+
.then(async (res: any) => {
|
|
308
|
+
try {
|
|
309
|
+
const { recordToolCall } = await import('elasticdash-sdk')
|
|
310
|
+
recordToolCall('dataService', input, res)
|
|
311
|
+
} catch {
|
|
312
|
+
// tracing must never block the main service path
|
|
313
|
+
}
|
|
314
|
+
return res
|
|
315
|
+
})
|
|
316
|
+
.catch(async (err: any) => {
|
|
317
|
+
try {
|
|
318
|
+
const { recordToolCall } = await import('elasticdash-sdk')
|
|
319
|
+
recordToolCall('dataService', input, err)
|
|
320
|
+
} catch {
|
|
321
|
+
// tracing must never block the main service path
|
|
322
|
+
}
|
|
323
|
+
throw err
|
|
324
|
+
})
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Important: Tool Function Compatibility**
|
|
329
|
+
|
|
330
|
+
Dashboard tool reruns execute exported tool functions directly in a subprocess. Exported functions in `ed_tools.ts/js` should:
|
|
331
|
+
|
|
332
|
+
- Be directly callable functions (not framework request handlers)
|
|
333
|
+
- Accept JSON-serializable input (object or array)
|
|
334
|
+
- Return JSON-serializable output (object, array, or primitive)
|
|
335
|
+
|
|
336
|
+
Not directly compatible as tool exports:
|
|
337
|
+
|
|
338
|
+
```ts
|
|
339
|
+
// Next.js route handler style
|
|
340
|
+
export async function POST(req: NextRequest): Promise<NextResponse> {
|
|
341
|
+
return NextResponse.json({ ok: true })
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
If your app uses framework handlers, create a plain tool function and call it from the handler.
|
|
346
|
+
|
|
347
|
+
#### Important: Tool Name and Input Matching
|
|
348
|
+
|
|
349
|
+
**Function names in `ed_tools.ts` must exactly match the tool `name` field in your Langfuse traces.** The dashboard uses this matching for step-level testing and trace replay.
|
|
350
|
+
|
|
351
|
+
Example:
|
|
352
|
+
- If Langfuse records a tool observation with `"name": "chargeCard"`
|
|
353
|
+
- Then your `ed_tools.ts` must export a function named `chargeCard`:
|
|
354
|
+
```ts
|
|
355
|
+
export const chargeCard = async (input: any) => { ... }
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**Function input must match exactly what was recorded in Langfuse:**
|
|
359
|
+
- The `input` parameter structure must match the `input` field in the Langfuse trace
|
|
360
|
+
- When using `recordToolCall`, pass the function's `input` parameter directly as the second argument:
|
|
361
|
+
```ts
|
|
362
|
+
recordToolCall('chargeCard', input, result) // ✅ Correct
|
|
363
|
+
recordToolCall('chargeCard', input.amount, result) // ❌ Wrong - partial input
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
If names or inputs don't match, step-level test assertions and dashboard replay features will not work correctly.
|
|
367
|
+
|
|
368
|
+
### `ed_agents.ts`
|
|
369
|
+
|
|
370
|
+
Re-export agent functions:
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
// ed_agents.ts
|
|
374
|
+
export { checkoutAgent, paymentAgent } from './src/agents'
|
|
375
|
+
|
|
376
|
+
// Or as a config object:
|
|
377
|
+
export const agents = {
|
|
378
|
+
checkout: checkoutAgent,
|
|
379
|
+
payment: paymentAgent,
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Usage in Tests
|
|
384
|
+
|
|
385
|
+
Access workflows from tests:
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import { orderWorkflow } from './ed_workflows'
|
|
389
|
+
|
|
390
|
+
aiTest('full order workflow', async (ctx) => {
|
|
391
|
+
const result = await orderWorkflow('order-123', 'cust-456')
|
|
392
|
+
expect(ctx.trace).toCallTool('chargeCard')
|
|
393
|
+
})
|
|
394
|
+
```
|
package/docs/deno.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Using elasticdash-sdk in Deno
|
|
2
|
+
|
|
3
|
+
This guide shows how to add, pin, and run `elasticdash-sdk` inside a Deno project for AI workflow tests.
|
|
4
|
+
|
|
5
|
+
> **Setting up instrumentation files?** See the [Instrumentation Guide](instrumentation.md) for how to create `ed_tools.ts`, `ed_workflows.ts`, and `ed_agents.ts` in your project. The examples there are written from a Deno project perspective.
|
|
6
|
+
|
|
7
|
+
## 1) Add the dependency via import map
|
|
8
|
+
|
|
9
|
+
In your package `deno.json` (e.g., `packages/api/deno.json`), add an import mapping and a test task. Example pinned to 0.2.0:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"tasks": {
|
|
14
|
+
"test": "deno run -A --env-file=../../.env npm:elasticdash-sdk@0.2.0 test tests"
|
|
15
|
+
},
|
|
16
|
+
"imports": {
|
|
17
|
+
"elasticdash-sdk": "npm:elasticdash-sdk@0.2.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If registry integrity issues block 0.2.0, use the last known good build, e.g. `npm:elasticdash-sdk@0.1.6-alpha-2`, and mirror that in the task command.
|
|
23
|
+
|
|
24
|
+
## 2) Cache (optional, for reproducibility/offline)
|
|
25
|
+
|
|
26
|
+
From the package directory (e.g., `packages/api`):
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
deno cache --reload npm:elasticdash-sdk@0.2.0
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If you hit a checksum mismatch, switch to the pinned fallback version (e.g., `0.1.6-alpha-2`) and cache that instead.
|
|
33
|
+
|
|
34
|
+
## 3) Write a test
|
|
35
|
+
|
|
36
|
+
Create a test file under `tests/` ending with `.ai.test.ts` or `.ai.test.js` and import the setup:
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import "npm:elasticdash-sdk/dist/test-setup.js"
|
|
40
|
+
import { expect } from "npm:elasticdash-sdk"
|
|
41
|
+
|
|
42
|
+
aiTest("example", async () => {
|
|
43
|
+
expect(1 + 1).toBe(2)
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For API router testing with optional live OpenAI calls, see the existing example at `packages/api/tests/router.ai.test.js`.
|
|
48
|
+
|
|
49
|
+
## 4) Run tests
|
|
50
|
+
|
|
51
|
+
From your package directory:
|
|
52
|
+
|
|
53
|
+
- Stubbed/deterministic mode (default):
|
|
54
|
+
```bash
|
|
55
|
+
deno task test
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- Live mode (hits OpenAI):
|
|
59
|
+
```bash
|
|
60
|
+
RUN_LIVE_OPENAI=1 deno task test
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Ensure `OPENAI_API_KEY` is available (e.g., via `.env` loaded by `--env-file`).
|
|
64
|
+
|
|
65
|
+
## 5) Troubleshooting
|
|
66
|
+
|
|
67
|
+
- **Checksum mismatch when caching**: use the fallback version that matches your import map (e.g., `0.1.6-alpha-2`) and rerun `deno cache --reload npm:elasticdash-sdk@...`.
|
|
68
|
+
- **Command not found**: ensure you run tasks from the package folder where `deno.json` defines `test`.
|
|
69
|
+
- **Missing env vars**: confirm `.env` is loaded via `--env-file` or exported in your shell.
|