@prsm/devtools 1.0.2 → 1.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.
- package/README.md +14 -1
- package/dist/client/assets/index-Dj0vLuDk.css +1 -0
- package/dist/client/assets/index-LvnrgtvZ.js +176 -0
- package/dist/client/index.html +2 -2
- package/package.json +2 -1
- package/src/index.js +55 -4
- package/dist/client/assets/index-CkwmeR8W.js +0 -176
- package/dist/client/assets/index-p_4czaPS.css +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<h1 align="center">@prsm/devtools</h1>
|
|
6
6
|
|
|
7
|
-
Read-only Express middleware dashboard for observing prsm infrastructure at runtime.
|
|
7
|
+
Read-only Express middleware that provides a live dashboard for observing prsm infrastructure at runtime. Pass your instances and mount the router to get a full UI.
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<img src=".github/record.png" width="800" alt="realtime records view">
|
|
@@ -29,6 +29,7 @@ import Queue from '@prsm/queue'
|
|
|
29
29
|
import { Cron } from '@prsm/cron'
|
|
30
30
|
import { slidingWindow } from '@prsm/limit'
|
|
31
31
|
import WorkflowEngine from '@prsm/workflow'
|
|
32
|
+
import { createGraph } from '@prsm/cells'
|
|
32
33
|
import { prsmDevtools } from '@prsm/devtools'
|
|
33
34
|
|
|
34
35
|
const app = express()
|
|
@@ -38,6 +39,7 @@ const queue = new Queue({ concurrency: 5 })
|
|
|
38
39
|
const cron = new Cron()
|
|
39
40
|
const apiLimiter = slidingWindow({ max: 100, window: '1m' })
|
|
40
41
|
const workflow = new WorkflowEngine()
|
|
42
|
+
const portfolio = createGraph({ prefix: 'portfolio:' })
|
|
41
43
|
|
|
42
44
|
app.use('/devtools', prsmDevtools({
|
|
43
45
|
realtime,
|
|
@@ -45,6 +47,7 @@ app.use('/devtools', prsmDevtools({
|
|
|
45
47
|
cron,
|
|
46
48
|
limit: { api: apiLimiter },
|
|
47
49
|
workflow,
|
|
50
|
+
cells: { portfolio },
|
|
48
51
|
}))
|
|
49
52
|
|
|
50
53
|
app.listen(3000)
|
|
@@ -77,6 +80,13 @@ Includes a connection picker sidebar for filtering all views by a specific clien
|
|
|
77
80
|
|
|
78
81
|
**Executions** - workflow execution list with filters, live graph overlay showing execution progress, per-step state, output/error inspector, and journal timeline
|
|
79
82
|
|
|
83
|
+
**Cells** - one or more `@prsm/cells` graphs with two views per graph:
|
|
84
|
+
|
|
85
|
+
- **Table** - every cell in the graph with current value, dependencies, status, and last-updated time. Click a row to open a detail panel below
|
|
86
|
+
- **Graph** - DAG visualization with topologically-laid-out nodes and live propagation flashes when values change
|
|
87
|
+
|
|
88
|
+
The detail panel shows the cell's current value (syntax-highlighted JSON), source descriptor, metadata, template body (for templated cells), recent history (for cells with history enabled), and graph relationships. Pass a single graph or a named map of graphs - the panel includes a graph picker when more than one is provided.
|
|
89
|
+
|
|
80
90
|
## API
|
|
81
91
|
|
|
82
92
|
### `prsmDevtools(options)`
|
|
@@ -96,6 +106,7 @@ app.use('/devtools', prsmDevtools(options))
|
|
|
96
106
|
| `cron` | `Cron` | A `@prsm/cron` instance |
|
|
97
107
|
| `limit` | `Object<string, Limiter>` | Named limiters from `@prsm/limit` |
|
|
98
108
|
| `workflow` | `WorkflowEngine` | An `@prsm/workflow` engine instance |
|
|
109
|
+
| `cells` | `Graph` or `Object<string, Graph>` | A `@prsm/cells` graph instance, or a named map of graphs |
|
|
99
110
|
|
|
100
111
|
All options are optional. The dashboard adapts to what's provided.
|
|
101
112
|
|
|
@@ -120,6 +131,8 @@ The middleware exposes these under its mount path:
|
|
|
120
131
|
| `GET /api/realtime/room/:name` | Room members with metadata and presence |
|
|
121
132
|
| `GET /api/realtime/record/:id` | Fetch a record's current value |
|
|
122
133
|
| `GET /api/realtime/collection/:id/records` | Resolved records for a collection + connection |
|
|
134
|
+
| `GET /api/cells/:graph` | All cells in the named graph with values, deps, status, metadata |
|
|
135
|
+
| `GET /api/cells/:graph/:name/history` | Recent values for a cell (if history is enabled on it) |
|
|
123
136
|
|
|
124
137
|
## How It Works
|
|
125
138
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--bg: #0a0a0a;--bg-surface: #111111;--bg-raised: #1a1a1a;--bg-hover: #222222;--bg-active: #2a2a2a;--border: #2a2a2a;--border-subtle: #1e1e1e;--text: #d4d4d4;--text-bright: #e8e8e8;--text-muted: #555555;--accent: #34d399;--accent-dim: rgba(52, 211, 153, .12);--accent-text: #2dd4a2;--color-blue: #6ad;--color-red: #c55;--color-yellow: #b93;--color-green: #5a9;--syn-string: #a5d6a7;--syn-number: #4dd0e1;--syn-boolean: #ce93d8;--syn-null: #666666;--syn-key: #b0b0b0;--syn-bracket: #555555}*{box-sizing:border-box;margin:0;padding:0}body{font-family:SF Mono,Fira Code,JetBrains Mono,Cascadia Code,monospace;font-size:12px;line-height:1.5;color:var(--text);background:var(--bg);-webkit-font-smoothing:antialiased}::selection{background:var(--accent-dim);color:var(--accent-text)}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#3a3a3a}.app{display:flex;flex-direction:column;height:100vh;overflow:hidden}.top-bar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:40px;border-bottom:1px solid var(--border);background:var(--bg-surface);flex-shrink:0}.top-bar-left{display:flex;align-items:center;gap:12px}.logo{font-size:11px;font-weight:600;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted)}.logo span{color:var(--accent)}.top-bar-right{display:flex;align-items:center;gap:12px}.nav-bar{display:flex;align-items:center;gap:0;border-bottom:1px solid var(--border);background:var(--bg-surface);flex-shrink:0;padding:0 16px}.nav-bar a{padding:8px 16px;font-size:11px;color:var(--text-muted);cursor:pointer;border-bottom:2px solid transparent;-webkit-user-select:none;user-select:none;text-decoration:none}.nav-bar a:hover{color:var(--text)}.nav-bar a.active{color:var(--accent-text);border-bottom-color:var(--accent)}.page-scroll{flex:1;overflow-y:auto}.page-content{max-width:1100px;padding:20px 24px 40px}.page-content-wide{padding:20px 24px 40px}.tab-bar{display:flex;align-items:center;gap:0;border-bottom:1px solid var(--border);background:var(--bg-surface);flex-shrink:0;padding:0 16px}.tab{padding:8px 16px;font-size:11px;color:var(--text-muted);cursor:pointer;border-bottom:2px solid transparent;-webkit-user-select:none;user-select:none}.tab:hover{color:var(--text)}.tab.active{color:var(--accent-text);border-bottom-color:var(--accent)}.tab .count{margin-left:6px;font-size:10px;color:var(--text-muted)}.tab.active .count{color:var(--accent)}.sidebar{width:280px;min-width:280px;border-right:1px solid var(--border);overflow-y:auto;background:var(--bg-surface)}.content{flex:1;overflow-y:auto;padding:16px}.sidebar-section{border-bottom:1px solid var(--border-subtle)}.sidebar-header{padding:8px 12px;font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);background:var(--bg)}.sidebar-item{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;cursor:pointer;border-left:2px solid transparent}.sidebar-item:hover{background:var(--bg-hover)}.sidebar-item.active{background:var(--accent-dim);border-left-color:var(--accent)}.sidebar-item .label{font-size:11px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar-item.active .label{color:var(--accent-text)}.sidebar-item .meta{font-size:10px;color:var(--text-muted);flex-shrink:0;margin-left:8px}.badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;font-size:10px;border-radius:9px;background:#1f1f1f;color:#999}.badge.accent{background:var(--accent-dim);color:var(--accent)}.section{margin-bottom:20px}.section-title{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--text-muted);margin-bottom:8px}.card{background:var(--bg-surface);border:1px solid var(--border);border-radius:4px;overflow:hidden}.card+.card{margin-top:8px}.card-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--bg);border-bottom:1px solid var(--border-subtle);font-size:11px}.card-header .name{color:var(--text-bright)}.card-body{padding:8px 12px}.kv-row{display:flex;align-items:baseline;padding:2px 0;font-size:11px}.kv-key{color:var(--text-muted);min-width:100px;flex-shrink:0}.kv-value{color:var(--text);word-break:break-all}.member-row{display:flex;align-items:center;justify-content:space-between;padding:4px 12px;font-size:11px;border-bottom:1px solid var(--border-subtle)}.member-row:last-child{border-bottom:none}.member-id{color:var(--text);font-size:11px}.member-presence{font-size:10px;color:var(--accent)}.tag{display:inline-block;padding:1px 6px;font-size:10px;border-radius:3px;background:#1f1f1f;color:#999;margin:1px 2px}.tag.accent{background:var(--accent-dim);color:var(--accent)}.empty{padding:24px;text-align:center;color:var(--text-muted);font-size:11px}.view-hint{font-size:11px;color:var(--text-muted);margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--border-subtle)}.no-presence{font-size:10px;color:#333}.pattern-list{display:flex;flex-wrap:wrap;gap:4px;margin-top:4px}.json-view{font-size:11px;line-height:1.6;white-space:pre-wrap;word-break:break-all}.json-view .shiki{background:transparent!important;padding:0;margin:0}.json-view .shiki code{font-family:inherit;font-size:inherit}.select{background:var(--bg-raised);border:1px solid var(--border);color:var(--text);font-family:inherit;font-size:11px;padding:4px 8px;border-radius:3px;outline:none;cursor:pointer}.select:focus{border-color:var(--accent)}.conn-link{cursor:pointer;text-decoration:underline;text-decoration-color:var(--border);text-underline-offset:2px}.conn-link:hover{color:var(--accent-text);text-decoration-color:var(--accent)}.exposed-row{display:flex;align-items:center;flex-wrap:wrap;gap:3px;padding:4px 12px;border-bottom:1px solid var(--border-subtle)}.exposed-row:last-child{border-bottom:none}.exposed-label{font-size:10px;color:var(--text-muted);min-width:70px;flex-shrink:0}.pulse{width:6px;height:6px;border-radius:50%;background:var(--accent)}.pulse.disconnected{background:#ef4444}.instance-id{font-size:10px;color:var(--text-muted)}section[data-v-5ee7e46a]{margin-top:28px}.subsystems[data-v-5ee7e46a]{display:flex;gap:8px;margin-bottom:20px}.chip[data-v-5ee7e46a]{padding:5px 14px;font-size:11px;font-weight:500;color:var(--text-muted);background:var(--bg-surface);border:1px solid var(--border);border-radius:4px;font-family:inherit;cursor:pointer}.chip.on[data-v-5ee7e46a]{color:var(--text);border-color:#333}.chip.off[data-v-5ee7e46a]{color:var(--text-muted);border-color:var(--border-subtle);opacity:.55}.chip[data-v-5ee7e46a]:disabled{cursor:default;opacity:.35}.stream[data-v-5ee7e46a]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;max-height:520px;overflow-y:auto}.event-row[data-v-5ee7e46a]{display:flex;gap:0;align-items:center;padding:0;border-bottom:1px solid var(--bg-raised);font-size:11px}.event-row[data-v-5ee7e46a]:last-child{border-bottom:none}.event-source[data-v-5ee7e46a]{width:72px;padding:6px 8px;color:var(--text-muted);text-align:right;border-right:1px solid var(--bg-raised);flex-shrink:0}.event-action[data-v-5ee7e46a]{width:152px;padding:6px 8px;color:var(--text-muted);flex-shrink:0}.event-action.complete[data-v-5ee7e46a],.event-action.fire[data-v-5ee7e46a],.event-action.execution-succeeded[data-v-5ee7e46a],.event-action.step-succeeded[data-v-5ee7e46a]{color:var(--color-green)}.event-action.step-routed[data-v-5ee7e46a]{color:var(--color-blue)}.event-action.failed[data-v-5ee7e46a],.event-action.error[data-v-5ee7e46a],.event-action.execution-failed[data-v-5ee7e46a],.event-action.step-failed[data-v-5ee7e46a],.event-action.execution-lease-lost[data-v-5ee7e46a]{color:var(--color-red)}.event-action.retry[data-v-5ee7e46a],.event-action.step-retry[data-v-5ee7e46a]{color:var(--color-yellow)}.event-data[data-v-5ee7e46a]{flex:1;min-width:0;padding:6px 8px;color:#666;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.event-time[data-v-5ee7e46a]{width:80px;padding:6px 8px;color:var(--text-muted);text-align:right;flex-shrink:0}.gauges[data-v-74a2dfa0]{display:flex;gap:12px;margin-bottom:8px}.gauge[data-v-74a2dfa0]{flex:1;padding:16px;background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px}.gauge-value[data-v-74a2dfa0]{display:block;font-size:28px;font-weight:600;color:var(--text-muted)}.gauge-value.lit[data-v-74a2dfa0]{color:var(--color-blue)}.gauge-value.warn[data-v-74a2dfa0]{color:var(--color-red)}.gauge-label[data-v-74a2dfa0]{display:block;font-size:10px;color:var(--text-muted);margin-top:4px;letter-spacing:.3px;text-transform:uppercase}.session-note[data-v-74a2dfa0]{font-size:10px;color:#333;margin-bottom:24px}section[data-v-74a2dfa0]{margin-top:24px}.stream[data-v-74a2dfa0]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;max-height:400px;overflow-y:auto}.event-row[data-v-74a2dfa0]{display:flex;gap:0;align-items:center;border-bottom:1px solid var(--bg-raised);font-size:11px}.event-row[data-v-74a2dfa0]:last-child{border-bottom:none}.event-action[data-v-74a2dfa0]{width:72px;padding:6px 10px;color:var(--text-muted);flex-shrink:0}.event-action.complete[data-v-74a2dfa0]{color:var(--color-green)}.event-action.failed[data-v-74a2dfa0]{color:var(--color-red)}.event-action.retry[data-v-74a2dfa0]{color:var(--color-yellow)}.event-action.new[data-v-74a2dfa0]{color:var(--text-muted)}.event-action.drain[data-v-74a2dfa0]{color:#666}.event-data[data-v-74a2dfa0]{flex:1;padding:6px 8px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.event-time[data-v-74a2dfa0]{width:80px;padding:6px 8px;color:#333;text-align:right;flex-shrink:0}.job-row[data-v-6d545d29]{display:flex;align-items:center;padding:0;border-bottom:1px solid var(--border-subtle);font-size:11px}.job-row[data-v-6d545d29]:last-child{border-bottom:none}.job-row.header[data-v-6d545d29]{font-size:10px;color:var(--text-muted);letter-spacing:.3px;text-transform:uppercase;border-bottom:1px solid var(--border)}.job-row.header span[data-v-6d545d29]{padding:8px 12px}.col-name[data-v-6d545d29]{flex:1;padding:10px 12px}.col-next[data-v-6d545d29]{width:100px;padding:10px 12px;color:#666;text-align:right}.col-in[data-v-6d545d29]{width:60px;padding:10px 12px;color:var(--text-muted);text-align:right}.col-in.soon[data-v-6d545d29]{color:var(--color-blue)}.stream[data-v-6d545d29]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;max-height:400px;overflow-y:auto}.event-row[data-v-6d545d29]{display:flex;align-items:center;border-bottom:1px solid var(--bg-raised);font-size:11px}.event-row[data-v-6d545d29]:last-child{border-bottom:none}.event-action[data-v-6d545d29]{width:52px;padding:6px 10px;color:var(--text-muted);flex-shrink:0}.event-action.fire[data-v-6d545d29]{color:var(--color-green)}.event-action.error[data-v-6d545d29]{color:var(--color-red)}.event-name[data-v-6d545d29]{flex:1;padding:6px 8px;color:#666}.event-time[data-v-6d545d29]{width:80px;padding:6px 8px;color:#333;text-align:right;flex-shrink:0}.text-view[data-v-5a4270db]{font:12px SF Mono,monospace;color:var(--text);white-space:pre-wrap;word-break:break-word;margin:0}.limiter-list[data-v-22c855ec]{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:24px}section[data-v-22c855ec]{margin-top:24px}.desc[data-v-22c855ec]{font-size:11px;color:var(--text-muted);margin-bottom:12px}.peek-form[data-v-22c855ec]{display:flex;gap:8px}.input[data-v-22c855ec]{padding:6px 10px;background:var(--bg-surface);border:1px solid var(--border);border-radius:4px;font-size:11px;color:var(--text);flex:1;font-family:inherit;outline:none}.input[data-v-22c855ec]::placeholder{color:#333}.input[data-v-22c855ec]:focus{border-color:var(--accent)}.btn[data-v-22c855ec]{padding:6px 16px;background:var(--bg-raised);color:#999;border:1px solid var(--border);border-radius:4px;cursor:pointer;font-size:11px;font-family:inherit}.btn[data-v-22c855ec]:hover{color:var(--text)}.btn[data-v-22c855ec]:disabled{opacity:.3;cursor:default}.error[data-v-22c855ec]{margin-top:10px;color:var(--color-red);font-size:11px}.graph-shell[data-v-6098c89d]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;overflow:hidden;position:relative;cursor:grab;touch-action:none}.graph-shell[data-v-6098c89d]:active{cursor:grabbing}.graph-shell svg[data-v-6098c89d]{user-select:none;-webkit-user-select:none}.graph-shell.fullscreen[data-v-6098c89d]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;border-radius:0;border:none;background:var(--bg)}.graph-controls[data-v-6098c89d]{position:absolute;top:10px;right:10px;z-index:2;display:flex;gap:4px}.graph-controls button[data-v-6098c89d]{padding:4px 10px;background:var(--bg-raised);border:1px solid var(--border);border-radius:4px;color:#888;font-size:11px;font-family:inherit;cursor:pointer}.graph-controls button[data-v-6098c89d]:hover{background:var(--bg-hover);color:#ccc}.graph[data-v-6098c89d]{width:100%;min-height:420px;display:block}.fullscreen .graph[data-v-6098c89d]{min-height:100vh}.edge[data-v-6098c89d]{fill:none;stroke:#232323;stroke-width:3}.edge-seen[data-v-6098c89d]{stroke:#3b3b3b}.edge-active[data-v-6098c89d]{stroke:#8fb3ff}.edge-label[data-v-6098c89d]{fill:#4a4a4a;font-size:11px;font-family:inherit}.node[data-v-6098c89d]{cursor:pointer}.node rect[data-v-6098c89d]{fill:#151515;stroke:#262626;stroke-width:1.5}.node.selected rect[data-v-6098c89d]{stroke:#6b7280}.node.current rect[data-v-6098c89d],.node.running rect[data-v-6098c89d]{stroke:#5b8cff}.node.succeeded rect[data-v-6098c89d],.node.decision-success rect[data-v-6098c89d]{stroke:#3d8f63}.node.failed rect[data-v-6098c89d]{stroke:#a14a4a}.node.activity .node-type[data-v-6098c89d]{fill:#7aa2f7}.node.decision .node-type[data-v-6098c89d]{fill:#e0af68}.node.succeed .node-type[data-v-6098c89d]{fill:#73daca}.node.fail .node-type[data-v-6098c89d]{fill:#f7768e}.node-name[data-v-6098c89d]{fill:var(--text-bright);font-size:13px;font-weight:600}.node-type[data-v-6098c89d],.node-meta[data-v-6098c89d]{font-family:inherit;font-size:11px}.node-meta[data-v-6098c89d]{fill:#5f5f5f}.workflow-layout[data-v-124a0c49]{display:grid;grid-template-columns:280px 1fr;gap:16px}.wf-sidebar[data-v-124a0c49]{display:flex;flex-direction:column;gap:8px}.wf-sidebar .card.active[data-v-124a0c49]{border-color:var(--accent)}.detail[data-v-124a0c49]{display:flex;flex-direction:column;gap:16px}.headline[data-v-124a0c49]{display:flex;justify-content:space-between;align-items:flex-end}.headline-name[data-v-124a0c49]{font-size:14px;font-weight:600;color:var(--text-bright)}.headline-sub[data-v-124a0c49]{margin-top:2px;color:var(--text-muted);font-size:11px}.headline-stats[data-v-124a0c49]{display:flex;gap:10px;color:var(--text-muted);font-size:11px}.filters[data-v-24631062]{display:flex;gap:8px;margin-bottom:16px}.execution-layout[data-v-24631062]{display:grid;grid-template-columns:240px minmax(0,1fr) 340px;gap:14px;align-items:start}.list[data-v-24631062]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;overflow:hidden;max-height:calc(100vh - 240px);overflow-y:auto}.execution-row[data-v-24631062]{padding:10px 12px;border-bottom:1px solid var(--bg-raised);cursor:pointer}.execution-row[data-v-24631062]:last-child{border-bottom:none}.execution-row.active[data-v-24631062]{background:var(--bg-raised)}.execution-main[data-v-24631062]{display:flex;justify-content:space-between;gap:8px}.execution-workflow[data-v-24631062]{color:var(--text-bright);font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.execution-id[data-v-24631062]{color:#666;font-size:11px;flex-shrink:0}.execution-meta[data-v-24631062]{display:flex;justify-content:space-between;gap:6px;margin-top:4px;color:var(--text-muted);font-size:10px}.execution-row.running .execution-workflow[data-v-24631062]{color:#8fb3ff}.execution-row.failed .execution-workflow[data-v-24631062]{color:#d87a7a}.execution-row.succeeded .execution-workflow[data-v-24631062]{color:#7ec49b}.headline[data-v-24631062]{margin-bottom:14px}.headline-name[data-v-24631062]{font-size:14px;font-weight:600;color:var(--text-bright)}.headline-sub[data-v-24631062]{margin-top:2px;color:var(--text-muted);font-size:11px}.center[data-v-24631062]{display:flex;flex-direction:column;gap:12px;min-width:0}.inspector[data-v-24631062]{display:flex;flex-direction:column;gap:10px;max-height:calc(100vh - 240px);overflow-y:auto}.step-hint[data-v-24631062]{color:#383838;font-size:10px;margin-bottom:8px;font-style:italic}.timeline[data-v-24631062]{max-height:420px;overflow-y:auto}.timeline-row[data-v-24631062]{display:flex;gap:6px;align-items:baseline;border-bottom:1px solid var(--border-subtle);padding:6px 12px;font-size:10px;white-space:nowrap}.timeline-row[data-v-24631062]:last-child{border-bottom:none}.timeline-type[data-v-24631062]{color:#b1b1b1;flex-shrink:0}.timeline-step[data-v-24631062]{color:#666;flex:1;overflow:hidden;text-overflow:ellipsis}.timeline-time[data-v-24631062]{color:var(--text-muted);flex-shrink:0}.realtime-shell[data-v-d6b8bed2]{display:flex;flex-direction:column;flex:1;overflow:hidden}.rt-main[data-v-d6b8bed2]{display:flex;flex:1;overflow:hidden}.tab-bar-right[data-v-d6b8bed2]{margin-left:auto;display:flex;align-items:center;gap:8px}.tab-bar a[data-v-d6b8bed2]{text-decoration:none}.cells-page[data-v-183abe97]{display:flex;flex-direction:column;gap:12px}.cells-toolbar[data-v-183abe97]{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.left-group[data-v-183abe97]{display:flex;align-items:center;gap:12px}.graph-tabs[data-v-183abe97]{display:flex;border:1px solid var(--border);border-radius:4px;overflow:hidden}.graph-tabs button[data-v-183abe97]{padding:6px 14px;background:var(--bg-surface);color:var(--text-muted);border:none;font:inherit;font-size:11px;cursor:pointer;border-right:1px solid var(--border)}.graph-tabs button[data-v-183abe97]:last-child{border-right:none}.graph-tabs button.active[data-v-183abe97]{background:var(--accent-dim);color:var(--accent-text)}.graph-tabs button[data-v-183abe97]:hover:not(.active){background:var(--bg-hover);color:var(--text)}.view-toggle[data-v-183abe97]{display:flex;border:1px solid var(--border);border-radius:4px;overflow:hidden}.view-toggle button[data-v-183abe97]{padding:6px 14px;background:var(--bg-surface);color:var(--text-muted);border:none;font:inherit;font-size:11px;cursor:pointer;border-right:1px solid var(--border)}.view-toggle button[data-v-183abe97]:last-child{border-right:none}.view-toggle button.active[data-v-183abe97]{background:var(--accent-dim);color:var(--accent-text)}.view-toggle button[data-v-183abe97]:hover:not(.active){background:var(--bg-hover);color:var(--text)}.stats[data-v-183abe97]{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--text-muted)}.dot[data-v-183abe97]{width:3px;height:3px;background:var(--text-muted);border-radius:50%}.cells-layout[data-v-183abe97]{display:flex;flex-direction:column;gap:12px;min-height:0}.cells-main[data-v-183abe97]{min-width:0;overflow:auto}.cells-detail[data-v-183abe97]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;padding:12px}.detail-grid[data-v-183abe97]{display:grid;gap:10px;grid-template-columns:minmax(0,1fr) 240px}.detail-main[data-v-183abe97]{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));min-width:0}.detail-side[data-v-183abe97]{display:flex;flex-direction:column;gap:10px}.detail-card[data-v-183abe97]{background:var(--bg);border:1px solid var(--border-subtle);border-radius:3px;padding:10px;min-width:0;display:flex;flex-direction:column;gap:6px}.detail-card.span-2[data-v-183abe97]{grid-column:span 2}@media(max-width:900px){.detail-grid[data-v-183abe97]{grid-template-columns:minmax(0,1fr)}.detail-card.span-2[data-v-183abe97]{grid-column:span 1}}.scroll-y[data-v-183abe97]{max-height:220px;overflow-y:auto}.kv-list[data-v-183abe97]{display:flex;flex-direction:column;gap:8px}.kv-list-row[data-v-183abe97]{display:flex;flex-direction:column;gap:2px;min-width:0}.kv-list-key[data-v-183abe97]{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.kv-list-val[data-v-183abe97]{font-size:11px;color:var(--text);word-break:break-word;font-family:SF Mono,monospace}.cell-row[data-v-183abe97]{display:flex;align-items:center;border-bottom:1px solid var(--border-subtle);font-size:11px;cursor:pointer}.cell-row[data-v-183abe97]:last-child{border-bottom:none}.cell-row[data-v-183abe97]:hover{background:var(--bg-hover)}.cell-row.selected[data-v-183abe97]{background:var(--accent-dim)}.cell-row.recent[data-v-183abe97]{animation:flash-183abe97 .8s ease-out}.cell-row.header[data-v-183abe97]{font-size:10px;color:var(--text-muted);letter-spacing:.3px;text-transform:uppercase;cursor:default;border-bottom:1px solid var(--border)}.cell-row.header[data-v-183abe97]:hover{background:transparent}@keyframes flash-183abe97{0%{background:var(--accent-dim)}to{background:transparent}}.col-name[data-v-183abe97]{flex:0 0 200px;padding:8px 12px;color:var(--text-bright)}.col-value[data-v-183abe97]{flex:1;padding:8px 12px;color:var(--text);font-family:SF Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-deps[data-v-183abe97]{flex:0 0 200px;padding:8px 12px;color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.col-status[data-v-183abe97]{flex:0 0 80px;padding:8px 12px}.col-updated[data-v-183abe97]{flex:0 0 100px;padding:8px 12px;color:var(--text-muted);text-align:right}.graph-wrap[data-v-183abe97]{background:var(--bg-surface);border:1px solid var(--border-subtle);border-radius:4px;padding:8px;overflow:auto;width:100%;box-sizing:border-box}.graph-wrap svg[data-v-183abe97]{display:block}.node-group[data-v-183abe97]{cursor:pointer}.node-group rect[data-v-183abe97]{fill:var(--bg-raised);stroke:var(--border);stroke-width:1}.node-group:hover rect[data-v-183abe97]{stroke:var(--text-muted)}.node-group.selected rect[data-v-183abe97]{stroke:var(--accent);stroke-width:1.5}.node-group.recent rect[data-v-183abe97]{animation:pulse-rect-183abe97 .8s ease-out}@keyframes pulse-rect-183abe97{0%{fill:var(--accent-dim);stroke:var(--accent)}to{fill:var(--bg-raised);stroke:var(--border)}}.edge-line[data-v-183abe97]{stroke:var(--border)}.edge-line.recent[data-v-183abe97]{animation:pulse-edge-183abe97 .8s ease-out}@keyframes pulse-edge-183abe97{0%{stroke:var(--accent)}to{stroke:var(--border)}}.node-name[data-v-183abe97]{fill:var(--text-bright);font:600 11px SF Mono,monospace}.node-value[data-v-183abe97]{fill:var(--text);font:10px SF Mono,monospace}.detail-header[data-v-183abe97]{display:flex;align-items:center;gap:8px;padding-bottom:10px;margin-bottom:12px;border-bottom:1px solid var(--border)}.detail-name[data-v-183abe97]{flex:1;font-size:12px;color:var(--text-bright);font-weight:600}.detail-status[data-v-183abe97]{font-size:9px;text-transform:uppercase;letter-spacing:.5px}.detail-spacer[data-v-183abe97]{flex:1}.detail-close[data-v-183abe97]{cursor:pointer;color:var(--text-muted);font-size:16px;padding:0 4px}.detail-close[data-v-183abe97]:hover{color:var(--text-bright)}.detail-section[data-v-183abe97]{margin-bottom:14px}.detail-label[data-v-183abe97]{font-size:9px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px}.detail-content[data-v-183abe97]{font-size:11px;color:var(--text);word-break:break-word}.detail-pre[data-v-183abe97]{font:11px SF Mono,monospace;color:var(--text);background:var(--bg);border:1px solid var(--border-subtle);border-radius:3px;padding:8px;white-space:pre-wrap;overflow-x:auto;max-height:220px}.detail-label[data-v-183abe97]{display:flex;align-items:center;gap:8px}.detail-label-meta[data-v-183abe97]{font-size:9px;color:var(--text);text-transform:none;letter-spacing:0;font-family:SF Mono,monospace}.history-disabled[data-v-183abe97]{font-size:10px;color:var(--text-muted);line-height:1.5}.history-disabled code[data-v-183abe97]{background:var(--bg-raised);color:var(--text);padding:1px 4px;border-radius:2px;font-size:10px}.history-list[data-v-183abe97]{display:flex;flex-direction:column;gap:2px;max-height:240px;overflow-y:auto}.history-entry[data-v-183abe97]{display:flex;gap:8px;align-items:center;font-size:10px;padding:3px 6px;background:var(--bg);border-radius:2px}.history-time[data-v-183abe97]{flex:0 0 70px;color:var(--text-muted)}.history-value[data-v-183abe97]{flex:1;color:var(--text);font-family:SF Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.empty[data-v-183abe97]{padding:20px;text-align:center;color:var(--text-muted);font-size:11px}.empty-small[data-v-183abe97]{padding:6px;text-align:center;color:var(--text-muted);font-size:10px}
|