@guildai/cli 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-CRMO5O3N.js +29 -0
- package/dist/auth-CRMO5O3N.js.map +7 -0
- package/dist/chat-5VX2WJH2.js +303 -0
- package/dist/chat-5VX2WJH2.js.map +7 -0
- package/dist/chat-SIKDYZQK.js +31 -0
- package/dist/chat-SIKDYZQK.js.map +7 -0
- package/dist/chunk-56YCMGL3.js +522 -0
- package/dist/chunk-56YCMGL3.js.map +7 -0
- package/dist/chunk-6EX6E7WP.js +7042 -0
- package/dist/chunk-6EX6E7WP.js.map +7 -0
- package/dist/chunk-B7VAF5UG.js +532 -0
- package/dist/chunk-B7VAF5UG.js.map +7 -0
- package/dist/chunk-DOIYVBNY.js +3057 -0
- package/dist/chunk-DOIYVBNY.js.map +7 -0
- package/dist/chunk-ENKEEJ45.js +17 -0
- package/dist/chunk-ENKEEJ45.js.map +7 -0
- package/dist/chunk-IBRKVGMZ.js +97041 -0
- package/dist/chunk-IBRKVGMZ.js.map +7 -0
- package/dist/chunk-LFMQJOKC.js +19778 -0
- package/dist/chunk-LFMQJOKC.js.map +7 -0
- package/dist/chunk-M347HP6M.js +22896 -0
- package/dist/chunk-M347HP6M.js.map +7 -0
- package/dist/chunk-OYQ476FQ.js +44 -0
- package/dist/chunk-OYQ476FQ.js.map +7 -0
- package/dist/chunk-PNCUR4OB.js +257 -0
- package/dist/chunk-PNCUR4OB.js.map +7 -0
- package/dist/chunk-RIG2HZWM.js +317 -0
- package/dist/chunk-RIG2HZWM.js.map +7 -0
- package/dist/chunk-SPZPZXUN.js +826 -0
- package/dist/chunk-SPZPZXUN.js.map +7 -0
- package/dist/chunk-VVSOU6ON.js +53 -0
- package/dist/chunk-VVSOU6ON.js.map +7 -0
- package/dist/chunk-X3ADGWOF.js +3643 -0
- package/dist/chunk-X3ADGWOF.js.map +7 -0
- package/dist/commands/agent/logs.d.ts +3 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/skill/create.d.ts +3 -0
- package/dist/commands/skill/get.d.ts +3 -0
- package/dist/commands/skill/list.d.ts +3 -0
- package/dist/commands/skill/update.d.ts +3 -0
- package/dist/commands/skill/version/create.d.ts +3 -0
- package/dist/commands/skill/version/get.d.ts +3 -0
- package/dist/commands/skill/version/list.d.ts +3 -0
- package/dist/devtools-AO7YSDOD.js +67 -0
- package/dist/devtools-AO7YSDOD.js.map +7 -0
- package/dist/dist-4CBK6X5H.js +1566 -0
- package/dist/dist-4CBK6X5H.js.map +7 -0
- package/dist/esm-FRAVZP4J.js +13 -0
- package/dist/esm-FRAVZP4J.js.map +7 -0
- package/dist/execa-XQMWSABC.js +35 -0
- package/dist/execa-XQMWSABC.js.map +7 -0
- package/dist/index.js +8231 -253
- package/dist/index.js.map +7 -0
- package/dist/lib/api-types.d.ts +44 -0
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/output-mode.d.ts +9 -2
- package/dist/lib/output.d.ts +17 -1
- package/dist/lib/session-events.d.ts +14 -3
- package/dist/lib/session-polling.d.ts +24 -1
- package/dist/lib/session-resume.d.ts +15 -1
- package/dist/lib/stdin.d.ts +5 -1
- package/dist/lib/websocket-client.d.ts +46 -0
- package/dist/open-RF4X5MOP.js +13 -0
- package/dist/open-RF4X5MOP.js.map +7 -0
- package/dist/server-JYVH64FD.js +27659 -0
- package/dist/server-JYVH64FD.js.map +7 -0
- package/dist/test-SNIYRJ32.js +692 -0
- package/dist/test-SNIYRJ32.js.map +7 -0
- package/docs/skills/codex-agent-dev.md +2 -2
- package/package.json +8 -12
- package/dist/commands/agent/chat.js +0 -278
- package/dist/commands/agent/clone.js +0 -116
- package/dist/commands/agent/code.js +0 -87
- package/dist/commands/agent/fork.js +0 -218
- package/dist/commands/agent/get.js +0 -37
- package/dist/commands/agent/grep.js +0 -107
- package/dist/commands/agent/init.js +0 -390
- package/dist/commands/agent/list.js +0 -110
- package/dist/commands/agent/owners.js +0 -74
- package/dist/commands/agent/publish.js +0 -91
- package/dist/commands/agent/pull.js +0 -198
- package/dist/commands/agent/revalidate.js +0 -56
- package/dist/commands/agent/save.js +0 -346
- package/dist/commands/agent/search.js +0 -61
- package/dist/commands/agent/tags/add.js +0 -73
- package/dist/commands/agent/tags/list.js +0 -43
- package/dist/commands/agent/tags/remove.js +0 -84
- package/dist/commands/agent/tags/set.js +0 -71
- package/dist/commands/agent/test.js +0 -486
- package/dist/commands/agent/unpublish.js +0 -64
- package/dist/commands/agent/update.js +0 -110
- package/dist/commands/agent/versions.js +0 -55
- package/dist/commands/agent/workspaces.js +0 -54
- package/dist/commands/auth/login.js +0 -33
- package/dist/commands/auth/logout.js +0 -24
- package/dist/commands/auth/status.js +0 -38
- package/dist/commands/auth/token.js +0 -19
- package/dist/commands/chat.js +0 -1345
- package/dist/commands/config/get.js +0 -64
- package/dist/commands/config/list.js +0 -47
- package/dist/commands/config/path.js +0 -38
- package/dist/commands/config/set.js +0 -132
- package/dist/commands/credentials/endpoint-list.js +0 -88
- package/dist/commands/credentials/list.js +0 -50
- package/dist/commands/credentials/policy-create.js +0 -66
- package/dist/commands/credentials/policy-delete.js +0 -33
- package/dist/commands/credentials/policy-list.js +0 -45
- package/dist/commands/credentials/policy-update.js +0 -66
- package/dist/commands/doctor.js +0 -233
- package/dist/commands/integration/connect.js +0 -76
- package/dist/commands/integration/create.js +0 -298
- package/dist/commands/integration/get.js +0 -95
- package/dist/commands/integration/list.js +0 -62
- package/dist/commands/integration/operation/create.js +0 -164
- package/dist/commands/integration/operation/list.js +0 -92
- package/dist/commands/integration/update.js +0 -139
- package/dist/commands/integration/version/build.js +0 -86
- package/dist/commands/integration/version/create.js +0 -45
- package/dist/commands/integration/version/get.js +0 -72
- package/dist/commands/integration/version/list.js +0 -45
- package/dist/commands/integration/version/publish.js +0 -79
- package/dist/commands/integration/version/test.js +0 -104
- package/dist/commands/job/get-step.js +0 -40
- package/dist/commands/job/get.js +0 -44
- package/dist/commands/mcp.js +0 -34
- package/dist/commands/session/create.js +0 -59
- package/dist/commands/session/events.js +0 -56
- package/dist/commands/session/get.js +0 -33
- package/dist/commands/session/interrupt.js +0 -33
- package/dist/commands/session/list.js +0 -59
- package/dist/commands/session/send.js +0 -54
- package/dist/commands/session/tasks.js +0 -45
- package/dist/commands/setup.js +0 -230
- package/dist/commands/trigger/activate.js +0 -41
- package/dist/commands/trigger/create.js +0 -197
- package/dist/commands/trigger/deactivate.js +0 -41
- package/dist/commands/trigger/get.js +0 -33
- package/dist/commands/trigger/list.js +0 -57
- package/dist/commands/trigger/sessions.js +0 -48
- package/dist/commands/trigger/update.js +0 -128
- package/dist/commands/version.js +0 -24
- package/dist/commands/workspace/agent/add.js +0 -114
- package/dist/commands/workspace/agent/list.js +0 -78
- package/dist/commands/workspace/agent/remove.js +0 -78
- package/dist/commands/workspace/clear.js +0 -45
- package/dist/commands/workspace/context/edit.js +0 -107
- package/dist/commands/workspace/context/get.js +0 -47
- package/dist/commands/workspace/context/list.js +0 -51
- package/dist/commands/workspace/context/publish.js +0 -42
- package/dist/commands/workspace/create.js +0 -51
- package/dist/commands/workspace/current.js +0 -63
- package/dist/commands/workspace/get.js +0 -39
- package/dist/commands/workspace/list.js +0 -70
- package/dist/commands/workspace/select.js +0 -184
- package/dist/components/AgentInstallPrompt.js +0 -97
- package/dist/components/SplashAnimation.js +0 -321
- package/dist/components/TaskView.js +0 -268
- package/dist/lib/agent-helpers.js +0 -306
- package/dist/lib/alternate-screen.js +0 -59
- package/dist/lib/api-client.js +0 -154
- package/dist/lib/api-types.js +0 -10
- package/dist/lib/auth.js +0 -284
- package/dist/lib/braille-canvas.js +0 -321
- package/dist/lib/colors.js +0 -46
- package/dist/lib/config-cache.js +0 -45
- package/dist/lib/config.js +0 -153
- package/dist/lib/did-you-mean.js +0 -144
- package/dist/lib/errors.js +0 -375
- package/dist/lib/event-filter.js +0 -91
- package/dist/lib/generated-types.js +0 -56
- package/dist/lib/git.js +0 -176
- package/dist/lib/gk.js +0 -91
- package/dist/lib/guild-config.js +0 -178
- package/dist/lib/iap.js +0 -117
- package/dist/lib/integration-helpers.js +0 -38
- package/dist/lib/loading-messages.js +0 -72
- package/dist/lib/logo.js +0 -141
- package/dist/lib/lottie-serverside.js +0 -181
- package/dist/lib/markdown.js +0 -38
- package/dist/lib/npmrc.js +0 -59
- package/dist/lib/output-mode.js +0 -33
- package/dist/lib/output.js +0 -591
- package/dist/lib/owner-helpers.js +0 -112
- package/dist/lib/polling.js +0 -76
- package/dist/lib/progress.js +0 -324
- package/dist/lib/session-events-fetch.js +0 -25
- package/dist/lib/session-events.js +0 -112
- package/dist/lib/session-polling.js +0 -160
- package/dist/lib/session-resume.js +0 -96
- package/dist/lib/spinners.js +0 -770
- package/dist/lib/splash.js +0 -41
- package/dist/lib/stdin.js +0 -84
- package/dist/lib/svg-to-braille.js +0 -76
- package/dist/lib/table.js +0 -59
- package/dist/lib/update-check.js +0 -65
- package/dist/lib/validate-input-schema.js +0 -208
- package/dist/lib/version-helpers.js +0 -121
- package/dist/lib/workspace-helpers.js +0 -49
- package/dist/mcp/resources.js +0 -67
- package/dist/mcp/server.js +0 -64
- package/dist/mcp/tools.js +0 -753
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import React, { useState } from 'react';
|
|
4
|
-
import { Box, Text, useInput } from 'ink';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
// Brand color for Guild
|
|
7
|
-
const brand = (text) => chalk.hex('#F97316')(text);
|
|
8
|
-
/**
|
|
9
|
-
* AgentInstallPrompt - Interactive prompt for agent installation requests
|
|
10
|
-
*
|
|
11
|
-
* Shows agent info and prompts user to approve or decline installation.
|
|
12
|
-
*/
|
|
13
|
-
export function AgentInstallPrompt({ event, onApprove, onDecline, onComplete, }) {
|
|
14
|
-
const [state, setState] = useState('waiting');
|
|
15
|
-
const [errorMessage, setErrorMessage] = useState('');
|
|
16
|
-
useInput((input, key) => {
|
|
17
|
-
if (state !== 'waiting')
|
|
18
|
-
return;
|
|
19
|
-
const lowerInput = input.toLowerCase();
|
|
20
|
-
if (lowerInput === 'y' || key.return) {
|
|
21
|
-
// Approve
|
|
22
|
-
setState('approving');
|
|
23
|
-
onApprove()
|
|
24
|
-
.then(() => {
|
|
25
|
-
setState('approved');
|
|
26
|
-
setTimeout(onComplete, 500);
|
|
27
|
-
})
|
|
28
|
-
.catch((err) => {
|
|
29
|
-
setState('error');
|
|
30
|
-
setErrorMessage(err.message);
|
|
31
|
-
setTimeout(onComplete, 2000);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
else if (lowerInput === 'n' || key.escape) {
|
|
35
|
-
// Decline
|
|
36
|
-
setState('declining');
|
|
37
|
-
onDecline()
|
|
38
|
-
.then(() => {
|
|
39
|
-
setState('declined');
|
|
40
|
-
setTimeout(onComplete, 500);
|
|
41
|
-
})
|
|
42
|
-
.catch((err) => {
|
|
43
|
-
setState('error');
|
|
44
|
-
setErrorMessage(err.message);
|
|
45
|
-
setTimeout(onComplete, 2000);
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
const agent = event.requested_agent;
|
|
50
|
-
// Render based on state
|
|
51
|
-
if (state === 'approved') {
|
|
52
|
-
return (React.createElement(Box, { marginY: 1 },
|
|
53
|
-
React.createElement(Text, { color: "green" },
|
|
54
|
-
" Agent \"",
|
|
55
|
-
agent.name,
|
|
56
|
-
"\" has been installed")));
|
|
57
|
-
}
|
|
58
|
-
if (state === 'declined') {
|
|
59
|
-
return (React.createElement(Box, { marginY: 1 },
|
|
60
|
-
React.createElement(Text, { dimColor: true }, " Agent installation skipped")));
|
|
61
|
-
}
|
|
62
|
-
if (state === 'error') {
|
|
63
|
-
return (React.createElement(Box, { marginY: 1 },
|
|
64
|
-
React.createElement(Text, { color: "red" },
|
|
65
|
-
" Error: ",
|
|
66
|
-
errorMessage)));
|
|
67
|
-
}
|
|
68
|
-
if (state === 'approving') {
|
|
69
|
-
return (React.createElement(Box, { marginY: 1 },
|
|
70
|
-
React.createElement(Text, { dimColor: true }, " Installing agent...")));
|
|
71
|
-
}
|
|
72
|
-
if (state === 'declining') {
|
|
73
|
-
return (React.createElement(Box, { marginY: 1 },
|
|
74
|
-
React.createElement(Text, { dimColor: true }, " Skipping...")));
|
|
75
|
-
}
|
|
76
|
-
// Waiting state - show prompt
|
|
77
|
-
return (React.createElement(Box, { flexDirection: "column", marginY: 1 },
|
|
78
|
-
React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1 },
|
|
79
|
-
React.createElement(Text, { bold: true, color: "yellow" }, "Agent Installation Request"),
|
|
80
|
-
React.createElement(Text, null, " "),
|
|
81
|
-
React.createElement(Text, null, "The assistant found an agent that could help with your request:"),
|
|
82
|
-
React.createElement(Text, null, " "),
|
|
83
|
-
React.createElement(Box, { paddingLeft: 2, flexDirection: "column" },
|
|
84
|
-
React.createElement(Text, null,
|
|
85
|
-
React.createElement(Text, { bold: true }, "Name:"),
|
|
86
|
-
" ",
|
|
87
|
-
brand(agent.name)),
|
|
88
|
-
React.createElement(Text, null,
|
|
89
|
-
React.createElement(Text, { bold: true }, "Description:"),
|
|
90
|
-
" ",
|
|
91
|
-
agent.description)),
|
|
92
|
-
React.createElement(Text, null, " "),
|
|
93
|
-
React.createElement(Text, null,
|
|
94
|
-
"Install this agent? ",
|
|
95
|
-
React.createElement(Text, { dimColor: true }, "[Y/n]")))));
|
|
96
|
-
}
|
|
97
|
-
//# sourceMappingURL=AgentInstallPrompt.js.map
|
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
4
|
-
import { Box, Text, useStdout, useInput } from 'ink';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { getRandomMessage, LOADING_TIMINGS } from '../lib/loading-messages.js';
|
|
7
|
-
import { renderLottieFrameToBraille, } from '../lib/lottie-serverside.js';
|
|
8
|
-
import * as fs from 'fs';
|
|
9
|
-
import * as path from 'path';
|
|
10
|
-
import { fileURLToPath } from 'url';
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = path.dirname(__filename);
|
|
13
|
-
// Frame rate tuning
|
|
14
|
-
const FRAME_INTERVAL = 33; // ~30fps
|
|
15
|
-
const FADE_INTERVAL = 16; // ~60fps
|
|
16
|
-
// Star/particle characters with varying brightness
|
|
17
|
-
const STAR_CHARS = ['·', '✦', '✧', '⋆', '∗', '˖'];
|
|
18
|
-
// Guild orange palette (matching www TetrisBlocksBackground)
|
|
19
|
-
const GUILD_ORANGE_COLORS = [
|
|
20
|
-
{ r: 255, g: 85, b: 0 }, // #FF5500 - Primary
|
|
21
|
-
{ r: 255, g: 132, b: 64 }, // #FF8440
|
|
22
|
-
{ r: 255, g: 179, b: 128 }, // #FFB380
|
|
23
|
-
{ r: 255, g: 204, b: 170 }, // #FFCCAA
|
|
24
|
-
];
|
|
25
|
-
/**
|
|
26
|
-
* Animated full-screen splash animation for Guild CLI
|
|
27
|
-
* Features:
|
|
28
|
-
* - SVG logo rendered to braille with fade-in effect
|
|
29
|
-
* - Particle/starfield background with twinkling
|
|
30
|
-
* - Rotating loading messages
|
|
31
|
-
* - Full screen centered layout
|
|
32
|
-
*/
|
|
33
|
-
export function SplashAnimation({ status, onComplete, onEscapePress, version, isFinalizing = false, }) {
|
|
34
|
-
const { stdout } = useStdout();
|
|
35
|
-
// Track terminal size with resize handler
|
|
36
|
-
const [terminalSize, setTerminalSize] = useState({
|
|
37
|
-
width: stdout?.columns || 80,
|
|
38
|
-
height: stdout?.rows || 24,
|
|
39
|
-
});
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
const handleResize = () => {
|
|
42
|
-
setTerminalSize({
|
|
43
|
-
width: process.stdout.columns || 80,
|
|
44
|
-
height: process.stdout.rows || 24,
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
process.stdout.on('resize', handleResize);
|
|
48
|
-
return () => {
|
|
49
|
-
process.stdout.off('resize', handleResize);
|
|
50
|
-
};
|
|
51
|
-
}, []);
|
|
52
|
-
const width = terminalSize.width;
|
|
53
|
-
const height = terminalSize.height;
|
|
54
|
-
// All hooks must be called before any conditional returns
|
|
55
|
-
const [tick, setTick] = useState(0);
|
|
56
|
-
const [message, setMessage] = useState(getRandomMessage());
|
|
57
|
-
const [messageOpacity, setMessageOpacity] = useState(0);
|
|
58
|
-
const [particles, setParticles] = useState([]);
|
|
59
|
-
const [currentFrame, setCurrentFrame] = useState(0);
|
|
60
|
-
const [animationData, setAnimationData] = useState(null);
|
|
61
|
-
const [totalFrames, setTotalFrames] = useState(0);
|
|
62
|
-
const [renderedFrame, setRenderedFrame] = useState(null);
|
|
63
|
-
const lastRenderedFrame = useRef(-1); // Track which frame was rendered (ref to avoid state churn)
|
|
64
|
-
const renderingFrame = useRef(-1); // Track which frame is currently being rendered
|
|
65
|
-
const lastDimensions = useRef({ width: 0, height: 0 }); // Track dimensions for resize detection
|
|
66
|
-
const startTime = useRef(Date.now());
|
|
67
|
-
const messageStartTime = useRef(Date.now());
|
|
68
|
-
// Reset frame rendering when terminal dimensions change (for resize support)
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (lastDimensions.current.width !== width ||
|
|
71
|
-
lastDimensions.current.height !== height) {
|
|
72
|
-
lastDimensions.current = { width, height };
|
|
73
|
-
// Force re-render of current frame at new dimensions
|
|
74
|
-
lastRenderedFrame.current = -1;
|
|
75
|
-
renderingFrame.current = -1;
|
|
76
|
-
setRenderedFrame(null);
|
|
77
|
-
}
|
|
78
|
-
}, [width, height]);
|
|
79
|
-
// Handle Esc key or Ctrl-C to exit splash screen early
|
|
80
|
-
useInput((input, key) => {
|
|
81
|
-
if (key.escape && onEscapePress) {
|
|
82
|
-
onEscapePress();
|
|
83
|
-
}
|
|
84
|
-
// Ctrl-C should exit the CLI entirely
|
|
85
|
-
if (input === 'c' && key.ctrl) {
|
|
86
|
-
process.exit(0);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
// Calculate logo dimensions - use full terminal space
|
|
90
|
-
const logoWidthChars = width;
|
|
91
|
-
const logoHeightChars = height;
|
|
92
|
-
const centerX = 0;
|
|
93
|
-
const centerY = 0;
|
|
94
|
-
// Load Lottie animation data (for real-time rendering)
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
const possiblePaths = [
|
|
97
|
-
path.resolve(__dirname, '../assets/logo-animation.json'),
|
|
98
|
-
path.resolve(__dirname, '../../src/assets/logo-animation.json'),
|
|
99
|
-
];
|
|
100
|
-
let loadedData = null;
|
|
101
|
-
for (const animPath of possiblePaths) {
|
|
102
|
-
if (fs.existsSync(animPath)) {
|
|
103
|
-
const content = fs.readFileSync(animPath, 'utf-8');
|
|
104
|
-
loadedData = JSON.parse(content);
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (loadedData) {
|
|
109
|
-
setAnimationData(loadedData);
|
|
110
|
-
setTotalFrames(Math.floor(loadedData.op || 0));
|
|
111
|
-
// Reset start time so animation begins from frame 0 after loading
|
|
112
|
-
startTime.current = Date.now();
|
|
113
|
-
}
|
|
114
|
-
}, []);
|
|
115
|
-
// Update current frame - sequential for intro, time-based after
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
if (totalFrames === 0)
|
|
118
|
-
return;
|
|
119
|
-
const maxFrame = Math.floor(totalFrames * 0.9);
|
|
120
|
-
// For first 45 frames (1.5 sec of intro), use sequential advancement
|
|
121
|
-
// This ensures the intro animation plays smoothly without skipping
|
|
122
|
-
// After that, allow time-based advancement to catch up if needed
|
|
123
|
-
const introFrames = 45;
|
|
124
|
-
const useSequential = lastRenderedFrame.current < introFrames;
|
|
125
|
-
let targetFrame;
|
|
126
|
-
if (useSequential) {
|
|
127
|
-
// Sequential: advance as soon as previous frame has rendered
|
|
128
|
-
if (lastRenderedFrame.current >= currentFrame) {
|
|
129
|
-
targetFrame = currentFrame + 1;
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
targetFrame = currentFrame; // Hold until render completes
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
// Time-based: follow the clock after intro
|
|
137
|
-
const elapsed = Date.now() - startTime.current;
|
|
138
|
-
const fps = 30;
|
|
139
|
-
const frameNumber = Math.floor((elapsed / 1000) * fps);
|
|
140
|
-
targetFrame = Math.min(frameNumber, lastRenderedFrame.current + 1);
|
|
141
|
-
}
|
|
142
|
-
targetFrame = Math.min(targetFrame, maxFrame);
|
|
143
|
-
if (targetFrame >= maxFrame) {
|
|
144
|
-
// Animation complete
|
|
145
|
-
setCurrentFrame(maxFrame);
|
|
146
|
-
if (onComplete) {
|
|
147
|
-
onComplete();
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
else if (targetFrame !== currentFrame) {
|
|
151
|
-
setCurrentFrame(targetFrame);
|
|
152
|
-
}
|
|
153
|
-
}, [tick, totalFrames, onComplete, currentFrame]);
|
|
154
|
-
// Render the current frame asynchronously
|
|
155
|
-
useEffect(() => {
|
|
156
|
-
if (!animationData || currentFrame >= totalFrames)
|
|
157
|
-
return;
|
|
158
|
-
// Don't re-render a frame we've already rendered or are currently rendering
|
|
159
|
-
if (currentFrame <= lastRenderedFrame.current ||
|
|
160
|
-
currentFrame === renderingFrame.current) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
// Mark this frame as being rendered
|
|
164
|
-
const frameToRender = currentFrame;
|
|
165
|
-
renderingFrame.current = frameToRender;
|
|
166
|
-
let cancelled = false;
|
|
167
|
-
renderLottieFrameToBraille(animationData, frameToRender, logoWidthChars, logoHeightChars)
|
|
168
|
-
.then((lines) => {
|
|
169
|
-
if (!cancelled && frameToRender > lastRenderedFrame.current) {
|
|
170
|
-
setRenderedFrame(lines);
|
|
171
|
-
lastRenderedFrame.current = frameToRender;
|
|
172
|
-
}
|
|
173
|
-
})
|
|
174
|
-
.catch((error) => {
|
|
175
|
-
console.error('Error rendering Lottie frame:', error);
|
|
176
|
-
});
|
|
177
|
-
return () => {
|
|
178
|
-
cancelled = true;
|
|
179
|
-
};
|
|
180
|
-
}, [animationData, currentFrame, totalFrames, logoWidthChars, logoHeightChars]);
|
|
181
|
-
// Initialize particles for starfield background
|
|
182
|
-
useEffect(() => {
|
|
183
|
-
const newParticles = [];
|
|
184
|
-
const particleCount = Math.floor((width * height) / 100);
|
|
185
|
-
for (let i = 0; i < particleCount; i++) {
|
|
186
|
-
newParticles.push({
|
|
187
|
-
x: Math.random() * width,
|
|
188
|
-
y: Math.random() * height,
|
|
189
|
-
char: STAR_CHARS[Math.floor(Math.random() * STAR_CHARS.length)],
|
|
190
|
-
opacity: 0.1 + Math.random() * 0.4,
|
|
191
|
-
twinkleSpeed: 0.5 + Math.random() * 1.5,
|
|
192
|
-
twinklePhase: Math.random() * Math.PI * 2,
|
|
193
|
-
colorIndex: Math.floor(Math.random() * GUILD_ORANGE_COLORS.length),
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
setParticles(newParticles);
|
|
197
|
-
}, [width, height]);
|
|
198
|
-
// Animation loop for particle updates
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
const interval = setInterval(() => {
|
|
201
|
-
setTick((t) => t + 1);
|
|
202
|
-
}, FRAME_INTERVAL);
|
|
203
|
-
return () => clearInterval(interval);
|
|
204
|
-
}, []);
|
|
205
|
-
// Animate loading message opacity (fade in/out)
|
|
206
|
-
useEffect(() => {
|
|
207
|
-
// Start with fade in
|
|
208
|
-
messageStartTime.current = Date.now();
|
|
209
|
-
const interval = setInterval(() => {
|
|
210
|
-
const elapsed = Date.now() - messageStartTime.current;
|
|
211
|
-
const cycleTime = LOADING_TIMINGS.messageRotation;
|
|
212
|
-
const fadeTime = LOADING_TIMINGS.messageFade;
|
|
213
|
-
const position = elapsed % cycleTime;
|
|
214
|
-
if (position < fadeTime) {
|
|
215
|
-
// Fade in
|
|
216
|
-
setMessageOpacity(position / fadeTime);
|
|
217
|
-
}
|
|
218
|
-
else if (position < cycleTime - fadeTime) {
|
|
219
|
-
// Hold at full opacity
|
|
220
|
-
setMessageOpacity(1);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
// Fade out
|
|
224
|
-
const fadeOutProgress = (position - (cycleTime - fadeTime)) / fadeTime;
|
|
225
|
-
setMessageOpacity(1 - fadeOutProgress);
|
|
226
|
-
}
|
|
227
|
-
}, FADE_INTERVAL);
|
|
228
|
-
return () => clearInterval(interval);
|
|
229
|
-
}, []);
|
|
230
|
-
// Rotate loading messages
|
|
231
|
-
useEffect(() => {
|
|
232
|
-
const interval = setInterval(() => {
|
|
233
|
-
setMessage(getRandomMessage());
|
|
234
|
-
messageStartTime.current = Date.now();
|
|
235
|
-
setMessageOpacity(0);
|
|
236
|
-
}, LOADING_TIMINGS.messageRotation);
|
|
237
|
-
return () => clearInterval(interval);
|
|
238
|
-
}, []);
|
|
239
|
-
// Render particles with twinkling effect
|
|
240
|
-
const renderParticles = useCallback(() => {
|
|
241
|
-
const chars = Array(height)
|
|
242
|
-
.fill(null)
|
|
243
|
-
.map(() => Array(width).fill(' '));
|
|
244
|
-
particles.forEach((p) => {
|
|
245
|
-
const x = Math.floor(p.x);
|
|
246
|
-
const y = Math.floor(p.y);
|
|
247
|
-
if (x >= 0 && x < width && y >= 0 && y < height) {
|
|
248
|
-
// Twinkle effect
|
|
249
|
-
const twinkle = Math.sin(tick * 0.1 * p.twinkleSpeed + p.twinklePhase) * 0.5 + 0.5;
|
|
250
|
-
const brightness = p.opacity * (0.3 + twinkle * 0.7);
|
|
251
|
-
// Edge fade (vignette effect)
|
|
252
|
-
const distFromCenterX = Math.abs(x - width / 2) / (width / 2);
|
|
253
|
-
const distFromCenterY = Math.abs(y - height / 2) / (height / 2);
|
|
254
|
-
const distFromCenter = Math.sqrt(distFromCenterX * distFromCenterX + distFromCenterY * distFromCenterY);
|
|
255
|
-
const edgeFade = Math.max(0, 1 - distFromCenter * 0.8);
|
|
256
|
-
const finalBrightness = brightness * edgeFade;
|
|
257
|
-
if (finalBrightness > 0.1) {
|
|
258
|
-
// Use Guild orange colors instead of grayscale
|
|
259
|
-
const color = GUILD_ORANGE_COLORS[p.colorIndex];
|
|
260
|
-
const r = Math.floor(color.r * finalBrightness);
|
|
261
|
-
const g = Math.floor(color.g * finalBrightness);
|
|
262
|
-
const b = Math.floor(color.b * finalBrightness);
|
|
263
|
-
chars[y][x] = chalk.rgb(r, g, b)(p.char);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
return chars;
|
|
268
|
-
}, [particles, tick, width, height]);
|
|
269
|
-
// Render the Lottie frame (uses pre-rendered frame from state)
|
|
270
|
-
const renderLogo = useCallback((chars) => {
|
|
271
|
-
// Don't render until we have a rendered frame
|
|
272
|
-
if (!renderedFrame)
|
|
273
|
-
return;
|
|
274
|
-
renderedFrame.forEach((line, row) => {
|
|
275
|
-
const y = centerY + row;
|
|
276
|
-
if (y >= 0 && y < height) {
|
|
277
|
-
[...line].forEach((char, col) => {
|
|
278
|
-
const x = centerX + col;
|
|
279
|
-
if (x >= 0 && x < width && char !== '⠀') {
|
|
280
|
-
// Use default terminal text color for compatibility with all themes
|
|
281
|
-
chars[y][x] = char;
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
});
|
|
286
|
-
}, [centerX, centerY, width, height, renderedFrame]);
|
|
287
|
-
// Build the frame
|
|
288
|
-
const chars = renderParticles();
|
|
289
|
-
renderLogo(chars);
|
|
290
|
-
// Convert to lines
|
|
291
|
-
const lines = chars.map((row) => row.join(''));
|
|
292
|
-
// Message positions
|
|
293
|
-
// Rotating messages: below logo (about 75% down the screen)
|
|
294
|
-
// Status ticker: near the bottom
|
|
295
|
-
const loadingMessageY = Math.floor(height * 0.68);
|
|
296
|
-
const statusY = height - 2;
|
|
297
|
-
// Apply opacity for fade effect
|
|
298
|
-
// Use a range that works on both light and dark terminals
|
|
299
|
-
const applyOpacity = (text, opacity) => {
|
|
300
|
-
// Map opacity 0-1 to grayscale range 150-255 for better visibility on dark backgrounds
|
|
301
|
-
const minBrightness = 150;
|
|
302
|
-
const maxBrightness = 255;
|
|
303
|
-
const gray = Math.floor(minBrightness + opacity * (maxBrightness - minBrightness));
|
|
304
|
-
return chalk.rgb(gray, gray, gray)(text);
|
|
305
|
-
};
|
|
306
|
-
// When finalizing, show final frame with version text (no status line)
|
|
307
|
-
if (isFinalizing) {
|
|
308
|
-
const versionText = version ? `Guild CLI v${version}` : 'Guild CLI';
|
|
309
|
-
return (React.createElement(Box, { flexDirection: "column", width: width, height: height },
|
|
310
|
-
lines.map((line, i) => (React.createElement(Text, { key: i }, line))),
|
|
311
|
-
React.createElement(Box, { position: "absolute", marginTop: loadingMessageY, width: width, justifyContent: "center" },
|
|
312
|
-
React.createElement(Text, null, chalk.bold(versionText)))));
|
|
313
|
-
}
|
|
314
|
-
return (React.createElement(Box, { flexDirection: "column", width: width, height: height },
|
|
315
|
-
lines.map((line, i) => (React.createElement(Text, { key: i }, line))),
|
|
316
|
-
React.createElement(Box, { position: "absolute", marginTop: statusY, width: width, justifyContent: "center" },
|
|
317
|
-
React.createElement(Text, null, chalk.dim(status))),
|
|
318
|
-
React.createElement(Box, { position: "absolute", marginTop: loadingMessageY, width: width, justifyContent: "center" },
|
|
319
|
-
React.createElement(Text, null, applyOpacity(message, messageOpacity)))));
|
|
320
|
-
}
|
|
321
|
-
//# sourceMappingURL=SplashAnimation.js.map
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import React, { useState, useEffect } from 'react';
|
|
4
|
-
import { Box, Text, useInput } from 'ink';
|
|
5
|
-
import { getTaskDisplayName, isFilteredTaskName, } from '../lib/session-events.js';
|
|
6
|
-
// Status colors (matching web: bg-status-* Tailwind classes)
|
|
7
|
-
const STATUS_COLORS = {
|
|
8
|
-
CREATED: '#6b7280', // gray (pending)
|
|
9
|
-
STARTED: '#6b7280', // gray (pending)
|
|
10
|
-
RUNNING: '#3b82f6', // blue (info)
|
|
11
|
-
WAITING: '#b8860b', // dark goldenrod (readable on light and dark terminals)
|
|
12
|
-
DONE: '#22c55e', // green (success)
|
|
13
|
-
ERROR: '#ef4444', // red (error)
|
|
14
|
-
INTERRUPTED: '#b8860b', // dark goldenrod (warning)
|
|
15
|
-
};
|
|
16
|
-
// Status icons (for completed/static states)
|
|
17
|
-
const STATUS_ICONS = {
|
|
18
|
-
CREATED: '○',
|
|
19
|
-
STARTED: '○',
|
|
20
|
-
RUNNING: '●',
|
|
21
|
-
WAITING: '◐',
|
|
22
|
-
DONE: '✓',
|
|
23
|
-
ERROR: '✗',
|
|
24
|
-
INTERRUPTED: '⊘',
|
|
25
|
-
};
|
|
26
|
-
// Animation frames for running tasks (alternates between empty and filled)
|
|
27
|
-
const RUNNING_ANIMATION_FRAMES = ['○', '●'];
|
|
28
|
-
const RUNNING_ANIMATION_INTERVAL_MS = 1000; // Toggle every 1s
|
|
29
|
-
// Show this many completed tasks before collapsing the rest
|
|
30
|
-
const VISIBLE_COMPLETED_COUNT = 5;
|
|
31
|
-
/**
|
|
32
|
-
* Get status color for a task
|
|
33
|
-
*/
|
|
34
|
-
export function getStatusColor(status) {
|
|
35
|
-
return STATUS_COLORS[status] || STATUS_COLORS.CREATED;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Get status icon for a task
|
|
39
|
-
*/
|
|
40
|
-
export function getStatusIcon(status) {
|
|
41
|
-
return STATUS_ICONS[status] || STATUS_ICONS.CREATED;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Check if a task status is "active" (not completed)
|
|
45
|
-
*/
|
|
46
|
-
function isActiveStatus(status) {
|
|
47
|
-
return (status === 'CREATED' ||
|
|
48
|
-
status === 'STARTED' ||
|
|
49
|
-
status === 'RUNNING' ||
|
|
50
|
-
status === 'WAITING');
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Check if a task is completed (done or error)
|
|
54
|
-
*/
|
|
55
|
-
function isCompletedStatus(status) {
|
|
56
|
-
return status === 'DONE' || status === 'ERROR';
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Format task duration in compact form
|
|
60
|
-
* For completed tasks: duration from created_at to updated_at
|
|
61
|
-
* For active tasks: elapsed time since created_at
|
|
62
|
-
* Returns empty string for very short durations (<5s)
|
|
63
|
-
*/
|
|
64
|
-
function formatTaskDuration(task) {
|
|
65
|
-
const createdAt = new Date(task.created_at);
|
|
66
|
-
const endTime = isActiveStatus(task.status) ? new Date() : new Date(task.updated_at);
|
|
67
|
-
const diffMs = endTime.getTime() - createdAt.getTime();
|
|
68
|
-
const diffSec = Math.floor(diffMs / 1000);
|
|
69
|
-
const diffMin = Math.floor(diffSec / 60);
|
|
70
|
-
const diffHr = Math.floor(diffMin / 60);
|
|
71
|
-
if (diffSec < 5)
|
|
72
|
-
return '';
|
|
73
|
-
if (diffSec < 60)
|
|
74
|
-
return `${diffSec}s`;
|
|
75
|
-
if (diffMin < 60)
|
|
76
|
-
return `${diffMin}m`;
|
|
77
|
-
if (diffHr < 24)
|
|
78
|
-
return `${diffHr}h`;
|
|
79
|
-
return createdAt.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Calculate depth for each task based on parent chain
|
|
83
|
-
* Returns a Map of task ID -> depth (0 for root tasks)
|
|
84
|
-
*/
|
|
85
|
-
function calculateTaskDepths(tasks) {
|
|
86
|
-
const depthMap = new Map();
|
|
87
|
-
const taskMap = new Map(tasks.map((t) => [t.id, t]));
|
|
88
|
-
function getDepth(taskId) {
|
|
89
|
-
if (depthMap.has(taskId))
|
|
90
|
-
return depthMap.get(taskId) ?? 0;
|
|
91
|
-
const task = taskMap.get(taskId);
|
|
92
|
-
const parentId = task?.parent_task?.id;
|
|
93
|
-
if (!parentId) {
|
|
94
|
-
depthMap.set(taskId, 0);
|
|
95
|
-
return 0;
|
|
96
|
-
}
|
|
97
|
-
const parentDepth = getDepth(parentId);
|
|
98
|
-
const depth = parentDepth + 1;
|
|
99
|
-
depthMap.set(taskId, depth);
|
|
100
|
-
return depth;
|
|
101
|
-
}
|
|
102
|
-
tasks.forEach((t) => getDepth(t.id));
|
|
103
|
-
return depthMap;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* TaskView - Hierarchical task tree display (matching web SessionDetailsSidebar)
|
|
107
|
-
*
|
|
108
|
-
* Shows tasks in a tree format with colored status dots:
|
|
109
|
-
* ● assistant 19s
|
|
110
|
-
* └ ✓ coding 15s
|
|
111
|
-
*
|
|
112
|
-
* Features:
|
|
113
|
-
* - Tree prefixes (└) for child tasks
|
|
114
|
-
* - Colored status dots (gray=pending, blue=running, yellow=waiting, green=done, red=error)
|
|
115
|
-
* - Animated icons for running tasks (alternates between ○ and ●)
|
|
116
|
-
* - Duration display (elapsed for active, final for completed)
|
|
117
|
-
* - Collapsible completed tasks (Ctrl+O to expand/collapse)
|
|
118
|
-
*/
|
|
119
|
-
export function TaskView({ tasks }) {
|
|
120
|
-
// Animation state for running tasks
|
|
121
|
-
const [animationFrame, setAnimationFrame] = useState(0);
|
|
122
|
-
// Expanded state for completed tasks
|
|
123
|
-
const [expanded, setExpanded] = useState(false);
|
|
124
|
-
// Handle Ctrl+O to toggle expand/collapse
|
|
125
|
-
useInput((input, key) => {
|
|
126
|
-
if (input === 'o' && key.ctrl) {
|
|
127
|
-
setExpanded((e) => !e);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
// Check if we have any running tasks that need animation
|
|
131
|
-
const hasRunningTasks = tasks.some((t) => t.status === 'RUNNING' || t.status === 'STARTED');
|
|
132
|
-
// Animate running task icons
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
if (!hasRunningTasks)
|
|
135
|
-
return;
|
|
136
|
-
const interval = setInterval(() => {
|
|
137
|
-
setAnimationFrame((f) => (f + 1) % RUNNING_ANIMATION_FRAMES.length);
|
|
138
|
-
}, RUNNING_ANIMATION_INTERVAL_MS);
|
|
139
|
-
return () => clearInterval(interval);
|
|
140
|
-
}, [hasRunningTasks]);
|
|
141
|
-
if (tasks.length === 0)
|
|
142
|
-
return null;
|
|
143
|
-
// Filter out internal tasks (ui_prompt, etc.)
|
|
144
|
-
const filteredTasks = tasks.filter((task) => {
|
|
145
|
-
const name = getTaskDisplayName(task);
|
|
146
|
-
return !isFilteredTaskName(name);
|
|
147
|
-
});
|
|
148
|
-
if (filteredTasks.length === 0)
|
|
149
|
-
return null;
|
|
150
|
-
// Sort by created_at (chronological order like web)
|
|
151
|
-
const sortedTasks = [...filteredTasks].sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
152
|
-
// Calculate depth for each task
|
|
153
|
-
const depthMap = calculateTaskDepths(sortedTasks);
|
|
154
|
-
// Build display items (collapsing completed tasks when not expanded)
|
|
155
|
-
const displayItems = [];
|
|
156
|
-
if (expanded) {
|
|
157
|
-
// Show all tasks when expanded
|
|
158
|
-
sortedTasks.forEach((task) => {
|
|
159
|
-
displayItems.push({ type: 'task', task, depth: depthMap.get(task.id) || 0 });
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
// Group tasks by parent and collapse completed ones
|
|
164
|
-
const tasksByParent = new Map();
|
|
165
|
-
sortedTasks.forEach((task) => {
|
|
166
|
-
const parentId = task.parent_task?.id || null;
|
|
167
|
-
if (!tasksByParent.has(parentId)) {
|
|
168
|
-
tasksByParent.set(parentId, []);
|
|
169
|
-
}
|
|
170
|
-
tasksByParent.get(parentId)?.push(task);
|
|
171
|
-
});
|
|
172
|
-
// Process root tasks first, then children
|
|
173
|
-
const processedIds = new Set();
|
|
174
|
-
const processTasksAtLevel = (parentId) => {
|
|
175
|
-
const tasksAtLevel = tasksByParent.get(parentId) || [];
|
|
176
|
-
// Separate active and completed tasks
|
|
177
|
-
const activeTasks = tasksAtLevel.filter((t) => !isCompletedStatus(t.status));
|
|
178
|
-
const completedTasks = tasksAtLevel.filter((t) => isCompletedStatus(t.status));
|
|
179
|
-
// Always show active tasks
|
|
180
|
-
activeTasks.forEach((task) => {
|
|
181
|
-
if (!processedIds.has(task.id)) {
|
|
182
|
-
processedIds.add(task.id);
|
|
183
|
-
displayItems.push({ type: 'task', task, depth: depthMap.get(task.id) || 0 });
|
|
184
|
-
// Process children of this task
|
|
185
|
-
processTasksAtLevel(task.id);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
// For completed tasks: show first N, then collapse the rest
|
|
189
|
-
const visibleCompleted = completedTasks.slice(0, VISIBLE_COMPLETED_COUNT);
|
|
190
|
-
const hiddenCompleted = completedTasks.slice(VISIBLE_COMPLETED_COUNT);
|
|
191
|
-
// Show visible completed tasks
|
|
192
|
-
visibleCompleted.forEach((task) => {
|
|
193
|
-
if (!processedIds.has(task.id)) {
|
|
194
|
-
processedIds.add(task.id);
|
|
195
|
-
displayItems.push({
|
|
196
|
-
type: 'task',
|
|
197
|
-
task,
|
|
198
|
-
depth: depthMap.get(task.id) || 0,
|
|
199
|
-
});
|
|
200
|
-
// Process children of this task
|
|
201
|
-
processTasksAtLevel(task.id);
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
// Show collapsed summary for hidden tasks
|
|
205
|
-
if (hiddenCompleted.length > 0) {
|
|
206
|
-
const depth = hiddenCompleted[0] ? depthMap.get(hiddenCompleted[0].id) || 0 : 1;
|
|
207
|
-
displayItems.push({ type: 'collapsed', count: hiddenCompleted.length, depth });
|
|
208
|
-
hiddenCompleted.forEach((t) => processedIds.add(t.id));
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
processTasksAtLevel(null);
|
|
212
|
-
}
|
|
213
|
-
// Count total collapsed tasks for the hint
|
|
214
|
-
const totalCompletedTasks = sortedTasks.filter((t) => isCompletedStatus(t.status)).length;
|
|
215
|
-
const hasCollapsedTasks = totalCompletedTasks > VISIBLE_COMPLETED_COUNT;
|
|
216
|
-
return (React.createElement(Box, { flexDirection: "column" },
|
|
217
|
-
displayItems.map((item, index) => {
|
|
218
|
-
if (item.type === 'collapsed') {
|
|
219
|
-
const indent = ' '.repeat(item.depth);
|
|
220
|
-
const treeChar = item.depth > 0 ? '└ ' : '';
|
|
221
|
-
return (React.createElement(Box, { key: `collapsed-${index}` },
|
|
222
|
-
React.createElement(Text, { dimColor: true },
|
|
223
|
-
indent,
|
|
224
|
-
treeChar,
|
|
225
|
-
"\u2026 +",
|
|
226
|
-
item.count,
|
|
227
|
-
" more",
|
|
228
|
-
' '),
|
|
229
|
-
React.createElement(Text, { dimColor: true }, "(ctrl+o to expand)")));
|
|
230
|
-
}
|
|
231
|
-
const task = item.task;
|
|
232
|
-
const name = getTaskDisplayName(task);
|
|
233
|
-
const status = task.status;
|
|
234
|
-
const statusColor = STATUS_COLORS[status] || STATUS_COLORS.CREATED;
|
|
235
|
-
const depth = item.depth;
|
|
236
|
-
const duration = formatTaskDuration(task);
|
|
237
|
-
// Animate running/started tasks, static icon for others
|
|
238
|
-
const icon = status === 'RUNNING' || status === 'STARTED'
|
|
239
|
-
? RUNNING_ANIMATION_FRAMES[animationFrame]
|
|
240
|
-
: STATUS_ICONS[status];
|
|
241
|
-
// Tree structure: indent based on depth, show └ for children
|
|
242
|
-
const indent = ' '.repeat(depth);
|
|
243
|
-
const treeChar = depth > 0 ? '└ ' : '';
|
|
244
|
-
// Hide duration for root tasks (depth 0) - they run for entire session
|
|
245
|
-
const showDuration = depth > 0 && duration;
|
|
246
|
-
return (React.createElement(Box, { key: task.id },
|
|
247
|
-
React.createElement(Text, { dimColor: true },
|
|
248
|
-
indent,
|
|
249
|
-
treeChar),
|
|
250
|
-
React.createElement(Text, { color: statusColor }, icon),
|
|
251
|
-
React.createElement(Text, null,
|
|
252
|
-
" ",
|
|
253
|
-
name),
|
|
254
|
-
showDuration && React.createElement(Text, { dimColor: true },
|
|
255
|
-
" (",
|
|
256
|
-
duration,
|
|
257
|
-
")")));
|
|
258
|
-
}),
|
|
259
|
-
expanded && hasCollapsedTasks && (React.createElement(Box, null,
|
|
260
|
-
React.createElement(Text, { dimColor: true }, " (ctrl+o to collapse)")))));
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Check if any task is active (not completed)
|
|
264
|
-
*/
|
|
265
|
-
export function hasActiveTasks(tasks) {
|
|
266
|
-
return tasks.some((t) => isActiveStatus(t.status));
|
|
267
|
-
}
|
|
268
|
-
//# sourceMappingURL=TaskView.js.map
|