@unifiedmemory/cli 1.3.14 → 1.3.16

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/.env.example CHANGED
@@ -17,17 +17,17 @@
17
17
  # ============================================
18
18
  # Clerk OAuth Configuration
19
19
  # ============================================
20
- # Production defaults are included in the CLI
21
- # Only override these if using a custom Clerk instance
22
- # CLERK_CLIENT_ID=custom_clerk_client_id
23
- # CLERK_DOMAIN=custom-app.clerk.accounts.dev
20
+ # Production defaults are included in the CLI.
21
+ # For local development, uncomment and use dev Clerk values:
22
+ # CLERK_CLIENT_ID=nULlnomaKB9rRGP2
23
+ # CLERK_DOMAIN=clear-caiman-45.clerk.accounts.dev
24
24
 
25
25
  # ============================================
26
26
  # API Configuration
27
27
  # ============================================
28
- # Production default is included in the CLI
29
- # Only override this for local testing or custom deployments
30
- # API_ENDPOINT=https://custom-api-gateway.zuplo.dev
28
+ # Production default is included in the CLI.
29
+ # For local development, uncomment and use dev gateway:
30
+ # API_ENDPOINT=https://rose-asp-main-1c0b114.d2.zuplo.dev
31
31
 
32
32
  # ============================================
33
33
  # OAuth Flow Configuration
package/lib/config.js CHANGED
@@ -10,12 +10,14 @@ dotenvConfig({ path: join(__dirname, '..', '.env') });
10
10
 
