@kaleidorg/mind 0.2.0 → 0.4.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.
Files changed (130) hide show
  1. package/dist/capabilities.d.ts +4 -0
  2. package/dist/capabilities.d.ts.map +1 -1
  3. package/dist/capabilities.js +7 -0
  4. package/dist/capabilities.js.map +1 -1
  5. package/dist/engine.d.ts +9 -0
  6. package/dist/engine.d.ts.map +1 -1
  7. package/dist/engine.js +1 -0
  8. package/dist/engine.js.map +1 -1
  9. package/dist/funnel.d.ts +6 -0
  10. package/dist/funnel.d.ts.map +1 -1
  11. package/dist/funnel.js +26 -6
  12. package/dist/funnel.js.map +1 -1
  13. package/dist/index.d.ts +9 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +8 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/kaleidoswap/contract.d.ts +72 -0
  18. package/dist/kaleidoswap/contract.d.ts.map +1 -0
  19. package/dist/kaleidoswap/contract.js +125 -0
  20. package/dist/kaleidoswap/contract.js.map +1 -0
  21. package/dist/knowledge/btc-map.d.ts +87 -0
  22. package/dist/knowledge/btc-map.d.ts.map +1 -0
  23. package/dist/knowledge/btc-map.js +365 -0
  24. package/dist/knowledge/btc-map.js.map +1 -0
  25. package/dist/lsps1/contract.d.ts +55 -0
  26. package/dist/lsps1/contract.d.ts.map +1 -0
  27. package/dist/lsps1/contract.js +91 -0
  28. package/dist/lsps1/contract.js.map +1 -0
  29. package/dist/memory/store.d.ts +7 -1
  30. package/dist/memory/store.d.ts.map +1 -1
  31. package/dist/memory/store.js +43 -3
  32. package/dist/memory/store.js.map +1 -1
  33. package/dist/memory/types.d.ts +12 -0
  34. package/dist/memory/types.d.ts.map +1 -1
  35. package/dist/qvac/assistant.d.ts +73 -0
  36. package/dist/qvac/assistant.d.ts.map +1 -0
  37. package/dist/qvac/assistant.js +97 -0
  38. package/dist/qvac/assistant.js.map +1 -0
  39. package/dist/qvac/config.d.ts +64 -0
  40. package/dist/qvac/config.d.ts.map +1 -0
  41. package/dist/qvac/config.js +71 -0
  42. package/dist/qvac/config.js.map +1 -0
  43. package/dist/qvac/delegate.d.ts +48 -0
  44. package/dist/qvac/delegate.d.ts.map +1 -0
  45. package/dist/qvac/delegate.js +51 -0
  46. package/dist/qvac/delegate.js.map +1 -0
  47. package/dist/qvac/index.d.ts +19 -0
  48. package/dist/qvac/index.d.ts.map +1 -0
  49. package/dist/qvac/index.js +19 -0
  50. package/dist/qvac/index.js.map +1 -0
  51. package/dist/qvac/parse.d.ts +44 -0
  52. package/dist/qvac/parse.d.ts.map +1 -0
  53. package/dist/qvac/parse.js +28 -0
  54. package/dist/qvac/parse.js.map +1 -0
  55. package/dist/qvac/provider.d.ts +49 -0
  56. package/dist/qvac/provider.d.ts.map +1 -0
  57. package/dist/qvac/provider.js +68 -0
  58. package/dist/qvac/provider.js.map +1 -0
  59. package/dist/qvac/stream.d.ts +37 -0
  60. package/dist/qvac/stream.d.ts.map +1 -0
  61. package/dist/qvac/stream.js +29 -0
  62. package/dist/qvac/stream.js.map +1 -0
  63. package/dist/qvac/text.d.ts +19 -0
  64. package/dist/qvac/text.d.ts.map +1 -0
  65. package/dist/qvac/text.js +56 -0
  66. package/dist/qvac/text.js.map +1 -0
  67. package/dist/qvac/voice.d.ts +69 -0
  68. package/dist/qvac/voice.d.ts.map +1 -0
  69. package/dist/qvac/voice.js +51 -0
  70. package/dist/qvac/voice.js.map +1 -0
  71. package/dist/recipe/kaleidoswap-atomic.d.ts +27 -0
  72. package/dist/recipe/kaleidoswap-atomic.d.ts.map +1 -0
  73. package/dist/recipe/kaleidoswap-atomic.js +111 -0
  74. package/dist/recipe/kaleidoswap-atomic.js.map +1 -0
  75. package/dist/recipe/runner.d.ts.map +1 -1
  76. package/dist/recipe/runner.js +13 -1
  77. package/dist/recipe/runner.js.map +1 -1
  78. package/dist/skills/registry.d.ts.map +1 -1
  79. package/dist/skills/registry.js +20 -2
  80. package/dist/skills/registry.js.map +1 -1
  81. package/dist/wallet/confirm.d.ts +12 -0
  82. package/dist/wallet/confirm.d.ts.map +1 -0
  83. package/dist/wallet/confirm.js +67 -0
  84. package/dist/wallet/confirm.js.map +1 -0
  85. package/package.json +16 -1
  86. package/skills/README.md +6 -1
  87. package/skills/kaleido-lsps/SKILL.md +56 -0
  88. package/skills/kaleido-trading/SKILL.md +85 -18
  89. package/skills/merchant-finder/SKILL.md +87 -0
  90. package/skills/paid-data/SKILL.md +12 -0
  91. package/skills/wallet-assistant/SKILL.md +38 -0
  92. package/src/capabilities.ts +12 -0
  93. package/src/context/context.test.ts +6 -2
  94. package/src/engine.ts +6 -0
  95. package/src/funnel.ts +32 -7
  96. package/src/index.ts +43 -0
  97. package/src/kaleidoswap/contract.test.ts +147 -0
  98. package/src/kaleidoswap/contract.ts +212 -0
  99. package/src/knowledge/btc-map.test.ts +188 -0
  100. package/src/knowledge/btc-map.ts +446 -0
  101. package/src/lsps1/contract.test.ts +81 -0
  102. package/src/lsps1/contract.ts +132 -0
  103. package/src/memory/memory.test.ts +55 -0
  104. package/src/memory/store.ts +49 -4
  105. package/src/memory/types.ts +13 -0
  106. package/src/qvac/assistant.test.ts +132 -0
  107. package/src/qvac/assistant.ts +146 -0
  108. package/src/qvac/config.test.ts +44 -0
  109. package/src/qvac/config.ts +76 -0
  110. package/src/qvac/delegate.test.ts +68 -0
  111. package/src/qvac/delegate.ts +71 -0
  112. package/src/qvac/index.ts +72 -0
  113. package/src/qvac/parse.test.ts +52 -0
  114. package/src/qvac/parse.ts +57 -0
  115. package/src/qvac/provider.test.ts +107 -0
  116. package/src/qvac/provider.ts +124 -0
  117. package/src/qvac/stream.test.ts +79 -0
  118. package/src/qvac/stream.ts +56 -0
  119. package/src/qvac/text.test.ts +70 -0
  120. package/src/qvac/text.ts +60 -0
  121. package/src/qvac/voice.test.ts +151 -0
  122. package/src/qvac/voice.ts +122 -0
  123. package/src/recipe/kaleidoswap-atomic.test.ts +138 -0
  124. package/src/recipe/kaleidoswap-atomic.ts +117 -0
  125. package/src/recipe/runner.ts +13 -1
  126. package/src/skills/registry.ts +21 -2
  127. package/src/skills/skills.test.ts +42 -0
  128. package/src/wallet/confirm.test.ts +57 -0
  129. package/src/wallet/confirm.ts +74 -0
  130. package/skills/kaleido-wallet/SKILL.md +0 -28
