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.
Files changed (349) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +775 -0
  3. package/dist/browser-ui.d.ts +43 -0
  4. package/dist/browser-ui.d.ts.map +1 -0
  5. package/dist/browser-ui.js +246 -0
  6. package/dist/browser-ui.js.map +1 -0
  7. package/dist/capture/event.d.ts +33 -0
  8. package/dist/capture/event.d.ts.map +1 -0
  9. package/dist/capture/event.js +2 -0
  10. package/dist/capture/event.js.map +1 -0
  11. package/dist/capture/index.d.ts +4 -0
  12. package/dist/capture/index.d.ts.map +1 -0
  13. package/dist/capture/index.js +4 -0
  14. package/dist/capture/index.js.map +1 -0
  15. package/dist/capture/recorder.d.ts +24 -0
  16. package/dist/capture/recorder.d.ts.map +1 -0
  17. package/dist/capture/recorder.js +46 -0
  18. package/dist/capture/recorder.js.map +1 -0
  19. package/dist/capture/replay.d.ts +20 -0
  20. package/dist/capture/replay.d.ts.map +1 -0
  21. package/dist/capture/replay.js +47 -0
  22. package/dist/capture/replay.js.map +1 -0
  23. package/dist/ci/api-client.d.ts +38 -0
  24. package/dist/ci/api-client.d.ts.map +1 -0
  25. package/dist/ci/api-client.js +96 -0
  26. package/dist/ci/api-client.js.map +1 -0
  27. package/dist/ci/benchmark.d.ts +33 -0
  28. package/dist/ci/benchmark.d.ts.map +1 -0
  29. package/dist/ci/benchmark.js +213 -0
  30. package/dist/ci/benchmark.js.map +1 -0
  31. package/dist/ci/ed-runner.d.ts +48 -0
  32. package/dist/ci/ed-runner.d.ts.map +1 -0
  33. package/dist/ci/ed-runner.js +260 -0
  34. package/dist/ci/ed-runner.js.map +1 -0
  35. package/dist/ci/executor.d.ts +13 -0
  36. package/dist/ci/executor.d.ts.map +1 -0
  37. package/dist/ci/executor.js +542 -0
  38. package/dist/ci/executor.js.map +1 -0
  39. package/dist/ci/git-info.d.ts +17 -0
  40. package/dist/ci/git-info.d.ts.map +1 -0
  41. package/dist/ci/git-info.js +102 -0
  42. package/dist/ci/git-info.js.map +1 -0
  43. package/dist/ci/index.d.ts +6 -0
  44. package/dist/ci/index.d.ts.map +1 -0
  45. package/dist/ci/index.js +4 -0
  46. package/dist/ci/index.js.map +1 -0
  47. package/dist/ci/measurement.d.ts +9 -0
  48. package/dist/ci/measurement.d.ts.map +1 -0
  49. package/dist/ci/measurement.js +15 -0
  50. package/dist/ci/measurement.js.map +1 -0
  51. package/dist/ci/replay.d.ts +31 -0
  52. package/dist/ci/replay.d.ts.map +1 -0
  53. package/dist/ci/replay.js +96 -0
  54. package/dist/ci/replay.js.map +1 -0
  55. package/dist/ci/reporters/default.d.ts +8 -0
  56. package/dist/ci/reporters/default.d.ts.map +1 -0
  57. package/dist/ci/reporters/default.js +46 -0
  58. package/dist/ci/reporters/default.js.map +1 -0
  59. package/dist/ci/reporters/index.d.ts +8 -0
  60. package/dist/ci/reporters/index.d.ts.map +1 -0
  61. package/dist/ci/reporters/index.js +14 -0
  62. package/dist/ci/reporters/index.js.map +1 -0
  63. package/dist/ci/reporters/json.d.ts +8 -0
  64. package/dist/ci/reporters/json.d.ts.map +1 -0
  65. package/dist/ci/reporters/json.js +14 -0
  66. package/dist/ci/reporters/json.js.map +1 -0
  67. package/dist/ci/reporters/junit.d.ts +8 -0
  68. package/dist/ci/reporters/junit.d.ts.map +1 -0
  69. package/dist/ci/reporters/junit.js +48 -0
  70. package/dist/ci/reporters/junit.js.map +1 -0
  71. package/dist/ci/runner.d.ts +3 -0
  72. package/dist/ci/runner.d.ts.map +1 -0
  73. package/dist/ci/runner.js +187 -0
  74. package/dist/ci/runner.js.map +1 -0
  75. package/dist/ci/test-discovery.d.ts +5 -0
  76. package/dist/ci/test-discovery.d.ts.map +1 -0
  77. package/dist/ci/test-discovery.js +11 -0
  78. package/dist/ci/test-discovery.js.map +1 -0
  79. package/dist/ci/test-loader.d.ts +19 -0
  80. package/dist/ci/test-loader.d.ts.map +1 -0
  81. package/dist/ci/test-loader.js +149 -0
  82. package/dist/ci/test-loader.js.map +1 -0
  83. package/dist/ci/test-registry.d.ts +42 -0
  84. package/dist/ci/test-registry.d.ts.map +1 -0
  85. package/dist/ci/test-registry.js +18 -0
  86. package/dist/ci/test-registry.js.map +1 -0
  87. package/dist/ci/trace-schema.d.ts +30 -0
  88. package/dist/ci/trace-schema.d.ts.map +1 -0
  89. package/dist/ci/trace-schema.js +66 -0
  90. package/dist/ci/trace-schema.js.map +1 -0
  91. package/dist/ci/trace-writer.d.ts +16 -0
  92. package/dist/ci/trace-writer.d.ts.map +1 -0
  93. package/dist/ci/trace-writer.js +108 -0
  94. package/dist/ci/trace-writer.js.map +1 -0
  95. package/dist/ci/types.d.ts +108 -0
  96. package/dist/ci/types.d.ts.map +1 -0
  97. package/dist/ci/types.js +3 -0
  98. package/dist/ci/types.js.map +1 -0
  99. package/dist/ci/upload-client.d.ts +74 -0
  100. package/dist/ci/upload-client.d.ts.map +1 -0
  101. package/dist/ci/upload-client.js +195 -0
  102. package/dist/ci/upload-client.js.map +1 -0
  103. package/dist/cli.d.ts +3 -0
  104. package/dist/cli.d.ts.map +1 -0
  105. package/dist/cli.js +716 -0
  106. package/dist/cli.js.map +1 -0
  107. package/dist/core/agent-state.d.ts +47 -0
  108. package/dist/core/agent-state.d.ts.map +1 -0
  109. package/dist/core/agent-state.js +137 -0
  110. package/dist/core/agent-state.js.map +1 -0
  111. package/dist/core/judge-utils.d.ts +22 -0
  112. package/dist/core/judge-utils.d.ts.map +1 -0
  113. package/dist/core/judge-utils.js +211 -0
  114. package/dist/core/judge-utils.js.map +1 -0
  115. package/dist/core/registry.d.ts +28 -0
  116. package/dist/core/registry.d.ts.map +1 -0
  117. package/dist/core/registry.js +52 -0
  118. package/dist/core/registry.js.map +1 -0
  119. package/dist/dashboard-server.d.ts +65 -0
  120. package/dist/dashboard-server.d.ts.map +1 -0
  121. package/dist/dashboard-server.js +3940 -0
  122. package/dist/dashboard-server.js.map +1 -0
  123. package/dist/execution/tool-runner.d.ts +26 -0
  124. package/dist/execution/tool-runner.d.ts.map +1 -0
  125. package/dist/execution/tool-runner.js +316 -0
  126. package/dist/execution/tool-runner.js.map +1 -0
  127. package/dist/html/dashboard.html +2218 -0
  128. package/dist/http.d.ts +14 -0
  129. package/dist/http.d.ts.map +1 -0
  130. package/dist/http.js +13 -0
  131. package/dist/http.js.map +1 -0
  132. package/dist/index.cjs +8102 -0
  133. package/dist/index.d.ts +61 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +67 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/interceptors/ai-interceptor.d.ts +26 -0
  138. package/dist/interceptors/ai-interceptor.d.ts.map +1 -0
  139. package/dist/interceptors/ai-interceptor.js +756 -0
  140. package/dist/interceptors/ai-interceptor.js.map +1 -0
  141. package/dist/interceptors/db-auto.d.ts +8 -0
  142. package/dist/interceptors/db-auto.d.ts.map +1 -0
  143. package/dist/interceptors/db-auto.js +217 -0
  144. package/dist/interceptors/db-auto.js.map +1 -0
  145. package/dist/interceptors/db.d.ts +23 -0
  146. package/dist/interceptors/db.d.ts.map +1 -0
  147. package/dist/interceptors/db.js +137 -0
  148. package/dist/interceptors/db.js.map +1 -0
  149. package/dist/interceptors/http.d.ts +28 -0
  150. package/dist/interceptors/http.d.ts.map +1 -0
  151. package/dist/interceptors/http.js +356 -0
  152. package/dist/interceptors/http.js.map +1 -0
  153. package/dist/interceptors/side-effects.d.ts +7 -0
  154. package/dist/interceptors/side-effects.d.ts.map +1 -0
  155. package/dist/interceptors/side-effects.js +72 -0
  156. package/dist/interceptors/side-effects.js.map +1 -0
  157. package/dist/interceptors/telemetry-push.d.ts +142 -0
  158. package/dist/interceptors/telemetry-push.d.ts.map +1 -0
  159. package/dist/interceptors/telemetry-push.js +463 -0
  160. package/dist/interceptors/telemetry-push.js.map +1 -0
  161. package/dist/interceptors/tool.d.ts +2 -0
  162. package/dist/interceptors/tool.d.ts.map +1 -0
  163. package/dist/interceptors/tool.js +274 -0
  164. package/dist/interceptors/tool.js.map +1 -0
  165. package/dist/interceptors/workflow-ai.d.ts +5 -0
  166. package/dist/interceptors/workflow-ai.d.ts.map +1 -0
  167. package/dist/interceptors/workflow-ai.js +382 -0
  168. package/dist/interceptors/workflow-ai.js.map +1 -0
  169. package/dist/internals/conditional-recorder.d.ts +21 -0
  170. package/dist/internals/conditional-recorder.d.ts.map +1 -0
  171. package/dist/internals/conditional-recorder.js +54 -0
  172. package/dist/internals/conditional-recorder.js.map +1 -0
  173. package/dist/internals/mock-resolver.d.ts +146 -0
  174. package/dist/internals/mock-resolver.d.ts.map +1 -0
  175. package/dist/internals/mock-resolver.js +427 -0
  176. package/dist/internals/mock-resolver.js.map +1 -0
  177. package/dist/matchers/index.d.ts +96 -0
  178. package/dist/matchers/index.d.ts.map +1 -0
  179. package/dist/matchers/index.js +668 -0
  180. package/dist/matchers/index.js.map +1 -0
  181. package/dist/observability.d.ts +82 -0
  182. package/dist/observability.d.ts.map +1 -0
  183. package/dist/observability.js +471 -0
  184. package/dist/observability.js.map +1 -0
  185. package/dist/portal-executor.d.ts +30 -0
  186. package/dist/portal-executor.d.ts.map +1 -0
  187. package/dist/portal-executor.js +324 -0
  188. package/dist/portal-executor.js.map +1 -0
  189. package/dist/portal-server.d.ts +3 -0
  190. package/dist/portal-server.d.ts.map +1 -0
  191. package/dist/portal-server.js +279 -0
  192. package/dist/portal-server.js.map +1 -0
  193. package/dist/proxy/llm-capture.d.ts +14 -0
  194. package/dist/proxy/llm-capture.d.ts.map +1 -0
  195. package/dist/proxy/llm-capture.js +264 -0
  196. package/dist/proxy/llm-capture.js.map +1 -0
  197. package/dist/reporter.d.ts +3 -0
  198. package/dist/reporter.d.ts.map +1 -0
  199. package/dist/reporter.js +72 -0
  200. package/dist/reporter.js.map +1 -0
  201. package/dist/runWorkflowSubprocess.d.ts +14 -0
  202. package/dist/runWorkflowSubprocess.d.ts.map +1 -0
  203. package/dist/runWorkflowSubprocess.js +66 -0
  204. package/dist/runWorkflowSubprocess.js.map +1 -0
  205. package/dist/runner.d.ts +16 -0
  206. package/dist/runner.d.ts.map +1 -0
  207. package/dist/runner.js +138 -0
  208. package/dist/runner.js.map +1 -0
  209. package/dist/socket-connector.d.ts +22 -0
  210. package/dist/socket-connector.d.ts.map +1 -0
  211. package/dist/socket-connector.js +104 -0
  212. package/dist/socket-connector.js.map +1 -0
  213. package/dist/telemetry-batcher.d.ts +56 -0
  214. package/dist/telemetry-batcher.d.ts.map +1 -0
  215. package/dist/telemetry-batcher.js +143 -0
  216. package/dist/telemetry-batcher.js.map +1 -0
  217. package/dist/test-setup.d.ts +12 -0
  218. package/dist/test-setup.d.ts.map +1 -0
  219. package/dist/test-setup.js +13 -0
  220. package/dist/test-setup.js.map +1 -0
  221. package/dist/tool-registry.d.ts +31 -0
  222. package/dist/tool-registry.d.ts.map +1 -0
  223. package/dist/tool-registry.js +73 -0
  224. package/dist/tool-registry.js.map +1 -0
  225. package/dist/tool-runner-worker.d.ts +2 -0
  226. package/dist/tool-runner-worker.d.ts.map +1 -0
  227. package/dist/tool-runner-worker.js +215 -0
  228. package/dist/tool-runner-worker.js.map +1 -0
  229. package/dist/trace-adapter/context.d.ts +72 -0
  230. package/dist/trace-adapter/context.d.ts.map +1 -0
  231. package/dist/trace-adapter/context.js +80 -0
  232. package/dist/trace-adapter/context.js.map +1 -0
  233. package/dist/tracing.d.ts +2 -0
  234. package/dist/tracing.d.ts.map +1 -0
  235. package/dist/tracing.js +59 -0
  236. package/dist/tracing.js.map +1 -0
  237. package/dist/trigger-executor.d.ts +12 -0
  238. package/dist/trigger-executor.d.ts.map +1 -0
  239. package/dist/trigger-executor.js +130 -0
  240. package/dist/trigger-executor.js.map +1 -0
  241. package/dist/types/portal.d.ts +76 -0
  242. package/dist/types/portal.d.ts.map +1 -0
  243. package/dist/types/portal.js +2 -0
  244. package/dist/types/portal.js.map +1 -0
  245. package/dist/utils/debug.d.ts +3 -0
  246. package/dist/utils/debug.d.ts.map +1 -0
  247. package/dist/utils/debug.js +8 -0
  248. package/dist/utils/debug.js.map +1 -0
  249. package/dist/utils/license-error.d.ts +23 -0
  250. package/dist/utils/license-error.d.ts.map +1 -0
  251. package/dist/utils/license-error.js +42 -0
  252. package/dist/utils/license-error.js.map +1 -0
  253. package/dist/utils/redact.d.ts +7 -0
  254. package/dist/utils/redact.d.ts.map +1 -0
  255. package/dist/utils/redact.js +26 -0
  256. package/dist/utils/redact.js.map +1 -0
  257. package/dist/workflow-runner-worker.d.ts +2 -0
  258. package/dist/workflow-runner-worker.d.ts.map +1 -0
  259. package/dist/workflow-runner-worker.js +329 -0
  260. package/dist/workflow-runner-worker.js.map +1 -0
  261. package/dist/workflow-runner.d.ts +14 -0
  262. package/dist/workflow-runner.d.ts.map +1 -0
  263. package/dist/workflow-runner.js +34 -0
  264. package/dist/workflow-runner.js.map +1 -0
  265. package/docs/agent-coding-instructions.md +138 -0
  266. package/docs/agent-integration-guide.md +564 -0
  267. package/docs/agents.md +140 -0
  268. package/docs/dashboard.md +394 -0
  269. package/docs/deno.md +69 -0
  270. package/docs/instrumentation.md +424 -0
  271. package/docs/langfuse-trace-structure.md +145 -0
  272. package/docs/matchers.md +173 -0
  273. package/docs/observability_contract.md +192 -0
  274. package/docs/observability_mode.md +195 -0
  275. package/docs/quickstart.md +621 -0
  276. package/docs/security-compliance.md +566 -0
  277. package/docs/test-writing-guidelines.md +444 -0
  278. package/docs/tools.md +165 -0
  279. package/docs/workflow-modes.md +253 -0
  280. package/package.json +76 -0
  281. package/src/browser-ui.ts +281 -0
  282. package/src/capture/event.ts +30 -0
  283. package/src/capture/index.ts +3 -0
  284. package/src/capture/recorder.ts +62 -0
  285. package/src/capture/replay.ts +55 -0
  286. package/src/ci/api-client.ts +136 -0
  287. package/src/ci/benchmark.ts +257 -0
  288. package/src/ci/ed-runner.ts +351 -0
  289. package/src/ci/executor.ts +671 -0
  290. package/src/ci/git-info.ts +127 -0
  291. package/src/ci/index.ts +5 -0
  292. package/src/ci/measurement.ts +25 -0
  293. package/src/ci/replay.ts +127 -0
  294. package/src/ci/reporters/default.ts +50 -0
  295. package/src/ci/reporters/index.ts +21 -0
  296. package/src/ci/reporters/json.ts +18 -0
  297. package/src/ci/reporters/junit.ts +61 -0
  298. package/src/ci/runner.ts +208 -0
  299. package/src/ci/test-discovery.ts +16 -0
  300. package/src/ci/test-loader.ts +187 -0
  301. package/src/ci/test-registry.ts +62 -0
  302. package/src/ci/trace-schema.ts +96 -0
  303. package/src/ci/trace-writer.ts +107 -0
  304. package/src/ci/types.ts +115 -0
  305. package/src/ci/upload-client.ts +300 -0
  306. package/src/cli.ts +811 -0
  307. package/src/core/agent-state.ts +162 -0
  308. package/src/core/judge-utils.ts +232 -0
  309. package/src/core/registry.ts +92 -0
  310. package/src/dashboard-server.ts +2047 -0
  311. package/src/execution/tool-runner.ts +352 -0
  312. package/src/html/dashboard.html +2218 -0
  313. package/src/http.ts +13 -0
  314. package/src/index.ts +138 -0
  315. package/src/interceptors/ai-interceptor.ts +798 -0
  316. package/src/interceptors/db-auto.ts +243 -0
  317. package/src/interceptors/db.ts +156 -0
  318. package/src/interceptors/http.ts +393 -0
  319. package/src/interceptors/side-effects.ts +83 -0
  320. package/src/interceptors/telemetry-push.ts +537 -0
  321. package/src/interceptors/tool.ts +287 -0
  322. package/src/interceptors/workflow-ai.ts +419 -0
  323. package/src/internals/conditional-recorder.ts +63 -0
  324. package/src/internals/mock-resolver.ts +492 -0
  325. package/src/matchers/index.ts +824 -0
  326. package/src/observability.ts +501 -0
  327. package/src/portal-executor.ts +355 -0
  328. package/src/portal-server.ts +304 -0
  329. package/src/proxy/llm-capture.ts +301 -0
  330. package/src/reporter.ts +81 -0
  331. package/src/runWorkflowSubprocess.ts +74 -0
  332. package/src/runner.ts +178 -0
  333. package/src/socket-connector.ts +117 -0
  334. package/src/telemetry-batcher.ts +191 -0
  335. package/src/test-setup.ts +16 -0
  336. package/src/tool-registry.ts +94 -0
  337. package/src/tool-runner-worker.ts +244 -0
  338. package/src/trace-adapter/context.ts +156 -0
  339. package/src/tracing.ts +62 -0
  340. package/src/trigger-executor.ts +171 -0
  341. package/src/types/agent.d.ts +63 -0
  342. package/src/types/expect.d.ts +81 -0
  343. package/src/types/modules.d.ts +2 -0
  344. package/src/types/portal.ts +69 -0
  345. package/src/utils/debug.ts +8 -0
  346. package/src/utils/license-error.ts +43 -0
  347. package/src/utils/redact.ts +25 -0
  348. package/src/workflow-runner-worker.ts +386 -0
  349. 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.