code-ollama 0.15.0 → 0.15.1
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.
|
@@ -169,7 +169,7 @@ var inlineMathExtension = {
|
|
|
169
169
|
}
|
|
170
170
|
};
|
|
171
171
|
//#endregion
|
|
172
|
-
//#region src/components/Markdown/
|
|
172
|
+
//#region src/components/Markdown/render.ts
|
|
173
173
|
var HR_PLACEHOLDER = "__CODE_OLLAMA_HR_PLACEHOLDER__";
|
|
174
174
|
function renderMarkdown(content, hrWidth) {
|
|
175
175
|
const hr = "─".repeat(Math.max(1, hrWidth));
|
|
@@ -196,10 +196,12 @@ function renderMarkdown(content, hrWidth) {
|
|
|
196
196
|
const result = markdown.parse(content);
|
|
197
197
|
return (typeof result === "string" ? result.trim() : content).replaceAll(HR_PLACEHOLDER, hr);
|
|
198
198
|
} catch {
|
|
199
|
+
// v8 ignore next
|
|
199
200
|
return content;
|
|
200
201
|
}
|
|
201
|
-
// v8 ignore stop
|
|
202
202
|
}
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/components/Markdown/Markdown.tsx
|
|
203
205
|
var Markdown = memo(function Markdown({ content, color, dimColor }) {
|
|
204
206
|
const { stdout } = useStdout();
|
|
205
207
|
const availableWidth = stdout.columns - 4;
|
|
@@ -217,7 +219,72 @@ var TURN_ABORTED_MESSAGE = [
|
|
|
217
219
|
"</turn_aborted>"
|
|
218
220
|
].join("\n");
|
|
219
221
|
//#endregion
|
|
220
|
-
//#region src/components/Messages/
|
|
222
|
+
//#region src/components/Messages/layout.ts
|
|
223
|
+
var ANSI_REGEX = new RegExp(String.raw`\u001B\[[0-9;]*m`, "g");
|
|
224
|
+
var CODE_BLOCK_MARGIN_Y = 2;
|
|
225
|
+
var CODE_BLOCK_BORDER_Y = 2;
|
|
226
|
+
var CODE_BLOCK_CHROME_X = 4;
|
|
227
|
+
function stripAnsi(value) {
|
|
228
|
+
return value.replaceAll(ANSI_REGEX, "");
|
|
229
|
+
}
|
|
230
|
+
function countLineWidth(value) {
|
|
231
|
+
return Array.from(stripAnsi(value)).length;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Counts the number of wrapped lines for a given content and width.
|
|
235
|
+
*
|
|
236
|
+
* This function splits the content by newlines and calculates how many lines
|
|
237
|
+
* each segment would wrap to based on the available width.
|
|
238
|
+
*
|
|
239
|
+
* @param content The text content to wrap.
|
|
240
|
+
* @param width The available width for wrapping.
|
|
241
|
+
* @returns The number of wrapped lines.
|
|
242
|
+
*/
|
|
243
|
+
function countWrappedLines(content, width) {
|
|
244
|
+
const safeWidth = Math.max(1, width);
|
|
245
|
+
return content.split("\n").reduce((lineCount, line) => {
|
|
246
|
+
const visibleWidth = countLineWidth(line);
|
|
247
|
+
return lineCount + Math.max(1, Math.ceil(visibleWidth / safeWidth));
|
|
248
|
+
}, 0);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Calculates the height of a code block based on its content and width.
|
|
252
|
+
*
|
|
253
|
+
* This function accounts for margins, borders, and wrapped lines to determine
|
|
254
|
+
* the total height required for displaying a code block.
|
|
255
|
+
*
|
|
256
|
+
* @param content The code block content to render.
|
|
257
|
+
* @param width The available width for the code block.
|
|
258
|
+
* @returns The total height in lines.
|
|
259
|
+
*/
|
|
260
|
+
function getCodeBlockHeight(content, width) {
|
|
261
|
+
const contentWidth = Math.max(1, width - CODE_BLOCK_CHROME_X);
|
|
262
|
+
return CODE_BLOCK_MARGIN_Y + CODE_BLOCK_BORDER_Y + countWrappedLines(content, contentWidth);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Calculates the total height of streaming text content based on wrapped lines.
|
|
266
|
+
*
|
|
267
|
+
* @param textParts Array of text parts with their content and type.
|
|
268
|
+
* @param width The available width for wrapping text.
|
|
269
|
+
* @returns The total height in lines.
|
|
270
|
+
*/
|
|
271
|
+
function getStreamingTextHeight(textParts, width) {
|
|
272
|
+
return textParts.reduce((height, part) => {
|
|
273
|
+
const renderMarkdown$1 = renderMarkdown;
|
|
274
|
+
return height + countWrappedLines(part.type === "markdown" ? renderMarkdown$1(part.content, width) : part.content, width);
|
|
275
|
+
}, 0);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Calculates the available width for assistant content after accounting for margins.
|
|
279
|
+
*
|
|
280
|
+
* @param columns The total number of columns in the terminal.
|
|
281
|
+
* @returns The available width for content (always at least 1).
|
|
282
|
+
*/
|
|
283
|
+
function getAssistantContentWidth(columns) {
|
|
284
|
+
return Math.max(1, columns - 4);
|
|
285
|
+
}
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region src/components/Messages/parsing.ts
|
|
221
288
|
var FENCE_LINE_REGEX = /^(?<indent>[ \t]*)(?<fence>`{3,})(?<language>\w+)?[ \t]*$/;
|
|
222
289
|
function flushTextSegment(segments, textLines) {
|
|
223
290
|
const textContent = textLines.join("\n").trim();
|
|
@@ -303,14 +370,8 @@ function parseContent(content) {
|
|
|
303
370
|
flushTextSegment(segments, textLines);
|
|
304
371
|
return segments;
|
|
305
372
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
case USER: return "black";
|
|
309
|
-
case ASSISTANT: return "cyan";
|
|
310
|
-
case SYSTEM: return "gray";
|
|
311
|
-
default: return;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
373
|
+
//#endregion
|
|
374
|
+
//#region src/components/Messages/streaming.ts
|
|
314
375
|
function isWordCharacter(char) {
|
|
315
376
|
return char !== void 0 && /[A-Za-z0-9]/.test(char);
|
|
316
377
|
}
|
|
@@ -405,11 +466,27 @@ function splitStreamingInlineContent(content) {
|
|
|
405
466
|
return parts;
|
|
406
467
|
}
|
|
407
468
|
//#endregion
|
|
469
|
+
//#region src/components/Messages/styles.ts
|
|
470
|
+
function getMessageColor(role) {
|
|
471
|
+
switch (role) {
|
|
472
|
+
case USER: return "black";
|
|
473
|
+
case ASSISTANT: return "cyan";
|
|
474
|
+
case SYSTEM: return "gray";
|
|
475
|
+
default: return;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
408
479
|
//#region src/components/Messages/Messages.tsx
|
|
409
480
|
function Message({ message, isStreaming = false }) {
|
|
481
|
+
const { stdout } = useStdout();
|
|
410
482
|
const messageColor = getMessageColor(message.role);
|
|
411
483
|
const isSystem = message.role === SYSTEM;
|
|
412
484
|
const isUser = message.role === USER;
|
|
485
|
+
const isStreamingAssistant = isStreaming && !isUser && !isSystem;
|
|
486
|
+
const stickyHeightRef = useRef({
|
|
487
|
+
columns: stdout.columns,
|
|
488
|
+
maxHeight: 0
|
|
489
|
+
});
|
|
413
490
|
if (isSystem) return /* @__PURE__ */ jsx(Box, {
|
|
414
491
|
flexDirection: "column",
|
|
415
492
|
marginBottom: 1,
|
|
@@ -420,10 +497,23 @@ function Message({ message, isStreaming = false }) {
|
|
|
420
497
|
children: message.content
|
|
421
498
|
})
|
|
422
499
|
});
|
|
423
|
-
|
|
500
|
+
const segments = parseContent(message.content);
|
|
501
|
+
const availableWidth = getAssistantContentWidth(stdout.columns);
|
|
502
|
+
if (stickyHeightRef.current.columns !== stdout.columns) stickyHeightRef.current = {
|
|
503
|
+
columns: stdout.columns,
|
|
504
|
+
maxHeight: 0
|
|
505
|
+
};
|
|
506
|
+
const streamingHeight = isStreamingAssistant ? segments.reduce((height, segment) => {
|
|
507
|
+
if (segment.type === "code") return height + getCodeBlockHeight(segment.content, availableWidth);
|
|
508
|
+
if (segment.type === "raw") return height + getCodeBlockHeight(unwrapRawMarkdownFence(segment.content) ?? segment.content, availableWidth);
|
|
509
|
+
return height + getStreamingTextHeight(splitStreamingInlineContent(segment.content), availableWidth);
|
|
510
|
+
}, 0) : 0;
|
|
511
|
+
if (isStreamingAssistant) stickyHeightRef.current.maxHeight = Math.max(stickyHeightRef.current.maxHeight, streamingHeight);
|
|
512
|
+
const stickyPaddingLines = isStreamingAssistant ? stickyHeightRef.current.maxHeight - streamingHeight : 0;
|
|
513
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
424
514
|
flexDirection: "column",
|
|
425
515
|
marginBottom: 1,
|
|
426
|
-
children:
|
|
516
|
+
children: [segments.map((segment, index) => {
|
|
427
517
|
const prefix = isUser && index === 0 ? "> " : "";
|
|
428
518
|
if (segment.type === "code") return isUser ? /* @__PURE__ */ jsx(Text, {
|
|
429
519
|
color: messageColor,
|
|
@@ -465,7 +555,7 @@ function Message({ message, isStreaming = false }) {
|
|
|
465
555
|
color: messageColor
|
|
466
556
|
}, partIndex))
|
|
467
557
|
}, index);
|
|
468
|
-
})
|
|
558
|
+
}), Array.from({ length: stickyPaddingLines }, (_, index) => /* @__PURE__ */ jsx(Text, { children: " " }, "padding-" + String(index)))]
|
|
469
559
|
});
|
|
470
560
|
}
|
|
471
561
|
function Messages({ messages, isLoading, sessionId, streamingMessage }) {
|
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var LIST = [
|
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region package.json
|
|
35
35
|
var name = "code-ollama";
|
|
36
|
-
var version = "0.15.
|
|
36
|
+
var version = "0.15.1";
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/constants/package.ts
|
|
39
39
|
var NAME = name;
|
|
@@ -931,7 +931,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
931
931
|
else await launchTui();
|
|
932
932
|
}
|
|
933
933
|
async function launchTui(sessionId) {
|
|
934
|
-
const { renderApp } = await import("./assets/tui-
|
|
934
|
+
const { renderApp } = await import("./assets/tui-CSRbnCod.js");
|
|
935
935
|
reset();
|
|
936
936
|
renderApp(sessionId);
|
|
937
937
|
}
|