@toon-protocol/client-mcp 0.2.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 +18 -37
- package/dist/app/index.html +31 -31
- package/dist/{chunk-NP35YO5O.js → chunk-CQ2QIZ6Z.js} +162 -211
- package/dist/chunk-CQ2QIZ6Z.js.map +1 -0
- package/dist/{chunk-L6F2B3GX.js → chunk-QFHCXJ2V.js} +96 -99
- package/dist/chunk-QFHCXJ2V.js.map +1 -0
- package/dist/{chunk-KNQ2DKNN.js → chunk-XV52IHVR.js} +123 -7
- package/dist/chunk-XV52IHVR.js.map +1 -0
- package/dist/daemon.js +2 -3
- 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/index.d.ts +61 -67
- package/dist/index.js +344 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +2 -3
- package/dist/mcp.js.map +1 -1
- package/package.json +9 -6
- package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js +0 -25
- package/dist/anon-proxy-W3KMM7GU-FN7ZJY7P.js.map +0 -1
- package/dist/chunk-KNQ2DKNN.js.map +0 -1
- package/dist/chunk-L6F2B3GX.js.map +0 -1
- package/dist/chunk-NP35YO5O.js.map +0 -1
- package/dist/chunk-SKQTKZIH.js +0 -278
- package/dist/chunk-SKQTKZIH.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
|
@@ -13,10 +13,7 @@ import {
|
|
|
13
13
|
isEventExpired,
|
|
14
14
|
parseIlpPeerInfo,
|
|
15
15
|
readConfigFile
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import {
|
|
18
|
-
startManagedAnonProxy
|
|
19
|
-
} from "./chunk-SKQTKZIH.js";
|
|
16
|
+
} from "./chunk-CQ2QIZ6Z.js";
|
|
20
17
|
import {
|
|
21
18
|
__require
|
|
22
19
|
} from "./chunk-F22GNSF6.js";
|
|
@@ -33,10 +30,12 @@ function hasConfiguredIdentity(file) {
|
|
|
33
30
|
);
|
|
34
31
|
}
|
|
35
32
|
var CONFIG_HELP = {
|
|
36
|
-
transport: "
|
|
37
|
-
|
|
33
|
+
transport: "Configure ONE uplink for paid writes: either `proxyUrl` (connector payment-proxy over ILP-over-HTTP, e.g. https://proxy.devnet.toonprotocol.dev) OR `btpUrl` (BTP WebSocket, e.g. ws://<host>:3000/btp). Reads are always free over relayUrl.",
|
|
34
|
+
proxyUrl: "Connector-proxy base URL (deployed devnet/testnet edge). When set, paid writes route through `POST /ilp` and no BTP socket is needed. Set `destination` to the apex ILP address (e.g. g.proxy for devnet).",
|
|
35
|
+
faucetUrl: "Devnet faucet base URL (e.g. https://faucet.devnet.toonprotocol.dev) used to drip test funds before publishing.",
|
|
36
|
+
btpUrl: "BTP WebSocket URL of the apex/connector for paid writes. Optional when `proxyUrl` is set.",
|
|
38
37
|
relayUrl: "Town relay WebSocket URL for FREE reads. Default ws://localhost:7100.",
|
|
39
|
-
|
|
38
|
+
destination: "Default ILP publish destination (apex address). Default g.townhouse.town; set to g.proxy for the deployed devnet proxy.",
|
|
40
39
|
keystorePath: "Auto-generated encrypted identity. Do not hand-edit; back up your seed phrase."
|
|
41
40
|
};
|
|
42
41
|
async function scaffoldFirstRun(opts = {}) {
|
|
@@ -75,13 +74,14 @@ async function scaffoldFirstRun(opts = {}) {
|
|
|
75
74
|
if (!existsSync(configPath)) {
|
|
76
75
|
updated = {
|
|
77
76
|
_help: CONFIG_HELP,
|
|
77
|
+
proxyUrl: "",
|
|
78
78
|
btpUrl: "",
|
|
79
79
|
relayUrl: "ws://localhost:7100",
|
|
80
80
|
...updated
|
|
81
81
|
};
|
|
82
82
|
changed = true;
|
|
83
83
|
log(
|
|
84
|
-
`[toon-clientd] wrote starter config at ${configPath} \u2014 set "btpUrl" to your apex before publishing.`
|
|
84
|
+
`[toon-clientd] wrote starter config at ${configPath} \u2014 set "proxyUrl" (connector proxy, ILP-over-HTTP) or "btpUrl" (BTP) to your apex before publishing.`
|
|
85
85
|
);
|
|
86
86
|
}
|
|
87
87
|
if (changed) writeConfigFile(configPath, updated);
|
|
@@ -124,7 +124,6 @@ var DEFAULT_MAX_MS = 3e4;
|
|
|
124
124
|
var noop = () => void 0;
|
|
125
125
|
var RelaySubscription = class {
|
|
126
126
|
relayUrl;
|
|
127
|
-
socksProxy;
|
|
128
127
|
bufferSize;
|
|
129
128
|
reconnectBaseMs;
|
|
130
129
|
reconnectMaxMs;
|
|
@@ -147,12 +146,11 @@ var RelaySubscription = class {
|
|
|
147
146
|
reconnectTimer = null;
|
|
148
147
|
constructor(opts) {
|
|
149
148
|
this.relayUrl = opts.relayUrl;
|
|
150
|
-
this.socksProxy = opts.socksProxy;
|
|
151
149
|
this.bufferSize = opts.bufferSize ?? DEFAULT_BUFFER;
|
|
152
150
|
this.reconnectBaseMs = opts.reconnectBaseMs ?? DEFAULT_BASE_MS;
|
|
153
151
|
this.reconnectMaxMs = opts.reconnectMaxMs ?? DEFAULT_MAX_MS;
|
|
154
152
|
this.log = opts.logger ?? noop;
|
|
155
|
-
this.wsFactory = opts.wsFactory ?? defaultWebSocketFactory(
|
|
153
|
+
this.wsFactory = opts.wsFactory ?? defaultWebSocketFactory();
|
|
156
154
|
this.decodeEvent = opts.decodeEvent;
|
|
157
155
|
this.onEvent = opts.onEvent;
|
|
158
156
|
}
|
|
@@ -347,15 +345,10 @@ function toText(data) {
|
|
|
347
345
|
function errMsg(err) {
|
|
348
346
|
return err instanceof Error ? err.message : String(err);
|
|
349
347
|
}
|
|
350
|
-
function defaultWebSocketFactory(
|
|
348
|
+
function defaultWebSocketFactory() {
|
|
351
349
|
return (url) => {
|
|
352
350
|
const WebSocketImpl = nodeRequire("ws");
|
|
353
|
-
|
|
354
|
-
if (socksProxy) {
|
|
355
|
-
const { SocksProxyAgent } = nodeRequire("socks-proxy-agent");
|
|
356
|
-
agent = new SocksProxyAgent(socksProxy);
|
|
357
|
-
}
|
|
358
|
-
return new WebSocketImpl(url, agent ? { agent } : void 0);
|
|
351
|
+
return new WebSocketImpl(url);
|
|
359
352
|
};
|
|
360
353
|
}
|
|
361
354
|
|
|
@@ -1404,7 +1397,6 @@ var ClientRunner = class {
|
|
|
1404
1397
|
config;
|
|
1405
1398
|
createClient;
|
|
1406
1399
|
createRelay;
|
|
1407
|
-
startReadProxy;
|
|
1408
1400
|
log;
|
|
1409
1401
|
targetsPath;
|
|
1410
1402
|
startedAt = Date.now();
|
|
@@ -1424,9 +1416,6 @@ var ClientRunner = class {
|
|
|
1424
1416
|
subIdCounter = 0;
|
|
1425
1417
|
defaultBtpUrl;
|
|
1426
1418
|
defaultRelayUrl;
|
|
1427
|
-
/** Teardown for the daemon-managed read proxy (btp-direct + relay-`.anyone`). */
|
|
1428
|
-
stopReadProxy;
|
|
1429
|
-
readProxyError;
|
|
1430
1419
|
stopped = false;
|
|
1431
1420
|
started = false;
|
|
1432
1421
|
constructor(deps) {
|
|
@@ -1438,17 +1427,12 @@ var ClientRunner = class {
|
|
|
1438
1427
|
this.defaultRelayUrl = deps.config.relayUrl;
|
|
1439
1428
|
this.createRelay = deps.createRelay ?? ((opts) => new RelaySubscription({
|
|
1440
1429
|
relayUrl: opts.relayUrl,
|
|
1441
|
-
...opts.socksProxy ? { socksProxy: opts.socksProxy } : {},
|
|
1442
1430
|
...opts.logger ? { logger: opts.logger } : {},
|
|
1443
1431
|
onEvent: opts.onEvent,
|
|
1444
1432
|
// The TOON relay sends events TOON-encoded (text) on reads, not JSON.
|
|
1445
1433
|
decodeEvent: (raw) => decodeEventFromToon(new TextEncoder().encode(raw))
|
|
1446
1434
|
}));
|
|
1447
|
-
this.
|
|
1448
|
-
socksPort: opts.socksPort,
|
|
1449
|
-
...opts.log ? { log: opts.log } : {}
|
|
1450
|
-
}));
|
|
1451
|
-
this.registerRelay(this.defaultRelayUrl, this.config.socksProxy);
|
|
1435
|
+
this.registerRelay(this.defaultRelayUrl);
|
|
1452
1436
|
const defaultApex = this.makeApex({
|
|
1453
1437
|
btpUrl: this.defaultBtpUrl,
|
|
1454
1438
|
client: this.createClient(this.config.toonClientConfig),
|
|
@@ -1470,13 +1454,13 @@ var ClientRunner = class {
|
|
|
1470
1454
|
start() {
|
|
1471
1455
|
if (this.started) return;
|
|
1472
1456
|
this.started = true;
|
|
1473
|
-
if (this.config.manageReadProxy) void this.bringUpReadProxy();
|
|
1474
1457
|
for (const relay of this.relays.values()) relay.start();
|
|
1475
1458
|
void this.bootstrap();
|
|
1476
1459
|
this.replayPersistedTargets();
|
|
1477
1460
|
}
|
|
1478
1461
|
/** Await the default apex's bootstrap (kicking it off if not already running). */
|
|
1479
1462
|
bootstrap() {
|
|
1463
|
+
if (!this.config.hasUplink) return Promise.resolve();
|
|
1480
1464
|
const apex = this.apexes.get(this.defaultBtpUrl);
|
|
1481
1465
|
if (!apex) return Promise.resolve();
|
|
1482
1466
|
return this.bootstrapApex(apex);
|
|
@@ -1487,12 +1471,11 @@ var ClientRunner = class {
|
|
|
1487
1471
|
* merged buffer and replaying active fan-out subscriptions. Does NOT start the
|
|
1488
1472
|
* socket — callers start it (so construction stays side-effect-free for tests).
|
|
1489
1473
|
*/
|
|
1490
|
-
registerRelay(relayUrl
|
|
1474
|
+
registerRelay(relayUrl) {
|
|
1491
1475
|
const existing = this.relays.get(relayUrl);
|
|
1492
1476
|
if (existing) return existing;
|
|
1493
1477
|
const relay = this.createRelay({
|
|
1494
1478
|
relayUrl,
|
|
1495
|
-
...socksProxy ? { socksProxy } : {},
|
|
1496
1479
|
logger: this.log,
|
|
1497
1480
|
onEvent: (subId, event) => this.pushMerged(relayUrl, subId, event)
|
|
1498
1481
|
});
|
|
@@ -1502,17 +1485,11 @@ var ClientRunner = class {
|
|
|
1502
1485
|
return relay;
|
|
1503
1486
|
}
|
|
1504
1487
|
/**
|
|
1505
|
-
* Add a relay read target at runtime.
|
|
1506
|
-
* proxy (started here if needed). Persisted unless `persist` is false.
|
|
1488
|
+
* Add a relay read target at runtime. Persisted unless `persist` is false.
|
|
1507
1489
|
*/
|
|
1508
1490
|
async addRelay(relayUrl, persist = true) {
|
|
1509
1491
|
if (this.relays.has(relayUrl)) return;
|
|
1510
|
-
|
|
1511
|
-
if (isAnyoneHost(relayUrl) && !socksProxy) {
|
|
1512
|
-
await this.ensureReadProxy();
|
|
1513
|
-
socksProxy = `socks5h://127.0.0.1:${this.config.readProxySocksPort ?? 9050}`;
|
|
1514
|
-
}
|
|
1515
|
-
const relay = this.registerRelay(relayUrl, socksProxy);
|
|
1492
|
+
const relay = this.registerRelay(relayUrl);
|
|
1516
1493
|
relay.start();
|
|
1517
1494
|
if (persist) saveRelayTarget(relayUrl, this.targetsPath);
|
|
1518
1495
|
}
|
|
@@ -1616,14 +1593,20 @@ var ClientRunner = class {
|
|
|
1616
1593
|
async doBootstrapApex(apex) {
|
|
1617
1594
|
apex.bootstrapping = true;
|
|
1618
1595
|
try {
|
|
1596
|
+
if (!apex.negotiation && this.config.proxyUrl) {
|
|
1597
|
+
await this.discoverApexNegotiation(apex);
|
|
1598
|
+
}
|
|
1619
1599
|
await apex.client.start();
|
|
1620
1600
|
this.injectApexNegotiation(apex);
|
|
1621
|
-
|
|
1601
|
+
const deferOpen = Boolean(this.config.proxyUrl);
|
|
1602
|
+
apex.apexChannelId = await this.openOrResumeApexChannel(apex, {
|
|
1603
|
+
resumeOnly: deferOpen
|
|
1604
|
+
});
|
|
1622
1605
|
this.routeChildPeersThroughApexChannel(apex);
|
|
1623
1606
|
apex.ready = true;
|
|
1624
1607
|
apex.lastError = void 0;
|
|
1625
1608
|
this.log(
|
|
1626
|
-
`[runner] apex ${apex.btpUrl} ready; channel ${apex.apexChannelId}`
|
|
1609
|
+
`[runner] apex ${apex.btpUrl || apex.destination} ready; channel ${apex.apexChannelId ?? "(deferred \u2014 open on first write)"}`
|
|
1627
1610
|
);
|
|
1628
1611
|
} catch (err) {
|
|
1629
1612
|
apex.lastError = err instanceof Error ? err.message : String(err);
|
|
@@ -1752,37 +1735,15 @@ var ClientRunner = class {
|
|
|
1752
1735
|
);
|
|
1753
1736
|
}
|
|
1754
1737
|
}
|
|
1755
|
-
// ── Shared read proxy ──────────────────────────────────────────────────────
|
|
1756
|
-
async ensureReadProxy() {
|
|
1757
|
-
if (this.stopReadProxy) return;
|
|
1758
|
-
await this.bringUpReadProxy();
|
|
1759
|
-
}
|
|
1760
|
-
async bringUpReadProxy() {
|
|
1761
|
-
if (this.stopReadProxy) return;
|
|
1762
|
-
const socksPort = this.config.readProxySocksPort ?? 9050;
|
|
1763
|
-
try {
|
|
1764
|
-
this.log(
|
|
1765
|
-
`[runner] starting managed read proxy on 127.0.0.1:${socksPort}`
|
|
1766
|
-
);
|
|
1767
|
-
const proxy = await this.startReadProxy({
|
|
1768
|
-
socksPort,
|
|
1769
|
-
log: (m) => this.log(`[anon] ${m}`)
|
|
1770
|
-
});
|
|
1771
|
-
if (this.stopped) {
|
|
1772
|
-
await proxy.stop();
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
this.stopReadProxy = () => proxy.stop();
|
|
1776
|
-
this.readProxyError = void 0;
|
|
1777
|
-
this.log("[runner] managed read proxy ready");
|
|
1778
|
-
} catch (err) {
|
|
1779
|
-
this.readProxyError = err instanceof Error ? err.message : String(err);
|
|
1780
|
-
this.log(`[runner] managed read proxy failed: ${this.readProxyError}`);
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
1738
|
// ── Channel / negotiation helpers (per-apex) ───────────────────────────────
|
|
1784
|
-
/**
|
|
1785
|
-
|
|
1739
|
+
/**
|
|
1740
|
+
* Open the apex channel — or, on a restart, RESUME the existing one.
|
|
1741
|
+
*
|
|
1742
|
+
* With `resumeOnly`, only a persisted channel is resumed (no on-chain open);
|
|
1743
|
+
* returns undefined when none exists so the caller can defer the open to the
|
|
1744
|
+
* first write (funded-after-start demo flow, #69).
|
|
1745
|
+
*/
|
|
1746
|
+
async openOrResumeApexChannel(apex, opts = {}) {
|
|
1786
1747
|
const { destination, chain } = apex;
|
|
1787
1748
|
const { apexChannelStorePath } = this.config;
|
|
1788
1749
|
const saved = loadApexChannel(apexChannelStorePath, destination, chain);
|
|
@@ -1794,10 +1755,24 @@ var ClientRunner = class {
|
|
|
1794
1755
|
);
|
|
1795
1756
|
return saved.channelId;
|
|
1796
1757
|
}
|
|
1758
|
+
if (opts.resumeOnly) return void 0;
|
|
1797
1759
|
const channelId = await apex.client.openChannel(destination);
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1760
|
+
this.persistApexChannel(apex, channelId);
|
|
1761
|
+
return channelId;
|
|
1762
|
+
}
|
|
1763
|
+
/**
|
|
1764
|
+
* Persist a (lazily- or eagerly-) opened apex channel so a restart RESUMES it
|
|
1765
|
+
* (tracked, no re-deposit) rather than opening a second on-chain channel.
|
|
1766
|
+
* No-op when the apex carries no negotiation (nothing to key the store on).
|
|
1767
|
+
*/
|
|
1768
|
+
persistApexChannel(apex, channelId) {
|
|
1769
|
+
const a = apex.negotiation;
|
|
1770
|
+
if (!a) return;
|
|
1771
|
+
saveApexChannel(
|
|
1772
|
+
this.config.apexChannelStorePath,
|
|
1773
|
+
apex.destination,
|
|
1774
|
+
apex.chain,
|
|
1775
|
+
{
|
|
1801
1776
|
channelId,
|
|
1802
1777
|
context: {
|
|
1803
1778
|
chainType: a.chain,
|
|
@@ -1806,9 +1781,34 @@ var ClientRunner = class {
|
|
|
1806
1781
|
...a.tokenAddress ? { tokenAddress: a.tokenAddress } : {},
|
|
1807
1782
|
recipient: a.settlementAddress
|
|
1808
1783
|
}
|
|
1809
|
-
}
|
|
1784
|
+
}
|
|
1785
|
+
);
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* Discover the apex's settlement negotiation from its kind:10032 on the
|
|
1789
|
+
* default relay and attach it to the apex (proxy-mode fallback when no config
|
|
1790
|
+
* negotiation was supplied, #69). Throws ApexDiscoveryError on timeout/missing
|
|
1791
|
+
* settlement params so the apex's `lastError` reports exactly what is missing.
|
|
1792
|
+
*/
|
|
1793
|
+
async discoverApexNegotiation(apex) {
|
|
1794
|
+
const relay = this.relays.get(this.defaultRelayUrl);
|
|
1795
|
+
if (!relay) {
|
|
1796
|
+
throw new TargetError(
|
|
1797
|
+
`Cannot discover apex "${apex.destination}": default relay ${this.defaultRelayUrl} is not registered.`
|
|
1798
|
+
);
|
|
1810
1799
|
}
|
|
1811
|
-
|
|
1800
|
+
relay.start();
|
|
1801
|
+
const discovered = await discoverApex({
|
|
1802
|
+
relay,
|
|
1803
|
+
ilpAddress: apex.destination,
|
|
1804
|
+
chain: apex.chain,
|
|
1805
|
+
...apex.childPeers.length > 0 ? { childPeers: apex.childPeers } : {}
|
|
1806
|
+
});
|
|
1807
|
+
apex.negotiation = discovered.negotiation;
|
|
1808
|
+
if (discovered.apexChildPeers) apex.childPeers = discovered.apexChildPeers;
|
|
1809
|
+
this.log(
|
|
1810
|
+
`[runner] discovered apex negotiation for "${apex.destination}" (chain ${discovered.negotiation.chainKey}, settle ${discovered.negotiation.settlementAddress})`
|
|
1811
|
+
);
|
|
1812
1812
|
}
|
|
1813
1813
|
/** Inject the apex settlement negotiation directly into its ToonClient. */
|
|
1814
1814
|
injectApexNegotiation(apex) {
|
|
@@ -1892,16 +1892,14 @@ var ClientRunner = class {
|
|
|
1892
1892
|
minaAddress: safe(() => client?.getMinaAddress())
|
|
1893
1893
|
},
|
|
1894
1894
|
transport: {
|
|
1895
|
-
type:
|
|
1896
|
-
...this.config.socksProxy ? { socksProxy: this.config.socksProxy } : {},
|
|
1895
|
+
type: "direct",
|
|
1897
1896
|
...apex ? { btpUrl: apex.btpUrl } : {}
|
|
1898
1897
|
},
|
|
1899
1898
|
relay: {
|
|
1900
1899
|
url: this.defaultRelayUrl,
|
|
1901
1900
|
connected: relay?.isConnected() ?? false,
|
|
1902
1901
|
buffered: relay?.bufferedCount() ?? 0,
|
|
1903
|
-
subscriptions: relay?.activeSubscriptions() ?? []
|
|
1904
|
-
...this.readProxyError ? { proxyError: this.readProxyError } : {}
|
|
1902
|
+
subscriptions: relay?.activeSubscriptions() ?? []
|
|
1905
1903
|
},
|
|
1906
1904
|
...network ? { network } : {},
|
|
1907
1905
|
...apex?.lastError ? { lastError: apex.lastError } : {}
|
|
@@ -1935,7 +1933,14 @@ var ClientRunner = class {
|
|
|
1935
1933
|
async publish(req) {
|
|
1936
1934
|
const apex = this.selectApex(req.btpUrl);
|
|
1937
1935
|
this.assertApexReady(apex);
|
|
1938
|
-
|
|
1936
|
+
let channelId = apex.apexChannelId;
|
|
1937
|
+
if (!channelId) {
|
|
1938
|
+
channelId = await apex.client.openChannel(req.destination);
|
|
1939
|
+
if (!req.destination || req.destination === apex.destination) {
|
|
1940
|
+
apex.apexChannelId = channelId;
|
|
1941
|
+
this.persistApexChannel(apex, channelId);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1939
1944
|
const fee = req.fee !== void 0 ? BigInt(req.fee) : apex.feePerEvent;
|
|
1940
1945
|
const claim = await apex.client.signBalanceProof(channelId, fee);
|
|
1941
1946
|
const result = await apex.client.publishEvent(req.event, {
|
|
@@ -2059,7 +2064,9 @@ var ClientRunner = class {
|
|
|
2059
2064
|
destination ?? apex.destination
|
|
2060
2065
|
);
|
|
2061
2066
|
if (!destination || destination === apex.destination) {
|
|
2067
|
+
const firstOpen = apex.apexChannelId !== channelId;
|
|
2062
2068
|
apex.apexChannelId = channelId;
|
|
2069
|
+
if (firstOpen) this.persistApexChannel(apex, channelId);
|
|
2063
2070
|
}
|
|
2064
2071
|
return { channelId };
|
|
2065
2072
|
}
|
|
@@ -2136,19 +2143,11 @@ var ClientRunner = class {
|
|
|
2136
2143
|
body: await res.text()
|
|
2137
2144
|
};
|
|
2138
2145
|
}
|
|
2139
|
-
/** Graceful teardown: close every relay + stop every apex client
|
|
2146
|
+
/** Graceful teardown: close every relay + stop every apex client. */
|
|
2140
2147
|
async stop() {
|
|
2141
2148
|
if (this.stopped) return;
|
|
2142
2149
|
this.stopped = true;
|
|
2143
2150
|
for (const relay of this.relays.values()) relay.close();
|
|
2144
|
-
if (this.stopReadProxy) {
|
|
2145
|
-
try {
|
|
2146
|
-
await this.stopReadProxy();
|
|
2147
|
-
} catch (err) {
|
|
2148
|
-
this.log(`[runner] read proxy stop error: ${errMsg2(err)}`);
|
|
2149
|
-
}
|
|
2150
|
-
this.stopReadProxy = void 0;
|
|
2151
|
-
}
|
|
2152
2151
|
for (const apex of this.apexes.values()) {
|
|
2153
2152
|
try {
|
|
2154
2153
|
await apex.client.stop();
|
|
@@ -2169,9 +2168,14 @@ var ClientRunner = class {
|
|
|
2169
2168
|
return def;
|
|
2170
2169
|
}
|
|
2171
2170
|
assertApexReady(apex) {
|
|
2171
|
+
if (!this.config.hasUplink) {
|
|
2172
|
+
throw new TargetError(
|
|
2173
|
+
"No write uplink configured \u2014 this daemon is read-only. Set TOON_CLIENT_PROXY_URL (connector proxy) or TOON_CLIENT_BTP_URL to enable paid writes."
|
|
2174
|
+
);
|
|
2175
|
+
}
|
|
2172
2176
|
if (!apex.ready) {
|
|
2173
2177
|
throw new NotReadyError(
|
|
2174
|
-
apex.bootstrapping ? "Apex is still bootstrapping (
|
|
2178
|
+
apex.bootstrapping ? "Apex is still bootstrapping (transport/channel coming up) \u2014 retry shortly." : apex.lastError ?? "Apex is not ready."
|
|
2175
2179
|
);
|
|
2176
2180
|
}
|
|
2177
2181
|
}
|
|
@@ -2259,13 +2263,6 @@ function errMsg2(err) {
|
|
|
2259
2263
|
function sanitize(s) {
|
|
2260
2264
|
return s.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
2261
2265
|
}
|
|
2262
|
-
function isAnyoneHost(url) {
|
|
2263
|
-
try {
|
|
2264
|
-
return new URL(url).hostname.endsWith(".anyone");
|
|
2265
|
-
} catch {
|
|
2266
|
-
return false;
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
2266
|
|
|
2270
2267
|
// src/daemon/routes.ts
|
|
2271
2268
|
function registerRoutes(app, runner) {
|
|
@@ -2492,4 +2489,4 @@ export {
|
|
|
2492
2489
|
PublishRejectedError,
|
|
2493
2490
|
registerRoutes
|
|
2494
2491
|
};
|
|
2495
|
-
//# sourceMappingURL=chunk-
|
|
2492
|
+
//# sourceMappingURL=chunk-QFHCXJ2V.js.map
|