kimi-code-memory-mcp-server 0.1.2 → 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.
@@ -0,0 +1,94 @@
1
+ import { state, LS_KEY_COLLAPSED } from '../state.js';
2
+
3
+ const $ = (sel) => document.querySelector(sel);
4
+
5
+ export function formatDate(iso) {
6
+ if (!iso) return '–';
7
+ const d = new Date(iso);
8
+ return isNaN(d.getTime()) ? iso : d.toLocaleString();
9
+ }
10
+
11
+ export function escapeHtml(str) {
12
+ return String(str)
13
+ .replace(/&/g, '&')
14
+ .replace(/</g, '&lt;')
15
+ .replace(/>/g, '&gt;')
16
+ .replace(/"/g, '&quot;');
17
+ }
18
+
19
+ export function iconKimiMemory() {
20
+ return `<svg class="brand-icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>`;
21
+ }
22
+
23
+ export function iconPanelLeftClose() {
24
+ return `<svg class="toggle-icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 9l-3 3 3 3"/><line x1="14" y1="4" x2="14" y2="20"/></svg>`;
25
+ }
26
+
27
+ export function iconPanelLeftOpen() {
28
+ return `<svg class="toggle-icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 9l3 3-3 3"/><line x1="14" y1="4" x2="14" y2="20"/></svg>`;
29
+ }
30
+
31
+ export function setStatus(el, message, type = 'success') {
32
+ if (!el) return;
33
+ el.textContent = message;
34
+ el.className = `composer-status ${type}`.trim();
35
+ if (message) {
36
+ setTimeout(() => {
37
+ el.textContent = '';
38
+ el.className = 'composer-status';
39
+ }, 3000);
40
+ }
41
+ }
42
+
43
+ export function getInitialCollapsed() {
44
+ const saved = localStorage.getItem(LS_KEY_COLLAPSED);
45
+ if (saved !== null) return saved === 'true';
46
+ return window.innerWidth < 768;
47
+ }
48
+
49
+ export function updateCollapsedClass() {
50
+ $('#app').classList.toggle('sidebar-collapsed', state.sidebarCollapsed);
51
+ }
52
+
53
+ export function toggleSidebar() {
54
+ state.sidebarCollapsed = !state.sidebarCollapsed;
55
+ localStorage.setItem(LS_KEY_COLLAPSED, String(state.sidebarCollapsed));
56
+ updateCollapsedClass();
57
+ }
58
+
59
+ export function toggleMobileSidebar() {
60
+ state.sidebarOpenMobile = !state.sidebarOpenMobile;
61
+ $('#sidebar').classList.toggle('open', state.sidebarOpenMobile);
62
+ }
63
+
64
+ const viewToSection = {
65
+ workspace: 'workspace',
66
+ themes: 'themes',
67
+ 'theme-detail': 'themes',
68
+ searches: 'searches',
69
+ 'search-detail': 'searches',
70
+ decisions: 'decisions',
71
+ memories: 'memories',
72
+ settings: 'settings',
73
+ };
74
+
75
+ export function sectionFor(view) {
76
+ return viewToSection[view] || 'workspace';
77
+ }
78
+
79
+ export function workspaceFolderName() {
80
+ const cwd = state.data.workspace?.cwd;
81
+ if (!cwd) return 'Workspace';
82
+ return (
83
+ String(cwd)
84
+ .replace(/\\/g, '/')
85
+ .split('/')
86
+ .filter(Boolean)
87
+ .pop() || 'Workspace'
88
+ );
89
+ }
90
+
91
+ export function updateDocumentTitle() {
92
+ const folder = workspaceFolderName();
93
+ document.title = folder === 'Workspace' ? 'Kimi Memory' : `Kimi Memory - ${folder}`;
94
+ }
@@ -0,0 +1,81 @@
1
+ import { escapeHtml } from './helpers.js';
2
+
3
+ export function renderMarkdown(md) {
4
+ if (!md) return '';
5
+ let text = escapeHtml(md);
6
+
7
+ // fenced code blocks
8
+ text = text.replace(/```([\s\S]*?)```/g, (_, code) => {
9
+ return `<pre><code>${code.replace(/^\n|\n$/g, '')}</code></pre>`;
10
+ });
11
+
12
+ // inline code
13
+ text = text.replace(/`([^`]+)`/g, '<code>$1</code>');
14
+
15
+ // headings
16
+ text = text.replace(/^#{1,6}\s+(.+)$/gm, (match, content) => {
17
+ const level = match.match(/^#+/)[0].length;
18
+ return `<h${level}>${content}</h${level}>`;
19
+ });
20
+
21
+ // horizontal rules
22
+ text = text.replace(/^\s*[-*]{3,}\s*$/gm, '<hr>');
23
+
24
+ // blockquote lines (single-line simple support)
25
+ text = text.replace(/^>\s+(.+)$/gm, '<blockquote>$1</blockquote>');
26
+
27
+ // unordered lists (single level)
28
+ text = text.replace(/(?:^[-*+]\s+.+\n?)+/gm, (block) => {
29
+ const items = block
30
+ .trim()
31
+ .split('\n')
32
+ .map((line) => `<li>${line.replace(/^[-*+]\s+/, '')}</li>`)
33
+ .join('');
34
+ return `<ul>${items}</ul>`;
35
+ });
36
+
37
+ // ordered lists (single level)
38
+ text = text.replace(/(?:^\d+\.\s+.+\n?)+/gm, (block) => {
39
+ const items = block
40
+ .trim()
41
+ .split('\n')
42
+ .map((line) => `<li>${line.replace(/^\d+\.\s+/, '')}</li>`)
43
+ .join('');
44
+ return `<ol>${items}</ol>`;
45
+ });
46
+
47
+ // links
48
+ text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
49
+
50
+ // bold / italic (handle combined)
51
+ text = text.replace(/\*\*\*([^*]+)\*\*\*/g, '<strong><em>$1</em></strong>');
52
+ text = text.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
53
+ text = text.replace(/\*([^*]+)\*/g, '<em>$1</em>');
54
+ text = text.replace(/___([^_]+)___/g, '<strong><em>$1</em></strong>');
55
+ text = text.replace(/__([^_]+)__/g, '<strong>$1</strong>');
56
+ text = text.replace(/_([^_]+)_/g, '<em>$1</em>');
57
+
58
+ // paragraphs: group consecutive non-empty, non-block lines
59
+ const blocks = [];
60
+ const lines = text.split('\n');
61
+ let buf = [];
62
+ for (const line of lines) {
63
+ const trimmed = line.trim();
64
+ const isBlock =
65
+ trimmed === '' ||
66
+ /^<(?:h[1-6]|ul|ol|li|pre|blockquote|hr)/.test(trimmed) ||
67
+ /^<\/(?:h[1-6]|ul|ol|li|pre|blockquote)>$/.test(trimmed);
68
+ if (isBlock) {
69
+ if (buf.length) {
70
+ blocks.push(`<p>${buf.join(' ')}</p>`);
71
+ buf = [];
72
+ }
73
+ if (trimmed !== '') blocks.push(line);
74
+ } else {
75
+ buf.push(line);
76
+ }
77
+ }
78
+ if (buf.length) blocks.push(`<p>${buf.join(' ')}</p>`);
79
+
80
+ return blocks.join('\n');
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kimi-code-memory-mcp-server",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Local stdio MCP server providing cross-session memory for Kimi Code CLI",
5
5
  "main": "dist/server.js",
6
6
  "types": "dist/server.d.ts",