@the-magic-tower/fixhive-opencode-plugin 0.1.14 → 0.1.15

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.
@@ -14,75 +14,31 @@ export interface CloudClientConfig {
14
14
  similarityThreshold?: number;
15
15
  }
16
16
  /**
17
- * Cloud Client Class
18
- * Manages communication with Supabase cloud database
17
+ * CloudClient interface - defines all public methods
19
18
  */
20
- export declare class CloudClient {
21
- private supabase;
22
- private embedding;
23
- private contributorId;
24
- private similarityThreshold;
25
- private constructor();
26
- /**
27
- * Create a CloudClient instance (async factory for Bun compatibility)
28
- */
29
- static create(config: CloudClientConfig): Promise<CloudClient>;
30
- /**
31
- * Search for similar errors in cloud knowledge base
32
- */
19
+ export interface CloudClient {
33
20
  searchSimilar(request: SearchRequest): Promise<SearchResponse>;
34
- /**
35
- * Fallback text-based search
36
- */
37
- private searchByText;
38
- /**
39
- * Upload a resolution to cloud knowledge base
40
- */
41
21
  uploadResolution(request: UploadRequest): Promise<UploadResponse>;
42
- /**
43
- * Check for duplicate entries
44
- */
45
22
  checkDuplicate(errorHash: string, embedding: number[]): Promise<DuplicateCheckResult>;
46
- /**
47
- * Vote on a knowledge entry (with duplicate vote prevention)
48
- */
49
23
  vote(knowledgeId: string, helpful: boolean): Promise<{
50
24
  success: boolean;
51
25
  error?: string;
52
26
  }>;
53
- /**
54
- * Report an entry for review
55
- */
56
27
  reportEntry(knowledgeId: string, reason?: string): Promise<{
57
28
  success: boolean;
58
29
  }>;
59
- /**
60
- * Report helpful usage
61
- */
62
30
  reportHelpful(knowledgeId: string): Promise<void>;
63
- /**
64
- * Get contributor statistics
65
- */
66
31
  getContributorStats(): Promise<ContributorStats>;
67
- /**
68
- * Get entry by ID
69
- */
70
32
  getEntry(id: string): Promise<CloudKnowledgeEntry | null>;
71
- /**
72
- * Map database row to CloudKnowledgeEntry
73
- */
74
- private mapToKnowledgeEntry;
75
- /**
76
- * Get contributor ID
77
- */
78
33
  getContributorId(): string;
79
- /**
80
- * Check if embedding service is available
81
- */
82
34
  hasEmbeddingService(): boolean;
83
35
  }
84
36
  /**
85
- * Create cloud client with config (async for Bun compatibility)
37
+ * Create a CloudClient instance
38
+ * Factory function pattern to avoid ES6 class issues with Bun
86
39
  */
87
40
  export declare function createCloudClient(config: CloudClientConfig): Promise<CloudClient>;
41
+ export declare const CloudClient: {
42
+ create: typeof createCloudClient;
43
+ };
88
44
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cloud/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAe3B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,mBAAmB,CAAS;IAEpC,OAAO;IAYP;;OAEG;WACU,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;IAqBpE;;OAEG;IACG,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAiCpE;;OAEG;YACW,YAAY;IAgC1B;;OAEG;IACG,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;IAgEvE;;OAEG;IACG,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,oBAAoB,CAAC;IAoChC;;OAEG;IACG,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA2BhG;;OAEG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IActF;;OAEG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAiBtD;;OAEG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAc/D;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwB3B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,mBAAmB,IAAI,OAAO;CAG/B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,WAAW,CAAC,CAEtB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/cloud/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAe3B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/D,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtF,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACjF,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC1D,gBAAgB,IAAI,MAAM,CAAC;IAC3B,mBAAmB,IAAI,OAAO,CAAC;CAChC;AA6BD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CA2RvF;AAID,eAAO,MAAM,WAAW;;CAEvB,CAAC"}
package/dist/index.js CHANGED
@@ -957,61 +957,69 @@ async function getCreateClient() {
957
957
  }
958
958
  return createClient;
959
959
  }
