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,459 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thread Supabase Service (OD-620, OD-621, OD-622, OD-623, OD-624)
|
|
3
|
+
*
|
|
4
|
+
* Provides Supabase CRUD operations for the orchestra_threads table.
|
|
5
|
+
* Supabase is the source of truth; local .gitmem/threads.json is a cache.
|
|
6
|
+
*
|
|
7
|
+
* Uses directQuery/directUpsert (PostgREST) like other Supabase operations
|
|
8
|
+
* in this codebase. Graceful fallback: if Supabase is unreachable, callers
|
|
9
|
+
* fall back to local file operations.
|
|
10
|
+
*/
|
|
11
|
+
import * as supabase from "./supabase-client.js";
|
|
12
|
+
import { hasSupabase } from "./tier.js";
|
|
13
|
+
import { computeLifecycleStatus, detectThreadClass } from "./thread-vitality.js";
|
|
14
|
+
// ---------- Mapping Helpers ----------
|
|
15
|
+
/**
|
|
16
|
+
* Map a local ThreadObject to a Supabase row for insert/upsert.
|
|
17
|
+
*/
|
|
18
|
+
export function threadObjectToRow(thread, project = "orchestra_dev", embedding) {
|
|
19
|
+
const now = new Date();
|
|
20
|
+
const createdAt = thread.created_at || now.toISOString();
|
|
21
|
+
const threadClass = detectThreadClass(thread.text);
|
|
22
|
+
// Phase 6: Use lifecycle status for new threads (will be "emerging" if < 24h old)
|
|
23
|
+
const { lifecycle_status, vitality } = computeLifecycleStatus({
|
|
24
|
+
last_touched_at: createdAt,
|
|
25
|
+
touch_count: 1,
|
|
26
|
+
created_at: createdAt,
|
|
27
|
+
thread_class: threadClass,
|
|
28
|
+
current_status: mapStatusToSupabase(thread.status),
|
|
29
|
+
}, now);
|
|
30
|
+
return {
|
|
31
|
+
thread_id: thread.id, // "t-XXXXXXXX" -> thread_id column
|
|
32
|
+
text: thread.text,
|
|
33
|
+
status: thread.status === "resolved" ? "resolved" : lifecycle_status,
|
|
34
|
+
thread_class: threadClass,
|
|
35
|
+
vitality_score: vitality.vitality_score,
|
|
36
|
+
last_touched_at: createdAt,
|
|
37
|
+
touch_count: 1,
|
|
38
|
+
created_at: createdAt,
|
|
39
|
+
resolved_at: thread.resolved_at || null,
|
|
40
|
+
resolution_note: thread.resolution_note || null,
|
|
41
|
+
source_session: thread.source_session || null,
|
|
42
|
+
resolved_by_session: thread.resolved_by_session || null,
|
|
43
|
+
project,
|
|
44
|
+
metadata: {},
|
|
45
|
+
...(embedding != null && { embedding }),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Map a Supabase row to a local ThreadObject.
|
|
50
|
+
*/
|
|
51
|
+
export function rowToThreadObject(row) {
|
|
52
|
+
return {
|
|
53
|
+
id: row.thread_id, // thread_id column -> ThreadObject.id
|
|
54
|
+
text: row.text,
|
|
55
|
+
status: mapStatusFromSupabase(row.status),
|
|
56
|
+
created_at: row.created_at,
|
|
57
|
+
...(row.resolved_at && { resolved_at: row.resolved_at }),
|
|
58
|
+
...(row.source_session && { source_session: row.source_session }),
|
|
59
|
+
...(row.resolved_by_session && { resolved_by_session: row.resolved_by_session }),
|
|
60
|
+
...(row.resolution_note && { resolution_note: row.resolution_note }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map local ThreadObject status ("open"|"resolved") to Supabase status.
|
|
65
|
+
* Phase 1: "open" -> "active", "resolved" -> "resolved"
|
|
66
|
+
*/
|
|
67
|
+
function mapStatusToSupabase(status) {
|
|
68
|
+
if (status === "open")
|
|
69
|
+
return "active";
|
|
70
|
+
if (status === "resolved")
|
|
71
|
+
return "resolved";
|
|
72
|
+
// Pass through any Supabase-native statuses
|
|
73
|
+
return status;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Map Supabase status to local ThreadObject status.
|
|
77
|
+
* Phase 1: Any non-resolved status -> "open"
|
|
78
|
+
*/
|
|
79
|
+
function mapStatusFromSupabase(status) {
|
|
80
|
+
if (status === "resolved")
|
|
81
|
+
return "resolved";
|
|
82
|
+
return "open"; // emerging, active, cooling, dormant, archived -> "open" for backward compat
|
|
83
|
+
}
|
|
84
|
+
// ---------- CRUD Operations ----------
|
|
85
|
+
/**
|
|
86
|
+
* Create a thread in Supabase.
|
|
87
|
+
* Returns the created row or null if Supabase is unavailable.
|
|
88
|
+
*/
|
|
89
|
+
export async function createThreadInSupabase(thread, project = "orchestra_dev", embedding) {
|
|
90
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const row = threadObjectToRow(thread, project, embedding);
|
|
95
|
+
const result = await supabase.directUpsert("orchestra_threads", row);
|
|
96
|
+
console.error(`[thread-supabase] Created thread ${thread.id} in Supabase`);
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error("[thread-supabase] Failed to create thread:", error instanceof Error ? error.message : error);
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolve a thread in Supabase by thread_id.
|
|
106
|
+
* Updates status, resolved_at, resolution_note, resolved_by_session.
|
|
107
|
+
* Returns true if update succeeded.
|
|
108
|
+
*/
|
|
109
|
+
export async function resolveThreadInSupabase(threadId, options = {}) {
|
|
110
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
// First, find the UUID primary key for this thread_id
|
|
115
|
+
const rows = await supabase.directQuery("orchestra_threads", {
|
|
116
|
+
select: "id,thread_id",
|
|
117
|
+
filters: { thread_id: threadId },
|
|
118
|
+
limit: 1,
|
|
119
|
+
});
|
|
120
|
+
if (rows.length === 0) {
|
|
121
|
+
console.error(`[thread-supabase] Thread ${threadId} not found in Supabase (will proceed with local-only)`);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const uuid = rows[0].id;
|
|
125
|
+
const patchData = {
|
|
126
|
+
status: "resolved",
|
|
127
|
+
resolved_at: options.resolvedAt || new Date().toISOString(),
|
|
128
|
+
};
|
|
129
|
+
if (options.resolutionNote) {
|
|
130
|
+
patchData.resolution_note = options.resolutionNote;
|
|
131
|
+
}
|
|
132
|
+
if (options.resolvedBySession) {
|
|
133
|
+
patchData.resolved_by_session = options.resolvedBySession;
|
|
134
|
+
}
|
|
135
|
+
await supabase.directPatch("orchestra_threads", { id: uuid }, patchData);
|
|
136
|
+
console.error(`[thread-supabase] Resolved thread ${threadId} in Supabase`);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error("[thread-supabase] Failed to resolve thread:", error instanceof Error ? error.message : error);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* List threads from Supabase with project filter.
|
|
146
|
+
* Uses orchestra_threads_lite view (no embedding column).
|
|
147
|
+
* Returns null if Supabase is unavailable (caller should fall back to local).
|
|
148
|
+
*/
|
|
149
|
+
export async function listThreadsFromSupabase(project = "orchestra_dev", options = {}) {
|
|
150
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const filters = {
|
|
155
|
+
project,
|
|
156
|
+
};
|
|
157
|
+
// Apply status filter unless including all
|
|
158
|
+
if (!options.includeResolved && options.statusFilter) {
|
|
159
|
+
if (options.statusFilter === "open") {
|
|
160
|
+
// "open" in local status = all non-terminal Supabase statuses
|
|
161
|
+
filters.status = "not.in.(resolved,archived)";
|
|
162
|
+
}
|
|
163
|
+
else if (options.statusFilter === "resolved") {
|
|
164
|
+
filters.status = "resolved";
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// Pass through any Supabase-native status
|
|
168
|
+
filters.status = options.statusFilter;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
else if (!options.includeResolved) {
|
|
172
|
+
// Default: exclude resolved and archived
|
|
173
|
+
filters.status = "not.in.(resolved,archived)";
|
|
174
|
+
}
|
|
175
|
+
const rows = await supabase.directQuery("orchestra_threads_lite", {
|
|
176
|
+
select: "*",
|
|
177
|
+
filters,
|
|
178
|
+
order: "vitality_score.desc,last_touched_at.desc",
|
|
179
|
+
limit: 100,
|
|
180
|
+
});
|
|
181
|
+
console.error(`[thread-supabase] Listed ${rows.length} threads from Supabase`);
|
|
182
|
+
return rows.map(rowToThreadObject);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error("[thread-supabase] Failed to list threads:", error instanceof Error ? error.message : error);
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Load active (non-archived, non-resolved) threads from Supabase for session_start.
|
|
191
|
+
* Uses orchestra_threads_lite view ordered by vitality_score DESC.
|
|
192
|
+
* Returns null if Supabase is unavailable.
|
|
193
|
+
*/
|
|
194
|
+
export async function loadActiveThreadsFromSupabase(project = "orchestra_dev") {
|
|
195
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
// Get all non-archived threads (both active and recently resolved)
|
|
200
|
+
const rows = await supabase.directQuery("orchestra_threads_lite", {
|
|
201
|
+
select: "*",
|
|
202
|
+
filters: {
|
|
203
|
+
project,
|
|
204
|
+
status: "not.in.(archived,dormant)",
|
|
205
|
+
},
|
|
206
|
+
order: "vitality_score.desc,last_touched_at.desc",
|
|
207
|
+
limit: 100,
|
|
208
|
+
});
|
|
209
|
+
const now = new Date();
|
|
210
|
+
const open = [];
|
|
211
|
+
const recentlyResolved = [];
|
|
212
|
+
const displayInfo = [];
|
|
213
|
+
// Deduplicate by text content (mirrors aggregateThreads logic)
|
|
214
|
+
const seenText = new Set();
|
|
215
|
+
const seenIds = new Set();
|
|
216
|
+
// Recently resolved = resolved in last 14 days
|
|
217
|
+
const cutoff = new Date();
|
|
218
|
+
cutoff.setDate(cutoff.getDate() - 14);
|
|
219
|
+
const cutoffStr = cutoff.toISOString();
|
|
220
|
+
for (const row of rows) {
|
|
221
|
+
// Deduplicate by both thread ID and normalized text
|
|
222
|
+
const key = (row.text || "").toLowerCase().trim();
|
|
223
|
+
if (seenIds.has(row.id) || (key && seenText.has(key)))
|
|
224
|
+
continue;
|
|
225
|
+
seenIds.add(row.id);
|
|
226
|
+
if (key)
|
|
227
|
+
seenText.add(key);
|
|
228
|
+
const thread = rowToThreadObject(row);
|
|
229
|
+
if (row.status === "resolved") {
|
|
230
|
+
if (row.resolved_at && row.resolved_at >= cutoffStr) {
|
|
231
|
+
recentlyResolved.push(thread);
|
|
232
|
+
}
|
|
233
|
+
// Older resolved threads are skipped
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
open.push(thread);
|
|
237
|
+
// Phase 6: Compute lifecycle display info for open threads
|
|
238
|
+
const lastTouched = new Date(row.last_touched_at);
|
|
239
|
+
const daysSinceTouch = Math.max((now.getTime() - lastTouched.getTime()) / (1000 * 60 * 60 * 24), 0);
|
|
240
|
+
const { lifecycle_status } = computeLifecycleStatus({
|
|
241
|
+
last_touched_at: row.last_touched_at,
|
|
242
|
+
touch_count: row.touch_count,
|
|
243
|
+
created_at: row.created_at,
|
|
244
|
+
thread_class: row.thread_class || "backlog",
|
|
245
|
+
current_status: row.status,
|
|
246
|
+
dormant_since: row.metadata?.dormant_since,
|
|
247
|
+
}, now);
|
|
248
|
+
displayInfo.push({
|
|
249
|
+
thread,
|
|
250
|
+
vitality_score: row.vitality_score,
|
|
251
|
+
lifecycle_status,
|
|
252
|
+
thread_class: row.thread_class || "backlog",
|
|
253
|
+
days_since_touch: Math.round(daysSinceTouch),
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const dupsRemoved = rows.length - open.length - recentlyResolved.length;
|
|
258
|
+
console.error(`[thread-supabase] Loaded ${open.length} open, ${recentlyResolved.length} recently resolved threads from Supabase (${dupsRemoved} duplicates removed)`);
|
|
259
|
+
return { open, recentlyResolved, displayInfo };
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error("[thread-supabase] Failed to load active threads:", error instanceof Error ? error.message : error);
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Touch threads in Supabase — increment touch_count and update last_touched_at.
|
|
268
|
+
* Called during session_close for threads that were referenced during the session.
|
|
269
|
+
*/
|
|
270
|
+
export async function touchThreadsInSupabase(threadIds) {
|
|
271
|
+
if (!hasSupabase() || !supabase.isConfigured() || threadIds.length === 0) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
for (const threadId of threadIds) {
|
|
275
|
+
try {
|
|
276
|
+
// Fetch current state (need created_at and thread_class for vitality recomputation)
|
|
277
|
+
const rows = await supabase.directQuery("orchestra_threads", {
|
|
278
|
+
select: "id,touch_count,created_at,thread_class,status",
|
|
279
|
+
filters: { thread_id: threadId },
|
|
280
|
+
limit: 1,
|
|
281
|
+
});
|
|
282
|
+
if (rows.length === 0)
|
|
283
|
+
continue;
|
|
284
|
+
const row = rows[0];
|
|
285
|
+
// Skip resolved/archived threads — no point recomputing vitality
|
|
286
|
+
if (row.status === "resolved" || row.status === "archived")
|
|
287
|
+
continue;
|
|
288
|
+
const now = new Date();
|
|
289
|
+
const newTouchCount = (row.touch_count || 0) + 1;
|
|
290
|
+
const nowIso = now.toISOString();
|
|
291
|
+
// Recompute lifecycle status (Phase 6: includes emerging/archival logic)
|
|
292
|
+
const { lifecycle_status, vitality } = computeLifecycleStatus({
|
|
293
|
+
last_touched_at: nowIso,
|
|
294
|
+
touch_count: newTouchCount,
|
|
295
|
+
created_at: row.created_at,
|
|
296
|
+
thread_class: row.thread_class || "backlog",
|
|
297
|
+
current_status: row.status,
|
|
298
|
+
dormant_since: row.metadata?.dormant_since,
|
|
299
|
+
}, now);
|
|
300
|
+
// Track dormant_since in metadata for archival computation
|
|
301
|
+
const metadata = { ...(row.metadata || {}) };
|
|
302
|
+
if (lifecycle_status === "dormant" && row.status !== "dormant") {
|
|
303
|
+
metadata.dormant_since = nowIso;
|
|
304
|
+
}
|
|
305
|
+
else if (lifecycle_status !== "dormant") {
|
|
306
|
+
delete metadata.dormant_since;
|
|
307
|
+
}
|
|
308
|
+
await supabase.directPatch("orchestra_threads", { id: row.id }, {
|
|
309
|
+
touch_count: newTouchCount,
|
|
310
|
+
last_touched_at: nowIso,
|
|
311
|
+
vitality_score: vitality.vitality_score,
|
|
312
|
+
status: lifecycle_status,
|
|
313
|
+
metadata,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.error(`[thread-supabase] Failed to touch thread ${threadId}:`, error instanceof Error ? error.message : error);
|
|
318
|
+
// Continue with other threads
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Batch create/update threads in Supabase.
|
|
324
|
+
* Used by session_close to sync thread state.
|
|
325
|
+
* New threads (not in Supabase) get created; existing threads get touched.
|
|
326
|
+
*/
|
|
327
|
+
export async function syncThreadsToSupabase(threads, project = "orchestra_dev", sessionId) {
|
|
328
|
+
if (!hasSupabase() || !supabase.isConfigured() || threads.length === 0) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
for (const thread of threads) {
|
|
332
|
+
try {
|
|
333
|
+
// Check if thread exists in Supabase
|
|
334
|
+
const existing = await supabase.directQuery("orchestra_threads", {
|
|
335
|
+
select: "id,thread_id,status",
|
|
336
|
+
filters: { thread_id: thread.id },
|
|
337
|
+
limit: 1,
|
|
338
|
+
});
|
|
339
|
+
if (existing.length === 0) {
|
|
340
|
+
// New thread — create it
|
|
341
|
+
await createThreadInSupabase(thread, project);
|
|
342
|
+
}
|
|
343
|
+
else if (thread.status === "resolved" && existing[0].status !== "resolved") {
|
|
344
|
+
// Thread was resolved during this session
|
|
345
|
+
await resolveThreadInSupabase(thread.id, {
|
|
346
|
+
resolvedAt: thread.resolved_at,
|
|
347
|
+
resolutionNote: thread.resolution_note,
|
|
348
|
+
resolvedBySession: thread.resolved_by_session || sessionId,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
// Existing thread, just touch it
|
|
353
|
+
await touchThreadsInSupabase([thread.id]);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
console.error(`[thread-supabase] Failed to sync thread ${thread.id}:`, error instanceof Error ? error.message : error);
|
|
358
|
+
// Continue with other threads
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// ---------- Archival (Phase 6) ----------
|
|
363
|
+
/**
|
|
364
|
+
* Archive dormant threads that have been dormant for 30+ days.
|
|
365
|
+
* Reads metadata.dormant_since to determine eligibility.
|
|
366
|
+
* Called at session_start as fire-and-forget.
|
|
367
|
+
*/
|
|
368
|
+
export async function archiveDormantThreads(project = "orchestra_dev", dormantDays = 30) {
|
|
369
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
370
|
+
return { archived_count: 0, archived_ids: [] };
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
// Fetch dormant threads
|
|
374
|
+
const rows = await supabase.directQuery("orchestra_threads", {
|
|
375
|
+
select: "id,thread_id,metadata",
|
|
376
|
+
filters: {
|
|
377
|
+
project,
|
|
378
|
+
status: "dormant",
|
|
379
|
+
},
|
|
380
|
+
limit: 100,
|
|
381
|
+
});
|
|
382
|
+
const now = new Date();
|
|
383
|
+
const archived_ids = [];
|
|
384
|
+
for (const row of rows) {
|
|
385
|
+
const dormantSince = row.metadata?.dormant_since;
|
|
386
|
+
if (!dormantSince)
|
|
387
|
+
continue;
|
|
388
|
+
const dormantStart = new Date(dormantSince);
|
|
389
|
+
const daysDormant = (now.getTime() - dormantStart.getTime()) / (1000 * 60 * 60 * 24);
|
|
390
|
+
if (daysDormant >= dormantDays) {
|
|
391
|
+
await supabase.directPatch("orchestra_threads", { id: row.id }, {
|
|
392
|
+
status: "archived",
|
|
393
|
+
});
|
|
394
|
+
archived_ids.push(row.thread_id);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (archived_ids.length > 0) {
|
|
398
|
+
console.error(`[thread-supabase] Auto-archived ${archived_ids.length} dormant threads: ${archived_ids.join(", ")}`);
|
|
399
|
+
}
|
|
400
|
+
return { archived_count: archived_ids.length, archived_ids };
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.error("[thread-supabase] Failed to archive dormant threads:", error instanceof Error ? error.message : error);
|
|
404
|
+
return { archived_count: 0, archived_ids: [] };
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
// ---------- Embedding Queries (Phase 3) ----------
|
|
408
|
+
/**
|
|
409
|
+
* Parse embedding from Supabase REST API response.
|
|
410
|
+
* REST returns vector columns as JSON strings, not arrays.
|
|
411
|
+
*/
|
|
412
|
+
function parseEmbedding(raw) {
|
|
413
|
+
if (raw === null || raw === undefined)
|
|
414
|
+
return null;
|
|
415
|
+
if (Array.isArray(raw))
|
|
416
|
+
return raw;
|
|
417
|
+
if (typeof raw === "string") {
|
|
418
|
+
try {
|
|
419
|
+
const parsed = JSON.parse(raw);
|
|
420
|
+
if (Array.isArray(parsed))
|
|
421
|
+
return parsed;
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
// Invalid JSON
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Load open threads WITH embeddings from Supabase for dedup comparison.
|
|
431
|
+
* Uses the full orchestra_threads table (not _lite view) to include embedding column.
|
|
432
|
+
* Returns null if Supabase is unavailable.
|
|
433
|
+
*/
|
|
434
|
+
export async function loadOpenThreadEmbeddings(project = "orchestra_dev") {
|
|
435
|
+
if (!hasSupabase() || !supabase.isConfigured()) {
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
const rows = await supabase.directQuery("orchestra_threads", {
|
|
440
|
+
select: "thread_id,text,embedding",
|
|
441
|
+
filters: {
|
|
442
|
+
project,
|
|
443
|
+
status: "not.in.(resolved,archived)",
|
|
444
|
+
},
|
|
445
|
+
limit: 100,
|
|
446
|
+
});
|
|
447
|
+
console.error(`[thread-supabase] Loaded ${rows.length} thread embeddings for dedup`);
|
|
448
|
+
return rows.map((row) => ({
|
|
449
|
+
thread_id: row.thread_id,
|
|
450
|
+
text: row.text,
|
|
451
|
+
embedding: parseEmbedding(row.embedding),
|
|
452
|
+
}));
|
|
453
|
+
}
|
|
454
|
+
catch (error) {
|
|
455
|
+
console.error("[thread-supabase] Failed to load thread embeddings:", error instanceof Error ? error.message : error);
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
//# sourceMappingURL=thread-supabase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-supabase.js","sourceRoot":"","sources":["../../src/services/thread-supabase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thread Vitality Scoring (Phase 2) + Lifecycle State Machine (Phase 6)
|
|
3
|
+
*
|
|
4
|
+
* Computes vitality from recency + frequency (two of four eventual components).
|
|
5
|
+
* Importance and relevance deferred to Phases 3-4 (knowledge graph + per-session embeddings).
|
|
6
|
+
*
|
|
7
|
+
* Formula: vitality = W_recency * recency + W_frequency * frequency
|
|
8
|
+
*
|
|
9
|
+
* Phase 2 weights (renormalized from 4-component to 2-component):
|
|
10
|
+
* recency: 0.55 (original 0.30 / 0.55 total)
|
|
11
|
+
* frequency: 0.45 (original 0.25 / 0.55 total)
|
|
12
|
+
*
|
|
13
|
+
* Recency: exponential decay based on thread_class half-life
|
|
14
|
+
* operational: 3-day half-life (short-lived tasks)
|
|
15
|
+
* backlog: 21-day half-life (long-running concerns)
|
|
16
|
+
*
|
|
17
|
+
* Frequency: log-scaled touch count normalized against thread age
|
|
18
|
+
* log(touch_count + 1) / log(max(days_alive, 0.01) + 1)
|
|
19
|
+
*
|
|
20
|
+
* Status thresholds:
|
|
21
|
+
* vitality > 0.5 → "active"
|
|
22
|
+
* 0.2 <= v <= 0.5 → "cooling"
|
|
23
|
+
* vitality < 0.2 → "dormant"
|
|
24
|
+
*
|
|
25
|
+
* Phase 6 Lifecycle:
|
|
26
|
+
* EMERGING (< 24h old) → ACTIVE → COOLING → DORMANT → ARCHIVED (30+ days dormant)
|
|
27
|
+
* Any state → RESOLVED (explicit resolve)
|
|
28
|
+
*/
|
|
29
|
+
export type ThreadClass = "operational" | "backlog";
|
|
30
|
+
export type VitalityStatus = "emerging" | "active" | "cooling" | "dormant";
|
|
31
|
+
export interface VitalityInput {
|
|
32
|
+
last_touched_at: string;
|
|
33
|
+
touch_count: number;
|
|
34
|
+
created_at: string;
|
|
35
|
+
thread_class: ThreadClass;
|
|
36
|
+
}
|
|
37
|
+
export interface VitalityResult {
|
|
38
|
+
vitality_score: number;
|
|
39
|
+
status: VitalityStatus;
|
|
40
|
+
recency_component: number;
|
|
41
|
+
frequency_component: number;
|
|
42
|
+
}
|
|
43
|
+
export type LifecycleStatus = "emerging" | "active" | "cooling" | "dormant" | "archived";
|
|
44
|
+
export interface LifecycleInput extends VitalityInput {
|
|
45
|
+
current_status: string;
|
|
46
|
+
dormant_since?: string;
|
|
47
|
+
}
|
|
48
|
+
export declare const EMERGING_WINDOW_HOURS = 24;
|
|
49
|
+
export declare const ARCHIVAL_DORMANT_DAYS = 30;
|
|
50
|
+
export declare function computeVitality(input: VitalityInput, now?: Date): VitalityResult;
|
|
51
|
+
/**
|
|
52
|
+
* Compute the full lifecycle status for a thread.
|
|
53
|
+
* Wraps vitality scoring with age-based emerging window and archival logic.
|
|
54
|
+
*
|
|
55
|
+
* State machine:
|
|
56
|
+
* EMERGING (< 24h) → ACTIVE → COOLING → DORMANT → ARCHIVED (30+ days dormant)
|
|
57
|
+
* Any state → RESOLVED (handled externally by resolve_thread)
|
|
58
|
+
*/
|
|
59
|
+
export declare function computeLifecycleStatus(input: LifecycleInput, now?: Date): {
|
|
60
|
+
lifecycle_status: LifecycleStatus;
|
|
61
|
+
vitality: VitalityResult;
|
|
62
|
+
};
|
|
63
|
+
export declare function vitalityToStatus(score: number): VitalityStatus;
|
|
64
|
+
export declare function detectThreadClass(text: string): ThreadClass;
|
|
65
|
+
//# sourceMappingURL=thread-vitality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thread-vitality.d.ts","sourceRoot":"","sources":["../../src/services/thread-vitality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AACpD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAGD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEzF,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAoBD,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAUxC,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,IAAI,GAAG,cAAc,CA6BhF;AAID;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,EACrB,GAAG,CAAC,EAAE,IAAI,GACT;IAAE,gBAAgB,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAqCjE;AAyCD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAI9D;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAM3D"}
|