@bitkyc08/opencodex 2.6.15 → 2.6.16
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/gui/dist/assets/{index-4jSPBLbx.js → index-D3GNd8DI.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic.ts +14 -1
- package/src/bridge.ts +4 -2
- package/src/types.ts +2 -0
- package/src/usage-log.ts +4 -2
- package/src/usage-summary.ts +6 -10
- package/src/usage-totals.ts +25 -0
package/gui/dist/index.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
} catch (e) {}
|
|
17
17
|
})();
|
|
18
18
|
</script>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-D3GNd8DI.js"></script>
|
|
20
20
|
<link rel="stylesheet" crossorigin href="/assets/index-DIBiVVC0.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
package/package.json
CHANGED
|
@@ -47,6 +47,14 @@ function withPromptCache<T extends Record<string, unknown>>(block: T): T & { cac
|
|
|
47
47
|
return { ...block, cache_control: EPHEMERAL_CACHE_CONTROL };
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
function usesNativeAnthropicEndpoint(provider: OcxProviderConfig): boolean {
|
|
51
|
+
try {
|
|
52
|
+
return new URL(provider.baseUrl).hostname === "api.anthropic.com";
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
50
58
|
/** Map a Responses reasoning effort to an Anthropic extended-thinking budget (tokens, >= 1024). */
|
|
51
59
|
function reasoningBudget(effort: string): number {
|
|
52
60
|
switch (effort) {
|
|
@@ -66,7 +74,11 @@ function usageFromAnthropic(usage: Record<string, number> | undefined): OcxUsage
|
|
|
66
74
|
return {
|
|
67
75
|
inputTokens: usage.input_tokens ?? 0,
|
|
68
76
|
outputTokens: usage.output_tokens ?? 0,
|
|
69
|
-
...(hasCache ? {
|
|
77
|
+
...(hasCache ? {
|
|
78
|
+
cachedInputTokens: (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0),
|
|
79
|
+
cacheReadInputTokens: usage.cache_read_input_tokens ?? 0,
|
|
80
|
+
cacheCreationInputTokens: usage.cache_creation_input_tokens ?? 0,
|
|
81
|
+
} : {}),
|
|
70
82
|
};
|
|
71
83
|
}
|
|
72
84
|
|
|
@@ -234,6 +246,7 @@ export function createAnthropicAdapter(provider: OcxProviderConfig): ProviderAda
|
|
|
234
246
|
stream: parsed.stream,
|
|
235
247
|
max_tokens: parsed.options.maxOutputTokens ?? DEFAULT_MAX_TOKENS,
|
|
236
248
|
};
|
|
249
|
+
if (usesNativeAnthropicEndpoint(provider)) body.cache_control = EPHEMERAL_CACHE_CONTROL;
|
|
237
250
|
if (isOAuth) {
|
|
238
251
|
// Claude OAuth (Pro/Max) requires the first system block to be the Claude Code identity.
|
|
239
252
|
body.system = [
|
package/src/bridge.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AdapterEvent, OcxUsage } from "./types";
|
|
2
2
|
import { classifyError, type OcxErrorPayload } from "./errors";
|
|
3
|
+
import { usageDisplayTotalTokens, usageInputTokensWithCacheDetail } from "./usage-totals";
|
|
3
4
|
|
|
4
5
|
function uuid(): string {
|
|
5
6
|
return crypto.randomUUID().replace(/-/g, "");
|
|
@@ -11,10 +12,11 @@ function sseEvent(name: string, data: Record<string, unknown>): string {
|
|
|
11
12
|
|
|
12
13
|
function responsesUsage(usage: OcxUsage | undefined): Record<string, unknown> {
|
|
13
14
|
if (!usage) return { input_tokens: 0, output_tokens: 0, total_tokens: 0 };
|
|
15
|
+
const inputTokens = usageInputTokensWithCacheDetail(usage);
|
|
14
16
|
const out: Record<string, unknown> = {
|
|
15
|
-
input_tokens:
|
|
17
|
+
input_tokens: inputTokens,
|
|
16
18
|
output_tokens: usage.outputTokens,
|
|
17
|
-
total_tokens: usage
|
|
19
|
+
total_tokens: usageDisplayTotalTokens(usage) ?? inputTokens + usage.outputTokens,
|
|
18
20
|
};
|
|
19
21
|
if (usage.cachedInputTokens !== undefined) {
|
|
20
22
|
out.input_tokens_details = { cached_tokens: usage.cachedInputTokens };
|
package/src/types.ts
CHANGED
|
@@ -209,6 +209,8 @@ export interface OcxUsage {
|
|
|
209
209
|
outputTokens: number;
|
|
210
210
|
totalTokens?: number;
|
|
211
211
|
cachedInputTokens?: number;
|
|
212
|
+
cacheReadInputTokens?: number;
|
|
213
|
+
cacheCreationInputTokens?: number;
|
|
212
214
|
reasoningOutputTokens?: number;
|
|
213
215
|
estimated?: boolean;
|
|
214
216
|
}
|
package/src/usage-log.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { chmodSync, existsSync, mkdirSync, readFileSync, appendFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { getConfigDir } from "./config";
|
|
4
|
+
import { usageDisplayTotalTokens } from "./usage-totals";
|
|
4
5
|
import type { OcxUsage } from "./types";
|
|
5
6
|
|
|
6
7
|
export type UsageStatus = "reported" | "unreported" | "unsupported" | "estimated";
|
|
@@ -23,8 +24,7 @@ export function usageLogPath(): string {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export function usageTotalTokens(usage: OcxUsage | undefined): number | undefined {
|
|
26
|
-
|
|
27
|
-
return usage.totalTokens ?? usage.inputTokens + usage.outputTokens;
|
|
27
|
+
return usageDisplayTotalTokens(usage);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function isKiroLogProvider(provider: string): boolean {
|
|
@@ -49,6 +49,8 @@ function normalizeUsageValue(usage: OcxUsage | undefined): OcxUsage | undefined
|
|
|
49
49
|
outputTokens: usage.outputTokens,
|
|
50
50
|
...(typeof usage.totalTokens === "number" ? { totalTokens: usage.totalTokens } : {}),
|
|
51
51
|
...(typeof usage.cachedInputTokens === "number" ? { cachedInputTokens: usage.cachedInputTokens } : {}),
|
|
52
|
+
...(typeof usage.cacheReadInputTokens === "number" ? { cacheReadInputTokens: usage.cacheReadInputTokens } : {}),
|
|
53
|
+
...(typeof usage.cacheCreationInputTokens === "number" ? { cacheCreationInputTokens: usage.cacheCreationInputTokens } : {}),
|
|
52
54
|
...(typeof usage.reasoningOutputTokens === "number" ? { reasoningOutputTokens: usage.reasoningOutputTokens } : {}),
|
|
53
55
|
...(usage.estimated ? { estimated: true } : {}),
|
|
54
56
|
};
|
package/src/usage-summary.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { baseProviderLabel } from "./provider-label";
|
|
2
|
+
import { usageDisplayTotalTokens } from "./usage-totals";
|
|
2
3
|
import type { PersistedUsageEntry, UsageStatus } from "./usage-log";
|
|
3
4
|
|
|
4
5
|
export type UsageRange = "7d" | "30d" | "all";
|
|
@@ -132,8 +133,7 @@ function addTokens(totals: UsageSummaryTotals, entry: PersistedUsageEntry): void
|
|
|
132
133
|
totals.outputTokens += entry.usage.outputTokens;
|
|
133
134
|
if (typeof entry.usage.cachedInputTokens === "number") totals.cachedInputTokens += entry.usage.cachedInputTokens;
|
|
134
135
|
if (typeof entry.usage.reasoningOutputTokens === "number") totals.reasoningOutputTokens += entry.usage.reasoningOutputTokens;
|
|
135
|
-
|
|
136
|
-
else totals.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
136
|
+
totals.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
function finalizeCoverage(totals: UsageSummaryTotals): void {
|
|
@@ -154,8 +154,7 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
|
|
|
154
154
|
let m = models.get(mKey);
|
|
155
155
|
if (!m) { m = { model: entry.model, provider: entry.provider, requests: 0, totalTokens: 0 }; models.set(mKey, m); }
|
|
156
156
|
m.requests += 1;
|
|
157
|
-
|
|
158
|
-
else if (entry.usage) m.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
157
|
+
m.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
|
|
159
158
|
};
|
|
160
159
|
for (let i = days - 1; i >= 0; i--) {
|
|
161
160
|
const key = localDateKey(now - i * DAY_MS);
|
|
@@ -171,8 +170,7 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
|
|
|
171
170
|
day.requests += 1;
|
|
172
171
|
if (isMeasuredStatus(entry.usageStatus)) day.measuredRequests += 1;
|
|
173
172
|
if (entry.usageStatus === "reported") day.reportedRequests += 1;
|
|
174
|
-
|
|
175
|
-
else if (entry.usage) day.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
173
|
+
day.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
|
|
176
174
|
bumpDayModel(key, entry);
|
|
177
175
|
}
|
|
178
176
|
void since;
|
|
@@ -216,8 +214,7 @@ function buildModels(entries: PersistedUsageEntry[], totalRequests: number): Usa
|
|
|
216
214
|
if (entry.usage) {
|
|
217
215
|
model.inputTokens += entry.usage.inputTokens;
|
|
218
216
|
model.outputTokens += entry.usage.outputTokens;
|
|
219
|
-
|
|
220
|
-
else model.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
217
|
+
model.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
|
|
221
218
|
}
|
|
222
219
|
}
|
|
223
220
|
const models = [...byKey.values()];
|
|
@@ -247,8 +244,7 @@ function buildProviders(entries: PersistedUsageEntry[], totalRequests: number):
|
|
|
247
244
|
if (entry.usageStatus === "reported") provider.reportedRequests += 1;
|
|
248
245
|
else if (entry.usageStatus === "estimated") provider.estimatedRequests += 1;
|
|
249
246
|
if (entry.usage) {
|
|
250
|
-
|
|
251
|
-
else provider.totalTokens += entry.usage.inputTokens + entry.usage.outputTokens;
|
|
247
|
+
provider.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
|
|
252
248
|
}
|
|
253
249
|
}
|
|
254
250
|
const providers = [...byKey.values()];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { OcxUsage } from "./types";
|
|
2
|
+
|
|
3
|
+
function cacheDetailTokens(usage: OcxUsage): number | undefined {
|
|
4
|
+
const hasRead = typeof usage.cacheReadInputTokens === "number";
|
|
5
|
+
const hasCreate = typeof usage.cacheCreationInputTokens === "number";
|
|
6
|
+
if (!hasRead && !hasCreate) return undefined;
|
|
7
|
+
return (usage.cacheReadInputTokens ?? 0) + (usage.cacheCreationInputTokens ?? 0);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function usageInputTokensWithCacheDetail(usage: OcxUsage): number {
|
|
11
|
+
const cacheDetailTotal = cacheDetailTokens(usage);
|
|
12
|
+
return usage.inputTokens + (cacheDetailTotal ?? 0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function usageDisplayTotalTokens(usage: OcxUsage | undefined, storedTotal?: number): number | undefined {
|
|
16
|
+
if (!usage) return storedTotal;
|
|
17
|
+
const baseTotal = usage.inputTokens + usage.outputTokens;
|
|
18
|
+
const explicitTotal = usage.totalTokens ?? storedTotal;
|
|
19
|
+
const cacheDetailTotal = cacheDetailTokens(usage);
|
|
20
|
+
if (cacheDetailTotal !== undefined) {
|
|
21
|
+
const detailedTotal = baseTotal + cacheDetailTotal;
|
|
22
|
+
return typeof explicitTotal === "number" ? Math.max(explicitTotal, detailedTotal) : detailedTotal;
|
|
23
|
+
}
|
|
24
|
+
return explicitTotal ?? baseTotal;
|
|
25
|
+
}
|