@tokz/cli 0.2.11 → 0.2.13
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/{Root-T2V2YHJ2.js → Root-HZIVZ2YT.js} +291 -130
- package/dist/cli.js +1 -1
- package/package.json +1 -1
|
@@ -632,117 +632,210 @@ var codebuffAdapter = {
|
|
|
632
632
|
};
|
|
633
633
|
|
|
634
634
|
// src/agents/codex.ts
|
|
635
|
-
import {
|
|
636
|
-
import { access as access5 } from "fs/promises";
|
|
637
|
-
import { createInterface } from "readline";
|
|
635
|
+
import { access as access5, readFile as readFile4, stat as stat2 } from "fs/promises";
|
|
638
636
|
import { homedir as homedir6 } from "os";
|
|
639
637
|
import { join as join6 } from "path";
|
|
640
638
|
import { glob as glob4 } from "tinyglobby";
|
|
641
|
-
import { z } from "zod";
|
|
642
|
-
var TokenTotals = z.object({
|
|
643
|
-
input_tokens: z.number().catch(0).default(0),
|
|
644
|
-
cached_input_tokens: z.number().catch(0).default(0),
|
|
645
|
-
output_tokens: z.number().catch(0).default(0),
|
|
646
|
-
reasoning_output_tokens: z.number().catch(0).default(0),
|
|
647
|
-
total_tokens: z.number().catch(0).default(0)
|
|
648
|
-
});
|
|
649
|
-
var Line = z.object({
|
|
650
|
-
timestamp: z.string().optional(),
|
|
651
|
-
type: z.string().optional(),
|
|
652
|
-
// old-format meta lines carry cwd at the top level
|
|
653
|
-
cwd: z.string().optional(),
|
|
654
|
-
payload: z.object({
|
|
655
|
-
type: z.string().optional(),
|
|
656
|
-
cwd: z.string().optional(),
|
|
657
|
-
model: z.string().optional(),
|
|
658
|
-
name: z.string().optional(),
|
|
659
|
-
info: z.object({
|
|
660
|
-
total_token_usage: TokenTotals.optional(),
|
|
661
|
-
// Codex writes the per-turn amount here directly; prefer it over
|
|
662
|
-
// differencing cumulative totals.
|
|
663
|
-
last_token_usage: TokenTotals.optional()
|
|
664
|
-
}).nullish()
|
|
665
|
-
}).passthrough().optional()
|
|
666
|
-
});
|
|
667
|
-
function codexHome(home) {
|
|
668
|
-
if (home) return join6(home, ".codex");
|
|
669
|
-
return process.env.CODEX_HOME ?? join6(homedir6(), ".codex");
|
|
670
|
-
}
|
|
671
639
|
var DEFAULT_MODEL = "gpt-5";
|
|
640
|
+
var CODEX_AUTO_REVIEW_MODEL = "codex-auto-review";
|
|
641
|
+
var CODEX_AUTO_REVIEW_FALLBACKS = [
|
|
642
|
+
{ releasedOn: "2026-04-23", model: "gpt-5.5" },
|
|
643
|
+
{ releasedOn: "2026-03-05", model: "gpt-5.4" },
|
|
644
|
+
{ releasedOn: "2026-02-05", model: "gpt-5.3-codex" },
|
|
645
|
+
{ releasedOn: "2025-12-11", model: "gpt-5.2-codex" },
|
|
646
|
+
{ releasedOn: "2025-11-13", model: "gpt-5.1-codex" },
|
|
647
|
+
{ releasedOn: "2025-09-15", model: "gpt-5-codex" },
|
|
648
|
+
{ releasedOn: "2025-08-07", model: "gpt-5" }
|
|
649
|
+
];
|
|
650
|
+
function codexHomes(home) {
|
|
651
|
+
if (home) return [join6(home, ".codex")];
|
|
652
|
+
const env = process.env.CODEX_HOME;
|
|
653
|
+
if (env) {
|
|
654
|
+
return env.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
655
|
+
}
|
|
656
|
+
return [join6(homedir6(), ".codex")];
|
|
657
|
+
}
|
|
658
|
+
function asDict(v) {
|
|
659
|
+
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
|
|
660
|
+
}
|
|
661
|
+
function u64(v) {
|
|
662
|
+
if (typeof v === "number") {
|
|
663
|
+
return Number.isInteger(v) && v >= 0 ? v : void 0;
|
|
664
|
+
}
|
|
665
|
+
if (typeof v === "string") {
|
|
666
|
+
const t = v.trim();
|
|
667
|
+
return /^\d+$/.test(t) ? Number(t) : void 0;
|
|
668
|
+
}
|
|
669
|
+
return void 0;
|
|
670
|
+
}
|
|
671
|
+
function rawUsage(v) {
|
|
672
|
+
const o = asDict(v);
|
|
673
|
+
if (!o) return void 0;
|
|
674
|
+
const input = u64(o.input_tokens) ?? u64(o.prompt_tokens) ?? u64(o.input) ?? 0;
|
|
675
|
+
const cached = u64(o.cached_input_tokens) ?? u64(o.cache_read_input_tokens) ?? u64(o.cached_tokens) ?? 0;
|
|
676
|
+
const output = u64(o.output_tokens) ?? u64(o.completion_tokens) ?? u64(o.output) ?? 0;
|
|
677
|
+
const reasoning = u64(o.reasoning_output_tokens) ?? u64(o.reasoning_tokens) ?? 0;
|
|
678
|
+
const sum = input + output + reasoning;
|
|
679
|
+
const totalField = u64(o.total_tokens);
|
|
680
|
+
const total = totalField !== void 0 && (totalField > 0 || sum === 0) ? totalField : sum;
|
|
681
|
+
return { input, cached, output, reasoning, total };
|
|
682
|
+
}
|
|
683
|
+
function subtractUsage(current, previous) {
|
|
684
|
+
return {
|
|
685
|
+
input: Math.max(0, current.input - (previous?.input ?? 0)),
|
|
686
|
+
cached: Math.max(0, current.cached - (previous?.cached ?? 0)),
|
|
687
|
+
output: Math.max(0, current.output - (previous?.output ?? 0)),
|
|
688
|
+
reasoning: Math.max(0, current.reasoning - (previous?.reasoning ?? 0)),
|
|
689
|
+
total: Math.max(0, current.total - (previous?.total ?? 0))
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
function nonEmpty(v) {
|
|
693
|
+
if (typeof v !== "string") return void 0;
|
|
694
|
+
const t = v.trim();
|
|
695
|
+
return t.length > 0 ? t : void 0;
|
|
696
|
+
}
|
|
697
|
+
function modelFromParts(v) {
|
|
698
|
+
const o = asDict(v);
|
|
699
|
+
if (!o) return void 0;
|
|
700
|
+
return nonEmpty(o.model) ?? nonEmpty(o.model_name) ?? nonEmpty(asDict(o.metadata)?.model);
|
|
701
|
+
}
|
|
702
|
+
function timestampDate(ts) {
|
|
703
|
+
const date = ts.slice(0, 10);
|
|
704
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) return void 0;
|
|
705
|
+
const year = Number(date.slice(0, 4));
|
|
706
|
+
const month = Number(date.slice(5, 7));
|
|
707
|
+
const day = Number(date.slice(8, 10));
|
|
708
|
+
const daysInMonth = month === 2 ? year % 4 === 0 && year % 100 !== 0 || year % 400 === 0 ? 29 : 28 : [1, 3, 5, 7, 8, 10, 12].includes(month) ? 31 : [4, 6, 9, 11].includes(month) ? 30 : void 0;
|
|
709
|
+
if (daysInMonth === void 0 || day < 1 || day > daysInMonth) return void 0;
|
|
710
|
+
return date;
|
|
711
|
+
}
|
|
712
|
+
function autoReviewFallback(model, timestamp) {
|
|
713
|
+
if (model !== CODEX_AUTO_REVIEW_MODEL) return void 0;
|
|
714
|
+
const date = timestampDate(timestamp);
|
|
715
|
+
if (!date) return DEFAULT_MODEL;
|
|
716
|
+
return CODEX_AUTO_REVIEW_FALLBACKS.find((f) => date >= f.releasedOn)?.model ?? DEFAULT_MODEL;
|
|
717
|
+
}
|
|
718
|
+
function resolveModel(parsed, timestamp, state) {
|
|
719
|
+
if (parsed !== void 0) {
|
|
720
|
+
state.current = parsed;
|
|
721
|
+
state.currentIsFallback = false;
|
|
722
|
+
}
|
|
723
|
+
let model = parsed ?? state.current;
|
|
724
|
+
if (model === void 0) {
|
|
725
|
+
state.currentIsFallback = true;
|
|
726
|
+
state.current = DEFAULT_MODEL;
|
|
727
|
+
model = DEFAULT_MODEL;
|
|
728
|
+
}
|
|
729
|
+
return autoReviewFallback(model, timestamp) ?? model;
|
|
730
|
+
}
|
|
731
|
+
function normalizeTimestamp(v) {
|
|
732
|
+
if (typeof v === "string") {
|
|
733
|
+
const t = v.trim();
|
|
734
|
+
if (t.length === 0) return void 0;
|
|
735
|
+
const ms2 = Date.parse(t);
|
|
736
|
+
return Number.isNaN(ms2) ? void 0 : new Date(ms2).toISOString();
|
|
737
|
+
}
|
|
738
|
+
const raw = u64(v);
|
|
739
|
+
if (raw === void 0) return void 0;
|
|
740
|
+
const ms = raw > 1e10 ? raw : raw * 1e3;
|
|
741
|
+
return new Date(ms).toISOString();
|
|
742
|
+
}
|
|
743
|
+
function rawOrNormalizedTimestamp(v) {
|
|
744
|
+
if (typeof v === "string") {
|
|
745
|
+
const t = v.trim();
|
|
746
|
+
if (t.length === 0) return void 0;
|
|
747
|
+
if (timestampDate(t) !== void 0) return t;
|
|
748
|
+
return normalizeTimestamp(t);
|
|
749
|
+
}
|
|
750
|
+
return normalizeTimestamp(v);
|
|
751
|
+
}
|
|
752
|
+
function tsSecond(ts) {
|
|
753
|
+
return (ts ?? "").slice(0, 19);
|
|
754
|
+
}
|
|
755
|
+
function parseLine(raw) {
|
|
756
|
+
let obj;
|
|
757
|
+
try {
|
|
758
|
+
obj = JSON.parse(raw);
|
|
759
|
+
} catch {
|
|
760
|
+
return void 0;
|
|
761
|
+
}
|
|
762
|
+
const o = asDict(obj);
|
|
763
|
+
if (!o) return void 0;
|
|
764
|
+
return {
|
|
765
|
+
timestamp: typeof o.timestamp === "string" ? o.timestamp : void 0,
|
|
766
|
+
type: typeof o.type === "string" ? o.type : void 0,
|
|
767
|
+
cwd: typeof o.cwd === "string" ? o.cwd : void 0,
|
|
768
|
+
payload: asDict(o.payload),
|
|
769
|
+
obj: o
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
function tokenCountInfo(p) {
|
|
773
|
+
return p.type === "event_msg" && p.payload?.type === "token_count" ? asDict(p.payload.info) : void 0;
|
|
774
|
+
}
|
|
775
|
+
function replayBurstSecond(content, lines) {
|
|
776
|
+
const head = content.slice(0, 16384);
|
|
777
|
+
if (!head.includes("thread_spawn") && !head.includes("forked_from_id")) return void 0;
|
|
778
|
+
let first;
|
|
779
|
+
for (const p of lines) {
|
|
780
|
+
const info = tokenCountInfo(p);
|
|
781
|
+
if (!info) continue;
|
|
782
|
+
if (!asDict(info.last_token_usage) && !asDict(info.total_token_usage)) continue;
|
|
783
|
+
const sec = tsSecond(p.timestamp);
|
|
784
|
+
if (first === void 0) first = sec;
|
|
785
|
+
else return first === sec ? first : void 0;
|
|
786
|
+
}
|
|
787
|
+
return void 0;
|
|
788
|
+
}
|
|
789
|
+
function headlessUsage(o) {
|
|
790
|
+
const usage = rawUsage(asDict(o.usage)) ?? rawUsage(asDict(asDict(o.data)?.usage)) ?? rawUsage(asDict(asDict(o.result)?.usage)) ?? rawUsage(asDict(asDict(o.response)?.usage));
|
|
791
|
+
if (!usage) return void 0;
|
|
792
|
+
if (usage.input === 0 && usage.cached === 0 && usage.output === 0 && usage.reasoning === 0 && usage.total === 0) {
|
|
793
|
+
return void 0;
|
|
794
|
+
}
|
|
795
|
+
return usage;
|
|
796
|
+
}
|
|
797
|
+
function headlessModel(o) {
|
|
798
|
+
return modelFromParts(o) ?? modelFromParts(asDict(o.data)) ?? modelFromParts(asDict(o.result)) ?? modelFromParts(asDict(o.response));
|
|
799
|
+
}
|
|
800
|
+
function headlessTimestamp(o, pick) {
|
|
801
|
+
const fromFields = (f) => f ? pick(f.timestamp) ?? pick(f.created_at) ?? pick(f.createdAt) : void 0;
|
|
802
|
+
return fromFields(o) ?? fromFields(asDict(o.data)) ?? fromFields(asDict(o.result)) ?? fromFields(asDict(o.response));
|
|
803
|
+
}
|
|
672
804
|
async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
|
|
673
805
|
const stats = { file, usageByModel: {}, toolCalls: {}, toolCostUsd: {}, dailyUsage: {} };
|
|
674
|
-
const
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
let turnTools = [];
|
|
678
|
-
for await (const raw of rl) {
|
|
806
|
+
const content = await readFile4(file, "utf8").catch(() => "");
|
|
807
|
+
const lines = [];
|
|
808
|
+
for (const raw of content.split("\n")) {
|
|
679
809
|
if (!raw.trim()) continue;
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
if (
|
|
691
|
-
|
|
692
|
-
if (!stats.firstTs) stats.firstTs = timestamp;
|
|
693
|
-
stats.lastTs = timestamp;
|
|
694
|
-
}
|
|
695
|
-
const toolName = payload2?.type === "function_call" || payload2?.type === "custom_tool_call" ? payload2.name : payload2?.type === "local_shell_call" ? "shell" : type === "function_call" ? parsed.data.name : void 0;
|
|
696
|
-
if (toolName) {
|
|
697
|
-
stats.toolCalls[toolName] = (stats.toolCalls[toolName] ?? 0) + 1;
|
|
698
|
-
turnTools.push(toolName);
|
|
810
|
+
const parsed = parseLine(raw);
|
|
811
|
+
if (parsed) lines.push(parsed);
|
|
812
|
+
}
|
|
813
|
+
const burstSecond = replayBurstSecond(content, lines);
|
|
814
|
+
let skippingReplay = burstSecond !== void 0;
|
|
815
|
+
const modelState = { currentIsFallback: false };
|
|
816
|
+
let prev;
|
|
817
|
+
let turnTools = [];
|
|
818
|
+
let mtimeIso;
|
|
819
|
+
const fileMtime = async () => {
|
|
820
|
+
if (mtimeIso === void 0) {
|
|
821
|
+
mtimeIso = await stat2(file).then((s) => s.mtime.toISOString()).catch(() => (/* @__PURE__ */ new Date(0)).toISOString());
|
|
699
822
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
const
|
|
705
|
-
const dedupKey = `${timestamp ?? ""}|${model}|${idTotals.input_tokens}|${idTotals.cached_input_tokens}|${idTotals.output_tokens}|${idTotals.reasoning_output_tokens}|${idTotals.total_tokens}`;
|
|
706
|
-
let dInput;
|
|
707
|
-
let dCached;
|
|
708
|
-
let dOutput;
|
|
709
|
-
if (last) {
|
|
710
|
-
dInput = last.input_tokens;
|
|
711
|
-
dCached = last.cached_input_tokens;
|
|
712
|
-
dOutput = last.output_tokens;
|
|
713
|
-
if (totals) {
|
|
714
|
-
prev = {
|
|
715
|
-
input: totals.input_tokens,
|
|
716
|
-
cached: totals.cached_input_tokens,
|
|
717
|
-
output: totals.output_tokens,
|
|
718
|
-
total: totals.total_tokens
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
} else {
|
|
722
|
-
const cur = {
|
|
723
|
-
input: totals.input_tokens,
|
|
724
|
-
cached: totals.cached_input_tokens,
|
|
725
|
-
output: totals.output_tokens,
|
|
726
|
-
total: totals.total_tokens
|
|
727
|
-
};
|
|
728
|
-
if (cur.total < prev.total) prev = { input: 0, cached: 0, output: 0, total: 0 };
|
|
729
|
-
dInput = Math.max(0, cur.input - prev.input);
|
|
730
|
-
dCached = Math.max(0, cur.cached - prev.cached);
|
|
731
|
-
dOutput = Math.max(0, cur.output - prev.output);
|
|
732
|
-
prev = cur;
|
|
733
|
-
}
|
|
734
|
-
if (dInput + dOutput === 0) continue;
|
|
823
|
+
return mtimeIso;
|
|
824
|
+
};
|
|
825
|
+
const accumulate = (usage, model, timestamp) => {
|
|
826
|
+
const cached = Math.min(usage.cached, usage.input);
|
|
827
|
+
const dedupKey = `${timestamp ?? ""}|${model}|${usage.input}|${cached}|${usage.output}|${usage.reasoning}|${usage.total}`;
|
|
735
828
|
if (seen.has(dedupKey)) {
|
|
736
829
|
turnTools = [];
|
|
737
|
-
|
|
830
|
+
return;
|
|
738
831
|
}
|
|
739
832
|
seen.add(dedupKey);
|
|
740
833
|
const delta = {
|
|
741
834
|
// Codex's input_tokens INCLUDES cached tokens; split them out.
|
|
742
|
-
inputTokens: Math.max(0,
|
|
743
|
-
cacheReadTokens:
|
|
835
|
+
inputTokens: Math.max(0, usage.input - cached),
|
|
836
|
+
cacheReadTokens: cached,
|
|
744
837
|
cacheCreationTokens: 0,
|
|
745
|
-
outputTokens:
|
|
838
|
+
outputTokens: usage.output,
|
|
746
839
|
turns: 1
|
|
747
840
|
};
|
|
748
841
|
const accs = [stats.usageByModel[model] ??= emptyUsage()];
|
|
@@ -764,15 +857,84 @@ async function parseCodexRollout(file, seen = /* @__PURE__ */ new Set()) {
|
|
|
764
857
|
}
|
|
765
858
|
}
|
|
766
859
|
turnTools = [];
|
|
860
|
+
};
|
|
861
|
+
for (const parsed of lines) {
|
|
862
|
+
const { timestamp, type, payload: payload2 } = parsed;
|
|
863
|
+
if (!stats.cwd) {
|
|
864
|
+
const payloadCwd = typeof payload2?.cwd === "string" ? payload2.cwd : void 0;
|
|
865
|
+
stats.cwd = payloadCwd ?? parsed.cwd;
|
|
866
|
+
}
|
|
867
|
+
if (timestamp) {
|
|
868
|
+
if (!stats.firstTs) stats.firstTs = timestamp;
|
|
869
|
+
stats.lastTs = timestamp;
|
|
870
|
+
}
|
|
871
|
+
const toolName = payload2?.type === "function_call" || payload2?.type === "custom_tool_call" ? nonEmpty(payload2.name) : payload2?.type === "local_shell_call" ? "shell" : type === "function_call" ? nonEmpty(parsed.obj.name) : void 0;
|
|
872
|
+
if (toolName) {
|
|
873
|
+
stats.toolCalls[toolName] = (stats.toolCalls[toolName] ?? 0) + 1;
|
|
874
|
+
turnTools.push(toolName);
|
|
875
|
+
}
|
|
876
|
+
if (type === "turn_context") {
|
|
877
|
+
const model2 = modelFromParts(payload2);
|
|
878
|
+
if (model2 !== void 0) {
|
|
879
|
+
modelState.current = model2;
|
|
880
|
+
modelState.currentIsFallback = false;
|
|
881
|
+
}
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
const info = tokenCountInfo(parsed);
|
|
885
|
+
if (info) {
|
|
886
|
+
const totals = rawUsage(info.total_token_usage);
|
|
887
|
+
const last = rawUsage(info.last_token_usage);
|
|
888
|
+
if (!last && !totals) continue;
|
|
889
|
+
if (skippingReplay && tsSecond(timestamp) === burstSecond) {
|
|
890
|
+
if (totals) prev = totals;
|
|
891
|
+
turnTools = [];
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
skippingReplay = false;
|
|
895
|
+
const usage2 = last ?? subtractUsage(totals, prev);
|
|
896
|
+
if (totals) prev = totals;
|
|
897
|
+
if (usage2.input === 0 && usage2.cached === 0 && usage2.output === 0 && usage2.reasoning === 0) {
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
const ts = nonEmpty(timestamp) ?? normalizeTimestamp(parsed.obj.timestamp);
|
|
901
|
+
const parsedModel = modelFromParts(payload2) ?? modelFromParts(info);
|
|
902
|
+
const model2 = resolveModel(parsedModel, ts ?? "", modelState);
|
|
903
|
+
accumulate(usage2, model2, ts);
|
|
904
|
+
continue;
|
|
905
|
+
}
|
|
906
|
+
if (type === "event_msg" || payload2?.type === "turn_context") continue;
|
|
907
|
+
const usage = headlessUsage(parsed.obj);
|
|
908
|
+
if (!usage) continue;
|
|
909
|
+
const eventTs = headlessTimestamp(parsed.obj, normalizeTimestamp) ?? await fileMtime();
|
|
910
|
+
const modelTs = headlessTimestamp(parsed.obj, rawOrNormalizedTimestamp) ?? await fileMtime();
|
|
911
|
+
const model = resolveModel(headlessModel(parsed.obj), modelTs, modelState);
|
|
912
|
+
accumulate(usage, model, eventTs);
|
|
767
913
|
}
|
|
768
914
|
return stats;
|
|
769
915
|
}
|
|
770
916
|
async function loadCodexProjects(home, onProgress) {
|
|
771
|
-
const
|
|
772
|
-
const
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
917
|
+
const files = [];
|
|
918
|
+
for (const root of codexHomes(home)) {
|
|
919
|
+
const sources = [];
|
|
920
|
+
for (const dir of ["sessions", "archived_sessions"]) {
|
|
921
|
+
const full = join6(root, dir);
|
|
922
|
+
const ok = await access5(full).then(() => true).catch(() => false);
|
|
923
|
+
if (ok) sources.push(full);
|
|
924
|
+
}
|
|
925
|
+
if (sources.length === 0) sources.push(root);
|
|
926
|
+
const seenRelative = /* @__PURE__ */ new Set();
|
|
927
|
+
for (const source of sources) {
|
|
928
|
+
const found = await glob4(["**/*.jsonl"], { cwd: source, absolute: false }).catch(() => []);
|
|
929
|
+
found.sort();
|
|
930
|
+
for (const rel of found) {
|
|
931
|
+
const key = rel.replaceAll("\\", "/");
|
|
932
|
+
if (seenRelative.has(key)) continue;
|
|
933
|
+
seenRelative.add(key);
|
|
934
|
+
files.push(join6(source, rel));
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
}
|
|
776
938
|
if (files.length === 0) return [];
|
|
777
939
|
const sessions = [];
|
|
778
940
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -790,12 +952,11 @@ var codexAdapter = {
|
|
|
790
952
|
name: "OpenAI Codex",
|
|
791
953
|
supported: true,
|
|
792
954
|
async detect(home) {
|
|
793
|
-
|
|
794
|
-
await access5(join6(
|
|
795
|
-
return true;
|
|
796
|
-
} catch {
|
|
797
|
-
return false;
|
|
955
|
+
for (const root of codexHomes(home)) {
|
|
956
|
+
const ok = await access5(join6(root, "sessions")).then(() => true).catch(() => false);
|
|
957
|
+
if (ok) return true;
|
|
798
958
|
}
|
|
959
|
+
return false;
|
|
799
960
|
},
|
|
800
961
|
loadProjects: loadCodexProjects
|
|
801
962
|
};
|
|
@@ -901,7 +1062,7 @@ var copilotAdapter = {
|
|
|
901
1062
|
};
|
|
902
1063
|
|
|
903
1064
|
// src/agents/droid.ts
|
|
904
|
-
import { access as access7, stat as
|
|
1065
|
+
import { access as access7, stat as stat3 } from "fs/promises";
|
|
905
1066
|
import { homedir as homedir8 } from "os";
|
|
906
1067
|
import { basename as basename2, join as join8 } from "path";
|
|
907
1068
|
import { glob as glob6 } from "tinyglobby";
|
|
@@ -915,7 +1076,7 @@ async function parseFile2(file) {
|
|
|
915
1076
|
let ts = str(settings, "updatedAt") ?? str(settings, "createdAt");
|
|
916
1077
|
if (!ts) {
|
|
917
1078
|
try {
|
|
918
|
-
ts = (await
|
|
1079
|
+
ts = (await stat3(file)).mtime.toISOString();
|
|
919
1080
|
} catch {
|
|
920
1081
|
}
|
|
921
1082
|
}
|
|
@@ -1031,7 +1192,7 @@ import { homedir as homedir10 } from "os";
|
|
|
1031
1192
|
import { join as join10 } from "path";
|
|
1032
1193
|
|
|
1033
1194
|
// src/sqlite.ts
|
|
1034
|
-
import { readFile as
|
|
1195
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
1035
1196
|
function u8(b, o) {
|
|
1036
1197
|
return b[o];
|
|
1037
1198
|
}
|
|
@@ -1171,7 +1332,7 @@ function columnNames(sql) {
|
|
|
1171
1332
|
async function readTable(file, table) {
|
|
1172
1333
|
let buf;
|
|
1173
1334
|
try {
|
|
1174
|
-
buf = await
|
|
1335
|
+
buf = await readFile5(file);
|
|
1175
1336
|
} catch {
|
|
1176
1337
|
return [];
|
|
1177
1338
|
}
|
|
@@ -1499,38 +1660,38 @@ var openclawAdapter = {
|
|
|
1499
1660
|
};
|
|
1500
1661
|
|
|
1501
1662
|
// src/agents/opencode.ts
|
|
1502
|
-
import { access as access14, readFile as
|
|
1663
|
+
import { access as access14, readFile as readFile6 } from "fs/promises";
|
|
1503
1664
|
import { homedir as homedir15 } from "os";
|
|
1504
1665
|
import { join as join15 } from "path";
|
|
1505
1666
|
import { glob as glob10 } from "tinyglobby";
|
|
1506
|
-
import { z
|
|
1507
|
-
var Message =
|
|
1508
|
-
sessionID:
|
|
1509
|
-
role:
|
|
1510
|
-
modelID:
|
|
1511
|
-
providerID:
|
|
1512
|
-
time:
|
|
1513
|
-
tokens:
|
|
1514
|
-
input:
|
|
1515
|
-
output:
|
|
1516
|
-
reasoning:
|
|
1517
|
-
cache:
|
|
1667
|
+
import { z } from "zod";
|
|
1668
|
+
var Message = z.object({
|
|
1669
|
+
sessionID: z.string(),
|
|
1670
|
+
role: z.string(),
|
|
1671
|
+
modelID: z.string().optional(),
|
|
1672
|
+
providerID: z.string().optional(),
|
|
1673
|
+
time: z.object({ created: z.number().optional(), completed: z.number().optional() }).optional(),
|
|
1674
|
+
tokens: z.object({
|
|
1675
|
+
input: z.number().catch(0).default(0),
|
|
1676
|
+
output: z.number().catch(0).default(0),
|
|
1677
|
+
reasoning: z.number().catch(0).default(0),
|
|
1678
|
+
cache: z.object({ read: z.number().catch(0).default(0), write: z.number().catch(0).default(0) }).optional()
|
|
1518
1679
|
}).optional()
|
|
1519
1680
|
});
|
|
1520
|
-
var Session =
|
|
1521
|
-
id:
|
|
1522
|
-
directory:
|
|
1523
|
-
projectID:
|
|
1524
|
-
time:
|
|
1681
|
+
var Session = z.object({
|
|
1682
|
+
id: z.string(),
|
|
1683
|
+
directory: z.string().optional(),
|
|
1684
|
+
projectID: z.string().optional(),
|
|
1685
|
+
time: z.object({ created: z.number().optional() }).optional()
|
|
1525
1686
|
});
|
|
1526
|
-
var Project =
|
|
1687
|
+
var Project = z.object({ id: z.string(), worktree: z.string().optional() });
|
|
1527
1688
|
function opencodeRoot(home) {
|
|
1528
1689
|
if (home) return join15(home, ".local", "share", "opencode");
|
|
1529
1690
|
return process.env.OPENCODE_DATA_DIR ?? join15(homedir15(), ".local", "share", "opencode");
|
|
1530
1691
|
}
|
|
1531
1692
|
async function readJson2(file) {
|
|
1532
1693
|
try {
|
|
1533
|
-
return JSON.parse(await
|
|
1694
|
+
return JSON.parse(await readFile6(file, "utf8"));
|
|
1534
1695
|
} catch {
|
|
1535
1696
|
return void 0;
|
|
1536
1697
|
}
|
package/dist/cli.js
CHANGED
|
@@ -276,7 +276,7 @@ program.action(async () => {
|
|
|
276
276
|
const [{ render }, React, { Root }, { Fullscreen }] = await Promise.all([
|
|
277
277
|
import("ink"),
|
|
278
278
|
import("react"),
|
|
279
|
-
import("./Root-
|
|
279
|
+
import("./Root-HZIVZ2YT.js"),
|
|
280
280
|
import("./Fullscreen-GK2ZYXHV.js")
|
|
281
281
|
]);
|
|
282
282
|
render(React.createElement(Fullscreen, null, React.createElement(Root)));
|