@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1
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/LICENSE +57744 -0
- package/native-manifest.json +1414 -0
- package/package.json +254 -0
- package/plugins/abacus-ai/icon.svg +18 -0
- package/plugins/abacus-ai/plugin.js +121 -0
- package/plugins/abacus-ai/plugin.json +17 -0
- package/plugins/alibaba/icon-color.svg +1 -0
- package/plugins/alibaba/icon.svg +1 -0
- package/plugins/alibaba/plugin.js +322 -0
- package/plugins/alibaba/plugin.json +20 -0
- package/plugins/alibaba-token-plan/icon-color.svg +1 -0
- package/plugins/alibaba-token-plan/icon.svg +1 -0
- package/plugins/alibaba-token-plan/plugin.js +544 -0
- package/plugins/alibaba-token-plan/plugin.json +19 -0
- package/plugins/amp/icon-color.svg +1 -0
- package/plugins/amp/icon-conflict.svg +6 -0
- package/plugins/amp/icon.svg +1 -0
- package/plugins/amp/plugin.js +175 -0
- package/plugins/amp/plugin.json +16 -0
- package/plugins/antigravity/icon-color.svg +1 -0
- package/plugins/antigravity/icon-conflict.svg +3 -0
- package/plugins/antigravity/icon.svg +1 -0
- package/plugins/antigravity/plugin.js +739 -0
- package/plugins/antigravity/plugin.json +31 -0
- package/plugins/antigravity-cli/icon.svg +3 -0
- package/plugins/antigravity-cli/plugin.js +570 -0
- package/plugins/antigravity-cli/plugin.json +16 -0
- package/plugins/antigravity-ide/icon.svg +3 -0
- package/plugins/antigravity-ide/plugin.js +257 -0
- package/plugins/antigravity-ide/plugin.json +29 -0
- package/plugins/augment/icon.svg +14 -0
- package/plugins/augment/plugin.js +59 -0
- package/plugins/augment/plugin.json +18 -0
- package/plugins/aws-bedrock/icon-color.svg +1 -0
- package/plugins/aws-bedrock/icon.svg +1 -0
- package/plugins/aws-bedrock/plugin.js +206 -0
- package/plugins/aws-bedrock/plugin.json +18 -0
- package/plugins/azure-openai/icon-color.svg +1 -0
- package/plugins/azure-openai/icon.svg +1 -0
- package/plugins/azure-openai/plugin.js +145 -0
- package/plugins/azure-openai/plugin.json +17 -0
- package/plugins/chutes/icon.svg +7 -0
- package/plugins/chutes/plugin.js +236 -0
- package/plugins/chutes/plugin.json +19 -0
- package/plugins/claude/icon-color.svg +1 -0
- package/plugins/claude/icon.svg +1 -0
- package/plugins/claude/plugin.js +1723 -0
- package/plugins/claude/plugin.json +30 -0
- package/plugins/codebuff/icon.svg +92 -0
- package/plugins/codebuff/plugin.js +113 -0
- package/plugins/codebuff/plugin.json +17 -0
- package/plugins/codex/icon-color.svg +5 -0
- package/plugins/codex/icon.svg +1 -0
- package/plugins/codex/plugin.js +1009 -0
- package/plugins/codex/plugin.json +82 -0
- package/plugins/command-code/icon.svg +3 -0
- package/plugins/command-code/plugin.js +184 -0
- package/plugins/command-code/plugin.json +20 -0
- package/plugins/copilot/icon-color.svg +1 -0
- package/plugins/copilot/icon.svg +1 -0
- package/plugins/copilot/plugin.js +684 -0
- package/plugins/copilot/plugin.json +21 -0
- package/plugins/crof/icon.svg +3 -0
- package/plugins/crof/plugin.js +53 -0
- package/plugins/crof/plugin.json +17 -0
- package/plugins/crofai/icon.svg +16 -0
- package/plugins/crofai/plugin.js +81 -0
- package/plugins/crofai/plugin.json +18 -0
- package/plugins/cursor/icon-conflict.svg +3 -0
- package/plugins/cursor/icon.svg +1 -0
- package/plugins/cursor/plugin.js +1379 -0
- package/plugins/cursor/plugin.json +23 -0
- package/plugins/cursor-nightly/icon.png +0 -0
- package/plugins/cursor-nightly/plugin.js +1379 -0
- package/plugins/cursor-nightly/plugin.json +23 -0
- package/plugins/deepgram/icon.svg +1 -0
- package/plugins/deepgram/plugin.js +20 -0
- package/plugins/deepgram/plugin.json +17 -0
- package/plugins/deepseek/icon-color.svg +1 -0
- package/plugins/deepseek/icon.svg +1 -0
- package/plugins/deepseek/plugin.js +71 -0
- package/plugins/deepseek/plugin.json +17 -0
- package/plugins/devin/icon.svg +5 -0
- package/plugins/devin/plugin.js +341 -0
- package/plugins/devin/plugin.json +16 -0
- package/plugins/doubao/icon-color.svg +1 -0
- package/plugins/doubao/icon.svg +1 -0
- package/plugins/doubao/plugin.js +92 -0
- package/plugins/doubao/plugin.json +17 -0
- package/plugins/droid/icon.svg +1 -0
- package/plugins/droid/plugin.json +20 -0
- package/plugins/elevenlabs/icon.svg +4 -0
- package/plugins/elevenlabs/plugin.js +48 -0
- package/plugins/elevenlabs/plugin.json +18 -0
- package/plugins/factory/icon-conflict.svg +1 -0
- package/plugins/factory/icon.svg +1 -0
- package/plugins/factory/plugin.js +487 -0
- package/plugins/factory/plugin.json +15 -0
- package/plugins/fireworks-ai/icon.svg +6 -0
- package/plugins/fireworks-ai/plugin.js +370 -0
- package/plugins/fireworks-ai/plugin.json +19 -0
- package/plugins/gemini/icon-color.svg +1 -0
- package/plugins/gemini/icon.svg +1 -0
- package/plugins/gemini/plugin.js +460 -0
- package/plugins/gemini/plugin.json +16 -0
- package/plugins/grok/icon.svg +1 -0
- package/plugins/grok/plugin.js +297 -0
- package/plugins/grok/plugin.json +19 -0
- package/plugins/groqcloud/icon.svg +1 -0
- package/plugins/groqcloud/plugin.js +117 -0
- package/plugins/groqcloud/plugin.json +19 -0
- package/plugins/jetbrains-ai-assistant/icon-color.svg +14 -0
- package/plugins/jetbrains-ai-assistant/icon-conflict.svg +3 -0
- package/plugins/jetbrains-ai-assistant/icon.svg +14 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +313 -0
- package/plugins/jetbrains-ai-assistant/plugin.json +16 -0
- package/plugins/kilo/icon.svg +1 -0
- package/plugins/kilo/plugin.js +111 -0
- package/plugins/kilo/plugin.json +19 -0
- package/plugins/kimi/icon-color.svg +1 -0
- package/plugins/kimi/icon-conflict.svg +3 -0
- package/plugins/kimi/icon.svg +1 -0
- package/plugins/kimi/plugin.js +358 -0
- package/plugins/kimi/plugin.json +15 -0
- package/plugins/kimi-k2/icon-color.svg +1 -0
- package/plugins/kimi-k2/icon.svg +1 -0
- package/plugins/kimi-k2/plugin.js +58 -0
- package/plugins/kimi-k2/plugin.json +18 -0
- package/plugins/kiro/icon-color.svg +5 -0
- package/plugins/kiro/icon-conflict.svg +1 -0
- package/plugins/kiro/icon.svg +4 -0
- package/plugins/kiro/plugin.js +390 -0
- package/plugins/kiro/plugin.json +16 -0
- package/plugins/litellm/icon.svg +16 -0
- package/plugins/litellm/plugin.js +199 -0
- package/plugins/litellm/plugin.json +16 -0
- package/plugins/llm-proxy/icon.svg +1 -0
- package/plugins/llm-proxy/plugin.js +40 -0
- package/plugins/llm-proxy/plugin.json +17 -0
- package/plugins/manus/icon.svg +6 -0
- package/plugins/manus/plugin.js +50 -0
- package/plugins/manus/plugin.json +17 -0
- package/plugins/mimo/icon.svg +1 -0
- package/plugins/mimo/plugin.js +177 -0
- package/plugins/mimo/plugin.json +19 -0
- package/plugins/minimax/icon-color.svg +1 -0
- package/plugins/minimax/icon-conflict.svg +4 -0
- package/plugins/minimax/icon.svg +1 -0
- package/plugins/minimax/plugin.js +453 -0
- package/plugins/minimax/plugin.json +14 -0
- package/plugins/mistral/icon-color.svg +1 -0
- package/plugins/mistral/icon.svg +1 -0
- package/plugins/mistral/plugin.js +152 -0
- package/plugins/mistral/plugin.json +18 -0
- package/plugins/moonshot/icon.svg +1 -0
- package/plugins/moonshot/plugin.js +43 -0
- package/plugins/moonshot/plugin.json +16 -0
- package/plugins/nanogpt/icon-color.svg +17 -0
- package/plugins/nanogpt/icon.svg +10 -0
- package/plugins/nanogpt/plugin.js +80 -0
- package/plugins/nanogpt/plugin.json +17 -0
- package/plugins/neuralwatt/icon.svg +3 -0
- package/plugins/neuralwatt/plugin.js +152 -0
- package/plugins/neuralwatt/plugin.json +17 -0
- package/plugins/ollama/icon.svg +1 -0
- package/plugins/ollama/plugin.js +92 -0
- package/plugins/ollama/plugin.json +20 -0
- package/plugins/openai-api/icon.svg +1 -0
- package/plugins/openai-api/plugin.js +533 -0
- package/plugins/openai-api/plugin.json +26 -0
- package/plugins/opencode/icon.svg +1 -0
- package/plugins/opencode/plugin.js +342 -0
- package/plugins/opencode/plugin.json +19 -0
- package/plugins/opencode-go/icon-conflict.svg +1 -0
- package/plugins/opencode-go/icon.svg +1 -0
- package/plugins/opencode-go/plugin.js +617 -0
- package/plugins/opencode-go/plugin.json +50 -0
- package/plugins/openrouter/icon.svg +1 -0
- package/plugins/openrouter/plugin.js +156 -0
- package/plugins/openrouter/plugin.json +8 -0
- package/plugins/perplexity/icon-color.svg +1 -0
- package/plugins/perplexity/icon-conflict.svg +1 -0
- package/plugins/perplexity/icon.svg +1 -0
- package/plugins/perplexity/plugin.js +425 -0
- package/plugins/perplexity/plugin.json +19 -0
- package/plugins/poe/icon.svg +1 -0
- package/plugins/poe/plugin.js +190 -0
- package/plugins/poe/plugin.json +19 -0
- package/plugins/stepfun/icon-color.svg +1 -0
- package/plugins/stepfun/icon.svg +1 -0
- package/plugins/stepfun/plugin.js +155 -0
- package/plugins/stepfun/plugin.json +18 -0
- package/plugins/synthetic/icon-conflict.svg +12 -0
- package/plugins/synthetic/icon.svg +14 -0
- package/plugins/synthetic/plugin.js +331 -0
- package/plugins/synthetic/plugin.json +23 -0
- package/plugins/t3chat/icon-color.svg +28 -0
- package/plugins/t3chat/icon.svg +4 -0
- package/plugins/t3chat/plugin.js +243 -0
- package/plugins/t3chat/plugin.json +20 -0
- package/plugins/venice/icon-color.svg +1 -0
- package/plugins/venice/icon.svg +1 -0
- package/plugins/venice/plugin.js +69 -0
- package/plugins/venice/plugin.json +16 -0
- package/plugins/vertex-ai/icon-color.svg +1 -0
- package/plugins/vertex-ai/icon.svg +1 -0
- package/plugins/vertex-ai/plugin.js +172 -0
- package/plugins/vertex-ai/plugin.json +18 -0
- package/plugins/warp/icon-color.svg +10 -0
- package/plugins/warp/icon.svg +6 -0
- package/plugins/warp/plugin.js +108 -0
- package/plugins/warp/plugin.json +18 -0
- package/plugins/windsurf/icon-conflict.svg +3 -0
- package/plugins/windsurf/icon.svg +1 -0
- package/plugins/windsurf/plugin.js +208 -0
- package/plugins/windsurf/plugin.json +16 -0
- package/plugins/zai/icon-conflict.svg +5 -0
- package/plugins/zai/icon.svg +1 -0
- package/plugins/zai/plugin.js +188 -0
- package/plugins/zai/plugin.json +16 -0
- package/plugins/zed/icon.svg +4 -0
- package/plugins/zed/plugin.js +270 -0
- package/plugins/zed/plugin.json +19 -0
- package/usagestat +0 -0
- package/usagestatd +0 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var API_URL = "https://api.synthetic.new/v2/quotas";
|
|
3
|
+
var ONE_HOUR_MS = 60 * 60 * 1000;
|
|
4
|
+
|
|
5
|
+
var CROSSUSAGE_CONFIG_PATH = "~/.crossusage/config.json";
|
|
6
|
+
var DEFAULT_PI_AGENT_DIR = "~/.pi/agent";
|
|
7
|
+
var FACTORY_SETTINGS_PATH = "~/.factory/settings.json";
|
|
8
|
+
var OPENCODE_AUTH_PATH = "~/.local/share/opencode/auth.json";
|
|
9
|
+
|
|
10
|
+
// Provider names a user might register Synthetic under in various harnesses
|
|
11
|
+
var PROVIDER_NAMES = ["synthetic", "synthetic.new", "syn"];
|
|
12
|
+
|
|
13
|
+
function resolvePiAgentDir(ctx) {
|
|
14
|
+
var envDir = ctx.host.env.get("PI_CODING_AGENT_DIR");
|
|
15
|
+
if (typeof envDir === "string" && envDir.trim()) {
|
|
16
|
+
return envDir.trim();
|
|
17
|
+
}
|
|
18
|
+
return DEFAULT_PI_AGENT_DIR;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function extractKey(value) {
|
|
22
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Search a parsed JSON object for a Synthetic API key under known provider names
|
|
27
|
+
function findKeyInProviderMap(obj) {
|
|
28
|
+
if (!obj || typeof obj !== "object") return null;
|
|
29
|
+
for (var i = 0; i < PROVIDER_NAMES.length; i++) {
|
|
30
|
+
var entry = obj[PROVIDER_NAMES[i]];
|
|
31
|
+
if (!entry) continue;
|
|
32
|
+
// Pi auth.json style: { "synthetic": { "type": "api_key", "key": "syn_..." } }
|
|
33
|
+
var k = extractKey(entry.key);
|
|
34
|
+
if (k) return k;
|
|
35
|
+
// Pi models.json style: { "providers": { "synthetic": { "apiKey": "syn_..." } } }
|
|
36
|
+
k = extractKey(entry.apiKey);
|
|
37
|
+
if (k) return k;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function tryReadJson(ctx, path) {
|
|
43
|
+
try {
|
|
44
|
+
if (!ctx.host.fs.exists(path)) return null;
|
|
45
|
+
return ctx.util.tryParseJson(ctx.host.fs.readText(path));
|
|
46
|
+
} catch (e) {
|
|
47
|
+
ctx.host.log.warn("Failed to read " + path + ": " + e);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function toFiniteNumber(v) {
|
|
53
|
+
if (typeof v === "number" && Number.isFinite(v)) return v;
|
|
54
|
+
if (typeof v === "string" && v.trim() !== "") {
|
|
55
|
+
var n = Number(v);
|
|
56
|
+
if (Number.isFinite(n)) return n;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** API may nest the payload under `data`. */
|
|
62
|
+
function unwrapQuotasJson(raw) {
|
|
63
|
+
if (!raw || typeof raw !== "object") return raw;
|
|
64
|
+
if (raw.data && typeof raw.data === "object") {
|
|
65
|
+
return Object.assign({}, raw.data, raw);
|
|
66
|
+
}
|
|
67
|
+
return raw;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function pickRollingFiveHour(json) {
|
|
71
|
+
return json.rollingFiveHourLimit || json.rolling_five_hour_limit || null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function pickWeeklyToken(json) {
|
|
75
|
+
return json.weeklyTokenLimit || json.weekly_token_limit || null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function pickFreeToolCalls(json) {
|
|
79
|
+
return json.freeToolCalls || json.free_tool_calls || null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function hasUsableRollingFiveHourLimit(value) {
|
|
83
|
+
if (!value || typeof value !== "object") return false;
|
|
84
|
+
var max = toFiniteNumber(value.max);
|
|
85
|
+
var remaining = toFiniteNumber(value.remaining);
|
|
86
|
+
return max !== null && remaining !== null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function hasUsableWeeklyTokenLimit(value) {
|
|
90
|
+
if (!value || typeof value !== "object") return false;
|
|
91
|
+
return toFiniteNumber(value.percentRemaining) !== null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function normalizeApiErrorMessage(json, status) {
|
|
95
|
+
var fallback = "Request failed (HTTP " + status + ")";
|
|
96
|
+
if (!json || typeof json !== "object") return fallback;
|
|
97
|
+
|
|
98
|
+
var direct = typeof json.error === "string" ? json.error.trim() : "";
|
|
99
|
+
if (direct) return direct;
|
|
100
|
+
|
|
101
|
+
if (json.error && typeof json.error === "object") {
|
|
102
|
+
var nested = typeof json.error.message === "string" ? json.error.message.trim() : "";
|
|
103
|
+
if (nested) return nested;
|
|
104
|
+
|
|
105
|
+
var serialized = JSON.stringify(json.error);
|
|
106
|
+
if (serialized && serialized !== "{}") return serialized;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
var message = typeof json.message === "string" ? json.message.trim() : "";
|
|
110
|
+
if (message) return message;
|
|
111
|
+
|
|
112
|
+
return fallback;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function loadApiKey(ctx) {
|
|
116
|
+
// 0. CrossUsage user config (created on first app launch)
|
|
117
|
+
var cu = tryReadJson(ctx, CROSSUSAGE_CONFIG_PATH);
|
|
118
|
+
var sk;
|
|
119
|
+
if (cu && cu.synthetic && typeof cu.synthetic === "object") {
|
|
120
|
+
sk = extractKey(cu.synthetic.apiKey);
|
|
121
|
+
if (sk) return sk;
|
|
122
|
+
}
|
|
123
|
+
if (cu && typeof cu.syntheticApiKey === "string") {
|
|
124
|
+
sk = extractKey(cu.syntheticApiKey);
|
|
125
|
+
if (sk) return sk;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
var piDir = resolvePiAgentDir(ctx);
|
|
129
|
+
|
|
130
|
+
// 1. Pi auth.json — primary source
|
|
131
|
+
var piAuth = tryReadJson(ctx, piDir + "/auth.json");
|
|
132
|
+
var key = findKeyInProviderMap(piAuth);
|
|
133
|
+
if (key) return key;
|
|
134
|
+
|
|
135
|
+
// 2. Pi models.json — custom provider config with apiKey field
|
|
136
|
+
var piModels = tryReadJson(ctx, piDir + "/models.json");
|
|
137
|
+
if (piModels && piModels.providers) {
|
|
138
|
+
key = findKeyInProviderMap(piModels.providers);
|
|
139
|
+
if (key) return key;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 3. Factory/Droid settings.json — custom models with synthetic.new baseUrl
|
|
143
|
+
var factorySettings = tryReadJson(ctx, FACTORY_SETTINGS_PATH);
|
|
144
|
+
if (factorySettings && Array.isArray(factorySettings.customModels)) {
|
|
145
|
+
for (var i = 0; i < factorySettings.customModels.length; i++) {
|
|
146
|
+
var model = factorySettings.customModels[i];
|
|
147
|
+
if (
|
|
148
|
+
model &&
|
|
149
|
+
typeof model.baseUrl === "string" &&
|
|
150
|
+
model.baseUrl.indexOf("synthetic.new") !== -1
|
|
151
|
+
) {
|
|
152
|
+
key = extractKey(model.apiKey);
|
|
153
|
+
if (key) return key;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 4. OpenCode auth.json
|
|
159
|
+
var ocAuth = tryReadJson(ctx, OPENCODE_AUTH_PATH);
|
|
160
|
+
key = findKeyInProviderMap(ocAuth);
|
|
161
|
+
if (key) return key;
|
|
162
|
+
|
|
163
|
+
// 5. SYNTHETIC_API_KEY env var
|
|
164
|
+
var envKey = ctx.host.env.get("SYNTHETIC_API_KEY");
|
|
165
|
+
if (typeof envKey === "string" && envKey.trim()) {
|
|
166
|
+
return envKey.trim();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function probe(ctx) {
|
|
173
|
+
var apiKey = loadApiKey(ctx);
|
|
174
|
+
if (!apiKey) {
|
|
175
|
+
throw "Synthetic API key not found. Put your syn_ key in ~/.crossusage/config.json under synthetic.apiKey, set SYNTHETIC_API_KEY, or configure Pi / Factory / OpenCode.";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
var resp, json;
|
|
179
|
+
try {
|
|
180
|
+
var result = ctx.util.requestJson({
|
|
181
|
+
method: "GET",
|
|
182
|
+
url: API_URL,
|
|
183
|
+
headers: {
|
|
184
|
+
Authorization: "Bearer " + apiKey,
|
|
185
|
+
Accept: "application/json",
|
|
186
|
+
},
|
|
187
|
+
timeoutMs: 15000,
|
|
188
|
+
});
|
|
189
|
+
resp = result.resp;
|
|
190
|
+
json = result.json;
|
|
191
|
+
} catch (e) {
|
|
192
|
+
throw "Request failed. Check your connection.";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (ctx.util.isAuthStatus(resp.status)) {
|
|
196
|
+
throw "API key invalid or expired. Check your Synthetic API key.";
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
200
|
+
var msg = normalizeApiErrorMessage(json, resp.status);
|
|
201
|
+
throw msg;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!json) {
|
|
205
|
+
throw "Could not parse usage data.";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
json = unwrapQuotasJson(json);
|
|
209
|
+
|
|
210
|
+
var rfl = pickRollingFiveHour(json);
|
|
211
|
+
var wtl = pickWeeklyToken(json);
|
|
212
|
+
|
|
213
|
+
var lines = [];
|
|
214
|
+
|
|
215
|
+
// 5h Rate Limit — hero metric (immediate blocker)
|
|
216
|
+
if (hasUsableRollingFiveHourLimit(rfl)) {
|
|
217
|
+
var rflMax = toFiniteNumber(rfl.max);
|
|
218
|
+
var rflRem = toFiniteNumber(rfl.remaining);
|
|
219
|
+
var rflUsed = Math.max(0, rflMax - rflRem);
|
|
220
|
+
lines.push(ctx.line.progress({
|
|
221
|
+
label: "5h Rate Limit",
|
|
222
|
+
used: rflUsed,
|
|
223
|
+
limit: rflMax,
|
|
224
|
+
format: { kind: "count", suffix: "requests" },
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Mana Bar — longer-term weekly budget
|
|
229
|
+
if (hasUsableWeeklyTokenLimit(wtl)) {
|
|
230
|
+
var pct = toFiniteNumber(wtl.percentRemaining);
|
|
231
|
+
var manaUsed = Math.max(0, Math.round(100 - pct));
|
|
232
|
+
lines.push(ctx.line.progress({
|
|
233
|
+
label: "Mana Bar",
|
|
234
|
+
used: manaUsed,
|
|
235
|
+
limit: 100,
|
|
236
|
+
format: { kind: "percent" },
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Rate Limited badge — only when actively limited
|
|
241
|
+
if (rfl && rfl.limited === true) {
|
|
242
|
+
lines.push(
|
|
243
|
+
ctx.line.badge({
|
|
244
|
+
label: "Rate Limited",
|
|
245
|
+
text: "Rate limited",
|
|
246
|
+
color: "#ef4444",
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Subscription — legacy request count, only shown if NOT on v3 rate limits
|
|
252
|
+
var onV3 = hasUsableRollingFiveHourLimit(rfl) || hasUsableWeeklyTokenLimit(wtl);
|
|
253
|
+
if (!onV3 && json.subscription) {
|
|
254
|
+
var sub = json.subscription;
|
|
255
|
+
var subLimit = toFiniteNumber(sub.limit);
|
|
256
|
+
if (subLimit !== null) {
|
|
257
|
+
var subReq = toFiniteNumber(sub.requests);
|
|
258
|
+
if (subReq === null) subReq = 0;
|
|
259
|
+
var subOpts = {
|
|
260
|
+
label: "Subscription",
|
|
261
|
+
used: subReq,
|
|
262
|
+
limit: subLimit,
|
|
263
|
+
format: { kind: "count", suffix: "requests" },
|
|
264
|
+
};
|
|
265
|
+
var subReset = ctx.util.toIso(sub.renewsAt);
|
|
266
|
+
if (subReset) subOpts.resetsAt = subReset;
|
|
267
|
+
lines.push(ctx.line.progress(subOpts));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Free Tool Calls — legacy only, zeroed out on v3
|
|
272
|
+
var ftc = pickFreeToolCalls(json);
|
|
273
|
+
if (!onV3 && ftc) {
|
|
274
|
+
var ftcLimit = toFiniteNumber(ftc.limit);
|
|
275
|
+
if (ftcLimit !== null && ftcLimit > 0) {
|
|
276
|
+
var ftcReq = toFiniteNumber(ftc.requests);
|
|
277
|
+
if (ftcReq === null) ftcReq = 0;
|
|
278
|
+
var ftcOpts = {
|
|
279
|
+
label: "Free Tool Calls",
|
|
280
|
+
used: Math.round(ftcReq),
|
|
281
|
+
limit: ftcLimit,
|
|
282
|
+
format: { kind: "count", suffix: "requests" },
|
|
283
|
+
};
|
|
284
|
+
var ftcReset = ctx.util.toIso(ftc.renewsAt);
|
|
285
|
+
if (ftcReset) ftcOpts.resetsAt = ftcReset;
|
|
286
|
+
lines.push(ctx.line.progress(ftcOpts));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Search — hourly search quota (detail)
|
|
291
|
+
if (json.search && json.search.hourly) {
|
|
292
|
+
var srch = json.search.hourly;
|
|
293
|
+
var srchLimit = toFiniteNumber(srch.limit);
|
|
294
|
+
if (srchLimit !== null) {
|
|
295
|
+
var srchReq = toFiniteNumber(srch.requests);
|
|
296
|
+
if (srchReq === null) srchReq = 0;
|
|
297
|
+
var srchOpts = {
|
|
298
|
+
label: "Search",
|
|
299
|
+
used: srchReq,
|
|
300
|
+
limit: srchLimit,
|
|
301
|
+
format: { kind: "count", suffix: "requests" },
|
|
302
|
+
periodDurationMs: ONE_HOUR_MS,
|
|
303
|
+
};
|
|
304
|
+
var srchReset = ctx.util.toIso(srch.renewsAt);
|
|
305
|
+
if (srchReset) srchOpts.resetsAt = srchReset;
|
|
306
|
+
lines.push(ctx.line.progress(srchOpts));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (lines.length === 0) {
|
|
311
|
+
var keys = Object.keys(json).filter(function (k) {
|
|
312
|
+
return k !== "data";
|
|
313
|
+
});
|
|
314
|
+
ctx.host.log.warn(
|
|
315
|
+
"Synthetic /v2/quotas: no quota rows matched; top-level keys: " + keys.join(", ")
|
|
316
|
+
);
|
|
317
|
+
lines.push(
|
|
318
|
+
ctx.line.badge({
|
|
319
|
+
label: "Quotas",
|
|
320
|
+
text:
|
|
321
|
+
"API OK — no fields matched (check Synthetic API changes or open a GitHub issue)",
|
|
322
|
+
color: "#64748b",
|
|
323
|
+
})
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return { lines: lines };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
globalThis.__openusage_plugin = { id: "synthetic", probe: probe };
|
|
331
|
+
})();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "synthetic",
|
|
4
|
+
"name": "Synthetic",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"icon": "icon.svg",
|
|
8
|
+
"brandColor": "#000000",
|
|
9
|
+
"lines": [
|
|
10
|
+
{ "type": "progress", "label": "5h Rate Limit", "scope": "overview", "primaryOrder": 1 },
|
|
11
|
+
{ "type": "progress", "label": "Mana Bar", "scope": "overview" },
|
|
12
|
+
{ "type": "badge", "label": "Rate Limited", "scope": "overview" },
|
|
13
|
+
{ "type": "badge", "label": "Quotas", "scope": "overview" },
|
|
14
|
+
{ "type": "progress", "label": "Subscription", "scope": "overview", "primaryOrder": 2 },
|
|
15
|
+
{ "type": "progress", "label": "Free Tool Calls", "scope": "detail" },
|
|
16
|
+
{ "type": "progress", "label": "Search", "scope": "overview" }
|
|
17
|
+
],
|
|
18
|
+
"supportedModes": ["api", "local"],
|
|
19
|
+
"autoMode": "local",
|
|
20
|
+
"links": [
|
|
21
|
+
{ "label": "Dashboard", "url": "https://synthetic.new/billing" }
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<title>T3 Chat</title>
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="bg" x1="256" y1="0" x2="256" y2="512" gradientUnits="userSpaceOnUse">
|
|
5
|
+
<stop offset="0" stop-color="#FF25B7"/>
|
|
6
|
+
<stop offset="1" stop-color="#8F005F"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<radialGradient id="bubble" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
|
|
10
|
+
gradientTransform="translate(240 210) rotate(90) scale(190 245)">
|
|
11
|
+
<stop offset="0" stop-color="#FFD6FF"/>
|
|
12
|
+
<stop offset="0.55" stop-color="#F8A4F7"/>
|
|
13
|
+
<stop offset="1" stop-color="#EF79E8"/>
|
|
14
|
+
</radialGradient>
|
|
15
|
+
|
|
16
|
+
<filter id="shadow" x="60" y="80" width="420" height="380" filterUnits="userSpaceOnUse">
|
|
17
|
+
<feDropShadow dx="18" dy="28" stdDeviation="20" flood-color="#5A003B" flood-opacity="0.45"/>
|
|
18
|
+
</filter>
|
|
19
|
+
</defs>
|
|
20
|
+
|
|
21
|
+
<rect width="512" height="512" rx="92" fill="url(#bg)"/>
|
|
22
|
+
|
|
23
|
+
<path
|
|
24
|
+
filter="url(#shadow)"
|
|
25
|
+
fill="url(#bubble)"
|
|
26
|
+
d="M434.5 238.5C434.5 314.8 354.6 376.7 256 376.7C240.1 376.7 224.7 375.1 210 372.1L120.1 408.8C116.5 410.3 112.7 407.4 113.2 403.5L123.5 330.8C94.6 306.4 77.5 274.2 77.5 238.5C77.5 162.2 157.4 100.3 256 100.3C354.6 100.3 434.5 162.2 434.5 238.5Z"
|
|
27
|
+
/>
|
|
28
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg fill="currentColor" height="1em" style="flex:none;line-height:1" viewBox="0 0 512 512" width="1em" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<title>T3 Chat</title>
|
|
3
|
+
<path d="M434.5 238.5C434.5 314.8 354.6 376.7 256 376.7C240.1 376.7 224.7 375.1 210 372.1L120.1 408.8C116.5 410.3 112.7 407.4 113.2 403.5L123.5 330.8C94.6 306.4 77.5 274.2 77.5 238.5C77.5 162.2 157.4 100.3 256 100.3C354.6 100.3 434.5 162.2 434.5 238.5Z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
const INPUT = '{"0":{"json":{"sessionId":null},"meta":{"values":{"sessionId":["undefined"]}}}}'
|
|
3
|
+
const CUSTOMER_DATA_URL =
|
|
4
|
+
"https://t3.chat/api/trpc/getCustomerData?batch=1&input=" + encodeURIComponent(INPUT)
|
|
5
|
+
const FORWARDED_HEADERS = {
|
|
6
|
+
"accept": "Accept",
|
|
7
|
+
"accept-language": "Accept-Language",
|
|
8
|
+
"cache-control": "Cache-Control",
|
|
9
|
+
"pragma": "Pragma",
|
|
10
|
+
"priority": "Priority",
|
|
11
|
+
"referer": "Referer",
|
|
12
|
+
"sec-fetch-dest": "Sec-Fetch-Dest",
|
|
13
|
+
"sec-fetch-mode": "Sec-Fetch-Mode",
|
|
14
|
+
"sec-fetch-site": "Sec-Fetch-Site",
|
|
15
|
+
"trpc-accept": "trpc-accept",
|
|
16
|
+
"user-agent": "User-Agent",
|
|
17
|
+
"x-client-context": "x-client-context",
|
|
18
|
+
"x-deployment-id": "X-Deployment-Id",
|
|
19
|
+
"x-trpc-batch": "x-trpc-batch",
|
|
20
|
+
"x-trpc-source": "x-trpc-source",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function rawCredential(ctx) {
|
|
24
|
+
return (
|
|
25
|
+
(ctx.provider && ctx.provider.cookieHeader) ||
|
|
26
|
+
ctx.host.env.get("T3CHAT_COOKIE") ||
|
|
27
|
+
ctx.host.env.get("T3_CHAT_COOKIE") ||
|
|
28
|
+
""
|
|
29
|
+
).trim()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function unquoteShell(value) {
|
|
33
|
+
value = String(value || "").trim()
|
|
34
|
+
if (!value) return ""
|
|
35
|
+
if ((value[0] === "'" && value[value.length - 1] === "'") || (value[0] === '"' && value[value.length - 1] === '"')) {
|
|
36
|
+
value = value.slice(1, -1)
|
|
37
|
+
}
|
|
38
|
+
return value.replace(/\\'/g, "'").replace(/\\"/g, '"').replace(/\\\\/g, "\\")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function headerFieldsFromCurl(raw) {
|
|
42
|
+
const fields = []
|
|
43
|
+
const text = String(raw || "")
|
|
44
|
+
const re = /(?:^|\s)(?:-H|--header)(?:\s+|=)(?:"([^"]*)"|'([^']*)'|(\S+))/g
|
|
45
|
+
let match
|
|
46
|
+
while ((match = re.exec(text)) !== null) {
|
|
47
|
+
fields.push(unquoteShell(match[1] || match[2] || match[3] || ""))
|
|
48
|
+
}
|
|
49
|
+
return fields
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function cookieFieldsFromCurl(raw) {
|
|
53
|
+
const fields = []
|
|
54
|
+
const text = String(raw || "")
|
|
55
|
+
const re = /(?:^|\s)(?:-b|--cookie)(?:\s+|=)(?:"([^"]*)"|'([^']*)'|(\S+))/g
|
|
56
|
+
let match
|
|
57
|
+
while ((match = re.exec(text)) !== null) {
|
|
58
|
+
fields.push(unquoteShell(match[1] || match[2] || match[3] || ""))
|
|
59
|
+
}
|
|
60
|
+
return fields
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function requestContext(raw) {
|
|
64
|
+
raw = String(raw || "").trim()
|
|
65
|
+
if (!raw) return null
|
|
66
|
+
const fields = headerFieldsFromCurl(raw)
|
|
67
|
+
const cookieFields = cookieFieldsFromCurl(raw)
|
|
68
|
+
if (!fields.length && !cookieFields.length) return { cookieHeader: raw, headers: {} }
|
|
69
|
+
|
|
70
|
+
let cookie = ""
|
|
71
|
+
const headers = {}
|
|
72
|
+
if (cookieFields.length) {
|
|
73
|
+
cookie = cookieFields[cookieFields.length - 1]
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < fields.length; i += 1) {
|
|
76
|
+
const field = fields[i]
|
|
77
|
+
const idx = field.indexOf(":")
|
|
78
|
+
if (idx === -1) continue
|
|
79
|
+
const name = field.slice(0, idx).trim()
|
|
80
|
+
const value = field.slice(idx + 1).trim()
|
|
81
|
+
if (!name || !value) continue
|
|
82
|
+
if (name.toLowerCase() === "cookie") {
|
|
83
|
+
cookie = value
|
|
84
|
+
continue
|
|
85
|
+
}
|
|
86
|
+
const canonical = FORWARDED_HEADERS[name.toLowerCase()]
|
|
87
|
+
if (canonical) headers[canonical] = value
|
|
88
|
+
}
|
|
89
|
+
return cookie ? { cookieHeader: cookie, headers: headers } : null
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function findCustomerData(value) {
|
|
93
|
+
if (!value || typeof value !== "object") return null
|
|
94
|
+
if (
|
|
95
|
+
value.usageFourHourPercentage !== undefined ||
|
|
96
|
+
value.usageMonthPercentage !== undefined ||
|
|
97
|
+
(value.subscription && value.usageBand !== undefined)
|
|
98
|
+
) {
|
|
99
|
+
return value
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(value)) {
|
|
102
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
103
|
+
const found = findCustomerData(value[i])
|
|
104
|
+
if (found) return found
|
|
105
|
+
}
|
|
106
|
+
return null
|
|
107
|
+
}
|
|
108
|
+
for (const key in value) {
|
|
109
|
+
const found = findCustomerData(value[key])
|
|
110
|
+
if (found) return found
|
|
111
|
+
}
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function parseCustomerData(text) {
|
|
116
|
+
const lines = String(text || "").split(/\r?\n/)
|
|
117
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
118
|
+
const line = lines[i].trim()
|
|
119
|
+
if (!line) continue
|
|
120
|
+
const parsed = ctxSafeJson(line)
|
|
121
|
+
const customer = findCustomerData(parsed)
|
|
122
|
+
if (customer) return customer
|
|
123
|
+
}
|
|
124
|
+
const parsed = ctxSafeJson(text)
|
|
125
|
+
const customer = findCustomerData(parsed)
|
|
126
|
+
if (customer) return customer
|
|
127
|
+
throw "Could not parse T3 Chat usage: missing customer data object."
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function ctxSafeJson(text) {
|
|
131
|
+
try {
|
|
132
|
+
return JSON.parse(text)
|
|
133
|
+
} catch (_) {
|
|
134
|
+
return null
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function percent(value) {
|
|
139
|
+
const n = Number(value)
|
|
140
|
+
if (!Number.isFinite(n)) return 0
|
|
141
|
+
return Math.max(0, Math.min(100, n))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function isoFromEpoch(value) {
|
|
145
|
+
const n = Number(value)
|
|
146
|
+
if (!Number.isFinite(n) || n <= 0) return null
|
|
147
|
+
const ms = n > 10000000000 ? n : n * 1000
|
|
148
|
+
return new Date(ms).toISOString()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function planLabel(data) {
|
|
152
|
+
const raw =
|
|
153
|
+
(data.subscription && data.subscription.productName) ||
|
|
154
|
+
data.subTier ||
|
|
155
|
+
""
|
|
156
|
+
return String(raw).trim().replace(/[-_]+/g, " ").replace(/\b\w/g, function (c) {
|
|
157
|
+
return c.toUpperCase()
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function isVercelChallenge(resp) {
|
|
162
|
+
if (!resp) return false
|
|
163
|
+
const headers = resp.headers || {}
|
|
164
|
+
const mitigated =
|
|
165
|
+
headers["x-vercel-mitigated"] ||
|
|
166
|
+
headers["X-Vercel-Mitigated"] ||
|
|
167
|
+
headers["X-Vercel-mitigated"]
|
|
168
|
+
return (
|
|
169
|
+
Number(resp.status) === 429 &&
|
|
170
|
+
String(mitigated || "").toLowerCase() === "challenge"
|
|
171
|
+
) || String(resp.bodyText || "").indexOf("Vercel") !== -1
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function probe(ctx) {
|
|
175
|
+
const requestCtx = requestContext(rawCredential(ctx))
|
|
176
|
+
if (!requestCtx || !requestCtx.cookieHeader) {
|
|
177
|
+
throw "T3 Chat session not configured. Paste a full browser cURL capture into the Cookie header field, or set T3CHAT_COOKIE/T3_CHAT_COOKIE."
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const headers = {
|
|
181
|
+
Accept: "*/*",
|
|
182
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
183
|
+
"Cache-Control": "no-cache",
|
|
184
|
+
Cookie: requestCtx.cookieHeader,
|
|
185
|
+
Pragma: "no-cache",
|
|
186
|
+
Priority: "u=4",
|
|
187
|
+
Referer: "https://t3.chat/settings/customization",
|
|
188
|
+
"Sec-Fetch-Dest": "empty",
|
|
189
|
+
"Sec-Fetch-Mode": "cors",
|
|
190
|
+
"Sec-Fetch-Site": "same-origin",
|
|
191
|
+
"User-Agent":
|
|
192
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
|
|
193
|
+
"trpc-accept": "application/jsonl",
|
|
194
|
+
"x-trpc-batch": "true",
|
|
195
|
+
"x-trpc-source": "web-client",
|
|
196
|
+
}
|
|
197
|
+
if (requestCtx && requestCtx.headers) {
|
|
198
|
+
for (const name in requestCtx.headers) headers[name] = requestCtx.headers[name]
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const resp = ctx.util.request({
|
|
202
|
+
method: "GET",
|
|
203
|
+
url: CUSTOMER_DATA_URL,
|
|
204
|
+
headers: headers,
|
|
205
|
+
timeoutMs: 15000,
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
if ((resp.status < 200 || resp.status >= 300) && isVercelChallenge(resp)) {
|
|
209
|
+
throw "T3 Chat returned a Vercel security challenge. Paste the full browser cURL request into the Cookie header field. Run `usagestat auth curl --provider t3chat` for steps."
|
|
210
|
+
}
|
|
211
|
+
if (ctx.util.isAuthStatus(resp.status)) throw "T3 Chat session cookie is invalid or expired."
|
|
212
|
+
if (resp.status < 200 || resp.status >= 300) throw "T3 Chat API error (HTTP " + resp.status + ")."
|
|
213
|
+
|
|
214
|
+
const data = parseCustomerData(resp.bodyText)
|
|
215
|
+
const lines = []
|
|
216
|
+
lines.push(ctx.line.progress({
|
|
217
|
+
label: "Base",
|
|
218
|
+
used: percent(data.usageFourHourPercentage || data.usagePeriodPercentage),
|
|
219
|
+
limit: 100,
|
|
220
|
+
resetsAt: isoFromEpoch(data.usageFourHourNextResetAt || data.usageWindowNextResetAt),
|
|
221
|
+
periodDurationMs: 4 * 60 * 60 * 1000,
|
|
222
|
+
format: { kind: "percent" },
|
|
223
|
+
}))
|
|
224
|
+
lines.push(ctx.line.progress({
|
|
225
|
+
label: "Overage",
|
|
226
|
+
used: percent(data.usageMonthPercentage || data.usagePeriodPercentage),
|
|
227
|
+
limit: 100,
|
|
228
|
+
resetsAt: isoFromEpoch(data.subscription && data.subscription.currentPeriodEnd),
|
|
229
|
+
format: { kind: "percent" },
|
|
230
|
+
}))
|
|
231
|
+
if (data.lifetimeBalance !== undefined && data.lifetimeBalance !== null) {
|
|
232
|
+
lines.push(ctx.line.text({ label: "Balance", value: String(data.lifetimeBalance) }))
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
source: "web",
|
|
237
|
+
plan: planLabel(data),
|
|
238
|
+
lines: lines,
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
globalThis.__openusage_plugin = { id: "t3chat", probe: probe };
|
|
243
|
+
})();
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "t3chat",
|
|
4
|
+
"name": "T3 Chat",
|
|
5
|
+
"version": "0.0.1",
|
|
6
|
+
"entry": "plugin.js",
|
|
7
|
+
"brandColor": "#F56647",
|
|
8
|
+
"links": [
|
|
9
|
+
{ "label": "Customization", "url": "https://t3.chat/settings/customization" },
|
|
10
|
+
{ "label": "Subscription", "url": "https://t3.chat/settings/subscription" }
|
|
11
|
+
],
|
|
12
|
+
"usageDashboardUrl": "https://t3.chat/settings/customization",
|
|
13
|
+
"supportedModes": ["web"],
|
|
14
|
+
"autoMode": "web",
|
|
15
|
+
"webUrl": "https://t3.chat",
|
|
16
|
+
"lines": [
|
|
17
|
+
{ "type": "progress", "label": "Base", "scope": "overview", "primaryOrder": 1 },
|
|
18
|
+
{ "type": "progress", "label": "Overage", "scope": "detail" }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Venice</title><path clip-rule="evenodd" d="M8.295 16.074a4.239 4.239 0 00-1.37-.685 4.255 4.255 0 00-1.636-.138 4.27 4.27 0 00-1.566.499c-.472.26-.875.602-1.19.973-.315.37-.59.824-.773 1.336a4.432 4.432 0 00-.257 1.644c.02.564.155 1.125.375 1.621s.528.93.87 1.275c.34.346.766.657 1.256.881.49.224 1.041.36 1.598.381a4.258 4.258 0 001.62-.26 4.25 4.25 0 001.318-.786c.365-.319.703-.728.959-1.206.256-.479.43-1.027.492-1.589a4.436 4.436 0 00-.137-1.659 4.346 4.346 0 00-.675-1.39l.95-.964.691.702h.393l.475-.481v-.399l-.692-.702L12 14.11l1.004 1.018-.691.702v.399l.474.48h.393l.691-.701.95.964a4.346 4.346 0 00-.675 1.39 4.435 4.435 0 00-.137 1.66c.062.56.236 1.11.492 1.588s.594.887.96 1.206c.364.32.812.599 1.316.785a4.258 4.258 0 001.621.261 4.262 4.262 0 001.598-.38c.49-.225.916-.536 1.257-.882.341-.346.648-.779.869-1.275.22-.496.355-1.057.375-1.62a4.433 4.433 0 00-.257-1.645 4.338 4.338 0 00-.774-1.336 4.272 4.272 0 00-1.189-.973 4.27 4.27 0 00-1.566-.5 4.255 4.255 0 00-1.635.14 4.239 4.239 0 00-1.37.684l-.933-.947.69-.702v-.398l-.49-.498h-.393l-.692.701-1.004-1.018L18.15 7.87l2.132 2.163v-2.25H22.5L20.368 5.62 22.5 3.457V3.06l-.491-.498h-.393L12 12.316 2.384 2.56H1.99l-.491.498v.398L3.632 5.62 1.5 7.782h2.218v2.25L5.85 7.87l5.266 5.342-1.004 1.018-.692-.701h-.393l-.49.498v.399l.69.7-.932.948zm8.546 4.95a1.59 1.59 0 00.107 1.49c.256.43.799.73 1.294.716.494.014 1.037-.287 1.293-.716a1.59 1.59 0 00.108-1.49l.054-.06a1.53 1.53 0 001.471-.107c.424-.26.72-.81.707-1.313.014-.502-.283-1.053-.707-1.313a1.53 1.53 0 00-1.471-.107l-.054-.059a1.59 1.59 0 00-.108-1.49c-.256-.43-.799-.73-1.293-.717-.495-.013-1.038.287-1.294.716a1.59 1.59 0 00-.107 1.491l-.054.059a1.53 1.53 0 00-1.472.107c-.424.26-.72.81-.707 1.313-.013.502.283 1.053.707 1.313a1.53 1.53 0 001.472.107l.054.06zm-9.79 1.49a1.59 1.59 0 00.108-1.49l.054-.06a1.53 1.53 0 001.471-.107c.424-.26.72-.81.707-1.313.014-.502-.283-1.053-.707-1.313a1.53 1.53 0 00-1.47-.107l-.055-.059a1.59 1.59 0 00-.107-1.49c-.257-.43-.8-.73-1.294-.717-.495-.013-1.037.287-1.294.716a1.59 1.59 0 00-.107 1.491l-.054.059a1.53 1.53 0 00-1.471.107c-.424.26-.72.81-.707 1.313-.014.502.283 1.053.707 1.313a1.53 1.53 0 001.471.107l.054.06a1.59 1.59 0 00.107 1.49c.257.43.8.73 1.294.716.495.014 1.037-.287 1.294-.716z" fill="#E05A2D" fill-rule="evenodd"></path><path clip-rule="evenodd" d="M12.274 2.56L14.8 0l1.25 1.268v4.274l-3.462 3.512h-.625L8.5 5.542V1.268L9.75 0l2.524 2.56zM9.75.898l2.212 2.243v4.12L9.75 5.018V.897zm2.837 2.243L14.799.897v4.12l-2.212 2.244V3.14z" fill="#E05A2D" fill-rule="evenodd"></path></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Venice</title><path clip-rule="evenodd" d="M8.295 16.074a4.239 4.239 0 00-1.37-.685 4.255 4.255 0 00-1.636-.138 4.27 4.27 0 00-1.566.499c-.472.26-.875.602-1.19.973-.315.37-.59.824-.773 1.336a4.432 4.432 0 00-.257 1.644c.02.564.155 1.125.375 1.621s.528.93.87 1.275c.34.346.766.657 1.256.881.49.224 1.041.36 1.598.381a4.258 4.258 0 001.62-.26 4.25 4.25 0 001.318-.786c.365-.319.703-.728.959-1.206.256-.479.43-1.027.492-1.589a4.436 4.436 0 00-.137-1.659 4.346 4.346 0 00-.675-1.39l.95-.964.691.702h.393l.475-.481v-.399l-.692-.702L12 14.11l1.004 1.018-.691.702v.399l.474.48h.393l.691-.701.95.964a4.346 4.346 0 00-.675 1.39 4.435 4.435 0 00-.137 1.66c.062.56.236 1.11.492 1.588s.594.887.96 1.206c.364.32.812.599 1.316.785a4.258 4.258 0 001.621.261 4.262 4.262 0 001.598-.38c.49-.225.916-.536 1.257-.882.341-.346.648-.779.869-1.275.22-.496.355-1.057.375-1.62a4.433 4.433 0 00-.257-1.645 4.338 4.338 0 00-.774-1.336 4.272 4.272 0 00-1.189-.973 4.27 4.27 0 00-1.566-.5 4.255 4.255 0 00-1.635.14 4.239 4.239 0 00-1.37.684l-.933-.947.69-.702v-.398l-.49-.498h-.393l-.692.701-1.004-1.018L18.15 7.87l2.132 2.163v-2.25H22.5L20.368 5.62 22.5 3.457V3.06l-.491-.498h-.393L12 12.316 2.384 2.56H1.99l-.491.498v.398L3.632 5.62 1.5 7.782h2.218v2.25L5.85 7.87l5.266 5.342-1.004 1.018-.692-.701h-.393l-.49.498v.399l.69.7-.932.948zm8.546 4.95a1.59 1.59 0 00.107 1.49c.256.43.799.73 1.294.716.494.014 1.037-.287 1.293-.716a1.59 1.59 0 00.108-1.49l.054-.06a1.53 1.53 0 001.471-.107c.424-.26.72-.81.707-1.313.014-.502-.283-1.053-.707-1.313a1.53 1.53 0 00-1.471-.107l-.054-.059a1.59 1.59 0 00-.108-1.49c-.256-.43-.799-.73-1.293-.717-.495-.013-1.038.287-1.294.716a1.59 1.59 0 00-.107 1.491l-.054.059a1.53 1.53 0 00-1.472.107c-.424.26-.72.81-.707 1.313-.013.502.283 1.053.707 1.313a1.53 1.53 0 001.472.107l.054.06zm-9.79 1.49a1.59 1.59 0 00.108-1.49l.054-.06a1.53 1.53 0 001.471-.107c.424-.26.72-.81.707-1.313.014-.502-.283-1.053-.707-1.313a1.53 1.53 0 00-1.47-.107l-.055-.059a1.59 1.59 0 00-.107-1.49c-.257-.43-.8-.73-1.294-.717-.495-.013-1.037.287-1.294.716a1.59 1.59 0 00-.107 1.491l-.054.059a1.53 1.53 0 00-1.471.107c-.424.26-.72.81-.707 1.313-.014.502.283 1.053.707 1.313a1.53 1.53 0 001.471.107l.054.06a1.59 1.59 0 00.107 1.49c.257.43.8.73 1.294.716.495.014 1.037-.287 1.294-.716z"></path><path clip-rule="evenodd" d="M12.274 2.56L14.8 0l1.25 1.268v4.274l-3.462 3.512h-.625L8.5 5.542V1.268L9.75 0l2.524 2.56zM9.75.898l2.212 2.243v4.12L9.75 5.018V.897zm2.837 2.243L14.799.897v4.12l-2.212 2.244V3.14z"></path></svg>
|