@clemrig/flow-ui 0.1.1 → 0.1.2
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 +1 -1
- package/dist/static/dashboard.js +4 -2
- package/dist/static/timeline.js +58 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install -g @clemrig/flow-ui
|
|
|
11
11
|
flow-ui [RUNS_DIR] [--port PORT]
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`flow-ui` serves the runs kept in `RUNS_DIR` (default: `.flow/runs`, where `@clemrig/flow` keeps them; a `RUNS_DIR` given must be an existing directory) on `127.0.0.1`, on `PORT` or a port the system chooses, prints its URL and stops on Ctrl-C. The page lists the runs with their workflow, status, current stage, duration, estimated cost and last update, and for a run its runtimes, a timeline with one block per stage (agent tools and tokens, journal, decision), its correction counters and its result. It follows a running run as it goes. A result shows the run's validated data as JSON.
|
|
14
|
+
`flow-ui` serves the runs kept in `RUNS_DIR` (default: `.flow/runs`, where `@clemrig/flow` keeps them; a `RUNS_DIR` given must be an existing directory) on `127.0.0.1`, on `PORT` or a port the system chooses, prints its URL and stops on Ctrl-C. The page lists the runs with their workflow, status, current stage, duration, estimated cost and last update, and for a run its runtimes, a timeline with one block per stage (the agent call's model and settings, its tools and tokens, journal, decision), its correction counters and its result. It follows a running run as it goes. A result shows the run's validated data as JSON.
|
|
15
15
|
|
|
16
16
|
To watch a run on another machine, forward the same port through SSH: `ssh -L 4321:127.0.0.1:4321 machine`, run `flow-ui --port 4321` there, and open `http://localhost:4321/`.
|
|
17
17
|
|
package/dist/static/dashboard.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* `follow.js` follows it. Text only, never HTML.
|
|
5
5
|
*/
|
|
6
6
|
import { follower } from "./follow.js";
|
|
7
|
-
import { cost, duration, timeline } from "./timeline.js";
|
|
7
|
+
import { cost, duration, settingsLines, timeline } from "./timeline.js";
|
|
8
8
|
|
|
9
9
|
/** @typedef {import("@clemrig/flow").RunEvent} RunEvent */
|
|
10
10
|
/** @typedef {import("./timeline.js").Block} Block */
|
|
@@ -142,6 +142,8 @@ function showBlock(block) {
|
|
|
142
142
|
const { call } = block;
|
|
143
143
|
if (call?.model)
|
|
144
144
|
line(`${call.runtime} ${call.model} · session ${call.session}`);
|
|
145
|
+
if (call?.settings)
|
|
146
|
+
for (const setting of settingsLines(call.settings)) line(setting);
|
|
145
147
|
for (const tool of block.tools)
|
|
146
148
|
line(
|
|
147
149
|
tool.status === "running"
|
|
@@ -150,7 +152,7 @@ function showBlock(block) {
|
|
|
150
152
|
);
|
|
151
153
|
if (call?.usage)
|
|
152
154
|
line(
|
|
153
|
-
`${call.scope === "session" ? "Session total" : "Call"}: ${tokenLine(call.usage)} · ${cost(call.usage.costUsd, false)}`,
|
|
155
|
+
`${call.scope === "session" ? "Session total" : "Call"}: ${tokenLine(call.usage)} · ${cost(call.usage.costUsd ?? null, false)}`,
|
|
154
156
|
);
|
|
155
157
|
else if (block.tokens)
|
|
156
158
|
line(
|
package/dist/static/timeline.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
3
|
* The dashboard's pure logic: a run's events grouped into one block per stage
|
|
4
|
-
* execution, and the formats of durations and
|
|
4
|
+
* execution, and the formats of durations, costs and agent settings. Served as
|
|
5
|
+
* is to the browser.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
/** @typedef {import("@clemrig/flow").RunEvent} RunEvent */
|
|
8
9
|
/** @typedef {import("@clemrig/flow").AgentActivity} AgentActivity */
|
|
10
|
+
/** @typedef {import("@clemrig/flow").AgentSettings} AgentSettings */
|
|
9
11
|
/** @typedef {import("@clemrig/flow").TokenCounts} TokenCounts */
|
|
10
12
|
/** @typedef {import("@clemrig/flow").AgentUsage} AgentUsage */
|
|
11
13
|
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
* @property {string} [runtime]
|
|
15
17
|
* @property {string} [model]
|
|
16
18
|
* @property {string} [session]
|
|
19
|
+
* @property {AgentSettings} [settings] Absent from runs recorded before calls recorded their settings.
|
|
17
20
|
* @property {"running" | "completed" | "failed"} status
|
|
18
21
|
* @property {AgentUsage} [usage] As the runtime announced it at the end of the call.
|
|
19
22
|
* @property {"call" | "session"} [scope] Whether `usage` is the call's own or its session's total.
|
|
@@ -72,8 +75,8 @@ function apply(target, activity) {
|
|
|
72
75
|
switch (activity.kind) {
|
|
73
76
|
case "call":
|
|
74
77
|
if (activity.status === "started") {
|
|
75
|
-
const { runtime, model, session } = activity;
|
|
76
|
-
target.call = { runtime, model, session, status: "running" };
|
|
78
|
+
const { runtime, model, session, settings } = activity;
|
|
79
|
+
target.call = { runtime, model, session, settings, status: "running" };
|
|
77
80
|
} else
|
|
78
81
|
target.call = {
|
|
79
82
|
...target.call,
|
|
@@ -168,10 +171,61 @@ export function duration(ms) {
|
|
|
168
171
|
return `${hours ? `${hours} h ` : ""}${minutes} min ${seconds % 60} s`;
|
|
169
172
|
}
|
|
170
173
|
|
|
174
|
+
/** Setting names that are not plain words. */
|
|
175
|
+
const settingLabels = /** @type {Record<string, string>} */ ({
|
|
176
|
+
mcpServers: "MCP servers",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* A setting's name as the operator reads it: `permissionMode` → `permission mode`.
|
|
181
|
+
* @param {string} key
|
|
182
|
+
* @returns {string}
|
|
183
|
+
*/
|
|
184
|
+
function settingLabel(key) {
|
|
185
|
+
return (
|
|
186
|
+
settingLabels[key] ??
|
|
187
|
+
key.replace(/[A-Z]/g, (letter) => ` ${letter.toLowerCase()}`)
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* An agent call's settings as its runtime recorded them, whatever the runtime:
|
|
193
|
+
* its thinking, its other single values and its timeout, then each list, its
|
|
194
|
+
* tools even when empty, the others only with items.
|
|
195
|
+
* @param {AgentSettings} settings
|
|
196
|
+
* @returns {string[]}
|
|
197
|
+
*/
|
|
198
|
+
export function settingsLines(settings) {
|
|
199
|
+
const entries = Object.entries(settings);
|
|
200
|
+
const values = entries.flatMap(([key, value]) =>
|
|
201
|
+
key === "thinking" ||
|
|
202
|
+
key === "timeoutMs" ||
|
|
203
|
+
value === undefined ||
|
|
204
|
+
Array.isArray(value)
|
|
205
|
+
? []
|
|
206
|
+
: [`${settingLabel(key)} ${String(value)}`],
|
|
207
|
+
);
|
|
208
|
+
const lists = entries.flatMap(([key, value]) => {
|
|
209
|
+
if (!Array.isArray(value) || (!value.length && key !== "tools")) return [];
|
|
210
|
+
const label = settingLabel(key);
|
|
211
|
+
return [
|
|
212
|
+
`${label[0]?.toUpperCase()}${label.slice(1)}: ${value.join(", ") || "none"}`,
|
|
213
|
+
];
|
|
214
|
+
});
|
|
215
|
+
return [
|
|
216
|
+
[
|
|
217
|
+
`thinking ${settings.thinking}`,
|
|
218
|
+
...values,
|
|
219
|
+
`timeout ${duration(settings.timeoutMs)}`,
|
|
220
|
+
].join(" · "),
|
|
221
|
+
...lists,
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
|
|
171
225
|
/**
|
|
172
226
|
* An estimated cost as the runtimes announced it; unknown without any measure.
|
|
173
227
|
* @param {number | null} usd
|
|
174
|
-
* @param {boolean} partial Some agent call announced no
|
|
228
|
+
* @param {boolean} partial Some agent call announced no cost.
|
|
175
229
|
* @returns {string}
|
|
176
230
|
*/
|
|
177
231
|
export function cost(usd, partial) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clemrig/flow-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "A local read-only dashboard of the runs of @clemrig/flow workflows",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,6 +34,6 @@
|
|
|
34
34
|
"prepack": "npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@clemrig/flow": "0.
|
|
37
|
+
"@clemrig/flow": "0.3.0"
|
|
38
38
|
}
|
|
39
39
|
}
|