@@ -0,0 +1,365 @@
1
+ /**
2
+ * BTC Map tool source — exposes `find_merchant_locations` and
3
+ * `get_merchant_info` so the agent can answer "where can I spend Bitcoin
4
+ * near me?" using the SAME tool names on every surface.
5
+ *
6
+ * - mobile → injects device GPS + a live BTC Map fetch
7
+ * - desktop → injects a live fetch (or a server-side cache)
8
+ * - eval / playground → no injection, falls back to the bundled offline list
9
+ *
10
+ * Pure data + orchestration — NO network in core. The host injects the
11
+ * `location` resolver and the `fetch` adapter; without them the source still
12
+ * runs against an offline `Merchant[]` so the skill is never dead on arrival.
13
+ *
14
+ * The result shape mirrors what rate's host returns today, so a mobile host
15
+ * can swap its bespoke merchant tools for this factory verbatim.
16
+ */
17
+ const FIND = 'find_merchant_locations';
18
+ const INFO = 'get_merchant_info';
19
+ /** A tiny, hand-curated sample so the skill works offline out of the box. */
20
+ export const BTC_MAP_SAMPLE = [
21
+ {
22
+ id: 'lugano-bitcoinpeople-cafe',
23
+ name: 'Bitcoin People Café',
24
+ category: 'cafe',
25
+ address: 'Via Pessina 12',
26
+ city: 'Lugano',
27
+ lat: 46.0037,
28
+ lng: 8.9511,
29
+ acceptedAssets: ['lightning', 'onchain'],
30
+ description: 'Specialty espresso bar; Plan ₿ Lugano partner.',
31
+ },
32
+ {
33
+ id: 'lugano-bistro-libertine',
34
+ name: 'Bistro Libertine',
35
+ category: 'restaurant',
36
+ address: 'Piazza della Riforma 3',
37
+ city: 'Lugano',
38
+ lat: 46.004,
39
+ lng: 8.952,
40
+ acceptedAssets: ['lightning', 'usdt', 'onchain'],
41
+ description: 'Italian-Swiss bistro, lunch + dinner. Accepts Tether on Liquid.',
42
+ },
43
+ {
44
+ id: 'lugano-bookshop-volta',
45
+ name: 'Libreria Volta',
46
+ category: 'shop',
47
+ address: 'Via Cattedrale 8',
48
+ city: 'Lugano',
49
+ lat: 46.0055,
50
+ lng: 8.9499,
51
+ acceptedAssets: ['lightning'],
52
+ description: 'Independent bookshop; Italian, English and German titles.',
53
+ },
54
+ {
55
+ id: 'lisbon-meson-andaluz',
56
+ name: 'Mesón Andaluz',
57
+ category: 'restaurant',
58
+ address: 'Rua das Flores 42',
59
+ city: 'Lisbon',
60
+ lat: 38.71,
61
+ lng: -9.143,
62
+ acceptedAssets: ['lightning', 'onchain'],
63
+ description: 'Andalusian tapas in Chiado. Bitcoin accepted since 2022.',
64
+ },
65
+ {
66
+ id: 'lisbon-surf-bitcoin',
67
+ name: 'Surf & Sats',
68
+ category: 'shop',
69
+ address: 'Av. da Liberdade 180',
70
+ city: 'Lisbon',
71
+ lat: 38.7211,
72
+ lng: -9.1466,
73
+ acceptedAssets: ['lightning'],
74
+ description: 'Surfboard rental and lessons in Costa da Caparica.',
75
+ },
76
+ {
77
+ id: 'sansalvador-elzonte-hope',
78
+ name: 'Hope House El Zonte',
79
+ category: 'cafe',
80
+ address: 'Calle Principal',
81
+ city: 'El Zonte',
82
+ lat: 13.492,
83
+ lng: -89.4395,
84
+ acceptedAssets: ['lightning', 'onchain'],
85
+ description: 'Bitcoin Beach hub. Coffee, community, and a Lightning ATM.',
86
+ },
87
+ {
88
+ id: 'sansalvador-elzonte-garten',
89
+ name: 'Garten Restaurante',
90
+ category: 'restaurant',
91
+ address: 'Bitcoin Beach',
92
+ city: 'El Zonte',
93
+ lat: 13.4925,
94
+ lng: -89.438,
95
+ acceptedAssets: ['lightning'],
96
+ description: 'Beachfront restaurant, full Bitcoin payments since 2021.',
97
+ },
98
+ {
99
+ id: 'nyc-pubkey',
100
+ name: 'PubKey',
101
+ category: 'bar',
102
+ address: '85 Washington Pl',
103
+ city: 'New York',
104
+ lat: 40.732,
105
+ lng: -73.999,
106
+ acceptedAssets: ['lightning', 'onchain'],
107
+ description: 'Bitcoin bar in Greenwich Village — meetups, Lightning tap.',
108
+ },
109
+ {
110
+ id: 'prague-paralelni-polis',
111
+ name: 'Paralelní Polis',
112
+ category: 'cafe',
113
+ address: 'Dělnická 43',
114
+ city: 'Prague',
115
+ lat: 50.105,
116
+ lng: 14.448,
117
+ acceptedAssets: ['lightning', 'onchain', 'monero'],
118
+ description: 'Crypto-only café and hackerspace — no fiat accepted, ever.',
119
+ },
120
+ {
121
+ id: 'amsterdam-bitcoin-embassy',
122
+ name: 'Bitcoin Embassy Amsterdam',
123
+ category: 'cafe',
124
+ address: 'Nieuwezijds Voorburgwal 162',
125
+ city: 'Amsterdam',
126
+ lat: 52.374,
127
+ lng: 4.893,
128
+ acceptedAssets: ['lightning', 'onchain'],
129
+ description: 'Co-working café and meetup hub, Lightning tap on draft beer.',
130
+ },
131
+ ];
132
+ /** Clamp a value to a numeric range, returning the default when input is bad. */
133
+ function clamp(n, lo, hi, dflt) {
134
+ const v = Number(n);
135
+ if (!Number.isFinite(v))
136
+ return dflt;
137
+ return Math.min(hi, Math.max(lo, v));
138
+ }
139
+ /** Substring scoring used by the offline fallback (matches the old behavior). */
140
+ function fuzzyScore(query, text) {
141
+ const q = query.toLowerCase();
142
+ const t = text.toLowerCase();
143
+ if (!q)
144
+ return 1;
145
+ if (t.includes(q))
146
+ return 1;
147
+ let hits = 0;
148
+ let qi = 0;
149
+ for (let i = 0; i < t.length && qi < q.length; i++) {
150
+ if (t[i] === q[qi]) {
151
+ hits++;
152
+ qi++;
153
+ }
154
+ }
155
+ return hits / q.length;
156
+ }
157
+ /** Map a Merchant → the response row the model sees (stable for rate parity). */
158
+ function row(m) {
159
+ return {
160
+ id: m.id,
161
+ name: m.name,
162
+ address: m.address,
163
+ category: m.category,
164
+ lat: m.lat,
165
+ lng: m.lng,
166
+ distance_m: m.distance_m,
167
+ phone: m.phone,
168
+ website: m.website,
169
+ opening_hours: m.opening_hours,
170
+ accepts_bitcoin: m.acceptedAssets?.includes('onchain') ?? true,
171
+ accepts_lightning: m.acceptedAssets?.includes('lightning') ?? true,
172
+ };
173
+ }
174
+ /** Offline search: substring + optional category over the bundled list. */
175
+ function searchOffline(merchants, query, category, limit) {
176
+ let filtered = merchants;
177
+ if (category) {
178
+ const c = category.toLowerCase().trim();
179
+ filtered = filtered.filter((m) => (m.category ?? '').toLowerCase() === c);
180
+ }
181
+ const q = (query ?? '').trim();
182
+ if (q.length >= 2) {
183
+ filtered = filtered
184
+ .map((m) => {
185
+ const hay = `${m.name ?? ''} ${m.description ?? ''} ${m.address ?? ''} ${m.city ?? ''}`;
186
+ const score = fuzzyScore(q, m.name ?? '') * 3 +
187
+ fuzzyScore(q, m.address ?? '') * 2 +
188
+ fuzzyScore(q, hay) * 1;
189
+ return { m, score };
190
+ })
191
+ .filter((x) => x.score > 0.3)
192
+ .sort((a, b) => b.score - a.score)
193
+ .map((x) => x.m);
194
+ }
195
+ return filtered.slice(0, limit);
196
+ }
197
+ /**
198
+ * Build a ToolSource exposing `find_merchant_locations` + `get_merchant_info`.
199
+ *
200
+ * Resolution order for `find_merchant_locations`:
201
+ * 1. `near_address` provided → opts.location.geocode → opts.fetch (live)
202
+ * 2. opts.location.getCurrent → opts.fetch (live)
203
+ * 3. fall through to offline substring search over opts.offlineMerchants
204
+ *
205
+ * Any step that fails silently falls through to the next, so the skill is
206
+ * always answerable.
207
+ */
208
+ export function createBtcMapToolSource(opts = {}) {
209
+ const offline = opts.offlineMerchants ?? BTC_MAP_SAMPLE;
210
+ const defaultLimit = opts.k ?? 10;
211
+ const find = {
212
+ name: FIND,
213
+ description: "Find Bitcoin-accepting merchants near the user using live BTC Map data " +
214
+ "and the device's real location when available. Use when the user wants " +
215
+ 'merchants, shops, restaurants, cafes, bars, ATMs, or places to spend ' +
216
+ 'Bitcoin nearby. Pass ONLY the fields the user actually named — do not ' +
217
+ 'invent constraints (e.g. omit `query` when they just say "near me").',
218
+ parameters: {
219
+ type: 'object',
220
+ properties: {
221
+ query: { type: 'string', description: 'Optional filter for merchant name or type, e.g. "coffee"' },
222
+ category: { type: 'string', description: 'restaurant | cafe | bar | shop | grocery | lodging | atm' },
223
+ near_address: { type: 'string', description: 'Address/city to search around instead of the current location' },
224
+ radius_km: { type: 'number', description: 'Search radius in km (0.25–50, default 5)' },
225
+ limit: { type: 'number', description: 'Max number of results (1–20, default 10)' },
226
+ },
227
+ },
228
+ };
229
+ const info = {
230
+ name: INFO,
231
+ description: 'Get detailed information about one specific merchant by id or name — ' +
232
+ 'full address, accepted assets, contact details. Use after ' +
233
+ 'find_merchant_locations when the user asks for more on a specific result.',
234
+ parameters: {
235
+ type: 'object',
236
+ properties: {
237
+ merchant_id: { type: 'string', description: 'Merchant id from find_merchant_locations (string or number)' },
238
+ merchant_name: { type: 'string', description: 'Merchant name (used when id is unknown)' },
239
+ },
240
+ },
241
+ };
242
+ async function tryLive(center, radiusMeters, query, category, limit) {
243
+ if (!opts.fetch)
244
+ return null;
245
+ try {
246
+ return await opts.fetch({
247
+ center: { lat: center.lat, lng: center.lng },
248
+ radiusMeters,
249
+ query,
250
+ category,
251
+ limit,
252
+ });
253
+ }
254
+ catch {
255
+ return null;
256
+ }
257
+ }
258
+ async function resolveCenter(near_address) {
259
+ if (!opts.location)
260
+ return null;
261
+ if (near_address && near_address.trim().length >= 2 && opts.location.geocode) {
262
+ try {
263
+ const pt = await opts.location.geocode(near_address);
264
+ if (pt)
265
+ return { ...pt, label: near_address, precise: false };
266
+ }
267
+ catch {
268
+ /* fall through */
269
+ }
270
+ }
271
+ try {
272
+ return await opts.location.getCurrent();
273
+ }
274
+ catch {
275
+ return null;
276
+ }
277
+ }
278
+ async function findLocations(args) {
279
+ const query = args.query ? String(args.query) : undefined;
280
+ const category = args.category ? String(args.category) : undefined;
281
+ const near_address = args.near_address ? String(args.near_address) : undefined;
282
+ const radius_km = clamp(args.radius_km, 0.25, 50, 5);
283
+ const limit = clamp(args.limit, 1, 20, defaultLimit);
284
+ const radiusMeters = radius_km * 1000;
285
+ // 1 + 2. Try the live path when we can.
286
+ const center = await resolveCenter(near_address);
287
+ if (center) {
288
+ const live = await tryLive(center, radiusMeters, query, category, limit);
289
+ if (live) {
290
+ const where = center.label || (center.precise ? 'your location' : 'the default location');
291
+ return {
292
+ success: true,
293
+ source: 'btcmap',
294
+ precise_location: !!center.precise,
295
+ center: { lat: center.lat, lng: center.lng },
296
+ merchants: live.map(row),
297
+ total_found: live.length,
298
+ message: live.length > 0
299
+ ? `Found ${live.length} Bitcoin merchant${live.length === 1 ? '' : 's'} near ${where}${query ? ` matching "${query}"` : ''}.`
300
+ : `No Bitcoin merchants found within ${radius_km} km of ${where}. Try widening the radius.`,
301
+ };
302
+ }
303
+ }
304
+ // 3. Offline fallback.
305
+ const found = searchOffline(offline, query, category, limit);
306
+ return {
307
+ success: true,
308
+ source: 'offline',
309
+ precise_location: false,
310
+ merchants: found.map(row),
311
+ total_found: found.length,
312
+ message: found.length > 0
313
+ ? `Showing ${found.length} merchant${found.length === 1 ? '' : 's'} from the offline list${query ? ` matching "${query}"` : ''}.`
314
+ : `No merchants in the offline list matched${query ? ` "${query}"` : ''}. The host hasn't injected a live BTC Map fetch.`,
315
+ };
316
+ }
317
+ async function getInfo(args) {
318
+ const idArg = args.merchant_id;
319
+ const nameArg = args.merchant_name ? String(args.merchant_name).trim() : '';
320
+ let m;
321
+ if (idArg !== undefined && idArg !== null && idArg !== '') {
322
+ const want = String(idArg);
323
+ m = offline.find((x) => String(x.id) === want);
324
+ }
325
+ if (!m && nameArg.length >= 2) {
326
+ const q = nameArg.toLowerCase();
327
+ m =
328
+ offline.find((x) => (x.name ?? '').toLowerCase() === q) ??
329
+ offline
330
+ .map((x) => ({ x, score: fuzzyScore(q, (x.name ?? '').toLowerCase()) }))
331
+ .filter((r) => r.score > 0.5)
332
+ .sort((a, b) => b.score - a.score)[0]?.x;
333
+ }
334
+ if (!m) {
335
+ const suggestions = nameArg
336
+ ? offline
337
+ .map((x) => ({ name: x.name ?? '', score: fuzzyScore(nameArg.toLowerCase(), (x.name ?? '').toLowerCase()) }))
338
+ .filter((r) => r.score > 0.3)
339
+ .sort((a, b) => b.score - a.score)
340
+ .slice(0, 3)
341
+ .map((r) => r.name)
342
+ : [];
343
+ return {
344
+ success: false,
345
+ error: `Could not find merchant${nameArg ? ` "${nameArg}"` : idArg !== undefined ? ` with id ${idArg}` : ''}.`,
346
+ suggestions: suggestions.length ? suggestions : undefined,
347
+ };
348
+ }
349
+ return { success: true, merchant: { ...row(m), city: m.city } };
350
+ }
351
+ async function execute(name, args) {
352
+ if (name === FIND)
353
+ return findLocations(args);
354
+ if (name === INFO)
355
+ return getInfo(args);
356
+ throw new Error(`btc-map: unknown tool "${name}"`);
357
+ }
358
+ return {
359
+ id: 'btc-map',
360
+ listTools: () => [find, info],
361
+ has: (name) => name === FIND || name === INFO,
362
+ execute,
363
+ };
364
+ }
365
+ //# sourceMappingURL=btc-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"btc-map.js","sourceRoot":"","sources":["../../src/knowledge/btc-map.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Canonical LSPS1 tool contract — Lightning Service Provider channel orders.
3
+ *
4
+ * LSPS1 is a transport-agnostic protocol for buying inbound channel liquidity
5
+ * from a Lightning Service Provider. The maker happens to implement it, but a
6
+ * different LSP could too — so the tool names are LSP-agnostic (`lsp_*`),
7
+ * not `kaleidoswap_*`. The host's binder decides which LSP they reach.
8
+ *
9
+ * Every surface implements THESE EXACT tools, only the transport differs:
10
+ * - mobile → in-process handlers over the WDK LSP adapter
11
+ * - desktop → HTTP / MCP / CLI handlers
12
+ * - eval → stub handlers
13
+ *
14
+ * `lsp_create_order` is a spend → confirmation-gated.
15
+ *
16
+ * Pure data — no deps, no fetch, RN-safe.
17
+ */
18
+ import type { ToolDef } from '../types.js';
19
+ import { InProcessToolSource } from '../tools/in-process.js';
20
+ export interface Lsps1ToolDef extends ToolDef {
21
+ /** Moves funds → confirmation-gated. */
22
+ spend?: boolean;
23
+ }
24
+ /**
25
+ * The canonical LSPS1 tool list — agent-facing schemas. Each host's binder
26
+ * translates these args into the LSP's request body (LSPS1 JSON-RPC, the
27
+ * KaleidoSwap maker's REST routes, MCP, or a WDK adapter call).
28
+ */
29
+ export declare const LSPS1_TOOLS: Lsps1ToolDef[];
30
+ /** All LSPS1 tool names that move funds (confirmation-gated). */
31
+ export declare const LSPS1_SPEND_TOOLS: Set<string>;
32
+ export declare function isLsps1SpendTool(name: string): boolean;
33
+ export declare function getLsps1Tool(name: string): Lsps1ToolDef | undefined;
34
+ /** A handler bound to one LSPS1 tool. */
35
+ export type Lsps1Handler = (args: Record<string, unknown>) => Promise<unknown>;
36
+ export interface BindLsps1Options {
37
+ /** Skip tools without a handler instead of throwing (default false). */
38
+ allowMissing?: boolean;
39
+ /** ToolSource id for the registry (default 'lsps1'). */
40
+ id?: string;
41
+ }
42
+ /**
43
+ * Bind LSPS1 contract tools to in-process handlers → an InProcessToolSource.
44
+ *
45
+ * const source = bindLsps1Tools({
46
+ * lsp_get_info: async () => makerLsp.getInfo(),
47
+ * lsp_estimate_fees: async (args) => makerLsp.estimateFees(args),
48
+ * lsp_create_order: async (args) => makerLsp.createOrder(args),
49
+ * lsp_get_order: async ({ order_id }) => makerLsp.getOrder(order_id),
50
+ * lsp_get_network_info:async () => makerLsp.networkInfo(),
51
+ * });
52
+ * tools.register(source);
53
+ */
54
+ export declare function bindLsps1Tools(handlers: Record<string, Lsps1Handler>, opts?: BindLsps1Options): InProcessToolSource;
55
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/lsps1/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC3C,wCAAwC;IACxC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAcD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,YAAY,EAiCrC,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAEzC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEnE;AAED,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/E,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wDAAwD;IACxD,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,GAAE,gBAAqB,GAAG,mBAAmB,CAiBvH"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Canonical LSPS1 tool contract — Lightning Service Provider channel orders.
3
+ *
4
+ * LSPS1 is a transport-agnostic protocol for buying inbound channel liquidity
5
+ * from a Lightning Service Provider. The maker happens to implement it, but a
6
+ * different LSP could too — so the tool names are LSP-agnostic (`lsp_*`),
7
+ * not `kaleidoswap_*`. The host's binder decides which LSP they reach.
8
+ *
9
+ * Every surface implements THESE EXACT tools, only the transport differs:
10
+ * - mobile → in-process handlers over the WDK LSP adapter
11
+ * - desktop → HTTP / MCP / CLI handlers
12
+ * - eval → stub handlers
13
+ *
14
+ * `lsp_create_order` is a spend → confirmation-gated.
15
+ *
16
+ * Pure data — no deps, no fetch, RN-safe.
17
+ */
18
+ import { InProcessToolSource } from '../tools/in-process.js';
19
+ function t(name, description, properties = {}, required = [], spend = false) {
20
+ return {
21
+ name,
22
+ description,
23
+ spend,
24
+ requiresConfirmation: spend,
25
+ parameters: { type: 'object', properties, required },
26
+ };
27
+ }
28
+ /**
29
+ * The canonical LSPS1 tool list — agent-facing schemas. Each host's binder
30
+ * translates these args into the LSP's request body (LSPS1 JSON-RPC, the
31
+ * KaleidoSwap maker's REST routes, MCP, or a WDK adapter call).
32
+ */
33
+ export const LSPS1_TOOLS = [
34
+ t('lsp_get_info', "Get the LSP's capabilities: minimum/maximum channel size, supported expiries, fee structure, accepted payment options. Use this before estimating or ordering a channel. No args."),
35
+ t('lsp_get_network_info', "Get the LSP's Lightning network info: pubkey, host, port, connect URI. Useful to display the counterparty or pre-connect a peer. No args."),
36
+ t('lsp_estimate_fees', "Estimate the fee for a channel order BEFORE committing. Returns the total cost in sats plus any LSP routing fee. Re-estimate rather than reusing a stale value.", {
37
+ lsp_balance_sat: { type: 'number', description: "Sats the LSP commits on their side (inbound capacity for the user)." },
38
+ client_balance_sat: { type: 'number', description: "Sats the user pre-funds into the channel (push amount). Often 0." },
39
+ channel_expiry_blocks: { type: 'number', description: 'Optional minimum lease in blocks. Defaults to the LSP minimum.' },
40
+ }, ['lsp_balance_sat']),
41
+ t('lsp_create_order', "Create a channel order. SPEND: confirmation-gated. Returns an order id + a Lightning invoice the user pays to lock the order. The channel opens only after payment.", {
42
+ lsp_balance_sat: { type: 'number', description: "Sats the LSP commits on their side (inbound capacity for the user)." },
43
+ client_balance_sat: { type: 'number', description: 'Sats the user pre-funds. Often 0.' },
44
+ channel_expiry_blocks: { type: 'number', description: 'Minimum lease in blocks. Defaults to LSP minimum from lsp_get_info.' },
45
+ refund_onchain_address: { type: 'string', description: 'Optional on-chain refund address if the LSP cannot open the channel.' },
46
+ }, ['lsp_balance_sat'],
47
+ /* spend */ true),
48
+ t('lsp_get_order', 'Check the status of an LSPS1 order — pending / paid / opening / completed / failed. Poll after creating an order until the channel opens.', {
49
+ order_id: { type: 'string', description: 'The order id from lsp_create_order.' },
50
+ }, ['order_id']),
51
+ ];
52
+ /** All LSPS1 tool names that move funds (confirmation-gated). */
53
+ export const LSPS1_SPEND_TOOLS = new Set(LSPS1_TOOLS.filter((t) => t.spend).map((t) => t.name));
54
+ export function isLsps1SpendTool(name) {
55
+ return LSPS1_SPEND_TOOLS.has(name);
56
+ }
57
+ export function getLsps1Tool(name) {
58
+ return LSPS1_TOOLS.find((t) => t.name === name);
59
+ }
60
+ /**
61
+ * Bind LSPS1 contract tools to in-process handlers → an InProcessToolSource.
62
+ *
63
+ * const source = bindLsps1Tools({
64
+ * lsp_get_info: async () => makerLsp.getInfo(),
65
+ * lsp_estimate_fees: async (args) => makerLsp.estimateFees(args),
66
+ * lsp_create_order: async (args) => makerLsp.createOrder(args),
67
+ * lsp_get_order: async ({ order_id }) => makerLsp.getOrder(order_id),
68
+ * lsp_get_network_info:async () => makerLsp.networkInfo(),
69
+ * });
70
+ * tools.register(source);
71
+ */
72
+ export function bindLsps1Tools(handlers, opts = {}) {
73
+ const bound = [];
74
+ for (const def of LSPS1_TOOLS) {
75
+ const handler = handlers[def.name];
76
+ if (!handler) {
77
+ if (opts.allowMissing)
78
+ continue;
79
+ throw new Error(`bindLsps1Tools: no handler for "${def.name}"`);
80
+ }
81
+ bound.push({
82
+ name: def.name,
83
+ description: def.description,
84
+ parameters: def.parameters,
85
+ requiresConfirmation: def.requiresConfirmation,
86
+ handler,
87
+ });
88
+ }
89
+ return new InProcessToolSource(opts.id ?? 'lsps1', bound);
90
+ }
91
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../src/lsps1/contract.ts"],"names":[],"mappings":"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"}
@@ -6,12 +6,17 @@
6
6
  * const store = new InMemoryMemoryStore({ io }); // persisted (RN/Node)
