elasticdash-test 0.1.11-alpha-1 → 0.1.11-alpha-3

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 (104) hide show
  1. package/README.md +256 -11
  2. package/dist/browser-ui.js +0 -4
  3. package/dist/browser-ui.js.map +1 -1
  4. package/dist/capture/event.d.ts +19 -0
  5. package/dist/capture/event.d.ts.map +1 -0
  6. package/dist/capture/event.js +2 -0
  7. package/dist/capture/event.js.map +1 -0
  8. package/dist/capture/index.d.ts +4 -0
  9. package/dist/capture/index.d.ts.map +1 -0
  10. package/dist/capture/index.js +4 -0
  11. package/dist/capture/index.js.map +1 -0
  12. package/dist/capture/recorder.d.ts +19 -0
  13. package/dist/capture/recorder.d.ts.map +1 -0
  14. package/dist/capture/recorder.js +36 -0
  15. package/dist/capture/recorder.js.map +1 -0
  16. package/dist/capture/replay.d.ts +20 -0
  17. package/dist/capture/replay.d.ts.map +1 -0
  18. package/dist/capture/replay.js +47 -0
  19. package/dist/capture/replay.js.map +1 -0
  20. package/dist/cli.js +0 -0
  21. package/dist/core/agent-state.d.ts +47 -0
  22. package/dist/core/agent-state.d.ts.map +1 -0
  23. package/dist/core/agent-state.js +137 -0
  24. package/dist/core/agent-state.js.map +1 -0
  25. package/dist/dashboard-server.d.ts +3 -0
  26. package/dist/dashboard-server.d.ts.map +1 -1
  27. package/dist/dashboard-server.js +2531 -687
  28. package/dist/dashboard-server.js.map +1 -1
  29. package/dist/index.d.ts +16 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +12 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/interceptors/ai-interceptor.d.ts.map +1 -1
  34. package/dist/interceptors/ai-interceptor.js +221 -10
  35. package/dist/interceptors/ai-interceptor.js.map +1 -1
  36. package/dist/interceptors/db-auto.d.ts +8 -0
  37. package/dist/interceptors/db-auto.d.ts.map +1 -0
  38. package/dist/interceptors/db-auto.js +125 -0
  39. package/dist/interceptors/db-auto.js.map +1 -0
  40. package/dist/interceptors/db.d.ts +18 -0
  41. package/dist/interceptors/db.d.ts.map +1 -0
  42. package/dist/interceptors/db.js +59 -0
  43. package/dist/interceptors/db.js.map +1 -0
  44. package/dist/interceptors/http.d.ts +3 -0
  45. package/dist/interceptors/http.d.ts.map +1 -0
  46. package/dist/interceptors/http.js +172 -0
  47. package/dist/interceptors/http.js.map +1 -0
  48. package/dist/interceptors/side-effects.d.ts +7 -0
  49. package/dist/interceptors/side-effects.d.ts.map +1 -0
  50. package/dist/interceptors/side-effects.js +72 -0
  51. package/dist/interceptors/side-effects.js.map +1 -0
  52. package/dist/interceptors/tool.d.ts +2 -0
  53. package/dist/interceptors/tool.d.ts.map +1 -0
  54. package/dist/interceptors/tool.js +75 -0
  55. package/dist/interceptors/tool.js.map +1 -0
  56. package/dist/interceptors/workflow-ai.d.ts +2 -0
  57. package/dist/interceptors/workflow-ai.d.ts.map +1 -0
  58. package/dist/interceptors/workflow-ai.js +26 -0
  59. package/dist/interceptors/workflow-ai.js.map +1 -0
  60. package/dist/internals/async-storage.d.ts +21 -0
  61. package/dist/internals/async-storage.d.ts.map +1 -0
  62. package/dist/internals/async-storage.js +46 -0
  63. package/dist/internals/async-storage.js.map +1 -0
  64. package/dist/internals/conditional-recorder.d.ts +21 -0
  65. package/dist/internals/conditional-recorder.d.ts.map +1 -0
  66. package/dist/internals/conditional-recorder.js +54 -0
  67. package/dist/internals/conditional-recorder.js.map +1 -0
  68. package/dist/internals/node-crypto.d.ts +12 -0
  69. package/dist/internals/node-crypto.d.ts.map +1 -0
  70. package/dist/internals/node-crypto.js +38 -0
  71. package/dist/internals/node-crypto.js.map +1 -0
  72. package/dist/matchers/index.d.ts +2 -1
  73. package/dist/matchers/index.d.ts.map +1 -1
  74. package/dist/matchers/index.js +28 -1
  75. package/dist/matchers/index.js.map +1 -1
  76. package/dist/runWorkflowSubprocess.d.ts +14 -0
  77. package/dist/runWorkflowSubprocess.d.ts.map +1 -0
  78. package/dist/runWorkflowSubprocess.js +66 -0
  79. package/dist/runWorkflowSubprocess.js.map +1 -0
  80. package/dist/tool-runner-worker.d.ts +2 -0
  81. package/dist/tool-runner-worker.d.ts.map +1 -0
  82. package/dist/tool-runner-worker.js +55 -0
  83. package/dist/tool-runner-worker.js.map +1 -0
  84. package/dist/trace-adapter/context.d.ts +2 -0
  85. package/dist/trace-adapter/context.d.ts.map +1 -1
  86. package/dist/trace-adapter/context.js +10 -4
  87. package/dist/trace-adapter/context.js.map +1 -1
  88. package/dist/tracing-universal.d.ts +13 -0
  89. package/dist/tracing-universal.d.ts.map +1 -0
  90. package/dist/tracing-universal.js +33 -0
  91. package/dist/tracing-universal.js.map +1 -0
  92. package/dist/tracing.d.ts +2 -0
  93. package/dist/tracing.d.ts.map +1 -0
  94. package/dist/tracing.js +59 -0
  95. package/dist/tracing.js.map +1 -0
  96. package/dist/workflow-runner-worker.d.ts +2 -0
  97. package/dist/workflow-runner-worker.d.ts.map +1 -0
  98. package/dist/workflow-runner-worker.js +256 -0
  99. package/dist/workflow-runner-worker.js.map +1 -0
  100. package/dist/workflow-runner.d.ts +14 -0
  101. package/dist/workflow-runner.d.ts.map +1 -0
  102. package/dist/workflow-runner.js +30 -0
  103. package/dist/workflow-runner.js.map +1 -0
  104. package/package.json +8 -3
