@kaleidorg/mind 0.7.0 → 0.8.1
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/README.md +96 -8
- package/dist/context/compress.d.ts.map +1 -1
- package/dist/context/compress.js +1 -0
- package/dist/context/compress.js.map +1 -1
- package/dist/context/rgb-units.d.ts +18 -0
- package/dist/context/rgb-units.d.ts.map +1 -0
- package/dist/context/rgb-units.js +86 -0
- package/dist/context/rgb-units.js.map +1 -0
- package/dist/engine.d.ts +59 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +196 -17
- package/dist/engine.js.map +1 -1
- package/dist/fastpath/fastpath.d.ts +6 -1
- package/dist/fastpath/fastpath.d.ts.map +1 -1
- package/dist/fastpath/fastpath.js +16 -2
- package/dist/fastpath/fastpath.js.map +1 -1
- package/dist/fastpath/render.d.ts +2 -0
- package/dist/fastpath/render.d.ts.map +1 -0
- package/dist/fastpath/render.js +58 -0
- package/dist/fastpath/render.js.map +1 -0
- package/dist/funnel.d.ts.map +1 -1
- package/dist/funnel.js +34 -18
- package/dist/funnel.js.map +1 -1
- package/dist/guards.d.ts +63 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +284 -0
- package/dist/guards.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/kaleidoswap/contract.d.ts +3 -4
- package/dist/kaleidoswap/contract.d.ts.map +1 -1
- package/dist/kaleidoswap/contract.js +3 -17
- package/dist/kaleidoswap/contract.js.map +1 -1
- package/dist/providers/openai.d.ts +64 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +233 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +33 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/qvac/config.d.ts +1 -1
- package/dist/qvac/config.js +1 -1
- package/dist/qvac/index.d.ts +1 -0
- package/dist/qvac/index.d.ts.map +1 -1
- package/dist/qvac/index.js +1 -0
- package/dist/qvac/index.js.map +1 -1
- package/dist/qvac/models.d.ts +31 -0
- package/dist/qvac/models.d.ts.map +1 -0
- package/dist/qvac/models.js +80 -0
- package/dist/qvac/models.js.map +1 -0
- package/dist/qvac/parse.d.ts +11 -0
- package/dist/qvac/parse.d.ts.map +1 -1
- package/dist/qvac/parse.js +29 -7
- package/dist/qvac/parse.js.map +1 -1
- package/dist/qvac/provider.d.ts +14 -4
- package/dist/qvac/provider.d.ts.map +1 -1
- package/dist/qvac/provider.js +33 -8
- package/dist/qvac/provider.js.map +1 -1
- package/dist/qvac/stream.d.ts +3 -5
- package/dist/qvac/stream.d.ts.map +1 -1
- package/dist/qvac/stream.js.map +1 -1
- package/dist/qvac/tools.d.ts +5 -0
- package/dist/qvac/tools.d.ts.map +1 -1
- package/dist/qvac/tools.js +10 -0
- package/dist/qvac/tools.js.map +1 -1
- package/dist/recipe/issue-asset.d.ts.map +1 -1
- package/dist/recipe/issue-asset.js +42 -16
- package/dist/recipe/issue-asset.js.map +1 -1
- package/dist/recipe/runner.d.ts.map +1 -1
- package/dist/recipe/runner.js +1 -0
- package/dist/recipe/runner.js.map +1 -1
- package/dist/recipe/submarine-pay.d.ts +17 -0
- package/dist/recipe/submarine-pay.d.ts.map +1 -0
- package/dist/recipe/submarine-pay.js +79 -0
- package/dist/recipe/submarine-pay.js.map +1 -0
- package/dist/skills/registry.js +1 -1
- package/dist/skills/select.d.ts +20 -0
- package/dist/skills/select.d.ts.map +1 -0
- package/dist/skills/select.js +32 -0
- package/dist/skills/select.js.map +1 -0
- package/dist/submarine/contract.d.ts +42 -0
- package/dist/submarine/contract.d.ts.map +1 -0
- package/dist/submarine/contract.js +73 -0
- package/dist/submarine/contract.js.map +1 -0
- package/dist/testing/mock-wallet.d.ts +24 -0
- package/dist/testing/mock-wallet.d.ts.map +1 -1
- package/dist/testing/mock-wallet.js +75 -6
- package/dist/testing/mock-wallet.js.map +1 -1
- package/dist/wallet/confirm.d.ts.map +1 -1
- package/dist/wallet/confirm.js +27 -9
- package/dist/wallet/confirm.js.map +1 -1
- package/package.json +6 -1
- package/skills/README.md +1 -0
- package/skills/kaleido-trading/SKILL.md +22 -28
- package/skills/kaleido-trading/references/api.md +3 -3
- package/skills/rgb-lightning-node/SKILL.md +32 -12
- package/skills/spark-wallet/SKILL.md +1 -0
- package/skills/submarine-swaps/SKILL.md +48 -0
- package/src/context/compress.ts +1 -0
- package/src/context/rgb-units.test.ts +42 -0
- package/src/context/rgb-units.ts +89 -0
- package/src/engine.test.ts +133 -3
- package/src/engine.ts +254 -19
- package/src/fastpath/fastpath.ts +22 -2
- package/src/fastpath/render.test.ts +39 -0
- package/src/fastpath/render.ts +56 -0
- package/src/funnel.mind.test.ts +15 -17
- package/src/funnel.ts +34 -19
- package/src/guards.test.ts +399 -0
- package/src/guards.ts +299 -0
- package/src/index.ts +37 -1
- package/src/kaleidoswap/contract.test.ts +8 -16
- package/src/kaleidoswap/contract.ts +4 -32
- package/src/providers/openai.test.ts +127 -0
- package/src/providers/openai.ts +282 -0
- package/src/providers/types.ts +35 -0
- package/src/qvac/config.ts +1 -1
- package/src/qvac/index.ts +10 -0
- package/src/qvac/models.ts +98 -0
- package/src/qvac/parse.test.ts +7 -0
- package/src/qvac/parse.ts +33 -1
- package/src/qvac/provider.test.ts +54 -1
- package/src/qvac/provider.ts +49 -13
- package/src/qvac/stream.ts +3 -5
- package/src/qvac/tools.ts +10 -0
- package/src/recipe/issue-asset.test.ts +39 -0
- package/src/recipe/issue-asset.ts +41 -13
- package/src/recipe/runner.ts +1 -0
- package/src/recipe/submarine-pay.test.ts +87 -0
- package/src/recipe/submarine-pay.ts +78 -0
- package/src/skills/registry.ts +1 -1
- package/src/skills/select.ts +41 -0
- package/src/submarine/contract.ts +112 -0
- package/src/testing/mock-wallet.ts +73 -6
- package/src/wallet/confirm.ts +27 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/wallet/confirm.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,GAA2B;IAC1C,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,sFAAsF;AACtF,SAAS,MAAM,CAAC,CAAS;IACvB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,GAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,qEAAqE;AACrE,SAAS,KAAK,CAAC,CAAS;IACtB,OAAO,sCAAsC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ,CAAC,CAAS;IACzB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/wallet/confirm.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaleidorg/mind",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Local-first reasoning + function-calling engine for KaleidoSwap. QVAC-powered.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -40,6 +40,11 @@
|
|
|
40
40
|
"import": "./dist/qvac/index.js",
|
|
41
41
|
"default": "./dist/qvac/index.js"
|
|
42
42
|
},
|
|
43
|
+
"./openai": {
|
|
44
|
+
"types": "./dist/providers/openai.d.ts",
|
|
45
|
+
"import": "./dist/providers/openai.js",
|
|
46
|
+
"default": "./dist/providers/openai.js"
|
|
47
|
+
},
|
|
43
48
|
"./testing": {
|
|
44
49
|
"types": "./dist/testing/index.d.ts",
|
|
45
50
|
"import": "./dist/testing/index.js",
|
package/skills/README.md
CHANGED
|
@@ -19,6 +19,7 @@ name: my-skill # required — stable id
|
|
|
19
19
|
description: When to use this… # required — selection signal (embed triggers here)
|
|
20
20
|
tools: tool_a, tool_b # optional — scope the model to these tools
|
|
21
21
|
triggers: foo, bar # optional — keywords that boost selection
|
|
22
|
+
requires-tools: tool_a # optional — skip this skill unless ALL of these tools are live
|
|
22
23
|
metadata: # optional — anything else (author, version, …)
|
|
23
24
|
author: kaleidoswap
|
|
24
25
|
---
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kaleido-trading
|
|
3
|
-
description: "Trade on KaleidoSwap — quote and execute swaps between BTC and RGB assets (USDT, XAUT). Get assets and pairs, pull an executable quote,
|
|
4
|
-
tools: kaleidoswap_get_assets, kaleidoswap_get_pairs, kaleidoswap_get_quote,
|
|
3
|
+
description: "Trade on KaleidoSwap — quote and execute swaps between BTC and RGB assets (USDT, XAUT). Get assets and pairs, pull an executable quote, or run/poll an atomic swap end-to-end. Triggers when the user wants a quote, to swap or trade assets, to rebalance between BTC and stablecoins, or to check the status of a swap / atomic swap."
|
|
4
|
+
tools: kaleidoswap_get_assets, kaleidoswap_get_pairs, kaleidoswap_get_quote, kaleidoswap_atomic_init, kaleidoswap_atomic_execute, kaleidoswap_atomic_status, rln_get_node_info, rln_atomic_taker, rln_refresh_transfers, rln_get_asset_balance, rln_list_channels, rln_list_swaps, rln_get_swap
|
|
5
5
|
triggers: quote, swap, trade, rebalance, slippage, pair, pairs, usdt, xaut, kaleidoswap, rfq, check status, order status, check the order, swap status, check my swap, atomic status
|
|
6
6
|
metadata:
|
|
7
7
|
author: kaleidoswap
|
|
@@ -110,7 +110,7 @@ verbatim. Do NOT do any arithmetic yourself.** The response looks like:
|
|
|
110
110
|
To state the answer, copy the strings:
|
|
111
111
|
- Receive amount → `to_amount_display`.
|
|
112
112
|
- Fee → `fee_display`.
|
|
113
|
-
- `rfq_id` is the quote handle (needed to
|
|
113
|
+
- `rfq_id` is the quote handle (needed to start the atomic swap), short-lived (~60s) —
|
|
114
114
|
mention it expires soon.
|
|
115
115
|
|
|
116
116
|
**Read `to_amount_display` / `fee_display` exactly as given.** Do NOT compute
|
|
@@ -121,21 +121,18 @@ correct numbers are the `*_display` strings in the CURRENT tool result.
|
|
|
121
121
|
A good reply: *"100,000 sats → <to_amount_display> (fee <fee_display>). Quote
|
|
122
122
|
<rfq_id> is valid ~60s — want me to place it?"*
|
|
123
123
|
|
|
124
|
-
### `
|
|
124
|
+
### `kaleidoswap_atomic_init` 🔒 spend
|
|
125
125
|
Only after `kaleidoswap_get_quote` returned an `rfq_id` THIS turn, and only when
|
|
126
|
-
the user has explicitly approved the amount + direction.
|
|
127
|
-
`
|
|
126
|
+
the user has explicitly approved the amount + direction. Starts the atomic
|
|
127
|
+
swap from that quote; the rest of the chain (`rln_atomic_taker` →
|
|
128
|
+
`kaleidoswap_atomic_execute` → `kaleidoswap_atomic_status`) is described
|
|
129
|
+
below and in `references/atomic.md`.
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
to terminal states. Always pass the exact values from the previous
|
|
135
|
-
`kaleidoswap_place_order` result **or from the most recent assistant message/summary**
|
|
136
|
-
(the one that said something like "order_id=xxx access_token=yyy" or "To check status use: kaleidoswap_get_order_status(order_id=..., access_token=...)").
|
|
137
|
-
If memory/remember is available, first recall the last order/swap details.
|
|
138
|
-
Report the outcome plainly.
|
|
131
|
+
### `kaleidoswap_atomic_status`
|
|
132
|
+
Poll after executing an atomic swap until it reaches a terminal state
|
|
133
|
+
(completed / failed / expired). Pass the exact ids returned by
|
|
134
|
+
`kaleidoswap_atomic_init` (or surfaced in the most recent swap summary) — never
|
|
135
|
+
invent them. Report the outcome plainly.
|
|
139
136
|
|
|
140
137
|
## Flow
|
|
141
138
|
|
|
@@ -143,12 +140,15 @@ Report the outcome plainly.
|
|
|
143
140
|
2. **Quote** — `kaleidoswap_get_quote`. REQUIRES amount; ask if missing.
|
|
144
141
|
3. **Read + present** — compute the receive amount + fee from the response (see
|
|
145
142
|
"Reading the quote response"). **Never hide cost.**
|
|
146
|
-
4. **
|
|
147
|
-
|
|
143
|
+
4. **Swap** — `kaleidoswap_atomic_init` → `rln_atomic_taker` →
|
|
144
|
+
`kaleidoswap_atomic_execute`. Spend-gated by the engine; the host pauses for
|
|
145
|
+
the user.
|
|
146
|
+
5. **Track** — poll `kaleidoswap_atomic_status` with the ids from
|
|
147
|
+
`kaleidoswap_atomic_init` until it terminates.
|
|
148
148
|
|
|
149
149
|
## Don'ts
|
|
150
150
|
|
|
151
|
-
- Don't invent prices, quotes, rfq_ids,
|
|
151
|
+
- Don't invent prices, quotes, rfq_ids, swap ids, or access_tokens.
|
|
152
152
|
- Don't reuse a number from a previous turn.
|
|
153
153
|
- Don't describe how a tool works — call it.
|
|
154
154
|
- Don't call `kaleidoswap_get_quote` with from/to only — ask for the amount.
|
|
@@ -158,13 +158,8 @@ Report the outcome plainly.
|
|
|
158
158
|
- Don't accept `XAU` as `XAUT` or `USD` as `USDT` silently — confirm.
|
|
159
159
|
- Don't retry the same failing tool call in a loop. If a call fails, read the
|
|
160
160
|
error and either ask the user, fix the args, or stop.
|
|
161
|
-
- Don't claim
|
|
162
|
-
|
|
163
|
-
- Never call `kaleidoswap_get_order_status` with only the access_token or only
|
|
164
|
-
the order_id. Always extract the exact values from the previous turn's summary
|
|
165
|
-
(the one that said "order_id=... access_token=..." or the explicit "To check
|
|
166
|
-
status use..." line) and pass them as separate arguments. If using the
|
|
167
|
-
`remember` tool, first recall the last order details.
|
|
161
|
+
- Don't claim a swap completed without polling `kaleidoswap_atomic_status`
|
|
162
|
+
and seeing a terminal state.
|
|
168
163
|
|
|
169
164
|
For the full atomic-swap flow (init → whitelist on the RGB node → execute), a
|
|
170
165
|
deterministic recipe drives the chain — the agentic loop is not safe to plan a
|
|
@@ -173,8 +168,7 @@ multi-step, two-service swap on a small model. Status for atomics uses the
|
|
|
173
168
|
|
|
174
169
|
## Over kaleido-mcp (desktop, Claude Code)
|
|
175
170
|
|
|
176
|
-
kaleido-mcp 0.3.0+ is **atomic-only
|
|
177
|
-
or order status. Its quote takes `from_asset_id` / `from_layer` /
|
|
171
|
+
kaleido-mcp 0.3.0+ is **atomic-only**. Its quote takes `from_asset_id` / `from_layer` /
|
|
178
172
|
`from_amount` (display units) and returns `amount_raw` values that
|
|
179
173
|
`kaleidoswap_atomic_init` takes unchanged. The full chain is quote →
|
|
180
174
|
`kaleidoswap_atomic_init` → `rln_atomic_taker` + `rln_get_node_info` →
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# KaleidoSwap maker API (what the tools call)
|
|
2
2
|
|
|
3
|
-
Base
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Base URL: `https://api.signet.kaleidoswap.com` (signet, `KALEIDO_NETWORK=signet`
|
|
4
|
+
in kaleido-mcp). There is no public mainnet API; for mainnet, set
|
|
5
|
+
`KALEIDOSWAP_API_URL` to your own maker endpoint. The MCP tools wrap these endpoints; you normally never call them
|
|
6
6
|
directly. Amounts on the wire are raw units (see `assets.md`).
|
|
7
7
|
|
|
8
8
|
| Endpoint | Tool |
|
|
@@ -5,7 +5,7 @@ tools: rln_get_node_info, rln_get_balances, rln_list_channels, rln_list_assets,
|
|
|
5
5
|
triggers: node, nodeinfo, pubkey, peer, channels, channel capacity, list channels, open channel, close channel, inbound, capacity, asset balance, whitelist, taker, swapstring, swaps, payments, invoice, receive, send asset, send rgb, on-chain address, deposit, rgb invoice, ln invoice, issue, mint, new token, nft, utxos, transfers
|
|
6
6
|
metadata:
|
|
7
7
|
author: kaleidoswap
|
|
8
|
-
version: "0.3.
|
|
8
|
+
version: "0.3.3"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# RGB Lightning Node (taker-side)
|
|
@@ -70,14 +70,26 @@ ASYNCHRONOUSLY (seconds to minutes after payment). If the new channel isn't
|
|
|
70
70
|
listed yet, say it's still opening and suggest checking again — don't claim
|
|
71
71
|
failure.
|
|
72
72
|
|
|
73
|
-
### `rln_list_assets` —
|
|
74
|
-
Lists RGB assets known to the node
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
### `rln_list_assets` — { schemas? }
|
|
74
|
+
Lists RGB assets known to the node: `asset_id`, `ticker`, `name`, `precision`
|
|
75
|
+
(in-app wallets also return balances). `schemas` is an optional filter — an
|
|
76
|
+
array of `"Nia"`, `"Uda"`, `"Cfa"`; call it with `{}` to list everything.
|
|
77
|
+
Use for "what assets do I hold / what's my USDT balance".
|
|
78
|
+
|
|
79
|
+
Call it **once** per question. An empty list is a real answer: the node holds
|
|
80
|
+
no RGB assets yet — tell the user that (and offer to issue one) instead of
|
|
81
|
+
calling it again.
|
|
82
|
+
|
|
83
|
+
### Tickers are not asset ids
|
|
84
|
+
`asset_id` arguments take the full RGB id (`rgb:…`), never a ticker like
|
|
85
|
+
`USDT` or `HCK`. When the user names an asset by ticker or name, first call
|
|
86
|
+
`rln_list_assets`, find the entry whose `ticker`/`name` matches, and pass its
|
|
87
|
+
`asset_id`. If nothing matches, say the node has no such asset — do not guess
|
|
88
|
+
an id.
|
|
77
89
|
|
|
78
90
|
### `rln_get_asset_balance` — { asset_id }
|
|
79
|
-
Balance for one RGB asset by id.
|
|
80
|
-
|
|
91
|
+
Balance for one RGB asset by id. Resolve a ticker to its `asset_id` with
|
|
92
|
+
`rln_list_assets` first.
|
|
81
93
|
|
|
82
94
|
| Field | Meaning |
|
|
83
95
|
|---|---|
|
|
@@ -105,7 +117,8 @@ the amount.
|
|
|
105
117
|
Sends an RGB asset to the recipient encoded in an RGB invoice. Use the argument
|
|
106
118
|
names of the schema you were given: in-app wallets take `{ asset, amount, to }`
|
|
107
119
|
(ticker or asset_id, units, the invoice); kaleido-mcp takes
|
|
108
|
-
`{ asset_id, amount, recipient_id }
|
|
120
|
+
`{ asset_id, amount, recipient_id }`, where `asset_id` is the `rgb:…` id from
|
|
121
|
+
`rln_list_assets`. Never invent a recipient.
|
|
109
122
|
|
|
110
123
|
### `rln_pay_invoice` — { invoice } — 🔒 confirm-gated
|
|
111
124
|
Pays a BOLT11 Lightning invoice from the node. Pass the full invoice string.
|
|
@@ -144,16 +157,21 @@ Call this **after** `kaleidoswap_atomic_init` and **before**
|
|
|
144
157
|
### `rln_create_ln_invoice` — Lightning invoice for receiving sats
|
|
145
158
|
Args:
|
|
146
159
|
- `amount_sats` (optional) — omit for an amountless invoice.
|
|
160
|
+
- `description` (optional, kaleido-mcp) — memo shown to the payer.
|
|
147
161
|
- `expiry_sec` (default 3600, kaleido-mcp only) — invoice TTL in seconds.
|
|
148
162
|
|
|
163
|
+
Reply with the full `invoice` string from the result — never write an invoice
|
|
164
|
+
yourself.
|
|
165
|
+
|
|
149
166
|
Use when the user wants to **receive** a Lightning payment. Do NOT call inside
|
|
150
167
|
an atomic swap flow unless the user explicitly asked to invoice someone.
|
|
151
168
|
|
|
152
169
|
### `rln_create_rgb_invoice` — on-chain RGB receive invoice
|
|
153
170
|
Args (use the names in your schema):
|
|
154
171
|
- in-app wallets: `asset` (ticker or asset_id) + `amount`.
|
|
155
|
-
- kaleido-mcp: `asset_id` (
|
|
156
|
-
|
|
172
|
+
- kaleido-mcp: `asset_id` (the `rgb:…` id from `rln_list_assets` — never a
|
|
173
|
+
ticker; omit for an any-asset invoice), `amount` (display units),
|
|
174
|
+
`duration_seconds` (default 86400).
|
|
157
175
|
|
|
158
176
|
Reply with the full `invoice` string; the payer needs all of it.
|
|
159
177
|
|
|
@@ -176,8 +194,10 @@ defaults (`num` 5, `fee_rate` 1) are fine; set `up_to: true` to only top up to
|
|
|
176
194
|
### `rln_issue_asset` — { name, ticker?, amount?, precision?, schema?, details? } — 🔒 confirm-gated
|
|
177
195
|
Creates a **new** RGB asset owned by this node. `schema`: `NIA` fungible token
|
|
178
196
|
(default), `CFA` collectible, `UDA` unique asset / NFT (supply 1).
|
|
179
|
-
- `ticker` (uppercase, 1–8 letters/digits) is required for `NIA`
|
|
180
|
-
|
|
197
|
+
- `ticker` (uppercase, 1–8 letters/digits, nothing else) is required for `NIA`
|
|
198
|
+
and `UDA`.
|
|
199
|
+
- `amount` is the total supply in display units (a number), required for `NIA`
|
|
200
|
+
and `CFA` — if the user did not say how many, ask before calling;
|
|
181
201
|
the raw supply is `amount × 10^precision` (`precision` defaults to 0).
|
|
182
202
|
- `details` is an optional description for `CFA` and `UDA`.
|
|
183
203
|
|
|
@@ -3,6 +3,7 @@ name: spark-wallet
|
|
|
3
3
|
description: "Operate the user's Spark BTC wallet on this device — check Spark balance, get a Spark deposit address, create a Spark Lightning invoice to receive, pay any BOLT11 Lightning invoice with Spark, or send BTC on-chain from Spark. Use this when the user names Spark explicitly OR when paying a Lightning invoice on a phone where Spark is the connected layer. Pairs with the bitrefill skill: a Bitrefill purchase that returns a Lightning invoice is paid with `spark_pay_invoice`."
|
|
4
4
|
tools: spark_get_balance, spark_get_address, spark_get_onchain_address, spark_create_invoice, spark_pay_invoice, spark_send, get_price, fiat_to_sats, bitrefill_search, bitrefill_get_product, bitrefill_get_balance, bitrefill_create_invoice, bitrefill_get_invoice, bitrefill_get_order
|
|
5
5
|
triggers: spark, sprak, spakr, spark wallet, pay with spark, send with spark, spark balance, spark address, spark invoice, lightning invoice, pay invoice, bolt11, ln invoice, pay this invoice, on-chain address, onchain address, deposit address, deposit btc, fund spark
|
|
6
|
+
requires-tools: spark_get_balance
|
|
6
7
|
metadata:
|
|
7
8
|
author: kaleidoswap
|
|
8
9
|
version: "1.0.0"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: submarine-swaps
|
|
3
|
+
description: "Pay a Lightning invoice from Liquid funds (L-USDT or L-BTC) through a KaleidoSwap submarine swap on the /v2 maker, and follow its status. Triggers when the user wants to pay a Lightning invoice with Liquid USDT / L-USDT / L-BTC, asks what Liquid assets can pay Lightning, or asks about a submarine swap."
|
|
4
|
+
tools: kaleidoswap_submarine_pairs, kaleidoswap_submarine_create, kaleidoswap_submarine_fund, kaleidoswap_submarine_status
|
|
5
|
+
triggers: l-usdt, liquid usdt, usdt on liquid, l-btc, liquid bitcoin, submarine, submarine swap, pay invoice with liquid, swap status
|
|
6
|
+
metadata:
|
|
7
|
+
author: kaleidoswap
|
|
8
|
+
version: "0.1.0"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Submarine swaps — pay Lightning from Liquid
|
|
12
|
+
|
|
13
|
+
A submarine swap pays a Lightning (BOLT11) invoice with funds the user locks on
|
|
14
|
+
Liquid. The KaleidoSwap maker pays the invoice, then claims the lockup. It is
|
|
15
|
+
atomic: if the maker can't pay, the lockup is refunded to the user.
|
|
16
|
+
|
|
17
|
+
## Critical rules
|
|
18
|
+
|
|
19
|
+
- Every amount, fee and status in your reply MUST come from a tool result in the
|
|
20
|
+
CURRENT turn. Never guess the amount to lock — `kaleidoswap_submarine_create`
|
|
21
|
+
returns it.
|
|
22
|
+
- `kaleidoswap_submarine_fund` moves money. Call it ONLY after the user has
|
|
23
|
+
confirmed the exact `expected_amount` returned by `kaleidoswap_submarine_create`.
|
|
24
|
+
- `kaleidoswap_submarine_fund` takes only `swap_id`. Never try to pass an amount
|
|
25
|
+
or an address.
|
|
26
|
+
- A bare "USDT" means RGB USDT on the Lightning node, which uses the atomic swap
|
|
27
|
+
tools, not this skill. Use this skill only for Liquid assets (L-USDT, L-BTC).
|
|
28
|
+
|
|
29
|
+
## Flow
|
|
30
|
+
|
|
31
|
+
1. `kaleidoswap_submarine_create { invoice, from_asset }` — from_asset is
|
|
32
|
+
`L-USDT` (default) or `L-BTC`. Returns `swap_id`, `expected_amount` (smallest
|
|
33
|
+
unit: L-USDT has 8 decimals, L-BTC is sats) and the fees.
|
|
34
|
+
2. Tell the user the amount and ask to confirm.
|
|
35
|
+
3. `kaleidoswap_submarine_fund { swap_id }`.
|
|
36
|
+
4. `kaleidoswap_submarine_status { swap_id }` — `transaction.claimed` means the
|
|
37
|
+
invoice was paid. `failed: true` on a funded swap means the funds need a refund;
|
|
38
|
+
say so and quote the `refund` field.
|
|
39
|
+
|
|
40
|
+
Use `kaleidoswap_submarine_pairs` when the user asks what can pay a Lightning
|
|
41
|
+
invoice, or for the limits and fees.
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
|
|
45
|
+
- "pay lntbs10u1p… with L-USDT" →
|
|
46
|
+
`kaleidoswap_submarine_create { invoice: "lntbs10u1p…", from_asset: "L-USDT" }`
|
|
47
|
+
- "did my Liquid payment go through? swap sub1" →
|
|
48
|
+
`kaleidoswap_submarine_status { swap_id: "sub1" }`
|
package/src/context/compress.ts
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { annotateRgbBalances, fixRgbBalanceUnits, formatRgbAmount } from './rgb-units.js';
|
|
3
|
+
|
|
4
|
+
const LIST = {
|
|
5
|
+
assets: [
|
|
6
|
+
{ asset_id: 'rgb:usdt', ticker: 'USDT', name: 'Tether USD', precision: 0, balance: { settled: 1000, spendable: 1000 } },
|
|
7
|
+
{ asset_id: 'rgb:xaut', ticker: 'XAUT', name: 'Tether Gold', precision: 0, balance: { spendable: 2 } },
|
|
8
|
+
{ asset_id: 'rgb:dec', ticker: 'DEC', precision: 6, balance: { spendable: 1_500_000 } },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe('RGB balance units', () => {
|
|
13
|
+
it('formats raw amounts with the asset precision', () => {
|
|
14
|
+
expect(formatRgbAmount(1_500_000, 6)).toBe('1.5');
|
|
15
|
+
expect(formatRgbAmount(1_000_000, 0)).toBe('1,000,000');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('adds balance_display next to each asset balance without touching the rest', () => {
|
|
19
|
+
const out = annotateRgbBalances(LIST) as typeof LIST & { assets: Array<{ balance_display: Record<string, string> }> };
|
|
20
|
+
expect(out.assets[0]!.balance_display).toEqual({ settled: '1,000 USDT', spendable: '1,000 USDT' });
|
|
21
|
+
expect(out.assets[2]!.balance_display).toEqual({ spendable: '1.5 DEC' });
|
|
22
|
+
expect(out.assets[0]!.balance).toEqual({ settled: 1000, spendable: 1000 });
|
|
23
|
+
expect(annotateRgbBalances({ vanilla: { spendable: 4277 } })).toEqual({ vanilla: { spendable: 4277 } });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('relabels the asset balances the 2B model called satoshis', () => {
|
|
27
|
+
const answer =
|
|
28
|
+
'You hold two RGB assets:\n1. **USDT** (Tether USD)\n - Balance: 1,000 satoshis (spendable)\n' +
|
|
29
|
+
'2. **XAUT** (Tether Gold)\n - Balance: 2 satoshis (spendable)';
|
|
30
|
+
expect(fixRgbBalanceUnits(answer, [LIST])).toBe(
|
|
31
|
+
'You hold two RGB assets:\n1. **USDT** (Tether USD)\n - Balance: 1,000 USDT (spendable)\n' +
|
|
32
|
+
'2. **XAUT** (Tether Gold)\n - Balance: 2 XAUT (spendable)',
|
|
33
|
+
);
|
|
34
|
+
expect(fixRgbBalanceUnits('DEC balance: 1,500,000 sats', [LIST])).toBe('DEC balance: 1.5 DEC');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('leaves real sats and unmatched numbers alone', () => {
|
|
38
|
+
const btc = { btc: { vanilla: { spendable: 4277 } } };
|
|
39
|
+
expect(fixRgbBalanceUnits('Your on-chain balance is 4,277 sats.', [btc, LIST])).toBe('Your on-chain balance is 4,277 sats.');
|
|
40
|
+
expect(fixRgbBalanceUnits('USDT channel fee: 300 sats', [LIST])).toBe('USDT channel fee: 300 sats');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RGB asset balances are raw integers in the asset's own unit, scaled by its
|
|
3
|
+
* `precision`. Nothing in the tool result says so, and small models fill the
|
|
4
|
+
* gap with "satoshis" ("USDT — Balance: 1,000 satoshis").
|
|
5
|
+
*
|
|
6
|
+
* `annotateRgbBalances` adds a `balance_display` next to each asset's
|
|
7
|
+
* `balance` before the result reaches the model ("1,000 USDT").
|
|
8
|
+
* `fixRgbBalanceUnits` corrects a final answer that still labels an asset
|
|
9
|
+
* balance as sats: the number must equal one of that asset's balances and the
|
|
10
|
+
* nearest ticker before it must be that asset's.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
type Obj = Record<string, unknown>;
|
|
14
|
+
|
|
15
|
+
interface RgbAsset {
|
|
16
|
+
ticker: string;
|
|
17
|
+
precision: number;
|
|
18
|
+
amounts: number[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const BALANCE_FIELDS = ['settled', 'spendable', 'future'] as const;
|
|
22
|
+
|
|
23
|
+
const isObj = (v: unknown): v is Obj => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
24
|
+
|
|
25
|
+
function asAsset(v: Obj): RgbAsset | null {
|
|
26
|
+
if (typeof v.ticker !== 'string' || !v.ticker || !isObj(v.balance)) return null;
|
|
27
|
+
const amounts = BALANCE_FIELDS.map((k) => (v.balance as Obj)[k]).filter((n): n is number => typeof n === 'number');
|
|
28
|
+
if (!amounts.length) return null;
|
|
29
|
+
const precision = typeof v.precision === 'number' && v.precision > 0 ? v.precision : 0;
|
|
30
|
+
return { ticker: v.ticker, precision, amounts };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** A raw RGB amount in display units, e.g. 1500000 at precision 6 → "1.5". */
|
|
34
|
+
export function formatRgbAmount(raw: number, precision: number): string {
|
|
35
|
+
const value = raw / 10 ** precision;
|
|
36
|
+
return value.toLocaleString('en-US', { maximumFractionDigits: precision });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Return a copy of `result` where every RGB asset carries `balance_display`. */
|
|
40
|
+
export function annotateRgbBalances(result: unknown): unknown {
|
|
41
|
+
if (Array.isArray(result)) return result.map(annotateRgbBalances);
|
|
42
|
+
if (!isObj(result)) return result;
|
|
43
|
+
const out: Obj = {};
|
|
44
|
+
for (const [k, v] of Object.entries(result)) out[k] = annotateRgbBalances(v);
|
|
45
|
+
const asset = asAsset(result);
|
|
46
|
+
if (asset) {
|
|
47
|
+
const balance = result.balance as Obj;
|
|
48
|
+
const display: Obj = {};
|
|
49
|
+
for (const k of BALANCE_FIELDS) {
|
|
50
|
+
if (typeof balance[k] === 'number') display[k] = `${formatRgbAmount(balance[k] as number, asset.precision)} ${asset.ticker}`;
|
|
51
|
+
}
|
|
52
|
+
out.balance_display = display;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function collectAssets(value: unknown, into: RgbAsset[]): void {
|
|
58
|
+
if (Array.isArray(value)) {
|
|
59
|
+
for (const v of value) collectAssets(v, into);
|
|
60
|
+
} else if (isObj(value)) {
|
|
61
|
+
const asset = asAsset(value);
|
|
62
|
+
if (asset) into.push(asset);
|
|
63
|
+
for (const v of Object.values(value)) collectAssets(v, into);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const AMOUNT_IN_SATS = /(\d[\d,]*(?:\.\d+)?)\s*(?:satoshis|sats?)\b/gi;
|
|
68
|
+
const escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
|
|
70
|
+
/** Relabel asset balances that the answer calls sats, using the tool results it was built from. */
|
|
71
|
+
export function fixRgbBalanceUnits(text: string, toolResults: unknown[]): string {
|
|
72
|
+
const assets: RgbAsset[] = [];
|
|
73
|
+
for (const r of toolResults) collectAssets(r, assets);
|
|
74
|
+
if (!assets.length) return text;
|
|
75
|
+
const tickerRe = new RegExp(`\\b(${[...new Set(assets.map((a) => escapeRe(a.ticker)))].join('|')})\\b`, 'g');
|
|
76
|
+
|
|
77
|
+
return text.replace(AMOUNT_IN_SATS, (match: string, num: string, offset: number) => {
|
|
78
|
+
let nearest: string | undefined;
|
|
79
|
+
for (const m of text.slice(Math.max(0, offset - 300), offset).matchAll(tickerRe)) nearest = m[1];
|
|
80
|
+
if (!nearest) return match;
|
|
81
|
+
const value = Number(num.replace(/,/g, ''));
|
|
82
|
+
const asset = assets.find(
|
|
83
|
+
(a) => a.ticker === nearest && a.amounts.some((raw) => raw === value || raw / 10 ** a.precision === value),
|
|
84
|
+
);
|
|
85
|
+
if (!asset) return match;
|
|
86
|
+
const raw = asset.amounts.find((r) => r === value) ?? value * 10 ** asset.precision;
|
|
87
|
+
return `${formatRgbAmount(raw, asset.precision)} ${asset.ticker}`;
|
|
88
|
+
});
|
|
89
|
+
}
|
package/src/engine.test.ts
CHANGED
|
@@ -111,8 +111,8 @@ describe('Engine agentic loop', () => {
|
|
|
111
111
|
const res = await engine.runAgentic([{ role: 'user', content: 'pay lnbc1' }], { onConfirm });
|
|
112
112
|
|
|
113
113
|
expect(payTool.handler).not.toHaveBeenCalled();
|
|
114
|
-
expect(res.toolCalls[0].result).toMatchObject({
|
|
115
|
-
expect(res.text).toBe('
|
|
114
|
+
expect(res.toolCalls[0].result).toMatchObject({ status: 'cancelled_by_user', declined_by: 'user', host_reason: 'cancelled' });
|
|
115
|
+
expect(res.text).toBe('Cancelled — you declined: pay invoice. Nothing was sent or changed.');
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
it('chains multiple tool calls across turns', async () => {
|
|
@@ -138,7 +138,9 @@ describe('Engine agentic loop', () => {
|
|
|
138
138
|
it('stops at maxTurns if the model never stops calling tools', async () => {
|
|
139
139
|
const engine = new Engine({
|
|
140
140
|
provider: scriptedProvider([
|
|
141
|
-
{ text: 'loop', toolCalls: [{ name: 'get_balance', arguments: {} }] },
|
|
141
|
+
{ text: 'loop', toolCalls: [{ name: 'get_balance', arguments: { n: 1 } }] },
|
|
142
|
+
{ text: 'loop', toolCalls: [{ name: 'get_balance', arguments: { n: 2 } }] },
|
|
143
|
+
{ text: 'loop', toolCalls: [{ name: 'get_balance', arguments: { n: 3 } }] },
|
|
142
144
|
]),
|
|
143
145
|
tools: freshTools(),
|
|
144
146
|
defaultMaxTurns: 3,
|
|
@@ -205,6 +207,134 @@ describe('Engine agentic loop', () => {
|
|
|
205
207
|
expect(res.toolCalls[0].result).toMatchObject({ error: 'kaboom' });
|
|
206
208
|
expect(res.text).toBe('handled the error');
|
|
207
209
|
});
|
|
210
|
+
|
|
211
|
+
it('sends firstTurnToolChoice on the first call only', async () => {
|
|
212
|
+
const seen: Array<string | undefined> = [];
|
|
213
|
+
const provider: LLMProvider = {
|
|
214
|
+
name: 'rec',
|
|
215
|
+
async runTurn(input) {
|
|
216
|
+
seen.push(input.toolChoice);
|
|
217
|
+
return seen.length === 1
|
|
218
|
+
? { text: '', rawContent: '', toolCalls: [{ name: 'get_balance', arguments: {} }] }
|
|
219
|
+
: { text: 'done', rawContent: 'done', toolCalls: [] };
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
const engine = new Engine({ provider, tools: freshTools() });
|
|
223
|
+
await engine.runAgentic([{ role: 'user', content: 'send 1000 sats' }], { firstTurnToolChoice: 'required' });
|
|
224
|
+
expect(seen).toEqual(['required', undefined]);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('passes one session key to every call of a run and ends the session', async () => {
|
|
228
|
+
const keys: Array<string | undefined> = [];
|
|
229
|
+
const ended: string[] = [];
|
|
230
|
+
const provider: LLMProvider = {
|
|
231
|
+
name: 'rec',
|
|
232
|
+
async runTurn(input) {
|
|
233
|
+
keys.push(input.sessionKey);
|
|
234
|
+
return keys.length === 1
|
|
235
|
+
? { text: '', rawContent: '', toolCalls: [{ name: 'get_balance', arguments: {} }] }
|
|
236
|
+
: { text: 'done', rawContent: 'done', toolCalls: [] };
|
|
237
|
+
},
|
|
238
|
+
async endSession(key) {
|
|
239
|
+
ended.push(key);
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
const engine = new Engine({ provider, tools: freshTools() });
|
|
243
|
+
await engine.runAgentic([{ role: 'user', content: 'x' }]);
|
|
244
|
+
await engine.runAgentic([{ role: 'user', content: 'y' }]);
|
|
245
|
+
expect(keys[0]).toBeTruthy();
|
|
246
|
+
expect(keys[1]).toBe(keys[0]);
|
|
247
|
+
expect(keys[2]).not.toBe(keys[0]);
|
|
248
|
+
expect(ended).toEqual([keys[0], keys[2]]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('turns thinking off on the forced first call only', async () => {
|
|
252
|
+
const thinking: Array<string | undefined> = [];
|
|
253
|
+
const provider: LLMProvider = {
|
|
254
|
+
name: 'rec',
|
|
255
|
+
async runTurn(input) {
|
|
256
|
+
thinking.push(input.thinking);
|
|
257
|
+
return thinking.length === 1
|
|
258
|
+
? { text: '', rawContent: '', toolCalls: [{ name: 'get_balance', arguments: {} }] }
|
|
259
|
+
: { text: 'done', rawContent: 'done', toolCalls: [] };
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
await new Engine({ provider, tools: freshTools() }).runAgentic([{ role: 'user', content: 'x' }], { firstTurnToolChoice: 'required' });
|
|
263
|
+
expect(thinking).toEqual(['off', undefined]);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('feeds an unparseable tool call back to the model once, then gives up cleanly', async () => {
|
|
267
|
+
const histories: number[] = [];
|
|
268
|
+
const provider: LLMProvider = {
|
|
269
|
+
name: 'broken',
|
|
270
|
+
async runTurn(input) {
|
|
271
|
+
histories.push(input.messages.length);
|
|
272
|
+
return {
|
|
273
|
+
text: '<tool_call>{"ticker":"HCK',
|
|
274
|
+
rawContent: '<tool_call>{"ticker":"HCK',
|
|
275
|
+
toolCalls: [],
|
|
276
|
+
toolErrors: [{ code: 'PARSE_ERROR', message: 'unterminated string' }],
|
|
277
|
+
};
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
const engine = new Engine({ provider, tools: freshTools() });
|
|
281
|
+
const res = await engine.runAgentic([{ role: 'user', content: 'issue HCK' }]);
|
|
282
|
+
expect(histories).toEqual([1, 3]);
|
|
283
|
+
expect(res.text).not.toContain('tool_call');
|
|
284
|
+
expect(res.text).toMatch(/couldn't put together a valid request/i);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('does not count the retry against maxTurns and explains a cut-off call', async () => {
|
|
288
|
+
const seen: string[] = [];
|
|
289
|
+
let n = 0;
|
|
290
|
+
const provider: LLMProvider = {
|
|
291
|
+
name: 'cutoff',
|
|
292
|
+
async runTurn(input) {
|
|
293
|
+
n += 1;
|
|
294
|
+
seen.push(input.messages[input.messages.length - 1]!.content);
|
|
295
|
+
if (n === 1) return { text: '', rawContent: '', toolCalls: [{ name: 'get_balance', arguments: {} }] };
|
|
296
|
+
if (n === 2) {
|
|
297
|
+
return {
|
|
298
|
+
text: '', rawContent: '<tool_call>{"name":"get_balance"', toolCalls: [],
|
|
299
|
+
toolErrors: [{ code: 'PARSE_ERROR', message: 'eof' }],
|
|
300
|
+
inference: { durationMs: 1, status: 'truncated' },
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return { text: 'You have 50,000 sats.', rawContent: '', toolCalls: [] };
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
const engine = new Engine({ provider, tools: freshTools() });
|
|
307
|
+
const res = await engine.runAgentic([{ role: 'user', content: 'balance?' }], { maxTurns: 2 });
|
|
308
|
+
expect(res.text).toBe('You have 50,000 sats.');
|
|
309
|
+
expect(seen[2]).toMatch(/cut off/);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it('never returns an empty answer', async () => {
|
|
313
|
+
const engine = new Engine({ provider: scriptedProvider([{ text: '' }]), tools: freshTools() });
|
|
314
|
+
const res = await engine.runAgentic([{ role: 'user', content: 'hi' }]);
|
|
315
|
+
expect(res.text).toMatch(/had to stop/);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('recovers when the retried call parses', async () => {
|
|
319
|
+
const engine = new Engine({
|
|
320
|
+
provider: (() => {
|
|
321
|
+
let n = 0;
|
|
322
|
+
return {
|
|
323
|
+
name: 'retry',
|
|
324
|
+
async runTurn(): Promise<TurnOutput> {
|
|
325
|
+
n += 1;
|
|
326
|
+
if (n === 1) return { text: 'x', rawContent: 'x', toolCalls: [], toolErrors: [{ code: 'PARSE_ERROR', message: 'bad' }] };
|
|
327
|
+
if (n === 2) return { text: '', rawContent: '', toolCalls: [{ name: 'get_balance', arguments: {} }] };
|
|
328
|
+
return { text: 'You have 50,000 sats.', rawContent: '', toolCalls: [] };
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
})(),
|
|
332
|
+
tools: freshTools(),
|
|
333
|
+
});
|
|
334
|
+
const res = await engine.runAgentic([{ role: 'user', content: 'balance?' }]);
|
|
335
|
+
expect(balanceTool.handler).toHaveBeenCalledTimes(1);
|
|
336
|
+
expect(res.text).toBe('You have 50,000 sats.');
|
|
337
|
+
});
|
|
208
338
|
});
|
|
209
339
|
|
|
210
340
|
describe('ToolRegistry', () => {
|