codeep 1.1.16 → 1.1.18

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.
@@ -21,6 +21,7 @@ export interface AppOptions {
21
21
  onSubmit: (message: string) => Promise<void>;
22
22
  onCommand: (command: string, args: string[]) => void;
23
23
  onExit: () => void;
24
+ onStopAgent?: () => void;
24
25
  getStatus: () => StatusInfo;
25
26
  hasWriteAccess?: () => boolean;
26
27
  hasProjectContext?: () => boolean;
@@ -473,9 +473,11 @@ export class App {
473
473
  this.agentIteration = 0;
474
474
  this.agentActions = [];
475
475
  this.agentThinking = '';
476
+ this.isLoading = false; // Clear loading state when agent takes over
476
477
  this.startSpinner();
477
478
  }
478
479
  else {
480
+ this.isLoading = false; // Ensure loading is cleared when agent finishes
479
481
  this.stopSpinner();
480
482
  }
481
483
  this.render();
@@ -860,13 +862,17 @@ export class App {
860
862
  this.handleMenuKey(event);
861
863
  return;
862
864
  }
863
- // Escape to cancel streaming/loading or close autocomplete
865
+ // Escape to cancel streaming/loading/agent or close autocomplete
864
866
  if (event.key === 'escape') {
865
867
  if (this.showAutocomplete) {
866
868
  this.showAutocomplete = false;
867
869
  this.render();
868
870
  return;
869
871
  }
872
+ if (this.isAgentRunning && this.options.onStopAgent) {
873
+ this.options.onStopAgent();
874
+ return;
875
+ }
870
876
  if (this.isStreaming) {
871
877
  this.endStreaming();
872
878
  }
@@ -1559,7 +1565,7 @@ export class App {
1559
1565
  bottomPanelHeight = previewLines + 6; // title + preview + extra line indicator + options
1560
1566
  }
1561
1567
  else if (this.isAgentRunning) {
1562
- bottomPanelHeight = 8; // Agent progress box
1568
+ bottomPanelHeight = 6; // Agent progress box (5 lines + 1 margin)
1563
1569
  }
1564
1570
  else if (this.permissionOpen) {
1565
1571
  bottomPanelHeight = 10; // Permission dialog
@@ -2166,7 +2172,7 @@ export class App {
2166
2172
  renderInlineAgentProgress(startY, width) {
2167
2173
  let y = startY;
2168
2174
  const spinner = SPINNER_FRAMES[this.spinnerFrame];
2169
- const boxWidth = Math.min(width - 4, 60);
2175
+ const boxWidth = width - 2; // Use full width minus small margin
2170
2176
  // Calculate stats
2171
2177
  const stats = {
2172
2178
  reads: this.agentActions.filter(a => a.type === 'read').length,
@@ -2178,58 +2184,67 @@ export class App {
2178
2184
  errors: this.agentActions.filter(a => a.result === 'error').length,
2179
2185
  };
2180
2186
  // Top border with title
2187
+ // Helper to draw a box line with content
2188
+ const drawBoxLine = (content, contentStyle = fg.white) => {
2189
+ this.screen.write(0, y, '│', PRIMARY_COLOR);
2190
+ this.screen.write(2, y, content, contentStyle);
2191
+ this.screen.write(boxWidth - 1, y, '│', PRIMARY_COLOR);
2192
+ y++;
2193
+ };
2194
+ // Top border with title
2181
2195
  const title = ` ${spinner} AGENT `;
2182
- const borderLeft = '╭' + '─'.repeat(2);
2183
- const borderRight = '─'.repeat(Math.max(0, boxWidth - title.length - 4)) + '╮';
2184
- this.screen.write(0, y, borderLeft, PRIMARY_COLOR);
2185
- this.screen.write(borderLeft.length, y, title, PRIMARY_COLOR + style.bold);
2186
- this.screen.write(borderLeft.length + title.length, y, borderRight, PRIMARY_COLOR);
2196
+ const titlePadLeft = 3;
2197
+ const titlePadRight = boxWidth - titlePadLeft - title.length - 1;
2198
+ this.screen.write(0, y, '╭' + '─'.repeat(titlePadLeft), PRIMARY_COLOR);
2199
+ this.screen.write(titlePadLeft + 1, y, title, PRIMARY_COLOR + style.bold);
2200
+ this.screen.write(titlePadLeft + 1 + title.length, y, '─'.repeat(Math.max(0, titlePadRight)) + '╮', PRIMARY_COLOR);
2187
2201
  y++;
2188
2202
  // Current action line
2189
- this.screen.write(0, y, '│ ', PRIMARY_COLOR);
2203
+ this.screen.write(0, y, '│', PRIMARY_COLOR);
2190
2204
  if (this.agentActions.length > 0) {
2191
2205
  const lastAction = this.agentActions[this.agentActions.length - 1];
2192
2206
  const actionLabel = this.getActionLabel(lastAction.type);
2193
2207
  const actionColor = this.getActionColor(lastAction.type);
2194
- const target = this.formatActionTarget(lastAction.target, boxWidth - actionLabel.length - 6);
2195
- this.screen.write(2, y, actionLabel + ' ', actionColor + style.bold);
2208
+ const maxTargetLen = boxWidth - actionLabel.length - 6;
2209
+ const target = this.formatActionTarget(lastAction.target, maxTargetLen);
2210
+ this.screen.write(2, y, actionLabel, actionColor + style.bold);
2196
2211
  this.screen.write(2 + actionLabel.length + 1, y, target, fg.white);
2197
2212
  }
2198
2213
  else {
2199
2214
  this.screen.write(2, y, 'Starting...', fg.gray);
2200
2215
  }
2201
- this.screen.write(boxWidth - 1, y, ' │', PRIMARY_COLOR);
2216
+ this.screen.write(boxWidth - 1, y, '│', PRIMARY_COLOR);
2202
2217
  y++;
2203
2218
  // Separator
2204
2219
  this.screen.write(0, y, '├' + '─'.repeat(boxWidth - 2) + '┤', fg.gray);
2205
2220
  y++;
2206
2221
  // File changes line
2207
- this.screen.write(0, y, '│ ', PRIMARY_COLOR);
2208
- this.screen.write(2, y, 'Files: ', fg.cyan);
2222
+ this.screen.write(0, y, '│', PRIMARY_COLOR);
2223
+ this.screen.write(2, y, 'Files:', fg.cyan);
2209
2224
  let fileX = 9;
2210
2225
  if (stats.writes > 0) {
2211
- const txt = `+${stats.writes} `;
2226
+ const txt = `+${stats.writes}`;
2212
2227
  this.screen.write(fileX, y, txt, fg.green);
2213
- fileX += txt.length;
2228
+ fileX += txt.length + 1;
2214
2229
  }
2215
2230
  if (stats.edits > 0) {
2216
- const txt = `~${stats.edits} `;
2231
+ const txt = `~${stats.edits}`;
2217
2232
  this.screen.write(fileX, y, txt, fg.yellow);
2218
- fileX += txt.length;
2233
+ fileX += txt.length + 1;
2219
2234
  }
2220
2235
  if (stats.deletes > 0) {
2221
- const txt = `-${stats.deletes} `;
2236
+ const txt = `-${stats.deletes}`;
2222
2237
  this.screen.write(fileX, y, txt, fg.red);
2223
- fileX += txt.length;
2238
+ fileX += txt.length + 1;
2224
2239
  }
2225
2240
  if (stats.writes === 0 && stats.edits === 0 && stats.deletes === 0) {
2226
2241
  this.screen.write(fileX, y, 'no changes yet', fg.gray);
2227
2242
  }
2228
- this.screen.write(boxWidth - 1, y, ' │', PRIMARY_COLOR);
2243
+ this.screen.write(boxWidth - 1, y, '│', PRIMARY_COLOR);
2229
2244
  y++;
2230
2245
  // Stats line
2231
- this.screen.write(0, y, '│ ', PRIMARY_COLOR);
2232
- this.screen.write(2, y, 'Stats: ', fg.cyan);
2246
+ this.screen.write(0, y, '│', PRIMARY_COLOR);
2247
+ this.screen.write(2, y, 'Stats:', fg.cyan);
2233
2248
  let statX = 9;
2234
2249
  const statParts = [];
2235
2250
  if (stats.reads > 0)
@@ -2241,34 +2256,21 @@ export class App {
2241
2256
  statParts.push({ text: `step ${this.agentIteration}`, color: fg.white });
2242
2257
  for (let i = 0; i < statParts.length; i++) {
2243
2258
  if (i > 0) {
2244
- this.screen.write(statX, y, ' | ', fg.gray);
2245
- statX += 3;
2259
+ this.screen.write(statX, y, '|', fg.gray);
2260
+ statX += 2;
2246
2261
  }
2247
2262
  this.screen.write(statX, y, statParts[i].text, statParts[i].color);
2248
- statX += statParts[i].text.length;
2263
+ statX += statParts[i].text.length + 1;
2249
2264
  }
2250
- this.screen.write(boxWidth - 1, y, ' │', PRIMARY_COLOR);
2251
- y++;
2252
- // Errors line (if any)
2253
- this.screen.write(0, y, '│ ', PRIMARY_COLOR);
2254
- if (stats.errors > 0) {
2255
- this.screen.write(2, y, `${stats.errors} error(s)`, fg.red);
2256
- }
2257
- else if (this.agentThinking) {
2258
- const thinking = this.agentThinking.length > boxWidth - 6
2259
- ? this.agentThinking.slice(0, boxWidth - 9) + '...'
2260
- : this.agentThinking;
2261
- this.screen.write(2, y, '> ' + thinking, fg.gray);
2262
- }
2263
- this.screen.write(boxWidth - 1, y, ' │', PRIMARY_COLOR);
2265
+ this.screen.write(boxWidth - 1, y, '│', PRIMARY_COLOR);
2264
2266
  y++;
2265
2267
  // Bottom border with help
2266
2268
  const helpText = ' Esc to stop ';
2267
- const bottomLeft = '╰' + '─'.repeat(Math.floor((boxWidth - helpText.length - 2) / 2));
2268
- const bottomRight = '─'.repeat(Math.ceil((boxWidth - helpText.length - 2) / 2)) + '╯';
2269
- this.screen.write(0, y, bottomLeft, PRIMARY_COLOR);
2270
- this.screen.write(bottomLeft.length, y, helpText, fg.gray);
2271
- this.screen.write(bottomLeft.length + helpText.length, y, bottomRight, PRIMARY_COLOR);
2269
+ const helpPadLeft = Math.floor((boxWidth - helpText.length - 2) / 2);
2270
+ const helpPadRight = Math.ceil((boxWidth - helpText.length - 2) / 2);
2271
+ this.screen.write(0, y, '╰' + '─'.repeat(helpPadLeft), PRIMARY_COLOR);
2272
+ this.screen.write(helpPadLeft + 1, y, helpText, fg.gray);
2273
+ this.screen.write(helpPadLeft + 1 + helpText.length, y, '─'.repeat(helpPadRight) + '╯', PRIMARY_COLOR);
2272
2274
  }
2273
2275
  /**
2274
2276
  * Get color for action type
@@ -1504,6 +1504,12 @@ Commands (in chat):
1504
1504
  console.log('\nGoodbye!');
1505
1505
  process.exit(0);
1506
1506
  },
1507
+ onStopAgent: () => {
1508
+ if (isAgentRunning && agentAbortController) {
1509
+ agentAbortController.abort();
1510
+ app.notify('Stopping agent...');
1511
+ }
1512
+ },
1507
1513
  getStatus,
1508
1514
  hasWriteAccess: () => hasWriteAccess,
1509
1515
  hasProjectContext: () => projectContext !== null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeep",
3
- "version": "1.1.16",
3
+ "version": "1.1.18",
4
4
  "description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",