@workflow/web-shared 5.0.0-beta.4 → 5.0.0-beta.5

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 (29) hide show
  1. package/dist/components/new-trace-viewer/components/event-list.js +2 -2
  2. package/dist/components/new-trace-viewer/components/event-list.js.map +1 -1
  3. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +1 -1
  4. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +1 -1
  5. package/dist/components/new-trace-viewer/trace-viewer.js +10 -4
  6. package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -1
  7. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  8. package/dist/components/sidebar/attribute-panel.js +6 -0
  9. package/dist/components/sidebar/attribute-panel.js.map +1 -1
  10. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  11. package/dist/components/ui/error-stack-block.js +24 -2
  12. package/dist/components/ui/error-stack-block.js.map +1 -1
  13. package/dist/components/workflow-trace-view.js +1 -1
  14. package/dist/components/workflow-trace-view.js.map +1 -1
  15. package/dist/components/workflow-traces/trace-span-construction.js +1 -1
  16. package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
  17. package/dist/lib/hydration.d.ts +6 -0
  18. package/dist/lib/hydration.d.ts.map +1 -1
  19. package/dist/lib/hydration.js +124 -1
  20. package/dist/lib/hydration.js.map +1 -1
  21. package/package.json +5 -4
  22. package/src/components/new-trace-viewer/components/event-list.tsx +9 -9
  23. package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +6 -6
  24. package/src/components/new-trace-viewer/trace-viewer.tsx +54 -46
  25. package/src/components/sidebar/attribute-panel.tsx +5 -0
  26. package/src/components/ui/error-stack-block.tsx +32 -4
  27. package/src/components/workflow-trace-view.tsx +1 -1
  28. package/src/components/workflow-traces/trace-span-construction.ts +1 -1
  29. package/src/lib/hydration.ts +132 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hydration.js","sourceRoot":"","sources":["../../src/lib/hydration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Web-specific hydration for o11y display.\n *\n * Browser-safe revivers that use `atob()` for base64 decoding (no Node.js\n * `Buffer` dependency). Produces `ClassInstanceRef` objects and `StreamRef`\n * objects for UI rendering.\n */\n\nimport {\n extractClassName,\n hydrateResourceIO as hydrateResourceIOGeneric,\n isEncryptedData,\n isExpiredStub,\n isRunRef,\n observabilityRevivers,\n type Revivers,\n serializedInstanceToRef,\n} from '@workflow/core/serialization-format';\nimport { EVENT_DATA_REF_FIELDS } from '@workflow/world';\n\n// Re-export types and utilities that consumers need\nexport {\n CLASS_INSTANCE_REF_TYPE,\n ClassInstanceRef,\n ENCRYPTED_PLACEHOLDER,\n extractStreamIds,\n isClassInstanceRef,\n isEncryptedData,\n isRunRef,\n isStreamId,\n isStreamRef,\n type Revivers,\n RUN_REF_TYPE,\n type RunRef,\n STREAM_REF_TYPE,\n type StreamRef,\n serializedInstanceToRef,\n truncateId,\n} from '@workflow/core/serialization-format';\n\n// ---------------------------------------------------------------------------\n// Browser-safe base64 decode\n// ---------------------------------------------------------------------------\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n if (base64 === '' || base64 === '.') {\n return new ArrayBuffer(0);\n }\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// ---------------------------------------------------------------------------\n// Web revivers (browser-safe, no Buffer dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Get the web-specific revivers for hydrating serialized data.\n *\n * Uses `atob()` for base64 decoding (no Node.js Buffer dependency).\n * All types are revived as real instances (Date, Map, Set, URL,\n * URLSearchParams, Headers, Error, etc.).\n */\nexport function getWebRevivers(): Revivers {\n function reviveArrayBuffer(value: string): ArrayBuffer {\n return base64ToArrayBuffer(value);\n }\n\n return {\n // O11y-specific revivers (streams, step functions → display objects).\n // Spread FIRST so web-specific overrides below take precedence.\n ...observabilityRevivers,\n\n // Binary types\n ArrayBuffer: reviveArrayBuffer,\n BigInt: (value: string) => BigInt(value),\n BigInt64Array: (value: string) =>\n new BigInt64Array(reviveArrayBuffer(value)),\n BigUint64Array: (value: string) =>\n new BigUint64Array(reviveArrayBuffer(value)),\n Date: (value) => new Date(value),\n Error: (value) => {\n const error = new Error(value.message);\n error.name = value.name;\n error.stack = value.stack;\n return error;\n },\n Float32Array: (value: string) => new Float32Array(reviveArrayBuffer(value)),\n Float64Array: (value: string) => new Float64Array(reviveArrayBuffer(value)),\n Int8Array: (value: string) => new Int8Array(reviveArrayBuffer(value)),\n Int16Array: (value: string) => new Int16Array(reviveArrayBuffer(value)),\n Int32Array: (value: string) => new Int32Array(reviveArrayBuffer(value)),\n Map: (value) => new Map(value),\n RegExp: (value) => new RegExp(value.source, value.flags),\n Set: (value) => new Set(value),\n Uint8Array: (value: string) => new Uint8Array(reviveArrayBuffer(value)),\n Uint8ClampedArray: (value: string) =>\n new Uint8ClampedArray(reviveArrayBuffer(value)),\n Uint16Array: (value: string) => new Uint16Array(reviveArrayBuffer(value)),\n Uint32Array: (value: string) => new Uint32Array(reviveArrayBuffer(value)),\n\n Headers: (value) => new Headers(value),\n Request: (value) => {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { Request: function () {} }.Request!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, {\n method: value.method,\n url: value.url,\n headers: new Headers(value.headers),\n body: value.body,\n duplex: value.duplex,\n ...(value.responseWritable\n ? { responseWritable: value.responseWritable }\n : {}),\n });\n return obj;\n },\n Response: (value) => {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { Response: function () {} }.Response!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, {\n status: value.status,\n statusText: value.statusText,\n url: value.url,\n headers: new Headers(value.headers),\n body: value.body,\n redirected: value.redirected,\n type: value.type,\n });\n return obj;\n },\n URL: (value) => new URL(value),\n URLSearchParams: (value) => new URLSearchParams(value === '.' ? '' : value),\n\n // Web-specific overrides for class instances.\n // Create objects with a dynamically-named constructor so that\n // react-inspector shows the class name (it reads constructor.name).\n Class: (value) => `<class:${extractClassName(value.classId)}>`,\n Instance: (value) => {\n // Run instances are rendered as clickable RunRef badges\n const runRef = serializedInstanceToRef(value);\n if (isRunRef(runRef)) {\n return runRef;\n }\n const className = extractClassName(value.classId);\n const data = value.data;\n const props =\n data && typeof data === 'object' ? { ...data } : { value: data };\n // Create a constructor with the right name using computed property\n // so react-inspector's `object.constructor.name` shows the class name.\n // Must use `function` (not arrow) because arrow functions have no .prototype.\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [className]: function () {} }[className]!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, props);\n return obj;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Pre-built web revivers (cached for performance)\n// ---------------------------------------------------------------------------\n\nlet cachedRevivers: Revivers | null = null;\n\nfunction getRevivers(): Revivers {\n if (!cachedRevivers) {\n cachedRevivers = getWebRevivers();\n }\n return cachedRevivers;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Hydrate the serialized data fields of a resource for web display.\n *\n * Uses browser-safe revivers (atob for base64, ClassInstanceRef for\n * custom classes, StreamRef for streams). Call this on data received\n * from the server before passing it to UI components.\n */\nexport function hydrateResourceIO<T>(resource: T): T {\n const hydrated = hydrateResourceIOGeneric(\n resource as any,\n getRevivers()\n ) as T;\n return replaceEncryptedAndExpiredWithMarkers(hydrated);\n}\n\n// ---------------------------------------------------------------------------\n// Encrypted data display markers\n// ---------------------------------------------------------------------------\n\nexport const ENCRYPTED_DISPLAY_NAME = 'Encrypted';\n\n/**\n * Create a display-friendly object for encrypted data.\n *\n * Uses the same named-constructor trick as the Instance reviver so that\n * ObjectInspector renders the constructor name (\"🔒 Encrypted\") with no\n * expandable children. The original encrypted bytes are stored in a\n * non-enumerable property for later decryption.\n */\nfunction createEncryptedMarker(data: Uint8Array): object {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [ENCRYPTED_DISPLAY_NAME]: function () {} }[\n ENCRYPTED_DISPLAY_NAME\n ]!;\n const obj = Object.create(ctor.prototype);\n // Store original bytes for decryption, but non-enumerable so\n // ObjectInspector doesn't show them as children\n Object.defineProperty(obj, '__encryptedData', {\n value: data,\n enumerable: false,\n configurable: false,\n });\n return obj;\n}\n\n/** Check if a value is an encrypted display marker */\nexport function isEncryptedMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === ENCRYPTED_DISPLAY_NAME\n );\n}\n\n// ---------------------------------------------------------------------------\n// Expired data display markers\n// ---------------------------------------------------------------------------\n\nexport const EXPIRED_DISPLAY_NAME = 'Expired Data';\n\n/**\n * Create a display-friendly object for expired data.\n *\n * Uses the same named-constructor trick as the encrypted marker so that\n * ObjectInspector renders the constructor name (\"Expired Data\") with no\n * expandable children.\n */\nfunction createExpiredMarker(): object {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [EXPIRED_DISPLAY_NAME]: function () {} }[\n EXPIRED_DISPLAY_NAME\n ]!;\n return Object.create(ctor.prototype);\n}\n\n/** Check if a value is an expired data display marker */\nexport function isExpiredMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === EXPIRED_DISPLAY_NAME\n );\n}\n\n/** Replace a single field value with a display marker if it's encrypted or expired. */\nfunction toDisplayMarker(value: unknown): unknown {\n if (isEncryptedData(value)) return createEncryptedMarker(value as Uint8Array);\n if (isExpiredStub(value)) return createExpiredMarker();\n return value;\n}\n\n/**\n * Post-process hydrated resource data: replace encrypted Uint8Array values\n * and expired stubs with display-friendly marker objects in known data fields.\n */\nfunction replaceEncryptedAndExpiredWithMarkers<T>(resource: T): T {\n if (!resource || typeof resource !== 'object') return resource;\n const r = resource as Record<string, unknown>;\n const result = { ...r };\n\n for (const key of ['input', 'output', 'metadata', 'error']) {\n result[key] = toDisplayMarker(result[key]);\n }\n\n if (result.eventData && typeof result.eventData === 'object') {\n const eventType =\n typeof result.eventType === 'string' ? result.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const ed = { ...(result.eventData as Record<string, unknown>) };\n for (const key of refKeys) {\n if (key in ed) {\n ed[key] = toDisplayMarker(ed[key]);\n }\n }\n result.eventData = ed;\n }\n\n return result as T;\n}\n\n/**\n * Hydrate resource data with decryption support.\n *\n * When a key is provided, encrypted fields are decrypted before hydration.\n * This is the async version used when the user clicks \"Decrypt\" in the web UI.\n *\n * Handles both top-level fields (input, output, metadata) and nested\n * eventData subfields per `EVENT_DATA_REF_FIELDS` from `@workflow/world` for that event type.\n */\nexport async function hydrateResourceIOWithKey<T>(\n resource: T,\n key: Uint8Array\n): Promise<T> {\n const { hydrateDataWithKey } = await import(\n '@workflow/core/serialization-format'\n );\n const { importKey } = await import('@workflow/core/encryption');\n const cryptoKey = await importKey(key);\n const revivers = getRevivers();\n\n /** Extract original encrypted bytes from a marker or raw Uint8Array, then decrypt + hydrate */\n async function decryptField(\n value: unknown,\n rev: Revivers,\n k: Awaited<ReturnType<typeof importKey>>\n ): Promise<unknown> {\n // Already-hydrated: encrypted marker with stored bytes\n if (isEncryptedMarker(value)) {\n const raw = (value as any).__encryptedData as Uint8Array;\n return hydrateDataWithKey(raw, rev, k);\n }\n // Raw encrypted Uint8Array (not yet hydrated)\n if (value instanceof Uint8Array) {\n return hydrateDataWithKey(value, rev, k);\n }\n // Not encrypted — return as-is\n return value;\n }\n\n const r = resource as Record<string, unknown>;\n const result = { ...r };\n\n // Decrypt + hydrate top-level serialized fields (runs, steps, hooks)\n for (const field of ['input', 'output', 'metadata', 'error']) {\n if (field in result) {\n result[field] = await decryptField(result[field], revivers, cryptoKey);\n }\n }\n\n // Decrypt + hydrate eventData subfields (events)\n if (result.eventData && typeof result.eventData === 'object') {\n const eventType =\n typeof result.eventType === 'string' ? result.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const eventData = { ...(result.eventData as Record<string, unknown>) };\n for (const field of refKeys) {\n if (field in eventData) {\n eventData[field] = await decryptField(\n eventData[field],\n revivers,\n cryptoKey\n );\n }\n }\n result.eventData = eventData;\n }\n\n return result as T;\n}\n\n/**\n * Check whether a hydrated resource (event, step, run, etc.) contains any\n * encrypted display markers. Inspects the standard top-level fields\n * (`input`, `output`, `error`, `metadata`) as well as the event-type-specific\n * `eventData` ref fields.\n */\nexport function hasEncryptedFields(resource: unknown): boolean {\n if (!resource || typeof resource !== 'object') return false;\n const r = resource as Record<string, unknown>;\n\n for (const key of ['input', 'output', 'metadata', 'error']) {\n if (isEncryptedMarker(r[key])) return true;\n }\n\n if (r.eventData && typeof r.eventData === 'object') {\n const eventType = typeof r.eventType === 'string' ? r.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const ed = r.eventData as Record<string, unknown>;\n for (const key of refKeys) {\n if (key in ed && isEncryptedMarker(ed[key])) return true;\n }\n }\n\n return false;\n}\n"]}
