@mauricode/token-derby 2.11.0 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +100 -32
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -702,10 +702,40 @@ function renderHatLabel(hats, hatChoice, initialEquipped) {
|
|
|
702
702
|
] });
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
+
// src/env/env.ts
|
|
706
|
+
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
707
|
+
import * as os from "os";
|
|
708
|
+
import * as path from "path";
|
|
709
|
+
var ENV_NAMES = ["prod", "staging"];
|
|
710
|
+
function baseDir() {
|
|
711
|
+
return process.env.TOKEN_DERBY_BASE ?? os.homedir();
|
|
712
|
+
}
|
|
713
|
+
function configFile() {
|
|
714
|
+
return path.join(baseDir(), ".token-derby", "config.json");
|
|
715
|
+
}
|
|
716
|
+
function selectedEnv() {
|
|
717
|
+
try {
|
|
718
|
+
const raw = readFileSync(configFile(), "utf8");
|
|
719
|
+
const parsed = JSON.parse(raw);
|
|
720
|
+
if (parsed.env === "prod" || parsed.env === "staging") return parsed.env;
|
|
721
|
+
return "prod";
|
|
722
|
+
} catch {
|
|
723
|
+
return "prod";
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
function setSelectedEnv(env) {
|
|
727
|
+
const file = configFile();
|
|
728
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
729
|
+
writeFileSync(file, JSON.stringify({ env }, null, 2) + "\n", "utf8");
|
|
730
|
+
}
|
|
731
|
+
|
|
705
732
|
// src/config.ts
|
|
706
|
-
var
|
|
733
|
+
var ENVIRONMENTS = {
|
|
734
|
+
prod: { apiBase: "https://token-derby.mauricode.co.uk/api" },
|
|
735
|
+
staging: { apiBase: "https://token-derby-staging.mauricode.co.uk/api" }
|
|
736
|
+
};
|
|
707
737
|
function apiBase() {
|
|
708
|
-
return process.env.TOKEN_DERBY_API_BASE ??
|
|
738
|
+
return process.env.TOKEN_DERBY_API_BASE ?? ENVIRONMENTS[selectedEnv()].apiBase;
|
|
709
739
|
}
|
|
710
740
|
var HEARTBEAT_INTERVAL_MS = 6e4;
|
|
711
741
|
var HEARTBEAT_RETRY_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
@@ -713,8 +743,8 @@ var HEARTBEAT_RETRY_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3];
|
|
|
713
743
|
// src/version.ts
|
|
714
744
|
import { createRequire } from "module";
|
|
715
745
|
function readVersion() {
|
|
716
|
-
if ("2.
|
|
717
|
-
return "2.
|
|
746
|
+
if ("2.12.1".length > 0) {
|
|
747
|
+
return "2.12.1";
|
|
718
748
|
}
|
|
719
749
|
try {
|
|
720
750
|
const req = createRequire(import.meta.url);
|
|
@@ -728,31 +758,34 @@ var CLI_VERSION = readVersion();
|
|
|
728
758
|
|
|
729
759
|
// src/identity/identity.ts
|
|
730
760
|
import { promises as fs } from "fs";
|
|
731
|
-
import * as
|
|
761
|
+
import * as path3 from "path";
|
|
732
762
|
|
|
733
763
|
// src/paths.ts
|
|
734
|
-
import * as
|
|
735
|
-
import * as
|
|
764
|
+
import * as os2 from "os";
|
|
765
|
+
import * as path2 from "path";
|
|
736
766
|
function homeDir() {
|
|
737
|
-
|
|
767
|
+
const override = process.env.TOKEN_DERBY_HOME;
|
|
768
|
+
if (override) return override;
|
|
769
|
+
const dir = selectedEnv() === "staging" ? ".token-derby-staging" : ".token-derby";
|
|
770
|
+
return path2.join(baseDir(), dir);
|
|
738
771
|
}
|
|
739
772
|
function identityFile() {
|
|
740
|
-
return
|
|
773
|
+
return path2.join(homeDir(), "identity.json");
|
|
741
774
|
}
|
|
742
775
|
function activeRaceFile(joinCode) {
|
|
743
|
-
return
|
|
776
|
+
return path2.join(homeDir(), "active-races", `${joinCode}.json`);
|
|
744
777
|
}
|
|
745
778
|
function activeRacesDir() {
|
|
746
|
-
return
|
|
779
|
+
return path2.join(homeDir(), "active-races");
|
|
747
780
|
}
|
|
748
781
|
function claudeProjectsDir() {
|
|
749
|
-
return process.env.TOKEN_DERBY_CLAUDE_DIR ??
|
|
782
|
+
return process.env.TOKEN_DERBY_CLAUDE_DIR ?? path2.join(os2.homedir(), ".claude", "projects");
|
|
750
783
|
}
|
|
751
784
|
function codexSessionsDir() {
|
|
752
|
-
return process.env.TOKEN_DERBY_CODEX_DIR ??
|
|
785
|
+
return process.env.TOKEN_DERBY_CODEX_DIR ?? path2.join(os2.homedir(), ".codex");
|
|
753
786
|
}
|
|
754
787
|
function geminiTmpDir() {
|
|
755
|
-
return process.env.TOKEN_DERBY_GEMINI_DIR ??
|
|
788
|
+
return process.env.TOKEN_DERBY_GEMINI_DIR ?? path2.join(os2.homedir(), ".gemini", "tmp");
|
|
756
789
|
}
|
|
757
790
|
|
|
758
791
|
// src/identity/identity.ts
|
|
@@ -808,8 +841,8 @@ function getIdentity() {
|
|
|
808
841
|
function _resetIdentityCacheForTests() {
|
|
809
842
|
identityCache = null;
|
|
810
843
|
}
|
|
811
|
-
async function request(method,
|
|
812
|
-
const url =
|
|
844
|
+
async function request(method, path8, body, horseAuthToken, fetchImpl = fetch) {
|
|
845
|
+
const url = path8.startsWith("http") ? path8 : `${apiBase()}${path8}`;
|
|
813
846
|
const headers = {};
|
|
814
847
|
headers[CLI_VERSION_HEADER] = CLI_VERSION;
|
|
815
848
|
headers["user-agent"] = `token-derby/${CLI_VERSION}`;
|
|
@@ -1321,7 +1354,7 @@ function PrimaryPicker({ onPick }) {
|
|
|
1321
1354
|
|
|
1322
1355
|
// src/stable/active-race.ts
|
|
1323
1356
|
import * as fs2 from "fs/promises";
|
|
1324
|
-
import * as
|
|
1357
|
+
import * as path4 from "path";
|
|
1325
1358
|
async function saveActiveRace(active) {
|
|
1326
1359
|
await fs2.mkdir(activeRacesDir(), { recursive: true });
|
|
1327
1360
|
await fs2.writeFile(
|
|
@@ -1512,11 +1545,11 @@ function runHeartbeatLoop(opts) {
|
|
|
1512
1545
|
|
|
1513
1546
|
// src/tokens/transcripts.ts
|
|
1514
1547
|
import * as fs3 from "fs/promises";
|
|
1515
|
-
import * as
|
|
1548
|
+
import * as path5 from "path";
|
|
1516
1549
|
var MAX_PROJECT_DEPTH = 8;
|
|
1517
1550
|
function conversationId(file, root) {
|
|
1518
|
-
const rel =
|
|
1519
|
-
const [project, session] = rel.split(
|
|
1551
|
+
const rel = path5.relative(root, file);
|
|
1552
|
+
const [project, session] = rel.split(path5.sep);
|
|
1520
1553
|
if (project === void 0 || session === void 0) return rel.replace(/\.jsonl$/, "");
|
|
1521
1554
|
return `${project}/${session.replace(/\.jsonl$/, "")}`;
|
|
1522
1555
|
}
|
|
@@ -1548,7 +1581,7 @@ async function listJsonlFiles(root) {
|
|
|
1548
1581
|
const projects = await fs3.readdir(root);
|
|
1549
1582
|
const out = [];
|
|
1550
1583
|
for (const project of projects) {
|
|
1551
|
-
const projectDir =
|
|
1584
|
+
const projectDir = path5.join(root, project);
|
|
1552
1585
|
const stat3 = await fs3.stat(projectDir);
|
|
1553
1586
|
if (!stat3.isDirectory()) continue;
|
|
1554
1587
|
await collectJsonl(projectDir, MAX_PROJECT_DEPTH, out);
|
|
@@ -1560,9 +1593,9 @@ async function collectJsonl(dir, depth, out) {
|
|
|
1560
1593
|
const entries = await fs3.readdir(dir);
|
|
1561
1594
|
for (const entry of entries) {
|
|
1562
1595
|
if (entry.endsWith(".jsonl")) {
|
|
1563
|
-
out.push(
|
|
1596
|
+
out.push(path5.join(dir, entry));
|
|
1564
1597
|
} else if (depth > 1) {
|
|
1565
|
-
const child =
|
|
1598
|
+
const child = path5.join(dir, entry);
|
|
1566
1599
|
const st = await fs3.stat(child);
|
|
1567
1600
|
if (st.isDirectory()) await collectJsonl(child, depth - 1, out);
|
|
1568
1601
|
}
|
|
@@ -1593,7 +1626,7 @@ async function sumFile(file) {
|
|
|
1593
1626
|
|
|
1594
1627
|
// src/tokens/codex.ts
|
|
1595
1628
|
import * as fs4 from "fs/promises";
|
|
1596
|
-
import * as
|
|
1629
|
+
import * as path6 from "path";
|
|
1597
1630
|
function num(v) {
|
|
1598
1631
|
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
1599
1632
|
}
|
|
@@ -1601,8 +1634,8 @@ async function sumCodexByConversation() {
|
|
|
1601
1634
|
const root = codexSessionsDir();
|
|
1602
1635
|
await fs4.stat(root);
|
|
1603
1636
|
const files = [
|
|
1604
|
-
...await collectRollouts(
|
|
1605
|
-
...await collectRollouts(
|
|
1637
|
+
...await collectRollouts(path6.join(root, "sessions")),
|
|
1638
|
+
...await collectRollouts(path6.join(root, "archived_sessions"))
|
|
1606
1639
|
];
|
|
1607
1640
|
const byConv = /* @__PURE__ */ new Map();
|
|
1608
1641
|
for (const file of files) {
|
|
@@ -1630,7 +1663,7 @@ async function collectRollouts(dir) {
|
|
|
1630
1663
|
}
|
|
1631
1664
|
const out = [];
|
|
1632
1665
|
for (const entry of entries) {
|
|
1633
|
-
const full =
|
|
1666
|
+
const full = path6.join(dir, entry.name);
|
|
1634
1667
|
if (entry.isDirectory()) out.push(...await collectRollouts(full));
|
|
1635
1668
|
else if (entry.name.startsWith("rollout-") && entry.name.endsWith(".jsonl")) out.push(full);
|
|
1636
1669
|
}
|
|
@@ -1665,7 +1698,7 @@ async function lastTokenCount(file) {
|
|
|
1665
1698
|
|
|
1666
1699
|
// src/tokens/gemini.ts
|
|
1667
1700
|
import * as fs5 from "fs/promises";
|
|
1668
|
-
import * as
|
|
1701
|
+
import * as path7 from "path";
|
|
1669
1702
|
function num2(v) {
|
|
1670
1703
|
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
1671
1704
|
}
|
|
@@ -1691,7 +1724,7 @@ async function listChatFiles(root) {
|
|
|
1691
1724
|
const entries = await fs5.readdir(root);
|
|
1692
1725
|
const out = [];
|
|
1693
1726
|
for (const entry of entries) {
|
|
1694
|
-
const chatsDir =
|
|
1727
|
+
const chatsDir = path7.join(root, entry, "chats");
|
|
1695
1728
|
let files;
|
|
1696
1729
|
try {
|
|
1697
1730
|
files = await fs5.readdir(chatsDir);
|
|
@@ -1699,7 +1732,7 @@ async function listChatFiles(root) {
|
|
|
1699
1732
|
continue;
|
|
1700
1733
|
}
|
|
1701
1734
|
for (const f of files) {
|
|
1702
|
-
if (f.endsWith(".json") || f.endsWith(".jsonl")) out.push(
|
|
1735
|
+
if (f.endsWith(".json") || f.endsWith(".jsonl")) out.push(path7.join(chatsDir, f));
|
|
1703
1736
|
}
|
|
1704
1737
|
}
|
|
1705
1738
|
return out;
|
|
@@ -2910,6 +2943,36 @@ async function webCommand(deps = {}) {
|
|
|
2910
2943
|
return 0;
|
|
2911
2944
|
}
|
|
2912
2945
|
|
|
2946
|
+
// src/commands/env.ts
|
|
2947
|
+
function warnOverrides() {
|
|
2948
|
+
if (process.env.TOKEN_DERBY_HOME) {
|
|
2949
|
+
console.error("Warning: TOKEN_DERBY_HOME overrides the per-env data directory; `env` selection does not change where the identity is stored.");
|
|
2950
|
+
}
|
|
2951
|
+
if (process.env.TOKEN_DERBY_API_BASE) {
|
|
2952
|
+
console.error("Warning: TOKEN_DERBY_API_BASE overrides the API base; `env` selection does not change which API is used.");
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
function envCommand(arg) {
|
|
2956
|
+
if (!arg) {
|
|
2957
|
+
console.log(`Environment: ${selectedEnv()}`);
|
|
2958
|
+
console.log(`API base: ${apiBase()}`);
|
|
2959
|
+
console.log(`Data dir: ${homeDir()}`);
|
|
2960
|
+
warnOverrides();
|
|
2961
|
+
return 0;
|
|
2962
|
+
}
|
|
2963
|
+
if (!ENV_NAMES.includes(arg)) {
|
|
2964
|
+
console.error(`Unknown environment: ${arg}`);
|
|
2965
|
+
console.error(`Valid environments: ${ENV_NAMES.join(", ")}`);
|
|
2966
|
+
return 2;
|
|
2967
|
+
}
|
|
2968
|
+
setSelectedEnv(arg);
|
|
2969
|
+
console.log(`Switched to ${arg}.`);
|
|
2970
|
+
console.log(`API base: ${apiBase()}`);
|
|
2971
|
+
console.log(`Data dir: ${homeDir()}`);
|
|
2972
|
+
warnOverrides();
|
|
2973
|
+
return 0;
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2913
2976
|
// src/bin.ts
|
|
2914
2977
|
var HELP = `token-derby v${CLI_VERSION}
|
|
2915
2978
|
|
|
@@ -2946,8 +3009,12 @@ Cosmetics:
|
|
|
2946
3009
|
Earn rolls by leveling up horses.
|
|
2947
3010
|
|
|
2948
3011
|
Environment:
|
|
2949
|
-
|
|
2950
|
-
|
|
3012
|
+
token-derby env Show the active environment (prod|staging)
|
|
3013
|
+
token-derby env <prod|staging> Switch environment. Each env has its own
|
|
3014
|
+
identity/stable dir, so switching never
|
|
3015
|
+
touches the other env's account.
|
|
3016
|
+
TOKEN_DERBY_API_BASE Hard-override API base URL (wins over env)
|
|
3017
|
+
TOKEN_DERBY_HOME Hard-override identity/stable directory
|
|
2951
3018
|
`;
|
|
2952
3019
|
async function main() {
|
|
2953
3020
|
const argv = process.argv.slice(2);
|
|
@@ -2965,6 +3032,7 @@ async function main() {
|
|
|
2965
3032
|
return initCommand(reset);
|
|
2966
3033
|
}
|
|
2967
3034
|
if (cmd === "update") return updateCommand();
|
|
3035
|
+
if (cmd === "env") return envCommand(argv[1]);
|
|
2968
3036
|
const identity = await loadIdentity();
|
|
2969
3037
|
if (!identity) {
|
|
2970
3038
|
console.error("Run `token-derby init` to set up your identity before using any other command.");
|