@bitkyc08/opencodex 2.5.6 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.ko.md +17 -6
  2. package/README.md +19 -7
  3. package/README.zh-CN.md +12 -3
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/codex-app-picker.png +0 -0
  7. package/bin/ocx.mjs +88 -2
  8. package/bin/package-main.mjs +9 -0
  9. package/gui/dist/assets/index-BS4X1QDi.js +9 -0
  10. package/gui/dist/assets/{index-CKqUwc02.css → index-BwvDb198.css} +1 -1
  11. package/gui/dist/index.html +2 -2
  12. package/package.json +20 -6
  13. package/src/adapters/anthropic.ts +16 -5
  14. package/src/adapters/google.ts +9 -2
  15. package/src/adapters/openai-chat.ts +13 -5
  16. package/src/bun-runtime.ts +22 -1
  17. package/src/cli-help.ts +111 -0
  18. package/src/cli-status.ts +164 -0
  19. package/src/cli.ts +77 -186
  20. package/src/codex-account-store.ts +47 -8
  21. package/src/codex-auth-api.ts +111 -54
  22. package/src/codex-auth-collision.ts +5 -0
  23. package/src/codex-catalog.ts +24 -12
  24. package/src/codex-history-provider.ts +29 -13
  25. package/src/codex-inject.ts +46 -29
  26. package/src/codex-journal.ts +77 -13
  27. package/src/codex-quota.ts +11 -3
  28. package/src/codex-routing.ts +14 -4
  29. package/src/codex-shim.ts +71 -24
  30. package/src/codex-websocket-registry.ts +20 -4
  31. package/src/config.ts +138 -4
  32. package/src/init.ts +7 -2
  33. package/src/oauth/callback-server.ts +22 -15
  34. package/src/oauth/index.ts +18 -4
  35. package/src/oauth/login-cli.ts +8 -1
  36. package/src/oauth/store.ts +2 -1
  37. package/src/process-control.ts +36 -0
  38. package/src/provider-label.ts +8 -0
  39. package/src/responses/parser.ts +18 -1
  40. package/src/router.ts +61 -5
  41. package/src/server.ts +878 -94
  42. package/src/service-secrets.ts +6 -0
  43. package/src/service.ts +293 -28
  44. package/src/types.ts +26 -1
  45. package/src/update.ts +16 -9
  46. package/src/usage-debug.ts +65 -0
  47. package/src/usage-log.ts +62 -0
  48. package/src/usage-summary.ts +0 -0
  49. package/src/ws-bridge.ts +2 -2
  50. package/gui/README.md +0 -73
  51. package/gui/dist/assets/index-CSUvRNAX.js +0 -9
