codesavant 1.2.0 → 1.2.6

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.
Files changed (2) hide show
  1. package/dist/cli.js +82 -36
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -5455,6 +5455,9 @@ var init_commands = __esm({
5455
5455
  // src/cli.ts
5456
5456
  import { Command } from "commander";
5457
5457
  import chalk20 from "chalk";
5458
+ import { readFileSync as readFileSync5 } from "fs";
5459
+ import { fileURLToPath as fileURLToPath4 } from "url";
5460
+ import { dirname as dirname4, join as join6 } from "path";
5458
5461
 
5459
5462
  // src/config.ts
5460
5463
  import fs from "fs-extra";
@@ -5792,6 +5795,9 @@ Use this context to provide more relevant and personalized assistance.`;
5792
5795
  import readline from "readline";
5793
5796
  import chalk17 from "chalk";
5794
5797
  import ora from "ora";
5798
+ import { readFileSync as readFileSync3 } from "fs";
5799
+ import { fileURLToPath as fileURLToPath2 } from "url";
5800
+ import { dirname as dirname2, join as join4 } from "path";
5795
5801
 
5796
5802
  // src/providers/router.ts
5797
5803
  import OpenAI from "openai";
@@ -23004,29 +23010,37 @@ function formatGlobResult(files, pattern, options = {}) {
23004
23010
  }
23005
23011
  function formatBashResult(result, command, options = {}) {
23006
23012
  const { collapsed = true, maxCollapsedLines = 10, showExpandHint = true } = options;
23013
+ const isFailed = result.exitCode !== 0;
23007
23014
  const lines = [];
23008
- const displayCommand = command.length > 60 ? command.slice(0, 60) + "..." : command;
23009
- const statusIcon = result.exitCode === 0 ? COLORS2.success(ICONS.success) : COLORS2.error(ICONS.error);
23010
- const statusText = result.exitCode === 0 ? "completed" : `failed (exit ${result.exitCode})`;
23011
- lines.push(`${COLORS2.accent(ICONS.lightning)} ${COLORS2.accent(displayCommand)}`);
23012
- lines.push(` ${statusIcon} ${result.exitCode === 0 ? COLORS2.success(statusText) : COLORS2.error(statusText)}`);
23015
+ const displayCommand = isFailed ? command : command.length > 60 ? command.slice(0, 60) + "..." : command;
23016
+ const statusIcon = isFailed ? COLORS2.error(ICONS.error) : COLORS2.success(ICONS.success);
23017
+ const statusText = isFailed ? `failed (exit ${result.exitCode})` : "completed";
23018
+ lines.push(`${COLORS2.accent(ICONS.lightning)} ${isFailed ? COLORS2.error("bash") : COLORS2.accent("bash")} ${COLORS2.accent(displayCommand)}`);
23019
+ lines.push(` ${statusIcon} ${isFailed ? COLORS2.error(statusText) : COLORS2.success(statusText)}`);
23013
23020
  const outputLines = result.output.split("\n").filter((l) => l.trim()).length;
23014
23021
  if (outputLines > 0) {
23015
23022
  lines.push(` ${COLORS2.muted(`${outputLines} lines of output`)}`);
23016
- if (collapsed && showExpandHint) {
23023
+ const shouldShowOutput = isFailed || !collapsed;
23024
+ if (collapsed && showExpandHint && !isFailed) {
23017
23025
  lines.push(COLORS2.muted(" (ctrl+o to expand)"));
23018
23026
  }
23019
- if (!collapsed) {
23027
+ if (shouldShowOutput) {
23020
23028
  const outputPreview = result.output.split("\n").slice(0, maxCollapsedLines);
23021
23029
  lines.push(COLORS2.muted(" \u2500".repeat(30)));
23022
23030
  for (const line of outputPreview) {
23023
- lines.push(` ${COLORS2.muted("\u2502")} ${line}`);
23031
+ if (isFailed && (line.toLowerCase().includes("error") || line.toLowerCase().includes("failed"))) {
23032
+ lines.push(` ${COLORS2.muted("\u2502")} ${COLORS2.error(line)}`);
23033
+ } else {
23034
+ lines.push(` ${COLORS2.muted("\u2502")} ${line}`);
23035
+ }
23024
23036
  }
23025
23037
  if (result.truncated || outputLines > maxCollapsedLines) {
23026
23038
  const remaining = (result.totalLines || outputLines) - maxCollapsedLines;
23027
23039
  lines.push(` ${COLORS2.muted("\u2502")} ${COLORS2.muted(`... (${remaining} more lines)`)}`);
23028
23040
  }
23029
23041
  }
23042
+ } else if (isFailed) {
23043
+ lines.push(` ${COLORS2.error("No output (command failed silently)")}`);
23030
23044
  }
23031
23045
  return lines.join("\n");
23032
23046
  }
@@ -25463,6 +25477,9 @@ init_commands();
25463
25477
  import os18 from "os";
25464
25478
  import path24 from "path";
25465
25479
  import fs23 from "fs-extra";
25480
+ import { readFileSync as readFileSync2 } from "fs";
25481
+ import { fileURLToPath } from "url";
25482
+ import { dirname, join as join3 } from "path";
25466
25483
 
25467
25484
  // src/commands/types.ts
25468
25485
  var DEFAULT_BUG_REPORT_OPTIONS = {
@@ -25475,7 +25492,11 @@ var DEFAULT_BUG_REPORT_OPTIONS = {
25475
25492
  };
25476
25493
 
25477
25494
  // src/commands/bug.ts
25478
- var CODESAVANT_VERSION = "1.0.0";
25495
+ var __bug_filename = fileURLToPath(import.meta.url);
25496
+ var __bug_dirname = dirname(__bug_filename);
25497
+ var bugPackageJsonPath = join3(__bug_dirname, "..", "package.json");
25498
+ var bugPackageJson = JSON.parse(readFileSync2(bugPackageJsonPath, "utf-8"));
25499
+ var CODESAVANT_VERSION = bugPackageJson.version;
25479
25500
  var GITHUB_REPO_URL = "https://github.com/codesavant/codesavant";
25480
25501
  function collectSystemInfo() {
25481
25502
  return {
@@ -26505,6 +26526,11 @@ function stripAnsi2(str) {
26505
26526
  }
26506
26527
 
26507
26528
  // src/repl.ts
26529
+ var __classic_repl_filename = fileURLToPath2(import.meta.url);
26530
+ var __classic_repl_dirname = dirname2(__classic_repl_filename);
26531
+ var classicReplPackageJsonPath = join4(__classic_repl_dirname, "..", "package.json");
26532
+ var classicReplPackageJson = JSON.parse(readFileSync3(classicReplPackageJsonPath, "utf-8"));
26533
+ var CLASSIC_REPL_VERSION = classicReplPackageJson.version;
26508
26534
  var PERMISSION_MODES = ["default", "plan", "acceptEdits", "strict", "yolo"];
26509
26535
  function createREPL(replConfig) {
26510
26536
  const agent = createAgent({
@@ -27091,7 +27117,7 @@ ${result.message}`));
27091
27117
  });
