thinyai 0.1.11 → 0.1.13
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/bin.js +65 -19
- package/package.json +7 -7
package/dist/bin.js
CHANGED
|
@@ -1535,18 +1535,13 @@ function explorerTxUrl(network, digest) {
|
|
|
1535
1535
|
function suiPlugin(opts) {
|
|
1536
1536
|
const sig = opts.signer;
|
|
1537
1537
|
const resolve2 = typeof sig === "function" ? sig : () => sig;
|
|
1538
|
-
const
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
"No Sui wallet configured yet. Call sui_setup to create or import one (or tell the user to run `thiny sui init`)."
|
|
1543
|
-
);
|
|
1544
|
-
}
|
|
1545
|
-
return s;
|
|
1538
|
+
const SETUP_NEEDED = {
|
|
1539
|
+
ok: false,
|
|
1540
|
+
setupNeeded: true,
|
|
1541
|
+
message: "Sui isn't set up yet. Ask the user which network (testnet or mainnet) and which wallet (generate a new key, import a private key, or use a Rill agent wallet), then call sui_setup. Do NOT retry this tool until setup is complete."
|
|
1546
1542
|
};
|
|
1547
1543
|
const requireSimSuccess = opts.policy?.requireSimSuccess ?? true;
|
|
1548
|
-
const executeTx = async (tx, toolName, approvalArgs, reason) => {
|
|
1549
|
-
const signer = signerOrThrow();
|
|
1544
|
+
const executeTx = async (signer, tx, toolName, approvalArgs, reason) => {
|
|
1550
1545
|
const sim = await signer.devInspect(tx);
|
|
1551
1546
|
const status = sim.effects.status.status;
|
|
1552
1547
|
if (requireSimSuccess && status !== "success") {
|
|
@@ -1576,10 +1571,11 @@ function suiPlugin(opts) {
|
|
|
1576
1571
|
coinType: z4.string().optional().describe("Coin type, e.g. 0x2::sui::SUI (default: SUI).")
|
|
1577
1572
|
}),
|
|
1578
1573
|
execute: async ({ address, coinType }) => {
|
|
1579
|
-
const signer =
|
|
1574
|
+
const signer = resolve2();
|
|
1575
|
+
if (!signer) return SETUP_NEEDED;
|
|
1580
1576
|
const owner = address ?? signer.address;
|
|
1581
1577
|
if (owner === void 0) {
|
|
1582
|
-
|
|
1578
|
+
return { ok: false, message: "No address given and no wallet is set up. Run sui_setup first." };
|
|
1583
1579
|
}
|
|
1584
1580
|
const bal = await signer.client.getBalance({ owner, ...coinType ? { coinType } : {} });
|
|
1585
1581
|
return {
|
|
@@ -1595,7 +1591,8 @@ function suiPlugin(opts) {
|
|
|
1595
1591
|
description: "Read a Sui object's type and fields by id.",
|
|
1596
1592
|
parameters: z4.object({ objectId: z4.string().min(1).describe("The object id (0x\u2026).") }),
|
|
1597
1593
|
execute: async ({ objectId }) => {
|
|
1598
|
-
const signer =
|
|
1594
|
+
const signer = resolve2();
|
|
1595
|
+
if (!signer) return SETUP_NEEDED;
|
|
1599
1596
|
const res = await signer.client.getObject({
|
|
1600
1597
|
id: objectId,
|
|
1601
1598
|
options: { showContent: true, showType: true, showOwner: true }
|
|
@@ -1617,8 +1614,10 @@ function suiPlugin(opts) {
|
|
|
1617
1614
|
unsignedTx: z4.string().min(1).describe("Unsigned PTB \u2014 the JSON string from Transaction.toJSON() (no sender, no gas).")
|
|
1618
1615
|
}),
|
|
1619
1616
|
execute: async ({ unsignedTx }) => {
|
|
1617
|
+
const signer = resolve2();
|
|
1618
|
+
if (!signer) return SETUP_NEEDED;
|
|
1620
1619
|
const tx = Transaction2.from(unsignedTx);
|
|
1621
|
-
return await executeTx(tx, "sui_execute_ptb", { unsignedTx }, "sign and submit a Sui PTB");
|
|
1620
|
+
return await executeTx(signer, tx, "sui_execute_ptb", { unsignedTx }, "sign and submit a Sui PTB");
|
|
1622
1621
|
}
|
|
1623
1622
|
});
|
|
1624
1623
|
const transfer = defineTool({
|
|
@@ -1631,7 +1630,8 @@ function suiPlugin(opts) {
|
|
|
1631
1630
|
coinType: z4.string().optional().describe("Coin type (default 0x2::sui::SUI).")
|
|
1632
1631
|
}),
|
|
1633
1632
|
execute: async ({ recipient, amountMist, coinType }) => {
|
|
1634
|
-
const signer =
|
|
1633
|
+
const signer = resolve2();
|
|
1634
|
+
if (!signer) return SETUP_NEEDED;
|
|
1635
1635
|
const amount = BigInt(amountMist);
|
|
1636
1636
|
const type = coinType ?? "0x2::sui::SUI";
|
|
1637
1637
|
const tx = new Transaction2();
|
|
@@ -1640,7 +1640,7 @@ function suiPlugin(opts) {
|
|
|
1640
1640
|
tx.transferObjects([coin], tx.pure.address(recipient));
|
|
1641
1641
|
} else {
|
|
1642
1642
|
const owner = signer.address;
|
|
1643
|
-
if (owner === void 0)
|
|
1643
|
+
if (owner === void 0) return { ok: false, message: "Wallet has no address. Run sui_setup." };
|
|
1644
1644
|
const { data } = await signer.client.getCoins({ owner, coinType: type });
|
|
1645
1645
|
const [first, ...rest] = data;
|
|
1646
1646
|
if (!first) throw new Error(`sui_transfer: no ${type} coins owned by ${owner}.`);
|
|
@@ -1652,6 +1652,7 @@ function suiPlugin(opts) {
|
|
|
1652
1652
|
tx.transferObjects([coin], tx.pure.address(recipient));
|
|
1653
1653
|
}
|
|
1654
1654
|
return executeTx(
|
|
1655
|
+
signer,
|
|
1655
1656
|
tx,
|
|
1656
1657
|
"sui_transfer",
|
|
1657
1658
|
{ recipient, amountMist, coinType: type },
|
|
@@ -1675,6 +1676,8 @@ function suiPlugin(opts) {
|
|
|
1675
1676
|
).optional().describe("Ordered arguments to the function.")
|
|
1676
1677
|
}),
|
|
1677
1678
|
execute: async ({ target, typeArguments, args }) => {
|
|
1679
|
+
const signer = resolve2();
|
|
1680
|
+
if (!signer) return SETUP_NEEDED;
|
|
1678
1681
|
const tx = new Transaction2();
|
|
1679
1682
|
const built = (args ?? []).map((a) => {
|
|
1680
1683
|
if (a.kind === "gas") return tx.gas;
|
|
@@ -1705,7 +1708,7 @@ function suiPlugin(opts) {
|
|
|
1705
1708
|
}
|
|
1706
1709
|
});
|
|
1707
1710
|
tx.moveCall({ target, typeArguments: typeArguments ?? [], arguments: built });
|
|
1708
|
-
return await executeTx(tx, "sui_move_call", { target, typeArguments, args }, `Move call ${target}`);
|
|
1711
|
+
return await executeTx(signer, tx, "sui_move_call", { target, typeArguments, args }, `Move call ${target}`);
|
|
1709
1712
|
}
|
|
1710
1713
|
});
|
|
1711
1714
|
return { name: "sui", tools: [balance, object, executePtb, transfer, moveCall] };
|
|
@@ -2796,12 +2799,55 @@ async function runCli() {
|
|
|
2796
2799
|
return { activeAddress: address, note: `Now signing as ${address}.` };
|
|
2797
2800
|
}
|
|
2798
2801
|
});
|
|
2802
|
+
const suiBalancesTool = defineTool({
|
|
2803
|
+
name: "sui_balances",
|
|
2804
|
+
description: "Fetch ALL coin balances across ALL of the user's Sui addresses on a network. Use for 'what's my balance / what coins do I have'. Returns each address with its coins. SUI amounts are also given in whole SUI (1 SUI = 1e9 MIST).",
|
|
2805
|
+
parameters: z7.object({
|
|
2806
|
+
network: z7.enum(["testnet", "mainnet"]).optional().describe("Network (default: the active one)."),
|
|
2807
|
+
address: z7.string().optional().describe("Limit to one address (default: all the user's wallets).")
|
|
2808
|
+
}),
|
|
2809
|
+
execute: async ({ network: network2, address }) => {
|
|
2810
|
+
const net = network2 ?? suiNetwork;
|
|
2811
|
+
const client = net === suiNetwork && suiSignerRef ? suiSignerRef.client : suiSigner({ network: net }).client;
|
|
2812
|
+
const walletAddrs = suiWalletsOf(loadConfig()).map((w) => w.address);
|
|
2813
|
+
if (suiSignerRef?.address && !walletAddrs.includes(suiSignerRef.address)) {
|
|
2814
|
+
walletAddrs.push(suiSignerRef.address);
|
|
2815
|
+
}
|
|
2816
|
+
const addrs = address ? [address] : walletAddrs;
|
|
2817
|
+
if (addrs.length === 0) {
|
|
2818
|
+
return {
|
|
2819
|
+
ok: false,
|
|
2820
|
+
setupNeeded: true,
|
|
2821
|
+
message: "Sui isn't set up. Ask the user which network and wallet (generate / import / Rill), then call sui_setup. Don't retry until then."
|
|
2822
|
+
};
|
|
2823
|
+
}
|
|
2824
|
+
const addresses = [];
|
|
2825
|
+
for (const addr of addrs) {
|
|
2826
|
+
const balances = await client.getAllBalances({ owner: addr });
|
|
2827
|
+
addresses.push({
|
|
2828
|
+
address: addr,
|
|
2829
|
+
coins: balances.map((b) => {
|
|
2830
|
+
const symbol = b.coinType.split("::").pop() ?? b.coinType;
|
|
2831
|
+
const isSui = b.coinType.endsWith("::sui::SUI");
|
|
2832
|
+
return {
|
|
2833
|
+
symbol,
|
|
2834
|
+
coinType: b.coinType,
|
|
2835
|
+
balanceMist: b.totalBalance,
|
|
2836
|
+
...isSui ? { sui: Number(b.totalBalance) / 1e9 } : {}
|
|
2837
|
+
};
|
|
2838
|
+
})
|
|
2839
|
+
});
|
|
2840
|
+
}
|
|
2841
|
+
return { network: net, addresses };
|
|
2842
|
+
}
|
|
2843
|
+
});
|
|
2799
2844
|
const walletTools = [
|
|
2800
2845
|
suiWalletsTool,
|
|
2801
2846
|
suiCreateWalletTool,
|
|
2802
2847
|
suiImportWalletTool,
|
|
2803
2848
|
suiExportWalletTool,
|
|
2804
|
-
suiUseWalletTool
|
|
2849
|
+
suiUseWalletTool,
|
|
2850
|
+
suiBalancesTool
|
|
2805
2851
|
];
|
|
2806
2852
|
const fetchUrlTool = defineTool({
|
|
2807
2853
|
name: "fetch_url",
|
|
@@ -2874,7 +2920,7 @@ HOW TO ACT: When a request maps to one of your tools, CALL THE TOOL automaticall
|
|
|
2874
2920
|
YOUR TOOLS:
|
|
2875
2921
|
\u2022 Memory \u2014 remember_fact: durable memory across sessions. Whenever the user shares anything durable about themselves (name, role, preferences, projects, goals), call remember_fact ONCE to save it. Your known facts are AUTO-INJECTED at the top of every conversation under \u201C[User Memory \u2026]\u201D, so answer \u201Cwhat do you remember / what's my name\u201D directly from that context \u2014 do NOT call recall_memory unless the injected memory is empty and you truly need to re-check. You DO remember across sessions; never say otherwise.
|
|
2876
2922
|
\u2022 Links \u2014 fetch_url: read ANY URL the user shares (a skill.md, docs, JSON, an API/MCP endpoint). Always fetch shared links instead of saying you can't open URLs.
|
|
2877
|
-
` + (webSearchOn ? "\u2022 Web search \u2014 web_search: search the web for anything you don't know (news, prices, docs). web_search FINDS pages by query; fetch_url READS a specific URL \u2014 use them together.\n" : "") + "\u2022 Planning \u2014 update_plan (track multi-step work), delegate_task (hand a focused subtask to a sub-agent).\n\u2022 Sui blockchain \u2014 you transact yourself; NEVER tell the user to install a browser wallet. " + (suiSignerRef ? `The active wallet is on ${suiNetwork} at ${suiSignerRef.address ?? "?"}. ` : "
|
|
2923
|
+
` + (webSearchOn ? "\u2022 Web search \u2014 web_search: search the web for anything you don't know (news, prices, docs). web_search FINDS pages by query; fetch_url READS a specific URL \u2014 use them together.\n" : "") + "\u2022 Planning \u2014 update_plan (track multi-step work), delegate_task (hand a focused subtask to a sub-agent).\n\u2022 Sui blockchain \u2014 you transact yourself; NEVER tell the user to install a browser wallet. " + (suiSignerRef ? `Sui IS set up. The user's primary (active) wallet is on ${suiNetwork} at ${suiSignerRef.address ?? "?"}. ` : "Sui is NOT set up yet. When the user wants anything Sui-related, FIRST ask if they'd like you to set it up, and ask which network (testnet/mainnet) and which wallet option (generate a new key, import a suiprivkey, or use a Rill agent wallet). Then call sui_setup with their choices. Do not attempt other Sui tools until setup succeeds. ") + "Wallet tools: sui_wallets (list ALL wallets + which is primary/active \u2014 answer 'what's my address' from this), sui_balances (ALL coins across ALL addresses on a network \u2014 answer 'what's my balance' with this), sui_create_wallet, sui_import_wallet, sui_export_wallet (reveal a key only when asked), sui_use_wallet (switch primary). Never overwrite or replace an existing wallet \u2014 adding a wallet keeps the others. If it's unclear which wallet to use, ask the user which is their primary. On-chain: sui_balance & sui_object (read), sui_transfer (send SUI/any coin \u2014 amounts in MIST, 1 SUI = 1e9), sui_move_call (call ANY Move function), sui_execute_ptb (sign a builder/Rill PTB). Prefer sui_transfer for sends and sui_move_call for contract calls; confirm details before signing.\nWhen ANY Sui tool fails, do NOT paste raw JSON or stack traces \u2014 explain what went wrong in one plain sentence and what to do next. Present balances/results readably (SUI amounts in whole SUI, short addresses), and keep every answer brief and to the point.",
|
|
2878
2924
|
tools: [echoTool, suiSetupTool, ...walletTools, fetchUrlTool, ...webTools],
|
|
2879
2925
|
plugins: [
|
|
2880
2926
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thinyai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Thiny AI — a beautiful terminal agent: interactive chat, tools, Walrus memory, and Sui execution.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
"tsup": "^8.5.1",
|
|
39
39
|
"typescript": "^5.5.0",
|
|
40
40
|
"@thiny/core": "0.1.0",
|
|
41
|
-
"@thiny/logger-pino": "0.1.0",
|
|
42
41
|
"@thiny/memory-memwal": "0.1.0",
|
|
43
|
-
"@thiny/
|
|
42
|
+
"@thiny/logger-pino": "0.1.0",
|
|
44
43
|
"@thiny/mcp": "0.1.0",
|
|
45
|
-
"@thiny/
|
|
44
|
+
"@thiny/walrus": "0.1.0",
|
|
46
45
|
"@thiny/plugin-agents": "0.1.0",
|
|
46
|
+
"@thiny/plugin-sui": "0.1.0",
|
|
47
47
|
"@thiny/plugin-web-search": "0.1.0",
|
|
48
|
-
"@thiny/
|
|
49
|
-
"@thiny/
|
|
50
|
-
"@thiny/
|
|
48
|
+
"@thiny/model-aisdk": "0.1.0",
|
|
49
|
+
"@thiny/skills": "0.1.0",
|
|
50
|
+
"@thiny/signer-sui": "0.1.0"
|
|
51
51
|
},
|
|
52
52
|
"author": "Thiny AI",
|
|
53
53
|
"engines": {
|