11
11
  export const config = {
12
12
  // Clerk OAuth configuration (production defaults, can be overridden via env vars)
13
- clerkClientId: process.env.CLERK_CLIENT_ID || 'nULlnomaKB9rRGP2',
13
+ // TODO: Replace clerkClientId with production Clerk OAuth client ID once created
14
+ clerkClientId: process.env.CLERK_CLIENT_ID || 'bNpTWw0hP3V7ueqN',
14
15
  clerkClientSecret: process.env.CLERK_CLIENT_SECRET, // Optional for PKCE flow
15
- clerkDomain: process.env.CLERK_DOMAIN || 'clear-caiman-45.clerk.accounts.dev',
16
+ clerkDomain: process.env.CLERK_DOMAIN || 'clerk.unifiedmemory.ai',
16
17
 
17
18
  // API configuration (production default, can be overridden via env var)
18
- apiEndpoint: process.env.API_ENDPOINT || 'https://rose-asp-main-1c0b114.d2.zuplo.dev',
19
+ // TODO: Replace with production Zuplo gateway URL once deployed
20
+ apiEndpoint: process.env.API_ENDPOINT || 'https://api.unifiedmemory.ai',
19
21
 
20
22
  // OAuth flow configuration (localhost defaults for callback server)
21
23
  redirectUri: process.env.REDIRECT_URI || 'http://localhost:3333/callback',
package/lib/mcp-proxy.js CHANGED
@@ -2,7 +2,9 @@
2
2
  * MCP Proxy Client - Forwards MCP requests to the gateway HTTP endpoint
3
3
  */
4
4
 
5
- const GATEWAY_MCP_URL = 'https://rose-asp-main-1c0b114.d2.zuplo.dev/mcp';
5
+ import { config } from './config.js';
6
+
7
+ const GATEWAY_MCP_URL = `${config.apiEndpoint}/mcp`;
6
8
 
7
9
  /**
8
10
  * Transform tool schema to hide context parameters (org, proj, user)
@@ -1,82 +1,76 @@
1
1
  // Unique marker to detect if instructions already present
2
- export const MEMORY_INSTRUCTIONS_MARKER = '<!-- UNIFIEDMEMORY_INSTRUCTIONS_V2 -->';
2
+ export const MEMORY_INSTRUCTIONS_MARKER = '<!-- UNIFIEDMEMORY_INSTRUCTIONS_V3 -->';
3
3
 
4
4
  export function getMemoryInstructions() {
5
5
  return `${MEMORY_INSTRUCTIONS_MARKER}
6
6
 
7
- # UnifiedMemory Integration (REQUIRED)
7
+ # STOP - Read Before ANY Code Task
8
8
 
9
- This project uses UnifiedMemory for persistent knowledge management. The \`unifiedmemory\` MCP server is configured and MUST be used for all relevant queries.
9
+ **MANDATORY**: Call \`search_notes\` BEFORE writing any code. Always. No exceptions.
10
10
 
11
- ## Available Tools
11
+ ## Pre-Implementation Checklist
12
12
 
13
- The \`unifiedmemory\` MCP server provides these tools (call them like any MCP tool):
13
+ Before ANY coding task, you MUST:
14
+ - [ ] Call \`search_notes\` with relevant keywords
15
+ - [ ] Review results for existing patterns/decisions
16
+ - [ ] Mention what you found (or didn't) in your response
17
+ - [ ] THEN start implementation
14
18
 
15
- | Tool | Purpose | Required Parameters |
16
- |------|---------|---------------------|
17
- | \`search_notes\` | **Primary tool** - Search project knowledge base | \`query\` (search text) |
18
- | \`create_note\` | Record decisions, plans, or completions | \`summary_text\`, \`topic\` |
19
- | \`list_notes\` | List all notes in current project | None |
20
- | \`get_note\` | Retrieve a specific note by ID | \`note_id\` |
21
- | \`list_topics\` | List available topics/categories | None |
22
- | \`create_topic\` | Create a new topic for organization | \`name\` |
23
- | \`list_projects\` | List available projects | None |
19
+ ---
24
20
 
25
- All tools automatically use the correct project context - no additional configuration needed.
21
+ ## WRONG
26
22
 
27
- ## MANDATORY: Search Before Implementing
23
+ \`\`\`
24
+ User: "Create a calculator app"
25
+ Assistant: [immediately writes code] ← NEVER DO THIS
26
+ \`\`\`
28
27
 
29
- **REQUIREMENT**: Before responding to ANY coding task, feature request, or implementation question, you MUST:
28
+ ## CORRECT
30
29
 
31
- 1. Call the \`search_notes\` tool with the user's query or relevant keywords
32
- 2. Review returned results for prior decisions, patterns, or context
33
- 3. Incorporate relevant findings into your response
34
- 4. Mention what context you found (or didn't find) in your response
30
+ \`\`\`
31
+ User: "Create a calculator app"
32
+ Assistant: [calls search_notes first]
33
+ Assistant: "No relevant patterns found in UnifiedMemory. Proceeding..."
34
+ Assistant: [writes code]
35
+ \`\`\`
35
36
 
36
- ### When to Search
37
+ ---
37
38
 
38
- You MUST search before:
39
- - Implementing any feature (search for existing patterns)
40
- - Fixing any bug (search for related issues)
41
- - Answering architecture questions (search for design decisions)
42
- - Modifying any component (search for existing conventions)
43
- - ANY coding task, no exceptions
39
+ ## When to Search (ALWAYS)
44
40
 
45
- ### Example Workflow
41
+ - Before implementing ANY feature ← search first
42
+ - Before fixing ANY bug ← search first
43
+ - Before answering architecture questions ← search first
44
+ - Before modifying ANY component ← search first
45
+ - For "simple" tasks ← search first (context always helps)
46
46
 
47
- \`\`\`
48
- User: "Add authentication to the API"
49
-
50
- Step 1: Call search_notes with query "authentication API security"
51
- Step 2: Review results - found: "Decision: Use JWT with refresh tokens"
52
- Step 3: Implement following the established pattern
53
- Step 4: Respond: "Based on prior decisions in UnifiedMemory, I'll use JWT..."
54
- \`\`\`
47
+ ---
55
48
 
56
- ## Do NOT Skip These Tools
49
+ ## MCP Tool Reference
57
50
 
58
- - NEVER start implementing without calling \`search_notes\` first
59
- - ❌ NEVER assume patterns without checking the knowledge base
60
- - NEVER skip search for "simple" tasks - context always helps
61
- - ALWAYS search even if you think you know the answer
62
- - ALWAYS mention search results (or lack thereof) in your response
63
- - ALWAYS use these tools when they can provide relevant context
51
+ | Tool | Purpose | Parameters |
52
+ |------|---------|------------|
53
+ | \`search_notes\` | **Search knowledge base** | \`body: {q: "search text"}\` |
54
+ | \`create_note\` | Record decisions/completions | \`body: {summary_text: "...", topic: "..."}\` |
55
+ | \`list_notes\` | Browse all notes | None |
56
+ | \`get_note\` | Get note by ID | \`body: {note_id: "..."}\` |
57
+ | \`list_topics\` | List categories | None |
58
+ | \`create_topic\` | Create category | \`body: {name: "..."}\` |
64
59
 
65
- ## Recording Knowledge with create_note
60
+ Project context is automatic - no extra config needed.
66
61
 
67
- After completing significant work, use \`create_note\` to record:
68
- - Implementation decisions and rationale
69
- - Completed features or fixes
70
- - Architectural patterns established
71
- - Gotchas or lessons learned
62
+ ---
72
63
 
73
- Keep notes concise (under 1000 characters) and focus on the "why" not the "what".
64
+ ## After Completing Work
74
65
 
75
- ## Additional Tools
66
+ Use \`create_note\` to record:
67
+ - Decisions and rationale (the "why")
68
+ - Patterns established
69
+ - Gotchas or lessons learned
76
70
 
77
- Use \`list_topics\` to understand project organization, \`list_notes\` to browse available knowledge, and \`get_note\` to retrieve full details of relevant notes found via search.
71
+ Keep notes under 1000 chars. Focus on "why" not "what".
78
72
 
79
73
  ---
80
- *UnifiedMemory CLI - Knowledge that persists*
74
+ *UnifiedMemory - \`search_notes\` FIRST, code SECOND*
81
75
  `;
82
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifiedmemory/cli",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "UnifiedMemory CLI - AI code assistant integration",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -8,6 +8,11 @@
8
8
 
9
9
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
10
10
 
11
+ // Mock dotenv so the local .env file doesn't interfere with unit tests
12
+ vi.mock('dotenv', () => ({
13
+ config: vi.fn()
14
+ }));
15
+
11
16
  describe('config', () => {
12
17
  // Store original env vars
13
18
  const originalEnv = { ...process.env };
@@ -35,9 +40,9 @@ describe('config', () => {
35
40
  // Fresh import to get defaults
36
41
  const { config } = await import('../../lib/config.js');
37
42
 
38
- expect(config.clerkClientId).toBe('nULlnomaKB9rRGP2');
39
- expect(config.clerkDomain).toBe('clear-caiman-45.clerk.accounts.dev');
40
- expect(config.apiEndpoint).toBe('https://rose-asp-main-1c0b114.d2.zuplo.dev');
43
+ expect(config.clerkClientId).toBe('bNpTWw0hP3V7ueqN');
44
+ expect(config.clerkDomain).toBe('clerk.unifiedmemory.ai');
45
+ expect(config.apiEndpoint).toBe('https://api.unifiedmemory.ai');
41
46
  expect(config.redirectUri).toBe('http://localhost:3333/callback');
42
47
  expect(config.port).toBe(3333);
43
48
  });
@@ -123,7 +128,7 @@ describe('config', () => {
123
128
  const { config, validateConfig } = await import('../../lib/config.js');
124
129
 
125
130
  // Empty string is falsy, so it falls back to default
126
- expect(config.clerkDomain).toBe('clear-caiman-45.clerk.accounts.dev');
131
+ expect(config.clerkDomain).toBe('clerk.unifiedmemory.ai');
127
132
  expect(validateConfig()).toBe(true);
128
133
  });
129
134
 
@@ -142,7 +147,7 @@ describe('config', () => {
142
147
  const { config, validateConfig } = await import('../../lib/config.js');
143
148
 
144
149
  // Empty string is falsy, so it falls back to default
145
- expect(config.clerkClientId).toBe('nULlnomaKB9rRGP2');
150
+ expect(config.clerkClientId).toBe('bNpTWw0hP3V7ueqN');
146
151
  expect(validateConfig()).toBe(true);
147
152
  });
148
153
 
@@ -8,11 +8,17 @@
8
8
  * are tested indirectly through the exported functions.
9
9
  */
10
10
 
11
- import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from 'vitest';
11
+ import { describe, it, expect, vi, beforeAll, beforeEach, afterAll, afterEach } from 'vitest';
12
12
  import { setupServer } from 'msw/node';
13
13
  import { http, HttpResponse } from 'msw';
14
14
 
15
- const GATEWAY_MCP_URL = 'https://rose-asp-main-1c0b114.d2.zuplo.dev/mcp';
15
+ // Mock dotenv so the local .env file doesn't interfere with unit tests
16
+ vi.mock('dotenv', () => ({
17
+ config: vi.fn()
18
+ }));
19
+
20
+ // Must match the fallback default in lib/config.js (used when no .env is present, e.g. CI)
21
+ const GATEWAY_MCP_URL = 'https://api.unifiedmemory.ai/mcp';
16
22
 
17
23
  // Sample tool with pathParams and headers that should be transformed
18
24
  const sampleToolWithContext = {
@@ -59,6 +65,11 @@ const sampleToolNoContext = {
59
65
  const server = setupServer();
60
66
 
61
67
  beforeAll(() => server.listen({ onUnhandledRequest: 'bypass' }));
68
+ beforeEach(() => {
69
+ vi.resetModules();
70
+ // Clear API_ENDPOINT so config.js uses the hardcoded default matching GATEWAY_MCP_URL above
71
+ delete process.env.API_ENDPOINT;
72
+ });
62
73
  afterEach(() => server.resetHandlers());
63
74
  afterAll(() => server.close());
64
75