@the-magic-tower/fixhive-opencode-plugin 0.1.3 → 0.1.5

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.
Files changed (2) hide show
  1. package/dist/index.d.ts +616 -0
  2. package/package.json +3 -2
@@ -0,0 +1,616 @@
1
+ import { Plugin } from '@opencode-ai/plugin';
2
+ import Database from 'better-sqlite3';
3
+
4
+ /**
5
+ * FixHive OpenCode Plugin
6
+ * Community-based error knowledge sharing plugin for OpenCode
7
+ */
8
+
9
+ /**
10
+ * FixHive Plugin Factory
11
+ */
12
+ declare const FixHivePlugin: Plugin;
13
+
14
+ /**
15
+ * FixHive Type Definitions
16
+ * Community-based error knowledge sharing for OpenCode
17
+ */
18
+ type ErrorType = 'runtime' | 'build' | 'lint' | 'test' | 'network' | 'permission' | 'dependency' | 'syntax' | 'type_error' | 'unknown';
19
+ type ErrorStatus = 'unresolved' | 'resolved' | 'uploaded';
20
+ type Language = 'typescript' | 'javascript' | 'python' | 'rust' | 'go' | 'java' | 'ruby' | 'php' | 'csharp' | 'cpp' | 'other';
21
+ type Severity = 'critical' | 'error' | 'warning';
22
+ interface LocalErrorRecord {
23
+ id: string;
24
+ errorHash: string;
25
+ errorType: ErrorType;
26
+ errorMessage: string;
27
+ errorStack?: string;
28
+ language?: Language;
29
+ framework?: string;
30
+ toolName: string;
31
+ toolInput: Record<string, unknown>;
32
+ sessionId: string;
33
+ status: ErrorStatus;
34
+ resolution?: string;
35
+ resolutionCode?: string;
36
+ createdAt: string;
37
+ resolvedAt?: string;
38
+ uploadedAt?: string;
39
+ cloudKnowledgeId?: string;
40
+ }
41
+ interface QueryCacheEntry {
42
+ id: string;
43
+ errorHash: string;
44
+ results: CloudKnowledgeEntry[];
45
+ createdAt: string;
46
+ expiresAt: string;
47
+ }
48
+ interface LocalStats {
49
+ totalErrors: number;
50
+ resolvedErrors: number;
51
+ uploadedErrors: number;
52
+ }
53
+ interface CloudKnowledgeEntry {
54
+ id: string;
55
+ errorHash: string;
56
+ errorType: ErrorType;
57
+ errorMessage: string;
58
+ errorStack?: string;
59
+ language: Language;
60
+ framework?: string;
61
+ dependencies?: Record<string, string>;
62
+ embedding?: number[];
63
+ resolutionDescription: string;
64
+ resolutionCode?: string;
65
+ resolutionSteps?: string[];
66
+ contributorId: string;
67
+ upvotes: number;
68
+ downvotes: number;
69
+ usageCount: number;
70
+ createdAt: string;
71
+ updatedAt: string;
72
+ isVerified: boolean;
73
+ similarity?: number;
74
+ }
75
+ interface DuplicateCheckResult {
76
+ isDuplicate: boolean;
77
+ existingId?: string;
78
+ similarityScore: number;
79
+ }
80
+ interface ContributorStats {
81
+ contributionCount: number;
82
+ helpedCount: number;
83
+ totalUpvotes: number;
84
+ }
85
+ interface DetectedSignal {
86
+ type: 'exit_code' | 'stderr' | 'pattern' | 'stack_trace';
87
+ weight: number;
88
+ value: string | number;
89
+ description: string;
90
+ }
91
+ interface ErrorDetectionResult {
92
+ detected: boolean;
93
+ confidence: number;
94
+ errorType: ErrorType;
95
+ severity: Severity;
96
+ signals: DetectedSignal[];
97
+ errorMessage: string;
98
+ errorStack?: string;
99
+ rawOutput: string;
100
+ }
101
+ interface StackFrame {
102
+ function: string;
103
+ file: string;
104
+ line: number;
105
+ column?: number;
106
+ isProjectCode: boolean;
107
+ }
108
+ interface StackTraceInfo {
109
+ hasStackTrace: boolean;
110
+ language: string | null;
111
+ frames: string[];
112
+ }
113
+ interface FixHiveContext {
114
+ sessionId: string;
115
+ projectDirectory: string;
116
+ language?: Language;
117
+ framework?: string;
118
+ }
119
+ interface ToolOutput {
120
+ tool: string;
121
+ output: string;
122
+ exitCode?: number;
123
+ stderr?: string;
124
+ metadata?: Record<string, unknown>;
125
+ }
126
+ interface PrivacyFilterRule {
127
+ name: string;
128
+ category: 'secret' | 'identity' | 'infrastructure' | 'path' | 'environment';
129
+ pattern: RegExp;
130
+ replacement: string | ((match: string, ...groups: string[]) => string);
131
+ priority: number;
132
+ }
133
+ interface SanitizedContent {
134
+ original: string;
135
+ sanitized: string;
136
+ redactedCount: number;
137
+ appliedFilters: string[];
138
+ }
139
+ interface FilterContext {
140
+ projectRoot: string;
141
+ homeDir: string;
142
+ commonPaths: Map<string, string>;
143
+ }
144
+ interface SearchRequest {
145
+ errorMessage: string;
146
+ errorStack?: string;
147
+ language?: Language;
148
+ framework?: string;
149
+ limit?: number;
150
+ threshold?: number;
151
+ }
152
+ interface SearchResponse {
153
+ results: CloudKnowledgeEntry[];
154
+ queryTime: number;
155
+ cached: boolean;
156
+ }
157
+ interface UploadRequest {
158
+ errorRecord: LocalErrorRecord;
159
+ resolution: string;
160
+ resolutionCode?: string;
161
+ resolutionSteps?: string[];
162
+ }
163
+ interface UploadResponse {
164
+ success: boolean;
165
+ knowledgeId?: string;
166
+ isDuplicate: boolean;
167
+ existingId?: string;
168
+ message: string;
169
+ }
170
+ interface QueryKnowledgeArgs {
171
+ errorMessage: string;
172
+ language?: string;
173
+ framework?: string;
174
+ limit?: number;
175
+ }
176
+ interface SubmitResolutionArgs {
177
+ errorId: string;
178
+ resolution: string;
179
+ resolutionCode?: string;
180
+ }
181
+ interface ListErrorsArgs {
182
+ status?: ErrorStatus;
183
+ limit?: number;
184
+ }
185
+ interface MarkResolvedArgs {
186
+ errorId: string;
187
+ resolution: string;
188
+ resolutionCode?: string;
189
+ upload?: boolean;
190
+ }
191
+ interface VoteArgs {
192
+ knowledgeId: string;
193
+ helpful: boolean;
194
+ }
195
+ interface FixHiveConfig {
196
+ supabaseUrl: string;
197
+ supabaseAnonKey: string;
198
+ openaiApiKey?: string;
199
+ contributorId: string;
200
+ cacheExpirationMs: number;
201
+ embeddingModel: string;
202
+ embeddingDimensions: number;
203
+ similarityThreshold: number;
204
+ maxSearchResults: number;
205
+ }
206
+ interface PartialConfig {
207
+ supabaseUrl?: string;
208
+ supabaseAnonKey?: string;
209
+ openaiApiKey?: string;
210
+ contributorId?: string;
211
+ cacheExpirationMs?: number;
212
+ }
213
+ type FixHiveEvent = {
214
+ type: 'error:detected';
215
+ payload: LocalErrorRecord;
216
+ } | {
217
+ type: 'error:resolved';
218
+ payload: {
219
+ errorId: string;
220
+ resolution: string;
221
+ };
222
+ } | {
223
+ type: 'solution:uploaded';
224
+ payload: {
225
+ knowledgeId: string;
226
+ };
227
+ } | {
228
+ type: 'solution:found';
229
+ payload: CloudKnowledgeEntry[];
230
+ };
231
+
232
+ /**
233
+ * FixHive Privacy Filter
234
+ * Sanitizes sensitive information from error messages before sharing
235
+ */
236
+
237
+ /**
238
+ * Privacy Filter Pipeline
239
+ * Applies multiple filtering rules to sanitize sensitive content
240
+ */
241
+ declare class PrivacyFilter {
242
+ private rules;
243
+ constructor(customRules?: PrivacyFilterRule[]);
244
+ /**
245
+ * Sanitize content by applying all filter rules
246
+ */
247
+ sanitize(content: string, context?: FilterContext): SanitizedContent;
248
+ /**
249
+ * Generalize file paths while keeping meaningful structure
250
+ */
251
+ private generalizePaths;
252
+ /**
253
+ * Add a custom filter rule
254
+ */
255
+ addRule(rule: PrivacyFilterRule): void;
256
+ /**
257
+ * Remove a filter rule by name
258
+ */
259
+ removeRule(name: string): boolean;
260
+ /**
261
+ * Get all current rules
262
+ */
263
+ getRules(): ReadonlyArray<PrivacyFilterRule>;
264
+ /**
265
+ * Check if content contains sensitive data
266
+ * Note: Always reset regex lastIndex BEFORE testing to prevent state pollution
267
+ */
268
+ containsSensitiveData(content: string): boolean;
269
+ }
270
+ /**
271
+ * Create default filter context from project directory
272
+ */
273
+ declare function createFilterContext(projectDirectory: string): FilterContext;
274
+ declare const defaultPrivacyFilter: PrivacyFilter;
275
+
276
+ /**
277
+ * FixHive Error Detector
278
+ * Detects errors from tool outputs using multi-signal analysis
279
+ */
280
+
281
+ /**
282
+ * Error Detector Class
283
+ * Analyzes tool outputs to detect errors
284
+ */
285
+ declare class ErrorDetector {
286
+ private privacyFilter;
287
+ constructor(privacyFilter?: PrivacyFilter);
288
+ /**
289
+ * Detect if output contains an error
290
+ */
291
+ detect(toolOutput: ToolOutput): ErrorDetectionResult;
292
+ /**
293
+ * Check if content contains error keywords
294
+ */
295
+ private containsErrorKeywords;
296
+ /**
297
+ * Detect error patterns in content
298
+ */
299
+ private detectErrorPatterns;
300
+ /**
301
+ * Detect stack traces in content
302
+ */
303
+ private detectStackTrace;
304
+ /**
305
+ * Calculate confidence score from signals
306
+ */
307
+ private calculateConfidence;
308
+ /**
309
+ * Classify error type based on signals and content
310
+ */
311
+ private classifyErrorType;
312
+ /**
313
+ * Determine severity from signals and exit code
314
+ */
315
+ private determineSeverity;
316
+ /**
317
+ * Extract error message and stack from output
318
+ */
319
+ private extractErrorDetails;
320
+ /**
321
+ * Check if a line looks like an error message
322
+ */
323
+ private isErrorLine;
324
+ }
325
+ declare const defaultErrorDetector: ErrorDetector;
326
+
327
+ /**
328
+ * FixHive Hash Utilities
329
+ * Generates fingerprints and hashes for error deduplication
330
+ */
331
+ /**
332
+ * Generate SHA-256 hash of content
333
+ */
334
+ declare function sha256(content: string): string;
335
+ /**
336
+ * Generate a shortened hash (first 16 characters)
337
+ */
338
+ declare function shortHash(content: string): string;
339
+ /**
340
+ * Generate error fingerprint for matching similar errors
341
+ * Normalizes variable parts (paths, numbers, hashes) before hashing
342
+ */
343
+ declare function generateErrorFingerprint(errorMessage: string, errorStack?: string): string;
344
+ /**
345
+ * Normalize error content by replacing variable parts
346
+ */
347
+ declare function normalizeErrorContent(content: string): string;
348
+ /**
349
+ * Generate contributor ID (anonymous hash)
350
+ * Uses machine-specific information to create a stable anonymous ID
351
+ */
352
+ declare function generateContributorId(): string;
353
+ /**
354
+ * Generate session-specific hash
355
+ */
356
+ declare function generateSessionHash(sessionId: string): string;
357
+ /**
358
+ * Compare two fingerprints for similarity
359
+ * Returns true if they're identical (exact match)
360
+ */
361
+ declare function fingerprintsMatch(fp1: string, fp2: string): boolean;
362
+ /**
363
+ * Calculate simple string similarity (Jaccard index)
364
+ * Used as a fallback when embeddings aren't available
365
+ */
366
+ declare function calculateStringSimilarity(str1: string, str2: string): number;
367
+
368
+ /**
369
+ * FixHive Local Store
370
+ * SQLite-based local storage for error records and caching
371
+ */
372
+
373
+ /**
374
+ * Local Store Class
375
+ * Manages SQLite database for error records and caching
376
+ */
377
+ declare class LocalStore {
378
+ private db;
379
+ constructor(projectDirectory: string);
380
+ /**
381
+ * Create a new error record
382
+ */
383
+ createErrorRecord(data: Omit<LocalErrorRecord, 'id' | 'errorHash' | 'status' | 'createdAt'>): LocalErrorRecord;
384
+ /**
385
+ * Get error record by ID
386
+ */
387
+ getErrorById(id: string): LocalErrorRecord | null;
388
+ /**
389
+ * Get errors by session
390
+ */
391
+ getSessionErrors(sessionId: string, options?: {
392
+ status?: ErrorStatus;
393
+ limit?: number;
394
+ }): LocalErrorRecord[];
395
+ /**
396
+ * Get unresolved errors for a session
397
+ */
398
+ getUnresolvedErrors(sessionId: string): LocalErrorRecord[];
399
+ /**
400
+ * Get recent errors across all sessions
401
+ */
402
+ getRecentErrors(limit?: number): LocalErrorRecord[];
403
+ /**
404
+ * Mark error as resolved
405
+ */
406
+ markResolved(id: string, data: {
407
+ resolution: string;
408
+ resolutionCode?: string;
409
+ }): LocalErrorRecord | null;
410
+ /**
411
+ * Mark error as uploaded to cloud
412
+ */
413
+ markUploaded(id: string, cloudKnowledgeId: string): void;
414
+ /**
415
+ * Find similar errors by hash
416
+ */
417
+ findSimilarErrors(errorHash: string): LocalErrorRecord[];
418
+ /**
419
+ * Get cached query results
420
+ */
421
+ getCachedResults(errorHash: string): CloudKnowledgeEntry[] | null;
422
+ /**
423
+ * Cache query results
424
+ */
425
+ cacheResults(errorHash: string, results: CloudKnowledgeEntry[], expirationMs?: number): void;
426
+ /**
427
+ * Clear expired cache entries
428
+ */
429
+ clearExpiredCache(): number;
430
+ /**
431
+ * Get usage statistics
432
+ */
433
+ getStats(): LocalStats;
434
+ /**
435
+ * Allowed stat column names for incrementStat (whitelist to prevent SQL injection)
436
+ */
437
+ private static readonly ALLOWED_STATS;
438
+ /**
439
+ * Increment a stat counter
440
+ * @throws Error if stat name is not in the allowed whitelist
441
+ */
442
+ private incrementStat;
443
+ /**
444
+ * Get preference value
445
+ */
446
+ getPreference(key: string): string | null;
447
+ /**
448
+ * Set preference value
449
+ */
450
+ setPreference(key: string, value: string): void;
451
+ /**
452
+ * Convert database row to LocalErrorRecord
453
+ */
454
+ private rowToRecord;
455
+ /**
456
+ * Close database connection
457
+ */
458
+ close(): void;
459
+ /**
460
+ * Get database for advanced queries
461
+ */
462
+ getDatabase(): Database.Database;
463
+ }
464
+
465
+ /**
466
+ * FixHive Database Migrations
467
+ * SQLite schema setup and migrations
468
+ */
469
+
470
+ /**
471
+ * Run all migrations on the database
472
+ */
473
+ declare function runMigrations(db: Database.Database): void;
474
+
475
+ /**
476
+ * FixHive Cloud Client
477
+ * Supabase client for cloud knowledge base operations
478
+ */
479
+
480
+ /**
481
+ * Cloud Client Class
482
+ * Manages communication with Supabase cloud database
483
+ */
484
+ declare class CloudClient {
485
+ private supabase;
486
+ private embedding;
487
+ private contributorId;
488
+ private similarityThreshold;
489
+ constructor(config: {
490
+ supabaseUrl: string;
491
+ supabaseAnonKey: string;
492
+ openaiApiKey?: string;
493
+ contributorId?: string;
494
+ similarityThreshold?: number;
495
+ });
496
+ /**
497
+ * Search for similar errors in cloud knowledge base
498
+ */
499
+ searchSimilar(request: SearchRequest): Promise<SearchResponse>;
500
+ /**
501
+ * Fallback text-based search
502
+ */
503
+ private searchByText;
504
+ /**
505
+ * Upload a resolution to cloud knowledge base
506
+ */
507
+ uploadResolution(request: UploadRequest): Promise<UploadResponse>;
508
+ /**
509
+ * Check for duplicate entries
510
+ */
511
+ checkDuplicate(errorHash: string, embedding: number[]): Promise<DuplicateCheckResult>;
512
+ /**
513
+ * Vote on a knowledge entry (with duplicate vote prevention)
514
+ */
515
+ vote(knowledgeId: string, helpful: boolean): Promise<{
516
+ success: boolean;
517
+ error?: string;
518
+ }>;
519
+ /**
520
+ * Report an entry for review
521
+ */
522
+ reportEntry(knowledgeId: string, reason?: string): Promise<{
523
+ success: boolean;
524
+ }>;
525
+ /**
526
+ * Report helpful usage
527
+ */
528
+ reportHelpful(knowledgeId: string): Promise<void>;
529
+ /**
530
+ * Get contributor statistics
531
+ */
532
+ getContributorStats(): Promise<ContributorStats>;
533
+ /**
534
+ * Get entry by ID
535
+ */
536
+ getEntry(id: string): Promise<CloudKnowledgeEntry | null>;
537
+ /**
538
+ * Map database row to CloudKnowledgeEntry
539
+ */
540
+ private mapToKnowledgeEntry;
541
+ /**
542
+ * Get contributor ID
543
+ */
544
+ getContributorId(): string;
545
+ /**
546
+ * Check if embedding service is available
547
+ */
548
+ hasEmbeddingService(): boolean;
549
+ }
550
+ /**
551
+ * Create cloud client with config
552
+ */
553
+ declare function createCloudClient(config: {
554
+ supabaseUrl: string;
555
+ supabaseAnonKey: string;
556
+ openaiApiKey?: string;
557
+ contributorId?: string;
558
+ similarityThreshold?: number;
559
+ }): CloudClient;
560
+
561
+ /**
562
+ * FixHive Embedding Service
563
+ * Generates text embeddings for semantic search using OpenAI
564
+ */
565
+ /**
566
+ * Embedding Service Class
567
+ * Generates embeddings for error messages and solutions
568
+ */
569
+ declare class EmbeddingService {
570
+ private client;
571
+ private model;
572
+ private dimensions;
573
+ constructor(apiKey: string, model?: string, dimensions?: number);
574
+ /**
575
+ * Generate embedding for a single text
576
+ */
577
+ generate(text: string): Promise<number[]>;
578
+ /**
579
+ * Generate embeddings for multiple texts
580
+ */
581
+ generateBatch(texts: string[]): Promise<number[][]>;
582
+ /**
583
+ * Generate embedding for error context
584
+ * Combines error message, stack trace, and context
585
+ */
586
+ generateErrorEmbedding(errorMessage: string, errorStack?: string, context?: {
587
+ language?: string;
588
+ framework?: string;
589
+ }): Promise<number[]>;
590
+ /**
591
+ * Truncate text to fit within model limits
592
+ */
593
+ private truncateText;
594
+ /**
595
+ * Calculate cosine similarity between two embeddings
596
+ */
597
+ static cosineSimilarity(a: number[], b: number[]): number;
598
+ /**
599
+ * Get embedding dimensions
600
+ */
601
+ getDimensions(): number;
602
+ /**
603
+ * Get model name
604
+ */
605
+ getModel(): string;
606
+ }
607
+ /**
608
+ * Create embedding service with config
609
+ */
610
+ declare function createEmbeddingService(config: {
611
+ apiKey: string;
612
+ model?: string;
613
+ dimensions?: number;
614
+ }): EmbeddingService;
615
+
616
+ export { CloudClient, type CloudKnowledgeEntry, type ContributorStats, type DetectedSignal, type DuplicateCheckResult, EmbeddingService, type ErrorDetectionResult, ErrorDetector, type ErrorStatus, type ErrorType, type FilterContext, type FixHiveConfig, type FixHiveContext, type FixHiveEvent, FixHivePlugin, type Language, type ListErrorsArgs, type LocalErrorRecord, type LocalStats, LocalStore, type MarkResolvedArgs, type PartialConfig, PrivacyFilter, type PrivacyFilterRule, type QueryCacheEntry, type QueryKnowledgeArgs, type SanitizedContent, type SearchRequest, type SearchResponse, type Severity, type StackFrame, type StackTraceInfo, type SubmitResolutionArgs, type ToolOutput, type UploadRequest, type UploadResponse, type VoteArgs, calculateStringSimilarity, createCloudClient, createEmbeddingService, createFilterContext, FixHivePlugin as default, defaultErrorDetector, defaultPrivacyFilter, fingerprintsMatch, generateContributorId, generateErrorFingerprint, generateSessionHash, normalizeErrorContent, runMigrations, sha256, shortHash };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-magic-tower/fixhive-opencode-plugin",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Community-based error knowledge sharing for OpenCode",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "dist"
16
16
  ],
17
17
  "scripts": {
18
- "build": "tsup src/index.ts --format esm --clean",
18
+ "build": "tsup src/index.ts --format esm --dts --clean",
19
19
  "build:dts": "tsup src/index.ts --format esm --dts --clean",
20
20
  "dev": "tsup src/index.ts --format esm --watch",
21
21
  "typecheck": "tsc --noEmit",
@@ -56,6 +56,7 @@
56
56
  "@types/uuid": "^10.0.0",
57
57
  "@typescript-eslint/eslint-plugin": "^8.0.0",
58
58
  "@typescript-eslint/parser": "^8.0.0",
59
+ "@vitest/coverage-v8": "^2.1.9",
59
60
  "eslint": "^9.0.0",
60
61
  "tsup": "^8.2.0",
61
62
  "typescript": "^5.5.0",