@workflow/web-shared 5.0.0-beta.3 → 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.
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/event-list.js +7 -4
- package/dist/components/new-trace-viewer/components/event-list.js.map +1 -1
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/split-pane.js +2 -3
- package/dist/components/new-trace-viewer/components/split-pane.js.map +1 -1
- package/dist/components/new-trace-viewer/components/timeline.d.ts +10 -11
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/components/timeline.js +57 -53
- package/dist/components/new-trace-viewer/components/timeline.js.map +1 -1
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/context.js +5 -7
- package/dist/components/new-trace-viewer/context.js.map +1 -1
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/detail-panel.js +2 -1
- package/dist/components/new-trace-viewer/detail-panel.js.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/trace-viewer.js +44 -18
- package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -1
- package/dist/components/new-trace-viewer/utils.d.ts +3 -8
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
- package/dist/components/new-trace-viewer/utils.js +12 -65
- package/dist/components/new-trace-viewer/utils.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/trace-viewer/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +5 -8
- package/dist/components/trace-viewer/util/timing.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.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +17 -4
- 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/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +2 -1
- package/dist/lib/trace-builder.js.map +1 -1
- package/dist/lib/utils.d.ts +9 -7
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +27 -27
- package/dist/lib/utils.js.map +1 -1
- package/package.json +5 -4
- package/src/components/new-trace-viewer/components/event-list.tsx +26 -19
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +2 -3
- package/src/components/new-trace-viewer/components/timeline.tsx +119 -115
- package/src/components/new-trace-viewer/context.tsx +7 -9
- package/src/components/new-trace-viewer/detail-panel.tsx +2 -1
- package/src/components/new-trace-viewer/trace-viewer.tsx +100 -32
- package/src/components/new-trace-viewer/utils.ts +19 -93
- package/src/components/sidebar/attribute-panel.tsx +5 -0
- package/src/components/trace-viewer/util/timing.ts +5 -9
- 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 +23 -5
- package/src/lib/hydration.ts +132 -1
- package/src/lib/trace-builder.ts +2 -1
- package/src/lib/utils.ts +29 -29
package/dist/lib/hydration.js
CHANGED
|
@@ -26,12 +26,51 @@ function base64ToArrayBuffer(base64) {
|
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
// Web revivers (browser-safe, no Buffer dependency)
|
|
28
28
|
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Build a reviver for one of the built-in `Error` subclasses (e.g.
|
|
31
|
+
* `TypeError`, `RangeError`). The constructor for the named subclass is
|
|
32
|
+
* resolved off `globalThis` at call time so the produced instance has the
|
|
33
|
+
* correct prototype chain in the consumer realm. Falls back to a generic
|
|
34
|
+
* `Error` (with `name` set) if the global isn't available, which keeps the
|
|
35
|
+
* o11y UI rendering even on exotic browsers.
|
|
36
|
+
*
|
|
37
|
+
* `cause` is passed through `ErrorOptions` to the constructor when present,
|
|
38
|
+
* matching `getCommonRevivers` in `@workflow/core` so the resulting `cause`
|
|
39
|
+
* property has the same semantics (non-enumerable, set by the engine) as a
|
|
40
|
+
* freshly thrown Error in the consumer realm. The `'cause' in value` check
|
|
41
|
+
* preserves the distinction between "no cause" and "cause is undefined".
|
|
42
|
+
*/
|
|
43
|
+
function makeWebErrorSubclassReviver(name) {
|
|
44
|
+
return (value) => {
|
|
45
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
46
|
+
const Ctor = globalThis[name];
|
|
47
|
+
let error;
|
|
48
|
+
if (typeof Ctor === 'function') {
|
|
49
|
+
error = new Ctor(value.message, opts);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Fallback path: no built-in subclass available (exotic env). Construct
|
|
53
|
+
// a plain Error with the right `name` and copy `cause` manually since
|
|
54
|
+
// the base Error constructor is what we actually called.
|
|
55
|
+
error = Object.assign(new Error(value.message, opts), { name });
|
|
56
|
+
}
|
|
57
|
+
if (value.stack !== undefined)
|
|
58
|
+
error.stack = value.stack;
|
|
59
|
+
return error;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
29
62
|
/**
|
|
30
63
|
* Get the web-specific revivers for hydrating serialized data.
|
|
31
64
|
*
|
|
32
65
|
* Uses `atob()` for base64 decoding (no Node.js Buffer dependency).
|
|
33
66
|
* All types are revived as real instances (Date, Map, Set, URL,
|
|
34
67
|
* URLSearchParams, Headers, Error, etc.).
|
|
68
|
+
*
|
|
69
|
+
* NOTE: this set must mirror the keys in `SerializableSpecial` (see
|
|
70
|
+
* `@workflow/core/serialization/types`). Any reducer key added on the
|
|
71
|
+
* serialization side that isn't covered here will cause `devalue.unflatten`
|
|
72
|
+
* to throw `Unknown type X`, which `hydrateResourceIO` swallows and
|
|
73
|
+
* surfaces as a "Failed to load resource details" banner in the o11y UI.
|
|
35
74
|
*/
|
|
36
75
|
export function getWebRevivers() {
|
|
37
76
|
function reviveArrayBuffer(value) {
|
|
@@ -47,10 +86,94 @@ export function getWebRevivers() {
|
|
|
47
86
|
BigInt64Array: (value) => new BigInt64Array(reviveArrayBuffer(value)),
|
|
48
87
|
BigUint64Array: (value) => new BigUint64Array(reviveArrayBuffer(value)),
|
|
49
88
|
Date: (value) => new Date(value),
|
|
89
|
+
// Error family. The reducer side (see
|
|
90
|
+
// `packages/core/src/serialization/reducers/common.ts`) emits a tagged
|
|
91
|
+
// entry for each built-in Error subclass plus the workflow-specific
|
|
92
|
+
// `FatalError` / `RetryableError` and `AggregateError`. Without
|
|
93
|
+
// matching revivers here, `devalue.unflatten` throws "Unknown type X"
|
|
94
|
+
// — which surfaces in the web o11y UI as "Failed to load resource
|
|
95
|
+
// details: Unknown type FatalError".
|
|
50
96
|
Error: (value) => {
|
|
97
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
98
|
+
const error = new Error(value.message, opts);
|
|
99
|
+
error.name = value.name;
|
|
100
|
+
if (value.stack !== undefined)
|
|
101
|
+
error.stack = value.stack;
|
|
102
|
+
return error;
|
|
103
|
+
},
|
|
104
|
+
EvalError: makeWebErrorSubclassReviver('EvalError'),
|
|
105
|
+
RangeError: makeWebErrorSubclassReviver('RangeError'),
|
|
106
|
+
ReferenceError: makeWebErrorSubclassReviver('ReferenceError'),
|
|
107
|
+
SyntaxError: makeWebErrorSubclassReviver('SyntaxError'),
|
|
108
|
+
TypeError: makeWebErrorSubclassReviver('TypeError'),
|
|
109
|
+
URIError: makeWebErrorSubclassReviver('URIError'),
|
|
110
|
+
AggregateError: (value) => {
|
|
111
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
112
|
+
const Ctor = globalThis.AggregateError;
|
|
113
|
+
const error = typeof Ctor === 'function'
|
|
114
|
+
? new Ctor(value.errors, value.message, opts)
|
|
115
|
+
: Object.assign(new Error(value.message, opts), {
|
|
116
|
+
name: 'AggregateError',
|
|
117
|
+
errors: value.errors,
|
|
118
|
+
});
|
|
119
|
+
if (value.stack !== undefined)
|
|
120
|
+
error.stack = value.stack;
|
|
121
|
+
return error;
|
|
122
|
+
},
|
|
123
|
+
// `FatalError` and `RetryableError` are not built-in browser globals,
|
|
124
|
+
// so we can't resolve a constructor from globalThis. The web o11y UI
|
|
125
|
+
// doesn't need `instanceof FatalError` to pass (no user code runs
|
|
126
|
+
// here) — it just needs `name`, `message`, `stack`, and any extra
|
|
127
|
+
// enumerable fields to render. Construct a plain `Error` with `name`
|
|
128
|
+
// set; ObjectInspector reads `constructor.name` for the displayed
|
|
129
|
+
// class label, but we don't have the real class, so we emit a tagged
|
|
130
|
+
// Error whose `name` field carries the class identity. This matches
|
|
131
|
+
// how the existing base `Error` reviver presents unknown subclasses.
|
|
132
|
+
FatalError: (value) => {
|
|
133
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
134
|
+
const error = new Error(value.message, opts);
|
|
135
|
+
error.name = 'FatalError';
|
|
136
|
+
if (value.stack !== undefined)
|
|
137
|
+
error.stack = value.stack;
|
|
138
|
+
return error;
|
|
139
|
+
},
|
|
140
|
+
RetryableError: (value) => {
|
|
141
|
+
const opts = 'cause' in value ? { cause: value.cause } : undefined;
|
|
142
|
+
const error = new Error(value.message, opts);
|
|
143
|
+
error.name = 'RetryableError';
|
|
144
|
+
if (value.stack !== undefined)
|
|
145
|
+
error.stack = value.stack;
|
|
146
|
+
// `retryAfter` is serialized as an epoch ms number (see the runtime
|
|
147
|
+
// RetryableError reducer for the rationale around realm-safety).
|
|
148
|
+
// Rehydrate as a Date so o11y consumers can render it directly.
|
|
149
|
+
// Guard against payloads from older runtime versions that predate
|
|
150
|
+
// the field — without this check, `new Date(undefined)` would
|
|
151
|
+
// produce an Invalid Date rather than omitting the property.
|
|
152
|
+
if (value.retryAfter != null) {
|
|
153
|
+
error.retryAfter = new Date(value.retryAfter);
|
|
154
|
+
}
|
|
155
|
+
return error;
|
|
156
|
+
},
|
|
157
|
+
DOMException: (value) => {
|
|
158
|
+
// Modern browsers and Node 18+ expose `DOMException` on globalThis.
|
|
159
|
+
// `AbortController.abort()` with no argument synthesizes one as the
|
|
160
|
+
// signal's reason, so this is a common payload for any aborted step.
|
|
161
|
+
const G = globalThis;
|
|
162
|
+
if (typeof G.DOMException === 'function') {
|
|
163
|
+
const e = new G.DOMException(value.message, value.name);
|
|
164
|
+
if (value.stack !== undefined)
|
|
165
|
+
e.stack = value.stack;
|
|
166
|
+
if ('cause' in value)
|
|
167
|
+
e.cause = value.cause;
|
|
168
|
+
return e;
|
|
169
|
+
}
|
|
51
170
|
const error = new Error(value.message);
|
|
52
171
|
error.name = value.name;
|
|
53
|
-
|
|
172
|
+
if (value.stack !== undefined)
|
|
173
|
+
error.stack = value.stack;
|
|
174
|
+
if ('cause' in value) {
|
|
175
|
+
error.cause = value.cause;
|
|
176
|
+
}
|
|
54
177
|
return error;
|
|
55
178
|
},
|
|
56
179
|
Float32Array: (value) => new Float32Array(reviveArrayBuffer(value)),
|
|
@@ -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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace-builder.d.ts","sourceRoot":"","sources":["../../src/lib/trace-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AAc7D,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,YAAkC,CAAC;AAEhF,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,mDACkB,CAAC;AAEjE,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,oEAGvB,CAAC;AAMhC,MAAM,MAAM,aAAa,GAAG;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrC,cAAc,EAAE,KAAK,EAAE,CAAC;IACxB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;CAClC,CAAC;AAeF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAgCvE;
|
|
1
|
+
{"version":3,"file":"trace-builder.d.ts","sourceRoot":"","sources":["../../src/lib/trace-builder.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kCAAkC,CAAC;AAc7D,eAAO,MAAM,WAAW,GAAI,WAAW,MAAM,YAAkC,CAAC;AAEhF,eAAO,MAAM,YAAY,GAAI,WAAW,MAAM,mDACkB,CAAC;AAEjE,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,oEAGvB,CAAC;AAMhC,MAAM,MAAM,aAAa,GAAG;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACrC,cAAc,EAAE,KAAK,EAAE,CAAC;IACxB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;CAClC,CAAC;AAeF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAgCvE;AAsED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,EAAE,CAAC;IAClE,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,KAAK,EAAE,EACf,GAAG,EAAE,IAAI,GACR,aAAa,CA6Bf"}
|
|
@@ -72,6 +72,7 @@ function buildSpans(run, groupedEvents, now, latestKnownTime) {
|
|
|
72
72
|
// unknown territory. Even when the run is completed, we may not have loaded
|
|
73
73
|
// all events yet, so always use the latest event we've actually seen.
|
|
74
74
|
const childMaxEnd = latestKnownTime;
|
|
75
|
+
const runMaxEnd = run.completedAt ?? now;
|
|
75
76
|
const stepSpans = Array.from(groupedEvents.eventsByStepId.values())
|
|
76
77
|
.map((events) => stepToSpan(events, childMaxEnd))
|
|
77
78
|
.filter((span) => span !== null);
|
|
@@ -79,7 +80,7 @@ function buildSpans(run, groupedEvents, now, latestKnownTime) {
|
|
|
79
80
|
.map((events) => hookToSpan(events, childMaxEnd))
|
|
80
81
|
.filter((span) => span !== null);
|
|
81
82
|
const waitSpans = Array.from(groupedEvents.timerEvents.values())
|
|
82
|
-
.map((events) => waitToSpan(events, childMaxEnd))
|
|
83
|
+
.map((events) => waitToSpan(events, childMaxEnd, runMaxEnd))
|
|
83
84
|
.filter((span) => span !== null);
|
|
84
85
|
return {
|
|
85
86
|
runSpan: runToSpan(run, groupedEvents.runLevelEvents, now),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trace-builder.js","sourceRoot":"","sources":["../../src/lib/trace-builder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Builds a complete trace from a WorkflowRun and its Events.\n *\n * This module groups raw events by correlation ID and entity type,\n * converts each group into an OpenTelemetry-style Span, and returns\n * a fully-formed Trace ready for the trace viewer.\n */\n\nimport type { Event, WorkflowRun } from '@workflow/world';\nimport type { Span } from '../components/trace-viewer/types';\nimport {\n hookToSpan,\n runToSpan,\n stepToSpan,\n waitToSpan,\n WORKFLOW_LIBRARY,\n} from '../components/workflow-traces/trace-span-construction';\nimport { otelTimeToMs } from '../components/workflow-traces/trace-time-utils';\n\n// ---------------------------------------------------------------------------\n// Event type classifiers\n// ---------------------------------------------------------------------------\n\nexport const isStepEvent = (eventType: string) => eventType.startsWith('step_');\n\nexport const isTimerEvent = (eventType: string) =>\n eventType === 'wait_created' || eventType === 'wait_completed';\n\nexport const isHookLifecycleEvent = (eventType: string) =>\n eventType === 'hook_received' ||\n eventType === 'hook_created' ||\n eventType === 'hook_disposed';\n\n// ---------------------------------------------------------------------------\n// Event grouping\n// ---------------------------------------------------------------------------\n\nexport type GroupedEvents = {\n eventsByStepId: Map<string, Event[]>;\n runLevelEvents: Event[];\n timerEvents: Map<string, Event[]>;\n hookEvents: Map<string, Event[]>;\n};\n\nfunction pushEvent(\n map: Map<string, Event[]>,\n correlationId: string,\n event: Event\n) {\n const existing = map.get(correlationId);\n if (existing) {\n existing.push(event);\n return;\n }\n map.set(correlationId, [event]);\n}\n\nexport function groupEventsByCorrelation(events: Event[]): GroupedEvents {\n const eventsByStepId = new Map<string, Event[]>();\n const runLevelEvents: Event[] = [];\n const timerEvents = new Map<string, Event[]>();\n const hookEvents = new Map<string, Event[]>();\n\n for (const event of events) {\n const correlationId = event.correlationId;\n if (!correlationId) {\n runLevelEvents.push(event);\n continue;\n }\n\n if (isTimerEvent(event.eventType)) {\n pushEvent(timerEvents, correlationId, event);\n continue;\n }\n\n if (isHookLifecycleEvent(event.eventType)) {\n pushEvent(hookEvents, correlationId, event);\n continue;\n }\n\n if (isStepEvent(event.eventType)) {\n pushEvent(eventsByStepId, correlationId, event);\n continue;\n }\n\n runLevelEvents.push(event);\n }\n\n return { eventsByStepId, runLevelEvents, timerEvents, hookEvents };\n}\n\n// ---------------------------------------------------------------------------\n// Trace construction\n// ---------------------------------------------------------------------------\n\n/**\n * Computes the latest known event time from the events list.\n * Active (in-progress) child spans are capped at this time instead of `now`,\n * so they only extend as far as our data goes.\n */\nfunction computeLatestKnownTime(events: Event[], run: WorkflowRun): Date {\n let latest = new Date(run.createdAt).getTime();\n for (const event of events) {\n const t = new Date(event.createdAt).getTime();\n if (t > latest) latest = t;\n }\n return new Date(latest);\n}\n\nfunction buildSpans(\n run: WorkflowRun,\n groupedEvents: GroupedEvents,\n now: Date,\n latestKnownTime: Date\n) {\n // Active child spans cap at latestKnownTime so they don't extend into\n // unknown territory. Even when the run is completed, we may not have loaded\n // all events yet, so always use the latest event we've actually seen.\n const childMaxEnd = latestKnownTime;\n\n const stepSpans = Array.from(groupedEvents.eventsByStepId.values())\n .map((events) => stepToSpan(events, childMaxEnd))\n .filter((span): span is Span => span !== null);\n\n const hookSpans = Array.from(groupedEvents.hookEvents.values())\n .map((events) => hookToSpan(events, childMaxEnd))\n .filter((span): span is Span => span !== null);\n\n const waitSpans = Array.from(groupedEvents.timerEvents.values())\n .map((events) => waitToSpan(events, childMaxEnd))\n .filter((span): span is Span => span !== null);\n\n return {\n runSpan: runToSpan(run, groupedEvents.runLevelEvents, now),\n spans: [...stepSpans, ...hookSpans, ...waitSpans],\n };\n}\n\nfunction cascadeSpans(runSpan: Span, spans: Span[]) {\n const sortedSpans = [\n runSpan,\n ...spans.slice().sort((a, b) => {\n const aStart = otelTimeToMs(a.startTime);\n const bStart = otelTimeToMs(b.startTime);\n return aStart - bStart;\n }),\n ];\n\n return sortedSpans.map((span, index) => {\n const parentSpanId =\n index === 0 ? undefined : String(sortedSpans[index - 1].spanId);\n return {\n ...span,\n parentSpanId,\n };\n });\n}\n\nexport interface TraceWithMeta {\n traceId: string;\n rootSpanId: string;\n spans: Span[];\n resources: { name: string; attributes: Record<string, string> }[];\n /** Duration in ms from trace start to the latest known event. */\n knownDurationMs: number;\n}\n\nexport function buildTrace(\n run: WorkflowRun,\n events: Event[],\n now: Date\n): TraceWithMeta {\n const groupedEvents = groupEventsByCorrelation(events);\n const latestKnownTime = computeLatestKnownTime(events, run);\n const { runSpan, spans } = buildSpans(\n run,\n groupedEvents,\n now,\n latestKnownTime\n );\n const sortedCascadingSpans = cascadeSpans(runSpan, spans);\n\n // Compute known duration relative to trace start\n const traceStartMs = otelTimeToMs(runSpan.startTime);\n const knownDurationMs = latestKnownTime.getTime() - traceStartMs;\n\n return {\n traceId: run.runId,\n rootSpanId: run.runId,\n spans: sortedCascadingSpans,\n resources: [\n {\n name: 'workflow',\n attributes: {\n 'service.name': WORKFLOW_LIBRARY.name,\n },\n },\n ],\n knownDurationMs: Math.max(0, knownDurationMs),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"trace-builder.js","sourceRoot":"","sources":["../../src/lib/trace-builder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Builds a complete trace from a WorkflowRun and its Events.\n *\n * This module groups raw events by correlation ID and entity type,\n * converts each group into an OpenTelemetry-style Span, and returns\n * a fully-formed Trace ready for the trace viewer.\n */\n\nimport type { Event, WorkflowRun } from '@workflow/world';\nimport type { Span } from '../components/trace-viewer/types';\nimport {\n hookToSpan,\n runToSpan,\n stepToSpan,\n waitToSpan,\n WORKFLOW_LIBRARY,\n} from '../components/workflow-traces/trace-span-construction';\nimport { otelTimeToMs } from '../components/workflow-traces/trace-time-utils';\n\n// ---------------------------------------------------------------------------\n// Event type classifiers\n// ---------------------------------------------------------------------------\n\nexport const isStepEvent = (eventType: string) => eventType.startsWith('step_');\n\nexport const isTimerEvent = (eventType: string) =>\n eventType === 'wait_created' || eventType === 'wait_completed';\n\nexport const isHookLifecycleEvent = (eventType: string) =>\n eventType === 'hook_received' ||\n eventType === 'hook_created' ||\n eventType === 'hook_disposed';\n\n// ---------------------------------------------------------------------------\n// Event grouping\n// ---------------------------------------------------------------------------\n\nexport type GroupedEvents = {\n eventsByStepId: Map<string, Event[]>;\n runLevelEvents: Event[];\n timerEvents: Map<string, Event[]>;\n hookEvents: Map<string, Event[]>;\n};\n\nfunction pushEvent(\n map: Map<string, Event[]>,\n correlationId: string,\n event: Event\n) {\n const existing = map.get(correlationId);\n if (existing) {\n existing.push(event);\n return;\n }\n map.set(correlationId, [event]);\n}\n\nexport function groupEventsByCorrelation(events: Event[]): GroupedEvents {\n const eventsByStepId = new Map<string, Event[]>();\n const runLevelEvents: Event[] = [];\n const timerEvents = new Map<string, Event[]>();\n const hookEvents = new Map<string, Event[]>();\n\n for (const event of events) {\n const correlationId = event.correlationId;\n if (!correlationId) {\n runLevelEvents.push(event);\n continue;\n }\n\n if (isTimerEvent(event.eventType)) {\n pushEvent(timerEvents, correlationId, event);\n continue;\n }\n\n if (isHookLifecycleEvent(event.eventType)) {\n pushEvent(hookEvents, correlationId, event);\n continue;\n }\n\n if (isStepEvent(event.eventType)) {\n pushEvent(eventsByStepId, correlationId, event);\n continue;\n }\n\n runLevelEvents.push(event);\n }\n\n return { eventsByStepId, runLevelEvents, timerEvents, hookEvents };\n}\n\n// ---------------------------------------------------------------------------\n// Trace construction\n// ---------------------------------------------------------------------------\n\n/**\n * Computes the latest known event time from the events list.\n * Active (in-progress) child spans are capped at this time instead of `now`,\n * so they only extend as far as our data goes.\n */\nfunction computeLatestKnownTime(events: Event[], run: WorkflowRun): Date {\n let latest = new Date(run.createdAt).getTime();\n for (const event of events) {\n const t = new Date(event.createdAt).getTime();\n if (t > latest) latest = t;\n }\n return new Date(latest);\n}\n\nfunction buildSpans(\n run: WorkflowRun,\n groupedEvents: GroupedEvents,\n now: Date,\n latestKnownTime: Date\n) {\n // Active child spans cap at latestKnownTime so they don't extend into\n // unknown territory. Even when the run is completed, we may not have loaded\n // all events yet, so always use the latest event we've actually seen.\n const childMaxEnd = latestKnownTime;\n const runMaxEnd = run.completedAt ?? now;\n\n const stepSpans = Array.from(groupedEvents.eventsByStepId.values())\n .map((events) => stepToSpan(events, childMaxEnd))\n .filter((span): span is Span => span !== null);\n\n const hookSpans = Array.from(groupedEvents.hookEvents.values())\n .map((events) => hookToSpan(events, childMaxEnd))\n .filter((span): span is Span => span !== null);\n\n const waitSpans = Array.from(groupedEvents.timerEvents.values())\n .map((events) => waitToSpan(events, childMaxEnd, runMaxEnd))\n .filter((span): span is Span => span !== null);\n\n return {\n runSpan: runToSpan(run, groupedEvents.runLevelEvents, now),\n spans: [...stepSpans, ...hookSpans, ...waitSpans],\n };\n}\n\nfunction cascadeSpans(runSpan: Span, spans: Span[]) {\n const sortedSpans = [\n runSpan,\n ...spans.slice().sort((a, b) => {\n const aStart = otelTimeToMs(a.startTime);\n const bStart = otelTimeToMs(b.startTime);\n return aStart - bStart;\n }),\n ];\n\n return sortedSpans.map((span, index) => {\n const parentSpanId =\n index === 0 ? undefined : String(sortedSpans[index - 1].spanId);\n return {\n ...span,\n parentSpanId,\n };\n });\n}\n\nexport interface TraceWithMeta {\n traceId: string;\n rootSpanId: string;\n spans: Span[];\n resources: { name: string; attributes: Record<string, string> }[];\n /** Duration in ms from trace start to the latest known event. */\n knownDurationMs: number;\n}\n\nexport function buildTrace(\n run: WorkflowRun,\n events: Event[],\n now: Date\n): TraceWithMeta {\n const groupedEvents = groupEventsByCorrelation(events);\n const latestKnownTime = computeLatestKnownTime(events, run);\n const { runSpan, spans } = buildSpans(\n run,\n groupedEvents,\n now,\n latestKnownTime\n );\n const sortedCascadingSpans = cascadeSpans(runSpan, spans);\n\n // Compute known duration relative to trace start\n const traceStartMs = otelTimeToMs(runSpan.startTime);\n const knownDurationMs = latestKnownTime.getTime() - traceStartMs;\n\n return {\n traceId: run.runId,\n rootSpanId: run.runId,\n spans: sortedCascadingSpans,\n resources: [\n {\n name: 'workflow',\n attributes: {\n 'service.name': WORKFLOW_LIBRARY.name,\n },\n },\n ],\n knownDurationMs: Math.max(0, knownDurationMs),\n };\n}\n"]}
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -6,17 +6,19 @@ export declare function cn(...inputs: ClassValue[]): string;
|
|
|
6
6
|
* Formats a duration in milliseconds to a human-readable string.
|
|
7
7
|
*
|
|
8
8
|
* @param ms - Duration in milliseconds
|
|
9
|
-
* @param compact - If true, returns a
|
|
10
|
-
* If false (default), returns multi-part format (e.g., "1m
|
|
9
|
+
* @param compact - If true, returns a compact format (e.g., "380ms", "2m 30s").
|
|
10
|
+
* If false (default), returns multi-part format (e.g., "1m 13s", "2d 5h 3m 12s").
|
|
11
11
|
*
|
|
12
12
|
* Compact format (timeline markers):
|
|
13
|
-
* - <
|
|
14
|
-
* - <
|
|
15
|
-
* -
|
|
13
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
14
|
+
* - < 1m: shows seconds (e.g., "45s")
|
|
15
|
+
* - < 1h: shows minutes and seconds (e.g., "2m 30s")
|
|
16
|
+
* - >= 1h: shows hours and minutes (e.g., "2h 30m")
|
|
16
17
|
*
|
|
17
18
|
* Full format:
|
|
18
|
-
* - <
|
|
19
|
-
* -
|
|
19
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
20
|
+
* - < 1m: shows seconds (e.g., "45s")
|
|
21
|
+
* - >= 1m: shows decomposed format with whole seconds (e.g., "1m 13s", "2m 13s")
|
|
20
22
|
*/
|
|
21
23
|
export declare function formatDuration(ms: number, compact?: boolean): string;
|
|
22
24
|
/**
|
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC;AAOD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,MAAM,CAgDlE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,GACf,MAAM,CAKR;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,GAAG,YAAY,EAAE,GAAG,IAAI,CAmB7E;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,CAc/D"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -3,13 +3,6 @@ import { twMerge } from 'tailwind-merge';
|
|
|
3
3
|
export function cn(...inputs) {
|
|
4
4
|
return twMerge(clsx(inputs));
|
|
5
5
|
}
|
|
6
|
-
// const compactFormatter = new Intl.NumberFormat(undefined, {
|
|
7
|
-
// maximumFractionDigits: 2,
|
|
8
|
-
// });
|
|
9
|
-
const secondsFormatter = new Intl.NumberFormat(undefined, {
|
|
10
|
-
minimumFractionDigits: 2,
|
|
11
|
-
maximumFractionDigits: 2,
|
|
12
|
-
});
|
|
13
6
|
const MS_IN_SECOND = 1000;
|
|
14
7
|
const MS_IN_MINUTE = 60 * MS_IN_SECOND;
|
|
15
8
|
const MS_IN_HOUR = 60 * MS_IN_MINUTE;
|
|
@@ -18,41 +11,48 @@ const MS_IN_DAY = 24 * MS_IN_HOUR;
|
|
|
18
11
|
* Formats a duration in milliseconds to a human-readable string.
|
|
19
12
|
*
|
|
20
13
|
* @param ms - Duration in milliseconds
|
|
21
|
-
* @param compact - If true, returns a
|
|
22
|
-
* If false (default), returns multi-part format (e.g., "1m
|
|
14
|
+
* @param compact - If true, returns a compact format (e.g., "380ms", "2m 30s").
|
|
15
|
+
* If false (default), returns multi-part format (e.g., "1m 13s", "2d 5h 3m 12s").
|
|
23
16
|
*
|
|
24
17
|
* Compact format (timeline markers):
|
|
25
|
-
* - <
|
|
26
|
-
* - <
|
|
27
|
-
* -
|
|
18
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
19
|
+
* - < 1m: shows seconds (e.g., "45s")
|
|
20
|
+
* - < 1h: shows minutes and seconds (e.g., "2m 30s")
|
|
21
|
+
* - >= 1h: shows hours and minutes (e.g., "2h 30m")
|
|
28
22
|
*
|
|
29
23
|
* Full format:
|
|
30
|
-
* - <
|
|
31
|
-
* -
|
|
24
|
+
* - < 1s: shows milliseconds (e.g., "380ms")
|
|
25
|
+
* - < 1m: shows seconds (e.g., "45s")
|
|
26
|
+
* - >= 1m: shows decomposed format with whole seconds (e.g., "1m 13s", "2m 13s")
|
|
32
27
|
*/
|
|
33
28
|
export function formatDuration(ms, compact = false) {
|
|
34
29
|
if (ms === 0) {
|
|
35
30
|
return '0s';
|
|
36
31
|
}
|
|
37
|
-
if (ms <
|
|
38
|
-
|
|
32
|
+
if (ms < MS_IN_SECOND) {
|
|
33
|
+
const roundedMs = Math.round(ms);
|
|
34
|
+
return roundedMs < MS_IN_SECOND ? `${roundedMs}ms` : '1s';
|
|
35
|
+
}
|
|
36
|
+
const roundedMs = Math.round(ms / MS_IN_SECOND) * MS_IN_SECOND;
|
|
37
|
+
if (roundedMs < MS_IN_MINUTE) {
|
|
38
|
+
return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;
|
|
39
39
|
}
|
|
40
40
|
// Compact format: multi-unit without decimals (e.g. "8m 20s", "2h 30m")
|
|
41
41
|
if (compact) {
|
|
42
|
-
if (
|
|
43
|
-
const m = Math.floor(
|
|
44
|
-
const s = Math.floor((
|
|
42
|
+
if (roundedMs < MS_IN_HOUR) {
|
|
43
|
+
const m = Math.floor(roundedMs / MS_IN_MINUTE);
|
|
44
|
+
const s = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
|
|
45
45
|
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
46
46
|
}
|
|
47
|
-
const h = Math.floor(
|
|
48
|
-
const m = Math.floor((
|
|
47
|
+
const h = Math.floor(roundedMs / MS_IN_HOUR);
|
|
48
|
+
const m = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
|
|
49
49
|
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
|
50
50
|
}
|
|
51
|
-
// Full format: decompose into larger units +
|
|
52
|
-
const days = Math.floor(
|
|
53
|
-
const hours = Math.floor((
|
|
54
|
-
const minutes = Math.floor((
|
|
55
|
-
const seconds = (
|
|
51
|
+
// Full format: decompose into larger units + whole seconds.
|
|
52
|
+
const days = Math.floor(roundedMs / MS_IN_DAY);
|
|
53
|
+
const hours = Math.floor((roundedMs % MS_IN_DAY) / MS_IN_HOUR);
|
|
54
|
+
const minutes = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);
|
|
55
|
+
const seconds = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);
|
|
56
56
|
const parts = [];
|
|
57
57
|
if (days > 0) {
|
|
58
58
|
parts.push(`${days}d`);
|
|
@@ -63,7 +63,7 @@ export function formatDuration(ms, compact = false) {
|
|
|
63
63
|
if (minutes > 0) {
|
|
64
64
|
parts.push(`${minutes}m`);
|
|
65
65
|
}
|
|
66
|
-
parts.push(`${
|
|
66
|
+
parts.push(`${seconds}s`);
|
|
67
67
|
return parts.join(' ');
|
|
68
68
|
}
|
|
69
69
|
/**
|
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Step } from '@workflow/world';\nimport type { ModelMessage } from 'ai';\nimport { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\nconst MS_IN_SECOND = 1000;\nconst MS_IN_MINUTE = 60 * MS_IN_SECOND;\nconst MS_IN_HOUR = 60 * MS_IN_MINUTE;\nconst MS_IN_DAY = 24 * MS_IN_HOUR;\n\n/**\n * Formats a duration in milliseconds to a human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @param compact - If true, returns a compact format (e.g., \"380ms\", \"2m 30s\").\n * If false (default), returns multi-part format (e.g., \"1m 13s\", \"2d 5h 3m 12s\").\n *\n * Compact format (timeline markers):\n * - < 1s: shows milliseconds (e.g., \"380ms\")\n * - < 1m: shows seconds (e.g., \"45s\")\n * - < 1h: shows minutes and seconds (e.g., \"2m 30s\")\n * - >= 1h: shows hours and minutes (e.g., \"2h 30m\")\n *\n * Full format:\n * - < 1s: shows milliseconds (e.g., \"380ms\")\n * - < 1m: shows seconds (e.g., \"45s\")\n * - >= 1m: shows decomposed format with whole seconds (e.g., \"1m 13s\", \"2m 13s\")\n */\nexport function formatDuration(ms: number, compact = false): string {\n if (ms === 0) {\n return '0s';\n }\n\n if (ms < MS_IN_SECOND) {\n const roundedMs = Math.round(ms);\n return roundedMs < MS_IN_SECOND ? `${roundedMs}ms` : '1s';\n }\n\n const roundedMs = Math.round(ms / MS_IN_SECOND) * MS_IN_SECOND;\n\n if (roundedMs < MS_IN_MINUTE) {\n return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;\n }\n\n // Compact format: multi-unit without decimals (e.g. \"8m 20s\", \"2h 30m\")\n if (compact) {\n if (roundedMs < MS_IN_HOUR) {\n const m = Math.floor(roundedMs / MS_IN_MINUTE);\n const s = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);\n return s > 0 ? `${m}m ${s}s` : `${m}m`;\n }\n const h = Math.floor(roundedMs / MS_IN_HOUR);\n const m = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);\n return m > 0 ? `${h}h ${m}m` : `${h}h`;\n }\n\n // Full format: decompose into larger units + whole seconds.\n const days = Math.floor(roundedMs / MS_IN_DAY);\n const hours = Math.floor((roundedMs % MS_IN_DAY) / MS_IN_HOUR);\n const minutes = Math.floor((roundedMs % MS_IN_HOUR) / MS_IN_MINUTE);\n const seconds = Math.floor((roundedMs % MS_IN_MINUTE) / MS_IN_SECOND);\n\n const parts: string[] = [];\n\n if (days > 0) {\n parts.push(`${days}d`);\n }\n if (hours > 0) {\n parts.push(`${hours}h`);\n }\n if (minutes > 0) {\n parts.push(`${minutes}m`);\n }\n parts.push(`${seconds}s`);\n\n return parts.join(' ');\n}\n\n/**\n * Returns a formatted pagination display string\n * @param currentPage - The current page number\n * @param totalPages - The total number of pages visited so far\n * @param hasMore - Whether there are more pages available\n * @returns Formatted string like \"Page 1 of 3+\" or \"Page 2 of 2\"\n */\nexport function getPaginationDisplay(\n currentPage: number,\n totalPages: number,\n hasMore: boolean\n): string {\n if (hasMore) {\n return `Page ${currentPage} of ${totalPages}+`;\n }\n return `Page ${currentPage} of ${totalPages}`;\n}\n\n// ============================================================================\n// Durable Agent Utilities\n// ============================================================================\n\n/**\n * Check if a step is a doStreamStep (LLM call with conversation input)\n */\nexport function isDoStreamStep(stepName: string): boolean {\n return stepName.endsWith('//doStreamStep');\n}\n\n/**\n * Extract the conversation from a hydrated doStreamStep input.\n * doStreamStep signature: (conversationPrompt, model, writable, tools, options)\n * So input[0] is the conversation.\n */\nexport function extractConversation(stepInput: unknown): ModelMessage[] | null {\n if (!Array.isArray(stepInput) || stepInput.length === 0) {\n return null;\n }\n\n const firstArg = stepInput[0];\n\n if (!Array.isArray(firstArg)) {\n return null;\n }\n\n // Validate it looks like ModelMessage[]\n if (\n !firstArg.every((msg) => msg && typeof msg === 'object' && 'role' in msg)\n ) {\n return null;\n }\n\n return firstArg as ModelMessage[];\n}\n\n/**\n * A doStreamStep with its conversation input extracted\n */\nexport interface StreamStep {\n stepId: string;\n stepName: string;\n displayName: string;\n conversation: ModelMessage[];\n}\n\n/**\n * Identifies all stream steps (doStreamStep) in a run and extracts their conversations.\n */\nexport function identifyStreamSteps(steps: Step[]): StreamStep[] {\n return steps\n .filter((step) => isDoStreamStep(step.stepName))\n .map((step) => {\n const functionName = step.stepName.split('//').pop() ?? 'unknown';\n const conversation = extractConversation(step.input) ?? [];\n\n return {\n stepId: step.stepId,\n stepName: step.stepName,\n displayName: functionName,\n conversation,\n };\n });\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.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.
|
|
57
|
-
"@workflow/utils": "5.0.0-beta.
|
|
58
|
-
"@workflow/world": "5.0.0-beta.
|
|
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": {
|