27092
27118
  const defaultProvider = replConfig.config.providers.find((p) => p.name === replConfig.config.defaultProvider) || replConfig.config.providers[0];
27093
27119
  const welcomeScreen = createWelcomeScreen({
27094
- version: "1.0.0",
27120
+ version: CLASSIC_REPL_VERSION,
27095
27121
  sessionId: sessionId2,
27096
27122
  // Multi-provider info
27097
27123
  providers: providerInfoList,
@@ -28799,6 +28825,11 @@ Undo complete: restored ${restoredCount} file(s)`));
28799
28825
  };
28800
28826
  }
28801
28827
 
28828
+ // src/repl-ink.ts
28829
+ import { readFileSync as readFileSync4 } from "fs";
28830
+ import { fileURLToPath as fileURLToPath3 } from "url";
28831
+ import { dirname as dirname3, join as join5 } from "path";
28832
+
28802
28833
  // src/ink/index.tsx
28803
28834
  import { render } from "ink";
28804
28835
 
@@ -30069,7 +30100,7 @@ function InputBoxView({
30069
30100
  }
30070
30101
  ),
30071
30102
  /* @__PURE__ */ jsx4(Text4, { color: colors.muted, children: icons.horizontal.repeat(cols) }),
30072
- /* @__PURE__ */ jsxs4(Box4, { paddingLeft: 1, children: [
30103
+ /* @__PURE__ */ jsx4(Box4, { paddingLeft: 1, flexDirection: "column", children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
30073
30104
  /* @__PURE__ */ jsxs4(Text4, { color: colors.primary, bold: true, children: [
30074
30105
  isMultiline ? icons.boxV : icons.prompt,
30075
30106
  " "
@@ -30080,11 +30111,11 @@ function InputBoxView({
30080
30111
  " ",
30081
30112
  statusText || "Processing..."
30082
30113
  ] })
30083
- ] }) : /* @__PURE__ */ jsxs4(Text4, { color: colors.text, children: [
30084
- value,
30114
+ ] }) : /* @__PURE__ */ jsx4(Box4, { flexGrow: 1, children: /* @__PURE__ */ jsxs4(Text4, { wrap: "truncate-end", color: colors.text, children: [
30115
+ value.length > cols - 5 ? value.slice(-(cols - 5)) : value,
30085
30116
  /* @__PURE__ */ jsx4(Text4, { color: colors.muted, children: "_" })
30086
- ] })
30087
- ] }),
30117
+ ] }) })
30118
+ ] }) }),
30088
30119
  /* @__PURE__ */ jsx4(Box4, { paddingLeft: 1, children: isMultiline ? /* @__PURE__ */ jsxs4(Text4, { children: [
30089
30120
  /* @__PURE__ */ jsx4(Text4, { color: colors.warning, children: "multiline" }),
30090
30121
  /* @__PURE__ */ jsxs4(Text4, { color: colors.muted, children: [
@@ -30130,7 +30161,7 @@ function InputBoxView({
30130
30161
  ] }),
30131
30162
  /* @__PURE__ */ jsx4(Text4, { color: colors.primary, children: "Ctrl+C" }),
30132
30163
  /* @__PURE__ */ jsx4(Text4, { color: colors.muted, children: " cancel" }),
30133
- currentPermissionMode && /* @__PURE__ */ jsxs4(Fragment2, { children: [
30164
+ permissionMode && /* @__PURE__ */ jsxs4(Fragment2, { children: [
30134
30165
  /* @__PURE__ */ jsxs4(Text4, { color: colors.muted, children: [
30135
30166
  " ",
30136
30167
  icons.boxV,
@@ -30138,7 +30169,7 @@ function InputBoxView({
30138
30169
  ] }),
30139
30170
  /* @__PURE__ */ jsxs4(Text4, { color: colors.info, children: [
30140
30171
  "[",
30141
- currentPermissionMode,
30172
+ permissionMode,
30142
30173
  "]"
30143
30174
  ] })
30144
30175
  ] })
@@ -30170,8 +30201,8 @@ function App({
30170
30201
  const [autocompleteQuery, setAutocompleteQuery] = useState5("");
30171
30202
  const lastEscapeRef = useRef(0);
30172
30203
  const [renderedMessageCount, setRenderedMessageCount] = useState5(0);
30173
- const permissionModes = ["prompt", "auto-edit", "auto-full", "deny"];
30174
- const [currentPermissionMode2, setCurrentPermissionMode] = useState5(permissionMode);
30204
+ const permissionModes = ["default", "plan", "acceptEdits", "strict", "yolo"];
30205
+ const [currentPermissionMode, setCurrentPermissionMode] = useState5(permissionMode);
30175
30206
  useEffect2(() => {
30176
30207
  if (sessionId2) actions.setSessionId(sessionId2);
30177
30208
  if (provider && model) actions.setProvider(provider, model);
@@ -30251,7 +30282,7 @@ function App({
30251
30282
  return;
30252
30283
  }
30253
30284
  if (key.shift && key.tab) {
30254
- const currentIndex = permissionModes.indexOf(currentPermissionMode2);
30285
+ const currentIndex = permissionModes.indexOf(currentPermissionMode);
30255
30286
  const nextIndex = (currentIndex + 1) % permissionModes.length;
30256
30287
  const nextMode = permissionModes[nextIndex];
30257
30288
  setCurrentPermissionMode(nextMode);
@@ -30387,10 +30418,14 @@ function App({
30387
30418
  setAutocompleteQuery("");
30388
30419
  }, []);
30389
30420
  useEffect2(() => {
30390
- if (!state.isProcessing && state.messages.length > renderedMessageCount) {
30391
- setRenderedMessageCount(state.messages.length);
30392
- }
30393
- }, [state.isProcessing, state.messages.length, renderedMessageCount]);
30421
+ const canMoveToStatic = !state.isProcessing && !state.streamingContent && (!state.todosVisible || state.todos.length === 0);
30422
+ if (canMoveToStatic && state.messages.length > renderedMessageCount) {
30423
+ const timer = setTimeout(() => {
30424
+ setRenderedMessageCount(state.messages.length);
30425
+ }, 100);
30426
+ return () => clearTimeout(timer);
30427
+ }
30428
+ }, [state.isProcessing, state.streamingContent, state.todosVisible, state.todos.length, state.messages.length, renderedMessageCount]);
30394
30429
  const completedMessages = state.messages.slice(0, renderedMessageCount);
30395
30430
  const activeMessages = state.messages.slice(renderedMessageCount);
30396
30431
  const { colors } = theme;
@@ -30425,7 +30460,7 @@ function App({
30425
30460
  historyIndex: state.historyIndex,
30426
30461
  onHistoryNavigate: handleHistoryNavigate,
30427
30462
  theme,
30428
- permissionMode: currentPermissionMode2,
30463
+ permissionMode: currentPermissionMode,
30429
30464
  historySearchMode,
30430
30465
  historySearchQuery,
30431
30466
  historySearchMatch,
@@ -30624,6 +30659,11 @@ async function waitForExit() {
30624
30659
  // src/repl-ink.ts
30625
30660
  init_errors();
30626
30661
  init_commands();
30662
+ var __repl_filename = fileURLToPath3(import.meta.url);
30663
+ var __repl_dirname = dirname3(__repl_filename);
30664
+ var replPackageJsonPath = join5(__repl_dirname, "..", "package.json");
30665
+ var replPackageJson = JSON.parse(readFileSync4(replPackageJsonPath, "utf-8"));
30666
+ var REPL_VERSION = replPackageJson.version;
30627
30667
  function createInkREPL(replConfig) {
30628
30668
  const agent = createAgent({
30629
30669
  config: replConfig.config,
@@ -30703,13 +30743,14 @@ function createInkREPL(replConfig) {
30703
30743
  truncated: output.length > 500,
30704
30744
  totalLines: lineCount
30705
30745
  };
30706
- return formatBashResult(result, command, { collapsed: true });
30746
+ return formatBashResult(result, command, { collapsed: success });
30707
30747
  }
30708
30748
  default:
30709
30749
  if (success) {
30710
30750
  return `${toolName} completed${lineCount > 0 ? ` (${lineCount} lines)` : ""}`;
30711
30751
  } else {
30712
- return `${toolName} failed`;
30752
+ const errorMsg = toolResult.error || output.slice(0, 200) || "Unknown error";
30753
+ return `${toolName} failed: ${errorMsg}`;
30713
30754
  }
30714
30755
  }
30715
30756
  }
@@ -31977,7 +32018,7 @@ Type /help for available commands.`);
31977
32018
  isAvailable: p.name === "ollama" || !!p.apiKey
31978
32019
  }));
