mirror of
https://github.com/stablyai/orca.git
synced 2026-10-08 16:02:37 +00:00
* feat: [AI-GEN] add Trae CLI as a supported TUI agent Closes #10579. Wire trae-cli into the desktop and mobile agent catalogs following the same integration pattern as other CLI agents (e.g. Ante, Devin): - src/shared/types.ts, tui-agent-config.ts: register 'trae' with detectCmdAliases (traecli/trae-agent) and argv prompt injection, matching trae-cli's `trae-cli [prompt]` contract. The CLI's own third documented alias `ta` is intentionally excluded — too generic a 2-letter name to use as a PATH-existence detection signal without false-positiving on unrelated tools. - src/shared/trae-headless-command.ts: recognize `--print`/`-p` and `--output-format json|stream-json` as one-shot headless invocations (same shape as claude-headless-command.ts) so they aren't mistaken for a live interactive session. - agent-kind.ts, telemetry-events.ts, agent-status-types.ts, agent-type-label.ts, tui-agent-display-names.ts, tui-agent-permissions.ts (YOLO via trae-cli's own --yolo flag), tui-agent-selection.ts: standard per-agent registrations. - agent-catalog.tsx, agent-favicon-assets.ts, mobile/src/tasks/mobile-tui-agents.ts, mobile/src/components/mobile-agent-icon-assets.ts: catalog entries and bundled favicon (fetched from docs.trae.cn, required by mobile's offline-icon invariant test). - i18n: add the "Trae" label to all five locale catalogs (en/es/ja/ko/zh). - Tests: agent-process-recognition, agent-status, tui-agent-startup. Verified with `pnpm typecheck` (desktop + mobile), the relevant vitest suites (869 tests across 12 files, all green), oxlint (clean), and a real end-to-end launch of the actual trae-cli binary through Orca's pty.spawn IPC path (confirmed via the OS process table). * fix: [AI-GEN] point Trae catalog entry at the real CLI quick-start doc docs.trae.cn/cli (what the installed CLI's own --help text prints as its "User manual" link) soft-404s — the docs site restructured and the working page is docs.trae.cn/cli_get-started-with-trae-cli (confirmed by HTTP fetch: real page title "TRAE CLI 快速开始" vs the old path's "404 - 页面不存在"). Addresses CodeRabbit's homepageUrl review comment. * fix: [AI-GEN] detect Trae on traecli, not the ambiguous trae-cli name Per @AmethystLiang's review: the open-source bytedance/trae-agent project (MIT, ~12k stars) registers its own console script as `trae-cli` (pyproject.toml: `trae-cli = "trae_agent.cli:main"`), an entirely unrelated CLI with a different contract (`trae-cli run "task"`, `-p` short for `--provider`). Detecting on bare `trae-cli` would false-positive on that project's installs and break launch for anyone who has it instead of the actual TRAE CN CLI. - tui-agent-config.ts: detectCmd/launchCmd/expectedProcess -> `traecli` (TRAE CN's own installer symlinks this alias too, but the other project does not ship it). Dropped the `trae-agent` alias entirely — it's the colliding project's literal repo name, the highest false-positive string available. - agent-catalog.tsx: cmd -> `traecli` to match; faviconDomain -> `www.trae.cn` (bare `trae.cn` 404s on Google's favicon service; `www.trae.cn` is the product-root domain that actually resolves). - mobile-tui-agents.ts: faviconDomain -> `www.trae.cn` to match. - Tests updated: agent-process-recognition now asserts `trae-cli` and `trae-agent` are NOT recognized as Trae (regression guard against reintroducing the collision); tui-agent-startup updated for the new launch command. promptInjectionMode stays `argv` and the headless-command file stays as-is — both verified against the real TRAE CN CLI's actual --help output (pasted in the PR review thread), not assumptions. * refactor: [AI-GEN] share one print-mode headless matcher across agents trae-headless-command.ts was a rename-only fork of claude-headless-command.ts, and ante-headless-command.ts carried a third copy of optionName. Collapse both print-mode files into print-mode-headless-command.ts, dispatch from a Partial<Record<TuiAgent, ...>> table instead of an if-chain, and compress the Trae comments to the repo's one-line style. * fix: [AI-GEN] terminate Trae flag parsing before the positional prompt `traecli` is a Cobra CLI with subcommands, so an argv prompt starting with `help`, `config`, `-…` was dispatched as a subcommand or flag instead of being run as the task. Add `argvPromptSeparator: '--'` (same reason Grok has it), and stop the shared print-mode headless matcher at `--` so a prompt that reads like `--print` no longer drops the pane out of agent recognition. * docs: [AI-GEN] name both Trae CLIs explicitly in the detect-name comment Co-authored-by: Orca <help@stably.ai> * docs: [AI-GEN] drop the vendor tag from the Trae union comment Co-authored-by: Orca <help@stably.ai> * fix: [AI-GEN] guard the nullable startup plan in the Trae separator test Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: 陈泽榜 <chenzebang@jianzhikeji.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
// Mapping from the renderer's `TuiAgent` union (every agent Orca knows how
|
|
// to launch) to the closed `agentKindSchema` enum on telemetry events. Every
|
|
// shipped agent maps to a concrete telemetry value so dashboards can
|
|
// distinguish launch interest instead of collapsing the long tail to `other`.
|
|
//
|
|
// Lives in `src/shared/` (not the renderer) because main-side telemetry
|
|
// emission (`agent_started` from the `pty:spawn` IPC handler) needs the
|
|
// same mapping. Centralizing here means a new TuiAgent member is one edit,
|
|
// not a sweep across renderer + main.
|
|
|
|
import type { AgentKind } from './telemetry-events'
|
|
import type { TuiAgent } from './types'
|
|
|
|
type ConcreteAgentKind = Exclude<AgentKind, 'other'>
|
|
|
|
const TUI_AGENT_KIND_BY_AGENT = {
|
|
claude: 'claude-code',
|
|
'claude-agent-teams': 'claude-agent-teams',
|
|
openclaude: 'openclaude',
|
|
codex: 'codex',
|
|
autohand: 'autohand',
|
|
opencode: 'opencode',
|
|
'mimo-code': 'mimo-code',
|
|
pi: 'pi',
|
|
omp: 'omp',
|
|
gemini: 'gemini',
|
|
antigravity: 'antigravity',
|
|
aider: 'aider',
|
|
goose: 'goose',
|
|
amp: 'amp',
|
|
kilo: 'kilo',
|
|
kiro: 'kiro',
|
|
crush: 'crush',
|
|
aug: 'aug',
|
|
cline: 'cline',
|
|
codebuff: 'codebuff',
|
|
'command-code': 'command-code',
|
|
continue: 'continue',
|
|
cursor: 'cursor',
|
|
droid: 'droid',
|
|
kimi: 'kimi',
|
|
'mistral-vibe': 'mistral-vibe',
|
|
'qwen-code': 'qwen-code',
|
|
rovo: 'rovo',
|
|
hermes: 'hermes',
|
|
openclaw: 'openclaw',
|
|
copilot: 'copilot',
|
|
grok: 'grok',
|
|
devin: 'devin',
|
|
ante: 'ante',
|
|
trae: 'trae'
|
|
} satisfies Record<TuiAgent, ConcreteAgentKind>
|
|
|
|
// Why: `satisfies Record<TuiAgent, …>` makes the lookup exhaustive at compile
|
|
// time, but stale persisted settings or unsafe IPC casts can carry a string
|
|
// outside the union at runtime — fall back to `'other'` so the event still
|
|
// emits instead of failing validation and dropping silently.
|
|
export function tuiAgentToAgentKind(agent: TuiAgent): AgentKind {
|
|
return TUI_AGENT_KIND_BY_AGENT[agent] ?? 'other'
|
|
}
|
|
|
|
// Why: the worktree-initial-terminal launch path only carries the telemetry
|
|
// `agent_kind`, not the TuiAgent. Reverse the map so that path can stamp the
|
|
// tab's launch agent without threading TuiAgent through every startup builder.
|
|
const AGENT_BY_TUI_AGENT_KIND: Partial<Record<AgentKind, TuiAgent>> = Object.fromEntries(
|
|
Object.entries(TUI_AGENT_KIND_BY_AGENT).map(([agent, kind]) => [kind, agent as TuiAgent])
|
|
)
|
|
|
|
export function agentKindToTuiAgent(kind: AgentKind | null | undefined): TuiAgent | null {
|
|
if (!kind) {
|
|
return null
|
|
}
|
|
return AGENT_BY_TUI_AGENT_KIND[kind] ?? null
|
|
}
|