balchemy 0.1.19 → 0.1.21
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/LICENSE +2 -2
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/dist/tui/AgentBridge.d.ts +5 -0
- package/dist/tui/AgentBridge.d.ts.map +1 -1
- package/dist/tui/AgentBridge.js +355 -29
- package/dist/tui/AgentBridge.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +22 -7
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/ChatPanel.d.ts +2 -1
- package/dist/tui/ChatPanel.d.ts.map +1 -1
- package/dist/tui/ChatPanel.js +43 -20
- package/dist/tui/ChatPanel.js.map +1 -1
- package/dist/tui/StatusPanel.d.ts +4 -1
- package/dist/tui/StatusPanel.d.ts.map +1 -1
- package/dist/tui/StatusPanel.js +43 -18
- package/dist/tui/StatusPanel.js.map +1 -1
- package/dist/tui/setup-guidance.d.ts +7 -0
- package/dist/tui/setup-guidance.d.ts.map +1 -1
- package/dist/tui/setup-guidance.js +53 -1
- package/dist/tui/setup-guidance.js.map +1 -1
- package/dist/tui/text-layout.d.ts +7 -0
- package/dist/tui/text-layout.d.ts.map +1 -0
- package/dist/tui/text-layout.js +136 -0
- package/dist/tui/text-layout.js.map +1 -0
- package/package.json +2 -2
- package/templates/agent.config.yaml +71 -0
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2025 Balchemy Team
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,25 @@ function ask(rl, question, defaultVal = "") {
|
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
+
function parseSemver(value) {
|
|
41
|
+
const match = value.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
42
|
+
if (!match)
|
|
43
|
+
return null;
|
|
44
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
45
|
+
}
|
|
46
|
+
function isNewerVersion(latest, current) {
|
|
47
|
+
const latestParts = parseSemver(latest);
|
|
48
|
+
const currentParts = parseSemver(current);
|
|
49
|
+
if (!latestParts || !currentParts)
|
|
50
|
+
return latest !== current;
|
|
51
|
+
for (let index = 0; index < latestParts.length; index += 1) {
|
|
52
|
+
if (latestParts[index] > currentParts[index])
|
|
53
|
+
return true;
|
|
54
|
+
if (latestParts[index] < currentParts[index])
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
40
59
|
async function checkForUpdate() {
|
|
41
60
|
try {
|
|
42
61
|
const res = await fetch("https://registry.npmjs.org/balchemy/latest", {
|
|
@@ -52,7 +71,7 @@ async function checkForUpdate() {
|
|
|
52
71
|
const require = createRequire(import.meta.url);
|
|
53
72
|
const pkg = require("../package.json");
|
|
54
73
|
const current = pkg.version;
|
|
55
|
-
if (latest
|
|
74
|
+
if (isNewerVersion(latest, current)) {
|
|
56
75
|
process.stdout.write(`\n ${G}Update available${R} ${D}${current}${R} → ${T}${latest}${R}\n`);
|
|
57
76
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
58
77
|
const answer = await ask(rl, `${W}Update now?${R} (Y/n)`, "y");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAgB,MAAM,kBAAkB,CAAC;AAEvE,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAExC,MAAM,CAAC,GAAG,sBAAsB,CAAC;AACjC,MAAM,CAAC,GAAG,sBAAsB,CAAC;AACjC,MAAM,CAAC,GAAG,YAAY,CAAC;AACvB,MAAM,CAAC,GAAG,gBAAgB,CAAC;AAC3B,MAAM,CAAC,GAAG,SAAS,CAAC;AAEpB,SAAS,iBAAiB,CAAC,KAAa,EAAE,IAA6C;IACrF,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,GAAG,CAAC,EAAsB,EAAE,QAAgB,EAAE,UAAU,GAAG,EAAE;IACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,QAAQ,GAAG,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE;YACvD,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,4CAA4C,EAAE;YACpE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAE1B,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;QAC9D,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;QAE5B,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ export declare class AgentBridge {
|
|
|
14
14
|
private lowBalanceWarned;
|
|
15
15
|
private pendingLoopConfig;
|
|
16
16
|
private setupPollTimer;
|
|
17
|
+
private setupFlow;
|
|
17
18
|
constructor(config: TuiConfig, setters: StateSetters);
|
|
18
19
|
/**
|
|
19
20
|
* Start the bridge: init ChatAgent, start AgentLoop + SSE.
|
|
@@ -29,6 +30,10 @@ export declare class AgentBridge {
|
|
|
29
30
|
/** Start AgentLoop if setup just completed during this session. */
|
|
30
31
|
private tryStartLoop;
|
|
31
32
|
private startSetupPolling;
|
|
33
|
+
private beginSetupFlow;
|
|
34
|
+
private setupPromptFor;
|
|
35
|
+
private handleSetupInput;
|
|
36
|
+
private callSetupAgent;
|
|
32
37
|
private applyToolResult;
|
|
33
38
|
private applyPortfolioSnapshot;
|
|
34
39
|
private upsertWallet;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentBridge.d.ts","sourceRoot":"","sources":["../../src/tui/AgentBridge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAa,SAAS,EAAc,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"AgentBridge.d.ts","sourceRoot":"","sources":["../../src/tui/AgentBridge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAa,SAAS,EAAc,MAAM,YAAY,CAAC;AAoQ5F,KAAK,YAAY,GAAG;IAClB,UAAU,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IACvC,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,UAAU,KAAK,IAAI,CAAC;IAC/D,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD,CAAC;AAqGF,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAC3C,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,iBAAiB,CAAgC;IACzD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,SAAS,CAA+B;gBAEpC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY;IAmBpD;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsH5B,yEAAyE;YAC3D,KAAK;IAwBb,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,mFAAmF;IAC7E,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAW5C,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgClD,mEAAmE;YACrD,YAAY;IAkB1B,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,cAAc;YAuBR,gBAAgB;YAsMhB,cAAc;IAiB5B,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,YAAY;YAON,0BAA0B;IAuCxC,wFAAwF;YAC1E,gBAAgB;IAa9B,OAAO,CAAC,eAAe;IAIvB,4EAA4E;IACtE,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAW/B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BnC,gEAAgE;IAC1D,mBAAmB,IAAI,OAAO,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAwCjF,kGAAkG;IAC5F,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASnD,gFAAgF;IAC1E,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrD,2FAA2F;IAC3F,OAAO,CAAC,WAAW;IAWnB,4FAA4F;IAC5F,cAAc,IAAI;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAkB3E,OAAO,CAAC,eAAe;IAGvB,OAAO,CAAC,gBAAgB;IAGxB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,eAAe;CAKxB"}
|
package/dist/tui/AgentBridge.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { AgentLoop, connectMcp } from "@balchemyai/agent-sdk";
|
|
4
4
|
import { ChatAgent } from "./ChatAgent.js";
|
|
5
|
-
import { buildSetupRequiredMessage, parseSetupStatusSnapshot, } from "./setup-guidance.js";
|
|
5
|
+
import { buildSetupRequiredMessage, getInitialSetupStep, isSetupReady, parseNetworkSelection, parseSetupStatusSnapshot, } from "./setup-guidance.js";
|
|
6
6
|
import { buildStrategyUpdateArgs } from "./session-sync.js";
|
|
7
7
|
import { loadAgent } from "../agent-store.js";
|
|
8
8
|
/** Truncate verbose API errors (429 JSON blobs, stack traces) to a readable one-liner. */
|
|
@@ -80,9 +80,9 @@ function firstNumber(source, keys) {
|
|
|
80
80
|
}
|
|
81
81
|
function normalizeChain(value) {
|
|
82
82
|
const raw = String(value ?? "").toLowerCase();
|
|
83
|
-
if (raw === "sol" || raw === "solana")
|
|
83
|
+
if (raw === "sol" || raw === "solana" || raw === "solana-devnet" || raw === "devnet")
|
|
84
84
|
return "solana";
|
|
85
|
-
if (raw === "base" || raw === "evm" || raw === "ethereum" || raw === "eth" || raw === "eip155" || raw === "1" || raw === "8453")
|
|
85
|
+
if (raw === "base" || raw === "base-sepolia" || raw === "evm" || raw === "ethereum" || raw === "eth" || raw === "eip155" || raw === "1" || raw === "8453" || raw === "84532")
|
|
86
86
|
return "base";
|
|
87
87
|
return null;
|
|
88
88
|
}
|
|
@@ -160,7 +160,7 @@ function collectWallets(source) {
|
|
|
160
160
|
chain: funding.chain ?? funding.chainId ?? "base",
|
|
161
161
|
}));
|
|
162
162
|
}
|
|
163
|
-
for (const key of ["status", "setupStatus", "data", "snapshot"]) {
|
|
163
|
+
for (const key of ["status", "setupStatus", "data", "snapshot", "portfolio"]) {
|
|
164
164
|
const nested = asRecord(source[key]);
|
|
165
165
|
if (nested) {
|
|
166
166
|
for (const wallet of collectWallets(nested))
|
|
@@ -169,6 +169,12 @@ function collectWallets(source) {
|
|
|
169
169
|
}
|
|
170
170
|
return wallets;
|
|
171
171
|
}
|
|
172
|
+
function readTokenHumanAmount(value) {
|
|
173
|
+
const record = asRecord(value);
|
|
174
|
+
if (!record)
|
|
175
|
+
return undefined;
|
|
176
|
+
return firstNumber(record, ["human", "amount", "balance"]);
|
|
177
|
+
}
|
|
172
178
|
function sumWalletBalances(source) {
|
|
173
179
|
const balances = readRecords(source.walletBalances);
|
|
174
180
|
let balanceSol = 0;
|
|
@@ -194,6 +200,29 @@ function sumWalletBalances(source) {
|
|
|
194
200
|
hasUsd = true;
|
|
195
201
|
}
|
|
196
202
|
}
|
|
203
|
+
const wallets = asRecord(source.wallets);
|
|
204
|
+
if (wallets) {
|
|
205
|
+
for (const walletValue of Object.values(wallets)) {
|
|
206
|
+
const wallet = asRecord(walletValue);
|
|
207
|
+
const walletBalances = asRecord(wallet?.balances);
|
|
208
|
+
if (!walletBalances)
|
|
209
|
+
continue;
|
|
210
|
+
for (const [symbol, tokenBalance] of Object.entries(walletBalances)) {
|
|
211
|
+
const amount = readTokenHumanAmount(tokenBalance);
|
|
212
|
+
if (amount === undefined)
|
|
213
|
+
continue;
|
|
214
|
+
const upperSymbol = symbol.toUpperCase();
|
|
215
|
+
if (upperSymbol === "SOL") {
|
|
216
|
+
balanceSol += amount;
|
|
217
|
+
hasSol = true;
|
|
218
|
+
}
|
|
219
|
+
if (upperSymbol === "USDC" || upperSymbol === "TUSD" || upperSymbol === "USD") {
|
|
220
|
+
balanceUsd += amount;
|
|
221
|
+
hasUsd = true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
197
226
|
return {
|
|
198
227
|
...(hasSol ? { balanceSol } : {}),
|
|
199
228
|
...(hasUsd ? { balanceUsd } : {}),
|
|
@@ -210,6 +239,75 @@ function collectPositions(source) {
|
|
|
210
239
|
return [{ token, action: "buy", amount, timestamp: Date.now() }];
|
|
211
240
|
});
|
|
212
241
|
}
|
|
242
|
+
function isEvmAddress(value) {
|
|
243
|
+
return /^0x[a-fA-F0-9]{40}$/.test(value.trim());
|
|
244
|
+
}
|
|
245
|
+
function isSolanaAddress(value) {
|
|
246
|
+
return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value.trim());
|
|
247
|
+
}
|
|
248
|
+
function isAffirmative(value) {
|
|
249
|
+
const normalized = value.trim().toLowerCase();
|
|
250
|
+
return ["y", "yes", "yep", "yeah", "evet", "ok", "okay", "tamam", "onay", "onayliyorum"].includes(normalized);
|
|
251
|
+
}
|
|
252
|
+
function isNegative(value) {
|
|
253
|
+
const normalized = value.trim().toLowerCase();
|
|
254
|
+
return ["n", "no", "nope", "hayir", "hayir istemiyorum", "iptal", "degistir"].includes(normalized);
|
|
255
|
+
}
|
|
256
|
+
function parseSlippageBps(value) {
|
|
257
|
+
const normalized = value.trim().toLowerCase();
|
|
258
|
+
const match = normalized.match(/([0-9]+(?:[.,][0-9]+)?)/);
|
|
259
|
+
if (!match)
|
|
260
|
+
return null;
|
|
261
|
+
const numeric = Number(match[1].replace(",", "."));
|
|
262
|
+
if (!Number.isFinite(numeric) || numeric <= 0)
|
|
263
|
+
return null;
|
|
264
|
+
const explicitBps = /\b(bps|basis)\b/.test(normalized);
|
|
265
|
+
const bps = explicitBps ? Math.round(numeric) : Math.round(numeric * 100);
|
|
266
|
+
if (bps < 1 || bps > 5_000)
|
|
267
|
+
return null;
|
|
268
|
+
return bps;
|
|
269
|
+
}
|
|
270
|
+
function parseTradeLimits(value) {
|
|
271
|
+
const solMatch = value.match(/([0-9]+(?:[.,][0-9]+)?)\s*(?:sol)\b/i);
|
|
272
|
+
const usdMatch = value.match(/(?:\$|usd\s*)\s*([0-9]+(?:[.,][0-9]+)?)/i)
|
|
273
|
+
?? value.match(/([0-9]+(?:[.,][0-9]+)?)\s*(?:usd|usdc|dollar)\b/i);
|
|
274
|
+
const maxTradeSol = solMatch ? Number(solMatch[1].replace(",", ".")) : undefined;
|
|
275
|
+
const maxTradeUsd = usdMatch ? Number(usdMatch[1].replace(",", ".")) : undefined;
|
|
276
|
+
return {
|
|
277
|
+
...(maxTradeSol !== undefined && Number.isFinite(maxTradeSol) ? { maxTradeSol } : {}),
|
|
278
|
+
...(maxTradeUsd !== undefined && Number.isFinite(maxTradeUsd) ? { maxTradeUsd } : {}),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function formatChains(chains) {
|
|
282
|
+
return chains.map((chain) => chain === "solana" ? "Solana Devnet" : "Base Sepolia").join(" + ");
|
|
283
|
+
}
|
|
284
|
+
function chainTitle(chain) {
|
|
285
|
+
return chain === "solana" ? "Solana" : "Base";
|
|
286
|
+
}
|
|
287
|
+
function extractMasterKey(source) {
|
|
288
|
+
const direct = firstString(source.masterKey, source.master_key);
|
|
289
|
+
if (direct)
|
|
290
|
+
return direct;
|
|
291
|
+
const reply = firstString(source.reply, source.message);
|
|
292
|
+
if (!reply)
|
|
293
|
+
return null;
|
|
294
|
+
const match = reply.match(/master key(?:\s+is)?\s*:\s*([^\s—]+)/i);
|
|
295
|
+
return match?.[1] ?? null;
|
|
296
|
+
}
|
|
297
|
+
function buildCombinedStrategy(flow) {
|
|
298
|
+
if (flow.strategyText)
|
|
299
|
+
return flow.strategyText;
|
|
300
|
+
const chainStrategies = flow.chainStrategies ?? {};
|
|
301
|
+
const parts = [];
|
|
302
|
+
if (chainStrategies.solana)
|
|
303
|
+
parts.push(`Solana strategy:\n${chainStrategies.solana}`);
|
|
304
|
+
if (chainStrategies.base)
|
|
305
|
+
parts.push(`Base strategy:\n${chainStrategies.base}`);
|
|
306
|
+
return parts.join("\n\n");
|
|
307
|
+
}
|
|
308
|
+
function nextStrategyChain(chains, chainStrategies) {
|
|
309
|
+
return chains.find((chain) => !chainStrategies[chain]) ?? null;
|
|
310
|
+
}
|
|
213
311
|
export class AgentBridge {
|
|
214
312
|
loop = null;
|
|
215
313
|
mcp;
|
|
@@ -220,6 +318,7 @@ export class AgentBridge {
|
|
|
220
318
|
lowBalanceWarned = false;
|
|
221
319
|
pendingLoopConfig = null;
|
|
222
320
|
setupPollTimer = null;
|
|
321
|
+
setupFlow = null;
|
|
223
322
|
constructor(config, setters) {
|
|
224
323
|
this.config = config;
|
|
225
324
|
this.setters = setters;
|
|
@@ -336,32 +435,21 @@ export class AgentBridge {
|
|
|
336
435
|
provider: resolveProviderLabel(this.config.llmProvider, this.config.llmBaseUrl),
|
|
337
436
|
model: this.config.llmModel,
|
|
338
437
|
}));
|
|
339
|
-
// Input is ready now
|
|
340
|
-
|
|
438
|
+
// Input is ready now. Setup must be deterministic; do not let an LLM drive it.
|
|
439
|
+
if (setupComplete) {
|
|
440
|
+
void this.greet(true);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
this.beginSetupFlow(setupStatus);
|
|
444
|
+
}
|
|
341
445
|
}
|
|
342
446
|
/** Background greeting after start — does not block input activation. */
|
|
343
|
-
async greet(setupComplete
|
|
447
|
+
async greet(setupComplete) {
|
|
344
448
|
if (!this.chatAgent)
|
|
345
449
|
return;
|
|
346
450
|
if (setupComplete) {
|
|
347
451
|
await this.checkBalance();
|
|
348
452
|
}
|
|
349
|
-
if (!setupComplete) {
|
|
350
|
-
try {
|
|
351
|
-
const reply = await this.chatAgent.chat("Start my Balchemy setup. First call setup_agent get_status, then ask me only the next required setup question.", (name, result) => {
|
|
352
|
-
this.applyToolResult(name, result);
|
|
353
|
-
if (name !== "setup_agent") {
|
|
354
|
-
this.addSystemMessage(`Tool: ${name}`);
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
this.addAgentMessage(reply || buildSetupRequiredMessage(setupStatus ?? {}));
|
|
358
|
-
}
|
|
359
|
-
catch (err) {
|
|
360
|
-
this.addAgentMessage(buildSetupRequiredMessage(setupStatus ?? {}));
|
|
361
|
-
this.addErrorMessage(`LLM setup prompt failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
362
|
-
}
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
453
|
try {
|
|
366
454
|
const prompt = "Check my portfolio and status, then greet me. Tell me my balance, wallets, and current strategy. Keep it brief and do not narrate tool calls.";
|
|
367
455
|
const reply = await this.chatAgent.chat(prompt, (name, result) => {
|
|
@@ -397,14 +485,18 @@ export class AgentBridge {
|
|
|
397
485
|
await this.start();
|
|
398
486
|
}
|
|
399
487
|
async sendUserMessage(text) {
|
|
400
|
-
if (!this.chatAgent)
|
|
401
|
-
return;
|
|
402
488
|
this.setters.addMessage({
|
|
403
489
|
id: randomUUID(),
|
|
404
490
|
type: "user",
|
|
405
491
|
text,
|
|
406
492
|
timestamp: Date.now(),
|
|
407
493
|
});
|
|
494
|
+
if (this.setupFlow) {
|
|
495
|
+
await this.handleSetupInput(text);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (!this.chatAgent)
|
|
499
|
+
return;
|
|
408
500
|
try {
|
|
409
501
|
const reply = await this.chatAgent.chat(text, (name, result) => {
|
|
410
502
|
this.applyToolResult(name, result);
|
|
@@ -420,7 +512,7 @@ export class AgentBridge {
|
|
|
420
512
|
}
|
|
421
513
|
/** Start AgentLoop if setup just completed during this session. */
|
|
422
514
|
async tryStartLoop() {
|
|
423
|
-
if (this.loop || !this.pendingLoopConfig)
|
|
515
|
+
if (this.loop || !this.pendingLoopConfig || this.setupFlow)
|
|
424
516
|
return;
|
|
425
517
|
const setupStatus = await this.fetchSetupStatus();
|
|
426
518
|
const nowComplete = this.isSetupComplete(setupStatus);
|
|
@@ -445,6 +537,240 @@ export class AgentBridge {
|
|
|
445
537
|
}, 10_000);
|
|
446
538
|
this.setupPollTimer.unref();
|
|
447
539
|
}
|
|
540
|
+
beginSetupFlow(status) {
|
|
541
|
+
const snapshot = status ?? {};
|
|
542
|
+
const step = getInitialSetupStep(snapshot);
|
|
543
|
+
this.setupFlow = {
|
|
544
|
+
step,
|
|
545
|
+
...(snapshot.selectedChains && snapshot.selectedChains.length > 0 ? { selectedChains: snapshot.selectedChains } : {}),
|
|
546
|
+
};
|
|
547
|
+
this.addAgentMessage(`${buildSetupRequiredMessage(snapshot)}\n\n${this.setupPromptFor(this.setupFlow.step)}`);
|
|
548
|
+
}
|
|
549
|
+
setupPromptFor(step) {
|
|
550
|
+
switch (step) {
|
|
551
|
+
case "developer-wallet":
|
|
552
|
+
return "Paste your Base/EVM 0x developer wallet. This is the recovery, Hub, and withdrawal wallet. Trading wallets are created separately.";
|
|
553
|
+
case "developer-wallet-confirm":
|
|
554
|
+
return "Paste the same 0x developer wallet again to confirm it.";
|
|
555
|
+
case "networks":
|
|
556
|
+
return "Which networks should this agent trade on: Solana, Base, or both?";
|
|
557
|
+
case "solana-recovery-wallet":
|
|
558
|
+
return "Paste your Solana recovery/withdrawal wallet address. This is separate from the Solana trading wallet I create for execution.";
|
|
559
|
+
case "solana-recovery-wallet-confirm":
|
|
560
|
+
return "Paste the same Solana recovery/withdrawal wallet again to confirm it.";
|
|
561
|
+
case "slippage":
|
|
562
|
+
return "Set slippage in percent or bps. Examples: 1% = 100 bps, 3% = 300 bps, 5% = 500 bps.";
|
|
563
|
+
case "strategy":
|
|
564
|
+
return "Send the hard limits and strategy for this chain. Include max trade size, entry filters, stop loss, take profit, max positions, and tokens/categories to avoid.";
|
|
565
|
+
case "strategy-confirm":
|
|
566
|
+
return "Confirm with 'yes'/'evet', or say 'no'/'hayir' to rewrite the strategy.";
|
|
567
|
+
case "subscriptions":
|
|
568
|
+
return "Create monitoring subscriptions now? For Solana new launches I can enable the testlab launch feed. Answer yes/evet or no/hayir.";
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
async handleSetupInput(text) {
|
|
572
|
+
const flow = this.setupFlow;
|
|
573
|
+
if (!flow)
|
|
574
|
+
return;
|
|
575
|
+
try {
|
|
576
|
+
if (flow.step === "developer-wallet") {
|
|
577
|
+
const wallet = text.trim();
|
|
578
|
+
if (!isEvmAddress(wallet)) {
|
|
579
|
+
this.addAgentMessage("That is not a valid 0x EVM address. Paste a Base/EVM wallet like 0x...");
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
this.setupFlow = { ...flow, step: "developer-wallet-confirm", developerWallet: wallet };
|
|
583
|
+
this.addAgentMessage(this.setupPromptFor("developer-wallet-confirm"));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
if (flow.step === "developer-wallet-confirm") {
|
|
587
|
+
const wallet = text.trim();
|
|
588
|
+
if (!flow.developerWallet || wallet.toLowerCase() !== flow.developerWallet.toLowerCase()) {
|
|
589
|
+
this.setupFlow = { step: "developer-wallet" };
|
|
590
|
+
this.addAgentMessage("The confirmation did not match. Start again by pasting the Base/EVM 0x developer wallet.");
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const structured = await this.callSetupAgent({
|
|
594
|
+
action: "bind_developer_wallet",
|
|
595
|
+
walletAddress: flow.developerWallet,
|
|
596
|
+
walletAddressConfirm: wallet,
|
|
597
|
+
});
|
|
598
|
+
const masterKey = extractMasterKey(structured);
|
|
599
|
+
this.setupFlow = { step: "networks" };
|
|
600
|
+
this.addAgentMessage(masterKey
|
|
601
|
+
? `Developer wallet bound.\n\nCopy and store this master key now:\n${masterKey}\n\nIt is shown once in real environments.\n\n${this.setupPromptFor("networks")}`
|
|
602
|
+
: `Developer wallet bound.\n\n${this.setupPromptFor("networks")}`);
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (flow.step === "networks") {
|
|
606
|
+
const chains = parseNetworkSelection(text);
|
|
607
|
+
if (!chains) {
|
|
608
|
+
this.addAgentMessage("Choose Solana, Base, or both.");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const walletLines = [];
|
|
612
|
+
for (const chain of chains) {
|
|
613
|
+
const structured = await this.callSetupAgent({ action: "create_wallet", chain });
|
|
614
|
+
const address = firstString(structured.address, asRecord(structured.wallet)?.address);
|
|
615
|
+
walletLines.push(`${chainTitle(chain)} trading wallet: ${address ?? "(created)"}`);
|
|
616
|
+
}
|
|
617
|
+
this.setupFlow = {
|
|
618
|
+
step: chains.includes("solana") ? "solana-recovery-wallet" : "slippage",
|
|
619
|
+
selectedChains: chains,
|
|
620
|
+
};
|
|
621
|
+
this.addAgentMessage(`Trading networks configured: ${formatChains(chains)}.\n\nCopyable trading wallet addresses:\n${walletLines.join("\n")}\n\n${this.setupPromptFor(chains.includes("solana") ? "solana-recovery-wallet" : "slippage")}`);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
if (flow.step === "solana-recovery-wallet") {
|
|
625
|
+
const wallet = text.trim();
|
|
626
|
+
if (!isSolanaAddress(wallet)) {
|
|
627
|
+
this.addAgentMessage("That is not a valid Solana wallet address. Paste a base58 Solana public key.");
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
this.setupFlow = { ...flow, step: "solana-recovery-wallet-confirm", solanaRecoveryWallet: wallet };
|
|
631
|
+
this.addAgentMessage(this.setupPromptFor("solana-recovery-wallet-confirm"));
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
if (flow.step === "solana-recovery-wallet-confirm") {
|
|
635
|
+
const wallet = text.trim();
|
|
636
|
+
if (!flow.solanaRecoveryWallet || wallet !== flow.solanaRecoveryWallet) {
|
|
637
|
+
this.setupFlow = {
|
|
638
|
+
step: "solana-recovery-wallet",
|
|
639
|
+
...(flow.developerWallet ? { developerWallet: flow.developerWallet } : {}),
|
|
640
|
+
...(flow.selectedChains ? { selectedChains: flow.selectedChains } : {}),
|
|
641
|
+
};
|
|
642
|
+
this.addAgentMessage("The Solana wallet confirmation did not match. Paste the Solana recovery/withdrawal wallet again.");
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
try {
|
|
646
|
+
await this.callSetupAgent({
|
|
647
|
+
action: "bind_solana_developer_wallet",
|
|
648
|
+
solanaWalletAddress: flow.solanaRecoveryWallet,
|
|
649
|
+
solanaWalletAddressConfirm: wallet,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
catch (err) {
|
|
653
|
+
this.addSystemMessage(`Solana recovery wallet stored locally for this setup. MCP did not bind it directly: ${err instanceof Error ? err.message : String(err)}`);
|
|
654
|
+
}
|
|
655
|
+
this.setupFlow = { ...flow, step: "slippage", solanaRecoveryWallet: wallet };
|
|
656
|
+
this.addAgentMessage(`Solana recovery wallet confirmed:\n${wallet}\n\n${this.setupPromptFor("slippage")}`);
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
if (flow.step === "slippage") {
|
|
660
|
+
const bps = parseSlippageBps(text);
|
|
661
|
+
if (bps === null) {
|
|
662
|
+
this.addAgentMessage("I could not parse that slippage. Send a value like 3%, 300 bps, or 5.");
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
await this.callSetupAgent({ action: "configure_slippage", slippageBps: bps });
|
|
666
|
+
const selectedChains = flow.selectedChains ?? ["solana"];
|
|
667
|
+
const currentStrategyChain = nextStrategyChain(selectedChains, {}) ?? selectedChains[0];
|
|
668
|
+
this.setupFlow = { ...flow, step: "strategy", slippageBps: bps, currentStrategyChain, chainStrategies: {} };
|
|
669
|
+
this.addAgentMessage(`Slippage set to ${bps} bps.\n\n${chainTitle(currentStrategyChain)} strategy:\n${this.setupPromptFor("strategy")}`);
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (flow.step === "strategy") {
|
|
673
|
+
const strategyText = text.trim();
|
|
674
|
+
if (strategyText.length < 20) {
|
|
675
|
+
this.addAgentMessage("The strategy is too short. Include limits, entries, exits, max positions, and avoid rules.");
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
const chainStrategies = {
|
|
679
|
+
...(flow.chainStrategies ?? {}),
|
|
680
|
+
...(flow.currentStrategyChain ? { [flow.currentStrategyChain]: strategyText } : {}),
|
|
681
|
+
};
|
|
682
|
+
const selectedChains = flow.selectedChains ?? (flow.currentStrategyChain ? [flow.currentStrategyChain] : ["solana"]);
|
|
683
|
+
const nextChain = nextStrategyChain(selectedChains, chainStrategies);
|
|
684
|
+
if (nextChain) {
|
|
685
|
+
this.setupFlow = { ...flow, chainStrategies, currentStrategyChain: nextChain };
|
|
686
|
+
this.addAgentMessage(`${chainTitle(flow.currentStrategyChain ?? selectedChains[0])} strategy saved.\n\n${chainTitle(nextChain)} strategy:\n${this.setupPromptFor("strategy")}`);
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const combinedStrategy = buildCombinedStrategy({ ...flow, chainStrategies });
|
|
690
|
+
const limits = parseTradeLimits(combinedStrategy);
|
|
691
|
+
this.setupFlow = { ...flow, ...limits, chainStrategies, step: "strategy-confirm", strategyText: combinedStrategy };
|
|
692
|
+
this.addAgentMessage(`Review before live configuration:\n\n${combinedStrategy}\n\nMax SOL/trade: ${limits.maxTradeSol ?? "not specified"}\nMax USD/trade: ${limits.maxTradeUsd ?? "not specified"}\n\n${this.setupPromptFor("strategy-confirm")}`);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
if (flow.step === "strategy-confirm") {
|
|
696
|
+
if (isNegative(text)) {
|
|
697
|
+
this.setupFlow = {
|
|
698
|
+
step: "strategy",
|
|
699
|
+
...(flow.developerWallet ? { developerWallet: flow.developerWallet } : {}),
|
|
700
|
+
...(flow.solanaRecoveryWallet ? { solanaRecoveryWallet: flow.solanaRecoveryWallet } : {}),
|
|
701
|
+
...(flow.selectedChains ? { selectedChains: flow.selectedChains } : {}),
|
|
702
|
+
...(flow.slippageBps !== undefined ? { slippageBps: flow.slippageBps } : {}),
|
|
703
|
+
chainStrategies: {},
|
|
704
|
+
currentStrategyChain: (flow.selectedChains ?? ["solana"])[0],
|
|
705
|
+
};
|
|
706
|
+
this.addAgentMessage(this.setupPromptFor("strategy"));
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (!isAffirmative(text)) {
|
|
710
|
+
this.addAgentMessage(this.setupPromptFor("strategy-confirm"));
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
if (!flow.strategyText) {
|
|
714
|
+
this.setupFlow = { ...flow, step: "strategy" };
|
|
715
|
+
this.addAgentMessage(this.setupPromptFor("strategy"));
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
await this.callSetupAgent({
|
|
719
|
+
...buildStrategyUpdateArgs(flow.strategyText, false),
|
|
720
|
+
chainStrategies: flow.chainStrategies,
|
|
721
|
+
selectedChains: flow.selectedChains,
|
|
722
|
+
solanaRecoveryWallet: flow.solanaRecoveryWallet,
|
|
723
|
+
...(flow.maxTradeSol !== undefined ? { maxTradeSol: flow.maxTradeSol } : {}),
|
|
724
|
+
...(flow.maxTradeUsd !== undefined ? { maxTradeUsd: flow.maxTradeUsd } : {}),
|
|
725
|
+
});
|
|
726
|
+
this.setupFlow = { ...flow, step: "subscriptions" };
|
|
727
|
+
this.addAgentMessage(`Strategy configured for live execution.\n\n${this.setupPromptFor("subscriptions")}`);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (flow.step === "subscriptions") {
|
|
731
|
+
if (isAffirmative(text)) {
|
|
732
|
+
const chains = flow.selectedChains ?? ["solana"];
|
|
733
|
+
if (chains.includes("solana")) {
|
|
734
|
+
await this.mcp.callTool("create_subscription", {
|
|
735
|
+
type: "new_token_launch",
|
|
736
|
+
chain: "solana",
|
|
737
|
+
filter: { platform: "pumpfun" },
|
|
738
|
+
format: "summary",
|
|
739
|
+
});
|
|
740
|
+
this.addSystemMessage("Tool: create_subscription");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
else if (!isNegative(text)) {
|
|
744
|
+
this.addAgentMessage(this.setupPromptFor("subscriptions"));
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
this.setupFlow = null;
|
|
748
|
+
this.addAgentMessage("Setup is complete. I am starting the agent loop and checking the portfolio now.");
|
|
749
|
+
await this.tryStartLoop();
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
catch (err) {
|
|
753
|
+
this.addErrorMessage(`Setup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
754
|
+
this.addAgentMessage(`${this.setupPromptFor(this.setupFlow?.step ?? flow.step)} Try again.`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
async callSetupAgent(args) {
|
|
758
|
+
const resp = await this.mcp.callTool("setup_agent", args);
|
|
759
|
+
const text = resp.content?.find((c) => c.type === "text")?.text ?? "{}";
|
|
760
|
+
this.applyToolResult("setup_agent", text);
|
|
761
|
+
this.addSystemMessage(`Tool: setup_agent ${String(args.action ?? "")}`.trim());
|
|
762
|
+
const parsed = parseJsonObject(text);
|
|
763
|
+
if (!parsed)
|
|
764
|
+
throw new Error("setup_agent returned non-JSON response");
|
|
765
|
+
const structured = asRecord(parsed.structured) ?? parsed;
|
|
766
|
+
if (parsed.ok === false || structured.error) {
|
|
767
|
+
throw new Error(String(structured.error ?? parsed.error ?? "setup_agent rejected the request"));
|
|
768
|
+
}
|
|
769
|
+
return {
|
|
770
|
+
...parsed,
|
|
771
|
+
...structured,
|
|
772
|
+
};
|
|
773
|
+
}
|
|
448
774
|
applyToolResult(name, resultText) {
|
|
449
775
|
const parsed = parseJsonObject(resultText);
|
|
450
776
|
if (!parsed)
|
|
@@ -473,7 +799,7 @@ export class AgentBridge {
|
|
|
473
799
|
}
|
|
474
800
|
applyPortfolioSnapshot(parsed) {
|
|
475
801
|
const structured = asRecord(parsed.structured);
|
|
476
|
-
const snapshot = asRecord(structured?.snapshot) ?? asRecord(parsed.snapshot) ?? parsed;
|
|
802
|
+
const snapshot = asRecord(structured?.snapshot) ?? asRecord(parsed.snapshot) ?? asRecord(parsed.portfolio) ?? parsed;
|
|
477
803
|
const data = asRecord(snapshot.data);
|
|
478
804
|
const wallets = mergeWallets(collectWallets(snapshot), data ? collectWallets(data) : []);
|
|
479
805
|
const summed = data ? sumWalletBalances(data) : sumWalletBalances(snapshot);
|
|
@@ -555,7 +881,7 @@ export class AgentBridge {
|
|
|
555
881
|
}
|
|
556
882
|
}
|
|
557
883
|
isSetupComplete(status) {
|
|
558
|
-
return status
|
|
884
|
+
return isSetupReady(status);
|
|
559
885
|
}
|
|
560
886
|
/** Silent balance refresh — updates status panel only, no chat messages. */
|
|
561
887
|
async refreshBalance() {
|
|
@@ -576,7 +902,7 @@ export class AgentBridge {
|
|
|
576
902
|
const text = response.content?.find((c) => c.type === "text")?.text ?? "{}";
|
|
577
903
|
const parsed = parseJsonObject(text);
|
|
578
904
|
const snapshot = parsed
|
|
579
|
-
? asRecord(asRecord(parsed.structured)?.snapshot) ?? asRecord(parsed.snapshot) ?? parsed
|
|
905
|
+
? asRecord(asRecord(parsed.structured)?.snapshot) ?? asRecord(parsed.snapshot) ?? asRecord(parsed.portfolio) ?? parsed
|
|
580
906
|
: {};
|
|
581
907
|
const data = asRecord(snapshot.data);
|
|
582
908
|
const sol = firstNumber(snapshot, ["totalValueSol", "portfolioValueSol", "portfolio_value_sol", "total_value_sol"])
|