opencode-glm-quota 1.3.2 → 1.3.4

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/dist/index.js CHANGED
@@ -249,7 +249,95 @@ function formatToolUsage(data, quotaData) {
249
249
  * @returns Formatted line with box characters
250
250
  */
251
251
  function formatBoxLine(content, lineIndent) {
252
- return '║ ' + content.padEnd(lineIndent) + '║';
252
+ const trimmed = trimToDisplayWidth(content, lineIndent, 0);
253
+ const padding = Math.max(lineIndent - getDisplayWidth(trimmed), 0);
254
+ return '║ ' + trimmed + ' '.repeat(padding) + '║';
255
+ }
256
+ function formatProgressBoxLine(content, lineIndent) {
257
+ const gap = 2;
258
+ const contentWidth = Math.max(lineIndent - gap, 0);
259
+ const trimmed = trimToDisplayWidth(content, contentWidth, 0);
260
+ const padding = Math.max(contentWidth - getDisplayWidth(trimmed), 0);
261
+ return '║ ' + trimmed + ' '.repeat(padding + gap) + '║';
262
+ }
263
+ function getDisplayWidth(text) {
264
+ let width = 0;
265
+ for (let i = 0; i < text.length; i += 1) {
266
+ const codePoint = text.codePointAt(i);
267
+ if (codePoint === undefined) {
268
+ continue;
269
+ }
270
+ if (codePoint > 0xffff) {
271
+ i += 1;
272
+ }
273
+ if (isControlCodePoint(codePoint) || isZeroWidthCodePoint(codePoint)) {
274
+ continue;
275
+ }
276
+ width += isEmojiCodePoint(codePoint) || isFullWidthCodePoint(codePoint) ? 2 : 1;
277
+ }
278
+ return width;
279
+ }
280
+ function trimToDisplayWidth(text, maxWidth, reserveRightPadding) {
281
+ let width = 0;
282
+ let result = '';
283
+ const allowedWidth = Math.max(maxWidth - reserveRightPadding, 0);
284
+ for (let i = 0; i < text.length; i += 1) {
285
+ const codePoint = text.codePointAt(i);
286
+ if (codePoint === undefined) {
287
+ continue;
288
+ }
289
+ if (codePoint > 0xffff) {
290
+ i += 1;
291
+ }
292
+ if (isControlCodePoint(codePoint) || isZeroWidthCodePoint(codePoint)) {
293
+ continue;
294
+ }
295
+ const charWidth = isEmojiCodePoint(codePoint) || isFullWidthCodePoint(codePoint) ? 2 : 1;
296
+ if (width + charWidth > allowedWidth) {
297
+ break;
298
+ }
299
+ result += String.fromCodePoint(codePoint);
300
+ width += charWidth;
301
+ }
302
+ return result;
303
+ }
304
+ function isControlCodePoint(codePoint) {
305
+ return codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f);
306
+ }
307
+ function isZeroWidthCodePoint(codePoint) {
308
+ return (codePoint === 0x200d ||
309
+ codePoint === 0xfe0f ||
310
+ (codePoint >= 0xfe00 && codePoint <= 0xfe0f));
311
+ }
312
+ function isEmojiCodePoint(codePoint) {
313
+ return ((codePoint >= 0x1f300 && codePoint <= 0x1f5ff) ||
314
+ (codePoint >= 0x1f600 && codePoint <= 0x1f64f) ||
315
+ (codePoint >= 0x1f680 && codePoint <= 0x1f6ff) ||
316
+ (codePoint >= 0x1f700 && codePoint <= 0x1f77f) ||
317
+ (codePoint >= 0x1f780 && codePoint <= 0x1f7ff) ||
318
+ (codePoint >= 0x1f800 && codePoint <= 0x1f8ff) ||
319
+ (codePoint >= 0x1f900 && codePoint <= 0x1f9ff) ||
320
+ (codePoint >= 0x1fa00 && codePoint <= 0x1faff) ||
321
+ (codePoint >= 0x2600 && codePoint <= 0x26ff) ||
322
+ (codePoint >= 0x2700 && codePoint <= 0x27bf));
323
+ }
324
+ function isFullWidthCodePoint(codePoint) {
325
+ return (codePoint >= 0x1100 && (codePoint <= 0x115f ||
326
+ codePoint === 0x2329 ||
327
+ codePoint === 0x232a ||
328
+ (codePoint >= 0x2e80 && codePoint <= 0x3247 && codePoint !== 0x303f) ||
329
+ (codePoint >= 0x3250 && codePoint <= 0x4dbf) ||
330
+ (codePoint >= 0x4e00 && codePoint <= 0xa4c6) ||
331
+ (codePoint >= 0xa960 && codePoint <= 0xa97c) ||
332
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
333
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
334
+ (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||
335
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6b) ||
336
+ (codePoint >= 0xff01 && codePoint <= 0xff60) ||
337
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
338
+ (codePoint >= 0x1b000 && codePoint <= 0x1b001) ||
339
+ (codePoint >= 0x1f200 && codePoint <= 0x1f251) ||
340
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd)));
253
341
  }