package/README.md CHANGED
@@ -285,6 +285,99 @@ aiTest('user lookup flow', async (ctx) => {
285
285
 
286
286
  **Libraries using `https.request` directly** (older versions of some SDKs) are not covered by fetch interception. Use manual `ctx.trace.recordLLMStep()` for those.
287
287
 
288
+ ## Automatic Tool Recording
289
+
290
+ Tool functions are automatically wrapped and recorded when imported and called during workflow execution. This gives you tracing and replay support without any manual instrumentation.
291
+
292
+ ### How to use tools
293
+
294
+ Define your tools in `ed_tools.ts` and export them:
295
+
296
+ ```ts
297
+ // ed_tools.ts
298
+ import { wrapTool } from 'elasticdash-test'
299
+
300
+ export const chargeCard = wrapTool('chargeCard', async (input: { amount: number; cardToken: string }) => {
301
+ // your actual implementation
302
+ return { success: true, transactionId: 'txn-123' }
303
+ })
304
+
305
+ export const fetchOrderStatus = wrapTool('fetchOrderStatus', async (input: { orderId: string }) => {
306
+ // query your database or API
307
+ return { status: 'shipped', tracking: 'track-456' }
308
+ })
309
+ ```
310
+
311
+ In your workflows or agents, simply import and call them — the runner automatically wraps them and records each call:
312
+
313
+ ```ts
314
+ import { chargeCard, fetchOrderStatus } from './ed_tools'
315
+
316
+ export async function checkoutFlow(orderId: string, cardToken: string) {
317
+ const order = await fetchOrderStatus({ orderId })
318
+ const charge = await chargeCard({ amount: order.total, cardToken })
319
+ return { orderId, chargeId: charge.transactionId }
320
+ }
321
+ ```
322
+
323
+ Each call to a tool is automatically recorded to `ctx.trace` with:
324
+ - Tool name
325
+ - Input arguments
326
+ - Output result
327
+ - Timestamp and duration
328
+
329
+ No `ctx.trace.recordToolCall()` needed — it happens behind the scenes.
330
+
331
+ Runtime behavior by mode:
332
+ - Local/normal execution: wrapped tools run normally (no replay context).
333
+ - Trace capture mode: wrapped tools run normally and are recorded.
334
+ - Replay mode (`Run from here`): pre-checkpoint wrapped calls return historical results and skip tool body execution.
335
+
336
+ ### Tool replay and freezing in "Run from here"
337
+
338
+ When you use the dashboard's "Run from here" feature to replay a workflow from a checkpoint:
339
+
340
+ 1. **Tools called before the checkpoint** are **frozen** — their recorded results are returned instantly without re-executing the actual function.
341
+ 2. **Tools called after the checkpoint** execute normally with live dependencies.
342
+
343
+ This means:
344
+ - If a tool made 3 API calls before the checkpoint, those calls won't happen again on replay.
345
+ - If the tool is slow (waiting for external services), frozen calls are instant.
346
+ - The tool's frozen status is visible in the dashboard with a frozen tag/styling, matching AI step behavior.
347
+ - Side-effect replay is type-checked (`Date.now` vs `Math.random`) and malformed observation timestamps are auto-sanitized.
348
+
349
+ Example:
350
+ ```
351
+ Task 1: fetchOrderStatus() ↓ frozen (checkpoint before this)
352
+ │─ API call to orders service ↓ frozen
353
+ └─ Result: { status: shipped } ↓ frozen
354
+
355
+ → You modify input for Task 2 and re-run
356
+ The fetchOrderStatus API call is skipped; the original result is reused instantly.
357
+ ```
358
+
359
+ ### Recording tool calls manually
360
+
361
+ If you need to record tools outside the normal import flow or for providers not in `ed_tools.ts`, use:
362
+
363
+ ```ts
364
+ ctx.trace.recordToolCall({
365
+ name: 'customTool',
366
+ args: { param: 'value' },
367
+ result: { success: true }
368
+ })
369
+ ```
370
+
371
+ Manual recording is best-effort trace logging. For full replay/freeze semantics in "Run from here" (including frozen tool tags and deterministic replay), run tools through the replay-aware wrapper path (auto-wrapped worker tools or `wrapTool(...)`).
372
+
373
+ ```ts
374
+ import { wrapTool } from 'elasticdash-test'
375
+
376
+ export const customTool = wrapTool('customTool', async (input: { param: string }) => {
377
+ return await doWork(input)
378
+ })
379
+ ```
380
+
288
381
  ### Recording flow steps without passing `ctx.trace` (AsyncLocalStorage)
289
382
 
290
383
  The runner now sets a per-test `currentTrace` using Node’s `AsyncLocalStorage`, so your app code can record steps without threading `ctx.trace` through every function. This remains safe under parallel execution.
@@ -377,12 +470,26 @@ elasticdash dashboard --port 4572 # use custom port
377
470
  elasticdash dashboard --no-open # skip auto-opening browser
378
471
  ```
379
472
 
380
- The dashboard scans `ed_workflow.ts` or `ed_workflow.js` and displays:
381
- - **Function names** all exported functions in the module
382
- - **Signatures**function parameters and return types
383
- - **Async indicator** marks async vs sync functions
384
- - **Source module** — where the function is imported from (if re-exported)
385
- - **File path** location of the workflow file
473
+ The dashboard scans your workflow/tool files and displays:
474
+ - If both `.ts` and `.js` versions of a file exist (e.g., `ed_workflows.ts` and `ed_workflows.js`), the dashboard will always use the `.ts` file.
475
+ - If only `.ts` exists, it will be automatically transpiled to `.js` before scanning/importingno manual build step required.
476
+ - If only `.js` exists, it will be used directly.
477
+
478
+ This means you can write your workflows and tools in TypeScript, and the dashboard will handle transpilation automatically. You do not need to run `tsc` or build manually for dashboard usage.
479
+
480
+ **Example file selection logic:**
481
+ | Scenario | File Used |
482
+ |-------------------------|------------------|
483
+ | Only `ed_workflows.ts` | Transpiled `.ts` |
484
+ | Only `ed_workflows.js` | `.js` |
485
+ | Both exist | `.ts` (preferred)|
486
+
487
+ The dashboard displays:
488
+ - **Function names** — all exported functions in the module
489
+ - **Signatures** — function parameters and return types
490
+ - **Async indicator** — marks async vs sync functions
491
+ - **Source module** — where the function is imported from (if re-exported)
492
+ - **File path** — location of the workflow file
386
493
 
387
494
  Use the search field to filter workflows by:
388
495
  - **Name** — find workflow by function name (e.g., `checkoutFlow`)
@@ -391,16 +498,16 @@ Use the search field to filter workflows by:
391
498
 
392
499
  This is useful for discovering available workflows, understanding their signatures, and identifying where functions are defined before calling them in tests.
393
500
 
394
- ### `ed_workflow.ts`, `ed_tools.ts`, `ed_agents.ts`
501
+ ### `ed_workflows.ts`, `ed_tools.ts`, `ed_agents.ts`
395
502
 
396
503
  These optional files bundle and re-export existing functions from your codebase for use in tests.
397
504
 
398
- #### `ed_workflow.ts`
505
+ #### `ed_workflows.ts`
399
506
 
400
507
  Re-export workflow functions from your application:
401
508
 
402
509
  ```ts
403
- // ed_workflow.ts
510
+ // ed_workflows.ts
404
511
  export { orderWorkflow, refundWorkflow } from './src/workflows'
405
512
  export { userLookupFlow } from './src/user-flows'
406
513
  ```
@@ -408,7 +515,7 @@ export { userLookupFlow } from './src/user-flows'
408
515
  Access in tests:
409
516
 
410
517
  ```ts
411
- import { orderWorkflow } from './ed_workflow'
518
+ import { orderWorkflow } from './ed_workflows'
412
519
 
413
520
  aiTest('full order workflow', async (ctx) => {
414
521
  const result = await orderWorkflow('order-123', 'cust-456')
@@ -422,7 +529,12 @@ Re-export tool functions that agents or workflows can invoke:
422
529
 
423
530
  ```ts
424
531
  // ed_tools.ts
425
- export { chargeCard, fetchOrderStatus, sendNotification } from './src/tools'
532
+ import { wrapTool } from 'elasticdash-test'
533
+ import { chargeCard as chargeCardRaw, fetchOrderStatus as fetchOrderStatusRaw, sendNotification as sendNotificationRaw } from './src/tools'
534
+
535
+ export const chargeCard = wrapTool('chargeCard', chargeCardRaw)
536
+ export const fetchOrderStatus = wrapTool('fetchOrderStatus', fetchOrderStatusRaw)
537
+ export const sendNotification = wrapTool('sendNotification', sendNotificationRaw)
426
538
  ```
427
539
 
428
540
  #### `ed_agents.ts`
@@ -444,6 +556,111 @@ The dashboard command will scan these files and display all exported functions w
444
556
 
445
557
  ---
446
558
 
559
+ ## Agent Mid-Trace Replay
560
+
561
+ ElasticDash supports resuming a long-running agent from any task in its plan — without re-executing already-completed steps. This is useful for:
562
+
563
+ - **Resuming after failures**: If task 3 of 5 fails, fix the issue and re-run from task 3 only.
564
+ - **Pausing for approval**: Capture state after task 2, get human sign-off, then continue.
565
+ - **Debugging in isolation**: Re-run a single task with modified input to diagnose a problem.
566
+
567
+ ### How it works
568
+
569
+ Agents are structured as an **AgentPlan** — an ordered list of **AgentTask** objects, each with a tool name, input, and output. When serialized, the plan plus all captured trace events form an **AgentState** that can be saved to disk/database and replayed later.
570
+
571
+ ### Quick start
572
+
573
+ ```ts
574
+ import { plannerAgent, executorAgent, resumeAgentFromTrace } from './ed_agents'
575
+ import { serializeAgentState, deserializeAgentState } from 'elasticdash-test'
576
+ import fs from 'node:fs'
577
+
578
+ // 1. Generate a plan
579
+ const plan = await plannerAgent('Show me sales for Q1', { userToken: 'tok-abc' })
580
+
581
+ // 2. Execute the plan (runs all tasks sequentially)
582
+ const completedPlan = await executorAgent(plan)
583
+
584
+ // 3. Serialize and save state (e.g., after partial execution)
585
+ const state = serializeAgentState(completedPlan, [] /* pass recorder.events in worker context */)
586
+ fs.writeFileSync('agent-state.json', JSON.stringify(state, null, 2))
587
+
588
+ // 4. Later: load saved state and resume from task 2 (0-based index 1)
589
+ const savedState = JSON.parse(fs.readFileSync('agent-state.json', 'utf8'))
590
+ const stateToResume = deserializeAgentState({ ...savedState, resumeFromTaskIndex: 1 })
591
+ const resumedPlan = await resumeAgentFromTrace(stateToResume)
592
+
593
+ console.log('Resumed plan status:', resumedPlan.status)
594
+ console.log('Task outputs:', resumedPlan.tasks.map((t) => ({ id: t.id, status: t.status })))
595
+ ```
596
+
597
+ ### AgentState structure
598
+
599
+ ```ts
600
+ interface AgentState {
601
+ plan: AgentPlan // Full plan with all tasks (completed and pending)
602
+ trace: WorkflowEvent[] // Captured trace events from previous execution
603
+ resumeFromTaskIndex: number // Zero-based index — tasks before this are loaded from cache
604
+ }
605
+
606
+ interface AgentPlan {
607
+ id: string
608
+ tasks: AgentTask[]
609
+ status: 'planning' | 'executing' | 'completed' | 'failed' | 'paused'
610
+ currentTaskIndex: number
611
+ context: Record<string, unknown>
612
+ metadata: Record<string, unknown>
613
+ }
614
+
615
+ interface AgentTask {
616
+ id: string
617
+ status: 'pending' | 'in-progress' | 'completed' | 'failed'
618
+ description: string
619
+ tool: string // Name of the tool function to invoke
620
+ input: unknown // May contain { $ref: "task-N.output.fieldName" } placeholders
621
+ output?: unknown // Populated after execution
622
+ error?: string
623
+ startedAt?: number
624
+ completedAt?: number
625
+ }
626
+ ```
627
+
628
+ ### Task input placeholders
629
+
630
+ Task inputs can reference previous task outputs using `{ $ref: "taskId.output.fieldPath" }`:
631
+
632
+ ```ts
633
+ // task-2 uses the embedding produced by task-1
634
+ {
635
+ id: 'task-2',
636
+ tool: 'taskSelectorService',
637
+ input: {
638
+ queryEmbedding: { $ref: 'task-1.output.embedding' },
639
+ topK: 3,
640
+ }
641
+ }
642
+ ```
643
+
644
+ Placeholders are resolved at execution time by `resolveTaskInput()`.
645
+
646
+ ### Dashboard integration
647
+
648
+ When running an agent workflow through the dashboard:
649
+
650
+ 1. Agent task observations are **visually highlighted** with a purple background and left border, making them easy to identify.
651
+ 2. Each agent observation shows a **T1 / T2 / T3** badge indicating which task it belongs to.
652
+ 3. In the observation detail panel, a **"Resume from Task N"** button appears (agent steps only — non-agent steps have no button).
653
+ 4. Clicking it calls `/api/resume-agent-from-task` with the serialized `AgentState` and the chosen `taskIndex`, then adds the resumed run as a new trace in the comparison table.
654
+
655
+ ### Best practices for resumable agents
656
+
657
+ - **Keep tasks idempotent** where possible — if a task must be re-run, ensure it produces the same result.
658
+ - **Store minimal outputs** — only record what downstream tasks need, not full API responses.
659
+ - **Version your state schema** — if tool interfaces change, old states may need migration.
660
+ - **Use sequential tasks** — the current implementation runs tasks one-by-one; parallel task support is a planned future enhancement.
661
+
662
+ ---
663
+
447
664
  ## Project Structure
448
665
 
449
666
  ```
@@ -481,6 +698,34 @@ uninstallAIInterceptor() // restore original fetch when done
481
698
 
482
699
  ---
483
700
 
701
+ ## Recording Tool Calls Explicitly
702
+
703
+ If you want to ensure tool calls are always recorded in the workflow trace—regardless of how your tools are imported or used—you can use the `recordToolCall` utility provided by this SDK.
704
+
705
+ ### How to Use
706
+
707
+
708
+ 1. Import the function in your tool implementation:
709
+
710
+ ```ts
711
+ import { recordToolCall } from 'elasticdash-test'
712
+
713
+ export async function myTool(input: string) {
714
+ // ...tool logic...
715
+ const result = `Hello, ${input}!`
716
+ recordToolCall('myTool', { input }, result)
717
+ return result
718
+ }
719
+ ```
720
+
721
+ 2. When running under ElasticDash, all calls to `recordToolCall` will be captured in the workflow trace. When running locally or outside the runner, this function is a no-op and will not affect your code.
722
+
723
+ **This approach is robust and works with both imported and global tools.**
724
+
725
+ **Summary:**
726
+ - Use tools as globals (no import) for full traceability and automatic tool call capture.
727
+ - This approach keeps your workflow code clean and enables powerful debugging and analytics in ElasticDash.
728
+
484
729
  ## Non-Goals
485
730
 
486
731
  This runner intentionally does not support:
@@ -1,7 +1,5 @@
1
1
  import http from 'node:http';
2
- import path from 'node:path';
3
2
  import os from 'node:os';
4
- import { fileURLToPath } from 'node:url';
5
3
  import { spawn } from 'node:child_process';
6
4
  const defaultHtml = `<!doctype html>
7
5
  <html lang="en">
@@ -149,8 +147,6 @@ const defaultHtml = `<!doctype html>
149
147
  export async function startBrowserUiServer(opts = {}) {
150
148
  const autoOpen = opts.autoOpen !== false;
151
149
  let port = opts.port ?? 4571;
152
- // Ensure base dir for potential static assets (none now)
153
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
154
150
  const clients = [];
155
151
  const eventBuffer = [];
156
152
  const handler = (req, res) => {
@@ -1 +1 @@
1
- {"version":3,"file":"browser-ui.js","sourceRoot":"","sources":["../src/browser-ui.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAmB1C,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8IZ,CAAA;AAER,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAyB,EAAE;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAA;IACxC,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAA;IAE5B,yDAAyD;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAG9D,MAAM,OAAO,GAAwB,EAAE,CAAA;IACvC,MAAM,WAAW,GAAc,EAAE,CAAA;IAEjC,MAAM,OAAO,GAAyB,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACjD,IAAI,CAAC,GAAG,CAAC,GAAG;YAAE,OAAO,GAAG,CAAC,GAAG,EAAE,CAAA;QAC9B,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,GAAwB,CAAA;YACvC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;gBACpB,cAAc,EAAE,mBAAmB;gBACnC,UAAU,EAAE,YAAY;gBACxB,eAAe,EAAE,UAAU;aAC5B,CAAC,CAAA;YACF,sDAAsD;YACtD,MAAM,CAAC,YAAY,EAAE,EAAE,CAAA;YACvB,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAC/B,MAAM,CAAC,KAAK,EAAE,EAAE,CAAA;YAChB,qFAAqF;YACrF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;gBAC5B,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;YAChD,CAAC;YACD,MAAM,CAAC,KAAK,EAAE,EAAE,CAAA;YAChB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACpB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACnB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;gBACnC,IAAI,GAAG,IAAI,CAAC;oBAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YACtC,CAAC,CAAC,CAAA;YACF,OAAM;QACR,CAAC;QAED,oBAAoB;QACpB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAA;QACnD,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACtB,CAAC,CAAA;IAED,IAAI,MAA+B,CAAA;IACnC,IAAI,SAAqD,CAAA;IACzD,IAAI,OAAO,GAAG,KAAK,CAAA;IAEnB,OAAO,CAAC,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;YACnC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAO,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC7B,MAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC/B,CAAC,CAAC,CAAA;YACF,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,CAAA;YACT,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACpC,OAAO,CAAC,KAAK,CAAC,kDAAkD,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;gBACzF,OAAO,SAAS,CAAA;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,oBAAoB,IAAI,EAAE,CAAA;IAEtC,SAAS,IAAI,CAAC,KAAc;QAC1B,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,MAAM,OAAO,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAA;QACpD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACrB,MAAM,CAAC,KAAK,EAAE,EAAE,CAAA;QAClB,CAAC;IACH,CAAC;IAED,SAAS,KAAK;QACZ,IAAI,SAAS,EAAE,CAAC;YACd,aAAa,CAAC,SAAS,CAAC,CAAA;YACxB,SAAS,GAAG,SAAS,CAAA;QACvB,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,CAAC,GAAG,EAAE,CAAA;QACd,CAAC;QACD,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;QAClB,MAAM,EAAE,KAAK,EAAE,CAAA;IACjB,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAA;IAClB,CAAC;IAED,8EAA8E;IAC9E,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QAC3B,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;YAC/B,MAAM,CAAC,KAAK,EAAE,EAAE,CAAA;QAClB,CAAC;IACH,CAAC,EAAE,IAAI,CAAC,CAAA;IAER,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AAC7B,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAA;IAC9B,MAAM,OAAO,GACX,QAAQ,KAAK,QAAQ;QACnB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,QAAQ,KAAK,OAAO;YACtB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,UAAU,CAAA;IAEhB,MAAM,IAAI,GAAG,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACtE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvE,KAAK,CAAC,KAAK,EAAE,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"browser-ui.js","sourceRoot":"","sources":["../src/browser-ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export type WorkflowEventType = 'ai' | 'tool' | 'http' | 'db' | 'side_effect';
2
+ export interface WorkflowEvent {
3
+ id: number;
4
+ type: WorkflowEventType;
5
+ name: string;
6
+ input: unknown;
7
+ output: unknown;
8
+ timestamp: number;
9
+ durationMs: number;
10
+ /** Optional: ID of the agent task that produced this event */
11
+ agentTaskId?: string;
12
+ /** Optional: Zero-based index of the agent task that produced this event */
13
+ agentTaskIndex?: number;
14
+ }
15
+ export interface WorkflowTrace {
16
+ traceId: string;
17
+ events: WorkflowEvent[];
18
+ }
19
+ //# sourceMappingURL=event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../src/capture/event.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,aAAa,CAAA;AAE7E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,iBAAiB,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,aAAa,EAAE,CAAA;CACxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.js","sourceRoot":"","sources":["../../src/capture/event.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export * from './event.js';
2
+ export * from './recorder.js';
3
+ export * from './replay.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from './event.js';
2
+ export * from './recorder.js';
3
+ export * from './replay.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capture/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,19 @@
1
+ import type { WorkflowEvent, WorkflowTrace } from './event.js';
2
+ import type { ReplayController } from './replay.js';
3
+ export declare class TraceRecorder {
4
+ events: WorkflowEvent[];
5
+ private _counter;
6
+ private _sideEffectCounter;
7
+ record(event: WorkflowEvent): void;
8
+ nextId(): number;
9
+ /** Separate counter for Date.now / Math.random — never shares IDs with main events. */
10
+ nextSideEffectId(): number;
11
+ toTrace(traceId?: string): WorkflowTrace;
12
+ }
13
+ export interface CaptureContext {
14
+ recorder: TraceRecorder;
15
+ replay: ReplayController;
16
+ }
17
+ export declare function setCaptureContext(ctx: CaptureContext | undefined): void;
18
+ export declare function getCaptureContext(): CaptureContext | undefined;
19
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/capture/recorder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,qBAAa,aAAa;IACxB,MAAM,EAAE,aAAa,EAAE,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,kBAAkB,CAAI;IAE9B,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAIlC,MAAM,IAAI,MAAM;IAIhB,uFAAuF;IACvF,gBAAgB,IAAI,MAAM;IAI1B,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa;CAMzC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,aAAa,CAAA;IACvB,MAAM,EAAE,gBAAgB,CAAA;CACzB;AASD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAEvE;AAED,wBAAgB,iBAAiB,IAAI,cAAc,GAAG,SAAS,CAE9D"}
@@ -0,0 +1,36 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { randomUUID } from 'node:crypto';
3
+ export class TraceRecorder {
4
+ events = [];
5
+ _counter = 0;
6
+ _sideEffectCounter = 0;
7
+ record(event) {
8
+ this.events.push(event);
9
+ }
10
+ nextId() {
11
+ return ++this._counter;
12
+ }
13
+ /** Separate counter for Date.now / Math.random — never shares IDs with main events. */
14
+ nextSideEffectId() {
15
+ return ++this._sideEffectCounter;
16
+ }
17
+ toTrace(traceId) {
18
+ return {
19
+ traceId: traceId ?? randomUUID(),
20
+ events: [...this.events],
21
+ };
22
+ }
23
+ }
24
+ const g = globalThis;
25
+ const CAPTURE_ALS_KEY = '__elasticdash_capture_als__';
26
+ const captureAls = g[CAPTURE_ALS_KEY] ??
27
+ new AsyncLocalStorage();
28
+ if (!g[CAPTURE_ALS_KEY])
29
+ g[CAPTURE_ALS_KEY] = captureAls;
30
+ export function setCaptureContext(ctx) {
31
+ captureAls.enterWith(ctx);
32
+ }
33
+ export function getCaptureContext() {
34
+ return captureAls.getStore();
35
+ }
36
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/capture/recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,MAAM,OAAO,aAAa;IACxB,MAAM,GAAoB,EAAE,CAAA;IACpB,QAAQ,GAAG,CAAC,CAAA;IACZ,kBAAkB,GAAG,CAAC,CAAA;IAE9B,MAAM,CAAC,KAAoB;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAA;IACxB,CAAC;IAED,uFAAuF;IACvF,gBAAgB;QACd,OAAO,EAAE,IAAI,CAAC,kBAAkB,CAAA;IAClC,CAAC;IAED,OAAO,CAAC,OAAgB;QACtB,OAAO;YACL,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE;YAChC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;SACzB,CAAA;IACH,CAAC;CACF;AAOD,MAAM,CAAC,GAAG,UAAqC,CAAA;AAC/C,MAAM,eAAe,GAAG,6BAA6B,CAAA;AACrD,MAAM,UAAU,GACb,CAAC,CAAC,eAAe,CAAmD;IACrE,IAAI,iBAAiB,EAA8B,CAAA;AACrD,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC;IAAE,CAAC,CAAC,eAAe,CAAC,GAAG,UAAU,CAAA;AAExD,MAAM,UAAU,iBAAiB,CAAC,GAA+B;IAC/D,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,UAAU,CAAC,QAAQ,EAAE,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { WorkflowEvent } from './event.js';
2
+ export declare class ReplayController {
3
+ replayMode: boolean;
4
+ checkpoint: number;
5
+ history: WorkflowEvent[];
6
+ private historyMap;
7
+ /** Side effects keyed by their assigned sideEffectId, independent of main event IDs */
8
+ private sideEffectMap;
9
+ constructor(replayMode: boolean, checkpoint: number, history: WorkflowEvent[]);
10
+ shouldReplay(eventId: number): boolean;
11
+ getRecordedEvent(eventId: number): WorkflowEvent | undefined;
12
+ getRecordedResult(eventId: number): unknown;
13
+ /** Returns true if the side effect with this sideEffectId has a recorded value to replay */
14
+ shouldReplaySideEffect(n: number): boolean;
15
+ getSideEffectResult(n: number): unknown;
16
+ getRecordedSideEffectEvent(n: number): WorkflowEvent | undefined;
17
+ shouldReplaySideEffectOfType(n: number, expectedName: string): boolean;
18
+ getSideEffectResultOfType(n: number, expectedName: string): unknown;
19
+ }
20
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/capture/replay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,qBAAa,gBAAgB;IAMlB,UAAU,EAAE,OAAO;IACnB,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,aAAa,EAAE;IAPjC,OAAO,CAAC,UAAU,CAA4B;IAC9C,uFAAuF;IACvF,OAAO,CAAC,aAAa,CAA4B;gBAGxC,UAAU,EAAE,OAAO,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EAAE;IAQjC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAItC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI5D,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI3C,4FAA4F;IAC5F,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAI1C,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO;IAIvC,0BAA0B,CAAC,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIhE,4BAA4B,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAMtE,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;CAKpE"}
@@ -0,0 +1,47 @@
1
+ export class ReplayController {
2
+ replayMode;
3
+ checkpoint;
4
+ history;
5
+ historyMap;
6
+ /** Side effects keyed by their assigned sideEffectId, independent of main event IDs */
7
+ sideEffectMap;
8
+ constructor(replayMode, checkpoint, history) {
9
+ this.replayMode = replayMode;
10
+ this.checkpoint = checkpoint;
11
+ this.history = history;
12
+ this.historyMap = new Map(history.map(e => [e.id, e]));
13
+ this.sideEffectMap = new Map(history.filter(e => e.type === 'side_effect').map(e => [e.id, e]));
14
+ }
15
+ shouldReplay(eventId) {
16
+ return this.replayMode && eventId <= this.checkpoint;
17
+ }
18
+ getRecordedEvent(eventId) {
19
+ return this.historyMap.get(eventId);
20
+ }
21
+ getRecordedResult(eventId) {
22
+ return this.historyMap.get(eventId)?.output;
23
+ }
24
+ /** Returns true if the side effect with this sideEffectId has a recorded value to replay */
25
+ shouldReplaySideEffect(n) {
26
+ return this.replayMode && this.sideEffectMap.has(n);
27
+ }
28
+ getSideEffectResult(n) {
29
+ return this.sideEffectMap.get(n)?.output;
30
+ }
31
+ getRecordedSideEffectEvent(n) {
32
+ return this.sideEffectMap.get(n);
33
+ }
34
+ shouldReplaySideEffectOfType(n, expectedName) {
35
+ if (!this.replayMode)
36
+ return false;
37
+ const event = this.sideEffectMap.get(n);
38
+ return !!event && event.type === 'side_effect' && event.name === expectedName;
39
+ }
40
+ getSideEffectResultOfType(n, expectedName) {
41
+ const event = this.sideEffectMap.get(n);
42
+ if (!event || event.type !== 'side_effect' || event.name !== expectedName)
43
+ return undefined;
44
+ return event.output;
45
+ }
46
+ }
47
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/capture/replay.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,gBAAgB;IAMlB;IACA;IACA;IAPD,UAAU,CAA4B;IAC9C,uFAAuF;IAC/E,aAAa,CAA4B;IAEjD,YACS,UAAmB,EACnB,UAAkB,EAClB,OAAwB;QAFxB,eAAU,GAAV,UAAU,CAAS;QACnB,eAAU,GAAV,UAAU,CAAQ;QAClB,YAAO,GAAP,OAAO,CAAiB;QAE/B,IAAI,CAAC,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACtD,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,CAC1B,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAClE,CAAA;IACH,CAAC;IAED,YAAY,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,UAAU,IAAI,OAAO,IAAI,IAAI,CAAC,UAAU,CAAA;IACtD,CAAC;IAED,gBAAgB,CAAC,OAAe;QAC9B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACrC,CAAC;IAED,iBAAiB,CAAC,OAAe;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IAC7C,CAAC;IAED,4FAA4F;IAC5F,sBAAsB,CAAC,CAAS;QAC9B,OAAO,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,mBAAmB,CAAC,CAAS;QAC3B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAA;IAC1C,CAAC;IAED,0BAA0B,CAAC,CAAS;QAClC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,4BAA4B,CAAC,CAAS,EAAE,YAAoB;QAC1D,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACvC,OAAO,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAA;IAC/E,CAAC;IAED,yBAAyB,CAAC,CAAS,EAAE,YAAoB;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACvC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO,SAAS,CAAA;QAC3F,OAAO,KAAK,CAAC,MAAM,CAAA;IACrB,CAAC;CACF"}
package/dist/cli.js CHANGED
File without changes
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Agent state serialization, deserialization, and utility functions.
3
+ *
4
+ * Enables capturing agent plan state during execution and resuming
5
+ * agents from any task in the plan without re-executing completed steps.
6
+ */
7
+ import type { AgentPlan, AgentState, AgentTask } from '../types/agent.js';
8
+ import type { WorkflowEvent } from '../capture/event.js';
9
+ /**
10
+ * Serializes an agent plan and its captured trace events into an AgentState
11
+ * that can be persisted and later used for resumption.
12
+ *
13
+ * The resumeFromTaskIndex is automatically determined as the index of the
14
+ * first non-completed task. If all tasks are completed, it equals tasks.length.
15
+ */
16
+ export declare function serializeAgentState(plan: AgentPlan, trace: WorkflowEvent[]): AgentState;
17
+ /**
18
+ * Validates and hydrates an AgentState from a parsed JSON object.
19
+ * Throws if the state is invalid or cannot be safely used for resumption.
20
+ */
21
+ export declare function deserializeAgentState(raw: unknown): AgentState;
22
+ /**
23
+ * Extracts all completed task outputs into a flat map keyed by task ID.
24
+ * Used for resolving placeholder references in subsequent task inputs.
25
+ */
26
+ export declare function extractTaskOutputs(plan: AgentPlan): Record<string, unknown>;
27
+ /**
28
+ * Resolves placeholder references in a task input.
29
+ *
30
+ * Placeholders use the form: `{ $ref: "task-N.output.fieldName" }`
31
+ * where "task-N" is a task ID and "fieldName" is a dot-separated path
32
+ * into that task's output.
33
+ *
34
+ * Example:
35
+ * previousOutputs = { "task-1": { userId: "abc" } }
36
+ * input = { $ref: "task-1.output.userId" }
37
+ * → returns "abc"
38
+ *
39
+ * Works recursively on nested objects and arrays.
40
+ */
41
+ export declare function resolveTaskInput(input: unknown, previousOutputs: Record<string, unknown>): unknown;
42
+ /**
43
+ * Clones a task and marks it as completed with the given output.
44
+ * Used internally when skipping already-completed tasks during resumption.
45
+ */
46
+ export declare function markTaskCompleted(task: AgentTask, output: unknown): AgentTask;
47
+ //# sourceMappingURL=agent-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-state.d.ts","sourceRoot":"","sources":["../../src/core/agent-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,UAAU,CASvF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAuC9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ3E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvC,OAAO,CAwBT;AAsBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,CAO7E"}