fix(env): fix fish escaping, profile parsing, and add OPENAI_MODEL mapping

- Fix P0: fish single-quote escaping uses '\'' (end-quote, literal, reopen)
  instead of \' which fish doesn't support inside single-quoted strings
- Fix P0: profile arg parsing now skips flag values via findProfile() so
  `ccs env --format openai gemini` correctly resolves to 'gemini'
- Add OPENAI_MODEL mapping from ANTHROPIC_MODEL in transformToOpenAI
- Add stderr warning when invalid env var keys are silently dropped
- Update --shell help text to mention zsh compatibility
- Add findProfile tests (6) and OPENAI_MODEL omission test
This commit is contained in:
Tam Nhu Tran committed 2026-02-11 06:52:21 +07:00
1 parent 44b3152d34
commit d5c03d1f2d
2 files changed
+73 -11

No files matched your search

+39 -2
View File
@@ -9,6 +9,7 @@ import {
formatExportLine,
transformToOpenAI,
parseFlag,
findProfile,
} from '../../../src/commands/env-command';
describe('env-command', () => {
@@ -98,7 +99,7 @@ describe('env-command', () => {
});
it('escapes single quotes in fish values', () => {
expect(formatExportLine('fish', 'VAL', "it's here")).toBe("set -gx VAL 'it\\'s here'");
expect(formatExportLine('fish', 'VAL', "it's here")).toBe("set -gx VAL 'it'\\''s here'");
});
it('escapes single quotes in powershell values', () => {
@@ -120,6 +121,7 @@ describe('env-command', () => {
OPENAI_API_KEY: 'ccs-internal-managed',
OPENAI_BASE_URL: 'http://127.0.0.1:8317/api/provider/gemini',
LOCAL_ENDPOINT: 'http://127.0.0.1:8317/api/provider/gemini',
OPENAI_MODEL: 'gemini-claude-sonnet-4-5',
});
});
@@ -141,10 +143,19 @@ describe('env-command', () => {
DISABLE_TELEMETRY: '1',
});
// Should only have 3 keys
// Should only have 3 keys (no OPENAI_MODEL when ANTHROPIC_MODEL absent)
expect(Object.keys(result)).toHaveLength(3);
expect(result['ANTHROPIC_MAX_TOKENS']).toBeUndefined();
});
it('omits OPENAI_MODEL when ANTHROPIC_MODEL absent', () => {
const result = transformToOpenAI({
ANTHROPIC_BASE_URL: 'http://localhost:8317',
ANTHROPIC_AUTH_TOKEN: 'key',
});
expect(result['OPENAI_MODEL']).toBeUndefined();
});
});
describe('parseFlag', () => {
@@ -168,4 +179,30 @@ describe('env-command', () => {
expect(parseFlag(['--format', '--shell'], 'format')).toBeUndefined();
});
});
describe('findProfile', () => {
it('finds profile as first positional arg', () => {
expect(findProfile(['gemini'], ['format', 'shell'])).toBe('gemini');
});
it('skips flags before profile', () => {
expect(findProfile(['--format', 'openai', 'gemini'], ['format', 'shell'])).toBe('gemini');
});
it('skips --flag=value style flags', () => {
expect(findProfile(['--format=openai', 'gemini'], ['format', 'shell'])).toBe('gemini');
});
it('handles profile before flags', () => {
expect(findProfile(['gemini', '--format', 'openai'], ['format', 'shell'])).toBe('gemini');
});
it('returns undefined when no positional args', () => {
expect(findProfile(['--format', 'openai', '--shell', 'fish'], ['format', 'shell'])).toBeUndefined();
});
it('skips multiple flag-value pairs', () => {
expect(findProfile(['--format', 'openai', '--shell', 'fish', 'codex'], ['format', 'shell'])).toBe('codex');
});
});
});