code-ollama 0.19.1 → 0.21.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 { A as WARNING, B as LABEL, C as loadConfig, D as resetSystemMessage, E as saveClipboardImage, F as USER, G as VERSION, H as SAFE, I as PLAN_GENERATION_INSTRUCTION, K as LIST, L as BACK, M as getTheme, N as ASSISTANT, O as withSystemMessage, P as SYSTEM, R as CATALOG, S as streamChat, T as removeClipboardImage, U as APPROVE, V as PLAN, W as REJECT, _ as setClearHandler, a as tick, b as listModels, c as appendMessage, d as deleteSessionIfEmpty, f as listSessions, g as reset, h as clear, i as WRITE_TOOLS, j as LIST$1, k as HEADER_PREFIX, l as createSession, m as updateSessionModel, n as READ_TOOLS, o as color, p as loadSession, r as TOOLS, s as write, t as executeTool, u as deleteSession, v as checkHealth, w as saveConfig, x as pullModel, y as deleteModel, z as AUTO } from "../cli.js";
1
+ import { A as HEADER_PREFIX, B as AUTO, C as streamChat, D as saveClipboardImage, E as removeClipboardImage, F as SYSTEM, G as REJECT, H as PLAN, I as USER, J as LIST, K as NAME, L as PLAN_GENERATION_INSTRUCTION, M as LIST$1, N as getTheme, O as resetSystemMessage, P as ASSISTANT, R as BACK, S as pullModel, T as saveConfig, U as SAFE, V as LABEL, W as APPROVE, _ as reset, a as WRITE_TOOLS, b as deleteModel, c as write, d as deleteSession, f as deleteSessionIfEmpty, g as clear, h as updateSessionModel, i as TOOLS, j as WARNING, k as withSystemMessage, l as appendMessage, m as loadSession, n as executeTool, o as tick, p as listSessions, q as VERSION, r as READ_TOOLS, s as color, t as checkForUpdate, u as createSession, v as setClearHandler, w as loadConfig, x as listModels, y as checkHealth, z as CATALOG } 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";
@@ -1783,12 +1783,9 @@ function abbreviatePath(dir) {
1783
1783
  const home = homedir();
1784
1784
  return dir.startsWith(home) ? `~${dir.slice(home.length)}` : dir;
1785
1785
  }