7
7
  * const store = new InMemoryMemoryStore({ io, embed }); // + semantic recall
8
8
  */
9
- import type { MemoryIO, MemoryItem, MemoryQuery, MemoryStore, NewMemory } from './types.js';
9
+ import type { MemoryConsolidation, MemoryIO, MemoryItem, MemoryQuery, MemoryStore, NewMemory } from './types.js';
10
10
  export interface MemoryStoreOptions {
11
11
  /** Persistence (load on first use, save on writes). Omit for ephemeral memory. */
12
12
  io?: MemoryIO;
13
13
  /** Embed text for semantic recall. Omit to fall back to substring matching. */
14
14
  embed?: (text: string) => Promise<number[]>;
15
+ /**
16
+ * Fold near-duplicate writes into one item instead of appending. Needs `embed`.
17
+ * Omit for append-only. See {@link MemoryConsolidation}.
18
+ */
19
+ consolidate?: MemoryConsolidation;
15
20
  /** Clock — injectable for deterministic tests. */
16
21
  now?: () => number;
17
22
  }
@@ -21,6 +26,7 @@ export declare class InMemoryMemoryStore implements MemoryStore {
21
26
  private counter;
22
27
  private readonly io?;
23
28
  private readonly embed?;
29
+ private readonly consolidate?;
24
30
  private readonly now;
25
31
  constructor(opts?: MemoryStoreOptions);
26
32
  private hydrate;
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,+EAA+E;IAC/E,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,GAAE,kBAAuB;YAM3B,OAAO;YAaP,OAAO;IAIf,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAiBzC,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAK5B,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqCjD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,EAAE,CAAC,EAAE,QAAQ,CAAC;IACd,+EAA+E;IAC/E,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C;;;OAGG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAW;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAsC;IAC7D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,IAAI,GAAE,kBAAuB;YAO3B,OAAO;YAaP,OAAO;IAIf,GAAG,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IA8CzC,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAK5B,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqCjD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
@@ -7,16 +7,19 @@
7
7
  * const store = new InMemoryMemoryStore({ io, embed }); // + semantic recall
8
8
  */
9
9
  import { cosineSimilarity } from '../rag/vector-store.js';
10
+ const DEFAULT_DEDUP_THRESHOLD = 0.92;
10
11
  export class InMemoryMemoryStore {
11
12
  items = [];
12
13
  hydrated = false;
13
14
  counter = 0;
14
15
  io;
15
16
  embed;
17
+ consolidate;
16
18
  now;
17
19
  constructor(opts = {}) {
18
20
  this.io = opts.io;
19
21
  this.embed = opts.embed;
22
+ this.consolidate = opts.consolidate;
20
23
  this.now = opts.now ?? (() => Date.now());
21
24
  }
22
25
  async hydrate() {
@@ -39,15 +42,46 @@ export class InMemoryMemoryStore {
39
42
  }
40
43
  async add(item) {
41
44
  await this.hydrate();
42
- const embedding = item.embedding ?? (this.embed ? await this.embed(item.text).catch(() => undefined) : undefined);
45
+ let text = item.text;
46
+ let embedding = item.embedding ?? (this.embed ? await this.embed(text).catch(() => undefined) : undefined);
47
+ let tags = item.tags;
48
+ let supersedeId;
49
+ // Consolidation: fold a same-kind near-duplicate into this write instead of
50
+ // appending — embedding-only by default, LLM rewrite when `merge` is set.
51
+ if (this.consolidate && embedding) {
52
+ const threshold = this.consolidate.threshold ?? DEFAULT_DEDUP_THRESHOLD;
53
+ let best;
54
+ for (const m of this.items) {
55
+ if (m.kind !== item.kind || !m.embedding)
56
+ continue;
57
+ const score = cosineSimilarity(embedding, m.embedding);
58
+ if (!best || score > best.score)
59
+ best = { item: m, score };
60
+ }
61
+ if (best && best.score >= threshold) {
62
+ supersedeId = best.item.id;
63
+ tags = unionTags(best.item.tags, item.tags);
64
+ if (this.consolidate.merge) {
65
+ const merged = await this.consolidate.merge(best.item.text, text).catch(() => null);
66
+ if (merged && merged.trim()) {
67
+ text = merged.trim();
68
+ if (this.embed)
69
+ embedding = await this.embed(text).catch(() => embedding);
70
+ }
71
+ }
72
+ // No merger → the incoming (newer) text supersedes the older item as-is.
73
+ }
74
+ }
43
75
  const full = {
44
76
  id: item.id ?? `mem_${this.now()}_${++this.counter}`,
45
- text: item.text,
77
+ text,
46
78
  kind: item.kind,
47
- tags: item.tags,
79
+ tags,
48
80
  createdAt: item.createdAt ?? this.now(),
49
81
  ...(embedding ? { embedding } : {}),
50
82
  };
83
+ if (supersedeId)
84
+ this.items = this.items.filter((m) => m.id !== supersedeId);
51
85
  this.items.push(full);
52
86
  await this.persist();
53
87
  return full;
@@ -100,4 +134,10 @@ export class InMemoryMemoryStore {
100
134
  await this.persist();
101
135
  }
102
136
  }
137
+ /** Merge two optional tag lists, de-duplicated. Returns undefined when both empty. */
138
+ function unionTags(a, b) {
139
+ if (!a?.length && !b?.length)
140
+ return undefined;
141
+ return [...new Set([...(a ?? []), ...(b ?? [])])];
142
+ }
103
143
  //# sourceMappingURL=store.js.map