@ereinha/opencode-enhanced-quotas 1.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.
- package/README.md +333 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +42 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +13 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +19 -0
- package/dist/constants.js.map +1 -0
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +56 -0
- package/dist/defaults.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +449 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces.d.ts +210 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/interfaces.js +2 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +47 -0
- package/dist/logger.js.map +1 -0
- package/dist/plugin-state.d.ts +32 -0
- package/dist/plugin-state.d.ts.map +1 -0
- package/dist/plugin-state.js +81 -0
- package/dist/plugin-state.js.map +1 -0
- package/dist/providers/antigravity/auth.d.ts +12 -0
- package/dist/providers/antigravity/auth.d.ts.map +1 -0
- package/dist/providers/antigravity/auth.js +109 -0
- package/dist/providers/antigravity/auth.js.map +1 -0
- package/dist/providers/antigravity/index.d.ts +2 -0
- package/dist/providers/antigravity/index.d.ts.map +1 -0
- package/dist/providers/antigravity/index.js +2 -0
- package/dist/providers/antigravity/index.js.map +1 -0
- package/dist/providers/antigravity/provider.d.ts +34 -0
- package/dist/providers/antigravity/provider.d.ts.map +1 -0
- package/dist/providers/antigravity/provider.js +221 -0
- package/dist/providers/antigravity/provider.js.map +1 -0
- package/dist/providers/codex.d.ts +4 -0
- package/dist/providers/codex.d.ts.map +1 -0
- package/dist/providers/codex.js +233 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/github.d.ts +4 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +139 -0
- package/dist/providers/github.js.map +1 -0
- package/dist/quota-cache.d.ts +26 -0
- package/dist/quota-cache.d.ts.map +1 -0
- package/dist/quota-cache.js +107 -0
- package/dist/quota-cache.js.map +1 -0
- package/dist/registry.d.ts +3 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +23 -0
- package/dist/registry.js.map +1 -0
- package/dist/services/aggregation-service.d.ts +34 -0
- package/dist/services/aggregation-service.d.ts.map +1 -0
- package/dist/services/aggregation-service.js +89 -0
- package/dist/services/aggregation-service.js.map +1 -0
- package/dist/services/config-loader.d.ts +32 -0
- package/dist/services/config-loader.d.ts.map +1 -0
- package/dist/services/config-loader.js +168 -0
- package/dist/services/config-loader.js.map +1 -0
- package/dist/services/history-service.d.ts +39 -0
- package/dist/services/history-service.d.ts.map +1 -0
- package/dist/services/history-service.js +207 -0
- package/dist/services/history-service.js.map +1 -0
- package/dist/services/prediction-engine.d.ts +51 -0
- package/dist/services/prediction-engine.d.ts.map +1 -0
- package/dist/services/prediction-engine.js +108 -0
- package/dist/services/prediction-engine.js.map +1 -0
- package/dist/services/quota-service.d.ts +42 -0
- package/dist/services/quota-service.d.ts.map +1 -0
- package/dist/services/quota-service.js +339 -0
- package/dist/services/quota-service.js.map +1 -0
- package/dist/ui/progress-bar.d.ts +20 -0
- package/dist/ui/progress-bar.d.ts.map +1 -0
- package/dist/ui/progress-bar.js +150 -0
- package/dist/ui/progress-bar.js.map +1 -0
- package/dist/ui/quota-table.d.ts +15 -0
- package/dist/ui/quota-table.d.ts.map +1 -0
- package/dist/ui/quota-table.js +137 -0
- package/dist/ui/quota-table.js.map +1 -0
- package/dist/utils/paths.d.ts +7 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +37 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/time.d.ts +3 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +38 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/validation.d.ts +6 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +66 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +42 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import { QuotaService } from "./services/quota-service";
|
|
3
|
+
import { HistoryService } from "./services/history-service";
|
|
4
|
+
import { renderQuotaTable } from "./ui/quota-table";
|
|
5
|
+
import { QuotaCache } from "./quota-cache";
|
|
6
|
+
import { PLUGIN_FOOTER_SIGNATURE, SKIP_REASONS, } from "./constants";
|
|
7
|
+
import { logger } from "./logger";
|
|
8
|
+
import { getPluginState } from "./plugin-state";
|
|
9
|
+
const z = tool.schema;
|
|
10
|
+
/**
|
|
11
|
+
* QuotaHub Plugin for OpenCode.ai
|
|
12
|
+
*/
|
|
13
|
+
export const QuotaHubPlugin = async ({ client, $, directory, serverUrl, }) => {
|
|
14
|
+
const state = getPluginState();
|
|
15
|
+
const historyService = new HistoryService();
|
|
16
|
+
const quotaService = new QuotaService();
|
|
17
|
+
let quotaCache;
|
|
18
|
+
let initPromise;
|
|
19
|
+
const MAX_INIT_RETRIES = 3;
|
|
20
|
+
const INITIAL_RETRY_DELAY_MS = 2000;
|
|
21
|
+
// Dedicated initialization function
|
|
22
|
+
const ensureInit = async () => {
|
|
23
|
+
if (initPromise)
|
|
24
|
+
return initPromise;
|
|
25
|
+
initPromise = (async () => {
|
|
26
|
+
let lastError;
|
|
27
|
+
for (let attempt = 1; attempt <= MAX_INIT_RETRIES; attempt++) {
|
|
28
|
+
try {
|
|
29
|
+
await historyService.init();
|
|
30
|
+
await quotaService.init(directory, historyService);
|
|
31
|
+
const config = quotaService.getConfig();
|
|
32
|
+
const providers = quotaService.getProviders();
|
|
33
|
+
logger.debug("init:providers", {
|
|
34
|
+
ids: providers.map((p) => p.id),
|
|
35
|
+
count: providers.length,
|
|
36
|
+
});
|
|
37
|
+
quotaCache = new QuotaCache(providers, {
|
|
38
|
+
refreshIntervalMs: config.pollingInterval ?? 60_000,
|
|
39
|
+
historyService,
|
|
40
|
+
debug: !!config.debug,
|
|
41
|
+
});
|
|
42
|
+
quotaCache.start();
|
|
43
|
+
logger.debug("init:complete");
|
|
44
|
+
return; // Success
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
lastError = e;
|
|
48
|
+
const errorMsg = e instanceof Error ? e.message : String(e);
|
|
49
|
+
if (attempt < MAX_INIT_RETRIES) {
|
|
50
|
+
const delay = INITIAL_RETRY_DELAY_MS * Math.pow(2, attempt - 1);
|
|
51
|
+
logger.warn("init:failed_retry", {
|
|
52
|
+
attempt,
|
|
53
|
+
delayMs: delay,
|
|
54
|
+
error: errorMsg,
|
|
55
|
+
});
|
|
56
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
logger.error("init:failed_final", {
|
|
60
|
+
attempt,
|
|
61
|
+
error: errorMsg,
|
|
62
|
+
});
|
|
63
|
+
// Log a user-visible warning
|
|
64
|
+
console.warn(`[QuotaHub] Failed to initialize after ${MAX_INIT_RETRIES} attempts. Quota information will be unavailable. Error: ${errorMsg}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
throw lastError;
|
|
69
|
+
})();
|
|
70
|
+
return initPromise;
|
|
71
|
+
};
|
|
72
|
+
// Trigger background initialization
|
|
73
|
+
ensureInit().catch(() => {
|
|
74
|
+
// Warning already logged in ensureInit if it failed after max retries
|
|
75
|
+
});
|
|
76
|
+
const makeDebugLog = (config) => {
|
|
77
|
+
return (msg, data) => {
|
|
78
|
+
if (config.debug)
|
|
79
|
+
logger.debug(msg, data);
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
const buildFooterText = (assistantMsg, config, cache, debugLog) => {
|
|
83
|
+
const snapshot = cache.getSnapshot();
|
|
84
|
+
const rawResults = snapshot.data;
|
|
85
|
+
debugLog("cache:snapshot", {
|
|
86
|
+
fetchedAt: snapshot.fetchedAt?.toISOString(),
|
|
87
|
+
totalCount: rawResults.length,
|
|
88
|
+
hasError: !!snapshot.lastError,
|
|
89
|
+
});
|
|
90
|
+
if (rawResults.length === 0) {
|
|
91
|
+
debugLog("skip:no_cached_quotas", {
|
|
92
|
+
fetchedAt: snapshot.fetchedAt?.toISOString(),
|
|
93
|
+
lastError: snapshot.lastError,
|
|
94
|
+
});
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const filteredResults = quotaService.processQuotas(rawResults, {
|
|
98
|
+
providerId: assistantMsg.providerID,
|
|
99
|
+
modelId: assistantMsg.modelID,
|
|
100
|
+
});
|
|
101
|
+
debugLog("quotas:processed", {
|
|
102
|
+
before: rawResults.length,
|
|
103
|
+
after: filteredResults.length,
|
|
104
|
+
providerId: assistantMsg.providerID,
|
|
105
|
+
modelId: assistantMsg.modelID,
|
|
106
|
+
});
|
|
107
|
+
if (filteredResults.length === 0) {
|
|
108
|
+
debugLog("skip:all_quotas_filtered", {
|
|
109
|
+
providerId: assistantMsg.providerID,
|
|
110
|
+
modelId: assistantMsg.modelID,
|
|
111
|
+
});
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const lines = renderQuotaTable(filteredResults, {
|
|
115
|
+
progressBarConfig: config.progressBar,
|
|
116
|
+
tableConfig: config.table,
|
|
117
|
+
}).map((l) => l.line);
|
|
118
|
+
const showMode = config.progressBar?.show ?? "used";
|
|
119
|
+
const modeLabel = showMode === "available" ? "(Remaining)" : "(Used)";
|
|
120
|
+
const showTitle = config.showFooterTitle !== false;
|
|
121
|
+
const titleText = showTitle
|
|
122
|
+
? `${PLUGIN_FOOTER_SIGNATURE} ${modeLabel}_\n`
|
|
123
|
+
: "";
|
|
124
|
+
return {
|
|
125
|
+
text: "\n\n" + titleText + lines.join("\n"),
|
|
126
|
+
lineCount: lines.length,
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
const hooks = {
|
|
130
|
+
/**
|
|
131
|
+
* Tool definitions for slash commands
|
|
132
|
+
*/
|
|
133
|
+
tool: {
|
|
134
|
+
/**
|
|
135
|
+
* /usage - Display comprehensive quota usage information
|
|
136
|
+
* Similar to Claude Code's usage display
|
|
137
|
+
*/
|
|
138
|
+
usage: tool({
|
|
139
|
+
description: "Display comprehensive quota usage information for all configured providers. Shows current usage, limits, reset times, and status for each quota.",
|
|
140
|
+
args: {
|
|
141
|
+
provider: z.string().optional().describe("Filter by specific provider ID (e.g., 'claude', 'openrouter', 'cursor')"),
|
|
142
|
+
format: z.enum(["table", "json", "compact"]).optional().describe("Output format: table (default), json, or compact"),
|
|
143
|
+
},
|
|
144
|
+
async execute(args, context) {
|
|
145
|
+
// Ensure initialization is complete
|
|
146
|
+
await ensureInit().catch((e) => {
|
|
147
|
+
logger.error("usage:init_error", { error: e });
|
|
148
|
+
});
|
|
149
|
+
if (!quotaCache) {
|
|
150
|
+
return "Quota service is not initialized. Please wait a moment and try again.";
|
|
151
|
+
}
|
|
152
|
+
const snapshot = quotaCache.getSnapshot();
|
|
153
|
+
const rawResults = snapshot.data;
|
|
154
|
+
if (rawResults.length === 0) {
|
|
155
|
+
return "No quota data available. This could mean:\n- No quota providers are configured\n- Providers haven't been initialized yet\n- There was an error fetching quota data";
|
|
156
|
+
}
|
|
157
|
+
// Helper to calculate percentage
|
|
158
|
+
const calcPercent = (q) => q.limit ? (q.used / q.limit) * 100 : 0;
|
|
159
|
+
// Filter by provider if specified
|
|
160
|
+
let filteredResults = rawResults;
|
|
161
|
+
if (args.provider) {
|
|
162
|
+
filteredResults = rawResults.filter(q => q.providerName?.toLowerCase().includes(args.provider.toLowerCase()) ||
|
|
163
|
+
q.id?.toLowerCase().includes(args.provider.toLowerCase()));
|
|
164
|
+
if (filteredResults.length === 0) {
|
|
165
|
+
return `No quotas found for provider: ${args.provider}\n\nAvailable providers: ${[...new Set(rawResults.map(q => q.providerName || 'unknown'))].join(', ')}`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const config = quotaService.getConfig();
|
|
169
|
+
const format = args.format || "table";
|
|
170
|
+
if (format === "json") {
|
|
171
|
+
return JSON.stringify(filteredResults.map(q => ({
|
|
172
|
+
id: q.id,
|
|
173
|
+
provider: q.providerName,
|
|
174
|
+
used: q.used,
|
|
175
|
+
limit: q.limit,
|
|
176
|
+
remaining: q.limit ? q.limit - q.used : null,
|
|
177
|
+
percentUsed: calcPercent(q),
|
|
178
|
+
reset: q.reset,
|
|
179
|
+
unit: q.unit,
|
|
180
|
+
})), null, 2);
|
|
181
|
+
}
|
|
182
|
+
if (format === "compact") {
|
|
183
|
+
return filteredResults.map(q => {
|
|
184
|
+
const pct = calcPercent(q);
|
|
185
|
+
const status = pct >= 90 ? "[!]" : pct >= 70 ? "[~]" : "[OK]";
|
|
186
|
+
return `${status} ${q.id}: ${pct.toFixed(0)}% used`;
|
|
187
|
+
}).join("\n");
|
|
188
|
+
}
|
|
189
|
+
// Default: table format
|
|
190
|
+
const lines = renderQuotaTable(filteredResults, {
|
|
191
|
+
progressBarConfig: config.progressBar,
|
|
192
|
+
tableConfig: config.table,
|
|
193
|
+
}).map((l) => l.line);
|
|
194
|
+
const showMode = config.progressBar?.show ?? "used";
|
|
195
|
+
const modeLabel = showMode === "available" ? "(Remaining)" : "(Used)";
|
|
196
|
+
const header = `Quota Usage ${modeLabel}\n${"─".repeat(60)}\n`;
|
|
197
|
+
const footer = `\n${"─".repeat(60)}\nLast updated: ${snapshot.fetchedAt?.toLocaleTimeString() || 'Unknown'}`;
|
|
198
|
+
return header + lines.join("\n") + footer;
|
|
199
|
+
},
|
|
200
|
+
}),
|
|
201
|
+
/**
|
|
202
|
+
* /mymodels - Display available models filtered by quota status
|
|
203
|
+
*/
|
|
204
|
+
mymodels: tool({
|
|
205
|
+
description: "Display available models filtered by current quota status. Shows which models are available, rate-limited, or exhausted based on real-time quota data.",
|
|
206
|
+
args: {
|
|
207
|
+
status: z.enum(["available", "limited", "exhausted", "all"]).optional().describe("Filter by availability status (default: all)"),
|
|
208
|
+
provider: z.string().optional().describe("Filter by provider ID"),
|
|
209
|
+
},
|
|
210
|
+
async execute(args, context) {
|
|
211
|
+
// Ensure initialization is complete
|
|
212
|
+
await ensureInit().catch((e) => {
|
|
213
|
+
logger.error("mymodels:init_error", { error: e });
|
|
214
|
+
});
|
|
215
|
+
if (!quotaCache) {
|
|
216
|
+
return "Quota service is not initialized. Please wait a moment and try again.";
|
|
217
|
+
}
|
|
218
|
+
const snapshot = quotaCache.getSnapshot();
|
|
219
|
+
const rawResults = snapshot.data;
|
|
220
|
+
if (rawResults.length === 0) {
|
|
221
|
+
return "No quota data available to determine model availability.";
|
|
222
|
+
}
|
|
223
|
+
// Helper to calculate percentage
|
|
224
|
+
const calcPercent = (q) => q.limit ? (q.used / q.limit) * 100 : 0;
|
|
225
|
+
// Categorize quotas by status
|
|
226
|
+
const available = [];
|
|
227
|
+
const limited = [];
|
|
228
|
+
const exhausted = [];
|
|
229
|
+
for (const quota of rawResults) {
|
|
230
|
+
// Filter by provider if specified
|
|
231
|
+
if (args.provider && !quota.providerName?.toLowerCase().includes(args.provider.toLowerCase())) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const pct = calcPercent(quota);
|
|
235
|
+
if (pct >= 100) {
|
|
236
|
+
exhausted.push(quota);
|
|
237
|
+
}
|
|
238
|
+
else if (pct >= 80) {
|
|
239
|
+
limited.push(quota);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
available.push(quota);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const statusFilter = args.status || "all";
|
|
246
|
+
let output = [];
|
|
247
|
+
const formatQuota = (q, marker) => {
|
|
248
|
+
const pct = calcPercent(q);
|
|
249
|
+
const reset = q.reset ? ` (resets: ${q.reset})` : "";
|
|
250
|
+
return `${marker} ${q.id}: ${pct.toFixed(0)}% used${reset}`;
|
|
251
|
+
};
|
|
252
|
+
if (statusFilter === "all" || statusFilter === "available") {
|
|
253
|
+
if (available.length > 0) {
|
|
254
|
+
output.push("[OK] Available Models:");
|
|
255
|
+
output.push(...available.map(q => formatQuota(q, " +")));
|
|
256
|
+
output.push("");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (statusFilter === "all" || statusFilter === "limited") {
|
|
260
|
+
if (limited.length > 0) {
|
|
261
|
+
output.push("[~] Rate-Limited (use with caution):");
|
|
262
|
+
output.push(...limited.map(q => formatQuota(q, " ~")));
|
|
263
|
+
output.push("");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (statusFilter === "all" || statusFilter === "exhausted") {
|
|
267
|
+
if (exhausted.length > 0) {
|
|
268
|
+
output.push("[!] Exhausted (unavailable):");
|
|
269
|
+
output.push(...exhausted.map(q => formatQuota(q, " x")));
|
|
270
|
+
output.push("");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (output.length === 0) {
|
|
274
|
+
return `No models found with status: ${statusFilter}`;
|
|
275
|
+
}
|
|
276
|
+
// Add summary
|
|
277
|
+
output.push("-".repeat(40));
|
|
278
|
+
output.push(`Summary: ${available.length} available, ${limited.length} limited, ${exhausted.length} exhausted`);
|
|
279
|
+
return output.join("\n");
|
|
280
|
+
},
|
|
281
|
+
}),
|
|
282
|
+
},
|
|
283
|
+
/**
|
|
284
|
+
* The platform calls this hook after a text generation is complete.
|
|
285
|
+
* We inject the quota footer directly into output.text for final assistant messages.
|
|
286
|
+
*/
|
|
287
|
+
"experimental.text.complete": async (input, output) => {
|
|
288
|
+
// Ensure initialization is complete before processing
|
|
289
|
+
await ensureInit().catch((e) => {
|
|
290
|
+
logger.error("init:error", { error: e });
|
|
291
|
+
});
|
|
292
|
+
if (!quotaCache) {
|
|
293
|
+
const config = quotaService.getConfig();
|
|
294
|
+
if (config.debug)
|
|
295
|
+
logger.debug("hook:no_cache", {
|
|
296
|
+
messageID: input.messageID,
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const cache = quotaCache;
|
|
301
|
+
const config = quotaService.getConfig();
|
|
302
|
+
const debugLog = makeDebugLog(config);
|
|
303
|
+
if (config.footer === false) {
|
|
304
|
+
debugLog("skip:footer_disabled", {
|
|
305
|
+
messageID: input.messageID,
|
|
306
|
+
});
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
// Log hook invocation
|
|
310
|
+
debugLog("hook:experimental.text.complete", {
|
|
311
|
+
input,
|
|
312
|
+
processed: state.isProcessed(input.messageID),
|
|
313
|
+
pending: state.isPending(input.messageID),
|
|
314
|
+
});
|
|
315
|
+
// Fast path check
|
|
316
|
+
if (state.isProcessed(input.messageID)) {
|
|
317
|
+
debugLog("skip:already_processed", {
|
|
318
|
+
messageID: input.messageID,
|
|
319
|
+
});
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
if (state.isPending(input.messageID)) {
|
|
323
|
+
debugLog("skip:already_pending", {
|
|
324
|
+
messageID: input.messageID,
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// Secondary safeguard: check if footer already present
|
|
329
|
+
if (output.text.includes(PLUGIN_FOOTER_SIGNATURE)) {
|
|
330
|
+
debugLog(SKIP_REASONS.FOOTER_PRESENT, {
|
|
331
|
+
messageID: input.messageID,
|
|
332
|
+
});
|
|
333
|
+
state.markProcessed(input.messageID);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
debugLog("lock:acquire_start", { messageID: input.messageID });
|
|
337
|
+
// Acquire lock for this message
|
|
338
|
+
const release = await state.acquireLock(input.messageID);
|
|
339
|
+
debugLog("lock:acquired", { messageID: input.messageID });
|
|
340
|
+
try {
|
|
341
|
+
// After acquiring lock, re-check if processed
|
|
342
|
+
if (state.isProcessed(input.messageID)) {
|
|
343
|
+
debugLog("skip:already_processed_after_lock", {
|
|
344
|
+
messageID: input.messageID,
|
|
345
|
+
});
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (state.isPending(input.messageID)) {
|
|
349
|
+
debugLog("skip:already_pending_after_lock", {
|
|
350
|
+
messageID: input.messageID,
|
|
351
|
+
});
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
// Double-check text content in case another process injected it while we waited for lock
|
|
355
|
+
if (output.text.includes(PLUGIN_FOOTER_SIGNATURE)) {
|
|
356
|
+
debugLog("skip:footer_present_after_lock", {
|
|
357
|
+
messageID: input.messageID,
|
|
358
|
+
});
|
|
359
|
+
state.markProcessed(input.messageID);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
// Fetch message to verify role and parts
|
|
363
|
+
const { data: result } = await client.session.message({
|
|
364
|
+
path: {
|
|
365
|
+
id: input.sessionID,
|
|
366
|
+
messageID: input.messageID,
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
if (!result || result.info.role !== "assistant") {
|
|
370
|
+
debugLog("skip:not_assistant", {
|
|
371
|
+
messageID: input.messageID,
|
|
372
|
+
role: result?.info?.role,
|
|
373
|
+
});
|
|
374
|
+
state.markProcessed(input.messageID);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const assistantMsg = result.info;
|
|
378
|
+
const parts = result.parts || [];
|
|
379
|
+
const currentPartIndex = parts.findIndex((p) => p.id === input.partID);
|
|
380
|
+
const currentPart = parts[currentPartIndex];
|
|
381
|
+
// Simplified completion check: Is this the last part of the message?
|
|
382
|
+
const isLastPart = currentPartIndex === parts.length - 1;
|
|
383
|
+
debugLog("message:details", {
|
|
384
|
+
id: input.messageID,
|
|
385
|
+
mode: assistantMsg.mode,
|
|
386
|
+
agent: assistantMsg.agent,
|
|
387
|
+
partID: input.partID,
|
|
388
|
+
partType: currentPart?.type,
|
|
389
|
+
isLastPart,
|
|
390
|
+
totalParts: parts.length
|
|
391
|
+
});
|
|
392
|
+
const isSubagentMessage = assistantMsg.mode === "subagent";
|
|
393
|
+
const isReasoningPart = currentPart?.type === "reasoning";
|
|
394
|
+
const hasReasoningType = assistantMsg.mode === "reasoning" ||
|
|
395
|
+
assistantMsg.type === "reasoning";
|
|
396
|
+
const isThinking = isSubagentMessage || isReasoningPart || hasReasoningType;
|
|
397
|
+
if (isThinking) {
|
|
398
|
+
debugLog(SKIP_REASONS.THINKING, {
|
|
399
|
+
messageID: input.messageID,
|
|
400
|
+
partID: input.partID,
|
|
401
|
+
type: currentPart?.type
|
|
402
|
+
});
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
// Only inject on the last part of the message to avoid double injection
|
|
406
|
+
// and to ensure we are at the very end.
|
|
407
|
+
if (!isLastPart) {
|
|
408
|
+
debugLog("skip:not_last_part", {
|
|
409
|
+
messageID: input.messageID,
|
|
410
|
+
partID: input.partID,
|
|
411
|
+
index: currentPartIndex,
|
|
412
|
+
total: parts.length
|
|
413
|
+
});
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
// Verify it's a text part (we don't want to inject into tool calls or others)
|
|
417
|
+
if (currentPart?.type !== "text") {
|
|
418
|
+
debugLog("skip:not_text_part", {
|
|
419
|
+
messageID: input.messageID,
|
|
420
|
+
partID: input.partID,
|
|
421
|
+
type: currentPart?.type
|
|
422
|
+
});
|
|
423
|
+
state.markProcessed(input.messageID);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
// Build footer and inject directly into output.text
|
|
427
|
+
const footer = buildFooterText(assistantMsg, config, cache, debugLog);
|
|
428
|
+
if (!footer) {
|
|
429
|
+
state.markProcessed(input.messageID);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Inline injection: modify output.text directly
|
|
433
|
+
output.text = output.text + footer.text;
|
|
434
|
+
state.markProcessed(input.messageID);
|
|
435
|
+
debugLog("inject:footer_inline", {
|
|
436
|
+
messageID: input.messageID,
|
|
437
|
+
lines: footer.lineCount,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
finally {
|
|
441
|
+
debugLog("lock:release", { messageID: input.messageID });
|
|
442
|
+
release();
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
return hooks;
|
|
447
|
+
};
|
|
448
|
+
export default QuotaHubPlugin;
|
|
449
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|