agentk8 2.3.4 → 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.
package/dist/cli.js CHANGED
@@ -27,10 +27,14 @@ const cli = meow(`
27
27
  /exit Exit AGENT-K
28
28
 
29
29
  Keyboard
30
- Esc Cancel current operation (when processing)
30
+ Esc Cancel operation (when processing)
31
31
  Esc Esc Exit (double-press when idle)
32
32
  Ctrl+U Clear input line
33
- Shift+Tab Toggle auto-edit mode
33
+
34
+ Modes (/normal, /plan, /auto)
35
+ normal Execute, confirm edits (default)
36
+ plan Plan first, then execute
37
+ auto No confirmations
34
38
  `, {
35
39
  importMeta: import.meta,
36
40
  flags: {
@@ -25,7 +25,7 @@ export const App = ({ mode, version }) => {
25
25
  const [totalTokens, setTotalTokens] = useState(0);
26
26
  const [startTime] = useState(new Date());
27
27
  const [error, setError] = useState(null);
28
- const [executionMode, setExecutionMode] = useState('plan');
28
+ const [executionMode, setExecutionMode] = useState('normal');
29
29
  const [activeAgent, setActiveAgent] = useState(undefined);
30
30
  const [completedAgents, setCompletedAgents] = useState([]);
31
31
  const [confirmationState, setConfirmationState] = useState(null);
@@ -136,6 +136,7 @@ export const App = ({ mode, version }) => {
136
136
  await generatePlan(input);
137
137
  }
138
138
  else {
139
+ // normal or auto mode - executeTask handles autoAccept
139
140
  await executeTask(input);
140
141
  }
141
142
  };
@@ -372,35 +373,36 @@ Format your response clearly with headers.`;
372
373
  setActiveAgent(undefined);
373
374
  setCompletedAgents([]);
374
375
  break;
376
+ case 'normal':
377
+ setExecutionMode('normal');
378
+ setAutoAccept(false);
379
+ // Status bar shows the mode change
380
+ break;
375
381
  case 'plan':
376
382
  setExecutionMode('plan');
377
- addSystemMessage('Plan mode enabled. I will show plans for approval before executing.');
383
+ setAutoAccept(false);
384
+ // Status bar shows the mode change
378
385
  break;
379
386
  case 'auto':
387
+ // Only auto mode shows a warning confirmation
380
388
  setConfirmationState({
381
- message: '⚠️ Are you sure you want to enable Auto Mode? This will execute actions without further approval.',
389
+ message: '⚠️ Enable Auto Mode? This executes everything without confirmations.',
382
390
  options: [
383
- { label: 'Yes, enable auto mode', value: 'yes' },
384
- { label: 'No, stay in plan mode', value: 'no' },
391
+ { label: 'Yes, enable auto', value: 'yes' },
392
+ { label: 'No, stay normal', value: 'no' },
385
393
  ],
386
394
  onSelect: (value) => {
387
395
  setConfirmationState(null);
388
396
  if (value === 'yes') {
389
397
  setExecutionMode('auto');
390
- addSystemMessage('Auto mode enabled. I will execute tasks directly without approval.');
391
- }
392
- else {
393
- addSystemMessage('Kept in plan mode.');
398
+ setAutoAccept(true);
394
399
  }
395
400
  },
396
- onCancel: () => {
397
- setConfirmationState(null);
398
- addSystemMessage('Kept in plan mode.');
399
- },
401
+ onCancel: () => setConfirmationState(null),
400
402
  });
401
403
  break;
402
404
  case 'mode':
403
- addSystemMessage(`Current execution mode: ${executionMode}\nUse /plan or /auto to switch.`);
405
+ addSystemMessage(`Current mode: ${executionMode}\nUse /normal, /plan, or /auto to switch.`);
404
406
  break;
405
407
  case 'agents':
406
408
  if (!activeAgent && completedAgents.length === 0) {
@@ -457,9 +459,10 @@ Format your response clearly with headers.`;
457
459
  /help - Show this help
458
460
  /clear - Clear chat history
459
461
  /status - Show session status
460
- /plan - Enable plan mode (ask before executing)
461
- /auto - Enable auto mode (execute directly)
462
- /mode - Show current execution mode
462
+ /normal - Normal mode (execute, confirm edits)
463
+ /plan - Plan mode (plan first, then execute)
464
+ /auto - Auto mode (no confirmations)
465
+ /mode - Show current mode
463
466
  /agents - Show active agents
464
467
  /council - Toggle council mode (multi-LLM consensus)
465
468
  /solo - Enable solo council (multi-Claude personas)
@@ -467,9 +470,9 @@ Format your response clearly with headers.`;
467
470
  /exit - Exit AGENT-K
468
471
 
469
472
  Keyboard shortcuts:
473
+ Shift+Tab - Cycle mode (normal/plan/auto)
470
474
  ↑/↓ - Browse command history
471
475
  Tab - Autocomplete commands
472
- Shift+Tab - Toggle auto-edit mode
473
476
  Esc - Cancel operation (when processing)
474
477
  Esc Esc - Exit (when idle)
475
478
  Ctrl+U - Clear input line`,
@@ -499,8 +502,52 @@ Ctrl+U - Clear input line`,
499
502
  setError(`Unknown command: /${command}`);
500
503
  }
501
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
+ };
502
544
  // Handle keyboard shortcuts
503
- 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
+ }
504
551
  // Escape key handling
505
552
  if (key.escape) {
506
553
  const now = Date.now();
@@ -537,30 +584,6 @@ Ctrl+U - Clear input line`,
537
584
  }
538
585
  }
539
586
  }
