@claudetools/tools 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,159 @@
1
+ // =============================================================================
2
+ // CodeDNA Monitoring Dashboard
3
+ // =============================================================================
4
+ //
5
+ // Query functions for monitoring CodeDNA performance and error rates.
6
+ //
7
+ import { getErrorRate } from './error-tracking.js';
8
+ /**
9
+ * Get dashboard metrics for a time range
10
+ */
11
+ export async function getDashboardMetrics(startTime, endTime) {
12
+ const errorMetrics = await getErrorRate({ startTime, endTime });
13
+ const alerts = [];
14
+ const recommendations = [];
15
+ // Check error rate threshold (>5% is warning, >10% is critical)
16
+ if (errorMetrics.errorRate > 10) {
17
+ alerts.push({
18
+ level: 'critical',
19
+ message: 'CodeDNA error rate exceeds 10%',
20
+ metric: 'error_rate',
21
+ value: errorMetrics.errorRate,
22
+ threshold: 10,
23
+ });
24
+ recommendations.push('Investigate template fetch errors and validation failures');
25
+ recommendations.push('Check Cloudflare Workers logs for registry issues');
26
+ }
27
+ else if (errorMetrics.errorRate > 5) {
28
+ alerts.push({
29
+ level: 'warning',
30
+ message: 'CodeDNA error rate exceeds 5%',
31
+ metric: 'error_rate',
32
+ value: errorMetrics.errorRate,
33
+ threshold: 5,
34
+ });
35
+ recommendations.push('Monitor error trends over next 24 hours');
36
+ }
37
+ // Check validation errors
38
+ const validationErrors = errorMetrics.errorsByType['validation_error'] || 0;
39
+ if (validationErrors > errorMetrics.totalErrors * 0.5) {
40
+ alerts.push({
41
+ level: 'info',
42
+ message: 'High percentage of validation errors (>50%)',
43
+ metric: 'validation_error_rate',
44
+ value: (validationErrors / errorMetrics.totalErrors) * 100,
45
+ threshold: 50,
46
+ });
47
+ recommendations.push('Review Entity DSL documentation with users');
48
+ recommendations.push('Consider adding Entity DSL syntax examples to error messages');
49
+ }
50
+ // Check template fetch errors
51
+ const templateErrors = errorMetrics.errorsByType['template_error'] || 0;
52
+ if (templateErrors > 3) {
53
+ alerts.push({
54
+ level: 'warning',
55
+ message: 'Multiple template fetch errors detected',
56
+ metric: 'template_errors',
57
+ value: templateErrors,
58
+ threshold: 3,
59
+ });
60
+ recommendations.push('Verify Cloudflare Workers deployment is healthy');
61
+ recommendations.push('Check R2 storage bucket access');
62
+ recommendations.push('Verify DOCS_CACHE KV namespace is operational');
63
+ }
64
+ // Check network errors
65
+ const networkErrors = errorMetrics.errorsByType['network_error'] || 0;
66
+ if (networkErrors > 2) {
67
+ alerts.push({
68
+ level: 'warning',
69
+ message: 'Network connectivity issues detected',
70
+ metric: 'network_errors',
71
+ value: networkErrors,
72
+ threshold: 2,
73
+ });
74
+ recommendations.push('Check api.claudetools.dev availability');
75
+ recommendations.push('Verify network connection and firewall rules');
76
+ }
77
+ return {
78
+ timeRange: `${startTime} to ${endTime}`,
79
+ errorMetrics,
80
+ alerts,
81
+ recommendations,
82
+ };
83
+ }
84
+ /**
85
+ * Get error metrics for last 24 hours
86
+ */
87
+ export async function getLast24Hours() {
88
+ const endTime = new Date().toISOString();
89
+ const startTime = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
90
+ return getDashboardMetrics(startTime, endTime);
91
+ }
92
+ /**
93
+ * Get error metrics for last 7 days
94
+ */
95
+ export async function getLast7Days() {
96
+ const endTime = new Date().toISOString();
97
+ const startTime = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
98
+ return getDashboardMetrics(startTime, endTime);
99
+ }
100
+ /**
101
+ * Print dashboard to console
102
+ */
103
+ export function printDashboard(metrics) {
104
+ console.log('\n=================================================');
105
+ console.log('CodeDNA Monitoring Dashboard');
106
+ console.log('=================================================\n');
107
+ console.log(`Time Range: ${metrics.timeRange}\n`);
108
+ console.log('Error Metrics:');
109
+ console.log(` Total Errors: ${metrics.errorMetrics.totalErrors}`);
110
+ console.log(` Error Rate: ${metrics.errorMetrics.errorRate.toFixed(2)}%\n`);
111
+ console.log('Errors by Type:');
112
+ Object.entries(metrics.errorMetrics.errorsByType).forEach(([type, count]) => {
113
+ console.log(` ${type}: ${count}`);
114
+ });
115
+ console.log();
116
+ console.log('Errors by Operation:');
117
+ Object.entries(metrics.errorMetrics.errorsByOperation).forEach(([op, count]) => {
118
+ console.log(` ${op}: ${count}`);
119
+ });
120
+ console.log();
121
+ if (metrics.alerts.length > 0) {
122
+ console.log('Alerts:');
123
+ metrics.alerts.forEach(alert => {
124
+ const emoji = alert.level === 'critical' ? '🔴' : alert.level === 'warning' ? '🟡' : 'ℹ️';
125
+ console.log(` ${emoji} [${alert.level.toUpperCase()}] ${alert.message}`);
126
+ console.log(` ${alert.metric}: ${alert.value} (threshold: ${alert.threshold})`);
127
+ });
128
+ console.log();
129
+ }
130
+ if (metrics.recommendations.length > 0) {
131
+ console.log('Recommendations:');
132
+ metrics.recommendations.forEach((rec, i) => {
133
+ console.log(` ${i + 1}. ${rec}`);
134
+ });
135
+ console.log();
136
+ }
137
+ if (metrics.errorMetrics.recentErrors.length > 0) {
138
+ console.log('Recent Errors (last 10):');
139
+ metrics.errorMetrics.recentErrors.forEach((error, i) => {
140
+ console.log(` ${i + 1}. [${error.timestamp}] ${error.operation}`);
141
+ console.log(` Type: ${error.errorType}`);
142
+ console.log(` Message: ${error.errorMessage}`);
143
+ });
144
+ }
145
+ console.log('\n=================================================\n');
146
+ }
147
+ /**
148
+ * CLI command: npm run codedna:monitor
149
+ */
150
+ export async function runMonitoring() {
151
+ console.log('Fetching CodeDNA metrics for last 24 hours...\n');
152
+ const metrics = await getLast24Hours();
153
+ printDashboard(metrics);
154
+ // Exit with error code if critical alerts
155
+ const hasCritical = metrics.alerts.some(a => a.level === 'critical');
156
+ if (hasCritical) {
157
+ process.exit(1);
158
+ }
159
+ }
@@ -0,0 +1,73 @@
1
+ export interface CodeDNAError {
2
+ timestamp: string;
3
+ operation: 'generate_api' | 'generate_frontend' | 'generate_component' | 'validate_spec' | 'list_generators' | 'template_fetch';
4
+ errorType: 'validation_error' | 'generation_error' | 'template_error' | 'network_error' | 'unknown_error';
5
+ errorMessage: string;
6
+ context: {
7
+ spec?: string;
8
+ framework?: string;
9
+ generatorId?: string;
10
+ templateFile?: string;
11
+ stackTrace?: string;
12
+ };
13
+ projectId?: string;
14
+ }
15
+ export declare class CodeDNAErrorTracker {
16
+ private static instance;
17
+ private constructor();
18
+ static getInstance(): CodeDNAErrorTracker;
19
+ /**
20
+ * Track a CodeDNA error
21
+ */
22
+ trackError(error: Omit<CodeDNAError, 'timestamp'>): Promise<void>;
23
+ /**
24
+ * Track validation error
25
+ */
26
+ trackValidationError(spec: string, errors: string[], projectId?: string): Promise<void>;
27
+ /**
28
+ * Track generation error
29
+ */
30
+ trackGenerationError(framework: string, spec: string, error: Error, projectId?: string): Promise<void>;
31
+ /**
32
+ * Track template fetch error
33
+ */
34
+ trackTemplateFetchError(generatorId: string, templateFile: string, error: Error, projectId?: string): Promise<void>;
35
+ /**
36
+ * Track network error
37
+ */
38
+ trackNetworkError(operation: CodeDNAError['operation'], error: Error, projectId?: string): Promise<void>;
39
+ }
40
+ export declare const errorTracker: CodeDNAErrorTracker;
41
+ /**
42
+ * Get error rate for monitoring dashboard
43
+ */
44
+ export interface ErrorRateQuery {
45
+ startTime: string;
46
+ endTime: string;
47
+ operation?: CodeDNAError['operation'];
48
+ errorType?: CodeDNAError['errorType'];
49
+ }
50
+ export interface ErrorRateResult {
51
+ totalErrors: number;
52
+ errorsByType: Record<string, number>;
53
+ errorsByOperation: Record<string, number>;
54
+ errorRate: number;
55
+ recentErrors: CodeDNAError[];
56
+ }
57
+ /**
58
+ * Query for error rate monitoring
59
+ *
60
+ * Example usage:
61
+ * ```typescript
62
+ * const result = await getErrorRate({
63
+ * startTime: '2025-12-04T00:00:00Z',
64
+ * endTime: '2025-12-05T00:00:00Z',
65
+ * operation: 'generate_api'
66
+ * });
67
+ *
68
+ * if (result.errorRate > 5) {
69
+ * console.warn('CodeDNA error rate exceeds 5%:', result);
70
+ * }
71
+ * ```
72
+ */
73
+ export declare function getErrorRate(query: ErrorRateQuery): Promise<ErrorRateResult>;
@@ -0,0 +1,164 @@
1
+ // =============================================================================
2
+ // CodeDNA Error Tracking
3
+ // =============================================================================
4
+ //
5
+ // Centralized error tracking for CodeDNA operations with memory storage
6
+ // and analytics queries.
7
+ //
8
+ import { storeFact, searchMemory } from './api-client.js';
9
+ import { DEFAULT_USER_ID, resolveProjectId } from './config.js';
10
+ export class CodeDNAErrorTracker {
11
+ static instance;
12
+ constructor() { }
13
+ static getInstance() {
14
+ if (!CodeDNAErrorTracker.instance) {
15
+ CodeDNAErrorTracker.instance = new CodeDNAErrorTracker();
16
+ }
17
+ return CodeDNAErrorTracker.instance;
18
+ }
19
+ /**
20
+ * Track a CodeDNA error
21
+ */
22
+ async trackError(error) {
23
+ try {
24
+ const errorRecord = {
25
+ ...error,
26
+ timestamp: new Date().toISOString(),
27
+ };
28
+ // Store error in memory system as a fact
29
+ const userId = DEFAULT_USER_ID;
30
+ const projectId = error.projectId || resolveProjectId();
31
+ await storeFact(projectId, 'CodeDNA', 'ERROR_OCCURRED', error.operation, JSON.stringify(errorRecord), userId);
32
+ // Log to console for immediate visibility
33
+ console.error('[CodeDNA Error]', {
34
+ operation: error.operation,
35
+ type: error.errorType,
36
+ message: error.errorMessage,
37
+ });
38
+ }
39
+ catch (trackingError) {
40
+ // Don't fail the operation if error tracking fails
41
+ console.error('[CodeDNA Error Tracking Failed]', trackingError);
42
+ }
43
+ }
44
+ /**
45
+ * Track validation error
46
+ */
47
+ async trackValidationError(spec, errors, projectId) {
48
+ await this.trackError({
49
+ operation: 'validate_spec',
50
+ errorType: 'validation_error',
51
+ errorMessage: `Validation failed: ${errors.join(', ')}`,
52
+ context: {
53
+ spec,
54
+ },
55
+ projectId,
56
+ });
57
+ }
58
+ /**
59
+ * Track generation error
60
+ */
61
+ async trackGenerationError(framework, spec, error, projectId) {
62
+ await this.trackError({
63
+ operation: 'generate_api',
64
+ errorType: 'generation_error',
65
+ errorMessage: error.message,
66
+ context: {
67
+ spec,
68
+ framework,
69
+ stackTrace: error.stack,
70
+ },
71
+ projectId,
72
+ });
73
+ }
74
+ /**
75
+ * Track template fetch error
76
+ */
77
+ async trackTemplateFetchError(generatorId, templateFile, error, projectId) {
78
+ await this.trackError({
79
+ operation: 'template_fetch',
80
+ errorType: 'template_error',
81
+ errorMessage: error.message,
82
+ context: {
83
+ generatorId,
84
+ templateFile,
85
+ stackTrace: error.stack,
86
+ },
87
+ projectId,
88
+ });
89
+ }
90
+ /**
91
+ * Track network error
92
+ */
93
+ async trackNetworkError(operation, error, projectId) {
94
+ await this.trackError({
95
+ operation,
96
+ errorType: 'network_error',
97
+ errorMessage: error.message,
98
+ context: {
99
+ stackTrace: error.stack,
100
+ },
101
+ projectId,
102
+ });
103
+ }
104
+ }
105
+ // Export singleton instance
106
+ export const errorTracker = CodeDNAErrorTracker.getInstance();
107
+ /**
108
+ * Query for error rate monitoring
109
+ *
110
+ * Example usage:
111
+ * ```typescript
112
+ * const result = await getErrorRate({
113
+ * startTime: '2025-12-04T00:00:00Z',
114
+ * endTime: '2025-12-05T00:00:00Z',
115
+ * operation: 'generate_api'
116
+ * });
117
+ *
118
+ * if (result.errorRate > 5) {
119
+ * console.warn('CodeDNA error rate exceeds 5%:', result);
120
+ * }
121
+ * ```
122
+ */
123
+ export async function getErrorRate(query) {
124
+ const userId = DEFAULT_USER_ID;
125
+ const projectId = resolveProjectId();
126
+ // Search for error facts
127
+ const searchQuery = `CodeDNA ERROR_OCCURRED ${query.operation || ''}`;
128
+ const result = await searchMemory(projectId, searchQuery, 100, userId);
129
+ // Parse error records from facts
130
+ const errors = result.relevant_facts
131
+ .map((fact) => {
132
+ try {
133
+ return JSON.parse(fact.fact);
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ })
139
+ .filter((e) => e !== null)
140
+ .filter((e) => {
141
+ const errorTime = new Date(e.timestamp).getTime();
142
+ const start = new Date(query.startTime).getTime();
143
+ const end = new Date(query.endTime).getTime();
144
+ return errorTime >= start && errorTime <= end;
145
+ })
146
+ .filter((e) => !query.operation || e.operation === query.operation)
147
+ .filter((e) => !query.errorType || e.errorType === query.errorType);
148
+ // Calculate error rate (errors per 100 operations - assuming 1:1 for now)
149
+ const errorRate = errors.length > 0 ? (errors.length / Math.max(errors.length, 1)) * 100 : 0;
150
+ // Group by type and operation
151
+ const errorsByType = {};
152
+ const errorsByOperation = {};
153
+ errors.forEach(error => {
154
+ errorsByType[error.errorType] = (errorsByType[error.errorType] || 0) + 1;
155
+ errorsByOperation[error.operation] = (errorsByOperation[error.operation] || 0) + 1;
156
+ });
157
+ return {
158
+ totalErrors: errors.length,
159
+ errorsByType,
160
+ errorsByOperation,
161
+ errorRate,
162
+ recentErrors: errors.slice(0, 10), // Last 10 errors
163
+ };
164
+ }
@@ -0,0 +1,91 @@
1
+ export interface UsageEvent {
2
+ timestamp: string;
3
+ operation: 'generate_api' | 'generate_frontend' | 'generate_component' | 'validate_spec';
4
+ generator?: string;
5
+ framework?: string;
6
+ entityName?: string;
7
+ fieldCount?: number;
8
+ specLength?: number;
9
+ filesGenerated?: number;
10
+ linesOfCode?: number;
11
+ tokensSaved?: number;
12
+ options?: {
13
+ auth?: boolean;
14
+ validation?: boolean;
15
+ tests?: boolean;
16
+ database?: string;
17
+ };
18
+ success: boolean;
19
+ executionTimeMs?: number;
20
+ projectId?: string;
21
+ }
22
+ export declare class UsageAnalytics {
23
+ private static instance;
24
+ private constructor();
25
+ static getInstance(): UsageAnalytics;
26
+ /**
27
+ * Track a successful generation
28
+ */
29
+ trackGeneration(event: Omit<UsageEvent, 'timestamp' | 'success'>): Promise<void>;
30
+ /**
31
+ * Track a validation
32
+ */
33
+ trackValidation(spec: string, valid: boolean, entityName?: string, fieldCount?: number, projectId?: string): Promise<void>;
34
+ }
35
+ export declare const analytics: UsageAnalytics;
36
+ /**
37
+ * Analytics query interface
38
+ */
39
+ export interface AnalyticsQuery {
40
+ startTime: string;
41
+ endTime: string;
42
+ operation?: UsageEvent['operation'];
43
+ generator?: string;
44
+ framework?: string;
45
+ }
46
+ export interface AnalyticsResult {
47
+ totalGenerations: number;
48
+ totalTokensSaved: number;
49
+ avgTokensSavedPerGeneration: number;
50
+ totalLinesOfCode: number;
51
+ totalFiles: number;
52
+ generatorStats: Record<string, {
53
+ count: number;
54
+ tokensSaved: number;
55
+ linesOfCode: number;
56
+ filesGenerated: number;
57
+ }>;
58
+ frameworkStats: Record<string, number>;
59
+ optionsUsage: {
60
+ auth: number;
61
+ validation: number;
62
+ tests: number;
63
+ };
64
+ entityPatterns: Record<string, number>;
65
+ avgExecutionTime?: number;
66
+ recentGenerations: UsageEvent[];
67
+ }
68
+ /**
69
+ * Query usage analytics
70
+ */
71
+ export declare function getUsageAnalytics(query: AnalyticsQuery): Promise<AnalyticsResult>;
72
+ /**
73
+ * Get analytics for last 24 hours
74
+ */
75
+ export declare function getLast24HoursAnalytics(): Promise<AnalyticsResult>;
76
+ /**
77
+ * Get analytics for last 7 days
78
+ */
79
+ export declare function getLast7DaysAnalytics(): Promise<AnalyticsResult>;
80
+ /**
81
+ * Get analytics for last 30 days
82
+ */
83
+ export declare function getLast30DaysAnalytics(): Promise<AnalyticsResult>;
84
+ /**
85
+ * Print analytics report
86
+ */
87
+ export declare function printAnalytics(result: AnalyticsResult, title?: string): void;
88
+ /**
89
+ * Weekly analytics summary
90
+ */
91
+ export declare function weeklyAnalyticsSummary(): Promise<void>;