@lovelybunch/api 1.0.46 → 1.0.48

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 (38) hide show
  1. package/dist/lib/gait-path.d.ts +7 -5
  2. package/dist/lib/gait-path.js +23 -17
  3. package/dist/lib/project-paths.d.ts +2 -2
  4. package/dist/lib/project-paths.js +8 -5
  5. package/dist/lib/storage/file-storage.js +4 -4
  6. package/dist/lib/symlinks/symlink-manager.js +40 -24
  7. package/dist/lib/terminal/context-helper.js +27 -27
  8. package/dist/lib/terminal/shell-utils.js +6 -6
  9. package/dist/lib/terminal/terminal-manager.d.ts +2 -0
  10. package/dist/lib/terminal/terminal-manager.js +31 -9
  11. package/dist/routes/api/v1/agents/[id]/route.js +4 -4
  12. package/dist/routes/api/v1/agents/route.js +4 -4
  13. package/dist/routes/api/v1/ai/route.js +3 -6
  14. package/dist/routes/api/v1/chats/[id]/route.js +4 -4
  15. package/dist/routes/api/v1/chats/route.js +4 -4
  16. package/dist/routes/api/v1/config/index.js +2 -1
  17. package/dist/routes/api/v1/config/route.d.ts +13 -0
  18. package/dist/routes/api/v1/config/route.js +69 -0
  19. package/dist/routes/api/v1/context/knowledge/[filename]/route.js +4 -4
  20. package/dist/routes/api/v1/context/knowledge/route.js +4 -4
  21. package/dist/routes/api/v1/mcp/config/index.d.ts +1 -0
  22. package/dist/routes/api/v1/mcp/config/index.js +1 -0
  23. package/dist/routes/api/v1/mcp/config/route.d.ts +3 -0
  24. package/dist/routes/api/v1/mcp/config/route.js +59 -0
  25. package/dist/routes/api/v1/mcp/index.js +2 -2
  26. package/dist/routes/api/v1/proposals/[id]/route.d.ts +0 -2
  27. package/dist/routes/api/v1/proposals/route.d.ts +0 -2
  28. package/dist/routes/api/v1/resources/[id]/route.js +4 -4
  29. package/dist/routes/api/v1/resources/[id]/thumbnail/route.js +4 -4
  30. package/dist/routes/api/v1/resources/route.js +4 -4
  31. package/dist/routes/api/v1/symlinks/index.d.ts +1 -0
  32. package/dist/routes/api/v1/symlinks/index.js +1 -0
  33. package/dist/routes/api/v1/symlinks/route.d.ts +3 -0
  34. package/dist/routes/api/v1/symlinks/route.js +135 -0
  35. package/dist/server.js +2 -0
  36. package/package.json +5 -5
  37. package/static/assets/index-DnaNaR1E.js +714 -0
  38. package/static/index.html +1 -1
@@ -3,16 +3,16 @@ import { join, resolve } from "path";
3
3
  function getChatsPath() {
4
4
  let basePath;
5
5
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
- // Dev mode: use project root .gait directory
6
+ // Dev mode: use project root .nut directory
7
7
  basePath = process.env.GAIT_DEV_ROOT;
8
8
  }
9
9
  else if (process.env.GAIT_DATA_PATH) {
10
10
  // Production mode: use GAIT_DATA_PATH (set by CLI)
11
- basePath = resolve(process.env.GAIT_DATA_PATH, '.gait');
11
+ basePath = resolve(process.env.GAIT_DATA_PATH, '.nut');
12
12
  }
13
13
  else {
14
- // Fallback: use current directory .gait
15
- basePath = resolve(process.cwd(), '.gait');
14
+ // Fallback: use current directory .nut
15
+ basePath = resolve(process.cwd(), '.nut');
16
16
  }
17
17
  return join(basePath, 'chats');
18
18
  }
@@ -1,6 +1,7 @@
1
1
  import { Hono } from 'hono';