254
342
  /**
255
343
  * Format header section
@@ -260,16 +348,16 @@ function formatBoxLine(content, lineIndent) {
260
348
  */
261
349
  function formatHeader(platformName, startTime, endTime) {
262
350
  const lines = [];
263
- const LINE_WIDTH = 60;
264
- lines.push('╔' + '═'.repeat(58) + '╗');
265
- lines.push('' + ' '.repeat(58) + '');
266
- lines.push('║' + ' Z.ai GLM Coding Plan Usage Statistics '.padStart(35).padEnd(58) + '║');
267
- lines.push('║' + ' '.repeat(58) + '║');
268
- lines.push('' + ''.repeat(58) + '');
269
- lines.push('║ Platform: ' + platformName.padEnd(LINE_WIDTH - 13 - 1) + '');
270
- const periodLine = '║ Period: ' + startTime + ' → ' + endTime;
271
- lines.push(periodLine.padEnd(LINE_WIDTH) + '║');
272
- lines.push('╠' + '═'.repeat(58) + '╣');
351
+ const LINE_CONTENT = 58;
352
+ const LINE_INDENT = 56;
353
+ lines.push('' + ''.repeat(LINE_CONTENT) + '');
354
+ lines.push('║' + ' '.repeat(LINE_CONTENT) + '║');
355
+ lines.push('║' + ' Z.ai GLM Coding Plan Usage Statistics '.padStart(35).padEnd(LINE_CONTENT) + '║');
356
+ lines.push('' + ' '.repeat(LINE_CONTENT) + '');
357
+ lines.push('' + '═'.repeat(LINE_CONTENT) + '');
358
+ lines.push(formatBoxLine(`Platform: ${platformName}`, LINE_INDENT));
359
+ lines.push(formatBoxLine(`Period: ${startTime} ${endTime}`, LINE_INDENT));
360
+ lines.push('╠' + '═'.repeat(LINE_CONTENT) + '╣');
273
361
  return lines;
274
362
  }
