polydev-ai 1.9.27 → 1.9.28

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.
Files changed (2) hide show
  1. package/mcp/stdio-wrapper.js +74 -185
  2. package/package.json +1 -1
@@ -155,9 +155,6 @@ if (writableTmp) {
155
155
  * Strips: provider info, approval, sandbox, reasoning, session id, MCP errors, etc.
156
156
  *
157
157
  * Codex CLI output structure:
158
- * [metadata] → user → [echoed prompt] → thinking → [status] → codex → [RESPONSE] → tokens used → [count]
159
- *
160
- * Claude Code output structure:
161
158
  * [may include JSON or plain text response]
162
159
  */
163
160
  function cleanCliResponse(content) {
@@ -1046,9 +1043,28 @@ To authenticate, pass your token directly:
1046
1043
  };
1047
1044
  }
1048
1045
 
1049
- // Not sandboxed — auto-trigger browser login
1050
- console.error('[Polydev] No token found, auto-triggering login flow...');
1051
- return await this.triggerReAuth(id, 'Not authenticated. Opening browser for login...');
1046
+ // Not sandboxed — tell user to use login tool (don't auto-open browser)
1047
+ console.error('[Polydev] No token found, prompting user to login');
1048
+ return {
1049
+ jsonrpc: '2.0',
1050
+ id,
1051
+ result: {
1052
+ content: [{
1053
+ type: 'text',
1054
+ text: `POLYDEV STATUS
1055
+ ==============
1056
+
1057
+ Authentication: Not connected
1058
+
1059
+ To login:
1060
+ 1. Use the "login" tool (opens browser)
1061
+ 2. Or run: npx polydev-ai
1062
+
1063
+ Token will be saved automatically after login.`
1064
+ }],
1065
+ isError: true
1066
+ }
1067
+ };
1052
1068
  }
1053
1069
 
1054
1070
  try {
@@ -1138,9 +1154,26 @@ Configure: https://polydev.ai/dashboard/models`
1138
1154
  }
1139
1155
  };
1140
1156
  } else {
1141
- // Token invalid/expired - auto-trigger re-authentication
1142
- console.error('[Polydev] Auth status: token invalid/expired, auto-triggering re-auth...');
1143
- return await this.triggerReAuth(id, 'Token invalid or expired.');
1157
+ // Token invalid/expired - tell user to re-login (don't auto-open browser)
1158
+ console.error('[Polydev] Auth status: token invalid/expired');
1159
+ return {
1160
+ jsonrpc: '2.0',
1161
+ id,
1162
+ result: {
1163
+ content: [{
1164
+ type: 'text',
1165
+ text: `POLYDEV STATUS
1166
+ ==============
1167
+
1168
+ Authentication: Token invalid or expired
1169
+
1170
+ To re-authenticate:
1171
+ 1. Use the "login" tool (opens browser)
1172
+ 2. Or run: npx polydev-ai`
1173
+ }],
1174
+ isError: true
1175
+ }
1176
+ };
1144
1177
  }
