mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
* fix(native-chat): restore Codex model picker dispatch * fix(native-chat): type Codex effort picker command
96 lines
3.4 KiB
TypeScript
96 lines
3.4 KiB
TypeScript
import type { AgentType } from './agent-status-types'
|
|
import {
|
|
CLAUDE_SESSION_OPTION_CATALOG,
|
|
CODEX_SESSION_OPTION_CATALOG,
|
|
createClaudeCatalogOptions
|
|
} from './agent-session-option-catalog-claude-codex'
|
|
import {
|
|
CURSOR_SESSION_OPTION_CATALOG,
|
|
GEMINI_SESSION_OPTION_CATALOG
|
|
} from './agent-session-option-catalog-gemini-cursor'
|
|
import { GROK_SESSION_OPTION_CATALOG } from './agent-session-option-catalog-grok'
|
|
import type {
|
|
AgentSessionOptionCatalog,
|
|
AgentSessionOptionCatalogMap,
|
|
CatalogModel,
|
|
CatalogOption
|
|
} from './agent-session-option-catalog-types'
|
|
import type { SessionOptionValue } from './native-chat-session-options'
|
|
|
|
export type {
|
|
AgentSessionOptionCatalog,
|
|
CatalogAgentInteractionDetection,
|
|
CatalogCommandDelivery,
|
|
CatalogMidSessionApply,
|
|
CatalogModel,
|
|
CatalogOption,
|
|
CatalogOptionApply
|
|
} from './agent-session-option-catalog-types'
|
|
export { createClaudeCatalogOptions }
|
|
|
|
const CATALOGS: AgentSessionOptionCatalogMap = {
|
|
claude: CLAUDE_SESSION_OPTION_CATALOG,
|
|
codex: CODEX_SESSION_OPTION_CATALOG,
|
|
gemini: GEMINI_SESSION_OPTION_CATALOG,
|
|
cursor: CURSOR_SESSION_OPTION_CATALOG,
|
|
grok: GROK_SESSION_OPTION_CATALOG
|
|
}
|
|
|
|
export function getAgentSessionOptionCatalog(agent: AgentType): AgentSessionOptionCatalog | null {
|
|
return CATALOGS[agent] ?? null
|
|
}
|
|
|
|
export function findCatalogModel(
|
|
catalog: AgentSessionOptionCatalog,
|
|
modelId: string
|
|
): CatalogModel | undefined {
|
|
return catalog.models.find((model) => model.id === modelId)
|
|
}
|
|
|
|
export function findCatalogOption(
|
|
model: CatalogModel | undefined,
|
|
optionId: string
|
|
): CatalogOption | undefined {
|
|
return model?.options.find((option) => option.id === optionId)
|
|
}
|
|
|
|
/** Merge live rows over the static seed while retaining cataloged option mappings. */
|
|
export function mergeCatalogModels(
|
|
seed: readonly CatalogModel[],
|
|
discovered: readonly CatalogModel[]
|
|
): CatalogModel[] {
|
|
const discoveredById = new Map(discovered.map((model) => [model.id, model]))
|
|
const merged = seed.map((model) => {
|
|
const live = discoveredById.get(model.id)
|
|
if (!live) {
|
|
return model
|
|
}
|
|
discoveredById.delete(model.id)
|
|
return { ...model, ...live, options: model.options }
|
|
})
|
|
return [...merged, ...discoveredById.values()]
|
|
}
|
|
|
|
/** Discovery decides membership; the seed keeps its option menus, which discovery never carries.
|
|
* Why: an unseeded model inherits the default seed's options because these catalogs' options are
|
|
* global CLI flags, not per-model capabilities — dropping them would hide the picker entirely. */
|
|
export function mergeDiscoveredAuthoritativeModels(
|
|
seed: readonly CatalogModel[],
|
|
discovered: readonly CatalogModel[]
|
|
): CatalogModel[] {
|
|
const inheritedOptions = (seed.find((model) => model.isDefault) ?? seed[0])?.options ?? []
|
|
return discovered.map((disc) => {
|
|
const seedMatch = seed.find((model) => model.id === disc.id)
|
|
const { isDefault: _seeded, ...merged } = seedMatch
|
|
? { ...seedMatch, ...disc, options: seedMatch.options }
|
|
: { ...disc, options: inheritedOptions }
|
|
// Why: the probe reports which id the CLI defaults to today; a seed flag frozen at
|
|
// release would keep naming the old one after the account's default moves.
|
|
return disc.isDefault ? { ...merged, isDefault: true } : merged
|
|
})
|
|
}
|
|
|
|
export function sessionOptionValueIsValid(value: unknown): value is SessionOptionValue {
|
|
return typeof value === 'string' || typeof value === 'boolean'
|
|
}
|