openaxies 0.5.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/App.js +261 -194
- package/src/components/BrandHeader.js +17 -0
- package/src/providers/index.js +0 -3
- package/src/providers/streaming.js +5 -2
package/package.json
CHANGED
package/src/App.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Box, Text, useInput, useStdout } from 'ink';
|
|
3
3
|
import { hex } from './config/theme.js';
|
|
4
|
-
import { getCommands } from './config/commands.js';
|
|
5
4
|
import { getModels, getModelById, DEFAULT_MODEL_ID } from './config/models.js';
|
|
6
5
|
import { callModel } from './providers/index.js';
|
|
7
|
-
import {
|
|
6
|
+
import { createHeaderBar, HEADER_HEIGHT } from './components/BrandHeader.js';
|
|
7
|
+
import TextInput from 'ink-text-input';
|
|
8
8
|
|
|
9
9
|
const h = React.createElement;
|
|
10
|
-
|
|
11
10
|
export default AppRoot;
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
' \
|
|
12
|
+
const STARTUP_LOGO = [
|
|
13
|
+
' \u2588\u2588\u2588\u2588\u2588\u2588\u2557',
|
|
14
|
+
' \u2588\u2588\u2594\u2594\u2594\u2594\u2588\u2588\u2557',
|
|
15
|
+
' \u2588\u2588\u2591 \u2588\u2588\u2591',
|
|
16
|
+
' \u2588\u2588\u2591 \u2588\u2588\u2591',
|
|
17
|
+
' \u255a\u2588\u2588\u2588\u2588\u2588\u2588\u2594\u259d',
|
|
19
18
|
];
|
|
20
19
|
|
|
21
|
-
const LOGO_COLORS = ['#00F0FF', '#00DDFF', '#00CCFF', '#00BBFF', '#00AAFF'];
|
|
22
|
-
|
|
23
20
|
function buildHistory(messages, newText) {
|
|
24
21
|
const h = [];
|
|
25
22
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -36,20 +33,28 @@ function buildHistory(messages, newText) {
|
|
|
36
33
|
return h;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
function
|
|
36
|
+
function fmtTime(s) {
|
|
40
37
|
if (typeof s !== 'number' || s < 0) return '0.0s';
|
|
41
38
|
return s.toFixed(1) + 's';
|
|
42
39
|
}
|
|
43
40
|
|
|
44
|
-
function hr(cols
|
|
41
|
+
function hr(cols) {
|
|
45
42
|
const n = typeof cols === 'number' && cols > 0 ? cols : 80;
|
|
46
|
-
const c = typeof color === 'string' ? color : '#1A1A28';
|
|
47
43
|
let s = '';
|
|
48
44
|
for (let i = 0; i < n; i++) s = s + '\u2500';
|
|
49
|
-
return h(Text, { color:
|
|
45
|
+
return h(Text, { color: '#1A1A28' }, s);
|
|
50
46
|
}
|
|
51
47
|
|
|
52
|
-
const SPINNER = ['\u25CB', '\u25D4', '\u25D0', '\u25D5', '\u25CF', '\u25D5', '\u25D0', '\u25D4'];
|
|
48
|
+
const SPINNER = ['\u25CB', '\u25D4', '\u25D0', '\u25D5', '\u25CF', '\u25D5', '\u25D0', '\u25D4', '\u25D1', '\u25D2', '\u25D3'];
|
|
49
|
+
|
|
50
|
+
const COMMANDS = [
|
|
51
|
+
{ id: 'model', trigger: '/model', desc: 'Switch model' },
|
|
52
|
+
{ id: 'thoughts', trigger: '/thoughts', desc: 'Toggle thinking visibility' },
|
|
53
|
+
{ id: 'resume', trigger: '/resume', desc: 'Re-run last query' },
|
|
54
|
+
{ id: 'clear', trigger: '/clear', desc: 'Clear conversation' },
|
|
55
|
+
{ id: 'help', trigger: '/help', desc: 'Show commands' },
|
|
56
|
+
{ id: 'exit', trigger: '/exit', desc: 'Quit' },
|
|
57
|
+
];
|
|
53
58
|
|
|
54
59
|
function AppRoot() {
|
|
55
60
|
const { stdout } = useStdout();
|
|
@@ -67,51 +72,33 @@ function AppRoot() {
|
|
|
67
72
|
const [showOverlay, setShowOverlay] = React.useState(false);
|
|
68
73
|
const [overlayIndex, setOverlayIndex] = React.useState(0);
|
|
69
74
|
const [toolInfo, setToolInfo] = React.useState(null);
|
|
75
|
+
const [showThoughts, setShowThoughts] = React.useState(true);
|
|
76
|
+
const [startupDone, setStartupDone] = React.useState(false);
|
|
70
77
|
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const
|
|
78
|
+
const SEP_H = 1;
|
|
79
|
+
const FIXED_H = startupDone ? (HEADER_HEIGHT + SEP_H + 1 + 1) : 0;
|
|
80
|
+
const DOCK_H = 1;
|
|
81
|
+
const STATUS_H = 1;
|
|
82
|
+
const totalFixed = startupDone ? (HEADER_HEIGHT + SEP_H + DOCK_H + STATUS_H) : 11;
|
|
83
|
+
const availLines = Math.max(10, rows - totalFixed);
|
|
76
84
|
|
|
77
85
|
const abortRef = React.useRef(null);
|
|
78
86
|
const connRef = React.useRef(null);
|
|
79
87
|
const spinnerRef = React.useRef(null);
|
|
80
88
|
const timerRef = React.useRef(null);
|
|
81
89
|
const thinkStartRef = React.useRef(null);
|
|
90
|
+
const lastQueryRef = React.useRef('');
|
|
82
91
|
|
|
83
92
|
React.useEffect(function () {
|
|
84
|
-
if (isThinking === false)
|
|
85
|
-
if (spinnerRef.current !== null) {
|
|
86
|
-
clearInterval(spinnerRef.current);
|
|
87
|
-
spinnerRef.current = null;
|
|
88
|
-
}
|
|
89
|
-
if (timerRef.current !== null) {
|
|
90
|
-
clearInterval(timerRef.current);
|
|
91
|
-
timerRef.current = null;
|
|
92
|
-
}
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
93
|
+
if (isThinking === false) return;
|
|
95
94
|
let idx = 0;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
const si = setInterval(function () { idx = (idx + 1) % SPINNER.length; setSpinnerIdx(idx); }, 120);
|
|
96
|
+
const ti = setInterval(function () {
|
|
97
|
+
if (thinkStartRef.current !== null) setThinkingElapsed((Date.now() - thinkStartRef.current) / 1000);
|
|
99
98
|
}, 100);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
}, 100);
|
|
105
|
-
return function () {
|
|
106
|
-
if (spinnerRef.current !== null) {
|
|
107
|
-
clearInterval(spinnerRef.current);
|
|
108
|
-
spinnerRef.current = null;
|
|
109
|
-
}
|
|
110
|
-
if (timerRef.current !== null) {
|
|
111
|
-
clearInterval(timerRef.current);
|
|
112
|
-
timerRef.current = null;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
99
|
+
spinnerRef.current = si;
|
|
100
|
+
timerRef.current = ti;
|
|
101
|
+
return function () { clearInterval(si); clearInterval(ti); };
|
|
115
102
|
}, [isThinking]);
|
|
116
103
|
|
|
117
104
|
function cycleModel() {
|
|
@@ -133,9 +120,16 @@ function AppRoot() {
|
|
|
133
120
|
return o > c;
|
|
134
121
|
}
|
|
135
122
|
|
|
123
|
+
function filterText(t) {
|
|
124
|
+
if (showThoughts === true) return t;
|
|
125
|
+
return t.split('<think>').join('').split('</think>').join('');
|
|
126
|
+
}
|
|
127
|
+
|
|
136
128
|
async function handleSubmit(text) {
|
|
137
129
|
const safe = typeof text === 'string' ? text : '';
|
|
138
130
|
if (safe.length === 0 || streamingActive === true) return;
|
|
131
|
+
if (startupDone === false) setStartupDone(true);
|
|
132
|
+
lastQueryRef.current = safe;
|
|
139
133
|
setStreamingActive(true);
|
|
140
134
|
setToolInfo(null);
|
|
141
135
|
setStreamText(' connecting');
|
|
@@ -148,16 +142,13 @@ function AppRoot() {
|
|
|
148
142
|
return ' connecting';
|
|
149
143
|
});
|
|
150
144
|
}, 400);
|
|
151
|
-
setMessages(function (p) {
|
|
152
|
-
return p.concat([{ role: 'user', content: safe, id: 'u-' + Date.now() }]);
|
|
153
|
-
});
|
|
145
|
+
setMessages(function (p) { return p.concat([{ role: 'user', content: safe, id: 'u-' + Date.now() }]); });
|
|
154
146
|
setInputBuffer('');
|
|
155
147
|
const modelInfo = getModelById(activeModel);
|
|
156
148
|
if (modelInfo === null) {
|
|
157
149
|
if (connRef.current !== null) clearInterval(connRef.current), connRef.current = null;
|
|
158
|
-
setStreamingActive(false);
|
|
159
|
-
|
|
160
|
-
setMessages(function (p) { return p.concat([{ role: 'assistant', content: 'No model selected. Use /model.', id: 'e-' + Date.now() }]); });
|
|
150
|
+
setStreamingActive(false); setStreamText('');
|
|
151
|
+
setMessages(function (p) { return p.concat([{ role: 'assistant', content: 'No model selected.', id: 'e-' + Date.now() }]); });
|
|
161
152
|
return;
|
|
162
153
|
}
|
|
163
154
|
const history = buildHistory(messages, safe);
|
|
@@ -170,90 +161,72 @@ function AppRoot() {
|
|
|
170
161
|
let thinkStarted = false;
|
|
171
162
|
for await (const event of gen) {
|
|
172
163
|
if (abortController.signal.aborted === true) break;
|
|
173
|
-
if (firstEvent === true) {
|
|
174
|
-
|
|
175
|
-
if (connRef.current !== null) clearInterval(connRef.current), connRef.current = null;
|
|
176
|
-
}
|
|
177
|
-
if (event.type === 'tool') {
|
|
178
|
-
setToolInfo({ tool: event.tool, used: event.used, sites: event.sites, query: event.query });
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
164
|
+
if (firstEvent === true) { firstEvent = false; if (connRef.current !== null) clearInterval(connRef.current), connRef.current = null; }
|
|
165
|
+
if (event.type === 'tool') { setToolInfo({ tool: event.tool, used: event.used, sites: event.sites, query: event.query }); continue; }
|
|
181
166
|
if (event.type === 'thinking' || event.type === 'token') {
|
|
182
|
-
const
|
|
183
|
-
accumulated = accumulated +
|
|
167
|
+
const c = typeof event.content === 'string' ? event.content : '';
|
|
168
|
+
accumulated = accumulated + c;
|
|
184
169
|
const inside = checkThink(accumulated);
|
|
185
170
|
setStreamText(accumulated);
|
|
186
171
|
setIsThinking(inside);
|
|
187
|
-
if (inside === true && thinkStarted === false) {
|
|
188
|
-
|
|
189
|
-
thinkStartRef.current = Date.now();
|
|
190
|
-
setThinkingElapsed(0);
|
|
191
|
-
}
|
|
192
|
-
if (inside === false && thinkStarted === true) {
|
|
193
|
-
thinkStarted = false;
|
|
194
|
-
thinkStartRef.current = null;
|
|
195
|
-
setThinkingElapsed(0);
|
|
196
|
-
}
|
|
197
|
-
await new Promise(function (r) { setTimeout(r, 0); });
|
|
172
|
+
if (inside === true && thinkStarted === false) { thinkStarted = true; thinkStartRef.current = Date.now(); setThinkingElapsed(0); }
|
|
173
|
+
if (inside === false && thinkStarted === true) { thinkStarted = false; thinkStartRef.current = null; setThinkingElapsed(0); }
|
|
198
174
|
}
|
|
199
175
|
if (event.type === 'done') break;
|
|
200
176
|
if (event.type === 'timeout') {
|
|
201
177
|
if (accumulated.length > 0) accumulated = accumulated + '\n\n\u2014 stream timed out \u2014';
|
|
202
|
-
setStreamText(accumulated);
|
|
203
|
-
break;
|
|
178
|
+
setStreamText(accumulated); break;
|
|
204
179
|
}
|
|
205
180
|
}
|
|
206
181
|
if (connRef.current !== null) clearInterval(connRef.current), connRef.current = null;
|
|
207
|
-
setIsThinking(false);
|
|
208
|
-
thinkStartRef.current = null;
|
|
209
|
-
setThinkingElapsed(0);
|
|
210
|
-
setStreamingActive(false);
|
|
182
|
+
setIsThinking(false); thinkStartRef.current = null; setThinkingElapsed(0); setStreamingActive(false);
|
|
211
183
|
setStreamText('');
|
|
212
184
|
if (accumulated.length > 0) {
|
|
213
185
|
setMessages(function (p) { return p.concat([{ role: 'assistant', content: accumulated, id: 'a-' + Date.now() }]); });
|
|
214
186
|
}
|
|
215
187
|
} catch (err) {
|
|
216
188
|
if (connRef.current !== null) clearInterval(connRef.current), connRef.current = null;
|
|
217
|
-
setIsThinking(false);
|
|
218
|
-
thinkStartRef.current = null;
|
|
219
|
-
setThinkingElapsed(0);
|
|
220
|
-
setStreamingActive(false);
|
|
221
|
-
setStreamText('');
|
|
189
|
+
setIsThinking(false); thinkStartRef.current = null; setThinkingElapsed(0); setStreamingActive(false); setStreamText('');
|
|
222
190
|
const errMsg = err !== null && err !== undefined ? (err.message || String(err)) : 'Unknown error';
|
|
223
|
-
setMessages(function (p) {
|
|
224
|
-
return p.concat([{ role: 'assistant', content: 'Error: ' + errMsg + '\n\nSpace cold-starting? Try again.', id: 'er-' + Date.now() }]);
|
|
225
|
-
});
|
|
191
|
+
setMessages(function (p) { return p.concat([{ role: 'assistant', content: 'Error: ' + errMsg, id: 'er-' + Date.now() }]); });
|
|
226
192
|
}
|
|
227
193
|
}
|
|
228
194
|
|
|
229
195
|
function handleChange(v) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
if (showOverlay === true && (s.length === 0 || s[0] !== '/')) { setShowOverlay(false); }
|
|
196
|
+
setInputBuffer(v);
|
|
197
|
+
if (v.length === 1 && v[0] === '/') { setShowOverlay(true); setOverlayIndex(0); }
|
|
198
|
+
if (showOverlay === true && (v.length === 0 || v[0] !== '/')) { setShowOverlay(false); }
|
|
234
199
|
}
|
|
235
200
|
|
|
236
201
|
function handleCmd(item) {
|
|
237
202
|
if (item === null || item === undefined) return;
|
|
238
|
-
const t = item.
|
|
203
|
+
const t = item.trigger;
|
|
239
204
|
if (typeof t !== 'string') return;
|
|
240
205
|
if (t === '/exit') process.exit(0);
|
|
241
|
-
if (t === '/clear') setMessages([]);
|
|
206
|
+
if (t === '/clear') { setMessages([]); }
|
|
242
207
|
if (t === '/model') cycleModel();
|
|
243
|
-
if (t === '/
|
|
244
|
-
|
|
208
|
+
if (t === '/thoughts') { setShowThoughts(function (p) { return !p; }); }
|
|
209
|
+
if (t === '/resume') {
|
|
210
|
+
const q = lastQueryRef.current;
|
|
211
|
+
if (q.length > 0 && streamingActive === false) handleSubmit(q);
|
|
245
212
|
}
|
|
246
|
-
|
|
247
|
-
setShowOverlay(false);
|
|
248
|
-
setOverlayIndex(0);
|
|
213
|
+
if (t === '/help') { setMessages(function (p) { return p.concat([{ role: 'assistant', content: 'Commands: /help /clear /model /thoughts /resume /exit', id: 'h-' + Date.now() }]); }); }
|
|
214
|
+
setInputBuffer(''); setShowOverlay(false); setOverlayIndex(0);
|
|
249
215
|
}
|
|
250
216
|
|
|
251
217
|
useInput(function handleInput(input, key) {
|
|
252
218
|
if (showOverlay === true) {
|
|
253
219
|
if (key.escape === true) { setShowOverlay(false); setInputBuffer(''); setOverlayIndex(0); return; }
|
|
254
|
-
if (key.upArrow === true) { setOverlayIndex(function (p) { return p > 0 ? p - 1 :
|
|
255
|
-
if (key.downArrow === true) { setOverlayIndex(function (p) { return p <
|
|
256
|
-
if (key.return === true) { const cmd =
|
|
220
|
+
if (key.upArrow === true) { setOverlayIndex(function (p) { return p > 0 ? p - 1 : COMMANDS.length - 1; }); return; }
|
|
221
|
+
if (key.downArrow === true) { setOverlayIndex(function (p) { return p < COMMANDS.length - 1 ? p + 1 : 0; }); return; }
|
|
222
|
+
if (key.return === true) { const cmd = COMMANDS[overlayIndex]; if (cmd !== null && cmd !== undefined) handleCmd(cmd); return; }
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (key.escape === true) {
|
|
226
|
+
if (streamingActive === true) {
|
|
227
|
+
if (abortRef.current !== null) { try { abortRef.current.abort(); } catch (_) {} abortRef.current = null; }
|
|
228
|
+
setStreamingActive(false); setStreamText(''); setIsThinking(false);
|
|
229
|
+
}
|
|
257
230
|
return;
|
|
258
231
|
}
|
|
259
232
|
if (key.return === true) {
|
|
@@ -261,144 +234,238 @@ function AppRoot() {
|
|
|
261
234
|
if (s.length > 0 && streamingActive === false) handleSubmit(s);
|
|
262
235
|
return;
|
|
263
236
|
}
|
|
264
|
-
if (key.ctrl === true
|
|
265
|
-
if (
|
|
266
|
-
|
|
237
|
+
if (key.ctrl === true) {
|
|
238
|
+
if (input === 'c' || input === 'C') {
|
|
239
|
+
if (abortRef.current !== null) { try { abortRef.current.abort(); } catch (_) {} abortRef.current = null; }
|
|
240
|
+
setStreamingActive(false); setStreamText(''); setIsThinking(false);
|
|
241
|
+
process.exit(0);
|
|
242
|
+
}
|
|
243
|
+
if (input === 't' || input === 'T') { setShowThoughts(function (p) { return !p; }); return; }
|
|
244
|
+
if (input === 'p' || input === 'P') { cycleModel(); return; }
|
|
245
|
+
if (input === 'r' || input === 'R') {
|
|
246
|
+
const q = lastQueryRef.current;
|
|
247
|
+
if (q.length > 0 && streamingActive === false) handleSubmit(q);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (input === 'l' || input === 'L') { setMessages([]); return; }
|
|
251
|
+
if (input === 'k' || input === 'K') { setInputBuffer('/'); setShowOverlay(true); setOverlayIndex(0); return; }
|
|
267
252
|
}
|
|
268
253
|
});
|
|
269
254
|
|
|
270
|
-
const
|
|
271
|
-
const
|
|
255
|
+
const modelInfo = getModelById(activeModel);
|
|
256
|
+
const modelLabel = modelInfo !== null ? modelInfo.label : 'OpenAxies Llama';
|
|
257
|
+
|
|
258
|
+
// Build viewport sections
|
|
259
|
+
const sections = [];
|
|
272
260
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
)
|
|
261
|
+
// Overlay items
|
|
262
|
+
if (showOverlay === true) {
|
|
263
|
+
sections.push({ t: 'sep' });
|
|
264
|
+
sections.push({ t: 'overlay_header' });
|
|
265
|
+
for (let i = 0; i < COMMANDS.length; i++) {
|
|
266
|
+
const c = COMMANDS[i];
|
|
267
|
+
sections.push({ t: 'cmd', trigger: c.trigger, desc: c.desc, sel: i === overlayIndex });
|
|
268
|
+
}
|
|
269
|
+
sections.push({ t: 'sep' });
|
|
278
270
|
}
|
|
279
|
-
const logo = h(Box, { flexDirection: 'column', width: '100%', flexShrink: 0, paddingLeft: 0 }, ...logoEls);
|
|
280
271
|
|
|
281
|
-
|
|
272
|
+
// Messages
|
|
282
273
|
for (let i = 0; i < messages.length; i++) {
|
|
283
274
|
const msg = messages[i];
|
|
284
275
|
if (msg === null || typeof msg !== 'object') continue;
|
|
285
276
|
const content = typeof msg.content === 'string' ? msg.content : '';
|
|
286
277
|
if (content.length === 0) continue;
|
|
287
278
|
if (msg.role === 'user') {
|
|
288
|
-
|
|
279
|
+
sections.push({ t: 'sep' });
|
|
280
|
+
sections.push({ t: 'user', text: content });
|
|
289
281
|
} else {
|
|
290
|
-
|
|
282
|
+
if (sections.length > 0 && sections[sections.length - 1].t !== 'sep') sections.push({ t: 'sep' });
|
|
283
|
+
sections.push({ t: 'assistant', text: filterText(content) });
|
|
291
284
|
}
|
|
292
285
|
}
|
|
293
286
|
|
|
294
|
-
|
|
295
|
-
if (
|
|
287
|
+
// Streaming
|
|
288
|
+
if (typeof streamText === 'string' && streamText.length > 0) {
|
|
289
|
+
const clean = filterText(streamText);
|
|
296
290
|
if (toolInfo !== null && toolInfo.used === true && toolInfo.query.length > 0) {
|
|
297
|
-
|
|
291
|
+
sections.push({ t: 'tool', tool: toolInfo.tool, query: toolInfo.query, sites: toolInfo.sites });
|
|
298
292
|
}
|
|
299
293
|
if (isThinking === true) {
|
|
300
|
-
|
|
301
|
-
const clean = streamText.split('<think>').join('').split('</think>').join('');
|
|
302
|
-
viewLines.push({ t: 'think-text', text: clean });
|
|
294
|
+
sections.push({ t: 'thinking', spin: SPINNER[spinnerIdx], elapsed: fmtTime(thinkingElapsed), content: clean });
|
|
303
295
|
} else {
|
|
304
|
-
|
|
305
|
-
viewLines.push({ t: 'text', text: clean });
|
|
296
|
+
sections.push({ t: 'stream', text: clean });
|
|
306
297
|
}
|
|
307
298
|
}
|
|
308
299
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
viewLines.push({ t: 'idle-sm', text: ' Models: OpenAxies Llama | OpenAxies GPT | OpenAxies DeepSeek' });
|
|
313
|
-
viewLines.push({ t: 'idle-sm', text: ' Current: ' + activeLabel });
|
|
300
|
+
// Startup screen
|
|
301
|
+
if (startupDone === false && messages.length === 0) {
|
|
302
|
+
sections.push({ t: 'startup' });
|
|
314
303
|
}
|
|
315
304
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
305
|
+
// Ready state
|
|
306
|
+
if (sections.length === 0) {
|
|
307
|
+
sections.push({ t: 'sep' });
|
|
308
|
+
sections.push({ t: 'ready' });
|
|
309
|
+
sections.push({ t: 'sep' });
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Estimate and limit sections
|
|
313
|
+
function estLines(s) {
|
|
314
|
+
if (s.t === 'sep' || s.t === 'assistant' || s.t === 'stream' || s.t === 'tool' || s.t === 'ready' || s.t === 'overlay_header') return 1;
|
|
315
|
+
if (s.t === 'cmd') return 1;
|
|
316
|
+
if (s.t === 'user') return 2;
|
|
317
|
+
if (s.t === 'thinking') return 2;
|
|
318
|
+
if (s.t === 'startup') return 11;
|
|
319
|
+
return 1;
|
|
320
|
+
}
|
|
319
321
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
322
|
+
let totalEst = 0;
|
|
323
|
+
let lastN = 0;
|
|
324
|
+
for (let i = sections.length - 1; i >= 0; i--) {
|
|
325
|
+
const l = estLines(sections[i]);
|
|
326
|
+
if (totalEst + l > availLines) break;
|
|
327
|
+
totalEst += l;
|
|
328
|
+
lastN = sections.length - i;
|
|
329
|
+
}
|
|
330
|
+
const visible = sections.slice(sections.length - lastN);
|
|
331
|
+
|
|
332
|
+
// Render sections
|
|
333
|
+
const sectionEls = [];
|
|
334
|
+
for (let i = 0; i < visible.length; i++) {
|
|
335
|
+
const s = visible[i];
|
|
336
|
+
const ki = 's-' + i;
|
|
337
|
+
|
|
338
|
+
if (s.t === 'sep') {
|
|
339
|
+
sectionEls.push(h(Box, { key: ki, height: 1 }, hr(cols)));
|
|
340
|
+
} else if (s.t === 'user') {
|
|
341
|
+
sectionEls.push(
|
|
342
|
+
h(Box, { key: ki + '-h', height: 1, paddingLeft: 1 },
|
|
343
|
+
h(Text, { color: '#888899', bold: true }, 'You')
|
|
344
|
+
)
|
|
345
|
+
);
|
|
346
|
+
sectionEls.push(
|
|
347
|
+
h(Box, { key: ki + '-t', height: 1, paddingLeft: 2 },
|
|
348
|
+
h(Text, { color: hex.neonBlue, wrap: 'wrap' }, s.text)
|
|
349
|
+
)
|
|
350
|
+
);
|
|
351
|
+
} else if (s.t === 'assistant' || s.t === 'stream') {
|
|
352
|
+
sectionEls.push(
|
|
353
|
+
h(Box, { key: ki, height: 1, paddingLeft: 1 },
|
|
354
|
+
h(Text, { color: hex.primary, wrap: 'wrap' }, s.text)
|
|
355
|
+
)
|
|
356
|
+
);
|
|
357
|
+
} else if (s.t === 'thinking') {
|
|
358
|
+
sectionEls.push(
|
|
359
|
+
h(Box, { key: ki + '-h', height: 1, paddingLeft: 1 },
|
|
360
|
+
h(Text, { color: '#FF9F43', bold: true }, s.spin + ' Thinking \u2022 ' + s.elapsed)
|
|
361
|
+
)
|
|
362
|
+
);
|
|
363
|
+
sectionEls.push(
|
|
364
|
+
h(Box, { key: ki + '-c', height: 1, paddingLeft: 2 },
|
|
365
|
+
h(Text, { color: '#FF9F43', wrap: 'wrap' }, s.content)
|
|
326
366
|
)
|
|
327
367
|
);
|
|
328
|
-
} else if (
|
|
329
|
-
|
|
330
|
-
h(Box, { key:
|
|
331
|
-
h(Text, { color: '#
|
|
368
|
+
} else if (s.t === 'tool') {
|
|
369
|
+
sectionEls.push(
|
|
370
|
+
h(Box, { key: ki, height: 1, paddingLeft: 1 },
|
|
371
|
+
h(Text, { color: '#5B5B8A' }, '\u2500\u2500 ' + s.tool + ' \u2014 ' + (s.query || '') + ' (' + (s.sites || 0) + ' sites)')
|
|
332
372
|
)
|
|
333
373
|
);
|
|
334
|
-
} else if (
|
|
335
|
-
|
|
336
|
-
h(Box, { key:
|
|
337
|
-
h(Text, { color: '#
|
|
374
|
+
} else if (s.t === 'overlay_header') {
|
|
375
|
+
sectionEls.push(
|
|
376
|
+
h(Box, { key: ki, height: 1, paddingLeft: 1 },
|
|
377
|
+
h(Text, { color: '#888899', bold: true }, 'Commands')
|
|
338
378
|
)
|
|
339
379
|
);
|
|
340
|
-
} else if (
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
380
|
+
} else if (s.t === 'cmd') {
|
|
381
|
+
const prefix = s.sel === true ? '\u276F ' : ' ';
|
|
382
|
+
const col = s.sel === true ? hex.neonBlue : '#666688';
|
|
383
|
+
sectionEls.push(
|
|
384
|
+
h(Box, { key: ki, height: 1, paddingLeft: 2 },
|
|
385
|
+
h(Text, { color: col }, prefix + s.trigger),
|
|
386
|
+
h(Text, { color: '#444466' }, ' ' + (s.desc || ''))
|
|
344
387
|
)
|
|
345
388
|
);
|
|
346
|
-
} else if (
|
|
347
|
-
|
|
348
|
-
h(Box, { key:
|
|
349
|
-
h(Text, { color:
|
|
389
|
+
} else if (s.t === 'ready') {
|
|
390
|
+
sectionEls.push(
|
|
391
|
+
h(Box, { key: ki, height: 1, paddingLeft: 1 },
|
|
392
|
+
h(Text, { color: '#00FF88', bold: true }, 'Ready')
|
|
350
393
|
)
|
|
351
394
|
);
|
|
352
|
-
} else if (
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
h(
|
|
395
|
+
} else if (s.t === 'startup') {
|
|
396
|
+
for (let li = 0; li < STARTUP_LOGO.length; li++) {
|
|
397
|
+
sectionEls.push(
|
|
398
|
+
h(Box, { key: ki + '-l' + li, height: 1, paddingLeft: 1 },
|
|
399
|
+
h(Text, { color: '#00BBFF', bold: true }, STARTUP_LOGO[li])
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
sectionEls.push(h(Box, { key: ki + '-e1', height: 1 }, null));
|
|
404
|
+
sectionEls.push(
|
|
405
|
+
h(Box, { key: ki + '-t1', height: 1, paddingLeft: 1 },
|
|
406
|
+
h(Text, { color: '#FFFFFF', bold: true }, 'OpenAxies')
|
|
407
|
+
)
|
|
408
|
+
);
|
|
409
|
+
sectionEls.push(
|
|
410
|
+
h(Box, { key: ki + '-t2', height: 1, paddingLeft: 1 },
|
|
411
|
+
h(Text, { color: '#777788' }, 'local agent runtime')
|
|
356
412
|
)
|
|
357
413
|
);
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
h(Box, { key: '
|
|
361
|
-
h(Text, { color: '#
|
|
414
|
+
sectionEls.push(h(Box, { key: ki + '-e2', height: 1 }, null));
|
|
415
|
+
sectionEls.push(
|
|
416
|
+
h(Box, { key: ki + '-t3', height: 1, paddingLeft: 1 },
|
|
417
|
+
h(Text, { color: '#555577' }, 'Press Enter to begin')
|
|
362
418
|
)
|
|
363
419
|
);
|
|
364
420
|
}
|
|
365
421
|
}
|
|
366
422
|
|
|
423
|
+
// Fill remaining
|
|
424
|
+
while (sectionEls.length < availLines) {
|
|
425
|
+
sectionEls.push(h(Box, { key: 'fl-' + sectionEls.length, height: 1 }, h(Text, {}, '')));
|
|
426
|
+
}
|
|
427
|
+
|
|
367
428
|
const viewport = h(Box, {
|
|
368
429
|
flexGrow: 1,
|
|
369
430
|
height: availLines,
|
|
370
431
|
flexDirection: 'column',
|
|
371
432
|
overflow: 'hidden',
|
|
372
|
-
|
|
373
|
-
paddingBottom: 0,
|
|
374
|
-
}, ...viewEls);
|
|
375
|
-
|
|
376
|
-
const slashOverlay = showOverlay === true ? createSlashOverlay(commands, overlayIndex) : null;
|
|
377
|
-
|
|
378
|
-
const dock = createComposerDock({
|
|
379
|
-
value: inputBuffer,
|
|
380
|
-
onChange: handleChange,
|
|
381
|
-
onSubmit: function () {},
|
|
382
|
-
inputActive: showOverlay === false,
|
|
383
|
-
isStreaming: streamingActive,
|
|
384
|
-
terminalWidth: cols,
|
|
385
|
-
modelLabel: activeLabel + ' \u25CF',
|
|
386
|
-
modelStatus: true,
|
|
387
|
-
});
|
|
433
|
+
}, ...sectionEls);
|
|
388
434
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
h(
|
|
435
|
+
// Main layout
|
|
436
|
+
const headerBar = startupDone === true ? createHeaderBar(modelLabel) : null;
|
|
437
|
+
const headerSep = startupDone === true ? h(Box, { height: 1 }, hr(cols)) : null;
|
|
438
|
+
|
|
439
|
+
// Input line
|
|
440
|
+
const inputLine = h(Box, { height: DOCK_H, flexShrink: 0, paddingLeft: 2, paddingRight: 2 },
|
|
441
|
+
h(Text, { color: hex.greenOnline }, '\u258C'),
|
|
442
|
+
h(Text, { color: '#555577' }, ' Ask OpenAxies'),
|
|
443
|
+
h(TextInput, {
|
|
444
|
+
value: inputBuffer,
|
|
445
|
+
onChange: handleChange,
|
|
446
|
+
onSubmit: function () {},
|
|
447
|
+
placeholder: '',
|
|
448
|
+
focus: showOverlay === false,
|
|
449
|
+
showCursor: true,
|
|
450
|
+
})
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
// Shortcuts footer
|
|
454
|
+
const modelShort = modelLabel.replace('OpenAxies ', '');
|
|
455
|
+
const footerLine = h(Box, { height: STATUS_H, flexShrink: 0, paddingLeft: 2, paddingRight: 2 },
|
|
456
|
+
h(Text, { color: '#444466' }, 'esc \u2248 '),
|
|
457
|
+
h(Text, { color: '#444466' }, 'ctrl+t '),
|
|
458
|
+
h(Text, { color: '#444466' }, 'ctrl+p '),
|
|
459
|
+
h(Text, { color: '#444466' }, 'ctrl+k'),
|
|
460
|
+
h(Box, { flexGrow: 1 }),
|
|
461
|
+
h(Text, { color: '#555577' }, modelShort.toLowerCase() + ' \u2022 local'),
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
return h(Box, { flexDirection: 'column', width: '100%', height: rows, overflow: 'hidden' },
|
|
465
|
+
headerBar,
|
|
466
|
+
headerSep,
|
|
398
467
|
viewport,
|
|
399
|
-
|
|
400
|
-
|
|
468
|
+
inputLine,
|
|
469
|
+
footerLine,
|
|
401
470
|
);
|
|
402
471
|
}
|
|
403
|
-
|
|
404
|
-
import { createSlashOverlay } from './components/SlashOverlay.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
|
|
4
|
+
const h = React.createElement;
|
|
5
|
+
|
|
6
|
+
export function createHeaderBar(modelLabel) {
|
|
7
|
+
const label = typeof modelLabel === 'string' && modelLabel.length > 0 ? modelLabel : 'OpenAxies Llama';
|
|
8
|
+
return h(Box, { height: 1, paddingLeft: 1, paddingTop: 0, paddingBottom: 0 },
|
|
9
|
+
h(Text, { color: '#00BBFF', bold: true }, 'OpenAxies'),
|
|
10
|
+
h(Text, { color: '#555577' }, ' \u2022 '),
|
|
11
|
+
h(Text, { color: '#FFFFFF' }, label),
|
|
12
|
+
h(Text, { color: '#555577' }, ' \u2022 '),
|
|
13
|
+
h(Text, { color: '#777788' }, 'local'),
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const HEADER_HEIGHT = 1;
|
package/src/providers/index.js
CHANGED
|
@@ -4,15 +4,12 @@ import { runWebSearchGraph, shouldUseWebSearch } from './websearch.js';
|
|
|
4
4
|
const MODEL_ROUTES = Object.freeze({
|
|
5
5
|
'openaxis/openaxis-llama': Object.freeze([
|
|
6
6
|
'https://universal-618-clarity-main.hf.space/v1/chat/completions',
|
|
7
|
-
'https://universal-618-clarity-4.hf.space/v1/chat/completions',
|
|
8
7
|
]),
|
|
9
8
|
'openaxis/openaxis-gpt': Object.freeze([
|
|
10
9
|
'https://universal-618-clarity-2.hf.space/v1/chat/completions',
|
|
11
|
-
'https://universal-618-clarity-5.hf.space/v1/chat/completions',
|
|
12
10
|
]),
|
|
13
11
|
'openaxis/openaxis-deepseek': Object.freeze([
|
|
14
12
|
'https://universal-618-clarity-3.hf.space/v1/chat/completions',
|
|
15
|
-
'https://universal-618-clarity-6.hf.space/v1/chat/completions',
|
|
16
13
|
]),
|
|
17
14
|
});
|
|
18
15
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const CONNECT_TIMEOUT =
|
|
2
|
-
const READ_TIMEOUT =
|
|
1
|
+
const CONNECT_TIMEOUT = 10000;
|
|
2
|
+
const READ_TIMEOUT = 30000;
|
|
3
3
|
|
|
4
4
|
function checkEndpoint(endpoint) {
|
|
5
5
|
if (typeof endpoint !== 'string') {
|
|
@@ -44,6 +44,9 @@ export async function* streamResponse(endpoint, body, signal) {
|
|
|
44
44
|
headers: {
|
|
45
45
|
'Content-Type': 'application/json',
|
|
46
46
|
'Accept': 'text/event-stream',
|
|
47
|
+
'Authorization': typeof process !== 'undefined' && process.env && process.env.OPENAXIES_HF_TOKEN
|
|
48
|
+
? 'Bearer ' + process.env.OPENAXIES_HF_TOKEN
|
|
49
|
+
: undefined,
|
|
47
50
|
},
|
|
48
51
|
body: JSON.stringify(body),
|
|
49
52
|
signal: combinedSignal,
|