agentglow 0.3.2 → 0.4.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.
@@ -1,3 +1,5 @@
1
+ import { type Backlog, type PrimEdge, type PrimState, type PrimWorldEvent, type ResStat } from "./prims";
2
+ export type { PrimState, PrimWorldEvent } from "./prims";
1
3
  export type AgentType = "planner" | "researcher" | "graph_scout" | "records_scout" | "data_scout" | "writer";
2
4
  /** Any workflow-defined step name (the backend scrubs and caps it). */
3
5
  export type StepName = string;
@@ -10,7 +12,14 @@ export type WorldEvent = {
10
12
  topic: string;
11
13
  workflow: string;
12
14
  ts: number;
15
+ reason?: string;
13
16
  } | {
17
+ type: "run";
18
+ run_id: string;
19
+ status: "idle" | "active";
20
+ since?: number;
21
+ ts: number;
22
+ } | ({
14
23
  type: "step";
15
24
  run_id: string;
16
25
  step: StepName;
@@ -18,13 +27,15 @@ export type WorldEvent = {
18
27
  reason?: string;
19
28
  until?: number;
20
29
  ts: number;
21
- } | {
30
+ } & WaitExtra) | {
22
31
  type: "spawn";
23
32
  run_id: string;
24
33
  id: string;
25
34
  agent: string;
26
35
  parent_id: string | null;
27
36
  subagent?: boolean;
37
+ job?: boolean;
38
+ since?: number;
28
39
  ts: number;
29
40
  } | {
30
41
  type: "exit";
@@ -32,7 +43,7 @@ export type WorldEvent = {
32
43
  id: string;
33
44
  status: "done" | "failed";
34
45
  ts: number;
35
- } | {
46
+ } | ({
36
47
  type: "agent";
37
48
  run_id: string;
38
49
  id: string;
@@ -40,7 +51,7 @@ export type WorldEvent = {
40
51
  reason?: string;
41
52
  until?: number;
42
53
  ts: number;
43
- } | {
54
+ } & WaitExtra) | {
44
55
  type: "llm";
45
56
  run_id: string;
46
57
  id: string;
@@ -57,6 +68,7 @@ export type WorldEvent = {
57
68
  to_id: string;
58
69
  text: string;
59
70
  ts: number;
71
+ failed?: boolean;
60
72
  } | {
61
73
  type: "tool";
62
74
  run_id: string;
@@ -106,6 +118,7 @@ export type WorldEvent = {
106
118
  purpose?: string;
107
119
  target?: string;
108
120
  scope?: string;
121
+ threshold?: number;
109
122
  ms: number;
110
123
  ts: number;
111
124
  hv?: boolean;
@@ -121,6 +134,40 @@ export type WorldEvent = {
121
134
  p95_ms: number;
122
135
  providers: Record<string, number>;
123
136
  ts: number;
137
+ } | {
138
+ type: "request";
139
+ run_id: string;
140
+ id: string;
141
+ service: string;
142
+ name: string;
143
+ kind: "http" | "rpc" | "message" | "event";
144
+ status?: number;
145
+ error: boolean;
146
+ rejected?: boolean;
147
+ ms: number;
148
+ ts: number;
149
+ hv?: boolean;
150
+ } | {
151
+ type: "service_stats";
152
+ run_id: string;
153
+ id: string;
154
+ service: string;
155
+ window_ms: number;
156
+ n: number;
157
+ errors: number;
158
+ codes: Record<string, number>;
159
+ p50_ms: number;
160
+ p95_ms: number;
161
+ routes: Record<string, number>;
162
+ ts: number;
163
+ instances?: number;
164
+ inflight?: number;
165
+ } | {
166
+ type: "drives";
167
+ run_id: string;
168
+ id: string;
169
+ target_run: string;
170
+ ts: number;
124
171
  } | {
125
172
  type: "order";
126
173
  run_id: string;
@@ -153,8 +200,33 @@ export type WorldEvent = {
153
200
  ts: number;
154
201
  resource?: string;
155
202
  resource_kind?: ResourceKind;
156
- };
203
+ units?: number;
204
+ unit?: string;
205
+ device?: string;
206
+ } | PrimWorldEvent;
157
207
  export type DecisionKind = "choice" | "score" | "noul";
208
+ /** The decision that triggered a wait (docs/SPEC.md "Human approval"): a summary of its `decision` event. */
209
+ export type WaitBecause = {
210
+ id?: string;
211
+ kind: string;
212
+ question: string;
213
+ result: string;
214
+ p?: number;
215
+ provider?: string;
216
+ purpose?: string;
217
+ target?: string;
218
+ threshold?: number;
219
+ ms?: number;
220
+ ts?: number;
221
+ };
222
+ /** A declared wait's drawer fields (`agentglow.wait.*`): `kind` "approval" = a human approval ("Needs you"). */
223
+ export type WaitExtra = {
224
+ kind?: string;
225
+ title?: string;
226
+ details?: Record<string, string | number | boolean>;
227
+ url?: string;
228
+ because?: WaitBecause;
229
+ };
158
230
  export type DecisionStatsByPurpose = {
159
231
  route?: {
160
232
  n: number;
@@ -195,6 +267,9 @@ export type HvStats = {
195
267
  provider: string;
196
268
  n: number;
197
269
  windows: number;
270
+ unit?: "req" | "msg";
271
+ instances?: number;
272
+ inflight?: number;
198
273
  };
199
274
  /** outcome categories of a decision halo arc: allow, deny, check yes, check no, route result slots 0..3, other */
200
275
  export declare const HALO_CATS: readonly ["allow", "deny", "yes", "no", "r0", "r1", "r2", "r3", "other"];
@@ -206,10 +281,27 @@ export declare const HV_QUIET_MS = 2500;
206
281
  export declare const HV_FADE_MS = 1500;
207
282
  /** 0..1 visibility of an agent's decision halo */
208
283
  export declare function haloMix(h: HvStats | null, now?: number): number;
284
+ /** a backend service with no traffic for this long (ms) reads as idle: dimmed, label `feed · idle` */
285
+ export declare const SVC_IDLE_MS = 10000;
286
+ /** a top-level backend service agent (`svc:` id) */
287
+ export declare const isSvc: (i: Instance) => boolean;
288
+ /** a backend service with no requests / messages in the last SVC_IDLE_MS (or none since it appeared) */
289
+ export declare const svcIdle: (i: Instance, now?: number) => boolean;
209
290
  /** the agent is in high-volume mode now (recent decision_stats) */
210
291
  export declare const hvActive: (i: Instance, now?: number) => boolean;
211
- /** `jev 42/s · 3% deny · p50 38ms` */
292
+ /** The halo label: rate + error / deny share (only when > 0): `jev 42/s · 3% deny`; a service: `42 req/s · 2% errors`
293
+ * (`msg/s` for a consumer). Latency lives in the Selected panel and the label's hover tooltip (`haloLatency`). */
212
294
  export declare function haloText(h: HvStats): string;
295
+ /** `3% deny` / `2% errors` / "" when none */
296
+ export declare function haloShare(h: HvStats): string;
297
+ /** `p50 38ms · p95 120ms` (+ `· 3 in flight` for a service) */
298
+ export declare function haloLatency(h: HvStats): string;
299
+ /** `2m14s` / `38s` / `1h05m` */
300
+ export declare function elapsedText(ms: number): string;
301
+ /** a job's name label: `mkt:tick · 2m14s` (frozen at its end) */
302
+ export declare const jobText: (i: Instance) => string;
303
+ /** a job's end flash 0..1 (green done / red failed), ~1.2 s */
304
+ export declare const flashMix: (i: Instance, now?: number) => number;
213
305
  /** One decision on one agent; `at` (performance.now()) = when its glyph starts (staggered so a burst reads one by one). */
214
306
  export type DecisionUse = Omit<Extract<WorldEvent, {
215
307
  type: "decision";
@@ -272,7 +364,10 @@ export declare function orderText(o: {
272
364
  status?: string;
273
365
  }): string;
274
366
  /** What sits behind an MCP server (the server is a node; its backends are nodes too). */
275
- export type ResourceKind = "db" | "warehouse" | "spark" | "api" | "storage" | "queue";
367
+ export type ResourceKind = "db" | "warehouse" | "spark" | "api" | "storage" | "queue" | "model" | "gpu" | "worker" | "cache";
368
+ /** the six shapes every theme draws: newer kinds map onto the closest one (model / gpu -> spark, worker -> storage, cache -> db) */
369
+ export type ShapeKind = "db" | "warehouse" | "spark" | "api" | "storage" | "queue";
370
+ export declare const shapeKind: (k: string | undefined) => ShapeKind;
276
371
  export declare const AGENT_TYPES: {
277
372
  type: AgentType;
278
373
  label: string;
@@ -335,12 +430,34 @@ export type Instance = {
335
430
  }[];
336
431
  /** what it is waiting on (status "waiting" with a reason), else null */
337
432
  wait: Wait | null;
433
+ /** backend service agent: requests / errors handled (from `service_stats`) */
434
+ svcN?: number;
435
+ svcErr?: number;
436
+ /** backend service agent: performance.now() of its last traffic (requests / messages in or out); see svcIdle */
437
+ svcAt?: number;
438
+ /** a long-running request of a service shown as its subagent: started / ended (epoch ms, end 0 while open) */
439
+ job?: {
440
+ since: number;
441
+ end: number;
442
+ };
443
+ /** a job just ended: its halo flashes green (ok) / red (performance.now()) */
444
+ flash?: {
445
+ at: number;
446
+ ok: boolean;
447
+ };
448
+ /** generic primitives (prims.ts): created on the instance's first primitive event */
449
+ prim?: PrimState;
338
450
  };
339
451
  /** A declared wait: what it waits on ("approval", "sleep", an event key) and its deadline / wake-up (epoch ms, 0 = none). */
340
452
  export type Wait = {
341
453
  reason: string;
342
454
  until: number;
343
- };
455
+ } & WaitExtra;
456
+ /** reason / until + the drawer fields of a waiting `step` / `agent` event */
457
+ export declare function waitOf(ev: {
458
+ reason?: string;
459
+ until?: number;
460
+ } & WaitExtra): Wait;
344
461
  /** one skill on one agent; startAt / endAt (performance.now()) drive its sigil ring (endAt 0 while active) */
345
462
  export type SkillUse = {
346
463
  active: boolean;
@@ -389,6 +506,8 @@ export type Run = {
389
506
  final: string;
390
507
  /** performance.now() of the run's latest event (stale detection) */
391
508
  lastEventAt: number;
509
+ /** server-declared idle since (epoch ms of its last event), 0 = active (isIdle / idleText) */
510
+ idleSince: number;
392
511
  };
393
512
  /** Which of the 3 scene slots a step is drawn in (see STEP_SLOTS). */
394
513
  export declare function stepSlot(r: Run, step: StepName): number;
@@ -406,6 +525,17 @@ export declare function runWait(r: Run): (Wait & {
406
525
  * STALE_GRACE_MS (e.g. its worker restarted mid-run: nobody will resolve the wait or end the run). */
407
526
  export declare const STALE_QUIET_MS = 20000;
408
527
  export declare const STALE_GRACE_MS = 15000;
528
+ /** Idle run (server `run` status "idle"): its agents are dimmed (IDLE_DIM) and its label says "idle · 4m". */
529
+ export declare const IDLE_DIM = 0.55;
530
+ export declare const isIdle: (r: Run | undefined) => boolean;
531
+ export declare function idleText(r: Run, wall?: number): string;
532
+ export declare const isDismissed: (runId: string | undefined) => boolean;
533
+ /** Hide a run (and its agents) for this viewer. */
534
+ export declare function dismissRun(runId: string): void;
535
+ /** Show the given runs again (all dismissed ones when omitted). */
536
+ export declare function undismissRuns(ids?: string[]): void;
537
+ /** Dismissed runs that are still in the world (the HUD's "N hidden" chip). */
538
+ export declare const dismissedRuns: () => string[];
409
539
  export declare function isStale(r: Run | undefined, now?: number, wall?: number): boolean;
410
540
  export declare const STALE_TEXT = "stale: no worker activity";
411
541
  export declare function waitLabel(w: Wait, now?: number): string;
@@ -421,11 +551,21 @@ export type Comet = {
421
551
  start: number;
422
552
  dur: number;
423
553
  text: string;
554
+ failed?: boolean;
424
555
  };
556
+ /** a failed comet (a publish that raised) sputters out half way: it stalls here and is gone at FIZZLE_END of its life */
557
+ export declare const FIZZLE_STALL = 0.55;
558
+ export declare const FIZZLE_END = 0.8;
559
+ /** path parameter (0..1, before a theme's easing) of a comet: a failed one decelerates to the midpoint and stops */
560
+ export declare function cometPos(c: Comet, now?: number): number;
561
+ /** the comet head is still drawn (a failed one never arrives: no arrival flash) */
562
+ export declare const cometOn: (c: Comet, now?: number) => boolean;
425
563
  /** External MCP servers agents call (persistent "satellites"; registered on first use). */
564
+ /** `kind` = the shape themes draw (shapeKind), `sub` = the reported kind (model, gpu, worker, cache, ...) */
426
565
  export type McpResource = {
427
566
  name: string;
428
- kind: ResourceKind;
567
+ kind: ShapeKind;
568
+ sub: ResourceKind;
429
569
  activeAt: number;
430
570
  inflight: number;
431
571
  calls: number;
@@ -522,6 +662,9 @@ export declare const world: {
522
662
  mcpCalls: number;
523
663
  decisions: number;
524
664
  decisionMs: number;
665
+ requests: number;
666
+ errors: number;
667
+ rejected: number;
525
668
  };
526
669
  /** decisions per provider (jev / laya / llm ...): count + summed latency (HUD chip tooltip) */
527
670
  decisionProviders: Map<string, {
@@ -580,7 +723,32 @@ export declare const world: {
580
723
  unauthorized: boolean;
581
724
  /** desk-wide halts (global-scope guard denies, see Halt), keyed by the owning agent */
582
725
  halts: Map<string, Halt>;
726
+ /** transient dashed edges: fallbacks and completed deferred callbacks (prims.ts) */
727
+ primEdges: PrimEdge[];
728
+ /** broker backlog per topic (prims.ts) */
729
+ backlogs: Map<string, Backlog>;
730
+ /** resource stats (pools, caches, models) keyed `server|resource` */
731
+ resStats: Map<string, ResStat>;
732
+ /** message topics between two services (`mkt:tick` feed -> worker), keyed `from|to|topic`: a persistent edge */
733
+ topics: Map<string, SvcTopic>;
734
+ /** service -> agent run it drives (`drives`), keyed `svc|run` */
735
+ drives: Map<string, {
736
+ svc: string;
737
+ run: string;
738
+ }>;
739
+ };
740
+ /** A topic between two services: first / last message (performance.now()), messages seen, the last one failed. */
741
+ export type SvcTopic = {
742
+ from: string;
743
+ to: string;
744
+ topic: string;
745
+ first: number;
746
+ at: number;
747
+ n: number;
748
+ failed: boolean;
583
749
  };
750
+ /** a topic edge stays drawn this long after its last message */
751
+ export declare const TOPIC_STALE_MS = 15000;
584
752
  /**
585
753
  * A desk-wide halt: a guard decision with `scope: "global"` (docs/SPEC.md "Decisions") said no, e.g. a kill switch.
586
754
  * Owned by the topmost agent that reports global guards (a desk), drawn ONCE on it (red, `HALTED · <reason>`) instead
@@ -634,6 +802,9 @@ export declare function useWorld(): {
634
802
  mcpCalls: number;
635
803
  decisions: number;
636
804
  decisionMs: number;
805
+ requests: number;
806
+ errors: number;
807
+ rejected: number;
637
808
  };
638
809
  /** decisions per provider (jev / laya / llm ...): count + summed latency (HUD chip tooltip) */
639
810
  decisionProviders: Map<string, {
@@ -692,6 +863,19 @@ export declare function useWorld(): {
692
863
  unauthorized: boolean;
693
864
  /** desk-wide halts (global-scope guard denies, see Halt), keyed by the owning agent */
694
865
  halts: Map<string, Halt>;
866
+ /** transient dashed edges: fallbacks and completed deferred callbacks (prims.ts) */
867
+ primEdges: PrimEdge[];
868
+ /** broker backlog per topic (prims.ts) */
869
+ backlogs: Map<string, Backlog>;
870
+ /** resource stats (pools, caches, models) keyed `server|resource` */
871
+ resStats: Map<string, ResStat>;
872
+ /** message topics between two services (`mkt:tick` feed -> worker), keyed `from|to|topic`: a persistent edge */
873
+ topics: Map<string, SvcTopic>;
874
+ /** service -> agent run it drives (`drives`), keyed `svc|run` */
875
+ drives: Map<string, {
876
+ svc: string;
877
+ run: string;
878
+ }>;
695
879
  };
696
880
  /** Stable pseudo-random 0..1 from a string (same id → same value, different ids → different values). */
697
881
  export declare const hash01: (id: string, salt?: number) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentglow",
3
- "version": "0.3.2",
3
+ "version": "0.4.1",
4
4
  "description": "Live 3D views of agent systems (LangGraph, deepagents, any OpenTelemetry-instrumented agents) as a React component.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -12,7 +12,8 @@
12
12
  "deepagents",
13
13
  "react",
14
14
  "observability",
15
- "react-three-fiber"
15
+ "react-three-fiber",
16
+ "nodejs"
16
17
  ],
17
18
  "license": "MIT",
18
19
  "repository": {
@@ -34,6 +35,17 @@
34
35
  "import": "./dist/index.js",
35
36
  "default": "./dist/index.js"
36
37
  },
38
+ "./pulse": {
39
+ "types": "./dist/types/pulse.d.ts",
40
+ "import": "./dist/pulse.js",
41
+ "default": "./dist/pulse.js"
42
+ },
43
+ "./node": {
44
+ "types": "./dist/types/node.d.ts",
45
+ "node": "./dist/node.js",
46
+ "import": "./dist/node.js",
47
+ "default": "./dist/node.js"
48
+ },
37
49
  "./style.css": "./dist/style.css",
38
50
  "./package.json": "./package.json"
39
51
  },
@@ -64,7 +76,37 @@
64
76
  },
65
77
  "peerDependencies": {
66
78
  "react": "^19.0.0",
67
- "react-dom": "^19.0.0"
79
+ "react-dom": "^19.0.0",
80
+ "@opentelemetry/api": "^1.9.0",
81
+ "@opentelemetry/exporter-trace-otlp-http": ">=0.200.0 <1",
82
+ "@opentelemetry/instrumentation": ">=0.200.0 <1",
83
+ "@opentelemetry/instrumentation-http": ">=0.200.0 <1",
84
+ "@opentelemetry/instrumentation-undici": ">=0.10.0 <1",
85
+ "@opentelemetry/resources": "^2.0.0",
86
+ "@opentelemetry/sdk-trace-node": "^2.0.0"
87
+ },
88
+ "peerDependenciesMeta": {
89
+ "@opentelemetry/api": {
90
+ "optional": true
91
+ },
92
+ "@opentelemetry/exporter-trace-otlp-http": {
93
+ "optional": true
94
+ },
95
+ "@opentelemetry/instrumentation": {
96
+ "optional": true
97
+ },
98
+ "@opentelemetry/instrumentation-http": {
99
+ "optional": true
100
+ },
101
+ "@opentelemetry/instrumentation-undici": {
102
+ "optional": true
103
+ },
104
+ "@opentelemetry/resources": {
105
+ "optional": true
106
+ },
107
+ "@opentelemetry/sdk-trace-node": {
108
+ "optional": true
109
+ }
68
110
  },
69
111
  "dependencies": {
70
112
  "@react-three/drei": "^10.7.9",
@@ -74,13 +116,20 @@
74
116
  "three": "^0.186.1"
75
117
  },
76
118
  "devDependencies": {
119
+ "@opentelemetry/api": "^1.9.1",
120
+ "@opentelemetry/exporter-trace-otlp-http": "^0.222.0",
121
+ "@opentelemetry/instrumentation": "^0.222.0",
122
+ "@opentelemetry/instrumentation-http": "^0.222.0",
123
+ "@opentelemetry/instrumentation-undici": "^0.32.0",
124
+ "@opentelemetry/resources": "^2.11.0",
125
+ "@opentelemetry/sdk-trace-node": "^2.11.0",
77
126
  "@types/node": "^22.20.4",
78
127
  "@types/react": "^19.0.0",
79
128
  "@types/react-dom": "^19.0.0",
80
129
  "@vitejs/plugin-react": "^4.0.0",
81
- "typescript": "^5.6.0",
82
- "vite": "^6.0.0",
83
130
  "react": "^19.0.0",
84
- "react-dom": "^19.0.0"
131
+ "react-dom": "^19.0.0",
132
+ "typescript": "^5.6.0",
133
+ "vite": "^6.0.0"
85
134
  }
86
135
  }