@unifiedmemory/cli 1.3.0 → 1.3.1

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.
@@ -52,6 +52,7 @@ export async function record(summary, options = {}) {
52
52
  };
53
53
 
54
54
  // 5. Prepare tool arguments
55
+ // Note: headers (X-Org-Id, X-User-Id) are handled at HTTP level by authHeaders
55
56
  const toolArgs = {
56
57
  body: {
57
58
  summary_text: summary,
@@ -59,10 +60,6 @@ export async function record(summary, options = {}) {
59
60
  source: options.source || 'um-cli',
60
61
  confidence: options.confidence ? parseFloat(options.confidence) : 0.7,
61
62
  tags: options.tags ? options.tags.split(',') : []
62
- },
63
- headers: {
64
- 'X-Org-Id': tokenData.selectedOrg?.id || tokenData.decoded?.sub,
65
- 'X-User-Id': tokenData.decoded?.sub
66
63
  }
67
64
  };
68
65
 
@@ -89,22 +86,47 @@ export async function record(summary, options = {}) {
89
86
  projectContext
90
87
  );
91
88
 
92
- // 7. Handle response
89
+ // 7. Handle response - validate success properly
93
90
  if (result.content && Array.isArray(result.content)) {
94
91
  const textContent = result.content.find(c => c.type === 'text');
95
92
  if (textContent) {
96
- const response = JSON.parse(textContent.text);
97
- console.log(chalk.green('✓ Note created successfully'));
98
- console.log(chalk.gray(` Note ID: ${response.note_id || 'N/A'}`));
99
- if (response.confidence) {
100
- console.log(chalk.gray(` Confidence: ${response.confidence}`));
93
+ try {
94
+ const response = JSON.parse(textContent.text);
95
+
96
+ // Check for error in response
97
+ if (result.isError || response.error || response.detail) {
98
+ throw new Error(response.error || response.detail || 'Note creation failed');
99
+ }
100
+
101
+ console.log(chalk.green('✓ Note created successfully'));
102
+ console.log(chalk.gray(` Note ID: ${response.note_id || 'N/A'}`));
103
+ if (response.confidence) {
104
+ console.log(chalk.gray(` Confidence: ${response.confidence}`));
105
+ }
106
+ return response;
107
+ } catch (parseError) {
108
+ if (parseError.message.includes('Note creation failed')) {
109
+ throw parseError;
110
+ }
111
+ throw new Error(`Failed to parse API response: ${parseError.message}`);
101
112
  }
102
- return response;
103
113
  }
104
114
  }
105
115
 
106
- console.log(chalk.green('✓ Note created'));
107
- return result;
116
+ // Check for direct note response (some backends return this directly)
117
+ if (result.note_id) {
118
+ console.log(chalk.green('✓ Note created successfully'));
119
+ console.log(chalk.gray(` Note ID: ${result.note_id}`));
120
+ return result;
121
+ }
122
+
123
+ // Check for error indicators
124
+ if (result.error || result.detail || result.isError) {
125
+ throw new Error(result.error || result.detail || 'Note creation failed');
126
+ }
127
+
128
+ // Unknown response format - fail explicitly instead of silent success
129
+ throw new Error('Unexpected response format from API');
108
130
 
109
131
  } catch (error) {
110
132
  console.error(chalk.red('✗ Failed to create note:'));
package/lib/mcp-proxy.js CHANGED
@@ -14,6 +14,23 @@ function transformToolSchema(tool) {
14
14
  // Deep clone to avoid mutations
15
15
  const transformed = JSON.parse(JSON.stringify(tool));
16
16
 
17
+ // Remove headers entirely - proxy handles all headers at HTTP level
18
+ // AI never needs to provide X-Org-Id, X-User-Id, etc.
19
+ if (transformed.inputSchema?.properties?.headers) {
20
+ delete transformed.inputSchema.properties.headers;
21
+
22
+ // Also remove from required array if present
23
+ if (transformed.inputSchema.required && Array.isArray(transformed.inputSchema.required)) {
24
+ transformed.inputSchema.required = transformed.inputSchema.required.filter(
25
+ field => field !== 'headers'
26
+ );
27
+
28
+ if (transformed.inputSchema.required.length === 0) {
29
+ delete transformed.inputSchema.required;
30
+ }
31
+ }
32
+ }
33
+
17
34
  // Check if tool has pathParams in schema
18
35
  if (!transformed.inputSchema?.properties?.pathParams) {
19
36
  return transformed;
@@ -79,22 +96,31 @@ function injectContextParams(args, authContext, projectContext) {
79
96
  injected.pathParams = {};
80
97
  }
81
98
 
99
+ // Ensure headers object exists (gateway expects these in tool args)
100
+ if (!injected.headers) {
101
+ injected.headers = {};
102
+ }
103
+
82
104
  // Inject user ID from decoded JWT
83
105
  if (authContext?.decoded?.sub) {
84
106
  injected.pathParams.user = authContext.decoded.sub;
107
+ injected.headers['X-User-Id'] = authContext.decoded.sub;
85
108
  }
86
109
 
87
110
  // Inject org ID (from selectedOrg or fallback to user ID for personal account)
88
111
  if (authContext?.selectedOrg?.id) {
89
112
  injected.pathParams.org = authContext.selectedOrg.id;
113
+ injected.headers['X-Org-Id'] = authContext.selectedOrg.id;
90
114
  } else if (authContext?.decoded?.sub) {
91
115
  // Fallback to user ID for personal account context
92
116
  injected.pathParams.org = authContext.decoded.sub;
117
+ injected.headers['X-Org-Id'] = authContext.decoded.sub;
93
118
  }
94
119
 
95
120
  // Inject project ID from project config
96
121
  if (projectContext?.project_id) {
97
122
  injected.pathParams.proj = projectContext.project_id;
123
+ injected.headers['X-Project-Id'] = projectContext.project_id;
98
124
  }
99
125
 
100
126
  return injected;
@@ -1,72 +1,82 @@
1
1
  // Unique marker to detect if instructions already present
2
- export const MEMORY_INSTRUCTIONS_MARKER = '<!-- UNIFIEDMEMORY_INSTRUCTIONS_V1 -->';
2
+ export const MEMORY_INSTRUCTIONS_MARKER = '<!-- UNIFIEDMEMORY_INSTRUCTIONS_V2 -->';
3
3
 
4
4
  export function getMemoryInstructions() {
5
5
  return `${MEMORY_INSTRUCTIONS_MARKER}
6
6
 
7
- # UnifiedMemory Automatic Integration
7
+ # UnifiedMemory Integration (REQUIRED)
8
8
 
9
- When working in this project, automatically integrate with UnifiedMemory to maintain project knowledge:
9
+ This project uses UnifiedMemory for persistent knowledge management. The \`unifiedmemory\` MCP server is configured and MUST be used for all relevant queries.
10
10
 
11
- ## 1. Search Before Responding
11
+ ## Available Tools
12
12
 
13
- **When**: User submits any query or request
14
- **Action**: Use the \`unifiedmemory\` MCP tool to search for relevant context
15
- **Usage**:
16
- - Send the user's query to the search tool
17
- - Review the search results for relevant prior work, decisions, or context
18
- - Incorporate findings into your response
13
+ The \`unifiedmemory\` MCP server provides these tools (call them like any MCP tool):
19
14
 
20
- Example:
21
- \`\`\`
22
- User: "Add dark mode to the dashboard"
23
- Search: unifiedmemory search --query "dark mode dashboard styling"
24
- Review results for existing patterns or decisions
25
- Respond with context-aware answer
26
- \`\`\`
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 |
27
24
 
28
- ## 2. Record Plans
25
+ All tools automatically use the correct project context - no additional configuration needed.
29
26
 
30
- **When**: Creating an implementation plan or design approach
31
- **Action**: Record the plan as a note using the \`unifiedmemory\` tool
32
- **Format**:
33
- - Include: objective, approach, key steps, important decisions
34
- - Keep concise but informative
35
- - Limit to under 1000 characters for optimal indexing
27
+ ## MANDATORY: Search Before Implementing
36
28
 
37
- Example:
38
- \`\`\`
39
- Plan created for dark mode feature
40
- → unifiedmemory create_note --content "Plan: Dark mode implementation. Approach: CSS variables + localStorage persistence. Steps: 1) Define color tokens, 2) Add toggle component, 3) Persist preference. Decision: Use system preference as default."
41
- \`\`\`
29
+ **REQUIREMENT**: Before responding to ANY coding task, feature request, or implementation question, you MUST:
30
+
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
35
+
36
+ ### When to Search
42
37
 
43
- ## 3. Record Task Completions
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
44
44
 
45
- **When**: After completing any task, feature, or significant milestone
46
- **Action**: Create a summary note using the \`unifiedmemory\` tool
47
- **Format**:
48
- - Summarize what was accomplished and why
49
- - Include key technical decisions or gotchas
50
- - **IMPORTANT**: Limit to under 1000 characters
51
- - Focus on outcomes, not detailed code
45
+ ### Example Workflow
52
46
 
53
- Example:
54
47
  \`\`\`
55
- Completed dark mode feature
56
- → unifiedmemory create_note --content "Completed: Dark mode toggle in dashboard. Implemented CSS custom properties with theme switcher component. User preference stored in localStorage. Respects system prefers-color-scheme by default. All components updated to use theme tokens."
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..."
57
54
  \`\`\`
58
55
 
59
- ## Summary Guidelines
56
+ ## Do NOT Skip These Tools
57
+
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
64
+
65
+ ## Recording Knowledge with create_note
66
+
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
72
+
73
+ Keep notes concise (under 1000 characters) and focus on the "why" not the "what".
74
+
75
+ ## Additional Tools
60
76
 
61
- - **DO**: Search context before responding
62
- - ✅ **DO**: Record plans and completions automatically
63
- - ✅ **DO**: Keep notes under 1000 characters
64
- - ✅ **DO**: Focus on decisions, outcomes, and context
65
- - ❌ **DON'T**: Record trivial tasks (typo fixes, minor edits)
66
- - ❌ **DON'T**: Include full code in notes
67
- - ❌ **DON'T**: Duplicate information already in git commits
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.
68
78
 
69
79
  ---
70
- *Auto-generated by UnifiedMemory CLI v1.0*
80
+ *UnifiedMemory CLI - Knowledge that persists*
71
81
  `;
72
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifiedmemory/cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "UnifiedMemory CLI - AI code assistant integration",
5
5
  "main": "index.js",
6
6
  "type": "module",