@astra-cli/cli 1.2.6 → 1.2.8
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 +309 -206
- package/package.json +1 -1
package/dist/astra.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/bin/astra.ts
|
|
4
4
|
import process4 from "process";
|
|
5
|
-
import
|
|
5
|
+
import React7 from "react";
|
|
6
6
|
import { render } from "ink";
|
|
7
7
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
8
8
|
|
|
@@ -52,6 +52,33 @@ function getActiveManifest() {
|
|
|
52
52
|
return _activeManifest;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// src/ui/AppErrorBoundary.tsx
|
|
56
|
+
import React from "react";
|
|
57
|
+
import { Text, Box } from "ink";
|
|
58
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
59
|
+
var AppErrorBoundary = class extends React.Component {
|
|
60
|
+
state = { error: null };
|
|
61
|
+
static getDerivedStateFromError(error) {
|
|
62
|
+
return { error };
|
|
63
|
+
}
|
|
64
|
+
componentDidCatch(error) {
|
|
65
|
+
process.stderr.write(`[astra] Fatal render error: ${error.stack ?? error.message}
|
|
66
|
+
`);
|
|
67
|
+
}
|
|
68
|
+
render() {
|
|
69
|
+
if (this.state.error) {
|
|
70
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 1, children: [
|
|
71
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "red", children: "Something went wrong" }),
|
|
72
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
73
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: this.state.error.message }),
|
|
74
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
75
|
+
/* @__PURE__ */ jsx(Text, { children: "Press Ctrl+C to exit. Your session has been saved." })
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
return this.props.children;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
55
82
|
// src/domain/astranova/manifest.ts
|
|
56
83
|
var ASTRANOVA_MANIFEST = {
|
|
57
84
|
name: "astranova",
|
|
@@ -452,8 +479,7 @@ function getActivePlugin() {
|
|
|
452
479
|
return loadState()?.activePlugin ?? "astranova";
|
|
453
480
|
}
|
|
454
481
|
function setActivePlugin(name) {
|
|
455
|
-
const state = loadState();
|
|
456
|
-
if (!state) return;
|
|
482
|
+
const state = loadState() ?? { activePlugin: "astranova", activeAgents: {}, agents: {} };
|
|
457
483
|
saveState({ ...state, activePlugin: name });
|
|
458
484
|
}
|
|
459
485
|
function loadPluginManifest(name) {
|
|
@@ -556,11 +582,24 @@ async function refreshTokens(params) {
|
|
|
556
582
|
client_id: clientId,
|
|
557
583
|
refresh_token: params.refreshToken
|
|
558
584
|
});
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
585
|
+
const controller = new AbortController();
|
|
586
|
+
const timeoutId = setTimeout(() => controller.abort(), 15e3);
|
|
587
|
+
let response;
|
|
588
|
+
try {
|
|
589
|
+
response = await fetch(OPENAI_TOKEN_ENDPOINT, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
592
|
+
body,
|
|
593
|
+
signal: controller.signal
|
|
594
|
+
});
|
|
595
|
+
} catch (err) {
|
|
596
|
+
clearTimeout(timeoutId);
|
|
597
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
598
|
+
throw new Error("Token refresh timed out after 15s");
|
|
599
|
+
}
|
|
600
|
+
throw err;
|
|
601
|
+
}
|
|
602
|
+
clearTimeout(timeoutId);
|
|
564
603
|
if (!response.ok) {
|
|
565
604
|
const text3 = await response.text();
|
|
566
605
|
throw new Error(`Token refresh failed (HTTP ${response.status}): ${text3.slice(0, 200)}`);
|
|
@@ -871,31 +910,38 @@ async function promptApiKey(provider) {
|
|
|
871
910
|
openai: "sk-...",
|
|
872
911
|
google: "AIza..."
|
|
873
912
|
};
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
913
|
+
const maxAttempts = 5;
|
|
914
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
915
|
+
const apiKey = await clack.text({
|
|
916
|
+
message: `Enter your ${labels[provider] ?? "API key"}`,
|
|
917
|
+
placeholder: placeholders[provider] ?? "your-api-key",
|
|
918
|
+
validate(value) {
|
|
919
|
+
if (!value || value.trim().length === 0) {
|
|
920
|
+
return "API key is required";
|
|
921
|
+
}
|
|
922
|
+
return void 0;
|
|
880
923
|
}
|
|
881
|
-
|
|
924
|
+
});
|
|
925
|
+
if (clack.isCancel(apiKey)) {
|
|
926
|
+
clack.cancel("Setup cancelled.");
|
|
927
|
+
process.exit(0);
|
|
882
928
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
return
|
|
929
|
+
const trimmed = apiKey.trim();
|
|
930
|
+
const spinner5 = clack.spinner();
|
|
931
|
+
spinner5.start("Validating API key...");
|
|
932
|
+
const valid = await validateApiKey(provider, trimmed);
|
|
933
|
+
if (!valid.ok) {
|
|
934
|
+
spinner5.stop(`API key validation failed: ${valid.error}`);
|
|
935
|
+
clack.log.error(
|
|
936
|
+
attempt < maxAttempts - 1 ? "Please check your key and try again." : "Too many failed attempts. Please restart setup."
|
|
937
|
+
);
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
spinner5.stop("API key validated.");
|
|
941
|
+
return trimmed;
|
|
896
942
|
}
|
|
897
|
-
|
|
898
|
-
|
|
943
|
+
clack.cancel("Too many failed API key attempts.");
|
|
944
|
+
process.exit(1);
|
|
899
945
|
}
|
|
900
946
|
async function validateApiKey(provider, apiKey) {
|
|
901
947
|
try {
|
|
@@ -1081,6 +1127,10 @@ async function registerAgent() {
|
|
|
1081
1127
|
if (!parsed.success) {
|
|
1082
1128
|
spinner5.stop("Registration failed.");
|
|
1083
1129
|
clack2.log.error("Unexpected response from API. Please try again.");
|
|
1130
|
+
if (process.env.ASTRA_DEBUG) {
|
|
1131
|
+
process.stderr.write(`[astra] Schema validation: ${JSON.stringify(parsed.error.issues)}
|
|
1132
|
+
`);
|
|
1133
|
+
}
|
|
1084
1134
|
continue;
|
|
1085
1135
|
}
|
|
1086
1136
|
const { agent } = parsed.data;
|
|
@@ -1459,11 +1509,11 @@ async function getCached(name, url, ttlMs) {
|
|
|
1459
1509
|
return fallbackToStale(contentPath, name, url, response.status);
|
|
1460
1510
|
}
|
|
1461
1511
|
const content = await response.text();
|
|
1462
|
-
fs3.writeFileSync(contentPath, content, "utf-8");
|
|
1512
|
+
fs3.writeFileSync(contentPath, content, { encoding: "utf-8", mode: 384 });
|
|
1463
1513
|
fs3.writeFileSync(
|
|
1464
1514
|
metaPath(name),
|
|
1465
1515
|
JSON.stringify({ fetchedAt: (/* @__PURE__ */ new Date()).toISOString(), url }),
|
|
1466
|
-
"utf-8"
|
|
1516
|
+
{ encoding: "utf-8", mode: 384 }
|
|
1467
1517
|
);
|
|
1468
1518
|
return content;
|
|
1469
1519
|
} catch {
|
|
@@ -1554,7 +1604,7 @@ function saveSession(params) {
|
|
|
1554
1604
|
agentName: params.agentName,
|
|
1555
1605
|
provider: params.provider,
|
|
1556
1606
|
sessionId: params.sessionId,
|
|
1557
|
-
createdAt:
|
|
1607
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1558
1608
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1559
1609
|
coreMessages: serializeMessages(params.coreMessages),
|
|
1560
1610
|
chatMessages: params.chatMessages.slice(-MAX_MESSAGES)
|
|
@@ -2909,21 +2959,22 @@ var registerAgentTool = tool6({
|
|
|
2909
2959
|
api_key: apiKey,
|
|
2910
2960
|
api_base: getActiveManifest().apiBase
|
|
2911
2961
|
});
|
|
2962
|
+
const verificationCode = data.verification_code ?? data.agent?.verification_code;
|
|
2912
2963
|
setActiveAgent(name);
|
|
2913
2964
|
updateAgentState(name, {
|
|
2914
2965
|
status: "pending_verification",
|
|
2915
2966
|
journeyStage: "fresh",
|
|
2916
|
-
verificationCode
|
|
2967
|
+
verificationCode
|
|
2917
2968
|
});
|
|
2918
2969
|
requestRestart();
|
|
2919
2970
|
return {
|
|
2920
2971
|
success: true,
|
|
2921
2972
|
agentName: name,
|
|
2922
2973
|
status: "pending_verification",
|
|
2923
|
-
verificationCode
|
|
2974
|
+
verificationCode,
|
|
2924
2975
|
simBalance: data.agent?.simBalance ?? 1e4,
|
|
2925
2976
|
restartRequired: true,
|
|
2926
|
-
message: `Agent "${name}" registered successfully
|
|
2977
|
+
message: `Agent "${name}" registered successfully!${verificationCode ? ` Verification code: ${verificationCode}.` : ""} Restarting to load the new agent...`
|
|
2927
2978
|
};
|
|
2928
2979
|
}
|
|
2929
2980
|
});
|
|
@@ -3162,7 +3213,6 @@ async function parseSSEStream(body, callbacks, idleTimeoutMs = 45e3) {
|
|
|
3162
3213
|
name: event.item.name,
|
|
3163
3214
|
args: ""
|
|
3164
3215
|
});
|
|
3165
|
-
callbacks?.onToolCallStart?.(event.item.name);
|
|
3166
3216
|
}
|
|
3167
3217
|
break;
|
|
3168
3218
|
case "response.function_call_arguments.delta":
|
|
@@ -3174,12 +3224,6 @@ async function parseSSEStream(body, callbacks, idleTimeoutMs = 45e3) {
|
|
|
3174
3224
|
}
|
|
3175
3225
|
break;
|
|
3176
3226
|
case "response.function_call_arguments.done":
|
|
3177
|
-
if (event.item_id) {
|
|
3178
|
-
const tc = toolCalls.get(event.item_id);
|
|
3179
|
-
if (tc) {
|
|
3180
|
-
callbacks?.onToolCallEnd?.(tc.name);
|
|
3181
|
-
}
|
|
3182
|
-
}
|
|
3183
3227
|
break;
|
|
3184
3228
|
case "response.failed": {
|
|
3185
3229
|
const resp = event.response;
|
|
@@ -3574,7 +3618,11 @@ async function runResponsesApiTurn(messages, systemPrompt, callbacks, turnConfig
|
|
|
3574
3618
|
const startTime = Date.now();
|
|
3575
3619
|
try {
|
|
3576
3620
|
debugLog3(`Tool ${tc.name}(${tc.callId}) args: ${JSON.stringify(parsedArgs)}`);
|
|
3577
|
-
const
|
|
3621
|
+
const exec2 = toolDef.execute;
|
|
3622
|
+
if (typeof exec2 !== "function") {
|
|
3623
|
+
throw new Error(`Tool "${tc.name}" has no execute method`);
|
|
3624
|
+
}
|
|
3625
|
+
const execute = exec2;
|
|
3578
3626
|
const toolResult = await execute(parsedArgs, {});
|
|
3579
3627
|
debugLog3(`Tool ${tc.name}(${tc.callId}) result: ${JSON.stringify(toolResult).slice(0, 200)}`);
|
|
3580
3628
|
writeAuditEntry({
|
|
@@ -3719,6 +3767,12 @@ async function runSdkTurn(messages, systemPrompt, callbacks) {
|
|
|
3719
3767
|
maxSteps: 10,
|
|
3720
3768
|
temperature: 0.7,
|
|
3721
3769
|
abortSignal: abortController.signal,
|
|
3770
|
+
toolCallStreaming: true,
|
|
3771
|
+
onChunk: ({ chunk }) => {
|
|
3772
|
+
if (chunk.type === "tool-call-streaming-start") {
|
|
3773
|
+
callbacks.onToolCallStart?.(chunk.toolName);
|
|
3774
|
+
}
|
|
3775
|
+
},
|
|
3722
3776
|
onStepFinish: ({ toolCalls, toolResults }) => {
|
|
3723
3777
|
resetIdleTimer();
|
|
3724
3778
|
if (toolCalls && toolCalls.length > 0) {
|
|
@@ -4189,7 +4243,8 @@ function extractNarrativeContent(skillMd) {
|
|
|
4189
4243
|
return skillMd.slice(0, firstEngineIdx);
|
|
4190
4244
|
}
|
|
4191
4245
|
function buildManifestFromMeta(meta) {
|
|
4192
|
-
const
|
|
4246
|
+
const rawName = typeof meta.name === "string" ? meta.name.trim() : void 0;
|
|
4247
|
+
const name = rawName && /^[a-z0-9_-]+$/.test(rawName) ? rawName : void 0;
|
|
4193
4248
|
const version = typeof meta.version === "string" ? meta.version.trim() : "0.0.0";
|
|
4194
4249
|
const description = typeof meta.description === "string" ? meta.description.trim() : name ?? "Unknown";
|
|
4195
4250
|
const apiBase = typeof meta.apiBase === "string" ? meta.apiBase.trim().replace(/\/$/, "") : void 0;
|
|
@@ -4519,14 +4574,14 @@ async function runPluginsPicker() {
|
|
|
4519
4574
|
|
|
4520
4575
|
// src/ui/App.tsx
|
|
4521
4576
|
import { useState as useState4, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
4522
|
-
import { Box as
|
|
4577
|
+
import { Box as Box9, Text as Text10, useApp, useInput } from "ink";
|
|
4523
4578
|
|
|
4524
4579
|
// src/ui/StatusBar.tsx
|
|
4525
|
-
import
|
|
4526
|
-
import { Box, Text } from "ink";
|
|
4527
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4580
|
+
import React2, { useState, useEffect, useRef, useCallback } from "react";
|
|
4581
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
4582
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
4528
4583
|
var POLL_INTERVAL_MS = 6e4;
|
|
4529
|
-
var StatusBar =
|
|
4584
|
+
var StatusBar = React2.memo(function StatusBar2({
|
|
4530
4585
|
agentName,
|
|
4531
4586
|
pluginName,
|
|
4532
4587
|
isAstraNova,
|
|
@@ -4583,50 +4638,50 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4583
4638
|
}, [canFetchData, poll]);
|
|
4584
4639
|
const { market, portfolio } = data;
|
|
4585
4640
|
const apActive = autopilotMode !== "off";
|
|
4586
|
-
return /* @__PURE__ */
|
|
4587
|
-
/* @__PURE__ */
|
|
4588
|
-
/* @__PURE__ */
|
|
4589
|
-
/* @__PURE__ */
|
|
4590
|
-
/* @__PURE__ */
|
|
4641
|
+
return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", width: "100%", children: /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, justifyContent: "space-between", children: [
|
|
4642
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
4643
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "#00ff00", children: pluginName }),
|
|
4644
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4645
|
+
/* @__PURE__ */ jsx2(Text2, { color: "#ff8800", children: agentName }),
|
|
4591
4646
|
!isAstraNova && pluginData && pluginMap?.status?.fields.map((field) => {
|
|
4592
4647
|
const value = getNestedValue(pluginData, field.path);
|
|
4593
4648
|
if (value == null) return null;
|
|
4594
|
-
return /* @__PURE__ */
|
|
4595
|
-
/* @__PURE__ */
|
|
4596
|
-
/* @__PURE__ */
|
|
4649
|
+
return /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
|
|
4650
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4651
|
+
/* @__PURE__ */ jsxs2(Text2, { color: field.color, children: [
|
|
4597
4652
|
field.label,
|
|
4598
4653
|
": ",
|
|
4599
4654
|
String(value)
|
|
4600
4655
|
] })
|
|
4601
4656
|
] }, field.path);
|
|
4602
4657
|
}),
|
|
4603
|
-
!isAstraNova && !pluginData && pluginMap?.status && /* @__PURE__ */
|
|
4604
|
-
/* @__PURE__ */
|
|
4605
|
-
/* @__PURE__ */
|
|
4658
|
+
!isAstraNova && !pluginData && pluginMap?.status && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4659
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4660
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "loading..." })
|
|
4606
4661
|
] }),
|
|
4607
|
-
canFetchData && market && /* @__PURE__ */
|
|
4608
|
-
/* @__PURE__ */
|
|
4609
|
-
/* @__PURE__ */
|
|
4610
|
-
/* @__PURE__ */
|
|
4611
|
-
/* @__PURE__ */
|
|
4612
|
-
/* @__PURE__ */
|
|
4662
|
+
canFetchData && market && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4663
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4664
|
+
/* @__PURE__ */ jsx2(Text2, { color: "#ffff00", children: "$NOVA " }),
|
|
4665
|
+
/* @__PURE__ */ jsx2(Text2, { color: "white", children: formatPrice(market.price) }),
|
|
4666
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4667
|
+
/* @__PURE__ */ jsx2(Text2, { color: moodColor(market.mood), children: market.mood })
|
|
4613
4668
|
] }),
|
|
4614
|
-
canFetchData && portfolio && /* @__PURE__ */
|
|
4615
|
-
/* @__PURE__ */
|
|
4616
|
-
/* @__PURE__ */
|
|
4669
|
+
canFetchData && portfolio && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4670
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4671
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "#00ffff", children: [
|
|
4617
4672
|
formatNum(portfolio.cash),
|
|
4618
4673
|
" $SIM"
|
|
4619
4674
|
] }),
|
|
4620
|
-
portfolio.tokens > 0 && /* @__PURE__ */
|
|
4621
|
-
/* @__PURE__ */
|
|
4622
|
-
/* @__PURE__ */
|
|
4675
|
+
portfolio.tokens > 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4676
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4677
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "#ff00ff", children: [
|
|
4623
4678
|
formatNum(portfolio.tokens),
|
|
4624
4679
|
" $NOVA"
|
|
4625
4680
|
] })
|
|
4626
4681
|
] }),
|
|
4627
|
-
portfolio.pnl !== 0 && /* @__PURE__ */
|
|
4628
|
-
/* @__PURE__ */
|
|
4629
|
-
/* @__PURE__ */
|
|
4682
|
+
portfolio.pnl !== 0 && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4683
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4684
|
+
/* @__PURE__ */ jsxs2(Text2, { color: portfolio.pnl >= 0 ? "#00ff00" : "#ff4444", children: [
|
|
4630
4685
|
"P&L ",
|
|
4631
4686
|
portfolio.pnl >= 0 ? "+" : "",
|
|
4632
4687
|
formatNum(portfolio.pnl),
|
|
@@ -4636,22 +4691,22 @@ var StatusBar = React.memo(function StatusBar2({
|
|
|
4636
4691
|
"%)"
|
|
4637
4692
|
] })
|
|
4638
4693
|
] }),
|
|
4639
|
-
/* @__PURE__ */
|
|
4640
|
-
/* @__PURE__ */
|
|
4694
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4695
|
+
/* @__PURE__ */ jsxs2(Text2, { color: "#e2f902", children: [
|
|
4641
4696
|
"Net ",
|
|
4642
4697
|
formatNum(portfolio.portfolioValue)
|
|
4643
4698
|
] })
|
|
4644
4699
|
] }),
|
|
4645
|
-
isAstraNova && !canFetchData && /* @__PURE__ */
|
|
4646
|
-
/* @__PURE__ */
|
|
4647
|
-
/* @__PURE__ */
|
|
4700
|
+
isAstraNova && !canFetchData && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4701
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4702
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "pending verification" })
|
|
4648
4703
|
] }),
|
|
4649
|
-
canFetchData && !market && !portfolio && /* @__PURE__ */
|
|
4650
|
-
/* @__PURE__ */
|
|
4651
|
-
/* @__PURE__ */
|
|
4704
|
+
canFetchData && !market && !portfolio && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
4705
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2502 " }),
|
|
4706
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "loading..." })
|
|
4652
4707
|
] })
|
|
4653
4708
|
] }),
|
|
4654
|
-
apActive && /* @__PURE__ */
|
|
4709
|
+
apActive && /* @__PURE__ */ jsxs2(Text2, { color: "#00ff00", children: [
|
|
4655
4710
|
"AP: \u25CF ",
|
|
4656
4711
|
autopilotMode.toUpperCase(),
|
|
4657
4712
|
" ",
|
|
@@ -4724,14 +4779,14 @@ async function fetchPortfolio(agentName) {
|
|
|
4724
4779
|
}
|
|
4725
4780
|
|
|
4726
4781
|
// src/ui/ChatView.tsx
|
|
4727
|
-
import { Box as
|
|
4782
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
4728
4783
|
|
|
4729
4784
|
// src/ui/MarkdownText.tsx
|
|
4730
|
-
import { Text as
|
|
4785
|
+
import { Text as Text5, Box as Box5 } from "ink";
|
|
4731
4786
|
|
|
4732
4787
|
// src/ui/PortfolioCard.tsx
|
|
4733
|
-
import { Box as
|
|
4734
|
-
import { Fragment as Fragment2, jsx as
|
|
4788
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
4789
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4735
4790
|
function PortfolioCard({ data }) {
|
|
4736
4791
|
const price = data.currentPrice ?? 0;
|
|
4737
4792
|
const cash = data.cash ?? 0;
|
|
@@ -4743,14 +4798,14 @@ function PortfolioCard({ data }) {
|
|
|
4743
4798
|
const claimable = data.claimable ? Number(data.claimable) / 1e9 : 0;
|
|
4744
4799
|
const pnlColor = pnl >= 0 ? "#00ff00" : "#ff4444";
|
|
4745
4800
|
const pnlSign = pnl >= 0 ? "+" : "";
|
|
4746
|
-
return /* @__PURE__ */
|
|
4747
|
-
/* @__PURE__ */
|
|
4748
|
-
/* @__PURE__ */
|
|
4749
|
-
/* @__PURE__ */
|
|
4750
|
-
/* @__PURE__ */
|
|
4751
|
-
/* @__PURE__ */
|
|
4752
|
-
/* @__PURE__ */
|
|
4753
|
-
(data.hasWallet !== void 0 || data.walletLocal !== void 0) && /* @__PURE__ */
|
|
4801
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingLeft: 1, marginY: 1, children: [
|
|
4802
|
+
/* @__PURE__ */ jsx3(Box3, { marginBottom: 1, children: /* @__PURE__ */ jsx3(Text3, { bold: true, color: "#00ffff", children: "Portfolio Overview" }) }),
|
|
4803
|
+
/* @__PURE__ */ jsx3(Row, { label: "$SIM Balance", value: formatNum2(cash), color: "#00ffff" }),
|
|
4804
|
+
/* @__PURE__ */ jsx3(Row, { label: "$NOVA Holdings", value: tokens > 0 ? formatNum2(tokens) : "\u2014", color: "#ff00ff" }),
|
|
4805
|
+
/* @__PURE__ */ jsx3(Row, { label: "$NOVA Price", value: price > 0 ? formatPrice2(price) : "\u2014", color: "#ffff00" }),
|
|
4806
|
+
/* @__PURE__ */ jsx3(Row, { label: "Portfolio Value", value: formatNum2(value), color: "white" }),
|
|
4807
|
+
/* @__PURE__ */ jsx3(Row, { label: "P&L", value: `${pnlSign}${formatNum2(pnl)} (${pnlSign}${pnlPct.toFixed(1)}%)`, color: pnlColor }),
|
|
4808
|
+
(data.hasWallet !== void 0 || data.walletLocal !== void 0) && /* @__PURE__ */ jsx3(
|
|
4754
4809
|
Row,
|
|
4755
4810
|
{
|
|
4756
4811
|
label: "Wallet",
|
|
@@ -4758,19 +4813,19 @@ function PortfolioCard({ data }) {
|
|
|
4758
4813
|
color: data.hasWallet ? "#00ff00" : data.walletLocal ? "#ffff00" : "gray"
|
|
4759
4814
|
}
|
|
4760
4815
|
),
|
|
4761
|
-
(earned > 0 || claimable > 0) && /* @__PURE__ */
|
|
4762
|
-
/* @__PURE__ */
|
|
4763
|
-
/* @__PURE__ */
|
|
4816
|
+
(earned > 0 || claimable > 0) && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
4817
|
+
/* @__PURE__ */ jsx3(Row, { label: "$ASTRA Earned", value: earned > 0 ? formatAstra(earned) : "\u2014", color: "#ffff00" }),
|
|
4818
|
+
/* @__PURE__ */ jsx3(Row, { label: "Claimable", value: claimable > 0 ? formatAstra(claimable) : "\u2014", color: claimable > 0 ? "#00ff00" : "gray" })
|
|
4764
4819
|
] })
|
|
4765
4820
|
] });
|
|
4766
4821
|
}
|
|
4767
4822
|
function Row({ label, value, color }) {
|
|
4768
|
-
return /* @__PURE__ */
|
|
4769
|
-
/* @__PURE__ */
|
|
4823
|
+
return /* @__PURE__ */ jsxs3(Box3, { children: [
|
|
4824
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
4770
4825
|
label,
|
|
4771
4826
|
": "
|
|
4772
4827
|
] }),
|
|
4773
|
-
/* @__PURE__ */
|
|
4828
|
+
/* @__PURE__ */ jsx3(Text3, { color, bold: true, children: value })
|
|
4774
4829
|
] });
|
|
4775
4830
|
}
|
|
4776
4831
|
function formatPrice2(price) {
|
|
@@ -4790,40 +4845,40 @@ function formatAstra(n) {
|
|
|
4790
4845
|
}
|
|
4791
4846
|
|
|
4792
4847
|
// src/ui/RewardsCard.tsx
|
|
4793
|
-
import { Box as
|
|
4794
|
-
import { jsx as
|
|
4848
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
4849
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4795
4850
|
function RewardsCard({ data }) {
|
|
4796
4851
|
const total = data.totalAstra ? Number(data.totalAstra) / 1e9 : 0;
|
|
4797
4852
|
const epoch = data.epochAstra ? Number(data.epochAstra) / 1e9 : 0;
|
|
4798
4853
|
const bonus = data.bonusAstra ? Number(data.bonusAstra) / 1e9 : 0;
|
|
4799
4854
|
const statusColor = data.claimStatus === "claimable" ? "#00ff00" : data.claimStatus === "sent" ? "#00ffff" : "#ffff00";
|
|
4800
|
-
return /* @__PURE__ */
|
|
4801
|
-
/* @__PURE__ */
|
|
4802
|
-
/* @__PURE__ */
|
|
4803
|
-
data.seasonId && /* @__PURE__ */
|
|
4855
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingLeft: 1, marginY: 1, children: [
|
|
4856
|
+
/* @__PURE__ */ jsxs4(Box4, { marginBottom: 1, children: [
|
|
4857
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "#ffff00", children: "$ASTRA Rewards" }),
|
|
4858
|
+
data.seasonId && /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
4804
4859
|
" ",
|
|
4805
4860
|
data.seasonId
|
|
4806
4861
|
] })
|
|
4807
4862
|
] }),
|
|
4808
|
-
/* @__PURE__ */
|
|
4809
|
-
/* @__PURE__ */
|
|
4810
|
-
/* @__PURE__ */
|
|
4811
|
-
/* @__PURE__ */
|
|
4812
|
-
/* @__PURE__ */
|
|
4813
|
-
data.bestEpochPnl !== void 0 && data.bestEpochPnl > 0 && /* @__PURE__ */
|
|
4814
|
-
data.txSignature && /* @__PURE__ */
|
|
4815
|
-
/* @__PURE__ */
|
|
4816
|
-
/* @__PURE__ */
|
|
4863
|
+
/* @__PURE__ */ jsx4(Row2, { label: "Total Earned", value: formatAstra2(total), color: "#ffff00" }),
|
|
4864
|
+
/* @__PURE__ */ jsx4(Row2, { label: "Epoch Rewards", value: formatAstra2(epoch), color: "#00ffff" }),
|
|
4865
|
+
/* @__PURE__ */ jsx4(Row2, { label: "Season Bonus", value: formatAstra2(bonus), color: "#ff00ff" }),
|
|
4866
|
+
/* @__PURE__ */ jsx4(Row2, { label: "Status", value: data.claimStatus ?? "\u2014", color: statusColor }),
|
|
4867
|
+
/* @__PURE__ */ jsx4(Row2, { label: "Epochs Rewarded", value: data.epochsRewarded?.toString() ?? "\u2014", color: "white" }),
|
|
4868
|
+
data.bestEpochPnl !== void 0 && data.bestEpochPnl > 0 && /* @__PURE__ */ jsx4(Row2, { label: "Best Epoch P&L", value: `+${data.bestEpochPnl.toFixed(2)}`, color: "#00ff00" }),
|
|
4869
|
+
data.txSignature && /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, children: [
|
|
4870
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Tx: " }),
|
|
4871
|
+
/* @__PURE__ */ jsx4(Text4, { color: "#00ffff", children: data.txSignature })
|
|
4817
4872
|
] })
|
|
4818
4873
|
] });
|
|
4819
4874
|
}
|
|
4820
4875
|
function Row2({ label, value, color }) {
|
|
4821
|
-
return /* @__PURE__ */
|
|
4822
|
-
/* @__PURE__ */
|
|
4876
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
4877
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
4823
4878
|
label,
|
|
4824
4879
|
": "
|
|
4825
4880
|
] }),
|
|
4826
|
-
/* @__PURE__ */
|
|
4881
|
+
/* @__PURE__ */ jsx4(Text4, { color, bold: true, children: value })
|
|
4827
4882
|
] });
|
|
4828
4883
|
}
|
|
4829
4884
|
function formatAstra2(n) {
|
|
@@ -4834,7 +4889,7 @@ function formatAstra2(n) {
|
|
|
4834
4889
|
}
|
|
4835
4890
|
|
|
4836
4891
|
// src/ui/MarkdownText.tsx
|
|
4837
|
-
import { jsx as
|
|
4892
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4838
4893
|
function MarkdownText({ children }) {
|
|
4839
4894
|
const lines = children.split("\n");
|
|
4840
4895
|
const elements = [];
|
|
@@ -4854,14 +4909,14 @@ function MarkdownText({ children }) {
|
|
|
4854
4909
|
const raw = jsonLines.join("\n");
|
|
4855
4910
|
if (cardType === "portfolio") {
|
|
4856
4911
|
const data = JSON.parse(raw);
|
|
4857
|
-
elements.push(/* @__PURE__ */
|
|
4912
|
+
elements.push(/* @__PURE__ */ jsx5(PortfolioCard, { data }, elements.length));
|
|
4858
4913
|
} else {
|
|
4859
4914
|
const data = JSON.parse(raw);
|
|
4860
|
-
elements.push(/* @__PURE__ */
|
|
4915
|
+
elements.push(/* @__PURE__ */ jsx5(RewardsCard, { data }, elements.length));
|
|
4861
4916
|
}
|
|
4862
4917
|
} catch {
|
|
4863
4918
|
elements.push(
|
|
4864
|
-
/* @__PURE__ */
|
|
4919
|
+
/* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { wrap: "wrap", children: jsonLines.join("\n") }) }, elements.length)
|
|
4865
4920
|
);
|
|
4866
4921
|
}
|
|
4867
4922
|
continue;
|
|
@@ -4875,13 +4930,13 @@ function MarkdownText({ children }) {
|
|
|
4875
4930
|
}
|
|
4876
4931
|
i++;
|
|
4877
4932
|
elements.push(
|
|
4878
|
-
/* @__PURE__ */
|
|
4933
|
+
/* @__PURE__ */ jsx5(Box5, { marginLeft: 2, marginY: 0, children: /* @__PURE__ */ jsx5(Text5, { color: "gray", children: codeLines.join("\n") }) }, elements.length)
|
|
4879
4934
|
);
|
|
4880
4935
|
continue;
|
|
4881
4936
|
}
|
|
4882
4937
|
if (/^---+$/.test(line.trim())) {
|
|
4883
4938
|
elements.push(
|
|
4884
|
-
/* @__PURE__ */
|
|
4939
|
+
/* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "\u2500".repeat(40) }) }, elements.length)
|
|
4885
4940
|
);
|
|
4886
4941
|
i++;
|
|
4887
4942
|
continue;
|
|
@@ -4889,7 +4944,7 @@ function MarkdownText({ children }) {
|
|
|
4889
4944
|
const headerMatch = /^(#{1,4})\s+(.+)$/.exec(line);
|
|
4890
4945
|
if (headerMatch) {
|
|
4891
4946
|
elements.push(
|
|
4892
|
-
/* @__PURE__ */
|
|
4947
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: elements.length > 0 ? 1 : 0, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: "cyan", children: headerMatch[2] }) }, elements.length)
|
|
4893
4948
|
);
|
|
4894
4949
|
i++;
|
|
4895
4950
|
continue;
|
|
@@ -4898,8 +4953,8 @@ function MarkdownText({ children }) {
|
|
|
4898
4953
|
if (bulletMatch) {
|
|
4899
4954
|
const indent = Math.floor((bulletMatch[1]?.length ?? 0) / 2);
|
|
4900
4955
|
elements.push(
|
|
4901
|
-
/* @__PURE__ */
|
|
4902
|
-
/* @__PURE__ */
|
|
4956
|
+
/* @__PURE__ */ jsxs5(Box5, { marginLeft: indent * 2, children: [
|
|
4957
|
+
/* @__PURE__ */ jsx5(Text5, { children: " \u25CF " }),
|
|
4903
4958
|
renderInline(bulletMatch[2])
|
|
4904
4959
|
] }, elements.length)
|
|
4905
4960
|
);
|
|
@@ -4910,8 +4965,8 @@ function MarkdownText({ children }) {
|
|
|
4910
4965
|
if (numMatch) {
|
|
4911
4966
|
const indent = Math.floor((numMatch[1]?.length ?? 0) / 2);
|
|
4912
4967
|
elements.push(
|
|
4913
|
-
/* @__PURE__ */
|
|
4914
|
-
/* @__PURE__ */
|
|
4968
|
+
/* @__PURE__ */ jsxs5(Box5, { marginLeft: indent * 2, children: [
|
|
4969
|
+
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
4915
4970
|
" ",
|
|
4916
4971
|
numMatch[2],
|
|
4917
4972
|
". "
|
|
@@ -4923,16 +4978,16 @@ function MarkdownText({ children }) {
|
|
|
4923
4978
|
continue;
|
|
4924
4979
|
}
|
|
4925
4980
|
if (line.trim() === "") {
|
|
4926
|
-
elements.push(/* @__PURE__ */
|
|
4981
|
+
elements.push(/* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(Text5, { children: " " }) }, elements.length));
|
|
4927
4982
|
i++;
|
|
4928
4983
|
continue;
|
|
4929
4984
|
}
|
|
4930
4985
|
elements.push(
|
|
4931
|
-
/* @__PURE__ */
|
|
4986
|
+
/* @__PURE__ */ jsx5(Box5, { flexWrap: "wrap", children: renderInline(line) }, elements.length)
|
|
4932
4987
|
);
|
|
4933
4988
|
i++;
|
|
4934
4989
|
}
|
|
4935
|
-
return /* @__PURE__ */
|
|
4990
|
+
return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: elements });
|
|
4936
4991
|
}
|
|
4937
4992
|
function renderInline(text3) {
|
|
4938
4993
|
const parts = [];
|
|
@@ -4945,7 +5000,7 @@ function renderInline(text3) {
|
|
|
4945
5000
|
candidates.push({
|
|
4946
5001
|
index: boldMatch.index,
|
|
4947
5002
|
length: boldMatch[0].length,
|
|
4948
|
-
node: /* @__PURE__ */
|
|
5003
|
+
node: /* @__PURE__ */ jsx5(Text5, { bold: true, children: boldMatch[1] ?? boldMatch[2] }, key++)
|
|
4949
5004
|
});
|
|
4950
5005
|
}
|
|
4951
5006
|
const codeMatch = /`([^`]+?)`/.exec(remaining);
|
|
@@ -4953,7 +5008,7 @@ function renderInline(text3) {
|
|
|
4953
5008
|
candidates.push({
|
|
4954
5009
|
index: codeMatch.index,
|
|
4955
5010
|
length: codeMatch[0].length,
|
|
4956
|
-
node: /* @__PURE__ */
|
|
5011
|
+
node: /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: codeMatch[1] }, key++)
|
|
4957
5012
|
});
|
|
4958
5013
|
}
|
|
4959
5014
|
const italicMatch = /(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)|(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/.exec(remaining);
|
|
@@ -4961,58 +5016,83 @@ function renderInline(text3) {
|
|
|
4961
5016
|
candidates.push({
|
|
4962
5017
|
index: italicMatch.index,
|
|
4963
5018
|
length: italicMatch[0].length,
|
|
4964
|
-
node: /* @__PURE__ */
|
|
5019
|
+
node: /* @__PURE__ */ jsx5(Text5, { italic: true, children: italicMatch[1] ?? italicMatch[2] }, key++)
|
|
4965
5020
|
});
|
|
4966
5021
|
}
|
|
4967
5022
|
candidates.sort((a, b) => a.index - b.index);
|
|
4968
5023
|
const pick = candidates[0];
|
|
4969
5024
|
if (!pick) {
|
|
4970
|
-
parts.push(/* @__PURE__ */
|
|
5025
|
+
parts.push(/* @__PURE__ */ jsx5(Text5, { children: remaining }, key++));
|
|
4971
5026
|
break;
|
|
4972
5027
|
}
|
|
4973
5028
|
if (pick.index > 0) {
|
|
4974
|
-
parts.push(/* @__PURE__ */
|
|
5029
|
+
parts.push(/* @__PURE__ */ jsx5(Text5, { children: remaining.slice(0, pick.index) }, key++));
|
|
4975
5030
|
}
|
|
4976
5031
|
parts.push(pick.node);
|
|
4977
5032
|
remaining = remaining.slice(pick.index + pick.length);
|
|
4978
5033
|
}
|
|
4979
|
-
return /* @__PURE__ */
|
|
5034
|
+
return /* @__PURE__ */ jsx5(Text5, { wrap: "wrap", children: parts });
|
|
4980
5035
|
}
|
|
4981
5036
|
|
|
5037
|
+
// src/ui/ErrorBoundary.tsx
|
|
5038
|
+
import React3 from "react";
|
|
5039
|
+
import { Text as Text6, Box as Box6 } from "ink";
|
|
5040
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
5041
|
+
var ErrorBoundary = class extends React3.Component {
|
|
5042
|
+
state = { error: null };
|
|
5043
|
+
static getDerivedStateFromError(error) {
|
|
5044
|
+
return { error };
|
|
5045
|
+
}
|
|
5046
|
+
componentDidCatch(error) {
|
|
5047
|
+
process.stderr.write(`[astra] Render error: ${error.message}
|
|
5048
|
+
`);
|
|
5049
|
+
}
|
|
5050
|
+
render() {
|
|
5051
|
+
if (this.state.error) {
|
|
5052
|
+
return this.props.fallback ?? /* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsxs6(Text6, { color: "red", dimColor: true, children: [
|
|
5053
|
+
"[render error: ",
|
|
5054
|
+
this.state.error.message,
|
|
5055
|
+
"]"
|
|
5056
|
+
] }) });
|
|
5057
|
+
}
|
|
5058
|
+
return this.props.children;
|
|
5059
|
+
}
|
|
5060
|
+
};
|
|
5061
|
+
|
|
4982
5062
|
// src/ui/ChatView.tsx
|
|
4983
|
-
import { jsx as
|
|
5063
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4984
5064
|
function ChatView({
|
|
4985
5065
|
messages,
|
|
4986
5066
|
streamingText
|
|
4987
5067
|
}) {
|
|
4988
|
-
return /* @__PURE__ */
|
|
5068
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflow: "hidden", paddingX: 1, children: [
|
|
4989
5069
|
messages.map((msg, i) => {
|
|
4990
5070
|
if (msg.role === "log") {
|
|
4991
|
-
return /* @__PURE__ */
|
|
5071
|
+
return /* @__PURE__ */ jsx7(Box7, { paddingLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: msg.content }) }, i);
|
|
4992
5072
|
}
|
|
4993
5073
|
if (msg.role === "autopilot") {
|
|
4994
|
-
return /* @__PURE__ */
|
|
4995
|
-
/* @__PURE__ */
|
|
4996
|
-
/* @__PURE__ */
|
|
5074
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, children: [
|
|
5075
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "#ff00ff", children: " Autopilot" }),
|
|
5076
|
+
/* @__PURE__ */ jsx7(Box7, { marginLeft: 1, children: /* @__PURE__ */ jsx7(Text7, { dimColor: true, wrap: "wrap", children: msg.content }) })
|
|
4997
5077
|
] }, i);
|
|
4998
5078
|
}
|
|
4999
|
-
return /* @__PURE__ */
|
|
5000
|
-
/* @__PURE__ */
|
|
5001
|
-
/* @__PURE__ */
|
|
5079
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, children: [
|
|
5080
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: msg.role === "user" ? "#00ff00" : "#00ffff", children: msg.role === "user" ? " You" : " Agent" }),
|
|
5081
|
+
/* @__PURE__ */ jsx7(Box7, { marginLeft: 1, children: msg.role === "assistant" ? /* @__PURE__ */ jsx7(ErrorBoundary, { children: /* @__PURE__ */ jsx7(MarkdownText, { children: msg.content }) }) : /* @__PURE__ */ jsx7(Text7, { wrap: "wrap", children: msg.content }) })
|
|
5002
5082
|
] }, i);
|
|
5003
5083
|
}),
|
|
5004
|
-
streamingText !== void 0 && streamingText.length > 0 && /* @__PURE__ */
|
|
5005
|
-
/* @__PURE__ */
|
|
5006
|
-
/* @__PURE__ */
|
|
5084
|
+
streamingText !== void 0 && streamingText.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginBottom: 1, children: [
|
|
5085
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "#00ffff", children: " Agent" }),
|
|
5086
|
+
/* @__PURE__ */ jsx7(Box7, { marginLeft: 1, children: /* @__PURE__ */ jsx7(ErrorBoundary, { children: /* @__PURE__ */ jsx7(MarkdownText, { children: streamingText }) }) })
|
|
5007
5087
|
] })
|
|
5008
5088
|
] });
|
|
5009
5089
|
}
|
|
5010
5090
|
|
|
5011
5091
|
// src/ui/Input.tsx
|
|
5012
5092
|
import { useState as useState2 } from "react";
|
|
5013
|
-
import { Box as
|
|
5093
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
5014
5094
|
import TextInput from "ink-text-input";
|
|
5015
|
-
import { jsx as
|
|
5095
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5016
5096
|
function Input({
|
|
5017
5097
|
isActive,
|
|
5018
5098
|
onSubmit
|
|
@@ -5024,9 +5104,9 @@ function Input({
|
|
|
5024
5104
|
onSubmit(trimmed);
|
|
5025
5105
|
setValue("");
|
|
5026
5106
|
};
|
|
5027
|
-
return /* @__PURE__ */
|
|
5028
|
-
/* @__PURE__ */
|
|
5029
|
-
/* @__PURE__ */
|
|
5107
|
+
return /* @__PURE__ */ jsxs8(Box8, { width: "100%", paddingX: 2, paddingY: 1, children: [
|
|
5108
|
+
/* @__PURE__ */ jsx8(Text8, { color: isActive ? "yellow" : "gray", bold: true, children: "\u276F\u276F " }),
|
|
5109
|
+
/* @__PURE__ */ jsx8(
|
|
5030
5110
|
TextInput,
|
|
5031
5111
|
{
|
|
5032
5112
|
value,
|
|
@@ -5042,10 +5122,10 @@ function Input({
|
|
|
5042
5122
|
|
|
5043
5123
|
// src/ui/Spinner.tsx
|
|
5044
5124
|
import { useState as useState3, useEffect as useEffect2 } from "react";
|
|
5045
|
-
import { Text as
|
|
5046
|
-
import { jsxs as
|
|
5125
|
+
import { Text as Text9 } from "ink";
|
|
5126
|
+
import { jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5047
5127
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
5048
|
-
var INTERVAL_MS =
|
|
5128
|
+
var INTERVAL_MS = 120;
|
|
5049
5129
|
function Spinner({ label }) {
|
|
5050
5130
|
const [frame, setFrame] = useState3(0);
|
|
5051
5131
|
useEffect2(() => {
|
|
@@ -5054,7 +5134,7 @@ function Spinner({ label }) {
|
|
|
5054
5134
|
}, INTERVAL_MS);
|
|
5055
5135
|
return () => clearInterval(timer);
|
|
5056
5136
|
}, []);
|
|
5057
|
-
return /* @__PURE__ */
|
|
5137
|
+
return /* @__PURE__ */ jsxs9(Text9, { color: "#ff00ff", children: [
|
|
5058
5138
|
FRAMES[frame],
|
|
5059
5139
|
" ",
|
|
5060
5140
|
label ?? "Thinking..."
|
|
@@ -5062,7 +5142,7 @@ function Spinner({ label }) {
|
|
|
5062
5142
|
}
|
|
5063
5143
|
|
|
5064
5144
|
// src/ui/App.tsx
|
|
5065
|
-
import { Fragment as Fragment3, jsx as
|
|
5145
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5066
5146
|
function App({
|
|
5067
5147
|
agentName,
|
|
5068
5148
|
skillContext,
|
|
@@ -5099,6 +5179,27 @@ function App({
|
|
|
5099
5179
|
isLoadingRef.current = isLoading;
|
|
5100
5180
|
}, [isLoading]);
|
|
5101
5181
|
const [toolName, setToolName] = useState4(void 0);
|
|
5182
|
+
const streamBufferRef = useRef2("");
|
|
5183
|
+
const streamFlushTimerRef = useRef2(null);
|
|
5184
|
+
const flushStreamBuffer = useCallback2(() => {
|
|
5185
|
+
streamFlushTimerRef.current = null;
|
|
5186
|
+
setStreamingText((prev) => (prev ?? "") + streamBufferRef.current);
|
|
5187
|
+
streamBufferRef.current = "";
|
|
5188
|
+
}, []);
|
|
5189
|
+
const appendStreamChunk = useCallback2((chunk) => {
|
|
5190
|
+
streamBufferRef.current += chunk;
|
|
5191
|
+
if (!streamFlushTimerRef.current) {
|
|
5192
|
+
streamFlushTimerRef.current = setTimeout(flushStreamBuffer, 50);
|
|
5193
|
+
}
|
|
5194
|
+
}, [flushStreamBuffer]);
|
|
5195
|
+
const clearStream = useCallback2(() => {
|
|
5196
|
+
if (streamFlushTimerRef.current) {
|
|
5197
|
+
clearTimeout(streamFlushTimerRef.current);
|
|
5198
|
+
streamFlushTimerRef.current = null;
|
|
5199
|
+
}
|
|
5200
|
+
streamBufferRef.current = "";
|
|
5201
|
+
clearStream();
|
|
5202
|
+
}, []);
|
|
5102
5203
|
const [autopilotMode, setAutopilotMode] = useState4(initialAutopilotConfig?.mode ?? "off");
|
|
5103
5204
|
const [autopilotIntervalMs, setAutopilotIntervalMs] = useState4(initialAutopilotConfig?.intervalMs ?? 3e5);
|
|
5104
5205
|
const epochCallCountRef = useRef2(0);
|
|
@@ -5168,7 +5269,7 @@ function App({
|
|
|
5168
5269
|
{ ...profile, autopilotMode },
|
|
5169
5270
|
{
|
|
5170
5271
|
onTextChunk: displayMode === "chat" ? (chunk) => {
|
|
5171
|
-
|
|
5272
|
+
appendStreamChunk(chunk);
|
|
5172
5273
|
} : () => {
|
|
5173
5274
|
},
|
|
5174
5275
|
onToolCallStart: displayMode === "chat" ? (name) => {
|
|
@@ -5188,7 +5289,7 @@ function App({
|
|
|
5188
5289
|
setCoreMessages(updatedCore);
|
|
5189
5290
|
const responseText = result.text.trim();
|
|
5190
5291
|
if (displayMode === "chat") {
|
|
5191
|
-
|
|
5292
|
+
clearStream();
|
|
5192
5293
|
setChatMessages((prev) => [
|
|
5193
5294
|
...prev,
|
|
5194
5295
|
{ role: "assistant", content: responseText || "Market checked \u2014 holding." }
|
|
@@ -5209,7 +5310,7 @@ function App({
|
|
|
5209
5310
|
} catch (error) {
|
|
5210
5311
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
5211
5312
|
if (displayMode === "chat") {
|
|
5212
|
-
|
|
5313
|
+
clearStream();
|
|
5213
5314
|
setChatMessages((prev) => [...prev, { role: "assistant", content: `Autopilot error: ${message}` }]);
|
|
5214
5315
|
} else {
|
|
5215
5316
|
addLogEntry("error", message);
|
|
@@ -5219,7 +5320,7 @@ function App({
|
|
|
5219
5320
|
if (displayMode === "chat") setToolName(void 0);
|
|
5220
5321
|
}
|
|
5221
5322
|
},
|
|
5222
|
-
[skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry]
|
|
5323
|
+
[skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry, appendStreamChunk, clearStream, pluginMap]
|
|
5223
5324
|
);
|
|
5224
5325
|
useEffect3(() => {
|
|
5225
5326
|
if (!hasAutopilot || autopilotMode === "off") return;
|
|
@@ -5517,7 +5618,7 @@ Let's go through it and improve or replace it.` : "I want to create a trading st
|
|
|
5517
5618
|
{ ...profile, autopilotMode },
|
|
5518
5619
|
{
|
|
5519
5620
|
onTextChunk: (chunk) => {
|
|
5520
|
-
|
|
5621
|
+
appendStreamChunk(chunk);
|
|
5521
5622
|
},
|
|
5522
5623
|
onToolCallStart: (name) => {
|
|
5523
5624
|
setToolName(name);
|
|
@@ -5550,7 +5651,7 @@ Let's go through it and improve or replace it.` : "I want to create a trading st
|
|
|
5550
5651
|
}
|
|
5551
5652
|
setChatMessages(updatedChat);
|
|
5552
5653
|
setCoreMessages(updatedCore);
|
|
5553
|
-
|
|
5654
|
+
clearStream();
|
|
5554
5655
|
saveSession({
|
|
5555
5656
|
agentName,
|
|
5556
5657
|
provider: providerRef.current,
|
|
@@ -5576,13 +5677,13 @@ ${stack}
|
|
|
5576
5677
|
{ role: "assistant", content: `Error: ${message}${debugInfo}` }
|
|
5577
5678
|
]);
|
|
5578
5679
|
setCoreMessages(newCoreMessages);
|
|
5579
|
-
|
|
5680
|
+
clearStream();
|
|
5580
5681
|
} finally {
|
|
5581
5682
|
setIsLoading(false);
|
|
5582
5683
|
setToolName(void 0);
|
|
5583
5684
|
}
|
|
5584
5685
|
},
|
|
5585
|
-
[coreMessages, chatMessages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry]
|
|
5686
|
+
[coreMessages, chatMessages, skillContext, tradingContext, walletContext, rewardsContext, onboardingContext, apiContext, profile, autopilotMode, agentName, sessionId, memoryContent, addLogEntry, pluginMap, hasAutopilot, hasJourneyStages, exit, debug, appendStreamChunk, clearStream, runAutopilotTurn]
|
|
5586
5687
|
);
|
|
5587
5688
|
useEffect3(() => {
|
|
5588
5689
|
sendMessageRef.current = sendMessage;
|
|
@@ -5593,12 +5694,12 @@ ${stack}
|
|
|
5593
5694
|
},
|
|
5594
5695
|
[sendMessage]
|
|
5595
5696
|
);
|
|
5596
|
-
return /* @__PURE__ */
|
|
5597
|
-
/* @__PURE__ */
|
|
5598
|
-
isLoading && toolName && /* @__PURE__ */
|
|
5599
|
-
isLoading && !toolName && /* @__PURE__ */
|
|
5600
|
-
/* @__PURE__ */
|
|
5601
|
-
/* @__PURE__ */
|
|
5697
|
+
return /* @__PURE__ */ jsxs10(Box9, { flexDirection: "column", width: "100%", height: "100%", children: [
|
|
5698
|
+
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", flexGrow: 1, flexShrink: 1, children: /* @__PURE__ */ jsx9(ChatView, { messages: chatMessages, streamingText }) }),
|
|
5699
|
+
isLoading && toolName && /* @__PURE__ */ jsx9(Spinner, { label: `Calling ${toolName}...` }),
|
|
5700
|
+
isLoading && !toolName && /* @__PURE__ */ jsx9(Spinner, { label: streamingText ? "Thinking..." : void 0 }),
|
|
5701
|
+
/* @__PURE__ */ jsx9(Box9, { flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsx9(Input, { isActive: !isLoading, onSubmit: handleSubmit }) }),
|
|
5702
|
+
/* @__PURE__ */ jsx9(Box9, { flexShrink: 0, width: "100%", children: /* @__PURE__ */ jsx9(
|
|
5602
5703
|
StatusBar_default,
|
|
5603
5704
|
{
|
|
5604
5705
|
agentName,
|
|
@@ -5611,12 +5712,12 @@ ${stack}
|
|
|
5611
5712
|
pluginMap
|
|
5612
5713
|
}
|
|
5613
5714
|
) }),
|
|
5614
|
-
/* @__PURE__ */
|
|
5615
|
-
/* @__PURE__ */
|
|
5616
|
-
/* @__PURE__ */
|
|
5617
|
-
] }) : /* @__PURE__ */
|
|
5618
|
-
/* @__PURE__ */
|
|
5619
|
-
/* @__PURE__ */
|
|
5715
|
+
/* @__PURE__ */ jsx9(Box9, { flexShrink: 0, width: "100%", paddingX: 2, marginTop: 1, justifyContent: "space-between", children: hasJourneyStages ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5716
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "/help \xB7 /portfolio \xB7 /market \xB7 /strategy \xB7 /exit" }),
|
|
5717
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: "/auto on\xB7off\xB7set \xB7 Ctrl+C quit" })
|
|
5718
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5719
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: (pluginMap?.commands?.map((c) => c.command).join(" \xB7 ") ?? "/help") + " \xB7 /exit" }),
|
|
5720
|
+
/* @__PURE__ */ jsx9(Text10, { dimColor: true, children: manifest.name })
|
|
5620
5721
|
] }) })
|
|
5621
5722
|
] });
|
|
5622
5723
|
}
|
|
@@ -5795,8 +5896,9 @@ async function main() {
|
|
|
5795
5896
|
let sessionId = newSessionId();
|
|
5796
5897
|
let initialCoreMessages;
|
|
5797
5898
|
let initialChatMessages;
|
|
5899
|
+
let session = null;
|
|
5798
5900
|
if (shouldContinue) {
|
|
5799
|
-
|
|
5901
|
+
session = loadLatestSession(agentName);
|
|
5800
5902
|
if (session) {
|
|
5801
5903
|
const updatedAt = new Date(session.updatedAt);
|
|
5802
5904
|
const minutesAgo = Math.round((Date.now() - updatedAt.getTime()) / 6e4);
|
|
@@ -5810,31 +5912,32 @@ async function main() {
|
|
|
5810
5912
|
}
|
|
5811
5913
|
}
|
|
5812
5914
|
const initialAutopilotConfig = loadAutopilotConfig();
|
|
5813
|
-
const lastSessionAt = shouldContinue ? (
|
|
5814
|
-
const s = loadLatestSession(agentName);
|
|
5815
|
-
return s ? new Date(s.updatedAt) : null;
|
|
5816
|
-
})() : null;
|
|
5915
|
+
const lastSessionAt = shouldContinue && session ? new Date(session.updatedAt) : null;
|
|
5817
5916
|
const pendingTrades = loadAutopilotLogSince(agentName, lastSessionAt);
|
|
5818
5917
|
const initialPendingTrades = pendingTrades.length;
|
|
5819
5918
|
const { waitUntilExit } = render(
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5919
|
+
React7.createElement(
|
|
5920
|
+
AppErrorBoundary,
|
|
5921
|
+
null,
|
|
5922
|
+
React7.createElement(App, {
|
|
5923
|
+
agentName,
|
|
5924
|
+
skillContext,
|
|
5925
|
+
tradingContext,
|
|
5926
|
+
walletContext,
|
|
5927
|
+
rewardsContext,
|
|
5928
|
+
onboardingContext,
|
|
5929
|
+
apiContext,
|
|
5930
|
+
profile,
|
|
5931
|
+
sessionId,
|
|
5932
|
+
memoryContent,
|
|
5933
|
+
initialCoreMessages,
|
|
5934
|
+
initialChatMessages,
|
|
5935
|
+
initialAutopilotConfig,
|
|
5936
|
+
initialPendingTrades,
|
|
5937
|
+
debug,
|
|
5938
|
+
pluginMap
|
|
5939
|
+
})
|
|
5940
|
+
)
|
|
5838
5941
|
);
|
|
5839
5942
|
await waitUntilExit();
|
|
5840
5943
|
if (isPluginsPickerRequested()) {
|