laminark 0.1.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.
Files changed (55) hide show
  1. package/README.md +147 -0
  2. package/package.json +65 -0
  3. package/plugin/.claude-plugin/plugin.json +13 -0
  4. package/plugin/.mcp.json +12 -0
  5. package/plugin/CLAUDE.md +10 -0
  6. package/plugin/commands/recall.md +55 -0
  7. package/plugin/commands/remember.md +34 -0
  8. package/plugin/commands/resume.md +45 -0
  9. package/plugin/commands/stash.md +34 -0
  10. package/plugin/commands/status.md +33 -0
  11. package/plugin/dist/analysis/worker.d.ts +1 -0
  12. package/plugin/dist/analysis/worker.js +233 -0
  13. package/plugin/dist/analysis/worker.js.map +1 -0
  14. package/plugin/dist/config-t8LZeB-u.mjs +90 -0
  15. package/plugin/dist/config-t8LZeB-u.mjs.map +1 -0
  16. package/plugin/dist/hooks/handler.d.ts +286 -0
  17. package/plugin/dist/hooks/handler.d.ts.map +1 -0
  18. package/plugin/dist/hooks/handler.js +2413 -0
  19. package/plugin/dist/hooks/handler.js.map +1 -0
  20. package/plugin/dist/index.d.ts +447 -0
  21. package/plugin/dist/index.d.ts.map +1 -0
  22. package/plugin/dist/index.js +7334 -0
  23. package/plugin/dist/index.js.map +1 -0
  24. package/plugin/dist/observations-CorAAc1A.d.mts +192 -0
  25. package/plugin/dist/observations-CorAAc1A.d.mts.map +1 -0
  26. package/plugin/dist/tool-registry-e710BvXq.mjs +3574 -0
  27. package/plugin/dist/tool-registry-e710BvXq.mjs.map +1 -0
  28. package/plugin/hooks/hooks.json +78 -0
  29. package/plugin/laminark.db +0 -0
  30. package/plugin/package.json +17 -0
  31. package/plugin/scripts/README.md +65 -0
  32. package/plugin/scripts/bump-version.sh +42 -0
  33. package/plugin/scripts/dev-sync.sh +58 -0
  34. package/plugin/scripts/ensure-deps.sh +15 -0
  35. package/plugin/scripts/install.sh +139 -0
  36. package/plugin/scripts/local-install.sh +138 -0
  37. package/plugin/scripts/uninstall.sh +133 -0
  38. package/plugin/scripts/update.sh +39 -0
  39. package/plugin/scripts/verify-install.sh +87 -0
  40. package/plugin/skills/status/SKILL.md +6 -0
  41. package/plugin/ui/activity.js +197 -0
  42. package/plugin/ui/app.js +1612 -0
  43. package/plugin/ui/graph.js +2560 -0
  44. package/plugin/ui/help/activity-feed.png +0 -0
  45. package/plugin/ui/help/analysis-panel.png +0 -0
  46. package/plugin/ui/help/graph-toolbar.png +0 -0
  47. package/plugin/ui/help/graph-view.png +0 -0
  48. package/plugin/ui/help/settings.png +0 -0
  49. package/plugin/ui/help/timeline.png +0 -0
  50. package/plugin/ui/help.js +932 -0
  51. package/plugin/ui/index.html +756 -0
  52. package/plugin/ui/settings.js +1414 -0
  53. package/plugin/ui/styles.css +3856 -0
  54. package/plugin/ui/timeline.js +652 -0
  55. package/plugin/ui/tools.js +826 -0
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+ # Update Laminark to the latest version via npm
3
+
4
+ set -e
5
+
6
+ echo "Laminark Updater"
7
+ echo "================"
8
+ echo ""
9
+
10
+ # Check if npm is available
11
+ if ! command -v npm &> /dev/null; then
12
+ echo "Error: npm not found"
13
+ exit 1
14
+ fi
15
+
16
+ # Check if installed
17
+ CURRENT_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "")
18
+ if [ -z "$CURRENT_VERSION" ]; then
19
+ echo "Laminark is not installed globally."
20
+ echo "Run: ./plugin/scripts/install.sh"
21
+ exit 1
22
+ fi
23
+
24
+ echo "Currently installed: v$CURRENT_VERSION"
25
+ echo ""
26
+ echo "Updating..."
27
+ npm update -g laminark
28
+
29
+ NEW_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "unknown")
30
+ echo ""
31
+ if [ "$CURRENT_VERSION" = "$NEW_VERSION" ]; then
32
+ echo "✓ Already at latest version: v$NEW_VERSION"
33
+ else
34
+ echo "✓ Updated: v$CURRENT_VERSION → v$NEW_VERSION"
35
+ fi
36
+ echo ""
37
+ echo "Restart your Claude Code session for changes to take effect."
38
+
39
+ exit 0
@@ -0,0 +1,87 @@
1
+ #!/bin/bash
2
+ # Verify Laminark installation
3
+ # Checks: npm global package, MCP server, hooks in settings.json
4
+
5
+ set -e
6
+
7
+ echo "Checking Laminark installation..."
8
+ echo ""
9
+
10
+ ERRORS=0
11
+
12
+ # Check 1: npm global package
13
+ NPM_VERSION=$(npm list -g laminark --depth=0 2>/dev/null | grep laminark@ | sed 's/.*@//' || echo "")
14
+ if [ -n "$NPM_VERSION" ]; then
15
+ echo "✓ npm package: v$NPM_VERSION"
16
+ else
17
+ # Check for npm link (dev install)
18
+ if command -v laminark-server &> /dev/null; then
19
+ echo "✓ laminark-server on PATH (linked)"
20
+ else
21
+ echo "✗ npm package not installed"
22
+ ERRORS=$((ERRORS + 1))
23
+ fi
24
+ fi
25
+
26
+ # Check 2: laminark-server binary
27
+ if command -v laminark-server &> /dev/null; then
28
+ echo "✓ laminark-server binary available"
29
+ else
30
+ echo "✗ laminark-server not found on PATH"
31
+ ERRORS=$((ERRORS + 1))
32
+ fi
33
+
34
+ # Check 3: laminark-hook binary
35
+ if command -v laminark-hook &> /dev/null; then
36
+ echo "✓ laminark-hook binary available"
37
+ else
38
+ echo "⚠ laminark-hook not on PATH (hooks may use direct node path)"
39
+ fi
40
+
41
+ # Check 4: Claude CLI
42
+ if ! command -v claude &> /dev/null; then
43
+ echo "✗ claude CLI not found"
44
+ ERRORS=$((ERRORS + 1))
45
+ else
46
+ # Check 5: MCP server registration
47
+ if claude mcp list 2>/dev/null | grep -q "laminark"; then
48
+ echo "✓ MCP server registered"
49
+ else
50
+ echo "✗ MCP server not registered"
51
+ echo " Run: claude mcp add-json laminark '{\"command\":\"laminark-server\"}' -s user"
52
+ ERRORS=$((ERRORS + 1))
53
+ fi
54
+ fi
55
+
56
+ # Check 6: Hooks in settings.json
57
+ SETTINGS_FILE="${CLAUDE_HOME:-$HOME/.claude}/settings.json"
58
+ if [ -f "$SETTINGS_FILE" ]; then
59
+ if grep -q "laminark" "$SETTINGS_FILE"; then
60
+ echo "✓ Hooks configured in settings.json"
61
+ else
62
+ echo "✗ No laminark hooks in settings.json"
63
+ ERRORS=$((ERRORS + 1))
64
+ fi
65
+ else
66
+ echo "✗ Settings file not found: $SETTINGS_FILE"
67
+ ERRORS=$((ERRORS + 1))
68
+ fi
69
+
70
+ # Check 7: Data directory
71
+ DATA_DIR="$HOME/.laminark"
72
+ if [ -d "$DATA_DIR" ]; then
73
+ echo "✓ Data directory exists: $DATA_DIR"
74
+ else
75
+ echo "⚠ Data directory not yet created (will be created on first use)"
76
+ fi
77
+
78
+ echo ""
79
+ if [ $ERRORS -eq 0 ]; then
80
+ echo "Installation verified successfully!"
81
+ echo ""
82
+ echo "Start a new Claude Code session to use Laminark."
83
+ else
84
+ echo "Found $ERRORS issue(s). Run ./plugin/scripts/install.sh to fix."
85
+ fi
86
+
87
+ exit $ERRORS
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: status
3
+ description: Show Laminark system status — connection info, memory count, token stats, and capabilities
4
+ ---
5
+
6
+ Call the `mcp__plugin_laminark_laminark__status` tool with no arguments and display the result to the user.
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Laminark Activity Feed Module
3
+ *
4
+ * Listens to SSE-dispatched CustomEvents and renders a live activity feed.
5
+ * Max 100 items in memory, newest first. Supports clear and slide-in animation.
6
+ */
7
+
8
+ (function () {
9
+ var MAX_ITEMS = 100;
10
+ var items = [];
11
+ var feedEl = null;
12
+
13
+ var EVENT_CONFIG = {
14
+ 'laminark:new_observation': {
15
+ icon: '\u{1F4DD}',
16
+ label: 'Observation',
17
+ cssClass: 'activity-observation',
18
+ format: function (d) {
19
+ return d.text || (d.id ? 'Observation ' + d.id.substring(0, 8) : 'New observation');
20
+ },
21
+ },
22
+ 'laminark:entity_updated': {
23
+ icon: '\u{1F9E9}',
24
+ label: 'Entity',
25
+ cssClass: 'activity-entity',
26
+ format: function (d) {
27
+ return (d.label || d.name || d.id || 'Unknown') + (d.type ? ' (' + d.type + ')' : '');
28
+ },
29
+ },
30
+ 'laminark:topic_shift': {
31
+ icon: '\u{1F500}',
32
+ label: 'Topic Shift',
33
+ cssClass: 'activity-topic-shift',
34
+ format: function (d) {
35
+ var msg = 'Topic shift detected';
36
+ if (d.confidence != null) msg += ' (' + (d.confidence * 100).toFixed(0) + '% confidence)';
37
+ return msg;
38
+ },
39
+ },
40
+ 'laminark:session_start': {
41
+ icon: '\u{25B6}\uFE0F',
42
+ label: 'Session Start',
43
+ cssClass: 'activity-session-start',
44
+ format: function (d) {
45
+ return 'Session started' + (d.id ? ': ' + d.id.substring(0, 8) : '');
46
+ },
47
+ },
48
+ 'laminark:session_end': {
49
+ icon: '\u{23F9}\uFE0F',
50
+ label: 'Session End',
51
+ cssClass: 'activity-session-end',
52
+ format: function (d) {
53
+ return 'Session ended' + (d.id ? ': ' + d.id.substring(0, 8) : '');
54
+ },
55
+ },
56
+ };
57
+
58
+ function relativeTime(isoString) {
59
+ if (!isoString) return 'just now';
60
+ try {
61
+ var diff = Date.now() - new Date(isoString).getTime();
62
+ if (diff < 0) diff = 0;
63
+ var secs = Math.floor(diff / 1000);
64
+ if (secs < 60) return secs + 's ago';
65
+ var mins = Math.floor(secs / 60);
66
+ if (mins < 60) return mins + 'm ago';
67
+ var hrs = Math.floor(mins / 60);
68
+ if (hrs < 24) return hrs + 'h ago';
69
+ return Math.floor(hrs / 24) + 'd ago';
70
+ } catch (_e) {
71
+ return 'just now';
72
+ }
73
+ }
74
+
75
+ function createItemEl(item) {
76
+ var el = document.createElement('div');
77
+ el.className = 'activity-item ' + item.cssClass + ' activity-slide-in';
78
+
79
+ var iconSpan = document.createElement('span');
80
+ iconSpan.className = 'activity-icon';
81
+ iconSpan.textContent = item.icon;
82
+ el.appendChild(iconSpan);
83
+
84
+ var body = document.createElement('div');
85
+ body.className = 'activity-body';
86
+
87
+ var title = document.createElement('div');
88
+ title.className = 'activity-title';
89
+ title.textContent = item.label;
90
+ body.appendChild(title);
91
+
92
+ var desc = document.createElement('div');
93
+ desc.className = 'activity-desc';
94
+ desc.textContent = item.description;
95
+ body.appendChild(desc);
96
+
97
+ el.appendChild(body);
98
+
99
+ var time = document.createElement('span');
100
+ time.className = 'activity-time';
101
+ time.textContent = relativeTime(item.timestamp);
102
+ el.appendChild(time);
103
+
104
+ return el;
105
+ }
106
+
107
+ function renderFeed() {
108
+ if (!feedEl) return;
109
+
110
+ if (items.length === 0) {
111
+ feedEl.innerHTML = '<p class="empty-state">Waiting for live events...</p>';
112
+ return;
113
+ }
114
+
115
+ feedEl.innerHTML = '';
116
+ items.forEach(function (item) {
117
+ feedEl.appendChild(createItemEl(item));
118
+ });
119
+ }
120
+
121
+ function addItem(eventName, detail) {
122
+ var config = EVENT_CONFIG[eventName];
123
+ if (!config) return;
124
+
125
+ // Filter out events from other projects
126
+ if (detail.projectHash && window.laminarkState && window.laminarkState.currentProject &&
127
+ detail.projectHash !== window.laminarkState.currentProject) {
128
+ return;
129
+ }
130
+
131
+ var item = {
132
+ icon: config.icon,
133
+ label: config.label,
134
+ cssClass: config.cssClass,
135
+ description: config.format(detail || {}),
136
+ timestamp: detail.createdAt || detail.timestamp || new Date().toISOString(),
137
+ };
138
+
139
+ items.unshift(item);
140
+ if (items.length > MAX_ITEMS) {
141
+ items = items.slice(0, MAX_ITEMS);
142
+ }
143
+
144
+ // If feed is visible, prepend DOM element directly for performance
145
+ if (feedEl) {
146
+ // Remove empty state if present
147
+ var empty = feedEl.querySelector('.empty-state');
148
+ if (empty) empty.remove();
149
+
150
+ var el = createItemEl(item);
151
+ if (feedEl.firstChild) {
152
+ feedEl.insertBefore(el, feedEl.firstChild);
153
+ } else {
154
+ feedEl.appendChild(el);
155
+ }
156
+
157
+ // Trim excess DOM nodes
158
+ while (feedEl.children.length > MAX_ITEMS) {
159
+ feedEl.removeChild(feedEl.lastChild);
160
+ }
161
+ }
162
+ }
163
+
164
+ function clearFeed() {
165
+ items = [];
166
+ renderFeed();
167
+ }
168
+
169
+ function initActivityFeed() {
170
+ feedEl = document.getElementById('activity-feed');
171
+
172
+ var clearBtn = document.getElementById('activity-clear-btn');
173
+ if (clearBtn) {
174
+ clearBtn.addEventListener('click', clearFeed);
175
+ }
176
+
177
+ // Listen to all SSE event types
178
+ Object.keys(EVENT_CONFIG).forEach(function (eventName) {
179
+ document.addEventListener(eventName, function (e) {
180
+ addItem(eventName, e.detail || {});
181
+ });
182
+ });
183
+
184
+ // Clear feed when project changes
185
+ var projectSelect = document.getElementById('project-selector');
186
+ if (projectSelect) {
187
+ projectSelect.addEventListener('change', clearFeed);
188
+ }
189
+
190
+ renderFeed();
191
+ }
192
+
193
+ window.laminarkActivity = {
194
+ initActivityFeed: initActivityFeed,
195
+ clearFeed: clearFeed,
196
+ };
197
+ })();