const tsConfigPaths = require("tsconfig-paths") const fs = require("fs") const path = require("path") const Module = require("module") const baseUrl = path.resolve(__dirname) const tsConfig = JSON.parse(fs.readFileSync(path.join(baseUrl, "tsconfig.json"), "utf-8")) /** * The aliases point towards the `src` directory. * However, `tsc` doesn't compile paths by itself * (https://www.typescriptlang.org/docs/handbook/modules/reference.html#paths-does-not-affect-emit) * So we need to use tsconfig-paths to resolve the aliases when running tests, * but pointing to `out` instead. */ const outPaths = {} Object.keys(tsConfig.compilerOptions.paths).forEach((key) => { const value = tsConfig.compilerOptions.paths[key] outPaths[key] = value.map((path) => path.replace("src", "out/src")) }) tsConfigPaths.register({ baseUrl: baseUrl, paths: outPaths, }) // Mock the @google/genai module to avoid ESM compatibility issues in tests // The module is ES6 only, but the integration tests are compiled to commonJS. const originalRequire = Module.prototype.require Module.prototype.require = function (id) { // Intercept requires for @google/genai if (id === "@google/genai") { // Return the mock instead const mockPath = path.join(baseUrl, "out/src/test/fixtures/google-genai-mock.js") return originalRequire.call(this, mockPath) } // The SDK packages are ESM-only and expose only an `import` condition. // Integration tests run the tsc-built `out/` tree as CommonJS in VS Code's // extension host, so `require("@cline/core")` fails before tests start. // Mock the small surface needed by legacy VS Code integration tests. if (id === "@cline/core") { const createNoopTelemetry = () => ({ setDistinctId() {}, setMetadata() {}, updateMetadata() {}, setCommonProperties() {}, updateCommonProperties() {}, isEnabled: () => false, capture() {}, captureRequired() {}, recordCounter() {}, recordHistogram() {}, recordGauge() {}, flush: async () => {}, dispose: async () => {}, }) class ProviderSettingsManager { constructor(_options) { this.state = { providers: {}, lastUsedProvider: undefined } } read() { return this.state } getLastUsedProviderSettings() { return undefined } getProviderSettings(_provider) { return undefined } saveProviderSettings(_settings, _options) {} } const getProviderAuthStorageId = (providerId) => { const normalized = String(providerId || "") .trim() .toLowerCase() if (normalized === "cline" || normalized === "cline-pass") return "cline" if (normalized === "oca" || normalized === "openai-codex") return normalized return undefined } const formatClineApiKey = (token) => { const trimmed = String(token || "").trim() return trimmed.toLowerCase().startsWith("workos:") ? trimmed : `workos:${trimmed}` } const getProviderAuthHandler = (providerId) => { const storageProviderId = getProviderAuthStorageId(providerId) if (!storageProviderId) return undefined return { providerId, storageProviderId, getApiKey(settings) { const accessToken = settings?.auth?.accessToken?.trim?.() if (accessToken) return storageProviderId === "cline" ? formatClineApiKey(accessToken) : accessToken return settings?.apiKey?.trim?.() || settings?.auth?.apiKey?.trim?.() || undefined }, } } const resolveProviderApiKeyFromSettings = (manager, providerId) => { const handler = getProviderAuthHandler(providerId) const storageProviderId = handler?.storageProviderId ?? providerId const settings = manager.getProviderSettings(storageProviderId) return handler?.getApiKey(settings) ?? settings?.apiKey?.trim?.() } const listLocalProviders = async (manager) => ({ providers: [], settingsPath: manager.getFilePath?.() ?? "" }) return { createClineTelemetryServiceConfig: (config = {}) => ({ enabled: false, metadata: { extension_version: "test", cline_type: "test", platform: "test", platform_version: "test", os_type: "test", os_version: "test", }, ...config, }), createConfiguredTelemetryHandle: () => ({ telemetry: createNoopTelemetry(), flush: async () => {}, dispose: async () => {}, }), ClineCore: class { constructor() { this.runtimeAddress = undefined this.pendingPrompts = { list: async () => [], update: async () => ({ updated: false }), delete: async () => ({ updated: false }), } } static async create() { return new this() } async start() { return { sessionId: "test-session" } } async send() { return undefined } async getAccumulatedUsage() { return { usage: undefined } } async abort() {} async stop() {} async dispose() {} async get() { return undefined } async list() { return [] } async listHistory() { return [] } async delete() { return false } async readMessages() { return [] } async update() { return { updated: false } } async ingestHookEvent() {} async updateSessionModel() {} subscribe() { return () => {} } }, ProviderSettingsManager, listLocalProviders, resolveProviderConfig: async () => undefined, getProviderConfigFields: () => [], fetchClineRecommendedModels: async () => ({ recommended: [], free: [] }), readGlobalSettings: () => ({ telemetryOptOut: false }), setTelemetryOptOutGlobally: () => undefined, prepareRemoteConfigCoreIntegration: () => undefined, createDefaultExecutors: () => ({}), createMcpTools: () => ({}), createOAuthClientCallbacks: () => ({}), getProviderAuthHandler, getProviderAuthStorageId, resolveProviderApiKeyFromSettings, getValidClineCredentials: async () => undefined, loginClineOAuth: async () => undefined, loginOcaOAuth: async () => undefined, loginOpenAICodex: async () => undefined, } } if (id === "@cline/shared") { return { buildClineSystemPrompt: () => "", createTool: (tool) => tool, formatDisplayUserInput: (input) => (typeof input === "string" ? input : JSON.stringify(input)), } } if (id === "@cline/shared/storage") { return { resolveGlobalSettingsPath: () => path.join(baseUrl, ".vscode-test", "shared-global-settings.json"), } } if (id === "@cline/llms") { return { getAllProviders: async () => [], getGeneratedModelsForProvider: () => ({}), getProviderCollectionSync: () => undefined, MODEL_COLLECTIONS_BY_PROVIDER_ID: {}, } } if (id === "vitest") { const assert = require("node:assert/strict") const makeMockFn = (implementation = () => undefined) => { const fn = (...args) => implementation(...args) fn.mock = { calls: [] } const wrapped = (...args) => { wrapped.mock.calls.push(args) return implementation(...args) } wrapped.mock = fn.mock wrapped.mockImplementation = (next) => { implementation = next return wrapped } wrapped.mockResolvedValue = (value) => wrapped.mockImplementation(() => Promise.resolve(value)) wrapped.mockReturnValue = (value) => wrapped.mockImplementation(() => value) return wrapped } const expect = (actual) => ({ toBe: (expected) => assert.equal(actual, expected), toEqual: (expected) => assert.deepEqual(actual, expected), toBeDefined: () => assert.notEqual(actual, undefined), toBeTruthy: () => assert.ok(actual), toBeGreaterThanOrEqual: (expected) => assert.ok(actual >= expected), toContain: (expected) => assert.ok(actual.includes(expected)), toHaveLength: (expected) => assert.equal(actual.length, expected), not: { toBe: (expected) => assert.notEqual(actual, expected), toContain: (expected) => assert.ok(!actual.includes(expected)), }, }) return { afterAll: globalThis.after ?? (() => undefined), afterEach: globalThis.afterEach ?? (() => undefined), beforeAll: globalThis.before ?? (() => undefined), beforeEach: globalThis.beforeEach ?? (() => undefined), describe: globalThis.describe ?? (() => undefined), expect, it: globalThis.it ?? (() => undefined), vi: { fn: makeMockFn, mock: () => undefined, mocked: (value) => value, clearAllMocks: () => undefined, restoreAllMocks: () => undefined, }, } } return originalRequire.call(this, id) }