feat(tenant): bill AI points by output characters
Previously AI point cost was computed from request (input) characters at reservation time. Switch to reserving a single point up front and settling the final cost from the generated output length on completion. - Reserve 1 point (or FixedPoints) instead of pricing on request chars - On completion, recompute points from output chars vs base chars, update the reservation amounts, and post a ledger delta for the top-up/refund; invalidate the workspace quota summary cache - MarkCompleted now persists final request_chars/base_chars/points - Use ceil division in calculateAIPointCost so an exact base boundary charges one point instead of rolling over - Thread output text through all CompleteAIPoints callers (article selection, KOL assist, question expansion, template assist, compliance judge) and return the settled reservation - Add unit tests plus an integration test gated on TEST_DATABASE_URL - Update the user manual: billing is by output characters Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -93,7 +93,7 @@ func (w *KolAssistWorker) Process(ctx context.Context, job tenantapp.KolAssistJo
|
||||
}
|
||||
switch task.Status {
|
||||
case "completed":
|
||||
w.completeAIPoints(ctx, job, "")
|
||||
w.completeAIPoints(ctx, job, "", string(task.ResultJSON))
|
||||
return nil
|
||||
case "failed":
|
||||
errorMessage := "kol assist task failed"
|
||||
@@ -262,14 +262,14 @@ func (w *KolAssistWorker) processTask(ctx context.Context, job tenantapp.KolAssi
|
||||
if err := w.repo.MarkCompleted(ctx, job.TenantID, job.TaskID, resultJSON); err != nil {
|
||||
return fmt.Errorf("mark kol assist completed: %w", err)
|
||||
}
|
||||
w.completeAIPoints(ctx, job, result.Model)
|
||||
w.completeAIPoints(ctx, job, result.Model, result.Content)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *KolAssistWorker) completeAIPoints(ctx context.Context, job tenantapp.KolAssistJob, model string) {
|
||||
func (w *KolAssistWorker) completeAIPoints(ctx context.Context, job tenantapp.KolAssistJob, model string, meteredOutputText string) {
|
||||
resourceType := "kol_assist_task"
|
||||
resourceUID := job.TaskID
|
||||
if err := tenantapp.CompletePendingAIPointsByResource(ctx, w.pool, job.TenantID, resourceType, nil, &resourceUID, model); err != nil && w.logger != nil {
|
||||
if _, err := tenantapp.CompletePendingAIPointsByResource(ctx, w.pool, w.cache, job.TenantID, resourceType, nil, &resourceUID, model, meteredOutputText); err != nil && w.logger != nil {
|
||||
w.logger.Warn("kol assist ai points confirmation failed",
|
||||
zap.Error(err),
|
||||
zap.String("task_id", job.TaskID),
|
||||
|
||||
Reference in New Issue
Block a user