-
Notifications
You must be signed in to change notification settings - Fork 1.3k
refactor(coderd/x/chatd): clean generation preparer setup #26511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,6 +125,11 @@ const ( | |
| // It is intentionally generous relative to the advisor's concise | ||
| // guidance remit so short plans are not truncated mid-reasoning. | ||
| defaultAdvisorMaxOutputTokens = 16384 | ||
|
|
||
| // defaultChatMaxOutputTokens caps a model response when the model config | ||
| // does not set a provider-specific output limit. This keeps unbounded | ||
| // requests from accidentally exhausting large-context models. | ||
| defaultChatMaxOutputTokens int64 = 32_000 | ||
|
Comment on lines
+129
to
+132
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit [CRF-3] The adjacent This constant says what it prevents but not why 32,000. Is it half a 64k context window? A provider default? Empirically determined? The next person tuning this value has no anchor. (Leorio)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit [CRF-4] Commit subject "clean generation preparer setup" is vague. "clean" doesn't convey what changed. Something like "centralize preparer error cleanup via named return" or "simplify preparer setup: extract token constant, defer cleanup" tells (Leorio)
|
||
| ) | ||
|
|
||
| var ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ import ( | |
| func (server *Server) prepareGeneration( | ||
| ctx context.Context, | ||
| input generationPrepareInput, | ||
| ) (generationPrepared, error) { | ||
| ) (prepared generationPrepared, err error) { | ||
| chat := input.Chat | ||
| logger := server.logger.With( | ||
| slog.F("chat_id", chat.ID), | ||
|
|
@@ -85,7 +85,6 @@ func (server *Server) prepareGeneration( | |
| modelOpts = modelBuildOptionsFromMessages(promptRows) | ||
| ctx = withActiveTurnAPIKeyID(ctx, modelOpts) | ||
|
|
||
| var err error | ||
| model, modelConfig, providerKeys, modelRoute, debugEnabled, resolvedProvider, debugModel, err = server.resolveChatModel(ctx, chat, modelOpts) | ||
| if err != nil { | ||
| return generationPrepared{}, err | ||
|
|
@@ -97,7 +96,7 @@ func (server *Server) prepareGeneration( | |
| } | ||
|
|
||
| if callConfig.MaxOutputTokens == nil { | ||
| maxOutputTokens := int64(32_000) | ||
| maxOutputTokens := defaultChatMaxOutputTokens | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit [CRF-2] Go 1.26 supports maxOutputTokens := defaultChatMaxOutputTokens
callConfig.MaxOutputTokens = &maxOutputTokenscan be: callConfig.MaxOutputTokens = new(defaultChatMaxOutputTokens)Verified: (Ging-Go)
|
||
| callConfig.MaxOutputTokens = &maxOutputTokens | ||
| } | ||
|
|
||
|
|
@@ -121,8 +120,7 @@ func (server *Server) prepareGeneration( | |
|
|
||
| var advisorRuntime *chatadvisor.Runtime | ||
| if advisorCfg.Enabled && isRootChat && !isPlanModeTurn && !isExploreSubagent { | ||
| var advisorErr error | ||
| advisorRuntime, advisorErr = server.newAdvisorRuntime( | ||
| advisorRuntime, err = server.newAdvisorRuntime( | ||
| ctx, | ||
| chat, | ||
| advisorCfg, | ||
|
|
@@ -132,8 +130,8 @@ func (server *Server) prepareGeneration( | |
| modelOpts, | ||
| logger, | ||
| ) | ||
| if advisorErr != nil { | ||
| return generationPrepared{}, advisorErr | ||
| if err != nil { | ||
| return generationPrepared{}, err | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -157,9 +155,18 @@ func (server *Server) prepareGeneration( | |
| currentChat: ¤tChat, | ||
| loadChatSnapshot: loadChatSnapshot, | ||
| } | ||
| var mcpCleanup func() | ||
| cleanup := func() { | ||
| if mcpCleanup != nil { | ||
| mcpCleanup() | ||
| } | ||
| workspaceCtx.close() | ||
| } | ||
| defer func() { | ||
| if err != nil { | ||
| cleanup() | ||
| } | ||
| }() | ||
|
Comment on lines
+158
to
+169
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note [CRF-5] Five reviewers independently noticed this restructuring incidentally fixes a latent MCP connection leak. In the old code, The new code captures (Hisoka, Pariston, Meruem, Mafuuu, Kite)
|
||
|
|
||
| planPathFn := func(ctx context.Context) (string, string, error) { | ||
| conn, err := workspaceCtx.getWorkspaceConn(ctx) | ||
|
|
@@ -208,7 +215,6 @@ func (server *Server) prepareGeneration( | |
| prompt []fantasy.Message | ||
| instruction string | ||
| mcpTools []fantasy.AgentTool | ||
| mcpCleanup func() | ||
| workspaceMCPTools []fantasy.AgentTool | ||
| workspaceSkills []chattool.SkillMeta | ||
| personalSkills []skillspkg.Skill | ||
|
|
@@ -273,18 +279,9 @@ func (server *Server) prepareGeneration( | |
| }) | ||
| } | ||
| if err := g2.Wait(); err != nil { | ||
| cleanup() | ||
| return generationPrepared{}, err | ||
| } | ||
|
|
||
| if mcpCleanup != nil { | ||
| previousCleanup := cleanup | ||
| cleanup = func() { | ||
| mcpCleanup() | ||
| previousCleanup() | ||
| } | ||
| } | ||
|
|
||
| prompt, sanitizeStats := chatsanitize.SanitizeAnthropicProviderToolHistory(model.Provider(), prompt) | ||
| chatsanitize.LogAnthropicProviderToolSanitization( | ||
| ctx, | ||
|
|
@@ -427,7 +424,6 @@ func (server *Server) prepareGeneration( | |
|
|
||
| tools, dynamicToolNames, err := appendDynamicTools(ctx, logger, tools, chat.DynamicTools, currentPlanMode, chat.Mode) | ||
| if err != nil { | ||
| cleanup() | ||
| return generationPrepared{}, err | ||
| } | ||
|
|
||
|
|
@@ -449,12 +445,10 @@ func (server *Server) prepareGeneration( | |
| if isComputerUse { | ||
| computerUseProvider, computerUseModelProvider, computerUseModelName, err := server.computerUseProviderAndModelFromConfig(ctx) | ||
| if err != nil { | ||
| cleanup() | ||
| return generationPrepared{}, xerrors.Errorf("resolve computer use provider and model: %w", err) | ||
| } | ||
| computerUseRoute, keyErr := server.resolveModelRouteForProviderType(ctx, chat.OwnerID, computerUseModelProvider) | ||
| if keyErr != nil { | ||
| cleanup() | ||
| return generationPrepared{}, xerrors.Errorf("resolve computer use provider route: %w", keyErr) | ||
| } | ||
| modelRoute = computerUseRoute | ||
|
|
@@ -469,7 +463,6 @@ func (server *Server) prepareGeneration( | |
| modelOpts, | ||
| ) | ||
| if cuErr != nil { | ||
| cleanup() | ||
| return generationPrepared{}, cuErr | ||
| } | ||
| model = cuModel | ||
|
|
@@ -486,7 +479,6 @@ func (server *Server) prepareGeneration( | |
| logger: server.logger.Named("computer_use"), | ||
| }) | ||
| if err != nil { | ||
| cleanup() | ||
| return generationPrepared{}, xerrors.Errorf("register computer use provider tool for provider %q: %w", computerUseProvider, err) | ||
| } | ||
| } else { | ||
|
|
@@ -495,7 +487,6 @@ func (server *Server) prepareGeneration( | |
| isComputerUse: false, | ||
| }) | ||
| if err != nil { | ||
| cleanup() | ||
| return generationPrepared{}, err | ||
| } | ||
| } | ||
|
|
@@ -529,7 +520,6 @@ func (server *Server) prepareGeneration( | |
| var debug *generationDebug | ||
| if debugEnabled { | ||
| if debugSvc == nil { | ||
| cleanup() | ||
| return generationPrepared{}, xerrors.New("chat debug service missing after enablement check") | ||
| } | ||
| debug = &generationDebug{ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit [CRF-1] The first sentence ("caps a model response when the model config does not set a provider-specific output limit") restates what the name + usage site already show:
default= fallback,ChatMaxOutputTokens= caps tokens, and thecallConfig.MaxOutputTokens == nilguard shows when it fires.Downgraded from P2 because the sibling
defaultAdvisorMaxOutputTokensfollows the identical what-then-why pattern, so this matches local convention.(Gon P2, downgraded to Nit by orchestrator)