feat: add SpecDialog component for editing spec frontmatter

- Implement SpecDialog for managing spec details including title, read mode, priority, and keywords.
- Add validation and keyword management functionality.
- Integrate SpecDialog into SpecsSettingsPage for editing specs.

feat: create index file for specs components

- Export SpecCard, SpecDialog, and related types from a new index file for better organization.

feat: implement SpecsSettingsPage for managing specs and hooks

- Create main settings page with tabs for Project Specs, Personal Specs, Hooks, Injection, and Settings.
- Integrate SpecDialog and HookDialog for editing specs and hooks.
- Add search functionality and mock data for specs and hooks.

feat: add spec management API routes

- Implement API endpoints for listing specs, getting spec details, updating frontmatter, rebuilding indices, and initializing the spec system.
- Handle errors and responses appropriately for each endpoint.
This commit is contained in:
catlog22
2026-02-26 22:03:13 +08:00
parent 430d817e43
commit 6155fcc7b8
115 changed files with 4883 additions and 21127 deletions

View File

@@ -728,13 +728,26 @@ export interface Issue {
id: string;
title: string;
context?: string;
status: 'open' | 'in_progress' | 'resolved' | 'closed' | 'completed';
status: 'registered' | 'planning' | 'planned' | 'queued' | 'executing' | 'completed' | 'failed' | 'paused';
priority: 'low' | 'medium' | 'high' | 'critical';
createdAt: string;
updatedAt?: string;
plannedAt?: string;
queuedAt?: string;
completedAt?: string;
solutions?: IssueSolution[];
labels?: string[];
assignee?: string;
tags?: string[];
source?: 'github' | 'text' | 'discovery';
sourceUrl?: string;
boundSolutionId?: string | null;
feedback?: Array<{
type: 'failure' | 'clarification' | 'rejection';
stage: string;
content: string;
createdAt: string;
}>;
attachments?: Attachment[];
}
@@ -7133,6 +7146,121 @@ export async function triggerReindex(
);
}
// ========== System Settings API ==========
/**
* System settings response from /api/system/settings
*/
export interface SystemSettings {
injectionControl: {
maxLength: number;
warnThreshold: number;
truncateOnExceed: boolean;
};
personalSpecDefaults: {
defaultReadMode: 'required' | 'optional' | 'keywords';
autoEnable: boolean;
};
recommendedHooks: Array<{
id: string;
event: string;
name: string;
command: string;
description: string;
scope: 'global' | 'project';
autoInstall: boolean;
}>;
}
/**
* Update system settings request
*/
export interface UpdateSystemSettingsInput {
injectionControl?: Partial<SystemSettings['injectionControl']>;
personalSpecDefaults?: Partial<SystemSettings['personalSpecDefaults']>;
}
/**
* Install recommended hooks request
*/
export interface InstallRecommendedHooksInput {
hookIds: string[];
scope?: 'global' | 'project';
}
/**
* Installed hook result
*/
export interface InstalledHook {
id: string;
event: string;
status: 'installed' | 'already-exists';
}
/**
* Install recommended hooks response
*/
export interface InstallRecommendedHooksResponse {
success: boolean;
installed: InstalledHook[];
}
/**
* Fetch system settings (injection control, personal spec defaults, recommended hooks)
*/
export async function getSystemSettings(): Promise<SystemSettings> {
return fetchApi<SystemSettings>('/api/system/settings');
}
/**
* Update system settings
*/
export async function updateSystemSettings(data: UpdateSystemSettingsInput): Promise<{ success: boolean; settings?: Record<string, unknown> }> {
return fetchApi<{ success: boolean; settings?: Record<string, unknown> }>('/api/system/settings', {
method: 'POST',
body: JSON.stringify(data),
});
}
/**
* Install recommended hooks
*/
export async function installRecommendedHooks(
hookIds: string[],
scope?: 'global' | 'project'
): Promise<InstallRecommendedHooksResponse> {
return fetchApi<InstallRecommendedHooksResponse>('/api/system/hooks/install-recommended', {
method: 'POST',
body: JSON.stringify({ hookIds, scope } as InstallRecommendedHooksInput),
});
}
// ========== Spec Stats API ==========
/**
* Spec stats response from /api/specs/stats
*/
export interface SpecStats {
dimensions: Record<string, { count: number; requiredCount: number }>;
injectionLength: {
requiredOnly: number;
withKeywords: number;
maxLength: number;
percentage: number;
};
}
/**
* Fetch spec statistics for a specific workspace
* @param projectPath - Optional project path to filter data by workspace
*/
export async function getSpecStats(projectPath?: string): Promise<SpecStats> {
const url = projectPath
? `/api/specs/stats?path=${encodeURIComponent(projectPath)}`
: '/api/specs/stats';
return fetchApi<SpecStats>(url);
}
// ========== Analysis API ==========
import type { AnalysisSessionSummary, AnalysisSessionDetail } from '../types/analysis';