@siglo/monitor 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +514 -2
  3. package/dist/client.d.ts +53 -0
  4. package/dist/client.d.ts.map +1 -0
  5. package/dist/client.js +185 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/index.d.ts +13 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +29 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/metrics.d.ts +15 -0
  12. package/dist/metrics.d.ts.map +1 -0
  13. package/dist/metrics.js +79 -0
  14. package/dist/metrics.js.map +1 -0
  15. package/dist/middleware/express.d.ts +9 -0
  16. package/dist/middleware/express.d.ts.map +1 -0
  17. package/dist/middleware/express.js +33 -0
  18. package/dist/middleware/express.js.map +1 -0
  19. package/dist/middleware/fastify.d.ts +8 -0
  20. package/dist/middleware/fastify.d.ts.map +1 -0
  21. package/dist/middleware/fastify.js +29 -0
  22. package/dist/middleware/fastify.js.map +1 -0
  23. package/dist/middleware/hono.d.ts +8 -0
  24. package/dist/middleware/hono.d.ts.map +1 -0
  25. package/dist/middleware/hono.js +27 -0
  26. package/dist/middleware/hono.js.map +1 -0
  27. package/dist/server.d.ts +30 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +546 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/store.d.ts +19 -0
  32. package/dist/store.d.ts.map +1 -0
  33. package/dist/store.js +173 -0
  34. package/dist/store.js.map +1 -0
  35. package/dist/transports/redis.d.ts +26 -0
  36. package/dist/transports/redis.d.ts.map +1 -0
  37. package/dist/transports/redis.js +70 -0
  38. package/dist/transports/redis.js.map +1 -0
  39. package/dist/transports/sse.d.ts +24 -0
  40. package/dist/transports/sse.d.ts.map +1 -0
  41. package/dist/transports/sse.js +98 -0
  42. package/dist/transports/sse.js.map +1 -0
  43. package/dist/transports/websocket.d.ts +37 -0
  44. package/dist/transports/websocket.d.ts.map +1 -0
  45. package/dist/transports/websocket.js +277 -0
  46. package/dist/transports/websocket.js.map +1 -0
  47. package/dist/types.d.ts +131 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +3 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/ui/dashboard.d.ts +2 -0
  52. package/dist/ui/dashboard.d.ts.map +1 -0
  53. package/dist/ui/dashboard.js +43 -0
  54. package/dist/ui/dashboard.js.map +1 -0
  55. package/dist/wait-state.d.ts +12 -0
  56. package/dist/wait-state.d.ts.map +1 -0
  57. package/dist/wait-state.js +27 -0
  58. package/dist/wait-state.js.map +1 -0
  59. package/grafana/siglo-live-monitoring.json +109 -0
  60. package/package.json +54 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Jerico de guzman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,515 @@
