dexto 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/ink-cli/components/ResourceAutocomplete.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/ResourceAutocomplete.js +8 -2
- package/dist/cli/ink-cli/components/TextBufferInput.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/TextBufferInput.js +17 -3
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts +3 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/chat/MessageItem.js +33 -9
- package/dist/cli/ink-cli/components/modes/AlternateBufferCLI.js +3 -3
- package/dist/cli/ink-cli/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/modes/StaticCLI.js +10 -3
- package/dist/cli/ink-cli/components/renderers/GenericRenderer.js +1 -1
- package/dist/cli/ink-cli/components/renderers/SearchRenderer.js +1 -1
- package/dist/cli/ink-cli/components/shared/MarkdownText.d.ts.map +1 -1
- package/dist/cli/ink-cli/components/shared/MarkdownText.js +4 -4
- package/dist/cli/ink-cli/constants/processingPhrases.d.ts.map +1 -1
- package/dist/cli/ink-cli/constants/processingPhrases.js +58 -48
- package/dist/cli/ink-cli/constants/tips.d.ts.map +1 -1
- package/dist/cli/ink-cli/constants/tips.js +33 -32
- package/dist/cli/ink-cli/containers/InputContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/InputContainer.js +18 -11
- package/dist/cli/ink-cli/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/cli/ink-cli/containers/OverlayContainer.js +24 -1
- package/dist/cli/ink-cli/hooks/useCLIState.d.ts.map +1 -1
- package/dist/cli/ink-cli/hooks/useCLIState.js +14 -1
- package/dist/cli/ink-cli/utils/messageFormatting.d.ts.map +1 -1
- package/dist/cli/ink-cli/utils/messageFormatting.js +92 -5
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceAutocomplete.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ResourceAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,0BAA0B;IACvC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,yBAAyB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACvD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;CACrB;AA6ED;;GAEG;AACH,QAAA,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"ResourceAutocomplete.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/ResourceAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,0BAA0B;IACvC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,yBAAyB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACvD,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,UAAU,CAAC;CACrB;AA6ED;;GAEG;AACH,QAAA,MAAM,yBAAyB,8GAoQ9B,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,oBAAoB,EAErB,OAAO,yBAAyB,CAAC;AAEtC,eAAe,oBAAoB,CAAC"}
|
|
@@ -74,7 +74,7 @@ const ResourceAutocompleteInner = forwardRef(function ResourceAutocomplete({ isV
|
|
|
74
74
|
// Combined state to guarantee single render on navigation
|
|
75
75
|
const [selection, setSelection] = useState({ index: 0, offset: 0 });
|
|
76
76
|
const selectedIndexRef = useRef(0);
|
|
77
|
-
const MAX_VISIBLE_ITEMS =
|
|
77
|
+
const MAX_VISIBLE_ITEMS = 5;
|
|
78
78
|
// Update selection AND scroll offset in a single state update
|
|
79
79
|
// This guarantees exactly one render per navigation action
|
|
80
80
|
const updateSelection = useCallback((indexUpdater) => {
|
|
@@ -122,6 +122,10 @@ const ResourceAutocompleteInner = forwardRef(function ResourceAutocomplete({ isV
|
|
|
122
122
|
cancelled = true;
|
|
123
123
|
};
|
|
124
124
|
}, [isVisible, agent]);
|
|
125
|
+
// NOTE: Auto-close logic is handled synchronously in TextBufferInput.tsx
|
|
126
|
+
// (on backspace deleting @ and on space after @). We don't use useEffect here
|
|
127
|
+
// because React batches state updates, causing race conditions where isVisible
|
|
128
|
+
// and searchQuery update at different times.
|
|
125
129
|
// Extract query from @mention (everything after @)
|
|
126
130
|
const mentionQuery = useMemo(() => {
|
|
127
131
|
// Find the last @ that's at start or after space
|
|
@@ -250,7 +254,9 @@ const ResourceAutocompleteInner = forwardRef(function ResourceAutocomplete({ isV
|
|
|
250
254
|
const uriParts = resource.uri.split('/');
|
|
251
255
|
const displayName = resource.name || uriParts[uriParts.length - 1] || resource.uri;
|
|
252
256
|
const isImage = (resource.mimeType || '').startsWith('image/');
|
|
253
|
-
|
|
257
|
+
// Truncate URI for display (show last 40 chars with ellipsis)
|
|
258
|
+
const truncatedUri = resource.uri.length > 50 ? '…' + resource.uri.slice(-49) : resource.uri;
|
|
259
|
+
return (_jsxs(Box, { children: [isImage && _jsx(Text, { color: isSelected ? 'cyan' : 'gray', children: "\uD83D\uDDBC\uFE0F " }), _jsx(Text, { color: isSelected ? 'cyan' : 'white', bold: isSelected, children: displayName }), resource.serverName && (_jsxs(Text, { color: "gray", children: [" [", resource.serverName, "]"] })), _jsxs(Text, { color: "gray", children: [" ", truncatedUri] })] }, resource.uri));
|
|
254
260
|
})] }));
|
|
255
261
|
});
|
|
256
262
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextBufferInput.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/TextBufferInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGnE,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,OAAO,CAAC;AActF,UAAU,oBAAoB;IAC1B,oCAAoC;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,mEAAmE;IACnE,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrE,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnE,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kDAAkD;IAClD,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpE,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3D,iEAAiE;IACjE,MAAM,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC;IACpC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACxD,wDAAwD;IACxD,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACzC,oEAAoE;IACpE,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5F,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAuCD,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAqB,EACrB,QAAQ,EACR,gBAAgB,EAChB,UAAc,EACd,YAAY,EACZ,MAAW,EACX,aAAa,EACb,YAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,GACjB,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"TextBufferInput.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/components/TextBufferInput.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGnE,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,OAAO,CAAC;AActF,UAAU,oBAAoB;IAC1B,oCAAoC;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,mEAAmE;IACnE,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACrE,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnE,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kDAAkD;IAClD,QAAQ,EAAE,OAAO,CAAC;IAClB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACpE,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,iDAAiD;IACjD,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC3D,iEAAiE;IACjE,MAAM,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC;IACpC,4DAA4D;IAC5D,aAAa,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACxD,wDAAwD;IACxD,YAAY,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACzC,oEAAoE;IACpE,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5F,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC7D,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAuCD,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,QAAQ,EACR,WAAW,EACX,UAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAqB,EACrB,QAAQ,EACR,gBAAgB,EAChB,UAAc,EACd,YAAY,EACZ,MAAW,EACX,aAAa,EACb,YAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,GACjB,EAAE,oBAAoB,2CA0hBtB"}
|
|
@@ -250,14 +250,23 @@ export function TextBufferInput({ buffer, onSubmit, placeholder, isDisabled = fa
|
|
|
250
250
|
buffer.backspace();
|
|
251
251
|
checkRemovedImages();
|
|
252
252
|
checkRemovedPasteBlocks();
|
|
253
|
+
// Check if we should close overlay after backspace
|
|
254
|
+
// NOTE: buffer.text is memoized and won't update until next render,
|
|
255
|
+
// so we calculate the expected new text ourselves
|
|
253
256
|
if (onTriggerOverlay && cursorPos > 0) {
|
|
254
257
|
const deletedChar = prevText[cursorPos - 1];
|
|
255
|
-
|
|
258
|
+
// Calculate what the text will be after backspace
|
|
259
|
+
const expectedNewText = prevText.slice(0, cursorPos - 1) + prevText.slice(cursorPos);
|
|
256
260
|
if (deletedChar === '/' && cursorPos === 1) {
|
|
257
261
|
onTriggerOverlay('close');
|
|
258
262
|
}
|
|
259
|
-
else if (deletedChar === '@'
|
|
260
|
-
|
|
263
|
+
else if (deletedChar === '@') {
|
|
264
|
+
// Close if no valid @ mention remains
|
|
265
|
+
// A valid @ is at start of text or after whitespace
|
|
266
|
+
const hasValidAt = /(^|[\s])@/.test(expectedNewText);
|
|
267
|
+
if (!hasValidAt) {
|
|
268
|
+
onTriggerOverlay('close');
|
|
269
|
+
}
|
|
261
270
|
}
|
|
262
271
|
}
|
|
263
272
|
return;
|
|
@@ -388,6 +397,11 @@ export function TextBufferInput({ buffer, onSubmit, placeholder, isDisabled = fa
|
|
|
388
397
|
else if (key.sequence === '@') {
|
|
389
398
|
onTriggerOverlay('resource-autocomplete');
|
|
390
399
|
}
|
|
400
|
+
else if (/\s/.test(key.sequence)) {
|
|
401
|
+
// Close resource autocomplete when user types whitespace
|
|
402
|
+
// Whitespace means user is done with the mention (either selected or abandoned)
|
|
403
|
+
onTriggerOverlay('close');
|
|
404
|
+
}
|
|
391
405
|
}
|
|
392
406
|
}
|
|
393
407
|
}, [
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import type { Message } from '../../state/types.js';
|
|
7
7
|
interface MessageItemProps {
|
|
8
8
|
message: Message;
|
|
9
|
+
/** Terminal width for proper text wrapping calculations */
|
|
10
|
+
terminalWidth?: number;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Pure presentational component for a single message
|
|
@@ -14,6 +16,6 @@ interface MessageItemProps {
|
|
|
14
16
|
* Memoization with custom comparator prevents re-renders when message array changes
|
|
15
17
|
* but individual message content hasn't changed.
|
|
16
18
|
*/
|
|
17
|
-
export declare const MessageItem: import("react").MemoExoticComponent<({ message }: MessageItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
19
|
+
export declare const MessageItem: import("react").MemoExoticComponent<({ message, terminalWidth }: MessageItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
18
20
|
export {};
|
|
19
21
|
//# sourceMappingURL=MessageItem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageItem.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/chat/MessageItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"MessageItem.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/chat/MessageItem.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EACR,OAAO,EAUV,MAAM,sBAAsB,CAAC;AAuC9B,UAAU,gBAAgB;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,mEACc,gBAAgB,6CA+LrD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
3
|
* MessageItem Component
|
|
4
4
|
* Displays a single message with visual hierarchy
|
|
@@ -6,6 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
*/
|
|
7
7
|
import { memo } from 'react';
|
|
8
8
|
import { Box, Text } from 'ink';
|
|
9
|
+
import wrapAnsi from 'wrap-ansi';
|
|
9
10
|
import { ConfigBox, StatsBox, HelpBox, SessionListBox, SessionHistoryBox, LogConfigBox, ShortcutsBox, SyspromptBox, } from './styled-boxes/index.js';
|
|
10
11
|
import { ToolResultRenderer } from '../renderers/index.js';
|
|
11
12
|
import { MarkdownText } from '../shared/MarkdownText.js';
|
|
@@ -36,7 +37,7 @@ function formatDuration(ms) {
|
|
|
36
37
|
* Memoization with custom comparator prevents re-renders when message array changes
|
|
37
38
|
* but individual message content hasn't changed.
|
|
38
39
|
*/
|
|
39
|
-
export const MessageItem = memo(({ message }) => {
|
|
40
|
+
export const MessageItem = memo(({ message, terminalWidth = 80 }) => {
|
|
40
41
|
// Check for styled message first
|
|
41
42
|
if (message.styledType && message.styledData) {
|
|
42
43
|
switch (message.styledType) {
|
|
@@ -59,7 +60,7 @@ export const MessageItem = memo(({ message }) => {
|
|
|
59
60
|
const tokensStr = data.totalTokens >= 1000
|
|
60
61
|
? `, Used ${(data.totalTokens / 1000).toFixed(1)}K tokens`
|
|
61
62
|
: '';
|
|
62
|
-
return (_jsx(Box, { marginTop: 1, marginBottom: 1, width:
|
|
63
|
+
return (_jsx(Box, { marginTop: 1, marginBottom: 1, width: terminalWidth, children: _jsxs(Text, { color: "gray", children: ["\u2500 Worked for ", durationStr, tokensStr, " \u2500"] }) }));
|
|
63
64
|
}
|
|
64
65
|
case 'shortcuts':
|
|
65
66
|
return _jsx(ShortcutsBox, { data: message.styledData });
|
|
@@ -68,8 +69,18 @@ export const MessageItem = memo(({ message }) => {
|
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
// User message: '>' prefix with gray background
|
|
72
|
+
// Properly wrap text accounting for prefix "> " (2 chars) and paddingX={1} (2 chars total)
|
|
71
73
|
if (message.role === 'user') {
|
|
72
|
-
|
|
74
|
+
const prefix = '> ';
|
|
75
|
+
const paddingChars = 2; // paddingX={1} = 1 char on each side
|
|
76
|
+
const availableWidth = Math.max(20, terminalWidth - prefix.length - paddingChars);
|
|
77
|
+
const wrappedContent = wrapAnsi(message.content, availableWidth, {
|
|
78
|
+
hard: true,
|
|
79
|
+
wordWrap: true,
|
|
80
|
+
trim: false,
|
|
81
|
+
});
|
|
82
|
+
const lines = wrappedContent.split('\n');
|
|
83
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: 2, marginBottom: 1, width: terminalWidth, children: _jsx(Box, { flexDirection: "column", paddingX: 1, backgroundColor: "gray", children: lines.map((line, i) => (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: "green", children: i === 0 ? prefix : ' ' }), _jsx(Text, { color: "white", children: line })] }, i))) }) }));
|
|
73
84
|
}
|
|
74
85
|
// Assistant message: Gray circle indicator (unless continuation)
|
|
75
86
|
// IMPORTANT: width="100%" is required to prevent Ink layout failures on large content.
|
|
@@ -78,12 +89,12 @@ export const MessageItem = memo(({ message }) => {
|
|
|
78
89
|
if (message.role === 'assistant') {
|
|
79
90
|
// Continuation messages: no indicator, just content
|
|
80
91
|
if (message.isContinuation) {
|
|
81
|
-
return (_jsx(Box, { flexDirection: "column", width:
|
|
92
|
+
return (_jsx(Box, { flexDirection: "column", width: terminalWidth, children: _jsx(MarkdownText, { children: message.content || '' }) }));
|
|
82
93
|
}
|
|
83
94
|
// Regular assistant message: bullet prefix inline with first line
|
|
84
95
|
// Text wraps at terminal width - wrapped lines may start at column 0
|
|
85
96
|
// This is simpler and avoids mid-word splitting issues with Ink's wrap
|
|
86
|
-
return (_jsx(Box, { flexDirection: "column", marginTop: 1, width:
|
|
97
|
+
return (_jsx(Box, { flexDirection: "column", marginTop: 1, width: terminalWidth, children: _jsx(MarkdownText, { bulletPrefix: "\u23FA ", children: message.content || '' }) }));
|
|
87
98
|
}
|
|
88
99
|
// Tool message: Animated icon based on status
|
|
89
100
|
// - Running: green spinner + "Running..."
|
|
@@ -98,10 +109,22 @@ export const MessageItem = memo(({ message }) => {
|
|
|
98
109
|
const parenIndex = message.content.indexOf('(');
|
|
99
110
|
const toolName = parenIndex > 0 ? message.content.slice(0, parenIndex) : message.content;
|
|
100
111
|
const toolArgs = parenIndex > 0 ? message.content.slice(parenIndex) : '';
|
|
101
|
-
|
|
112
|
+
// Build the full tool header text for wrapping
|
|
113
|
+
const statusSuffix = isRunning ? ' Running...' : isPending ? ' Waiting...' : '';
|
|
114
|
+
const fullToolText = `${toolName}${toolArgs}${statusSuffix}`;
|
|
115
|
+
// ToolIcon takes 2 chars ("● "), so available width is terminalWidth - 2
|
|
116
|
+
const iconWidth = 2;
|
|
117
|
+
const availableWidth = Math.max(20, terminalWidth - iconWidth);
|
|
118
|
+
const wrappedToolText = wrapAnsi(fullToolText, availableWidth, {
|
|
119
|
+
hard: true,
|
|
120
|
+
wordWrap: true,
|
|
121
|
+
trim: false,
|
|
122
|
+
});
|
|
123
|
+
const toolLines = wrappedToolText.split('\n');
|
|
124
|
+
return (_jsxs(Box, { flexDirection: "column", marginTop: 1, width: terminalWidth, children: [toolLines.map((line, i) => (_jsxs(Box, { flexDirection: "row", children: [i === 0 ? (_jsx(ToolIcon, { status: message.toolStatus || 'finished', isError: message.isError ?? false })) : (_jsx(Text, { children: ' ' })), _jsx(Text, { children: i === 0 ? (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: line.slice(0, toolName.length) }), _jsx(Text, { children: line.slice(toolName.length) })] })) : (line) })] }, i))), hasStructuredDisplay ? (_jsx(ToolResultRenderer, { display: message.toolDisplayData, content: message.toolContent })) : (message.toolResult && (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "gray", children: [" \u23BF ", message.toolResult] }) })))] }));
|
|
102
125
|
}
|
|
103
126
|
// System message: Compact gray text
|
|
104
|
-
return (_jsx(Box, { flexDirection: "column", marginBottom: 1, width:
|
|
127
|
+
return (_jsx(Box, { flexDirection: "column", marginBottom: 1, width: terminalWidth, children: _jsx(Text, { color: "gray", children: message.content }) }));
|
|
105
128
|
},
|
|
106
129
|
// Custom comparator: only re-render if message content actually changed
|
|
107
130
|
(prev, next) => {
|
|
@@ -116,6 +139,7 @@ export const MessageItem = memo(({ message }) => {
|
|
|
116
139
|
prev.message.isContinuation === next.message.isContinuation &&
|
|
117
140
|
prev.message.isError === next.message.isError &&
|
|
118
141
|
prev.message.toolDisplayData === next.message.toolDisplayData &&
|
|
119
|
-
prev.message.toolContent === next.message.toolContent
|
|
142
|
+
prev.message.toolContent === next.message.toolContent &&
|
|
143
|
+
prev.terminalWidth === next.terminalWidth);
|
|
120
144
|
});
|
|
121
145
|
MessageItem.displayName = 'MessageItem';
|
|
@@ -94,7 +94,7 @@ export function AlternateBufferCLI({ agent, initialSessionId, startupInfo, onSel
|
|
|
94
94
|
return () => clearTimeout(timer);
|
|
95
95
|
}, [selectionHintVisible]);
|
|
96
96
|
// Get terminal dimensions - updates on resize
|
|
97
|
-
const { rows: terminalHeight } = useTerminalSize();
|
|
97
|
+
const { rows: terminalHeight, columns: terminalWidth } = useTerminalSize();
|
|
98
98
|
// Build list data: header as first item, then finalized + pending + dequeued buffer
|
|
99
99
|
// In alternate buffer mode, everything is re-rendered anyway, so we combine all
|
|
100
100
|
// Order: finalized messages → pending/streaming → dequeued user messages (guarantees order)
|
|
@@ -119,8 +119,8 @@ export function AlternateBufferCLI({ agent, initialSessionId, startupInfo, onSel
|
|
|
119
119
|
if (item.type === 'header') {
|
|
120
120
|
return (_jsx(Header, { modelName: session.modelName, sessionId: session.id || undefined, hasActiveSession: session.hasActiveSession, startupInfo: startupInfo }));
|
|
121
121
|
}
|
|
122
|
-
return _jsx(MessageItem, { message: item.message });
|
|
123
|
-
}, [session.modelName, session.id, session.hasActiveSession, startupInfo]);
|
|
122
|
+
return _jsx(MessageItem, { message: item.message, terminalWidth: terminalWidth });
|
|
123
|
+
}, [session.modelName, session.id, session.hasActiveSession, startupInfo, terminalWidth]);
|
|
124
124
|
// Smart height estimation based on item type and content
|
|
125
125
|
const estimateItemHeight = useCallback((index) => {
|
|
126
126
|
const item = listData[index];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StaticCLI.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/modes/StaticCLI.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAkBxD,UAAU,cAAc;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EACtB,KAAK,EACL,gBAAgB,EAChB,WAAW,EACX,YAAmB,GACtB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"StaticCLI.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/modes/StaticCLI.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAkBxD,UAAU,cAAc;IACpB,KAAK,EAAE,UAAU,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EACtB,KAAK,EACL,gBAAgB,EAChB,WAAW,EACX,YAAmB,GACtB,EAAE,cAAc,2CAoNhB"}
|
|
@@ -87,9 +87,16 @@ export function StaticCLI({ agent, initialSessionId, startupInfo, useStreaming =
|
|
|
87
87
|
const staticItems = useMemo(() => {
|
|
88
88
|
const items = [
|
|
89
89
|
_jsx(Header, { modelName: session.modelName, sessionId: session.id || undefined, hasActiveSession: session.hasActiveSession, startupInfo: startupInfo }, "header"),
|
|
90
|
-
...visibleMessages.map((msg) => _jsx(MessageItem, { message: msg }, msg.id)),
|
|
90
|
+
...visibleMessages.map((msg) => (_jsx(MessageItem, { message: msg, terminalWidth: terminalWidth }, msg.id))),
|
|
91
91
|
];
|
|
92
92
|
return items;
|
|
93
|
-
}, [
|
|
94
|
-
|
|
93
|
+
}, [
|
|
94
|
+
visibleMessages,
|
|
95
|
+
session.modelName,
|
|
96
|
+
session.id,
|
|
97
|
+
session.hasActiveSession,
|
|
98
|
+
startupInfo,
|
|
99
|
+
terminalWidth,
|
|
100
|
+
]);
|
|
101
|
+
return (_jsxs(Box, { flexDirection: "column", width: terminalWidth, children: [_jsx(Static, { items: staticItems, children: (item) => item }, staticRemountKey), pendingMessages.map((message) => (_jsx(MessageItem, { message: message, terminalWidth: terminalWidth }, message.id))), dequeuedBuffer.map((message) => (_jsx(MessageItem, { message: message, terminalWidth: terminalWidth }, message.id))), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(StatusBar, { agent: agent, isProcessing: ui.isProcessing, isThinking: ui.isThinking, approvalQueueCount: approvalQueue.length, copyModeEnabled: ui.copyModeEnabled, isAwaitingApproval: approval !== null }), _jsx(QueuedMessagesDisplay, { messages: queuedMessages }), _jsx(InputContainer, { ref: inputContainerRef, buffer: buffer, input: input, ui: ui, session: session, approval: approval, queuedMessages: queuedMessages, setInput: setInput, setUi: setUi, setSession: setSession, setMessages: setMessages, setPendingMessages: setPendingMessages, setDequeuedBuffer: setDequeuedBuffer, setQueuedMessages: setQueuedMessages, setApproval: setApproval, setApprovalQueue: setApprovalQueue, agent: agent, inputService: inputService, useStreaming: useStreaming }), _jsx(OverlayContainer, { ref: overlayContainerRef, ui: ui, input: input, session: session, approval: approval, setInput: setInput, setUi: setUi, setSession: setSession, setMessages: setMessages, setApproval: setApproval, setApprovalQueue: setApprovalQueue, agent: agent, inputService: inputService, buffer: buffer, refreshStatic: refreshStatic, onSubmitPromptCommand: handleSubmitPromptCommand }), ui.exitWarningShown && (_jsxs(Box, { paddingX: 1, children: [_jsx(Text, { color: "yellowBright", bold: true, children: "\u26A0 Press Ctrl+C again to exit" }), _jsx(Text, { color: "gray", children: " (or press any key to cancel)" })] })), _jsx(Footer, { modelName: session.modelName, cwd: process.cwd(), autoApproveEdits: ui.autoApproveEdits }), ui.historySearch.isActive && (_jsx(HistorySearchBar, { query: ui.historySearch.query, hasMatch: historySearchHasMatch }))] })] }));
|
|
95
102
|
}
|
|
@@ -22,5 +22,5 @@ export function GenericRenderer({ content, maxLines = 15 }) {
|
|
|
22
22
|
const line = lines[0];
|
|
23
23
|
return (_jsxs(Text, { color: "gray", children: [' ⎿ ', line.slice(0, 80), line.length > 80 ? '...' : ''] }));
|
|
24
24
|
}
|
|
25
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: [' ⎿ ', displayLines.length, " lines"] }), displayLines.map((line, i) => (_jsxs(Text, { color: "gray", wrap: "truncate", children: ['
|
|
25
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: [' ⎿ ', displayLines.length, " lines"] }), displayLines.map((line, i) => (_jsxs(Text, { color: "gray", wrap: "truncate", children: [' ⎿ ', line] }, i))), truncated && (_jsxs(Text, { color: "gray", children: [' ⎿ ', "... ", lines.length - maxLines, " more lines"] }))] }));
|
|
26
26
|
}
|
|
@@ -8,5 +8,5 @@ export function SearchRenderer({ data, maxMatches = 5 }) {
|
|
|
8
8
|
const { pattern, matches, totalMatches, truncated: dataTruncated } = data;
|
|
9
9
|
const displayMatches = matches.slice(0, maxMatches);
|
|
10
10
|
const truncated = dataTruncated || matches.length > maxMatches;
|
|
11
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: [' ⎿ ', totalMatches, " match", totalMatches !== 1 ? 'es' : '', " for \"", pattern, "\"", truncated && ' (truncated)'] }), displayMatches.map((match, i) => (_jsxs(Text, { color: "gray", children: ['
|
|
11
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "gray", children: [' ⎿ ', totalMatches, " match", totalMatches !== 1 ? 'es' : '', " for \"", pattern, "\"", truncated && ' (truncated)'] }), displayMatches.map((match, i) => (_jsxs(Text, { color: "gray", wrap: "truncate", children: [' ⎿ ', match.file, match.line > 0 && `:${match.line}`] }, i))), matches.length > maxMatches && (_jsxs(Text, { color: "gray", children: [' ⎿ ', "... ", matches.length - maxMatches, " more"] }))] }));
|
|
12
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownText.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/shared/MarkdownText.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAwB,MAAM,OAAO,CAAC;AAU7C,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,GAAG,KAAK,CAAC;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,iBAAS,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAuE1D;
|
|
1
|
+
{"version":3,"file":"MarkdownText.d.ts","sourceRoot":"","sources":["../../../../../src/cli/ink-cli/components/shared/MarkdownText.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAwB,MAAM,OAAO,CAAC;AAU7C,UAAU,aAAa;IACnB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,MAAM,GAAG,KAAK,CAAC;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,iBAAS,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAuE1D;AAyID,UAAU,iBAAiB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAkED,QAAA,MAAM,YAAY,+CAA6B,CAAC;AAMhD,UAAU,iBAAiB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AA4RD,eAAO,MAAM,YAAY,+CAA6B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -168,12 +168,12 @@ const WrappedParagraphInternal = ({ text, defaultColor, bulletPrefix, isFirstPar
|
|
|
168
168
|
return wrapped.split('\n');
|
|
169
169
|
}, [text, defaultColor, bulletPrefix, isFirstParagraph, terminalWidth]);
|
|
170
170
|
// Calculate indent for continuation lines (spaces to align with first line content)
|
|
171
|
-
|
|
171
|
+
// All lines get indentation when bulletPrefix is provided, for consistent left margin
|
|
172
|
+
const indentSpaces = bulletPrefix ? ' '.repeat(stringWidth(bulletPrefix)) : '';
|
|
172
173
|
return (_jsx(_Fragment, { children: wrappedLines.map((line, i) => {
|
|
173
174
|
const isFirstLine = i === 0;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
: continuationIndent;
|
|
175
|
+
// First line of first paragraph gets bullet, all other lines get space indent
|
|
176
|
+
const prefix = isFirstLine && isFirstParagraph && bulletPrefix ? bulletPrefix : indentSpaces;
|
|
177
177
|
return (_jsx(Box, { children: _jsxs(Text, { children: [prefix, line] }) }, i));
|
|
178
178
|
}) }));
|
|
179
179
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processingPhrases.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/processingPhrases.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"processingPhrases.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/processingPhrases.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAAM,EAiErC,CAAC;AAEF;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAGxC"}
|
|
@@ -4,61 +4,71 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export const processingPhrases = [
|
|
6
6
|
// pop culture
|
|
7
|
-
'I want to be the very best
|
|
8
|
-
'I will be the next hokage
|
|
9
|
-
'Shinzou Sasageyo
|
|
10
|
-
'My soldiers! Rage
|
|
11
|
-
'May the force be with you
|
|
12
|
-
'Why so serious
|
|
13
|
-
"That's what she said
|
|
14
|
-
'Winter is coming
|
|
15
|
-
"It's over 9000
|
|
16
|
-
"I'm Batman
|
|
17
|
-
"You can't handle the truth
|
|
18
|
-
'We were on a break
|
|
19
|
-
'Bazinga
|
|
20
|
-
"How you doin'
|
|
21
|
-
"There's always money in the banana stand
|
|
22
|
-
'I am the one who knocks
|
|
23
|
-
'Yabba dabba doo
|
|
24
|
-
'The tribe has spoken
|
|
25
|
-
'This is the Way
|
|
26
|
-
'Plata o plomo
|
|
27
|
-
'Yeah, science
|
|
28
|
-
"They're minerals, Marie
|
|
29
|
-
'The North remembers
|
|
30
|
-
'Life is like a box of chocolates
|
|
7
|
+
'I want to be the very best…',
|
|
8
|
+
'I will be the next hokage…',
|
|
9
|
+
'Shinzou Sasageyo…',
|
|
10
|
+
'My soldiers! Rage!…',
|
|
11
|
+
'May the force be with you…',
|
|
12
|
+
'Why so serious?…',
|
|
13
|
+
"That's what she said …",
|
|
14
|
+
'Winter is coming…',
|
|
15
|
+
"It's over 9000!…",
|
|
16
|
+
"I'm Batman…",
|
|
17
|
+
"You can't handle the truth…",
|
|
18
|
+
'We were on a break!…',
|
|
19
|
+
'Bazinga!…',
|
|
20
|
+
"How you doin'?…",
|
|
21
|
+
"There's always money in the banana stand…",
|
|
22
|
+
'I am the one who knocks…',
|
|
23
|
+
'Yabba dabba doo!…',
|
|
24
|
+
'The tribe has spoken…',
|
|
25
|
+
'This is the Way…',
|
|
26
|
+
'Plata o plomo…',
|
|
27
|
+
'Yeah, science!…',
|
|
28
|
+
"They're minerals, Marie!…",
|
|
29
|
+
'The North remembers…',
|
|
30
|
+
'Life is like a box of chocolates…',
|
|
31
31
|
'Avengers, assemble!',
|
|
32
|
-
'I can do this all day
|
|
33
|
-
'Elementary, my dear Watson
|
|
34
|
-
'Identity theft is not a joke, Jim!
|
|
35
|
-
"I'm not superstitious, but I am a little stitious
|
|
32
|
+
'I can do this all day…',
|
|
33
|
+
'Elementary, my dear Watson…',
|
|
34
|
+
'Identity theft is not a joke, Jim! …',
|
|
35
|
+
"I'm not superstitious, but I am a little stitious…",
|
|
36
36
|
// Playful
|
|
37
|
-
'Let me cook
|
|
38
|
-
'Manifesting greatness
|
|
39
|
-
'Rizzing the huzz
|
|
40
|
-
'Memeing
|
|
41
|
-
'Outperforming other AI agents
|
|
42
|
-
'Rolling with the squad
|
|
43
|
-
'Incanting secret scripts
|
|
44
|
-
'Making no mistakes
|
|
45
|
-
'Making you rich
|
|
46
|
-
'Farming easy points
|
|
47
|
-
'Using 200+ IQ
|
|
48
|
-
'Turning into Jarvis
|
|
49
|
-
'Dextomaxxing
|
|
50
|
-
'Zapping
|
|
51
|
-
'Braining
|
|
52
|
-
'Using all 3 brain cells
|
|
53
|
-
//'Installing malware (just kidding)
|
|
37
|
+
'Let me cook…',
|
|
38
|
+
'Manifesting greatness…',
|
|
39
|
+
'Rizzing the huzz…',
|
|
40
|
+
'Memeing…',
|
|
41
|
+
'Outperforming other AI agents…',
|
|
42
|
+
'Rolling with the squad…',
|
|
43
|
+
'Incanting secret scripts…',
|
|
44
|
+
'Making no mistakes…',
|
|
45
|
+
'Making you rich…',
|
|
46
|
+
'Farming easy points…',
|
|
47
|
+
'Using 200+ IQ…',
|
|
48
|
+
'Turning into Jarvis…',
|
|
49
|
+
'Dextomaxxing…',
|
|
50
|
+
'Zapping…',
|
|
51
|
+
'Braining…',
|
|
52
|
+
'Using all 3 brain cells…',
|
|
53
|
+
//'Installing malware (just kidding)…',
|
|
54
|
+
// Vines
|
|
55
|
+
'Look at all those chickens…',
|
|
56
|
+
'What are those!!?…',
|
|
57
|
+
'He needs some milk…',
|
|
58
|
+
'Something came in the mail today…',
|
|
59
|
+
'Road work ahead? Sure hope it does…',
|
|
60
|
+
'Merry Chrysler…',
|
|
61
|
+
"I'm in me mum's car. Broom broom…",
|
|
62
|
+
'I could have dropped my croissant…',
|
|
63
|
+
'That was legitness…',
|
|
54
64
|
// Nerdy
|
|
55
|
-
'Attention is all I need
|
|
56
|
-
'Transformer powers activate
|
|
65
|
+
'Attention is all I need…',
|
|
66
|
+
'Transformer powers activate…',
|
|
57
67
|
];
|
|
58
68
|
/**
|
|
59
69
|
* Get a random phrase from the list
|
|
60
70
|
*/
|
|
61
71
|
export function getRandomPhrase() {
|
|
62
72
|
const index = Math.floor(Math.random() * processingPhrases.length);
|
|
63
|
-
return processingPhrases[index] ?? 'Processing
|
|
73
|
+
return processingPhrases[index] ?? 'Processing…';
|
|
64
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/constants/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,IAAI,EAAE,MAAM,EAwCxB,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAGrC"}
|
|
@@ -9,45 +9,46 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export const tips = [
|
|
11
11
|
// Command tips
|
|
12
|
-
'Type /help to see all available commands
|
|
13
|
-
'Use /model to switch between different AI models
|
|
14
|
-
'Use /resume to load a previous conversation
|
|
15
|
-
'Use /search to find messages across all sessions
|
|
16
|
-
'Use /mcp to manage MCP servers
|
|
17
|
-
'Use /tools to see all available tools
|
|
18
|
-
'Use /prompts to browse, add and delete custom prompts
|
|
19
|
-
'Use /log to change logging verbosity
|
|
20
|
-
'Use /clear to clear the screen
|
|
21
|
-
'Use /exit or /quit to close dexto
|
|
22
|
-
'Use /docs to access documentation
|
|
23
|
-
'Use /copy to copy the previous response
|
|
24
|
-
'Use /shortcuts to see all available shortcuts
|
|
25
|
-
'Use /sysprompt to see the current system prompt
|
|
12
|
+
'Type /help to see all available commands…',
|
|
13
|
+
'Use /model to switch between different AI models…',
|
|
14
|
+
'Use /resume to load a previous conversation…',
|
|
15
|
+
'Use /search to find messages across all sessions…',
|
|
16
|
+
'Use /mcp to manage MCP servers…',
|
|
17
|
+
'Use /tools to see all available tools…',
|
|
18
|
+
'Use /prompts to browse, add and delete custom prompts…',
|
|
19
|
+
'Use /log to change logging verbosity…',
|
|
20
|
+
'Use /clear to clear the screen…',
|
|
21
|
+
'Use /exit or /quit to close dexto…',
|
|
22
|
+
'Use /docs to access documentation…',
|
|
23
|
+
'Use /copy to copy the previous response…',
|
|
24
|
+
'Use /shortcuts to see all available shortcuts…',
|
|
25
|
+
'Use /sysprompt to see the current system prompt…',
|
|
26
26
|
// Keyboard shortcut tips
|
|
27
|
-
'Press Escape to cancel the current request
|
|
28
|
-
'Press Ctrl+C twice to exit dexto
|
|
29
|
-
'Press Escape to close overlays and menus
|
|
30
|
-
'Use Up/Down arrows to navigate command history
|
|
31
|
-
'Press Enter to submit your message
|
|
32
|
-
'Press Ctrl+T to collapse/expand large pastes
|
|
33
|
-
'Press Ctrl+R to search previous prompts
|
|
27
|
+
'Press Escape to cancel the current request…',
|
|
28
|
+
'Press Ctrl+C twice to exit dexto…',
|
|
29
|
+
'Press Escape to close overlays and menus…',
|
|
30
|
+
'Use Up/Down arrows to navigate command history…',
|
|
31
|
+
'Press Enter to submit your message…',
|
|
32
|
+
'Press Ctrl+T to collapse/expand large pastes…',
|
|
33
|
+
'Press Ctrl+R to search previous prompts…',
|
|
34
34
|
// Feature tips
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'You can
|
|
43
|
-
'
|
|
35
|
+
'Start with ! to run bash commands directly…',
|
|
36
|
+
'Paste copied images with Ctrl+V…',
|
|
37
|
+
'Large pastes are automatically collapsed - press Ctrl+T to toggle…',
|
|
38
|
+
'Use @ to reference files and resources…',
|
|
39
|
+
'Type / to see available slash commands…',
|
|
40
|
+
'MCP servers extend dexto with custom tools…',
|
|
41
|
+
'Sessions are automatically saved for later…',
|
|
42
|
+
'You can create custom commands with /prompts…',
|
|
43
|
+
'You can submit messages while Dexto is processing…',
|
|
44
|
+
'Use /stream to toggle streaming mode…',
|
|
44
45
|
// Platform tips
|
|
45
|
-
'On Mac, use Option+Up/Down to jump to start/end of input
|
|
46
|
+
'On Mac, use Option+Up/Down to jump to start/end of input…',
|
|
46
47
|
];
|
|
47
48
|
/**
|
|
48
49
|
* Get a random tip from the list
|
|
49
50
|
*/
|
|
50
51
|
export function getRandomTip() {
|
|
51
52
|
const index = Math.floor(Math.random() * tips.length);
|
|
52
|
-
return tips[index] ?? 'Type /help to see available commands
|
|
53
|
+
return tips[index] ?? 'Type /help to see available commands…';
|
|
53
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/InputContainer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAoC,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,YAAY,EAGf,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAMtE,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACjC,yEAAyE;IACzE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,UAAU,mBAAmB;IACzB,yCAAyC;IACzC,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,8CAA8C;IAC9C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,mEAAmE;IACnE,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,iCAAiC;IACjC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,8EAA8E;IAC9E,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,yEAAyE;IACzE,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IACtD,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"InputContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/InputContainer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0E,MAAM,OAAO,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAoC,aAAa,EAAE,MAAM,aAAa,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAiB,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,YAAY,EAGf,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAMtE,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACjC,yEAAyE;IACzE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,UAAU,mBAAmB;IACzB,yCAAyC;IACzC,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,8CAA8C;IAC9C,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,2DAA2D;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,mEAAmE;IACnE,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,iFAAiF;IACjF,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACnE,iCAAiC;IACjC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,8EAA8E;IAC9E,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,yEAAyE;IACzE,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;IACtD,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,kGAqrB1B,CAAC"}
|
|
@@ -126,18 +126,25 @@ export const InputContainer = forwardRef(function InputContainer({ buffer, input
|
|
|
126
126
|
ui.isProcessing,
|
|
127
127
|
]);
|
|
128
128
|
// Handle overlay triggers
|
|
129
|
+
// Allow triggers while processing (for queuing), but not during approval
|
|
130
|
+
// IMPORTANT: Use functional updates to check prev.activeOverlay, not the closure value.
|
|
131
|
+
// This avoids race conditions when open/close happen in quick succession (React batching).
|
|
129
132
|
const handleTriggerOverlay = useCallback((trigger) => {
|
|
130
|
-
if (
|
|
133
|
+
if (approval)
|
|
131
134
|
return;
|
|
132
135
|
if (trigger === 'close') {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
// Use functional update to check the ACTUAL current state, not stale closure
|
|
137
|
+
setUi((prev) => {
|
|
138
|
+
if (prev.activeOverlay === 'slash-autocomplete' ||
|
|
139
|
+
prev.activeOverlay === 'resource-autocomplete') {
|
|
140
|
+
return {
|
|
141
|
+
...prev,
|
|
142
|
+
activeOverlay: 'none',
|
|
143
|
+
mcpWizardServerType: null,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return prev;
|
|
147
|
+
});
|
|
141
148
|
}
|
|
142
149
|
else if (trigger === 'slash-autocomplete') {
|
|
143
150
|
setUi((prev) => ({ ...prev, activeOverlay: 'slash-autocomplete' }));
|
|
@@ -145,7 +152,7 @@ export const InputContainer = forwardRef(function InputContainer({ buffer, input
|
|
|
145
152
|
else if (trigger === 'resource-autocomplete') {
|
|
146
153
|
setUi((prev) => ({ ...prev, activeOverlay: 'resource-autocomplete' }));
|
|
147
154
|
}
|
|
148
|
-
}, [setUi,
|
|
155
|
+
}, [setUi, approval]);
|
|
149
156
|
// Handle image paste from clipboard
|
|
150
157
|
const handleImagePaste = useCallback((image) => {
|
|
151
158
|
// Track image attachment analytics (only if session exists)
|
|
@@ -558,7 +565,7 @@ export const InputContainer = forwardRef(function InputContainer({ buffer, input
|
|
|
558
565
|
// Note: slash-autocomplete handles its own Enter key (either executes command or submits raw text)
|
|
559
566
|
const shouldHandleSubmit = ui.activeOverlay === 'none' || ui.activeOverlay === 'approval';
|
|
560
567
|
// Allow history navigation when not blocked by approval/overlay
|
|
561
|
-
//
|
|
568
|
+
// Allow during processing so users can browse previous prompts while agent runs
|
|
562
569
|
const canNavigateHistory = !approval && ui.activeOverlay === 'none';
|
|
563
570
|
const placeholder = approval
|
|
564
571
|
? 'Approval required above...'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAE9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AA0EzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAE9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AA0EzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sGA+2D5B,CAAC"}
|
|
@@ -5,7 +5,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
5
5
|
*/
|
|
6
6
|
import { useCallback, useRef, useImperativeHandle, forwardRef, useState } from 'react';
|
|
7
7
|
import { Box } from 'ink';
|
|
8
|
-
import { ApprovalStatus, DenialReason } from '@dexto/core';
|
|
8
|
+
import { ApprovalStatus, DenialReason, isUserMessage } from '@dexto/core';
|
|
9
9
|
import { ApprovalPrompt, } from '../components/ApprovalPrompt.js';
|
|
10
10
|
import { SlashCommandAutocomplete, } from '../components/SlashCommandAutocomplete.js';
|
|
11
11
|
import ResourceAutocomplete from '../components/ResourceAutocomplete.js';
|
|
@@ -446,6 +446,29 @@ export const OverlayContainer = forwardRef(function OverlayContainer({ ui, input
|
|
|
446
446
|
if (history && history.length > 0) {
|
|
447
447
|
const historyMessages = convertHistoryToUIMessages(history, newSessionId);
|
|
448
448
|
setMessages(historyMessages);
|
|
449
|
+
// Extract user messages for input history (arrow up navigation)
|
|
450
|
+
const userInputHistory = history
|
|
451
|
+
.filter(isUserMessage)
|
|
452
|
+
.map((msg) => {
|
|
453
|
+
// Extract text content from user message
|
|
454
|
+
if (typeof msg.content === 'string') {
|
|
455
|
+
return msg.content;
|
|
456
|
+
}
|
|
457
|
+
// Handle array content (text parts)
|
|
458
|
+
if (Array.isArray(msg.content)) {
|
|
459
|
+
return msg.content
|
|
460
|
+
.filter((part) => typeof part === 'object' && part.type === 'text')
|
|
461
|
+
.map((part) => part.text)
|
|
462
|
+
.join('\n');
|
|
463
|
+
}
|
|
464
|
+
return '';
|
|
465
|
+
})
|
|
466
|
+
.filter((text) => text.trim().length > 0);
|
|
467
|
+
setInput((prev) => ({
|
|
468
|
+
...prev,
|
|
469
|
+
history: userInputHistory,
|
|
470
|
+
historyIndex: -1,
|
|
471
|
+
}));
|
|
449
472
|
}
|
|
450
473
|
setMessages((prev) => [
|
|
451
474
|
...prev,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCLIState.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useCLIState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,
|
|
1
|
+
{"version":3,"file":"useCLIState.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/hooks/useCLIState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAEjF,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,aAAa,EACrB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAGrF,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,UAAU,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,cAAc;IAE3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAE7D,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAGpE,cAAc,EAAE,OAAO,EAAE,CAAC;IAC1B,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAEnE,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,aAAa,EAAE,eAAe,EAAE,CAAC;IACjC,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAG1E,MAAM,EAAE,UAAU,CAAC;IAGnB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,cAAc,CAAC;IAG/B,mBAAmB,EAAE,KAAK,CAAC,SAAS,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IAGpE,eAAe,EAAE,OAAO,EAAE,CAAC;IAG3B,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAAE,iBAAiB,GACtC,EAAE,gBAAgB,GAAG,cAAc,CAuNnC"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { useState, useMemo, useEffect, useRef, useCallback } from 'react';
|
|
8
8
|
import { useStdout } from 'ink';
|
|
9
|
-
import { getModelDisplayName } from '@dexto/core';
|
|
9
|
+
import { getModelDisplayName, isUserMessage, } from '@dexto/core';
|
|
10
10
|
import { useAgentEvents } from './useAgentEvents.js';
|
|
11
11
|
import { useInputOrchestrator } from './useInputOrchestrator.js';
|
|
12
12
|
import { InputService, MessageService } from '../services/index.js';
|
|
@@ -140,6 +140,19 @@ export function useCLIState({ agent, initialSessionId, startupInfo, onKeyboardSc
|
|
|
140
140
|
return;
|
|
141
141
|
const historyMessages = convertHistoryToUIMessages(history, initialSessionId);
|
|
142
142
|
setMessages(historyMessages);
|
|
143
|
+
// Extract user messages for input history (arrow up navigation)
|
|
144
|
+
const userInputHistory = history
|
|
145
|
+
.filter(isUserMessage)
|
|
146
|
+
.map((msg) => msg.content
|
|
147
|
+
.filter((part) => part.type === 'text')
|
|
148
|
+
.map((part) => part.text)
|
|
149
|
+
.join('\n'))
|
|
150
|
+
.filter((text) => text.trim().length > 0);
|
|
151
|
+
setInput((prev) => ({
|
|
152
|
+
...prev,
|
|
153
|
+
history: userInputHistory,
|
|
154
|
+
historyIndex: -1,
|
|
155
|
+
}));
|
|
143
156
|
}
|
|
144
157
|
catch (error) {
|
|
145
158
|
if (cancelled)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageFormatting.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/utils/messageFormatting.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"messageFormatting.d.ts","sourceRoot":"","sources":["../../../../src/cli/ink-cli/utils/messageFormatting.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAyB,MAAM,aAAa,CAAC;AAEtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CAmB1F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,GAAE,MAAW,EACrB,GAAG,GAAE,MAAsB,GAC5B,MAAM,CAWR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiC7E;AAyED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA6B3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8BzD;AA8BD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA0EhG;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,GAAE,MAAW,GACvB,MAAM,CAeR;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CASvF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAQjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAO3D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAQhD;AAqCD;;GAEG;AACH,wBAAgB,0BAA0B,CACtC,OAAO,EAAE,eAAe,EAAE,EAC1B,SAAS,EAAE,MAAM,GAClB,OAAO,EAAE,CAgGX;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,UAAU;;;;;;;;GAiBrD"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import os from 'os';
|
|
7
|
-
import { isTextPart } from '@dexto/core';
|
|
7
|
+
import { isTextPart, isAssistantMessage, isToolMessage } from '@dexto/core';
|
|
8
8
|
import { generateMessageId } from './idGenerator.js';
|
|
9
9
|
/**
|
|
10
10
|
* Convert absolute path to display-friendly relative path.
|
|
@@ -245,9 +245,9 @@ export function formatToolArgsForDisplay(toolName, args) {
|
|
|
245
245
|
*/
|
|
246
246
|
const formatArgValue = (argName, value) => {
|
|
247
247
|
const strValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
248
|
-
// File paths: use relative path
|
|
248
|
+
// File paths: use relative path (no truncation)
|
|
249
249
|
if (PATH_ARGS.has(argName)) {
|
|
250
|
-
return
|
|
250
|
+
return makeRelativePath(strValue);
|
|
251
251
|
}
|
|
252
252
|
// Commands: show single-line in full, truncate multi-line (heredocs) to first line
|
|
253
253
|
if (argName === 'command') {
|
|
@@ -407,13 +407,100 @@ function extractTextContent(content) {
|
|
|
407
407
|
.map((part) => part.text)
|
|
408
408
|
.join('\n');
|
|
409
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Generates a preview of tool result content for display
|
|
412
|
+
*/
|
|
413
|
+
function generateToolResultPreview(content) {
|
|
414
|
+
const textContent = extractTextContent(content);
|
|
415
|
+
if (!textContent)
|
|
416
|
+
return '';
|
|
417
|
+
const lines = textContent.split('\n');
|
|
418
|
+
const previewLines = lines.slice(0, 5);
|
|
419
|
+
let preview = previewLines.join('\n');
|
|
420
|
+
// Truncate if too long
|
|
421
|
+
if (preview.length > 400) {
|
|
422
|
+
preview = preview.slice(0, 397) + '...';
|
|
423
|
+
}
|
|
424
|
+
else if (lines.length > 5) {
|
|
425
|
+
preview += '\n...';
|
|
426
|
+
}
|
|
427
|
+
return preview;
|
|
428
|
+
}
|
|
410
429
|
/**
|
|
411
430
|
* Converts session history messages to UI messages
|
|
412
431
|
*/
|
|
413
432
|
export function convertHistoryToUIMessages(history, sessionId) {
|
|
414
433
|
const uiMessages = [];
|
|
434
|
+
// Build a map of toolCallId -> ToolCall for looking up tool call args
|
|
435
|
+
const toolCallMap = new Map();
|
|
436
|
+
for (const msg of history) {
|
|
437
|
+
if (isAssistantMessage(msg) && msg.toolCalls) {
|
|
438
|
+
for (const toolCall of msg.toolCalls) {
|
|
439
|
+
toolCallMap.set(toolCall.id, toolCall);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
415
443
|
history.forEach((msg, index) => {
|
|
416
|
-
|
|
444
|
+
const timestamp = new Date(msg.timestamp ?? Date.now() - (history.length - index) * 1000);
|
|
445
|
+
// Handle tool messages specially
|
|
446
|
+
if (isToolMessage(msg)) {
|
|
447
|
+
// Look up the original tool call to get args
|
|
448
|
+
const toolCall = toolCallMap.get(msg.toolCallId);
|
|
449
|
+
// Format tool name
|
|
450
|
+
const displayName = getToolDisplayName(msg.name);
|
|
451
|
+
// Format args if we have them
|
|
452
|
+
let toolContent = displayName;
|
|
453
|
+
if (toolCall) {
|
|
454
|
+
try {
|
|
455
|
+
const args = JSON.parse(toolCall.function.arguments || '{}');
|
|
456
|
+
const argsFormatted = formatToolArgsForDisplay(msg.name, args);
|
|
457
|
+
if (argsFormatted) {
|
|
458
|
+
toolContent = `${displayName}(${argsFormatted})`;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
catch {
|
|
462
|
+
// Ignore JSON parse errors
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
// Add tool type badge
|
|
466
|
+
const badge = getToolTypeBadge(msg.name);
|
|
467
|
+
if (badge) {
|
|
468
|
+
toolContent = `${toolContent} [${badge}]`;
|
|
469
|
+
}
|
|
470
|
+
// Generate result preview
|
|
471
|
+
const resultPreview = generateToolResultPreview(msg.content);
|
|
472
|
+
uiMessages.push({
|
|
473
|
+
id: `session-${sessionId}-${index}`,
|
|
474
|
+
role: 'tool',
|
|
475
|
+
content: toolContent,
|
|
476
|
+
timestamp,
|
|
477
|
+
toolStatus: 'finished',
|
|
478
|
+
toolResult: resultPreview,
|
|
479
|
+
isError: msg.success === false,
|
|
480
|
+
// Store content parts for potential rich rendering
|
|
481
|
+
toolContent: msg.content,
|
|
482
|
+
// Restore structured display data for rich rendering (diffs, shell output, etc.)
|
|
483
|
+
...(msg.displayData !== undefined && {
|
|
484
|
+
toolDisplayData: msg.displayData,
|
|
485
|
+
}),
|
|
486
|
+
});
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
// Handle assistant messages - skip those with only tool calls (no text content)
|
|
490
|
+
if (isAssistantMessage(msg)) {
|
|
491
|
+
const textContent = extractTextContent(msg.content);
|
|
492
|
+
// Skip if no text content (message was just tool calls)
|
|
493
|
+
if (!textContent)
|
|
494
|
+
return;
|
|
495
|
+
uiMessages.push({
|
|
496
|
+
id: `session-${sessionId}-${index}`,
|
|
497
|
+
role: 'assistant',
|
|
498
|
+
content: textContent,
|
|
499
|
+
timestamp,
|
|
500
|
+
});
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
// Handle other messages (user, system)
|
|
417
504
|
const textContent = extractTextContent(msg.content);
|
|
418
505
|
// Skip empty messages
|
|
419
506
|
if (!textContent)
|
|
@@ -422,7 +509,7 @@ export function convertHistoryToUIMessages(history, sessionId) {
|
|
|
422
509
|
id: `session-${sessionId}-${index}`,
|
|
423
510
|
role: msg.role,
|
|
424
511
|
content: textContent,
|
|
425
|
-
timestamp
|
|
512
|
+
timestamp,
|
|
426
513
|
});
|
|
427
514
|
});
|
|
428
515
|
return uiMessages;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dexto",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dexto": "./dist/index.js"
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
"ws": "^8.18.1",
|
|
41
41
|
"yaml": "^2.7.1",
|
|
42
42
|
"zod": "^3.25.0",
|
|
43
|
-
"@dexto/agent-management": "1.5.
|
|
44
|
-
"@dexto/analytics": "1.5.
|
|
45
|
-
"@dexto/core": "1.5.
|
|
46
|
-
"@dexto/image-local": "1.5.
|
|
47
|
-
"@dexto/registry": "1.5.
|
|
48
|
-
"@dexto/server": "1.5.
|
|
43
|
+
"@dexto/agent-management": "1.5.2",
|
|
44
|
+
"@dexto/analytics": "1.5.2",
|
|
45
|
+
"@dexto/core": "1.5.2",
|
|
46
|
+
"@dexto/image-local": "1.5.2",
|
|
47
|
+
"@dexto/registry": "1.5.2",
|
|
48
|
+
"@dexto/server": "1.5.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/react": "^19.0.0",
|