opencode-glm-quota 1.3.4 → 1.4.0

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/README.md CHANGED
@@ -3,6 +3,12 @@
3
3
  [![npm version](https://img.shields.io/npm/v/opencode-glm-quota.svg)](https://www.npmjs.com/package/opencode-glm-quota)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Build Status](https://github.com/guyinwonder168/opencode-glm-quota/workflows/CI/badge.svg)](https://github.com/guyinwonder168/opencode-glm-quota/actions)
6
+ [![SonarQube Cloud](https://sonarcloud.io/images/project_badges/sonarcloud-light.svg)](https://sonarcloud.io/summary/new_code?id=guyinwonder168_opencode-glm-quota)
7
+ ---
8
+ [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=guyinwonder168_opencode-glm-quota&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=guyinwonder168_opencode-glm-quota)
9
+ [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=guyinwonder168_opencode-glm-quota&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=guyinwonder168_opencode-glm-quota)
10
+ [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=guyinwonder168_opencode-glm-quota&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=guyinwonder168_opencode-glm-quota)
11
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=guyinwonder168_opencode-glm-quota&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=guyinwonder168_opencode-glm-quota)
6
12
 
7
13
  OpenCode plugin to query Z.ai GLM Coding Plan usage statistics with real-time quota monitoring, model usage tracking, and MCP tool usage.
8
14
 
@@ -32,7 +38,7 @@ npx opencode-glm-quota install
32
38
  - Copies `/glm_quota` command to `~/.config/opencode/command/glm_quota.md`
33
39
  - Copies skill documentation to `~/.config/opencode/skills/glm-quota/SKILL.md`
34
40
  - Automatically adds plugin to your OpenCode config
35
- - Merges agent configuration into `~/.config/opencode/opencode.json`
41
+ - Copies agent to `~/.config/opencode/agents/`
36
42
  - Supports `--force` flag to overwrite existing files
37
43
 
38
44
  ### Uninstall
@@ -49,7 +55,7 @@ npx opencode-glm-quota uninstall --global
49
55
  - Removes `/glm_quota` command
50
56
  - Deletes `skills/glm-quota/SKILL.md`
51
57
  - Removes plugin entry from OpenCode config
52
- - Removes `glm-quota-exec` agent config
58
+ - Removes agent file and legacy config
53
59
  - Runs `npm remove opencode-glm-quota` (or `--global`)
54
60
 
55
61
  ### Option 2: From GitHub
@@ -252,9 +258,9 @@ src/
252
258
  progress-bar.ts # ASCII progress bar rendering
253
259
  time-window.ts # Rolling window calculation
254
260
  integration/
261
+ agents/glm-quota-exec.md # Minimal executor agent (Markdown)
255
262
  command/glm_quota.md # /glm_quota slash command
256
263
  skills/glm-quota/SKILL.md # Skill documentation
257
- opencode.jsonc # Agent configuration (JSONC)
258
264
  bin/
259
265
  install.js # Installation script
260
266
  dist/ # Compiled JavaScript (generated)
package/bin/install.js CHANGED
@@ -27,11 +27,12 @@ const __dirname = path.dirname(__filename)
27
27
  const SOURCE_DIR = path.join(__dirname, '..', 'integration')
28
28
  const COMMAND_FILE = path.join(SOURCE_DIR, 'command', 'glm_quota.md')
29
29
  const SKILL_FILE = path.join(SOURCE_DIR, 'skills', 'glm-quota', 'SKILL.md')
30
- const AGENT_CONFIG = path.join(SOURCE_DIR, 'opencode.jsonc')
30
+ const AGENT_FILE = path.join(SOURCE_DIR, 'agents', 'glm-quota-exec.md')
31
31
 
32
32
  const CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode')
33
33
  const TARGET_COMMAND = path.join(CONFIG_DIR, 'command', 'glm_quota.md')
34
34
  const TARGET_SKILL = path.join(CONFIG_DIR, 'skills', 'glm-quota', 'SKILL.md')
35
+ const TARGET_AGENT = path.join(CONFIG_DIR, 'agents', 'glm-quota-exec.md')
35
36
 
36
37
  // Check which config file exists (opencode.json or opencode.jsonc)
37
38
  const TARGET_CONFIG_JSON = path.join(CONFIG_DIR, 'opencode.json')
@@ -181,25 +182,42 @@ function installSkill(force) {
181
182
  }
182
183
 
183
184
  /**
184
- * Merge agent configuration and add plugin to plugins array
185
+ * Install agent file
185
186
  */
186
- function mergeConfig() {
187
- // Parse existing config if it exists (same file type will be written)
187
+ function installAgent(force) {
188
+ if (fileExists(TARGET_AGENT) && !force) {
189
+ if (!promptConfirm(`Agent file exists: ${TARGET_AGENT}\nOverwrite?`)) {
190
+ console.log(` ⊘ Skipped ${TARGET_AGENT}`)
191
+ return
192
+ }
193
+ }
194
+
195
+ copyFile(AGENT_FILE, TARGET_AGENT)
196
+ console.log(` ✓ Created ${TARGET_AGENT}`)
197
+ }
198
+
199
+ /**
200
+ * Update plugin configuration and cleanup old JSON agent
201
+ */
202
+ function updatePluginConfig() {
203
+ // Parse existing config if it exists
188
204
  let existingConfig = {}
189
205
  if (fileExists(TARGET_CONFIG)) {
190
206
  existingConfig = parseConfig(TARGET_CONFIG)
191
- // REMOVE old 'options' field to prevent verbose agent output
192
- if (existingConfig.agent?.['glm-quota-exec']?.options) {
193
- delete existingConfig.agent['glm-quota-exec'].options
194
- }
195
207
  }
196
208
 
197
- // Parse new agent config from integration
198
- const newConfig = parseConfig(AGENT_CONFIG)
199
-
200
209
  const PLUGIN_NAME = 'opencode-glm-quota'
201
210
 
202
- // Handle both "plugin" array and "agent" section
211
+ // CLEANUP: Remove old JSON agent config if it exists (migration from v1.3.x)
212
+ if (existingConfig.agent && existingConfig.agent['glm-quota-exec']) {
213
+ delete existingConfig.agent['glm-quota-exec']
214
+ if (Object.keys(existingConfig.agent).length === 0) {
215
+ delete existingConfig.agent
216
+ }
217
+ console.log(' ✓ Removed old JSON agent config (migrated to Markdown)')
218
+ }
219
+
220
+ // Handle both "plugin" array and "plugins" array
203
221
  // Check for "plugin" array first (user's config uses this)
204
222
  const pluginArrayName = existingConfig.plugin ? 'plugin' : 'plugins'
205
223
 
@@ -210,16 +228,6 @@ function mergeConfig() {
210
228
 
211
229
  const plugins = Array.isArray(existingConfig[pluginArrayName]) ? existingConfig[pluginArrayName] : []
212
230
 
213
- // REPLACE entire glm-quota-exec agent (not merge, to remove old redundant fields)
214
- if (newConfig.agent && newConfig.agent['glm-quota-exec']) {
215
- if (!existingConfig.agent) {
216
- existingConfig.agent = {}
217
- }
218
- existingConfig.agent['glm-quota-exec'] = newConfig.agent['glm-quota-exec']
219
- } else if (!existingConfig.agent && newConfig.agent) {
220
- existingConfig.agent = newConfig.agent
221
- }
222
-
223
231
  // Only add if not already present
224
232
  if (!plugins.includes(PLUGIN_NAME)) {
225
233
  plugins.push(PLUGIN_NAME)
@@ -229,9 +237,9 @@ function mergeConfig() {
229
237
  console.log(` ⊙ Plugin ${PLUGIN_NAME} already in ${pluginArrayName} array`)
230
238
  }
231
239
 
232
- // Write merged config back to same file (opencode.json or opencode.jsonc)
240
+ // Write config back to same file (opencode.json or opencode.jsonc)
233
241
  writeConfig(TARGET_CONFIG, existingConfig)
234
- console.log(` ✓ Merged configuration into ${path.basename(TARGET_CONFIG)}`)
242
+ console.log(` ✓ Updated ${path.basename(TARGET_CONFIG)}`)
235
243
  }
236
244
 
237
245
  /**
@@ -303,6 +311,7 @@ function removePackage(globalFlag) {
303
311
  function uninstall(globalFlag) {
304
312
  removeFile(TARGET_COMMAND, TARGET_COMMAND)
305
313
  removeDirectory(path.dirname(TARGET_SKILL), path.dirname(TARGET_SKILL))
314
+ removeFile(TARGET_AGENT, TARGET_AGENT)
306
315
  removeConfig()
307
316
  removePackage(globalFlag)
308
317
  }
@@ -335,7 +344,8 @@ function main() {
335
344
  // Install integration files
336
345
  installCommand(forceFlag)
337
346
  installSkill(forceFlag)
338
- mergeConfig()
347
+ installAgent(forceFlag)
348
+ updatePluginConfig()
339
349
 
340
350
  console.log()
341
351
  console.log('✓ Installation complete!')
@@ -34,7 +34,7 @@ export function formatPercentage(percentage, decimals = 1) {
34
34
  * @returns Formatted progress bar line
35
35
  */
36
36
  export function formatProgressLine(label, percentage) {
37
- const bar = createProgressBar(percentage, { width: 11 });
37
+ const bar = createProgressBar(percentage, { width: 12 });
38
38
  const pctStr = formatPercentage(percentage).padStart(6);
39
39
  const labelStr = label.slice(0, 20).padEnd(20);
40
40
  return `${labelStr} [${bar}] ${pctStr}`;
@@ -0,0 +1,20 @@
1
+ ---
2
+ description: Minimal executor for GLM quota tool
3
+ mode: subagent
4
+ hidden: true
5
+ permission:
6
+ edit: deny
7
+ bash: deny
8
+ ---
9
+
10
+ CRITICAL INSTRUCTION: When the glm_quota tool returns output, you MUST return it EXACTLY as received, character-for-character, with NO modifications.
11
+
12
+ - Do NOT add introductory text
13
+ - Do NOT summarize
14
+ - Do NOT reformat
15
+ - Do NOT explain anything
16
+ - Do NOT add any commentary
17
+ - Return ONLY the raw string from the tool
18
+
19
+ Example of WRONG behavior: 'Here is your usage: [summary]'
20
+ Example of CORRECT behavior: [paste entire tool output verbatim]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-glm-quota",
3
- "version": "1.3.4",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin to query Z.ai GLM Coding Plan usage statistics including quota limits, model usage, and MCP tool usage",
6
6
  "main": "dist/index.js",
@@ -1,10 +0,0 @@
1
- {
2
- "$schema": "https://opencode.ai/config.json",
3
- "agent": {
4
- "glm-quota-exec": {
5
- "mode": "subagent",
6
- "system": "CRITICAL INSTRUCTION: When the glm_quota tool returns output, you MUST return it EXACTLY as received, character-for-character, with NO modifications.\n\n- Do NOT add introductory text\n- Do NOT summarize\n- Do NOT reformat\n- Do NOT explain anything\n- Do NOT add any commentary\n- Return ONLY the raw string from the tool\n\nExample of WRONG behavior: 'Here is your usage: [summary]'\nExample of CORRECT behavior: [paste entire tool output verbatim]",
7
- "permission": {}
8
- }
9
- }
10
- }