paralith-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 +10 -2
- package/dist/chains.json +79 -42
- package/dist/client.mjs +8 -5
- package/dist/graph.json +2 -2
- package/dist/http.mjs +233 -22
- package/dist/server.mjs +644 -122
- package/dist/view.html +117 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,7 +9,13 @@ Solana and Sui. Public docs: `products/orderbook/app/src/docs/pages/ai/mcp.md`
|
|
|
9
9
|
|
|
10
10
|
Read-only, no install: connect your MCP client to `https://mcp.paralithmarkets.com/mcp`.
|
|
11
11
|
|
|
12
|
-
To play, trade and bridge,
|
|
12
|
+
To play, trade and bridge, connect every agent app on this machine (Claude Code, Claude Desktop, Codex, Grok), each with its own new wallet:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx -y paralith-mcp@latest setup
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or by hand, with a phrase made for the agent (Node 20+):
|
|
13
19
|
|
|
14
20
|
```bash
|
|
15
21
|
claude mcp add paralith --env PARALITH_MNEMONIC_FILE=/path/to/agent-phrase.txt -- npx -y paralith-mcp@latest
|
|
@@ -30,7 +36,9 @@ PARALITH_MNEMONIC_FILE=phrase.txt node scripts/call.mjs wallet '{}' # call one
|
|
|
30
36
|
npm test # also fails if dist/ or the tool reference is stale
|
|
31
37
|
```
|
|
32
38
|
|
|
33
|
-
- `src/server.mjs`: stdio entry. No phrase means read-only.
|
|
39
|
+
- `src/server.mjs`: stdio entry. No phrase means read-only. `setup` runs `src/setup.mjs` instead.
|
|
40
|
+
- `src/setup.mjs`: one wallet per agent app, written into each app's MCP config; `src/agents.mjs` records their public addresses.
|
|
41
|
+
- `src/progress.mjs`: the `progress` tool, one read across game, venues, vaults, bridge and gas, for one agent or all.
|
|
34
42
|
- `src/http.mjs`: hosted read-only endpoint, `POST /mcp`, `GET /health`.
|
|
35
43
|
- `src/build.mjs`: `buildServer()` and the account tools.
|
|
36
44
|
- `src/keys.mjs`: phrase to AO/Base/Solana/Sui signers.
|
package/dist/chains.json
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
"chainId": 8453,
|
|
5
5
|
"rpc": "https://mainnet.base.org",
|
|
6
6
|
"explorer": "https://basescan.org",
|
|
7
|
-
"bridge": "
|
|
8
|
-
"deployBlock":
|
|
7
|
+
"bridge": "0x871ae9cd37B76F9216076d775928C733687596e6",
|
|
8
|
+
"deployBlock": 52429067,
|
|
9
9
|
"tokens": [
|
|
10
10
|
{
|
|
11
|
-
"address": "
|
|
11
|
+
"address": "0xce2ED346Ff3E537E2D99B47F5162b0A07431d9a4",
|
|
12
12
|
"symbol": "TEST-USDC",
|
|
13
13
|
"decimals": 6,
|
|
14
14
|
"faucet": true
|
|
@@ -19,95 +19,132 @@
|
|
|
19
19
|
"cluster": "mainnet-beta",
|
|
20
20
|
"rpc": "https://api.mainnet-beta.solana.com",
|
|
21
21
|
"explorer": "https://solscan.io",
|
|
22
|
-
"programId": "
|
|
22
|
+
"programId": "41aBnUWVghxSWboMKY2F1MhtAYhPMU83igKbfvtjVjcr",
|
|
23
23
|
"deployed": true,
|
|
24
24
|
"tokens": [
|
|
25
25
|
{
|
|
26
|
-
"mint": "
|
|
26
|
+
"mint": "4CjGDd6atsPPe7YPukt3aaHAuXUfhsA9KPkgbgVrcGyq",
|
|
27
27
|
"symbol": "TEST-USDC",
|
|
28
28
|
"decimals": 6,
|
|
29
29
|
"tokenProgram": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
|
|
30
30
|
"faucet": true
|
|
31
31
|
}
|
|
32
32
|
],
|
|
33
|
-
"programIndex":
|
|
33
|
+
"programIndex": 5
|
|
34
34
|
},
|
|
35
35
|
"sui": {
|
|
36
36
|
"network": "mainnet",
|
|
37
37
|
"rpc": "https://fullnode.mainnet.sui.io:443",
|
|
38
38
|
"graphql": "https://graphql.mainnet.sui.io/graphql",
|
|
39
39
|
"explorer": "https://suivision.xyz",
|
|
40
|
-
"package": "
|
|
41
|
-
"originalPackage": "
|
|
42
|
-
"bridge": "
|
|
43
|
-
"faucet": "
|
|
40
|
+
"package": "0x647f58c931f3f9c48ada70a3f91bc554f8945bcad16967e02a0bd49fffe9aed6",
|
|
41
|
+
"originalPackage": "0x647f58c931f3f9c48ada70a3f91bc554f8945bcad16967e02a0bd49fffe9aed6",
|
|
42
|
+
"bridge": "0x270b73af9e6543d196ba7a3bc160f87aabdc662e8601af46ceb0d465ae103337",
|
|
43
|
+
"faucet": "0x4c549789110006fadc343790b770fffa314269bcbeafd4f48853c3bf3d9639ef",
|
|
44
44
|
"tokens": [
|
|
45
45
|
{
|
|
46
|
-
"type": "
|
|
46
|
+
"type": "0x647f58c931f3f9c48ada70a3f91bc554f8945bcad16967e02a0bd49fffe9aed6::test_usdc::TEST_USDC",
|
|
47
47
|
"symbol": "TEST-USDC",
|
|
48
48
|
"decimals": 6,
|
|
49
49
|
"faucet": true
|
|
50
50
|
}
|
|
51
51
|
],
|
|
52
|
-
"adminCap": "
|
|
52
|
+
"adminCap": "0xdd6abffeb51098b05be212f89fe44e78cbef062edfeec6078b225f9e75267570",
|
|
53
53
|
"deployed": true,
|
|
54
54
|
"upgradeCap": "0xa1fb1dc179dcdc0579dca5b50a8d1162c1a3c40f531fb723f21de206c1ca78cd"
|
|
55
55
|
},
|
|
56
|
-
"relayers": {
|
|
57
|
-
"base": "0xDaaefC6Fe9C820DB57E9be7C0b566800de11ac22",
|
|
58
|
-
"solana": "9eVvxEPKgpQ4Y2BZV8BWVAeRHWWfSEJy3vrM2AFNzdQ2",
|
|
59
|
-
"sui": "0x46bd8f40263f6e056262f82f13c61d0849d813a030cde4c5bd6a8dd768144e9f",
|
|
60
|
-
"ao": "z2OMYtbWHqNZY01ehkN0tsepznlrZQW-6dXPQO5lxDM"
|
|
61
|
-
},
|
|
62
56
|
"deploy": {
|
|
63
57
|
"sui": {
|
|
64
|
-
"id": "
|
|
65
|
-
"version": "sha256:
|
|
66
|
-
"localHash": "sha256:
|
|
67
|
-
"deployedAt": "2026-10-
|
|
68
|
-
"tx": "
|
|
58
|
+
"id": "0x647f58c931f3f9c48ada70a3f91bc554f8945bcad16967e02a0bd49fffe9aed6",
|
|
59
|
+
"version": "sha256:d8675a23dc00cfe0d9e73f128ed5948d05e9a708afc1a68829906bec0aaeb432",
|
|
60
|
+
"localHash": "sha256:d8675a23dc00cfe0d9e73f128ed5948d05e9a708afc1a68829906bec0aaeb432",
|
|
61
|
+
"deployedAt": "2026-10-10T16:08:52.325Z",
|
|
62
|
+
"tx": "7CjZL9MGDVXUgSeGCNmT69HWtksnNyJaacFDTrAGahhu",
|
|
69
63
|
"action": "FRESH"
|
|
70
64
|
},
|
|
71
65
|
"pusd": {
|
|
72
|
-
"id": "
|
|
73
|
-
"version": "sha256:
|
|
74
|
-
"localHash": "sha256:
|
|
75
|
-
"deployedAt": "2026-10-
|
|
76
|
-
"tx": "
|
|
66
|
+
"id": "xhYkQ8qm7zssDC2nrOfzkk2Xy8rPVvlEMWestfrAvK8",
|
|
67
|
+
"version": "sha256:5c7aee2fad4dd8c558bbbcc4cf1dd19da28c5faf834bf4a801cf82969c0225c8",
|
|
68
|
+
"localHash": "sha256:5c7aee2fad4dd8c558bbbcc4cf1dd19da28c5faf834bf4a801cf82969c0225c8",
|
|
69
|
+
"deployedAt": "2026-10-10T15:51:14.512Z",
|
|
70
|
+
"tx": "xhYkQ8qm7zssDC2nrOfzkk2Xy8rPVvlEMWestfrAvK8",
|
|
77
71
|
"action": "FRESH"
|
|
78
72
|
},
|
|
79
73
|
"base": {
|
|
80
|
-
"id": "
|
|
81
|
-
"version": "
|
|
82
|
-
"localHash": "
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
74
|
+
"id": "0x871ae9cd37B76F9216076d775928C733687596e6",
|
|
75
|
+
"version": "0xe9e86188e3c0aa76ab1148c6cdee756045799152b0d796c2c74138ffae8ad03b",
|
|
76
|
+
"localHash": "0xe9e86188e3c0aa76ab1148c6cdee756045799152b0d796c2c74138ffae8ad03b",
|
|
77
|
+
"baselined": false,
|
|
78
|
+
"recordedAt": "2026-10-10T16:09:39.076Z",
|
|
79
|
+
"deployedAt": null
|
|
86
80
|
},
|
|
87
81
|
"solana": {
|
|
88
|
-
"id": "
|
|
89
|
-
"version": "sha256:
|
|
90
|
-
"localHash": "sha256:
|
|
91
|
-
"deployedAt": "2026-10-
|
|
92
|
-
"tx": "
|
|
82
|
+
"id": "41aBnUWVghxSWboMKY2F1MhtAYhPMU83igKbfvtjVjcr",
|
|
83
|
+
"version": "sha256:4279831e73a9247928ad5c4490bb203bc498d834da24f6da0ff20562898ec47e",
|
|
84
|
+
"localHash": "sha256:4279831e73a9247928ad5c4490bb203bc498d834da24f6da0ff20562898ec47e",
|
|
85
|
+
"deployedAt": "2026-10-10T16:08:35.744Z",
|
|
86
|
+
"tx": "J8trVshLfVhCxSJHnXXLhxdbkmkWLEhpE9FEjTHDK8qTkYY7izhX2zAtVscsztaTn7nMDnLhT88BHBw9MsVmbVC",
|
|
93
87
|
"action": "FRESH"
|
|
94
88
|
},
|
|
95
89
|
"lastRun": {
|
|
96
|
-
"at": "2026-10-
|
|
97
|
-
"startedAt": "2026-10-
|
|
90
|
+
"at": "2026-10-10T16:09:39.077Z",
|
|
91
|
+
"startedAt": "2026-10-10T15:51:02.462Z",
|
|
98
92
|
"steps": [
|
|
99
93
|
{
|
|
100
94
|
"component": "pusd",
|
|
101
95
|
"action": "FRESH",
|
|
102
96
|
"status": "done",
|
|
103
|
-
"tx": "
|
|
97
|
+
"tx": "xhYkQ8qm7zssDC2nrOfzkk2Xy8rPVvlEMWestfrAvK8"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"component": "base",
|
|
101
|
+
"action": "FRESH",
|
|
102
|
+
"status": "done"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"component": "solana",
|
|
106
|
+
"action": "FRESH",
|
|
107
|
+
"status": "done",
|
|
108
|
+
"tx": "J8trVshLfVhCxSJHnXXLhxdbkmkWLEhpE9FEjTHDK8qTkYY7izhX2zAtVscsztaTn7nMDnLhT88BHBw9MsVmbVC"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"component": "sui",
|
|
112
|
+
"action": "FRESH",
|
|
113
|
+
"status": "done",
|
|
114
|
+
"tx": "7CjZL9MGDVXUgSeGCNmT69HWtksnNyJaacFDTrAGahhu"
|
|
104
115
|
},
|
|
105
116
|
{
|
|
106
117
|
"component": "tokens",
|
|
107
118
|
"action": "CONFIGURE",
|
|
108
119
|
"status": "done"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"component": "graph",
|
|
123
|
+
"action": "CONFIGURE",
|
|
124
|
+
"status": "done"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"component": "site",
|
|
128
|
+
"action": "CONFIGURE",
|
|
129
|
+
"status": "done"
|
|
109
130
|
}
|
|
110
131
|
]
|
|
111
132
|
}
|
|
133
|
+
},
|
|
134
|
+
"attestors": [
|
|
135
|
+
{
|
|
136
|
+
"ao": "tkqULqMDeHKXCN79Cm_bDIV560JxXl6pBSmdPgxqwSw",
|
|
137
|
+
"operator": "efH9MDGEFZqQ4nTTRNxl8WXJi2NbZvd2xVgCWmG5EeM",
|
|
138
|
+
"base": "0xcefcaae4d5077eda2b126e9b315b5d7c4dd2ff38",
|
|
139
|
+
"solana": "BBuQ11wQE6K5bj6Cx7X5VpVDB9CG83nbeDdDSinavUz",
|
|
140
|
+
"sui": "0x397c399eb2f7e24e8f5d1988f71284baac48149b9e8cdcd741b353c771118ebc",
|
|
141
|
+
"epoch": 0
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"retiredRelayers": {
|
|
145
|
+
"base": "0xDaaefC6Fe9C820DB57E9be7C0b566800de11ac22",
|
|
146
|
+
"solana": "9eVvxEPKgpQ4Y2BZV8BWVAeRHWWfSEJy3vrM2AFNzdQ2",
|
|
147
|
+
"sui": "0x46bd8f40263f6e056262f82f13c61d0849d813a030cde4c5bd6a8dd768144e9f",
|
|
148
|
+
"ao": "z2OMYtbWHqNZY01ehkN0tsepznlrZQW-6dXPQO5lxDM"
|
|
112
149
|
}
|
|
113
150
|
}
|
package/dist/client.mjs
CHANGED
|
@@ -401,7 +401,7 @@ var init_slot_settle = __esm({
|
|
|
401
401
|
var graph_default;
|
|
402
402
|
var init_graph = __esm({
|
|
403
403
|
"runerealm-graph:C:\\REPO\\paralith-mono\\products\\runerealm-ui\\src\\lib\\graph.json"() {
|
|
404
|
-
graph_default = { node: "https://hyperbeam.tylerw.ai", owner: "DA9qhP25ZPz6MHIhO-7aNHDN3LsTAL7yCKYIkqr13Z8", deployedAt: "", processes: { game: "bqkZT1qY8Qpea7QsKZEk8q7m0yUE8-G3Miq8EFXnRJg", rune: "0j4rkkEqUO25aXI8LoDuou2Ibr0GSMGsXrFRxwrSfY8", pusd: "
|
|
404
|
+
graph_default = { node: "https://hyperbeam.tylerw.ai", owner: "DA9qhP25ZPz6MHIhO-7aNHDN3LsTAL7yCKYIkqr13Z8", deployedAt: "", processes: { game: "bqkZT1qY8Qpea7QsKZEk8q7m0yUE8-G3Miq8EFXnRJg", rune: "0j4rkkEqUO25aXI8LoDuou2Ibr0GSMGsXrFRxwrSfY8", pusd: "xhYkQ8qm7zssDC2nrOfzkk2Xy8rPVvlEMWestfrAvK8", dao: "YAPgWNxRQksjYn_zfUw-h-JkwpmJDtPL1K9yifR5S_Q", elements: { earth: "3CS-LPEfD4YJwpuh1kuPGOv3lGwIlOAWOT15ATGIbPg", air: "y51gmVYD1GoJWtMxAtePMnvMCR0aT-jSfnsMKjFeU70", fire: "os6EKVQGuukvgTFmaZbGj23Xt3frHB3cb8ljquCdJ18", water: "P9OPPoVw9MxpIz8QghA6TcYUhXrYG3Ro09KM8shX5QM" }, internalVenue: "pxw-Y9Hl8CNQlPGLr-2Ez_9BVjjEP6wisxrZhe-AyxU", externalVenue: "D3SUysjoweBXtoGFm4zoq1dKSt7Dc5b_V9x_weLJV7Y", hunt: "4iABQxFjL3LtMGgfZQuwsH5WHKKjjSu7b7XfxEN_j40", huntWorkers: ["4iABQxFjL3LtMGgfZQuwsH5WHKKjjSu7b7XfxEN_j40", "2RBkmldqPdij2PopnEPuStLl6Pb6OcIrpilfK64Q1m8", "EATa5vTV53J1c711CEjiuks2Kllq3Gi-kVSXFqe7O7M", "SHXyU87725eI8i6qSET70Pwovf744DJqEfajTZI4N4M", "iesbJSITvqtDXMHxhGeOOXUXofnD-nh1qro9PH5IHNQ"], battleWorkers: ["Xk8XXWY2QY-UCd1Y_yqx6SHlVt5bNUbQnwzngMgxbzc", "IPjes-iFyMZH_JCx1z-4c-7JEdJgd3RGgbglgl3_u2s", "-m-6qgUsU6ybjOpMMlPHvG1bIlHypFMORKw4blCpRnU", "mSzalVGuEgxAG_tCEhVivSPMhSvmp5ePMHRIW0-gASM", "PkPEU-yZpgn9LwXWYPahUKOPe-Hw2sHB0DPBNPoxQeA"] }, huntNode: "https://hyperbeam.tylerw.ai", marketNode: "https://hyperbeam.tylerw.ai", venueNode: "https://hyperbeam.tylerw.ai" };
|
|
405
405
|
}
|
|
406
406
|
});
|
|
407
407
|
|
|
@@ -9801,9 +9801,12 @@ var ShardedVenue = class {
|
|
|
9801
9801
|
return { cancelled: { cancelledIds }, account: await this.summed(address, targets) };
|
|
9802
9802
|
}
|
|
9803
9803
|
/** Housekeeping, on every pair: anyone may call it, nobody is paid to. */
|
|
9804
|
-
|
|
9804
|
+
/** `pairIds` sweeps only those pairs: one signed message each, so name the ones holding expired orders. */
|
|
9805
|
+
async maintain(limit = 25, pairIds) {
|
|
9805
9806
|
let expired = 0;
|
|
9806
|
-
|
|
9807
|
+
const pairs = await this.pairs();
|
|
9808
|
+
const due = pairIds ? pairIds.filter((id) => pairs[id]).map((id) => pairs[id]) : Object.values(pairs);
|
|
9809
|
+
for (const pair2 of due) {
|
|
9807
9810
|
const reply = unwrap4(await this.transport.send(pair2.process, tags2({
|
|
9808
9811
|
Action: "Order.Maintain",
|
|
9809
9812
|
Limit: String(Math.max(1, Math.floor(limit)))
|
|
@@ -10016,9 +10019,9 @@ var cancelAllVenueOrders = async (process, item) => {
|
|
|
10016
10019
|
...item ? { Item: item } : {}
|
|
10017
10020
|
});
|
|
10018
10021
|
};
|
|
10019
|
-
var maintainVenueOrders = async (process, limit = 25) => {
|
|
10022
|
+
var maintainVenueOrders = async (process, limit = 25, pairIds) => {
|
|
10020
10023
|
const s = await shard(process);
|
|
10021
|
-
if (s) return s.maintain(limit);
|
|
10024
|
+
if (s) return s.maintain(limit, pairIds);
|
|
10022
10025
|
return write4(process, {
|
|
10023
10026
|
Action: "Order.Maintain",
|
|
10024
10027
|
Limit: String(Math.max(1, Math.floor(limit)))
|
package/dist/graph.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"node": "https://hyperbeam.tylerw.ai",
|
|
3
3
|
"owner": "DA9qhP25ZPz6MHIhO-7aNHDN3LsTAL7yCKYIkqr13Z8",
|
|
4
|
-
"deployedAt": "2026-10-
|
|
4
|
+
"deployedAt": "2026-10-10T15:51:09.959Z",
|
|
5
5
|
"processes": {
|
|
6
6
|
"game": "bqkZT1qY8Qpea7QsKZEk8q7m0yUE8-G3Miq8EFXnRJg",
|
|
7
7
|
"rune": "0j4rkkEqUO25aXI8LoDuou2Ibr0GSMGsXrFRxwrSfY8",
|
|
8
|
-
"pusd": "
|
|
8
|
+
"pusd": "xhYkQ8qm7zssDC2nrOfzkk2Xy8rPVvlEMWestfrAvK8",
|
|
9
9
|
"dao": "YAPgWNxRQksjYn_zfUw-h-JkwpmJDtPL1K9yifR5S_Q",
|
|
10
10
|
"elements": {
|
|
11
11
|
"earth": "3CS-LPEfD4YJwpuh1kuPGOv3lGwIlOAWOT15ATGIbPg",
|
package/dist/http.mjs
CHANGED
|
@@ -5,8 +5,8 @@ import http2 from "node:http";
|
|
|
5
5
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
6
6
|
|
|
7
7
|
// src/runtime.mjs
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import fs3 from "node:fs";
|
|
9
|
+
import path3 from "node:path";
|
|
10
10
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
11
|
|
|
12
12
|
// ../../backend/native/ans104.mjs
|
|
@@ -135,7 +135,7 @@ import { mnemonicToAccount } from "viem/accounts";
|
|
|
135
135
|
import { Keypair } from "@solana/web3.js";
|
|
136
136
|
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
|
|
137
137
|
import { getKeyFromMnemonic } from "arweave-mnemonic-keys";
|
|
138
|
-
var
|
|
138
|
+
var HOME = process.env.PARALITH_MCP_HOME || path.join(os.homedir(), ".paralith", "mcp");
|
|
139
139
|
function readPhrase(env = process.env) {
|
|
140
140
|
const raw = env.PARALITH_MNEMONIC ?? (env.PARALITH_MNEMONIC_FILE ? fs.readFileSync(env.PARALITH_MNEMONIC_FILE, "utf8") : null);
|
|
141
141
|
if (!raw) {
|
|
@@ -162,25 +162,27 @@ function slip10(seed, derivation) {
|
|
|
162
162
|
async function aoJwk(phrase, env) {
|
|
163
163
|
if (env.PARALITH_AO_JWK) return JSON.parse(fs.readFileSync(env.PARALITH_AO_JWK, "utf8"));
|
|
164
164
|
const id = crypto2.createHash("sha256").update(phrase).digest("hex").slice(0, 24);
|
|
165
|
-
const file = path.join(
|
|
165
|
+
const file = path.join(HOME, `ao-${id}.json`);
|
|
166
166
|
if (fs.existsSync(file)) return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
167
167
|
const jwk = await getKeyFromMnemonic(phrase);
|
|
168
|
-
fs.mkdirSync(
|
|
168
|
+
fs.mkdirSync(HOME, { recursive: true, mode: 448 });
|
|
169
169
|
fs.writeFileSync(file, JSON.stringify(jwk), { mode: 384 });
|
|
170
170
|
return jwk;
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
function chainWallets(phrase) {
|
|
173
173
|
const evm = mnemonicToAccount(phrase, { path: "m/44'/60'/0'/0/0" });
|
|
174
174
|
const solana = Keypair.fromSeed(slip10(mnemonicToSeedSync(phrase), "m/44'/501'/0'/0'"));
|
|
175
175
|
const sui = Ed25519Keypair.deriveKeypair(phrase, "m/44'/784'/0'/0'/0'");
|
|
176
|
-
const jwk = await aoJwk(phrase, env);
|
|
177
176
|
return {
|
|
178
|
-
ao: { jwk, address: jwkToAddress(jwk) },
|
|
179
177
|
base: { account: evm, address: evm.address },
|
|
180
178
|
solana: { keypair: solana, address: solana.publicKey.toBase58() },
|
|
181
179
|
sui: { keypair: sui, address: sui.getPublicKey().toSuiAddress() }
|
|
182
180
|
};
|
|
183
181
|
}
|
|
182
|
+
async function deriveWallets(phrase, env = process.env) {
|
|
183
|
+
const jwk = await aoJwk(phrase, env);
|
|
184
|
+
return { ao: { jwk, address: jwkToAddress(jwk) }, ...chainWallets(phrase) };
|
|
185
|
+
}
|
|
184
186
|
var publicAddresses = (w) => ({
|
|
185
187
|
ao: w.ao.address,
|
|
186
188
|
base: w.base.address,
|
|
@@ -188,12 +190,32 @@ var publicAddresses = (w) => ({
|
|
|
188
190
|
sui: w.sui.address
|
|
189
191
|
});
|
|
190
192
|
|
|
193
|
+
// src/agents.mjs
|
|
194
|
+
import fs2 from "node:fs";
|
|
195
|
+
import path2 from "node:path";
|
|
196
|
+
var FILE = path2.join(HOME, "agents.json");
|
|
197
|
+
function readAgents() {
|
|
198
|
+
try {
|
|
199
|
+
return JSON.parse(fs2.readFileSync(FILE, "utf8"));
|
|
200
|
+
} catch {
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function saveAgent(name, entry) {
|
|
205
|
+
const all = readAgents();
|
|
206
|
+
all[name] = { ...all[name], ...entry, addresses: { ...all[name]?.addresses, ...entry.addresses } };
|
|
207
|
+
fs2.mkdirSync(HOME, { recursive: true, mode: 448 });
|
|
208
|
+
fs2.writeFileSync(FILE, `${JSON.stringify(all, null, 2)}
|
|
209
|
+
`);
|
|
210
|
+
return all[name];
|
|
211
|
+
}
|
|
212
|
+
|
|
191
213
|
// src/runtime.mjs
|
|
192
|
-
var HERE =
|
|
193
|
-
var DIST =
|
|
194
|
-
var graph = JSON.parse(
|
|
214
|
+
var HERE = path3.dirname(fileURLToPath(import.meta.url));
|
|
215
|
+
var DIST = fs3.existsSync(path3.join(HERE, "graph.json")) ? HERE : path3.join(HERE, "..", "dist");
|
|
216
|
+
var graph = JSON.parse(fs3.readFileSync(path3.join(DIST, "graph.json"), "utf8"));
|
|
195
217
|
var NODE = graph.node.replace(/\/$/, "");
|
|
196
|
-
var chains = JSON.parse(
|
|
218
|
+
var chains = JSON.parse(fs3.readFileSync(path3.join(DIST, "chains.json"), "utf8"));
|
|
197
219
|
var PROCESS_ALIASES = {
|
|
198
220
|
game: graph.processes.game,
|
|
199
221
|
rune: graph.processes.rune,
|
|
@@ -215,7 +237,8 @@ var loaded = null;
|
|
|
215
237
|
function runtime() {
|
|
216
238
|
loaded ??= (async () => {
|
|
217
239
|
const wallets = READ_ONLY ? null : await deriveWallets(readPhrase());
|
|
218
|
-
|
|
240
|
+
if (wallets && process.env.PARALITH_AGENT) saveAgent(process.env.PARALITH_AGENT, { addresses: publicAddresses(wallets) });
|
|
241
|
+
const api = await import(pathToFileURL(path3.join(DIST, "client.mjs")).href);
|
|
219
242
|
if (wallets) api.swarmWalletSlot.wallet = walletShim(wallets.ao.jwk);
|
|
220
243
|
return { api, wallets };
|
|
221
244
|
})();
|
|
@@ -277,7 +300,7 @@ async function until(what, read, done, timeoutMs = 6e5, everyMs = 3e3) {
|
|
|
277
300
|
|
|
278
301
|
// src/build.mjs
|
|
279
302
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
280
|
-
import { z as
|
|
303
|
+
import { z as z9 } from "zod";
|
|
281
304
|
|
|
282
305
|
// src/tool.mjs
|
|
283
306
|
import { z } from "zod";
|
|
@@ -1153,6 +1176,19 @@ function suiChain(w) {
|
|
|
1153
1176
|
}
|
|
1154
1177
|
};
|
|
1155
1178
|
}
|
|
1179
|
+
async function gasOf(name, address) {
|
|
1180
|
+
if (name === "base") {
|
|
1181
|
+
const rpc = process.env.PARALITH_BASE_RPC || chains.base.rpc;
|
|
1182
|
+
const pub = createPublicClient({ chain: { ...base, id: chains.base.chainId }, transport: http(rpc) });
|
|
1183
|
+
return `${formatEther(await pub.getBalance({ address }))} ETH`;
|
|
1184
|
+
}
|
|
1185
|
+
if (name === "solana") {
|
|
1186
|
+
const conn = new Connection(process.env.PARALITH_SOLANA_RPC || chains.solana.rpc, "confirmed");
|
|
1187
|
+
return `${await conn.getBalance(new PublicKey(address)) / 1e9} SOL`;
|
|
1188
|
+
}
|
|
1189
|
+
const client = new SuiGrpcClient({ network: chains.sui.network, baseUrl: process.env.PARALITH_SUI_RPC || chains.sui.rpc });
|
|
1190
|
+
return `${Number((await client.getBalance({ owner: address })).balance.balance) / 1e9} SUI`;
|
|
1191
|
+
}
|
|
1156
1192
|
async function chainFor(name) {
|
|
1157
1193
|
const { wallets } = await runtime();
|
|
1158
1194
|
return { base: baseChain, solana: solanaChain, sui: suiChain }[name](wallets);
|
|
@@ -1420,11 +1456,11 @@ function registerDao(server) {
|
|
|
1420
1456
|
exec_process: z5.string().regex(ID).optional().describe("Process the passed proposal sends its one message to."),
|
|
1421
1457
|
exec_tags: z5.record(z5.string(), z5.string()).optional().describe('Tags of that message, e.g. {"Action": "Admin.SetRules", ...}. At most 16; required with exec_process.')
|
|
1422
1458
|
},
|
|
1423
|
-
async ({ title, body, link, exec_process, exec_tags }) => send({
|
|
1459
|
+
async ({ title, body, link: link2, exec_process, exec_tags }) => send({
|
|
1424
1460
|
Action: "Propose",
|
|
1425
1461
|
Title: title,
|
|
1426
1462
|
Body: body,
|
|
1427
|
-
Link:
|
|
1463
|
+
Link: link2,
|
|
1428
1464
|
"Exec-Process": exec_process,
|
|
1429
1465
|
"Exec-Tags": exec_tags && JSON.stringify(exec_tags)
|
|
1430
1466
|
}),
|
|
@@ -1626,6 +1662,175 @@ function registerVaults(server) {
|
|
|
1626
1662
|
);
|
|
1627
1663
|
}
|
|
1628
1664
|
|
|
1665
|
+
// src/show.mjs
|
|
1666
|
+
import fs4 from "node:fs";
|
|
1667
|
+
import path4 from "node:path";
|
|
1668
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
1669
|
+
import { z as z7 } from "zod";
|
|
1670
|
+
import { registerAppResource, registerAppTool, RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
|
|
1671
|
+
var GAME = (process.env.PARALITH_GAME_URL || "https://game.paralithmarkets.com").replace(/\/$/, "");
|
|
1672
|
+
var TRADE = (process.env.PARALITH_TRADE_URL || "https://trade.paralithmarkets.com").replace(/\/$/, "");
|
|
1673
|
+
var URI = "ui://paralith/view";
|
|
1674
|
+
var HERE2 = path4.dirname(fileURLToPath2(import.meta.url));
|
|
1675
|
+
function viewHtml() {
|
|
1676
|
+
for (const file of [path4.join(HERE2, "view.html"), path4.join(HERE2, "..", "dist", "view.html")]) {
|
|
1677
|
+
if (fs4.existsSync(file)) return fs4.readFileSync(file, "utf8");
|
|
1678
|
+
}
|
|
1679
|
+
throw new Error("view.html is missing: run npm run build");
|
|
1680
|
+
}
|
|
1681
|
+
var link = (base2, page, params) => {
|
|
1682
|
+
const query = new URLSearchParams(Object.entries(params).filter(([, v]) => v !== void 0 && v !== ""));
|
|
1683
|
+
return `${base2}/embed/${page}${query.size ? `?${query}` : ""}`;
|
|
1684
|
+
};
|
|
1685
|
+
var VIEWS = {
|
|
1686
|
+
battle: (a) => a.battle_id && a.worker ? link(GAME, "battle", { w: a.worker, b: a.battle_id, a: a.address }) : link(GAME, "battle", { a: need2(a, "address") }),
|
|
1687
|
+
companion: (a) => link(GAME, "companion", { a: need2(a, "address"), m: a.monster_id }),
|
|
1688
|
+
hunt: (a) => link(GAME, "hunt", { a: need2(a, "address") }),
|
|
1689
|
+
market: (a) => link(TRADE, "market", { venue: a.venue ?? "token", m: need2(a, "market") }),
|
|
1690
|
+
vault: (a) => link(TRADE, "vault", { venue: a.venue ?? "token", m: need2(a, "market"), v: a.vault ?? "amm" }),
|
|
1691
|
+
position: (a) => link(TRADE, "position", { venue: a.venue ?? "token", a: need2(a, "address") }),
|
|
1692
|
+
bridge: (a) => link(TRADE, "bridge", { a: a.address, chain: a.chain, tx: a.tx })
|
|
1693
|
+
};
|
|
1694
|
+
function need2(args, key) {
|
|
1695
|
+
if (!args[key]) throw new Error(`${key} is required to show this.`);
|
|
1696
|
+
return args[key];
|
|
1697
|
+
}
|
|
1698
|
+
async function ownAddress() {
|
|
1699
|
+
if (READ_ONLY) return void 0;
|
|
1700
|
+
const { wallets } = await runtime();
|
|
1701
|
+
return wallets?.ao.address;
|
|
1702
|
+
}
|
|
1703
|
+
function registerShow(server) {
|
|
1704
|
+
const csp = { frameDomains: [GAME, TRADE] };
|
|
1705
|
+
registerAppResource(
|
|
1706
|
+
server,
|
|
1707
|
+
"Paralith view",
|
|
1708
|
+
URI,
|
|
1709
|
+
{ description: "Live game and exchange visuals." },
|
|
1710
|
+
async () => ({ contents: [{ uri: URI, mimeType: RESOURCE_MIME_TYPE, text: viewHtml(), _meta: { ui: { csp } } }] })
|
|
1711
|
+
);
|
|
1712
|
+
registerAppTool(server, "show", {
|
|
1713
|
+
description: "Show something with the game's and exchange's own visuals, live: battle (follows a player's arena fights, animated), companion (card), hunt, market (order book and chart), vault, position, bridge (transfers). Returns a link; clients that support MCP Apps also display it inline. Address defaults to yours.",
|
|
1714
|
+
inputSchema: {
|
|
1715
|
+
what: z7.enum(Object.keys(VIEWS)),
|
|
1716
|
+
address: z7.string().optional().describe("AO address; omit for yours."),
|
|
1717
|
+
monster_id: z7.string().optional().describe("companion: which one; omit for the active companion."),
|
|
1718
|
+
battle_id: z7.string().optional().describe("battle: a specific battle, with worker."),
|
|
1719
|
+
worker: z7.string().optional().describe("battle: the battle worker process id."),
|
|
1720
|
+
venue: z7.enum(["game", "token"]).optional().describe("market/vault/position. Default token."),
|
|
1721
|
+
market: z7.string().optional().describe("market/vault: the market, as exchange_markets lists it."),
|
|
1722
|
+
vault: z7.enum(["amm", "active", "grid"]).optional(),
|
|
1723
|
+
chain: z7.enum(["base", "solana", "sui"]).optional().describe("bridge: with tx, one transfer."),
|
|
1724
|
+
tx: z7.string().optional()
|
|
1725
|
+
},
|
|
1726
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
1727
|
+
_meta: { ui: { resourceUri: URI } }
|
|
1728
|
+
}, async (args) => {
|
|
1729
|
+
try {
|
|
1730
|
+
const view = VIEWS[args.what]({ ...args, address: args.address ?? await ownAddress() });
|
|
1731
|
+
return { structuredContent: { what: args.what, view }, content: [{ type: "text", text: `${args.what}: ${view}` }] };
|
|
1732
|
+
} catch (error) {
|
|
1733
|
+
return { isError: true, content: [{ type: "text", text: error.message }] };
|
|
1734
|
+
}
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
// src/progress.mjs
|
|
1739
|
+
import { z as z8 } from "zod";
|
|
1740
|
+
var VENUES = { game: graph.processes.internalVenue, token: graph.processes.externalVenue };
|
|
1741
|
+
var count = (x) => Array.isArray(x) ? x.length : Object.values(x ?? {}).reduce((n, v) => n + Number(v || 0), 0);
|
|
1742
|
+
async function targets(who) {
|
|
1743
|
+
const { wallets } = await runtime();
|
|
1744
|
+
const agents = readAgents();
|
|
1745
|
+
const self = wallets && { name: process.env.PARALITH_AGENT ?? "you", addresses: publicAddresses(wallets) };
|
|
1746
|
+
if (!who || who === "me") {
|
|
1747
|
+
if (!self) throw new Error("This server has no wallet; pass who: an AO address.");
|
|
1748
|
+
return [self];
|
|
1749
|
+
}
|
|
1750
|
+
if (who === "all") {
|
|
1751
|
+
const list = Object.entries(agents).map(([name, a]) => ({ name, addresses: a.addresses }));
|
|
1752
|
+
if (self && !list.some((t) => t.name === self.name)) list.unshift(self);
|
|
1753
|
+
if (!list.length) throw new Error("No agents are set up here. Run: npx -y paralith-mcp@latest setup");
|
|
1754
|
+
return list;
|
|
1755
|
+
}
|
|
1756
|
+
if (agents[who]) return [{ name: who, addresses: agents[who].addresses }];
|
|
1757
|
+
if (ID.test(who)) return [{ name: who, addresses: { ao: who } }];
|
|
1758
|
+
throw new Error(`"${who}" is not an agent here (${Object.keys(agents).join(", ") || "none"}) or an AO address.`);
|
|
1759
|
+
}
|
|
1760
|
+
async function report({ name, addresses: a }) {
|
|
1761
|
+
const { api } = await runtime();
|
|
1762
|
+
const out = { agent: name, addresses: a };
|
|
1763
|
+
const todo = [];
|
|
1764
|
+
const gas = Object.fromEntries(await Promise.all(["base", "solana", "sui"].filter((c) => a[c]).map(async (c) => [c, await gasOf(c, a[c]).catch(() => "unreadable")])));
|
|
1765
|
+
if (Object.keys(gas).length) out.gas = gas;
|
|
1766
|
+
if (!a.ao) {
|
|
1767
|
+
out.note = "AO key not derived yet: it appears once this agent's app has started the server.";
|
|
1768
|
+
return out;
|
|
1769
|
+
}
|
|
1770
|
+
const [p, tokens, venues, redemptions] = await Promise.all([
|
|
1771
|
+
api.readPlayer(a.ao).catch(() => null),
|
|
1772
|
+
Promise.all(Object.entries({ rune: graph.processes.rune, pusd: graph.processes.pusd, ...graph.processes.elements }).map(async ([t, id]) => [t, await readAtoms(id, `balance-${a.ao}`).catch(() => 0n)])),
|
|
1773
|
+
Promise.all(Object.entries(VENUES).map(async ([v, pid]) => [
|
|
1774
|
+
v,
|
|
1775
|
+
await api.readVenuePosition(pid, a.ao).catch(() => null),
|
|
1776
|
+
await api.readVenueVaultPositions(pid, a.ao).catch(() => null)
|
|
1777
|
+
])),
|
|
1778
|
+
readKey("pusd", "withdrawals").catch(() => null)
|
|
1779
|
+
]);
|
|
1780
|
+
if (!p) {
|
|
1781
|
+
out.game = { joined: false };
|
|
1782
|
+
todo.push("Join the game (game_join).");
|
|
1783
|
+
} else {
|
|
1784
|
+
const raw = p.monsters?.[p.activeId] ?? p.collection?.[p.activeId];
|
|
1785
|
+
const c = companion(raw);
|
|
1786
|
+
out.game = {
|
|
1787
|
+
faction: p.faction,
|
|
1788
|
+
gold: p.gold,
|
|
1789
|
+
rune: p.inventory?.rune ?? 0,
|
|
1790
|
+
companion: c && { name: c.name, level: c.level, exp: c.exp, energy: c.energy, happiness: c.happiness },
|
|
1791
|
+
arena: { wins: p.wins ?? 0, losses: p.losses ?? 0, rating: p.rating, sessionBattlesLeft: p.battlesRemaining ?? 0 },
|
|
1792
|
+
...p.battleFleet ? { inBattle: p.battleFleet.battleId } : {},
|
|
1793
|
+
...p.hunt ? { onHunt: p.hunt.runId } : {}
|
|
1794
|
+
};
|
|
1795
|
+
if (!p.dailyReadyAt || Number(p.dailyReadyAt) <= Date.now()) todo.push("Daily crate is ready (game_daily).");
|
|
1796
|
+
if (count(p.lootboxes)) todo.push(`${count(p.lootboxes)} loot box(es) to open (game_lootbox).`);
|
|
1797
|
+
if (raw && Number(raw.exp ?? 0) >= Number(raw.nextLevelExp ?? Infinity)) todo.push("Companion can level up (game_level_up).");
|
|
1798
|
+
if (c && (c.energy < 25 || c.happiness < 25)) todo.push("Companion is below the arena's 25 energy/happiness: feed or play.");
|
|
1799
|
+
}
|
|
1800
|
+
const held = Object.fromEntries(tokens.filter(([, v]) => v > 0n).map(([t, v]) => [t, formatAtoms(v)]));
|
|
1801
|
+
if (Object.keys(held).length) out.tokens = held;
|
|
1802
|
+
const trading = {};
|
|
1803
|
+
for (const [v, pos, vaults] of venues) {
|
|
1804
|
+
const row = {};
|
|
1805
|
+
if (pos?.orders?.length) row.openOrders = pos.orders.length;
|
|
1806
|
+
if (pos?.fills?.length) row.recentFills = pos.fills.length;
|
|
1807
|
+
const shares = Object.entries(vaults ?? {}).flatMap(([m, r]) => Object.entries(r).filter(([, x]) => BigInt(x?.shares ?? 0) > 0n).map(([s]) => `${m} ${s}`));
|
|
1808
|
+
if (shares.length) row.vaults = shares;
|
|
1809
|
+
if (Object.keys(row).length) trading[v] = row;
|
|
1810
|
+
}
|
|
1811
|
+
if (Object.keys(trading).length) out.trading = trading;
|
|
1812
|
+
const pending = (redemptions ?? []).filter((w) => w.account === a.ao && w.status !== "released");
|
|
1813
|
+
if (pending.length) out.bridge = { pendingRedemptions: pending.length };
|
|
1814
|
+
if (Object.keys(gas).length && Object.values(gas).every((g) => /^0 /.test(g))) {
|
|
1815
|
+
todo.push("No chain gas yet: fund an address above to bridge.");
|
|
1816
|
+
}
|
|
1817
|
+
if (todo.length) out.todo = todo;
|
|
1818
|
+
return out;
|
|
1819
|
+
}
|
|
1820
|
+
function registerProgress(server) {
|
|
1821
|
+
tool(
|
|
1822
|
+
server,
|
|
1823
|
+
"progress",
|
|
1824
|
+
'How an agent is doing, in one free read: game (companion, Gold, Rune, arena record, live battle or hunt), tokens, open orders and vault shares on both venues, pending bridge redemptions, chain gas, and what needs doing next. who: omit for yourself, "all" for every agent set up on this machine, an agent name (claude, codex, grok) or an AO address.',
|
|
1825
|
+
{ who: z8.string().optional() },
|
|
1826
|
+
async ({ who }) => {
|
|
1827
|
+
const list = await Promise.all((await targets(who)).map(report));
|
|
1828
|
+
return list.length === 1 ? list[0] : list;
|
|
1829
|
+
},
|
|
1830
|
+
READ
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1629
1834
|
// src/build.mjs
|
|
1630
1835
|
var DOCS = process.env.PARALITH_DOCS_URL || "https://docs.paralithmarkets.com";
|
|
1631
1836
|
var INSTRUCTIONS = `Paralith on AO (HyperBEAM): Rune Realm (a companion game), two order books, and the PUSD bridge.
|
|
@@ -1642,13 +1847,17 @@ Vaults (pooled liquidity, one amm/active/grid per market): vault_list, vault_pos
|
|
|
1642
1847
|
Rune: rune_move withdraw (game -> token) / deposit (token -> game). Bridge: bridge_balances, bridge_faucet, bridge_deposit, bridge_redeem.
|
|
1643
1848
|
DAO (stake TEST-RUNE; a passed proposal may send one attached message): dao_info, dao_proposals, dao_stake stake/unstake/withdraw, dao_propose, dao_vote.
|
|
1644
1849
|
|
|
1850
|
+
To report how you (or every agent set up on this machine) are doing, call progress (who: "all" for every agent); it also lists what needs doing next.
|
|
1851
|
+
|
|
1852
|
+
To let the user SEE something (an arena fight as it happens, a companion, a hunt, a market's book and chart, a vault, a position, bridge transfers), call show: it returns a live link and displays inline where the client supports it.
|
|
1853
|
+
|
|
1645
1854
|
Rules: if a tool says a write WAS accepted but unconfirmed, never resend it; re-read state instead.
|
|
1646
1855
|
A refusal ({"error": ...}) costs nothing. Use game_catalog for exact costs and move stats; docs at ${DOCS}/llms-full.txt.`;
|
|
1647
1856
|
var READ_ONLY_NOTE = `This endpoint is READ-ONLY: it explains the protocol and reads live state for any address.
|
|
1648
1857
|
To play, trade or bridge, run the local server with a wallet phrase: ${DOCS}/ai/mcp`;
|
|
1649
1858
|
function buildServer() {
|
|
1650
1859
|
const server = new McpServer(
|
|
1651
|
-
{ name: "paralith", version: "0.
|
|
1860
|
+
{ name: "paralith", version: "0.3.0" },
|
|
1652
1861
|
{ instructions: READ_ONLY ? `${READ_ONLY_NOTE}
|
|
1653
1862
|
|
|
1654
1863
|
${INSTRUCTIONS}` : INSTRUCTIONS }
|
|
@@ -1679,7 +1888,7 @@ ${INSTRUCTIONS}` : INSTRUCTIONS }
|
|
|
1679
1888
|
server,
|
|
1680
1889
|
"read_state",
|
|
1681
1890
|
`Read any published key of any process, free: /<process>~process@1.0/now/<key>. process is an id or an alias (${Object.keys(PROCESS_ALIASES).join(", ")}). Returns null when absent.`,
|
|
1682
|
-
{ process:
|
|
1891
|
+
{ process: z9.string(), key: z9.string() },
|
|
1683
1892
|
async ({ process: process2, key }) => readKey(process2, key),
|
|
1684
1893
|
READ
|
|
1685
1894
|
);
|
|
@@ -1688,10 +1897,10 @@ ${INSTRUCTIONS}` : INSTRUCTIONS }
|
|
|
1688
1897
|
"send_message",
|
|
1689
1898
|
"Escape hatch: sign and send a raw message to any process and return its reply. Prefer the specific tools; use this only for an action they do not cover. Tag values must be strings; never use a tag named Target.",
|
|
1690
1899
|
{
|
|
1691
|
-
process:
|
|
1692
|
-
tags:
|
|
1693
|
-
data:
|
|
1694
|
-
push_outbox:
|
|
1900
|
+
process: z9.string(),
|
|
1901
|
+
tags: z9.record(z9.string(), z9.string()).describe('e.g. {"Action": "Pass.Info"}'),
|
|
1902
|
+
data: z9.string().optional(),
|
|
1903
|
+
push_outbox: z9.boolean().optional().describe("Deliver the messages this one emits to other processes (e.g. a Transfer to a process).")
|
|
1695
1904
|
},
|
|
1696
1905
|
async ({ process: process2, tags: tags2, data, push_outbox }) => {
|
|
1697
1906
|
if (Object.keys(tags2).some((k) => k.toLowerCase() === "target")) throw new Error("Target is not a usable tag name.");
|
|
@@ -1720,6 +1929,8 @@ ${INSTRUCTIONS}` : INSTRUCTIONS }
|
|
|
1720
1929
|
registerBridge(server);
|
|
1721
1930
|
registerDao(server);
|
|
1722
1931
|
registerVaults(server);
|
|
1932
|
+
registerShow(server);
|
|
1933
|
+
registerProgress(server);
|
|
1723
1934
|
return server;
|
|
1724
1935
|
}
|
|
1725
1936
|
|