nyxora 1.0.2 → 1.0.4
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/package.json +10 -1
- package/.env.example +0 -17
- package/dashboard/eslint.config.js +0 -22
- package/dashboard/index.html +0 -13
- package/dashboard/package-lock.json +0 -2737
- package/dashboard/package.json +0 -31
- package/dashboard/public/favicon.svg +0 -1
- package/dashboard/public/icons.svg +0 -24
- package/dashboard/src/App.css +0 -184
- package/dashboard/src/App.tsx +0 -485
- package/dashboard/src/BalanceWidget.tsx +0 -65
- package/dashboard/src/MarketWidget.tsx +0 -73
- package/dashboard/src/Memory.tsx +0 -109
- package/dashboard/src/Overview.tsx +0 -156
- package/dashboard/src/Settings.tsx +0 -213
- package/dashboard/src/Skills.tsx +0 -97
- package/dashboard/src/SwapWidget.tsx +0 -130
- package/dashboard/src/TransactionWidget.tsx +0 -86
- package/dashboard/src/assets/hero.png +0 -0
- package/dashboard/src/assets/react.svg +0 -1
- package/dashboard/src/assets/vite.svg +0 -1
- package/dashboard/src/index.css +0 -508
- package/dashboard/src/main.tsx +0 -10
- package/dashboard/src/overview.css +0 -304
- package/dashboard/tsconfig.app.json +0 -25
- package/dashboard/tsconfig.json +0 -7
- package/dashboard/tsconfig.node.json +0 -24
- package/dashboard/vite.config.ts +0 -7
- package/src/agent/reasoning.d.ts +0 -2
- package/src/agent/reasoning.d.ts.map +0 -1
- package/src/agent/reasoning.js +0 -97
- package/src/agent/reasoning.js.map +0 -1
- package/src/agent/reasoning.ts +0 -232
- package/src/config/parser.d.ts +0 -17
- package/src/config/parser.d.ts.map +0 -1
- package/src/config/parser.js +0 -26
- package/src/config/parser.js.map +0 -1
- package/src/config/parser.ts +0 -47
- package/src/config/paths.ts +0 -33
- package/src/gateway/cli.d.ts +0 -3
- package/src/gateway/cli.d.ts.map +0 -1
- package/src/gateway/cli.js +0 -80
- package/src/gateway/cli.js.map +0 -1
- package/src/gateway/cli.ts +0 -69
- package/src/gateway/server.ts +0 -135
- package/src/gateway/telegram.ts +0 -47
- package/src/gateway/test.ts +0 -16
- package/src/gateway/tracker.ts +0 -70
- package/src/memory/logger.d.ts +0 -18
- package/src/memory/logger.d.ts.map +0 -1
- package/src/memory/logger.js +0 -51
- package/src/memory/logger.js.map +0 -1
- package/src/memory/logger.ts +0 -57
- package/src/web3/config.d.ts +0 -793
- package/src/web3/config.d.ts.map +0 -1
- package/src/web3/config.js +0 -81
- package/src/web3/config.js.map +0 -1
- package/src/web3/config.ts +0 -51
- package/src/web3/skills/getBalance.d.ts +0 -25
- package/src/web3/skills/getBalance.d.ts.map +0 -1
- package/src/web3/skills/getBalance.js +0 -46
- package/src/web3/skills/getBalance.js.map +0 -1
- package/src/web3/skills/getBalance.ts +0 -48
- package/src/web3/skills/getPrice.ts +0 -43
- package/src/web3/skills/swapToken.ts +0 -69
- package/src/web3/skills/transfer.ts +0 -47
- package/tsconfig.json +0 -13
package/dashboard/src/Memory.tsx
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { Trash2, Download } from 'lucide-react';
|
|
3
|
-
|
|
4
|
-
interface MemoryEntry {
|
|
5
|
-
role: 'user' | 'assistant' | 'tool' | 'system';
|
|
6
|
-
content: string;
|
|
7
|
-
name?: string;
|
|
8
|
-
tool_calls?: any[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const Memory: React.FC = () => {
|
|
12
|
-
const [history, setHistory] = useState<MemoryEntry[]>([]);
|
|
13
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
14
|
-
|
|
15
|
-
const fetchMemory = async () => {
|
|
16
|
-
try {
|
|
17
|
-
const res = await fetch('http://localhost:3000/api/history');
|
|
18
|
-
if (res.ok) {
|
|
19
|
-
setHistory(await res.json());
|
|
20
|
-
}
|
|
21
|
-
} catch (e) {
|
|
22
|
-
console.error(e);
|
|
23
|
-
} finally {
|
|
24
|
-
setIsLoading(false);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
fetchMemory();
|
|
30
|
-
}, []);
|
|
31
|
-
|
|
32
|
-
const handleClear = async () => {
|
|
33
|
-
if (!confirm('Are you sure you want to wipe the agent memory? This cannot be undone.')) return;
|
|
34
|
-
try {
|
|
35
|
-
await fetch('http://localhost:3000/api/history', { method: 'DELETE' });
|
|
36
|
-
setHistory([]);
|
|
37
|
-
} catch (e) {
|
|
38
|
-
console.error(e);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const handleExport = () => {
|
|
43
|
-
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(history, null, 2));
|
|
44
|
-
const downloadAnchorNode = document.createElement('a');
|
|
45
|
-
downloadAnchorNode.setAttribute("href", dataStr);
|
|
46
|
-
downloadAnchorNode.setAttribute("download", "agent_memory.json");
|
|
47
|
-
document.body.appendChild(downloadAnchorNode);
|
|
48
|
-
downloadAnchorNode.click();
|
|
49
|
-
downloadAnchorNode.remove();
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
if (isLoading) return <div className="overview-container">Loading memory...</div>;
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<div className="overview-container">
|
|
56
|
-
<div className="overview-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
|
57
|
-
<div>
|
|
58
|
-
<h1>Memory Vault</h1>
|
|
59
|
-
<p>Long-term storage and conversational context of the Agent.</p>
|
|
60
|
-
</div>
|
|
61
|
-
<div style={{ display: 'flex', gap: '12px' }}>
|
|
62
|
-
<button className="btn-secondary" onClick={handleExport}>
|
|
63
|
-
<Download size={14} style={{ marginRight: '6px', display: 'inline' }}/>
|
|
64
|
-
Export JSON
|
|
65
|
-
</button>
|
|
66
|
-
<button className="btn-primary" style={{ background: '#ef4444' }} onClick={handleClear}>
|
|
67
|
-
<Trash2 size={14} style={{ marginRight: '6px', display: 'inline' }}/>
|
|
68
|
-
Wipe Memory
|
|
69
|
-
</button>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<div className="panel">
|
|
74
|
-
{history.length === 0 ? (
|
|
75
|
-
<div style={{ color: '#94a3b8', textAlign: 'center', padding: '40px' }}>Memory is completely empty.</div>
|
|
76
|
-
) : (
|
|
77
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
78
|
-
{history.map((entry, idx) => (
|
|
79
|
-
<div key={idx} style={{
|
|
80
|
-
padding: '16px',
|
|
81
|
-
borderRadius: '8px',
|
|
82
|
-
background: entry.role === 'user' ? 'rgba(59, 130, 246, 0.1)' :
|
|
83
|
-
entry.role === 'assistant' ? 'rgba(34, 197, 94, 0.1)' : 'rgba(255, 255, 255, 0.05)',
|
|
84
|
-
borderLeft: `4px solid ${entry.role === 'user' ? '#3b82f6' : entry.role === 'assistant' ? '#22c55e' : '#94a3b8'}`
|
|
85
|
-
}}>
|
|
86
|
-
<div style={{ fontSize: '0.75rem', textTransform: 'uppercase', color: '#94a3b8', marginBottom: '8px' }}>
|
|
87
|
-
{entry.role} {entry.name ? `(${entry.name})` : ''}
|
|
88
|
-
</div>
|
|
89
|
-
<div style={{ fontSize: '0.9rem', whiteSpace: 'pre-wrap' }}>
|
|
90
|
-
{entry.content}
|
|
91
|
-
</div>
|
|
92
|
-
{entry.tool_calls && entry.tool_calls.length > 0 && (
|
|
93
|
-
<div style={{ marginTop: '12px', fontSize: '0.8rem', color: '#fb923c' }}>
|
|
94
|
-
<strong>Tool Calls:</strong>
|
|
95
|
-
<pre style={{ background: 'rgba(0,0,0,0.3)', padding: '8px', borderRadius: '4px', marginTop: '4px' }}>
|
|
96
|
-
{JSON.stringify(entry.tool_calls, null, 2)}
|
|
97
|
-
</pre>
|
|
98
|
-
</div>
|
|
99
|
-
)}
|
|
100
|
-
</div>
|
|
101
|
-
))}
|
|
102
|
-
</div>
|
|
103
|
-
)}
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export default Memory;
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import './overview.css';
|
|
3
|
-
|
|
4
|
-
interface Config {
|
|
5
|
-
agent: { name: string; default_chain: string };
|
|
6
|
-
llm: { provider: string; model: string; temperature: number };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface Stats {
|
|
10
|
-
cost: number;
|
|
11
|
-
tokens: number;
|
|
12
|
-
messages: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface EventLog {
|
|
16
|
-
timestamp: string;
|
|
17
|
-
event: string;
|
|
18
|
-
meta: any;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface GatewayLog {
|
|
22
|
-
timestamp: string;
|
|
23
|
-
message: string;
|
|
24
|
-
meta?: any;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
interface OverviewProps {
|
|
28
|
-
config: Config | null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const Overview: React.FC<OverviewProps> = ({ config }) => {
|
|
32
|
-
const [stats, setStats] = useState<Stats>({ cost: 0, tokens: 0, messages: 0 });
|
|
33
|
-
const [events, setEvents] = useState<EventLog[]>([]);
|
|
34
|
-
const [gatewayLogs, setGatewayLogs] = useState<GatewayLog[]>([]);
|
|
35
|
-
const eventLogsEndRef = useRef<HTMLDivElement>(null);
|
|
36
|
-
const gatewayLogsEndRef = useRef<HTMLDivElement>(null);
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
const fetchData = async () => {
|
|
40
|
-
try {
|
|
41
|
-
const statsRes = await fetch('http://localhost:3000/api/stats');
|
|
42
|
-
if (statsRes.ok) setStats(await statsRes.json());
|
|
43
|
-
|
|
44
|
-
const logsRes = await fetch('http://localhost:3000/api/logs');
|
|
45
|
-
if (logsRes.ok) {
|
|
46
|
-
const logs = await logsRes.json();
|
|
47
|
-
setEvents(logs.events);
|
|
48
|
-
setGatewayLogs(logs.gateway);
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.error("Failed to fetch analytics");
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
fetchData();
|
|
56
|
-
const interval = setInterval(fetchData, 2000);
|
|
57
|
-
return () => clearInterval(interval);
|
|
58
|
-
}, []);
|
|
59
|
-
|
|
60
|
-
if (!config) return <div className="overview-container">Loading...</div>;
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<div className="overview-container">
|
|
64
|
-
<div className="overview-header">
|
|
65
|
-
<h1>Nyxora Status</h1>
|
|
66
|
-
<p>System health, active configuration, and loaded Web3 skills.</p>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<div className="panel gateway-access">
|
|
70
|
-
<div className="panel-header">
|
|
71
|
-
<h3>System Configuration</h3>
|
|
72
|
-
<p>Current runtime parameters for your Web3 Agent.</p>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div className="form-row">
|
|
76
|
-
<div className="form-group flex-1">
|
|
77
|
-
<label>API Endpoint</label>
|
|
78
|
-
<input type="text" value="http://localhost:3000/api/chat" readOnly />
|
|
79
|
-
</div>
|
|
80
|
-
<div className="form-group flex-1">
|
|
81
|
-
<label>Agent Name</label>
|
|
82
|
-
<input type="text" value={config.agent.name} readOnly />
|
|
83
|
-
</div>
|
|
84
|
-
<div className="form-group flex-1">
|
|
85
|
-
<label>Memory Storage</label>
|
|
86
|
-
<input type="text" value="./memory.json" readOnly />
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div className="metrics-grid">
|
|
92
|
-
<div className="metric-card">
|
|
93
|
-
<label>COST</label>
|
|
94
|
-
<div className="metric-val">${stats.cost.toFixed(4)}</div>
|
|
95
|
-
<div className="metric-sub">{stats.tokens} tokens - {stats.messages} msgs</div>
|
|
96
|
-
</div>
|
|
97
|
-
<div className="metric-card">
|
|
98
|
-
<label>SESSIONS</label>
|
|
99
|
-
<div className="metric-val">1</div>
|
|
100
|
-
<div className="metric-sub">Local chat session active</div>
|
|
101
|
-
</div>
|
|
102
|
-
<div className="metric-card">
|
|
103
|
-
<label>SKILLS</label>
|
|
104
|
-
<div className="metric-val">2/2</div>
|
|
105
|
-
<div className="metric-sub">2 Web3 skills loaded</div>
|
|
106
|
-
</div>
|
|
107
|
-
<div className="metric-card">
|
|
108
|
-
<label>CRON</label>
|
|
109
|
-
<div className="metric-val">0 jobs</div>
|
|
110
|
-
<div className="metric-sub">No scheduled tasks</div>
|
|
111
|
-
</div>
|
|
112
|
-
<div className="metric-card">
|
|
113
|
-
<label>MODEL AUTH</label>
|
|
114
|
-
<div className="metric-val text-green">1 ok</div>
|
|
115
|
-
<div className="metric-sub">{config.llm.provider.toUpperCase()} provider connected</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
|
|
119
|
-
<div className="logs-grid">
|
|
120
|
-
<div className="log-panel">
|
|
121
|
-
<div className="log-header">
|
|
122
|
-
<span>Event Log <span className="badge">{events.length}</span></span>
|
|
123
|
-
</div>
|
|
124
|
-
<div className="log-content">
|
|
125
|
-
{events.map((log, i) => (
|
|
126
|
-
<div key={i} className="log-row">
|
|
127
|
-
<span className="log-time">{log.timestamp}</span>
|
|
128
|
-
<span className="log-msg">
|
|
129
|
-
{log.event} <span className="log-meta">{JSON.stringify(log.meta)}</span>
|
|
130
|
-
</span>
|
|
131
|
-
</div>
|
|
132
|
-
))}
|
|
133
|
-
<div ref={eventLogsEndRef} />
|
|
134
|
-
</div>
|
|
135
|
-
</div>
|
|
136
|
-
<div className="log-panel">
|
|
137
|
-
<div className="log-header">
|
|
138
|
-
<span>Gateway Logs <span className="badge">{gatewayLogs.length}</span></span>
|
|
139
|
-
</div>
|
|
140
|
-
<div className="log-content">
|
|
141
|
-
{gatewayLogs.map((log, i) => (
|
|
142
|
-
<div key={i} className="log-row gateway-row">
|
|
143
|
-
<span className="log-json">
|
|
144
|
-
{`{"timestamp":"${log.timestamp}","message":${JSON.stringify(log.message)}${log.meta ? `,"meta":${JSON.stringify(log.meta)}` : ''}}`}
|
|
145
|
-
</span>
|
|
146
|
-
</div>
|
|
147
|
-
))}
|
|
148
|
-
<div ref={gatewayLogsEndRef} />
|
|
149
|
-
</div>
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
export default Overview;
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { Save } from 'lucide-react';
|
|
3
|
-
|
|
4
|
-
interface Config {
|
|
5
|
-
agent: { name: string; default_chain: string };
|
|
6
|
-
llm: { provider: string; model: string; temperature: number; api_keys?: string[] };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface SettingsProps {
|
|
10
|
-
config: Config | null;
|
|
11
|
-
onConfigChange: (newConfig: Config) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const Settings: React.FC<SettingsProps> = ({ config, onConfigChange }) => {
|
|
15
|
-
const [formData, setFormData] = useState<Config | null>(null);
|
|
16
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (config) setFormData(config);
|
|
20
|
-
}, [config]);
|
|
21
|
-
|
|
22
|
-
if (!formData) return <div className="overview-container">Loading settings...</div>;
|
|
23
|
-
|
|
24
|
-
const handleChange = (section: 'agent' | 'llm', field: string, value: string | number) => {
|
|
25
|
-
setFormData(prev => {
|
|
26
|
-
if (!prev) return prev;
|
|
27
|
-
return {
|
|
28
|
-
...prev,
|
|
29
|
-
[section]: {
|
|
30
|
-
...prev[section],
|
|
31
|
-
[field]: field === 'temperature' ? Number(value) : value
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const handleAddApiKey = () => {
|
|
38
|
-
setFormData(prev => {
|
|
39
|
-
if (!prev) return prev;
|
|
40
|
-
const currentKeys = prev.llm.api_keys || [];
|
|
41
|
-
if (currentKeys.length >= 10) return prev;
|
|
42
|
-
return { ...prev, llm: { ...prev.llm, api_keys: [...currentKeys, ''] } };
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const handleUpdateApiKey = (index: number, value: string) => {
|
|
47
|
-
setFormData(prev => {
|
|
48
|
-
if (!prev) return prev;
|
|
49
|
-
const newKeys = [...(prev.llm.api_keys || [])];
|
|
50
|
-
newKeys[index] = value;
|
|
51
|
-
return { ...prev, llm: { ...prev.llm, api_keys: newKeys } };
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const handleRemoveApiKey = (index: number) => {
|
|
56
|
-
setFormData(prev => {
|
|
57
|
-
if (!prev) return prev;
|
|
58
|
-
const newKeys = [...(prev.llm.api_keys || [])];
|
|
59
|
-
newKeys.splice(index, 1);
|
|
60
|
-
return { ...prev, llm: { ...prev.llm, api_keys: newKeys } };
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const handleSave = async () => {
|
|
65
|
-
setIsSaving(true);
|
|
66
|
-
try {
|
|
67
|
-
const res = await fetch('http://localhost:3000/api/config', {
|
|
68
|
-
method: 'POST',
|
|
69
|
-
headers: { 'Content-Type': 'application/json' },
|
|
70
|
-
body: JSON.stringify(formData)
|
|
71
|
-
});
|
|
72
|
-
if (res.ok) {
|
|
73
|
-
onConfigChange(formData);
|
|
74
|
-
alert('Settings saved successfully!');
|
|
75
|
-
}
|
|
76
|
-
} catch (e) {
|
|
77
|
-
console.error(e);
|
|
78
|
-
alert('Failed to save settings');
|
|
79
|
-
} finally {
|
|
80
|
-
setIsSaving(false);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<div className="overview-container">
|
|
86
|
-
<div className="overview-header">
|
|
87
|
-
<h1>Configuration</h1>
|
|
88
|
-
<p>Modify the core behaviors and parameters of the Nyxora Agent.</p>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div className="panel">
|
|
92
|
-
<div className="panel-header">
|
|
93
|
-
<h3>Agent Profile</h3>
|
|
94
|
-
</div>
|
|
95
|
-
<div className="form-row">
|
|
96
|
-
<div className="form-group flex-1">
|
|
97
|
-
<label>Agent Name</label>
|
|
98
|
-
<input
|
|
99
|
-
type="text"
|
|
100
|
-
value={formData.agent.name}
|
|
101
|
-
onChange={e => handleChange('agent', 'name', e.target.value)}
|
|
102
|
-
/>
|
|
103
|
-
</div>
|
|
104
|
-
<div className="form-group flex-1">
|
|
105
|
-
<label>Default Web3 Chain</label>
|
|
106
|
-
<select
|
|
107
|
-
value={formData.agent.default_chain}
|
|
108
|
-
onChange={e => handleChange('agent', 'default_chain', e.target.value)}
|
|
109
|
-
>
|
|
110
|
-
<option value="sepolia">Sepolia Testnet</option>
|
|
111
|
-
<option value="ethereum">Ethereum Mainnet</option>
|
|
112
|
-
<option value="base">Base</option>
|
|
113
|
-
<option value="bsc">BNB Chain</option>
|
|
114
|
-
<option value="arbitrum">Arbitrum</option>
|
|
115
|
-
<option value="optimism">Optimism</option>
|
|
116
|
-
</select>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<div className="panel">
|
|
122
|
-
<div className="panel-header">
|
|
123
|
-
<h3>LLM Engine</h3>
|
|
124
|
-
</div>
|
|
125
|
-
<div className="form-row">
|
|
126
|
-
<div className="form-group flex-1">
|
|
127
|
-
<label>Provider</label>
|
|
128
|
-
<select
|
|
129
|
-
value={formData.llm.provider}
|
|
130
|
-
onChange={e => handleChange('llm', 'provider', e.target.value)}
|
|
131
|
-
>
|
|
132
|
-
<option value="gemini">Google Gemini</option>
|
|
133
|
-
<option value="openai">OpenAI</option>
|
|
134
|
-
<option value="ollama">Ollama (Local)</option>
|
|
135
|
-
</select>
|
|
136
|
-
</div>
|
|
137
|
-
<div className="form-group flex-1">
|
|
138
|
-
<label>Model Name</label>
|
|
139
|
-
<input
|
|
140
|
-
type="text"
|
|
141
|
-
value={formData.llm.model}
|
|
142
|
-
onChange={e => handleChange('llm', 'model', e.target.value)}
|
|
143
|
-
/>
|
|
144
|
-
</div>
|
|
145
|
-
<div className="form-group flex-1">
|
|
146
|
-
<label>Temperature ({formData.llm.temperature})</label>
|
|
147
|
-
<input
|
|
148
|
-
type="range"
|
|
149
|
-
min="0" max="1" step="0.1"
|
|
150
|
-
value={formData.llm.temperature}
|
|
151
|
-
onChange={e => handleChange('llm', 'temperature', e.target.value)}
|
|
152
|
-
style={{ padding: '0', background: 'transparent' }}
|
|
153
|
-
/>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<div className="panel">
|
|
159
|
-
<div className="panel-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
160
|
-
<h3>API Keys (Rotation)</h3>
|
|
161
|
-
<span style={{ fontSize: '0.8rem', color: '#94a3b8' }}>
|
|
162
|
-
{formData.llm.api_keys?.length || 0} / 10 Keys
|
|
163
|
-
</span>
|
|
164
|
-
</div>
|
|
165
|
-
<p style={{ fontSize: '0.85rem', color: '#64748b', marginBottom: '16px' }}>
|
|
166
|
-
Add up to 10 API keys. The system will automatically rotate through them (Round-Robin) for each request to prevent rate limits. Leave empty to fallback to .env file.
|
|
167
|
-
</p>
|
|
168
|
-
|
|
169
|
-
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
170
|
-
{(formData.llm.api_keys || []).map((key, index) => (
|
|
171
|
-
<div key={index} style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
|
|
172
|
-
<input
|
|
173
|
-
type="password"
|
|
174
|
-
value={key}
|
|
175
|
-
placeholder="sk-..."
|
|
176
|
-
onChange={(e) => handleUpdateApiKey(index, e.target.value)}
|
|
177
|
-
style={{ flex: 1, padding: '10px 14px', background: 'rgba(15, 23, 42, 0.5)', border: '1px solid var(--glass-border)', borderRadius: '6px', color: 'white' }}
|
|
178
|
-
/>
|
|
179
|
-
<button
|
|
180
|
-
onClick={() => handleRemoveApiKey(index)}
|
|
181
|
-
style={{ background: 'rgba(239, 68, 68, 0.1)', color: '#ef4444', border: '1px solid rgba(239, 68, 68, 0.3)', borderRadius: '6px', padding: '10px 14px', cursor: 'pointer', transition: 'all 0.2s' }}
|
|
182
|
-
onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(239, 68, 68, 0.2)'}
|
|
183
|
-
onMouseLeave={(e) => e.currentTarget.style.background = 'rgba(239, 68, 68, 0.1)'}
|
|
184
|
-
>
|
|
185
|
-
Delete
|
|
186
|
-
</button>
|
|
187
|
-
</div>
|
|
188
|
-
))}
|
|
189
|
-
|
|
190
|
-
{(!formData.llm.api_keys || formData.llm.api_keys.length < 10) && (
|
|
191
|
-
<button
|
|
192
|
-
onClick={handleAddApiKey}
|
|
193
|
-
style={{ alignSelf: 'flex-start', background: 'rgba(59, 130, 246, 0.1)', color: '#3b82f6', border: '1px dashed #3b82f6', borderRadius: '6px', padding: '8px 16px', cursor: 'pointer', marginTop: '8px', transition: 'all 0.2s' }}
|
|
194
|
-
onMouseEnter={(e) => e.currentTarget.style.background = 'rgba(59, 130, 246, 0.2)'}
|
|
195
|
-
onMouseLeave={(e) => e.currentTarget.style.background = 'rgba(59, 130, 246, 0.1)'}
|
|
196
|
-
>
|
|
197
|
-
+ Add API Key
|
|
198
|
-
</button>
|
|
199
|
-
)}
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
<div className="form-actions" style={{ justifyContent: 'flex-end', marginTop: '32px' }}>
|
|
204
|
-
<button className="btn-primary" onClick={handleSave} disabled={isSaving}>
|
|
205
|
-
<Save size={16} style={{ marginRight: '8px', display: 'inline' }} />
|
|
206
|
-
{isSaving ? 'Saving...' : 'Save Configuration'}
|
|
207
|
-
</button>
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
);
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
export default Settings;
|
package/dashboard/src/Skills.tsx
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { Compass, Code } from 'lucide-react';
|
|
3
|
-
|
|
4
|
-
interface SkillParam {
|
|
5
|
-
type: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
enum?: string[];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface SkillDefinition {
|
|
11
|
-
type: string;
|
|
12
|
-
function: {
|
|
13
|
-
name: string;
|
|
14
|
-
description: string;
|
|
15
|
-
parameters: {
|
|
16
|
-
type: string;
|
|
17
|
-
properties: Record<string, SkillParam>;
|
|
18
|
-
required: string[];
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const Skills: React.FC = () => {
|
|
24
|
-
const [skills, setSkills] = useState<SkillDefinition[]>([]);
|
|
25
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
const fetchSkills = async () => {
|
|
29
|
-
try {
|
|
30
|
-
const res = await fetch('http://localhost:3000/api/skills');
|
|
31
|
-
if (res.ok) setSkills(await res.json());
|
|
32
|
-
} catch (e) {
|
|
33
|
-
console.error(e);
|
|
34
|
-
} finally {
|
|
35
|
-
setIsLoading(false);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
fetchSkills();
|
|
39
|
-
}, []);
|
|
40
|
-
|
|
41
|
-
if (isLoading) return <div className="overview-container">Loading skills...</div>;
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<div className="overview-container">
|
|
45
|
-
<div className="overview-header">
|
|
46
|
-
<h1>Web3 Capabilities</h1>
|
|
47
|
-
<p>Explore the autonomous on-chain functions currently loaded into the Agent's neural network.</p>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(350px, 1fr))', gap: '20px' }}>
|
|
51
|
-
{skills.map((skill, idx) => (
|
|
52
|
-
<div key={idx} className="panel" style={{ display: 'flex', flexDirection: 'column' }}>
|
|
53
|
-
<div className="panel-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: '1px solid rgba(255,255,255,0.05)', paddingBottom: '12px' }}>
|
|
54
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
55
|
-
<Compass size={18} color="#3b82f6" />
|
|
56
|
-
<h3 style={{ margin: 0, fontFamily: 'monospace', fontSize: '1.1rem', color: '#60a5fa' }}>
|
|
57
|
-
{skill.function.name}
|
|
58
|
-
</h3>
|
|
59
|
-
</div>
|
|
60
|
-
<span className="badge" style={{ background: 'rgba(34, 197, 94, 0.2)', color: '#4ade80' }}>Active</span>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<div style={{ padding: '16px 0', flex: 1 }}>
|
|
64
|
-
<p style={{ color: '#d1d5db', fontSize: '0.9rem', lineHeight: '1.5' }}>
|
|
65
|
-
{skill.function.description}
|
|
66
|
-
</p>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<div style={{ background: 'rgba(0,0,0,0.3)', borderRadius: '6px', padding: '12px', border: '1px solid rgba(255,255,255,0.05)' }}>
|
|
70
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginBottom: '8px', color: '#9ca3af', fontSize: '0.8rem', textTransform: 'uppercase' }}>
|
|
71
|
-
<Code size={12} />
|
|
72
|
-
<span>Parameters Schema</span>
|
|
73
|
-
</div>
|
|
74
|
-
<pre style={{
|
|
75
|
-
margin: 0,
|
|
76
|
-
fontFamily: 'Consolas, Monaco, monospace',
|
|
77
|
-
fontSize: '0.75rem',
|
|
78
|
-
color: '#a3a3a3',
|
|
79
|
-
overflowX: 'auto',
|
|
80
|
-
whiteSpace: 'pre-wrap'
|
|
81
|
-
}}>
|
|
82
|
-
{JSON.stringify(skill.function.parameters.properties, null, 2)}
|
|
83
|
-
</pre>
|
|
84
|
-
{skill.function.parameters.required && skill.function.parameters.required.length > 0 && (
|
|
85
|
-
<div style={{ marginTop: '8px', fontSize: '0.75rem', color: '#ef4444' }}>
|
|
86
|
-
<strong>Required:</strong> {skill.function.parameters.required.join(', ')}
|
|
87
|
-
</div>
|
|
88
|
-
)}
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
))}
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export default Skills;
|