@kaleidorg/mind 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/funnel.d.ts +19 -0
- package/dist/funnel.d.ts.map +1 -1
- package/dist/funnel.js +48 -10
- package/dist/funnel.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/kaleidoswap/contract.d.ts +3 -3
- package/dist/kaleidoswap/contract.d.ts.map +1 -1
- package/dist/kaleidoswap/contract.js +16 -4
- package/dist/kaleidoswap/contract.js.map +1 -1
- package/dist/knowledge/bitcoin-copilot.d.ts.map +1 -1
- package/dist/knowledge/bitcoin-copilot.js +102 -0
- package/dist/knowledge/bitcoin-copilot.js.map +1 -1
- package/dist/knowledge/btc-map.d.ts +14 -17
- package/dist/knowledge/btc-map.d.ts.map +1 -1
- package/dist/knowledge/btc-map.js +66 -266
- package/dist/knowledge/btc-map.js.map +1 -1
- package/dist/lsps1/contract.d.ts.map +1 -1
- package/dist/lsps1/contract.js +28 -10
- package/dist/lsps1/contract.js.map +1 -1
- package/dist/qvac/assistant.d.ts +73 -0
- package/dist/qvac/assistant.d.ts.map +1 -0
- package/dist/qvac/assistant.js +97 -0
- package/dist/qvac/assistant.js.map +1 -0
- package/dist/qvac/config.d.ts +64 -0
- package/dist/qvac/config.d.ts.map +1 -0
- package/dist/qvac/config.js +71 -0
- package/dist/qvac/config.js.map +1 -0
- package/dist/qvac/delegate.d.ts +48 -0
- package/dist/qvac/delegate.d.ts.map +1 -0
- package/dist/qvac/delegate.js +51 -0
- package/dist/qvac/delegate.js.map +1 -0
- package/dist/qvac/index.d.ts +19 -0
- package/dist/qvac/index.d.ts.map +1 -0
- package/dist/qvac/index.js +19 -0
- package/dist/qvac/index.js.map +1 -0
- package/dist/qvac/parse.d.ts +44 -0
- package/dist/qvac/parse.d.ts.map +1 -0
- package/dist/qvac/parse.js +28 -0
- package/dist/qvac/parse.js.map +1 -0
- package/dist/qvac/provider.d.ts +49 -0
- package/dist/qvac/provider.d.ts.map +1 -0
- package/dist/qvac/provider.js +68 -0
- package/dist/qvac/provider.js.map +1 -0
- package/dist/qvac/stream.d.ts +37 -0
- package/dist/qvac/stream.d.ts.map +1 -0
- package/dist/qvac/stream.js +29 -0
- package/dist/qvac/stream.js.map +1 -0
- package/dist/qvac/text.d.ts +19 -0
- package/dist/qvac/text.d.ts.map +1 -0
- package/dist/qvac/text.js +56 -0
- package/dist/qvac/text.js.map +1 -0
- package/dist/qvac/voice.d.ts +69 -0
- package/dist/qvac/voice.d.ts.map +1 -0
- package/dist/qvac/voice.js +51 -0
- package/dist/qvac/voice.js.map +1 -0
- package/dist/recipe/buy-asset-channel.d.ts +26 -0
- package/dist/recipe/buy-asset-channel.d.ts.map +1 -0
- package/dist/recipe/buy-asset-channel.js +112 -0
- package/dist/recipe/buy-asset-channel.js.map +1 -0
- package/dist/recipe/kaleidoswap-atomic.d.ts +26 -18
- package/dist/recipe/kaleidoswap-atomic.d.ts.map +1 -1
- package/dist/recipe/kaleidoswap-atomic.js +101 -63
- package/dist/recipe/kaleidoswap-atomic.js.map +1 -1
- package/dist/recipe/kaleidoswap-channel-order.d.ts +35 -0
- package/dist/recipe/kaleidoswap-channel-order.d.ts.map +1 -0
- package/dist/recipe/kaleidoswap-channel-order.js +493 -0
- package/dist/recipe/kaleidoswap-channel-order.js.map +1 -0
- package/dist/recipe/kaleidoswap-price.d.ts +21 -0
- package/dist/recipe/kaleidoswap-price.d.ts.map +1 -0
- package/dist/recipe/kaleidoswap-price.js +57 -0
- package/dist/recipe/kaleidoswap-price.js.map +1 -0
- package/dist/recipe/runner.d.ts +7 -1
- package/dist/recipe/runner.d.ts.map +1 -1
- package/dist/recipe/runner.js +115 -29
- package/dist/recipe/runner.js.map +1 -1
- package/dist/recipe/swap.d.ts +26 -1
- package/dist/recipe/swap.d.ts.map +1 -1
- package/dist/recipe/swap.js +108 -13
- package/dist/recipe/swap.js.map +1 -1
- package/dist/recipe/types.d.ts +25 -1
- package/dist/recipe/types.d.ts.map +1 -1
- package/dist/skills/registry.d.ts +33 -1
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +45 -1
- package/dist/skills/registry.js.map +1 -1
- package/package.json +15 -1
- package/skills/README.md +3 -0
- package/skills/kaleido-lsps/SKILL.md +101 -43
- package/skills/kaleido-trading/SKILL.md +81 -31
- package/skills/merchant-finder/SKILL.md +96 -66
- package/skills/rgb-lightning-node/SKILL.md +108 -0
- package/skills/wallet-assistant/SKILL.md +32 -21
- package/src/funnel.ts +66 -11
- package/src/index.ts +14 -2
- package/src/kaleidoswap/contract.test.ts +7 -2
- package/src/kaleidoswap/contract.ts +27 -5
- package/src/knowledge/bitcoin-copilot.ts +111 -0
- package/src/knowledge/btc-map.test.ts +53 -96
- package/src/knowledge/btc-map.ts +72 -287
- package/src/lsps1/contract.ts +32 -14
- package/src/qvac/assistant.test.ts +132 -0
- package/src/qvac/assistant.ts +146 -0
- package/src/qvac/config.test.ts +44 -0
- package/src/qvac/config.ts +76 -0
- package/src/qvac/delegate.test.ts +68 -0
- package/src/qvac/delegate.ts +71 -0
- package/src/qvac/index.ts +72 -0
- package/src/qvac/parse.test.ts +52 -0
- package/src/qvac/parse.ts +57 -0
- package/src/qvac/provider.test.ts +107 -0
- package/src/qvac/provider.ts +124 -0
- package/src/qvac/stream.test.ts +79 -0
- package/src/qvac/stream.ts +56 -0
- package/src/qvac/text.test.ts +70 -0
- package/src/qvac/text.ts +60 -0
- package/src/qvac/voice.test.ts +151 -0
- package/src/qvac/voice.ts +122 -0
- package/src/recipe/buy-asset-channel.test.ts +148 -0
- package/src/recipe/buy-asset-channel.ts +118 -0
- package/src/recipe/kaleidoswap-atomic.test.ts +134 -61
- package/src/recipe/kaleidoswap-atomic.ts +112 -66
- package/src/recipe/kaleidoswap-channel-order.test.ts +333 -0
- package/src/recipe/kaleidoswap-channel-order.ts +548 -0
- package/src/recipe/kaleidoswap-price.ts +68 -0
- package/src/recipe/recipe.test.ts +61 -5
- package/src/recipe/runner.ts +128 -31
- package/src/recipe/swap.ts +109 -13
- package/src/recipe/types.ts +25 -1
- package/src/skills/registry.ts +52 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consume a QVAC `completion()` run: drain the event stream (forwarding visible
|
|
3
|
+
* + thinking tokens) and fold the `final` frame into a ParsedTurn.
|
|
4
|
+
*
|
|
5
|
+
* Defined over a structural `CompletionRunLike` (not the SDK type) so it stays
|
|
6
|
+
* SDK-free and unit-testable with a fake run — the real `CompletionRun` is
|
|
7
|
+
* assignable to it. The actual `@qvac/sdk` import lives in `provider.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ParsedTurn, type QvacFinalLike } from './parse.js';
|
|
10
|
+
/** Minimal shape of a QVAC completion event we react to. */
|
|
11
|
+
export interface CompletionEventLike {
|
|
12
|
+
type: string;
|
|
13
|
+
/** Present on `contentDelta` / `thinkingDelta` / `rawDelta`. */
|
|
14
|
+
text?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Structural subset of `completion()`'s return we depend on. */
|
|
17
|
+
export interface CompletionRunLike {
|
|
18
|
+
requestId: string;
|
|
19
|
+
events: AsyncIterable<CompletionEventLike>;
|
|
20
|
+
final: Promise<QvacFinalLike>;
|
|
21
|
+
}
|
|
22
|
+
export interface StreamHandlers {
|
|
23
|
+
/** Visible assistant tokens (excludes `<think>` reasoning). */
|
|
24
|
+
onToken?: (token: string) => void;
|
|
25
|
+
/** The model's `<think>` reasoning, streamed separately. */
|
|
26
|
+
onThinking?: (token: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface ConsumedTurn extends ParsedTurn {
|
|
29
|
+
requestId: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stream a run to completion. `contentDelta` → onToken (and the streamed
|
|
33
|
+
* fallback text), `thinkingDelta` → onThinking. Returns the parsed turn plus the
|
|
34
|
+
* run's `requestId` (for cancellation bookkeeping by the caller).
|
|
35
|
+
*/
|
|
36
|
+
export declare function consumeRun(run: CompletionRunLike, handlers?: StreamHandlers): Promise<ConsumedTurn>;
|
|
37
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/qvac/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAe,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE9E,4DAA4D;AAC5D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,iBAAiB,EACtB,QAAQ,GAAE,cAAmB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAYvB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consume a QVAC `completion()` run: drain the event stream (forwarding visible
|
|
3
|
+
* + thinking tokens) and fold the `final` frame into a ParsedTurn.
|
|
4
|
+
*
|
|
5
|
+
* Defined over a structural `CompletionRunLike` (not the SDK type) so it stays
|
|
6
|
+
* SDK-free and unit-testable with a fake run — the real `CompletionRun` is
|
|
7
|
+
* assignable to it. The actual `@qvac/sdk` import lives in `provider.ts`.
|
|
8
|
+
*/
|
|
9
|
+
import { finalToTurn } from './parse.js';
|
|
10
|
+
/**
|
|
11
|
+
* Stream a run to completion. `contentDelta` → onToken (and the streamed
|
|
12
|
+
* fallback text), `thinkingDelta` → onThinking. Returns the parsed turn plus the
|
|
13
|
+
* run's `requestId` (for cancellation bookkeeping by the caller).
|
|
14
|
+
*/
|
|
15
|
+
export async function consumeRun(run, handlers = {}) {
|
|
16
|
+
let streamed = '';
|
|
17
|
+
for await (const event of run.events) {
|
|
18
|
+
if (event.type === 'contentDelta' && typeof event.text === 'string') {
|
|
19
|
+
streamed += event.text;
|
|
20
|
+
handlers.onToken?.(event.text);
|
|
21
|
+
}
|
|
22
|
+
else if (event.type === 'thinkingDelta' && typeof event.text === 'string') {
|
|
23
|
+
handlers.onThinking?.(event.text);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const final = await run.final;
|
|
27
|
+
return { ...finalToTurn(final, streamed), requestId: run.requestId };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/qvac/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,WAAW,EAAuC,MAAM,YAAY,CAAC;AA2B9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAsB,EACtB,WAA2B,EAAE;IAE7B,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpE,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;YACvB,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5E,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC;IAC9B,OAAO,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure text helpers for QVAC output. No SDK, no platform — safe to run and test
|
|
3
|
+
* anywhere. Lifted verbatim from rate's QVACService so every host shares one
|
|
4
|
+
* implementation instead of drifting copies.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Clean a raw assistant completion into user-visible text:
|
|
8
|
+
* - drop `<think>…</think>` reasoning (small models leak it into content),
|
|
9
|
+
* - drop a leading `{"name":…,"arguments":…}` tool-call object some tiny models
|
|
10
|
+
* emit as plain text, keeping any natural-language sentence that follows.
|
|
11
|
+
*/
|
|
12
|
+
export declare function cleanAssistantVisibleText(text: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Make text safe for the SUPERTONIC TTS model: redact payment strings (so they
|
|
15
|
+
* are never read aloud), strip markdown/code, normalize smart punctuation, and
|
|
16
|
+
* drop any non-ASCII or backtick (U+0060) the model can't synthesize.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sanitizeForSupertonic(text: string): string;
|
|
19
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/qvac/text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkB9D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB1D"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure text helpers for QVAC output. No SDK, no platform — safe to run and test
|
|
3
|
+
* anywhere. Lifted verbatim from rate's QVACService so every host shares one
|
|
4
|
+
* implementation instead of drifting copies.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Clean a raw assistant completion into user-visible text:
|
|
8
|
+
* - drop `<think>…</think>` reasoning (small models leak it into content),
|
|
9
|
+
* - drop a leading `{"name":…,"arguments":…}` tool-call object some tiny models
|
|
10
|
+
* emit as plain text, keeping any natural-language sentence that follows.
|
|
11
|
+
*/
|
|
12
|
+
export function cleanAssistantVisibleText(text) {
|
|
13
|
+
let cleaned = text
|
|
14
|
+
// Qwen-style reasoning sometimes arrives in contentText. Never show/speak it.
|
|
15
|
+
.replace(/<think\b[\s\S]*?<\/think>/gi, ' ')
|
|
16
|
+
.replace(/<think\b[\s\S]*$/gi, ' ')
|
|
17
|
+
.replace(/\s+/g, ' ')
|
|
18
|
+
.trim();
|
|
19
|
+
// Some small local models emit a tool-call object as plain text. Drop the
|
|
20
|
+
// leading fragment and keep any natural-language sentence that follows.
|
|
21
|
+
const toolPrefix = cleaned.match(/^\s*\{?\s*"name"\s*:\s*"[^"]+"\s*,\s*"arguments"\s*:\s*/i);
|
|
22
|
+
if (toolPrefix) {
|
|
23
|
+
cleaned = cleaned.slice(toolPrefix[0].length).replace(/^\s*\{?\s*/, '').trim();
|
|
24
|
+
}
|
|
25
|
+
return cleaned
|
|
26
|
+
.replace(/\s+/g, ' ')
|
|
27
|
+
.trim();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Make text safe for the SUPERTONIC TTS model: redact payment strings (so they
|
|
31
|
+
* are never read aloud), strip markdown/code, normalize smart punctuation, and
|
|
32
|
+
* drop any non-ASCII or backtick (U+0060) the model can't synthesize.
|
|
33
|
+
*/
|
|
34
|
+
export function sanitizeForSupertonic(text) {
|
|
35
|
+
const normalized = text
|
|
36
|
+
.replace(/\b(?:lightning:)?ln(?:bc|tb|bcrt)[a-z0-9]{40,}\b/gi, 'Lightning invoice')
|
|
37
|
+
.replace(/\blnurl[0-9a-z]{40,}\b/gi, 'Lightning payment link')
|
|
38
|
+
.replace(/```[\s\S]*?```/g, ' ')
|
|
39
|
+
.replace(/`([^`]*)`/g, '$1')
|
|
40
|
+
.replace(/[`´ˋ′*_~#<>|[\]{}]/g, ' ')
|
|
41
|
+
.replace(/[“”]/g, '"')
|
|
42
|
+
.replace(/[‘’]/g, "'")
|
|
43
|
+
.replace(/[•·]/g, '. ')
|
|
44
|
+
.replace(/[^\x09\x0A\x0D\x20-\x7E]/g, ' ')
|
|
45
|
+
.replace(/\s+/g, ' ');
|
|
46
|
+
return Array.from(normalized)
|
|
47
|
+
.filter((ch) => {
|
|
48
|
+
const code = ch.charCodeAt(0);
|
|
49
|
+
return (code === 0x09 || code === 0x0A || code === 0x0D || (code >= 0x20 && code <= 0x7E)) &&
|
|
50
|
+
code !== 0x60;
|
|
51
|
+
})
|
|
52
|
+
.join('')
|
|
53
|
+
.replace(/\s+/g, ' ')
|
|
54
|
+
.trim();
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/qvac/text.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,IAAI,OAAO,GAAG,IAAI;QAChB,8EAA8E;SAC7E,OAAO,CAAC,6BAA6B,EAAE,GAAG,CAAC;SAC3C,OAAO,CAAC,oBAAoB,EAAE,GAAG,CAAC;SAClC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IAEV,0EAA0E;IAC1E,wEAAwE;IACxE,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC7F,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjF,CAAC;IAED,OAAO,OAAO;SACX,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,UAAU,GAAG,IAAI;SACpB,OAAO,CAAC,oDAAoD,EAAE,mBAAmB,CAAC;SAClF,OAAO,CAAC,0BAA0B,EAAE,wBAAwB,CAAC;SAC7D,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC;SAC/B,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC;SAC3B,OAAO,CAAC,qBAAqB,EAAE,GAAG,CAAC;SACnC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,OAAO,CAAC,2BAA2B,EAAE,GAAG,CAAC;SACzC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAExB,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;SAC1B,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC9B,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC;YACxF,IAAI,KAAK,IAAI,CAAC;IAClB,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC;SACR,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Voice runtime ops shared across hosts: one-shot transcription (Whisper) and
|
|
3
|
+
* speech synthesis (SUPERTONIC TTS). Like the provider, the SDK functions are
|
|
4
|
+
* injected (type-only `@qvac/sdk` import, erased at build) so this carries no
|
|
5
|
+
* runtime SDK dependency and is unit-testable with fakes.
|
|
6
|
+
*
|
|
7
|
+
* The host still owns model lifecycle (download, load, local-vs-delegated) and
|
|
8
|
+
* audio I/O (mic capture, playback). It passes the loaded model-id resolvers;
|
|
9
|
+
* this module does the SDK calls + the text gating that must be identical
|
|
10
|
+
* everywhere (payment-string redaction, U+0060 refusal, file:// stripping).
|
|
11
|
+
*
|
|
12
|
+
* The streaming voice-assistant loop (transcribeStream + VAD) builds on top of
|
|
13
|
+
* these in a later pass.
|
|
14
|
+
*/
|
|
15
|
+
import type * as QvacSdk from '@qvac/sdk';
|
|
16
|
+
import type { VoiceTranscriptEvent } from './assistant.js';
|
|
17
|
+
type TranscribeFn = typeof QvacSdk.transcribe;
|
|
18
|
+
type TextToSpeechFn = typeof QvacSdk.textToSpeech;
|
|
19
|
+
type TranscribeStreamFn = typeof QvacSdk.transcribeStream;
|
|
20
|
+
/** 16-bit PCM samples plus their sample rate, ready for the host to play. */
|
|
21
|
+
export interface PcmAudio {
|
|
22
|
+
pcm: number[];
|
|
23
|
+
sampleRate: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A live VAD transcription session: feed mic audio with `write()`, iterate to
|
|
27
|
+
* receive `text`/`vad`/`endOfTurn` events, `end()` when audio stops. Pass it
|
|
28
|
+
* straight to `runVoiceAssistant`.
|
|
29
|
+
*/
|
|
30
|
+
export interface VoiceSession {
|
|
31
|
+
write(audioChunk: Uint8Array): void;
|
|
32
|
+
end(): void;
|
|
33
|
+
destroy(): void;
|
|
34
|
+
[Symbol.asyncIterator](): AsyncIterator<VoiceTranscriptEvent>;
|
|
35
|
+
}
|
|
36
|
+
export interface QvacVoiceOptions {
|
|
37
|
+
/** The SDK's `transcribe` (injected). */
|
|
38
|
+
transcribe: TranscribeFn;
|
|
39
|
+
/** The SDK's `textToSpeech` (injected). */
|
|
40
|
+
textToSpeech: TextToSpeechFn;
|
|
41
|
+
/** The SDK's `transcribeStream` (injected) — only needed for `openVoiceSession`. */
|
|
42
|
+
transcribeStream?: TranscribeStreamFn;
|
|
43
|
+
/** Resolve the loaded Whisper model id (null ⇒ not loaded → throws). */
|
|
44
|
+
getWhisperModelId: () => string | null;
|
|
45
|
+
/** Resolve the loaded TTS model id (null ⇒ not loaded → returns null). */
|
|
46
|
+
getTtsModelId: () => string | null;
|
|
47
|
+
/** TTS output sample rate; defaults to SUPERTONIC-2's 44.1 kHz. */
|
|
48
|
+
ttsSampleRate?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface QvacVoice {
|
|
51
|
+
/** Transcribe an audio file (path or `file://` URI) to text. */
|
|
52
|
+
transcribeAudio(audioUri: string): Promise<string>;
|
|
53
|
+
/**
|
|
54
|
+
* Synthesize speech for `text`. Returns PCM + sample rate, or `null` when TTS
|
|
55
|
+
* is unavailable or the text is empty after sanitization (host falls back to
|
|
56
|
+
* the system voice). Payment strings are redacted so they're never read aloud.
|
|
57
|
+
*/
|
|
58
|
+
synthesizeSpeech(text: string): Promise<PcmAudio | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Open a hands-free VAD transcription session (continuous voice). Requires
|
|
61
|
+
* `transcribeStream` to have been provided. Merge in `paramsOverride` to tune
|
|
62
|
+
* the defaults ({@link DEFAULT_VOICE_STREAM_PARAMS}). Feed the returned session
|
|
63
|
+
* to `runVoiceAssistant`.
|
|
64
|
+
*/
|
|
65
|
+
openVoiceSession(paramsOverride?: Record<string, unknown>): Promise<VoiceSession>;
|
|
66
|
+
}
|
|
67
|
+
export declare function createQvacVoice(options: QvacVoiceOptions): QvacVoice;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=voice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/qvac/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,KAAK,OAAO,MAAM,WAAW,CAAC;AAG1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,KAAK,YAAY,GAAG,OAAO,OAAO,CAAC,UAAU,CAAC;AAC9C,KAAK,cAAc,GAAG,OAAO,OAAO,CAAC,YAAY,CAAC;AAClD,KAAK,kBAAkB,GAAG,OAAO,OAAO,CAAC,gBAAgB,CAAC;AAE1D,6EAA6E;AAC7E,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,GAAG,IAAI,IAAI,CAAC;IACZ,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,oBAAoB,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,UAAU,EAAE,YAAY,CAAC;IACzB,2CAA2C;IAC3C,YAAY,EAAE,cAAc,CAAC;IAC7B,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IACtC,wEAAwE;IACxE,iBAAiB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACvC,0EAA0E;IAC1E,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACnC,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,gEAAgE;IAChE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACnD;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACzD;;;;;OAKG;IACH,gBAAgB,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACnF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CA+CpE"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { sanitizeForSupertonic } from './text.js';
|
|
2
|
+
import { TTS_SAMPLE_RATE, DEFAULT_VOICE_STREAM_PARAMS } from './config.js';
|
|
3
|
+
export function createQvacVoice(options) {
|
|
4
|
+
const sampleRate = options.ttsSampleRate ?? TTS_SAMPLE_RATE;
|
|
5
|
+
return {
|
|
6
|
+
async transcribeAudio(audioUri) {
|
|
7
|
+
const modelId = options.getWhisperModelId();
|
|
8
|
+
if (!modelId)
|
|
9
|
+
throw new Error('Whisper model not loaded');
|
|
10
|
+
// The SDK's native file reader wants a plain filesystem path, not a
|
|
11
|
+
// `file://` URI — the URI raises AUDIO_FILE_NOT_FOUND even when present.
|
|
12
|
+
const audioChunk = audioUri.replace('file://', '');
|
|
13
|
+
return await options.transcribe({ modelId, audioChunk });
|
|
14
|
+
},
|
|
15
|
+
async synthesizeSpeech(text) {
|
|
16
|
+
const modelId = options.getTtsModelId();
|
|
17
|
+
if (!modelId)
|
|
18
|
+
return null;
|
|
19
|
+
const trimmed = sanitizeForSupertonic(text);
|
|
20
|
+
if (!trimmed)
|
|
21
|
+
return null;
|
|
22
|
+
// Belt-and-suspenders: SUPERTONIC chokes on U+0060; sanitize already
|
|
23
|
+
// strips it, so refuse if any slipped through rather than crash the voice.
|
|
24
|
+
if (Array.from(trimmed).some((ch) => ch.charCodeAt(0) === 0x60))
|
|
25
|
+
return null;
|
|
26
|
+
const result = options.textToSpeech({
|
|
27
|
+
modelId,
|
|
28
|
+
text: trimmed,
|
|
29
|
+
inputType: 'text',
|
|
30
|
+
stream: false,
|
|
31
|
+
});
|
|
32
|
+
const pcm = await result.buffer;
|
|
33
|
+
return { pcm, sampleRate };
|
|
34
|
+
},
|
|
35
|
+
async openVoiceSession(paramsOverride = {}) {
|
|
36
|
+
if (!options.transcribeStream) {
|
|
37
|
+
throw new Error('transcribeStream not provided — pass it in QvacVoiceOptions for voice sessions');
|
|
38
|
+
}
|
|
39
|
+
const modelId = options.getWhisperModelId();
|
|
40
|
+
if (!modelId)
|
|
41
|
+
throw new Error('Whisper model not loaded');
|
|
42
|
+
const session = await options.transcribeStream({
|
|
43
|
+
modelId,
|
|
44
|
+
...DEFAULT_VOICE_STREAM_PARAMS,
|
|
45
|
+
...paramsOverride,
|
|
46
|
+
});
|
|
47
|
+
return session;
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=voice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/qvac/voice.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AA0D3E,MAAM,UAAU,eAAe,CAAC,OAAyB;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,IAAI,eAAe,CAAC;IAE5D,OAAO;QACL,KAAK,CAAC,eAAe,CAAC,QAAgB;YACpC,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC5C,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC1D,oEAAoE;YACpE,yEAAyE;YACzE,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACnD,OAAO,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAiC,CAAC,CAAC;QAC1F,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,IAAY;YACjC,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YAE1B,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAC;YAC1B,qEAAqE;YACrE,2EAA2E;YAC3E,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;gBAAE,OAAO,IAAI,CAAC;YAE7E,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;gBAClC,OAAO;gBACP,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,MAAM;gBACjB,MAAM,EAAE,KAAK;aACmB,CAAC,CAAC;YACpC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YAChC,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;QAC7B,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,iBAA0C,EAAE;YACjE,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,gFAAgF,CAAC,CAAC;YACpG,CAAC;YACD,MAAM,OAAO,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC5C,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC1D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC;gBAC7C,OAAO;gBACP,GAAG,2BAA2B;gBAC9B,GAAG,cAAc;aACmB,CAAC,CAAC;YACxC,OAAO,OAAkC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in "buy an asset channel" recipe — the onboarding buy.
|
|
3
|
+
*
|
|
4
|
+
* The user has on-chain BTC but no Lightning channel yet, and wants to HOLD an
|
|
5
|
+
* RGB asset (USDT, XAUT). They can't swap (no channel to swap inside), so they
|
|
6
|
+
* buy a NEW channel from the maker LSP pre-loaded with the asset. One quote,
|
|
7
|
+
* one spend:
|
|
8
|
+
*
|
|
9
|
+
* "buy 100 usdt" / "get me 50 xaut" / "i want 200 usdt"
|
|
10
|
+
* ↓ 1 model inference (slot extraction; 0 when the regex hits)
|
|
11
|
+
* kaleidoswap_lsp_quote_asset_channel ← maker prices the asset + channel
|
|
12
|
+
* kaleidoswap_lsp_create_asset_channel 🔒 ← (final) order it; pay to open
|
|
13
|
+
*
|
|
14
|
+
* Distinct from `swapRecipe`: a swap names a source asset ("swap 10 usdt FOR
|
|
15
|
+
* btc", "buy btc WITH usdt") and needs an existing channel. This is the
|
|
16
|
+
* no-source, no-channel onboarding path — "buy <amount> <asset>" with nothing
|
|
17
|
+
* to spend it from — so it must be SELECTED BEFORE swap for that phrasing.
|
|
18
|
+
*
|
|
19
|
+
* Opt-in: register via `Funnel.recipes` (like `kaleidoswapAtomicRecipe`). The
|
|
20
|
+
* host binds `kaleidoswap_lsp_*` to its transport (maker REST / MCP / WDK).
|
|
21
|
+
*/
|
|
22
|
+
import type { Recipe } from './types.js';
|
|
23
|
+
/** "buy 100 usdt" / "get me 50 xaut" / "i want 200 usdt" / "purchase 10 xaut". */
|
|
24
|
+
export declare function extractBuyAsset(text: string): Record<string, unknown> | null;
|
|
25
|
+
export declare const buyAssetChannelRecipe: Recipe;
|
|
26
|
+
//# sourceMappingURL=buy-asset-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buy-asset-channel.d.ts","sourceRoot":"","sources":["../../src/recipe/buy-asset-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AA4BzC,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAW5E;AAED,eAAO,MAAM,qBAAqB,EAAE,MAqDnC,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in "buy an asset channel" recipe — the onboarding buy.
|
|
3
|
+
*
|
|
4
|
+
* The user has on-chain BTC but no Lightning channel yet, and wants to HOLD an
|
|
5
|
+
* RGB asset (USDT, XAUT). They can't swap (no channel to swap inside), so they
|
|
6
|
+
* buy a NEW channel from the maker LSP pre-loaded with the asset. One quote,
|
|
7
|
+
* one spend:
|
|
8
|
+
*
|
|
9
|
+
* "buy 100 usdt" / "get me 50 xaut" / "i want 200 usdt"
|
|
10
|
+
* ↓ 1 model inference (slot extraction; 0 when the regex hits)
|
|
11
|
+
* kaleidoswap_lsp_quote_asset_channel ← maker prices the asset + channel
|
|
12
|
+
* kaleidoswap_lsp_create_asset_channel 🔒 ← (final) order it; pay to open
|
|
13
|
+
*
|
|
14
|
+
* Distinct from `swapRecipe`: a swap names a source asset ("swap 10 usdt FOR
|
|
15
|
+
* btc", "buy btc WITH usdt") and needs an existing channel. This is the
|
|
16
|
+
* no-source, no-channel onboarding path — "buy <amount> <asset>" with nothing
|
|
17
|
+
* to spend it from — so it must be SELECTED BEFORE swap for that phrasing.
|
|
18
|
+
*
|
|
19
|
+
* Opt-in: register via `Funnel.recipes` (like `kaleidoswapAtomicRecipe`). The
|
|
20
|
+
* host binds `kaleidoswap_lsp_*` to its transport (maker REST / MCP / WDK).
|
|
21
|
+
*/
|
|
22
|
+
/** RGB assets the maker sells as an asset channel. BTC is never "bought" this way. */
|
|
23
|
+
const RGB_ASSET = /\b(usdt|tether|xaut|gold)\b/i;
|
|
24
|
+
/** A named funding source ⇒ this is a swap, not an onboarding buy. */
|
|
25
|
+
const HAS_SOURCE = /\b(?:with|using|from)\b|\bfor\s+(?:btc|bitcoin|sats?|usdt|xaut|tether|gold)\b/i;
|
|
26
|
+
/** Verbs other intents own (swap / sell / send) — never an onboarding buy. */
|
|
27
|
+
const NOT_BUY = /\b(swap|exchange|convert|trade|sell|send)\b/i;
|
|
28
|
+
/** Acquire verbs that DO mean an onboarding buy. */
|
|
29
|
+
const BUY_VERB = /\b(buy|get|acquire|want|purchase|onboard|need)\b/i;
|
|
30
|
+
function normAsset(a) {
|
|
31
|
+
if (!a)
|
|
32
|
+
return undefined;
|
|
33
|
+
const x = a.toLowerCase();
|
|
34
|
+
if (/usdt|tether/.test(x))
|
|
35
|
+
return 'USDT';
|
|
36
|
+
if (/xaut|gold/.test(x))
|
|
37
|
+
return 'XAUT';
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const num = (s) => {
|
|
41
|
+
if (!s)
|
|
42
|
+
return undefined;
|
|
43
|
+
const n = Number(s.replace(/,/g, ''));
|
|
44
|
+
return Number.isFinite(n) ? n : undefined;
|
|
45
|
+
};
|
|
46
|
+
/** Thousands separators, locale-independent (deterministic for tests). */
|
|
47
|
+
const commas = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
48
|
+
/** "buy 100 usdt" / "get me 50 xaut" / "i want 200 usdt" / "purchase 10 xaut". */
|
|
49
|
+
export function extractBuyAsset(text) {
|
|
50
|
+
const t = text.trim();
|
|
51
|
+
if (NOT_BUY.test(t) || HAS_SOURCE.test(t))
|
|
52
|
+
return null;
|
|
53
|
+
if (!RGB_ASSET.test(t))
|
|
54
|
+
return null;
|
|
55
|
+
// buy/get/want/acquire/purchase [me] <amount> <asset>
|
|
56
|
+
const m = t.match(/\b(?:buy|get|acquire|want|purchase|onboard|need)\b(?:\s+me)?\s+([\d.,]+)\s*([a-z]+)/i);
|
|
57
|
+
if (!m)
|
|
58
|
+
return null;
|
|
59
|
+
const asset = normAsset(m[2]);
|
|
60
|
+
const amount = num(m[1]);
|
|
61
|
+
if (!asset || amount === undefined)
|
|
62
|
+
return null;
|
|
63
|
+
return { asset, asset_amount: amount };
|
|
64
|
+
}
|
|
65
|
+
export const buyAssetChannelRecipe = {
|
|
66
|
+
name: 'buy-asset-channel',
|
|
67
|
+
description: 'Onboarding buy: purchase a new Lightning channel pre-loaded with an RGB asset (USDT, XAUT) from the maker LSP — for a user with on-chain BTC but no channel yet. Quote, then order (with confirmation).',
|
|
68
|
+
// "buy/get/want N <rgb-asset>" with NO named source asset and NO swap/send verb.
|
|
69
|
+
match: (t) => !NOT_BUY.test(t) && !HAS_SOURCE.test(t) && RGB_ASSET.test(t) && BUY_VERB.test(t),
|
|
70
|
+
triggers: ['buy', 'get', 'purchase', 'acquire'],
|
|
71
|
+
slots: [
|
|
72
|
+
{ name: 'asset', type: 'string', description: 'RGB asset to acquire (USDT or XAUT)', required: true },
|
|
73
|
+
{ name: 'asset_amount', type: 'number', description: 'Amount of the asset to load into the channel (display units, e.g. 100)', required: true },
|
|
74
|
+
],
|
|
75
|
+
extract: extractBuyAsset,
|
|
76
|
+
confident: (s) => !!s.asset && s.asset_amount !== undefined && Number(s.asset_amount) > 0,
|
|
77
|
+
steps: [
|
|
78
|
+
// 1. Maker prices the asset + the channel.
|
|
79
|
+
// Returns { rfq_id, btc_amount_sat, channel_fee_sat, total_sat, expires_at }.
|
|
80
|
+
{
|
|
81
|
+
tool: 'kaleidoswap_lsp_quote_asset_channel',
|
|
82
|
+
as: 'quote',
|
|
83
|
+
args: (ctx) => ({ asset: ctx.slots.asset, asset_amount: ctx.slots.asset_amount }),
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
// 2. Order the channel with the fresh rfq_id. Spend → confirmation-gated.
|
|
87
|
+
// The quote's cost fields ride along so the host's confirm card can show
|
|
88
|
+
// the price before approval; the create tool treats them as display-only.
|
|
89
|
+
final: {
|
|
90
|
+
tool: 'kaleidoswap_lsp_create_asset_channel',
|
|
91
|
+
args: (ctx) => {
|
|
92
|
+
const q = (ctx.results.quote ?? {});
|
|
93
|
+
return {
|
|
94
|
+
asset: ctx.slots.asset,
|
|
95
|
+
asset_amount: ctx.slots.asset_amount,
|
|
96
|
+
rfq_id: q.rfq_id,
|
|
97
|
+
total_sat: q.total_sat,
|
|
98
|
+
btc_amount_sat: q.btc_amount_sat,
|
|
99
|
+
channel_fee_sat: q.channel_fee_sat,
|
|
100
|
+
expires_at: q.expires_at,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
summary: (ctx, finalResult) => {
|
|
105
|
+
const q = ctx.results.quote;
|
|
106
|
+
const o = finalResult;
|
|
107
|
+
const cost = typeof q?.total_sat === 'number' ? ` for ${commas(q.total_sat)} sats` : '';
|
|
108
|
+
const id = o?.order_id ? ` (order ${o.order_id})` : '';
|
|
109
|
+
return `Ordered a Lightning channel with ${ctx.slots.asset_amount} ${ctx.slots.asset}${cost}${id}. Pay the returned invoice/address to open it.`;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=buy-asset-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buy-asset-channel.js","sourceRoot":"","sources":["../../src/recipe/buy-asset-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Built-in "
|
|
2
|
+
* Built-in "swap on KaleidoSwap" recipe — the real atomic-swap chain.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* user pays the maker's Lightning invoice, and the maker releases.
|
|
4
|
+
* A swap (especially the full maker + RLN atomic) is a 6-step, two-service flow
|
|
5
|
+
* no small model can plan reliably, so the recipe carries the plan. The model
|
|
6
|
+
* is used for natural-language understanding of the request (slot extraction).
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* "buy 1 usdt" (or "swap 10 usdt to btc")
|
|
9
|
+
* ↓ heuristic pre-filter (0 inf) decides to enter the reliable recipe branch
|
|
10
|
+
* ↓ 1 model inference (forced LLM slot extraction — the model parses intent)
|
|
11
|
+
* kaleidoswap_get_quote ← MAKER prices the swap (read-only)
|
|
12
|
+
* ↓ [ONE confirmation gate — shows the real quote numbers]
|
|
13
|
+
* kaleidoswap_atomic_init ← MAKER locks the swap → swapstring, payment_hash
|
|
14
|
+
* rln_get_node_info ← NODE read pubkey (= taker_pubkey)
|
|
15
|
+
* rln_whitelist_swap ← NODE accept the swapstring
|
|
16
|
+
* kaleidoswap_atomic_execute ← MAKER settle (final)
|
|
12
17
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* kaleidoswap_atomic_init 🔒 ← maker locks the swap, returns its invoice
|
|
19
|
-
* rln_pay_invoice 🔒 ← user pays the maker
|
|
20
|
-
* kaleidoswap_atomic_execute 🔒 ← (final) maker releases the asset
|
|
18
|
+
* `forceModelExtract` ensures the model is always consulted for slot parsing
|
|
19
|
+
* (1 inference) so natural language like "buy 1 usdt" is interpreted by the LLM.
|
|
20
|
+
* A safety fallback in the runner uses the deterministic extractor if the model
|
|
21
|
+
* returns incomplete slots. The execution sequence + single-confirm gate remain
|
|
22
|
+
* fully deterministic and reliable.
|
|
21
23
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
+
* Status is NOT polled here — settlement takes seconds-to-minutes and blocking
|
|
25
|
+
* the chat is bad UX. The recipe reports "submitted, settling"; the user (or a
|
|
26
|
+
* follow-up turn) calls `kaleidoswap_atomic_status` on demand.
|
|
27
|
+
*
|
|
28
|
+
* Confirmation: the single decision a user makes is "given this quote, proceed?"
|
|
29
|
+
* — so the recipe declares ONE `confirm(ctx)` summary, fired after the quote and
|
|
30
|
+
* before init. init/whitelist/execute then run as one approved unit. (The
|
|
31
|
+
* runner's recipe-level confirm path handles this; see recipe/runner.ts.)
|
|
24
32
|
*/
|
|
25
33
|
import type { Recipe } from './types.js';
|
|
26
34
|
export declare const kaleidoswapAtomicRecipe: Recipe;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kaleidoswap-atomic.d.ts","sourceRoot":"","sources":["../../src/recipe/kaleidoswap-atomic.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"kaleidoswap-atomic.d.ts","sourceRoot":"","sources":["../../src/recipe/kaleidoswap-atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,YAAY,CAAC;AAkCxD,eAAO,MAAM,uBAAuB,EAAE,MA+FrC,CAAC"}
|