1145
1178
  } catch (error) {
1146
1179
  // Categorize the error for clearer user messaging
@@ -1687,11 +1720,24 @@ To re-login: /polydev:login`
1687
1720
  heartbeat.stop(); // Always clean up heartbeat
1688
1721
  console.error(`[Stdio Wrapper] get_perspectives error:`, error);
1689
1722
 
1690
- // Check if error is auth-related
1723
+ // Check if error is specifically an HTTP 401 unauthorized
1724
+ // IMPORTANT: Don't match generic 'token' or 'auth' strings — they appear in
1725
+ // unrelated errors like "Unexpected token" (JSON parse) or "authentication" (CLI output)
1691
1726
  const errMsg = (error.message || '').toLowerCase();
1692
- if (errMsg.includes('401') || errMsg.includes('unauthorized') || errMsg.includes('auth') || errMsg.includes('token')) {
1693
- console.error('[Polydev] Perspectives auth error, auto-triggering re-authentication...');
1694
- return await this.triggerReAuth(id, 'Authentication expired. Re-authenticating...');
1727
+ const isHttp401 = errMsg.includes('401') || errMsg.includes('unauthorized');
1728
+ if (isHttp401) {
1729
+ console.error('[Polydev] Perspectives auth error (401), suggesting re-login');
1730
+ return {
1731
+ jsonrpc: '2.0',
1732
+ id,
1733
+ result: {
1734
+ content: [{
1735
+ type: 'text',
1736
+ text: `Authentication error: ${error.message}\n\nPlease re-authenticate using the "login" tool or run: npx polydev-ai`
1737
+ }],
1738
+ isError: true
1739
+ }
1740
+ };
1695
1741
  }
1696
1742
 
1697
1743
  return {
@@ -2676,8 +2722,8 @@ To re-login: /polydev:login`
2676
2722
  const statusFile = path.join(polydevevDir, 'cli-status.json');
2677
2723
 
2678
2724
  // Ensure directory exists
2679
- if (!fs.existsSync(polydevevDir)) {
2680
- fs.mkdirSync(polydevevDir, { recursive: true });
2725
+ if (!fs.existsSync(polydeveevDir)) {
2726
+ fs.mkdirSync(polydeveevDir, { recursive: true });
2681
2727
  }
2682
2728
 
2683
2729
  // Save status with timestamp
@@ -3141,28 +3187,24 @@ To re-login: /polydev:login`
3141
3187
  }
3142
3188
 
3143
3189
  /**
3144
- * Run startup flow - auto-login if no token, verify if has token
3190
+ * Run startup flow - verify token if present, show instructions if not
3191
+ * NEVER auto-opens browser — only the explicit "login" tool should do that
3145
3192
  */
3146
3193
  async runStartupFlow() {
3194
+ // Last-chance token reload before deciding
3195
+ if (!this.userToken) {
3196
+ this.reloadTokenFromFiles();
3197
+ }
3198
+
3147
3199
  if (!this.userToken) {
3148
- // No token - auto-open browser for login (NON-BLOCKING)
3200
+ // No token found just log instructions, don't open browser
3149
3201
  console.error('─'.repeat(50));
3150
- console.error('Polydev - First Time Setup');
3202
+ console.error('Polydev - Authentication Required');
3151
3203
  console.error('─'.repeat(50));
3152
- console.error('Opening browser for authentication...\n');
3153
-
3154
- // Run auto-login in background (don't block MCP server startup)
3155
- this.autoLoginOnStartup().then(() => {
3156
- console.error('[Polydev] Login completed, running CLI detection...');
3157
- // After login, run CLI detection
3158
- return this.localForceCliDetection({});
3159
- }).then(() => {
3160
- this._cliDetectionComplete = true;
3161
- // Display CLI status after detection
3162
- return this.displayCliStatus();
3163
- }).catch((error) => {
3164
- console.error('[Polydev] Auto-login flow error:', error.message);
3165
- });
3204
+ console.error('No token found. To authenticate:');
3205
+ console.error(' 1. Use the "login" tool');
3206
+ console.error(' 2. Or run: npx polydev-ai');
3207
+ console.error('─'.repeat(50) + '\n');
3166
3208
  } else {
3167
3209
  // Has token - verify it (also non-blocking)
3168
3210
  this.verifyAndDisplayAuth().catch((error) => {
@@ -3171,159 +3213,6 @@ To re-login: /polydev:login`
3171
3213
  }
3172
3214
  }
3173
3215
 
