@plexor-dev/claude-code-plugin 0.1.0-beta.4 → 0.1.0-beta.7

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.
@@ -24,38 +24,75 @@ The config file contains:
24
24
 
25
25
  If `apiKey` is missing or empty, tell the user to run `/plexor-login` first.
26
26
 
27
- **Step 3: Call the stats API**
27
+ **Step 3: Call the APIs**
28
28
 
29
- Make a request to get usage statistics:
29
+ First, get user info:
30
30
  ```
31
- GET {apiUrl}/api/users/me/usage
32
- Authorization: Bearer {apiKey}
31
+ GET {apiUrl}/v1/user
32
+ X-Plexor-Key: {apiKey}
33
33
  ```
34
34
 
35
- Note: The apiKey IS the bearer token - use it directly in the Authorization header.
35
+ Then, get usage statistics:
36
+ ```
37
+ GET {apiUrl}/v1/stats
38
+ X-Plexor-Key: {apiKey}
39
+ ```
40
+
41
+ The stats response contains:
42
+ - `summary.total_requests`: number of requests
43
+ - `summary.original_tokens`: tokens before optimization
44
+ - `summary.optimized_tokens`: tokens after optimization
45
+ - `summary.tokens_saved`: tokens saved
46
+ - `summary.tokens_saved_percent`: percentage saved
47
+ - `summary.baseline_cost`: cost without optimization
48
+ - `summary.total_cost`: actual cost
49
+ - `summary.cost_saved`: money saved
50
+ - `summary.cost_saved_percent`: percentage saved
51
+ - `summary.cache_hit_rate`: cache hit rate
52
+ - `period.start` / `period.end`: date range
36
53
 
37
54
  **Step 4: Display the status**
38
55
 
39
- Show the user a formatted status display like this:
56
+ Show the user a formatted status display:
40
57
 
41
58
  ```
42
- Plexor Status
43
- =============
44
- Account: [tier from API response, e.g., "Pro" or "Free"]
45
- Status: [Enabled/Disabled based on config.enabled]
46
-
47
- This Session
48
- Requests: [totalRequests from API]
49
- Tokens saved: [tokensUsed from API]
50
- Est. savings: $[costSavings from API]
51
-
52
- Settings
53
- Mode: [config.mode]
54
- Provider: [config.preferredProvider]
55
- Local cache: [Enabled/Disabled based on config.localCacheEnabled]
56
- API URL: [config.apiUrl]
57
-
58
- Dashboard: https://plexor.dev/dashboard
59
+ ┌─────────────────────────────────────────────┐
60
+ │ Plexor Status │
61
+ ├─────────────────────────────────────────────┤
62
+ │ Account: [tier from /v1/user]
63
+ │ Email: [email from /v1/user] │
64
+ │ Status: ● Active │
65
+ ├─────────────────────────────────────────────┤
66
+ This Week ([period.start] - [period.end]) │
67
+ ├── Requests: [total_requests]
68
+ │ ├── Original tokens: [original_tokens] │
69
+ │ ├── Optimized tokens: [optimized_tokens] │
70
+ ├── Tokens saved: [tokens_saved] ([tokens_saved_percent]%) │
71
+ ├── Baseline cost: $[baseline_cost]
72
+ ├── Actual cost: $[total_cost]
73
+ └── Cost saved: $[cost_saved] ([cost_saved_percent]%) │
74
+ ├─────────────────────────────────────────────┤
75
+ │ Performance │
76
+ │ └── Cache hit rate: [cache_hit_rate]% │
77
+ ├─────────────────────────────────────────────┤
78
+ │ Limits │
79
+ │ ├── Monthly optimizations: [from tier] │
80
+ │ └── Monthly completions: [from tier] │
81
+ ├─────────────────────────────────────────────┤
82
+ │ Settings │
83
+ │ ├── Optimization: [Enabled/Disabled] │
84
+ │ ├── Local cache: [Enabled/Disabled] │
85
+ │ ├── Mode: [mode] │
86
+ │ └── Provider routing: [preferredProvider] │
87
+ └─────────────────────────────────────────────┘
88
+
89
+ Dashboard: [apiUrl]/dashboard
59
90
  ```
60
91
 
92
+ Notes:
93
+ - Use "● Active" (green dot) if enabled, "○ Inactive" if disabled
94
+ - Format token counts with commas (e.g., 46,700)
95
+ - Format costs with 2 decimal places (e.g., $8.02)
96
+ - Multiply cache_hit_rate by 100 for percentage display
97
+
61
98
  If the API call fails, show the configuration status and mention the API is unavailable.
@@ -42,6 +42,38 @@ async function main() {
42
42
  });
43
43
  }
44
44
 
45
+ // CRITICAL: Skip optimization for slash commands (Issue #683)
46
+ // Slash commands like /plexor-status should pass through unchanged
47
+ if (isSlashCommand(request)) {
48
+ logger.debug('Slash command detected, passing through unchanged');
49
+ return output({
50
+ ...request,
51
+ plexor_cwd: process.cwd(),
52
+ _plexor: {
53
+ source: 'passthrough_slash_command',
54
+ reason: 'slash_command_detected',
55
+ cwd: process.cwd(),
56
+ latency_ms: Date.now() - startTime
57
+ }
58
+ });
59
+ }
60
+
61
+ // CRITICAL: Skip optimization for CLI commands requiring tool execution (Issue #683)
62
+ // Azure CLI, AWS CLI, kubectl, etc. need tools to be preserved
63
+ if (requiresToolExecution(request)) {
64
+ logger.debug('CLI tool execution detected, passing through unchanged');
65
+ return output({
66
+ ...request,
67
+ plexor_cwd: process.cwd(),
68
+ _plexor: {
69
+ source: 'passthrough_cli',
70
+ reason: 'cli_tool_execution_detected',
71
+ cwd: process.cwd(),
72
+ latency_ms: Date.now() - startTime
73
+ }
74
+ });
75
+ }
76
+
45
77
  const settings = await config.load();
