Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion mobile/src/tasks/mobile-tui-agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const MOBILE_TUI_AGENT_AUTO_PICK_ORDER = [
'pi',
'omp',
'prime-agent',
'gjc',
'gemini',
'antigravity',
'aider',
Expand Down Expand Up @@ -78,7 +79,8 @@ export const MOBILE_TUI_AGENT_LABELS: Record<TuiAgent, string> = {
rovo: 'Rovo Dev',
hermes: 'Hermes',
devin: 'Devin',
openclaw: 'OpenClaw'
openclaw: 'OpenClaw',
gjc: 'Gajae Code'
}

export const MOBILE_TUI_AGENT_FAVICON_DOMAINS: Partial<Record<TuiAgent, string>> = {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@
"da41abbdd4": "Ante",
"060d152fb5": "Trae",
"d443a47995": "Prime Agent",
"c851f042e2": "Gajae Code",
"mimo_code_label": "MiMo Code"
},
"skill": {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"da41abbdd4": "Ante",
"060d152fb5": "Trae",
"d443a47995": "Prime Agent",
"c851f042e2": "Gajae Code",
"mimo_code_label": "MiMo Code"
},
"skill": {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"da41abbdd4": "Ante",
"060d152fb5": "Trae",
"d443a47995": "Prime Agent",
"c851f042e2": "Gajae Code",
"mimo_code_label": "MiMo Code"
},
"skill": {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/i18n/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"da41abbdd4": "Ante",
"060d152fb5": "Trae",
"d443a47995": "Prime Agent",
"c851f042e2": "Gajae Code",
"mimo_code_label": "MiMo Code"
},
"skill": {
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@
"da41abbdd4": "Ante",
"060d152fb5": "Trae",
"d443a47995": "Prime Agent",
"c851f042e2": "Gajae Code",
"mimo_code_label": "MiMo Code"
},
"skill": {
Expand Down
9 changes: 9 additions & 0 deletions src/renderer/src/lib/agent-catalog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/lib/agent-draft-readiness.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/src/lib/agent-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ const ICONABLE_AGENT_TYPES: Record<TuiAgent, true> = {
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.
Expand Down
30 changes: 30 additions & 0 deletions src/renderer/src/lib/tui-agent-startup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
3 changes: 2 additions & 1 deletion src/shared/agent-kind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ const TUI_AGENT_KIND_BY_AGENT = {
grok: 'grok',
devin: 'devin',
ante: 'ante',
trae: 'trae'
trae: 'trae',
gjc: 'gjc'
} satisfies Record<TuiAgent, ConcreteAgentKind>

// Why: `satisfies Record<TuiAgent, …>` makes the lookup exhaustive at compile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/shared/draft-paste-ready-scanner.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/shared/skills-cli-agent-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TuiAgent, string | null>

/**
Expand Down
1 change: 1 addition & 0 deletions src/shared/telemetry-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const AGENT_KIND_VALUES = [
'devin',
'ante',
'trae',
'gjc',
'other'
] as const
export const agentKindSchema = z.enum(AGENT_KIND_VALUES)
Expand Down
51 changes: 51 additions & 0 deletions src/shared/tui-agent-config-types.ts
Original file line number Diff line number Diff line change
@@ -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<Record<NodeJS.Platform, string>>
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 <text>`); 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'
}
67 changes: 18 additions & 49 deletions src/shared/tui-agent-config.ts
Original file line number Diff line number Diff line change
@@ -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<Record<NodeJS.Platform, string>>
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 <text>`); 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<TuiAgent, TuiAgentConfig> = {
claude: {
Expand Down Expand Up @@ -162,6 +114,23 @@ export const TUI_AGENT_CONFIG: Record<TuiAgent, TuiAgentConfig> = {
// 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',
Expand Down
8 changes: 2 additions & 6 deletions src/shared/tui-agent-detection-commands.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions src/shared/tui-agent-display-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const TUI_AGENT_DISPLAY_NAMES: Record<TuiAgent, string> = {
pi: 'Pi',
omp: 'OMP',
'prime-agent': 'Prime Agent',
gjc: 'Gajae Code',
gemini: 'Gemini',
antigravity: 'Antigravity',
aider: 'Aider',
Expand Down
1 change: 1 addition & 0 deletions src/shared/tui-agent-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const TUI_AGENT_AUTO_PICK_ORDER = [
'pi',
'omp',
'prime-agent',
'gjc',
'gemini',
'antigravity',
'aider',
Expand Down
1 change: 1 addition & 0 deletions src/shared/tui-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export type TuiAgent =
| 'ante' // Ante (Antigma Labs)
| 'trae' // Trae CLI
| 'prime-agent' // Prime Agent (Prime Intellect)
| 'gjc' // Gajae Code