+2
-1
@@ -54,3 +54,4 @@ #!/usr/bin/env node | ||
| break; | ||
| case 'stats': { | ||
| case 'stats': | ||
| case 'usage': { | ||
| const { showStats } = await import('./commands/stats.js'); | ||
@@ -57,0 +58,0 @@ const period = flags.includes('--monthly') ? 'monthly' : 'daily'; |
@@ -61,2 +61,8 @@ /** | ||
| } | ||
| else if (arg === '-m' || arg === '--max-tokens') { | ||
| const value = parseInt(args[++i], 10); | ||
| if (!isNaN(value) && value > 0) { | ||
| options.maxTokens = value; | ||
| } | ||
| } | ||
| else if (arg === '-x' || arg === '--exec') { | ||
@@ -117,14 +123,34 @@ options.execute = true; | ||
| ]; | ||
| // Stream response (to stdout only if not saving to file and not executing) | ||
| // Use non-streaming for file output (to get token usage) | ||
| // Use streaming for interactive output (real-time feedback) | ||
| let fullContent = ''; | ||
| let usage = null; | ||
| const suppressOutput = !!options.output || !!options.execute; | ||
| const useStreaming = !options.output; // Disable streaming when writing to file | ||
| // Lower temperature for execution mode (more deterministic) | ||
| const temperature = options.execute ? 0.3 : undefined; | ||
| try { | ||
| for await (const chunk of client.generateCompletionStream({ messages, temperature })) { | ||
| if (!suppressOutput) { | ||
| process.stdout.write(chunk); | ||
| if (useStreaming) { | ||
| // Streaming mode (interactive, no token usage) | ||
| for await (const chunk of client.generateCompletionStream({ | ||
| messages, | ||
| temperature, | ||
| maxTokens: options.maxTokens, | ||
| })) { | ||
| if (!suppressOutput) { | ||
| process.stdout.write(chunk); | ||
| } | ||
| fullContent += chunk; | ||
| } | ||
| fullContent += chunk; | ||
| } | ||
| else { | ||
| // Non-streaming mode (file output, includes token usage) | ||
| const response = await client.generateCompletion({ | ||
| messages, | ||
| temperature, | ||
| maxTokens: options.maxTokens, | ||
| }); | ||
| fullContent = response.choices[0].message.content; | ||
| usage = response.usage || null; | ||
| } | ||
| } | ||
@@ -139,3 +165,3 @@ catch (error) { | ||
| model: config.apiModel, | ||
| stream: true, | ||
| stream: useStreaming, | ||
| error: errorMessage, | ||
@@ -145,4 +171,4 @@ }); | ||
| } | ||
| // Ensure newline at end (only when outputting to stdout) | ||
| if (!suppressOutput && !fullContent.endsWith('\n')) { | ||
| // Ensure newline at end (only when outputting to stdout in streaming mode) | ||
| if (useStreaming && !suppressOutput && !fullContent.endsWith('\n')) { | ||
| process.stdout.write('\n'); | ||
@@ -219,3 +245,3 @@ } | ||
| } | ||
| // Log usage (streaming doesn't return token counts) | ||
| // Log usage (non-streaming mode includes token counts) | ||
| await logUsage({ | ||
@@ -226,4 +252,4 @@ profile: options.profile || null, | ||
| model: config.apiModel, | ||
| stream: true, | ||
| usage: null, | ||
| stream: useStreaming, | ||
| usage: usage, | ||
| }); | ||
@@ -230,0 +256,0 @@ } |
@@ -19,2 +19,3 @@ /** | ||
| -l, --language <lang> Language for execution (python, node, bash) | ||
| -m, --max-tokens <num> Maximum tokens (default: 20000, GLM max: 20K) | ||
| -x, --exec Execute generated code after security check | ||
@@ -27,3 +28,4 @@ --force Bypass security check (not recommended) | ||
| init [-g] Initialize configuration (local or global) | ||
| stats [--monthly] Show usage statistics | ||
| stats [--monthly] Show usage statistics (daily by default) | ||
| usage [--monthly] Alias for stats command | ||
| version Show version | ||
@@ -30,0 +32,0 @@ help Show this help |
@@ -58,12 +58,14 @@ /** | ||
| /** | ||
| * Format date for grouping | ||
| * Format date for grouping (using local timezone) | ||
| */ | ||
| function formatDateKey(date, period) { | ||
| // Use local timezone instead of UTC | ||
| const year = date.getFullYear(); | ||
| const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
| const day = String(date.getDate()).padStart(2, '0'); | ||
| if (period === 'daily') { | ||
| return date.toISOString().split('T')[0]; // YYYY-MM-DD | ||
| return `${year}-${month}-${day}`; // YYYY-MM-DD in local timezone | ||
| } | ||
| else { | ||
| const year = date.getFullYear(); | ||
| const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
| return `${year}-${month}`; // YYYY-MM | ||
| return `${year}-${month}`; // YYYY-MM in local timezone | ||
| } | ||
@@ -70,0 +72,0 @@ } |
@@ -10,3 +10,3 @@ /** | ||
| export declare const DEFAULT_TEMPERATURE = 0.7; | ||
| export declare const DEFAULT_MAX_TOKENS = 4096; | ||
| export declare const DEFAULT_MAX_TOKENS = 20000; | ||
| /** | ||
@@ -13,0 +13,0 @@ * Timeout values (milliseconds) |
@@ -11,3 +11,3 @@ /** | ||
| export const DEFAULT_TEMPERATURE = 0.7; | ||
| export const DEFAULT_MAX_TOKENS = 4096; | ||
| export const DEFAULT_MAX_TOKENS = 20000; // GLM supports up to 20K tokens | ||
| /** | ||
@@ -14,0 +14,0 @@ * Timeout values (milliseconds) |
@@ -101,2 +101,3 @@ /** | ||
| dryRun?: boolean; | ||
| maxTokens?: number; | ||
| } | ||
@@ -103,0 +104,0 @@ /** |
+1
-1
| { | ||
| "name": "glm-coding", | ||
| "version": "0.6.0", | ||
| "version": "0.7.0", | ||
| "description": "GLM CLI - AI Code Generator with streaming output", | ||
@@ -5,0 +5,0 @@ "type": "module", |
+53
-4
@@ -150,5 +150,6 @@ # GLM CLI - AI Code Generator | ||
| -q, --query <prompt> Query prompt (required if no pipe) | ||
| -o, --output <file> Save output to file (suppresses code output) | ||
| -o, --output <file> Save output to file (enables token tracking) | ||
| -p, --profile <name> Use specific profile | ||
| -l, --language <lang> Language for execution (python, node, bash) | ||
| -m, --max-tokens <num> Maximum tokens (default: 20000, GLM max: 20K) | ||
| -x, --exec Execute generated code after security check | ||
@@ -167,2 +168,4 @@ --force Bypass security check (not recommended) | ||
| glm stats --monthly Show monthly statistics | ||
| glm usage Alias for stats command | ||
| glm usage --monthly Monthly statistics (alias) | ||
| glm version Show version | ||
@@ -332,7 +335,9 @@ glm help Show help | ||
| ```bash | ||
| # View 5-hour usage + daily stats | ||
| # View 5-hour usage + daily stats (both commands work) | ||
| glm stats | ||
| glm usage | ||
| # View monthly stats | ||
| glm stats --monthly | ||
| glm usage --monthly | ||
| ``` | ||
@@ -342,6 +347,6 @@ | ||
| - **5-Hour Usage Window**: Current usage vs plan limit with progress bar | ||
| - **Historical Stats**: Daily/monthly aggregated data | ||
| - **Historical Stats**: Daily/monthly aggregated data (in your local timezone) | ||
| - **Profile breakdown**: Top 5 profiles used | ||
| - Request counts (total, successful, failed) | ||
| - Token usage (prompt, completion, total) | ||
| - **Token usage** (prompt, completion, total) - **NEW in v0.7.0** | ||
@@ -352,2 +357,46 @@ **Log locations:** | ||
| ### Token Usage Tracking (NEW in v0.7.0) | ||
| **Automatic token tracking when using `-o` flag:** | ||
| ```bash | ||
| # This captures token usage statistics | ||
| glm -q "create API client" -o api.py | ||
| # Check usage | ||
| glm stats | ||
| ``` | ||
| **Output example:** | ||
| ``` | ||
| Date Requests Success Failed Total Tokens Prompt Completion | ||
| ──────────────────────────────────────────────────────────────────────────────── | ||
| 2024-12-10 10 10 0 45,231 32,148 13,083 | ||
| ``` | ||
| **How it works:** | ||
| - **Interactive mode** (`glm -q "prompt"`): Streaming output, no token tracking | ||
| - **File output mode** (`glm -q "prompt" -o file.py`): Non-streaming, **captures token usage** | ||
| - No configuration needed - automatically optimizes for each use case | ||
| ### Controlling Output Length (NEW in v0.7.0) | ||
| **Use `--max-tokens` to control output size and costs:** | ||
| ```bash | ||
| # Limit to 1000 tokens (good for simple functions) | ||
| glm -q "simple validation function" -o validator.py -m 1000 | ||
| # Use full capacity for complex files (default: 20000) | ||
| glm -q "comprehensive REST API" -o api.py -m 20000 | ||
| # Default is 20K, so no flag needed for complex tasks | ||
| glm -q "large application" -o app.py | ||
| ``` | ||
| **Benefits:** | ||
| - **Cost control**: Limit tokens for simple tasks | ||
| - **No truncation**: Default 20K handles complex files (increased from 4K) | ||
| - **Flexible**: Override per-request based on complexity | ||
| ## Project Structure | ||
@@ -354,0 +403,0 @@ |
| # GLM Code Generation | ||
| - `@glm`, `-glm`, `--glm` in prompt → Auto-triggers GLM mode (hook) | ||
| - `/glm TASK` → Explicit GLM command | ||
| - Always use `-o` for direct file save | ||
| - 'GLM -q {CODE GENERATION TASK}' returns the entire code as stdout | ||
| - USE '-l {python|node|bash}' to specify the language | ||
| - Use '-o {path/filename}' for direct file save | ||
| - GLM can only generate codes, no documents |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
143413
2.43%3051
1.06%567
9.46%