`/models` now returns only deepseek-v4-pro and deepseek-v4-flash;
deepseek-chat / deepseek-reasoner sunset 2026-07-24 and the
deepseek-v3.2 hard-coded in the ark-coding fallback list never
existed. Both v4 models default to thinking enabled and the API
toggles via `{"thinking":{"type":"disabled"}}` — keep
`thinkingMode: 'disabled'` so the app's fast/non-thinking default
stays intact (server reasoning paths honor it; the Zig openai-compat
path doesn't emit the toggle yet, so calls through that path still
get provider-default thinking until it's wired). v4-pro promoted to
full tier; legacy aliases pinned to an exact RegExp so future
deepseek-* variants don't inherit a forced disabled mode.
Bandaid for the unwired toggle: v4-pro gets `timeoutMultiplier: 2`
because its default-on reasoning blows past the orchestrator's
planning timeout on long system prompts (observed in dev: planning
phase falls back, sub-agent then succeeds — UX degraded but
functional). Drop the multiplier once the Zig path actually sends
`thinking:{type:disabled}`.
Don't add a BUILTIN_MODEL_LISTS.deepseek entry — DeepSeek exposes
/v1/models, so let `fetchProviderModels` pull the live catalog
through `/api/ai/provider-models` instead of pinning a snapshot
(the ark-coding `deepseek-v3.2` ghost above shows what those
snapshots drift into).
54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
// apps/desktop/git/__tests__/git-ipc.test.ts
|
|
import { describe, it, expect } from 'vitest';
|
|
import { GitError } from '../error';
|
|
import { serializeGitError, GIT_ERROR_MARKER } from '../ipc-handlers';
|
|
|
|
describe('serializeGitError', () => {
|
|
it('produces an Error whose message starts with the marker and round-trips fields', () => {
|
|
const original = new GitError('commit-empty', 'No changes', { recoverable: true });
|
|
const serialized = serializeGitError(original);
|
|
expect(serialized.message.startsWith(GIT_ERROR_MARKER)).toBe(true);
|
|
const payload = JSON.parse(serialized.message.slice(GIT_ERROR_MARKER.length));
|
|
expect(payload.code).toBe('commit-empty');
|
|
expect(payload.message).toBe('No changes');
|
|
expect(payload.recoverable).toBe(true);
|
|
});
|
|
|
|
it('preserves recoverable=false from the GitError', () => {
|
|
const original = new GitError('engine-crash', 'something blew up', { recoverable: false });
|
|
const serialized = serializeGitError(original);
|
|
const payload = JSON.parse(serialized.message.slice(GIT_ERROR_MARKER.length));
|
|
expect(payload.recoverable).toBe(false);
|
|
});
|
|
|
|
it('the marker is a stable, unique string the renderer can pattern-match', () => {
|
|
expect(GIT_ERROR_MARKER).toBe('__GIT_ERROR__');
|
|
});
|
|
|
|
it('serializes auth-related and network error codes', () => {
|
|
const codes = [
|
|
'auth-failed',
|
|
'auth-required',
|
|
'clone-failed',
|
|
'network',
|
|
'pull-non-fast-forward',
|
|
] as const;
|
|
for (const code of codes) {
|
|
const original = new GitError(code, `${code} test`);
|
|
const serialized = serializeGitError(original);
|
|
const payload = JSON.parse(serialized.message.slice(GIT_ERROR_MARKER.length));
|
|
expect(payload.code).toBe(code);
|
|
}
|
|
});
|
|
|
|
it('serializes merge-related error codes', () => {
|
|
const codes = ['merge-conflict', 'merge-still-conflicted', 'merge-abort-failed'] as const;
|
|
for (const code of codes) {
|
|
const original = new GitError(code, `${code} test`);
|
|
const serialized = serializeGitError(original);
|
|
const payload = JSON.parse(serialized.message.slice(GIT_ERROR_MARKER.length));
|
|
expect(payload.code).toBe(code);
|
|
}
|
|
});
|
|
});
|