mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
Compare commits
17 Commits
cff3d90613
...
9fc0b39730
| Author | SHA1 | Date | |
|---|---|---|---|
| 9fc0b39730 | |||
| 194bfe23a1 | |||
| 35110480ef | |||
| 959595e33a | |||
| a960424dfb | |||
| 0df6c7d08b | |||
| 65c841e7a7 | |||
| b21b8cc982 | |||
| aa2c4f06b7 | |||
| b8d7b4ec10 | |||
| c48520255a | |||
| 0790da989d | |||
| 506d24d2fd | |||
| 1348dbf493 | |||
| ce677f3cd9 | |||
| 39203d78e3 | |||
| 2ef7daf369 |
@@ -33,7 +33,10 @@ const _styles = {
|
||||
} as const,
|
||||
'& nav > ol > li:first-of-type': {
|
||||
overflow: 'hidden',
|
||||
maxWidth: { xs: '110px', md: '140px' },
|
||||
// allow the chat title to use available space, shrinking gracefully when the bar is narrow
|
||||
// NOTE: already performed by virtue of the breadcrumb having agi-ellipsize on the crumbs
|
||||
// flexShrink: 1,
|
||||
// minWidth: '60px',
|
||||
} as const,
|
||||
|
||||
} as const,
|
||||
|
||||
@@ -23,7 +23,7 @@ export const Release = {
|
||||
|
||||
// this is here to trigger revalidation of data, e.g. models refresh
|
||||
Monotonics: {
|
||||
Aix: 68,
|
||||
Aix: 69,
|
||||
NewsVersion: 204,
|
||||
},
|
||||
|
||||
|
||||
@@ -905,9 +905,12 @@ export class ContentReassembler {
|
||||
/**
|
||||
* Stores raw termination data from the wire - classification deferred to finalizeReassembly()
|
||||
*/
|
||||
private onCGEnd({ terminationReason, tokenStopReason }: Extract<AixWire_Particles.ChatGenerateOp, { cg: 'end' }>): void {
|
||||
private onCGEnd({ terminationReason, tokenStopReason, tokenStopError }: Extract<AixWire_Particles.ChatGenerateOp, { cg: 'end' }>): void {
|
||||
this.S.terminationReason = terminationReason;
|
||||
this.S.dialectStopReason = tokenStopReason;
|
||||
// Vendor-composed stop error, surfaced as a complementary error fragment alongside the generic classification message
|
||||
if (tokenStopError)
|
||||
this._appendErrorFragment(tokenStopError);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Box, Card, Chip, Divider, Sheet, Typography } from '@mui/joy';
|
||||
import { RenderCodeMemo } from '~/modules/blocks/code/RenderCode';
|
||||
|
||||
import { ExpanderControlledBox } from '~/common/components/ExpanderControlledBox';
|
||||
import { objectDeepCloneWithStringLimit } from '~/common/util/objectUtils';
|
||||
import TimelapseIcon from '@mui/icons-material/Timelapse';
|
||||
|
||||
import type { AixClientDebugger } from './memstore-aix-client-debugger';
|
||||
@@ -184,12 +185,10 @@ export function AixDebuggerFrame(props: {
|
||||
{/* List of particles */}
|
||||
{frame.particles.map((particle, idx) => {
|
||||
|
||||
// truncated preview of particle content
|
||||
// preview of particle content: preserve structure, trim long string fields
|
||||
let jsonPreview = '';
|
||||
try {
|
||||
const content = particle.content;
|
||||
jsonPreview = JSON.stringify(content).substring(0, 1024);
|
||||
if (jsonPreview.length >= 1024) jsonPreview += '...';
|
||||
jsonPreview = JSON.stringify(objectDeepCloneWithStringLimit(particle.content, 'aix-debugger-particle', 64));
|
||||
} catch (e) {
|
||||
jsonPreview = 'Error parsing content';
|
||||
}
|
||||
|
||||
@@ -689,7 +689,7 @@ export namespace AixWire_Particles {
|
||||
|
||||
export type ChatControlOp =
|
||||
// | { cg: 'start' } // not really used for now
|
||||
| { cg: 'end', terminationReason: CGEndReason /* we know why we're sending 'end' */, tokenStopReason?: GCTokenStopReason /* we may or not have gotten a logical token stop reason from the dispatch */ }
|
||||
| { cg: 'end', terminationReason: CGEndReason /* we know why we're sending 'end' */, tokenStopReason?: GCTokenStopReason /* we may or not have gotten a logical token stop reason from the dispatch */, tokenStopError?: string /* optional vendor-composed human-readable detail paired with tokenStopReason */ }
|
||||
| { cg: 'issue', issueId: CGIssueId, issueText: string }
|
||||
| { cg: 'aix-info', ait: 'flow-cont' /* important: establishes a checkpoint */, text: string }
|
||||
| { cg: 'aix-retry-reset', rScope: 'srv-dispatch' | 'srv-op' | 'cli-ll', rClearStrategy: 'none' | 'since-checkpoint' | 'all', reason: string, attempt: number, maxAttempts: number, delayMs: number, causeHttp?: number, causeConn?: string }
|
||||
|
||||
@@ -56,6 +56,7 @@ export class ChatGenerateTransmitter implements IParticleTransmitter {
|
||||
|
||||
// Token stop reason
|
||||
private tokenStopReason: AixWire_Particles.GCTokenStopReason | undefined = undefined;
|
||||
private tokenStopError: string | undefined = undefined;
|
||||
|
||||
// Metrics
|
||||
private accMetrics: AixWire_Particles.CGSelectMetrics | undefined = undefined;
|
||||
@@ -105,6 +106,7 @@ export class ChatGenerateTransmitter implements IParticleTransmitter {
|
||||
cg: 'end',
|
||||
terminationReason: this.terminationReason,
|
||||
tokenStopReason: this.tokenStopReason, // See NOTE above - || (dispatchOrDialectIssue ? 'cg-issue' : 'ok'),
|
||||
...(this.tokenStopError && { tokenStopError: this.tokenStopError }),
|
||||
});
|
||||
// Keep this in a terminated state, so that every subsequent call will yield errors (not implemented)
|
||||
// this.terminationReason = null;
|
||||
@@ -201,12 +203,13 @@ export class ChatGenerateTransmitter implements IParticleTransmitter {
|
||||
this.setDialectEnded('issue-dialect');
|
||||
}
|
||||
|
||||
setTokenStopReason(reason: AixWire_Particles.GCTokenStopReason) {
|
||||
setTokenStopReason(reason: AixWire_Particles.GCTokenStopReason, errorText?: string) {
|
||||
if (SERVER_DEBUG_WIRE)
|
||||
console.log('|token-stop|', reason);
|
||||
console.log('|token-stop|', reason, errorText ?? '');
|
||||
if (this.tokenStopReason && this.tokenStopReason !== reason)
|
||||
console.warn(`[Aix.${this.prettyDialect}] setTokenStopReason('${reason}'): already has token stop reason '${this.tokenStopReason}' (overriding)`);
|
||||
this.tokenStopReason = reason;
|
||||
if (errorText) this.tokenStopError = errorText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ export interface IParticleTransmitter {
|
||||
/** End the current part and flush it, which also calls `setDialectEnded('issue-dialect')` */
|
||||
setDialectTerminatingIssue(dialectText: string, symbol: string | null, serverLog: ParticleServerLogLevel): void;
|
||||
|
||||
/** Communicates the finish reason to the client - Data only, this does not do Control, like the above */
|
||||
setTokenStopReason(reason: AixWire_Particles.GCTokenStopReason): void;
|
||||
/** Communicates the finish reason to the client - Data only. Optional `errorText` is a vendor-composed string rendered as a complementary error fragment alongside the generic classification message. */
|
||||
setTokenStopReason(reason: AixWire_Particles.GCTokenStopReason, errorText?: string): void;
|
||||
|
||||
|
||||
// Parts data //
|
||||
|
||||
@@ -404,7 +404,7 @@ export function createAnthropicMessageParser(): ChatGenerateParseFunction {
|
||||
// -> Token Stop Reason
|
||||
const tokenStopReason = _fromAnthropicStopReason(delta.stop_reason, 'message_delta');
|
||||
if (tokenStopReason !== null)
|
||||
pt.setTokenStopReason(tokenStopReason);
|
||||
pt.setTokenStopReason(tokenStopReason, _formatAnthropicStopError(delta.stop_details));
|
||||
|
||||
// NOTE: we have more fields we're not parsing yet - https://platform.claude.com/docs/en/api/typescript/messages#message_delta_usage
|
||||
if (usage?.output_tokens && messageStartTime) {
|
||||
@@ -511,6 +511,7 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
|
||||
content,
|
||||
container,
|
||||
stop_reason,
|
||||
stop_details,
|
||||
usage,
|
||||
} = AnthropicWire_API_Message_Create.Response_schema.parse(JSON.parse(fullData));
|
||||
|
||||
@@ -653,7 +654,7 @@ export function createAnthropicMessageParserNS(): ChatGenerateParseFunction {
|
||||
// -> Token Stop Reason (pause_turn already thrown above)
|
||||
const tokenStopReason = _fromAnthropicStopReason(stop_reason, 'parser_NS');
|
||||
if (tokenStopReason !== null)
|
||||
pt.setTokenStopReason(tokenStopReason);
|
||||
pt.setTokenStopReason(tokenStopReason, _formatAnthropicStopError(stop_details));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -681,6 +682,19 @@ function _emitContainerState(pt: IParticleTransmitter, container: { id: string;
|
||||
});
|
||||
}
|
||||
|
||||
/** Compose a human-readable error string from Anthropic's stop_details. Returns undefined when nothing useful to surface. */
|
||||
function _formatAnthropicStopError(stopDetails: { type: string; category?: string | null; explanation?: string | null } | null | undefined): string | undefined {
|
||||
if (!stopDetails) return undefined;
|
||||
if (stopDetails.type !== 'refusal') {
|
||||
aixResilientUnknownValue('Anthropic', 'stopDetailsType', stopDetails.type);
|
||||
return undefined;
|
||||
}
|
||||
const parts: string[] = [];
|
||||
if (stopDetails.category) parts.push(`[${stopDetails.category}]`);
|
||||
if (stopDetails.explanation) parts.push(stopDetails.explanation);
|
||||
return parts.length ? `Refusal: ${parts.join(' ')}` : undefined;
|
||||
}
|
||||
|
||||
|
||||
// --- Shared server tool result handlers (used by both S and NS parsers) ---
|
||||
|
||||
|
||||
@@ -18,6 +18,21 @@ const OPENAI_RESPONSES_SAME_PART_SPACER = '\n\n';
|
||||
const INLINE_IMAGE_SKIP_RESIZE_MAX_B64_BYTES = 250_000; // skip resize for small images (e.g. code interpreter charts)
|
||||
|
||||
|
||||
/**
|
||||
* Wishlist marker: hosted tool calls (web_search_call, image_generation_call, code_interpreter_call, ...)
|
||||
* are rendered via ephemeral OperationState/inline-asset paths and are NOT round-tripped as structured
|
||||
* fragments. This breaks stateless multi-turn with reasoning models. See PRD.FUTURE-atol.md "Wishlist:
|
||||
* Hosted tool invocations as first-class fragments".
|
||||
*/
|
||||
// const _hostedToolWishlistSeen = new Set<string>();
|
||||
function _hostedToolWishlistHint(family: 'web_search' | 'image_generation' | 'code_interpreter' | 'custom_tool'): void {
|
||||
// if (_hostedToolWishlistSeen.has(family)) return;
|
||||
// _hostedToolWishlistSeen.add(family);
|
||||
// NOTE: disable the log because it's logging all the time evenrwyehre; just implement this
|
||||
// console.log(`[DEV] AIX: ATOL wishlist - hosted '${family}' call observed; not round-tripped as a structured fragment yet (see kb/product/PRD.FUTURE-atol.md)`);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Safely sanitizes a URL for display in placeholders by removing query parameters and paths
|
||||
* to prevent leaking sensitive information while keeping the domain recognizable.
|
||||
@@ -46,6 +61,11 @@ type TEventType = OpenAIWire_API_Responses.StreamingEvent['type'];
|
||||
// cached config for the image_generation hosted tool, captured at response.created
|
||||
type TImageGenToolCfg = Extract<OpenAIWire_Responses_Tools.Tool, { type: 'image_generation' }>;
|
||||
|
||||
/** Extract the image_generation tool config from the echoed tools array (API does not echo `model` per-item). Shared by streaming and non-streaming paths. */
|
||||
function _findImageGenToolCfg(tools: TResponse['tools']): TImageGenToolCfg | undefined {
|
||||
return tools?.find((t): t is TImageGenToolCfg => t.type === 'image_generation');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* We need this just to ensure events are not out of order, as out streaming is progressive
|
||||
@@ -248,8 +268,7 @@ class ResponseParserStateMachine {
|
||||
// Hosted tool config capture
|
||||
|
||||
captureHostedToolConfigs(tools: TResponse['tools']) {
|
||||
if (!tools?.length) return;
|
||||
this.#imageGenToolCfg = tools.find((t): t is TImageGenToolCfg => t.type === 'image_generation');
|
||||
this.#imageGenToolCfg = _findImageGenToolCfg(tools);
|
||||
}
|
||||
|
||||
get imageGenToolCfg() {
|
||||
@@ -448,6 +467,7 @@ export function createOpenAIResponsesEventParser(): ChatGenerateParseFunction {
|
||||
break;
|
||||
|
||||
case 'image_generation_call':
|
||||
_hostedToolWishlistHint('image_generation');
|
||||
// -> IGC: process completed image generation using 'ii' particle for inline images
|
||||
const { id: igId, result: igResult, revised_prompt: igRevisedPrompt } = doneItem;
|
||||
const igDoneText = !igRevisedPrompt?.length ? 'Image generated'
|
||||
@@ -765,6 +785,9 @@ export function createOpenAIResponseParserNS(): ChatGenerateParseFunction {
|
||||
if (response.model)
|
||||
pt.setModelName(response.model);
|
||||
|
||||
// -> Hosted tool config capture (needed for enriching done-item particles with tool params the API does not echo per-item, e.g. image_generation.model)
|
||||
const imageGenToolCfg = _findImageGenToolCfg(response.tools);
|
||||
|
||||
// -> Upstream Handle (for remote control: resume, cancel, delete)
|
||||
// NOTE: we don't do it for full responses, because they're supposed to be 'complete' - i.e. no 'background' execution
|
||||
|
||||
@@ -875,11 +898,16 @@ export function createOpenAIResponseParserNS(): ChatGenerateParseFunction {
|
||||
pt.appendReasoningText(item.text);
|
||||
}
|
||||
|
||||
// [DEV] surface cases that diverge from our continuity round-trip expectations
|
||||
if (!reasoningId && !reasoningEC)
|
||||
console.warn('[DEV] AIX: OpenAI-Response-NS: reasoning item has neither id nor encrypted_content - no continuity handle captured for this turn', { oItem });
|
||||
else if (!reasoningEC)
|
||||
console.log('[DEV] AIX: OpenAI-Response-NS: reasoning item has id but no encrypted_content - stateless round-trip requires include:[\'reasoning.encrypted_content\'] on the request');
|
||||
|
||||
// Capture the continuity handle (encrypted_content + id) for stateless multi-turn round-tripping.
|
||||
// Attached to the ma fragment produced by the summary above; if no summary was emitted, this may
|
||||
// attach to an unrelated preceding fragment - tolerable as the worst case is a misfiled blob.
|
||||
// FIXME: make sure we are attaching to an 'ma' (i.e. reasoning text or somehting was emitted)
|
||||
if (reasoningEC || reasoningId)
|
||||
if (reasoningEC || reasoningId) {
|
||||
// Defensive: ensure an ma fragment exists as the attach target for the svs particle below (parity with the streaming path).
|
||||
pt.appendReasoningText('');
|
||||
pt.sendSetVendorState({
|
||||
p: 'svs',
|
||||
vendor: 'openai',
|
||||
@@ -890,10 +918,7 @@ export function createOpenAIResponseParserNS(): ChatGenerateParseFunction {
|
||||
},
|
||||
},
|
||||
});
|
||||
else if (!reasoningId && !reasoningEC)
|
||||
console.warn('[DEV] AIX: OpenAI-Response-NS: reasoning item has neither id nor encrypted_content - no continuity handle captured for this turn', { oItem });
|
||||
else if (!reasoningEC)
|
||||
console.log('[DEV] AIX: OpenAI-Response-NS: reasoning item has id but no encrypted_content - stateless round-trip requires include:[\'reasoning.encrypted_content\'] on the request');
|
||||
}
|
||||
break;
|
||||
|
||||
// Message contains the main 'assistant' response
|
||||
@@ -957,6 +982,7 @@ export function createOpenAIResponseParserNS(): ChatGenerateParseFunction {
|
||||
break;
|
||||
|
||||
case 'image_generation_call':
|
||||
_hostedToolWishlistHint('image_generation');
|
||||
// -> IGC: process completed image generation using 'ii' particle for inline images
|
||||
const { result: igResult, revised_prompt: igRevisedPrompt } = oItem;
|
||||
// Create inline image with base64 data
|
||||
@@ -965,7 +991,7 @@ export function createOpenAIResponseParserNS(): ChatGenerateParseFunction {
|
||||
_imageGenerationMimeType(oItem), // infer from output_format echoed in the item
|
||||
igResult,
|
||||
igRevisedPrompt || 'Generated image',
|
||||
AIX_OAI_DEFAULT_IMAGE_GEN_MODEL, // generator: non-streaming path has no captured tool config, use current default
|
||||
imageGenToolCfg?.model || AIX_OAI_DEFAULT_IMAGE_GEN_MODEL, // generator: read from echoed tools (API does not echo model per-item), fallback to current default
|
||||
igRevisedPrompt || '', // prompt used
|
||||
);
|
||||
else
|
||||
@@ -1150,6 +1176,7 @@ function _imageGenerationMimeType(item: { output_format?: string }): string {
|
||||
* - citations: High-quality links (2-3) via annotations in message content
|
||||
*/
|
||||
function _forwardDoneWebSearchCallItem(pt: IParticleTransmitter, webSearchCall: Extract<OpenAIWire_API_Responses.Response['output'][number], { type: 'web_search_call' }>, opId: string): void {
|
||||
_hostedToolWishlistHint('web_search');
|
||||
const { action, status } = webSearchCall;
|
||||
|
||||
const doneOpts = { opId, state: 'done' } as const;
|
||||
@@ -1203,6 +1230,7 @@ function _forwardDoneWebSearchCallItem(pt: IParticleTransmitter, webSearchCall:
|
||||
* - addCodeExecutionResponse for each output result
|
||||
*/
|
||||
function _forwardDoneCodeInterpreterCallItem(pt: IParticleTransmitter, codeInterpreterCall: Extract<OpenAIWire_API_Responses.Response['output'][number], { type: 'code_interpreter_call' }>): void {
|
||||
_hostedToolWishlistHint('code_interpreter');
|
||||
const { id, code, outputs, status /*,container_id*/ } = codeInterpreterCall;
|
||||
|
||||
// <- Emit code (like Gemini's executableCode)
|
||||
|
||||
+5
-7
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
Upstream snapshot - DO NOT EDIT - run _upstream/sync.sh to refresh
|
||||
Source: https://platform.claude.com/docs/en/api/messages/create.md
|
||||
Synced: 2026-04-23
|
||||
Synced: 2026-04-24
|
||||
Consumed by: anthropic.wiretypes.ts, anthropic.parser.ts, anthropic.messageCreate.ts, anthropic.transform-fileInline.ts
|
||||
-->
|
||||
|
||||
@@ -2429,7 +2429,7 @@ Learn more about the Messages API in our [user guide](https://docs.claude.com/en
|
||||
|
||||
Configuration options for the model's output, such as the output format.
|
||||
|
||||
- `effort: optional "low" or "medium" or "high" or 2 more`
|
||||
- `effort: optional "low" or "medium" or "high" or "max"`
|
||||
|
||||
All possible effort levels.
|
||||
|
||||
@@ -2439,8 +2439,6 @@ Learn more about the Messages API in our [user guide](https://docs.claude.com/en
|
||||
|
||||
- `"high"`
|
||||
|
||||
- `"xhigh"`
|
||||
|
||||
- `"max"`
|
||||
|
||||
- `format: optional JSONOutputFormat`
|
||||
@@ -3822,15 +3820,15 @@ Learn more about the Messages API in our [user guide](https://docs.claude.com/en
|
||||
|
||||
Used to remove "long tail" low probability responses. [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
|
||||
|
||||
Recommended for advanced use cases only. You usually only need to use `temperature`.
|
||||
Recommended for advanced use cases only.
|
||||
|
||||
- `top_p: optional number`
|
||||
|
||||
Use nucleus sampling.
|
||||
|
||||
In nucleus sampling, we compute the cumulative distribution over all the options for each subsequent token in decreasing probability order and cut it off once it reaches a particular probability specified by `top_p`. You should either alter `temperature` or `top_p`, but not both.
|
||||
In nucleus sampling, we compute the cumulative distribution over all the options for each subsequent token in decreasing probability order and cut it off once it reaches a particular probability specified by `top_p`.
|
||||
|
||||
Recommended for advanced use cases only. You usually only need to use `temperature`.
|
||||
Recommended for advanced use cases only.
|
||||
|
||||
### Returns
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
Upstream snapshot - DO NOT EDIT - run _upstream/sync.sh to refresh
|
||||
Source: https://ai.google.dev/gemini-api/docs/deep-research.md.txt
|
||||
Synced: 2026-04-23
|
||||
Synced: 2026-04-24
|
||||
Consumed by: gemini.interactions.wiretypes.ts, gemini.interactions.parser.ts, gemini.interactionsCreate.ts, gemini.interactionsPoller.ts
|
||||
Companion: ./gemini.interactions.guide.md (the Interactions API guide)
|
||||
-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
Upstream snapshot - DO NOT EDIT - run _upstream/sync.sh to refresh
|
||||
Source: https://ai.google.dev/gemini-api/docs/interactions.md.txt
|
||||
Synced: 2026-04-23
|
||||
Synced: 2026-04-24
|
||||
Consumed by: gemini.interactions.wiretypes.ts, gemini.interactions.parser.ts, gemini.interactionsCreate.ts, gemini.interactionsPoller.ts
|
||||
Companion: ./gemini.interactions.spec.md (the Interactions API reference spec), ./gemini.deep-research.guide.md (the Deep Research agent guide)
|
||||
-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
Upstream snapshot - DO NOT EDIT - run _upstream/sync.sh to refresh
|
||||
Source: https://ai.google.dev/api/interactions-api.md.txt
|
||||
Synced: 2026-04-23
|
||||
Synced: 2026-04-24
|
||||
Consumed by: gemini.interactions.wiretypes.ts, gemini.interactions.parser.ts, gemini.interactionsCreate.ts, gemini.interactionsPoller.ts
|
||||
Companion: ./gemini.interactions.guide.md (the Interactions API guide)
|
||||
-->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
Upstream snapshot - DO NOT EDIT - run _upstream/sync.sh to refresh
|
||||
Source: https://developers.openai.com/api/reference/resources/responses/methods/create/index.md
|
||||
Synced: 2026-04-23
|
||||
Synced: 2026-04-24
|
||||
Consumed by: openai.wiretypes.ts, openai.responses.parser.ts, openai.responsesCreate.ts
|
||||
-->
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ const hotFixAntShipNoEmptyTextBlocks = true; // Replace empty text blocks with a
|
||||
*
|
||||
* ## Updates
|
||||
*
|
||||
* ### 2026-04-24 - API Sync: stop_details for structured refusals
|
||||
* - Response: added `stop_details` ({ type: 'refusal', category: 'cyber'|'bio'|null, explanation: string|null })
|
||||
* - event_MessageDelta.delta: added `stop_details` (arrives alongside stop_reason in streaming)
|
||||
*
|
||||
* ### 2026-03-21 - API Sync: GA tool versions, thinking display, caller updates, cache_control
|
||||
* - Tools: Added web_search_20260209 (GA), web_fetch_20260209/20260309 (GA), code_execution_20260120 (GA REPL)
|
||||
* - Request: Added top-level `cache_control` for automatic caching (Feb 2026)
|
||||
@@ -825,6 +829,16 @@ export namespace AnthropicWire_API_Message_Create {
|
||||
'model_context_window_exceeded',
|
||||
]);
|
||||
|
||||
/**
|
||||
* Structured stop details, paired with stop_reason. Currently only populated when stop_reason === 'refusal'.
|
||||
* Both `type` and `category` are loosely typed for forward-compat - parser warns on unknown `type`.
|
||||
*/
|
||||
const StopDetails_schema = z.object({
|
||||
type: z.enum(['refusal']).or(z.string()),
|
||||
category: z.enum(['cyber', 'bio']).or(z.string()).nullish(),
|
||||
explanation: z.string().nullish(),
|
||||
});
|
||||
|
||||
/// Request
|
||||
|
||||
export type Request = z.infer<typeof Request_schema>;
|
||||
@@ -1030,6 +1044,12 @@ export namespace AnthropicWire_API_Message_Create {
|
||||
// Which custom stop sequence was generated, if any.
|
||||
stop_sequence: z.string().nullable(),
|
||||
|
||||
/**
|
||||
* Structured stop details. Present when stop_reason === 'refusal' (carries category + explanation).
|
||||
* In streaming, stop_details is null at message_start and appears on message_delta alongside stop_reason.
|
||||
*/
|
||||
stop_details: StopDetails_schema.nullish(),
|
||||
|
||||
/**
|
||||
* Billing and rate-limit usage.
|
||||
* Token counts represent the underlying cost to Anthropic's systems.
|
||||
@@ -1088,6 +1108,10 @@ export namespace AnthropicWire_API_Message_Create {
|
||||
delta: z.object({
|
||||
stop_reason: StopReason_schema.nullable(),
|
||||
stop_sequence: z.string().nullable(),
|
||||
/**
|
||||
* Structured stop details - present alongside stop_reason === 'refusal' (category + explanation).
|
||||
*/
|
||||
stop_details: StopDetails_schema.nullish(),
|
||||
/**
|
||||
* Container state updates - present when Skills/code_execution tools are used.
|
||||
* Provides container id/expiry that may differ from message_start if the container was created mid-stream.
|
||||
|
||||
@@ -1183,9 +1183,11 @@ export namespace OpenAIWire_Responses_Items {
|
||||
// [OpenAI 2026-03-xx] DEPRECATED query might not always be present in done event
|
||||
query: z.string().optional(),
|
||||
// the output websites, if any [{"type":"url","url":"https://www.enricoros.com/"}, {"type":"url","url": "https://linkedin.com/in/enricoros/"}, ...]
|
||||
// [OpenAI 2026-04-23, GPT-5.5] new source types: { type: 'api', name: 'oai-calculator' } for hosted-tool invocations (no url)
|
||||
sources: z.array(z.object({
|
||||
type: z.literal('url').optional(), // source type
|
||||
url: z.string(),
|
||||
type: z.enum(['url', 'api']).or(z.string()).optional(), // 'url' (default) | 'api' (GPT-5.5 hosted tools) | future types
|
||||
url: z.string().nullish(), // optional: 'api' sources have no url, only name
|
||||
name: z.string().nullish(), // for 'api' sources (e.g., 'oai-calculator')
|
||||
// [OpenAI 2026-03-xx] not present anymore
|
||||
// title: z.string().optional(),
|
||||
// snippet: z.string().optional(),
|
||||
@@ -1446,6 +1448,7 @@ export namespace OpenAIWire_Responses_Tools {
|
||||
const WebSearchTool_schema = z.object({
|
||||
type: z.enum(['web_search', 'web_search_preview', 'web_search_preview_2025_03_11']),
|
||||
search_context_size: z.enum(['low', 'medium', 'high']).optional(),
|
||||
// [OpenAI 2026-04-23, GPT-5.5] API echoes user_location as `null` (not undefined) when unset - so .nullish()
|
||||
user_location: z.object({
|
||||
type: z.literal('approximate'),
|
||||
// API echoes these as `null` when unset, not omitted - so .nullish()
|
||||
@@ -1453,7 +1456,7 @@ export namespace OpenAIWire_Responses_Tools {
|
||||
country: z.string().nullish(),
|
||||
region: z.string().nullish(),
|
||||
timezone: z.string().nullish(),
|
||||
}).optional(),
|
||||
}).nullish(),
|
||||
external_web_access: z.boolean().optional(),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import { Alert, Box, CircularProgress } from '@mui/joy';
|
||||
import { Alert, Box, Button, CircularProgress } from '@mui/joy';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import TelegramIcon from '@mui/icons-material/Telegram';
|
||||
|
||||
import { ConfirmationModal } from '~/common/components/modals/ConfirmationModal';
|
||||
import { ShortcutKey, useGlobalShortcuts } from '~/common/components/shortcuts/useGlobalShortcuts';
|
||||
@@ -204,13 +206,30 @@ export function BeamView(props: {
|
||||
isMobile={props.isMobile}
|
||||
rayIds={rayIds}
|
||||
showRayAdd={cardAdd}
|
||||
showRaysOps={(isScattering || raysReady < 2) ? undefined : raysReady}
|
||||
hadImportedRays={hadImportedRays}
|
||||
onIncreaseRayCount={handleRayIncreaseCount}
|
||||
onRaysOperation={handleRaysOperation}
|
||||
// linkedLlmId={currentGatherLlmId}
|
||||
/>
|
||||
|
||||
{/* Rays Action Bar (2+ ready beams) - sibling of the grid (NOT a grid child); an in-grid spanning element with gridColumn:'1/-1' pins all auto-fit tracks open and leaves dead whitespace when raysCount < tracksCount. Fixes #1073. */}
|
||||
{(!isScattering && raysReady >= 2) && (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', gap: 2, mx: 'var(--Pad)' }}>
|
||||
<Button size='sm' variant='outlined' color='neutral' onClick={() => handleRaysOperation('copy')} endDecorator={<ContentCopyIcon sx={{ fontSize: 'md' }} />} sx={{
|
||||
backgroundColor: 'background.surface',
|
||||
'&:hover': { backgroundColor: 'background.popup' },
|
||||
}}>
|
||||
Copy {raysReady}
|
||||
</Button>
|
||||
<Button size='sm' variant='outlined' color='success' onClick={() => handleRaysOperation('use')} endDecorator={<TelegramIcon sx={{ fontSize: 'xl' }} />} sx={{
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: 'background.surface',
|
||||
'&:hover': { backgroundColor: 'background.popup' },
|
||||
}}>
|
||||
Use {raysReady === 2 ? 'both' : 'all ' + raysReady} messages
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
{/* Gapper between Rays and Merge, without compromising the auto margin of the Ray Grid */}
|
||||
<Box />
|
||||
@@ -246,9 +265,9 @@ export function BeamView(props: {
|
||||
onPositive={handleStartMergeConfirmation}
|
||||
// lowStakes
|
||||
noTitleBar
|
||||
confirmationText='Some responses are still being generated. Do you want to stop and proceed with merging the available responses now?'
|
||||
positiveActionText='Proceed with Merge'
|
||||
negativeActionText='Wait for All Responses'
|
||||
confirmationText={'Some replies are still generating. Merge what\'s ready?'}
|
||||
positiveActionText='Merge now'
|
||||
negativeActionText='Wait for all'
|
||||
negativeActionStartDecorator={
|
||||
<CircularProgress color='neutral' sx={{ '--CircularProgress-size': '24px', '--CircularProgress-trackThickness': '1px' }} />
|
||||
}
|
||||
|
||||
@@ -149,7 +149,8 @@ export function BeamFusionGrid(props: {
|
||||
</Box> : (
|
||||
<Typography level='body-sm' sx={{ opacity: 0.8 }}>
|
||||
{/*You need two or more replies for a {currentFactory?.shortLabel?.toLocaleLowerCase() ?? ''} merge.*/}
|
||||
Waiting for multiple responses.
|
||||
{/*Waiting for multiple responses.*/}
|
||||
Merge needs 2+ replies. Beam some first.
|
||||
</Typography>
|
||||
)}
|
||||
</BeamCard>
|
||||
|
||||
@@ -49,7 +49,7 @@ export async function executeGatherInstruction(_i: GatherInstruction, inputs: Ex
|
||||
if (!inputs.chatMessages.length)
|
||||
throw new Error('No conversation history available');
|
||||
if (!inputs.rayMessages.length)
|
||||
throw new Error('No responses available');
|
||||
throw new Error('Needs two Beams at least');
|
||||
for (let rayMessage of inputs.rayMessages)
|
||||
if (rayMessage.role !== 'assistant')
|
||||
throw new Error('Invalid response role');
|
||||
|
||||
@@ -58,7 +58,7 @@ export function gatherStartFusion(
|
||||
if (chatMessages.length < 1)
|
||||
return onError('No conversation history available');
|
||||
if (rayMessages.length <= 1)
|
||||
return onError('No responses available');
|
||||
return onError('Needs two Beams at least');
|
||||
if (!initialFusion.llmId)
|
||||
return onError('No Merge model selected');
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ The final output should reflect a deep understanding of the user's preferences a
|
||||
addLabel: 'Add Breakdown',
|
||||
cardTitle: 'Evaluation Table',
|
||||
Icon: TableViewRoundedIcon as typeof SvgIcon,
|
||||
description: 'Analyzes and compares AI responses, offering a structured framework to support your response choice.',
|
||||
description: 'Analyzes and compares replies, with a structured framework to support your choice.',
|
||||
createInstructions: () => [
|
||||
{
|
||||
type: 'gather',
|
||||
|
||||
@@ -3,8 +3,6 @@ import * as React from 'react';
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { Box, Button } from '@mui/joy';
|
||||
import AddCircleOutlineRoundedIcon from '@mui/icons-material/AddCircleOutlineRounded';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import TelegramIcon from '@mui/icons-material/Telegram';
|
||||
|
||||
import type { BeamStoreApi } from '../store-beam.hooks';
|
||||
import { BeamCard } from '../BeamCard';
|
||||
@@ -32,10 +30,8 @@ export function BeamRayGrid(props: {
|
||||
hadImportedRays: boolean,
|
||||
isMobile: boolean,
|
||||
onIncreaseRayCount: () => void,
|
||||
onRaysOperation: (operation: 'copy' | 'use') => void,
|
||||
rayIds: string[],
|
||||
showRayAdd: boolean,
|
||||
showRaysOps: undefined | number,
|
||||
}) {
|
||||
|
||||
const raysCount = props.rayIds.length;
|
||||
@@ -71,25 +67,6 @@ export function BeamRayGrid(props: {
|
||||
</BeamCard>
|
||||
)}
|
||||
|
||||
{/* Multi-Use and Copy Buttons */}
|
||||
{!!props.showRaysOps && (
|
||||
<Box sx={{ gridColumn: '1 / -1', display: 'flex', justifyContent: 'center', gap: 2, mt: 2 }}>
|
||||
<Button size='sm' variant='outlined' color='neutral' onClick={() => props.onRaysOperation('copy')} endDecorator={<ContentCopyIcon sx={{ fontSize: 'md' }} />} sx={{
|
||||
backgroundColor: 'background.surface',
|
||||
'&:hover': { backgroundColor: 'background.popup' },
|
||||
}}>
|
||||
Copy {props.showRaysOps}
|
||||
</Button>
|
||||
<Button size='sm' variant='outlined' color='success' onClick={() => props.onRaysOperation('use')} endDecorator={<TelegramIcon sx={{ fontSize: 'xl' }} />} sx={{
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: 'background.surface',
|
||||
'&:hover': { backgroundColor: 'background.popup' },
|
||||
}}>
|
||||
Use {props.showRaysOps == 2 ? 'both' : 'all ' + props.showRaysOps} messages
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/*/!* Takes a full row *!/*/}
|
||||
{/*<Divider sx={{*/}
|
||||
{/* gridColumn: '1 / -1',*/}
|
||||
|
||||
@@ -72,7 +72,7 @@ const geminiExpFree: ModelDescriptionSchema['chatPrice'] = {
|
||||
};
|
||||
|
||||
|
||||
// Pricing based on https://ai.google.dev/pricing (Apr 22, 2026)
|
||||
// Pricing based on https://ai.google.dev/pricing (Apr 24, 2026)
|
||||
|
||||
const gemini31FlashLitePricing: ModelDescriptionSchema['chatPrice'] = {
|
||||
input: 0.25, // text/image/video; audio is $0.50 but we don't differentiate yet
|
||||
@@ -262,8 +262,10 @@ const _knownGeminiModels: ({
|
||||
|
||||
/// Generation 3.0
|
||||
|
||||
// 3.0 Pro (Preview) - Released November 18, 2025; DEPRECATED: shutdown March 9, 2026 (still served by API as of Apr 17, 2026)
|
||||
// 3.0 Pro (Preview) - Released November 18, 2025; SHUT DOWN March 9, 2026 - now silently routed to gemini-3.1-pro-preview
|
||||
// Kept hidden (still returned by API) to avoid confusing users with a silently-redirected model.
|
||||
{
|
||||
hidden: true, // March 9, 2026: API silently routes 'gemini-3-pro-preview' to 'gemini-3.1-pro-preview' - hide to prevent user confusion
|
||||
id: 'models/gemini-3-pro-preview',
|
||||
labelOverride: 'Gemini 3 Pro Preview',
|
||||
isPreview: true,
|
||||
@@ -335,6 +337,7 @@ const _knownGeminiModels: ({
|
||||
|
||||
// 2.5 Pro (Stable) - Released June 17, 2025; DEPRECATED: shutdown June 17, 2026
|
||||
{
|
||||
hidden: true, // outperformed by 3.1 Pro (1493) and even 3 Flash (1474) - deprecated in 2 months
|
||||
id: 'models/gemini-2.5-pro',
|
||||
labelOverride: 'Gemini 2.5 Pro',
|
||||
deprecated: '2026-06-17',
|
||||
@@ -412,6 +415,7 @@ const _knownGeminiModels: ({
|
||||
|
||||
// 2.5 Flash
|
||||
{
|
||||
hidden: true, // outperformed by 3 Flash Preview (1474 vs 1411) - deprecated in 2 months
|
||||
id: 'models/gemini-2.5-flash',
|
||||
labelOverride: 'Gemini 2.5 Flash',
|
||||
deprecated: '2026-06-17',
|
||||
@@ -467,6 +471,7 @@ const _knownGeminiModels: ({
|
||||
|
||||
// 2.5 Flash-Based: Gemini Robotics-ER 1.5 Preview - Released September 25, 2025; DEPRECATED: shutdown April 30, 2026
|
||||
{
|
||||
hidden: true, // superseded by Robotics-ER 1.6 - shutdown April 30, 2026
|
||||
id: 'models/gemini-robotics-er-1.5-preview',
|
||||
labelOverride: 'Gemini Robotics-ER 1.5 Preview',
|
||||
isPreview: true,
|
||||
@@ -573,6 +578,7 @@ const _knownGeminiModels: ({
|
||||
|
||||
// 2.0 Flash - DEPRECATED: shutdown June 1, 2026 (announced Feb 18, 2026)
|
||||
{
|
||||
hidden: true, // outclassed by all Flash models in 2.5/3.x series - shutdown in ~5 weeks
|
||||
id: 'models/gemini-2.0-flash-001',
|
||||
deprecated: '2026-06-01',
|
||||
chatPrice: gemini20FlashPricing,
|
||||
@@ -580,6 +586,7 @@ const _knownGeminiModels: ({
|
||||
benchmark: { cbaElo: 1360 }, // gemini-2.0-flash-001
|
||||
},
|
||||
{
|
||||
hidden: true, // outclassed by all Flash models in 2.5/3.x series - shutdown in ~5 weeks
|
||||
id: 'models/gemini-2.0-flash',
|
||||
symLink: 'models/gemini-2.0-flash-001',
|
||||
deprecated: '2026-06-01',
|
||||
@@ -591,6 +598,7 @@ const _knownGeminiModels: ({
|
||||
|
||||
// 2.0 Flash Lite - DEPRECATED: shutdown June 1, 2026 (announced Feb 18, 2026)
|
||||
{
|
||||
hidden: true, // outclassed by 2.5/3.1 Flash-Lite - shutdown in ~5 weeks
|
||||
id: 'models/gemini-2.0-flash-lite',
|
||||
chatPrice: gemini20FlashLitePricing,
|
||||
symLink: 'models/gemini-2.0-flash-lite-001',
|
||||
@@ -599,6 +607,7 @@ const _knownGeminiModels: ({
|
||||
benchmark: { cbaElo: 1310 },
|
||||
},
|
||||
{
|
||||
hidden: true, // outclassed by 2.5/3.1 Flash-Lite - shutdown in ~5 weeks
|
||||
id: 'models/gemini-2.0-flash-lite-001',
|
||||
chatPrice: gemini20FlashLitePricing,
|
||||
deprecated: '2026-06-01',
|
||||
|
||||
@@ -12,6 +12,23 @@ import { fromManualMapping, KnownModel, llmDevCheckModels_DEV, ManualMappings }
|
||||
// OpenAI Model Variants
|
||||
export const hardcodedOpenAIVariants: ModelVariantMap = {
|
||||
|
||||
// GPT-5.5 with reasoning disabled (non-thinking) - supports temperature control
|
||||
'gpt-5.5-2026-04-23': {
|
||||
idVariant: '::thinking-none',
|
||||
label: 'GPT-5.5 (No-thinking)',
|
||||
hidden: true, // hidden by default as redundant, user can unhide in settings
|
||||
description: 'Supports temperature control for creative applications. GPT-5.5 with reasoning disabled (reasoning_effort=none).',
|
||||
interfaces: [LLM_IF_OAI_Responses, LLM_IF_OAI_Chat, LLM_IF_OAI_Vision, LLM_IF_OAI_Fn, LLM_IF_OAI_PromptCaching], // NO LLM_IF_OAI_Reasoning, NO LLM_IF_HOTFIX_NoTemperature
|
||||
parameterSpecs: [
|
||||
{ paramId: 'llmVndOaiEffort', enumValues: ['none', 'low', 'medium', 'high', 'xhigh'], initialValue: 'none', hidden: true }, // factory 'none', not changeable
|
||||
{ paramId: 'llmVndOaiWebSearchContext' },
|
||||
{ paramId: 'llmVndOaiVerbosity' },
|
||||
{ paramId: 'llmVndOaiImageGeneration' },
|
||||
{ paramId: 'llmVndOaiCodeInterpreter' },
|
||||
{ paramId: 'llmForceNoStream' },
|
||||
],
|
||||
},
|
||||
|
||||
// GPT-5.4 with reasoning disabled (non-thinking) - supports temperature control
|
||||
'gpt-5.4-2026-03-05': {
|
||||
idVariant: '::thinking-none',
|
||||
@@ -88,6 +105,58 @@ const PS_DEEP_RESEARCH = [{ paramId: 'llmVndOaiWebSearchContext' as const, initi
|
||||
// https://platform.openai.com/docs/pricing
|
||||
export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
/// GPT-5.5 series - Released April 23, 2026
|
||||
|
||||
// GPT-5.5
|
||||
{
|
||||
idPrefix: 'gpt-5.5-2026-04-23',
|
||||
label: 'GPT-5.5 (2026-04-23)',
|
||||
description: 'New baseline for complex production workflows. Stronger task execution, more precise tool use, more efficient reasoning with fewer tokens. 1M token context.',
|
||||
contextWindow: 1050000,
|
||||
maxCompletionTokens: 128000,
|
||||
interfaces: [LLM_IF_OAI_Responses, ...IFS_CHAT_CACHE_REASON, LLM_IF_HOTFIX_NoTemperature],
|
||||
parameterSpecs: [
|
||||
{ paramId: 'llmVndOaiEffort', enumValues: ['none', 'low', 'medium', 'high', 'xhigh'], initialValue: 'medium' }, // medium is the new default for 5.5
|
||||
{ paramId: 'llmVndOaiWebSearchContext' },
|
||||
{ paramId: 'llmVndOaiVerbosity' },
|
||||
{ paramId: 'llmVndOaiImageGeneration' },
|
||||
{ paramId: 'llmVndOaiCodeInterpreter' },
|
||||
{ paramId: 'llmForceNoStream' },
|
||||
],
|
||||
chatPrice: { input: 5, cache: { cType: 'oai-ac', read: 0.5 }, output: 30 },
|
||||
// benchmark: TBD - no CBA ELO yet
|
||||
},
|
||||
{
|
||||
idPrefix: 'gpt-5.5',
|
||||
label: 'GPT-5.5',
|
||||
symLink: 'gpt-5.5-2026-04-23',
|
||||
},
|
||||
|
||||
// GPT-5.5 Pro
|
||||
{
|
||||
idPrefix: 'gpt-5.5-pro-2026-04-23',
|
||||
label: 'GPT-5.5 Pro (2026-04-23)',
|
||||
description: 'Most capable model for complex tasks. Uses more compute for smarter, more precise responses on the hardest problems.',
|
||||
contextWindow: 1050000,
|
||||
maxCompletionTokens: 272000,
|
||||
interfaces: [LLM_IF_OAI_Responses, ...IFS_CHAT_MIN, LLM_IF_OAI_Reasoning, LLM_IF_HOTFIX_NoTemperature],
|
||||
parameterSpecs: [
|
||||
{ paramId: 'llmVndOaiEffort', enumValues: ['medium', 'high', 'xhigh'] }, // Pro: no low/none
|
||||
{ paramId: 'llmVndOaiWebSearchContext' },
|
||||
{ paramId: 'llmVndOaiVerbosity' },
|
||||
{ paramId: 'llmVndOaiImageGeneration' },
|
||||
{ paramId: 'llmForceNoStream' },
|
||||
],
|
||||
chatPrice: { input: 30, output: 180 },
|
||||
// benchmark: TBD
|
||||
},
|
||||
{
|
||||
idPrefix: 'gpt-5.5-pro',
|
||||
label: 'GPT-5.5 Pro',
|
||||
symLink: 'gpt-5.5-pro-2026-04-23',
|
||||
},
|
||||
|
||||
|
||||
/// GPT-5.4 series - Released March 5, 2026
|
||||
|
||||
// GPT-5.4
|
||||
@@ -250,6 +319,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.2
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5.2-2025-12-11',
|
||||
label: 'GPT-5.2 (2025-12-11)',
|
||||
description: 'Most capable model for professional work and long-running agents. Improvements in general intelligence, long-context, agentic tool-calling, and vision.',
|
||||
@@ -268,6 +338,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
benchmark: { cbaElo: 1441 }, // gpt-5.2-high
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5.2',
|
||||
label: 'GPT-5.2',
|
||||
symLink: 'gpt-5.2-2025-12-11',
|
||||
@@ -275,6 +346,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.2 Codex
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Codex
|
||||
idPrefix: 'gpt-5.2-codex',
|
||||
label: 'GPT-5.2 Codex',
|
||||
description: 'GPT-5.2 optimized for long-horizon, agentic coding tasks in Codex or similar environments. Supports low, medium, high, and xhigh reasoning effort settings.',
|
||||
@@ -293,6 +365,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.2 Chat Latest
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Instant
|
||||
idPrefix: 'gpt-5.2-chat-latest',
|
||||
label: 'GPT-5.2 Instant',
|
||||
description: 'GPT-5.2 model powering ChatGPT. Fast, capable for everyday work with clear improvements in info-seeking, how-tos, technical writing.',
|
||||
@@ -311,6 +384,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.2 Pro
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5 Pro
|
||||
idPrefix: 'gpt-5.2-pro-2025-12-11',
|
||||
label: 'GPT-5.2 Pro (2025-12-11)',
|
||||
description: 'Smartest and most trustworthy option for difficult questions. Uses more compute for harder thinking on complex domains like programming.',
|
||||
@@ -328,6 +402,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// benchmark: TBD
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5 Pro
|
||||
idPrefix: 'gpt-5.2-pro',
|
||||
label: 'GPT-5.2 Pro',
|
||||
symLink: 'gpt-5.2-pro-2025-12-11',
|
||||
@@ -338,6 +413,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.1
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5.1-2025-11-13',
|
||||
label: 'GPT-5.1 (2025-11-13)',
|
||||
description: 'The best model for coding and agentic tasks with configurable reasoning effort.',
|
||||
@@ -355,6 +431,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
benchmark: { cbaElo: 1455 }, // gpt-5.1-high
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5.1',
|
||||
label: 'GPT-5.1',
|
||||
symLink: 'gpt-5.1-2025-11-13',
|
||||
@@ -362,6 +439,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.1 Chat Latest
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Instant
|
||||
idPrefix: 'gpt-5.1-chat-latest',
|
||||
label: 'GPT-5.1 Instant',
|
||||
description: 'GPT-5.1 Instant with adaptive reasoning. More conversational with improved instruction following.',
|
||||
@@ -381,6 +459,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5.1 Codex Max
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Codex
|
||||
idPrefix: 'gpt-5.1-codex-max',
|
||||
label: 'GPT-5.1 Codex Max',
|
||||
description: 'Our most intelligent coding model optimized for long-horizon, agentic coding tasks.',
|
||||
@@ -398,6 +477,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
},
|
||||
// GPT-5.1 Codex
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Codex
|
||||
idPrefix: 'gpt-5.1-codex',
|
||||
label: 'GPT-5.1 Codex',
|
||||
description: 'A version of GPT-5.1 optimized for agentic coding tasks in Codex or similar environments.',
|
||||
@@ -415,6 +495,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
},
|
||||
// GPT-5.1 Codex Mini
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.3 Codex
|
||||
idPrefix: 'gpt-5.1-codex-mini',
|
||||
label: 'GPT-5.1 Codex Mini',
|
||||
description: 'Smaller, faster version of GPT-5.1 Codex for efficient coding tasks.',
|
||||
@@ -436,6 +517,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5-2025-08-07',
|
||||
label: 'GPT-5 (2025-08-07)',
|
||||
description: 'The best model for coding and agentic tasks across domains.',
|
||||
@@ -453,6 +535,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
benchmark: { cbaElo: 1433 }, // gpt-5-high
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5
|
||||
idPrefix: 'gpt-5',
|
||||
label: 'GPT-5',
|
||||
symLink: 'gpt-5-2025-08-07',
|
||||
@@ -460,6 +543,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5 Pro
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5 Pro
|
||||
idPrefix: 'gpt-5-pro-2025-10-06',
|
||||
label: 'GPT-5 Pro (2025-10-06)',
|
||||
description: 'Version of GPT-5 that uses more compute to produce smarter and more precise responses. Designed for tough problems.',
|
||||
@@ -471,6 +555,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// benchmark: has not been measured yet
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4/5.5 Pro
|
||||
idPrefix: 'gpt-5-pro',
|
||||
label: 'GPT-5 Pro',
|
||||
symLink: 'gpt-5-pro-2025-10-06',
|
||||
@@ -511,6 +596,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5 Search API
|
||||
{
|
||||
hidden: true, // poor quality - use llmVndOaiWebSearchContext on regular models instead
|
||||
idPrefix: 'gpt-5-search-api-2025-10-14',
|
||||
label: 'GPT-5 Search API (2025-10-14)',
|
||||
description: 'Updated web search model in Chat Completions API. 60% cheaper with domain filtering support.',
|
||||
@@ -522,6 +608,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// benchmark: TBD
|
||||
},
|
||||
{
|
||||
hidden: true, // poor quality - use llmVndOaiWebSearchContext on regular models instead
|
||||
idPrefix: 'gpt-5-search-api',
|
||||
label: 'GPT-5 Search API',
|
||||
symLink: 'gpt-5-search-api-2025-10-14',
|
||||
@@ -529,6 +616,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5 mini
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4 Mini
|
||||
idPrefix: 'gpt-5-mini-2025-08-07',
|
||||
label: 'GPT-5 Mini (2025-08-07)',
|
||||
description: 'A faster, more cost-efficient version of GPT-5 for well-defined tasks.',
|
||||
@@ -540,6 +628,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
benchmark: { cbaElo: 1390 }, // gpt-5-mini-high
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4 Mini
|
||||
idPrefix: 'gpt-5-mini',
|
||||
label: 'GPT-5 Mini',
|
||||
symLink: 'gpt-5-mini-2025-08-07',
|
||||
@@ -547,6 +636,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// GPT-5 nano
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4 Nano
|
||||
idPrefix: 'gpt-5-nano-2025-08-07',
|
||||
label: 'GPT-5 Nano (2025-08-07)',
|
||||
description: 'Fastest, most cost-efficient version of GPT-5 for summarization and classification tasks.',
|
||||
@@ -558,6 +648,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
benchmark: { cbaElo: 1337 }, // gpt-5-nano-high
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT-5.4 Nano
|
||||
idPrefix: 'gpt-5-nano',
|
||||
label: 'GPT-5 Nano',
|
||||
symLink: 'gpt-5-nano-2025-08-07',
|
||||
@@ -608,8 +699,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// o4-mini-deep-research - (v1/responses API)
|
||||
{
|
||||
idPrefix: 'o4-mini-deep-research-2025-06-26',
|
||||
label: 'o4 Mini Deep Research (2025-06-26)',
|
||||
description: 'Faster, more affordable deep research model for complex, multi-step research tasks.',
|
||||
label: 'o4 Mini Deep Research [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Faster, more affordable deep research model for complex, multi-step research tasks. [Shutdown: 2026-07-23 - migrate to GPT-5.5 with web search.]',
|
||||
contextWindow: 200000,
|
||||
maxCompletionTokens: 100000,
|
||||
interfaces: [LLM_IF_OAI_Responses, ...IFS_CHAT_CACHE_REASON, LLM_IF_HOTFIX_NoTemperature],
|
||||
@@ -625,8 +717,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
/// o4-mini
|
||||
{
|
||||
idPrefix: 'o4-mini-2025-04-16',
|
||||
label: 'o4 Mini (2025-04-16)',
|
||||
description: 'Latest o4-mini model. Optimized for fast, effective reasoning with exceptionally efficient performance in coding and visual tasks.',
|
||||
label: 'o4 Mini [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Latest o4-mini model. Optimized for fast, effective reasoning with exceptionally efficient performance in coding and visual tasks. [Shutdown: 2026-10-23 - migrate to GPT-5.4 Mini.]',
|
||||
contextWindow: 200000,
|
||||
maxCompletionTokens: 100000,
|
||||
interfaces: IFS_CHAT_CACHE_REASON,
|
||||
@@ -643,8 +736,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// o3-deep-research - (v1/responses API)
|
||||
{
|
||||
idPrefix: 'o3-deep-research-2025-06-26',
|
||||
label: 'o3 Deep Research (2025-06-26)',
|
||||
description: 'Our most powerful deep research model for complex, multi-step research tasks.',
|
||||
label: 'o3 Deep Research [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Our most powerful deep research model for complex, multi-step research tasks. [Shutdown: 2026-07-23 - migrate to GPT-5.5 Pro with web search.]',
|
||||
contextWindow: 200000,
|
||||
maxCompletionTokens: 100000,
|
||||
interfaces: [LLM_IF_OAI_Responses, ...IFS_CHAT_CACHE_REASON, LLM_IF_HOTFIX_NoTemperature],
|
||||
@@ -696,8 +790,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// o3-mini
|
||||
{
|
||||
idPrefix: 'o3-mini-2025-01-31',
|
||||
label: 'o3 Mini (2025-01-31)',
|
||||
description: 'Latest o3-mini model snapshot. High intelligence at the same cost and latency targets of o1-mini. Excels at science, math, and coding tasks.',
|
||||
label: 'o3 Mini [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Latest o3-mini model snapshot. High intelligence at the same cost and latency targets of o1-mini. Excels at science, math, and coding tasks. [Shutdown: 2026-10-23 - migrate to GPT-5.4 Mini.]',
|
||||
contextWindow: 200000,
|
||||
maxCompletionTokens: 100000,
|
||||
interfaces: [LLM_IF_OAI_Chat, LLM_IF_OAI_Fn, LLM_IF_OAI_PromptCaching, LLM_IF_OAI_Reasoning, LLM_IF_HOTFIX_StripImages],
|
||||
@@ -733,8 +828,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// o1
|
||||
{
|
||||
idPrefix: 'o1-2024-12-17',
|
||||
label: 'o1 (2024-12-17)',
|
||||
description: 'Previous full o-series reasoning model.',
|
||||
label: 'o1 [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Previous full o-series reasoning model. [Shutdown: 2026-10-23 - migrate to GPT-5.5 or o3.]',
|
||||
contextWindow: 200000,
|
||||
maxCompletionTokens: 100000,
|
||||
interfaces: IFS_CHAT_CACHE_REASON,
|
||||
@@ -788,8 +884,9 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// GPT-4.1 nano
|
||||
{
|
||||
idPrefix: 'gpt-4.1-nano-2025-04-14',
|
||||
label: 'GPT-4.1 Nano (2025-04-14)',
|
||||
description: 'Fastest, most cost-effective GPT 4.1 model. Delivers exceptional performance with low latency, ideal for tasks like classification or autocompletion.',
|
||||
label: 'GPT-4.1 Nano [Deprecated]',
|
||||
isLegacy: true,
|
||||
description: 'Fastest, most cost-effective GPT 4.1 model. Delivers exceptional performance with low latency, ideal for tasks like classification or autocompletion. [Shutdown: 2026-10-23 - migrate to GPT-5.4 Nano.]',
|
||||
contextWindow: 1047576,
|
||||
maxCompletionTokens: 32768,
|
||||
interfaces: IFS_CHAT_CACHE,
|
||||
@@ -819,6 +916,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
|
||||
// gpt-audio
|
||||
{
|
||||
hidden: true, // superseded by GPT Audio 1.5
|
||||
idPrefix: 'gpt-audio-2025-08-28',
|
||||
label: 'GPT Audio (2025-08-28)',
|
||||
description: 'First generally available audio model. Accepts audio inputs and outputs, and can be used in the Chat Completions REST API.',
|
||||
@@ -829,6 +927,7 @@ export const _knownOpenAIChatModels: ManualMappings = [
|
||||
// benchmark: TBD
|
||||
},
|
||||
{
|
||||
hidden: true, // superseded by GPT Audio 1.5
|
||||
idPrefix: 'gpt-audio',
|
||||
label: 'GPT Audio',
|
||||
symLink: 'gpt-audio-2025-08-28',
|
||||
@@ -1220,6 +1319,12 @@ export function openAIInjectVariants(acc: ModelDescriptionSchema[], model: Model
|
||||
|
||||
|
||||
const _manualOrderingIdPrefixes = [
|
||||
// GPT-5.5
|
||||
'gpt-5.5-20',
|
||||
'gpt-5.5-pro-20',
|
||||
'gpt-5.5-pro',
|
||||
'gpt-5.5-chat-latest',
|
||||
'gpt-5.5',
|
||||
// GPT-5.4
|
||||
'gpt-5.4-20',
|
||||
'gpt-5.4-pro-20',
|
||||
@@ -1419,6 +1524,7 @@ export function llmOrtOaiLookup(orModelName: string): OrtVendorLookupResult | un
|
||||
// typemap to known models
|
||||
const ortOaiRefMap: Record<string, string | null> = {
|
||||
// renames
|
||||
'gpt-5.5-chat': 'gpt-5.5-2026-04-23', // no chat-latest yet, map to snapshot
|
||||
'gpt-5.4-chat': 'gpt-5.4-2026-03-05', // no chat-latest yet, map to snapshot
|
||||
'gpt-5.3-chat': 'gpt-5.3-chat-latest',
|
||||
'gpt-5.2-chat': 'gpt-5.2-chat-latest',
|
||||
|
||||
Reference in New Issue
Block a user