{"version":3,"file":"ActionDevtoolsCore-DJgiYs7a.mjs","names":[],"sources":["../src/devtools/core/ActionDevtoolsCore.ts"],"sourcesContent":["import {\n  ERunningActionFinishedType,\n  ERunningActionUpdateType,\n} from \"../../ActionDefinition/Action/RunningAction.types\";\nimport type {\n  IDevtoolsActionEntry,\n  IDevtoolsActionMeta,\n  IDevtoolsObservableDomain,\n  IDevtoolsRouteItem,\n  TDevtoolsListener,\n} from \"./ActionDevtools.types\";\n\nexport interface IActionDevtoolsCoreOptions {\n  /** Max root entries to retain. Older entries (and their children) are evicted. */\n  maxEntries?: number;\n}\n\nfunction serializeErrorForDisplay(error: unknown): unknown {\n  if (\n    error != null &&\n    typeof error === \"object\" &&\n    (error as any).name === \"NiceError\" &&\n    typeof (error as any).toJsonObject === \"function\"\n  ) {\n    return (error as any).toJsonObject();\n  }\n  return error;\n}\n\nfunction extractRouting(context: any): IDevtoolsRouteItem[] {\n  return (context?.routing ?? []).map((item: any): IDevtoolsRouteItem => {\n    const handler = item.handler;\n    const isPeer = handler?.type === \"peer\";\n    return {\n      runtime: {\n        envId: item.runtime?.envId ?? \"unknown\",\n        perId: item.runtime?.perId,\n        insId: item.runtime?.insId,\n      },\n      handlerType: isPeer ? \"peer\" : \"local\",\n      handlerClient:\n        isPeer && handler.client != null\n          ? {\n              envId: handler.client.envId ?? \"unknown\",\n              perId: handler.client.perId,\n              insId: handler.client.insId,\n            }\n          : undefined,\n      transport: isPeer ? (handler.transInfo?.carrierLabel ?? handler.transShape) : undefined,\n      transportSummary: isPeer ? handler.transInfo?.summary : undefined,\n      transportUrl: isPeer ? handler.transInfo?.url : undefined,\n      time: item.time,\n    };\n  });\n}\n\nfunction extractReliability(runningAction: any): IDevtoolsActionEntry[\"reliability\"] {\n  const r = runningAction?.reliability;\n  if (r == null) return undefined;\n  return { tier: r.tier, seq: r.seq, streamKey: r.streamKey, acked: r.acked };\n}\n\nfunction extractMeta(context: any): IDevtoolsActionMeta {\n  return {\n    timeCreated: context?.timeCreated ?? Date.now(),\n    originClient: {\n      envId: context?.originClient?.envId ?? \"unknown\",\n      perId: context?.originClient?.perId,\n      insId: context?.originClient?.insId,\n    },\n    routing: extractRouting(context),\n  };\n}\n\nexport class ActionDevtoolsCore {\n  private _entries: IDevtoolsActionEntry[] = [];\n  private _listeners: Set<TDevtoolsListener> = new Set();\n  private readonly _maxEntries: number;\n  private _paused = false;\n\n  constructor(options: IActionDevtoolsCoreOptions = {}) {\n    this._maxEntries = options.maxEntries ?? 500;\n  }\n\n  get paused(): boolean {\n    return this._paused;\n  }\n\n  /**\n   * While paused, no NEW actions are recorded; actions already on the timeline\n   * still settle (progress / reliability / finish updates apply), so nothing is\n   * left stuck \"running\" forever. Mirrors `StateDevtoolsCore.setPaused`.\n   */\n  setPaused(paused: boolean): void {\n    if (this._paused === paused) return;\n    this._paused = paused;\n    this._notify();\n  }\n\n  togglePaused(): void {\n    this.setPaused(!this._paused);\n  }\n\n  attachToDomain(domain: IDevtoolsObservableDomain): () => void {\n    return domain.addActionListener((update) => {\n      const { runningAction, type, time } = update;\n\n      if (type === ERunningActionUpdateType.started) {\n        if (this._paused) return;\n        const entry: IDevtoolsActionEntry = {\n          cuid: runningAction.cuid,\n          actionId: runningAction.id,\n          domain: runningAction.domain,\n          allDomains: [...runningAction.allDomains],\n          status: \"running\",\n          startTime: time,\n          input: runningAction.state?.request?.input,\n          inputHash: runningAction.state?.request?.inputHash,\n          progressUpdates: [],\n          meta: extractMeta(runningAction.context),\n          parentCuid: runningAction.parentCuid,\n          callSite: runningAction.callSite,\n          reliability: extractReliability(runningAction),\n        };\n        this._entries = [entry, ...this._entries];\n        // Bound retention: entries are newest-first, so the oldest fall off the tail.\n        // Grouping already renders any child whose parent is gone as its own root, so\n        // dropping an old parent never breaks the surviving children's display.\n        if (this._entries.length > this._maxEntries) {\n          this._entries.length = this._maxEntries;\n        }\n        this._notify();\n      } else if (type === ERunningActionUpdateType.progress) {\n        this._updateEntry(runningAction.cuid, (e) => ({\n          ...e,\n          progressUpdates: [...e.progressUpdates, update.progress],\n        }));\n      } else if (type === ERunningActionUpdateType.reliability) {\n        // Sender-side delivery facts changed (e.g. the peer's ack landed). Fires *after* `finished` for\n        // a reply-less reliable action — this is what finally flips its chip to `✓` (the old E2\n        // staleness: the entry snapshot taken at `finished` predates the ack).\n        this._updateEntry(runningAction.cuid, (e) => ({\n          ...e,\n          reliability: extractReliability(runningAction) ?? e.reliability,\n        }));\n      } else if (type === ERunningActionUpdateType.finished) {\n        this._updateEntry(runningAction.cuid, (e) => {\n          // On success the result payload's context may carry the full routing from the handling\n          // runtime (including backend hops) — richer than the local context, which only has this\n          // side's outgoing hops. Prefer it *only when it's actually richer*: the optimized binary\n          // WS session strips routing from the wire and reconstructs an empty array, so an empty\n          // response routing must never clobber the real local hops (otherwise the entry renders as\n          // \"call\"/\"local\" instead of \"→ ws → backend\").\n          const responseRouting = extractRouting((update as any).response?.context);\n          const localRouting = extractRouting(runningAction.context);\n          const routing =\n            responseRouting.length >= localRouting.length ? responseRouting : localRouting;\n          const base: IDevtoolsActionEntry = {\n            ...e,\n            endTime: time,\n            meta: { ...e.meta, routing },\n            // Reliability is stamped after the constructor's `started` event, so re-read it here (the entry\n            // created at `started` may not have had it yet).\n            reliability: extractReliability(runningAction) ?? e.reliability,\n          };\n          const finishType: string = update.finishType;\n\n          if (finishType === ERunningActionFinishedType.success) {\n            const result = update.response?.result;\n            const outputHash: string | undefined = update.response?.outputHash;\n            if (result != null && !result.ok) {\n              const rawError = result.error;\n              const errorStack = rawError instanceof Error ? rawError.stack : undefined;\n              return {\n                ...base,\n                status: \"action-error\",\n                outputHash,\n                error: serializeErrorForDisplay(rawError),\n                expected: result.expected,\n                errorStack,\n              };\n            }\n            return { ...base, status: \"success\", output: result?.output, outputHash };\n          }\n          if (finishType === ERunningActionFinishedType.failed) {\n            const rawError = (update as any).error;\n            const errorStack = rawError instanceof Error ? rawError.stack : undefined;\n            return {\n              ...base,\n              status: \"failed\",\n              error: serializeErrorForDisplay(rawError),\n              errorStack,\n            };\n          }\n          const abortReason = update.reason;\n          const errorStack = abortReason instanceof Error ? abortReason.stack : undefined;\n          return {\n            ...base,\n            status: \"aborted\",\n            abortReason: serializeErrorForDisplay(abortReason),\n            errorStack,\n          };\n        });\n      }\n    });\n  }\n\n  getEntries(): readonly IDevtoolsActionEntry[] {\n    return this._entries;\n  }\n\n  subscribe(listener: TDevtoolsListener): () => void {\n    this._listeners.add(listener);\n    listener(this._entries);\n    return () => {\n      this._listeners.delete(listener);\n    };\n  }\n\n  clear(): void {\n    this._entries = [];\n    this._notify();\n  }\n\n  private _updateEntry(\n    cuid: string,\n    updater: (entry: IDevtoolsActionEntry) => IDevtoolsActionEntry,\n  ): void {\n    this._entries = this._entries.map((e) => (e.cuid === cuid ? updater(e) : e));\n    this._notify();\n  }\n\n  private _notify(): void {\n    const snapshot = this._entries;\n    for (const listener of this._listeners) listener(snapshot);\n  }\n}\n"],"mappings":"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"}