mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 11:26:58 +10:00
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
|
|
import { getFeatureValue_CACHED_MAY_BE_STALE } from '../services/analytics/growthbook.js'
|
|||
|
|
import { getRateLimitTier, getSubscriptionType } from './auth.js'
|
|||
|
|
import { isEnvDefinedFalsy, isEnvTruthy } from './envUtils.js'
|
|||
|
|
|
|||
|
|
export function getPlanModeV2AgentCount(): number {
|
|||
|
|
// Environment variable override takes precedence
|
|||
|
|
if (process.env.CLAUDE_CODE_PLAN_V2_AGENT_COUNT) {
|
|||
|
|
const count = parseInt(process.env.CLAUDE_CODE_PLAN_V2_AGENT_COUNT, 10)
|
|||
|
|
if (!isNaN(count) && count > 0 && count <= 10) {
|
|||
|
|
return count
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const subscriptionType = getSubscriptionType()
|
|||
|
|
const rateLimitTier = getRateLimitTier()
|
|||
|
|
|
|||
|
|
if (
|
|||
|
|
subscriptionType === 'max' &&
|
|||
|
|
rateLimitTier === 'default_claude_max_20x'
|
|||
|
|
) {
|
|||
|
|
return 3
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (subscriptionType === 'enterprise' || subscriptionType === 'team') {
|
|||
|
|
return 3
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function getPlanModeV2ExploreAgentCount(): number {
|
|||
|
|
if (process.env.CLAUDE_CODE_PLAN_V2_EXPLORE_AGENT_COUNT) {
|
|||
|
|
const count = parseInt(
|
|||
|
|
process.env.CLAUDE_CODE_PLAN_V2_EXPLORE_AGENT_COUNT,
|
|||
|
|
10,
|
|||
|
|
)
|
|||
|
|
if (!isNaN(count) && count > 0 && count <= 10) {
|
|||
|
|
return count
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return 3
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Check if plan mode interview phase is enabled.
|
|||
|
|
*
|
|||
|
|
* Config: ant=always_on, external=tengu_plan_mode_interview_phase gate, envVar=true
|
|||
|
|
*/
|
|||
|
|
export function isPlanModeInterviewPhaseEnabled(): boolean {
|
|||
|
|
// Always on for ants
|
|||
|
|
if (process.env.USER_TYPE === 'ant') return true
|
|||
|
|
|
|||
|
|
const env = process.env.CLAUDE_CODE_PLAN_MODE_INTERVIEW_PHASE
|
|||
|
|
if (isEnvTruthy(env)) return true
|
|||
|
|
if (isEnvDefinedFalsy(env)) return false
|
|||
|
|
|
|||
|
|
return getFeatureValue_CACHED_MAY_BE_STALE(
|
|||
|
|
'tengu_plan_mode_interview_phase',
|
|||
|
|
false,
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export type PewterLedgerVariant = 'trim' | 'cut' | 'cap' | null
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* tengu_pewter_ledger — plan file structure prompt experiment.
|
|||
|
|
*
|
|||
|
|
* Controls the Phase 4 "Final Plan" bullets in the 5-phase plan mode
|
|||
|
|
* workflow (messages.ts getPlanPhase4Section). 5-phase is 99% of plan
|
|||
|
|
* traffic; interview-phase (ants) is untouched as a reference population.
|
|||
|
|
*
|
|||
|
|
* Arms: null (control), 'trim', 'cut', 'cap' — progressively stricter
|
|||
|
|
* guidance on plan file size.
|
|||
|
|
*
|
|||
|
|
* Baseline (control, 14d ending 2026-03-02, N=26.3M):
|
|||
|
|
* p50 4,906 chars | p90 11,617 | mean 6,207 | 82% Opus 4.6
|
|||
|
|
* Reject rate monotonic with size: 20% at <2K → 50% at 20K+
|
|||
|
|
*
|
|||
|
|
* Primary: session-level Avg Cost (fact__201omjcij85f) — Opus output is
|
|||
|
|
* 5× input price so cost is an output-weighted proxy. planLengthChars
|
|||
|
|
* on tengu_plan_exit is the mechanism but NOT the goal — the cap arm
|
|||
|
|
* could shrink the plan file while increasing total output via
|
|||
|
|
* write→count→edit cycles.
|
|||
|
|
* Guardrail: feedback-bad rate, requests/session (too-thin plans →
|
|||
|
|
* more implementation iterations), tool error rate
|
|||
|
|
*/
|
|||
|
|
export function getPewterLedgerVariant(): PewterLedgerVariant {
|
|||
|
|
const raw = getFeatureValue_CACHED_MAY_BE_STALE<string | null>(
|
|||
|
|
'tengu_pewter_ledger',
|
|||
|
|
null,
|
|||
|
|
)
|
|||
|
|
if (raw === 'trim' || raw === 'cut' || raw === 'cap') return raw
|
|||
|
|
return null
|
|||
|
|
}
|