diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index aab6699a95..56aaa2a95d 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -16723,7 +16723,7 @@ const docTemplate = `{ "overloaded", "rate_limit", "timeout", - "startup_timeout", + "stream_silence_timeout", "auth", "config", "usage_limit", @@ -16735,7 +16735,7 @@ const docTemplate = `{ "ChatErrorKindOverloaded", "ChatErrorKindRateLimit", "ChatErrorKindTimeout", - "ChatErrorKindStartupTimeout", + "ChatErrorKindStreamSilenceTimeout", "ChatErrorKindAuth", "ChatErrorKindConfig", "ChatErrorKindUsageLimit", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 865e9ac96d..606f7ae4ea 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -15049,7 +15049,7 @@ "overloaded", "rate_limit", "timeout", - "startup_timeout", + "stream_silence_timeout", "auth", "config", "usage_limit", @@ -15061,7 +15061,7 @@ "ChatErrorKindOverloaded", "ChatErrorKindRateLimit", "ChatErrorKindTimeout", - "ChatErrorKindStartupTimeout", + "ChatErrorKindStreamSilenceTimeout", "ChatErrorKindAuth", "ChatErrorKindConfig", "ChatErrorKindUsageLimit", diff --git a/coderd/x/chatd/chaterror/classify_test.go b/coderd/x/chatd/chaterror/classify_test.go index a35ee865b9..0d127d94e7 100644 --- a/coderd/x/chatd/chaterror/classify_test.go +++ b/coderd/x/chatd/chaterror/classify_test.go @@ -981,21 +981,21 @@ func TestClassify_StatusCodeBeatsHTTP2Transport(t *testing.T) { } } -func TestClassify_StartupTimeoutWrappedClassificationWins(t *testing.T) { +func TestClassify_StreamSilenceTimeoutWrappedClassificationWins(t *testing.T) { t.Parallel() wrapped := chaterror.WithClassification( xerrors.New("context canceled"), chaterror.ClassifiedError{ - Kind: codersdk.ChatErrorKindStartupTimeout, + Kind: codersdk.ChatErrorKindStreamSilenceTimeout, Provider: "openai", Retryable: true, }, ) require.Equal(t, chaterror.ClassifiedError{ - Message: "OpenAI did not start responding in time.", - Kind: codersdk.ChatErrorKindStartupTimeout, + Message: "OpenAI did not send response data in time.", + Kind: codersdk.ChatErrorKindStreamSilenceTimeout, Provider: "openai", Retryable: true, StatusCode: 0, diff --git a/coderd/x/chatd/chaterror/message.go b/coderd/x/chatd/chaterror/message.go index fef3ba78fa..3ebe6366e7 100644 --- a/coderd/x/chatd/chaterror/message.go +++ b/coderd/x/chatd/chaterror/message.go @@ -28,9 +28,9 @@ func terminalMessage(classified ClassifiedError) string { } return stringutil.Capitalize(fmt.Sprintf("%s is temporarily unavailable.", subject)) - case codersdk.ChatErrorKindStartupTimeout: + case codersdk.ChatErrorKindStreamSilenceTimeout: return stringutil.Capitalize(fmt.Sprintf( - "%s did not start responding in time.", subject, + "%s did not send response data in time.", subject, )) case codersdk.ChatErrorKindUsageLimit: @@ -89,9 +89,9 @@ func retryMessage(classified ClassifiedError) string { return stringutil.Capitalize(fmt.Sprintf("%s is rate limiting requests.", subject)) case codersdk.ChatErrorKindTimeout: return stringutil.Capitalize(fmt.Sprintf("%s is temporarily unavailable.", subject)) - case codersdk.ChatErrorKindStartupTimeout: + case codersdk.ChatErrorKindStreamSilenceTimeout: return stringutil.Capitalize(fmt.Sprintf( - "%s did not start responding in time.", subject, + "%s did not send response data in time.", subject, )) case codersdk.ChatErrorKindAuth: return fmt.Sprintf( diff --git a/coderd/x/chatd/chaterror/message_test.go b/coderd/x/chatd/chaterror/message_test.go index 94bf14bd13..ba00b595fb 100644 --- a/coderd/x/chatd/chaterror/message_test.go +++ b/coderd/x/chatd/chaterror/message_test.go @@ -11,7 +11,7 @@ import ( ) // TestTerminalMessage covers the per-provider "temporarily -// unavailable" copy, the startup-timeout copy, and the generic +// unavailable" copy, the stream-silence timeout copy, and the generic // fallback string for its intended (unclassified, non-retryable) // path. func TestTerminalMessage(t *testing.T) { @@ -54,18 +54,18 @@ func TestTerminalMessage(t *testing.T) { want: "The request timed out before it completed.", }, { - name: "StartupTimeout_Anthropic", - kind: codersdk.ChatErrorKindStartupTimeout, + name: "StreamSilenceTimeout_Anthropic", + kind: codersdk.ChatErrorKindStreamSilenceTimeout, provider: "anthropic", retryable: true, - want: "Anthropic did not start responding in time.", + want: "Anthropic did not send response data in time.", }, { - name: "StartupTimeout_OpenAI", - kind: codersdk.ChatErrorKindStartupTimeout, + name: "StreamSilenceTimeout_OpenAI", + kind: codersdk.ChatErrorKindStreamSilenceTimeout, provider: "openai", retryable: true, - want: "OpenAI did not start responding in time.", + want: "OpenAI did not send response data in time.", }, { // Generic fallback reserved for genuinely diff --git a/coderd/x/chatd/chatloop/chatloop.go b/coderd/x/chatd/chatloop/chatloop.go index 7a81dc4d6e..efe67083e2 100644 --- a/coderd/x/chatd/chatloop/chatloop.go +++ b/coderd/x/chatd/chatloop/chatloop.go @@ -867,7 +867,7 @@ func classifyStreamSilenceTimeout( err = errStreamSilenceTimeout } return chaterror.WithClassification(err, chaterror.ClassifiedError{ - Kind: codersdk.ChatErrorKindStartupTimeout, + Kind: codersdk.ChatErrorKindStreamSilenceTimeout, Provider: provider, Retryable: true, }) diff --git a/coderd/x/chatd/chatloop/chatloop_run_internal_test.go b/coderd/x/chatd/chatloop/chatloop_run_internal_test.go index 2ba435d9ca..9769f10d01 100644 --- a/coderd/x/chatd/chatloop/chatloop_run_internal_test.go +++ b/coderd/x/chatd/chatloop/chatloop_run_internal_test.go @@ -700,12 +700,12 @@ func TestRun_RetriesSilenceTimeoutWhileOpeningStream(t *testing.T) { require.NoError(t, awaitRunResult(ctx, t, done)) require.Equal(t, 2, attempts) require.Len(t, retries, 1) - require.Equal(t, codersdk.ChatErrorKindStartupTimeout, retries[0].Kind) + require.Equal(t, codersdk.ChatErrorKindStreamSilenceTimeout, retries[0].Kind) require.True(t, retries[0].Retryable) require.Equal(t, "openai", retries[0].Provider) require.Equal( t, - "OpenAI did not start responding in time.", + "OpenAI did not send response data in time.", retries[0].Message, ) select { @@ -930,12 +930,12 @@ func TestRun_RetriesSilenceTimeoutBeforeFirstPart(t *testing.T) { require.NoError(t, awaitRunResult(ctx, t, done)) require.Equal(t, 2, attempts) require.Len(t, retries, 1) - require.Equal(t, codersdk.ChatErrorKindStartupTimeout, retries[0].Kind) + require.Equal(t, codersdk.ChatErrorKindStreamSilenceTimeout, retries[0].Kind) require.True(t, retries[0].Retryable) require.Equal(t, "openai", retries[0].Provider) require.Equal( t, - "OpenAI did not start responding in time.", + "OpenAI did not send response data in time.", retries[0].Message, ) select { @@ -1161,7 +1161,7 @@ func TestRun_RetriesSilenceTimeoutBetweenParts(t *testing.T) { require.NoError(t, awaitRunResult(ctx, t, done)) require.Equal(t, 2, attempts) require.Len(t, retries, 1) - require.Equal(t, codersdk.ChatErrorKindStartupTimeout, retries[0].Kind) + require.Equal(t, codersdk.ChatErrorKindStreamSilenceTimeout, retries[0].Kind) require.True(t, retries[0].Retryable) require.Equal(t, "openai", retries[0].Provider) select { @@ -1278,12 +1278,12 @@ func TestRun_RetriesSilenceTimeoutWhenStreamStaysSilent(t *testing.T) { require.NoError(t, awaitRunResult(ctx, t, done)) require.Equal(t, 2, attempts) require.Len(t, retries, 1) - require.Equal(t, codersdk.ChatErrorKindStartupTimeout, retries[0].Kind) + require.Equal(t, codersdk.ChatErrorKindStreamSilenceTimeout, retries[0].Kind) require.True(t, retries[0].Retryable) require.Equal(t, "openai", retries[0].Provider) require.Equal( t, - "OpenAI did not start responding in time.", + "OpenAI did not send response data in time.", retries[0].Message, ) select { diff --git a/coderd/x/chatd/chatloop/metrics_test.go b/coderd/x/chatd/chatloop/metrics_test.go index adc23ef291..40eabf99ca 100644 --- a/coderd/x/chatd/chatloop/metrics_test.go +++ b/coderd/x/chatd/chatloop/metrics_test.go @@ -293,7 +293,7 @@ func TestRecordStreamRetry(t *testing.T) { {name: "overloaded", kind: codersdk.ChatErrorKindOverloaded}, {name: "rate_limit", kind: codersdk.ChatErrorKindRateLimit}, {name: "timeout", kind: codersdk.ChatErrorKindTimeout}, - {name: "startup_timeout", kind: codersdk.ChatErrorKindStartupTimeout}, + {name: "stream_silence_timeout", kind: codersdk.ChatErrorKindStreamSilenceTimeout}, {name: "auth", kind: codersdk.ChatErrorKindAuth}, {name: "config", kind: codersdk.ChatErrorKindConfig}, {name: "missing_key", kind: codersdk.ChatErrorKindMissingKey}, diff --git a/codersdk/chats.go b/codersdk/chats.go index bcf235f590..8770368a3d 100644 --- a/codersdk/chats.go +++ b/codersdk/chats.go @@ -1525,16 +1525,16 @@ type ChatStreamStatus struct { type ChatErrorKind string const ( - ChatErrorKindGeneric ChatErrorKind = "generic" - ChatErrorKindOverloaded ChatErrorKind = "overloaded" - ChatErrorKindRateLimit ChatErrorKind = "rate_limit" - ChatErrorKindTimeout ChatErrorKind = "timeout" - ChatErrorKindStartupTimeout ChatErrorKind = "startup_timeout" - ChatErrorKindAuth ChatErrorKind = "auth" - ChatErrorKindConfig ChatErrorKind = "config" - ChatErrorKindUsageLimit ChatErrorKind = "usage_limit" - ChatErrorKindMissingKey ChatErrorKind = "missing_key" - ChatErrorKindProviderDisabled ChatErrorKind = "provider_disabled" + ChatErrorKindGeneric ChatErrorKind = "generic" + ChatErrorKindOverloaded ChatErrorKind = "overloaded" + ChatErrorKindRateLimit ChatErrorKind = "rate_limit" + ChatErrorKindTimeout ChatErrorKind = "timeout" + ChatErrorKindStreamSilenceTimeout ChatErrorKind = "stream_silence_timeout" + ChatErrorKindAuth ChatErrorKind = "auth" + ChatErrorKindConfig ChatErrorKind = "config" + ChatErrorKindUsageLimit ChatErrorKind = "usage_limit" + ChatErrorKindMissingKey ChatErrorKind = "missing_key" + ChatErrorKindProviderDisabled ChatErrorKind = "provider_disabled" ) // AllChatErrorKinds contains every ChatErrorKind value. @@ -1544,7 +1544,7 @@ var AllChatErrorKinds = []ChatErrorKind{ ChatErrorKindOverloaded, ChatErrorKindRateLimit, ChatErrorKindTimeout, - ChatErrorKindStartupTimeout, + ChatErrorKindStreamSilenceTimeout, ChatErrorKindAuth, ChatErrorKindConfig, ChatErrorKindUsageLimit, diff --git a/docs/reference/api/chats.md b/docs/reference/api/chats.md index f475d8482d..e11363788f 100644 --- a/docs/reference/api/chats.md +++ b/docs/reference/api/chats.md @@ -292,13 +292,13 @@ Status Code **200** #### Enumerated Values -| Property | Value(s) | -|---------------|------------------------------------------------------------------------------------------------------------------------------------------| -| `client_type` | `api`, `ui` | -| `kind` | `auth`, `config`, `generic`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `startup_timeout`, `timeout`, `usage_limit` | -| `type` | `context-file`, `file`, `file-reference`, `reasoning`, `skill`, `source`, `text`, `tool-call`, `tool-result` | -| `plan_mode` | `plan` | -| `status` | `completed`, `error`, `paused`, `pending`, `requires_action`, `running`, `waiting` | +| Property | Value(s) | +|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `client_type` | `api`, `ui` | +| `kind` | `auth`, `config`, `generic`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `stream_silence_timeout`, `timeout`, `usage_limit` | +| `type` | `context-file`, `file`, `file-reference`, `reasoning`, `skill`, `source`, `text`, `tool-call`, `tool-result` | +| `plan_mode` | `plan` | +| `status` | `completed`, `error`, `paused`, `pending`, `requires_action`, `running`, `waiting` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 55eac2c4f2..36ed488d48 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -2703,9 +2703,9 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in #### Enumerated Values -| Value(s) | -|------------------------------------------------------------------------------------------------------------------------------------------| -| `auth`, `config`, `generic`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `startup_timeout`, `timeout`, `usage_limit` | +| Value(s) | +|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `auth`, `config`, `generic`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `stream_silence_timeout`, `timeout`, `usage_limit` | ## codersdk.ChatFileMetadata diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 807c63f400..2f3f46e679 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1992,7 +1992,7 @@ export type ChatErrorKind = | "overloaded" | "provider_disabled" | "rate_limit" - | "startup_timeout" + | "stream_silence_timeout" | "timeout" | "usage_limit"; @@ -2004,7 +2004,7 @@ export const ChatErrorKinds: ChatErrorKind[] = [ "overloaded", "provider_disabled", "rate_limit", - "startup_timeout", + "stream_silence_timeout", "timeout", "usage_limit", ]; diff --git a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx index 514e35fb5a..10d0e7af97 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/LiveStreamTail.stories.tsx @@ -257,14 +257,14 @@ export const RetryingTimeoutAnthropic: Story = { }, }; -/** Terminal startup timeouts get a specific heading without provider metadata. */ -export const TerminalStartupTimeoutError: Story = { +/** Terminal stream-silence timeouts get a specific heading without provider metadata. */ +export const TerminalStreamSilenceTimeoutError: Story = { args: { ...defaultArgs, liveStatus: buildLiveStatus({ persistedError: { - kind: "startup_timeout", - message: "Anthropic did not start responding in time.", + kind: "stream_silence_timeout", + message: "Anthropic did not send response data in time.", provider: "anthropic", retryable: true, }, @@ -273,10 +273,10 @@ export const TerminalStartupTimeoutError: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect( - canvas.getByRole("heading", { name: /startup timed out/i }), + canvas.getByRole("heading", { name: /response stalled/i }), ).toBeVisible(); expect( - canvas.getByText(/anthropic did not start responding in time./i), + canvas.getByText(/anthropic did not send response data in time./i), ).toBeVisible(); expect(canvas.queryByText(/please try again/i)).not.toBeInTheDocument(); expect(canvas.queryByText(/^retryable$/i)).not.toBeInTheDocument(); diff --git a/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx b/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx index 11546ed4db..9fd03871d8 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx +++ b/site/src/pages/AgentsPage/components/ChatConversation/StreamingOutput.stories.tsx @@ -225,15 +225,15 @@ export const RetryTimeout: Story = { }, }; -/** Startup timeouts explain the first-token delay before retrying. */ -export const RetryStartupTimeout: Story = { +/** Stream-silence timeouts explain the first-token delay before retrying. */ +export const RetryStreamSilenceTimeout: Story = { args: { streamState: null, streamTools: [], liveStatus: buildLiveStatus({ retryState: buildRetryState({ - kind: "startup_timeout", - error: "Anthropic did not start responding in time.", + kind: "stream_silence_timeout", + error: "Anthropic did not send response data in time.", }), isAwaitingFirstStreamChunk: true, }), @@ -241,10 +241,10 @@ export const RetryStartupTimeout: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); expect( - canvas.getByRole("heading", { name: /startup timed out/i }), + canvas.getByRole("heading", { name: /response stalled/i }), ).toBeVisible(); expect( - canvas.getByText(/anthropic did not start responding in time/i), + canvas.getByText(/anthropic did not send response data in time/i), ).toBeVisible(); expect(canvas.queryByText(/please try again/i)).not.toBeInTheDocument(); expect(canvas.queryByText(/provider anthropic/i)).not.toBeInTheDocument(); diff --git a/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts b/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts index d9ea6f6e59..9389b6d11c 100644 --- a/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts +++ b/site/src/pages/AgentsPage/components/ChatConversation/chatStatusHelpers.ts @@ -34,8 +34,8 @@ export const getErrorTitle = ( return "Rate limited"; case "timeout": return "Request timed out"; - case "startup_timeout": - return "Startup timed out"; + case "stream_silence_timeout": + return "Response stalled"; case "auth": return "Authentication failed"; case "config":