agentk8 2.3.5 → 2.3.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.
@@ -376,26 +376,26 @@ Format your response clearly with headers.`;
376
376
  case 'normal':
377
377
  setExecutionMode('normal');
378
378
  setAutoAccept(false);
379
- addSystemMessage('Normal mode. I will execute and ask for confirmation on edits.');
379
+ // Status bar shows the mode change
380
380
  break;
381
381
  case 'plan':
382
382
  setExecutionMode('plan');
383
383
  setAutoAccept(false);
384
- addSystemMessage('Plan mode. I will create a plan for approval before executing.');
384
+ // Status bar shows the mode change
385
385
  break;
386
386
  case 'auto':
387
+ // Only auto mode shows a warning confirmation
387
388
  setConfirmationState({
388
- message: '⚠️ Enable Auto Mode? This executes everything without any confirmations.',
389
+ message: '⚠️ Enable Auto Mode? This executes everything without confirmations.',
389
390
  options: [
390
391
  { label: 'Yes, enable auto', value: 'yes' },
391
- { label: 'No, keep current mode', value: 'no' },
392
+ { label: 'No, stay normal', value: 'no' },
392
393
  ],
393
394
  onSelect: (value) => {
394
395
  setConfirmationState(null);
395
396
  if (value === 'yes') {
396
397
  setExecutionMode('auto');
397
398
  setAutoAccept(true);
398
- addSystemMessage('Auto mode. No confirmations, executing everything directly.');
399
399
  }
400
400
  },
401
401
  onCancel: () => setConfirmationState(null),
@@ -470,6 +470,7 @@ Format your response clearly with headers.`;
470
470
  /exit - Exit AGENT-K
471
471
 
472
472
  Keyboard shortcuts:
473
+ Shift+Tab - Cycle mode (normal/plan/auto)
473
474
  ↑/↓ - Browse command history
474
475
  Tab - Autocomplete commands
475
476
  Esc - Cancel operation (when processing)