540
- // Shift+Tab to toggle auto-accept
541
- if (key.shift && key.tab) {
542
- if (autoAccept) {
543
- // Disable silently
544
- setAutoAccept(false);
545
- }
546
- else {
547
- // Show confirmation prompt
548
- setConfirmationState({
549
- message: 'Enable auto-accept for code edits?',
550
- options: [
551
- { label: 'Yes, enable auto-accept', value: 'yes' },
552
- { label: 'No, keep asking', value: 'no' },
553
- ],
554
- onSelect: (value) => {
555
- setConfirmationState(null);
556
- if (value === 'yes') {
557
- setAutoAccept(true);
558
- }
559
- },
560
- onCancel: () => setConfirmationState(null),
561
- });
562
- }
563
- }
564
587
  });
565
588
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: messages, children: (item) => {
566
589
  if ('isWelcome' in item && item.isWelcome) {
@@ -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);
@@ -3,7 +3,7 @@ import { AgentName } from './AgentPanel.js';
3
3
  type CouncilMode = 'solo' | 'council' | 'off';
4
4
  interface StatusBarProps {
5
5
  mode: 'dev' | 'ml';
6
- executionMode: 'plan' | 'auto';
6
+ executionMode: 'normal' | 'plan' | 'auto';
7
7
  tokens: number;
8
8
  startTime: Date;
9
9
  isProcessing?: boolean;
@@ -106,6 +106,6 @@ export const StatusBar = ({ mode, executionMode, tokens, startTime, isProcessing
106
106
  const leftBracket = isActive ? pulseBrackets[pulseFrame] : '[';
107
107
  const rightBracket = isActive ? pulseBrackets[(pulseFrame + 3) % pulseBrackets.length] === '<' ? '>' : pulseBrackets[(pulseFrame + 3) % pulseBrackets.length] === '{' ? '}' : pulseBrackets[(pulseFrame + 3) % pulseBrackets.length] === '(' ? ')' : ']' : ']';
108
108
  return (_jsxs(React.Fragment, { children: [_jsx(Text, { color: getAgentColor(agent), children: leftBracket }), _jsx(Text, { color: getAgentColor(agent), children: agentIcons[agent] }), _jsx(Text, { color: getAgentColor(agent), children: rightBracket }), i < modeAgents.length - 1 && _jsx(Text, { color: theme.dim, children: " " })] }, agent));
109
- })), _jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.dim, children: "? help" }), councilMode !== 'off' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.highlight, children: councilMode === 'council' ? 'COUNCIL' : 'SOLO' })] })), executionMode === 'auto' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.active, children: "AUTO-EXEC" })] })), autoAccept && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.active, children: "AUTO-EDIT" })] })), isProcessing && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.highlight, children: icons.spinner[spinnerFrame] })] })), elapsed && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.dim, children: elapsed })] }))] }), _jsxs(Box, { children: [showExitHint && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.dim, children: "Press Esc again to exit" }), _jsx(Text, { color: theme.border, children: " \u2502 " })] })), _jsxs(Text, { color: theme.accent, children: ["\u2191 ", formatTokens(tokens)] }), _jsx(Text, { color: theme.dim, children: " tokens " })] })] }));
109
+ })), _jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.dim, children: "? help" }), councilMode !== 'off' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.highlight, children: councilMode === 'council' ? 'COUNCIL' : 'SOLO' })] })), executionMode !== 'normal' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: executionMode === 'auto' ? theme.active : theme.accent, children: executionMode.toUpperCase() })] })), isProcessing && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.highlight, children: icons.spinner[spinnerFrame] })] })), elapsed && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: " \u2502 " }), _jsx(Text, { color: theme.dim, children: elapsed })] }))] }), _jsxs(Box, { children: [showExitHint && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.dim, children: "Press Esc again to exit" }), _jsx(Text, { color: theme.border, children: " \u2502 " })] })), _jsxs(Text, { color: theme.accent, children: ["\u2191 ", formatTokens(tokens)] }), _jsx(Text, { color: theme.dim, children: " tokens " })] })] }));
110
110
  };
111
111
  export default StatusBar;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentk8",
3
- "version": "2.3.4",
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",