hedgequantx 2.5.8 → 2.5.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/package.json +1 -1
- package/src/menus/ai-agent.js +11 -3
- package/src/menus/dashboard.js +16 -5
- package/src/services/ai/index.js +45 -2
package/package.json
CHANGED
package/src/menus/ai-agent.js
CHANGED
|
@@ -174,9 +174,17 @@ const showExistingTokens = async () => {
|
|
|
174
174
|
const spinner = ora({ text: 'VALIDATING TOKEN...', color: 'cyan' }).start();
|
|
175
175
|
|
|
176
176
|
try {
|
|
177
|
-
// Validate the token
|
|
178
|
-
const credentials = {
|
|
179
|
-
|
|
177
|
+
// Validate the token - include metadata from scanner
|
|
178
|
+
const credentials = {
|
|
179
|
+
apiKey: selectedToken.token,
|
|
180
|
+
sessionKey: selectedToken.token,
|
|
181
|
+
accessToken: selectedToken.token,
|
|
182
|
+
fromKeychain: selectedToken.sourceId === 'secureStorage' || selectedToken.sourceId === 'keychain',
|
|
183
|
+
subscriptionType: selectedToken.subscriptionType,
|
|
184
|
+
refreshToken: selectedToken.refreshToken,
|
|
185
|
+
expiresAt: selectedToken.expiresAt
|
|
186
|
+
};
|
|
187
|
+
const validation = await aiService.validateConnection(selectedToken.provider, selectedToken.type, credentials);
|
|
180
188
|
|
|
181
189
|
if (!validation.valid) {
|
|
182
190
|
spinner.fail(`TOKEN INVALID OR EXPIRED: ${validation.error}`);
|
package/src/menus/dashboard.js
CHANGED
|
@@ -80,7 +80,7 @@ const dashboardMenu = async (service) => {
|
|
|
80
80
|
|
|
81
81
|
console.log(chalk.cyan('╠' + '═'.repeat(W) + '╣'));
|
|
82
82
|
|
|
83
|
-
// Menu in 3 columns
|
|
83
|
+
// Menu in 3 columns - centered
|
|
84
84
|
const colWidth = Math.floor(W / 3);
|
|
85
85
|
|
|
86
86
|
const menuRow3 = (col1, col2, col3) => {
|
|
@@ -88,11 +88,22 @@ const dashboardMenu = async (service) => {
|
|
|
88
88
|
const c2Plain = col2.replace(/\x1b\[[0-9;]*m/g, '');
|
|
89
89
|
const c3Plain = col3.replace(/\x1b\[[0-9;]*m/g, '');
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
const
|
|
91
|
+
// Center each column within its space
|
|
92
|
+
const c1LeftPad = Math.floor((colWidth - c1Plain.length) / 2);
|
|
93
|
+
const c1RightPad = colWidth - c1Plain.length - c1LeftPad;
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const c2LeftPad = Math.floor((colWidth - c2Plain.length) / 2);
|
|
96
|
+
const c2RightPad = colWidth - c2Plain.length - c2LeftPad;
|
|
97
|
+
|
|
98
|
+
const c3Width = W - colWidth * 2;
|
|
99
|
+
const c3LeftPad = Math.floor((c3Width - c3Plain.length) / 2);
|
|
100
|
+
const c3RightPad = c3Width - c3Plain.length - c3LeftPad;
|
|
101
|
+
|
|
102
|
+
console.log(chalk.cyan('║') +
|
|
103
|
+
' '.repeat(Math.max(0, c1LeftPad)) + col1 + ' '.repeat(Math.max(0, c1RightPad)) +
|
|
104
|
+
' '.repeat(Math.max(0, c2LeftPad)) + col2 + ' '.repeat(Math.max(0, c2RightPad)) +
|
|
105
|
+
' '.repeat(Math.max(0, c3LeftPad)) + col3 + ' '.repeat(Math.max(0, c3RightPad)) +
|
|
106
|
+
chalk.cyan('║'));
|
|
96
107
|
};
|
|
97
108
|
|
|
98
109
|
const centerLine = (content) => {
|
package/src/services/ai/index.js
CHANGED
|
@@ -150,11 +150,54 @@ const validateConnection = async (providerId, optionId, credentials) => {
|
|
|
150
150
|
// Validation functions for each provider
|
|
151
151
|
const validateAnthropic = async (credentials) => {
|
|
152
152
|
try {
|
|
153
|
+
const token = credentials.apiKey || credentials.sessionKey || credentials.accessToken;
|
|
154
|
+
|
|
155
|
+
// Check if it's an OAuth token (sk-ant-oat...) vs API key (sk-ant-api...)
|
|
156
|
+
const isOAuthToken = token && token.startsWith('sk-ant-oat');
|
|
157
|
+
|
|
158
|
+
if (isOAuthToken) {
|
|
159
|
+
// OAuth tokens use Bearer auth and claude.ai endpoint
|
|
160
|
+
const response = await fetch('https://api.claude.ai/api/organizations', {
|
|
161
|
+
method: 'GET',
|
|
162
|
+
headers: {
|
|
163
|
+
'Authorization': `Bearer ${token}`,
|
|
164
|
+
'Content-Type': 'application/json',
|
|
165
|
+
'User-Agent': 'HQX-CLI/1.0'
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (response.ok) {
|
|
170
|
+
return { valid: true, tokenType: 'oauth', subscriptionType: credentials.subscriptionType || 'max' };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Try alternate endpoint
|
|
174
|
+
const altResponse = await fetch('https://claude.ai/api/auth/session', {
|
|
175
|
+
method: 'GET',
|
|
176
|
+
headers: {
|
|
177
|
+
'Authorization': `Bearer ${token}`,
|
|
178
|
+
'Cookie': `sessionKey=${token}`
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (altResponse.ok) {
|
|
183
|
+
return { valid: true, tokenType: 'oauth', subscriptionType: credentials.subscriptionType || 'max' };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// For OAuth tokens from Keychain, trust them without validation
|
|
187
|
+
// since the Keychain already verified the user
|
|
188
|
+
if (credentials.fromKeychain) {
|
|
189
|
+
return { valid: true, tokenType: 'oauth', subscriptionType: credentials.subscriptionType || 'max', trusted: true };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return { valid: false, error: 'OAuth token expired or invalid' };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Standard API key validation
|
|
153
196
|
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
|
154
197
|
method: 'POST',
|
|
155
198
|
headers: {
|
|
156
199
|
'Content-Type': 'application/json',
|
|
157
|
-
'x-api-key':
|
|
200
|
+
'x-api-key': token,
|
|
158
201
|
'anthropic-version': '2023-06-01'
|
|
159
202
|
},
|
|
160
203
|
body: JSON.stringify({
|
|
@@ -165,7 +208,7 @@ const validateAnthropic = async (credentials) => {
|
|
|
165
208
|
});
|
|
166
209
|
|
|
167
210
|
if (response.ok) {
|
|
168
|
-
return { valid: true };
|
|
211
|
+
return { valid: true, tokenType: 'api_key' };
|
|
169
212
|
}
|
|
170
213
|
|
|
171
214
|
const error = await response.json();
|