agentglow 0.1.0

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.
@@ -0,0 +1,35 @@
1
+ import { h as f, w as c } from "./ClusterBall-CPsd6JvJ.js";
2
+ const _ = (e) => e === "graph_scout" || e === "records_scout" || e === "data_scout", g = (e, t) => f(e, t) - 0.5, w = (e) => e === 0 ? 0 : e % 2 ? (e + 1) / 2 : -e / 2, u = /* @__PURE__ */ new Map();
3
+ function l(e, t) {
4
+ var n;
5
+ let s = u.get(t);
6
+ s || u.set(t, s = /* @__PURE__ */ new Map());
7
+ const o = s.get(e.id);
8
+ if (o !== void 0) return o;
9
+ for (const r of s.keys()) c.instances.has(r) || s.delete(r);
10
+ let a = 0;
11
+ for (let r = !0; r; ) {
12
+ r = !1;
13
+ for (const [i, d] of s)
14
+ if (d === a && ((n = c.instances.get(i)) == null ? void 0 : n.run) === e.run) {
15
+ r = !0, a++;
16
+ break;
17
+ }
18
+ }
19
+ return s.set(e.id, a), a;
20
+ }
21
+ const p = {
22
+ planner: "planner",
23
+ researcher: "researcher",
24
+ writer: "writer",
25
+ graph_scout: "sub",
26
+ records_scout: "sub",
27
+ data_scout: "sub"
28
+ }, b = (e) => l(e, p[e.type]);
29
+ export {
30
+ w as a,
31
+ _ as i,
32
+ g as j,
33
+ b as r,
34
+ l as s
35
+ };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import "./style.css";
3
+ import { A as E, T as s, a as T } from "./chunks/index-55W5crSg.js";
4
+ export {
5
+ E as AgentScene,
6
+ s as THEMES,
7
+ T as THEME_INFO
8
+ };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .scene-root{position:fixed;top:0;right:0;bottom:0;left:0;background:#03050b;color:#e8edf5;font-family:Public Sans,system-ui,sans-serif;overflow:hidden}.scene-root canvas{display:block}.hud{position:absolute;z-index:10;background:#0a0e1a8c;border:1px solid rgba(148,163,255,.16);border-radius:14px;backdrop-filter:blur(14px) saturate(1.3);-webkit-backdrop-filter:blur(14px) saturate(1.3);box-shadow:0 8px 32px #00000059,inset 0 1px #ffffff0a}.hud-top{top:16px;left:16px;padding:12px 16px;max-width:min(560px,calc(100vw - 32px))}.hud-title{display:flex;align-items:center;gap:10px;font-weight:700;font-size:17px;letter-spacing:-.01em}.hud-sub{margin-top:3px;font-size:12px;color:#94a3b8}.hud-dot{width:9px;height:9px;border-radius:50%;background:#22c55e;box-shadow:0 0 10px #22c55e;animation:hud-ping 1.6s ease-out infinite}@keyframes hud-ping{0%{box-shadow:0 0 #22c55eb3}to{box-shadow:0 0 0 10px #22c55e00}}.hud-badge{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.08em;padding:2px 7px;border-radius:999px;background:#94a3b829;color:#cbd5e1}.hud-nav{display:flex;flex-wrap:wrap;gap:4px;margin-top:10px}.hud-nav a{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:#94a3b8;text-decoration:none;padding:3px 8px;border-radius:999px;border:1px solid transparent}.hud-nav a:hover{color:#e2e8f0;border-color:#94a3ff40}.hud-nav a[aria-current=page]{color:#03050b;background:linear-gradient(135deg,#818cf8,#22d3ee)}.hud-counts{right:16px;bottom:16px;padding:12px 14px;display:grid;grid-template-columns:repeat(7,auto);gap:4px 16px;font-size:10px;color:#94a3b8;text-transform:uppercase;letter-spacing:.06em}.hud-counts b{display:block;font-size:20px;color:#f1f5f9;letter-spacing:-.02em;text-transform:none;font-variant-numeric:tabular-nums}.hud-legend{display:none;top:16px;right:16px;padding:8px 12px;display:grid;gap:4px;font-size:13px}.hud-legend div{display:flex;align-items:center;gap:8px}.hud-legend i{width:10px;height:10px;border-radius:50%;background:var(--c);box-shadow:0 0 10px var(--c)}.hud-legend em{margin-left:auto;padding-left:12px;font-style:normal;font-variant-numeric:tabular-nums;color:var(--c);font-weight:700}.hud-ticker{left:16px;bottom:16px;width:min(560px,calc(100vw - 32px));padding:10px 12px;display:grid;gap:4px;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.hud-tick{display:flex;gap:8px;align-items:baseline;white-space:nowrap;overflow:hidden;color:#cbd5e1}.hud-tick i{flex:0 0 7px;height:7px;border-radius:50%;background:var(--c);box-shadow:0 0 8px var(--c)}.hud-tick span{overflow:hidden;text-overflow:ellipsis}.hud-card{top:210px;right:16px;width:min(380px,calc(100vw - 32px));max-height:46vh;overflow:auto;padding:14px 16px}.hud-card h3{margin:0 0 4px;font-size:13px;text-transform:uppercase;letter-spacing:.06em;color:var(--c);display:flex;align-items:center;gap:8px}.hud-card h3 i{width:10px;height:10px;border-radius:50%;background:var(--c);box-shadow:0 0 10px var(--c)}.hud-card ul{margin:8px 0 0;padding-left:16px;display:grid;gap:4px;font-size:12px;color:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.hud-muted{margin:0;color:#94a3b8;font-size:12px}.hud-close{all:unset;position:absolute;top:8px;right:12px;cursor:pointer;font-size:18px;color:#94a3b8}.scene-label{font-size:12px;font-weight:600;color:#f8fafc;padding:2px 8px;border-radius:999px;white-space:nowrap;background:#03050b8c;border:1px solid color-mix(in srgb,var(--c, #818cf8) 55%,transparent);text-shadow:0 0 10px var(--c, #818cf8);pointer-events:none}.scene-label{scale:.78;max-width:240px;overflow:hidden;text-overflow:ellipsis;border-width:.5px;text-shadow:0 0 6px color-mix(in srgb,var(--c, #818cf8) 70%,transparent);background:#03050b6b}@media(max-width:760px){.hud-counts{grid-template-columns:repeat(3,auto);bottom:auto;top:150px}.hud-legend{display:none}}.hud-agents{top:16px;right:16px;width:min(360px,calc(100vw - 32px));max-height:calc(100vh - 140px);display:flex;flex-direction:column;padding:10px 12px;font-size:13px}.hud-agents.is-collapsed{max-height:none}.ap-head{display:flex;align-items:center;gap:8px}.ap-head strong{font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:#a5b4fc}.ap-count{color:#64748b;font-size:12px;font-variant-numeric:tabular-nums}.ap-link{all:unset;cursor:pointer;margin-left:auto;font-size:12px;color:#93c5fd}.ap-toggle{all:unset;cursor:pointer;margin-left:auto;width:20px;text-align:center;color:#94a3b8;font-size:16px}.ap-link+.ap-toggle{margin-left:8px}.ap-search{margin-top:8px;width:100%;box-sizing:border-box;background:#03050b99;border:1px solid rgba(148,163,255,.2);border-radius:8px;color:inherit;font:inherit;font-size:12px;padding:6px 9px;outline:none}.ap-search:focus{border-color:#818cf8}.ap-chips{display:flex;flex-wrap:wrap;gap:4px;margin-top:8px}.ap-chips button{all:unset;cursor:pointer;display:flex;align-items:center;gap:5px;font-size:11px;padding:3px 7px;border-radius:999px;border:1px solid rgba(148,163,255,.15);color:#cbd5e1}.ap-chips button.on{border-color:var(--c);background:color-mix(in srgb,var(--c) 18%,transparent);color:#f8fafc}.ap-chips i{width:8px;height:8px;border-radius:50%;background:var(--c);box-shadow:0 0 8px var(--c)}.ap-chips em{font-style:normal;color:var(--c);font-weight:700;font-variant-numeric:tabular-nums}.ap-row-filters{display:flex;gap:6px;margin-top:8px;align-items:center}.ap-seg{display:flex;border:1px solid rgba(148,163,255,.15);border-radius:8px;overflow:hidden}.ap-seg button{all:unset;cursor:pointer;font-size:11px;padding:3px 7px;color:#94a3b8;text-transform:capitalize}.ap-seg button.on{background:#818cf840;color:#f1f5f9}.ap-row-filters select{flex:1;min-width:0;background:#03050b99;color:#cbd5e1;border:1px solid rgba(148,163,255,.15);border-radius:8px;font:inherit;font-size:11px;padding:3px 6px}.ap-list{list-style:none;margin:8px -4px 0;padding:0;overflow-y:auto;min-height:0;flex:1}.ap-list li button{all:unset;box-sizing:border-box;width:100%;cursor:pointer;display:flex;align-items:center;gap:8px;padding:6px;border-radius:8px}.ap-list li button:hover{background:#94a3ff1a}.ap-list li button.is-done{opacity:.55}.ap-list i{flex:0 0 9px;height:9px;border-radius:50%;background:var(--c);box-shadow:0 0 8px var(--c)}.ap-list i[data-status=thinking]{animation:ap-pulse .9s ease-in-out infinite}.ap-list i[data-status=waiting]{opacity:.5}.ap-list i[data-status=done]{background:transparent;border:1.5px solid var(--c);box-shadow:none}@keyframes ap-pulse{50%{transform:scale(1.5)}}.ap-name{flex:1;min-width:0;display:flex;flex-direction:column;font-size:12px;color:#e2e8f0}.ap-name small{color:#64748b;font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ap-meta{text-align:right;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums;display:flex;flex-direction:column}.ap-meta b{color:var(--c);font-weight:600;text-transform:lowercase}.ap-more{padding:6px;color:#64748b;font-size:11px}.ap-detail{overflow-y:auto;min-height:0;margin-top:8px}.ap-detail h3{margin:0;display:flex;align-items:center;gap:8px;font-size:15px;color:var(--c)}.ap-detail h3 i{width:11px;height:11px;border-radius:50%;background:var(--c);box-shadow:0 0 10px var(--c)}.ap-detail h3 small{color:#64748b;font-size:11px;font-weight:500}.ap-status{margin-top:3px;font-size:12px;color:#cbd5e1}.ap-status[data-status=thinking]{color:#fde68a}.ap-stats{display:grid;grid-template-columns:repeat(5,1fr);gap:4px;margin:10px 0 4px}.ap-stats div{background:#03050b73;border-radius:8px;padding:6px;text-align:center}.ap-stats dt{font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:#64748b}.ap-stats dd{margin:2px 0 0;font-size:15px;font-weight:700;color:#f1f5f9;font-variant-numeric:tabular-nums}.ap-detail section{margin-top:10px}.ap-detail h4{margin:0 0 4px;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:#64748b}.ap-detail p{margin:0;font-size:12px;color:#cbd5e1}.ap-steps{display:flex;gap:4px;margin-top:4px}.ap-steps span{font-size:10px;text-transform:uppercase;letter-spacing:.06em;padding:2px 7px;border-radius:999px;border:1px solid #334155;color:#64748b}.ap-steps span[data-status=running]{border-color:#fbbf24;color:#fde68a}.ap-steps span[data-status=done]{border-color:#22c55e;color:#86efac}.ap-chip-link{all:unset;cursor:pointer;display:block;font-size:12px;color:#e2e8f0;padding:3px 6px;border-left:2px solid var(--c);margin:2px 0;border-radius:0 6px 6px 0}.ap-chip-link:hover{background:#94a3ff1a}.ap-wait{color:#fbbf24!important;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.ap-nodes{line-height:1.5}.ap-events{margin:0;padding-left:14px;display:grid;gap:3px;font-size:11px;color:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.hud-badge--live{background:#22c55e2e;color:#86efac}.hud-run{display:flex;gap:6px;margin-top:8px;align-items:center;flex-wrap:wrap}.hud-run input{flex:1;min-width:160px;background:#03050b99;border:1px solid rgba(148,163,255,.2);border-radius:999px;color:inherit;font:inherit;font-size:12px;padding:6px 11px;outline:none}.hud-run button{border:0;border-radius:999px;padding:6px 13px;font:inherit;font-size:12px;font-weight:600;background:linear-gradient(135deg,#818cf8,#22d3ee);color:#03050b;cursor:pointer}.hud-run button:disabled{opacity:.5}.hud-run span{font-size:11px;color:#86efac}.agentglow-embed{position:relative;overflow:hidden;width:100%;height:100%;min-height:320px;isolation:isolate}.agentglow-embed .scene-root{position:absolute;top:0;right:0;bottom:0;left:0}.agentglow-embed .hud-top{max-width:min(560px,calc(100% - 32px))}.agentglow-embed .hud-ticker{width:min(560px,calc(100% - 32px))}.agentglow-embed .hud-agents{width:min(360px,calc(100% - 32px));max-height:calc(100% - 140px)}.lod-cluster-label{all:unset;box-sizing:border-box;display:grid;gap:1px;text-align:center;cursor:pointer;pointer-events:auto;font-size:12px;font-weight:600;color:#f8fafc;padding:4px 11px 5px;border-radius:12px;white-space:nowrap;background:#03050b9e;border:1px solid color-mix(in srgb,var(--c, #818cf8) 60%,transparent);text-shadow:0 0 10px var(--c, #818cf8);box-shadow:0 0 18px color-mix(in srgb,var(--c, #818cf8) 22%,transparent);transition:border-color .2s,background .2s}.lod-cluster-label:hover{background:color-mix(in srgb,var(--c, #818cf8) 22%,rgba(3,5,11,.7));border-color:var(--c, #818cf8)}.lod-cluster-label b{font-weight:700;letter-spacing:-.01em}.lod-cluster-label small{font-size:10px;font-weight:500;color:#94a3b8;text-shadow:none;font-variant-numeric:tabular-nums}.hud-lod{left:50%;transform:translate(-50%);top:16px;padding:6px 8px 6px 14px;display:flex;align-items:center;gap:10px;font-size:12px;color:#cbd5e1;white-space:nowrap}.hud-lod b{color:#f1f5f9;font-variant-numeric:tabular-nums}.hud-lod i{width:7px;height:7px;border-radius:50%;background:#a5b4fc;box-shadow:0 0 8px #a5b4fc}.hud-lod button{all:unset;cursor:pointer;font-size:11px;padding:3px 9px;border-radius:999px;border:1px solid rgba(148,163,255,.25);color:#c7d2fe}.hud-lod button:hover{background:#818cf833;color:#f8fafc}@media(max-width:1100px){.hud-lod{top:auto;bottom:96px}}.scene-label.subway-station{font-size:10px;font-weight:500;padding:1px 6px;letter-spacing:.08em;text-transform:uppercase;color:#cbd5e1;opacity:.85}.scene-label.subway-airport{font-size:11px}.scene-label.subway-run{display:flex;flex-direction:column;align-items:flex-start;gap:3px;padding:4px 9px;border-radius:10px;font-size:11px}.subway-steps{display:flex;gap:4px}.subway-steps b{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;padding:0 5px;border-radius:999px;color:#94a3b8;border:1px solid #334155;text-shadow:none}.subway-steps b[data-st=running]{color:#fde68a;border-color:#fbbf24;box-shadow:0 0 8px #fbbf2499}.subway-steps b[data-st=done]{color:#bbf7d0;border-color:#22c55e}.subway-steps b[data-st=failed]{color:#fecaca;border-color:#ef4444}.scene-label.subway-flare{font-size:10px;transition:opacity .2s}.city-root{background:#05040d}.city-district{display:grid;gap:4px;padding:5px 10px 6px;border-radius:10px;transition:opacity .4s}.city-district-top{display:flex;align-items:baseline;gap:8px}.city-district-top b{font-size:12px;color:#f8fafc}.city-count{font-size:10px;font-weight:500;color:#a5b4fc;text-shadow:none}.city-steps{display:flex;gap:4px}.city-chip{--sc: #3b4256;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;padding:1px 7px;border-radius:999px;color:var(--sc);border:1px solid color-mix(in srgb,var(--sc) 70%,transparent);text-shadow:none}.city-chip[data-st=running]{color:#03050b;background:var(--sc);box-shadow:0 0 10px var(--sc)}.city-chip[data-st=done]{color:var(--sc);background:color-mix(in srgb,var(--sc) 18%,transparent)}.city-chip[data-st=queued]{color:#64748b;border-color:#334155}.city-chip+.city-chip:before{content:""}.city-tower-label{font-size:13px}.city-mcp-label{font-size:11px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.city-tower-label{font-size:15px;font-weight:800;letter-spacing:.06em;padding:3px 12px}.city-node-label{font-size:10px;transition:opacity .2s}.flow-run{display:flex;flex-direction:column;align-items:center;gap:4px;pointer-events:none}.flow-run .scene-label{font-size:11px;max-width:220px;overflow:hidden;text-overflow:ellipsis}.flow-steps{display:flex;gap:3px;font:600 9px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase;letter-spacing:.06em}.flow-steps span{padding:2px 5px;border-radius:999px;color:#64748b;background:#03050b8c;border:1px solid rgba(100,116,139,.35)}.flow-steps span[data-s=running]{color:#03050b;background:var(--c);border-color:var(--c);box-shadow:0 0 12px var(--c)}.flow-steps span[data-s=done]{color:var(--c);border-color:color-mix(in srgb,var(--c) 60%,transparent)}.flow-steps span[data-s=failed]{color:#fecaca;background:#7f1d1d}.flow-step{font:600 9px/1 ui-monospace,SFMono-Regular,Menlo,monospace;text-transform:uppercase;letter-spacing:.08em;color:color-mix(in srgb,var(--c) 70%,white);text-shadow:0 0 8px var(--c);opacity:.55;pointer-events:none;white-space:nowrap;transition:opacity .3s}.flow-step[data-s=running]{opacity:1}.flow-hint{font-size:10px;padding:1px 7px;opacity:.9}.flow-label-core{font-size:11px;letter-spacing:.04em}.ap-root{background:radial-gradient(ellipse at 45% 50%,#03140e,#010604 60%,#000302)}.ap-root,.ap-tag,.ap-airport,.ap-gate,.ap-strip,.ap-wp,.ap-bearing{--mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace}.ap-bearing{font:600 9px/1 var(--mono);color:#2fae6e;letter-spacing:.08em;opacity:.85;text-shadow:0 0 6px rgba(70,255,154,.5)}.ap-tag{position:relative;width:0;height:0;pointer-events:none;transition:none}.ap-leader{position:absolute;left:6px;top:-22px;overflow:visible}.ap-leader line{stroke:color-mix(in srgb,var(--c) 45%,#46ff9a);stroke-width:1;opacity:.7}.ap-tag-box{position:absolute;left:28px;top:-38px;display:grid;gap:1px;padding:2px 6px 2px 5px;border-left:2px solid var(--c);background:#010c089e;white-space:nowrap}.ap-call{font:700 10px/1.15 var(--mono);letter-spacing:.06em;color:#d9ffe9;text-shadow:0 0 8px color-mix(in srgb,var(--c) 70%,transparent)}.ap-data{font:500 9px/1.15 var(--mono);letter-spacing:.05em;color:#57d897}.ap-tag-big .ap-call{font-size:12px}.ap-tag-big .ap-data{font-size:10px}.ap-airport{width:max-content;display:flex;align-items:center;gap:6px;white-space:nowrap;font:600 10px/1 var(--mono);color:#c8f7de;letter-spacing:.04em;padding:3px 7px;border:1px solid color-mix(in srgb,var(--c) 55%,transparent);background:#010a07b3;text-shadow:0 0 8px color-mix(in srgb,var(--c) 60%,transparent)}.ap-airport-code{font-weight:800;color:var(--c);letter-spacing:.1em}.ap-gate{white-space:nowrap;font:500 9px/1 var(--mono);color:#a6e9c6;letter-spacing:.03em;padding:2px 5px;background:#010a078c;border-bottom:1px solid color-mix(in srgb,var(--c) 50%,transparent)}.ap-gate.ap-hot{color:#fff;font-weight:700;border-bottom-color:var(--c);box-shadow:0 0 10px color-mix(in srgb,var(--c) 50%,transparent)}.ap-strip{width:max-content;display:grid;gap:2px;text-align:left;padding:4px 9px 4px 8px;border-left:3px solid var(--c);background:#010c08b8;outline:1px solid rgba(70,255,154,.14);max-width:260px}.ap-strip-topic{font:600 11px/1.25 Public Sans,system-ui,sans-serif;color:#e8fff1;white-space:normal}.ap-strip-sub{font:500 9px/1.2 var(--mono);color:#5fbf8d;letter-spacing:.05em;white-space:nowrap}.ap-wp{white-space:nowrap;font:600 9px/1 var(--mono);letter-spacing:.05em;color:#e9fffb;padding:2px 5px;border:1px solid color-mix(in srgb,var(--c, #38e8ff) 60%,transparent);background:#010a0aa6;text-shadow:0 0 8px var(--c, #38e8ff)}.ap-tag-left .ap-leader{left:-28px;transform:scaleX(-1)}.ap-tag-left .ap-tag-box{left:auto;right:28px;text-align:right;border-left:0;border-right:2px solid var(--c);padding:2px 5px 2px 6px}
@@ -0,0 +1,17 @@
1
+ /** <AgentScene/>: one AgentGlow theme, sized to its container, fed by an agentglow server (or the simulator). */
2
+ import { type CSSProperties } from "react";
3
+ import { type Theme } from "./themes";
4
+ export type AgentSceneProps = {
5
+ /** Visual theme. Default "neural". */
6
+ theme?: Theme;
7
+ /** agentglow server base URL, e.g. "http://localhost:8100". Default "" (same origin). */
8
+ source?: string;
9
+ /** Show the HUD (counts, event ticker, agent panel). Default true. */
10
+ hud?: boolean;
11
+ /** Use the built-in simulator instead of a server. Default false (auto-fallback if the server is unreachable). */
12
+ sim?: boolean;
13
+ style?: CSSProperties;
14
+ className?: string;
15
+ };
16
+ export declare function AgentScene({ theme, source, hud, sim, style, className }: AgentSceneProps): import("react").JSX.Element;
17
+ export default AgentScene;
@@ -0,0 +1,3 @@
1
+ export { AgentScene, type AgentSceneProps } from "./AgentScene";
2
+ export { THEMES, THEME_INFO, type Theme } from "./themes";
3
+ export type { WorldEvent } from "./world";
@@ -0,0 +1,12 @@
1
+ /** The AgentGlow themes (scene modules live in src/scenes/<theme>/index.tsx). */
2
+ import type { ComponentType } from "react";
3
+ export declare const THEMES: readonly ["orbit", "neural", "subway", "city", "ocean", "circuit", "tunnel", "flow", "hive", "forest", "constellation", "factory", "airport", "mycelium", "atom"];
4
+ export type Theme = (typeof THEMES)[number];
5
+ export declare const THEME_INFO: Record<Theme, {
6
+ name: string;
7
+ tagline: string;
8
+ }>;
9
+ /** Lazy loaders, one chunk per theme (static strings so every bundler can split them). */
10
+ export declare const THEME_LOADERS: Record<Theme, () => Promise<{
11
+ default: ComponentType;
12
+ }>>;
@@ -0,0 +1,301 @@
1
+ export type AgentType = "planner" | "researcher" | "graph_scout" | "records_scout" | "data_scout" | "writer";
2
+ export type StepName = "plan" | "research" | "write";
3
+ export type InstanceStatus = "spawning" | "thinking" | "waiting" | "done" | "failed";
4
+ export type WorldEvent = {
5
+ type: "run";
6
+ run_id: string;
7
+ status: "started" | "completed" | "failed";
8
+ topic: string;
9
+ workflow: string;
10
+ ts: number;
11
+ } | {
12
+ type: "step";
13
+ run_id: string;
14
+ step: StepName;
15
+ status: "running" | "done" | "failed";
16
+ ts: number;
17
+ } | {
18
+ type: "spawn";
19
+ run_id: string;
20
+ id: string;
21
+ agent: string;
22
+ parent_id: string | null;
23
+ subagent?: boolean;
24
+ ts: number;
25
+ } | {
26
+ type: "exit";
27
+ run_id: string;
28
+ id: string;
29
+ status: "done" | "failed";
30
+ ts: number;
31
+ } | {
32
+ type: "agent";
33
+ run_id: string;
34
+ id: string;
35
+ status: "thinking" | "waiting";
36
+ ts: number;
37
+ } | {
38
+ type: "llm";
39
+ run_id: string;
40
+ id: string;
41
+ tokens_in: number;
42
+ tokens_out: number;
43
+ latency_ms: number;
44
+ ts: number;
45
+ } | {
46
+ type: "message";
47
+ run_id: string;
48
+ from_id: string;
49
+ to_id: string;
50
+ text: string;
51
+ ts: number;
52
+ } | {
53
+ type: "tool";
54
+ run_id: string;
55
+ id: string;
56
+ tool: string;
57
+ args_preview: string;
58
+ ts: number;
59
+ } | {
60
+ type: "graph";
61
+ run_id: string;
62
+ id: string;
63
+ op: "read" | "write";
64
+ nodes: string[];
65
+ ts: number;
66
+ } | {
67
+ type: "final";
68
+ run_id: string;
69
+ text: string;
70
+ ts: number;
71
+ } | {
72
+ type: "mcp_register";
73
+ run_id?: string;
74
+ server: string;
75
+ resources: {
76
+ name: string;
77
+ kind: ResourceKind;
78
+ }[];
79
+ ts: number;
80
+ } | {
81
+ type: "mcp";
82
+ run_id: string;
83
+ id: string;
84
+ server: string;
85
+ tool: string;
86
+ phase: "call" | "result";
87
+ latency_ms?: number;
88
+ ts: number;
89
+ resource?: string;
90
+ resource_kind?: ResourceKind;
91
+ };
92
+ /** What sits behind an MCP server (the server is a node; its backends are nodes too). */
93
+ export type ResourceKind = "db" | "warehouse" | "spark" | "api" | "storage" | "queue";
94
+ export declare const AGENT_TYPES: {
95
+ type: AgentType;
96
+ label: string;
97
+ color: string;
98
+ }[];
99
+ export declare const TYPE_COLOR: Record<AgentType, string>;
100
+ export declare const TYPE_LABEL: Record<AgentType, string>;
101
+ export declare const STEPS: StepName[];
102
+ export declare const RUN_COLORS: string[];
103
+ export declare const KIND_COLOR: Record<string, string>;
104
+ export type Instance = {
105
+ id: string;
106
+ run: string;
107
+ type: AgentType;
108
+ /** real agent name from the trace (e.g. "researcher", "web_scout", "report_writer") */
109
+ name: string;
110
+ parent: string | null;
111
+ status: InstanceStatus;
112
+ /** spawned by a parent agent via the deepagents `task` tool (vs a top-level workflow-step agent) */
113
+ subagent: boolean;
114
+ bornAt: number;
115
+ exitAt: number;
116
+ pulse: number;
117
+ pulseAt: number;
118
+ tokens: number;
119
+ index: number;
120
+ recent: WorldEvent[];
121
+ llmCalls: number;
122
+ toolCalls: number;
123
+ mcpCalls: number;
124
+ nodes: Set<string>;
125
+ };
126
+ export type Run = {
127
+ id: string;
128
+ topic: string;
129
+ workflow: string;
130
+ color: string;
131
+ slot: number;
132
+ status: "started" | "completed" | "failed";
133
+ steps: Record<StepName, "queued" | "running" | "done" | "failed">;
134
+ /** true once a step event arrives (e.g. Hatchet); plain agent runs have no steps */
135
+ hasSteps: boolean;
136
+ startedAt: number;
137
+ endedAt: number;
138
+ handoffAt: number;
139
+ handoffFrom: StepName;
140
+ handoffTo: StepName;
141
+ final: string;
142
+ };
143
+ export type Comet = {
144
+ id: number;
145
+ run: string;
146
+ from: string;
147
+ to: string;
148
+ start: number;
149
+ dur: number;
150
+ text: string;
151
+ };
152
+ /** External MCP servers agents call (persistent "satellites"; registered on first use). */
153
+ export type McpResource = {
154
+ name: string;
155
+ kind: ResourceKind;
156
+ activeAt: number;
157
+ inflight: number;
158
+ calls: number;
159
+ };
160
+ export type McpServer = {
161
+ name: string;
162
+ color: string;
163
+ slot: number;
164
+ activeAt: number;
165
+ calls: number;
166
+ inflight: number;
167
+ resources: Map<string, McpResource>;
168
+ };
169
+ /** One MCP request/response: a packet flying instance → server ("call") or server → instance ("result"). */
170
+ export type McpCall = {
171
+ id: number;
172
+ run: string;
173
+ instance: string;
174
+ server: string;
175
+ tool: string;
176
+ resource?: string;
177
+ phase: "call" | "result";
178
+ start: number;
179
+ dur: number;
180
+ };
181
+ /** An MCP call that has been sent but not answered yet: draw a live tether instance ↔ server while it waits. */
182
+ export type McpPending = {
183
+ key: string;
184
+ run: string;
185
+ instance: string;
186
+ server: string;
187
+ tool: string;
188
+ resource?: string;
189
+ since: number;
190
+ };
191
+ export declare const MCP_COLORS: Record<string, string>;
192
+ export type Flare = {
193
+ id: number;
194
+ run: string;
195
+ instance: string;
196
+ node: string;
197
+ op: "read" | "write";
198
+ start: number;
199
+ };
200
+ /** How long finished instances/runs stay visible while fading out (ms). */
201
+ export declare const FADE_MS = 2500;
202
+ export declare const RUN_LINGER_MS = 6000;
203
+ /** Exit-fade length hook: lod.ts shortens it when the scene is crowded. Use `lingerMs(i)` instead of FADE_MS. */
204
+ export declare const linger: {
205
+ fadeMs: (_i: Instance) => number;
206
+ };
207
+ /** How long this exited instance stays visible while fading out (ms). */
208
+ export declare const lingerMs: (i: Instance) => number;
209
+ export declare const world: {
210
+ runs: Map<string, Run>;
211
+ instances: Map<string, Instance>;
212
+ comets: Comet[];
213
+ flares: Flare[];
214
+ mcpServers: Map<string, McpServer>;
215
+ mcpCalls: McpCall[];
216
+ /** in-flight MCP calls keyed `${instance}|${server}|${tool}`; resolvedAt kept briefly for a "snap back" effect */
217
+ mcpPending: Map<string, McpPending>;
218
+ mcpResolved: (McpPending & {
219
+ resolvedAt: number;
220
+ })[];
221
+ ticker: WorldEvent[];
222
+ stats: {
223
+ runs: number;
224
+ spawned: number;
225
+ llmCalls: number;
226
+ tokens: number;
227
+ toolCalls: number;
228
+ graphReads: number;
229
+ graphWrites: number;
230
+ mcpCalls: number;
231
+ };
232
+ lastFinal: string;
233
+ simulated: boolean;
234
+ mode: "connecting" | "sim" | "live";
235
+ /** label for the graph/memory structure: names the DB only when the server provides a real graph */
236
+ graphLabel: string;
237
+ focus: string | null;
238
+ focusAt: number;
239
+ /** exited instances kept for the agent panel after their shape fades (newest last, capped) */
240
+ archive: Map<string, Instance>;
241
+ /** instance selected in the agent panel or by clicking a shape */
242
+ selected: string | null;
243
+ };
244
+ /** Subscribe a React component to world changes (HUD / DOM). Scenes should read `world` in useFrame instead. */
245
+ export declare function useWorld(): {
246
+ runs: Map<string, Run>;
247
+ instances: Map<string, Instance>;
248
+ comets: Comet[];
249
+ flares: Flare[];
250
+ mcpServers: Map<string, McpServer>;
251
+ mcpCalls: McpCall[];
252
+ /** in-flight MCP calls keyed `${instance}|${server}|${tool}`; resolvedAt kept briefly for a "snap back" effect */
253
+ mcpPending: Map<string, McpPending>;
254
+ mcpResolved: (McpPending & {
255
+ resolvedAt: number;
256
+ })[];
257
+ ticker: WorldEvent[];
258
+ stats: {
259
+ runs: number;
260
+ spawned: number;
261
+ llmCalls: number;
262
+ tokens: number;
263
+ toolCalls: number;
264
+ graphReads: number;
265
+ graphWrites: number;
266
+ mcpCalls: number;
267
+ };
268
+ lastFinal: string;
269
+ simulated: boolean;
270
+ mode: "connecting" | "sim" | "live";
271
+ /** label for the graph/memory structure: names the DB only when the server provides a real graph */
272
+ graphLabel: string;
273
+ focus: string | null;
274
+ focusAt: number;
275
+ /** exited instances kept for the agent panel after their shape fades (newest last, capped) */
276
+ archive: Map<string, Instance>;
277
+ /** instance selected in the agent panel or by clicking a shape */
278
+ selected: string | null;
279
+ };
280
+ /** Stable pseudo-random 0..1 from a string (same id → same value, different ids → different values). */
281
+ export declare const hash01: (id: string, salt?: number) => number;
282
+ export declare function apply(ev: WorldEvent): void;
283
+ export declare function tick(now?: number): void;
284
+ /** 0..1 visibility for an instance: grows in on spawn, fades out after exit. */
285
+ export declare function presence(i: Instance, now?: number): number;
286
+ /** Current pulse energy (decays after each LLM/tool event). */
287
+ export declare function energy(i: Instance, now?: number): number;
288
+ /** Seconds an MCP call has been waiting (for tether intensity / color: amber → red past ~2s). */
289
+ export declare function waitSeconds(p: McpPending, now?: number): number;
290
+ /** Map any real agent name onto a visual role the scenes know (layout + color). */
291
+ export declare function roleOf(name: string, subagent: boolean): AgentType;
292
+ /** Visual size multiplier by role: parent agents read bigger, their subagents smaller. */
293
+ export declare function roleScale(i: Instance): number;
294
+ /** Look up a live or archived (exited) instance. */
295
+ export declare function getInstance(id: string | null | undefined): Instance | undefined;
296
+ /** Select an agent (panel list click or 3D click); null clears. */
297
+ export declare function selectInstance(id: string | null): void;
298
+ export declare function setSimulated(v: boolean): void;
299
+ /** Name the graph structure (e.g. when the server serves a real FalkorDB sample). */
300
+ export declare function setGraphLabel(label: string): void;
301
+ export declare function setMode(m: "sim" | "live"): void;
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "agentglow",
3
+ "version": "0.1.0",
4
+ "description": "Live 3D views of agent systems (LangGraph, deepagents, any OpenTelemetry-instrumented agents) as a React component.",
5
+ "keywords": [
6
+ "opentelemetry",
7
+ "agents",
8
+ "3d",
9
+ "three.js",
10
+ "langgraph",
11
+ "deepagents",
12
+ "react",
13
+ "observability",
14
+ "react-three-fiber"
15
+ ],
16
+ "license": "MIT",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/Nideesh1/agentglow.git",
20
+ "directory": "frontend"
21
+ },
22
+ "homepage": "https://github.com/Nideesh1/agentglow#readme",
23
+ "bugs": {
24
+ "url": "https://github.com/Nideesh1/agentglow/issues"
25
+ },
26
+ "type": "module",
27
+ "main": "./dist/index.js",
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/types/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/types/index.d.ts",
33
+ "import": "./dist/index.js",
34
+ "default": "./dist/index.js"
35
+ },
36
+ "./style.css": "./dist/style.css",
37
+ "./package.json": "./package.json"
38
+ },
39
+ "files": [
40
+ "dist"
41
+ ],
42
+ "sideEffects": [
43
+ "**/*.css",
44
+ "./dist/index.js"
45
+ ],
46
+ "scripts": {
47
+ "dev": "vite",
48
+ "typecheck": "tsc --noEmit",
49
+ "build": "npm run build:lib && npm run build:app",
50
+ "build:app": "tsc --noEmit && vite build",
51
+ "build:lib": "vite build -c vite.lib.config.ts && tsc -p tsconfig.lib.json && node scripts/postbuild-lib.mjs",
52
+ "preview": "vite preview",
53
+ "prepublishOnly": "npm run build:lib"
54
+ },
55
+ "peerDependencies": {
56
+ "react": "^19.0.0",
57
+ "react-dom": "^19.0.0"
58
+ },
59
+ "dependencies": {
60
+ "@react-three/drei": "^10.7.9",
61
+ "@react-three/fiber": "^9.8.1",
62
+ "@react-three/postprocessing": "^3.1.3",
63
+ "postprocessing": "^6.39.5",
64
+ "three": "^0.186.1"
65
+ },
66
+ "devDependencies": {
67
+ "@types/node": "^22.20.4",
68
+ "@types/react": "^19.0.0",
69
+ "@types/react-dom": "^19.0.0",
70
+ "@vitejs/plugin-react": "^4.0.0",
71
+ "typescript": "^5.6.0",
72
+ "vite": "^6.0.0",
73
+ "react": "^19.0.0",
74
+ "react-dom": "^19.0.0"
75
+ }
76
+ }