@slkiser/opencode-quota 2.16.0 → 3.0.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.
Files changed (129) hide show
  1. package/README.md +145 -49
  2. package/dist/bin/opencode-quota.d.ts +3 -0
  3. package/dist/bin/opencode-quota.d.ts.map +1 -0
  4. package/dist/bin/opencode-quota.js +37 -0
  5. package/dist/bin/opencode-quota.js.map +1 -0
  6. package/dist/lib/config-file-utils.d.ts +18 -0
  7. package/dist/lib/config-file-utils.d.ts.map +1 -0
  8. package/dist/lib/config-file-utils.js +88 -0
  9. package/dist/lib/config-file-utils.js.map +1 -0
  10. package/dist/lib/config.d.ts +10 -7
  11. package/dist/lib/config.d.ts.map +1 -1
  12. package/dist/lib/config.js +111 -31
  13. package/dist/lib/config.js.map +1 -1
  14. package/dist/lib/cursor-detection.d.ts +1 -0
  15. package/dist/lib/cursor-detection.d.ts.map +1 -1
  16. package/dist/lib/cursor-detection.js +16 -8
  17. package/dist/lib/cursor-detection.js.map +1 -1
  18. package/dist/lib/display-sanitize.d.ts +7 -0
  19. package/dist/lib/display-sanitize.d.ts.map +1 -1
  20. package/dist/lib/display-sanitize.js +49 -0
  21. package/dist/lib/display-sanitize.js.map +1 -1
  22. package/dist/lib/entries.d.ts +1 -1
  23. package/dist/lib/entries.d.ts.map +1 -1
  24. package/dist/lib/format.js +1 -1
  25. package/dist/lib/format.js.map +1 -1
  26. package/dist/lib/google-antigravity-companion.d.ts +29 -0
  27. package/dist/lib/google-antigravity-companion.d.ts.map +1 -0
  28. package/dist/lib/google-antigravity-companion.js +122 -0
  29. package/dist/lib/google-antigravity-companion.js.map +1 -0
  30. package/dist/lib/google.d.ts +1 -0
  31. package/dist/lib/google.d.ts.map +1 -1
  32. package/dist/lib/google.js +54 -16
  33. package/dist/lib/google.js.map +1 -1
  34. package/dist/lib/grouped-entry-normalization.d.ts.map +1 -1
  35. package/dist/lib/grouped-entry-normalization.js +83 -23
  36. package/dist/lib/grouped-entry-normalization.js.map +1 -1
  37. package/dist/lib/init-installer.d.ts +101 -0
  38. package/dist/lib/init-installer.d.ts.map +1 -0
  39. package/dist/lib/init-installer.js +507 -0
  40. package/dist/lib/init-installer.js.map +1 -0
  41. package/dist/lib/provider-metadata.d.ts +1 -0
  42. package/dist/lib/provider-metadata.d.ts.map +1 -1
  43. package/dist/lib/provider-metadata.js +5 -0
  44. package/dist/lib/provider-metadata.js.map +1 -1
  45. package/dist/lib/quota-render-data.d.ts +72 -0
  46. package/dist/lib/quota-render-data.d.ts.map +1 -0
  47. package/dist/lib/quota-render-data.js +315 -0
  48. package/dist/lib/quota-render-data.js.map +1 -0
  49. package/dist/lib/quota-status.d.ts +9 -0
  50. package/dist/lib/quota-status.d.ts.map +1 -1
  51. package/dist/lib/quota-status.js +39 -1
  52. package/dist/lib/quota-status.js.map +1 -1
  53. package/dist/lib/session-tokens-format.d.ts +16 -3
  54. package/dist/lib/session-tokens-format.d.ts.map +1 -1
  55. package/dist/lib/session-tokens-format.js +65 -11
  56. package/dist/lib/session-tokens-format.js.map +1 -1
  57. package/dist/lib/toast-format-grouped.js +1 -1
  58. package/dist/lib/toast-format-grouped.js.map +1 -1
  59. package/dist/lib/tui-config-diagnostics.d.ts +12 -0
  60. package/dist/lib/tui-config-diagnostics.d.ts.map +1 -0
  61. package/dist/lib/tui-config-diagnostics.js +49 -0
  62. package/dist/lib/tui-config-diagnostics.js.map +1 -0
  63. package/dist/lib/tui-line-style.d.ts +3 -0
  64. package/dist/lib/tui-line-style.d.ts.map +1 -0
  65. package/dist/lib/tui-line-style.js +7 -0
  66. package/dist/lib/tui-line-style.js.map +1 -0
  67. package/dist/lib/tui-panel-state.d.ts +7 -0
  68. package/dist/lib/tui-panel-state.d.ts.map +1 -0
  69. package/dist/lib/tui-panel-state.js +13 -0
  70. package/dist/lib/tui-panel-state.js.map +1 -0
  71. package/dist/lib/tui-runtime.d.ts +11 -0
  72. package/dist/lib/tui-runtime.d.ts.map +1 -0
  73. package/dist/lib/tui-runtime.js +107 -0
  74. package/dist/lib/tui-runtime.js.map +1 -0
  75. package/dist/lib/tui-sidebar-format.d.ts +13 -0
  76. package/dist/lib/tui-sidebar-format.d.ts.map +1 -0
  77. package/dist/lib/tui-sidebar-format.js +29 -0
  78. package/dist/lib/tui-sidebar-format.js.map +1 -0
  79. package/dist/lib/types.d.ts +8 -5
  80. package/dist/lib/types.d.ts.map +1 -1
  81. package/dist/lib/types.js +2 -2
  82. package/dist/lib/types.js.map +1 -1
  83. package/dist/plugin.d.ts.map +1 -1
  84. package/dist/plugin.js +66 -320
  85. package/dist/plugin.js.map +1 -1
  86. package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
  87. package/dist/providers/alibaba-coding-plan.js +12 -19
  88. package/dist/providers/alibaba-coding-plan.js.map +1 -1
  89. package/dist/providers/anthropic.d.ts.map +1 -1
  90. package/dist/providers/anthropic.js +12 -19
  91. package/dist/providers/anthropic.js.map +1 -1
  92. package/dist/providers/chutes.d.ts.map +1 -1
  93. package/dist/providers/chutes.js +10 -17
  94. package/dist/providers/chutes.js.map +1 -1
  95. package/dist/providers/copilot.js +1 -1
  96. package/dist/providers/copilot.js.map +1 -1
  97. package/dist/providers/cursor.js +1 -1
  98. package/dist/providers/cursor.js.map +1 -1
  99. package/dist/providers/firmware.d.ts.map +1 -1
  100. package/dist/providers/firmware.js +11 -18
  101. package/dist/providers/firmware.js.map +1 -1
  102. package/dist/providers/google-antigravity.js +4 -4
  103. package/dist/providers/google-antigravity.js.map +1 -1
  104. package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
  105. package/dist/providers/minimax-coding-plan.js +14 -29
  106. package/dist/providers/minimax-coding-plan.js.map +1 -1
  107. package/dist/providers/nanogpt.d.ts.map +1 -1
  108. package/dist/providers/nanogpt.js +5 -12
  109. package/dist/providers/nanogpt.js.map +1 -1
  110. package/dist/providers/openai.d.ts.map +1 -1
  111. package/dist/providers/openai.js +13 -28
  112. package/dist/providers/openai.js.map +1 -1
  113. package/dist/providers/opencode-go.d.ts.map +1 -1
  114. package/dist/providers/opencode-go.js +15 -40
  115. package/dist/providers/opencode-go.js.map +1 -1
  116. package/dist/providers/qwen-code.d.ts.map +1 -1
  117. package/dist/providers/qwen-code.js +16 -19
  118. package/dist/providers/qwen-code.js.map +1 -1
  119. package/dist/providers/result-helpers.d.ts +5 -0
  120. package/dist/providers/result-helpers.d.ts.map +1 -0
  121. package/dist/providers/result-helpers.js +10 -0
  122. package/dist/providers/result-helpers.js.map +1 -0
  123. package/dist/providers/zai.d.ts.map +1 -1
  124. package/dist/providers/zai.js +13 -28
  125. package/dist/providers/zai.js.map +1 -1
  126. package/dist/tui.d.ts +7 -0
  127. package/dist/tui.d.ts.map +1 -0
  128. package/dist/tui.tsx +155 -0
  129. package/package.json +27 -9
