@aria-cli/cli 1.0.50 → 1.0.51
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/aria.mjs +1 -1
- package/dist/.tsbuildinfo +1 -0
- package/dist/attached-local-control-client.js +826 -0
- package/dist/bootstrap-local-control-client.js +2 -0
- package/dist/capability-aware-method-proxy.js +42 -0
- package/dist/cli-context.js +160 -0
- package/dist/commands/arions.js +174 -0
- package/dist/commands/auth.js +123 -0
- package/dist/commands/daemon.js +245 -0
- package/dist/commands/definitions.js +176 -0
- package/dist/commands/index.js +74 -0
- package/dist/commands/login-handler.js +1108 -0
- package/dist/commands/logout-handler.js +92 -0
- package/dist/commands/memory-handlers.js +89 -0
- package/dist/commands/pairing.js +60 -0
- package/dist/commands/runtime-cutover-reset-command.js +12 -0
- package/dist/commands/runtime-cutover-reset.js +265 -0
- package/dist/commands/terminal-setup.js +84 -0
- package/dist/config/aria-config.js +238 -0
- package/dist/config/index.js +3 -0
- package/dist/config/loader.js +97 -0
- package/dist/config.js +142 -0
- package/dist/daemon-info.js +10 -0
- package/dist/ensure-daemon.js +128 -0
- package/dist/entrypoints/command-mode.js +5 -0
- package/dist/entrypoints/daemon.js +50 -0
- package/dist/entrypoints/headless-stdio.js +25 -0
- package/dist/entrypoints/interactive.js +80 -0
- package/dist/event-loop-watchdog.js +73 -0
- package/dist/headless/auth-orchestrator.js +508 -0
- package/dist/headless/auth-service.js +43 -0
- package/dist/headless/bootstrap-fast-path.js +112 -0
- package/dist/headless/call-command.js +143 -0
- package/dist/headless/daemon-service.js +318 -0
- package/dist/headless/hook-actions.js +235 -0
- package/dist/headless/hook-service.js +42 -0
- package/dist/headless/kernel-services.js +216 -0
- package/dist/headless/kernel.js +785 -0
- package/dist/headless/operations/arion.js +119 -0
- package/dist/headless/operations/auth.js +45 -0
- package/dist/headless/operations/client.js +31 -0
- package/dist/headless/operations/config.js +69 -0
- package/dist/headless/operations/daemon.js +47 -0
- package/dist/headless/operations/hook.js +56 -0
- package/dist/headless/operations/index.js +11 -0
- package/dist/headless/operations/memory.js +102 -0
- package/dist/headless/operations/message.js +279 -0
- package/dist/headless/operations/model.js +100 -0
- package/dist/headless/operations/peer.js +56 -0
- package/dist/headless/operations/run.js +24 -0
- package/dist/headless/operations/session.js +90 -0
- package/dist/headless/operations/system.js +19 -0
- package/dist/headless/operations/utils.js +35 -0
- package/dist/headless/run-orchestrator.js +703 -0
- package/dist/headless/stdio-server.js +439 -0
- package/dist/history/SessionHistory.js +8 -0
- package/dist/history/SessionHistoryClient.js +186 -0
- package/dist/history/conversation-message.js +112 -0
- package/dist/history/index.js +8 -0
- package/dist/history/jsonl-replay.js +154 -0
- package/dist/history/repair-tool-pairing.js +84 -0
- package/dist/history/stall-phase-bridge.js +11 -0
- package/dist/history/turn-accumulator.js +427 -0
- package/dist/index.js +7 -0
- package/dist/ink-repl.js +4183 -0
- package/dist/local-control-bootstrap.js +26 -0
- package/dist/local-control-client.js +2 -0
- package/dist/local-control-error-reporting.js +34 -0
- package/dist/local-control-http-client.js +362 -0
- package/dist/local-control-lazy-wrapper.js +363 -0
- package/dist/local-control-manager.js +146 -0
- package/dist/main.js +38 -0
- package/dist/network-security.js +62 -0
- package/dist/networking-server.js +38 -0
- package/dist/peer-identity.js +23 -0
- package/dist/polling-subscription.js +34 -0
- package/dist/relaunch.js +588 -0
- package/dist/release-notes.js +35 -0
- package/dist/repl-cleanup.js +47 -0
- package/dist/runtime/configure-bun-sqlite.js +3 -0
- package/dist/runtime/crash-handlers.js +111 -0
- package/dist/runtime/interactive-invocation.js +39 -0
- package/dist/runtime/internal-mode.js +14 -0
- package/dist/runtime/launch-spec.js +64 -0
- package/dist/runtime/owner-lease.js +44 -0
- package/dist/runtime/public-mode.js +20 -0
- package/dist/runtime/run-internal-mode.js +18 -0
- package/dist/runtime/runtime-kind.js +32 -0
- package/dist/runtime/spawn-aria.js +38 -0
- package/dist/selectable-client.js +2 -0
- package/dist/selectable-peer.js +2 -0
- package/dist/session.js +203 -0
- package/dist/slash-commands.js +80 -0
- package/dist/sounds.js +210 -0
- package/dist/ui/App.js +526 -0
- package/dist/ui/components/AnthropicMethodPicker.js +6 -0
- package/dist/ui/components/ArionPrompt.js +15 -0
- package/dist/ui/components/AutocompleteDropdown.js +23 -0
- package/dist/ui/components/AutonomySelector.js +55 -0
- package/dist/ui/components/Banner.js +98 -0
- package/dist/ui/components/ConversationHistory.js +175 -0
- package/dist/ui/components/CopilotDeviceLoginFlow.js +88 -0
- package/dist/ui/components/CopilotSourcePicker.js +50 -0
- package/dist/ui/components/Cost.js +10 -0
- package/dist/ui/components/CustomSelect/option-map.js +30 -0
- package/dist/ui/components/CustomSelect/select-option.js +13 -0
- package/dist/ui/components/CustomSelect/select.js +42 -0
- package/dist/ui/components/CustomSelect/use-select-state.js +179 -0
- package/dist/ui/components/CustomSelect/use-select.js +15 -0
- package/dist/ui/components/ErrorDisplay.js +35 -0
- package/dist/ui/components/FallbackToolUseRejectedMessage.js +7 -0
- package/dist/ui/components/FileEditToolUpdatedMessage.js +57 -0
- package/dist/ui/components/HandoffMarker.js +18 -0
- package/dist/ui/components/HighlightedCode.js +21 -0
- package/dist/ui/components/InputArea.js +187 -0
- package/dist/ui/components/Message.js +25 -0
- package/dist/ui/components/OAuthLoginFlow.js +113 -0
- package/dist/ui/components/OutputTruncation.js +35 -0
- package/dist/ui/components/PermissionPrompt.js +79 -0
- package/dist/ui/components/PipelineTimingPanel.js +15 -0
- package/dist/ui/components/ProviderMethodPicker.js +61 -0
- package/dist/ui/components/ProviderPicker.js +63 -0
- package/dist/ui/components/RenderItemView.js +71 -0
- package/dist/ui/components/Spinner.js +46 -0
- package/dist/ui/components/StatusBar.js +95 -0
- package/dist/ui/components/StreamingIndicator.js +55 -0
- package/dist/ui/components/StructuredDiff.js +168 -0
- package/dist/ui/components/TextInputOverlay.js +43 -0
- package/dist/ui/components/ThinkingBlock.js +82 -0
- package/dist/ui/components/ToolCost.js +17 -0
- package/dist/ui/components/ToolExecution.js +61 -0
- package/dist/ui/components/ToolHeader.js +51 -0
- package/dist/ui/components/ToolRenderLayoutContext.js +14 -0
- package/dist/ui/components/ToolResultWrapper.js +6 -0
- package/dist/ui/components/ToolUseLoader.js +35 -0
- package/dist/ui/components/TraceWaterfall.js +91 -0
- package/dist/ui/components/index.js +33 -0
- package/dist/ui/components/messages/AssistantTextMessage.js +25 -0
- package/dist/ui/components/messages/UserImageMessage.js +12 -0
- package/dist/ui/components/messages/UserTextMessage.js +12 -0
- package/dist/ui/components/overlays/ArionSelector.js +68 -0
- package/dist/ui/components/overlays/ClientSelector.js +62 -0
- package/dist/ui/components/overlays/CommandPalette.js +67 -0
- package/dist/ui/components/overlays/DaemonControl.js +87 -0
- package/dist/ui/components/overlays/InviteShareOverlay.js +15 -0
- package/dist/ui/components/overlays/JoinInviteOverlay.js +32 -0
- package/dist/ui/components/overlays/MemoryBrowser.js +100 -0
- package/dist/ui/components/overlays/MessageSelector.js +123 -0
- package/dist/ui/components/overlays/ModelSelector.js +211 -0
- package/dist/ui/components/overlays/PairRequestOverlay.js +42 -0
- package/dist/ui/components/overlays/PeerSelector.js +84 -0
- package/dist/ui/components/overlays/SessionSelector.js +102 -0
- package/dist/ui/components/overlays/SoundSelector.js +86 -0
- package/dist/ui/components/overlays/ThemeSelector.js +139 -0
- package/dist/ui/components/overlays/index.js +15 -0
- package/dist/ui/components/permissions/BashPermissionRequest/BashPermissionRequest.js +53 -0
- package/dist/ui/components/permissions/FallbackPermissionRequest.js +56 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.js +76 -0
- package/dist/ui/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js +18 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.js +64 -0
- package/dist/ui/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js +26 -0
- package/dist/ui/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.js +141 -0
- package/dist/ui/components/permissions/PermissionRequest.js +70 -0
- package/dist/ui/components/permissions/PermissionRequestTitle.js +41 -0
- package/dist/ui/components/permissions/hooks.js +10 -0
- package/dist/ui/components/permissions/toolUseOptions.js +68 -0
- package/dist/ui/components/permissions/utils.js +10 -0
- package/dist/ui/components/text-input/Cursor.js +326 -0
- package/dist/ui/components/text-input/TextInput.js +231 -0
- package/dist/ui/components/text-input/imagePaste.js +28 -0
- package/dist/ui/components/text-input/index.js +6 -0
- package/dist/ui/components/text-input/useDoublePress.js +30 -0
- package/dist/ui/components/text-input/useTextInput.js +245 -0
- package/dist/ui/components/tool-types.js +9 -0
- package/dist/ui/constants/figures.js +4 -0
- package/dist/ui/constants/index.js +3 -0
- package/dist/ui/display-mode.js +93 -0
- package/dist/ui/display-policy.js +19 -0
- package/dist/ui/hooks/index.js +6 -0
- package/dist/ui/hooks/useCommandAutocomplete.js +93 -0
- package/dist/ui/hooks/useDoublePress.js +37 -0
- package/dist/ui/hooks/useIndicatorState.js +55 -0
- package/dist/ui/hooks/useInterval.js +23 -0
- package/dist/ui/hooks/useKeyboardShortcuts.js +127 -0
- package/dist/ui/hooks/useTerminalSize.js +55 -0
- package/dist/ui/hooks/useUnifiedMessages.js +117 -0
- package/dist/ui/indicator-state.js +44 -0
- package/dist/ui/markdown/highlight.js +44 -0
- package/dist/ui/markdown/index.js +1460 -0
- package/dist/ui/markdown/tokenizer.js +24 -0
- package/dist/ui/render-item.js +5 -0
- package/dist/ui/screens/REPL.js +119 -0
- package/dist/ui/screens/approval-lifecycle.js +38 -0
- package/dist/ui/status-line.js +72 -0
- package/dist/ui/theme/index.js +51 -0
- package/dist/ui/theme/themes/claude-dark-daltonized.js +51 -0
- package/dist/ui/theme/themes/claude-dark.js +50 -0
- package/dist/ui/theme/themes/claude-light-daltonized.js +51 -0
- package/dist/ui/theme/themes/claude-light.js +50 -0
- package/dist/ui/theme/themes/dark-accessible.js +18 -0
- package/dist/ui/theme/themes/dark.js +49 -0
- package/dist/ui/theme/themes/light-accessible.js +18 -0
- package/dist/ui/theme/themes/light.js +49 -0
- package/dist/ui/theme/types.js +3 -0
- package/dist/ui/theme.js +142 -0
- package/dist/ui/to-render-items.js +145 -0
- package/dist/ui/tools/AgentTool/index.js +30 -0
- package/dist/ui/tools/ArchitectTool/index.js +31 -0
- package/dist/ui/tools/AskUserTool/index.js +46 -0
- package/dist/ui/tools/BashTool/BashToolResultMessage.js +11 -0
- package/dist/ui/tools/BashTool/OutputLine.js +21 -0
- package/dist/ui/tools/BashTool/index.js +91 -0
- package/dist/ui/tools/BrowseTool/index.js +43 -0
- package/dist/ui/tools/BrowserTool/index.js +47 -0
- package/dist/ui/tools/CbmTool/index.js +188 -0
- package/dist/ui/tools/CheckDelegationTool/index.js +46 -0
- package/dist/ui/tools/CheckMessagesTool/index.js +85 -0
- package/dist/ui/tools/CreateQuipTool/index.js +30 -0
- package/dist/ui/tools/CreateSkillTool/index.js +22 -0
- package/dist/ui/tools/CreateToolTool/index.js +31 -0
- package/dist/ui/tools/DelegateRemoteTool/index.js +42 -0
- package/dist/ui/tools/DeployTool/index.js +47 -0
- package/dist/ui/tools/FffTool/index.js +103 -0
- package/dist/ui/tools/FileEditTool/index.js +67 -0
- package/dist/ui/tools/FileReadTool/index.js +68 -0
- package/dist/ui/tools/FileWriteTool/index.js +61 -0
- package/dist/ui/tools/ForkTool/index.js +47 -0
- package/dist/ui/tools/FrgTool/index.js +96 -0
- package/dist/ui/tools/GetThreadTool/index.js +39 -0
- package/dist/ui/tools/GlobTool/index.js +50 -0
- package/dist/ui/tools/GrepTool/index.js +84 -0
- package/dist/ui/tools/HatchArionTool/index.js +36 -0
- package/dist/ui/tools/LearnSkillTool/index.js +22 -0
- package/dist/ui/tools/LearnTool/index.js +43 -0
- package/dist/ui/tools/LearnToolTool/index.js +22 -0
- package/dist/ui/tools/ListClientsTool/index.js +39 -0
- package/dist/ui/tools/LspTool/index.js +261 -0
- package/dist/ui/tools/MCPTool/index.js +33 -0
- package/dist/ui/tools/ManageNetworkTool/index.js +53 -0
- package/dist/ui/tools/MemoryReadTool/index.js +64 -0
- package/dist/ui/tools/MemoryWriteTool/index.js +20 -0
- package/dist/ui/tools/NotebookEditTool/index.js +33 -0
- package/dist/ui/tools/NotebookReadTool/index.js +25 -0
- package/dist/ui/tools/OutlookReadTool/index.js +66 -0
- package/dist/ui/tools/OutlookReplyTool/index.js +49 -0
- package/dist/ui/tools/OutlookSendTool/index.js +49 -0
- package/dist/ui/tools/PauseDelegationTool/index.js +35 -0
- package/dist/ui/tools/ProbeTool/index.js +121 -0
- package/dist/ui/tools/ProcessTool/index.js +66 -0
- package/dist/ui/tools/QuestListTool/index.js +46 -0
- package/dist/ui/tools/QuestReportTool/index.js +49 -0
- package/dist/ui/tools/QuestUpdateTool/index.js +87 -0
- package/dist/ui/tools/QuipCommentTool/index.js +69 -0
- package/dist/ui/tools/QuipReadTool/index.js +71 -0
- package/dist/ui/tools/RestArionTool/index.js +32 -0
- package/dist/ui/tools/RestartTool/index.js +35 -0
- package/dist/ui/tools/ResumeDelegationTool/index.js +35 -0
- package/dist/ui/tools/RetireArionTool/index.js +32 -0
- package/dist/ui/tools/RgTool/index.js +73 -0
- package/dist/ui/tools/SearchKnowledgeTool/index.js +43 -0
- package/dist/ui/tools/SearchMessagesTool/index.js +43 -0
- package/dist/ui/tools/SelfDiagnoseTool/index.js +61 -0
- package/dist/ui/tools/SendMessageTool/index.js +45 -0
- package/dist/ui/tools/SerenaTool/index.js +124 -0
- package/dist/ui/tools/SessionHistoryTool/index.js +52 -0
- package/dist/ui/tools/SgTool/index.js +80 -0
- package/dist/ui/tools/SlackReactTool/index.js +41 -0
- package/dist/ui/tools/SlackReadTool/index.js +48 -0
- package/dist/ui/tools/SlackSendTool/index.js +45 -0
- package/dist/ui/tools/SpawnWorkerTool/index.js +33 -0
- package/dist/ui/tools/StickerRequestTool/index.js +19 -0
- package/dist/ui/tools/ThinkTool/index.js +17 -0
- package/dist/ui/tools/UgTool/index.js +108 -0
- package/dist/ui/tools/UseSkillTool/index.js +22 -0
- package/dist/ui/tools/WakeArionTool/index.js +32 -0
- package/dist/ui/tools/WebFetchTool/index.js +56 -0
- package/dist/ui/tools/WebSearchTool/index.js +44 -0
- package/dist/ui/tools/lsTool/index.js +58 -0
- package/dist/ui/tools/registry.js +197 -0
- package/dist/ui/tools/tool-renderer.js +11 -0
- package/dist/ui/tools/truncation.js +35 -0
- package/dist/ui/types/anthropic.js +4 -0
- package/dist/ui/types/index.js +2 -0
- package/dist/ui/types/message.js +3 -0
- package/dist/ui/types/tool.js +4 -0
- package/dist/ui/utils/array.js +4 -0
- package/dist/ui/utils/cursor.js +131 -0
- package/dist/ui/utils/diff.js +120 -0
- package/dist/ui/utils/format.js +42 -0
- package/dist/ui/utils/fuzzy.js +59 -0
- package/dist/ui/utils/index.js +11 -0
- package/dist/ui/utils/keys.js +8 -0
- package/dist/ui/utils/patch.js +17 -0
- package/dist/ui/utils/risk.js +114 -0
- package/dist/ui/utils/terminal-image.js +70 -0
- package/dist/ui/utils/validation.js +48 -0
- package/dist/ui/verb-pairs.js +248 -0
- package/dist/ui.js +131 -0
- package/package.json +73 -14
- package/src/entrypoints/command-mode.ts +5 -0
- package/src/entrypoints/daemon.ts +54 -0
- package/src/entrypoints/headless-stdio.ts +27 -0
- package/src/entrypoints/interactive.ts +112 -0
- package/src/main.ts +44 -0
- package/src/runtime/configure-bun-sqlite.ts +3 -0
- package/src/runtime/crash-handlers.ts +128 -0
- package/src/runtime/interactive-invocation.test.ts +42 -0
- package/src/runtime/interactive-invocation.ts +51 -0
- package/src/runtime/internal-mode.test.ts +19 -0
- package/src/runtime/internal-mode.ts +24 -0
- package/src/runtime/launch-spec.test.ts +26 -0
- package/src/runtime/launch-spec.ts +84 -0
- package/src/runtime/owner-lease.ts +52 -0
- package/src/runtime/public-mode.test.ts +18 -0
- package/src/runtime/public-mode.ts +19 -0
- package/src/runtime/run-internal-mode.ts +19 -0
- package/src/runtime/runtime-kind.test.ts +23 -0
- package/src/runtime/runtime-kind.ts +41 -0
- package/src/runtime/spawn-aria.ts +62 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Text, useInput } from "ink";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { useTextInput } from "./useTextInput.js";
|
|
6
|
+
import { getTheme } from "../../theme/index.js";
|
|
7
|
+
// Bracketed paste mode markers.
|
|
8
|
+
// Terminals wrap pasted text in \x1b[200~ ... \x1b[201~ sequences.
|
|
9
|
+
// Ink's useInput strips the leading \x1b from the start of the first chunk,
|
|
10
|
+
// so the start marker appears as "[200~" in the input string.
|
|
11
|
+
// The end marker may appear as "\x1b[201~" (mid-string) or "[201~" (if in its own chunk).
|
|
12
|
+
const BRACKET_PASTE_START = "[200~";
|
|
13
|
+
const BRACKET_PASTE_END_RAW = "\x1b[201~";
|
|
14
|
+
const BRACKET_PASTE_END_STRIPPED = "[201~";
|
|
15
|
+
function stripBracketPasteMarkers(input) {
|
|
16
|
+
let text = input;
|
|
17
|
+
let hasBracketStart = false;
|
|
18
|
+
let hasBracketEnd = false;
|
|
19
|
+
if (text.startsWith(BRACKET_PASTE_START)) {
|
|
20
|
+
text = text.slice(BRACKET_PASTE_START.length);
|
|
21
|
+
hasBracketStart = true;
|
|
22
|
+
}
|
|
23
|
+
if (text.endsWith(BRACKET_PASTE_END_RAW)) {
|
|
24
|
+
text = text.slice(0, -BRACKET_PASTE_END_RAW.length);
|
|
25
|
+
hasBracketEnd = true;
|
|
26
|
+
}
|
|
27
|
+
else if (text.endsWith(BRACKET_PASTE_END_STRIPPED)) {
|
|
28
|
+
text = text.slice(0, -BRACKET_PASTE_END_STRIPPED.length);
|
|
29
|
+
hasBracketEnd = true;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// End marker might be mid-string (before trailing content in same chunk)
|
|
33
|
+
const rawIdx = text.indexOf(BRACKET_PASTE_END_RAW);
|
|
34
|
+
if (rawIdx !== -1) {
|
|
35
|
+
text = text.slice(0, rawIdx) + text.slice(rawIdx + BRACKET_PASTE_END_RAW.length);
|
|
36
|
+
hasBracketEnd = true;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const strippedIdx = text.indexOf(BRACKET_PASTE_END_STRIPPED);
|
|
40
|
+
if (strippedIdx !== -1) {
|
|
41
|
+
text =
|
|
42
|
+
text.slice(0, strippedIdx) + text.slice(strippedIdx + BRACKET_PASTE_END_STRIPPED.length);
|
|
43
|
+
hasBracketEnd = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { text, hasBracketStart, hasBracketEnd };
|
|
48
|
+
}
|
|
49
|
+
export default function TextInput({ value: originalValue, placeholder = "", focus = true, mask, multiline = false, highlightPastedText = false, showCursor = true, onChange, onSubmit, onExit, onHistoryUp, onHistoryDown, onExitMessage, onMessage, onHistoryReset, onDoubleEscape, columns: columnsProp, onImagePaste, onPaste, isDimmed = false, disableCursorMovementForUpDownKeys = false, cursorOffset: cursorOffsetProp, onChangeCursorOffset: onChangeCursorOffsetProp, }) {
|
|
50
|
+
const PASTE_CHUNK_THRESHOLD = 800;
|
|
51
|
+
const PASTE_IDLE_TIMEOUT_MS = 100;
|
|
52
|
+
// Internal cursor state used when external cursor control is not provided
|
|
53
|
+
const [internalOffset, setInternalOffset] = useState(0);
|
|
54
|
+
const columns = columnsProp ?? process.stdout.columns ?? 80;
|
|
55
|
+
const cursorOffset = cursorOffsetProp ?? internalOffset;
|
|
56
|
+
const onChangeCursorOffset = onChangeCursorOffsetProp ?? setInternalOffset;
|
|
57
|
+
const { onInput, renderedValue } = useTextInput({
|
|
58
|
+
value: originalValue,
|
|
59
|
+
onChange,
|
|
60
|
+
onSubmit,
|
|
61
|
+
onExit,
|
|
62
|
+
onExitMessage,
|
|
63
|
+
onMessage,
|
|
64
|
+
onHistoryReset,
|
|
65
|
+
onHistoryUp,
|
|
66
|
+
onHistoryDown,
|
|
67
|
+
onDoubleEscape,
|
|
68
|
+
focus,
|
|
69
|
+
mask,
|
|
70
|
+
multiline,
|
|
71
|
+
cursorChar: showCursor ? " " : "",
|
|
72
|
+
highlightPastedText,
|
|
73
|
+
invert: chalk.inverse,
|
|
74
|
+
themeText: (text) => chalk.hex(getTheme().colors.text)(text),
|
|
75
|
+
columns,
|
|
76
|
+
onImagePaste,
|
|
77
|
+
disableCursorMovementForUpDownKeys,
|
|
78
|
+
externalOffset: cursorOffset,
|
|
79
|
+
onOffsetChange: onChangeCursorOffset,
|
|
80
|
+
});
|
|
81
|
+
// Paste detection state.
|
|
82
|
+
// Use refs (not React state) so back-to-back stdin chunks are handled
|
|
83
|
+
// synchronously without render-timing races.
|
|
84
|
+
const pasteChunksRef = useRef([]);
|
|
85
|
+
const pasteTimeoutRef = useRef(null);
|
|
86
|
+
// Track whether we're inside a bracketed paste (\x1b[200~ ... \x1b[201~).
|
|
87
|
+
// This is more reliable than the 800-char heuristic for terminals that send
|
|
88
|
+
// bracketed paste sequences (iTerm2, most modern terminals in raw mode).
|
|
89
|
+
const bracketedPasteActiveRef = useRef(false);
|
|
90
|
+
const clearPasteTimeout = () => {
|
|
91
|
+
if (pasteTimeoutRef.current) {
|
|
92
|
+
clearTimeout(pasteTimeoutRef.current);
|
|
93
|
+
pasteTimeoutRef.current = null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const flushPaste = () => {
|
|
97
|
+
const pastedText = pasteChunksRef.current.join("");
|
|
98
|
+
pasteChunksRef.current = [];
|
|
99
|
+
clearPasteTimeout();
|
|
100
|
+
bracketedPasteActiveRef.current = false;
|
|
101
|
+
if (!pastedText || !onPaste) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Schedule callback after current render to avoid state updates during render
|
|
105
|
+
Promise.resolve().then(() => onPaste(pastedText));
|
|
106
|
+
};
|
|
107
|
+
const schedulePasteFlush = () => {
|
|
108
|
+
clearPasteTimeout();
|
|
109
|
+
pasteTimeoutRef.current = setTimeout(() => {
|
|
110
|
+
flushPaste();
|
|
111
|
+
}, PASTE_IDLE_TIMEOUT_MS);
|
|
112
|
+
};
|
|
113
|
+
const enqueuePasteChunk = (chunk) => {
|
|
114
|
+
pasteChunksRef.current.push(chunk);
|
|
115
|
+
schedulePasteFlush();
|
|
116
|
+
};
|
|
117
|
+
const isPasteInProgress = () => pasteTimeoutRef.current !== null || bracketedPasteActiveRef.current;
|
|
118
|
+
useEffect(() => () => {
|
|
119
|
+
clearPasteTimeout();
|
|
120
|
+
pasteChunksRef.current = [];
|
|
121
|
+
bracketedPasteActiveRef.current = false;
|
|
122
|
+
}, []);
|
|
123
|
+
const isControlKey = (key) => {
|
|
124
|
+
return Boolean(key.return ||
|
|
125
|
+
key.escape ||
|
|
126
|
+
key.tab ||
|
|
127
|
+
key.ctrl ||
|
|
128
|
+
key.meta ||
|
|
129
|
+
key.upArrow ||
|
|
130
|
+
key.downArrow ||
|
|
131
|
+
key.leftArrow ||
|
|
132
|
+
key.rightArrow ||
|
|
133
|
+
key.pageUp ||
|
|
134
|
+
key.pageDown ||
|
|
135
|
+
key.backspace ||
|
|
136
|
+
key.delete);
|
|
137
|
+
};
|
|
138
|
+
const wrappedOnInput = (input, key) => {
|
|
139
|
+
// --- Bracketed paste marker stripping ---
|
|
140
|
+
// Terminals wrap pasted text in escape sequences that Ink doesn't understand.
|
|
141
|
+
// Strip them to prevent marker pollution in the text buffer.
|
|
142
|
+
const { text: cleanInput, hasBracketStart, hasBracketEnd } = stripBracketPasteMarkers(input);
|
|
143
|
+
// If bracket start detected, enter bracketed paste mode — but only when
|
|
144
|
+
// onPaste is provided. Without onPaste, bracket markers are just stripped
|
|
145
|
+
// and the content falls through to normal onInput insertion.
|
|
146
|
+
if (hasBracketStart && onPaste) {
|
|
147
|
+
bracketedPasteActiveRef.current = true;
|
|
148
|
+
}
|
|
149
|
+
// During bracketed paste, collect all content.
|
|
150
|
+
// Control keys (Enter, Escape, etc.) flush the paste immediately — this
|
|
151
|
+
// prevents input from being swallowed during an orphaned bracket start
|
|
152
|
+
// (when \x1b[201~ end marker never arrives).
|
|
153
|
+
if (bracketedPasteActiveRef.current && onPaste) {
|
|
154
|
+
if (isControlKey(key)) {
|
|
155
|
+
flushPaste();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (cleanInput) {
|
|
159
|
+
enqueuePasteChunk(cleanInput);
|
|
160
|
+
}
|
|
161
|
+
// If bracket end detected, flush immediately (no 100ms wait)
|
|
162
|
+
if (hasBracketEnd) {
|
|
163
|
+
flushPaste();
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// If bracket end arrives outside active paste (edge case), flush any pending
|
|
168
|
+
if (hasBracketEnd && isPasteInProgress()) {
|
|
169
|
+
if (cleanInput) {
|
|
170
|
+
enqueuePasteChunk(cleanInput);
|
|
171
|
+
}
|
|
172
|
+
flushPaste();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Special handling for backspace or delete.
|
|
176
|
+
// Must come BEFORE the empty-input guard: Ink sets input='' for
|
|
177
|
+
// backspace/delete keys (they're in nonAlphanumericKeys), so we
|
|
178
|
+
// detect them via key flags, not input content.
|
|
179
|
+
if (key.backspace ||
|
|
180
|
+
key.delete ||
|
|
181
|
+
cleanInput === "\b" ||
|
|
182
|
+
cleanInput === "\x7f" ||
|
|
183
|
+
cleanInput === "\x08") {
|
|
184
|
+
onInput(cleanInput, {
|
|
185
|
+
...key,
|
|
186
|
+
backspace: true,
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// No content AND no meaningful key flags — nothing to do.
|
|
191
|
+
// Arrow keys, Ctrl combos, etc. have empty input but meaningful key flags
|
|
192
|
+
// that onInput needs to process (e.g., up arrow → history navigation).
|
|
193
|
+
if (!cleanInput && !isControlKey(key))
|
|
194
|
+
return;
|
|
195
|
+
// Handle pastes (>800 chars) — heuristic fallback for terminals without
|
|
196
|
+
// bracketed paste mode.
|
|
197
|
+
// Usually we get one or two input characters at a time. If we
|
|
198
|
+
// get a bunch, the user has probably pasted.
|
|
199
|
+
// Unfortunately node batches long pastes, so it's possible
|
|
200
|
+
// that we would see e.g. 1024 characters and then just a few
|
|
201
|
+
// more in the next frame that belong with the original paste.
|
|
202
|
+
// This batching number is not consistent.
|
|
203
|
+
// While collecting a paste, flush on control keys and wait for the next
|
|
204
|
+
// keypress. This prevents Enter/Escape/etc from being appended into paste
|
|
205
|
+
// text or acting against stale pre-paste value.
|
|
206
|
+
if (onPaste && isPasteInProgress() && isControlKey(key)) {
|
|
207
|
+
flushPaste();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (onPaste && (cleanInput.length > PASTE_CHUNK_THRESHOLD || isPasteInProgress())) {
|
|
211
|
+
enqueuePasteChunk(cleanInput);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
onInput(cleanInput, key);
|
|
215
|
+
};
|
|
216
|
+
useInput(wrappedOnInput, { isActive: focus });
|
|
217
|
+
let renderedPlaceholder = placeholder
|
|
218
|
+
? chalk.hex(getTheme().colors.textMuted)(placeholder)
|
|
219
|
+
: undefined;
|
|
220
|
+
// Fake mouse cursor, because we like punishment
|
|
221
|
+
if (showCursor && focus) {
|
|
222
|
+
renderedPlaceholder =
|
|
223
|
+
placeholder.length > 0
|
|
224
|
+
? chalk.inverse(placeholder[0]) +
|
|
225
|
+
chalk.hex(getTheme().colors.textMuted)(placeholder.slice(1))
|
|
226
|
+
: chalk.inverse(" ");
|
|
227
|
+
}
|
|
228
|
+
const showPlaceholder = originalValue.length == 0 && placeholder;
|
|
229
|
+
return (_jsx(Text, { wrap: "truncate-end", dimColor: isDimmed, children: showPlaceholder ? renderedPlaceholder : renderedValue }));
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=TextInput.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
const SCREENSHOT_PATH = "/tmp/claude_cli_latest_screenshot.png";
|
|
4
|
+
export const CLIPBOARD_ERROR_MESSAGE = "No image found in clipboard. Use Cmd + Ctrl + Shift + 4 to copy a screenshot to clipboard.";
|
|
5
|
+
export function getImageFromClipboard() {
|
|
6
|
+
if (process.platform !== "darwin") {
|
|
7
|
+
// only support image paste on macOS for now
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
// Check if clipboard has image
|
|
12
|
+
execSync(`osascript -e 'the clipboard as «class PNGf»'`, {
|
|
13
|
+
stdio: "ignore",
|
|
14
|
+
});
|
|
15
|
+
// Save the image
|
|
16
|
+
execSync(`osascript -e 'set png_data to (the clipboard as «class PNGf»)' -e 'set fp to open for access POSIX file "${SCREENSHOT_PATH}" with write permission' -e 'write png_data to fp' -e 'close access fp'`, { stdio: "ignore" });
|
|
17
|
+
// Read the image and convert to base64
|
|
18
|
+
const imageBuffer = readFileSync(SCREENSHOT_PATH);
|
|
19
|
+
const base64Image = imageBuffer.toString("base64");
|
|
20
|
+
// Cleanup
|
|
21
|
+
execSync(`rm -f "${SCREENSHOT_PATH}"`, { stdio: "ignore" });
|
|
22
|
+
return base64Image;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=imagePaste.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as TextInput } from "./TextInput.js";
|
|
2
|
+
export { Cursor, MeasuredText } from "./Cursor.js";
|
|
3
|
+
export { useTextInput } from "./useTextInput.js";
|
|
4
|
+
export { useDoublePress } from "./useDoublePress.js";
|
|
5
|
+
export { getImageFromClipboard } from "./imagePaste.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Creates a function that calls one function on the first call and another
|
|
2
|
+
// function on the second call within a certain timeout
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
export const DOUBLE_PRESS_TIMEOUT_MS = 2000;
|
|
5
|
+
export function useDoublePress(setPending, onDoublePress, onFirstPress) {
|
|
6
|
+
const lastPressRef = useRef(0);
|
|
7
|
+
const timeoutRef = useRef(undefined);
|
|
8
|
+
return () => {
|
|
9
|
+
const now = Date.now();
|
|
10
|
+
const timeSinceLastPress = now - lastPressRef.current;
|
|
11
|
+
// For this to count as a double-call, be sure to check that
|
|
12
|
+
// timeoutRef.current exists so we don't trigger on triple call
|
|
13
|
+
// (e.g. of Esc to clear the text input)
|
|
14
|
+
if (timeSinceLastPress <= DOUBLE_PRESS_TIMEOUT_MS && timeoutRef.current) {
|
|
15
|
+
if (timeoutRef.current) {
|
|
16
|
+
clearTimeout(timeoutRef.current);
|
|
17
|
+
timeoutRef.current = undefined;
|
|
18
|
+
}
|
|
19
|
+
onDoublePress();
|
|
20
|
+
setPending(false);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
onFirstPress?.();
|
|
24
|
+
setPending(true);
|
|
25
|
+
timeoutRef.current = setTimeout(() => setPending(false), DOUBLE_PRESS_TIMEOUT_MS);
|
|
26
|
+
}
|
|
27
|
+
lastPressRef.current = now;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=useDoublePress.js.map
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { useDoublePress } from "./useDoublePress.js";
|
|
3
|
+
import { Cursor } from "./Cursor.js";
|
|
4
|
+
import { getImageFromClipboard, CLIPBOARD_ERROR_MESSAGE } from "./imagePaste.js";
|
|
5
|
+
import { isEscapeInput } from "../../utils/keys.js";
|
|
6
|
+
const IMAGE_PLACEHOLDER = "[Image pasted]";
|
|
7
|
+
function mapInput(input_map) {
|
|
8
|
+
return function (input) {
|
|
9
|
+
const handler = new Map(input_map).get(input) ?? (() => { });
|
|
10
|
+
return handler(input);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function useTextInput({ value: originalValue, onChange, onSubmit, onExit, onExitMessage, onMessage, onHistoryUp, onHistoryDown, onHistoryReset, onDoubleEscape, mask = "", multiline = false, cursorChar, invert, columns, onImagePaste, disableCursorMovementForUpDownKeys = false, externalOffset, onOffsetChange, }) {
|
|
14
|
+
const offset = externalOffset;
|
|
15
|
+
const setOffset = onOffsetChange;
|
|
16
|
+
const cursor = Cursor.fromText(originalValue, columns, offset);
|
|
17
|
+
const [imagePasteErrorTimeout, setImagePasteErrorTimeout] = useState(null);
|
|
18
|
+
function maybeClearImagePasteErrorTimeout() {
|
|
19
|
+
if (!imagePasteErrorTimeout) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
clearTimeout(imagePasteErrorTimeout);
|
|
23
|
+
setImagePasteErrorTimeout(null);
|
|
24
|
+
onMessage?.(false);
|
|
25
|
+
}
|
|
26
|
+
const handleCtrlC = useDoublePress((show) => {
|
|
27
|
+
maybeClearImagePasteErrorTimeout();
|
|
28
|
+
onExitMessage?.(show, "Ctrl-C");
|
|
29
|
+
}, () => onExit?.(), () => {
|
|
30
|
+
if (originalValue) {
|
|
31
|
+
onChange("");
|
|
32
|
+
onHistoryReset?.();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// Keep Escape for clearing input (or open message-edit overlay via onDoubleEscape)
|
|
36
|
+
const handleEscape = useDoublePress((show) => {
|
|
37
|
+
maybeClearImagePasteErrorTimeout();
|
|
38
|
+
onMessage?.(!!originalValue && show, `Press Escape again to clear`);
|
|
39
|
+
}, () => {
|
|
40
|
+
// Try message-edit overlay first; if handled, skip default clear
|
|
41
|
+
if (onDoubleEscape?.())
|
|
42
|
+
return;
|
|
43
|
+
if (originalValue) {
|
|
44
|
+
onChange("");
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
function clear() {
|
|
48
|
+
return Cursor.fromText("", columns, 0);
|
|
49
|
+
}
|
|
50
|
+
const handleEmptyCtrlD = useDoublePress((show) => onExitMessage?.(show, "Ctrl-D"), () => onExit?.());
|
|
51
|
+
function handleCtrlD() {
|
|
52
|
+
maybeClearImagePasteErrorTimeout();
|
|
53
|
+
if (cursor.text === "") {
|
|
54
|
+
// When input is empty, handle double-press
|
|
55
|
+
handleEmptyCtrlD();
|
|
56
|
+
return cursor;
|
|
57
|
+
}
|
|
58
|
+
// When input is not empty, delete forward like iPython
|
|
59
|
+
return cursor.del();
|
|
60
|
+
}
|
|
61
|
+
function tryImagePaste() {
|
|
62
|
+
const base64Image = getImageFromClipboard();
|
|
63
|
+
if (base64Image === null) {
|
|
64
|
+
if (process.platform !== "darwin") {
|
|
65
|
+
return cursor;
|
|
66
|
+
}
|
|
67
|
+
onMessage?.(true, CLIPBOARD_ERROR_MESSAGE);
|
|
68
|
+
maybeClearImagePasteErrorTimeout();
|
|
69
|
+
setImagePasteErrorTimeout(setTimeout(() => {
|
|
70
|
+
onMessage?.(false);
|
|
71
|
+
}, 4000));
|
|
72
|
+
return cursor;
|
|
73
|
+
}
|
|
74
|
+
onImagePaste?.(base64Image);
|
|
75
|
+
return cursor.insert(IMAGE_PLACEHOLDER);
|
|
76
|
+
}
|
|
77
|
+
const handleCtrl = mapInput([
|
|
78
|
+
["a", () => cursor.startOfLine()],
|
|
79
|
+
["b", () => cursor.left()],
|
|
80
|
+
["c", handleCtrlC],
|
|
81
|
+
["d", handleCtrlD],
|
|
82
|
+
["e", () => cursor.endOfLine()],
|
|
83
|
+
["f", () => cursor.right()],
|
|
84
|
+
[
|
|
85
|
+
"h",
|
|
86
|
+
() => {
|
|
87
|
+
maybeClearImagePasteErrorTimeout();
|
|
88
|
+
return cursor.backspace();
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
["k", () => cursor.deleteToLineEnd()],
|
|
92
|
+
["l", () => clear()],
|
|
93
|
+
["n", () => downOrHistoryDown()],
|
|
94
|
+
["p", () => upOrHistoryUp()],
|
|
95
|
+
["u", () => cursor.deleteToLineStart()],
|
|
96
|
+
["v", tryImagePaste],
|
|
97
|
+
["w", () => cursor.deleteWordBefore()],
|
|
98
|
+
]);
|
|
99
|
+
const handleMeta = mapInput([
|
|
100
|
+
["b", () => cursor.prevWord()],
|
|
101
|
+
["f", () => cursor.nextWord()],
|
|
102
|
+
["d", () => cursor.deleteWordAfter()],
|
|
103
|
+
]);
|
|
104
|
+
function handleEnter(key) {
|
|
105
|
+
if (multiline && cursor.offset > 0 && cursor.text[cursor.offset - 1] === "\\") {
|
|
106
|
+
return cursor.backspace().insert("\n");
|
|
107
|
+
}
|
|
108
|
+
if (key.meta || key.shift) {
|
|
109
|
+
return cursor.insert("\n");
|
|
110
|
+
}
|
|
111
|
+
onSubmit?.(originalValue);
|
|
112
|
+
}
|
|
113
|
+
function upOrHistoryUp() {
|
|
114
|
+
if (disableCursorMovementForUpDownKeys) {
|
|
115
|
+
onHistoryUp?.();
|
|
116
|
+
return cursor;
|
|
117
|
+
}
|
|
118
|
+
const cursorUp = cursor.up();
|
|
119
|
+
if (cursorUp.equals(cursor)) {
|
|
120
|
+
// already at beginning
|
|
121
|
+
onHistoryUp?.();
|
|
122
|
+
}
|
|
123
|
+
return cursorUp;
|
|
124
|
+
}
|
|
125
|
+
function downOrHistoryDown() {
|
|
126
|
+
if (disableCursorMovementForUpDownKeys) {
|
|
127
|
+
onHistoryDown?.();
|
|
128
|
+
return cursor;
|
|
129
|
+
}
|
|
130
|
+
const cursorDown = cursor.down();
|
|
131
|
+
if (cursorDown.equals(cursor)) {
|
|
132
|
+
onHistoryDown?.();
|
|
133
|
+
}
|
|
134
|
+
return cursorDown;
|
|
135
|
+
}
|
|
136
|
+
function onInput(input, key) {
|
|
137
|
+
// Shift+Delete — delete whole word backward.
|
|
138
|
+
// Many terminals report this as key.shift+key.delete, while some surface the
|
|
139
|
+
// raw CSI sequence directly.
|
|
140
|
+
if ((key.shift && key.delete) || input === "\x1b[3;2~") {
|
|
141
|
+
const nextCursor = cursor.deleteWordBefore();
|
|
142
|
+
if (!cursor.equals(nextCursor)) {
|
|
143
|
+
setOffset(nextCursor.offset);
|
|
144
|
+
if (cursor.text !== nextCursor.text) {
|
|
145
|
+
onChange(nextCursor.text);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Option+Delete (meta+backspace) — delete whole word backward
|
|
151
|
+
if (key.meta && (key.backspace || key.delete || input === "\x7f")) {
|
|
152
|
+
const nextCursor = cursor.deleteWordBefore();
|
|
153
|
+
if (!cursor.equals(nextCursor)) {
|
|
154
|
+
setOffset(nextCursor.offset);
|
|
155
|
+
if (cursor.text !== nextCursor.text) {
|
|
156
|
+
onChange(nextCursor.text);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Direct handling for backspace or delete (which is being detected as delete)
|
|
162
|
+
if (key.backspace || key.delete || input === "\b" || input === "\x7f" || input === "\x08") {
|
|
163
|
+
const nextCursor = cursor.backspace();
|
|
164
|
+
if (!cursor.equals(nextCursor)) {
|
|
165
|
+
setOffset(nextCursor.offset);
|
|
166
|
+
if (cursor.text !== nextCursor.text) {
|
|
167
|
+
onChange(nextCursor.text);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const nextCursor = mapKey(input, key)(input);
|
|
173
|
+
if (nextCursor) {
|
|
174
|
+
if (!cursor.equals(nextCursor)) {
|
|
175
|
+
setOffset(nextCursor.offset);
|
|
176
|
+
if (cursor.text !== nextCursor.text) {
|
|
177
|
+
onChange(nextCursor.text);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function mapKey(input, key) {
|
|
183
|
+
if (isEscapeInput(input, key)) {
|
|
184
|
+
return handleEscape;
|
|
185
|
+
}
|
|
186
|
+
// Direct handling for backspace or delete
|
|
187
|
+
if (key.backspace || key.delete) {
|
|
188
|
+
maybeClearImagePasteErrorTimeout();
|
|
189
|
+
return () => cursor.backspace();
|
|
190
|
+
}
|
|
191
|
+
switch (true) {
|
|
192
|
+
case key.leftArrow && (key.ctrl || key.meta || key.fn):
|
|
193
|
+
return () => cursor.prevWord();
|
|
194
|
+
case key.rightArrow && (key.ctrl || key.meta || key.fn):
|
|
195
|
+
return () => cursor.nextWord();
|
|
196
|
+
case key.ctrl:
|
|
197
|
+
return handleCtrl;
|
|
198
|
+
case key.home:
|
|
199
|
+
return () => cursor.startOfLine();
|
|
200
|
+
case key.end:
|
|
201
|
+
return () => cursor.endOfLine();
|
|
202
|
+
case key.pageDown:
|
|
203
|
+
return () => cursor.endOfLine();
|
|
204
|
+
case key.pageUp:
|
|
205
|
+
return () => cursor.startOfLine();
|
|
206
|
+
case key.return:
|
|
207
|
+
return () => handleEnter(key);
|
|
208
|
+
case key.meta:
|
|
209
|
+
return handleMeta;
|
|
210
|
+
case key.tab:
|
|
211
|
+
return () => { };
|
|
212
|
+
case key.upArrow:
|
|
213
|
+
return upOrHistoryUp;
|
|
214
|
+
case key.downArrow:
|
|
215
|
+
return downOrHistoryDown;
|
|
216
|
+
case key.leftArrow:
|
|
217
|
+
return () => cursor.left();
|
|
218
|
+
case key.rightArrow:
|
|
219
|
+
return () => cursor.right();
|
|
220
|
+
}
|
|
221
|
+
return function (input) {
|
|
222
|
+
switch (true) {
|
|
223
|
+
// Home key
|
|
224
|
+
case input == "\x1b[H" || input == "\x1b[1~":
|
|
225
|
+
return cursor.startOfLine();
|
|
226
|
+
// End key
|
|
227
|
+
case input == "\x1b[F" || input == "\x1b[4~":
|
|
228
|
+
return cursor.endOfLine();
|
|
229
|
+
// Handle backspace character explicitly - this is the key fix
|
|
230
|
+
case input === "\b" || input === "\x7f" || input === "\x08":
|
|
231
|
+
maybeClearImagePasteErrorTimeout();
|
|
232
|
+
return cursor.backspace();
|
|
233
|
+
default:
|
|
234
|
+
return cursor.insert(input.replace(/\r/g, "\n"));
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
onInput,
|
|
240
|
+
renderedValue: cursor.render(cursorChar, mask, invert),
|
|
241
|
+
offset,
|
|
242
|
+
setOffset,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=useTextInput.js.map
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// packages/cli/src/ui/display-mode.ts
|
|
2
|
+
//
|
|
3
|
+
// Display modes control UI presentation density. All data is always collected
|
|
4
|
+
// by ObservabilityContext — modes only affect what gets rendered.
|
|
5
|
+
//
|
|
6
|
+
// This is UI presentation state, not feature toggling. Consistent with the
|
|
7
|
+
// "no opt-in, no opt-out" principle: features are always ON, modes are
|
|
8
|
+
// analogous to collapsing a sidebar.
|
|
9
|
+
/**
|
|
10
|
+
* Mode presets — the base defaults for each display mode.
|
|
11
|
+
* Each key controls UI presentation density, not feature availability.
|
|
12
|
+
*/
|
|
13
|
+
export const MODE_PRESETS = {
|
|
14
|
+
minimal: {
|
|
15
|
+
showThinking: false,
|
|
16
|
+
showCosts: false,
|
|
17
|
+
showToolArgs: false,
|
|
18
|
+
toolOutput: "hidden",
|
|
19
|
+
showTraces: false,
|
|
20
|
+
showPipelineTiming: false,
|
|
21
|
+
showStatusBar: false,
|
|
22
|
+
},
|
|
23
|
+
standard: {
|
|
24
|
+
showThinking: true,
|
|
25
|
+
showCosts: true,
|
|
26
|
+
showToolArgs: true,
|
|
27
|
+
toolOutput: "standard",
|
|
28
|
+
showTraces: false,
|
|
29
|
+
showPipelineTiming: false,
|
|
30
|
+
showStatusBar: true,
|
|
31
|
+
},
|
|
32
|
+
debug: {
|
|
33
|
+
showThinking: true,
|
|
34
|
+
showCosts: true,
|
|
35
|
+
showToolArgs: true,
|
|
36
|
+
toolOutput: "expanded",
|
|
37
|
+
showTraces: true,
|
|
38
|
+
showPipelineTiming: true,
|
|
39
|
+
showStatusBar: true,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* All display modes in cycle order. Used by the 'd' hotkey.
|
|
44
|
+
*/
|
|
45
|
+
export const DISPLAY_MODE_CYCLE = ["minimal", "standard", "debug"];
|
|
46
|
+
/**
|
|
47
|
+
* Get the next display mode in the cycle.
|
|
48
|
+
* minimal -> standard -> debug -> minimal
|
|
49
|
+
*/
|
|
50
|
+
export function nextDisplayMode(current) {
|
|
51
|
+
const idx = DISPLAY_MODE_CYCLE.indexOf(current);
|
|
52
|
+
return DISPLAY_MODE_CYCLE[(idx + 1) % DISPLAY_MODE_CYCLE.length];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the DisplayConfig for a given mode.
|
|
56
|
+
*/
|
|
57
|
+
export function getDisplayConfig(mode) {
|
|
58
|
+
return { ...MODE_PRESETS[mode] };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Compute explicit overrides relative to a mode preset.
|
|
62
|
+
* Useful for preserving layered config/hotkey choices across mode cycling.
|
|
63
|
+
*/
|
|
64
|
+
export function deriveDisplayOverrides(mode, config) {
|
|
65
|
+
const preset = MODE_PRESETS[mode];
|
|
66
|
+
const overrides = {};
|
|
67
|
+
if (config.showThinking !== preset.showThinking)
|
|
68
|
+
overrides.showThinking = config.showThinking;
|
|
69
|
+
if (config.showCosts !== preset.showCosts)
|
|
70
|
+
overrides.showCosts = config.showCosts;
|
|
71
|
+
if (config.showToolArgs !== preset.showToolArgs)
|
|
72
|
+
overrides.showToolArgs = config.showToolArgs;
|
|
73
|
+
if (config.toolOutput !== preset.toolOutput)
|
|
74
|
+
overrides.toolOutput = config.toolOutput;
|
|
75
|
+
if (config.showTraces !== preset.showTraces)
|
|
76
|
+
overrides.showTraces = config.showTraces;
|
|
77
|
+
if (config.showPipelineTiming !== preset.showPipelineTiming) {
|
|
78
|
+
overrides.showPipelineTiming = config.showPipelineTiming;
|
|
79
|
+
}
|
|
80
|
+
if (config.showStatusBar !== preset.showStatusBar)
|
|
81
|
+
overrides.showStatusBar = config.showStatusBar;
|
|
82
|
+
return overrides;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Apply explicit overrides on top of a mode preset.
|
|
86
|
+
*/
|
|
87
|
+
export function resolveDisplayConfig(mode, overrides) {
|
|
88
|
+
return {
|
|
89
|
+
...MODE_PRESETS[mode],
|
|
90
|
+
...(overrides ?? {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=display-mode.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function applyDisplayPolicy(items, mode) {
|
|
2
|
+
if (mode === "debug")
|
|
3
|
+
return items;
|
|
4
|
+
return items.flatMap((item) => {
|
|
5
|
+
if (item.kind === "thinking") {
|
|
6
|
+
if (mode === "minimal")
|
|
7
|
+
return [];
|
|
8
|
+
// Standard mode: show collapsed "Thought for Xs" only when duration is known.
|
|
9
|
+
// Items without durationSec would render as null from RenderItemView, but the
|
|
10
|
+
// wrapping <Box marginTop={1}> in App.tsx still renders — producing a blank line
|
|
11
|
+
// per invisible item. With thousands of messages this creates a massive gap.
|
|
12
|
+
if (item.durationSec == null)
|
|
13
|
+
return [];
|
|
14
|
+
return [{ ...item, content: "" }];
|
|
15
|
+
}
|
|
16
|
+
return [item];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=display-policy.js.map
|