feat: add codex fast mode and harden subagent launch

This commit is contained in:
luckyyzh
2026-08-05 03:24:17 +08:00
parent a196c3a6b1
commit 836042b97c
12 changed files with 5950 additions and 3893 deletions
+1
View File
@@ -41,6 +41,7 @@ export function buildBaseOptions(
maxRetries: options?.maxRetries,
maxRetryDelayMs: options?.maxRetryDelayMs,
metadata: options?.metadata,
serviceTier: options?.serviceTier,
env: options?.env,
};
}
+19
View File
@@ -113,6 +113,13 @@ export interface ProviderResponse {
headers: Record<string, string>;
}
/**
* Request-level service tier for providers that support it.
* OpenAI Codex / Responses: "priority" is fast mode (higher cost, lower latency), "flex" is the cheaper tier.
* See https://developers.openai.com/codex/speed for Codex fast mode semantics.
*/
export type ServiceTier = "auto" | "default" | "flex" | "priority" | "scale";
export interface StreamOptions {
temperature?: number;
maxTokens?: number;
@@ -189,6 +196,12 @@ export interface StreamOptions {
* For example, Anthropic uses `user_id` for abuse tracking and rate limiting.
*/
metadata?: Record<string, unknown>;
/**
* Request-level service tier. Providers that understand it (OpenAI Codex,
* OpenAI Responses) send it as `service_tier`; other providers ignore it.
* "priority" is Codex fast mode (1.5x speed, ~2x cost).
*/
serviceTier?: ServiceTier | null;
/**
* Provider-scoped environment values. These take precedence over process.env for
* provider configuration such as regional settings, endpoint placeholders, and
@@ -773,6 +786,12 @@ export interface Model<TApi extends Api> {
contextWindow: number;
maxTokens: number;
headers?: Record<string, string>;
/**
* Optional default request-level service tier for this model (e.g. "priority"
* for Codex fast mode). Configured via models.json; forwarded to providers
* that support `service_tier`.
*/
serviceTier?: ServiceTier;
/** Compatibility overrides for OpenAI-compatible APIs. If not set, auto-detected from baseUrl. */
compat?: TApi extends "openai-completions"
? OpenAICompletionsCompat
@@ -151,6 +151,13 @@ const ModelCostSchema = Type.Object({
tiers: Type.Optional(Type.Array(ModelCostTierSchema)),
});
const ServiceTierSchema = Type.Union([
Type.Literal("auto"),
Type.Literal("default"),
Type.Literal("priority"),
Type.Literal("flex"),
]);
const ModelDefinitionSchema = Type.Object({
id: Type.String({ minLength: 1 }),
name: Type.Optional(Type.String({ minLength: 1 })),
@@ -163,6 +170,7 @@ const ModelDefinitionSchema = Type.Object({
contextWindow: Type.Optional(Type.Number()),
maxTokens: Type.Optional(Type.Number()),
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
serviceTier: Type.Optional(ServiceTierSchema),
compat: Type.Optional(ProviderCompatSchema),
});
@@ -183,6 +191,7 @@ const ModelOverrideSchema = Type.Object({
contextWindow: Type.Optional(Type.Number()),
maxTokens: Type.Optional(Type.Number()),
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
serviceTier: Type.Optional(ServiceTierSchema),
compat: Type.Optional(ProviderCompatSchema),
});
@@ -117,6 +117,7 @@ function applyModelOverride(model: Model<Api>, override: ModelsJsonModelOverride
: model.cost,
contextWindow: override.contextWindow ?? model.contextWindow,
maxTokens: override.maxTokens ?? model.maxTokens,
serviceTier: override.serviceTier ?? model.serviceTier,
compat: mergeCompat(model.compat, override.compat),
};
}
@@ -154,6 +155,7 @@ function modelFromJson(
contextWindow: definition.contextWindow ?? 128000,
maxTokens: definition.maxTokens ?? 16384,
headers: undefined,
serviceTier: definition.serviceTier,
compat: mergeCompat(providerConfig.compat, definition.compat),
};
}
+5
View File
@@ -309,8 +309,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
const websocketConnectTimeoutMs =
options?.websocketConnectTimeoutMs ?? settingsManager.getWebSocketConnectTimeoutMs();
const headerRunner = extensionRunnerRef.current;
// Model-level service tier (models.json `serviceTier`, e.g. "priority" for
// Codex fast mode) is forwarded as request `service_tier`. Providers that
// don't understand it ignore the option.
const serviceTier = model.serviceTier;
return modelRuntime.streamSimple(model, context, {
...options,
...(serviceTier ? { serviceTier } : {}),
timeoutMs,
websocketConnectTimeoutMs,
maxRetries: options?.maxRetries ?? providerRetrySettings.maxRetries,