2
- import { GET, PUT } from './route.js';
2
+ import { GET, PUT, TEST } from './route.js';
3
3
  const config = new Hono();
4
4
  config.get('/', GET);
5
5
  config.put('/', PUT);
6
+ config.post('/test', TEST);
6
7
  export default config;
@@ -17,3 +17,16 @@ export declare function PUT(c: Context): Promise<(Response & import("hono").Type
17
17
  }, 500, "json">) | (Response & import("hono").TypedResponse<{
18
18
  error: string;
19
19
  }, 405, "json">)>;
20
+ export declare function TEST(c: Context): Promise<(Response & import("hono").TypedResponse<{
21
+ success: false;
22
+ message: string;
23
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
24
+ success: false;
25
+ message: string;
26
+ }, 200, "json">) | (Response & import("hono").TypedResponse<{
27
+ success: true;
28
+ message: string;
29
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
30
+ success: false;
31
+ message: string;
32
+ }, 501, "json">)>;
@@ -127,3 +127,72 @@ export async function PUT(c) {
127
127
  return c.json({ error: 'PUT not supported for project config' }, 405);
128
128
  }
129
129
  }
130
+ // POST /api/v1/config/test
131
+ // Body: { provider: string, key?: string }
132
+ // Tests the provided API key (or the saved key if not provided) for a supported provider.
133
+ export async function TEST(c) {
134
+ try {
135
+ const body = await c.req.json();
136
+ const provider = (body?.provider || '').toString();
137
+ const providedKey = typeof body?.key === 'string' ? body.key : undefined;
138
+ if (!provider) {
139
+ return c.json({ success: false, message: 'Missing provider' }, 400);
140
+ }
141
+ // Load saved key if none provided (or if a masked placeholder was provided)
142
+ let effectiveKey = providedKey && providedKey !== '***' ? providedKey : undefined;
143
+ if (!effectiveKey) {
144
+ // Read from global config
145
+ const configPath = await getGlobalConfigPath();
146
+ let config = { apiKeys: {}, defaults: {} };
147
+ try {
148
+ const content = await fs.readFile(configPath, 'utf-8');
149
+ config = JSON.parse(content);
150
+ }
151
+ catch { }
152
+ effectiveKey = config.apiKeys?.[provider];
153
+ // Fallback: env var for OpenRouter only (optional)
154
+ if (!effectiveKey && provider === 'openrouter') {
155
+ effectiveKey = process.env.OPENROUTER_API_KEY;
156
+ }
157
+ }
158
+ if (!effectiveKey) {
159
+ return c.json({ success: false, message: 'No API key configured or provided' }, 400);
160
+ }
161
+ if (provider === 'openrouter') {
162
+ try {
163
+ // Minimal auth-required request to validate key
164
+ const resp = await fetch('https://openrouter.ai/api/v1/chat/completions', {
165
+ method: 'POST',
166
+ headers: {
167
+ 'Authorization': `Bearer ${effectiveKey}`,
168
+ 'Content-Type': 'application/json',
169
+ 'HTTP-Referer': process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001',
170
+ 'X-Title': 'Coconut AI Assistant',
171
+ },
172
+ body: JSON.stringify({
173
+ model: 'openai/gpt-4o-mini',
174
+ messages: [
175
+ { role: 'system', content: 'Health check' },
176
+ { role: 'user', content: 'ping' },
177
+ ],
178
+ temperature: 0,
179
+ max_tokens: 1,
180
+ }),
181
+ });
182
+ if (!resp.ok) {
183
+ const text = await resp.text();
184
+ return c.json({ success: false, message: `OpenRouter rejected key: ${text.slice(0, 200)}` }, 200);
185
+ }
186
+ return c.json({ success: true, message: 'OpenRouter key is valid' });
187
+ }
188
+ catch (err) {
189
+ return c.json({ success: false, message: err instanceof Error ? err.message : 'Network error' }, 200);
190
+ }
191
+ }
192
+ // Other providers not wired up yet
193
+ return c.json({ success: false, message: `Provider '${provider}' test not implemented yet` }, 501);
194
+ }
195
+ catch (error) {
196
+ return c.json({ success: false, message: 'Invalid request body' }, 400);
197
+ }
198
+ }
@@ -6,16 +6,16 @@ const app = new Hono();
6
6
  function getKnowledgePath() {
7
7
  let basePath;
8
8
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
9
- // Dev mode: use project root .gait directory
9
+ // Dev mode: use project root .nut directory
10
10
  basePath = process.env.GAIT_DEV_ROOT;
11
11
  }
