@unifiedmemory/cli 1.3.9 → 1.3.10
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/commands/init.js +49 -8
- package/index.js +1 -1
- package/lib/token-refresh.js +0 -4
- package/lib/token-validation.js +30 -1
- package/package.json +1 -1
package/commands/init.js
CHANGED
|
@@ -69,17 +69,58 @@ export async function init(options = {}) {
|
|
|
69
69
|
console.log(chalk.green(`✓ Organization: ${authData.org_id}`));
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
// Step
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
// Step 1.5: Check for existing config
|
|
73
|
+
const umDir = path.join(process.cwd(), '.um');
|
|
74
|
+
const configPath = path.join(umDir, 'config.json');
|
|
75
|
+
let projectData = null;
|
|
76
|
+
let skipProjectSetup = false;
|
|
77
|
+
|
|
78
|
+
if (fs.existsSync(configPath)) {
|
|
79
|
+
try {
|
|
80
|
+
const existingConfig = fs.readJSONSync(configPath);
|
|
81
|
+
|
|
82
|
+
console.log(chalk.cyan('\n📋 Existing configuration found:\n'));
|
|
83
|
+
console.log(chalk.gray(` Project: ${existingConfig.project_name}`));
|
|
84
|
+
console.log(chalk.gray(` Project ID: ${existingConfig.project_id}`));
|
|
85
|
+
console.log(chalk.gray(` Organization: ${existingConfig.org_id}`));
|
|
86
|
+
console.log('');
|
|
87
|
+
|
|
88
|
+
const { override } = await inquirer.prompt([{
|
|
89
|
+
type: 'confirm',
|
|
90
|
+
name: 'override',
|
|
91
|
+
message: 'Override existing configuration?',
|
|
92
|
+
default: false,
|
|
93
|
+
}]);
|
|
94
|
+
|
|
95
|
+
if (!override) {
|
|
96
|
+
// Use existing config - skip project selection
|
|
97
|
+
projectData = {
|
|
98
|
+
project_id: existingConfig.project_id,
|
|
99
|
+
project_name: existingConfig.project_name,
|
|
100
|
+
project_slug: existingConfig.project_slug,
|
|
101
|
+
};
|
|
102
|
+
skipProjectSetup = true;
|
|
103
|
+
console.log(chalk.green(`\n✓ Using existing project: ${projectData.project_name}`));
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.log(chalk.yellow(`\n⚠ Could not read existing config: ${error.message}`));
|
|
107
|
+
console.log(chalk.gray('Continuing with new project setup...\n'));
|
|
108
|
+
}
|
|
77
109
|
}
|
|
78
110
|
|
|
79
|
-
|
|
111
|
+
// Step 2: Select/create project (skip if using existing config)
|
|
112
|
+
if (!skipProjectSetup) {
|
|
113
|
+
projectData = await selectOrCreateProject(authData, options);
|
|
114
|
+
if (!projectData) {
|
|
115
|
+
console.error(chalk.red('❌ Project setup failed'));
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log(chalk.green(`✓ Project: ${projectData.project_name} (${projectData.project_id})`));
|
|
80
120
|
|
|
81
|
-
|
|
82
|
-
|
|
121
|
+
// Step 3: Save project config (only if we selected a new project)
|
|
122
|
+
await saveProjectConfig(authData, projectData);
|
|
123
|
+
}
|
|
83
124
|
|
|
84
125
|
// Step 3.5: Fetch available MCP tools for permissions
|
|
85
126
|
let mcpToolPermissions = null;
|
package/index.js
CHANGED
package/lib/token-refresh.js
CHANGED
|
@@ -77,10 +77,6 @@ export async function refreshAccessToken(tokenData) {
|
|
|
77
77
|
let finalIdToken = newTokenData.id_token;
|
|
78
78
|
let decoded = parseJWT(refreshedToken);
|
|
79
79
|
|
|
80
|
-
// Debug: log what we got from refresh
|
|
81
|
-
console.error(` Refreshed token has sid: ${decoded?.sid ? 'yes' : 'no'}`);
|
|
82
|
-
console.error(` selectedOrg: ${tokenData.selectedOrg?.id || 'none'}`);
|
|
83
|
-
|
|
84
80
|
// If we have org context, get org-scoped token to ensure JWT has org claims
|
|
85
81
|
if (tokenData.selectedOrg?.id && decoded?.sid) {
|
|
86
82
|
try {
|
package/lib/token-validation.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { getToken } from './token-storage.js';
|
|
1
|
+
import { getToken, saveToken } from './token-storage.js';
|
|
2
2
|
import { isTokenExpired, refreshAccessToken } from './token-refresh.js';
|
|
3
|
+
import { getOrgScopedToken } from './clerk-api.js';
|
|
4
|
+
import { parseJWT } from './jwt-utils.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Load token and refresh if expired
|
|
@@ -43,5 +45,32 @@ export async function loadAndRefreshToken(requireAuth = true) {
|
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
// Check if token has org context but lacks org claims in JWT
|
|
49
|
+
// This can happen if getOrgScopedToken() failed during login
|
|
50
|
+
if (tokenData.selectedOrg?.id && tokenData.decoded?.sid && !tokenData.decoded?.o) {
|
|
51
|
+
console.error('⚠️ Token missing org claims, attempting to fix...');
|
|
52
|
+
try {
|
|
53
|
+
const orgToken = await getOrgScopedToken(
|
|
54
|
+
tokenData.decoded.sid,
|
|
55
|
+
tokenData.selectedOrg.id,
|
|
56
|
+
tokenData.idToken || tokenData.accessToken
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const decoded = parseJWT(orgToken.jwt);
|
|
60
|
+
const updatedToken = {
|
|
61
|
+
...tokenData,
|
|
62
|
+
idToken: orgToken.jwt,
|
|
63
|
+
decoded: decoded,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
saveToken(updatedToken);
|
|
67
|
+
console.error('✓ Token updated with org claims');
|
|
68
|
+
return updatedToken;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error(`⚠️ Could not get org-scoped token: ${error.message}`);
|
|
71
|
+
// Continue with existing token - API calls may fail
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
return tokenData;
|
|
47
76
|
}
|