mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
Merge pull request #181 from Lint111/agent/split-codex-animations
feat(codex): make terminal animations configurable
This commit is contained in:
@@ -643,6 +643,10 @@ export function buildCodexCommand(config?: CodexConfig): string {
|
||||
parts.push('--dangerously-bypass-approvals-and-sandbox');
|
||||
}
|
||||
|
||||
if (config?.animations !== undefined) {
|
||||
parts.push('--config', `tui.animations=${config.animations ? 'true' : 'false'}`);
|
||||
}
|
||||
|
||||
if (config?.model) {
|
||||
const safeModel = /^[a-zA-Z0-9._\-/]+$/.test(config.model) ? config.model : undefined;
|
||||
if (safeModel) parts.push('--model', safeModel);
|
||||
|
||||
@@ -305,6 +305,8 @@ export interface CodexConfig {
|
||||
resumeSessionId?: string;
|
||||
/** Bypass approval prompts (passes --dangerously-bypass-approvals-and-sandbox) */
|
||||
dangerouslyBypassApprovals?: boolean;
|
||||
/** Enable Codex's decorative TUI animations. Disable to reduce remote terminal redraws. */
|
||||
animations?: boolean;
|
||||
/** Browser rendering strategy for Codex sessions. Hybrid TUI is the only supported mode. */
|
||||
renderMode?: CodexRenderMode;
|
||||
}
|
||||
|
||||
@@ -1688,6 +1688,14 @@
|
||||
</label>
|
||||
<span class="form-hint">Start new Codex sessions with --dangerously-bypass-approvals-and-sandbox</span>
|
||||
</div>
|
||||
<div class="form-row form-row-switch">
|
||||
<label>Animated Status Effects</label>
|
||||
<label class="switch">
|
||||
<input type="checkbox" id="appSettingsCodexAnimations">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span class="form-hint">Decorative Codex TUI motion for new local sessions. Leave off to reduce remote and mobile redraws.</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Models Tab -->
|
||||
<div class="modal-tab-content hidden" id="settings-models">
|
||||
|
||||
@@ -1040,6 +1040,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
...(isRemote ? {} : {
|
||||
codexConfig: {
|
||||
dangerouslyBypassApprovals: globalSettings.codexDangerouslyBypassApprovals ?? false,
|
||||
animations: globalSettings.codexAnimationsEnabled ?? false,
|
||||
renderMode: 'hybrid',
|
||||
},
|
||||
...(Object.keys(envOverrides).length > 0 ? { envOverrides } : {}),
|
||||
|
||||
@@ -376,6 +376,8 @@ Object.assign(CodemanApp.prototype, {
|
||||
// Codex CLI settings
|
||||
document.getElementById('appSettingsCodexDangerouslyBypassApprovals').checked =
|
||||
settings.codexDangerouslyBypassApprovals ?? false;
|
||||
document.getElementById('appSettingsCodexAnimations').checked =
|
||||
settings.codexAnimationsEnabled ?? false;
|
||||
// Claude Permissions settings
|
||||
document.getElementById('appSettingsAgentTeams').checked = settings.agentTeamsEnabled ?? false;
|
||||
document.getElementById('appSettingsClaudeModel').value = settings.claudeModel ?? '';
|
||||
@@ -1482,6 +1484,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
|
||||
// Codex CLI settings
|
||||
codexDangerouslyBypassApprovals: document.getElementById('appSettingsCodexDangerouslyBypassApprovals').checked,
|
||||
codexAnimationsEnabled: document.getElementById('appSettingsCodexAnimations').checked,
|
||||
// Claude Permissions settings
|
||||
agentTeamsEnabled: document.getElementById('appSettingsAgentTeams').checked,
|
||||
claudeModel: document.getElementById('appSettingsClaudeModel').value,
|
||||
|
||||
@@ -182,6 +182,7 @@ const CodexConfigSchema = z
|
||||
.regex(/^[a-zA-Z0-9_-]+$/)
|
||||
.optional(),
|
||||
dangerouslyBypassApprovals: z.boolean().optional(),
|
||||
animations: z.boolean().optional(),
|
||||
renderMode: z
|
||||
.enum(['scrollback', 'hybrid'])
|
||||
.optional()
|
||||
@@ -776,6 +777,7 @@ export const SettingsUpdateSchema = z
|
||||
allowedTools: z.string().max(2000).optional(),
|
||||
// Codex CLI settings
|
||||
codexDangerouslyBypassApprovals: z.boolean().optional(),
|
||||
codexAnimationsEnabled: z.boolean().optional(),
|
||||
// Terminal history and retention
|
||||
terminalScrollbackLines: z
|
||||
.number()
|
||||
|
||||
@@ -283,11 +283,13 @@ describe('Codex quick start settings', () => {
|
||||
/<div class="modal-tab-content hidden" id="settings-claude">([\s\S]*?)<!-- Codex CLI Tab -->/
|
||||
);
|
||||
expect(claudeTab?.[1]).not.toContain('appSettingsCodexDangerouslyBypassApprovals');
|
||||
expect(claudeTab?.[1]).not.toContain('appSettingsCodexAnimations');
|
||||
|
||||
const codexTab = html.match(
|
||||
/<div class="modal-tab-content hidden" id="settings-codex">([\s\S]*?)<\/div>\s*<!-- Models Tab -->/
|
||||
);
|
||||
expect(codexTab?.[1]).toContain('appSettingsCodexDangerouslyBypassApprovals');
|
||||
expect(codexTab?.[1]).toContain('appSettingsCodexAnimations');
|
||||
expect(codexTab?.[1]).not.toContain('appSettingsCodexRenderMode');
|
||||
});
|
||||
|
||||
@@ -327,6 +329,7 @@ describe('Codex quick start settings', () => {
|
||||
app.terminal = { clear: () => {}, writeln: () => {}, focus: () => {} };
|
||||
app.loadAppSettingsFromStorage = () => ({
|
||||
codexDangerouslyBypassApprovals: true,
|
||||
codexAnimationsEnabled: false,
|
||||
});
|
||||
app.getCaseSettings = () => ({});
|
||||
app.buildEnvOverrides = () => ({});
|
||||
@@ -345,7 +348,7 @@ describe('Codex quick start settings', () => {
|
||||
mode: 'codex',
|
||||
// tabs follow the w<n>-<case> naming convention (quick-start would otherwise auto-name codeman-<id>)
|
||||
sessionName: 'w1-codex-case',
|
||||
codexConfig: { dangerouslyBypassApprovals: true, renderMode: 'hybrid' },
|
||||
codexConfig: { dangerouslyBypassApprovals: true, animations: false, renderMode: 'hybrid' },
|
||||
});
|
||||
expect(selected).toEqual(['sess-1']);
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import {
|
||||
TmuxManager,
|
||||
buildCodexCommand,
|
||||
buildRemoteKillCommand,
|
||||
buildRemoteLaunchCommand,
|
||||
formatPaneSnapshot,
|
||||
@@ -98,6 +99,14 @@ describe('TmuxManager (unit)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Codex command builder', () => {
|
||||
it('controls decorative TUI animation through Codex config', () => {
|
||||
expect(buildCodexCommand({ animations: false })).toBe('codex --config tui.animations=false');
|
||||
expect(buildCodexCommand({ animations: true })).toBe('codex --config tui.animations=true');
|
||||
expect(buildCodexCommand()).toBe('codex');
|
||||
});
|
||||
});
|
||||
|
||||
describe('remote launch command builder', () => {
|
||||
it('wraps codex command overrides in ssh with remote tmux launch', () => {
|
||||
const command = buildRemoteLaunchCommand({
|
||||
|
||||
Reference in New Issue
Block a user