Pulse/internal
rcourtman a0b3bc7ed3 Record user-chat token usage to the cost ledger
chat.Service.ExecuteStream was a long-standing cost-ledger gap: the
agentic loop accumulated token counts via stream callbacks (see
GetTotalInputTokens / GetTotalOutputTokens in agentic_control.go)
and surfaced them in the SSE done envelope to the frontend, but
nothing on the server side recorded a cost.UsageEvent. Patrol,
discovery, QuickAnalysis, and the report narrators all record; only
chat — the bulk of AI token spend — did not. The operator's AI
usage dashboard was therefore understating cost dramatically.

Found while extending the cost-recording mindset across subpackages
after fixing QuickAnalysis (08491b9f4). Initially spawned as a
separate task but the right shape and scope became clear, so landing
it directly here.

Pipeline:
- Service.CostStore() exposes the per-tenant cost store handle.
- chat.Config gains optional CostStore *cost.Store field, threaded
  into chat.Service.costStore at NewService time.
- chat.Service.recordChatTurnCost records a UsageEvent with
  UseCase="chat" after every loop.ExecuteWithTools return (success
  OR error — operator was billed regardless of clean response).
  Skips when costStore is nil or zero tokens accumulated.
- ai_handler.go's two chatCfg construction sites populate CostStore
  via h.resolveCostStore(ctx).
- router wires the resolver to AISettingsHandler.GetAIService(ctx).CostStore()
  with no Enabled gate — even brief chat usage while AI was being
  configured should appear in the dashboard.

ExecutePatrolStream is deliberately not changed. It creates a
separate tempLoop and its caller (patrol_ai.go) records cost via
its own helper at line 887. Recording in ExecuteStream only avoids
double-counting on the patrol-via-chat path.

Tests in chat/cost_recording_test.go cover: recording when store
configured, no-op when store nil, no-op on zero tokens (early
failures), graceful handling of model strings missing the
provider prefix.
2026-05-10 23:15:53 +01:00
..
actionplanner Fail closed dry-run action execution 2026-05-05 09:22:04 +01:00
agentexec Align Patrol prober with agent command policy 2026-05-01 20:28:11 +01:00
agenttls Add fingerprint-pinned TLS mode for unified agent 2026-04-22 01:36:46 +01:00
agentupdate Harden unified agent runtime and installer 2026-04-23 23:04:18 +01:00
ai Record user-chat token usage to the cost ledger 2026-05-10 23:15:53 +01:00
alerts Skip agent-sourced alerts in node-presence cleanup 2026-05-10 23:12:31 +01:00
api Record user-chat token usage to the cost ledger 2026-05-10 23:15:53 +01:00
bootstrap feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
cloudcp Remove monitored-system volume caps 2026-05-05 12:59:59 +01:00
config Keep direct DeepSeek Patrol models selectable 2026-05-08 11:57:04 +01:00
crypto Harden secure local key file handling 2026-04-22 05:13:01 +01:00
deploy Remove monitored-system volume caps 2026-05-05 12:59:59 +01:00
discovery feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
dockeragent Allow insecure dev HTTP agent runtime URLs 2026-04-23 13:48:54 +01:00
hostagent Fix PVE version detection on agent hosts 2026-05-08 15:30:08 +01:00
hosted Canonicalize legacy hosted signup principals 2026-05-04 22:52:00 +01:00
hostmetrics feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
kubernetesagent Allow insecure dev HTTP agent runtime URLs 2026-04-23 13:48:54 +01:00
license Remove monitored-system volume caps 2026-05-05 12:59:59 +01:00
logging Stabilize backend race tests for v6 RC publish 2026-04-11 22:46:34 +01:00
metrics feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
mock Drive agent host profiles from platform manifest 2026-05-07 23:42:15 +01:00
mockmode Gate release mock fixtures behind demo entitlement 2026-04-10 12:33:57 +01:00
mockmodel Sharpen mock summary isolation and role shaping 2026-04-01 12:21:36 +01:00
mockruntime Gate release mock fixtures behind demo entitlement 2026-04-10 12:33:57 +01:00
models Fix platform identity source contracts 2026-05-08 14:54:08 +01:00
monitoring Mark failed PBS poll as failure and lock down with regression tests 2026-05-08 19:53:03 +01:00
notifications Fix notification queue race test 2026-05-01 22:26:01 +01:00
platformsupport Show platform versions in system badges 2026-05-08 15:07:09 +01:00
recovery fix(recovery): preserve canonical pbs guest continuity 2026-03-29 11:38:35 +01:00
relay Fix RC3 backend release blockers 2026-05-01 21:36:28 +01:00
remoteconfig Allow insecure dev HTTP agent runtime URLs 2026-04-23 13:48:54 +01:00
repoctl Retire product upgrade metrics runtime 2026-04-30 12:24:22 +01:00
securityutil Allow insecure dev HTTP agent runtime URLs 2026-04-23 13:48:54 +01:00
sensors feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
servicediscovery Fix silent fingerprint loss for LXC and VMs 2026-05-10 20:31:46 +01:00
ssh/knownhosts feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
storagehealth Fix Unraid storage health explanations 2026-05-08 12:18:09 +01:00
system feat: Pulse v6 release 2026-03-18 16:06:30 +00:00
telemetry Canonicalize usage-data telemetry reporting 2026-04-14 11:05:10 +01:00
testutil Stabilize rc1 mock mode and metrics history 2026-04-11 16:47:37 +01:00
truenas Curate demo-facing mock data across platform views 2026-03-31 18:05:55 +01:00
unifiedresources Merge duplicate map keys in TestActionExecutionContractStaysAPIOwned 2026-05-09 15:08:51 +01:00
updates Verify SSHSIG on in-app update artifacts 2026-05-09 23:14:07 +01:00
updatesignature Fix v6 demo release signing key deployment 2026-05-05 21:40:14 +01:00
utils Canonicalize ago duration formatting 2026-03-19 03:07:56 +00:00
vmware Curate demo-facing mock data across platform views 2026-03-31 18:05:55 +01:00
websocket Fix RC3 backend release blockers 2026-05-01 21:36:28 +01:00