@iaforged/context-code 1.1.7 → 1.2.1
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/README.md +56 -0
- package/dist/src/commands/agent/agent.js +62 -0
- package/dist/src/commands/agent/index.js +1 -1
- package/dist/src/commands/model/model.js +9 -5
- package/dist/src/commands/orchestrate/index.js +2 -2
- package/dist/src/commands/orchestrate/orchestrate.js +12 -627
- package/dist/src/commands/tasks/index.js +1 -1
- package/dist/src/commands/tasks/tasks.js +8 -3
- package/dist/src/commands/team/index.js +2 -2
- package/dist/src/commands/team/team.js +12 -589
- package/dist/src/commands/timeline/index.js +8 -0
- package/dist/src/commands/timeline/timeline.js +194 -0
- package/dist/src/commands/workspace/workspace.js +3 -3
- package/dist/src/commands.js +2 -6
- package/dist/src/components/AgentActivitySidebar.js +50 -0
- package/dist/src/components/AgentProgressLine.js +5 -5
- package/dist/src/components/ModelPicker.js +252 -441
- package/dist/src/components/PromptInput/Notifications.js +1 -1
- package/dist/src/components/PromptInput/PromptInput.js +7 -3
- package/dist/src/components/PromptInput/PromptInputFooter.js +10 -29
- package/dist/src/components/Spinner/TeammateSpinnerLine.js +20 -62
- package/dist/src/components/Spinner/TeammateSpinnerTree.js +16 -258
- package/dist/src/components/Spinner/teammateSelectHint.js +1 -1
- package/dist/src/components/Spinner/utils.js +3 -6
- package/dist/src/components/ThemeBrowser.js +120 -0
- package/dist/src/components/ThemePicker.js +113 -321
- package/dist/src/components/design-system/ThemeProvider.js +3 -0
- package/dist/src/components/mcp/MCPListPanel.js +138 -444
- package/dist/src/components/permissions/SandboxPermissionRequest.js +5 -5
- package/dist/src/components/teams/TeamStatus.js +7 -71
- package/dist/src/constants/spinnerVerbs.js +80 -180
- package/dist/src/context/modalStackContext.js +12 -0
- package/dist/src/hooks/useTextInput.js +28 -18
- package/dist/src/main.js +12 -0
- package/dist/src/screens/REPL.js +386 -320
- package/dist/src/services/api/errors.js +1 -1
- package/dist/src/services/api/openai.js +70 -22
- package/dist/src/services/api/withRetry.js +3 -2
- package/dist/src/skills/loadSkillsDir.js +1 -0
- package/dist/src/tools/AgentTool/UI.js +8 -8
- package/dist/src/tools/AgentTool/loadAgentsDir.js +9 -4
- package/dist/src/tools/AgentTool/providerAgents.js +71 -0
- package/dist/src/tools/BashTool/bashSecurity.js +1 -1
- package/dist/src/utils/handlePromptSubmit.js +12 -2
- package/dist/src/utils/processUserInput/processSlashCommand.js +9 -5
- package/dist/src/utils/sembleMcp/common.js +5 -0
- package/dist/src/utils/sembleMcp/setup.js +119 -0
- package/dist/src/utils/theme.js +24 -3
- package/dist/src/utils/themes/bootstrap.js +109 -0
- package/dist/src/utils/themes/builtin/opencode/_index.json +41 -0
- package/dist/src/utils/themes/builtin/opencode/amoled.json +49 -0
- package/dist/src/utils/themes/builtin/opencode/aura.json +51 -0
- package/dist/src/utils/themes/builtin/opencode/ayu.json +51 -0
- package/dist/src/utils/themes/builtin/opencode/carbonfox.json +53 -0
- package/dist/src/utils/themes/builtin/opencode/catppuccin-frappe.json +85 -0
- package/dist/src/utils/themes/builtin/opencode/catppuccin-macchiato.json +85 -0
- package/dist/src/utils/themes/builtin/opencode/catppuccin.json +45 -0
- package/dist/src/utils/themes/builtin/opencode/cobalt2.json +87 -0
- package/dist/src/utils/themes/builtin/opencode/cursor.json +91 -0
- package/dist/src/utils/themes/builtin/opencode/dracula.json +49 -0
- package/dist/src/utils/themes/builtin/opencode/everforest.json +89 -0
- package/dist/src/utils/themes/builtin/opencode/flexoki.json +86 -0
- package/dist/src/utils/themes/builtin/opencode/github.json +85 -0
- package/dist/src/utils/themes/builtin/opencode/gruvbox.json +45 -0
- package/dist/src/utils/themes/builtin/opencode/kanagawa.json +89 -0
- package/dist/src/utils/themes/builtin/opencode/lucent-orng.json +87 -0
- package/dist/src/utils/themes/builtin/opencode/material.json +87 -0
- package/dist/src/utils/themes/builtin/opencode/matrix.json +91 -0
- package/dist/src/utils/themes/builtin/opencode/mercury.json +86 -0
- package/dist/src/utils/themes/builtin/opencode/monokai.json +49 -0
- package/dist/src/utils/themes/builtin/opencode/nightowl.json +46 -0
- package/dist/src/utils/themes/builtin/opencode/nord.json +46 -0
- package/dist/src/utils/themes/builtin/opencode/oc-2.json +88 -0
- package/dist/src/utils/themes/builtin/opencode/one-dark.json +89 -0
- package/dist/src/utils/themes/builtin/opencode/onedarkpro.json +45 -0
- package/dist/src/utils/themes/builtin/opencode/opencode.json +89 -0
- package/dist/src/utils/themes/builtin/opencode/orng.json +87 -0
- package/dist/src/utils/themes/builtin/opencode/osaka-jade.json +88 -0
- package/dist/src/utils/themes/builtin/opencode/palenight.json +85 -0
- package/dist/src/utils/themes/builtin/opencode/rosepine.json +85 -0
- package/dist/src/utils/themes/builtin/opencode/shadesofpurple.json +51 -0
- package/dist/src/utils/themes/builtin/opencode/solarized.json +49 -0
- package/dist/src/utils/themes/builtin/opencode/synthwave84.json +87 -0
- package/dist/src/utils/themes/builtin/opencode/tokyonight.json +47 -0
- package/dist/src/utils/themes/builtin/opencode/vercel.json +90 -0
- package/dist/src/utils/themes/builtin/opencode/vesper.json +51 -0
- package/dist/src/utils/themes/builtin/opencode/zenburn.json +87 -0
- package/dist/src/utils/themes/index.js +4 -0
- package/dist/src/utils/themes/loader.js +147 -0
- package/dist/src/utils/themes/opencodeMapper.js +124 -0
- package/dist/src/utils/themes/resolver.js +66 -0
- package/dist/src/utils/themes/types.js +1 -0
- package/docs/MCP_SERVERS.md +27 -1
- package/docs/comandos.md +16 -4
- package/package.json +1 -1
|
@@ -217,5 +217,5 @@ function NotificationContent({ ideSelection, mcpClients, notifications, isInOver
|
|
|
217
217
|
if (feature('VOICE_MODE') && voiceEnabled && (voiceState === 'recording' || voiceState === 'processing')) {
|
|
218
218
|
return _jsx(VoiceIndicator, { voiceState: voiceState });
|
|
219
219
|
}
|
|
220
|
-
return _jsxs(_Fragment, { children: [_jsx(IdeStatusIndicator, { ideSelection: ideSelection, mcpClients: mcpClients }), notifications.current && ('jsx' in notifications.current ? _jsx(Text, { wrap: "truncate", children: notifications.current.jsx }, notifications.current.key) : _jsx(Text, { color: notifications.current.color, dimColor: !notifications.current.color, wrap: "truncate", children: notifications.current.text })), isInOverageMode && !isTeamOrEnterprise && _jsx(Box, { children: _jsx(Text, { dimColor: true, wrap: "truncate", children: "Now using extra usage" }) }), apiKeyHelperSlow && _jsxs(Box, { children: [_jsxs(Text, { color: "warning", wrap: "truncate", children: ["apiKeyHelper is taking a while", ' '] }), _jsxs(Text, { dimColor: true, wrap: "truncate", children: ["(", apiKeyHelperSlow, ")"] })] }), (apiKeyStatus === 'invalid' || apiKeyStatus === 'missing') && _jsx(Box, { children: _jsx(Text, { color: "error", wrap: "truncate", children: isEnvTruthy(process.env.CLAUDE_CODE_REMOTE) ? '
|
|
220
|
+
return _jsxs(_Fragment, { children: [_jsx(IdeStatusIndicator, { ideSelection: ideSelection, mcpClients: mcpClients }), notifications.current && ('jsx' in notifications.current ? _jsx(Text, { wrap: "truncate", children: notifications.current.jsx }, notifications.current.key) : _jsx(Text, { color: notifications.current.color, dimColor: !notifications.current.color, wrap: "truncate", children: notifications.current.text })), isInOverageMode && !isTeamOrEnterprise && _jsx(Box, { children: _jsx(Text, { dimColor: true, wrap: "truncate", children: "Now using extra usage" }) }), apiKeyHelperSlow && _jsxs(Box, { children: [_jsxs(Text, { color: "warning", wrap: "truncate", children: ["apiKeyHelper is taking a while", ' '] }), _jsxs(Text, { dimColor: true, wrap: "truncate", children: ["(", apiKeyHelperSlow, ")"] })] }), (apiKeyStatus === 'invalid' || apiKeyStatus === 'missing') && _jsx(Box, { children: _jsx(Text, { color: "error", wrap: "truncate", children: isEnvTruthy(process.env.CLAUDE_CODE_REMOTE) ? 'Error de autenticacion · intenta de nuevo' : 'No has iniciado sesion · Ejecuta /login' }) }), debug && _jsx(Box, { children: _jsx(Text, { color: "warning", wrap: "truncate", children: "Debug mode" }) }), apiKeyStatus !== 'invalid' && apiKeyStatus !== 'missing' && verbose && _jsx(Box, { children: _jsxs(Text, { dimColor: true, wrap: "truncate", children: [tokenUsage, " tokens"] }) }), !isBriefOnly && _jsx(TokenWarning, { tokenUsage: tokenUsage, model: mainLoopModel }), shouldShowAutoUpdater && _jsx(AutoUpdaterWrapper, { verbose: verbose, onAutoUpdaterResult: onAutoUpdaterResult, autoUpdaterResult: autoUpdaterResult, isUpdating: isAutoUpdating, onChangeIsUpdating: onChangeIsUpdating, showSuccessMessage: !isShowingCompactMessage }), feature('VOICE_MODE') ? voiceEnabled && voiceError && _jsx(Box, { children: _jsx(Text, { color: "error", wrap: "truncate", children: voiceError }) }) : null, _jsx(MemoryUsageIndicator, {}), _jsx(SandboxPromptFooterHint, {})] });
|
|
221
221
|
}
|
|
@@ -121,11 +121,15 @@ function PromptInput({ debug, ideSelection, toolPermissionContext, setToolPermis
|
|
|
121
121
|
// Track the last input value set via internal handlers so we can detect
|
|
122
122
|
// external input changes (e.g. speech-to-text injection) and move cursor to end.
|
|
123
123
|
const lastInternalInputRef = React.useRef(input);
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (input === lastInternalInputRef.current) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Input changed externally (not through any internal handler) — move cursor to end.
|
|
129
|
+
// Keep this in an effect to avoid state updates during render.
|
|
126
130
|
setCursorOffset(input.length);
|
|
127
131
|
lastInternalInputRef.current = input;
|
|
128
|
-
}
|
|
132
|
+
}, [input]);
|
|
129
133
|
// Wrap onInputChange to track internal changes before they trigger re-render
|
|
130
134
|
const trackAndSetInput = React.useCallback((value) => {
|
|
131
135
|
lastInternalInputRef.current = value;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { feature } from '../../recovery/bunBundleShim.js';
|
|
1
|
+
import { MACRO, feature } from '../../recovery/bunBundleShim.js';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { memo, useMemo, useRef } from 'react';
|
|
4
4
|
import { isBridgeEnabled } from '../../bridge/bridgeEnabled.js';
|
|
@@ -23,27 +23,15 @@ function PromptInputFooter({ apiKeyStatus, debug, exitMessage, vimMode, mode, au
|
|
|
23
23
|
messagesRef.current = messages;
|
|
24
24
|
const lastAssistantMessageId = useMemo(() => getLastAssistantMessageId(messages), [messages]);
|
|
25
25
|
const isNarrow = columns < 80;
|
|
26
|
-
// In fullscreen the bottom slot is flexShrink:0, so every row here is a row
|
|
27
|
-
// stolen from the ScrollBox. Drop the optional StatusLine first. Non-fullscreen
|
|
28
|
-
// has terminal scrollback to absorb overflow, so we never hide StatusLine there.
|
|
29
26
|
const isFullscreen = isFullscreenEnvEnabled();
|
|
30
27
|
const isShort = isFullscreen && rows < 24;
|
|
31
|
-
// Pill highlights when tasks is the active footer item AND no specific
|
|
32
|
-
// agent row is selected. When coordinatorTaskIndex >= 0 the pointer has
|
|
33
|
-
// moved into CoordinatorTaskPanel, so the pill should un-highlight.
|
|
34
|
-
// coordinatorTaskCount === 0 covers the bash-only case (no agent rows
|
|
35
|
-
// exist, pill is the only selectable item).
|
|
36
28
|
const coordinatorTaskCount = useCoordinatorTaskCount();
|
|
37
29
|
const coordinatorTaskIndex = useAppState(s => s.coordinatorTaskIndex);
|
|
30
|
+
const mainLoopModel = useAppState(s => s.mainLoopModelForSession ?? s.mainLoopModel);
|
|
31
|
+
const modelStatusText = isNarrow ? `Modelo: ${mainLoopModel}` : `ContextCode v${MACRO.VERSION} · Modelo activo: ${mainLoopModel}`;
|
|
38
32
|
const pillSelected = tasksSelected && (coordinatorTaskCount === 0 || coordinatorTaskIndex < 0);
|
|
39
|
-
// Hide `? for shortcuts` if the user has a custom status line, or during ctrl-r
|
|
40
33
|
const suppressHint = suppressHintFromProps || statusLineShouldDisplay(settings) || isSearching;
|
|
41
|
-
|
|
42
|
-
const overlayData = useMemo(() => isFullscreen && suggestions.length ? {
|
|
43
|
-
suggestions,
|
|
44
|
-
selectedSuggestion,
|
|
45
|
-
maxColumnWidth
|
|
46
|
-
} : null, [isFullscreen, suggestions, selectedSuggestion, maxColumnWidth]);
|
|
34
|
+
const overlayData = useMemo(() => isFullscreen && suggestions.length ? { suggestions, selectedSuggestion, maxColumnWidth } : null, [isFullscreen, suggestions, selectedSuggestion, maxColumnWidth]);
|
|
47
35
|
useSetPromptOverlay(overlayData);
|
|
48
36
|
if (suggestions.length && !isFullscreen) {
|
|
49
37
|
return _jsx(Box, { paddingX: 2, paddingY: 0, children: _jsx(PromptInputFooterSuggestions, { suggestions: suggestions, selectedSuggestion: selectedSuggestion, maxColumnWidth: maxColumnWidth }) });
|
|
@@ -51,7 +39,7 @@ function PromptInputFooter({ apiKeyStatus, debug, exitMessage, vimMode, mode, au
|
|
|
51
39
|
if (helpOpen) {
|
|
52
40
|
return _jsx(PromptInputHelpMenu, { dimColor: true, fixedWidth: true, paddingX: 2 });
|
|
53
41
|
}
|
|
54
|
-
return _jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: isNarrow ? 'column' : 'row', justifyContent: isNarrow ? 'flex-start' : 'space-between', paddingX: 2, gap: isNarrow ? 0 : 1, children: [_jsxs(Box, { flexDirection: "column", flexShrink: isNarrow ? 0 : 1, children: [mode === 'prompt' && !isShort && !exitMessage.show && !isPasting && statusLineShouldDisplay(settings) && _jsx(StatusLine, { messagesRef: messagesRef, lastAssistantMessageId: lastAssistantMessageId, vimMode: vimMode }), _jsx(PromptInputFooterLeftSide, { exitMessage: exitMessage, vimMode: vimMode, mode: mode, toolPermissionContext: toolPermissionContext, suppressHint: suppressHint, isLoading: isLoading, tasksSelected: pillSelected, teamsSelected: teamsSelected, teammateFooterIndex: teammateFooterIndex, tmuxSelected: tmuxSelected, isPasting: isPasting, isSearching: isSearching, historyQuery: historyQuery, setHistoryQuery: setHistoryQuery, historyFailedMatch: historyFailedMatch, onOpenTasksDialog: onOpenTasksDialog })] }), _jsxs(Box, { flexShrink: 1, gap: 1, children: [isFullscreen ? null : _jsx(Notifications, { apiKeyStatus: apiKeyStatus, autoUpdaterResult: autoUpdaterResult, debug: debug, isAutoUpdating: isAutoUpdating, verbose: verbose, messages: messages, onAutoUpdaterResult: onAutoUpdaterResult, onChangeIsUpdating: onChangeIsUpdating, ideSelection: ideSelection, mcpClients: mcpClients, isInputWrapped: isInputWrapped, isNarrow: isNarrow }), process.env.USER_TYPE === 'ant' && isUndercover() && _jsx(Text, { dimColor: true, children: "undercover" }), _jsx(BridgeStatusIndicator, { bridgeSelected: bridgeSelected })] })] }), process.env.USER_TYPE === 'ant' && _jsx(CoordinatorTaskPanel, {})] });
|
|
42
|
+
return _jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: isNarrow ? 'column' : 'row', justifyContent: isNarrow ? 'flex-start' : 'space-between', paddingX: 2, gap: isNarrow ? 0 : 1, children: [_jsxs(Box, { flexDirection: "column", flexShrink: isNarrow ? 0 : 1, children: [mode === 'prompt' && !isShort && !exitMessage.show && !isPasting && statusLineShouldDisplay(settings) && _jsx(StatusLine, { messagesRef: messagesRef, lastAssistantMessageId: lastAssistantMessageId, vimMode: vimMode }), _jsx(PromptInputFooterLeftSide, { exitMessage: exitMessage, vimMode: vimMode, mode: mode, toolPermissionContext: toolPermissionContext, suppressHint: suppressHint, isLoading: isLoading, tasksSelected: pillSelected, teamsSelected: teamsSelected, teammateFooterIndex: teammateFooterIndex, tmuxSelected: tmuxSelected, isPasting: isPasting, isSearching: isSearching, historyQuery: historyQuery, setHistoryQuery: setHistoryQuery, historyFailedMatch: historyFailedMatch, onOpenTasksDialog: onOpenTasksDialog })] }), _jsxs(Box, { flexShrink: 1, gap: 1, children: [isFullscreen ? null : _jsx(Notifications, { apiKeyStatus: apiKeyStatus, autoUpdaterResult: autoUpdaterResult, debug: debug, isAutoUpdating: isAutoUpdating, verbose: verbose, messages: messages, onAutoUpdaterResult: onAutoUpdaterResult, onChangeIsUpdating: onChangeIsUpdating, ideSelection: ideSelection, mcpClients: mcpClients, isInputWrapped: isInputWrapped, isNarrow: isNarrow }), process.env.USER_TYPE === 'ant' && isUndercover() && _jsx(Text, { dimColor: true, children: "undercover" }), _jsx(BridgeStatusIndicator, { bridgeSelected: bridgeSelected })] })] }), _jsx(Box, { paddingX: 2, children: _jsx(Text, { dimColor: true, wrap: "truncate", children: modelStatusText }) }), process.env.USER_TYPE === 'ant' && _jsx(CoordinatorTaskPanel, {})] });
|
|
55
43
|
}
|
|
56
44
|
export default memo(PromptInputFooter);
|
|
57
45
|
function BridgeStatusIndicator({ bridgeSelected }) {
|
|
@@ -60,23 +48,16 @@ function BridgeStatusIndicator({ bridgeSelected }) {
|
|
|
60
48
|
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
|
61
49
|
const enabled = useAppState(s => s.replBridgeEnabled);
|
|
62
50
|
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
|
63
|
-
const connected = useAppState(
|
|
51
|
+
const connected = useAppState(s => s.replBridgeConnected);
|
|
64
52
|
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
|
65
|
-
const sessionActive = useAppState(
|
|
53
|
+
const sessionActive = useAppState(s => s.replBridgeSessionActive);
|
|
66
54
|
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
|
67
|
-
const reconnecting = useAppState(
|
|
55
|
+
const reconnecting = useAppState(s => s.replBridgeReconnecting);
|
|
68
56
|
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
|
69
|
-
const explicit = useAppState(
|
|
70
|
-
// Failed state is surfaced via notification (useReplBridge), not a footer pill.
|
|
57
|
+
const explicit = useAppState(s => s.replBridgeExplicit);
|
|
71
58
|
if (!isBridgeEnabled() || !enabled)
|
|
72
59
|
return null;
|
|
73
|
-
const status = getBridgeStatus({
|
|
74
|
-
error: undefined,
|
|
75
|
-
connected,
|
|
76
|
-
sessionActive,
|
|
77
|
-
reconnecting
|
|
78
|
-
});
|
|
79
|
-
// For implicit (config-driven) remote, only show the reconnecting state
|
|
60
|
+
const status = getBridgeStatus({ error: undefined, connected, sessionActive, reconnecting });
|
|
80
61
|
if (!explicit && status.label !== 'Reconectando Control Remoto') {
|
|
81
62
|
return null;
|
|
82
63
|
}
|
|
@@ -6,26 +6,20 @@ import { getSpinnerVerbs } from '../../constants/spinnerVerbs.js';
|
|
|
6
6
|
import { TURN_COMPLETION_VERBS } from '../../constants/turnCompletionVerbs.js';
|
|
7
7
|
import { useElapsedTime } from '../../hooks/useElapsedTime.js';
|
|
8
8
|
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
|
|
9
|
-
import { stringWidth } from '../../ink/stringWidth.js';
|
|
10
9
|
import { Box, Text } from '../../ink.js';
|
|
10
|
+
import { stringWidth } from '../../ink/stringWidth.js';
|
|
11
11
|
import { summarizeRecentActivities } from '../../utils/collapseReadSearch.js';
|
|
12
12
|
import { formatDuration, formatNumber, truncateToWidth } from '../../utils/format.js';
|
|
13
13
|
import { toInkColor } from '../../utils/ink.js';
|
|
14
14
|
import { TEAMMATE_SELECT_HINT } from './teammateSelectHint.js';
|
|
15
|
-
/**
|
|
16
|
-
* Extract the last 3 lines of content from a teammate's conversation.
|
|
17
|
-
* Shows recent activity from any message type (user or assistant).
|
|
18
|
-
*/
|
|
19
15
|
function getMessagePreview(messages) {
|
|
20
16
|
if (!messages?.length)
|
|
21
17
|
return [];
|
|
22
18
|
const allLines = [];
|
|
23
19
|
const maxLineLength = 80;
|
|
24
|
-
// Collect lines from recent messages (newest first)
|
|
25
20
|
for (let i = messages.length - 1; i >= 0 && allLines.length < 3; i--) {
|
|
26
21
|
const msg = messages[i];
|
|
27
|
-
|
|
28
|
-
if (!msg || msg.type !== 'user' && msg.type !== 'assistant' || !msg.message?.content?.length) {
|
|
22
|
+
if (!msg || (msg.type !== 'user' && msg.type !== 'assistant') || !msg.message?.content?.length) {
|
|
29
23
|
continue;
|
|
30
24
|
}
|
|
31
25
|
const content = msg.message.content;
|
|
@@ -35,11 +29,9 @@ function getMessagePreview(messages) {
|
|
|
35
29
|
if (!block || typeof block !== 'object')
|
|
36
30
|
continue;
|
|
37
31
|
if ('type' in block && block.type === 'tool_use' && 'name' in block) {
|
|
38
|
-
// Try to show meaningful info from tool input
|
|
39
32
|
const input = 'input' in block ? block.input : null;
|
|
40
|
-
let toolLine = `
|
|
33
|
+
let toolLine = `Usando ${block.name}...`;
|
|
41
34
|
if (input) {
|
|
42
|
-
// Look for common descriptive fields
|
|
43
35
|
const desc = input.description || input.prompt || input.command || input.query || input.pattern;
|
|
44
36
|
if (desc) {
|
|
45
37
|
toolLine = desc.split('\n')[0] ?? toolLine;
|
|
@@ -49,7 +41,6 @@ function getMessagePreview(messages) {
|
|
|
49
41
|
}
|
|
50
42
|
else if ('type' in block && block.type === 'text' && 'text' in block) {
|
|
51
43
|
const textLines = block.text.split('\n').filter(l => l.trim());
|
|
52
|
-
// Take from end of text (most recent lines)
|
|
53
44
|
for (let j = textLines.length - 1; j >= 0 && allLines.length < 3; j--) {
|
|
54
45
|
const line = textLines[j];
|
|
55
46
|
if (!line)
|
|
@@ -59,76 +50,52 @@ function getMessagePreview(messages) {
|
|
|
59
50
|
}
|
|
60
51
|
}
|
|
61
52
|
}
|
|
62
|
-
// Reverse so oldest of the 3 is first (reading order)
|
|
63
53
|
return allLines.reverse();
|
|
64
54
|
}
|
|
65
55
|
export function TeammateSpinnerLine({ teammate, isLast, isSelected, isForegrounded, allIdle, showPreview }) {
|
|
66
56
|
const [randomVerb] = useState(() => teammate.spinnerVerb ?? sample(getSpinnerVerbs()));
|
|
67
57
|
const [pastTenseVerb] = useState(() => teammate.pastTenseVerb ?? sample(TURN_COMPLETION_VERBS));
|
|
68
58
|
const isHighlighted = isSelected || isForegrounded;
|
|
69
|
-
const treeChar = isHighlighted ? isLast ? '╘═' : '╞═' : isLast ? '└─' : '├─';
|
|
59
|
+
const treeChar = isHighlighted ? (isLast ? '╘═' : '╞═') : isLast ? '└─' : '├─';
|
|
70
60
|
const nameColor = toInkColor(teammate.identity.color);
|
|
71
61
|
const { columns } = useTerminalSize();
|
|
72
|
-
// Track when teammate became idle (for "Idle for X..." display)
|
|
73
62
|
const idleStartRef = useRef(null);
|
|
74
|
-
// Freeze elapsed time when entering all-idle state
|
|
75
63
|
const frozenDurationRef = useRef(null);
|
|
76
|
-
// Track idle start time
|
|
77
64
|
if (teammate.isIdle && idleStartRef.current === null) {
|
|
78
65
|
idleStartRef.current = Date.now();
|
|
79
66
|
}
|
|
80
67
|
else if (!teammate.isIdle) {
|
|
81
68
|
idleStartRef.current = null;
|
|
82
69
|
}
|
|
83
|
-
// Reset frozen duration when leaving all-idle state
|
|
84
70
|
if (!allIdle && frozenDurationRef.current !== null) {
|
|
85
71
|
frozenDurationRef.current = null;
|
|
86
72
|
}
|
|
87
|
-
// Get elapsed idle time (how long they've been idle) - for "Idle for X..." display
|
|
88
73
|
const idleElapsedTime = useElapsedTime(idleStartRef.current ?? Date.now(), teammate.isIdle && !allIdle);
|
|
89
|
-
// Freeze the duration when we first detect all idle
|
|
90
|
-
// Use the teammate's actual work time (since task started) for the past-tense display
|
|
91
74
|
if (allIdle && frozenDurationRef.current === null) {
|
|
92
75
|
frozenDurationRef.current = formatDuration(Math.max(0, Date.now() - teammate.startTime - (teammate.totalPausedMs ?? 0)));
|
|
93
76
|
}
|
|
94
|
-
|
|
95
|
-
const displayTime = allIdle ? frozenDurationRef.current ?? (() => {
|
|
96
|
-
throw new Error(`frozenDurationRef is null for idle teammate ${teammate.identity.agentName}`);
|
|
97
|
-
})() : idleElapsedTime;
|
|
98
|
-
// Layout: paddingLeft(3) + pointer(1) + space(1) + treeChar(2) + space(1) = 8 fixed chars
|
|
99
|
-
// Then optionally: @name + ": " OR just ": "
|
|
100
|
-
// Then: activity text + optional extras (stats, hints)
|
|
77
|
+
const displayTime = allIdle ? frozenDurationRef.current ?? '0s' : idleElapsedTime;
|
|
101
78
|
const basePrefix = 8;
|
|
102
79
|
const fullAgentName = `@${teammate.identity.agentName}`;
|
|
103
80
|
const fullNameWidth = stringWidth(fullAgentName);
|
|
104
|
-
// Get stats from progress
|
|
105
81
|
const toolUseCount = teammate.progress?.toolUseCount ?? 0;
|
|
106
82
|
const tokenCount = teammate.progress?.tokenCount ?? 0;
|
|
107
|
-
const statsText = ` · ${toolUseCount}
|
|
83
|
+
const statsText = ` · ${toolUseCount} uso${toolUseCount === 1 ? '' : 's'} de herramienta · ${formatNumber(tokenCount)} tokens`;
|
|
108
84
|
const statsWidth = stringWidth(statsText);
|
|
109
85
|
const selectHintText = ` · ${TEAMMATE_SELECT_HINT}`;
|
|
110
86
|
const selectHintWidth = stringWidth(selectHintText);
|
|
111
|
-
const viewHintText = ' ·
|
|
87
|
+
const viewHintText = ' · Enter para ver';
|
|
112
88
|
const viewHintWidth = stringWidth(viewHintText);
|
|
113
|
-
// Progressive responsive layout:
|
|
114
|
-
// Wide (80+): full name + activity + stats + hint
|
|
115
|
-
// Medium (60-80): full name + activity
|
|
116
|
-
// Narrow (<60): hide name, just show activity
|
|
117
89
|
const minActivityWidth = 25;
|
|
118
|
-
// Hide name on narrow terminals (< 60 cols) or if there's not enough room
|
|
119
90
|
const spaceWithFullName = columns - basePrefix - fullNameWidth - 2;
|
|
120
91
|
const showName = columns >= 60 && spaceWithFullName >= minActivityWidth;
|
|
121
|
-
const nameWidth = showName ? fullNameWidth + 2 : 0;
|
|
92
|
+
const nameWidth = showName ? fullNameWidth + 2 : 0;
|
|
122
93
|
const availableForActivity = columns - basePrefix - nameWidth;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const showViewHint = isSelected && !isForegrounded && availableForActivity > viewHintWidth + statsWidth + minActivityWidth + 5;
|
|
126
|
-
const showSelectHint = isHighlighted && availableForActivity > selectHintWidth + (showViewHint ? viewHintWidth : 0) + statsWidth + minActivityWidth + 5;
|
|
94
|
+
const showViewHint = !!(isSelected && !isForegrounded && availableForActivity > viewHintWidth + statsWidth + minActivityWidth + 5);
|
|
95
|
+
const showSelectHint = !!(isHighlighted && availableForActivity > selectHintWidth + (showViewHint ? viewHintWidth : 0) + statsWidth + minActivityWidth + 5);
|
|
127
96
|
const showStats = availableForActivity > statsWidth + minActivityWidth + 5;
|
|
128
|
-
// Activity text gets remaining space
|
|
129
97
|
const extrasCost = (showStats ? statsWidth : 0) + (showSelectHint ? selectHintWidth : 0) + (showViewHint ? viewHintWidth : 0);
|
|
130
98
|
const activityMaxWidth = Math.max(minActivityWidth, availableForActivity - extrasCost - 1);
|
|
131
|
-
// Format the activity text for active teammates, rolling up search/read ops
|
|
132
99
|
const activityText = (() => {
|
|
133
100
|
const activities = teammate.progress?.recentActivities;
|
|
134
101
|
if (activities && activities.length > 0) {
|
|
@@ -141,30 +108,21 @@ export function TeammateSpinnerLine({ teammate, isLast, isSelected, isForeground
|
|
|
141
108
|
return truncateToWidth(desc, activityMaxWidth);
|
|
142
109
|
return randomVerb;
|
|
143
110
|
})();
|
|
144
|
-
// Status rendering logic
|
|
145
111
|
const renderStatus = () => {
|
|
146
|
-
if (teammate.shutdownRequested)
|
|
147
|
-
return _jsx(Text, { dimColor: true, children: "[
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return _jsx(Text, { color: "warning", children: "[awaiting approval]" });
|
|
151
|
-
}
|
|
112
|
+
if (teammate.shutdownRequested)
|
|
113
|
+
return _jsx(Text, { dimColor: true, children: "[deteniendo]" });
|
|
114
|
+
if (teammate.awaitingPlanApproval)
|
|
115
|
+
return _jsx(Text, { color: "warning", children: "[esperando aprobaci\u00F3n]" });
|
|
152
116
|
if (teammate.isIdle) {
|
|
153
|
-
if (allIdle)
|
|
154
|
-
return _jsxs(Text, { dimColor: true, children: [pastTenseVerb, "
|
|
155
|
-
}
|
|
156
|
-
return _jsxs(Text, { dimColor: true, children: ["Idle for ", idleElapsedTime] });
|
|
117
|
+
if (allIdle)
|
|
118
|
+
return _jsxs(Text, { dimColor: true, children: [pastTenseVerb, " durante ", displayTime] });
|
|
119
|
+
return _jsxs(Text, { dimColor: true, children: ["Inactivo durante ", idleElapsedTime] });
|
|
157
120
|
}
|
|
158
|
-
|
|
159
|
-
// when highlighted, the main spinner above already shows the verb)
|
|
160
|
-
if (isHighlighted) {
|
|
121
|
+
if (isHighlighted)
|
|
161
122
|
return null;
|
|
162
|
-
}
|
|
163
|
-
return _jsx(Text, { dimColor: true, children: activityText?.endsWith('…') ? activityText : `${activityText}…` });
|
|
123
|
+
return _jsx(Text, { dimColor: true, children: activityText?.endsWith('...') ? activityText : `${activityText}...` });
|
|
164
124
|
};
|
|
165
|
-
// Get preview lines if enabled
|
|
166
125
|
const previewLines = showPreview ? getMessagePreview(teammate.messages) : [];
|
|
167
|
-
// Tree continuation character for preview lines
|
|
168
126
|
const previewTreeChar = isLast ? ' ' : '│ ';
|
|
169
|
-
return _jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { paddingLeft: 3, children: [_jsx(Text, { color: isSelected ? 'suggestion' : undefined, bold: isSelected, children: isSelected ? figures.pointer : ' ' }), _jsxs(Text, { dimColor: !isSelected, children: [treeChar, " "] }), showName && _jsxs(Text, { color: isSelected ? 'suggestion' : nameColor, children: ["@", teammate.identity.agentName] }), showName && _jsx(Text, { dimColor: !isSelected, children: ": " }), renderStatus(), showStats &&
|
|
127
|
+
return _jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { paddingLeft: 3, children: [_jsx(Text, { color: isSelected ? 'suggestion' : undefined, bold: isSelected, children: isSelected ? figures.pointer : ' ' }), _jsxs(Text, { dimColor: !isSelected, children: [treeChar, " "] }), showName && _jsxs(Text, { color: isSelected ? 'suggestion' : nameColor, children: ["@", teammate.identity.agentName] }), showName && _jsx(Text, { dimColor: !isSelected, children: ": " }), renderStatus(), showStats && _jsx(Text, { dimColor: true, children: statsText }), showSelectHint && _jsx(Text, { dimColor: true, children: selectHintText }), showViewHint && _jsx(Text, { dimColor: true, children: viewHintText })] }), previewLines.map((line, idx) => _jsxs(Box, { paddingLeft: 3, children: [_jsx(Text, { dimColor: true, children: " " }), _jsxs(Text, { dimColor: true, children: [previewTreeChar, " "] }), _jsx(Text, { dimColor: true, children: line })] }, idx))] });
|
|
170
128
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { c as _c } from "react/compiler-runtime";
|
|
3
2
|
import figures from 'figures';
|
|
4
3
|
import { Box, Text } from '../../ink.js';
|
|
5
4
|
import { useAppState } from '../../state/AppState.js';
|
|
@@ -7,262 +6,21 @@ import { getRunningTeammatesSorted } from '../../tasks/InProcessTeammateTask/InP
|
|
|
7
6
|
import { formatNumber } from '../../utils/format.js';
|
|
8
7
|
import { TeammateSpinnerLine } from './TeammateSpinnerLine.js';
|
|
9
8
|
import { TEAMMATE_SELECT_HINT } from './teammateSelectHint.js';
|
|
10
|
-
export function TeammateSpinnerTree(
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if ($[0] !== allIdle || $[1] !== isInSelectionMode || $[2] !== leaderIdleText || $[3] !== leaderTokenCount || $[4] !== leaderVerb || $[5] !== selectedIndex || $[6] !== showTeammateMessagePreview || $[7] !== tasks || $[8] !== viewingAgentTaskId) {
|
|
24
|
-
t5 = Symbol.for("react.early_return_sentinel");
|
|
25
|
-
bb0: {
|
|
26
|
-
const teammateTasks = getRunningTeammatesSorted(tasks);
|
|
27
|
-
if (teammateTasks.length === 0) {
|
|
28
|
-
t5 = null;
|
|
29
|
-
break bb0;
|
|
30
|
-
}
|
|
31
|
-
const isLeaderForegrounded = viewingAgentTaskId === undefined;
|
|
32
|
-
const isLeaderSelected = isInSelectionMode && selectedIndex === -1;
|
|
33
|
-
const isLeaderHighlighted = isLeaderForegrounded || isLeaderSelected;
|
|
34
|
-
isHideSelected = isInSelectionMode === true && selectedIndex === teammateTasks.length;
|
|
35
|
-
T0 = Box;
|
|
36
|
-
t1 = "column";
|
|
37
|
-
t2 = 1;
|
|
38
|
-
const t6 = isLeaderSelected ? "suggestion" : undefined;
|
|
39
|
-
const t7 = isLeaderSelected ? figures.pointer : " ";
|
|
40
|
-
let t8;
|
|
41
|
-
if ($[16] !== isLeaderHighlighted || $[17] !== t6 || $[18] !== t7) {
|
|
42
|
-
t8 = _jsx(Text, { color: t6, bold: isLeaderHighlighted, children: t7 });
|
|
43
|
-
$[16] = isLeaderHighlighted;
|
|
44
|
-
$[17] = t6;
|
|
45
|
-
$[18] = t7;
|
|
46
|
-
$[19] = t8;
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
t8 = $[19];
|
|
50
|
-
}
|
|
51
|
-
const t9 = !isLeaderHighlighted;
|
|
52
|
-
const t10 = isLeaderHighlighted ? "\u2552\u2550" : "\u250C\u2500";
|
|
53
|
-
let t11;
|
|
54
|
-
if ($[20] !== isLeaderHighlighted || $[21] !== t10 || $[22] !== t9) {
|
|
55
|
-
t11 = _jsxs(Text, { dimColor: t9, bold: isLeaderHighlighted, children: [t10, " "] });
|
|
56
|
-
$[20] = isLeaderHighlighted;
|
|
57
|
-
$[21] = t10;
|
|
58
|
-
$[22] = t9;
|
|
59
|
-
$[23] = t11;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
t11 = $[23];
|
|
63
|
-
}
|
|
64
|
-
const t12 = isLeaderSelected ? "suggestion" : "cyan_FOR_SUBAGENTS_ONLY";
|
|
65
|
-
let t13;
|
|
66
|
-
if ($[24] !== isLeaderHighlighted || $[25] !== t12) {
|
|
67
|
-
t13 = _jsx(Text, { bold: isLeaderHighlighted, color: t12, children: "team-lead" });
|
|
68
|
-
$[24] = isLeaderHighlighted;
|
|
69
|
-
$[25] = t12;
|
|
70
|
-
$[26] = t13;
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
t13 = $[26];
|
|
74
|
-
}
|
|
75
|
-
let t14;
|
|
76
|
-
if ($[27] !== isLeaderForegrounded || $[28] !== leaderVerb) {
|
|
77
|
-
t14 = !isLeaderForegrounded && leaderVerb && _jsxs(Text, { dimColor: true, children: [": ", leaderVerb, "\u2026"] });
|
|
78
|
-
$[27] = isLeaderForegrounded;
|
|
79
|
-
$[28] = leaderVerb;
|
|
80
|
-
$[29] = t14;
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
t14 = $[29];
|
|
84
|
-
}
|
|
85
|
-
let t15;
|
|
86
|
-
if ($[30] !== isLeaderForegrounded || $[31] !== leaderIdleText || $[32] !== leaderVerb) {
|
|
87
|
-
t15 = !isLeaderForegrounded && !leaderVerb && leaderIdleText && _jsxs(Text, { dimColor: true, children: [": ", leaderIdleText] });
|
|
88
|
-
$[30] = isLeaderForegrounded;
|
|
89
|
-
$[31] = leaderIdleText;
|
|
90
|
-
$[32] = leaderVerb;
|
|
91
|
-
$[33] = t15;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
t15 = $[33];
|
|
95
|
-
}
|
|
96
|
-
let t16;
|
|
97
|
-
if ($[34] !== isLeaderHighlighted || $[35] !== leaderTokenCount) {
|
|
98
|
-
t16 = leaderTokenCount !== undefined && leaderTokenCount > 0 && _jsxs(Text, { dimColor: !isLeaderHighlighted, children: [" ", "\u00B7 ", formatNumber(leaderTokenCount), " tokens"] });
|
|
99
|
-
$[34] = isLeaderHighlighted;
|
|
100
|
-
$[35] = leaderTokenCount;
|
|
101
|
-
$[36] = t16;
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
t16 = $[36];
|
|
105
|
-
}
|
|
106
|
-
let t17;
|
|
107
|
-
if ($[37] !== isLeaderHighlighted) {
|
|
108
|
-
t17 = isLeaderHighlighted && _jsxs(Text, { dimColor: true, children: [" \u00B7 ", TEAMMATE_SELECT_HINT] });
|
|
109
|
-
$[37] = isLeaderHighlighted;
|
|
110
|
-
$[38] = t17;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
t17 = $[38];
|
|
114
|
-
}
|
|
115
|
-
let t18;
|
|
116
|
-
if ($[39] !== isLeaderForegrounded || $[40] !== isLeaderSelected) {
|
|
117
|
-
t18 = isLeaderSelected && !isLeaderForegrounded && _jsx(Text, { dimColor: true, children: " \u00B7 enter to view" });
|
|
118
|
-
$[39] = isLeaderForegrounded;
|
|
119
|
-
$[40] = isLeaderSelected;
|
|
120
|
-
$[41] = t18;
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
t18 = $[41];
|
|
124
|
-
}
|
|
125
|
-
if ($[42] !== t11 || $[43] !== t13 || $[44] !== t14 || $[45] !== t15 || $[46] !== t16 || $[47] !== t17 || $[48] !== t18 || $[49] !== t8) {
|
|
126
|
-
t3 = _jsxs(Box, { paddingLeft: 3, children: [t8, t11, t13, t14, t15, t16, t17, t18] });
|
|
127
|
-
$[42] = t11;
|
|
128
|
-
$[43] = t13;
|
|
129
|
-
$[44] = t14;
|
|
130
|
-
$[45] = t15;
|
|
131
|
-
$[46] = t16;
|
|
132
|
-
$[47] = t17;
|
|
133
|
-
$[48] = t18;
|
|
134
|
-
$[49] = t8;
|
|
135
|
-
$[50] = t3;
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
t3 = $[50];
|
|
139
|
-
}
|
|
140
|
-
t4 = teammateTasks.map((teammate, index) => _jsx(TeammateSpinnerLine, { teammate: teammate, isLast: !isInSelectionMode && index === teammateTasks.length - 1, isSelected: isInSelectionMode && selectedIndex === index, isForegrounded: viewingAgentTaskId === teammate.id, allIdle: allIdle, showPreview: showTeammateMessagePreview }, teammate.id));
|
|
141
|
-
}
|
|
142
|
-
$[0] = allIdle;
|
|
143
|
-
$[1] = isInSelectionMode;
|
|
144
|
-
$[2] = leaderIdleText;
|
|
145
|
-
$[3] = leaderTokenCount;
|
|
146
|
-
$[4] = leaderVerb;
|
|
147
|
-
$[5] = selectedIndex;
|
|
148
|
-
$[6] = showTeammateMessagePreview;
|
|
149
|
-
$[7] = tasks;
|
|
150
|
-
$[8] = viewingAgentTaskId;
|
|
151
|
-
$[9] = T0;
|
|
152
|
-
$[10] = isHideSelected;
|
|
153
|
-
$[11] = t1;
|
|
154
|
-
$[12] = t2;
|
|
155
|
-
$[13] = t3;
|
|
156
|
-
$[14] = t4;
|
|
157
|
-
$[15] = t5;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
T0 = $[9];
|
|
161
|
-
isHideSelected = $[10];
|
|
162
|
-
t1 = $[11];
|
|
163
|
-
t2 = $[12];
|
|
164
|
-
t3 = $[13];
|
|
165
|
-
t4 = $[14];
|
|
166
|
-
t5 = $[15];
|
|
167
|
-
}
|
|
168
|
-
if (t5 !== Symbol.for("react.early_return_sentinel")) {
|
|
169
|
-
return t5;
|
|
170
|
-
}
|
|
171
|
-
let t6;
|
|
172
|
-
if ($[51] !== isHideSelected || $[52] !== isInSelectionMode) {
|
|
173
|
-
t6 = isInSelectionMode && _jsx(HideRow, { isSelected: isHideSelected });
|
|
174
|
-
$[51] = isHideSelected;
|
|
175
|
-
$[52] = isInSelectionMode;
|
|
176
|
-
$[53] = t6;
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
t6 = $[53];
|
|
180
|
-
}
|
|
181
|
-
let t7;
|
|
182
|
-
if ($[54] !== T0 || $[55] !== t1 || $[56] !== t2 || $[57] !== t3 || $[58] !== t4 || $[59] !== t6) {
|
|
183
|
-
t7 = _jsxs(T0, { flexDirection: t1, marginTop: t2, children: [t3, t4, t6] });
|
|
184
|
-
$[54] = T0;
|
|
185
|
-
$[55] = t1;
|
|
186
|
-
$[56] = t2;
|
|
187
|
-
$[57] = t3;
|
|
188
|
-
$[58] = t4;
|
|
189
|
-
$[59] = t6;
|
|
190
|
-
$[60] = t7;
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
t7 = $[60];
|
|
194
|
-
}
|
|
195
|
-
return t7;
|
|
9
|
+
export function TeammateSpinnerTree({ selectedIndex, isInSelectionMode, allIdle, leaderVerb, leaderTokenCount, leaderIdleText }) {
|
|
10
|
+
const tasks = useAppState(s => s.tasks);
|
|
11
|
+
const viewingAgentTaskId = useAppState(s => s.viewingAgentTaskId);
|
|
12
|
+
const showTeammateMessagePreview = useAppState(s => s.showTeammateMessagePreview);
|
|
13
|
+
const teammateTasks = getRunningTeammatesSorted(tasks);
|
|
14
|
+
if (teammateTasks.length === 0)
|
|
15
|
+
return null;
|
|
16
|
+
const isLeaderForegrounded = viewingAgentTaskId === undefined;
|
|
17
|
+
const isLeaderSelected = !!isInSelectionMode && selectedIndex === -1;
|
|
18
|
+
const isLeaderHighlighted = isLeaderForegrounded || isLeaderSelected;
|
|
19
|
+
const hideSelected = isInSelectionMode === true && selectedIndex === teammateTasks.length;
|
|
20
|
+
const leaderConnector = isLeaderHighlighted ? '╒═' : '┌─';
|
|
21
|
+
return _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Box, { paddingLeft: 3, children: [_jsx(Text, { color: isLeaderSelected ? 'suggestion' : undefined, bold: isLeaderHighlighted, children: isLeaderSelected ? figures.pointer : ' ' }), _jsxs(Text, { dimColor: !isLeaderHighlighted, bold: isLeaderHighlighted, children: [leaderConnector, " "] }), _jsx(Text, { bold: isLeaderHighlighted, color: isLeaderSelected ? 'suggestion' : 'cyan_FOR_SUBAGENTS_ONLY', children: "l\u00EDder" }), !isLeaderForegrounded && leaderVerb && _jsxs(Text, { dimColor: true, children: [": ", leaderVerb, "..."] }), !isLeaderForegrounded && !leaderVerb && leaderIdleText && _jsxs(Text, { dimColor: true, children: [": ", leaderIdleText] }), leaderTokenCount !== undefined && leaderTokenCount > 0 && _jsxs(Text, { dimColor: !isLeaderHighlighted, children: [" \u00B7 ", formatNumber(leaderTokenCount), " tokens"] }), isLeaderHighlighted && _jsxs(Text, { dimColor: true, children: [" \u00B7 ", TEAMMATE_SELECT_HINT] }), isLeaderSelected && !isLeaderForegrounded && _jsx(Text, { dimColor: true, children: " \u00B7 Enter para ver" })] }), teammateTasks.map((teammate, index) => _jsx(TeammateSpinnerLine, { teammate: teammate, isLast: !isInSelectionMode && index === teammateTasks.length - 1, isSelected: !!isInSelectionMode && selectedIndex === index, isForegrounded: viewingAgentTaskId === teammate.id, allIdle: allIdle, showPreview: showTeammateMessagePreview }, teammate.id)), isInSelectionMode && _jsx(HideRow, { isSelected: hideSelected })] });
|
|
196
22
|
}
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
function _temp2(s_0) {
|
|
201
|
-
return s_0.viewingAgentTaskId;
|
|
202
|
-
}
|
|
203
|
-
function _temp(s) {
|
|
204
|
-
return s.tasks;
|
|
205
|
-
}
|
|
206
|
-
function HideRow(t0) {
|
|
207
|
-
const $ = _c(18);
|
|
208
|
-
const { isSelected } = t0;
|
|
209
|
-
const t1 = isSelected ? "suggestion" : undefined;
|
|
210
|
-
const t2 = isSelected ? figures.pointer : " ";
|
|
211
|
-
let t3;
|
|
212
|
-
if ($[0] !== isSelected || $[1] !== t1 || $[2] !== t2) {
|
|
213
|
-
t3 = _jsx(Text, { color: t1, bold: isSelected, children: t2 });
|
|
214
|
-
$[0] = isSelected;
|
|
215
|
-
$[1] = t1;
|
|
216
|
-
$[2] = t2;
|
|
217
|
-
$[3] = t3;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
t3 = $[3];
|
|
221
|
-
}
|
|
222
|
-
const t4 = !isSelected;
|
|
223
|
-
const t5 = isSelected ? "\u2558\u2550" : "\u2514\u2500";
|
|
224
|
-
let t6;
|
|
225
|
-
if ($[4] !== isSelected || $[5] !== t4 || $[6] !== t5) {
|
|
226
|
-
t6 = _jsxs(Text, { dimColor: t4, bold: isSelected, children: [t5, " "] });
|
|
227
|
-
$[4] = isSelected;
|
|
228
|
-
$[5] = t4;
|
|
229
|
-
$[6] = t5;
|
|
230
|
-
$[7] = t6;
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
t6 = $[7];
|
|
234
|
-
}
|
|
235
|
-
const t7 = !isSelected;
|
|
236
|
-
let t8;
|
|
237
|
-
if ($[8] !== isSelected || $[9] !== t7) {
|
|
238
|
-
t8 = _jsx(Text, { dimColor: t7, bold: isSelected, children: "hide" });
|
|
239
|
-
$[8] = isSelected;
|
|
240
|
-
$[9] = t7;
|
|
241
|
-
$[10] = t8;
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
t8 = $[10];
|
|
245
|
-
}
|
|
246
|
-
let t9;
|
|
247
|
-
if ($[11] !== isSelected) {
|
|
248
|
-
t9 = isSelected && _jsx(Text, { dimColor: true, children: " \u00B7 enter to collapse" });
|
|
249
|
-
$[11] = isSelected;
|
|
250
|
-
$[12] = t9;
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
t9 = $[12];
|
|
254
|
-
}
|
|
255
|
-
let t10;
|
|
256
|
-
if ($[13] !== t3 || $[14] !== t6 || $[15] !== t8 || $[16] !== t9) {
|
|
257
|
-
t10 = _jsxs(Box, { paddingLeft: 3, children: [t3, t6, t8, t9] });
|
|
258
|
-
$[13] = t3;
|
|
259
|
-
$[14] = t6;
|
|
260
|
-
$[15] = t8;
|
|
261
|
-
$[16] = t9;
|
|
262
|
-
$[17] = t10;
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
t10 = $[17];
|
|
266
|
-
}
|
|
267
|
-
return t10;
|
|
23
|
+
function HideRow({ isSelected }) {
|
|
24
|
+
const connector = isSelected ? '╘═' : '└─';
|
|
25
|
+
return _jsxs(Box, { paddingLeft: 3, children: [_jsx(Text, { color: isSelected ? 'suggestion' : undefined, bold: isSelected, children: isSelected ? figures.pointer : ' ' }), _jsxs(Text, { dimColor: !isSelected, bold: isSelected, children: [connector, " "] }), _jsx(Text, { dimColor: !isSelected, bold: isSelected, children: "ocultar" }), isSelected && _jsx(Text, { dimColor: true, children: " \u00B7 Enter para colapsar" })] });
|
|
268
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const TEAMMATE_SELECT_HINT = '
|
|
1
|
+
export const TEAMMATE_SELECT_HINT = 'Shift + ↑/↓ para seleccionar';
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
export function getDefaultCharacters() {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return process.platform === 'darwin'
|
|
6
|
-
? ['·', '✢', '✳', '✶', '✻', '✽']
|
|
7
|
-
: ['·', '✢', '*', '✶', '✻', '✽'];
|
|
2
|
+
// Unified, clean spinner glyphs across OS/terminals.
|
|
3
|
+
// Keep symbols simple to avoid odd fallback rendering.
|
|
4
|
+
return ['.', 'o', 'O', 'o'];
|
|
8
5
|
}
|
|
9
6
|
// Interpolate between two RGB colors
|
|
10
7
|
export function interpolateColor(color1, color2, t) {
|