wave-code 0.14.4 → 0.15.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.
Files changed (116) hide show
  1. package/dist/acp/agent.d.ts.map +1 -1
  2. package/dist/acp/agent.js +10 -0
  3. package/dist/components/BackgroundTaskManager.d.ts.map +1 -1
  4. package/dist/components/BackgroundTaskManager.js +17 -53
  5. package/dist/components/CommandSelector.d.ts.map +1 -1
  6. package/dist/components/CommandSelector.js +38 -28
  7. package/dist/components/ConfirmationSelector.d.ts.map +1 -1
  8. package/dist/components/ConfirmationSelector.js +18 -196
  9. package/dist/components/DiscoverView.d.ts.map +1 -1
  10. package/dist/components/DiscoverView.js +19 -11
  11. package/dist/components/FileSelector.d.ts.map +1 -1
  12. package/dist/components/FileSelector.js +29 -25
  13. package/dist/components/HelpView.d.ts.map +1 -1
  14. package/dist/components/HelpView.js +24 -28
  15. package/dist/components/HistorySearch.d.ts.map +1 -1
  16. package/dist/components/HistorySearch.js +26 -28
  17. package/dist/components/InputBox.d.ts.map +1 -1
  18. package/dist/components/InputBox.js +14 -6
  19. package/dist/components/InstalledView.d.ts.map +1 -1
  20. package/dist/components/InstalledView.js +19 -11
  21. package/dist/components/MarketplaceDetail.d.ts.map +1 -1
  22. package/dist/components/MarketplaceDetail.js +35 -16
  23. package/dist/components/MarketplaceView.d.ts.map +1 -1
  24. package/dist/components/MarketplaceView.js +21 -12
  25. package/dist/components/McpManager.d.ts.map +1 -1
  26. package/dist/components/McpManager.js +27 -46
  27. package/dist/components/ModelSelector.d.ts.map +1 -1
  28. package/dist/components/ModelSelector.js +27 -17
  29. package/dist/components/PluginDetail.d.ts.map +1 -1
  30. package/dist/components/PluginDetail.js +39 -26
  31. package/dist/components/RewindCommand.d.ts.map +1 -1
  32. package/dist/components/RewindCommand.js +27 -21
  33. package/dist/components/SessionSelector.d.ts.map +1 -1
  34. package/dist/components/SessionSelector.js +21 -16
  35. package/dist/components/StatusLine.d.ts.map +1 -1
  36. package/dist/components/StatusLine.js +5 -1
  37. package/dist/components/WorktreeExitPrompt.d.ts.map +1 -1
  38. package/dist/components/WorktreeExitPrompt.js +21 -12
  39. package/dist/contexts/useChat.d.ts +0 -1
  40. package/dist/contexts/useChat.d.ts.map +1 -1
  41. package/dist/contexts/useChat.js +13 -20
  42. package/dist/hooks/useInputManager.d.ts +5 -19
  43. package/dist/hooks/useInputManager.d.ts.map +1 -1
  44. package/dist/hooks/useInputManager.js +224 -79
  45. package/dist/managers/inputHandlers.d.ts +1 -1
  46. package/dist/managers/inputHandlers.d.ts.map +1 -1
  47. package/dist/managers/inputHandlers.js +3 -6
  48. package/dist/managers/inputReducer.d.ts +50 -4
  49. package/dist/managers/inputReducer.d.ts.map +1 -1
  50. package/dist/managers/inputReducer.js +519 -4
  51. package/dist/print-cli.d.ts.map +1 -1
  52. package/dist/print-cli.js +17 -9
  53. package/dist/reducers/backgroundTaskManagerReducer.d.ts +20 -0
  54. package/dist/reducers/backgroundTaskManagerReducer.d.ts.map +1 -1
  55. package/dist/reducers/backgroundTaskManagerReducer.js +83 -0
  56. package/dist/reducers/confirmationReducer.d.ts +11 -0
  57. package/dist/reducers/confirmationReducer.d.ts.map +1 -1
  58. package/dist/reducers/confirmationReducer.js +146 -0
  59. package/dist/reducers/helpSelectorReducer.d.ts +26 -0
  60. package/dist/reducers/helpSelectorReducer.d.ts.map +1 -0
  61. package/dist/reducers/helpSelectorReducer.js +52 -0
  62. package/dist/reducers/mcpManagerReducer.d.ts +22 -0
  63. package/dist/reducers/mcpManagerReducer.d.ts.map +1 -1
  64. package/dist/reducers/mcpManagerReducer.js +57 -0
  65. package/dist/reducers/pluginDetailReducer.d.ts +8 -0
  66. package/dist/reducers/pluginDetailReducer.d.ts.map +1 -1
  67. package/dist/reducers/pluginDetailReducer.js +32 -0
  68. package/dist/reducers/questionReducer.d.ts +21 -0
  69. package/dist/reducers/questionReducer.d.ts.map +1 -1
  70. package/dist/reducers/questionReducer.js +177 -0
  71. package/dist/reducers/rewindSelectorReducer.d.ts +22 -0
  72. package/dist/reducers/rewindSelectorReducer.d.ts.map +1 -0
  73. package/dist/reducers/rewindSelectorReducer.js +37 -0
  74. package/dist/reducers/selectorReducer.d.ts +22 -0
  75. package/dist/reducers/selectorReducer.d.ts.map +1 -0
  76. package/dist/reducers/selectorReducer.js +40 -0
  77. package/dist/utils/inputUtils.d.ts +18 -0
  78. package/dist/utils/inputUtils.d.ts.map +1 -0
  79. package/dist/utils/inputUtils.js +67 -0
  80. package/dist/utils/worktree.d.ts.map +1 -1
  81. package/dist/utils/worktree.js +1 -2
  82. package/package.json +2 -2
  83. package/src/acp/agent.ts +10 -0
  84. package/src/components/BackgroundTaskManager.tsx +19 -58
  85. package/src/components/CommandSelector.tsx +53 -44
  86. package/src/components/ConfirmationSelector.tsx +18 -202
  87. package/src/components/DiscoverView.tsx +21 -11
  88. package/src/components/FileSelector.tsx +40 -35
  89. package/src/components/HelpView.tsx +37 -43
  90. package/src/components/HistorySearch.tsx +29 -36
  91. package/src/components/InputBox.tsx +14 -7
  92. package/src/components/InstalledView.tsx +21 -11
  93. package/src/components/MarketplaceDetail.tsx +48 -24
  94. package/src/components/MarketplaceView.tsx +25 -10
  95. package/src/components/McpManager.tsx +29 -54
  96. package/src/components/ModelSelector.tsx +30 -23
  97. package/src/components/PluginDetail.tsx +50 -27
  98. package/src/components/RewindCommand.tsx +38 -32
  99. package/src/components/SessionSelector.tsx +23 -20
  100. package/src/components/StatusLine.tsx +10 -1
  101. package/src/components/WorktreeExitPrompt.tsx +23 -13
  102. package/src/contexts/useChat.tsx +13 -31
  103. package/src/hooks/useInputManager.ts +275 -141
  104. package/src/managers/inputHandlers.ts +1 -6
  105. package/src/managers/inputReducer.ts +680 -7
  106. package/src/print-cli.ts +15 -11
  107. package/src/reducers/backgroundTaskManagerReducer.ts +110 -1
  108. package/src/reducers/confirmationReducer.ts +173 -1
  109. package/src/reducers/helpSelectorReducer.ts +77 -0
  110. package/src/reducers/mcpManagerReducer.ts +82 -1
  111. package/src/reducers/pluginDetailReducer.ts +42 -1
  112. package/src/reducers/questionReducer.ts +204 -0
  113. package/src/reducers/rewindSelectorReducer.ts +54 -0
  114. package/src/reducers/selectorReducer.ts +57 -0
  115. package/src/utils/inputUtils.ts +94 -0
  116. package/src/utils/worktree.ts +1 -7
