diff --git a/README.md b/README.md index 5d75bcc89d32..d5320e51a889 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ Works with **any CLI agent** — if it runs in a terminal, it runs in Orca. OpenClaude logo OpenClaude   Antigravity logo Antigravity   Pi logo Pi   + Gajae Code logo Gajae Code   oh-my-pi logo oh-my-pi   Hermes Agent logo Hermes Agent   Devin logo Devin   diff --git a/config/scripts/locale-translation-policy.mjs b/config/scripts/locale-translation-policy.mjs index eb1a7ea0b925..ec34a1c61bee 100644 --- a/config/scripts/locale-translation-policy.mjs +++ b/config/scripts/locale-translation-policy.mjs @@ -43,6 +43,7 @@ export const NEVER_TRANSLATE_VALUES = new Set([ 'Cursor', 'Droid', 'Devin', + 'Gajae Code', 'Gemini', 'Git', 'Git Bash', diff --git a/mobile/src/components/mobile-agent-icon-assets.ts b/mobile/src/components/mobile-agent-icon-assets.ts index 38a48373734b..12311c2edcd8 100644 --- a/mobile/src/components/mobile-agent-icon-assets.ts +++ b/mobile/src/components/mobile-agent-icon-assets.ts @@ -39,5 +39,6 @@ export const MOBILE_AGENT_ICON_ASSETS: Partial faviconDomain: 'primeintellect.ai', homepageUrl: 'https://github.com/PrimeIntellect-ai/prime-agent' }, + { + id: 'gjc', + label: translate('auto.lib.agent.catalog.c851f042e2', 'Gajae Code'), + cmd: 'gjc', + faviconDomain: 'gajae-code.com', + homepageUrl: 'https://gajae-code.com' + }, { id: 'gemini', label: translate('auto.lib.agent.catalog.12e6baa4f7', 'Gemini'), diff --git a/src/renderer/src/lib/agent-favicon-assets.ts b/src/renderer/src/lib/agent-favicon-assets.ts index 565437f75bef..04327137341d 100644 --- a/src/renderer/src/lib/agent-favicon-assets.ts +++ b/src/renderer/src/lib/agent-favicon-assets.ts @@ -24,6 +24,7 @@ import rovoUrl from '../../../shared/agent-icons/rovo.png?url' import hermesUrl from '../../../shared/agent-icons/hermes.png?url' import devinUrl from '../../../shared/agent-icons/devin.png?url' import openclawUrl from '../../../shared/agent-icons/openclaw.png?url' +import gjcUrl from '../../../shared/agent-icons/gjc.png?url' // Why: these agents have no hand-authored SVG glyph, so previously their icons // loaded live from Google's favicon service. That service is unreachable in some @@ -57,5 +58,6 @@ export const AGENT_FAVICON_ASSETS: Partial> = { rovo: rovoUrl, hermes: hermesUrl, devin: devinUrl, - openclaw: openclawUrl + openclaw: openclawUrl, + gjc: gjcUrl } diff --git a/src/renderer/src/lib/agent-status.ts b/src/renderer/src/lib/agent-status.ts index 94933a05bffa..5d6d75613c7c 100644 --- a/src/renderer/src/lib/agent-status.ts +++ b/src/renderer/src/lib/agent-status.ts @@ -108,6 +108,7 @@ const ICONABLE_AGENT_TYPES: Record = { pi: true, omp: true, 'prime-agent': true, + gjc: true, gemini: true, antigravity: true, aider: true, diff --git a/src/shared/agent-icons/gjc.png b/src/shared/agent-icons/gjc.png new file mode 100644 index 000000000000..e96bf3506688 Binary files /dev/null and b/src/shared/agent-icons/gjc.png differ diff --git a/src/shared/agent-kind.ts b/src/shared/agent-kind.ts index 324a73f2cd89..a549efb047fe 100644 --- a/src/shared/agent-kind.ts +++ b/src/shared/agent-kind.ts @@ -24,6 +24,7 @@ const TUI_AGENT_KIND_BY_AGENT = { pi: 'pi', omp: 'omp', 'prime-agent': 'prime-agent', + gjc: 'gjc', gemini: 'gemini', antigravity: 'antigravity', aider: 'aider', diff --git a/src/shared/gjc-agent-registration.test.ts b/src/shared/gjc-agent-registration.test.ts new file mode 100644 index 000000000000..0862c5b28654 --- /dev/null +++ b/src/shared/gjc-agent-registration.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest' +import { tuiAgentToAgentKind } from './agent-kind' +import { SKILLS_CLI_AGENT_KEY_BY_TUI_AGENT } from './skills-cli-agent-keys' +import { TUI_AGENT_DISPLAY_NAMES } from './tui-agent-display-names' +import { getTuiAgentLaunchCommand, isTuiAgent, TUI_AGENT_CONFIG } from './tui-agent-config' +import { TUI_AGENT_AUTO_PICK_ORDER } from './tui-agent-selection' + +// Why: Gajae Code launches as a plain interactive TUI on `gjc`, so the only thing +// that can silently break it is a half-finished registration (union member with no +// config, or a config the auto-pick order never reaches). +describe('Gajae Code agent registration', () => { + it('detects and launches the published `gjc` binary', () => { + expect(isTuiAgent('gjc')).toBe(true) + const config = TUI_AGENT_CONFIG.gjc + expect(config.detectCmd).toBe('gjc') + expect(getTuiAgentLaunchCommand(config, 'darwin')).toBe('gjc') + expect(config.expectedProcess).toBe('gjc') + }) + + it('injects the launch prompt after startup instead of as argv', () => { + // Why: `gjc -p ` is its non-interactive print mode, and it exposes no + // prefill flag or env var, so argv/flag injection would exit the hosted session. + expect(TUI_AGENT_CONFIG.gjc.promptInjectionMode).toBe('stdin-after-start') + expect(TUI_AGENT_CONFIG.gjc.draftPromptFlag).toBeUndefined() + expect(TUI_AGENT_CONFIG.gjc.draftPromptEnvVar).toBeUndefined() + }) + + it('is selectable, labelled, and telemetry-mapped', () => { + expect(TUI_AGENT_DISPLAY_NAMES.gjc).toBe('Gajae Code') + expect(TUI_AGENT_AUTO_PICK_ORDER).toContain('gjc') + expect(tuiAgentToAgentKind('gjc')).toBe('gjc') + }) + + it('claims no skills CLI agent key', () => { + // Why: the community skills CLI exits 1 on an unknown --agent value, and it has + // no gjc key; Gajae Code reads its own .gjc roots plus shared .agents/skills. + expect(SKILLS_CLI_AGENT_KEY_BY_TUI_AGENT.gjc).toBeNull() + }) +}) diff --git a/src/shared/skills-cli-agent-keys.ts b/src/shared/skills-cli-agent-keys.ts index 3126c0a81e5f..5e0406ee16f5 100644 --- a/src/shared/skills-cli-agent-keys.ts +++ b/src/shared/skills-cli-agent-keys.ts @@ -23,6 +23,8 @@ export const SKILLS_CLI_AGENT_KEY_BY_TUI_AGENT = { pi: 'pi', omp: null, 'prime-agent': null, + // Why: the skills CLI has no gjc key; Gajae Code reads its own .gjc roots plus shared .agents/skills. + gjc: null, gemini: 'gemini-cli', antigravity: 'antigravity', aider: null, diff --git a/src/shared/telemetry-events.ts b/src/shared/telemetry-events.ts index f6bbea3c755f..bf87ccdd555a 100644 --- a/src/shared/telemetry-events.ts +++ b/src/shared/telemetry-events.ts @@ -100,6 +100,7 @@ export const AGENT_KIND_VALUES = [ 'devin', 'ante', 'trae', + 'gjc', 'other' ] as const export const agentKindSchema = z.enum(AGENT_KIND_VALUES) diff --git a/src/shared/tui-agent-config-table.ts b/src/shared/tui-agent-config-table.ts new file mode 100644 index 000000000000..b96d8db9a722 --- /dev/null +++ b/src/shared/tui-agent-config-table.ts @@ -0,0 +1,300 @@ +// Why: split out of tui-agent-config.ts so the launch table can keep growing with +// new agents without pushing that module past the 300-line lint ceiling; the types +// and helpers live beside it in ./tui-agent-config. +import { getOrcaCliCommandNameForPlatform } from './orca-cli-command-name' +import type { TuiAgent } from './tui-agent' +import type { TuiAgentConfig } from './tui-agent-config' + +export const TUI_AGENT_CONFIG: Record = { + claude: { + detectCmd: 'claude', + launchCmd: 'claude', + expectedProcess: 'claude', + promptInjectionMode: 'argv', + // Why: `claude --prefill ` seeds the input without submitting, avoiding the paste-after-ready race (PR https://github.com/stablyai/orca/pull/926). + draftPromptFlag: '--prefill' + }, + 'claude-agent-teams': { + // Why: an Orca-provided launch mode, not a separate binary; detection follows the Orca CLI. + detectCmd: 'orca', + detectCmdAliases: ['orca-dev', 'orca-ide'], + // Why: require Claude too so fresh installs (Orca shim always present) don't report Agent Teams without an agent CLI. + detectRequiredCommands: ['claude'], + // Why: Windows/WSL use Claude's in-process Agent Teams fallback, not this Orca native-pane/tmux-shim wrapper. + detectUnsupportedRuntimes: ['win32', 'wsl'], + launchCmd: 'orca claude-teams', + launchCmdByPlatform: { + linux: `${getOrcaCliCommandNameForPlatform('linux')} claude-teams`, + win32: `${getOrcaCliCommandNameForPlatform('win32')} claude-teams` + }, + expectedProcess: 'claude', + promptInjectionMode: 'stdin-after-start' + }, + openclaude: { + detectCmd: 'openclaude', + launchCmd: 'openclaude', + expectedProcess: 'openclaude', + promptInjectionMode: 'argv', + draftPromptFlag: '--prefill' + }, + codex: { + detectCmd: 'codex', + launchCmd: 'codex', + expectedProcess: 'codex', + promptInjectionMode: 'argv', + windowsInputRecordPasteNewline: 'alt-enter', + preflightTrust: 'codex', + draftPasteReadySignal: 'codex-composer-prompt', + draftPasteReadyTimeoutMs: 20_000 + }, + autohand: { + detectCmd: 'autohand', + launchCmd: 'autohand', + expectedProcess: 'autohand', + promptInjectionMode: 'stdin-after-start' + }, + ante: { + detectCmd: 'ante', + launchCmd: 'ante', + expectedProcess: 'ante', + // 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', + expectedProcess: 'opencode', + promptInjectionMode: 'flag-prompt', + // Why: opencode enables bracketed paste before its composer mounts; wait for the post-\x1b[?2004h show-cursor so paste lands. + draftPasteReadySignal: 'render-cursor-after-bracketed-paste' + }, + 'mimo-code': { + detectCmd: 'mimo', + launchCmd: 'mimo', + expectedProcess: 'mimo', + promptInjectionMode: 'flag-prompt', + // Why: mirrors opencode's cursor-gated signal by parity; mimo's startup stream isn't separately validated. + draftPasteReadySignal: 'render-cursor-after-bracketed-paste' + }, + pi: { + detectCmd: 'pi', + launchCmd: 'pi', + expectedProcess: 'pi', + promptInjectionMode: 'argv', + // Why: pi has no `--prefill` and paste-after-ready races its long startup; the orca-prefill extension seeds this env var instead. + draftPromptEnvVar: 'ORCA_PI_PREFILL', + // Why: Pi decodes CSI-u; Esc+CR submits after tool subprocesses reset live KKP state (#9703). + windowsShiftEnterEncoding: 'csi-u' + }, + omp: { + detectCmd: 'omp', + launchCmd: 'omp', + expectedProcess: 'omp', + promptInjectionMode: 'argv', + draftPromptEnvVar: 'ORCA_OMP_PREFILL' + }, + 'prime-agent': { + detectCmd: 'prime-agent', + launchCmd: 'prime-agent', + expectedProcess: 'prime-agent', + // Why: `prime-agent [options] [@files...] [message...]` takes the task as positional argv. + promptInjectionMode: 'argv', + // Why: separator so prompts starting with `help`/`agents`/`-…` aren't parsed as a + // subcommand or flag — its help documents `--` as "treat all following arguments as messages". + argvPromptSeparator: '--', + // Why: Prime Agent embeds Pi's TUI and decodes CSI-u the same way (see pi above). + windowsShiftEnterEncoding: 'csi-u' + }, + gjc: { + detectCmd: 'gjc', + launchCmd: 'gjc', + expectedProcess: 'gjc', + // Why: `gjc -p ` is its non-interactive print mode (processes and exits), so + // launch the bare TUI and inject after startup instead of passing the task as argv. + promptInjectionMode: 'stdin-after-start' + }, + gemini: { + detectCmd: 'gemini', + launchCmd: 'gemini', + expectedProcess: 'gemini', + promptInjectionMode: 'flag-prompt-interactive' + }, + antigravity: { + detectCmd: 'agy', + launchCmd: 'agy', + expectedProcess: 'agy', + promptInjectionMode: 'flag-prompt-interactive' + }, + aider: { + detectCmd: 'aider', + launchCmd: 'aider', + expectedProcess: 'aider', + promptInjectionMode: 'stdin-after-start' + }, + goose: { + detectCmd: 'goose', + launchCmd: 'goose', + expectedProcess: 'goose', + promptInjectionMode: 'stdin-after-start' + }, + amp: { + detectCmd: 'amp', + launchCmd: 'amp', + expectedProcess: 'amp', + promptInjectionMode: 'stdin-after-start' + }, + kilo: { + detectCmd: 'kilo', + launchCmd: 'kilo', + expectedProcess: 'kilo', + promptInjectionMode: 'stdin-after-start' + }, + kiro: { + // Why: the Kiro installer (https://cli.kiro.dev/install) ships `kiro-cli`, not `kiro`; keep id 'kiro' for stored prefs. + detectCmd: 'kiro-cli', + // Why: trust flags like --trust-all-tools attach to Kiro's `chat` subcommand, not top-level kiro-cli. + launchCmd: 'kiro-cli chat --tui', + expectedProcess: 'kiro-cli', + promptInjectionMode: 'stdin-after-start' + }, + crush: { + detectCmd: 'crush', + launchCmd: 'crush', + expectedProcess: 'crush', + promptInjectionMode: 'stdin-after-start' + }, + aug: { + // Why: @augmentcode/auggie installs a binary named `auggie`, not `aug`; keep id 'aug' for stored prefs. + detectCmd: 'auggie', + launchCmd: 'auggie', + expectedProcess: 'auggie', + promptInjectionMode: 'stdin-after-start' + }, + cline: { + detectCmd: 'cline', + launchCmd: 'cline', + expectedProcess: 'cline', + promptInjectionMode: 'stdin-after-start' + }, + codebuff: { + detectCmd: 'codebuff', + launchCmd: 'codebuff', + expectedProcess: 'codebuff', + promptInjectionMode: 'stdin-after-start' + }, + 'command-code': { + // Why: use the full name (not its `cmd` alias) so detection doesn't collide with Windows' built-in cmd.exe. + detectCmd: 'command-code', + // Why: `--trust` skips the first-run trust prompt so it doesn't consume the task text. + launchCmd: 'command-code --trust', + expectedProcess: 'command-code', + promptInjectionMode: 'argv' + }, + continue: { + // Why: Continue's CLI binary is `cn`; `continue` is a bash/zsh builtin and would resolve to the shell keyword. + detectCmd: 'cn', + launchCmd: 'cn', + expectedProcess: 'cn', + promptInjectionMode: 'stdin-after-start' + }, + cursor: { + detectCmd: 'cursor-agent', + launchCmd: 'cursor-agent', + expectedProcess: 'cursor-agent', + promptInjectionMode: 'argv', + // Why: first-launch trust menu swallows the bracketed paste; pre-write the .workspace-trusted marker so it skips (agent-trust-presets.ts). + preflightTrust: 'cursor' + }, + droid: { + detectCmd: 'droid', + launchCmd: 'droid', + expectedProcess: 'droid', + promptInjectionMode: 'argv', + // Why: Droid decodes CSI-u on Windows; the legacy Esc+CR fallback reads as Enter and submits instead of newline. + windowsShiftEnterEncoding: 'csi-u', + ctrlEnterEncoding: 'csi-u' + }, + kimi: { + detectCmd: 'kimi', + launchCmd: 'kimi', + expectedProcess: 'kimi', + promptInjectionMode: 'stdin-after-start' + }, + 'mistral-vibe': { + // Why: installer exposes binary `vibe` though the package is mistral-vibe; keep old name as alias for wrapped installs. + detectCmd: 'vibe', + detectCmdAliases: ['mistral-vibe'], + launchCmd: 'vibe', + expectedProcess: 'vibe', + promptInjectionMode: 'stdin-after-start' + }, + 'qwen-code': { + // Why: package is qwen-code but its installed CLI binary on PATH is `qwen`. + detectCmd: 'qwen', + launchCmd: 'qwen', + expectedProcess: 'qwen', + promptInjectionMode: 'stdin-after-start' + }, + rovo: { + detectCmd: 'rovo', + launchCmd: 'rovo', + expectedProcess: 'rovo', + promptInjectionMode: 'stdin-after-start' + }, + hermes: { + detectCmd: 'hermes', + // Why: bare `hermes` opens the classic REPL; `--tui` starts the full-screen agent UI Orca hosts. + launchCmd: 'hermes --tui', + expectedProcess: 'hermes', + // Why: Hermes delivers the prompt via its startup-query contract, submitting only after the composer is ready. + promptInjectionMode: 'hermes-query' + }, + openclaw: { + detectCmd: 'openclaw', + launchCmd: 'openclaw', + expectedProcess: 'openclaw', + promptInjectionMode: 'stdin-after-start' + }, + copilot: { + detectCmd: 'copilot', + launchCmd: 'copilot', + expectedProcess: 'copilot', + // Why: `--prompt` exits on completion (kills the hosted session); `-i/--interactive` keeps it interactive. + promptInjectionMode: 'flag-interactive', + // Why: first-launch trust menu swallows the bracketed paste; pre-write trust so it skips (see agent-trust-presets.ts). + preflightTrust: 'copilot' + }, + grok: { + detectCmd: 'grok', + launchCmd: 'grok', + expectedProcess: 'grok', + // Why: argv (grok takes a positional prompt) so multi-line/special-char text isn't mangled as raw PTY keystrokes. + promptInjectionMode: 'argv', + // Why: separator so prompts like `help`/`--version` aren't parsed as Grok CLI syntax. + argvPromptSeparator: '--', + // Why: grok shimmers its startup logo until the session opens, so the quiet + // window never settles and launch drafts waited out the full 8s hard + // timeout; its composer glyph lands ~0.6s in. + draftPasteReadySignal: 'grok-composer-prompt', + ctrlEnterEncoding: 'csi-u' + }, + devin: { + detectCmd: 'devin', + launchCmd: 'devin', + expectedProcess: 'devin', + // Why: `devin -- ` auto-submits immediately (docs.devin.ai/cli), so start the REPL with no argv prompt. + promptInjectionMode: 'stdin-after-start' + } +} diff --git a/src/shared/tui-agent-config.ts b/src/shared/tui-agent-config.ts index 78772924c4ce..10cd18728e5c 100644 --- a/src/shared/tui-agent-config.ts +++ b/src/shared/tui-agent-config.ts @@ -1,5 +1,4 @@ import type { TuiAgent } from './tui-agent' -import { getOrcaCliCommandNameForPlatform } from './orca-cli-command-name' export type AgentPromptInjectionMode = | 'argv' @@ -50,291 +49,11 @@ export type TuiAgentConfig = { ctrlEnterEncoding?: 'csi-u' } -export const TUI_AGENT_CONFIG: Record = { - claude: { - detectCmd: 'claude', - launchCmd: 'claude', - expectedProcess: 'claude', - promptInjectionMode: 'argv', - // Why: `claude --prefill ` seeds the input without submitting, avoiding the paste-after-ready race (PR https://github.com/stablyai/orca/pull/926). - draftPromptFlag: '--prefill' - }, - 'claude-agent-teams': { - // Why: an Orca-provided launch mode, not a separate binary; detection follows the Orca CLI. - detectCmd: 'orca', - detectCmdAliases: ['orca-dev', 'orca-ide'], - // Why: require Claude too so fresh installs (Orca shim always present) don't report Agent Teams without an agent CLI. - detectRequiredCommands: ['claude'], - // Why: Windows/WSL use Claude's in-process Agent Teams fallback, not this Orca native-pane/tmux-shim wrapper. - detectUnsupportedRuntimes: ['win32', 'wsl'], - launchCmd: 'orca claude-teams', - launchCmdByPlatform: { - linux: `${getOrcaCliCommandNameForPlatform('linux')} claude-teams`, - win32: `${getOrcaCliCommandNameForPlatform('win32')} claude-teams` - }, - expectedProcess: 'claude', - promptInjectionMode: 'stdin-after-start' - }, - openclaude: { - detectCmd: 'openclaude', - launchCmd: 'openclaude', - expectedProcess: 'openclaude', - promptInjectionMode: 'argv', - draftPromptFlag: '--prefill' - }, - codex: { - detectCmd: 'codex', - launchCmd: 'codex', - expectedProcess: 'codex', - promptInjectionMode: 'argv', - windowsInputRecordPasteNewline: 'alt-enter', - preflightTrust: 'codex', - draftPasteReadySignal: 'codex-composer-prompt', - draftPasteReadyTimeoutMs: 20_000 - }, - autohand: { - detectCmd: 'autohand', - launchCmd: 'autohand', - expectedProcess: 'autohand', - promptInjectionMode: 'stdin-after-start' - }, - ante: { - detectCmd: 'ante', - launchCmd: 'ante', - expectedProcess: 'ante', - // 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', - expectedProcess: 'opencode', - promptInjectionMode: 'flag-prompt', - // Why: opencode enables bracketed paste before its composer mounts; wait for the post-\x1b[?2004h show-cursor so paste lands. - draftPasteReadySignal: 'render-cursor-after-bracketed-paste' - }, - 'mimo-code': { - detectCmd: 'mimo', - launchCmd: 'mimo', - expectedProcess: 'mimo', - promptInjectionMode: 'flag-prompt', - // Why: mirrors opencode's cursor-gated signal by parity; mimo's startup stream isn't separately validated. - draftPasteReadySignal: 'render-cursor-after-bracketed-paste' - }, - pi: { - detectCmd: 'pi', - launchCmd: 'pi', - expectedProcess: 'pi', - promptInjectionMode: 'argv', - // Why: pi has no `--prefill` and paste-after-ready races its long startup; the orca-prefill extension seeds this env var instead. - draftPromptEnvVar: 'ORCA_PI_PREFILL', - // Why: Pi decodes CSI-u; Esc+CR submits after tool subprocesses reset live KKP state (#9703). - windowsShiftEnterEncoding: 'csi-u' - }, - omp: { - detectCmd: 'omp', - launchCmd: 'omp', - expectedProcess: 'omp', - promptInjectionMode: 'argv', - draftPromptEnvVar: 'ORCA_OMP_PREFILL' - }, - 'prime-agent': { - detectCmd: 'prime-agent', - launchCmd: 'prime-agent', - expectedProcess: 'prime-agent', - // Why: `prime-agent [options] [@files...] [message...]` takes the task as positional argv. - promptInjectionMode: 'argv', - // Why: separator so prompts starting with `help`/`agents`/`-…` aren't parsed as a - // subcommand or flag — its help documents `--` as "treat all following arguments as messages". - argvPromptSeparator: '--', - // Why: Prime Agent embeds Pi's TUI and decodes CSI-u the same way (see pi above). - windowsShiftEnterEncoding: 'csi-u' - }, - gemini: { - detectCmd: 'gemini', - launchCmd: 'gemini', - expectedProcess: 'gemini', - promptInjectionMode: 'flag-prompt-interactive' - }, - antigravity: { - detectCmd: 'agy', - launchCmd: 'agy', - expectedProcess: 'agy', - promptInjectionMode: 'flag-prompt-interactive' - }, - aider: { - detectCmd: 'aider', - launchCmd: 'aider', - expectedProcess: 'aider', - promptInjectionMode: 'stdin-after-start' - }, - goose: { - detectCmd: 'goose', - launchCmd: 'goose', - expectedProcess: 'goose', - promptInjectionMode: 'stdin-after-start' - }, - amp: { - detectCmd: 'amp', - launchCmd: 'amp', - expectedProcess: 'amp', - promptInjectionMode: 'stdin-after-start' - }, - kilo: { - detectCmd: 'kilo', - launchCmd: 'kilo', - expectedProcess: 'kilo', - promptInjectionMode: 'stdin-after-start' - }, - kiro: { - // Why: the Kiro installer (https://cli.kiro.dev/install) ships `kiro-cli`, not `kiro`; keep id 'kiro' for stored prefs. - detectCmd: 'kiro-cli', - // Why: trust flags like --trust-all-tools attach to Kiro's `chat` subcommand, not top-level kiro-cli. - launchCmd: 'kiro-cli chat --tui', - expectedProcess: 'kiro-cli', - promptInjectionMode: 'stdin-after-start' - }, - crush: { - detectCmd: 'crush', - launchCmd: 'crush', - expectedProcess: 'crush', - promptInjectionMode: 'stdin-after-start' - }, - aug: { - // Why: @augmentcode/auggie installs a binary named `auggie`, not `aug`; keep id 'aug' for stored prefs. - detectCmd: 'auggie', - launchCmd: 'auggie', - expectedProcess: 'auggie', - promptInjectionMode: 'stdin-after-start' - }, - cline: { - detectCmd: 'cline', - launchCmd: 'cline', - expectedProcess: 'cline', - promptInjectionMode: 'stdin-after-start' - }, - codebuff: { - detectCmd: 'codebuff', - launchCmd: 'codebuff', - expectedProcess: 'codebuff', - promptInjectionMode: 'stdin-after-start' - }, - 'command-code': { - // Why: use the full name (not its `cmd` alias) so detection doesn't collide with Windows' built-in cmd.exe. - detectCmd: 'command-code', - // Why: `--trust` skips the first-run trust prompt so it doesn't consume the task text. - launchCmd: 'command-code --trust', - expectedProcess: 'command-code', - promptInjectionMode: 'argv' - }, - continue: { - // Why: Continue's CLI binary is `cn`; `continue` is a bash/zsh builtin and would resolve to the shell keyword. - detectCmd: 'cn', - launchCmd: 'cn', - expectedProcess: 'cn', - promptInjectionMode: 'stdin-after-start' - }, - cursor: { - detectCmd: 'cursor-agent', - launchCmd: 'cursor-agent', - expectedProcess: 'cursor-agent', - promptInjectionMode: 'argv', - // Why: first-launch trust menu swallows the bracketed paste; pre-write the .workspace-trusted marker so it skips (agent-trust-presets.ts). - preflightTrust: 'cursor' - }, - droid: { - detectCmd: 'droid', - launchCmd: 'droid', - expectedProcess: 'droid', - promptInjectionMode: 'argv', - // Why: Droid decodes CSI-u on Windows; the legacy Esc+CR fallback reads as Enter and submits instead of newline. - windowsShiftEnterEncoding: 'csi-u', - ctrlEnterEncoding: 'csi-u' - }, - kimi: { - detectCmd: 'kimi', - launchCmd: 'kimi', - expectedProcess: 'kimi', - promptInjectionMode: 'stdin-after-start' - }, - 'mistral-vibe': { - // Why: installer exposes binary `vibe` though the package is mistral-vibe; keep old name as alias for wrapped installs. - detectCmd: 'vibe', - detectCmdAliases: ['mistral-vibe'], - launchCmd: 'vibe', - expectedProcess: 'vibe', - promptInjectionMode: 'stdin-after-start' - }, - 'qwen-code': { - // Why: package is qwen-code but its installed CLI binary on PATH is `qwen`. - detectCmd: 'qwen', - launchCmd: 'qwen', - expectedProcess: 'qwen', - promptInjectionMode: 'stdin-after-start' - }, - rovo: { - detectCmd: 'rovo', - launchCmd: 'rovo', - expectedProcess: 'rovo', - promptInjectionMode: 'stdin-after-start' - }, - hermes: { - detectCmd: 'hermes', - // Why: bare `hermes` opens the classic REPL; `--tui` starts the full-screen agent UI Orca hosts. - launchCmd: 'hermes --tui', - expectedProcess: 'hermes', - // Why: Hermes delivers the prompt via its startup-query contract, submitting only after the composer is ready. - promptInjectionMode: 'hermes-query' - }, - openclaw: { - detectCmd: 'openclaw', - launchCmd: 'openclaw', - expectedProcess: 'openclaw', - promptInjectionMode: 'stdin-after-start' - }, - copilot: { - detectCmd: 'copilot', - launchCmd: 'copilot', - expectedProcess: 'copilot', - // Why: `--prompt` exits on completion (kills the hosted session); `-i/--interactive` keeps it interactive. - promptInjectionMode: 'flag-interactive', - // Why: first-launch trust menu swallows the bracketed paste; pre-write trust so it skips (see agent-trust-presets.ts). - preflightTrust: 'copilot' - }, - grok: { - detectCmd: 'grok', - launchCmd: 'grok', - expectedProcess: 'grok', - // Why: argv (grok takes a positional prompt) so multi-line/special-char text isn't mangled as raw PTY keystrokes. - promptInjectionMode: 'argv', - // Why: separator so prompts like `help`/`--version` aren't parsed as Grok CLI syntax. - argvPromptSeparator: '--', - // Why: grok shimmers its startup logo until the session opens, so the quiet - // window never settles and launch drafts waited out the full 8s hard - // timeout; its composer glyph lands ~0.6s in. - draftPasteReadySignal: 'grok-composer-prompt', - ctrlEnterEncoding: 'csi-u' - }, - devin: { - detectCmd: 'devin', - launchCmd: 'devin', - expectedProcess: 'devin', - // Why: `devin -- ` auto-submits immediately (docs.devin.ai/cli), so start the REPL with no argv prompt. - promptInjectionMode: 'stdin-after-start' - } -} +import { TUI_AGENT_CONFIG } from './tui-agent-config-table' + +// Re-export: the launch table moved to its own module; every existing importer of +// `TUI_AGENT_CONFIG` from this path keeps working unchanged. +export { TUI_AGENT_CONFIG } export function isTuiAgent(value: unknown): value is TuiAgent { return typeof value === 'string' && Object.hasOwn(TUI_AGENT_CONFIG, value) diff --git a/src/shared/tui-agent-display-names.ts b/src/shared/tui-agent-display-names.ts index 0b2078f0479c..3dfe9193496c 100644 --- a/src/shared/tui-agent-display-names.ts +++ b/src/shared/tui-agent-display-names.ts @@ -19,6 +19,7 @@ export const TUI_AGENT_DISPLAY_NAMES: Record = { pi: 'Pi', omp: 'OMP', 'prime-agent': 'Prime Agent', + gjc: 'Gajae Code', gemini: 'Gemini', antigravity: 'Antigravity', aider: 'Aider', diff --git a/src/shared/tui-agent-selection.ts b/src/shared/tui-agent-selection.ts index 86216e589b82..42d809b98a3d 100644 --- a/src/shared/tui-agent-selection.ts +++ b/src/shared/tui-agent-selection.ts @@ -17,6 +17,7 @@ export const TUI_AGENT_AUTO_PICK_ORDER = [ 'pi', 'omp', 'prime-agent', + 'gjc', 'gemini', 'antigravity', 'aider', diff --git a/src/shared/tui-agent.ts b/src/shared/tui-agent.ts index a885e3dd24cb..f3ca2f38ed6b 100644 --- a/src/shared/tui-agent.ts +++ b/src/shared/tui-agent.ts @@ -37,3 +37,4 @@ export type TuiAgent = | 'ante' // Ante (Antigma Labs) | 'trae' // Trae CLI | 'prime-agent' // Prime Agent (Prime Intellect) + | 'gjc' // Gajae Code (gajae-code.com)