46
78
 
47
79
  if (!settings.enabled) {
@@ -293,6 +325,85 @@ function isAgenticRequest(request) {
293
325
  return false;
294
326
  }
295
327
 
328
+ /**
329
+ * Detect if this is a slash command request that should not be optimized.
330
+ * Slash commands like /plexor-status need to pass through unchanged.
331
+ */
332
+ function isSlashCommand(request) {
333
+ const messages = request.messages || [];
334
+
335
+ // Check the last user message for slash command patterns
336
+ for (let i = messages.length - 1; i >= 0; i--) {
337
+ const msg = messages[i];
338
+ if (msg.role === 'user') {
339
+ const content = typeof msg.content === 'string' ? msg.content : '';
340
+ // Detect slash commands at the start of user message
341
+ if (/^\/[a-z-]+/i.test(content.trim())) {
342
+ return true;
343
+ }
344
+ // Detect <command-name> tags (Claude Code skill invocation)
345
+ if (/<command-name>/.test(content)) {
346
+ return true;
347
+ }
348
+ // Detect plexor-related commands
349
+ if (/plexor-(?:status|login|logout|mode|provider|enabled|settings)/i.test(content)) {
350
+ return true;
351
+ }
352
+ break; // Only check last user message
353
+ }
354
+ }
355
+
356
+ // Check for system messages with skill instructions
357
+ for (const msg of messages) {
358
+ if (msg.role === 'system') {
359
+ const content = typeof msg.content === 'string' ? msg.content : '';
360
+ if (/# Plexor (?:Status|Login|Logout|Mode|Provider|Enabled|Settings)/i.test(content)) {
361
+ return true;
362
+ }
363
+ }
364
+ }
365
+
366
+ return false;
367
+ }
368
+
369
+ /**
370
+ * Detect if this request involves CLI/shell commands that need tool execution.
371
+ * These should pass through to ensure proper tool calling behavior.
372
+ */
373
+ function requiresToolExecution(request) {
374
+ const messages = request.messages || [];
375
+
376
+ // Check user messages for CLI command patterns
377
+ for (const msg of messages) {
378
+ if (msg.role === 'user') {
379
+ const content = typeof msg.content === 'string' ? msg.content : '';
380
+ const contentLower = content.toLowerCase();
381
+
382
+ // Azure CLI patterns
383
+ if (/\baz\s+(login|logout|group|account|vm|storage|webapp|aks|acr|keyvault|sql|cosmos|network)/i.test(content)) {
384
+ return true;
385
+ }
386
+
387
+ // Common CLI execution requests
388
+ if (/\b(run|execute|show|list|create|delete|update)\b.*\b(az|aws|gcloud|kubectl|docker|npm|git)\b/i.test(content)) {
389
+ return true;
390
+ }
391
+
392
+ // Direct command patterns
393
+ if (/^(az|aws|gcloud|kubectl|docker|npm|yarn|pip|cargo|go)\s+/m.test(content)) {
394
+ return true;
395
+ }
396
+
397
+ // Imperative CLI requests
398
+ if (/\b(list|show|get|describe)\s+(resource\s*groups?|rgs?|vms?|instances?|clusters?|pods?|containers?)/i.test(content)) {
399
+ return true;
400
+ }
401
+ }
402
+ }
403
+
404
+ return false;
405
+ }
406
+
296
407
  main().catch((error) => {
297
408
  console.error(`[Plexor] Fatal error: ${error.message}`);
298
409
  process.exit(1);
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Plexor Claude Code Plugin - Constants
3
+ */
4
+
5
+ const path = require('path');
6
+ const os = require('os');
7
+
8
+ module.exports = {
9
+ // API endpoints
10
+ PLEXOR_API_URL: process.env.PLEXOR_API_URL || 'https://api.plexor.dev',
11
+ PLEXOR_GATEWAY_URL: process.env.PLEXOR_GATEWAY_URL || 'https://api.plexor.dev/v1',
12
+ PLEXOR_AUTH_URL: 'https://plexor.dev/auth/device',
13
+
14
+ // File paths
15
+ PLEXOR_CONFIG_DIR: process.env.PLEXOR_CONFIG_DIR || path.join(os.homedir(), '.plexor'),
16
+ PLEXOR_CONFIG_FILE: path.join(
17
+ process.env.PLEXOR_CONFIG_DIR || path.join(os.homedir(), '.plexor'),
18
+ 'config.json'
19
+ ),
20
+ CLAUDE_COMMANDS_DIR: path.join(os.homedir(), '.claude', 'commands'),
21
+
22
+ // Config schema version
23
+ CONFIG_VERSION: 1,
24
+
25
+ // Default settings
26
+ DEFAULTS: {
27
+ enabled: true,
28
+ preferred_provider: 'auto',
29
+ telemetry: true,
30
+ local_cache: false
31
+ },
32
+
33
+ // API key prefix for identification
34
+ API_KEY_PREFIX: 'plx_',
35
+
36
+ // Timeouts (ms)
37
+ DEVICE_CODE_POLL_INTERVAL: 5000,
38
+ DEVICE_CODE_TIMEOUT: 900000, // 15 minutes
39
+ API_TIMEOUT: 30000
40
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plexor-dev/claude-code-plugin",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.7",
4
4
  "description": "LLM cost optimization plugin for Claude Code - Save up to 90% on AI costs",
5
5
  "main": "lib/constants.js",
6
6
  "scripts": {