Files
hapi/shared/src/flavors.ts
T
SSU-WEI HUANGandGitHub b9eed7c071 feat: add Grok Build support (#1030)
* test: define Grok Build integration behavior

* feat: add Grok Build agent integration

* test: cover Grok permissions and resume paths

* docs: add Grok Build setup guide

* fix: scope Grok ACP discovery to session cwd

* fix: align Grok permission UI semantics

* docs: clarify Grok runner setup

* test: require Grok create model and effort options

* feat: add Grok create model and effort pickers

* test: define Grok runtime parity behavior

* feat: add Grok runtime ACP controls and discovery

* fix: tighten Grok runtime controls

* fix: suppress nonfatal Grok title quota errors

* feat: support Grok Auto permission mode

* feat: forward ACP native session titles for Grok

* fix: guard Grok Windows shell arguments
2026-07-13 08:41:30 +08:00

66 lines
2.1 KiB
TypeScript

import type { AgentFlavor } from './modes'
// --- Capability constants (prevent literal scattering) ---
export const Capabilities = {
ModelChange: 'model-change',
Effort: 'effort',
} as const
export type Capability = typeof Capabilities[keyof typeof Capabilities]
// --- Per-flavor capability sets ---
const FLAVOR_CAPS: Record<AgentFlavor, ReadonlySet<Capability>> = {
claude: new Set([Capabilities.ModelChange, Capabilities.Effort]),
gemini: new Set([Capabilities.ModelChange]),
kimi: new Set([Capabilities.ModelChange]),
grok: new Set([Capabilities.ModelChange, Capabilities.Effort]),
codex: new Set([Capabilities.ModelChange]),
cursor: new Set([Capabilities.ModelChange]),
opencode: new Set([Capabilities.ModelChange]),
pi: new Set([Capabilities.ModelChange, Capabilities.Effort]),
}
// --- Flavor display names ---
const FLAVOR_LABELS: Record<AgentFlavor, string> = {
claude: 'Claude',
gemini: 'Gemini',
kimi: 'Kimi',
grok: 'Grok Build',
codex: 'Codex',
cursor: 'Cursor',
opencode: 'OpenCode',
pi: 'Pi',
}
// --- Query functions ---
export function isKnownFlavor(flavor: string | null | undefined): flavor is AgentFlavor {
return typeof flavor === 'string' && Object.hasOwn(FLAVOR_CAPS, flavor)
}
export function hasCapability(flavor: string | null | undefined, cap: Capability): boolean {
if (!isKnownFlavor(flavor)) return false
return FLAVOR_CAPS[flavor].has(cap)
}
export function getFlavorLabel(flavor: string | null | undefined): string {
if (!isKnownFlavor(flavor)) return 'Unknown'
return FLAVOR_LABELS[flavor]
}
// --- Convenience functions ---
export function supportsModelChange(flavor: string | null | undefined): boolean {
return hasCapability(flavor, Capabilities.ModelChange)
}
export function supportsEffort(flavor: string | null | undefined): boolean {
return hasCapability(flavor, Capabilities.Effort)
}
export function isCodexFamilyFlavor(flavor: string | null | undefined): boolean {
return flavor === 'codex'
|| flavor === 'gemini'
|| flavor === 'grok'
|| flavor === 'kimi'
|| flavor === 'opencode'
}