@@ -501,8 +502,52 @@ Ctrl+U - Clear input line`,
501
502
  setError(`Unknown command: /${command}`);
502
503
  }
503
504
  };
505
+ // Cycle execution mode (normal -> plan -> auto)
506
+ // Only shows warning for auto mode, otherwise just updates status bar silently
507
+ const cycleExecutionMode = () => {
508
+ const modes = ['normal', 'plan', 'auto'];
509
+ const currentIndex = modes.indexOf(executionMode);
510
+ const nextMode = modes[(currentIndex + 1) % modes.length];
511
+ if (nextMode === 'auto') {
512
+ // Show warning confirmation only for auto mode
513
+ setConfirmationState({
514
+ message: '⚠️ Enable Auto Mode? This executes everything without confirmations.',
515
+ options: [
516
+ { label: 'Yes, enable auto', value: 'yes' },
517
+ { label: 'No, stay normal', value: 'no' },
518
+ ],
519
+ onSelect: (value) => {
520
+ setConfirmationState(null);
521
+ if (value === 'yes') {
522
+ setExecutionMode('auto');
523
+ setAutoAccept(true);
524
+ }
525
+ else {
526
+ // Rejected - go back to normal
527
+ setExecutionMode('normal');
528
+ setAutoAccept(false);
529
+ }
530
+ },
531
+ onCancel: () => {
532
+ setConfirmationState(null);
533
+ setExecutionMode('normal');
534
+ setAutoAccept(false);
535
+ },
536
+ });
537
+ }
538
+ else {
539
+ // normal and plan modes switch silently - status bar shows the change
540
+ setExecutionMode(nextMode);
541
+ setAutoAccept(false);
542
+ }
543
+ };
504
544
  // Handle keyboard shortcuts
505
- useInput((input, key) => {
545
+ useInput((_input, key) => {
546
+ // Shift+Tab to cycle execution mode
547
+ if (key.tab && key.shift && !isProcessing && !confirmationState && !questionWizardState) {
548
+ cycleExecutionMode();
549
+ return;
550
+ }
506
551
  // Escape key handling
507
552
  if (key.escape) {
508
553
  const now = Date.now();
@@ -13,10 +13,28 @@ const theme = {
13
13
  code: '#f6ad55', // Orange for inline code
14
14
  header: '#63b3ed', // Blue for headers
15
15
  };
16
+ // Pre-process text to remove orphaned markdown markers
17
+ function cleanOrphanedMarkers(text) {
18
+ let result = text;
19
+ // Remove orphaned ** (bold markers without pairs)
20
+ // Count ** occurrences - if odd, the last one is orphaned
21
+ const boldMatches = result.match(/\*\*/g);
22
+ if (boldMatches && boldMatches.length % 2 !== 0) {
23
+ // Find and remove the last unmatched **
24
+ const lastIndex = result.lastIndexOf('**');
25
+ result = result.slice(0, lastIndex) + result.slice(lastIndex + 2);
26
+ }
27
+ // Also handle case where ** appears at start or end without content
28
+ result = result.replace(/^\*\*\s*$/, '');
29
+ result = result.replace(/^\*\*(?!\S)/, '');
30
+ result = result.replace(/(?<!\S)\*\*$/, '');
31
+ return result;
32
+ }
16
33
  // Parse inline markdown and return React elements
17
34
  function parseInlineMarkdown(text, defaultColor) {
18
35
  const elements = [];
19
- let remaining = text;
36
+ // Clean orphaned markers first
37
+ let remaining = cleanOrphanedMarkers(text);
20
38
  let key = 0;
21
39
  while (remaining.length > 0) {
22
40
  // Check for bold **text**
@@ -48,9 +66,14 @@ function parseInlineMarkdown(text, defaultColor) {
48
66
  break;
49
67
  }
50
68
  else if (nextSpecial === 0) {
51
- // Special char at start but didn't match pattern - treat as literal
52
- elements.push(_jsx(Text, { color: defaultColor, children: remaining[0] }, key++));
53
- remaining = remaining.slice(1);
69
+ // Special char at start but didn't match pattern - skip marker silently
70
+ // Check if it's a double asterisk that didn't match
71
+ if (remaining.startsWith('**')) {
72
+ remaining = remaining.slice(2);
73
+ }
74
+ else {
75
+ remaining = remaining.slice(1);
76
+ }
54
77
  }
55
78
  else {
56
79
  // Add text before special char
@@ -31,9 +31,46 @@ export const Input = ({ onSubmit, placeholder = 'Type a message...', prefix = '
31
31
  return matches[0].slice(value.length);
32
32
  };
33
33
  const suggestion = getSuggestion();
34
+ // Navigate history up
35
+ const navigateHistoryUp = () => {
36
+ if (commandHistory.length > 0) {
37
+ if (historyIndex === -1) {
38
+ setTempValue(value);
39
+ const newIndex = commandHistory.length - 1;
40
+ setHistoryIndex(newIndex);
41
+ setValue(commandHistory[newIndex]);
42
+ setCursorPosition(commandHistory[newIndex].length);
43
+ }
44
+ else if (historyIndex > 0) {
45
+ const newIndex = historyIndex - 1;
46
+ setHistoryIndex(newIndex);
47
+ setValue(commandHistory[newIndex]);
48
+ setCursorPosition(commandHistory[newIndex].length);
49
+ }
50
+ }
51
+ };
52
+ // Navigate history down
53
+ const navigateHistoryDown = () => {
54
+ if (historyIndex !== -1) {
55
+ if (historyIndex < commandHistory.length - 1) {
56
+ const newIndex = historyIndex + 1;
57
+ setHistoryIndex(newIndex);
58
+ setValue(commandHistory[newIndex]);
59
+ setCursorPosition(commandHistory[newIndex].length);
60
+ }
61
+ else {
62
+ setHistoryIndex(-1);
63
+ setValue(tempValue);
64
+ setCursorPosition(tempValue.length);
65
+ }
66
+ }
67
+ };
34
68
  useInput((input, key) => {
35
69
  if (disabled)
36
70
  return;
71
+ // Handle arrow keys first (including escape sequence fallback)
72
+ const isUpArrow = key.upArrow || input === '\x1b[A' || input === '\x1bOA';
73
+ const isDownArrow = key.downArrow || input === '\x1b[B' || input === '\x1bOB';
37
74
  if (key.return) {
38
75
  if (value.trim()) {
39
76
  if (commandHistory.length === 0 || commandHistory[commandHistory.length - 1] !== value) {
@@ -49,37 +86,11 @@ export const Input = ({ onSubmit, placeholder = 'Type a message...', prefix = '
49
86
  setTempValue('');
50
87
  }
51
88
  }
52
- else if (key.upArrow) {
53
- if (commandHistory.length > 0) {
54
- if (historyIndex === -1) {
55
- setTempValue(value);
56
- const newIndex = commandHistory.length - 1;
57
- setHistoryIndex(newIndex);
58
- setValue(commandHistory[newIndex]);
59
- setCursorPosition(commandHistory[newIndex].length);
60
- }
61
- else if (historyIndex > 0) {
62
- const newIndex = historyIndex - 1;
63
- setHistoryIndex(newIndex);
64
- setValue(commandHistory[newIndex]);
65
- setCursorPosition(commandHistory[newIndex].length);
66
- }
67
- }
89
+ else if (isUpArrow) {
90
+ navigateHistoryUp();
68
91
  }
69
- else if (key.downArrow) {
70
- if (historyIndex !== -1) {
71
- if (historyIndex < commandHistory.length - 1) {
72
- const newIndex = historyIndex + 1;
73
- setHistoryIndex(newIndex);
74
- setValue(commandHistory[newIndex]);
75
- setCursorPosition(commandHistory[newIndex].length);
76
- }
77
- else {
78
- setHistoryIndex(-1);
79
- setValue(tempValue);
80
- setCursorPosition(tempValue.length);
81
- }
82
- }
92
+ else if (isDownArrow) {
93
+ navigateHistoryDown();
83
94
  }
84
95
  else if (key.backspace || key.delete) {
85
96
  if (cursorPosition > 0) {
@@ -108,7 +119,8 @@ export const Input = ({ onSubmit, placeholder = 'Type a message...', prefix = '
108
119
  else if (key.ctrl && input === 'e') {
109
120
  setCursorPosition(value.length);
110
121
  }
111
- else if (key.tab) {
122
+ else if (key.tab && !key.shift) {
123
+ // Plain Tab for autocomplete (Shift+Tab handled by App for mode cycling)
112
124
  if (suggestion) {
113
125
  const completed = value + suggestion;
114
126
  setValue(completed);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentk8",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "Multi-LLM Council Terminal Suite - Three-stage consensus with GPT, Gemini, and Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",