@candledottv/cli 0.8.2 → 0.8.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/dist/index.js +177 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18850,6 +18850,42 @@ var init_convert = __esm(() => {
|
|
|
18850
18850
|
DECIMAL_RE = /^\d+(\.\d+)?$/;
|
|
18851
18851
|
});
|
|
18852
18852
|
|
|
18853
|
+
// ../mcp/src/version.ts
|
|
18854
|
+
var SERVER_VERSION = "0.6.4";
|
|
18855
|
+
|
|
18856
|
+
// ../mcp/src/update-notice.ts
|
|
18857
|
+
function newer(a, b) {
|
|
18858
|
+
const [a1 = 0, a2 = 0, a3 = 0] = a.split(".").map(Number);
|
|
18859
|
+
const [b1 = 0, b2 = 0, b3 = 0] = b.split(".").map(Number);
|
|
18860
|
+
return a1 !== b1 ? a1 > b1 : a2 !== b2 ? a2 > b2 : a3 > b3;
|
|
18861
|
+
}
|
|
18862
|
+
function noteVersionHeaders(res) {
|
|
18863
|
+
const headers = res?.headers;
|
|
18864
|
+
const value = typeof headers?.get === "function" ? headers.get("x-candle-mcp-latest") : null;
|
|
18865
|
+
if (!value || !PLAIN_VERSION.test(value))
|
|
18866
|
+
return;
|
|
18867
|
+
if (latestSeen !== null && !newer(value, latestSeen))
|
|
18868
|
+
return;
|
|
18869
|
+
latestSeen = value;
|
|
18870
|
+
if (!warned && newer(value, SERVER_VERSION) && !process.env.CANDLE_NO_UPDATE_NOTIFIER) {
|
|
18871
|
+
warned = true;
|
|
18872
|
+
console.error(`@candledottv/mcp ${value} is available (running ${SERVER_VERSION}). Update: npm install -g @candledottv/mcp@latest`);
|
|
18873
|
+
}
|
|
18874
|
+
}
|
|
18875
|
+
function updateAvailable() {
|
|
18876
|
+
if (latestSeen === null || !newer(latestSeen, SERVER_VERSION))
|
|
18877
|
+
return null;
|
|
18878
|
+
return {
|
|
18879
|
+
current: SERVER_VERSION,
|
|
18880
|
+
latest: latestSeen,
|
|
18881
|
+
command: "npm install -g @candledottv/mcp@latest"
|
|
18882
|
+
};
|
|
18883
|
+
}
|
|
18884
|
+
var PLAIN_VERSION, latestSeen = null, warned = false;
|
|
18885
|
+
var init_update_notice = __esm(() => {
|
|
18886
|
+
PLAIN_VERSION = /^\d+\.\d+\.\d+$/;
|
|
18887
|
+
});
|
|
18888
|
+
|
|
18853
18889
|
// ../mcp/src/orchestrate.ts
|
|
18854
18890
|
import { randomUUID } from "node:crypto";
|
|
18855
18891
|
function requireApiKey(cfg) {
|
|
@@ -19156,6 +19192,7 @@ async function executionStatus(cfg, doFetch) {
|
|
|
19156
19192
|
const apiKey = requireApiKey(cfg);
|
|
19157
19193
|
const get = async (path) => {
|
|
19158
19194
|
const res = await doFetch(`${base(cfg)}${path}`, { method: "GET", headers: headers(apiKey) });
|
|
19195
|
+
noteVersionHeaders(res);
|
|
19159
19196
|
const text = await res.text();
|
|
19160
19197
|
let body;
|
|
19161
19198
|
try {
|
|
@@ -19175,10 +19212,13 @@ async function executionStatus(cfg, doFetch) {
|
|
|
19175
19212
|
["tier", tier],
|
|
19176
19213
|
["limits", limits]
|
|
19177
19214
|
].filter(([, r]) => !r.ok);
|
|
19215
|
+
const tierBody = tier.ok ? tier.body : undefined;
|
|
19178
19216
|
return {
|
|
19179
19217
|
text: JSON.stringify({
|
|
19180
19218
|
success: true,
|
|
19181
19219
|
ready: unreadable.length === 0 ? true : undefined,
|
|
19220
|
+
notice: tierBody?.maxExpired ? tierBody.maxExpiredNotice : undefined,
|
|
19221
|
+
updateAvailable: updateAvailable() ?? undefined,
|
|
19182
19222
|
unreadable: unreadable.length > 0 ? unreadable.map(([name]) => name) : undefined,
|
|
19183
19223
|
wallets: wallets2.body,
|
|
19184
19224
|
tier: tier.body,
|
|
@@ -19190,6 +19230,7 @@ async function executionStatus(cfg, doFetch) {
|
|
|
19190
19230
|
var SWEEP_BASE_ASSETS;
|
|
19191
19231
|
var init_orchestrate = __esm(() => {
|
|
19192
19232
|
init_convert();
|
|
19233
|
+
init_update_notice();
|
|
19193
19234
|
SWEEP_BASE_ASSETS = {
|
|
19194
19235
|
solana: ["USDC", "CNDL", "SOL"],
|
|
19195
19236
|
hood: ["USDG", "ETH"]
|
|
@@ -19319,6 +19360,7 @@ function buildRequest(name, args, cfg) {
|
|
|
19319
19360
|
async function callAndRelay(name, args, cfg) {
|
|
19320
19361
|
const { url, init } = buildRequest(name, args, cfg);
|
|
19321
19362
|
const res = await fetch(url, init);
|
|
19363
|
+
noteVersionHeaders(res);
|
|
19322
19364
|
const text = await res.text();
|
|
19323
19365
|
return {
|
|
19324
19366
|
content: [{ type: "text", text }],
|
|
@@ -19446,6 +19488,7 @@ var init_tools = __esm(() => {
|
|
|
19446
19488
|
init_zod();
|
|
19447
19489
|
init_convert();
|
|
19448
19490
|
init_orchestrate();
|
|
19491
|
+
init_update_notice();
|
|
19449
19492
|
TOOL_NAMES = [
|
|
19450
19493
|
"candle_launch_token",
|
|
19451
19494
|
"candle_get_market",
|
|
@@ -19544,9 +19587,6 @@ var init_tools = __esm(() => {
|
|
|
19544
19587
|
};
|
|
19545
19588
|
});
|
|
19546
19589
|
|
|
19547
|
-
// ../mcp/src/version.ts
|
|
19548
|
-
var SERVER_VERSION = "0.6.2";
|
|
19549
|
-
|
|
19550
19590
|
// ../mcp/src/server.ts
|
|
19551
19591
|
var exports_server = {};
|
|
19552
19592
|
__export(exports_server, {
|
|
@@ -19675,6 +19715,10 @@ function classifyError(status, raw) {
|
|
|
19675
19715
|
}
|
|
19676
19716
|
return { message: `Request failed with status ${status}` };
|
|
19677
19717
|
}
|
|
19718
|
+
var latestCliVersionSeen = null;
|
|
19719
|
+
function latestCliVersionFromApi() {
|
|
19720
|
+
return latestCliVersionSeen;
|
|
19721
|
+
}
|
|
19678
19722
|
async function apiRequest(path, opts) {
|
|
19679
19723
|
const url = buildUrl(opts.apiUrl, path);
|
|
19680
19724
|
const insecure = insecureApiUrlFault(opts.apiUrl, opts.env ?? process.env);
|
|
@@ -19702,6 +19746,9 @@ async function apiRequest(path, opts) {
|
|
|
19702
19746
|
raw: undefined
|
|
19703
19747
|
};
|
|
19704
19748
|
}
|
|
19749
|
+
const latestHeader = response.headers?.get?.("x-candle-cli-latest");
|
|
19750
|
+
if (latestHeader)
|
|
19751
|
+
latestCliVersionSeen = latestHeader;
|
|
19705
19752
|
const text = await response.text();
|
|
19706
19753
|
const raw = parseBody(text);
|
|
19707
19754
|
if (response.ok) {
|
|
@@ -20258,7 +20305,7 @@ async function resolveApiKey(deps, profile) {
|
|
|
20258
20305
|
}
|
|
20259
20306
|
|
|
20260
20307
|
// src/version.ts
|
|
20261
|
-
var CLI_VERSION = "0.8.
|
|
20308
|
+
var CLI_VERSION = "0.8.4";
|
|
20262
20309
|
|
|
20263
20310
|
// src/commands/auth.ts
|
|
20264
20311
|
var DEVICE_CODE_PATH = "/api/v1/agent/device/code";
|
|
@@ -20600,6 +20647,9 @@ async function authStatus(args, ctx) {
|
|
|
20600
20647
|
var RELEASE_BASE_URL = "https://github.com/candledottv/agentic";
|
|
20601
20648
|
var RELEASE_ISSUER = "https://token.actions.githubusercontent.com";
|
|
20602
20649
|
var VERSION = /^\d+\.\d+\.\d+$/;
|
|
20650
|
+
function isPlainVersion(value) {
|
|
20651
|
+
return VERSION.test(value);
|
|
20652
|
+
}
|
|
20603
20653
|
function releaseIdentityUri(version) {
|
|
20604
20654
|
if (!VERSION.test(version))
|
|
20605
20655
|
throw new Error(`invalid release version: ${version}`);
|
|
@@ -20735,6 +20785,30 @@ async function doctor(args, ctx) {
|
|
|
20735
20785
|
passDetail
|
|
20736
20786
|
}));
|
|
20737
20787
|
}
|
|
20788
|
+
if (!apiKey) {
|
|
20789
|
+
rows.push({ check: "Plan", state: "SKIP", detail: "no API key to check" });
|
|
20790
|
+
} else {
|
|
20791
|
+
const tierRes = await apiRequest("/api/v1/agent/tier", {
|
|
20792
|
+
auth: "key",
|
|
20793
|
+
credentials: { apiKey },
|
|
20794
|
+
apiUrl,
|
|
20795
|
+
fetch: deps.fetch,
|
|
20796
|
+
env: deps.env
|
|
20797
|
+
});
|
|
20798
|
+
const tierBody = tierRes.ok ? tierRes.body : undefined;
|
|
20799
|
+
if (!tierBody || typeof tierBody.tier !== "string") {
|
|
20800
|
+
rows.push({ check: "Plan", state: "SKIP", detail: "tier not reported" });
|
|
20801
|
+
} else if (tierBody.maxExpired) {
|
|
20802
|
+
rows.push({
|
|
20803
|
+
check: "Plan",
|
|
20804
|
+
state: "WARN",
|
|
20805
|
+
detail: tierBody.maxExpiredNotice ?? `Max expired; this account is now on the ${tierBody.tier} plan`
|
|
20806
|
+
});
|
|
20807
|
+
} else {
|
|
20808
|
+
const fee = typeof tierBody.feeBps === "number" ? ` (${tierBody.feeBps / 100}% trade fee)` : "";
|
|
20809
|
+
rows.push({ check: "Plan", state: "PASS", detail: `${tierBody.tier}${fee}` });
|
|
20810
|
+
}
|
|
20811
|
+
}
|
|
20738
20812
|
let account;
|
|
20739
20813
|
if (!apiKey) {
|
|
20740
20814
|
rows.push({ check: "Launch wallet delegated", state: "SKIP", detail: "no API key to check" });
|
|
@@ -21512,6 +21586,58 @@ Console (keys, funding, withdrawal addresses, limits): ${portalDeviceUrl(apiUrl,
|
|
|
21512
21586
|
// src/commands/update.ts
|
|
21513
21587
|
import { createHash as createHash2, randomBytes } from "node:crypto";
|
|
21514
21588
|
|
|
21589
|
+
// src/progress.ts
|
|
21590
|
+
var FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
21591
|
+
var INTERVAL_MS = 80;
|
|
21592
|
+
function stepReporter(write, tty) {
|
|
21593
|
+
let timer = null;
|
|
21594
|
+
let frame = 0;
|
|
21595
|
+
let current = null;
|
|
21596
|
+
const clearSpinner = () => {
|
|
21597
|
+
if (timer !== null)
|
|
21598
|
+
clearInterval(timer);
|
|
21599
|
+
timer = null;
|
|
21600
|
+
if (tty && current !== null)
|
|
21601
|
+
write("\r\x1B[2K");
|
|
21602
|
+
current = null;
|
|
21603
|
+
};
|
|
21604
|
+
return {
|
|
21605
|
+
start(label) {
|
|
21606
|
+
clearSpinner();
|
|
21607
|
+
current = label;
|
|
21608
|
+
if (!tty) {
|
|
21609
|
+
write(`${label}...
|
|
21610
|
+
`);
|
|
21611
|
+
return;
|
|
21612
|
+
}
|
|
21613
|
+
write(`${FRAMES[0]} ${label}`);
|
|
21614
|
+
frame = 1;
|
|
21615
|
+
timer = setInterval(() => {
|
|
21616
|
+
write(`\r\x1B[2K${FRAMES[frame % FRAMES.length]} ${current}`);
|
|
21617
|
+
frame++;
|
|
21618
|
+
}, INTERVAL_MS);
|
|
21619
|
+
if (typeof timer === "object" && "unref" in timer)
|
|
21620
|
+
timer.unref();
|
|
21621
|
+
},
|
|
21622
|
+
done(label) {
|
|
21623
|
+
clearSpinner();
|
|
21624
|
+
write(`✓ ${label}
|
|
21625
|
+
`);
|
|
21626
|
+
},
|
|
21627
|
+
fail(label) {
|
|
21628
|
+
clearSpinner();
|
|
21629
|
+
write(`✗ ${label}
|
|
21630
|
+
`);
|
|
21631
|
+
},
|
|
21632
|
+
stop: clearSpinner
|
|
21633
|
+
};
|
|
21634
|
+
}
|
|
21635
|
+
function formatBytes(n) {
|
|
21636
|
+
if (n >= 1024 * 1024)
|
|
21637
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
21638
|
+
return `${Math.max(1, Math.round(n / 1024))} KB`;
|
|
21639
|
+
}
|
|
21640
|
+
|
|
21515
21641
|
// src/bun-crypto-shim.ts
|
|
21516
21642
|
import crypto2, { KeyObject } from "node:crypto";
|
|
21517
21643
|
var original = crypto2.verify.bind(crypto2);
|
|
@@ -21854,12 +21980,19 @@ async function update(args, ctx) {
|
|
|
21854
21980
|
}, json);
|
|
21855
21981
|
return 1;
|
|
21856
21982
|
}
|
|
21983
|
+
const steps = json ? stepReporter(() => {}, false) : stepReporter((text) => deps.stderr.write(text), process.stderr.isTTY === true);
|
|
21984
|
+
if (!json)
|
|
21985
|
+
deps.stderr.write(`Updating candle ${CLI_VERSION} -> ${target.version}
|
|
21986
|
+
`);
|
|
21987
|
+
steps.start(`downloading ${expectedName}`);
|
|
21857
21988
|
const download = await fetchAll(deps, base, target.tag, expectedName);
|
|
21858
21989
|
if (!download.ok) {
|
|
21990
|
+
steps.fail(`downloading ${expectedName}`);
|
|
21859
21991
|
writeLocalFailure(deps, { code: "UPDATE_UNREACHABLE", message: download.message }, json);
|
|
21860
21992
|
return 1;
|
|
21861
21993
|
}
|
|
21862
21994
|
const { bytes, sums, bundle } = download;
|
|
21995
|
+
steps.done(`downloaded ${expectedName} (${formatBytes(bytes.length)})`);
|
|
21863
21996
|
const dir = realExec.slice(0, realExec.lastIndexOf("/")) || ".";
|
|
21864
21997
|
const tmpPath = `${dir}/.candle-update-${target.version}-${randomBytes(6).toString("hex")}`;
|
|
21865
21998
|
try {
|
|
@@ -21868,10 +22001,12 @@ async function update(args, ctx) {
|
|
|
21868
22001
|
writeLocalFailure(deps, notWritable(dir, error), json);
|
|
21869
22002
|
return 1;
|
|
21870
22003
|
}
|
|
22004
|
+
steps.start("verifying checksum");
|
|
21871
22005
|
const actual = createHash2("sha256").update(bytes).digest("hex");
|
|
21872
22006
|
const fromSums = sums.split(`
|
|
21873
22007
|
`).map((line) => line.trim().split(/\s+/)).find((parts) => parts[1] === expectedName)?.[0];
|
|
21874
22008
|
if (actual !== asset.sha256 || actual !== fromSums) {
|
|
22009
|
+
steps.fail("verifying checksum");
|
|
21875
22010
|
await discard(deps, tmpPath);
|
|
21876
22011
|
writeLocalFailure(deps, {
|
|
21877
22012
|
code: "UPDATE_VERIFY_FAILED",
|
|
@@ -21879,9 +22014,12 @@ async function update(args, ctx) {
|
|
|
21879
22014
|
}, json);
|
|
21880
22015
|
return 1;
|
|
21881
22016
|
}
|
|
22017
|
+
steps.done("checksum verified");
|
|
22018
|
+
steps.start("verifying signature");
|
|
21882
22019
|
const verify = deps.verify ?? verifyReleaseAsset;
|
|
21883
22020
|
const verdict = verify(bytes, bundle, identityUri, RELEASE_ISSUER);
|
|
21884
22021
|
if (!verdict.ok) {
|
|
22022
|
+
steps.fail("verifying signature");
|
|
21885
22023
|
await discard(deps, tmpPath);
|
|
21886
22024
|
writeLocalFailure(deps, {
|
|
21887
22025
|
code: "UPDATE_VERIFY_FAILED",
|
|
@@ -21890,13 +22028,17 @@ async function update(args, ctx) {
|
|
|
21890
22028
|
}, json);
|
|
21891
22029
|
return 1;
|
|
21892
22030
|
}
|
|
22031
|
+
steps.done("signature verified");
|
|
22032
|
+
steps.start("installing");
|
|
21893
22033
|
try {
|
|
21894
22034
|
await deps.rename(tmpPath, realExec);
|
|
21895
22035
|
} catch (error) {
|
|
22036
|
+
steps.fail("installing");
|
|
21896
22037
|
await discard(deps, tmpPath);
|
|
21897
22038
|
writeLocalFailure(deps, notWritable(dir, error), json);
|
|
21898
22039
|
return 1;
|
|
21899
22040
|
}
|
|
22041
|
+
steps.done(`installed to ${realExec}`);
|
|
21900
22042
|
if (json) {
|
|
21901
22043
|
const payload = { current: CLI_VERSION, latest: target.version, updated: true, path: realExec };
|
|
21902
22044
|
deps.stdout.write(`${JSON.stringify(payload)}
|
|
@@ -28474,6 +28616,30 @@ async function resolveSecretStore(platform = process.platform) {
|
|
|
28474
28616
|
return { store: new EncryptedFileSecretStore, backend: "encrypted-file" };
|
|
28475
28617
|
}
|
|
28476
28618
|
|
|
28619
|
+
// src/update-notice.ts
|
|
28620
|
+
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
28621
|
+
async function maybeWriteUpdateNotice(deps, opts = {}) {
|
|
28622
|
+
try {
|
|
28623
|
+
if (deps.env.CANDLE_NO_UPDATE_NOTIFIER)
|
|
28624
|
+
return;
|
|
28625
|
+
if (opts.command === "update" || opts.command === "doctor")
|
|
28626
|
+
return;
|
|
28627
|
+
const latest = latestCliVersionFromApi();
|
|
28628
|
+
if (!latest || !isPlainVersion(latest) || compareVersions(latest, CLI_VERSION) <= 0)
|
|
28629
|
+
return;
|
|
28630
|
+
const config = await deps.readConfig();
|
|
28631
|
+
const prior = config.updateNotice;
|
|
28632
|
+
if (prior && prior.version === latest && deps.now() - prior.shownAt < DAY_MS)
|
|
28633
|
+
return;
|
|
28634
|
+
const line = `Update available: candle ${CLI_VERSION} -> ${latest}. Run: candle update`;
|
|
28635
|
+
const tty = process.stderr.isTTY === true;
|
|
28636
|
+
deps.stderr.write(tty ? `\x1B[2m${line}\x1B[0m
|
|
28637
|
+
` : `${line}
|
|
28638
|
+
`);
|
|
28639
|
+
await deps.writeConfig({ updateNotice: { version: latest, shownAt: deps.now() } });
|
|
28640
|
+
} catch {}
|
|
28641
|
+
}
|
|
28642
|
+
|
|
28477
28643
|
// src/index.ts
|
|
28478
28644
|
function extractGlobalFlags(argv) {
|
|
28479
28645
|
const rest = [];
|
|
@@ -28590,6 +28756,13 @@ function routesToCommand(cmd, sub) {
|
|
|
28590
28756
|
}
|
|
28591
28757
|
var NEVER_GUARDED = new Set(["auth", "profile", "doctor", "verify", "update"]);
|
|
28592
28758
|
async function run2(argv, deps) {
|
|
28759
|
+
const code = await runCommand(argv, deps);
|
|
28760
|
+
const extractedForNotice = extractGlobalFlags(argv);
|
|
28761
|
+
const word = "error" in extractedForNotice ? undefined : canonicalCommand(extractedForNotice.rest[0] === "candle" ? extractedForNotice.rest[1] : extractedForNotice.rest[0]);
|
|
28762
|
+
await maybeWriteUpdateNotice(deps, { command: word });
|
|
28763
|
+
return code;
|
|
28764
|
+
}
|
|
28765
|
+
async function runCommand(argv, deps) {
|
|
28593
28766
|
const extracted = extractGlobalFlags(argv);
|
|
28594
28767
|
if ("error" in extracted) {
|
|
28595
28768
|
deps.stderr.write(`${extracted.error}
|
package/package.json
CHANGED