1
+ {"version":3,"file":"hydration.js","sourceRoot":"","sources":["../../src/lib/hydration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Web-specific hydration for o11y display.\n *\n * Browser-safe revivers that use `atob()` for base64 decoding (no Node.js\n * `Buffer` dependency). Produces `ClassInstanceRef` objects and `StreamRef`\n * objects for UI rendering.\n */\n\nimport {\n extractClassName,\n hydrateResourceIO as hydrateResourceIOGeneric,\n isEncryptedData,\n isExpiredStub,\n isRunRef,\n observabilityRevivers,\n type Revivers,\n serializedInstanceToRef,\n} from '@workflow/core/serialization-format';\nimport { EVENT_DATA_REF_FIELDS } from '@workflow/world';\n\n// Re-export types and utilities that consumers need\nexport {\n CLASS_INSTANCE_REF_TYPE,\n ClassInstanceRef,\n ENCRYPTED_PLACEHOLDER,\n extractStreamIds,\n isClassInstanceRef,\n isEncryptedData,\n isRunRef,\n isStreamId,\n isStreamRef,\n type Revivers,\n RUN_REF_TYPE,\n type RunRef,\n STREAM_REF_TYPE,\n type StreamRef,\n serializedInstanceToRef,\n truncateId,\n} from '@workflow/core/serialization-format';\n\n// ---------------------------------------------------------------------------\n// Browser-safe base64 decode\n// ---------------------------------------------------------------------------\n\nfunction base64ToArrayBuffer(base64: string): ArrayBuffer {\n if (base64 === '' || base64 === '.') {\n return new ArrayBuffer(0);\n }\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n// ---------------------------------------------------------------------------\n// Web revivers (browser-safe, no Buffer dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Build a reviver for one of the built-in `Error` subclasses (e.g.\n * `TypeError`, `RangeError`). The constructor for the named subclass is\n * resolved off `globalThis` at call time so the produced instance has the\n * correct prototype chain in the consumer realm. Falls back to a generic\n * `Error` (with `name` set) if the global isn't available, which keeps the\n * o11y UI rendering even on exotic browsers.\n *\n * `cause` is passed through `ErrorOptions` to the constructor when present,\n * matching `getCommonRevivers` in `@workflow/core` so the resulting `cause`\n * property has the same semantics (non-enumerable, set by the engine) as a\n * freshly thrown Error in the consumer realm. The `'cause' in value` check\n * preserves the distinction between \"no cause\" and \"cause is undefined\".\n */\nfunction makeWebErrorSubclassReviver(\n name:\n | 'EvalError'\n | 'RangeError'\n | 'ReferenceError'\n | 'SyntaxError'\n | 'TypeError'\n | 'URIError'\n) {\n return (value: { message: string; stack?: string; cause?: unknown }) => {\n const opts = 'cause' in value ? { cause: value.cause } : undefined;\n const Ctor = (globalThis as Record<string, any>)[name] as\n | ErrorConstructor\n | undefined;\n let error: Error;\n if (typeof Ctor === 'function') {\n error = new Ctor(value.message, opts);\n } else {\n // Fallback path: no built-in subclass available (exotic env). Construct\n // a plain Error with the right `name` and copy `cause` manually since\n // the base Error constructor is what we actually called.\n error = Object.assign(new Error(value.message, opts), { name });\n }\n if (value.stack !== undefined) error.stack = value.stack;\n return error;\n };\n}\n\n/**\n * Get the web-specific revivers for hydrating serialized data.\n *\n * Uses `atob()` for base64 decoding (no Node.js Buffer dependency).\n * All types are revived as real instances (Date, Map, Set, URL,\n * URLSearchParams, Headers, Error, etc.).\n *\n * NOTE: this set must mirror the keys in `SerializableSpecial` (see\n * `@workflow/core/serialization/types`). Any reducer key added on the\n * serialization side that isn't covered here will cause `devalue.unflatten`\n * to throw `Unknown type X`, which `hydrateResourceIO` swallows and\n * surfaces as a \"Failed to load resource details\" banner in the o11y UI.\n */\nexport function getWebRevivers(): Revivers {\n function reviveArrayBuffer(value: string): ArrayBuffer {\n return base64ToArrayBuffer(value);\n }\n\n return {\n // O11y-specific revivers (streams, step functions → display objects).\n // Spread FIRST so web-specific overrides below take precedence.\n ...observabilityRevivers,\n\n // Binary types\n ArrayBuffer: reviveArrayBuffer,\n BigInt: (value: string) => BigInt(value),\n BigInt64Array: (value: string) =>\n new BigInt64Array(reviveArrayBuffer(value)),\n BigUint64Array: (value: string) =>\n new BigUint64Array(reviveArrayBuffer(value)),\n Date: (value) => new Date(value),\n\n // Error family. The reducer side (see\n // `packages/core/src/serialization/reducers/common.ts`) emits a tagged\n // entry for each built-in Error subclass plus the workflow-specific\n // `FatalError` / `RetryableError` and `AggregateError`. Without\n // matching revivers here, `devalue.unflatten` throws \"Unknown type X\"\n // — which surfaces in the web o11y UI as \"Failed to load resource\n // details: Unknown type FatalError\".\n Error: (value) => {\n const opts = 'cause' in value ? { cause: value.cause } : undefined;\n const error = new Error(value.message, opts);\n error.name = value.name;\n if (value.stack !== undefined) error.stack = value.stack;\n return error;\n },\n EvalError: makeWebErrorSubclassReviver('EvalError'),\n RangeError: makeWebErrorSubclassReviver('RangeError'),\n ReferenceError: makeWebErrorSubclassReviver('ReferenceError'),\n SyntaxError: makeWebErrorSubclassReviver('SyntaxError'),\n TypeError: makeWebErrorSubclassReviver('TypeError'),\n URIError: makeWebErrorSubclassReviver('URIError'),\n AggregateError: (value) => {\n const opts = 'cause' in value ? { cause: value.cause } : undefined;\n const Ctor = (\n globalThis as { AggregateError?: AggregateErrorConstructor }\n ).AggregateError;\n const error =\n typeof Ctor === 'function'\n ? new Ctor(value.errors, value.message, opts)\n : Object.assign(new Error(value.message, opts), {\n name: 'AggregateError',\n errors: value.errors,\n });\n if (value.stack !== undefined) error.stack = value.stack;\n return error;\n },\n // `FatalError` and `RetryableError` are not built-in browser globals,\n // so we can't resolve a constructor from globalThis. The web o11y UI\n // doesn't need `instanceof FatalError` to pass (no user code runs\n // here) — it just needs `name`, `message`, `stack`, and any extra\n // enumerable fields to render. Construct a plain `Error` with `name`\n // set; ObjectInspector reads `constructor.name` for the displayed\n // class label, but we don't have the real class, so we emit a tagged\n // Error whose `name` field carries the class identity. This matches\n // how the existing base `Error` reviver presents unknown subclasses.\n FatalError: (value) => {\n const opts = 'cause' in value ? { cause: value.cause } : undefined;\n const error = new Error(value.message, opts);\n error.name = 'FatalError';\n if (value.stack !== undefined) error.stack = value.stack;\n return error;\n },\n RetryableError: (value) => {\n const opts = 'cause' in value ? { cause: value.cause } : undefined;\n const error = new Error(value.message, opts) as Error & {\n retryAfter?: Date;\n };\n error.name = 'RetryableError';\n if (value.stack !== undefined) error.stack = value.stack;\n // `retryAfter` is serialized as an epoch ms number (see the runtime\n // RetryableError reducer for the rationale around realm-safety).\n // Rehydrate as a Date so o11y consumers can render it directly.\n // Guard against payloads from older runtime versions that predate\n // the field — without this check, `new Date(undefined)` would\n // produce an Invalid Date rather than omitting the property.\n if (value.retryAfter != null) {\n error.retryAfter = new Date(value.retryAfter);\n }\n return error;\n },\n DOMException: (value) => {\n // Modern browsers and Node 18+ expose `DOMException` on globalThis.\n // `AbortController.abort()` with no argument synthesizes one as the\n // signal's reason, so this is a common payload for any aborted step.\n const G = globalThis as { DOMException?: typeof DOMException };\n if (typeof G.DOMException === 'function') {\n const e = new G.DOMException(value.message, value.name);\n if (value.stack !== undefined) e.stack = value.stack;\n if ('cause' in value) (e as { cause?: unknown }).cause = value.cause;\n return e;\n }\n const error = new Error(value.message);\n error.name = value.name;\n if (value.stack !== undefined) error.stack = value.stack;\n if ('cause' in value) {\n (error as Error & { cause?: unknown }).cause = value.cause;\n }\n return error;\n },\n Float32Array: (value: string) => new Float32Array(reviveArrayBuffer(value)),\n Float64Array: (value: string) => new Float64Array(reviveArrayBuffer(value)),\n Int8Array: (value: string) => new Int8Array(reviveArrayBuffer(value)),\n Int16Array: (value: string) => new Int16Array(reviveArrayBuffer(value)),\n Int32Array: (value: string) => new Int32Array(reviveArrayBuffer(value)),\n Map: (value) => new Map(value),\n RegExp: (value) => new RegExp(value.source, value.flags),\n Set: (value) => new Set(value),\n Uint8Array: (value: string) => new Uint8Array(reviveArrayBuffer(value)),\n Uint8ClampedArray: (value: string) =>\n new Uint8ClampedArray(reviveArrayBuffer(value)),\n Uint16Array: (value: string) => new Uint16Array(reviveArrayBuffer(value)),\n Uint32Array: (value: string) => new Uint32Array(reviveArrayBuffer(value)),\n\n Headers: (value) => new Headers(value),\n Request: (value) => {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { Request: function () {} }.Request!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, {\n method: value.method,\n url: value.url,\n headers: new Headers(value.headers),\n body: value.body,\n duplex: value.duplex,\n ...(value.responseWritable\n ? { responseWritable: value.responseWritable }\n : {}),\n });\n return obj;\n },\n Response: (value) => {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { Response: function () {} }.Response!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, {\n status: value.status,\n statusText: value.statusText,\n url: value.url,\n headers: new Headers(value.headers),\n body: value.body,\n redirected: value.redirected,\n type: value.type,\n });\n return obj;\n },\n URL: (value) => new URL(value),\n URLSearchParams: (value) => new URLSearchParams(value === '.' ? '' : value),\n\n // Web-specific overrides for class instances.\n // Create objects with a dynamically-named constructor so that\n // react-inspector shows the class name (it reads constructor.name).\n Class: (value) => `<class:${extractClassName(value.classId)}>`,\n Instance: (value) => {\n // Run instances are rendered as clickable RunRef badges\n const runRef = serializedInstanceToRef(value);\n if (isRunRef(runRef)) {\n return runRef;\n }\n const className = extractClassName(value.classId);\n const data = value.data;\n const props =\n data && typeof data === 'object' ? { ...data } : { value: data };\n // Create a constructor with the right name using computed property\n // so react-inspector's `object.constructor.name` shows the class name.\n // Must use `function` (not arrow) because arrow functions have no .prototype.\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [className]: function () {} }[className]!;\n const obj = Object.create(ctor.prototype);\n Object.assign(obj, props);\n return obj;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Pre-built web revivers (cached for performance)\n// ---------------------------------------------------------------------------\n\nlet cachedRevivers: Revivers | null = null;\n\nfunction getRevivers(): Revivers {\n if (!cachedRevivers) {\n cachedRevivers = getWebRevivers();\n }\n return cachedRevivers;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Hydrate the serialized data fields of a resource for web display.\n *\n * Uses browser-safe revivers (atob for base64, ClassInstanceRef for\n * custom classes, StreamRef for streams). Call this on data received\n * from the server before passing it to UI components.\n */\nexport function hydrateResourceIO<T>(resource: T): T {\n const hydrated = hydrateResourceIOGeneric(\n resource as any,\n getRevivers()\n ) as T;\n return replaceEncryptedAndExpiredWithMarkers(hydrated);\n}\n\n// ---------------------------------------------------------------------------\n// Encrypted data display markers\n// ---------------------------------------------------------------------------\n\nexport const ENCRYPTED_DISPLAY_NAME = 'Encrypted';\n\n/**\n * Create a display-friendly object for encrypted data.\n *\n * Uses the same named-constructor trick as the Instance reviver so that\n * ObjectInspector renders the constructor name (\"🔒 Encrypted\") with no\n * expandable children. The original encrypted bytes are stored in a\n * non-enumerable property for later decryption.\n */\nfunction createEncryptedMarker(data: Uint8Array): object {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [ENCRYPTED_DISPLAY_NAME]: function () {} }[\n ENCRYPTED_DISPLAY_NAME\n ]!;\n const obj = Object.create(ctor.prototype);\n // Store original bytes for decryption, but non-enumerable so\n // ObjectInspector doesn't show them as children\n Object.defineProperty(obj, '__encryptedData', {\n value: data,\n enumerable: false,\n configurable: false,\n });\n return obj;\n}\n\n/** Check if a value is an encrypted display marker */\nexport function isEncryptedMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === ENCRYPTED_DISPLAY_NAME\n );\n}\n\n// ---------------------------------------------------------------------------\n// Expired data display markers\n// ---------------------------------------------------------------------------\n\nexport const EXPIRED_DISPLAY_NAME = 'Expired Data';\n\n/**\n * Create a display-friendly object for expired data.\n *\n * Uses the same named-constructor trick as the encrypted marker so that\n * ObjectInspector renders the constructor name (\"Expired Data\") with no\n * expandable children.\n */\nfunction createExpiredMarker(): object {\n // biome-ignore lint/complexity/useArrowFunction: arrow functions have no .prototype\n const ctor = { [EXPIRED_DISPLAY_NAME]: function () {} }[\n EXPIRED_DISPLAY_NAME\n ]!;\n return Object.create(ctor.prototype);\n}\n\n/** Check if a value is an expired data display marker */\nexport function isExpiredMarker(value: unknown): boolean {\n return (\n value !== null &&\n typeof value === 'object' &&\n value.constructor?.name === EXPIRED_DISPLAY_NAME\n );\n}\n\n/** Replace a single field value with a display marker if it's encrypted or expired. */\nfunction toDisplayMarker(value: unknown): unknown {\n if (isEncryptedData(value)) return createEncryptedMarker(value as Uint8Array);\n if (isExpiredStub(value)) return createExpiredMarker();\n return value;\n}\n\n/**\n * Post-process hydrated resource data: replace encrypted Uint8Array values\n * and expired stubs with display-friendly marker objects in known data fields.\n */\nfunction replaceEncryptedAndExpiredWithMarkers<T>(resource: T): T {\n if (!resource || typeof resource !== 'object') return resource;\n const r = resource as Record<string, unknown>;\n const result = { ...r };\n\n for (const key of ['input', 'output', 'metadata', 'error']) {\n result[key] = toDisplayMarker(result[key]);\n }\n\n if (result.eventData && typeof result.eventData === 'object') {\n const eventType =\n typeof result.eventType === 'string' ? result.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const ed = { ...(result.eventData as Record<string, unknown>) };\n for (const key of refKeys) {\n if (key in ed) {\n ed[key] = toDisplayMarker(ed[key]);\n }\n }\n result.eventData = ed;\n }\n\n return result as T;\n}\n\n/**\n * Hydrate resource data with decryption support.\n *\n * When a key is provided, encrypted fields are decrypted before hydration.\n * This is the async version used when the user clicks \"Decrypt\" in the web UI.\n *\n * Handles both top-level fields (input, output, metadata) and nested\n * eventData subfields per `EVENT_DATA_REF_FIELDS` from `@workflow/world` for that event type.\n */\nexport async function hydrateResourceIOWithKey<T>(\n resource: T,\n key: Uint8Array\n): Promise<T> {\n const { hydrateDataWithKey } = await import(\n '@workflow/core/serialization-format'\n );\n const { importKey } = await import('@workflow/core/encryption');\n const cryptoKey = await importKey(key);\n const revivers = getRevivers();\n\n /** Extract original encrypted bytes from a marker or raw Uint8Array, then decrypt + hydrate */\n async function decryptField(\n value: unknown,\n rev: Revivers,\n k: Awaited<ReturnType<typeof importKey>>\n ): Promise<unknown> {\n // Already-hydrated: encrypted marker with stored bytes\n if (isEncryptedMarker(value)) {\n const raw = (value as any).__encryptedData as Uint8Array;\n return hydrateDataWithKey(raw, rev, k);\n }\n // Raw encrypted Uint8Array (not yet hydrated)\n if (value instanceof Uint8Array) {\n return hydrateDataWithKey(value, rev, k);\n }\n // Not encrypted — return as-is\n return value;\n }\n\n const r = resource as Record<string, unknown>;\n const result = { ...r };\n\n // Decrypt + hydrate top-level serialized fields (runs, steps, hooks)\n for (const field of ['input', 'output', 'metadata', 'error']) {\n if (field in result) {\n result[field] = await decryptField(result[field], revivers, cryptoKey);\n }\n }\n\n // Decrypt + hydrate eventData subfields (events)\n if (result.eventData && typeof result.eventData === 'object') {\n const eventType =\n typeof result.eventType === 'string' ? result.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const eventData = { ...(result.eventData as Record<string, unknown>) };\n for (const field of refKeys) {\n if (field in eventData) {\n eventData[field] = await decryptField(\n eventData[field],\n revivers,\n cryptoKey\n );\n }\n }\n result.eventData = eventData;\n }\n\n return result as T;\n}\n\n/**\n * Check whether a hydrated resource (event, step, run, etc.) contains any\n * encrypted display markers. Inspects the standard top-level fields\n * (`input`, `output`, `error`, `metadata`) as well as the event-type-specific\n * `eventData` ref fields.\n */\nexport function hasEncryptedFields(resource: unknown): boolean {\n if (!resource || typeof resource !== 'object') return false;\n const r = resource as Record<string, unknown>;\n\n for (const key of ['input', 'output', 'metadata', 'error']) {\n if (isEncryptedMarker(r[key])) return true;\n }\n\n if (r.eventData && typeof r.eventData === 'object') {\n const eventType = typeof r.eventType === 'string' ? r.eventType : '';\n const refKeys = EVENT_DATA_REF_FIELDS[eventType] ?? [];\n const ed = r.eventData as Record<string, unknown>;\n for (const key of refKeys) {\n if (key in ed && isEncryptedMarker(ed[key])) return true;\n }\n }\n\n return false;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workflow/web-shared",
3
3
  "description": "Shared components for Workflow Observability UI",
4
- "version": "5.0.0-beta.4",
4
+ "version": "5.0.0-beta.5",
5
5
  "private": false,
6
6
  "files": [
7
7
  "dist",
@@ -53,9 +53,9 @@
53
53
  "streamdown": "2.3.0",
54
54
  "tailwind-merge": "3.5.0",
55
55
  "tailwindcss": "4",
56
- "@workflow/core": "5.0.0-beta.4",
57
- "@workflow/utils": "5.0.0-beta.1",
58
- "@workflow/world": "5.0.0-beta.1"
56
+ "@workflow/core": "5.0.0-beta.5",
57
+ "@workflow/utils": "5.0.0-beta.2",
58
+ "@workflow/world": "5.0.0-beta.2"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@biomejs/biome": "^2.4.4",
@@ -65,6 +65,7 @@
65
65
  "ai": "6.0.116",
66
66
  "typescript": "^5.9.3",
67
67
  "vitest": "^4.0.18",
68
+ "@workflow/errors": "5.0.0-beta.2",
68
69
  "@workflow/tsconfig": "5.0.0-beta.0"
69
70
  },
70
71
  "scripts": {
@@ -61,24 +61,24 @@ const EventRow = ({
61
61
  'relative overflow-clip group after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-gray-alpha-400',
62
62
  ROW_HEIGHT_CLASS
63
63
  )}
64
- role='treeitem'
64
+ role="treeitem"
65
65
  aria-selected={isSelected}
66
66
  aria-expanded={isSelected}
67
67
  aria-level={1}
68
68
  onClick={() => onSelectSpan(span.spanId)}
69
69
  >
70
- <div className='h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200'>
71
- <div className='flex h-full min-w-0 items-center px-2'>
72
- <div className='flex min-w-0 flex-1 items-center gap-2'>
70
+ <div className="h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200">
71
+ <div className="flex h-full min-w-0 items-center px-2">
72
+ <div className="flex min-w-0 flex-1 items-center gap-2">
73
73
  <span className={cn('shrink-0', tagClassName)}>
74
- <Icon className='w-4 h-4' />
74
+ <Icon className="w-4 h-4" />
75
75
  </span>
76
- <span className='min-w-0 text-label-14'>
76
+ <span className="min-w-0 text-label-14">
77
77
  <MiddleTruncate value={span.name} />
78
78
  </span>
79
79
  </div>
80
- <div className='ml-2 shrink-0'>
81
- <span className='text-label-14 text-gray-900 tabular-nums'>
80
+ <div className="ml-2 shrink-0">
81
+ <span className="text-label-14 text-gray-900 tabular-nums">
82
82
  {formatDuration(durationMs)}
83
83
  </span>
84
84
  </div>
@@ -98,7 +98,7 @@ const EventList = ({
98
98
  onSelectSpan: (spanId: string) => void;
99
99
  }) => {
100
100
  return (
101
- <ul id='event-list' role='tree' className='block min-h-0 overflow-visible'>
101
+ <ul id="event-list" role="tree" className="block min-h-0 overflow-visible">
102
102
  {spans.map((span) => {
103
103
  return (
104
104
  <EventRow
@@ -122,16 +122,16 @@ function MiddleTruncate({
122
122
  )}
123
123
  onCopy={handleCopy}
124
124
  >
125
- {isTruncated && <span className='sr-only select-none'>{value}</span>}
125
+ {isTruncated && <span className="sr-only select-none">{value}</span>}
126
126
  <span
127
- aria-hidden='true'
128
- className='pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap'
127
+ aria-hidden="true"
128
+ className="pointer-events-none col-start-1 row-start-1 invisible select-none whitespace-nowrap"
129
129
  >
130
130
  {value}
131
131
  </span>
132
132
  <span
133
133
  aria-hidden={isTruncated || undefined}
134
- className='col-start-1 row-start-1 min-w-0 overflow-hidden'
134
+ className="col-start-1 row-start-1 min-w-0 overflow-hidden"
135
135
  ref={visibleRef}
136
136
  >
137
137
  {isTruncated ? (
@@ -145,8 +145,8 @@ function MiddleTruncate({
145
145
  )}
146
146
  </span>
147
147
  <span
148
- aria-hidden='true'
149
- className='pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap'
148
+ aria-hidden="true"
149
+ className="pointer-events-none absolute left-0 top-0 inline-block invisible select-none whitespace-nowrap"
150
150
  ref={measureRef}
151
151
  />
152
152
  </span>
@@ -443,6 +443,10 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
443
443
  const selectedSpanName = useMemo(() => {
444
444
  if (!selectedSpan?.data) return 'Details';
445
445
  const data = selectedSpan.data as Record<string, unknown>;
446
+ if (selectedSpan.resource === 'hook') {
447
+ return (data.token as string | undefined) ?? (data.hookId as string);
448
+ }
449
+
446
450
  const stepName = data.stepName as string | undefined;
447
451
  const workflowName = data.workflowName as string | undefined;
448
452
  return (
@@ -453,51 +457,55 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
453
457
  (data.hookId as string) ??
454
458
  'Details'
455
459
  );
456
- }, [selectedSpan?.data]);
460
+ }, [selectedSpan?.data, selectedSpan?.resource]);
457
461
 
458
462
  const selectedResource = selectedSpan?.resource as string | undefined;
459
463
  const selectedResourceId = useMemo(() => {
460
464
  if (!selectedSpan?.data) return undefined;
461
465
  const data = selectedSpan.data as Record<string, unknown>;
466
+ if (selectedSpan.resource === 'hook') {
467
+ return (data.hookId as string | undefined) ?? selectedSpan.spanId;
468
+ }
469
+
462
470
  return (
463
471
  (data.stepId as string) ??
464
472
  (data.runId as string) ??
465
473
  (data.hookId as string) ??
466
474
  selectedSpan.spanId
467
475
  );
468
- }, [selectedSpan?.data, selectedSpan?.spanId]);
476
+ }, [selectedSpan?.data, selectedSpan?.resource, selectedSpan?.spanId]);
469
477
 
470
478
  return (
471
479
  <div
472
- data-pane='pane-root'
480
+ data-pane="pane-root"
473
481
  data-has-detail={activeSpan ? '' : undefined}
474
- className='grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]'
482
+ className="grid w-full h-full max-h-full grid-cols-[minmax(100px,1fr)] data-[has-detail]:grid-cols-[minmax(100px,1fr)_clamp(280px,420px,100%)]"
475
483
  >
476
484
  <div
477
- id='trace-parent'
478
- className='grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100'
485
+ id="trace-parent"
486
+ className="grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100"
479
487
  >
480
488
  <SplitPane
481
489
  startHeader={
482
- <div className='bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center px-2 gap-1.5'>
483
- <Search className='w-3.5 h-3.5 shrink-0 text-gray-800' />
490
+ <div className="bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center px-2 gap-1.5">
491
+ <Search className="w-3.5 h-3.5 shrink-0 text-gray-800" />
484
492
  <input
485
- id='trace-viewer-search'
486
- name='trace-viewer-search'
487
- type='text'
493
+ id="trace-viewer-search"
494
+ name="trace-viewer-search"
495
+ type="text"
488
496
  value={searchQuery}
489
497
  onChange={(e) => setSearchQuery(e.target.value)}
490
- placeholder='Search spans...'
491
- aria-label='Search spans'
492
- className='flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none'
498
+ placeholder="Search spans..."
499
+ aria-label="Search spans"
500
+ className="flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none"
493
501
  />
494
502
  {searchQuery && (
495
503
  <button
496
- type='button'
504
+ type="button"
497
505
  onClick={() => setSearchQuery('')}
498
- className='shrink-0 p-0.5 rounded-sm text-gray-800 hover:text-gray-1000 hover:bg-gray-200 transition-colors'
506
+ className="shrink-0 p-0.5 rounded-sm text-gray-800 hover:text-gray-1000 hover:bg-gray-200 transition-colors"
499
507
  >
500
- <X className='w-3 h-3' />
508
+ <X className="w-3 h-3" />
501
509
  </button>
502
510
  )}
503
511
  </div>
@@ -506,7 +514,7 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
506
514
  <TimelineHeader markers={timeMarkers} hoverInfo={hoverInfo} />
507
515
  }
508
516
  >
509
- <div className='block overflow-visible'>
517
+ <div className="block overflow-visible">
510
518
  <EventList
511
519
  spans={filteredSpans}
512
520
  activeSpanId={activeSpanId}
@@ -515,7 +523,7 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
515
523
  </div>
516
524
  <div
517
525
  ref={timelineRef}
518
- className='block min-h-0 overflow-visible relative'
526
+ className="block min-h-0 overflow-visible relative"
519
527
  onDoubleClick={resetZoom}
520
528
  onMouseMove={handleTimelineMouseMove}
521
529
  onMouseLeave={handleTimelineMouseLeave}
@@ -532,46 +540,46 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
532
540
  />
533
541
  </div>
534
542
  </SplitPane>
535
- <div className='absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-lg bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400'>
543
+ <div className="absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-lg bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400">
536
544
  <button
537
- type='button'
538
- className='flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100'
545
+ type="button"
546
+ className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
539
547
  onClick={zoomOut}
540
- aria-label='Zoom out'
548
+ aria-label="Zoom out"
541
549
  >
542
- <ZoomOut className='w-4 h-4' />
550
+ <ZoomOut className="w-4 h-4" />
543
551
  </button>
544
552
  <button
545
- type='button'
546
- className='flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100'
553
+ type="button"
554
+ className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
547
555
  onClick={resetZoom}
548
- aria-label='Reset zoom'
556
+ aria-label="Reset zoom"
549
557
  >
550
- <RotateCcw className='w-3.5 h-3.5' />
558
+ <RotateCcw className="w-3.5 h-3.5" />
551
559
  </button>
552
560
  <button
553
- type='button'
554
- className='flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100'
561
+ type="button"
562
+ className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
555
563
  onClick={zoomIn}
556
- aria-label='Zoom in'
564
+ aria-label="Zoom in"
557
565
  >
558
- <ZoomIn className='w-4 h-4' />
566
+ <ZoomIn className="w-4 h-4" />
559
567
  </button>
560
568
  </div>
561
569
  </div>
562
570
 
563
571
  {/* Detail panel */}
564
572
  {activeSpan && sidebar ? (
565
- <aside className='flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto'>
573
+ <aside className="flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto">
566
574
  {/* Panel header */}
567
- <div className='flex-shrink-0 px-4 pt-4 pb-3'>
568
- <div className='flex items-start justify-between gap-2'>
569
- <div className='min-w-0 flex-1'>
570
- <span className='text-[15px] font-semibold text-gray-1000 truncate block'>
575
+ <div className="flex-shrink-0 px-4 pt-4 pb-3">
576
+ <div className="flex items-start justify-between gap-2">
577
+ <div className="min-w-0 flex-1">
578
+ <span className="text-[15px] font-semibold text-gray-1000 truncate block">
571
579
  {selectedSpanName}
572
580
  </span>
573
581
  {selectedResourceId && (
574
- <div className='mt-1 flex items-center gap-2'>
582
+ <div className="mt-1 flex items-center gap-2">
575
583
  {selectedResource && (
576
584
  <span
577
585
  className={`inline-flex items-center rounded-md px-1.5 py-0.5 text-[11px] font-medium leading-none shrink-0 ${
@@ -589,30 +597,30 @@ function NewTraceViewerContent({ trace }: NewTraceViewerProps): ReactNode {
589
597
  </span>
590
598
  )}
591
599
  <div
592
- className='flex items-center gap-1 text-[13px] font-mono text-gray-700 min-w-0'
600
+ className="flex items-center gap-1 text-[13px] font-mono text-gray-700 min-w-0"
593
601
  title={selectedResourceId}
594
602
  >
595
- <span className='truncate'>{selectedResourceId}</span>
603
+ <span className="truncate">{selectedResourceId}</span>
596
604
  <CopyButton
597
605
  copyText={selectedResourceId}
598
- ariaLabel='Copy ID'
599
- className='shrink-0'
606
+ ariaLabel="Copy ID"
607
+ className="shrink-0"
600
608
  />
601
609
  </div>
602
610
  </div>
603
611
  )}
604
612
  </div>
605
613
  <button
606
- type='button'
607
- className='p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors shrink-0'
614
+ type="button"
615
+ className="p-1 rounded-md text-gray-900 hover:text-gray-1000 hover:bg-gray-alpha-200 transition-colors shrink-0"
608
616
  onClick={clearActiveSpan}
609
617
  >
610
- <X className='w-4 h-4' />
618
+ <X className="w-4 h-4" />
611
619
  </button>
612
620
  </div>
613
621
  </div>
614
622
  {/* Panel body */}
615
- <div className='flex-1 overflow-y-auto'>
623
+ <div className="flex-1 overflow-y-auto">
616
624
  <ErrorBoundary>
617
625
  <EntityDetailPanel
618
626
  run={sidebar.run}
@@ -441,6 +441,7 @@ const attributeToDisplayFn: Record<
441
441
  // Hook details
442
442
  token: (value: unknown) => String(value),
443
443
  isWebhook: (value: unknown) => String(value),
444
+ isSystem: (value: unknown) => String(value),
444
445
  receivedCount: (value: unknown) => String(value),
445
446
  lastReceivedAt: localMillisecondTimeOrNull,
446
447
  disposedAt: localMillisecondTimeOrNull,
@@ -624,6 +625,10 @@ const attributeToDisplayFn: Record<
624
625
  if (!hasDisplayContent(value)) return null;
625
626
  return <DetailCard summary="Event Data">{JsonBlock(value)}</DetailCard>;
626
627
  },
628
+ errorCode: (value: unknown) => {
629
+ if (typeof value !== 'string' || value.length === 0) return null;
630
+ return String(value);
631
+ },
627
632
  };
628
633
 
629
634
  const resolvableAttributes = [
@@ -18,6 +18,21 @@ export function isStructuredErrorWithStack(
18
18
  );
19
19
  }
20
20
 
21
+ /**
22
+ * Pull a short, single-line title out of an error message.
23
+ *
24
+ * Workflow's structured error messages are multi-line — the first line is
25
+ * the headline (`Failed to serialize step return value`) and the rest are
26
+ * `╰▶ hint:` / `╰▶ docs:` framed details. The full message belongs in the
27
+ * body of the error block; the title should just be the headline so the
28
+ * card stays scannable.
29
+ */
30
+ function deriveTitle(message: string): string {
31
+ const firstLine =
32
+ message.split('\n').find((line) => line.trim().length > 0) ?? message;
33
+ return firstLine.trim();
34
+ }
35
+
21
36
  /**
22
37
  * Renders an error with a `stack` field as a visually distinct error block.
23
38
  * Shows the error message with an alert icon at the top, separated from
@@ -31,6 +46,10 @@ export function ErrorStackBlock({
31
46
  const toast = useToast();
32
47
  const stack = value.stack;
33
48
  const message = typeof value.message === 'string' ? value.message : undefined;
49
+ // V8's `Error.stack` already starts with `Name: message`, so when the
50
+ // body shows the stack it includes the full multi-line message anyway.
51
+ // The header just needs the first line.
52
+ const title = message ? deriveTitle(message) : undefined;
34
53
  const copyText = message ? `${message}\n\n${stack}` : stack;
35
54
 
36
55
  return (
@@ -65,16 +84,25 @@ export function ErrorStackBlock({
65
84
  <Copy size={12} />
66
85
  </button>
67
86
 
68
- {message && (
87
+ {title && (
69
88
  <div
70
- className="flex items-start gap-2 px-3 py-2.5 pr-10"
89
+ className="flex items-center gap-2 px-3 py-2.5 pr-10"
71
90
  style={{
72
91
  color: 'var(--ds-red-900)',
73
92
  borderBottom: '1px solid var(--ds-red-400)',
74
93
  }}
75
94
  >
76
- <AlertCircle className="h-4 w-4 shrink-0" style={{ marginTop: 1 }} />
77
- <p className="text-xs font-semibold m-0 break-words">{message}</p>
95
+ <AlertCircle className="h-4 w-4 shrink-0" />
96
+ <p
97
+ className="text-xs font-semibold m-0 truncate"
98
+ // The full multi-line message is in the stack body below; the
99
+ // header just shows the first line, single-line, with overflow
100
+ // ellipsised so a long title doesn't push the copy button or
101
+ // wrap into the framed hint/docs lines.
102
+ title={message}
103
+ >
104
+ {title}
105
+ </p>
78
106
  </div>
79
107
  )}
80
108
  <pre
@@ -974,7 +974,7 @@ export const WorkflowTraceViewer = ({
974
974
  }
975
975
 
976
976
  return (
977
- <div className="relative w-full h-full flex flex-col">
977
+ <div className="relative w-full h-full flex flex-row">
978
978
  {/* Timeline (takes remaining space) */}
979
979
  <div className="flex-1 min-w-0 relative">
980
980
  <TraceViewerContextProvider
@@ -314,7 +314,7 @@ export function hookToSpan(hookEvents: Event[], maxEndTime: Date): Span | null {
314
314
 
315
315
  return {
316
316
  spanId: String(hook.hookId),
317
- name: String(hook.hookId),
317
+ name: hook.token ?? String(hook.hookId),
318
318
  kind: 1, // INTERNAL span kind
319
319
  resource: 'hook',
320
320
  library: WORKFLOW_LIBRARY,