275
363
  /**
@@ -281,14 +369,14 @@ function formatQuotaLimits(quotaData) {
281
369
  const lines = [];
282
370
  const LINE_CONTENT = 58;
283
371
  const LINE_INDENT = 56;
284
- lines.push('║ 📊 QUOTA LIMITS' + ' '.repeat(LINE_CONTENT - 14) + '║');
285
- lines.push('╟' + '─'.repeat(58) + '╢');
372
+ lines.push(formatBoxLine('QUOTA LIMITS', LINE_INDENT));
373
+ lines.push('╟' + '─'.repeat(LINE_CONTENT) + '╢');
286
374
  const limits = quotaData?.limits;
287
375
  if (limits && Array.isArray(limits)) {
288
376
  for (const limit of limits) {
289
377
  const pct = typeof limit.percentage === 'number' ? limit.percentage : 0;
290
378
  const line = formatProgressLine(limit.type || 'Unknown', pct);
291
- lines.push(formatBoxLine(line, LINE_INDENT));
379
+ lines.push(formatProgressBoxLine(line, LINE_INDENT));
292
380
  if (limit.nextResetTime !== undefined) {
293
381
  const resetMsg = formatTimeUntilReset(limit.nextResetTime);
294
382
  if (resetMsg) {
@@ -302,9 +390,9 @@ function formatQuotaLimits(quotaData) {
302
390
  }
303
391
  }
304
392
  else {
305
- lines.push('No quota data available' + ' '.repeat(LINE_INDENT - 21) + '║');
393
+ lines.push(formatBoxLine('No quota data available', LINE_INDENT));
306
394
  }
307
- lines.push('╠' + '═'.repeat(58) + '╣');
395
+ lines.push('╠' + '═'.repeat(LINE_CONTENT) + '╣');
308
396
  return lines;
309
397
  }
310
398
  /**
@@ -319,8 +407,8 @@ function formatQuotaLimits(quotaData) {
319
407
  function formatDataSection(title, data, formatter, quotaData, noDataMessage, LINE_INDENT) {
320
408
  const lines = [];
321
409
  const LINE_CONTENT = 58;
322
- lines.push('║ ' + title + ' '.repeat(LINE_CONTENT - title.length) + '║');
323
- lines.push('╟' + '─'.repeat(58) + '╢');
410
+ lines.push(formatBoxLine(title, LINE_INDENT));
411
+ lines.push('╟' + '─'.repeat(LINE_CONTENT) + '╢');
324
412
  if (data) {
325
413
  const formattedLines = formatter(data, quotaData);
326
414
  for (const line of formattedLines) {
@@ -328,9 +416,9 @@ function formatDataSection(title, data, formatter, quotaData, noDataMessage, LIN
328
416
  }
329
417
  }
330
418
  else {
331
- lines.push('║ ' + noDataMessage + ' '.repeat(LINE_INDENT - noDataMessage.length) + '║');
419
+ lines.push(formatBoxLine(noDataMessage, LINE_INDENT));
332
420
  }
333
- lines.push('╠' + '═'.repeat(58) + '╣');
421
+ lines.push('╠' + '═'.repeat(LINE_CONTENT) + '╣');
334
422
  return lines;
335
423
  }
336
424
  /**
@@ -356,8 +444,8 @@ function formatOutput(platform, startTime, endTime, quotaData, modelData, toolDa
356
444
  const LINE_INDENT = 56;
357
445
  lines.push(...formatHeader(platformName, startTime, endTime));
358
446
  lines.push(...formatQuotaLimits(quotaData));
359
- lines.push(...formatDataSection('🤖 MODEL USAGE (24h)', modelData, formatModelUsage, quotaData, 'No model usage data available', LINE_INDENT));
360
- lines.push(...formatDataSection('🔧 TOOL/MCP USAGE (24h)', toolData, formatToolUsage, quotaData, 'No tool usage data available', LINE_INDENT));
447
+ lines.push(...formatDataSection('MODEL USAGE (24h)', modelData, formatModelUsage, quotaData, 'No model usage data available', LINE_INDENT));
448
+ lines.push(...formatDataSection('TOOL/MCP USAGE (24h)', toolData, formatToolUsage, quotaData, 'No tool usage data available', LINE_INDENT));
361
449
  lines.push(...formatFooter());
362
450
  return lines.join('\n');
363
451
  }
@@ -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, { width: 26 });
37
+ const bar = createProgressBar(percentage, { width: 11 });
38
38
  const pctStr = formatPercentage(percentage).padStart(6);
39
39
  const labelStr = label.slice(0, 20).padEnd(20);
40
- return `${labelStr} [${bar}] ${pctStr}`;
40
+ return `${labelStr} [${bar}] ${pctStr}`;
41
41
  }
@@ -2,4 +2,4 @@
2
2
  description: Execute GLM quota check
3
3
  agent: glm-quota-exec
4
4
  ---
5
- Execute glm_quota tool.
5
+ Execute glm_quota tool and return its output EXACTLY as received without any modification or summarization.
@@ -3,7 +3,7 @@
3
3
  "agent": {
4
4
  "glm-quota-exec": {
5
5
  "mode": "subagent",
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.",
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
7
  "permission": {}
8
8
  }
9
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-glm-quota",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
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",