th-1cc9fa: model-output ceiling clamp + raise starvation defaults (TypeScript parity)#195
Open
brentrager wants to merge 1 commit into
Open
th-1cc9fa: model-output ceiling clamp + raise starvation defaults (TypeScript parity)#195brentrager wants to merge 1 commit into
brentrager wants to merge 1 commit into
Conversation
… server) TypeScript parity with the merged Rust reference (rust/smooth-operator-server: admin.rs model_output_ceiling/map_model_info + config.rs DEFAULT_MAX_TOKENS/ ITERATIONS). - modelCeiling.ts: best-effort per-model output ceiling from the gateway's /model/info (extractModelCeilings + createGatewayModelCeilingResolver), cached once per process, undefined on any error => engine leaves max_tokens unclamped. The TS analog of admin.rs's fetch_model_costs/model_output_ceiling/map_model_info. - TurnRunner: raise DEFAULT_MAX_TOKENS 512->8192 and DEFAULT_MAX_ITERATIONS 6->20 (chat-widget sizing starved reasoning models), thread the per-turn ceiling into the engine via AgentOptions.modelMaxOutput, and set an explicit DEFAULT_MODEL (= engine default) that both the request and the ceiling lookup share. - Thread model + modelCeiling through FrameDispatcher, ServerOptions, serveLocal; main.ts builds the resolver from SMOOAI_GATEWAY_URL/KEY (undefined on the keyless local path => unclamped, behaviour unchanged). - Bump @smooai/smooth-operator-core pin to ^0.20.1 (the release introducing modelMaxOutput / effectiveMaxTokens). Tests: modelCeiling extract/resolve (caching, best-effort, auth header, single-flight) + TurnRunner clamp-down / passthrough / unclamped. Server suite green (57 tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A budget/policy
max_tokenscan exceed what a model can physically emit. When it does, reasoning models burn the whole budget onreasoning_contentand return emptycontent, or the upstream 400s (e.g.groq-compoundcaps output at 8192). Separately, the server's chat-widget-sized defaults (max_tokens=512,max_iterations=6) starve reasoning / multi-step turns.What (TypeScript server)
Mirrors the already-merged Rust reference on this branch —
rust/smooth-operator-server/src/admin.rs(model_output_ceiling/fetch_model_costs/map_model_info),config.rs(DEFAULT_MAX_TOKENS/DEFAULT_MAX_ITERATIONS),handler.rs+runner.rs(thread the ceiling into the turn) — in TS idioms:modelCeiling.ts(new): best-effort per-model output ceiling from the gateway's/model/info.extractModelCeilings(payload)(pure, themap_model_infoanalog, narrowed tomodel_info.max_output_tokens) +createGatewayModelCeilingResolver(url, key, fetch?), fetched at most once per process and cached; any error / unknown model ⇒undefined⇒ the engine leavesmax_tokensunclamped (graceful, no behaviour change).TurnRunner: raiseDEFAULT_MAX_TOKENS512→8192 andDEFAULT_MAX_ITERATIONS6→20 (safe now that the clamp bounds per-model output; a cap doesn't lengthen concise answers). Look up the resolved model's ceiling per turn and thread it into the engine viaAgentOptions.modelMaxOutput. An explicitDEFAULT_MODEL(= the engine's own default) is now set so the request model and the ceiling-lookup model are always the same.model+modelCeilingthroughFrameDispatcher→ServerOptions/serveLocal;main.tsbuilds the resolver fromSMOOAI_GATEWAY_URL/SMOOAI_GATEWAY_KEY(absent on the keyless local path ⇒ unclamped, behaviour unchanged).@smooai/smooth-operator-corepin to^0.20.1— the release that introducesmodelMaxOutput/effectiveMaxTokens(th-1cc9fa: model-output ceiling clamp + raise starvation defaults (TypeScript parity) smooth-operator-core#71).Mirroring Rust
undefined/unset ceiling ⇒ no clamp, identical to the RustNonepassthrough. The ceiling is sourced by the consumer (this server) from/model/infoand passed into the engine, keeping LiteLLM-specific HTTP out of the published engine — same split as Rust.Tests
modelCeiling: payload extraction (skips missing name / no ceiling / non-integer), resolver caching (one fetch),{url}/model/info+ bearer header, no-key path, best-effortundefinedon non-ok / thrown fetch (not cached → retries), single-flight across concurrent first lookups.TurnRunner: raised default budget sent; clamp-down when ceiling < budget; passthrough when ceiling ≥ budget; unclamped on unknown model; ceiling looked up for the model the turn actually uses.tscbuild + typecheck clean (verified against a local link to the modified core).Caveat — release ordering (see companion core PR)
The
modelMaxOutputoption ships in@smooai/smooth-operator-core0.20.1 (SmooAI/smooth-operator-core#71). Until that publishes, a freshpnpm installhere can't resolve the bumped^0.20.1pin (the committed lockfile still points at the stale prior core). The TS server is a private package and is not built/tested in PR CI, so this doesn't gate the PR — but land/publish the core PR first, then refresh the lockfile.🤖 Generated with Claude Code