Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/old-hats-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@workflow/web-shared": patch
"@workflow/web": patch
---

Add workflow graph visualization to observability UI and o11y migration to nuqs for url state management
2 changes: 1 addition & 1 deletion packages/web-shared/src/api/workflow-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const getErrorMessage = (error: Error | WorkflowAPIError): string => {
/**
* Helper to handle server action results and throw WorkflowAPIError on failure
*/
function unwrapServerActionResult<T>(result: {
export function unwrapServerActionResult<T>(result: {
success: boolean;
data?: T;
error?: ServerActionError;
Expand Down
35 changes: 35 additions & 0 deletions packages/web-shared/src/api/workflow-server-actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use server';

import fs from 'node:fs/promises';
import path from 'node:path';
import { hydrateResourceIO } from '@workflow/core/observability';
import { createWorld, start } from '@workflow/core/runtime';
import type {
Expand Down Expand Up @@ -499,3 +501,36 @@ export async function readStreamServerAction(
};
}
}

/**
* Fetch the workflows manifest from the data directory
* The manifest is generated at build time and contains static structure info about workflows
*/
export async function fetchWorkflowsManifest(
worldEnv: EnvMap
): Promise<ServerActionResult<any>> {
try {
// Get the data directory from the world environment config
// This contains the correct absolute path passed from the client
const dataDir =
worldEnv.WORKFLOW_EMBEDDED_DATA_DIR ||
process.env.WORKFLOW_EMBEDDED_DATA_DIR ||
'.next/workflow-data';

// If dataDir is absolute, use it directly; otherwise join with cwd
const fullPath = path.isAbsolute(dataDir)
? path.join(dataDir, 'workflows.json')
: path.join(process.cwd(), dataDir, 'workflows.json');

const content = await fs.readFile(fullPath, 'utf-8');
const manifest = JSON.parse(content);

return createResponse(manifest);
} catch (error) {
console.error('Failed to fetch workflows manifest:', error);
return {
success: false,
error: createServerActionError(error, 'fetchWorkflowsManifest', {}),
};
}
}
5 changes: 5 additions & 0 deletions packages/web-shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ export {

export type { Event, Hook, Step, WorkflowRun } from '@workflow/world';
export * from './api/workflow-api-client';
export type { EnvMap } from './api/workflow-server-actions';
export {
fetchEventsByCorrelationId,
fetchWorkflowsManifest,
} from './api/workflow-server-actions';
export { RunTraceView } from './run-trace-view';
export type { Span, SpanEvent } from './trace-viewer/types';
export { WorkflowTraceViewer } from './workflow-trace-view';
7 changes: 6 additions & 1 deletion packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
"format": "biome format --write"
},
"dependencies": {
"next": "15.5.4"
"next": "15.5.4",
"nuqs": "^2.2.5",
"@xyflow/react": "12.9.3"
},
"devDependencies": {
"@biomejs/biome": "catalog:",
Expand All @@ -36,6 +38,9 @@
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-switch": "1.1.2",
"@radix-ui/react-tooltip": "1.2.8",
"@radix-ui/react-dialog": "1.1.15",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-dropdown-menu": "2.1.6",
"@tailwindcss/postcss": "4",
"@types/node": "catalog:",
"@types/react": "19",
Expand Down
Loading
Loading