Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions coderd/chatd/chatd.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ func (p *Server) CreateChat(ctx context.Context, opts CreateOptions) (database.C
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
})
if err != nil {
return xerrors.Errorf("insert system message: %w", err)
Expand Down Expand Up @@ -524,6 +525,7 @@ func (p *Server) CreateChat(ctx context.Context, opts CreateOptions) (database.C
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
})
if err != nil {
return xerrors.Errorf("insert workspace awareness message: %w", err)
Expand Down Expand Up @@ -552,6 +554,7 @@ func (p *Server) CreateChat(ctx context.Context, opts CreateOptions) (database.C
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
Compressed: sql.NullBool{},
})
if err != nil {
Expand Down Expand Up @@ -1170,6 +1173,7 @@ func insertUserMessageAndSetPending(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
Compressed: sql.NullBool{},
})
if err != nil {
Expand Down Expand Up @@ -2147,6 +2151,7 @@ func (p *Server) tryAutoPromoteQueuedMessage(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
Compressed: sql.NullBool{},
})
if err != nil {
Expand Down Expand Up @@ -2709,6 +2714,10 @@ func (p *Server) runChat(
ContextLimit: step.ContextLimit,
Compressed: sql.NullBool{},
TotalCostMicros: usageNullInt64Ptr(totalCostMicros),
RuntimeMs: sql.NullInt64{
Int64: step.Runtime.Milliseconds(),
Valid: step.Runtime > 0,
},
})
if insertErr != nil {
return xerrors.Errorf("insert assistant message: %w", insertErr)
Expand All @@ -2733,6 +2742,7 @@ func (p *Server) runChat(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
Compressed: sql.NullBool{},
})
if insertErr != nil {
Expand Down Expand Up @@ -3117,6 +3127,7 @@ func (p *Server) persistChatContextSummary(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
})
if txErr != nil {
return xerrors.Errorf("insert hidden summary message: %w", txErr)
Expand All @@ -3142,6 +3153,7 @@ func (p *Server) persistChatContextSummary(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
})
if txErr != nil {
return xerrors.Errorf("insert summary tool call message: %w", txErr)
Expand All @@ -3168,6 +3180,7 @@ func (p *Server) persistChatContextSummary(
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
TotalCostMicros: sql.NullInt64{},
RuntimeMs: sql.NullInt64{},
})
if txErr != nil {
return xerrors.Errorf("insert summary tool result message: %w", txErr)
Expand Down
7 changes: 7 additions & 0 deletions coderd/chatd/chatd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ func TestCreateChatRejectsWhenUsageLimitReached(t *testing.T) {
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{Int64: 100, Valid: true},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down Expand Up @@ -824,6 +825,7 @@ func TestPromoteQueuedAllowsAlreadyQueuedMessageWhenUsageLimitReached(t *testing
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{Int64: 100, Valid: true},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down Expand Up @@ -1012,6 +1014,7 @@ func TestInterruptAutoPromotionIgnoresLaterUsageLimitIncrease(t *testing.T) {
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{Int64: 100, Valid: true},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down Expand Up @@ -1107,6 +1110,7 @@ func TestEditMessageRejectsWhenUsageLimitReached(t *testing.T) {
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
TotalCostMicros: sql.NullInt64{Int64: 100, Valid: true},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down Expand Up @@ -1196,6 +1200,7 @@ func TestEditMessageRejectsNonUserMessage(t *testing.T) {
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down Expand Up @@ -1544,6 +1549,7 @@ func TestSubscribeAfterMessageID(t *testing.T) {
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand All @@ -1567,6 +1573,7 @@ func TestSubscribeAfterMessageID(t *testing.T) {
CacheReadTokens: sql.NullInt64{},
ContextLimit: sql.NullInt64{},
Compressed: sql.NullBool{},
RuntimeMs: sql.NullInt64{},
})
require.NoError(t, err)

Expand Down
7 changes: 7 additions & 0 deletions coderd/chatd/chatloop/chatloop.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ type PersistedStep struct {
Content []fantasy.Content
Usage fantasy.Usage
ContextLimit sql.NullInt64
// Runtime is the wall-clock duration of this step,
// covering LLM streaming, tool execution, and retries.
// Zero indicates the duration was not measured (e.g.
// interrupted steps).
Runtime time.Duration
}

// RunOptions configures a single streaming chat loop run.
Expand Down Expand Up @@ -260,6 +265,7 @@ func Run(ctx context.Context, opts RunOptions) error {

for step := 0; totalSteps < opts.MaxSteps; step++ {
totalSteps++
stepStart := time.Now()
// Copy messages so that provider-specific caching
// mutations don't leak back to the caller's slice.
// copy copies Message structs by value, so field
Expand Down Expand Up @@ -365,6 +371,7 @@ func Run(ctx context.Context, opts RunOptions) error {
Content: result.content,
Usage: result.usage,
ContextLimit: contextLimit,
Runtime: time.Since(stepStart),
}); err != nil {
if errors.Is(err, ErrInterrupted) {
persistInterruptedStep(ctx, opts, &result)
Expand Down
3 changes: 3 additions & 0 deletions coderd/chatd/chatloop/chatloop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"sync"
"testing"
"time"

"charm.land/fantasy"
fantasyanthropic "charm.land/fantasy/providers/anthropic"
Expand Down Expand Up @@ -64,6 +65,8 @@ func TestRun_ActiveToolsPrepareBehavior(t *testing.T) {
require.Equal(t, 1, persistStepCalls)
require.True(t, persistedStep.ContextLimit.Valid)
require.Equal(t, int64(4096), persistedStep.ContextLimit.Int64)
require.Greater(t, persistedStep.Runtime, time.Duration(0),
"step runtime should be positive")

require.NotEmpty(t, capturedCall.Prompt)
require.False(t, containsPromptSentinel(capturedCall.Prompt))
Expand Down
3 changes: 2 additions & 1 deletion coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE chat_messages DROP COLUMN runtime_ms;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE chat_messages ADD COLUMN runtime_ms bigint;
1 change: 1 addition & 0 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 20 additions & 9 deletions coderd/database/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions coderd/database/queries/chats.sql
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ INSERT INTO chat_messages (
cache_read_tokens,
context_limit,
compressed,
total_cost_micros
total_cost_micros,
runtime_ms
) VALUES (
@chat_id::uuid,
sqlc.narg('created_by')::uuid,
Expand All @@ -222,7 +223,8 @@ INSERT INTO chat_messages (
sqlc.narg('cache_read_tokens')::bigint,
sqlc.narg('context_limit')::bigint,
COALESCE(sqlc.narg('compressed')::boolean, FALSE),
sqlc.narg('total_cost_micros')::bigint
sqlc.narg('total_cost_micros')::bigint,
sqlc.narg('runtime_ms')::bigint
)
RETURNING
*;
Expand Down
Loading