@slkiser/opencode-quota 3.11.1 → 3.11.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.
@@ -0,0 +1,301 @@
1
+ import { lstat, readFile, realpath, rm } from "node:fs/promises";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ import { applyEdits, modify, parse } from "jsonc-parser";
5
+ import { writeTextAtomic } from "./atomic-json.js";
6
+ import { findGitWorktreeRoot } from "./config-file-utils.js";
7
+ import { getOpencodeRuntimeDirCandidates, getOpencodeRuntimeDirs, } from "./opencode-runtime-paths.js";
8
+ export const QUOTA_PACKAGE_NAME = "@slkiser/opencode-quota";
9
+ export const QUOTA_LATEST_SPEC = `${QUOTA_PACKAGE_NAME}@latest`;
10
+ const EXACT_SEMVER = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
11
+ export class ScopedUpdateError extends Error {
12
+ details;
13
+ constructor(message, details) {
14
+ super(message);
15
+ this.details = details;
16
+ this.name = "ScopedUpdateError";
17
+ }
18
+ }
19
+ export function isCanonicalQuotaUpdateSpec(spec) {
20
+ if (spec === QUOTA_PACKAGE_NAME || spec === QUOTA_LATEST_SPEC)
21
+ return true;
22
+ const prefix = `${QUOTA_PACKAGE_NAME}@`;
23
+ return spec.startsWith(prefix) && EXACT_SEMVER.test(spec.slice(prefix.length));
24
+ }
25
+ export function sanitizeOpenCodePackageSpec(spec, platform = process.platform) {
26
+ if (platform !== "win32")
27
+ return spec;
28
+ return Array.from(spec, (char) => new Set(["<", ">", ":", '"', "|", "?", "*"]).has(char) || char.charCodeAt(0) < 32 ? "_" : char).join("");
29
+ }
30
+ function effectiveGlobalConfigDir(params) {
31
+ const fallback = getOpencodeRuntimeDirs({
32
+ env: params.env,
33
+ homeDir: params.homeDir,
34
+ }).configDir;
35
+ const configured = params.env.OPENCODE_CONFIG_DIR?.trim();
36
+ if (!configured)
37
+ return fallback;
38
+ return isAbsolute(configured) ? configured : resolve(fallback, configured);
39
+ }
40
+ function selectedConfigPaths(root) {
41
+ const result = [];
42
+ for (const kind of ["opencode", "tui"]) {
43
+ const jsonc = join(root, `${kind}.jsonc`);
44
+ const json = join(root, `${kind}.json`);
45
+ if (existsSync(jsonc))
46
+ result.push(jsonc);
47
+ else if (existsSync(json))
48
+ result.push(json);
49
+ }
50
+ return result;
51
+ }
52
+ async function dedupeByRealPath(paths) {
53
+ const output = [];
54
+ const seen = new Set();
55
+ for (const path of paths) {
56
+ const resolved = await realpath(path);
57
+ if (seen.has(resolved))
58
+ continue;
59
+ seen.add(resolved);
60
+ output.push(path);
61
+ }
62
+ return output;
63
+ }
64
+ function pluginArrays(config) {
65
+ if (!config || typeof config !== "object" || Array.isArray(config))
66
+ return [];
67
+ const root = config;
68
+ const arrays = [];
69
+ if (Array.isArray(root.plugin))
70
+ arrays.push({ path: ["plugin"], entries: root.plugin });
71
+ if (root.tui && typeof root.tui === "object" && !Array.isArray(root.tui)) {
72
+ const tui = root.tui;
73
+ if (Array.isArray(tui.plugin))
74
+ arrays.push({ path: ["tui", "plugin"], entries: tui.plugin });
75
+ }
76
+ return arrays;
77
+ }
78
+ function updateConfig(raw, path) {
79
+ const errors = [];
80
+ const parsed = parse(raw, errors, { allowTrailingComma: true, disallowComments: false });
81
+ if (errors.length > 0) {
82
+ throw new ScopedUpdateError(`Cannot update unparseable config: ${path}`, { path });
83
+ }
84
+ let updated = raw;
85
+ let replacements = 0;
86
+ const specs = [];
87
+ for (const array of pluginArrays(parsed)) {
88
+ for (let index = array.entries.length - 1; index >= 0; index--) {
89
+ const entry = array.entries[index];
90
+ const spec = typeof entry === "string"
91
+ ? entry
92
+ : Array.isArray(entry) && typeof entry[0] === "string"
93
+ ? entry[0]
94
+ : null;
95
+ if (spec === null || !isCanonicalQuotaUpdateSpec(spec))
96
+ continue;
97
+ specs.push(spec);
98
+ if (spec === QUOTA_LATEST_SPEC)
99
+ continue;
100
+ const targetPath = typeof entry === "string" ? [...array.path, index] : [...array.path, index, 0];
101
+ updated = applyEdits(updated, modify(updated, targetPath, QUOTA_LATEST_SPEC, {}));
102
+ replacements++;
103
+ }
104
+ }
105
+ return { updated, replacements, specs };
106
+ }
107
+ export async function planScopedUpdate(params = {}) {
108
+ const cwd = params.cwd ?? process.cwd();
109
+ const env = params.env ?? process.env;
110
+ const projectRoot = findGitWorktreeRoot(cwd) ?? cwd;
111
+ const globalRoot = effectiveGlobalConfigDir({ env, homeDir: params.homeDir });
112
+ const configPaths = await dedupeByRealPath([
113
+ ...selectedConfigPaths(projectRoot),
114
+ ...selectedConfigPaths(globalRoot),
115
+ ]);
116
+ const configEdits = [];
117
+ const configSnapshots = [];
118
+ const foundSpecs = [];
119
+ for (const path of configPaths) {
120
+ const originalBytes = await readFile(path);
121
+ const original = originalBytes.toString("utf8");
122
+ const planned = updateConfig(original, path);
123
+ foundSpecs.push(...planned.specs);
124
+ const changed = planned.updated !== original;
125
+ configSnapshots.push({
126
+ path,
127
+ originalBytes,
128
+ expectedBytes: changed ? Buffer.from(planned.updated, "utf8") : originalBytes,
129
+ updated: planned.updated,
130
+ changed,
131
+ });
132
+ if (changed) {
133
+ configEdits.push({
134
+ path,
135
+ original,
136
+ originalBytes,
137
+ updated: planned.updated,
138
+ replacements: planned.replacements,
139
+ });
140
+ }
141
+ }
142
+ const uniqueSpecs = [...new Set(foundSpecs)];
143
+ const cacheSpecs = [...new Set([...uniqueSpecs, QUOTA_LATEST_SPEC])];
144
+ const runtime = getOpencodeRuntimeDirCandidates({
145
+ platform: params.platform,
146
+ env,
147
+ homeDir: params.homeDir,
148
+ });
149
+ const cacheCandidates = runtime.cacheDirs.flatMap((cacheDir) => cacheSpecs.map((spec) => join(cacheDir, "packages", sanitizeOpenCodePackageSpec(spec, params.platform))));
150
+ return {
151
+ configEdits,
152
+ configSnapshots,
153
+ configPaths,
154
+ foundSpecs: uniqueSpecs,
155
+ cacheCandidates: [...new Set(cacheCandidates)],
156
+ authoritativeLatest: uniqueSpecs.length > 0,
157
+ };
158
+ }
159
+ function containedBy(root, candidate) {
160
+ const rel = relative(root, candidate);
161
+ return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
162
+ }
163
+ async function removeVerifiedCacheCandidate(path) {
164
+ const packagesPath = dirname(dirname(path));
165
+ try {
166
+ const packagesStat = await lstat(packagesPath);
167
+ const ownerStat = await lstat(dirname(path));
168
+ if (packagesStat.isSymbolicLink() || ownerStat.isSymbolicLink())
169
+ return "skipped";
170
+ const packagesReal = await realpath(packagesPath);
171
+ const stat = await lstat(path);
172
+ if (stat.isSymbolicLink() || !stat.isDirectory())
173
+ return "skipped";
174
+ const candidateReal = await realpath(path);
175
+ if (!containedBy(packagesReal, candidateReal) || candidateReal === packagesReal)
176
+ return "skipped";
177
+ const manifestPath = join(candidateReal, "node_modules", "@slkiser", "opencode-quota", "package.json");
178
+ const manifestStat = await lstat(manifestPath);
179
+ if (manifestStat.isSymbolicLink() || !manifestStat.isFile())
180
+ return "skipped";
181
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
182
+ if (manifest.name !== QUOTA_PACKAGE_NAME)
183
+ return "skipped";
184
+ await rm(candidateReal, { recursive: true, force: false });
185
+ return "removed";
186
+ }
187
+ catch {
188
+ return "skipped";
189
+ }
190
+ }
191
+ export async function applyScopedUpdatePlan(plan, options = {}) {
192
+ if (options.dryRun) {
193
+ return { writtenPaths: [], removedCachePaths: [], skippedCachePaths: [] };
194
+ }
195
+ const readBytes = options.readBytes ?? ((path) => readFile(path));
196
+ const writeText = options.writeText ?? writeTextAtomic;
197
+ const writtenPaths = [];
198
+ const failure = (action, path) => {
199
+ const changed = writtenPaths.length > 0 ? ` Changed before failure: ${writtenPaths.join(", ")}.` : "";
200
+ return new ScopedUpdateError(`${action} ${path}; no cache was deleted.${changed}`, {
201
+ path,
202
+ writtenPaths: [...writtenPaths],
203
+ });
204
+ };
205
+ for (const snapshot of plan.configSnapshots) {
206
+ let current;
207
+ try {
208
+ current = await readBytes(snapshot.path);
209
+ }
210
+ catch {
211
+ throw failure("Failed reading", snapshot.path);
212
+ }
213
+ if (!current.equals(snapshot.originalBytes)) {
214
+ throw failure("Config changed since preview:", snapshot.path);
215
+ }
216
+ if (!snapshot.changed)
217
+ continue;
218
+ try {
219
+ await writeText(snapshot.path, snapshot.updated);
220
+ writtenPaths.push(snapshot.path);
221
+ }
222
+ catch {
223
+ throw failure("Failed writing", snapshot.path);
224
+ }
225
+ }
226
+ await options.beforeCacheDeletion?.();
227
+ let authoritativeLatest = false;
228
+ for (const snapshot of plan.configSnapshots) {
229
+ let current;
230
+ try {
231
+ current = await readBytes(snapshot.path);
232
+ }
233
+ catch {
234
+ throw failure("Failed re-reading", snapshot.path);
235
+ }
236
+ if (!current.equals(snapshot.expectedBytes)) {
237
+ throw failure("Config changed before cache deletion:", snapshot.path);
238
+ }
239
+ const currentPlan = updateConfig(current.toString("utf8"), snapshot.path);
240
+ if (currentPlan.specs.includes(QUOTA_LATEST_SPEC))
241
+ authoritativeLatest = true;
242
+ }
243
+ const removedCachePaths = [];
244
+ const skippedCachePaths = [];
245
+ if (authoritativeLatest) {
246
+ for (const candidate of plan.cacheCandidates) {
247
+ const result = await removeVerifiedCacheCandidate(candidate);
248
+ (result === "removed" ? removedCachePaths : skippedCachePaths).push(candidate);
249
+ }
250
+ }
251
+ return { writtenPaths, removedCachePaths, skippedCachePaths };
252
+ }
253
+ export async function runScopedUpdateCommand(params = {}) {
254
+ const argv = params.argv ?? [];
255
+ const unknown = argv.filter((arg) => arg !== "--dry-run" && arg !== "--yes");
256
+ if (unknown.length > 0)
257
+ return 1;
258
+ const dryRun = argv.includes("--dry-run");
259
+ const yes = argv.includes("--yes");
260
+ const log = params.log ?? console.log;
261
+ try {
262
+ const plan = await planScopedUpdate(params);
263
+ log("Scoped OpenCode Quota update preview:");
264
+ for (const edit of plan.configEdits) {
265
+ log(` edit ${edit.path} (${edit.replacements} replacement(s))`);
266
+ }
267
+ for (const candidate of plan.cacheCandidates)
268
+ log(` cache candidate ${candidate}`);
269
+ if (plan.configPaths.length === 0 || !plan.authoritativeLatest) {
270
+ log("No authoritative OpenCode config references an updatable OpenCode Quota spec.");
271
+ return 0;
272
+ }
273
+ if (dryRun)
274
+ return 0;
275
+ if (!yes) {
276
+ const confirm = params.confirm ??
277
+ (async (message) => {
278
+ const prompts = await import("@clack/prompts");
279
+ const answer = await prompts.confirm({ message });
280
+ return !prompts.isCancel(answer) && answer === true;
281
+ });
282
+ if (!(await confirm("Apply these config edits and delete only verified cache directories?"))) {
283
+ log("Update cancelled.");
284
+ return 0;
285
+ }
286
+ }
287
+ const result = await applyScopedUpdatePlan(plan);
288
+ for (const path of result.writtenPaths)
289
+ log(`Updated ${path}`);
290
+ for (const path of result.removedCachePaths)
291
+ log(`Removed ${path}`);
292
+ for (const path of result.skippedCachePaths)
293
+ log(`Skipped unverified cache candidate ${path}`);
294
+ return 0;
295
+ }
296
+ catch (error) {
297
+ log(error instanceof Error ? error.message : String(error));
298
+ return 1;
299
+ }
300
+ }
301
+ //# sourceMappingURL=scoped-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-update.js","sourceRoot":"","sources":["../../src/lib/scoped-update.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA6C,MAAM,mBAAmB,CAAC;AAclG,eAAO,MAAM,cAAc,EAAE,aA4C5B,CAAC"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAA6C,MAAM,mBAAmB,CAAC;AAclG,eAAO,MAAM,cAAc,EAAE,aA6C5B,CAAC"}
@@ -31,6 +31,7 @@ export const openaiProvider = {
31
31
  windows: [
32
32
  { window: result.windows.hourly, suffix: "5h", label: "5h:" },
33
33
  { window: result.windows.weekly, suffix: "Weekly", label: "Weekly:" },
34
+ { window: result.windows.monthly, suffix: "Monthly", label: "Monthly:" },
34
35
  { window: result.windows.codeReview, suffix: "Code Review", label: "Code Review:" },
35
36
  ],
36
37
  }), [], {
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,oCAAoC,EACpC,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,EAAE,EAAE,QAAQ;IAEZ,KAAK,CAAC,WAAW,CAAC,GAAyB;QACzC,gFAAgF;QAChF,MAAM,qBAAqB,GAAG,MAAM,4BAA4B,CAAC;YAC/D,GAAG;YACH,UAAU,EAAE,QAAQ;YACpB,eAAe,EAAE,IAAI;SACtB,CAAC,CAAC;QAEH,IAAI,qBAAqB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,oBAAoB,CAAC,EAAE,QAAQ,EAAE,oCAAoC,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,mBAAmB,CAAC,KAAa;QAC/B,OAAO,wBAAwB,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAyB;QACnC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAE1F,OAAO,yBAAyB,CAAC,MAAM,EAAE;YACvC,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CACpB,eAAe,CACb,2BAA2B,CAAC;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE;oBACP,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;oBAC7D,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;oBACrE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE;iBACpF;aACF,CAAC,EACF,EAAE,EACF;gBACE,uBAAuB,EAAE,MAAM,CAAC,KAAK;aACtC,CACF;SACJ,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,oCAAoC,EACpC,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,EACL,eAAe,EACf,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,EAAE,EAAE,QAAQ;IAEZ,KAAK,CAAC,WAAW,CAAC,GAAyB;QACzC,gFAAgF;QAChF,MAAM,qBAAqB,GAAG,MAAM,4BAA4B,CAAC;YAC/D,GAAG;YACH,UAAU,EAAE,QAAQ;YACpB,eAAe,EAAE,IAAI;SACtB,CAAC,CAAC;QAEH,IAAI,qBAAqB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,oBAAoB,CAAC,EAAE,QAAQ,EAAE,oCAAoC,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,mBAAmB,CAAC,KAAa;QAC/B,OAAO,wBAAwB,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,GAAyB;QACnC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAE1F,OAAO,yBAAyB,CAAC,MAAM,EAAE;YACvC,UAAU,EAAE,QAAQ;YACpB,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CACpB,eAAe,CACb,2BAA2B,CAAC;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE;oBACP,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE;oBAC7D,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE;oBACrE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE;oBACxE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,cAAc,EAAE;iBACpF;aACF,CAAC,EACF,EAAE,EACF;gBACE,uBAAuB,EAAE,MAAM,CAAC,KAAK;aACtC,CACF;SACJ,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
package/dist/tui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAsvBjC,QAAA,MAAM,YAAY,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAGjD,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAqgBjC,QAAA,MAAM,YAAY,EAAE,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAGjD,CAAC;AAEF,eAAe,YAAY,CAAC"}
package/dist/tui.js CHANGED
@@ -11,8 +11,7 @@ import { createElement as _$createElement } from "@opentui/solid";
11
11
  import { Show, createEffect, createSignal, onCleanup } from "solid-js";
12
12
  import { getCompactStatusText, getHomeBottomAnnouncementText, getSidebarPanelLines, getSidebarPanelLinesExpanded, shouldRenderCompactStatus, shouldRenderHomeBottom, shouldRenderSidebarPanel } from "./lib/tui-panel-state.js";
13
13
  import { getSidebarBodyLineColor } from "./lib/tui-line-style.js";
14
- import { createTuiQuotaClient, getTuiRuntimeRootHints, getTuiSessionModelMeta, loadTuiHomeBottomStatus, normalizeTuiSessionID, loadTuiSessionQuotaSurfaces, resolveTuiSurfaceRegistration, writeTuiQuotaExportIfEnabled } from "./lib/tui-runtime.js";
15
- import { QUOTA_DIALOG_COMMANDS, buildQuotaDialogCommandOutput } from "./lib/quota-dialog-commands.js";
14
+ import { loadTuiHomeBottomStatus, loadTuiSessionQuotaSurfaces, resolveTuiSurfaceRegistration, writeTuiQuotaExportIfEnabled } from "./lib/tui-runtime.js";
16
15
  const id = "@slkiser/opencode-quota";
17
16
  // Place Quota near the top so variable-height built-in sections
18
17
  // (MCP/LSP/Todo/Files) do not push it below the visible fold.
@@ -437,282 +436,6 @@ function HomeBottomView(props) {
437
436
  }
438
437
  });
