groove-dev 0.24.5 → 0.24.6
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/node_modules/@groove-dev/daemon/src/api.js +3 -0
- package/node_modules/@groove-dev/daemon/src/process.js +3 -0
- package/node_modules/@groove-dev/gui/dist/assets/{index-CyUFyn1h.js → index-CuL9rJki.js} +125 -125
- package/node_modules/@groove-dev/gui/dist/assets/index-DjxlUkR9.css +1 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/fleet-panel.jsx +16 -4
- package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +22 -2
- package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +96 -116
- package/package.json +1 -1
- package/packages/daemon/src/api.js +3 -0
- package/packages/daemon/src/process.js +3 -0
- package/packages/gui/dist/assets/{index-CyUFyn1h.js → index-CuL9rJki.js} +125 -125
- package/packages/gui/dist/assets/index-DjxlUkR9.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/src/components/dashboard/fleet-panel.jsx +16 -4
- package/packages/gui/src/components/dashboard/intel-panel.jsx +22 -2
- package/packages/gui/src/components/dashboard/token-chart.jsx +96 -116
- package/node_modules/@groove-dev/gui/dist/assets/index-AXS9JOJD.css +0 -1
- package/packages/gui/dist/assets/index-AXS9JOJD.css +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
2
|
-
import { useRef, useEffect, useState, useCallback, memo } from 'react';
|
|
2
|
+
import { useRef, useEffect, useState, useCallback, useMemo, memo } from 'react';
|
|
3
3
|
import { HEX, hexAlpha } from '../../lib/theme-hex';
|
|
4
|
-
import { fmtNum,
|
|
4
|
+
import { fmtNum, fmtPct } from '../../lib/format';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Modern
|
|
8
|
-
*
|
|
7
|
+
* Modern burn-rate chart — shows tokens/interval (velocity) + running agent count
|
|
8
|
+
* instead of monotonically climbing cumulative values. Self-sizing.
|
|
9
9
|
*/
|
|
10
10
|
const TokenChart = memo(function TokenChart({ data }) {
|
|
11
11
|
const containerRef = useRef(null);
|
|
@@ -14,11 +14,27 @@ const TokenChart = memo(function TokenChart({ data }) {
|
|
|
14
14
|
const [hover, setHover] = useState(null);
|
|
15
15
|
|
|
16
16
|
const { width, height } = size;
|
|
17
|
-
// Minimal padding — just enough for floating labels to breathe
|
|
18
17
|
const pad = { top: 28, right: 12, bottom: 8, left: 12 };
|
|
19
18
|
const w = Math.max(width - pad.left - pad.right, 0);
|
|
20
19
|
const h = Math.max(height - pad.top - pad.bottom, 0);
|
|
21
20
|
|
|
21
|
+
// Derive burn rate + cache rate from consecutive snapshots
|
|
22
|
+
const chartData = useMemo(() => {
|
|
23
|
+
if (!data || data.length < 2) return [];
|
|
24
|
+
return data.slice(1).map((d, i) => {
|
|
25
|
+
const prev = data[i];
|
|
26
|
+
const dt = (d.t - prev.t) / 60000; // minutes
|
|
27
|
+
const dTokens = Math.max((d.tokens || 0) - (prev.tokens || 0), 0);
|
|
28
|
+
return {
|
|
29
|
+
burnRate: dt > 0 ? Math.round(dTokens / dt) : 0, // tokens/min
|
|
30
|
+
cacheHitRate: d.cacheHitRate || 0,
|
|
31
|
+
running: d.running || 0,
|
|
32
|
+
agents: d.agents || 0,
|
|
33
|
+
t: d.t,
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}, [data]);
|
|
37
|
+
|
|
22
38
|
// Self-size
|
|
23
39
|
useEffect(() => {
|
|
24
40
|
const el = containerRef.current;
|
|
@@ -33,20 +49,20 @@ const TokenChart = memo(function TokenChart({ data }) {
|
|
|
33
49
|
|
|
34
50
|
const onMouseMove = useCallback((e) => {
|
|
35
51
|
const canvas = canvasRef.current;
|
|
36
|
-
if (!canvas || !
|
|
52
|
+
if (!canvas || !chartData.length || w <= 0) return;
|
|
37
53
|
const rect = canvas.getBoundingClientRect();
|
|
38
54
|
const x = e.clientX - rect.left - pad.left;
|
|
39
55
|
if (x < 0 || x > w) { setHover(null); return; }
|
|
40
|
-
const index = Math.round((x / w) * (
|
|
41
|
-
setHover({ x: pad.left + (index / (
|
|
42
|
-
}, [
|
|
56
|
+
const index = Math.round((x / w) * (chartData.length - 1));
|
|
57
|
+
setHover({ x: pad.left + (index / Math.max(chartData.length - 1, 1)) * w, index });
|
|
58
|
+
}, [chartData, w, pad.left]);
|
|
43
59
|
|
|
44
60
|
const onMouseLeave = useCallback(() => setHover(null), []);
|
|
45
61
|
|
|
46
62
|
// Draw
|
|
47
63
|
useEffect(() => {
|
|
48
64
|
const canvas = canvasRef.current;
|
|
49
|
-
if (!canvas || !
|
|
65
|
+
if (!canvas || !chartData.length || width <= 0 || height <= 0 || w <= 0 || h <= 0) return;
|
|
50
66
|
const ctx = canvas.getContext('2d');
|
|
51
67
|
const dpr = window.devicePixelRatio || 1;
|
|
52
68
|
|
|
@@ -55,21 +71,31 @@ const TokenChart = memo(function TokenChart({ data }) {
|
|
|
55
71
|
ctx.scale(dpr, dpr);
|
|
56
72
|
ctx.clearRect(0, 0, width, height);
|
|
57
73
|
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const hasCacheData = caches.some((c) => c !== null && c > 0);
|
|
74
|
+
const burns = chartData.map((d) => d.burnRate);
|
|
75
|
+
const caches = chartData.map((d) => d.cacheHitRate);
|
|
76
|
+
const running = chartData.map((d) => d.running);
|
|
77
|
+
const maxBurn = Math.max(...burns, 100);
|
|
78
|
+
const maxRunning = Math.max(...running, 1);
|
|
64
79
|
|
|
65
|
-
const xAt = (i) => pad.left + (i / Math.max(
|
|
66
|
-
const
|
|
67
|
-
const yCost = (v) => pad.top + h - (v / maxC) * h;
|
|
80
|
+
const xAt = (i) => pad.left + (i / Math.max(chartData.length - 1, 1)) * w;
|
|
81
|
+
const yBurn = (v) => pad.top + h - (v / maxBurn) * h;
|
|
68
82
|
const yCache = (v) => pad.top + h - (v * h);
|
|
69
83
|
|
|
70
|
-
// ──
|
|
84
|
+
// ── Running agents bars (background, subtle) ────────────
|
|
85
|
+
const barW = Math.max(w / chartData.length - 1, 2);
|
|
86
|
+
for (let i = 0; i < chartData.length; i++) {
|
|
87
|
+
const r = running[i];
|
|
88
|
+
if (r <= 0) continue;
|
|
89
|
+
const barH = (r / maxRunning) * h * 0.3; // max 30% height
|
|
90
|
+
const x = xAt(i) - barW / 2;
|
|
91
|
+
const y = pad.top + h - barH;
|
|
92
|
+
ctx.fillStyle = hexAlpha(HEX.surface5, 0.5);
|
|
93
|
+
ctx.fillRect(x, y, barW, barH);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ── Subtle horizontal guidelines ────────────────────────
|
|
71
97
|
ctx.setLineDash([2, 4]);
|
|
72
|
-
ctx.strokeStyle = hexAlpha(HEX.text4, 0.
|
|
98
|
+
ctx.strokeStyle = hexAlpha(HEX.text4, 0.2);
|
|
73
99
|
ctx.lineWidth = 1;
|
|
74
100
|
for (let i = 1; i <= 3; i++) {
|
|
75
101
|
const y = pad.top + (h / 4) * i;
|
|
@@ -80,77 +106,58 @@ const TokenChart = memo(function TokenChart({ data }) {
|
|
|
80
106
|
}
|
|
81
107
|
ctx.setLineDash([]);
|
|
82
108
|
|
|
83
|
-
// ── Floating Y
|
|
109
|
+
// ── Floating Y labels ───────────────────────────────────
|
|
84
110
|
ctx.font = "9px 'JetBrains Mono Variable', monospace";
|
|
85
111
|
ctx.textAlign = 'left';
|
|
86
|
-
ctx.fillStyle = hexAlpha(HEX.text3, 0.
|
|
87
|
-
|
|
88
|
-
ctx.fillText(fmtNum(
|
|
89
|
-
// Mid label
|
|
90
|
-
ctx.fillText(fmtNum(maxT / 2), pad.left + 4, pad.top + h / 2 + 4);
|
|
112
|
+
ctx.fillStyle = hexAlpha(HEX.text3, 0.5);
|
|
113
|
+
ctx.fillText(`${fmtNum(maxBurn)}/m`, pad.left + 4, pad.top + 10);
|
|
114
|
+
ctx.fillText(`${fmtNum(Math.round(maxBurn / 2))}/m`, pad.left + 4, pad.top + h / 2 + 4);
|
|
91
115
|
|
|
92
|
-
// ──
|
|
116
|
+
// ── Burn rate area fill ─────────────────────────────────
|
|
93
117
|
ctx.beginPath();
|
|
94
118
|
ctx.moveTo(pad.left, pad.top + h);
|
|
95
|
-
for (let i = 0; i <
|
|
96
|
-
ctx.lineTo(xAt(i),
|
|
119
|
+
for (let i = 0; i < chartData.length; i++) {
|
|
120
|
+
ctx.lineTo(xAt(i), yBurn(burns[i]));
|
|
97
121
|
}
|
|
98
|
-
ctx.lineTo(xAt(
|
|
122
|
+
ctx.lineTo(xAt(chartData.length - 1), pad.top + h);
|
|
99
123
|
ctx.closePath();
|
|
100
124
|
const grad = ctx.createLinearGradient(0, pad.top, 0, pad.top + h);
|
|
101
|
-
grad.addColorStop(0, hexAlpha(HEX.accent, 0.
|
|
125
|
+
grad.addColorStop(0, hexAlpha(HEX.accent, 0.2));
|
|
102
126
|
grad.addColorStop(0.7, hexAlpha(HEX.accent, 0.04));
|
|
103
127
|
grad.addColorStop(1, hexAlpha(HEX.accent, 0));
|
|
104
128
|
ctx.fillStyle = grad;
|
|
105
129
|
ctx.fill();
|
|
106
130
|
|
|
107
|
-
// ──
|
|
131
|
+
// ── Burn rate line ──────────────────────────────────────
|
|
108
132
|
ctx.beginPath();
|
|
109
133
|
ctx.strokeStyle = HEX.accent;
|
|
110
134
|
ctx.lineWidth = 1.5;
|
|
111
135
|
ctx.lineJoin = 'round';
|
|
112
|
-
for (let i = 0; i <
|
|
113
|
-
const x = xAt(i);
|
|
114
|
-
const y = yToken(tokens[i]);
|
|
115
|
-
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
|
|
116
|
-
}
|
|
117
|
-
ctx.stroke();
|
|
118
|
-
|
|
119
|
-
// ── Cost line (dashed, subtle) ──────────────────────────
|
|
120
|
-
ctx.beginPath();
|
|
121
|
-
ctx.strokeStyle = hexAlpha(HEX.warning, 0.6);
|
|
122
|
-
ctx.lineWidth = 1;
|
|
123
|
-
ctx.lineJoin = 'round';
|
|
124
|
-
ctx.setLineDash([5, 4]);
|
|
125
|
-
for (let i = 0; i < data.length; i++) {
|
|
136
|
+
for (let i = 0; i < chartData.length; i++) {
|
|
126
137
|
const x = xAt(i);
|
|
127
|
-
const y =
|
|
138
|
+
const y = yBurn(burns[i]);
|
|
128
139
|
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
|
|
129
140
|
}
|
|
130
141
|
ctx.stroke();
|
|
131
|
-
ctx.setLineDash([]);
|
|
132
142
|
|
|
133
|
-
// ── Cache hit rate line
|
|
143
|
+
// ── Cache hit rate line ─────────────────────────────────
|
|
144
|
+
const hasCacheData = caches.some((c) => c > 0);
|
|
134
145
|
if (hasCacheData) {
|
|
135
146
|
ctx.beginPath();
|
|
136
147
|
ctx.strokeStyle = hexAlpha(HEX.info, 0.45);
|
|
137
148
|
ctx.lineWidth = 1;
|
|
138
149
|
ctx.lineJoin = 'round';
|
|
139
150
|
ctx.setLineDash([2, 3]);
|
|
140
|
-
let
|
|
141
|
-
for (let i = 0; i < data.length; i++) {
|
|
142
|
-
const c = caches[i];
|
|
143
|
-
if (c === null || c === undefined) continue;
|
|
151
|
+
for (let i = 0; i < chartData.length; i++) {
|
|
144
152
|
const x = xAt(i);
|
|
145
|
-
const y = yCache(
|
|
146
|
-
|
|
147
|
-
else ctx.lineTo(x, y);
|
|
153
|
+
const y = yCache(caches[i]);
|
|
154
|
+
i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
|
|
148
155
|
}
|
|
149
156
|
ctx.stroke();
|
|
150
157
|
ctx.setLineDash([]);
|
|
151
158
|
}
|
|
152
159
|
|
|
153
|
-
// ── Inline legend (top-right
|
|
160
|
+
// ── Inline legend (top-right) ───────────────────────────
|
|
154
161
|
ctx.font = "9px 'Inter Variable', sans-serif";
|
|
155
162
|
ctx.textAlign = 'right';
|
|
156
163
|
let rx = width - pad.right - 4;
|
|
@@ -158,99 +165,72 @@ const TokenChart = memo(function TokenChart({ data }) {
|
|
|
158
165
|
|
|
159
166
|
if (hasCacheData) {
|
|
160
167
|
ctx.fillStyle = hexAlpha(HEX.info, 0.5);
|
|
161
|
-
ctx.fillText('Cache', rx, ly);
|
|
162
|
-
rx -= ctx.measureText('Cache').width + 4;
|
|
163
|
-
ctx.beginPath();
|
|
164
|
-
|
|
165
|
-
ctx.fillStyle = hexAlpha(HEX.info, 0.5);
|
|
166
|
-
ctx.fill();
|
|
167
|
-
rx -= 12;
|
|
168
|
+
ctx.fillText('Cache %', rx, ly);
|
|
169
|
+
rx -= ctx.measureText('Cache %').width + 4;
|
|
170
|
+
ctx.beginPath(); ctx.arc(rx, ly - 3, 2.5, 0, Math.PI * 2); ctx.fill();
|
|
171
|
+
rx -= 14;
|
|
168
172
|
}
|
|
169
173
|
|
|
170
|
-
ctx.fillStyle = hexAlpha(HEX.
|
|
171
|
-
ctx.fillText('
|
|
172
|
-
rx -= ctx.measureText('
|
|
173
|
-
ctx.beginPath();
|
|
174
|
-
|
|
175
|
-
ctx.fillStyle = hexAlpha(HEX.warning, 0.7);
|
|
176
|
-
ctx.fill();
|
|
177
|
-
rx -= 12;
|
|
174
|
+
ctx.fillStyle = hexAlpha(HEX.surface5, 0.7);
|
|
175
|
+
ctx.fillText('Agents', rx, ly);
|
|
176
|
+
rx -= ctx.measureText('Agents').width + 4;
|
|
177
|
+
ctx.beginPath(); ctx.arc(rx, ly - 3, 2.5, 0, Math.PI * 2); ctx.fill();
|
|
178
|
+
rx -= 14;
|
|
178
179
|
|
|
179
180
|
ctx.fillStyle = HEX.accent;
|
|
180
|
-
ctx.fillText('
|
|
181
|
-
rx -= ctx.measureText('
|
|
182
|
-
ctx.beginPath();
|
|
183
|
-
ctx.arc(rx, ly - 3, 2.5, 0, Math.PI * 2);
|
|
184
|
-
ctx.fillStyle = HEX.accent;
|
|
185
|
-
ctx.fill();
|
|
181
|
+
ctx.fillText('Burn Rate', rx, ly);
|
|
182
|
+
rx -= ctx.measureText('Burn Rate').width + 4;
|
|
183
|
+
ctx.beginPath(); ctx.arc(rx, ly - 3, 2.5, 0, Math.PI * 2); ctx.fill();
|
|
186
184
|
|
|
187
|
-
// ── Hover
|
|
188
|
-
if (hover && hover.index >= 0 && hover.index <
|
|
185
|
+
// ── Hover ───────────────────────────────────────────────
|
|
186
|
+
if (hover && hover.index >= 0 && hover.index < chartData.length) {
|
|
189
187
|
const hx = hover.x;
|
|
188
|
+
const d = chartData[hover.index];
|
|
190
189
|
|
|
191
|
-
//
|
|
190
|
+
// Crosshair
|
|
192
191
|
ctx.beginPath();
|
|
193
192
|
ctx.moveTo(hx, pad.top);
|
|
194
193
|
ctx.lineTo(hx, pad.top + h);
|
|
195
194
|
ctx.strokeStyle = hexAlpha(HEX.text1, 0.15);
|
|
196
195
|
ctx.lineWidth = 1;
|
|
197
|
-
ctx.setLineDash([]);
|
|
198
196
|
ctx.stroke();
|
|
199
197
|
|
|
200
|
-
// Dot
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
ctx.
|
|
204
|
-
ctx.arc(hx, dotY, 3, 0, Math.PI * 2);
|
|
205
|
-
ctx.fillStyle = HEX.accent;
|
|
206
|
-
ctx.fill();
|
|
198
|
+
// Dot
|
|
199
|
+
const dotY = yBurn(d.burnRate);
|
|
200
|
+
ctx.beginPath(); ctx.arc(hx, dotY, 3, 0, Math.PI * 2);
|
|
201
|
+
ctx.fillStyle = HEX.accent; ctx.fill();
|
|
207
202
|
|
|
208
203
|
// Tooltip
|
|
209
204
|
const lines = [
|
|
210
|
-
{ label: '
|
|
211
|
-
{ label: '
|
|
205
|
+
{ label: 'Burn', value: `${fmtNum(d.burnRate)}/m`, color: HEX.accent },
|
|
206
|
+
{ label: 'Cache', value: fmtPct(d.cacheHitRate * 100), color: HEX.info },
|
|
207
|
+
{ label: 'Agents', value: `${d.running}/${d.agents}`, color: HEX.text2 },
|
|
212
208
|
];
|
|
213
|
-
|
|
214
|
-
lines.push({ label: 'Cache', value: fmtPct(d.cacheHitRate * 100), color: HEX.info });
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const tooltipW = 100;
|
|
209
|
+
const tooltipW = 104;
|
|
218
210
|
const tooltipH = lines.length * 16 + 12;
|
|
219
211
|
let tx = hx + 12;
|
|
220
212
|
if (tx + tooltipW > width - 8) tx = hx - tooltipW - 12;
|
|
221
213
|
const ty = Math.max(pad.top, dotY - tooltipH / 2);
|
|
222
214
|
|
|
223
|
-
// Background
|
|
224
215
|
ctx.fillStyle = hexAlpha(HEX.surface0, 0.92);
|
|
225
|
-
ctx.beginPath();
|
|
226
|
-
ctx.roundRect(tx, ty, tooltipW, tooltipH, 4);
|
|
227
|
-
ctx.fill();
|
|
216
|
+
ctx.beginPath(); ctx.roundRect(tx, ty, tooltipW, tooltipH, 4); ctx.fill();
|
|
228
217
|
ctx.strokeStyle = hexAlpha(HEX.text4, 0.2);
|
|
229
|
-
ctx.lineWidth = 1;
|
|
230
|
-
ctx.stroke();
|
|
218
|
+
ctx.lineWidth = 1; ctx.stroke();
|
|
231
219
|
|
|
232
|
-
// Rows
|
|
233
220
|
ctx.textAlign = 'left';
|
|
234
221
|
lines.forEach((line, i) => {
|
|
235
222
|
const rowY = ty + 14 + i * 16;
|
|
236
|
-
|
|
237
|
-
ctx.
|
|
238
|
-
ctx.arc(tx + 8, rowY - 3, 2, 0, Math.PI * 2);
|
|
239
|
-
ctx.fillStyle = line.color;
|
|
240
|
-
ctx.fill();
|
|
241
|
-
// Label
|
|
223
|
+
ctx.beginPath(); ctx.arc(tx + 8, rowY - 3, 2, 0, Math.PI * 2);
|
|
224
|
+
ctx.fillStyle = line.color; ctx.fill();
|
|
242
225
|
ctx.font = "8px 'Inter Variable', sans-serif";
|
|
243
|
-
ctx.fillStyle = HEX.text3;
|
|
244
|
-
ctx.fillText(line.label, tx + 14, rowY);
|
|
245
|
-
// Value
|
|
226
|
+
ctx.fillStyle = HEX.text3; ctx.fillText(line.label, tx + 14, rowY);
|
|
246
227
|
ctx.font = "9px 'JetBrains Mono Variable', monospace";
|
|
247
|
-
ctx.fillStyle = HEX.text0;
|
|
248
|
-
ctx.textAlign = 'right';
|
|
228
|
+
ctx.fillStyle = HEX.text0; ctx.textAlign = 'right';
|
|
249
229
|
ctx.fillText(line.value, tx + tooltipW - 8, rowY);
|
|
250
230
|
ctx.textAlign = 'left';
|
|
251
231
|
});
|
|
252
232
|
}
|
|
253
|
-
}, [
|
|
233
|
+
}, [chartData, width, height, hover, w, h, pad]);
|
|
254
234
|
|
|
255
235
|
return (
|
|
256
236
|
<div ref={containerRef} className="absolute inset-0">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.6",
|
|
4
4
|
"description": "Open-source agent orchestration layer — the AI company OS. MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -1718,6 +1718,7 @@ Keep responses concise. Help them think, don't lecture them about the system the
|
|
|
1718
1718
|
outputTokens: tokenData.outputTokens || 0,
|
|
1719
1719
|
cacheHitRate: agentCacheTotal > 0 ? Math.round(((tokenData.cacheReadTokens || 0) / agentCacheTotal) * 1000) / 1000 : 0,
|
|
1720
1720
|
contextUsage: a.contextUsage || 0,
|
|
1721
|
+
rotationThreshold: daemon.adaptive.getThreshold(a.provider, a.role),
|
|
1721
1722
|
durationMs: a.durationMs || tokenData.totalDurationMs || 0,
|
|
1722
1723
|
turns: a.turns || tokenData.totalTurns || 0,
|
|
1723
1724
|
modelDistribution: tokenData.modelDistribution || {},
|
|
@@ -1773,6 +1774,8 @@ Keep responses concise. Help them think, don't lecture them about the system the
|
|
|
1773
1774
|
journalist: {
|
|
1774
1775
|
...journalistStatus,
|
|
1775
1776
|
lastSummary: lastSynthesis?.summary || '',
|
|
1777
|
+
projectMap: lastSynthesis?.projectMap || '',
|
|
1778
|
+
decisions: lastSynthesis?.decisions || '',
|
|
1776
1779
|
recentHistory: journalistHistory,
|
|
1777
1780
|
},
|
|
1778
1781
|
timeline: timelineData,
|
|
@@ -317,6 +317,9 @@ For normal file edits within your scope, proceed without review.
|
|
|
317
317
|
model: output.model,
|
|
318
318
|
estimatedCostUsd: output.estimatedCostUsd,
|
|
319
319
|
});
|
|
320
|
+
// Feed router cost log for tier tracking
|
|
321
|
+
const tier = this.daemon.classifier.classify(agent.id);
|
|
322
|
+
this.daemon.router.recordUsage(agent.id, output.model || current.model, output.tokensUsed, tier);
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
325
|
// Record session result data (cost, duration, turns)
|