1
- # Temporary Holding Version
1
+ # @siglo/monitor
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Real-time workflow telemetry server, modern React DevTools web dashboard, SSE/WebSocket streaming, and Prometheus metrics exporter for [Siglo](https://github.com/jsoftgem/siglo) workflows.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@siglo/monitor.svg)](https://www.npmjs.com/package/@siglo/monitor)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## 1. Overview
11
+
12
+ `@siglo/monitor` provides complete runtime observability, telemetry, and interactive developer tooling for `Siglo` workflows. It captures fine-grained execution events (`flow:start`, `step:start`, `step:complete`, `step:retry`, `step:error`, `step:skipped`, `flow:suspended`, `flow:resumed`, `context:change`, etc.) and streams them to a modern **React 18 + Vite + Tailwind CSS** DevTools dashboard, Server-Sent Events (SSE) clients, WebSockets, or distributed Redis pub/sub channels.
13
+
14
+ ```
15
+ +---------------------------+
16
+ | Siglo Workflow Run |
17
+ +-------------+-------------+
18
+ |
19
+ v
20
+ +--------------------+--------------------+
21
+ | Workflow Event Bus / Monitoring Adapter |
22
+ +--------------------+--------------------+
23
+ |
24
+ +-----------------------+-----------------------+
25
+ | |
26
+ v (SSE / WebSocket) v (Prometheus / Metrics)
27
+ +------------+------------+ +------------+------------+
28
+ | React DevTools UI | | Production Telemetry |
29
+ | - Live DAG Visualizer | | - Prometheus Metrics |
30
+ | - Context Diff Viewer | | - Grafana Dashboards |
31
+ | - Latency Waterfall | | - Multi-Worker Pub/Sub |
32
+ | - Interactive Resume | | |
33
+ +-------------------------+ +-------------------------+
34
+ ```
35
+
36
+ ### Key Capabilities
37
+
38
+ - ⚛️ **Modern React DevTools UI**: Built with React 18, Vite, and Tailwind CSS. Packaged as a self-contained, zero-dependency SPA with no external CDN or asset server required at runtime.
39
+ - 🔗 **Flexible Attachment**: Attach workflows to a newly created server, an active in-process server, or a remotely running server (e.g. started via CLI `siglo monitor`).
40
+ - 🗺️ **Interactive DAG Topology**: Dynamic visual representation of workflow steps, live execution states (pulsing running state, completed, failed, suspended), attempt counts, and step details inspector.
41
+ - ⏱️ **Latency Waterfall Timeline**: Visual duration breakdown of each step relative to total execution time with attempt indicators.
42
+ - 🔍 **Context & State Diff Inspector**: Syntax-highlighted JSON viewer tracking state mutations, initial input, and diff history with one-click clipboard copying.
43
+ - ⚡ **Interactive Durable Resumption**: Resume suspended workflows (`waitForEvent`) directly from the web UI with custom signal event names and JSON payloads.
44
+ - 🔄 **Replay Workflows**: Trigger execution replays directly from the dashboard or REST endpoints.
45
+ - 📡 **Multi-Transport Streaming**: Native Server-Sent Events (SSE) and RFC 6455 WebSockets with automatic reconnection, heartbeat pings, and connection tracking.
46
+ - 📊 **Prometheus Telemetry**: Standard `/metrics` endpoint exporting active flow gauges, completion counters, execution summaries, and step retry counters.
47
+ - 📈 **Pre-Packaged Grafana Dashboard**: Ready-to-import Grafana JSON template (`grafana/siglo-live-monitoring.json`).
48
+ - 🛡️ **Automated Data Redaction**: Automatic masking of sensitive fields (`password`, `token`, `secret`, `apiKey`) and tenant-isolated `$namespace` filtering.
49
+ - 🔌 **Framework Middlewares**: One-line integration for Express, Fastify, and Hono applications.
50
+
51
+ ---
52
+
53
+ ## 2. Installation
54
+
55
+ ```bash
56
+ npm install @siglo/monitor @siglo/core
57
+ ```
58
+
59
+ For developer CLI commands (`siglo monitor`):
60
+ ```bash
61
+ npm install --save-dev @siglo/cli
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 3. Quick Start: Standalone Dev Server
67
+
68
+ Start a standalone monitor server and attach it to your workflow runs:
69
+
70
+ ```typescript
71
+ import { Step, flow } from '@siglo/core';
72
+ import { createMonitorServer } from '@siglo/monitor';
73
+
74
+ async function main() {
75
+ // 1. Launch monitor server on port 4000
76
+ const monitor = await createMonitorServer({
77
+ port: 4000,
78
+ host: '0.0.0.0'
79
+ });
80
+
81
+ console.log(`Live DevTools available at: http://localhost:${monitor.port}`);
82
+
83
+ // 2. Define workflow steps
84
+ const fetchUser = Step.create('fetchUser', async () => ({ id: 'usr_100', name: 'Alice' }));
85
+ const chargeCard = Step.create('chargeCard', async (ctx) => {
86
+ return { charged: true, amount: 49.99 };
87
+ });
88
+
89
+ const orderPipeline = flow(fetchUser, chargeCard)
90
+ .monitor(monitor.emitter); // Attach live monitoring
91
+
92
+ // 3. Execute workflow
93
+ await orderPipeline.run({ orderId: 'ord_999' });
94
+ }
95
+
96
+ main();
97
+ ```
98
+
99
+ Open `http://localhost:4000` in your browser to inspect the interactive DAG, step latency waterfall, state diffs, and live event log in real time.
100
+
101
+ ---
102
+
103
+ ## 4. Attaching to an Already Running Monitor Server
104
+
105
+ Instead of spinning up a new HTTP server every time, workflows can attach to a monitor server that is **already running** (e.g. launched via the CLI `npm exec --package=@siglo/cli -- siglo monitor`, in a Docker container, or started once at application bootstrap).
106
+
107
+ ### Scenario A: Remote / Separate Process (CLI or Dedicated Server)
108
+
109
+ When your monitor server is running in a different process (such as `npm exec --package=@siglo/cli -- siglo monitor --port 4000` in another terminal):
110
+
111
+ ```typescript
112
+ import { flow } from '@siglo/core';
113
+ import { attachToMonitorServer } from '@siglo/monitor';
114
+
115
+ // Attach workflow directly to the running server by port or URL
116
+ const orderPipeline = flow(fetchUser, chargeCard)
117
+ .monitor(attachToMonitorServer('https://monitor.internal.corp:4000', {
118
+ apiKey: process.env.MONITOR_API_KEY
119
+ }));
120
+ // or local dev: .monitor(attachToMonitorServer(4000))
121
+
122
+ await orderPipeline.run({ orderId: 'ord_123' });
123
+ ```
124
+
125
+ Events are automatically dispatched asynchronously to the monitor server's `POST /api/events` endpoint without blocking your workflow execution or throwing errors if the server is temporarily unreachable.
126
+
127
+ ### Scenario B: Same Process (In-Memory Singleton / App Bootstrap)
128
+
129
+ If your application starts the monitor server once during startup, other files and services can connect without creating redundant HTTP servers:
130
+
131
+ ```typescript
132
+ import { flow } from '@siglo/core';
133
+ import { createMonitorServer, attachToMonitorServer, getMonitorEmitter } from '@siglo/monitor';
134
+
135
+ // In server startup file (e.g., server.ts):
136
+ const monitor = await createMonitorServer({
137
+ port: 4000,
138
+ reuseExisting: true // Reuses existing instance instead of throwing EADDRINUSE
139
+ });
140
+
141
+ // In any other file / workflow definition:
142
+ const orderPipeline = flow(fetchUser, chargeCard)
143
+ .monitor(attachToMonitorServer()); // Automatically resolves the active in-process server
144
+ ```
145
+
146
+ You can also retrieve the global emitter directly:
147
+ ```typescript
148
+ import { getMonitorEmitter } from '@siglo/monitor';
149
+
150
+ const emitter = getMonitorEmitter();
151
+ const orderPipeline = flow(fetchUser, chargeCard).monitor(emitter!);
152
+ ```
153
+
154
+ ### Scenario C: High-Throughput Remote Client
155
+
156
+ For distributed workers or background jobs pushing events to a central monitor server, use `createMonitorClient` to configure batching and debounce intervals:
157
+
158
+ ```typescript
159
+ import { createMonitorClient } from '@siglo/monitor';
160
+
161
+ const client = createMonitorClient({
162
+ url: 'http://monitor-service:4000',
163
+ batchSize: 20, // Flush when 20 events accumulate
164
+ flushIntervalMs: 50, // Or flush every 50ms
165
+ redaction: {
166
+ redactKeys: ['password', 'creditCard']
167
+ }
168
+ });
169
+
170
+ const orderPipeline = flow(fetchUser, chargeCard)
171
+ .monitor(client.monitor);
172
+ ```
173
+
174
+ ---
175
+
176
+ ## 5. Web Framework Middlewares
177
+
178
+ Embed the live monitoring UI and telemetry endpoints directly inside your existing web applications without running a separate server.
179
+
180
+ ### Express Integration
181
+
182
+ ```typescript
183
+ import express from 'express';
184
+ import { createExpressMonitorMiddleware } from '@siglo/monitor';
185
+
186
+ const app = express();
187
+
188
+ // Mount dashboard UI, /events SSE, and /api endpoints on /_siglo
189
+ app.use('/_siglo', createExpressMonitorMiddleware());
190
+
191
+ app.listen(3000, () => {
192
+ console.log('Monitor dashboard available at http://localhost:3000/_siglo');
193
+ });
194
+ ```
195
+
196
+ ### Fastify Integration
197
+
198
+ ```typescript
199
+ import Fastify from 'fastify';
200
+ import { fastifyMonitorPlugin } from '@siglo/monitor';
201
+
202
+ const fastify = Fastify();
203
+
204
+ await fastify.register(fastifyMonitorPlugin, { prefix: '/_siglo' });
205
+ await fastify.listen({ port: 3000 });
206
+ ```
207
+
208
+ ### Hono Integration
209
+
210
+ ```typescript
211
+ import { Hono } from 'hono';
212
+ import { honoMonitorMiddleware } from '@siglo/monitor';
213
+
214
+ const app = new Hono();
215
+
216
+ app.use('/_siglo/*', honoMonitorMiddleware());
217
+ ```
218
+
219
+ ---
220
+
221
+ ## 6. Live DevTools Dashboard Features
222
+
223
+ The web dashboard is a responsive single-page application built with React, Vite, and Tailwind CSS:
224
+
225
+ | View / Feature | Description |
226
+ |---|---|
227
+ | **Topology (DAG)** | Interactive step sequence diagram highlighting active nodes (`RUNNING`), completions, failures, and retry counters. Clicking a node opens an inspector with execution duration and errors. |
228
+ | **Latency Waterfall** | Horizontal timeline chart showing execution offset, relative latency, and attempt counts for each step. |
229
+ | **Context & State Diff** | Monospace JSON viewer with tabs for current state and chronological field mutations (`context:change`), plus one-click copy. |
230
+ | **Live Events Stream** | Chronological feed of all 14 Siglo events with filtering by event type and expandable raw payloads. |
231
+ | **Interactive Resume** | Modal for durable workflows suspended on `waitForEvent()`. Enter signal event name and JSON payload to resume execution. |
232
+ | **Replay Trigger** | One-click workflow replay button to re-trigger executions with recorded input context. |
233
+ | **Search & Status Filter** | Instant client-side search by flow name, namespace, or stack ID with status filter tabs (`ALL`, `RUNNING`, `SUSPENDED`, `FAILED`, `COMPLETED`). |
234
+ | **Multi-Tenant Filter** | Top header dropdown to isolate telemetry to a specific `$namespace`. |
235
+
236
+ ---
237
+
238
+ ## 7. Transports & Streaming
239
+
240
+ ### Server-Sent Events (SSE)
241
+
242
+ Clients can subscribe to `/events` for one-way live event streaming with automated heartbeat keep-alive:
243
+
244
+ ```javascript
245
+ const es = new EventSource('http://localhost:4000/events');
246
+
247
+ es.addEventListener('flow:start', (e) => {
248
+ console.log('Flow started:', JSON.parse(e.data));
249
+ });
250
+
251
+ es.addEventListener('step:complete', (e) => {
252
+ console.log('Step finished:', JSON.parse(e.data));
253
+ });
254
+
255
+ es.addEventListener('flow:suspended', (e) => {
256
+ console.log('Waiting for signal:', JSON.parse(e.data));
257
+ });
258
+ ```
259
+
260
+ Filter events by namespace via query parameter:
261
+ ```javascript
262
+ const es = new EventSource('http://localhost:4000/events?namespace=tenant-a');
263
+ ```
264
+
265
+ ### WebSocket Streaming
266
+
267
+ For bidirectional communication or interactive controls, connect to `ws://localhost:4000/ws`:
268
+
269
+ ```javascript
270
+ const ws = new WebSocket('ws://localhost:4000/ws');
271
+
272
+ ws.onmessage = (event) => {
273
+ const data = JSON.parse(event.data);
274
+ console.log('WebSocket event:', data);
275
+ };
276
+ ```
277
+
278
+ ---
279
+
280
+ ## 8. Distributed Monitoring with Redis Pub/Sub
281
+
282
+ When scaling workflows across multiple worker processes or Kubernetes pods, aggregate telemetry through Redis:
283
+
284
+ ```typescript
285
+ import { RedisMonitoringAdapter, createMonitorServer } from '@siglo/monitor';
286
+ import { WorkflowEventEmitter } from '@siglo/core';
287
+ import Redis from 'ioredis';
288
+
289
+ const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
290
+
291
+ // 1. In Worker Process: Publish events to Redis
292
+ const publisher = new Redis(redisUrl);
293
+ const workerAdapter = new RedisMonitoringAdapter({
294
+ publisher,
295
+ channel: 'siglo:monitor:events'
296
+ });
297
+
298
+ emitter.on('*', (event) => {
299
+ workerAdapter.publish(event);
300
+ });
301
+
302
+ // 2. In Central Monitor Server: Ingest events via subscriber and deliver to server emitter
303
+ const subscriber = new Redis(redisUrl);
304
+ const monitor = await createMonitorServer({ port: 4000 });
305
+
306
+ const serverAdapter = new RedisMonitoringAdapter({
307
+ subscriber,
308
+ channel: 'siglo:monitor:events',
309
+ emitter: monitor.emitter // Automatically routes incoming Redis events to monitor store & SSE
310
+ });
311
+ ```
312
+
313
+ ---
314
+
315
+ ## 9. Prometheus Metrics & Grafana
316
+
317
+ Expose standard Prometheus metrics for cluster alerting and visualization:
318
+
319
+ ```typescript
320
+ import { PrometheusExporter, createMonitorServer } from '@siglo/monitor';
321
+
322
+ const monitor = await createMonitorServer({ port: 4000 });
323
+
324
+ // GET /metrics exposes:
325
+ // - siglo_active_flows
326
+ // - siglo_flow_executions_total{status="completed|failed"}
327
+ // - siglo_flow_duration_seconds
328
+ // - siglo_step_retries_total
329
+ ```
330
+
331
+ Import the ready-to-use Grafana JSON dashboard located in:
332
+ [`grafana/siglo-live-monitoring.json`](./grafana/siglo-live-monitoring.json)
333
+
334
+ ---
335
+
336
+ ## 10. Security, Authentication & Production Hardening
337
+
338
+ When deploying `@siglo/monitor` across internal networks or attaching remote workers, apply production-grade security controls:
339
+
340
+ ### 10.1 API Key & Token Authentication
341
+ Protect telemetry ingestion, control-plane endpoints, and event streams with API keys:
342
+
343
+ ```typescript
344
+ const monitor = await createMonitorServer({
345
+ port: 4000,
346
+ auth: {
347
+ ingestionKey: 'ingest-secret-token', // Required for POST /api/events
348
+ adminKey: 'admin-secret-token', // Required for /resume, /replay, /api/workflows
349
+ }
350
+ // Or shorthand for general single key: auth: 'my-secret-key'
351
+ });
352
+ ```
353
+
354
+ Remote clients attach with their key:
355
+ ```typescript
356
+ const monitor = attachToMonitorServer('https://monitor.corp.internal:4000', {
357
+ apiKey: 'ingest-secret-token'
358
+ });
359
+ ```
360
+
361
+ The Web UI and SSE clients authenticate via `Authorization: Bearer <token>`, `X-API-Key: <token>`, or URL query parameter `?token=<token>`.
362
+
363
+ ### 10.2 Disabling Remote Control in Sensitive Environments
364
+ In production, disable interactive workflow resumption (`/resume`) and replays (`/replay`) to prevent remote state manipulation:
365
+
366
+ ```typescript
367
+ const monitor = await createMonitorServer({
368
+ allowRemoteResume: false // Returns 403 Forbidden on resume/replay
369
+ });
370
+ ```
371
+
372
+ ### 10.3 CORS Hardening
373
+ Restrict browser DevTools access to explicit trusted origins (preventing drive-by intranet CSRF):
374
+
375
+ ```typescript
376
+ const monitor = await createMonitorServer({
377
+ cors: {
378
+ origin: ['https://devtools.internal.corp', 'http://localhost:3000'],
379
+ credentials: true
380
+ }
381
+ });
382
+ ```
383
+
384
+ ### 10.4 Payload Caps & Client Memory Protection
385
+ - **Payload Limits**: Limits JSON ingestion payloads to 1MB (configurable via `maxPayloadBytes`). Exceeding requests receive `413 Payload Too Large`.
386
+ - **Bounded Client Queue**: Remote client automatically drops oldest events if telemetry buffer exceeds `maxQueueSize` (default: 1000) when the network is slow or unreachable.
387
+
388
+ ### 10.5 Context & Credential Redaction
389
+ Prevent sensitive credentials, API keys, or personal identifiable information (PII) from leaking to dashboards and event streams:
390
+
391
+ ```typescript
392
+ const monitor = await createMonitorServer({
393
+ redaction: {
394
+ redactKeys: ['apiKey', 'password', 'creditCard', 'secret', 'token'],
395
+ redactHook: (key, val) => {
396
+ if (key === 'email') return val.replace(/(?<=.).(?=[^@]*?@)/g, '*');
397
+ return undefined; // use default '[REDACTED]'
398
+ }
399
+ }
400
+ });
401
+ ```
402
+
403
+ ---
404
+
405
+ ## 11. Dashboard UI Development (React + Vite + Tailwind)
406
+
407
+ The live monitor web interface source code is located in [`packages/monitor/ui`](./ui) and adheres to modular, industry-standard frontend architecture.
408
+
409
+ ### Tech Stack
410
+ - **React 18** with typed hooks and functional components
411
+ - **Tailwind CSS** for dark-mode DevTools styling
412
+ - **Lucide React** for icons
413
+ - **Vite** with `vite-plugin-singlefile` for self-contained distribution
414
+
415
+ ### Directory Layout
416
+ ```
417
+ packages/monitor/ui/
418
+ ├── src/
419
+ │ ├── api/
420
+ │ │ └── workflowApi.ts # REST client for workflow fetch, resume, and replay
421
+ │ ├── constants/
422
+ │ │ ├── events.ts # Siglo event types enumeration
423
+ │ │ └── status.ts # Workflow status filters list
424
+ │ ├── hooks/
425
+ │ │ ├── useWorkflowMonitor.ts # SSE connection, event reducer & state sync hook
426
+ │ │ └── useClipboard.ts # Clipboard copy helper with timeout
427
+ │ ├── types/
428
+ │ │ ├── workflow.ts # WorkflowRun, StepRun, ContextDiff types
429
+ │ │ ├── events.ts # MonitoringEvent, SigloEventType types
430
+ │ │ └── index.ts # Centralized type exports
431
+ │ ├── utils/
432
+ │ │ └── formatters.ts # Time, duration, ID, and JSON formatters
433
+ │ ├── components/
434
+ │ │ ├── ui/ # Reusable design system atoms
435
+ │ │ │ ├── StatusBadge.tsx # Color-coded status badge
436
+ │ │ │ ├── Modal.tsx # Accessible dialog modal
437
+ │ │ │ └── EmptyState.tsx # Empty state illustration card
438
+ │ │ ├── layout/ # Layout shells
439
+ │ │ │ └── Header.tsx # Navigation header & SSE connectivity badge
440
+ │ │ └── workflows/ # Feature-specific components
441
+ │ │ ├── RunList/ # Workflow execution sidebar & filters
442
+ │ │ ├── Dag/ # Interactive DAG topology visualizer
443
+ │ │ ├── Waterfall/ # Latency waterfall chart
444
+ │ │ ├── Context/ # Context JSON & mutation diff inspector
445
+ │ │ ├── Events/ # Live streaming telemetry log
446
+ │ │ ├── ResumeModal/ # Resumption modal dialog
447
+ │ │ ├── Stats/ # High-level metrics grid
448
+ │ │ └── WorkflowDetail.tsx # Tabbed workflow execution view
449
+ │ ├── App.tsx # Root layout orchestrator
450
+ │ ├── main.tsx # React DOM entry point
451
+ │ └── index.css # Tailwind base & utilities
452
+ ├── scripts/
453
+ │ └── embed-html.js # Inlines dist/index.html into src/ui/dashboard.ts
454
+ ├── vite.config.ts # Vite config with backend proxy and singlefile plugin
455
+ ├── tailwind.config.js # Tailwind configuration
456
+ └── package.json
457
+ ```
458
+
459
+ ### Local Development Server
460
+
461
+ Run Vite with hot module replacement (HMR) and backend proxy forwarding `/events` and `/api` to `http://localhost:4000`:
462
+
463
+ ```bash
464
+ npm run dev:ui
465
+ ```
466
+
467
+ ### Production Build
468
+
469
+ Builds the SPA into a single inlined bundle and updates [`src/ui/dashboard.ts`](./src/ui/dashboard.ts):
470
+
471
+ ```bash
472
+ npm run build:ui
473
+ ```
474
+
475
+ ---
476
+
477
+ ## 12. REST API Reference
478
+
479
+ The monitor server exposes REST endpoints for programmatic inspection and control:
480
+
481
+ | Method | Endpoint | Description |
482
+ |---|---|---|
483
+ | `GET` | `/` or `/index.html` | Serves the single-page DevTools web dashboard |
484
+ | `GET` | `/events` | Server-Sent Events (SSE) stream (`?namespace=...`) |
485
+ | `POST` | `/api/events` | Ingests telemetry events from external processes / clients |
486
+ | `GET` | `/metrics` | Prometheus metrics exposition format |
487
+ | `GET` | `/api/workflows` | List recorded workflow runs (`?namespace=...&status=...`) |
488
+ | `GET` | `/api/workflows/:stackId` | Get execution details and step history for a workflow |
489
+ | `POST` | `/api/workflows/:stackId/resume` | Resume a suspended workflow (`{ eventName, payload }`) |
490
+ | `POST` | `/api/workflows/:stackId/replay` | Trigger replay of a recorded workflow |
491
+
492
+ ---
493
+
494
+ ## 13. Programmatic API Reference
495
+
496
+ ### `attachToMonitorServer(target?: string | number | MonitorServerInstance | MonitorClientOptions): (event: WorkflowExecutionEvent) => void`
497
+ Convenient hook to attach a workflow to a running monitor server (in-process or remote over HTTP).
498
+
499
+ ### `createMonitorClient(options?: MonitorClientOptions): MonitorClientInstance`
500
+ Creates a remote client with configurable buffering and auto-flush to stream events to an external monitor server.
501
+
502
+ ### `getActiveMonitorServer(port?: number): MonitorServerInstance | undefined`
503
+ Returns the active in-process monitor server instance.
504
+
505
+ ### `getMonitorEmitter(port?: number): WorkflowEventEmitter | undefined`
506
+ Returns the event emitter of the currently active in-process monitor server.
507
+
508
+ ### `createMonitorServer(options?: MonitorServerOptions): Promise<MonitorServerInstance>`
509
+ Creates and starts an HTTP monitor server. Supports `reuseExisting: true` to reuse an already running instance.
510
+
511
+ ---
512
+
513
+ ## 14. License
514
+
515
+ MIT &copy; Jerico de Guzman
@@ -0,0 +1,53 @@
1
+ import { WorkflowEventEmitter, WorkflowExecutionEvent } from '@siglo/core';
2
+ import { MonitorClientOptions, MonitorClientInstance } from './types';
3
+ import { MonitorServerInstance } from './server';
4
+ export declare class RemoteMonitorClient implements MonitorClientInstance {
5
+ readonly emitter: WorkflowEventEmitter;
6
+ private readonly baseUrl;
7
+ private readonly batchSize;
8
+ private readonly flushIntervalMs;
9
+ private readonly redaction?;
10
+ private readonly apiKey?;
11
+ private readonly customHeaders;
12
+ private readonly maxQueueSize;
13
+ private queue;
14
+ private flushTimer;
15
+ private isClosing;
16
+ private activeFlushPromise;
17
+ constructor(options?: MonitorClientOptions);
18
+ monitor: (event: WorkflowExecutionEvent) => void;
19
+ sendEvent(event: WorkflowExecutionEvent): Promise<void>;
20
+ private queueEvent;
21
+ flush(): Promise<void>;
22
+ close(): Promise<void>;
23
+ }
24
+ /**
25
+ * Creates a client that streams workflow telemetry to an external or running monitor server.
26
+ */
27
+ export declare function createMonitorClient(options?: MonitorClientOptions): MonitorClientInstance;
28
+ /**
29
+ * Attaches a workflow to an already running monitor server.
30
+ *
31
+ * Supports:
32
+ * - No arguments: Attaches to the active in-process server if running, or defaults to http://127.0.0.1:4000.
33
+ * - Port number (e.g. 4000): Attaches to the in-process server on that port if present, or connects over HTTP.
34
+ * - URL string (e.g. 'http://localhost:4000'): Connects to the remote monitor server over HTTP.
35
+ * - MonitorServerInstance: Directly pipes events into the server's event emitter in memory.
36
+ * - MonitorClientOptions: Configures remote batching and connection parameters.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // 1. Attach to running server on default port (4000)
41
+ * const orderFlow = flow(step1, step2).monitor(attachToMonitorServer());
42
+ *
43
+ * // 2. Attach to authenticated remote monitor server
44
+ * const orderFlow = flow(step1, step2).monitor(attachToMonitorServer('https://monitor.corp.internal:4000', {
45
+ * apiKey: 'secret-token'
46
+ * }));
47
+ *
48
+ * // 3. Attach by port
49
+ * const orderFlow = flow(step1, step2).monitor(attachToMonitorServer(4000));
50
+ * ```
51
+ */
52
+ export declare function attachToMonitorServer(target?: string | number | MonitorServerInstance | MonitorClientOptions, clientOptions?: MonitorClientOptions): (event: WorkflowExecutionEvent) => void;
53
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAiC,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAA0B,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEzE,qBAAa,mBAAoB,YAAW,qBAAqB;IAC7D,SAAgB,OAAO,EAAE,oBAAoB,CAAC;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyB;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAA8B;gBAE5C,OAAO,GAAE,oBAAyB;IAuBvC,OAAO,UAAW,sBAAsB,KAAG,IAAI,CAEpD;IAEW,SAAS,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpE,OAAO,CAAC,UAAU;IAqBL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2CtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAItC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,qBAAqB,CAE7F;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,qBAAqB,GAAG,oBAAoB,EACvE,aAAa,CAAC,EAAE,oBAAoB,GACrC,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CA8CzC"}