@ironbee-ai/cli 0.6.2 → 0.7.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/CHANGELOG.md +6 -0
- package/README.md +167 -39
- package/dist/analysis/code-changes.js.map +1 -1
- package/dist/analysis/cross-session.js.map +1 -1
- package/dist/analysis/fix-effectiveness.js.map +1 -1
- package/dist/analysis/time-analysis.js.map +1 -1
- package/dist/analysis/verdict-details.js.map +1 -1
- package/dist/analysis/verification-quality.js.map +1 -1
- package/dist/analytics/classifier.d.ts +99 -0
- package/dist/analytics/classifier.d.ts.map +1 -0
- package/dist/analytics/classifier.js +380 -0
- package/dist/analytics/classifier.js.map +1 -0
- package/dist/analytics/emit.d.ts +67 -0
- package/dist/analytics/emit.d.ts.map +1 -0
- package/dist/analytics/emit.js +901 -0
- package/dist/analytics/emit.js.map +1 -0
- package/dist/analytics/errors.d.ts +33 -0
- package/dist/analytics/errors.d.ts.map +1 -0
- package/dist/analytics/errors.js +93 -0
- package/dist/analytics/errors.js.map +1 -0
- package/dist/analytics/hook-trigger.d.ts +39 -0
- package/dist/analytics/hook-trigger.d.ts.map +1 -0
- package/dist/analytics/hook-trigger.js +127 -0
- package/dist/analytics/hook-trigger.js.map +1 -0
- package/dist/analytics/log.d.ts +44 -0
- package/dist/analytics/log.d.ts.map +1 -0
- package/dist/analytics/log.js +158 -0
- package/dist/analytics/log.js.map +1 -0
- package/dist/analytics/merge.d.ts +40 -0
- package/dist/analytics/merge.d.ts.map +1 -0
- package/dist/analytics/merge.js +527 -0
- package/dist/analytics/merge.js.map +1 -0
- package/dist/analytics/pricing.d.ts +149 -0
- package/dist/analytics/pricing.d.ts.map +1 -0
- package/dist/analytics/pricing.js +179 -0
- package/dist/analytics/pricing.js.map +1 -0
- package/dist/analytics/projection.d.ts +356 -0
- package/dist/analytics/projection.d.ts.map +1 -0
- package/dist/analytics/projection.js +2281 -0
- package/dist/analytics/projection.js.map +1 -0
- package/dist/analytics/spawn.d.ts +28 -0
- package/dist/analytics/spawn.d.ts.map +1 -0
- package/dist/analytics/spawn.js +57 -0
- package/dist/analytics/spawn.js.map +1 -0
- package/dist/analytics/state.d.ts +58 -0
- package/dist/analytics/state.d.ts.map +1 -0
- package/dist/analytics/state.js +329 -0
- package/dist/analytics/state.js.map +1 -0
- package/dist/analytics/transcript.d.ts +150 -0
- package/dist/analytics/transcript.d.ts.map +1 -0
- package/dist/analytics/transcript.js +276 -0
- package/dist/analytics/transcript.js.map +1 -0
- package/dist/analytics/types.d.ts +875 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +31 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/clients/base.d.ts +21 -2
- package/dist/clients/base.d.ts.map +1 -1
- package/dist/clients/claude/commands/ironbee-verify.md +15 -7
- package/dist/clients/claude/fragments/command-verify.node.md +33 -0
- package/dist/clients/claude/fragments/rule.node.md +29 -0
- package/dist/clients/claude/fragments/skill.node.md +77 -0
- package/dist/clients/claude/hooks/activity-end.d.ts +13 -0
- package/dist/clients/claude/hooks/activity-end.d.ts.map +1 -0
- package/dist/clients/claude/hooks/activity-end.js +42 -0
- package/dist/clients/claude/hooks/activity-end.js.map +1 -0
- package/dist/clients/claude/hooks/require-verdict.d.ts +3 -2
- package/dist/clients/claude/hooks/require-verdict.d.ts.map +1 -1
- package/dist/clients/claude/hooks/require-verdict.js +6 -5
- package/dist/clients/claude/hooks/require-verdict.js.map +1 -1
- package/dist/clients/claude/hooks/require-verification.d.ts +7 -4
- package/dist/clients/claude/hooks/require-verification.d.ts.map +1 -1
- package/dist/clients/claude/hooks/require-verification.js +44 -22
- package/dist/clients/claude/hooks/require-verification.js.map +1 -1
- package/dist/clients/claude/hooks/session-end.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-end.js +17 -2
- package/dist/clients/claude/hooks/session-end.js.map +1 -1
- package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-start.js +2 -1
- package/dist/clients/claude/hooks/session-start.js.map +1 -1
- package/dist/clients/claude/hooks/track-action-monitor.d.ts +27 -0
- package/dist/clients/claude/hooks/track-action-monitor.d.ts.map +1 -0
- package/dist/clients/claude/hooks/track-action-monitor.js +126 -0
- package/dist/clients/claude/hooks/track-action-monitor.js.map +1 -0
- package/dist/clients/claude/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/claude/hooks/track-action.js +29 -20
- package/dist/clients/claude/hooks/track-action.js.map +1 -1
- package/dist/clients/claude/hooks/verify-gate.d.ts.map +1 -1
- package/dist/clients/claude/hooks/verify-gate.js +18 -1
- package/dist/clients/claude/hooks/verify-gate.js.map +1 -1
- package/dist/clients/claude/index.d.ts +4 -1
- package/dist/clients/claude/index.d.ts.map +1 -1
- package/dist/clients/claude/index.js +171 -94
- package/dist/clients/claude/index.js.map +1 -1
- package/dist/clients/claude/rules/ironbee-verification.md +41 -33
- package/dist/clients/claude/skills/ironbee-verification.md +93 -76
- package/dist/clients/cursor/commands/ironbee-verify/SKILL.md +18 -10
- package/dist/clients/cursor/fragments/command-verify.node.md +33 -0
- package/dist/clients/cursor/fragments/rule.node.md +29 -0
- package/dist/clients/cursor/fragments/skill.node.md +77 -0
- package/dist/clients/cursor/hooks/activity-end.d.ts +14 -0
- package/dist/clients/cursor/hooks/activity-end.d.ts.map +1 -0
- package/dist/clients/cursor/hooks/activity-end.js +45 -0
- package/dist/clients/cursor/hooks/activity-end.js.map +1 -0
- package/dist/clients/cursor/hooks/require-verdict.d.ts +1 -1
- package/dist/clients/cursor/hooks/require-verdict.js +4 -4
- package/dist/clients/cursor/hooks/require-verification.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/require-verification.js +42 -16
- package/dist/clients/cursor/hooks/require-verification.js.map +1 -1
- package/dist/clients/cursor/hooks/session-end.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/session-end.js +18 -2
- package/dist/clients/cursor/hooks/session-end.js.map +1 -1
- package/dist/clients/cursor/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/session-start.js +2 -1
- package/dist/clients/cursor/hooks/session-start.js.map +1 -1
- package/dist/clients/cursor/hooks/track-action-monitor.d.ts +27 -0
- package/dist/clients/cursor/hooks/track-action-monitor.d.ts.map +1 -0
- package/dist/clients/cursor/hooks/track-action-monitor.js +133 -0
- package/dist/clients/cursor/hooks/track-action-monitor.js.map +1 -0
- package/dist/clients/cursor/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/track-action.js +51 -23
- package/dist/clients/cursor/hooks/track-action.js.map +1 -1
- package/dist/clients/cursor/hooks/verify-gate.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/verify-gate.js +14 -1
- package/dist/clients/cursor/hooks/verify-gate.js.map +1 -1
- package/dist/clients/cursor/index.d.ts +4 -1
- package/dist/clients/cursor/index.d.ts.map +1 -1
- package/dist/clients/cursor/index.js +117 -71
- package/dist/clients/cursor/index.js.map +1 -1
- package/dist/clients/cursor/rules/ironbee-verification.mdc +37 -29
- package/dist/clients/cursor/skills/ironbee-verification.md +93 -76
- package/dist/clients/registry.d.ts +14 -0
- package/dist/clients/registry.d.ts.map +1 -1
- package/dist/clients/registry.js +34 -0
- package/dist/clients/registry.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +40 -0
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/backend-toggle.d.ts +45 -0
- package/dist/commands/backend-toggle.d.ts.map +1 -0
- package/dist/commands/backend-toggle.js +192 -0
- package/dist/commands/backend-toggle.js.map +1 -0
- package/dist/commands/disable-backend.d.ts +14 -0
- package/dist/commands/disable-backend.d.ts.map +1 -0
- package/dist/commands/disable-backend.js +34 -0
- package/dist/commands/disable-backend.js.map +1 -0
- package/dist/commands/disable-verification.d.ts +16 -0
- package/dist/commands/disable-verification.d.ts.map +1 -0
- package/dist/commands/disable-verification.js +36 -0
- package/dist/commands/disable-verification.js.map +1 -0
- package/dist/commands/enable-backend.d.ts +15 -0
- package/dist/commands/enable-backend.d.ts.map +1 -0
- package/dist/commands/enable-backend.js +35 -0
- package/dist/commands/enable-backend.js.map +1 -0
- package/dist/commands/enable-verification.d.ts +14 -0
- package/dist/commands/enable-verification.d.ts.map +1 -0
- package/dist/commands/enable-verification.js +34 -0
- package/dist/commands/enable-verification.js.map +1 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +60 -0
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/import.d.ts +39 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +369 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +15 -20
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/process-analytics.d.ts +18 -0
- package/dist/commands/process-analytics.d.ts.map +1 -0
- package/dist/commands/process-analytics.js +57 -0
- package/dist/commands/process-analytics.js.map +1 -0
- package/dist/commands/queue.d.ts +2 -3
- package/dist/commands/queue.d.ts.map +1 -1
- package/dist/commands/queue.js +2 -3
- package/dist/commands/queue.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +29 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verification-toggle.d.ts +47 -0
- package/dist/commands/verification-toggle.d.ts.map +1 -0
- package/dist/commands/verification-toggle.js +113 -0
- package/dist/commands/verification-toggle.js.map +1 -0
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +28 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/hooks/core/actions.d.ts +64 -67
- package/dist/hooks/core/actions.d.ts.map +1 -1
- package/dist/hooks/core/actions.js +39 -24
- package/dist/hooks/core/actions.js.map +1 -1
- package/dist/hooks/core/activity-end.d.ts +20 -0
- package/dist/hooks/core/activity-end.d.ts.map +1 -0
- package/dist/hooks/core/activity-end.js +23 -0
- package/dist/hooks/core/activity-end.js.map +1 -0
- package/dist/hooks/core/required-tools.d.ts +30 -0
- package/dist/hooks/core/required-tools.d.ts.map +1 -0
- package/dist/hooks/core/required-tools.js +70 -0
- package/dist/hooks/core/required-tools.js.map +1 -0
- package/dist/hooks/core/session-state.d.ts +12 -3
- package/dist/hooks/core/session-state.d.ts.map +1 -1
- package/dist/hooks/core/session-state.js +59 -0
- package/dist/hooks/core/session-state.js.map +1 -1
- package/dist/hooks/core/submit-verdict.d.ts.map +1 -1
- package/dist/hooks/core/submit-verdict.js +16 -12
- package/dist/hooks/core/submit-verdict.js.map +1 -1
- package/dist/hooks/core/verify-gate.d.ts +17 -3
- package/dist/hooks/core/verify-gate.d.ts.map +1 -1
- package/dist/hooks/core/verify-gate.js +312 -116
- package/dist/hooks/core/verify-gate.js.map +1 -1
- package/dist/import/claude/analytics-runner.d.ts +42 -0
- package/dist/import/claude/analytics-runner.d.ts.map +1 -0
- package/dist/import/claude/analytics-runner.js +213 -0
- package/dist/import/claude/analytics-runner.js.map +1 -0
- package/dist/import/claude/discovery.d.ts +22 -0
- package/dist/import/claude/discovery.d.ts.map +1 -0
- package/dist/import/claude/discovery.js +197 -0
- package/dist/import/claude/discovery.js.map +1 -0
- package/dist/import/claude/encoding.d.ts +50 -0
- package/dist/import/claude/encoding.d.ts.map +1 -0
- package/dist/import/claude/encoding.js +110 -0
- package/dist/import/claude/encoding.js.map +1 -0
- package/dist/import/claude/events/file-change.d.ts +28 -0
- package/dist/import/claude/events/file-change.d.ts.map +1 -0
- package/dist/import/claude/events/file-change.js +112 -0
- package/dist/import/claude/events/file-change.js.map +1 -0
- package/dist/import/claude/events/tool-call.d.ts +61 -0
- package/dist/import/claude/events/tool-call.d.ts.map +1 -0
- package/dist/import/claude/events/tool-call.js +119 -0
- package/dist/import/claude/events/tool-call.js.map +1 -0
- package/dist/import/claude/runner.d.ts +31 -0
- package/dist/import/claude/runner.d.ts.map +1 -0
- package/dist/import/claude/runner.js +280 -0
- package/dist/import/claude/runner.js.map +1 -0
- package/dist/import/claude/summary.d.ts +23 -0
- package/dist/import/claude/summary.d.ts.map +1 -0
- package/dist/import/claude/summary.js +186 -0
- package/dist/import/claude/summary.js.map +1 -0
- package/dist/import/claude/transcript-walk.d.ts +52 -0
- package/dist/import/claude/transcript-walk.d.ts.map +1 -0
- package/dist/import/claude/transcript-walk.js +187 -0
- package/dist/import/claude/transcript-walk.js.map +1 -0
- package/dist/import/concurrent-pool.d.ts +45 -0
- package/dist/import/concurrent-pool.d.ts.map +1 -0
- package/dist/import/concurrent-pool.js +95 -0
- package/dist/import/concurrent-pool.js.map +1 -0
- package/dist/import/emitter.d.ts +29 -0
- package/dist/import/emitter.d.ts.map +1 -0
- package/dist/import/emitter.js +66 -0
- package/dist/import/emitter.js.map +1 -0
- package/dist/import/events/activity.d.ts +23 -0
- package/dist/import/events/activity.d.ts.map +1 -0
- package/dist/import/events/activity.js +45 -0
- package/dist/import/events/activity.js.map +1 -0
- package/dist/import/events/session.d.ts +24 -0
- package/dist/import/events/session.d.ts.map +1 -0
- package/dist/import/events/session.js +47 -0
- package/dist/import/events/session.js.map +1 -0
- package/dist/import/filter.d.ts +47 -0
- package/dist/import/filter.d.ts.map +1 -0
- package/dist/import/filter.js +90 -0
- package/dist/import/filter.js.map +1 -0
- package/dist/import/ids.d.ts +56 -0
- package/dist/import/ids.d.ts.map +1 -0
- package/dist/import/ids.js +87 -0
- package/dist/import/ids.js.map +1 -0
- package/dist/import/index.d.ts +29 -0
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +52 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/marker.d.ts +20 -0
- package/dist/import/marker.d.ts.map +1 -0
- package/dist/import/marker.js +71 -0
- package/dist/import/marker.js.map +1 -0
- package/dist/import/pipeline.d.ts +41 -0
- package/dist/import/pipeline.d.ts.map +1 -0
- package/dist/import/pipeline.js +47 -0
- package/dist/import/pipeline.js.map +1 -0
- package/dist/import/progress.d.ts +20 -0
- package/dist/import/progress.d.ts.map +1 -0
- package/dist/import/progress.js +69 -0
- package/dist/import/progress.js.map +1 -0
- package/dist/import/skip.d.ts +13 -0
- package/dist/import/skip.d.ts.map +1 -0
- package/dist/import/skip.js +24 -0
- package/dist/import/skip.js.map +1 -0
- package/dist/import/types.d.ts +125 -0
- package/dist/import/types.d.ts.map +1 -0
- package/dist/import/types.js +28 -0
- package/dist/import/types.js.map +1 -0
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/collector.d.ts +29 -3
- package/dist/lib/collector.d.ts.map +1 -1
- package/dist/lib/collector.js +118 -8
- package/dist/lib/collector.js.map +1 -1
- package/dist/lib/config.d.ts +240 -83
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +482 -89
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/event.d.ts +72 -0
- package/dist/lib/event.d.ts.map +1 -0
- package/dist/lib/event.js +42 -0
- package/dist/lib/event.js.map +1 -0
- package/dist/lib/gitignore.d.ts +21 -0
- package/dist/lib/gitignore.d.ts.map +1 -0
- package/dist/lib/gitignore.js +54 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/runtime-section.d.ts +118 -0
- package/dist/lib/runtime-section.d.ts.map +1 -0
- package/dist/lib/runtime-section.js +256 -0
- package/dist/lib/runtime-section.js.map +1 -0
- package/dist/lib/telemetry.d.ts +1 -1
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/telemetry.js +4 -1
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/queue/dead-letter.d.ts +5 -1
- package/dist/queue/dead-letter.d.ts.map +1 -1
- package/dist/queue/dead-letter.js +5 -1
- package/dist/queue/dead-letter.js.map +1 -1
- package/dist/queue/drain.d.ts +3 -2
- package/dist/queue/drain.d.ts.map +1 -1
- package/dist/queue/drain.js +3 -2
- package/dist/queue/drain.js.map +1 -1
- package/dist/queue/flush.d.ts +28 -12
- package/dist/queue/flush.d.ts.map +1 -1
- package/dist/queue/flush.js +43 -18
- package/dist/queue/flush.js.map +1 -1
- package/dist/queue/handlers/send-event.d.ts.map +1 -1
- package/dist/queue/handlers/send-event.js.map +1 -1
- package/dist/queue/index.d.ts +1 -2
- package/dist/queue/index.d.ts.map +1 -1
- package/dist/queue/index.js +2 -2
- package/dist/queue/index.js.map +1 -1
- package/dist/queue/paths.d.ts +4 -2
- package/dist/queue/paths.d.ts.map +1 -1
- package/dist/queue/paths.js +4 -2
- package/dist/queue/paths.js.map +1 -1
- package/dist/queue/process-file.d.ts +5 -1
- package/dist/queue/process-file.d.ts.map +1 -1
- package/dist/queue/process-file.js +5 -1
- package/dist/queue/process-file.js.map +1 -1
- package/dist/queue/snapshot.d.ts +4 -1
- package/dist/queue/snapshot.d.ts.map +1 -1
- package/dist/queue/snapshot.js +4 -1
- package/dist/queue/snapshot.js.map +1 -1
- package/dist/queue/spawn.d.ts +1 -3
- package/dist/queue/spawn.d.ts.map +1 -1
- package/dist/queue/spawn.js +1 -3
- package/dist/queue/spawn.js.map +1 -1
- package/dist/queue/submit.d.ts +6 -1
- package/dist/queue/submit.d.ts.map +1 -1
- package/dist/queue/submit.js +6 -1
- package/dist/queue/submit.js.map +1 -1
- package/dist/queue/types.d.ts +5 -1
- package/dist/queue/types.d.ts.map +1 -1
- package/dist/queue/types.js +5 -1
- package/dist/queue/types.js.map +1 -1
- package/dist/queue/worker-log.d.ts +3 -1
- package/dist/queue/worker-log.d.ts.map +1 -1
- package/dist/queue/worker-log.js +3 -1
- package/dist/queue/worker-log.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IronBee CLI — Analytics Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the analytics collection pipeline. The CLI projects
|
|
5
|
+
* the host transcript JSONL into a `SessionAnalytics` record (no content)
|
|
6
|
+
* and ships it to the IronBee collector as a `session_analytics` event.
|
|
7
|
+
*
|
|
8
|
+
* Privacy invariant: no field in any of these types ever holds raw
|
|
9
|
+
* user-prompt text or assistant-text content. Every field is structured
|
|
10
|
+
* metadata, count, label, byte size, or timestamp. The projection reads
|
|
11
|
+
* content locally for keyword matching / byte counting but emits only
|
|
12
|
+
* derived structural signals.
|
|
13
|
+
*
|
|
14
|
+
* Wire shape: top-level scalar fields are grouped into cohesive nested
|
|
15
|
+
* objects (`time`, `turns`, `classification`, `usage`, `tool_meta`,
|
|
16
|
+
* `code_changes`, `errors`, `user_activity`, `context_tokens`,
|
|
17
|
+
* `process_errors`, `user_messages`). Per-tool measurement is byte-based
|
|
18
|
+
* (`input_size`, `output_size`) plus a heuristic `approximated_*_tokens`;
|
|
19
|
+
* there is no per-tool token attribution and no `unattributed_*` residual.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Current schema_version emitted on the wire. Kept at "1.0" by operator
|
|
23
|
+
* choice — the internal refactor (logical groups + byte-based ToolUsage)
|
|
24
|
+
* doesn't bump the wire-version; backend migrates to the new shape under
|
|
25
|
+
* the same `schema_version: "1.0"` label.
|
|
26
|
+
*/
|
|
27
|
+
export declare const SCHEMA_VERSION: string;
|
|
28
|
+
/** Turn-bucket keys for context_tokens distribution. Bucketed by assistant message index. */
|
|
29
|
+
export type ContextTurnBucket = "1-3" | "4-10" | "11-25" | "26-50" | "51-100" | "100+";
|
|
30
|
+
/** Closed list of error categories derived from tool_result.content keyword match. */
|
|
31
|
+
export type ToolErrorCategory = "command_failed" | "user_rejected" | "edit_failed" | "file_changed" | "file_too_large" | "file_not_found" | "other";
|
|
32
|
+
export type TranscriptSource = "claude-code" | "cursor" | "missing";
|
|
33
|
+
/**
|
|
34
|
+
* Per-turn category label assigned by the heuristic classifier in
|
|
35
|
+
* `src/analytics/classifier.ts`. Mirrors codeburn's taxonomy with extended
|
|
36
|
+
* pattern coverage (more runtimes / frameworks). Closed string union — add
|
|
37
|
+
* a new value here if the classifier introduces a new bucket.
|
|
38
|
+
*/
|
|
39
|
+
export type TurnCategory = "coding" | "debugging" | "feature" | "refactoring" | "testing" | "exploration" | "planning" | "delegation" | "git" | "build/deploy" | "conversation" | "brainstorming" | "general";
|
|
40
|
+
/**
|
|
41
|
+
* Session-wide shape inferred from per-turn distribution + structural signals.
|
|
42
|
+
*
|
|
43
|
+
* - `quick_question`: very short session, no edits, minimal turns.
|
|
44
|
+
* - `exploration`: read-heavy with little/no editing.
|
|
45
|
+
* - `iterative_refinement`: many edits to a small concentrated set of files.
|
|
46
|
+
* - `multi_task`: ≥3 distinct human prompts (the user moved across tasks).
|
|
47
|
+
* - `single_task`: focused; default when no other shape applies.
|
|
48
|
+
* - `general`: not enough signal yet (e.g. fresh init, no human-user msg).
|
|
49
|
+
*
|
|
50
|
+
* Recomputed from `classification.category_breakdown` + bounds at every merge.
|
|
51
|
+
*/
|
|
52
|
+
export type SessionType = "quick_question" | "exploration" | "iterative_refinement" | "multi_task" | "single_task" | "general";
|
|
53
|
+
/**
|
|
54
|
+
* Per-category aggregate stats emitted in `classification.category_breakdown`.
|
|
55
|
+
* Element-wise additive across deltas (per-key sum of every numeric field).
|
|
56
|
+
*/
|
|
57
|
+
export interface CategoryStats {
|
|
58
|
+
/** Number of turns classified into this category. */
|
|
59
|
+
turns: number;
|
|
60
|
+
/** Of those, how many had at least one Edit/Write tool call. */
|
|
61
|
+
turns_with_edit: number;
|
|
62
|
+
/** Of those, how many had at least one Edit→Bash→Edit retry chain. */
|
|
63
|
+
turns_with_retry: number;
|
|
64
|
+
/** Total Edit→Bash→Edit retry events across this category. */
|
|
65
|
+
total_retries: number;
|
|
66
|
+
/**
|
|
67
|
+
* Sum of `cost_usd` attributed to the assistant messages within this
|
|
68
|
+
* category's turns. Approximation — uses the per-message cost from
|
|
69
|
+
* `pricing.ts`.
|
|
70
|
+
*/
|
|
71
|
+
cost_usd: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Time-bound aggregates: wall-clock duration, active vs. idle decomposition,
|
|
75
|
+
* hour-of-day for first / last activity.
|
|
76
|
+
*
|
|
77
|
+
* active = wall-clock - idle (idle = sum of next-msg-is-user gaps)
|
|
78
|
+
* start_hour, last_activity_hour are 0..23 local-time, derived from
|
|
79
|
+
* start_time / last_activity_time at projection time.
|
|
80
|
+
*/
|
|
81
|
+
export interface TimeMetrics {
|
|
82
|
+
/** Wall-clock duration in minutes (`last_activity_time - start_time`). Includes idle. */
|
|
83
|
+
duration_minutes: number;
|
|
84
|
+
/** Active duration in minutes (`duration_minutes - idle_minutes`, clamped ≥ 0). */
|
|
85
|
+
active_minutes: number;
|
|
86
|
+
/** User-idle duration in minutes (sum of pre-user-msg gaps). */
|
|
87
|
+
idle_minutes: number;
|
|
88
|
+
/** Hour-of-day (0..23 local) of session start. */
|
|
89
|
+
start_hour: number;
|
|
90
|
+
/** Hour-of-day (0..23 local) of last activity. */
|
|
91
|
+
last_activity_hour: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Per-turn counters at session level. `with_retry` and `one_shot` are
|
|
95
|
+
* convenience rollups of `classification.category_breakdown[*].turns_with_retry`
|
|
96
|
+
* and the inverse — surfaced here so backend dashboards don't need to walk the
|
|
97
|
+
* category map.
|
|
98
|
+
*/
|
|
99
|
+
export interface TurnsMetrics {
|
|
100
|
+
/** User-typed prompts (count only — privacy fence). */
|
|
101
|
+
user_count: number;
|
|
102
|
+
/** Assistant messages emitted across the session. */
|
|
103
|
+
assistant_count: number;
|
|
104
|
+
/** Turns with at least one Edit→Bash→Edit retry chain. */
|
|
105
|
+
with_retry: number;
|
|
106
|
+
/** Turns with ≥1 edit AND zero retries — first try worked. */
|
|
107
|
+
one_shot: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Heuristic per-turn classification — distribution + session-wide shape.
|
|
111
|
+
* `category_breakdown` keys are members of `TurnCategory` typed as open
|
|
112
|
+
* string for compactness (zero-count categories omitted).
|
|
113
|
+
*/
|
|
114
|
+
export interface ClassificationMetrics {
|
|
115
|
+
category_breakdown: Record<string, CategoryStats>;
|
|
116
|
+
session_type: SessionType;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Anthropic-exact token / cost aggregates. Sourced from `usage.*` on
|
|
120
|
+
* assistant messages, msg_id deduped, computed via the pricing table in
|
|
121
|
+
* `src/analytics/pricing.ts`.
|
|
122
|
+
*/
|
|
123
|
+
export interface UsageMetrics {
|
|
124
|
+
/** Fresh (non-cached) input tokens. */
|
|
125
|
+
input_tokens: number;
|
|
126
|
+
output_tokens: number;
|
|
127
|
+
/** Tokens written into Anthropic prompt cache (1.25× rate). */
|
|
128
|
+
cache_creation_tokens: number;
|
|
129
|
+
/** Tokens served from prompt cache (0.1× rate). */
|
|
130
|
+
cache_read_tokens: number;
|
|
131
|
+
/** Total estimated USD cost — sum of per-message attributions. */
|
|
132
|
+
cost_usd: number;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Aggregate signal about user prompts — count + total bytes + heuristic
|
|
136
|
+
* token estimate. Privacy: only structured signal, never raw text.
|
|
137
|
+
*
|
|
138
|
+
* `size` = sum of `JSON.stringify(message.content).length`
|
|
139
|
+
* for every human-typed user message.
|
|
140
|
+
* `approximated_tokens` = size / BYTES_PER_TOKEN.
|
|
141
|
+
*/
|
|
142
|
+
export interface UserMessagesMetrics {
|
|
143
|
+
count: number;
|
|
144
|
+
size: number;
|
|
145
|
+
approximated_tokens: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Bash-subcommand counts and session-wide tool boolean indicators. Per-tool
|
|
149
|
+
* breakdowns (tools / mcp_servers / skills / sub_agents / bash_binaries)
|
|
150
|
+
* remain top-level on the session — they each carry the full ToolUsage
|
|
151
|
+
* shape and have different keying semantics.
|
|
152
|
+
*/
|
|
153
|
+
export interface ToolMetaMetrics {
|
|
154
|
+
/** Optional argv[0..1] count map (e.g. `"git commit"` → N). */
|
|
155
|
+
bash_subcommands?: Record<string, number>;
|
|
156
|
+
/** Any `Task`/`Agent` tool_use seen — sub-agent invocation. */
|
|
157
|
+
uses_sub_agent: boolean;
|
|
158
|
+
/** Any `Skill` tool_use seen. */
|
|
159
|
+
uses_skill: boolean;
|
|
160
|
+
/** Any `mcp__<server>__<tool>` tool_use seen. */
|
|
161
|
+
uses_mcp: boolean;
|
|
162
|
+
uses_web_search: boolean;
|
|
163
|
+
uses_web_fetch: boolean;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* File-edit aggregates — modified-file count, line deltas, hot files,
|
|
167
|
+
* per-language counts. `languages` lives here because it's derived from
|
|
168
|
+
* file extensions of edits.
|
|
169
|
+
*/
|
|
170
|
+
export interface CodeChangesMetrics {
|
|
171
|
+
/** Distinct file_paths edited across the session. */
|
|
172
|
+
files_modified: number;
|
|
173
|
+
lines_added: number;
|
|
174
|
+
lines_removed: number;
|
|
175
|
+
/** Top 5 by edit count. */
|
|
176
|
+
hot_files: Array<{
|
|
177
|
+
path: string;
|
|
178
|
+
change_count: number;
|
|
179
|
+
}>;
|
|
180
|
+
/** Per-language counts derived from edited file extensions. */
|
|
181
|
+
languages: Record<string, number>;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Tool-error totals + interrupt count. Categories are keyed by
|
|
185
|
+
* `ToolErrorCategory`; counts are session-wide.
|
|
186
|
+
*/
|
|
187
|
+
export interface ErrorsMetrics {
|
|
188
|
+
tool_errors_total: number;
|
|
189
|
+
tool_error_categories: Record<string, number>;
|
|
190
|
+
/** `[Request interrupted by user]` tool_results across the session. */
|
|
191
|
+
user_interruptions: number;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* User-activity histograms — when did the user message? Privacy fence:
|
|
195
|
+
* histograms only, no per-message arrays.
|
|
196
|
+
*
|
|
197
|
+
* `response_time_buckets` — `"2-10s"`, `"10-30s"`, `"30s-1m"`, `"1-2m"`,
|
|
198
|
+
* `"2-5m"`, `"5-15m"`, `">15m"` (counter-map, additive)
|
|
199
|
+
* `messages_by_hour` — keys `"0".."23"` (local timezone)
|
|
200
|
+
* `messages_by_date` — keys `"YYYY-MM-DD"` (local timezone)
|
|
201
|
+
* `messages_by_weekday` — keys `"monday".."sunday"` (lowercase, local timezone)
|
|
202
|
+
*/
|
|
203
|
+
export interface UserActivityMetrics {
|
|
204
|
+
response_time_buckets: Record<string, number>;
|
|
205
|
+
messages_by_hour: Record<string, number>;
|
|
206
|
+
messages_by_date: Record<string, number>;
|
|
207
|
+
messages_by_weekday: Record<string, number>;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Context-window statistics. `latest` is the most recent assistant
|
|
211
|
+
* message's total context tokens (input + cache_creation + cache_read).
|
|
212
|
+
* `peak` is the max observed. `buckets` maps each `ContextTurnBucket` key
|
|
213
|
+
* to `{sum, count, avg}` where `avg = sum / count`.
|
|
214
|
+
*/
|
|
215
|
+
export interface ContextTokensMetrics {
|
|
216
|
+
latest: number;
|
|
217
|
+
peak: number;
|
|
218
|
+
buckets: Record<string, {
|
|
219
|
+
sum: number;
|
|
220
|
+
count: number;
|
|
221
|
+
avg: number;
|
|
222
|
+
}>;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Projection-time errors (parse / format / projector exceptions).
|
|
226
|
+
* `has` is the convenience boolean (`Object.keys(items).length > 0`).
|
|
227
|
+
*/
|
|
228
|
+
export interface ProcessErrorsMetrics {
|
|
229
|
+
has: boolean;
|
|
230
|
+
items: Record<string, ProcessError>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The wire payload — fully-accumulated session analytics emitted to the
|
|
234
|
+
* collector at every Stop hook and SessionEnd. Backend retains the latest
|
|
235
|
+
* snapshot per session_id via (snapshot_at, offset) lexicographic LWW.
|
|
236
|
+
*
|
|
237
|
+
* Top-level scalar fields are grouped into logical objects (`time`,
|
|
238
|
+
* `turns`, `classification`, `usage`, `code_changes`, …). Identity /
|
|
239
|
+
* provenance, snapshot meta, and time bounds (ISO strings) stay flat.
|
|
240
|
+
* Per-tool maps (`tools`, `mcp_servers`, `skills`, `sub_agents`,
|
|
241
|
+
* `bash_binaries`) and `models` also stay top-level — each has different
|
|
242
|
+
* keying / merge semantics.
|
|
243
|
+
*/
|
|
244
|
+
export interface SessionAnalytics {
|
|
245
|
+
session_id: string;
|
|
246
|
+
/**
|
|
247
|
+
* Project name (basename of git root or project dir). Same convention as
|
|
248
|
+
* other IronBee events' `project_name` field — see `resolveProjectName`
|
|
249
|
+
* in `src/hooks/core/actions.ts`.
|
|
250
|
+
*/
|
|
251
|
+
project_name: string;
|
|
252
|
+
/**
|
|
253
|
+
* Operator email read from per-session state.json (populated at
|
|
254
|
+
* session-start). Composed at emit time, NOT persisted in accumulated.
|
|
255
|
+
* Omitted from wire when unset.
|
|
256
|
+
*/
|
|
257
|
+
user_email?: string;
|
|
258
|
+
/** semver-ish, e.g. "1.0". Bumped on any projection logic change. */
|
|
259
|
+
schema_version: string;
|
|
260
|
+
transcript_source: TranscriptSource;
|
|
261
|
+
is_final: boolean;
|
|
262
|
+
/** ISO; when this snapshot was projected. */
|
|
263
|
+
snapshot_at: string;
|
|
264
|
+
/** Byte offset in the host transcript JSONL that this snapshot covers up to. */
|
|
265
|
+
offset: number;
|
|
266
|
+
/** Only set when is_final and SessionEnd carried a reason. */
|
|
267
|
+
end_reason?: string;
|
|
268
|
+
/** ISO. */
|
|
269
|
+
start_time: string;
|
|
270
|
+
/** ISO; latest message timestamp seen. */
|
|
271
|
+
last_activity_time: string;
|
|
272
|
+
time: TimeMetrics;
|
|
273
|
+
turns: TurnsMetrics;
|
|
274
|
+
classification: ClassificationMetrics;
|
|
275
|
+
usage: UsageMetrics;
|
|
276
|
+
/**
|
|
277
|
+
* Per-model breakdown — `assistant.message.model` → usage + cost.
|
|
278
|
+
* Element-wise additive across deltas (per-key sum on every numeric
|
|
279
|
+
* field) — see merge.ts.
|
|
280
|
+
*/
|
|
281
|
+
models: Record<string, ModelUsage>;
|
|
282
|
+
/** Aggregate user-prompt signal (count + size + approximated_tokens). */
|
|
283
|
+
user_messages: UserMessagesMetrics;
|
|
284
|
+
/** Per-tool — `tool_use.name` → ToolUsage. */
|
|
285
|
+
tools: Record<string, ToolUsage>;
|
|
286
|
+
/** Per-MCP-server — extracted prefix from `mcp__<server>__<tool>`. */
|
|
287
|
+
mcp_servers: Record<string, ToolUsage>;
|
|
288
|
+
/** Per-skill — keyed by `Skill` tool's `input.skill`. */
|
|
289
|
+
skills: Record<string, ToolUsage>;
|
|
290
|
+
/** Per-sub-agent — keyed by `Agent`/`Task` tool's `input.subagent_type`. */
|
|
291
|
+
sub_agents: Record<string, ToolUsage>;
|
|
292
|
+
/** Per-bash-binary — first token of every Bash command body. */
|
|
293
|
+
bash_binaries: Record<string, ToolUsage>;
|
|
294
|
+
tool_meta: ToolMetaMetrics;
|
|
295
|
+
code_changes: CodeChangesMetrics;
|
|
296
|
+
errors: ErrorsMetrics;
|
|
297
|
+
user_activity: UserActivityMetrics;
|
|
298
|
+
context_tokens: ContextTokensMetrics;
|
|
299
|
+
process_errors: ProcessErrorsMetrics;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Per-model usage breakdown. One entry per `assistant.message.model` seen
|
|
303
|
+
* in the session. Element-wise additive across deltas: matching keys sum
|
|
304
|
+
* every numeric field; new keys are added.
|
|
305
|
+
*/
|
|
306
|
+
export interface ModelUsage {
|
|
307
|
+
/** Number of assistant messages emitted by this model. */
|
|
308
|
+
count: number;
|
|
309
|
+
input_tokens: number;
|
|
310
|
+
output_tokens: number;
|
|
311
|
+
cache_creation_tokens: number;
|
|
312
|
+
cache_read_tokens: number;
|
|
313
|
+
/** Cost contribution of this model for this session, in USD. */
|
|
314
|
+
cost_usd: number;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Per-tool / per-MCP-server / per-skill / per-sub-agent / per-bash-binary
|
|
318
|
+
* usage breakdown. Byte-based measurement: `input_size` /
|
|
319
|
+
* `output_size` are exact byte counts; `approximated_*_tokens` is a
|
|
320
|
+
* single bytes/4 heuristic conversion. There is no per-tool token
|
|
321
|
+
* attribution — backend recomputes per-tool cost from session-level
|
|
322
|
+
* Anthropic-exact tokens × pricing rate when needed.
|
|
323
|
+
*
|
|
324
|
+
* `input_size` — sum of `JSON.stringify(tool_use.input).length`
|
|
325
|
+
* `output_size` — sum of `JSON.stringify(tool_result.content).length`
|
|
326
|
+
* `approximated_input_tokens` = input_size / BYTES_PER_TOKEN
|
|
327
|
+
* `approximated_output_tokens` = output_size / BYTES_PER_TOKEN
|
|
328
|
+
*
|
|
329
|
+
* Element-wise additive across deltas. `approximated_*_tokens` are
|
|
330
|
+
* recomputed from the summed sizes after merge to avoid drift.
|
|
331
|
+
*/
|
|
332
|
+
export interface ToolUsage {
|
|
333
|
+
count: number;
|
|
334
|
+
errors: number;
|
|
335
|
+
input_size: number;
|
|
336
|
+
output_size: number;
|
|
337
|
+
approximated_input_tokens: number;
|
|
338
|
+
approximated_output_tokens: number;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Captured projection-time error. Recorded into
|
|
342
|
+
* `accumulated.process_errors.items` (deduped by `errorSignature`) so
|
|
343
|
+
* analytics consumers can see when the client hit unexpected transcript
|
|
344
|
+
* shapes / format changes / projector bugs.
|
|
345
|
+
*
|
|
346
|
+
* Privacy: `error_message` and `stack_first_lines` are truncated and come
|
|
347
|
+
* from the JS engine / projector code path — not from user content.
|
|
348
|
+
*/
|
|
349
|
+
export interface ProcessError {
|
|
350
|
+
/** `Error.name` (e.g. "TypeError"). */
|
|
351
|
+
error_type: string;
|
|
352
|
+
/** `Error.message`, truncated to 200 chars. */
|
|
353
|
+
error_message: string;
|
|
354
|
+
/** First ~3 stack frames, joined by `\n`. Truncated to 800 chars. */
|
|
355
|
+
stack_first_lines: string;
|
|
356
|
+
/** How many times this signature was seen across the session. */
|
|
357
|
+
count: number;
|
|
358
|
+
/** ISO timestamp of the first occurrence. */
|
|
359
|
+
first_seen: string;
|
|
360
|
+
/** ISO timestamp of the most recent occurrence. */
|
|
361
|
+
last_seen: string;
|
|
362
|
+
/** Optional short label of where it happened. Truncated to 100 chars. */
|
|
363
|
+
sample_context?: string;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Pending tool_use lifecycle entry. Persisted in `state.internal` so a
|
|
367
|
+
* tool_use emitted in slice K can have its tool_result counted in slice
|
|
368
|
+
* K+N correctly. No per-tool token attribution — this carries only the
|
|
369
|
+
* identity needed to look up the tool's bucket when its tool_result
|
|
370
|
+
* eventually arrives.
|
|
371
|
+
*/
|
|
372
|
+
export interface PendingToolUse {
|
|
373
|
+
/** Full tool name (keeps `mcp__<server>__<tool>` prefix). */
|
|
374
|
+
tool_name: string;
|
|
375
|
+
/** Bash binary name (first non-env token) — set only when tool is Bash. */
|
|
376
|
+
bash_binary?: string;
|
|
377
|
+
/** Skill name from `Skill` tool's `input.skill`. */
|
|
378
|
+
skill_name?: string;
|
|
379
|
+
/** Sub-agent type from `Agent` / `Task` tool's `input.subagent_type`. */
|
|
380
|
+
sub_agent_type?: string;
|
|
381
|
+
/**
|
|
382
|
+
* `turn_index` of the turn that EMITTED this tool_use. Lets a
|
|
383
|
+
* late-arriving tool_result detect cross-turn cases.
|
|
384
|
+
*/
|
|
385
|
+
originating_turn_index?: number;
|
|
386
|
+
}
|
|
387
|
+
/** Fields composed at emit time, never stored in `accumulated`. */
|
|
388
|
+
export type PerTriggerFields = "is_final" | "snapshot_at" | "offset" | "end_reason" | "user_email";
|
|
389
|
+
/**
|
|
390
|
+
* Accumulated subset of SessionAnalytics — only fields that carry forward
|
|
391
|
+
* across triggers. Per-trigger metadata is composed live from the trigger.
|
|
392
|
+
*/
|
|
393
|
+
export type AccumulatedAnalytics = Omit<SessionAnalytics, PerTriggerFields>;
|
|
394
|
+
/**
|
|
395
|
+
* Per-session state file shape (stored at
|
|
396
|
+
* `<projectDir>/.ironbee/sessions/<session_id>/analytics/state.json`).
|
|
397
|
+
*
|
|
398
|
+
* Holds the read cursor + accumulated analytics + idempotency markers +
|
|
399
|
+
* transcript identity (for reset detection) + internal aggregation maps.
|
|
400
|
+
*/
|
|
401
|
+
export interface AnalyticsSessionState {
|
|
402
|
+
session_id: string;
|
|
403
|
+
transcript_path: string;
|
|
404
|
+
transcript_inode: number;
|
|
405
|
+
transcript_size_at_last_read: number;
|
|
406
|
+
transcript_first_kb_sha256: string;
|
|
407
|
+
/** Byte position to resume reading from (turn-safe — §4.8). */
|
|
408
|
+
offset: number;
|
|
409
|
+
/** ISO; touched on every persist for orphan-cleanup (§10.6). */
|
|
410
|
+
last_read_at: string;
|
|
411
|
+
last_emitted_offset: number;
|
|
412
|
+
last_emitted_is_final: boolean;
|
|
413
|
+
accumulated: AccumulatedAnalytics;
|
|
414
|
+
internal: {
|
|
415
|
+
/** Full path→count map; emit's `code_changes.hot_files` = top 5 of this. */
|
|
416
|
+
file_path_change_counts: Record<string, number>;
|
|
417
|
+
/** For `code_changes.files_modified` count integrity. Sorted on persist. */
|
|
418
|
+
distinct_file_paths_seen: string[];
|
|
419
|
+
/**
|
|
420
|
+
* ms-since-epoch of the most recent assistant message we've seen.
|
|
421
|
+
* Used to compute the user-msg gap to the FIRST human-text user
|
|
422
|
+
* message of the next slice.
|
|
423
|
+
*/
|
|
424
|
+
last_assistant_ts_ms?: number;
|
|
425
|
+
/**
|
|
426
|
+
* Tool_use lifecycle tracking, keyed by `tool_use_id`. Carries an
|
|
427
|
+
* entry from the emitting assistant N1 until the tool_result arrives.
|
|
428
|
+
*/
|
|
429
|
+
pending_tool_uses?: Record<string, PendingToolUse>;
|
|
430
|
+
/**
|
|
431
|
+
* Cumulative user-idle ms across all merged deltas. Stored at ms
|
|
432
|
+
* precision; the wire field `time.idle_minutes` is `Math.round(this / 60000)`.
|
|
433
|
+
*/
|
|
434
|
+
idle_ms_total?: number;
|
|
435
|
+
/**
|
|
436
|
+
* In-flight per-turn classifier state. Persists across slice
|
|
437
|
+
* boundaries when a turn spans slices.
|
|
438
|
+
*/
|
|
439
|
+
current_turn?: CurrentTurnState;
|
|
440
|
+
/**
|
|
441
|
+
* Next turn_index to assign when a fresh turn opens. Starts at 1.
|
|
442
|
+
*/
|
|
443
|
+
next_turn_index?: number;
|
|
444
|
+
/**
|
|
445
|
+
* Built `SessionTurnAnalytics` records that have closed and are
|
|
446
|
+
* waiting for emit to drain to the collector.
|
|
447
|
+
*/
|
|
448
|
+
pending_turn_events?: SessionTurnAnalytics[];
|
|
449
|
+
/**
|
|
450
|
+
* Built `SessionTurnStepAnalytics` records that have closed (their
|
|
451
|
+
* parent turn closed) and are waiting for emit to drain.
|
|
452
|
+
*/
|
|
453
|
+
pending_step_events?: SessionTurnStepAnalytics[];
|
|
454
|
+
/**
|
|
455
|
+
* Built `APIRequestAnalytics` body-only records (one per assistant
|
|
456
|
+
* line in this and prior slices that haven't been drained yet).
|
|
457
|
+
* Emit drains these as `api_request` wire events alongside
|
|
458
|
+
* session_turn / session_turn_step.
|
|
459
|
+
*/
|
|
460
|
+
pending_api_request_events?: APIRequestAnalytics[];
|
|
461
|
+
/**
|
|
462
|
+
* Anthropic API message ids already counted across all prior slices.
|
|
463
|
+
* Claude Code's transcript writer occasionally persists the same
|
|
464
|
+
* assistant API response on multiple JSONL lines; projection skips
|
|
465
|
+
* any assistant line whose `message.id` is in this set so a single
|
|
466
|
+
* API call counts once toward tokens / cost.
|
|
467
|
+
*/
|
|
468
|
+
seen_assistant_message_ids?: string[];
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* In-flight signal accumulator for a single turn. Built by the projection
|
|
473
|
+
* walk and consumed by `classifyTurn` when the turn closes.
|
|
474
|
+
*
|
|
475
|
+
* Privacy: every field is a boolean / number — no raw content text.
|
|
476
|
+
*
|
|
477
|
+
* The per-turn aggregator carries the same logical structure as the wire
|
|
478
|
+
* `SessionTurnAnalytics` (groups: usage, tool_meta, code_changes, errors).
|
|
479
|
+
* Tokens / cost stay flat in the accumulator (`UsageMetrics`-shaped fields
|
|
480
|
+
* are folded into `usage` at delta-build time).
|
|
481
|
+
*/
|
|
482
|
+
export interface CurrentTurnState {
|
|
483
|
+
/** 1-based turn index within the session (assigned at openTurn). */
|
|
484
|
+
turn_index: number;
|
|
485
|
+
/** ISO timestamp of the opening human-user msg (this turn's start_time). */
|
|
486
|
+
start_time: string;
|
|
487
|
+
/**
|
|
488
|
+
* What opened this turn. Set at openTurn time based on whether the
|
|
489
|
+
* opening user msg carried `isMeta: true`.
|
|
490
|
+
*/
|
|
491
|
+
triggered_by: "user_msg" | "host_inject";
|
|
492
|
+
/** Regex-match flags from the user prompt that opened this turn. */
|
|
493
|
+
kw_debug: boolean;
|
|
494
|
+
kw_feature: boolean;
|
|
495
|
+
kw_refactor: boolean;
|
|
496
|
+
kw_brainstorm: boolean;
|
|
497
|
+
kw_research: boolean;
|
|
498
|
+
kw_file_pattern: boolean;
|
|
499
|
+
kw_script_pattern: boolean;
|
|
500
|
+
kw_url: boolean;
|
|
501
|
+
/** Tool-bucket flags accumulated as assistant messages arrive. */
|
|
502
|
+
has_edit: boolean;
|
|
503
|
+
has_read: boolean;
|
|
504
|
+
has_bash: boolean;
|
|
505
|
+
has_task: boolean;
|
|
506
|
+
has_search: boolean;
|
|
507
|
+
has_mcp: boolean;
|
|
508
|
+
has_skill: boolean;
|
|
509
|
+
has_plan: boolean;
|
|
510
|
+
/** Bash command keyword flags accumulated across Bash tool_use bodies. */
|
|
511
|
+
bash_test: boolean;
|
|
512
|
+
bash_build: boolean;
|
|
513
|
+
bash_install: boolean;
|
|
514
|
+
bash_git: boolean;
|
|
515
|
+
/**
|
|
516
|
+
* Edit→Bash→Edit retry detection. `saw_edit_pending_bash` is true after
|
|
517
|
+
* an Edit until a Bash arrives; seeing the next Edit increments `retries`.
|
|
518
|
+
*/
|
|
519
|
+
saw_edit_pending_bash: boolean;
|
|
520
|
+
saw_bash_after_edit: boolean;
|
|
521
|
+
retries: number;
|
|
522
|
+
/** Number of assistant messages observed in this turn. */
|
|
523
|
+
assistant_messages: number;
|
|
524
|
+
/** Total tool_use blocks observed in this turn. */
|
|
525
|
+
tool_calls: number;
|
|
526
|
+
/** Whether the turn was interrupted (tool_result with `[Request interrupted by user]`). */
|
|
527
|
+
was_interrupted: boolean;
|
|
528
|
+
/** Most recent message timestamp seen (drives end_time + duration). */
|
|
529
|
+
last_activity_time: string;
|
|
530
|
+
/** Tokens (this turn — Anthropic-exact). Folded into `usage` at delta build. */
|
|
531
|
+
input_tokens: number;
|
|
532
|
+
output_tokens: number;
|
|
533
|
+
cache_creation_tokens: number;
|
|
534
|
+
cache_read_tokens: number;
|
|
535
|
+
/** Sum of per-message cost_usd contributed by assistant messages in this turn. */
|
|
536
|
+
cost_usd: number;
|
|
537
|
+
/** Per-turn per-tool/server/binary/skill/sub-agent/model breakdowns. */
|
|
538
|
+
tools: Record<string, ToolUsage>;
|
|
539
|
+
mcp_servers: Record<string, ToolUsage>;
|
|
540
|
+
bash_binaries: Record<string, ToolUsage>;
|
|
541
|
+
bash_subcommands: Record<string, number>;
|
|
542
|
+
skills: Record<string, ToolUsage>;
|
|
543
|
+
sub_agents: Record<string, ToolUsage>;
|
|
544
|
+
models: Record<string, ModelUsage>;
|
|
545
|
+
/** Per-turn languages — derived from edited file extensions. Lives in CodeChanges group on wire. */
|
|
546
|
+
languages: Record<string, number>;
|
|
547
|
+
/** Per-turn parallels to the session-level `tool_meta.uses_*` booleans. */
|
|
548
|
+
uses_sub_agent: boolean;
|
|
549
|
+
uses_skill: boolean;
|
|
550
|
+
uses_mcp: boolean;
|
|
551
|
+
uses_web_search: boolean;
|
|
552
|
+
uses_web_fetch: boolean;
|
|
553
|
+
/** Files edited in this turn — path → change count. */
|
|
554
|
+
file_change_counts: Record<string, number>;
|
|
555
|
+
lines_added: number;
|
|
556
|
+
lines_removed: number;
|
|
557
|
+
/** Tool errors observed in this turn (tool_result with is_error=true). */
|
|
558
|
+
tool_errors: number;
|
|
559
|
+
tool_error_categories: Record<string, number>;
|
|
560
|
+
/** Context tokens at every assistant message in this turn. */
|
|
561
|
+
context_tokens_samples: number[];
|
|
562
|
+
context_tokens_latest: number;
|
|
563
|
+
context_tokens_peak: number;
|
|
564
|
+
/** Projection-time errors during this turn's lines, deduped by signature. */
|
|
565
|
+
process_errors: Record<string, ProcessError>;
|
|
566
|
+
/** In-flight per-step accumulator. */
|
|
567
|
+
current_step?: CurrentStepState;
|
|
568
|
+
/** Closed steps in this turn that are NOT yet ready to emit. */
|
|
569
|
+
completed_steps: CurrentStepState[];
|
|
570
|
+
/** Next `step_index` to assign when a fresh step opens within this turn. */
|
|
571
|
+
next_step_index: number;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* In-flight signal accumulator for a single step within a turn. A step
|
|
575
|
+
* boundary = one assistant message + every tool_result that came back
|
|
576
|
+
* from its tool_uses.
|
|
577
|
+
*
|
|
578
|
+
* Privacy: same fence as CurrentTurnState — counts, labels, byte sizes,
|
|
579
|
+
* no raw text content.
|
|
580
|
+
*/
|
|
581
|
+
export interface CurrentStepState {
|
|
582
|
+
/** 1-based ordinal within the parent turn (resets per turn). */
|
|
583
|
+
step_index: number;
|
|
584
|
+
/** ISO timestamp of the opening assistant message. */
|
|
585
|
+
start_time: string;
|
|
586
|
+
/** ISO; updated to the latest tool_result timestamp in this step. */
|
|
587
|
+
last_activity_time: string;
|
|
588
|
+
tool_calls: number;
|
|
589
|
+
/** True if a `[Request interrupted by user]` tool_result landed in this step. */
|
|
590
|
+
was_interrupted: boolean;
|
|
591
|
+
/** Tokens / cost (this step only — Anthropic-exact). */
|
|
592
|
+
input_tokens: number;
|
|
593
|
+
output_tokens: number;
|
|
594
|
+
cache_creation_tokens: number;
|
|
595
|
+
cache_read_tokens: number;
|
|
596
|
+
cost_usd: number;
|
|
597
|
+
/** Per-step per-tool/server/binary/skill/sub-agent/model breakdowns. */
|
|
598
|
+
tools: Record<string, ToolUsage>;
|
|
599
|
+
mcp_servers: Record<string, ToolUsage>;
|
|
600
|
+
bash_binaries: Record<string, ToolUsage>;
|
|
601
|
+
bash_subcommands: Record<string, number>;
|
|
602
|
+
skills: Record<string, ToolUsage>;
|
|
603
|
+
sub_agents: Record<string, ToolUsage>;
|
|
604
|
+
models: Record<string, ModelUsage>;
|
|
605
|
+
languages: Record<string, number>;
|
|
606
|
+
/** Per-step parallels to the session/turn-level `tool_meta.uses_*` booleans. */
|
|
607
|
+
uses_sub_agent: boolean;
|
|
608
|
+
uses_skill: boolean;
|
|
609
|
+
uses_mcp: boolean;
|
|
610
|
+
uses_web_search: boolean;
|
|
611
|
+
uses_web_fetch: boolean;
|
|
612
|
+
/** Files edited in this step — path → change count. */
|
|
613
|
+
file_change_counts: Record<string, number>;
|
|
614
|
+
lines_added: number;
|
|
615
|
+
lines_removed: number;
|
|
616
|
+
/** Tool errors observed in this step. */
|
|
617
|
+
tool_errors: number;
|
|
618
|
+
tool_error_categories: Record<string, number>;
|
|
619
|
+
/** Context tokens at this step's assistant message (single sample per step). */
|
|
620
|
+
context_tokens?: number;
|
|
621
|
+
/** Projection-time errors during this step's lines. */
|
|
622
|
+
process_errors: Record<string, ProcessError>;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Why a turn closed.
|
|
626
|
+
*
|
|
627
|
+
* - `stop` — the Stop hook fired (agent finished its current task).
|
|
628
|
+
* - `session_end` — finalization with an open turn at SessionEnd.
|
|
629
|
+
* - `next_user_msg` — multiple human-user prompts arrived in a single slice.
|
|
630
|
+
* - `still_open` — reserved; not emitted in the Stop-closes-turn model.
|
|
631
|
+
*/
|
|
632
|
+
export type TurnEndReason = "stop" | "next_user_msg" | "session_end" | "still_open";
|
|
633
|
+
/**
|
|
634
|
+
* Per-turn analytics record — one human-user prompt + the assistant
|
|
635
|
+
* messages and tool_results it triggered. Backend can reconstruct the
|
|
636
|
+
* session-level `SessionAnalytics` aggregate by merging N of these
|
|
637
|
+
* records (sum / max / OR per the rules in `merge.ts`).
|
|
638
|
+
*
|
|
639
|
+
* Same logical group structure as session, with these differences:
|
|
640
|
+
* - `turns` group GONE (turn = 1 turn, redundant)
|
|
641
|
+
* - `classification` collapses to single `category` field (not nested)
|
|
642
|
+
* - `user_activity` GONE (session-level only)
|
|
643
|
+
* - `context_tokens.buckets` GONE (turn has single sample range)
|
|
644
|
+
*/
|
|
645
|
+
export interface SessionTurnAnalytics {
|
|
646
|
+
session_id: string;
|
|
647
|
+
project_name: string;
|
|
648
|
+
user_email?: string;
|
|
649
|
+
schema_version: string;
|
|
650
|
+
transcript_source: TranscriptSource;
|
|
651
|
+
/** 1-based ordinal within the session. */
|
|
652
|
+
turn_index: number;
|
|
653
|
+
/**
|
|
654
|
+
* Deterministic identifier — `sha256(session_id|turn_index|start_time)`
|
|
655
|
+
* sliced to 16 hex chars. Idempotent across re-emits.
|
|
656
|
+
*/
|
|
657
|
+
turn_id: string;
|
|
658
|
+
/**
|
|
659
|
+
* What opened this turn:
|
|
660
|
+
* - `"user_msg"` — a real human-typed user prompt (no `isMeta` flag).
|
|
661
|
+
* - `"host_inject"` — a host-injected user msg (`isMeta=true`) opened
|
|
662
|
+
* the turn because no turn was open at the time.
|
|
663
|
+
*/
|
|
664
|
+
triggered_by: "user_msg" | "host_inject";
|
|
665
|
+
/** ISO; opening human-user message timestamp. */
|
|
666
|
+
start_time: string;
|
|
667
|
+
/** ISO; closing event timestamp. */
|
|
668
|
+
end_time: string;
|
|
669
|
+
end_reason: TurnEndReason;
|
|
670
|
+
/** 0..23 derived from start_time (local timezone). */
|
|
671
|
+
start_hour: number;
|
|
672
|
+
/** 0..23 derived from end_time (local timezone). */
|
|
673
|
+
end_hour: number;
|
|
674
|
+
/** Wall-clock ms of the turn. */
|
|
675
|
+
duration: number;
|
|
676
|
+
category: TurnCategory;
|
|
677
|
+
/** Had at least one Edit/Write AND zero retries → first try worked. */
|
|
678
|
+
was_one_shot: boolean;
|
|
679
|
+
/** A `[Request interrupted by user]` tool_result was seen in this turn. */
|
|
680
|
+
was_interrupted: boolean;
|
|
681
|
+
assistant_messages: number;
|
|
682
|
+
tool_calls: number;
|
|
683
|
+
/** Edit→Bash→Edit retry chain count within this turn. */
|
|
684
|
+
retries: number;
|
|
685
|
+
usage: UsageMetrics;
|
|
686
|
+
tools: Record<string, ToolUsage>;
|
|
687
|
+
mcp_servers: Record<string, ToolUsage>;
|
|
688
|
+
bash_binaries: Record<string, ToolUsage>;
|
|
689
|
+
skills: Record<string, ToolUsage>;
|
|
690
|
+
sub_agents: Record<string, ToolUsage>;
|
|
691
|
+
models: Record<string, ModelUsage>;
|
|
692
|
+
tool_meta: ToolMetaMetrics;
|
|
693
|
+
code_changes: CodeChangesMetrics;
|
|
694
|
+
errors: ErrorsMetrics;
|
|
695
|
+
process_errors: ProcessErrorsMetrics;
|
|
696
|
+
/**
|
|
697
|
+
* Context tokens at each assistant message in this turn (in order).
|
|
698
|
+
* Lets backend reconstruct `context_tokens.buckets` at session level.
|
|
699
|
+
*/
|
|
700
|
+
context_tokens_samples: number[];
|
|
701
|
+
/** Last assistant message's context tokens in this turn. */
|
|
702
|
+
context_tokens_latest: number;
|
|
703
|
+
/** Max across assistant messages in this turn. */
|
|
704
|
+
context_tokens_peak: number;
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Per-step analytics record — one assistant message + the tool_results
|
|
708
|
+
* it received before the next assistant message in the same turn.
|
|
709
|
+
*
|
|
710
|
+
* Minimal subset of the group structure — `usage`, per-tool maps,
|
|
711
|
+
* `errors`, `process_errors`. `tool_meta` and `code_changes` are carried
|
|
712
|
+
* for reconstruction parity. `context_tokens` is a single optional scalar
|
|
713
|
+
* (no group wrapper, no buckets).
|
|
714
|
+
*/
|
|
715
|
+
export interface SessionTurnStepAnalytics {
|
|
716
|
+
session_id: string;
|
|
717
|
+
project_name: string;
|
|
718
|
+
user_email?: string;
|
|
719
|
+
schema_version: string;
|
|
720
|
+
transcript_source: TranscriptSource;
|
|
721
|
+
turn_id: string;
|
|
722
|
+
turn_index: number;
|
|
723
|
+
triggered_by: "user_msg" | "host_inject";
|
|
724
|
+
/** Deterministic — `sha256(turn_id|step_index|start_time)[:16]`. */
|
|
725
|
+
step_id: string;
|
|
726
|
+
/** 1-based ordinal within the parent turn (resets per turn). */
|
|
727
|
+
step_index: number;
|
|
728
|
+
start_time: string;
|
|
729
|
+
end_time: string;
|
|
730
|
+
/** 0..23 derived from start_time (local timezone). */
|
|
731
|
+
start_hour: number;
|
|
732
|
+
/** 0..23 derived from end_time. */
|
|
733
|
+
end_hour: number;
|
|
734
|
+
/** Wall-clock ms of the step. */
|
|
735
|
+
duration: number;
|
|
736
|
+
is_last_step: boolean;
|
|
737
|
+
turn_end_reason?: TurnEndReason;
|
|
738
|
+
turn_end_time?: string;
|
|
739
|
+
turn_duration?: number;
|
|
740
|
+
turn_category?: TurnCategory;
|
|
741
|
+
turn_was_one_shot?: boolean;
|
|
742
|
+
turn_was_interrupted?: boolean;
|
|
743
|
+
/** Always 1 — surfaced for reconstruction sums. */
|
|
744
|
+
assistant_messages: number;
|
|
745
|
+
tool_calls: number;
|
|
746
|
+
was_interrupted: boolean;
|
|
747
|
+
usage: UsageMetrics;
|
|
748
|
+
tools: Record<string, ToolUsage>;
|
|
749
|
+
mcp_servers: Record<string, ToolUsage>;
|
|
750
|
+
bash_binaries: Record<string, ToolUsage>;
|
|
751
|
+
skills: Record<string, ToolUsage>;
|
|
752
|
+
sub_agents: Record<string, ToolUsage>;
|
|
753
|
+
models: Record<string, ModelUsage>;
|
|
754
|
+
tool_meta: ToolMetaMetrics;
|
|
755
|
+
code_changes: CodeChangesMetrics;
|
|
756
|
+
errors: ErrorsMetrics;
|
|
757
|
+
process_errors: ProcessErrorsMetrics;
|
|
758
|
+
/** Context tokens at this step's assistant message (single sample). */
|
|
759
|
+
context_tokens?: number;
|
|
760
|
+
}
|
|
761
|
+
import { Event } from "../lib/event";
|
|
762
|
+
/**
|
|
763
|
+
* Wire event format. Extends the generic `Event` base (see
|
|
764
|
+
* `src/lib/event.ts`) so the collector envelope shape stays uniform
|
|
765
|
+
* across every event type IronBee emits.
|
|
766
|
+
*/
|
|
767
|
+
export interface SessionAnalyticsEvent extends Event {
|
|
768
|
+
type: "session_analytics";
|
|
769
|
+
analytics: SessionAnalytics;
|
|
770
|
+
}
|
|
771
|
+
export interface SessionTurnEvent extends Event {
|
|
772
|
+
type: "session_turn_analytics";
|
|
773
|
+
turn: SessionTurnAnalytics;
|
|
774
|
+
}
|
|
775
|
+
export interface SessionTurnStepEvent extends Event {
|
|
776
|
+
type: "session_turn_step_analytics";
|
|
777
|
+
step: SessionTurnStepAnalytics;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Per-API-request body. Mirrors the Java `APIRequestEvent` shape (one
|
|
781
|
+
* record per assistant message line in the transcript). Stored in
|
|
782
|
+
* `internal.pending_api_request_events` as the body-only struct; emit
|
|
783
|
+
* wraps with the {@link Event} envelope at drain time.
|
|
784
|
+
*
|
|
785
|
+
* `id` carries the transcript line's top-level `uuid` (verified 100%
|
|
786
|
+
* presence on real transcripts, both success and failure lines). At
|
|
787
|
+
* drain time it becomes the wire `Event.id` — deterministic across re-
|
|
788
|
+
* projections so backend dedup on `(session_id, id)` is safe even when
|
|
789
|
+
* `request_id` is null (failure case).
|
|
790
|
+
*
|
|
791
|
+
* `timestamp_ms` is the line's parsed ISO timestamp, used as the wire
|
|
792
|
+
* `Event.timestamp` at drain time (semantically: when the API call
|
|
793
|
+
* completed, not when the wire envelope was constructed).
|
|
794
|
+
*
|
|
795
|
+
* Other fields are nullable where the transcript doesn't carry them:
|
|
796
|
+
* - `request_id`: present on successful lines (top-level `requestId`);
|
|
797
|
+
* ALWAYS absent on `isApiErrorMessage:true` failure lines → null.
|
|
798
|
+
* - `error`: present on failure lines (top-level `error`); null on success.
|
|
799
|
+
* - `status_code`: rare even on failure (transcript-side; only seen on
|
|
800
|
+
* explicit HTTP errors like 429); always null on success.
|
|
801
|
+
* - `speed`: usually present on successful lines; null on failures
|
|
802
|
+
* (synthetic placeholder messages).
|
|
803
|
+
* - `duration`: NEVER populated from transcript — Claude Code's transcript
|
|
804
|
+
* does not carry per-API-call latency. Always null in transcript-derived
|
|
805
|
+
* events. (Java consumers writing their own APIRequestEvents fill this.)
|
|
806
|
+
*/
|
|
807
|
+
export interface APIRequestAnalytics {
|
|
808
|
+
id: string;
|
|
809
|
+
timestamp_ms: number;
|
|
810
|
+
request_id: string | null;
|
|
811
|
+
success: boolean;
|
|
812
|
+
error: string | null;
|
|
813
|
+
status_code: number | null;
|
|
814
|
+
model: string;
|
|
815
|
+
speed: string | null;
|
|
816
|
+
input_tokens: number;
|
|
817
|
+
output_tokens: number;
|
|
818
|
+
cache_read_tokens: number;
|
|
819
|
+
cache_creation_tokens: number;
|
|
820
|
+
cost_usd: number;
|
|
821
|
+
duration: number | null;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Wire event for a single API request. Flat field layout (no nested body
|
|
825
|
+
* object) — matches the Java `APIRequestEvent` shape exactly so the
|
|
826
|
+
* collector schema stays uniform across producers.
|
|
827
|
+
*/
|
|
828
|
+
export interface APIRequestEvent extends Event {
|
|
829
|
+
type: "api_request";
|
|
830
|
+
request_id: string | null;
|
|
831
|
+
success: boolean;
|
|
832
|
+
error: string | null;
|
|
833
|
+
status_code: number | null;
|
|
834
|
+
model: string;
|
|
835
|
+
speed: string | null;
|
|
836
|
+
input_tokens: number;
|
|
837
|
+
output_tokens: number;
|
|
838
|
+
cache_read_tokens: number;
|
|
839
|
+
cache_creation_tokens: number;
|
|
840
|
+
cost_usd: number;
|
|
841
|
+
duration: number | null;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Delta produced by projecting a single slice of new transcript bytes.
|
|
845
|
+
* Same shape as AccumulatedAnalytics with delta-local signals (never
|
|
846
|
+
* emitted on the wire; merge consumes them and discards).
|
|
847
|
+
*/
|
|
848
|
+
export interface DeltaAnalytics extends AccumulatedAnalytics {
|
|
849
|
+
/** True if the delta consumed at least one assistant message with usage data. */
|
|
850
|
+
has_assistant_with_usage: boolean;
|
|
851
|
+
/**
|
|
852
|
+
* Tool_uses still in-flight at end of this slice. Merge copies verbatim
|
|
853
|
+
* into `state.internal.pending_tool_uses`.
|
|
854
|
+
*/
|
|
855
|
+
closing_pending_tool_uses: Record<string, PendingToolUse>;
|
|
856
|
+
/** In-flight per-turn classifier state at slice end. `null` between turns. */
|
|
857
|
+
closing_current_turn: CurrentTurnState | null;
|
|
858
|
+
/** Turns that completed during this slice. */
|
|
859
|
+
completed_turns: SessionTurnAnalytics[];
|
|
860
|
+
/**
|
|
861
|
+
* Steps belonging to turns that completed during this slice — one entry
|
|
862
|
+
* per step, in `(turn_index, step_index)` order. Each turn's last step
|
|
863
|
+
* carries `is_last_step=true` + the turn-bookend fields.
|
|
864
|
+
*/
|
|
865
|
+
completed_steps: SessionTurnStepAnalytics[];
|
|
866
|
+
/**
|
|
867
|
+
* Per-API-request records observed in this slice — one per non-duplicate
|
|
868
|
+
* assistant message line (success + failure). Body-only structs; emit
|
|
869
|
+
* wraps with the {@link Event} envelope at drain time. Backend dedup
|
|
870
|
+
* key: `(session_id, request_id)` for successes; failures carry no
|
|
871
|
+
* `request_id` so dedup is best-effort (id+timestamp fingerprint).
|
|
872
|
+
*/
|
|
873
|
+
api_request_events: APIRequestAnalytics[];
|
|
874
|
+
}
|
|
875
|
+
//# sourceMappingURL=types.d.ts.map
|