code-ollama 0.6.0 → 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.
|
@@ -4,17 +4,24 @@ import { join, relative } from "node:path";
|
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { exec } from "node:child_process";
|
|
6
6
|
import { Box, Text, render, useApp, useInput } from "ink";
|
|
7
|
-
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
7
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
8
|
import { Select, Spinner, TextInput } from "@inkjs/ui";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/constants/command.ts
|
|
11
|
-
var LIST = [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
var LIST = [
|
|
12
|
+
{
|
|
13
|
+
name: "/clear",
|
|
14
|
+
description: "clear the current session"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "/model",
|
|
18
|
+
description: "switch the model"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "/exit",
|
|
22
|
+
description: "exit the application"
|
|
23
|
+
}
|
|
24
|
+
];
|
|
18
25
|
//#endregion
|
|
19
26
|
//#region src/constants/decision.ts
|
|
20
27
|
var APPROVE = "approve";
|
|
@@ -298,7 +305,7 @@ async function listProjectFiles(rootDir) {
|
|
|
298
305
|
return listProjectFilesFallback(rootDir);
|
|
299
306
|
}
|
|
300
307
|
}
|
|
301
|
-
function FileSuggestions({ input, isDisabled = false, onSelect }) {
|
|
308
|
+
function FileSuggestions({ input, isDisabled = false, onChange, onSelect }) {
|
|
302
309
|
const [filePaths, setFilePaths] = useState([]);
|
|
303
310
|
const [focusedIndex, setFocusedIndex] = useState(0);
|
|
304
311
|
useEffect(() => {
|
|
@@ -323,6 +330,20 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
|
|
|
323
330
|
}
|
|
324
331
|
setFocusedIndex((currentIndex) => Math.min(currentIndex, options.length - 1));
|
|
325
332
|
}, [options]);
|
|
333
|
+
useEffect(() => {
|
|
334
|
+
if (!onChange) return;
|
|
335
|
+
if (!mentionMatch || !options.length) {
|
|
336
|
+
onChange(null);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
onChange(buildNextInput(input, options[focusedIndex]));
|
|
340
|
+
}, [
|
|
341
|
+
focusedIndex,
|
|
342
|
+
input,
|
|
343
|
+
mentionMatch,
|
|
344
|
+
onChange,
|
|
345
|
+
options
|
|
346
|
+
]);
|
|
326
347
|
useInput((_, key) => {
|
|
327
348
|
if (isDisabled || !options.length) return;
|
|
328
349
|
if (key.downArrow) {
|
|
@@ -333,7 +354,7 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
|
|
|
333
354
|
setFocusedIndex((currentIndex) => Math.max(currentIndex - 1, 0));
|
|
334
355
|
return;
|
|
335
356
|
}
|
|
336
|
-
if (key.tab) onSelect(buildNextInput(input, options[focusedIndex]));
|
|
357
|
+
if (key.tab || key.return) onSelect(buildNextInput(input, options[focusedIndex]));
|
|
337
358
|
});
|
|
338
359
|
if (!mentionMatch || !options.length) return null;
|
|
339
360
|
const visibleStart = Math.min(Math.max(0, focusedIndex - MAX_VISIBLE_OPTIONS + 1), Math.max(0, options.length - MAX_VISIBLE_OPTIONS));
|
|
@@ -352,43 +373,52 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
|
|
|
352
373
|
}
|
|
353
374
|
//#endregion
|
|
354
375
|
//#region src/components/Chat/Input.tsx
|
|
355
|
-
function
|
|
376
|
+
function hasFileSuggestionQuery(input) {
|
|
356
377
|
return /(^|\s)@\S+$/.test(input);
|
|
357
378
|
}
|
|
358
379
|
function Input({ isDisabled = false, onSubmit }) {
|
|
359
380
|
const { exit } = useApp();
|
|
360
381
|
const [input, setInput] = useState("");
|
|
361
382
|
const [inputKey, setInputKey] = useState(0);
|
|
383
|
+
const fileSuggestionRef = useRef(null);
|
|
362
384
|
const remountTextInput = useCallback(() => {
|
|
363
385
|
setInputKey((key) => key + 1);
|
|
364
386
|
}, [setInputKey]);
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
387
|
+
const handleSelectFileSuggestion = useCallback((nextInput) => {
|
|
388
|
+
setInput(nextInput);
|
|
389
|
+
remountTextInput();
|
|
390
|
+
}, [remountTextInput]);
|
|
391
|
+
const handleFileSuggestionChange = useCallback((nextInput) => {
|
|
392
|
+
fileSuggestionRef.current = nextInput;
|
|
393
|
+
}, []);
|
|
394
|
+
const submitAndReset = useCallback((input) => {
|
|
368
395
|
const trimmedInput = input.trim();
|
|
369
396
|
if (!trimmedInput) return;
|
|
370
397
|
onSubmit(trimmedInput);
|
|
371
398
|
setInput("");
|
|
399
|
+
fileSuggestionRef.current = null;
|
|
372
400
|
remountTextInput();
|
|
373
401
|
}, [onSubmit, remountTextInput]);
|
|
402
|
+
const showCommandMenu = input.startsWith("/");
|
|
403
|
+
const showFileSuggestions = !showCommandMenu && hasFileSuggestionQuery(input);
|
|
404
|
+
const handleSubmitText = useCallback(async (input) => {
|
|
405
|
+
await tick();
|
|
406
|
+
if (input.startsWith("/")) return;
|
|
407
|
+
if (hasFileSuggestionQuery(input)) {
|
|
408
|
+
if (fileSuggestionRef.current) handleSelectFileSuggestion(fileSuggestionRef.current);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
submitAndReset(input);
|
|
412
|
+
}, [handleSelectFileSuggestion, submitAndReset]);
|
|
374
413
|
const handleSubmitCommand = useCallback((input) => {
|
|
375
|
-
if (
|
|
376
|
-
|
|
377
|
-
setInput("");
|
|
378
|
-
remountTextInput();
|
|
379
|
-
}, [onSubmit, remountTextInput]);
|
|
380
|
-
const handleSelectFileSuggestion = useCallback((nextInput) => {
|
|
381
|
-
setInput(nextInput);
|
|
382
|
-
remountTextInput();
|
|
383
|
-
}, [remountTextInput]);
|
|
414
|
+
if (LIST.find(({ name }) => name === input)) submitAndReset(input);
|
|
415
|
+
}, [submitAndReset]);
|
|
384
416
|
useInput((_input, key) => {
|
|
385
417
|
if (key.ctrl && _input === "c") if (input) {
|
|
386
418
|
setInput("");
|
|
387
419
|
remountTextInput();
|
|
388
420
|
} else exit();
|
|
389
421
|
});
|
|
390
|
-
const showCommandMenu = input.startsWith("/");
|
|
391
|
-
const showFileSuggestions = !showCommandMenu && hasActiveMentionQuery(input);
|
|
392
422
|
return /* @__PURE__ */ jsxs(Box, {
|
|
393
423
|
flexDirection: "column",
|
|
394
424
|
children: [
|
|
@@ -406,6 +436,7 @@ function Input({ isDisabled = false, onSubmit }) {
|
|
|
406
436
|
showFileSuggestions && /* @__PURE__ */ jsx(FileSuggestions, {
|
|
407
437
|
input,
|
|
408
438
|
isDisabled,
|
|
439
|
+
onChange: handleFileSuggestionChange,
|
|
409
440
|
onSelect: handleSelectFileSuggestion
|
|
410
441
|
})
|
|
411
442
|
]
|
|
@@ -843,6 +874,7 @@ function ModelPicker({ currentModel, onSelect, onClose }) {
|
|
|
843
874
|
//#endregion
|
|
844
875
|
//#region src/components/App.tsx
|
|
845
876
|
function App() {
|
|
877
|
+
const { exit } = useApp();
|
|
846
878
|
const [model, setModel] = useState(() => loadConfig().model);
|
|
847
879
|
const [picking, setPicking] = useState(false);
|
|
848
880
|
const [mode, setMode] = useState(NAME.SAFE);
|
|
@@ -857,8 +889,11 @@ function App() {
|
|
|
857
889
|
setPicking(false);
|
|
858
890
|
setSessionId((sessionId) => sessionId + 1);
|
|
859
891
|
break;
|
|
892
|
+
case "/exit":
|
|
893
|
+
exit();
|
|
894
|
+
break;
|
|
860
895
|
}
|
|
861
|
-
}, []);
|
|
896
|
+
}, [exit]);
|
|
862
897
|
const handleSelect = useCallback((selected) => {
|
|
863
898
|
setModel(selected);
|
|
864
899
|
saveConfig({ model: selected });
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { exec } from "node:child_process";
|
|
|
8
8
|
import { promisify } from "node:util";
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/constants/package.ts
|
|
11
|
-
var VERSION = "0.
|
|
11
|
+
var VERSION = "0.7.0";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/constants/prompt.ts
|
|
14
14
|
var BASE_SYSTEM_PROMPT = `You are a coding assistant that helps users write, edit, and understand code. You have access to tools for reading files, writing files, running shell commands, and searching code
|
|
@@ -502,7 +502,7 @@ async function processRunStream(messages, model) {
|
|
|
502
502
|
}
|
|
503
503
|
async function main(args = process.argv.slice(2)) {
|
|
504
504
|
if (!args.length) {
|
|
505
|
-
const { renderApp } = await import("./assets/tui-
|
|
505
|
+
const { renderApp } = await import("./assets/tui-CDaKDOEJ.js");
|
|
506
506
|
process.stdout.write("\x1Bc");
|
|
507
507
|
renderApp();
|
|
508
508
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-ollama",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"react": "19.2.6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@commitlint/cli": "
|
|
50
|
-
"@commitlint/config-conventional": "
|
|
51
|
-
"@eslint/
|
|
49
|
+
"@commitlint/cli": "21.0.0",
|
|
50
|
+
"@commitlint/config-conventional": "21.0.0",
|
|
51
|
+
"@eslint/config-helpers": "0.6.0",
|
|
52
52
|
"@eslint/js": "10.0.1",
|
|
53
53
|
"@types/node": "25.6.2",
|
|
54
54
|
"@types/react": "19.2.14",
|
|
@@ -59,9 +59,9 @@
|
|
|
59
59
|
"globals": "17.6.0",
|
|
60
60
|
"husky": "9.1.7",
|
|
61
61
|
"ink-testing-library": "4.0.0",
|
|
62
|
-
"lint-staged": "17.0.
|
|
62
|
+
"lint-staged": "17.0.3",
|
|
63
63
|
"prettier": "3.8.3",
|
|
64
|
-
"publint": "0.3.
|
|
64
|
+
"publint": "0.3.20",
|
|
65
65
|
"tsx": "4.21.0",
|
|
66
66
|
"typescript": "6.0.3",
|
|
67
67
|
"typescript-eslint": "8.59.2",
|