wave-code 1.0.10 → 1.1.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.
- package/bin/wave-code.js +8 -2
- package/dist/bundle/wave.mjs +3207 -0
- package/package.json +24 -25
- package/src/commands/update.ts +2 -7
- package/src/components/App.tsx +3 -7
- package/src/components/BtwDisplay.tsx +10 -1
- package/src/components/ChatInterface.tsx +21 -52
- package/src/components/ConfirmationDetails.tsx +144 -37
- package/src/components/DiffDisplay.tsx +335 -301
- package/src/components/InputBox.tsx +3 -1
- package/src/components/LoadingIndicator.tsx +16 -2
- package/src/components/MessageBlockItem.tsx +2 -4
- package/src/components/MessageList.tsx +75 -14
- package/src/components/ReasoningDisplay.tsx +2 -4
- package/src/components/SessionSelector.tsx +82 -11
- package/src/components/StatusCommand.tsx +2 -9
- package/src/components/ToolDisplay.tsx +2 -4
- package/src/contexts/useChat.tsx +156 -335
- package/src/daemon/commands.ts +57 -27
- package/src/daemon/jsonRpcClient.ts +1 -1
- package/src/daemon/socketClient.ts +2 -2
- package/src/hooks/useInputManager.ts +1 -1
- package/src/index.ts +57 -10
- package/src/managers/inputReducer.ts +186 -104
- package/src/print-cli.ts +21 -17
- package/src/reducers/selectorReducer.ts +10 -0
- package/src/session-selector-cli.tsx +269 -28
- package/src/stdio/agentBridge.ts +22 -21
- package/src/stdio/daemonServer.ts +3 -1
- package/src/utils/clipboard.ts +21 -0
- package/src/utils/highlightUtils.ts +46 -1
- package/src/utils/readPackageJson.ts +29 -0
- package/src/utils/streamingText.ts +11 -0
- package/src/utils/worktree.ts +191 -43
- package/dist/cli.d.ts +0 -6
- package/dist/cli.js +0 -53
- package/dist/commands/plugin/disable.d.ts +0 -5
- package/dist/commands/plugin/disable.js +0 -15
- package/dist/commands/plugin/enable.d.ts +0 -5
- package/dist/commands/plugin/enable.js +0 -15
- package/dist/commands/plugin/install.d.ts +0 -5
- package/dist/commands/plugin/install.js +0 -21
- package/dist/commands/plugin/list.d.ts +0 -1
- package/dist/commands/plugin/list.js +0 -31
- package/dist/commands/plugin/marketplace.d.ts +0 -10
- package/dist/commands/plugin/marketplace.js +0 -90
- package/dist/commands/plugin/uninstall.d.ts +0 -3
- package/dist/commands/plugin/uninstall.js +0 -16
- package/dist/commands/plugin/update.d.ts +0 -3
- package/dist/commands/plugin/update.js +0 -15
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.js +0 -97
- package/dist/components/AgentsManager.d.ts +0 -7
- package/dist/components/AgentsManager.js +0 -109
- package/dist/components/App.d.ts +0 -9
- package/dist/components/App.js +0 -76
- package/dist/components/BackgroundTaskManager.d.ts +0 -5
- package/dist/components/BackgroundTaskManager.js +0 -99
- package/dist/components/BangDisplay.d.ts +0 -8
- package/dist/components/BangDisplay.js +0 -17
- package/dist/components/BtwDisplay.d.ts +0 -7
- package/dist/components/BtwDisplay.js +0 -19
- package/dist/components/ChatInterface.d.ts +0 -2
- package/dist/components/ChatInterface.js +0 -61
- package/dist/components/CommandSelector.d.ts +0 -10
- package/dist/components/CommandSelector.js +0 -66
- package/dist/components/CompactDisplay.d.ts +0 -8
- package/dist/components/CompactDisplay.js +0 -13
- package/dist/components/ConfirmationDetails.d.ts +0 -9
- package/dist/components/ConfirmationDetails.js +0 -45
- package/dist/components/ConfirmationSelector.d.ts +0 -13
- package/dist/components/ConfirmationSelector.js +0 -127
- package/dist/components/DiffDisplay.d.ts +0 -8
- package/dist/components/DiffDisplay.js +0 -201
- package/dist/components/DiscoverView.d.ts +0 -2
- package/dist/components/DiscoverView.js +0 -37
- package/dist/components/FileSelector.d.ts +0 -11
- package/dist/components/FileSelector.js +0 -50
- package/dist/components/HelpView.d.ts +0 -7
- package/dist/components/HelpView.js +0 -74
- package/dist/components/HistorySearch.d.ts +0 -8
- package/dist/components/HistorySearch.js +0 -66
- package/dist/components/InputBox.d.ts +0 -24
- package/dist/components/InputBox.js +0 -149
- package/dist/components/InstalledView.d.ts +0 -2
- package/dist/components/InstalledView.js +0 -45
- package/dist/components/LoadingIndicator.d.ts +0 -10
- package/dist/components/LoadingIndicator.js +0 -6
- package/dist/components/LoginCommand.d.ts +0 -5
- package/dist/components/LoginCommand.js +0 -153
- package/dist/components/Markdown.d.ts +0 -5
- package/dist/components/Markdown.js +0 -127
- package/dist/components/MarketplaceAddForm.d.ts +0 -2
- package/dist/components/MarketplaceAddForm.js +0 -55
- package/dist/components/MarketplaceDetail.d.ts +0 -2
- package/dist/components/MarketplaceDetail.js +0 -74
- package/dist/components/MarketplaceList.d.ts +0 -8
- package/dist/components/MarketplaceList.js +0 -17
- package/dist/components/MarketplaceView.d.ts +0 -2
- package/dist/components/MarketplaceView.js +0 -41
- package/dist/components/McpManager.d.ts +0 -9
- package/dist/components/McpManager.js +0 -88
- package/dist/components/MessageBlockItem.d.ts +0 -8
- package/dist/components/MessageBlockItem.js +0 -15
- package/dist/components/MessageList.d.ts +0 -10
- package/dist/components/MessageList.js +0 -80
- package/dist/components/ModelSelector.d.ts +0 -8
- package/dist/components/ModelSelector.js +0 -45
- package/dist/components/Notifications.d.ts +0 -7
- package/dist/components/Notifications.js +0 -9
- package/dist/components/PlanDisplay.d.ts +0 -7
- package/dist/components/PlanDisplay.js +0 -6
- package/dist/components/PluginDetail.d.ts +0 -2
- package/dist/components/PluginDetail.js +0 -87
- package/dist/components/PluginList.d.ts +0 -13
- package/dist/components/PluginList.js +0 -15
- package/dist/components/PluginManagerShell.d.ts +0 -6
- package/dist/components/PluginManagerShell.js +0 -92
- package/dist/components/PluginManagerTypes.d.ts +0 -35
- package/dist/components/PluginManagerTypes.js +0 -1
- package/dist/components/QueuedMessageList.d.ts +0 -2
- package/dist/components/QueuedMessageList.js +0 -18
- package/dist/components/ReasoningDisplay.d.ts +0 -8
- package/dist/components/ReasoningDisplay.js +0 -13
- package/dist/components/RewindCommand.d.ts +0 -12
- package/dist/components/RewindCommand.js +0 -78
- package/dist/components/SessionSelector.d.ts +0 -12
- package/dist/components/SessionSelector.js +0 -47
- package/dist/components/StatusCommand.d.ts +0 -5
- package/dist/components/StatusCommand.js +0 -28
- package/dist/components/StatusLine.d.ts +0 -6
- package/dist/components/StatusLine.js +0 -9
- package/dist/components/TaskList.d.ts +0 -5
- package/dist/components/TaskList.js +0 -197
- package/dist/components/TaskNotificationMessage.d.ts +0 -5
- package/dist/components/TaskNotificationMessage.js +0 -12
- package/dist/components/ToolDisplay.d.ts +0 -9
- package/dist/components/ToolDisplay.js +0 -55
- package/dist/components/WorkflowManager.d.ts +0 -5
- package/dist/components/WorkflowManager.js +0 -102
- package/dist/components/WorktreeExitPrompt.d.ts +0 -12
- package/dist/components/WorktreeExitPrompt.js +0 -35
- package/dist/constants/commands.d.ts +0 -2
- package/dist/constants/commands.js +0 -92
- package/dist/contexts/PluginManagerContext.d.ts +0 -3
- package/dist/contexts/PluginManagerContext.js +0 -9
- package/dist/contexts/useAppConfig.d.ts +0 -10
- package/dist/contexts/useAppConfig.js +0 -13
- package/dist/contexts/useChat.d.ts +0 -101
- package/dist/contexts/useChat.js +0 -993
- package/dist/contracts/status.d.ts +0 -7
- package/dist/contracts/status.js +0 -1
- package/dist/daemon/commands.d.ts +0 -49
- package/dist/daemon/commands.js +0 -341
- package/dist/daemon/jsonRpcClient.d.ts +0 -38
- package/dist/daemon/jsonRpcClient.js +0 -129
- package/dist/daemon/socketClient.d.ts +0 -13
- package/dist/daemon/socketClient.js +0 -26
- package/dist/daemon-cli.d.ts +0 -10
- package/dist/daemon-cli.js +0 -15
- package/dist/hooks/useInputManager.d.ts +0 -75
- package/dist/hooks/useInputManager.js +0 -583
- package/dist/hooks/usePluginManager.d.ts +0 -4
- package/dist/hooks/usePluginManager.js +0 -265
- package/dist/hooks/useTasks.d.ts +0 -1
- package/dist/hooks/useTasks.js +0 -5
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -447
- package/dist/managers/inputHandlers.d.ts +0 -30
- package/dist/managers/inputHandlers.js +0 -625
- package/dist/managers/inputReducer.d.ts +0 -271
- package/dist/managers/inputReducer.js +0 -1121
- package/dist/plugin-manager-cli.d.ts +0 -5
- package/dist/plugin-manager-cli.js +0 -12
- package/dist/print-cli.d.ts +0 -10
- package/dist/print-cli.js +0 -209
- package/dist/reducers/agentsManagerReducer.d.ts +0 -26
- package/dist/reducers/agentsManagerReducer.js +0 -54
- package/dist/reducers/backgroundTaskManagerReducer.d.ts +0 -62
- package/dist/reducers/backgroundTaskManagerReducer.js +0 -106
- package/dist/reducers/confirmationReducer.d.ts +0 -37
- package/dist/reducers/confirmationReducer.js +0 -193
- package/dist/reducers/helpSelectorReducer.d.ts +0 -25
- package/dist/reducers/helpSelectorReducer.js +0 -52
- package/dist/reducers/marketplaceAddFormReducer.d.ts +0 -24
- package/dist/reducers/marketplaceAddFormReducer.js +0 -58
- package/dist/reducers/mcpManagerReducer.d.ts +0 -37
- package/dist/reducers/mcpManagerReducer.js +0 -74
- package/dist/reducers/pluginDetailReducer.d.ts +0 -32
- package/dist/reducers/pluginDetailReducer.js +0 -70
- package/dist/reducers/questionReducer.d.ts +0 -82
- package/dist/reducers/questionReducer.js +0 -375
- package/dist/reducers/rewindSelectorReducer.d.ts +0 -21
- package/dist/reducers/rewindSelectorReducer.js +0 -37
- package/dist/reducers/selectorReducer.d.ts +0 -23
- package/dist/reducers/selectorReducer.js +0 -42
- package/dist/reducers/workflowManagerReducer.d.ts +0 -40
- package/dist/reducers/workflowManagerReducer.js +0 -100
- package/dist/session-selector-cli.d.ts +0 -3
- package/dist/session-selector-cli.js +0 -25
- package/dist/stdio/agentBridge.d.ts +0 -139
- package/dist/stdio/agentBridge.js +0 -999
- package/dist/stdio/daemonServer.d.ts +0 -67
- package/dist/stdio/daemonServer.js +0 -191
- package/dist/stdio/index.d.ts +0 -5
- package/dist/stdio/index.js +0 -5
- package/dist/stdio/jsonRpcConnection.d.ts +0 -39
- package/dist/stdio/jsonRpcConnection.js +0 -135
- package/dist/stdio/protocol.d.ts +0 -41
- package/dist/stdio/protocol.js +0 -26
- package/dist/stdio/stdioServer.d.ts +0 -36
- package/dist/stdio/stdioServer.js +0 -51
- package/dist/stdio-cli.d.ts +0 -8
- package/dist/stdio-cli.js +0 -15
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/bracketedPaste.d.ts +0 -39
- package/dist/utils/bracketedPaste.js +0 -122
- package/dist/utils/clipboard.d.ts +0 -21
- package/dist/utils/clipboard.js +0 -347
- package/dist/utils/constants.d.ts +0 -16
- package/dist/utils/constants.js +0 -18
- package/dist/utils/highlightUtils.d.ts +0 -1
- package/dist/utils/highlightUtils.js +0 -93
- package/dist/utils/inputUtils.d.ts +0 -17
- package/dist/utils/inputUtils.js +0 -67
- package/dist/utils/logger.d.ts +0 -71
- package/dist/utils/logger.js +0 -259
- package/dist/utils/markdownTable.d.ts +0 -34
- package/dist/utils/markdownTable.js +0 -302
- package/dist/utils/rewindCheckpoints.d.ts +0 -8
- package/dist/utils/rewindCheckpoints.js +0 -17
- package/dist/utils/throttle.d.ts +0 -14
- package/dist/utils/throttle.js +0 -55
- package/dist/utils/toolParameterTransforms.d.ts +0 -18
- package/dist/utils/toolParameterTransforms.js +0 -73
- package/dist/utils/usageSummary.d.ts +0 -28
- package/dist/utils/usageSummary.js +0 -121
- package/dist/utils/version.d.ts +0 -1
- package/dist/utils/version.js +0 -4
- package/dist/utils/worktree.d.ts +0 -35
- package/dist/utils/worktree.js +0 -219
|
@@ -255,6 +255,53 @@ function insertTextWithPlaceholder(
|
|
|
255
255
|
return newState;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Delete a placeholder token ([LongText#N] / [Image #N]) as a whole block
|
|
260
|
+
* when the cursor sits at the token's end, aligned with Claude Code's
|
|
261
|
+
* Cursor.deleteTokenBefore (Cursor.ts:937-969): the token must be preceded
|
|
262
|
+
* by start-of-input or whitespace and followed by whitespace or EOL, so a
|
|
263
|
+
* mid-token cursor or a token glued to following text falls back to
|
|
264
|
+
* one-character deletion. Also drops the deleted token's longTextMap entry.
|
|
265
|
+
* Returns null when no token is at the cursor position.
|
|
266
|
+
*/
|
|
267
|
+
function deleteTokenBefore(
|
|
268
|
+
inputText: string,
|
|
269
|
+
cursorPosition: number,
|
|
270
|
+
longTextMap: Record<string, string>,
|
|
271
|
+
): {
|
|
272
|
+
inputText: string;
|
|
273
|
+
cursorPosition: number;
|
|
274
|
+
longTextMap: Record<string, string>;
|
|
275
|
+
} | null {
|
|
276
|
+
if (cursorPosition <= 0) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Word-boundary guard (aligned with CC): only trigger when the char after
|
|
281
|
+
// the cursor is whitespace or the end of the string.
|
|
282
|
+
const charAfter = inputText[cursorPosition];
|
|
283
|
+
if (charAfter !== undefined && !/\s/.test(charAfter)) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const textBefore = inputText.slice(0, cursorPosition);
|
|
288
|
+
const tokenMatch = textBefore.match(/(^|\s)\[(LongText#\d+|Image #\d+)\]$/);
|
|
289
|
+
if (!tokenMatch) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const tokenStart = tokenMatch.index! + tokenMatch[1]!.length;
|
|
294
|
+
const token = tokenMatch[0].slice(tokenMatch[1]!.length);
|
|
295
|
+
const newLongTextMap = { ...longTextMap };
|
|
296
|
+
delete newLongTextMap[token];
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
inputText: inputText.slice(0, tokenStart) + inputText.slice(cursorPosition),
|
|
300
|
+
cursorPosition: tokenStart,
|
|
301
|
+
longTextMap: newLongTextMap,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
258
305
|
/**
|
|
259
306
|
* Submit the current input text: extract [Image #N] references, route /btw
|
|
260
307
|
* and CLI-internal slash commands, otherwise send as a message. Returns null
|
|
@@ -823,7 +870,9 @@ export function inputReducer(
|
|
|
823
870
|
// chunk (e.g. "\x7f\x7f") that ink cannot parse into a key event, so it
|
|
824
871
|
// arrives as raw input and would otherwise be treated as a paste and
|
|
825
872
|
// inserted literally. Treat each DEL as a synchronous backspace instead
|
|
826
|
-
// (aligned with Claude Code Issue #1853).
|
|
873
|
+
// (aligned with Claude Code Issue #1853). Each DEL deletes a placeholder
|
|
874
|
+
// token as a whole block first, falling back to one character (aligned
|
|
875
|
+
// with Claude Code's useTextInput.ts:442-465).
|
|
827
876
|
if (!key.backspace && !key.delete && input.includes("\x7f")) {
|
|
828
877
|
const delCount = (input.match(/\x7f/g) || []).length;
|
|
829
878
|
|
|
@@ -834,74 +883,92 @@ export function inputReducer(
|
|
|
834
883
|
};
|
|
835
884
|
}
|
|
836
885
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
const newInputText =
|
|
843
|
-
state.inputText.substring(0, newCursorPosition) +
|
|
844
|
-
state.inputText.substring(state.cursorPosition);
|
|
845
|
-
|
|
846
|
-
const newState = {
|
|
847
|
-
...state,
|
|
848
|
-
inputText: newInputText,
|
|
849
|
-
cursorPosition: newCursorPosition,
|
|
850
|
-
historyIndex: -1,
|
|
851
|
-
};
|
|
852
|
-
|
|
853
|
-
// Deactivate selectors if their trigger character was deleted
|
|
854
|
-
if (
|
|
855
|
-
newState.showFileSelector &&
|
|
856
|
-
newCursorPosition <= newState.atPosition
|
|
857
|
-
) {
|
|
858
|
-
newState.showFileSelector = false;
|
|
859
|
-
newState.atPosition = -1;
|
|
860
|
-
newState.fileSearchQuery = "";
|
|
861
|
-
newState.isFileSearching = false;
|
|
862
|
-
}
|
|
863
|
-
if (
|
|
864
|
-
newState.showCommandSelector &&
|
|
865
|
-
newCursorPosition <= newState.slashPosition
|
|
866
|
-
) {
|
|
867
|
-
newState.showCommandSelector = false;
|
|
868
|
-
newState.slashPosition = -1;
|
|
869
|
-
newState.commandSearchQuery = "";
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
// Reactivate selectors if cursor is within a trigger word
|
|
873
|
-
const atPos = getAtSelectorPosition(newInputText, newCursorPosition);
|
|
874
|
-
if (atPos !== -1 && !state.showFileSelector) {
|
|
875
|
-
newState.showFileSelector = true;
|
|
876
|
-
newState.atPosition = atPos;
|
|
877
|
-
newState.isFileSearching = true;
|
|
878
|
-
}
|
|
879
|
-
const slashPos = getSlashSelectorPosition(
|
|
886
|
+
let newInputText = state.inputText;
|
|
887
|
+
let newCursorPosition = state.cursorPosition;
|
|
888
|
+
let newLongTextMap = state.longTextMap;
|
|
889
|
+
for (let i = 0; i < delCount; i++) {
|
|
890
|
+
const tokenDeletion = deleteTokenBefore(
|
|
880
891
|
newInputText,
|
|
881
892
|
newCursorPosition,
|
|
893
|
+
newLongTextMap,
|
|
882
894
|
);
|
|
883
|
-
if (
|
|
884
|
-
|
|
885
|
-
|
|
895
|
+
if (tokenDeletion) {
|
|
896
|
+
newInputText = tokenDeletion.inputText;
|
|
897
|
+
newCursorPosition = tokenDeletion.cursorPosition;
|
|
898
|
+
newLongTextMap = tokenDeletion.longTextMap;
|
|
899
|
+
} else if (newCursorPosition > 0) {
|
|
900
|
+
newInputText =
|
|
901
|
+
newInputText.substring(0, newCursorPosition - 1) +
|
|
902
|
+
newInputText.substring(newCursorPosition);
|
|
903
|
+
newCursorPosition -= 1;
|
|
886
904
|
}
|
|
905
|
+
}
|
|
887
906
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
}
|
|
895
|
-
if (newState.showCommandSelector && newState.slashPosition >= 0) {
|
|
896
|
-
newState.commandSearchQuery = newInputText.substring(
|
|
897
|
-
newState.slashPosition + 1,
|
|
898
|
-
newCursorPosition,
|
|
899
|
-
);
|
|
900
|
-
}
|
|
907
|
+
if (
|
|
908
|
+
newInputText === state.inputText &&
|
|
909
|
+
newCursorPosition === state.cursorPosition
|
|
910
|
+
) {
|
|
911
|
+
return state;
|
|
912
|
+
}
|
|
901
913
|
|
|
902
|
-
|
|
914
|
+
const newState = {
|
|
915
|
+
...state,
|
|
916
|
+
inputText: newInputText,
|
|
917
|
+
cursorPosition: newCursorPosition,
|
|
918
|
+
longTextMap: newLongTextMap,
|
|
919
|
+
historyIndex: -1,
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
// Deactivate selectors if their trigger character was deleted
|
|
923
|
+
if (
|
|
924
|
+
newState.showFileSelector &&
|
|
925
|
+
newCursorPosition <= newState.atPosition
|
|
926
|
+
) {
|
|
927
|
+
newState.showFileSelector = false;
|
|
928
|
+
newState.atPosition = -1;
|
|
929
|
+
newState.fileSearchQuery = "";
|
|
930
|
+
newState.isFileSearching = false;
|
|
903
931
|
}
|
|
904
|
-
|
|
932
|
+
if (
|
|
933
|
+
newState.showCommandSelector &&
|
|
934
|
+
newCursorPosition <= newState.slashPosition
|
|
935
|
+
) {
|
|
936
|
+
newState.showCommandSelector = false;
|
|
937
|
+
newState.slashPosition = -1;
|
|
938
|
+
newState.commandSearchQuery = "";
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// Reactivate selectors if cursor is within a trigger word
|
|
942
|
+
const atPos = getAtSelectorPosition(newInputText, newCursorPosition);
|
|
943
|
+
if (atPos !== -1 && !state.showFileSelector) {
|
|
944
|
+
newState.showFileSelector = true;
|
|
945
|
+
newState.atPosition = atPos;
|
|
946
|
+
newState.isFileSearching = true;
|
|
947
|
+
}
|
|
948
|
+
const slashPos = getSlashSelectorPosition(
|
|
949
|
+
newInputText,
|
|
950
|
+
newCursorPosition,
|
|
951
|
+
);
|
|
952
|
+
if (slashPos !== -1 && !state.showCommandSelector) {
|
|
953
|
+
newState.showCommandSelector = true;
|
|
954
|
+
newState.slashPosition = slashPos;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// Update queries
|
|
958
|
+
if (newState.showFileSelector && newState.atPosition >= 0) {
|
|
959
|
+
newState.fileSearchQuery = newInputText.substring(
|
|
960
|
+
newState.atPosition + 1,
|
|
961
|
+
newCursorPosition,
|
|
962
|
+
);
|
|
963
|
+
}
|
|
964
|
+
if (newState.showCommandSelector && newState.slashPosition >= 0) {
|
|
965
|
+
newState.commandSearchQuery = newInputText.substring(
|
|
966
|
+
newState.slashPosition + 1,
|
|
967
|
+
newCursorPosition,
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
return newState;
|
|
905
972
|
}
|
|
906
973
|
|
|
907
974
|
// 1. /btw overlay handling (active while a question is displayed, or
|
|
@@ -1425,54 +1492,69 @@ export function inputReducer(
|
|
|
1425
1492
|
|
|
1426
1493
|
// 8. Backspace / Delete (Normal Mode)
|
|
1427
1494
|
if (key.backspace || key.delete) {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1495
|
+
// Placeholder token deletion first (aligned with Claude Code's
|
|
1496
|
+
// deleteTokenBefore, Cursor.ts:937-969): backspace at the end of a
|
|
1497
|
+
// [LongText#N] / [Image #N] token removes the whole token in one
|
|
1498
|
+
// press (and drops its longTextMap entry); otherwise delete one
|
|
1499
|
+
// character. Selector backspace (section 5) stays character-wise —
|
|
1500
|
+
// @mention and /command words are intentionally not tokenized.
|
|
1501
|
+
const tokenDeletion = deleteTokenBefore(
|
|
1502
|
+
state.inputText,
|
|
1503
|
+
state.cursorPosition,
|
|
1504
|
+
state.longTextMap,
|
|
1505
|
+
);
|
|
1506
|
+
if (!tokenDeletion && state.cursorPosition <= 0) {
|
|
1507
|
+
return state;
|
|
1508
|
+
}
|
|
1509
|
+
const newInputText = tokenDeletion
|
|
1510
|
+
? tokenDeletion.inputText
|
|
1511
|
+
: state.inputText.substring(0, state.cursorPosition - 1) +
|
|
1512
|
+
state.inputText.substring(state.cursorPosition);
|
|
1513
|
+
const newCursorPosition = tokenDeletion
|
|
1514
|
+
? tokenDeletion.cursorPosition
|
|
1515
|
+
: state.cursorPosition - 1;
|
|
1436
1516
|
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1517
|
+
const newState = {
|
|
1518
|
+
...state,
|
|
1519
|
+
inputText: newInputText,
|
|
1520
|
+
cursorPosition: newCursorPosition,
|
|
1521
|
+
longTextMap: tokenDeletion
|
|
1522
|
+
? tokenDeletion.longTextMap
|
|
1523
|
+
: state.longTextMap,
|
|
1524
|
+
historyIndex: -1,
|
|
1525
|
+
};
|
|
1443
1526
|
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1527
|
+
// Reactivate selectors if cursor is within word
|
|
1528
|
+
const atPos = getAtSelectorPosition(newInputText, newCursorPosition);
|
|
1529
|
+
if (atPos !== -1 && !state.showFileSelector) {
|
|
1530
|
+
newState.showFileSelector = true;
|
|
1531
|
+
newState.atPosition = atPos;
|
|
1532
|
+
newState.isFileSearching = true;
|
|
1533
|
+
}
|
|
1451
1534
|
|
|
1452
|
-
|
|
1453
|
-
|
|
1535
|
+
const slashPos = getSlashSelectorPosition(
|
|
1536
|
+
newInputText,
|
|
1537
|
+
newCursorPosition,
|
|
1538
|
+
);
|
|
1539
|
+
if (slashPos !== -1 && !state.showCommandSelector) {
|
|
1540
|
+
newState.showCommandSelector = true;
|
|
1541
|
+
newState.slashPosition = slashPos;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
// Update queries
|
|
1545
|
+
if (newState.showFileSelector && newState.atPosition >= 0) {
|
|
1546
|
+
newState.fileSearchQuery = newInputText.substring(
|
|
1547
|
+
newState.atPosition + 1,
|
|
1548
|
+
newCursorPosition,
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1551
|
+
if (newState.showCommandSelector && newState.slashPosition >= 0) {
|
|
1552
|
+
newState.commandSearchQuery = newInputText.substring(
|
|
1553
|
+
newState.slashPosition + 1,
|
|
1454
1554
|
newCursorPosition,
|
|
1455
1555
|
);
|
|
1456
|
-
if (slashPos !== -1 && !state.showCommandSelector) {
|
|
1457
|
-
newState.showCommandSelector = true;
|
|
1458
|
-
newState.slashPosition = slashPos;
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
// Update queries
|
|
1462
|
-
if (newState.showFileSelector && newState.atPosition >= 0) {
|
|
1463
|
-
newState.fileSearchQuery = newInputText.substring(
|
|
1464
|
-
newState.atPosition + 1,
|
|
1465
|
-
newCursorPosition,
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
if (newState.showCommandSelector && newState.slashPosition >= 0) {
|
|
1469
|
-
newState.commandSearchQuery = newInputText.substring(
|
|
1470
|
-
newState.slashPosition + 1,
|
|
1471
|
-
newCursorPosition,
|
|
1472
|
-
);
|
|
1473
|
-
}
|
|
1474
|
-
return newState;
|
|
1475
1556
|
}
|
|
1557
|
+
return newState;
|
|
1476
1558
|
}
|
|
1477
1559
|
|
|
1478
1560
|
// 9. Cursor Movement (Normal Mode)
|
package/src/print-cli.ts
CHANGED
|
@@ -147,6 +147,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
147
147
|
worktreeName: worktreeSession.name,
|
|
148
148
|
isNew: worktreeSession.isNew,
|
|
149
149
|
repoRoot: worktreeSession.repoRoot,
|
|
150
|
+
hookBased: worktreeSession.hookBased,
|
|
150
151
|
};
|
|
151
152
|
agent.setWorktreeSession(session);
|
|
152
153
|
}
|
|
@@ -186,8 +187,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
186
187
|
// Display timing information
|
|
187
188
|
displayTimingInfo(startTime, showStats);
|
|
188
189
|
|
|
189
|
-
//
|
|
190
|
-
// decide whether the worktree is clean enough to remove
|
|
190
|
+
// Decide whether the worktree is clean enough to remove
|
|
191
191
|
let cleanWorktree = false;
|
|
192
192
|
if (worktreeSession) {
|
|
193
193
|
const cwd = workdir || worktreeSession.path;
|
|
@@ -196,9 +196,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
196
196
|
const hasCommits = hasNewCommits(cwd, baseBranch);
|
|
197
197
|
cleanWorktree = !hasChanges && !hasCommits;
|
|
198
198
|
|
|
199
|
-
if (cleanWorktree) {
|
|
200
|
-
await agent.triggerWorktreeRemoveHook(worktreeSession.path);
|
|
201
|
-
} else {
|
|
199
|
+
if (!cleanWorktree) {
|
|
202
200
|
process.stdout.write(
|
|
203
201
|
`\n⚠️ Worktree '${worktreeSession.name}' has changes or commits. Keeping it at: ${worktreeSession.path}\n`,
|
|
204
202
|
);
|
|
@@ -211,10 +209,14 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
211
209
|
// Handle worktree cleanup for print mode (git removal stays after destroy)
|
|
212
210
|
if (worktreeSession && cleanWorktree) {
|
|
213
211
|
try {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
212
|
+
// Hook-based worktrees are owned by the hook; the git-root
|
|
213
|
+
// containment check does not apply to them
|
|
214
|
+
if (!worktreeSession.hookBased) {
|
|
215
|
+
validateWorktreeRemovalPath(
|
|
216
|
+
worktreeSession.path,
|
|
217
|
+
worktreeSession.repoRoot,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
218
220
|
await removeWorktree(worktreeSession);
|
|
219
221
|
} catch (error) {
|
|
220
222
|
// Never block print-mode exit on worktree cleanup failures
|
|
@@ -242,7 +244,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
242
244
|
// Display timing information even on error
|
|
243
245
|
displayTimingInfo(startTime, showStats);
|
|
244
246
|
|
|
245
|
-
//
|
|
247
|
+
// Decide whether the worktree is clean enough to remove
|
|
246
248
|
let cleanWorktree = false;
|
|
247
249
|
if (worktreeSession) {
|
|
248
250
|
const cwd = workdir || worktreeSession.path;
|
|
@@ -251,9 +253,7 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
251
253
|
const hasCommits = hasNewCommits(cwd, baseBranch);
|
|
252
254
|
cleanWorktree = !hasChanges && !hasCommits;
|
|
253
255
|
|
|
254
|
-
if (cleanWorktree) {
|
|
255
|
-
await agent.triggerWorktreeRemoveHook(worktreeSession.path);
|
|
256
|
-
} else {
|
|
256
|
+
if (!cleanWorktree) {
|
|
257
257
|
process.stdout.write(
|
|
258
258
|
`\n⚠️ Worktree '${worktreeSession.name}' has changes or commits. Keeping it at: ${worktreeSession.path}\n`,
|
|
259
259
|
);
|
|
@@ -265,10 +265,14 @@ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
|
|
|
265
265
|
// Handle worktree cleanup for print mode even on error
|
|
266
266
|
if (worktreeSession && cleanWorktree) {
|
|
267
267
|
try {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
268
|
+
// Hook-based worktrees are owned by the hook; the git-root
|
|
269
|
+
// containment check does not apply to them
|
|
270
|
+
if (!worktreeSession.hookBased) {
|
|
271
|
+
validateWorktreeRemovalPath(
|
|
272
|
+
worktreeSession.path,
|
|
273
|
+
worktreeSession.repoRoot,
|
|
274
|
+
);
|
|
275
|
+
}
|
|
272
276
|
await removeWorktree(worktreeSession);
|
|
273
277
|
} catch (error) {
|
|
274
278
|
process.stdout.write(
|
|
@@ -4,6 +4,10 @@ export interface SelectorState<T = unknown> {
|
|
|
4
4
|
selectedIndex: number;
|
|
5
5
|
pendingDecision: "select" | "insert" | "cancel" | null;
|
|
6
6
|
items: T[];
|
|
7
|
+
/** View state: show sessions from all projects (Ctrl+A toggle). */
|
|
8
|
+
showAllProjects?: boolean;
|
|
9
|
+
/** View state: show sessions from all same-repo worktrees (Ctrl+W toggle). */
|
|
10
|
+
showAllWorktrees?: boolean;
|
|
7
11
|
}
|
|
8
12
|
|
|
9
13
|
export type SelectorAction<T = unknown> =
|
|
@@ -12,6 +16,8 @@ export type SelectorAction<T = unknown> =
|
|
|
12
16
|
| { type: "RESET_INDEX" }
|
|
13
17
|
| { type: "SET_ITEMS"; items: T[] }
|
|
14
18
|
| { type: "HANDLE_KEY"; key: Key; hasInsert: boolean }
|
|
19
|
+
| { type: "TOGGLE_ALL_PROJECTS" }
|
|
20
|
+
| { type: "TOGGLE_ALL_WORKTREES" }
|
|
15
21
|
| { type: "CLEAR_DECISION" };
|
|
16
22
|
|
|
17
23
|
export function selectorReducer<T = unknown>(
|
|
@@ -33,6 +39,10 @@ export function selectorReducer<T = unknown>(
|
|
|
33
39
|
return { ...state, selectedIndex: 0 };
|
|
34
40
|
case "SET_ITEMS":
|
|
35
41
|
return { ...state, items: action.items, selectedIndex: 0 };
|
|
42
|
+
case "TOGGLE_ALL_PROJECTS":
|
|
43
|
+
return { ...state, showAllProjects: !state.showAllProjects };
|
|
44
|
+
case "TOGGLE_ALL_WORKTREES":
|
|
45
|
+
return { ...state, showAllWorktrees: !state.showAllWorktrees };
|
|
36
46
|
case "HANDLE_KEY":
|
|
37
47
|
if (action.key.upArrow) {
|
|
38
48
|
return {
|