opencode-glm-quota 1.3.0 → 1.3.2
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
|
@@ -21,22 +21,37 @@ OpenCode plugin to query Z.ai GLM Coding Plan usage statistics with real-time qu
|
|
|
21
21
|
### Option 1: npm (Recommended)
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
# Install
|
|
25
|
-
npm install
|
|
24
|
+
# Install plugin
|
|
25
|
+
npm install opencode-glm-quota
|
|
26
26
|
|
|
27
|
-
# Run
|
|
28
|
-
npx
|
|
29
|
-
|
|
30
|
-
# Add to your OpenCode config (~/.config/opencode/opencode.json)
|
|
31
|
-
echo '"@opencode-glm-quota/plugin"' >> ~/.config/opencode/opencode.json
|
|
27
|
+
# Run installer to configure OpenCode
|
|
28
|
+
npx opencode-glm-quota install
|
|
32
29
|
```
|
|
33
30
|
|
|
34
31
|
**What the installer does:**
|
|
35
32
|
- Copies `/glm_quota` command to `~/.config/opencode/command/glm_quota.md`
|
|
36
|
-
- Copies skill documentation to `~/.config/opencode/
|
|
33
|
+
- Copies skill documentation to `~/.config/opencode/skills/glm-quota/SKILL.md`
|
|
34
|
+
- Automatically adds plugin to your OpenCode config
|
|
37
35
|
- Merges agent configuration into `~/.config/opencode/opencode.json`
|
|
38
36
|
- Supports `--force` flag to overwrite existing files
|
|
39
37
|
|
|
38
|
+
### Uninstall
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Remove OpenCode integration files and config
|
|
42
|
+
npx opencode-glm-quota uninstall
|
|
43
|
+
|
|
44
|
+
# If installed globally
|
|
45
|
+
npx opencode-glm-quota uninstall --global
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**What the uninstaller does:**
|
|
49
|
+
- Removes `/glm_quota` command
|
|
50
|
+
- Deletes `skills/glm-quota/SKILL.md`
|
|
51
|
+
- Removes plugin entry from OpenCode config
|
|
52
|
+
- Removes `glm-quota-exec` agent config
|
|
53
|
+
- Runs `npm remove opencode-glm-quota` (or `--global`)
|
|
54
|
+
|
|
40
55
|
### Option 2: From GitHub
|
|
41
56
|
|
|
42
57
|
```bash
|
|
@@ -227,7 +242,7 @@ npm run prepublishOnly
|
|
|
227
242
|
|
|
228
243
|
```
|
|
229
244
|
src/
|
|
230
|
-
index.ts # Main plugin entry point
|
|
245
|
+
index.ts # Main plugin entry point
|
|
231
246
|
api/
|
|
232
247
|
client.ts # HTTPS client with timeout and error handling
|
|
233
248
|
endpoints.ts # Platform-specific API endpoints
|
|
@@ -236,16 +251,16 @@ src/
|
|
|
236
251
|
date-formatter.ts # Date/time formatting utilities
|
|
237
252
|
progress-bar.ts # ASCII progress bar rendering
|
|
238
253
|
time-window.ts # Rolling window calculation
|
|
239
|
-
integration/
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
bin/
|
|
244
|
-
|
|
245
|
-
dist/ # Compiled JavaScript (generated)
|
|
246
|
-
tests/ # Test suite
|
|
247
|
-
package.json # Dependencies and scripts
|
|
248
|
-
tsconfig.json # TypeScript configuration
|
|
254
|
+
integration/
|
|
255
|
+
command/glm_quota.md # /glm_quota slash command
|
|
256
|
+
skills/glm-quota/SKILL.md # Skill documentation
|
|
257
|
+
opencode.jsonc # Agent configuration (JSONC)
|
|
258
|
+
bin/
|
|
259
|
+
install.js # Installation script
|
|
260
|
+
dist/ # Compiled JavaScript (generated)
|
|
261
|
+
tests/ # Test suite
|
|
262
|
+
package.json # Dependencies and scripts
|
|
263
|
+
tsconfig.json # TypeScript configuration
|
|
249
264
|
```
|
|
250
265
|
|
|
251
266
|
### Code Style Guidelines
|
package/bin/install.js
CHANGED
|
@@ -9,11 +9,13 @@
|
|
|
9
9
|
* Usage:
|
|
10
10
|
* node bin/install.js # Interactive install (ask before overwriting)
|
|
11
11
|
* node bin/install.js --force # Force overwrite existing files
|
|
12
|
+
* node bin/install.js uninstall # Remove integration files and config
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import * as fs from 'fs'
|
|
15
16
|
import * as path from 'path'
|
|
16
17
|
import * as os from 'os'
|
|
18
|
+
import { spawnSync } from 'child_process'
|
|
17
19
|
import { parse as parseJsonc } from 'jsonc-parser'
|
|
18
20
|
|
|
19
21
|
// ==========================================
|
|
@@ -24,12 +26,12 @@ const __filename = decodeURIComponent(new URL(import.meta.url).pathname)
|
|
|
24
26
|
const __dirname = path.dirname(__filename)
|
|
25
27
|
const SOURCE_DIR = path.join(__dirname, '..', 'integration')
|
|
26
28
|
const COMMAND_FILE = path.join(SOURCE_DIR, 'command', 'glm_quota.md')
|
|
27
|
-
const SKILL_FILE = path.join(SOURCE_DIR, '
|
|
29
|
+
const SKILL_FILE = path.join(SOURCE_DIR, 'skills', 'glm-quota', 'SKILL.md')
|
|
28
30
|
const AGENT_CONFIG = path.join(SOURCE_DIR, 'opencode.jsonc')
|
|
29
31
|
|
|
30
32
|
const CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode')
|
|
31
33
|
const TARGET_COMMAND = path.join(CONFIG_DIR, 'command', 'glm_quota.md')
|
|
32
|
-
const TARGET_SKILL = path.join(CONFIG_DIR, '
|
|
34
|
+
const TARGET_SKILL = path.join(CONFIG_DIR, 'skills', 'glm-quota', 'SKILL.md')
|
|
33
35
|
|
|
34
36
|
// Check which config file exists (opencode.json or opencode.jsonc)
|
|
35
37
|
const TARGET_CONFIG_JSON = path.join(CONFIG_DIR, 'opencode.json')
|
|
@@ -72,6 +74,30 @@ function copyFile(source, destination) {
|
|
|
72
74
|
fs.copyFileSync(source, destination)
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Remove file if it exists
|
|
79
|
+
*/
|
|
80
|
+
function removeFile(filePath, label) {
|
|
81
|
+
if (fileExists(filePath)) {
|
|
82
|
+
fs.unlinkSync(filePath)
|
|
83
|
+
console.log(` ✓ Removed ${label}`)
|
|
84
|
+
} else {
|
|
85
|
+
console.log(` ⊙ Not found ${label}`)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Remove directory if it exists
|
|
91
|
+
*/
|
|
92
|
+
function removeDirectory(dirPath, label) {
|
|
93
|
+
if (fileExists(dirPath)) {
|
|
94
|
+
fs.rmSync(dirPath, { recursive: true, force: true })
|
|
95
|
+
console.log(` ✓ Removed ${label}`)
|
|
96
|
+
} else {
|
|
97
|
+
console.log(` ⊙ Not found ${label}`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
75
101
|
/**
|
|
76
102
|
* Parse JSON or JSONC file
|
|
77
103
|
*/
|
|
@@ -144,14 +170,14 @@ function installCommand(force) {
|
|
|
144
170
|
*/
|
|
145
171
|
function installSkill(force) {
|
|
146
172
|
if (fileExists(TARGET_SKILL) && !force) {
|
|
147
|
-
if (!promptConfirm(`Skill
|
|
173
|
+
if (!promptConfirm(`Skill directory exists: ${path.dirname(TARGET_SKILL)}\nOverwrite?`)) {
|
|
148
174
|
console.log(` ⊘ Skipped ${TARGET_SKILL}`)
|
|
149
175
|
return
|
|
150
176
|
}
|
|
151
177
|
}
|
|
152
178
|
|
|
153
179
|
copyFile(SKILL_FILE, TARGET_SKILL)
|
|
154
|
-
console.log(` ✓ Created ${TARGET_SKILL}`)
|
|
180
|
+
console.log(` ✓ Created ${path.join(path.basename(path.dirname(TARGET_SKILL)), path.basename(TARGET_SKILL))}`)
|
|
155
181
|
}
|
|
156
182
|
|
|
157
183
|
/**
|
|
@@ -162,36 +188,125 @@ function mergeConfig() {
|
|
|
162
188
|
let existingConfig = {}
|
|
163
189
|
if (fileExists(TARGET_CONFIG)) {
|
|
164
190
|
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
|
+
}
|
|
165
195
|
}
|
|
166
196
|
|
|
167
197
|
// Parse new agent config from integration
|
|
168
198
|
const newConfig = parseConfig(AGENT_CONFIG)
|
|
169
199
|
|
|
170
|
-
|
|
171
|
-
const mergedConfig = deepMerge(existingConfig, newConfig)
|
|
200
|
+
const PLUGIN_NAME = 'opencode-glm-quota'
|
|
172
201
|
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
202
|
+
// Handle both "plugin" array and "agent" section
|
|
203
|
+
// Check for "plugin" array first (user's config uses this)
|
|
204
|
+
const pluginArrayName = existingConfig.plugin ? 'plugin' : 'plugins'
|
|
205
|
+
|
|
206
|
+
// Only ensure that array we're going to use exists, not both!
|
|
207
|
+
if (!existingConfig[pluginArrayName]) {
|
|
208
|
+
existingConfig[pluginArrayName] = []
|
|
176
209
|
}
|
|
177
210
|
|
|
178
|
-
const
|
|
179
|
-
|
|
211
|
+
const plugins = Array.isArray(existingConfig[pluginArrayName]) ? existingConfig[pluginArrayName] : []
|
|
212
|
+
|
|
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
|
+
}
|
|
180
222
|
|
|
181
223
|
// Only add if not already present
|
|
182
224
|
if (!plugins.includes(PLUGIN_NAME)) {
|
|
183
225
|
plugins.push(PLUGIN_NAME)
|
|
184
|
-
|
|
185
|
-
console.log(` ✓ Added ${PLUGIN_NAME} to
|
|
226
|
+
existingConfig[pluginArrayName] = plugins
|
|
227
|
+
console.log(` ✓ Added ${PLUGIN_NAME} to ${pluginArrayName} array`)
|
|
186
228
|
} else {
|
|
187
|
-
console.log(` ⊙ Plugin ${PLUGIN_NAME} already in
|
|
229
|
+
console.log(` ⊙ Plugin ${PLUGIN_NAME} already in ${pluginArrayName} array`)
|
|
188
230
|
}
|
|
189
231
|
|
|
190
|
-
// Write merged config back to
|
|
191
|
-
writeConfig(TARGET_CONFIG,
|
|
232
|
+
// Write merged config back to same file (opencode.json or opencode.jsonc)
|
|
233
|
+
writeConfig(TARGET_CONFIG, existingConfig)
|
|
192
234
|
console.log(` ✓ Merged configuration into ${path.basename(TARGET_CONFIG)}`)
|
|
193
235
|
}
|
|
194
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Remove plugin configuration and agent configuration
|
|
239
|
+
*/
|
|
240
|
+
function removeConfig() {
|
|
241
|
+
if (!fileExists(TARGET_CONFIG)) {
|
|
242
|
+
console.log(` ⊙ Config not found: ${TARGET_CONFIG}`)
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const PLUGIN_NAME = 'opencode-glm-quota'
|
|
247
|
+
const existingConfig = parseConfig(TARGET_CONFIG)
|
|
248
|
+
let changed = false
|
|
249
|
+
|
|
250
|
+
if (Array.isArray(existingConfig.plugin)) {
|
|
251
|
+
const next = existingConfig.plugin.filter((name) => name !== PLUGIN_NAME)
|
|
252
|
+
if (next.length !== existingConfig.plugin.length) {
|
|
253
|
+
existingConfig.plugin = next
|
|
254
|
+
changed = true
|
|
255
|
+
console.log(' ✓ Removed plugin from plugin array')
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (Array.isArray(existingConfig.plugins)) {
|
|
260
|
+
const next = existingConfig.plugins.filter((name) => name !== PLUGIN_NAME)
|
|
261
|
+
if (next.length !== existingConfig.plugins.length) {
|
|
262
|
+
existingConfig.plugins = next
|
|
263
|
+
changed = true
|
|
264
|
+
console.log(' ✓ Removed plugin from plugins array')
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (existingConfig.agent && existingConfig.agent['glm-quota-exec']) {
|
|
269
|
+
delete existingConfig.agent['glm-quota-exec']
|
|
270
|
+
if (Object.keys(existingConfig.agent).length === 0) {
|
|
271
|
+
delete existingConfig.agent
|
|
272
|
+
}
|
|
273
|
+
changed = true
|
|
274
|
+
console.log(' ✓ Removed glm-quota-exec agent config')
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (changed) {
|
|
278
|
+
writeConfig(TARGET_CONFIG, existingConfig)
|
|
279
|
+
console.log(` ✓ Updated ${path.basename(TARGET_CONFIG)}`)
|
|
280
|
+
} else {
|
|
281
|
+
console.log(' ⊙ No config changes needed')
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Remove npm package
|
|
287
|
+
*/
|
|
288
|
+
function removePackage(globalFlag) {
|
|
289
|
+
const args = ['remove', 'opencode-glm-quota']
|
|
290
|
+
if (globalFlag) {
|
|
291
|
+
args.push('--global')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const result = spawnSync('npm', args, { stdio: 'inherit' })
|
|
295
|
+
if (result.status !== 0) {
|
|
296
|
+
console.log(' ⊙ npm remove failed, remove manually if needed')
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Uninstall integration files and configuration
|
|
302
|
+
*/
|
|
303
|
+
function uninstall(globalFlag) {
|
|
304
|
+
removeFile(TARGET_COMMAND, TARGET_COMMAND)
|
|
305
|
+
removeDirectory(path.dirname(TARGET_SKILL), path.dirname(TARGET_SKILL))
|
|
306
|
+
removeConfig()
|
|
307
|
+
removePackage(globalFlag)
|
|
308
|
+
}
|
|
309
|
+
|
|
195
310
|
// ==========================================
|
|
196
311
|
// MAIN INSTALLATION FUNCTION
|
|
197
312
|
// ==========================================
|
|
@@ -203,7 +318,17 @@ function main() {
|
|
|
203
318
|
try {
|
|
204
319
|
// Parse command line arguments
|
|
205
320
|
const args = process.argv.slice(2)
|
|
321
|
+
const isUninstall = args.includes('uninstall')
|
|
206
322
|
const forceFlag = args.includes('--force')
|
|
323
|
+
const globalFlag = args.includes('--global') || args.includes('-g')
|
|
324
|
+
|
|
325
|
+
if (isUninstall) {
|
|
326
|
+
console.log('✓ Uninstalling GLM Quota Plugin...\n')
|
|
327
|
+
uninstall(globalFlag)
|
|
328
|
+
console.log()
|
|
329
|
+
console.log('✓ Uninstall complete!')
|
|
330
|
+
return
|
|
331
|
+
}
|
|
207
332
|
|
|
208
333
|
console.log('✓ Installing GLM Quota Plugin...\n')
|
|
209
334
|
|
|
@@ -224,6 +349,4 @@ function main() {
|
|
|
224
349
|
}
|
|
225
350
|
|
|
226
351
|
// Run installer
|
|
227
|
-
|
|
228
|
-
main()
|
|
229
|
-
}
|
|
352
|
+
main()
|
|
@@ -34,8 +34,8 @@ 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);
|
|
37
|
+
const bar = createProgressBar(percentage, { width: 26 });
|
|
38
38
|
const pctStr = formatPercentage(percentage).padStart(6);
|
|
39
|
-
const labelStr = label.padEnd(20);
|
|
39
|
+
const labelStr = label.slice(0, 20).padEnd(20);
|
|
40
40
|
return `${labelStr} [${bar}] ${pctStr}`;
|
|
41
41
|
}
|
|
@@ -4,14 +4,7 @@
|
|
|
4
4
|
"glm-quota-exec": {
|
|
5
5
|
"mode": "subagent",
|
|
6
6
|
"system": "You are a minimal tool executor. Your only purpose is to execute the glm_quota tool when requested. Do not explain, reason, or add any commentary. Simply call the tool and return its output directly.",
|
|
7
|
-
"provider": "opencode",
|
|
8
|
-
"options": {
|
|
9
|
-
"system": "You are a minimal tool executor. Your only purpose is to execute the glm_quota tool when requested. Do not explain, reason, or add any commentary. Simply call the tool and return its output directly.",
|
|
10
|
-
"provider": "opencode"
|
|
11
|
-
},
|
|
12
7
|
"permission": {}
|
|
13
8
|
}
|
|
14
9
|
}
|
|
15
|
-
// Note: This agent definition is merged into user's existing OpenCode config
|
|
16
|
-
// by the installer script to avoid overwriting their custom configurations
|
|
17
10
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-glm-quota",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
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",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"opencode-glm-quota
|
|
9
|
+
"opencode-glm-quota": "./bin/install.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@types/node": "^20.0.0",
|
|
62
62
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
63
63
|
"@typescript-eslint/parser": "^6.0.0",
|
|
64
|
-
"baseline-browser-mapping": "^2.9.
|
|
64
|
+
"baseline-browser-mapping": "^2.9.18",
|
|
65
65
|
"c8": "^10.1.3",
|
|
66
66
|
"eslint": "^8.0.0",
|
|
67
67
|
"tsx": "^4.0.0",
|
|
File without changes
|