@workflow/web-shared 5.0.0-beta.4 → 5.0.0-beta.6
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.
- package/dist/components/new-trace-viewer/components/event-list.js +2 -2
- package/dist/components/new-trace-viewer/components/event-list.js.map +1 -1
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +1 -1
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.js +10 -4
- package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +6 -0
- package/dist/components/sidebar/attribute-panel.js.map +1 -1
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +24 -2
- package/dist/components/ui/error-stack-block.js.map +1 -1
- package/dist/components/workflow-trace-view.js +1 -1
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
- package/dist/lib/hydration.d.ts +6 -0
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +124 -1
- package/dist/lib/hydration.js.map +1 -1
- package/package.json +5 -4
- package/src/components/new-trace-viewer/components/event-list.tsx +9 -9
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +6 -6
- package/src/components/new-trace-viewer/trace-viewer.tsx +54 -46
- package/src/components/sidebar/attribute-panel.tsx +5 -0
- package/src/components/ui/error-stack-block.tsx +32 -4
- package/src/components/workflow-trace-view.tsx +1 -1
- package/src/components/workflow-traces/trace-span-construction.ts +1 -1
- 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
|
+
"version": "5.0.0-beta.6",
|
|
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.
|
|
57
|
-
"@workflow/utils": "5.0.0-beta.
|
|
58
|
-
"@workflow/world": "5.0.0-beta.
|
|
56
|
+
"@workflow/core": "5.0.0-beta.6",
|
|
57
|
+
"@workflow/utils": "5.0.0-beta.2",
|
|
58
|
+
"@workflow/world": "5.0.0-beta.3"
|
|
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.3",
|
|
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=
|
|
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=
|
|
71
|
-
<div className=
|
|
72
|
-
<div className=
|
|
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=
|
|
74
|
+
<Icon className="w-4 h-4" />
|
|
75
75
|
</span>
|
|
76
|
-
<span className=
|
|
76
|
+
<span className="min-w-0 text-label-14">
|
|
77
77
|
<MiddleTruncate value={span.name} />
|
|
78
78
|
</span>
|
|
79
79
|
</div>
|
|
80
|
-
<div className=
|
|
81
|
-
<span className=
|
|
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=
|
|
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=
|
|
125
|
+
{isTruncated && <span className="sr-only select-none">{value}</span>}
|
|
126
126
|
<span
|
|
127
|
-
aria-hidden=
|
|
128
|
-
className=
|
|
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=
|
|
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=
|
|
149
|
-
className=
|
|
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=
|
|
480
|
+
data-pane="pane-root"
|
|
473
481
|
data-has-detail={activeSpan ? '' : undefined}
|
|
474
|
-
className=
|
|
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=
|
|
478
|
-
className=
|
|
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=
|
|
483
|
-
<Search className=
|
|
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=
|
|
486
|
-
name=
|
|
487
|
-
type=
|
|
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=
|
|
491
|
-
aria-label=
|
|
492
|
-
className=
|
|
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=
|
|
504
|
+
type="button"
|
|
497
505
|
onClick={() => setSearchQuery('')}
|
|
498
|
-
className=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
538
|
-
className=
|
|
545
|
+
type="button"
|
|
546
|
+
className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
|
|
539
547
|
onClick={zoomOut}
|
|
540
|
-
aria-label=
|
|
548
|
+
aria-label="Zoom out"
|
|
541
549
|
>
|
|
542
|
-
<ZoomOut className=
|
|
550
|
+
<ZoomOut className="w-4 h-4" />
|
|
543
551
|
</button>
|
|
544
552
|
<button
|
|
545
|
-
type=
|
|
546
|
-
className=
|
|
553
|
+
type="button"
|
|
554
|
+
className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
|
|
547
555
|
onClick={resetZoom}
|
|
548
|
-
aria-label=
|
|
556
|
+
aria-label="Reset zoom"
|
|
549
557
|
>
|
|
550
|
-
<RotateCcw className=
|
|
558
|
+
<RotateCcw className="w-3.5 h-3.5" />
|
|
551
559
|
</button>
|
|
552
560
|
<button
|
|
553
|
-
type=
|
|
554
|
-
className=
|
|
561
|
+
type="button"
|
|
562
|
+
className="flex items-center justify-center w-8 h-8 text-gray-900 cursor-pointer transition-colors duration-[time:120ms] ease-in-out hover:text-gray-1000 hover:bg-gray-alpha-100"
|
|
555
563
|
onClick={zoomIn}
|
|
556
|
-
aria-label=
|
|
564
|
+
aria-label="Zoom in"
|
|
557
565
|
>
|
|
558
|
-
<ZoomIn className=
|
|
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=
|
|
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=
|
|
568
|
-
<div className=
|
|
569
|
-
<div className=
|
|
570
|
-
<span className=
|
|
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=
|
|
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=
|
|
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=
|
|
603
|
+
<span className="truncate">{selectedResourceId}</span>
|
|
596
604
|
<CopyButton
|
|
597
605
|
copyText={selectedResourceId}
|
|
598
|
-
ariaLabel=
|
|
599
|
-
className=
|
|
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=
|
|
607
|
-
className=
|
|
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=
|
|
618
|
+
<X className="w-4 h-4" />
|
|
611
619
|
</button>
|
|
612
620
|
</div>
|
|
613
621
|
</div>
|
|
614
622
|
{/* Panel body */}
|
|
615
|
-
<div className=
|
|
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
|
-
{
|
|
87
|
+
{title && (
|
|
69
88
|
<div
|
|
70
|
-
className="flex items-
|
|
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"
|
|
77
|
-
<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-
|
|
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,
|