mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-28 09:23:08 +08:00
feat: Add CodexLens Manager Page with tabbed interface for managing CodexLens features
feat: Implement ConflictTab component to display conflict resolution decisions in session detail feat: Create ImplPlanTab component to show implementation plan with modal viewer in session detail feat: Develop ReviewTab component to display review findings by dimension in session detail test: Add end-to-end tests for CodexLens Manager functionality including navigation, tab switching, and settings validation
This commit is contained in:
@@ -146,13 +146,16 @@ async function fetchApi<T>(
|
||||
status: response.status,
|
||||
};
|
||||
|
||||
try {
|
||||
const body = await response.json();
|
||||
if (body.message) error.message = body.message;
|
||||
if (body.code) error.code = body.code;
|
||||
} catch (parseError) {
|
||||
// Log parse errors instead of silently ignoring
|
||||
console.warn('[API] Failed to parse error response:', parseError);
|
||||
// Only try to parse JSON if the content type indicates JSON
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
try {
|
||||
const body = await response.json();
|
||||
if (body.message) error.message = body.message;
|
||||
if (body.code) error.code = body.code;
|
||||
} catch (parseError) {
|
||||
// Silently ignore JSON parse errors for non-JSON responses
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
@@ -599,12 +602,26 @@ export interface Issue {
|
||||
assignee?: string;
|
||||
}
|
||||
|
||||
export interface QueueItem {
|
||||
item_id: string;
|
||||
issue_id: string;
|
||||
solution_id: string;
|
||||
task_id?: string;
|
||||
status: 'pending' | 'ready' | 'executing' | 'completed' | 'failed' | 'blocked';
|
||||
execution_order: number;
|
||||
execution_group: string;
|
||||
depends_on: string[];
|
||||
semantic_priority: number;
|
||||
files_touched?: string[];
|
||||
task_count?: number;
|
||||
}
|
||||
|
||||
export interface IssueQueue {
|
||||
tasks: string[];
|
||||
solutions: string[];
|
||||
conflicts: string[];
|
||||
execution_groups: string[];
|
||||
grouped_items: Record<string, string[]>;
|
||||
grouped_items: Record<string, QueueItem[]>;
|
||||
}
|
||||
|
||||
export interface IssuesResponse {
|
||||
@@ -683,6 +700,37 @@ export async function deleteIssue(issueId: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull issues from GitHub
|
||||
*/
|
||||
export interface GitHubPullOptions {
|
||||
state?: 'open' | 'closed' | 'all';
|
||||
limit?: number;
|
||||
labels?: string;
|
||||
downloadImages?: boolean;
|
||||
}
|
||||
|
||||
export interface GitHubPullResponse {
|
||||
imported: number;
|
||||
updated: number;
|
||||
skipped: number;
|
||||
images_downloaded: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export async function pullIssuesFromGitHub(options: GitHubPullOptions = {}): Promise<GitHubPullResponse> {
|
||||
const params = new URLSearchParams();
|
||||
if (options.state) params.set('state', options.state);
|
||||
if (options.limit) params.set('limit', String(options.limit));
|
||||
if (options.labels) params.set('labels', options.labels);
|
||||
if (options.downloadImages) params.set('downloadImages', 'true');
|
||||
|
||||
const url = `/api/issues/pull${params.toString() ? '?' + params.toString() : ''}`;
|
||||
return fetchApi<GitHubPullResponse>(url, {
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate a queue
|
||||
*/
|
||||
@@ -720,6 +768,16 @@ export async function mergeQueues(sourceId: string, targetId: string, projectPat
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Split queue - split items from source queue into a new queue
|
||||
*/
|
||||
export async function splitQueue(sourceQueueId: string, itemIds: string[], projectPath: string): Promise<void> {
|
||||
return fetchApi<void>(`/api/queue/split?path=${encodeURIComponent(projectPath)}`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ sourceQueueId, itemIds }),
|
||||
});
|
||||
}
|
||||
|
||||
// ========== Discovery API ==========
|
||||
|
||||
export interface DiscoverySession {
|
||||
@@ -743,14 +801,42 @@ export interface Finding {
|
||||
line?: number;
|
||||
code_snippet?: string;
|
||||
created_at: string;
|
||||
issue_id?: string; // Associated issue ID if exported
|
||||
exported?: boolean; // Whether this finding has been exported as an issue
|
||||
}
|
||||
|
||||
export async function fetchDiscoveries(projectPath?: string): Promise<DiscoverySession[]> {
|
||||
const url = projectPath
|
||||
? `/api/discoveries?path=${encodeURIComponent(projectPath)}`
|
||||
: '/api/discoveries';
|
||||
const data = await fetchApi<{ sessions?: DiscoverySession[] }>(url);
|
||||
return data.sessions ?? [];
|
||||
const data = await fetchApi<{ discoveries?: any[]; sessions?: DiscoverySession[] }>(url);
|
||||
|
||||
// Backend returns 'discoveries' with different schema, transform to frontend format
|
||||
const rawDiscoveries = data.discoveries ?? data.sessions ?? [];
|
||||
|
||||
// Map backend schema to frontend DiscoverySession interface
|
||||
return rawDiscoveries.map((d: any) => {
|
||||
// Map phase to status
|
||||
let status: 'running' | 'completed' | 'failed' = 'running';
|
||||
if (d.phase === 'complete' || d.phase === 'completed') {
|
||||
status = 'completed';
|
||||
} else if (d.phase === 'failed') {
|
||||
status = 'failed';
|
||||
}
|
||||
|
||||
// Extract progress percentage from nested progress object
|
||||
const progress = d.progress?.perspective_analysis?.percent_complete ?? 0;
|
||||
|
||||
return {
|
||||
id: d.discovery_id || d.id,
|
||||
name: d.target_pattern || d.discovery_id || d.name || 'Discovery',
|
||||
status,
|
||||
progress,
|
||||
findings_count: d.total_findings ?? d.findings_count ?? 0,
|
||||
created_at: d.created_at,
|
||||
completed_at: d.completed_at
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchDiscoveryDetail(
|
||||
@@ -774,6 +860,27 @@ export async function fetchDiscoveryFindings(
|
||||
return data.findings ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Export findings as issues
|
||||
* @param sessionId - Discovery session ID
|
||||
* @param findingIds - Array of finding IDs to export
|
||||
* @param exportAll - Export all findings if true
|
||||
* @param projectPath - Optional project path
|
||||
*/
|
||||
export async function exportDiscoveryFindingsAsIssues(
|
||||
sessionId: string,
|
||||
{ findingIds, exportAll }: { findingIds?: string[]; exportAll?: boolean },
|
||||
projectPath?: string
|
||||
): Promise<{ success: boolean; message?: string; exported?: number }> {
|
||||
const url = projectPath
|
||||
? `/api/discoveries/${encodeURIComponent(sessionId)}/export?path=${encodeURIComponent(projectPath)}`
|
||||
: `/api/discoveries/${encodeURIComponent(sessionId)}/export`;
|
||||
return fetchApi<{ success: boolean; message?: string; exported?: number }>(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ finding_ids: findingIds, export_all: exportAll }),
|
||||
});
|
||||
}
|
||||
|
||||
// ========== Skills API ==========
|
||||
|
||||
export interface Skill {
|
||||
@@ -796,10 +903,30 @@ export interface SkillsResponse {
|
||||
* @param projectPath - Optional project path to filter data by workspace
|
||||
*/
|
||||
export async function fetchSkills(projectPath?: string): Promise<SkillsResponse> {
|
||||
const url = projectPath ? `/api/skills?path=${encodeURIComponent(projectPath)}` : '/api/skills';
|
||||
const data = await fetchApi<{ skills?: Skill[] }>(url);
|
||||
// Try with project path first, fall back to global on 403/404
|
||||
if (projectPath) {
|
||||
try {
|
||||
const url = `/api/skills?path=${encodeURIComponent(projectPath)}`;
|
||||
const data = await fetchApi<{ skills?: Skill[]; projectSkills?: Skill[]; userSkills?: Skill[] }>(url);
|
||||
const allSkills = [...(data.projectSkills ?? []), ...(data.userSkills ?? [])];
|
||||
return {
|
||||
skills: data.skills ?? allSkills,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const apiError = error as ApiError;
|
||||
if (apiError.status === 403 || apiError.status === 404) {
|
||||
// Fall back to global skills list
|
||||
console.warn('[fetchSkills] 403/404 for project path, falling back to global skills');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: fetch global skills
|
||||
const data = await fetchApi<{ skills?: Skill[]; projectSkills?: Skill[]; userSkills?: Skill[] }>('/api/skills');
|
||||
const allSkills = [...(data.projectSkills ?? []), ...(data.userSkills ?? [])];
|
||||
return {
|
||||
skills: data.skills ?? [],
|
||||
skills: data.skills ?? allSkills,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -834,10 +961,30 @@ export interface CommandsResponse {
|
||||
* @param projectPath - Optional project path to filter data by workspace
|
||||
*/
|
||||
export async function fetchCommands(projectPath?: string): Promise<CommandsResponse> {
|
||||
const url = projectPath ? `/api/commands?path=${encodeURIComponent(projectPath)}` : '/api/commands';
|
||||
const data = await fetchApi<{ commands?: Command[] }>(url);
|
||||
// Try with project path first, fall back to global on 403/404
|
||||
if (projectPath) {
|
||||
try {
|
||||
const url = `/api/commands?path=${encodeURIComponent(projectPath)}`;
|
||||
const data = await fetchApi<{ commands?: Command[]; projectCommands?: Command[]; userCommands?: Command[] }>(url);
|
||||
const allCommands = [...(data.projectCommands ?? []), ...(data.userCommands ?? [])];
|
||||
return {
|
||||
commands: data.commands ?? allCommands,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const apiError = error as ApiError;
|
||||
if (apiError.status === 403 || apiError.status === 404) {
|
||||
// Fall back to global commands list
|
||||
console.warn('[fetchCommands] 403/404 for project path, falling back to global commands');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: fetch global commands
|
||||
const data = await fetchApi<{ commands?: Command[]; projectCommands?: Command[]; userCommands?: Command[] }>('/api/commands');
|
||||
const allCommands = [...(data.projectCommands ?? []), ...(data.userCommands ?? [])];
|
||||
return {
|
||||
commands: data.commands ?? [],
|
||||
commands: data.commands ?? allCommands,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -864,12 +1011,36 @@ export interface MemoryResponse {
|
||||
* @param projectPath - Optional project path to filter data by workspace
|
||||
*/
|
||||
export async function fetchMemories(projectPath?: string): Promise<MemoryResponse> {
|
||||
const url = projectPath ? `/api/memory?path=${encodeURIComponent(projectPath)}` : '/api/memory';
|
||||
// Try with project path first, fall back to global on 403/404
|
||||
if (projectPath) {
|
||||
try {
|
||||
const url = `/api/memory?path=${encodeURIComponent(projectPath)}`;
|
||||
const data = await fetchApi<{
|
||||
memories?: CoreMemory[];
|
||||
totalSize?: number;
|
||||
claudeMdCount?: number;
|
||||
}>(url);
|
||||
return {
|
||||
memories: data.memories ?? [],
|
||||
totalSize: data.totalSize ?? 0,
|
||||
claudeMdCount: data.claudeMdCount ?? 0,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const apiError = error as ApiError;
|
||||
if (apiError.status === 403 || apiError.status === 404) {
|
||||
// Fall back to global memories list
|
||||
console.warn('[fetchMemories] 403/404 for project path, falling back to global memories');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: fetch global memories
|
||||
const data = await fetchApi<{
|
||||
memories?: CoreMemory[];
|
||||
totalSize?: number;
|
||||
claudeMdCount?: number;
|
||||
}>(url);
|
||||
}>('/api/memory');
|
||||
return {
|
||||
memories: data.memories ?? [],
|
||||
totalSize: data.totalSize ?? 0,
|
||||
@@ -1027,6 +1198,65 @@ export interface SessionDetailContext {
|
||||
tech_stack?: string[];
|
||||
conventions?: string[];
|
||||
};
|
||||
// Extended context fields for context-package.json
|
||||
context?: {
|
||||
metadata?: {
|
||||
task_description?: string;
|
||||
session_id?: string;
|
||||
complexity?: string;
|
||||
keywords?: string[];
|
||||
};
|
||||
project_context?: {
|
||||
tech_stack?: {
|
||||
languages?: Array<{ name: string; file_count?: number }>;
|
||||
frameworks?: string[];
|
||||
libraries?: string[];
|
||||
};
|
||||
architecture_patterns?: string[];
|
||||
};
|
||||
assets?: {
|
||||
documentation?: Array<{ path: string; relevance_score?: number; scope?: string; contains?: string[] }>;
|
||||
source_code?: Array<{ path: string; relevance_score?: number; scope?: string; contains?: string[] }>;
|
||||
tests?: Array<{ path: string; relevance_score?: number; scope?: string; contains?: string[] }>;
|
||||
};
|
||||
dependencies?: {
|
||||
internal?: Array<{ from: string; type: string; to: string }>;
|
||||
external?: Array<{ package: string; version?: string; usage?: string }>;
|
||||
};
|
||||
test_context?: {
|
||||
frameworks?: {
|
||||
backend?: { name?: string; plugins?: string[] };
|
||||
frontend?: { name?: string };
|
||||
};
|
||||
existing_tests?: string[];
|
||||
coverage_config?: Record<string, unknown>;
|
||||
test_markers?: string[];
|
||||
};
|
||||
conflict_detection?: {
|
||||
risk_level?: 'low' | 'medium' | 'high' | 'critical';
|
||||
mitigation_strategy?: string;
|
||||
risk_factors?: {
|
||||
test_gaps?: string[];
|
||||
existing_implementations?: string[];
|
||||
};
|
||||
affected_modules?: string[];
|
||||
};
|
||||
};
|
||||
explorations?: {
|
||||
manifest: {
|
||||
task_description: string;
|
||||
complexity?: string;
|
||||
exploration_count: number;
|
||||
};
|
||||
data: Record<string, {
|
||||
project_structure?: string[];
|
||||
relevant_files?: string[];
|
||||
patterns?: string[];
|
||||
dependencies?: string[];
|
||||
integration_points?: string[];
|
||||
testing?: string[];
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SessionDetailResponse {
|
||||
@@ -1136,6 +1366,47 @@ export async function deleteAllHistory(): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
// ========== Task Status Update API ==========
|
||||
|
||||
/**
|
||||
* Bulk update task status for multiple tasks
|
||||
* @param sessionPath - Path to session directory
|
||||
* @param taskIds - Array of task IDs to update
|
||||
* @param newStatus - New status to set
|
||||
*/
|
||||
export async function bulkUpdateTaskStatus(
|
||||
sessionPath: string,
|
||||
taskIds: string[],
|
||||
newStatus: TaskStatus
|
||||
): Promise<{ success: boolean; updated: number; error?: string }> {
|
||||
return fetchApi('/api/bulk-update-task-status', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionPath, taskIds, newStatus }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update single task status
|
||||
* @param sessionPath - Path to session directory
|
||||
* @param taskId - Task ID to update
|
||||
* @param newStatus - New status to set
|
||||
*/
|
||||
export async function updateTaskStatus(
|
||||
sessionPath: string,
|
||||
taskId: string,
|
||||
newStatus: TaskStatus
|
||||
): Promise<{ success: boolean; error?: string }> {
|
||||
return fetchApi('/api/update-task-status', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionPath, taskId, newStatus }),
|
||||
});
|
||||
}
|
||||
|
||||
// Task status type (matches TaskData.status)
|
||||
export type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'skipped';
|
||||
|
||||
/**
|
||||
* Fetch CLI execution detail (conversation records)
|
||||
*/
|
||||
@@ -1728,10 +1999,30 @@ export async function installHookTemplate(templateId: string): Promise<Hook> {
|
||||
* @param projectPath - Optional project path to filter data by workspace
|
||||
*/
|
||||
export async function fetchRules(projectPath?: string): Promise<RulesResponse> {
|
||||
const url = projectPath ? `/api/rules?path=${encodeURIComponent(projectPath)}` : '/api/rules';
|
||||
const data = await fetchApi<{ rules?: Rule[] }>(url);
|
||||
// Try with project path first, fall back to global on 403/404
|
||||
if (projectPath) {
|
||||
try {
|
||||
const url = `/api/rules?path=${encodeURIComponent(projectPath)}`;
|
||||
const data = await fetchApi<{ rules?: Rule[]; projectRules?: Rule[]; userRules?: Rule[] }>(url);
|
||||
const allRules = [...(data.projectRules ?? []), ...(data.userRules ?? [])];
|
||||
return {
|
||||
rules: data.rules ?? allRules,
|
||||
};
|
||||
} catch (error: unknown) {
|
||||
const apiError = error as ApiError;
|
||||
if (apiError.status === 403 || apiError.status === 404) {
|
||||
// Fall back to global rules list
|
||||
console.warn('[fetchRules] 403/404 for project path, falling back to global rules');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: fetch global rules
|
||||
const data = await fetchApi<{ rules?: Rule[]; projectRules?: Rule[]; userRules?: Rule[] }>('/api/rules');
|
||||
const allRules = [...(data.projectRules ?? []), ...(data.userRules ?? [])];
|
||||
return {
|
||||
rules: data.rules ?? [],
|
||||
rules: data.rules ?? allRules,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2091,3 +2382,428 @@ export async function fetchGraphImpact(request: GraphImpactRequest): Promise<Gra
|
||||
return fetchApi<GraphImpactResponse>(`/api/graph/impact?${params.toString()}`);
|
||||
}
|
||||
|
||||
// ========== CodexLens API ==========
|
||||
|
||||
/**
|
||||
* CodexLens venv status response
|
||||
*/
|
||||
export interface CodexLensVenvStatus {
|
||||
ready: boolean;
|
||||
installed: boolean;
|
||||
version?: string;
|
||||
pythonVersion?: string;
|
||||
venvPath?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* CodexLens status data
|
||||
*/
|
||||
export interface CodexLensStatusData {
|
||||
projects_count?: number;
|
||||
total_files?: number;
|
||||
total_chunks?: number;
|
||||
api_url?: string;
|
||||
api_ready?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* CodexLens configuration
|
||||
*/
|
||||
export interface CodexLensConfig {
|
||||
index_dir: string;
|
||||
index_count: number;
|
||||
api_max_workers: number;
|
||||
api_batch_size: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic search status
|
||||
*/
|
||||
export interface CodexLensSemanticStatus {
|
||||
available: boolean;
|
||||
backend?: string;
|
||||
model?: string;
|
||||
hasEmbeddings?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard init response
|
||||
*/
|
||||
export interface CodexLensDashboardInitResponse {
|
||||
installed: boolean;
|
||||
status: CodexLensVenvStatus;
|
||||
config: CodexLensConfig;
|
||||
semantic: CodexLensSemanticStatus;
|
||||
statusData?: CodexLensStatusData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workspace index status
|
||||
*/
|
||||
export interface CodexLensWorkspaceStatus {
|
||||
success: boolean;
|
||||
hasIndex: boolean;
|
||||
path?: string;
|
||||
fts: {
|
||||
percent: number;
|
||||
indexedFiles: number;
|
||||
totalFiles: number;
|
||||
};
|
||||
vector: {
|
||||
percent: number;
|
||||
filesWithEmbeddings: number;
|
||||
totalFiles: number;
|
||||
totalChunks: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* GPU device info
|
||||
*/
|
||||
export interface CodexLensGpuDevice {
|
||||
name: string;
|
||||
type: 'integrated' | 'discrete';
|
||||
index: number;
|
||||
device_id?: string;
|
||||
memory?: {
|
||||
total?: number;
|
||||
free?: number;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* GPU detect response
|
||||
*/
|
||||
export interface CodexLensGpuDetectResponse {
|
||||
success: boolean;
|
||||
supported: boolean;
|
||||
platform: string;
|
||||
deviceCount?: number;
|
||||
devices?: CodexLensGpuDevice[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* GPU list response
|
||||
*/
|
||||
export interface CodexLensGpuListResponse {
|
||||
success: boolean;
|
||||
devices: CodexLensGpuDevice[];
|
||||
selected_device_id?: string | number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model info
|
||||
*/
|
||||
export interface CodexLensModel {
|
||||
profile: string;
|
||||
name: string;
|
||||
type: 'embedding' | 'reranker';
|
||||
backend: string;
|
||||
size?: string;
|
||||
installed: boolean;
|
||||
cache_path?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model list response
|
||||
*/
|
||||
export interface CodexLensModelsResponse {
|
||||
success: boolean;
|
||||
models: CodexLensModel[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Model info response
|
||||
*/
|
||||
export interface CodexLensModelInfoResponse {
|
||||
success: boolean;
|
||||
profile: string;
|
||||
info: {
|
||||
name: string;
|
||||
backend: string;
|
||||
type: string;
|
||||
size?: string;
|
||||
path?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Download model response
|
||||
*/
|
||||
export interface CodexLensDownloadModelResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
profile?: string;
|
||||
progress?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete model response
|
||||
*/
|
||||
export interface CodexLensDeleteModelResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Environment variables response
|
||||
*/
|
||||
export interface CodexLensEnvResponse {
|
||||
success: boolean;
|
||||
path?: string;
|
||||
env: Record<string, string>;
|
||||
raw?: string;
|
||||
settings?: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update environment request
|
||||
*/
|
||||
export interface CodexLensUpdateEnvRequest {
|
||||
env: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update environment response
|
||||
*/
|
||||
export interface CodexLensUpdateEnvResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
path?: string;
|
||||
settingsPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore patterns response
|
||||
*/
|
||||
export interface CodexLensIgnorePatternsResponse {
|
||||
success: boolean;
|
||||
patterns: string[];
|
||||
extensionFilters: string[];
|
||||
defaults: {
|
||||
patterns: string[];
|
||||
extensionFilters: string[];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ignore patterns request
|
||||
*/
|
||||
export interface CodexLensUpdateIgnorePatternsRequest {
|
||||
patterns?: string[];
|
||||
extensionFilters?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap install response
|
||||
*/
|
||||
export interface CodexLensBootstrapResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
version?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall response
|
||||
*/
|
||||
export interface CodexLensUninstallResponse {
|
||||
success: boolean;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens dashboard initialization data
|
||||
*/
|
||||
export async function fetchCodexLensDashboardInit(): Promise<CodexLensDashboardInitResponse> {
|
||||
return fetchApi<CodexLensDashboardInitResponse>('/api/codexlens/dashboard-init');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens venv status
|
||||
*/
|
||||
export async function fetchCodexLensStatus(): Promise<CodexLensVenvStatus> {
|
||||
return fetchApi<CodexLensVenvStatus>('/api/codexlens/status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens workspace index status
|
||||
*/
|
||||
export async function fetchCodexLensWorkspaceStatus(projectPath: string): Promise<CodexLensWorkspaceStatus> {
|
||||
const params = new URLSearchParams();
|
||||
params.append('path', projectPath);
|
||||
return fetchApi<CodexLensWorkspaceStatus>(`/api/codexlens/workspace-status?${params.toString()}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens configuration
|
||||
*/
|
||||
export async function fetchCodexLensConfig(): Promise<CodexLensConfig> {
|
||||
return fetchApi<CodexLensConfig>('/api/codexlens/config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update CodexLens configuration
|
||||
*/
|
||||
export async function updateCodexLensConfig(config: {
|
||||
index_dir: string;
|
||||
api_max_workers?: number;
|
||||
api_batch_size?: number;
|
||||
}): Promise<{ success: boolean; message?: string; error?: string }> {
|
||||
return fetchApi('/api/codexlens/config', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(config),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap/install CodexLens
|
||||
*/
|
||||
export async function bootstrapCodexLens(): Promise<CodexLensBootstrapResponse> {
|
||||
return fetchApi<CodexLensBootstrapResponse>('/api/codexlens/bootstrap', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall CodexLens
|
||||
*/
|
||||
export async function uninstallCodexLens(): Promise<CodexLensUninstallResponse> {
|
||||
return fetchApi<CodexLensUninstallResponse>('/api/codexlens/uninstall', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens models list
|
||||
*/
|
||||
export async function fetchCodexLensModels(): Promise<CodexLensModelsResponse> {
|
||||
return fetchApi<CodexLensModelsResponse>('/api/codexlens/models');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens model info by profile
|
||||
*/
|
||||
export async function fetchCodexLensModelInfo(profile: string): Promise<CodexLensModelInfoResponse> {
|
||||
const params = new URLSearchParams();
|
||||
params.append('profile', profile);
|
||||
return fetchApi<CodexLensModelInfoResponse>(`/api/codexlens/models/info?${params.toString()}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download CodexLens model by profile
|
||||
*/
|
||||
export async function downloadCodexLensModel(profile: string): Promise<CodexLensDownloadModelResponse> {
|
||||
return fetchApi<CodexLensDownloadModelResponse>('/api/codexlens/models/download', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ profile }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Download custom CodexLens model from HuggingFace
|
||||
*/
|
||||
export async function downloadCodexLensCustomModel(modelName: string, modelType: string = 'embedding'): Promise<CodexLensDownloadModelResponse> {
|
||||
return fetchApi<CodexLensDownloadModelResponse>('/api/codexlens/models/download-custom', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ model_name: modelName, model_type: modelType }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete CodexLens model by profile
|
||||
*/
|
||||
export async function deleteCodexLensModel(profile: string): Promise<CodexLensDeleteModelResponse> {
|
||||
return fetchApi<CodexLensDeleteModelResponse>('/api/codexlens/models/delete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ profile }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete CodexLens model by cache path
|
||||
*/
|
||||
export async function deleteCodexLensModelByPath(cachePath: string): Promise<CodexLensDeleteModelResponse> {
|
||||
return fetchApi<CodexLensDeleteModelResponse>('/api/codexlens/models/delete-path', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ cache_path: cachePath }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens environment variables
|
||||
*/
|
||||
export async function fetchCodexLensEnv(): Promise<CodexLensEnvResponse> {
|
||||
return fetchApi<CodexLensEnvResponse>('/api/codexlens/env');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update CodexLens environment variables
|
||||
*/
|
||||
export async function updateCodexLensEnv(request: CodexLensUpdateEnvRequest): Promise<CodexLensUpdateEnvResponse> {
|
||||
return fetchApi<CodexLensUpdateEnvResponse>('/api/codexlens/env', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect GPU support for CodexLens
|
||||
*/
|
||||
export async function fetchCodexLensGpuDetect(): Promise<CodexLensGpuDetectResponse> {
|
||||
return fetchApi<CodexLensGpuDetectResponse>('/api/codexlens/gpu/detect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch available GPU devices
|
||||
*/
|
||||
export async function fetchCodexLensGpuList(): Promise<CodexLensGpuListResponse> {
|
||||
return fetchApi<CodexLensGpuListResponse>('/api/codexlens/gpu/list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Select GPU device for CodexLens
|
||||
*/
|
||||
export async function selectCodexLensGpu(deviceId: string | number): Promise<{ success: boolean; message?: string; error?: string }> {
|
||||
return fetchApi('/api/codexlens/gpu/select', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ device_id: deviceId }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset GPU selection to auto-detection
|
||||
*/
|
||||
export async function resetCodexLensGpu(): Promise<{ success: boolean; message?: string; error?: string }> {
|
||||
return fetchApi('/api/codexlens/gpu/reset', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch CodexLens ignore patterns
|
||||
*/
|
||||
export async function fetchCodexLensIgnorePatterns(): Promise<CodexLensIgnorePatternsResponse> {
|
||||
return fetchApi<CodexLensIgnorePatternsResponse>('/api/codexlens/ignore-patterns');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update CodexLens ignore patterns
|
||||
*/
|
||||
export async function updateCodexLensIgnorePatterns(request: CodexLensUpdateIgnorePatternsRequest): Promise<CodexLensIgnorePatternsResponse> {
|
||||
return fetchApi<CodexLensIgnorePatternsResponse>('/api/codexlens/ignore-patterns', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user