@sleds/cli 0.1.24 → 0.1.25
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/sleds.mjs +154 -26
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -833,7 +833,7 @@ var GUIDES = [
|
|
|
833
833
|
{
|
|
834
834
|
do: "Add the custom connector",
|
|
835
835
|
where: "claude.ai › Settings › Connectors › `Add custom connector`",
|
|
836
|
-
note: "URL `https://
|
|
836
|
+
note: "URL `https://mcp.sleds.ai/mcp`. It signs you in with OAuth — the same email your workspace invited."
|
|
837
837
|
},
|
|
838
838
|
{
|
|
839
839
|
do: "Say `/sled usage` in any chat",
|
|
@@ -1221,7 +1221,7 @@ var VERBS = [
|
|
|
1221
1221
|
id: "connector",
|
|
1222
1222
|
group: "trust",
|
|
1223
1223
|
want: "Use SLEDS from chat, Cowork or Claude Design",
|
|
1224
|
-
mcp: "add https://
|
|
1224
|
+
mcp: "add https://mcp.sleds.ai/mcp as a connector (OAuth) — then every verb in this column",
|
|
1225
1225
|
how: "The conversation is your cockpit: the same tools, no terminal. Your seat is the account you signed in with."
|
|
1226
1226
|
},
|
|
1227
1227
|
{
|
|
@@ -2076,8 +2076,8 @@ var SERVER_INFO = {
|
|
|
2076
2076
|
description: "The cost and limits of AI agent work — estimate, hand off, and track what a task takes.",
|
|
2077
2077
|
websiteUrl: "https://sleds.ai",
|
|
2078
2078
|
icons: [
|
|
2079
|
-
{ src: "https://
|
|
2080
|
-
{ src: "https://
|
|
2079
|
+
{ src: "https://mcp.sleds.ai/icon.png", mimeType: "image/png", sizes: ["192x192"] },
|
|
2080
|
+
{ src: "https://mcp.sleds.ai/icon.svg", mimeType: "image/svg+xml", sizes: ["any"] }
|
|
2081
2081
|
]
|
|
2082
2082
|
};
|
|
2083
2083
|
var SERVER_INSTRUCTIONS = [
|
|
@@ -3318,7 +3318,7 @@ async function actualTool(ctx, args) {
|
|
|
3318
3318
|
...num3(args.tokensIn) !== undefined ? { tokensIn: num3(args.tokensIn) } : {},
|
|
3319
3319
|
...num3(args.tokensOut) !== undefined ? { tokensOut: num3(args.tokensOut) } : {},
|
|
3320
3320
|
...str4(args.by) ? { by: str4(args.by) } : {},
|
|
3321
|
-
...sessionIdOf(args.sessionId) ? { sessionId: sessionIdOf(args.sessionId) } : {},
|
|
3321
|
+
...sessionIdOf(args.sessionId) ?? ctx.sessionId?.() ? { sessionId: sessionIdOf(args.sessionId) ?? ctx.sessionId?.() } : {},
|
|
3322
3322
|
...str4(args.ref) ? { ref: str4(args.ref) } : {},
|
|
3323
3323
|
...phases && Object.keys(phases).length > 0 ? { phases } : {},
|
|
3324
3324
|
...num3(args.seatCreditsUsd) !== undefined ? { seatCreditsUsd: num3(args.seatCreditsUsd) } : {}
|
|
@@ -5214,7 +5214,12 @@ function contextFor(deps) {
|
|
|
5214
5214
|
const src = meterSource(deps.home);
|
|
5215
5215
|
const now = deps.now ?? Date.now;
|
|
5216
5216
|
const client = src ? trackingClient(fetchClient({ ...src, fetchFn: deps.fetchFn, timeoutMs: deps.timeoutMs }), deps.home, now) : null;
|
|
5217
|
-
return {
|
|
5217
|
+
return {
|
|
5218
|
+
client,
|
|
5219
|
+
now: deps.now,
|
|
5220
|
+
usage: () => usageTool2(deps),
|
|
5221
|
+
sessionId: () => readSession(deps.home)?.sessionId
|
|
5222
|
+
};
|
|
5218
5223
|
}
|
|
5219
5224
|
var callTool2 = (name, args, deps) => callTool(name, args, contextFor(deps));
|
|
5220
5225
|
var handleLine2 = (line, deps) => handleLine(line, contextFor(deps));
|
|
@@ -7474,6 +7479,128 @@ var announce = (o, events) => {
|
|
|
7474
7479
|
};
|
|
7475
7480
|
|
|
7476
7481
|
// src/commands/stopEvent.ts
|
|
7482
|
+
init_meter();
|
|
7483
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
|
|
7484
|
+
|
|
7485
|
+
// src/transcript.ts
|
|
7486
|
+
var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
7487
|
+
var n = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
7488
|
+
function sumTranscript(text) {
|
|
7489
|
+
const seen = new Set;
|
|
7490
|
+
const turn = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
7491
|
+
let sub = 0;
|
|
7492
|
+
let messages = 0;
|
|
7493
|
+
const byModel = new Map;
|
|
7494
|
+
const agents = new Set;
|
|
7495
|
+
let anySidechain = false;
|
|
7496
|
+
for (const line of text.split(`
|
|
7497
|
+
`)) {
|
|
7498
|
+
const t = line.trim();
|
|
7499
|
+
if (!t)
|
|
7500
|
+
continue;
|
|
7501
|
+
let j;
|
|
7502
|
+
try {
|
|
7503
|
+
j = JSON.parse(t);
|
|
7504
|
+
} catch {
|
|
7505
|
+
continue;
|
|
7506
|
+
}
|
|
7507
|
+
if (!isObject12(j) || j.type !== "assistant" || !isObject12(j.message))
|
|
7508
|
+
continue;
|
|
7509
|
+
const m = j.message;
|
|
7510
|
+
const id = typeof m.id === "string" ? m.id : typeof j.uuid === "string" ? j.uuid : undefined;
|
|
7511
|
+
if (id) {
|
|
7512
|
+
if (seen.has(id))
|
|
7513
|
+
continue;
|
|
7514
|
+
seen.add(id);
|
|
7515
|
+
}
|
|
7516
|
+
const u = isObject12(m.usage) ? m.usage : undefined;
|
|
7517
|
+
if (!u)
|
|
7518
|
+
continue;
|
|
7519
|
+
const input = n(u.input_tokens);
|
|
7520
|
+
const output = n(u.output_tokens);
|
|
7521
|
+
const cacheRead = n(u.cache_read_input_tokens);
|
|
7522
|
+
const cacheWrite = n(u.cache_creation_input_tokens);
|
|
7523
|
+
messages++;
|
|
7524
|
+
const model = typeof m.model === "string" ? m.model : undefined;
|
|
7525
|
+
if (model)
|
|
7526
|
+
byModel.set(model, (byModel.get(model) ?? 0) + output);
|
|
7527
|
+
if (j.isSidechain === true) {
|
|
7528
|
+
anySidechain = true;
|
|
7529
|
+
sub += input + output + cacheRead + cacheWrite;
|
|
7530
|
+
if (typeof j.agentId === "string")
|
|
7531
|
+
agents.add(j.agentId);
|
|
7532
|
+
} else {
|
|
7533
|
+
turn.input += input;
|
|
7534
|
+
turn.output += output;
|
|
7535
|
+
turn.cacheRead += cacheRead;
|
|
7536
|
+
turn.cacheWrite += cacheWrite;
|
|
7537
|
+
}
|
|
7538
|
+
}
|
|
7539
|
+
let model;
|
|
7540
|
+
let best = -1;
|
|
7541
|
+
for (const [k, v] of byModel)
|
|
7542
|
+
if (v > best)
|
|
7543
|
+
[model, best] = [k, v];
|
|
7544
|
+
return {
|
|
7545
|
+
turnTokens: turn,
|
|
7546
|
+
subagentTokens: sub,
|
|
7547
|
+
messages,
|
|
7548
|
+
...model ? { model } : {},
|
|
7549
|
+
subagentRuns: agents.size > 0 ? agents.size : anySidechain ? 1 : 0
|
|
7550
|
+
};
|
|
7551
|
+
}
|
|
7552
|
+
function sessionBody(sessionId, sum, a) {
|
|
7553
|
+
return {
|
|
7554
|
+
capturedAt: a.capturedAt,
|
|
7555
|
+
sessions: [
|
|
7556
|
+
{
|
|
7557
|
+
sessionId,
|
|
7558
|
+
...a.title ? { title: a.title.slice(0, 200) } : {},
|
|
7559
|
+
updatedAt: a.capturedAt,
|
|
7560
|
+
subagentTokens: sum.subagentTokens,
|
|
7561
|
+
taskCount: sum.subagentRuns,
|
|
7562
|
+
turnTokens: sum.turnTokens,
|
|
7563
|
+
tasks: []
|
|
7564
|
+
}
|
|
7565
|
+
]
|
|
7566
|
+
};
|
|
7567
|
+
}
|
|
7568
|
+
|
|
7569
|
+
// src/commands/stopEvent.ts
|
|
7570
|
+
var SESSION_POST_TIMEOUT_MS = 2500;
|
|
7571
|
+
async function postTranscript(o, payload, now) {
|
|
7572
|
+
const sessionId = payload.session_id?.trim();
|
|
7573
|
+
const path = payload.transcript_path?.trim();
|
|
7574
|
+
if (!sessionId || !path)
|
|
7575
|
+
return false;
|
|
7576
|
+
const src = meterSource(o.home);
|
|
7577
|
+
if (!src)
|
|
7578
|
+
return false;
|
|
7579
|
+
const read = o.readFile ?? ((p) => existsSync14(p) ? readFileSync12(p, "utf8") : null);
|
|
7580
|
+
let text;
|
|
7581
|
+
try {
|
|
7582
|
+
text = read(path);
|
|
7583
|
+
} catch {
|
|
7584
|
+
return false;
|
|
7585
|
+
}
|
|
7586
|
+
if (!text)
|
|
7587
|
+
return false;
|
|
7588
|
+
const sum = sumTranscript(text);
|
|
7589
|
+
if (sum.messages === 0)
|
|
7590
|
+
return false;
|
|
7591
|
+
const fetchFn = o.fetchFn ?? fetch;
|
|
7592
|
+
try {
|
|
7593
|
+
const res = await fetchFn(`${src.proxyUrl.replace(/\/+$/, "")}/proxy/sessions`, {
|
|
7594
|
+
method: "POST",
|
|
7595
|
+
headers: { authorization: `Bearer ${src.token}`, "content-type": "application/json" },
|
|
7596
|
+
body: JSON.stringify(sessionBody(sessionId, sum, { capturedAt: now })),
|
|
7597
|
+
signal: AbortSignal.timeout(SESSION_POST_TIMEOUT_MS)
|
|
7598
|
+
});
|
|
7599
|
+
return res.ok;
|
|
7600
|
+
} catch {
|
|
7601
|
+
return false;
|
|
7602
|
+
}
|
|
7603
|
+
}
|
|
7477
7604
|
var parseStopPayload = (raw) => {
|
|
7478
7605
|
try {
|
|
7479
7606
|
const j = JSON.parse(raw);
|
|
@@ -7503,6 +7630,7 @@ var stopEvent = async (o) => {
|
|
|
7503
7630
|
const now = (o.now ?? Date.now)();
|
|
7504
7631
|
const raw = o.stdin ?? await readStdin(HOOK_STDIN_TIMEOUT_MS);
|
|
7505
7632
|
const payload = parseStopPayload(raw);
|
|
7633
|
+
await postTranscript(o, payload, now);
|
|
7506
7634
|
let rows;
|
|
7507
7635
|
try {
|
|
7508
7636
|
rows = readOwed(o.home, now);
|
|
@@ -7526,11 +7654,11 @@ var stopEvent = async (o) => {
|
|
|
7526
7654
|
|
|
7527
7655
|
// src/commands/uninstall.ts
|
|
7528
7656
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
7529
|
-
import { existsSync as
|
|
7657
|
+
import { existsSync as existsSync16, rmSync as rmSync5 } from "node:fs";
|
|
7530
7658
|
|
|
7531
7659
|
// src/codex.ts
|
|
7532
7660
|
init_config();
|
|
7533
|
-
import { existsSync as
|
|
7661
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync12, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "node:fs";
|
|
7534
7662
|
import { dirname as dirname6, join as join12 } from "node:path";
|
|
7535
7663
|
var PROVIDER_ID2 = "sleds";
|
|
7536
7664
|
var codexDir2 = (home) => join12(home, ".codex");
|
|
@@ -7563,9 +7691,9 @@ function removeCodexProvider2(toml, o = {}) {
|
|
|
7563
7691
|
}
|
|
7564
7692
|
function uninstallCodex(home) {
|
|
7565
7693
|
const path = codexConfigPath2(home);
|
|
7566
|
-
if (!
|
|
7694
|
+
if (!existsSync15(path))
|
|
7567
7695
|
return null;
|
|
7568
|
-
const prior =
|
|
7696
|
+
const prior = readFileSync13(path, "utf8");
|
|
7569
7697
|
const next = removeCodexProvider2(prior);
|
|
7570
7698
|
if (next === prior)
|
|
7571
7699
|
return null;
|
|
@@ -7586,7 +7714,7 @@ var uninstall2 = (o) => {
|
|
|
7586
7714
|
(o.log ?? console.log)(` ${codexLine}`);
|
|
7587
7715
|
const log = o.log ?? console.log;
|
|
7588
7716
|
const removed = [];
|
|
7589
|
-
if (
|
|
7717
|
+
if (existsSync16(settingsPath(o.home))) {
|
|
7590
7718
|
let settings = readSettings(o.home);
|
|
7591
7719
|
let changed = false;
|
|
7592
7720
|
if (hasEitherKey(settings)) {
|
|
@@ -7633,18 +7761,18 @@ var uninstall2 = (o) => {
|
|
|
7633
7761
|
writeSettings(o.home, settings);
|
|
7634
7762
|
}
|
|
7635
7763
|
for (const file of [meterCachePath(o.home), seatStatePath(o.home)]) {
|
|
7636
|
-
if (
|
|
7764
|
+
if (existsSync16(file)) {
|
|
7637
7765
|
rmSync5(file, { force: true });
|
|
7638
7766
|
removed.push(file);
|
|
7639
7767
|
}
|
|
7640
7768
|
}
|
|
7641
7769
|
const skill = skillDir(o.home);
|
|
7642
|
-
if (
|
|
7770
|
+
if (existsSync16(skill)) {
|
|
7643
7771
|
rmSync5(skill, { recursive: true, force: true });
|
|
7644
7772
|
removed.push(skill);
|
|
7645
7773
|
}
|
|
7646
7774
|
const plist = musherPlistPath(o.home);
|
|
7647
|
-
if (
|
|
7775
|
+
if (existsSync16(plist)) {
|
|
7648
7776
|
(o.unloadAgent ?? defaultUnload)(plist);
|
|
7649
7777
|
rmSync5(plist, { force: true });
|
|
7650
7778
|
removed.push(`launchd agent ${musherLabel()}`);
|
|
@@ -7716,17 +7844,17 @@ var verify = async (o) => {
|
|
|
7716
7844
|
|
|
7717
7845
|
// src/config.ts
|
|
7718
7846
|
init_settings();
|
|
7719
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
7847
|
+
import { chmodSync as chmodSync2, existsSync as existsSync17, mkdirSync as mkdirSync13, readFileSync as readFileSync14, renameSync as renameSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
7720
7848
|
import { join as join13, resolve as resolve4 } from "node:path";
|
|
7721
7849
|
var configDir2 = (home, env = process.env) => {
|
|
7722
7850
|
const o = env.SLEDS_HOME?.trim();
|
|
7723
7851
|
return o ? resolve4(home, o) : join13(home, ".config", "sleds");
|
|
7724
7852
|
};
|
|
7725
7853
|
var configPath2 = (home) => join13(configDir2(home), "config.json");
|
|
7726
|
-
var
|
|
7854
|
+
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
7727
7855
|
var optString2 = (v) => typeof v === "string" ? v : undefined;
|
|
7728
7856
|
var parsePriorEnv2 = (v) => {
|
|
7729
|
-
if (!
|
|
7857
|
+
if (!isObject13(v))
|
|
7730
7858
|
return;
|
|
7731
7859
|
const out = {};
|
|
7732
7860
|
const url = optString2(v[BASE_URL_KEY]);
|
|
@@ -7741,7 +7869,7 @@ var parsePriorEnv2 = (v) => {
|
|
|
7741
7869
|
};
|
|
7742
7870
|
var parseSchedule2 = (v) => v === "launchd" || v === "systemd" || v === "manual" ? v : undefined;
|
|
7743
7871
|
var parseConfig2 = (raw) => {
|
|
7744
|
-
if (!
|
|
7872
|
+
if (!isObject13(raw))
|
|
7745
7873
|
return {};
|
|
7746
7874
|
const cfg = {};
|
|
7747
7875
|
const token = optString2(raw.token);
|
|
@@ -7785,7 +7913,7 @@ var parseConfig2 = (raw) => {
|
|
|
7785
7913
|
return cfg;
|
|
7786
7914
|
};
|
|
7787
7915
|
var parseMusher2 = (raw) => {
|
|
7788
|
-
if (!
|
|
7916
|
+
if (!isObject13(raw))
|
|
7789
7917
|
return;
|
|
7790
7918
|
const out = {};
|
|
7791
7919
|
const pm = optString2(raw.permissionMode);
|
|
@@ -7801,7 +7929,7 @@ var parseMusher2 = (raw) => {
|
|
|
7801
7929
|
return out;
|
|
7802
7930
|
};
|
|
7803
7931
|
var parseOrgInfo2 = (raw) => {
|
|
7804
|
-
if (!
|
|
7932
|
+
if (!isObject13(raw) || !isObject13(raw.capabilities))
|
|
7805
7933
|
return;
|
|
7806
7934
|
const name = optString2(raw.name);
|
|
7807
7935
|
const slug = optString2(raw.slug);
|
|
@@ -7825,9 +7953,9 @@ var parseOrgInfo2 = (raw) => {
|
|
|
7825
7953
|
};
|
|
7826
7954
|
var readConfig2 = (home) => {
|
|
7827
7955
|
const p = configPath2(home);
|
|
7828
|
-
if (!
|
|
7956
|
+
if (!existsSync17(p))
|
|
7829
7957
|
return {};
|
|
7830
|
-
return parseConfig2(JSON.parse(
|
|
7958
|
+
return parseConfig2(JSON.parse(readFileSync14(p, "utf8")));
|
|
7831
7959
|
};
|
|
7832
7960
|
|
|
7833
7961
|
// src/schedule.ts
|
|
@@ -7853,12 +7981,12 @@ var withSeatEnv2 = (command, home, env = process.env) => {
|
|
|
7853
7981
|
return parts.join(" ");
|
|
7854
7982
|
};
|
|
7855
7983
|
var shellWord2 = (v) => /^[\w./~-]+$/.test(v) ? v : `'${v.replace(/'/g, "'\\''")}'`;
|
|
7856
|
-
var
|
|
7984
|
+
var isObject14 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
7857
7985
|
var isSledsHookFor2 = (sub) => (entry) => {
|
|
7858
|
-
if (!
|
|
7986
|
+
if (!isObject14(entry) || !Array.isArray(entry.hooks))
|
|
7859
7987
|
return false;
|
|
7860
7988
|
const re = new RegExp(`\\b${sub}\\b`);
|
|
7861
|
-
return entry.hooks.some((h) =>
|
|
7989
|
+
return entry.hooks.some((h) => isObject14(h) && h.type === "command" && typeof h.command === "string" && re.test(h.command));
|
|
7862
7990
|
};
|
|
7863
7991
|
var isSledsSessionHook2 = isSledsHookFor2("session-event");
|
|
7864
7992
|
var isSledsStopHook2 = isSledsHookFor2("stop-event");
|
|
@@ -8118,7 +8246,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
8118
8246
|
case "version":
|
|
8119
8247
|
case "--version":
|
|
8120
8248
|
case "-v":
|
|
8121
|
-
console.log("sleds 0.1.
|
|
8249
|
+
console.log("sleds 0.1.25");
|
|
8122
8250
|
return 0;
|
|
8123
8251
|
default:
|
|
8124
8252
|
console.error(`unknown command: ${cmd}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleds/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.25",
|
|
4
4
|
"description": "SLEDS CLI — the cost and limits of AI agent work, decided at the wall. Point Claude Code at a SLEDS proxy; estimate before you run; hold, switch model, or run overnight when you hit a limit.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|