@@ -3,7 +3,8 @@ import { parseAgentId } from '../util/agent-id-parsing'
33import type { CostMode } from './model-config'
44
55/**
6- * The cost mode that indicates FREE mode - all agents in this mode cost 0 credits.
6+ * The cost mode that indicates FREE mode.
7+ * Only allowlisted agent+model combinations cost 0 credits in this mode.
78 */
89export const FREE_COST_MODE = 'free' as const
910
@@ -35,21 +36,6 @@ export const FREE_MODE_AGENT_MODELS: Record<string, Set<string>> = {
3536 'editor-glm' : new Set ( [ 'z-ai/glm-4.7' , 'z-ai/glm-4.6' ] ) ,
3637}
3738
38- /**
39- * Set of all agent IDs allowed in FREE mode.
40- * Derived from FREE_MODE_AGENT_MODELS for quick lookups.
41- */
42- export const FREE_MODE_ALLOWED_AGENTS = new Set ( Object . keys ( FREE_MODE_AGENT_MODELS ) )
43-
44- /**
45- * Models that are allowed in FREE mode.
46- * Derived from FREE_MODE_AGENT_MODELS - this is the union of all allowed models.
47- * This prevents abuse by users trying to use expensive models for free.
48- */
49- export const FREE_MODE_ALLOWED_MODELS = new Set (
50- Object . values ( FREE_MODE_AGENT_MODELS ) . flatMap ( ( models ) => Array . from ( models ) ) ,
51- )
52-
5339/**
5440 * Agents that don't charge credits when credits would be very small (<5).
5541 *
@@ -81,59 +67,28 @@ export function isFreeMode(costMode: CostMode | string | undefined): boolean {
8167 return costMode === FREE_COST_MODE
8268}
8369
84- /**
85- * Check if a model is allowed in FREE mode.
86- * Only whitelisted cheap/fast models can be used for free.
87- */
88- export function isFreeModeAllowedModel ( model : string ) : boolean {
89- return FREE_MODE_ALLOWED_MODELS . has ( model )
90- }
91-
92- /**
93- * Check if an agent is allowed to run in FREE mode.
94- * Validates both the agent ID and optionally the publisher.
95- *
96- * For security, we only allow:
97- * - Internal agents (no publisher, e.g., 'base2-free')
98- * - Codebuff-published agents (publisher === 'codebuff')
99- *
100- * This prevents attackers from creating agents with matching names
101- * under different publishers to abuse free mode.
102- */
103- export function isFreeModeAllowedAgent ( fullAgentId : string ) : boolean {
104- const { publisherId, agentId } = parseAgentId ( fullAgentId )
105-
106- // Must have a valid agent ID
107- if ( ! agentId ) return false
108-
109- // Must be in the allowed agents list
110- if ( ! FREE_MODE_ALLOWED_AGENTS . has ( agentId ) ) return false
111-
112- // Must be either internal (no publisher) or from codebuff
113- if ( publisherId && publisherId !== 'codebuff' ) return false
114-
115- return true
116- }
117-
11870/**
11971 * Check if a specific agent is allowed to use a specific model in FREE mode.
12072 * This is the strictest check - validates both the agent AND model combination.
12173 *
12274 * Returns true only if:
123- * 1. The agent is allowed in free mode (isFreeModeAllowedAgent)
124- * 2. The model is in that agent's allowed model set
75+ * 1. The agent has a valid agent ID
76+ * 2. The agent is in the allowed free-mode agents list
77+ * 3. The agent is either internal or published by 'codebuff' (prevents spoofing)
78+ * 4. The model is in that agent's allowed model set
12579 */
12680export function isFreeModeAllowedAgentModel (
12781 fullAgentId : string ,
12882 model : string ,
12983) : boolean {
130- // First check if agent is allowed in free mode (includes publisher validation)
131- if ( ! isFreeModeAllowedAgent ( fullAgentId ) ) return false
84+ const { publisherId, agentId } = parseAgentId ( fullAgentId )
13285
133- // Parse to get the base agent ID for model lookup
134- const { agentId } = parseAgentId ( fullAgentId )
86+ // Must have a valid agent ID
13587 if ( ! agentId ) return false
13688
89+ // Must be either internal (no publisher) or from codebuff
90+ if ( publisherId && publisherId !== 'codebuff' ) return false
91+
13792 // Get the allowed models for this agent
13893 const allowedModels = FREE_MODE_AGENT_MODELS [ agentId ]
13994 if ( ! allowedModels ) return false
0 commit comments