@astranova-live/cli 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astra.js +432 -129
- package/package.json +1 -1
package/dist/astra.js
CHANGED
|
@@ -59,6 +59,9 @@ function memoryPath(agentName) {
|
|
|
59
59
|
function pendingClaimPath(agentName) {
|
|
60
60
|
return path.join(agentDir(agentName), "pending_claim.json");
|
|
61
61
|
}
|
|
62
|
+
function epochBudgetPath(agentName) {
|
|
63
|
+
return path.join(agentDir(agentName), "epoch_budget.json");
|
|
64
|
+
}
|
|
62
65
|
function cachePath(fileName) {
|
|
63
66
|
return path.join(_root(), ".cache", fileName);
|
|
64
67
|
}
|
|
@@ -99,7 +102,11 @@ var ConfigSchema = z.object({
|
|
|
99
102
|
apiBase: z.string().default("https://agents.astranova.live"),
|
|
100
103
|
preferences: z.object({
|
|
101
104
|
theme: z.enum(["dark", "light"]).default("dark")
|
|
102
|
-
}).default({})
|
|
105
|
+
}).default({}),
|
|
106
|
+
autopilot: z.object({
|
|
107
|
+
mode: z.enum(["off", "semi", "full"]).default("off"),
|
|
108
|
+
intervalMs: z.number().min(6e4).max(36e5).default(3e5)
|
|
109
|
+
}).default({ mode: "off", intervalMs: 3e5 })
|
|
103
110
|
});
|
|
104
111
|
var CredentialsSchema = z.object({
|
|
105
112
|
agent_name: z.string(),
|
|
@@ -164,6 +171,15 @@ function saveConfig(config) {
|
|
|
164
171
|
ensureBaseStructure();
|
|
165
172
|
writeFileSecure(configPath(), JSON.stringify(config, null, 2));
|
|
166
173
|
}
|
|
174
|
+
function loadAutopilotConfig() {
|
|
175
|
+
const config = loadConfig();
|
|
176
|
+
return config?.autopilot ?? { mode: "off", intervalMs: 3e5 };
|
|
177
|
+
}
|
|
178
|
+
function saveAutopilotConfig(autopilot) {
|
|
179
|
+
const config = loadConfig();
|
|
180
|
+
if (!config) return;
|
|
181
|
+
saveConfig({ ...config, autopilot });
|
|
182
|
+
}
|
|
167
183
|
function loadState() {
|
|
168
184
|
return readJsonFile(statePath(), StateSchema);
|
|
169
185
|
}
|
|
@@ -253,6 +269,22 @@ function loadPendingClaim(agentName) {
|
|
|
253
269
|
return null;
|
|
254
270
|
}
|
|
255
271
|
}
|
|
272
|
+
function loadEpochBudget(agentName) {
|
|
273
|
+
const filePath = epochBudgetPath(agentName);
|
|
274
|
+
if (!fs2.existsSync(filePath)) return null;
|
|
275
|
+
try {
|
|
276
|
+
return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
|
|
277
|
+
} catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function saveEpochBudget(agentName, data) {
|
|
282
|
+
try {
|
|
283
|
+
ensureDir(agentDir(agentName));
|
|
284
|
+
writeFileSecure(epochBudgetPath(agentName), JSON.stringify(data));
|
|
285
|
+
} catch {
|
|
286
|
+
}
|
|
287
|
+
}
|
|
256
288
|
function clearPendingClaim(agentName) {
|
|
257
289
|
const filePath = pendingClaimPath(agentName);
|
|
258
290
|
if (fs2.existsSync(filePath)) {
|
|
@@ -1054,7 +1086,8 @@ async function runOnboarding() {
|
|
|
1054
1086
|
model,
|
|
1055
1087
|
auth,
|
|
1056
1088
|
apiBase: "https://agents.astranova.live",
|
|
1057
|
-
preferences: { theme: "dark" }
|
|
1089
|
+
preferences: { theme: "dark" },
|
|
1090
|
+
autopilot: { mode: "off", intervalMs: 3e5 }
|
|
1058
1091
|
};
|
|
1059
1092
|
saveConfig(config);
|
|
1060
1093
|
clack3.log.success(`Provider set to ${provider} (${model})`);
|
|
@@ -1358,17 +1391,49 @@ function loadMemory(agentName) {
|
|
|
1358
1391
|
}
|
|
1359
1392
|
|
|
1360
1393
|
// src/ui/App.tsx
|
|
1361
|
-
import { useState as useState4, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
1394
|
+
import { useState as useState4, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
1362
1395
|
import { Box as Box7, Text as Text8, useApp, useInput } from "ink";
|
|
1363
1396
|
|
|
1364
1397
|
// src/ui/StatusBar.tsx
|
|
1365
1398
|
import React, { useState, useEffect, useRef, useCallback } from "react";
|
|
1366
1399
|
import { Box, Text } from "ink";
|
|
1400
|
+
|
|
1401
|
+
// src/autopilot/scheduler.ts
|
|
1402
|
+
var EPOCH_BUDGET = 10;
|
|
1403
|
+
var BUDGET_BUFFER = 2;
|
|
1404
|
+
var SEMI_TRIGGER_MSG = "AUTOPILOT CHECK: Analyze market and propose a trade if signal is clear. Ask me to confirm before executing.";
|
|
1405
|
+
var FULL_TRIGGER_MSG = "AUTOPILOT CHECK: Analyze market and execute a trade if signal is clear. If uncertain, skip. Keep response to 2-3 lines max.";
|
|
1406
|
+
function buildAutopilotTrigger(mode) {
|
|
1407
|
+
switch (mode) {
|
|
1408
|
+
case "semi":
|
|
1409
|
+
return SEMI_TRIGGER_MSG;
|
|
1410
|
+
case "full":
|
|
1411
|
+
return FULL_TRIGGER_MSG;
|
|
1412
|
+
case "off":
|
|
1413
|
+
return null;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
function formatInterval(ms) {
|
|
1417
|
+
const minutes = Math.round(ms / 6e4);
|
|
1418
|
+
return `${minutes}m`;
|
|
1419
|
+
}
|
|
1420
|
+
function parseInterval(input) {
|
|
1421
|
+
const match = input.match(/^(\d+)m$/);
|
|
1422
|
+
if (!match) return null;
|
|
1423
|
+
const minutes = parseInt(match[1], 10);
|
|
1424
|
+
if (minutes < 1 || minutes > 60) return null;
|
|
1425
|
+
return minutes * 6e4;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
// src/ui/StatusBar.tsx
|
|
1367
1429
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
1368
|
-
var POLL_INTERVAL_MS =
|
|
1430
|
+
var POLL_INTERVAL_MS = 6e4;
|
|
1369
1431
|
var StatusBar = React.memo(function StatusBar2({
|
|
1370
1432
|
agentName,
|
|
1371
|
-
journeyStage
|
|
1433
|
+
journeyStage,
|
|
1434
|
+
autopilotMode = "off",
|
|
1435
|
+
autopilotIntervalMs = 3e5,
|
|
1436
|
+
onEpochChange
|
|
1372
1437
|
}) {
|
|
1373
1438
|
const [data, setData] = useState({ market: null, portfolio: null });
|
|
1374
1439
|
const mounted = useRef(true);
|
|
@@ -1383,7 +1448,10 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
1383
1448
|
market: marketRes ?? prev.market,
|
|
1384
1449
|
portfolio: portfolioRes ?? prev.portfolio
|
|
1385
1450
|
}));
|
|
1386
|
-
|
|
1451
|
+
if (marketRes && onEpochChange) {
|
|
1452
|
+
onEpochChange(marketRes.epochId);
|
|
1453
|
+
}
|
|
1454
|
+
}, [agentName, onEpochChange]);
|
|
1387
1455
|
useEffect(() => {
|
|
1388
1456
|
mounted.current = true;
|
|
1389
1457
|
if (!canFetchData) return;
|
|
@@ -1395,50 +1463,64 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
1395
1463
|
};
|
|
1396
1464
|
}, [canFetchData, poll]);
|
|
1397
1465
|
const { market, portfolio } = data;
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
/* @__PURE__ */
|
|
1401
|
-
|
|
1402
|
-
canFetchData && market && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1403
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1404
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children: "$NOVA " }),
|
|
1405
|
-
/* @__PURE__ */ jsx(Text, { color: "white", children: formatPrice(market.price) }),
|
|
1406
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1407
|
-
/* @__PURE__ */ jsx(Text, { color: moodColor(market.mood), children: market.mood })
|
|
1408
|
-
] }),
|
|
1409
|
-
canFetchData && portfolio && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1466
|
+
const apActive = autopilotMode !== "off";
|
|
1467
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsxs(Box, { paddingX: 1, justifyContent: "space-between", children: [
|
|
1468
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1469
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "#00ff00", children: "AstraNova" }),
|
|
1410
1470
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1411
|
-
/* @__PURE__ */
|
|
1412
|
-
|
|
1413
|
-
"
|
|
1471
|
+
/* @__PURE__ */ jsx(Text, { color: "#ff8800", children: agentName }),
|
|
1472
|
+
canFetchData && market && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1473
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1474
|
+
/* @__PURE__ */ jsx(Text, { color: "#ffff00", children: "$NOVA " }),
|
|
1475
|
+
/* @__PURE__ */ jsx(Text, { color: "white", children: formatPrice(market.price) }),
|
|
1476
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1477
|
+
/* @__PURE__ */ jsx(Text, { color: moodColor(market.mood), children: market.mood })
|
|
1414
1478
|
] }),
|
|
1415
|
-
|
|
1479
|
+
canFetchData && portfolio && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1416
1480
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1417
|
-
/* @__PURE__ */ jsxs(Text, { color: "
|
|
1418
|
-
formatNum(portfolio.
|
|
1419
|
-
" $
|
|
1481
|
+
/* @__PURE__ */ jsxs(Text, { color: "#00ffff", children: [
|
|
1482
|
+
formatNum(portfolio.cash),
|
|
1483
|
+
" $SIM"
|
|
1484
|
+
] }),
|
|
1485
|
+
portfolio.tokens > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1486
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1487
|
+
/* @__PURE__ */ jsxs(Text, { color: "#ff00ff", children: [
|
|
1488
|
+
formatNum(portfolio.tokens),
|
|
1489
|
+
" $NOVA"
|
|
1490
|
+
] })
|
|
1491
|
+
] }),
|
|
1492
|
+
portfolio.pnl !== 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1493
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1494
|
+
/* @__PURE__ */ jsxs(Text, { color: portfolio.pnl >= 0 ? "#00ff00" : "#ff4444", children: [
|
|
1495
|
+
"P&L ",
|
|
1496
|
+
portfolio.pnl >= 0 ? "+" : "",
|
|
1497
|
+
formatNum(portfolio.pnl),
|
|
1498
|
+
" (",
|
|
1499
|
+
portfolio.pnlPct >= 0 ? "+" : "",
|
|
1500
|
+
portfolio.pnlPct.toFixed(1),
|
|
1501
|
+
"%)"
|
|
1502
|
+
] })
|
|
1503
|
+
] }),
|
|
1504
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1505
|
+
/* @__PURE__ */ jsxs(Text, { color: "#e2f902", children: [
|
|
1506
|
+
"Val ",
|
|
1507
|
+
formatNum(portfolio.portfolioValue)
|
|
1420
1508
|
] })
|
|
1421
1509
|
] }),
|
|
1422
|
-
|
|
1510
|
+
!canFetchData && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1423
1511
|
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1424
|
-
/* @__PURE__ */
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
portfolio.pnlPct >= 0 ? "+" : "",
|
|
1430
|
-
portfolio.pnlPct.toFixed(1),
|
|
1431
|
-
"%)"
|
|
1432
|
-
] })
|
|
1512
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "pending verification" })
|
|
1513
|
+
] }),
|
|
1514
|
+
canFetchData && !market && !portfolio && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1515
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1516
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "loading..." })
|
|
1433
1517
|
] })
|
|
1434
1518
|
] }),
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u2502 " }),
|
|
1441
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "loading..." })
|
|
1519
|
+
apActive && /* @__PURE__ */ jsxs(Text, { color: "#00ff00", children: [
|
|
1520
|
+
"AP: \u25CF ",
|
|
1521
|
+
autopilotMode.toUpperCase(),
|
|
1522
|
+
" ",
|
|
1523
|
+
formatInterval(autopilotIntervalMs)
|
|
1442
1524
|
] })
|
|
1443
1525
|
] }) });
|
|
1444
1526
|
});
|
|
@@ -1457,12 +1539,12 @@ function moodColor(mood) {
|
|
|
1457
1539
|
switch (mood) {
|
|
1458
1540
|
case "euphoria":
|
|
1459
1541
|
case "bullish":
|
|
1460
|
-
return "
|
|
1542
|
+
return "#00ff00";
|
|
1461
1543
|
case "fear":
|
|
1462
1544
|
case "bearish":
|
|
1463
|
-
return "
|
|
1545
|
+
return "#ff4444";
|
|
1464
1546
|
case "crab":
|
|
1465
|
-
return "
|
|
1547
|
+
return "#ffff00";
|
|
1466
1548
|
default:
|
|
1467
1549
|
return "white";
|
|
1468
1550
|
}
|
|
@@ -1474,7 +1556,8 @@ async function fetchMarket(agentName) {
|
|
|
1474
1556
|
const m = d.market ?? d;
|
|
1475
1557
|
return {
|
|
1476
1558
|
price: m.price ?? 0,
|
|
1477
|
-
mood: m.mood ?? ""
|
|
1559
|
+
mood: m.mood ?? "",
|
|
1560
|
+
epochId: m.epoch?.global ?? 0
|
|
1478
1561
|
};
|
|
1479
1562
|
}
|
|
1480
1563
|
async function fetchPortfolio(agentName) {
|
|
@@ -1487,9 +1570,13 @@ async function fetchPortfolio(agentName) {
|
|
|
1487
1570
|
if (!result.ok) return null;
|
|
1488
1571
|
const d = result.data;
|
|
1489
1572
|
const p = d.portfolio ?? d;
|
|
1573
|
+
const cash = p.cash ?? 0;
|
|
1574
|
+
const tokens = p.tokens ?? 0;
|
|
1575
|
+
const currentPrice = p.currentPrice ?? 0;
|
|
1490
1576
|
return {
|
|
1491
|
-
cash
|
|
1492
|
-
tokens
|
|
1577
|
+
cash,
|
|
1578
|
+
tokens,
|
|
1579
|
+
portfolioValue: p.portfolioValue ?? cash + tokens * currentPrice,
|
|
1493
1580
|
pnl: p.pnl ?? 0,
|
|
1494
1581
|
pnlPct: p.pnlPct ?? 0
|
|
1495
1582
|
};
|
|
@@ -1513,35 +1600,26 @@ function PortfolioCard({ data }) {
|
|
|
1513
1600
|
const pnlPct = data.pnlPct ?? 0;
|
|
1514
1601
|
const earned = data.totalEarned ? Number(data.totalEarned) / 1e9 : 0;
|
|
1515
1602
|
const claimable = data.claimable ? Number(data.claimable) / 1e9 : 0;
|
|
1516
|
-
const pnlColor = pnl >= 0 ? "
|
|
1603
|
+
const pnlColor = pnl >= 0 ? "#00ff00" : "#ff4444";
|
|
1517
1604
|
const pnlSign = pnl >= 0 ? "+" : "";
|
|
1518
|
-
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column",
|
|
1519
|
-
/* @__PURE__ */ jsx2(Box2, {
|
|
1520
|
-
/* @__PURE__ */
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
value: data.hasWallet ? "registered" : data.walletLocal ? "needs registration" : "not set",
|
|
1534
|
-
color: data.hasWallet ? "green" : data.walletLocal ? "yellow" : "gray"
|
|
1535
|
-
}
|
|
1536
|
-
)
|
|
1537
|
-
] })
|
|
1538
|
-
] }),
|
|
1605
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingLeft: 1, marginY: 1, children: [
|
|
1606
|
+
/* @__PURE__ */ jsx2(Box2, { marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { bold: true, color: "#00ffff", children: "Portfolio Overview" }) }),
|
|
1607
|
+
/* @__PURE__ */ jsx2(Row, { label: "$SIM Balance", value: formatNum2(cash), color: "#00ffff" }),
|
|
1608
|
+
/* @__PURE__ */ jsx2(Row, { label: "$NOVA Holdings", value: tokens > 0 ? formatNum2(tokens) : "\u2014", color: "#ff00ff" }),
|
|
1609
|
+
/* @__PURE__ */ jsx2(Row, { label: "$NOVA Price", value: price > 0 ? formatPrice2(price) : "\u2014", color: "#ffff00" }),
|
|
1610
|
+
/* @__PURE__ */ jsx2(Row, { label: "Portfolio Value", value: formatNum2(value), color: "white" }),
|
|
1611
|
+
/* @__PURE__ */ jsx2(Row, { label: "P&L", value: `${pnlSign}${formatNum2(pnl)} (${pnlSign}${pnlPct.toFixed(1)}%)`, color: pnlColor }),
|
|
1612
|
+
(data.hasWallet !== void 0 || data.walletLocal !== void 0) && /* @__PURE__ */ jsx2(
|
|
1613
|
+
Row,
|
|
1614
|
+
{
|
|
1615
|
+
label: "Wallet",
|
|
1616
|
+
value: data.hasWallet ? "registered" : data.walletLocal ? "needs registration" : "not set",
|
|
1617
|
+
color: data.hasWallet ? "#00ff00" : data.walletLocal ? "#ffff00" : "gray"
|
|
1618
|
+
}
|
|
1619
|
+
),
|
|
1539
1620
|
(earned > 0 || claimable > 0) && /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1540
|
-
/* @__PURE__ */ jsx2(
|
|
1541
|
-
/* @__PURE__ */
|
|
1542
|
-
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "50%", children: /* @__PURE__ */ jsx2(Row, { label: "$ASTRA Earned", value: earned > 0 ? formatAstra(earned) : "\u2014", color: "yellow" }) }),
|
|
1543
|
-
/* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "50%", children: /* @__PURE__ */ jsx2(Row, { label: "Claimable", value: claimable > 0 ? formatAstra(claimable) : "\u2014", color: claimable > 0 ? "green" : "gray" }) })
|
|
1544
|
-
] })
|
|
1621
|
+
/* @__PURE__ */ jsx2(Row, { label: "$ASTRA Earned", value: earned > 0 ? formatAstra(earned) : "\u2014", color: "#ffff00" }),
|
|
1622
|
+
/* @__PURE__ */ jsx2(Row, { label: "Claimable", value: claimable > 0 ? formatAstra(claimable) : "\u2014", color: claimable > 0 ? "#00ff00" : "gray" })
|
|
1545
1623
|
] })
|
|
1546
1624
|
] });
|
|
1547
1625
|
}
|
|
@@ -1572,38 +1650,29 @@ function formatAstra(n) {
|
|
|
1572
1650
|
|
|
1573
1651
|
// src/ui/RewardsCard.tsx
|
|
1574
1652
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
1575
|
-
import {
|
|
1653
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1576
1654
|
function RewardsCard({ data }) {
|
|
1577
1655
|
const total = data.totalAstra ? Number(data.totalAstra) / 1e9 : 0;
|
|
1578
1656
|
const epoch = data.epochAstra ? Number(data.epochAstra) / 1e9 : 0;
|
|
1579
1657
|
const bonus = data.bonusAstra ? Number(data.bonusAstra) / 1e9 : 0;
|
|
1580
|
-
const statusColor = data.claimStatus === "claimable" ? "
|
|
1581
|
-
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column",
|
|
1582
|
-
/* @__PURE__ */ jsxs3(Box3, {
|
|
1583
|
-
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "
|
|
1658
|
+
const statusColor = data.claimStatus === "claimable" ? "#00ff00" : data.claimStatus === "sent" ? "#00ffff" : "#ffff00";
|
|
1659
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingLeft: 1, marginY: 1, children: [
|
|
1660
|
+
/* @__PURE__ */ jsxs3(Box3, { marginBottom: 1, children: [
|
|
1661
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: "#ffff00", children: "$ASTRA Rewards" }),
|
|
1584
1662
|
data.seasonId && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1585
|
-
"
|
|
1663
|
+
" ",
|
|
1586
1664
|
data.seasonId
|
|
1587
1665
|
] })
|
|
1588
1666
|
] }),
|
|
1589
|
-
/* @__PURE__ */
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
data.bestEpochPnl !== void 0 && data.bestEpochPnl > 0 && /* @__PURE__ */ jsx3(Row2, { label: "Best Epoch P&L", value: `+${data.bestEpochPnl.toFixed(2)}`, color: "green" })
|
|
1599
|
-
] })
|
|
1600
|
-
] }),
|
|
1601
|
-
data.txSignature && /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
1602
|
-
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "\u2500".repeat(36) }) }),
|
|
1603
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
1604
|
-
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Tx: " }),
|
|
1605
|
-
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: data.txSignature })
|
|
1606
|
-
] })
|
|
1667
|
+
/* @__PURE__ */ jsx3(Row2, { label: "Total Earned", value: formatAstra2(total), color: "#ffff00" }),
|
|
1668
|
+
/* @__PURE__ */ jsx3(Row2, { label: "Epoch Rewards", value: formatAstra2(epoch), color: "#00ffff" }),
|
|
1669
|
+
/* @__PURE__ */ jsx3(Row2, { label: "Season Bonus", value: formatAstra2(bonus), color: "#ff00ff" }),
|
|
1670
|
+
/* @__PURE__ */ jsx3(Row2, { label: "Status", value: data.claimStatus ?? "\u2014", color: statusColor }),
|
|
1671
|
+
/* @__PURE__ */ jsx3(Row2, { label: "Epochs Rewarded", value: data.epochsRewarded?.toString() ?? "\u2014", color: "white" }),
|
|
1672
|
+
data.bestEpochPnl !== void 0 && data.bestEpochPnl > 0 && /* @__PURE__ */ jsx3(Row2, { label: "Best Epoch P&L", value: `+${data.bestEpochPnl.toFixed(2)}`, color: "#00ff00" }),
|
|
1673
|
+
data.txSignature && /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, children: [
|
|
1674
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Tx: " }),
|
|
1675
|
+
/* @__PURE__ */ jsx3(Text3, { color: "#00ffff", children: data.txSignature })
|
|
1607
1676
|
] })
|
|
1608
1677
|
] });
|
|
1609
1678
|
}
|
|
@@ -1776,12 +1845,23 @@ function ChatView({
|
|
|
1776
1845
|
streamingText
|
|
1777
1846
|
}) {
|
|
1778
1847
|
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflow: "hidden", paddingX: 1, children: [
|
|
1779
|
-
messages.map((msg, i) =>
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1848
|
+
messages.map((msg, i) => {
|
|
1849
|
+
if (msg.role === "log") {
|
|
1850
|
+
return /* @__PURE__ */ jsx5(Box5, { paddingLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: msg.content }) }, i);
|
|
1851
|
+
}
|
|
1852
|
+
if (msg.role === "autopilot") {
|
|
1853
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
1854
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "#ff00ff", children: " Autopilot" }),
|
|
1855
|
+
/* @__PURE__ */ jsx5(Box5, { marginLeft: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, wrap: "wrap", children: msg.content }) })
|
|
1856
|
+
] }, i);
|
|
1857
|
+
}
|
|
1858
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
1859
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: msg.role === "user" ? "#00ff00" : "#00ffff", children: msg.role === "user" ? " You" : " Agent" }),
|
|
1860
|
+
/* @__PURE__ */ jsx5(Box5, { marginLeft: 1, children: msg.role === "assistant" ? /* @__PURE__ */ jsx5(MarkdownText, { children: msg.content }) : /* @__PURE__ */ jsx5(Text5, { wrap: "wrap", children: msg.content }) })
|
|
1861
|
+
] }, i);
|
|
1862
|
+
}),
|
|
1783
1863
|
streamingText !== void 0 && streamingText.length > 0 && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
1784
|
-
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "
|
|
1864
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "#00ffff", children: " Agent" }),
|
|
1785
1865
|
/* @__PURE__ */ jsx5(Box5, { marginLeft: 1, children: /* @__PURE__ */ jsx5(MarkdownText, { children: streamingText }) })
|
|
1786
1866
|
] })
|
|
1787
1867
|
] });
|
|
@@ -1803,8 +1883,8 @@ function Input({
|
|
|
1803
1883
|
onSubmit(trimmed);
|
|
1804
1884
|
setValue("");
|
|
1805
1885
|
};
|
|
1806
|
-
return /* @__PURE__ */
|
|
1807
|
-
/* @__PURE__ */ jsx6(Text6, { color: isActive ? "yellow" : "gray", bold: true, children: "\
|
|
1886
|
+
return /* @__PURE__ */ jsxs6(Box6, { width: "100%", paddingX: 2, paddingY: 1, children: [
|
|
1887
|
+
/* @__PURE__ */ jsx6(Text6, { color: isActive ? "yellow" : "gray", bold: true, children: "\u276F\u276F " }),
|
|
1808
1888
|
/* @__PURE__ */ jsx6(
|
|
1809
1889
|
TextInput,
|
|
1810
1890
|
{
|
|
@@ -1813,10 +1893,10 @@ function Input({
|
|
|
1813
1893
|
onSubmit: handleSubmit,
|
|
1814
1894
|
focus: isActive,
|
|
1815
1895
|
showCursor: isActive,
|
|
1816
|
-
placeholder:
|
|
1896
|
+
placeholder: ""
|
|
1817
1897
|
}
|
|
1818
1898
|
)
|
|
1819
|
-
] })
|
|
1899
|
+
] });
|
|
1820
1900
|
}
|
|
1821
1901
|
|
|
1822
1902
|
// src/ui/Spinner.tsx
|
|
@@ -2029,6 +2109,21 @@ function buildSystemPrompt(skillContext, tradingContext, walletContext, rewardsC
|
|
|
2029
2109
|
if (profile.season !== void 0) {
|
|
2030
2110
|
parts.push(`Season: ${profile.season}`);
|
|
2031
2111
|
}
|
|
2112
|
+
const apMode = profile.autopilotMode ?? "off";
|
|
2113
|
+
if (apMode !== "off") {
|
|
2114
|
+
parts.push("", "---", "");
|
|
2115
|
+
parts.push(`## AUTOPILOT: ${apMode.toUpperCase()}`);
|
|
2116
|
+
parts.push("");
|
|
2117
|
+
parts.push(`On AUTOPILOT CHECK triggers:`);
|
|
2118
|
+
parts.push(`- GET /api/v1/market/state + GET /api/v1/portfolio`);
|
|
2119
|
+
parts.push(`- Apply strategy from memory.md (default: momentum + balance)`);
|
|
2120
|
+
if (apMode === "semi") {
|
|
2121
|
+
parts.push(`- SEMI: propose trade, wait for explicit user approval`);
|
|
2122
|
+
} else {
|
|
2123
|
+
parts.push(`- FULL: execute if signal clear; skip if uncertain`);
|
|
2124
|
+
}
|
|
2125
|
+
parts.push(`- Max 2-3 lines. No action = "Market checked \u2014 holding."`);
|
|
2126
|
+
}
|
|
2032
2127
|
if (memoryContent && memoryContent.trim()) {
|
|
2033
2128
|
parts.push("", "---", "");
|
|
2034
2129
|
parts.push("## Agent Memory (persistent across sessions)", "");
|
|
@@ -2596,6 +2691,10 @@ var apiCallTool = tool2({
|
|
|
2596
2691
|
if (method === "POST" && path6 === "/api/v1/board" && agentName) {
|
|
2597
2692
|
markBoardPosted(agentName);
|
|
2598
2693
|
}
|
|
2694
|
+
if (method === "POST" && path6.startsWith("/api/v1/trades") && agentName) {
|
|
2695
|
+
const budget = loadEpochBudget(agentName) ?? { epochId: 0, callCount: 0 };
|
|
2696
|
+
saveEpochBudget(agentName, { ...budget, callCount: budget.callCount + 1 });
|
|
2697
|
+
}
|
|
2599
2698
|
return result.data;
|
|
2600
2699
|
}
|
|
2601
2700
|
});
|
|
@@ -3476,6 +3575,7 @@ async function runResponsesApiTurn(messages, systemPrompt, callbacks, turnConfig
|
|
|
3476
3575
|
toolResultParts.push({
|
|
3477
3576
|
type: "tool-result",
|
|
3478
3577
|
toolCallId: tc.callId,
|
|
3578
|
+
toolName: tc.name,
|
|
3479
3579
|
result: errorResult
|
|
3480
3580
|
});
|
|
3481
3581
|
codexInput.push({
|
|
@@ -3511,6 +3611,7 @@ async function runResponsesApiTurn(messages, systemPrompt, callbacks, turnConfig
|
|
|
3511
3611
|
toolResultParts.push({
|
|
3512
3612
|
type: "tool-result",
|
|
3513
3613
|
toolCallId: tc.callId,
|
|
3614
|
+
toolName: tc.name,
|
|
3514
3615
|
result: toolResult
|
|
3515
3616
|
});
|
|
3516
3617
|
codexInput.push({
|
|
@@ -3541,6 +3642,7 @@ async function runResponsesApiTurn(messages, systemPrompt, callbacks, turnConfig
|
|
|
3541
3642
|
toolResultParts.push({
|
|
3542
3643
|
type: "tool-result",
|
|
3543
3644
|
toolCallId: tc.callId,
|
|
3645
|
+
toolName: tc.name,
|
|
3544
3646
|
result: errorResult
|
|
3545
3647
|
});
|
|
3546
3648
|
codexInput.push({
|
|
@@ -3828,6 +3930,7 @@ function App({
|
|
|
3828
3930
|
memoryContent,
|
|
3829
3931
|
initialCoreMessages,
|
|
3830
3932
|
initialChatMessages,
|
|
3933
|
+
initialAutopilotConfig,
|
|
3831
3934
|
debug
|
|
3832
3935
|
}) {
|
|
3833
3936
|
const { exit } = useApp();
|
|
@@ -3838,20 +3941,131 @@ function App({
|
|
|
3838
3941
|
initialCoreMessages ?? []
|
|
3839
3942
|
);
|
|
3840
3943
|
const providerRef = useRef2(loadConfig()?.provider ?? "unknown");
|
|
3841
|
-
const [streamingText, setStreamingText] = useState4(
|
|
3842
|
-
void 0
|
|
3843
|
-
);
|
|
3944
|
+
const [streamingText, setStreamingText] = useState4(void 0);
|
|
3844
3945
|
const [isLoading, setIsLoading] = useState4(false);
|
|
3946
|
+
const isLoadingRef = useRef2(false);
|
|
3947
|
+
useEffect3(() => {
|
|
3948
|
+
isLoadingRef.current = isLoading;
|
|
3949
|
+
}, [isLoading]);
|
|
3845
3950
|
const [toolName, setToolName] = useState4(void 0);
|
|
3951
|
+
const [autopilotMode, setAutopilotMode] = useState4(initialAutopilotConfig?.mode ?? "off");
|
|
3952
|
+
const [autopilotIntervalMs, setAutopilotIntervalMs] = useState4(initialAutopilotConfig?.intervalMs ?? 3e5);
|
|
3953
|
+
const epochCallCountRef = useRef2(0);
|
|
3954
|
+
const epochIdRef = useRef2(null);
|
|
3955
|
+
useEffect3(() => {
|
|
3956
|
+
const saved = loadEpochBudget(agentName);
|
|
3957
|
+
if (saved) {
|
|
3958
|
+
epochIdRef.current = saved.epochId;
|
|
3959
|
+
epochCallCountRef.current = saved.callCount;
|
|
3960
|
+
}
|
|
3961
|
+
}, [agentName]);
|
|
3962
|
+
const coreMessagesRef = useRef2(coreMessages);
|
|
3963
|
+
useEffect3(() => {
|
|
3964
|
+
coreMessagesRef.current = coreMessages;
|
|
3965
|
+
}, [coreMessages]);
|
|
3966
|
+
const chatMessagesRef = useRef2(chatMessages);
|
|
3967
|
+
useEffect3(() => {
|
|
3968
|
+
chatMessagesRef.current = chatMessages;
|
|
3969
|
+
}, [chatMessages]);
|
|
3970
|
+
const sendMessageRef = useRef2(async () => {
|
|
3971
|
+
});
|
|
3846
3972
|
useInput((_input, key) => {
|
|
3847
3973
|
if (key.ctrl && _input === "c") {
|
|
3848
3974
|
exit();
|
|
3849
3975
|
}
|
|
3850
3976
|
});
|
|
3977
|
+
const handleEpochChange = useCallback2((newEpoch) => {
|
|
3978
|
+
if (epochIdRef.current === newEpoch) return;
|
|
3979
|
+
epochIdRef.current = newEpoch;
|
|
3980
|
+
epochCallCountRef.current = 0;
|
|
3981
|
+
saveEpochBudget(agentName, { epochId: newEpoch, callCount: 0 });
|
|
3982
|
+
}, [agentName]);
|
|
3983
|
+
const addLogEntry = useCallback2((action, detail) => {
|
|
3984
|
+
const time = formatTime(/* @__PURE__ */ new Date());
|
|
3985
|
+
const text3 = detail ? `\u27F3 ${time} ${action} \u2014 ${detail}` : `\u27F3 ${time} ${action}`;
|
|
3986
|
+
setChatMessages((prev) => [...prev, { role: "log", content: text3 }]);
|
|
3987
|
+
}, []);
|
|
3988
|
+
const runAutopilotTurn = useCallback2(
|
|
3989
|
+
async (triggerMsg) => {
|
|
3990
|
+
const currentCore = coreMessagesRef.current;
|
|
3991
|
+
const newCoreMessages = [
|
|
3992
|
+
...currentCore,
|
|
3993
|
+
{ role: "user", content: triggerMsg }
|
|
3994
|
+
];
|
|
3995
|
+
setIsLoading(true);
|
|
3996
|
+
try {
|
|
3997
|
+
const result = await runAgentTurn(
|
|
3998
|
+
newCoreMessages,
|
|
3999
|
+
skillContext,
|
|
4000
|
+
tradingContext,
|
|
4001
|
+
walletContext,
|
|
4002
|
+
rewardsContext,
|
|
4003
|
+
onboardingContext,
|
|
4004
|
+
apiContext,
|
|
4005
|
+
{ ...profile, autopilotMode },
|
|
4006
|
+
{
|
|
4007
|
+
onTextChunk: () => {
|
|
4008
|
+
},
|
|
4009
|
+
onToolCallStart: () => {
|
|
4010
|
+
},
|
|
4011
|
+
onToolCallEnd: () => {
|
|
4012
|
+
}
|
|
4013
|
+
},
|
|
4014
|
+
memoryContent
|
|
4015
|
+
);
|
|
4016
|
+
const baseCoreMessages = result.compactedMessages ?? newCoreMessages;
|
|
4017
|
+
const updatedCore = [...baseCoreMessages, ...result.responseMessages];
|
|
4018
|
+
setCoreMessages(updatedCore);
|
|
4019
|
+
const responseText = result.text.trim();
|
|
4020
|
+
if (responseText) {
|
|
4021
|
+
const firstLine = responseText.split("\n")[0].slice(0, 80);
|
|
4022
|
+
const detail = responseText.length > 80 ? responseText.slice(0, 120) : void 0;
|
|
4023
|
+
addLogEntry(firstLine, detail !== firstLine ? detail : void 0);
|
|
4024
|
+
} else {
|
|
4025
|
+
addLogEntry("checked \u2192 no response");
|
|
4026
|
+
}
|
|
4027
|
+
const updatedChat = chatMessagesRef.current;
|
|
4028
|
+
saveSession({
|
|
4029
|
+
agentName,
|
|
4030
|
+
provider: providerRef.current,
|
|
4031
|
+
sessionId,
|
|
4032
|
+
coreMessages: updatedCore,
|
|
4033
|
+
chatMessages: updatedChat
|
|
4034
|
+
});
|
|
4035
|
+
} catch (error) {
|
|
4036
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
4037
|
+
addLogEntry("error", message);
|
|
4038
|
+
} finally {
|
|
4039
|
+
setIsLoading(false);
|
|
4040
|
+
}
|
|
4041
|
+
},
|
|
4042
|
+
[skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry]
|
|
4043
|
+
);
|
|
4044
|
+
useEffect3(() => {
|
|
4045
|
+
if (autopilotMode === "off") return;
|
|
4046
|
+
const interval = setInterval(() => {
|
|
4047
|
+
if (isLoadingRef.current) return;
|
|
4048
|
+
const budget = loadEpochBudget(agentName);
|
|
4049
|
+
const tradeCount = budget?.callCount ?? 0;
|
|
4050
|
+
if (tradeCount >= EPOCH_BUDGET - BUDGET_BUFFER) {
|
|
4051
|
+
addLogEntry("Budget reached \u2014 skipping until next epoch");
|
|
4052
|
+
return;
|
|
4053
|
+
}
|
|
4054
|
+
const trigger = buildAutopilotTrigger(autopilotMode);
|
|
4055
|
+
if (!trigger) return;
|
|
4056
|
+
if (autopilotMode === "semi") {
|
|
4057
|
+
void sendMessageRef.current(trigger, "autopilot");
|
|
4058
|
+
} else {
|
|
4059
|
+
void runAutopilotTurn(trigger);
|
|
4060
|
+
}
|
|
4061
|
+
}, autopilotIntervalMs);
|
|
4062
|
+
return () => clearInterval(interval);
|
|
4063
|
+
}, [autopilotMode, autopilotIntervalMs, addLogEntry, runAutopilotTurn]);
|
|
3851
4064
|
const sendMessage = useCallback2(
|
|
3852
|
-
async (userText) => {
|
|
4065
|
+
async (userText, displayRole = "user") => {
|
|
3853
4066
|
if (userText.startsWith("/")) {
|
|
3854
|
-
const
|
|
4067
|
+
const parts = userText.trim().split(/\s+/);
|
|
4068
|
+
const cmd = parts[0].toLowerCase();
|
|
3855
4069
|
if (cmd === "/exit" || cmd === "/quit" || cmd === "/q") {
|
|
3856
4070
|
exit();
|
|
3857
4071
|
return;
|
|
@@ -3868,6 +4082,78 @@ function App({
|
|
|
3868
4082
|
]);
|
|
3869
4083
|
return;
|
|
3870
4084
|
}
|
|
4085
|
+
if (cmd === "/auto") {
|
|
4086
|
+
const sub = parts[1]?.toLowerCase();
|
|
4087
|
+
if (!sub || sub === "status") {
|
|
4088
|
+
const modeLabel = autopilotMode.toUpperCase();
|
|
4089
|
+
const intervalLabel = formatInterval(autopilotIntervalMs);
|
|
4090
|
+
const tradeCount = loadEpochBudget(agentName)?.callCount ?? 0;
|
|
4091
|
+
const budgetLabel = `${tradeCount}/${EPOCH_BUDGET}`;
|
|
4092
|
+
setChatMessages((prev) => [
|
|
4093
|
+
...prev,
|
|
4094
|
+
{ role: "user", content: userText },
|
|
4095
|
+
{ role: "assistant", content: `**Autopilot Status**
|
|
4096
|
+
|
|
4097
|
+
Mode: ${modeLabel}
|
|
4098
|
+
Interval: ${intervalLabel}
|
|
4099
|
+
Epoch Budget: ${budgetLabel} calls used` }
|
|
4100
|
+
]);
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
if (sub === "on" || sub === "semi") {
|
|
4104
|
+
setAutopilotMode("semi");
|
|
4105
|
+
saveAutopilotConfig({ mode: "semi", intervalMs: autopilotIntervalMs });
|
|
4106
|
+
setChatMessages((prev) => [
|
|
4107
|
+
...prev,
|
|
4108
|
+
{ role: "user", content: userText },
|
|
4109
|
+
{ role: "assistant", content: `Autopilot enabled: **SEMI** mode (every ${formatInterval(autopilotIntervalMs)}). I'll propose trades for your approval.` }
|
|
4110
|
+
]);
|
|
4111
|
+
addLogEntry("Mode set to SEMI");
|
|
4112
|
+
return;
|
|
4113
|
+
}
|
|
4114
|
+
if (sub === "full") {
|
|
4115
|
+
setAutopilotMode("full");
|
|
4116
|
+
saveAutopilotConfig({ mode: "full", intervalMs: autopilotIntervalMs });
|
|
4117
|
+
setChatMessages((prev) => [
|
|
4118
|
+
...prev,
|
|
4119
|
+
{ role: "user", content: userText },
|
|
4120
|
+
{ role: "assistant", content: `Autopilot enabled: **FULL** mode (every ${formatInterval(autopilotIntervalMs)}). I'll execute trades autonomously \u2014 check the log panel.` }
|
|
4121
|
+
]);
|
|
4122
|
+
addLogEntry("Mode set to FULL");
|
|
4123
|
+
return;
|
|
4124
|
+
}
|
|
4125
|
+
if (sub === "off") {
|
|
4126
|
+
setAutopilotMode("off");
|
|
4127
|
+
saveAutopilotConfig({ mode: "off", intervalMs: autopilotIntervalMs });
|
|
4128
|
+
setChatMessages((prev) => [
|
|
4129
|
+
...prev,
|
|
4130
|
+
{ role: "user", content: userText },
|
|
4131
|
+
{ role: "assistant", content: "Autopilot disabled." }
|
|
4132
|
+
]);
|
|
4133
|
+
addLogEntry("Autopilot OFF");
|
|
4134
|
+
return;
|
|
4135
|
+
}
|
|
4136
|
+
const parsed = parseInterval(sub);
|
|
4137
|
+
if (parsed !== null) {
|
|
4138
|
+
setAutopilotIntervalMs(parsed);
|
|
4139
|
+
const newMode = autopilotMode === "off" ? "semi" : autopilotMode;
|
|
4140
|
+
setAutopilotMode(newMode);
|
|
4141
|
+
saveAutopilotConfig({ mode: newMode, intervalMs: parsed });
|
|
4142
|
+
setChatMessages((prev) => [
|
|
4143
|
+
...prev,
|
|
4144
|
+
{ role: "user", content: userText },
|
|
4145
|
+
{ role: "assistant", content: `Autopilot interval set to **${formatInterval(parsed)}**. Mode: ${newMode.toUpperCase()}.` }
|
|
4146
|
+
]);
|
|
4147
|
+
addLogEntry(`Interval set to ${formatInterval(parsed)}`);
|
|
4148
|
+
return;
|
|
4149
|
+
}
|
|
4150
|
+
setChatMessages((prev) => [
|
|
4151
|
+
...prev,
|
|
4152
|
+
{ role: "user", content: userText },
|
|
4153
|
+
{ role: "assistant", content: "Usage: `/auto on` \xB7 `/auto full` \xB7 `/auto off` \xB7 `/auto 5m` \xB7 `/auto status`" }
|
|
4154
|
+
]);
|
|
4155
|
+
return;
|
|
4156
|
+
}
|
|
3871
4157
|
if (cmd === "/help" || cmd === "/?") {
|
|
3872
4158
|
setChatMessages((prev) => [
|
|
3873
4159
|
...prev,
|
|
@@ -3886,13 +4172,13 @@ function App({
|
|
|
3886
4172
|
" `/buy <amt>` \u2014 Buy $NOVA (e.g. `/buy 500`)",
|
|
3887
4173
|
" `/sell <amt>`\u2014 Sell $NOVA (e.g. `/sell 200`)",
|
|
3888
4174
|
"",
|
|
3889
|
-
"**
|
|
4175
|
+
"**Autopilot**",
|
|
3890
4176
|
"",
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
4177
|
+
" `/auto on` \u2014 Enable semi-auto mode",
|
|
4178
|
+
" `/auto full` \u2014 Enable full-auto mode",
|
|
4179
|
+
" `/auto off` \u2014 Disable autopilot",
|
|
4180
|
+
" `/auto 5m` \u2014 Set interval (1m-60m)",
|
|
4181
|
+
" `/auto status` \u2014 Show autopilot status",
|
|
3896
4182
|
"",
|
|
3897
4183
|
"**System**",
|
|
3898
4184
|
"",
|
|
@@ -3912,8 +4198,8 @@ function App({
|
|
|
3912
4198
|
"/trades": "Show my recent trade history.",
|
|
3913
4199
|
"/board": "Show recent posts from the board.",
|
|
3914
4200
|
"/wallet": "Check my wallet status \u2014 do I have one set up?",
|
|
3915
|
-
"/buy": `Buy ${
|
|
3916
|
-
"/sell": `Sell ${
|
|
4201
|
+
"/buy": `Buy ${parts.slice(1).join(" ") || "some"} $NOVA.`,
|
|
4202
|
+
"/sell": `Sell ${parts.slice(1).join(" ") || "some"} $NOVA.`
|
|
3917
4203
|
};
|
|
3918
4204
|
if (shortcuts[cmd]) {
|
|
3919
4205
|
userText = shortcuts[cmd];
|
|
@@ -3928,7 +4214,7 @@ function App({
|
|
|
3928
4214
|
}
|
|
3929
4215
|
setChatMessages((prev) => [
|
|
3930
4216
|
...prev,
|
|
3931
|
-
{ role:
|
|
4217
|
+
{ role: displayRole, content: userText }
|
|
3932
4218
|
]);
|
|
3933
4219
|
const newCoreMessages = [
|
|
3934
4220
|
...coreMessages,
|
|
@@ -3946,7 +4232,7 @@ function App({
|
|
|
3946
4232
|
rewardsContext,
|
|
3947
4233
|
onboardingContext,
|
|
3948
4234
|
apiContext,
|
|
3949
|
-
profile,
|
|
4235
|
+
{ ...profile, autopilotMode },
|
|
3950
4236
|
{
|
|
3951
4237
|
onTextChunk: (chunk) => {
|
|
3952
4238
|
setStreamingText((prev) => (prev ?? "") + chunk);
|
|
@@ -3969,13 +4255,13 @@ function App({
|
|
|
3969
4255
|
updatedChat = [
|
|
3970
4256
|
marker,
|
|
3971
4257
|
...recentChat,
|
|
3972
|
-
{ role:
|
|
4258
|
+
{ role: displayRole, content: userText },
|
|
3973
4259
|
{ role: "assistant", content: result.text }
|
|
3974
4260
|
];
|
|
3975
4261
|
} else {
|
|
3976
4262
|
updatedChat = [
|
|
3977
4263
|
...chatMessages,
|
|
3978
|
-
{ role:
|
|
4264
|
+
{ role: displayRole, content: userText },
|
|
3979
4265
|
{ role: "assistant", content: result.text }
|
|
3980
4266
|
];
|
|
3981
4267
|
}
|
|
@@ -4013,8 +4299,11 @@ ${stack}
|
|
|
4013
4299
|
setToolName(void 0);
|
|
4014
4300
|
}
|
|
4015
4301
|
},
|
|
4016
|
-
[coreMessages, chatMessages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, agentName, sessionId]
|
|
4302
|
+
[coreMessages, chatMessages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry]
|
|
4017
4303
|
);
|
|
4304
|
+
useEffect3(() => {
|
|
4305
|
+
sendMessageRef.current = sendMessage;
|
|
4306
|
+
}, [sendMessage]);
|
|
4018
4307
|
const handleSubmit = useCallback2(
|
|
4019
4308
|
(userText) => {
|
|
4020
4309
|
void sendMessage(userText);
|
|
@@ -4026,13 +4315,25 @@ ${stack}
|
|
|
4026
4315
|
isLoading && toolName && /* @__PURE__ */ jsx7(Spinner, { label: `Calling ${toolName}...` }),
|
|
4027
4316
|
isLoading && !toolName && /* @__PURE__ */ jsx7(Spinner, { label: streamingText ? "Thinking..." : void 0 }),
|
|
4028
4317
|
/* @__PURE__ */ jsx7(Box7, { flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsx7(Input, { isActive: !isLoading, onSubmit: handleSubmit }) }),
|
|
4029
|
-
/* @__PURE__ */ jsx7(Box7, { flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsx7(
|
|
4030
|
-
|
|
4318
|
+
/* @__PURE__ */ jsx7(Box7, { flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsx7(
|
|
4319
|
+
StatusBar_default,
|
|
4320
|
+
{
|
|
4321
|
+
agentName,
|
|
4322
|
+
journeyStage: profile.journeyStage ?? "full",
|
|
4323
|
+
autopilotMode,
|
|
4324
|
+
autopilotIntervalMs,
|
|
4325
|
+
onEpochChange: handleEpochChange
|
|
4326
|
+
}
|
|
4327
|
+
) }),
|
|
4328
|
+
/* @__PURE__ */ jsxs8(Box7, { flexShrink: 0, width: "100%", paddingX: 2, marginTop: 1, justifyContent: "space-between", children: [
|
|
4031
4329
|
/* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "/help \xB7 /portfolio \xB7 /market \xB7 /exit" }),
|
|
4032
|
-
/* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "Ctrl+C quit" })
|
|
4330
|
+
/* @__PURE__ */ jsx7(Text8, { dimColor: true, children: "/auto on\xB7off\xB7set \xB7 Ctrl+C quit" })
|
|
4033
4331
|
] })
|
|
4034
4332
|
] });
|
|
4035
4333
|
}
|
|
4334
|
+
function formatTime(d) {
|
|
4335
|
+
return `${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
4336
|
+
}
|
|
4036
4337
|
|
|
4037
4338
|
// src/bin/astra.ts
|
|
4038
4339
|
function detectJourneyStage(params) {
|
|
@@ -4150,6 +4451,7 @@ async function main() {
|
|
|
4150
4451
|
console.log(" No previous session found. Starting fresh.\n");
|
|
4151
4452
|
}
|
|
4152
4453
|
}
|
|
4454
|
+
const initialAutopilotConfig = loadAutopilotConfig();
|
|
4153
4455
|
const { waitUntilExit } = render(
|
|
4154
4456
|
React5.createElement(App, {
|
|
4155
4457
|
agentName,
|
|
@@ -4164,6 +4466,7 @@ async function main() {
|
|
|
4164
4466
|
memoryContent,
|
|
4165
4467
|
initialCoreMessages,
|
|
4166
4468
|
initialChatMessages,
|
|
4469
|
+
initialAutopilotConfig,
|
|
4167
4470
|
debug
|
|
4168
4471
|
})
|
|
4169
4472
|
);
|