Files
openclaude/src/utils/apiPreconnect.test.ts
T
chioarubandGitHub 102cc3060f feat(goal): add session-scoped /goal continuation (#1293)
* feat(goal): add persisted session goal state

Introduce the session-scoped goal state model, bounded evaluator, continuation controller, and transcript metadata persistence. Restore active goals on session resume while keeping achieved and cleared goals from auto-running.

* feat(goal): add slash command controls

Register /goal as a lazy local command with set, status, pause, resume, clear, and clear aliases. Route command-started continuations through hidden meta messages and make /clear clear active goal state.

* feat(goal): continue goals through stop hooks

Evaluate active goals once per terminal assistant turn after configured Stop hooks pass. Incomplete goals reuse the blocking-error continuation path; complete goals persist achieved status without spawning a parallel queue.

* test(goal): cover commands continuation and resume

Add focused coverage for command validation and aliases, state transitions, evaluator malformed-output handling, Stop-hook precedence, SDK/headless visibility, /clear lifecycle behavior, and durable resume persistence.

* fix(goal): fail closed on evaluator failures

* fix(goal): clear stale goal on resume

* Persist goal continuations before auto-resume

* test: isolate CI-sensitive state

* test: isolate attribution provider state

* test: tighten CI state isolation

* fix(goal): clear cached metadata on resume

* test(goal): harden resume metadata coverage

* test: clean up teammate model fixture merge

* fix(goal): align persistence session id type

* fix(goal): address status command review

* fix(goal): address follow-up review comments

* test(goal): isolate review regression coverage

* test(goal): make queryengine fixture ci-safe

* fix(goal): clarify resume message

* test: restore api preconnect provider mock

* fix(goal): address review feedback
2026-06-09 07:55:49 +08:00

126 lines
4.3 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
import {
acquireSharedMutationLock,
releaseSharedMutationLock,
} from '../test/sharedMutationLock.js'
import * as actualProviders from './model/providers.js'
const originalEnv = { ...process.env }
const originalFetch = globalThis.fetch
function getMockApiProvider() {
if (process.env.CLAUDE_CODE_USE_OPENAI === '1') return 'openai'
if (process.env.CLAUDE_CODE_USE_GEMINI === '1') return 'gemini'
if (process.env.CLAUDE_CODE_USE_GITHUB === '1') return 'github'
return 'firstParty'
}
async function importFreshModule() {
mock.restore()
mock.module('./model/providers.js', () => ({
...actualProviders,
getAPIProvider: getMockApiProvider,
}))
return import(`./apiPreconnect.ts?ts=${Date.now()}-${Math.random()}`)
}
beforeEach(async () => {
await acquireSharedMutationLock('utils/apiPreconnect.test.ts')
process.env = { ...originalEnv }
})
afterEach(() => {
try {
process.env = { ...originalEnv }
globalThis.fetch = originalFetch
mock.restore()
mock.module('./model/providers.js', () => actualProviders)
} finally {
releaseSharedMutationLock()
}
})
describe('preconnectAnthropicApi', () => {
// The provider is injected directly rather than mocking getAPIProvider():
// bun does not unregister mock.module() overrides, so a leaked providers.js
// mock from another test file (e.g. fastMode) would otherwise force
// getAPIProvider() to 'firstParty' here and break these assertions.
test('does not fetch when OpenAI mode is enabled', async () => {
const fetchMock = mock(() => Promise.resolve(new Response(null, { status: 200 })))
globalThis.fetch = fetchMock as typeof globalThis.fetch
const { preconnectAnthropicApi } = await importFreshModule()
preconnectAnthropicApi('openai')
expect(fetchMock).not.toHaveBeenCalled()
})
test('does not fetch when Gemini mode is enabled', async () => {
const fetchMock = mock(() => Promise.resolve(new Response(null, { status: 200 })))
globalThis.fetch = fetchMock as typeof globalThis.fetch
const { preconnectAnthropicApi } = await importFreshModule()
preconnectAnthropicApi('gemini')
expect(fetchMock).not.toHaveBeenCalled()
})
test('does not fetch when GitHub mode is enabled', async () => {
const fetchMock = mock(() => Promise.resolve(new Response(null, { status: 200 })))
globalThis.fetch = fetchMock as typeof globalThis.fetch
const { preconnectAnthropicApi } = await importFreshModule()
preconnectAnthropicApi('github')
expect(fetchMock).not.toHaveBeenCalled()
})
test('fetches in first-party mode', async () => {
delete process.env.CLAUDE_CODE_USE_OPENAI
delete process.env.CLAUDE_CODE_USE_GEMINI
delete process.env.CLAUDE_CODE_USE_GITHUB
delete process.env.CLAUDE_CODE_USE_MISTRAL
delete process.env.CLAUDE_CODE_USE_BEDROCK
delete process.env.CLAUDE_CODE_USE_VERTEX
delete process.env.CLAUDE_CODE_USE_FOUNDRY
delete process.env.OPENAI_BASE_URL
delete process.env.OPENAI_API_BASE
delete process.env.OPENAI_MODEL
delete process.env.OPENAI_API_KEY
delete process.env.XAI_API_KEY
delete process.env.MINIMAX_API_KEY
delete process.env.VENICE_API_KEY
delete process.env.MIMO_API_KEY
delete process.env.NVIDIA_NIM
delete process.env.ANTHROPIC_BASE_URL
delete process.env.ANTHROPIC_API_KEY
delete process.env.HTTPS_PROXY
delete process.env.https_proxy
delete process.env.HTTP_PROXY
delete process.env.http_proxy
delete process.env.ANTHROPIC_UNIX_SOCKET
delete process.env.CLAUDE_CODE_CLIENT_CERT
delete process.env.CLAUDE_CODE_CLIENT_KEY
mock.module('./model/providers.js', () => ({
...actualProviders,
getAPIProvider: () => 'firstParty',
}))
const fetchMock = mock(() => Promise.resolve(new Response(null, { status: 200 })))
globalThis.fetch = fetchMock as typeof globalThis.fetch
const { preconnectAnthropicApi } = await importFreshModule()
preconnectAnthropicApi('firstParty')
expect(fetchMock).toHaveBeenCalledTimes(1)
})
test('keeps non-mocked provider exports available to neighboring imports', async () => {
await importFreshModule()
const providers = await import('./model/providers.js')
expect(typeof providers.isFirstPartyAnthropicBaseUrl).toBe('function')
})
})