farming-code 2.2.30 → 2.2.32
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/THIRD_PARTY_NOTICES.md +7 -0
- package/backend/acp/{client-services.js → client-services.cjs} +132 -134
- package/backend/acp/packaged-claude-acp.cjs +37 -0
- package/backend/acp/packaged-codex-acp.cjs +37 -0
- package/backend/acp/patch-decisions.cjs +182 -0
- package/backend/acp/permission-security.cjs +131 -0
- package/backend/{acp-checkpoint-store.js → acp-checkpoint-store.cjs} +90 -59
- package/backend/{acp-runtime.js → acp-runtime.cjs} +1220 -1112
- package/backend/acp-session-state.cjs +622 -0
- package/backend/acp-transcript.cjs +525 -0
- package/backend/agent-env.cjs +257 -0
- package/backend/agent-extension-discovery.cjs +452 -0
- package/backend/agent-extension-inventory.cjs +116 -0
- package/backend/agent-json-stream.cjs +283 -0
- package/backend/agent-lifecycle-journal.cjs +185 -0
- package/backend/{agent-manager.js → agent-manager.cjs} +3116 -4275
- package/backend/agent-order-transaction.cjs +85 -0
- package/backend/agent-order.cjs +159 -0
- package/backend/agent-provider-session.cjs +98 -0
- package/backend/agent-runtime-binding.cjs +179 -0
- package/backend/agent-session-history.cjs +1022 -0
- package/backend/agent-session-inventory.cjs +291 -0
- package/backend/async-cache.cjs +104 -0
- package/backend/atomic-json-store.cjs +67 -0
- package/backend/auth.cjs +261 -0
- package/backend/authoritative-inventory-cache.cjs +383 -0
- package/backend/business-health.cjs +68 -0
- package/backend/chat-runtime.cjs +50 -0
- package/backend/claude-settings.cjs +132 -0
- package/backend/cli-agents.cjs +435 -0
- package/backend/codex-context-window.cjs +196 -0
- package/backend/codex-models.cjs +228 -0
- package/backend/codex-session-archive.cjs +82 -0
- package/backend/codex-session-history.cjs +590 -0
- package/backend/{codex-terminal-profile.js → codex-terminal-profile.cjs} +149 -155
- package/backend/codex-transcript-sanitizer.cjs +130 -0
- package/backend/codex-transcript.cjs +2107 -0
- package/backend/command-runner-child.cjs +105 -0
- package/backend/config-manager.cjs +1263 -0
- package/backend/control-api.cjs +439 -0
- package/backend/data/LICENSE.cua +21 -0
- package/backend/executable-discovery.cjs +204 -0
- package/backend/farming-agent-bootstrap.cjs +81 -0
- package/backend/farming-agent-bootstrap.zh_cn.md +6 -2
- package/backend/{farming-app-cli.js → farming-app-cli.cjs} +441 -493
- package/backend/farming-cli.cjs +414 -0
- package/backend/farming-net-pass.cjs +319 -0
- package/backend/farming-net-registry.cjs +123 -0
- package/backend/farming-net-server.cjs +309 -0
- package/backend/farming-session-store.cjs +651 -0
- package/backend/git-worktree-info.cjs +181 -0
- package/backend/haiku-token.cjs +828 -0
- package/backend/index-html.cjs +96 -0
- package/backend/input-parts.cjs +68 -0
- package/backend/input-routing.cjs +40 -0
- package/backend/{local-session-engine.js → local-session-engine.cjs} +276 -282
- package/backend/main-agent-skills.cjs +309 -0
- package/backend/main-page-session.cjs +132 -0
- package/backend/native-pty-controller-generation.cjs +139 -0
- package/backend/{native-pty-host-client.js → native-pty-host-client.cjs} +338 -346
- package/backend/native-pty-host-identity.cjs +125 -0
- package/backend/native-pty-host-path.cjs +68 -0
- package/backend/{native-pty-host.js → native-pty-host.cjs} +480 -569
- package/backend/native-session-engine.cjs +296 -0
- package/backend/network.cjs +57 -0
- package/backend/npm-update-helper.cjs +399 -0
- package/backend/packaged-node-pty.cjs +120 -0
- package/backend/preview-session-manager.cjs +89 -0
- package/backend/provider-adapters.cjs +492 -0
- package/backend/provider-home-configuration.cjs +211 -0
- package/backend/provider-session-id.cjs +79 -0
- package/backend/provider-session-service.cjs +333 -0
- package/backend/qr-share-tickets.cjs +119 -0
- package/backend/resource-broadcast-protocol.cjs +50 -0
- package/backend/review-diff-router.cjs +202 -0
- package/backend/review-diff-service.cjs +1267 -0
- package/backend/review-session-router.cjs +93 -0
- package/backend/review-session-service.cjs +470 -0
- package/backend/review-session-store.cjs +161 -0
- package/backend/review-state-router.cjs +132 -0
- package/backend/review-state-store.cjs +299 -0
- package/backend/run-history-store.cjs +97 -0
- package/backend/runtime-dependency-manager.cjs +893 -0
- package/backend/runtime-executable-invocation.cjs +37 -0
- package/backend/runtime-observation.cjs +96 -0
- package/backend/server-process-identity.cjs +70 -0
- package/backend/server.cjs +3356 -0
- package/backend/session-engine-bridge.cjs +144 -0
- package/backend/session-engine-router.cjs +105 -0
- package/backend/session-engine.cjs +64 -0
- package/backend/session-stream-protocol.cjs +181 -0
- package/backend/shell-busy-integration.cjs +442 -0
- package/backend/slash-command-discovery.cjs +423 -0
- package/backend/storage-layout.cjs +263 -0
- package/backend/system-monitor.cjs +96 -0
- package/backend/terminal-attach-checkpoint.cjs +73 -0
- package/backend/terminal-exit-quiescence.cjs +57 -0
- package/backend/{terminal-reducer-flow-control.js → terminal-reducer-flow-control.cjs} +45 -22
- package/backend/terminal-runtime-cleanup.cjs +99 -0
- package/backend/{terminal-screen-state.js → terminal-screen-state.cjs} +100 -108
- package/backend/{terminal-screen-worker-pool.js → terminal-screen-worker-pool.cjs} +89 -79
- package/backend/{terminal-screen-worker-thread.js → terminal-screen-worker-thread.cjs} +64 -65
- package/backend/terminal-screen-worker.cjs +352 -0
- package/backend/terminal-state-serialization.cjs +147 -0
- package/backend/{terminal-status.js → terminal-status.cjs} +137 -187
- package/backend/theme-manager.cjs +185 -0
- package/backend/{update-service.js → update-service.cjs} +258 -248
- package/backend/usage-forecast.cjs +95 -0
- package/backend/{usage-history-client.js → usage-history-client.cjs} +144 -94
- package/backend/usage-history-smoke.cjs +85 -0
- package/backend/usage-history-worker.cjs +60 -0
- package/backend/{usage-monitor.js → usage-monitor.cjs} +363 -390
- package/backend/workspace-directory.cjs +239 -0
- package/backend/workspace-discovery.cjs +271 -0
- package/backend/{workspace-file-router.js → workspace-file-router.cjs} +213 -282
- package/backend/{workspace-file-service.js → workspace-file-service.cjs} +1139 -1318
- package/backend/workspace-root-registry.cjs +192 -0
- package/bin/farming +1 -1
- package/dist/acp/codex-acp-1.1.4.mjs +18 -1
- package/dist/assets/App-BCkdpWB6.css +1 -0
- package/dist/assets/App-CRjKpaGp.js +697 -0
- package/dist/assets/CodeSelect-Ci8sKZPU.js +1 -0
- package/dist/assets/CodeSelect-T2eNzrOc.css +1 -0
- package/dist/assets/{FileEditorMarkdownPreview-Cs9cLv8a.js → FileEditorMarkdownPreview-V06QHlAg.js} +55 -55
- package/dist/assets/FileEditorPane-BX-Wjg9U.js +2 -0
- package/dist/assets/IconGlyphs-YhV7tqd4.js +1 -0
- package/dist/assets/ProjectFilesSection-BDT2_r0o.js +12 -0
- package/dist/assets/ReviewPage-BqAs5sG1.js +3 -0
- package/dist/assets/code-dark-B7eM_9G9.css +1 -0
- package/dist/assets/{cssMode-Bdg5RpcJ.js → cssMode-ADdAlxTO.js} +1 -1
- package/dist/assets/{editor.api2-D74ufkbr.js → editor.api2-BFLAr0YF.js} +162 -162
- package/dist/assets/file-icons-BpeqWkIB.js +1 -0
- package/dist/assets/{freemarker2-DfMDJfnE.js → freemarker2-C90q5jrp.js} +1 -1
- package/dist/assets/{handlebars-BEdPtzMT.js → handlebars-BwUQcEDq.js} +1 -1
- package/dist/assets/{html-B1fPb1QD.js → html-1s3uPKfh.js} +1 -1
- package/dist/assets/{htmlMode-CY2ZjHxH.js → htmlMode-xtKD99de.js} +1 -1
- package/dist/assets/{index-D-zetSol.js → index-C8MchCem.js} +3 -3
- package/dist/assets/{javascript-BV2OsWA0.js → javascript-Ph7ijyny.js} +1 -1
- package/dist/assets/{jsonMode-zd07aeuX.js → jsonMode-D-jGAnFH.js} +1 -1
- package/dist/assets/linkComputer-CbGyI_qx.js +1 -0
- package/dist/assets/{liquid-BParI24X.js → liquid-0IamE_cI.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-BzredkoV.js → lspLanguageFeatures-BxnQunWF.js} +1 -1
- package/dist/assets/main-CLKXa6hf.css +1 -0
- package/dist/assets/{mdx-vGzUJN98.js → mdx-DdNmfivn.js} +1 -1
- package/dist/assets/{monaco.contribution-BmaeBQEc.js → monaco.contribution-B43jsUs1.js} +2 -2
- package/dist/assets/{python-CUwdLgsI.js → python-IAt4X5TS.js} +1 -1
- package/dist/assets/{razor-BScebUxU.js → razor-DRkFYW0S.js} +1 -1
- package/dist/assets/review-C8-oPKXk.css +1 -0
- package/dist/assets/{tsMode-DzUAibXK.js → tsMode-_d_4U2gf.js} +1 -1
- package/dist/assets/{typescript-D9EOeM7N.js → typescript-C7zcMq9l.js} +1 -1
- package/dist/assets/{workers-DAiomYZM.js → workers-D0nOyJzf.js} +1 -1
- package/dist/assets/workspace-editor-model-DND_Y-Bj.js +1 -0
- package/dist/assets/workspace-editor-monaco-BPWhgcIB.js +4 -0
- package/dist/assets/workspace-editor-monaco-N641qPjX.js +1 -0
- package/dist/assets/workspace-view-state-k1bTlJ_Z.js +13 -0
- package/dist/assets/{xml-wWl1dhkQ.js → xml-BR-HvxT8.js} +1 -1
- package/dist/assets/{yaml-Dc2WDaOZ.js → yaml-YtFQwh4q.js} +1 -1
- package/dist/index.html +1 -1
- package/extensions/browser/backend/agent-browser-runtime.cjs +1040 -0
- package/extensions/browser/backend/agent-capability.cjs +85 -0
- package/extensions/browser/backend/browser-mcp-server.cjs +655 -0
- package/extensions/browser/backend/browser-resource-manager.cjs +1486 -0
- package/extensions/browser/backend/browser-resource-store.cjs +228 -0
- package/extensions/browser/backend/browser-router.cjs +203 -0
- package/extensions/browser/backend/executable-discovery.cjs +248 -0
- package/extensions/browser/backend/farming-browser-client.cjs +116 -0
- package/extensions/browser/backend/index.cjs +32 -0
- package/extensions/browser/backend/managed-chromium-installer.cjs +833 -0
- package/extensions/browser/bin/farming-browser +16 -7
- package/extensions/computer/backend/agent-capability.cjs +72 -0
- package/extensions/computer/backend/computer-constants.cjs +59 -0
- package/extensions/computer/backend/computer-mcp-server.cjs +182 -0
- package/extensions/computer/backend/computer-resource-manager.cjs +1219 -0
- package/extensions/computer/backend/computer-resource-store.cjs +190 -0
- package/extensions/computer/backend/computer-router.cjs +257 -0
- package/extensions/computer/backend/cua-tools.json +3067 -0
- package/extensions/computer/backend/farming-computer-client.cjs +84 -0
- package/extensions/computer/backend/index.cjs +35 -0
- package/extensions/computer/backend/isolated-browser-provider.cjs +157 -0
- package/extensions/computer/bin/farming-computer +131 -0
- package/frontend/farming-net/app.js +255 -262
- package/frontend/ghostty-loader.js +24 -20
- package/frontend/reading-anchor.js +210 -193
- package/frontend/runtime-paths.js +24 -26
- package/frontend/session-bridge.js +90 -111
- package/frontend/session-modal-bridge.js +184 -302
- package/frontend/skin-bridge.js +20 -23
- package/frontend/skins/crt/app.js +7686 -7901
- package/frontend/skins/crt/effects.js +7 -6
- package/frontend/skins/crt/index.html +6 -6
- package/frontend/skins/crt/styles/markdown.css +4 -4
- package/frontend/terminal-bridge.js +174 -181
- package/frontend/terminal-replay.js +320 -345
- package/frontend/theme-loader.js +55 -71
- package/package.json +64 -37
- package/shared/backend-connection-status.js +38 -69
- package/shared/browser-protocol.js +235 -110
- package/shared/websocket-liveness.js +40 -0
- package/backend/acp/packaged-claude-acp.js +0 -13
- package/backend/acp/packaged-codex-acp.js +0 -13
- package/backend/acp/patch-decisions.js +0 -153
- package/backend/acp/permission-security.js +0 -108
- package/backend/acp-session-state.js +0 -634
- package/backend/acp-transcript.js +0 -512
- package/backend/agent-env.js +0 -250
- package/backend/agent-json-stream.js +0 -268
- package/backend/agent-lifecycle-journal.js +0 -133
- package/backend/agent-order.js +0 -166
- package/backend/agent-provider-session.js +0 -76
- package/backend/agent-runtime-binding.js +0 -174
- package/backend/agent-session-history.js +0 -986
- package/backend/async-cache.js +0 -94
- package/backend/atomic-json-store.js +0 -37
- package/backend/auth.js +0 -251
- package/backend/chat-runtime.js +0 -28
- package/backend/claude-settings.js +0 -121
- package/backend/cli-agents.js +0 -486
- package/backend/codex-context-window.js +0 -189
- package/backend/codex-models.js +0 -226
- package/backend/codex-session-archive.js +0 -65
- package/backend/codex-session-history.js +0 -647
- package/backend/codex-transcript-sanitizer.js +0 -115
- package/backend/codex-transcript.js +0 -2362
- package/backend/command-runner-child.js +0 -67
- package/backend/config-manager.js +0 -1117
- package/backend/control-api.js +0 -455
- package/backend/executable-discovery.js +0 -216
- package/backend/farming-agent-bootstrap.js +0 -49
- package/backend/farming-cli.js +0 -403
- package/backend/farming-net-pass.js +0 -285
- package/backend/farming-net-registry.js +0 -112
- package/backend/farming-net-server.js +0 -298
- package/backend/farming-session-store.js +0 -677
- package/backend/git-worktree-info.js +0 -181
- package/backend/haiku-token.js +0 -772
- package/backend/index-html.js +0 -80
- package/backend/input-parts.js +0 -54
- package/backend/input-routing.js +0 -24
- package/backend/json-cli-runtime.js +0 -275
- package/backend/main-agent-skills.js +0 -288
- package/backend/main-page-session.js +0 -122
- package/backend/native-pty-controller-generation.js +0 -106
- package/backend/native-pty-host-identity.js +0 -86
- package/backend/native-pty-host-path.js +0 -42
- package/backend/native-session-engine.js +0 -268
- package/backend/network.js +0 -23
- package/backend/npm-update-helper.js +0 -374
- package/backend/packaged-node-pty.js +0 -99
- package/backend/preview-session-manager.js +0 -68
- package/backend/provider-adapters.js +0 -399
- package/backend/provider-session-id.js +0 -47
- package/backend/provider-session-service.js +0 -345
- package/backend/qr-share-tickets.js +0 -100
- package/backend/review-diff-router.js +0 -180
- package/backend/review-diff-service.js +0 -1270
- package/backend/review-session-router.js +0 -74
- package/backend/review-session-service.js +0 -446
- package/backend/review-session-store.js +0 -151
- package/backend/review-state-router.js +0 -116
- package/backend/review-state-store.js +0 -286
- package/backend/run-history-store.js +0 -67
- package/backend/runtime-dependency-manager.js +0 -759
- package/backend/runtime-executable-invocation.js +0 -20
- package/backend/runtime-observation.js +0 -81
- package/backend/server-process-identity.js +0 -47
- package/backend/server.js +0 -3225
- package/backend/session-engine-bridge.js +0 -129
- package/backend/session-engine-router.js +0 -66
- package/backend/session-engine.js +0 -39
- package/backend/session-stream-protocol.js +0 -185
- package/backend/shell-busy-integration.js +0 -472
- package/backend/slash-command-discovery.js +0 -433
- package/backend/storage-layout.js +0 -205
- package/backend/system-monitor.js +0 -77
- package/backend/terminal-attach-checkpoint.js +0 -74
- package/backend/terminal-exit-quiescence.js +0 -39
- package/backend/terminal-runtime-cleanup.js +0 -80
- package/backend/terminal-screen-worker.js +0 -337
- package/backend/terminal-state-serialization.js +0 -127
- package/backend/theme-manager.js +0 -163
- package/backend/usage-forecast.js +0 -86
- package/backend/usage-history-scanner.ts +0 -2718
- package/backend/usage-history-smoke.js +0 -64
- package/backend/usage-history-worker.js +0 -34
- package/backend/workspace-directory.js +0 -232
- package/backend/workspace-discovery.js +0 -311
- package/backend/workspace-root-registry.js +0 -166
- package/dist/assets/App-BKNUILuL.css +0 -1
- package/dist/assets/App-Z1N7T0eM.js +0 -695
- package/dist/assets/FileEditorPane-CNtuGjQ3.js +0 -2
- package/dist/assets/IconGlyphs-BClgag6E.js +0 -1
- package/dist/assets/ProjectFilesSection-K3GHuQ4U.js +0 -12
- package/dist/assets/ReviewPage-BRuxFaH5.js +0 -3
- package/dist/assets/code-dark-kLsQLvpf.css +0 -1
- package/dist/assets/file-icons-BOlcJ0ZF.js +0 -1
- package/dist/assets/main-DUTz-Rd2.css +0 -1
- package/dist/assets/review-BcnwQtJv.css +0 -1
- package/dist/assets/workspace-editor-model-CSGCl21x.js +0 -1
- package/dist/assets/workspace-editor-monaco-CJNwbpCy.js +0 -4
- package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +0 -1
- package/dist/assets/workspace-view-state-BjKPYp0E.js +0 -7
- package/extensions/browser/backend/agent-browser-runtime.js +0 -1041
- package/extensions/browser/backend/agent-capability.js +0 -55
- package/extensions/browser/backend/browser-mcp-server.js +0 -621
- package/extensions/browser/backend/browser-resource-manager.js +0 -1331
- package/extensions/browser/backend/browser-resource-store.js +0 -190
- package/extensions/browser/backend/browser-router.js +0 -141
- package/extensions/browser/backend/executable-discovery.js +0 -238
- package/extensions/browser/backend/farming-browser-client.js +0 -83
- package/extensions/browser/backend/index.js +0 -7
- package/extensions/browser/backend/managed-chromium-installer.js +0 -593
- package/extensions/browser/frontend/BrowserSidebarPortals.tsx +0 -360
- package/extensions/browser/frontend/BrowserViewer.tsx +0 -500
- package/extensions/browser/frontend/browser-resource-state.ts +0 -60
- package/extensions/browser/frontend/browser.css +0 -567
- package/extensions/browser/frontend/types.ts +0 -38
- package/extensions/browser/frontend/useBrowserResources.ts +0 -166
- package/frontend/vendor/ghostty-web/index.d.ts +0 -1842
- package/shared/backend-connection-status.d.ts +0 -37
- package/shared/browser-protocol.d.ts +0 -5
- /package/dist/assets/{api-w2x5QfxB.js → api-ByCV9MEr.js} +0 -0
- /package/dist/assets/{core-vPkV8P_m.js → core-Czwdx12k.js} +0 -0
- /package/dist/assets/{fsharp-DNZNZyEE.js → fsharp-BjPpkoJe.js} +0 -0
- /package/dist/assets/{go-_kPJjNc_.js → go-BkIDmSUP.js} +0 -0
- /package/dist/assets/{graphql-4HCNVt5g.js → graphql-CCJTpqi1.js} +0 -0
- /package/dist/assets/{hcl-C87ymY0o.js → hcl-s4z8lUFg.js} +0 -0
- /package/dist/assets/{ini-BYrrGNTc.js → ini-CyUW1I7Z.js} +0 -0
- /package/dist/assets/{java-B211rJbk.js → java-CFCcGRiM.js} +0 -0
- /package/dist/assets/{julia-DVPsRtBm.js → julia-DQyH_EYb.js} +0 -0
- /package/dist/assets/{kotlin-BYyNerjp.js → kotlin-B8hA5O51.js} +0 -0
- /package/dist/assets/{less-EC9UblGE.js → less-DaVdaas0.js} +0 -0
- /package/dist/assets/{lexon-B1yuUdqW.js → lexon-DLBhPd3y.js} +0 -0
- /package/dist/assets/{lua-Bo6GFzxT.js → lua-gB1c_cif.js} +0 -0
- /package/dist/assets/{m3-C-Y9cBVI.js → m3-C2T3z3gB.js} +0 -0
- /package/dist/assets/{markdown-BHu-wLbe.js → markdown-CKq-Euj1.js} +0 -0
- /package/dist/assets/{mips-Dkds26rX.js → mips-Bcs5qIDX.js} +0 -0
- /package/dist/assets/{msdax-PU4g-8_g.js → msdax-CBP48FHF.js} +0 -0
- /package/dist/assets/{mysql-fPpuGpS7.js → mysql-c7tiPcFj.js} +0 -0
- /package/dist/assets/{objective-c-Wy1e5JUf.js → objective-c-D4BZkeEV.js} +0 -0
- /package/dist/assets/{pascal-BIXwvrqU.js → pascal-CJDZg0MN.js} +0 -0
- /package/dist/assets/{pascaligo-DwR0AtL_.js → pascaligo-Bygi8Ynl.js} +0 -0
- /package/dist/assets/{perl-CGHAl8my.js → perl-aS8bkf7E.js} +0 -0
- /package/dist/assets/{pgsql-B91M73E2.js → pgsql-CzNAYFYl.js} +0 -0
- /package/dist/assets/{php-C70ttrCx.js → php-DOtoEFTT.js} +0 -0
- /package/dist/assets/{pla-BNrXaRh0.js → pla-DugRnao1.js} +0 -0
- /package/dist/assets/{postiats-Dv2IAZR9.js → postiats-DsXwusKh.js} +0 -0
- /package/dist/assets/{powerquery-CkY5Wq7J.js → powerquery-DL3o72oD.js} +0 -0
- /package/dist/assets/{powershell-uGIYLU3C.js → powershell-C1qHekys.js} +0 -0
- /package/dist/assets/{protobuf-CavfmJu-.js → protobuf-DHgsc-cH.js} +0 -0
- /package/dist/assets/{pug-Drqnyitx.js → pug-FZXlE_Iu.js} +0 -0
- /package/dist/assets/{qrcode-7uGsTEmi.js → qrcode-DJDTdjL7.js} +0 -0
- /package/dist/assets/{qsharp-C7yF-Dti.js → qsharp-bLyhI3DT.js} +0 -0
- /package/dist/assets/{r-HXLGP0_-.js → r-DjFGXbAa.js} +0 -0
- /package/dist/assets/{redis-C4y6mf2p.js → redis-DSoZ_V6u.js} +0 -0
- /package/dist/assets/{redshift-DdQrFPrv.js → redshift-CzkdCsrg.js} +0 -0
- /package/dist/assets/{restructuredtext-CBrf2PNj.js → restructuredtext-B_XPrGCQ.js} +0 -0
- /package/dist/assets/{ruby-CVtMoX2B.js → ruby-Cry2RneJ.js} +0 -0
- /package/dist/assets/{rust-Ckq4sbMP.js → rust-CWzdbFq1.js} +0 -0
- /package/dist/assets/{sb-er66OpE3.js → sb-DmofU59h.js} +0 -0
- /package/dist/assets/{scala-BdWZz-hH.js → scala-BUC2l-vN.js} +0 -0
- /package/dist/assets/{scheme-kTV_s2kP.js → scheme-CNIB_72f.js} +0 -0
- /package/dist/assets/{scss-Bymy2VJQ.js → scss-DcL4-NbX.js} +0 -0
- /package/dist/assets/{shell-bwEP1LQ1.js → shell-CgAGvSSA.js} +0 -0
- /package/dist/assets/{solidity-DCddeBgL.js → solidity-DSkt6O_P.js} +0 -0
- /package/dist/assets/{sophia-BMN3AQig.js → sophia--5ytcjDN.js} +0 -0
- /package/dist/assets/{sparql-CSXOLjzi.js → sparql-C1Srr7cD.js} +0 -0
- /package/dist/assets/{sql-COg8ewmK.js → sql-2k_O5fj7.js} +0 -0
- /package/dist/assets/{st-CIaZtBS_.js → st-DCCCPqfz.js} +0 -0
- /package/dist/assets/{swift-DXiOhUHu.js → swift-Dd8mAfOt.js} +0 -0
- /package/dist/assets/{systemverilog-BTDE6Dr2.js → systemverilog-B0-aZYXu.js} +0 -0
- /package/dist/assets/{tcl-B0zy9NvV.js → tcl-CZAZwPVX.js} +0 -0
- /package/dist/assets/{twig-D594l4Z1.js → twig-D-Ag0tdS.js} +0 -0
- /package/dist/assets/{typespec-XKVjaPqo.js → typespec-B7kTFp0Z.js} +0 -0
- /package/dist/assets/{useWorkspaceMenuKeyboard-Bpy_s69Z.js → useWorkspaceMenuKeyboard-uYZpDxhU.js} +0 -0
- /package/dist/assets/{vb-B2wYoKRV.js → vb-20w1JPum.js} +0 -0
- /package/dist/assets/{wgsl-D0Yf2LbK.js → wgsl-CLJfqFt0.js} +0 -0
- /package/dist/assets/{workspace-working-copy-C3FSR3N6.js → workspace-working-copy-Cfz07cOd.js} +0 -0
|
@@ -1,52 +1,96 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// Generated by scripts/build-backend-runtime.ts. Do not edit.
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var usage_monitor_exports = {};
|
|
21
|
+
__export(usage_monitor_exports, {
|
|
22
|
+
USAGE_DAILY_CACHE_MS: () => USAGE_DAILY_CACHE_MS,
|
|
23
|
+
USAGE_DAILY_DAYS: () => USAGE_DAILY_DAYS,
|
|
24
|
+
USAGE_LIVE_DAY_CACHE_MS: () => USAGE_LIVE_DAY_CACHE_MS,
|
|
25
|
+
USAGE_LIVE_TIMELINE_BUCKET_COUNT: () => USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
26
|
+
USAGE_LIVE_TIMELINE_WINDOW_MS: () => USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
27
|
+
USAGE_TIMELINE_BUCKET_COUNT: () => USAGE_TIMELINE_BUCKET_COUNT,
|
|
28
|
+
USAGE_TIMELINE_WINDOW_MS: () => USAGE_TIMELINE_WINDOW_MS,
|
|
29
|
+
USAGE_WINDOW_MS: () => USAGE_WINDOW_MS,
|
|
30
|
+
UsageMonitor: () => UsageMonitor,
|
|
31
|
+
buildDailyUsage: () => buildDailyUsage,
|
|
32
|
+
buildUsageDayDetail: () => buildUsageDayDetail,
|
|
33
|
+
buildUsageTimeline: () => buildUsageTimeline,
|
|
34
|
+
collectClaudeUsage: () => collectClaudeUsage,
|
|
35
|
+
collectCodexUsage: () => collectCodexUsage,
|
|
36
|
+
collectDailyUsage: () => collectDailyUsage,
|
|
37
|
+
collectOpenCodeDailyEvents: () => collectOpenCodeDailyEvents,
|
|
38
|
+
openCodeTokenEventsFromExport: () => openCodeTokenEventsFromExport,
|
|
39
|
+
readClaudeAuthStatus: () => readClaudeAuthStatus,
|
|
40
|
+
readCodexAuthStatus: () => readCodexAuthStatus
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(usage_monitor_exports);
|
|
43
|
+
var import_usage_history_client = require("./usage-history-client.cjs");
|
|
44
|
+
var import_usage_forecast = require("./usage-forecast.cjs");
|
|
45
|
+
const os = require("os");
|
|
46
|
+
const path = require("path");
|
|
47
|
+
const { execFile } = require("child_process");
|
|
48
|
+
const { promisify } = require("util");
|
|
49
|
+
function asRecord(value) {
|
|
50
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
51
|
+
}
|
|
8
52
|
const execFileAsync = promisify(execFile);
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const USAGE_TIMELINE_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
53
|
+
const USAGE_WINDOW_MS = 5 * 60 * 1e3;
|
|
54
|
+
const USAGE_TIMELINE_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
12
55
|
const USAGE_TIMELINE_BUCKET_COUNT = 24;
|
|
13
|
-
const USAGE_LIVE_TIMELINE_WINDOW_MS = 60 * 60 *
|
|
56
|
+
const USAGE_LIVE_TIMELINE_WINDOW_MS = 60 * 60 * 1e3;
|
|
14
57
|
const USAGE_LIVE_TIMELINE_BUCKET_COUNT = 60;
|
|
15
58
|
const USAGE_DAILY_DAYS = 52 * 7;
|
|
16
|
-
const USAGE_DAILY_CACHE_MS = 5 * 60 *
|
|
17
|
-
const USAGE_LIVE_DAY_CACHE_MS = 5 *
|
|
59
|
+
const USAGE_DAILY_CACHE_MS = 5 * 60 * 1e3;
|
|
60
|
+
const USAGE_LIVE_DAY_CACHE_MS = 5 * 1e3;
|
|
18
61
|
const COMMAND_TIMEOUT_MS = 2500;
|
|
19
|
-
const OPENCODE_COMMAND_TIMEOUT_MS =
|
|
62
|
+
const OPENCODE_COMMAND_TIMEOUT_MS = 2e4;
|
|
20
63
|
const OPENCODE_EXPORT_CONCURRENCY = 4;
|
|
21
|
-
const OPENCODE_SESSION_LIMIT =
|
|
22
|
-
const OPENCODE_SESSION_CACHE_LIMIT =
|
|
23
|
-
const openCodeSessionEventCache = new Map();
|
|
24
|
-
|
|
64
|
+
const OPENCODE_SESSION_LIMIT = 5e3;
|
|
65
|
+
const OPENCODE_SESSION_CACHE_LIMIT = 5e3;
|
|
66
|
+
const openCodeSessionEventCache = /* @__PURE__ */ new Map();
|
|
25
67
|
function numberOrNull(value) {
|
|
26
68
|
const numberValue = Number(value);
|
|
27
69
|
return Number.isFinite(numberValue) ? numberValue : null;
|
|
28
70
|
}
|
|
29
|
-
|
|
30
71
|
function roundRate(value) {
|
|
31
72
|
if (!Number.isFinite(value)) return 0;
|
|
32
73
|
return Math.round(value * 10) / 10;
|
|
33
74
|
}
|
|
34
|
-
|
|
35
75
|
function normalizeEpochMs(value) {
|
|
36
76
|
const numberValue = numberOrNull(value);
|
|
37
77
|
if (numberValue === null || numberValue <= 0) return null;
|
|
38
|
-
return numberValue <
|
|
78
|
+
return numberValue < 1e10 ? numberValue * 1e3 : numberValue;
|
|
39
79
|
}
|
|
40
|
-
|
|
41
80
|
function parseTimestampMs(value) {
|
|
42
81
|
if (!value) return null;
|
|
43
|
-
if (typeof value ===
|
|
82
|
+
if (typeof value === "number") return normalizeEpochMs(value);
|
|
44
83
|
const parsed = Date.parse(value);
|
|
45
84
|
return Number.isFinite(parsed) ? parsed : null;
|
|
46
85
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
86
|
+
function tokenUsageSummary({
|
|
87
|
+
totalTokens,
|
|
88
|
+
eventCount,
|
|
89
|
+
source,
|
|
90
|
+
windowMs,
|
|
91
|
+
sampledAt
|
|
92
|
+
}) {
|
|
93
|
+
const windowMinutes = Math.max(1, windowMs / 6e4);
|
|
50
94
|
return {
|
|
51
95
|
available: true,
|
|
52
96
|
windowMs,
|
|
@@ -54,10 +98,9 @@ function tokenUsageSummary({ totalTokens, eventCount, source, windowMs, sampledA
|
|
|
54
98
|
totalTokens,
|
|
55
99
|
tokensPerMinute: roundRate(totalTokens / windowMinutes),
|
|
56
100
|
eventCount,
|
|
57
|
-
sampledAt
|
|
101
|
+
sampledAt
|
|
58
102
|
};
|
|
59
103
|
}
|
|
60
|
-
|
|
61
104
|
function emptyTokenBreakdown() {
|
|
62
105
|
return {
|
|
63
106
|
totalTokens: 0,
|
|
@@ -65,19 +108,19 @@ function emptyTokenBreakdown() {
|
|
|
65
108
|
outputTokens: 0,
|
|
66
109
|
cacheReadTokens: 0,
|
|
67
110
|
cacheWriteTokens: 0,
|
|
68
|
-
unattributedTokens: 0
|
|
111
|
+
unattributedTokens: 0
|
|
69
112
|
};
|
|
70
113
|
}
|
|
71
|
-
|
|
72
114
|
function tokenBreakdownFromOpenCode(tokens) {
|
|
73
|
-
if (!tokens || typeof tokens !==
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
const
|
|
115
|
+
if (!tokens || typeof tokens !== "object") return emptyTokenBreakdown();
|
|
116
|
+
const source = tokens;
|
|
117
|
+
const cache = asRecord(source.cache);
|
|
118
|
+
const inputTokens = Math.max(0, numberOrNull(source.input) ?? 0);
|
|
119
|
+
const outputTokens = Math.max(0, numberOrNull(source.output) ?? 0) + Math.max(0, numberOrNull(source.reasoning) ?? 0);
|
|
120
|
+
const cacheReadTokens = Math.max(0, numberOrNull(cache?.read) ?? 0);
|
|
121
|
+
const cacheWriteTokens = Math.max(0, numberOrNull(cache?.write) ?? 0);
|
|
79
122
|
const componentTotal = inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens;
|
|
80
|
-
const explicitTotal = numberOrNull(
|
|
123
|
+
const explicitTotal = numberOrNull(source.total);
|
|
81
124
|
const totalTokens = Math.max(0, explicitTotal ?? componentTotal);
|
|
82
125
|
return {
|
|
83
126
|
totalTokens,
|
|
@@ -85,63 +128,56 @@ function tokenBreakdownFromOpenCode(tokens) {
|
|
|
85
128
|
outputTokens,
|
|
86
129
|
cacheReadTokens,
|
|
87
130
|
cacheWriteTokens,
|
|
88
|
-
unattributedTokens: Math.max(0, totalTokens - componentTotal)
|
|
131
|
+
unattributedTokens: Math.max(0, totalTokens - componentTotal)
|
|
89
132
|
};
|
|
90
133
|
}
|
|
91
|
-
|
|
92
134
|
function providerHomePaths(providerHomes, provider, fallbackPath) {
|
|
93
|
-
const configured = providerHomes && Array.isArray(providerHomes[provider])
|
|
94
|
-
? providerHomes[provider]
|
|
95
|
-
: [];
|
|
135
|
+
const configured = providerHomes && Array.isArray(providerHomes[provider]) ? providerHomes[provider] : [];
|
|
96
136
|
const candidates = configured.length > 0 ? configured : [fallbackPath];
|
|
97
137
|
return Array.from(new Set(candidates.map((home) => {
|
|
98
|
-
if (typeof home ===
|
|
99
|
-
return home && typeof home.path ===
|
|
138
|
+
if (typeof home === "string") return home;
|
|
139
|
+
return home && typeof home.path === "string" ? home.path : "";
|
|
100
140
|
}).filter(Boolean)));
|
|
101
141
|
}
|
|
102
|
-
|
|
103
142
|
function ccStatisticsRoots(options = {}) {
|
|
104
143
|
const codexHomes = providerHomePaths(
|
|
105
144
|
options.providerHomes,
|
|
106
|
-
|
|
107
|
-
options.codexHome || path.join(os.homedir(),
|
|
145
|
+
"codex",
|
|
146
|
+
options.codexHome || path.join(os.homedir(), ".codex")
|
|
108
147
|
);
|
|
109
148
|
const claudeHomes = providerHomePaths(
|
|
110
149
|
options.providerHomes,
|
|
111
|
-
|
|
112
|
-
options.claudeHome || path.join(os.homedir(),
|
|
150
|
+
"claude",
|
|
151
|
+
options.claudeHome || path.join(os.homedir(), ".claude")
|
|
113
152
|
);
|
|
114
153
|
return {
|
|
115
154
|
codexHomes,
|
|
116
155
|
claudeHomes,
|
|
117
|
-
codexRoots: codexHomes.flatMap(home => [
|
|
118
|
-
path.join(home,
|
|
119
|
-
path.join(home,
|
|
156
|
+
codexRoots: codexHomes.flatMap((home) => [
|
|
157
|
+
path.join(home, "sessions"),
|
|
158
|
+
path.join(home, "archived_sessions")
|
|
120
159
|
]),
|
|
121
|
-
claudeRoots: claudeHomes.map(home => path.join(home,
|
|
160
|
+
claudeRoots: claudeHomes.map((home) => path.join(home, "projects"))
|
|
122
161
|
};
|
|
123
162
|
}
|
|
124
|
-
|
|
125
163
|
function ccStatisticsClient(options = {}) {
|
|
126
|
-
return options.usageHistoryClient || options.ccStatisticsClient || new UsageHistoryClient({
|
|
127
|
-
configDir: options.configDir || path.join(os.homedir(),
|
|
164
|
+
return options.usageHistoryClient || options.ccStatisticsClient || new import_usage_history_client.UsageHistoryClient({
|
|
165
|
+
configDir: options.configDir || path.join(os.homedir(), ".farming")
|
|
128
166
|
});
|
|
129
167
|
}
|
|
130
|
-
|
|
131
168
|
function unavailableCCStatisticsResult(error, now) {
|
|
132
169
|
const reason = commandUnavailable(error);
|
|
133
170
|
return {
|
|
134
171
|
schemaVersion: 1,
|
|
135
|
-
source:
|
|
172
|
+
source: "local usage history unavailable",
|
|
136
173
|
sampledAt: now,
|
|
137
174
|
providers: {
|
|
138
175
|
codex: { events: [], quotaCandidates: [], available: false, reason, fileCount: 0 },
|
|
139
|
-
claude: { events: [], quotaCandidates: [], available: false, reason, fileCount: 0 }
|
|
176
|
+
claude: { events: [], quotaCandidates: [], available: false, reason, fileCount: 0 }
|
|
140
177
|
},
|
|
141
|
-
cache: { errors: 1 }
|
|
178
|
+
cache: { errors: 1 }
|
|
142
179
|
};
|
|
143
180
|
}
|
|
144
|
-
|
|
145
181
|
async function collectCCStatistics(options = {}) {
|
|
146
182
|
const now = options.now ?? Date.now();
|
|
147
183
|
const roots = ccStatisticsRoots(options);
|
|
@@ -151,57 +187,50 @@ async function collectCCStatistics(options = {}) {
|
|
|
151
187
|
retentionDays: options.retentionDays ?? USAGE_DAILY_DAYS,
|
|
152
188
|
codexRoots: roots.codexRoots,
|
|
153
189
|
claudeRoots: roots.claudeRoots,
|
|
154
|
-
fresh: options.fresh
|
|
190
|
+
fresh: options.fresh
|
|
155
191
|
});
|
|
156
192
|
return { result, roots };
|
|
157
193
|
} catch (error) {
|
|
158
194
|
return { result: unavailableCCStatisticsResult(error, now), roots };
|
|
159
195
|
}
|
|
160
196
|
}
|
|
161
|
-
|
|
162
197
|
function ccStatisticsProviderEvents(result, provider) {
|
|
163
|
-
return (result?.providers?.[provider]?.events || []).map(event => attributeUsageEvent(
|
|
198
|
+
return (result?.providers?.[provider]?.events || []).map((event) => attributeUsageEvent(
|
|
164
199
|
event,
|
|
165
200
|
provider,
|
|
166
|
-
String(event.sessionId ||
|
|
201
|
+
String(event.sessionId || "unattributed")
|
|
167
202
|
));
|
|
168
203
|
}
|
|
169
|
-
|
|
170
204
|
function addTokenBreakdown(target, source) {
|
|
171
205
|
for (const field of Object.keys(emptyTokenBreakdown())) {
|
|
172
206
|
target[field] += Math.max(0, numberOrNull(source?.[field]) ?? 0);
|
|
173
207
|
}
|
|
174
208
|
return target;
|
|
175
209
|
}
|
|
176
|
-
|
|
177
210
|
function usageAgentLabel(provider, agentId) {
|
|
178
211
|
const providerName = {
|
|
179
|
-
codex:
|
|
180
|
-
claude:
|
|
181
|
-
opencode:
|
|
182
|
-
qoder:
|
|
212
|
+
codex: "Codex",
|
|
213
|
+
claude: "Claude",
|
|
214
|
+
opencode: "OpenCode",
|
|
215
|
+
qoder: "Qoder"
|
|
183
216
|
}[provider] || provider;
|
|
184
|
-
if (!agentId || agentId ===
|
|
185
|
-
const shortId = agentId.length > 12 ?
|
|
186
|
-
return `${providerName}
|
|
217
|
+
if (!agentId || agentId === "unattributed") return providerName;
|
|
218
|
+
const shortId = agentId.length > 12 ? `\u2026${agentId.slice(-6)}` : agentId;
|
|
219
|
+
return `${providerName} \xB7 ${shortId}`;
|
|
187
220
|
}
|
|
188
|
-
|
|
189
221
|
function attributeUsageEvent(event, provider, agentId) {
|
|
190
222
|
return {
|
|
191
223
|
...event,
|
|
192
224
|
agentId,
|
|
193
|
-
agentLabel: usageAgentLabel(provider, agentId)
|
|
225
|
+
agentLabel: usageAgentLabel(provider, agentId)
|
|
194
226
|
};
|
|
195
227
|
}
|
|
196
|
-
|
|
197
228
|
function buildUsageTimeline(providerEvents, options = {}) {
|
|
198
229
|
const now = options.now ?? Date.now();
|
|
199
|
-
const windowMs = Math.max(
|
|
230
|
+
const windowMs = Math.max(6e4, options.windowMs ?? USAGE_TIMELINE_WINDOW_MS);
|
|
200
231
|
const bucketCount = Math.max(1, Math.floor(options.bucketCount ?? USAGE_TIMELINE_BUCKET_COUNT));
|
|
201
232
|
const bucketMs = windowMs / bucketCount;
|
|
202
|
-
const endAt = options.alignToBucket
|
|
203
|
-
? Math.ceil(now / bucketMs) * bucketMs
|
|
204
|
-
: now;
|
|
233
|
+
const endAt = options.alignToBucket ? Math.ceil(now / bucketMs) * bucketMs : now;
|
|
205
234
|
const startAt = endAt - windowMs;
|
|
206
235
|
const providerNames = Object.keys(providerEvents || {});
|
|
207
236
|
const points = Array.from({ length: bucketCount }, (_, index) => ({
|
|
@@ -209,21 +238,19 @@ function buildUsageTimeline(providerEvents, options = {}) {
|
|
|
209
238
|
endedAt: Math.round(startAt + (index + 1) * bucketMs),
|
|
210
239
|
totalTokens: 0,
|
|
211
240
|
tokensPerMinute: 0,
|
|
212
|
-
providers: Object.fromEntries(providerNames.map(provider => [provider, 0]))
|
|
241
|
+
providers: Object.fromEntries(providerNames.map((provider) => [provider, 0]))
|
|
213
242
|
}));
|
|
214
|
-
|
|
215
243
|
for (const provider of providerNames) {
|
|
216
244
|
for (const event of providerEvents[provider] || []) {
|
|
217
245
|
const timestamp = parseTimestampMs(event?.timestamp);
|
|
218
|
-
const
|
|
219
|
-
if (!timestamp ||
|
|
246
|
+
const totalTokens2 = Math.max(0, numberOrNull(event?.totalTokens) ?? 0);
|
|
247
|
+
if (!timestamp || totalTokens2 <= 0 || timestamp < startAt || timestamp > endAt + 6e4) continue;
|
|
220
248
|
const index = Math.min(bucketCount - 1, Math.max(0, Math.floor((timestamp - startAt) / bucketMs)));
|
|
221
|
-
points[index].providers[provider] +=
|
|
222
|
-
points[index].totalTokens +=
|
|
249
|
+
points[index].providers[provider] += totalTokens2;
|
|
250
|
+
points[index].totalTokens += totalTokens2;
|
|
223
251
|
}
|
|
224
252
|
}
|
|
225
|
-
|
|
226
|
-
const bucketMinutes = bucketMs / 60_000;
|
|
253
|
+
const bucketMinutes = bucketMs / 6e4;
|
|
227
254
|
let totalTokens = 0;
|
|
228
255
|
let peakTokensPerMinute = 0;
|
|
229
256
|
let activeBucketCount = 0;
|
|
@@ -233,9 +260,8 @@ function buildUsageTimeline(providerEvents, options = {}) {
|
|
|
233
260
|
peakTokensPerMinute = Math.max(peakTokensPerMinute, point.tokensPerMinute);
|
|
234
261
|
if (point.totalTokens > 0) activeBucketCount += 1;
|
|
235
262
|
}
|
|
236
|
-
|
|
237
263
|
return {
|
|
238
|
-
source:
|
|
264
|
+
source: "local provider token events",
|
|
239
265
|
sampledAt: now,
|
|
240
266
|
startAt,
|
|
241
267
|
endAt,
|
|
@@ -243,13 +269,12 @@ function buildUsageTimeline(providerEvents, options = {}) {
|
|
|
243
269
|
bucketMs,
|
|
244
270
|
bucketCount,
|
|
245
271
|
totalTokens,
|
|
246
|
-
averageTokensPerMinute: roundRate(totalTokens / (windowMs /
|
|
272
|
+
averageTokensPerMinute: roundRate(totalTokens / (windowMs / 6e4)),
|
|
247
273
|
peakTokensPerMinute: roundRate(peakTokensPerMinute),
|
|
248
274
|
activeBucketCount,
|
|
249
|
-
points
|
|
275
|
+
points
|
|
250
276
|
};
|
|
251
277
|
}
|
|
252
|
-
|
|
253
278
|
function providerUsageFromEvents(events, options = {}) {
|
|
254
279
|
const now = options.now ?? Date.now();
|
|
255
280
|
const windowMs = options.windowMs ?? USAGE_WINDOW_MS;
|
|
@@ -260,7 +285,7 @@ function providerUsageFromEvents(events, options = {}) {
|
|
|
260
285
|
for (const event of Array.isArray(events) ? events : []) {
|
|
261
286
|
const timestamp = parseTimestampMs(event?.timestamp);
|
|
262
287
|
const eventTokens = Math.max(0, numberOrNull(event?.totalTokens) ?? 0);
|
|
263
|
-
if (!timestamp || eventTokens <= 0 || timestamp > now +
|
|
288
|
+
if (!timestamp || eventTokens <= 0 || timestamp > now + 6e4) continue;
|
|
264
289
|
if (timestamp >= now - historyWindowMs) tokenEvents.push(event);
|
|
265
290
|
if (timestamp >= now - windowMs) {
|
|
266
291
|
totalTokens += eventTokens;
|
|
@@ -271,92 +296,85 @@ function providerUsageFromEvents(events, options = {}) {
|
|
|
271
296
|
tokenUsage: tokenUsageSummary({
|
|
272
297
|
totalTokens,
|
|
273
298
|
eventCount,
|
|
274
|
-
source: options.source ||
|
|
299
|
+
source: options.source || "local provider token events",
|
|
275
300
|
windowMs,
|
|
276
|
-
sampledAt: now
|
|
301
|
+
sampledAt: now
|
|
277
302
|
}),
|
|
278
|
-
tokenEvents
|
|
303
|
+
tokenEvents
|
|
279
304
|
};
|
|
280
305
|
}
|
|
281
|
-
|
|
282
306
|
async function defaultCommandRunner(command, args, options = {}) {
|
|
283
307
|
const result = await execFileAsync(command, args, {
|
|
284
308
|
timeout: options.timeoutMs ?? COMMAND_TIMEOUT_MS,
|
|
285
|
-
windowsHide: true
|
|
309
|
+
windowsHide: true
|
|
286
310
|
});
|
|
287
|
-
|
|
288
311
|
return {
|
|
289
|
-
stdout: String(result.stdout ||
|
|
290
|
-
stderr: String(result.stderr ||
|
|
312
|
+
stdout: String(result.stdout || ""),
|
|
313
|
+
stderr: String(result.stderr || "")
|
|
291
314
|
};
|
|
292
315
|
}
|
|
293
|
-
|
|
294
316
|
function commandUnavailable(error) {
|
|
295
|
-
if (!error) return
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
317
|
+
if (!error) return "Unavailable";
|
|
318
|
+
const details = asRecord(error);
|
|
319
|
+
if (details?.code === "ENOENT") return "Command not found";
|
|
320
|
+
const stderr = String(details?.stderr || "").trim();
|
|
321
|
+
const stdout = String(details?.stdout || "").trim();
|
|
322
|
+
return stderr || stdout || String(details?.message || "") || "Unavailable";
|
|
300
323
|
}
|
|
301
|
-
|
|
302
324
|
async function readCodexAuthStatus(commandRunner = defaultCommandRunner) {
|
|
303
325
|
try {
|
|
304
|
-
const result = await commandRunner(
|
|
305
|
-
const status = `${result.stdout ||
|
|
326
|
+
const result = await commandRunner("codex", ["login", "status"], { timeoutMs: COMMAND_TIMEOUT_MS });
|
|
327
|
+
const status = `${result.stdout || ""}${result.stderr || ""}`.trim().split(/\r?\n/).filter(Boolean).join(" ");
|
|
306
328
|
return {
|
|
307
329
|
available: true,
|
|
308
|
-
status: status ||
|
|
309
|
-
source:
|
|
330
|
+
status: status || "Available",
|
|
331
|
+
source: "codex login status"
|
|
310
332
|
};
|
|
311
333
|
} catch (error) {
|
|
312
334
|
return {
|
|
313
335
|
available: false,
|
|
314
336
|
status: commandUnavailable(error),
|
|
315
|
-
source:
|
|
337
|
+
source: "codex login status"
|
|
316
338
|
};
|
|
317
339
|
}
|
|
318
340
|
}
|
|
319
|
-
|
|
320
341
|
async function readClaudeAuthStatus(commandRunner = defaultCommandRunner) {
|
|
321
342
|
try {
|
|
322
|
-
const result = await commandRunner(
|
|
323
|
-
const parsed = JSON.parse((result.stdout || result.stderr ||
|
|
343
|
+
const result = await commandRunner("claude", ["auth", "status", "--json"], { timeoutMs: COMMAND_TIMEOUT_MS });
|
|
344
|
+
const parsed = JSON.parse((result.stdout || result.stderr || "{}").trim() || "{}");
|
|
324
345
|
const loggedIn = parsed.loggedIn === true;
|
|
325
346
|
const statusParts = [
|
|
326
|
-
loggedIn ?
|
|
347
|
+
loggedIn ? "logged in" : "logged out",
|
|
327
348
|
parsed.authMethod,
|
|
328
|
-
parsed.apiProvider
|
|
349
|
+
parsed.apiProvider
|
|
329
350
|
].filter(Boolean);
|
|
330
|
-
|
|
331
351
|
return {
|
|
332
352
|
available: true,
|
|
333
|
-
status: statusParts.join(
|
|
353
|
+
status: statusParts.join(" / ") || "Available",
|
|
334
354
|
loggedIn,
|
|
335
|
-
authMethod: parsed.authMethod ||
|
|
336
|
-
apiProvider: parsed.apiProvider ||
|
|
337
|
-
source:
|
|
355
|
+
authMethod: parsed.authMethod || "",
|
|
356
|
+
apiProvider: parsed.apiProvider || "",
|
|
357
|
+
source: "claude auth status --json"
|
|
338
358
|
};
|
|
339
359
|
} catch (error) {
|
|
340
360
|
return {
|
|
341
361
|
available: false,
|
|
342
362
|
status: commandUnavailable(error),
|
|
343
363
|
loggedIn: false,
|
|
344
|
-
authMethod:
|
|
345
|
-
apiProvider:
|
|
346
|
-
source:
|
|
364
|
+
authMethod: "",
|
|
365
|
+
apiProvider: "",
|
|
366
|
+
source: "claude auth status --json"
|
|
347
367
|
};
|
|
348
368
|
}
|
|
349
369
|
}
|
|
350
|
-
|
|
351
370
|
function localDateKey(timestamp) {
|
|
352
371
|
const date = new Date(timestamp);
|
|
353
|
-
if (!Number.isFinite(date.getTime())) return
|
|
372
|
+
if (!Number.isFinite(date.getTime())) return "";
|
|
354
373
|
const year = date.getFullYear();
|
|
355
|
-
const month = String(date.getMonth() + 1).padStart(2,
|
|
356
|
-
const day = String(date.getDate()).padStart(2,
|
|
374
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
375
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
357
376
|
return `${year}-${month}-${day}`;
|
|
358
377
|
}
|
|
359
|
-
|
|
360
378
|
function buildDailyUsage(providerEvents, options = {}) {
|
|
361
379
|
const now = options.now ?? Date.now();
|
|
362
380
|
const days = Math.max(1, Math.floor(options.days ?? USAGE_DAILY_DAYS));
|
|
@@ -364,21 +382,19 @@ function buildDailyUsage(providerEvents, options = {}) {
|
|
|
364
382
|
cursor.setHours(0, 0, 0, 0);
|
|
365
383
|
cursor.setDate(cursor.getDate() - days + 1);
|
|
366
384
|
const points = [];
|
|
367
|
-
const byDate = new Map();
|
|
385
|
+
const byDate = /* @__PURE__ */ new Map();
|
|
368
386
|
const providerNames = Object.keys(providerEvents || {});
|
|
369
|
-
|
|
370
387
|
for (let index = 0; index < days; index += 1) {
|
|
371
388
|
const date = localDateKey(cursor.getTime());
|
|
372
389
|
const point = {
|
|
373
390
|
date,
|
|
374
391
|
...emptyTokenBreakdown(),
|
|
375
|
-
providers: Object.fromEntries(providerNames.map(provider => [provider, emptyTokenBreakdown()]))
|
|
392
|
+
providers: Object.fromEntries(providerNames.map((provider) => [provider, emptyTokenBreakdown()]))
|
|
376
393
|
};
|
|
377
394
|
points.push(point);
|
|
378
395
|
byDate.set(date, point);
|
|
379
396
|
cursor.setDate(cursor.getDate() + 1);
|
|
380
397
|
}
|
|
381
|
-
|
|
382
398
|
for (const provider of providerNames) {
|
|
383
399
|
for (const event of providerEvents[provider] || []) {
|
|
384
400
|
const point = byDate.get(localDateKey(parseTimestampMs(event?.timestamp)));
|
|
@@ -387,73 +403,62 @@ function buildDailyUsage(providerEvents, options = {}) {
|
|
|
387
403
|
addTokenBreakdown(point.providers[provider], event);
|
|
388
404
|
}
|
|
389
405
|
}
|
|
390
|
-
|
|
391
|
-
const
|
|
392
|
-
.slice(Math.max(0, points.length - count))
|
|
393
|
-
.reduce((total, point) => total + point.totalTokens, 0);
|
|
394
|
-
const peak = points.reduce((best, point) => (
|
|
395
|
-
!best || point.totalTokens > best.totalTokens ? point : best
|
|
396
|
-
), null);
|
|
397
|
-
|
|
406
|
+
const sumRange = (count) => points.slice(Math.max(0, points.length - count)).reduce((total, point) => total + point.totalTokens, 0);
|
|
407
|
+
const peak = points.reduce((best, point) => !best || point.totalTokens > best.totalTokens ? point : best, null);
|
|
398
408
|
return {
|
|
399
|
-
source:
|
|
409
|
+
source: "local provider token events",
|
|
400
410
|
sampledAt: now,
|
|
401
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone ||
|
|
411
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone || "local",
|
|
402
412
|
days,
|
|
403
|
-
startDate: points[0]?.date ||
|
|
404
|
-
endDate: points[points.length - 1]?.date ||
|
|
413
|
+
startDate: points[0]?.date || "",
|
|
414
|
+
endDate: points[points.length - 1]?.date || "",
|
|
405
415
|
summary: {
|
|
406
416
|
todayTokens: sumRange(1),
|
|
407
417
|
sevenDayTokens: sumRange(7),
|
|
408
418
|
thirtyDayTokens: sumRange(30),
|
|
409
419
|
periodTokens: sumRange(days),
|
|
410
|
-
peakDate: peak?.date ||
|
|
411
|
-
peakTokens: peak?.totalTokens || 0
|
|
420
|
+
peakDate: peak?.date || "",
|
|
421
|
+
peakTokens: peak?.totalTokens || 0
|
|
412
422
|
},
|
|
413
|
-
points
|
|
423
|
+
points
|
|
414
424
|
};
|
|
415
425
|
}
|
|
416
|
-
|
|
417
426
|
function buildUsageDayDetail(providerEvents, options = {}) {
|
|
418
|
-
const date = String(options.date ||
|
|
419
|
-
const parts = date.split(
|
|
420
|
-
const dateProbe = parts.length === 3
|
|
421
|
-
? new Date(parts[0], parts[1] - 1, parts[2], 12, 0, 0, 0)
|
|
422
|
-
: null;
|
|
427
|
+
const date = String(options.date || "").trim();
|
|
428
|
+
const parts = date.split("-").map(Number);
|
|
429
|
+
const dateProbe = parts.length === 3 ? new Date(parts[0], parts[1] - 1, parts[2], 12, 0, 0, 0) : null;
|
|
423
430
|
if (!dateProbe || localDateKey(dateProbe.getTime()) !== date) {
|
|
424
|
-
throw new RangeError(
|
|
431
|
+
throw new RangeError("Usage day must be a valid local date in YYYY-MM-DD format.");
|
|
425
432
|
}
|
|
426
|
-
|
|
427
433
|
const providerNames = Object.keys(providerEvents || {});
|
|
428
434
|
const hours = Array.from({ length: 24 }, (_, hour) => ({
|
|
429
435
|
hour,
|
|
430
|
-
label: String(hour).padStart(2,
|
|
436
|
+
label: String(hour).padStart(2, "0"),
|
|
431
437
|
...emptyTokenBreakdown(),
|
|
432
|
-
agents: {}
|
|
438
|
+
agents: {}
|
|
433
439
|
}));
|
|
434
440
|
const providers = Object.fromEntries(
|
|
435
|
-
providerNames.map(provider => [provider, emptyTokenBreakdown()])
|
|
441
|
+
providerNames.map((provider) => [provider, emptyTokenBreakdown()])
|
|
436
442
|
);
|
|
437
443
|
const total = emptyTokenBreakdown();
|
|
438
|
-
const agents = new Map();
|
|
439
|
-
const agentLabels = options.agentLabels instanceof Map ? options.agentLabels : new Map();
|
|
440
|
-
|
|
444
|
+
const agents = /* @__PURE__ */ new Map();
|
|
445
|
+
const agentLabels = options.agentLabels instanceof Map ? options.agentLabels : /* @__PURE__ */ new Map();
|
|
441
446
|
for (const provider of providerNames) {
|
|
442
447
|
for (const event of providerEvents[provider] || []) {
|
|
443
448
|
const timestamp = parseTimestampMs(event?.timestamp);
|
|
444
449
|
if (localDateKey(timestamp) !== date) continue;
|
|
445
450
|
const hour = new Date(timestamp).getHours();
|
|
446
451
|
if (!Number.isInteger(hour) || hour < 0 || hour > 23) continue;
|
|
447
|
-
const agentId = String(event?.agentId ||
|
|
452
|
+
const agentId = String(event?.agentId || "unattributed");
|
|
448
453
|
const agentKey = `${provider}:${agentId}`;
|
|
449
454
|
let agent = agents.get(agentKey);
|
|
450
455
|
if (!agent) {
|
|
451
456
|
agent = {
|
|
452
457
|
key: agentKey,
|
|
453
458
|
provider,
|
|
454
|
-
sessionId: agentId ===
|
|
459
|
+
sessionId: agentId === "unattributed" ? "" : agentId,
|
|
455
460
|
label: agentLabels.get(agentKey) || event?.agentLabel || usageAgentLabel(provider, agentId),
|
|
456
|
-
...emptyTokenBreakdown()
|
|
461
|
+
...emptyTokenBreakdown()
|
|
457
462
|
};
|
|
458
463
|
agents.set(agentKey, agent);
|
|
459
464
|
}
|
|
@@ -465,89 +470,89 @@ function buildUsageDayDetail(providerEvents, options = {}) {
|
|
|
465
470
|
addTokenBreakdown(total, event);
|
|
466
471
|
}
|
|
467
472
|
}
|
|
468
|
-
|
|
469
473
|
return {
|
|
470
|
-
source:
|
|
474
|
+
source: "local provider token events",
|
|
471
475
|
date,
|
|
472
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone ||
|
|
476
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone || "local",
|
|
473
477
|
total,
|
|
474
478
|
hours,
|
|
475
479
|
providers,
|
|
476
|
-
agents: Array.from(agents.values()).sort((left, right) => (
|
|
477
|
-
right.totalTokens - left.totalTokens || left.label.localeCompare(right.label)
|
|
478
|
-
)),
|
|
480
|
+
agents: Array.from(agents.values()).sort((left, right) => right.totalTokens - left.totalTokens || left.label.localeCompare(right.label))
|
|
479
481
|
};
|
|
480
482
|
}
|
|
481
|
-
|
|
482
483
|
async function defaultOpenCodeCommandRunner(args, options = {}) {
|
|
483
484
|
const env = { ...process.env };
|
|
484
485
|
if (options.openCodeHome) env.OPENCODE_CONFIG_DIR = options.openCodeHome;
|
|
485
486
|
const result = await execFileAsync(
|
|
486
|
-
options.openCodeBin || process.env.FARMING_OPENCODE_BIN ||
|
|
487
|
+
options.openCodeBin || process.env.FARMING_OPENCODE_BIN || "opencode",
|
|
487
488
|
args,
|
|
488
489
|
{
|
|
489
490
|
env,
|
|
490
491
|
timeout: options.timeoutMs ?? OPENCODE_COMMAND_TIMEOUT_MS,
|
|
491
492
|
maxBuffer: options.maxBuffer ?? 64 * 1024 * 1024,
|
|
492
|
-
windowsHide: true
|
|
493
|
-
}
|
|
493
|
+
windowsHide: true
|
|
494
|
+
}
|
|
494
495
|
);
|
|
495
|
-
return { stdout: String(result.stdout ||
|
|
496
|
+
return { stdout: String(result.stdout || ""), stderr: String(result.stderr || "") };
|
|
496
497
|
}
|
|
497
|
-
|
|
498
498
|
function openCodeTokenEventsFromExport(sessionExport, options = {}) {
|
|
499
499
|
const cutoffMs = options.cutoffMs ?? 0;
|
|
500
500
|
const now = options.now ?? Date.now();
|
|
501
501
|
const events = [];
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
|
|
502
|
+
const exported = asRecord(sessionExport);
|
|
503
|
+
for (const messageValue of Array.isArray(exported?.messages) ? exported.messages : []) {
|
|
504
|
+
const message = asRecord(messageValue);
|
|
505
|
+
const info = asRecord(message?.info);
|
|
506
|
+
const time = asRecord(info?.time);
|
|
507
|
+
if (info?.role !== "assistant" || !info.tokens) continue;
|
|
508
|
+
const timestamp = parseTimestampMs(time?.completed ?? time?.created);
|
|
509
|
+
if (!timestamp || timestamp < cutoffMs || timestamp > now + 6e4) continue;
|
|
507
510
|
const breakdown = tokenBreakdownFromOpenCode(info.tokens);
|
|
508
511
|
if (breakdown.totalTokens > 0) events.push({ timestamp, ...breakdown });
|
|
509
512
|
}
|
|
510
513
|
return events;
|
|
511
514
|
}
|
|
512
|
-
|
|
513
515
|
function cacheOpenCodeSessionEvents(cacheKey, value) {
|
|
514
516
|
openCodeSessionEventCache.delete(cacheKey);
|
|
515
517
|
openCodeSessionEventCache.set(cacheKey, value);
|
|
516
518
|
while (openCodeSessionEventCache.size > OPENCODE_SESSION_CACHE_LIMIT) {
|
|
517
519
|
const oldestKey = openCodeSessionEventCache.keys().next().value;
|
|
518
|
-
if (oldestKey ===
|
|
520
|
+
if (oldestKey === void 0) break;
|
|
519
521
|
openCodeSessionEventCache.delete(oldestKey);
|
|
520
522
|
}
|
|
521
523
|
}
|
|
522
|
-
|
|
523
524
|
async function collectOpenCodeDailyEvents(homePaths, options = {}) {
|
|
524
525
|
const now = options.now ?? Date.now();
|
|
525
526
|
const cutoffMs = options.cutoffMs ?? 0;
|
|
526
527
|
const commandRunner = options.openCodeCommandRunner || defaultOpenCodeCommandRunner;
|
|
527
528
|
const sessions = [];
|
|
528
|
-
const seenSessionIds = new Set();
|
|
529
|
+
const seenSessionIds = /* @__PURE__ */ new Set();
|
|
529
530
|
let successfulHomes = 0;
|
|
530
531
|
let successfulExports = 0;
|
|
531
532
|
let partial = false;
|
|
532
|
-
let reason =
|
|
533
|
-
|
|
533
|
+
let reason = "";
|
|
534
534
|
for (const openCodeHome of homePaths) {
|
|
535
535
|
try {
|
|
536
536
|
const result = await commandRunner([
|
|
537
|
-
|
|
537
|
+
"session",
|
|
538
|
+
"list",
|
|
539
|
+
"--format",
|
|
540
|
+
"json",
|
|
541
|
+
"--max-count",
|
|
542
|
+
String(OPENCODE_SESSION_LIMIT)
|
|
538
543
|
], { openCodeHome, timeoutMs: OPENCODE_COMMAND_TIMEOUT_MS });
|
|
539
|
-
const listed = JSON.parse(String(result?.stdout ||
|
|
540
|
-
if (!Array.isArray(listed)) throw new Error(
|
|
544
|
+
const listed = JSON.parse(String(result?.stdout || "[]"));
|
|
545
|
+
if (!Array.isArray(listed)) throw new Error("OpenCode session list was not an array");
|
|
541
546
|
successfulHomes += 1;
|
|
542
547
|
if (listed.length >= OPENCODE_SESSION_LIMIT) {
|
|
543
548
|
partial = true;
|
|
544
|
-
reason = reason
|
|
545
|
-
|| `OpenCode returned the ${OPENCODE_SESSION_LIMIT.toLocaleString('en-US')} session limit; older sessions may be omitted.`;
|
|
549
|
+
reason = reason || `OpenCode returned the ${OPENCODE_SESSION_LIMIT.toLocaleString("en-US")} session limit; older sessions may be omitted.`;
|
|
546
550
|
}
|
|
547
|
-
for (const
|
|
548
|
-
const
|
|
551
|
+
for (const sessionValue of listed) {
|
|
552
|
+
const session = asRecord(sessionValue);
|
|
553
|
+
const id = typeof session?.id === "string" ? session.id.trim() : "";
|
|
549
554
|
const updatedAt = parseTimestampMs(session?.updated ?? session?.created);
|
|
550
|
-
if (!id || seenSessionIds.has(id) ||
|
|
555
|
+
if (!id || seenSessionIds.has(id) || updatedAt && updatedAt < cutoffMs) continue;
|
|
551
556
|
seenSessionIds.add(id);
|
|
552
557
|
sessions.push({ id, openCodeHome, updatedAt: updatedAt || 0 });
|
|
553
558
|
}
|
|
@@ -556,7 +561,6 @@ async function collectOpenCodeDailyEvents(homePaths, options = {}) {
|
|
|
556
561
|
reason = reason || commandUnavailable(error);
|
|
557
562
|
}
|
|
558
563
|
}
|
|
559
|
-
|
|
560
564
|
const events = [];
|
|
561
565
|
let nextSessionIndex = 0;
|
|
562
566
|
const worker = async () => {
|
|
@@ -573,16 +577,15 @@ async function collectOpenCodeDailyEvents(homePaths, options = {}) {
|
|
|
573
577
|
}
|
|
574
578
|
try {
|
|
575
579
|
const result = await commandRunner(
|
|
576
|
-
[
|
|
577
|
-
{ openCodeHome: session.openCodeHome, timeoutMs: OPENCODE_COMMAND_TIMEOUT_MS }
|
|
580
|
+
["export", session.id, "--pure", "--sanitize"],
|
|
581
|
+
{ openCodeHome: session.openCodeHome, timeoutMs: OPENCODE_COMMAND_TIMEOUT_MS }
|
|
578
582
|
);
|
|
579
|
-
const exported = JSON.parse(String(result?.stdout ||
|
|
580
|
-
const sessionEvents = openCodeTokenEventsFromExport(exported, { cutoffMs, now })
|
|
581
|
-
.map(event => attributeUsageEvent(event, 'opencode', session.id));
|
|
583
|
+
const exported = JSON.parse(String(result?.stdout || "{}"));
|
|
584
|
+
const sessionEvents = openCodeTokenEventsFromExport(exported, { cutoffMs, now }).map((event) => attributeUsageEvent(event, "opencode", session.id));
|
|
582
585
|
successfulExports += 1;
|
|
583
586
|
cacheOpenCodeSessionEvents(
|
|
584
587
|
cacheKey,
|
|
585
|
-
{ updatedAt: session.updatedAt, events: sessionEvents }
|
|
588
|
+
{ updatedAt: session.updatedAt, events: sessionEvents }
|
|
586
589
|
);
|
|
587
590
|
events.push(...sessionEvents);
|
|
588
591
|
} catch (error) {
|
|
@@ -593,21 +596,17 @@ async function collectOpenCodeDailyEvents(homePaths, options = {}) {
|
|
|
593
596
|
};
|
|
594
597
|
await Promise.all(Array.from(
|
|
595
598
|
{ length: Math.min(OPENCODE_EXPORT_CONCURRENCY, sessions.length) },
|
|
596
|
-
() => worker()
|
|
599
|
+
() => worker()
|
|
597
600
|
));
|
|
598
|
-
|
|
599
601
|
return {
|
|
600
602
|
events,
|
|
601
603
|
partial,
|
|
602
|
-
available: !partial
|
|
603
|
-
&& successfulHomes === homePaths.length
|
|
604
|
-
&& (sessions.length === 0 || successfulExports === sessions.length),
|
|
604
|
+
available: !partial && successfulHomes === homePaths.length && (sessions.length === 0 || successfulExports === sessions.length),
|
|
605
605
|
reason,
|
|
606
606
|
sessionCount: sessions.length,
|
|
607
|
-
exportCount: successfulExports
|
|
607
|
+
exportCount: successfulExports
|
|
608
608
|
};
|
|
609
609
|
}
|
|
610
|
-
|
|
611
610
|
async function collectUsageHistory(options = {}) {
|
|
612
611
|
const now = options.now ?? Date.now();
|
|
613
612
|
const days = options.days ?? USAGE_DAILY_DAYS;
|
|
@@ -616,69 +615,69 @@ async function collectUsageHistory(options = {}) {
|
|
|
616
615
|
cutoff.setDate(cutoff.getDate() - days);
|
|
617
616
|
const openCodeHomes = providerHomePaths(
|
|
618
617
|
options.providerHomes,
|
|
619
|
-
|
|
620
|
-
options.openCodeHome || path.join(os.homedir(),
|
|
618
|
+
"opencode",
|
|
619
|
+
options.openCodeHome || path.join(os.homedir(), ".opencode")
|
|
621
620
|
);
|
|
622
621
|
const qoderHomes = providerHomePaths(
|
|
623
622
|
options.providerHomes,
|
|
624
|
-
|
|
625
|
-
options.qoderHome || path.join(os.homedir(),
|
|
623
|
+
"qoder",
|
|
624
|
+
options.qoderHome || path.join(os.homedir(), ".qoder")
|
|
626
625
|
);
|
|
627
626
|
const [ccStatistics, openCode] = await Promise.all([
|
|
628
627
|
collectCCStatistics({ ...options, now, days }),
|
|
629
628
|
collectOpenCodeDailyEvents(openCodeHomes, {
|
|
630
629
|
now,
|
|
631
630
|
cutoffMs: cutoff.getTime(),
|
|
632
|
-
openCodeCommandRunner: options.openCodeCommandRunner
|
|
633
|
-
})
|
|
631
|
+
openCodeCommandRunner: options.openCodeCommandRunner
|
|
632
|
+
})
|
|
634
633
|
]);
|
|
635
634
|
const codex = ccStatistics.result.providers.codex;
|
|
636
635
|
const claude = ccStatistics.result.providers.claude;
|
|
637
|
-
const codexEvents = ccStatisticsProviderEvents(ccStatistics.result,
|
|
638
|
-
const claudeEvents = ccStatisticsProviderEvents(ccStatistics.result,
|
|
636
|
+
const codexEvents = ccStatisticsProviderEvents(ccStatistics.result, "codex");
|
|
637
|
+
const claudeEvents = ccStatisticsProviderEvents(ccStatistics.result, "claude");
|
|
639
638
|
const providerEvents = {
|
|
640
639
|
codex: codexEvents,
|
|
641
640
|
claude: claudeEvents,
|
|
642
|
-
opencode: openCode.events
|
|
641
|
+
opencode: openCode.events
|
|
643
642
|
};
|
|
644
643
|
const coverage = [
|
|
645
644
|
{
|
|
646
|
-
provider:
|
|
647
|
-
providerName:
|
|
645
|
+
provider: "codex",
|
|
646
|
+
providerName: "Codex",
|
|
648
647
|
available: codex.available === true,
|
|
649
648
|
homeCount: ccStatistics.roots.codexHomes.length,
|
|
650
649
|
fileCount: codex.fileCount,
|
|
651
650
|
source: codex.source || ccStatistics.result.source,
|
|
652
|
-
...
|
|
651
|
+
...codex.reason ? { reason: codex.reason } : {}
|
|
653
652
|
},
|
|
654
653
|
{
|
|
655
|
-
provider:
|
|
656
|
-
providerName:
|
|
654
|
+
provider: "claude",
|
|
655
|
+
providerName: "Claude",
|
|
657
656
|
available: claude.available === true,
|
|
658
657
|
homeCount: ccStatistics.roots.claudeHomes.length,
|
|
659
658
|
fileCount: claude.fileCount,
|
|
660
659
|
source: claude.source || ccStatistics.result.source,
|
|
661
|
-
...
|
|
660
|
+
...claude.reason ? { reason: claude.reason } : {}
|
|
662
661
|
},
|
|
663
662
|
{
|
|
664
|
-
provider:
|
|
665
|
-
providerName:
|
|
663
|
+
provider: "opencode",
|
|
664
|
+
providerName: "OpenCode",
|
|
666
665
|
available: openCode.available,
|
|
667
666
|
homeCount: openCodeHomes.length,
|
|
668
667
|
sessionCount: openCode.sessionCount,
|
|
669
668
|
exportCount: openCode.exportCount,
|
|
670
669
|
partial: openCode.partial,
|
|
671
|
-
source:
|
|
672
|
-
...
|
|
670
|
+
source: "opencode session export",
|
|
671
|
+
...openCode.reason ? { reason: openCode.reason } : {}
|
|
673
672
|
},
|
|
674
673
|
{
|
|
675
|
-
provider:
|
|
676
|
-
providerName:
|
|
674
|
+
provider: "qoder",
|
|
675
|
+
providerName: "Qoder",
|
|
677
676
|
available: false,
|
|
678
677
|
homeCount: qoderHomes.length,
|
|
679
|
-
source:
|
|
680
|
-
reason:
|
|
681
|
-
}
|
|
678
|
+
source: "local Qoder sessions",
|
|
679
|
+
reason: "Qoder session files do not expose model token usage."
|
|
680
|
+
}
|
|
682
681
|
];
|
|
683
682
|
return {
|
|
684
683
|
daily: {
|
|
@@ -686,58 +685,53 @@ async function collectUsageHistory(options = {}) {
|
|
|
686
685
|
partial: codex.available !== true || claude.available !== true || openCode.partial,
|
|
687
686
|
syncing: ccStatistics.result.cache?.scan_complete === false,
|
|
688
687
|
coverage,
|
|
689
|
-
ccStatisticsCache: ccStatistics.result.cache
|
|
688
|
+
ccStatisticsCache: ccStatistics.result.cache
|
|
690
689
|
},
|
|
691
690
|
providerEvents,
|
|
692
|
-
coverage
|
|
691
|
+
coverage
|
|
693
692
|
};
|
|
694
693
|
}
|
|
695
|
-
|
|
696
694
|
async function collectDailyUsage(options = {}) {
|
|
697
695
|
return (await collectUsageHistory(options)).daily;
|
|
698
696
|
}
|
|
699
|
-
|
|
700
697
|
function parseCodexLimit(limit) {
|
|
701
|
-
if (!limit || typeof limit !==
|
|
702
|
-
const
|
|
703
|
-
const
|
|
704
|
-
const
|
|
705
|
-
const
|
|
706
|
-
|
|
698
|
+
if (!limit || typeof limit !== "object") return null;
|
|
699
|
+
const source = limit;
|
|
700
|
+
const usedPercent = numberOrNull(source.used_percent ?? source.usedPercent);
|
|
701
|
+
const windowMinutes = numberOrNull(source.window_minutes ?? source.windowMinutes ?? source.windowDurationMins);
|
|
702
|
+
const resetsAt = normalizeEpochMs(source.resets_at ?? source.resetsAt);
|
|
703
|
+
const totalTokens = numberOrNull(source.total_tokens ?? source.totalTokens ?? source.limit_tokens ?? source.limitTokens);
|
|
707
704
|
if (usedPercent === null && windowMinutes === null && resetsAt === null && totalTokens === null) return null;
|
|
708
705
|
return {
|
|
709
706
|
usedPercent,
|
|
710
707
|
windowMinutes,
|
|
711
708
|
resetsAt,
|
|
712
|
-
totalTokens
|
|
709
|
+
totalTokens
|
|
713
710
|
};
|
|
714
711
|
}
|
|
715
|
-
|
|
716
712
|
function parseCodexRateLimits(rateLimits) {
|
|
717
|
-
if (!rateLimits || typeof rateLimits !==
|
|
718
|
-
const
|
|
719
|
-
const
|
|
720
|
-
|
|
713
|
+
if (!rateLimits || typeof rateLimits !== "object") return null;
|
|
714
|
+
const source = rateLimits;
|
|
715
|
+
const primary = parseCodexLimit(source.primary);
|
|
716
|
+
const secondary = parseCodexLimit(source.secondary);
|
|
721
717
|
if (!primary && !secondary) return null;
|
|
722
|
-
const resetCredits =
|
|
718
|
+
const resetCredits = asRecord(source.rate_limit_reset_credits ?? source.rateLimitResetCredits);
|
|
723
719
|
const resetCreditsAvailable = numberOrNull(resetCredits?.available_count ?? resetCredits?.availableCount);
|
|
724
720
|
return {
|
|
725
721
|
available: true,
|
|
726
|
-
source:
|
|
727
|
-
limitId:
|
|
728
|
-
limitName:
|
|
729
|
-
planType:
|
|
722
|
+
source: "codex token_count events",
|
|
723
|
+
limitId: source.limit_id || source.limitId || "",
|
|
724
|
+
limitName: source.limit_name ?? source.limitName ?? null,
|
|
725
|
+
planType: source.plan_type || source.planType || "",
|
|
730
726
|
resetCreditsAvailable,
|
|
731
727
|
primary,
|
|
732
|
-
secondary
|
|
728
|
+
secondary
|
|
733
729
|
};
|
|
734
730
|
}
|
|
735
|
-
|
|
736
731
|
function isCodexOverallRateLimit(quota) {
|
|
737
|
-
const limitId = String(quota?.limitId ||
|
|
738
|
-
return !limitId || limitId ===
|
|
732
|
+
const limitId = String(quota?.limitId || "").trim().toLowerCase();
|
|
733
|
+
return !limitId || limitId === "codex";
|
|
739
734
|
}
|
|
740
|
-
|
|
741
735
|
async function collectCodexUsage(options = {}) {
|
|
742
736
|
const now = options.now ?? Date.now();
|
|
743
737
|
const windowMs = options.windowMs ?? USAGE_WINDOW_MS;
|
|
@@ -745,16 +739,15 @@ async function collectCodexUsage(options = {}) {
|
|
|
745
739
|
const ccStatistics = await collectCCStatistics({
|
|
746
740
|
...options,
|
|
747
741
|
now,
|
|
748
|
-
days: options.days ?? USAGE_DAILY_DAYS
|
|
742
|
+
days: options.days ?? USAGE_DAILY_DAYS
|
|
749
743
|
});
|
|
750
744
|
const provider = ccStatistics.result.providers.codex;
|
|
751
745
|
const providerSource = provider.source || ccStatistics.result.source;
|
|
752
|
-
const events = ccStatisticsProviderEvents(ccStatistics.result,
|
|
746
|
+
const events = ccStatisticsProviderEvents(ccStatistics.result, "codex");
|
|
753
747
|
let latestQuota = null;
|
|
754
748
|
let latestQuotaAt = 0;
|
|
755
749
|
let latestOverallQuota = null;
|
|
756
750
|
let latestOverallQuotaAt = 0;
|
|
757
|
-
|
|
758
751
|
for (const candidate of provider.quotaCandidates || []) {
|
|
759
752
|
const timestamp = parseTimestampMs(candidate.timestamp);
|
|
760
753
|
const rateLimits = parseCodexRateLimits(candidate.rateLimits);
|
|
@@ -770,25 +763,23 @@ async function collectCodexUsage(options = {}) {
|
|
|
770
763
|
const quota = latestOverallQuota || latestQuota || {
|
|
771
764
|
available: false,
|
|
772
765
|
source: providerSource,
|
|
773
|
-
reason: provider.reason ||
|
|
766
|
+
reason: provider.reason || "No Codex token_count event with rate limits was found."
|
|
774
767
|
};
|
|
775
768
|
const usage = providerUsageFromEvents(events, {
|
|
776
769
|
now,
|
|
777
770
|
windowMs,
|
|
778
771
|
historyWindowMs,
|
|
779
|
-
source: providerSource
|
|
772
|
+
source: providerSource
|
|
780
773
|
});
|
|
781
774
|
if (provider.available !== true) {
|
|
782
775
|
usage.tokenUsage.available = false;
|
|
783
|
-
usage.tokenUsage.reason = provider.reason ||
|
|
776
|
+
usage.tokenUsage.reason = provider.reason || "Local usage history is unavailable.";
|
|
784
777
|
}
|
|
785
|
-
|
|
786
778
|
return {
|
|
787
|
-
quota: attachQuotaForecasts(quota, { now }),
|
|
788
|
-
...usage
|
|
779
|
+
quota: (0, import_usage_forecast.attachQuotaForecasts)(quota, { now }),
|
|
780
|
+
...usage
|
|
789
781
|
};
|
|
790
782
|
}
|
|
791
|
-
|
|
792
783
|
async function collectClaudeUsage(options = {}) {
|
|
793
784
|
const now = options.now ?? Date.now();
|
|
794
785
|
const windowMs = options.windowMs ?? USAGE_WINDOW_MS;
|
|
@@ -796,33 +787,48 @@ async function collectClaudeUsage(options = {}) {
|
|
|
796
787
|
const ccStatistics = await collectCCStatistics({
|
|
797
788
|
...options,
|
|
798
789
|
now,
|
|
799
|
-
days: options.days ?? USAGE_DAILY_DAYS
|
|
790
|
+
days: options.days ?? USAGE_DAILY_DAYS
|
|
800
791
|
});
|
|
801
792
|
const provider = ccStatistics.result.providers.claude;
|
|
802
793
|
const providerSource = provider.source || ccStatistics.result.source;
|
|
803
|
-
const events = ccStatisticsProviderEvents(ccStatistics.result,
|
|
794
|
+
const events = ccStatisticsProviderEvents(ccStatistics.result, "claude");
|
|
804
795
|
const usage = providerUsageFromEvents(events, {
|
|
805
796
|
now,
|
|
806
797
|
windowMs,
|
|
807
798
|
historyWindowMs,
|
|
808
|
-
source: providerSource
|
|
799
|
+
source: providerSource
|
|
809
800
|
});
|
|
810
801
|
if (provider.available !== true) {
|
|
811
802
|
usage.tokenUsage.available = false;
|
|
812
|
-
usage.tokenUsage.reason = provider.reason ||
|
|
803
|
+
usage.tokenUsage.reason = provider.reason || "Local usage history is unavailable.";
|
|
813
804
|
}
|
|
814
|
-
|
|
815
805
|
return {
|
|
816
806
|
quota: {
|
|
817
807
|
available: false,
|
|
818
|
-
source:
|
|
819
|
-
reason:
|
|
808
|
+
source: "claude auth status",
|
|
809
|
+
reason: "Claude Code auth/status output does not expose usage remaining."
|
|
820
810
|
},
|
|
821
|
-
...usage
|
|
811
|
+
...usage
|
|
822
812
|
};
|
|
823
813
|
}
|
|
824
|
-
|
|
825
814
|
class UsageMonitor {
|
|
815
|
+
agentManager;
|
|
816
|
+
systemMonitor;
|
|
817
|
+
commandRunner;
|
|
818
|
+
codexHome;
|
|
819
|
+
claudeHome;
|
|
820
|
+
openCodeHome;
|
|
821
|
+
qoderHome;
|
|
822
|
+
getProviderHomes;
|
|
823
|
+
openCodeCommandRunner;
|
|
824
|
+
configDir;
|
|
825
|
+
ccStatisticsClient;
|
|
826
|
+
windowMs;
|
|
827
|
+
dailyDays;
|
|
828
|
+
dailyCacheMs;
|
|
829
|
+
dailyCache;
|
|
830
|
+
liveDayCacheMs;
|
|
831
|
+
liveDayCache;
|
|
826
832
|
constructor(options = {}) {
|
|
827
833
|
this.agentManager = options.agentManager || null;
|
|
828
834
|
this.systemMonitor = options.systemMonitor || this.agentManager?.systemMonitor || null;
|
|
@@ -833,61 +839,48 @@ class UsageMonitor {
|
|
|
833
839
|
this.qoderHome = options.qoderHome;
|
|
834
840
|
this.getProviderHomes = options.getProviderHomes || null;
|
|
835
841
|
this.openCodeCommandRunner = options.openCodeCommandRunner;
|
|
836
|
-
this.configDir = options.configDir || path.join(os.homedir(),
|
|
837
|
-
this.ccStatisticsClient = options.usageHistoryClient
|
|
838
|
-
|| options.ccStatisticsClient
|
|
839
|
-
|| new UsageHistoryClient({ configDir: this.configDir });
|
|
842
|
+
this.configDir = options.configDir || path.join(os.homedir(), ".farming");
|
|
843
|
+
this.ccStatisticsClient = options.usageHistoryClient || options.ccStatisticsClient || new import_usage_history_client.UsageHistoryClient({ configDir: this.configDir });
|
|
840
844
|
this.windowMs = options.windowMs ?? USAGE_WINDOW_MS;
|
|
841
845
|
this.dailyDays = options.dailyDays ?? USAGE_DAILY_DAYS;
|
|
842
846
|
this.dailyCacheMs = options.dailyCacheMs ?? USAGE_DAILY_CACHE_MS;
|
|
843
847
|
this.dailyCache = { value: null, fetchedAt: 0, pending: null };
|
|
844
848
|
this.liveDayCacheMs = options.liveDayCacheMs ?? USAGE_LIVE_DAY_CACHE_MS;
|
|
845
|
-
this.liveDayCache = { date:
|
|
849
|
+
this.liveDayCache = { date: "", value: null, fetchedAt: 0, pending: null };
|
|
846
850
|
}
|
|
847
|
-
|
|
848
851
|
invalidateDailyCache() {
|
|
849
852
|
this.dailyCache.fetchedAt = 0;
|
|
850
853
|
this.liveDayCache.fetchedAt = 0;
|
|
851
854
|
}
|
|
852
|
-
|
|
853
855
|
usageAgentLabels() {
|
|
854
|
-
const labels = new Map();
|
|
856
|
+
const labels = /* @__PURE__ */ new Map();
|
|
855
857
|
const agents = this.agentManager?.getState?.().agents;
|
|
856
858
|
if (!Array.isArray(agents)) return labels;
|
|
857
|
-
for (const
|
|
858
|
-
const
|
|
859
|
-
const
|
|
859
|
+
for (const agentValue of agents) {
|
|
860
|
+
const agent = asRecord(agentValue);
|
|
861
|
+
const provider = String(agent?.providerSessionProvider || "").trim();
|
|
862
|
+
const sessionId = String(agent?.providerSessionId || "").trim();
|
|
860
863
|
if (!provider || !sessionId) continue;
|
|
861
864
|
const label = String(
|
|
862
|
-
agent
|
|
863
|
-
|| agent.task
|
|
864
|
-
|| agent.sessionTitle
|
|
865
|
-
|| agent.providerSessionTitle
|
|
866
|
-
|| '',
|
|
865
|
+
agent?.customTitle || agent?.task || agent?.sessionTitle || agent?.providerSessionTitle || ""
|
|
867
866
|
).trim();
|
|
868
867
|
if (label) labels.set(`${provider}:${sessionId}`, label);
|
|
869
868
|
}
|
|
870
869
|
return labels;
|
|
871
870
|
}
|
|
872
|
-
|
|
873
871
|
buildUsageDay(providerEvents, date) {
|
|
874
872
|
return buildUsageDayDetail(providerEvents, {
|
|
875
873
|
date,
|
|
876
|
-
agentLabels: this.usageAgentLabels()
|
|
874
|
+
agentLabels: this.usageAgentLabels()
|
|
877
875
|
});
|
|
878
876
|
}
|
|
879
|
-
|
|
880
877
|
getDailyUsage(options = {}) {
|
|
881
878
|
const now = options.now ?? Date.now();
|
|
882
|
-
if (
|
|
883
|
-
!options.force
|
|
884
|
-
&& this.dailyCache.value
|
|
885
|
-
&& now - this.dailyCache.fetchedAt <= this.dailyCacheMs
|
|
886
|
-
) {
|
|
879
|
+
if (!options.force && this.dailyCache.value && now - this.dailyCache.fetchedAt <= this.dailyCacheMs) {
|
|
887
880
|
return Promise.resolve(this.dailyCache.value);
|
|
888
881
|
}
|
|
889
882
|
if (this.dailyCache.pending) return this.dailyCache.pending;
|
|
890
|
-
const providerHomes = this.getProviderHomes ? this.getProviderHomes() :
|
|
883
|
+
const providerHomes = this.getProviderHomes ? this.getProviderHomes() : void 0;
|
|
891
884
|
this.dailyCache.pending = collectUsageHistory({
|
|
892
885
|
codexHome: this.codexHome,
|
|
893
886
|
claudeHome: this.claudeHome,
|
|
@@ -898,8 +891,8 @@ class UsageMonitor {
|
|
|
898
891
|
configDir: this.configDir,
|
|
899
892
|
ccStatisticsClient: this.ccStatisticsClient,
|
|
900
893
|
now,
|
|
901
|
-
days: this.dailyDays
|
|
902
|
-
}).then(value => {
|
|
894
|
+
days: this.dailyDays
|
|
895
|
+
}).then((value) => {
|
|
903
896
|
this.dailyCache.value = value;
|
|
904
897
|
this.dailyCache.fetchedAt = now;
|
|
905
898
|
return value;
|
|
@@ -908,19 +901,14 @@ class UsageMonitor {
|
|
|
908
901
|
});
|
|
909
902
|
return this.dailyCache.pending;
|
|
910
903
|
}
|
|
911
|
-
|
|
912
904
|
async getUsageDay(date, options = {}) {
|
|
913
905
|
const now = options.now ?? Date.now();
|
|
914
|
-
if (options.live === true && String(date ||
|
|
906
|
+
if (options.live === true && String(date || "").trim() === localDateKey(now)) {
|
|
915
907
|
const liveDate = String(date).trim();
|
|
916
|
-
const dailyFallback = this.dailyCache.value?.providerEvents
|
|
917
|
-
|
|
918
|
-
: null;
|
|
919
|
-
const cachedFallback = this.liveDayCache.date === liveDate
|
|
920
|
-
? this.liveDayCache.value
|
|
921
|
-
: null;
|
|
908
|
+
const dailyFallback = this.dailyCache.value?.providerEvents ? this.buildUsageDay(this.dailyCache.value.providerEvents, liveDate) : null;
|
|
909
|
+
const cachedFallback = this.liveDayCache.date === liveDate ? this.liveDayCache.value : null;
|
|
922
910
|
const fallback = cachedFallback || dailyFallback;
|
|
923
|
-
const recoverWithFallback = error => {
|
|
911
|
+
const recoverWithFallback = (error) => {
|
|
924
912
|
if (!fallback) throw error;
|
|
925
913
|
if (this.liveDayCache.date === liveDate) {
|
|
926
914
|
this.liveDayCache.value = fallback;
|
|
@@ -928,12 +916,7 @@ class UsageMonitor {
|
|
|
928
916
|
}
|
|
929
917
|
return fallback;
|
|
930
918
|
};
|
|
931
|
-
if (
|
|
932
|
-
options.fresh !== true
|
|
933
|
-
&& this.liveDayCache.date === liveDate
|
|
934
|
-
&& this.liveDayCache.value
|
|
935
|
-
&& now - this.liveDayCache.fetchedAt < this.liveDayCacheMs
|
|
936
|
-
) {
|
|
919
|
+
if (options.fresh !== true && this.liveDayCache.date === liveDate && this.liveDayCache.value && now - this.liveDayCache.fetchedAt < this.liveDayCacheMs) {
|
|
937
920
|
return this.liveDayCache.value;
|
|
938
921
|
}
|
|
939
922
|
if (this.liveDayCache.pending && this.liveDayCache.date === liveDate) {
|
|
@@ -945,14 +928,14 @@ class UsageMonitor {
|
|
|
945
928
|
claudeHome: this.claudeHome,
|
|
946
929
|
openCodeHome: this.openCodeHome,
|
|
947
930
|
qoderHome: this.qoderHome,
|
|
948
|
-
providerHomes: this.getProviderHomes ? this.getProviderHomes() :
|
|
931
|
+
providerHomes: this.getProviderHomes ? this.getProviderHomes() : void 0,
|
|
949
932
|
openCodeCommandRunner: this.openCodeCommandRunner,
|
|
950
933
|
configDir: this.configDir,
|
|
951
934
|
ccStatisticsClient: this.ccStatisticsClient,
|
|
952
935
|
now,
|
|
953
|
-
days: 1
|
|
954
|
-
}).then(
|
|
955
|
-
const detail = this.buildUsageDay(
|
|
936
|
+
days: 1
|
|
937
|
+
}).then((history2) => {
|
|
938
|
+
const detail = this.buildUsageDay(history2.providerEvents, liveDate);
|
|
956
939
|
if (this.liveDayCache.date === liveDate) {
|
|
957
940
|
this.liveDayCache.value = detail;
|
|
958
941
|
this.liveDayCache.fetchedAt = now;
|
|
@@ -966,24 +949,22 @@ class UsageMonitor {
|
|
|
966
949
|
}
|
|
967
950
|
const history = await this.getDailyUsage({
|
|
968
951
|
now,
|
|
969
|
-
force: options.fresh === true
|
|
952
|
+
force: options.fresh === true
|
|
970
953
|
});
|
|
971
954
|
return this.buildUsageDay(history.providerEvents, date);
|
|
972
955
|
}
|
|
973
|
-
|
|
974
956
|
async getUsageSummary(options = {}) {
|
|
975
957
|
const now = options.now ?? Date.now();
|
|
976
958
|
const windowMs = options.windowMs ?? this.windowMs;
|
|
977
959
|
const historyWindowMs = options.historyWindowMs ?? USAGE_TIMELINE_WINDOW_MS;
|
|
978
|
-
|
|
979
|
-
const providerHomes = this.getProviderHomes ? this.getProviderHomes() : undefined;
|
|
960
|
+
const providerHomes = this.getProviderHomes ? this.getProviderHomes() : void 0;
|
|
980
961
|
const [
|
|
981
962
|
codexAuth,
|
|
982
963
|
claudeAuth,
|
|
983
964
|
codexUsage,
|
|
984
965
|
claudeUsage,
|
|
985
966
|
history,
|
|
986
|
-
systemStats
|
|
967
|
+
systemStats
|
|
987
968
|
] = await Promise.all([
|
|
988
969
|
readCodexAuthStatus(this.commandRunner),
|
|
989
970
|
readClaudeAuthStatus(this.commandRunner),
|
|
@@ -995,7 +976,7 @@ class UsageMonitor {
|
|
|
995
976
|
ccStatisticsClient: this.ccStatisticsClient,
|
|
996
977
|
now,
|
|
997
978
|
windowMs,
|
|
998
|
-
historyWindowMs
|
|
979
|
+
historyWindowMs
|
|
999
980
|
}),
|
|
1000
981
|
collectClaudeUsage({
|
|
1001
982
|
codexHome: this.codexHome,
|
|
@@ -1005,32 +986,30 @@ class UsageMonitor {
|
|
|
1005
986
|
ccStatisticsClient: this.ccStatisticsClient,
|
|
1006
987
|
now,
|
|
1007
988
|
windowMs,
|
|
1008
|
-
historyWindowMs
|
|
989
|
+
historyWindowMs
|
|
1009
990
|
}),
|
|
1010
991
|
this.getDailyUsage({ now, force: options.fresh === true }),
|
|
1011
|
-
this.systemMonitor?.getSystemStats ? this.systemMonitor.getSystemStats().catch(() => null) : Promise.resolve(null)
|
|
992
|
+
this.systemMonitor?.getSystemStats ? this.systemMonitor.getSystemStats().catch(() => null) : Promise.resolve(null)
|
|
1012
993
|
]);
|
|
1013
|
-
|
|
1014
994
|
const openCodeUsage = providerUsageFromEvents(history.providerEvents.opencode, {
|
|
1015
995
|
now,
|
|
1016
996
|
windowMs,
|
|
1017
997
|
historyWindowMs,
|
|
1018
|
-
source:
|
|
998
|
+
source: "opencode session export"
|
|
1019
999
|
});
|
|
1020
1000
|
const timeline = buildUsageTimeline(history.providerEvents, {
|
|
1021
1001
|
now,
|
|
1022
1002
|
windowMs: historyWindowMs,
|
|
1023
|
-
alignToBucket: true
|
|
1003
|
+
alignToBucket: true
|
|
1024
1004
|
});
|
|
1025
1005
|
const liveTimeline = buildUsageTimeline(history.providerEvents, {
|
|
1026
1006
|
now,
|
|
1027
1007
|
windowMs: USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
1028
1008
|
bucketCount: USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
1029
|
-
alignToBucket: true
|
|
1009
|
+
alignToBucket: true
|
|
1030
1010
|
});
|
|
1031
|
-
const openCodeCoverage = history.coverage.find(entry => entry.provider ===
|
|
1032
|
-
const qoderCoverage = history.coverage.find(entry => entry.provider ===
|
|
1033
|
-
|
|
1011
|
+
const openCodeCoverage = history.coverage.find((entry) => entry.provider === "opencode");
|
|
1012
|
+
const qoderCoverage = history.coverage.find((entry) => entry.provider === "qoder");
|
|
1034
1013
|
return {
|
|
1035
1014
|
sampledAt: now,
|
|
1036
1015
|
windowMs,
|
|
@@ -1039,89 +1018,83 @@ class UsageMonitor {
|
|
|
1039
1018
|
daily: history.daily,
|
|
1040
1019
|
providers: [
|
|
1041
1020
|
{
|
|
1042
|
-
provider:
|
|
1043
|
-
providerName:
|
|
1021
|
+
provider: "codex",
|
|
1022
|
+
providerName: "Codex",
|
|
1044
1023
|
auth: codexAuth,
|
|
1045
1024
|
quota: codexUsage.quota,
|
|
1046
|
-
tokenUsage: codexUsage.tokenUsage
|
|
1025
|
+
tokenUsage: codexUsage.tokenUsage
|
|
1047
1026
|
},
|
|
1048
1027
|
{
|
|
1049
|
-
provider:
|
|
1050
|
-
providerName:
|
|
1028
|
+
provider: "claude",
|
|
1029
|
+
providerName: "Claude",
|
|
1051
1030
|
auth: claudeAuth,
|
|
1052
1031
|
quota: claudeUsage.quota,
|
|
1053
|
-
tokenUsage: claudeUsage.tokenUsage
|
|
1032
|
+
tokenUsage: claudeUsage.tokenUsage
|
|
1054
1033
|
},
|
|
1055
1034
|
{
|
|
1056
|
-
provider:
|
|
1057
|
-
providerName:
|
|
1035
|
+
provider: "opencode",
|
|
1036
|
+
providerName: "OpenCode",
|
|
1058
1037
|
auth: {
|
|
1059
1038
|
available: openCodeCoverage?.available === true,
|
|
1060
|
-
status: openCodeCoverage?.available === true
|
|
1061
|
-
|
|
1062
|
-
: openCodeCoverage?.reason || 'OpenCode unavailable',
|
|
1063
|
-
source: 'opencode session export',
|
|
1039
|
+
status: openCodeCoverage?.available === true ? "Local session export" : openCodeCoverage?.reason || "OpenCode unavailable",
|
|
1040
|
+
source: "opencode session export"
|
|
1064
1041
|
},
|
|
1065
1042
|
quota: {
|
|
1066
1043
|
available: false,
|
|
1067
|
-
source:
|
|
1068
|
-
reason:
|
|
1044
|
+
source: "opencode session export",
|
|
1045
|
+
reason: "OpenCode session exports do not expose quota remaining."
|
|
1069
1046
|
},
|
|
1070
|
-
tokenUsage: openCodeCoverage?.available === true
|
|
1071
|
-
|
|
1072
|
-
:
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
reason: openCodeCoverage?.reason || 'OpenCode token usage is unavailable.',
|
|
1076
|
-
},
|
|
1047
|
+
tokenUsage: openCodeCoverage?.available === true ? openCodeUsage.tokenUsage : {
|
|
1048
|
+
...openCodeUsage.tokenUsage,
|
|
1049
|
+
available: false,
|
|
1050
|
+
reason: openCodeCoverage?.reason || "OpenCode token usage is unavailable."
|
|
1051
|
+
}
|
|
1077
1052
|
},
|
|
1078
1053
|
{
|
|
1079
|
-
provider:
|
|
1080
|
-
providerName:
|
|
1081
|
-
auth: { available: true, status:
|
|
1054
|
+
provider: "qoder",
|
|
1055
|
+
providerName: "Qoder",
|
|
1056
|
+
auth: { available: true, status: "Local sessions", source: "Qoder session files" },
|
|
1082
1057
|
quota: {
|
|
1083
1058
|
available: false,
|
|
1084
|
-
source:
|
|
1085
|
-
reason: qoderCoverage?.reason ||
|
|
1059
|
+
source: "Qoder session files",
|
|
1060
|
+
reason: qoderCoverage?.reason || "Qoder quota telemetry is unavailable."
|
|
1086
1061
|
},
|
|
1087
1062
|
tokenUsage: {
|
|
1088
1063
|
available: false,
|
|
1089
1064
|
windowMs,
|
|
1090
|
-
source:
|
|
1065
|
+
source: "Qoder session files",
|
|
1091
1066
|
totalTokens: null,
|
|
1092
1067
|
tokensPerMinute: null,
|
|
1093
1068
|
eventCount: 0,
|
|
1094
1069
|
sampledAt: now,
|
|
1095
|
-
reason: qoderCoverage?.reason ||
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1070
|
+
reason: qoderCoverage?.reason || "Qoder session files do not expose model token usage."
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1098
1073
|
],
|
|
1099
|
-
agentUsage: this.agentManager?.getAgentUsageSnapshots
|
|
1100
|
-
|
|
1101
|
-
: null,
|
|
1102
|
-
systemStats,
|
|
1074
|
+
agentUsage: this.agentManager?.getAgentUsageSnapshots ? this.agentManager.getAgentUsageSnapshots({ now, windowMs }) : null,
|
|
1075
|
+
systemStats
|
|
1103
1076
|
};
|
|
1104
1077
|
}
|
|
1105
1078
|
}
|
|
1106
|
-
|
|
1107
|
-
module.exports = {
|
|
1108
|
-
USAGE_WINDOW_MS,
|
|
1109
|
-
USAGE_TIMELINE_WINDOW_MS,
|
|
1110
|
-
USAGE_TIMELINE_BUCKET_COUNT,
|
|
1111
|
-
USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
1112
|
-
USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
1113
|
-
USAGE_DAILY_DAYS,
|
|
1079
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1080
|
+
0 && (module.exports = {
|
|
1114
1081
|
USAGE_DAILY_CACHE_MS,
|
|
1082
|
+
USAGE_DAILY_DAYS,
|
|
1115
1083
|
USAGE_LIVE_DAY_CACHE_MS,
|
|
1084
|
+
USAGE_LIVE_TIMELINE_BUCKET_COUNT,
|
|
1085
|
+
USAGE_LIVE_TIMELINE_WINDOW_MS,
|
|
1086
|
+
USAGE_TIMELINE_BUCKET_COUNT,
|
|
1087
|
+
USAGE_TIMELINE_WINDOW_MS,
|
|
1088
|
+
USAGE_WINDOW_MS,
|
|
1116
1089
|
UsageMonitor,
|
|
1117
|
-
buildUsageTimeline,
|
|
1118
1090
|
buildDailyUsage,
|
|
1119
1091
|
buildUsageDayDetail,
|
|
1120
|
-
|
|
1092
|
+
buildUsageTimeline,
|
|
1121
1093
|
collectClaudeUsage,
|
|
1122
1094
|
collectCodexUsage,
|
|
1095
|
+
collectDailyUsage,
|
|
1123
1096
|
collectOpenCodeDailyEvents,
|
|
1124
1097
|
openCodeTokenEventsFromExport,
|
|
1125
1098
|
readClaudeAuthStatus,
|
|
1126
|
-
readCodexAuthStatus
|
|
1127
|
-
};
|
|
1099
|
+
readCodexAuthStatus
|
|
1100
|
+
});
|