31979
32020
  const welcomeMessage = createWelcomeScreen({
31980
- version: "1.0.0",
32021
+ version: REPL_VERSION,
31981
32022
  sessionId: sessionId2,
31982
32023
  providers: providerInfoList,
31983
32024
  activeProvider: replConfig.config.defaultProvider,
@@ -31990,13 +32031,13 @@ Type /help for available commands.`);
31990
32031
  mcpTools: mcpToolCount,
31991
32032
  workingDir: projectPath
31992
32033
  });
31993
- let currentPermissionMode2 = agent.getPermissionManager().getMode();
32034
+ let currentPermissionMode = agent.getPermissionManager().getMode();
31994
32035
  appController = renderApp({
31995
32036
  sessionId: sessionId2,
31996
32037
  provider: defaultProvider?.name,
31997
32038
  model: defaultProvider?.model,
31998
32039
  welcomeMessage,
31999
- permissionMode: currentPermissionMode2,
32040
+ permissionMode: currentPermissionMode,
32000
32041
  onSubmit: (input) => {
32001
32042
  if (!isProcessing) {
32002
32043
  processAgentStream(input);
@@ -32032,7 +32073,7 @@ Type /help for available commands.`);
32032
32073
  const validModes = ["prompt", "auto-edit", "auto-full", "deny"];
32033
32074
  if (validModes.includes(mode)) {
32034
32075
  agent.getPermissionManager().setMode(mode);
32035
- currentPermissionMode2 = mode;
32076
+ currentPermissionMode = mode;
32036
32077
  }
32037
32078
  }
