quotacap 0.0.20 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -24
- package/dist/adapters/agy.d.ts +3 -0
- package/dist/adapters/agy.js +81 -0
- package/dist/adapters/claude.d.ts +7 -5
- package/dist/adapters/claude.js +6 -6
- package/dist/adapters/codex.d.ts +3 -3
- package/dist/adapters/codex.js +128 -49
- package/dist/adapters/grok.d.ts +3 -3
- package/dist/adapters/grok.js +114 -70
- package/dist/adapters/index.d.ts +5 -2
- package/dist/adapters/index.js +36 -9
- package/dist/adapters/kimi.d.ts +3 -3
- package/dist/adapters/kimi.js +64 -86
- package/dist/adapters/manual.d.ts +4 -4
- package/dist/adapters/manual.js +2 -2
- package/dist/adapters/pty.d.ts +41 -0
- package/dist/adapters/pty.js +579 -0
- package/dist/adapters/types.d.ts +7 -3
- package/dist/advisory/engine.d.ts +19 -2
- package/dist/advisory/engine.js +130 -10
- package/dist/advisory/snapshot.d.ts +22 -0
- package/dist/advisory/snapshot.js +213 -0
- package/dist/advisory/types.d.ts +53 -4
- package/dist/advisory/validate.d.ts +5 -0
- package/dist/advisory/validate.js +18 -0
- package/dist/cli/advise.d.ts +3 -0
- package/dist/cli/advise.js +128 -0
- package/dist/cli/clients.d.ts +28 -0
- package/dist/cli/clients.js +11 -0
- package/dist/cli/index.js +16 -91
- package/dist/cli/ingest.d.ts +3 -0
- package/dist/cli/ingest.js +31 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +29 -0
- package/dist/cli/runtime.d.ts +33 -0
- package/dist/cli/runtime.js +252 -0
- package/dist/cli/snapshot-source.d.ts +26 -0
- package/dist/cli/snapshot-source.js +232 -0
- package/dist/cli/status.d.ts +3 -0
- package/dist/cli/status.js +150 -0
- package/dist/cli/takeover.d.ts +64 -0
- package/dist/cli/takeover.js +175 -0
- package/dist/cli/update.d.ts +61 -0
- package/dist/cli/update.js +392 -0
- package/dist/config.d.ts +27 -0
- package/dist/config.js +154 -1
- package/dist/daemon.d.ts +4 -29
- package/dist/daemon.js +12 -67
- package/dist/format/markdown.d.ts +3 -0
- package/dist/format/markdown.js +24 -0
- package/dist/format/rows.d.ts +27 -0
- package/dist/format/rows.js +241 -0
- package/dist/format/terminal.d.ts +12 -0
- package/dist/format/terminal.js +144 -0
- package/dist/http/server.d.ts +32 -3
- package/dist/http/server.js +276 -106
- package/dist/mcp/server.d.ts +0 -6
- package/dist/mcp/server.js +78 -25
- package/dist/runtime/client.d.ts +24 -0
- package/dist/runtime/client.js +72 -0
- package/dist/runtime/owner.d.ts +35 -0
- package/dist/runtime/owner.js +393 -0
- package/dist/runtime/poll.d.ts +50 -0
- package/dist/runtime/poll.js +229 -0
- package/dist/runtime/service.d.ts +24 -0
- package/dist/runtime/service.js +268 -0
- package/dist/runtime/spawn.d.ts +17 -0
- package/dist/runtime/spawn.js +97 -0
- package/dist/runtime/token.d.ts +3 -0
- package/dist/runtime/token.js +64 -0
- package/dist/runtime/updates.d.ts +74 -0
- package/dist/runtime/updates.js +445 -0
- package/dist/runtime/versions.d.ts +2 -0
- package/dist/runtime/versions.js +26 -0
- package/dist/service/index.d.ts +9 -0
- package/dist/service/index.js +103 -0
- package/dist/service/macos.d.ts +100 -0
- package/dist/service/macos.js +602 -0
- package/dist/service/systemd.d.ts +40 -0
- package/dist/service/systemd.js +387 -0
- package/dist/src/adapters/agy.d.ts +3 -0
- package/dist/src/adapters/agy.js +81 -0
- package/dist/src/adapters/claude.d.ts +7 -5
- package/dist/src/adapters/claude.js +6 -6
- package/dist/src/adapters/codex.d.ts +3 -3
- package/dist/src/adapters/codex.js +128 -49
- package/dist/src/adapters/grok.d.ts +3 -3
- package/dist/src/adapters/grok.js +114 -70
- package/dist/src/adapters/index.d.ts +5 -2
- package/dist/src/adapters/index.js +36 -9
- package/dist/src/adapters/kimi.d.ts +3 -3
- package/dist/src/adapters/kimi.js +64 -86
- package/dist/src/adapters/manual.d.ts +4 -4
- package/dist/src/adapters/manual.js +2 -2
- package/dist/src/adapters/pty.d.ts +41 -0
- package/dist/src/adapters/pty.js +579 -0
- package/dist/src/adapters/types.d.ts +7 -3
- package/dist/src/advisory/engine.d.ts +19 -2
- package/dist/src/advisory/engine.js +130 -10
- package/dist/src/advisory/snapshot.d.ts +22 -0
- package/dist/src/advisory/snapshot.js +213 -0
- package/dist/src/advisory/types.d.ts +53 -4
- package/dist/src/advisory/validate.d.ts +5 -0
- package/dist/src/advisory/validate.js +18 -0
- package/dist/src/cli/advise.d.ts +3 -0
- package/dist/src/cli/advise.js +128 -0
- package/dist/src/cli/clients.d.ts +28 -0
- package/dist/src/cli/clients.js +11 -0
- package/dist/src/cli/index.js +16 -91
- package/dist/src/cli/ingest.d.ts +3 -0
- package/dist/src/cli/ingest.js +31 -0
- package/dist/src/cli/init.d.ts +2 -0
- package/dist/src/cli/init.js +29 -0
- package/dist/src/cli/runtime.d.ts +33 -0
- package/dist/src/cli/runtime.js +252 -0
- package/dist/src/cli/snapshot-source.d.ts +26 -0
- package/dist/src/cli/snapshot-source.js +232 -0
- package/dist/src/cli/status.d.ts +3 -0
- package/dist/src/cli/status.js +150 -0
- package/dist/src/cli/takeover.d.ts +64 -0
- package/dist/src/cli/takeover.js +175 -0
- package/dist/src/cli/update.d.ts +61 -0
- package/dist/src/cli/update.js +392 -0
- package/dist/src/config.d.ts +27 -0
- package/dist/src/config.js +154 -1
- package/dist/src/daemon.d.ts +4 -29
- package/dist/src/daemon.js +12 -67
- package/dist/src/format/markdown.d.ts +3 -0
- package/dist/src/format/markdown.js +24 -0
- package/dist/src/format/rows.d.ts +27 -0
- package/dist/src/format/rows.js +241 -0
- package/dist/src/format/terminal.d.ts +12 -0
- package/dist/src/format/terminal.js +144 -0
- package/dist/src/http/server.d.ts +32 -3
- package/dist/src/http/server.js +276 -106
- package/dist/src/mcp/server.d.ts +0 -6
- package/dist/src/mcp/server.js +78 -25
- package/dist/src/runtime/client.d.ts +24 -0
- package/dist/src/runtime/client.js +72 -0
- package/dist/src/runtime/owner.d.ts +35 -0
- package/dist/src/runtime/owner.js +393 -0
- package/dist/src/runtime/poll.d.ts +50 -0
- package/dist/src/runtime/poll.js +229 -0
- package/dist/src/runtime/service.d.ts +24 -0
- package/dist/src/runtime/service.js +268 -0
- package/dist/src/runtime/spawn.d.ts +17 -0
- package/dist/src/runtime/spawn.js +97 -0
- package/dist/src/runtime/token.d.ts +3 -0
- package/dist/src/runtime/token.js +64 -0
- package/dist/src/runtime/updates.d.ts +74 -0
- package/dist/src/runtime/updates.js +445 -0
- package/dist/src/runtime/versions.d.ts +2 -0
- package/dist/src/runtime/versions.js +26 -0
- package/dist/src/service/index.d.ts +9 -0
- package/dist/src/service/index.js +103 -0
- package/dist/src/service/macos.d.ts +100 -0
- package/dist/src/service/macos.js +602 -0
- package/dist/src/service/systemd.d.ts +40 -0
- package/dist/src/service/systemd.js +387 -0
- package/dist/src/store/attempts.d.ts +12 -0
- package/dist/src/store/attempts.js +29 -0
- package/dist/src/store/db.d.ts +1 -1
- package/dist/src/store/db.js +58 -2
- package/dist/src/store/quotas.js +52 -10
- package/dist/src/version.js +1 -1
- package/dist/src/webAssets.js +1 -1
- package/dist/src/webHtml.js +1 -1
- package/dist/store/attempts.d.ts +12 -0
- package/dist/store/attempts.js +29 -0
- package/dist/store/db.d.ts +1 -1
- package/dist/store/db.js +58 -2
- package/dist/store/quotas.js +52 -10
- package/dist/tests/adapters/agy.test.js +337 -0
- package/dist/tests/adapters/claude.test.js +41 -1
- package/dist/tests/adapters/codex.test.js +231 -91
- package/dist/tests/adapters/credential-free.test.js +211 -0
- package/dist/tests/adapters/grok.test.js +249 -135
- package/dist/tests/adapters/kimi.test.js +219 -104
- package/dist/tests/adapters/pty-perms.test.d.ts +1 -0
- package/dist/tests/adapters/pty-perms.test.js +78 -0
- package/dist/tests/adapters/pty.test.d.ts +1 -0
- package/dist/tests/adapters/pty.test.js +240 -0
- package/dist/tests/adapters/registry.test.js +5 -5
- package/dist/tests/advisory/engine.test.js +194 -6
- package/dist/tests/advisory/pace.test.d.ts +1 -0
- package/dist/tests/advisory/pace.test.js +60 -0
- package/dist/tests/advisory/snapshot.test.d.ts +1 -0
- package/dist/tests/advisory/snapshot.test.js +65 -0
- package/dist/tests/advisory/validate.test.d.ts +1 -0
- package/dist/tests/advisory/validate.test.js +19 -0
- package/dist/tests/cli/advise.test.d.ts +1 -0
- package/dist/tests/cli/advise.test.js +367 -0
- package/dist/tests/cli/cli.test.js +39 -19
- package/dist/tests/cli/helpers.d.ts +9 -0
- package/dist/tests/cli/helpers.js +93 -0
- package/dist/tests/cli/ingest.test.d.ts +1 -0
- package/dist/tests/cli/ingest.test.js +188 -0
- package/dist/tests/cli/init.test.d.ts +1 -0
- package/dist/tests/cli/init.test.js +55 -0
- package/dist/tests/cli/launcher.test.d.ts +1 -0
- package/dist/tests/cli/launcher.test.js +271 -0
- package/dist/tests/cli/parity.test.d.ts +1 -0
- package/dist/tests/cli/parity.test.js +225 -0
- package/dist/tests/cli/snapshot-source.test.d.ts +1 -0
- package/dist/tests/cli/snapshot-source.test.js +305 -0
- package/dist/tests/cli/status.test.d.ts +1 -0
- package/dist/tests/cli/status.test.js +536 -0
- package/dist/tests/cli/takeover.test.d.ts +1 -0
- package/dist/tests/cli/takeover.test.js +325 -0
- package/dist/tests/cli/update.test.d.ts +1 -0
- package/dist/tests/cli/update.test.js +382 -0
- package/dist/tests/daemon.test.js +140 -38
- package/dist/tests/fixtures/stable-state.d.ts +22 -0
- package/dist/tests/fixtures/stable-state.js +152 -0
- package/dist/tests/fixtures/stable-state.test.d.ts +1 -0
- package/dist/tests/fixtures/stable-state.test.js +17 -0
- package/dist/tests/format/markdown.test.d.ts +1 -0
- package/dist/tests/format/markdown.test.js +49 -0
- package/dist/tests/format/terminal.test.d.ts +1 -0
- package/dist/tests/format/terminal.test.js +476 -0
- package/dist/tests/http/api.test.js +224 -2
- package/dist/tests/integration.test.js +20 -7
- package/dist/tests/mcp/protocol.test.d.ts +1 -0
- package/dist/tests/mcp/protocol.test.js +134 -0
- package/dist/tests/mcp/quotas.test.js +38 -6
- package/dist/tests/mcp/tools.test.d.ts +1 -0
- package/dist/tests/mcp/tools.test.js +291 -0
- package/dist/tests/runtime/cancel.test.d.ts +1 -0
- package/dist/tests/runtime/cancel.test.js +264 -0
- package/dist/tests/runtime/cli.test.d.ts +1 -0
- package/dist/tests/runtime/cli.test.js +426 -0
- package/dist/tests/runtime/config.test.d.ts +1 -0
- package/dist/tests/runtime/config.test.js +144 -0
- package/dist/tests/runtime/http.test.d.ts +1 -0
- package/dist/tests/runtime/http.test.js +346 -0
- package/dist/tests/runtime/lifecycle.test.d.ts +1 -0
- package/dist/tests/runtime/lifecycle.test.js +303 -0
- package/dist/tests/runtime/ownership.test.d.ts +1 -0
- package/dist/tests/runtime/ownership.test.js +355 -0
- package/dist/tests/runtime/poll.test.d.ts +1 -0
- package/dist/tests/runtime/poll.test.js +438 -0
- package/dist/tests/runtime/status.test.d.ts +1 -0
- package/dist/tests/runtime/status.test.js +232 -0
- package/dist/tests/runtime/updates.test.d.ts +1 -0
- package/dist/tests/runtime/updates.test.js +509 -0
- package/dist/tests/service/macos.test.d.ts +1 -0
- package/dist/tests/service/macos.test.js +450 -0
- package/dist/tests/service/systemd.test.d.ts +1 -0
- package/dist/tests/service/systemd.test.js +330 -0
- package/dist/tests/smoke/dashboard.e2e.d.ts +1 -0
- package/dist/tests/smoke/dashboard.e2e.js +142 -0
- package/dist/tests/smoke/playwright.config.d.ts +2 -0
- package/dist/tests/smoke/playwright.config.js +11 -0
- package/dist/tests/store/attempts.test.d.ts +1 -0
- package/dist/tests/store/attempts.test.js +29 -0
- package/dist/tests/store/db.test.js +61 -6
- package/dist/tests/store/migration.test.d.ts +1 -0
- package/dist/tests/store/migration.test.js +41 -0
- package/dist/tests/web/advice-drawer.test.d.ts +1 -0
- package/dist/tests/web/advice-drawer.test.js +45 -0
- package/dist/tests/web/dashboard.e2e.d.ts +1 -0
- package/dist/tests/web/dashboard.e2e.js +670 -0
- package/dist/tests/web/header.test.d.ts +1 -0
- package/dist/tests/web/header.test.js +82 -0
- package/dist/tests/web/names.test.d.ts +1 -0
- package/dist/tests/web/names.test.js +19 -0
- package/dist/tests/web/onboarding.test.d.ts +1 -0
- package/dist/tests/web/onboarding.test.js +21 -0
- package/dist/tests/web/pacing.test.d.ts +1 -0
- package/dist/tests/web/pacing.test.js +62 -0
- package/dist/tests/web/playwright.config.d.ts +2 -0
- package/dist/tests/web/playwright.config.js +10 -0
- package/dist/tests/web/provider-drawer.test.d.ts +1 -0
- package/dist/tests/web/provider-drawer.test.js +68 -0
- package/dist/tests/web/recommendation.test.d.ts +1 -0
- package/dist/tests/web/recommendation.test.js +38 -0
- package/dist/tests/web/reset-rail.test.d.ts +1 -0
- package/dist/tests/web/reset-rail.test.js +63 -0
- package/dist/tests/web/responsive.test.d.ts +1 -0
- package/dist/tests/web/responsive.test.js +21 -0
- package/dist/tests/web/settings.test.d.ts +1 -0
- package/dist/tests/web/settings.test.js +32 -0
- package/dist/tests/web/state-catalog.test.d.ts +1 -0
- package/dist/tests/web/state-catalog.test.js +206 -0
- package/dist/tests/web/state.test.d.ts +1 -0
- package/dist/tests/web/state.test.js +27 -0
- package/dist/tests/web/stub-server.d.ts +37 -0
- package/dist/tests/web/stub-server.js +132 -0
- package/dist/tests/web/theme.test.d.ts +1 -0
- package/dist/tests/web/theme.test.js +12 -0
- package/dist/version.js +1 -1
- package/dist/web/src/App.d.ts +1 -0
- package/dist/web/src/App.js +106 -78
- package/dist/web/src/Theme.d.ts +11 -0
- package/dist/web/src/Theme.js +53 -0
- package/dist/web/src/api.d.ts +27 -2
- package/dist/web/src/api.js +102 -6
- package/dist/web/src/components/AdviceDrawer.d.ts +9 -0
- package/dist/web/src/components/AdviceDrawer.js +77 -0
- package/dist/web/src/components/FaultBanner.d.ts +17 -0
- package/dist/web/src/components/FaultBanner.js +60 -0
- package/dist/web/src/components/Header.d.ts +22 -0
- package/dist/web/src/components/Header.js +50 -0
- package/dist/web/src/components/PaceBar.d.ts +51 -0
- package/dist/web/src/components/PaceBar.js +251 -0
- package/dist/web/src/components/PacingLegend.d.ts +3 -0
- package/dist/web/src/components/PacingLegend.js +43 -0
- package/dist/web/src/components/ProviderCard.d.ts +8 -0
- package/dist/web/src/components/ProviderCard.js +27 -0
- package/dist/web/src/components/ProviderDrawer.d.ts +52 -0
- package/dist/web/src/components/ProviderDrawer.js +270 -0
- package/dist/web/src/components/ProviderIcon.d.ts +7 -0
- package/dist/web/src/components/ProviderIcon.js +27 -0
- package/dist/web/src/components/ProviderRow.d.ts +8 -0
- package/dist/web/src/components/ProviderRow.js +14 -0
- package/dist/web/src/components/Recommendation.d.ts +27 -0
- package/dist/web/src/components/Recommendation.js +77 -0
- package/dist/web/src/components/ResetRail.d.ts +38 -0
- package/dist/web/src/components/ResetRail.js +188 -0
- package/dist/web/src/components/SubscriptionList.d.ts +19 -0
- package/dist/web/src/components/SubscriptionList.js +107 -0
- package/dist/web/src/components/settings/CliIntegrationPanel.d.ts +2 -0
- package/dist/web/src/components/settings/CliIntegrationPanel.js +49 -0
- package/dist/web/src/components/settings/DaemonPanel.d.ts +6 -0
- package/dist/web/src/components/settings/DaemonPanel.js +45 -0
- package/dist/web/src/components/settings/ProvidersPanel.d.ts +14 -0
- package/dist/web/src/components/settings/ProvidersPanel.js +69 -0
- package/dist/web/src/components/settings/SettingsDrawer.d.ts +9 -0
- package/dist/web/src/components/settings/SettingsDrawer.js +55 -0
- package/dist/web/src/names.d.ts +3 -0
- package/dist/web/src/names.js +19 -0
- package/dist/web/src/pages/Onboarding.d.ts +17 -0
- package/dist/web/src/pages/Onboarding.js +96 -0
- package/dist/web/src/router.d.ts +11 -0
- package/dist/web/src/router.js +31 -0
- package/dist/web/src/state.d.ts +104 -0
- package/dist/web/src/state.js +80 -0
- package/dist/webAssets.js +1 -1
- package/dist/webHtml.js +1 -1
- package/package.json +27 -9
- package/web/dist/assets/index-BEBqgvq8.css +1 -0
- package/web/dist/assets/index-DZfttQgo.js +12 -0
- package/web/dist/index.html +19 -2
- package/dist/adapters/core.d.ts +0 -9
- package/dist/adapters/core.js +0 -90
- package/dist/format/table.d.ts +0 -2
- package/dist/format/table.js +0 -56
- package/dist/src/adapters/core.d.ts +0 -9
- package/dist/src/adapters/core.js +0 -90
- package/dist/src/format/table.d.ts +0 -2
- package/dist/src/format/table.js +0 -56
- package/dist/tests/adapters/core.test.js +0 -110
- package/dist/tests/format/table.test.js +0 -98
- package/web/dist/assets/index-Dpiqzcc8.js +0 -40
- /package/dist/tests/adapters/{core.test.d.ts → agy.test.d.ts} +0 -0
- /package/dist/tests/{format/table.test.d.ts → adapters/credential-free.test.d.ts} +0 -0
package/dist/adapters/grok.js
CHANGED
|
@@ -1,82 +1,126 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
import { runPty, stripAnsi } from "./pty.js";
|
|
3
|
+
import { adapterSignal } from "../runtime/spawn.js";
|
|
4
|
+
const FULL_MONTHS = {
|
|
5
|
+
january: 0, february: 1, march: 2, april: 3, may: 4, june: 5,
|
|
6
|
+
july: 6, august: 7, september: 8, october: 9, november: 10, december: 11,
|
|
7
|
+
};
|
|
8
|
+
const ABBR_MONTHS = {
|
|
9
|
+
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,
|
|
10
|
+
jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11,
|
|
11
|
+
};
|
|
12
|
+
function parseGrokReset(raw, now) {
|
|
13
|
+
const m = raw.trim().match(/^([A-Za-z]+)\s+(\d{1,2}),\s*(\d{1,2}):(\d{2})$/);
|
|
14
|
+
if (!m)
|
|
15
|
+
return null;
|
|
16
|
+
const monStr = m[1].toLowerCase();
|
|
17
|
+
const day = parseInt(m[2], 10);
|
|
18
|
+
const hours = parseInt(m[3], 10);
|
|
19
|
+
const mins = parseInt(m[4], 10);
|
|
20
|
+
let month = FULL_MONTHS[monStr];
|
|
21
|
+
if (month === undefined)
|
|
22
|
+
month = ABBR_MONTHS[monStr.slice(0, 3)];
|
|
23
|
+
if (month === undefined || !Number.isFinite(day) || !Number.isFinite(hours) || !Number.isFinite(mins))
|
|
24
|
+
return null;
|
|
25
|
+
if (day < 1 || day > 31 || hours < 0 || hours > 23 || mins < 0 || mins > 59)
|
|
26
|
+
return null;
|
|
27
|
+
let year = now.getFullYear();
|
|
28
|
+
let dt = new Date(year, month, day, hours, mins, 0, 0);
|
|
29
|
+
if (Number.isNaN(dt.getTime()))
|
|
30
|
+
return null;
|
|
31
|
+
if (dt.getTime() < now.getTime()) {
|
|
32
|
+
dt = new Date(year + 1, month, day, hours, mins, 0, 0);
|
|
33
|
+
if (Number.isNaN(dt.getTime()))
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return dt.toISOString();
|
|
37
|
+
}
|
|
38
|
+
export function parseGrokTui(text, now = new Date()) {
|
|
39
|
+
const cleaned = stripAnsi(text);
|
|
40
|
+
const planMatch = cleaned.match(/Weekly lim[i!l]t\s*\(([^)]+)\)/i);
|
|
41
|
+
let plan = "unknown";
|
|
42
|
+
if (planMatch) {
|
|
43
|
+
plan = planMatch[1].trim();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const tier = cleaned.match(/\b(SuperGrok|Grok\s+Pro|Grok\s+Enterprise|Grok\s+Basic)\b/i);
|
|
47
|
+
if (tier)
|
|
48
|
+
plan = tier[1].trim();
|
|
49
|
+
}
|
|
50
|
+
const pctRe = /Weekly lim[i!l]t[^\n%]*?(\d+)%/i;
|
|
51
|
+
const mPct = cleaned.match(pctRe);
|
|
52
|
+
let usedPct = null;
|
|
53
|
+
if (mPct) {
|
|
54
|
+
const v = parseInt(mPct[1], 10);
|
|
55
|
+
if (Number.isFinite(v) && v >= 0 && v <= 100)
|
|
56
|
+
usedPct = v;
|
|
57
|
+
}
|
|
58
|
+
if (usedPct === null) {
|
|
59
|
+
const barRe = /[█░▓▓]+\s*(\d+)%/;
|
|
60
|
+
const b = cleaned.match(barRe);
|
|
61
|
+
if (b) {
|
|
62
|
+
const v = parseInt(b[1], 10);
|
|
63
|
+
if (Number.isFinite(v) && v >= 0 && v <= 100)
|
|
64
|
+
usedPct = v;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (usedPct === null)
|
|
68
|
+
throw new Error("grok: weekly percent not found in TUI output");
|
|
69
|
+
let creditsUsd;
|
|
70
|
+
const mCred = cleaned.match(/Credits:\s*\$([0-9]+(?:\.[0-9]+)?)/i);
|
|
71
|
+
if (mCred) {
|
|
72
|
+
const v = parseFloat(mCred[1]);
|
|
73
|
+
if (Number.isFinite(v) && v >= 0)
|
|
74
|
+
creditsUsd = v;
|
|
75
|
+
}
|
|
76
|
+
const mReset = cleaned.match(/Resets:\s*([A-Za-z]+\s+\d+,\s*\d+:\d+)/i);
|
|
77
|
+
let resetsAt = null;
|
|
78
|
+
let estimated = false;
|
|
79
|
+
if (mReset) {
|
|
80
|
+
const resetsRaw = mReset[1].trim();
|
|
81
|
+
resetsAt = parseGrokReset(resetsRaw, now);
|
|
82
|
+
if (!resetsAt)
|
|
83
|
+
throw new Error(`grok: bad resets timestamp "${resetsRaw}"`);
|
|
84
|
+
}
|
|
85
|
+
else if (cleaned.match(/Resets:/i)) {
|
|
86
|
+
throw new Error("grok: bad resets timestamp");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
resetsAt = new Date(now.getTime() + 7 * 86400000).toISOString();
|
|
90
|
+
estimated = true;
|
|
91
|
+
}
|
|
92
|
+
const periodStart = new Date(new Date(resetsAt).getTime() - 7 * 86400000).toISOString();
|
|
15
93
|
return {
|
|
16
94
|
provider: "grok",
|
|
17
|
-
plan
|
|
18
|
-
usedPct
|
|
19
|
-
resetsAt
|
|
20
|
-
periodStart
|
|
21
|
-
|
|
22
|
-
source: "api",
|
|
95
|
+
plan,
|
|
96
|
+
usedPct,
|
|
97
|
+
resetsAt,
|
|
98
|
+
periodStart,
|
|
99
|
+
source: "tui",
|
|
23
100
|
fetchedAt: now.toISOString(),
|
|
101
|
+
creditsUsd,
|
|
102
|
+
resetsAtEstimated: estimated || undefined,
|
|
103
|
+
raw: cleaned.slice(0, 4096),
|
|
24
104
|
};
|
|
25
105
|
}
|
|
26
|
-
function grokHome() {
|
|
27
|
-
return process.env.GROK_HOME ?? path.join(os.homedir(), ".grok");
|
|
28
|
-
}
|
|
29
|
-
async function loadEntry() {
|
|
30
|
-
const file = path.join(grokHome(), "auth.json");
|
|
31
|
-
const auth = await readJsonFile(file);
|
|
32
|
-
for (const [entryKey, entry] of Object.entries(auth)) {
|
|
33
|
-
if (entry.refresh_token)
|
|
34
|
-
return { file, entryKey, entry };
|
|
35
|
-
}
|
|
36
|
-
throw new Error("grok: no refresh_token in auth.json — run `grok login`");
|
|
37
|
-
}
|
|
38
106
|
export const grokAdapter = {
|
|
39
107
|
id: "grok",
|
|
40
|
-
requiresAuth: "
|
|
108
|
+
requiresAuth: "grok login (CLI owns credentials)",
|
|
41
109
|
async poll() {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!tok.access_token)
|
|
56
|
-
throw new Error("grok: refresh returned no access_token");
|
|
57
|
-
await persistCreds(file, (cur) => {
|
|
58
|
-
const next = { ...cur };
|
|
59
|
-
const target = next[entryKey];
|
|
60
|
-
if (target) {
|
|
61
|
-
next[entryKey] = {
|
|
62
|
-
...target,
|
|
63
|
-
key: tok.access_token ?? target.key,
|
|
64
|
-
refresh_token: tok.refresh_token ?? target.refresh_token,
|
|
65
|
-
expires_at: tok.expires_at ??
|
|
66
|
-
(tok.expires_in ? new Date(Date.now() + Number(tok.expires_in) * 1000).toISOString() : target.expires_at),
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
return next;
|
|
70
|
-
});
|
|
71
|
-
token = String(tok.access_token);
|
|
72
|
-
}
|
|
73
|
-
const body = await getJson(BILLING_URL, {
|
|
74
|
-
Authorization: `Bearer ${token}`,
|
|
75
|
-
Accept: "application/json",
|
|
76
|
-
"x-grok-client-version": CLIENT_VERSION,
|
|
77
|
-
"x-grok-client-surface": "grok-build",
|
|
78
|
-
"X-XAI-Token-Auth": "xai-grok-cli",
|
|
110
|
+
const transcript = await runPty({
|
|
111
|
+
file: "grok",
|
|
112
|
+
args: [],
|
|
113
|
+
cwd: os.homedir(),
|
|
114
|
+
cols: 140,
|
|
115
|
+
rows: 50,
|
|
116
|
+
settleDelayMs: 5000,
|
|
117
|
+
input: "/usage\r",
|
|
118
|
+
completionRegex: /Weekly lim|Credits:/i,
|
|
119
|
+
timeoutMs: 14000,
|
|
120
|
+
maxBytes: 256 * 1024,
|
|
121
|
+
signal: adapterSignal("grok"),
|
|
122
|
+
label: "grok",
|
|
79
123
|
});
|
|
80
|
-
return
|
|
124
|
+
return parseGrokTui(transcript);
|
|
81
125
|
},
|
|
82
126
|
};
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { Adapter } from "./types.js";
|
|
2
2
|
export declare const adapters: Record<string, Adapter>;
|
|
3
|
-
export
|
|
3
|
+
export interface PollAllOptions {
|
|
4
|
+
timeouts?: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export declare function pollAll(enabled: string[], opts?: PollAllOptions): Promise<({
|
|
4
7
|
provider: string;
|
|
5
8
|
status: "fulfilled";
|
|
6
|
-
value:
|
|
9
|
+
value: unknown;
|
|
7
10
|
reason?: undefined;
|
|
8
11
|
} | {
|
|
9
12
|
provider: string;
|
package/dist/adapters/index.js
CHANGED
|
@@ -3,28 +3,55 @@ import { manualAdapter } from "./manual.js";
|
|
|
3
3
|
import { codexAdapter } from "./codex.js";
|
|
4
4
|
import { kimiAdapter } from "./kimi.js";
|
|
5
5
|
import { grokAdapter } from "./grok.js";
|
|
6
|
+
import { agyAdapter } from "./agy.js";
|
|
7
|
+
import { installAdapterSignal, clearAdapterSignal } from "../runtime/spawn.js";
|
|
6
8
|
export const adapters = {
|
|
7
9
|
claude: claudeAdapter,
|
|
8
10
|
manual: manualAdapter,
|
|
9
11
|
codex: codexAdapter,
|
|
10
12
|
kimi: kimiAdapter,
|
|
11
13
|
grok: grokAdapter,
|
|
14
|
+
agy: agyAdapter,
|
|
12
15
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const ADAPTER_TIMEOUTS = {
|
|
17
|
+
claude: 8000,
|
|
18
|
+
codex: 12000,
|
|
19
|
+
kimi: 8000,
|
|
20
|
+
grok: 14000,
|
|
21
|
+
agy: 20000,
|
|
22
|
+
};
|
|
23
|
+
export async function pollAll(enabled, opts) {
|
|
20
24
|
const rawJobs = enabled.map(id => {
|
|
21
25
|
const a = adapters[id];
|
|
22
26
|
if (!a)
|
|
23
27
|
return Promise.reject(new Error(`unknown adapter ${id}`));
|
|
24
28
|
// manual adapter has no poll capability — skip without degraded
|
|
25
29
|
if (id === "manual")
|
|
26
|
-
return Promise.reject(new Error("manual skipped
|
|
27
|
-
|
|
30
|
+
return Promise.reject(new Error("manual skipped"));
|
|
31
|
+
const timeout = opts?.timeouts?.[id] ?? ADAPTER_TIMEOUTS[id] ?? 8000;
|
|
32
|
+
// One controller per adapter: a timeout aborts only that adapter's
|
|
33
|
+
// children; the signal clears when its job settles.
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
installAdapterSignal(id, controller.signal);
|
|
36
|
+
let p;
|
|
37
|
+
try {
|
|
38
|
+
p = Promise.resolve(a.poll());
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
clearAdapterSignal(id);
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
const gated = new Promise((resolve, reject) => {
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
try {
|
|
47
|
+
controller.abort();
|
|
48
|
+
}
|
|
49
|
+
catch { }
|
|
50
|
+
reject(new Error(`timeout after ${timeout}ms`));
|
|
51
|
+
}, timeout);
|
|
52
|
+
p.then((v) => { clearTimeout(timer); resolve(v); }, (e) => { clearTimeout(timer); reject(e); });
|
|
53
|
+
});
|
|
54
|
+
return gated.finally(() => clearAdapterSignal(id));
|
|
28
55
|
});
|
|
29
56
|
const settled = await Promise.allSettled(rawJobs);
|
|
30
57
|
return settled.map((s, i) => {
|
package/dist/adapters/kimi.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function
|
|
1
|
+
import type { ParsedQuota } from "./types.js";
|
|
2
|
+
export declare function parseKimiTui(text: string, now?: Date): ParsedQuota;
|
|
3
3
|
export declare const kimiAdapter: {
|
|
4
4
|
id: string;
|
|
5
5
|
requiresAuth: string;
|
|
6
|
-
poll(): Promise<
|
|
6
|
+
poll(): Promise<ParsedQuota>;
|
|
7
7
|
};
|
package/dist/adapters/kimi.js
CHANGED
|
@@ -1,98 +1,76 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
if (!
|
|
14
|
-
throw new Error("kimi:
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
import { parseResetText } from "./parse.js";
|
|
3
|
+
import { runPty, stripAnsi } from "./pty.js";
|
|
4
|
+
import { adapterSignal } from "../runtime/spawn.js";
|
|
5
|
+
export function parseKimiTui(text, now = new Date()) {
|
|
6
|
+
const cleaned = stripAnsi(text);
|
|
7
|
+
const weeklyRe = /Weekly limit\s+[^0-9]*(\d+)%\s+used\s+resets\s+(in\s+[^\n│\r]+)/i;
|
|
8
|
+
const fiveRe = /5h limit\s+[^0-9]*(\d+)%\s+used\s+resets\s+(in\s+[^\n│\r]+)/i;
|
|
9
|
+
const w = cleaned.match(weeklyRe);
|
|
10
|
+
if (!w)
|
|
11
|
+
throw new Error("kimi: weekly limit not found in TUI output");
|
|
12
|
+
const f = cleaned.match(fiveRe);
|
|
13
|
+
if (!f)
|
|
14
|
+
throw new Error("kimi: 5h limit not found in TUI output");
|
|
15
|
+
const usedPct = parseInt(w[1], 10);
|
|
16
|
+
const sessionPct = parseInt(f[1], 10);
|
|
17
|
+
if (!Number.isFinite(usedPct) || usedPct < 0 || usedPct > 100)
|
|
18
|
+
throw new Error("kimi: bad weekly pct");
|
|
19
|
+
if (!Number.isFinite(sessionPct) || sessionPct < 0 || sessionPct > 100)
|
|
20
|
+
throw new Error("kimi: bad 5h pct");
|
|
21
|
+
const weeklyRaw = w[2].trim();
|
|
22
|
+
const fiveRaw = f[2].trim();
|
|
23
|
+
const weeklyIso = parseResetText(`resets ${weeklyRaw}`, now);
|
|
24
|
+
if (!weeklyIso)
|
|
25
|
+
throw new Error(`kimi: bad weekly reset "${weeklyRaw}"`);
|
|
26
|
+
const fiveIso = parseResetText(`resets ${fiveRaw}`, now);
|
|
27
|
+
if (!fiveIso)
|
|
28
|
+
throw new Error(`kimi: bad 5h reset "${fiveRaw}"`);
|
|
29
|
+
let plan = "unknown";
|
|
30
|
+
const paren = cleaned.match(/Weekly limit\s*\(([^)]+)\)/i);
|
|
31
|
+
if (paren) {
|
|
32
|
+
plan = paren[1].trim().toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const lvl = cleaned.match(/level\s*[:\-]\s*([A-Za-z0-9_\-]+)/i);
|
|
36
|
+
if (lvl)
|
|
37
|
+
plan = lvl[1].trim().toLowerCase().replace(/^level_/i, "");
|
|
38
|
+
}
|
|
39
|
+
const periodStart = new Date(new Date(weeklyIso).getTime() - 7 * 86400000).toISOString();
|
|
20
40
|
return {
|
|
21
41
|
provider: "kimi",
|
|
22
|
-
plan
|
|
23
|
-
usedPct
|
|
24
|
-
|
|
42
|
+
plan,
|
|
43
|
+
usedPct,
|
|
44
|
+
sessionPct,
|
|
45
|
+
resetsAt: weeklyIso,
|
|
25
46
|
periodStart,
|
|
26
|
-
|
|
27
|
-
source: "api",
|
|
47
|
+
source: "tui",
|
|
28
48
|
fetchedAt: now.toISOString(),
|
|
49
|
+
raw: cleaned.slice(0, 4096),
|
|
29
50
|
};
|
|
30
51
|
}
|
|
31
|
-
function credsCandidates() {
|
|
32
|
-
const home = process.env.KIMI_CODE_HOME ?? path.join(os.homedir(), ".kimi-code");
|
|
33
|
-
const legacy = path.join(os.homedir(), ".kimi", "credentials", "kimi-code.json");
|
|
34
|
-
return [path.join(home, "credentials", "kimi-code.json"), legacy];
|
|
35
|
-
}
|
|
36
|
-
async function loadCreds() {
|
|
37
|
-
for (const file of credsCandidates()) {
|
|
38
|
-
try {
|
|
39
|
-
return { file, creds: await readJsonFile(file) };
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
throw new Error("kimi: no credentials file — run `kimi login`");
|
|
46
|
-
}
|
|
47
|
-
function isFreshExpiry(raw) {
|
|
48
|
-
const v = Number(raw);
|
|
49
|
-
if (!Number.isFinite(v) || v <= 0)
|
|
50
|
-
return false;
|
|
51
|
-
const ms = v < 1e12 ? v * 1000 : v; // CLI stores seconds; legacy rows from earlier quotas are ms
|
|
52
|
-
return ms > Date.now();
|
|
53
|
-
}
|
|
54
|
-
async function refreshAndPersist(file, creds) {
|
|
55
|
-
if (!creds.refresh_token)
|
|
56
|
-
throw new Error("kimi: no refresh_token — run `kimi login`");
|
|
57
|
-
const tok = await postForm(REFRESH_URL, {
|
|
58
|
-
grant_type: "refresh_token",
|
|
59
|
-
client_id: CLIENT_ID,
|
|
60
|
-
refresh_token: creds.refresh_token,
|
|
61
|
-
});
|
|
62
|
-
if (!tok.access_token)
|
|
63
|
-
throw new Error("kimi: refresh returned no access_token");
|
|
64
|
-
await persistCreds(file, (cur) => ({
|
|
65
|
-
...cur,
|
|
66
|
-
access_token: tok.access_token,
|
|
67
|
-
refresh_token: tok.refresh_token ?? cur.refresh_token,
|
|
68
|
-
expires_at: Math.floor(Date.now() / 1000) + (Number(tok.expires_in) || 3600),
|
|
69
|
-
token_type: tok.token_type ?? cur.token_type,
|
|
70
|
-
scope: tok.scope ?? cur.scope,
|
|
71
|
-
}));
|
|
72
|
-
return String(tok.access_token);
|
|
73
|
-
}
|
|
74
52
|
export const kimiAdapter = {
|
|
75
53
|
id: "kimi",
|
|
76
|
-
requiresAuth: "
|
|
54
|
+
requiresAuth: "kimi login (CLI owns credentials)",
|
|
77
55
|
async poll() {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
56
|
+
// Use homedir as neutral cwd so quota modal does not depend on project path
|
|
57
|
+
// and workspace-trust prompts are minimized. Fail closed if trust prompt appears.
|
|
58
|
+
const transcript = await runPty({
|
|
59
|
+
file: "kimi",
|
|
60
|
+
args: [],
|
|
61
|
+
cols: 140,
|
|
62
|
+
rows: 35,
|
|
63
|
+
cwd: os.homedir(),
|
|
64
|
+
readyRegex: /Welcome to Kimi Code|context:/i,
|
|
65
|
+
readyTimeoutMs: 8000,
|
|
66
|
+
input: "/usage\r",
|
|
67
|
+
completionRegex: /Weekly limit[\s\S]*?5h limit|5h limit[\s\S]*?Weekly limit/i,
|
|
68
|
+
abortOn: /Trust this folder\?/i,
|
|
69
|
+
timeoutMs: 8000,
|
|
70
|
+
maxBytes: 256 * 1024,
|
|
71
|
+
signal: adapterSignal("kimi"),
|
|
72
|
+
label: "kimi",
|
|
73
|
+
});
|
|
74
|
+
return parseKimiTui(transcript);
|
|
97
75
|
},
|
|
98
76
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function parseManualUsage(provider: string, text: string, now?: Date):
|
|
1
|
+
import type { ParsedQuota } from "./types.js";
|
|
2
|
+
export declare function parseManualUsage(provider: string, text: string, now?: Date): ParsedQuota;
|
|
3
3
|
export declare const manualAdapter: {
|
|
4
4
|
id: string;
|
|
5
5
|
requiresAuth: string;
|
|
6
|
-
ingest(provider: string, text: string): Promise<
|
|
7
|
-
poll(): Promise<
|
|
6
|
+
ingest(provider: string, text: string): Promise<ParsedQuota>;
|
|
7
|
+
poll(): Promise<ParsedQuota>;
|
|
8
8
|
};
|
package/dist/adapters/manual.js
CHANGED
|
@@ -11,9 +11,9 @@ export function parseManualUsage(provider, text, now = new Date()) {
|
|
|
11
11
|
usedPct,
|
|
12
12
|
resetsAt,
|
|
13
13
|
periodStart,
|
|
14
|
-
raw: text,
|
|
15
14
|
source: "manual",
|
|
16
15
|
fetchedAt: now.toISOString(),
|
|
16
|
+
raw: text,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
export const manualAdapter = {
|
|
@@ -23,6 +23,6 @@ export const manualAdapter = {
|
|
|
23
23
|
return parseManualUsage(provider, text);
|
|
24
24
|
},
|
|
25
25
|
async poll() {
|
|
26
|
-
throw new Error("manual has no poll
|
|
26
|
+
throw new Error("manual has no poll");
|
|
27
27
|
},
|
|
28
28
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare function stripAnsi(s: string): string;
|
|
2
|
+
export interface PtyRunOptions {
|
|
3
|
+
file: string;
|
|
4
|
+
args?: string[];
|
|
5
|
+
cwd?: string;
|
|
6
|
+
env?: Record<string, string>;
|
|
7
|
+
cols?: number;
|
|
8
|
+
rows?: number;
|
|
9
|
+
readyRegex?: RegExp;
|
|
10
|
+
readyTimeoutMs?: number;
|
|
11
|
+
settleDelayMs?: number;
|
|
12
|
+
input: string;
|
|
13
|
+
completionRegex?: RegExp;
|
|
14
|
+
/** If matched, abort immediately with a clear error (e.g. trust prompts). */
|
|
15
|
+
abortOn?: RegExp;
|
|
16
|
+
timeoutMs: number;
|
|
17
|
+
maxBytes?: number;
|
|
18
|
+
/** Abort kills the child via the existing kill path and rejects `pty aborted`. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
/** Diagnostic label for the tracked child (adapter id). */
|
|
21
|
+
label?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface SpawnHelperRepair {
|
|
24
|
+
helper: string;
|
|
25
|
+
ok: boolean;
|
|
26
|
+
error?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Lazy replacement for the removed postinstall: best-effort `chmod 0o755`
|
|
30
|
+
* over every prebuilds entry `spawn-helper` under the given node-pty roots.
|
|
31
|
+
* Missing roots, missing prebuild dirs, and missing helpers are skipped
|
|
32
|
+
* silently; only attempted repairs are recorded.
|
|
33
|
+
*/
|
|
34
|
+
export declare function repairSpawnHelpers(roots: string[], chmod?: (p: string, mode: number) => void): SpawnHelperRepair[];
|
|
35
|
+
/**
|
|
36
|
+
* Human diagnostic for failed repairs, or null when nothing failed.
|
|
37
|
+
* Load-bearing for root-owned trees (e.g. `sudo` global installs) where the
|
|
38
|
+
* invoking user cannot repair: without it the failure would go opaque again.
|
|
39
|
+
*/
|
|
40
|
+
export declare function describeSpawnHelperRepairs(outcomes: SpawnHelperRepair[]): string | null;
|
|
41
|
+
export declare function runPty(opts: PtyRunOptions): Promise<string>;
|