960
-
961
- class CloudClient {
962
- supabase;
963
- embedding;
964
- contributorId;
965
- similarityThreshold;
966
- constructor(supabase, embedding, contributorId, similarityThreshold) {
967
- this.supabase = supabase;
968
- this.embedding = embedding;
969
- this.contributorId = contributorId;
970
- this.similarityThreshold = similarityThreshold;
971
- }
972
- static async create(config) {
973
- const createClientFn = await getCreateClient();
974
- const supabase = createClientFn(config.supabaseUrl, config.supabaseAnonKey);
975
- let embedding = null;
976
- if (config.openaiApiKey) {
977
- try {
978
- embedding = new EmbeddingService(config.openaiApiKey);
979
- } catch (err) {
980
- console.warn("[FixHive] Failed to initialize embedding service:", err);
981
- }
960
+ function mapToKnowledgeEntry(row) {
961
+ return {
962
+ id: row.id,
963
+ errorHash: row.error_hash,
964
+ errorType: row.error_type,
965
+ errorMessage: row.error_message,
966
+ errorStack: row.error_stack || undefined,
967
+ language: row.language,
968
+ framework: row.framework || undefined,
969
+ dependencies: row.dependencies || undefined,
970
+ resolutionDescription: row.resolution_description,
971
+ resolutionCode: row.resolution_code || undefined,
972
+ resolutionSteps: row.resolution_steps || undefined,
973
+ contributorId: row.contributor_id,
974
+ upvotes: row.upvotes || 0,
975
+ downvotes: row.downvotes || 0,
976
+ usageCount: row.usage_count || 0,
977
+ createdAt: row.created_at,
978
+ updatedAt: row.updated_at,
979
+ isVerified: row.is_verified || false,
980
+ similarity: row.similarity || undefined
981
+ };
982
+ }
983
+ async function createCloudClient(config) {
984
+ const createClientFn = await getCreateClient();
985
+ const supabase = createClientFn(config.supabaseUrl, config.supabaseAnonKey);
986
+ let embedding = null;
987
+ if (config.openaiApiKey) {
988
+ try {
989
+ embedding = new EmbeddingService(config.openaiApiKey);
990
+ } catch (err) {
991
+ console.warn("[FixHive] Failed to initialize embedding service:", err);
982
992
  }
983
- const contributorId = config.contributorId || generateContributorId();
984
- const similarityThreshold = config.similarityThreshold || 0.7;
985
- return new CloudClient(supabase, embedding, contributorId, similarityThreshold);
986
993
  }
987
- async searchSimilar(request) {
988
- const startTime = Date.now();
989
- if (!this.embedding) {
990
- return this.searchByText(request);
994
+ const contributorId = config.contributorId || generateContributorId();
995
+ const similarityThreshold = config.similarityThreshold || 0.7;
996
+ async function checkDuplicateInternal(errorHash, embeddingData) {
997
+ const { data: hashMatch } = await supabase.from("knowledge_entries").select("id").eq("error_hash", errorHash).limit(1).single();
998
+ if (hashMatch) {
999
+ return {
1000
+ isDuplicate: true,
1001
+ existingId: hashMatch.id,
1002
+ similarityScore: 1
1003
+ };
991
1004
  }
992
- const queryText = `${request.errorMessage}
993
- ${request.errorStack || ""}`;
994
- const embedding = await this.embedding.generate(queryText);
995
- const { data, error } = await this.supabase.rpc("search_similar_errors", {
996
- query_embedding: embedding,
997
- match_threshold: request.threshold || this.similarityThreshold,
998
- match_count: request.limit || 10,
999
- filter_language: request.language || null,
1000
- filter_framework: request.framework || null
1005
+ const { data, error } = await supabase.rpc("check_duplicate_entry", {
1006
+ new_hash: errorHash,
1007
+ new_embedding: embeddingData,
1008
+ similarity_threshold: 0.95
1001
1009
  });
1002
- if (error) {
1003
- console.error("Search error:", error);
1004
- return { results: [], queryTime: Date.now() - startTime, cached: false };
1010
+ if (error || !data || data.length === 0) {
1011
+ return { isDuplicate: false, similarityScore: 0 };
1005
1012
  }
1013
+ const result = data[0];
1006
1014
  return {
1007
- results: (data || []).map(this.mapToKnowledgeEntry),
1008
- queryTime: Date.now() - startTime,
1009
- cached: false
1015
+ isDuplicate: result.is_duplicate,
1016
+ existingId: result.existing_id,
1017
+ similarityScore: result.similarity_score
1010
1018
  };
1011
1019
  }
1012
- async searchByText(request) {
1020
+ async function searchByText(request) {
1013
1021
  const startTime = Date.now();
1014
- let query = this.supabase.from("knowledge_entries").select("*").ilike("error_message", `%${request.errorMessage.substring(0, 100)}%`).order("upvotes", { ascending: false }).limit(request.limit || 10);
1022
+ let query = supabase.from("knowledge_entries").select("*").ilike("error_message", `%${request.errorMessage.substring(0, 100)}%`).order("upvotes", { ascending: false }).limit(request.limit || 10);
1015
1023
  if (request.language) {
1016
1024
  query = query.eq("language", request.language);
1017
1025
  }
@@ -1024,176 +1032,159 @@ ${request.errorStack || ""}`;
1024
1032
  return { results: [], queryTime: Date.now() - startTime, cached: false };
1025
1033
  }
1026
1034
  return {
1027
- results: (data || []).map(this.mapToKnowledgeEntry),
1035
+ results: (data || []).map(mapToKnowledgeEntry),
1028
1036
  queryTime: Date.now() - startTime,
1029
1037
  cached: false
1030
1038
  };
1031
1039
  }
1032
- async uploadResolution(request) {
1033
- const { errorRecord, resolution, resolutionCode, resolutionSteps } = request;
1034
- let embedding = null;
1035
- if (this.embedding) {
1036
- const embeddingText = `${errorRecord.errorMessage}
1040
+ return {
1041
+ async searchSimilar(request) {
1042
+ const startTime = Date.now();
1043
+ if (!embedding) {
1044
+ return searchByText(request);
1045
+ }
1046
+ const queryText = `${request.errorMessage}
1047
+ ${request.errorStack || ""}`;
1048
+ const queryEmbedding = await embedding.generate(queryText);
1049
+ const { data, error } = await supabase.rpc("search_similar_errors", {
1050
+ query_embedding: queryEmbedding,
1051
+ match_threshold: request.threshold || similarityThreshold,
1052
+ match_count: request.limit || 10,
1053
+ filter_language: request.language || null,
1054
+ filter_framework: request.framework || null
1055
+ });
1056
+ if (error) {
1057
+ console.error("Search error:", error);
1058
+ return { results: [], queryTime: Date.now() - startTime, cached: false };
1059
+ }
1060
+ return {
1061
+ results: (data || []).map(mapToKnowledgeEntry),
1062
+ queryTime: Date.now() - startTime,
1063
+ cached: false
1064
+ };
1065
+ },
1066
+ async uploadResolution(request) {
1067
+ const { errorRecord, resolution, resolutionCode, resolutionSteps } = request;
1068
+ let embeddingData = null;
1069
+ if (embedding) {
1070
+ const embeddingText = `${errorRecord.errorMessage}
1037
1071
  ${errorRecord.errorStack || ""}`;
1038
- embedding = await this.embedding.generate(embeddingText);
1039
- }
1040
- if (embedding) {
1041
- const duplicateCheck = await this.checkDuplicate(errorRecord.errorHash, embedding);
1042
- if (duplicateCheck.isDuplicate && duplicateCheck.similarityScore > 0.95) {
1043
- await this.supabase.rpc("increment_usage_count", {
1044
- entry_id: duplicateCheck.existingId
1045
- });
1072
+ embeddingData = await embedding.generate(embeddingText);
1073
+ }
1074
+ if (embeddingData) {
1075
+ const duplicateCheck = await checkDuplicateInternal(errorRecord.errorHash, embeddingData);
1076
+ if (duplicateCheck.isDuplicate && duplicateCheck.similarityScore > 0.95) {
1077
+ await supabase.rpc("increment_usage_count", {
1078
+ entry_id: duplicateCheck.existingId
1079
+ });
1080
+ return {
1081
+ success: true,
1082
+ isDuplicate: true,
1083
+ existingId: duplicateCheck.existingId,
1084
+ message: "Similar solution already exists. Usage count incremented."
1085
+ };
1086
+ }
1087
+ }
1088
+ const { data, error } = await supabase.from("knowledge_entries").insert({
1089
+ error_hash: errorRecord.errorHash,
1090
+ error_type: errorRecord.errorType,
1091
+ error_message: errorRecord.errorMessage,
1092
+ error_stack: errorRecord.errorStack,
1093
+ language: errorRecord.language || "other",
1094
+ framework: errorRecord.framework,
1095
+ embedding: embeddingData,
1096
+ resolution_description: resolution,
1097
+ resolution_code: resolutionCode,
1098
+ resolution_steps: resolutionSteps,
1099
+ contributor_id: contributorId
1100
+ }).select("id").single();
1101
+ if (error) {
1046
1102
  return {
1047
- success: true,
1048
- isDuplicate: true,
1049
- existingId: duplicateCheck.existingId,
1050
- message: "Similar solution already exists. Usage count incremented."
1103
+ success: false,
1104
+ isDuplicate: false,
1105
+ message: `Upload failed: ${error.message}`
1051
1106
  };
1052
1107
  }
1053
- }
1054
- const { data, error } = await this.supabase.from("knowledge_entries").insert({
1055
- error_hash: errorRecord.errorHash,
1056
- error_type: errorRecord.errorType,
1057
- error_message: errorRecord.errorMessage,
1058
- error_stack: errorRecord.errorStack,
1059
- language: errorRecord.language || "other",
1060
- framework: errorRecord.framework,
1061
- embedding,
1062
- resolution_description: resolution,
1063
- resolution_code: resolutionCode,
1064
- resolution_steps: resolutionSteps,
1065
- contributor_id: this.contributorId
1066
- }).select("id").single();
1067
- if (error) {
1068
1108
  return {
1069
- success: false,
1109
+ success: true,
1110
+ knowledgeId: data.id,
1070
1111
  isDuplicate: false,
1071
- message: `Upload failed: ${error.message}`
1112
+ message: "Solution uploaded successfully!"
1072
1113
  };
1073
- }
1074
- return {
1075
- success: true,
1076
- knowledgeId: data.id,
1077
- isDuplicate: false,
1078
- message: "Solution uploaded successfully!"
1079
- };
1080
- }
1081
- async checkDuplicate(errorHash, embedding) {
1082
- const { data: hashMatch } = await this.supabase.from("knowledge_entries").select("id").eq("error_hash", errorHash).limit(1).single();
1083
- if (hashMatch) {
1084
- return {
1085
- isDuplicate: true,
1086
- existingId: hashMatch.id,
1087
- similarityScore: 1
1088
- };
1089
- }
1090
- const { data, error } = await this.supabase.rpc("check_duplicate_entry", {
1091
- new_hash: errorHash,
1092
- new_embedding: embedding,
1093
- similarity_threshold: 0.95
1094
- });
1095
- if (error || !data || data.length === 0) {
1096
- return { isDuplicate: false, similarityScore: 0 };
1097
- }
1098
- const result = data[0];
1099
- return {
1100
- isDuplicate: result.is_duplicate,
1101
- existingId: result.existing_id,
1102
- similarityScore: result.similarity_score
1103
- };
1104
- }
1105
- async vote(knowledgeId, helpful) {
1106
- const voteType = helpful ? "up" : "down";
1107
- const { data, error } = await this.supabase.rpc("safe_vote", {
1108
- p_entry_id: knowledgeId,
1109
- p_user_hash: this.contributorId,
1110
- p_vote_type: voteType
1111
- });
1112
- if (error) {
1113
- return { success: false, error: error.message };
1114
- }
1115
- const result = data;
1116
- if (result.success) {
1117
- await this.supabase.from("usage_logs").insert({
1114
+ },
1115
+ async checkDuplicate(errorHash, embeddingData) {
1116
+ return checkDuplicateInternal(errorHash, embeddingData);
1117
+ },
1118
+ async vote(knowledgeId, helpful) {
1119
+ const voteType = helpful ? "up" : "down";
1120
+ const { data, error } = await supabase.rpc("safe_vote", {
1121
+ p_entry_id: knowledgeId,
1122
+ p_user_hash: contributorId,
1123
+ p_vote_type: voteType
1124
+ });
1125
+ if (error) {
1126
+ return { success: false, error: error.message };
1127
+ }
1128
+ const result = data;
1129
+ if (result.success) {
1130
+ await supabase.from("usage_logs").insert({
1131
+ knowledge_id: knowledgeId,
1132
+ action: helpful ? "upvote" : "downvote",
1133
+ user_hash: contributorId
1134
+ });
1135
+ }
1136
+ return result;
1137
+ },
1138
+ async reportEntry(knowledgeId, reason) {
1139
+ const { data, error } = await supabase.rpc("report_entry", {
1140
+ p_entry_id: knowledgeId,
1141
+ p_user_hash: contributorId,
1142
+ p_reason: reason || null
1143
+ });
1144
+ if (error) {
1145
+ return { success: false };
1146
+ }
1147
+ return data;
1148
+ },
1149
+ async reportHelpful(knowledgeId) {
1150
+ await supabase.rpc("increment_usage_count", {
1151
+ entry_id: knowledgeId
1152
+ });
1153
+ await supabase.from("usage_logs").insert({
1118
1154
  knowledge_id: knowledgeId,
1119
- action: helpful ? "upvote" : "downvote",
1120
- user_hash: this.contributorId
1155
+ action: "apply",
1156
+ user_hash: contributorId
1121
1157
  });
1158
+ },
1159
+ async getContributorStats() {
1160
+ const { data } = await supabase.from("knowledge_entries").select("upvotes, usage_count").eq("contributor_id", contributorId);
1161
+ if (!data || data.length === 0) {
1162
+ return { contributionCount: 0, helpedCount: 0, totalUpvotes: 0 };
1163
+ }
1164
+ return {
1165
+ contributionCount: data.length,
1166
+ helpedCount: data.reduce((sum, e) => sum + (e.usage_count || 0), 0),
1167
+ totalUpvotes: data.reduce((sum, e) => sum + (e.upvotes || 0), 0)
1168
+ };
1169
+ },
1170
+ async getEntry(id) {
1171
+ const { data, error } = await supabase.from("knowledge_entries").select("*").eq("id", id).single();
1172
+ if (error || !data) {
1173
+ return null;
1174
+ }
1175
+ return mapToKnowledgeEntry(data);
1176
+ },
1177
+ getContributorId() {
1178
+ return contributorId;
1179
+ },
1180
+ hasEmbeddingService() {
1181
+ return embedding !== null;
1122
1182
  }
1123
- return result;
1124
- }
1125
- async reportEntry(knowledgeId, reason) {
1126
- const { data, error } = await this.supabase.rpc("report_entry", {
1127
- p_entry_id: knowledgeId,
1128
- p_user_hash: this.contributorId,
1129
- p_reason: reason || null
1130
- });
1131
- if (error) {
1132
- return { success: false };
1133
- }
1134
- return data;
1135
- }
1136
- async reportHelpful(knowledgeId) {
1137
- await this.supabase.rpc("increment_usage_count", {
1138
- entry_id: knowledgeId
1139
- });
1140
- await this.supabase.from("usage_logs").insert({
1141
- knowledge_id: knowledgeId,
1142
- action: "apply",
1143
- user_hash: this.contributorId
1144
- });
1145
- }
1146
- async getContributorStats() {
1147
- const { data } = await this.supabase.from("knowledge_entries").select("upvotes, usage_count").eq("contributor_id", this.contributorId);
1148
- if (!data || data.length === 0) {
1149
- return { contributionCount: 0, helpedCount: 0, totalUpvotes: 0 };
1150
- }
1151
- return {
1152
- contributionCount: data.length,
1153
- helpedCount: data.reduce((sum, e) => sum + (e.usage_count || 0), 0),
1154
- totalUpvotes: data.reduce((sum, e) => sum + (e.upvotes || 0), 0)
1155
- };
1156
- }
1157
- async getEntry(id) {
1158
- const { data, error } = await this.supabase.from("knowledge_entries").select("*").eq("id", id).single();
1159
- if (error || !data) {
1160
- return null;
1161
- }
1162
- return this.mapToKnowledgeEntry(data);
1163
- }
1164
- mapToKnowledgeEntry(row) {
1165
- return {
1166
- id: row.id,
1167
- errorHash: row.error_hash,
1168
- errorType: row.error_type,
1169
- errorMessage: row.error_message,
1170
- errorStack: row.error_stack || undefined,
1171
- language: row.language,
1172
- framework: row.framework || undefined,
1173
- dependencies: row.dependencies || undefined,
1174
- resolutionDescription: row.resolution_description,
1175
- resolutionCode: row.resolution_code || undefined,
1176
- resolutionSteps: row.resolution_steps || undefined,
1177
- contributorId: row.contributor_id,
1178
- upvotes: row.upvotes || 0,
1179
- downvotes: row.downvotes || 0,
1180
- usageCount: row.usage_count || 0,
1181
- createdAt: row.created_at,
1182
- updatedAt: row.updated_at,
1183
- isVerified: row.is_verified || false,
1184
- similarity: row.similarity || undefined
1185
- };
1186
- }
1187
- getContributorId() {
1188
- return this.contributorId;
1189
- }
1190
- hasEmbeddingService() {
1191
- return this.embedding !== null;
1192
- }
1193
- }
1194
- async function createCloudClient(config) {
1195
- return CloudClient.create(config);
1183
+ };
1196
1184
  }
1185
+ var CloudClient = {
1186
+ create: createCloudClient
1187
+ };
1197
1188
 
1198
1189
  // src/plugin/tools.ts
1199
1190
  import { tool } from "@opencode-ai/plugin";
@@ -1416,7 +1407,7 @@ var FixHivePlugin = async (ctx) => {
1416
1407
  let cloudClient = null;
1417
1408
  if (config.supabaseUrl && config.supabaseAnonKey) {
1418
1409
  try {
1419
- cloudClient = await CloudClient.create({
1410
+ cloudClient = await createCloudClient({
1420
1411
  supabaseUrl: config.supabaseUrl,
1421
1412
  supabaseAnonKey: config.supabaseAnonKey,
1422
1413
  openaiApiKey: config.openaiApiKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-magic-tower/fixhive-opencode-plugin",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Community-based error knowledge sharing for OpenCode",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",