tokmon 0.28.1 → 0.28.2
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/{bootstrap-ink-L7QSJBMS.js → bootstrap-ink-IMT3S5HU.js} +5 -4
- package/dist/{chunk-FMP3P2WV.js → chunk-44ZSQEOS.js} +1 -1
- package/dist/{chunk-S33XIUAW.js → chunk-6ZEW2M6P.js} +158 -30
- package/dist/{chunk-XDA5RJST.js → chunk-J3JW3RFP.js} +9 -6
- package/dist/{chunk-CVKCVHS7.js → chunk-LCAHTRGP.js} +14 -281
- package/dist/{chunk-4HU4EI5T.js → chunk-LKYOWBD4.js} +15 -15
- package/dist/{chunk-3RTWFGGD.js → chunk-M7XMV36F.js} +1 -1
- package/dist/chunk-WUK3MQUB.js +249 -0
- package/dist/{cli-command-75LP4IDS.js → cli-command-DCENRCO3.js} +5 -5
- package/dist/cli.js +5 -5
- package/dist/{daemon-CL4FJW26.js → daemon-6Y4O7NXS.js} +35 -13
- package/dist/{daemon-handle-QQLJE46Y.js → daemon-handle-GVCYVDPO.js} +3 -3
- package/dist/server-GXXOWUVZ.js +11 -0
- package/package.json +1 -1
- package/dist/chunk-SMPY52EV.js +0 -125
- package/dist/server-EUO7CWYH.js +0 -11
|
@@ -739,243 +739,6 @@ function coalesceTables(list) {
|
|
|
739
739
|
return mergeTables(list);
|
|
740
740
|
}
|
|
741
741
|
|
|
742
|
-
// src/rpc/contract.ts
|
|
743
|
-
import { Schema } from "effect";
|
|
744
|
-
import * as Rpc from "effect/unstable/rpc/Rpc";
|
|
745
|
-
import * as RpcGroup from "effect/unstable/rpc/RpcGroup";
|
|
746
|
-
var TOKMON_WS_PATH = "/ws";
|
|
747
|
-
var TOKMON_PROTOCOL_VERSION = 3;
|
|
748
|
-
var TOKMON_CAPABILITIES = ["config-cas", "config-revision", "allowed-hosts"];
|
|
749
|
-
var TOKMON_WS_METHODS = {
|
|
750
|
-
getConfig: "tokmon.getConfig",
|
|
751
|
-
setConfig: "tokmon.setConfig",
|
|
752
|
-
refresh: "tokmon.refresh",
|
|
753
|
-
browseFs: "tokmon.browseFs",
|
|
754
|
-
snapshot: "tokmon.snapshot",
|
|
755
|
-
config: "tokmon.config"
|
|
756
|
-
};
|
|
757
|
-
var RefreshScopeSchema = Schema.Literals([
|
|
758
|
-
"all",
|
|
759
|
-
"summary",
|
|
760
|
-
"table",
|
|
761
|
-
"billing",
|
|
762
|
-
"peak"
|
|
763
|
-
]);
|
|
764
|
-
var ProviderIdSchema = Schema.Literals(PROVIDER_IDS);
|
|
765
|
-
var NonNegativeIntegerSchema = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
766
|
-
var PositiveFiniteSchema = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1));
|
|
767
|
-
var AccountSchema = Schema.Struct({
|
|
768
|
-
id: Schema.String,
|
|
769
|
-
providerId: ProviderIdSchema,
|
|
770
|
-
name: Schema.String,
|
|
771
|
-
homeDir: Schema.String,
|
|
772
|
-
color: Schema.optionalKey(Schema.String)
|
|
773
|
-
});
|
|
774
|
-
var ConfigSchema = Schema.Struct({
|
|
775
|
-
revision: NonNegativeIntegerSchema,
|
|
776
|
-
interval: PositiveFiniteSchema,
|
|
777
|
-
billingInterval: PositiveFiniteSchema,
|
|
778
|
-
clearScreen: Schema.Boolean,
|
|
779
|
-
privacyMode: Schema.Boolean,
|
|
780
|
-
privacyToggleKey: Schema.String,
|
|
781
|
-
timezone: Schema.NullOr(Schema.String),
|
|
782
|
-
accounts: Schema.Array(AccountSchema),
|
|
783
|
-
activeAccountId: Schema.NullOr(Schema.String),
|
|
784
|
-
disabledProviders: Schema.Array(ProviderIdSchema),
|
|
785
|
-
onboarded: Schema.Boolean,
|
|
786
|
-
dashboardLayout: Schema.Literals(["grid", "single"]),
|
|
787
|
-
defaultFocus: Schema.Literals(["all", "last"]),
|
|
788
|
-
ascii: Schema.Literals(["auto", "on", "off"]),
|
|
789
|
-
allowNetworkAccess: Schema.Boolean,
|
|
790
|
-
allowedHosts: Schema.Array(Schema.String),
|
|
791
|
-
resetDisplay: Schema.Literals(["relative", "absolute"]),
|
|
792
|
-
knownProviders: Schema.Array(ProviderIdSchema)
|
|
793
|
-
});
|
|
794
|
-
var ProtocolInfoSchema = Schema.Struct({
|
|
795
|
-
version: Schema.Literal(TOKMON_PROTOCOL_VERSION),
|
|
796
|
-
// Capabilities are additive within a protocol version. Older clients must
|
|
797
|
-
// preserve forward compatibility when a newer daemon advertises one they do
|
|
798
|
-
// not understand yet.
|
|
799
|
-
capabilities: Schema.Array(Schema.String)
|
|
800
|
-
});
|
|
801
|
-
var ConfigStateSchema = Schema.Struct({
|
|
802
|
-
protocol: ProtocolInfoSchema,
|
|
803
|
-
config: ConfigSchema
|
|
804
|
-
});
|
|
805
|
-
var ConfigUpdateRequestSchema = Schema.Struct({
|
|
806
|
-
expectedRevision: NonNegativeIntegerSchema,
|
|
807
|
-
config: ConfigSchema
|
|
808
|
-
});
|
|
809
|
-
var ConfigUpdateConflictSchema = Schema.Struct({
|
|
810
|
-
kind: Schema.Literal("conflict"),
|
|
811
|
-
state: ConfigStateSchema
|
|
812
|
-
});
|
|
813
|
-
var ConfigPersistenceFailureSchema = Schema.Struct({
|
|
814
|
-
kind: Schema.Literal("persistence"),
|
|
815
|
-
message: Schema.String
|
|
816
|
-
});
|
|
817
|
-
var FsEntrySchema = Schema.Struct({
|
|
818
|
-
name: Schema.String,
|
|
819
|
-
path: Schema.String,
|
|
820
|
-
dir: Schema.Boolean
|
|
821
|
-
});
|
|
822
|
-
var FsListingSchema = Schema.Struct({
|
|
823
|
-
path: Schema.String,
|
|
824
|
-
parent: Schema.NullOr(Schema.String),
|
|
825
|
-
entries: Schema.Array(FsEntrySchema)
|
|
826
|
-
});
|
|
827
|
-
var UsageSummarySchema = Schema.Struct({
|
|
828
|
-
cost: Schema.Finite,
|
|
829
|
-
tokens: Schema.Finite,
|
|
830
|
-
input: Schema.Finite,
|
|
831
|
-
cacheRead: Schema.Finite,
|
|
832
|
-
cacheSavings: Schema.Finite
|
|
833
|
-
});
|
|
834
|
-
var ModelDetailSchema = Schema.Struct({
|
|
835
|
-
name: Schema.String,
|
|
836
|
-
input: Schema.Finite,
|
|
837
|
-
output: Schema.Finite,
|
|
838
|
-
cacheCreate: Schema.Finite,
|
|
839
|
-
cacheRead: Schema.Finite,
|
|
840
|
-
cacheSavings: Schema.Finite,
|
|
841
|
-
cost: Schema.Finite,
|
|
842
|
-
count: Schema.Finite
|
|
843
|
-
});
|
|
844
|
-
var TableRowSchema = Schema.Struct({
|
|
845
|
-
label: Schema.String,
|
|
846
|
-
models: Schema.Array(Schema.String),
|
|
847
|
-
input: Schema.Finite,
|
|
848
|
-
output: Schema.Finite,
|
|
849
|
-
cacheCreate: Schema.Finite,
|
|
850
|
-
cacheRead: Schema.Finite,
|
|
851
|
-
cacheSavings: Schema.Finite,
|
|
852
|
-
total: Schema.Finite,
|
|
853
|
-
cost: Schema.Finite,
|
|
854
|
-
count: Schema.Finite,
|
|
855
|
-
breakdown: Schema.Array(ModelDetailSchema)
|
|
856
|
-
});
|
|
857
|
-
var DashboardDataSchema = Schema.Struct({
|
|
858
|
-
today: UsageSummarySchema,
|
|
859
|
-
week: UsageSummarySchema,
|
|
860
|
-
month: UsageSummarySchema,
|
|
861
|
-
burnRate: Schema.Finite,
|
|
862
|
-
series: Schema.Array(Schema.Finite)
|
|
863
|
-
});
|
|
864
|
-
var TableDataSchema = Schema.Struct({
|
|
865
|
-
daily: Schema.Array(TableRowSchema),
|
|
866
|
-
weekly: Schema.Array(TableRowSchema),
|
|
867
|
-
monthly: Schema.Array(TableRowSchema)
|
|
868
|
-
});
|
|
869
|
-
var MetricFormatSchema = Schema.Union([
|
|
870
|
-
Schema.Struct({ kind: Schema.Literal("percent") }),
|
|
871
|
-
Schema.Struct({ kind: Schema.Literal("dollars"), currency: Schema.optionalKey(Schema.String) }),
|
|
872
|
-
Schema.Struct({ kind: Schema.Literal("count"), suffix: Schema.optionalKey(Schema.String) })
|
|
873
|
-
]);
|
|
874
|
-
var MetricSchema = Schema.Struct({
|
|
875
|
-
label: Schema.String,
|
|
876
|
-
used: Schema.Finite,
|
|
877
|
-
limit: Schema.NullOr(Schema.Finite),
|
|
878
|
-
format: MetricFormatSchema,
|
|
879
|
-
resetsAt: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
880
|
-
primary: Schema.optionalKey(Schema.Boolean)
|
|
881
|
-
});
|
|
882
|
-
var BillingResultSchema = Schema.Struct({
|
|
883
|
-
plan: Schema.NullOr(Schema.String),
|
|
884
|
-
metrics: Schema.Array(MetricSchema),
|
|
885
|
-
error: Schema.NullOr(Schema.String),
|
|
886
|
-
email: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
887
|
-
displayName: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
888
|
-
activity: Schema.optionalKey(Schema.NullOr(Schema.Struct({
|
|
889
|
-
series: Schema.Array(Schema.Finite),
|
|
890
|
-
summary: Schema.String
|
|
891
|
-
}))),
|
|
892
|
-
modelSpend: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Struct({
|
|
893
|
-
name: Schema.String,
|
|
894
|
-
usd: Schema.Finite,
|
|
895
|
-
requests: Schema.Finite
|
|
896
|
-
})))),
|
|
897
|
-
asOfMs: Schema.optionalKey(Schema.Finite)
|
|
898
|
-
});
|
|
899
|
-
var WebAccountSchema = Schema.Struct({
|
|
900
|
-
id: Schema.String,
|
|
901
|
-
providerId: ProviderIdSchema,
|
|
902
|
-
name: Schema.String,
|
|
903
|
-
color: Schema.String,
|
|
904
|
-
homeDir: Schema.NullOr(Schema.String),
|
|
905
|
-
hasUsage: Schema.Boolean,
|
|
906
|
-
hasBilling: Schema.Boolean,
|
|
907
|
-
email: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
908
|
-
displayName: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
909
|
-
plan: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
910
|
-
dashboard: Schema.NullOr(DashboardDataSchema),
|
|
911
|
-
table: Schema.NullOr(TableDataSchema),
|
|
912
|
-
billing: Schema.NullOr(BillingResultSchema),
|
|
913
|
-
summaryState: Schema.Literals(["pending", "ready", "error"]),
|
|
914
|
-
billingState: Schema.Literals(["pending", "ready", "error"]),
|
|
915
|
-
tableState: Schema.Literals(["pending", "ready", "error"]),
|
|
916
|
-
summaryUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema)),
|
|
917
|
-
billingUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema)),
|
|
918
|
-
tableUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema))
|
|
919
|
-
});
|
|
920
|
-
var WebSnapshotSchema = Schema.Struct({
|
|
921
|
-
version: Schema.String,
|
|
922
|
-
generatedAt: NonNegativeIntegerSchema,
|
|
923
|
-
tz: Schema.String,
|
|
924
|
-
intervalMs: PositiveFiniteSchema,
|
|
925
|
-
billingIntervalMs: Schema.optionalKey(PositiveFiniteSchema),
|
|
926
|
-
providers: Schema.Array(Schema.Struct({
|
|
927
|
-
id: ProviderIdSchema,
|
|
928
|
-
name: Schema.String,
|
|
929
|
-
color: Schema.String
|
|
930
|
-
})),
|
|
931
|
-
accounts: Schema.Array(WebAccountSchema),
|
|
932
|
-
seeded: Schema.Boolean,
|
|
933
|
-
peak: Schema.NullOr(Schema.Struct({
|
|
934
|
-
state: Schema.Literals(["peak", "off-peak", "weekend"]),
|
|
935
|
-
label: Schema.String,
|
|
936
|
-
// The upstream clock is only normalized to a finite number; do not make
|
|
937
|
-
// the wire contract narrower than the producer's declared type.
|
|
938
|
-
minutesUntilChange: Schema.NullOr(Schema.Finite),
|
|
939
|
-
changesAt: Schema.optionalKey(Schema.NullOr(Schema.String))
|
|
940
|
-
}))
|
|
941
|
-
});
|
|
942
|
-
var EmptyPayloadSchema = Schema.Struct({});
|
|
943
|
-
var GetConfigRpc = Rpc.make(TOKMON_WS_METHODS.getConfig, {
|
|
944
|
-
payload: EmptyPayloadSchema,
|
|
945
|
-
success: ConfigStateSchema
|
|
946
|
-
});
|
|
947
|
-
var SetConfigRpc = Rpc.make(TOKMON_WS_METHODS.setConfig, {
|
|
948
|
-
payload: ConfigUpdateRequestSchema,
|
|
949
|
-
success: ConfigStateSchema,
|
|
950
|
-
error: Schema.Union([ConfigUpdateConflictSchema, ConfigPersistenceFailureSchema])
|
|
951
|
-
});
|
|
952
|
-
var RefreshRpc = Rpc.make(TOKMON_WS_METHODS.refresh, {
|
|
953
|
-
payload: Schema.Struct({ scope: RefreshScopeSchema }),
|
|
954
|
-
success: Schema.Void
|
|
955
|
-
});
|
|
956
|
-
var BrowseFsRpc = Rpc.make(TOKMON_WS_METHODS.browseFs, {
|
|
957
|
-
payload: Schema.Struct({ path: Schema.String }),
|
|
958
|
-
success: FsListingSchema
|
|
959
|
-
});
|
|
960
|
-
var SnapshotRpc = Rpc.make(TOKMON_WS_METHODS.snapshot, {
|
|
961
|
-
payload: EmptyPayloadSchema,
|
|
962
|
-
success: WebSnapshotSchema,
|
|
963
|
-
stream: true
|
|
964
|
-
});
|
|
965
|
-
var ConfigRpc = Rpc.make(TOKMON_WS_METHODS.config, {
|
|
966
|
-
payload: EmptyPayloadSchema,
|
|
967
|
-
success: ConfigStateSchema,
|
|
968
|
-
stream: true
|
|
969
|
-
});
|
|
970
|
-
var TokmonRpcGroup = RpcGroup.make(
|
|
971
|
-
GetConfigRpc,
|
|
972
|
-
SetConfigRpc,
|
|
973
|
-
RefreshRpc,
|
|
974
|
-
BrowseFsRpc,
|
|
975
|
-
SnapshotRpc,
|
|
976
|
-
ConfigRpc
|
|
977
|
-
);
|
|
978
|
-
|
|
979
742
|
// src/shared/format.ts
|
|
980
743
|
var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
981
744
|
function formatCurrency(value, opts = {}) {
|
|
@@ -1727,13 +1490,14 @@ function timestampSecond(value) {
|
|
|
1727
1490
|
const ts = timestampMs(value);
|
|
1728
1491
|
return ts === null ? null : new Date(ts).toISOString().slice(0, 19);
|
|
1729
1492
|
}
|
|
1730
|
-
async function
|
|
1493
|
+
async function hasForkedHistory(path) {
|
|
1731
1494
|
let handle = null;
|
|
1732
1495
|
try {
|
|
1733
1496
|
handle = await openFile(path, "r");
|
|
1734
1497
|
const buffer = Buffer.alloc(16 * 1024);
|
|
1735
1498
|
const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
|
|
1736
|
-
|
|
1499
|
+
const prefix = buffer.subarray(0, bytesRead).toString("utf8");
|
|
1500
|
+
return prefix.includes("thread_spawn") && /"forked_from_id"\s*:\s*"[^"]+"/.test(prefix);
|
|
1737
1501
|
} catch {
|
|
1738
1502
|
return false;
|
|
1739
1503
|
} finally {
|
|
@@ -1741,32 +1505,11 @@ async function hasThreadSpawn(path) {
|
|
|
1741
1505
|
});
|
|
1742
1506
|
}
|
|
1743
1507
|
}
|
|
1744
|
-
|
|
1745
|
-
if (
|
|
1746
|
-
|
|
1747
|
-
const
|
|
1748
|
-
|
|
1749
|
-
});
|
|
1750
|
-
const rl = createInterface2({ input, crlfDelay: Infinity });
|
|
1751
|
-
try {
|
|
1752
|
-
for await (const rawLine of rl) {
|
|
1753
|
-
if (!rawLine.includes("token_count")) continue;
|
|
1754
|
-
try {
|
|
1755
|
-
const line = rawLine.charCodeAt(0) === 65279 ? rawLine.slice(1) : rawLine;
|
|
1756
|
-
const obj = JSON.parse(line);
|
|
1757
|
-
if ((obj?.payload?.type ?? obj?.type) !== "token_count") continue;
|
|
1758
|
-
const info = obj?.payload?.info;
|
|
1759
|
-
if (!normalizeUsage(info?.last_token_usage) && !normalizeUsage(info?.total_token_usage)) continue;
|
|
1760
|
-
const second = timestampSecond(obj.timestamp ?? obj?.payload?.timestamp);
|
|
1761
|
-
if (!second) continue;
|
|
1762
|
-
if (!first) first = second;
|
|
1763
|
-
else return first === second ? second : null;
|
|
1764
|
-
} catch {
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
} catch {
|
|
1768
|
-
}
|
|
1769
|
-
return null;
|
|
1508
|
+
function isLiveTaskStart(obj) {
|
|
1509
|
+
if ((obj?.payload?.type ?? obj?.type) !== "task_started") return false;
|
|
1510
|
+
const eventSecond = timestampSecond(obj?.timestamp ?? obj?.payload?.timestamp);
|
|
1511
|
+
const startedSecond = timestampSecond(obj?.payload?.started_at);
|
|
1512
|
+
return eventSecond !== null && eventSecond === startedSecond;
|
|
1770
1513
|
}
|
|
1771
1514
|
function findUsage(obj) {
|
|
1772
1515
|
return normalizeUsage(obj?.usage) ?? normalizeUsage(obj?.payload?.usage) ?? normalizeUsage(obj?.payload?.info?.usage) ?? normalizeUsage(obj?.result?.usage) ?? normalizeUsage(obj?.response?.usage) ?? normalizeUsage(obj?.token_usage) ?? normalizeUsage(obj);
|
|
@@ -1779,19 +1522,22 @@ async function parseFile2(path) {
|
|
|
1779
1522
|
let model = "gpt-5";
|
|
1780
1523
|
let prevTotal = null;
|
|
1781
1524
|
let prevSig = null;
|
|
1782
|
-
|
|
1783
|
-
let skipReplay = replaySecond !== null;
|
|
1525
|
+
let skipReplay = await hasForkedHistory(path);
|
|
1784
1526
|
const input = createReadStream2(path);
|
|
1785
1527
|
input.on("error", () => {
|
|
1786
1528
|
});
|
|
1787
1529
|
const rl = createInterface2({ input, crlfDelay: Infinity });
|
|
1788
1530
|
try {
|
|
1789
1531
|
for await (const rawLine of rl) {
|
|
1790
|
-
if (!rawLine.includes("token_count") && !rawLine.includes("turn_context") && !rawLine.includes('"usage"') && !rawLine.includes("input_tokens") && !rawLine.includes("prompt_tokens")) continue;
|
|
1532
|
+
if (!rawLine.includes("token_count") && !rawLine.includes("task_started") && !rawLine.includes("turn_context") && !rawLine.includes('"usage"') && !rawLine.includes("input_tokens") && !rawLine.includes("prompt_tokens")) continue;
|
|
1791
1533
|
try {
|
|
1792
1534
|
const line = rawLine.charCodeAt(0) === 65279 ? rawLine.slice(1) : rawLine;
|
|
1793
1535
|
const obj = JSON.parse(line);
|
|
1794
1536
|
const payloadType = obj?.payload?.type ?? obj?.type;
|
|
1537
|
+
if (skipReplay) {
|
|
1538
|
+
if (isLiveTaskStart(obj)) skipReplay = false;
|
|
1539
|
+
continue;
|
|
1540
|
+
}
|
|
1795
1541
|
if (payloadType === "turn_context") {
|
|
1796
1542
|
const m2 = extractModel(obj);
|
|
1797
1543
|
if (typeof m2 === "string" && m2.trim()) model = m2;
|
|
@@ -1827,14 +1573,6 @@ async function parseFile2(path) {
|
|
|
1827
1573
|
const total = normalizeUsage(info?.total_token_usage);
|
|
1828
1574
|
const last = normalizeUsage(info?.last_token_usage);
|
|
1829
1575
|
const tsValue = obj.timestamp ?? obj?.payload?.timestamp;
|
|
1830
|
-
if (skipReplay && replaySecond) {
|
|
1831
|
-
const second = timestampSecond(tsValue);
|
|
1832
|
-
if (second === replaySecond) {
|
|
1833
|
-
if (total) prevTotal = total;
|
|
1834
|
-
continue;
|
|
1835
|
-
}
|
|
1836
|
-
if (second) skipReplay = false;
|
|
1837
|
-
}
|
|
1838
1576
|
const sig = eventSig(last, total);
|
|
1839
1577
|
if (sig === prevSig) continue;
|
|
1840
1578
|
prevSig = sig;
|
|
@@ -4622,11 +4360,6 @@ async function detectProviders() {
|
|
|
4622
4360
|
}
|
|
4623
4361
|
|
|
4624
4362
|
export {
|
|
4625
|
-
TOKMON_WS_PATH,
|
|
4626
|
-
TOKMON_PROTOCOL_VERSION,
|
|
4627
|
-
TOKMON_CAPABILITIES,
|
|
4628
|
-
TOKMON_WS_METHODS,
|
|
4629
|
-
TokmonRpcGroup,
|
|
4630
4363
|
withTimeout,
|
|
4631
4364
|
systemTimezone,
|
|
4632
4365
|
resolveTimezone,
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
readLock,
|
|
6
6
|
reclaimDeadLock,
|
|
7
7
|
verifyLock
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-J3JW3RFP.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
} from "./chunk-
|
|
10
|
+
TOKMON_PROTOCOL_VERSION
|
|
11
|
+
} from "./chunk-WUK3MQUB.js";
|
|
12
12
|
|
|
13
13
|
// src/client/daemon-handle.ts
|
|
14
14
|
import { spawn } from "child_process";
|
|
@@ -37,7 +37,7 @@ function runtimeExecArgv(entry, override) {
|
|
|
37
37
|
function parseHandshake(line) {
|
|
38
38
|
try {
|
|
39
39
|
const value = JSON.parse(line);
|
|
40
|
-
return value?.ready === 1 && typeof value.url === "string" && typeof value.wsToken === "string" && typeof value.version === "string" ? value : null;
|
|
40
|
+
return value?.ready === 1 && typeof value.url === "string" && typeof value.wsToken === "string" && typeof value.version === "string" && typeof value.protocolVersion === "number" && Array.isArray(value.capabilities) && value.capabilities.every((capability) => typeof capability === "string") && (value.ownerKind === "cli" || value.ownerKind === "desktop") ? value : null;
|
|
41
41
|
} catch {
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
@@ -46,18 +46,18 @@ function connected(url) {
|
|
|
46
46
|
return { kind: "spawned", baseUrl: url, stop: () => {
|
|
47
47
|
} };
|
|
48
48
|
}
|
|
49
|
-
async function attach(opts,
|
|
50
|
-
const lock = await verifyLock(readLock(opts),
|
|
49
|
+
async function attach(opts, protocolVersion) {
|
|
50
|
+
const lock = await verifyLock(readLock(opts), protocolVersion);
|
|
51
51
|
return lock ? connected(lock.url) : null;
|
|
52
52
|
}
|
|
53
53
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
54
|
-
async function retireIncompatibleDaemon(opts,
|
|
54
|
+
async function retireIncompatibleDaemon(opts, protocolVersion, timeoutMs) {
|
|
55
55
|
const lock = readLock(opts);
|
|
56
|
-
if (!lock || lock.state !== "ready" || lock.
|
|
56
|
+
if (!lock || lock.state !== "ready" || lock.protocolVersion === protocolVersion || lock.ownerKind === "desktop" || lock.pid === process.pid || !isAlive(lock.pid)) return;
|
|
57
57
|
const authenticated = await probeHealth(
|
|
58
58
|
lock.url,
|
|
59
59
|
lock.wsToken,
|
|
60
|
-
lock
|
|
60
|
+
lock,
|
|
61
61
|
Math.min(1e3, timeoutMs)
|
|
62
62
|
);
|
|
63
63
|
if (!authenticated) return;
|
|
@@ -79,12 +79,12 @@ async function retireIncompatibleDaemon(opts, version, timeoutMs) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
async function attachOrSpawn(opts = {}) {
|
|
82
|
-
const
|
|
82
|
+
const protocolVersion = TOKMON_PROTOCOL_VERSION;
|
|
83
83
|
const timeoutMs = opts.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;
|
|
84
|
-
const existing = await attach(opts,
|
|
84
|
+
const existing = await attach(opts, protocolVersion);
|
|
85
85
|
if (existing) return existing;
|
|
86
|
-
await retireIncompatibleDaemon(opts,
|
|
87
|
-
const upgraded = await attach(opts,
|
|
86
|
+
await retireIncompatibleDaemon(opts, protocolVersion, timeoutMs);
|
|
87
|
+
const upgraded = await attach(opts, protocolVersion);
|
|
88
88
|
if (upgraded) return upgraded;
|
|
89
89
|
const entry = opts.entry ?? process.argv[1];
|
|
90
90
|
if (!entry) return degraded();
|
|
@@ -117,7 +117,7 @@ async function attachOrSpawn(opts = {}) {
|
|
|
117
117
|
resolve(handle);
|
|
118
118
|
};
|
|
119
119
|
const tryAttach = (final = false) => {
|
|
120
|
-
void attach(opts,
|
|
120
|
+
void attach(opts, protocolVersion).then((found) => {
|
|
121
121
|
if (found) {
|
|
122
122
|
finish(found);
|
|
123
123
|
return;
|
|
@@ -143,7 +143,7 @@ async function attachOrSpawn(opts = {}) {
|
|
|
143
143
|
const line = stdout.slice(0, newline).trim();
|
|
144
144
|
stdout = stdout.slice(newline + 1);
|
|
145
145
|
const handshake = parseHandshake(line);
|
|
146
|
-
if (!handshake || handshake.
|
|
146
|
+
if (!handshake || handshake.protocolVersion !== protocolVersion) continue;
|
|
147
147
|
tryAttach();
|
|
148
148
|
return;
|
|
149
149
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
TOKMON_WS_METHODS,
|
|
4
4
|
TOKMON_WS_PATH,
|
|
5
5
|
TokmonRpcGroup
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WUK3MQUB.js";
|
|
7
7
|
|
|
8
8
|
// src/client/daemon-rpc-client.ts
|
|
9
9
|
import { Cause, Context, Duration, Effect, Exit, Fiber, Layer, ManagedRuntime, Schedule, Stream } from "effect";
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
PROVIDER_IDS
|
|
4
|
+
} from "./chunk-HP5UZCXP.js";
|
|
5
|
+
|
|
6
|
+
// src/rpc/contract.ts
|
|
7
|
+
import { Schema } from "effect";
|
|
8
|
+
import * as Rpc from "effect/unstable/rpc/Rpc";
|
|
9
|
+
import * as RpcGroup from "effect/unstable/rpc/RpcGroup";
|
|
10
|
+
var TOKMON_WS_PATH = "/ws";
|
|
11
|
+
var TOKMON_PROTOCOL_VERSION = 3;
|
|
12
|
+
var TOKMON_CAPABILITIES = ["config-cas", "config-revision", "allowed-hosts"];
|
|
13
|
+
var TOKMON_WS_METHODS = {
|
|
14
|
+
getConfig: "tokmon.getConfig",
|
|
15
|
+
setConfig: "tokmon.setConfig",
|
|
16
|
+
refresh: "tokmon.refresh",
|
|
17
|
+
browseFs: "tokmon.browseFs",
|
|
18
|
+
snapshot: "tokmon.snapshot",
|
|
19
|
+
config: "tokmon.config"
|
|
20
|
+
};
|
|
21
|
+
var RefreshScopeSchema = Schema.Literals([
|
|
22
|
+
"all",
|
|
23
|
+
"summary",
|
|
24
|
+
"table",
|
|
25
|
+
"billing",
|
|
26
|
+
"peak"
|
|
27
|
+
]);
|
|
28
|
+
var ProviderIdSchema = Schema.Literals(PROVIDER_IDS);
|
|
29
|
+
var NonNegativeIntegerSchema = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
30
|
+
var PositiveFiniteSchema = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(1));
|
|
31
|
+
var AccountSchema = Schema.Struct({
|
|
32
|
+
id: Schema.String,
|
|
33
|
+
providerId: ProviderIdSchema,
|
|
34
|
+
name: Schema.String,
|
|
35
|
+
homeDir: Schema.String,
|
|
36
|
+
color: Schema.optionalKey(Schema.String)
|
|
37
|
+
});
|
|
38
|
+
var ConfigSchema = Schema.Struct({
|
|
39
|
+
revision: NonNegativeIntegerSchema,
|
|
40
|
+
interval: PositiveFiniteSchema,
|
|
41
|
+
billingInterval: PositiveFiniteSchema,
|
|
42
|
+
clearScreen: Schema.Boolean,
|
|
43
|
+
privacyMode: Schema.Boolean,
|
|
44
|
+
privacyToggleKey: Schema.String,
|
|
45
|
+
timezone: Schema.NullOr(Schema.String),
|
|
46
|
+
accounts: Schema.Array(AccountSchema),
|
|
47
|
+
activeAccountId: Schema.NullOr(Schema.String),
|
|
48
|
+
disabledProviders: Schema.Array(ProviderIdSchema),
|
|
49
|
+
onboarded: Schema.Boolean,
|
|
50
|
+
dashboardLayout: Schema.Literals(["grid", "single"]),
|
|
51
|
+
defaultFocus: Schema.Literals(["all", "last"]),
|
|
52
|
+
ascii: Schema.Literals(["auto", "on", "off"]),
|
|
53
|
+
allowNetworkAccess: Schema.Boolean,
|
|
54
|
+
allowedHosts: Schema.Array(Schema.String),
|
|
55
|
+
resetDisplay: Schema.Literals(["relative", "absolute"]),
|
|
56
|
+
knownProviders: Schema.Array(ProviderIdSchema)
|
|
57
|
+
});
|
|
58
|
+
var ProtocolInfoSchema = Schema.Struct({
|
|
59
|
+
version: Schema.Literal(TOKMON_PROTOCOL_VERSION),
|
|
60
|
+
// Capabilities are additive within a protocol version. Older clients must
|
|
61
|
+
// preserve forward compatibility when a newer daemon advertises one they do
|
|
62
|
+
// not understand yet.
|
|
63
|
+
capabilities: Schema.Array(Schema.String)
|
|
64
|
+
});
|
|
65
|
+
var ConfigStateSchema = Schema.Struct({
|
|
66
|
+
protocol: ProtocolInfoSchema,
|
|
67
|
+
config: ConfigSchema
|
|
68
|
+
});
|
|
69
|
+
var ConfigUpdateRequestSchema = Schema.Struct({
|
|
70
|
+
expectedRevision: NonNegativeIntegerSchema,
|
|
71
|
+
config: ConfigSchema
|
|
72
|
+
});
|
|
73
|
+
var ConfigUpdateConflictSchema = Schema.Struct({
|
|
74
|
+
kind: Schema.Literal("conflict"),
|
|
75
|
+
state: ConfigStateSchema
|
|
76
|
+
});
|
|
77
|
+
var ConfigPersistenceFailureSchema = Schema.Struct({
|
|
78
|
+
kind: Schema.Literal("persistence"),
|
|
79
|
+
message: Schema.String
|
|
80
|
+
});
|
|
81
|
+
var FsEntrySchema = Schema.Struct({
|
|
82
|
+
name: Schema.String,
|
|
83
|
+
path: Schema.String,
|
|
84
|
+
dir: Schema.Boolean
|
|
85
|
+
});
|
|
86
|
+
var FsListingSchema = Schema.Struct({
|
|
87
|
+
path: Schema.String,
|
|
88
|
+
parent: Schema.NullOr(Schema.String),
|
|
89
|
+
entries: Schema.Array(FsEntrySchema)
|
|
90
|
+
});
|
|
91
|
+
var UsageSummarySchema = Schema.Struct({
|
|
92
|
+
cost: Schema.Finite,
|
|
93
|
+
tokens: Schema.Finite,
|
|
94
|
+
input: Schema.Finite,
|
|
95
|
+
cacheRead: Schema.Finite,
|
|
96
|
+
cacheSavings: Schema.Finite
|
|
97
|
+
});
|
|
98
|
+
var ModelDetailSchema = Schema.Struct({
|
|
99
|
+
name: Schema.String,
|
|
100
|
+
input: Schema.Finite,
|
|
101
|
+
output: Schema.Finite,
|
|
102
|
+
cacheCreate: Schema.Finite,
|
|
103
|
+
cacheRead: Schema.Finite,
|
|
104
|
+
cacheSavings: Schema.Finite,
|
|
105
|
+
cost: Schema.Finite,
|
|
106
|
+
count: Schema.Finite
|
|
107
|
+
});
|
|
108
|
+
var TableRowSchema = Schema.Struct({
|
|
109
|
+
label: Schema.String,
|
|
110
|
+
models: Schema.Array(Schema.String),
|
|
111
|
+
input: Schema.Finite,
|
|
112
|
+
output: Schema.Finite,
|
|
113
|
+
cacheCreate: Schema.Finite,
|
|
114
|
+
cacheRead: Schema.Finite,
|
|
115
|
+
cacheSavings: Schema.Finite,
|
|
116
|
+
total: Schema.Finite,
|
|
117
|
+
cost: Schema.Finite,
|
|
118
|
+
count: Schema.Finite,
|
|
119
|
+
breakdown: Schema.Array(ModelDetailSchema)
|
|
120
|
+
});
|
|
121
|
+
var DashboardDataSchema = Schema.Struct({
|
|
122
|
+
today: UsageSummarySchema,
|
|
123
|
+
week: UsageSummarySchema,
|
|
124
|
+
month: UsageSummarySchema,
|
|
125
|
+
burnRate: Schema.Finite,
|
|
126
|
+
series: Schema.Array(Schema.Finite)
|
|
127
|
+
});
|
|
128
|
+
var TableDataSchema = Schema.Struct({
|
|
129
|
+
daily: Schema.Array(TableRowSchema),
|
|
130
|
+
weekly: Schema.Array(TableRowSchema),
|
|
131
|
+
monthly: Schema.Array(TableRowSchema)
|
|
132
|
+
});
|
|
133
|
+
var MetricFormatSchema = Schema.Union([
|
|
134
|
+
Schema.Struct({ kind: Schema.Literal("percent") }),
|
|
135
|
+
Schema.Struct({ kind: Schema.Literal("dollars"), currency: Schema.optionalKey(Schema.String) }),
|
|
136
|
+
Schema.Struct({ kind: Schema.Literal("count"), suffix: Schema.optionalKey(Schema.String) })
|
|
137
|
+
]);
|
|
138
|
+
var MetricSchema = Schema.Struct({
|
|
139
|
+
label: Schema.String,
|
|
140
|
+
used: Schema.Finite,
|
|
141
|
+
limit: Schema.NullOr(Schema.Finite),
|
|
142
|
+
format: MetricFormatSchema,
|
|
143
|
+
resetsAt: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
144
|
+
primary: Schema.optionalKey(Schema.Boolean)
|
|
145
|
+
});
|
|
146
|
+
var BillingResultSchema = Schema.Struct({
|
|
147
|
+
plan: Schema.NullOr(Schema.String),
|
|
148
|
+
metrics: Schema.Array(MetricSchema),
|
|
149
|
+
error: Schema.NullOr(Schema.String),
|
|
150
|
+
email: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
151
|
+
displayName: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
152
|
+
activity: Schema.optionalKey(Schema.NullOr(Schema.Struct({
|
|
153
|
+
series: Schema.Array(Schema.Finite),
|
|
154
|
+
summary: Schema.String
|
|
155
|
+
}))),
|
|
156
|
+
modelSpend: Schema.optionalKey(Schema.NullOr(Schema.Array(Schema.Struct({
|
|
157
|
+
name: Schema.String,
|
|
158
|
+
usd: Schema.Finite,
|
|
159
|
+
requests: Schema.Finite
|
|
160
|
+
})))),
|
|
161
|
+
asOfMs: Schema.optionalKey(Schema.Finite)
|
|
162
|
+
});
|
|
163
|
+
var WebAccountSchema = Schema.Struct({
|
|
164
|
+
id: Schema.String,
|
|
165
|
+
providerId: ProviderIdSchema,
|
|
166
|
+
name: Schema.String,
|
|
167
|
+
color: Schema.String,
|
|
168
|
+
homeDir: Schema.NullOr(Schema.String),
|
|
169
|
+
hasUsage: Schema.Boolean,
|
|
170
|
+
hasBilling: Schema.Boolean,
|
|
171
|
+
email: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
172
|
+
displayName: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
173
|
+
plan: Schema.optionalKey(Schema.NullOr(Schema.String)),
|
|
174
|
+
dashboard: Schema.NullOr(DashboardDataSchema),
|
|
175
|
+
table: Schema.NullOr(TableDataSchema),
|
|
176
|
+
billing: Schema.NullOr(BillingResultSchema),
|
|
177
|
+
summaryState: Schema.Literals(["pending", "ready", "error"]),
|
|
178
|
+
billingState: Schema.Literals(["pending", "ready", "error"]),
|
|
179
|
+
tableState: Schema.Literals(["pending", "ready", "error"]),
|
|
180
|
+
summaryUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema)),
|
|
181
|
+
billingUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema)),
|
|
182
|
+
tableUpdatedAt: Schema.optionalKey(Schema.NullOr(NonNegativeIntegerSchema))
|
|
183
|
+
});
|
|
184
|
+
var WebSnapshotSchema = Schema.Struct({
|
|
185
|
+
version: Schema.String,
|
|
186
|
+
generatedAt: NonNegativeIntegerSchema,
|
|
187
|
+
tz: Schema.String,
|
|
188
|
+
intervalMs: PositiveFiniteSchema,
|
|
189
|
+
billingIntervalMs: Schema.optionalKey(PositiveFiniteSchema),
|
|
190
|
+
providers: Schema.Array(Schema.Struct({
|
|
191
|
+
id: ProviderIdSchema,
|
|
192
|
+
name: Schema.String,
|
|
193
|
+
color: Schema.String
|
|
194
|
+
})),
|
|
195
|
+
accounts: Schema.Array(WebAccountSchema),
|
|
196
|
+
seeded: Schema.Boolean,
|
|
197
|
+
peak: Schema.NullOr(Schema.Struct({
|
|
198
|
+
state: Schema.Literals(["peak", "off-peak", "weekend"]),
|
|
199
|
+
label: Schema.String,
|
|
200
|
+
// The upstream clock is only normalized to a finite number; do not make
|
|
201
|
+
// the wire contract narrower than the producer's declared type.
|
|
202
|
+
minutesUntilChange: Schema.NullOr(Schema.Finite),
|
|
203
|
+
changesAt: Schema.optionalKey(Schema.NullOr(Schema.String))
|
|
204
|
+
}))
|
|
205
|
+
});
|
|
206
|
+
var EmptyPayloadSchema = Schema.Struct({});
|
|
207
|
+
var GetConfigRpc = Rpc.make(TOKMON_WS_METHODS.getConfig, {
|
|
208
|
+
payload: EmptyPayloadSchema,
|
|
209
|
+
success: ConfigStateSchema
|
|
210
|
+
});
|
|
211
|
+
var SetConfigRpc = Rpc.make(TOKMON_WS_METHODS.setConfig, {
|
|
212
|
+
payload: ConfigUpdateRequestSchema,
|
|
213
|
+
success: ConfigStateSchema,
|
|
214
|
+
error: Schema.Union([ConfigUpdateConflictSchema, ConfigPersistenceFailureSchema])
|
|
215
|
+
});
|
|
216
|
+
var RefreshRpc = Rpc.make(TOKMON_WS_METHODS.refresh, {
|
|
217
|
+
payload: Schema.Struct({ scope: RefreshScopeSchema }),
|
|
218
|
+
success: Schema.Void
|
|
219
|
+
});
|
|
220
|
+
var BrowseFsRpc = Rpc.make(TOKMON_WS_METHODS.browseFs, {
|
|
221
|
+
payload: Schema.Struct({ path: Schema.String }),
|
|
222
|
+
success: FsListingSchema
|
|
223
|
+
});
|
|
224
|
+
var SnapshotRpc = Rpc.make(TOKMON_WS_METHODS.snapshot, {
|
|
225
|
+
payload: EmptyPayloadSchema,
|
|
226
|
+
success: WebSnapshotSchema,
|
|
227
|
+
stream: true
|
|
228
|
+
});
|
|
229
|
+
var ConfigRpc = Rpc.make(TOKMON_WS_METHODS.config, {
|
|
230
|
+
payload: EmptyPayloadSchema,
|
|
231
|
+
success: ConfigStateSchema,
|
|
232
|
+
stream: true
|
|
233
|
+
});
|
|
234
|
+
var TokmonRpcGroup = RpcGroup.make(
|
|
235
|
+
GetConfigRpc,
|
|
236
|
+
SetConfigRpc,
|
|
237
|
+
RefreshRpc,
|
|
238
|
+
BrowseFsRpc,
|
|
239
|
+
SnapshotRpc,
|
|
240
|
+
ConfigRpc
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
export {
|
|
244
|
+
TOKMON_WS_PATH,
|
|
245
|
+
TOKMON_PROTOCOL_VERSION,
|
|
246
|
+
TOKMON_CAPABILITIES,
|
|
247
|
+
TOKMON_WS_METHODS,
|
|
248
|
+
TokmonRpcGroup
|
|
249
|
+
};
|