@t2000/cli 3.2.0 → 3.3.0

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 CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  saveKey,
13
13
  truncateAddress,
14
14
  walletExists
15
- } from "./chunk-ZH6PX6WS.js";
15
+ } from "./chunk-YSV3YXTK.js";
16
16
  import {
17
17
  esm_default3 as esm_default,
18
18
  esm_default8 as esm_default2
@@ -4147,23 +4147,33 @@ function registerSave(program3) {
4147
4147
  }
4148
4148
 
4149
4149
  // src/commands/withdraw.ts
4150
+ var WITHDRAW_ASSETS = ["USDC", "USDsui"];
4151
+ function resolveWithdrawAsset(input) {
4152
+ if (!input) return void 0;
4153
+ const match2 = WITHDRAW_ASSETS.find((a) => a.toLowerCase() === input.toLowerCase());
4154
+ if (!match2) {
4155
+ throw new Error(`--asset must be one of: ${WITHDRAW_ASSETS.join(", ")}. Got: "${input}"`);
4156
+ }
4157
+ return match2;
4158
+ }
4150
4159
  function registerWithdraw(program3) {
4151
- program3.command("withdraw").description("Withdraw USDC or USDsui from NAVI lending").argument("<amount>", 'Amount to withdraw (or "all")').option("--key <path>", "Key file path").option("--protocol <name>", "Protocol to use (e.g. navi)").option("--asset <token>", "Asset to withdraw (default: auto-detect)").action(async (amountStr, opts) => {
4160
+ program3.command("withdraw").description("Withdraw USDC or USDsui from NAVI lending").argument("<amount>", 'Amount to withdraw (or "all")').option("--key <path>", "Key file path").option("--protocol <name>", "Protocol to use (e.g. navi)").option("--asset <symbol>", "Asset to withdraw: USDC or USDsui (omit to auto-detect)").action(async (amountStr, opts) => {
4152
4161
  try {
4153
4162
  const amount = amountStr === "all" ? "all" : parseFloat(amountStr);
4154
4163
  if (amount !== "all" && (isNaN(amount) || amount <= 0)) {
4155
4164
  throw new Error('Amount must be a positive number or "all"');
4156
4165
  }
4166
+ const asset = resolveWithdrawAsset(opts.asset);
4157
4167
  const pin = await resolvePin();
4158
4168
  const agent = await T2000.create({ pin, keyPath: opts.key });
4159
- const result = await agent.withdraw({ amount, asset: opts.asset, protocol: opts.protocol });
4169
+ const result = await agent.withdraw({ amount, asset, protocol: opts.protocol });
4160
4170
  if (isJsonMode()) {
4161
4171
  printJson(result);
4162
4172
  return;
4163
4173
  }
4164
- const assetLabel = opts.asset ?? "USDC";
4174
+ const withdrawnAsset = result.asset ?? asset ?? "USDC";
4165
4175
  printBlank();
4166
- printSuccess(`Withdrew ${formatUsd(result.amount)} ${assetLabel}`);
4176
+ printSuccess(`Withdrew ${formatUsd(result.amount)} ${withdrawnAsset}`);
4167
4177
  printKeyValue("Tx", explorerUrl(result.tx));
4168
4178
  printBlank();
4169
4179
  } catch (error) {
@@ -7881,7 +7891,7 @@ function registerLock(program3) {
7881
7891
  });
7882
7892
  program3.command("unlock").description("Unlock agent \u2014 resume operations").action(async () => {
7883
7893
  try {
7884
- const { T2000: T20003 } = await import("./dist-UOJPIH47.js");
7894
+ const { T2000: T20003 } = await import("./dist-7RF5QOXU.js");
7885
7895
  const MAX_ATTEMPTS2 = 3;
7886
7896
  let pin;
7887
7897
  for (let attempt = 1; attempt <= MAX_ATTEMPTS2; attempt++) {
@@ -8055,7 +8065,7 @@ function registerMcp(program3) {
8055
8065
  mcp.command("start", { isDefault: true }).description("Start MCP server (stdio transport)").option("--key <path>", "Key file path").action(async (opts) => {
8056
8066
  let mod;
8057
8067
  try {
8058
- mod = await import("./dist-NH7XYB4F.js");
8068
+ mod = await import("./dist-UDLQ4IJN.js");
8059
8069
  } catch {
8060
8070
  console.error(
8061
8071
  "MCP server not installed. Run:\n npm install -g @t2000/mcp"
@@ -8322,64 +8332,8 @@ function registerSwapQuote(program3) {
8322
8332
  });
8323
8333
  }
8324
8334
 
8325
- // src/commands/stake.ts
8326
- var import_picocolors15 = __toESM(require_picocolors(), 1);
8327
- function registerStake(program3) {
8328
- program3.command("stake").description("Stake SUI for vSUI via VOLO liquid staking (earn ~3-5% APY)").argument("<amount>", "Amount of SUI to stake (minimum 1)").option("--key <path>", "Key file path").action(async (amountStr, opts) => {
8329
- try {
8330
- const amount = parseFloat(amountStr);
8331
- if (isNaN(amount) || amount < 1) {
8332
- throw new Error("Amount must be at least 1 SUI");
8333
- }
8334
- const pin = await resolvePin();
8335
- const agent = await T2000.create({ pin, keyPath: opts.key });
8336
- const result = await agent.stakeVSui({ amount });
8337
- if (isJsonMode()) {
8338
- printJson(result);
8339
- return;
8340
- }
8341
- printBlank();
8342
- printSuccess(`Staked ${import_picocolors15.default.yellow(String(result.amountSui))} SUI for ${import_picocolors15.default.green(result.vSuiReceived.toFixed(4))} vSUI`);
8343
- printSuccess(`APY: ${import_picocolors15.default.green(`${(result.apy * 100).toFixed(2)}%`)}`);
8344
- printKeyValue("Gas", `${result.gasCost.toFixed(4)} SUI`);
8345
- printKeyValue("Tx", explorerUrl(result.tx));
8346
- printBlank();
8347
- } catch (error) {
8348
- handleError(error);
8349
- }
8350
- });
8351
- }
8352
-
8353
- // src/commands/unstake.ts
8354
- var import_picocolors16 = __toESM(require_picocolors(), 1);
8355
- function registerUnstake(program3) {
8356
- program3.command("unstake").description("Unstake vSUI back to SUI (returns SUI including accumulated yield)").argument("<amount>", 'Amount of vSUI to unstake (or "all")').option("--key <path>", "Key file path").action(async (amountStr, opts) => {
8357
- try {
8358
- const amount = amountStr === "all" ? "all" : parseFloat(amountStr);
8359
- if (amount !== "all" && (isNaN(amount) || amount <= 0)) {
8360
- throw new Error('Amount must be a positive number or "all"');
8361
- }
8362
- const pin = await resolvePin();
8363
- const agent = await T2000.create({ pin, keyPath: opts.key });
8364
- const result = await agent.unstakeVSui({ amount });
8365
- if (isJsonMode()) {
8366
- printJson(result);
8367
- return;
8368
- }
8369
- printBlank();
8370
- printSuccess(`Unstaked ${import_picocolors16.default.yellow(result.vSuiAmount.toFixed(4))} vSUI`);
8371
- printSuccess(`Received ${import_picocolors16.default.green(result.suiReceived.toFixed(4))} SUI`);
8372
- printKeyValue("Gas", `${result.gasCost.toFixed(4)} SUI`);
8373
- printKeyValue("Tx", explorerUrl(result.tx));
8374
- printBlank();
8375
- } catch (error) {
8376
- handleError(error);
8377
- }
8378
- });
8379
- }
8380
-
8381
8335
  // src/commands/receive.ts
8382
- var import_picocolors17 = __toESM(require_picocolors(), 1);
8336
+ var import_picocolors15 = __toESM(require_picocolors(), 1);
8383
8337
  function registerReceive(program3) {
8384
8338
  program3.command("receive").description("Generate a payment request with address and QR code").option("--amount <number>", "Amount to request").option("--currency <symbol>", "Currency (default: USDC)", "USDC").option("--memo <text>", "Payment note").option("--label <text>", "Description for the request").option("--key <path>", "Key file path").action(async (opts) => {
8385
8339
  try {
@@ -8401,13 +8355,13 @@ function registerReceive(program3) {
8401
8355
  }
8402
8356
  printHeader("Payment Request");
8403
8357
  if (request.label) {
8404
- printLine(import_picocolors17.default.bold(request.label));
8358
+ printLine(import_picocolors15.default.bold(request.label));
8405
8359
  printBlank();
8406
8360
  }
8407
8361
  if (request.amount != null) {
8408
- printLine(import_picocolors17.default.bold(` $${request.amount.toFixed(2)} ${request.currency}`));
8362
+ printLine(import_picocolors15.default.bold(` $${request.amount.toFixed(2)} ${request.currency}`));
8409
8363
  } else {
8410
- printLine(import_picocolors17.default.dim(" Any amount") + ` ${request.currency}`);
8364
+ printLine(import_picocolors15.default.dim(" Any amount") + ` ${request.currency}`);
8411
8365
  }
8412
8366
  printBlank();
8413
8367
  printDivider();
@@ -8421,7 +8375,7 @@ function registerReceive(program3) {
8421
8375
  printBlank();
8422
8376
  printKeyValue("Payment URI", request.qrUri);
8423
8377
  printBlank();
8424
- printLine(import_picocolors17.default.dim("Share this URI or scan the QR to pay via any Sui wallet."));
8378
+ printLine(import_picocolors15.default.dim("Share this URI or scan the QR to pay via any Sui wallet."));
8425
8379
  printBlank();
8426
8380
  } catch (error) {
8427
8381
  handleError(error);
@@ -8429,6 +8383,199 @@ function registerReceive(program3) {
8429
8383
  });
8430
8384
  }
8431
8385
 
8386
+ // src/commands/skills.ts
8387
+ import { writeFile as writeFile5, mkdir as mkdir5, readdir, unlink as unlink2, rmdir, stat } from "fs/promises";
8388
+ import { join as join8 } from "path";
8389
+ import { homedir as homedir9 } from "os";
8390
+ var MANIFEST_URL = "https://t2000.ai/.well-known/agent-skills/index.json";
8391
+ var SKILL_PREFIXES = ["t2000-", "mpp-"];
8392
+ function isManagedSkillName(name) {
8393
+ return SKILL_PREFIXES.some((prefix) => name.startsWith(prefix));
8394
+ }
8395
+ var SKILL_TARGETS = ["agents", "cursor", "claude-code"];
8396
+ function resolveTargetDir(target, useGlobal, cwd = process.cwd()) {
8397
+ const root = useGlobal ? homedir9() : cwd;
8398
+ switch (target) {
8399
+ case "agents":
8400
+ return join8(root, ".agents", "skills");
8401
+ case "cursor":
8402
+ return join8(root, ".cursor", "rules");
8403
+ case "claude-code":
8404
+ return join8(root, ".claude", "skills");
8405
+ }
8406
+ }
8407
+ function filenameForTarget(slug, target) {
8408
+ switch (target) {
8409
+ case "agents":
8410
+ case "claude-code":
8411
+ return join8(slug, "SKILL.md");
8412
+ case "cursor":
8413
+ return `${slug}.mdc`;
8414
+ }
8415
+ }
8416
+ function transformForTarget(content, target, description) {
8417
+ if (target !== "cursor") return content;
8418
+ const stripped = content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, "");
8419
+ const safeDescription = JSON.stringify(description);
8420
+ return `---
8421
+ description: ${safeDescription}
8422
+ alwaysApply: false
8423
+ ---
8424
+ ${stripped}`;
8425
+ }
8426
+ function resolveSkillTarget(input) {
8427
+ const value = input ?? "agents";
8428
+ const match2 = SKILL_TARGETS.find((t) => t === value);
8429
+ if (!match2) {
8430
+ throw new Error(`--target must be one of: ${SKILL_TARGETS.join(", ")}. Got: "${value}"`);
8431
+ }
8432
+ return match2;
8433
+ }
8434
+ async function fetchManifest() {
8435
+ const res = await fetch(MANIFEST_URL);
8436
+ if (!res.ok) {
8437
+ throw new Error(
8438
+ `Failed to fetch skills manifest from ${MANIFEST_URL} (${res.status} ${res.statusText}). Check your network or fall back to \`git clone https://github.com/mission69b/t2000\` for offline install.`
8439
+ );
8440
+ }
8441
+ return await res.json();
8442
+ }
8443
+ async function fetchSkill(url) {
8444
+ const res = await fetch(url);
8445
+ if (!res.ok) {
8446
+ throw new Error(`Failed to fetch skill ${url} (${res.status} ${res.statusText})`);
8447
+ }
8448
+ return await res.text();
8449
+ }
8450
+ async function dirExists(path) {
8451
+ try {
8452
+ const s = await stat(path);
8453
+ return s.isDirectory();
8454
+ } catch {
8455
+ return false;
8456
+ }
8457
+ }
8458
+ function registerSkills(program3) {
8459
+ const skills = program3.command("skills").description("Install t2000 skills as local SKILL.md files (alternative to `t2000 mcp install`)");
8460
+ skills.command("list").description("List the skills available from t2000.ai (core t2000 + MPP recipes)").action(async () => {
8461
+ try {
8462
+ const manifest = await fetchManifest();
8463
+ if (isJsonMode()) {
8464
+ printJson({ skills: manifest.skills });
8465
+ return;
8466
+ }
8467
+ printBlank();
8468
+ printInfo(`${manifest.skills.length} skills available:`);
8469
+ printBlank();
8470
+ for (const s of manifest.skills) {
8471
+ console.log(` ${s.name.padEnd(28)} v${s.version}`);
8472
+ }
8473
+ printBlank();
8474
+ printInfo(`Install all: t2000 skills install`);
8475
+ printInfo(`Install one: t2000 skills install <name>`);
8476
+ printBlank();
8477
+ } catch (err) {
8478
+ handleError(err);
8479
+ }
8480
+ });
8481
+ skills.command("install [slug]").description("Install all skills (or one named slug) into a local directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Install to ~/.<target>/ instead of <cwd>/.<target>/").action(async (slug, opts) => {
8482
+ try {
8483
+ const target = resolveSkillTarget(opts.target);
8484
+ const useGlobal = opts.global === true;
8485
+ const manifest = await fetchManifest();
8486
+ const toInstall = slug ? manifest.skills.filter((s) => s.name === slug) : manifest.skills;
8487
+ if (toInstall.length === 0) {
8488
+ const available = manifest.skills.map((s) => s.name).join(", ");
8489
+ throw new Error(
8490
+ slug ? `Unknown skill: "${slug}". Available: ${available}` : "No skills found in manifest"
8491
+ );
8492
+ }
8493
+ const targetDir = resolveTargetDir(target, useGlobal);
8494
+ await mkdir5(targetDir, { recursive: true });
8495
+ const installed = [];
8496
+ for (const s of toInstall) {
8497
+ const raw2 = await fetchSkill(s.url);
8498
+ const transformed = transformForTarget(raw2, target, s.description);
8499
+ const relPath = filenameForTarget(s.name, target);
8500
+ const fullPath = join8(targetDir, relPath);
8501
+ await mkdir5(join8(fullPath, ".."), { recursive: true });
8502
+ await writeFile5(fullPath, transformed, "utf-8");
8503
+ installed.push({ name: s.name, path: fullPath });
8504
+ }
8505
+ if (isJsonMode()) {
8506
+ printJson({ target, global: useGlobal, targetDir, installed });
8507
+ return;
8508
+ }
8509
+ printBlank();
8510
+ printSuccess(`Installed ${installed.length} skill${installed.length === 1 ? "" : "s"} into ${targetDir}`);
8511
+ for (const r of installed) {
8512
+ console.log(` ${r.name}`);
8513
+ }
8514
+ printBlank();
8515
+ printInfo("Reload your AI client to pick up the new skill files.");
8516
+ if (target !== "cursor") {
8517
+ printInfo("(For an MCP-aware client, prefer `t2000 mcp install` \u2014 same skills, zero local files.)");
8518
+ }
8519
+ printBlank();
8520
+ } catch (err) {
8521
+ handleError(err);
8522
+ }
8523
+ });
8524
+ skills.command("uninstall").description("Remove installed t2000 + MPP skills from the target directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Uninstall from ~/.<target>/ instead of <cwd>/.<target>/").action(async (opts) => {
8525
+ try {
8526
+ const target = resolveSkillTarget(opts.target);
8527
+ const useGlobal = opts.global === true;
8528
+ const targetDir = resolveTargetDir(target, useGlobal);
8529
+ if (!await dirExists(targetDir)) {
8530
+ if (isJsonMode()) {
8531
+ printJson({ target, targetDir, removed: [] });
8532
+ return;
8533
+ }
8534
+ printInfo(`No skills installed at ${targetDir}`);
8535
+ return;
8536
+ }
8537
+ const entries = await readdir(targetDir);
8538
+ const removed = [];
8539
+ for (const entry of entries) {
8540
+ const full = join8(targetDir, entry);
8541
+ if (target === "cursor") {
8542
+ const slug = entry.endsWith(".mdc") ? entry.slice(0, -".mdc".length) : entry;
8543
+ if (entry.endsWith(".mdc") && isManagedSkillName(slug)) {
8544
+ await unlink2(full);
8545
+ removed.push(entry);
8546
+ }
8547
+ } else {
8548
+ if (isManagedSkillName(entry)) {
8549
+ const skillFile = join8(full, "SKILL.md");
8550
+ try {
8551
+ await unlink2(skillFile);
8552
+ } catch {
8553
+ }
8554
+ try {
8555
+ await rmdir(full);
8556
+ } catch {
8557
+ }
8558
+ removed.push(entry);
8559
+ }
8560
+ }
8561
+ }
8562
+ if (isJsonMode()) {
8563
+ printJson({ target, targetDir, removed });
8564
+ return;
8565
+ }
8566
+ printBlank();
8567
+ if (removed.length === 0) {
8568
+ printInfo(`No managed skills found in ${targetDir}`);
8569
+ } else {
8570
+ printSuccess(`Removed ${removed.length} skill${removed.length === 1 ? "" : "s"} from ${targetDir}`);
8571
+ }
8572
+ printBlank();
8573
+ } catch (err) {
8574
+ handleError(err);
8575
+ }
8576
+ });
8577
+ }
8578
+
8432
8579
  // src/program.ts
8433
8580
  var require2 = createRequire(import.meta.url);
8434
8581
  var { version: CLI_VERSION } = require2("../package.json");
@@ -8449,7 +8596,8 @@ Examples:
8449
8596
  $ t2000 swap 100 USDC SUI Swap 100 USDC for SUI
8450
8597
  $ t2000 borrow 200 Borrow $200 against savings
8451
8598
  $ t2000 pay openai ... Pay for an API via MPP gateway
8452
- $ t2000 mcp install Connect Claude / Cursor / Windsurf`);
8599
+ $ t2000 mcp install Connect Claude / Cursor / Windsurf (all skills come along as MCP prompts)
8600
+ $ t2000 skills install Install skills as local SKILL.md files (alternative to MCP)`);
8453
8601
  registerInit(program3);
8454
8602
  registerSend(program3);
8455
8603
  registerBalance(program3);
@@ -8477,9 +8625,8 @@ Examples:
8477
8625
  registerClaimRewards(program3);
8478
8626
  registerSwap(program3);
8479
8627
  registerSwapQuote(program3);
8480
- registerStake(program3);
8481
- registerUnstake(program3);
8482
8628
  registerReceive(program3);
8629
+ registerSkills(program3);
8483
8630
  return program3;
8484
8631
  }
8485
8632