12
12
  else if (process.env.GAIT_DATA_PATH) {
13
13
  // Production mode: use GAIT_DATA_PATH (set by CLI)
14
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
14
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
15
15
  }
16
16
  else {
17
- // Fallback: use current directory .gait
18
- basePath = path.resolve(process.cwd(), '.gait');
17
+ // Fallback: use current directory .nut
18
+ basePath = path.resolve(process.cwd(), '.nut');
19
19
  }
20
20
  return path.join(basePath, 'context', 'knowledge');
21
21
  }
@@ -7,16 +7,16 @@ const app = new Hono();
7
7
  function getKnowledgePath() {
8
8
  let basePath;
9
9
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
10
- // Dev mode: use project root .gait directory
10
+ // Dev mode: use project root .nut directory
11
11
  basePath = process.env.GAIT_DEV_ROOT;
12
12
  }
13
13
  else if (process.env.GAIT_DATA_PATH) {
14
14
  // Production mode: use GAIT_DATA_PATH (set by CLI)
15
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
16
16
  }
17
17
  else {
18
- // Fallback: use current directory .gait
19
- basePath = path.resolve(process.cwd(), '.gait');
18
+ // Fallback: use current directory .nut
19
+ basePath = path.resolve(process.cwd(), '.nut');
20
20
  }
21
21
  return path.join(basePath, 'context', 'knowledge');
22
22
  }
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,59 @@
1
+ import { Hono } from 'hono';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ const app = new Hono();
5
+ const getMcpConfigPath = () => {
6
+ const gaitPath = path.join(process.cwd(), '.gait');
7
+ return path.join(gaitPath, 'mcp', 'config.json');
8
+ };
9
+ const ensureMcpDirectory = async () => {
10
+ const gaitPath = path.join(process.cwd(), '.gait');
11
+ const mcpPath = path.join(gaitPath, 'mcp');
12
+ try {
13
+ await fs.access(mcpPath);
14
+ }
15
+ catch {
16
+ await fs.mkdir(mcpPath, { recursive: true });
17
+ }
18
+ };
19
+ // GET /api/v1/mcp/config - Get MCP configuration
20
+ app.get('/', async (c) => {
21
+ try {
22
+ await ensureMcpDirectory();
23
+ const configPath = getMcpConfigPath();
24
+ try {
25
+ const configData = await fs.readFile(configPath, 'utf-8');
26
+ const config = JSON.parse(configData);
27
+ return c.json(config);
28
+ }
29
+ catch (error) {
30
+ // If file doesn't exist or is invalid, return empty config
31
+ return c.json({});
32
+ }
33
+ }
34
+ catch (error) {
35
+ console.error('Error reading MCP config:', error);
36
+ return c.json({ error: 'Failed to read MCP configuration' }, 500);
37
+ }
38
+ });
39
+ // PUT /api/v1/mcp/config - Update MCP configuration
40
+ app.put('/', async (c) => {
41
+ try {
42
+ const body = await c.req.json();
43
+ await ensureMcpDirectory();
44
+ const configPath = getMcpConfigPath();
45
+ // Validate the configuration structure
46
+ if (typeof body !== 'object') {
47
+ return c.json({ error: 'Invalid configuration format' }, 400);
48
+ }
49
+ // Write the configuration to file
50
+ const configData = JSON.stringify(body, null, 2);
51
+ await fs.writeFile(configPath, configData, 'utf-8');
52
+ return c.json({ message: 'MCP configuration updated successfully' });
53
+ }
54
+ catch (error) {
55
+ console.error('Error updating MCP config:', error);
56
+ return c.json({ error: 'Failed to update MCP configuration' }, 500);
57
+ }
58
+ });
59
+ export default app;
@@ -12,10 +12,10 @@ function resolveGaitPath() {
12
12
  basePath = process.env.GAIT_DEV_ROOT;
13
13
  }
