gitmem-mcp 0.2.0
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/CHANGELOG.md +47 -0
- package/CLAUDE.md.template +65 -0
- package/LICENSE +21 -0
- package/README.md +221 -0
- package/bin/gitmem.js +383 -0
- package/dist/commands/check.d.ts +33 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +492 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/constants/closing-questions.d.ts +40 -0
- package/dist/constants/closing-questions.d.ts.map +1 -0
- package/dist/constants/closing-questions.js +107 -0
- package/dist/constants/closing-questions.js.map +1 -0
- package/dist/diagnostics/anonymizer.d.ts +55 -0
- package/dist/diagnostics/anonymizer.d.ts.map +1 -0
- package/dist/diagnostics/anonymizer.js +191 -0
- package/dist/diagnostics/anonymizer.js.map +1 -0
- package/dist/diagnostics/channels.d.ts +132 -0
- package/dist/diagnostics/channels.d.ts.map +1 -0
- package/dist/diagnostics/channels.js +150 -0
- package/dist/diagnostics/channels.js.map +1 -0
- package/dist/diagnostics/collector.d.ts +183 -0
- package/dist/diagnostics/collector.d.ts.map +1 -0
- package/dist/diagnostics/collector.js +227 -0
- package/dist/diagnostics/collector.js.map +1 -0
- package/dist/diagnostics/index.d.ts +28 -0
- package/dist/diagnostics/index.d.ts.map +1 -0
- package/dist/diagnostics/index.js +31 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/absorb-observations.d.ts +63 -0
- package/dist/schemas/absorb-observations.d.ts.map +1 -0
- package/dist/schemas/absorb-observations.js +25 -0
- package/dist/schemas/absorb-observations.js.map +1 -0
- package/dist/schemas/active-sessions.d.ts +71 -0
- package/dist/schemas/active-sessions.d.ts.map +1 -0
- package/dist/schemas/active-sessions.js +19 -0
- package/dist/schemas/active-sessions.js.map +1 -0
- package/dist/schemas/analyze.d.ts +38 -0
- package/dist/schemas/analyze.d.ts.map +1 -0
- package/dist/schemas/analyze.js +30 -0
- package/dist/schemas/analyze.js.map +1 -0
- package/dist/schemas/common.d.ts +55 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +65 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/create-decision.d.ts +48 -0
- package/dist/schemas/create-decision.d.ts.map +1 -0
- package/dist/schemas/create-decision.js +31 -0
- package/dist/schemas/create-decision.js.map +1 -0
- package/dist/schemas/create-learning.d.ts +107 -0
- package/dist/schemas/create-learning.d.ts.map +1 -0
- package/dist/schemas/create-learning.js +64 -0
- package/dist/schemas/create-learning.js.map +1 -0
- package/dist/schemas/get-transcript.d.ts +24 -0
- package/dist/schemas/get-transcript.d.ts.map +1 -0
- package/dist/schemas/get-transcript.js +22 -0
- package/dist/schemas/get-transcript.js.map +1 -0
- package/dist/schemas/index.d.ts +23 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +23 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/log.d.ts +36 -0
- package/dist/schemas/log.d.ts.map +1 -0
- package/dist/schemas/log.js +27 -0
- package/dist/schemas/log.js.map +1 -0
- package/dist/schemas/prepare-context.d.ts +41 -0
- package/dist/schemas/prepare-context.d.ts.map +1 -0
- package/dist/schemas/prepare-context.js +31 -0
- package/dist/schemas/prepare-context.js.map +1 -0
- package/dist/schemas/recall.d.ts +41 -0
- package/dist/schemas/recall.d.ts.map +1 -0
- package/dist/schemas/recall.js +47 -0
- package/dist/schemas/recall.js.map +1 -0
- package/dist/schemas/record-scar-usage-batch.d.ts +82 -0
- package/dist/schemas/record-scar-usage-batch.d.ts.map +1 -0
- package/dist/schemas/record-scar-usage-batch.js +25 -0
- package/dist/schemas/record-scar-usage-batch.js.map +1 -0
- package/dist/schemas/record-scar-usage.d.ts +51 -0
- package/dist/schemas/record-scar-usage.d.ts.map +1 -0
- package/dist/schemas/record-scar-usage.js +32 -0
- package/dist/schemas/record-scar-usage.js.map +1 -0
- package/dist/schemas/save-transcript.d.ts +38 -0
- package/dist/schemas/save-transcript.d.ts.map +1 -0
- package/dist/schemas/save-transcript.js +30 -0
- package/dist/schemas/save-transcript.js.map +1 -0
- package/dist/schemas/search.d.ts +36 -0
- package/dist/schemas/search.d.ts.map +1 -0
- package/dist/schemas/search.js +27 -0
- package/dist/schemas/search.js.map +1 -0
- package/dist/schemas/session-close.d.ts +371 -0
- package/dist/schemas/session-close.d.ts.map +1 -0
- package/dist/schemas/session-close.js +95 -0
- package/dist/schemas/session-close.js.map +1 -0
- package/dist/schemas/session-start.d.ts +46 -0
- package/dist/schemas/session-start.d.ts.map +1 -0
- package/dist/schemas/session-start.js +33 -0
- package/dist/schemas/session-start.js.map +1 -0
- package/dist/schemas/thread.d.ts +72 -0
- package/dist/schemas/thread.d.ts.map +1 -0
- package/dist/schemas/thread.js +39 -0
- package/dist/schemas/thread.js.map +1 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +313 -0
- package/dist/server.js.map +1 -0
- package/dist/services/active-sessions.d.ts +66 -0
- package/dist/services/active-sessions.d.ts.map +1 -0
- package/dist/services/active-sessions.js +311 -0
- package/dist/services/active-sessions.js.map +1 -0
- package/dist/services/agent-detection.d.ts +25 -0
- package/dist/services/agent-detection.d.ts.map +1 -0
- package/dist/services/agent-detection.js +93 -0
- package/dist/services/agent-detection.js.map +1 -0
- package/dist/services/analytics.d.ts +201 -0
- package/dist/services/analytics.d.ts.map +1 -0
- package/dist/services/analytics.js +483 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/cache.d.ts +148 -0
- package/dist/services/cache.d.ts.map +1 -0
- package/dist/services/cache.js +384 -0
- package/dist/services/cache.js.map +1 -0
- package/dist/services/cache.test.d.ts +8 -0
- package/dist/services/cache.test.d.ts.map +1 -0
- package/dist/services/cache.test.js +267 -0
- package/dist/services/cache.test.js.map +1 -0
- package/dist/services/compliance-validator.d.ts +30 -0
- package/dist/services/compliance-validator.d.ts.map +1 -0
- package/dist/services/compliance-validator.js +257 -0
- package/dist/services/compliance-validator.js.map +1 -0
- package/dist/services/config.d.ts +48 -0
- package/dist/services/config.d.ts.map +1 -0
- package/dist/services/config.js +128 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/embedding.d.ts +58 -0
- package/dist/services/embedding.d.ts.map +1 -0
- package/dist/services/embedding.js +243 -0
- package/dist/services/embedding.js.map +1 -0
- package/dist/services/gitmem-dir.d.ts +38 -0
- package/dist/services/gitmem-dir.d.ts.map +1 -0
- package/dist/services/gitmem-dir.js +84 -0
- package/dist/services/gitmem-dir.js.map +1 -0
- package/dist/services/local-file-storage.d.ts +56 -0
- package/dist/services/local-file-storage.d.ts.map +1 -0
- package/dist/services/local-file-storage.js +213 -0
- package/dist/services/local-file-storage.js.map +1 -0
- package/dist/services/local-vector-search.d.ts +137 -0
- package/dist/services/local-vector-search.d.ts.map +1 -0
- package/dist/services/local-vector-search.js +311 -0
- package/dist/services/local-vector-search.js.map +1 -0
- package/dist/services/metrics.d.ts +104 -0
- package/dist/services/metrics.d.ts.map +1 -0
- package/dist/services/metrics.js +264 -0
- package/dist/services/metrics.js.map +1 -0
- package/dist/services/session-state.d.ts +113 -0
- package/dist/services/session-state.d.ts.map +1 -0
- package/dist/services/session-state.js +203 -0
- package/dist/services/session-state.js.map +1 -0
- package/dist/services/startup.d.ts +112 -0
- package/dist/services/startup.d.ts.map +1 -0
- package/dist/services/startup.js +436 -0
- package/dist/services/startup.js.map +1 -0
- package/dist/services/storage.d.ts +43 -0
- package/dist/services/storage.d.ts.map +1 -0
- package/dist/services/storage.js +92 -0
- package/dist/services/storage.js.map +1 -0
- package/dist/services/supabase-client.d.ts +163 -0
- package/dist/services/supabase-client.d.ts.map +1 -0
- package/dist/services/supabase-client.js +510 -0
- package/dist/services/supabase-client.js.map +1 -0
- package/dist/services/thread-dedup.d.ts +44 -0
- package/dist/services/thread-dedup.d.ts.map +1 -0
- package/dist/services/thread-dedup.js +113 -0
- package/dist/services/thread-dedup.js.map +1 -0
- package/dist/services/thread-manager.d.ts +77 -0
- package/dist/services/thread-manager.d.ts.map +1 -0
- package/dist/services/thread-manager.js +250 -0
- package/dist/services/thread-manager.js.map +1 -0
- package/dist/services/thread-suggestions.d.ts +66 -0
- package/dist/services/thread-suggestions.d.ts.map +1 -0
- package/dist/services/thread-suggestions.js +243 -0
- package/dist/services/thread-suggestions.js.map +1 -0
- package/dist/services/thread-supabase.d.ts +111 -0
- package/dist/services/thread-supabase.d.ts.map +1 -0
- package/dist/services/thread-supabase.js +459 -0
- package/dist/services/thread-supabase.js.map +1 -0
- package/dist/services/thread-vitality.d.ts +65 -0
- package/dist/services/thread-vitality.d.ts.map +1 -0
- package/dist/services/thread-vitality.js +143 -0
- package/dist/services/thread-vitality.js.map +1 -0
- package/dist/services/tier.d.ts +52 -0
- package/dist/services/tier.d.ts.map +1 -0
- package/dist/services/tier.js +109 -0
- package/dist/services/tier.js.map +1 -0
- package/dist/services/timezone.d.ts +37 -0
- package/dist/services/timezone.d.ts.map +1 -0
- package/dist/services/timezone.js +147 -0
- package/dist/services/timezone.js.map +1 -0
- package/dist/services/transcript-chunker.d.ts +18 -0
- package/dist/services/transcript-chunker.d.ts.map +1 -0
- package/dist/services/transcript-chunker.js +237 -0
- package/dist/services/transcript-chunker.js.map +1 -0
- package/dist/services/triple-writer.d.ts +128 -0
- package/dist/services/triple-writer.d.ts.map +1 -0
- package/dist/services/triple-writer.js +338 -0
- package/dist/services/triple-writer.js.map +1 -0
- package/dist/services/variant-assignment.d.ts +92 -0
- package/dist/services/variant-assignment.d.ts.map +1 -0
- package/dist/services/variant-assignment.js +196 -0
- package/dist/services/variant-assignment.js.map +1 -0
- package/dist/tools/absorb-observations.d.ts +16 -0
- package/dist/tools/absorb-observations.d.ts.map +1 -0
- package/dist/tools/absorb-observations.js +82 -0
- package/dist/tools/absorb-observations.js.map +1 -0
- package/dist/tools/analyze.d.ts +55 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +139 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/cleanup-threads.d.ts +47 -0
- package/dist/tools/cleanup-threads.d.ts.map +1 -0
- package/dist/tools/cleanup-threads.js +127 -0
- package/dist/tools/cleanup-threads.js.map +1 -0
- package/dist/tools/confirm-scars.d.ts +23 -0
- package/dist/tools/confirm-scars.d.ts.map +1 -0
- package/dist/tools/confirm-scars.js +209 -0
- package/dist/tools/confirm-scars.js.map +1 -0
- package/dist/tools/create-decision.d.ts +15 -0
- package/dist/tools/create-decision.d.ts.map +1 -0
- package/dist/tools/create-decision.js +138 -0
- package/dist/tools/create-decision.js.map +1 -0
- package/dist/tools/create-learning.d.ts +15 -0
- package/dist/tools/create-learning.d.ts.map +1 -0
- package/dist/tools/create-learning.js +226 -0
- package/dist/tools/create-learning.js.map +1 -0
- package/dist/tools/create-thread.d.ts +42 -0
- package/dist/tools/create-thread.d.ts.map +1 -0
- package/dist/tools/create-thread.js +180 -0
- package/dist/tools/create-thread.js.map +1 -0
- package/dist/tools/definitions.d.ts +5013 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +2017 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/dismiss-suggestion.d.ts +20 -0
- package/dist/tools/dismiss-suggestion.d.ts.map +1 -0
- package/dist/tools/dismiss-suggestion.js +40 -0
- package/dist/tools/dismiss-suggestion.js.map +1 -0
- package/dist/tools/get-transcript.d.ts +24 -0
- package/dist/tools/get-transcript.d.ts.map +1 -0
- package/dist/tools/get-transcript.js +52 -0
- package/dist/tools/get-transcript.js.map +1 -0
- package/dist/tools/graph-traverse.d.ts +83 -0
- package/dist/tools/graph-traverse.d.ts.map +1 -0
- package/dist/tools/graph-traverse.js +394 -0
- package/dist/tools/graph-traverse.js.map +1 -0
- package/dist/tools/list-threads.d.ts +15 -0
- package/dist/tools/list-threads.d.ts.map +1 -0
- package/dist/tools/list-threads.js +114 -0
- package/dist/tools/list-threads.js.map +1 -0
- package/dist/tools/log.d.ts +43 -0
- package/dist/tools/log.d.ts.map +1 -0
- package/dist/tools/log.js +157 -0
- package/dist/tools/log.js.map +1 -0
- package/dist/tools/prepare-context.d.ts +36 -0
- package/dist/tools/prepare-context.d.ts.map +1 -0
- package/dist/tools/prepare-context.js +353 -0
- package/dist/tools/prepare-context.js.map +1 -0
- package/dist/tools/promote-suggestion.d.ts +25 -0
- package/dist/tools/promote-suggestion.d.ts.map +1 -0
- package/dist/tools/promote-suggestion.js +60 -0
- package/dist/tools/promote-suggestion.js.map +1 -0
- package/dist/tools/recall.d.ts +77 -0
- package/dist/tools/recall.d.ts.map +1 -0
- package/dist/tools/recall.js +423 -0
- package/dist/tools/recall.js.map +1 -0
- package/dist/tools/recall.test.d.ts +5 -0
- package/dist/tools/recall.test.d.ts.map +1 -0
- package/dist/tools/recall.test.js +155 -0
- package/dist/tools/recall.test.js.map +1 -0
- package/dist/tools/record-scar-usage-batch.d.ts +10 -0
- package/dist/tools/record-scar-usage-batch.d.ts.map +1 -0
- package/dist/tools/record-scar-usage-batch.js +153 -0
- package/dist/tools/record-scar-usage-batch.js.map +1 -0
- package/dist/tools/record-scar-usage.d.ts +14 -0
- package/dist/tools/record-scar-usage.d.ts.map +1 -0
- package/dist/tools/record-scar-usage.js +94 -0
- package/dist/tools/record-scar-usage.js.map +1 -0
- package/dist/tools/resolve-thread.d.ts +16 -0
- package/dist/tools/resolve-thread.d.ts.map +1 -0
- package/dist/tools/resolve-thread.js +102 -0
- package/dist/tools/resolve-thread.js.map +1 -0
- package/dist/tools/save-transcript.d.ts +29 -0
- package/dist/tools/save-transcript.d.ts.map +1 -0
- package/dist/tools/save-transcript.js +97 -0
- package/dist/tools/save-transcript.js.map +1 -0
- package/dist/tools/search.d.ts +46 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +186 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/session-close.d.ts +14 -0
- package/dist/tools/session-close.d.ts.map +1 -0
- package/dist/tools/session-close.js +881 -0
- package/dist/tools/session-close.js.map +1 -0
- package/dist/tools/session-start.d.ts +38 -0
- package/dist/tools/session-start.d.ts.map +1 -0
- package/dist/tools/session-start.js +1104 -0
- package/dist/tools/session-start.js.map +1 -0
- package/dist/types/index.d.ts +456 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +76 -0
- package/schema/setup.sql +193 -0
- package/schema/starter-scars.json +206 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supabase MCP Client
|
|
3
|
+
*
|
|
4
|
+
* HTTP client for ww-mcp Edge Function following the pattern from
|
|
5
|
+
* agents/coda/src/services/supabase-mcp.js
|
|
6
|
+
*
|
|
7
|
+
* Uses JSON-RPC 2.0 protocol over HTTPS.
|
|
8
|
+
* Integrates with CacheService for performance (OD-473).
|
|
9
|
+
*/
|
|
10
|
+
import { getCache } from "./cache.js";
|
|
11
|
+
// Configuration from environment
|
|
12
|
+
const SUPABASE_URL = process.env.SUPABASE_URL || "";
|
|
13
|
+
const SUPABASE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_KEY || "";
|
|
14
|
+
// Direct REST API base URL
|
|
15
|
+
const SUPABASE_REST_URL = SUPABASE_URL ? `${SUPABASE_URL}/rest/v1` : "";
|
|
16
|
+
/**
|
|
17
|
+
* Check if Supabase is configured
|
|
18
|
+
*/
|
|
19
|
+
export function isConfigured() {
|
|
20
|
+
return !!(SUPABASE_URL && SUPABASE_KEY);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the ww-mcp Edge Function URL
|
|
24
|
+
*/
|
|
25
|
+
function getMcpUrl() {
|
|
26
|
+
return `${SUPABASE_URL}/functions/v1/ww-mcp`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Call the ww-mcp Edge Function
|
|
30
|
+
*/
|
|
31
|
+
async function callMcp(toolName, args) {
|
|
32
|
+
if (!isConfigured()) {
|
|
33
|
+
throw new Error("Supabase not configured - check SUPABASE_URL and SUPABASE_KEY/SUPABASE_SERVICE_ROLE_KEY");
|
|
34
|
+
}
|
|
35
|
+
const mcpUrl = getMcpUrl();
|
|
36
|
+
const response = await fetch(mcpUrl, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: {
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
Authorization: `Bearer ${SUPABASE_KEY}`,
|
|
41
|
+
},
|
|
42
|
+
body: JSON.stringify({
|
|
43
|
+
jsonrpc: "2.0",
|
|
44
|
+
id: `${toolName}-${Date.now()}`,
|
|
45
|
+
method: "tools/call",
|
|
46
|
+
params: {
|
|
47
|
+
name: toolName,
|
|
48
|
+
arguments: args,
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const text = await response.text();
|
|
54
|
+
throw new Error(`MCP HTTP error: ${response.status} - ${text.slice(0, 200)}`);
|
|
55
|
+
}
|
|
56
|
+
const result = await response.json();
|
|
57
|
+
if (result.error) {
|
|
58
|
+
throw new Error(`MCP error: ${JSON.stringify(result.error)}`);
|
|
59
|
+
}
|
|
60
|
+
// Parse the result content
|
|
61
|
+
if (result.result?.content?.[0]?.text) {
|
|
62
|
+
return JSON.parse(result.result.content[0].text);
|
|
63
|
+
}
|
|
64
|
+
return result.result;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* List records from a table with optional filters
|
|
68
|
+
*/
|
|
69
|
+
export async function listRecords(options) {
|
|
70
|
+
const { table, columns, filters, limit = 50, orderBy } = options;
|
|
71
|
+
const args = {
|
|
72
|
+
table,
|
|
73
|
+
limit,
|
|
74
|
+
};
|
|
75
|
+
if (columns) {
|
|
76
|
+
args.columns = columns;
|
|
77
|
+
}
|
|
78
|
+
if (filters) {
|
|
79
|
+
args.filters = filters;
|
|
80
|
+
}
|
|
81
|
+
if (orderBy) {
|
|
82
|
+
args.orderBy = orderBy;
|
|
83
|
+
}
|
|
84
|
+
const result = await callMcp("list_records", args);
|
|
85
|
+
return result.data || [];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get a single record by ID
|
|
89
|
+
*/
|
|
90
|
+
export async function getRecord(table, id) {
|
|
91
|
+
const result = await callMcp("get_record", { table, id });
|
|
92
|
+
return result.data || null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Upsert (insert or update) a record
|
|
96
|
+
*/
|
|
97
|
+
export async function upsertRecord(table, data) {
|
|
98
|
+
const result = await callMcp("upsert_record", {
|
|
99
|
+
table,
|
|
100
|
+
data,
|
|
101
|
+
});
|
|
102
|
+
// ww-mcp returns { data: record, operation: 'insert'|'update', embedding_generated: bool }
|
|
103
|
+
return result.data || result;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Semantic search across tables
|
|
107
|
+
*/
|
|
108
|
+
export async function semanticSearch(options) {
|
|
109
|
+
const { query, tables, match_count = 10, project } = options;
|
|
110
|
+
const args = {
|
|
111
|
+
query,
|
|
112
|
+
match_count,
|
|
113
|
+
};
|
|
114
|
+
if (tables && tables.length > 0) {
|
|
115
|
+
args.tables = tables;
|
|
116
|
+
}
|
|
117
|
+
if (project) {
|
|
118
|
+
args.project = project;
|
|
119
|
+
}
|
|
120
|
+
const result = await callMcp("semantic_search", args);
|
|
121
|
+
return result.results || [];
|
|
122
|
+
}
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// DIRECT SUPABASE QUERIES (bypass ww-mcp for bulk operations)
|
|
125
|
+
// ============================================================================
|
|
126
|
+
/**
|
|
127
|
+
* Query Supabase REST API directly (bypasses ww-mcp)
|
|
128
|
+
*
|
|
129
|
+
* Used for bulk operations like loading all scars with embeddings.
|
|
130
|
+
* ww-mcp doesn't return embeddings by default to avoid bloated responses,
|
|
131
|
+
* but for local vector search we need them.
|
|
132
|
+
*/
|
|
133
|
+
export async function directQuery(table, options = {}) {
|
|
134
|
+
if (!isConfigured()) {
|
|
135
|
+
throw new Error("Supabase not configured");
|
|
136
|
+
}
|
|
137
|
+
const { select = "*", filters = {}, order, limit } = options;
|
|
138
|
+
// Build query URL
|
|
139
|
+
const url = new URL(`${SUPABASE_REST_URL}/${table}`);
|
|
140
|
+
url.searchParams.set("select", select);
|
|
141
|
+
// Add filters (PostgREST syntax)
|
|
142
|
+
// If value already contains an operator (e.g., "in.(...)"), use as-is
|
|
143
|
+
// Otherwise, prefix with "eq." for equality
|
|
144
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
145
|
+
const filterValue = value.includes('.') ? value : `eq.${value}`;
|
|
146
|
+
url.searchParams.set(key, filterValue);
|
|
147
|
+
}
|
|
148
|
+
// Add ordering
|
|
149
|
+
if (order) {
|
|
150
|
+
url.searchParams.set("order", order);
|
|
151
|
+
}
|
|
152
|
+
// Add limit
|
|
153
|
+
if (limit) {
|
|
154
|
+
url.searchParams.set("limit", String(limit));
|
|
155
|
+
}
|
|
156
|
+
const response = await fetch(url.toString(), {
|
|
157
|
+
method: "GET",
|
|
158
|
+
headers: {
|
|
159
|
+
"apikey": SUPABASE_KEY,
|
|
160
|
+
"Authorization": `Bearer ${SUPABASE_KEY}`,
|
|
161
|
+
"Content-Type": "application/json",
|
|
162
|
+
"Prefer": "return=representation",
|
|
163
|
+
"Accept-Profile": "public", // Required: explicitly use public schema
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
if (!response.ok) {
|
|
167
|
+
const text = await response.text();
|
|
168
|
+
throw new Error(`Supabase REST error: ${response.status} - ${text.slice(0, 200)}`);
|
|
169
|
+
}
|
|
170
|
+
return response.json();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Paginated fetch — retrieves ALL matching rows using PostgREST Range headers.
|
|
174
|
+
* Use instead of directQuery when the result set may exceed a single page.
|
|
175
|
+
*
|
|
176
|
+
* @param pageSize Rows per request (default 1000)
|
|
177
|
+
* @param maxRows Safety cap to prevent runaway queries (default 10000)
|
|
178
|
+
*/
|
|
179
|
+
export async function directQueryAll(table, options = {}, pageSize = 1000, maxRows = 10000) {
|
|
180
|
+
if (!isConfigured()) {
|
|
181
|
+
throw new Error("Supabase not configured");
|
|
182
|
+
}
|
|
183
|
+
const { select = "*", filters = {}, order } = options;
|
|
184
|
+
const allRows = [];
|
|
185
|
+
let offset = 0;
|
|
186
|
+
while (offset < maxRows) {
|
|
187
|
+
const url = new URL(`${SUPABASE_REST_URL}/${table}`);
|
|
188
|
+
url.searchParams.set("select", select);
|
|
189
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
190
|
+
const filterValue = value.includes('.') ? value : `eq.${value}`;
|
|
191
|
+
url.searchParams.set(key, filterValue);
|
|
192
|
+
}
|
|
193
|
+
if (order) {
|
|
194
|
+
url.searchParams.set("order", order);
|
|
195
|
+
}
|
|
196
|
+
const rangeEnd = offset + pageSize - 1;
|
|
197
|
+
const response = await fetch(url.toString(), {
|
|
198
|
+
method: "GET",
|
|
199
|
+
headers: {
|
|
200
|
+
"apikey": SUPABASE_KEY,
|
|
201
|
+
"Authorization": `Bearer ${SUPABASE_KEY}`,
|
|
202
|
+
"Content-Type": "application/json",
|
|
203
|
+
"Range": `${offset}-${rangeEnd}`,
|
|
204
|
+
"Range-Unit": "items",
|
|
205
|
+
"Prefer": "count=exact",
|
|
206
|
+
"Accept-Profile": "public",
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
if (!response.ok) {
|
|
210
|
+
const text = await response.text();
|
|
211
|
+
throw new Error(`Supabase REST error: ${response.status} - ${text.slice(0, 200)}`);
|
|
212
|
+
}
|
|
213
|
+
const rows = await response.json();
|
|
214
|
+
allRows.push(...rows);
|
|
215
|
+
// Check Content-Range header: "0-999/1234" or "*/0" for empty
|
|
216
|
+
const contentRange = response.headers.get("content-range");
|
|
217
|
+
if (!contentRange || rows.length < pageSize) {
|
|
218
|
+
break; // No more rows or last page
|
|
219
|
+
}
|
|
220
|
+
const match = contentRange.match(/\/(\d+)/);
|
|
221
|
+
if (match) {
|
|
222
|
+
const total = parseInt(match[1]);
|
|
223
|
+
if (offset + pageSize >= total)
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
offset += pageSize;
|
|
227
|
+
}
|
|
228
|
+
return allRows;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Fetch related knowledge triples for a set of scar IDs (OD-466)
|
|
232
|
+
*
|
|
233
|
+
* Queries knowledge_triples table where source_id matches any of the provided scar IDs.
|
|
234
|
+
* Returns triples grouped by source_id for easy attachment to scars.
|
|
235
|
+
*/
|
|
236
|
+
export async function fetchRelatedTriples(scarIds) {
|
|
237
|
+
const result = new Map();
|
|
238
|
+
if (scarIds.length === 0 || !isConfigured()) {
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const triples = await directQuery("knowledge_triples", {
|
|
243
|
+
select: "subject,predicate,object,event_time,decay_weight,half_life_days,decay_floor,source_id",
|
|
244
|
+
filters: {
|
|
245
|
+
source_id: `in.(${scarIds.join(",")})`,
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
for (const triple of triples) {
|
|
249
|
+
const existing = result.get(triple.source_id) || [];
|
|
250
|
+
existing.push(triple);
|
|
251
|
+
result.set(triple.source_id, existing);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
console.error("[fetchRelatedTriples] Failed:", error instanceof Error ? error.message : error);
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Upsert a record directly to Supabase REST API (bypasses ww-mcp)
|
|
261
|
+
*
|
|
262
|
+
* Used for tests where ww-mcp authentication is problematic.
|
|
263
|
+
* Uses Supabase REST API's upsert capability with Prefer: resolution=merge-duplicates.
|
|
264
|
+
*/
|
|
265
|
+
export async function directUpsert(table, data) {
|
|
266
|
+
if (!isConfigured()) {
|
|
267
|
+
throw new Error("Supabase not configured");
|
|
268
|
+
}
|
|
269
|
+
const url = `${SUPABASE_REST_URL}/${table}`;
|
|
270
|
+
const response = await fetch(url, {
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers: {
|
|
273
|
+
"apikey": SUPABASE_KEY,
|
|
274
|
+
"Authorization": `Bearer ${SUPABASE_KEY}`,
|
|
275
|
+
"Content-Type": "application/json",
|
|
276
|
+
"Prefer": "return=representation,resolution=merge-duplicates",
|
|
277
|
+
"Content-Profile": "public", // Schema for write operations
|
|
278
|
+
},
|
|
279
|
+
body: JSON.stringify(data),
|
|
280
|
+
});
|
|
281
|
+
if (!response.ok) {
|
|
282
|
+
const text = await response.text();
|
|
283
|
+
throw new Error(`Supabase upsert error: ${response.status} - ${text.slice(0, 200)}`);
|
|
284
|
+
}
|
|
285
|
+
const result = await response.json();
|
|
286
|
+
// OD-539: Validate that write actually happened
|
|
287
|
+
// Supabase can return 200 OK with empty array [] when:
|
|
288
|
+
// - RLS policy blocks the write
|
|
289
|
+
// - Constraint violation handled gracefully
|
|
290
|
+
// - Database trigger cancels the insert
|
|
291
|
+
// - Schema mismatch
|
|
292
|
+
if (!result || result.length === 0) {
|
|
293
|
+
throw new Error(`Supabase upsert returned empty result for table '${table}'. ` +
|
|
294
|
+
`This usually means the write was silently blocked. ` +
|
|
295
|
+
`Check: (1) RLS policies on ${table}, (2) NOT NULL constraints, (3) database triggers, (4) correct schema`);
|
|
296
|
+
}
|
|
297
|
+
return result[0];
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Patch (partial update) existing records in Supabase REST API.
|
|
301
|
+
*
|
|
302
|
+
* Uses HTTP PATCH for true partial updates — only the provided fields are
|
|
303
|
+
* modified. Unlike directUpsert (POST + merge-duplicates), this does NOT
|
|
304
|
+
* try to INSERT first, so NOT NULL columns that aren't changing can be
|
|
305
|
+
* omitted from `data`.
|
|
306
|
+
*
|
|
307
|
+
* @param table Target table name
|
|
308
|
+
* @param filters PostgREST filter to identify the row(s) to update
|
|
309
|
+
* @param data Fields to update (partial — omitted columns stay unchanged)
|
|
310
|
+
*/
|
|
311
|
+
export async function directPatch(table, filters, data) {
|
|
312
|
+
if (!isConfigured()) {
|
|
313
|
+
throw new Error("Supabase not configured");
|
|
314
|
+
}
|
|
315
|
+
const url = new URL(`${SUPABASE_REST_URL}/${table}`);
|
|
316
|
+
// Apply filters (same logic as directQuery)
|
|
317
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
318
|
+
const filterValue = value.includes(".") ? value : `eq.${value}`;
|
|
319
|
+
url.searchParams.set(key, filterValue);
|
|
320
|
+
}
|
|
321
|
+
const response = await fetch(url.toString(), {
|
|
322
|
+
method: "PATCH",
|
|
323
|
+
headers: {
|
|
324
|
+
"apikey": SUPABASE_KEY,
|
|
325
|
+
"Authorization": `Bearer ${SUPABASE_KEY}`,
|
|
326
|
+
"Content-Type": "application/json",
|
|
327
|
+
"Prefer": "return=representation",
|
|
328
|
+
"Content-Profile": "public",
|
|
329
|
+
},
|
|
330
|
+
body: JSON.stringify(data),
|
|
331
|
+
});
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
const text = await response.text();
|
|
334
|
+
throw new Error(`Supabase patch error: ${response.status} - ${text.slice(0, 200)}`);
|
|
335
|
+
}
|
|
336
|
+
return response.json();
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Load all learnings with embeddings directly from Supabase
|
|
340
|
+
*
|
|
341
|
+
* This bypasses ww-mcp because we need the embedding vectors for local search.
|
|
342
|
+
* Returns learnings (scars, patterns, wins, anti-patterns) with full embedding data.
|
|
343
|
+
*
|
|
344
|
+
* NOTE: Changed from "scars only" to "all learning types" (OD-542 related fix)
|
|
345
|
+
*/
|
|
346
|
+
export async function loadScarsWithEmbeddings(project, limit = 500) {
|
|
347
|
+
console.error(`[supabase-direct] Loading learnings with embeddings for project: ${project}`);
|
|
348
|
+
const startTime = Date.now();
|
|
349
|
+
try {
|
|
350
|
+
const learnings = await directQuery("orchestra_learnings", {
|
|
351
|
+
select: "id,title,description,severity,counter_arguments,applies_when,source_linear_issue,project,embedding,updated_at,learning_type",
|
|
352
|
+
filters: {
|
|
353
|
+
project,
|
|
354
|
+
learning_type: "in.(scar,pattern,win,anti_pattern)",
|
|
355
|
+
},
|
|
356
|
+
order: "updated_at.desc",
|
|
357
|
+
limit,
|
|
358
|
+
});
|
|
359
|
+
const elapsed = Date.now() - startTime;
|
|
360
|
+
console.error(`[supabase-direct] Loaded ${learnings.length} learnings in ${elapsed}ms`);
|
|
361
|
+
return learnings;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
console.error("[supabase-direct] Failed to load learnings:", error);
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Scar search with severity weighting
|
|
370
|
+
*/
|
|
371
|
+
export async function scarSearch(query, matchCount = 5, project) {
|
|
372
|
+
const args = {
|
|
373
|
+
query,
|
|
374
|
+
match_count: matchCount,
|
|
375
|
+
};
|
|
376
|
+
if (project) {
|
|
377
|
+
args.project = project;
|
|
378
|
+
}
|
|
379
|
+
const result = await callMcp("scar_search", args);
|
|
380
|
+
return result.results || [];
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Scar search with caching (OD-473)
|
|
384
|
+
*
|
|
385
|
+
* Returns cached results if available, otherwise fetches and caches.
|
|
386
|
+
*/
|
|
387
|
+
export async function cachedScarSearch(query, matchCount = 5, project = "orchestra_dev") {
|
|
388
|
+
const cache = getCache();
|
|
389
|
+
const { data, cache_hit, cache_age_ms } = await cache.getOrFetchScarSearch(query, project, matchCount, async () => scarSearch(query, matchCount, project));
|
|
390
|
+
return { results: data, cache_hit, cache_age_ms };
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* List records with caching for decisions (OD-473)
|
|
394
|
+
*/
|
|
395
|
+
export async function cachedListDecisions(project = "orchestra_dev", limit = 5) {
|
|
396
|
+
const cache = getCache();
|
|
397
|
+
const { data, cache_hit, cache_age_ms } = await cache.getOrFetchDecisions(project, limit, async () => listRecords({
|
|
398
|
+
table: "orchestra_decisions_lite",
|
|
399
|
+
limit,
|
|
400
|
+
orderBy: { column: "created_at", ascending: false },
|
|
401
|
+
}));
|
|
402
|
+
return { data, cache_hit, cache_age_ms };
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* List records with caching for wins
|
|
406
|
+
*/
|
|
407
|
+
export async function cachedListWins(project = "orchestra_dev", limit = 8, columns) {
|
|
408
|
+
const cache = getCache();
|
|
409
|
+
const { data, cache_hit, cache_age_ms } = await cache.getOrFetchWins(project, limit, async () => listRecords({
|
|
410
|
+
table: "orchestra_learnings_lite",
|
|
411
|
+
columns,
|
|
412
|
+
filters: {
|
|
413
|
+
learning_type: "win",
|
|
414
|
+
project,
|
|
415
|
+
},
|
|
416
|
+
limit,
|
|
417
|
+
orderBy: { column: "created_at", ascending: false },
|
|
418
|
+
}));
|
|
419
|
+
return { data, cache_hit, cache_age_ms };
|
|
420
|
+
}
|
|
421
|
+
// ============================================================================
|
|
422
|
+
// STORAGE API (for transcript persistence - OD-467)
|
|
423
|
+
// ============================================================================
|
|
424
|
+
const TRANSCRIPT_BUCKET = "session-transcripts";
|
|
425
|
+
/**
|
|
426
|
+
* Upload a file to Supabase Storage
|
|
427
|
+
*/
|
|
428
|
+
export async function uploadFile(bucket, path, content, contentType = "application/json") {
|
|
429
|
+
if (!isConfigured()) {
|
|
430
|
+
throw new Error("Supabase not configured");
|
|
431
|
+
}
|
|
432
|
+
const storageUrl = `${SUPABASE_URL}/storage/v1/object/${bucket}/${path}`;
|
|
433
|
+
const response = await fetch(storageUrl, {
|
|
434
|
+
method: "POST",
|
|
435
|
+
headers: {
|
|
436
|
+
"Content-Type": contentType,
|
|
437
|
+
Authorization: `Bearer ${SUPABASE_KEY}`,
|
|
438
|
+
},
|
|
439
|
+
body: content,
|
|
440
|
+
});
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
const text = await response.text();
|
|
443
|
+
throw new Error(`Storage upload error: ${response.status} - ${text.slice(0, 200)}`);
|
|
444
|
+
}
|
|
445
|
+
return { path: `${bucket}/${path}` };
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Download a file from Supabase Storage
|
|
449
|
+
*/
|
|
450
|
+
export async function downloadFile(bucket, path) {
|
|
451
|
+
if (!isConfigured()) {
|
|
452
|
+
throw new Error("Supabase not configured");
|
|
453
|
+
}
|
|
454
|
+
const storageUrl = `${SUPABASE_URL}/storage/v1/object/${bucket}/${path}`;
|
|
455
|
+
const response = await fetch(storageUrl, {
|
|
456
|
+
method: "GET",
|
|
457
|
+
headers: {
|
|
458
|
+
Authorization: `Bearer ${SUPABASE_KEY}`,
|
|
459
|
+
},
|
|
460
|
+
});
|
|
461
|
+
if (!response.ok) {
|
|
462
|
+
const text = await response.text();
|
|
463
|
+
throw new Error(`Storage download error: ${response.status} - ${text.slice(0, 200)}`);
|
|
464
|
+
}
|
|
465
|
+
return response.text();
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Save a session transcript to storage
|
|
469
|
+
*/
|
|
470
|
+
export async function saveTranscript(sessionId, transcript, metadata = {}) {
|
|
471
|
+
const { project = "orchestra_dev", agent = "unknown", format = "json" } = metadata;
|
|
472
|
+
const date = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
|
|
473
|
+
const extension = format === "markdown" ? "md" : "json";
|
|
474
|
+
const path = `${project}/${agent}/${date}/${sessionId}.${extension}`;
|
|
475
|
+
const contentType = format === "markdown" ? "text/markdown" : "application/json";
|
|
476
|
+
const content = format === "json" ? transcript : transcript;
|
|
477
|
+
await uploadFile(TRANSCRIPT_BUCKET, path, content, contentType);
|
|
478
|
+
// Update the session record with transcript_path (direct REST API)
|
|
479
|
+
try {
|
|
480
|
+
await directUpsert("orchestra_sessions", {
|
|
481
|
+
id: sessionId,
|
|
482
|
+
transcript_path: path,
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
// Log but don't fail - transcript is saved even if session update fails
|
|
487
|
+
console.error("Failed to update session with transcript_path:", error);
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
transcript_path: path,
|
|
491
|
+
size_bytes: Buffer.byteLength(content, "utf8"),
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Retrieve a session transcript from storage
|
|
496
|
+
*/
|
|
497
|
+
export async function getTranscript(sessionId) {
|
|
498
|
+
// First, get the session to find transcript_path
|
|
499
|
+
const session = await getRecord("orchestra_sessions", sessionId);
|
|
500
|
+
if (!session?.transcript_path) {
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
// Download the transcript
|
|
504
|
+
const transcript = await downloadFile(TRANSCRIPT_BUCKET, session.transcript_path);
|
|
505
|
+
return {
|
|
506
|
+
transcript,
|
|
507
|
+
path: session.transcript_path,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=supabase-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase-client.js","sourceRoot":"","sources":["../../src/services/supabase-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thread Deduplication Service (Phase 3)
|
|
3
|
+
*
|
|
4
|
+
* Pure functions for detecting duplicate threads by embedding similarity
|
|
5
|
+
* or normalized text equality. Zero I/O — all Supabase and embedding
|
|
6
|
+
* calls live in the caller (create-thread.ts).
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* 1. If embedding available: cosine similarity > 0.85 → duplicate
|
|
10
|
+
* 2. If embedding unavailable: normalized text equality → duplicate
|
|
11
|
+
* 3. If no existing threads: skip check
|
|
12
|
+
*/
|
|
13
|
+
export interface ThreadWithEmbedding {
|
|
14
|
+
thread_id: string;
|
|
15
|
+
text: string;
|
|
16
|
+
embedding: number[] | null;
|
|
17
|
+
}
|
|
18
|
+
export interface DedupResult {
|
|
19
|
+
is_duplicate: boolean;
|
|
20
|
+
matched_thread_id: string | null;
|
|
21
|
+
matched_text: string | null;
|
|
22
|
+
similarity: number | null;
|
|
23
|
+
method: "embedding" | "text_normalization" | "skipped";
|
|
24
|
+
}
|
|
25
|
+
export declare const DEDUP_SIMILARITY_THRESHOLD = 0.85;
|
|
26
|
+
/**
|
|
27
|
+
* Check if new thread text is a semantic duplicate of any existing open thread.
|
|
28
|
+
*
|
|
29
|
+
* @param newText - Trimmed thread text
|
|
30
|
+
* @param newEmbedding - Normalized embedding vector, or null if unavailable
|
|
31
|
+
* @param existingThreads - Open threads with optional embeddings
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkDuplicate(newText: string, newEmbedding: number[] | null, existingThreads: ThreadWithEmbedding[]): DedupResult;
|
|
34
|
+
/**
|
|
35
|
+
* Cosine similarity between two normalized vectors.
|
|
36
|
+
* Assumes vectors are already L2-normalized (dot product = cosine similarity).
|
|
37
|
+
*/
|
|
38
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
39
|
+
/**
|
|
40
|
+
* Normalize text for conservative text-only comparison.
|
|
41
|
+
* Lowercase, collapse whitespace, trim, strip trailing punctuation.
|
|
42
|
+
*/
|
|
43
|
+
export declare function normalizeText(text: string): string;
|
|
44
|
+
//# sourceMappingURL=thread-dedup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-dedup.d.ts","sourceRoot":"","sources":["../../src/services/thread-dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,GAAG,oBAAoB,GAAG,SAAS,CAAC;CACxD;AAID,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAI/C;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,EAC7B,eAAe,EAAE,mBAAmB,EAAE,GACrC,WAAW,CAmEb;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAQjE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlD"}
|