code-ollama 0.16.0 → 0.17.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/dist/assets/{tui-85A3pZD2.js → tui-CCHcdC7V.js} +422 -271
- package/dist/cli.js +160 -6
- package/package.json +2 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as PLAN_GENERATION_INSTRUCTION, C as withSystemMessage, D as ASSISTANT, E as getTheme, F as APPROVE, I as REJECT, L as VERSION, M as LABEL, N as PLAN, O as SYSTEM, P as SAFE, R as LIST, S as resetSystemMessage, T as LIST$1, _ as setClearHandler, a as tick, b as loadConfig, c as appendMessage, d as deleteSessionIfEmpty, f as listSessions, g as reset, h as clear, i as WRITE_TOOLS, j as AUTO, k as USER, l as createSession, m as updateSessionModel, n as READ_TOOLS, o as color, p as loadSession, r as TOOLS, s as write, t as executeTool, u as deleteSession, v as listModels, w as HEADER_PREFIX, x as saveConfig, y as streamChat } from "../cli.js";
|
|
2
2
|
import { readdirSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join, relative } from "node:path";
|
|
@@ -17,7 +17,7 @@ function normalizeCodeBlockContent(content, indent = "") {
|
|
|
17
17
|
const indentPattern = new RegExp(`^${indent}`, "gm");
|
|
18
18
|
return content.replace(indentPattern, "").trim();
|
|
19
19
|
}
|
|
20
|
-
async function prewarmCodeBlocks(content) {
|
|
20
|
+
async function prewarmCodeBlocks(content, theme = getTheme()) {
|
|
21
21
|
const promises = [];
|
|
22
22
|
let match;
|
|
23
23
|
CODE_BLOCK_REGEX.lastIndex = 0;
|
|
@@ -26,35 +26,35 @@ async function prewarmCodeBlocks(content) {
|
|
|
26
26
|
const language = match[3];
|
|
27
27
|
const code = normalizeCodeBlockContent(match[4], indent);
|
|
28
28
|
// v8 ignore next 2
|
|
29
|
-
if (code) promises.push(prewarmHighlight(code, language));
|
|
29
|
+
if (code) promises.push(prewarmHighlight(code, language, theme));
|
|
30
30
|
}
|
|
31
31
|
await Promise.all(promises);
|
|
32
32
|
}
|
|
33
|
-
async function prewarmHighlight(code, language) {
|
|
33
|
+
async function prewarmHighlight(code, language, theme = getTheme()) {
|
|
34
34
|
// v8 ignore start
|
|
35
|
-
const cacheKey = `${language ?? ""}:${code}`;
|
|
35
|
+
const cacheKey = `${theme.codeTheme}:${language ?? ""}:${code}`;
|
|
36
36
|
if (highlightCache.has(cacheKey)) return;
|
|
37
37
|
// v8 ignore stop
|
|
38
|
-
const result = await highlightCode(code, language);
|
|
38
|
+
const result = await highlightCode(code, language, theme.codeTheme);
|
|
39
39
|
highlightCache.set(cacheKey, result);
|
|
40
40
|
}
|
|
41
|
-
async function highlightCode(code, language = "text") {
|
|
41
|
+
async function highlightCode(code, language = "text", codeTheme = getTheme().codeTheme) {
|
|
42
42
|
const { codeToANSI } = await import("@shikijs/cli");
|
|
43
43
|
try {
|
|
44
|
-
return await codeToANSI(code, language,
|
|
44
|
+
return await codeToANSI(code, language, codeTheme);
|
|
45
45
|
} catch {
|
|
46
46
|
// v8 ignore next
|
|
47
47
|
return code;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
var CodeBlock = memo(function CodeBlock({ code, language, role }) {
|
|
51
|
-
const cacheKey = `${language ?? ""}:${code}`;
|
|
50
|
+
var CodeBlock = memo(function CodeBlock({ code, language, role, theme = getTheme() }) {
|
|
51
|
+
const cacheKey = `${theme.codeTheme}:${language ?? ""}:${code}`;
|
|
52
52
|
const [highlighted, setHighlighted] = useState(() => highlightCache.get(cacheKey) ?? code);
|
|
53
53
|
useEffect(() => {
|
|
54
54
|
let canceled = false;
|
|
55
55
|
async function loadHighlight() {
|
|
56
56
|
try {
|
|
57
|
-
const result = await highlightCode(code, language);
|
|
57
|
+
const result = await highlightCode(code, language, theme.codeTheme);
|
|
58
58
|
highlightCache.set(cacheKey, result);
|
|
59
59
|
if (!canceled) setHighlighted(result);
|
|
60
60
|
} catch {}
|
|
@@ -66,22 +66,31 @@ var CodeBlock = memo(function CodeBlock({ code, language, role }) {
|
|
|
66
66
|
}, [
|
|
67
67
|
cacheKey,
|
|
68
68
|
code,
|
|
69
|
-
language
|
|
69
|
+
language,
|
|
70
|
+
theme.codeTheme
|
|
70
71
|
]);
|
|
71
72
|
const isSystem = role === SYSTEM;
|
|
72
73
|
return /* @__PURE__ */ jsx(Box, {
|
|
73
74
|
flexDirection: "column",
|
|
74
75
|
borderStyle: "bold",
|
|
75
|
-
borderColor: isSystem ?
|
|
76
|
+
borderColor: isSystem ? theme.colors.secondary : theme.colors.codeBorder,
|
|
76
77
|
paddingX: 1,
|
|
77
78
|
marginY: 1,
|
|
78
79
|
children: /* @__PURE__ */ jsx(Text, {
|
|
80
|
+
color: isSystem ? theme.colors.messageSystem : void 0,
|
|
79
81
|
dimColor: isSystem,
|
|
80
82
|
children: highlighted
|
|
81
83
|
})
|
|
82
84
|
});
|
|
83
85
|
});
|
|
84
86
|
//#endregion
|
|
87
|
+
//#region src/components/Messages/constants.ts
|
|
88
|
+
var TURN_ABORTED_MESSAGE = [
|
|
89
|
+
"<turn_aborted>",
|
|
90
|
+
"The user interrupted the previous turn on purpose. Any running commands may still be running in the background. If any tools were aborted, they may have partially executed.",
|
|
91
|
+
"</turn_aborted>"
|
|
92
|
+
].join("\n");
|
|
93
|
+
//#endregion
|
|
85
94
|
//#region src/components/Markdown/extensions.ts
|
|
86
95
|
var LATEX_COMMANDS = {
|
|
87
96
|
"\\rightarrow": "→",
|
|
@@ -171,7 +180,7 @@ var inlineMathExtension = {
|
|
|
171
180
|
//#endregion
|
|
172
181
|
//#region src/components/Markdown/render.ts
|
|
173
182
|
var HR_PLACEHOLDER = "__CODE_OLLAMA_HR_PLACEHOLDER__";
|
|
174
|
-
function renderMarkdown(content, hrWidth) {
|
|
183
|
+
function renderMarkdown(content, hrWidth, syntaxTheme = "gitHub") {
|
|
175
184
|
const hr = "─".repeat(Math.max(1, hrWidth));
|
|
176
185
|
const markdown = new Marked();
|
|
177
186
|
const rendererExtension = {
|
|
@@ -187,7 +196,7 @@ function renderMarkdown(content, hrWidth) {
|
|
|
187
196
|
}
|
|
188
197
|
};
|
|
189
198
|
markdown.use(markedTerminal({
|
|
190
|
-
theme:
|
|
199
|
+
theme: syntaxTheme,
|
|
191
200
|
reflowText: true,
|
|
192
201
|
width: Math.max(1, hrWidth)
|
|
193
202
|
}));
|
|
@@ -202,23 +211,20 @@ function renderMarkdown(content, hrWidth) {
|
|
|
202
211
|
}
|
|
203
212
|
//#endregion
|
|
204
213
|
//#region src/components/Markdown/Markdown.tsx
|
|
205
|
-
var Markdown = memo(function Markdown({ content, color, dimColor }) {
|
|
214
|
+
var Markdown = memo(function Markdown({ content, color, dimColor, theme = getTheme() }) {
|
|
206
215
|
const { stdout } = useStdout();
|
|
207
216
|
const availableWidth = stdout.columns - 4;
|
|
208
217
|
return /* @__PURE__ */ jsx(Text, {
|
|
209
218
|
color,
|
|
210
219
|
dimColor,
|
|
211
|
-
children: useMemo(() => renderMarkdown(content, availableWidth), [
|
|
220
|
+
children: useMemo(() => renderMarkdown(content, availableWidth, theme.markdownTheme), [
|
|
221
|
+
content,
|
|
222
|
+
availableWidth,
|
|
223
|
+
theme.markdownTheme
|
|
224
|
+
])
|
|
212
225
|
});
|
|
213
226
|
});
|
|
214
227
|
//#endregion
|
|
215
|
-
//#region src/components/Messages/constants.ts
|
|
216
|
-
var TURN_ABORTED_MESSAGE = [
|
|
217
|
-
"<turn_aborted>",
|
|
218
|
-
"The user interrupted the previous turn on purpose. Any running commands may still be running in the background. If any tools were aborted, they may have partially executed.",
|
|
219
|
-
"</turn_aborted>"
|
|
220
|
-
].join("\n");
|
|
221
|
-
//#endregion
|
|
222
228
|
//#region src/components/Messages/layout.ts
|
|
223
229
|
var ANSI_REGEX = new RegExp(String.raw`\u001B\[[0-9;]*m`, "g");
|
|
224
230
|
var CODE_BLOCK_MARGIN_Y = 2;
|
|
@@ -371,118 +377,31 @@ function parseContent(content) {
|
|
|
371
377
|
return segments;
|
|
372
378
|
}
|
|
373
379
|
//#endregion
|
|
374
|
-
//#region src/components/Messages/streaming.ts
|
|
375
|
-
function isWordCharacter(char) {
|
|
376
|
-
return char !== void 0 && /[A-Za-z0-9]/.test(char);
|
|
377
|
-
}
|
|
378
|
-
function isEscaped(content, index) {
|
|
379
|
-
let slashCount = 0;
|
|
380
|
-
for (let cursor = index - 1; cursor >= 0 && content[cursor] === "\\"; cursor--) slashCount += 1;
|
|
381
|
-
return slashCount % 2 === 1;
|
|
382
|
-
}
|
|
383
|
-
function canOpenEmphasis(content, index, length) {
|
|
384
|
-
const previous = content[index - 1];
|
|
385
|
-
const next = content[index + length];
|
|
386
|
-
if (!next || /\s/.test(next)) return false;
|
|
387
|
-
return !isWordCharacter(previous);
|
|
388
|
-
}
|
|
389
|
-
function canCloseEmphasis(content, index, length) {
|
|
390
|
-
const previous = content[index - 1];
|
|
391
|
-
const next = content[index + length];
|
|
392
|
-
if (!previous || /\s/.test(previous)) return false;
|
|
393
|
-
return !isWordCharacter(next);
|
|
394
|
-
}
|
|
395
|
-
function findUnmatchedInlineDelimiter(content) {
|
|
396
|
-
const stack = [];
|
|
397
|
-
for (let index = 0; index < content.length; index += 1) {
|
|
398
|
-
const current = content[index];
|
|
399
|
-
if (isEscaped(content, index)) continue;
|
|
400
|
-
const top = stack.at(-1);
|
|
401
|
-
if (top?.kind === "code") {
|
|
402
|
-
if (current === "`") stack.pop();
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
if (top?.kind === "latex") {
|
|
406
|
-
if (current === "$") stack.pop();
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
if (current === "`") {
|
|
410
|
-
stack.push({
|
|
411
|
-
index,
|
|
412
|
-
length: 1,
|
|
413
|
-
kind: "code",
|
|
414
|
-
marker: "`"
|
|
415
|
-
});
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
if (current === "$") {
|
|
419
|
-
stack.push({
|
|
420
|
-
index,
|
|
421
|
-
length: 1,
|
|
422
|
-
kind: "latex",
|
|
423
|
-
marker: "$"
|
|
424
|
-
});
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
if (current !== "*") continue;
|
|
428
|
-
const marker = current;
|
|
429
|
-
const length = content[index + 1] === marker ? 2 : 1;
|
|
430
|
-
const token = marker.repeat(length);
|
|
431
|
-
const kind = length === 2 ? "bold" : "italic";
|
|
432
|
-
if (top?.marker === token && top.kind === kind && canCloseEmphasis(content, index, length)) {
|
|
433
|
-
stack.pop();
|
|
434
|
-
if (length === 2) index += 1;
|
|
435
|
-
continue;
|
|
436
|
-
}
|
|
437
|
-
if (canOpenEmphasis(content, index, length)) {
|
|
438
|
-
stack.push({
|
|
439
|
-
index,
|
|
440
|
-
length,
|
|
441
|
-
kind,
|
|
442
|
-
marker: token
|
|
443
|
-
});
|
|
444
|
-
if (length === 2) index += 1;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
return stack[0] ?? null;
|
|
448
|
-
}
|
|
449
|
-
function splitStreamingInlineContent(content) {
|
|
450
|
-
const unmatched = findUnmatchedInlineDelimiter(content);
|
|
451
|
-
if (!unmatched) return [{
|
|
452
|
-
type: "markdown",
|
|
453
|
-
content
|
|
454
|
-
}];
|
|
455
|
-
const parts = [];
|
|
456
|
-
const prefix = content.slice(0, unmatched.index);
|
|
457
|
-
const plainSuffix = content.slice(unmatched.index + unmatched.length);
|
|
458
|
-
if (prefix) parts.push({
|
|
459
|
-
type: "markdown",
|
|
460
|
-
content: prefix
|
|
461
|
-
});
|
|
462
|
-
if (plainSuffix) parts.push({
|
|
463
|
-
type: "plain",
|
|
464
|
-
content: plainSuffix
|
|
465
|
-
});
|
|
466
|
-
return parts;
|
|
467
|
-
}
|
|
468
|
-
//#endregion
|
|
469
380
|
//#region src/components/Messages/styles.ts
|
|
470
|
-
function getMessageColor(role) {
|
|
381
|
+
function getMessageColor(role, theme) {
|
|
471
382
|
switch (role) {
|
|
472
|
-
case USER:
|
|
473
|
-
case ASSISTANT: return
|
|
474
|
-
case SYSTEM: return
|
|
383
|
+
case USER:
|
|
384
|
+
case ASSISTANT: return;
|
|
385
|
+
case SYSTEM: return theme.colors.messageSystem;
|
|
475
386
|
default: return;
|
|
476
387
|
}
|
|
477
388
|
}
|
|
478
389
|
//#endregion
|
|
479
|
-
//#region src/components/Messages/
|
|
480
|
-
function
|
|
481
|
-
|
|
482
|
-
|
|
390
|
+
//#region src/components/Messages/Message.tsx
|
|
391
|
+
function renderStickyPaddingLines(count) {
|
|
392
|
+
return Array.from({ length: count }, (_, index) => /* @__PURE__ */ jsx(
|
|
393
|
+
Text,
|
|
394
|
+
// v8 ignore start
|
|
395
|
+
{ children: " " },
|
|
396
|
+
index
|
|
397
|
+
));
|
|
398
|
+
}
|
|
399
|
+
function Message({ message, isStreaming = false, theme }) {
|
|
400
|
+
const messageColor = getMessageColor(message.role, theme);
|
|
483
401
|
const isSystem = message.role === SYSTEM;
|
|
484
402
|
const isUser = message.role === USER;
|
|
485
403
|
const isStreamingAssistant = isStreaming && !isUser && !isSystem;
|
|
404
|
+
const { stdout } = useStdout();
|
|
486
405
|
const stickyHeightRef = useRef({
|
|
487
406
|
columns: stdout.columns,
|
|
488
407
|
maxHeight: 0
|
|
@@ -506,7 +425,10 @@ function Message({ message, isStreaming = false }) {
|
|
|
506
425
|
const streamingHeight = isStreamingAssistant ? segments.reduce((height, segment) => {
|
|
507
426
|
if (segment.type === "code") return height + getCodeBlockHeight(segment.content, availableWidth);
|
|
508
427
|
if (segment.type === "raw") return height + getCodeBlockHeight(unwrapRawMarkdownFence(segment.content) ?? segment.content, availableWidth);
|
|
509
|
-
return height + getStreamingTextHeight(
|
|
428
|
+
return height + getStreamingTextHeight([{
|
|
429
|
+
type: "markdown",
|
|
430
|
+
content: segment.content
|
|
431
|
+
}], availableWidth);
|
|
510
432
|
}, 0) : 0;
|
|
511
433
|
if (isStreamingAssistant) stickyHeightRef.current.maxHeight = Math.max(stickyHeightRef.current.maxHeight, streamingHeight);
|
|
512
434
|
const stickyPaddingLines = isStreamingAssistant ? stickyHeightRef.current.maxHeight - streamingHeight : 0;
|
|
@@ -523,7 +445,8 @@ function Message({ message, isStreaming = false }) {
|
|
|
523
445
|
children: /* @__PURE__ */ jsx(CodeBlock, {
|
|
524
446
|
code: segment.content,
|
|
525
447
|
language: segment.language,
|
|
526
|
-
role: message.role
|
|
448
|
+
role: message.role,
|
|
449
|
+
theme
|
|
527
450
|
})
|
|
528
451
|
}, index);
|
|
529
452
|
if (segment.type === "raw") {
|
|
@@ -533,11 +456,12 @@ function Message({ message, isStreaming = false }) {
|
|
|
533
456
|
children: /* @__PURE__ */ jsx(CodeBlock, {
|
|
534
457
|
code: markdownSource ?? segment.content,
|
|
535
458
|
language: markdownSource ? "markdown" : segment.language,
|
|
536
|
-
role: message.role
|
|
459
|
+
role: message.role,
|
|
460
|
+
theme
|
|
537
461
|
})
|
|
538
462
|
}, index);
|
|
539
463
|
}
|
|
540
|
-
const textParts =
|
|
464
|
+
const textParts = [{
|
|
541
465
|
type: "markdown",
|
|
542
466
|
content: segment.content
|
|
543
467
|
}];
|
|
@@ -547,28 +471,31 @@ function Message({ message, isStreaming = false }) {
|
|
|
547
471
|
}, index) : /* @__PURE__ */ jsx(Box, {
|
|
548
472
|
flexDirection: "column",
|
|
549
473
|
marginX: 2,
|
|
550
|
-
children: textParts.map((part, partIndex) =>
|
|
551
|
-
color: messageColor,
|
|
552
|
-
children: part.content
|
|
553
|
-
}, partIndex) : /* @__PURE__ */ jsx(Markdown, {
|
|
474
|
+
children: textParts.map((part, partIndex) => /* @__PURE__ */ jsx(Markdown, {
|
|
554
475
|
content: part.content,
|
|
555
|
-
|
|
476
|
+
theme
|
|
556
477
|
}, partIndex))
|
|
557
478
|
}, index);
|
|
558
|
-
}),
|
|
479
|
+
}), renderStickyPaddingLines(stickyPaddingLines)]
|
|
559
480
|
});
|
|
560
481
|
}
|
|
561
|
-
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/components/Messages/Messages.tsx
|
|
484
|
+
function Messages({ messages, isLoading, sessionId, streamingMessage, theme = getTheme() }) {
|
|
562
485
|
return /* @__PURE__ */ jsxs(Box, {
|
|
563
486
|
flexDirection: "column",
|
|
564
487
|
children: [
|
|
565
488
|
/* @__PURE__ */ jsx(Static, {
|
|
566
489
|
items: messages.filter(({ content }) => content !== TURN_ABORTED_MESSAGE),
|
|
567
|
-
children: (message, index) => /* @__PURE__ */ jsx(Message, {
|
|
490
|
+
children: (message, index) => /* @__PURE__ */ jsx(Message, {
|
|
491
|
+
message,
|
|
492
|
+
theme
|
|
493
|
+
}, index)
|
|
568
494
|
}, sessionId),
|
|
569
495
|
streamingMessage && /* @__PURE__ */ jsx(Message, {
|
|
570
496
|
isStreaming: true,
|
|
571
|
-
message: streamingMessage
|
|
497
|
+
message: streamingMessage,
|
|
498
|
+
theme
|
|
572
499
|
}),
|
|
573
500
|
isLoading && !streamingMessage?.content && /* @__PURE__ */ jsx(Box, {
|
|
574
501
|
marginTop: -1,
|
|
@@ -580,7 +507,7 @@ function Messages({ messages, isLoading, sessionId, streamingMessage }) {
|
|
|
580
507
|
});
|
|
581
508
|
}
|
|
582
509
|
//#endregion
|
|
583
|
-
//#region src/components/SelectPrompt.tsx
|
|
510
|
+
//#region src/components/SelectPrompt/SelectPrompt.tsx
|
|
584
511
|
function SelectPrompt({ borderStyle, children, onCancel, ...selectProps }) {
|
|
585
512
|
useInput((input, key) => {
|
|
586
513
|
if (key.escape || key.ctrl && input === "c") onCancel?.();
|
|
@@ -591,6 +518,8 @@ function SelectPrompt({ borderStyle, children, onCancel, ...selectProps }) {
|
|
|
591
518
|
children: [children, /* @__PURE__ */ jsx(Select, { ...selectProps })]
|
|
592
519
|
});
|
|
593
520
|
}
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region src/components/SelectPrompt/SelectPromptHint.tsx
|
|
594
523
|
function SelectPromptHint({ message = "Select option", escapeLabel = "cancel" }) {
|
|
595
524
|
return /* @__PURE__ */ jsxs(Box, {
|
|
596
525
|
flexDirection: "row",
|
|
@@ -646,7 +575,7 @@ var options$1 = [
|
|
|
646
575
|
value: PLAN
|
|
647
576
|
}
|
|
648
577
|
];
|
|
649
|
-
function PlanApproval({ planContent, onModeChange }) {
|
|
578
|
+
function PlanApproval({ planContent, onModeChange, theme = getTheme() }) {
|
|
650
579
|
return /* @__PURE__ */ jsx(Box, {
|
|
651
580
|
marginX: 2,
|
|
652
581
|
children: /* @__PURE__ */ jsx(SelectPrompt, {
|
|
@@ -663,7 +592,7 @@ function PlanApproval({ planContent, onModeChange }) {
|
|
|
663
592
|
children: [
|
|
664
593
|
/* @__PURE__ */ jsx(Text, {
|
|
665
594
|
bold: true,
|
|
666
|
-
color:
|
|
595
|
+
color: theme.colors.accent,
|
|
667
596
|
children: "Plan Generated - Choose execution mode:"
|
|
668
597
|
}),
|
|
669
598
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -685,7 +614,7 @@ var options = [{
|
|
|
685
614
|
label: "Reject tool call",
|
|
686
615
|
value: REJECT
|
|
687
616
|
}];
|
|
688
|
-
function ToolApproval({ toolCall, onDecision }) {
|
|
617
|
+
function ToolApproval({ toolCall, onDecision, theme = getTheme() }) {
|
|
689
618
|
const handleChange = useCallback((value) => {
|
|
690
619
|
onDecision(value);
|
|
691
620
|
}, [onDecision]);
|
|
@@ -702,7 +631,7 @@ function ToolApproval({ toolCall, onDecision }) {
|
|
|
702
631
|
onCancel: handleEscape,
|
|
703
632
|
children: [
|
|
704
633
|
/* @__PURE__ */ jsx(Text, {
|
|
705
|
-
color:
|
|
634
|
+
color: theme.colors.warning,
|
|
706
635
|
children: "Tool requires approval ⚠️ "
|
|
707
636
|
}),
|
|
708
637
|
/* @__PURE__ */ jsxs(Box, {
|
|
@@ -1205,7 +1134,7 @@ function hasExecutablePlan(content) {
|
|
|
1205
1134
|
}
|
|
1206
1135
|
//#endregion
|
|
1207
1136
|
//#region src/components/Chat/Chat.tsx
|
|
1208
|
-
function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onModeChange, sessionId }) {
|
|
1137
|
+
function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onModeChange, sessionId, theme = getTheme() }) {
|
|
1209
1138
|
const sessionMessages = initialMessages ?? [];
|
|
1210
1139
|
const history = useMemo(() => sessionMessages.flatMap(({ role, content }) => role === "user" && !content.startsWith("/") ? [content] : []), [sessionMessages]);
|
|
1211
1140
|
const [messages, setMessages] = useState(sessionMessages);
|
|
@@ -1322,13 +1251,13 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1322
1251
|
return;
|
|
1323
1252
|
}
|
|
1324
1253
|
}
|
|
1325
|
-
await prewarmCodeBlocks(assistantMessage.content);
|
|
1254
|
+
await prewarmCodeBlocks(assistantMessage.content, theme);
|
|
1326
1255
|
commitAssistantMessage();
|
|
1327
1256
|
} catch (error) {
|
|
1328
1257
|
// v8 ignore next
|
|
1329
1258
|
if (!controller.signal.aborted) {
|
|
1330
1259
|
assistantMessage.content = `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
1331
|
-
await prewarmCodeBlocks(assistantMessage.content);
|
|
1260
|
+
await prewarmCodeBlocks(assistantMessage.content, theme);
|
|
1332
1261
|
commitAssistantMessage();
|
|
1333
1262
|
}
|
|
1334
1263
|
} finally {
|
|
@@ -1338,7 +1267,8 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1338
1267
|
}, [
|
|
1339
1268
|
buildToolResultMessage,
|
|
1340
1269
|
model,
|
|
1341
|
-
mode
|
|
1270
|
+
mode,
|
|
1271
|
+
theme
|
|
1342
1272
|
]);
|
|
1343
1273
|
const processStreamReadOnly = useCallback(async (currentMessages) => {
|
|
1344
1274
|
const controller = new AbortController();
|
|
@@ -1394,7 +1324,7 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1394
1324
|
return;
|
|
1395
1325
|
}
|
|
1396
1326
|
}
|
|
1397
|
-
await prewarmCodeBlocks(assistantMessage.content);
|
|
1327
|
+
await prewarmCodeBlocks(assistantMessage.content, theme);
|
|
1398
1328
|
const researchMessages = commitAssistantMessage();
|
|
1399
1329
|
const planInstruction = {
|
|
1400
1330
|
role: SYSTEM,
|
|
@@ -1435,7 +1365,7 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1435
1365
|
// v8 ignore next
|
|
1436
1366
|
if (!controller.signal.aborted) {
|
|
1437
1367
|
assistantMessage.content = `Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
1438
|
-
await prewarmCodeBlocks(assistantMessage.content);
|
|
1368
|
+
await prewarmCodeBlocks(assistantMessage.content, theme);
|
|
1439
1369
|
commitAssistantMessage();
|
|
1440
1370
|
}
|
|
1441
1371
|
} finally {
|
|
@@ -1445,7 +1375,8 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1445
1375
|
}, [
|
|
1446
1376
|
buildPlanModeCorrectionMessage,
|
|
1447
1377
|
buildToolResultMessage,
|
|
1448
|
-
model
|
|
1378
|
+
model,
|
|
1379
|
+
theme
|
|
1449
1380
|
]);
|
|
1450
1381
|
const handlePlanApproval = useCallback(async (mode) => {
|
|
1451
1382
|
// v8 ignore next
|
|
@@ -1537,20 +1468,23 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1537
1468
|
messages,
|
|
1538
1469
|
isLoading,
|
|
1539
1470
|
sessionId,
|
|
1540
|
-
streamingMessage
|
|
1471
|
+
streamingMessage,
|
|
1472
|
+
theme
|
|
1541
1473
|
}),
|
|
1542
1474
|
pendingPlan && /* @__PURE__ */ jsx(PlanApproval, {
|
|
1543
1475
|
planContent: pendingPlan.planContent,
|
|
1544
|
-
onModeChange: handlePlanApproval
|
|
1476
|
+
onModeChange: handlePlanApproval,
|
|
1477
|
+
theme
|
|
1545
1478
|
}),
|
|
1546
1479
|
!pendingPlan && pendingToolCall && /* @__PURE__ */ jsx(ToolApproval, {
|
|
1547
1480
|
toolCall: pendingToolCall,
|
|
1548
|
-
onDecision: handleToolApproval
|
|
1481
|
+
onDecision: handleToolApproval,
|
|
1482
|
+
theme
|
|
1549
1483
|
}),
|
|
1550
1484
|
interruptReason && !isLoading && /* @__PURE__ */ jsx(Box, {
|
|
1551
1485
|
marginBottom: 1,
|
|
1552
1486
|
children: /* @__PURE__ */ jsx(Text, {
|
|
1553
|
-
color:
|
|
1487
|
+
color: theme.colors.error,
|
|
1554
1488
|
children: interruptReason === INTERRUPT_REASON.REJECTED ? "❗ Tool call rejected." : "❗ Execution interrupted."
|
|
1555
1489
|
})
|
|
1556
1490
|
}),
|
|
@@ -1568,29 +1502,31 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
|
|
|
1568
1502
|
}
|
|
1569
1503
|
//#endregion
|
|
1570
1504
|
//#region src/components/Footer.tsx
|
|
1571
|
-
function getModeColor(mode) {
|
|
1505
|
+
function getModeColor(mode, theme) {
|
|
1572
1506
|
switch (mode) {
|
|
1573
|
-
case PLAN: return
|
|
1574
|
-
case AUTO: return
|
|
1575
|
-
case SAFE: return
|
|
1507
|
+
case PLAN: return theme.colors.modePlan;
|
|
1508
|
+
case AUTO: return theme.colors.modeAuto;
|
|
1509
|
+
case SAFE: return theme.colors.modeSafe;
|
|
1576
1510
|
// v8 ignore next
|
|
1577
1511
|
default: return;
|
|
1578
1512
|
}
|
|
1579
1513
|
}
|
|
1580
|
-
function Footer({ mode, model, onToggleMode }) {
|
|
1514
|
+
function Footer({ mode, model, onToggleMode, theme = getTheme() }) {
|
|
1581
1515
|
useInput((_, key) => {
|
|
1582
1516
|
if (key.tab && key.shift) onToggleMode();
|
|
1583
1517
|
});
|
|
1584
1518
|
const modeLabel = LABEL[mode];
|
|
1519
|
+
const modeColor = getModeColor(mode, theme);
|
|
1585
1520
|
return /* @__PURE__ */ jsx(Box, {
|
|
1586
1521
|
justifyContent: "space-between",
|
|
1587
1522
|
marginTop: 1,
|
|
1588
1523
|
children: /* @__PURE__ */ jsxs(Text, {
|
|
1524
|
+
color: theme.colors.secondary,
|
|
1589
1525
|
dimColor: true,
|
|
1590
1526
|
children: [
|
|
1591
1527
|
"Mode: ",
|
|
1592
1528
|
/* @__PURE__ */ jsx(Text, {
|
|
1593
|
-
color:
|
|
1529
|
+
color: modeColor,
|
|
1594
1530
|
children: modeLabel
|
|
1595
1531
|
}),
|
|
1596
1532
|
" (Shift+Tab to toggle)",
|
|
@@ -1598,7 +1534,7 @@ function Footer({ mode, model, onToggleMode }) {
|
|
|
1598
1534
|
"❖",
|
|
1599
1535
|
" Model: ",
|
|
1600
1536
|
/* @__PURE__ */ jsx(Text, {
|
|
1601
|
-
color:
|
|
1537
|
+
color: theme.colors.model,
|
|
1602
1538
|
children: model
|
|
1603
1539
|
})
|
|
1604
1540
|
]
|
|
@@ -1611,7 +1547,7 @@ function abbreviatePath(dir) {
|
|
|
1611
1547
|
const home = homedir();
|
|
1612
1548
|
return dir.startsWith(home) ? `~${dir.slice(home.length)}` : dir;
|
|
1613
1549
|
}
|
|
1614
|
-
function Header({ model, onLoad }) {
|
|
1550
|
+
function Header({ model, onLoad, theme = getTheme() }) {
|
|
1615
1551
|
const directory = abbreviatePath(process.cwd());
|
|
1616
1552
|
useEffect(() => {
|
|
1617
1553
|
onLoad();
|
|
@@ -1627,9 +1563,11 @@ function Header({ model, onLoad }) {
|
|
|
1627
1563
|
bold: true,
|
|
1628
1564
|
children: [HEADER_PREFIX, "Code Ollama"]
|
|
1629
1565
|
}), /* @__PURE__ */ jsxs(Text, {
|
|
1566
|
+
color: theme.colors.secondary,
|
|
1630
1567
|
dimColor: true,
|
|
1631
1568
|
children: [
|
|
1632
|
-
"
|
|
1569
|
+
" ",
|
|
1570
|
+
"(v",
|
|
1633
1571
|
VERSION,
|
|
1634
1572
|
")"
|
|
1635
1573
|
]
|
|
@@ -1638,21 +1576,24 @@ function Header({ model, onLoad }) {
|
|
|
1638
1576
|
marginTop: 1,
|
|
1639
1577
|
children: [
|
|
1640
1578
|
/* @__PURE__ */ jsx(Text, {
|
|
1579
|
+
color: theme.colors.secondary,
|
|
1641
1580
|
dimColor: true,
|
|
1642
1581
|
children: "model:".padEnd(11)
|
|
1643
1582
|
}),
|
|
1644
1583
|
/* @__PURE__ */ jsx(Text, { children: model.padEnd(model.length + 3) }),
|
|
1645
1584
|
/* @__PURE__ */ jsx(Text, {
|
|
1646
|
-
color:
|
|
1585
|
+
color: theme.colors.command,
|
|
1647
1586
|
children: "/model"
|
|
1648
1587
|
}),
|
|
1649
|
-
/* @__PURE__ */
|
|
1588
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1589
|
+
color: theme.colors.secondary,
|
|
1650
1590
|
dimColor: true,
|
|
1651
|
-
children: " to switch"
|
|
1591
|
+
children: [" ", "to switch"]
|
|
1652
1592
|
})
|
|
1653
1593
|
]
|
|
1654
1594
|
}),
|
|
1655
1595
|
/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Text, {
|
|
1596
|
+
color: theme.colors.secondary,
|
|
1656
1597
|
dimColor: true,
|
|
1657
1598
|
children: "directory:".padEnd(11)
|
|
1658
1599
|
}), /* @__PURE__ */ jsx(Text, { children: directory })] })
|
|
@@ -1662,7 +1603,7 @@ function Header({ model, onLoad }) {
|
|
|
1662
1603
|
}
|
|
1663
1604
|
//#endregion
|
|
1664
1605
|
//#region src/components/ModelPicker.tsx
|
|
1665
|
-
function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
1606
|
+
function ModelPicker({ currentModel, onSelect, onClose, theme = getTheme() }) {
|
|
1666
1607
|
const [options, setOptions] = useState([]);
|
|
1667
1608
|
const [error, setError] = useState(null);
|
|
1668
1609
|
const handleChange = useCallback((model) => {
|
|
@@ -1693,7 +1634,7 @@ function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
|
1693
1634
|
load();
|
|
1694
1635
|
}, [currentModel]);
|
|
1695
1636
|
if (error) return /* @__PURE__ */ jsxs(Text, {
|
|
1696
|
-
color:
|
|
1637
|
+
color: theme.colors.error,
|
|
1697
1638
|
children: ["Error loading models: ", error]
|
|
1698
1639
|
});
|
|
1699
1640
|
if (!options.length) return /* @__PURE__ */ jsx(Spinner, { label: "Loading models..." });
|
|
@@ -1707,7 +1648,7 @@ function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
|
1707
1648
|
}
|
|
1708
1649
|
//#endregion
|
|
1709
1650
|
//#region src/components/SearchSettings.tsx
|
|
1710
|
-
function SearchSettings({ currentUrl, onClose, onSave }) {
|
|
1651
|
+
function SearchSettings({ currentUrl, onClose, onSave, theme = getTheme() }) {
|
|
1711
1652
|
const [view, setView] = useState("menu");
|
|
1712
1653
|
const [draftUrl, setDraftUrl] = useState(currentUrl ?? "");
|
|
1713
1654
|
const [error, setError] = useState(null);
|
|
@@ -1779,10 +1720,11 @@ function SearchSettings({ currentUrl, onClose, onSave }) {
|
|
|
1779
1720
|
placeholder: "http://localhost:8080"
|
|
1780
1721
|
})] }),
|
|
1781
1722
|
error && /* @__PURE__ */ jsx(Text, {
|
|
1782
|
-
color:
|
|
1723
|
+
color: theme.colors.error,
|
|
1783
1724
|
children: error
|
|
1784
1725
|
}),
|
|
1785
1726
|
/* @__PURE__ */ jsx(Text, {
|
|
1727
|
+
color: theme.colors.secondary,
|
|
1786
1728
|
dimColor: true,
|
|
1787
1729
|
children: "Press Enter to save, Esc to go back."
|
|
1788
1730
|
})
|
|
@@ -1793,10 +1735,14 @@ function SearchSettings({ currentUrl, onClose, onSave }) {
|
|
|
1793
1735
|
onChange: handleChange,
|
|
1794
1736
|
onCancel: onClose,
|
|
1795
1737
|
children: [
|
|
1796
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1738
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1739
|
+
"SearXNG URL:",
|
|
1740
|
+
" ",
|
|
1741
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1742
|
+
color: theme.colors.status,
|
|
1743
|
+
children: currentUrl ?? "not set"
|
|
1744
|
+
})
|
|
1745
|
+
] }),
|
|
1800
1746
|
/* @__PURE__ */ jsx(Text, { children: "DuckDuckGo fallback remains available." }),
|
|
1801
1747
|
/* @__PURE__ */ jsx(SelectPromptHint, { message: "Manage web search settings" })
|
|
1802
1748
|
]
|
|
@@ -1823,7 +1769,7 @@ function formatSessionLabel(session, maxWidth, prefix = "") {
|
|
|
1823
1769
|
if (availableTitleWidth < 1) return truncate(`${prefix}${session.title}${suffix}`, maxWidth);
|
|
1824
1770
|
return `${prefix}${truncate(session.title, availableTitleWidth)}${suffix}`;
|
|
1825
1771
|
}
|
|
1826
|
-
function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen }) {
|
|
1772
|
+
function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen, theme = getTheme() }) {
|
|
1827
1773
|
const [view, setView] = useState("main");
|
|
1828
1774
|
const [error, setError] = useState();
|
|
1829
1775
|
const [, refreshSessionList] = useState(0);
|
|
@@ -1909,7 +1855,7 @@ function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen })
|
|
|
1909
1855
|
error && /* @__PURE__ */ jsx(Box, {
|
|
1910
1856
|
marginBottom: 1,
|
|
1911
1857
|
children: /* @__PURE__ */ jsx(Text, {
|
|
1912
|
-
color:
|
|
1858
|
+
color: theme.colors.error,
|
|
1913
1859
|
children: error
|
|
1914
1860
|
})
|
|
1915
1861
|
}),
|
|
@@ -1922,25 +1868,177 @@ function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen })
|
|
|
1922
1868
|
});
|
|
1923
1869
|
}
|
|
1924
1870
|
//#endregion
|
|
1925
|
-
//#region src/components/
|
|
1926
|
-
function
|
|
1927
|
-
|
|
1871
|
+
//#region src/components/ThemeSettings.tsx
|
|
1872
|
+
function ThemeSettings({ currentTheme, onClose, onPreview, onSave }) {
|
|
1873
|
+
const [selectedIndex, setSelectedIndex] = useState(() => {
|
|
1874
|
+
const initialIndex = LIST$1.findIndex(({ id }) => id === currentTheme);
|
|
1875
|
+
return initialIndex >= 0 ? initialIndex : 0;
|
|
1876
|
+
});
|
|
1877
|
+
const selectedTheme = useMemo(
|
|
1878
|
+
// v8 ignore next
|
|
1879
|
+
() => LIST$1[selectedIndex] ?? getTheme(),
|
|
1880
|
+
[selectedIndex]
|
|
1881
|
+
);
|
|
1882
|
+
useEffect(() => {
|
|
1883
|
+
onPreview(selectedTheme.id);
|
|
1884
|
+
}, [onPreview, selectedTheme.id]);
|
|
1885
|
+
useInput((input, key) => {
|
|
1886
|
+
if (key.escape || key.ctrl && input === "c") {
|
|
1887
|
+
onClose();
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
if (key.upArrow) {
|
|
1891
|
+
setSelectedIndex((current) => current === 0 ? LIST$1.length - 1 : current - 1);
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
if (key.downArrow) {
|
|
1895
|
+
setSelectedIndex((current) => current === LIST$1.length - 1 ? 0 : current + 1);
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
if (key.return) onSave(selectedTheme.id);
|
|
1899
|
+
});
|
|
1900
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
1901
|
+
flexDirection: "column",
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1904
|
+
"Theme:",
|
|
1905
|
+
" ",
|
|
1906
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1907
|
+
color: selectedTheme.colors.accent,
|
|
1908
|
+
children: selectedTheme.label
|
|
1909
|
+
})
|
|
1910
|
+
] }),
|
|
1911
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1912
|
+
color: selectedTheme.colors.secondary,
|
|
1913
|
+
children: selectedTheme.description
|
|
1914
|
+
}),
|
|
1915
|
+
/* @__PURE__ */ jsx(Box, {
|
|
1916
|
+
flexDirection: "column",
|
|
1917
|
+
marginTop: 1,
|
|
1918
|
+
children: LIST$1.map((theme, index) => {
|
|
1919
|
+
const isSelected = index === selectedIndex;
|
|
1920
|
+
return /* @__PURE__ */ jsxs(Text, {
|
|
1921
|
+
color: isSelected ? selectedTheme.colors.accent : void 0,
|
|
1922
|
+
children: [
|
|
1923
|
+
isSelected ? "›" : " ",
|
|
1924
|
+
" ",
|
|
1925
|
+
theme.label
|
|
1926
|
+
]
|
|
1927
|
+
}, theme.id);
|
|
1928
|
+
})
|
|
1929
|
+
}),
|
|
1930
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
1931
|
+
borderColor: selectedTheme.colors.border,
|
|
1932
|
+
borderStyle: "round",
|
|
1933
|
+
flexDirection: "column",
|
|
1934
|
+
marginTop: 1,
|
|
1935
|
+
paddingX: 1,
|
|
1936
|
+
children: [
|
|
1937
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1938
|
+
color: selectedTheme.colors.status,
|
|
1939
|
+
children: [HEADER_PREFIX, " Preview"]
|
|
1940
|
+
}),
|
|
1941
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1942
|
+
color: selectedTheme.colors.secondary,
|
|
1943
|
+
children: "Markdown and code styling follow the selected theme."
|
|
1944
|
+
}),
|
|
1945
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1946
|
+
"Status accent:",
|
|
1947
|
+
" ",
|
|
1948
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1949
|
+
color: selectedTheme.colors.status,
|
|
1950
|
+
children: "search enabled"
|
|
1951
|
+
})
|
|
1952
|
+
] }),
|
|
1953
|
+
/* @__PURE__ */ jsx(CodeBlock, {
|
|
1954
|
+
code: "const theme = 'preview';",
|
|
1955
|
+
language: "ts",
|
|
1956
|
+
role: "assistant",
|
|
1957
|
+
theme: selectedTheme
|
|
1958
|
+
})
|
|
1959
|
+
]
|
|
1960
|
+
}),
|
|
1961
|
+
/* @__PURE__ */ jsx(Box, {
|
|
1962
|
+
marginTop: 1,
|
|
1963
|
+
children: /* @__PURE__ */ jsx(SelectPromptHint, {
|
|
1964
|
+
message: "Preview theme",
|
|
1965
|
+
escapeLabel: "cancel and restore"
|
|
1966
|
+
})
|
|
1967
|
+
})
|
|
1968
|
+
]
|
|
1969
|
+
});
|
|
1928
1970
|
}
|
|
1929
|
-
|
|
1971
|
+
//#endregion
|
|
1972
|
+
//#region src/components/App/constants.ts
|
|
1973
|
+
var SCREEN = /* @__PURE__ */ function(SCREEN) {
|
|
1974
|
+
SCREEN["CHAT"] = "chat";
|
|
1975
|
+
SCREEN["MODEL_PICKER"] = "model-picker";
|
|
1976
|
+
SCREEN["SEARCH_SETTINGS"] = "search-settings";
|
|
1977
|
+
SCREEN["SESSION_MANAGER"] = "session-manager";
|
|
1978
|
+
SCREEN["THEME_SETTINGS"] = "theme-settings";
|
|
1979
|
+
return SCREEN;
|
|
1980
|
+
}({});
|
|
1981
|
+
//#endregion
|
|
1982
|
+
//#region src/components/App/hooks/useScreenRouter.ts
|
|
1983
|
+
function useScreenRouter() {
|
|
1930
1984
|
const { exit } = useApp();
|
|
1931
|
-
const [
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1985
|
+
const [currentScreen, setScreen] = useState(SCREEN.CHAT);
|
|
1986
|
+
return {
|
|
1987
|
+
currentScreen,
|
|
1988
|
+
setScreen,
|
|
1989
|
+
handleClose: useCallback(() => {
|
|
1990
|
+
setScreen(SCREEN.CHAT);
|
|
1991
|
+
}, []),
|
|
1992
|
+
handleCommand: useCallback((command, callbacks) => {
|
|
1993
|
+
const { onCreateSession, onSetPreviewThemeId, model, theme } = callbacks;
|
|
1994
|
+
switch (command) {
|
|
1995
|
+
case "/session":
|
|
1996
|
+
setScreen(SCREEN.SESSION_MANAGER);
|
|
1997
|
+
break;
|
|
1998
|
+
case "/model":
|
|
1999
|
+
setScreen(SCREEN.MODEL_PICKER);
|
|
2000
|
+
break;
|
|
2001
|
+
case "/search":
|
|
2002
|
+
setScreen(SCREEN.SEARCH_SETTINGS);
|
|
2003
|
+
break;
|
|
2004
|
+
case "/theme":
|
|
2005
|
+
onSetPreviewThemeId(theme);
|
|
2006
|
+
setScreen(SCREEN.THEME_SETTINGS);
|
|
2007
|
+
break;
|
|
2008
|
+
case "/clear": {
|
|
2009
|
+
resetSystemMessage();
|
|
2010
|
+
const nextSession = onCreateSession(model);
|
|
2011
|
+
setScreen(SCREEN.CHAT);
|
|
2012
|
+
clear(nextSession.metadata.id);
|
|
2013
|
+
break;
|
|
2014
|
+
}
|
|
2015
|
+
case "/exit":
|
|
2016
|
+
exit();
|
|
2017
|
+
break;
|
|
2018
|
+
}
|
|
2019
|
+
}, [exit])
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
2022
|
+
//#endregion
|
|
2023
|
+
//#region src/components/App/hooks/useSessionManager.ts
|
|
2024
|
+
function useSessionManager({ sessionId, model, commandColor }) {
|
|
2025
|
+
const [activeSession, setSession] = useState(() => sessionId ? loadSession(sessionId) : createSession(model));
|
|
1936
2026
|
const sessionRef = useRef(activeSession);
|
|
2027
|
+
const commandColorRef = useRef(commandColor);
|
|
2028
|
+
const modelRef = useRef(model);
|
|
1937
2029
|
useEffect(() => {
|
|
1938
2030
|
sessionRef.current = activeSession;
|
|
1939
2031
|
}, [activeSession]);
|
|
2032
|
+
useEffect(() => {
|
|
2033
|
+
commandColorRef.current = commandColor;
|
|
2034
|
+
}, [commandColor]);
|
|
2035
|
+
useEffect(() => {
|
|
2036
|
+
modelRef.current = model;
|
|
2037
|
+
}, [model]);
|
|
1940
2038
|
useEffect(() => {
|
|
1941
2039
|
return () => {
|
|
1942
2040
|
const currentSession = sessionRef.current;
|
|
1943
|
-
if (!deleteSessionIfEmpty(currentSession.metadata.id) && currentSession.messages.length > 0) write(`Resume session: ${color(`code-ollama resume ${currentSession.metadata.id}`,
|
|
2041
|
+
if (!deleteSessionIfEmpty(currentSession.metadata.id) && currentSession.messages.length > 0) write(`Resume session: ${color(`code-ollama resume ${currentSession.metadata.id}`, commandColorRef.current)}\n`);
|
|
1944
2042
|
};
|
|
1945
2043
|
}, []);
|
|
1946
2044
|
const setActiveSession = useCallback((nextSession) => {
|
|
@@ -1949,73 +2047,81 @@ function App({ sessionId }) {
|
|
|
1949
2047
|
return nextSession;
|
|
1950
2048
|
});
|
|
1951
2049
|
}, []);
|
|
1952
|
-
|
|
1953
|
-
|
|
2050
|
+
return {
|
|
2051
|
+
activeSession,
|
|
2052
|
+
sessionRef,
|
|
2053
|
+
setActiveSession,
|
|
2054
|
+
setSession,
|
|
2055
|
+
handleCreateSession: useCallback(() => {
|
|
2056
|
+
const nextSession = createSession(modelRef.current);
|
|
2057
|
+
setActiveSession(nextSession);
|
|
2058
|
+
clear(nextSession.metadata.id);
|
|
2059
|
+
return nextSession;
|
|
2060
|
+
}, [setActiveSession]),
|
|
2061
|
+
handleOpenSession: useCallback((sessionId) => {
|
|
2062
|
+
if (sessionRef.current.metadata.id === sessionId) return false;
|
|
2063
|
+
setActiveSession(loadSession(sessionId));
|
|
2064
|
+
clear(sessionId);
|
|
2065
|
+
return true;
|
|
2066
|
+
}, [setActiveSession]),
|
|
2067
|
+
handleDeleteSession: useCallback((sessionId) => {
|
|
2068
|
+
deleteSession(sessionId);
|
|
2069
|
+
setSession((current) => {
|
|
2070
|
+
if (current.metadata.id !== sessionId) return current;
|
|
2071
|
+
return createSession(modelRef.current);
|
|
2072
|
+
});
|
|
2073
|
+
}, []),
|
|
2074
|
+
handleMessagesChange: useCallback((messages) => {
|
|
2075
|
+
setSession((current) => {
|
|
2076
|
+
const persistedMessages = messages.filter(({ content }) => content !== TURN_ABORTED_MESSAGE);
|
|
2077
|
+
if (persistedMessages.length <= current.messages.length) return current;
|
|
2078
|
+
let metadata = current.metadata;
|
|
2079
|
+
for (const message of persistedMessages.slice(current.messages.length)) metadata = appendMessage(metadata.id, message, modelRef.current);
|
|
2080
|
+
return {
|
|
2081
|
+
metadata,
|
|
2082
|
+
messages: persistedMessages
|
|
2083
|
+
};
|
|
2084
|
+
});
|
|
2085
|
+
}, [])
|
|
2086
|
+
};
|
|
2087
|
+
}
|
|
2088
|
+
//#endregion
|
|
2089
|
+
//#region src/components/App/hooks/useThemeSettings.ts
|
|
2090
|
+
function useThemeSettings({ currentTheme, onUpdateConfig, setScreen }) {
|
|
2091
|
+
const [previewThemeId, setPreviewThemeId] = useState(null);
|
|
2092
|
+
const activeThemeId = previewThemeId ?? currentTheme;
|
|
2093
|
+
const activeTheme = getTheme(activeThemeId);
|
|
2094
|
+
const handleThemePreview = useCallback((themeId) => {
|
|
2095
|
+
setPreviewThemeId(themeId);
|
|
1954
2096
|
}, []);
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
let metadata = current.metadata;
|
|
1984
|
-
for (const message of persistedMessages.slice(current.messages.length)) metadata = appendMessage(metadata.id, message, appConfig.model);
|
|
1985
|
-
return {
|
|
1986
|
-
metadata,
|
|
1987
|
-
messages: persistedMessages
|
|
1988
|
-
};
|
|
1989
|
-
});
|
|
1990
|
-
}, [appConfig.model]);
|
|
1991
|
-
const handleCommand = useCallback((command) => {
|
|
1992
|
-
switch (command) {
|
|
1993
|
-
case "/session":
|
|
1994
|
-
setScreen("session-manager");
|
|
1995
|
-
break;
|
|
1996
|
-
case "/model":
|
|
1997
|
-
setScreen("model-picker");
|
|
1998
|
-
break;
|
|
1999
|
-
case "/search":
|
|
2000
|
-
setScreen("search-settings");
|
|
2001
|
-
break;
|
|
2002
|
-
case "/clear": {
|
|
2003
|
-
resetSystemMessage();
|
|
2004
|
-
setScreen("chat");
|
|
2005
|
-
const nextSession = createSession$1(appConfig.model);
|
|
2006
|
-
setActiveSession(nextSession);
|
|
2007
|
-
clear(nextSession.metadata.id);
|
|
2008
|
-
break;
|
|
2009
|
-
}
|
|
2010
|
-
case "/exit":
|
|
2011
|
-
exit();
|
|
2012
|
-
break;
|
|
2013
|
-
}
|
|
2014
|
-
}, [
|
|
2015
|
-
appConfig.model,
|
|
2016
|
-
exit,
|
|
2017
|
-
setActiveSession
|
|
2018
|
-
]);
|
|
2097
|
+
return {
|
|
2098
|
+
activeTheme,
|
|
2099
|
+
activeThemeId,
|
|
2100
|
+
handleThemeClose: useCallback(() => {
|
|
2101
|
+
setPreviewThemeId(null);
|
|
2102
|
+
setScreen(SCREEN.CHAT);
|
|
2103
|
+
}, [setScreen]),
|
|
2104
|
+
handleThemePreview,
|
|
2105
|
+
handleThemeSave: useCallback((themeId) => {
|
|
2106
|
+
setPreviewThemeId(null);
|
|
2107
|
+
onUpdateConfig({ theme: themeId });
|
|
2108
|
+
}, [onUpdateConfig]),
|
|
2109
|
+
previewThemeId,
|
|
2110
|
+
setPreviewThemeId
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
//#endregion
|
|
2114
|
+
//#region src/components/App/App.tsx
|
|
2115
|
+
function App({ sessionId }) {
|
|
2116
|
+
const [appConfig, setConfig] = useState(() => loadConfig());
|
|
2117
|
+
const [mode, setMode] = useState(SAFE);
|
|
2118
|
+
const [isHeaderLoaded, setIsHeaderLoaded] = useState(false);
|
|
2119
|
+
const { currentScreen, setScreen, handleClose, handleCommand } = useScreenRouter();
|
|
2120
|
+
const { activeSession, setSession, handleCreateSession, handleOpenSession, handleDeleteSession, handleMessagesChange } = useSessionManager({
|
|
2121
|
+
sessionId,
|
|
2122
|
+
model: appConfig.model,
|
|
2123
|
+
commandColor: getTheme(appConfig.theme).colors.command
|
|
2124
|
+
});
|
|
2019
2125
|
const handleUpdateConfig = useCallback((update) => {
|
|
2020
2126
|
setConfig((current) => ({
|
|
2021
2127
|
...current,
|
|
@@ -2027,10 +2133,15 @@ function App({ sessionId }) {
|
|
|
2027
2133
|
...current,
|
|
2028
2134
|
metadata: updateSessionModel(current.metadata.id, newModel)
|
|
2029
2135
|
}));
|
|
2030
|
-
setScreen(
|
|
2031
|
-
}, []);
|
|
2032
|
-
const
|
|
2033
|
-
|
|
2136
|
+
setScreen(SCREEN.CHAT);
|
|
2137
|
+
}, [setScreen, setSession]);
|
|
2138
|
+
const { activeTheme, handleThemeClose, handleThemePreview, handleThemeSave, setPreviewThemeId } = useThemeSettings({
|
|
2139
|
+
currentTheme: appConfig.theme,
|
|
2140
|
+
onUpdateConfig: handleUpdateConfig,
|
|
2141
|
+
setScreen
|
|
2142
|
+
});
|
|
2143
|
+
const handleHeaderLoad = useCallback(() => {
|
|
2144
|
+
setIsHeaderLoaded(true);
|
|
2034
2145
|
}, []);
|
|
2035
2146
|
const handleToggleMode = useCallback(() => {
|
|
2036
2147
|
setMode((mode) => {
|
|
@@ -2042,40 +2153,78 @@ function App({ sessionId }) {
|
|
|
2042
2153
|
}
|
|
2043
2154
|
});
|
|
2044
2155
|
}, []);
|
|
2156
|
+
const handleChatCommand = useCallback((command) => {
|
|
2157
|
+
handleCommand(command, {
|
|
2158
|
+
model: appConfig.model,
|
|
2159
|
+
theme: appConfig.theme,
|
|
2160
|
+
onCreateSession: handleCreateSession,
|
|
2161
|
+
onSetPreviewThemeId: setPreviewThemeId
|
|
2162
|
+
});
|
|
2163
|
+
}, [
|
|
2164
|
+
appConfig.model,
|
|
2165
|
+
appConfig.theme,
|
|
2166
|
+
handleCommand,
|
|
2167
|
+
handleCreateSession,
|
|
2168
|
+
setPreviewThemeId
|
|
2169
|
+
]);
|
|
2170
|
+
const handleDeleteSessionAndStay = useCallback((sid) => {
|
|
2171
|
+
handleDeleteSession(sid);
|
|
2172
|
+
setScreen(SCREEN.SESSION_MANAGER);
|
|
2173
|
+
}, [handleDeleteSession, setScreen]);
|
|
2174
|
+
const handleOpenSessionAndNavigate = useCallback((sid) => {
|
|
2175
|
+
handleOpenSession(sid);
|
|
2176
|
+
setScreen(SCREEN.CHAT);
|
|
2177
|
+
}, [handleOpenSession, setScreen]);
|
|
2178
|
+
const handleCreateSessionAndNavigate = useCallback(() => {
|
|
2179
|
+
handleCreateSession();
|
|
2180
|
+
setScreen(SCREEN.CHAT);
|
|
2181
|
+
}, [handleCreateSession, setScreen]);
|
|
2045
2182
|
let screenContent;
|
|
2046
2183
|
switch (currentScreen) {
|
|
2047
|
-
case
|
|
2184
|
+
case SCREEN.MODEL_PICKER:
|
|
2048
2185
|
screenContent = /* @__PURE__ */ jsx(ModelPicker, {
|
|
2049
2186
|
currentModel: appConfig.model,
|
|
2050
2187
|
onSelect: handleUpdateConfig,
|
|
2051
|
-
onClose: handleClose
|
|
2188
|
+
onClose: handleClose,
|
|
2189
|
+
theme: activeTheme
|
|
2052
2190
|
});
|
|
2053
2191
|
break;
|
|
2054
|
-
case
|
|
2192
|
+
case SCREEN.SEARCH_SETTINGS:
|
|
2055
2193
|
screenContent = /* @__PURE__ */ jsx(SearchSettings, {
|
|
2056
2194
|
currentUrl: appConfig.searxngBaseUrl,
|
|
2057
2195
|
onSave: handleUpdateConfig,
|
|
2058
|
-
onClose: handleClose
|
|
2196
|
+
onClose: handleClose,
|
|
2197
|
+
theme: activeTheme
|
|
2059
2198
|
});
|
|
2060
2199
|
break;
|
|
2061
|
-
case
|
|
2200
|
+
case SCREEN.SESSION_MANAGER:
|
|
2062
2201
|
screenContent = /* @__PURE__ */ jsx(SessionManager, {
|
|
2063
2202
|
currentSessionId: activeSession.metadata.id,
|
|
2064
2203
|
onClose: handleClose,
|
|
2065
|
-
onDelete:
|
|
2066
|
-
onNew:
|
|
2067
|
-
onOpen:
|
|
2204
|
+
onDelete: handleDeleteSessionAndStay,
|
|
2205
|
+
onNew: handleCreateSessionAndNavigate,
|
|
2206
|
+
onOpen: handleOpenSessionAndNavigate,
|
|
2207
|
+
theme: activeTheme
|
|
2208
|
+
});
|
|
2209
|
+
break;
|
|
2210
|
+
case SCREEN.THEME_SETTINGS:
|
|
2211
|
+
screenContent = /* @__PURE__ */ jsx(ThemeSettings, {
|
|
2212
|
+
currentTheme: appConfig.theme,
|
|
2213
|
+
onClose: handleThemeClose,
|
|
2214
|
+
onPreview: handleThemePreview,
|
|
2215
|
+
onSave: handleThemeSave
|
|
2068
2216
|
});
|
|
2069
2217
|
break;
|
|
2070
|
-
case
|
|
2218
|
+
case SCREEN.CHAT:
|
|
2071
2219
|
screenContent = /* @__PURE__ */ jsx(Chat, {
|
|
2072
2220
|
initialMessages: activeSession.messages,
|
|
2073
2221
|
model: appConfig.model,
|
|
2074
|
-
onCommand:
|
|
2222
|
+
onCommand: handleChatCommand,
|
|
2075
2223
|
onMessagesChange: handleMessagesChange,
|
|
2076
2224
|
mode,
|
|
2077
2225
|
onModeChange: setMode,
|
|
2078
|
-
sessionId: activeSession.metadata.id
|
|
2226
|
+
sessionId: activeSession.metadata.id,
|
|
2227
|
+
theme: activeTheme
|
|
2079
2228
|
});
|
|
2080
2229
|
break;
|
|
2081
2230
|
}
|
|
@@ -2084,13 +2233,15 @@ function App({ sessionId }) {
|
|
|
2084
2233
|
children: [
|
|
2085
2234
|
/* @__PURE__ */ jsx(Header, {
|
|
2086
2235
|
model: appConfig.model,
|
|
2087
|
-
onLoad: handleHeaderLoad
|
|
2236
|
+
onLoad: handleHeaderLoad,
|
|
2237
|
+
theme: activeTheme
|
|
2088
2238
|
}),
|
|
2089
2239
|
isHeaderLoaded && screenContent,
|
|
2090
2240
|
/* @__PURE__ */ jsx(Footer, {
|
|
2091
2241
|
mode,
|
|
2092
2242
|
model: appConfig.model,
|
|
2093
|
-
onToggleMode: handleToggleMode
|
|
2243
|
+
onToggleMode: handleToggleMode,
|
|
2244
|
+
theme: activeTheme
|
|
2094
2245
|
})
|
|
2095
2246
|
]
|
|
2096
2247
|
});
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { v7 } from "uuid";
|
|
|
8
8
|
import { exec } from "node:child_process";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
10
|
//#region src/constants/command.ts
|
|
11
|
-
var LIST = [
|
|
11
|
+
var LIST$1 = [
|
|
12
12
|
{
|
|
13
13
|
name: "/clear",
|
|
14
14
|
description: "clear the current session"
|
|
@@ -21,6 +21,10 @@ var LIST = [
|
|
|
21
21
|
name: "/model",
|
|
22
22
|
description: "switch the model"
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
name: "/theme",
|
|
26
|
+
description: "change the theme"
|
|
27
|
+
},
|
|
24
28
|
{
|
|
25
29
|
name: "/search",
|
|
26
30
|
description: "configure web search"
|
|
@@ -33,7 +37,7 @@ var LIST = [
|
|
|
33
37
|
//#endregion
|
|
34
38
|
//#region package.json
|
|
35
39
|
var name = "code-ollama";
|
|
36
|
-
var version = "0.
|
|
40
|
+
var version = "0.17.0";
|
|
37
41
|
//#endregion
|
|
38
42
|
//#region src/constants/package.ts
|
|
39
43
|
var NAME = name;
|
|
@@ -102,6 +106,146 @@ var USER = "user";
|
|
|
102
106
|
var ASSISTANT = "assistant";
|
|
103
107
|
var SYSTEM = "system";
|
|
104
108
|
//#endregion
|
|
109
|
+
//#region src/constants/theme.ts
|
|
110
|
+
var DEFAULT_THEME_ID = "github-dark";
|
|
111
|
+
var LIST = [
|
|
112
|
+
{
|
|
113
|
+
id: "github-light",
|
|
114
|
+
label: "GitHub Light",
|
|
115
|
+
description: "Light GitHub palette",
|
|
116
|
+
markdownTheme: "gitHub",
|
|
117
|
+
codeTheme: "github-light",
|
|
118
|
+
colors: {
|
|
119
|
+
accent: "blue",
|
|
120
|
+
border: "blue",
|
|
121
|
+
codeBorder: "blue",
|
|
122
|
+
command: "blue",
|
|
123
|
+
error: "red",
|
|
124
|
+
messageSystem: "gray",
|
|
125
|
+
modeAuto: "magenta",
|
|
126
|
+
modePlan: "blue",
|
|
127
|
+
modeSafe: "green",
|
|
128
|
+
model: "blue",
|
|
129
|
+
secondary: "gray",
|
|
130
|
+
status: "cyan",
|
|
131
|
+
warning: "yellow"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: "github-dark",
|
|
136
|
+
label: "GitHub Dark",
|
|
137
|
+
description: "Dark GitHub palette",
|
|
138
|
+
markdownTheme: "gitHub",
|
|
139
|
+
codeTheme: "github-dark",
|
|
140
|
+
colors: {
|
|
141
|
+
accent: "cyan",
|
|
142
|
+
border: "cyan",
|
|
143
|
+
codeBorder: "gray",
|
|
144
|
+
command: "cyan",
|
|
145
|
+
error: "red",
|
|
146
|
+
messageSystem: "gray",
|
|
147
|
+
modeAuto: "magenta",
|
|
148
|
+
modePlan: "blue",
|
|
149
|
+
modeSafe: "green",
|
|
150
|
+
model: "cyan",
|
|
151
|
+
secondary: "gray",
|
|
152
|
+
status: "cyan",
|
|
153
|
+
warning: "yellow"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "nord",
|
|
158
|
+
label: "Nord",
|
|
159
|
+
description: "Cool nordic blues",
|
|
160
|
+
markdownTheme: "nord",
|
|
161
|
+
codeTheme: "nord",
|
|
162
|
+
colors: {
|
|
163
|
+
accent: "cyan",
|
|
164
|
+
border: "blue",
|
|
165
|
+
codeBorder: "blue",
|
|
166
|
+
command: "cyan",
|
|
167
|
+
error: "red",
|
|
168
|
+
messageSystem: "gray",
|
|
169
|
+
modeAuto: "magenta",
|
|
170
|
+
modePlan: "blue",
|
|
171
|
+
modeSafe: "green",
|
|
172
|
+
model: "cyan",
|
|
173
|
+
secondary: "gray",
|
|
174
|
+
status: "blue",
|
|
175
|
+
warning: "yellow"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
id: "dracula",
|
|
180
|
+
label: "Dracula",
|
|
181
|
+
description: "Bright neon contrast",
|
|
182
|
+
markdownTheme: "dracula",
|
|
183
|
+
codeTheme: "dracula",
|
|
184
|
+
colors: {
|
|
185
|
+
accent: "magenta",
|
|
186
|
+
border: "magenta",
|
|
187
|
+
codeBorder: "magenta",
|
|
188
|
+
command: "magenta",
|
|
189
|
+
error: "red",
|
|
190
|
+
messageSystem: "gray",
|
|
191
|
+
modeAuto: "yellow",
|
|
192
|
+
modePlan: "magenta",
|
|
193
|
+
modeSafe: "green",
|
|
194
|
+
model: "magenta",
|
|
195
|
+
secondary: "gray",
|
|
196
|
+
status: "cyan",
|
|
197
|
+
warning: "yellow"
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: "solarized-light",
|
|
202
|
+
label: "Solarized Light",
|
|
203
|
+
description: "Warm light contrast",
|
|
204
|
+
markdownTheme: "solarized",
|
|
205
|
+
codeTheme: "solarized-light",
|
|
206
|
+
colors: {
|
|
207
|
+
accent: "yellow",
|
|
208
|
+
border: "yellow",
|
|
209
|
+
codeBorder: "yellow",
|
|
210
|
+
command: "yellow",
|
|
211
|
+
error: "red",
|
|
212
|
+
messageSystem: "gray",
|
|
213
|
+
modeAuto: "cyan",
|
|
214
|
+
modePlan: "blue",
|
|
215
|
+
modeSafe: "green",
|
|
216
|
+
model: "yellow",
|
|
217
|
+
secondary: "gray",
|
|
218
|
+
status: "cyan",
|
|
219
|
+
warning: "yellow"
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: "solarized-dark",
|
|
224
|
+
label: "Solarized Dark",
|
|
225
|
+
description: "Warm dark contrast",
|
|
226
|
+
markdownTheme: "solarized",
|
|
227
|
+
codeTheme: "solarized-dark",
|
|
228
|
+
colors: {
|
|
229
|
+
accent: "yellow",
|
|
230
|
+
border: "yellow",
|
|
231
|
+
codeBorder: "yellow",
|
|
232
|
+
command: "yellow",
|
|
233
|
+
error: "red",
|
|
234
|
+
messageSystem: "gray",
|
|
235
|
+
modeAuto: "cyan",
|
|
236
|
+
modePlan: "blue",
|
|
237
|
+
modeSafe: "green",
|
|
238
|
+
model: "yellow",
|
|
239
|
+
secondary: "gray",
|
|
240
|
+
status: "cyan",
|
|
241
|
+
warning: "yellow"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
];
|
|
245
|
+
function getTheme(themeId = DEFAULT_THEME_ID) {
|
|
246
|
+
return LIST.find(({ id }) => id === themeId) ?? LIST[0];
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
105
249
|
//#region src/constants/tool.ts
|
|
106
250
|
var READ_FILE = "read_file";
|
|
107
251
|
var WRITE_FILE = "write_file";
|
|
@@ -166,7 +310,8 @@ function loadConfig() {
|
|
|
166
310
|
return {
|
|
167
311
|
host: process.env.OLLAMA_HOST ?? file.host ?? DEFAULT_HOST,
|
|
168
312
|
model: process.env.OLLAMA_MODEL ?? file.model ?? DEFAULT_MODEL$1,
|
|
169
|
-
searxngBaseUrl: file.searxngBaseUrl
|
|
313
|
+
searxngBaseUrl: file.searxngBaseUrl,
|
|
314
|
+
theme: file.theme ?? "github-dark"
|
|
170
315
|
};
|
|
171
316
|
}
|
|
172
317
|
function saveConfig(patch) {
|
|
@@ -370,7 +515,16 @@ function deleteSession(id) {
|
|
|
370
515
|
}
|
|
371
516
|
//#endregion
|
|
372
517
|
//#region src/utils/terminal.ts
|
|
373
|
-
var
|
|
518
|
+
var ANSI_RESET_FOREGROUND = "\x1B[39m";
|
|
519
|
+
var ANSI_COLOR = {
|
|
520
|
+
blue: ["\x1B[34m", ANSI_RESET_FOREGROUND],
|
|
521
|
+
cyan: ["\x1B[36m", ANSI_RESET_FOREGROUND],
|
|
522
|
+
gray: ["\x1B[90m", ANSI_RESET_FOREGROUND],
|
|
523
|
+
green: ["\x1B[32m", ANSI_RESET_FOREGROUND],
|
|
524
|
+
magenta: ["\x1B[35m", ANSI_RESET_FOREGROUND],
|
|
525
|
+
red: ["\x1B[31m", ANSI_RESET_FOREGROUND],
|
|
526
|
+
yellow: ["\x1B[33m", ANSI_RESET_FOREGROUND]
|
|
527
|
+
};
|
|
374
528
|
function color(text, name) {
|
|
375
529
|
const [open, close] = ANSI_COLOR[name];
|
|
376
530
|
return `${open}${text}${close}`;
|
|
@@ -931,7 +1085,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
931
1085
|
else await launchTui();
|
|
932
1086
|
}
|
|
933
1087
|
async function launchTui(sessionId) {
|
|
934
|
-
const { renderApp } = await import("./assets/tui-
|
|
1088
|
+
const { renderApp } = await import("./assets/tui-CCHcdC7V.js");
|
|
935
1089
|
reset();
|
|
936
1090
|
renderApp(sessionId);
|
|
937
1091
|
}
|
|
@@ -947,4 +1101,4 @@ function isEntrypoint(argv1 = process.argv[1]) {
|
|
|
947
1101
|
if (isEntrypoint()) main();
|
|
948
1102
|
// v8 ignore stop
|
|
949
1103
|
//#endregion
|
|
950
|
-
export {
|
|
1104
|
+
export { PLAN_GENERATION_INSTRUCTION as A, withSystemMessage as C, ASSISTANT as D, getTheme as E, APPROVE as F, REJECT as I, VERSION as L, LABEL as M, PLAN as N, SYSTEM as O, SAFE as P, LIST$1 as R, resetSystemMessage as S, LIST as T, setClearHandler as _, tick as a, loadConfig as b, appendMessage as c, deleteSessionIfEmpty as d, listSessions as f, reset as g, clear as h, WRITE_TOOLS as i, AUTO as j, USER as k, createSession as l, updateSessionModel as m, main, READ_TOOLS as n, color as o, loadSession as p, TOOLS as r, write as s, executeTool as t, deleteSession as u, listModels as v, HEADER_PREFIX as w, saveConfig as x, streamChat as y };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-ollama",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Ollama coding agent that runs in your terminal",
|
|
5
5
|
"author": "Mark <mark@remarkablemark.org> (https://remarkablemark.org)",
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@commitlint/cli": "21.0.1",
|
|
54
54
|
"@commitlint/config-conventional": "21.0.1",
|
|
55
|
-
"@eslint/config-helpers": "0.6.0",
|
|
56
55
|
"@eslint/js": "10.0.1",
|
|
57
56
|
"@types/node": "25.8.0",
|
|
58
57
|
"@types/react": "19.2.14",
|
|
@@ -63,7 +62,7 @@
|
|
|
63
62
|
"globals": "17.6.0",
|
|
64
63
|
"husky": "9.1.7",
|
|
65
64
|
"ink-testing-library": "4.0.0",
|
|
66
|
-
"lint-staged": "17.0.
|
|
65
|
+
"lint-staged": "17.0.5",
|
|
67
66
|
"prettier": "3.8.3",
|
|
68
67
|
"publint": "0.3.21",
|
|
69
68
|
"tsx": "4.22.0",
|