3174
- /**
3175
- * Auto-login on startup (opens browser automatically)
3176
- */
3177
- async autoLoginOnStartup() {
3178
- const http = require('http');
3179
- const { spawn } = require('child_process');
3180
-
3181
- return new Promise((resolve) => {
3182
- const server = http.createServer((req, res) => {
3183
- const url = new URL(req.url, `http://localhost`);
3184
-
3185
- if (req.method === 'OPTIONS') {
3186
- res.writeHead(204, {
3187
- 'Access-Control-Allow-Origin': '*',
3188
- 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
3189
- 'Access-Control-Allow-Headers': 'Content-Type'
3190
- });
3191
- res.end();
3192
- return;
3193
- }
3194
-
3195
- if (url.pathname === '/callback') {
3196
- const token = url.searchParams.get('token');
3197
-
3198
- if (token && token.startsWith('pd_')) {
3199
- this.saveTokenToFiles(token);
3200
- this.userToken = token;
3201
- this.isAuthenticated = true;
3202
- this._freshLogin = true; // Flag for opening models page after CLI detection
3203
-
3204
- res.writeHead(200, {
3205
- 'Content-Type': 'text/html; charset=utf-8',
3206
- 'Access-Control-Allow-Origin': '*'
3207
- });
3208
- res.end(this.getLoginSuccessHTML());
3209
-
3210
- console.error('[Polydev] Login successful, token saved');
3211
-
3212
- // Wait 7 seconds before closing server (gives time for 5s auto-close countdown + buffer)
3213
- setTimeout(() => {
3214
- server.close();
3215
- resolve({
3216
- jsonrpc: '2.0',
3217
- id,
3218
- result: {
3219
- content: [{
3220
- type: 'text',
3221
- text: `LOGIN SUCCESSFUL
3222
- ================
3223
-
3224
- Token saved to:
3225
- ~/.polydev.env
3226
- ~/.zshrc
3227
-
3228
- IMPORTANT: Restart your IDE to activate.
3229
-
3230
- After restart, you can:
3231
- /polydev:ask Query multiple AI models
3232
- /polydev:auth Check status & credits
3233
-
3234
- Dashboard: https://polydev.ai/dashboard`
3235
- }]
3236
- }
3237
- });
3238
- }, 7000);
3239
- } else {
3240
- res.writeHead(400, { 'Content-Type': 'text/plain' });
3241
- res.end('Invalid or missing token');
3242
- }
3243
- } else {
3244
- res.writeHead(404);
3245
- res.end('Not found');
3246
- }
3247
- });
3248
-
3249
- server.listen(0, 'localhost', () => {
3250
- const port = server.address().port;
3251
- const callbackUrl = `http://localhost:${port}/callback`;
3252
- const authUrl = `https://polydev.ai/auth?callback=${encodeURIComponent(callbackUrl)}&redirect=ide-plugin&auto=true`;
3253
-
3254
- console.error('If browser does not open, visit:');
3255
- console.error(authUrl);
3256
- console.error('');
3257
-
3258
- // Best-in-class browser opening using 'open' package (cross-platform)
3259
- // Falls back to platform-specific commands if package fails
3260
- this.openBrowser(authUrl).catch(() => {
3261
- console.error('[Polydev] All browser open methods failed');
3262
- console.error('[Polydev] Please open this URL manually:', authUrl);
3263
- });
3264
-
3265
- // Don't block forever - resolve after timeout
3266
- setTimeout(() => {
3267
- if (!this.isAuthenticated) {
3268
- console.error('[!] Login timeout - use "login" tool to try again');
3269
- console.error('─'.repeat(50) + '\n');
3270
- }
3271
- server.close();
3272
- resolve(false);
3273
- }, 2 * 60 * 1000); // 2 minute timeout for startup
3274
- });
3275
-
3276
- server.on('error', (err) => {
3277
- console.error('[!] Could not start login server:', err.message);
3278
- console.error(' Use "login" tool or run: npx polydev-ai login');
3279
- console.error('─'.repeat(50) + '\n');
3280
- resolve(false);
3281
- });
3282
- });
3283
- }
3284
-
3285
- /**
3286
- * Verify token and display auth status
3287
- */
3288
- async verifyAndDisplayAuth() {
3289
- try {
3290
- const response = await fetch('https://www.polydev.ai/api/mcp', {
3291
- method: 'POST',
3292
- headers: {
3293
- 'Content-Type': 'application/json',
3294
- 'Authorization': `Bearer ${this.userToken}`,
3295
- 'User-Agent': 'polydev-mcp/1.0.0'
3296
- },
3297
- body: JSON.stringify({ action: 'check_status' })
3298
- });
3299
-
3300
- if (response.ok) {
3301
- const data = await response.json();
3302
- const credits = data.credits_remaining?.toLocaleString() || 0;
3303
- const tier = data.subscription_tier || 'Free';
3304
-
3305
- console.error('─'.repeat(50));
3306
- console.error('Polydev - Authenticated');
3307
- console.error('─'.repeat(50));
3308
- console.error(`Account: ${data.email || 'Connected'}`);
3309
- console.error(`Credits: ${credits} | Tier: ${tier}`);
3310
- console.error('─'.repeat(50) + '\n');
3311
- } else {
3312
- // Don't clear isAuthenticated here — handleGetAuthStatus has its own
3313
- // verification and triggerReAuth logic. Clearing here causes a race condition
3314
- // where startup verification can invalidate auth before the user checks status.
3315
- console.error('─'.repeat(50));
3316
- console.error('Polydev - Token may be invalid');
3317
- console.error('─'.repeat(50));
3318
- console.error('Server returned non-OK. Will re-verify on next auth check.');
3319
- console.error('Use the "login" tool or run: npx polydev-ai login');
3320
- console.error('─'.repeat(50) + '\n');
3321
- }
3322
- } catch (error) {
3323
- console.error('[Polydev] Could not verify auth (offline?):', error.message || 'unknown');
3324
- }
3325
- }
3326
-
3327
3216
  /**
3328
3217
  * Display CLI tools status after detection
3329
3218
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.9.27",
3
+ "version": "1.9.28",
4
4
  "engines": {
5
5
  "node": ">=20.x <=22.x"
6
6
  },