@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 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 2: Select/create project
73
- const projectData = await selectOrCreateProject(authData, options);
74
- if (!projectData) {
75
- console.error(chalk.red('❌ Project setup failed'));
76
- process.exit(1);
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
- console.log(chalk.green(`✓ Project: ${projectData.project_name} (${projectData.project_id})`));
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
- // Step 3: Save project config
82
- await saveProjectConfig(authData, projectData);
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
@@ -206,7 +206,7 @@ noteCommand
206
206
  // Show welcome splash if no command provided
207
207
  if (process.argv.length === 2) {
208
208
  await showWelcome();
209
- program.help();
209
+ process.exit(0);
210
210
  }
211
211
 
212
212
  program.parse();
@@ -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 {
@@ -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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifiedmemory/cli",
3
- "version": "1.3.9",
3
+ "version": "1.3.10",
4
4
  "description": "UnifiedMemory CLI - AI code assistant integration",
5
5
  "main": "index.js",
6
6
  "type": "module",