@toon-protocol/client-mcp 0.1.0 → 0.3.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/README.md +19 -38
- package/dist/app/index.html +166 -0
- package/dist/{chunk-5KFXUT5Q.js → chunk-CQ2QIZ6Z.js} +864 -604
- package/dist/chunk-CQ2QIZ6Z.js.map +1 -0
- package/dist/{chunk-FSS45ZX3.js → chunk-DLYE6U2Z.js} +1516 -316
- package/dist/chunk-DLYE6U2Z.js.map +1 -0
- package/dist/{chunk-3NAWISI5.js → chunk-QFHCXJ2V.js} +348 -101
- package/dist/chunk-QFHCXJ2V.js.map +1 -0
- package/dist/chunk-XV52IHVR.js +977 -0
- package/dist/chunk-XV52IHVR.js.map +1 -0
- package/dist/daemon.js +3 -4
- package/dist/daemon.js.map +1 -1
- package/dist/e2e/run-journey.d.ts +1 -0
- package/dist/e2e/run-journey.js +19953 -0
- package/dist/e2e/run-journey.js.map +1 -0
- package/dist/{ed25519-2QVPINLS.js → ed25519-2LFQXLYS.js} +6 -2
- package/dist/index.d.ts +282 -68
- package/dist/index.js +380 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +39 -6
- package/dist/mcp.js.map +1 -1
- package/package.json +11 -7
- package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js +0 -25
- package/dist/chunk-3NAWISI5.js.map +0 -1
- package/dist/chunk-5KFXUT5Q.js.map +0 -1
- package/dist/chunk-FSS45ZX3.js.map +0 -1
- package/dist/chunk-SKQTKZIH.js +0 -278
- package/dist/chunk-SKQTKZIH.js.map +0 -1
- package/dist/chunk-ZQKYZJWT.js +0 -359
- package/dist/chunk-ZQKYZJWT.js.map +0 -1
- package/dist/ed25519-2QVPINLS.js.map +0 -1
- package/dist/gateway-QOK47RKS-SEGTXBR3.js +0 -16
- package/dist/gateway-QOK47RKS-SEGTXBR3.js.map +0 -1
- package/dist/socks5-WTJBYGME-6COK4LXW.js +0 -139
- package/dist/socks5-WTJBYGME-6COK4LXW.js.map +0 -1
- /package/dist/{anon-proxy-W3KMM7GU-FN7ZJY7P.js.map → ed25519-2LFQXLYS.js.map} +0 -0
|
@@ -3,25 +3,29 @@ import {
|
|
|
3
3
|
ED25519_TORSION_SUBGROUP,
|
|
4
4
|
_map_to_curve_elligator2_curve25519,
|
|
5
5
|
ed25519,
|
|
6
|
+
ed25519_FROST,
|
|
6
7
|
ed25519_hasher,
|
|
7
8
|
ed25519ctx,
|
|
8
9
|
ed25519ph,
|
|
9
10
|
ristretto255,
|
|
11
|
+
ristretto255_FROST,
|
|
10
12
|
ristretto255_hasher,
|
|
11
13
|
ristretto255_oprf,
|
|
12
14
|
x25519
|
|
13
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-DLYE6U2Z.js";
|
|
14
16
|
import "./chunk-F22GNSF6.js";
|
|
15
17
|
export {
|
|
16
18
|
ED25519_TORSION_SUBGROUP,
|
|
17
19
|
_map_to_curve_elligator2_curve25519,
|
|
18
20
|
ed25519,
|
|
21
|
+
ed25519_FROST,
|
|
19
22
|
ed25519_hasher,
|
|
20
23
|
ed25519ctx,
|
|
21
24
|
ed25519ph,
|
|
22
25
|
ristretto255,
|
|
26
|
+
ristretto255_FROST,
|
|
23
27
|
ristretto255_hasher,
|
|
24
28
|
ristretto255_oprf,
|
|
25
29
|
x25519
|
|
26
30
|
};
|
|
27
|
-
//# sourceMappingURL=ed25519-
|
|
31
|
+
//# sourceMappingURL=ed25519-2LFQXLYS.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { NostrEvent } from 'nostr-tools/pure';
|
|
1
|
+
import { NostrEvent, EventTemplate } from 'nostr-tools/pure';
|
|
2
2
|
import { SwapPair } from '@toon-protocol/core';
|
|
3
3
|
import { ToonClientConfig } from '@toon-protocol/client';
|
|
4
4
|
import { FastifyInstance } from 'fastify';
|
|
5
|
+
import { ViewSpec } from '@toon-protocol/views';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Shared request/response contract for the `toon-clientd` localhost control
|
|
@@ -27,8 +28,8 @@ interface StatusResponse {
|
|
|
27
28
|
/** Daemon process uptime, ms. */
|
|
28
29
|
uptimeMs: number;
|
|
29
30
|
/**
|
|
30
|
-
* True while the
|
|
31
|
-
*
|
|
31
|
+
* True while the BTP session / channel are still coming up. Tools should
|
|
32
|
+
* surface "bootstrapping — retry" rather than blocking.
|
|
32
33
|
*/
|
|
33
34
|
bootstrapping: boolean;
|
|
34
35
|
/** True once the client has started and a channel is open (ready to publish). */
|
|
@@ -42,8 +43,7 @@ interface StatusResponse {
|
|
|
42
43
|
minaAddress?: string;
|
|
43
44
|
};
|
|
44
45
|
transport: {
|
|
45
|
-
type: 'direct'
|
|
46
|
-
socksProxy?: string;
|
|
46
|
+
type: 'direct';
|
|
47
47
|
btpUrl?: string;
|
|
48
48
|
};
|
|
49
49
|
relay: {
|
|
@@ -53,13 +53,6 @@ interface StatusResponse {
|
|
|
53
53
|
buffered: number;
|
|
54
54
|
/** Active subscription ids. */
|
|
55
55
|
subscriptions: string[];
|
|
56
|
-
/**
|
|
57
|
-
* Error from the daemon-managed read proxy, if any. Set only in the
|
|
58
|
-
* btp-direct + relay-`.anyone` case where the daemon starts its own `anon`
|
|
59
|
-
* proxy for reads; a failure here means hidden-service reads are down while
|
|
60
|
-
* direct paid writes are unaffected.
|
|
61
|
-
*/
|
|
62
|
-
proxyError?: string;
|
|
63
56
|
};
|
|
64
57
|
/** Per-chain settlement status when a named `network` tier is configured. */
|
|
65
58
|
network?: ChainStatus[];
|
|
@@ -90,6 +83,58 @@ interface PublishResponse {
|
|
|
90
83
|
/** Channel nonce after this publish (advances by one per paid write). */
|
|
91
84
|
nonce: number;
|
|
92
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* `POST /publish-unsigned` — build, SIGN (with the daemon-held key), and
|
|
88
|
+
* pay-to-write a Nostr event. The caller (a UI/agent) supplies only the event
|
|
89
|
+
* shell — it never holds the private key. For replaceable kinds (0 profile,
|
|
90
|
+
* 3 follow list) the daemon merges the latest known event's tags before signing.
|
|
91
|
+
*/
|
|
92
|
+
interface PublishUnsignedRequest {
|
|
93
|
+
/** Event kind to publish (integer, 0–65535). */
|
|
94
|
+
kind: number;
|
|
95
|
+
/** Event content (default ''). */
|
|
96
|
+
content?: string;
|
|
97
|
+
/** Event tags (array of string arrays). */
|
|
98
|
+
tags?: string[][];
|
|
99
|
+
/** ILP destination override (default: the configured apex/town address). */
|
|
100
|
+
destination?: string;
|
|
101
|
+
/** Fee override in base units. Defaults to the daemon's configured fee. */
|
|
102
|
+
fee?: string;
|
|
103
|
+
/** Which apex (BTP write target) to publish through (default: config-seeded). */
|
|
104
|
+
btpUrl?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* `POST /upload-media` — two-step spendy write: upload bytes to Arweave via the
|
|
108
|
+
* kind:5094 blob-storage DVM, then sign+publish a media event referencing the
|
|
109
|
+
* resulting Arweave URL. Single-packet only (large media is out of scope; see
|
|
110
|
+
* `requestBlobStorage`).
|
|
111
|
+
*/
|
|
112
|
+
interface UploadMediaRequest {
|
|
113
|
+
/** Base64-encoded media bytes. */
|
|
114
|
+
dataBase64: string;
|
|
115
|
+
/** MIME type (default 'application/octet-stream'). */
|
|
116
|
+
mime?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Kind of the media event to publish referencing the upload. Default 1063
|
|
119
|
+
* (NIP-94 file metadata). 20 = NIP-68 picture, 21/22 = NIP-71 video, 1 = note
|
|
120
|
+
* with a NIP-92 `imeta` attachment.
|
|
121
|
+
*/
|
|
122
|
+
kind?: number;
|
|
123
|
+
/** Caption / content for the published media event. */
|
|
124
|
+
caption?: string;
|
|
125
|
+
/** Extra tags merged into the published media event. */
|
|
126
|
+
tags?: string[][];
|
|
127
|
+
/** Fee override in base units (applies to the upload + the publish). */
|
|
128
|
+
fee?: string;
|
|
129
|
+
/** Which apex to publish through (default: config-seeded). */
|
|
130
|
+
btpUrl?: string;
|
|
131
|
+
}
|
|
132
|
+
interface UploadMediaResponse extends PublishResponse {
|
|
133
|
+
/** Arweave URL the media event references. */
|
|
134
|
+
url: string;
|
|
135
|
+
/** Arweave transaction id of the uploaded blob. */
|
|
136
|
+
txId: string;
|
|
137
|
+
}
|
|
93
138
|
/** `POST /subscribe` — register a persistent free-read subscription. */
|
|
94
139
|
interface SubscribeRequest {
|
|
95
140
|
/** NIP-01 filter(s). A single object or an array of OR-ed filters. */
|
|
@@ -108,6 +153,18 @@ interface SubscribeResponse {
|
|
|
108
153
|
/** The relays the subscription was registered on. */
|
|
109
154
|
relays: string[];
|
|
110
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* `POST /query` — one-shot free read: subscribe the filter(s), wait briefly, and
|
|
158
|
+
* return every buffered event matching them. Used by the apps `toon_query` tool.
|
|
159
|
+
*/
|
|
160
|
+
interface QueryRequest {
|
|
161
|
+
filters: NostrFilter | NostrFilter[];
|
|
162
|
+
/** Bounded wait for relay delivery, ms (default 1200). */
|
|
163
|
+
timeoutMs?: number;
|
|
164
|
+
}
|
|
165
|
+
interface QueryResponse {
|
|
166
|
+
events: NostrEvent[];
|
|
167
|
+
}
|
|
111
168
|
/** `GET /events` — drain buffered events for a subscription (free read). */
|
|
112
169
|
interface EventsQuery {
|
|
113
170
|
/** Restrict to a single subscription id. */
|
|
@@ -211,9 +268,39 @@ interface SwapResponse {
|
|
|
211
268
|
/** First rejection message, if any. */
|
|
212
269
|
message?: string;
|
|
213
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* `POST /http-fetch-paid` — payment-aware HTTP GET/POST. The daemon issues the
|
|
273
|
+
* request via `ToonClient.h402Fetch`; if the origin answers `402 Payment
|
|
274
|
+
* Required` the client transparently pays over TOON and retries, returning the
|
|
275
|
+
* settled resource. The caller never holds chain keys — settlement happens
|
|
276
|
+
* inside the daemon against the open apex channel.
|
|
277
|
+
*/
|
|
278
|
+
interface HttpFetchPaidRequest {
|
|
279
|
+
/** Absolute URL of the resource to fetch (the origin may gate it behind 402). */
|
|
280
|
+
url: string;
|
|
281
|
+
/** HTTP method (default GET). */
|
|
282
|
+
method?: string;
|
|
283
|
+
/** Request headers as a flat string→string map. */
|
|
284
|
+
headers?: Record<string, string>;
|
|
285
|
+
/** Request body (string; sent verbatim). Typically used with POST. */
|
|
286
|
+
body?: string;
|
|
287
|
+
/** Per-request timeout, ms (passed through to the client). */
|
|
288
|
+
timeout?: number;
|
|
289
|
+
}
|
|
290
|
+
interface HttpFetchPaidResponse {
|
|
291
|
+
/** Final HTTP status after any 402-pay-and-retry round trip. */
|
|
292
|
+
status: number;
|
|
293
|
+
/** Response headers as a flat string→string map. */
|
|
294
|
+
headers: Record<string, string>;
|
|
295
|
+
/**
|
|
296
|
+
* Response body decoded as text. Binary bodies are returned as their decoded
|
|
297
|
+
* text for v1 (acceptable; a base64 path can be added later if needed).
|
|
298
|
+
*/
|
|
299
|
+
body: string;
|
|
300
|
+
}
|
|
214
301
|
/** `POST /relays` — add a relay READ target (fans into all fan-out reads). */
|
|
215
302
|
interface AddRelayRequest {
|
|
216
|
-
/** Relay WS URL, e.g. `ws://host:7100
|
|
303
|
+
/** Relay WS URL, e.g. `ws://host:7100`. */
|
|
217
304
|
relayUrl: string;
|
|
218
305
|
}
|
|
219
306
|
/** `DELETE /relays` — remove a relay read target. */
|
|
@@ -337,13 +424,17 @@ declare class ControlClient {
|
|
|
337
424
|
ping(): Promise<boolean>;
|
|
338
425
|
status(): Promise<StatusResponse>;
|
|
339
426
|
publish(body: PublishRequest): Promise<PublishResponse>;
|
|
427
|
+
publishUnsigned(body: PublishUnsignedRequest): Promise<PublishResponse>;
|
|
428
|
+
uploadMedia(body: UploadMediaRequest): Promise<UploadMediaResponse>;
|
|
340
429
|
subscribe(body: SubscribeRequest): Promise<SubscribeResponse>;
|
|
430
|
+
query(body: QueryRequest): Promise<QueryResponse>;
|
|
341
431
|
events(query?: EventsQuery): Promise<EventsResponse>;
|
|
342
432
|
openChannel(body?: OpenChannelRequest): Promise<{
|
|
343
433
|
channelId: string;
|
|
344
434
|
}>;
|
|
345
435
|
channels(): Promise<ChannelsResponse>;
|
|
346
436
|
swap(body: SwapRequest): Promise<SwapResponse>;
|
|
437
|
+
httpFetchPaid(body: HttpFetchPaidRequest): Promise<HttpFetchPaidResponse>;
|
|
347
438
|
targets(): Promise<TargetsResponse>;
|
|
348
439
|
addRelay(body: AddRelayRequest): Promise<TargetsResponse>;
|
|
349
440
|
removeRelay(body: RemoveRelayRequest): Promise<TargetsResponse>;
|
|
@@ -363,9 +454,7 @@ declare class ControlClient {
|
|
|
363
454
|
* with exponential backoff and re-issues every active REQ on reconnect.
|
|
364
455
|
*
|
|
365
456
|
* The WebSocket is injectable (`wsFactory`) so unit tests can drive the wire
|
|
366
|
-
* protocol without a real relay; the default factory uses the `ws` package
|
|
367
|
-
* when a `socks5h://` proxy is configured, routes through it so `.anyone`
|
|
368
|
-
* hidden-service relays are reachable.
|
|
457
|
+
* protocol without a real relay; the default factory uses the `ws` package.
|
|
369
458
|
*/
|
|
370
459
|
|
|
371
460
|
/** Minimal WebSocket surface this module depends on (subset of `ws`). */
|
|
@@ -378,10 +467,8 @@ interface MinimalWebSocket {
|
|
|
378
467
|
}
|
|
379
468
|
type WebSocketFactory = (url: string) => MinimalWebSocket;
|
|
380
469
|
interface RelaySubscriptionOptions {
|
|
381
|
-
/** Town relay WS URL, e.g. `
|
|
470
|
+
/** Town relay WS URL, e.g. `ws://localhost:7100`. */
|
|
382
471
|
relayUrl: string;
|
|
383
|
-
/** Optional `socks5h://host:port` proxy for `.anyone` relays. */
|
|
384
|
-
socksProxy?: string;
|
|
385
472
|
/** Max events retained in the ring buffer (oldest evicted). Default 5000. */
|
|
386
473
|
bufferSize?: number;
|
|
387
474
|
/** Base reconnect delay, ms. Default 1000. */
|
|
@@ -416,7 +503,6 @@ interface DrainResult {
|
|
|
416
503
|
}
|
|
417
504
|
declare class RelaySubscription {
|
|
418
505
|
private readonly relayUrl;
|
|
419
|
-
private readonly socksProxy?;
|
|
420
506
|
private readonly bufferSize;
|
|
421
507
|
private readonly reconnectBaseMs;
|
|
422
508
|
private readonly reconnectMaxMs;
|
|
@@ -527,12 +613,19 @@ interface DaemonConfigFile {
|
|
|
527
613
|
_help?: Record<string, string>;
|
|
528
614
|
/** BTP WebSocket URL of the apex/connector. */
|
|
529
615
|
btpUrl?: string;
|
|
530
|
-
/**
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
616
|
+
/**
|
|
617
|
+
* Connector-PROXY base URL (devnet payment-proxy, e.g.
|
|
618
|
+
* `https://proxy.devnet.toonprotocol.dev`). When set, the daemon routes paid
|
|
619
|
+
* writes through the proxy's `POST /ilp` (ILP-over-HTTP) WITHOUT a BTP socket;
|
|
620
|
+
* `btpUrl` then becomes optional. Env override: `TOON_CLIENT_PROXY_URL`.
|
|
621
|
+
*/
|
|
622
|
+
proxyUrl?: string;
|
|
623
|
+
/**
|
|
624
|
+
* Devnet faucet base URL (e.g. `https://faucet.devnet.toonprotocol.dev`),
|
|
625
|
+
* carried through to the ToonClient config for tooling/e2e funding. Env
|
|
626
|
+
* override: `TOON_CLIENT_FAUCET_URL`.
|
|
627
|
+
*/
|
|
628
|
+
faucetUrl?: string;
|
|
536
629
|
/** Town relay WS URL for FREE reads. */
|
|
537
630
|
relayUrl?: string;
|
|
538
631
|
/** Default ILP publish destination. Default `g.townhouse.town`. */
|
|
@@ -580,16 +673,17 @@ interface DaemonConfigFile {
|
|
|
580
673
|
interface ResolvedDaemonConfig {
|
|
581
674
|
httpPort: number;
|
|
582
675
|
relayUrl: string;
|
|
583
|
-
socksProxy?: string;
|
|
584
676
|
/**
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
588
|
-
*
|
|
677
|
+
* Whether a write uplink (proxy or BTP) is configured. FREE reads work
|
|
678
|
+
* without one; a write attempt with `hasUplink === false` is rejected at the
|
|
679
|
+
* control plane with a clear "configure an uplink" error (issue #69). Reads
|
|
680
|
+
* (`subscribe`/`query`/`getEvents`) never consult this.
|
|
589
681
|
*/
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
|
|
682
|
+
hasUplink: boolean;
|
|
683
|
+
/** Connector-proxy base URL (devnet payment-proxy), when configured. */
|
|
684
|
+
proxyUrl?: string;
|
|
685
|
+
/** Devnet faucet base URL, when configured. */
|
|
686
|
+
faucetUrl?: string;
|
|
593
687
|
destination: string;
|
|
594
688
|
feePerEvent: bigint;
|
|
595
689
|
apex?: ApexNegotiationConfig;
|
|
@@ -622,8 +716,9 @@ declare function resolveMnemonic(file: DaemonConfigFile): string;
|
|
|
622
716
|
/**
|
|
623
717
|
* Build the full resolved daemon config (file overlaid with env, mnemonic
|
|
624
718
|
* resolved, ToonClientConfig assembled). Env overrides supported:
|
|
625
|
-
* TOON_CLIENT_BTP_URL,
|
|
626
|
-
* TOON_CLIENT_HTTP_PORT, TOON_CLIENT_NETWORK
|
|
719
|
+
* TOON_CLIENT_BTP_URL, TOON_CLIENT_PROXY_URL, TOON_CLIENT_FAUCET_URL,
|
|
720
|
+
* TOON_CLIENT_RELAY_URL, TOON_CLIENT_HTTP_PORT, TOON_CLIENT_NETWORK,
|
|
721
|
+
* TOON_CLIENT_DESTINATION.
|
|
627
722
|
*/
|
|
628
723
|
declare function resolveConfig(file: DaemonConfigFile): ResolvedDaemonConfig;
|
|
629
724
|
|
|
@@ -643,8 +738,8 @@ declare function resolveConfig(file: DaemonConfigFile): ResolvedDaemonConfig;
|
|
|
643
738
|
* relay + apex are the permanent DEFAULT targets and cannot be removed.
|
|
644
739
|
*
|
|
645
740
|
* Each apex bootstraps asynchronously and non-blocking: the connection comes up
|
|
646
|
-
* in the background
|
|
647
|
-
*
|
|
741
|
+
* in the background. Until ready, writes against it report `bootstrapping` so
|
|
742
|
+
* tools surface "retry".
|
|
648
743
|
*/
|
|
649
744
|
|
|
650
745
|
/** The subset of `ToonClient` the runner depends on. */
|
|
@@ -674,6 +769,28 @@ interface ToonClientLike {
|
|
|
674
769
|
error?: string;
|
|
675
770
|
}>;
|
|
676
771
|
signBalanceProof(channelId: string, amount: bigint): Promise<unknown>;
|
|
772
|
+
/**
|
|
773
|
+
* Sign an unsigned event template with the daemon-held Nostr key (the key
|
|
774
|
+
* never leaves the daemon). Backs the `publish-unsigned` / `upload-media`
|
|
775
|
+
* paths so a UI/agent supplies only the event shell.
|
|
776
|
+
*/
|
|
777
|
+
signEvent(template: EventTemplate): NostrEvent | Promise<NostrEvent>;
|
|
778
|
+
/**
|
|
779
|
+
* Upload bytes to Arweave via the kind:5094 blob-storage DVM (single-packet),
|
|
780
|
+
* returning the Arweave tx id. Reuses the client's claim/channel plumbing.
|
|
781
|
+
*/
|
|
782
|
+
uploadBlob(params: {
|
|
783
|
+
blobData: Uint8Array;
|
|
784
|
+
contentType?: string;
|
|
785
|
+
bid?: string;
|
|
786
|
+
destination?: string;
|
|
787
|
+
ilpAmount?: bigint;
|
|
788
|
+
}): Promise<{
|
|
789
|
+
success: boolean;
|
|
790
|
+
txId?: string;
|
|
791
|
+
eventId?: string;
|
|
792
|
+
error?: string;
|
|
793
|
+
}>;
|
|
677
794
|
openChannel(destination?: string): Promise<string>;
|
|
678
795
|
getTrackedChannels(): string[];
|
|
679
796
|
getChannelNonce(channelId: string): number;
|
|
@@ -689,22 +806,25 @@ interface ToonClientLike {
|
|
|
689
806
|
code?: string;
|
|
690
807
|
message?: string;
|
|
691
808
|
}>;
|
|
809
|
+
/**
|
|
810
|
+
* Payment-aware HTTP fetch: issue the request and, on a `402 Payment
|
|
811
|
+
* Required`, transparently pay over TOON and retry, returning the settled Web
|
|
812
|
+
* `Response`. Pinned to the `ToonClient.h402Fetch` shape (issue #50).
|
|
813
|
+
*/
|
|
814
|
+
h402Fetch(url: string, opts?: {
|
|
815
|
+
method?: string;
|
|
816
|
+
headers?: Record<string, string>;
|
|
817
|
+
body?: string | Uint8Array;
|
|
818
|
+
timeout?: number;
|
|
819
|
+
destination?: string;
|
|
820
|
+
}): Promise<Response>;
|
|
692
821
|
}
|
|
693
822
|
/** A started managed proxy: just the teardown handle the runner needs. */
|
|
694
|
-
interface ManagedProxyHandle {
|
|
695
|
-
stop(): Promise<void>;
|
|
696
|
-
}
|
|
697
|
-
/** Starts a managed `anon` read proxy on a loopback SOCKS port. */
|
|
698
|
-
type StartReadProxy = (opts: {
|
|
699
|
-
socksPort: number;
|
|
700
|
-
log?: (msg: string) => void;
|
|
701
|
-
}) => Promise<ManagedProxyHandle>;
|
|
702
823
|
/** Builds a `ToonClient` (or a fake) for a given resolved client config. */
|
|
703
824
|
type CreateClient = (config: ToonClientConfig) => ToonClientLike;
|
|
704
|
-
/** Builds a `RelaySubscription` for a given relay URL
|
|
825
|
+
/** Builds a `RelaySubscription` for a given relay URL. */
|
|
705
826
|
type CreateRelay = (opts: {
|
|
706
827
|
relayUrl: string;
|
|
707
|
-
socksProxy?: string;
|
|
708
828
|
onEvent: (subId: string, event: NostrEvent) => void;
|
|
709
829
|
logger?: (msg: string) => void;
|
|
710
830
|
}) => RelaySubscription;
|
|
@@ -714,11 +834,6 @@ interface ClientRunnerDeps {
|
|
|
714
834
|
createClient: CreateClient;
|
|
715
835
|
/** Factory producing a relay subscription (defaults to the real one). */
|
|
716
836
|
createRelay?: CreateRelay;
|
|
717
|
-
/**
|
|
718
|
-
* Starts the daemon-managed read proxy (defaults to the real
|
|
719
|
-
* `startManagedAnonProxy`). Injected so tests avoid the anon download/spawn.
|
|
720
|
-
*/
|
|
721
|
-
startReadProxy?: StartReadProxy;
|
|
722
837
|
logger?: (msg: string) => void;
|
|
723
838
|
/** Path to the dynamic-targets store (tests override). */
|
|
724
839
|
targetsPath?: string;
|
|
@@ -727,7 +842,6 @@ declare class ClientRunner {
|
|
|
727
842
|
private readonly config;
|
|
728
843
|
private readonly createClient;
|
|
729
844
|
private readonly createRelay;
|
|
730
|
-
private readonly startReadProxy;
|
|
731
845
|
private readonly log;
|
|
732
846
|
private readonly targetsPath?;
|
|
733
847
|
private readonly startedAt;
|
|
@@ -747,9 +861,6 @@ declare class ClientRunner {
|
|
|
747
861
|
private subIdCounter;
|
|
748
862
|
private readonly defaultBtpUrl;
|
|
749
863
|
private readonly defaultRelayUrl;
|
|
750
|
-
/** Teardown for the daemon-managed read proxy (btp-direct + relay-`.anyone`). */
|
|
751
|
-
private stopReadProxy;
|
|
752
|
-
private readProxyError;
|
|
753
864
|
private stopped;
|
|
754
865
|
private started;
|
|
755
866
|
constructor(deps: ClientRunnerDeps);
|
|
@@ -768,8 +879,7 @@ declare class ClientRunner {
|
|
|
768
879
|
*/
|
|
769
880
|
private registerRelay;
|
|
770
881
|
/**
|
|
771
|
-
* Add a relay read target at runtime.
|
|
772
|
-
* proxy (started here if needed). Persisted unless `persist` is false.
|
|
882
|
+
* Add a relay read target at runtime. Persisted unless `persist` is false.
|
|
773
883
|
*/
|
|
774
884
|
addRelay(relayUrl: string, persist?: boolean): Promise<void>;
|
|
775
885
|
/** Remove a relay read target. The config-seeded default cannot be removed. */
|
|
@@ -781,6 +891,16 @@ declare class ClientRunner {
|
|
|
781
891
|
* every relay (and onto relays added later); with one it targets that relay.
|
|
782
892
|
*/
|
|
783
893
|
subscribe(req: SubscribeRequest): SubscribeResponse;
|
|
894
|
+
/**
|
|
895
|
+
* One-shot free read: subscribe the given filter(s) across all relays, wait a
|
|
896
|
+
* bounded window for the relay(s) to deliver, then return every buffered event
|
|
897
|
+
* matching the filter (matched by content, not subId — so events already
|
|
898
|
+
* buffered by other subscriptions are included despite the global dedup).
|
|
899
|
+
*
|
|
900
|
+
* Backs the apps `toon_query` tool the generative-UI runtime calls to resolve
|
|
901
|
+
* a ViewSpec node's data bind.
|
|
902
|
+
*/
|
|
903
|
+
query(filters: NostrFilter | NostrFilter[], timeoutMs?: number): Promise<NostrEvent[]>;
|
|
784
904
|
/** Drain merged events newer than the cursor (free read), optionally scoped. */
|
|
785
905
|
getEvents(query: EventsQuery): EventsResponse;
|
|
786
906
|
private makeApex;
|
|
@@ -804,10 +924,27 @@ declare class ClientRunner {
|
|
|
804
924
|
private deriveApexClientConfig;
|
|
805
925
|
private apexChannelStorePathFor;
|
|
806
926
|
private replayPersistedTargets;
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
927
|
+
/**
|
|
928
|
+
* Open the apex channel — or, on a restart, RESUME the existing one.
|
|
929
|
+
*
|
|
930
|
+
* With `resumeOnly`, only a persisted channel is resumed (no on-chain open);
|
|
931
|
+
* returns undefined when none exists so the caller can defer the open to the
|
|
932
|
+
* first write (funded-after-start demo flow, #69).
|
|
933
|
+
*/
|
|
810
934
|
private openOrResumeApexChannel;
|
|
935
|
+
/**
|
|
936
|
+
* Persist a (lazily- or eagerly-) opened apex channel so a restart RESUMES it
|
|
937
|
+
* (tracked, no re-deposit) rather than opening a second on-chain channel.
|
|
938
|
+
* No-op when the apex carries no negotiation (nothing to key the store on).
|
|
939
|
+
*/
|
|
940
|
+
private persistApexChannel;
|
|
941
|
+
/**
|
|
942
|
+
* Discover the apex's settlement negotiation from its kind:10032 on the
|
|
943
|
+
* default relay and attach it to the apex (proxy-mode fallback when no config
|
|
944
|
+
* negotiation was supplied, #69). Throws ApexDiscoveryError on timeout/missing
|
|
945
|
+
* settlement params so the apex's `lastError` reports exactly what is missing.
|
|
946
|
+
*/
|
|
947
|
+
private discoverApexNegotiation;
|
|
811
948
|
/** Inject the apex settlement negotiation directly into its ToonClient. */
|
|
812
949
|
private injectApexNegotiation;
|
|
813
950
|
/** Route apex CHILD peers (dvm/mill) through the SAME apex payment channel. */
|
|
@@ -821,6 +958,26 @@ declare class ClientRunner {
|
|
|
821
958
|
getTargets(): TargetsResponse;
|
|
822
959
|
/** Pay-to-write a single event through the selected (or default) apex. */
|
|
823
960
|
publish(req: PublishRequest): Promise<PublishResponse>;
|
|
961
|
+
/**
|
|
962
|
+
* Build, sign (with the daemon-held key), and pay-to-write an event. The
|
|
963
|
+
* caller supplies only the event shell; the private key never leaves the
|
|
964
|
+
* daemon. Payloads are MODEL-AUTHORED → validated server-side here (the model
|
|
965
|
+
* is not a security boundary). Replaceable kinds (0/3) merge the latest known
|
|
966
|
+
* event's tags before signing.
|
|
967
|
+
*/
|
|
968
|
+
publishUnsigned(req: PublishUnsignedRequest): Promise<PublishResponse>;
|
|
969
|
+
/**
|
|
970
|
+
* Upload media to Arweave (kind:5094 blob DVM, single-packet) then sign+publish
|
|
971
|
+
* a media event referencing the resulting URL. One spendy operation, two steps,
|
|
972
|
+
* entirely server-side.
|
|
973
|
+
*/
|
|
974
|
+
uploadMedia(req: UploadMediaRequest): Promise<UploadMediaResponse>;
|
|
975
|
+
/** Validate + assemble a signable event template (with replaceable merge). */
|
|
976
|
+
private buildTemplate;
|
|
977
|
+
/** Latest self-authored event of `kind` currently in the merged read buffer. */
|
|
978
|
+
private latestSelfReplaceable;
|
|
979
|
+
/** Tags for a published media event referencing an Arweave URL. */
|
|
980
|
+
private buildMediaTags;
|
|
824
981
|
/** Open (or return) a payment channel on the selected (or default) apex. */
|
|
825
982
|
openChannel(destination?: string, btpUrl?: string): Promise<{
|
|
826
983
|
channelId: string;
|
|
@@ -829,7 +986,13 @@ declare class ClientRunner {
|
|
|
829
986
|
getChannels(): ChannelsResponse;
|
|
830
987
|
/** Swap source→target asset against a mill peer via the selected apex. */
|
|
831
988
|
swap(req: SwapRequest): Promise<SwapResponse>;
|
|
832
|
-
/**
|
|
989
|
+
/**
|
|
990
|
+
* Payment-aware HTTP fetch through an apex's client. The client issues the
|
|
991
|
+
* request and, on `402 Payment Required`, pays over TOON and retries; we
|
|
992
|
+
* translate the resulting Web `Response` into the wire envelope.
|
|
993
|
+
*/
|
|
994
|
+
httpFetchPaid(req: HttpFetchPaidRequest): Promise<HttpFetchPaidResponse>;
|
|
995
|
+
/** Graceful teardown: close every relay + stop every apex client. */
|
|
833
996
|
stop(): Promise<void>;
|
|
834
997
|
private selectApex;
|
|
835
998
|
private assertApexReady;
|
|
@@ -859,9 +1022,8 @@ declare class PublishRejectedError extends Error {
|
|
|
859
1022
|
* a default password so the identity survives restarts with no env var.
|
|
860
1023
|
* The mnemonic + derived addresses are printed ONCE for backup.
|
|
861
1024
|
* 2. **Transport scaffolding** — ensure `config.json` carries the transport
|
|
862
|
-
* knobs (`btpUrl`/`relayUrl
|
|
863
|
-
*
|
|
864
|
-
* point at.
|
|
1025
|
+
* knobs (`btpUrl`/`relayUrl`) plus a `_help` block documenting them, so the
|
|
1026
|
+
* user can see what to point at.
|
|
865
1027
|
*
|
|
866
1028
|
* This is all idempotent: on later runs an identity already exists, so nothing
|
|
867
1029
|
* is regenerated and the config is left untouched.
|
|
@@ -928,7 +1090,8 @@ declare function spawnDaemonDetached(opts?: SpawnDaemonOptions): number;
|
|
|
928
1090
|
/**
|
|
929
1091
|
* Poll the control plane until the daemon answers `GET /status`, up to
|
|
930
1092
|
* `timeoutMs`. Resolves true once reachable (NOT necessarily done
|
|
931
|
-
* bootstrapping —
|
|
1093
|
+
* bootstrapping — the BTP session can take a moment; callers surface
|
|
1094
|
+
* `bootstrapping`).
|
|
932
1095
|
*/
|
|
933
1096
|
declare function waitForReady(baseUrl: string, timeoutMs?: number, intervalMs?: number): Promise<boolean>;
|
|
934
1097
|
|
|
@@ -944,6 +1107,8 @@ interface ToolDefinition {
|
|
|
944
1107
|
name: string;
|
|
945
1108
|
description: string;
|
|
946
1109
|
inputSchema: Record<string, unknown>;
|
|
1110
|
+
/** MCP-apps metadata, e.g. `{ ui: { resourceUri } }` linking a UI resource. */
|
|
1111
|
+
_meta?: Record<string, unknown>;
|
|
947
1112
|
}
|
|
948
1113
|
/** MCP tool-call result shape (subset of the SDK's CallToolResult). */
|
|
949
1114
|
interface ToolResult {
|
|
@@ -951,6 +1116,8 @@ interface ToolResult {
|
|
|
951
1116
|
type: 'text';
|
|
952
1117
|
text: string;
|
|
953
1118
|
}[];
|
|
1119
|
+
/** Machine-readable payload the MCP-app iframe reads (events, ViewSpec, …). */
|
|
1120
|
+
structuredContent?: Record<string, unknown>;
|
|
954
1121
|
isError?: boolean;
|
|
955
1122
|
}
|
|
956
1123
|
declare const TOOL_DEFINITIONS: ToolDefinition[];
|
|
@@ -962,4 +1129,51 @@ declare const TOOL_DEFINITIONS: ToolDefinition[];
|
|
|
962
1129
|
*/
|
|
963
1130
|
declare function dispatchTool(client: ControlClient, name: string, args: Record<string, unknown>): Promise<ToolResult>;
|
|
964
1131
|
|
|
965
|
-
|
|
1132
|
+
/** Accumulated per-step results keyed by step id. */
|
|
1133
|
+
type JourneyState = Record<string, unknown>;
|
|
1134
|
+
/** One step in a journey: a tool call with a ViewSpec renderer. */
|
|
1135
|
+
interface JourneyStep {
|
|
1136
|
+
/** Unique identifier for this step within the plan. */
|
|
1137
|
+
id: string;
|
|
1138
|
+
/** MCP tool name to call (e.g. `toon_status`, `toon_publish_unsigned`). */
|
|
1139
|
+
toolName: string;
|
|
1140
|
+
/** Build the tool input from accumulated prior-step state. */
|
|
1141
|
+
buildInput: (state: JourneyState) => Record<string, unknown>;
|
|
1142
|
+
/** Render the step's result data as a ViewSpec panel. */
|
|
1143
|
+
renderPanel: (data: unknown, state: JourneyState) => ViewSpec;
|
|
1144
|
+
}
|
|
1145
|
+
/** Ordered sequence of steps with plan metadata. */
|
|
1146
|
+
interface JourneyPlan {
|
|
1147
|
+
id: string;
|
|
1148
|
+
title: string;
|
|
1149
|
+
steps: JourneyStep[];
|
|
1150
|
+
}
|
|
1151
|
+
/** Result for one executed step. */
|
|
1152
|
+
interface JourneyStepResult {
|
|
1153
|
+
stepId: string;
|
|
1154
|
+
/** Raw ToolResult from the tool call. */
|
|
1155
|
+
toolResult: ToolResult;
|
|
1156
|
+
/** ToolResult carrying the step's ViewSpec panel as structuredContent. */
|
|
1157
|
+
panel: ToolResult;
|
|
1158
|
+
}
|
|
1159
|
+
/** Final result of a runJourney call. */
|
|
1160
|
+
interface JourneyResult {
|
|
1161
|
+
/** True when all steps completed without error. */
|
|
1162
|
+
completed: boolean;
|
|
1163
|
+
/** Results for every step that ran (may be partial on error). */
|
|
1164
|
+
steps: JourneyStepResult[];
|
|
1165
|
+
/** Present when the run halted due to a tool error. */
|
|
1166
|
+
error?: {
|
|
1167
|
+
stepId: string;
|
|
1168
|
+
message: string;
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/**
|
|
1173
|
+
* Run all steps in the plan sequentially against the given ControlClient.
|
|
1174
|
+
* Each step's result is threaded forward into the next step's buildInput via
|
|
1175
|
+
* JourneyState. Halts on the first tool error and returns a partial result.
|
|
1176
|
+
*/
|
|
1177
|
+
declare function runJourney(plan: JourneyPlan, client: ControlClient): Promise<JourneyResult>;
|
|
1178
|
+
|
|
1179
|
+
export { type AddApexRequest, type AddApexResponse, type AddRelayRequest, type ApexNegotiationConfig, type ApexTargetStatus, type ChainStatus, type ChannelInfo, type ChannelsResponse, ClientRunner, type ClientRunnerDeps, ControlApiError, ControlClient, type ControlClientOptions, DEFAULT_KEYSTORE_PASSWORD, type DaemonConfigFile, DaemonUnreachableError, type DrainResult, type ErrorResponse, type EventsQuery, type EventsResponse, type HttpFetchPaidRequest, type HttpFetchPaidResponse, type JourneyPlan, type JourneyResult, type JourneyState, type JourneyStep, type JourneyStepResult, type MinimalWebSocket, type NostrFilter, NotReadyError, type OpenChannelRequest, PublishRejectedError, type PublishRequest, type PublishResponse, type PublishUnsignedRequest, type QueryRequest, type QueryResponse, RelaySubscription, type RelaySubscriptionOptions, type RelayTargetStatus, type RemoveApexRequest, type RemoveRelayRequest, type ResolvedDaemonConfig, type SettlementChain, type StatusResponse, type SubscribeRequest, type SubscribeResponse, type SwapClaim, type SwapRequest, type SwapResponse, TOOL_DEFINITIONS, type TargetsResponse, type ToolDefinition, type ToolResult, type ToonClientLike, type UploadMediaRequest, type UploadMediaResponse, type WebSocketFactory, acquireLock, configDir, defaultConfigPath, defaultKeystorePath, dispatchTool, hasConfiguredIdentity, isDaemonRunning, isProcessAlive, readConfigFile, readPid, registerRoutes, releaseLock, resolveConfig, resolveMnemonic, runJourney, scaffoldFirstRun, spawnDaemonDetached, waitForReady };
|