@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.
- package/dist/cloud/client.d.ts +7 -51
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/index.js +193 -202
- package/package.json +1 -1
package/dist/cloud/client.d.ts
CHANGED
|
@@ -14,75 +14,31 @@ export interface CloudClientConfig {
|
|
|
14
14
|
similarityThreshold?: number;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* Manages communication with Supabase cloud database
|
|
17
|
+
* CloudClient interface - defines all public methods
|
|
19
18
|
*/
|
|
20
|
-
export
|
|
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
|
|
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
|
|
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
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
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
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
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
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
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 =
|
|
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(
|
|
1035
|
+
results: (data || []).map(mapToKnowledgeEntry),
|
|
1028
1036
|
queryTime: Date.now() - startTime,
|
|
1029
1037
|
cached: false
|
|
1030
1038
|
};
|
|
1031
1039
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
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
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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:
|
|
1048
|
-
isDuplicate:
|
|
1049
|
-
|
|
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:
|
|
1109
|
+
success: true,
|
|
1110
|
+
knowledgeId: data.id,
|
|
1070
1111
|
isDuplicate: false,
|
|
1071
|
-
message:
|
|
1112
|
+
message: "Solution uploaded successfully!"
|
|
1072
1113
|
};
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
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:
|
|
1120
|
-
user_hash:
|
|
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
|
-
|
|
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
|
|
1410
|
+
cloudClient = await createCloudClient({
|
|
1420
1411
|
supabaseUrl: config.supabaseUrl,
|
|
1421
1412
|
supabaseAnonKey: config.supabaseAnonKey,
|
|
1422
1413
|
openaiApiKey: config.openaiApiKey,
|