439
438
  }
440
- function getActiveTuiSessionID(api) {
441
- const route = api.route?.current;
442
- if (route?.name !== "session" && route?.type !== "session") return undefined;
443
- return normalizeTuiSessionID(route.params?.sessionID ?? route.params?.session_id ?? route.params?.id ?? route.sessionID);
444
- }
445
- function getTuiCommandArguments(input) {
446
- if (!input || typeof input !== "object") return undefined;
447
- const record = input;
448
- for (const key of ["arguments", "args", "query"]) {
449
- const value = record[key];
450
- if (typeof value === "string" && value.trim()) return value.trim();
451
- }
452
- return undefined;
453
- }
454
- function CommandLoadingDialog(props) {
455
- return (() => {
456
- var _el$19 = _$createElement("box"),
457
- _el$20 = _$createElement("text"),
458
- _el$21 = _$createElement("b"),
459
- _el$22 = _$createElement("text");
460
- _$insertNode(_el$19, _el$20);
461
- _$insertNode(_el$19, _el$22);
462
- _$setProp(_el$19, "gap", 1);
463
- _$insertNode(_el$20, _el$21);
464
- _$insert(_el$21, () => props.title);
465
- _$insertNode(_el$22, _$createTextNode(`Loading deterministic local output…`));
466
- _$effect(_p$ => {
467
- var _v$3 = props.api.theme.current.text,
468
- _v$4 = props.api.theme.current.textMuted;
469
- _v$3 !== _p$.e && (_p$.e = _$setProp(_el$20, "fg", _v$3, _p$.e));
470
- _v$4 !== _p$.t && (_p$.t = _$setProp(_el$22, "fg", _v$4, _p$.t));
471
- return _p$;
472
- }, {
473
- e: undefined,
474
- t: undefined
475
- });
476
- return _el$19;
477
- })();
478
- }
479
- function CommandOutputDialog(props) {
480
- const lines = () => props.output.split("\n");
481
- const bodyHeight = () => Math.min(28, Math.max(6, lines().length));
482
- return (() => {
483
- var _el$24 = _$createElement("box"),
484
- _el$25 = _$createElement("text"),
485
- _el$26 = _$createElement("b"),
486
- _el$27 = _$createElement("scrollbox"),
487
- _el$28 = _$createElement("box"),
488
- _el$29 = _$createElement("text");
489
- _$insertNode(_el$24, _el$25);
490
- _$insertNode(_el$24, _el$27);
491
- _$insertNode(_el$24, _el$29);
492
- _$setProp(_el$24, "gap", 1);
493
- _$setProp(_el$24, "width", "100%");
494
- _$setProp(_el$24, "flexGrow", 1);
495
- _$setProp(_el$24, "paddingLeft", 2);
496
- _$setProp(_el$24, "paddingRight", 2);
497
- _$setProp(_el$24, "paddingBottom", 1);
498
- _$insertNode(_el$25, _el$26);
499
- _$insert(_el$26, () => props.title);
500
- _$insertNode(_el$27, _el$28);
501
- _$setProp(_el$27, "width", "100%");
502
- _$setProp(_el$27, "flexGrow", 1);
503
- _$setProp(_el$27, "maxHeight", 28);
504
- _$setProp(_el$28, "gap", 0);
505
- _$setProp(_el$28, "width", "100%");
506
- _$setProp(_el$28, "minWidth", 0);
507
- _$insert(_el$28, () => lines().map(line => (() => {
508
- var _el$31 = _$createElement("text");
509
- _$setProp(_el$31, "wrapMode", "word");
510
- _$setProp(_el$31, "width", "100%");
511
- _$insert(_el$31, line || " ");
512
- _$effect(_$p => _$setProp(_el$31, "fg", props.api.theme.current.text, _$p));
513
- return _el$31;
514
- })()));
515
- _$insertNode(_el$29, _$createTextNode(`esc closes`));
516
- _$effect(_p$ => {
517
- var _v$5 = props.api.theme.current.text,
518
- _v$6 = bodyHeight(),
519
- _v$7 = props.api.theme.current.textMuted;
520
- _v$5 !== _p$.e && (_p$.e = _$setProp(_el$25, "fg", _v$5, _p$.e));
521
- _v$6 !== _p$.t && (_p$.t = _$setProp(_el$27, "minHeight", _v$6, _p$.t));
522
- _v$7 !== _p$.a && (_p$.a = _$setProp(_el$29, "fg", _v$7, _p$.a));
523
- return _p$;
524
- }, {
525
- e: undefined,
526
- t: undefined,
527
- a: undefined
528
- });
529
- return _el$24;
530
- })();
531
- }
532
- function CommandErrorDialog(props) {
533
- const message = props.error instanceof Error ? props.error.message : String(props.error);
534
- return (() => {
535
- var _el$32 = _$createElement("box"),
536
- _el$33 = _$createElement("text"),
537
- _el$34 = _$createElement("b"),
538
- _el$35 = _$createElement("text"),
539
- _el$37 = _$createElement("text"),
540
- _el$38 = _$createElement("text");
541
- _$insertNode(_el$32, _el$33);
542
- _$insertNode(_el$32, _el$35);
543
- _$insertNode(_el$32, _el$37);
544
- _$insertNode(_el$32, _el$38);
545
- _$setProp(_el$32, "gap", 1);
546
- _$insertNode(_el$33, _el$34);
547
- _$insert(_el$34, () => props.title);
548
- _$insertNode(_el$35, _$createTextNode(`OpenCode Quota command failed.`));
549
- _$setProp(_el$37, "wrapMode", "none");
550
- _$insert(_el$37, message || "Unknown error");
551
- _$insertNode(_el$38, _$createTextNode(`esc closes`));
552
- _$effect(_p$ => {
553
- var _v$8 = props.api.theme.current.text,
554
- _v$9 = props.api.theme.current.text,
555
- _v$0 = props.api.theme.current.textMuted,
556
- _v$1 = props.api.theme.current.textMuted;
557
- _v$8 !== _p$.e && (_p$.e = _$setProp(_el$33, "fg", _v$8, _p$.e));
558
- _v$9 !== _p$.t && (_p$.t = _$setProp(_el$35, "fg", _v$9, _p$.t));
559
- _v$0 !== _p$.a && (_p$.a = _$setProp(_el$37, "fg", _v$0, _p$.a));
560
- _v$1 !== _p$.o && (_p$.o = _$setProp(_el$38, "fg", _v$1, _p$.o));
561
- return _p$;
562
- }, {
563
- e: undefined,
564
- t: undefined,
565
- a: undefined,
566
- o: undefined
567
- });
568
- return _el$32;
569
- })();
570
- }
571
- function TokensBetweenPromptDialog(props) {
572
- const DialogPrompt = props.api.ui?.DialogPrompt;
573
- if (DialogPrompt) {
574
- return _$createComponent(DialogPrompt, {
575
- title: "OpenCode Quota Token Range",
576
- placeholder: "YYYY-MM-DD YYYY-MM-DD",
577
- description: () => (() => {
578
- var _el$40 = _$createElement("text");
579
- _$insertNode(_el$40, _$createTextNode(`Enter start and end dates, for example: 2026-01-01 2026-01-15`));
580
- _$setProp(_el$40, "wrapMode", "none");
581
- _$effect(_$p => _$setProp(_el$40, "fg", props.api.theme.current.textMuted, _$p));
582
- return _el$40;
583
- })(),
584
- get onConfirm() {
585
- return props.onConfirm;
586
- },
587
- get onCancel() {
588
- return props.onCancel;
589
- }
590
- });
591
- }
592
- return _$createComponent(CommandOutputDialog, {
593
- get api() {
594
- return props.api;
595
- },
596
- title: "OpenCode Quota Token Range",
597
- output: "Missing arguments for /tokens_between\n\nExpected: /tokens_between YYYY-MM-DD YYYY-MM-DD\nExample: /tokens_between 2026-01-01 2026-01-15"
598
- });
599
- }
600
- function replaceDialog(api, size, render) {
601
- const dialog = api.ui?.dialog;
602
- dialog?.replace?.(render);
603
- // OpenCode's dialog.replace() resets size to medium; xlarge is the widest supported dialog.
604
- dialog?.setSize?.(size);
605
- }
606
- function clearDialog(api) {
607
- api.ui?.dialog?.clear?.();
608
- }
609
- async function runQuotaDialogCommandAsync(api, command, rawInput, state) {
610
- const spec = QUOTA_DIALOG_COMMANDS.find(item => item.id === command);
611
- const args = getTuiCommandArguments(rawInput);
612
- const sessionID = getActiveTuiSessionID(api);
613
- if (command === "tokens_between" && !args) {
614
- replaceDialog(api, "medium", () => _$createComponent(TokensBetweenPromptDialog, {
615
- api: api,
616
- onCancel: () => clearDialog(api),
617
- onConfirm: value => {
618
- const nextArgs = value.trim();
619
- if (!nextArgs) {
620
- replaceDialog(api, "large", () => _$createComponent(CommandOutputDialog, {
621
- api: api,
622
- get title() {
623
- return spec.title;
624
- },
625
- output: "Missing arguments for /tokens_between\n\nExpected: /tokens_between YYYY-MM-DD YYYY-MM-DD\nExample: /tokens_between 2026-01-01 2026-01-15"
626
- }));
627
- return;
628
- }
629
- runQuotaDialogCommand(api, command, {
630
- arguments: nextArgs
631
- }, state);
632
- }
633
- }));
634
- return;
635
- }
636
- replaceDialog(api, spec.dialogSize, () => _$createComponent(CommandLoadingDialog, {
637
- api: api,
638
- get title() {
639
- return spec.title;
640
- }
641
- }));
642
- try {
643
- const result = await buildQuotaDialogCommandOutput({
644
- command,
645
- arguments: args,
646
- client: createTuiQuotaClient(api),
647
- roots: getTuiRuntimeRootHints(api),
648
- sessionID,
649
- resolveSessionMeta: id => getTuiSessionModelMeta(api, id),
650
- lastSessionTokenError: state?.lastSessionTokenError,
651
- setLastSessionTokenError: state ? error => {
652
- state.lastSessionTokenError = error;
653
- } : undefined,
654
- log: async (message, extra) => {
655
- await api.client?.app?.log?.({
656
- body: {
657
- service: "quota-toast",
658
- level: "debug",
659
- message,
660
- extra
661
- }
662
- });
663
- }
664
- });
665
- if (result.state === "noop") {
666
- clearDialog(api);
667
- return;
668
- }
669
- replaceDialog(api, result.dialogSize, () => _$createComponent(CommandOutputDialog, {
670
- api: api,
671
- get title() {
672
- return result.title;
673
- },
674
- get output() {
675
- return result.output;
676
- }
677
- }));
678
- } catch (error) {
679
- replaceDialog(api, "large", () => _$createComponent(CommandErrorDialog, {
680
- api: api,
681
- get title() {
682
- return spec.title;
683
- },
684
- error: error
685
- }));
686
- api.ui?.toast?.({
687
- variant: "error",
688
- message: "OpenCode Quota command failed"
689
- });
690
- }
691
- }
692
- function runQuotaDialogCommand(api, command, rawInput, state) {
693
- void runQuotaDialogCommandAsync(api, command, rawInput, state);
694
- }
695
- function registerQuotaDialogCommands(api) {
696
- const keymap = api.keymap;
697
- if (!keymap?.registerLayer) return;
698
- const commandState = {};
699
- const dispose = keymap.registerLayer({
700
- commands: QUOTA_DIALOG_COMMANDS.map(spec => ({
701
- namespace: "palette",
702
- name: `opencode-quota.${spec.id}`,
703
- title: spec.title,
704
- desc: spec.description,
705
- category: "OpenCode Quota",
706
- slashName: spec.slashName,
707
- run(input) {
708
- runQuotaDialogCommand(api, spec.id, input, commandState);
709
- }
710
- }))
711
- });
712
- if (typeof dispose === "function") {
713
- api.lifecycle.onDispose(dispose);
714
- }
715
- }
716
439
  function registerSidebarSlots(api) {
717
440
  api.slots.register({
718
441
  order: SIDEBAR_ORDER,
@@ -729,7 +452,6 @@ function registerSidebarSlots(api) {
729
452
  });
730
453
  }
731
454
  const tui = async api => {
732
- registerQuotaDialogCommands(api);
733
455
  let surfaceRegistration;
734
456
  try {
735
457
  surfaceRegistration = await resolveTuiSurfaceRegistration(api);