You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(billing+identity): usage/quota APIs, per-call token log, user identity cleanup
Billing:
- GET /v1/usage, PUT/GET/DELETE /v1/quota APIs for upstream SaaS billing
- token_usage_log table: append-only per-LLM-call audit trail (vs daily UPSERT)
- Quota enforcement in agent loop entry (HandleMessage + HandleMessageStream)
- session_messages gains provider/model columns for per-message LLM attribution
Identity:
- users.owner_user_id: explicit parent link replacing overloaded apikey_id
- role=channel_user for IM-originated users (was indistinguishable from app_user)
- EnsureChatter separates channel user creation from API app_user provisioning
- resolveChatter scoped to channel owner ID (fixes cross-tenant chatter collision
when multiple app_users share the same platform API key)
- extID drops accountID so chatter identity survives bot reconnection and is
shared across agents under the same owner
- Migration backfills owner_user_id, fixes roles, normalizes username/email,
cleans up apikey_id
Fixes:
- web_fetch UTF-8 truncation: back up to valid rune boundary before cutting
- channel_user blocked from web login alongside app_user
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
returnfmt.Sprintf("Sorry, your usage quota has been exceeded (used %d/%d tokens, %d/%d requests). Your quota resets on %s. Please contact your service provider to upgrade your plan.",
673
+
status.TokensUsed, status.MonthlyTokenLimit,
674
+
status.RequestsUsed, status.MonthlyRequestLimit,
675
+
status.ResetsAt)
676
+
}
677
+
653
678
// meterTokens records one Chat call's token counts. Safe to call with
654
679
// zero usage (still bumps request_count). Errors are logged but never
655
680
// propagated — metering must not break the chat path. The agent's
656
681
// configured model string carries the provider prefix when a per-agent
657
682
// override is set; we split it so the meter stores provider and model
658
683
// in their own columns rather than mashing them together.
659
-
func (a*Agent) meterTokens(ctx context.Context, sessionKeystring, u provider.Usage) {
684
+
// durationMs is the wall-clock time of the LLM call; pass 0 when not
685
+
// measured (the daily bucket doesn't use it, only the log table).
686
+
func (a*Agent) meterTokens(ctx context.Context, sessionKeystring, u provider.Usage, durationMsint64) {
content=fmt.Sprintf("I've reached the maximum number of tool iterations (%d) and couldn't synthesize a final response. The work above represents what I gathered before hitting the limit.", a.maxToolIterations)
0 commit comments