1786
- function Header({ model, onLoad, theme = getTheme() }) {
1786
+ function Header({ model, theme = getTheme() }) {
1787
1787
  const directory = abbreviatePath(process.cwd());
1788
1788
  const modelLabel = model || "not configured";
1789
- useEffect(() => {
1790
- onLoad();
1791
- }, []);
1792
1789
  return /* @__PURE__ */ jsx(Static, {
1793
1790
  items: [0],
1794
1791
  children: (key) => /* @__PURE__ */ jsxs(Box, {
@@ -2781,6 +2778,63 @@ function ThemeSettings({ currentTheme, onClose, onPreview, onSave }) {
2781
2778
  });
2782
2779
  }
2783
2780
  //#endregion
2781
+ //#region src/components/UpdateBanner/UpdateBanner.tsx
2782
+ var RELEASES_URL = `https://github.com/ai-action/${NAME}/releases`;
2783
+ function UpdateBanner({ onLoad, theme }) {
2784
+ const [latestVersion, setLatestVersion] = useState();
2785
+ useEffect(() => {
2786
+ checkForUpdate().then(setLatestVersion).finally(async () => {
2787
+ await tick();
2788
+ onLoad();
2789
+ });
2790
+ }, []);
2791
+ if (!latestVersion) return null;
2792
+ return /* @__PURE__ */ jsx(Static, {
2793
+ items: [0],
2794
+ children: (key) => /* @__PURE__ */ jsxs(Box, {
2795
+ borderStyle: "bold",
2796
+ flexDirection: "column",
2797
+ paddingX: 1,
2798
+ children: [
2799
+ /* @__PURE__ */ jsxs(Text, { children: [
2800
+ /* @__PURE__ */ jsx(Text, {
2801
+ italic: true,
2802
+ children: "🚀 Update available! "
2803
+ }),
2804
+ /* @__PURE__ */ jsx(Text, {
2805
+ color: theme.colors.secondary,
2806
+ children: VERSION
2807
+ }),
2808
+ " →",
2809
+ " ",
2810
+ /* @__PURE__ */ jsx(Text, {
2811
+ color: theme.colors.secondary,
2812
+ children: latestVersion
2813
+ })
2814
+ ] }),
2815
+ /* @__PURE__ */ jsx(Box, {
2816
+ marginBottom: 1,
2817
+ children: /* @__PURE__ */ jsxs(Text, { children: [
2818
+ "Run to update:",
2819
+ " ",
2820
+ /* @__PURE__ */ jsxs(Text, {
2821
+ color: theme.colors.command,
2822
+ children: ["npm i -g ", NAME]
2823
+ })
2824
+ ] })
2825
+ }),
2826
+ /* @__PURE__ */ jsx(Text, { children: "See release notes:" }),
2827
+ /* @__PURE__ */ jsx(Text, {
2828
+ color: theme.colors.accent,
2829
+ dimColor: true,
2830
+ underline: true,
2831
+ children: RELEASES_URL
2832
+ })
2833
+ ]
2834
+ }, key)
2835
+ });
2836
+ }
2837
+ //#endregion
2784
2838
  //#region src/components/App/constants.ts
2785
2839
  var Screen = /* @__PURE__ */ function(Screen) {
2786
2840
  Screen["Chat"] = "chat";
@@ -3002,7 +3056,7 @@ function ReadinessCheck({ errorMessage, onCommand, setupState, theme = getTheme(
3002
3056
  function App({ sessionId }) {
3003
3057
  const [appConfig, setConfig] = useState(() => loadConfig());
3004
3058
  const [mode, setMode] = useState(SAFE);
3005
- const [isHeaderLoaded, setIsHeaderLoaded] = useState(false);
3059
+ const [isLoaded, setIsLoaded] = useState(false);
3006
3060
  const [setupState, setSetupState] = useState(() => appConfig.model ? ReadinessState.Ready : ReadinessState.MissingModelConfig);
3007
3061
  const [setupErrorMessage, setSetupErrorMessage] = useState(null);
3008
3062
  const { currentScreen, setScreen, handleClose, handleCommand } = useScreenRouter();
@@ -3066,19 +3120,6 @@ function App({ sessionId }) {
3066
3120
  onUpdateConfig: handleUpdateConfig,
3067
3121
  setScreen
3068
3122
  });
3069
- const handleHeaderLoad = useCallback(() => {
3070
- setIsHeaderLoaded(true);
3071
- }, []);
3072
- const handleToggleMode = useCallback(() => {
3073
- setMode((mode) => {
3074
- switch (mode) {
3075
- case SAFE: return AUTO;
3076
- case AUTO: return PLAN;
3077
- case PLAN:
3078
- default: return SAFE;
3079
- }
3080
- });
3081
- }, []);
3082
3123
  const handleChatCommand = useCallback((command) => {
3083
3124
  handleCommand(command, {
3084
3125
  model: appConfig.model ?? "",
@@ -3093,18 +3134,6 @@ function App({ sessionId }) {
3093
3134
  handleCreateSession,
3094
3135
  setPreviewThemeId
3095
3136
  ]);
3096
- const handleDeleteSessionAndStay = useCallback((sid) => {
3097
- handleDeleteSession(sid);
3098
- setScreen(Screen.SessionManager);
3099
- }, [handleDeleteSession, setScreen]);
3100
- const handleOpenSessionAndNavigate = useCallback((sid) => {
3101
- handleOpenSession(sid);
3102
- setScreen(Screen.Chat);
3103
- }, [handleOpenSession, setScreen]);
3104
- const handleCreateSessionAndNavigate = useCallback(() => {
3105
- handleCreateSession();
3106
- setScreen(Screen.Chat);
3107
- }, [handleCreateSession, setScreen]);
3108
3137
  let screenContent;
3109
3138
  switch (currentScreen) {
3110
3139
  case Screen.ModelManager:
@@ -3127,9 +3156,18 @@ function App({ sessionId }) {
3127
3156
  screenContent = /* @__PURE__ */ jsx(SessionManager, {
3128
3157
  currentSessionId: activeSession.metadata.id,
3129
3158
  onClose: handleClose,
3130
- onDelete: handleDeleteSessionAndStay,
3131
- onNew: handleCreateSessionAndNavigate,
3132
- onOpen: handleOpenSessionAndNavigate,
3159
+ onDelete: (sessionId) => {
3160
+ handleDeleteSession(sessionId);
3161
+ setScreen(Screen.SessionManager);
3162
+ },
3163
+ onNew: () => {
3164
+ handleCreateSession();
3165
+ setScreen(Screen.Chat);
3166
+ },
3167
+ onOpen: (sessionId) => {
3168
+ handleOpenSession(sessionId);
3169
+ setScreen(Screen.Chat);
3170
+ },
3133
3171
  theme: activeTheme
3134
3172
  });
3135
3173
  break;
@@ -3164,14 +3202,27 @@ function App({ sessionId }) {
3164
3202
  children: [
3165
3203
  /* @__PURE__ */ jsx(Header, {
3166
3204
  model: appConfig.model ?? "",
3167
- onLoad: handleHeaderLoad,
3168
3205
  theme: activeTheme
3169
3206
  }),
3170
- isHeaderLoaded && screenContent,
3207
+ /* @__PURE__ */ jsx(UpdateBanner, {
3208
+ onLoad: () => {
3209
+ setIsLoaded(true);
3210
+ },
3211
+ theme: activeTheme
3212
+ }),
3213
+ isLoaded && screenContent,
3171
3214
  /* @__PURE__ */ jsx(Footer, {
3172
3215
  mode,
3173
3216
  model: appConfig.model ?? "",
3174
- onToggleMode: handleToggleMode,
3217
+ onToggleMode: () => {
3218
+ setMode((mode) => {
3219
+ switch (mode) {
3220
+ case SAFE: return AUTO;
3221
+ case AUTO: return PLAN;
3222
+ case PLAN: return SAFE;
3223
+ }
3224
+ });
3225
+ },
3175
3226
  theme: activeTheme
3176
3227
  })
3177
3228
  ]
package/dist/cli.js CHANGED
@@ -38,7 +38,7 @@ var LIST$1 = [
38
38
  //#endregion
39
39
  //#region package.json
40
40
  var name = "code-ollama";
41
- var version = "0.19.1";
41
+ var version = "0.21.0";
42
42
  //#endregion
43
43
  //#region src/constants/package.ts
44
44
  var NAME = name;
@@ -604,7 +604,8 @@ function createSession(model) {
604
604
  createdAt: now,
605
605
  updatedAt: now,
606
606
  title: DEFAULT_TITLE,
607
- model
607
+ model,
608
+ directory: process.cwd()
608
609
  };
609
610
  ensureSessionDirectory(id);
610
611
  writeMetadata(metadata);
@@ -614,7 +615,7 @@ function createSession(model) {
614
615
  messages: []
615
616
  };
616
617
  }
617
- function listSessions() {
618
+ function listSessions(directory = process.cwd()) {
618
619
  if (!existsSync(SESSIONS_DIRECTORY)) return [];
619
620
  return readdirSync(SESSIONS_DIRECTORY, { withFileTypes: true }).filter((entry) => entry.isDirectory()).flatMap((entry) => {
620
621
  try {
@@ -622,7 +623,7 @@ function listSessions() {
622
623
  } catch {
623
624
  return [];
624
625
  }
625
- }).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
626
+ }).filter((metadata) => metadata.directory === directory).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
626
627
  }
627
628
  function loadSession(id) {
628
629
  return {
@@ -1205,6 +1206,38 @@ async function executeTool(name, args, options) {
1205
1206
  }
1206
1207
  }
1207
1208
  //#endregion
1209
+ //#region src/utils/update.ts
1210
+ var REGISTRY_URL = `https://registry.npmjs.org/${NAME}/latest`;
1211
+ function getSemver(version) {
1212
+ return version.split(".").map(Number);
1213
+ }
1214
+ /**
1215
+ * Check if the latest version is newer than the current version
1216
+ * @param current The current version
1217
+ * @param latest The latest version
1218
+ * @returns true if the latest version is newer, false otherwise
1219
+ */
1220
+ function isVersionNewer(current, latest) {
1221
+ const [currentMajor, currentMinor, currentPatch] = getSemver(current);
1222
+ const [latestMajor, latestMinor, latestPatch] = getSemver(latest);
1223
+ if (latestMajor !== currentMajor) return latestMajor > currentMajor;
1224
+ if (latestMinor !== currentMinor) return latestMinor > currentMinor;
1225
+ return latestPatch > currentPatch;
1226
+ }
1227
+ /**
1228
+ * Check if a newer version is available on npm
1229
+ * @returns The latest version if available, undefined otherwise
1230
+ */
1231
+ async function checkForUpdate() {
1232
+ try {
1233
+ const response = await fetch(REGISTRY_URL);
1234
+ if (!response.ok) return;
1235
+ const { version: latestVersion } = await response.json();
1236
+ if (!latestVersion) return;
1237
+ if (isVersionNewer(VERSION, latestVersion)) return latestVersion;
1238
+ } catch {}
1239
+ }
1240
+ //#endregion
1208
1241
  //#region src/cli.ts
1209
1242
  var cli = cac("code-ollama");
1210
1243
  cli.version(VERSION);
@@ -1219,7 +1252,12 @@ cli.command("run <model> <prompt>", "Run a one-off prompt").action(async (model,
1219
1252
  });
1220
1253
  cli.command("resume <sessionId>", "Resume a saved session").action(async (sessionId) => {
1221
1254
  try {
1222
- loadSession(sessionId);
1255
+ const loaded = loadSession(sessionId);
1256
+ if (loaded.metadata.directory && loaded.metadata.directory !== process.cwd()) {
1257
+ writeError(color(`${WARNING} Cannot resume: session belongs to ${loaded.metadata.directory}\n`, "yellow"));
1258
+ process.exitCode = 1;
1259
+ return;
1260
+ }
1223
1261
  await launchTui(sessionId);
1224
1262
  } catch (error) {
1225
1263
  writeError(`Error: ${error instanceof Error ? error.message : "Unknown error"}\n`);
@@ -1268,7 +1306,7 @@ async function main(args = process.argv.slice(2)) {
1268
1306
  else await launchTui();
1269
1307
  }
1270
1308
  async function launchTui(sessionId) {
1271
- const { renderApp } = await import("./assets/tui-DDbMjcMS.js");
1309
+ const { renderApp } = await import("./assets/tui-48fT4HLs.js");
1272
1310
  reset();
1273
1311
  renderApp(sessionId);
1274
1312
  }
@@ -1284,4 +1322,4 @@ function isEntrypoint(argv1 = process.argv[1]) {
1284
1322
  if (isEntrypoint()) main();
1285
1323
  // v8 ignore stop
1286
1324
  //#endregion
1287
- export { WARNING as A, LABEL as B, loadConfig as C, resetSystemMessage as D, saveClipboardImage as E, USER as F, VERSION as G, SAFE as H, PLAN_GENERATION_INSTRUCTION as I, LIST$1 as K, BACK as L, getTheme as M, ASSISTANT as N, withSystemMessage as O, SYSTEM as P, CATALOG as R, streamChat as S, removeClipboardImage as T, APPROVE as U, PLAN as V, REJECT as W, setClearHandler as _, tick as a, listModels as b, appendMessage as c, deleteSessionIfEmpty as d, listSessions as f, reset as g, clear as h, WRITE_TOOLS as i, LIST as j, HEADER_PREFIX as k, createSession as l, updateSessionModel as m, main, READ_TOOLS as n, color as o, loadSession as p, TOOLS as r, write as s, executeTool as t, deleteSession as u, checkHealth as v, saveConfig as w, pullModel as x, deleteModel as y, AUTO as z };
1325
+ export { HEADER_PREFIX as A, AUTO as B, streamChat as C, saveClipboardImage as D, removeClipboardImage as E, SYSTEM as F, REJECT as G, PLAN as H, USER as I, LIST$1 as J, NAME as K, PLAN_GENERATION_INSTRUCTION as L, LIST as M, getTheme as N, resetSystemMessage as O, ASSISTANT as P, BACK as R, pullModel as S, saveConfig as T, SAFE as U, LABEL as V, APPROVE as W, reset as _, WRITE_TOOLS as a, deleteModel as b, write as c, deleteSession as d, deleteSessionIfEmpty as f, clear as g, updateSessionModel as h, TOOLS as i, WARNING as j, withSystemMessage as k, appendMessage as l, loadSession as m, main, executeTool as n, tick as o, listSessions as p, VERSION as q, READ_TOOLS as r, color as s, checkForUpdate as t, createSession as u, setClearHandler as v, loadConfig as w, listModels as x, checkHealth as y, CATALOG as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-ollama",
3
- "version": "0.19.1",
3
+ "version": "0.21.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",