feat: add Trae CLI as a supported TUI agent (#10763)
* 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>
This commit is contained in:
parent
1bd80931bd
commit
2d23217166
|
|
@ -16,6 +16,7 @@ export const MOBILE_AGENT_ICON_ASSETS: Partial<Record<TuiAgent, ImageSourcePropT
|
|||
opencode: require('../../../src/shared/agent-icons/opencode.png'),
|
||||
'mimo-code': require('../../../src/shared/agent-icons/mimo-code.png'),
|
||||
ante: require('../../../src/shared/agent-icons/ante.png'),
|
||||
trae: require('../../../src/shared/agent-icons/trae.png'),
|
||||
gemini: require('../../../src/shared/agent-icons/gemini.png'),
|
||||
antigravity: require('../../../src/shared/agent-icons/antigravity.png'),
|
||||
goose: require('../../../src/shared/agent-icons/goose.png'),
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export const MOBILE_TUI_AGENT_AUTO_PICK_ORDER = [
|
|||
'opencode',
|
||||
'mimo-code',
|
||||
'ante',
|
||||
'trae',
|
||||
'pi',
|
||||
'omp',
|
||||
'gemini',
|
||||
|
|
@ -50,6 +51,7 @@ export const MOBILE_TUI_AGENT_LABELS: Record<TuiAgent, string> = {
|
|||
opencode: 'OpenCode',
|
||||
'mimo-code': 'MiMo Code',
|
||||
ante: 'Ante',
|
||||
trae: 'Trae',
|
||||
pi: 'Pi',
|
||||
omp: 'OMP',
|
||||
gemini: 'Gemini',
|
||||
|
|
@ -84,6 +86,7 @@ export const MOBILE_TUI_AGENT_FAVICON_DOMAINS: Partial<Record<TuiAgent, string>>
|
|||
opencode: 'opencode.ai',
|
||||
'mimo-code': 'mimo.xiaomi.com',
|
||||
ante: 'antigma.ai',
|
||||
trae: 'www.trae.cn',
|
||||
omp: 'omp.sh',
|
||||
gemini: 'gemini.google.com',
|
||||
antigravity: 'antigravity.google',
|
||||
|
|
|
|||
|
|
@ -356,6 +356,7 @@
|
|||
"0708ed89f1": "Claude",
|
||||
"fc80296033": "Devin",
|
||||
"da41abbdd4": "Ante",
|
||||
"060d152fb5": "Trae",
|
||||
"mimo_code_label": "MiMo Code"
|
||||
},
|
||||
"skill": {
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@
|
|||
"0708ed89f1": "Claude",
|
||||
"fc80296033": "Devin",
|
||||
"da41abbdd4": "Ante",
|
||||
"060d152fb5": "Trae",
|
||||
"mimo_code_label": "MiMo Code"
|
||||
},
|
||||
"skill": {
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@
|
|||
"0708ed89f1": "Claude",
|
||||
"fc80296033": "Devin",
|
||||
"da41abbdd4": "Ante",
|
||||
"060d152fb5": "Trae",
|
||||
"mimo_code_label": "MiMo Code"
|
||||
},
|
||||
"skill": {
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@
|
|||
"0708ed89f1": "Claude",
|
||||
"fc80296033": "Devin",
|
||||
"da41abbdd4": "Ante",
|
||||
"060d152fb5": "Trae",
|
||||
"mimo_code_label": "MiMo Code"
|
||||
},
|
||||
"skill": {
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@
|
|||
"0708ed89f1": "Claude",
|
||||
"fc80296033": "Devin",
|
||||
"da41abbdd4": "Ante",
|
||||
"060d152fb5": "Trae",
|
||||
"mimo_code_label": "MiMo Code"
|
||||
},
|
||||
"skill": {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,15 @@ export const getAgentCatalog = createLocalizedCatalog((): AgentCatalogEntry[] =>
|
|||
faviconDomain: 'antigma.ai',
|
||||
homepageUrl: 'https://github.com/AntigmaLabs/ante-preview'
|
||||
},
|
||||
{
|
||||
id: 'trae',
|
||||
label: translate('auto.lib.agent.catalog.060d152fb5', 'Trae'),
|
||||
// Why: matches TUI_AGENT_CONFIG.trae.detectCmd, not the ambiguous `trae-cli` — see the Why there.
|
||||
cmd: 'traecli',
|
||||
// Why: bare `trae.cn` 404s on Google's favicon service.
|
||||
faviconDomain: 'www.trae.cn',
|
||||
homepageUrl: 'https://docs.trae.cn/cli_get-started-with-trae-cli'
|
||||
},
|
||||
{
|
||||
id: 'pi',
|
||||
label: translate('auto.lib.agent.catalog.302934c5d9', 'Pi'),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import type { TuiAgent } from '../../../shared/types'
|
|||
import grokUrl from '../../../shared/agent-icons/grok.png?url'
|
||||
import mimoCodeUrl from '../../../shared/agent-icons/mimo-code.png?url'
|
||||
import anteUrl from '../../../shared/agent-icons/ante.png?url'
|
||||
import traeUrl from '../../../shared/agent-icons/trae.png?url'
|
||||
import geminiUrl from '../../../shared/agent-icons/gemini.png?url'
|
||||
import antigravityUrl from '../../../shared/agent-icons/antigravity.png?url'
|
||||
import gooseUrl from '../../../shared/agent-icons/goose.png?url'
|
||||
|
|
@ -34,6 +35,7 @@ export const AGENT_FAVICON_ASSETS: Partial<Record<TuiAgent, string>> = {
|
|||
grok: grokUrl,
|
||||
'mimo-code': mimoCodeUrl,
|
||||
ante: anteUrl,
|
||||
trae: traeUrl,
|
||||
gemini: geminiUrl,
|
||||
antigravity: antigravityUrl,
|
||||
goose: gooseUrl,
|
||||
|
|
|
|||
|
|
@ -860,6 +860,10 @@ describe('formatAgentTypeLabel', () => {
|
|||
expect(formatAgentTypeLabel('ante')).toBe('Ante')
|
||||
})
|
||||
|
||||
it("maps 'trae' to 'Trae'", () => {
|
||||
expect(formatAgentTypeLabel('trae')).toBe('Trae')
|
||||
})
|
||||
|
||||
it('passes through arbitrary custom agent names as-is', () => {
|
||||
expect(formatAgentTypeLabel('weirdo')).toBe('weirdo')
|
||||
})
|
||||
|
|
@ -884,6 +888,7 @@ describe('agentTypeToIconAgent', () => {
|
|||
expect(agentTypeToIconAgent('antigravity')).toBe('antigravity')
|
||||
expect(agentTypeToIconAgent('command-code')).toBe('command-code')
|
||||
expect(agentTypeToIconAgent('ante')).toBe('ante')
|
||||
expect(agentTypeToIconAgent('trae')).toBe('trae')
|
||||
})
|
||||
|
||||
it('returns null for arbitrary non-iconable strings', () => {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,8 @@ const ICONABLE_AGENT_TYPES: Record<TuiAgent, true> = {
|
|||
copilot: true,
|
||||
grok: true,
|
||||
devin: true,
|
||||
ante: true
|
||||
ante: true,
|
||||
trae: true
|
||||
}
|
||||
|
||||
// Why: return null (not a 'claude' fallback) for unknown so Codex panes don't flash the Claude icon before the hook fires.
|
||||
|
|
|
|||
|
|
@ -115,6 +115,35 @@ describe('buildAgentStartupPlan', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('passes the prompt to Trae as a positional argv behind a `--` separator', () => {
|
||||
expect(
|
||||
buildAgentStartupPlan({
|
||||
agent: 'trae',
|
||||
prompt: 'Summarize the failing tests',
|
||||
cmdOverrides: {},
|
||||
platform: 'linux'
|
||||
})
|
||||
).toEqual({
|
||||
agent: 'trae',
|
||||
launchCommand: "traecli -- 'Summarize the failing tests'",
|
||||
expectedProcess: 'traecli',
|
||||
followupPrompt: null,
|
||||
launchConfig: emptyLaunchConfig('traecli')
|
||||
})
|
||||
})
|
||||
|
||||
// Why: without the separator these dispatch to Trae's `help`/`config` subcommands instead.
|
||||
it('keeps subcommand-shaped Trae prompts as the positional prompt', () => {
|
||||
expect(
|
||||
buildAgentStartupPlan({
|
||||
agent: 'trae',
|
||||
prompt: 'help me name this config',
|
||||
cmdOverrides: {},
|
||||
platform: 'linux'
|
||||
})?.launchCommand
|
||||
).toBe("traecli -- 'help me name this config'")
|
||||
})
|
||||
|
||||
it('uses cursor-agent as the actual launch binary', () => {
|
||||
expect(
|
||||
buildAgentStartupPlan({
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
import { isAnteHeadlessOneShotCommand } from './ante-headless-command'
|
||||
import { isClaudeHeadlessOneShotCommand } from './claude-headless-command'
|
||||
import { isPrintModeHeadlessOneShotCommand } from './print-mode-headless-command'
|
||||
import type { TuiAgent } from './types'
|
||||
|
||||
// Why: a table (not an if-chain) so adding an agent is one entry; Claude and Trae share
|
||||
// the same `--print` one-shot contract, Ante's `--prompt` form needs its own matcher.
|
||||
const HEADLESS_ONE_SHOT_MATCHERS: Partial<
|
||||
Record<TuiAgent, (tokens: readonly string[]) => boolean>
|
||||
> = {
|
||||
claude: isPrintModeHeadlessOneShotCommand,
|
||||
trae: isPrintModeHeadlessOneShotCommand,
|
||||
ante: isAnteHeadlessOneShotCommand
|
||||
}
|
||||
|
||||
export function isHeadlessOneShotAgentCommand(agent: TuiAgent, tokens: readonly string[]): boolean {
|
||||
if (agent === 'claude') {
|
||||
return isClaudeHeadlessOneShotCommand(tokens)
|
||||
}
|
||||
return agent === 'ante' && isAnteHeadlessOneShotCommand(tokens)
|
||||
return HEADLESS_ONE_SHOT_MATCHERS[agent]?.(tokens) ?? false
|
||||
}
|
||||
|
||||
type AgentCommandRecognition = { agent: TuiAgent } | null
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 412 B |
|
|
@ -47,7 +47,8 @@ const TUI_AGENT_KIND_BY_AGENT = {
|
|||
copilot: 'copilot',
|
||||
grok: 'grok',
|
||||
devin: 'devin',
|
||||
ante: 'ante'
|
||||
ante: 'ante',
|
||||
trae: 'trae'
|
||||
} satisfies Record<TuiAgent, ConcreteAgentKind>
|
||||
|
||||
// Why: `satisfies Record<TuiAgent, …>` makes the lookup exhaustive at compile
|
||||
|
|
|
|||
|
|
@ -130,6 +130,42 @@ describe('agent process recognition', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('recognizes Trae by its traecli binary, not the ambiguous trae-cli name', () => {
|
||||
expect(recognizeAgentProcess('traecli')).toEqual({
|
||||
agent: 'trae',
|
||||
processName: 'traecli'
|
||||
})
|
||||
expect(recognizeAgentProcess('/Users/dev/.local/bin/traecli')).toEqual({
|
||||
agent: 'trae',
|
||||
processName: 'traecli'
|
||||
})
|
||||
expect(isExpectedAgentProcess('/Users/dev/.local/bin/traecli', 'traecli')).toBe(true)
|
||||
expect(isRecognizedAgentType('traecli')).toBe(true)
|
||||
// Why: `trae-cli` and `trae-agent` both name the unrelated open-source bytedance/trae-agent.
|
||||
expect(recognizeAgentProcess('trae-cli')).toBeNull()
|
||||
expect(recognizeAgentProcess('trae-agent')).toBeNull()
|
||||
})
|
||||
|
||||
it('does not recognize Trae headless one-shot commands as interactive agents', () => {
|
||||
expect(recognizeAgentProcessFromCommandLine('traecli -p "summarize this diff"')).toBeNull()
|
||||
expect(recognizeAgentProcessFromCommandLine('traecli --print "review this"')).toBeNull()
|
||||
expect(
|
||||
recognizeAgentProcessFromCommandLine('traecli --output-format json "review this"')
|
||||
).toBeNull()
|
||||
expect(
|
||||
recognizeAgentProcessFromCommandLine('traecli --output-format=stream-json review')
|
||||
).toBeNull()
|
||||
expect(recognizeAgentProcessFromCommandLine('traecli --resume AUTO')).toEqual({
|
||||
agent: 'trae',
|
||||
processName: 'traecli'
|
||||
})
|
||||
// Why: past `--` nothing is a flag, so this is the interactive pane Orca itself launches.
|
||||
expect(recognizeAgentProcessFromCommandLine('traecli -- "--print the release notes"')).toEqual({
|
||||
agent: 'trae',
|
||||
processName: 'traecli'
|
||||
})
|
||||
})
|
||||
|
||||
it('recognizes Mistral Vibe by its installed executable and legacy alias', () => {
|
||||
expect(recognizeAgentProcess('/home/dev/.local/bin/vibe')).toEqual({
|
||||
agent: 'mistral-vibe',
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export type WellKnownAgentType =
|
|||
| 'hermes'
|
||||
| 'devin'
|
||||
| 'ante'
|
||||
| 'trae'
|
||||
| 'unknown'
|
||||
export type AgentType = WellKnownAgentType | (string & {})
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const WELL_KNOWN_LABELS: Record<string, string> = {
|
|||
hermes: 'Hermes',
|
||||
devin: 'Devin',
|
||||
ante: 'Ante',
|
||||
trae: 'Trae',
|
||||
kimi: 'Kimi'
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
const ANTE_HEADLESS_PROMPT_FLAGS = new Set(['--prompt', '-p'])
|
||||
import { optionName } from './print-mode-headless-command'
|
||||
|
||||
function optionName(token: string): string {
|
||||
const eq = token.indexOf('=')
|
||||
return eq === -1 ? token : token.slice(0, eq)
|
||||
}
|
||||
const ANTE_HEADLESS_PROMPT_FLAGS = new Set(['--prompt', '-p'])
|
||||
|
||||
function isAnteHeadlessPromptFlag(token: string): boolean {
|
||||
const name = optionName(token)
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
const CLAUDE_PRINT_MODE_FLAGS = new Set(['--print', '-p'])
|
||||
const CLAUDE_HEADLESS_OUTPUT_FORMATS = new Set(['json', 'stream-json'])
|
||||
|
||||
function optionName(token: string): string {
|
||||
const eq = token.indexOf('=')
|
||||
return eq === -1 ? token : token.slice(0, eq)
|
||||
}
|
||||
|
||||
function optionValue(tokens: readonly string[], index: number): string | null {
|
||||
const token = tokens[index]
|
||||
const eq = token.indexOf('=')
|
||||
if (eq !== -1) {
|
||||
return token.slice(eq + 1)
|
||||
}
|
||||
return tokens[index + 1] ?? null
|
||||
}
|
||||
|
||||
export function isClaudeHeadlessOneShotCommand(tokens: readonly string[]): boolean {
|
||||
for (let index = 1; index < tokens.length; index += 1) {
|
||||
const name = optionName(tokens[index])
|
||||
if (CLAUDE_PRINT_MODE_FLAGS.has(name)) {
|
||||
return true
|
||||
}
|
||||
if (name === '--output-format') {
|
||||
const value = optionValue(tokens, index)?.toLowerCase()
|
||||
if (value && CLAUDE_HEADLESS_OUTPUT_FORMATS.has(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
const PRINT_MODE_FLAGS = new Set(['--print', '-p'])
|
||||
const HEADLESS_OUTPUT_FORMATS = new Set(['json', 'stream-json'])
|
||||
|
||||
export function optionName(token: string): string {
|
||||
const eq = token.indexOf('=')
|
||||
return eq === -1 ? token : token.slice(0, eq)
|
||||
}
|
||||
|
||||
function optionValue(tokens: readonly string[], index: number): string | null {
|
||||
const token = tokens[index]
|
||||
const eq = token.indexOf('=')
|
||||
if (eq !== -1) {
|
||||
return token.slice(eq + 1)
|
||||
}
|
||||
return tokens[index + 1] ?? null
|
||||
}
|
||||
|
||||
// Why: `--print`/`-p` prints one response and exits, and `--output-format json|stream-json`
|
||||
// is only meaningful there — either means a headless run, not the interactive TUI Orca hosts.
|
||||
export function isPrintModeHeadlessOneShotCommand(tokens: readonly string[]): boolean {
|
||||
for (let index = 1; index < tokens.length; index += 1) {
|
||||
// Why: `--` ends option parsing, so a prompt that reads like `--print` is still a prompt.
|
||||
if (tokens[index] === '--') {
|
||||
return false
|
||||
}
|
||||
const name = optionName(tokens[index])
|
||||
if (PRINT_MODE_FLAGS.has(name)) {
|
||||
return true
|
||||
}
|
||||
if (name === '--output-format') {
|
||||
const value = optionValue(tokens, index)?.toLowerCase()
|
||||
if (value && HEADLESS_OUTPUT_FORMATS.has(value)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -94,6 +94,7 @@ export const AGENT_KIND_VALUES = [
|
|||
'grok',
|
||||
'devin',
|
||||
'ante',
|
||||
'trae',
|
||||
'other'
|
||||
] as const
|
||||
export const agentKindSchema = z.enum(AGENT_KIND_VALUES)
|
||||
|
|
|
|||
|
|
@ -96,6 +96,18 @@ export const TUI_AGENT_CONFIG: Record<TuiAgent, TuiAgentConfig> = {
|
|||
// Why: `ante --prompt` is headless (runs once and exits), so launch the bare TUI and inject after startup.
|
||||
promptInjectionMode: 'stdin-after-start'
|
||||
},
|
||||
trae: {
|
||||
// Why: the unrelated open-source bytedance/trae-agent also installs a `trae-cli`
|
||||
// binary, so detect TRAE CN's CLI on `traecli`, an alias only TRAE CN ships.
|
||||
detectCmd: 'traecli',
|
||||
launchCmd: 'traecli',
|
||||
expectedProcess: 'traecli',
|
||||
// Why: `traecli [prompt]` takes the task as a positional argv, same as Claude/Codex.
|
||||
promptInjectionMode: 'argv',
|
||||
// Why: separator so prompts starting with `help`/`config`/`-…` aren't parsed as a
|
||||
// Trae subcommand or flag — `--` stops both in its Cobra parser.
|
||||
argvPromptSeparator: '--'
|
||||
},
|
||||
opencode: {
|
||||
detectCmd: 'opencode',
|
||||
launchCmd: 'opencode',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const TUI_AGENT_DISPLAY_NAMES: Record<TuiAgent, string> = {
|
|||
codex: 'Codex',
|
||||
devin: 'Devin',
|
||||
ante: 'Ante',
|
||||
trae: 'Trae',
|
||||
autohand: 'Autohand Code',
|
||||
opencode: 'OpenCode',
|
||||
'mimo-code': 'MiMo Code',
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ export const YOLO_TUI_AGENT_ARGS: Partial<Record<TuiAgent, string>> = {
|
|||
copilot: '--yolo',
|
||||
grok: '--permission-mode bypassPermissions',
|
||||
devin: '--permission-mode bypass',
|
||||
ante: '--yolo'
|
||||
ante: '--yolo',
|
||||
trae: '--yolo'
|
||||
}
|
||||
|
||||
export const YOLO_TUI_AGENT_ENV: Partial<Record<TuiAgent, Record<string, string>>> = {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export const TUI_AGENT_AUTO_PICK_ORDER = [
|
|||
'opencode',
|
||||
'mimo-code',
|
||||
'ante',
|
||||
'trae',
|
||||
'pi',
|
||||
'omp',
|
||||
'gemini',
|
||||
|
|
|
|||
|
|
@ -2530,6 +2530,7 @@ export type TuiAgent =
|
|||
| 'grok' // xAI Grok CLI
|
||||
| 'devin' // Devin CLI
|
||||
| 'ante' // Ante (Antigma Labs)
|
||||
| 'trae' // Trae CLI
|
||||
|
||||
export type TaskViewPresetId = 'all' | 'issues' | 'review' | 'my-issues' | 'my-prs' | 'prs'
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue