mirror of
https://github.com/stablyai/orca.git
synced 2026-09-25 08:02:31 +00:00
#14397 split `shared/types.ts` into 46 per-domain modules but kept the path as a re-export barrel so the import sites did not have to change. This removes the barrel: every consumer now imports from the module that actually declares the type, and `src/shared/types.ts` is deleted. Barrels hide where a type lives, make every consumer look like it depends on the whole domain, and let an unrelated edit invalidate a module that ~2,000 files transitively import. 2,323 import declarations across 2,321 files. Rewritten mechanically: each specifier was resolved to an absolute path via the TypeScript AST and recomputed, rather than string-substituted, so alias forms (`@/../../shared/ types`) and per-specifier `type` modifiers survive. Four cases the mechanical pass had to handle, each found by a gate rather than by reading the diff: - Modules inside `src/shared` import the barrel as `./types`, not `shared/types`. A pre-filter on the latter string skipped 176 of them and left imports dangling at a deleted file, which surfaced as confusing `Property 'x' is optional in type 'Repo' but required in Pick<Repo, ...>` errors rather than "module not found". - The barrel RENAMED one type on the way through (`WorkspaceSource as WorkspaceCreateTelemetrySource`), so the original name in the owning module has to be re-aliased at each consumer. - Three test files put `;(globalThis as ...)` on the line after the import. TypeScript parses that `;` as the import statement's terminator, so replacing through `statement.getEnd()` deletes it and breaks ASI. The rewrite now stops at the module specifier. - A file that already imported directly from a module got a SECOND import from it, because the barrel re-exported those same names — which trips `import/no-duplicates` under `--deny-warnings`. A post-pass merges declarations sharing a specifier and type-only-ness; the `import type` plus `import` pair from one module is left alone, since that form is allowed. Splitting one barrel import into several genuinely adds lines, which pushed `terminal-layout-pty-ownership.ts` to 301 counted lines: its 107-character import must wrap, and neither local type collapses onto one line (101 and 116 characters). Rather than contort a type declaration to fit a line budget, `collectLeafIds` and `pruneLeaves` move to `terminal-pane-layout-tree.ts` — they are pure structural operations on the layout tree and independent of PTY ownership. `visible-worktrees.ts` similarly loses its own mini-barrel re-export of `isDefaultBranchWorkspace`, with the four real consumers repointed at the declaring module. No `max-lines` bypass added. Verified: cold `tsc --noEmit` green on node, cli, and web (buildinfo deleted first — these projects are `composite: true` and reuse stale caches); the full `pnpm lint` green, not just bare oxlint — the narrower local check is what let the duplicate imports reach CI; max-lines ratchet OK at 344.
100 lines
2.6 KiB
TypeScript
100 lines
2.6 KiB
TypeScript
import type { TuiAgent } from './tui-agent'
|
|
import { isTuiAgent } from './tui-agent-config'
|
|
|
|
// Keep this order in sync with the desktop agent catalog. It defines the
|
|
// automatic fallback priority when the user has not chosen a default agent.
|
|
export const TUI_AGENT_AUTO_PICK_ORDER = [
|
|
'claude',
|
|
'claude-agent-teams',
|
|
'openclaude',
|
|
'codex',
|
|
'grok',
|
|
'copilot',
|
|
'opencode',
|
|
'mimo-code',
|
|
'ante',
|
|
'trae',
|
|
'pi',
|
|
'omp',
|
|
'prime-agent',
|
|
'gemini',
|
|
'antigravity',
|
|
'aider',
|
|
'goose',
|
|
'amp',
|
|
'kilo',
|
|
'kiro',
|
|
'crush',
|
|
'aug',
|
|
'autohand',
|
|
'cline',
|
|
'codebuff',
|
|
'command-code',
|
|
'continue',
|
|
'cursor',
|
|
'droid',
|
|
'kimi',
|
|
'mistral-vibe',
|
|
'qwen-code',
|
|
'rovo',
|
|
'hermes',
|
|
'devin',
|
|
'openclaw'
|
|
] as const satisfies readonly TuiAgent[]
|
|
|
|
// Why: fresh installs should expose Claude Agent Teams in agent pickers; the
|
|
// persistence migration separately preserves the old hidden default for legacy profiles.
|
|
export const DEFAULT_DISABLED_TUI_AGENTS = [] as const satisfies readonly TuiAgent[]
|
|
|
|
export function pickTuiAgent(
|
|
preferred: TuiAgent | 'blank' | null | undefined,
|
|
detected: Iterable<TuiAgent>,
|
|
disabled?: Iterable<unknown> | null
|
|
): TuiAgent | null {
|
|
if (preferred === 'blank') {
|
|
return null
|
|
}
|
|
const disabledSet = new Set(normalizeDisabledTuiAgents(disabled))
|
|
const detectedSet = detected instanceof Set ? detected : new Set(detected)
|
|
if (preferred && detectedSet.has(preferred) && !disabledSet.has(preferred)) {
|
|
return preferred
|
|
}
|
|
for (const agent of TUI_AGENT_AUTO_PICK_ORDER) {
|
|
if (detectedSet.has(agent) && !disabledSet.has(agent)) {
|
|
return agent
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function normalizeDisabledTuiAgents(value: unknown): TuiAgent[] {
|
|
if (!Array.isArray(value)) {
|
|
return []
|
|
}
|
|
const seen = new Set<TuiAgent>()
|
|
for (const item of value) {
|
|
if (isTuiAgent(item)) {
|
|
seen.add(item)
|
|
}
|
|
}
|
|
return [...seen]
|
|
}
|
|
|
|
export function haveSameDisabledTuiAgents(left: unknown, right: unknown): boolean {
|
|
const leftSet = new Set(normalizeDisabledTuiAgents(left))
|
|
const rightSet = new Set(normalizeDisabledTuiAgents(right))
|
|
return leftSet.size === rightSet.size && [...leftSet].every((agent) => rightSet.has(agent))
|
|
}
|
|
|
|
export function isTuiAgentEnabled(agent: TuiAgent, disabled?: Iterable<unknown> | null): boolean {
|
|
return !normalizeDisabledTuiAgents(disabled).includes(agent)
|
|
}
|
|
|
|
export function filterEnabledTuiAgents<T extends TuiAgent>(
|
|
agents: Iterable<T>,
|
|
disabled?: Iterable<unknown> | null
|
|
): T[] {
|
|
const disabledSet = new Set(normalizeDisabledTuiAgents(disabled))
|
|
return [...agents].filter((agent) => !disabledSet.has(agent))
|
|
}
|