@unifiedmemory/cli 1.0.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.
- package/.env.example +9 -0
- package/CHANGELOG.md +34 -0
- package/HOOK_SETUP.md +338 -0
- package/LICENSE +51 -0
- package/README.md +220 -0
- package/bin/um-mcp-serve +62 -0
- package/commands/init.js +315 -0
- package/commands/login.js +390 -0
- package/commands/org.js +111 -0
- package/commands/record.js +114 -0
- package/index.js +215 -0
- package/lib/clerk-api.js +172 -0
- package/lib/config.js +39 -0
- package/lib/hooks.js +43 -0
- package/lib/mcp-proxy.js +227 -0
- package/lib/mcp-server.js +284 -0
- package/lib/provider-detector.js +291 -0
- package/lib/token-refresh.js +113 -0
- package/lib/token-storage.js +63 -0
- package/lib/token-validation.js +47 -0
- package/package.json +49 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
|
|
5
|
+
const TOKEN_DIR = path.join(os.homedir(), '.um');
|
|
6
|
+
const TOKEN_FILE = path.join(TOKEN_DIR, 'auth.json');
|
|
7
|
+
|
|
8
|
+
export function saveToken(tokenData) {
|
|
9
|
+
// Create directory if it doesn't exist
|
|
10
|
+
if (!fs.existsSync(TOKEN_DIR)) {
|
|
11
|
+
fs.mkdirSync(TOKEN_DIR, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Preserve existing organization context if not explicitly overwritten
|
|
15
|
+
const existingData = getToken();
|
|
16
|
+
if (existingData && existingData.selectedOrg && !tokenData.selectedOrg) {
|
|
17
|
+
tokenData.selectedOrg = existingData.selectedOrg;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokenData, null, 2));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getToken() {
|
|
24
|
+
if (!fs.existsSync(TOKEN_FILE)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const data = fs.readFileSync(TOKEN_FILE, 'utf8');
|
|
30
|
+
return JSON.parse(data);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function clearToken() {
|
|
37
|
+
if (fs.existsSync(TOKEN_FILE)) {
|
|
38
|
+
fs.unlinkSync(TOKEN_FILE);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Update the selected organization context
|
|
44
|
+
* @param {Object|null} orgData - Organization data or null for personal context
|
|
45
|
+
*/
|
|
46
|
+
export function updateSelectedOrg(orgData) {
|
|
47
|
+
const tokenData = getToken();
|
|
48
|
+
if (!tokenData) {
|
|
49
|
+
throw new Error('No token found. Please login first.');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
tokenData.selectedOrg = orgData;
|
|
53
|
+
fs.writeFileSync(TOKEN_FILE, JSON.stringify(tokenData, null, 2));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get the currently selected organization context
|
|
58
|
+
* @returns {Object|null} Organization data or null if personal context
|
|
59
|
+
*/
|
|
60
|
+
export function getSelectedOrg() {
|
|
61
|
+
const tokenData = getToken();
|
|
62
|
+
return tokenData?.selectedOrg || null;
|
|
63
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getToken } from './token-storage.js';
|
|
2
|
+
import { isTokenExpired, refreshAccessToken } from './token-refresh.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Load token and refresh if expired
|
|
6
|
+
* @param {boolean} requireAuth - Whether to throw if not authenticated (default true)
|
|
7
|
+
* @returns {Promise<Object|null>} - Token data or null
|
|
8
|
+
* @throws {Error} - If not authenticated and requireAuth is true, or if refresh fails
|
|
9
|
+
*/
|
|
10
|
+
export async function loadAndRefreshToken(requireAuth = true) {
|
|
11
|
+
const tokenData = getToken();
|
|
12
|
+
|
|
13
|
+
if (!tokenData) {
|
|
14
|
+
if (requireAuth) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
'Not authenticated. Please run: um login\n' +
|
|
17
|
+
'No token found at ~/.um/auth.json'
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check expiration
|
|
24
|
+
if (isTokenExpired(tokenData)) {
|
|
25
|
+
console.error('⚠️ Token expired, attempting refresh...');
|
|
26
|
+
|
|
27
|
+
if (tokenData.refresh_token) {
|
|
28
|
+
try {
|
|
29
|
+
const refreshed = await refreshAccessToken(tokenData);
|
|
30
|
+
console.error('✓ Token refreshed successfully');
|
|
31
|
+
return refreshed;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
'Token expired and refresh failed. Please run: um login\n' +
|
|
35
|
+
`Refresh error: ${error.message}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
throw new Error(
|
|
40
|
+
'Token expired and no refresh token available. Please run: um login\n' +
|
|
41
|
+
'Hint: Try logging in again to get a new refresh token'
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return tokenData;
|
|
47
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unifiedmemory/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "UnifiedMemory CLI - AI code assistant integration",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"um": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node index.js",
|
|
12
|
+
"build": "pkg . --targets node18-linux-x64,node18-macos-x64,node18-win-x64 --output dist/um"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"ai",
|
|
16
|
+
"mcp",
|
|
17
|
+
"claude",
|
|
18
|
+
"cursor",
|
|
19
|
+
"unified-memory",
|
|
20
|
+
"cli",
|
|
21
|
+
"code-assistant",
|
|
22
|
+
"model-context-protocol"
|
|
23
|
+
],
|
|
24
|
+
"author": "Episodic Solutions Limited <support@unifiedmemory.ai>",
|
|
25
|
+
"license": "PROPRIETARY",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/Episodic-Solutions/um-cli/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://unifiedmemory.ai",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"commander": "^11.1.0",
|
|
37
|
+
"inquirer": "^13.0.1",
|
|
38
|
+
"open": "^10.0.3",
|
|
39
|
+
"axios": "^1.6.2",
|
|
40
|
+
"fs-extra": "^11.2.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"pkg": "^5.8.1"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "https://github.com/unifiedmemory/um-cli.git"
|
|
48
|
+
}
|
|
49
|
+
}
|