@@ -1,3 +1,4 @@
1
+ import { getAtSelectorPosition, getSlashSelectorPosition, getWordEnd, SELECTOR_TRIGGERS, getProjectedState, } from "../utils/inputUtils.js";
1
2
  export const initialState = {
2
3
  inputText: "",
3
4
  cursorPosition: 0,
@@ -22,7 +23,6 @@ export const initialState = {
22
23
  showPluginManager: false,
23
24
  showModelSelector: false,
24
25
  permissionMode: "default",
25
- allowBypassInCycle: false,
26
26
  selectorJustUsed: false,
27
27
  isPasting: false,
28
28
  pasteBuffer: "",
@@ -37,6 +37,7 @@ export const initialState = {
37
37
  question: "",
38
38
  isLoading: false,
39
39
  },
40
+ pendingEffect: null,
40
41
  };
41
42
  export function inputReducer(state, action) {
42
43
  switch (action.type) {
@@ -208,8 +209,6 @@ export function inputReducer(state, action) {
208
209
  };
209
210
  case "SET_PERMISSION_MODE":
210
211
  return { ...state, permissionMode: action.payload };
211
- case "SET_ALLOW_BYPASS_IN_CYCLE":
212
- return { ...state, allowBypassInCycle: action.payload };
213
212
  case "SET_SELECTOR_JUST_USED":
214
213
  return { ...state, selectorJustUsed: action.payload };
215
214
  case "INSERT_TEXT_WITH_PLACEHOLDER": {
@@ -226,7 +225,7 @@ export function inputReducer(state, action) {
226
225
  const afterCursor = state.inputText.substring(state.cursorPosition);
227
226
  const newText = beforeCursor + textToInsert + afterCursor;
228
227
  const newCursorPosition = state.cursorPosition + textToInsert.length;
229
- return {
228
+ const newState = {
230
229
  ...state,
231
230
  inputText: newText,
232
231
  cursorPosition: newCursorPosition,
@@ -234,6 +233,25 @@ export function inputReducer(state, action) {
234
233
  longTextMap: newLongTextMap,
235
234
  historyIndex: -1,
236
235
  };
236
+ // Sync selectors
237
+ const atPos = getAtSelectorPosition(newText, newCursorPosition);
238
+ if (atPos !== -1 && !newState.showFileSelector) {
239
+ newState.showFileSelector = true;
240
+ newState.atPosition = atPos;
241
+ newState.isFileSearching = true;
242
+ }
243
+ const slashPos = getSlashSelectorPosition(newText, newCursorPosition);
244
+ if (slashPos !== -1 && !newState.showCommandSelector) {
245
+ newState.showCommandSelector = true;
246
+ newState.slashPosition = slashPos;
247
+ }
248
+ if (newState.showFileSelector && newState.atPosition >= 0) {
249
+ newState.fileSearchQuery = newText.substring(newState.atPosition + 1, newCursorPosition);
250
+ }
251
+ else if (newState.showCommandSelector && newState.slashPosition >= 0) {
252
+ newState.commandSearchQuery = newText.substring(newState.slashPosition + 1, newCursorPosition);
253
+ }
254
+ return newState;
237
255
  }
238
256
  case "CLEAR_LONG_TEXT_MAP":
239
257
  return { ...state, longTextMap: {} };
@@ -357,6 +375,69 @@ export function inputReducer(state, action) {
357
375
  selectorJustUsed: true,
358
376
  };
359
377
  }
378
+ case "SELECT_COMMAND": {
379
+ const command = action.payload;
380
+ if (state.slashPosition >= 0) {
381
+ const wordEnd = getWordEnd(state.inputText, state.slashPosition);
382
+ const beforeSlash = state.inputText.substring(0, state.slashPosition);
383
+ const afterWord = state.inputText.substring(wordEnd);
384
+ const newInput = beforeSlash + afterWord;
385
+ const newCursorPosition = beforeSlash.length;
386
+ return {
387
+ ...state,
388
+ inputText: newInput,
389
+ cursorPosition: newCursorPosition,
390
+ showCommandSelector: false,
391
+ slashPosition: -1,
392
+ commandSearchQuery: "",
393
+ selectorJustUsed: true,
394
+ pendingEffect: { type: "EXECUTE_COMMAND", command },
395
+ };
396
+ }
397
+ return state;
398
+ }
399
+ case "INSERT_COMMAND": {
400
+ const command = action.payload;
401
+ if (state.slashPosition >= 0) {
402
+ const wordEnd = getWordEnd(state.inputText, state.slashPosition);
403
+ const beforeSlash = state.inputText.substring(0, state.slashPosition);
404
+ const afterWord = state.inputText.substring(wordEnd);
405
+ const newInput = beforeSlash + `/${command} ` + afterWord;
406
+ const newCursorPosition = beforeSlash.length + command.length + 2;
407
+ return {
408
+ ...state,
409
+ inputText: newInput,
410
+ cursorPosition: newCursorPosition,
411
+ showCommandSelector: false,
412
+ slashPosition: -1,
413
+ commandSearchQuery: "",
414
+ selectorJustUsed: true,
415
+ };
416
+ }
417
+ return state;
418
+ }
419
+ case "SELECT_FILE": {
420
+ const filePath = action.payload;
421
+ if (state.atPosition >= 0) {
422
+ const wordEnd = getWordEnd(state.inputText, state.atPosition);
423
+ const beforeAt = state.inputText.substring(0, state.atPosition);
424
+ const afterWord = state.inputText.substring(wordEnd);
425
+ const newInput = beforeAt + `@${filePath} ` + afterWord;
426
+ const newCursorPosition = beforeAt.length + filePath.length + 2;
427
+ return {
428
+ ...state,
429
+ inputText: newInput,
430
+ cursorPosition: newCursorPosition,
431
+ showFileSelector: false,
432
+ atPosition: -1,
433
+ fileSearchQuery: "",
434
+ filteredFiles: [],
435
+ selectorJustUsed: true,
436
+ isFileSearching: false,
437
+ };
438
+ }
439
+ return state;
440
+ }
360
441
  case "RESET_HISTORY_NAVIGATION":
361
442
  return {
362
443
  ...state,
@@ -365,6 +446,440 @@ export function inputReducer(state, action) {
365
446
  originalInputText: "",
366
447
  originalLongTextMap: {},
367
448
  };
449
+ case "CLEAR_PENDING_EFFECT":
450
+ return { ...state, pendingEffect: null };
451
+ case "HANDLE_KEY": {
452
+ const { input, key } = action.payload;
453
+ if (state.selectorJustUsed) {
454
+ return state;
455
+ }
456
+ // 1. BTW State Handling
457
+ if (state.btwState.isActive) {
458
+ if (key.escape) {
459
+ return {
460
+ ...state,
461
+ btwState: {
462
+ isActive: false,
463
+ question: "",
464
+ answer: undefined,
465
+ isLoading: false,
466
+ },
467
+ };
468
+ }
469
+ if (key.return) {
470
+ const question = state.inputText.trim();
471
+ if (question && !state.btwState.isLoading) {
472
+ return {
473
+ ...state,
474
+ inputText: "",
475
+ cursorPosition: 0,
476
+ btwState: {
477
+ ...state.btwState,
478
+ question,
479
+ isLoading: true,
480
+ answer: undefined,
481
+ },
482
+ pendingEffect: { type: "ASK_BTW", question },
483
+ };
484
+ }
485
+ return state;
486
+ }
487
+ }
488
+ // 2. Escape Handling
489
+ if (key.escape) {
490
+ if (state.showFileSelector) {
491
+ return {
492
+ ...state,
493
+ showFileSelector: false,
494
+ atPosition: -1,
495
+ fileSearchQuery: "",
496
+ filteredFiles: [],
497
+ selectorJustUsed: true,
498
+ isFileSearching: false,
499
+ };
500
+ }
501
+ if (state.showCommandSelector) {
502
+ return {
503
+ ...state,
504
+ showCommandSelector: false,
505
+ slashPosition: -1,
506
+ commandSearchQuery: "",
507
+ selectorJustUsed: true,
508
+ };
509
+ }
510
+ if (state.showHistorySearch) {
511
+ return {
512
+ ...state,
513
+ showHistorySearch: false,
514
+ historySearchQuery: "",
515
+ selectorJustUsed: true,
516
+ };
517
+ }
518
+ if (state.historyIndex !== -1) {
519
+ return {
520
+ ...state,
521
+ historyIndex: -1,
522
+ inputText: state.originalInputText,
523
+ longTextMap: state.originalLongTextMap,
524
+ cursorPosition: state.originalInputText.length,
525
+ originalInputText: "",
526
+ originalLongTextMap: {},
527
+ };
528
+ }
529
+ if (!(state.showBackgroundTaskManager ||
530
+ state.showMcpManager ||
531
+ state.showRewindManager ||
532
+ state.showHelp ||
533
+ state.showStatusCommand ||
534
+ state.showPluginManager ||
535
+ state.showModelSelector)) {
536
+ return { ...state, pendingEffect: { type: "ABORT_MESSAGE" } };
537
+ }
538
+ return state;
539
+ }
540
+ // 3. Special Shortcuts
541
+ if (key.tab && key.shift) {
542
+ const modes = [
543
+ "default",
544
+ "acceptEdits",
545
+ "plan",
546
+ "bypassPermissions",
547
+ ];
548
+ const currentIndex = modes.indexOf(state.permissionMode);
549
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % modes.length;
550
+ const nextMode = modes[nextIndex];
551
+ return {
552
+ ...state,
553
+ permissionMode: nextMode,
554
+ pendingEffect: { type: "PERMISSION_MODE_CHANGE", mode: nextMode },
555
+ };
556
+ }
557
+ if (key.ctrl && input === "v") {
558
+ return { ...state, pendingEffect: { type: "PASTE_IMAGE" } };
559
+ }
560
+ if (key.ctrl && input === "r") {
561
+ return {
562
+ ...state,
563
+ showHistorySearch: true,
564
+ historySearchQuery: "",
565
+ };
566
+ }
567
+ if (key.ctrl && input === "b") {
568
+ return {
569
+ ...state,
570
+ pendingEffect: { type: "BACKGROUND_CURRENT_TASK" },
571
+ };
572
+ }
573
+ // 4. History Navigation
574
+ if (key.upArrow &&
575
+ !state.showFileSelector &&
576
+ !state.showCommandSelector) {
577
+ if (state.history.length === 0) {
578
+ return { ...state, pendingEffect: { type: "FETCH_HISTORY" } };
579
+ }
580
+ // If history is already loaded, NAVIGATE_HISTORY logic follows
581
+ let newIndex = state.historyIndex;
582
+ let newOriginalInputText = state.originalInputText;
583
+ let newOriginalLongTextMap = state.originalLongTextMap;
584
+ if (newIndex === -1) {
585
+ newOriginalInputText = state.inputText;
586
+ newOriginalLongTextMap = state.longTextMap;
587
+ }
588
+ newIndex = Math.min(state.history.length - 1, newIndex + 1);
589
+ const entry = state.history[newIndex];
590
+ return {
591
+ ...state,
592
+ historyIndex: newIndex,
593
+ inputText: entry.prompt,
594
+ longTextMap: entry.longTextMap || {},
595
+ cursorPosition: entry.prompt.length,
596
+ originalInputText: newOriginalInputText,
597
+ originalLongTextMap: newOriginalLongTextMap,
598
+ };
599
+ }
600
+ if (key.downArrow &&
601
+ !state.showFileSelector &&
602
+ !state.showCommandSelector) {
603
+ if (state.historyIndex === -1)
604
+ return state;
605
+ const newIndex = state.historyIndex - 1;
606
+ if (newIndex === -1) {
607
+ return {
608
+ ...state,
609
+ historyIndex: -1,
610
+ inputText: state.originalInputText,
611
+ longTextMap: state.originalLongTextMap,
612
+ cursorPosition: state.originalInputText.length,
613
+ originalInputText: "",
614
+ originalLongTextMap: {},
615
+ };
616
+ }
617
+ else {
618
+ const entry = state.history[newIndex];
619
+ return {
620
+ ...state,
621
+ historyIndex: newIndex,
622
+ inputText: entry.prompt,
623
+ longTextMap: entry.longTextMap || {},
624
+ cursorPosition: entry.prompt.length,
625
+ };
626
+ }
627
+ }
628
+ // 5. Active Selector Handling (History Search, File, Command)
629
+ if (state.showHistorySearch) {
630
+ if (key.backspace || key.delete) {
631
+ return {
632
+ ...state,
633
+ historySearchQuery: state.historySearchQuery.slice(0, -1),
634
+ };
635
+ }
636
+ if (input && !key.ctrl && !key.meta && !key.return && !key.tab) {
637
+ return {
638
+ ...state,
639
+ historySearchQuery: state.historySearchQuery + input,
640
+ };
641
+ }
642
+ return state;
643
+ }
644
+ if (state.showFileSelector || state.showCommandSelector) {
645
+ if (key.backspace || key.delete) {
646
+ if (state.cursorPosition > 0) {
647
+ const newCursorPosition = state.cursorPosition - 1;
648
+ const beforeCursor = state.inputText.substring(0, state.cursorPosition - 1);
649
+ const afterCursor = state.inputText.substring(state.cursorPosition);
650
+ const newInputText = beforeCursor + afterCursor;
651
+ const newState = {
652
+ ...state,
653
+ inputText: newInputText,
654
+ cursorPosition: newCursorPosition,
655
+ historyIndex: -1,
656
+ };
657
+ // checkForAtDeletion
658
+ if (newState.showFileSelector &&
659
+ newCursorPosition <= newState.atPosition) {
660
+ newState.showFileSelector = false;
661
+ newState.atPosition = -1;
662
+ newState.fileSearchQuery = "";
663
+ }
664
+ // checkForSlashDeletion
665
+ if (newState.showCommandSelector &&
666
+ newCursorPosition <= newState.slashPosition) {
667
+ newState.showCommandSelector = false;
668
+ newState.slashPosition = -1;
669
+ newState.commandSearchQuery = "";
670
+ }
671
+ // Update queries
672
+ if (newState.showFileSelector && newState.atPosition >= 0) {
673
+ newState.fileSearchQuery = newInputText.substring(newState.atPosition + 1, newCursorPosition);
674
+ }
675
+ if (newState.showCommandSelector && newState.slashPosition >= 0) {
676
+ newState.commandSearchQuery = newInputText.substring(newState.slashPosition + 1, newCursorPosition);
677
+ }
678
+ return newState;
679
+ }
680
+ }
681
+ if (key.leftArrow || key.rightArrow) {
682
+ const delta = key.leftArrow ? -1 : 1;
683
+ const newCursorPosition = Math.max(0, Math.min(state.inputText.length, state.cursorPosition + delta));
684
+ const newState = { ...state, cursorPosition: newCursorPosition };
685
+ if (newState.showFileSelector &&
686
+ newCursorPosition <= newState.atPosition) {
687
+ newState.showFileSelector = false;
688
+ newState.atPosition = -1;
689
+ }
690
+ if (newState.showCommandSelector &&
691
+ newCursorPosition <= newState.slashPosition) {
692
+ newState.showCommandSelector = false;
693
+ newState.slashPosition = -1;
694
+ }
695
+ return newState;
696
+ }
697
+ if (input === " ") {
698
+ return {
699
+ ...state,
700
+ showFileSelector: false,
701
+ atPosition: -1,
702
+ showCommandSelector: false,
703
+ slashPosition: -1,
704
+ inputText: state.inputText.substring(0, state.cursorPosition) +
705
+ " " +
706
+ state.inputText.substring(state.cursorPosition),
707
+ cursorPosition: state.cursorPosition + 1,
708
+ };
709
+ }
710
+ if (key.return || key.tab || key.upArrow || key.downArrow) {
711
+ return state;
712
+ }
713
+ }
714
+ // 6. Return / Submit
715
+ if (key.return) {
716
+ if (state.inputText.trim()) {
717
+ const imageRegex = /\[Image #(\d+)\]/g;
718
+ const matches = [...state.inputText.matchAll(imageRegex)];
719
+ const referencedImages = matches
720
+ .map((match) => {
721
+ const imageId = parseInt(match[1], 10);
722
+ return state.attachedImages.find((img) => img.id === imageId);
723
+ })
724
+ .filter((img) => img !== undefined)
725
+ .map((img) => ({ path: img.path, mimeType: img.mimeType }));
726
+ const contentWithPlaceholders = state.inputText
727
+ .replace(imageRegex, "")
728
+ .trim();
729
+ if (contentWithPlaceholders === "/btw" ||
730
+ contentWithPlaceholders.startsWith("/btw ")) {
731
+ const question = contentWithPlaceholders.startsWith("/btw ")
732
+ ? contentWithPlaceholders.substring(5).trim()
733
+ : "";
734
+ return {
735
+ ...state,
736
+ inputText: "",
737
+ cursorPosition: 0,
738
+ historyIndex: -1,
739
+ longTextMap: {},
740
+ btwState: {
741
+ isActive: true,
742
+ question,
743
+ isLoading: question !== "",
744
+ answer: undefined,
745
+ },
746
+ pendingEffect: question ? { type: "ASK_BTW", question } : null,
747
+ };
748
+ }
749
+ return {
750
+ ...state,
751
+ inputText: "",
752
+ cursorPosition: 0,
753
+ historyIndex: -1,
754
+ longTextMap: {},
755
+ pendingEffect: {
756
+ type: "SEND_MESSAGE",
757
+ content: contentWithPlaceholders,
758
+ images: referencedImages.length > 0 ? referencedImages : undefined,
759
+ longTextMap: state.longTextMap,
760
+ },
761
+ };
762
+ }
763
+ return state;
764
+ }
765
+ // 7. Regular Input
766
+ if (input &&
767
+ !key.ctrl &&
768
+ !("alt" in key && key.alt) &&
769
+ !key.meta &&
770
+ !key.return &&
771
+ !key.escape &&
772
+ !key.leftArrow &&
773
+ !key.rightArrow &&
774
+ !("home" in key && key.home) &&
775
+ !("end" in key && key.end)) {
776
+ const isPasteOperation = input.length > 1 || input.includes("\n") || input.includes("\r");
777
+ if (isPasteOperation) {
778
+ const isNewPaste = !state.pasteBuffer;
779
+ return {
780
+ ...state,
781
+ isPasting: true,
782
+ pasteBuffer: state.pasteBuffer + input,
783
+ initialPasteCursorPosition: isNewPaste
784
+ ? state.cursorPosition
785
+ : state.initialPasteCursorPosition,
786
+ };
787
+ }
788
+ else {
789
+ let char = input;
790
+ if (char === "!" && state.cursorPosition === 0) {
791
+ char = "!";
792
+ }
793
+ const { newInputText, newCursorPosition } = getProjectedState(state.inputText, state.cursorPosition, char);
794
+ const newState = {
795
+ ...state,
796
+ inputText: newInputText,
797
+ cursorPosition: newCursorPosition,
798
+ historyIndex: -1,
799
+ };
800
+ // Selector Activation
801
+ const trigger = SELECTOR_TRIGGERS.find((t) => t.shouldActivate(char, newCursorPosition, newInputText, state.showFileSelector));
802
+ if (trigger) {
803
+ if (trigger.type === "ACTIVATE_FILE_SELECTOR") {
804
+ newState.showFileSelector = true;
805
+ newState.atPosition = newCursorPosition - 1;
806
+ newState.fileSearchQuery = "";
807
+ newState.isFileSearching = true;
808
+ }
809
+ else if (trigger.type === "ACTIVATE_COMMAND_SELECTOR") {
810
+ newState.showCommandSelector = true;
811
+ newState.slashPosition = newCursorPosition - 1;
812
+ newState.commandSearchQuery = "";
813
+ }
814
+ }
815
+ else {
816
+ const atPos = getAtSelectorPosition(newInputText, newCursorPosition);
817
+ if (atPos !== -1 && !state.showFileSelector) {
818
+ newState.showFileSelector = true;
819
+ newState.atPosition = atPos;
820
+ newState.fileSearchQuery = "";
821
+ newState.isFileSearching = true;
822
+ }
823
+ const slashPos = getSlashSelectorPosition(newInputText, newCursorPosition);
824
+ if (slashPos !== -1 && !state.showCommandSelector) {
825
+ newState.showCommandSelector = true;
826
+ newState.slashPosition = slashPos;
827
+ newState.commandSearchQuery = "";
828
+ }
829
+ }
830
+ // Update queries
831
+ if (newState.showFileSelector && newState.atPosition >= 0) {
832
+ newState.fileSearchQuery = newInputText.substring(newState.atPosition + 1, newCursorPosition);
833
+ }
834
+ if (newState.showCommandSelector && newState.slashPosition >= 0) {
835
+ newState.commandSearchQuery = newInputText.substring(newState.slashPosition + 1, newCursorPosition);
836
+ }
837
+ return newState;
838
+ }
839
+ }
840
+ // 8. Backspace / Delete (Normal Mode)
841
+ if (key.backspace || key.delete) {
842
+ if (state.cursorPosition > 0) {
843
+ const newCursorPosition = state.cursorPosition - 1;
844
+ const beforeCursor = state.inputText.substring(0, state.cursorPosition - 1);
845
+ const afterCursor = state.inputText.substring(state.cursorPosition);
846
+ const newInputText = beforeCursor + afterCursor;
847
+ const newState = {
848
+ ...state,
849
+ inputText: newInputText,
850
+ cursorPosition: newCursorPosition,
851
+ historyIndex: -1,
852
+ };
853
+ // Reactivate selectors if cursor is within word
854
+ const atPos = getAtSelectorPosition(newInputText, newCursorPosition);
855
+ if (atPos !== -1 && !state.showFileSelector) {
856
+ newState.showFileSelector = true;
857
+ newState.atPosition = atPos;
858
+ newState.isFileSearching = true;
859
+ }
860
+ const slashPos = getSlashSelectorPosition(newInputText, newCursorPosition);
861
+ if (slashPos !== -1 && !state.showCommandSelector) {
862
+ newState.showCommandSelector = true;
863
+ newState.slashPosition = slashPos;
864
+ }
865
+ // Update queries
866
+ if (newState.showFileSelector && newState.atPosition >= 0) {
867
+ newState.fileSearchQuery = newInputText.substring(newState.atPosition + 1, newCursorPosition);
868
+ }
869
+ if (newState.showCommandSelector && newState.slashPosition >= 0) {
870
+ newState.commandSearchQuery = newInputText.substring(newState.slashPosition + 1, newCursorPosition);
871
+ }
872
+ return newState;
873
+ }
874
+ }
875
+ // 9. Cursor Movement (Normal Mode)
876
+ if (key.leftArrow || key.rightArrow) {
877
+ const delta = key.leftArrow ? -1 : 1;
878
+ const newCursorPosition = Math.max(0, Math.min(state.inputText.length, state.cursorPosition + delta));
879
+ return { ...state, cursorPosition: newCursorPosition };
880
+ }
881
+ return state;
882
+ }
368
883
  case "SET_BTW_STATE":
369
884
  return {
370
885
  ...state,
@@ -1 +1 @@
1
- {"version":3,"file":"print-cli.d.ts","sourceRoot":"","sources":["../src/print-cli.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAgBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA4M3E"}
1
+ {"version":3,"file":"print-cli.d.ts","sourceRoot":"","sources":["../src/print-cli.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAgBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgN3E"}
package/dist/print-cli.js CHANGED
@@ -32,18 +32,22 @@ export async function startPrintCli(options) {
32
32
  isReasoning = false;
33
33
  isContent = false;
34
34
  // Assistant message started - no content to output yet
35
- process.stdout.write("\n");
36
35
  },
37
36
  onAssistantReasoningUpdated: (chunk) => {
38
37
  if (!isReasoning) {
39
- process.stdout.write("šŸ’­ Reasoning:\n");
38
+ process.stdout.write("\nšŸ’­ Reasoning:\n");
40
39
  isReasoning = true;
41
40
  }
42
41
  process.stdout.write(chunk);
43
42
  },
44
43
  onAssistantContentUpdated: (chunk) => {
45
- if (isReasoning && !isContent) {
46
- process.stdout.write("\n\nšŸ“ Response:\n");
44
+ if (!isContent) {
45
+ if (isReasoning) {
46
+ process.stdout.write("\n\nšŸ“ Response:\n");
47
+ }
48
+ else {
49
+ process.stdout.write("\n");
50
+ }
47
51
  isContent = true;
48
52
  }
49
53
  // FR-001: Stream content updates for real-time display - output only the new chunk
@@ -53,19 +57,22 @@ export async function startPrintCli(options) {
53
57
  onSubagentAssistantMessageAdded: (subagentId) => {
54
58
  subagentReasoningStates.set(subagentId, false);
55
59
  subagentContentStates.set(subagentId, false);
56
- process.stdout.write("\n ");
57
60
  },
58
61
  onSubagentAssistantReasoningUpdated: (subagentId, chunk) => {
59
62
  if (!subagentReasoningStates.get(subagentId)) {
60
- process.stdout.write("šŸ’­ Reasoning: ");
63
+ process.stdout.write("\n šŸ’­ Reasoning: ");
61
64
  subagentReasoningStates.set(subagentId, true);
62
65
  }
63
66
  process.stdout.write(chunk);
64
67
  },
65
68
  onSubagentAssistantContentUpdated: (subagentId, chunk) => {
66
- if (subagentReasoningStates.get(subagentId) &&
67
- !subagentContentStates.get(subagentId)) {
68
- process.stdout.write("\n šŸ“ Response: ");
69
+ if (!subagentContentStates.get(subagentId)) {
70
+ if (subagentReasoningStates.get(subagentId)) {
71
+ process.stdout.write("\n šŸ“ Response: ");
72
+ }
73
+ else {
74
+ process.stdout.write("\n ");
75
+ }
69
76
  subagentContentStates.set(subagentId, true);
70
77
  }
71
78
  process.stdout.write(chunk);
@@ -108,6 +115,7 @@ export async function startPrintCli(options) {
108
115
  // Send message if provided and not empty
109
116
  if (typeof message === "string" && message.trim() !== "") {
110
117
  await agent.sendMessage(message);
118
+ process.stdout.write("\n");
111
119
  }
112
120
  // Display usage summary before exit
113
121
  if (showStats) {