@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.
- package/commands/plexor-status.md +60 -23
- package/hooks/intercept.js +111 -0
- package/lib/constants.js +40 -0
- package/package.json +1 -1
|
@@ -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
|
|
27
|
+
**Step 3: Call the APIs**
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
First, get user info:
|
|
30
30
|
```
|
|
31
|
-
GET {apiUrl}/
|
|
32
|
-
|
|
31
|
+
GET {apiUrl}/v1/user
|
|
32
|
+
X-Plexor-Key: {apiKey}
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
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
|
|
56
|
+
Show the user a formatted status display:
|
|
40
57
|
|
|
41
58
|
```
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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.
|
package/hooks/intercept.js
CHANGED
|
@@ -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);
|
package/lib/constants.js
ADDED
|
@@ -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