32038
32079
  });
@@ -32195,10 +32236,10 @@ async function detectCICommands(projectPath) {
32195
32236
  const fs26 = await import("fs-extra");
32196
32237
  const path27 = await import("path");
32197
32238
  const commands = [];
32198
- const packageJsonPath = path27.join(projectPath, "package.json");
32199
- if (await fs26.pathExists(packageJsonPath)) {
32239
+ const packageJsonPath2 = path27.join(projectPath, "package.json");
32240
+ if (await fs26.pathExists(packageJsonPath2)) {
32200
32241
  try {
32201
- const pkg = await fs26.readJson(packageJsonPath);
32242
+ const pkg = await fs26.readJson(packageJsonPath2);
32202
32243
  if (pkg.scripts?.build) {
32203
32244
  commands.push("npm run build");
32204
32245
  }
@@ -32231,7 +32272,7 @@ async function detectCICommands(projectPath) {
32231
32272
  if (await fs26.pathExists(path27.join(projectPath, "pyproject.toml")) || await fs26.pathExists(path27.join(projectPath, "setup.py"))) {
32232
32273
  commands.push("python -m pytest");
32233
32274
  }
32234
- if (commands.length === 0 && await fs26.pathExists(packageJsonPath)) {
32275
+ if (commands.length === 0 && await fs26.pathExists(packageJsonPath2)) {
32235
32276
  commands.push("npm run build");
32236
32277
  }
32237
32278
  return commands;
@@ -32327,6 +32368,11 @@ Fix all the issues to make the CI pass. Use the available tools to read files, e
32327
32368
  }
32328
32369
 
32329
32370
  // src/cli.ts
32371
+ var __filename = fileURLToPath4(import.meta.url);
32372
+ var __dirname = dirname4(__filename);
32373
+ var packageJsonPath = join6(__dirname, "..", "package.json");
32374
+ var packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
32375
+ var VERSION = packageJson.version;
32330
32376
  var MAX_STDIN_SIZE = 10 * 1024 * 1024;
32331
32377
  var MAX_STDIN_LINES = 1e5;
32332
32378
  async function readStdinInput(format, options) {
@@ -32378,7 +32424,7 @@ async function readStdinInput(format, options) {
32378
32424
  });
32379
32425
  }
32380
32426
  var program = new Command();
32381
- program.name("codesavant").description("AI coding assistant for your terminal").version("1.0.0").option("--verbose", "Enable verbose logging for debugging").option("--debug <categories>", 'Enable debug logging for specific categories (comma-separated: api,mcp,tool,provider,stream,session,context,permission,checkpoint,error,all). Use ! prefix to exclude: "all,!mcp"').option("--mcp-debug", "Enable MCP protocol-level debug logging").hook("preAction", (thisCommand) => {
32427
+ program.name("codesavant").description("AI coding assistant for your terminal").version(VERSION).option("--verbose", "Enable verbose logging for debugging").option("--debug <categories>", 'Enable debug logging for specific categories (comma-separated: api,mcp,tool,provider,stream,session,context,permission,checkpoint,error,all). Use ! prefix to exclude: "all,!mcp"').option("--mcp-debug", "Enable MCP protocol-level debug logging").hook("preAction", (thisCommand) => {
32382
32428
  const opts = thisCommand.opts();
32383
32429
  if (opts.debug) {
32384
32430
  setVerbose(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codesavant",
3
- "version": "1.2.0",
3
+ "version": "1.2.6",
4
4
  "description": "Multi-provider AI coding assistant for your terminal",
5
5
  "type": "module",
6
6
  "bin": {