@@ -0,0 +1,65 @@
1
+ import { appendFileSync, chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getConfigDir } from "./config";
4
+ import type { OcxUsage } from "./types";
5
+
6
+ export const USAGE_DEBUG_ENV = "OPENCODEX_USAGE_DEBUG";
7
+ export const USAGE_DEBUG_BODY_SAMPLE_BYTES = 2048;
8
+ export const USAGE_DEBUG_MAX_LINES = 200;
9
+ export const USAGE_DEBUG_KEEP_LINES = 100;
10
+
11
+ export type UsageDebugBodyKind = "sse" | "json" | "other" | "none";
12
+
13
+ export interface UsageDebugRecord {
14
+ ts: number;
15
+ requestId: string;
16
+ provider: string;
17
+ model: string;
18
+ upstreamContentType: string | null;
19
+ upstreamStatus: number;
20
+ bodyKind: UsageDebugBodyKind;
21
+ bodySample: string;
22
+ extractedUsage: OcxUsage | null;
23
+ }
24
+
25
+ export function isUsageDebugEnabled(): boolean {
26
+ return process.env[USAGE_DEBUG_ENV] === "1";
27
+ }
28
+
29
+ export function usageDebugPath(): string {
30
+ return join(getConfigDir(), "usage-debug.jsonl");
31
+ }
32
+
33
+ export function truncateForDebug(text: string, max = USAGE_DEBUG_BODY_SAMPLE_BYTES): string {
34
+ if (text.length <= max) return text;
35
+ const cut = text.slice(0, max);
36
+ const remaining = text.length - max;
37
+ return `${cut}... [+${remaining} more]`;
38
+ }
39
+
40
+ function ensureUsageDebugDir(): void {
41
+ const dir = getConfigDir();
42
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
43
+ try { chmodSync(dir, 0o700); } catch { /* best-effort */ }
44
+ }
45
+
46
+ function trimRollingFile(path: string): void {
47
+ const text = readFileSync(path, "utf-8");
48
+ const lines = text.split(/\r?\n/).filter(line => line.length > 0);
49
+ if (lines.length <= USAGE_DEBUG_MAX_LINES) return;
50
+ const kept = lines.slice(-USAGE_DEBUG_KEEP_LINES).join("\n") + "\n";
51
+ writeFileSync(path, kept, { encoding: "utf-8", mode: 0o600 });
52
+ try { chmodSync(path, 0o600); } catch { /* best-effort */ }
53
+ }
54
+
55
+ export function appendUsageDebug(record: UsageDebugRecord): void {
56
+ try {
57
+ ensureUsageDebugDir();
58
+ const path = usageDebugPath();
59
+ appendFileSync(path, `${JSON.stringify(record)}\n`, { encoding: "utf-8", mode: 0o600 });
60
+ try { chmodSync(path, 0o600); } catch { /* best-effort */ }
61
+ if (existsSync(path)) trimRollingFile(path);
62
+ } catch {
63
+ /* debug capture must never break the proxy */
64
+ }
65
+ }
@@ -0,0 +1,62 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, appendFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getConfigDir } from "./config";
4
+ import type { OcxUsage } from "./types";
5
+
6
+ export type UsageStatus = "reported" | "unreported" | "unsupported" | "estimated";
7
+
8
+ export interface PersistedUsageEntry {
9
+ requestId: string;
10
+ timestamp: number;
11
+ provider: string;
12
+ model: string;
13
+ resolvedModel?: string;
14
+ status: number;
15
+ durationMs: number;
16
+ usageStatus: UsageStatus;
17
+ usage?: OcxUsage;
18
+ totalTokens?: number;
19
+ }
20
+
21
+ export function usageLogPath(): string {
22
+ return join(getConfigDir(), "usage.jsonl");
23
+ }
24
+
25
+ export function usageTotalTokens(usage: OcxUsage | undefined): number | undefined {
26
+ if (!usage) return undefined;
27
+ return usage.inputTokens + usage.outputTokens;
28
+ }
29
+
30
+ export function usageStatusForFinalLog(usage: OcxUsage | undefined): UsageStatus {
31
+ return usage ? "reported" : "unreported";
32
+ }
33
+
34
+ function ensureUsageLogDir(): void {
35
+ const dir = getConfigDir();
36
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
37
+ try { chmodSync(dir, 0o700); } catch { /* best-effort on platforms that ignore chmod */ }
38
+ }
39
+
40
+ export function appendUsageEntry(entry: PersistedUsageEntry): void {
41
+ ensureUsageLogDir();
42
+ const path = usageLogPath();
43
+ appendFileSync(path, `${JSON.stringify(entry)}\n`, { encoding: "utf-8", mode: 0o600 });
44
+ try { chmodSync(path, 0o600); } catch { /* best-effort on platforms that ignore chmod */ }
45
+ }
46
+
47
+ export function readUsageEntries(): PersistedUsageEntry[] {
48
+ const path = usageLogPath();
49
+ if (!existsSync(path)) return [];
50
+ const lines = readFileSync(path, "utf-8").split(/\r?\n/);
51
+ const entries: PersistedUsageEntry[] = [];
52
+ for (const line of lines) {
53
+ if (!line.trim()) continue;
54
+ try {
55
+ const parsed = JSON.parse(line) as PersistedUsageEntry;
56
+ if (parsed && typeof parsed === "object" && typeof parsed.requestId === "string") entries.push(parsed);
57
+ } catch {
58
+ /* keep reading after a partially written or hand-edited line */
59
+ }
60
+ }
61
+ return entries;
62
+ }
Binary file
package/src/ws-bridge.ts CHANGED
@@ -17,8 +17,8 @@ const SAFE_RESPONSE_HEADER_EXACT = new Set([
17
17
  ]);
18
18
 
19
19
  export interface WsData {
20
- headers?: Headers; // selected inbound upgrade headers only; never store full cookies/handshake internals
21
- authContext?: CodexAuthContext; // immutable account decision made at upgrade time
20
+ headers?: Headers; // base inbound forward headers only; per-turn auth refresh injects current pool tokens
21
+ authContext?: CodexAuthContext; // last resolved account decision for observability/registry cleanup
22
22
  cancel?: () => void; // cancels the in-flight stream reader/fetch
23
23
  turnId?: number; // monotonically increasing per socket; prevents stale frames after replacement turns
24
24
  }
package/gui/README.md DELETED
@@ -1,73 +0,0 @@
1
- # React + TypeScript + Vite
2
-
3
- This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
-
5
- Currently, two official plugins are available:
6
-
7
- - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
8
- - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
9
-
10
- ## React Compiler
11
-
12
- The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
-
14
- ## Expanding the ESLint configuration
15
-
16
- If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
-
18
- ```js
19
- export default defineConfig([
20
- globalIgnores(['dist']),
21
- {
22
- files: ['**/*.{ts,tsx}'],
23
- extends: [
24
- // Other configs...
25
-
26
- // Remove tseslint.configs.recommended and replace with this
27
- tseslint.configs.recommendedTypeChecked,
28
- // Alternatively, use this for stricter rules
29
- tseslint.configs.strictTypeChecked,
30
- // Optionally, add this for stylistic rules
31
- tseslint.configs.stylisticTypeChecked,
32
-
33
- // Other configs...
34
- ],
35
- languageOptions: {
36
- parserOptions: {
37
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
- tsconfigRootDir: import.meta.dirname,
39
- },
40
- // other options...
41
- },
42
- },
43
- ])
44
- ```
45
-
46
- You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
-
48
- ```js
49
- // eslint.config.js
50
- import reactX from 'eslint-plugin-react-x'
51
- import reactDom from 'eslint-plugin-react-dom'
52
-
53
- export default defineConfig([
54
- globalIgnores(['dist']),
55
- {
56
- files: ['**/*.{ts,tsx}'],
57
- extends: [
58
- // Other configs...
59
- // Enable lint rules for React
60
- reactX.configs['recommended-typescript'],
61
- // Enable lint rules for React DOM
62
- reactDom.configs.recommended,
63
- ],
64
- languageOptions: {
65
- parserOptions: {
66
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
- tsconfigRootDir: import.meta.dirname,
68
- },
69
- // other options...
70
- },
71
- },
72
- ])
73
- ```