package/dist/tui.tsx ADDED
@@ -0,0 +1,155 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui";
3
+ import { createEffect, createSignal, onCleanup } from "solid-js";
4
+
5
+ import type { ProviderFetchCacheStore } from "./lib/quota-render-data.js";
6
+ import type { SidebarPanelState } from "./lib/tui-panel-state.js";
7
+
8
+ import { getSidebarPanelLines, shouldRenderSidebarPanel } from "./lib/tui-panel-state.js";
9
+ import { getSidebarBodyLineColor } from "./lib/tui-line-style.js";
10
+ import { loadSidebarPanel } from "./lib/tui-runtime.js";
11
+
12
+ const id = "@slkiser/opencode-quota";
13
+ // Place Quota near the top so variable-height built-in sections
14
+ // (MCP/LSP/Todo/Files) do not push it below the visible fold.
15
+ const SIDEBAR_ORDER = 150;
16
+ const REFRESH_INTERVAL_MS = 60_000;
17
+
18
+ function SidebarContentView(props: {
19
+ api: TuiPluginApi;
20
+ sessionID: string;
21
+ providerFetchCache: ProviderFetchCacheStore;
22
+ }) {
23
+ const [panel, setPanel] = createSignal<SidebarPanelState>({
24
+ status: "loading",
25
+ lines: [],
26
+ });
27
+
28
+ let disposed = false;
29
+ let loadVersion = 0;
30
+ const timers = new Set<ReturnType<typeof setTimeout>>();
31
+
32
+ const reload = () => {
33
+ const currentVersion = ++loadVersion;
34
+
35
+ void loadSidebarPanel({
36
+ api: props.api,
37
+ sessionID: props.sessionID,
38
+ providerFetchCache: props.providerFetchCache,
39
+ })
40
+ .then((next) => {
41
+ if (disposed || currentVersion !== loadVersion) return;
42
+ setPanel(next);
43
+ })
44
+ .catch(() => {
45
+ if (disposed || currentVersion !== loadVersion) return;
46
+ });
47
+ };
48
+
49
+ const queueRefresh = (delay: number) => {
50
+ const timer = setTimeout(() => {
51
+ timers.delete(timer);
52
+ reload();
53
+ }, delay);
54
+ timers.add(timer);
55
+ };
56
+
57
+ const scheduleRefresh = () => {
58
+ queueRefresh(150);
59
+ queueRefresh(600);
60
+ };
61
+
62
+ // TUI/session state can hydrate asynchronously after mount or session switch,
63
+ // so retry a few times to recover from empty first-load reads.
64
+ const scheduleMountRecovery = () => {
65
+ queueRefresh(500);
66
+ queueRefresh(1_500);
67
+ queueRefresh(4_000);
68
+ };
69
+
70
+ createEffect(() => {
71
+ props.sessionID;
72
+ reload();
73
+ scheduleMountRecovery();
74
+ });
75
+
76
+ const interval = setInterval(reload, REFRESH_INTERVAL_MS);
77
+ const unsubscribers = [
78
+ props.api.event.on("session.updated", (event) => {
79
+ if (event.properties?.info?.id === props.sessionID) {
80
+ scheduleRefresh();
81
+ }
82
+ }),
83
+ props.api.event.on("message.updated", (event) => {
84
+ if (event.properties?.info?.sessionID === props.sessionID) {
85
+ scheduleRefresh();
86
+ }
87
+ }),
88
+ props.api.event.on("message.removed", (event) => {
89
+ if (event.properties?.sessionID === props.sessionID) {
90
+ scheduleRefresh();
91
+ }
92
+ }),
93
+ props.api.event.on("tui.session.select", (event) => {
94
+ if (event.properties?.sessionID === props.sessionID) {
95
+ scheduleRefresh();
96
+ }
97
+ }),
98
+ ];
99
+
100
+ onCleanup(() => {
101
+ disposed = true;
102
+ clearInterval(interval);
103
+ for (const timer of timers) clearTimeout(timer);
104
+ timers.clear();
105
+ for (const unsubscribe of unsubscribers) unsubscribe();
106
+ });
107
+
108
+ if (!shouldRenderSidebarPanel(panel())) return null;
109
+
110
+ const lines = () => getSidebarPanelLines(panel());
111
+
112
+ return (
113
+ <box gap={0}>
114
+ <text fg={props.api.theme.current.text}>
115
+ <b>Quota</b>
116
+ </text>
117
+ <box gap={0}>
118
+ {lines().map((line) => (
119
+ <text fg={getSidebarBodyLineColor(line, props.api.theme.current)} wrapMode="none">
120
+ {line || " "}
121
+ </text>
122
+ ))}
123
+ </box>
124
+ </box>
125
+ );
126
+ }
127
+
128
+ const tui: TuiPlugin = async (api) => {
129
+ const providerFetchCache: ProviderFetchCacheStore = new Map();
130
+ api.lifecycle.onDispose(() => {
131
+ providerFetchCache.clear();
132
+ });
133
+
134
+ api.slots.register({
135
+ order: SIDEBAR_ORDER,
136
+ slots: {
137
+ sidebar_content(_ctx, props: { session_id: string }) {
138
+ return (
139
+ <SidebarContentView
140
+ api={api}
141
+ sessionID={props.session_id}
142
+ providerFetchCache={providerFetchCache}
143
+ />
144
+ );
145
+ },
146
+ },
147
+ });
148
+ };
149
+
150
+ const pluginModule: TuiPluginModule & { id: string } = {
151
+ id,
152
+ tui,
153
+ };
154
+
155
+ export default pluginModule;
package/package.json CHANGED
@@ -1,23 +1,38 @@
1
1
  {
2
2
  "name": "@slkiser/opencode-quota",
3
- "version": "2.16.0",
3
+ "version": "3.0.0",
4
4
  "description": "OpenCode quota & tokens usage with zero context window pollution. Supports GitHub Copilot, OpenAI (Plus/Pro), Qwen Code, Chutes AI, Firmware AI, Google Antigravity, Z.ai coding plan and more.",
5
5
  "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "opencode-quota": "./dist/bin/opencode-quota.js"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./server": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "./tui": {
21
+ "types": "./dist/tui.d.ts",
22
+ "default": "./dist/tui.tsx"
12
23
  }
13
24
  },
