code-ollama 0.14.2 → 0.15.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-Dse5XVJ_.js → tui-DPx5MGHZ.js} +126 -108
- package/dist/cli.js +29 -46
- package/package.json +1 -1
|
@@ -218,6 +218,99 @@ var TURN_ABORTED_MESSAGE = [
|
|
|
218
218
|
].join("\n");
|
|
219
219
|
//#endregion
|
|
220
220
|
//#region src/components/Messages/utils.ts
|
|
221
|
+
var FENCE_LINE_REGEX = /^(?<indent>[ \t]*)(?<fence>`{3,})(?<language>\w+)?[ \t]*$/;
|
|
222
|
+
function flushTextSegment(segments, textLines) {
|
|
223
|
+
const textContent = textLines.join("\n").trim();
|
|
224
|
+
if (textContent) segments.push({
|
|
225
|
+
type: "text",
|
|
226
|
+
content: textContent
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function flushCodeSegment(segments, codeLines, fenceState) {
|
|
230
|
+
if (fenceState.ambiguous) {
|
|
231
|
+
segments.push({
|
|
232
|
+
type: "raw",
|
|
233
|
+
content: fenceState.rawLines.join("\n")
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const codeContent = normalizeCodeBlockContent(codeLines.join("\n"), fenceState.indent);
|
|
238
|
+
if (codeContent) segments.push({
|
|
239
|
+
type: "code",
|
|
240
|
+
content: codeContent,
|
|
241
|
+
language: fenceState.language
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function unwrapRawMarkdownFence(content) {
|
|
245
|
+
if (!content.startsWith("```markdown\n") || !content.endsWith("\n```")) return null;
|
|
246
|
+
return content.slice(12, -4);
|
|
247
|
+
}
|
|
248
|
+
function parseContent(content) {
|
|
249
|
+
const segments = [];
|
|
250
|
+
const lines = content.split("\n");
|
|
251
|
+
const textLines = [];
|
|
252
|
+
const codeLines = [];
|
|
253
|
+
let fenceState = null;
|
|
254
|
+
for (const line of lines) {
|
|
255
|
+
const fenceMatch = FENCE_LINE_REGEX.exec(line);
|
|
256
|
+
if (fenceMatch?.groups) {
|
|
257
|
+
const { indent, fence, language } = fenceMatch.groups;
|
|
258
|
+
if (!fenceState) {
|
|
259
|
+
flushTextSegment(segments, textLines);
|
|
260
|
+
textLines.length = 0;
|
|
261
|
+
fenceState = {
|
|
262
|
+
indent,
|
|
263
|
+
fence,
|
|
264
|
+
language,
|
|
265
|
+
rawLines: [line],
|
|
266
|
+
ambiguous: false,
|
|
267
|
+
rawFenceDepth: 1
|
|
268
|
+
};
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (indent === fenceState.indent && fence === fenceState.fence) {
|
|
272
|
+
fenceState.rawLines.push(line);
|
|
273
|
+
if (fenceState.ambiguous) {
|
|
274
|
+
if (language) {
|
|
275
|
+
fenceState.rawFenceDepth += 1;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
fenceState.rawFenceDepth -= 1;
|
|
279
|
+
if (fenceState.rawFenceDepth === 0) {
|
|
280
|
+
flushCodeSegment(segments, codeLines, fenceState);
|
|
281
|
+
codeLines.length = 0;
|
|
282
|
+
fenceState = null;
|
|
283
|
+
}
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (!language) {
|
|
287
|
+
flushCodeSegment(segments, codeLines, fenceState);
|
|
288
|
+
codeLines.length = 0;
|
|
289
|
+
fenceState = null;
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
fenceState.ambiguous = true;
|
|
293
|
+
fenceState.rawFenceDepth += 1;
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (fenceState) {
|
|
298
|
+
fenceState.rawLines.push(line);
|
|
299
|
+
codeLines.push(line);
|
|
300
|
+
} else textLines.push(line);
|
|
301
|
+
}
|
|
302
|
+
if (fenceState) textLines.push(...fenceState.rawLines);
|
|
303
|
+
flushTextSegment(segments, textLines);
|
|
304
|
+
return segments;
|
|
305
|
+
}
|
|
306
|
+
function getMessageColor(role) {
|
|
307
|
+
switch (role) {
|
|
308
|
+
case USER: return "black";
|
|
309
|
+
case ASSISTANT: return "cyan";
|
|
310
|
+
case SYSTEM: return "gray";
|
|
311
|
+
default: return;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
221
314
|
function isWordCharacter(char) {
|
|
222
315
|
return char !== void 0 && /[A-Za-z0-9]/.test(char);
|
|
223
316
|
}
|
|
@@ -313,100 +406,7 @@ function splitStreamingInlineContent(content) {
|
|
|
313
406
|
}
|
|
314
407
|
//#endregion
|
|
315
408
|
//#region src/components/Messages/Messages.tsx
|
|
316
|
-
function
|
|
317
|
-
switch (role) {
|
|
318
|
-
case USER: return "black";
|
|
319
|
-
case ASSISTANT: return "cyan";
|
|
320
|
-
case SYSTEM: return "gray";
|
|
321
|
-
default: return;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
var FENCE_LINE_REGEX = /^(?<indent>[ \t]*)(?<fence>`{3,})(?<language>\w+)?[ \t]*$/;
|
|
325
|
-
function flushTextSegment(segments, textLines) {
|
|
326
|
-
const textContent = textLines.join("\n").trim();
|
|
327
|
-
if (textContent) segments.push({
|
|
328
|
-
type: "text",
|
|
329
|
-
content: textContent
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
function flushCodeSegment(segments, codeLines, fenceState) {
|
|
333
|
-
if (fenceState.ambiguous) {
|
|
334
|
-
segments.push({
|
|
335
|
-
type: "raw",
|
|
336
|
-
content: fenceState.rawLines.join("\n")
|
|
337
|
-
});
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const codeContent = normalizeCodeBlockContent(codeLines.join("\n"), fenceState.indent);
|
|
341
|
-
if (codeContent) segments.push({
|
|
342
|
-
type: "code",
|
|
343
|
-
content: codeContent,
|
|
344
|
-
language: fenceState.language
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
function unwrapRawMarkdownFence(content) {
|
|
348
|
-
if (!content.startsWith("```markdown\n") || !content.endsWith("\n```")) return null;
|
|
349
|
-
return content.slice(12, -4);
|
|
350
|
-
}
|
|
351
|
-
function parseContent(content) {
|
|
352
|
-
const segments = [];
|
|
353
|
-
const lines = content.split("\n");
|
|
354
|
-
const textLines = [];
|
|
355
|
-
const codeLines = [];
|
|
356
|
-
let fenceState = null;
|
|
357
|
-
for (const line of lines) {
|
|
358
|
-
const fenceMatch = FENCE_LINE_REGEX.exec(line);
|
|
359
|
-
if (fenceMatch?.groups) {
|
|
360
|
-
const { indent, fence, language } = fenceMatch.groups;
|
|
361
|
-
if (!fenceState) {
|
|
362
|
-
flushTextSegment(segments, textLines);
|
|
363
|
-
textLines.length = 0;
|
|
364
|
-
fenceState = {
|
|
365
|
-
indent,
|
|
366
|
-
fence,
|
|
367
|
-
language,
|
|
368
|
-
rawLines: [line],
|
|
369
|
-
ambiguous: false,
|
|
370
|
-
rawFenceDepth: 1
|
|
371
|
-
};
|
|
372
|
-
continue;
|
|
373
|
-
}
|
|
374
|
-
if (indent === fenceState.indent && fence === fenceState.fence) {
|
|
375
|
-
fenceState.rawLines.push(line);
|
|
376
|
-
if (fenceState.ambiguous) {
|
|
377
|
-
if (language) {
|
|
378
|
-
fenceState.rawFenceDepth += 1;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
fenceState.rawFenceDepth -= 1;
|
|
382
|
-
if (fenceState.rawFenceDepth === 0) {
|
|
383
|
-
flushCodeSegment(segments, codeLines, fenceState);
|
|
384
|
-
codeLines.length = 0;
|
|
385
|
-
fenceState = null;
|
|
386
|
-
}
|
|
387
|
-
continue;
|
|
388
|
-
}
|
|
389
|
-
if (!language) {
|
|
390
|
-
flushCodeSegment(segments, codeLines, fenceState);
|
|
391
|
-
codeLines.length = 0;
|
|
392
|
-
fenceState = null;
|
|
393
|
-
continue;
|
|
394
|
-
}
|
|
395
|
-
fenceState.ambiguous = true;
|
|
396
|
-
fenceState.rawFenceDepth += 1;
|
|
397
|
-
continue;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
if (fenceState) {
|
|
401
|
-
fenceState.rawLines.push(line);
|
|
402
|
-
codeLines.push(line);
|
|
403
|
-
} else textLines.push(line);
|
|
404
|
-
}
|
|
405
|
-
if (fenceState) textLines.push(...fenceState.rawLines);
|
|
406
|
-
flushTextSegment(segments, textLines);
|
|
407
|
-
return segments;
|
|
408
|
-
}
|
|
409
|
-
var Message = memo(function Message({ message, isStreaming = false }) {
|
|
409
|
+
function Message({ message, isStreaming = false }) {
|
|
410
410
|
const messageColor = getMessageColor(message.role);
|
|
411
411
|
const isSystem = message.role === SYSTEM;
|
|
412
412
|
const isUser = message.role === USER;
|
|
@@ -467,8 +467,8 @@ var Message = memo(function Message({ message, isStreaming = false }) {
|
|
|
467
467
|
}, index);
|
|
468
468
|
})
|
|
469
469
|
});
|
|
470
|
-
}
|
|
471
|
-
function Messages({ messages, isLoading, sessionId
|
|
470
|
+
}
|
|
471
|
+
function Messages({ messages, isLoading, sessionId, streamingMessage }) {
|
|
472
472
|
return /* @__PURE__ */ jsxs(Box, {
|
|
473
473
|
flexDirection: "column",
|
|
474
474
|
children: [
|
|
@@ -1659,34 +1659,49 @@ var ACTION = {
|
|
|
1659
1659
|
DELETE_MENU: "delete-menu",
|
|
1660
1660
|
DELETE_PREFIX: "delete:",
|
|
1661
1661
|
NEW: "new",
|
|
1662
|
+
OPEN_MENU: "open-menu",
|
|
1662
1663
|
OPEN_PREFIX: "open:"
|
|
1663
1664
|
};
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
return `${
|
|
1665
|
+
var SESSION_LABEL_PADDING = 4;
|
|
1666
|
+
function truncate(value, maxLength) {
|
|
1667
|
+
return value.length > maxLength ? `${value.slice(0, maxLength - 1).trimEnd()}…` : value;
|
|
1668
|
+
}
|
|
1669
|
+
function formatSessionLabel(session, maxWidth, prefix = "") {
|
|
1670
|
+
const suffix = ` (${new Date(session.updatedAt).toLocaleString()})`;
|
|
1671
|
+
const availableTitleWidth = maxWidth - prefix.length - suffix.length;
|
|
1672
|
+
if (availableTitleWidth < 1) return truncate(`${prefix}${session.title}${suffix}`, maxWidth);
|
|
1673
|
+
return `${prefix}${truncate(session.title, availableTitleWidth)}${suffix}`;
|
|
1667
1674
|
}
|
|
1668
1675
|
function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen }) {
|
|
1669
1676
|
const [view, setView] = useState("main");
|
|
1670
1677
|
const [error, setError] = useState();
|
|
1671
1678
|
const [, refreshSessionList] = useState(0);
|
|
1679
|
+
const { stdout } = useStdout();
|
|
1672
1680
|
const sessions = listSessions();
|
|
1673
|
-
const
|
|
1674
|
-
|
|
1681
|
+
const maxLabelWidth = Math.max(1, stdout.columns - SESSION_LABEL_PADDING);
|
|
1682
|
+
const options = view === "open" ? [...sessions.filter(({ id }) => id !== currentSessionId).map((session) => ({
|
|
1683
|
+
label: formatSessionLabel(session, maxLabelWidth),
|
|
1684
|
+
value: `${ACTION.OPEN_PREFIX}${session.id}`
|
|
1685
|
+
})), {
|
|
1686
|
+
label: "Back",
|
|
1687
|
+
value: ACTION.BACK
|
|
1688
|
+
}] : view === "delete" ? [...sessions.filter(({ id }) => id !== currentSessionId).map((session) => ({
|
|
1689
|
+
label: formatSessionLabel(session, maxLabelWidth, "Delete "),
|
|
1675
1690
|
value: `${ACTION.DELETE_PREFIX}${session.id}`
|
|
1676
1691
|
})), {
|
|
1677
1692
|
label: "Back",
|
|
1678
1693
|
value: ACTION.BACK
|
|
1679
1694
|
}] : [
|
|
1680
1695
|
{
|
|
1681
|
-
label: "
|
|
1696
|
+
label: "New session",
|
|
1682
1697
|
value: ACTION.NEW
|
|
1683
1698
|
},
|
|
1684
|
-
...sessions.map((session) => ({
|
|
1685
|
-
label: `${session.id === currentSessionId ? "Current: " : ""}${formatSessionLabel(session)}`,
|
|
1686
|
-
value: `${ACTION.OPEN_PREFIX}${session.id}`
|
|
1687
|
-
})),
|
|
1688
1699
|
{
|
|
1689
|
-
label: "
|
|
1700
|
+
label: "Open session",
|
|
1701
|
+
value: ACTION.OPEN_MENU
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
label: "Delete session",
|
|
1690
1705
|
value: ACTION.DELETE_MENU
|
|
1691
1706
|
},
|
|
1692
1707
|
{
|
|
@@ -1705,6 +1720,9 @@ function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen })
|
|
|
1705
1720
|
case value === ACTION.DELETE_MENU:
|
|
1706
1721
|
setView("delete");
|
|
1707
1722
|
break;
|
|
1723
|
+
case value === ACTION.OPEN_MENU:
|
|
1724
|
+
setView("open");
|
|
1725
|
+
break;
|
|
1708
1726
|
case value === ACTION.BACK:
|
|
1709
1727
|
setView("main");
|
|
1710
1728
|
break;
|
|
@@ -1736,7 +1754,7 @@ function SessionManager({ currentSessionId, onClose, onDelete, onNew, onOpen })
|
|
|
1736
1754
|
flexDirection: "column",
|
|
1737
1755
|
children: [
|
|
1738
1756
|
/* @__PURE__ */ jsx(Text, { children: "Sessions" }),
|
|
1739
|
-
/* @__PURE__ */ jsx(SelectPromptHint, { message: view === "delete" ? "Delete session" : "Select session" }),
|
|
1757
|
+
/* @__PURE__ */ jsx(SelectPromptHint, { message: view === "delete" ? "Delete session" : view === "open" ? "Open session" : "Select session" }),
|
|
1740
1758
|
error && /* @__PURE__ */ jsx(Box, {
|
|
1741
1759
|
marginBottom: 1,
|
|
1742
1760
|
children: /* @__PURE__ */ jsx(Text, {
|
package/dist/cli.js
CHANGED
|
@@ -7,18 +7,6 @@ import { Ollama } from "ollama";
|
|
|
7
7
|
import { v7 } from "uuid";
|
|
8
8
|
import { exec } from "node:child_process";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
|
-
//#region \0rolldown/runtime.js
|
|
11
|
-
var __defProp = Object.defineProperty;
|
|
12
|
-
var __exportAll = (all, no_symbols) => {
|
|
13
|
-
let target = {};
|
|
14
|
-
for (var name in all) __defProp(target, name, {
|
|
15
|
-
get: all[name],
|
|
16
|
-
enumerable: true
|
|
17
|
-
});
|
|
18
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
19
|
-
return target;
|
|
20
|
-
};
|
|
21
|
-
//#endregion
|
|
22
10
|
//#region src/constants/command.ts
|
|
23
11
|
var LIST = [
|
|
24
12
|
{
|
|
@@ -45,7 +33,7 @@ var LIST = [
|
|
|
45
33
|
//#endregion
|
|
46
34
|
//#region package.json
|
|
47
35
|
var name = "code-ollama";
|
|
48
|
-
var version = "0.
|
|
36
|
+
var version = "0.15.0";
|
|
49
37
|
//#endregion
|
|
50
38
|
//#region src/constants/package.ts
|
|
51
39
|
var NAME = name;
|
|
@@ -510,6 +498,33 @@ var WRITE_TOOLS = new Set([
|
|
|
510
498
|
RUN_SHELL
|
|
511
499
|
]);
|
|
512
500
|
//#endregion
|
|
501
|
+
//#region src/utils/tools/shell.ts
|
|
502
|
+
var execAsync = promisify(exec);
|
|
503
|
+
var SHELL_EXEC_OPTIONS = {
|
|
504
|
+
timeout: 3e4,
|
|
505
|
+
maxBuffer: 1024 * 1024
|
|
506
|
+
};
|
|
507
|
+
/**
|
|
508
|
+
* Execute shell command with shared options (throws on error)
|
|
509
|
+
*/
|
|
510
|
+
function execShell(command) {
|
|
511
|
+
return execAsync(command, SHELL_EXEC_OPTIONS);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Execute shell command
|
|
515
|
+
*/
|
|
516
|
+
async function runShell(command) {
|
|
517
|
+
try {
|
|
518
|
+
const { stdout, stderr } = await execShell(command);
|
|
519
|
+
return { content: stdout || stderr };
|
|
520
|
+
} catch (error) {
|
|
521
|
+
return {
|
|
522
|
+
content: "",
|
|
523
|
+
error: `Command failed: ${error instanceof Error ? error.message : String(error)}`
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
//#endregion
|
|
513
528
|
//#region src/utils/tools/filesystem.ts
|
|
514
529
|
/**
|
|
515
530
|
* Read file contents
|
|
@@ -616,7 +631,6 @@ function listDir(dirPath) {
|
|
|
616
631
|
* Search for pattern in files using ripgrep if available, fallback to Node.js
|
|
617
632
|
*/
|
|
618
633
|
async function grepSearch(pattern, dirPath) {
|
|
619
|
-
const { execShell } = await Promise.resolve().then(() => shell_exports);
|
|
620
634
|
try {
|
|
621
635
|
const { stdout } = await execShell(`rg --line-number --no-heading --smart-case "${pattern.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}" "${dirPath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`);
|
|
622
636
|
// v8 ignore next
|
|
@@ -655,37 +669,6 @@ async function grepSearch(pattern, dirPath) {
|
|
|
655
669
|
}
|
|
656
670
|
}
|
|
657
671
|
//#endregion
|
|
658
|
-
//#region src/utils/tools/shell.ts
|
|
659
|
-
var shell_exports = /* @__PURE__ */ __exportAll({
|
|
660
|
-
execShell: () => execShell,
|
|
661
|
-
runShell: () => runShell
|
|
662
|
-
});
|
|
663
|
-
var execAsync = promisify(exec);
|
|
664
|
-
var SHELL_EXEC_OPTIONS = {
|
|
665
|
-
timeout: 3e4,
|
|
666
|
-
maxBuffer: 1024 * 1024
|
|
667
|
-
};
|
|
668
|
-
/**
|
|
669
|
-
* Execute shell command with shared options (throws on error)
|
|
670
|
-
*/
|
|
671
|
-
function execShell(command) {
|
|
672
|
-
return execAsync(command, SHELL_EXEC_OPTIONS);
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Execute shell command
|
|
676
|
-
*/
|
|
677
|
-
async function runShell(command) {
|
|
678
|
-
try {
|
|
679
|
-
const { stdout, stderr } = await execShell(command);
|
|
680
|
-
return { content: stdout || stderr };
|
|
681
|
-
} catch (error) {
|
|
682
|
-
return {
|
|
683
|
-
content: "",
|
|
684
|
-
error: `Command failed: ${error instanceof Error ? error.message : String(error)}`
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
//#endregion
|
|
689
672
|
//#region src/utils/tools/web/fetch.ts
|
|
690
673
|
var FETCH_TIMEOUT_MS = 1e4;
|
|
691
674
|
var BASE_HEADERS = { "user-agent": `${NAME}/${VERSION}` };
|
|
@@ -948,7 +931,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
948
931
|
else await launchTui();
|
|
949
932
|
}
|
|
950
933
|
async function launchTui(sessionId) {
|
|
951
|
-
const { renderApp } = await import("./assets/tui-
|
|
934
|
+
const { renderApp } = await import("./assets/tui-DPx5MGHZ.js");
|
|
952
935
|
reset();
|
|
953
936
|
renderApp(sessionId);
|
|
954
937
|
}
|