This pass rewrites comment-only ANT-ONLY markers to neutral internal-only language across the source tree without changing runtime strings, flags, commands, or protocol identifiers. The goal is to lower obvious internal prose leakage while keeping the diff mechanically safe and easy to review. Constraint: Phase B is limited to comments/prose only; runtime strings and user-facing labels remain deferred Rejected: Broad search-and-replace across strings and command descriptions | too risky for a prose-only pass Confidence: high Scope-risk: narrow Reversibility: clean Directive: Remaining ANT-ONLY hits are mostly runtime/user-facing strings and should be handled separately from comment cleanup Tested: bun run build Tested: bun run smoke Tested: bun run verify:privacy Tested: bun run test:provider Tested: bun run test:provider-recommendation Not-tested: Full repo typecheck (upstream baseline remains noisy) Co-authored-by: anandh8x <test@example.com>
163 lines
5.4 KiB
TypeScript
163 lines
5.4 KiB
TypeScript
// biome-ignore-all assist/source/organizeImports: internal-only import markers must not be reordered
|
|
import type { Theme } from './theme.js'
|
|
import { feature } from 'bun:bundle'
|
|
import { getFeatureValue_CACHED_MAY_BE_STALE } from '../services/analytics/growthbook.js'
|
|
import { getCanonicalName } from './model/model.js'
|
|
import { get3PModelCapabilityOverride } from './model/modelSupportOverrides.js'
|
|
import { getAPIProvider } from './model/providers.js'
|
|
import { getSettingsWithErrors } from './settings/settings.js'
|
|
|
|
export type ThinkingConfig =
|
|
| { type: 'adaptive' }
|
|
| { type: 'enabled'; budgetTokens: number }
|
|
| { type: 'disabled' }
|
|
|
|
/**
|
|
* Build-time gate (feature) + runtime gate (GrowthBook). The build flag
|
|
* controls code inclusion in external builds; the GB flag controls rollout.
|
|
*/
|
|
export function isUltrathinkEnabled(): boolean {
|
|
if (!feature('ULTRATHINK')) {
|
|
return false
|
|
}
|
|
return getFeatureValue_CACHED_MAY_BE_STALE('tengu_turtle_carbon', true)
|
|
}
|
|
|
|
/**
|
|
* Check if text contains the "ultrathink" keyword.
|
|
*/
|
|
export function hasUltrathinkKeyword(text: string): boolean {
|
|
return /\bultrathink\b/i.test(text)
|
|
}
|
|
|
|
/**
|
|
* Find positions of "ultrathink" keyword in text (for UI highlighting/notification)
|
|
*/
|
|
export function findThinkingTriggerPositions(text: string): Array<{
|
|
word: string
|
|
start: number
|
|
end: number
|
|
}> {
|
|
const positions: Array<{ word: string; start: number; end: number }> = []
|
|
// Fresh /g literal each call — String.prototype.matchAll copies lastIndex
|
|
// from the source regex, so a shared instance would leak state from
|
|
// hasUltrathinkKeyword's .test() into this call on the next render.
|
|
const matches = text.matchAll(/\bultrathink\b/gi)
|
|
|
|
for (const match of matches) {
|
|
if (match.index !== undefined) {
|
|
positions.push({
|
|
word: match[0],
|
|
start: match.index,
|
|
end: match.index + match[0].length,
|
|
})
|
|
}
|
|
}
|
|
|
|
return positions
|
|
}
|
|
|
|
const RAINBOW_COLORS: Array<keyof Theme> = [
|
|
'rainbow_red',
|
|
'rainbow_orange',
|
|
'rainbow_yellow',
|
|
'rainbow_green',
|
|
'rainbow_blue',
|
|
'rainbow_indigo',
|
|
'rainbow_violet',
|
|
]
|
|
|
|
const RAINBOW_SHIMMER_COLORS: Array<keyof Theme> = [
|
|
'rainbow_red_shimmer',
|
|
'rainbow_orange_shimmer',
|
|
'rainbow_yellow_shimmer',
|
|
'rainbow_green_shimmer',
|
|
'rainbow_blue_shimmer',
|
|
'rainbow_indigo_shimmer',
|
|
'rainbow_violet_shimmer',
|
|
]
|
|
|
|
export function getRainbowColor(
|
|
charIndex: number,
|
|
shimmer: boolean = false,
|
|
): keyof Theme {
|
|
const colors = shimmer ? RAINBOW_SHIMMER_COLORS : RAINBOW_COLORS
|
|
return colors[charIndex % colors.length]!
|
|
}
|
|
|
|
// TODO(inigo): add support for probing unknown models via API error detection
|
|
// Provider-aware thinking support detection (aligns with modelSupportsISP in betas.ts)
|
|
export function modelSupportsThinking(model: string): boolean {
|
|
const supported3P = get3PModelCapabilityOverride(model, 'thinking')
|
|
if (supported3P !== undefined) {
|
|
return supported3P
|
|
}
|
|
if (process.env.USER_TYPE === 'ant') {
|
|
if (resolveAntModel(model.toLowerCase())) {
|
|
return true
|
|
}
|
|
}
|
|
// IMPORTANT: Do not change thinking support without notifying the model
|
|
// launch DRI and research. This can greatly affect model quality and bashing.
|
|
const canonical = getCanonicalName(model)
|
|
const provider = getAPIProvider()
|
|
// 1P and Foundry: all Claude 4+ models (including Haiku 4.5)
|
|
if (provider === 'foundry' || provider === 'firstParty') {
|
|
return !canonical.includes('claude-3-')
|
|
}
|
|
// 3P (Bedrock/Vertex): only Opus 4+ and Sonnet 4+
|
|
return canonical.includes('sonnet-4') || canonical.includes('opus-4')
|
|
}
|
|
|
|
// @[MODEL LAUNCH]: Add the new model to the allowlist if it supports adaptive thinking.
|
|
export function modelSupportsAdaptiveThinking(model: string): boolean {
|
|
const supported3P = get3PModelCapabilityOverride(model, 'adaptive_thinking')
|
|
if (supported3P !== undefined) {
|
|
return supported3P
|
|
}
|
|
const canonical = getCanonicalName(model)
|
|
// Supported by a subset of Claude 4 models
|
|
if (canonical.includes('opus-4-6') || canonical.includes('sonnet-4-6')) {
|
|
return true
|
|
}
|
|
// Exclude any other known legacy models (allowlist above catches 4-6 variants first)
|
|
if (
|
|
canonical.includes('opus') ||
|
|
canonical.includes('sonnet') ||
|
|
canonical.includes('haiku')
|
|
) {
|
|
return false
|
|
}
|
|
// IMPORTANT: Do not change adaptive thinking support without notifying the
|
|
// model launch DRI and research. This can greatly affect model quality and
|
|
// bashing.
|
|
|
|
// Newer models (4.6+) are all trained on adaptive thinking and MUST have it
|
|
// enabled for model testing. DO NOT default to false for first party, otherwise
|
|
// we may silently degrade model quality.
|
|
|
|
// Default to true for unknown model strings on 1P and Foundry (because Foundry
|
|
// is a proxy). Do not default to true for other 3P as they have different formats
|
|
// for their model strings.
|
|
const provider = getAPIProvider()
|
|
return provider === 'firstParty' || provider === 'foundry'
|
|
}
|
|
|
|
export function shouldEnableThinkingByDefault(): boolean {
|
|
if (process.env.MAX_THINKING_TOKENS) {
|
|
return parseInt(process.env.MAX_THINKING_TOKENS, 10) > 0
|
|
}
|
|
|
|
const { settings } = getSettingsWithErrors()
|
|
if (settings.alwaysThinkingEnabled === false) {
|
|
return false
|
|
}
|
|
|
|
// IMPORTANT: Do not change default thinking enabled value without notifying
|
|
// the model launch DRI and research. This can greatly affect model quality and
|
|
// bashing.
|
|
|
|
// Enable thinking by default unless explicitly disabled.
|
|
return true
|
|
}
|