@novaqore/atom 0.1.3 → 0.1.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
CHANGED
|
@@ -26,15 +26,15 @@ function shortPath(p) {
|
|
|
26
26
|
return p;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function ChatInput({
|
|
30
|
-
value,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
export function ChatInput({ onSubmit, cwd, totalTokens, loading, disabled }) {
|
|
30
|
+
const [value, setValue] = useState("");
|
|
31
|
+
|
|
32
|
+
const handleSubmit = (val) => {
|
|
33
|
+
if (!val.trim() || disabled) return;
|
|
34
|
+
setValue("");
|
|
35
|
+
onSubmit(val);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
38
|
return React.createElement(
|
|
39
39
|
Box,
|
|
40
40
|
{ flexDirection: "column" },
|
|
@@ -74,8 +74,8 @@ export function ChatInput({
|
|
|
74
74
|
React.createElement(Text, { dimColor: true }, "❯ "),
|
|
75
75
|
React.createElement(TextInput, {
|
|
76
76
|
value,
|
|
77
|
-
onChange,
|
|
78
|
-
onSubmit,
|
|
77
|
+
onChange: setValue,
|
|
78
|
+
onSubmit: handleSubmit,
|
|
79
79
|
showCursor: !disabled,
|
|
80
80
|
focus: !disabled,
|
|
81
81
|
})
|
|
@@ -5,28 +5,49 @@ function formatName(name) {
|
|
|
5
5
|
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
function
|
|
8
|
+
function parseArgs(rawArgs) {
|
|
9
|
+
if (!rawArgs) return null;
|
|
9
10
|
try {
|
|
10
|
-
const parsed = JSON.parse(rawArgs
|
|
11
|
+
const parsed = JSON.parse(rawArgs);
|
|
11
12
|
const keys = Object.keys(parsed);
|
|
13
|
+
if (keys.length === 0) return "";
|
|
12
14
|
if (keys.length === 1) return String(parsed[keys[0]]);
|
|
13
15
|
return keys.map((k) => `${k}=${JSON.stringify(parsed[k])}`).join(", ");
|
|
14
|
-
} catch {
|
|
15
|
-
|
|
16
|
+
} catch {}
|
|
17
|
+
const m = rawArgs.match(/"[^"]+"\s*:\s*"((?:\\.|[^"\\])*)/);
|
|
18
|
+
if (m) {
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse('"' + m[1] + '"');
|
|
21
|
+
} catch {
|
|
22
|
+
return m[1];
|
|
23
|
+
}
|
|
16
24
|
}
|
|
25
|
+
return null;
|
|
17
26
|
}
|
|
18
27
|
|
|
19
|
-
export const ToolCall = React.memo(function ToolCall({ tc }) {
|
|
28
|
+
export const ToolCall = React.memo(function ToolCall({ tc, streaming = false }) {
|
|
29
|
+
const parsed = parseArgs(tc.function.arguments);
|
|
30
|
+
const name = React.createElement(
|
|
31
|
+
Text,
|
|
32
|
+
{ bold: true, color: "yellow" },
|
|
33
|
+
formatName(tc.function.name)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
let args;
|
|
37
|
+
if (parsed !== null) {
|
|
38
|
+
args = parsed;
|
|
39
|
+
} else if (streaming) {
|
|
40
|
+
return React.createElement(Text, null, name);
|
|
41
|
+
} else {
|
|
42
|
+
args = tc.function.arguments || "";
|
|
43
|
+
}
|
|
44
|
+
|
|
20
45
|
return React.createElement(
|
|
21
46
|
Text,
|
|
22
47
|
null,
|
|
23
|
-
|
|
24
|
-
Text,
|
|
25
|
-
{ bold: true, color: "yellow" },
|
|
26
|
-
formatName(tc.function.name)
|
|
27
|
-
),
|
|
48
|
+
name,
|
|
28
49
|
React.createElement(Text, { dimColor: true }, "("),
|
|
29
|
-
|
|
50
|
+
args,
|
|
30
51
|
React.createElement(Text, { dimColor: true }, ")")
|
|
31
52
|
);
|
|
32
53
|
});
|
package/src/components/Header.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Box, Text } from "ink";
|
|
|
4
4
|
import { DISK } from "../utils/system.js";
|
|
5
5
|
import { RUNTIMES } from "../utils/runtimes.js";
|
|
6
6
|
|
|
7
|
-
export function Header({ version, unhinged }) {
|
|
7
|
+
export const Header = React.memo(function Header({ version, unhinged }) {
|
|
8
8
|
const cpuList = cpus();
|
|
9
9
|
const cpuCount = cpuList?.length || 0;
|
|
10
10
|
const cpuSpeed = cpuList?.[0]?.speed || 0;
|
|
@@ -61,4 +61,4 @@ export function Header({ version, unhinged }) {
|
|
|
61
61
|
React.createElement(Text, { dimColor: true }, hardwareParts.join(" · "))
|
|
62
62
|
)
|
|
63
63
|
);
|
|
64
|
-
}
|
|
64
|
+
});
|
package/src/screens/chat.js
CHANGED
|
@@ -16,7 +16,6 @@ import { Header } from "../components/Header.js";
|
|
|
16
16
|
export function ChatScreen({ version, unhinged, onBack }) {
|
|
17
17
|
const [nq] = useState(() => new NovaQoreAI(SERVICE_FILE));
|
|
18
18
|
const [messages, setMessages] = useState([]);
|
|
19
|
-
const [input, setInput] = useState("");
|
|
20
19
|
const [streaming, setStreaming] = useState("");
|
|
21
20
|
const [streamingTools, setStreamingTools] = useState([]);
|
|
22
21
|
const [sending, setSending] = useState(false);
|
|
@@ -68,7 +67,6 @@ export function ChatScreen({ version, unhinged, onBack }) {
|
|
|
68
67
|
|
|
69
68
|
let convo = [...messages, { role: "user", content: text }];
|
|
70
69
|
setMessages(convo);
|
|
71
|
-
setInput("");
|
|
72
70
|
setSending(true);
|
|
73
71
|
setError(null);
|
|
74
72
|
|
|
@@ -235,7 +233,11 @@ export function ChatScreen({ version, unhinged, onBack }) {
|
|
|
235
233
|
streaming: true,
|
|
236
234
|
}),
|
|
237
235
|
...streamingTools.map((tc, j) =>
|
|
238
|
-
React.createElement(ToolCall, {
|
|
236
|
+
React.createElement(ToolCall, {
|
|
237
|
+
key: `streaming-tc-${j}`,
|
|
238
|
+
tc,
|
|
239
|
+
streaming: true,
|
|
240
|
+
})
|
|
239
241
|
),
|
|
240
242
|
running &&
|
|
241
243
|
React.createElement(RunningIndicator, {
|
|
@@ -256,8 +258,6 @@ export function ChatScreen({ version, unhinged, onBack }) {
|
|
|
256
258
|
})
|
|
257
259
|
: React.createElement(ChatInput, {
|
|
258
260
|
key: "input",
|
|
259
|
-
value: input,
|
|
260
|
-
onChange: setInput,
|
|
261
261
|
onSubmit: handleSubmit,
|
|
262
262
|
cwd,
|
|
263
263
|
totalTokens: usage.total,
|
package/src/utils/markdown.js
CHANGED
|
@@ -7,9 +7,6 @@ const ext = markedTerminal({
|
|
|
7
7
|
text: chalk.white,
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
// Patch: marked-terminal v7's text renderer ignores nested inline tokens
|
|
11
|
-
// (codespan, strong, em, link, etc.) when they appear inside list items.
|
|
12
|
-
// Force it to parse them inline so styling works in lists too.
|
|
13
10
|
const origText = ext.renderer.text;
|
|
14
11
|
ext.renderer.text = function (token) {
|
|
15
12
|
if (
|
|
@@ -40,18 +37,8 @@ function balanceForStreaming(buffer) {
|
|
|
40
37
|
return out;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
const cache = new Map();
|
|
44
|
-
const MAX_CACHE = 500;
|
|
45
|
-
|
|
46
40
|
export function renderMarkdown(text, { streaming = false } = {}) {
|
|
47
41
|
if (!text) return "";
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
const cached = cache.get(text);
|
|
52
|
-
if (cached !== undefined) return cached;
|
|
53
|
-
const result = marked.parse(text).trim();
|
|
54
|
-
if (cache.size >= MAX_CACHE) cache.clear();
|
|
55
|
-
cache.set(text, result);
|
|
56
|
-
return result;
|
|
42
|
+
const input = streaming ? balanceForStreaming(text) : text;
|
|
43
|
+
return marked.parse(input).trim();
|
|
57
44
|
}
|