code-ollama 0.24.0 → 0.25.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.
@@ -1,4 +1,4 @@
1
- import { $ as NAME, A as loadConfig, B as ASSISTANT, C as checkHealth, D as pullModel, E as listModels, F as withSystemMessage, G as BACK, H as USER, I as HEADER_PREFIX, J as LABEL, K as CATALOG, L as WARNING, M as removeClipboardImage, N as saveClipboardImage, O as sanitizeAssistantContent, P as resetSystemMessage, Q as REJECT, R as LIST$1, S as TOOL_INTENT_CORRECTION, T as hasUncalledToolIntent, U as PLAN_GENERATION_INSTRUCTION, V as SYSTEM, W as PLAN_INSTRUCTION, X as SAFE, Y as PLAN, Z as APPROVE, _ as loadSession, a as normalizeToolCall, b as reset, c as WRITE_TOOLS, d as write, et as VERSION, f as appendMessage, g as listSessions, h as deleteSessionIfEmpty, i as formatToolResultContent, j as saveConfig, k as streamChat, l as tick, m as deleteSession, n as executeTool, o as READ_TOOLS, p as createSession, q as AUTO, r as executeToolCall, s as TOOLS, t as checkForUpdate, tt as LIST, u as color, v as updateSessionModel, w as deleteModel, x as setClearHandler, y as clear, z as getTheme } from "../cli.js";
1
+ import { $ as LABEL, A as loadConfig, B as CHAT, C as checkHealth, D as pullModel, E as listModels, F as withSystemMessage, G as ASSISTANT, H as SEARCH_SETTINGS, I as HEADER_PREFIX, J as PLAN_GENERATION_INSTRUCTION, K as SYSTEM, L as WARNING, M as removeClipboardImage, N as saveClipboardImage, O as sanitizeAssistantContent, P as resetSystemMessage, Q as AUTO, R as LIST$1, S as TOOL_INTENT_CORRECTION, T as hasUncalledToolIntent, U as SESSION_MANAGER, V as MODEL_MANAGER, W as THEME_SETTINGS, X as BACK, Y as PLAN_INSTRUCTION, Z as CATALOG, _ as loadSession, a as normalizeToolCall, at as VERSION, b as reset, c as WRITE_TOOLS, d as write, et as PLAN, f as appendMessage, g as listSessions, h as deleteSessionIfEmpty, i as formatToolResultContent, it as NAME, j as saveConfig, k as streamChat, l as tick, m as deleteSession, n as executeTool, nt as APPROVE, o as READ_TOOLS, ot as LIST, p as createSession, q as USER, r as executeToolCall, rt as REJECT, s as TOOLS, t as checkForUpdate, tt as SAFE, u as color, v as updateSessionModel, w as deleteModel, x as setClearHandler, y as clear, z as getTheme } from "../cli.js";
2
2
  import { existsSync, readdirSync, statSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
4
  import { basename, extname, isAbsolute, join, relative, resolve } from "node:path";
@@ -1411,7 +1411,7 @@ function ChatInput({ history: sessionHistory, isDisabled = false, onInterrupt, o
1411
1411
  }
1412
1412
  //#endregion
1413
1413
  //#region src/components/Chat/constants.ts
1414
- var ACTION_NOT_PERFORMED = "The requested action was NOT performed";
1414
+ var ACTION_NOT_PERFORMED = "The requested action did not complete successfully";
1415
1415
  var PLAN_CHECKLIST_REMINDER = "Then display the plan using either the Plan Needs Input or Proposed Plan Markdown template";
1416
1416
  var PLAN_EXECUTION_REMINDER = `Do not claim success and do not call ${Array.from(WRITE_TOOLS).join(", ")} until the user approves execution`;
1417
1417
  var ChatActionType = /* @__PURE__ */ function(ChatActionType) {
@@ -1445,6 +1445,18 @@ function hasExecutablePlan(content) {
1445
1445
  const nextSectionIndex = lines.findIndex((line, index) => index > executionStepsIndex && /^#{1,6}\s+\S/.test(line.trim()));
1446
1446
  return lines.slice(executionStepsIndex + 1, nextSectionIndex === -1 ? void 0 : nextSectionIndex).some((line) => /^(?:[-*]|\d+[.)])\s+\S/.test(line.trim()));
1447
1447
  }
1448
+ function isPlanModeFinal(content) {
1449
+ const firstHeading = content.split("\n").find((line) => line.trim())?.trim().toLowerCase();
1450
+ return isPlanNeedsInput(content) || firstHeading === "## proposed plan";
1451
+ }
1452
+ function isPlanNeedsInput(content) {
1453
+ return content.split("\n").find((line) => line.trim())?.trim().toLowerCase() === "## plan needs input";
1454
+ }
1455
+ function isDirectPlanAnswer(content) {
1456
+ const normalized = content.trim();
1457
+ if (!normalized || isPlanModeFinal(normalized)) return false;
1458
+ return !/^(?:research(?: is)? complete|done)\.?$/i.test(normalized);
1459
+ }
1448
1460
  //#endregion
1449
1461
  //#region src/components/Chat/reducer.ts
1450
1462
  function createInitialChatState(messages = []) {
@@ -1667,7 +1679,9 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
1667
1679
  toolResultMessages.push(buildToolResultMessage(toolCall.function.name, {
1668
1680
  content: "",
1669
1681
  // v8 ignore next
1670
- error: error instanceof Error ? error.message : String(error)
1682
+ error: error instanceof Error ? error.message : String(error),
1683
+ // v8 ignore next
1684
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
1671
1685
  }));
1672
1686
  }
1673
1687
  nextMessages = [...updatedMessages, ...toolResultMessages];
@@ -1746,7 +1760,7 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
1746
1760
  mode,
1747
1761
  theme
1748
1762
  ]);
1749
- const processStreamReadOnly = useCallback(async (currentMessages) => {
1763
+ const processStreamReadOnly = useCallback(async (currentMessages, toolIntentCorrections = 0) => {
1750
1764
  const modelName = model;
1751
1765
  // v8 ignore next
1752
1766
  if (!modelName) throw new Error("Model is required");
@@ -1843,7 +1857,9 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
1843
1857
  /* v8 ignore start */
1844
1858
  const toolResultMessage = buildToolResultMessage(toolCall.function.name, {
1845
1859
  content: "",
1846
- error: error instanceof Error ? error.message : String(error)
1860
+ error: error instanceof Error ? error.message : String(error),
1861
+ // v8 ignore next
1862
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
1847
1863
  });
1848
1864
  const newMessages = [...updatedMessages, toolResultMessage];
1849
1865
  dispatch({
@@ -1866,6 +1882,13 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
1866
1882
  }
1867
1883
  await prewarmCodeBlocks(assistantMessage.content, theme);
1868
1884
  const researchMessages = commitAssistantMessage();
1885
+ if (isPlanNeedsInput(assistantMessage.content)) {
1886
+ dispatch({
1887
+ type: ChatActionType.SetLoading,
1888
+ isLoading: false
1889
+ });
1890
+ return;
1891
+ }
1869
1892
  if (hasExecutablePlan(assistantMessage.content)) {
1870
1893
  dispatch({
1871
1894
  type: ChatActionType.RequestPlanReview,
@@ -1876,6 +1899,32 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
1876
1899
  });
1877
1900
  return;
1878
1901
  }
1902
+ if (hasUncalledToolIntent(assistantMessage.content) && toolIntentCorrections < MAX_TOOL_INTENT_CORRECTIONS) {
1903
+ const correctedMessages = [...researchMessages, {
1904
+ role: SYSTEM,
1905
+ content: TOOL_INTENT_CORRECTION
1906
+ }];
1907
+ dispatch({
1908
+ type: ChatActionType.CommitMessages,
1909
+ messages: correctedMessages
1910
+ });
1911
+ await processStreamReadOnly(correctedMessages, toolIntentCorrections + 1);
1912
+ return;
1913
+ }
1914
+ if (isPlanModeFinal(assistantMessage.content)) {
1915
+ dispatch({
1916
+ type: ChatActionType.SetLoading,
1917
+ isLoading: false
1918
+ });
1919
+ return;
1920
+ }
1921
+ if (currentMessages.some((message) => !!message.toolResult) && isDirectPlanAnswer(assistantMessage.content)) {
1922
+ dispatch({
1923
+ type: ChatActionType.SetLoading,
1924
+ isLoading: false
1925
+ });
1926
+ return;
1927
+ }
1879
1928
  const planInstruction = {
1880
1929
  role: SYSTEM,
1881
1930
  content: PLAN_GENERATION_INSTRUCTION
@@ -2003,6 +2052,13 @@ function Chat({ initialMessages, model, onCommand, onMessagesChange, mode, onMod
2003
2052
  });
2004
2053
  switch (decision) {
2005
2054
  case APPROVE: {
2055
+ dispatch({
2056
+ type: ChatActionType.SetStreamingMessage,
2057
+ message: {
2058
+ role: ASSISTANT,
2059
+ content: ""
2060
+ }
2061
+ });
2006
2062
  const result = await executeToolCall(toolCall);
2007
2063
  const toolResultMessage = buildToolResultMessage(toolCall.function.name, result, toolCall.function.arguments);
2008
2064
  const newMessages = [...approvedMessages, toolResultMessage];
@@ -3199,46 +3255,36 @@ function UpdateBanner({ onLoad, theme }) {
3199
3255
  });
3200
3256
  }
3201
3257
  //#endregion
3202
- //#region src/components/App/constants.ts
3203
- var Screen = /* @__PURE__ */ function(Screen) {
3204
- Screen["Chat"] = "chat";
3205
- Screen["ModelManager"] = "model-manager";
3206
- Screen["SearchSettings"] = "search-settings";
3207
- Screen["SessionManager"] = "session-manager";
3208
- Screen["ThemeSettings"] = "theme-settings";
3209
- return Screen;
3210
- }({});
3211
- //#endregion
3212
3258
  //#region src/components/App/hooks/useScreenRouter.ts
3213
- function useScreenRouter() {
3259
+ function useScreenRouter({ initialScreen } = {}) {
3214
3260
  const { exit } = useApp();
3215
- const [currentScreen, setScreen] = useState(Screen.Chat);
3261
+ const [currentScreen, setScreen] = useState(initialScreen ?? "chat");
3216
3262
  return {
3217
3263
  currentScreen,
3218
3264
  setScreen,
3219
3265
  handleClose: useCallback(() => {
3220
- setScreen(Screen.Chat);
3266
+ setScreen(CHAT);
3221
3267
  }, []),
3222
3268
  handleCommand: useCallback((command, callbacks) => {
3223
3269
  const { onCreateSession, onSetPreviewThemeId, model, theme } = callbacks;
3224
3270
  switch (command) {
3225
3271
  case "/session":
3226
- setScreen(Screen.SessionManager);
3272
+ setScreen(SESSION_MANAGER);
3227
3273
  break;
3228
3274
  case "/model":
3229
- setScreen(Screen.ModelManager);
3275
+ setScreen(MODEL_MANAGER);
3230
3276
  break;
3231
3277
  case "/search":
3232
- setScreen(Screen.SearchSettings);
3278
+ setScreen(SEARCH_SETTINGS);
3233
3279
  break;
3234
3280
  case "/theme":
3235
3281
  onSetPreviewThemeId(theme);
3236
- setScreen(Screen.ThemeSettings);
3282
+ setScreen(THEME_SETTINGS);
3237
3283
  break;
3238
3284
  case "/clear": {
3239
3285
  resetSystemMessage();
3240
3286
  const nextSession = onCreateSession(model);
3241
- setScreen(Screen.Chat);
3287
+ setScreen(CHAT);
3242
3288
  clear(nextSession.metadata.id);
3243
3289
  break;
3244
3290
  }
@@ -3325,7 +3371,7 @@ function useThemeSettings({ currentTheme, onUpdateConfig, setScreen }) {
3325
3371
  activeTheme,
3326
3372
  handleThemeClose: useCallback(() => {
3327
3373
  setPreviewThemeId(null);
3328
- setScreen(Screen.Chat);
3374
+ setScreen(CHAT);
3329
3375
  }, [setScreen]),
3330
3376
  handleThemePreview,
3331
3377
  handleThemeSave: useCallback((themeId) => {
@@ -3417,13 +3463,13 @@ function ReadinessCheck({ errorMessage, onCommand, setupState, theme = getTheme(
3417
3463
  }
3418
3464
  //#endregion
3419
3465
  //#region src/components/App/App.tsx
3420
- function App({ sessionId }) {
3466
+ function App({ sessionId, initialScreen }) {
3421
3467
  const [appConfig, setConfig] = useState(() => loadConfig());
3422
3468
  const [mode, setMode] = useState(SAFE);
3423
3469
  const [isLoaded, setIsLoaded] = useState(false);
3424
3470
  const [setupState, setSetupState] = useState(() => appConfig.model ? ReadinessState.Ready : ReadinessState.MissingModelConfig);
3425
3471
  const [setupErrorMessage, setSetupErrorMessage] = useState(null);
3426
- const { currentScreen, setScreen, handleClose, handleCommand } = useScreenRouter();
3472
+ const { currentScreen, setScreen, handleClose, handleCommand } = useScreenRouter({ initialScreen });
3427
3473
  const { activeSession, setSession, handleCreateSession, handleOpenSession, handleDeleteSession, handleMessagesChange } = useSessionManager({
3428
3474
  sessionId,
3429
3475
  model: appConfig.model ?? "",
@@ -3440,7 +3486,7 @@ function App({ sessionId }) {
3440
3486
  }
3441
3487
  return;
3442
3488
  }
3443
- if (currentScreen !== Screen.Chat) return;
3489
+ if (currentScreen !== "chat") return;
3444
3490
  // v8 ignore next
3445
3491
  if (isMounted) {
3446
3492
  setSetupErrorMessage(null);
@@ -3477,7 +3523,7 @@ function App({ sessionId }) {
3477
3523
  ...current,
3478
3524
  metadata: updateSessionModel(current.metadata.id, newModel)
3479
3525
  }));
3480
- setScreen(Screen.Chat);
3526
+ setScreen(CHAT);
3481
3527
  }, [setScreen, setSession]);
3482
3528
  const { activeTheme, handleThemeClose, handleThemePreview, handleThemeSave, setPreviewThemeId } = useThemeSettings({
3483
3529
  currentTheme: appConfig.theme,
@@ -3500,7 +3546,7 @@ function App({ sessionId }) {
3500
3546
  ]);
3501
3547
  let screenContent;
3502
3548
  switch (currentScreen) {
3503
- case Screen.ModelManager:
3549
+ case MODEL_MANAGER:
3504
3550
  screenContent = /* @__PURE__ */ jsx(ModelManager, {
3505
3551
  currentModel: appConfig.model ?? "",
3506
3552
  onSelect: handleUpdateConfig,
@@ -3508,7 +3554,7 @@ function App({ sessionId }) {
3508
3554
  theme: activeTheme
3509
3555
  });
3510
3556
  break;
3511
- case Screen.SearchSettings:
3557
+ case SEARCH_SETTINGS:
3512
3558
  screenContent = /* @__PURE__ */ jsx(SearchSettings, {
3513
3559
  currentUrl: appConfig.searxngBaseUrl,
3514
3560
  onSave: handleUpdateConfig,
@@ -3516,26 +3562,26 @@ function App({ sessionId }) {
3516
3562
  theme: activeTheme
3517
3563
  });
3518
3564
  break;
3519
- case Screen.SessionManager:
3565
+ case SESSION_MANAGER:
3520
3566
  screenContent = /* @__PURE__ */ jsx(SessionManager, {
3521
3567
  currentSessionId: activeSession.metadata.id,
3522
3568
  onClose: handleClose,
3523
3569
  onDelete: (sessionId) => {
3524
3570
  handleDeleteSession(sessionId);
3525
- setScreen(Screen.SessionManager);
3571
+ setScreen(SESSION_MANAGER);
3526
3572
  },
3527
3573
  onNew: () => {
3528
3574
  handleCreateSession();
3529
- setScreen(Screen.Chat);
3575
+ setScreen(CHAT);
3530
3576
  },
3531
3577
  onOpen: (sessionId) => {
3532
3578
  handleOpenSession(sessionId);
3533
- setScreen(Screen.Chat);
3579
+ setScreen(CHAT);
3534
3580
  },
3535
3581
  theme: activeTheme
3536
3582
  });
3537
3583
  break;
3538
- case Screen.ThemeSettings:
3584
+ case THEME_SETTINGS:
3539
3585
  screenContent = /* @__PURE__ */ jsx(ThemeSettings, {
3540
3586
  currentTheme: appConfig.theme,
3541
3587
  onClose: handleThemeClose,
@@ -3543,7 +3589,7 @@ function App({ sessionId }) {
3543
3589
  onSave: handleThemeSave
3544
3590
  });
3545
3591
  break;
3546
- case Screen.Chat:
3592
+ case CHAT:
3547
3593
  screenContent = setupState === ReadinessState.Ready ? /* @__PURE__ */ jsx(Chat, {
3548
3594
  initialMessages: activeSession.messages,
3549
3595
  model: appConfig.model,
@@ -3631,15 +3677,18 @@ function ExitHint({ action = "go back" }) {
3631
3677
  }
3632
3678
  //#endregion
3633
3679
  //#region src/tui.tsx
3634
- function renderApp(sessionId) {
3680
+ function renderApp(options = {}) {
3635
3681
  let resetKey = 0;
3636
- const app = render(/* @__PURE__ */ jsx(App, { sessionId }, resetKey), {
3682
+ const app = render(/* @__PURE__ */ jsx(App, {
3683
+ sessionId: options.sessionId,
3684
+ initialScreen: options.initialScreen
3685
+ }, resetKey), {
3637
3686
  exitOnCtrlC: false,
3638
3687
  maxFps: 60
3639
3688
  });
3640
3689
  setClearHandler((nextSessionId) => {
3641
3690
  reset();
3642
- app.rerender(/* @__PURE__ */ jsx(App, { sessionId: nextSessionId ?? sessionId }, ++resetKey));
3691
+ app.rerender(/* @__PURE__ */ jsx(App, { sessionId: nextSessionId ?? options.sessionId }, ++resetKey));
3643
3692
  });
3644
3693
  }
3645
3694
  //#endregion
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var LIST$1 = [
50
50
  //#endregion
51
51
  //#region package.json
52
52
  var name = "code-ollama";
53
- var version = "0.24.0";
53
+ var version = "0.25.0";
54
54
  //#endregion
55
55
  //#region src/constants/package.ts
56
56
  var NAME = name;
@@ -230,10 +230,18 @@ Use the exact headings shown below
230
230
  ${PLAN_RESPONSE_TEMPLATE}`;
231
231
  var PLAN_INSTRUCTION = `Plan mode is active
232
232
 
233
+ Explore first:
234
+ - If the user provides an exact file path, inspect it with read_file before planning changes
235
+ - If the user asks "where", names an identifier/symbol, or asks where behavior is implemented, search the codebase with grep_search before answering
236
+ - If the user asks about project structure without a target identifier or path, use list_dir or find_files to locate likely files
237
+ - Prefer targeted grep_search for exact names over broad directory listing when the user provides an identifier
238
+ - After each read-only tool result, decide whether another read-only tool would materially improve the answer
239
+ - Do not produce Plan Needs Input while also saying you will use another read-only tool; call that tool instead
240
+
233
241
  Only use read-only tools: ${PLAN_READ_TOOLS}
234
242
  Do not call ${PLAN_WRITE_TOOLS} during Plan mode
235
243
  Use read-only tools to resolve discoverable facts before asking questions
236
- If the user asks to search, inspect, find, read, or locate something, use read-only tools immediately
244
+ If the user asks to search, inspect, find, read, locate, change, adjust, update, edit, configure, or identify something, use read-only tools immediately
237
245
  Only ask questions for user preferences or product decisions that cannot be discovered from available tools
238
246
  When enough context is available, stop calling tools and produce either Plan Needs Input or Proposed Plan using the required template
239
247
 
@@ -244,6 +252,13 @@ var USER = "user";
244
252
  var ASSISTANT = "assistant";
245
253
  var SYSTEM = "system";
246
254
  //#endregion
255
+ //#region src/constants/screen.ts
256
+ var CHAT = "chat";
257
+ var MODEL_MANAGER = "model-manager";
258
+ var SEARCH_SETTINGS = "search-settings";
259
+ var SESSION_MANAGER = "session-manager";
260
+ var THEME_SETTINGS = "theme-settings";
261
+ //#endregion
247
262
  //#region src/constants/theme.ts
248
263
  var DEFAULT_THEME_ID = "github-dark";
249
264
  var LIST = [
@@ -956,6 +971,11 @@ var SHELL_EXEC_OPTIONS = {
956
971
  timeout: 3e4,
957
972
  maxBuffer: 1024 * 1024
958
973
  };
974
+ function getErrorOutput(error) {
975
+ if (typeof error !== "object" || error === null) return "";
976
+ const output = error;
977
+ return [output.stdout, output.stderr].filter((value) => typeof value === "string" && !!value).join("\n");
978
+ }
959
979
  /**
960
980
  * Execute shell command with shared options (throws on error)
961
981
  */
@@ -970,9 +990,12 @@ async function runShell(command) {
970
990
  const { stdout, stderr } = await execShell(command);
971
991
  return { content: stdout || stderr };
972
992
  } catch (error) {
993
+ const message = error instanceof Error ? error.message : String(error);
973
994
  return {
974
- content: "",
975
- error: `Command failed: ${error instanceof Error ? error.message : String(error)}`
995
+ content: getErrorOutput(error),
996
+ error: `Command failed: ${message}`,
997
+ // v8 ignore next
998
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
976
999
  };
977
1000
  }
978
1001
  }
@@ -1617,14 +1640,16 @@ function normalizeToolCall(toolCall) {
1617
1640
  }
1618
1641
  function formatToolResultContent(toolName, result, args) {
1619
1642
  const formattedArgs = args ? `(${formatToolArguments(args)})` : "";
1620
- const status = result.error ? "The requested action was NOT performed" : "";
1643
+ const status = result.error ? "The requested action did not complete successfully" : "";
1621
1644
  const content = result.content ? `\n${result.content}` : "";
1622
1645
  const error = result.error ? `\nError: ${result.error}` : "";
1646
+ const stack = result.error && result.stack ? `\nStack trace:\n${result.stack}` : "";
1623
1647
  return [
1624
1648
  `Tool ${toolName}${formattedArgs} result:`,
1625
1649
  status,
1626
1650
  content.trim(),
1627
- error.trim()
1651
+ error.trim(),
1652
+ stack.trim()
1628
1653
  ].filter(Boolean).join("\n");
1629
1654
  }
1630
1655
  function formatToolArguments(args) {
@@ -1642,7 +1667,9 @@ async function executeToolCall(toolCall, options) {
1642
1667
  return {
1643
1668
  content: "",
1644
1669
  // v8 ignore next
1645
- error: error instanceof Error ? error.message : String(error)
1670
+ error: error instanceof Error ? error.message : String(error),
1671
+ // v8 ignore next
1672
+ ...error instanceof Error && error.stack ? { stack: error.stack } : {}
1646
1673
  };
1647
1674
  }
1648
1675
  }
@@ -1736,15 +1763,19 @@ cli.command("run <model> <prompt>", "Run a one-off prompt").action(async (model,
1736
1763
  process.exitCode = 1;
1737
1764
  }
1738
1765
  });
1739
- cli.command("resume <sessionId>", "Resume a saved session").action(async (sessionId) => {
1766
+ cli.command("resume [sessionId]", "Resume a saved session").action(async (sessionId) => {
1740
1767
  try {
1768
+ if (!sessionId) {
1769
+ await launchTui({ initialScreen: SESSION_MANAGER });
1770
+ return;
1771
+ }
1741
1772
  const loaded = loadSession(sessionId);
1742
1773
  if (loaded.metadata.directory && loaded.metadata.directory !== process.cwd()) {
1743
1774
  writeError(color(`${WARNING} Cannot resume: session belongs to ${loaded.metadata.directory}\n`, "yellow"));
1744
1775
  process.exitCode = 1;
1745
1776
  return;
1746
1777
  }
1747
- await launchTui(sessionId);
1778
+ await launchTui({ sessionId });
1748
1779
  } catch (error) {
1749
1780
  writeError(`Error: ${error instanceof Error ? error.message : "Unknown error"}\n`);
1750
1781
  process.exitCode = 1;
@@ -1819,10 +1850,10 @@ async function main(args = process.argv.slice(2)) {
1819
1850
  ]);
1820
1851
  else await launchTui();
1821
1852
  }
1822
- async function launchTui(sessionId) {
1823
- const { renderApp } = await import("./assets/tui-DEmaVgHT.js");
1853
+ async function launchTui(options = {}) {
1854
+ const { renderApp } = await import("./assets/tui-c76QePyQ.js");
1824
1855
  reset();
1825
- renderApp(sessionId);
1856
+ renderApp(options);
1826
1857
  }
1827
1858
  // v8 ignore start
1828
1859
  function isEntrypoint(argv1 = process.argv[1]) {
@@ -1836,4 +1867,4 @@ function isEntrypoint(argv1 = process.argv[1]) {
1836
1867
  if (isEntrypoint()) main();
1837
1868
  // v8 ignore stop
1838
1869
  //#endregion
1839
- export { NAME as $, loadConfig as A, ASSISTANT as B, checkHealth as C, pullModel as D, listModels as E, withSystemMessage as F, BACK as G, USER as H, HEADER_PREFIX as I, LABEL as J, CATALOG as K, WARNING as L, removeClipboardImage as M, saveClipboardImage as N, sanitizeAssistantContent as O, resetSystemMessage as P, REJECT as Q, LIST as R, TOOL_INTENT_CORRECTION as S, hasUncalledToolIntent as T, PLAN_GENERATION_INSTRUCTION as U, SYSTEM as V, PLAN_INSTRUCTION as W, SAFE as X, PLAN as Y, APPROVE as Z, loadSession as _, normalizeToolCall as a, reset as b, WRITE_TOOLS as c, write as d, VERSION as et, appendMessage as f, listSessions as g, deleteSessionIfEmpty as h, formatToolResultContent as i, saveConfig as j, streamChat as k, tick as l, deleteSession as m, main, executeTool as n, READ_TOOLS as o, createSession as p, AUTO as q, executeToolCall as r, TOOLS as s, checkForUpdate as t, LIST$1 as tt, color as u, updateSessionModel as v, deleteModel as w, setClearHandler as x, clear as y, getTheme as z };
1870
+ export { LABEL as $, loadConfig as A, CHAT as B, checkHealth as C, pullModel as D, listModels as E, withSystemMessage as F, ASSISTANT as G, SEARCH_SETTINGS as H, HEADER_PREFIX as I, PLAN_GENERATION_INSTRUCTION as J, SYSTEM as K, WARNING as L, removeClipboardImage as M, saveClipboardImage as N, sanitizeAssistantContent as O, resetSystemMessage as P, AUTO as Q, LIST as R, TOOL_INTENT_CORRECTION as S, hasUncalledToolIntent as T, SESSION_MANAGER as U, MODEL_MANAGER as V, THEME_SETTINGS as W, BACK as X, PLAN_INSTRUCTION as Y, CATALOG as Z, loadSession as _, normalizeToolCall as a, VERSION as at, reset as b, WRITE_TOOLS as c, write as d, PLAN as et, appendMessage as f, listSessions as g, deleteSessionIfEmpty as h, formatToolResultContent as i, NAME as it, saveConfig as j, streamChat as k, tick as l, deleteSession as m, main, executeTool as n, APPROVE as nt, READ_TOOLS as o, LIST$1 as ot, createSession as p, USER as q, executeToolCall as r, REJECT as rt, TOOLS as s, checkForUpdate as t, SAFE as tt, color as u, updateSessionModel as v, deleteModel as w, setClearHandler as x, clear as y, getTheme as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-ollama",
3
- "version": "0.24.0",
3
+ "version": "0.25.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",
@@ -20,7 +20,7 @@
20
20
  "prepublishOnly": "npm run build && npm run lint && npm run lint:tsc && npm run test:ci",
21
21
  "test": "vitest run",
22
22
  "test:ci": "CI=true npm test -- --color --coverage",
23
- "test:watch": "vitest --coverage.enabled=false"
23
+ "test:watch": "vitest"
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",