diff --git a/mobile/src/tasks/mobile-tui-agents.ts b/mobile/src/tasks/mobile-tui-agents.ts index 598e762aa77..2f1b079b214 100644 --- a/mobile/src/tasks/mobile-tui-agents.ts +++ b/mobile/src/tasks/mobile-tui-agents.ts @@ -17,6 +17,7 @@ export const MOBILE_TUI_AGENT_AUTO_PICK_ORDER = [ 'pi', 'omp', 'prime-agent', + 'gjc', 'gemini', 'antigravity', 'aider', @@ -78,7 +79,8 @@ export const MOBILE_TUI_AGENT_LABELS: Record = { rovo: 'Rovo Dev', hermes: 'Hermes', devin: 'Devin', - openclaw: 'OpenClaw' + openclaw: 'OpenClaw', + gjc: 'Gajae Code' } export const MOBILE_TUI_AGENT_FAVICON_DOMAINS: Partial> = { diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index 8e8cf2ab5e2..0b9e296aa71 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -453,6 +453,7 @@ "da41abbdd4": "Ante", "060d152fb5": "Trae", "d443a47995": "Prime Agent", + "c851f042e2": "Gajae Code", "mimo_code_label": "MiMo Code" }, "skill": { diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index d57447ad578..4c999c8e567 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -351,6 +351,7 @@ "da41abbdd4": "Ante", "060d152fb5": "Trae", "d443a47995": "Prime Agent", + "c851f042e2": "Gajae Code", "mimo_code_label": "MiMo Code" }, "skill": { diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index 664ad050519..7a8ba97400b 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -351,6 +351,7 @@ "da41abbdd4": "Ante", "060d152fb5": "Trae", "d443a47995": "Prime Agent", + "c851f042e2": "Gajae Code", "mimo_code_label": "MiMo Code" }, "skill": { diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index 0cd21562faa..40067a220bc 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -351,6 +351,7 @@ "da41abbdd4": "Ante", "060d152fb5": "Trae", "d443a47995": "Prime Agent", + "c851f042e2": "Gajae Code", "mimo_code_label": "MiMo Code" }, "skill": { diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index 783b110b6a0..a4bc10b33a2 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -351,6 +351,7 @@ "da41abbdd4": "Ante", "060d152fb5": "Trae", "d443a47995": "Prime Agent", + "c851f042e2": "Gajae Code", "mimo_code_label": "MiMo Code" }, "skill": { diff --git a/src/renderer/src/lib/agent-catalog.tsx b/src/renderer/src/lib/agent-catalog.tsx index 650668bc1a0..9ec5fda4f41 100644 --- a/src/renderer/src/lib/agent-catalog.tsx +++ b/src/renderer/src/lib/agent-catalog.tsx @@ -134,6 +134,15 @@ export const getAgentCatalog = createLocalizedCatalog((): AgentCatalogEntry[] => faviconDomain: 'primeintellect.ai', homepageUrl: 'https://github.com/PrimeIntellect-ai/prime-agent' }, + { + id: 'gjc', + label: translate('auto.lib.agent.catalog.c851f042e2', 'Gajae Code'), + cmd: 'gjc', + // Why: no faviconDomain — gajae-code.com serves an inline data-URI favicon, so + // Google's favicon service 404s and would render its generic globe placeholder + // instead of the agent's mark; the letter glyph fallback is the honest icon. + homepageUrl: 'https://gajae-code.com' + }, { id: 'gemini', label: translate('auto.lib.agent.catalog.12e6baa4f7', 'Gemini'), diff --git a/src/renderer/src/lib/agent-draft-readiness.ts b/src/renderer/src/lib/agent-draft-readiness.ts index 25be94193da..6277eca5c21 100644 --- a/src/renderer/src/lib/agent-draft-readiness.ts +++ b/src/renderer/src/lib/agent-draft-readiness.ts @@ -1,4 +1,4 @@ -import type { DraftPasteReadySignal } from '../../../shared/tui-agent-config' +import type { DraftPasteReadySignal } from '../../../shared/tui-agent-config-types' import type { GlobalSettings } from '../../../shared/global-settings-types' import { subscribeToPtyData } from '@/components/terminal-pane/pty-data-sidecar-subscriptions' import { replayPreHandlerPtyData } from '@/components/terminal-pane/pty-pre-handler-buffer' diff --git a/src/renderer/src/lib/agent-status.ts b/src/renderer/src/lib/agent-status.ts index 94933a05bff..54874b1fd6d 100644 --- a/src/renderer/src/lib/agent-status.ts +++ b/src/renderer/src/lib/agent-status.ts @@ -133,7 +133,8 @@ const ICONABLE_AGENT_TYPES: Record = { grok: true, devin: true, ante: true, - trae: true + trae: true, + gjc: true } // Why: return null (not a 'claude' fallback) for unknown so Codex panes don't flash the Claude icon before the hook fires. diff --git a/src/renderer/src/lib/tui-agent-startup.test.ts b/src/renderer/src/lib/tui-agent-startup.test.ts index 768a5363c85..84a8146fbfb 100644 --- a/src/renderer/src/lib/tui-agent-startup.test.ts +++ b/src/renderer/src/lib/tui-agent-startup.test.ts @@ -173,6 +173,36 @@ describe('buildAgentStartupPlan', () => { ).toBe("prime-agent -- 'help me name this config'") }) + it('passes the prompt to Gajae Code as a positional argv behind a `--` separator', () => { + expect( + buildAgentStartupPlan({ + agent: 'gjc', + prompt: 'Summarize the failing tests', + cmdOverrides: {}, + platform: 'linux' + }) + ).toEqual({ + agent: 'gjc', + launchCommand: "gjc -- 'Summarize the failing tests'", + expectedProcess: 'gjc', + followupPrompt: null, + launchConfig: emptyLaunchConfig('gjc') + }) + }) + + // Why: `gjc resume` is its own launch alias and `stats`/`models` are subcommands, so an + // unseparated prompt of exactly those words would dispatch instead of seeding the composer. + it('keeps subcommand-shaped Gajae Code prompts as the positional prompt', () => { + expect( + buildAgentStartupPlan({ + agent: 'gjc', + prompt: 'resume', + cmdOverrides: {}, + platform: 'linux' + })?.launchCommand + ).toBe("gjc -- 'resume'") + }) + it('uses cursor-agent as the actual launch binary', () => { expect( buildAgentStartupPlan({ diff --git a/src/shared/agent-kind.ts b/src/shared/agent-kind.ts index 324a73f2cd8..30b6b948be8 100644 --- a/src/shared/agent-kind.ts +++ b/src/shared/agent-kind.ts @@ -49,7 +49,8 @@ const TUI_AGENT_KIND_BY_AGENT = { grok: 'grok', devin: 'devin', ante: 'ante', - trae: 'trae' + trae: 'trae', + gjc: 'gjc' } satisfies Record // Why: `satisfies Record` makes the lookup exhaustive at compile diff --git a/src/shared/draft-paste-ready-scanner-grok-trace-replay.test.ts b/src/shared/draft-paste-ready-scanner-grok-trace-replay.test.ts index a853b075b6c..21f7d745b8a 100644 --- a/src/shared/draft-paste-ready-scanner-grok-trace-replay.test.ts +++ b/src/shared/draft-paste-ready-scanner-grok-trace-replay.test.ts @@ -12,7 +12,7 @@ // the inline mode that emits no alt-screen switch (quiet-window floor). import { describe, expect, it } from 'vitest' import { createDraftPasteReadyScanner } from './draft-paste-ready-scanner' -import type { DraftPasteReadySignal } from './tui-agent-config' +import type { DraftPasteReadySignal } from './tui-agent-config-types' import { GROK_STARTUP_PTY_TRACE, type GrokStartupTraceChunk diff --git a/src/shared/draft-paste-ready-scanner.ts b/src/shared/draft-paste-ready-scanner.ts index 0b0e104e54a..65f73277832 100644 --- a/src/shared/draft-paste-ready-scanner.ts +++ b/src/shared/draft-paste-ready-scanner.ts @@ -1,4 +1,4 @@ -import type { DraftPasteReadySignal } from './tui-agent-config' +import type { DraftPasteReadySignal } from './tui-agent-config-types' // Why: agents enable bracketed paste (DECSET 2004) before their composer is // actually mounted/focused. These markers let the scanner detect the real diff --git a/src/shared/skills-cli-agent-keys.ts b/src/shared/skills-cli-agent-keys.ts index 3126c0a81e5..aa9c66349ea 100644 --- a/src/shared/skills-cli-agent-keys.ts +++ b/src/shared/skills-cli-agent-keys.ts @@ -49,7 +49,8 @@ export const SKILLS_CLI_AGENT_KEY_BY_TUI_AGENT = { devin: 'devin', ante: null, // Why: Orca detects trae by `traecli`, an alias only TRAE CN ships. - trae: 'trae-cn' + trae: 'trae-cn', + gjc: null } satisfies Record /** diff --git a/src/shared/telemetry-events.ts b/src/shared/telemetry-events.ts index 0466ca79430..178a45bf8f6 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-types.ts b/src/shared/tui-agent-config-types.ts new file mode 100644 index 00000000000..282c4ec297d --- /dev/null +++ b/src/shared/tui-agent-config-types.ts @@ -0,0 +1,51 @@ +/** Shape of a single agent's launch/detection entry in `TUI_AGENT_CONFIG`. Split out of + * tui-agent-config.ts to keep that file's per-agent table under the shared max-lines ceiling. */ + +export type AgentPromptInjectionMode = + | 'argv' + | 'flag-prompt' + | 'flag-prompt-interactive' + | 'flag-interactive' + | 'hermes-query' + | 'stdin-after-start' + +export type DraftPasteReadySignal = + | 'render-quiet-after-bracketed-paste' + | 'codex-composer-prompt' + | 'render-cursor-after-bracketed-paste' + | 'grok-composer-prompt' + +export type TuiAgentDetectionRuntime = NodeJS.Platform | 'wsl' + +export type TuiAgentConfig = { + detectCmd: string + /** Additional executable names that identify the same agent on PATH. */ + detectCmdAliases?: readonly string[] + /** Other commands that must also be present before this agent counts as installed. */ + detectRequiredCommands?: readonly string[] + /** Detection runtimes where this launch mode is not available as a detected agent. */ + detectUnsupportedRuntimes?: readonly TuiAgentDetectionRuntime[] + launchCmd: string + /** Platform-specific launch command when the public binary name differs. */ + launchCmdByPlatform?: Partial> + expectedProcess: string + promptInjectionMode: AgentPromptInjectionMode + /** Option terminator required before positional prompts that may look like CLI syntax. */ + argvPromptSeparator?: '--' + /** Native CLI flag that seeds the input without submitting (e.g. Claude's `--prefill `); preferred over the paste-after-ready path. */ + draftPromptFlag?: string + /** Startup env var that seeds the input without submitting, for agents with no `--prefill`-style flag (e.g. pi); avoids the paste-after-ready race. */ + draftPromptEnvVar?: string + /** Pre-write a trust artifact so the agent's first-launch "trust this folder?" menu doesn't consume the bracketed paste (see agent-trust-presets.ts). */ + preflightTrust?: 'cursor' | 'copilot' | 'codex' + /** Agent-specific signal that the composer is ready for paste, stronger than the default quiet-render window. */ + draftPasteReadySignal?: DraftPasteReadySignal + /** Hard deadline for the agent's composer readiness signal. */ + draftPasteReadyTimeoutMs?: number + /** Windows Shift+Enter encoding override; omitted agents keep the legacy Esc+CR path. */ + windowsShiftEnterEncoding?: 'csi-u' + /** Paste newlines for TUIs that read Windows console input records instead of VT paste frames. */ + windowsInputRecordPasteNewline?: 'alt-enter' | 'csi-u' + /** Ctrl+Enter encoding for agents that consume CSI-u without active kitty flags. */ + ctrlEnterEncoding?: 'csi-u' +} diff --git a/src/shared/tui-agent-config.ts b/src/shared/tui-agent-config.ts index 78772924c4c..51fc12cb9da 100644 --- a/src/shared/tui-agent-config.ts +++ b/src/shared/tui-agent-config.ts @@ -1,54 +1,6 @@ import type { TuiAgent } from './tui-agent' import { getOrcaCliCommandNameForPlatform } from './orca-cli-command-name' - -export type AgentPromptInjectionMode = - | 'argv' - | 'flag-prompt' - | 'flag-prompt-interactive' - | 'flag-interactive' - | 'hermes-query' - | 'stdin-after-start' - -export type DraftPasteReadySignal = - | 'render-quiet-after-bracketed-paste' - | 'codex-composer-prompt' - | 'render-cursor-after-bracketed-paste' - | 'grok-composer-prompt' - -export type TuiAgentDetectionRuntime = NodeJS.Platform | 'wsl' - -export type TuiAgentConfig = { - detectCmd: string - /** Additional executable names that identify the same agent on PATH. */ - detectCmdAliases?: readonly string[] - /** Other commands that must also be present before this agent counts as installed. */ - detectRequiredCommands?: readonly string[] - /** Detection runtimes where this launch mode is not available as a detected agent. */ - detectUnsupportedRuntimes?: readonly TuiAgentDetectionRuntime[] - launchCmd: string - /** Platform-specific launch command when the public binary name differs. */ - launchCmdByPlatform?: Partial> - expectedProcess: string - promptInjectionMode: AgentPromptInjectionMode - /** Option terminator required before positional prompts that may look like CLI syntax. */ - argvPromptSeparator?: '--' - /** Native CLI flag that seeds the input without submitting (e.g. Claude's `--prefill `); preferred over the paste-after-ready path. */ - draftPromptFlag?: string - /** Startup env var that seeds the input without submitting, for agents with no `--prefill`-style flag (e.g. pi); avoids the paste-after-ready race. */ - draftPromptEnvVar?: string - /** Pre-write a trust artifact so the agent's first-launch "trust this folder?" menu doesn't consume the bracketed paste (see agent-trust-presets.ts). */ - preflightTrust?: 'cursor' | 'copilot' | 'codex' - /** Agent-specific signal that the composer is ready for paste, stronger than the default quiet-render window. */ - draftPasteReadySignal?: DraftPasteReadySignal - /** Hard deadline for the agent's composer readiness signal. */ - draftPasteReadyTimeoutMs?: number - /** Windows Shift+Enter encoding override; omitted agents keep the legacy Esc+CR path. */ - windowsShiftEnterEncoding?: 'csi-u' - /** Paste newlines for TUIs that read Windows console input records instead of VT paste frames. */ - windowsInputRecordPasteNewline?: 'alt-enter' | 'csi-u' - /** Ctrl+Enter encoding for agents that consume CSI-u without active kitty flags. */ - ctrlEnterEncoding?: 'csi-u' -} +import type { TuiAgentConfig } from './tui-agent-config-types' export const TUI_AGENT_CONFIG: Record = { claude: { @@ -162,6 +114,23 @@ export const TUI_AGENT_CONFIG: Record = { // 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', + // Why: `gjc` ships as a compiled single-file binary, so the foreground process + // carries its own name — no Node/Bun shim entrypoint to disambiguate. + expectedProcess: 'gjc', + // Why: `gjc [prompt]` takes the task as positional argv (`gjc "List all .ts files in src/"`). + promptInjectionMode: 'argv', + // Why: separator so a prompt that is exactly a subcommand word (`resume`, `stats`, + // `models`) or starts with `/` reaches the parser as message text instead of + // dispatching. Verified against its arg parser: a bare `--` is skipped and every + // following non-flag token lands in `messages`. + argvPromptSeparator: '--' + // Why no windowsShiftEnterEncoding: unlike the Pi TUI it forked, gjc binds newline to + // `alt+enter`/`ctrl+j` on win32 (interactive-mode.ts) rather than `shift+enter`, so the + // default Esc+CR path is already the encoding it expects. + }, gemini: { detectCmd: 'gemini', launchCmd: 'gemini', diff --git a/src/shared/tui-agent-detection-commands.ts b/src/shared/tui-agent-detection-commands.ts index 81ee6589649..49185ef7f6f 100644 --- a/src/shared/tui-agent-detection-commands.ts +++ b/src/shared/tui-agent-detection-commands.ts @@ -1,10 +1,6 @@ import type { TuiAgent } from './tui-agent' -import { - getTuiAgentDetectCommands, - TUI_AGENT_CONFIG, - type TuiAgentConfig, - type TuiAgentDetectionRuntime -} from './tui-agent-config' +import { getTuiAgentDetectCommands, TUI_AGENT_CONFIG } from './tui-agent-config' +import type { TuiAgentConfig, TuiAgentDetectionRuntime } from './tui-agent-config-types' export type TuiAgentDetectionCommand = { id: TuiAgent diff --git a/src/shared/tui-agent-display-names.ts b/src/shared/tui-agent-display-names.ts index 0b2078f0479..3dfe9193496 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 86216e589b8..42d809b98a3 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 a885e3dd24c..2c3d2033228 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