@codemieai/code 0.4.2 → 0.5.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 +7 -1
- package/bin/codemie-kimi-acp.js +18 -0
- package/bin/codemie-kimi.js +18 -0
- package/dist/agents/core/AgentCLI.d.ts.map +1 -1
- package/dist/agents/core/AgentCLI.js +4 -0
- package/dist/agents/core/AgentCLI.js.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.js +26 -6
- package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
- package/dist/agents/core/metrics/types.d.ts +1 -1
- package/dist/agents/core/metrics/types.d.ts.map +1 -1
- package/dist/agents/core/session/BaseProcessor.d.ts +2 -0
- package/dist/agents/core/session/BaseProcessor.d.ts.map +1 -1
- package/dist/agents/core/session/BaseSessionAdapter.d.ts +7 -0
- package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
- package/dist/agents/core/types.d.ts +30 -0
- package/dist/agents/core/types.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +3 -3
- package/dist/agents/plugins/claude/claude.session.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.session.js +21 -6
- package/dist/agents/plugins/claude/claude.session.js.map +1 -1
- package/dist/agents/plugins/gemini/gemini.plugin.js.map +1 -1
- package/dist/agents/plugins/gemini/session/processors/gemini.metrics-processor.d.ts.map +1 -1
- package/dist/agents/plugins/gemini/session/processors/gemini.metrics-processor.js +3 -0
- package/dist/agents/plugins/gemini/session/processors/gemini.metrics-processor.js.map +1 -1
- package/dist/agents/plugins/kimi/extension/SKILL.md +6 -0
- package/dist/agents/plugins/kimi/extension/manifest.json +8 -0
- package/dist/agents/plugins/kimi/kimi-acp.plugin.d.ts +7 -0
- package/dist/agents/plugins/kimi/kimi-acp.plugin.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi-acp.plugin.js +28 -0
- package/dist/agents/plugins/kimi/kimi-acp.plugin.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.extension-installer.d.ts +56 -0
- package/dist/agents/plugins/kimi/kimi.extension-installer.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.extension-installer.js +79 -0
- package/dist/agents/plugins/kimi/kimi.extension-installer.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.hook-config-injector.d.ts +34 -0
- package/dist/agents/plugins/kimi/kimi.hook-config-injector.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.hook-config-injector.js +158 -0
- package/dist/agents/plugins/kimi/kimi.hook-config-injector.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.hook-transformer.d.ts +23 -0
- package/dist/agents/plugins/kimi/kimi.hook-transformer.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.hook-transformer.js +46 -0
- package/dist/agents/plugins/kimi/kimi.hook-transformer.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.models.d.ts +8 -0
- package/dist/agents/plugins/kimi/kimi.models.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.models.js +174 -0
- package/dist/agents/plugins/kimi/kimi.models.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.paths.d.ts +65 -0
- package/dist/agents/plugins/kimi/kimi.paths.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.paths.js +95 -0
- package/dist/agents/plugins/kimi/kimi.paths.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.plugin.d.ts +37 -0
- package/dist/agents/plugins/kimi/kimi.plugin.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.plugin.js +318 -0
- package/dist/agents/plugins/kimi/kimi.plugin.js.map +1 -0
- package/dist/agents/plugins/kimi/kimi.session.d.ts +40 -0
- package/dist/agents/plugins/kimi/kimi.session.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/kimi.session.js +191 -0
- package/dist/agents/plugins/kimi/kimi.session.js.map +1 -0
- package/dist/agents/plugins/kimi/session/processors/kimi.metrics-processor.d.ts +43 -0
- package/dist/agents/plugins/kimi/session/processors/kimi.metrics-processor.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/session/processors/kimi.metrics-processor.js +421 -0
- package/dist/agents/plugins/kimi/session/processors/kimi.metrics-processor.js.map +1 -0
- package/dist/agents/plugins/kimi/session/types.d.ts +81 -0
- package/dist/agents/plugins/kimi/session/types.d.ts.map +1 -0
- package/dist/agents/plugins/kimi/session/types.js +5 -0
- package/dist/agents/plugins/kimi/session/types.js.map +1 -0
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +4 -0
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-enricher.js +67 -1
- package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -1
- package/dist/cli/commands/analytics/cost/dispatch-extractor.d.ts +2 -2
- package/dist/cli/commands/analytics/cost/dispatch-extractor.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/dispatch-extractor.js +6 -4
- package/dist/cli/commands/analytics/cost/dispatch-extractor.js.map +1 -1
- package/dist/cli/commands/analytics/cost/pricing.json +9 -2
- package/dist/cli/commands/analytics/cost/types.d.ts +13 -0
- package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/types.js.map +1 -1
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts +13 -4
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/usage-readers.js +115 -27
- package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -1
- package/dist/cli/commands/analytics/model-normalizer.d.ts +2 -0
- package/dist/cli/commands/analytics/model-normalizer.d.ts.map +1 -1
- package/dist/cli/commands/analytics/model-normalizer.js +8 -0
- package/dist/cli/commands/analytics/model-normalizer.js.map +1 -1
- package/dist/cli/commands/analytics/report/client/app.js +233 -120
- package/dist/cli/commands/analytics/report/template.html +28 -4
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +24 -7
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/plugins/moonshot-subscription/index.d.ts +9 -0
- package/dist/providers/plugins/moonshot-subscription/index.d.ts.map +1 -0
- package/dist/providers/plugins/moonshot-subscription/index.js +9 -0
- package/dist/providers/plugins/moonshot-subscription/index.js.map +1 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.d.ts +8 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.d.ts.map +1 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.js +80 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.setup-steps.js.map +1 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.template.d.ts +11 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.template.d.ts.map +1 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.template.js +111 -0
- package/dist/providers/plugins/moonshot-subscription/moonshot-subscription.template.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +2 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js +3 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/kimi-request-normalizer.plugin.d.ts +18 -0
- package/dist/providers/plugins/sso/proxy/plugins/kimi-request-normalizer.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/kimi-request-normalizer.plugin.js +56 -0
- package/dist/providers/plugins/sso/proxy/plugins/kimi-request-normalizer.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/sso.auth.d.ts +5 -0
- package/dist/providers/plugins/sso/sso.auth.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.auth.js +23 -1
- package/dist/providers/plugins/sso/sso.auth.js.map +1 -1
- package/dist/utils/config.d.ts +24 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +83 -8
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/native-installer.d.ts.map +1 -1
- package/dist/utils/native-installer.js +6 -3
- package/dist/utils/native-installer.js.map +1 -1
- package/package.json +4 -1
- package/scripts/copy-plugins.js +5 -0
- package/scripts/test-desktop-telemetry.js +1 -1
|
@@ -155,6 +155,93 @@
|
|
|
155
155
|
return cv;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
var INVOCATION_CHARTS = [
|
|
159
|
+
{ kind: 'skill', title: 'Skills invoked', color: '#7c4fff' },
|
|
160
|
+
{ kind: 'agent', title: 'Agent subtypes', color: '#ff6b6b' },
|
|
161
|
+
{ kind: 'command', title: 'Slash commands', color: '#4a9eff' },
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
function appendToolsAndModels(host, fs, chartFn) {
|
|
165
|
+
var toolAgg = new Map();
|
|
166
|
+
fs.forEach(function (s) {
|
|
167
|
+
(s.tools || []).forEach(function (t) {
|
|
168
|
+
var cur = toolAgg.get(t.toolName) || { total: 0, success: 0, failure: 0 };
|
|
169
|
+
cur.total += t.totalCalls; cur.success += t.successCount; cur.failure += t.failureCount;
|
|
170
|
+
toolAgg.set(t.toolName, cur);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
var tools = Array.from(toolAgg.entries()).map(function (e) { return { name: e[0], total: e[1].total, success: e[1].success, rate: e[1].total ? Math.round((e[1].success / e[1].total) * 100) : 0 }; })
|
|
174
|
+
.sort(function (a, b) { return b.total - a.total; });
|
|
175
|
+
var maxTool = tools.length ? tools[0].total : 1;
|
|
176
|
+
|
|
177
|
+
var row = el('div', 'grid-2 mb16');
|
|
178
|
+
var toolCard = card('Tool usage & success rate');
|
|
179
|
+
tools.slice(0, 12).forEach(function (t) {
|
|
180
|
+
var bar = el('div', 'bar-row');
|
|
181
|
+
var color = t.rate >= 90 ? '#259F4C' : (t.rate >= 70 ? '#F5A534' : '#F9303C');
|
|
182
|
+
bar.innerHTML = '<span class="nm">' + esc(t.name) + '</span><div class="bar-track"><div class="bar-fill" style="width:' + Math.max(3, (t.total / maxTool) * 100) + '%;background:' + color + '"></div></div><span class="vl">' + fmtNum(t.total) + ' · ' + t.rate + '%</span>';
|
|
183
|
+
toolCard._body.appendChild(bar);
|
|
184
|
+
});
|
|
185
|
+
if (!tools.length) toolCard._body.appendChild(el('div', 'empty', 'No per-tool data.'));
|
|
186
|
+
row.appendChild(toolCard);
|
|
187
|
+
|
|
188
|
+
var modelAgg = new Map();
|
|
189
|
+
fs.forEach(function (s) { (s.perModelCost || []).forEach(function (m) { modelAgg.set(m.model, (modelAgg.get(m.model) || 0) + (m.tokens ? m.tokens.total : 0)); }); });
|
|
190
|
+
var modelCard = card('Tokens by model');
|
|
191
|
+
var mEntries = Array.from(modelAgg.entries()).sort(function (a, b) { return b[1] - a[1]; }).slice(0, 8);
|
|
192
|
+
if (mEntries.length) {
|
|
193
|
+
chartFn(canvasIn(modelCard._body), {
|
|
194
|
+
type: 'bar',
|
|
195
|
+
data: { labels: mEntries.map(function (e) { return e[0]; }), datasets: [{ data: mEntries.map(function (e) { return e[1]; }), backgroundColor: mEntries.map(function (_, i) { return PALETTE[i % PALETTE.length]; }), borderRadius: 5 }] },
|
|
196
|
+
options: { indexAxis: 'y', plugins: { legend: { display: false }, tooltip: { callbacks: { label: function (c) { return fmtTokens(c.parsed.x) + ' tokens'; } } } }, scales: { x: { grid: { color: GRID }, ticks: { callback: function (v) { return fmtTokens(v); } } }, y: { grid: { display: false } } } }
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
modelCard._body.appendChild(el('div', 'empty', 'No token data (sessions unpriced or no native logs).'));
|
|
200
|
+
}
|
|
201
|
+
row.appendChild(modelCard);
|
|
202
|
+
host.appendChild(row);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function appendInvocationCharts(host, fs, chartFn) {
|
|
206
|
+
INVOCATION_CHARTS.forEach(function (def) {
|
|
207
|
+
var agg = {};
|
|
208
|
+
fs.forEach(function (s) {
|
|
209
|
+
dispatchCounts(s, def.kind).forEach(function (x) {
|
|
210
|
+
agg[x.name] = (agg[x.name] || 0) + x.totalCalls;
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
var entries = Object.entries(agg)
|
|
214
|
+
.sort(function (a, b) { return b[1] - a[1]; })
|
|
215
|
+
.slice(0, 10);
|
|
216
|
+
|
|
217
|
+
var invCard = card(def.title);
|
|
218
|
+
if (entries.length) {
|
|
219
|
+
chartFn(canvasIn(invCard._body), {
|
|
220
|
+
type: 'bar',
|
|
221
|
+
data: {
|
|
222
|
+
labels: entries.map(function (e) { return e[0]; }),
|
|
223
|
+
datasets: [{
|
|
224
|
+
data: entries.map(function (e) { return e[1]; }),
|
|
225
|
+
backgroundColor: def.color,
|
|
226
|
+
borderRadius: 4,
|
|
227
|
+
}],
|
|
228
|
+
},
|
|
229
|
+
options: {
|
|
230
|
+
indexAxis: 'y',
|
|
231
|
+
plugins: { legend: { display: false } },
|
|
232
|
+
scales: {
|
|
233
|
+
x: { grid: { color: GRID }, ticks: { precision: 0 } },
|
|
234
|
+
y: { grid: { display: false } },
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
} else {
|
|
239
|
+
invCard._body.appendChild(el('div', 'empty', 'No data.'));
|
|
240
|
+
}
|
|
241
|
+
host.appendChild(invCard);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
158
245
|
// ---- small DOM builders -------------------------------------------------
|
|
159
246
|
function el(tag, cls, html) { var e = document.createElement(tag); if (cls) e.className = cls; if (html != null) e.innerHTML = html; return e; }
|
|
160
247
|
function card(title, sub) {
|
|
@@ -405,92 +492,8 @@
|
|
|
405
492
|
host.appendChild(el('h2', 'view-title', 'Tools & Models'));
|
|
406
493
|
host.appendChild(el('p', 'view-sub', 'Tool usage across sessions and model token/cost distribution.'));
|
|
407
494
|
if (!fs.length) { host.appendChild(el('div', 'empty', 'No sessions in view.')); return; }
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
var toolAgg = new Map();
|
|
411
|
-
fs.forEach(function (s) {
|
|
412
|
-
(s.tools || []).forEach(function (t) {
|
|
413
|
-
var cur = toolAgg.get(t.toolName) || { total: 0, success: 0, failure: 0 };
|
|
414
|
-
cur.total += t.totalCalls; cur.success += t.successCount; cur.failure += t.failureCount;
|
|
415
|
-
toolAgg.set(t.toolName, cur);
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
|
-
var tools = Array.from(toolAgg.entries()).map(function (e) { return { name: e[0], total: e[1].total, success: e[1].success, rate: e[1].total ? Math.round((e[1].success / e[1].total) * 100) : 0 }; })
|
|
419
|
-
.sort(function (a, b) { return b.total - a.total; });
|
|
420
|
-
var maxTool = tools.length ? tools[0].total : 1;
|
|
421
|
-
|
|
422
|
-
var row = el('div', 'grid-2 mb16');
|
|
423
|
-
var toolCard = card('Tool usage & success rate');
|
|
424
|
-
tools.slice(0, 12).forEach(function (t) {
|
|
425
|
-
var bar = el('div', 'bar-row');
|
|
426
|
-
var color = t.rate >= 90 ? '#259F4C' : (t.rate >= 70 ? '#F5A534' : '#F9303C');
|
|
427
|
-
bar.innerHTML = '<span class="nm">' + esc(t.name) + '</span><div class="bar-track"><div class="bar-fill" style="width:' + Math.max(3, (t.total / maxTool) * 100) + '%;background:' + color + '"></div></div><span class="vl">' + fmtNum(t.total) + ' · ' + t.rate + '%</span>';
|
|
428
|
-
toolCard._body.appendChild(bar);
|
|
429
|
-
});
|
|
430
|
-
if (!tools.length) toolCard._body.appendChild(el('div', 'empty', 'No per-tool data.'));
|
|
431
|
-
row.appendChild(toolCard);
|
|
432
|
-
|
|
433
|
-
// models by tokens (from perModelCost)
|
|
434
|
-
var modelAgg = new Map();
|
|
435
|
-
fs.forEach(function (s) { (s.perModelCost || []).forEach(function (m) { modelAgg.set(m.model, (modelAgg.get(m.model) || 0) + (m.tokens ? m.tokens.total : 0)); }); });
|
|
436
|
-
var modelCard = card('Tokens by model');
|
|
437
|
-
var mEntries = Array.from(modelAgg.entries()).sort(function (a, b) { return b[1] - a[1]; }).slice(0, 8);
|
|
438
|
-
if (mEntries.length) {
|
|
439
|
-
makeChart(canvasIn(modelCard._body), {
|
|
440
|
-
type: 'bar',
|
|
441
|
-
data: { labels: mEntries.map(function (e) { return e[0]; }), datasets: [{ data: mEntries.map(function (e) { return e[1]; }), backgroundColor: mEntries.map(function (_, i) { return PALETTE[i % PALETTE.length]; }), borderRadius: 5 }] },
|
|
442
|
-
options: { indexAxis: 'y', plugins: { legend: { display: false }, tooltip: { callbacks: { label: function (c) { return fmtTokens(c.parsed.x) + ' tokens'; } } } }, scales: { x: { grid: { color: GRID }, ticks: { callback: function (v) { return fmtTokens(v); } } }, y: { grid: { display: false } } } }
|
|
443
|
-
});
|
|
444
|
-
} else {
|
|
445
|
-
modelCard._body.appendChild(el('div', 'empty', 'No token data (sessions unpriced or no native logs).'));
|
|
446
|
-
}
|
|
447
|
-
row.appendChild(modelCard);
|
|
448
|
-
host.appendChild(row);
|
|
449
|
-
|
|
450
|
-
// ── Named invocation charts ──────────────────────────────────────────────
|
|
451
|
-
var invocationDefs = [
|
|
452
|
-
{ field: 'skillInvocations', title: 'Skills invoked', color: '#7c4fff' },
|
|
453
|
-
{ field: 'agentInvocations', title: 'Agent subtypes', color: '#ff6b6b' },
|
|
454
|
-
{ field: 'commandInvocations', title: 'Slash commands', color: '#4a9eff' },
|
|
455
|
-
];
|
|
456
|
-
|
|
457
|
-
invocationDefs.forEach(function (def) {
|
|
458
|
-
var agg = {};
|
|
459
|
-
fs.forEach(function (s) {
|
|
460
|
-
(s[def.field] || []).forEach(function (x) {
|
|
461
|
-
agg[x.name] = (agg[x.name] || 0) + x.totalCalls;
|
|
462
|
-
});
|
|
463
|
-
});
|
|
464
|
-
var entries = Object.entries(agg)
|
|
465
|
-
.sort(function (a, b) { return b[1] - a[1]; })
|
|
466
|
-
.slice(0, 10);
|
|
467
|
-
|
|
468
|
-
var invCard = card(def.title);
|
|
469
|
-
if (entries.length) {
|
|
470
|
-
makeChart(canvasIn(invCard._body), {
|
|
471
|
-
type: 'bar',
|
|
472
|
-
data: {
|
|
473
|
-
labels: entries.map(function (e) { return e[0]; }),
|
|
474
|
-
datasets: [{
|
|
475
|
-
data: entries.map(function (e) { return e[1]; }),
|
|
476
|
-
backgroundColor: def.color,
|
|
477
|
-
borderRadius: 4,
|
|
478
|
-
}],
|
|
479
|
-
},
|
|
480
|
-
options: {
|
|
481
|
-
indexAxis: 'y',
|
|
482
|
-
plugins: { legend: { display: false } },
|
|
483
|
-
scales: {
|
|
484
|
-
x: { grid: { color: GRID }, ticks: { precision: 0 } },
|
|
485
|
-
y: { grid: { display: false } },
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
});
|
|
489
|
-
} else {
|
|
490
|
-
invCard._body.appendChild(el('div', 'empty', 'No data.'));
|
|
491
|
-
}
|
|
492
|
-
host.appendChild(invCard);
|
|
493
|
-
});
|
|
495
|
+
appendToolsAndModels(host, fs, makeChart);
|
|
496
|
+
appendInvocationCharts(host, fs, makeChart);
|
|
494
497
|
};
|
|
495
498
|
|
|
496
499
|
VIEWS.activity = function (host, fs) {
|
|
@@ -819,10 +822,17 @@
|
|
|
819
822
|
};
|
|
820
823
|
|
|
821
824
|
// ---- session-detail modal ----------------------------------------------
|
|
822
|
-
var
|
|
825
|
+
var modalCharts = []; // owned by the modal; NOT in the global charts[] (decoupled from destroyCharts()).
|
|
823
826
|
var modalEsc = null;
|
|
827
|
+
function makeModalChart(canvas, config) {
|
|
828
|
+
if (!window.Chart) return null;
|
|
829
|
+
var c = new Chart(canvas, config);
|
|
830
|
+
modalCharts.push(c);
|
|
831
|
+
return c;
|
|
832
|
+
}
|
|
824
833
|
function closeSessionModal() {
|
|
825
|
-
|
|
834
|
+
modalCharts.forEach(function (c) { try { c.destroy(); } catch (e) {} });
|
|
835
|
+
modalCharts = [];
|
|
826
836
|
if (modalEsc) { document.removeEventListener('keydown', modalEsc); modalEsc = null; }
|
|
827
837
|
var ov = document.getElementById('session-modal'); if (ov && ov.parentNode) ov.parentNode.removeChild(ov);
|
|
828
838
|
}
|
|
@@ -870,33 +880,139 @@
|
|
|
870
880
|
row.appendChild(el('div', 'tl-label' + (strong ? ' tl-label-strong' : ''), esc(label)));
|
|
871
881
|
var track = el('div', 'tl-track');
|
|
872
882
|
var bar = el('div', 'tl-bar');
|
|
873
|
-
bar.style.left = leftPct + '%'; bar.style.width = wPct + '%'; bar.style.background = color;
|
|
874
|
-
if (barText)
|
|
883
|
+
bar.style.left = 'calc(min(' + leftPct + '%, 100% - 28px))'; bar.style.width = wPct + '%'; bar.style.background = color;
|
|
884
|
+
if (barText) {
|
|
885
|
+
bar.classList.add('tl-bar-has-text');
|
|
886
|
+
bar.innerHTML = '<span class="tl-bar-text">' + esc(barText) + '</span>';
|
|
887
|
+
}
|
|
875
888
|
bar.title = label + ' · ' + durText; // .title property = safe (not parsed as HTML)
|
|
876
889
|
track.appendChild(bar); row.appendChild(track);
|
|
877
890
|
row.appendChild(el('div', 'tl-dur', esc(durText)));
|
|
878
891
|
return row;
|
|
879
892
|
}
|
|
880
|
-
//
|
|
893
|
+
// Precise wall-clock timing for short timeline steps. The general report formatter rounds
|
|
894
|
+
// sub-minute values up to one minute, which is useful for sessions but misleading here.
|
|
895
|
+
function fmtTimelineDuration(ms) {
|
|
896
|
+
ms = Math.max(0, ms || 0);
|
|
897
|
+
if (ms < 1000) return Math.round(ms) + 'ms';
|
|
898
|
+
if (ms < 60000) return (Math.round(ms / 100) / 10) + 's';
|
|
899
|
+
if (ms < 3600000) return Math.floor(ms / 60000) + 'm ' + Math.round((ms % 60000) / 1000) + 's';
|
|
900
|
+
return Math.floor(ms / 3600000) + 'h ' + Math.round((ms % 3600000) / 60000) + 'm';
|
|
901
|
+
}
|
|
902
|
+
// Side panel content for a selected timeline step.
|
|
903
|
+
function tlDetailEl(d) {
|
|
904
|
+
var panel = el('div', '');
|
|
905
|
+
if (!d) {
|
|
906
|
+
panel.appendChild(el('div', 'tl-side-empty', 'Click a timeline step to see details.'));
|
|
907
|
+
return panel;
|
|
908
|
+
}
|
|
909
|
+
var color = PALETTE[hashStr(d.kind + ':' + d.name) % PALETTE.length];
|
|
910
|
+
var nameEl = el('div', 'tl-side-name');
|
|
911
|
+
var dot = el('span', 'tl-side-dot'); dot.style.background = color;
|
|
912
|
+
nameEl.appendChild(dot);
|
|
913
|
+
nameEl.appendChild(document.createTextNode(d.kind + ' · ' + d.name));
|
|
914
|
+
panel.appendChild(nameEl);
|
|
915
|
+
var hasCost = d.costUSD != null;
|
|
916
|
+
var hasTok = d.tokens != null;
|
|
917
|
+
panel.appendChild(statsEl([
|
|
918
|
+
['Cost', hasCost ? fmtUSD(d.costUSD) : '—', ''],
|
|
919
|
+
['Tokens', hasTok ? fmtTokens(d.tokens.total) : '—', ''],
|
|
920
|
+
['Duration', fmtTimelineDuration(d.durationMs), ''],
|
|
921
|
+
]));
|
|
922
|
+
if (hasTok) {
|
|
923
|
+
var tok = d.tokens;
|
|
924
|
+
var total = Math.max(tok.total, 1);
|
|
925
|
+
var barEl = el('div', 'tl-tok-bar');
|
|
926
|
+
var segs = [
|
|
927
|
+
{ val: tok.input, color: '#7C5CFC' },
|
|
928
|
+
{ val: tok.output, color: '#F5A534' },
|
|
929
|
+
{ val: tok.cacheRead, color: '#259F4C' },
|
|
930
|
+
{ val: tok.cacheCreation, color: '#3B82F6' },
|
|
931
|
+
].filter(function(s) { return s.val > 0; });
|
|
932
|
+
segs.forEach(function(s) {
|
|
933
|
+
var seg = el('div', 'tl-tok-seg');
|
|
934
|
+
seg.style.flex = String(s.val / total * 100);
|
|
935
|
+
seg.style.background = s.color;
|
|
936
|
+
barEl.appendChild(seg);
|
|
937
|
+
});
|
|
938
|
+
var tokSec = el('div', 'tl-side-section');
|
|
939
|
+
tokSec.appendChild(el('div', 'tl-side-label', 'Token breakdown'));
|
|
940
|
+
tokSec.appendChild(barEl);
|
|
941
|
+
tokSec.appendChild(statsEl([
|
|
942
|
+
['Input', fmtTokens(tok.input), ''],
|
|
943
|
+
['Output', fmtTokens(tok.output), ''],
|
|
944
|
+
['Cache read', fmtTokens(tok.cacheRead), ''],
|
|
945
|
+
['Cache write', fmtTokens(tok.cacheCreation), ''],
|
|
946
|
+
]));
|
|
947
|
+
panel.appendChild(tokSec);
|
|
948
|
+
}
|
|
949
|
+
if (d.tools && d.tools.length) {
|
|
950
|
+
var toolSec = el('div', 'tl-side-section');
|
|
951
|
+
toolSec.appendChild(el('div', 'tl-side-label', 'Tools called'));
|
|
952
|
+
var chips = el('div', 'modal-chips');
|
|
953
|
+
d.tools.forEach(function(t) {
|
|
954
|
+
chips.appendChild(el('span', 'chip', esc(t.name) + '<b>\xd7' + fmtNum(t.calls) + '</b>'));
|
|
955
|
+
});
|
|
956
|
+
toolSec.appendChild(chips);
|
|
957
|
+
panel.appendChild(toolSec);
|
|
958
|
+
}
|
|
959
|
+
return panel;
|
|
960
|
+
}
|
|
961
|
+
// Gantt of top-level agent dispatches: session span on top, each agent bar positioned
|
|
962
|
+
// by wall-clock start time relative to the session start (proportional scaling).
|
|
963
|
+
// Skills and commands are excluded — they have no separate transcript or cost to show.
|
|
964
|
+
// min-width 28px (CSS) keeps short agents visible and clickable without distorting the scale.
|
|
881
965
|
function timelineEl(s) {
|
|
882
|
-
var
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
var
|
|
887
|
-
var
|
|
888
|
-
|
|
966
|
+
var dispatches = (s.dispatches || []).filter(function (d) { return d.kind === 'agent'; }).sort(function (a, b) { return a.start - b.start; });
|
|
967
|
+
// Scale bars to the agent activity window, not the full session duration.
|
|
968
|
+
// Agent bars fill the track proportionally relative to each other; absolute
|
|
969
|
+
// start offset (vs. session start) is shown in the side panel detail view.
|
|
970
|
+
var actStart = dispatches.length ? dispatches.reduce(function (m, d) { return Math.min(m, d.start); }, Infinity) : s.startTime;
|
|
971
|
+
var actEnd = dispatches.length ? dispatches.reduce(function (m, d) { return Math.max(m, d.start + (d.durationMs || 0)); }, -Infinity) : s.startTime + s.durationMs;
|
|
972
|
+
var ganttSpan = Math.max(1, actEnd - actStart);
|
|
973
|
+
|
|
974
|
+
var container = el('div', 'tl-container');
|
|
975
|
+
var gantt = el('div', 'tl-gantt timeline');
|
|
976
|
+
var sidePane = el('div', 'tl-side');
|
|
977
|
+
|
|
978
|
+
var selected = dispatches[0] || null;
|
|
979
|
+
sidePane.appendChild(tlDetailEl(selected));
|
|
980
|
+
|
|
981
|
+
function selectDispatch(d, barEl) {
|
|
982
|
+
gantt.querySelectorAll('.tl-bar[data-dispatch]').forEach(function(b) {
|
|
983
|
+
b.style.outline = b === barEl ? '2px solid rgba(255,255,255,0.55)' : 'none';
|
|
984
|
+
});
|
|
985
|
+
sidePane.innerHTML = '';
|
|
986
|
+
sidePane.appendChild(tlDetailEl(d));
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
gantt.appendChild(tlRow('session', '#259F4C', 0, 100, fmtTimelineDuration(s.durationMs), fmtUSD(s.costUSD), true));
|
|
990
|
+
|
|
889
991
|
var occ = {};
|
|
890
|
-
|
|
891
|
-
var
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
var
|
|
895
|
-
var
|
|
896
|
-
|
|
897
|
-
|
|
992
|
+
dispatches.forEach(function (d) {
|
|
993
|
+
var key = d.kind + ':' + d.name;
|
|
994
|
+
var total = dispatches.filter(function (x) { return x.kind === d.kind && x.name === d.name; }).length;
|
|
995
|
+
occ[key] = (occ[key] || 0) + 1;
|
|
996
|
+
var label = d.kind + ' · ' + d.name + (total > 1 ? ' #' + occ[key] : '');
|
|
997
|
+
var leftPct = Math.max(0, (d.start - actStart) / ganttSpan * 100);
|
|
998
|
+
var wPct = (d.durationMs || 0) / ganttSpan * 100;
|
|
999
|
+
if (leftPct + wPct > 100) wPct = Math.max(0, 100 - leftPct);
|
|
1000
|
+
var barText = d.costUSD != null && wPct >= 8 ? fmtUSD(d.costUSD) : '';
|
|
1001
|
+
var color = PALETTE[hashStr(key) % PALETTE.length];
|
|
1002
|
+
var row = tlRow(label, color, leftPct, wPct, fmtTimelineDuration(d.durationMs), barText, false);
|
|
1003
|
+
var bar = row.querySelector('.tl-bar');
|
|
1004
|
+
if (bar) {
|
|
1005
|
+
bar.setAttribute('data-dispatch', key);
|
|
1006
|
+
if (d === selected) bar.style.outline = '2px solid rgba(255,255,255,0.55)';
|
|
1007
|
+
}
|
|
1008
|
+
row.style.cursor = 'pointer';
|
|
1009
|
+
row.addEventListener('click', function () { selectDispatch(d, bar); });
|
|
1010
|
+
gantt.appendChild(row);
|
|
898
1011
|
});
|
|
899
|
-
|
|
1012
|
+
|
|
1013
|
+
container.appendChild(gantt);
|
|
1014
|
+
container.appendChild(sidePane);
|
|
1015
|
+
return container;
|
|
900
1016
|
}
|
|
901
1017
|
function openSessionModal(s, onBack) {
|
|
902
1018
|
if (!s) return;
|
|
@@ -966,7 +1082,7 @@
|
|
|
966
1082
|
var t0 = series[0].t;
|
|
967
1083
|
var labels = series.map(function (p) { return useTs ? fmtDuration(Math.max(0, p.t - t0)) : ('turn ' + p.t); });
|
|
968
1084
|
var cv = canvasIn(growth._body, 220);
|
|
969
|
-
|
|
1085
|
+
makeModalChart(cv, {
|
|
970
1086
|
type: 'line',
|
|
971
1087
|
data: { labels: labels, datasets: [
|
|
972
1088
|
{ label: 'Cost ($)', data: series.map(function (p) { return Math.round(p.cost * 10000) / 10000; }), borderColor: '#7C5CFC', backgroundColor: 'rgba(124,92,252,0.12)', fill: true, yAxisID: 'y', tension: 0.25, pointRadius: 0 },
|
|
@@ -982,23 +1098,20 @@
|
|
|
982
1098
|
}
|
|
983
1099
|
body.appendChild(growth);
|
|
984
1100
|
|
|
985
|
-
// Timeline — Gantt of top-level agent
|
|
986
|
-
var
|
|
987
|
-
var
|
|
988
|
-
|
|
1101
|
+
// Timeline — Gantt of all top-level agent, skill, and command dispatches.
|
|
1102
|
+
var hasDispatches = (s.dispatches || []).length > 0;
|
|
1103
|
+
var hasCostData = (s.dispatches || []).some(function (d) { return d.kind === 'agent' && d.costUSD != null; });
|
|
1104
|
+
var tlSubtitle = hasDispatches ? (hasCostData ? 'click a step for cost, token & timing details · long idle gaps compressed' : 'click a step for timing details · long idle gaps compressed') : '';
|
|
1105
|
+
var tlCard = card('Timeline', tlSubtitle);
|
|
1106
|
+
if (hasDispatches) {
|
|
989
1107
|
tlCard._body.appendChild(timelineEl(s));
|
|
990
1108
|
} else {
|
|
991
|
-
tlCard._body.appendChild(el('div', 'empty', 'No
|
|
1109
|
+
tlCard._body.appendChild(el('div', 'empty', 'No agent, skill, or command dispatches recorded for this session.'));
|
|
992
1110
|
}
|
|
993
1111
|
body.appendChild(tlCard);
|
|
994
1112
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
var cols = el('div', 'dispatch-cols');
|
|
998
|
-
cols.appendChild(chipsEl('Skills', dispatchCounts(s, 'skill')));
|
|
999
|
-
cols.appendChild(chipsEl('Commands', dispatchCounts(s, 'command')));
|
|
1000
|
-
scCard._body.appendChild(cols);
|
|
1001
|
-
body.appendChild(scCard);
|
|
1113
|
+
appendToolsAndModels(body, [s], makeModalChart);
|
|
1114
|
+
appendInvocationCharts(body, [s], makeModalChart);
|
|
1002
1115
|
|
|
1003
1116
|
modal.appendChild(body);
|
|
1004
1117
|
ov.appendChild(modal);
|
|
@@ -163,9 +163,21 @@
|
|
|
163
163
|
.tl-label { width: 168px; flex-shrink: 0; font-size: 12px; color: var(--color-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
164
164
|
.tl-label-strong { font-weight: 700; }
|
|
165
165
|
.tl-track { position: relative; flex: 1; height: 22px; background: var(--color-bg-tertiary); border-radius: 5px; overflow: hidden; }
|
|
166
|
-
.tl-bar { position: absolute; top: 0; height: 100%; min-width:
|
|
166
|
+
.tl-bar { position: absolute; top: 0; height: 100%; min-width: 28px; border-radius: 5px; display: flex; align-items: center; padding: 0; box-sizing: border-box; }
|
|
167
|
+
.tl-bar-has-text { padding: 0 8px; }
|
|
167
168
|
.tl-bar-text { font-size: 10.5px; color: #fff; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
|
|
168
|
-
.tl-dur { width:
|
|
169
|
+
.tl-dur { width: 72px; flex-shrink: 0; text-align: right; font-size: 10.5px; color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
170
|
+
/* timeline split layout: gantt left + side panel right */
|
|
171
|
+
.tl-container { display: flex; gap: 16px; align-items: flex-start; }
|
|
172
|
+
.tl-gantt { flex: 1; min-width: 0; }
|
|
173
|
+
.tl-side { width: 230px; flex-shrink: 0; border-left: 1px solid var(--color-border-structural); padding-left: 14px; min-height: 60px; }
|
|
174
|
+
.tl-side-empty { font-size: 12px; color: var(--color-text-muted); }
|
|
175
|
+
.tl-side-name { font-size: 12px; font-weight: 700; color: var(--color-text-primary); margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }
|
|
176
|
+
.tl-side-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
|
|
177
|
+
.tl-side-section { margin-top: 8px; }
|
|
178
|
+
.tl-side-label { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--color-text-muted); margin-bottom: 4px; }
|
|
179
|
+
.tl-tok-bar { display: flex; gap: 2px; height: 5px; border-radius: 3px; overflow: hidden; margin-bottom: 4px; }
|
|
180
|
+
.tl-tok-seg { border-radius: 2px; }
|
|
169
181
|
|
|
170
182
|
/* session-detail modal */
|
|
171
183
|
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.62); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: var(--z-modal, 50); padding: 24px; }
|
|
@@ -195,9 +207,21 @@
|
|
|
195
207
|
.tl-label { width: 168px; flex-shrink: 0; font-size: 12px; color: var(--color-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
196
208
|
.tl-label-strong { font-weight: 700; }
|
|
197
209
|
.tl-track { position: relative; flex: 1; height: 22px; background: var(--color-bg-tertiary); border-radius: 5px; overflow: hidden; }
|
|
198
|
-
.tl-bar { position: absolute; top: 0; height: 100%; min-width:
|
|
210
|
+
.tl-bar { position: absolute; top: 0; height: 100%; min-width: 28px; border-radius: 5px; display: flex; align-items: center; padding: 0; box-sizing: border-box; }
|
|
211
|
+
.tl-bar-has-text { padding: 0 8px; }
|
|
199
212
|
.tl-bar-text { font-size: 10.5px; color: #fff; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
|
|
200
|
-
.tl-dur { width:
|
|
213
|
+
.tl-dur { width: 72px; flex-shrink: 0; text-align: right; font-size: 10.5px; color: var(--color-text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
214
|
+
/* timeline split layout: gantt left + side panel right */
|
|
215
|
+
.tl-container { display: flex; gap: 16px; align-items: flex-start; }
|
|
216
|
+
.tl-gantt { flex: 1; min-width: 0; }
|
|
217
|
+
.tl-side { width: 230px; flex-shrink: 0; border-left: 1px solid var(--color-border-structural); padding-left: 14px; min-height: 60px; }
|
|
218
|
+
.tl-side-empty { font-size: 12px; color: var(--color-text-muted); }
|
|
219
|
+
.tl-side-name { font-size: 12px; font-weight: 700; color: var(--color-text-primary); margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }
|
|
220
|
+
.tl-side-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
|
|
221
|
+
.tl-side-section { margin-top: 8px; }
|
|
222
|
+
.tl-side-label { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--color-text-muted); margin-bottom: 4px; }
|
|
223
|
+
.tl-tok-bar { display: flex; gap: 2px; height: 5px; border-radius: 3px; overflow: hidden; margin-bottom: 4px; }
|
|
224
|
+
.tl-tok-seg { border-radius: 2px; }
|
|
201
225
|
|
|
202
226
|
/* table alignment — the design-system `.table thead tr th` (text-align:left, higher
|
|
203
227
|
specificity) was overriding `.td-number` on numeric <th>, so numeric headers stayed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,KAAK,EAAE,aAAa,EAA4D,MAAM,wBAAwB,CAAC;AAGtH;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,eAAe,EAAE,cAAc,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,eAAe,EAAE,YAAY,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,eAAe,EAAE,cAAc,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,KAAK,EAAE,aAAa,EAA4D,MAAM,wBAAwB,CAAC;AAGtH;;;;;;GAMG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,eAAe,EAAE,cAAc,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,aAAa;IACpD,eAAe,EAAE,YAAY,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,eAAe,EAAE,cAAc,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAynCD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBrG;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAkG3C"}
|
|
@@ -268,6 +268,18 @@ async function buildProcessingContext(sessionId, agentSessionId, agentSessionFil
|
|
|
268
268
|
const apiUrl = getConfigValue('CODEMIE_SYNC_API_URL', config) || getConfigValue('CODEMIE_BASE_URL', config) || '';
|
|
269
269
|
const cliVersion = getConfigValue('CODEMIE_CLI_VERSION', config) || '0.0.0';
|
|
270
270
|
const clientType = getConfigValue('CODEMIE_CLIENT_TYPE', config) || 'codemie-cli';
|
|
271
|
+
// Load the CodeMie session metadata so processors can use gitBranch and other
|
|
272
|
+
// session-level fields that are not present in the native agent transcript.
|
|
273
|
+
let gitBranch;
|
|
274
|
+
try {
|
|
275
|
+
const { getCodemiePath } = await import('../../utils/paths.js');
|
|
276
|
+
const { readFile } = await import('node:fs/promises');
|
|
277
|
+
const sessionMeta = JSON.parse(await readFile(getCodemiePath('sessions', `${sessionId}.json`), 'utf-8'));
|
|
278
|
+
gitBranch = sessionMeta.gitBranch;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
// Session metadata may not exist in all contexts (e.g., tests); proceed without it.
|
|
282
|
+
}
|
|
271
283
|
// Build context with SSO credentials if available
|
|
272
284
|
let cookies = config?.cookies || '';
|
|
273
285
|
let apiKey = config?.apiKey;
|
|
@@ -302,7 +314,8 @@ async function buildProcessingContext(sessionId, agentSessionId, agentSessionFil
|
|
|
302
314
|
dryRun: false,
|
|
303
315
|
sessionId,
|
|
304
316
|
agentSessionId,
|
|
305
|
-
agentSessionFile
|
|
317
|
+
agentSessionFile,
|
|
318
|
+
gitBranch,
|
|
306
319
|
};
|
|
307
320
|
}
|
|
308
321
|
/**
|
|
@@ -1054,16 +1067,20 @@ export function createHookCommand() {
|
|
|
1054
1067
|
logger.debug(`[hook] Received event: ${JSON.stringify(event)}`);
|
|
1055
1068
|
process.exit(2); // Blocking error
|
|
1056
1069
|
}
|
|
1057
|
-
if (!event.transcript_path) {
|
|
1058
|
-
logger.error('[hook] Missing required field: transcript_path');
|
|
1059
|
-
logger.debug(`[hook] Received event: ${JSON.stringify(event)}`);
|
|
1060
|
-
process.exit(2); // Blocking error
|
|
1061
|
-
}
|
|
1062
1070
|
// Initialize logger context using CODEMIE_SESSION_ID from environment
|
|
1063
1071
|
// This ensures consistent session ID across all hooks
|
|
1064
1072
|
const { sessionId, agentName } = initializeHookContext();
|
|
1065
|
-
// Apply hook transformation if agent provides a transformer
|
|
1073
|
+
// Apply hook transformation if agent provides a transformer.
|
|
1074
|
+
// Some agents (e.g. Kimi) do not emit a transcript_path in their raw
|
|
1075
|
+
// hook payload; the transformer computes it from agent-specific session
|
|
1076
|
+
// layout before we validate the internal event shape.
|
|
1066
1077
|
const transformedEvent = applyHookTransformation(event, agentName);
|
|
1078
|
+
// Validate required fields after transformation so agent-specific
|
|
1079
|
+
// transformers can populate fields such as transcript_path.
|
|
1080
|
+
validateHookEvent(transformedEvent);
|
|
1081
|
+
if (process.exitCode === 2) {
|
|
1082
|
+
return; // Validation failed
|
|
1083
|
+
}
|
|
1067
1084
|
// Normalize event name and log processing info
|
|
1068
1085
|
normalizeAndLogEvent(transformedEvent, sessionId, agentName);
|
|
1069
1086
|
// Route to appropriate handler with transformed event and session ID
|