@tech-leads-club/harness-toolkit 0.3.2 → 0.3.4
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/bin/tlc-build.mjs +15 -29
- package/bin/tlc-cli.ts +99 -3
- package/dist/compact-before.mjs +7961 -13
- package/dist/doctor.mjs +8480 -33
- package/dist/help-topic.mjs +14 -6
- package/dist/init-project.mjs +793 -36
- package/dist/install-runtime.mjs +7268 -17
- package/dist/lessons-cli.mjs +7044 -26
- package/dist/obs-cli.mjs +7037 -27
- package/dist/price-lookup.mjs +201 -11
- package/dist/prompt-submit.mjs +7975 -15
- package/dist/refresh-model-prices.mjs +7060 -25
- package/dist/response-after.mjs +7962 -12
- package/dist/run.mjs +7960 -10
- package/dist/session-end.mjs +8030 -15
- package/dist/session-start.mjs +8076 -21
- package/dist/shim.mjs +7024 -18
- package/dist/stop.mjs +8042 -29
- package/dist/subagent-start.mjs +7983 -13
- package/dist/subagent-stop.mjs +7962 -12
- package/dist/support.mjs +7168 -21
- package/dist/tlc-cli.mjs +8250 -65
- package/dist/tool-after.mjs +8177 -21
- package/dist/tool-before.mjs +7991 -16
- package/dist/tool-failure.mjs +7962 -15
- package/dist/uninstall-runtime.mjs +1008 -61
- package/docs/log.md +1 -1
- package/package.json +1 -1
- package/dist/chunks/compact-before-1e4qg1qt.mjs +0 -1185
- package/dist/chunks/compact-before-2hpbfxm5.mjs +0 -5782
- package/dist/chunks/compact-before-49j320yp.mjs +0 -1283
- package/dist/chunks/compact-before-4jrq0sqs.mjs +0 -61
- package/dist/chunks/compact-before-6w8n1vh1.mjs +0 -186
- package/dist/chunks/compact-before-7sdmwswh.mjs +0 -52
- package/dist/chunks/compact-before-beqpmqrm.mjs +0 -187
- package/dist/chunks/compact-before-j9y4jgn4.mjs +0 -845
- package/dist/chunks/compact-before-pk86tqx2.mjs +0 -118
- package/dist/chunks/compact-before-pkqk5v29.mjs +0 -137
- package/dist/chunks/compact-before-w1293m4n.mjs +0 -315
- package/dist/chunks/compact-before-wnnds45y.mjs +0 -26
- package/dist/chunks/compact-before-wt2c3nh4.mjs +0 -551
package/dist/price-lookup.mjs
CHANGED
|
@@ -1,14 +1,204 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/platform/cli-output.ts
|
|
5
|
+
var JSON_FLAG = "--json";
|
|
6
|
+
function takeJsonFlag(args) {
|
|
7
|
+
const rest = [];
|
|
8
|
+
let json = false;
|
|
9
|
+
for (const arg of args) {
|
|
10
|
+
if (arg === JSON_FLAG) {
|
|
11
|
+
json = true;
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
rest.push(arg);
|
|
15
|
+
}
|
|
16
|
+
return { json, rest };
|
|
17
|
+
}
|
|
18
|
+
function emitJson(value, write = writeStdout) {
|
|
19
|
+
write(`${JSON.stringify(value)}
|
|
20
|
+
`);
|
|
21
|
+
}
|
|
22
|
+
function writeStdout(text) {
|
|
23
|
+
process.stdout.write(text);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/platform/pricing.ts
|
|
27
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
28
|
+
import { join as join2 } from "node:path";
|
|
29
|
+
|
|
30
|
+
// src/platform/paths.ts
|
|
31
|
+
import { homedir } from "node:os";
|
|
32
|
+
import { join } from "node:path";
|
|
33
|
+
function conventionalRuntimeHome() {
|
|
34
|
+
return join(homedir(), ".tlc", "harness");
|
|
35
|
+
}
|
|
36
|
+
function runtimeHome(env = process.env) {
|
|
37
|
+
return env.TLC_HOME ?? conventionalRuntimeHome();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/platform/pricing.ts
|
|
41
|
+
var FALLBACK_PLANE = "litellm";
|
|
42
|
+
var MODEL_ALIASES = {
|
|
43
|
+
"cursor-grok-4.5": "grok-4.5",
|
|
44
|
+
auto: "auto-cost"
|
|
45
|
+
};
|
|
46
|
+
function stripMeta(table) {
|
|
47
|
+
if (!table) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
const { _meta: _ignored, ...rest } = table;
|
|
51
|
+
return rest;
|
|
52
|
+
}
|
|
53
|
+
function slugifyModelName(name) {
|
|
54
|
+
return name.trim().toLowerCase().replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/[[\]]/g, "").replace(/[^a-z0-9.+]+/g, "-").replace(/^-+|-+$/g, "");
|
|
55
|
+
}
|
|
56
|
+
function candidatesFor(model, aliases) {
|
|
57
|
+
const trimmed = model.trim();
|
|
58
|
+
const out = [];
|
|
59
|
+
const push = (v) => {
|
|
60
|
+
if (v && !out.includes(v)) {
|
|
61
|
+
out.push(v);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
push(trimmed);
|
|
65
|
+
push(aliases[trimmed]);
|
|
66
|
+
push(slugifyModelName(trimmed));
|
|
67
|
+
push(aliases[slugifyModelName(trimmed)]);
|
|
68
|
+
if (trimmed.includes("/")) {
|
|
69
|
+
push(trimmed.slice(trimmed.lastIndexOf("/") + 1));
|
|
70
|
+
}
|
|
71
|
+
const noEffort = trimmed.replace(/-(high|medium|low|max|fast|thinking)$/i, "");
|
|
72
|
+
if (noEffort !== trimmed) {
|
|
73
|
+
push(noEffort);
|
|
74
|
+
push(aliases[noEffort]);
|
|
75
|
+
push(slugifyModelName(noEffort));
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function fuzzyFind(table, needle) {
|
|
80
|
+
const direct = table[needle];
|
|
81
|
+
if (direct) {
|
|
82
|
+
return { key: needle, entry: direct };
|
|
83
|
+
}
|
|
84
|
+
for (const [key, entry] of Object.entries(table)) {
|
|
85
|
+
if (needle.startsWith(key) || key.startsWith(needle)) {
|
|
86
|
+
return { key, entry };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
function cataloguePath() {
|
|
92
|
+
return join2(runtimeHome(), "model-prices.json");
|
|
93
|
+
}
|
|
94
|
+
function overridesPath() {
|
|
95
|
+
return join2(runtimeHome(), "model-prices.local.json");
|
|
96
|
+
}
|
|
97
|
+
var cache = new Map;
|
|
98
|
+
function readCatalogue(path) {
|
|
99
|
+
if (!existsSync(path)) {
|
|
100
|
+
cache.delete(path);
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
let text;
|
|
104
|
+
try {
|
|
105
|
+
text = readFileSync(path, "utf8");
|
|
106
|
+
} catch {
|
|
107
|
+
cache.delete(path);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const hit = cache.get(path);
|
|
111
|
+
if (hit && hit.text === text) {
|
|
112
|
+
return hit.value;
|
|
113
|
+
}
|
|
114
|
+
let parsed;
|
|
115
|
+
try {
|
|
116
|
+
parsed = JSON.parse(text);
|
|
117
|
+
} catch {
|
|
118
|
+
cache.delete(path);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
cache.set(path, { text, value: parsed });
|
|
122
|
+
return parsed;
|
|
123
|
+
}
|
|
124
|
+
function loadCatalogue() {
|
|
125
|
+
return readCatalogue(cataloguePath()) ?? {};
|
|
126
|
+
}
|
|
127
|
+
function planeFor(catalogue, plane) {
|
|
128
|
+
return stripMeta(catalogue.planes?.[plane] ?? null);
|
|
129
|
+
}
|
|
130
|
+
function resolveModelPrice(provider, model) {
|
|
131
|
+
const trimmed = model.trim();
|
|
132
|
+
if (!trimmed) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const catalogue = loadCatalogue();
|
|
136
|
+
const overrides = stripMeta(readCatalogue(overridesPath()));
|
|
137
|
+
const native = provider ? planeFor(catalogue, provider) : {};
|
|
138
|
+
const litellm = planeFor(catalogue, FALLBACK_PLANE);
|
|
139
|
+
const candidates = candidatesFor(trimmed, MODEL_ALIASES);
|
|
140
|
+
for (const id of candidates) {
|
|
141
|
+
const entry = overrides[id];
|
|
142
|
+
if (entry) {
|
|
143
|
+
return { entry, key: id, source: "override" };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const id of candidates) {
|
|
147
|
+
const entry = native[id];
|
|
148
|
+
if (entry) {
|
|
149
|
+
return { entry, key: id, source: "provider" };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const id of candidates) {
|
|
153
|
+
const entry = litellm[id];
|
|
154
|
+
if (entry) {
|
|
155
|
+
return { entry, key: id, source: "litellm" };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const slug = slugifyModelName(trimmed);
|
|
159
|
+
const fuzzyOverride = fuzzyFind(overrides, slug);
|
|
160
|
+
if (fuzzyOverride) {
|
|
161
|
+
return { ...fuzzyOverride, source: "override" };
|
|
162
|
+
}
|
|
163
|
+
const fuzzyNative = fuzzyFind(native, slug);
|
|
164
|
+
if (fuzzyNative) {
|
|
165
|
+
return { ...fuzzyNative, source: "provider" };
|
|
166
|
+
}
|
|
167
|
+
const fuzzyLitellm = fuzzyFind(litellm, slug);
|
|
168
|
+
if (fuzzyLitellm) {
|
|
169
|
+
return { ...fuzzyLitellm, source: "litellm" };
|
|
170
|
+
}
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
function estimateCostUsd(provider, model, usage) {
|
|
174
|
+
const inputTokens = usage.inputTokens ?? 0;
|
|
175
|
+
const outputTokens = usage.outputTokens ?? 0;
|
|
176
|
+
const cacheReadTokens = usage.cacheReadTokens ?? 0;
|
|
177
|
+
const cacheWriteTokens = usage.cacheWriteTokens ?? 0;
|
|
178
|
+
if (!model || inputTokens <= 0 && outputTokens <= 0 && cacheReadTokens <= 0 && cacheWriteTokens <= 0) {
|
|
179
|
+
return { costUsd: null, billing: "unknown", pool: "unknown", source: "missing" };
|
|
180
|
+
}
|
|
181
|
+
const resolved = resolveModelPrice(provider, model);
|
|
182
|
+
if (!resolved) {
|
|
183
|
+
return { costUsd: null, billing: "unknown", pool: "unknown", source: "missing" };
|
|
184
|
+
}
|
|
185
|
+
const { entry, key, source } = resolved;
|
|
186
|
+
const pool = entry.pool ?? "unknown";
|
|
187
|
+
if (entry.billing === "included") {
|
|
188
|
+
return { costUsd: null, billing: "included", pool, source, catalogKey: key };
|
|
189
|
+
}
|
|
190
|
+
if (typeof entry.promptPer1M !== "number" || typeof entry.completionPer1M !== "number") {
|
|
191
|
+
return { costUsd: null, billing: entry.billing ?? "unknown", pool, source, catalogKey: key };
|
|
192
|
+
}
|
|
193
|
+
let costUsd = inputTokens / 1e6 * entry.promptPer1M + outputTokens / 1e6 * entry.completionPer1M;
|
|
194
|
+
if (typeof entry.cacheReadPer1M === "number" && cacheReadTokens > 0) {
|
|
195
|
+
costUsd += cacheReadTokens / 1e6 * entry.cacheReadPer1M;
|
|
196
|
+
}
|
|
197
|
+
if (typeof entry.cacheWritePer1M === "number" && cacheWriteTokens > 0) {
|
|
198
|
+
costUsd += cacheWriteTokens / 1e6 * entry.cacheWritePer1M;
|
|
199
|
+
}
|
|
200
|
+
return { costUsd, billing: "metered", pool, source, catalogKey: key };
|
|
201
|
+
}
|
|
12
202
|
|
|
13
203
|
// tools/price-lookup.ts
|
|
14
204
|
function parsePriceLookupArgs(argv) {
|