25
+ "oc-plugin": [
26
+ "server",
27
+ "tui"
28
+ ],
14
29
  "files": [
15
30
  "dist",
16
31
  "README.md",
17
32
  "LICENSE"
18
33
  ],
19
34
  "scripts": {
20
- "build": "tsc && node scripts/copy-data.mjs",
35
+ "build": "tsc && node scripts/copy-data.mjs && node scripts/prepare-tui-dist.mjs",
21
36
  "pricing:refresh": "node scripts/refresh-modelsdev-pricing.mjs",
22
37
  "pricing:refresh:if-stale": "node scripts/refresh-modelsdev-pricing-if-stale.mjs",
23
38
  "upstream:check": "node scripts/check-upstream-plugin-updates.mjs",
@@ -53,7 +68,7 @@
53
68
  },
54
69
  "homepage": "https://github.com/slkiser/opencode-quota#readme",
55
70
  "devDependencies": {
56
- "@opencode-ai/plugin": "^1.1.14",
71
+ "@opencode-ai/plugin": "^1.4.3",
57
72
  "@types/node": "^22.0.0",
58
73
  "husky": "^9.1.7",
59
74
  "lint-staged": "^16.2.7",
@@ -63,14 +78,17 @@
63
78
  "zod": "4.1.8"
64
79
  },
65
80
  "dependencies": {
66
- "opencode-antigravity-auth": "^1.2.8",
81
+ "@clack/prompts": "^1.2.0",
82
+ "@opentui/core": "^0.1.92",
83
+ "@opentui/solid": "^0.1.92",
84
+ "solid-js": "^1.9.10",
67
85
  "xdg-basedir": "^5.1.0"
68
86
  },
69
87
  "overrides": {
70
88
  "zod": "4.1.8"
71
89
  },
72
90
  "peerDependencies": {
73
- "@opencode-ai/plugin": "^1.1.0"
91
+ "@opencode-ai/plugin": "^1.4.3"
74
92
  },
75
93
  "engines": {
76
94
  "node": ">=18.0.0"