14
14
  else if (process.env.GAIT_DATA_PATH) {
15
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
16
16
  }
17
17
  else {
18
- basePath = path.resolve(process.cwd(), '.gait');
18
+ basePath = path.resolve(process.cwd(), '.nut');
19
19
  }
20
20
  return basePath;
21
21
  }
@@ -16,7 +16,6 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
16
16
  id: string;
17
17
  name: string;
18
18
  email?: string;
19
- role?: string;
20
19
  };
21
20
  productSpecRef?: string;
22
21
  planSteps: {
@@ -174,7 +173,6 @@ export declare function PATCH(c: Context): Promise<(Response & import("hono").Ty
174
173
  id: string;
175
174
  name: string;
176
175
  email?: string;
177
- role?: string;
178
176
  };
179
177
  productSpecRef?: string;
180
178
  planSteps: {
@@ -10,7 +10,6 @@ export declare function GET(c: Context): Promise<(Response & import("hono").Type
10
10
  id: string;
11
11
  name: string;
12
12
  email?: string;
13
- role?: string;
14
13
  };
15
14
  productSpecRef?: string;
16
15
  planSteps: {
@@ -168,7 +167,6 @@ export declare function POST(c: Context): Promise<(Response & import("hono").Typ
168
167
  id: string;
169
168
  name: string;
170
169
  email?: string;
171
- role?: string;
172
170
  };
173
171
  productSpecRef?: string;
174
172
  planSteps: {
@@ -3,16 +3,16 @@ import path from 'path';
3
3
  function getResourcesPath() {
4
4
  let basePath;
5
5
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
- // Dev mode: use project root .gait directory
6
+ // Dev mode: use project root .nut directory
7
7
  basePath = process.env.GAIT_DEV_ROOT;
8
8
  }
9
9
  else if (process.env.GAIT_DATA_PATH) {
10
10
  // Production mode: use GAIT_DATA_PATH (set by CLI)
11
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
11
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
12
12
  }
13
13
  else {
14
- // Fallback: use current directory .gait
15
- basePath = path.resolve(process.cwd(), '.gait');
14
+ // Fallback: use current directory .nut
15
+ basePath = path.resolve(process.cwd(), '.nut');
16
16
  }
17
17
  return path.join(basePath, 'resources');
18
18
  }
@@ -3,16 +3,16 @@ import path from 'path';
3
3
  function getResourcesPath() {
4
4
  let basePath;
5
5
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
6
- // Dev mode: use project root .gait directory
6
+ // Dev mode: use project root .nut directory
7
7
  basePath = process.env.GAIT_DEV_ROOT;
8
8
  }
9
9
  else if (process.env.GAIT_DATA_PATH) {
10
10
  // Production mode: use GAIT_DATA_PATH (set by CLI)
11
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
11
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
12
12
  }
13
13
  else {
14
- // Fallback: use current directory .gait
15
- basePath = path.resolve(process.cwd(), '.gait');
14
+ // Fallback: use current directory .nut
15
+ basePath = path.resolve(process.cwd(), '.nut');
16
16
  }
17
17
  return path.join(basePath, 'resources');
18
18
  }
@@ -7,16 +7,16 @@ function generateId() {
7
7
  function getResourcesPath() {
8
8
  let basePath;
9
9
  if (process.env.NODE_ENV === 'development' && process.env.GAIT_DEV_ROOT) {
10
- // Dev mode: use project root .gait directory
10
+ // Dev mode: use project root .nut directory
11
11
  basePath = process.env.GAIT_DEV_ROOT;
12
12
  }
13
13
  else if (process.env.GAIT_DATA_PATH) {
14
14
  // Production mode: use GAIT_DATA_PATH (set by CLI)
15
- basePath = path.resolve(process.env.GAIT_DATA_PATH, '.gait');
15
+ basePath = path.resolve(process.env.GAIT_DATA_PATH, '.nut');
16
16
  }
17
17
  else {
18
- // Fallback: use current directory .gait
19
- basePath = path.resolve(process.cwd(), '.gait');
18
+ // Fallback: use current directory .nut
19
+ basePath = path.resolve(process.cwd(), '.nut');
20
20
  }
21
21
  return path.join(basePath, 'resources');
22
22
  }
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1 @@
1
+ export { default } from './route.js';
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export default app;
@@ -0,0 +1,135 @@
1
+ import { Hono } from 'hono';
2
+ import { getSymlinkManager } from '../../../../lib/symlinks/symlink-manager.js';
3
+ const app = new Hono();
4
+ /**
5
+ * GET /api/v1/symlinks
6
+ * Get all symlink configurations
7
+ */
8
+ app.get('/', async (c) => {
9
+ try {
10
+ const manager = await getSymlinkManager();
11
+ const symlinks = await manager.getSymlinks();
12
+ return c.json({
13
+ success: true,
14
+ symlinks
15
+ });
16
+ }
17
+ catch (error) {
18
+ console.error('Failed to get symlinks:', error);
19
+ return c.json({ success: false, error: 'Failed to get symlinks' }, 500);
20
+ }
21
+ });
22
+ /**
23
+ * POST /api/v1/symlinks
24
+ * Create a new symlink configuration
25
+ */
26
+ app.post('/', async (c) => {
27
+ try {
28
+ const body = await c.req.json();
29
+ const { name, description, linkPath, targetPath, isActive = false } = body;
30
+ if (!name || !linkPath || !targetPath) {
31
+ return c.json({ success: false, error: 'Name, linkPath, and targetPath are required' }, 400);
32
+ }
33
+ const manager = await getSymlinkManager();
34
+ const result = await manager.addSymlink({
35
+ name,
36
+ description: description || '',
37
+ linkPath,
38
+ targetPath,
39
+ isActive
40
+ });
41
+ if (!result.success) {
42
+ return c.json({ success: false, error: result.message }, 400);
43
+ }
44
+ return c.json({
45
+ success: true,
46
+ symlink: result.symlink,
47
+ message: result.message
48
+ });
49
+ }
50
+ catch (error) {
51
+ console.error('Failed to create symlink:', error);
52
+ return c.json({ success: false, error: 'Failed to create symlink' }, 500);
53
+ }
54
+ });
55
+ /**
56
+ * PUT /api/v1/symlinks/:id
57
+ * Update a symlink configuration
58
+ */
59
+ app.put('/:id', async (c) => {
60
+ try {
61
+ const id = c.req.param('id');
62
+ const body = await c.req.json();
63
+ const { name, description, linkPath, targetPath, isActive } = body;
64
+ const manager = await getSymlinkManager();
65
+ const result = await manager.updateSymlink(id, {
66
+ name,
67
+ description,
68
+ linkPath,
69
+ targetPath,
70
+ isActive
71
+ });
72
+ if (!result.success) {
73
+ return c.json({ success: false, error: result.message }, 400);
74
+ }
75
+ return c.json({
76
+ success: true,
77
+ symlink: result.symlink,
78
+ message: result.message
79
+ });
80
+ }
81
+ catch (error) {
82
+ console.error('Failed to update symlink:', error);
83
+ return c.json({ success: false, error: 'Failed to update symlink' }, 500);
84
+ }
85
+ });
86
+ /**
87
+ * DELETE /api/v1/symlinks/:id
88
+ * Delete a symlink configuration
89
+ */
90
+ app.delete('/:id', async (c) => {
91
+ try {
92
+ const id = c.req.param('id');
93
+ const manager = await getSymlinkManager();
94
+ const result = await manager.deleteSymlink(id);
95
+ if (!result.success) {
96
+ return c.json({ success: false, error: result.message }, 400);
97
+ }
98
+ return c.json({
99
+ success: true,
100
+ message: result.message
101
+ });
102
+ }
103
+ catch (error) {
104
+ console.error('Failed to delete symlink:', error);
105
+ return c.json({ success: false, error: 'Failed to delete symlink' }, 500);
106
+ }
107
+ });
108
+ /**
109
+ * POST /api/v1/symlinks/:id/toggle
110
+ * Toggle symlink active state (create/remove actual symlink)
111
+ */
112
+ app.post('/:id/toggle', async (c) => {
113
+ try {
114
+ const id = c.req.param('id');
115
+ const manager = await getSymlinkManager();
116
+ const symlink = await manager.getSymlink(id);
117
+ if (!symlink) {
118
+ return c.json({ success: false, error: 'Symlink not found' }, 404);
119
+ }
120
+ const result = await manager.toggleSymlink(id);
121
+ if (!result.success) {
122
+ return c.json({ success: false, error: result.message }, 400);
123
+ }
124
+ return c.json({
125
+ success: true,
126
+ symlink: result.symlink,
127
+ message: result.message
128
+ });
129
+ }
130
+ catch (error) {
131
+ console.error('Failed to toggle symlink:', error);
132
+ return c.json({ success: false, error: 'Failed to toggle symlink' }, 500);
133
+ }
134
+ });
135
+ export default app;
package/dist/server.js CHANGED
@@ -69,6 +69,7 @@ import agents from './routes/api/v1/agents/index.js';
69
69
  import agentsById from './routes/api/v1/agents/[id]/index.js';
70
70
  import git from './routes/api/v1/git/index.js';
71
71
  import mcp from './routes/api/v1/mcp/index.js';
72
+ import symlinks from './routes/api/v1/symlinks/index.js';
72
73
  // Register API routes
73
74
  app.route('/api/v1/proposals', proposals);
74
75
  app.route('/api/v1/terminal/sessions', terminalSessions);
@@ -88,6 +89,7 @@ app.route('/api/v1/agents', agents);
88
89
  app.route('/api/v1/agents/:id', agentsById);
89
90
  app.route('/api/v1/git', git);
90
91
  app.route('/api/v1/mcp', mcp);
92
+ app.route('/api/v1/symlinks', symlinks);
91
93
  // Health check endpoint
92
94
  app.get('/health', (c) => {
93
95
  return c.json({ status: 'ok', timestamp: new Date().toISOString() });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovelybunch/api",
3
- "version": "1.0.46",
3
+ "version": "1.0.48",
4
4
  "type": "module",
5
5
  "main": "dist/server-with-static.js",
6
6
  "exports": {
@@ -12,7 +12,7 @@
12
12
  "static/**/*"
13
13
  ],
14
14
  "scripts": {
15
- "dev": "NODE_ENV=development GAIT_DEV_ROOT=../../.gait tsx watch src/server.ts",
15
+ "dev": "NODE_ENV=development GAIT_DEV_ROOT=../../.nut tsx watch src/server.ts",
16
16
  "build": "tsc",
17
17
  "build:bundle": "tsc && node scripts/bundle-frontend.js",
18
18
  "start": "node dist/server-with-static.js",
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@hono/node-server": "^1.13.7",
34
34
  "@hono/node-ws": "^1.0.6",
35
- "@lovelybunch/core": "^1.0.46",
36
- "@lovelybunch/mcp": "^1.0.45",
37
- "@lovelybunch/types": "^1.0.46",
35
+ "@lovelybunch/core": "^1.0.48",
36
+ "@lovelybunch/mcp": "^1.0.48",
37
+ "@lovelybunch/types": "^1.0.48",
38
38
  "dotenv": "^17.2.1",
39
39
  "fuse.js": "^7.0.0",
40
40
  "gray-matter": "^4.0.3",