{"version":3,"file":"trace-events.cjs","names":["config: {\n  debugLabel?: string;\n  getInitialValue: () => Metadata;\n  onBeforeHandler: (\n    handler: Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>,\n    handlerContext: HandlerContext,\n    metadata: Metadata,\n  ) => Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>;\n  onAfterHandler: (metadata: Metadata) => Metadata;\n}","handler: Fn","noop: (...args: any[]) => void","noop","eventData: WorkflowEventData<any>","workflow: WorkflowLike","options?: WithTraceEventsOptions","stream: WorkflowStream<T>","eventData","accept: AcceptEvents","handler: Fn","handlerMiddleware: Handler<\n          WorkflowEvent<any>[],\n          WorkflowEventData<any> | void\n        >","tracingContext: TracingContext","context","next","result"],"sources":["../src/middleware/trace-events/create-handler-decorator.ts","../src/middleware/trace-events/run-once.ts","../src/middleware/trace-events.ts"],"sourcesContent":["import type {\n  Handler,\n  WorkflowEvent,\n  WorkflowEventData,\n} from \"@llamaindex/workflow-core\";\nimport type { HandlerContext } from \"../../core/context\";\n\nconst namespace = \"decorator\" as const;\n\nlet counter = 0;\n\nexport const decoratorRegistry = new Map<\n  string,\n  {\n    handlers: WeakSet<\n      Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>\n    >;\n    debugLabel: string;\n    getInitialValue: () => any;\n    onBeforeHandler: (\n      handler: Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>,\n      handlerContext: Readonly<HandlerContext>,\n      metadata: any,\n    ) => Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>;\n    onAfterHandler: (metadata: any) => any;\n  }\n>();\n\n/**\n * Creates a handler decorator that can instrument workflow handlers with custom behavior.\n *\n * Handler decorators allow you to wrap workflow handlers with additional functionality\n * such as logging, timing, error handling, or state management. They provide hooks\n * that run before and after handler execution.\n *\n * @typeParam Metadata - The type of metadata to track for each handler\n *\n * @param config - Configuration object for the decorator\n * @param config.debugLabel - Optional debug label for identifying the decorator\n * @param config.getInitialValue - Function that returns initial metadata value\n * @param config.onBeforeHandler - Hook that runs before handler execution\n * @param config.onAfterHandler - Hook that runs after handler execution\n * @returns A decorator function that can be used as a trace plugin\n *\n * @example\n * ```typescript\n * import { createWorkflow, workflowEvent } from \"@llamaindex/workflow-core\";\n * import {\n *   withTraceEvents,\n *   createHandlerDecorator\n * } from \"@llamaindex/workflow-core/middleware/trace-events\";\n *\n * // Create a timing decorator\n * type TimingMetadata = { startTime: number | null };\n * const timingDecorator = createHandlerDecorator<TimingMetadata>({\n *   debugLabel: \"timing\",\n *   getInitialValue: () => ({ startTime: null }),\n *   onBeforeHandler: (handler, context, metadata) => async (...args) => {\n *     metadata.startTime = Date.now();\n *     try {\n *       return await handler(...args);\n *     } finally {\n *       const duration = Date.now() - (metadata.startTime ?? 0);\n *       console.log(`Handler executed in ${duration}ms`);\n *     }\n *   },\n *   onAfterHandler: () => ({ startTime: null })\n * });\n *\n * // Use the decorator\n * const workflow = withTraceEvents(createWorkflow(), {\n *   plugins: [timingDecorator]\n * });\n * ```\n *\n * @category Middleware\n * @public\n */\nexport function createHandlerDecorator<Metadata>(config: {\n  debugLabel?: string;\n  getInitialValue: () => Metadata;\n  onBeforeHandler: (\n    handler: Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>,\n    handlerContext: HandlerContext,\n    metadata: Metadata,\n  ) => Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>;\n  onAfterHandler: (metadata: Metadata) => Metadata;\n}) {\n  const uid = `${namespace}:${counter++}`;\n  decoratorRegistry.set(uid, {\n    handlers: new WeakSet(),\n    debugLabel: config.debugLabel ?? uid,\n    getInitialValue: config.getInitialValue,\n    onAfterHandler: config.onAfterHandler,\n    onBeforeHandler: config.onBeforeHandler,\n  });\n  return <\n    const AcceptEvents extends WorkflowEvent<any>[],\n    Result extends ReturnType<WorkflowEvent<any>[\"with\"]> | void,\n    Fn extends Handler<AcceptEvents, Result>,\n  >(\n    handler: Fn,\n  ) => {\n    decoratorRegistry\n      .get(uid)!\n      .handlers.add(\n        handler as Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>,\n      );\n    return handler;\n  };\n}\n","import { createHandlerDecorator } from \"./create-handler-decorator\";\n\nconst noop: (...args: any[]) => void = function noop() {};\n\nexport const runOnce = createHandlerDecorator({\n  debugLabel: \"onceHook\",\n  getInitialValue: () => false,\n  onBeforeHandler: (handler, _, tracked) => (tracked ? noop : handler),\n  onAfterHandler: () => true,\n});\n","import {\n  getContext,\n  type Handler,\n  type WorkflowContext,\n  type WorkflowEvent,\n  type WorkflowEventData,\n  type WorkflowStream,\n} from \"@llamaindex/workflow-core\";\nimport type { HandlerContext } from \"../core/context\";\nimport { isPromiseLike } from \"../core/utils\";\nimport {\n  createHandlerDecorator,\n  decoratorRegistry,\n} from \"./trace-events/create-handler-decorator\";\nimport { runOnce } from \"./trace-events/run-once\";\n\ntype TracingContext = Record<string, unknown>;\n\nconst tracingWeakMap = new WeakMap<\n  WorkflowContext,\n  WeakMap<\n    WorkflowEvent<any>[],\n    WeakMap<\n      Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>,\n      TracingContext\n    >\n  >\n>();\n\nconst contextTraceWeakMap = new WeakMap<HandlerContext, WorkflowContext>();\n\nconst eventToHandlerContextWeakMap = new WeakMap<\n  WorkflowEventData<any>,\n  HandlerContext\n>();\n\nexport function getEventOrigins(\n  eventData: WorkflowEventData<any>,\n  context = getContext(),\n): [WorkflowEventData<any>, ...WorkflowEventData<any>[]] {\n  let currentContext = eventToHandlerContextWeakMap.get(eventData);\n  if (!currentContext) {\n    throw new Error(\n      \"Event context not found, this should not happen. Please report this issue with a reproducible example.\",\n    );\n  }\n  do {\n    const workflowContext = contextTraceWeakMap.get(currentContext.prev)!;\n    if (workflowContext === context) {\n      return currentContext.inputs as [\n        WorkflowEventData<any>,\n        ...WorkflowEventData<any>[],\n      ];\n    }\n\n    currentContext = currentContext.prev;\n  } while (currentContext.prev);\n  throw new Error(\n    \"Event context not found, this should not happen. Please report this issue with a reproducible example.\",\n  );\n}\n\nexport type HandlerRef<\n  AcceptEvents extends WorkflowEvent<any>[],\n  Result extends ReturnType<WorkflowEvent<any>[\"with\"]> | void,\n  Fn extends Handler<AcceptEvents, Result>,\n> = {\n  get handler(): Fn;\n};\n\nexport type TracePlugin<\n  AcceptEvents extends WorkflowEvent<any>[] = WorkflowEvent<any>[],\n> = (\n  handler: Handler<AcceptEvents, WorkflowEventData<any> | void>,\n) => Handler<AcceptEvents, WorkflowEventData<any> | void>;\n\nexport type WithTraceEventsOptions = {\n  /**\n   * Config decorators to apply to all handlers\n   */\n  plugins?: TracePlugin[];\n};\n\n/**\n * Adds tracing capabilities to a workflow by wrapping handlers with trace plugins.\n *\n * This middleware enables comprehensive tracing and monitoring of workflow execution,\n * allowing you to attach plugins that can observe, measure, and instrument handler execution.\n *\n * @typeParam WorkflowLike - The workflow type to enhance with tracing\n *\n * @param workflow - The workflow instance to add tracing to\n * @param options - Configuration object containing trace plugins\n * @returns The workflow enhanced with tracing capabilities\n *\n * @example\n * ```typescript\n * import { createWorkflow, workflowEvent } from \"@llamaindex/workflow-core\";\n * import { withTraceEvents } from \"@llamaindex/workflow-core/middleware/trace-events\";\n *\n * // Define events\n * const startEvent = workflowEvent();\n * const processEvent = workflowEvent<string>();\n *\n * // Create a simple timing plugin\n * const timingPlugin = (handler) => async (...args) => {\n *   const start = Date.now();\n *   try {\n *     return await handler(...args);\n *   } finally {\n *     console.log(`Handler took ${Date.now() - start}ms`);\n *   }\n * };\n *\n * // Apply tracing to workflow\n * const workflow = withTraceEvents(createWorkflow(), {\n *   plugins: [timingPlugin]\n * });\n *\n * workflow.handle([startEvent], (context) => {\n *   context.sendEvent(processEvent.with(\"data\"));\n * });\n * ```\n *\n * @category Middleware\n * @public\n */\nexport function withTraceEvents<\n  WorkflowLike extends {\n    handle<\n      const AcceptEvents extends WorkflowEvent<any>[],\n      Result extends ReturnType<WorkflowEvent<any>[\"with\"]> | void,\n    >(accept: AcceptEvents, handler: Handler<AcceptEvents, Result>): void;\n    createContext(): WorkflowContext;\n  },\n>(\n  workflow: WorkflowLike,\n  options?: WithTraceEventsOptions,\n): Omit<WorkflowLike, \"handle\"> & {\n  handle<\n    const AcceptEvents extends WorkflowEvent<any>[],\n    Result extends ReturnType<WorkflowEvent<any>[\"with\"]> | void,\n    Fn extends Handler<AcceptEvents, Result>,\n  >(accept: AcceptEvents, handler: Fn): HandlerRef<AcceptEvents, Result, Fn>;\n  substream<T extends WorkflowEventData<any>>(\n    eventData: WorkflowEventData<any>,\n    stream: WorkflowStream<T>,\n  ): WorkflowStream<T>;\n} {\n  return {\n    ...workflow,\n    substream: <T extends WorkflowEventData<any>>(\n      eventData: WorkflowEventData<any>,\n      stream: WorkflowStream<T>,\n    ): WorkflowStream<T> => {\n      const rootContext = eventToHandlerContextWeakMap.get(eventData);\n      return stream.pipeThrough(\n        new TransformStream({\n          transform(eventData, controller) {\n            let isInSameContext = false;\n            let currentEventContext =\n              eventToHandlerContextWeakMap.get(eventData);\n            while (currentEventContext) {\n              if (currentEventContext === rootContext) {\n                isInSameContext = true;\n                break;\n              }\n              currentEventContext = currentEventContext.prev;\n            }\n            if (isInSameContext) {\n              controller.enqueue(eventData);\n            }\n          },\n        }),\n      );\n    },\n    handle: <\n      const AcceptEvents extends WorkflowEvent<any>[],\n      Result extends ReturnType<WorkflowEvent<any>[\"with\"]> | void,\n      Fn extends Handler<AcceptEvents, Result>,\n    >(\n      accept: AcceptEvents,\n      handler: Fn,\n    ): HandlerRef<AcceptEvents, Result, Fn> => {\n      let handlerFn = handler as Handler<WorkflowEvent<any>[], Result>;\n\n      if (options?.plugins?.length) {\n        // apply plugins to handler one by one\n        options.plugins.forEach((plugin) => {\n          handlerFn = plugin(handlerFn) as Handler<\n            WorkflowEvent<any>[],\n            Result\n          >;\n        });\n      }\n\n      workflow.handle(accept, handlerFn);\n      return {\n        get handler(): Fn {\n          return handlerFn as Fn;\n        },\n      };\n    },\n    createContext(): WorkflowContext {\n      const context = workflow.createContext();\n      tracingWeakMap.set(context, new WeakMap());\n      context.__internal__call_send_event.subscribe((event, handlerContext) => {\n        eventToHandlerContextWeakMap.set(event, handlerContext);\n      });\n      context.__internal__call_context.subscribe((handlerContext, next) => {\n        handlerContext.inputs.forEach((input) => {\n          if (!eventToHandlerContextWeakMap.has(input)) {\n            console.warn(\"unregistered event detected\");\n          }\n          eventToHandlerContextWeakMap.set(input, handlerContext);\n        });\n        const inputEvents = handlerContext.inputEvents;\n        const handlersWeakMap = tracingWeakMap.get(context)!;\n        if (!handlersWeakMap.has(inputEvents)) {\n          handlersWeakMap.set(inputEvents, new WeakMap());\n        }\n        const handlerWeakMap = handlersWeakMap.get(inputEvents)!;\n\n        const originalHandler = handlerContext.handler;\n        const finalHandler = originalHandler;\n        // biome-ignore lint/style/useConst: .\n        let handlerMiddleware: Handler<\n          WorkflowEvent<any>[],\n          WorkflowEventData<any> | void\n        >;\n        if (!handlerWeakMap) {\n          throw new Error(\n            \"Handler context is not defined, this should not happen. Please report this issue with a reproducible example.\",\n          );\n        }\n        const tracingContext: TracingContext =\n          handlerWeakMap.get(originalHandler) ?? {};\n        if (!handlerWeakMap.has(originalHandler)) {\n          handlerWeakMap.set(originalHandler, tracingContext);\n        }\n\n        const onAfterHandlers = [] as (() => void)[];\n        const onBeforeHandlers = [] as ((\n          nextHandler: Handler<\n            WorkflowEvent<any>[],\n            WorkflowEventData<any> | void\n          >,\n        ) => Handler<WorkflowEvent<any>[], WorkflowEventData<any> | void>)[];\n        handlerMiddleware = (...args) => {\n          const context = getContext();\n          contextTraceWeakMap.set(handlerContext, context);\n          const result = onBeforeHandlers.reduce((next, cb) => {\n            return cb(next);\n          }, finalHandler)(...args);\n          if (isPromiseLike(result)) {\n            return result.then((result) => {\n              onAfterHandlers.forEach((cb) => {\n                cb();\n              });\n              return result;\n            });\n          } else {\n            onAfterHandlers.forEach((cb) => {\n              cb();\n            });\n            return result;\n          }\n        };\n        [...decoratorRegistry]\n          .filter(([, { handlers }]) =>\n            handlers.has(\n              handlerContext.handler as Handler<\n                WorkflowEvent<any>[],\n                WorkflowEventData<any> | void\n              >,\n            ),\n          )\n          .forEach(\n            ([name, { getInitialValue, onAfterHandler, onBeforeHandler }]) => {\n              if (!tracingContext[name]) {\n                tracingContext[name] = getInitialValue();\n              }\n              onBeforeHandlers.push((next) =>\n                onBeforeHandler(next, handlerContext, tracingContext[name]),\n              );\n              onAfterHandlers.push(() => {\n                tracingContext[name] = onAfterHandler(tracingContext[name]);\n              });\n            },\n          );\n        next({\n          ...handlerContext,\n          handler: handlerMiddleware,\n        });\n      });\n      return context;\n    },\n  };\n}\n\nexport { createHandlerDecorator, runOnce };\n"],"mappings":"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"}