opencode-mem 2.1.1 → 2.3.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/README.md +60 -77
- package/dist/config.d.ts +1 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -86
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +0 -4
- package/dist/services/ai/providers/anthropic-messages.d.ts.map +1 -1
- package/dist/services/ai/providers/anthropic-messages.js +11 -17
- package/dist/services/ai/providers/openai-chat-completion.d.ts.map +1 -1
- package/dist/services/ai/providers/openai-chat-completion.js +11 -17
- package/dist/services/ai/providers/openai-responses.d.ts.map +1 -1
- package/dist/services/ai/providers/openai-responses.js +11 -17
- package/dist/services/api-handlers.d.ts +5 -3
- package/dist/services/api-handlers.d.ts.map +1 -1
- package/dist/services/api-handlers.js +165 -42
- package/dist/services/auto-capture.js +2 -2
- package/dist/services/context.d.ts +1 -1
- package/dist/services/context.d.ts.map +1 -1
- package/dist/services/context.js +1 -10
- package/dist/services/deduplication-service.d.ts.map +1 -1
- package/dist/services/deduplication-service.js +1 -3
- package/dist/services/logger.js +1 -1
- package/dist/services/user-memory-learning.d.ts +1 -1
- package/dist/services/user-memory-learning.d.ts.map +1 -1
- package/dist/services/user-memory-learning.js +5 -3
- package/dist/services/user-profile/user-profile-manager.d.ts.map +1 -1
- package/dist/services/web-server-worker.js +30 -3
- package/dist/web/app.js +254 -47
- package/dist/web/index.html +31 -15
- package/dist/web/styles.css +309 -0
- package/package.json +1 -1
package/dist/web/app.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
const API_BASE = "";
|
|
2
2
|
|
|
3
3
|
const state = {
|
|
4
|
-
tags: {
|
|
4
|
+
tags: { project: [] },
|
|
5
5
|
memories: [],
|
|
6
6
|
currentPage: 1,
|
|
7
7
|
pageSize: 20,
|
|
8
8
|
totalPages: 1,
|
|
9
9
|
totalItems: 0,
|
|
10
10
|
selectedTag: "",
|
|
11
|
-
|
|
11
|
+
currentView: "project",
|
|
12
12
|
searchQuery: "",
|
|
13
13
|
isSearching: false,
|
|
14
14
|
selectedMemories: new Set(),
|
|
15
15
|
autoRefreshInterval: null,
|
|
16
|
+
userProfile: null,
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
marked.setOptions({
|
|
@@ -53,7 +54,7 @@ function populateTagDropdowns() {
|
|
|
53
54
|
tagFilter.innerHTML = '<option value="">All Tags</option>';
|
|
54
55
|
addTag.innerHTML = '<option value="">Select tag</option>';
|
|
55
56
|
|
|
56
|
-
const scopeTags = state.
|
|
57
|
+
const scopeTags = state.tags.project;
|
|
57
58
|
|
|
58
59
|
scopeTags.forEach((tagInfo) => {
|
|
59
60
|
const displayText = tagInfo.displayName || tagInfo.tag;
|
|
@@ -75,7 +76,7 @@ function populateTagDropdowns() {
|
|
|
75
76
|
async function loadMemories() {
|
|
76
77
|
showRefreshIndicator(true);
|
|
77
78
|
|
|
78
|
-
let endpoint = `/api/memories?page=${state.currentPage}&pageSize=${state.pageSize}&
|
|
79
|
+
let endpoint = `/api/memories?page=${state.currentPage}&pageSize=${state.pageSize}&includePrompts=true`;
|
|
79
80
|
|
|
80
81
|
if (state.isSearching && state.searchQuery) {
|
|
81
82
|
endpoint = `/api/search?q=${encodeURIComponent(state.searchQuery)}&page=${state.currentPage}&pageSize=${state.pageSize}`;
|
|
@@ -143,7 +144,7 @@ function renderPromptCard(prompt) {
|
|
|
143
144
|
<input type="checkbox" class="memory-checkbox" data-id="${prompt.id}" ${isSelected ? "checked" : ""} />
|
|
144
145
|
<i data-lucide="message-circle" class="icon"></i>
|
|
145
146
|
<span class="badge badge-prompt">USER PROMPT</span>
|
|
146
|
-
${isLinked ? '<span class="badge badge-linked"
|
|
147
|
+
${isLinked ? '<span class="badge badge-linked"><i data-lucide="link" class="icon-sm"></i> LINKED</span>' : ""}
|
|
147
148
|
<span class="prompt-date">${promptDate}</span>
|
|
148
149
|
</div>
|
|
149
150
|
<div class="prompt-actions">
|
|
@@ -156,7 +157,7 @@ function renderPromptCard(prompt) {
|
|
|
156
157
|
<div class="prompt-content">
|
|
157
158
|
${escapeHtml(prompt.content)}
|
|
158
159
|
</div>
|
|
159
|
-
${isLinked ? '<div class="link-indicator"
|
|
160
|
+
${isLinked ? '<div class="link-indicator"><i data-lucide="arrow-down" class="icon-sm"></i> Generated memory above <i data-lucide="arrow-up" class="icon-sm"></i></div>' : ""}
|
|
160
161
|
</div>
|
|
161
162
|
`;
|
|
162
163
|
}
|
|
@@ -171,15 +172,13 @@ function renderMemoryCard(memory) {
|
|
|
171
172
|
: "";
|
|
172
173
|
|
|
173
174
|
let displayInfo = memory.displayName || memory.id;
|
|
174
|
-
if (memory.
|
|
175
|
+
if (memory.projectPath) {
|
|
175
176
|
const pathParts = memory.projectPath.split("/");
|
|
176
177
|
displayInfo = pathParts[pathParts.length - 1] || memory.projectPath;
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
let subtitle = "";
|
|
180
|
-
if (memory.
|
|
181
|
-
subtitle = `<span class="memory-subtitle">${escapeHtml(memory.userEmail)}</span>`;
|
|
182
|
-
} else if (memory.scope === "project" && memory.projectPath) {
|
|
181
|
+
if (memory.projectPath) {
|
|
183
182
|
subtitle = `<span class="memory-subtitle">${escapeHtml(memory.projectPath)}</span>`;
|
|
184
183
|
}
|
|
185
184
|
|
|
@@ -200,9 +199,8 @@ function renderMemoryCard(memory) {
|
|
|
200
199
|
<div class="memory-header">
|
|
201
200
|
<div class="meta">
|
|
202
201
|
<input type="checkbox" class="memory-checkbox" data-id="${memory.id}" ${isSelected ? "checked" : ""} />
|
|
203
|
-
<span class="badge badge-${memory.scope}">${memory.scope}</span>
|
|
204
202
|
${memory.memoryType ? `<span class="badge badge-type">${memory.memoryType}</span>` : ""}
|
|
205
|
-
${isLinked ? '<span class="badge badge-linked"
|
|
203
|
+
${isLinked ? '<span class="badge badge-linked"><i data-lucide="link" class="icon-sm"></i> LINKED</span>' : ""}
|
|
206
204
|
${similarityHtml}
|
|
207
205
|
${isPinned ? '<span class="badge badge-pinned">PINNED</span>' : ""}
|
|
208
206
|
<span class="memory-display-name">${escapeHtml(displayInfo)}</span>
|
|
@@ -218,7 +216,7 @@ function renderMemoryCard(memory) {
|
|
|
218
216
|
</div>
|
|
219
217
|
</div>
|
|
220
218
|
<div class="memory-content markdown-content">${renderMarkdown(memory.content)}</div>
|
|
221
|
-
${isLinked ? '<div class="link-indicator"
|
|
219
|
+
${isLinked ? '<div class="link-indicator"><i data-lucide="arrow-up" class="icon-sm"></i> From prompt below <i data-lucide="arrow-down" class="icon-sm"></i></div>' : ""}
|
|
222
220
|
<div class="memory-footer">
|
|
223
221
|
${dateInfo}
|
|
224
222
|
<span>ID: ${memory.id}</span>
|
|
@@ -278,10 +276,9 @@ function updatePagination() {
|
|
|
278
276
|
}
|
|
279
277
|
|
|
280
278
|
function updateSectionTitle() {
|
|
281
|
-
const scopeName = state.currentScope.toUpperCase();
|
|
282
279
|
const title = state.isSearching
|
|
283
280
|
? `└─ SEARCH RESULTS (${state.totalItems}) ──`
|
|
284
|
-
: `└─
|
|
281
|
+
: `└─ PROJECT MEMORIES (${state.totalItems}) ──`;
|
|
285
282
|
document.getElementById("section-title").textContent = title;
|
|
286
283
|
}
|
|
287
284
|
|
|
@@ -289,26 +286,9 @@ async function loadStats() {
|
|
|
289
286
|
const result = await fetchAPI("/api/stats");
|
|
290
287
|
if (result.success) {
|
|
291
288
|
document.getElementById("stats-total").textContent = `Total: ${result.data.total}`;
|
|
292
|
-
document.getElementById("stats-user").textContent = `User: ${result.data.byScope.user}`;
|
|
293
|
-
document.getElementById("stats-project").textContent =
|
|
294
|
-
`Project: ${result.data.byScope.project}`;
|
|
295
289
|
}
|
|
296
290
|
}
|
|
297
291
|
|
|
298
|
-
function switchScope(scope) {
|
|
299
|
-
state.currentScope = scope;
|
|
300
|
-
state.currentPage = 1;
|
|
301
|
-
state.selectedTag = "";
|
|
302
|
-
|
|
303
|
-
document.querySelectorAll(".tab-btn").forEach((btn) => {
|
|
304
|
-
btn.classList.remove("active");
|
|
305
|
-
});
|
|
306
|
-
document.getElementById(`tab-${scope}`).classList.add("active");
|
|
307
|
-
|
|
308
|
-
populateTagDropdowns();
|
|
309
|
-
loadMemories();
|
|
310
|
-
}
|
|
311
|
-
|
|
312
292
|
async function addMemory(e) {
|
|
313
293
|
e.preventDefault();
|
|
314
294
|
|
|
@@ -507,21 +487,18 @@ function changePage(delta) {
|
|
|
507
487
|
}
|
|
508
488
|
|
|
509
489
|
function handleAddScopeChange() {
|
|
510
|
-
const scope = document.getElementById("add-scope").value;
|
|
511
490
|
const tagDropdown = document.getElementById("add-tag");
|
|
512
491
|
|
|
513
492
|
tagDropdown.innerHTML = '<option value="">Select tag</option>';
|
|
514
493
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const tags = scope === "user" ? state.tags.user : state.tags.project;
|
|
494
|
+
const tags = state.tags.project;
|
|
518
495
|
tags.forEach((tagInfo) => {
|
|
519
496
|
const displayText = tagInfo.displayName || tagInfo.tag;
|
|
520
497
|
const shortDisplay =
|
|
521
498
|
displayText.length > 50 ? displayText.substring(0, 50) + "..." : displayText;
|
|
522
499
|
const option = document.createElement("option");
|
|
523
500
|
option.value = tagInfo.tag;
|
|
524
|
-
option.textContent =
|
|
501
|
+
option.textContent = shortDisplay;
|
|
525
502
|
tagDropdown.appendChild(option);
|
|
526
503
|
});
|
|
527
504
|
}
|
|
@@ -551,12 +528,6 @@ function showRefreshIndicator(show) {
|
|
|
551
528
|
}
|
|
552
529
|
}
|
|
553
530
|
|
|
554
|
-
function escapeHtml(text) {
|
|
555
|
-
const div = document.createElement("div");
|
|
556
|
-
div.textContent = text;
|
|
557
|
-
return div.innerHTML;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
531
|
function formatDate(isoString) {
|
|
561
532
|
const date = new Date(isoString);
|
|
562
533
|
return date.toLocaleString("en-US", {
|
|
@@ -722,9 +693,247 @@ async function runMigration(strategy) {
|
|
|
722
693
|
}
|
|
723
694
|
}
|
|
724
695
|
|
|
696
|
+
async function loadUserProfile() {
|
|
697
|
+
const result = await fetchAPI("/api/user-profile");
|
|
698
|
+
if (result.success) {
|
|
699
|
+
state.userProfile = result.data;
|
|
700
|
+
renderUserProfile();
|
|
701
|
+
} else {
|
|
702
|
+
showError(result.error || "Failed to load profile");
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function renderUserProfile() {
|
|
707
|
+
const container = document.getElementById("profile-content");
|
|
708
|
+
const profile = state.userProfile;
|
|
709
|
+
|
|
710
|
+
if (!profile.exists) {
|
|
711
|
+
container.innerHTML = `
|
|
712
|
+
<div class="empty-state">
|
|
713
|
+
<i data-lucide="user-x" class="icon-large"></i>
|
|
714
|
+
<p>${profile.message}</p>
|
|
715
|
+
</div>
|
|
716
|
+
`;
|
|
717
|
+
lucide.createIcons();
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
const data = profile.profileData;
|
|
722
|
+
const preferences = data.preferences || [];
|
|
723
|
+
const patterns = data.patterns || [];
|
|
724
|
+
const workflows = data.workflows || [];
|
|
725
|
+
const skillLevel = data.skillLevel || {};
|
|
726
|
+
|
|
727
|
+
container.innerHTML = `
|
|
728
|
+
<div class="profile-header">
|
|
729
|
+
<div class="profile-info">
|
|
730
|
+
<h3>${profile.displayName || profile.userId}</h3>
|
|
731
|
+
<p class="profile-meta">
|
|
732
|
+
<span>Version: ${profile.version}</span>
|
|
733
|
+
<span class="separator">|</span>
|
|
734
|
+
<span>Analyzed: ${profile.totalPromptsAnalyzed} prompts</span>
|
|
735
|
+
<span class="separator">|</span>
|
|
736
|
+
<span>Updated: ${formatDate(profile.lastAnalyzedAt)}</span>
|
|
737
|
+
</p>
|
|
738
|
+
</div>
|
|
739
|
+
<button id="view-changelog-btn" class="btn-secondary">
|
|
740
|
+
<i data-lucide="history" class="icon"></i> Version History
|
|
741
|
+
</button>
|
|
742
|
+
</div>
|
|
743
|
+
|
|
744
|
+
<div class="profile-section">
|
|
745
|
+
<h4><i data-lucide="heart" class="icon"></i> Preferences (${preferences.length})</h4>
|
|
746
|
+
${
|
|
747
|
+
preferences.length === 0
|
|
748
|
+
? '<p class="empty-text">No preferences learned yet</p>'
|
|
749
|
+
: `
|
|
750
|
+
<div class="preferences-list">
|
|
751
|
+
${preferences
|
|
752
|
+
.map(
|
|
753
|
+
(p) => `
|
|
754
|
+
<div class="preference-item">
|
|
755
|
+
<div class="preference-header">
|
|
756
|
+
<span class="preference-name">${escapeHtml(p.description)}</span>
|
|
757
|
+
<span class="confidence-badge">${Math.round(p.confidence * 100)}%</span>
|
|
758
|
+
</div>
|
|
759
|
+
<div class="confidence-bar">
|
|
760
|
+
<div class="confidence-fill" style="width: ${p.confidence * 100}%"></div>
|
|
761
|
+
</div>
|
|
762
|
+
<p class="preference-evidence">${escapeHtml(Array.isArray(p.evidence) ? p.evidence.join(", ") : p.evidence)}</p>
|
|
763
|
+
<p class="preference-meta">Category: ${escapeHtml(p.category)}</p>
|
|
764
|
+
</div>
|
|
765
|
+
`
|
|
766
|
+
)
|
|
767
|
+
.join("")}
|
|
768
|
+
</div>
|
|
769
|
+
`
|
|
770
|
+
}
|
|
771
|
+
</div>
|
|
772
|
+
|
|
773
|
+
<div class="profile-section">
|
|
774
|
+
<h4><i data-lucide="activity" class="icon"></i> Patterns (${patterns.length})</h4>
|
|
775
|
+
${
|
|
776
|
+
patterns.length === 0
|
|
777
|
+
? '<p class="empty-text">No patterns detected yet</p>'
|
|
778
|
+
: `
|
|
779
|
+
<div class="patterns-list">
|
|
780
|
+
${patterns
|
|
781
|
+
.map(
|
|
782
|
+
(p) => `
|
|
783
|
+
<div class="pattern-item">
|
|
784
|
+
<div class="pattern-header">
|
|
785
|
+
<span class="pattern-name">${escapeHtml(p.description)}</span>
|
|
786
|
+
<span class="category-badge">${escapeHtml(p.category)}</span>
|
|
787
|
+
</div>
|
|
788
|
+
</div>
|
|
789
|
+
`
|
|
790
|
+
)
|
|
791
|
+
.join("")}
|
|
792
|
+
</div>
|
|
793
|
+
`
|
|
794
|
+
}
|
|
795
|
+
</div>
|
|
796
|
+
|
|
797
|
+
<div class="profile-section">
|
|
798
|
+
<h4><i data-lucide="workflow" class="icon"></i> Workflows (${workflows.length})</h4>
|
|
799
|
+
${
|
|
800
|
+
workflows.length === 0
|
|
801
|
+
? '<p class="empty-text">No workflows identified yet</p>'
|
|
802
|
+
: `
|
|
803
|
+
<div class="workflows-list">
|
|
804
|
+
${workflows
|
|
805
|
+
.map(
|
|
806
|
+
(w) => `
|
|
807
|
+
<div class="workflow-item">
|
|
808
|
+
<div class="workflow-header">
|
|
809
|
+
<span class="workflow-name">${escapeHtml(w.description)}</span>
|
|
810
|
+
</div>
|
|
811
|
+
<div class="workflow-steps">
|
|
812
|
+
${w.steps
|
|
813
|
+
.map(
|
|
814
|
+
(step) => `
|
|
815
|
+
<div class="workflow-step">
|
|
816
|
+
<span class="step-text">${escapeHtml(step)}</span>
|
|
817
|
+
</div>
|
|
818
|
+
`
|
|
819
|
+
)
|
|
820
|
+
.join("")}
|
|
821
|
+
</div>
|
|
822
|
+
</div>
|
|
823
|
+
`
|
|
824
|
+
)
|
|
825
|
+
.join("")}
|
|
826
|
+
</div>
|
|
827
|
+
`
|
|
828
|
+
}
|
|
829
|
+
</div>
|
|
830
|
+
|
|
831
|
+
<div class="profile-section">
|
|
832
|
+
<h4><i data-lucide="award" class="icon"></i> Skill Level</h4>
|
|
833
|
+
<div class="skill-level">
|
|
834
|
+
<div class="skill-item">
|
|
835
|
+
<span class="skill-label">Overall</span>
|
|
836
|
+
<span class="skill-value">${escapeHtml(skillLevel.overall || "unknown")}</span>
|
|
837
|
+
</div>
|
|
838
|
+
${Object.entries(skillLevel.domains || {})
|
|
839
|
+
.map(
|
|
840
|
+
([domain, level]) => `
|
|
841
|
+
<div class="skill-item">
|
|
842
|
+
<span class="skill-label">${escapeHtml(domain)}</span>
|
|
843
|
+
<span class="skill-value">${escapeHtml(level)}</span>
|
|
844
|
+
</div>
|
|
845
|
+
`
|
|
846
|
+
)
|
|
847
|
+
.join("")}
|
|
848
|
+
</div>
|
|
849
|
+
</div>
|
|
850
|
+
`;
|
|
851
|
+
|
|
852
|
+
document.getElementById("view-changelog-btn")?.addEventListener("click", showChangelog);
|
|
853
|
+
lucide.createIcons();
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
async function showChangelog() {
|
|
857
|
+
const modal = document.getElementById("changelog-modal");
|
|
858
|
+
const list = document.getElementById("changelog-list");
|
|
859
|
+
|
|
860
|
+
modal.classList.remove("hidden");
|
|
861
|
+
list.innerHTML = '<div class="loading">Loading changelog...</div>';
|
|
862
|
+
|
|
863
|
+
const result = await fetchAPI(
|
|
864
|
+
`/api/user-profile/changelog?profileId=${state.userProfile.id}&limit=10`
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
if (result.success && result.data.length > 0) {
|
|
868
|
+
list.innerHTML = result.data
|
|
869
|
+
.map(
|
|
870
|
+
(c) => `
|
|
871
|
+
<div class="changelog-item">
|
|
872
|
+
<div class="changelog-header">
|
|
873
|
+
<span class="changelog-version">v${c.version}</span>
|
|
874
|
+
<span class="changelog-type">${c.changeType}</span>
|
|
875
|
+
<span class="changelog-date">${formatDate(c.createdAt)}</span>
|
|
876
|
+
</div>
|
|
877
|
+
<p class="changelog-summary">${escapeHtml(c.changeSummary)}</p>
|
|
878
|
+
</div>
|
|
879
|
+
`
|
|
880
|
+
)
|
|
881
|
+
.join("");
|
|
882
|
+
} else {
|
|
883
|
+
list.innerHTML = '<div class="empty-state">No changelog available</div>';
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
async function refreshProfile() {
|
|
888
|
+
showToast("Refreshing profile...", "info");
|
|
889
|
+
const result = await fetchAPI("/api/user-profile/refresh", {
|
|
890
|
+
method: "POST",
|
|
891
|
+
headers: { "Content-Type": "application/json" },
|
|
892
|
+
body: JSON.stringify({}),
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
if (result.success) {
|
|
896
|
+
showToast(result.data.message, "success");
|
|
897
|
+
await loadUserProfile();
|
|
898
|
+
} else {
|
|
899
|
+
showToast(result.error || "Failed to refresh profile", "error");
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
function switchView(view) {
|
|
904
|
+
state.currentView = view;
|
|
905
|
+
|
|
906
|
+
document.querySelectorAll(".tab-btn").forEach((btn) => btn.classList.remove("active"));
|
|
907
|
+
|
|
908
|
+
if (view === "project") {
|
|
909
|
+
document.getElementById("tab-project").classList.add("active");
|
|
910
|
+
document.getElementById("project-section").classList.remove("hidden");
|
|
911
|
+
document.getElementById("profile-section").classList.add("hidden");
|
|
912
|
+
document.querySelector(".controls").classList.remove("hidden");
|
|
913
|
+
document.querySelector(".add-section").classList.remove("hidden");
|
|
914
|
+
} else if (view === "profile") {
|
|
915
|
+
document.getElementById("tab-profile").classList.add("active");
|
|
916
|
+
document.getElementById("project-section").classList.add("hidden");
|
|
917
|
+
document.getElementById("profile-section").classList.remove("hidden");
|
|
918
|
+
document.querySelector(".controls").classList.add("hidden");
|
|
919
|
+
document.querySelector(".add-section").classList.add("hidden");
|
|
920
|
+
loadUserProfile();
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function escapeHtml(text) {
|
|
925
|
+
const div = document.createElement("div");
|
|
926
|
+
div.textContent = text;
|
|
927
|
+
return div.innerHTML;
|
|
928
|
+
}
|
|
929
|
+
|
|
725
930
|
document.addEventListener("DOMContentLoaded", async () => {
|
|
726
|
-
document.getElementById("tab-project").addEventListener("click", () =>
|
|
727
|
-
document.getElementById("tab-
|
|
931
|
+
document.getElementById("tab-project").addEventListener("click", () => switchView("project"));
|
|
932
|
+
document.getElementById("tab-profile").addEventListener("click", () => switchView("profile"));
|
|
933
|
+
document.getElementById("refresh-profile-btn")?.addEventListener("click", refreshProfile);
|
|
934
|
+
document.getElementById("changelog-close")?.addEventListener("click", () => {
|
|
935
|
+
document.getElementById("changelog-modal").classList.add("hidden");
|
|
936
|
+
});
|
|
728
937
|
|
|
729
938
|
document.getElementById("tag-filter").addEventListener("change", () => {
|
|
730
939
|
state.selectedTag = document.getElementById("tag-filter").value;
|
|
@@ -732,8 +941,6 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
732
941
|
loadMemories();
|
|
733
942
|
});
|
|
734
943
|
|
|
735
|
-
document.getElementById("add-scope").addEventListener("change", handleAddScopeChange);
|
|
736
|
-
|
|
737
944
|
document.getElementById("search-btn").addEventListener("click", performSearch);
|
|
738
945
|
document.getElementById("clear-search-btn").addEventListener("click", clearSearch);
|
|
739
946
|
document.getElementById("search-input").addEventListener("keypress", (e) => {
|
package/dist/web/index.html
CHANGED
|
@@ -27,8 +27,6 @@
|
|
|
27
27
|
</div>
|
|
28
28
|
<div class="stats-bar">
|
|
29
29
|
<span id="stats-total">Total: 0</span>
|
|
30
|
-
<span id="stats-user">User: 0</span>
|
|
31
|
-
<span id="stats-project">Project: 0</span>
|
|
32
30
|
<span id="refresh-indicator" class="hidden"
|
|
33
31
|
><i data-lucide="rotate-cw" class="icon icon-spin"></i
|
|
34
32
|
></span>
|
|
@@ -38,11 +36,11 @@
|
|
|
38
36
|
<div class="scope-tabs">
|
|
39
37
|
<button id="tab-project" class="tab-btn active">
|
|
40
38
|
<i data-lucide="folder" class="icon"></i>
|
|
41
|
-
PROJECT
|
|
39
|
+
PROJECT MEMORIES
|
|
42
40
|
</button>
|
|
43
|
-
<button id="tab-
|
|
41
|
+
<button id="tab-profile" class="tab-btn">
|
|
44
42
|
<i data-lucide="user" class="icon"></i>
|
|
45
|
-
USER
|
|
43
|
+
USER PROFILE
|
|
46
44
|
</button>
|
|
47
45
|
</div>
|
|
48
46
|
|
|
@@ -99,7 +97,7 @@
|
|
|
99
97
|
</div>
|
|
100
98
|
</div>
|
|
101
99
|
|
|
102
|
-
<div class="memories-section">
|
|
100
|
+
<div class="memories-section" id="project-section">
|
|
103
101
|
<div class="section-header">
|
|
104
102
|
<h2 id="section-title">└─ PROJECT MEMORIES (0) ──</h2>
|
|
105
103
|
<div class="pagination" id="pagination-top">
|
|
@@ -128,19 +126,23 @@
|
|
|
128
126
|
</div>
|
|
129
127
|
</div>
|
|
130
128
|
|
|
129
|
+
<div class="profile-section hidden" id="profile-section">
|
|
130
|
+
<div class="section-header">
|
|
131
|
+
<h2>└─ USER PROFILE ──</h2>
|
|
132
|
+
<button id="refresh-profile-btn" class="btn-secondary">
|
|
133
|
+
<i data-lucide="refresh-cw" class="icon"></i> Refresh
|
|
134
|
+
</button>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<div id="profile-content" class="profile-content">
|
|
138
|
+
<div class="loading">Loading profile...</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
131
142
|
<div class="add-section">
|
|
132
143
|
<h2>└─ ADD NEW MEMORY ──</h2>
|
|
133
144
|
<form id="add-form">
|
|
134
145
|
<div class="form-row">
|
|
135
|
-
<div class="form-group">
|
|
136
|
-
<label>Scope:</label>
|
|
137
|
-
<select id="add-scope" required>
|
|
138
|
-
<option value="">Select scope</option>
|
|
139
|
-
<option value="user">User</option>
|
|
140
|
-
<option value="project">Project</option>
|
|
141
|
-
</select>
|
|
142
|
-
</div>
|
|
143
|
-
|
|
144
146
|
<div class="form-group">
|
|
145
147
|
<label>Tag:</label>
|
|
146
148
|
<select id="add-tag" required>
|
|
@@ -201,6 +203,20 @@
|
|
|
201
203
|
|
|
202
204
|
<div id="toast" class="toast hidden"></div>
|
|
203
205
|
|
|
206
|
+
<div id="changelog-modal" class="modal hidden">
|
|
207
|
+
<div class="modal-content">
|
|
208
|
+
<div class="modal-header">
|
|
209
|
+
<h3>Profile Version History</h3>
|
|
210
|
+
<button class="modal-close" id="changelog-close">
|
|
211
|
+
<i data-lucide="x" class="icon"></i>
|
|
212
|
+
</button>
|
|
213
|
+
</div>
|
|
214
|
+
<div id="changelog-list" class="changelog-list">
|
|
215
|
+
<div class="loading">Loading changelog...</div>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
204
220
|
<script src="/app.js"></script>
|
|
205
221
|
</body>
|
|
206
222
|
</html>
|