@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
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { bindWalletTools, type WalletHandler } from '../wallet/contract.js';
|
|
13
13
|
import { ToolRegistry } from '../tools/registry.js';
|
|
14
|
+
import { bindSubmarineTools, type SubmarineHandler } from '../submarine/contract.js';
|
|
14
15
|
|
|
15
16
|
export interface SendRecord {
|
|
16
17
|
tool: string;
|
|
@@ -28,6 +29,8 @@ export interface MockWalletOptions {
|
|
|
28
29
|
assets?: Record<string, number>;
|
|
29
30
|
/** Free colored UTXOs on the RLN node (issuance / RGB receive consume one). */
|
|
30
31
|
utxos?: number;
|
|
32
|
+
/** Liquid balances in smallest units (L-USDT: 8 decimals, L-BTC: sats) for submarine swaps. */
|
|
33
|
+
liquid?: { 'L-USDT': number; 'L-BTC': number };
|
|
31
34
|
}
|
|
32
35
|
export interface MockRgbAsset {
|
|
33
36
|
asset_id: string;
|
|
@@ -52,23 +55,31 @@ export class MockWallet {
|
|
|
52
55
|
assets: Record<string, number>;
|
|
53
56
|
contacts: MockContact[];
|
|
54
57
|
utxos: number;
|
|
58
|
+
liquid: { 'L-USDT': number; 'L-BTC': number };
|
|
59
|
+
/** Submarine swaps opened against the mock /v2 maker, by id. */
|
|
60
|
+
submarineSwaps: Record<string, { from: 'L-USDT' | 'L-BTC'; invoice: string; expected: number; funded: boolean }> = {};
|
|
55
61
|
/** RGB assets the node knows about (seeded USDT/XAUT + anything issued). */
|
|
56
62
|
rgbAssets: MockRgbAsset[];
|
|
57
63
|
transfers: MockTransfer[] = [];
|
|
58
64
|
sends: SendRecord[] = [];
|
|
59
65
|
|
|
66
|
+
private readonly opts: MockWalletOptions;
|
|
67
|
+
|
|
60
68
|
constructor(o: MockWalletOptions = {}) {
|
|
69
|
+
this.opts = o;
|
|
61
70
|
this.priceUsd = o.priceUsd ?? 65_000;
|
|
62
71
|
this.failRoute = o.failRoute ?? false;
|
|
63
|
-
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
72
|
+
// Copies: the wallet mutates its state, and reset() rebuilds from `o`.
|
|
73
|
+
this.balances = { ...(o.balances ?? { spark: 500_000, rln: 300_000, arkade: 200_000 }) };
|
|
74
|
+
this.assets = { ...(o.assets ?? { USDT: 25_000_000, XAUT: 0 }) };
|
|
75
|
+
this.contacts = o.contacts ? [...o.contacts] : [
|
|
66
76
|
{ name: 'bob', ln_address: 'bob@kaleidoswap.com' },
|
|
67
77
|
{ name: 'alice', ln_address: 'alice@kaleidoswap.com' },
|
|
68
78
|
{ name: 'john', ln_address: 'john.smith@kaleidoswap.com' },
|
|
69
79
|
{ name: 'john', ln_address: 'john.doe@kaleidoswap.com' }, // ambiguous on purpose
|
|
70
80
|
];
|
|
71
81
|
this.utxos = o.utxos ?? 5;
|
|
82
|
+
this.liquid = { ...(o.liquid ?? { 'L-USDT': 100 * 1e8, 'L-BTC': 200_000 }) };
|
|
72
83
|
this.rgbAssets = Object.keys(this.assets).map((ticker) => ({
|
|
73
84
|
asset_id: mockAssetId(ticker),
|
|
74
85
|
ticker,
|
|
@@ -112,9 +123,9 @@ export class MockWallet {
|
|
|
112
123
|
totalSats(): number {
|
|
113
124
|
return this.balances.spark + this.balances.rln + this.balances.arkade;
|
|
114
125
|
}
|
|
126
|
+
/** Back to the constructor state: balances, contacts, UTXOs, issued assets, history. */
|
|
115
127
|
reset(): void {
|
|
116
|
-
this
|
|
117
|
-
this.transfers = [];
|
|
128
|
+
Object.assign(this, new MockWallet(this.opts));
|
|
118
129
|
}
|
|
119
130
|
|
|
120
131
|
private send(tool: string, rec: { to: string; amount_sats?: number; asset?: string; amount?: number }) {
|
|
@@ -196,10 +207,56 @@ export class MockWallet {
|
|
|
196
207
|
};
|
|
197
208
|
}
|
|
198
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The KaleidoSwap /v2 submarine contract against a toy maker: 0.5% fee, the
|
|
212
|
+
* invoice amount read from its BOLT11 human-readable part, L-USDT at `priceUsd`.
|
|
213
|
+
*/
|
|
214
|
+
submarineHandlers(): Record<string, SubmarineHandler> {
|
|
215
|
+
return {
|
|
216
|
+
kaleidoswap_submarine_pairs: async () => ({
|
|
217
|
+
pairs: [
|
|
218
|
+
{ from: 'L-USDT', to: 'BTC', fees: { percentage: 0.5 }, limits: { minimal: 10 * 1e8, maximal: 1_000 * 1e8 } },
|
|
219
|
+
{ from: 'L-BTC', to: 'BTC', fees: { percentage: 0.5 }, limits: { minimal: 10_000, maximal: 1_000_000 } },
|
|
220
|
+
],
|
|
221
|
+
}),
|
|
222
|
+
kaleidoswap_submarine_create: async ({ invoice, from_asset }) => {
|
|
223
|
+
const from = (from_asset ?? 'L-USDT') as 'L-USDT' | 'L-BTC';
|
|
224
|
+
if (from !== 'L-USDT' && from !== 'L-BTC') throw new Error(`Unsupported from_asset "${String(from_asset)}".`);
|
|
225
|
+
const sats = bolt11Sats(String(invoice));
|
|
226
|
+
if (sats == null) throw new Error('invalid_invoice: the invoice must be BOLT11 with an amount.');
|
|
227
|
+
const withFee = sats * 1.005;
|
|
228
|
+
const expected = Math.ceil(from === 'L-USDT' ? (withFee / 1e8) * this.priceUsd * 1e8 : withFee);
|
|
229
|
+
const id = `sub${Object.keys(this.submarineSwaps).length + 1}`;
|
|
230
|
+
this.submarineSwaps[id] = { from, invoice: String(invoice), expected, funded: false };
|
|
231
|
+
return { swap_id: id, from_asset: from, expected_amount: String(expected), lockup_address: `tlq1qmock${id}` };
|
|
232
|
+
},
|
|
233
|
+
kaleidoswap_submarine_fund: async ({ swap_id }) => {
|
|
234
|
+
const swap = this.submarineSwaps[String(swap_id)];
|
|
235
|
+
if (!swap) throw new Error(`No submarine swap "${String(swap_id)}" was created by this server.`);
|
|
236
|
+
if (swap.funded) throw new Error(`Swap ${String(swap_id)} is already funded.`);
|
|
237
|
+
if (this.liquid[swap.from] < swap.expected) throw new Error(`Insufficient ${swap.from} balance.`);
|
|
238
|
+
this.liquid[swap.from] -= swap.expected;
|
|
239
|
+
swap.funded = true;
|
|
240
|
+
this.sends.push({ tool: 'kaleidoswap_submarine_fund', to: swap.invoice, asset: swap.from, amount: swap.expected });
|
|
241
|
+
return { funded: true, swap_id, asset: swap.from, amount: String(swap.expected), txid: `mocktx${String(swap_id)}` };
|
|
242
|
+
},
|
|
243
|
+
kaleidoswap_submarine_status: async ({ swap_id }) => {
|
|
244
|
+
const swap = this.submarineSwaps[String(swap_id)];
|
|
245
|
+
if (!swap) throw new Error(`invalid_swap_id: "${String(swap_id)}" is not a swap id`);
|
|
246
|
+
const status = swap.funded ? 'transaction.claimed' : 'swap.created';
|
|
247
|
+
return { swap_id, status, done: swap.funded, failed: false, funded: swap.funded };
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
199
252
|
/** Bind the contract tools to this wallet (optionally overriding some — e.g. to inject). */
|
|
200
253
|
registry(overrides?: Partial<Record<string, WalletHandler>>): ToolRegistry {
|
|
201
254
|
const h = { ...this.handlers(), ...(overrides ?? {}) } as Record<string, WalletHandler>;
|
|
202
|
-
|
|
255
|
+
const sub = { ...this.submarineHandlers(), ...(overrides ?? {}) } as Record<string, SubmarineHandler>;
|
|
256
|
+
return new ToolRegistry([
|
|
257
|
+
bindWalletTools(h, { layers: ['spark', 'rln', 'arkade', 'core'], allowMissing: true }),
|
|
258
|
+
bindSubmarineTools(sub, { allowMissing: true }),
|
|
259
|
+
]);
|
|
203
260
|
}
|
|
204
261
|
}
|
|
205
262
|
|
|
@@ -209,3 +266,13 @@ function mockAssetId(ticker: string): string {
|
|
|
209
266
|
for (const c of ticker) h = (h * 31 + c.charCodeAt(0)) >>> 0;
|
|
210
267
|
return `rgb:mock-${ticker.toLowerCase()}-${h.toString(36)}`;
|
|
211
268
|
}
|
|
269
|
+
|
|
270
|
+
/** Amount in sats from a BOLT11 human-readable part ("lntbs10u…" → 1000), or null. */
|
|
271
|
+
function bolt11Sats(invoice: string): number | null {
|
|
272
|
+
const m = invoice.toLowerCase().match(/^ln(?:bcrt|tbs|bc|tb)(\d+)([munp])?1/);
|
|
273
|
+
if (!m) return null;
|
|
274
|
+
const n = Number(m[1]);
|
|
275
|
+
const mult = { m: 1e5, u: 100, n: 0.1, p: 0.0001 }[m[2] ?? ''] ?? 1e8;
|
|
276
|
+
const sats = n * mult;
|
|
277
|
+
return sats >= 1 ? Math.round(sats) : null;
|
|
278
|
+
}
|
package/src/wallet/confirm.ts
CHANGED
|
@@ -31,7 +31,7 @@ function isRef(s: string): boolean {
|
|
|
31
31
|
/** Shorten an address/invoice for speech; leave contact names intact. */
|
|
32
32
|
function shortRef(s: string): string {
|
|
33
33
|
const v = s.trim();
|
|
34
|
-
return isRef(v) ? `${v.slice(0, 6)}…${v.slice(-4)}` : v;
|
|
34
|
+
return isRef(v) && v.length > 12 ? `${v.slice(0, 6)}…${v.slice(-4)}` : v;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/** " over Spark" suffix for the call's layer (explicit arg wins, else the tool's). */
|
|
@@ -41,8 +41,26 @@ function over(name: string, args: Record<string, unknown>): string {
|
|
|
41
41
|
return label ? ` over ${label}` : '';
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
/** A finite number from a tool arg, else undefined (never NaN in a readback). */
|
|
45
|
+
function num(v: unknown): number | undefined {
|
|
46
|
+
if (typeof v === 'number') return Number.isFinite(v) ? v : undefined;
|
|
47
|
+
if (typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v))) return Number(v);
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A display string from a tool arg, stripped of stray quotes/commas a model may leave in. */
|
|
52
|
+
function label(v: unknown): string {
|
|
53
|
+
return String(v ?? '').trim().replace(/^[\s'"`,]+|[\s'"`,]+$/g, '') || '?';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const sats = (v: unknown) => {
|
|
57
|
+
const n = num(v);
|
|
58
|
+
return n === undefined ? 'an unspecified amount of sats' : `${fmtNum(n)} sats`;
|
|
59
|
+
};
|
|
60
|
+
const asset = (amount: unknown, ticker: unknown) => {
|
|
61
|
+
const n = num(amount);
|
|
62
|
+
return n === undefined ? `an unspecified amount of ${label(ticker)}` : `${fmtNum(n)} ${label(ticker)}`;
|
|
63
|
+
};
|
|
46
64
|
|
|
47
65
|
/** A spoken confirmation ending in "Confirm?", or null for non-spend tools. */
|
|
48
66
|
export function confirmReadback(call: { name: string; arguments: Record<string, unknown> }): string | null {
|
|
@@ -68,18 +86,18 @@ export function confirmReadback(call: { name: string; arguments: Record<string,
|
|
|
68
86
|
case 'spark_pay_invoice':
|
|
69
87
|
return ask(`Pay Lightning invoice ${shortRef(String(a.invoice ?? ''))}${over(name, a)}`);
|
|
70
88
|
case 'rln_issue_asset': {
|
|
71
|
-
const
|
|
89
|
+
const named = a.name != null && a.ticker != null && label(a.name) !== label(a.ticker) ? ` (${label(a.name)})` : '';
|
|
72
90
|
return a.schema === 'UDA'
|
|
73
|
-
? ask(`Issue unique asset ${
|
|
74
|
-
: ask(`Issue ${asset(a.amount, a.ticker ?? a.name)}${
|
|
91
|
+
? ask(`Issue unique asset ${label(a.ticker ?? a.name)}${named} on RGB`)
|
|
92
|
+
: ask(`Issue ${asset(a.amount, a.ticker ?? a.name)}${named}, a new RGB asset`);
|
|
75
93
|
}
|
|
76
94
|
case 'rln_create_utxos':
|
|
77
|
-
return ask(`Create ${fmtNum(
|
|
95
|
+
return ask(`Create ${fmtNum(num(a.num) ?? 5)} RGB UTXOs on-chain${over(name, a)}`);
|
|
78
96
|
case 'rln_send_btc':
|
|
79
97
|
return ask(`Send ${sats(a.amount_sat)} on-chain to ${to('address')}${over(name, a)}`);
|
|
80
98
|
case 'rln_open_channel': {
|
|
81
99
|
const peer = shortRef(String(a.peer_pubkey_and_addr ?? '').split('@')[0] ?? '');
|
|
82
|
-
const withAsset = a.asset_id != null && a.asset_amount
|
|
100
|
+
const withAsset = a.asset_id != null && num(a.asset_amount) !== undefined ? ` with ${fmtNum(num(a.asset_amount)!)} of ${shortRef(String(a.asset_id))}` : '';
|
|
83
101
|
return ask(`Open a ${sats(a.capacity_sat)} channel to ${peer}${withAsset}`);
|
|
84
102
|
}
|
|
85
103
|
case 'rln_close_channel':
|
|
@@ -87,7 +105,7 @@ export function confirmReadback(call: { name: string; arguments: Record<string,
|
|
|
87
105
|
case 'rln_atomic_taker':
|
|
88
106
|
return ask(`Accept atomic swap ${shortRef(String(a.swapstring ?? ''))} on your node`);
|
|
89
107
|
case 'execute_swap':
|
|
90
|
-
return ask(`Swap ${
|
|
108
|
+
return ask(`Swap ${asset(a.amount, a.from_asset)} for ${label(a.to_asset)}`);
|
|
91
109
|
default:
|
|
92
110
|
// Unknown but spend-flagged tool → a generic, still-honest readback.
|
|
93
111
|
return getWalletTool(name)?.spend ? ask(`Confirm ${name.replace(/_/g, ' ')}`) : null;
|