Merge branch 'main' into mcp-rebased-2

# Conflicts:
#	server/claude-sdk.js
#	server/cursor-cli.js
#	server/gemini-cli.js
#	server/openai-codex.js
#	server/providers/cursor/adapter.js
#	server/providers/registry.js
#	server/providers/types.js
#	server/routes/cli-auth.js
#	server/routes/cursor.js
This commit is contained in:
Haileyesus
2026-04-17 19:47:10 +03:00
25 changed files with 488 additions and 1161 deletions

View File

@@ -1,4 +1,5 @@
import crypto from 'node:crypto';
import { createRequire } from 'node:module';
import os from 'node:os';
import path from 'node:path';
@@ -10,9 +11,22 @@ import type { FetchHistoryOptions, FetchHistoryResult, NormalizedMessage } from
import { createNormalizedMessage, generateMessageId, readObjectRecord } from '@/shared/utils.js';
const PROVIDER = 'cursor';
const nodeRequire = createRequire(import.meta.url);
type RawProviderMessage = Record<string, any>;
type BetterSqliteDatabase = {
prepare(sql: string): {
all(): CursorDbBlob[];
};
close(): void;
};
type BetterSqliteConstructor = new (
filename: string,
options: { readonly: boolean; fileMustExist: boolean },
) => BetterSqliteDatabase;
type CursorDbBlob = {
rowid: number;
id: string;
@@ -47,21 +61,15 @@ export class CursorProvider extends AbstractProvider {
* order. Cursor history is stored as content-addressed blobs rather than JSONL.
*/
private async loadCursorBlobs(sessionId: string, projectPath: string): Promise<CursorMessageBlob[]> {
const sqlite3Module = await import('sqlite3');
const sqlite3 = sqlite3Module.default;
const { open } = await import('sqlite');
const Database = nodeRequire('better-sqlite3') as BetterSqliteConstructor;
const cwdId = crypto.createHash('md5').update(projectPath || process.cwd()).digest('hex');
const storeDbPath = path.join(os.homedir(), '.cursor', 'chats', cwdId, sessionId, 'store.db');
const db = await open({
filename: storeDbPath,
driver: sqlite3.Database,
mode: sqlite3.OPEN_READONLY,
});
const db = new Database(storeDbPath, { readonly: true, fileMustExist: true });
try {
const allBlobs = await db.all('SELECT rowid, id, data FROM blobs') as CursorDbBlob[];
const allBlobs = db.prepare('SELECT rowid, id, data FROM blobs').all();
const blobMap = new Map<string, CursorDbBlob>();
const parentRefs = new Map<string, string[]>();
@@ -170,7 +178,7 @@ export class CursorProvider extends AbstractProvider {
return messages;
} finally {
await db.close();
db.close();
}
}

View File

@@ -1,5 +1,5 @@
import { providerRegistry } from '@/modules/providers/provider.registry.js';
import type { ProviderAuthStatus } from '@/shared/types.js';
import type { LLMProvider, ProviderAuthStatus } from '@/shared/types.js';
export const providerAuthService = {
/**
@@ -9,4 +9,18 @@ export const providerAuthService = {
const provider = providerRegistry.resolveProvider(providerName);
return provider.auth.getStatus();
},
/**
* Returns whether a provider runtime appears installed.
* Falls back to true if status lookup itself fails so callers preserve the
* original runtime error instead of replacing it with a status-check failure.
*/
async isProviderInstalled(providerName: LLMProvider): Promise<boolean> {
try {
const status = await this.getProviderAuthStatus(providerName);
return status.installed;
} catch {
return true;
}
},
};