code-ollama 0.6.0 → 0.6.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.
@@ -4,7 +4,7 @@ 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
@@ -298,7 +298,7 @@ async function listProjectFiles(rootDir) {
298
298
  return listProjectFilesFallback(rootDir);
299
299
  }
300
300
  }
301
- function FileSuggestions({ input, isDisabled = false, onSelect }) {
301
+ function FileSuggestions({ input, isDisabled = false, onChange, onSelect }) {
302
302
  const [filePaths, setFilePaths] = useState([]);
303
303
  const [focusedIndex, setFocusedIndex] = useState(0);
304
304
  useEffect(() => {
@@ -323,6 +323,20 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
323
323
  }
324
324
  setFocusedIndex((currentIndex) => Math.min(currentIndex, options.length - 1));
325
325
  }, [options]);
326
+ useEffect(() => {
327
+ if (!onChange) return;
328
+ if (!mentionMatch || !options.length) {
329
+ onChange(null);
330
+ return;
331
+ }
332
+ onChange(buildNextInput(input, options[focusedIndex]));
333
+ }, [
334
+ focusedIndex,
335
+ input,
336
+ mentionMatch,
337
+ onChange,
338
+ options
339
+ ]);
326
340
  useInput((_, key) => {
327
341
  if (isDisabled || !options.length) return;
328
342
  if (key.downArrow) {
@@ -333,7 +347,7 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
333
347
  setFocusedIndex((currentIndex) => Math.max(currentIndex - 1, 0));
334
348
  return;
335
349
  }
336
- if (key.tab) onSelect(buildNextInput(input, options[focusedIndex]));
350
+ if (key.tab || key.return) onSelect(buildNextInput(input, options[focusedIndex]));
337
351
  });
338
352
  if (!mentionMatch || !options.length) return null;
339
353
  const visibleStart = Math.min(Math.max(0, focusedIndex - MAX_VISIBLE_OPTIONS + 1), Math.max(0, options.length - MAX_VISIBLE_OPTIONS));
@@ -352,43 +366,52 @@ function FileSuggestions({ input, isDisabled = false, onSelect }) {
352
366
  }
353
367
  //#endregion
354
368
  //#region src/components/Chat/Input.tsx
355
- function hasActiveMentionQuery(input) {
369
+ function hasFileSuggestionQuery(input) {
356
370
  return /(^|\s)@\S+$/.test(input);
357
371
  }
358
372
  function Input({ isDisabled = false, onSubmit }) {
359
373
  const { exit } = useApp();
360
374
  const [input, setInput] = useState("");
361
375
  const [inputKey, setInputKey] = useState(0);
376
+ const fileSuggestionRef = useRef(null);
362
377
  const remountTextInput = useCallback(() => {
363
378
  setInputKey((key) => key + 1);
364
379
  }, [setInputKey]);
365
- const handleSubmitText = useCallback(async (input) => {
366
- await tick();
367
- if (input.startsWith("/")) return;
380
+ const handleSelectFileSuggestion = useCallback((nextInput) => {
381
+ setInput(nextInput);
382
+ remountTextInput();
383
+ }, [remountTextInput]);
384
+ const handleFileSuggestionChange = useCallback((nextInput) => {
385
+ fileSuggestionRef.current = nextInput;
386
+ }, []);
387
+ const submitAndReset = useCallback((input) => {
368
388
  const trimmedInput = input.trim();
369
389
  if (!trimmedInput) return;
370
390
  onSubmit(trimmedInput);
371
391
  setInput("");
392
+ fileSuggestionRef.current = null;
372
393
  remountTextInput();
373
394
  }, [onSubmit, remountTextInput]);
395
+ const showCommandMenu = input.startsWith("/");
396
+ const showFileSuggestions = !showCommandMenu && hasFileSuggestionQuery(input);
397
+ const handleSubmitText = useCallback(async (input) => {
398
+ await tick();
399
+ if (input.startsWith("/")) return;
400
+ if (hasFileSuggestionQuery(input)) {
401
+ if (fileSuggestionRef.current) handleSelectFileSuggestion(fileSuggestionRef.current);
402
+ return;
403
+ }
404
+ submitAndReset(input);
405
+ }, [handleSelectFileSuggestion, submitAndReset]);
374
406
  const handleSubmitCommand = useCallback((input) => {
375
- if (!LIST.find(({ name }) => name === input)) return;
376
- onSubmit(input);
377
- setInput("");
378
- remountTextInput();
379
- }, [onSubmit, remountTextInput]);
380
- const handleSelectFileSuggestion = useCallback((nextInput) => {
381
- setInput(nextInput);
382
- remountTextInput();
383
- }, [remountTextInput]);
407
+ if (LIST.find(({ name }) => name === input)) submitAndReset(input);
408
+ }, [submitAndReset]);
384
409
  useInput((_input, key) => {
385
410
  if (key.ctrl && _input === "c") if (input) {
386
411
  setInput("");
387
412
  remountTextInput();
388
413
  } else exit();
389
414
  });
390
- const showCommandMenu = input.startsWith("/");
391
- const showFileSuggestions = !showCommandMenu && hasActiveMentionQuery(input);
392
415
  return /* @__PURE__ */ jsxs(Box, {
393
416
  flexDirection: "column",
394
417
  children: [
@@ -406,6 +429,7 @@ function Input({ isDisabled = false, onSubmit }) {
406
429
  showFileSuggestions && /* @__PURE__ */ jsx(FileSuggestions, {
407
430
  input,
408
431
  isDisabled,
432
+ onChange: handleFileSuggestionChange,
409
433
  onSelect: handleSelectFileSuggestion
410
434
  })
411
435
  ]
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.6.0";
11
+ var VERSION = "0.6.1";
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-UfyDivSA.js");
505
+ const { renderApp } = await import("./assets/tui-B1jg-OeC.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.6.0",
3
+ "version": "0.6.1",
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": "20.5.3",
50
- "@commitlint/config-conventional": "20.5.3",
51
- "@eslint/compat": "2.0.5",
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.2",
62
+ "lint-staged": "17.0.3",
63
63
  "prettier": "3.8.3",
64
- "publint": "0.3.19",
64
+ "publint": "0.3.20",
65
65
  "tsx": "4.21.0",
66
66
  "typescript": "6.0.3",
67
67
  "typescript-eslint": "8.59.2",